1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) Index Data
3 * See the file LICENSE for details.
7 * \brief Implements SRW/SRU utilities.
16 #include <yaz/matchstr.h>
17 #include <yaz/base64.h>
18 #include <yaz/yaz-iconv.h>
21 #define MAX_SRU_PARAMETERS 30
23 static Z_SRW_extra_arg **append_extra_arg(ODR odr, Z_SRW_extra_arg **l,
24 const char *n, const char *v)
26 if (n && v && *v != '\0')
30 *l = (Z_SRW_extra_arg *) odr_malloc(odr, sizeof(**l));
31 (*l)->name = odr_strdup(odr, n);
32 (*l)->value = odr_strdup(odr, v);
39 static Z_SRW_extra_arg **append_extra_arg_int(ODR odr, Z_SRW_extra_arg **l,
40 const char *n, Odr_int *v)
45 sprintf(str, ODR_INT_PRINTF, *v);
46 l = append_extra_arg(odr, l, n, str);
51 static char *yaz_decode_sru_dbpath_odr(ODR n, const char *uri, size_t len)
53 return odr_strdupn(n, uri, len);
56 void yaz_encode_sru_dbpath_buf(char *dst, const char *db)
63 char *yaz_encode_sru_dbpath_odr(ODR out, const char *db)
65 char *dst = odr_malloc(out, 3 * strlen(db) + 2);
66 yaz_encode_sru_dbpath_buf(dst, db);
71 const char *yaz_element_attribute_value_get(xmlNodePtr ptr,
72 const char *node_name,
73 const char *attribute_name)
75 struct _xmlAttr *attr;
76 // check if the node name matches
77 if (strcmp((const char*) ptr->name, node_name))
79 // check if the attribute name and return the value
80 for (attr = ptr->properties; attr; attr = attr->next)
81 if (attr->children && attr->children->type == XML_TEXT_NODE)
83 if (!strcmp((const char *) attr->name, attribute_name))
84 return (const char *) attr->children->content;
90 int yaz_srw_check_content_type(Z_HTTP_Response *hres)
92 const char *content_type = z_HTTP_header_lookup(hres->headers,
96 if (!yaz_strcmp_del("text/xml", content_type, "; "))
98 if (!yaz_strcmp_del("application/xml", content_type, "; "))
100 if (!yaz_strcmp_del("application/sru+xml", content_type, "; "))
107 * Look for authentication tokens in HTTP Basic parameters or in x-username/x-password
108 * parameters. Added by SH.
110 static void yaz_srw_decodeauth(Z_SRW_PDU *sr, Z_HTTP_Request *hreq,
111 char *username, char *password, ODR decode)
113 const char *basic = z_HTTP_header_lookup(hreq->headers, "Authorization");
116 sr->username = username;
118 sr->password = password;
124 char ubuf[256] = "", pbuf[256] = "", *p;
125 if (strncmp(basic, "Basic ", 6))
129 if (!len || len > 256)
131 yaz_base64decode(basic, out);
132 /* Format of out should be username:password at this point */
134 if ((p = strchr(ubuf, ':')))
141 sr->username = odr_strdup(decode, ubuf);
143 sr->password = odr_strdup(decode, pbuf);
147 void yaz_mk_srw_diagnostic(ODR o, Z_SRW_diagnostic *d,
148 const char *uri, const char *message,
151 d->uri = odr_strdup(o, uri);
153 d->message = odr_strdup(o, message);
157 d->details = odr_strdup(o, details);
162 void yaz_mk_std_diagnostic(ODR o, Z_SRW_diagnostic *d,
163 int code, const char *details)
167 sprintf(uri, "info:srw/diagnostic/1/%d", code);
168 yaz_mk_srw_diagnostic(o, d, uri, 0, details);
171 void yaz_add_srw_diagnostic_uri(ODR o, Z_SRW_diagnostic **d,
172 int *num, const char *uri,
173 const char *message, const char *details)
175 Z_SRW_diagnostic *d_new;
176 d_new = (Z_SRW_diagnostic *) odr_malloc(o, (*num + 1)* sizeof(**d));
178 memcpy(d_new, *d, *num *sizeof(**d));
181 yaz_mk_srw_diagnostic(o, *d + *num, uri, message, details);
185 void yaz_add_srw_diagnostic(ODR o, Z_SRW_diagnostic **d,
186 int *num, int code, const char *addinfo)
190 sprintf(uri, "info:srw/diagnostic/1/%d", code);
191 yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
195 void yaz_add_sru_update_diagnostic(ODR o, Z_SRW_diagnostic **d,
196 int *num, int code, const char *addinfo)
200 sprintf(uri, "info:srw/diagnostic/12/%d", code);
201 yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
205 void yaz_mk_sru_surrogate(ODR o, Z_SRW_record *record, int pos,
206 int code, const char *details)
208 const char *message = yaz_diag_srw_str(code);
211 len += strlen(message);
213 len += strlen(details);
215 record->recordData_buf = (char *) odr_malloc(o, len);
217 sprintf(record->recordData_buf, "<diagnostic "
218 "xmlns=\"http://www.loc.gov/zing/srw/diagnostic/\">\n"
219 " <uri>info:srw/diagnostic/1/%d</uri>\n", code);
221 sprintf(record->recordData_buf + strlen(record->recordData_buf),
222 " <details>%s</details>\n", details);
224 sprintf(record->recordData_buf + strlen(record->recordData_buf),
225 " <message>%s</message>\n", message);
226 sprintf(record->recordData_buf + strlen(record->recordData_buf),
228 record->recordData_len = strlen(record->recordData_buf);
229 record->recordPosition = odr_intdup(o, pos);
230 record->recordSchema = "info:srw/schema/1/diagnostics-v1.1";
233 static void grab_charset(ODR o, const char *content_type, char **charset)
237 const char *charset_p = 0;
238 if (content_type && (charset_p = strstr(content_type, "; charset=")))
242 charset_p += 10; /* skip ; charset= */
243 if (charset_p[i] == '"' || charset_p[i] == '\'')
244 sep = charset_p[i++];
245 *charset = odr_strdup(o, charset_p);
246 while (charset_p[i] && charset_p[i] != sep)
248 if (!sep && strchr("; \n\r", charset_p[i]))
250 if (charset_p[i] == '\\' && charset_p[i+1])
252 (*charset)[j++] = charset_p[i++];
254 (*charset)[j] = '\0';
259 int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
260 Z_SOAP **soap_package, ODR decode, char **charset)
262 if (!strcmp(hreq->method, "POST"))
264 const char *content_type = z_HTTP_header_lookup(hreq->headers,
267 (!yaz_strcmp_del("text/xml", content_type, "; ") ||
268 !yaz_strcmp_del("application/soap+xml", content_type, "; ") ||
269 !yaz_strcmp_del("text/plain", content_type, "; ")))
271 char *db = "Default";
272 const char *p0 = hreq->path, *p1;
275 static Z_SOAP_Handler soap_handlers[5] = {
277 { YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec },
278 { YAZ_XMLNS_SRU_v1_0, 0, (Z_SOAP_fun) yaz_srw_codec },
279 { YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec },
280 { YAZ_XMLNS_SRU_v2_mask, 0, (Z_SOAP_fun) yaz_srw_codec },
287 p1 = strchr(p0, '?');
289 p1 = p0 + strlen(p0);
291 db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);
293 ret = z_soap_codec(decode, soap_package,
294 &hreq->content_buf, &hreq->content_len,
296 if (ret == 0 && (*soap_package)->which == Z_SOAP_generic)
298 *srw_pdu = (Z_SRW_PDU*) (*soap_package)->u.generic->p;
299 yaz_srw_decodeauth(*srw_pdu, hreq, 0, 0, decode);
301 /* last entry in handlers - SRU 2.0 - is turned into
302 offset 0.. due to other pieces relying on it */
303 if ((*soap_package)->u.generic->no == 3)
304 (*soap_package)->u.generic->no = 0;
305 if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request &&
306 (*srw_pdu)->u.request->database == 0)
307 (*srw_pdu)->u.request->database = db;
309 if ((*srw_pdu)->which == Z_SRW_explain_request &&
310 (*srw_pdu)->u.explain_request->database == 0)
311 (*srw_pdu)->u.explain_request->database = db;
313 if ((*srw_pdu)->which == Z_SRW_scan_request &&
314 (*srw_pdu)->u.scan_request->database == 0)
315 (*srw_pdu)->u.scan_request->database = db;
317 if ((*srw_pdu)->which == Z_SRW_update_request &&
318 (*srw_pdu)->u.update_request->database == 0)
319 (*srw_pdu)->u.update_request->database = db;
330 static int yaz_sru_decode_integer(ODR odr, const char *pname,
331 const char *valstr, Odr_int **valp,
332 Z_SRW_diagnostic **diag, int *num_diag,
338 if (sscanf(valstr, "%d", &ival) != 1)
340 yaz_add_srw_diagnostic(odr, diag, num_diag,
341 YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
344 if (min_value >= 0 && ival < min_value)
346 yaz_add_srw_diagnostic(odr, diag, num_diag,
347 YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
350 *valp = odr_intdup(odr, ival);
356 http://www.loc.gov/z3950/agency/zing/srw/service.html
358 int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
359 Z_SOAP **soap_package, ODR decode, char **charset,
360 Z_SRW_diagnostic **diag, int *num_diag)
363 static Z_SOAP_Handler soap_handlers[2] = {
364 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
368 const char *content_type = z_HTTP_header_lookup(hreq->headers,
372 SRU GET: ignore content type.
373 SRU POST: we support "application/x-www-form-urlencoded";
374 not "multipart/form-data" .
376 if (!strcmp(hreq->method, "GET")
378 (!strcmp(hreq->method, "POST") && content_type &&
379 !yaz_strcmp_del("application/x-www-form-urlencoded",
380 content_type, "; ")))
382 char *db = "Default";
383 const char *p0 = hreq->path, *p1;
385 const char *operation = 0;
388 char *queryType = "cql";
392 char *stylesheet = 0;
393 char *scanClause = 0;
394 char *recordXPath = 0;
395 char *recordSchema = 0;
396 char *recordXMLEscaping = 0;
397 char *recordPacking = 0;
398 char *maximumRecords = 0;
399 char *startRecord = 0;
400 char *maximumTerms = 0;
401 char *responsePosition = 0;
402 const char *facetLimit = 0;
403 const char *facetStart = 0;
404 const char *facetSort = 0;
405 Z_SRW_extra_arg *extra_args = 0;
410 grab_charset(decode, content_type, charset);
411 if (charset && *charset == 0 && !strcmp(hreq->method, "GET"))
416 p1 = strchr(p0, '?');
418 p1 = p0 + strlen(p0);
420 db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);
421 if (!strcmp(hreq->method, "POST") && hreq->content_buf)
422 p1 = hreq->content_buf;
423 yaz_uri_to_array(p1, decode, &uri_name, &uri_val);
428 for (i = 0; uri_name[i]; i++)
430 char *n = uri_name[i];
431 char *v = uri_val[i];
432 if (!strcmp(n, "query"))
434 else if (!strcmp(n, "x-pquery"))
439 else if (!strcmp(n, "queryType"))
441 else if (!strcmp(n, "x-username"))
443 else if (!strcmp(n, "x-password"))
445 else if (!strcmp(n, "operation"))
447 else if (!strcmp(n, "stylesheet"))
449 else if (!strcmp(n, "sortKeys"))
451 else if (!strcmp(n, "recordXPath"))
453 else if (!strcmp(n, "recordSchema"))
455 else if (!strcmp(n, "recordPacking"))
457 else if (!strcmp(n, "recordXMLEscaping"))
458 recordXMLEscaping = v;
459 else if (!strcmp(n, "version"))
461 else if (!strcmp(n, "scanClause"))
463 else if (!strcmp(n, "x-pScanClause"))
468 else if (!strcmp(n, "maximumRecords"))
470 else if (!strcmp(n, "startRecord"))
472 else if (!strcmp(n, "maximumTerms"))
474 else if (!strcmp(n, "responsePosition"))
475 responsePosition = v;
476 else if (!strcmp(n, "facetLimit"))
478 else if (!strcmp(n, "facetStart"))
480 else if (!strcmp(n, "facetSort"))
482 else if (!strcmp(n, "extraRequestData"))
483 ; /* ignoring extraRequestData */
484 else if (n[0] == 'x' && n[1] == '-')
486 append_extra_arg(decode, &extra_args, n, v);
491 yaz_add_srw_diagnostic(decode, diag, num_diag,
492 YAZ_SRW_UNSUPP_PARAMETER, n);
499 operation = "searchRetrieve";
503 operation = "explain";
505 version = yaz_negotiate_sru_version(version);
508 { /* negotiation failed. */
509 yaz_add_srw_diagnostic(decode, diag, num_diag,
510 YAZ_SRW_UNSUPP_VERSION, "2.0");
516 yaz_add_srw_diagnostic(
517 decode, diag, num_diag,
518 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "operation");
519 operation = "explain";
521 if (strcmp(version, "2.0"))
523 if (recordXMLEscaping)
525 yaz_add_srw_diagnostic(decode, diag, num_diag,
526 YAZ_SRW_UNSUPP_PARAMETER,
527 "recordXMLEscaping");
530 recordXMLEscaping = recordPacking;
531 recordPacking = "packed";
533 if (!recordXMLEscaping)
534 recordXMLEscaping = "xml";
535 if (!strcmp(operation, "searchRetrieve"))
537 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
539 sr->srw_version = version;
540 sr->extra_args = extra_args;
542 yaz_srw_decodeauth(sr, hreq, username, password, decode);
544 sr->u.request->queryType = queryType;
545 sr->u.request->query = query;
548 yaz_add_srw_diagnostic(
549 decode, diag, num_diag,
550 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "query");
554 sr->u.request->sort_type = Z_SRW_sort_type_sort;
555 sr->u.request->sort.sortKeys = sortKeys;
557 sr->u.request->recordXPath = recordXPath;
558 sr->u.request->recordSchema = recordSchema;
559 sr->u.request->recordPacking = recordXMLEscaping;
560 sr->u.request->packing = recordPacking;
561 sr->u.request->stylesheet = stylesheet;
562 yaz_sru_facet_request(decode , &sr->u.request->facetList,
563 &facetLimit, &facetStart, &facetSort);
565 yaz_sru_decode_integer(decode, "maximumRecords", maximumRecords,
566 &sr->u.request->maximumRecords,
569 yaz_sru_decode_integer(decode, "startRecord", startRecord,
570 &sr->u.request->startRecord,
573 sr->u.request->database = db;
575 (*soap_package) = (Z_SOAP *)
576 odr_malloc(decode, sizeof(**soap_package));
577 (*soap_package)->which = Z_SOAP_generic;
579 (*soap_package)->u.generic = (Z_SOAP_Generic *)
580 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
582 (*soap_package)->u.generic->p = sr;
583 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
584 (*soap_package)->u.generic->no = 0;
586 (*soap_package)->ns = "SRU";
590 else if (!strcmp(operation, "explain"))
592 /* Transfer SRU explain parameters to common struct */
593 /* http://www.loc.gov/z3950/agency/zing/srw/explain.html */
594 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
596 sr->srw_version = version;
597 sr->extra_args = extra_args;
598 yaz_srw_decodeauth(sr, hreq, username, password, decode);
600 sr->u.explain_request->recordPacking = recordXMLEscaping;
601 sr->u.explain_request->packing = recordPacking;
602 sr->u.explain_request->database = db;
604 sr->u.explain_request->stylesheet = stylesheet;
606 (*soap_package) = (Z_SOAP *)
607 odr_malloc(decode, sizeof(**soap_package));
608 (*soap_package)->which = Z_SOAP_generic;
610 (*soap_package)->u.generic = (Z_SOAP_Generic *)
611 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
613 (*soap_package)->u.generic->p = sr;
614 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
615 (*soap_package)->u.generic->no = 0;
617 (*soap_package)->ns = "SRU";
621 else if (!strcmp(operation, "scan"))
623 /* Transfer SRU scan parameters to common struct */
624 /* http://www.loc.gov/z3950/agency/zing/srw/scan.html */
625 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_scan_request);
627 sr->srw_version = version;
628 sr->extra_args = extra_args;
630 yaz_srw_decodeauth(sr, hreq, username, password, decode);
632 sr->u.scan_request->queryType = queryType;
633 sr->u.scan_request->scanClause = scanClause;
636 yaz_add_srw_diagnostic(
637 decode, diag, num_diag,
638 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "scanClause");
639 sr->u.scan_request->database = db;
641 yaz_sru_decode_integer(decode, "maximumTerms",
643 &sr->u.scan_request->maximumTerms,
646 yaz_sru_decode_integer(decode, "responsePosition",
648 &sr->u.scan_request->responsePosition,
651 sr->u.scan_request->stylesheet = stylesheet;
653 (*soap_package) = (Z_SOAP *)
654 odr_malloc(decode, sizeof(**soap_package));
655 (*soap_package)->which = Z_SOAP_generic;
657 (*soap_package)->u.generic = (Z_SOAP_Generic *)
658 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
660 (*soap_package)->u.generic->p = sr;
661 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
662 (*soap_package)->u.generic->no = 0;
664 (*soap_package)->ns = "SRU";
670 /* unsupported operation ... */
671 /* Act as if we received a explain request and throw diagnostic. */
673 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
675 sr->srw_version = version;
677 sr->u.explain_request->recordPacking = recordPacking;
678 sr->u.explain_request->database = db;
680 sr->u.explain_request->stylesheet = stylesheet;
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";
695 yaz_add_srw_diagnostic(decode, diag, num_diag,
696 YAZ_SRW_UNSUPP_OPERATION, operation);
706 Z_SRW_extra_record *yaz_srw_get_extra_record(ODR o)
708 Z_SRW_extra_record *res = (Z_SRW_extra_record *)
709 odr_malloc(o, sizeof(*res));
711 res->extraRecordData_buf = 0;
712 res->extraRecordData_len = 0;
713 res->recordIdentifier = 0;
718 Z_SRW_record *yaz_srw_get_records(ODR o, int n)
720 Z_SRW_record *res = (Z_SRW_record *) odr_malloc(o, n * sizeof(*res));
723 for (i = 0; i<n; i++)
725 res[i].recordSchema = 0;
726 res[i].recordPacking = Z_SRW_recordPacking_string;
727 res[i].recordData_buf = 0;
728 res[i].recordData_len = 0;
729 res[i].recordPosition = 0;
734 Z_SRW_record *yaz_srw_get_record(ODR o)
736 return yaz_srw_get_records(o, 1);
739 static Z_SRW_PDU *yaz_srw_get_core_ver(ODR o, const char *version)
741 Z_SRW_PDU *p = (Z_SRW_PDU *) odr_malloc(o, sizeof(*p));
742 p->srw_version = odr_strdup(o, version);
746 p->extraResponseData_buf = 0;
747 p->extraResponseData_len = 0;
751 Z_SRW_PDU *yaz_srw_get_core_v_2_0(ODR o)
753 return yaz_srw_get_core_ver(o, "2.0");
756 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
758 return yaz_srw_get_pdu(o, which, "2.0");
761 /* http://docs.oasis-open.org/search-ws/searchRetrieve/v1.0/os/schemas/sruResponse.xsd */
762 Z_SRW_PDU *yaz_srw_get_pdu_e(ODR o, int which, Z_SRW_PDU *req)
764 int version2 = !req->srw_version || strcmp(req->srw_version, "2.") > 0;
765 Z_SRW_PDU *res = yaz_srw_get_pdu(o, which, req->srw_version);
766 Z_SRW_extra_arg **l = &res->extra_args, *ea;
767 l = append_extra_arg(o, l, "version", req->srw_version);
768 if (req->which == Z_SRW_searchRetrieve_request &&
769 which == Z_SRW_searchRetrieve_response)
771 if (req->u.request->queryType &&
772 strcmp(req->u.request->queryType, "cql"))
773 l = append_extra_arg(o, l, "queryType", req->u.request->queryType);
774 l = append_extra_arg(o, l, "query", req->u.request->query);
775 l = append_extra_arg_int(o, l, "startRecord",
776 req->u.request->startRecord);
777 l = append_extra_arg_int(o, l, "maximumRecords",
778 req->u.request->maximumRecords);
781 l = append_extra_arg(o, l, "recordXMLEscaping",
782 req->u.request->recordPacking);
783 l = append_extra_arg(o, l, "recordPacking",
784 req->u.request->packing);
787 l = append_extra_arg(o, l, "recordPacking",
788 req->u.request->recordPacking);
789 l = append_extra_arg(o, l, "recordSchema",
790 req->u.request->recordSchema);
791 if (req->u.request->sort_type == Z_SRW_sort_type_sort)
792 l = append_extra_arg(o, l, "sortKeys",
793 req->u.request->sort.sortKeys);
794 l = append_extra_arg(o, l, "stylesheet", req->u.request->stylesheet);
796 if (req->which == Z_SRW_explain_request &&
797 which == Z_SRW_explain_response)
801 l = append_extra_arg(o, l, "recordXMLEscaping",
802 req->u.explain_request->recordPacking);
803 l = append_extra_arg(o, l, "recordPacking",
804 req->u.explain_request->packing);
807 l = append_extra_arg(o, l, "recordPacking",
808 req->u.explain_request->recordPacking);
809 l = append_extra_arg(o, l, "stylesheet",
810 req->u.explain_request->stylesheet);
812 for (ea = req->extra_args; ea; ea = ea->next)
813 l = append_extra_arg(o, l, ea->name, ea->value);
817 Z_SRW_PDU *yaz_srw_get_pdu(ODR o, int which, const char *version)
819 Z_SRW_PDU *sr = yaz_srw_get_core_ver(o, version);
824 case Z_SRW_searchRetrieve_request:
825 sr->u.request = (Z_SRW_searchRetrieveRequest *)
826 odr_malloc(o, sizeof(*sr->u.request));
827 sr->u.request->queryType = "cql";
828 sr->u.request->query = 0;
829 sr->u.request->sort_type = Z_SRW_sort_type_none;
830 sr->u.request->sort.none = 0;
831 sr->u.request->startRecord = 0;
832 sr->u.request->maximumRecords = 0;
833 sr->u.request->recordSchema = 0;
834 sr->u.request->recordPacking = 0;
835 sr->u.request->packing = 0;
836 sr->u.request->recordXPath = 0;
837 sr->u.request->database = 0;
838 sr->u.request->resultSetTTL = 0;
839 sr->u.request->stylesheet = 0;
840 sr->u.request->facetList = 0;
842 case Z_SRW_searchRetrieve_response:
843 sr->u.response = (Z_SRW_searchRetrieveResponse *)
844 odr_malloc(o, sizeof(*sr->u.response));
845 sr->u.response->numberOfRecords = 0;
846 sr->u.response->resultCountPrecision = 0;
847 sr->u.response->resultSetId = 0;
848 sr->u.response->resultSetIdleTime = 0;
849 sr->u.response->records = 0;
850 sr->u.response->num_records = 0;
851 sr->u.response->diagnostics = 0;
852 sr->u.response->num_diagnostics = 0;
853 sr->u.response->nextRecordPosition = 0;
854 sr->u.response->extra_records = 0;
855 sr->u.response->facetList = 0;
856 sr->u.response->suggestions = 0;
858 case Z_SRW_explain_request:
859 sr->u.explain_request = (Z_SRW_explainRequest *)
860 odr_malloc(o, sizeof(*sr->u.explain_request));
861 sr->u.explain_request->recordPacking = 0;
862 sr->u.explain_request->packing = 0;
863 sr->u.explain_request->database = 0;
864 sr->u.explain_request->stylesheet = 0;
866 case Z_SRW_explain_response:
867 sr->u.explain_response = (Z_SRW_explainResponse *)
868 odr_malloc(o, sizeof(*sr->u.explain_response));
869 sr->u.explain_response->record.recordData_buf = 0;
870 sr->u.explain_response->record.recordData_len = 0;
871 sr->u.explain_response->record.recordSchema = 0;
872 sr->u.explain_response->record.recordPosition = 0;
873 sr->u.explain_response->record.recordPacking =
874 Z_SRW_recordPacking_string;
875 sr->u.explain_response->diagnostics = 0;
876 sr->u.explain_response->num_diagnostics = 0;
877 sr->u.explain_response->extra_record = 0;
879 case Z_SRW_scan_request:
880 sr->u.scan_request = (Z_SRW_scanRequest *)
881 odr_malloc(o, sizeof(*sr->u.scan_request));
882 sr->u.scan_request->database = 0;
883 sr->u.scan_request->stylesheet = 0;
884 sr->u.scan_request->maximumTerms = 0;
885 sr->u.scan_request->responsePosition = 0;
886 sr->u.scan_request->queryType = "cql";
887 sr->u.scan_request->scanClause = 0;
889 case Z_SRW_scan_response:
890 sr->u.scan_response = (Z_SRW_scanResponse *)
891 odr_malloc(o, sizeof(*sr->u.scan_response));
892 sr->u.scan_response->terms = 0;
893 sr->u.scan_response->num_terms = 0;
894 sr->u.scan_response->diagnostics = 0;
895 sr->u.scan_response->num_diagnostics = 0;
897 case Z_SRW_update_request:
898 sr->u.update_request = (Z_SRW_updateRequest *)
899 odr_malloc(o, sizeof(*sr->u.update_request));
900 sr->u.update_request->database = 0;
901 sr->u.update_request->stylesheet = 0;
902 sr->u.update_request->record = 0;
903 sr->u.update_request->recordId = 0;
904 sr->u.update_request->recordVersions = 0;
905 sr->u.update_request->num_recordVersions = 0;
906 sr->u.update_request->extra_record = 0;
907 sr->u.update_request->extraRequestData_buf = 0;
908 sr->u.update_request->extraRequestData_len = 0;
909 sr->u.request->database = 0;
911 case Z_SRW_update_response:
912 sr->u.update_response = (Z_SRW_updateResponse *)
913 odr_malloc(o, sizeof(*sr->u.update_response));
914 sr->u.update_response->operationStatus = 0;
915 sr->u.update_response->recordId = 0;
916 sr->u.update_response->recordVersions = 0;
917 sr->u.update_response->num_recordVersions = 0;
918 sr->u.update_response->record = 0;
919 sr->u.update_response->extra_record = 0;
920 sr->u.update_response->extraResponseData_buf = 0;
921 sr->u.update_response->extraResponseData_len = 0;
922 sr->u.update_response->diagnostics = 0;
923 sr->u.update_response->num_diagnostics = 0;
928 void yaz_add_name_value_int(ODR o, char **name, char **value, int *i,
929 char *a_name, Odr_int *val)
934 value[*i] = (char *) odr_malloc(o, 40);
935 sprintf(value[*i], ODR_INT_PRINTF, *val);
940 void yaz_add_name_value_str(ODR o, char **name, char **value, int *i,
941 char *a_name, char *val)
951 static int yaz_get_sru_parms(const Z_SRW_PDU *srw_pdu, ODR encode,
952 char **name, char **value, int max_names)
954 int version2 = strcmp(srw_pdu->srw_version, "2.") > 0;
957 yaz_add_name_value_str(encode, name, value, &i, "version",
958 srw_pdu->srw_version);
959 name[i] = "operation";
960 switch (srw_pdu->which)
962 case Z_SRW_searchRetrieve_request:
963 value[i++] = "searchRetrieve";
964 queryType = srw_pdu->u.request->queryType;
967 if (queryType && strcmp(queryType, "cql"))
968 yaz_add_name_value_str(encode, name, value, &i, "queryType",
970 yaz_add_name_value_str(encode, name, value, &i, "query",
971 srw_pdu->u.request->query);
975 if (!strcmp(queryType, "cql"))
977 yaz_add_name_value_str(encode, name, value, &i, "query",
978 srw_pdu->u.request->query);
980 else if (!strcmp(queryType, "pqf"))
982 yaz_add_name_value_str(encode, name, value, &i, "x-pquery",
983 srw_pdu->u.request->query);
985 else if (!strcmp(queryType, "xcql"))
987 yaz_add_name_value_str(encode, name, value, &i, "x-cql",
988 srw_pdu->u.request->query);
991 switch (srw_pdu->u.request->sort_type)
993 case Z_SRW_sort_type_none:
995 case Z_SRW_sort_type_sort:
996 yaz_add_name_value_str(encode, name, value, &i, "sortKeys",
997 srw_pdu->u.request->sort.sortKeys);
1000 yaz_add_name_value_int(encode, name, value, &i, "startRecord",
1001 srw_pdu->u.request->startRecord);
1002 yaz_add_name_value_int(encode, name, value, &i, "maximumRecords",
1003 srw_pdu->u.request->maximumRecords);
1004 yaz_add_name_value_str(encode, name, value, &i, "recordSchema",
1005 srw_pdu->u.request->recordSchema);
1008 yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping",
1009 srw_pdu->u.request->recordPacking);
1010 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
1011 srw_pdu->u.request->packing);
1014 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
1015 srw_pdu->u.request->recordPacking);
1016 yaz_add_name_value_str(encode, name, value, &i, "recordXPath",
1017 srw_pdu->u.request->recordXPath);
1018 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
1019 srw_pdu->u.request->stylesheet);
1020 yaz_add_name_value_int(encode, name, value, &i, "resultSetTTL",
1021 srw_pdu->u.request->resultSetTTL);
1023 const char *facetLimit = 0;
1024 const char *facetStart = 0;
1025 const char *facetSort = 0;
1026 yaz_sru_facet_request(encode, &srw_pdu->u.request->facetList,
1027 &facetLimit, &facetStart, &facetSort);
1028 yaz_add_name_value_str(encode, name, value, &i, "facetLimit",
1029 (char *) facetLimit);
1030 yaz_add_name_value_str(encode, name, value, &i, "facetStart",
1031 (char *) facetStart);
1032 yaz_add_name_value_str(encode, name, value, &i, "facetSort",
1033 (char *) facetSort);
1036 case Z_SRW_explain_request:
1037 value[i++] = "explain";
1041 yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping",
1042 srw_pdu->u.explain_request->recordPacking);
1043 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
1044 srw_pdu->u.explain_request->packing);
1047 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
1048 srw_pdu->u.explain_request->recordPacking);
1049 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
1050 srw_pdu->u.explain_request->stylesheet);
1052 case Z_SRW_scan_request:
1053 value[i++] = "scan";
1054 queryType = srw_pdu->u.scan_request->queryType;
1057 if (queryType && strcmp(queryType, "cql"))
1058 yaz_add_name_value_str(encode, name, value, &i, "queryType",
1060 yaz_add_name_value_str(encode, name, value, &i, "scanClause",
1061 srw_pdu->u.scan_request->scanClause);
1065 if (!queryType || !strcmp(queryType, "cql"))
1066 yaz_add_name_value_str(encode, name, value, &i, "scanClause",
1067 srw_pdu->u.scan_request->scanClause);
1068 else if (!strcmp(queryType, "pqf"))
1069 yaz_add_name_value_str(encode, name, value, &i, "x-pScanClause",
1070 srw_pdu->u.scan_request->scanClause);
1071 else if (!strcmp(queryType, "xcql"))
1072 yaz_add_name_value_str(encode, name, value, &i,
1074 srw_pdu->u.scan_request->scanClause);
1076 yaz_add_name_value_int(encode, name, value, &i, "responsePosition",
1077 srw_pdu->u.scan_request->responsePosition);
1078 yaz_add_name_value_int(encode, name, value, &i, "maximumTerms",
1079 srw_pdu->u.scan_request->maximumTerms);
1080 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
1081 srw_pdu->u.scan_request->stylesheet);
1083 case Z_SRW_update_request:
1084 value[i++] = "update";
1089 if (srw_pdu->extra_args)
1091 Z_SRW_extra_arg *ea = srw_pdu->extra_args;
1092 for (; ea && i < max_names-1; ea = ea->next)
1095 value[i] = ea->value;
1104 int yaz_sru_get_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1105 ODR encode, const char *charset)
1107 char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */
1112 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1113 srw_pdu->username, srw_pdu->password);
1114 if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS))
1116 yaz_array_to_uri(&uri_args, encode, name, value);
1118 hreq->method = "GET";
1120 cp = strchr(hreq->path, '#');
1125 odr_malloc(encode, strlen(hreq->path) + strlen(uri_args) + 4);
1127 sprintf(path, "%s%c%s", hreq->path, strchr(hreq->path, '?') ? '&' : '?',
1131 z_HTTP_header_add_content_type(encode, &hreq->headers,
1132 "text/xml", charset);
1136 int yaz_sru_post_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1137 ODR encode, const char *charset)
1139 char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */
1142 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1143 srw_pdu->username, srw_pdu->password);
1144 if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS))
1147 yaz_array_to_uri(&uri_args, encode, name, value);
1149 hreq->method = "POST";
1151 hreq->content_buf = uri_args;
1152 hreq->content_len = strlen(uri_args);
1154 z_HTTP_header_add_content_type(encode, &hreq->headers,
1155 "application/x-www-form-urlencoded",
1160 int yaz_sru_soap_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1161 ODR odr, const char *charset)
1163 Z_SOAP_Handler handlers[3] = {
1165 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
1166 {YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec},
1170 Z_SOAP *p = (Z_SOAP*) odr_malloc(odr, sizeof(*p));
1172 z_HTTP_header_add_basic_auth(odr, &hreq->headers,
1173 srw_pdu->username, srw_pdu->password);
1174 z_HTTP_header_add_content_type(odr,
1176 "text/xml", 0 /* no charset in MIME */);
1178 z_HTTP_header_add(odr, &hreq->headers,
1179 "SOAPAction", "\"\"");
1180 p->which = Z_SOAP_generic;
1181 p->u.generic = (Z_SOAP_Generic *) odr_malloc(odr, sizeof(*p->u.generic));
1182 p->u.generic->no = 0;
1183 p->u.generic->ns = 0;
1184 p->u.generic->p = srw_pdu;
1185 p->ns = "http://schemas.xmlsoap.org/soap/envelope/";
1188 if (srw_pdu->which == Z_SRW_update_request ||
1189 srw_pdu->which == Z_SRW_update_response)
1190 p->u.generic->no = 1; /* second handler */
1192 return z_soap_codec_enc(odr, &p,
1194 &hreq->content_len, handlers,
1198 Z_SRW_recordVersion *yaz_srw_get_record_versions(ODR odr, int num)
1200 Z_SRW_recordVersion *ver
1201 = (Z_SRW_recordVersion *) odr_malloc(odr,num * sizeof(*ver));
1203 for (i = 0; i < num; ++i)
1205 ver[i].versionType = 0;
1206 ver[i].versionValue = 0;
1211 const char *yaz_srw_pack_to_str(int pack)
1215 case Z_SRW_recordPacking_string:
1217 case Z_SRW_recordPacking_XML:
1219 case Z_SRW_recordPacking_URL:
1225 int yaz_srw_str_to_pack(const char *str)
1227 if (!yaz_matchstr(str, "string"))
1228 return Z_SRW_recordPacking_string;
1229 if (!yaz_matchstr(str, "xml"))
1230 return Z_SRW_recordPacking_XML;
1231 if (!yaz_matchstr(str, "url"))
1232 return Z_SRW_recordPacking_URL;
1236 void yaz_encode_sru_extra(Z_SRW_PDU *sr, ODR odr, const char *extra_args)
1242 Z_SRW_extra_arg **ea = &sr->extra_args;
1243 yaz_uri_to_array(extra_args, odr, &name, &val);
1247 ea = append_extra_arg(odr, ea, *name, *val);
1258 * c-file-style: "Stroustrup"
1259 * indent-tabs-mode: nil
1261 * vim: shiftwidth=4 tabstop=8 expandtab