X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=src%2Fsrwutil.c;h=493a7a34bd52df292f253817266788865542796f;hp=9e71129639b0a3c49e78537d924a976a39bb7ea9;hb=7fc72f3ae149e416a297ef1f55c09271056e98f1;hpb=2ad2651374674c895ad59b267da6fe2d8665fabd diff --git a/src/srwutil.c b/src/srwutil.c index 9e71129..493a7a3 100644 --- a/src/srwutil.c +++ b/src/srwutil.c @@ -1,19 +1,25 @@ /* This file is part of the YAZ toolkit. - * Copyright (C) 1995-2010 Index Data + * Copyright (C) Index Data * See the file LICENSE for details. */ /** * \file srwutil.c * \brief Implements SRW/SRU utilities. */ +#if HAVE_CONFIG_H +#include +#endif #include #include #include #include +#include #include #include "sru-p.h" +#define MAX_SRU_PARAMETERS 30 + static char *yaz_decode_sru_dbpath_odr(ODR n, const char *uri, size_t len) { return odr_strdupn(n, uri, len); @@ -33,51 +39,57 @@ char *yaz_encode_sru_dbpath_odr(ODR out, const char *db) return dst; } -#if YAZ_HAVE_XML2 -static int yaz_base64decode(const char *in, char *out) +Z_AttributeElement *yaz_string_element_create(ODR o, int type, + const char *value) { - const char *map = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz0123456789+/"; - int olen = 0; - int len = strlen(in); + Z_AttributeElement *element = (Z_AttributeElement*) + odr_malloc(o, sizeof(*element)); + element->attributeType = odr_intdup(o, type); + element->attributeSet = 0; + element->which = Z_AttributeValue_complex; + element->value.complex = (Z_ComplexAttribute *) + odr_malloc(o, sizeof(Z_ComplexAttribute)); + element->value.complex->num_list = 1; + element->value.complex->list = (Z_StringOrNumeric **) + odr_malloc(o, 1 * sizeof(Z_StringOrNumeric *)); + element->value.complex->list[0] = (Z_StringOrNumeric *) + odr_malloc(o, sizeof(Z_StringOrNumeric)); + element->value.complex->list[0]->which = Z_StringOrNumeric_string; + element->value.complex->list[0]->u.string = odr_strdup(o, value); + element->value.complex->semanticAction = 0; + element->value.complex->num_semanticAction = 0; + return element; +} - while (len >= 4) - { - char i0, i1, i2, i3; - char *p; - - if (!(p = strchr(map, in[0]))) - return 0; - i0 = p - map; - len--; - if (!(p = strchr(map, in[1]))) - return 0; - i1 = p - map; - len--; - *(out++) = i0 << 2 | i1 >> 4; - olen++; - if (in[2] == '=') - break; - if (!(p = strchr(map, in[2]))) - return 0; - i2 = p - map; - len--; - *(out++) = i1 << 4 | i2 >> 2; - olen++; - if (in[3] == '=') - break; - if (!(p = strchr(map, in[3]))) - return 0; - i3 = p - map; - len--; - *(out++) = i2 << 6 | i3; - olen++; - - in += 4; - } +Z_AttributeList *yaz_use_attribute_create(ODR o, const char *name) +{ + Z_AttributeList *attributes = (Z_AttributeList *) + odr_malloc(o, sizeof(*attributes)); + + attributes->num_attributes = 1; + attributes->attributes = (Z_AttributeElement**) + odr_malloc(o, sizeof(*attributes->attributes)); + attributes->attributes[0] = yaz_string_element_create(o, 1, name); + return attributes; +} - *out = '\0'; - return olen; +#if YAZ_HAVE_XML2 +const char *yaz_element_attribute_value_get(xmlNodePtr ptr, + const char *node_name, + const char *attribute_name) +{ + struct _xmlAttr *attr; + // check if the node name matches + if (strcmp((const char*) ptr->name, node_name)) + return 0; + // check if the attribute name and return the value + for (attr = ptr->properties; attr; attr = attr->next) + if (attr->children && attr->children->type == XML_TEXT_NODE) + { + if (!strcmp((const char *) attr->name, attribute_name)) + return (const char *) attr->children->content; + } + return 0; } #endif @@ -99,7 +111,6 @@ int yaz_srw_check_content_type(Z_HTTP_Response *hres) * Look for authentication tokens in HTTP Basic parameters or in x-username/x-password * parameters. Added by SH. */ -#if YAZ_HAVE_XML2 static void yaz_srw_decodeauth(Z_SRW_PDU *sr, Z_HTTP_Request *hreq, char *username, char *password, ODR decode) { @@ -110,8 +121,9 @@ static void yaz_srw_decodeauth(Z_SRW_PDU *sr, Z_HTTP_Request *hreq, if (password) sr->password = password; - if (basic) { - int len, olen; + if (basic) + { + int len; char out[256]; char ubuf[256] = "", pbuf[256] = "", *p; if (strncmp(basic, "Basic ", 6)) @@ -120,10 +132,11 @@ static void yaz_srw_decodeauth(Z_SRW_PDU *sr, Z_HTTP_Request *hreq, len = strlen(basic); if (!len || len > 256) return; - olen = yaz_base64decode(basic, out); + yaz_base64decode(basic, out); /* Format of out should be username:password at this point */ strcpy(ubuf, out); - if ((p = strchr(ubuf, ':'))) { + if ((p = strchr(ubuf, ':'))) + { *(p++) = '\0'; if (*p) strcpy(pbuf, p); @@ -134,16 +147,8 @@ static void yaz_srw_decodeauth(Z_SRW_PDU *sr, Z_HTTP_Request *hreq, sr->password = odr_strdup(decode, pbuf); } } -#endif - -void yaz_uri_val_int(const char *path, const char *name, ODR o, Odr_int **intp) -{ - const char *v = yaz_uri_val(path, name, o); - if (v) - *intp = odr_intdup(o, atoi(v)); -} -void yaz_mk_srw_diagnostic(ODR o, Z_SRW_diagnostic *d, +void yaz_mk_srw_diagnostic(ODR o, Z_SRW_diagnostic *d, const char *uri, const char *message, const char *details) { @@ -158,11 +163,11 @@ void yaz_mk_srw_diagnostic(ODR o, Z_SRW_diagnostic *d, d->details = 0; } -void yaz_mk_std_diagnostic(ODR o, Z_SRW_diagnostic *d, +void yaz_mk_std_diagnostic(ODR o, Z_SRW_diagnostic *d, int code, const char *details) { char uri[40]; - + sprintf(uri, "info:srw/diagnostic/1/%d", code); yaz_mk_srw_diagnostic(o, d, uri, 0, details); } @@ -172,9 +177,9 @@ void yaz_add_srw_diagnostic_uri(ODR o, Z_SRW_diagnostic **d, const char *message, const char *details) { Z_SRW_diagnostic *d_new; - d_new = (Z_SRW_diagnostic *) odr_malloc (o, (*num + 1)* sizeof(**d)); + d_new = (Z_SRW_diagnostic *) odr_malloc(o, (*num + 1)* sizeof(**d)); if (*num) - memcpy (d_new, *d, *num *sizeof(**d)); + memcpy(d_new, *d, *num *sizeof(**d)); *d = d_new; yaz_mk_srw_diagnostic(o, *d + *num, uri, message, details); @@ -185,7 +190,7 @@ void yaz_add_srw_diagnostic(ODR o, Z_SRW_diagnostic **d, int *num, int code, const char *addinfo) { char uri[40]; - + sprintf(uri, "info:srw/diagnostic/1/%d", code); yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo); } @@ -195,7 +200,7 @@ void yaz_add_sru_update_diagnostic(ODR o, Z_SRW_diagnostic **d, int *num, int code, const char *addinfo) { char uri[40]; - + sprintf(uri, "info:srw/diagnostic/12/%d", code); yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo); } @@ -210,9 +215,9 @@ void yaz_mk_sru_surrogate(ODR o, Z_SRW_record *record, int pos, len += strlen(message); if (details) len += strlen(details); - + record->recordData_buf = (char *) odr_malloc(o, len); - + sprintf(record->recordData_buf, "\n" " info:srw/diagnostic/1/%d\n", code); @@ -232,18 +237,25 @@ void yaz_mk_sru_surrogate(ODR o, Z_SRW_record *record, int pos, static void grab_charset(ODR o, const char *content_type, char **charset) { if (charset) - { + { const char *charset_p = 0; if (content_type && (charset_p = strstr(content_type, "; charset="))) { - int i = 0; - charset_p += 10; - while (i < 20 && charset_p[i] && - !strchr("; \n\r", charset_p[i])) - i++; - *charset = (char*) odr_malloc(o, i+1); - memcpy(*charset, charset_p, i); - (*charset)[i] = '\0'; + int j = 0, i = 0; + int sep = 0; + charset_p += 10; /* skip ; charset= */ + if (charset_p[i] == '"' || charset_p[i] == '\'') + sep = charset_p[i++]; + *charset = odr_strdup(o, charset_p); + while (charset_p[i] && charset_p[i] != sep) + { + if (!sep && strchr("; \n\r", charset_p[i])) + break; + if (charset_p[i] == '\\' && charset_p[i+1]) + i++; + (*charset)[j++] = charset_p[i++]; + } + (*charset)[j] = '\0'; } } } @@ -255,7 +267,7 @@ int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu, { const char *content_type = z_HTTP_header_lookup(hreq->headers, "Content-Type"); - if (content_type && + if (content_type && (!yaz_strcmp_del("text/xml", content_type, "; ") || !yaz_strcmp_del("application/soap+xml", content_type, "; ") || !yaz_strcmp_del("text/plain", content_type, "; "))) @@ -263,16 +275,17 @@ int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu, char *db = "Default"; const char *p0 = hreq->path, *p1; int ret = -1; - - static Z_SOAP_Handler soap_handlers[4] = { + + static Z_SOAP_Handler soap_handlers[5] = { #if YAZ_HAVE_XML2 { YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec }, { YAZ_XMLNS_SRU_v1_0, 0, (Z_SOAP_fun) yaz_srw_codec }, { YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec }, + { YAZ_XMLNS_SRU_v2_mask, 0, (Z_SOAP_fun) yaz_srw_codec }, #endif {0, 0, 0} }; - + if (*p0 == '/') p0++; p1 = strchr(p0, '?'); @@ -280,15 +293,19 @@ int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu, p1 = p0 + strlen(p0); if (p1 != p0) db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0); - grab_charset(decode, content_type, charset); - ret = z_soap_codec(decode, soap_package, + ret = z_soap_codec(decode, soap_package, &hreq->content_buf, &hreq->content_len, soap_handlers); if (ret == 0 && (*soap_package)->which == Z_SOAP_generic) { *srw_pdu = (Z_SRW_PDU*) (*soap_package)->u.generic->p; - + yaz_srw_decodeauth(*srw_pdu, hreq, 0, 0, decode); + + /* last entry in handlers - SRU 2.0 - is turned into + offset 0.. due to other pieces relying on it */ + if ((*soap_package)->u.generic->no == 3) + (*soap_package)->u.generic->no = 0; if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request && (*srw_pdu)->u.request->database == 0) (*srw_pdu)->u.request->database = db; @@ -314,7 +331,7 @@ int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu, } #if YAZ_HAVE_XML2 -static int yaz_sru_decode_integer(ODR odr, const char *pname, +static int yaz_sru_decode_integer(ODR odr, const char *pname, const char *valstr, Odr_int **valp, Z_SRW_diagnostic **diag, int *num_diag, int min_value) @@ -341,7 +358,7 @@ static int yaz_sru_decode_integer(ODR odr, const char *pname, /** http://www.loc.gov/z3950/agency/zing/srw/service.html -*/ +*/ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu, Z_SOAP **soap_package, ODR decode, char **charset, Z_SRW_diagnostic **diag, int *num_diag) @@ -361,7 +378,7 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu, not "multipart/form-data" . */ if (!strcmp(hreq->method, "GET") - || + || (!strcmp(hreq->method, "POST") && content_type && !yaz_strcmp_del("application/x-www-form-urlencoded", content_type, "; "))) @@ -372,21 +389,23 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu, const char *operation = 0; char *version = 0; char *query = 0; - char *pQuery = 0; + char *queryType = "cql"; char *username = 0; char *password = 0; char *sortKeys = 0; char *stylesheet = 0; char *scanClause = 0; - char *pScanClause = 0; char *recordXPath = 0; char *recordSchema = 0; - char *recordPacking = "xml"; /* xml packing is default for SRU */ + char *recordXMLEscaping = 0; + char *recordPacking = 0; char *maximumRecords = 0; char *startRecord = 0; char *maximumTerms = 0; char *responsePosition = 0; - char *extraRequestData = 0; + const char *facetLimit = 0; + const char *facetStart = 0; + const char *facetSort = 0; Z_SRW_extra_arg *extra_args = 0; #endif char **uri_name; @@ -417,7 +436,12 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu, if (!strcmp(n, "query")) query = v; else if (!strcmp(n, "x-pquery")) - pQuery = v; + { + query = v; + queryType = "pqf"; + } + else if (!strcmp(n, "queryType")) + queryType = v; else if (!strcmp(n, "x-username")) username = v; else if (!strcmp(n, "x-password")) @@ -434,12 +458,17 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu, recordSchema = v; else if (!strcmp(n, "recordPacking")) recordPacking = v; + else if (!strcmp(n, "recordXMLEscaping")) + recordXMLEscaping = v; else if (!strcmp(n, "version")) version = v; else if (!strcmp(n, "scanClause")) scanClause = v; else if (!strcmp(n, "x-pScanClause")) - pScanClause = v; + { + scanClause = v; + queryType = "pqf"; + } else if (!strcmp(n, "maximumRecords")) maximumRecords = v; else if (!strcmp(n, "startRecord")) @@ -448,8 +477,14 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu, maximumTerms = v; else if (!strcmp(n, "responsePosition")) responsePosition = v; + else if (!strcmp(n, "facetLimit")) + facetLimit = v; + else if (!strcmp(n, "facetStart")) + facetStart = v; + else if (!strcmp(n, "facetSort")) + facetSort = v; else if (!strcmp(n, "extraRequestData")) - extraRequestData = v; + ; /* ignoring extraRequestData */ else if (n[0] == 'x' && n[1] == '-') { Z_SRW_extra_arg **l = &extra_args; @@ -461,36 +496,50 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu, (*l)->next = 0; } else - yaz_add_srw_diagnostic(decode, diag, num_diag, - YAZ_SRW_UNSUPP_PARAMETER, n); + { + if (*num_diag < 10) + yaz_add_srw_diagnostic(decode, diag, num_diag, + YAZ_SRW_UNSUPP_PARAMETER, n); + } } } - if (!version) + if (!operation) { - if (uri_name) - yaz_add_srw_diagnostic( - decode, diag, num_diag, - YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "version"); - version = "1.1"; + if (query) + operation = "searchRetrieve"; + else if (scanClause) + operation = "scan"; } - version = yaz_negotiate_sru_version(version); if (!version) { /* negotiation failed. */ yaz_add_srw_diagnostic(decode, diag, num_diag, - YAZ_SRW_UNSUPP_VERSION, "1.2"); - version = "1.2"; + YAZ_SRW_UNSUPP_VERSION, "2.0"); + version = "2.0"; } - if (!operation) { if (uri_name) yaz_add_srw_diagnostic( - decode, diag, num_diag, + decode, diag, num_diag, YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "operation"); operation = "explain"; } + if (strcmp(version, "2.0")) + { + if (recordXMLEscaping) + { + yaz_add_srw_diagnostic(decode, diag, num_diag, + YAZ_SRW_UNSUPP_PARAMETER, + "recordXMLEscaping"); + + } + recordXMLEscaping = recordPacking; + recordPacking = "packed"; + } + if (!recordXMLEscaping) + recordXMLEscaping = "xml"; if (!strcmp(operation, "searchRetrieve")) { Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request); @@ -499,19 +548,13 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu, sr->extra_args = extra_args; *srw_pdu = sr; yaz_srw_decodeauth(sr, hreq, username, password, decode); - if (query) - { - sr->u.request->query_type = Z_SRW_query_type_cql; - sr->u.request->query.cql = query; - } - else if (pQuery) - { - sr->u.request->query_type = Z_SRW_query_type_pqf; - sr->u.request->query.pqf = pQuery; - } - else + + sr->u.request->queryType = queryType; + sr->u.request->query = query; + + if (!query) yaz_add_srw_diagnostic( - decode, diag, num_diag, + decode, diag, num_diag, YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "query"); if (sortKeys) @@ -521,14 +564,17 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu, } sr->u.request->recordXPath = recordXPath; sr->u.request->recordSchema = recordSchema; - sr->u.request->recordPacking = recordPacking; + sr->u.request->recordPacking = recordXMLEscaping; + sr->u.request->packing = recordPacking; sr->u.request->stylesheet = stylesheet; + yaz_sru_facet_request(decode , &sr->u.request->facetList, + &facetLimit, &facetStart, &facetSort); - yaz_sru_decode_integer(decode, "maximumRecords", maximumRecords, - &sr->u.request->maximumRecords, + yaz_sru_decode_integer(decode, "maximumRecords", maximumRecords, + &sr->u.request->maximumRecords, diag, num_diag, 0); - - yaz_sru_decode_integer(decode, "startRecord", startRecord, + + yaz_sru_decode_integer(decode, "startRecord", startRecord, &sr->u.request->startRecord, diag, num_diag, 1); @@ -537,14 +583,14 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu, (*soap_package) = (Z_SOAP *) odr_malloc(decode, sizeof(**soap_package)); (*soap_package)->which = Z_SOAP_generic; - + (*soap_package)->u.generic = (Z_SOAP_Generic *) odr_malloc(decode, sizeof(*(*soap_package)->u.generic)); - + (*soap_package)->u.generic->p = sr; (*soap_package)->u.generic->ns = soap_handlers[0].ns; (*soap_package)->u.generic->no = 0; - + (*soap_package)->ns = "SRU"; return 0; @@ -559,7 +605,8 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu, sr->extra_args = extra_args; yaz_srw_decodeauth(sr, hreq, username, password, decode); *srw_pdu = sr; - sr->u.explain_request->recordPacking = recordPacking; + sr->u.explain_request->recordPacking = recordXMLEscaping; + sr->u.explain_request->packing = recordPacking; sr->u.explain_request->database = db; sr->u.explain_request->stylesheet = stylesheet; @@ -567,14 +614,14 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu, (*soap_package) = (Z_SOAP *) odr_malloc(decode, sizeof(**soap_package)); (*soap_package)->which = Z_SOAP_generic; - + (*soap_package)->u.generic = (Z_SOAP_Generic *) odr_malloc(decode, sizeof(*(*soap_package)->u.generic)); - + (*soap_package)->u.generic->p = sr; (*soap_package)->u.generic->ns = soap_handlers[0].ns; (*soap_package)->u.generic->no = 0; - + (*soap_package)->ns = "SRU"; return 0; @@ -590,29 +637,22 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu, *srw_pdu = sr; yaz_srw_decodeauth(sr, hreq, username, password, decode); - if (scanClause) - { - sr->u.scan_request->query_type = Z_SRW_query_type_cql; - sr->u.scan_request->scanClause.cql = scanClause; - } - else if (pScanClause) - { - sr->u.scan_request->query_type = Z_SRW_query_type_pqf; - sr->u.scan_request->scanClause.pqf = pScanClause; - } - else + sr->u.scan_request->queryType = queryType; + sr->u.scan_request->scanClause = scanClause; + + if (!scanClause) yaz_add_srw_diagnostic( - decode, diag, num_diag, + decode, diag, num_diag, YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "scanClause"); sr->u.scan_request->database = db; - + yaz_sru_decode_integer(decode, "maximumTerms", - maximumTerms, + maximumTerms, &sr->u.scan_request->maximumTerms, diag, num_diag, 0); - + yaz_sru_decode_integer(decode, "responsePosition", - responsePosition, + responsePosition, &sr->u.scan_request->responsePosition, diag, num_diag, 0); @@ -621,14 +661,14 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu, (*soap_package) = (Z_SOAP *) odr_malloc(decode, sizeof(**soap_package)); (*soap_package)->which = Z_SOAP_generic; - + (*soap_package)->u.generic = (Z_SOAP_Generic *) odr_malloc(decode, sizeof(*(*soap_package)->u.generic)); - + (*soap_package)->u.generic->p = sr; (*soap_package)->u.generic->ns = soap_handlers[0].ns; (*soap_package)->u.generic->no = 0; - + (*soap_package)->ns = "SRU"; return 0; @@ -650,22 +690,23 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu, (*soap_package) = (Z_SOAP *) odr_malloc(decode, sizeof(**soap_package)); (*soap_package)->which = Z_SOAP_generic; - + (*soap_package)->u.generic = (Z_SOAP_Generic *) odr_malloc(decode, sizeof(*(*soap_package)->u.generic)); - + (*soap_package)->u.generic->p = sr; (*soap_package)->u.generic->ns = soap_handlers[0].ns; (*soap_package)->u.generic->no = 0; - + (*soap_package)->ns = "SRU"; - yaz_add_srw_diagnostic(decode, diag, num_diag, + yaz_add_srw_diagnostic(decode, diag, num_diag, YAZ_SRW_UNSUPP_OPERATION, operation); return 0; } -#endif +#else return 1; +#endif } return 2; } @@ -715,14 +756,14 @@ static Z_SRW_PDU *yaz_srw_get_core_ver(ODR o, const char *version) return p; } -Z_SRW_PDU *yaz_srw_get_core_v_1_1(ODR o) +Z_SRW_PDU *yaz_srw_get_core_v_2_0(ODR o) { - return yaz_srw_get_core_ver(o, "1.1"); + return yaz_srw_get_core_ver(o, "2.0"); } Z_SRW_PDU *yaz_srw_get(ODR o, int which) { - return yaz_srw_get_pdu(o, which, "1.1"); + return yaz_srw_get_pdu(o, which, "2.0"); } Z_SRW_PDU *yaz_srw_get_pdu(ODR o, int which, const char *version) @@ -735,23 +776,26 @@ Z_SRW_PDU *yaz_srw_get_pdu(ODR o, int which, const char *version) case Z_SRW_searchRetrieve_request: sr->u.request = (Z_SRW_searchRetrieveRequest *) odr_malloc(o, sizeof(*sr->u.request)); - sr->u.request->query_type = Z_SRW_query_type_cql; - sr->u.request->query.cql = 0; + sr->u.request->queryType = "cql"; + sr->u.request->query = 0; sr->u.request->sort_type = Z_SRW_sort_type_none; sr->u.request->sort.none = 0; sr->u.request->startRecord = 0; sr->u.request->maximumRecords = 0; sr->u.request->recordSchema = 0; sr->u.request->recordPacking = 0; + sr->u.request->packing = 0; sr->u.request->recordXPath = 0; sr->u.request->database = 0; sr->u.request->resultSetTTL = 0; sr->u.request->stylesheet = 0; + sr->u.request->facetList = 0; break; case Z_SRW_searchRetrieve_response: sr->u.response = (Z_SRW_searchRetrieveResponse *) odr_malloc(o, sizeof(*sr->u.response)); sr->u.response->numberOfRecords = 0; + sr->u.response->resultCountPrecision = 0; sr->u.response->resultSetId = 0; sr->u.response->resultSetIdleTime = 0; sr->u.response->records = 0; @@ -760,11 +804,14 @@ Z_SRW_PDU *yaz_srw_get_pdu(ODR o, int which, const char *version) sr->u.response->num_diagnostics = 0; sr->u.response->nextRecordPosition = 0; sr->u.response->extra_records = 0; + sr->u.response->facetList = 0; + sr->u.response->suggestions = 0; break; case Z_SRW_explain_request: sr->u.explain_request = (Z_SRW_explainRequest *) odr_malloc(o, sizeof(*sr->u.explain_request)); sr->u.explain_request->recordPacking = 0; + sr->u.explain_request->packing = 0; sr->u.explain_request->database = 0; sr->u.explain_request->stylesheet = 0; break; @@ -788,8 +835,8 @@ Z_SRW_PDU *yaz_srw_get_pdu(ODR o, int which, const char *version) sr->u.scan_request->stylesheet = 0; sr->u.scan_request->maximumTerms = 0; sr->u.scan_request->responsePosition = 0; - sr->u.scan_request->query_type = Z_SRW_query_type_cql; - sr->u.scan_request->scanClause.cql = 0; + sr->u.scan_request->queryType = "cql"; + sr->u.scan_request->scanClause = 0; break; case Z_SRW_scan_response: sr->u.scan_response = (Z_SRW_scanResponse *) @@ -830,222 +877,6 @@ Z_SRW_PDU *yaz_srw_get_pdu(ODR o, int which, const char *version) return sr; } -/* bib1:srw */ -static int bib1_srw_map[] = { - 1, 1, - 2, 2, - 3, 11, - 4, 35, - 5, 12, - 6, 38, - 7, 30, - 8, 32, - 9, 29, - 108, 10, /* Malformed query : Syntax error */ - 10, 10, - 11, 12, - 11, 23, - 12, 60, - 13, 61, - 13, 62, - 14, 63, - 14, 64, - 14, 65, - 15, 68, - 15, 69, - 16, 70, - 17, 70, - 18, 50, - 19, 55, - 20, 56, - 21, 52, - 22, 50, - 23, 3, - 24, 66, - 25, 66, - 26, 66, - 27, 51, - 28, 52, - 29, 52, - 30, 51, - 31, 57, - 32, 58, - 33, 59, - 100, 1, /* bad map */ - 101, 3, - 102, 3, - 103, 3, - 104, 3, - 105, 3, - 106, 66, - 107, 11, - 108, 13, - 108, 14, - 108, 25, - 108, 26, - 108, 27, - 108, 45, - - 109, 2, - 110, 37, - 111, 1, - 112, 58, - 113, 10, - 114, 16, - 115, 16, - 116, 16, - 117, 19, - 117, 20, - 118, 22, - 119, 32, - 119, 31, - 120, 28, - 121, 15, - 122, 32, - 123, 22, - 123, 17, - 123, 18, - 124, 24, - 125, 36, - 126, 36, - 127, 36, - 128, 51, - 129, 39, - 130, 43, - 131, 40, - 132, 42, - 201, 44, - 201, 33, - 201, 34, - 202, 41, - 203, 43, - 205, 1, /* bad map */ - 206, 1, /* bad map */ - 207, 89, - 208, 1, /* bad map */ - 209, 80, - 210, 80, - 210, 81, - 211, 84, - 212, 85, - 213, 92, - 214, 90, - 215, 91, - 216, 92, - 217, 63, - 218, 1, /* bad map */ - 219, 1, /* bad map */ - 220, 1, /* bad map */ - 221, 1, /* bad map */ - 222, 3, - 223, 1, /* bad map */ - 224, 1, /* bad map */ - 225, 1, /* bad map */ - 226, 1, /* bad map */ - 227, 66, - 228, 1, /* bad map */ - 229, 36, - 230, 83, - 231, 89, - 232, 1, - 233, 1, /* bad map */ - 234, 1, /* bad map */ - 235, 2, - 236, 3, - 237, 82, - 238, 67, - 239, 66, - 240, 1, /* bad map */ - 241, 1, /* bad map */ - 242, 70, - 243, 1, /* bad map */ - 244, 66, - 245, 10, - 246, 10, - 247, 10, - 1001, 1, /* bad map */ - 1002, 1, /* bad map */ - 1003, 1, /* bad map */ - 1004, 1, /* bad map */ - 1005, 1, /* bad map */ - 1006, 1, /* bad map */ - 1007, 100, - 1008, 1, - 1009, 1, - 1010, 3, - 1011, 3, - 1012, 3, - 1013, 3, - 1014, 3, - 1015, 3, - 1015, 3, - 1016, 3, - 1017, 3, - 1018, 2, - 1019, 2, - 1020, 2, - 1021, 3, - 1022, 3, - 1023, 3, - 1024, 16, - 1025, 3, - 1026, 64, - 1027, 1, - 1028, 65, - 1029, 1, - 1040, 1, - /* 1041-1065 */ - 1066, 66, - 1066, 67, - 0 -}; - -/* - * This array contains overrides for when the first occurrence of a - * particular SRW error in the array above does not correspond with - * the best back-translation of that SRW error. - */ -static int srw_bib1_map[] = { - 66, 238, - /* No doubt there are many more */ - 0 -}; - - -int yaz_diag_bib1_to_srw (int code) -{ - const int *p = bib1_srw_map; - while (*p) - { - if (code == p[0]) - return p[1]; - p += 2; - } - return 1; -} - -int yaz_diag_srw_to_bib1(int code) -{ - /* Check explicit reverse-map first */ - const int *p = srw_bib1_map; - while (*p) - { - if (code == p[0]) - return p[1]; - p += 2; - } - - /* Fall back on reverse lookup in main map */ - p = bib1_srw_map; - while (*p) - { - if (code == p[1]) - return p[0]; - p += 2; - } - return 1; -} - void yaz_add_name_value_int(ODR o, char **name, char **value, int *i, char *a_name, Odr_int *val) { @@ -1072,78 +903,131 @@ void yaz_add_name_value_str(ODR o, char **name, char **value, int *i, static int yaz_get_sru_parms(const Z_SRW_PDU *srw_pdu, ODR encode, char **name, char **value, int max_names) { + int version2 = strcmp(srw_pdu->srw_version, "2.") > 0; int i = 0; - yaz_add_name_value_str(encode, name, value, &i, "version", srw_pdu->srw_version); + char *queryType; + yaz_add_name_value_str(encode, name, value, &i, "version", + srw_pdu->srw_version); name[i] = "operation"; - switch(srw_pdu->which) + switch (srw_pdu->which) { case Z_SRW_searchRetrieve_request: value[i++] = "searchRetrieve"; - switch(srw_pdu->u.request->query_type) + queryType = srw_pdu->u.request->queryType; + if (version2) { - case Z_SRW_query_type_cql: + if (queryType && strcmp(queryType, "cql")) + yaz_add_name_value_str(encode, name, value, &i, "queryType", + queryType); yaz_add_name_value_str(encode, name, value, &i, "query", - srw_pdu->u.request->query.cql); - break; - case Z_SRW_query_type_pqf: - yaz_add_name_value_str(encode, name, value, &i, "x-pquery", - srw_pdu->u.request->query.pqf); - break; - case Z_SRW_query_type_xcql: - yaz_add_name_value_str(encode, name, value, &i, "x-cql", - srw_pdu->u.request->query.xcql); - break; + srw_pdu->u.request->query); + } + else + { + if (!strcmp(queryType, "cql")) + { + yaz_add_name_value_str(encode, name, value, &i, "query", + srw_pdu->u.request->query); + } + else if (!strcmp(queryType, "pqf")) + { + yaz_add_name_value_str(encode, name, value, &i, "x-pquery", + srw_pdu->u.request->query); + } + else if (!strcmp(queryType, "xcql")) + { + yaz_add_name_value_str(encode, name, value, &i, "x-cql", + srw_pdu->u.request->query); + } } - switch(srw_pdu->u.request->sort_type) + switch (srw_pdu->u.request->sort_type) { case Z_SRW_sort_type_none: break; - case Z_SRW_sort_type_sort: + case Z_SRW_sort_type_sort: yaz_add_name_value_str(encode, name, value, &i, "sortKeys", srw_pdu->u.request->sort.sortKeys); break; } - yaz_add_name_value_int(encode, name, value, &i, "startRecord", + yaz_add_name_value_int(encode, name, value, &i, "startRecord", srw_pdu->u.request->startRecord); - yaz_add_name_value_int(encode, name, value, &i, "maximumRecords", + yaz_add_name_value_int(encode, name, value, &i, "maximumRecords", srw_pdu->u.request->maximumRecords); yaz_add_name_value_str(encode, name, value, &i, "recordSchema", srw_pdu->u.request->recordSchema); - yaz_add_name_value_str(encode, name, value, &i, "recordPacking", - srw_pdu->u.request->recordPacking); + if (version2) + { + yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping", + srw_pdu->u.request->recordPacking); + yaz_add_name_value_str(encode, name, value, &i, "recordPacking", + srw_pdu->u.request->packing); + } + else + yaz_add_name_value_str(encode, name, value, &i, "recordPacking", + srw_pdu->u.request->recordPacking); yaz_add_name_value_str(encode, name, value, &i, "recordXPath", srw_pdu->u.request->recordXPath); yaz_add_name_value_str(encode, name, value, &i, "stylesheet", srw_pdu->u.request->stylesheet); - yaz_add_name_value_int(encode, name, value, &i, "resultSetTTL", + yaz_add_name_value_int(encode, name, value, &i, "resultSetTTL", srw_pdu->u.request->resultSetTTL); + { + const char *facetLimit = 0; + const char *facetStart = 0; + const char *facetSort = 0; + yaz_sru_facet_request(encode, &srw_pdu->u.request->facetList, + &facetLimit, &facetStart, &facetSort); + yaz_add_name_value_str(encode, name, value, &i, "facetLimit", + (char *) facetLimit); + yaz_add_name_value_str(encode, name, value, &i, "facetStart", + (char *) facetStart); + yaz_add_name_value_str(encode, name, value, &i, "facetSort", + (char *) facetSort); + } break; case Z_SRW_explain_request: value[i++] = "explain"; + + if (version2) + { + yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping", + srw_pdu->u.explain_request->recordPacking); + yaz_add_name_value_str(encode, name, value, &i, "recordPacking", + srw_pdu->u.explain_request->packing); + } + else + yaz_add_name_value_str(encode, name, value, &i, "recordPacking", + srw_pdu->u.explain_request->recordPacking); yaz_add_name_value_str(encode, name, value, &i, "stylesheet", srw_pdu->u.explain_request->stylesheet); break; case Z_SRW_scan_request: value[i++] = "scan"; - - switch(srw_pdu->u.scan_request->query_type) + queryType = srw_pdu->u.scan_request->queryType; + if (version2) { - case Z_SRW_query_type_cql: + if (queryType && strcmp(queryType, "cql")) + yaz_add_name_value_str(encode, name, value, &i, "queryType", + queryType); yaz_add_name_value_str(encode, name, value, &i, "scanClause", - srw_pdu->u.scan_request->scanClause.cql); - break; - case Z_SRW_query_type_pqf: - yaz_add_name_value_str(encode, name, value, &i, "x-pScanClause", - srw_pdu->u.scan_request->scanClause.pqf); - break; - case Z_SRW_query_type_xcql: - yaz_add_name_value_str(encode, name, value, &i, "x-cqlScanClause", - srw_pdu->u.scan_request->scanClause.xcql); - break; + srw_pdu->u.scan_request->scanClause); } - yaz_add_name_value_int(encode, name, value, &i, "responsePosition", + else + { + if (!queryType || !strcmp(queryType, "cql")) + yaz_add_name_value_str(encode, name, value, &i, "scanClause", + srw_pdu->u.scan_request->scanClause); + else if (!strcmp(queryType, "pqf")) + yaz_add_name_value_str(encode, name, value, &i, "x-pScanClause", + srw_pdu->u.scan_request->scanClause); + else if (!strcmp(queryType, "xcql")) + yaz_add_name_value_str(encode, name, value, &i, + "x-cqlScanClause", + srw_pdu->u.scan_request->scanClause); + } + yaz_add_name_value_int(encode, name, value, &i, "responsePosition", srw_pdu->u.scan_request->responsePosition); - yaz_add_name_value_int(encode, name, value, &i, "maximumTerms", + yaz_add_name_value_int(encode, name, value, &i, "maximumTerms", srw_pdu->u.scan_request->maximumTerms); yaz_add_name_value_str(encode, name, value, &i, "stylesheet", srw_pdu->u.scan_request->stylesheet); @@ -1172,22 +1056,28 @@ static int yaz_get_sru_parms(const Z_SRW_PDU *srw_pdu, ODR encode, int yaz_sru_get_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu, ODR encode, const char *charset) { - char *name[30], *value[30]; /* definite upper limit for SRU params */ + char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */ char *uri_args; char *path; + char *cp; - z_HTTP_header_add_basic_auth(encode, &hreq->headers, + z_HTTP_header_add_basic_auth(encode, &hreq->headers, srw_pdu->username, srw_pdu->password); - if (yaz_get_sru_parms(srw_pdu, encode, name, value, 30)) + if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS)) return -1; yaz_array_to_uri(&uri_args, encode, name, value); hreq->method = "GET"; - + + cp = strchr(hreq->path, '#'); + if (cp) + *cp = '\0'; + path = (char *) odr_malloc(encode, strlen(hreq->path) + strlen(uri_args) + 4); - sprintf(path, "%s?%s", hreq->path, uri_args); + sprintf(path, "%s%c%s", hreq->path, strchr(hreq->path, '?') ? '&' : '?', + uri_args); hreq->path = path; z_HTTP_header_add_content_type(encode, &hreq->headers, @@ -1198,18 +1088,18 @@ int yaz_sru_get_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu, int yaz_sru_post_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu, ODR encode, const char *charset) { - char *name[30], *value[30]; /* definite upper limit for SRU params */ + char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */ char *uri_args; - z_HTTP_header_add_basic_auth(encode, &hreq->headers, + z_HTTP_header_add_basic_auth(encode, &hreq->headers, srw_pdu->username, srw_pdu->password); - if (yaz_get_sru_parms(srw_pdu, encode, name, value, 30)) + if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS)) return -1; yaz_array_to_uri(&uri_args, encode, name, value); hreq->method = "POST"; - + hreq->content_buf = uri_args; hreq->content_len = strlen(uri_args); @@ -1231,12 +1121,12 @@ int yaz_sru_soap_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu, }; Z_SOAP *p = (Z_SOAP*) odr_malloc(odr, sizeof(*p)); - z_HTTP_header_add_basic_auth(odr, &hreq->headers, + z_HTTP_header_add_basic_auth(odr, &hreq->headers, srw_pdu->username, srw_pdu->password); z_HTTP_header_add_content_type(odr, &hreq->headers, - "text/xml", charset); - + "text/xml", 0 /* no charset in MIME */); + z_HTTP_header_add(odr, &hreq->headers, "SOAPAction", "\"\""); p->which = Z_SOAP_generic; @@ -1257,12 +1147,13 @@ int yaz_sru_soap_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu, charset); } -Z_SRW_recordVersion *yaz_srw_get_record_versions(ODR odr, int num ) +Z_SRW_recordVersion *yaz_srw_get_record_versions(ODR odr, int num) { - Z_SRW_recordVersion *ver - = (Z_SRW_recordVersion *) odr_malloc( odr, num * sizeof(*ver) ); + Z_SRW_recordVersion *ver + = (Z_SRW_recordVersion *) odr_malloc(odr,num * sizeof(*ver)); int i; - for ( i=0; i < num; ++i ){ + for (i = 0; i < num; ++i) + { ver[i].versionType = 0; ver[i].versionValue = 0; } @@ -1303,6 +1194,9 @@ void yaz_encode_sru_extra(Z_SRW_PDU *sr, ODR odr, const char *extra_args) Z_SRW_extra_arg **ea = &sr->extra_args; yaz_uri_to_array(extra_args, odr, &name, &val); + /** append rather than override */ + while (*ea) + ea = &(*ea)->next; while (*name) { *ea = (Z_SRW_extra_arg *) odr_malloc(odr, sizeof(**ea));