/*
- * Copyright (c) 2000-2003, Index Data
+ * Copyright (c) 2000-2004, Index Data
* See the file LICENSE for details.
*
- * $Id: zoom-c.c,v 1.6 2003-11-25 09:50:35 mike Exp $
+ * $Id: zoom-c.c,v 1.18 2004-01-12 12:10:17 adam Exp $
*
* ZOOM layer for C, connections, result sets, queries.
*/
static zoom_ret ZOOM_connection_send_init (ZOOM_connection c)
{
- const char *impid, *impname, *impver;
Z_APDU *apdu = zget_APDU(c->odr_out, Z_APDU_initRequest);
Z_InitRequest *ireq = apdu->u.initRequest;
Z_IdAuthentication *auth = (Z_IdAuthentication *)
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);
ODR_MASK_SET(ireq->protocolVersion, Z_ProtocolVersion_1);
ODR_MASK_SET(ireq->protocolVersion, Z_ProtocolVersion_2);
ODR_MASK_SET(ireq->protocolVersion, Z_ProtocolVersion_3);
-
- impid = ZOOM_options_get (c->options, "implementationId");
- ireq->implementationId =
- (char *) odr_malloc (c->odr_out, 15 + (impid ? strlen(impid) : 0));
- strcpy (ireq->implementationId, "");
- if (impid)
- {
- strcat (ireq->implementationId, impid);
- strcat (ireq->implementationId, "/");
- }
- strcat (ireq->implementationId, "81"); /* Index's implementor ID */
-
- 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");
-
- impver = ZOOM_options_get (c->options, "implementationVersion");
- ireq->implementationVersion =
- (char *) odr_malloc (c->odr_out, strlen("$Revision: 1.6 $") + 2 +
- (impver ? strlen(impver) : 0));
- strcpy (ireq->implementationVersion, "");
- if (impver)
- {
- strcat (ireq->implementationVersion, impver);
- strcat (ireq->implementationVersion, "/");
- }
- strcat (ireq->implementationVersion, "$Revision: 1.6 $");
+
+ /* 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.18 $");
+ 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);
{
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);
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)
{
char type[40];
char charset[40];
+ char xpath[512];
const char *cp;
int i;
Z_NamePlusRecord *npr;
}
type[i] = '\0';
charset[0] = '\0';
- if (type_spec[i] == ';')
+ while (type_spec[i] == ';')
{
i++;
while (type_spec[i] == ' ')
}
charset[i] = '\0';
}
- }
-
+ else if (!strncmp(type_spec+i, "xpath=", 6))
+ {
+ cp = type_spec+i+6;
+ for (i = 0; cp[i] && i < sizeof(xpath)-1; i++)
+ xpath[i] = cp[i];
+ xpath[i] = '\0';
+ }
+ while (type_spec[i] == ' ')
+ i++;
+ }
if (!strcmp (type, "database"))
{
if (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);
charset);
else if (r->which == Z_External_octet)
{
- yaz_marc_t mt;
+ const char *ret_buf;
switch (ent->value)
{
case VAL_SOIF:
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,
}
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);
charset);
else if (r->which == Z_External_octet)
{
- yaz_marc_t mt;
+ const char *ret_buf;
int marc_decode_type = YAZ_MARC_MARCXML;
if (!strcmp(type, "oai"))
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,
}
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;
if (t->displayTerm)
{
- term = (const char *) t->term->u.general->buf;
+ term = t->displayTerm;
*len = strlen(term);
}
else if (t->term->which == Z_Term_general)
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)
{
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,
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)
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}
};
}
else
ret = -1;
- odr_destroy(o);
}
if (ret)
{
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);
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 : "<unknown>");
+ set_ZOOM_error(c, ZOOM_ERROR_DECODE, msg);
do_close (c);
}
else if (gdu->which == Z_GDU_Z3950)