1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2013 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 char *yaz_decode_sru_dbpath_odr(ODR n, const char *uri, size_t len)
25 return odr_strdupn(n, uri, len);
28 void yaz_encode_sru_dbpath_buf(char *dst, const char *db)
35 char *yaz_encode_sru_dbpath_odr(ODR out, const char *db)
37 char *dst = odr_malloc(out, 3 * strlen(db) + 2);
38 yaz_encode_sru_dbpath_buf(dst, db);
42 Z_AttributeList *yaz_use_attribute_create(ODR o, const char *name)
44 Z_AttributeList *attributes= (Z_AttributeList *)
45 odr_malloc(o, sizeof(*attributes));
46 Z_AttributeElement ** elements;
47 attributes->num_attributes = 1;
48 elements = (Z_AttributeElement**)
49 odr_malloc(o, attributes->num_attributes * sizeof(*elements));
50 elements[0] = (Z_AttributeElement*) odr_malloc(o,sizeof(**elements));
51 elements[0]->attributeType = odr_intdup(o, 1);
52 elements[0]->attributeSet = odr_nullval();
53 elements[0]->which = Z_AttributeValue_complex;
54 elements[0]->value.complex = (Z_ComplexAttribute *)
55 odr_malloc(o, sizeof(Z_ComplexAttribute));
56 elements[0]->value.complex->num_list = 1;
57 elements[0]->value.complex->list = (Z_StringOrNumeric **)
58 odr_malloc(o, 1 * sizeof(Z_StringOrNumeric *));
59 elements[0]->value.complex->list[0] = (Z_StringOrNumeric *)
60 odr_malloc(o, sizeof(Z_StringOrNumeric));
61 elements[0]->value.complex->list[0]->which = Z_StringOrNumeric_string;
62 elements[0]->value.complex->list[0]->u.string = odr_strdup(o, name);
63 elements[0]->value.complex->semanticAction = 0;
64 elements[0]->value.complex->num_semanticAction = 0;
65 attributes->attributes = elements;
70 const char *yaz_element_attribute_value_get(xmlNodePtr ptr,
71 const char *node_name,
72 const char *attribute_name)
74 struct _xmlAttr *attr;
75 // check if the node name matches
76 if (strcmp((const char*) ptr->name, node_name))
78 // check if the attribute name and return the value
79 for (attr = ptr->properties; attr; attr = attr->next)
80 if (attr->children && attr->children->type == XML_TEXT_NODE)
82 if (!strcmp((const char *) attr->name, attribute_name))
83 return (const char *) attr->children->content;
89 int yaz_srw_check_content_type(Z_HTTP_Response *hres)
91 const char *content_type = z_HTTP_header_lookup(hres->headers,
95 if (!yaz_strcmp_del("text/xml", content_type, "; "))
97 if (!yaz_strcmp_del("application/xml", content_type, "; "))
104 * Look for authentication tokens in HTTP Basic parameters or in x-username/x-password
105 * parameters. Added by SH.
107 static void yaz_srw_decodeauth(Z_SRW_PDU *sr, Z_HTTP_Request *hreq,
108 char *username, char *password, ODR decode)
110 const char *basic = z_HTTP_header_lookup(hreq->headers, "Authorization");
113 sr->username = username;
115 sr->password = password;
121 char ubuf[256] = "", pbuf[256] = "", *p;
122 if (strncmp(basic, "Basic ", 6))
126 if (!len || len > 256)
128 yaz_base64decode(basic, out);
129 /* Format of out should be username:password at this point */
131 if ((p = strchr(ubuf, ':')))
138 sr->username = odr_strdup(decode, ubuf);
140 sr->password = odr_strdup(decode, pbuf);
144 void yaz_mk_srw_diagnostic(ODR o, Z_SRW_diagnostic *d,
145 const char *uri, const char *message,
148 d->uri = odr_strdup(o, uri);
150 d->message = odr_strdup(o, message);
154 d->details = odr_strdup(o, details);
159 void yaz_mk_std_diagnostic(ODR o, Z_SRW_diagnostic *d,
160 int code, const char *details)
164 sprintf(uri, "info:srw/diagnostic/1/%d", code);
165 yaz_mk_srw_diagnostic(o, d, uri, 0, details);
168 void yaz_add_srw_diagnostic_uri(ODR o, Z_SRW_diagnostic **d,
169 int *num, const char *uri,
170 const char *message, const char *details)
172 Z_SRW_diagnostic *d_new;
173 d_new = (Z_SRW_diagnostic *) odr_malloc(o, (*num + 1)* sizeof(**d));
175 memcpy(d_new, *d, *num *sizeof(**d));
178 yaz_mk_srw_diagnostic(o, *d + *num, uri, message, details);
182 void yaz_add_srw_diagnostic(ODR o, Z_SRW_diagnostic **d,
183 int *num, int code, const char *addinfo)
187 sprintf(uri, "info:srw/diagnostic/1/%d", code);
188 yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
192 void yaz_add_sru_update_diagnostic(ODR o, Z_SRW_diagnostic **d,
193 int *num, int code, const char *addinfo)
197 sprintf(uri, "info:srw/diagnostic/12/%d", code);
198 yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
202 void yaz_mk_sru_surrogate(ODR o, Z_SRW_record *record, int pos,
203 int code, const char *details)
205 const char *message = yaz_diag_srw_str(code);
208 len += strlen(message);
210 len += strlen(details);
212 record->recordData_buf = (char *) odr_malloc(o, len);
214 sprintf(record->recordData_buf, "<diagnostic "
215 "xmlns=\"http://www.loc.gov/zing/srw/diagnostic/\">\n"
216 " <uri>info:srw/diagnostic/1/%d</uri>\n", code);
218 sprintf(record->recordData_buf + strlen(record->recordData_buf),
219 " <details>%s</details>\n", details);
221 sprintf(record->recordData_buf + strlen(record->recordData_buf),
222 " <message>%s</message>\n", message);
223 sprintf(record->recordData_buf + strlen(record->recordData_buf),
225 record->recordData_len = strlen(record->recordData_buf);
226 record->recordPosition = odr_intdup(o, pos);
227 record->recordSchema = "info:srw/schema/1/diagnostics-v1.1";
230 static void grab_charset(ODR o, const char *content_type, char **charset)
234 const char *charset_p = 0;
235 if (content_type && (charset_p = strstr(content_type, "; charset=")))
239 charset_p += 10; /* skip ; charset= */
240 if (charset_p[i] == '"' || charset_p[i] == '\'')
241 sep = charset_p[i++];
242 *charset = odr_strdup(o, charset_p);
243 while (charset_p[i] && charset_p[i] != sep)
245 if (charset_p[i] == '\\' && charset_p[i+1])
247 (*charset)[j++] = charset_p[i++];
249 (*charset)[j] = '\0';
254 int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
255 Z_SOAP **soap_package, ODR decode, char **charset)
257 if (!strcmp(hreq->method, "POST"))
259 const char *content_type = z_HTTP_header_lookup(hreq->headers,
262 (!yaz_strcmp_del("text/xml", content_type, "; ") ||
263 !yaz_strcmp_del("application/soap+xml", content_type, "; ") ||
264 !yaz_strcmp_del("text/plain", content_type, "; ")))
266 char *db = "Default";
267 const char *p0 = hreq->path, *p1;
270 static Z_SOAP_Handler soap_handlers[5] = {
272 { YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec },
273 { YAZ_XMLNS_SRU_v1_0, 0, (Z_SOAP_fun) yaz_srw_codec },
274 { YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec },
275 { YAZ_XMLNS_SRU_v2_mask, 0, (Z_SOAP_fun) yaz_srw_codec },
282 p1 = strchr(p0, '?');
284 p1 = p0 + strlen(p0);
286 db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);
288 ret = z_soap_codec(decode, soap_package,
289 &hreq->content_buf, &hreq->content_len,
291 if (ret == 0 && (*soap_package)->which == Z_SOAP_generic)
293 *srw_pdu = (Z_SRW_PDU*) (*soap_package)->u.generic->p;
294 yaz_srw_decodeauth(*srw_pdu, hreq, 0, 0, decode);
296 /* last entry in handlers - SRU 2.0 - is turned into
297 offset 0.. due to other pieces relying on it */
298 if ((*soap_package)->u.generic->no == 3)
299 (*soap_package)->u.generic->no = 0;
300 if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request &&
301 (*srw_pdu)->u.request->database == 0)
302 (*srw_pdu)->u.request->database = db;
304 if ((*srw_pdu)->which == Z_SRW_explain_request &&
305 (*srw_pdu)->u.explain_request->database == 0)
306 (*srw_pdu)->u.explain_request->database = db;
308 if ((*srw_pdu)->which == Z_SRW_scan_request &&
309 (*srw_pdu)->u.scan_request->database == 0)
310 (*srw_pdu)->u.scan_request->database = db;
312 if ((*srw_pdu)->which == Z_SRW_update_request &&
313 (*srw_pdu)->u.update_request->database == 0)
314 (*srw_pdu)->u.update_request->database = db;
325 static int yaz_sru_decode_integer(ODR odr, const char *pname,
326 const char *valstr, Odr_int **valp,
327 Z_SRW_diagnostic **diag, int *num_diag,
333 if (sscanf(valstr, "%d", &ival) != 1)
335 yaz_add_srw_diagnostic(odr, diag, num_diag,
336 YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
339 if (min_value >= 0 && ival < min_value)
341 yaz_add_srw_diagnostic(odr, diag, num_diag,
342 YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
345 *valp = odr_intdup(odr, ival);
351 http://www.loc.gov/z3950/agency/zing/srw/service.html
353 int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
354 Z_SOAP **soap_package, ODR decode, char **charset,
355 Z_SRW_diagnostic **diag, int *num_diag)
358 static Z_SOAP_Handler soap_handlers[2] = {
359 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
363 const char *content_type = z_HTTP_header_lookup(hreq->headers,
367 SRU GET: ignore content type.
368 SRU POST: we support "application/x-www-form-urlencoded";
369 not "multipart/form-data" .
371 if (!strcmp(hreq->method, "GET")
373 (!strcmp(hreq->method, "POST") && content_type &&
374 !yaz_strcmp_del("application/x-www-form-urlencoded",
375 content_type, "; ")))
377 char *db = "Default";
378 const char *p0 = hreq->path, *p1;
380 const char *operation = 0;
383 char *queryType = "cql";
387 char *stylesheet = 0;
388 char *scanClause = 0;
389 char *recordXPath = 0;
390 char *recordSchema = 0;
391 char *recordXMLEscaping = 0;
392 char *recordPacking = 0;
393 char *maximumRecords = 0;
394 char *startRecord = 0;
395 char *maximumTerms = 0;
396 char *responsePosition = 0;
397 const char *facetLimit = 0;
398 const char *facetStart = 0;
399 const char *facetSort = 0;
400 Z_SRW_extra_arg *extra_args = 0;
405 grab_charset(decode, content_type, charset);
406 if (charset && *charset == 0 && !strcmp(hreq->method, "GET"))
411 p1 = strchr(p0, '?');
413 p1 = p0 + strlen(p0);
415 db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);
416 if (!strcmp(hreq->method, "POST"))
417 p1 = hreq->content_buf;
418 yaz_uri_to_array(p1, decode, &uri_name, &uri_val);
423 for (i = 0; uri_name[i]; i++)
425 char *n = uri_name[i];
426 char *v = uri_val[i];
427 if (!strcmp(n, "query"))
429 else if (!strcmp(n, "x-pquery"))
434 else if (!strcmp(n, "queryType"))
436 else if (!strcmp(n, "x-username"))
438 else if (!strcmp(n, "x-password"))
440 else if (!strcmp(n, "operation"))
442 else if (!strcmp(n, "stylesheet"))
444 else if (!strcmp(n, "sortKeys"))
446 else if (!strcmp(n, "recordXPath"))
448 else if (!strcmp(n, "recordSchema"))
450 else if (!strcmp(n, "recordPacking"))
452 else if (!strcmp(n, "recordXMLEscaping"))
453 recordXMLEscaping = v;
454 else if (!strcmp(n, "version"))
456 else if (!strcmp(n, "scanClause"))
458 else if (!strcmp(n, "x-pScanClause"))
463 else if (!strcmp(n, "maximumRecords"))
465 else if (!strcmp(n, "startRecord"))
467 else if (!strcmp(n, "maximumTerms"))
469 else if (!strcmp(n, "responsePosition"))
470 responsePosition = v;
471 else if (!strcmp(n, "facetLimit"))
473 else if (!strcmp(n, "facetStart"))
475 else if (!strcmp(n, "facetSort"))
477 else if (!strcmp(n, "extraRequestData"))
478 ; /* ignoring extraRequestData */
479 else if (n[0] == 'x' && n[1] == '-')
481 Z_SRW_extra_arg **l = &extra_args;
484 *l = (Z_SRW_extra_arg *) odr_malloc(decode, sizeof(**l));
485 (*l)->name = odr_strdup(decode, n);
486 (*l)->value = odr_strdup(decode, v);
492 yaz_add_srw_diagnostic(decode, diag, num_diag,
493 YAZ_SRW_UNSUPP_PARAMETER, n);
500 operation = "searchRetrieve";
504 version = yaz_negotiate_sru_version(version);
507 { /* negotiation failed. */
508 yaz_add_srw_diagnostic(decode, diag, num_diag,
509 YAZ_SRW_UNSUPP_VERSION, "2.0");
515 yaz_add_srw_diagnostic(
516 decode, diag, num_diag,
517 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "operation");
518 operation = "explain";
520 if (strcmp(version, "2.0"))
522 if (recordXMLEscaping)
524 yaz_add_srw_diagnostic(decode, diag, num_diag,
525 YAZ_SRW_UNSUPP_PARAMETER,
526 "recordXMLEscaping");
529 recordXMLEscaping = recordPacking;
530 recordPacking = "packed";
532 if (!recordXMLEscaping)
533 recordXMLEscaping = "xml";
534 if (!strcmp(operation, "searchRetrieve"))
536 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
538 sr->srw_version = version;
539 sr->extra_args = extra_args;
541 yaz_srw_decodeauth(sr, hreq, username, password, decode);
543 sr->u.request->queryType = queryType;
544 sr->u.request->query = query;
547 yaz_add_srw_diagnostic(
548 decode, diag, num_diag,
549 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "query");
553 sr->u.request->sort_type = Z_SRW_sort_type_sort;
554 sr->u.request->sort.sortKeys = sortKeys;
556 sr->u.request->recordXPath = recordXPath;
557 sr->u.request->recordSchema = recordSchema;
558 sr->u.request->recordPacking = recordXMLEscaping;
559 sr->u.request->packing = recordPacking;
560 sr->u.request->stylesheet = stylesheet;
561 yaz_sru_facet_request(decode , &sr->u.request->facetList,
562 &facetLimit, &facetStart, &facetSort);
564 yaz_sru_decode_integer(decode, "maximumRecords", maximumRecords,
565 &sr->u.request->maximumRecords,
568 yaz_sru_decode_integer(decode, "startRecord", startRecord,
569 &sr->u.request->startRecord,
572 sr->u.request->database = db;
574 (*soap_package) = (Z_SOAP *)
575 odr_malloc(decode, sizeof(**soap_package));
576 (*soap_package)->which = Z_SOAP_generic;
578 (*soap_package)->u.generic = (Z_SOAP_Generic *)
579 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
581 (*soap_package)->u.generic->p = sr;
582 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
583 (*soap_package)->u.generic->no = 0;
585 (*soap_package)->ns = "SRU";
589 else if (!strcmp(operation, "explain"))
591 /* Transfer SRU explain parameters to common struct */
592 /* http://www.loc.gov/z3950/agency/zing/srw/explain.html */
593 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
595 sr->srw_version = version;
596 sr->extra_args = extra_args;
597 yaz_srw_decodeauth(sr, hreq, username, password, decode);
599 sr->u.explain_request->recordPacking = recordXMLEscaping;
600 sr->u.explain_request->packing = recordPacking;
601 sr->u.explain_request->database = db;
603 sr->u.explain_request->stylesheet = stylesheet;
605 (*soap_package) = (Z_SOAP *)
606 odr_malloc(decode, sizeof(**soap_package));
607 (*soap_package)->which = Z_SOAP_generic;
609 (*soap_package)->u.generic = (Z_SOAP_Generic *)
610 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
612 (*soap_package)->u.generic->p = sr;
613 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
614 (*soap_package)->u.generic->no = 0;
616 (*soap_package)->ns = "SRU";
620 else if (!strcmp(operation, "scan"))
622 /* Transfer SRU scan parameters to common struct */
623 /* http://www.loc.gov/z3950/agency/zing/srw/scan.html */
624 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_scan_request);
626 sr->srw_version = version;
627 sr->extra_args = extra_args;
629 yaz_srw_decodeauth(sr, hreq, username, password, decode);
631 sr->u.scan_request->queryType = queryType;
632 sr->u.scan_request->scanClause = scanClause;
635 yaz_add_srw_diagnostic(
636 decode, diag, num_diag,
637 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "scanClause");
638 sr->u.scan_request->database = db;
640 yaz_sru_decode_integer(decode, "maximumTerms",
642 &sr->u.scan_request->maximumTerms,
645 yaz_sru_decode_integer(decode, "responsePosition",
647 &sr->u.scan_request->responsePosition,
650 sr->u.scan_request->stylesheet = stylesheet;
652 (*soap_package) = (Z_SOAP *)
653 odr_malloc(decode, sizeof(**soap_package));
654 (*soap_package)->which = Z_SOAP_generic;
656 (*soap_package)->u.generic = (Z_SOAP_Generic *)
657 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
659 (*soap_package)->u.generic->p = sr;
660 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
661 (*soap_package)->u.generic->no = 0;
663 (*soap_package)->ns = "SRU";
669 /* unsupported operation ... */
670 /* Act as if we received a explain request and throw diagnostic. */
672 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
674 sr->srw_version = version;
676 sr->u.explain_request->recordPacking = recordPacking;
677 sr->u.explain_request->database = db;
679 sr->u.explain_request->stylesheet = stylesheet;
681 (*soap_package) = (Z_SOAP *)
682 odr_malloc(decode, sizeof(**soap_package));
683 (*soap_package)->which = Z_SOAP_generic;
685 (*soap_package)->u.generic = (Z_SOAP_Generic *)
686 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
688 (*soap_package)->u.generic->p = sr;
689 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
690 (*soap_package)->u.generic->no = 0;
692 (*soap_package)->ns = "SRU";
694 yaz_add_srw_diagnostic(decode, diag, num_diag,
695 YAZ_SRW_UNSUPP_OPERATION, operation);
705 Z_SRW_extra_record *yaz_srw_get_extra_record(ODR o)
707 Z_SRW_extra_record *res = (Z_SRW_extra_record *)
708 odr_malloc(o, sizeof(*res));
710 res->extraRecordData_buf = 0;
711 res->extraRecordData_len = 0;
712 res->recordIdentifier = 0;
717 Z_SRW_record *yaz_srw_get_records(ODR o, int n)
719 Z_SRW_record *res = (Z_SRW_record *) odr_malloc(o, n * sizeof(*res));
722 for (i = 0; i<n; i++)
724 res[i].recordSchema = 0;
725 res[i].recordPacking = Z_SRW_recordPacking_string;
726 res[i].recordData_buf = 0;
727 res[i].recordData_len = 0;
728 res[i].recordPosition = 0;
733 Z_SRW_record *yaz_srw_get_record(ODR o)
735 return yaz_srw_get_records(o, 1);
738 static Z_SRW_PDU *yaz_srw_get_core_ver(ODR o, const char *version)
740 Z_SRW_PDU *p = (Z_SRW_PDU *) odr_malloc(o, sizeof(*p));
741 p->srw_version = odr_strdup(o, version);
745 p->extraResponseData_buf = 0;
746 p->extraResponseData_len = 0;
750 Z_SRW_PDU *yaz_srw_get_core_v_2_0(ODR o)
752 return yaz_srw_get_core_ver(o, "2.0");
755 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
757 return yaz_srw_get_pdu(o, which, "2.0");
760 Z_SRW_PDU *yaz_srw_get_pdu(ODR o, int which, const char *version)
762 Z_SRW_PDU *sr = yaz_srw_get_core_ver(o, version);
767 case Z_SRW_searchRetrieve_request:
768 sr->u.request = (Z_SRW_searchRetrieveRequest *)
769 odr_malloc(o, sizeof(*sr->u.request));
770 sr->u.request->queryType = "cql";
771 sr->u.request->query = 0;
772 sr->u.request->sort_type = Z_SRW_sort_type_none;
773 sr->u.request->sort.none = 0;
774 sr->u.request->startRecord = 0;
775 sr->u.request->maximumRecords = 0;
776 sr->u.request->recordSchema = 0;
777 sr->u.request->recordPacking = 0;
778 sr->u.request->packing = 0;
779 sr->u.request->recordXPath = 0;
780 sr->u.request->database = 0;
781 sr->u.request->resultSetTTL = 0;
782 sr->u.request->stylesheet = 0;
783 sr->u.request->facetList = 0;
785 case Z_SRW_searchRetrieve_response:
786 sr->u.response = (Z_SRW_searchRetrieveResponse *)
787 odr_malloc(o, sizeof(*sr->u.response));
788 sr->u.response->numberOfRecords = 0;
789 sr->u.response->resultCountPrecision = 0;
790 sr->u.response->resultSetId = 0;
791 sr->u.response->resultSetIdleTime = 0;
792 sr->u.response->records = 0;
793 sr->u.response->num_records = 0;
794 sr->u.response->diagnostics = 0;
795 sr->u.response->num_diagnostics = 0;
796 sr->u.response->nextRecordPosition = 0;
797 sr->u.response->extra_records = 0;
798 sr->u.response->facetList = 0;
799 sr->u.response->suggestions = 0;
801 case Z_SRW_explain_request:
802 sr->u.explain_request = (Z_SRW_explainRequest *)
803 odr_malloc(o, sizeof(*sr->u.explain_request));
804 sr->u.explain_request->recordPacking = 0;
805 sr->u.explain_request->packing = 0;
806 sr->u.explain_request->database = 0;
807 sr->u.explain_request->stylesheet = 0;
809 case Z_SRW_explain_response:
810 sr->u.explain_response = (Z_SRW_explainResponse *)
811 odr_malloc(o, sizeof(*sr->u.explain_response));
812 sr->u.explain_response->record.recordData_buf = 0;
813 sr->u.explain_response->record.recordData_len = 0;
814 sr->u.explain_response->record.recordSchema = 0;
815 sr->u.explain_response->record.recordPosition = 0;
816 sr->u.explain_response->record.recordPacking =
817 Z_SRW_recordPacking_string;
818 sr->u.explain_response->diagnostics = 0;
819 sr->u.explain_response->num_diagnostics = 0;
820 sr->u.explain_response->extra_record = 0;
822 case Z_SRW_scan_request:
823 sr->u.scan_request = (Z_SRW_scanRequest *)
824 odr_malloc(o, sizeof(*sr->u.scan_request));
825 sr->u.scan_request->database = 0;
826 sr->u.scan_request->stylesheet = 0;
827 sr->u.scan_request->maximumTerms = 0;
828 sr->u.scan_request->responsePosition = 0;
829 sr->u.scan_request->queryType = "cql";
830 sr->u.scan_request->scanClause = 0;
832 case Z_SRW_scan_response:
833 sr->u.scan_response = (Z_SRW_scanResponse *)
834 odr_malloc(o, sizeof(*sr->u.scan_response));
835 sr->u.scan_response->terms = 0;
836 sr->u.scan_response->num_terms = 0;
837 sr->u.scan_response->diagnostics = 0;
838 sr->u.scan_response->num_diagnostics = 0;
840 case Z_SRW_update_request:
841 sr->u.update_request = (Z_SRW_updateRequest *)
842 odr_malloc(o, sizeof(*sr->u.update_request));
843 sr->u.update_request->database = 0;
844 sr->u.update_request->stylesheet = 0;
845 sr->u.update_request->record = 0;
846 sr->u.update_request->recordId = 0;
847 sr->u.update_request->recordVersions = 0;
848 sr->u.update_request->num_recordVersions = 0;
849 sr->u.update_request->extra_record = 0;
850 sr->u.update_request->extraRequestData_buf = 0;
851 sr->u.update_request->extraRequestData_len = 0;
852 sr->u.request->database = 0;
854 case Z_SRW_update_response:
855 sr->u.update_response = (Z_SRW_updateResponse *)
856 odr_malloc(o, sizeof(*sr->u.update_response));
857 sr->u.update_response->operationStatus = 0;
858 sr->u.update_response->recordId = 0;
859 sr->u.update_response->recordVersions = 0;
860 sr->u.update_response->num_recordVersions = 0;
861 sr->u.update_response->record = 0;
862 sr->u.update_response->extra_record = 0;
863 sr->u.update_response->extraResponseData_buf = 0;
864 sr->u.update_response->extraResponseData_len = 0;
865 sr->u.update_response->diagnostics = 0;
866 sr->u.update_response->num_diagnostics = 0;
871 void yaz_add_name_value_int(ODR o, char **name, char **value, int *i,
872 char *a_name, Odr_int *val)
877 value[*i] = (char *) odr_malloc(o, 40);
878 sprintf(value[*i], ODR_INT_PRINTF, *val);
883 void yaz_add_name_value_str(ODR o, char **name, char **value, int *i,
884 char *a_name, char *val)
894 static int yaz_get_sru_parms(const Z_SRW_PDU *srw_pdu, ODR encode,
895 char **name, char **value, int max_names)
897 int version2 = strcmp(srw_pdu->srw_version, "2.") > 0;
900 yaz_add_name_value_str(encode, name, value, &i, "version",
901 srw_pdu->srw_version);
902 name[i] = "operation";
903 switch (srw_pdu->which)
905 case Z_SRW_searchRetrieve_request:
906 value[i++] = "searchRetrieve";
907 queryType = srw_pdu->u.request->queryType;
910 if (queryType && strcmp(queryType, "cql"))
911 yaz_add_name_value_str(encode, name, value, &i, "queryType",
913 yaz_add_name_value_str(encode, name, value, &i, "query",
914 srw_pdu->u.request->query);
918 if (!strcmp(queryType, "cql"))
920 yaz_add_name_value_str(encode, name, value, &i, "query",
921 srw_pdu->u.request->query);
923 else if (!strcmp(queryType, "pqf"))
925 yaz_add_name_value_str(encode, name, value, &i, "x-pquery",
926 srw_pdu->u.request->query);
928 else if (!strcmp(queryType, "xcql"))
930 yaz_add_name_value_str(encode, name, value, &i, "x-cql",
931 srw_pdu->u.request->query);
934 switch (srw_pdu->u.request->sort_type)
936 case Z_SRW_sort_type_none:
938 case Z_SRW_sort_type_sort:
939 yaz_add_name_value_str(encode, name, value, &i, "sortKeys",
940 srw_pdu->u.request->sort.sortKeys);
943 yaz_add_name_value_int(encode, name, value, &i, "startRecord",
944 srw_pdu->u.request->startRecord);
945 yaz_add_name_value_int(encode, name, value, &i, "maximumRecords",
946 srw_pdu->u.request->maximumRecords);
947 yaz_add_name_value_str(encode, name, value, &i, "recordSchema",
948 srw_pdu->u.request->recordSchema);
951 yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping",
952 srw_pdu->u.request->recordPacking);
953 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
954 srw_pdu->u.request->packing);
957 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
958 srw_pdu->u.request->recordPacking);
959 yaz_add_name_value_str(encode, name, value, &i, "recordXPath",
960 srw_pdu->u.request->recordXPath);
961 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
962 srw_pdu->u.request->stylesheet);
963 yaz_add_name_value_int(encode, name, value, &i, "resultSetTTL",
964 srw_pdu->u.request->resultSetTTL);
966 const char *facetLimit = 0;
967 const char *facetStart = 0;
968 const char *facetSort = 0;
969 yaz_sru_facet_request(encode, &srw_pdu->u.request->facetList,
970 &facetLimit, &facetStart, &facetSort);
971 yaz_add_name_value_str(encode, name, value, &i, "facetLimit",
972 (char *) facetLimit);
973 yaz_add_name_value_str(encode, name, value, &i, "facetStart",
974 (char *) facetStart);
975 yaz_add_name_value_str(encode, name, value, &i, "facetSort",
979 case Z_SRW_explain_request:
980 value[i++] = "explain";
984 yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping",
985 srw_pdu->u.explain_request->recordPacking);
986 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
987 srw_pdu->u.explain_request->packing);
990 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
991 srw_pdu->u.explain_request->recordPacking);
992 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
993 srw_pdu->u.explain_request->stylesheet);
995 case Z_SRW_scan_request:
997 queryType = srw_pdu->u.scan_request->queryType;
1000 if (queryType && strcmp(queryType, "cql"))
1001 yaz_add_name_value_str(encode, name, value, &i, "queryType",
1003 yaz_add_name_value_str(encode, name, value, &i, "scanClause",
1004 srw_pdu->u.scan_request->scanClause);
1008 if (!queryType || !strcmp(queryType, "cql"))
1009 yaz_add_name_value_str(encode, name, value, &i, "scanClause",
1010 srw_pdu->u.scan_request->scanClause);
1011 else if (!strcmp(queryType, "pqf"))
1012 yaz_add_name_value_str(encode, name, value, &i, "x-pScanClause",
1013 srw_pdu->u.scan_request->scanClause);
1014 else if (!strcmp(queryType, "xcql"))
1015 yaz_add_name_value_str(encode, name, value, &i,
1017 srw_pdu->u.scan_request->scanClause);
1019 yaz_add_name_value_int(encode, name, value, &i, "responsePosition",
1020 srw_pdu->u.scan_request->responsePosition);
1021 yaz_add_name_value_int(encode, name, value, &i, "maximumTerms",
1022 srw_pdu->u.scan_request->maximumTerms);
1023 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
1024 srw_pdu->u.scan_request->stylesheet);
1026 case Z_SRW_update_request:
1027 value[i++] = "update";
1032 if (srw_pdu->extra_args)
1034 Z_SRW_extra_arg *ea = srw_pdu->extra_args;
1035 for (; ea && i < max_names-1; ea = ea->next)
1038 value[i] = ea->value;
1047 int yaz_sru_get_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1048 ODR encode, const char *charset)
1050 char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */
1054 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1055 srw_pdu->username, srw_pdu->password);
1056 if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS))
1058 yaz_array_to_uri(&uri_args, encode, name, value);
1060 hreq->method = "GET";
1063 odr_malloc(encode, strlen(hreq->path) + strlen(uri_args) + 4);
1065 sprintf(path, "%s?%s", hreq->path, uri_args);
1068 z_HTTP_header_add_content_type(encode, &hreq->headers,
1069 "text/xml", charset);
1073 int yaz_sru_post_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1074 ODR encode, const char *charset)
1076 char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */
1079 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1080 srw_pdu->username, srw_pdu->password);
1081 if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS))
1084 yaz_array_to_uri(&uri_args, encode, name, value);
1086 hreq->method = "POST";
1088 hreq->content_buf = uri_args;
1089 hreq->content_len = strlen(uri_args);
1091 z_HTTP_header_add_content_type(encode, &hreq->headers,
1092 "application/x-www-form-urlencoded",
1097 int yaz_sru_soap_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1098 ODR odr, const char *charset)
1100 Z_SOAP_Handler handlers[3] = {
1102 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
1103 {YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec},
1107 Z_SOAP *p = (Z_SOAP*) odr_malloc(odr, sizeof(*p));
1109 z_HTTP_header_add_basic_auth(odr, &hreq->headers,
1110 srw_pdu->username, srw_pdu->password);
1111 z_HTTP_header_add_content_type(odr,
1113 "text/xml", 0 /* no charset in MIME */);
1115 z_HTTP_header_add(odr, &hreq->headers,
1116 "SOAPAction", "\"\"");
1117 p->which = Z_SOAP_generic;
1118 p->u.generic = (Z_SOAP_Generic *) odr_malloc(odr, sizeof(*p->u.generic));
1119 p->u.generic->no = 0;
1120 p->u.generic->ns = 0;
1121 p->u.generic->p = srw_pdu;
1122 p->ns = "http://schemas.xmlsoap.org/soap/envelope/";
1125 if (srw_pdu->which == Z_SRW_update_request ||
1126 srw_pdu->which == Z_SRW_update_response)
1127 p->u.generic->no = 1; /* second handler */
1129 return z_soap_codec_enc(odr, &p,
1131 &hreq->content_len, handlers,
1135 Z_SRW_recordVersion *yaz_srw_get_record_versions(ODR odr, int num)
1137 Z_SRW_recordVersion *ver
1138 = (Z_SRW_recordVersion *) odr_malloc(odr,num * sizeof(*ver));
1140 for (i = 0; i < num; ++i)
1142 ver[i].versionType = 0;
1143 ver[i].versionValue = 0;
1148 const char *yaz_srw_pack_to_str(int pack)
1152 case Z_SRW_recordPacking_string:
1154 case Z_SRW_recordPacking_XML:
1156 case Z_SRW_recordPacking_URL:
1162 int yaz_srw_str_to_pack(const char *str)
1164 if (!yaz_matchstr(str, "string"))
1165 return Z_SRW_recordPacking_string;
1166 if (!yaz_matchstr(str, "xml"))
1167 return Z_SRW_recordPacking_XML;
1168 if (!yaz_matchstr(str, "url"))
1169 return Z_SRW_recordPacking_URL;
1173 void yaz_encode_sru_extra(Z_SRW_PDU *sr, ODR odr, const char *extra_args)
1179 Z_SRW_extra_arg **ea = &sr->extra_args;
1180 yaz_uri_to_array(extra_args, odr, &name, &val);
1182 /** append rather than override */
1187 *ea = (Z_SRW_extra_arg *) odr_malloc(odr, sizeof(**ea));
1188 (*ea)->name = *name;
1189 (*ea)->value = *val;
1202 * c-file-style: "Stroustrup"
1203 * indent-tabs-mode: nil
1205 * vim: shiftwidth=4 tabstop=8 expandtab