X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=src%2Fzoom-c.c;h=c05e51ca97796e7f3a88dd37413b65ae43f0fa82;hb=2b8a6e970b5ed4182a67d423ba4ba5dc74ffc6bb;hp=30be6ba34b1aa4dcf77208e0c071f2a48dba10f9;hpb=28f52a57a140e602427fe10c3cc4309d23433e2c;p=yaz-moved-to-github.git diff --git a/src/zoom-c.c b/src/zoom-c.c index 30be6ba..c05e51c 100644 --- a/src/zoom-c.c +++ b/src/zoom-c.c @@ -2,7 +2,7 @@ * Copyright (C) 1995-2005, Index Data ApS * See the file LICENSE for details. * - * $Id: zoom-c.c,v 1.60 2005-12-21 00:07:21 mike Exp $ + * $Id: zoom-c.c,v 1.70 2006-04-21 10:28:07 adam Exp $ */ /** * \file zoom-c.c @@ -54,7 +54,6 @@ static zoom_ret ZOOM_connection_send_init (ZOOM_connection c); static zoom_ret do_write_ex (ZOOM_connection c, char *buf_out, int len_out); static char *cql2pqf(ZOOM_connection c, const char *cql); - static void initlog() { static int log_level_initialized = 0; @@ -167,7 +166,13 @@ static void set_ZOOM_error (ZOOM_connection c, int error, static void clear_error (ZOOM_connection c) { - + /* + * If an error is tied to an operation then it's ok to clear: for + * example, a diagnostic returned from a search is cleared by a + * subsequent search. However, problems such as Connection Lost + * or Init Refused are not cleared, because they are not + * recoverable: doing another search doesn't help. + */ switch (c->error) { case ZOOM_ERROR_CONNECT: @@ -240,6 +245,12 @@ void ZOOM_connection_remove_task (ZOOM_connection c) assert (0); } xfree (task); + + if (!c->tasks) + { + ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_END); + ZOOM_connection_put_event(c, event); + } } } @@ -309,7 +320,7 @@ static char **set_DatabaseNames (ZOOM_connection con, ZOOM_options options, char **databaseNames; const char *cp = ZOOM_options_get (options, "databaseName"); - if (!cp || !*cp) + if ((!cp || !*cp) && con->host_port) { if (strncmp (con->host_port, "unix:", 5) == 0) cp = strchr(con->host_port+5, ':'); @@ -333,6 +344,19 @@ ZOOM_connection_new (const char *host, int portnum) return c; } +static zoom_sru_mode get_sru_mode_from_string(const char *s) +{ + if (!s || !*s) + return zoom_sru_soap; + if (!yaz_matchstr(s, "soap")) + return zoom_sru_soap; + else if (!yaz_matchstr(s, "get")) + return zoom_sru_get; + else if (!yaz_matchstr(s, "post")) + return zoom_sru_post; + return zoom_sru_error; +} + ZOOM_API(void) ZOOM_connection_connect(ZOOM_connection c, const char *host, int portnum) @@ -382,6 +406,9 @@ ZOOM_connection_connect(ZOOM_connection c, else c->lang = 0; + val = ZOOM_options_get (c->options, "sru"); + c->sru_mode = get_sru_mode_from_string(val); + xfree (c->host_port); if (portnum) { @@ -524,6 +551,31 @@ ZOOM_query_cql(ZOOM_query s, const char *str) return 0; } +/* + * Translate the CQL string client-side into RPN which is passed to + * the server. This is useful for server's that don't themselves + * support CQL, for which ZOOM_query_cql() is useless. `conn' is used + * only as a place to stash diagnostics if compilation fails; if this + * information is not needed, a null pointer may be used. + */ +ZOOM_API(int) +ZOOM_query_cql2rpn(ZOOM_query s, const char *str, ZOOM_connection conn) +{ + char *rpn; + int ret; + + yaz_log(log_details, "%p ZOOM_query_cql2rpn str=%s conn=%p", s, str, conn); + if (conn == 0) + conn = ZOOM_connection_create(0); + + if ((rpn = cql2pqf(conn, str)) == 0) + return -1; + + ret = ZOOM_query_prefix(s, rpn); + xfree(rpn); + return ret; +} + ZOOM_API(int) ZOOM_query_sortby(ZOOM_query s, const char *criteria) { @@ -866,8 +918,8 @@ ZOOM_resultset_records (ZOOM_resultset r, ZOOM_record *recs, if (!r) return ; - yaz_log(log_api, "%p ZOOM_resultset_records r=%p start=%d count=%d", - r, r, start, count); + yaz_log(log_api, "%p ZOOM_resultset_records r=%p start=%ld count=%ld", + r, r, (long) start, (long) count); if (count && recs) force_present = 1; ZOOM_resultset_retrieve (r, force_present, start, count); @@ -1098,7 +1150,7 @@ static zoom_ret ZOOM_connection_send_init (ZOOM_connection c) ZOOM_options_get(c->options, "implementationName"), odr_prepend(c->odr_out, "ZOOM-C", ireq->implementationName)); - version = odr_strdup(c->odr_out, "$Revision: 1.60 $"); + version = odr_strdup(c->odr_out, "$Revision: 1.70 $"); if (strlen(version) > 10) /* check for unexpanded CVS strings */ version[strlen(version)-2] = '\0'; ireq->implementationVersion = odr_prepend(c->odr_out, @@ -1165,26 +1217,11 @@ static zoom_ret ZOOM_connection_send_init (ZOOM_connection c) if ((oi_unit = yaz_oi_update(oi, c->odr_out, NULL, 0, 0))) { - char **charsets_addresses = 0; - char **langs_addresses = 0; - int charsets_count = 0; - int langs_count = 0; - - if (c->charset) - nmem_strsplit_blank(c->odr_out->mem, c->charset, - &charsets_addresses, &charsets_count); - if (c->lang) - nmem_strsplit_blank(c->odr_out->mem, c->lang, - &langs_addresses, &langs_count); ODR_MASK_SET(ireq->options, Z_Options_negotiationModel); oi_unit->which = Z_OtherInfo_externallyDefinedInfo; oi_unit->information.externallyDefinedInfo = - yaz_set_proposal_charneg(c->odr_out, - (const char **) charsets_addresses, - charsets_count, - (const char **) langs_addresses, - langs_count, - 1); + yaz_set_proposal_charneg_list(c->odr_out, " ", + c->charset, c->lang, 1); } } assert (apdu); @@ -1194,7 +1231,6 @@ static zoom_ret ZOOM_connection_send_init (ZOOM_connection c) #if HAVE_XML2 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/", 0, (Z_SOAP_fun) yaz_srw_codec}, {0, 0, 0} @@ -1231,34 +1267,40 @@ static zoom_ret send_srw (ZOOM_connection c, Z_SRW_PDU *sr) } } - strcpy(ctype, "text/xml"); - if (c->charset && strlen(c->charset) < 20) + if (c->sru_mode == zoom_sru_get) + { + yaz_sru_get_encode(gdu->u.HTTP_Request, sr, c->odr_out, c->charset); + } + else if (c->sru_mode == zoom_sru_post) { - strcat(ctype, "; charset="); - strcat(ctype, c->charset); + yaz_sru_post_encode(gdu->u.HTTP_Request, sr, c->odr_out, c->charset); } - z_HTTP_header_add(c->odr_out, &gdu->u.HTTP_Request->headers, - "Content-Type", ctype); - z_HTTP_header_add(c->odr_out, &gdu->u.HTTP_Request->headers, - "SOAPAction", "\"\""); - p->which = Z_SOAP_generic; - p->u.generic = (Z_SOAP_Generic *) odr_malloc(o, sizeof(*p->u.generic)); - p->u.generic->no = 0; - p->u.generic->ns = 0; - p->u.generic->p = sr; - p->ns = "http://schemas.xmlsoap.org/soap/envelope/"; + else if (c->sru_mode == zoom_sru_soap) + { + z_HTTP_header_add_content_type(c->odr_out, + &gdu->u.HTTP_Request->headers, + "text/xml", c->charset); - ret = z_soap_codec_enc(o, &p, - &gdu->u.HTTP_Request->content_buf, - &gdu->u.HTTP_Request->content_len, h, - c->charset); + z_HTTP_header_add(c->odr_out, &gdu->u.HTTP_Request->headers, + "SOAPAction", "\"\""); + p->which = Z_SOAP_generic; + p->u.generic = (Z_SOAP_Generic *) odr_malloc(o, sizeof(*p->u.generic)); + p->u.generic->no = 0; + p->u.generic->ns = 0; + p->u.generic->p = sr; + p->ns = "http://schemas.xmlsoap.org/soap/envelope/"; + + ret = z_soap_codec_enc(o, &p, + &gdu->u.HTTP_Request->content_buf, + &gdu->u.HTTP_Request->content_len, h, + c->charset); + } if (!z_GDU(c->odr_out, &gdu, 0, 0)) return zoom_complete; c->buf_out = odr_getbuf(c->odr_out, &c->len_out, 0); - odr_destroy(o); - + event = ZOOM_Event_create (ZOOM_EVENT_SEND_APDU); ZOOM_connection_put_event (c, event); odr_reset(c->odr_out); @@ -1823,7 +1865,7 @@ ZOOM_record_get (ZOOM_record rec, const char *type_spec, int *len) } return 0; } - else if (!strcmp (type, "xml") || !strcmp(type, "oai")) + else if (!strcmp (type, "xml")) { Z_External *r = (Z_External *) npr->u.databaseRecord; oident *ent = oid_getentbyoid(r->direct_reference); @@ -1847,8 +1889,6 @@ ZOOM_record_get (ZOOM_record rec, const char *type_spec, int *len) const char *ret_buf; int marc_decode_type = YAZ_MARC_MARCXML; - if (!strcmp(type, "oai")) - marc_decode_type = YAZ_MARC_OAIMARC; switch (ent->value) { case VAL_SOIF: @@ -2332,9 +2372,10 @@ static zoom_ret send_present(ZOOM_connection c) *req->resultSetStartPoint = resultset->start + 1; *req->numberOfRecordsRequested = resultset->step>0 ? resultset->step : resultset->count; + if (*req->numberOfRecordsRequested + resultset->start > resultset->size) + *req->numberOfRecordsRequested = resultset->size - resultset->start; assert (*req->numberOfRecordsRequested > 0); - if (syntax && *syntax) req->preferredRecordSyntax = yaz_str_to_z3950oid (c->odr_out, CLASS_RECSYN, syntax); @@ -2684,13 +2725,10 @@ static Z_External *encode_ill_request (ZOOM_package p) r->descriptor = 0; r->which = Z_External_single; - r->u.single_ASN1_type = (Odr_oct *) - odr_malloc (out, sizeof(*r->u.single_ASN1_type)); - r->u.single_ASN1_type->buf = (unsigned char*) - odr_malloc (out, illRequest_size); - r->u.single_ASN1_type->len = illRequest_size; - r->u.single_ASN1_type->size = illRequest_size; - memcpy (r->u.single_ASN1_type->buf, illRequest_buf, illRequest_size); + r->u.single_ASN1_type = + odr_create_Odr_oct(out, + (unsigned char *)illRequest_buf, + illRequest_size); } return r; } @@ -2812,20 +2850,18 @@ static Z_APDU *create_xmlupdate_package(ZOOM_package p) Z_External *ext = (Z_External *) odr_malloc(p->odr_out, sizeof(*ext)); const char *doc = ZOOM_options_get(p->options, "doc"); + if (!doc) + doc = ""; + req->taskSpecificParameters = ext; ext->direct_reference = req->packageType; ext->descriptor = 0; ext->indirect_reference = 0; ext->which = Z_External_octet; - ext->u.single_ASN1_type = (Odr_oct *) - odr_malloc (p->odr_out, sizeof(Odr_oct)); - - if (!doc) - doc = ""; - ext->u.single_ASN1_type->buf = (unsigned char*) - odr_strdup(p->odr_out, doc); - ext->u.single_ASN1_type->size = ext->u.single_ASN1_type->len = strlen(doc); + ext->u.single_ASN1_type = + odr_create_Odr_oct(p->odr_out, (const unsigned char *) doc, + strlen(doc)); return apdu; } @@ -2915,12 +2951,10 @@ static Z_APDU *create_update_package(ZOOM_package p) notToKeep->elements[0]->which = Z_IUSuppliedRecords_elem_opaque; if (recordIdOpaque) { - notToKeep->elements[0]->u.opaque = (Odr_oct *) - odr_malloc (p->odr_out, sizeof(Odr_oct)); - notToKeep->elements[0]->u.opaque->size = - notToKeep->elements[0]->u.opaque->len = strlen(recordIdOpaque); - notToKeep->elements[0]->u.opaque->buf = (unsigned char*) - odr_strdup(p->odr_out, recordIdOpaque); + notToKeep->elements[0]->u.opaque = + odr_create_Odr_oct(p->odr_out, + (const unsigned char *) recordIdOpaque, + strlen(recordIdOpaque)); } else if (recordIdNumber) { @@ -3393,6 +3427,7 @@ static void handle_srw_response(ZOOM_connection c, npr->u.databaseRecord->direct_reference = yaz_oidval_to_z3950oid(c->odr_in, CLASS_RECSYN, VAL_TEXT_XML); npr->u.databaseRecord->which = Z_External_octet; + npr->u.databaseRecord->u.octet_aligned = (Odr_oct *) odr_malloc(c->odr_in, sizeof(Odr_oct)); npr->u.databaseRecord->u.octet_aligned->buf = (unsigned char*)