X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=src%2Fzoom-c.c;h=d400ece1242b1b6f1d2a928b7312957643b81609;hb=e28a34b085aa1970ff0ae49bb658e94a9a564e8a;hp=da9ca8b3e8abb7348f0c665eb105b2ee2506e54f;hpb=c6e47cbbff56f39f6d81b079ebaeac41d793d4d9;p=yaz-moved-to-github.git diff --git a/src/zoom-c.c b/src/zoom-c.c index da9ca8b..d400ece 100644 --- a/src/zoom-c.c +++ b/src/zoom-c.c @@ -2,7 +2,7 @@ * Copyright (c) 2000-2003, Index Data * See the file LICENSE for details. * - * $Id: zoom-c.c,v 1.1 2003-10-27 12:21:36 adam Exp $ + * $Id: zoom-c.c,v 1.14 2003-12-20 19:11:39 adam Exp $ * * ZOOM layer for C, connections, result sets, queries. */ @@ -544,7 +544,12 @@ ZOOM_connection_search(ZOOM_connection c, ZOOM_query q) r->start = ZOOM_options_get_int(r->options, "start", 0); r->count = ZOOM_options_get_int(r->options, "count", 0); - r->step = ZOOM_options_get_int(r->options, "step", 0); + { + /* If "presentChunk" is defined use that; otherwise "step" */ + const char *cp = ZOOM_options_get (r->options, "presentChunk"); + r->step = ZOOM_options_get_int(r->options, + (cp != 0 ? "presentChunk": "step"), 0); + } r->piggyback = ZOOM_options_get_bool (r->options, "piggyback", 1); cp = ZOOM_options_get (r->options, "setname"); if (cp) @@ -884,7 +889,6 @@ static zoom_ret send_APDU (ZOOM_connection c, Z_APDU *a) static zoom_ret ZOOM_connection_send_init (ZOOM_connection c) { - const char *impname; Z_APDU *apdu = zget_APDU(c->odr_out, Z_APDU_initRequest); Z_InitRequest *ireq = apdu->u.initRequest; Z_IdAuthentication *auth = (Z_IdAuthentication *) @@ -892,7 +896,8 @@ static zoom_ret ZOOM_connection_send_init (ZOOM_connection c) const char *auth_groupId = ZOOM_options_get (c->options, "group"); const char *auth_userId = ZOOM_options_get (c->options, "user"); const char *auth_password = ZOOM_options_get (c->options, "pass"); - + char *version; + ODR_MASK_SET(ireq->options, Z_Options_search); ODR_MASK_SET(ireq->options, Z_Options_present); ODR_MASK_SET(ireq->options, Z_Options_scan); @@ -903,18 +908,23 @@ static zoom_ret ZOOM_connection_send_init (ZOOM_connection c) ODR_MASK_SET(ireq->protocolVersion, Z_ProtocolVersion_1); ODR_MASK_SET(ireq->protocolVersion, Z_ProtocolVersion_2); ODR_MASK_SET(ireq->protocolVersion, Z_ProtocolVersion_3); - - impname = ZOOM_options_get (c->options, "implementationName"); - ireq->implementationName = - (char *) odr_malloc (c->odr_out, 15 + (impname ? strlen(impname) : 0)); - strcpy (ireq->implementationName, ""); - if (impname) - { - strcat (ireq->implementationName, impname); - strcat (ireq->implementationName, "/"); - } - strcat (ireq->implementationName, "ZOOM-C/YAZ"); - + + /* Index Data's Z39.50 Implementor Id is 81 */ + ireq->implementationId = odr_prepend(c->odr_out, + ZOOM_options_get(c->options, "implementationId"), + odr_prepend(c->odr_out, "81", ireq->implementationId)); + + ireq->implementationName = odr_prepend(c->odr_out, + ZOOM_options_get(c->options, "implementationName"), + odr_prepend(c->odr_out, "ZOOM-C", ireq->implementationName)); + + version = odr_strdup(c->odr_out, "$Revision: 1.14 $"); + if (strlen(version) > 10) /* check for unexpanded CVS strings */ + version[strlen(version)-2] = '\0'; + ireq->implementationVersion = odr_prepend(c->odr_out, + ZOOM_options_get(c->options, "implementationVersion"), + odr_prepend(c->odr_out, &version[11], ireq->implementationVersion)); + *ireq->maximumRecordSize = ZOOM_options_get_int (c->options, "maximumRecordSize", 1024*1024); *ireq->preferredMessageSize = @@ -994,7 +1004,7 @@ static zoom_ret send_srw (ZOOM_connection c, Z_SRW_PDU *sr) { 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); @@ -1025,7 +1035,7 @@ static zoom_ret send_srw (ZOOM_connection c, Z_SRW_PDU *sr) memcpy (h, cp0, cp1 - cp0); h[cp1-cp0] = '\0'; z_HTTP_header_add(c->odr_out, &gdu->u.HTTP_Request->headers, - "host", h); + "Host", h); } } @@ -1349,6 +1359,62 @@ ZOOM_record_destroy (ZOOM_record rec) xfree (rec); } +static const char *marc_iconv_return(ZOOM_record rec, int marc_type, + int *len, + const char *buf, int sz, + const char *record_charset) +{ + char to[40]; + char from[40]; + yaz_iconv_t cd = 0; + yaz_marc_t mt = yaz_marc_create(); + + *from = '\0'; + strcpy(to, "UTF-8"); + if (record_charset && *record_charset) + { + /* Use "from,to" or just "from" */ + const char *cp =strchr(record_charset, ','); + int clen = strlen(record_charset); + if (cp && cp[1]) + { + strncpy( to, cp+1, sizeof(to)-1); + to[sizeof(to)-1] = '\0'; + clen = cp - record_charset; + } + if (clen > sizeof(from)-1) + clen = sizeof(from)-1; + + if (clen) + strncpy(from, record_charset, clen); + from[clen] = '\0'; + } + + if (*from && *to) + { + cd = yaz_iconv_open(to, from); + yaz_marc_iconv(mt, cd); + } + + yaz_marc_xml(mt, marc_type); + if (!rec->wrbuf_marc) + rec->wrbuf_marc = wrbuf_alloc(); + wrbuf_rewind (rec->wrbuf_marc); + if (yaz_marc_decode_wrbuf (mt, buf, sz, rec->wrbuf_marc) > 0) + { + yaz_marc_destroy(mt); + if (cd) + yaz_iconv_close(cd); + if (len) + *len = wrbuf_len(rec->wrbuf_marc); + return wrbuf_buf(rec->wrbuf_marc); + } + yaz_marc_destroy(mt); + if (cd) + yaz_iconv_close(cd); + return 0; +} + static const char *record_iconv_return(ZOOM_record rec, int *len, const char *buf, int sz, const char *record_charset) @@ -1481,8 +1547,11 @@ ZOOM_record_get (ZOOM_record rec, const char *type_spec, int *len) *len = strlen(desc); return desc; } - else if (!strcmp (type, "render") && - npr->which == Z_NamePlusRecord_databaseRecord) + if (npr->which != Z_NamePlusRecord_databaseRecord) + return 0; + + /* from now on - we have a database record .. */ + if (!strcmp (type, "render")) { Z_External *r = (Z_External *) npr->u.databaseRecord; oident *ent = oid_getentbyoid(r->direct_reference); @@ -1502,6 +1571,7 @@ ZOOM_record_get (ZOOM_record rec, const char *type_spec, int *len) else if (r->which == Z_External_octet) { yaz_marc_t mt; + const char *ret_buf; switch (ent->value) { case VAL_SOIF: @@ -1512,23 +1582,13 @@ ZOOM_record_get (ZOOM_record rec, const char *type_spec, int *len) case VAL_APPLICATION_XML: break; default: - if (!rec->wrbuf_marc) - rec->wrbuf_marc = wrbuf_alloc(); - - mt = yaz_marc_create(); - wrbuf_rewind (rec->wrbuf_marc); - if (yaz_marc_decode_wrbuf ( - mt, (const char *) r->u.octet_aligned->buf, - r->u.octet_aligned->len, - rec->wrbuf_marc) > 0) - { - yaz_marc_destroy(mt); - return record_iconv_return(rec, len, - wrbuf_buf(rec->wrbuf_marc), - wrbuf_len(rec->wrbuf_marc), - charset); - } - yaz_marc_destroy(mt); + ret_buf = marc_iconv_return( + rec, YAZ_MARC_LINE, len, + (const char *) r->u.octet_aligned->buf, + r->u.octet_aligned->len, + charset); + if (ret_buf) + return ret_buf; } return record_iconv_return(rec, len, (const char *) r->u.octet_aligned->buf, @@ -1548,8 +1608,7 @@ ZOOM_record_get (ZOOM_record rec, const char *type_spec, int *len) } return 0; } - else if (npr->which == Z_NamePlusRecord_databaseRecord && - (!strcmp (type, "xml") || !strcmp(type, "oai"))) + else if (!strcmp (type, "xml") || !strcmp(type, "oai")) { Z_External *r = (Z_External *) npr->u.databaseRecord; oident *ent = oid_getentbyoid(r->direct_reference); @@ -1570,6 +1629,7 @@ ZOOM_record_get (ZOOM_record rec, const char *type_spec, int *len) charset); else if (r->which == Z_External_octet) { + const char *ret_buf; yaz_marc_t mt; int marc_decode_type = YAZ_MARC_MARCXML; @@ -1585,24 +1645,13 @@ ZOOM_record_get (ZOOM_record rec, const char *type_spec, int *len) case VAL_APPLICATION_XML: break; default: - if (!rec->wrbuf_marc) - rec->wrbuf_marc = wrbuf_alloc(); - wrbuf_rewind (rec->wrbuf_marc); - mt = yaz_marc_create(); - - yaz_marc_xml(mt, YAZ_MARC_MARCXML); - if (yaz_marc_decode_wrbuf ( - mt, (const char *) r->u.octet_aligned->buf, - r->u.octet_aligned->len, - rec->wrbuf_marc) > 0) - { - yaz_marc_destroy(mt); - return record_iconv_return(rec, len, - wrbuf_buf(rec->wrbuf_marc), - wrbuf_len(rec->wrbuf_marc), - charset); - } - yaz_marc_destroy(mt); + ret_buf = marc_iconv_return( + rec, marc_decode_type, len, + (const char *) r->u.octet_aligned->buf, + r->u.octet_aligned->len, + charset); + if (ret_buf) + return ret_buf; } return record_iconv_return(rec, len, (const char *) r->u.octet_aligned->buf, @@ -1618,36 +1667,31 @@ ZOOM_record_get (ZOOM_record rec, const char *type_spec, int *len) } else if (!strcmp (type, "raw")) { - if (npr->which == Z_NamePlusRecord_databaseRecord) + Z_External *r = (Z_External *) npr->u.databaseRecord; + + if (r->which == Z_External_sutrs) { - Z_External *r = (Z_External *) npr->u.databaseRecord; - - if (r->which == Z_External_sutrs) - { - if (len) *len = r->u.sutrs->len; - return (const char *) r->u.sutrs->buf; - } - else if (r->which == Z_External_octet) - { - if (len) *len = r->u.octet_aligned->len; - return (const char *) r->u.octet_aligned->buf; - } - else /* grs-1, explain, OPAC, ... */ - { - if (len) *len = -1; - return (const char *) npr->u.databaseRecord; - } + if (len) *len = r->u.sutrs->len; + return (const char *) r->u.sutrs->buf; + } + else if (r->which == Z_External_octet) + { + if (len) *len = r->u.octet_aligned->len; + return (const char *) r->u.octet_aligned->buf; + } + else /* grs-1, explain, OPAC, ... */ + { + if (len) *len = -1; + return (const char *) npr->u.databaseRecord; } return 0; } else if (!strcmp (type, "ext")) { - if (npr->which == Z_NamePlusRecord_databaseRecord) - return (const char *) npr->u.databaseRecord; - return 0; + if (len) *len = -1; + return (const char *) npr->u.databaseRecord; } - else if (npr->which == Z_NamePlusRecord_databaseRecord && - !strcmp (type, "opac")) + else if (!strcmp (type, "opac")) { Z_External *r = (Z_External *) npr->u.databaseRecord; @@ -2127,7 +2171,7 @@ ZOOM_scanset_size (ZOOM_scanset scan) ZOOM_API(const char *) ZOOM_scanset_term (ZOOM_scanset scan, size_t pos, - int *occ, int *len) + int *occ, int *len) { const char *term = 0; size_t noent = ZOOM_scanset_size (scan); @@ -2152,6 +2196,37 @@ ZOOM_scanset_term (ZOOM_scanset scan, size_t pos, } ZOOM_API(const char *) +ZOOM_scanset_display_term (ZOOM_scanset scan, size_t pos, + int *occ, int *len) +{ + const char *term = 0; + size_t noent = ZOOM_scanset_size (scan); + Z_ScanResponse *res = scan->scan_response; + + *len = 0; + *occ = 0; + if (pos >= noent) + return 0; + if (res->entries->entries[pos]->which == Z_Entry_termInfo) + { + Z_TermInfo *t = res->entries->entries[pos]->u.termInfo; + + if (t->displayTerm) + { + term = (const char *) t->term->u.general->buf; + *len = strlen(term); + } + else if (t->term->which == Z_Term_general) + { + term = (const char *) t->term->u.general->buf; + *len = t->term->u.general->len; + } + *occ = t->globalOccurrences ? *t->globalOccurrences : 0; + } + return term; +} + +ZOOM_API(const char *) ZOOM_scanset_option_get (ZOOM_scanset scan, const char *key) { return ZOOM_options_get (scan->options, key); @@ -2309,6 +2384,167 @@ static Z_ItemOrder *encode_item_order(ZOOM_package p) return req; } +Z_APDU *create_admin_package(ZOOM_package p, int type, + Z_ESAdminOriginPartToKeep **toKeepP, + Z_ESAdminOriginPartNotToKeep **notToKeepP) +{ + Z_APDU *apdu = create_es_package (p, VAL_ADMINSERVICE); + if (apdu) + { + Z_ESAdminOriginPartToKeep *toKeep; + Z_ESAdminOriginPartNotToKeep *notToKeep; + Z_External *r = (Z_External *) odr_malloc (p->odr_out, sizeof(*r)); + const char *first_db = "Default"; + int num_db; + char **db = set_DatabaseNames(p->connection, p->options, &num_db); + if (num_db > 0) + first_db = db[0]; + + r->direct_reference = + yaz_oidval_to_z3950oid(p->odr_out, CLASS_EXTSERV, + VAL_ADMINSERVICE); + r->descriptor = 0; + r->indirect_reference = 0; + r->which = Z_External_ESAdmin; + + r->u.adminService = (Z_Admin *) + odr_malloc(p->odr_out, sizeof(*r->u.adminService)); + r->u.adminService->which = Z_Admin_esRequest; + r->u.adminService->u.esRequest = (Z_AdminEsRequest *) + odr_malloc(p->odr_out, sizeof(*r->u.adminService->u.esRequest)); + + toKeep = r->u.adminService->u.esRequest->toKeep = + (Z_ESAdminOriginPartToKeep *) + odr_malloc(p->odr_out, sizeof(*r->u.adminService->u.esRequest->toKeep)); + toKeep->which=type; + toKeep->databaseName = odr_strdup(p->odr_out, first_db); + toKeep->u.create=odr_nullval(); + apdu->u.extendedServicesRequest->taskSpecificParameters = r; + + r->u.adminService->u.esRequest->notToKeep = notToKeep = + (Z_ESAdminOriginPartNotToKeep *) + odr_malloc(p->odr_out, + sizeof(*r->u.adminService->u.esRequest->notToKeep)); + notToKeep->which=Z_ESAdminOriginPartNotToKeep_recordsWillFollow; + notToKeep->u.recordsWillFollow=odr_nullval(); + if (toKeepP) + *toKeepP = toKeep; + if (notToKeepP) + *notToKeepP = notToKeep; + } + return apdu; +} + +static Z_APDU *create_update_package(ZOOM_package p) +{ + Z_APDU *apdu = 0; + const char *first_db = "Default"; + int num_db; + char **db = set_DatabaseNames(p->connection, p->options, &num_db); + const char *action = ZOOM_options_get(p->options, "action"); + const char *recordId = ZOOM_options_get(p->options, "recordId"); + const char *record_buf = ZOOM_options_get(p->options, "record"); + const char *syntax_str = ZOOM_options_get(p->options, "syntax"); + int syntax_oid = VAL_NONE; + int action_no = -1; + + if (syntax_str) + syntax_oid = oid_getvalbyname(syntax_str); + if (!record_buf) + { + record_buf = "void"; + syntax_oid = VAL_SUTRS; + } + if (syntax_oid != VAL_NONE) + syntax_oid = VAL_TEXT_XML; + + if (num_db > 0) + first_db = db[0]; + + if (!action) + action = "specialUpdate"; + + if (!strcmp(action, "recordInsert")) + action_no = Z_IUOriginPartToKeep_recordInsert; + else if (!strcmp(action, "recordReplace")) + action_no = Z_IUOriginPartToKeep_recordReplace; + else if (!strcmp(action, "recordDelete")) + action_no = Z_IUOriginPartToKeep_recordDelete; + else if (!strcmp(action, "elementUpdate")) + action_no = Z_IUOriginPartToKeep_elementUpdate; + else if (!strcmp(action, "specialUpdate")) + action_no = Z_IUOriginPartToKeep_specialUpdate; + else + return 0; + + apdu = create_es_package (p, VAL_DBUPDATE); + if (apdu) + { + Z_IUOriginPartToKeep *toKeep; + Z_IUSuppliedRecords *notToKeep; + Z_External *r = (Z_External *) + odr_malloc (p->odr_out, sizeof(*r)); + + apdu->u.extendedServicesRequest->taskSpecificParameters = r; + + r->direct_reference = + yaz_oidval_to_z3950oid(p->odr_out, CLASS_EXTSERV, + VAL_DBUPDATE); + r->descriptor = 0; + r->which = Z_External_update; + r->indirect_reference = 0; + r->u.update = (Z_IUUpdate *) + odr_malloc(p->odr_out, sizeof(*r->u.update)); + + r->u.update->which = Z_IUUpdate_esRequest; + r->u.update->u.esRequest = (Z_IUUpdateEsRequest *) + odr_malloc(p->odr_out, sizeof(*r->u.update->u.esRequest)); + toKeep = r->u.update->u.esRequest->toKeep = + (Z_IUOriginPartToKeep *) + odr_malloc(p->odr_out, sizeof(*toKeep)); + + toKeep->databaseName = odr_strdup(p->odr_out, first_db); + toKeep->schema = 0; + toKeep->elementSetName = 0; + toKeep->actionQualifier = 0; + toKeep->action = odr_intdup(p->odr_out, action_no); + + notToKeep = r->u.update->u.esRequest->notToKeep = + (Z_IUSuppliedRecords *) + odr_malloc(p->odr_out, sizeof(*notToKeep)); + notToKeep->num = 1; + notToKeep->elements = (Z_IUSuppliedRecords_elem **) + odr_malloc(p->odr_out, sizeof(*notToKeep->elements)); + notToKeep->elements[0] = (Z_IUSuppliedRecords_elem *) + odr_malloc(p->odr_out, sizeof(**notToKeep->elements)); + notToKeep->elements[0]->which = Z_IUSuppliedRecords_elem_opaque; + if (recordId) + { + notToKeep->elements[0]->u.opaque = (Odr_oct *) + odr_malloc (p->odr_out, sizeof(Odr_oct)); + notToKeep->elements[0]->u.opaque->size = strlen(recordId); + notToKeep->elements[0]->u.opaque->len = strlen(recordId); + notToKeep->elements[0]->u.opaque->buf = + odr_strdup(p->odr_out, recordId); + } + else + notToKeep->elements[0]->u.opaque = 0; + notToKeep->elements[0]->supplementalId = 0; + notToKeep->elements[0]->correlationInfo = 0; + notToKeep->elements[0]->record = + z_ext_record(p->odr_out, syntax_oid, + record_buf, strlen(record_buf)); + } + if (0 && apdu) + { + ODR print = odr_createmem(ODR_PRINT); + + z_APDU(print, &apdu, 0, 0); + odr_destroy(print); + } + return apdu; +} + ZOOM_API(void) ZOOM_package_send (ZOOM_package p, const char *type) { @@ -2322,11 +2558,10 @@ ZOOM_API(void) p->buf_out = 0; if (!strcmp(type, "itemorder")) { - Z_External *r; apdu = create_es_package (p, VAL_ITEMORDER); if (apdu) { - r = (Z_External *) odr_malloc (p->odr_out, sizeof(*r)); + Z_External *r = (Z_External *) odr_malloc (p->odr_out, sizeof(*r)); r->direct_reference = yaz_oidval_to_z3950oid(p->odr_out, CLASS_EXTSERV, @@ -2339,6 +2574,20 @@ ZOOM_API(void) apdu->u.extendedServicesRequest->taskSpecificParameters = r; } } + if (!strcmp(type, "create")) /* create database */ + { + apdu = create_admin_package(p, Z_ESAdminOriginPartToKeep_create, + 0, 0); + } + if (!strcmp(type, "drop")) /* drop database */ + { + apdu = create_admin_package(p, Z_ESAdminOriginPartToKeep_drop, + 0, 0); + } + if (!strcmp(type, "update")) /* update record(s) */ + { + apdu = create_update_package(p); + } if (apdu) { if (encode_APDU(p->connection, apdu, p->odr_out) == 0) @@ -2511,6 +2760,16 @@ static void handle_apdu (ZOOM_connection c, Z_APDU *apdu) { case Z_APDU_initResponse: initrs = apdu->u.initResponse; + ZOOM_connection_option_set(c, "serverImplementationId", + initrs->implementationId ? + initrs->implementationId : ""); + ZOOM_connection_option_set(c, "serverImplementationName", + initrs->implementationName ? + initrs->implementationName : ""); + ZOOM_connection_option_set(c, "serverImplementationVersion", + initrs->implementationVersion ? + initrs->implementationVersion : ""); + /* Set the three old options too, for old applications */ ZOOM_connection_option_set(c, "targetImplementationId", initrs->implementationId ? initrs->implementationId : ""); @@ -2694,9 +2953,9 @@ static void handle_http(ZOOM_connection c, Z_HTTP_Response *hres) if (content_type && !yaz_strcmp_del("text/xml", content_type, "; ")) { Z_SOAP *soap_package = 0; - ODR o = odr_createmem(ODR_DECODE); + ODR o = c->odr_in; 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} }; @@ -2721,7 +2980,6 @@ static void handle_http(ZOOM_connection c, Z_HTTP_Response *hres) } else ret = -1; - odr_destroy(o); } if (ret) { @@ -2755,7 +3013,6 @@ static int do_read (ZOOM_connection c) event = ZOOM_Event_create (ZOOM_EVENT_RECV_DATA); ZOOM_connection_put_event (c, event); - r = cs_get (c->cs, &c->buf_in, &c->len_in); more = cs_more(c->cs); yaz_log (LOG_DEBUG, "do_read len=%d more=%d", r, more); @@ -2789,7 +3046,13 @@ static int do_read (ZOOM_connection c) if (!z_GDU (c->odr_in, &gdu, 0, 0)) { - set_ZOOM_error(c, ZOOM_ERROR_DECODE, 0); + int x; + int err = odr_geterrorx(c->odr_in, &x); + char msg[60]; + const char *element = odr_getelement(c->odr_in); + sprintf (msg, "ODR code %d:%d element=%-20s", + err, x, element ? element : ""); + set_ZOOM_error(c, ZOOM_ERROR_DECODE, msg); do_close (c); } else if (gdu->which == Z_GDU_Z3950)