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, "; "))
105 * Look for authentication tokens in HTTP Basic parameters or in x-username/x-password
106 * parameters. Added by SH.
108 static void yaz_srw_decodeauth(Z_SRW_PDU *sr, Z_HTTP_Request *hreq,
109 char *username, char *password, ODR decode)
111 const char *basic = z_HTTP_header_lookup(hreq->headers, "Authorization");
114 sr->username = username;
116 sr->password = password;
122 char ubuf[256] = "", pbuf[256] = "", *p;
123 if (strncmp(basic, "Basic ", 6))
127 if (!len || len > 256)
129 yaz_base64decode(basic, out);
130 /* Format of out should be username:password at this point */
132 if ((p = strchr(ubuf, ':')))
139 sr->username = odr_strdup(decode, ubuf);
141 sr->password = odr_strdup(decode, pbuf);
145 void yaz_mk_srw_diagnostic(ODR o, Z_SRW_diagnostic *d,
146 const char *uri, const char *message,
149 d->uri = odr_strdup(o, uri);
151 d->message = odr_strdup(o, message);
155 d->details = odr_strdup(o, details);
160 void yaz_mk_std_diagnostic(ODR o, Z_SRW_diagnostic *d,
161 int code, const char *details)
165 sprintf(uri, "info:srw/diagnostic/1/%d", code);
166 yaz_mk_srw_diagnostic(o, d, uri, 0, details);
169 void yaz_add_srw_diagnostic_uri(ODR o, Z_SRW_diagnostic **d,
170 int *num, const char *uri,
171 const char *message, const char *details)
173 Z_SRW_diagnostic *d_new;
174 d_new = (Z_SRW_diagnostic *) odr_malloc(o, (*num + 1)* sizeof(**d));
176 memcpy(d_new, *d, *num *sizeof(**d));
179 yaz_mk_srw_diagnostic(o, *d + *num, uri, message, details);
183 void yaz_add_srw_diagnostic(ODR o, Z_SRW_diagnostic **d,
184 int *num, int code, const char *addinfo)
188 sprintf(uri, "info:srw/diagnostic/1/%d", code);
189 yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
193 void yaz_add_sru_update_diagnostic(ODR o, Z_SRW_diagnostic **d,
194 int *num, int code, const char *addinfo)
198 sprintf(uri, "info:srw/diagnostic/12/%d", code);
199 yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
203 void yaz_mk_sru_surrogate(ODR o, Z_SRW_record *record, int pos,
204 int code, const char *details)
206 const char *message = yaz_diag_srw_str(code);
209 len += strlen(message);
211 len += strlen(details);
213 record->recordData_buf = (char *) odr_malloc(o, len);
215 sprintf(record->recordData_buf, "<diagnostic "
216 "xmlns=\"http://www.loc.gov/zing/srw/diagnostic/\">\n"
217 " <uri>info:srw/diagnostic/1/%d</uri>\n", code);
219 sprintf(record->recordData_buf + strlen(record->recordData_buf),
220 " <details>%s</details>\n", details);
222 sprintf(record->recordData_buf + strlen(record->recordData_buf),
223 " <message>%s</message>\n", message);
224 sprintf(record->recordData_buf + strlen(record->recordData_buf),
226 record->recordData_len = strlen(record->recordData_buf);
227 record->recordPosition = odr_intdup(o, pos);
228 record->recordSchema = "info:srw/schema/1/diagnostics-v1.1";
231 static void grab_charset(ODR o, const char *content_type, char **charset)
235 const char *charset_p = 0;
236 if (content_type && (charset_p = strstr(content_type, "; charset=")))
240 charset_p += 10; /* skip ; charset= */
241 if (charset_p[i] == '"' || charset_p[i] == '\'')
242 sep = charset_p[i++];
243 *charset = odr_strdup(o, charset_p);
244 while (charset_p[i] && charset_p[i] != sep)
246 if (!sep && strchr("; \n\r", charset_p[i]))
248 if (charset_p[i] == '\\' && charset_p[i+1])
250 (*charset)[j++] = charset_p[i++];
252 (*charset)[j] = '\0';
257 int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
258 Z_SOAP **soap_package, ODR decode, char **charset)
260 if (!strcmp(hreq->method, "POST"))
262 const char *content_type = z_HTTP_header_lookup(hreq->headers,
265 (!yaz_strcmp_del("text/xml", content_type, "; ") ||
266 !yaz_strcmp_del("application/soap+xml", content_type, "; ") ||
267 !yaz_strcmp_del("text/plain", content_type, "; ")))
269 char *db = "Default";
270 const char *p0 = hreq->path, *p1;
273 static Z_SOAP_Handler soap_handlers[5] = {
275 { YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec },
276 { YAZ_XMLNS_SRU_v1_0, 0, (Z_SOAP_fun) yaz_srw_codec },
277 { YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec },
278 { YAZ_XMLNS_SRU_v2_mask, 0, (Z_SOAP_fun) yaz_srw_codec },
285 p1 = strchr(p0, '?');
287 p1 = p0 + strlen(p0);
289 db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);
291 ret = z_soap_codec(decode, soap_package,
292 &hreq->content_buf, &hreq->content_len,
294 if (ret == 0 && (*soap_package)->which == Z_SOAP_generic)
296 *srw_pdu = (Z_SRW_PDU*) (*soap_package)->u.generic->p;
297 yaz_srw_decodeauth(*srw_pdu, hreq, 0, 0, decode);
299 /* last entry in handlers - SRU 2.0 - is turned into
300 offset 0.. due to other pieces relying on it */
301 if ((*soap_package)->u.generic->no == 3)
302 (*soap_package)->u.generic->no = 0;
303 if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request &&
304 (*srw_pdu)->u.request->database == 0)
305 (*srw_pdu)->u.request->database = db;
307 if ((*srw_pdu)->which == Z_SRW_explain_request &&
308 (*srw_pdu)->u.explain_request->database == 0)
309 (*srw_pdu)->u.explain_request->database = db;
311 if ((*srw_pdu)->which == Z_SRW_scan_request &&
312 (*srw_pdu)->u.scan_request->database == 0)
313 (*srw_pdu)->u.scan_request->database = db;
315 if ((*srw_pdu)->which == Z_SRW_update_request &&
316 (*srw_pdu)->u.update_request->database == 0)
317 (*srw_pdu)->u.update_request->database = db;
328 static int yaz_sru_decode_integer(ODR odr, const char *pname,
329 const char *valstr, Odr_int **valp,
330 Z_SRW_diagnostic **diag, int *num_diag,
336 if (sscanf(valstr, "%d", &ival) != 1)
338 yaz_add_srw_diagnostic(odr, diag, num_diag,
339 YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
342 if (min_value >= 0 && ival < min_value)
344 yaz_add_srw_diagnostic(odr, diag, num_diag,
345 YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
348 *valp = odr_intdup(odr, ival);
354 http://www.loc.gov/z3950/agency/zing/srw/service.html
356 int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
357 Z_SOAP **soap_package, ODR decode, char **charset,
358 Z_SRW_diagnostic **diag, int *num_diag)
361 static Z_SOAP_Handler soap_handlers[2] = {
362 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
366 const char *content_type = z_HTTP_header_lookup(hreq->headers,
370 SRU GET: ignore content type.
371 SRU POST: we support "application/x-www-form-urlencoded";
372 not "multipart/form-data" .
374 if (!strcmp(hreq->method, "GET")
376 (!strcmp(hreq->method, "POST") && content_type &&
377 !yaz_strcmp_del("application/x-www-form-urlencoded",
378 content_type, "; ")))
380 char *db = "Default";
381 const char *p0 = hreq->path, *p1;
383 const char *operation = 0;
386 char *queryType = "cql";
390 char *stylesheet = 0;
391 char *scanClause = 0;
392 char *recordXPath = 0;
393 char *recordSchema = 0;
394 char *recordXMLEscaping = 0;
395 char *recordPacking = 0;
396 char *maximumRecords = 0;
397 char *startRecord = 0;
398 char *maximumTerms = 0;
399 char *responsePosition = 0;
400 const char *facetLimit = 0;
401 const char *facetStart = 0;
402 const char *facetSort = 0;
403 Z_SRW_extra_arg *extra_args = 0;
408 grab_charset(decode, content_type, charset);
409 if (charset && *charset == 0 && !strcmp(hreq->method, "GET"))
414 p1 = strchr(p0, '?');
416 p1 = p0 + strlen(p0);
418 db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);
419 if (!strcmp(hreq->method, "POST"))
420 p1 = hreq->content_buf;
421 yaz_uri_to_array(p1, decode, &uri_name, &uri_val);
426 for (i = 0; uri_name[i]; i++)
428 char *n = uri_name[i];
429 char *v = uri_val[i];
430 if (!strcmp(n, "query"))
432 else if (!strcmp(n, "x-pquery"))
437 else if (!strcmp(n, "queryType"))
439 else if (!strcmp(n, "x-username"))
441 else if (!strcmp(n, "x-password"))
443 else if (!strcmp(n, "operation"))
445 else if (!strcmp(n, "stylesheet"))
447 else if (!strcmp(n, "sortKeys"))
449 else if (!strcmp(n, "recordXPath"))
451 else if (!strcmp(n, "recordSchema"))
453 else if (!strcmp(n, "recordPacking"))
455 else if (!strcmp(n, "recordXMLEscaping"))
456 recordXMLEscaping = v;
457 else if (!strcmp(n, "version"))
459 else if (!strcmp(n, "scanClause"))
461 else if (!strcmp(n, "x-pScanClause"))
466 else if (!strcmp(n, "maximumRecords"))
468 else if (!strcmp(n, "startRecord"))
470 else if (!strcmp(n, "maximumTerms"))
472 else if (!strcmp(n, "responsePosition"))
473 responsePosition = v;
474 else if (!strcmp(n, "facetLimit"))
476 else if (!strcmp(n, "facetStart"))
478 else if (!strcmp(n, "facetSort"))
480 else if (!strcmp(n, "extraRequestData"))
481 ; /* ignoring extraRequestData */
482 else if (n[0] == 'x' && n[1] == '-')
484 append_extra_arg(decode, &extra_args, n, v);
489 yaz_add_srw_diagnostic(decode, diag, num_diag,
490 YAZ_SRW_UNSUPP_PARAMETER, n);
497 operation = "searchRetrieve";
501 version = yaz_negotiate_sru_version(version);
504 { /* negotiation failed. */
505 yaz_add_srw_diagnostic(decode, diag, num_diag,
506 YAZ_SRW_UNSUPP_VERSION, "2.0");
512 yaz_add_srw_diagnostic(
513 decode, diag, num_diag,
514 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "operation");
515 operation = "explain";
517 if (strcmp(version, "2.0"))
519 if (recordXMLEscaping)
521 yaz_add_srw_diagnostic(decode, diag, num_diag,
522 YAZ_SRW_UNSUPP_PARAMETER,
523 "recordXMLEscaping");
526 recordXMLEscaping = recordPacking;
527 recordPacking = "packed";
529 if (!recordXMLEscaping)
530 recordXMLEscaping = "xml";
531 if (!strcmp(operation, "searchRetrieve"))
533 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
535 sr->srw_version = version;
536 sr->extra_args = extra_args;
538 yaz_srw_decodeauth(sr, hreq, username, password, decode);
540 sr->u.request->queryType = queryType;
541 sr->u.request->query = query;
544 yaz_add_srw_diagnostic(
545 decode, diag, num_diag,
546 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "query");
550 sr->u.request->sort_type = Z_SRW_sort_type_sort;
551 sr->u.request->sort.sortKeys = sortKeys;
553 sr->u.request->recordXPath = recordXPath;
554 sr->u.request->recordSchema = recordSchema;
555 sr->u.request->recordPacking = recordXMLEscaping;
556 sr->u.request->packing = recordPacking;
557 sr->u.request->stylesheet = stylesheet;
558 yaz_sru_facet_request(decode , &sr->u.request->facetList,
559 &facetLimit, &facetStart, &facetSort);
561 yaz_sru_decode_integer(decode, "maximumRecords", maximumRecords,
562 &sr->u.request->maximumRecords,
565 yaz_sru_decode_integer(decode, "startRecord", startRecord,
566 &sr->u.request->startRecord,
569 sr->u.request->database = db;
571 (*soap_package) = (Z_SOAP *)
572 odr_malloc(decode, sizeof(**soap_package));
573 (*soap_package)->which = Z_SOAP_generic;
575 (*soap_package)->u.generic = (Z_SOAP_Generic *)
576 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
578 (*soap_package)->u.generic->p = sr;
579 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
580 (*soap_package)->u.generic->no = 0;
582 (*soap_package)->ns = "SRU";
586 else if (!strcmp(operation, "explain"))
588 /* Transfer SRU explain parameters to common struct */
589 /* http://www.loc.gov/z3950/agency/zing/srw/explain.html */
590 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
592 sr->srw_version = version;
593 sr->extra_args = extra_args;
594 yaz_srw_decodeauth(sr, hreq, username, password, decode);
596 sr->u.explain_request->recordPacking = recordXMLEscaping;
597 sr->u.explain_request->packing = recordPacking;
598 sr->u.explain_request->database = db;
600 sr->u.explain_request->stylesheet = stylesheet;
602 (*soap_package) = (Z_SOAP *)
603 odr_malloc(decode, sizeof(**soap_package));
604 (*soap_package)->which = Z_SOAP_generic;
606 (*soap_package)->u.generic = (Z_SOAP_Generic *)
607 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
609 (*soap_package)->u.generic->p = sr;
610 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
611 (*soap_package)->u.generic->no = 0;
613 (*soap_package)->ns = "SRU";
617 else if (!strcmp(operation, "scan"))
619 /* Transfer SRU scan parameters to common struct */
620 /* http://www.loc.gov/z3950/agency/zing/srw/scan.html */
621 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_scan_request);
623 sr->srw_version = version;
624 sr->extra_args = extra_args;
626 yaz_srw_decodeauth(sr, hreq, username, password, decode);
628 sr->u.scan_request->queryType = queryType;
629 sr->u.scan_request->scanClause = scanClause;
632 yaz_add_srw_diagnostic(
633 decode, diag, num_diag,
634 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "scanClause");
635 sr->u.scan_request->database = db;
637 yaz_sru_decode_integer(decode, "maximumTerms",
639 &sr->u.scan_request->maximumTerms,
642 yaz_sru_decode_integer(decode, "responsePosition",
644 &sr->u.scan_request->responsePosition,
647 sr->u.scan_request->stylesheet = stylesheet;
649 (*soap_package) = (Z_SOAP *)
650 odr_malloc(decode, sizeof(**soap_package));
651 (*soap_package)->which = Z_SOAP_generic;
653 (*soap_package)->u.generic = (Z_SOAP_Generic *)
654 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
656 (*soap_package)->u.generic->p = sr;
657 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
658 (*soap_package)->u.generic->no = 0;
660 (*soap_package)->ns = "SRU";
666 /* unsupported operation ... */
667 /* Act as if we received a explain request and throw diagnostic. */
669 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
671 sr->srw_version = version;
673 sr->u.explain_request->recordPacking = recordPacking;
674 sr->u.explain_request->database = db;
676 sr->u.explain_request->stylesheet = stylesheet;
678 (*soap_package) = (Z_SOAP *)
679 odr_malloc(decode, sizeof(**soap_package));
680 (*soap_package)->which = Z_SOAP_generic;
682 (*soap_package)->u.generic = (Z_SOAP_Generic *)
683 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
685 (*soap_package)->u.generic->p = sr;
686 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
687 (*soap_package)->u.generic->no = 0;
689 (*soap_package)->ns = "SRU";
691 yaz_add_srw_diagnostic(decode, diag, num_diag,
692 YAZ_SRW_UNSUPP_OPERATION, operation);
702 Z_SRW_extra_record *yaz_srw_get_extra_record(ODR o)
704 Z_SRW_extra_record *res = (Z_SRW_extra_record *)
705 odr_malloc(o, sizeof(*res));
707 res->extraRecordData_buf = 0;
708 res->extraRecordData_len = 0;
709 res->recordIdentifier = 0;
714 Z_SRW_record *yaz_srw_get_records(ODR o, int n)
716 Z_SRW_record *res = (Z_SRW_record *) odr_malloc(o, n * sizeof(*res));
719 for (i = 0; i<n; i++)
721 res[i].recordSchema = 0;
722 res[i].recordPacking = Z_SRW_recordPacking_string;
723 res[i].recordData_buf = 0;
724 res[i].recordData_len = 0;
725 res[i].recordPosition = 0;
730 Z_SRW_record *yaz_srw_get_record(ODR o)
732 return yaz_srw_get_records(o, 1);
735 static Z_SRW_PDU *yaz_srw_get_core_ver(ODR o, const char *version)
737 Z_SRW_PDU *p = (Z_SRW_PDU *) odr_malloc(o, sizeof(*p));
738 p->srw_version = odr_strdup(o, version);
742 p->extraResponseData_buf = 0;
743 p->extraResponseData_len = 0;
747 Z_SRW_PDU *yaz_srw_get_core_v_2_0(ODR o)
749 return yaz_srw_get_core_ver(o, "2.0");
752 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
754 return yaz_srw_get_pdu(o, which, "2.0");
757 Z_SRW_PDU *yaz_srw_get_pdu_e(ODR o, int which, Z_SRW_PDU *req)
759 int version2 = !req->srw_version || strcmp(req->srw_version, "2.") > 0;
760 Z_SRW_PDU *res = yaz_srw_get_pdu(o, which, req->srw_version);
761 if (req->which == Z_SRW_searchRetrieve_request &&
762 which == Z_SRW_searchRetrieve_response)
764 Z_SRW_extra_arg **l = &res->extra_args;
765 l = append_extra_arg(o, l, "version", req->srw_version);
766 if (req->u.request->queryType &&
767 strcmp(req->u.request->queryType, "cql"))
768 l = append_extra_arg(o, l, "queryType", req->u.request->queryType);
769 l = append_extra_arg(o, l, "query", req->u.request->query);
770 l = append_extra_arg_int(o, l, "startRecord",
771 req->u.request->startRecord);
772 l = append_extra_arg_int(o, l, "maximumRecords",
773 req->u.request->maximumRecords);
776 l = append_extra_arg(o, l, "recordXMLEscaping",
777 req->u.request->recordPacking);
778 l = append_extra_arg(o, l, "recordPacking",
779 req->u.request->packing);
782 l = append_extra_arg(o, l, "recordPacking",
783 req->u.request->recordPacking);
784 l = append_extra_arg(o, l, "recordSchema",
785 req->u.request->recordSchema);
786 if (req->u.request->sort_type == Z_SRW_sort_type_sort)
787 l = append_extra_arg(o, l, "sortKeys",
788 req->u.request->sort.sortKeys);
793 Z_SRW_PDU *yaz_srw_get_pdu(ODR o, int which, const char *version)
795 Z_SRW_PDU *sr = yaz_srw_get_core_ver(o, version);
800 case Z_SRW_searchRetrieve_request:
801 sr->u.request = (Z_SRW_searchRetrieveRequest *)
802 odr_malloc(o, sizeof(*sr->u.request));
803 sr->u.request->queryType = "cql";
804 sr->u.request->query = 0;
805 sr->u.request->sort_type = Z_SRW_sort_type_none;
806 sr->u.request->sort.none = 0;
807 sr->u.request->startRecord = 0;
808 sr->u.request->maximumRecords = 0;
809 sr->u.request->recordSchema = 0;
810 sr->u.request->recordPacking = 0;
811 sr->u.request->packing = 0;
812 sr->u.request->recordXPath = 0;
813 sr->u.request->database = 0;
814 sr->u.request->resultSetTTL = 0;
815 sr->u.request->stylesheet = 0;
816 sr->u.request->facetList = 0;
818 case Z_SRW_searchRetrieve_response:
819 sr->u.response = (Z_SRW_searchRetrieveResponse *)
820 odr_malloc(o, sizeof(*sr->u.response));
821 sr->u.response->numberOfRecords = 0;
822 sr->u.response->resultCountPrecision = 0;
823 sr->u.response->resultSetId = 0;
824 sr->u.response->resultSetIdleTime = 0;
825 sr->u.response->records = 0;
826 sr->u.response->num_records = 0;
827 sr->u.response->diagnostics = 0;
828 sr->u.response->num_diagnostics = 0;
829 sr->u.response->nextRecordPosition = 0;
830 sr->u.response->extra_records = 0;
831 sr->u.response->facetList = 0;
832 sr->u.response->suggestions = 0;
834 case Z_SRW_explain_request:
835 sr->u.explain_request = (Z_SRW_explainRequest *)
836 odr_malloc(o, sizeof(*sr->u.explain_request));
837 sr->u.explain_request->recordPacking = 0;
838 sr->u.explain_request->packing = 0;
839 sr->u.explain_request->database = 0;
840 sr->u.explain_request->stylesheet = 0;
842 case Z_SRW_explain_response:
843 sr->u.explain_response = (Z_SRW_explainResponse *)
844 odr_malloc(o, sizeof(*sr->u.explain_response));
845 sr->u.explain_response->record.recordData_buf = 0;
846 sr->u.explain_response->record.recordData_len = 0;
847 sr->u.explain_response->record.recordSchema = 0;
848 sr->u.explain_response->record.recordPosition = 0;
849 sr->u.explain_response->record.recordPacking =
850 Z_SRW_recordPacking_string;
851 sr->u.explain_response->diagnostics = 0;
852 sr->u.explain_response->num_diagnostics = 0;
853 sr->u.explain_response->extra_record = 0;
855 case Z_SRW_scan_request:
856 sr->u.scan_request = (Z_SRW_scanRequest *)
857 odr_malloc(o, sizeof(*sr->u.scan_request));
858 sr->u.scan_request->database = 0;
859 sr->u.scan_request->stylesheet = 0;
860 sr->u.scan_request->maximumTerms = 0;
861 sr->u.scan_request->responsePosition = 0;
862 sr->u.scan_request->queryType = "cql";
863 sr->u.scan_request->scanClause = 0;
865 case Z_SRW_scan_response:
866 sr->u.scan_response = (Z_SRW_scanResponse *)
867 odr_malloc(o, sizeof(*sr->u.scan_response));
868 sr->u.scan_response->terms = 0;
869 sr->u.scan_response->num_terms = 0;
870 sr->u.scan_response->diagnostics = 0;
871 sr->u.scan_response->num_diagnostics = 0;
873 case Z_SRW_update_request:
874 sr->u.update_request = (Z_SRW_updateRequest *)
875 odr_malloc(o, sizeof(*sr->u.update_request));
876 sr->u.update_request->database = 0;
877 sr->u.update_request->stylesheet = 0;
878 sr->u.update_request->record = 0;
879 sr->u.update_request->recordId = 0;
880 sr->u.update_request->recordVersions = 0;
881 sr->u.update_request->num_recordVersions = 0;
882 sr->u.update_request->extra_record = 0;
883 sr->u.update_request->extraRequestData_buf = 0;
884 sr->u.update_request->extraRequestData_len = 0;
885 sr->u.request->database = 0;
887 case Z_SRW_update_response:
888 sr->u.update_response = (Z_SRW_updateResponse *)
889 odr_malloc(o, sizeof(*sr->u.update_response));
890 sr->u.update_response->operationStatus = 0;
891 sr->u.update_response->recordId = 0;
892 sr->u.update_response->recordVersions = 0;
893 sr->u.update_response->num_recordVersions = 0;
894 sr->u.update_response->record = 0;
895 sr->u.update_response->extra_record = 0;
896 sr->u.update_response->extraResponseData_buf = 0;
897 sr->u.update_response->extraResponseData_len = 0;
898 sr->u.update_response->diagnostics = 0;
899 sr->u.update_response->num_diagnostics = 0;
904 void yaz_add_name_value_int(ODR o, char **name, char **value, int *i,
905 char *a_name, Odr_int *val)
910 value[*i] = (char *) odr_malloc(o, 40);
911 sprintf(value[*i], ODR_INT_PRINTF, *val);
916 void yaz_add_name_value_str(ODR o, char **name, char **value, int *i,
917 char *a_name, char *val)
927 static int yaz_get_sru_parms(const Z_SRW_PDU *srw_pdu, ODR encode,
928 char **name, char **value, int max_names)
930 int version2 = strcmp(srw_pdu->srw_version, "2.") > 0;
933 yaz_add_name_value_str(encode, name, value, &i, "version",
934 srw_pdu->srw_version);
935 name[i] = "operation";
936 switch (srw_pdu->which)
938 case Z_SRW_searchRetrieve_request:
939 value[i++] = "searchRetrieve";
940 queryType = srw_pdu->u.request->queryType;
943 if (queryType && strcmp(queryType, "cql"))
944 yaz_add_name_value_str(encode, name, value, &i, "queryType",
946 yaz_add_name_value_str(encode, name, value, &i, "query",
947 srw_pdu->u.request->query);
951 if (!strcmp(queryType, "cql"))
953 yaz_add_name_value_str(encode, name, value, &i, "query",
954 srw_pdu->u.request->query);
956 else if (!strcmp(queryType, "pqf"))
958 yaz_add_name_value_str(encode, name, value, &i, "x-pquery",
959 srw_pdu->u.request->query);
961 else if (!strcmp(queryType, "xcql"))
963 yaz_add_name_value_str(encode, name, value, &i, "x-cql",
964 srw_pdu->u.request->query);
967 switch (srw_pdu->u.request->sort_type)
969 case Z_SRW_sort_type_none:
971 case Z_SRW_sort_type_sort:
972 yaz_add_name_value_str(encode, name, value, &i, "sortKeys",
973 srw_pdu->u.request->sort.sortKeys);
976 yaz_add_name_value_int(encode, name, value, &i, "startRecord",
977 srw_pdu->u.request->startRecord);
978 yaz_add_name_value_int(encode, name, value, &i, "maximumRecords",
979 srw_pdu->u.request->maximumRecords);
980 yaz_add_name_value_str(encode, name, value, &i, "recordSchema",
981 srw_pdu->u.request->recordSchema);
984 yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping",
985 srw_pdu->u.request->recordPacking);
986 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
987 srw_pdu->u.request->packing);
990 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
991 srw_pdu->u.request->recordPacking);
992 yaz_add_name_value_str(encode, name, value, &i, "recordXPath",
993 srw_pdu->u.request->recordXPath);
994 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
995 srw_pdu->u.request->stylesheet);
996 yaz_add_name_value_int(encode, name, value, &i, "resultSetTTL",
997 srw_pdu->u.request->resultSetTTL);
999 const char *facetLimit = 0;
1000 const char *facetStart = 0;
1001 const char *facetSort = 0;
1002 yaz_sru_facet_request(encode, &srw_pdu->u.request->facetList,
1003 &facetLimit, &facetStart, &facetSort);
1004 yaz_add_name_value_str(encode, name, value, &i, "facetLimit",
1005 (char *) facetLimit);
1006 yaz_add_name_value_str(encode, name, value, &i, "facetStart",
1007 (char *) facetStart);
1008 yaz_add_name_value_str(encode, name, value, &i, "facetSort",
1009 (char *) facetSort);
1012 case Z_SRW_explain_request:
1013 value[i++] = "explain";
1017 yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping",
1018 srw_pdu->u.explain_request->recordPacking);
1019 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
1020 srw_pdu->u.explain_request->packing);
1023 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
1024 srw_pdu->u.explain_request->recordPacking);
1025 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
1026 srw_pdu->u.explain_request->stylesheet);
1028 case Z_SRW_scan_request:
1029 value[i++] = "scan";
1030 queryType = srw_pdu->u.scan_request->queryType;
1033 if (queryType && strcmp(queryType, "cql"))
1034 yaz_add_name_value_str(encode, name, value, &i, "queryType",
1036 yaz_add_name_value_str(encode, name, value, &i, "scanClause",
1037 srw_pdu->u.scan_request->scanClause);
1041 if (!queryType || !strcmp(queryType, "cql"))
1042 yaz_add_name_value_str(encode, name, value, &i, "scanClause",
1043 srw_pdu->u.scan_request->scanClause);
1044 else if (!strcmp(queryType, "pqf"))
1045 yaz_add_name_value_str(encode, name, value, &i, "x-pScanClause",
1046 srw_pdu->u.scan_request->scanClause);
1047 else if (!strcmp(queryType, "xcql"))
1048 yaz_add_name_value_str(encode, name, value, &i,
1050 srw_pdu->u.scan_request->scanClause);
1052 yaz_add_name_value_int(encode, name, value, &i, "responsePosition",
1053 srw_pdu->u.scan_request->responsePosition);
1054 yaz_add_name_value_int(encode, name, value, &i, "maximumTerms",
1055 srw_pdu->u.scan_request->maximumTerms);
1056 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
1057 srw_pdu->u.scan_request->stylesheet);
1059 case Z_SRW_update_request:
1060 value[i++] = "update";
1065 if (srw_pdu->extra_args)
1067 Z_SRW_extra_arg *ea = srw_pdu->extra_args;
1068 for (; ea && i < max_names-1; ea = ea->next)
1071 value[i] = ea->value;
1080 int yaz_sru_get_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1081 ODR encode, const char *charset)
1083 char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */
1088 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1089 srw_pdu->username, srw_pdu->password);
1090 if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS))
1092 yaz_array_to_uri(&uri_args, encode, name, value);
1094 hreq->method = "GET";
1096 cp = strchr(hreq->path, '#');
1101 odr_malloc(encode, strlen(hreq->path) + strlen(uri_args) + 4);
1103 sprintf(path, "%s%c%s", hreq->path, strchr(hreq->path, '?') ? '&' : '?',
1107 z_HTTP_header_add_content_type(encode, &hreq->headers,
1108 "text/xml", charset);
1112 int yaz_sru_post_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1113 ODR encode, const char *charset)
1115 char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */
1118 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1119 srw_pdu->username, srw_pdu->password);
1120 if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS))
1123 yaz_array_to_uri(&uri_args, encode, name, value);
1125 hreq->method = "POST";
1127 hreq->content_buf = uri_args;
1128 hreq->content_len = strlen(uri_args);
1130 z_HTTP_header_add_content_type(encode, &hreq->headers,
1131 "application/x-www-form-urlencoded",
1136 int yaz_sru_soap_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1137 ODR odr, const char *charset)
1139 Z_SOAP_Handler handlers[3] = {
1141 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
1142 {YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec},
1146 Z_SOAP *p = (Z_SOAP*) odr_malloc(odr, sizeof(*p));
1148 z_HTTP_header_add_basic_auth(odr, &hreq->headers,
1149 srw_pdu->username, srw_pdu->password);
1150 z_HTTP_header_add_content_type(odr,
1152 "text/xml", 0 /* no charset in MIME */);
1154 z_HTTP_header_add(odr, &hreq->headers,
1155 "SOAPAction", "\"\"");
1156 p->which = Z_SOAP_generic;
1157 p->u.generic = (Z_SOAP_Generic *) odr_malloc(odr, sizeof(*p->u.generic));
1158 p->u.generic->no = 0;
1159 p->u.generic->ns = 0;
1160 p->u.generic->p = srw_pdu;
1161 p->ns = "http://schemas.xmlsoap.org/soap/envelope/";
1164 if (srw_pdu->which == Z_SRW_update_request ||
1165 srw_pdu->which == Z_SRW_update_response)
1166 p->u.generic->no = 1; /* second handler */
1168 return z_soap_codec_enc(odr, &p,
1170 &hreq->content_len, handlers,
1174 Z_SRW_recordVersion *yaz_srw_get_record_versions(ODR odr, int num)
1176 Z_SRW_recordVersion *ver
1177 = (Z_SRW_recordVersion *) odr_malloc(odr,num * sizeof(*ver));
1179 for (i = 0; i < num; ++i)
1181 ver[i].versionType = 0;
1182 ver[i].versionValue = 0;
1187 const char *yaz_srw_pack_to_str(int pack)
1191 case Z_SRW_recordPacking_string:
1193 case Z_SRW_recordPacking_XML:
1195 case Z_SRW_recordPacking_URL:
1201 int yaz_srw_str_to_pack(const char *str)
1203 if (!yaz_matchstr(str, "string"))
1204 return Z_SRW_recordPacking_string;
1205 if (!yaz_matchstr(str, "xml"))
1206 return Z_SRW_recordPacking_XML;
1207 if (!yaz_matchstr(str, "url"))
1208 return Z_SRW_recordPacking_URL;
1212 void yaz_encode_sru_extra(Z_SRW_PDU *sr, ODR odr, const char *extra_args)
1218 Z_SRW_extra_arg **ea = &sr->extra_args;
1219 yaz_uri_to_array(extra_args, odr, &name, &val);
1223 ea = append_extra_arg(odr, ea, *name, *val);
1234 * c-file-style: "Stroustrup"
1235 * indent-tabs-mode: nil
1237 * vim: shiftwidth=4 tabstop=8 expandtab