1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2008 Index Data
3 * See the file LICENSE for details.
7 * \brief Implements SRW/SRU utilities.
12 #include <yaz/yaz-iconv.h>
14 static int hex_digit (int ch)
16 if (ch >= '0' && ch <= '9')
18 else if (ch >= 'a' && ch <= 'f')
20 else if (ch >= 'A' && ch <= 'F')
25 void encode_uri_char(char *dst, char ch)
29 /* mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" */
30 else if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') ||
31 (ch >= '0' && ch <= '9') || strchr("-_.!~*'(|)", ch))
39 sprintf(dst+1, "%02X", (unsigned char ) ch);
43 static void yaz_array_to_uri(char **path, ODR o, char **name, char **value)
45 size_t i, szp = 0, sz = 1;
46 for(i = 0; name[i]; i++)
47 sz += strlen(name[i]) + 3 + strlen(value[i]) * 3;
48 *path = (char *) odr_malloc(o, sz);
50 for(i = 0; name[i]; i++)
55 ilen = strlen(name[i]);
56 memcpy(*path+szp, name[i], ilen);
59 for (j = 0; value[i][j]; j++)
63 encode_uri_char(vstr, value[i][j]);
65 memcpy(*path+szp, vstr, vlen);
72 int yaz_uri_to_array(const char *path, ODR o, char ***name, char ***val)
82 while ((cp = strchr(cp, '&')))
87 *name = (char **) odr_malloc(o, no * sizeof(char*));
88 *val = (char **) odr_malloc(o, no * sizeof(char*));
90 for (no = 0; *path; no++)
92 const char *p1 = strchr(path, '=');
98 (*name)[no] = (char *) odr_malloc(o, (p1-path)+1);
99 memcpy((*name)[no], path, p1-path);
100 (*name)[no][p1-path] = '\0';
103 p1 = strchr(path, '&');
105 p1 = strlen(path) + path;
106 (*val)[no] = ret = (char *) odr_malloc(o, p1 - path + 1);
107 while (*path && *path != '&')
114 else if (*path == '%' && path[1] && path[2])
116 ret[i++] = hex_digit (path[1])*16 + hex_digit (path[2]);
132 char *yaz_uri_val(const char *path, const char *name, ODR o)
134 size_t nlen = strlen(name);
138 while (path && *path)
140 const char *p1 = strchr(path, '=');
143 if ((size_t)(p1 - path) == nlen && !memcmp(path, name, nlen))
149 p1 = strchr(path, '&');
151 p1 = strlen(path) + path;
152 ret = (char *) odr_malloc(o, p1 - path + 1);
153 while (*path && *path != '&')
160 else if (*path == '%' && path[1] && path[2])
162 ret[i++] = hex_digit (path[1])*16 + hex_digit (path[2]);
171 path = strchr(p1, '&');
179 static int yaz_base64decode(const char *in, char *out)
181 const char *map = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
182 "abcdefghijklmnopqrstuvwxyz0123456789+/";
184 int len = strlen(in);
191 if (!(p = strchr(map, in[0])))
195 if (!(p = strchr(map, in[1])))
199 *(out++) = i0 << 2 | i1 >> 4;
203 if (!(p = strchr(map, in[2])))
207 *(out++) = i1 << 4 | i2 >> 2;
211 if (!(p = strchr(map, in[3])))
215 *(out++) = i2 << 6 | i3;
226 int yaz_srw_check_content_type(Z_HTTP_Response *hres)
228 const char *content_type = z_HTTP_header_lookup(hres->headers,
232 if (!yaz_strcmp_del("text/xml", content_type, "; "))
234 if (!yaz_strcmp_del("application/xml", content_type, "; "))
241 * Look for authentication tokens in HTTP Basic parameters or in x-username/x-password
242 * parameters. Added by SH.
245 static void yaz_srw_decodeauth(Z_SRW_PDU *sr, Z_HTTP_Request *hreq,
246 char *username, char *password, ODR decode)
248 const char *basic = z_HTTP_header_lookup(hreq->headers, "Authorization");
251 sr->username = username;
253 sr->password = password;
258 char ubuf[256] = "", pbuf[256] = "", *p;
259 if (strncmp(basic, "Basic ", 6))
263 if (!len || len > 256)
265 olen = yaz_base64decode(basic, out);
266 /* Format of out should be username:password at this point */
268 if ((p = strchr(ubuf, ':'))) {
274 sr->username = odr_strdup(decode, ubuf);
276 sr->password = odr_strdup(decode, pbuf);
281 void yaz_uri_val_int(const char *path, const char *name, ODR o, int **intp)
283 const char *v = yaz_uri_val(path, name, o);
285 *intp = odr_intdup(o, atoi(v));
288 void yaz_mk_srw_diagnostic(ODR o, Z_SRW_diagnostic *d,
289 const char *uri, const char *message,
292 d->uri = odr_strdup(o, uri);
294 d->message = odr_strdup(o, message);
298 d->details = odr_strdup(o, details);
303 void yaz_mk_std_diagnostic(ODR o, Z_SRW_diagnostic *d,
304 int code, const char *details)
308 sprintf(uri, "info:srw/diagnostic/1/%d", code);
309 yaz_mk_srw_diagnostic(o, d, uri, 0, details);
312 void yaz_add_srw_diagnostic_uri(ODR o, Z_SRW_diagnostic **d,
313 int *num, const char *uri,
314 const char *message, const char *details)
316 Z_SRW_diagnostic *d_new;
317 d_new = (Z_SRW_diagnostic *) odr_malloc (o, (*num + 1)* sizeof(**d));
319 memcpy (d_new, *d, *num *sizeof(**d));
322 yaz_mk_srw_diagnostic(o, *d + *num, uri, message, details);
326 void yaz_add_srw_diagnostic(ODR o, Z_SRW_diagnostic **d,
327 int *num, int code, const char *addinfo)
331 sprintf(uri, "info:srw/diagnostic/1/%d", code);
332 yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
336 void yaz_add_sru_update_diagnostic(ODR o, Z_SRW_diagnostic **d,
337 int *num, int code, const char *addinfo)
341 sprintf(uri, "info:srw/diagnostic/12/%d", code);
342 yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
346 void yaz_mk_sru_surrogate(ODR o, Z_SRW_record *record, int pos,
347 int code, const char *details)
349 const char *message = yaz_diag_srw_str(code);
352 len += strlen(message);
354 len += strlen(details);
356 record->recordData_buf = (char *) odr_malloc(o, len);
358 sprintf(record->recordData_buf, "<diagnostic "
359 "xmlns=\"http://www.loc.gov/zing/srw/diagnostic/\">\n"
360 " <uri>info:srw/diagnostic/1/%d</uri>\n", code);
362 sprintf(record->recordData_buf + strlen(record->recordData_buf),
363 " <details>%s</details>\n", details);
365 sprintf(record->recordData_buf + strlen(record->recordData_buf),
366 " <message>%s</message>\n", message);
367 sprintf(record->recordData_buf + strlen(record->recordData_buf),
369 record->recordData_len = strlen(record->recordData_buf);
370 record->recordPosition = odr_intdup(o, pos);
371 record->recordSchema = "info:srw/schema/1/diagnostics-v1.1";
374 static void grab_charset(ODR o, const char *content_type, char **charset)
378 const char *charset_p = 0;
379 if (content_type && (charset_p = strstr(content_type, "; charset=")))
383 while (i < 20 && charset_p[i] &&
384 !strchr("; \n\r", charset_p[i]))
386 *charset = (char*) odr_malloc(o, i+1);
387 memcpy(*charset, charset_p, i);
388 (*charset)[i] = '\0';
393 int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
394 Z_SOAP **soap_package, ODR decode, char **charset)
396 if (!strcmp(hreq->method, "POST"))
398 const char *content_type = z_HTTP_header_lookup(hreq->headers,
401 (!yaz_strcmp_del("text/xml", content_type, "; ") ||
402 !yaz_strcmp_del("application/soap+xml", content_type, "; ") ||
403 !yaz_strcmp_del("text/plain", content_type, "; ")))
405 char *db = "Default";
406 const char *p0 = hreq->path, *p1;
409 static Z_SOAP_Handler soap_handlers[4] = {
411 { YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec },
412 { YAZ_XMLNS_SRU_v1_0, 0, (Z_SOAP_fun) yaz_srw_codec },
413 { YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec },
420 p1 = strchr(p0, '?');
422 p1 = p0 + strlen(p0);
425 db = (char*) odr_malloc(decode, p1 - p0 + 1);
426 memcpy (db, p0, p1 - p0);
430 grab_charset(decode, content_type, charset);
432 ret = z_soap_codec(decode, soap_package,
433 &hreq->content_buf, &hreq->content_len,
435 if (ret == 0 && (*soap_package)->which == Z_SOAP_generic)
437 *srw_pdu = (Z_SRW_PDU*) (*soap_package)->u.generic->p;
439 if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request &&
440 (*srw_pdu)->u.request->database == 0)
441 (*srw_pdu)->u.request->database = db;
443 if ((*srw_pdu)->which == Z_SRW_explain_request &&
444 (*srw_pdu)->u.explain_request->database == 0)
445 (*srw_pdu)->u.explain_request->database = db;
447 if ((*srw_pdu)->which == Z_SRW_scan_request &&
448 (*srw_pdu)->u.scan_request->database == 0)
449 (*srw_pdu)->u.scan_request->database = db;
451 if ((*srw_pdu)->which == Z_SRW_update_request &&
452 (*srw_pdu)->u.update_request->database == 0)
453 (*srw_pdu)->u.update_request->database = db;
464 static int yaz_sru_decode_integer(ODR odr, const char *pname,
465 const char *valstr, int **valp,
466 Z_SRW_diagnostic **diag, int *num_diag,
472 if (sscanf(valstr, "%d", &ival) != 1)
474 yaz_add_srw_diagnostic(odr, diag, num_diag,
475 YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
478 if (min_value >= 0 && ival < min_value)
480 yaz_add_srw_diagnostic(odr, diag, num_diag,
481 YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
484 *valp = odr_intdup(odr, ival);
490 http://www.loc.gov/z3950/agency/zing/srw/service.html
492 int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
493 Z_SOAP **soap_package, ODR decode, char **charset,
494 Z_SRW_diagnostic **diag, int *num_diag)
497 static Z_SOAP_Handler soap_handlers[2] = {
498 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
502 const char *content_type = z_HTTP_header_lookup(hreq->headers,
506 SRU GET: ignore content type.
507 SRU POST: we support "application/x-www-form-urlencoded";
508 not "multipart/form-data" .
510 if (!strcmp(hreq->method, "GET")
512 (!strcmp(hreq->method, "POST") && content_type &&
513 !yaz_strcmp_del("application/x-www-form-urlencoded",
514 content_type, "; ")))
516 char *db = "Default";
517 const char *p0 = hreq->path, *p1;
519 const char *operation = 0;
526 char *stylesheet = 0;
527 char *scanClause = 0;
528 char *pScanClause = 0;
529 char *recordXPath = 0;
530 char *recordSchema = 0;
531 char *recordPacking = "xml"; /* xml packing is default for SRU */
532 char *maximumRecords = 0;
533 char *startRecord = 0;
534 char *maximumTerms = 0;
535 char *responsePosition = 0;
536 char *extraRequestData = 0;
537 Z_SRW_extra_arg *extra_args = 0;
542 grab_charset(decode, content_type, charset);
543 if (charset && *charset == 0 && !strcmp(hreq->method, "GET"))
548 p1 = strchr(p0, '?');
550 p1 = p0 + strlen(p0);
553 db = (char*) odr_malloc(decode, p1 - p0 + 1);
554 memcpy (db, p0, p1 - p0);
557 if (!strcmp(hreq->method, "POST"))
558 p1 = hreq->content_buf;
559 yaz_uri_to_array(p1, decode, &uri_name, &uri_val);
564 for (i = 0; uri_name[i]; i++)
566 char *n = uri_name[i];
567 char *v = uri_val[i];
568 if (!strcmp(n, "query"))
570 else if (!strcmp(n, "x-pquery"))
572 else if (!strcmp(n, "x-username"))
574 else if (!strcmp(n, "x-password"))
576 else if (!strcmp(n, "operation"))
578 else if (!strcmp(n, "stylesheet"))
580 else if (!strcmp(n, "sortKeys"))
582 else if (!strcmp(n, "recordXPath"))
584 else if (!strcmp(n, "recordSchema"))
586 else if (!strcmp(n, "recordPacking"))
588 else if (!strcmp(n, "version"))
590 else if (!strcmp(n, "scanClause"))
592 else if (!strcmp(n, "x-pScanClause"))
594 else if (!strcmp(n, "maximumRecords"))
596 else if (!strcmp(n, "startRecord"))
598 else if (!strcmp(n, "maximumTerms"))
600 else if (!strcmp(n, "responsePosition"))
601 responsePosition = v;
602 else if (!strcmp(n, "extraRequestData"))
603 extraRequestData = v;
604 else if (n[0] == 'x' && n[1] == '-')
606 Z_SRW_extra_arg **l = &extra_args;
609 *l = (Z_SRW_extra_arg *) odr_malloc(decode, sizeof(**l));
610 (*l)->name = odr_strdup(decode, n);
611 (*l)->value = odr_strdup(decode, v);
615 yaz_add_srw_diagnostic(decode, diag, num_diag,
616 YAZ_SRW_UNSUPP_PARAMETER, n);
622 yaz_add_srw_diagnostic(
623 decode, diag, num_diag,
624 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "version");
628 version = yaz_negotiate_sru_version(version);
631 { /* negotiation failed. */
632 yaz_add_srw_diagnostic(decode, diag, num_diag,
633 YAZ_SRW_UNSUPP_VERSION, "1.2");
640 yaz_add_srw_diagnostic(
641 decode, diag, num_diag,
642 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "operation");
643 operation = "explain";
645 if (!strcmp(operation, "searchRetrieve"))
647 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
649 sr->srw_version = version;
650 sr->extra_args = extra_args;
652 yaz_srw_decodeauth(sr, hreq, username, password, decode);
655 sr->u.request->query_type = Z_SRW_query_type_cql;
656 sr->u.request->query.cql = query;
660 sr->u.request->query_type = Z_SRW_query_type_pqf;
661 sr->u.request->query.pqf = pQuery;
664 yaz_add_srw_diagnostic(
665 decode, diag, num_diag,
666 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "query");
670 sr->u.request->sort_type = Z_SRW_sort_type_sort;
671 sr->u.request->sort.sortKeys = sortKeys;
673 sr->u.request->recordXPath = recordXPath;
674 sr->u.request->recordSchema = recordSchema;
675 sr->u.request->recordPacking = recordPacking;
676 sr->u.request->stylesheet = stylesheet;
678 yaz_sru_decode_integer(decode, "maximumRecords", maximumRecords,
679 &sr->u.request->maximumRecords,
682 yaz_sru_decode_integer(decode, "startRecord", startRecord,
683 &sr->u.request->startRecord,
686 sr->u.request->database = db;
688 (*soap_package) = (Z_SOAP *)
689 odr_malloc(decode, sizeof(**soap_package));
690 (*soap_package)->which = Z_SOAP_generic;
692 (*soap_package)->u.generic = (Z_SOAP_Generic *)
693 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
695 (*soap_package)->u.generic->p = sr;
696 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
697 (*soap_package)->u.generic->no = 0;
699 (*soap_package)->ns = "SRU";
703 else if (!strcmp(operation, "explain"))
705 /* Transfer SRU explain parameters to common struct */
706 /* http://www.loc.gov/z3950/agency/zing/srw/explain.html */
707 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
709 sr->srw_version = version;
710 sr->extra_args = extra_args;
711 yaz_srw_decodeauth(sr, hreq, username, password, decode);
713 sr->u.explain_request->recordPacking = recordPacking;
714 sr->u.explain_request->database = db;
716 sr->u.explain_request->stylesheet = stylesheet;
718 (*soap_package) = (Z_SOAP *)
719 odr_malloc(decode, sizeof(**soap_package));
720 (*soap_package)->which = Z_SOAP_generic;
722 (*soap_package)->u.generic = (Z_SOAP_Generic *)
723 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
725 (*soap_package)->u.generic->p = sr;
726 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
727 (*soap_package)->u.generic->no = 0;
729 (*soap_package)->ns = "SRU";
733 else if (!strcmp(operation, "scan"))
735 /* Transfer SRU scan parameters to common struct */
736 /* http://www.loc.gov/z3950/agency/zing/srw/scan.html */
737 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_scan_request);
739 sr->srw_version = version;
740 sr->extra_args = extra_args;
742 yaz_srw_decodeauth(sr, hreq, username, password, decode);
746 sr->u.scan_request->query_type = Z_SRW_query_type_cql;
747 sr->u.scan_request->scanClause.cql = scanClause;
749 else if (pScanClause)
751 sr->u.scan_request->query_type = Z_SRW_query_type_pqf;
752 sr->u.scan_request->scanClause.pqf = pScanClause;
755 yaz_add_srw_diagnostic(
756 decode, diag, num_diag,
757 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "scanClause");
758 sr->u.scan_request->database = db;
760 yaz_sru_decode_integer(decode, "maximumTerms",
762 &sr->u.scan_request->maximumTerms,
765 yaz_sru_decode_integer(decode, "responsePosition",
767 &sr->u.scan_request->responsePosition,
770 sr->u.scan_request->stylesheet = stylesheet;
772 (*soap_package) = (Z_SOAP *)
773 odr_malloc(decode, sizeof(**soap_package));
774 (*soap_package)->which = Z_SOAP_generic;
776 (*soap_package)->u.generic = (Z_SOAP_Generic *)
777 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
779 (*soap_package)->u.generic->p = sr;
780 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
781 (*soap_package)->u.generic->no = 0;
783 (*soap_package)->ns = "SRU";
789 /* unsupported operation ... */
790 /* Act as if we received a explain request and throw diagnostic. */
792 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
794 sr->srw_version = version;
796 sr->u.explain_request->recordPacking = recordPacking;
797 sr->u.explain_request->database = db;
799 sr->u.explain_request->stylesheet = stylesheet;
801 (*soap_package) = (Z_SOAP *)
802 odr_malloc(decode, sizeof(**soap_package));
803 (*soap_package)->which = Z_SOAP_generic;
805 (*soap_package)->u.generic = (Z_SOAP_Generic *)
806 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
808 (*soap_package)->u.generic->p = sr;
809 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
810 (*soap_package)->u.generic->no = 0;
812 (*soap_package)->ns = "SRU";
814 yaz_add_srw_diagnostic(decode, diag, num_diag,
815 YAZ_SRW_UNSUPP_OPERATION, operation);
824 Z_SRW_extra_record *yaz_srw_get_extra_record(ODR o)
826 Z_SRW_extra_record *res = (Z_SRW_extra_record *)
827 odr_malloc(o, sizeof(*res));
829 res->extraRecordData_buf = 0;
830 res->extraRecordData_len = 0;
831 res->recordIdentifier = 0;
836 Z_SRW_record *yaz_srw_get_records(ODR o, int n)
838 Z_SRW_record *res = (Z_SRW_record *) odr_malloc(o, n * sizeof(*res));
841 for (i = 0; i<n; i++)
843 res[i].recordSchema = 0;
844 res[i].recordPacking = Z_SRW_recordPacking_string;
845 res[i].recordData_buf = 0;
846 res[i].recordData_len = 0;
847 res[i].recordPosition = 0;
852 Z_SRW_record *yaz_srw_get_record(ODR o)
854 return yaz_srw_get_records(o, 1);
857 static Z_SRW_PDU *yaz_srw_get_core_ver(ODR o, const char *version)
859 Z_SRW_PDU *p = (Z_SRW_PDU *) odr_malloc(o, sizeof(*p));
860 p->srw_version = odr_strdup(o, version);
867 Z_SRW_PDU *yaz_srw_get_core_v_1_1(ODR o)
869 return yaz_srw_get_core_ver(o, "1.1");
872 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
874 return yaz_srw_get_pdu(o, which, "1.1");
877 Z_SRW_PDU *yaz_srw_get_pdu(ODR o, int which, const char *version)
879 Z_SRW_PDU *sr = yaz_srw_get_core_ver(o, version);
884 case Z_SRW_searchRetrieve_request:
885 sr->u.request = (Z_SRW_searchRetrieveRequest *)
886 odr_malloc(o, sizeof(*sr->u.request));
887 sr->u.request->query_type = Z_SRW_query_type_cql;
888 sr->u.request->query.cql = 0;
889 sr->u.request->sort_type = Z_SRW_sort_type_none;
890 sr->u.request->sort.none = 0;
891 sr->u.request->startRecord = 0;
892 sr->u.request->maximumRecords = 0;
893 sr->u.request->recordSchema = 0;
894 sr->u.request->recordPacking = 0;
895 sr->u.request->recordXPath = 0;
896 sr->u.request->database = 0;
897 sr->u.request->resultSetTTL = 0;
898 sr->u.request->stylesheet = 0;
900 case Z_SRW_searchRetrieve_response:
901 sr->u.response = (Z_SRW_searchRetrieveResponse *)
902 odr_malloc(o, sizeof(*sr->u.response));
903 sr->u.response->numberOfRecords = 0;
904 sr->u.response->resultSetId = 0;
905 sr->u.response->resultSetIdleTime = 0;
906 sr->u.response->records = 0;
907 sr->u.response->num_records = 0;
908 sr->u.response->diagnostics = 0;
909 sr->u.response->num_diagnostics = 0;
910 sr->u.response->nextRecordPosition = 0;
911 sr->u.response->extra_records = 0;
913 case Z_SRW_explain_request:
914 sr->u.explain_request = (Z_SRW_explainRequest *)
915 odr_malloc(o, sizeof(*sr->u.explain_request));
916 sr->u.explain_request->recordPacking = 0;
917 sr->u.explain_request->database = 0;
918 sr->u.explain_request->stylesheet = 0;
920 case Z_SRW_explain_response:
921 sr->u.explain_response = (Z_SRW_explainResponse *)
922 odr_malloc(o, sizeof(*sr->u.explain_response));
923 sr->u.explain_response->record.recordData_buf = 0;
924 sr->u.explain_response->record.recordData_len = 0;
925 sr->u.explain_response->record.recordSchema = 0;
926 sr->u.explain_response->record.recordPosition = 0;
927 sr->u.explain_response->record.recordPacking =
928 Z_SRW_recordPacking_string;
929 sr->u.explain_response->diagnostics = 0;
930 sr->u.explain_response->num_diagnostics = 0;
931 sr->u.explain_response->extra_record = 0;
933 case Z_SRW_scan_request:
934 sr->u.scan_request = (Z_SRW_scanRequest *)
935 odr_malloc(o, sizeof(*sr->u.scan_request));
936 sr->u.scan_request->database = 0;
937 sr->u.scan_request->stylesheet = 0;
938 sr->u.scan_request->maximumTerms = 0;
939 sr->u.scan_request->responsePosition = 0;
940 sr->u.scan_request->query_type = Z_SRW_query_type_cql;
941 sr->u.scan_request->scanClause.cql = 0;
943 case Z_SRW_scan_response:
944 sr->u.scan_response = (Z_SRW_scanResponse *)
945 odr_malloc(o, sizeof(*sr->u.scan_response));
946 sr->u.scan_response->terms = 0;
947 sr->u.scan_response->num_terms = 0;
948 sr->u.scan_response->diagnostics = 0;
949 sr->u.scan_response->num_diagnostics = 0;
951 case Z_SRW_update_request:
952 sr->u.update_request = (Z_SRW_updateRequest *)
953 odr_malloc(o, sizeof(*sr->u.update_request));
954 sr->u.update_request->database = 0;
955 sr->u.update_request->stylesheet = 0;
956 sr->u.update_request->record = 0;
957 sr->u.update_request->recordId = 0;
958 sr->u.update_request->recordVersions = 0;
959 sr->u.update_request->num_recordVersions = 0;
960 sr->u.update_request->extra_record = 0;
961 sr->u.update_request->extraRequestData_buf = 0;
962 sr->u.update_request->extraRequestData_len = 0;
963 sr->u.request->database = 0;
965 case Z_SRW_update_response:
966 sr->u.update_response = (Z_SRW_updateResponse *)
967 odr_malloc(o, sizeof(*sr->u.update_response));
968 sr->u.update_response->operationStatus = 0;
969 sr->u.update_response->recordId = 0;
970 sr->u.update_response->recordVersions = 0;
971 sr->u.update_response->num_recordVersions = 0;
972 sr->u.update_response->record = 0;
973 sr->u.update_response->extra_record = 0;
974 sr->u.update_response->extraResponseData_buf = 0;
975 sr->u.update_response->extraResponseData_len = 0;
976 sr->u.update_response->diagnostics = 0;
977 sr->u.update_response->num_diagnostics = 0;
983 static int bib1_srw_map[] = {
993 108, 10, /* Malformed query : Syntax error */
1023 100, 1, /* bad map */
1071 205, 1, /* bad map */
1072 206, 1, /* bad map */
1074 208, 1, /* bad map */
1085 218, 1, /* bad map */
1086 219, 1, /* bad map */
1087 220, 1, /* bad map */
1088 221, 1, /* bad map */
1090 223, 1, /* bad map */
1091 224, 1, /* bad map */
1092 225, 1, /* bad map */
1093 226, 1, /* bad map */
1095 228, 1, /* bad map */
1100 233, 1, /* bad map */
1101 234, 1, /* bad map */
1107 240, 1, /* bad map */
1108 241, 1, /* bad map */
1110 243, 1, /* bad map */
1115 1001, 1, /* bad map */
1116 1002, 1, /* bad map */
1117 1003, 1, /* bad map */
1118 1004, 1, /* bad map */
1119 1005, 1, /* bad map */
1120 1006, 1, /* bad map */
1153 * This array contains overrides for when the first occurrence of a
1154 * particular SRW error in the array above does not correspond with
1155 * the best back-translation of that SRW error.
1157 static int srw_bib1_map[] = {
1159 /* No doubt there are many more */
1164 int yaz_diag_bib1_to_srw (int code)
1166 const int *p = bib1_srw_map;
1176 int yaz_diag_srw_to_bib1(int code)
1178 /* Check explicit reverse-map first */
1179 const int *p = srw_bib1_map;
1187 /* Fall back on reverse lookup in main map */
1198 static void add_val_int(ODR o, char **name, char **value, int *i,
1199 char *a_name, int *val)
1204 value[*i] = (char *) odr_malloc(o, 30);
1205 sprintf(value[*i], "%d", *val);
1210 static void add_val_str(ODR o, char **name, char **value, int *i,
1211 char *a_name, char *val)
1221 static int yaz_get_sru_parms(const Z_SRW_PDU *srw_pdu, ODR encode,
1222 char **name, char **value, int max_names)
1225 add_val_str(encode, name, value, &i, "version", srw_pdu->srw_version);
1226 name[i] = "operation";
1227 switch(srw_pdu->which)
1229 case Z_SRW_searchRetrieve_request:
1230 value[i++] = "searchRetrieve";
1231 switch(srw_pdu->u.request->query_type)
1233 case Z_SRW_query_type_cql:
1234 add_val_str(encode, name, value, &i, "query",
1235 srw_pdu->u.request->query.cql);
1237 case Z_SRW_query_type_pqf:
1238 add_val_str(encode, name, value, &i, "x-pquery",
1239 srw_pdu->u.request->query.pqf);
1241 case Z_SRW_query_type_xcql:
1242 add_val_str(encode, name, value, &i, "x-cql",
1243 srw_pdu->u.request->query.xcql);
1246 switch(srw_pdu->u.request->sort_type)
1248 case Z_SRW_sort_type_none:
1250 case Z_SRW_sort_type_sort:
1251 add_val_str(encode, name, value, &i, "sortKeys",
1252 srw_pdu->u.request->sort.sortKeys);
1255 add_val_int(encode, name, value, &i, "startRecord",
1256 srw_pdu->u.request->startRecord);
1257 add_val_int(encode, name, value, &i, "maximumRecords",
1258 srw_pdu->u.request->maximumRecords);
1259 add_val_str(encode, name, value, &i, "recordSchema",
1260 srw_pdu->u.request->recordSchema);
1261 add_val_str(encode, name, value, &i, "recordPacking",
1262 srw_pdu->u.request->recordPacking);
1263 add_val_str(encode, name, value, &i, "recordXPath",
1264 srw_pdu->u.request->recordXPath);
1265 add_val_str(encode, name, value, &i, "stylesheet",
1266 srw_pdu->u.request->stylesheet);
1267 add_val_int(encode, name, value, &i, "resultSetTTL",
1268 srw_pdu->u.request->resultSetTTL);
1270 case Z_SRW_explain_request:
1271 value[i++] = "explain";
1272 add_val_str(encode, name, value, &i, "stylesheet",
1273 srw_pdu->u.explain_request->stylesheet);
1275 case Z_SRW_scan_request:
1276 value[i++] = "scan";
1278 switch(srw_pdu->u.scan_request->query_type)
1280 case Z_SRW_query_type_cql:
1281 add_val_str(encode, name, value, &i, "scanClause",
1282 srw_pdu->u.scan_request->scanClause.cql);
1284 case Z_SRW_query_type_pqf:
1285 add_val_str(encode, name, value, &i, "x-pScanClause",
1286 srw_pdu->u.scan_request->scanClause.pqf);
1288 case Z_SRW_query_type_xcql:
1289 add_val_str(encode, name, value, &i, "x-cqlScanClause",
1290 srw_pdu->u.scan_request->scanClause.xcql);
1293 add_val_int(encode, name, value, &i, "responsePosition",
1294 srw_pdu->u.scan_request->responsePosition);
1295 add_val_int(encode, name, value, &i, "maximumTerms",
1296 srw_pdu->u.scan_request->maximumTerms);
1297 add_val_str(encode, name, value, &i, "stylesheet",
1298 srw_pdu->u.scan_request->stylesheet);
1300 case Z_SRW_update_request:
1301 value[i++] = "update";
1306 if (srw_pdu->extra_args)
1308 Z_SRW_extra_arg *ea = srw_pdu->extra_args;
1309 for (; ea && i < max_names-1; ea = ea->next)
1312 value[i] = ea->value;
1321 int yaz_sru_get_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1322 ODR encode, const char *charset)
1324 char *name[30], *value[30]; /* definite upper limit for SRU params */
1328 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1329 srw_pdu->username, srw_pdu->password);
1330 if (yaz_get_sru_parms(srw_pdu, encode, name, value, 30))
1332 yaz_array_to_uri(&uri_args, encode, name, value);
1334 hreq->method = "GET";
1337 odr_malloc(encode, strlen(hreq->path) + strlen(uri_args) + 4);
1339 sprintf(path, "%s?%s", hreq->path, uri_args);
1342 z_HTTP_header_add_content_type(encode, &hreq->headers,
1343 "text/xml", charset);
1347 int yaz_sru_post_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1348 ODR encode, const char *charset)
1350 char *name[30], *value[30]; /* definite upper limit for SRU params */
1353 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1354 srw_pdu->username, srw_pdu->password);
1355 if (yaz_get_sru_parms(srw_pdu, encode, name, value, 30))
1358 yaz_array_to_uri(&uri_args, encode, name, value);
1360 hreq->method = "POST";
1362 hreq->content_buf = uri_args;
1363 hreq->content_len = strlen(uri_args);
1365 z_HTTP_header_add_content_type(encode, &hreq->headers,
1366 "application/x-www-form-urlencoded",
1371 int yaz_sru_soap_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1372 ODR odr, const char *charset)
1374 Z_SOAP_Handler handlers[3] = {
1376 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
1377 {YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec},
1381 Z_SOAP *p = (Z_SOAP*) odr_malloc(odr, sizeof(*p));
1383 z_HTTP_header_add_basic_auth(odr, &hreq->headers,
1384 srw_pdu->username, srw_pdu->password);
1385 z_HTTP_header_add_content_type(odr,
1387 "text/xml", charset);
1389 z_HTTP_header_add(odr, &hreq->headers,
1390 "SOAPAction", "\"\"");
1391 p->which = Z_SOAP_generic;
1392 p->u.generic = (Z_SOAP_Generic *) odr_malloc(odr, sizeof(*p->u.generic));
1393 p->u.generic->no = 0;
1394 p->u.generic->ns = 0;
1395 p->u.generic->p = srw_pdu;
1396 p->ns = "http://schemas.xmlsoap.org/soap/envelope/";
1399 if (srw_pdu->which == Z_SRW_update_request ||
1400 srw_pdu->which == Z_SRW_update_response)
1401 p->u.generic->no = 1; /* second handler */
1403 return z_soap_codec_enc(odr, &p,
1405 &hreq->content_len, handlers,
1409 Z_SRW_recordVersion *yaz_srw_get_record_versions(ODR odr, int num )
1411 Z_SRW_recordVersion *ver
1412 = (Z_SRW_recordVersion *) odr_malloc( odr, num * sizeof(*ver) );
1414 for ( i=0; i < num; ++i ){
1415 ver[i].versionType = 0;
1416 ver[i].versionValue = 0;
1421 const char *yaz_srw_pack_to_str(int pack)
1425 case Z_SRW_recordPacking_string:
1427 case Z_SRW_recordPacking_XML:
1429 case Z_SRW_recordPacking_URL:
1435 int yaz_srw_str_to_pack(const char *str)
1437 if (!yaz_matchstr(str, "string"))
1438 return Z_SRW_recordPacking_string;
1439 if (!yaz_matchstr(str, "xml"))
1440 return Z_SRW_recordPacking_XML;
1441 if (!yaz_matchstr(str, "url"))
1442 return Z_SRW_recordPacking_URL;
1446 void yaz_encode_sru_extra(Z_SRW_PDU *sr, ODR odr, const char *extra_args)
1452 Z_SRW_extra_arg **ea = &sr->extra_args;
1453 yaz_uri_to_array(extra_args, odr, &name, &val);
1457 *ea = (Z_SRW_extra_arg *) odr_malloc(odr, sizeof(**ea));
1458 (*ea)->name = *name;
1459 (*ea)->value = *val;
1473 * indent-tabs-mode: nil
1475 * vim: shiftwidth=4 tabstop=8 expandtab