- char type[40];
- char charset[40];
- char xpath[512];
- const char *cp;
- int i;
- Z_NamePlusRecord *npr;
-
- if (len)
- *len = 0; /* default return */
-
- if (!rec)
- return 0;
- npr = rec->npr;
- if (!npr)
- return 0;
-
- cp = type_spec;
- for (i = 0; cp[i] && i < sizeof(type)-1; i++)
- {
- if (cp[i] == ';' || cp[i] == ' ')
- break;
- type[i] = cp[i];
- }
- type[i] = '\0';
- charset[0] = '\0';
- while (type_spec[i] == ';')
- {
- i++;
- while (type_spec[i] == ' ')
- i++;
- if (!strncmp(type_spec+i, "charset=", 8))
- {
- int j = 0;
- i = i + 8; /* skip charset= */
- for (j = 0; type_spec[i] && j < sizeof(charset)-1; i++, j++)
- {
- if (type_spec[i] == ';' || type_spec[i] == ' ')
- break;
- charset[j] = cp[i];
- }
- charset[j] = '\0';
- }
- else if (!strncmp(type_spec+i, "xpath=", 6))
- {
- int j = 0;
- i = i + 6;
- for (j = 0; type_spec[i] && j < sizeof(xpath)-1; i++, j++)
- xpath[j] = cp[i];
- xpath[j] = '\0';
- }
- while (type_spec[i] == ' ')
- i++;
- }
- if (!strcmp(type, "database"))
- {
- if (len)
- *len = (npr->databaseName ? strlen(npr->databaseName) : 0);
- return npr->databaseName;
- }
- else if (!strcmp(type, "syntax"))
- {
- const char *desc = 0;
- if (npr->which == Z_NamePlusRecord_databaseRecord)
- {
- Z_External *r = (Z_External *) npr->u.databaseRecord;
- desc = yaz_oid_to_string(yaz_oid_std(), r->direct_reference, 0);
- }
- if (!desc)
- desc = "none";
- if (len)
- *len = strlen(desc);
- return desc;
- }
- 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;
- const Odr_oid *oid = r->direct_reference;
-
- /* render bibliographic record .. */
- if (r->which == Z_External_OPAC)
- {
- r = r->u.opac->bibliographicRecord;
- if (!r)
- return 0;
- oid = r->direct_reference;
- }
- if (r->which == Z_External_sutrs)
- return record_iconv_return(rec, len,
- (char*) r->u.sutrs->buf,
- r->u.sutrs->len,
- charset);
- else if (r->which == Z_External_octet)
- {
- if (yaz_oid_is_iso2709(oid))
- {
- const char *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,
- r->u.octet_aligned->len,
- charset);
- }
- else if (r->which == Z_External_grs1)
- {
- if (!rec->wrbuf_marc)
- rec->wrbuf_marc = wrbuf_alloc();
- wrbuf_rewind(rec->wrbuf_marc);
- yaz_display_grs1(rec->wrbuf_marc, r->u.grs1, 0);
- return record_iconv_return(rec, len,
- wrbuf_buf(rec->wrbuf_marc),
- wrbuf_len(rec->wrbuf_marc),
- charset);
- }
- return 0;
- }
- else if (!strcmp(type, "xml"))
- {
- Z_External *r = (Z_External *) npr->u.databaseRecord;
- const Odr_oid *oid = r->direct_reference;
-
- /* render bibliographic record .. */
- if (r->which == Z_External_OPAC)
- {
- r = r->u.opac->bibliographicRecord;
- if (!r)
- return 0;
- oid = r->direct_reference;
- }
-
- if (r->which == Z_External_sutrs)
- return record_iconv_return(rec, len,
- (const char *) r->u.sutrs->buf,
- r->u.sutrs->len,
- charset);
- else if (r->which == Z_External_octet)
- {
- int marc_decode_type = YAZ_MARC_MARCXML;
- if (yaz_oid_is_iso2709(oid))
- {
- const char *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,
- r->u.octet_aligned->len,
- charset);
- }
- else if (r->which == Z_External_grs1)
- {
- if (len) *len = 5;
- return "GRS-1";
- }
- return 0;
- }
- else if (!strcmp(type, "raw"))
- {
- 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;
- }
- return 0;
- }
- else if (!strcmp (type, "ext"))
- {
- if (len) *len = -1;
- return (const char *) npr->u.databaseRecord;
- }
- else if (!strcmp (type, "opac"))
-
- {
- Z_External *r = (Z_External *) npr->u.databaseRecord;
- if (r->which == Z_External_OPAC)
- {
- if (!rec->wrbuf_opac)
- rec->wrbuf_opac = wrbuf_alloc();
- wrbuf_rewind(rec->wrbuf_opac);
- yaz_display_OPAC(rec->wrbuf_opac, r->u.opac, 0);
- return record_iconv_return(rec, len,
- wrbuf_buf(rec->wrbuf_opac),
- wrbuf_len(rec->wrbuf_opac),
- charset);
- }
- }
- return 0;
-}
-
-static int strcmp_null(const char *v1, const char *v2)
-{
- if (!v1 && !v2)
- return 0;
- if (!v1 || !v2)
- return -1;
- return strcmp(v1, v2);
-}
-
-static size_t record_hash(int pos)
-{
- if (pos < 0)
- pos = 0;
- return pos % RECORD_HASH_SIZE;
-}
-
-static void record_cache_add(ZOOM_resultset r, Z_NamePlusRecord *npr,
- int pos,
- const char *syntax, const char *elementSetName)
-{
- ZOOM_record_cache rc;
-
- ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_RECV_RECORD);
- ZOOM_connection_put_event(r->connection, event);
-
- for (rc = r->record_hash[record_hash(pos)]; rc; rc = rc->next)
- {
- if (pos == rc->pos)
- {
- if (strcmp_null(r->schema, rc->schema))
- continue;
- if (strcmp_null(elementSetName,rc->elementSetName))
- continue;
- if (strcmp_null(syntax, rc->syntax))
- continue;
- /* not destroying rc->npr (it's handled by nmem )*/
- rc->rec.npr = npr;
- /* keeping wrbuf_marc too */
- return;
- }
- }
- rc = (ZOOM_record_cache) odr_malloc(r->odr, sizeof(*rc));
- rc->rec.npr = npr;
- rc->rec.odr = 0;
- rc->rec.wrbuf_marc = 0;
- rc->rec.wrbuf_iconv = 0;
- rc->rec.wrbuf_opac = 0;
- if (elementSetName)
- rc->elementSetName = odr_strdup(r->odr, elementSetName);
- else
- rc->elementSetName = 0;
-
- if (syntax)
- rc->syntax = odr_strdup(r->odr, syntax);
- else
- rc->syntax = 0;
-
- if (r->schema)
- rc->schema = odr_strdup(r->odr, r->schema);
- else
- rc->schema = 0;
-
- rc->pos = pos;
- rc->next = r->record_hash[record_hash(pos)];
- r->record_hash[record_hash(pos)] = rc;
-}
-
-static ZOOM_record record_cache_lookup(ZOOM_resultset r, int pos,
- const char *syntax,
- const char *elementSetName)
-{
- ZOOM_record_cache rc;
-
- for (rc = r->record_hash[record_hash(pos)]; rc; rc = rc->next)
- {
- if (pos == rc->pos)
- {
- if (strcmp_null(r->schema, rc->schema))
- continue;
- if (strcmp_null(elementSetName,rc->elementSetName))
- continue;
- if (strcmp_null(syntax, rc->syntax))
- continue;
- return &rc->rec;
- }
- }
- return 0;
-}
-
-static void handle_records(ZOOM_connection c, Z_Records *sr,
- int present_phase)
-{
- ZOOM_resultset resultset;
- int *start, *count;
- const char *syntax = 0, *elementSetName = 0;
-
- if (!c->tasks)
- return ;
- switch (c->tasks->which)
- {
- case ZOOM_TASK_SEARCH:
- resultset = c->tasks->u.search.resultset;
- start = &c->tasks->u.search.start;
- count = &c->tasks->u.search.count;
- syntax = c->tasks->u.search.syntax;
- elementSetName = c->tasks->u.search.elementSetName;
- break;
- case ZOOM_TASK_RETRIEVE:
- resultset = c->tasks->u.retrieve.resultset;
- start = &c->tasks->u.retrieve.start;
- count = &c->tasks->u.retrieve.count;
- syntax = c->tasks->u.retrieve.syntax;
- elementSetName = c->tasks->u.retrieve.elementSetName;
- break;
- default:
- return;
- }
- if (sr && sr->which == Z_Records_NSD)
- response_default_diag(c, sr->u.nonSurrogateDiagnostic);
- else if (sr && sr->which == Z_Records_multipleNSD)
- {
- if (sr->u.multipleNonSurDiagnostics->num_diagRecs >= 1)
- response_diag(c, sr->u.multipleNonSurDiagnostics->diagRecs[0]);
- else
- set_ZOOM_error(c, ZOOM_ERROR_DECODE, 0);
- }
- else
- {
- if (*count + *start > resultset->size)
- *count = resultset->size - *start;
- if (*count < 0)
- *count = 0;
- if (sr && sr->which == Z_Records_DBOSD)
- {
- int i;
- NMEM nmem = odr_extract_mem(c->odr_in);
- Z_NamePlusRecordList *p =
- sr->u.databaseOrSurDiagnostics;
- for (i = 0; i<p->num_records; i++)
- {
- record_cache_add(resultset, p->records[i], i + *start,
- syntax, elementSetName);
- }
- *count -= i;
- if (*count < 0)
- *count = 0;
- *start += i;
- yaz_log(log_details,
- "handle_records resultset=%p start=%d count=%d",
- resultset, *start, *count);
-
- /* transfer our response to search_nmem .. we need it later */
- nmem_transfer(odr_getmem(resultset->odr), nmem);
- nmem_destroy(nmem);
- if (present_phase && p->num_records == 0)
- {
- /* present response and we didn't get any records! */
- Z_NamePlusRecord *myrec =
- zget_surrogateDiagRec(resultset->odr, 0, 14, 0);
- record_cache_add(resultset, myrec, *start,
- syntax, elementSetName);
- }
- }
- else if (present_phase)
- {
- /* present response and we didn't get any records! */
- Z_NamePlusRecord *myrec =
- zget_surrogateDiagRec(resultset->odr, 0, 14, 0);
- record_cache_add(resultset, myrec, *start, syntax, elementSetName);
- }
- }
-}
-
-static void handle_present_response(ZOOM_connection c, Z_PresentResponse *pr)
-{
- handle_records(c, pr->records, 1);
-}
-
-static void handle_queryExpressionTerm(ZOOM_options opt, const char *name,
- Z_Term *term)
-{
- switch (term->which)
- {
- case Z_Term_general:
- ZOOM_options_setl(opt, name,
- (const char *)(term->u.general->buf),
- term->u.general->len);
- break;
- case Z_Term_characterString:
- ZOOM_options_set(opt, name, term->u.characterString);
- break;
- case Z_Term_numeric:
- ZOOM_options_set_int(opt, name, *term->u.numeric);
- break;
- }
-}
-
-static void handle_queryExpression(ZOOM_options opt, const char *name,
- Z_QueryExpression *exp)
-{
- char opt_name[80];
-
- switch (exp->which)
- {
- case Z_QueryExpression_term:
- if (exp->u.term && exp->u.term->queryTerm)
- {
- sprintf(opt_name, "%s.term", name);
- handle_queryExpressionTerm(opt, opt_name, exp->u.term->queryTerm);
- }
- break;
- case Z_QueryExpression_query:
- break;
- }
-}
-
-static void handle_searchResult(ZOOM_connection c, ZOOM_resultset resultset,
- Z_OtherInformation *o)
-{
- int i;
- for (i = 0; o && i < o->num_elements; i++)
- {
- if (o->list[i]->which == Z_OtherInfo_externallyDefinedInfo)
- {
- Z_External *ext = o->list[i]->information.externallyDefinedInfo;
-
- if (ext->which == Z_External_searchResult1)
- {
- int j;
- Z_SearchInfoReport *sr = ext->u.searchResult1;
-
- if (sr->num)
- ZOOM_options_set_int(
- resultset->options, "searchresult.size", sr->num);
-
- for (j = 0; j < sr->num; j++)
- {
- Z_SearchInfoReport_s *ent =
- ext->u.searchResult1->elements[j];
- char pref[80];
-
- sprintf(pref, "searchresult.%d", j);
-
- if (ent->subqueryId)
- {
- char opt_name[80];
- sprintf(opt_name, "%s.id", pref);
- ZOOM_options_set(resultset->options, opt_name,
- ent->subqueryId);
- }
- if (ent->subqueryExpression)
- {
- char opt_name[80];
- sprintf(opt_name, "%s.subquery", pref);
- handle_queryExpression(resultset->options, opt_name,
- ent->subqueryExpression);
- }
- if (ent->subqueryInterpretation)
- {
- char opt_name[80];
- sprintf(opt_name, "%s.interpretation", pref);
- handle_queryExpression(resultset->options, opt_name,
- ent->subqueryInterpretation);
- }
- if (ent->subqueryRecommendation)
- {
- char opt_name[80];
- sprintf(opt_name, "%s.recommendation", pref);
- handle_queryExpression(resultset->options, opt_name,
- ent->subqueryRecommendation);
- }
- if (ent->subqueryCount)
- {
- char opt_name[80];
- sprintf(opt_name, "%s.count", pref);
- ZOOM_options_set_int(resultset->options, opt_name,
- *ent->subqueryCount);
- }
- }
- }
- }
- }
-}
-
-static void handle_search_response(ZOOM_connection c, Z_SearchResponse *sr)
-{
- ZOOM_resultset resultset;
- ZOOM_Event event;
-
- if (!c->tasks || c->tasks->which != ZOOM_TASK_SEARCH)
- return ;
-
- event = ZOOM_Event_create(ZOOM_EVENT_RECV_SEARCH);
- ZOOM_connection_put_event(c, event);
-
- resultset = c->tasks->u.search.resultset;
-
- if (sr->resultSetStatus)
- {
- ZOOM_options_set_int(resultset->options, "resultSetStatus",
- *sr->resultSetStatus);
- }
- if (sr->presentStatus)
- {
- ZOOM_options_set_int(resultset->options, "presentStatus",
- *sr->presentStatus);
- }
- handle_searchResult(c, resultset, sr->additionalSearchInfo);
-
- resultset->size = *sr->resultCount;
- handle_records(c, sr->records, 0);
-}
-
-static void sort_response(ZOOM_connection c, Z_SortResponse *res)
-{
- if (res->diagnostics && res->num_diagnostics > 0)
- response_diag(c, res->diagnostics[0]);
-}
-
-static int scan_response(ZOOM_connection c, Z_ScanResponse *res)
-{
- NMEM nmem = odr_extract_mem(c->odr_in);
- ZOOM_scanset scan;
-
- if (!c->tasks || c->tasks->which != ZOOM_TASK_SCAN)
- return 0;
- scan = c->tasks->u.scan.scan;
-
- if (res->entries && res->entries->nonsurrogateDiagnostics)
- response_diag(c, res->entries->nonsurrogateDiagnostics[0]);
- scan->scan_response = res;
- nmem_transfer(odr_getmem(scan->odr), nmem);
- if (res->stepSize)
- ZOOM_options_set_int(scan->options, "stepSize", *res->stepSize);
- if (res->positionOfTerm)
- ZOOM_options_set_int(scan->options, "position", *res->positionOfTerm);
- if (res->scanStatus)
- ZOOM_options_set_int(scan->options, "scanStatus", *res->scanStatus);
- if (res->numberOfEntriesReturned)
- ZOOM_options_set_int(scan->options, "number",
- *res->numberOfEntriesReturned);
- nmem_destroy(nmem);
- return 1;
-}
-
-static zoom_ret send_sort(ZOOM_connection c,
- ZOOM_resultset resultset)
-{
- if (c->error)
- resultset->r_sort_spec = 0;
- if (resultset->r_sort_spec)
- {
- Z_APDU *apdu = zget_APDU(c->odr_out, Z_APDU_sortRequest);
- Z_SortRequest *req = apdu->u.sortRequest;
-
- req->num_inputResultSetNames = 1;
- req->inputResultSetNames = (Z_InternationalString **)
- odr_malloc(c->odr_out, sizeof(*req->inputResultSetNames));
- req->inputResultSetNames[0] =
- odr_strdup(c->odr_out, resultset->setname);
- req->sortedResultSetName = odr_strdup(c->odr_out, resultset->setname);
- req->sortSequence = resultset->r_sort_spec;
- resultset->r_sort_spec = 0;
- return send_APDU(c, apdu);
- }
- return zoom_complete;
-}
-
-static zoom_ret send_present(ZOOM_connection c)
-{
- Z_APDU *apdu = 0;
- Z_PresentRequest *req = 0;
- int i = 0;
- const char *syntax = 0;
- const char *elementSetName = 0;
- ZOOM_resultset resultset;
- int *start, *count;
-
- if (!c->tasks)
- {
- yaz_log(log_details, "%p send_present no tasks", c);
- return zoom_complete;
- }
-
- switch (c->tasks->which)
- {
- case ZOOM_TASK_SEARCH:
- resultset = c->tasks->u.search.resultset;
- start = &c->tasks->u.search.start;
- count = &c->tasks->u.search.count;
- syntax = c->tasks->u.search.syntax;
- elementSetName = c->tasks->u.search.elementSetName;
- break;
- case ZOOM_TASK_RETRIEVE:
- resultset = c->tasks->u.retrieve.resultset;
- start = &c->tasks->u.retrieve.start;
- count = &c->tasks->u.retrieve.count;
- syntax = c->tasks->u.retrieve.syntax;
- elementSetName = c->tasks->u.retrieve.elementSetName;
- break;
- default:
- return zoom_complete;
- }
- yaz_log(log_details, "%p send_present start=%d count=%d",
- c, *start, *count);
-
- if (*start < 0 || *count < 0 || *start + *count > resultset->size)
- {
- set_dset_error(c, YAZ_BIB1_PRESENT_REQUEST_OUT_OF_RANGE, "Bib-1",
- "", 0);
- }
- if (c->error) /* don't continue on error */
- return zoom_complete;
- yaz_log(log_details, "send_present resultset=%p start=%d count=%d",
- resultset, *start, *count);
-
- for (i = 0; i < *count; i++)
- {
- ZOOM_record rec =
- record_cache_lookup(resultset, i + *start, syntax, elementSetName);
- if (!rec)
- break;
- else
- {
- ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_RECV_RECORD);
- ZOOM_connection_put_event(c, event);
- }
- }
- *start += i;
- *count -= i;
-
- if (*count == 0)
- {
- yaz_log(log_details, "%p send_present skip=%d no more to fetch", c, i);
- return zoom_complete;
- }
-
- apdu = zget_APDU(c->odr_out, Z_APDU_presentRequest);
- req = apdu->u.presentRequest;
-
- if (i)
- yaz_log(log_details, "%p send_present skip=%d", c, i);
-
- *req->resultSetStartPoint = *start + 1;
- *req->numberOfRecordsRequested = resultset->step>0 ?
- resultset->step : *count;
- if (*req->numberOfRecordsRequested + *start > resultset->size)
- *req->numberOfRecordsRequested = resultset->size - *start;
- assert(*req->numberOfRecordsRequested > 0);
-
- if (syntax && *syntax)
- req->preferredRecordSyntax =
- zoom_yaz_str_to_z3950oid(c, CLASS_RECSYN, syntax);
-
- if (resultset->schema && *resultset->schema)
- {
- Z_RecordComposition *compo = (Z_RecordComposition *)
- odr_malloc(c->odr_out, sizeof(*compo));
-
- req->recordComposition = compo;
- compo->which = Z_RecordComp_complex;
- compo->u.complex = (Z_CompSpec *)
- odr_malloc(c->odr_out, sizeof(*compo->u.complex));
- compo->u.complex->selectAlternativeSyntax = (bool_t *)
- odr_malloc(c->odr_out, sizeof(bool_t));
- *compo->u.complex->selectAlternativeSyntax = 0;
-
- compo->u.complex->generic = (Z_Specification *)
- odr_malloc(c->odr_out, sizeof(*compo->u.complex->generic));
-
- compo->u.complex->generic->which = Z_Schema_oid;
- compo->u.complex->generic->schema.oid = (Odr_oid *)
- zoom_yaz_str_to_z3950oid (c, CLASS_SCHEMA, resultset->schema);
-
- if (!compo->u.complex->generic->schema.oid)
- {
- /* OID wasn't a schema! Try record syntax instead. */
-
- compo->u.complex->generic->schema.oid = (Odr_oid *)
- zoom_yaz_str_to_z3950oid (c, CLASS_RECSYN, resultset->schema);
- }
- if (elementSetName && *elementSetName)
- {
- compo->u.complex->generic->elementSpec = (Z_ElementSpec *)
- odr_malloc(c->odr_out, sizeof(Z_ElementSpec));
- compo->u.complex->generic->elementSpec->which =
- Z_ElementSpec_elementSetName;
- compo->u.complex->generic->elementSpec->u.elementSetName =
- odr_strdup(c->odr_out, elementSetName);
- }
- else
- compo->u.complex->generic->elementSpec = 0;
- compo->u.complex->num_dbSpecific = 0;
- compo->u.complex->dbSpecific = 0;
- compo->u.complex->num_recordSyntax = 0;
- compo->u.complex->recordSyntax = 0;
- }
- else if (elementSetName && *elementSetName)
- {
- Z_ElementSetNames *esn = (Z_ElementSetNames *)
- odr_malloc(c->odr_out, sizeof(*esn));
- Z_RecordComposition *compo = (Z_RecordComposition *)
- odr_malloc(c->odr_out, sizeof(*compo));
-
- esn->which = Z_ElementSetNames_generic;
- esn->u.generic = odr_strdup(c->odr_out, elementSetName);
- compo->which = Z_RecordComp_simple;
- compo->u.simple = esn;
- req->recordComposition = compo;
- }
- req->resultSetId = odr_strdup(c->odr_out, resultset->setname);
- return send_APDU(c, apdu);
-}
-
-ZOOM_API(ZOOM_scanset)
- ZOOM_connection_scan(ZOOM_connection c, const char *start)
-{
- ZOOM_scanset s;
- ZOOM_query q = ZOOM_query_create();
-
- ZOOM_query_prefix(q, start);
-
- s = ZOOM_connection_scan1(c, q);
- ZOOM_query_destroy(q);
- return s;
-
-}
-
-ZOOM_API(ZOOM_scanset)
- ZOOM_connection_scan1(ZOOM_connection c, ZOOM_query q)
-{
- char *start;
- char *freeme = 0;
- ZOOM_scanset scan = 0;
-
- /*
- * We need to check the query-type, so we can recognise CQL and
- * CCL and compile them into a form that we can use here. The
- * ZOOM_query structure has no explicit `type' member, but
- * inspection of the ZOOM_query_prefix() and ZOOM_query_cql()
- * functions shows how the structure is set up in each case.
- */
- if (!q->z_query)
- return 0;
- else if (q->z_query->which == Z_Query_type_1)
- {
- yaz_log(log_api, "%p ZOOM_connection_scan1 q=%p PQF '%s'",
- c, q, q->query_string);
- start = q->query_string;
- }
- else if (q->z_query->which == Z_Query_type_104)
- {
- yaz_log(log_api, "%p ZOOM_connection_scan1 q=%p CQL '%s'",
- c, q, q->query_string);
- start = freeme = cql2pqf(c, q->query_string);
- if (start == 0)
- return 0;
- }
- else
- {
- yaz_log(YLOG_FATAL, "%p ZOOM_connection_scan1 q=%p unknown type '%s'",
- c, q, q->query_string);
- abort();
- }
-
- scan = (ZOOM_scanset) xmalloc(sizeof(*scan));
- scan->connection = c;
- scan->odr = odr_createmem(ODR_DECODE);
- scan->options = ZOOM_options_create_with_parent(c->options);
- scan->refcount = 1;
- scan->scan_response = 0;
- scan->termListAndStartPoint =
- p_query_scan(scan->odr, PROTO_Z3950, &scan->attributeSet, start);
- xfree(freeme);
-
- {
- const char *cp = ZOOM_options_get(scan->options, "rpnCharset");
- if (cp)
- {
- yaz_iconv_t cd = yaz_iconv_open(cp, "UTF-8");
- if (cd)
- {
- yaz_query_charset_convert_apt(scan->termListAndStartPoint,
- scan->odr, cd);
- }
- }
- }
-
-
- scan->databaseNames = set_DatabaseNames(c, c->options,
- &scan->num_databaseNames,
- scan->odr);
- if (scan->termListAndStartPoint != 0)
- {
- ZOOM_task task = ZOOM_connection_add_task(c, ZOOM_TASK_SCAN);
- task->u.scan.scan = scan;
-
- (scan->refcount)++;
- if (!c->async)
- {
- while (ZOOM_event(1, &c))
- ;
- }
- }
- return scan;
-}
-
-ZOOM_API(void)
- ZOOM_scanset_destroy(ZOOM_scanset scan)
-{
- if (!scan)
- return;
- (scan->refcount)--;
- if (scan->refcount == 0)
- {
- odr_destroy(scan->odr);
-
- ZOOM_options_destroy(scan->options);
- xfree(scan);
- }
-}
-
-static zoom_ret send_package(ZOOM_connection c)
-{
- ZOOM_Event event;
-
- yaz_log(log_details, "%p send_package", c);
- if (!c->tasks)
- return zoom_complete;
- assert (c->tasks->which == ZOOM_TASK_PACKAGE);
-
- event = ZOOM_Event_create(ZOOM_EVENT_SEND_APDU);
- ZOOM_connection_put_event(c, event);
-
- c->buf_out = c->tasks->u.package->buf_out;
- c->len_out = c->tasks->u.package->len_out;
-
- return do_write(c);
-}
-
-static zoom_ret send_scan(ZOOM_connection c)
-{
- ZOOM_scanset scan;
- Z_APDU *apdu = zget_APDU(c->odr_out, Z_APDU_scanRequest);
- Z_ScanRequest *req = apdu->u.scanRequest;
-
- yaz_log(log_details, "%p send_scan", c);
- if (!c->tasks)
- return zoom_complete;
- assert (c->tasks->which == ZOOM_TASK_SCAN);
- scan = c->tasks->u.scan.scan;
-
- req->termListAndStartPoint = scan->termListAndStartPoint;
- req->attributeSet = scan->attributeSet;
-
- *req->numberOfTermsRequested =
- ZOOM_options_get_int(scan->options, "number", 10);
-
- req->preferredPositionInResponse =
- odr_intdup(c->odr_out,
- ZOOM_options_get_int(scan->options, "position", 1));
-
- req->stepSize =
- odr_intdup(c->odr_out,
- ZOOM_options_get_int(scan->options, "stepSize", 0));
-
- req->databaseNames = scan->databaseNames;
- req->num_databaseNames = scan->num_databaseNames;
-
- return send_APDU(c, apdu);
-}
-
-ZOOM_API(size_t)
- ZOOM_scanset_size(ZOOM_scanset scan)
-{
- if (!scan || !scan->scan_response || !scan->scan_response->entries)
- return 0;
- return scan->scan_response->entries->num_entries;
-}
-
-ZOOM_API(const char *)
- ZOOM_scanset_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->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_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 = t->displayTerm;
- *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);
-}
-
-ZOOM_API(void)
- ZOOM_scanset_option_set(ZOOM_scanset scan, const char *key,
- const char *val)
-{
- ZOOM_options_set(scan->options, key, val);
-}
-
-static Z_APDU *create_es_package(ZOOM_package p, const Odr_oid *oid)
-{
- const char *str;
- Z_APDU *apdu = zget_APDU(p->odr_out, Z_APDU_extendedServicesRequest);
- Z_ExtendedServicesRequest *req = apdu->u.extendedServicesRequest;
-
- str = ZOOM_options_get(p->options, "package-name");
- if (str && *str)
- req->packageName = odr_strdup(p->odr_out, str);
-
- str = ZOOM_options_get(p->options, "user-id");
- if (str)
- req->userId = odr_strdup(p->odr_out, str);
-
- req->packageType = odr_oiddup(p->odr_out, oid);
-
- str = ZOOM_options_get(p->options, "function");
- if (str)
- {
- if (!strcmp (str, "create"))
- *req->function = Z_ExtendedServicesRequest_create;
- if (!strcmp (str, "delete"))
- *req->function = Z_ExtendedServicesRequest_delete;
- if (!strcmp (str, "modify"))
- *req->function = Z_ExtendedServicesRequest_modify;
- }
-
- str = ZOOM_options_get(p->options, "waitAction");
- if (str)
- {
- if (!strcmp (str, "wait"))
- *req->waitAction = Z_ExtendedServicesRequest_wait;
- if (!strcmp (str, "waitIfPossible"))
- *req->waitAction = Z_ExtendedServicesRequest_waitIfPossible;
- if (!strcmp (str, "dontWait"))
- *req->waitAction = Z_ExtendedServicesRequest_dontWait;
- if (!strcmp (str, "dontReturnPackage"))
- *req->waitAction = Z_ExtendedServicesRequest_dontReturnPackage;
- }
- return apdu;
-}
-
-static const char *ill_array_lookup(void *clientData, const char *idx)
-{
- ZOOM_package p = (ZOOM_package) clientData;
- return ZOOM_options_get(p->options, idx+4);
-}
-
-static Z_External *encode_ill_request(ZOOM_package p)
-{
- ODR out = p->odr_out;
- ILL_Request *req;
- Z_External *r = 0;
- struct ill_get_ctl ctl;
-
- ctl.odr = p->odr_out;
- ctl.clientData = p;
- ctl.f = ill_array_lookup;
-
- req = ill_get_ILLRequest(&ctl, "ill", 0);
-
- if (!ill_Request(out, &req, 0, 0))
- {
- int ill_request_size;
- char *ill_request_buf = odr_getbuf(out, &ill_request_size, 0);
- if (ill_request_buf)
- odr_setbuf(out, ill_request_buf, ill_request_size, 1);
- return 0;
- }
- else
- {
- int illRequest_size = 0;
- char *illRequest_buf = odr_getbuf(out, &illRequest_size, 0);
-
- r = (Z_External *) odr_malloc(out, sizeof(*r));
- r->direct_reference = odr_oiddup(out, yaz_oid_general_isoill_1);
- r->indirect_reference = 0;
- r->descriptor = 0;
- r->which = Z_External_single;
-
- r->u.single_ASN1_type =
- odr_create_Odr_oct(out,
- (unsigned char *)illRequest_buf,
- illRequest_size);
- }
- return r;
-}
-
-static Z_ItemOrder *encode_item_order(ZOOM_package p)
-{
- Z_ItemOrder *req = (Z_ItemOrder *) odr_malloc(p->odr_out, sizeof(*req));
- const char *str;
-
- req->which = Z_IOItemOrder_esRequest;
- req->u.esRequest = (Z_IORequest *)
- odr_malloc(p->odr_out,sizeof(Z_IORequest));
-
- /* to keep part ... */
- req->u.esRequest->toKeep = (Z_IOOriginPartToKeep *)
- odr_malloc(p->odr_out,sizeof(Z_IOOriginPartToKeep));
- req->u.esRequest->toKeep->supplDescription = 0;
- req->u.esRequest->toKeep->contact = (Z_IOContact *)
- odr_malloc(p->odr_out, sizeof(*req->u.esRequest->toKeep->contact));
-
- str = ZOOM_options_get(p->options, "contact-name");
- req->u.esRequest->toKeep->contact->name = str ?
- odr_strdup(p->odr_out, str) : 0;
-
- str = ZOOM_options_get(p->options, "contact-phone");
- req->u.esRequest->toKeep->contact->phone = str ?
- odr_strdup(p->odr_out, str) : 0;
-
- str = ZOOM_options_get(p->options, "contact-email");
- req->u.esRequest->toKeep->contact->email = str ?
- odr_strdup(p->odr_out, str) : 0;
-
- req->u.esRequest->toKeep->addlBilling = 0;
-
- /* not to keep part ... */
- req->u.esRequest->notToKeep = (Z_IOOriginPartNotToKeep *)
- odr_malloc(p->odr_out,sizeof(Z_IOOriginPartNotToKeep));
-
- str = ZOOM_options_get(p->options, "itemorder-setname");
- if (!str)
- str = "default";
-
- if (!*str)
- req->u.esRequest->notToKeep->resultSetItem = 0;
- else
- {
- req->u.esRequest->notToKeep->resultSetItem = (Z_IOResultSetItem *)
- odr_malloc(p->odr_out, sizeof(Z_IOResultSetItem));
-
- req->u.esRequest->notToKeep->resultSetItem->resultSetId =
- odr_strdup(p->odr_out, str);
- req->u.esRequest->notToKeep->resultSetItem->item =
- (int *) odr_malloc(p->odr_out, sizeof(int));
-
- str = ZOOM_options_get(p->options, "itemorder-item");
- *req->u.esRequest->notToKeep->resultSetItem->item =
- (str ? atoi(str) : 1);
- }
-
- str = ZOOM_options_get(p->options, "doc");
- if (str)
- {
- req->u.esRequest->notToKeep->itemRequest =
- z_ext_record_xml(p->odr_out, str, strlen(str));
- }
- else
- req->u.esRequest->notToKeep->itemRequest = encode_ill_request(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, yaz_oid_extserv_admin);
- 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,
- p->odr_out);
- if (num_db > 0)
- first_db = db[0];
-
- r->direct_reference = odr_oiddup(p->odr_out, yaz_oid_extserv_admin);
- 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_xmlupdate_package(ZOOM_package p)
-{
- Z_APDU *apdu = create_es_package(p, yaz_oid_extserv_xml_es);
- Z_ExtendedServicesRequest *req = apdu->u.extendedServicesRequest;
- 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_create_Odr_oct(p->odr_out, (const unsigned char *) doc,
- strlen(doc));
- 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, p->odr_out);
- const char *action = ZOOM_options_get(p->options, "action");
- const char *recordIdOpaque = ZOOM_options_get(p->options, "recordIdOpaque");
- const char *recordIdNumber = ZOOM_options_get(p->options, "recordIdNumber");
- const char *record_buf = ZOOM_options_get(p->options, "record");
- const char *syntax_str = ZOOM_options_get(p->options, "syntax");
- const char *version = ZOOM_options_get(p->options, "updateVersion");
-
- const char *correlationInfo_note =
- ZOOM_options_get(p->options, "correlationInfo.note");
- const char *correlationInfo_id =
- ZOOM_options_get(p->options, "correlationInfo.id");
- int action_no = -1;
- Odr_oid *syntax_oid = 0;
- const Odr_oid *package_oid = yaz_oid_extserv_database_update;
-
- if (!version)
- version = "3";
- if (!syntax_str)
- syntax_str = "xml";
- if (!record_buf)
- {
- record_buf = "void";
- syntax_str = "SUTRS";
- }
-
- if (syntax_str)
- {
- syntax_oid = yaz_string_to_oid_odr(yaz_oid_std(),
- CLASS_RECSYN, syntax_str,
- p->odr_out);
- }
- if (!syntax_oid)
- return 0;
-
- if (num_db > 0)
- first_db = db[0];
-
- switch(*version)
- {
- case '1':
- package_oid = yaz_oid_extserv_database_update_first_version;
- /* old update does not support specialUpdate */
- if (!action)
- action = "recordInsert";
- break;
- case '2':
- if (!action)
- action = "specialUpdate";
- package_oid = yaz_oid_extserv_database_update_second_version;
- break;
- case '3':
- if (!action)
- action = "specialUpdate";
- package_oid = yaz_oid_extserv_database_update;
- break;
- default:
- return 0;
- }
-
- 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, package_oid);
- if (apdu)
- {
- Z_IUOriginPartToKeep *toKeep;
- Z_IUSuppliedRecords *notToKeep;
- Z_External *r = (Z_External *)
- odr_malloc(p->odr_out, sizeof(*r));
- const char *elementSetName =
- ZOOM_options_get(p->options, "elementSetName");
-
- apdu->u.extendedServicesRequest->taskSpecificParameters = r;
-
- r->direct_reference = odr_oiddup(p->odr_out, package_oid);
- 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;
- if (elementSetName)
- toKeep->elementSetName = odr_strdup(p->odr_out, elementSetName);
-
- 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 (recordIdOpaque)
- {
- notToKeep->elements[0]->u.opaque =
- odr_create_Odr_oct(p->odr_out,
- (const unsigned char *) recordIdOpaque,
- strlen(recordIdOpaque));
- }
- else if (recordIdNumber)
- {
- notToKeep->elements[0]->which = Z_IUSuppliedRecords_elem_number;
-
- notToKeep->elements[0]->u.number =
- odr_intdup(p->odr_out, atoi(recordIdNumber));
- }
- else
- notToKeep->elements[0]->u.opaque = 0;
- notToKeep->elements[0]->supplementalId = 0;
- if (correlationInfo_note || correlationInfo_id)
- {
- Z_IUCorrelationInfo *ci;
- ci = notToKeep->elements[0]->correlationInfo =
- odr_malloc(p->odr_out, sizeof(*ci));
- ci->note = correlationInfo_note ?
- odr_strdup(p->odr_out, correlationInfo_note) : 0;
- ci->id = correlationInfo_id ?
- odr_intdup(p->odr_out, atoi(correlationInfo_id)) : 0;
- }
- else
- notToKeep->elements[0]->correlationInfo = 0;
- notToKeep->elements[0]->record =
- z_ext_record_oid(p->odr_out, syntax_oid,
- record_buf, strlen(record_buf));
- }
- if (0 && apdu)
- {
- ODR print = odr_createmem(ODR_PRINT);