X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=client%2Fclient.c;h=3f79e7a6638464766a2acf2dd3b32e4a2c700aa3;hp=fa55c321754f5b579513eaac835e6add0259a20b;hb=9021ba4aa6fcdbdd177073d44edd03a86d70198f;hpb=3236c79e8d4287738236a804fe887ce4094fc9e9 diff --git a/client/client.c b/client/client.c index fa55c32..3f79e7a 100644 --- a/client/client.c +++ b/client/client.c @@ -1,5 +1,5 @@ /* This file is part of the YAZ toolkit. - * Copyright (C) 1995-2011 Index Data + * Copyright (C) Index Data * See the file LICENSE for details. */ /** \file client.c @@ -44,7 +44,7 @@ #endif #include - +#include #include #include @@ -64,6 +64,7 @@ #include #include #include +#include #if HAVE_READLINE_READLINE_H #include @@ -83,6 +84,7 @@ static file_history_t file_history = 0; static char sru_method[10] = "soap"; static char sru_version[10] = "1.2"; +static char sru_recordPacking[10] = ""; static char *codeset = 0; /* character set for output */ static int hex_dump = 0; static char *dump_file_prefix = 0; @@ -102,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; @@ -125,7 +127,8 @@ static char ccl_fields[512] = "default.bib"; 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 int proxy_mode = 0; +static int kilobytes = 64 * 1024; static char *negotiationCharset = 0; static int negotiationCharsetRecords = 1; static int negotiationCharsetVersion = 3; @@ -142,12 +145,13 @@ static int auto_wait = 1; 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 WRBUF cur_host = 0; 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, @@ -252,9 +256,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) @@ -317,14 +324,9 @@ static void print_refid(Z_ReferenceId *id) static Z_ReferenceId *set_refid(ODR out) { - Z_ReferenceId *id; if (!refid) return 0; - id = (Z_ReferenceId *) odr_malloc(out, sizeof(*id)); - id->size = id->len = strlen(refid); - id->buf = (unsigned char *) odr_malloc(out, id->len); - memcpy(id->buf, refid, id->len); - return id; + return odr_create_Odr_oct(out, refid, strlen(refid)); } /* INIT SERVICE ------------------------------- */ @@ -348,7 +350,7 @@ static void send_Z3950_initRequest(const char* type_and_host) req->referenceId = set_refid(out); - if (yazProxy && type_and_host) + if (proxy_mode && type_and_host) { yaz_oi_set_string_oid(&req->otherInfo, out, yaz_oid_userinfo_proxy, 1, type_and_host); @@ -544,7 +546,7 @@ static void render_diag(Z_DiagnosticFormat *diag) Z_DefaultDiagFormat *dd = ds->u.defaultDiagRec; /* ### should check `dd->diagnosticSetId' */ printf("code=" ODR_INT_PRINTF " (%s)", *dd->condition, - diagbib1_str(*dd->condition)); + diagbib1_str((int) *dd->condition)); /* Both types of addinfo are the same, so use type-pun */ if (dd->u.v2Addinfo != 0) printf(",\n\taddinfo='%s'", dd->u.v2Addinfo); @@ -702,10 +704,7 @@ static int session_connect_base(const char *arg, const char **basep) strncpy(type_and_host, arg, sizeof(type_and_host)-1); type_and_host[sizeof(type_and_host)-1] = '\0'; - if (yazProxy) - conn = cs_create_host(yazProxy, 1, &add); - else - conn = cs_create_host(arg, 1, &add); + conn = cs_create_host2(arg, 1, &add, yazProxy, &proxy_mode); if (!conn) { printf("Could not resolve address %s\n", arg); @@ -741,12 +740,15 @@ static int session_connect_base(const char *arg, const char **basep) return 0; } -static int session_connect(const char *arg) +static int session_connect(void) { int r; const char *basep = 0; - r = session_connect_base(arg, &basep); + yaz_cookies_destroy(yaz_cookies); + yaz_cookies = yaz_cookies_create(); + + r = session_connect_base(wrbuf_cstr(cur_host), &basep); if (basep && *basep) set_base(basep); else if (protocol == PROTO_Z3950) @@ -759,15 +761,16 @@ static int cmd_open(const char *arg) int r; if (arg) { - strncpy(cur_host, arg, sizeof(cur_host)-1); - cur_host[sizeof(cur_host)-1] = 0; + wrbuf_rewind(cur_host); + if (!strstr(arg, "://") && strcmp(sru_method, "soap")) + wrbuf_puts(cur_host, "http://"); + wrbuf_puts(cur_host, arg); } set_base(""); - r = session_connect(cur_host); + r = session_connect(); if (conn && conn->protocol == PROTO_HTTP) queryType = QueryType_CQL; - return r; } @@ -845,6 +848,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,13 +973,16 @@ static void display_record(Z_External *r) const char *octet_buf = (const char*)r->u.octet_aligned->buf; size_t octet_len = r->u.octet_aligned->len; if (!oid_oidcmp(oid, yaz_oid_recsyn_xml) - || !oid_oidcmp(oid, yaz_oid_recsyn_xml) + || !oid_oidcmp(oid, yaz_oid_recsyn_application_xml) || !oid_oidcmp(oid, yaz_oid_recsyn_html)) { print_xml_record(octet_buf, octet_len); - } - else if (yaz_oid_is_iso2709(oid)) + else if (!oid_oidcmp(oid, yaz_oid_recsyn_mab)) + { + print_mab_record(octet_buf, octet_len); + } + else { const char *result; size_t rlen; @@ -978,17 +1028,14 @@ static void display_record(Z_External *r) } else { - printf("bad MARC. Dumping as it is:\n"); + if (yaz_oid_is_iso2709(oid)) + printf("bad MARC. Dumping as it is:\n"); print_record(octet_buf, octet_len); } yaz_marc_destroy(mt); if (cd) yaz_iconv_close(cd); } - else - { - print_record(octet_buf, octet_len); - } marc_file_write(octet_buf, r->u.octet_aligned->len); } else if (oid && !oid_oidcmp(oid, yaz_oid_recsyn_sutrs)) @@ -1157,7 +1204,7 @@ static void display_diagrecs(Z_DiagRec **pp, int num) printf("Unknown diagset: %s\n", diag_name); } printf(" [" ODR_INT_PRINTF "] %s", - *r->condition, diagbib1_str(*r->condition)); + *r->condition, diagbib1_str((int) *r->condition)); switch (r->which) { case Z_DefaultDiagFormat_v2Addinfo: @@ -1274,7 +1321,7 @@ static int send_srw_host_path(Z_SRW_PDU *sr, const char *host_port, const char *charset = negotiationCharset; Z_GDU *gdu; - gdu = z_get_HTTP_Request_host_path(out, host_port, path); + gdu = z_get_HTTP_Request_uri(out, host_port, path, proxy_mode); if (auth) { @@ -1317,47 +1364,20 @@ static int send_srw_host_path(Z_SRW_PDU *sr, const char *host_port, static int send_srw(Z_SRW_PDU *sr) { - char *path = yaz_encode_sru_dbpath_odr(out, databaseNames[0]); - return send_srw_host_path(sr, cur_host, path); + return send_srw_host_path(sr, wrbuf_cstr(cur_host), databaseNames[0]); } -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) @@ -1413,7 +1433,7 @@ static char *encode_SRW_term(ODR o, const char *q) } -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; @@ -1423,18 +1443,18 @@ static int send_SRW_scanRequest(const char *arg, int pos, int num) switch (queryType) { case QueryType_CQL: - sr->u.scan_request->query_type = Z_SRW_query_type_cql; - sr->u.scan_request->scanClause.cql = encode_SRW_term(out, arg); + sr->u.scan_request->queryType = "cql"; + sr->u.scan_request->scanClause = encode_SRW_term(out, arg); break; case QueryType_Prefix: - sr->u.scan_request->query_type = Z_SRW_query_type_pqf; - sr->u.scan_request->scanClause.pqf = encode_SRW_term(out, arg); + sr->u.scan_request->queryType = "pqf"; + sr->u.scan_request->scanClause = encode_SRW_term(out, arg); break; default: 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); } @@ -1462,27 +1482,29 @@ static int send_SRW_searchRequest(const char *arg) switch (queryType) { case QueryType_CQL: - srw_sr->u.request->query_type = Z_SRW_query_type_cql; - srw_sr->u.request->query.cql = encode_SRW_term(srw_sr_odr_out, arg); + srw_sr->u.request->queryType = "cql"; + srw_sr->u.request->query = encode_SRW_term(srw_sr_odr_out, arg); - sr->u.request->query_type = Z_SRW_query_type_cql; - sr->u.request->query.cql = encode_SRW_term(srw_sr_odr_out, arg); + sr->u.request->queryType = "cql"; + sr->u.request->query = encode_SRW_term(srw_sr_odr_out, arg); break; case QueryType_Prefix: - srw_sr->u.request->query_type = Z_SRW_query_type_pqf; - srw_sr->u.request->query.pqf = encode_SRW_term(srw_sr_odr_out, arg); + srw_sr->u.request->queryType = "pqf"; + srw_sr->u.request->query = encode_SRW_term(srw_sr_odr_out, arg); - sr->u.request->query_type = Z_SRW_query_type_pqf; - sr->u.request->query.pqf = encode_SRW_term(srw_sr_odr_out, arg); + sr->u.request->queryType = "pqf"; + sr->u.request->query = encode_SRW_term(srw_sr_odr_out, arg); break; default: printf("Only CQL and PQF supported in SRW\n"); return 0; } + if (*sru_recordPacking) + sr->u.request->recordPacking = sru_recordPacking; + 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); @@ -1528,7 +1550,7 @@ static int send_Z3950_searchRequest(const char *arg) 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 */ @@ -1562,12 +1584,12 @@ static int send_Z3950_searchRequest(const char *arg) req->referenceId = set_refid(out); if (!strcmp(arg, "@big")) /* strictly for troublemaking */ { - static unsigned char big[2100]; + static char big[2100]; static Odr_oct bigo; /* send a very big referenceid to test transport stack etc. */ memset(big, 'A', 2100); - bigo.len = bigo.size = 2100; + bigo.len = 2100; bigo.buf = big; req->referenceId = &bigo; } @@ -1621,7 +1643,7 @@ static int send_Z3950_searchRequest(const char *arg) case QueryType_CCL: query.which = Z_Query_type_2; query.u.type_2 = &ccl_query; - ccl_query.buf = (unsigned char*) arg; + ccl_query.buf = (char *) arg; ccl_query.len = strlen(arg); break; case QueryType_CCL2RPN: @@ -1661,16 +1683,16 @@ static void display_term(Z_Term *term) 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; } } @@ -1697,19 +1719,16 @@ static void display_facet(Z_FacetField *facet) { Z_AttributeList *al = facet->attributes; struct yaz_facet_attr attr_values; - attr_values.errcode = 0; - attr_values.limit = -1; - attr_values.useattr = 0; - attr_values.relation = "default"; - + yaz_facet_attr_init(&attr_values); 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); } @@ -1872,7 +1891,7 @@ static void print_referenceId(int iLevel, Z_ReferenceId *referenceId) int i; print_level(iLevel); - printf("Ref Id (%d, %d): ", referenceId->len, referenceId->size); + printf("Ref Id (%d): ", referenceId->len); for (i = 0; i < referenceId->len; i++) printf("%c", referenceId->buf[i]); printf("\n"); @@ -2128,21 +2147,14 @@ static Z_External *create_external_itemRequest(void) } else { + item_request_buf = odr_getbuf (out, &item_request_size, 0); r = (Z_External *) odr_malloc(out, sizeof(*r)); r->direct_reference = odr_oiddup(out, yaz_oid_general_isoill_1); r->indirect_reference = 0; r->descriptor = 0; r->which = Z_External_single; - - r->u.single_ASN1_type = (Odr_oct *) - odr_malloc(out, sizeof(*r->u.single_ASN1_type)); - r->u.single_ASN1_type->buf = (unsigned char *) - odr_malloc(out, item_request_size); - r->u.single_ASN1_type->len = item_request_size; - r->u.single_ASN1_type->size = item_request_size; - memcpy(r->u.single_ASN1_type->buf, item_request_buf, - item_request_size); - + r->u.single_ASN1_type = + odr_create_Odr_oct(out, item_request_buf, item_request_size); do_hex_dump(item_request_buf,item_request_size); } return r; @@ -2186,18 +2198,8 @@ static Z_External *create_external_ILL_APDU(void) r->indirect_reference = 0; r->descriptor = 0; r->which = Z_External_single; - - r->u.single_ASN1_type = (Odr_oct *) - odr_malloc(out, sizeof(*r->u.single_ASN1_type)); - r->u.single_ASN1_type->buf = (unsigned char *) - odr_malloc(out, ill_request_size); - r->u.single_ASN1_type->len = ill_request_size; - r->u.single_ASN1_type->size = ill_request_size; - memcpy(r->u.single_ASN1_type->buf, ill_request_buf, ill_request_size); -/* printf("len = %d\n", ill_request_size); */ -/* do_hex_dump(ill_request_buf,ill_request_size); */ -/* printf("--- end of extenal\n"); */ - + r->u.single_ASN1_type = odr_create_Odr_oct(out, ill_request_buf, + ill_request_size); } return r; } @@ -2376,9 +2378,9 @@ static int cmd_update_common(const char *arg, int version) #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 @@ -2386,7 +2388,7 @@ static int send_SRW_update(int action_no, const char *recid, char *rec_buf, int rec_len) { if (!conn) - session_connect(cur_host); + session_connect(); if (!conn) return 0; else @@ -2486,16 +2488,8 @@ static int send_Z3950_update(int version, int action_no, const char *recid, notToKeep->elements[0] = (Z_IU0SuppliedRecords_elem *) odr_malloc(out, sizeof(**notToKeep->elements)); notToKeep->elements[0]->which = Z_IUSuppliedRecords_elem_opaque; - if (recid) - { - notToKeep->elements[0]->u.opaque = (Odr_oct *) - odr_malloc(out, sizeof(Odr_oct)); - notToKeep->elements[0]->u.opaque->buf = (unsigned char *) recid; - notToKeep->elements[0]->u.opaque->size = strlen(recid); - notToKeep->elements[0]->u.opaque->len = strlen(recid); - } - else - notToKeep->elements[0]->u.opaque = 0; + notToKeep->elements[0]->u.opaque = recid ? + odr_create_Odr_oct(out, recid, strlen(recid)) : 0; notToKeep->elements[0]->supplementalId = 0; notToKeep->elements[0]->correlationInfo = 0; notToKeep->elements[0]->record = record_this; @@ -2533,16 +2527,8 @@ static int send_Z3950_update(int version, int action_no, const char *recid, notToKeep->elements[0] = (Z_IUSuppliedRecords_elem *) odr_malloc(out, sizeof(**notToKeep->elements)); notToKeep->elements[0]->which = Z_IUSuppliedRecords_elem_opaque; - if (recid) - { - notToKeep->elements[0]->u.opaque = (Odr_oct *) - odr_malloc(out, sizeof(Odr_oct)); - notToKeep->elements[0]->u.opaque->buf = (unsigned char *) recid; - notToKeep->elements[0]->u.opaque->size = strlen(recid); - notToKeep->elements[0]->u.opaque->len = strlen(recid); - } - else - notToKeep->elements[0]->u.opaque = 0; + notToKeep->elements[0]->u.opaque = recid ? + odr_create_Odr_oct(out, recid, strlen(recid)) : 0; notToKeep->elements[0]->supplementalId = 0; notToKeep->elements[0]->correlationInfo = 0; notToKeep->elements[0]->record = record_this; @@ -2586,7 +2572,7 @@ static int cmd_xmles(const char *arg) &ext->u.single_ASN1_type->len) == 0) return 0; - ext->u.single_ASN1_type->buf = (unsigned char *) asn_buf; + ext->u.single_ASN1_type->buf = asn_buf; oid = yaz_string_to_oid_odr(yaz_oid_std(), CLASS_EXTSERV, oid_str, out); @@ -2664,7 +2650,7 @@ static int cmd_explain(const char *arg) return 0; #if YAZ_HAVE_XML2 if (!conn) - session_connect(cur_host); + session_connect(); if (conn) { Z_SRW_PDU *sr = 0; @@ -2672,7 +2658,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"; @@ -2687,12 +2673,14 @@ static int cmd_init(const char *arg) { if (*arg) { - strncpy(cur_host, arg, sizeof(cur_host)-1); - cur_host[sizeof(cur_host)-1] = 0; + wrbuf_rewind(cur_host); + if (!strstr(arg, "://") && strcmp(sru_method, "soap")) + wrbuf_puts(cur_host, "http://"); + wrbuf_puts(cur_host, arg); } if (only_z3950()) return 1; - send_Z3950_initRequest(cur_host); + send_Z3950_initRequest(wrbuf_cstr(cur_host)); return 2; } @@ -2829,7 +2817,8 @@ static int cmd_sru(const char *arg) } else { - int r = sscanf(arg, "%9s %9s", sru_method, sru_version); + int r = sscanf(arg, "%9s %9s %9s", sru_method, sru_version, + sru_recordPacking); if (r >= 1) { if (!yaz_matchstr(sru_method, "post")) @@ -2862,7 +2851,7 @@ static int cmd_find(const char *arg) { #if YAZ_HAVE_XML2 if (!conn) - session_connect(cur_host); + session_connect(); if (!conn) return 0; if (!send_SRW_searchRequest(arg)) @@ -2873,7 +2862,7 @@ static int cmd_find(const char *arg) } else { - if (*cur_host && auto_reconnect) + if (wrbuf_len(cur_host) && auto_reconnect) { int i = 0; for (;;) @@ -2891,7 +2880,7 @@ static int cmd_find(const char *arg) printf("Unable to reconnect\n"); break; } - session_connect(cur_host); + session_connect(); wait_and_handle_response(0); } return 0; @@ -2942,30 +2931,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; } @@ -3017,7 +3006,7 @@ static int parse_show_args(const char *arg_c, char *setstring, sprintf(setstring, "%d", setnumber); else *setstring = '\0'; - + token_len = check_token(arg_c, "format"); if (token_len) { @@ -3172,10 +3161,12 @@ static int send_SRW_presentRequest(const char *arg) return 0; if (!parse_show_args(arg, setstring, &setno, &nos)) return 0; + if (*sru_recordPacking) + sr->u.request->recordPacking = sru_recordPacking; 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); @@ -3232,7 +3223,7 @@ static int cmd_show(const char *arg) { #if YAZ_HAVE_XML2 if (!conn) - session_connect(cur_host); + session_connect(); if (!conn) return 0; if (!send_SRW_presentRequest(arg)) @@ -3256,9 +3247,15 @@ static int cmd_show(const char *arg) static void exit_client(int code) { + odr_destroy(in); + odr_destroy(out); + odr_destroy(print); + ccl_qual_rm(&bibset); + yaz_cookies_destroy(yaz_cookies); file_history_save(file_history); file_history_destroy(&file_history); nmem_destroy(nmem_auth); + wrbuf_destroy(cur_host); exit(code); } @@ -3281,10 +3278,10 @@ static int cmd_cancel(const char *arg) apdu->u.triggerResourceControlRequest; bool_t rfalse = 0; char command[16]; - + *command = '\0'; sscanf(arg, "%15s", command); - + if (only_z3950()) return 0; if (session_initResponse && @@ -3297,7 +3294,7 @@ static int cmd_cancel(const char *arg) *req->requestedAction = Z_TriggerResourceControlRequest_cancel; req->resultSetWanted = &rfalse; req->referenceId = set_refid(out); - + send_apdu(apdu); printf("Sent cancel request\n"); if (!strcmp(command, "wait")) @@ -3320,13 +3317,14 @@ static int cmd_cancel_find(const char *arg) } 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; @@ -3386,17 +3384,15 @@ static int send_Z3950_scanrequest(const char *set, const char *query, req->termListAndStartPoint->term->u.general) { req->termListAndStartPoint->term->u.general->buf = - (unsigned char *) odr_strdup(out, term); - req->termListAndStartPoint->term->u.general->len = - req->termListAndStartPoint->term->u.general->size = - strlen(term); + odr_strdup(out, term); + req->termListAndStartPoint->term->u.general->len = strlen(term); } } req->referenceId = set_refid(out); 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) @@ -3482,7 +3478,7 @@ static void process_Z3950_scanResponse(Z_ScanResponse *res) num_entries = res->entries->num_entries; for (i = 0; i < num_entries; i++) { - int pos_term = res->positionOfTerm ? *res->positionOfTerm : -1; + Odr_int pos_term = res->positionOfTerm ? *res->positionOfTerm : -1; if (entries[i]->which == Z_Entry_termInfo) { printf("%c ", i + 1 == pos_term ? '*' : ' '); @@ -3571,9 +3567,17 @@ static int cmd_scanstep(const char *arg) 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; } @@ -3587,23 +3591,37 @@ static int cmd_scansize(const char *arg) 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 if (!conn) - session_connect(cur_host); + session_connect(); 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; @@ -3611,9 +3629,9 @@ static int cmd_scan_common(const char *set, const char *arg) } else { - if (*cur_host && !conn && auto_reconnect) + if (wrbuf_len(cur_host) && !conn && auto_reconnect) { - session_connect(cur_host); + session_connect(); wait_and_handle_response(0); } if (!conn) @@ -3624,19 +3642,9 @@ static int cmd_scan_common(const char *set, const char *arg) 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; } } @@ -4068,7 +4076,7 @@ static int cmd_set_auto_reconnect(const char* arg) printf("Error use on or off\n"); return 1; } - + if (auto_reconnect) printf("Set auto reconnect enabled.\n"); else @@ -4254,6 +4262,8 @@ static void initialize(const char *rc_file) FILE *inf; int i; + cur_host = wrbuf_alloc(); + if (!(out = odr_createmem(ODR_ENCODE)) || !(in = odr_createmem(ODR_DECODE)) || !(print = odr_createmem(ODR_PRINT))) @@ -4261,7 +4271,9 @@ static void initialize(const char *rc_file) fprintf(stderr, "failed to allocate ODR streams\n"); exit(1); } - + + strcpy(scan_position, "1"); + setvbuf(stdout, 0, _IONBF, 0); if (apdu_file) odr_setprint(print, apdu_file); @@ -4306,10 +4318,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"); @@ -4350,8 +4359,20 @@ static void handle_srw_response(Z_SRW_searchRetrieveResponse *res) printf("Number of hits: " ODR_INT_PRINTF "\n", *res->numberOfRecords); if (res->facetList) display_facets(res->facetList); - for (i = 0; inum_records; i++) + if (res->suggestions) + printf("Suggestions:\n%s\n", res->suggestions); + for (i = 0; i < res->num_records; i++) + { + if (i >= sru_maximumRecords) + { + printf("SRU server returns extra records. Skipping " + ODR_INT_PRINTF " records.\n", + res->num_records - sru_maximumRecords); + break; + } handle_srw_record(res->records + i); + } + setno += res->num_records; } static void handle_srw_scan_term(Z_SRW_scanTerm *term) @@ -4418,9 +4439,11 @@ static void http_response(Z_HTTP_Response *hres) if (ret == 0 && sr->which == Z_SRW_searchRetrieve_response) handle_srw_response(sr->u.response); + else if (ret == 0 && sr->which == Z_SRW_scan_response) + handle_srw_scan_response(sr->u.scan_response); else { - printf("Decoding of SOLR package failed\n"); + printf("Decoding of Solr package failed\n"); ret = -1; } odr_destroy(o); @@ -4429,9 +4452,11 @@ static void http_response(Z_HTTP_Response *hres) { 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}, + Z_SOAP_Handler soap_handlers[] = { + {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, @@ -4494,7 +4519,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) { @@ -4516,7 +4541,7 @@ static void wait_and_handle_response(int one_response_only) { cs_close(conn); conn = 0; - session_connect(cur_host); + session_connect(); reconnect_ok = 0; if (conn) { @@ -4631,17 +4656,23 @@ 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); + int host_change = 0; + location = yaz_check_location(in, wrbuf_cstr(cur_host), + location, &host_change); + if (host_change) + 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"); @@ -4815,9 +4846,9 @@ static int cmd_list_all(const char* args) /* connection options */ if (conn) - printf("Connected to : %s\n", cur_host); - else if (*cur_host) - printf("Not connected to : %s\n", cur_host); + printf("Connected to : %s\n", wrbuf_cstr(cur_host)); + else if (cur_host && wrbuf_len(cur_host)) + printf("Not connected to : %s\n", wrbuf_cstr(cur_host)); else printf("Not connected : \n"); if (yazProxy) printf("using proxy : %s\n",yazProxy); @@ -4861,7 +4892,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) @@ -4921,7 +4954,7 @@ static int cmd_wait_response(const char *arg) { int i; int wait_for = atoi(arg); - if (wait_for < 1) + if (wait_for < 1) wait_for = 1; for (i = 0 ; i < wait_for; ++i ) @@ -5368,6 +5401,8 @@ int main(int argc, char **argv) if (codeset) outputCharset = xstrdup(codeset); + yaz_enable_panic_backtrace(prog); + ODR_MASK_SET(&z3950_options, Z_Options_search); ODR_MASK_SET(&z3950_options, Z_Options_present); ODR_MASK_SET(&z3950_options, Z_Options_namedResultSets);