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, '&');
178 static int yaz_base64decode(const char *in, char *out)
180 const char *map = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
181 "abcdefghijklmnopqrstuvwxyz0123456789+/";
183 int len = strlen(in);
190 if (!(p = strchr(map, in[0])))
194 if (!(p = strchr(map, in[1])))
198 *(out++) = i0 << 2 | i1 >> 4;
202 if (!(p = strchr(map, in[2])))
206 *(out++) = i1 << 4 | i2 >> 2;
210 if (!(p = strchr(map, in[3])))
214 *(out++) = i2 << 6 | i3;
224 int yaz_srw_check_content_type(Z_HTTP_Response *hres)
226 const char *content_type = z_HTTP_header_lookup(hres->headers,
230 if (!yaz_strcmp_del("text/xml", content_type, "; "))
232 if (!yaz_strcmp_del("application/xml", content_type, "; "))
239 * Look for authentication tokens in HTTP Basic parameters or in x-username/x-password
240 * parameters. Added by SH.
242 static void yaz_srw_decodeauth(Z_SRW_PDU *sr, Z_HTTP_Request *hreq,
243 char *username, char *password, ODR decode)
245 const char *basic = z_HTTP_header_lookup(hreq->headers, "Authorization");
248 sr->username = username;
250 sr->password = password;
255 char ubuf[256] = "", pbuf[256] = "", *p;
256 if (strncmp(basic, "Basic ", 6))
260 if (!len || len > 256)
262 olen = yaz_base64decode(basic, out);
263 /* Format of out should be username:password at this point */
265 if ((p = strchr(ubuf, ':'))) {
271 sr->username = odr_strdup(decode, ubuf);
273 sr->password = odr_strdup(decode, pbuf);
277 void yaz_uri_val_int(const char *path, const char *name, ODR o, int **intp)
279 const char *v = yaz_uri_val(path, name, o);
281 *intp = odr_intdup(o, atoi(v));
284 void yaz_mk_srw_diagnostic(ODR o, Z_SRW_diagnostic *d,
285 const char *uri, const char *message,
288 d->uri = odr_strdup(o, uri);
290 d->message = odr_strdup(o, message);
294 d->details = odr_strdup(o, details);
299 void yaz_mk_std_diagnostic(ODR o, Z_SRW_diagnostic *d,
300 int code, const char *details)
304 sprintf(uri, "info:srw/diagnostic/1/%d", code);
305 yaz_mk_srw_diagnostic(o, d, uri, 0, details);
308 void yaz_add_srw_diagnostic_uri(ODR o, Z_SRW_diagnostic **d,
309 int *num, const char *uri,
310 const char *message, const char *details)
312 Z_SRW_diagnostic *d_new;
313 d_new = (Z_SRW_diagnostic *) odr_malloc (o, (*num + 1)* sizeof(**d));
315 memcpy (d_new, *d, *num *sizeof(**d));
318 yaz_mk_srw_diagnostic(o, *d + *num, uri, message, details);
322 void yaz_add_srw_diagnostic(ODR o, Z_SRW_diagnostic **d,
323 int *num, int code, const char *addinfo)
327 sprintf(uri, "info:srw/diagnostic/1/%d", code);
328 yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
332 void yaz_add_sru_update_diagnostic(ODR o, Z_SRW_diagnostic **d,
333 int *num, int code, const char *addinfo)
337 sprintf(uri, "info:srw/diagnostic/12/%d", code);
338 yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
342 void yaz_mk_sru_surrogate(ODR o, Z_SRW_record *record, int pos,
343 int code, const char *details)
345 const char *message = yaz_diag_srw_str(code);
348 len += strlen(message);
350 len += strlen(details);
352 record->recordData_buf = (char *) odr_malloc(o, len);
354 sprintf(record->recordData_buf, "<diagnostic "
355 "xmlns=\"http://www.loc.gov/zing/srw/diagnostic/\">\n"
356 " <uri>info:srw/diagnostic/1/%d</uri>\n", code);
358 sprintf(record->recordData_buf + strlen(record->recordData_buf),
359 " <details>%s</details>\n", details);
361 sprintf(record->recordData_buf + strlen(record->recordData_buf),
362 " <message>%s</message>\n", message);
363 sprintf(record->recordData_buf + strlen(record->recordData_buf),
365 record->recordData_len = strlen(record->recordData_buf);
366 record->recordPosition = odr_intdup(o, pos);
367 record->recordSchema = "info:srw/schema/1/diagnostics-v1.1";
370 static void grab_charset(ODR o, const char *content_type, char **charset)
374 const char *charset_p = 0;
375 if (content_type && (charset_p = strstr(content_type, "; charset=")))
379 while (i < 20 && charset_p[i] &&
380 !strchr("; \n\r", charset_p[i]))
382 *charset = (char*) odr_malloc(o, i+1);
383 memcpy(*charset, charset_p, i);
384 (*charset)[i] = '\0';
389 int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
390 Z_SOAP **soap_package, ODR decode, char **charset)
392 if (!strcmp(hreq->method, "POST"))
394 const char *content_type = z_HTTP_header_lookup(hreq->headers,
397 (!yaz_strcmp_del("text/xml", content_type, "; ") ||
398 !yaz_strcmp_del("application/soap+xml", content_type, "; ") ||
399 !yaz_strcmp_del("text/plain", content_type, "; ")))
401 char *db = "Default";
402 const char *p0 = hreq->path, *p1;
405 static Z_SOAP_Handler soap_handlers[4] = {
407 { YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec },
408 { YAZ_XMLNS_SRU_v1_0, 0, (Z_SOAP_fun) yaz_srw_codec },
409 { YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec },
416 p1 = strchr(p0, '?');
418 p1 = p0 + strlen(p0);
421 db = (char*) odr_malloc(decode, p1 - p0 + 1);
422 memcpy (db, p0, p1 - p0);
426 grab_charset(decode, content_type, charset);
428 ret = z_soap_codec(decode, soap_package,
429 &hreq->content_buf, &hreq->content_len,
431 if (ret == 0 && (*soap_package)->which == Z_SOAP_generic)
433 *srw_pdu = (Z_SRW_PDU*) (*soap_package)->u.generic->p;
435 if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request &&
436 (*srw_pdu)->u.request->database == 0)
437 (*srw_pdu)->u.request->database = db;
439 if ((*srw_pdu)->which == Z_SRW_explain_request &&
440 (*srw_pdu)->u.explain_request->database == 0)
441 (*srw_pdu)->u.explain_request->database = db;
443 if ((*srw_pdu)->which == Z_SRW_scan_request &&
444 (*srw_pdu)->u.scan_request->database == 0)
445 (*srw_pdu)->u.scan_request->database = db;
447 if ((*srw_pdu)->which == Z_SRW_update_request &&
448 (*srw_pdu)->u.update_request->database == 0)
449 (*srw_pdu)->u.update_request->database = db;
459 static int yaz_sru_decode_integer(ODR odr, const char *pname,
460 const char *valstr, int **valp,
461 Z_SRW_diagnostic **diag, int *num_diag,
467 if (sscanf(valstr, "%d", &ival) != 1)
469 yaz_add_srw_diagnostic(odr, diag, num_diag,
470 YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
473 if (min_value >= 0 && ival < min_value)
475 yaz_add_srw_diagnostic(odr, diag, num_diag,
476 YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
479 *valp = odr_intdup(odr, ival);
484 http://www.loc.gov/z3950/agency/zing/srw/service.html
486 int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
487 Z_SOAP **soap_package, ODR decode, char **charset,
488 Z_SRW_diagnostic **diag, int *num_diag)
491 static Z_SOAP_Handler soap_handlers[2] = {
492 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
496 const char *content_type = z_HTTP_header_lookup(hreq->headers,
500 SRU GET: ignore content type.
501 SRU POST: we support "application/x-www-form-urlencoded";
502 not "multipart/form-data" .
504 if (!strcmp(hreq->method, "GET")
506 (!strcmp(hreq->method, "POST") && content_type &&
507 !yaz_strcmp_del("application/x-www-form-urlencoded",
508 content_type, "; ")))
510 char *db = "Default";
511 const char *p0 = hreq->path, *p1;
513 const char *operation = 0;
520 char *stylesheet = 0;
521 char *scanClause = 0;
522 char *pScanClause = 0;
523 char *recordXPath = 0;
524 char *recordSchema = 0;
525 char *recordPacking = "xml"; /* xml packing is default for SRU */
526 char *maximumRecords = 0;
527 char *startRecord = 0;
528 char *maximumTerms = 0;
529 char *responsePosition = 0;
530 char *extraRequestData = 0;
531 Z_SRW_extra_arg *extra_args = 0;
536 grab_charset(decode, content_type, charset);
537 if (charset && *charset == 0 && !strcmp(hreq->method, "GET"))
542 p1 = strchr(p0, '?');
544 p1 = p0 + strlen(p0);
547 db = (char*) odr_malloc(decode, p1 - p0 + 1);
548 memcpy (db, p0, p1 - p0);
551 if (!strcmp(hreq->method, "POST"))
552 p1 = hreq->content_buf;
553 yaz_uri_to_array(p1, decode, &uri_name, &uri_val);
558 for (i = 0; uri_name[i]; i++)
560 char *n = uri_name[i];
561 char *v = uri_val[i];
562 if (!strcmp(n, "query"))
564 else if (!strcmp(n, "x-pquery"))
566 else if (!strcmp(n, "x-username"))
568 else if (!strcmp(n, "x-password"))
570 else if (!strcmp(n, "operation"))
572 else if (!strcmp(n, "stylesheet"))
574 else if (!strcmp(n, "sortKeys"))
576 else if (!strcmp(n, "recordXPath"))
578 else if (!strcmp(n, "recordSchema"))
580 else if (!strcmp(n, "recordPacking"))
582 else if (!strcmp(n, "version"))
584 else if (!strcmp(n, "scanClause"))
586 else if (!strcmp(n, "x-pScanClause"))
588 else if (!strcmp(n, "maximumRecords"))
590 else if (!strcmp(n, "startRecord"))
592 else if (!strcmp(n, "maximumTerms"))
594 else if (!strcmp(n, "responsePosition"))
595 responsePosition = v;
596 else if (!strcmp(n, "extraRequestData"))
597 extraRequestData = v;
598 else if (n[0] == 'x' && n[1] == '-')
600 Z_SRW_extra_arg **l = &extra_args;
603 *l = odr_malloc(decode, sizeof(**l));
604 (*l)->name = odr_strdup(decode, n);
605 (*l)->value = odr_strdup(decode, v);
609 yaz_add_srw_diagnostic(decode, diag, num_diag,
610 YAZ_SRW_UNSUPP_PARAMETER, n);
616 yaz_add_srw_diagnostic(
617 decode, diag, num_diag,
618 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "version");
622 version = yaz_negotiate_sru_version(version);
625 { /* negotiation failed. */
626 yaz_add_srw_diagnostic(decode, diag, num_diag,
627 YAZ_SRW_UNSUPP_VERSION, "1.2");
634 yaz_add_srw_diagnostic(
635 decode, diag, num_diag,
636 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "operation");
637 operation = "explain";
639 if (!strcmp(operation, "searchRetrieve"))
641 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
643 sr->srw_version = version;
644 sr->extra_args = extra_args;
646 yaz_srw_decodeauth(sr, hreq, username, password, decode);
649 sr->u.request->query_type = Z_SRW_query_type_cql;
650 sr->u.request->query.cql = query;
654 sr->u.request->query_type = Z_SRW_query_type_pqf;
655 sr->u.request->query.pqf = pQuery;
658 yaz_add_srw_diagnostic(
659 decode, diag, num_diag,
660 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "query");
664 sr->u.request->sort_type = Z_SRW_sort_type_sort;
665 sr->u.request->sort.sortKeys = sortKeys;
667 sr->u.request->recordXPath = recordXPath;
668 sr->u.request->recordSchema = recordSchema;
669 sr->u.request->recordPacking = recordPacking;
670 sr->u.request->stylesheet = stylesheet;
672 yaz_sru_decode_integer(decode, "maximumRecords", maximumRecords,
673 &sr->u.request->maximumRecords,
676 yaz_sru_decode_integer(decode, "startRecord", startRecord,
677 &sr->u.request->startRecord,
680 sr->u.request->database = db;
682 (*soap_package) = (Z_SOAP *)
683 odr_malloc(decode, sizeof(**soap_package));
684 (*soap_package)->which = Z_SOAP_generic;
686 (*soap_package)->u.generic = (Z_SOAP_Generic *)
687 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
689 (*soap_package)->u.generic->p = sr;
690 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
691 (*soap_package)->u.generic->no = 0;
693 (*soap_package)->ns = "SRU";
697 else if (!strcmp(operation, "explain"))
699 /* Transfer SRU explain parameters to common struct */
700 /* http://www.loc.gov/z3950/agency/zing/srw/explain.html */
701 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
703 sr->srw_version = version;
704 sr->extra_args = extra_args;
705 yaz_srw_decodeauth(sr, hreq, username, password, decode);
707 sr->u.explain_request->recordPacking = recordPacking;
708 sr->u.explain_request->database = db;
710 sr->u.explain_request->stylesheet = stylesheet;
712 (*soap_package) = (Z_SOAP *)
713 odr_malloc(decode, sizeof(**soap_package));
714 (*soap_package)->which = Z_SOAP_generic;
716 (*soap_package)->u.generic = (Z_SOAP_Generic *)
717 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
719 (*soap_package)->u.generic->p = sr;
720 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
721 (*soap_package)->u.generic->no = 0;
723 (*soap_package)->ns = "SRU";
727 else if (!strcmp(operation, "scan"))
729 /* Transfer SRU scan parameters to common struct */
730 /* http://www.loc.gov/z3950/agency/zing/srw/scan.html */
731 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_scan_request);
733 sr->srw_version = version;
734 sr->extra_args = extra_args;
736 yaz_srw_decodeauth(sr, hreq, username, password, decode);
740 sr->u.scan_request->query_type = Z_SRW_query_type_cql;
741 sr->u.scan_request->scanClause.cql = scanClause;
743 else if (pScanClause)
745 sr->u.scan_request->query_type = Z_SRW_query_type_pqf;
746 sr->u.scan_request->scanClause.pqf = pScanClause;
749 yaz_add_srw_diagnostic(
750 decode, diag, num_diag,
751 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "scanClause");
752 sr->u.scan_request->database = db;
754 yaz_sru_decode_integer(decode, "maximumTerms",
756 &sr->u.scan_request->maximumTerms,
759 yaz_sru_decode_integer(decode, "responsePosition",
761 &sr->u.scan_request->responsePosition,
764 sr->u.scan_request->stylesheet = stylesheet;
766 (*soap_package) = (Z_SOAP *)
767 odr_malloc(decode, sizeof(**soap_package));
768 (*soap_package)->which = Z_SOAP_generic;
770 (*soap_package)->u.generic = (Z_SOAP_Generic *)
771 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
773 (*soap_package)->u.generic->p = sr;
774 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
775 (*soap_package)->u.generic->no = 0;
777 (*soap_package)->ns = "SRU";
783 /* unsupported operation ... */
784 /* Act as if we received a explain request and throw diagnostic. */
786 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
788 sr->srw_version = version;
790 sr->u.explain_request->recordPacking = recordPacking;
791 sr->u.explain_request->database = db;
793 sr->u.explain_request->stylesheet = stylesheet;
795 (*soap_package) = (Z_SOAP *)
796 odr_malloc(decode, sizeof(**soap_package));
797 (*soap_package)->which = Z_SOAP_generic;
799 (*soap_package)->u.generic = (Z_SOAP_Generic *)
800 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
802 (*soap_package)->u.generic->p = sr;
803 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
804 (*soap_package)->u.generic->no = 0;
806 (*soap_package)->ns = "SRU";
808 yaz_add_srw_diagnostic(decode, diag, num_diag,
809 YAZ_SRW_UNSUPP_OPERATION, operation);
818 Z_SRW_extra_record *yaz_srw_get_extra_record(ODR o)
820 Z_SRW_extra_record *res = (Z_SRW_extra_record *)
821 odr_malloc(o, sizeof(*res));
823 res->extraRecordData_buf = 0;
824 res->extraRecordData_len = 0;
825 res->recordIdentifier = 0;
830 Z_SRW_record *yaz_srw_get_records(ODR o, int n)
832 Z_SRW_record *res = (Z_SRW_record *) odr_malloc(o, n * sizeof(*res));
835 for (i = 0; i<n; i++)
837 res[i].recordSchema = 0;
838 res[i].recordPacking = Z_SRW_recordPacking_string;
839 res[i].recordData_buf = 0;
840 res[i].recordData_len = 0;
841 res[i].recordPosition = 0;
846 Z_SRW_record *yaz_srw_get_record(ODR o)
848 return yaz_srw_get_records(o, 1);
851 static Z_SRW_PDU *yaz_srw_get_core_ver(ODR o, const char *version)
853 Z_SRW_PDU *p = (Z_SRW_PDU *) odr_malloc(o, sizeof(*p));
854 p->srw_version = odr_strdup(o, version);
861 Z_SRW_PDU *yaz_srw_get_core_v_1_1(ODR o)
863 return yaz_srw_get_core_ver(o, "1.1");
866 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
868 return yaz_srw_get_pdu(o, which, "1.1");
871 Z_SRW_PDU *yaz_srw_get_pdu(ODR o, int which, const char *version)
873 Z_SRW_PDU *sr = yaz_srw_get_core_ver(o, version);
878 case Z_SRW_searchRetrieve_request:
879 sr->u.request = (Z_SRW_searchRetrieveRequest *)
880 odr_malloc(o, sizeof(*sr->u.request));
881 sr->u.request->query_type = Z_SRW_query_type_cql;
882 sr->u.request->query.cql = 0;
883 sr->u.request->sort_type = Z_SRW_sort_type_none;
884 sr->u.request->sort.none = 0;
885 sr->u.request->startRecord = 0;
886 sr->u.request->maximumRecords = 0;
887 sr->u.request->recordSchema = 0;
888 sr->u.request->recordPacking = 0;
889 sr->u.request->recordXPath = 0;
890 sr->u.request->database = 0;
891 sr->u.request->resultSetTTL = 0;
892 sr->u.request->stylesheet = 0;
894 case Z_SRW_searchRetrieve_response:
895 sr->u.response = (Z_SRW_searchRetrieveResponse *)
896 odr_malloc(o, sizeof(*sr->u.response));
897 sr->u.response->numberOfRecords = 0;
898 sr->u.response->resultSetId = 0;
899 sr->u.response->resultSetIdleTime = 0;
900 sr->u.response->records = 0;
901 sr->u.response->num_records = 0;
902 sr->u.response->diagnostics = 0;
903 sr->u.response->num_diagnostics = 0;
904 sr->u.response->nextRecordPosition = 0;
905 sr->u.response->extra_records = 0;
907 case Z_SRW_explain_request:
908 sr->u.explain_request = (Z_SRW_explainRequest *)
909 odr_malloc(o, sizeof(*sr->u.explain_request));
910 sr->u.explain_request->recordPacking = 0;
911 sr->u.explain_request->database = 0;
912 sr->u.explain_request->stylesheet = 0;
914 case Z_SRW_explain_response:
915 sr->u.explain_response = (Z_SRW_explainResponse *)
916 odr_malloc(o, sizeof(*sr->u.explain_response));
917 sr->u.explain_response->record.recordData_buf = 0;
918 sr->u.explain_response->record.recordData_len = 0;
919 sr->u.explain_response->record.recordSchema = 0;
920 sr->u.explain_response->record.recordPosition = 0;
921 sr->u.explain_response->record.recordPacking =
922 Z_SRW_recordPacking_string;
923 sr->u.explain_response->diagnostics = 0;
924 sr->u.explain_response->num_diagnostics = 0;
925 sr->u.explain_response->extra_record = 0;
927 case Z_SRW_scan_request:
928 sr->u.scan_request = (Z_SRW_scanRequest *)
929 odr_malloc(o, sizeof(*sr->u.scan_request));
930 sr->u.scan_request->database = 0;
931 sr->u.scan_request->stylesheet = 0;
932 sr->u.scan_request->maximumTerms = 0;
933 sr->u.scan_request->responsePosition = 0;
934 sr->u.scan_request->query_type = Z_SRW_query_type_cql;
935 sr->u.scan_request->scanClause.cql = 0;
937 case Z_SRW_scan_response:
938 sr->u.scan_response = (Z_SRW_scanResponse *)
939 odr_malloc(o, sizeof(*sr->u.scan_response));
940 sr->u.scan_response->terms = 0;
941 sr->u.scan_response->num_terms = 0;
942 sr->u.scan_response->diagnostics = 0;
943 sr->u.scan_response->num_diagnostics = 0;
945 case Z_SRW_update_request:
946 sr->u.update_request = (Z_SRW_updateRequest *)
947 odr_malloc(o, sizeof(*sr->u.update_request));
948 sr->u.update_request->database = 0;
949 sr->u.update_request->stylesheet = 0;
950 sr->u.update_request->record = 0;
951 sr->u.update_request->recordId = 0;
952 sr->u.update_request->recordVersions = 0;
953 sr->u.update_request->num_recordVersions = 0;
954 sr->u.update_request->extra_record = 0;
955 sr->u.update_request->extraRequestData_buf = 0;
956 sr->u.update_request->extraRequestData_len = 0;
957 sr->u.request->database = 0;
959 case Z_SRW_update_response:
960 sr->u.update_response = (Z_SRW_updateResponse *)
961 odr_malloc(o, sizeof(*sr->u.update_response));
962 sr->u.update_response->operationStatus = 0;
963 sr->u.update_response->recordId = 0;
964 sr->u.update_response->recordVersions = 0;
965 sr->u.update_response->num_recordVersions = 0;
966 sr->u.update_response->record = 0;
967 sr->u.update_response->extra_record = 0;
968 sr->u.update_response->extraResponseData_buf = 0;
969 sr->u.update_response->extraResponseData_len = 0;
970 sr->u.update_response->diagnostics = 0;
971 sr->u.update_response->num_diagnostics = 0;
977 static int bib1_srw_map[] = {
987 108, 10, /* Malformed query : Syntax error */
1017 100, 1, /* bad map */
1065 205, 1, /* bad map */
1066 206, 1, /* bad map */
1068 208, 1, /* bad map */
1079 218, 1, /* bad map */
1080 219, 1, /* bad map */
1081 220, 1, /* bad map */
1082 221, 1, /* bad map */
1084 223, 1, /* bad map */
1085 224, 1, /* bad map */
1086 225, 1, /* bad map */
1087 226, 1, /* bad map */
1089 228, 1, /* bad map */
1094 233, 1, /* bad map */
1095 234, 1, /* bad map */
1101 240, 1, /* bad map */
1102 241, 1, /* bad map */
1104 243, 1, /* bad map */
1109 1001, 1, /* bad map */
1110 1002, 1, /* bad map */
1111 1003, 1, /* bad map */
1112 1004, 1, /* bad map */
1113 1005, 1, /* bad map */
1114 1006, 1, /* bad map */
1147 * This array contains overrides for when the first occurrence of a
1148 * particular SRW error in the array above does not correspond with
1149 * the best back-translation of that SRW error.
1151 static int srw_bib1_map[] = {
1153 /* No doubt there are many more */
1158 int yaz_diag_bib1_to_srw (int code)
1160 const int *p = bib1_srw_map;
1170 int yaz_diag_srw_to_bib1(int code)
1172 /* Check explicit reverse-map first */
1173 const int *p = srw_bib1_map;
1181 /* Fall back on reverse lookup in main map */
1192 static void add_val_int(ODR o, char **name, char **value, int *i,
1193 char *a_name, int *val)
1198 value[*i] = (char *) odr_malloc(o, 30);
1199 sprintf(value[*i], "%d", *val);
1204 static void add_val_str(ODR o, char **name, char **value, int *i,
1205 char *a_name, char *val)
1215 static int yaz_get_sru_parms(const Z_SRW_PDU *srw_pdu, ODR encode,
1216 char **name, char **value, int max_names)
1219 add_val_str(encode, name, value, &i, "version", srw_pdu->srw_version);
1220 name[i] = "operation";
1221 switch(srw_pdu->which)
1223 case Z_SRW_searchRetrieve_request:
1224 value[i++] = "searchRetrieve";
1225 switch(srw_pdu->u.request->query_type)
1227 case Z_SRW_query_type_cql:
1228 add_val_str(encode, name, value, &i, "query",
1229 srw_pdu->u.request->query.cql);
1231 case Z_SRW_query_type_pqf:
1232 add_val_str(encode, name, value, &i, "x-pquery",
1233 srw_pdu->u.request->query.pqf);
1235 case Z_SRW_query_type_xcql:
1236 add_val_str(encode, name, value, &i, "x-cql",
1237 srw_pdu->u.request->query.xcql);
1240 switch(srw_pdu->u.request->sort_type)
1242 case Z_SRW_sort_type_none:
1244 case Z_SRW_sort_type_sort:
1245 add_val_str(encode, name, value, &i, "sortKeys",
1246 srw_pdu->u.request->sort.sortKeys);
1249 add_val_int(encode, name, value, &i, "startRecord",
1250 srw_pdu->u.request->startRecord);
1251 add_val_int(encode, name, value, &i, "maximumRecords",
1252 srw_pdu->u.request->maximumRecords);
1253 add_val_str(encode, name, value, &i, "recordSchema",
1254 srw_pdu->u.request->recordSchema);
1255 add_val_str(encode, name, value, &i, "recordPacking",
1256 srw_pdu->u.request->recordPacking);
1257 add_val_str(encode, name, value, &i, "recordXPath",
1258 srw_pdu->u.request->recordXPath);
1259 add_val_str(encode, name, value, &i, "stylesheet",
1260 srw_pdu->u.request->stylesheet);
1261 add_val_int(encode, name, value, &i, "resultSetTTL",
1262 srw_pdu->u.request->resultSetTTL);
1264 case Z_SRW_explain_request:
1265 value[i++] = "explain";
1266 add_val_str(encode, name, value, &i, "stylesheet",
1267 srw_pdu->u.explain_request->stylesheet);
1269 case Z_SRW_scan_request:
1270 value[i++] = "scan";
1272 switch(srw_pdu->u.scan_request->query_type)
1274 case Z_SRW_query_type_cql:
1275 add_val_str(encode, name, value, &i, "scanClause",
1276 srw_pdu->u.scan_request->scanClause.cql);
1278 case Z_SRW_query_type_pqf:
1279 add_val_str(encode, name, value, &i, "x-pScanClause",
1280 srw_pdu->u.scan_request->scanClause.pqf);
1282 case Z_SRW_query_type_xcql:
1283 add_val_str(encode, name, value, &i, "x-cqlScanClause",
1284 srw_pdu->u.scan_request->scanClause.xcql);
1287 add_val_int(encode, name, value, &i, "responsePosition",
1288 srw_pdu->u.scan_request->responsePosition);
1289 add_val_int(encode, name, value, &i, "maximumTerms",
1290 srw_pdu->u.scan_request->maximumTerms);
1291 add_val_str(encode, name, value, &i, "stylesheet",
1292 srw_pdu->u.scan_request->stylesheet);
1294 case Z_SRW_update_request:
1295 value[i++] = "update";
1300 if (srw_pdu->extra_args)
1302 Z_SRW_extra_arg *ea = srw_pdu->extra_args;
1303 for (; ea && i < max_names-1; ea = ea->next)
1306 value[i] = ea->value;
1315 int yaz_sru_get_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1316 ODR encode, const char *charset)
1318 char *name[30], *value[30]; /* definite upper limit for SRU params */
1322 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1323 srw_pdu->username, srw_pdu->password);
1324 if (yaz_get_sru_parms(srw_pdu, encode, name, value, 30))
1326 yaz_array_to_uri(&uri_args, encode, name, value);
1328 hreq->method = "GET";
1331 odr_malloc(encode, strlen(hreq->path) + strlen(uri_args) + 4);
1333 sprintf(path, "%s?%s", hreq->path, uri_args);
1336 z_HTTP_header_add_content_type(encode, &hreq->headers,
1337 "text/xml", charset);
1341 int yaz_sru_post_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1342 ODR encode, const char *charset)
1344 char *name[30], *value[30]; /* definite upper limit for SRU params */
1347 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1348 srw_pdu->username, srw_pdu->password);
1349 if (yaz_get_sru_parms(srw_pdu, encode, name, value, 30))
1352 yaz_array_to_uri(&uri_args, encode, name, value);
1354 hreq->method = "POST";
1356 hreq->content_buf = uri_args;
1357 hreq->content_len = strlen(uri_args);
1359 z_HTTP_header_add_content_type(encode, &hreq->headers,
1360 "application/x-www-form-urlencoded",
1365 int yaz_sru_soap_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1366 ODR odr, const char *charset)
1368 Z_SOAP_Handler handlers[3] = {
1370 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
1371 {YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec},
1375 Z_SOAP *p = (Z_SOAP*) odr_malloc(odr, sizeof(*p));
1377 z_HTTP_header_add_basic_auth(odr, &hreq->headers,
1378 srw_pdu->username, srw_pdu->password);
1379 z_HTTP_header_add_content_type(odr,
1381 "text/xml", charset);
1383 z_HTTP_header_add(odr, &hreq->headers,
1384 "SOAPAction", "\"\"");
1385 p->which = Z_SOAP_generic;
1386 p->u.generic = (Z_SOAP_Generic *) odr_malloc(odr, sizeof(*p->u.generic));
1387 p->u.generic->no = 0;
1388 p->u.generic->ns = 0;
1389 p->u.generic->p = srw_pdu;
1390 p->ns = "http://schemas.xmlsoap.org/soap/envelope/";
1393 if (srw_pdu->which == Z_SRW_update_request ||
1394 srw_pdu->which == Z_SRW_update_response)
1395 p->u.generic->no = 1; /* second handler */
1397 return z_soap_codec_enc(odr, &p,
1399 &hreq->content_len, handlers,
1403 Z_SRW_recordVersion *yaz_srw_get_record_versions(ODR odr, int num )
1405 Z_SRW_recordVersion *ver
1406 = (Z_SRW_recordVersion *) odr_malloc( odr, num * sizeof(*ver) );
1408 for ( i=0; i < num; ++i ){
1409 ver[i].versionType = 0;
1410 ver[i].versionValue = 0;
1415 const char *yaz_srw_pack_to_str(int pack)
1419 case Z_SRW_recordPacking_string:
1421 case Z_SRW_recordPacking_XML:
1423 case Z_SRW_recordPacking_URL:
1429 int yaz_srw_str_to_pack(const char *str)
1431 if (!yaz_matchstr(str, "string"))
1432 return Z_SRW_recordPacking_string;
1433 if (!yaz_matchstr(str, "xml"))
1434 return Z_SRW_recordPacking_XML;
1435 if (!yaz_matchstr(str, "url"))
1436 return Z_SRW_recordPacking_URL;
1440 void yaz_encode_sru_extra(Z_SRW_PDU *sr, ODR odr, const char *extra_args)
1446 Z_SRW_extra_arg **ea = &sr->extra_args;
1447 yaz_uri_to_array(extra_args, odr, &name, &val);
1451 *ea = odr_malloc(odr, sizeof(**ea));
1452 (*ea)->name = *name;
1453 (*ea)->value = *val;
1467 * indent-tabs-mode: nil
1469 * vim: shiftwidth=4 tabstop=8 expandtab