X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=client%2Fclient.c;h=cacc274162d5bea10913edd4a88dc2f9affe0b9c;hp=83747073633531d02c51c53dc3c74c95405f8ec6;hb=8dc67a9430644549801c18ec7e3a725e5a4ef782;hpb=0442642bb213139271943552e5c1bc731ee96872 diff --git a/client/client.c b/client/client.c index 8374707..cacc274 100644 --- a/client/client.c +++ b/client/client.c @@ -1,8 +1,8 @@ /* - * Copyright (c) 1995-2003, Index Data + * Copyright (c) 1995-2004, Index Data * See the file LICENSE for details. * - * $Id: client.c,v 1.204 2003-07-18 22:41:25 mike Exp $ + * $Id: client.c,v 1.239 2004-04-28 12:10:51 adam Exp $ */ #include @@ -16,6 +16,14 @@ #include #endif +#if HAVE_OPENSSL_SSL_H +#include +#include +#include +#include +#include +#endif + #include #include @@ -60,6 +68,7 @@ static char *codeset = 0; /* character set for output */ static int hex_dump = 0; +static char *dump_file_prefix = 0; static ODR out, in, print; /* encoding and decoding streams */ #if HAVE_XML2 static ODR srw_sr_odr_out = 0; @@ -80,7 +89,7 @@ static Z_ElementSetNames *elementSetNames = 0; 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 char *schema = 0; +static char *record_schema = 0; static int sent_close = 0; static NMEM session_mem = NULL; /* memory handle for init-response */ static Z_InitResponse *session = 0; /* session parameters */ @@ -96,12 +105,17 @@ static char *negotiationCharset = 0; static char *outputCharset = 0; static char *marcCharset = 0; static char* yazLang = 0; +static char* http_version = "1.1"; static char last_cmd[32] = "?"; static FILE *marc_file = 0; static char *refid = NULL; static char *last_open_command = NULL; static int auto_reconnect = 0; +static Odr_bitmask z3950_options; +static int z3950_version = 3; + +static char cur_host[200]; typedef enum { QueryType_Prefix, @@ -114,7 +128,7 @@ typedef enum { static QueryType queryType = QueryType_Prefix; static CCL_bibset bibset; /* CCL bibset handle */ -static cql_transform_t cqltrans; /* CQL qualifier-set handle */ +static cql_transform_t cqltrans; /* CQL context-set handle */ #if HAVE_READLINE_COMPLETION_OVER @@ -174,6 +188,21 @@ static void do_hex_dump(const char* buf, int len) printf("\n"); } } + if (dump_file_prefix) + { + static int no = 0; + if (++no < 1000 && strlen(dump_file_prefix) < 500) + { + char fname[1024]; + FILE *of; + sprintf (fname, "%s.%03d.raw", dump_file_prefix, no); + of = fopen(fname, "wb"); + + fwrite (buf, 1, len, of); + + fclose(of); + } + } } void add_otherInfos(Z_APDU *a) @@ -212,13 +241,13 @@ int send_apdu(Z_APDU *a) 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))); close_session(); return 0; } - do_hex_dump(buf,len); odr_reset(out); /* release the APDU structure */ return 1; } @@ -261,19 +290,13 @@ static void send_initRequest(const char* type_and_host) { Z_APDU *apdu = zget_APDU(out, Z_APDU_initRequest); Z_InitRequest *req = apdu->u.initRequest; + int i; - ODR_MASK_SET(req->options, Z_Options_search); - ODR_MASK_SET(req->options, Z_Options_present); - ODR_MASK_SET(req->options, Z_Options_namedResultSets); - ODR_MASK_SET(req->options, Z_Options_triggerResourceCtrl); - ODR_MASK_SET(req->options, Z_Options_scan); - ODR_MASK_SET(req->options, Z_Options_sort); - ODR_MASK_SET(req->options, Z_Options_extendedServices); - ODR_MASK_SET(req->options, Z_Options_delSet); + req->options = &z3950_options; - ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_1); - ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_2); - ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_3); + ODR_MASK_ZERO(req->protocolVersion); + for (i = 0; iprotocolVersion, i); *req->maximumRecordSize = 1024*kilobytes; *req->preferredMessageSize = 1024*kilobytes; @@ -282,7 +305,7 @@ static void send_initRequest(const char* type_and_host) req->referenceId = set_refid (out); - if (yazProxy) + if (yazProxy && type_and_host) yaz_oi_set_string_oidval(&req->otherInfo, out, VAL_PROXY, 1, type_and_host); @@ -293,15 +316,15 @@ static void send_initRequest(const char* type_and_host) yaz_oi_APDU(apdu, &p); if ((p0=yaz_oi_update(p, out, NULL, 0, 0))) { - ODR_MASK_SET(req->options, Z_Options_negotiationModel); - - p0->which = Z_OtherInfo_externallyDefinedInfo; - p0->information.externallyDefinedInfo = - yaz_set_proposal_charneg( - out, - (const char**)&negotiationCharset, - negotiationCharset ? 1 : 0, - (const char**)&yazLang, yazLang ? 1 : 0, 1); + ODR_MASK_SET(req->options, Z_Options_negotiationModel); + + p0->which = Z_OtherInfo_externallyDefinedInfo; + p0->information.externallyDefinedInfo = + yaz_set_proposal_charneg( + out, + (const char**)&negotiationCharset, + negotiationCharset ? 1 : 0, + (const char**)&yazLang, yazLang ? 1 : 0, 1); } } @@ -309,6 +332,16 @@ static void send_initRequest(const char* type_and_host) printf("Sent initrequest.\n"); } + +/* These two are used only from process_initResponse() */ +static void render_initUserInfo(Z_OtherInformation *ui1); +static void render_diag(Z_DiagnosticFormat *diag); + +static void pr_opt(const char *opt, void *clientData) +{ + printf (" %s", opt); +} + static int process_initResponse(Z_InitResponse *res) { int ver = 0; @@ -316,7 +349,7 @@ static int process_initResponse(Z_InitResponse *res) session_mem = odr_extract_mem(in); session = res; - for (ver = 0; ver<5; ver++) + for (ver = 0; ver < 8; ver++) if (!ODR_MASK_GET(res->protocolVersion, ver)) break; @@ -333,64 +366,31 @@ static int process_initResponse(Z_InitResponse *res) if (res->userInformationField) { Z_External *uif = res->userInformationField; - printf("UserInformationfield:\n"); - if (!z_External(print, (Z_External**)&uif, 0, 0)) - { - odr_perror(print, "Printing userinfo\n"); - odr_reset(print); - } - if (uif->which == Z_External_octet) - { - printf("Guessing visiblestring:\n"); - printf("'%s'\n", uif->u. octet_aligned->buf); - } else if (uif->which == Z_External_single) { - /* Peek at any private Init-diagnostic APDUs */ - Odr_any *sat = uif->u.single_ASN1_type; - printf("### NAUGHTY: External is '%s'\n", sat->buf); + if (uif->which == Z_External_userInfo1) { + render_initUserInfo(uif->u.userInfo1); + } else { + printf("UserInformationfield:\n"); + if (!z_External(print, (Z_External**)&uif, 0, 0)) { + odr_perror(print, "Printing userinfo\n"); + odr_reset(print); + } + if (uif->which == Z_External_octet) { + printf("Guessing visiblestring:\n"); + printf("'%s'\n", uif->u. octet_aligned->buf); + } else if (uif->which == Z_External_single) { + /* Peek at any private Init-diagnostic APDUs */ + Odr_any *sat = uif->u.single_ASN1_type; + printf("### NAUGHTY: External is '%s'\n", sat->buf); + } + odr_reset (print); } - odr_reset (print); } printf ("Options:"); - if (ODR_MASK_GET(res->options, Z_Options_search)) - printf (" search"); - if (ODR_MASK_GET(res->options, Z_Options_present)) - printf (" present"); - if (ODR_MASK_GET(res->options, Z_Options_delSet)) - printf (" delSet"); - if (ODR_MASK_GET(res->options, Z_Options_resourceReport)) - printf (" resourceReport"); - if (ODR_MASK_GET(res->options, Z_Options_resourceCtrl)) - printf (" resourceCtrl"); - if (ODR_MASK_GET(res->options, Z_Options_accessCtrl)) - printf (" accessCtrl"); - if (ODR_MASK_GET(res->options, Z_Options_scan)) - printf (" scan"); - if (ODR_MASK_GET(res->options, Z_Options_sort)) - printf (" sort"); - if (ODR_MASK_GET(res->options, Z_Options_extendedServices)) - printf (" extendedServices"); - if (ODR_MASK_GET(res->options, Z_Options_level_1Segmentation)) - printf (" level1Segmentation"); - if (ODR_MASK_GET(res->options, Z_Options_level_2Segmentation)) - printf (" level2Segmentation"); - if (ODR_MASK_GET(res->options, Z_Options_concurrentOperations)) - printf (" concurrentOperations"); + yaz_init_opt_decode(res->options, pr_opt, 0); + printf ("\n"); + if (ODR_MASK_GET(res->options, Z_Options_namedResultSets)) - { - printf (" namedResultSets"); setnumber = 0; - } - if (ODR_MASK_GET(res->options, Z_Options_encapsulation)) - printf (" encapsulation"); - if (ODR_MASK_GET(res->options, Z_Options_resultCount)) - printf (" resultCount"); - if (ODR_MASK_GET(res->options, Z_Options_negotiationModel)) - printf (" negotiationModel"); - if (ODR_MASK_GET(res->options, Z_Options_duplicateDetection)) - printf (" duplicateDetection"); - if (ODR_MASK_GET(res->options, Z_Options_queryType104)) - printf (" queryType104"); - printf ("\n"); if (ODR_MASK_GET(res->options, Z_Options_negotiationModel)) { @@ -404,6 +404,15 @@ static int process_initResponse(Z_InitResponse *res) yaz_get_response_charneg(session_mem, p, &charset, &lang, &selected); + + if (outputCharset && negotiationCharset) { + odr_set_charset (out, charset, outputCharset); + odr_set_charset (in, outputCharset, charset); + } + else { + odr_set_charset (out, 0, 0); + odr_set_charset (in, 0, 0); + } printf("Accepted character set : %s\n", charset); printf("Accepted code language : %s\n", lang ? lang : "none"); @@ -414,6 +423,60 @@ static int process_initResponse(Z_InitResponse *res) return 0; } + +static void render_initUserInfo(Z_OtherInformation *ui1) { + int i; + printf("Init response contains %d otherInfo unit%s:\n", + ui1->num_elements, ui1->num_elements == 1 ? "" : "s"); + + for (i = 0; i < ui1->num_elements; i++) { + Z_OtherInformationUnit *unit = ui1->list[i]; + printf(" %d: otherInfo unit contains ", i+1); + if (unit->which == Z_OtherInfo_externallyDefinedInfo && + unit->information.externallyDefinedInfo->which == + Z_External_diag1) { + render_diag(unit->information.externallyDefinedInfo->u.diag1); + } else { + printf("unsupported otherInfo unit type %d\n", unit->which); + } + } +} + + +/* ### should this share code with display_diagrecs()? */ +static void render_diag(Z_DiagnosticFormat *diag) { + int i; + + printf("%d diagnostic%s:\n", diag->num, diag->num == 1 ? "" : "s"); + for (i = 0; i < diag->num; i++) { + Z_DiagnosticFormat_s *ds = diag->elements[i]; + printf(" %d: ", i+1); + switch (ds->which) { + case Z_DiagnosticFormat_s_defaultDiagRec: { + Z_DefaultDiagFormat *dd = ds->u.defaultDiagRec; + /* ### should check `dd->diagnosticSetId' */ + printf("code=%d (%s)", *dd->condition, + diagbib1_str(*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); + break; + } + case Z_DiagnosticFormat_s_explicitDiagnostic: + printf("Explicit diagnostic (not supported)"); + break; + default: + printf("Unrecognised diagnostic type %d", ds->which); + break; + } + + if (ds->message != 0) + printf(", message='%s'", ds->message); + printf("\n"); + } +} + + static int set_base(const char *arg) { int i; @@ -474,6 +537,9 @@ int session_connect(const char *arg) void *add; char type_and_host[101]; const char *basep = 0; +#if HAVE_OPENSSL_SSL_H + SSL *ssl; +#endif if (conn) { cs_close (conn); @@ -531,6 +597,31 @@ int session_connect(const char *arg) return 0; } printf("OK.\n"); +#if HAVE_OPENSSL_SSL_H + if ((ssl = (SSL *) cs_get_ssl(conn))) + { + X509 *server_cert = SSL_get_peer_certificate (ssl); + char *str; + if (server_cert) + { + printf ("Server certificate:\n"); + + str = X509_NAME_oneline (X509_get_subject_name (server_cert),0,0); + if (str) + { + printf ("\t subject: %s\n", str); + free (str); + } + str = X509_NAME_oneline (X509_get_issuer_name (server_cert),0,0); + if (str) + { + printf ("\t issuer: %s\n", str); + free (str); + } + X509_free (server_cert); + } + } +#endif if (basep && *basep) set_base (basep); if (protocol == PROTO_Z3950) @@ -543,7 +634,6 @@ int session_connect(const char *arg) int cmd_open(const char *arg) { - static char cur_host[200]; if (arg) { strncpy (cur_host, arg, sizeof(cur_host)-1); @@ -590,9 +680,14 @@ int cmd_authentication(const char *arg) if (r == 1) { auth = &au; - au.which = Z_IdAuthentication_open; - au.u.open = user; - printf("Authentication set to Open (%s)\n", user); + if (!strcmp(user, "-")) { + au.which = Z_IdAuthentication_anonymous; + printf("Authentication set to Anonymous\n"); + } else { + au.which = Z_IdAuthentication_open; + au.u.open = user; + printf("Authentication set to Open (%s)\n", user); + } } if (r == 2) { @@ -653,7 +748,7 @@ static void display_record(Z_External *r) if (ent && r->which == Z_External_octet) { Z_ext_typeent *type = z_ext_getentbyref(ent->value); - void *rr; + char *rr; if (type) { @@ -662,7 +757,7 @@ static void display_record(Z_External *r) */ odr_setbuf(in, (char*)r->u.octet_aligned->buf, r->u.octet_aligned->len, 0); - if (!(*type->fun)(in, (char **)&rr, 0, 0)) + if (!(*type->fun)(in, &rr, 0, 0)) { odr_perror(in, "Decoding constructed record."); fprintf(stdout, "[Near %d]\n", odr_offset(in)); @@ -682,16 +777,16 @@ static void display_record(Z_External *r) } } } - if (ent && ent->oclass != CLASS_RECSYN) - return; if (ent && ent->value == VAL_SOIF) print_record((const unsigned char *) r->u.octet_aligned->buf, r->u.octet_aligned->len); else if (r->which == Z_External_octet) { const char *octet_buf = (char*)r->u.octet_aligned->buf; - if (ent->value == VAL_TEXT_XML || ent->value == VAL_APPLICATION_XML || - ent->value == VAL_HTML) + if (ent->oclass == CLASS_RECSYN && + (ent->value == VAL_TEXT_XML || + ent->value == VAL_APPLICATION_XML || + ent->value == VAL_HTML)) { print_record((const unsigned char *) octet_buf, r->u.octet_aligned->len); @@ -857,6 +952,8 @@ static void display_record(Z_External *r) printf ("shelvingLocation: %s\n", data->shelvingLocation); if (data->callNumber) printf ("callNumber: %s\n", data->callNumber); + if (data->shelvingData) + printf ("shelvingData: %s\n", data->shelvingData); if (data->copyNumber) printf ("copyNumber: %s\n", data->copyNumber); if (data->publicNote) @@ -1035,11 +1132,11 @@ static int send_deleteResultSetRequest(const char *arg) static int send_srw(Z_SRW_PDU *sr) { const char *charset = negotiationCharset; - const char *host_port = 0; + const char *host_port = cur_host; 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}, + {"http://www.loc.gov/zing/srw/", 0, (Z_SOAP_fun) yaz_srw_codec}, {0, 0, 0} }; ODR o = odr_createmem(ODR_ENCODE); @@ -1052,6 +1149,7 @@ static int send_srw(Z_SRW_PDU *sr) strcpy(path+1, databaseNames[0]); gdu = z_get_HTTP_Request(out); + gdu->u.HTTP_Request->version = http_version; gdu->u.HTTP_Request->path = odr_strdup(out, path); if (host_port) @@ -1073,7 +1171,7 @@ static int send_srw(Z_SRW_PDU *sr) memcpy (h, cp0, cp1 - cp0); h[cp1-cp0] = '\0'; z_HTTP_header_add(out, &gdu->u.HTTP_Request->headers, - "host", h); + "Host", h); } } @@ -1105,10 +1203,18 @@ static int send_srw(Z_SRW_PDU *sr) char *buf_out; int len_out; int r; + if (apdu_file) + { + if (!z_GDU(print, &gdu, 0, 0)) + printf ("Failed to print outgoing APDU\n"); + odr_reset(print); + } buf_out = odr_getbuf(out, &len_out, 0); /* we don't odr_reset(out), since we may need the buffer again */ + do_hex_dump(buf_out, len_out); + r = cs_put(conn, buf_out, len_out); odr_destroy(o); @@ -1142,8 +1248,13 @@ static int send_SRW_searchRequest(const char *arg) sr = yaz_srw_get(out, Z_SRW_searchRetrieve_request); sr->u.request->query_type = Z_SRW_query_type_cql; sr->u.request->query.cql = odr_strdup(out, arg); - if (schema) - sr->u.request->recordSchema = schema; + + sr->u.request->maximumRecords = odr_intdup(out, 0); + + if (record_schema) + sr->u.request->recordSchema = record_schema; + if (recordsyntax == VAL_TEXT_XML) + sr->u.explain_request->recordPacking = "xml"; return send_srw(sr); } #endif @@ -1835,14 +1946,24 @@ static int only_z3950() return 0; } +static int cmd_update_common(const char *arg, int version); + static int cmd_update(const char *arg) { + return cmd_update_common(arg, 1); +} + +static int cmd_update0(const char *arg) +{ + return cmd_update_common(arg, 0); +} + +static int cmd_update_common(const char *arg, int version) +{ Z_APDU *apdu = zget_APDU(out, Z_APDU_extendedServicesRequest ); Z_ExtendedServicesRequest *req = apdu->u.extendedServicesRequest; Z_External *r; int oid[OID_SIZE]; - Z_IUOriginPartToKeep *toKeep; - Z_IUSuppliedRecords *notToKeep; oident update_oid; char action[20], recid[20], fname[80]; int action_no; @@ -1906,7 +2027,10 @@ static int cmd_update(const char *arg) update_oid.proto = PROTO_Z3950; update_oid.oclass = CLASS_EXTSERV; - update_oid.value = VAL_DBUPDATE; + if (version == 0) + update_oid.value = VAL_DBUPDATE0; + else + update_oid.value = VAL_DBUPDATE; oid_ent_to_oid (&update_oid, oid); req->packageType = odr_oiddup(out,oid); req->packageName = esPackageName; @@ -1918,41 +2042,90 @@ static int cmd_update(const char *arg) r->direct_reference = odr_oiddup(out,oid); r->indirect_reference = 0; r->descriptor = 0; - r->which = Z_External_update; - r->u.update = (Z_IUUpdate *) odr_malloc(out, sizeof(*r->u.update)); - r->u.update->which = Z_IUUpdate_esRequest; - r->u.update->u.esRequest = (Z_IUUpdateEsRequest *) - odr_malloc(out, sizeof(*r->u.update->u.esRequest)); - toKeep = r->u.update->u.esRequest->toKeep = (Z_IUOriginPartToKeep *) - odr_malloc(out, sizeof(*r->u.update->u.esRequest->toKeep)); - toKeep->databaseName = databaseNames[0]; - toKeep->schema = 0; - toKeep->elementSetName = 0; - toKeep->actionQualifier = 0; - toKeep->action = (int *) odr_malloc(out, sizeof(*toKeep->action)); - *toKeep->action = action_no; - - notToKeep = r->u.update->u.esRequest->notToKeep = (Z_IUSuppliedRecords *) - odr_malloc(out, sizeof(*r->u.update->u.esRequest->notToKeep)); - notToKeep->num = 1; - notToKeep->elements = (Z_IUSuppliedRecords_elem **) - odr_malloc(out, sizeof(*notToKeep->elements)); - 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); + if (version == 0) + { + Z_IU0OriginPartToKeep *toKeep; + Z_IU0SuppliedRecords *notToKeep; + + r->which = Z_External_update0; + r->u.update0 = (Z_IU0Update *) odr_malloc(out, sizeof(*r->u.update0)); + r->u.update0->which = Z_IUUpdate_esRequest; + r->u.update0->u.esRequest = (Z_IU0UpdateEsRequest *) + odr_malloc(out, sizeof(*r->u.update0->u.esRequest)); + toKeep = r->u.update0->u.esRequest->toKeep = (Z_IU0OriginPartToKeep *) + odr_malloc(out, sizeof(*r->u.update0->u.esRequest->toKeep)); + + toKeep->databaseName = databaseNames[0]; + toKeep->schema = 0; + toKeep->elementSetName = 0; + + toKeep->action = (int *) odr_malloc(out, sizeof(*toKeep->action)); + *toKeep->action = action_no; + + notToKeep = r->u.update0->u.esRequest->notToKeep = (Z_IU0SuppliedRecords *) + odr_malloc(out, sizeof(*r->u.update0->u.esRequest->notToKeep)); + notToKeep->num = 1; + notToKeep->elements = (Z_IU0SuppliedRecords_elem **) + odr_malloc(out, sizeof(*notToKeep->elements)); + 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]->supplementalId = 0; + notToKeep->elements[0]->correlationInfo = 0; + notToKeep->elements[0]->record = record_this; } else - notToKeep->elements[0]->u.opaque = 0; - notToKeep->elements[0]->supplementalId = 0; - notToKeep->elements[0]->correlationInfo = 0; - notToKeep->elements[0]->record = record_this; + { + Z_IUOriginPartToKeep *toKeep; + Z_IUSuppliedRecords *notToKeep; + + r->which = Z_External_update; + r->u.update = (Z_IUUpdate *) odr_malloc(out, sizeof(*r->u.update)); + r->u.update->which = Z_IUUpdate_esRequest; + r->u.update->u.esRequest = (Z_IUUpdateEsRequest *) + odr_malloc(out, sizeof(*r->u.update->u.esRequest)); + toKeep = r->u.update->u.esRequest->toKeep = (Z_IUOriginPartToKeep *) + odr_malloc(out, sizeof(*r->u.update->u.esRequest->toKeep)); + + toKeep->databaseName = databaseNames[0]; + toKeep->schema = 0; + toKeep->elementSetName = 0; + toKeep->actionQualifier = 0; + toKeep->action = (int *) odr_malloc(out, sizeof(*toKeep->action)); + *toKeep->action = action_no; + + notToKeep = r->u.update->u.esRequest->notToKeep = (Z_IUSuppliedRecords *) + odr_malloc(out, sizeof(*r->u.update->u.esRequest->notToKeep)); + notToKeep->num = 1; + notToKeep->elements = (Z_IUSuppliedRecords_elem **) + odr_malloc(out, sizeof(*notToKeep->elements)); + 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]->supplementalId = 0; + notToKeep->elements[0]->correlationInfo = 0; + notToKeep->elements[0]->record = record_this; + } send_apdu(apdu); @@ -1975,6 +2148,68 @@ static int cmd_itemorder(const char *arg) return 2; } +static void show_opt(const char *arg, void *clientData) +{ + printf ("%s ", arg); +} + +static int cmd_zversion(const char *arg) +{ + if (*arg && arg) + z3950_version = atoi(arg); + else + printf ("version is %d\n", z3950_version); + return 0; +} + +static int cmd_options(const char *arg) +{ + if (*arg) + { + int r; + int pos; + r = yaz_init_opt_encode(&z3950_options, arg, &pos); + } + else + { + yaz_init_opt_decode(&z3950_options, show_opt, 0); + printf ("\n"); + } + return 0; +} + +static int cmd_explain(const char *arg) +{ + if (protocol != PROTO_HTTP) + return 0; +#if HAVE_XML2 + if (!conn) + cmd_open(0); + if (conn) + { + Z_SRW_PDU *sr = 0; + + setno = 1; + + /* save this for later .. when fetching individual records */ + sr = yaz_srw_get(out, Z_SRW_explain_request); + if (recordsyntax == VAL_TEXT_XML) + sr->u.explain_request->recordPacking = "xml"; + send_srw(sr); + return 2; + } +#endif + return 0; +} + +static int cmd_init(const char *arg) +{ + if (!conn || protocol != PROTO_Z3950) + return 0; + send_initRequest(0); + return 2; +} + static int cmd_find(const char *arg) { if (!*arg) @@ -1987,6 +2222,8 @@ static int cmd_find(const char *arg) #if HAVE_XML2 if (!conn) cmd_open(0); + if (!conn) + return 0; if (!send_SRW_searchRequest(arg)) return 0; #else @@ -2125,13 +2362,13 @@ static int send_presentRequest(const char *arg) req->preferredRecordSyntax = odr_oiddup (out, oid_ent_to_oid(&prefsyn, oid)); - if (schema) + if (record_schema) { oident prefschema; prefschema.proto = protocol; prefschema.oclass = CLASS_SCHEMA; - prefschema.value = oid_getvalbyname(schema); + prefschema.value = oid_getvalbyname(record_schema); req->recordComposition = &compo; compo.which = Z_RecordComp_complex; @@ -2192,8 +2429,10 @@ static int send_SRW_presentRequest(const char *arg) parse_show_args(arg, setstring, &setno, &nos); sr->u.request->startRecord = odr_intdup(out, setno); sr->u.request->maximumRecords = odr_intdup(out, nos); - if (schema) - sr->u.request->recordSchema = schema; + if (record_schema) + sr->u.request->recordSchema = record_schema; + if (recordsyntax == VAL_TEXT_XML) + sr->u.request->recordPacking = "xml"; return send_srw(sr); } #endif @@ -2253,6 +2492,8 @@ static int cmd_show(const char *arg) #if HAVE_XML2 if (!conn) cmd_open(0); + if (!conn) + return 0; if (!send_SRW_presentRequest(arg)) return 0; #else @@ -2416,7 +2657,9 @@ int send_sortrequest(const char *arg, int newset) void display_term(Z_TermInfo *t) { - if (t->term->which == Z_Term_general) + if (t->displayTerm) + printf("%s", t->displayTerm); + else if (t->term->which == Z_Term_general) { printf("%.*s", t->term->u.general->len, t->term->u.general->buf); sprintf(last_scan_line, "%.*s", t->term->u.general->len, @@ -2567,10 +2810,10 @@ int cmd_scan(const char *arg) int cmd_schema(const char *arg) { - xfree(schema); - schema = 0; + xfree(record_schema); + record_schema = 0; if (arg && *arg) - schema = xstrdup(arg); + record_schema = xstrdup(arg); return 1; } @@ -2757,16 +3000,7 @@ int cmd_charset(const char* arg) 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; } @@ -3097,6 +3331,28 @@ struct timeval tv_start, tv_end; #endif #if HAVE_XML2 +static void handle_srw_record(Z_SRW_record *rec) +{ + if (rec->recordPosition) + { + printf ("pos=%d", *rec->recordPosition); + setno = *rec->recordPosition + 1; + } + if (rec->recordSchema) + printf (" schema=%s", rec->recordSchema); + printf ("\n"); + if (rec->recordData_buf && rec->recordData_len) + fwrite(rec->recordData_buf, 1, rec->recordData_len, stdout); + else + printf ("No data!"); + printf("\n"); +} + +static void handle_srw_explain_response(Z_SRW_explainResponse *res) +{ + handle_srw_record(&res->record); +} + static void handle_srw_response(Z_SRW_searchRetrieveResponse *res) { int i; @@ -3105,33 +3361,20 @@ static void handle_srw_response(Z_SRW_searchRetrieveResponse *res) for (i = 0; inum_diagnostics; i++) { - printf ("SRW diagnostic %d %s\n", - *res->diagnostics[i].code, - yaz_diag_srw_str(*res->diagnostics[i].code)); - + if (res->diagnostics[i].uri) + printf ("SRW diagnostic %s\n", + res->diagnostics[i].uri); + else + printf ("SRW diagnostic missing or could not be decoded\n"); + if (res->diagnostics[i].message) + printf ("Message: %s\n", res->diagnostics[i].message); 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; inum_records; i++) - { - Z_SRW_record *rec = res->records + i; - - if (rec->recordPosition) - { - printf ("pos=%d", *rec->recordPosition); - setno = *rec->recordPosition + 1; - } - if (rec->recordSchema) - printf (" schema=%s", rec->recordSchema); - printf ("\n"); - if (rec->recordData_buf && rec->recordData_len) - { - fwrite(rec->recordData_buf, 1, rec->recordData_len, stdout); - printf ("\n"); - } - } + handle_srw_record(res->records + i); } static void http_response(Z_HTTP_Response *hres) @@ -3146,7 +3389,7 @@ static void http_response(Z_HTTP_Response *hres) Z_SOAP *soap_package = 0; ODR o = odr_createmem(ODR_DECODE); Z_SOAP_Handler soap_handlers[2] = { - {"http://www.loc.gov/zing/srw/v1.0/", 0, + {"http://www.loc.gov/zing/srw/", 0, (Z_SOAP_fun) yaz_srw_codec}, {0, 0, 0} }; @@ -3159,10 +3402,12 @@ static void http_response(Z_HTTP_Response *hres) Z_SRW_PDU *sr = 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 ret = -1; } - else if (!ret && (soap_package->which == Z_SOAP_fault + else if (soap_package && (soap_package->which == Z_SOAP_fault || soap_package->which == Z_SOAP_error)) { printf ("HTTP Error Status=%d\n", hres->code); @@ -3170,6 +3415,9 @@ static void http_response(Z_HTTP_Response *hres) 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 ret = -1; @@ -3187,17 +3435,20 @@ static void http_response(Z_HTTP_Response *hres) } close_session(); } - if (!strcmp(hres->version, "1.0")) - { - /* HTTP 1.0: only if Keep-Alive we stay alive.. */ - if (!connection_head || strcmp(connection_head, "Keep-Alive")) - close_session(); - } - else + else { - /* HTTP 1.1: only if no close we stay alive .. */ - if (connection_head && !strcmp(connection_head, "close")) - close_session(); + if (!strcmp(hres->version, "1.0")) + { + /* HTTP 1.0: only if Keep-Alive we stay alive.. */ + if (!connection_head || strcmp(connection_head, "Keep-Alive")) + close_session(); + } + else + { + /* HTTP 1.1: only if no close we stay alive .. */ + if (connection_head && !strcmp(connection_head, "close")) + close_session(); + } } } #endif @@ -3226,6 +3477,8 @@ void wait_and_handle_response() buf_out = odr_getbuf(out, &len_out, 0); + do_hex_dump(buf_out, len_out); + cs_put(conn, buf_out, len_out); odr_reset(out); @@ -3253,7 +3506,10 @@ void wait_and_handle_response() odr_dumpBER(f, netbuffer, res); fprintf(f, "---------\n"); if (apdu_file) + { z_GDU(print, &gdu, 0, 0); + odr_reset(print); + } if (conn && cs_more(conn)) continue; break; @@ -3399,7 +3655,6 @@ int cmd_set_otherinfo(const char* args) printf("Error otherinfo index to large (%d>%d)\n",otherinfoNo,maxOtherInfosSupported); } - oidval = oid_getvalbyname (oid); if(oidval == -1 ) { printf("Error in set_otherinfo command unknown oid %s \n",oid); @@ -3502,7 +3757,7 @@ int cmd_list_all(const char* args) { /* print present related options */ printf("Format : %s\n",yaz_z3950_oid_value_to_str(recordsyntax,CLASS_RECSYN)); - printf("Schema : %s\n",schema); + printf("Schema : %s\n",record_schema ? record_schema : "not set"); printf("Elements : %s\n",elementSetNames?elementSetNames->u.generic:""); /* loging options */ @@ -3581,6 +3836,7 @@ static struct { {"refid", cmd_refid, "",NULL,0,NULL}, {"itemorder", cmd_itemorder, "ill|item ",NULL,0,NULL}, {"update", cmd_update, " []",NULL,0,NULL}, + {"update0", cmd_update0, " []",NULL,0,NULL}, {"packagename", cmd_packagename, "",NULL,0,NULL}, {"proxy", cmd_proxy, "[('tcp'|'ssl')][':']",NULL,0,NULL}, {"charset", cmd_charset, " ",NULL,0,NULL}, @@ -3612,7 +3868,11 @@ static struct { {"adm-commit", cmd_adm_commit, "",NULL,0,NULL}, {"adm-shutdown", cmd_adm_shutdown, "",NULL,0,NULL}, {"adm-startup", cmd_adm_startup, "",NULL,0,NULL}, + {"explain", cmd_explain, "", NULL, 0, NULL}, + {"options", cmd_options, "", NULL, 0, NULL}, + {"zversion", cmd_zversion, "", NULL, 0, NULL}, {"help", cmd_help, "", NULL,0,NULL}, + {"init", cmd_init, "", NULL,0,NULL}, {0,0,0,0,0,0} }; @@ -3910,8 +4170,17 @@ int main(int argc, char **argv) #endif if (codeset) outputCharset = xstrdup(codeset); + + ODR_MASK_SET(&z3950_options, Z_Options_search); + ODR_MASK_SET(&z3950_options, Z_Options_present); + ODR_MASK_SET(&z3950_options, Z_Options_namedResultSets); + ODR_MASK_SET(&z3950_options, Z_Options_triggerResourceCtrl); + ODR_MASK_SET(&z3950_options, Z_Options_scan); + ODR_MASK_SET(&z3950_options, Z_Options_sort); + ODR_MASK_SET(&z3950_options, Z_Options_extendedServices); + ODR_MASK_SET(&z3950_options, Z_Options_delSet); - while ((ret = options("k:c:q:a:b:m:v:p:u:t:Vx", argv, argc, &arg)) != -2) + while ((ret = options("k:c:q:a:b:m:v:p:u:t:Vxd:", argv, argc, &arg)) != -2) { switch (ret) { @@ -3923,6 +4192,9 @@ int main(int argc, char **argv) strcat (open_command, arg); } break; + case 'd': + dump_file_prefix = arg; + break; case 'k': kilobytes = atoi(arg); break; @@ -3980,7 +4252,7 @@ int main(int argc, char **argv) fprintf (stderr, "Usage: %s [-m ] [ -a ] " "[-b berdump] [-c cclfields] \n" "[-q cqlfields] [-p ] [-u ] " - "[-k size] [-V] []\n", + "[-k size] [-d dump] [-V] []\n", prog); exit (1); }