X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=client%2Fclient.c;h=811d9573ff2fa6657cc00797dd1646018361d8ae;hp=dee60903a70381c3d6b1a1c28e90c97ab71abf2f;hb=a4d9a7973644a72d521b462df6cad688e526d27c;hpb=5ee8b8431f852d06d1963134d38c1bb8fe6343fa diff --git a/client/client.c b/client/client.c index dee6090..811d957 100644 --- a/client/client.c +++ b/client/client.c @@ -2,7 +2,7 @@ * Copyright (C) 1995-2007, Index Data ApS * See the file LICENSE for details. * - * $Id: client.c,v 1.335 2007-05-02 11:51:54 adam Exp $ + * $Id: client.c,v 1.356 2007-12-27 13:27:40 adam Exp $ */ /** \file client.c * \brief yaz-client program @@ -63,6 +63,7 @@ #include #include #include +#include #include #include @@ -89,7 +90,8 @@ static file_history_t file_history = 0; -static char *sru_method = "soap"; +static char sru_method[10] = "soap"; +static char sru_version[10] = "1.2"; static char *codeset = 0; /* character set for output */ static int hex_dump = 0; static char *dump_file_prefix = 0; @@ -133,6 +135,7 @@ static int negotiationCharsetRecords = 1; static int negotiationCharsetVersion = 3; static char *outputCharset = 0; static char *marcCharset = 0; +static char *queryCharset = 0; static char* yazLang = 0; static char last_cmd[32] = "?"; @@ -169,12 +172,9 @@ static cql_transform_t cqltrans = 0; /* CQL context-set handle */ int rl_attempted_completion_over = 0; #endif -/* set this one to 1, to avoid decode of unknown MARCs */ -#define AVOID_MARC_DECODE 1 - #define maxOtherInfosSupported 10 -struct { - int oid[OID_SIZE]; +struct eoi { + Odr_oid oid[OID_SIZE]; char* value; } extraOtherInfos[maxOtherInfosSupported]; @@ -184,6 +184,7 @@ char **readline_completer(char *text, int start, int end); #endif static char *command_generator(const char *text, int state); int cmd_register_tab(const char* arg); +int cmd_querycharset(const char *arg); static void close_session (void); @@ -361,6 +362,21 @@ static void send_initRequest(const char* type_and_host) negotiationCharsetRecords); } } + else if (ODR_MASK_GET(req->options, Z_Options_negotiationModel)) + { + Z_OtherInformation **p; + Z_OtherInformationUnit *p0; + + yaz_oi_APDU(apdu, &p); + + if ((p0=yaz_oi_update(p, out, NULL, 0, 0))) + { + p0->which = Z_OtherInfo_externallyDefinedInfo; + p0->information.externallyDefinedInfo = + yaz_set_proposal_charneg(out, 0, 0, 0, 0, 0); + } + + } if (send_apdu(apdu)) printf("Sent initrequest.\n"); } @@ -415,11 +431,9 @@ static int process_initResponse(Z_InitResponse *res) } else if (uif->which == Z_External_single) { - const int *oclc_oid = yaz_string_to_oid(yaz_oid_std(), - CLASS_GENERAL, - "OCLC-userInfo"); Odr_any *sat = uif->u.single_ASN1_type; - if (!oid_oidcmp(uif->direct_reference, oclc_oid)) + if (!oid_oidcmp(uif->direct_reference, + yaz_oid_userinfo_oclc_userinfo)) { Z_OCLC_UserInformation *oclc_ui; ODR decode = odr_createmem(ODR_DECODE); @@ -454,27 +468,30 @@ static int process_initResponse(Z_InitResponse *res) Z_CharSetandLanguageNegotiation *p = yaz_get_charneg_record(res->otherInfo); - if (p) { - + if (p) + { char *charset=NULL, *lang=NULL; int selected; yaz_get_response_charneg(session_mem, p, &charset, &lang, &selected); - printf("Accepted character set : %s\n", charset); - printf("Accepted code language : %s\n", lang ? lang : "none"); + printf("Accepted character set : %s\n", charset ? charset:"none"); + printf("Accepted code language : %s\n", lang ? lang:"none"); printf("Accepted records in ...: %d\n", selected ); - if (outputCharset && negotiationCharset) { + if (outputCharset && charset) + { printf("Converting between %s and %s\n", - outputCharset, negotiationCharset); - odr_set_charset (out, charset, outputCharset); - odr_set_charset (in, outputCharset, charset); + outputCharset, charset); + odr_set_charset(out, charset, outputCharset); + odr_set_charset(in, outputCharset, charset); + cmd_querycharset(charset); } - else { - odr_set_charset (out, 0, 0); - odr_set_charset (in, 0, 0); + else + { + odr_set_charset(out, 0, 0); + odr_set_charset(in, 0, 0); } } } @@ -581,29 +598,27 @@ static int set_base(const char *arg) return 1; } -static int parse_cmd_doc(const char **arg, ODR out, char **buf, - int *len, int opt) +static int parse_cmd_doc(const char **arg, ODR out, char **buf, int *len) { const char *sep; while (**arg && strchr(" \t\n\r\f", **arg)) (*arg)++; - if ((*arg)[0] == '\"' && (sep=strchr(*arg+1, '"'))) + if (**arg == '\0') { - (*arg)++; - *len = sep - *arg; - *buf = odr_strdupn(out, *arg, *len); - (*arg) = sep+1; - return 1; + return 0; } - else if ((*arg)[0] && (*arg)[0] != '\"') + else if ((*arg)[0] == '<') { long fsize; FILE *inf; - const char *fname = *arg; - + const char *fname; + const char *arg_start = ++(*arg); + while (**arg != '\0' && **arg != ' ') (*arg)++; + fname = odr_strdupn(out, arg_start, *arg - arg_start); + inf = fopen(fname, "rb"); if (!inf) { @@ -624,7 +639,8 @@ static int parse_cmd_doc(const char **arg, ODR out, char **buf, return 0; } *len = fsize; - *buf = odr_malloc(out, fsize); + *buf = (char *) odr_malloc(out, fsize+1); + (*buf)[fsize] = '\0'; if (fread(*buf, 1, fsize, inf) != fsize) { printf("Unable to read %s\n", fname); @@ -632,21 +648,25 @@ static int parse_cmd_doc(const char **arg, ODR out, char **buf, return 0; } fclose(inf); - return 1; } - else if (**arg == '\0') + else if ((*arg)[0] == '\"' && (sep=strchr(*arg+1, '"'))) { - if (opt) - { - *len = 0; - *buf = 0; - return 1; - } - printf("Missing doc argument\n"); + (*arg)++; + *len = sep - *arg; + *buf = odr_strdupn(out, *arg, *len); + (*arg) = sep+1; } else - printf("Bad doc argument %s\n", *arg); - return 0; + { + const char *arg_start = *arg; + + while (**arg != '\0' && **arg != ' ') + (*arg)++; + + *len = *arg - arg_start; + *buf = odr_strdupn(out, arg_start, *len); + } + return 1; } static int cmd_base(const char *arg) @@ -704,8 +724,6 @@ int session_connect(const char *arg) return 0; } #if YAZ_HAVE_XML2 - if (conn->protocol == PROTO_HTTP) - queryType = QueryType_CQL; #else if (conn->protocol == PROTO_HTTP) { @@ -766,12 +784,16 @@ int session_connect(const char *arg) 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; } - return session_connect(cur_host); + r = session_connect(cur_host); + if (conn && conn->protocol == PROTO_HTTP) + queryType = QueryType_CQL; + return r; } void try_reconnect(void) @@ -827,8 +849,8 @@ int cmd_authentication(const char *arg) au.which = Z_IdAuthentication_idPass; au.u.idPass = &idPass; idPass.groupId = NULL; - idPass.userId = user; - idPass.password = group; + idPass.userId = !strcmp(user, "-") ? 0 : user; + idPass.password = !strcmp(group, "-") ? 0 : group; printf("Authentication set to User (%s), Pass (%s)\n", user, group); } if (r == 3) @@ -859,7 +881,7 @@ static void print_record(const unsigned char *buf, size_t len) static void display_record(Z_External *r) { - const int *oid = r->direct_reference; + const Odr_oid *oid = r->direct_reference; record_last = r; /* @@ -867,7 +889,7 @@ static void display_record(Z_External *r) */ if (oid) { - int oclass; + oid_class oclass; char oid_name_buf[OID_STR_MAX]; const char *oid_name = yaz_oid_to_string_buf(oid, &oclass, oid_name_buf); @@ -934,16 +956,7 @@ static void display_record(Z_External *r) } else { - const int *oidsuffix = oid_oidlen(oid) > 1 - ? oid + oid_oidlen(oid)-2 : 0; - if ( -#if AVOID_MARC_DECODE - /* primitive check for a marc OID 5.1-29 except 16 */ - oidsuffix[0] == 5 && oidsuffix[1] < 30 && oidsuffix[1] != 16 -#else - 1 -#endif - ) + if (oid && yaz_oid_is_iso2709(oid)) { const char *result; size_t rlen; @@ -1161,7 +1174,7 @@ static void display_diagrecs(Z_DiagRec **pp, int num) printf("Missing diagset\n"); else { - int oclass; + oid_class oclass; char diag_name_buf[OID_STR_MAX]; const char *diag_name = 0; diag_name = yaz_oid_to_string_buf @@ -1260,21 +1273,21 @@ static int send_srw(Z_SRW_PDU *sr) Z_GDU *gdu; char *path = 0; - path = odr_malloc(out, 2+strlen(databaseNames[0])); + path = (char *) odr_malloc(out, 2+strlen(databaseNames[0])); *path = '/'; strcpy(path+1, databaseNames[0]); gdu = z_get_HTTP_Request_host_path(out, host_port, path); - if (!strcmp(sru_method, "get")) + if (!yaz_matchstr(sru_method, "get")) { yaz_sru_get_encode(gdu->u.HTTP_Request, sr, out, charset); } - else if (!strcmp(sru_method, "post")) + else if (!yaz_matchstr(sru_method, "post")) { yaz_sru_post_encode(gdu->u.HTTP_Request, sr, out, charset); } - else if (!strcmp(sru_method, "soap")) + else if (!yaz_matchstr(sru_method, "soap")) { yaz_sru_soap_encode(gdu->u.HTTP_Request, sr, out, charset); } @@ -1337,7 +1350,7 @@ static int send_SRW_scanRequest(const char *arg, int pos, int num) Z_SRW_PDU *sr = 0; /* regular requestse .. */ - sr = yaz_srw_get(out, Z_SRW_scan_request); + sr = yaz_srw_get_pdu(out, Z_SRW_scan_request, sru_version); switch(queryType) { @@ -1372,10 +1385,11 @@ static int send_SRW_searchRequest(const char *arg) setno = 1; /* save this for later .. when fetching individual records */ - srw_sr = yaz_srw_get(srw_sr_odr_out, Z_SRW_searchRetrieve_request); + srw_sr = yaz_srw_get_pdu(srw_sr_odr_out, Z_SRW_searchRetrieve_request, + sru_version); /* regular request .. */ - sr = yaz_srw_get(out, Z_SRW_searchRetrieve_request); + sr = yaz_srw_get_pdu(out, Z_SRW_searchRetrieve_request, sru_version); switch(queryType) { @@ -1407,6 +1421,22 @@ static int send_SRW_searchRequest(const char *arg) } #endif +static void query_charset_convert(Z_RPNQuery *q) +{ + if (queryCharset && outputCharset) + { + yaz_iconv_t cd = yaz_iconv_open(queryCharset, outputCharset); + if (!cd) + { + printf("Conversion from %s to %s unsupported\n", + outputCharset, queryCharset); + return; + } + yaz_query_charset_convert_rpnquery(q, out, cd); + yaz_iconv_close(cd); + } +} + static int send_searchRequest(const char *arg) { Z_APDU *apdu = zget_APDU(out, Z_APDU_searchRequest); @@ -1512,6 +1542,7 @@ static int send_searchRequest(const char *arg) return 0; } yaz_pqf_destroy (pqf_parser); + query_charset_convert(RPNquery); query.u.type_1 = RPNquery; break; case QueryType_CCL: @@ -1528,6 +1559,7 @@ static int send_searchRequest(const char *arg) printf ("Couldn't convert from CCL to RPN\n"); return 0; } + query_charset_convert(RPNquery); query.u.type_1 = RPNquery; ccl_rpn_delete (rpn); break; @@ -1690,7 +1722,7 @@ static void print_oid(int iLevel, const char *pTag, Odr_oid *pOid) { if (pOid != NULL) { - int *pInt = pOid; + Odr_oid *pInt = pOid; print_level(iLevel); printf("%s:", pTag); @@ -1890,6 +1922,34 @@ void process_ESResponse(Z_ExtendedServicesResponse *res) } } } + if (ext->which == Z_External_itemOrder) + { + Z_IOTaskPackage *otp = ext->u.itemOrder->u.taskPackage; + + if (otp && otp->targetPart ) + { + if (otp->targetPart->itemRequest) + { + Z_External *ext = otp->targetPart->itemRequest; + if (ext->which == Z_External_octet) + { + Odr_oct *doc = ext->u.octet_aligned; + printf("Got itemRequest doc %.*s\n", + doc->len, doc->buf); + } + } + else if (otp->targetPart->statusOrErrorReport) + { + Z_External *ext = otp->targetPart->statusOrErrorReport; + if (ext->which == Z_External_octet) + { + Odr_oct *doc = ext->u.octet_aligned; + printf("Got Status or Error Report doc %.*s\n", + doc->len, doc->buf); + } + } + } + } } if (res->taskPackage && res->taskPackage->which == Z_External_octet) { @@ -1934,10 +1994,8 @@ static Z_External *create_external_itemRequest(void) } else { - const int *ill_oid = yaz_string_to_oid(yaz_oid_std(), - CLASS_GENERAL, "ISOILL-1"); r = (Z_External *) odr_malloc (out, sizeof(*r)); - r->direct_reference = odr_oiddup(out, ill_oid); + r->direct_reference = odr_oiddup(out, yaz_oid_general_isoill_1); r->indirect_reference = 0; r->descriptor = 0; r->which = Z_External_single; @@ -1987,13 +2045,10 @@ static Z_External *create_external_ILL_APDU(int which) } else { - const int *ill_oid = yaz_string_to_oid(yaz_oid_std(), - CLASS_GENERAL, "ISOILL-1"); - ill_request_buf = odr_getbuf (out, &ill_request_size, 0); r = (Z_External *) odr_malloc (out, sizeof(*r)); - r->direct_reference = odr_oiddup(out, ill_oid); + r->direct_reference = odr_oiddup(out, yaz_oid_general_isoill_1); r->indirect_reference = 0; r->descriptor = 0; r->which = Z_External_single; @@ -2014,13 +2069,12 @@ static Z_External *create_external_ILL_APDU(int which) } -static Z_External *create_ItemOrderExternal(const char *type, int itemno) +static Z_External *create_ItemOrderExternal(const char *type, int itemno, + const char *xml_buf, + int xml_len) { Z_External *r = (Z_External *) odr_malloc(out, sizeof(Z_External)); - const int *itemorder_oid = yaz_string_to_oid(yaz_oid_std(), - CLASS_EXTSERV, - "Item order"); - r->direct_reference = odr_oiddup(out, itemorder_oid); + r->direct_reference = odr_oiddup(out, yaz_oid_extserv_item_order); r->indirect_reference = 0; r->descriptor = 0; @@ -2068,16 +2122,18 @@ static Z_External *create_ItemOrderExternal(const char *type, int itemno) } else if (!strcmp(type, "xml") || !strcmp(type, "3")) { - const int *oid_xml = yaz_string_to_oid(yaz_oid_std(), - CLASS_RECSYN, "xml"); - const char *xml_buf = - "\n" - " request\n" - " 000200\n" - " 1212 \n" - ""; - r->u.itemOrder->u.esRequest->notToKeep->itemRequest = - z_ext_record_oid(out, oid_xml, xml_buf, strlen(xml_buf)); + printf("using XML ILL-request\n"); + + if (!xml_buf) + { + printf("no docoument added\n"); + r->u.itemOrder->u.esRequest->notToKeep->itemRequest = 0; + } + else + { + r->u.itemOrder->u.esRequest->notToKeep->itemRequest = + z_ext_record_oid(out, yaz_oid_recsyn_xml, xml_buf, xml_len); + } } else r->u.itemOrder->u.esRequest->notToKeep->itemRequest = 0; @@ -2085,21 +2141,19 @@ static Z_External *create_ItemOrderExternal(const char *type, int itemno) return r; } -static int send_itemorder(const char *type, int itemno) +static int send_itemorder(const char *type, int itemno, + const char *xml_buf, int xml_len) { Z_APDU *apdu = zget_APDU(out, Z_APDU_extendedServicesRequest); Z_ExtendedServicesRequest *req = apdu->u.extendedServicesRequest; - const int *itemorder_oid = yaz_string_to_oid(yaz_oid_std(), - CLASS_EXTSERV, - "Item order"); req->referenceId = set_refid (out); - req->packageType = odr_oiddup(out, itemorder_oid); + req->packageType = odr_oiddup(out, yaz_oid_extserv_item_order); req->packageName = esPackageName; - req->taskSpecificParameters = create_ItemOrderExternal(type, itemno); - + req->taskSpecificParameters = create_ItemOrderExternal(type, itemno, + xml_buf, xml_len); send_apdu(apdu); return 0; } @@ -2139,17 +2193,17 @@ static int cmd_update_SRW(int action_no, const char *recid, static int cmd_update_common(const char *arg, int version) { - char action[20], recid_buf[20]; + char *action_buf; + int action_len; + char *recid_buf; + int recid_len; const char *recid = 0; char *rec_buf; int rec_len; int action_no; int noread = 0; - *action = 0; - *recid_buf = 0; - sscanf (arg, "%19s %19s%n", action, recid_buf, &noread); - if (noread == 0) + if (parse_cmd_doc(&arg, out, &action_buf, &action_len) == 0) { printf("Use: update action recid [fname]\n"); printf(" where action is one of insert,replace,delete.update\n"); @@ -2158,17 +2212,23 @@ static int cmd_update_common(const char *arg, int version) return 0; } - if (!strcmp (action, "insert")) + if (parse_cmd_doc(&arg, out, &recid_buf, &recid_len) == 0) + { + printf("Missing recid\n"); + return 0; + } + + if (!strcmp(action_buf, "insert")) action_no = Z_IUOriginPartToKeep_recordInsert; - else if (!strcmp (action, "replace")) + else if (!strcmp(action_buf, "replace")) action_no = Z_IUOriginPartToKeep_recordReplace; - else if (!strcmp (action, "delete")) + else if (!strcmp(action_buf, "delete")) action_no = Z_IUOriginPartToKeep_recordDelete; - else if (!strcmp (action, "update")) + else if (!strcmp(action_buf, "update")) action_no = Z_IUOriginPartToKeep_specialUpdate; else { - printf ("Bad action: %s\n", action); + printf ("Bad action: %s\n", action_buf); printf ("Possible values: insert, replace, delete, update\n"); return 0; } @@ -2177,14 +2237,14 @@ static int cmd_update_common(const char *arg, int version) recid = recid_buf; arg += noread; - if (parse_cmd_doc(&arg, out, &rec_buf, &rec_len, 1) == 0) + if (parse_cmd_doc(&arg, out, &rec_buf, &rec_len) == 0) return 0; #if YAZ_HAVE_XML2 if (protocol == PROTO_HTTP) - return cmd_update_SRW(action_no, recid, rec_buf, rec_len); + return cmd_update_SRW(action_no, recid_buf, rec_buf, rec_len); #endif - return cmd_update_Z3950(version, action_no, recid, rec_buf, rec_len); + return cmd_update_Z3950(version, action_no, recid_buf, rec_buf, rec_len); } #if YAZ_HAVE_XML2 @@ -2192,7 +2252,7 @@ static int cmd_update_SRW(int action_no, const char *recid, char *rec_buf, int rec_len) { if (!conn) - cmd_open(0); + session_connect(cur_host); if (!conn) return 0; else @@ -2233,11 +2293,9 @@ static int cmd_update_Z3950(int version, int action_no, const char *recid, Z_ExtendedServicesRequest *req = apdu->u.extendedServicesRequest; Z_External *r; Z_External *record_this = 0; - const int *oid_xml = yaz_string_to_oid(yaz_oid_std(), - CLASS_RECSYN, "xml"); - if (rec_buf) - record_this = z_ext_record_oid(out, oid_xml, rec_buf, rec_len); + record_this = z_ext_record_oid(out, yaz_oid_recsyn_xml, + rec_buf, rec_len); else { if (!record_last) @@ -2248,11 +2306,10 @@ static int cmd_update_Z3950(int version, int action_no, const char *recid, record_this = record_last; } - req->packageType = - yaz_string_to_oid_odr(yaz_oid_std(), - CLASS_EXTSERV, - version == 0 ? "DB. Update (first version)" : - "DB. Update", out); + req->packageType = odr_oiddup(out, (version == 0 ? + yaz_oid_extserv_database_update_first_version : + yaz_oid_extserv_database_update)); + req->packageName = esPackageName; req->referenceId = set_refid (out); @@ -2277,6 +2334,12 @@ static int cmd_update_Z3950(int version, int action_no, const char *recid, toKeep->databaseName = databaseNames[0]; toKeep->schema = 0; + if (record_schema) + { + toKeep->schema = yaz_string_to_oid_odr(yaz_oid_std(), + CLASS_SCHEMA, + record_schema, out); + } toKeep->elementSetName = 0; toKeep->action = (int *) odr_malloc(out, sizeof(*toKeep->action)); @@ -2319,6 +2382,12 @@ static int cmd_update_Z3950(int version, int action_no, const char *recid, toKeep->databaseName = databaseNames[0]; toKeep->schema = 0; + if (record_schema) + { + toKeep->schema = yaz_string_to_oid_odr(yaz_oid_std(), + CLASS_SCHEMA, + record_schema, out); + } toKeep->elementSetName = 0; toKeep->actionQualifier = 0; toKeep->action = (int *) odr_malloc(out, sizeof(*toKeep->action)); @@ -2360,7 +2429,7 @@ static int cmd_xmles(const char *arg) { char *asn_buf = 0; int noread = 0; - int *oid; + Odr_oid *oid; char oid_str[51]; Z_APDU *apdu = zget_APDU(out, Z_APDU_extendedServicesRequest); Z_ExtendedServicesRequest *req = apdu->u.extendedServicesRequest; @@ -2382,7 +2451,7 @@ static int cmd_xmles(const char *arg) } arg += noread; if (parse_cmd_doc(&arg, out, &asn_buf, - &ext->u.single_ASN1_type->len, 0) == 0) + &ext->u.single_ASN1_type->len) == 0) return 0; ext->u.single_ASN1_type->buf = (unsigned char *) asn_buf; @@ -2409,15 +2478,19 @@ static int cmd_itemorder(const char *arg) { char type[12]; int itemno; + char *xml_buf = 0; + int xml_len = 0; + int no_read = 0; if (only_z3950()) return 1; - if (sscanf (arg, "%10s %d", type, &itemno) != 2) + if (sscanf(arg, "%10s %d%n", type, &itemno, &no_read) < 2) return 0; + arg += no_read; + parse_cmd_doc(&arg, out, &xml_buf, &xml_len); - printf("Item order request\n"); fflush(stdout); - send_itemorder(type, itemno); + send_itemorder(type, itemno, xml_buf, xml_len); return 2; } @@ -2459,7 +2532,7 @@ static int cmd_explain(const char *arg) return 0; #if YAZ_HAVE_XML2 if (!conn) - cmd_open(0); + session_connect(cur_host); if (conn) { Z_SRW_PDU *sr = 0; @@ -2496,19 +2569,26 @@ static int cmd_sru(const char *arg) if (!*arg) { printf("SRU method is: %s\n", sru_method); + printf("SRU version is: %s\n", sru_version); } else { - if (!yaz_matchstr(arg, "post")) - sru_method = "post"; - else if (!yaz_matchstr(arg, "get")) - sru_method = "get"; - else if (!yaz_matchstr(arg, "soap")) - sru_method = "soap"; - else + int r; + r = sscanf(arg, "%9s %9s", sru_method, sru_version); + if (r >= 1) { - printf("Unknown SRU method: %s\n", arg); - printf("Specify one of POST, GET, SOAP\n"); + if (!yaz_matchstr(sru_method, "post")) + ; + else if (!yaz_matchstr(sru_method, "get")) + ; + else if (!yaz_matchstr(sru_method, "soap")) + ; + else + { + strcpy(sru_method, "soap"); + printf("Unknown SRU method: %s\n", arg); + printf("Specify one of POST, GET, SOAP\n"); + } } } return 0; @@ -2525,7 +2605,7 @@ static int cmd_find(const char *arg) { #if YAZ_HAVE_XML2 if (!conn) - cmd_open(0); + session_connect(cur_host); if (!conn) return 0; if (!send_SRW_searchRequest(arg)) @@ -2802,7 +2882,7 @@ static int cmd_show(const char *arg) { #if YAZ_HAVE_XML2 if (!conn) - cmd_open(0); + session_connect(cur_host); if (!conn) return 0; if (!send_SRW_presentRequest(arg)) @@ -2880,7 +2960,8 @@ int cmd_cancel_find(const char *arg) { return fres; } -int send_scanrequest(const char *query, int pp, int num, const char *term) +int send_scanrequest(const char *set, const char *query, + int pp, int num, const char *term) { Z_APDU *apdu = zget_APDU(out, Z_APDU_scanRequest); Z_ScanRequest *req = apdu->u.scanRequest; @@ -2926,6 +3007,18 @@ int send_scanrequest(const char *query, int pp, int num, const char *term) } yaz_pqf_destroy (pqf_parser); } + if (queryCharset && outputCharset) + { + yaz_iconv_t cd = yaz_iconv_open(queryCharset, outputCharset); + if (!cd) + { + printf("Conversion from %s to %s unsupported\n", + outputCharset, queryCharset); + return -1; + } + yaz_query_charset_convert_apt(req->termListAndStartPoint, out, cd); + yaz_iconv_close(cd); + } if (term && *term) { if (req->termListAndStartPoint->term && @@ -2945,6 +3038,11 @@ int send_scanrequest(const char *query, int pp, int num, const char *term) req->numberOfTermsRequested = # req->preferredPositionInResponse = &pp; req->stepSize = odr_intdup(out, scan_stepSize); + + if (set) + yaz_oi_set_string_oid(&req->otherInfo, out, + yaz_oid_userinfo_scan_set, 1, set); + send_apdu(apdu); return 2; } @@ -2991,13 +3089,13 @@ void display_term(Z_TermInfo *t) 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, - t->term->u.general->buf); - } else printf("Term (not general)"); + if (t->term->which == Z_Term_general) + sprintf(last_scan_line, "%.*s", t->term->u.general->len, + t->term->u.general->buf); + if (t->globalOccurrences) printf (" (%d)\n", *t->globalOccurrences); else @@ -3125,13 +3223,13 @@ int cmd_scansize(const char *arg) return 0; } -int cmd_scan(const char *arg) +static int cmd_scan_common(const char *set, const char *arg) { if (protocol == PROTO_HTTP) { #if YAZ_HAVE_XML2 if (!conn) - cmd_open(0); + session_connect(cur_host); if (!conn) return 0; if (*arg) @@ -3169,18 +3267,37 @@ int cmd_scan(const char *arg) if (*arg) { strcpy (last_scan_query, arg); - if (send_scanrequest(arg, scan_position, scan_size, 0) < 0) + if (send_scanrequest(set, arg, + scan_position, scan_size, 0) < 0) return 0; } else { - if (send_scanrequest(last_scan_query, 1, scan_size, last_scan_line) < 0) + if (send_scanrequest(set, last_scan_query, + 1, scan_size, last_scan_line) < 0) return 0; } return 2; } } +int cmd_scan(const char *arg) +{ + return cmd_scan_common(0, arg); +} + +int cmd_setscan(const char *arg) +{ + char setstring[100]; + int nor; + if (sscanf(arg, "%99s%n", setstring, &nor) < 1) + { + printf("missing set for setscan\n"); + return 0; + } + return cmd_scan_common(setstring, arg + nor); +} + int cmd_schema(const char *arg) { xfree(record_schema); @@ -3318,11 +3435,29 @@ int cmd_marccharset(const char *arg) } xfree (marcCharset); marcCharset = 0; - if (strcmp(l1, "-")) + if (strcmp(l1, "-") && strcmp(l1, "none")) marcCharset = xstrdup(l1); return 1; } +int cmd_querycharset(const char *arg) +{ + char l1[30]; + + *l1 = 0; + if (sscanf(arg, "%29s", l1) < 1) + { + printf("Query character set is `%s'\n", + queryCharset ? queryCharset: "none"); + return 1; + } + xfree (queryCharset); + queryCharset = 0; + if (strcmp(l1, "-") && strcmp(l1, "none")) + queryCharset = xstrdup(l1); + return 1; +} + int cmd_displaycharset(const char *arg) { char l1[30]; @@ -3361,11 +3496,14 @@ int cmd_negcharset(const char *arg) if (sscanf(arg, "%29s %d %d", l1, &negotiationCharsetRecords, &negotiationCharsetVersion) < 1) { - printf("Current negotiation character set is `%s'\n", + printf("Negotiation character set `%s'\n", negotiationCharset ? negotiationCharset: "none"); - printf("Records in charset %s\n", negotiationCharsetRecords ? - "yes" : "no"); - printf("Charneg version %d\n", negotiationCharsetVersion); + if (negotiationCharset) + { + printf("Records in charset %s\n", negotiationCharsetRecords ? + "yes" : "no"); + printf("Charneg version %d\n", negotiationCharsetVersion); + } } else { @@ -3382,14 +3520,15 @@ int cmd_negcharset(const char *arg) int cmd_charset(const char* arg) { - char l1[30], l2[30], l3[30]; + char l1[30], l2[30], l3[30], l4[30]; - *l1 = *l2 = *l3 = 0; - if (sscanf(arg, "%29s %29s %29s", l1, l2, l3) < 1) + *l1 = *l2 = *l3 = *l4 = '\0'; + if (sscanf(arg, "%29s %29s %29s %29s", l1, l2, l3, l4) < 1) { cmd_negcharset(""); cmd_displaycharset(""); cmd_marccharset(""); + cmd_querycharset(""); } else { @@ -3398,6 +3537,8 @@ int cmd_charset(const char* arg) cmd_displaycharset(l2); if (*l3) cmd_marccharset(l3); + if (*l4) + cmd_querycharset(l4); } return 1; } @@ -3405,7 +3546,7 @@ int cmd_charset(const char* arg) int cmd_lang(const char* arg) { if (*arg == '\0') { - printf("Current language is `%s'\n", (yazLang)?yazLang:NULL); + printf("Current language is `%s'\n", yazLang ? yazLang : "none"); return 1; } xfree (yazLang); @@ -3634,8 +3775,8 @@ int cmd_register_oid(const char* args) { }; char oname_str[101], oclass_str[101], oid_str[101]; int i; - int oidclass = CLASS_GENERAL; - int oid[OID_SIZE]; + oid_class oidclass = CLASS_GENERAL; + Odr_oid oid[OID_SIZE]; if (sscanf (args, "%100[^ ] %100[^ ] %100s", oname_str,oclass_str, oid_str) < 1) { @@ -3677,19 +3818,42 @@ int cmd_push_command(const char* arg) return 1; } -void source_rcfile(void) +void source_rc_file(const char *rc_file) { - /* Look for a $HOME/.yazclientrc and source it if it exists */ + /* If rc_file != NULL, source that. Else + Look for .yazclientrc and read it if it exists. + If it does not exist, read $HOME/.yazclientrc instead */ struct stat statbuf; - char fname[1000]; - char* homedir = getenv("HOME"); - sprintf(fname, "%.500s%s%s", homedir ? homedir : "", - homedir ? "/" : "", - ".yazclientrc"); - - if (stat(fname,&statbuf)==0) - cmd_source(fname, 0 ); + if (rc_file) + { + if (stat(rc_file, &statbuf) == 0) + cmd_source(rc_file, 0); + else + { + fprintf(stderr, "yaz_client: cannot source '%s'\n", rc_file); + exit(1); + } + } + else + { + char fname[1000]; + strcpy(fname, ".yazclientrc"); + if (stat(fname, &statbuf)==0) + { + cmd_source(fname, 0); + } + else + { + const char* homedir = getenv("HOME"); + if (homedir) + { + sprintf(fname, "%.800s/%s", homedir, ".yazclientrc"); + if (stat(fname, &statbuf)==0) + cmd_source(fname, 0); + } + } + } } void add_to_readline_history(void *client_data, const char *line) @@ -3700,7 +3864,7 @@ void add_to_readline_history(void *client_data, const char *line) #endif } -static void initialize(void) +static void initialize(const char *rc_file) { FILE *inf; int i; @@ -3729,7 +3893,8 @@ static void initialize(void) /* If this fails, no problem: we detect cqltrans == 0 later */ #if HAVE_READLINE_READLINE_H - rl_attempted_completion_function = (CPPFunction*)readline_completer; + rl_attempted_completion_function = + (char **(*)(const char *, int, int)) readline_completer; #endif for(i = 0; i < maxOtherInfosSupported; ++i) { extraOtherInfos[i].oid[0] = -1; @@ -3738,7 +3903,7 @@ static void initialize(void) cmd_format("usmarc"); - source_rcfile(); + source_rc_file(rc_file); file_history = file_history_new(); file_history_load(file_history); @@ -3846,11 +4011,11 @@ static void handle_srw_scan_response(Z_SRW_scanResponse *res) static void http_response(Z_HTTP_Response *hres) { int ret = -1; - const char *content_type = z_HTTP_header_lookup(hres->headers, - "Content-Type"); const char *connection_head = z_HTTP_header_lookup(hres->headers, "Connection"); - if (content_type && !yaz_strcmp_del("text/xml", content_type, "; ")) + if (!yaz_srw_check_content_type(hres)) + printf("Content type does not appear to be XML\n"); + else { Z_SOAP *soap_package = 0; ODR o = odr_createmem(ODR_DECODE); @@ -3864,7 +4029,7 @@ static void http_response(Z_HTTP_Response *hres) soap_handlers); if (!ret && soap_package->which == Z_SOAP_generic) { - Z_SRW_PDU *sr = soap_package->u.generic->p; + 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) @@ -3945,7 +4110,7 @@ void wait_and_handle_response(int one_response_only) { cs_close(conn); conn = 0; - cmd_open(0); + session_connect(cur_host); reconnect_ok = 0; if (conn) { @@ -4144,7 +4309,7 @@ int cmd_set_otherinfo(const char* args) else { NMEM oid_tmp = nmem_create(); - const int *oid = + const Odr_oid *oid = yaz_string_to_oid_nmem(yaz_oid_std(), CLASS_GENERAL, oidstr, oid_tmp); oid_oidcpy(extraOtherInfos[otherinfoNo].oid, oid); @@ -4187,7 +4352,7 @@ int cmd_list_otherinfo(const char* args) if (extraOtherInfos[i].value) { char name_oid[OID_STR_MAX]; - int oclass; + oid_class oclass; const char *name = yaz_oid_to_string_buf(extraOtherInfos[i].oid, &oclass, name_oid); @@ -4204,7 +4369,7 @@ int cmd_list_otherinfo(const char* args) if (extraOtherInfos[i].value) { char name_oid[OID_STR_MAX]; - int oclass; + oid_class oclass; const char *name = yaz_oid_to_string_buf(extraOtherInfos[i].oid, &oclass, name_oid); @@ -4212,7 +4377,6 @@ int cmd_list_otherinfo(const char* args) i, name ? name : "null", extraOtherInfos[i].value); } - } } return 0; @@ -4355,6 +4519,7 @@ static struct { {"delete", cmd_delete, "",NULL,0,NULL}, {"base", cmd_base, "",NULL,0,NULL}, {"show", cmd_show, "['+'<#recs>['+']]",NULL,0,NULL}, + {"setscan", cmd_setscan, "",NULL,0,NULL}, {"scan", cmd_scan, "",NULL,0,NULL}, {"scanstep", cmd_scanstep, "",NULL,0,NULL}, {"scanpos", cmd_scanpos, "",NULL,0,NULL}, @@ -4385,6 +4550,7 @@ static struct { {"negcharset", cmd_negcharset, "",NULL,0,NULL}, {"displaycharset", cmd_displaycharset, "",NULL,0,NULL}, {"marccharset", cmd_marccharset, "",NULL,0,NULL}, + {"querycharset", cmd_querycharset, "",NULL,0,NULL}, {"lang", cmd_lang, "",NULL,0,NULL}, {"source", cmd_source_echo, "",NULL,1,NULL}, {".", cmd_source_echo, "",NULL,1,NULL}, @@ -4421,7 +4587,7 @@ static struct { {"zversion", cmd_zversion, "", NULL, 0, NULL}, {"help", cmd_help, "", NULL,0,NULL}, {"init", cmd_init, "", NULL,0,NULL}, - {"sru", cmd_sru, "", NULL,0,NULL}, + {"sru", cmd_sru, " ", NULL,0,NULL}, {"exit", cmd_quit, "",NULL,0,NULL}, {0,0,0,0,0,0} }; @@ -4745,6 +4911,7 @@ int main(int argc, char **argv) char *open_command = 0; char *auth_command = 0; char *arg; + const char *rc_file = 0; int ret; #if HAVE_LOCALE_H @@ -4769,7 +4936,7 @@ int main(int argc, char **argv) ODR_MASK_SET(&z3950_options, Z_Options_delSet); ODR_MASK_SET(&z3950_options, Z_Options_negotiationModel); - while ((ret = options("k:c:q:a:b:m:v:p:u:t:Vxd:", argv, argc, &arg)) != -2) + while ((ret = options("k:c:q:a:b:m:v:p:u:t:Vxd:f:", argv, argc, &arg)) != -2) { switch (ret) { @@ -4787,9 +4954,28 @@ int main(int argc, char **argv) exit(1); } break; + case 'a': + if (!strcmp(arg, "-")) + apdu_file=stderr; + else + apdu_file=fopen(arg, "a"); + break; + case 'b': + if (!strcmp(arg, "-")) + ber_file=stderr; + else + ber_file=fopen(arg, "a"); + break; + case 'c': + strncpy (ccl_fields, arg, sizeof(ccl_fields)-1); + ccl_fields[sizeof(ccl_fields)-1] = '\0'; + break; case 'd': dump_file_prefix = arg; break; + case 'f': + rc_file = arg; + break; case 'k': kilobytes = atoi(arg); break; @@ -4800,34 +4986,15 @@ int main(int argc, char **argv) exit (1); } break; - case 't': - outputCharset = xstrdup(arg); - break; - case 'c': - strncpy (ccl_fields, arg, sizeof(ccl_fields)-1); - ccl_fields[sizeof(ccl_fields)-1] = '\0'; + case 'p': + yazProxy = xstrdup(arg); break; case 'q': strncpy (cql_fields, arg, sizeof(cql_fields)-1); cql_fields[sizeof(cql_fields)-1] = '\0'; break; - case 'b': - if (!strcmp(arg, "-")) - ber_file=stderr; - else - ber_file=fopen(arg, "a"); - break; - case 'a': - if (!strcmp(arg, "-")) - apdu_file=stderr; - else - apdu_file=fopen(arg, "a"); - break; - case 'x': - hex_dump = 1; - break; - case 'p': - yazProxy = xstrdup(arg); + case 't': + outputCharset = xstrdup(arg); break; case 'u': if (!auth_command) @@ -4843,24 +5010,31 @@ int main(int argc, char **argv) case 'V': show_version(); break; + case 'x': + hex_dump = 1; + break; default: fprintf (stderr, "Usage: %s " - " [-a ]" + " [-a apdulog]" " [-b berdump]" - " [-d dump]\n" - " [-c cclfields]" + " [-c cclfile]" + " [-d dump]" + " [-f cmdfile]" " [-k size]" - " [-m ]\n" - " [-p ]" - " [-q cqlfields]" - " [-u ]" + " [-m marclog]" + " [-p proxy-addr]" + " [-q cqlfile]" + " [-t dispcharset]" + " [-u auth]" + " [-v loglevel]" " [-V]" - " []\n", + " [-x]" + " [server-addr]\n", prog); exit (1); } } - initialize(); + initialize(rc_file); if (auth_command) { #ifdef HAVE_GETTIMEOFDAY