X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=client%2Fclient.c;h=a55f095bd7aa775bb17b5539de7f8c62eb2a668b;hp=ba217e7e9d0db49015824131277a3a3a5423c7f7;hb=191c5db0e914f9774413da50bb1963ecf22b2f5c;hpb=1c0ca5448add3823add4ba4993da0864e2d3657a diff --git a/client/client.c b/client/client.c index ba217e7..a55f095 100644 --- a/client/client.c +++ b/client/client.c @@ -1,16 +1,18 @@ /* This file is part of the YAZ toolkit. - * Copyright (C) 1995-2010 Index Data + * Copyright (C) 1995-2013 Index Data * See the file LICENSE for details. */ /** \file client.c * \brief yaz-client program */ +#if HAVE_CONFIG_H +#include +#endif #include #include #include #include -#include #ifndef WIN32 #include #endif @@ -46,7 +48,6 @@ #include #include -#define NO_OID 1 #include #include #include @@ -106,6 +107,7 @@ static int largeSetLowerBound = 1; 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 @@ -123,7 +125,7 @@ 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 kilobytes = 64 * 1024; static char *negotiationCharset = 0; static int negotiationCharsetRecords = 1; static int negotiationCharsetVersion = 3; @@ -140,10 +142,12 @@ 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 Odr_int last_hit_count = 0; +static int pretty_xml = 0; +static Odr_int sru_maximumRecords = 0; typedef enum { QueryType_Prefix, @@ -280,11 +284,10 @@ int send_apdu(Z_APDU *a) 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; } @@ -759,10 +762,6 @@ static int cmd_open(const char *arg) 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) @@ -846,6 +845,31 @@ static void print_record(const char *buf, size_t len) 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; @@ -905,7 +929,8 @@ static void display_record(Z_External *r) || !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)) { @@ -1388,7 +1413,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; @@ -1409,7 +1434,7 @@ static int send_SRW_scanRequest(const char *arg, int pos, int num) 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); } @@ -1454,6 +1479,7 @@ static int send_SRW_searchRequest(const char *arg) printf("Only CQL and PQF supported in SRW\n"); return 0; } + sru_maximumRecords = 0; sr->u.request->maximumRecords = odr_intdup(out, 0); sr->u.request->facetList = facet_list; if (record_schema) @@ -1503,7 +1529,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 */ @@ -1636,16 +1662,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; } } @@ -1672,19 +1698,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); } @@ -2103,6 +2126,7 @@ 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; @@ -2280,22 +2304,6 @@ static int only_z3950(void) return 0; } -static int is_SRW(void) -{ - if (!conn) - { - printf("Not connected yet\n"); - return 1; - } - if (protocol == PROTO_HTTP && yaz_matchstr(sru_method, "solr")) - { - printf("Not supported by SRW\n"); - return 1; - } - return 0; -} - - static int cmd_update_common(const char *arg, int version); static int cmd_update(const char *arg) @@ -2367,9 +2375,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 @@ -2903,21 +2911,17 @@ static int cmd_find(const char *arg) static int cmd_facets(const char *arg) { - /* TODO Wrong odr. Loosing memory */ - ODR odr = odr_createmem(ODR_ENCODE); - 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 (is_SRW()) { - printf("WARN: No supported for SRW/SRU.\n"); - } - facet_list = yaz_pqf_parse_facet_list(odr, arg); - + facet_list = yaz_pqf_parse_facet_list(facet_odr, arg); if (!facet_list) { printf("Invalid facet list: %s", arg); @@ -2926,7 +2930,6 @@ static int cmd_facets(const char *arg) return 1; } - static int cmd_delete(const char *arg) { if (only_z3950()) @@ -2985,21 +2988,50 @@ static int cmd_setnames(const char *arg) /* 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'; - if (!strcmp(arg_c, "all")) + token_len = check_token(arg_c, "format"); + if (token_len) + { + pretty_xml = 1; + arg_c += token_len; + } + else + pretty_xml = 0; + + 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) @@ -3007,7 +3039,7 @@ static int parse_show_args(const char *arg_c, char *setstring, *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 != '+') { @@ -3024,7 +3056,7 @@ static int parse_show_args(const char *arg_c, char *setstring, } if (*end_ptr == '\0') return 1; - while (isspace(*(unsigned char *)end_ptr)) + while (yaz_isspace(*end_ptr)) end_ptr++; if (*end_ptr != '+') { @@ -3140,6 +3172,7 @@ static int send_SRW_presentRequest(const char *arg) if (!parse_show_args(arg, setstring, &setno, &nos)) return 0; 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; @@ -3248,10 +3281,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 && @@ -3264,7 +3297,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")) @@ -3287,13 +3320,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; @@ -3363,7 +3397,7 @@ static int send_Z3950_scanrequest(const char *set, const char *query, 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) @@ -3538,9 +3572,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; } @@ -3554,6 +3596,28 @@ 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 @@ -3561,16 +3625,8 @@ static int cmd_scan_common(const char *set, const char *arg) 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; @@ -3591,19 +3647,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; } } @@ -4035,7 +4081,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 @@ -4228,7 +4274,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); @@ -4282,7 +4330,7 @@ static void handle_srw_record(Z_SRW_record *rec) 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 @@ -4315,11 +4363,21 @@ static void handle_srw_response(Z_SRW_searchRetrieveResponse *res) } if (res->numberOfRecords) printf("Number of hits: " ODR_INT_PRINTF "\n", *res->numberOfRecords); - if (res->facetList) { + 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); + } } static void handle_srw_scan_term(Z_SRW_scanTerm *term) @@ -4386,9 +4444,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); @@ -4397,9 +4457,10 @@ 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_response, 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}, {0, 0, 0} }; ret = z_soap_codec(o, &soap_package, @@ -4889,7 +4950,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 ) @@ -5120,7 +5181,7 @@ static void process_cmd_line(char* line) for (; *p; ++p) { - if (!isspace(*(unsigned char *) p)) + if (!yaz_isspace(*p)) lastnonspace = p; } if (lastnonspace)