X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=src%2Fseshigh.c;h=65c262628f3c5b6c1633eac8e5698e168cd3ddf6;hb=49dfd3f8ec91ce7ced774d66f5db9a248e574bbf;hp=70581d47aaeaeb44acba9988b61bd67a2a2cf8eb;hpb=c519e4716646be3b24f7d4d3de99e06e423da865;p=yaz-moved-to-github.git diff --git a/src/seshigh.c b/src/seshigh.c index 70581d4..65c2626 100644 --- a/src/seshigh.c +++ b/src/seshigh.c @@ -2,7 +2,7 @@ * Copyright (C) 1995-2005, Index Data ApS * See the file LICENSE for details. * - * $Id: seshigh.c,v 1.47 2005-02-01 14:46:47 adam Exp $ + * $Id: seshigh.c,v 1.51 2005-03-05 12:14:12 adam Exp $ */ /** * \file seshigh.c @@ -50,6 +50,11 @@ #include #endif +#if HAVE_XML2 +#include +#include +#endif + #include #include #include @@ -177,6 +182,8 @@ association *create_association(IOCHAN channel, COMSTACK link, request_initq(&anew->incoming); request_initq(&anew->outgoing); anew->proto = cs_getproto(link); + anew->cql_transform = 0; + anew->server_node_ptr = 0; return anew; } @@ -475,8 +482,6 @@ static void assoc_init_reset(association *assoc) odr_strdup (assoc->encode, cs_addrstr(assoc->client_link)); yaz_log(log_requestdetail, "peer %s", assoc->init->peer_name); - - } static int srw_bend_init(association *assoc, Z_SRW_diagnostic **d, int *num) @@ -623,6 +628,79 @@ static int srw_bend_fetch(association *assoc, int pos, return rr.errcode; } +static int cql2pqf(ODR odr, const char *cql, cql_transform_t ct, + Z_Query *query_result) +{ + /* have a CQL query and CQL to PQF transform .. */ + CQL_parser cp = cql_parser_create(); + int r; + int srw_errcode = 0; + const char *add = 0; + char rpn_buf[512]; + + r = cql_parser_string(cp, cql); + if (r) + { + /* CQL syntax error */ + srw_errcode = 10; + } + if (!r) + { + /* Syntax OK */ + r = cql_transform_buf(ct, + cql_parser_result(cp), + rpn_buf, sizeof(rpn_buf)-1); + if (r) + srw_errcode = cql_transform_error(ct, &add); + } + if (!r) + { + /* Syntax & transform OK. */ + /* Convert PQF string to Z39.50 to RPN query struct */ + YAZ_PQF_Parser pp = yaz_pqf_create(); + Z_RPNQuery *rpnquery = yaz_pqf_parse(pp, odr, rpn_buf); + if (!rpnquery) + { + size_t off; + const char *pqf_msg; + int code = yaz_pqf_error(pp, &pqf_msg, &off); + yaz_log(YLOG_WARN, "PQF Parser Error %s (code %d)", + pqf_msg, code); + srw_errcode = 10; + } + else + { + query_result->which = Z_Query_type_1; + query_result->u.type_1 = rpnquery; + } + yaz_pqf_destroy(pp); + } + cql_parser_destroy(cp); + return srw_errcode; +} + +static int cql2pqf_scan(ODR odr, const char *cql, cql_transform_t ct, + Z_AttributesPlusTerm *result) +{ + Z_Query query; + Z_RPNQuery *rpn; + int srw_error = cql2pqf(odr, cql, ct, &query); + if (srw_error) + return srw_error; + if (query.which != Z_Query_type_1 && query.which != Z_Query_type_101) + return 10; /* bad query type */ + rpn = query.u.type_1; + if (!rpn->RPNStructure) + return 10; /* must be structure */ + if (rpn->RPNStructure->which != Z_RPNStructure_simple) + return 10; /* must be simple */ + if (rpn->RPNStructure->u.simple->which != Z_Operand_APT) + return 10; /* must be attributes plus term node .. */ + memcpy(result, rpn->RPNStructure->u.simple->u.attributesPlusTerm, + sizeof(*result)); + return 0; +} + static void srw_bend_search(association *assoc, request *req, Z_SRW_searchRetrieveRequest *srw_req, Z_SRW_searchRetrieveResponse *srw_res, @@ -647,19 +725,36 @@ static void srw_bend_search(association *assoc, request *req, rr.referenceId = 0; rr.query = (Z_Query *) odr_malloc (assoc->decode, sizeof(*rr.query)); + rr.query->u.type_1 = 0; if (srw_req->query_type == Z_SRW_query_type_cql) { - ext = (Z_External *) odr_malloc(assoc->decode, sizeof(*ext)); - ext->direct_reference = odr_getoidbystr(assoc->decode, - "1.2.840.10003.16.2"); - ext->indirect_reference = 0; - ext->descriptor = 0; - ext->which = Z_External_CQL; - ext->u.cql = srw_req->query.cql; - - rr.query->which = Z_Query_type_104; - rr.query->u.type_104 = ext; + if (assoc->cql_transform) + { + int srw_errcode = cql2pqf(assoc->encode, srw_req->query.cql, + assoc->cql_transform, rr.query); + if (srw_errcode) + { + yaz_add_srw_diagnostic(assoc->encode, + &srw_res->diagnostics, + &srw_res->num_diagnostics, + srw_errcode, 0); + } + } + else + { + /* CQL query to backend. Wrap it - Z39.50 style */ + ext = (Z_External *) odr_malloc(assoc->decode, sizeof(*ext)); + ext->direct_reference = odr_getoidbystr(assoc->decode, + "1.2.840.10003.16.2"); + ext->indirect_reference = 0; + ext->descriptor = 0; + ext->which = Z_External_CQL; + ext->u.cql = srw_req->query.cql; + + rr.query->which = Z_Query_type_104; + rr.query->u.type_104 = ext; + } } else if (srw_req->query_type == Z_SRW_query_type_pqf) { @@ -687,7 +782,6 @@ static void srw_bend_search(association *assoc, request *req, } else { - rr.query->u.type_1 = 0; yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics, &srw_res->num_diagnostics, 11, 0); } @@ -820,6 +914,42 @@ static void srw_bend_search(association *assoc, request *req, } } +static char *srw_bend_explain_default(void *handle, bend_explain_rr *rr) +{ +#if HAVE_XML2 + xmlNodePtr ptr = rr->server_node_ptr; + if (!ptr) + return 0; + for (ptr = ptr->children; ptr; ptr = ptr->next) + { + if (ptr->type != XML_ELEMENT_NODE) + continue; + if (!strcmp((const char *) ptr->name, "explain")) + { + int len; + xmlDocPtr doc = xmlNewDoc("1.0"); + xmlChar *buf_out; + char *content; + + ptr = xmlCopyNode(ptr, 1); + + xmlDocSetRootElement(doc, ptr); + + xmlDocDumpMemory(doc, &buf_out, &len); + content = (char*) odr_malloc(rr->stream, 1+len); + memcpy(content, buf_out, len); + content[len] = '\0'; + + xmlFree(buf_out); + xmlFreeDoc(doc); + rr->explain_buf = content; + return 0; + } + } +#endif + return 0; +} + static void srw_bend_explain(association *assoc, request *req, Z_SRW_explainRequest *srw_req, Z_SRW_explainResponse *srw_res, @@ -828,30 +958,35 @@ static void srw_bend_explain(association *assoc, request *req, yaz_log(log_requestdetail, "Got SRW ExplainRequest"); *http_code = 404; srw_bend_init(assoc, &srw_res->diagnostics, &srw_res->num_diagnostics); - if (assoc->init && assoc->init->bend_explain) - { - bend_explain_rr rr; - - rr.stream = assoc->encode; - rr.decode = assoc->decode; - rr.print = assoc->print; - rr.explain_buf = 0; - rr.database = srw_req->database; - rr.schema = "http://explain.z3950.org/dtd/2.0/"; - (*assoc->init->bend_explain)(assoc->backend, &rr); - if (rr.explain_buf) - { - int packing = Z_SRW_recordPacking_string; - if (srw_req->recordPacking && - !strcmp(srw_req->recordPacking, "xml")) - packing = Z_SRW_recordPacking_XML; - srw_res->record.recordSchema = rr.schema; - srw_res->record.recordPacking = packing; - srw_res->record.recordData_buf = rr.explain_buf; - srw_res->record.recordData_len = strlen(rr.explain_buf); - srw_res->record.recordPosition = 0; - *http_code = 200; - } + if (assoc->init) + { + bend_explain_rr rr; + + rr.stream = assoc->encode; + rr.decode = assoc->decode; + rr.print = assoc->print; + rr.explain_buf = 0; + rr.database = srw_req->database; + rr.server_node_ptr = assoc->server_node_ptr; + rr.schema = "http://explain.z3950.org/dtd/2.0/"; + if (assoc->init->bend_explain) + (*assoc->init->bend_explain)(assoc->backend, &rr); + else + srw_bend_explain_default(assoc->backend, &rr); + + if (rr.explain_buf) + { + int packing = Z_SRW_recordPacking_string; + if (srw_req->recordPacking && + !strcmp(srw_req->recordPacking, "xml")) + packing = Z_SRW_recordPacking_XML; + srw_res->record.recordSchema = rr.schema; + srw_res->record.recordPacking = packing; + srw_res->record.recordData_buf = rr.explain_buf; + srw_res->record.recordData_len = strlen(rr.explain_buf); + srw_res->record.recordPosition = 0; + *http_code = 200; + } } } @@ -927,11 +1062,34 @@ static void srw_bend_scan(association *assoc, request *req, else if (srw_req->query_type == Z_SRW_query_type_cql && assoc->init->bend_srw_scan) { - bsrr->term = 0; - bsrr->attributeset = VAL_NONE; - bsrr->scanClause = srw_req->scanClause.cql; - ((int (*)(void *, bend_scan_rr *)) - (*assoc->init->bend_srw_scan))(assoc->backend, bsrr); + if (assoc->cql_transform) + { + int srw_error; + bsrr->scanClause = 0; + bsrr->attributeset = VAL_NONE; + bsrr->term = odr_malloc(assoc->decode, sizeof(*bsrr->term)); + srw_error = cql2pqf_scan(assoc->encode, + srw_req->scanClause.cql, + assoc->cql_transform, + bsrr->term); + if (srw_error) + yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics, + &srw_res->num_diagnostics, + srw_error, 0); + else + { + ((int (*)(void *, bend_scan_rr *)) + (*assoc->init->bend_scan))(assoc->backend, bsrr); + } + } + else + { + bsrr->term = 0; + bsrr->attributeset = VAL_NONE; + bsrr->scanClause = srw_req->scanClause.cql; + ((int (*)(void *, bend_scan_rr *)) + (*assoc->init->bend_srw_scan))(assoc->backend, bsrr); + } } else { @@ -1602,7 +1760,7 @@ static Z_APDU *process_initRequest(association *assoc, request *reqb) assoc->init->implementation_name, odr_prepend(assoc->encode, "GFS", resp->implementationName)); - version = odr_strdup(assoc->encode, "$Revision: 1.47 $"); + version = odr_strdup(assoc->encode, "$Revision: 1.51 $"); if (strlen(version) > 10) /* check for unexpanded CVS strings */ version[strlen(version)-2] = '\0'; resp->implementationVersion = odr_prepend(assoc->encode, @@ -1866,11 +2024,24 @@ static Z_APDU *process_searchRequest(association *assoc, request *reqb, nmem_transfer(bsrr->stream->mem, reqb->request_mem); bsrr->decode = assoc->decode; bsrr->print = assoc->print; - bsrr->errcode = 0; bsrr->hits = 0; + bsrr->errcode = 0; bsrr->errstring = NULL; bsrr->search_info = NULL; - (assoc->init->bend_search)(assoc->backend, bsrr); + + if (assoc->cql_transform && + req->query->which == Z_Query_type_104 && + req->query->u.type_104->which == Z_External_CQL) + { + /* have a CQL query and a CQL to PQF transform .. */ + int srw_errcode = + cql2pqf(bsrr->stream, req->query->u.type_104->u.cql, + assoc->cql_transform, bsrr->query); + if (srw_errcode) + bsrr->errcode = yaz_diag_srw_to_bib1(srw_errcode); + } + if (!bsrr->errcode) + (assoc->init->bend_search)(assoc->backend, bsrr); if (!bsrr->request) /* backend not ready with the search response */ return 0; /* should not be used any more */ }