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/match-str.h>
13 #include <yaz/yaz-iconv.h>
15 static int hex_digit (int ch)
17 if (ch >= '0' && ch <= '9')
19 else if (ch >= 'a' && ch <= 'f')
21 else if (ch >= 'A' && ch <= 'F')
26 void encode_uri_char(char *dst, char ch)
30 /* mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" */
31 else if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') ||
32 (ch >= '0' && ch <= '9') || strchr("-_.!~*'(|)", ch))
40 sprintf(dst+1, "%02X", (unsigned char ) ch);
44 static void yaz_array_to_uri(char **path, ODR o, char **name, char **value)
46 size_t i, szp = 0, sz = 1;
47 for(i = 0; name[i]; i++)
48 sz += strlen(name[i]) + 3 + strlen(value[i]) * 3;
49 *path = (char *) odr_malloc(o, sz);
51 for(i = 0; name[i]; i++)
56 ilen = strlen(name[i]);
57 memcpy(*path+szp, name[i], ilen);
60 for (j = 0; value[i][j]; j++)
64 encode_uri_char(vstr, value[i][j]);
66 memcpy(*path+szp, vstr, vlen);
73 int yaz_uri_to_array(const char *path, ODR o, char ***name, char ***val)
83 while ((cp = strchr(cp, '&')))
88 *name = (char **) odr_malloc(o, no * sizeof(char*));
89 *val = (char **) odr_malloc(o, no * sizeof(char*));
91 for (no = 0; *path; no++)
93 const char *p1 = strchr(path, '=');
99 (*name)[no] = (char *) odr_malloc(o, (p1-path)+1);
100 memcpy((*name)[no], path, p1-path);
101 (*name)[no][p1-path] = '\0';
104 p1 = strchr(path, '&');
106 p1 = strlen(path) + path;
107 (*val)[no] = ret = (char *) odr_malloc(o, p1 - path + 1);
108 while (*path && *path != '&')
115 else if (*path == '%' && path[1] && path[2])
117 ret[i++] = hex_digit (path[1])*16 + hex_digit (path[2]);
133 char *yaz_uri_val(const char *path, const char *name, ODR o)
135 size_t nlen = strlen(name);
139 while (path && *path)
141 const char *p1 = strchr(path, '=');
144 if ((size_t)(p1 - path) == nlen && !memcmp(path, name, nlen))
150 p1 = strchr(path, '&');
152 p1 = strlen(path) + path;
153 ret = (char *) odr_malloc(o, p1 - path + 1);
154 while (*path && *path != '&')
161 else if (*path == '%' && path[1] && path[2])
163 ret[i++] = hex_digit (path[1])*16 + hex_digit (path[2]);
172 path = strchr(p1, '&');
180 static int yaz_base64decode(const char *in, char *out)
182 const char *map = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
183 "abcdefghijklmnopqrstuvwxyz0123456789+/";
185 int len = strlen(in);
192 if (!(p = strchr(map, in[0])))
196 if (!(p = strchr(map, in[1])))
200 *(out++) = i0 << 2 | i1 >> 4;
204 if (!(p = strchr(map, in[2])))
208 *(out++) = i1 << 4 | i2 >> 2;
212 if (!(p = strchr(map, in[3])))
216 *(out++) = i2 << 6 | i3;
227 int yaz_srw_check_content_type(Z_HTTP_Response *hres)
229 const char *content_type = z_HTTP_header_lookup(hres->headers,
233 if (!yaz_strcmp_del("text/xml", content_type, "; "))
235 if (!yaz_strcmp_del("application/xml", content_type, "; "))
242 * Look for authentication tokens in HTTP Basic parameters or in x-username/x-password
243 * parameters. Added by SH.
246 static void yaz_srw_decodeauth(Z_SRW_PDU *sr, Z_HTTP_Request *hreq,
247 char *username, char *password, ODR decode)
249 const char *basic = z_HTTP_header_lookup(hreq->headers, "Authorization");
252 sr->username = username;
254 sr->password = password;
259 char ubuf[256] = "", pbuf[256] = "", *p;
260 if (strncmp(basic, "Basic ", 6))
264 if (!len || len > 256)
266 olen = yaz_base64decode(basic, out);
267 /* Format of out should be username:password at this point */
269 if ((p = strchr(ubuf, ':'))) {
275 sr->username = odr_strdup(decode, ubuf);
277 sr->password = odr_strdup(decode, pbuf);
282 void yaz_uri_val_int(const char *path, const char *name, ODR o, int **intp)
284 const char *v = yaz_uri_val(path, name, o);
286 *intp = odr_intdup(o, atoi(v));
289 void yaz_mk_srw_diagnostic(ODR o, Z_SRW_diagnostic *d,
290 const char *uri, const char *message,
293 d->uri = odr_strdup(o, uri);
295 d->message = odr_strdup(o, message);
299 d->details = odr_strdup(o, details);
304 void yaz_mk_std_diagnostic(ODR o, Z_SRW_diagnostic *d,
305 int code, const char *details)
309 sprintf(uri, "info:srw/diagnostic/1/%d", code);
310 yaz_mk_srw_diagnostic(o, d, uri, 0, details);
313 void yaz_add_srw_diagnostic_uri(ODR o, Z_SRW_diagnostic **d,
314 int *num, const char *uri,
315 const char *message, const char *details)
317 Z_SRW_diagnostic *d_new;
318 d_new = (Z_SRW_diagnostic *) odr_malloc (o, (*num + 1)* sizeof(**d));
320 memcpy (d_new, *d, *num *sizeof(**d));
323 yaz_mk_srw_diagnostic(o, *d + *num, uri, message, details);
327 void yaz_add_srw_diagnostic(ODR o, Z_SRW_diagnostic **d,
328 int *num, int code, const char *addinfo)
332 sprintf(uri, "info:srw/diagnostic/1/%d", code);
333 yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
337 void yaz_add_sru_update_diagnostic(ODR o, Z_SRW_diagnostic **d,
338 int *num, int code, const char *addinfo)
342 sprintf(uri, "info:srw/diagnostic/12/%d", code);
343 yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
347 void yaz_mk_sru_surrogate(ODR o, Z_SRW_record *record, int pos,
348 int code, const char *details)
350 const char *message = yaz_diag_srw_str(code);
353 len += strlen(message);
355 len += strlen(details);
357 record->recordData_buf = (char *) odr_malloc(o, len);
359 sprintf(record->recordData_buf, "<diagnostic "
360 "xmlns=\"http://www.loc.gov/zing/srw/diagnostic/\">\n"
361 " <uri>info:srw/diagnostic/1/%d</uri>\n", code);
363 sprintf(record->recordData_buf + strlen(record->recordData_buf),
364 " <details>%s</details>\n", details);
366 sprintf(record->recordData_buf + strlen(record->recordData_buf),
367 " <message>%s</message>\n", message);
368 sprintf(record->recordData_buf + strlen(record->recordData_buf),
370 record->recordData_len = strlen(record->recordData_buf);
371 record->recordPosition = odr_intdup(o, pos);
372 record->recordSchema = "info:srw/schema/1/diagnostics-v1.1";
375 static void grab_charset(ODR o, const char *content_type, char **charset)
379 const char *charset_p = 0;
380 if (content_type && (charset_p = strstr(content_type, "; charset=")))
384 while (i < 20 && charset_p[i] &&
385 !strchr("; \n\r", charset_p[i]))
387 *charset = (char*) odr_malloc(o, i+1);
388 memcpy(*charset, charset_p, i);
389 (*charset)[i] = '\0';
394 int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
395 Z_SOAP **soap_package, ODR decode, char **charset)
397 if (!strcmp(hreq->method, "POST"))
399 const char *content_type = z_HTTP_header_lookup(hreq->headers,
402 (!yaz_strcmp_del("text/xml", content_type, "; ") ||
403 !yaz_strcmp_del("application/soap+xml", content_type, "; ") ||
404 !yaz_strcmp_del("text/plain", content_type, "; ")))
406 char *db = "Default";
407 const char *p0 = hreq->path, *p1;
410 static Z_SOAP_Handler soap_handlers[4] = {
412 { YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec },
413 { YAZ_XMLNS_SRU_v1_0, 0, (Z_SOAP_fun) yaz_srw_codec },
414 { YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec },
421 p1 = strchr(p0, '?');
423 p1 = p0 + strlen(p0);
426 db = (char*) odr_malloc(decode, p1 - p0 + 1);
427 memcpy (db, p0, p1 - p0);
431 grab_charset(decode, content_type, charset);
433 ret = z_soap_codec(decode, soap_package,
434 &hreq->content_buf, &hreq->content_len,
436 if (ret == 0 && (*soap_package)->which == Z_SOAP_generic)
438 *srw_pdu = (Z_SRW_PDU*) (*soap_package)->u.generic->p;
440 if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request &&
441 (*srw_pdu)->u.request->database == 0)
442 (*srw_pdu)->u.request->database = db;
444 if ((*srw_pdu)->which == Z_SRW_explain_request &&
445 (*srw_pdu)->u.explain_request->database == 0)
446 (*srw_pdu)->u.explain_request->database = db;
448 if ((*srw_pdu)->which == Z_SRW_scan_request &&
449 (*srw_pdu)->u.scan_request->database == 0)
450 (*srw_pdu)->u.scan_request->database = db;
452 if ((*srw_pdu)->which == Z_SRW_update_request &&
453 (*srw_pdu)->u.update_request->database == 0)
454 (*srw_pdu)->u.update_request->database = db;
465 static int yaz_sru_decode_integer(ODR odr, const char *pname,
466 const char *valstr, int **valp,
467 Z_SRW_diagnostic **diag, int *num_diag,
473 if (sscanf(valstr, "%d", &ival) != 1)
475 yaz_add_srw_diagnostic(odr, diag, num_diag,
476 YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
479 if (min_value >= 0 && ival < min_value)
481 yaz_add_srw_diagnostic(odr, diag, num_diag,
482 YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
485 *valp = odr_intdup(odr, ival);
491 http://www.loc.gov/z3950/agency/zing/srw/service.html
493 int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
494 Z_SOAP **soap_package, ODR decode, char **charset,
495 Z_SRW_diagnostic **diag, int *num_diag)
498 static Z_SOAP_Handler soap_handlers[2] = {
499 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
503 const char *content_type = z_HTTP_header_lookup(hreq->headers,
507 SRU GET: ignore content type.
508 SRU POST: we support "application/x-www-form-urlencoded";
509 not "multipart/form-data" .
511 if (!strcmp(hreq->method, "GET")
513 (!strcmp(hreq->method, "POST") && content_type &&
514 !yaz_strcmp_del("application/x-www-form-urlencoded",
515 content_type, "; ")))
517 char *db = "Default";
518 const char *p0 = hreq->path, *p1;
520 const char *operation = 0;
527 char *stylesheet = 0;
528 char *scanClause = 0;
529 char *pScanClause = 0;
530 char *recordXPath = 0;
531 char *recordSchema = 0;
532 char *recordPacking = "xml"; /* xml packing is default for SRU */
533 char *maximumRecords = 0;
534 char *startRecord = 0;
535 char *maximumTerms = 0;
536 char *responsePosition = 0;
537 char *extraRequestData = 0;
538 Z_SRW_extra_arg *extra_args = 0;
543 grab_charset(decode, content_type, charset);
544 if (charset && *charset == 0 && !strcmp(hreq->method, "GET"))
549 p1 = strchr(p0, '?');
551 p1 = p0 + strlen(p0);
554 db = (char*) odr_malloc(decode, p1 - p0 + 1);
555 memcpy (db, p0, p1 - p0);
558 if (!strcmp(hreq->method, "POST"))
559 p1 = hreq->content_buf;
560 yaz_uri_to_array(p1, decode, &uri_name, &uri_val);
565 for (i = 0; uri_name[i]; i++)
567 char *n = uri_name[i];
568 char *v = uri_val[i];
569 if (!strcmp(n, "query"))
571 else if (!strcmp(n, "x-pquery"))
573 else if (!strcmp(n, "x-username"))
575 else if (!strcmp(n, "x-password"))
577 else if (!strcmp(n, "operation"))
579 else if (!strcmp(n, "stylesheet"))
581 else if (!strcmp(n, "sortKeys"))
583 else if (!strcmp(n, "recordXPath"))
585 else if (!strcmp(n, "recordSchema"))
587 else if (!strcmp(n, "recordPacking"))
589 else if (!strcmp(n, "version"))
591 else if (!strcmp(n, "scanClause"))
593 else if (!strcmp(n, "x-pScanClause"))
595 else if (!strcmp(n, "maximumRecords"))
597 else if (!strcmp(n, "startRecord"))
599 else if (!strcmp(n, "maximumTerms"))
601 else if (!strcmp(n, "responsePosition"))
602 responsePosition = v;
603 else if (!strcmp(n, "extraRequestData"))
604 extraRequestData = v;
605 else if (n[0] == 'x' && n[1] == '-')
607 Z_SRW_extra_arg **l = &extra_args;
610 *l = (Z_SRW_extra_arg *) odr_malloc(decode, sizeof(**l));
611 (*l)->name = odr_strdup(decode, n);
612 (*l)->value = odr_strdup(decode, v);
616 yaz_add_srw_diagnostic(decode, diag, num_diag,
617 YAZ_SRW_UNSUPP_PARAMETER, n);
623 yaz_add_srw_diagnostic(
624 decode, diag, num_diag,
625 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "version");
629 version = yaz_negotiate_sru_version(version);
632 { /* negotiation failed. */
633 yaz_add_srw_diagnostic(decode, diag, num_diag,
634 YAZ_SRW_UNSUPP_VERSION, "1.2");
641 yaz_add_srw_diagnostic(
642 decode, diag, num_diag,
643 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "operation");
644 operation = "explain";
646 if (!strcmp(operation, "searchRetrieve"))
648 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
650 sr->srw_version = version;
651 sr->extra_args = extra_args;
653 yaz_srw_decodeauth(sr, hreq, username, password, decode);
656 sr->u.request->query_type = Z_SRW_query_type_cql;
657 sr->u.request->query.cql = query;
661 sr->u.request->query_type = Z_SRW_query_type_pqf;
662 sr->u.request->query.pqf = pQuery;
665 yaz_add_srw_diagnostic(
666 decode, diag, num_diag,
667 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "query");
671 sr->u.request->sort_type = Z_SRW_sort_type_sort;
672 sr->u.request->sort.sortKeys = sortKeys;
674 sr->u.request->recordXPath = recordXPath;
675 sr->u.request->recordSchema = recordSchema;
676 sr->u.request->recordPacking = recordPacking;
677 sr->u.request->stylesheet = stylesheet;
679 yaz_sru_decode_integer(decode, "maximumRecords", maximumRecords,
680 &sr->u.request->maximumRecords,
683 yaz_sru_decode_integer(decode, "startRecord", startRecord,
684 &sr->u.request->startRecord,
687 sr->u.request->database = db;
689 (*soap_package) = (Z_SOAP *)
690 odr_malloc(decode, sizeof(**soap_package));
691 (*soap_package)->which = Z_SOAP_generic;
693 (*soap_package)->u.generic = (Z_SOAP_Generic *)
694 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
696 (*soap_package)->u.generic->p = sr;
697 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
698 (*soap_package)->u.generic->no = 0;
700 (*soap_package)->ns = "SRU";
704 else if (!strcmp(operation, "explain"))
706 /* Transfer SRU explain parameters to common struct */
707 /* http://www.loc.gov/z3950/agency/zing/srw/explain.html */
708 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
710 sr->srw_version = version;
711 sr->extra_args = extra_args;
712 yaz_srw_decodeauth(sr, hreq, username, password, decode);
714 sr->u.explain_request->recordPacking = recordPacking;
715 sr->u.explain_request->database = db;
717 sr->u.explain_request->stylesheet = stylesheet;
719 (*soap_package) = (Z_SOAP *)
720 odr_malloc(decode, sizeof(**soap_package));
721 (*soap_package)->which = Z_SOAP_generic;
723 (*soap_package)->u.generic = (Z_SOAP_Generic *)
724 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
726 (*soap_package)->u.generic->p = sr;
727 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
728 (*soap_package)->u.generic->no = 0;
730 (*soap_package)->ns = "SRU";
734 else if (!strcmp(operation, "scan"))
736 /* Transfer SRU scan parameters to common struct */
737 /* http://www.loc.gov/z3950/agency/zing/srw/scan.html */
738 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_scan_request);
740 sr->srw_version = version;
741 sr->extra_args = extra_args;
743 yaz_srw_decodeauth(sr, hreq, username, password, decode);
747 sr->u.scan_request->query_type = Z_SRW_query_type_cql;
748 sr->u.scan_request->scanClause.cql = scanClause;
750 else if (pScanClause)
752 sr->u.scan_request->query_type = Z_SRW_query_type_pqf;
753 sr->u.scan_request->scanClause.pqf = pScanClause;
756 yaz_add_srw_diagnostic(
757 decode, diag, num_diag,
758 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "scanClause");
759 sr->u.scan_request->database = db;
761 yaz_sru_decode_integer(decode, "maximumTerms",
763 &sr->u.scan_request->maximumTerms,
766 yaz_sru_decode_integer(decode, "responsePosition",
768 &sr->u.scan_request->responsePosition,
771 sr->u.scan_request->stylesheet = stylesheet;
773 (*soap_package) = (Z_SOAP *)
774 odr_malloc(decode, sizeof(**soap_package));
775 (*soap_package)->which = Z_SOAP_generic;
777 (*soap_package)->u.generic = (Z_SOAP_Generic *)
778 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
780 (*soap_package)->u.generic->p = sr;
781 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
782 (*soap_package)->u.generic->no = 0;
784 (*soap_package)->ns = "SRU";
790 /* unsupported operation ... */
791 /* Act as if we received a explain request and throw diagnostic. */
793 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
795 sr->srw_version = version;
797 sr->u.explain_request->recordPacking = recordPacking;
798 sr->u.explain_request->database = db;
800 sr->u.explain_request->stylesheet = stylesheet;
802 (*soap_package) = (Z_SOAP *)
803 odr_malloc(decode, sizeof(**soap_package));
804 (*soap_package)->which = Z_SOAP_generic;
806 (*soap_package)->u.generic = (Z_SOAP_Generic *)
807 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
809 (*soap_package)->u.generic->p = sr;
810 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
811 (*soap_package)->u.generic->no = 0;
813 (*soap_package)->ns = "SRU";
815 yaz_add_srw_diagnostic(decode, diag, num_diag,
816 YAZ_SRW_UNSUPP_OPERATION, operation);
825 Z_SRW_extra_record *yaz_srw_get_extra_record(ODR o)
827 Z_SRW_extra_record *res = (Z_SRW_extra_record *)
828 odr_malloc(o, sizeof(*res));
830 res->extraRecordData_buf = 0;
831 res->extraRecordData_len = 0;
832 res->recordIdentifier = 0;
837 Z_SRW_record *yaz_srw_get_records(ODR o, int n)
839 Z_SRW_record *res = (Z_SRW_record *) odr_malloc(o, n * sizeof(*res));
842 for (i = 0; i<n; i++)
844 res[i].recordSchema = 0;
845 res[i].recordPacking = Z_SRW_recordPacking_string;
846 res[i].recordData_buf = 0;
847 res[i].recordData_len = 0;
848 res[i].recordPosition = 0;
853 Z_SRW_record *yaz_srw_get_record(ODR o)
855 return yaz_srw_get_records(o, 1);
858 static Z_SRW_PDU *yaz_srw_get_core_ver(ODR o, const char *version)
860 Z_SRW_PDU *p = (Z_SRW_PDU *) odr_malloc(o, sizeof(*p));
861 p->srw_version = odr_strdup(o, version);
868 Z_SRW_PDU *yaz_srw_get_core_v_1_1(ODR o)
870 return yaz_srw_get_core_ver(o, "1.1");
873 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
875 return yaz_srw_get_pdu(o, which, "1.1");
878 Z_SRW_PDU *yaz_srw_get_pdu(ODR o, int which, const char *version)
880 Z_SRW_PDU *sr = yaz_srw_get_core_ver(o, version);
885 case Z_SRW_searchRetrieve_request:
886 sr->u.request = (Z_SRW_searchRetrieveRequest *)
887 odr_malloc(o, sizeof(*sr->u.request));
888 sr->u.request->query_type = Z_SRW_query_type_cql;
889 sr->u.request->query.cql = 0;
890 sr->u.request->sort_type = Z_SRW_sort_type_none;
891 sr->u.request->sort.none = 0;
892 sr->u.request->startRecord = 0;
893 sr->u.request->maximumRecords = 0;
894 sr->u.request->recordSchema = 0;
895 sr->u.request->recordPacking = 0;
896 sr->u.request->recordXPath = 0;
897 sr->u.request->database = 0;
898 sr->u.request->resultSetTTL = 0;
899 sr->u.request->stylesheet = 0;
901 case Z_SRW_searchRetrieve_response:
902 sr->u.response = (Z_SRW_searchRetrieveResponse *)
903 odr_malloc(o, sizeof(*sr->u.response));
904 sr->u.response->numberOfRecords = 0;
905 sr->u.response->resultSetId = 0;
906 sr->u.response->resultSetIdleTime = 0;
907 sr->u.response->records = 0;
908 sr->u.response->num_records = 0;
909 sr->u.response->diagnostics = 0;
910 sr->u.response->num_diagnostics = 0;
911 sr->u.response->nextRecordPosition = 0;
912 sr->u.response->extra_records = 0;
914 case Z_SRW_explain_request:
915 sr->u.explain_request = (Z_SRW_explainRequest *)
916 odr_malloc(o, sizeof(*sr->u.explain_request));
917 sr->u.explain_request->recordPacking = 0;
918 sr->u.explain_request->database = 0;
919 sr->u.explain_request->stylesheet = 0;
921 case Z_SRW_explain_response:
922 sr->u.explain_response = (Z_SRW_explainResponse *)
923 odr_malloc(o, sizeof(*sr->u.explain_response));
924 sr->u.explain_response->record.recordData_buf = 0;
925 sr->u.explain_response->record.recordData_len = 0;
926 sr->u.explain_response->record.recordSchema = 0;
927 sr->u.explain_response->record.recordPosition = 0;
928 sr->u.explain_response->record.recordPacking =
929 Z_SRW_recordPacking_string;
930 sr->u.explain_response->diagnostics = 0;
931 sr->u.explain_response->num_diagnostics = 0;
932 sr->u.explain_response->extra_record = 0;
934 case Z_SRW_scan_request:
935 sr->u.scan_request = (Z_SRW_scanRequest *)
936 odr_malloc(o, sizeof(*sr->u.scan_request));
937 sr->u.scan_request->database = 0;
938 sr->u.scan_request->stylesheet = 0;
939 sr->u.scan_request->maximumTerms = 0;
940 sr->u.scan_request->responsePosition = 0;
941 sr->u.scan_request->query_type = Z_SRW_query_type_cql;
942 sr->u.scan_request->scanClause.cql = 0;
944 case Z_SRW_scan_response:
945 sr->u.scan_response = (Z_SRW_scanResponse *)
946 odr_malloc(o, sizeof(*sr->u.scan_response));
947 sr->u.scan_response->terms = 0;
948 sr->u.scan_response->num_terms = 0;
949 sr->u.scan_response->diagnostics = 0;
950 sr->u.scan_response->num_diagnostics = 0;
952 case Z_SRW_update_request:
953 sr->u.update_request = (Z_SRW_updateRequest *)
954 odr_malloc(o, sizeof(*sr->u.update_request));
955 sr->u.update_request->database = 0;
956 sr->u.update_request->stylesheet = 0;
957 sr->u.update_request->record = 0;
958 sr->u.update_request->recordId = 0;
959 sr->u.update_request->recordVersions = 0;
960 sr->u.update_request->num_recordVersions = 0;
961 sr->u.update_request->extra_record = 0;
962 sr->u.update_request->extraRequestData_buf = 0;
963 sr->u.update_request->extraRequestData_len = 0;
964 sr->u.request->database = 0;
966 case Z_SRW_update_response:
967 sr->u.update_response = (Z_SRW_updateResponse *)
968 odr_malloc(o, sizeof(*sr->u.update_response));
969 sr->u.update_response->operationStatus = 0;
970 sr->u.update_response->recordId = 0;
971 sr->u.update_response->recordVersions = 0;
972 sr->u.update_response->num_recordVersions = 0;
973 sr->u.update_response->record = 0;
974 sr->u.update_response->extra_record = 0;
975 sr->u.update_response->extraResponseData_buf = 0;
976 sr->u.update_response->extraResponseData_len = 0;
977 sr->u.update_response->diagnostics = 0;
978 sr->u.update_response->num_diagnostics = 0;
984 static int bib1_srw_map[] = {
994 108, 10, /* Malformed query : Syntax error */
1024 100, 1, /* bad map */
1072 205, 1, /* bad map */
1073 206, 1, /* bad map */
1075 208, 1, /* bad map */
1086 218, 1, /* bad map */
1087 219, 1, /* bad map */
1088 220, 1, /* bad map */
1089 221, 1, /* bad map */
1091 223, 1, /* bad map */
1092 224, 1, /* bad map */
1093 225, 1, /* bad map */
1094 226, 1, /* bad map */
1096 228, 1, /* bad map */
1101 233, 1, /* bad map */
1102 234, 1, /* bad map */
1108 240, 1, /* bad map */
1109 241, 1, /* bad map */
1111 243, 1, /* bad map */
1116 1001, 1, /* bad map */
1117 1002, 1, /* bad map */
1118 1003, 1, /* bad map */
1119 1004, 1, /* bad map */
1120 1005, 1, /* bad map */
1121 1006, 1, /* bad map */
1154 * This array contains overrides for when the first occurrence of a
1155 * particular SRW error in the array above does not correspond with
1156 * the best back-translation of that SRW error.
1158 static int srw_bib1_map[] = {
1160 /* No doubt there are many more */
1165 int yaz_diag_bib1_to_srw (int code)
1167 const int *p = bib1_srw_map;
1177 int yaz_diag_srw_to_bib1(int code)
1179 /* Check explicit reverse-map first */
1180 const int *p = srw_bib1_map;
1188 /* Fall back on reverse lookup in main map */
1199 static void add_val_int(ODR o, char **name, char **value, int *i,
1200 char *a_name, int *val)
1205 value[*i] = (char *) odr_malloc(o, 30);
1206 sprintf(value[*i], "%d", *val);
1211 static void add_val_str(ODR o, char **name, char **value, int *i,
1212 char *a_name, char *val)
1222 static int yaz_get_sru_parms(const Z_SRW_PDU *srw_pdu, ODR encode,
1223 char **name, char **value, int max_names)
1226 add_val_str(encode, name, value, &i, "version", srw_pdu->srw_version);
1227 name[i] = "operation";
1228 switch(srw_pdu->which)
1230 case Z_SRW_searchRetrieve_request:
1231 value[i++] = "searchRetrieve";
1232 switch(srw_pdu->u.request->query_type)
1234 case Z_SRW_query_type_cql:
1235 add_val_str(encode, name, value, &i, "query",
1236 srw_pdu->u.request->query.cql);
1238 case Z_SRW_query_type_pqf:
1239 add_val_str(encode, name, value, &i, "x-pquery",
1240 srw_pdu->u.request->query.pqf);
1242 case Z_SRW_query_type_xcql:
1243 add_val_str(encode, name, value, &i, "x-cql",
1244 srw_pdu->u.request->query.xcql);
1247 switch(srw_pdu->u.request->sort_type)
1249 case Z_SRW_sort_type_none:
1251 case Z_SRW_sort_type_sort:
1252 add_val_str(encode, name, value, &i, "sortKeys",
1253 srw_pdu->u.request->sort.sortKeys);
1256 add_val_int(encode, name, value, &i, "startRecord",
1257 srw_pdu->u.request->startRecord);
1258 add_val_int(encode, name, value, &i, "maximumRecords",
1259 srw_pdu->u.request->maximumRecords);
1260 add_val_str(encode, name, value, &i, "recordSchema",
1261 srw_pdu->u.request->recordSchema);
1262 add_val_str(encode, name, value, &i, "recordPacking",
1263 srw_pdu->u.request->recordPacking);
1264 add_val_str(encode, name, value, &i, "recordXPath",
1265 srw_pdu->u.request->recordXPath);
1266 add_val_str(encode, name, value, &i, "stylesheet",
1267 srw_pdu->u.request->stylesheet);
1268 add_val_int(encode, name, value, &i, "resultSetTTL",
1269 srw_pdu->u.request->resultSetTTL);
1271 case Z_SRW_explain_request:
1272 value[i++] = "explain";
1273 add_val_str(encode, name, value, &i, "stylesheet",
1274 srw_pdu->u.explain_request->stylesheet);
1276 case Z_SRW_scan_request:
1277 value[i++] = "scan";
1279 switch(srw_pdu->u.scan_request->query_type)
1281 case Z_SRW_query_type_cql:
1282 add_val_str(encode, name, value, &i, "scanClause",
1283 srw_pdu->u.scan_request->scanClause.cql);
1285 case Z_SRW_query_type_pqf:
1286 add_val_str(encode, name, value, &i, "x-pScanClause",
1287 srw_pdu->u.scan_request->scanClause.pqf);
1289 case Z_SRW_query_type_xcql:
1290 add_val_str(encode, name, value, &i, "x-cqlScanClause",
1291 srw_pdu->u.scan_request->scanClause.xcql);
1294 add_val_int(encode, name, value, &i, "responsePosition",
1295 srw_pdu->u.scan_request->responsePosition);
1296 add_val_int(encode, name, value, &i, "maximumTerms",
1297 srw_pdu->u.scan_request->maximumTerms);
1298 add_val_str(encode, name, value, &i, "stylesheet",
1299 srw_pdu->u.scan_request->stylesheet);
1301 case Z_SRW_update_request:
1302 value[i++] = "update";
1307 if (srw_pdu->extra_args)
1309 Z_SRW_extra_arg *ea = srw_pdu->extra_args;
1310 for (; ea && i < max_names-1; ea = ea->next)
1313 value[i] = ea->value;
1322 int yaz_sru_get_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1323 ODR encode, const char *charset)
1325 char *name[30], *value[30]; /* definite upper limit for SRU params */
1329 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1330 srw_pdu->username, srw_pdu->password);
1331 if (yaz_get_sru_parms(srw_pdu, encode, name, value, 30))
1333 yaz_array_to_uri(&uri_args, encode, name, value);
1335 hreq->method = "GET";
1338 odr_malloc(encode, strlen(hreq->path) + strlen(uri_args) + 4);
1340 sprintf(path, "%s?%s", hreq->path, uri_args);
1343 z_HTTP_header_add_content_type(encode, &hreq->headers,
1344 "text/xml", charset);
1348 int yaz_sru_post_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1349 ODR encode, const char *charset)
1351 char *name[30], *value[30]; /* definite upper limit for SRU params */
1354 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1355 srw_pdu->username, srw_pdu->password);
1356 if (yaz_get_sru_parms(srw_pdu, encode, name, value, 30))
1359 yaz_array_to_uri(&uri_args, encode, name, value);
1361 hreq->method = "POST";
1363 hreq->content_buf = uri_args;
1364 hreq->content_len = strlen(uri_args);
1366 z_HTTP_header_add_content_type(encode, &hreq->headers,
1367 "application/x-www-form-urlencoded",
1372 int yaz_sru_soap_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1373 ODR odr, const char *charset)
1375 Z_SOAP_Handler handlers[3] = {
1377 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
1378 {YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec},
1382 Z_SOAP *p = (Z_SOAP*) odr_malloc(odr, sizeof(*p));
1384 z_HTTP_header_add_basic_auth(odr, &hreq->headers,
1385 srw_pdu->username, srw_pdu->password);
1386 z_HTTP_header_add_content_type(odr,
1388 "text/xml", charset);
1390 z_HTTP_header_add(odr, &hreq->headers,
1391 "SOAPAction", "\"\"");
1392 p->which = Z_SOAP_generic;
1393 p->u.generic = (Z_SOAP_Generic *) odr_malloc(odr, sizeof(*p->u.generic));
1394 p->u.generic->no = 0;
1395 p->u.generic->ns = 0;
1396 p->u.generic->p = srw_pdu;
1397 p->ns = "http://schemas.xmlsoap.org/soap/envelope/";
1400 if (srw_pdu->which == Z_SRW_update_request ||
1401 srw_pdu->which == Z_SRW_update_response)
1402 p->u.generic->no = 1; /* second handler */
1404 return z_soap_codec_enc(odr, &p,
1406 &hreq->content_len, handlers,
1410 Z_SRW_recordVersion *yaz_srw_get_record_versions(ODR odr, int num )
1412 Z_SRW_recordVersion *ver
1413 = (Z_SRW_recordVersion *) odr_malloc( odr, num * sizeof(*ver) );
1415 for ( i=0; i < num; ++i ){
1416 ver[i].versionType = 0;
1417 ver[i].versionValue = 0;
1422 const char *yaz_srw_pack_to_str(int pack)
1426 case Z_SRW_recordPacking_string:
1428 case Z_SRW_recordPacking_XML:
1430 case Z_SRW_recordPacking_URL:
1436 int yaz_srw_str_to_pack(const char *str)
1438 if (!yaz_matchstr(str, "string"))
1439 return Z_SRW_recordPacking_string;
1440 if (!yaz_matchstr(str, "xml"))
1441 return Z_SRW_recordPacking_XML;
1442 if (!yaz_matchstr(str, "url"))
1443 return Z_SRW_recordPacking_URL;
1447 void yaz_encode_sru_extra(Z_SRW_PDU *sr, ODR odr, const char *extra_args)
1453 Z_SRW_extra_arg **ea = &sr->extra_args;
1454 yaz_uri_to_array(extra_args, odr, &name, &val);
1458 *ea = (Z_SRW_extra_arg *) odr_malloc(odr, sizeof(**ea));
1459 (*ea)->name = *name;
1460 (*ea)->value = *val;
1474 * indent-tabs-mode: nil
1476 * vim: shiftwidth=4 tabstop=8 expandtab