X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=client%2Fclient.c;h=4cf2207707d68d04a3b60d72f75e7919f01acadf;hp=e41c9f6eba48f8248822b8bd5347d8e10fe05a14;hb=db073edc9e7834e7f71f1fa9f76866aeb29e0421;hpb=aca4eb82b50d781d4ab636cfc15412a2aca3e903 diff --git a/client/client.c b/client/client.c index e41c9f6..4cf2207 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-2011 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 @@ -80,7 +81,6 @@ static file_history_t file_history = 0; -static char webservice_type[10]; static char sru_method[10] = "soap"; static char sru_version[10] = "1.2"; static char *codeset = 0; /* character set for output */ @@ -107,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 @@ -146,6 +147,8 @@ 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, QueryType_CCL, @@ -281,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; } @@ -760,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) @@ -847,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; @@ -906,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)) { @@ -1283,6 +1307,11 @@ static int send_srw_host_path(Z_SRW_PDU *sr, const char *host_port, { 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); } @@ -1410,43 +1439,6 @@ static int send_SRW_scanRequest(const char *arg, int pos, int num) return send_srw(sr); } -static void encode_SOLR_search(Z_HTTP_Request *hreq, ODR encode, - const char *query) -{ - char *path; - const char *name[10], *value[10]; - char *uri_args; - - name[0] = "q"; - value[0] = query; - name[1] = 0; - - yaz_array_to_uri(&uri_args, encode, (char **) name, (char **) value); - - path = (char *) - odr_malloc(encode, strlen(hreq->path) + strlen(uri_args) + 4); - - hreq->method = "GET"; - - if (strchr(hreq->path, '?')) - sprintf(path, "%s&%s", hreq->path, uri_args); - else - sprintf(path, "%s?%s", hreq->path, uri_args); - hreq->path = path; -} - -static int send_SOLR_searchRequest(const char *arg) -{ - Z_GDU *gdu; - char *path = yaz_encode_sru_dbpath_odr(out, databaseNames[0]); - - gdu = z_get_HTTP_Request_host_path(out, cur_host, path); - - encode_SOLR_search(gdu->u.HTTP_Request, out, arg); - - return send_gdu(gdu); -} - static int send_SRW_searchRequest(const char *arg) { Z_SRW_PDU *sr = 0; @@ -1488,7 +1480,7 @@ static int send_SRW_searchRequest(const char *arg) 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")) @@ -1669,16 +1661,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; } } @@ -1718,6 +1710,7 @@ static void display_facet(Z_FacetField *facet) 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); } @@ -2837,9 +2830,7 @@ static int cmd_sru(const char *arg) } else { - int r; - strcpy(webservice_type, "sru"); - 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")) @@ -2848,40 +2839,19 @@ static int cmd_sru(const char *arg) ; 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"); } } } return 0; } -static int cmd_webservice(const char *arg) -{ - if (!*arg) - { - printf("Webservice: %s\n", webservice_type); - } - else - { - if (!strcmp(arg, "sru")) - ; - else if (!strcmp(arg, "solr")) - ; - else - { - printf("Unknown webservice type\n"); - return 0; - } - strcpy(webservice_type, arg); - } - return 0; -} - - static int cmd_find(const char *arg) { if (!*arg) @@ -2896,16 +2866,8 @@ static int cmd_find(const char *arg) session_connect(cur_host); if (!conn) return 0; - if (!strcmp(webservice_type, "solr")) - { - if (!send_SOLR_searchRequest(arg)) - return 0; - } - else - { - if (!send_SRW_searchRequest(arg)) - return 0; - } + if (!send_SRW_searchRequest(arg)) + return 0; #else return 0; #endif @@ -2951,36 +2913,25 @@ static int cmd_find(const char *arg) 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()) @@ -3039,21 +2990,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'; + + 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) @@ -3061,7 +3041,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 != '+') { @@ -3078,7 +3058,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 != '+') { @@ -4283,8 +4263,6 @@ static void initialize(const char *rc_file) exit(1); } - strcpy(webservice_type, "sru"); - setvbuf(stdout, 0, _IONBF, 0); if (apdu_file) odr_setprint(print, apdu_file); @@ -4338,7 +4316,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 @@ -4371,6 +4349,8 @@ 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) + display_facets(res->facetList); for (i = 0; inum_records; i++) handle_srw_record(res->records + i); } @@ -4417,97 +4397,11 @@ static void handle_srw_scan_response(Z_SRW_scanResponse *res) handle_srw_scan_term(res->terms + i); } -static int decode_SOLR_response(const char *content_buf, int content_len) -{ - xmlDocPtr doc = xmlParseMemory(content_buf, content_len); - int ret = 0; - xmlNodePtr ptr = 0; - Odr_int hits = 0; - Odr_int start = 0; - - if (!doc) - { - ret = -1; - } - if (doc) - { - xmlNodePtr root = xmlDocGetRootElement(doc); - if (!root) - { - ret = -1; - } - else if (strcmp((const char *) root->name, "response")) - { - ret = -1; - } - else - { - /** look for result node */ - for (ptr = root->children; ptr; ptr = ptr->next) - { - if (ptr->type == XML_ELEMENT_NODE && - !strcmp((const char *) ptr->name, "result")) - break; - } - if (!ptr) - { - ret = -1; - } - } - } - if (ptr) - { /* got result node */ - struct _xmlAttr *attr; - for (attr = ptr->properties; attr; attr = attr->next) - if (attr->children && attr->children->type == XML_TEXT_NODE) - { - if (!strcmp((const char *) attr->name, "numFound")) - { - hits = odr_atoi((const char *) attr->children->content); - } - else if (!strcmp((const char *) attr->name, "start")) - { - start = odr_atoi((const char *) attr->children->content); - } - } - printf("Number of hits: " ODR_INT_PRINTF "\n", hits); - } - if (ptr) - { - xmlNodePtr node; - int offset = 0; - - for (node = ptr->children; node; node = node->next) - { - if (node->type == XML_ELEMENT_NODE) - { - xmlBufferPtr buf = xmlBufferCreate(); - xmlNode *tmp = xmlCopyNode(node, 1); - - printf(ODR_INT_PRINTF "\n", start + offset); - - xmlNodeDump(buf, tmp->doc, tmp, 0, 0); - - xmlFreeNode(tmp); - - fwrite(buf->content, 1, buf->use, stdout); - xmlBufferFree(buf); - offset++; - printf("\n"); - } - } - } - if (doc) - xmlFreeDoc(doc); - return ret; -} - static void http_response(Z_HTTP_Response *hres) { 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); @@ -4515,57 +4409,71 @@ static void http_response(Z_HTTP_Response *hres) if (!yaz_srw_check_content_type(hres)) printf("Content type does not appear to be XML\n"); - else if (!strcmp(webservice_type, "solr")) - { - decode_SOLR_response(hres->content_buf, hres->content_len); - } - else if (!strcmp(webservice_type, "sru")) - { - 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) + else + { + 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 */ @@ -5111,7 +5019,6 @@ static struct { {"init", cmd_init, "", NULL,0,NULL}, {"sru", cmd_sru, " ", NULL,0,NULL}, {"url", cmd_url, "", NULL,0,NULL}, - {"webservice", cmd_webservice, "", NULL,0,NULL}, {"exit", cmd_quit, "",NULL,0,NULL}, {0,0,0,0,0,0} }; @@ -5246,7 +5153,7 @@ static void process_cmd_line(char* line) for (; *p; ++p) { - if (!isspace(*(unsigned char *) p)) + if (!yaz_isspace(*p)) lastnonspace = p; } if (lastnonspace)