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_uri_val_int(const char *path, const char *name, ODR o, Odr_int **intp)
146 const char *v = yaz_uri_val(path, name, o);
148 *intp = odr_intdup(o, atoi(v));
151 void yaz_mk_srw_diagnostic(ODR o, Z_SRW_diagnostic *d,
152 const char *uri, const char *message,
155 d->uri = odr_strdup(o, uri);
157 d->message = odr_strdup(o, message);
161 d->details = odr_strdup(o, details);
166 void yaz_mk_std_diagnostic(ODR o, Z_SRW_diagnostic *d,
167 int code, const char *details)
171 sprintf(uri, "info:srw/diagnostic/1/%d", code);
172 yaz_mk_srw_diagnostic(o, d, uri, 0, details);
175 void yaz_add_srw_diagnostic_uri(ODR o, Z_SRW_diagnostic **d,
176 int *num, const char *uri,
177 const char *message, const char *details)
179 Z_SRW_diagnostic *d_new;
180 d_new = (Z_SRW_diagnostic *) odr_malloc(o, (*num + 1)* sizeof(**d));
182 memcpy(d_new, *d, *num *sizeof(**d));
185 yaz_mk_srw_diagnostic(o, *d + *num, uri, message, details);
189 void yaz_add_srw_diagnostic(ODR o, Z_SRW_diagnostic **d,
190 int *num, int code, const char *addinfo)
194 sprintf(uri, "info:srw/diagnostic/1/%d", code);
195 yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
199 void yaz_add_sru_update_diagnostic(ODR o, Z_SRW_diagnostic **d,
200 int *num, int code, const char *addinfo)
204 sprintf(uri, "info:srw/diagnostic/12/%d", code);
205 yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
209 void yaz_mk_sru_surrogate(ODR o, Z_SRW_record *record, int pos,
210 int code, const char *details)
212 const char *message = yaz_diag_srw_str(code);
215 len += strlen(message);
217 len += strlen(details);
219 record->recordData_buf = (char *) odr_malloc(o, len);
221 sprintf(record->recordData_buf, "<diagnostic "
222 "xmlns=\"http://www.loc.gov/zing/srw/diagnostic/\">\n"
223 " <uri>info:srw/diagnostic/1/%d</uri>\n", code);
225 sprintf(record->recordData_buf + strlen(record->recordData_buf),
226 " <details>%s</details>\n", details);
228 sprintf(record->recordData_buf + strlen(record->recordData_buf),
229 " <message>%s</message>\n", message);
230 sprintf(record->recordData_buf + strlen(record->recordData_buf),
232 record->recordData_len = strlen(record->recordData_buf);
233 record->recordPosition = odr_intdup(o, pos);
234 record->recordSchema = "info:srw/schema/1/diagnostics-v1.1";
237 static void grab_charset(ODR o, const char *content_type, char **charset)
241 const char *charset_p = 0;
242 if (content_type && (charset_p = strstr(content_type, "; charset=")))
246 while (i < 20 && charset_p[i] &&
247 !strchr("; \n\r", charset_p[i]))
249 *charset = (char*) odr_malloc(o, i+1);
250 memcpy(*charset, charset_p, i);
251 (*charset)[i] = '\0';
256 int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
257 Z_SOAP **soap_package, ODR decode, char **charset)
259 if (!strcmp(hreq->method, "POST"))
261 const char *content_type = z_HTTP_header_lookup(hreq->headers,
264 (!yaz_strcmp_del("text/xml", content_type, "; ") ||
265 !yaz_strcmp_del("application/soap+xml", content_type, "; ") ||
266 !yaz_strcmp_del("text/plain", content_type, "; ")))
268 char *db = "Default";
269 const char *p0 = hreq->path, *p1;
272 static Z_SOAP_Handler soap_handlers[5] = {
274 { YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec },
275 { YAZ_XMLNS_SRU_v1_0, 0, (Z_SOAP_fun) yaz_srw_codec },
276 { YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec },
277 { YAZ_XMLNS_SRU_v2_mask, 0, (Z_SOAP_fun) yaz_srw_codec },
284 p1 = strchr(p0, '?');
286 p1 = p0 + strlen(p0);
288 db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);
289 grab_charset(decode, content_type, charset);
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 Z_SRW_extra_arg **l = &extra_args;
487 *l = (Z_SRW_extra_arg *) odr_malloc(decode, sizeof(**l));
488 (*l)->name = odr_strdup(decode, n);
489 (*l)->value = odr_strdup(decode, v);
495 yaz_add_srw_diagnostic(decode, diag, num_diag,
496 YAZ_SRW_UNSUPP_PARAMETER, n);
503 operation = "searchRetrieve";
507 version = yaz_negotiate_sru_version(version);
510 { /* negotiation failed. */
511 yaz_add_srw_diagnostic(decode, diag, num_diag,
512 YAZ_SRW_UNSUPP_VERSION, "2.0");
518 yaz_add_srw_diagnostic(
519 decode, diag, num_diag,
520 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "operation");
521 operation = "explain";
523 if (strcmp(version, "2.0"))
525 if (recordXMLEscaping)
527 yaz_add_srw_diagnostic(decode, diag, num_diag,
528 YAZ_SRW_UNSUPP_PARAMETER,
529 "recordXMLEscaping");
532 recordXMLEscaping = recordPacking;
533 recordPacking = "packed";
535 if (!recordXMLEscaping)
536 recordXMLEscaping = "xml";
537 if (!strcmp(operation, "searchRetrieve"))
539 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
541 sr->srw_version = version;
542 sr->extra_args = extra_args;
544 yaz_srw_decodeauth(sr, hreq, username, password, decode);
546 sr->u.request->queryType = queryType;
547 sr->u.request->query = query;
550 yaz_add_srw_diagnostic(
551 decode, diag, num_diag,
552 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "query");
556 sr->u.request->sort_type = Z_SRW_sort_type_sort;
557 sr->u.request->sort.sortKeys = sortKeys;
559 sr->u.request->recordXPath = recordXPath;
560 sr->u.request->recordSchema = recordSchema;
561 sr->u.request->recordPacking = recordXMLEscaping;
562 sr->u.request->packing = recordPacking;
563 sr->u.request->stylesheet = stylesheet;
564 yaz_sru_facet_request(decode , &sr->u.request->facetList,
565 &facetLimit, &facetStart, &facetSort);
567 yaz_sru_decode_integer(decode, "maximumRecords", maximumRecords,
568 &sr->u.request->maximumRecords,
571 yaz_sru_decode_integer(decode, "startRecord", startRecord,
572 &sr->u.request->startRecord,
575 sr->u.request->database = db;
577 (*soap_package) = (Z_SOAP *)
578 odr_malloc(decode, sizeof(**soap_package));
579 (*soap_package)->which = Z_SOAP_generic;
581 (*soap_package)->u.generic = (Z_SOAP_Generic *)
582 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
584 (*soap_package)->u.generic->p = sr;
585 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
586 (*soap_package)->u.generic->no = 0;
588 (*soap_package)->ns = "SRU";
592 else if (!strcmp(operation, "explain"))
594 /* Transfer SRU explain parameters to common struct */
595 /* http://www.loc.gov/z3950/agency/zing/srw/explain.html */
596 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
598 sr->srw_version = version;
599 sr->extra_args = extra_args;
600 yaz_srw_decodeauth(sr, hreq, username, password, decode);
602 sr->u.explain_request->recordPacking = recordXMLEscaping;
603 sr->u.explain_request->packing = recordPacking;
604 sr->u.explain_request->database = db;
606 sr->u.explain_request->stylesheet = stylesheet;
608 (*soap_package) = (Z_SOAP *)
609 odr_malloc(decode, sizeof(**soap_package));
610 (*soap_package)->which = Z_SOAP_generic;
612 (*soap_package)->u.generic = (Z_SOAP_Generic *)
613 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
615 (*soap_package)->u.generic->p = sr;
616 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
617 (*soap_package)->u.generic->no = 0;
619 (*soap_package)->ns = "SRU";
623 else if (!strcmp(operation, "scan"))
625 /* Transfer SRU scan parameters to common struct */
626 /* http://www.loc.gov/z3950/agency/zing/srw/scan.html */
627 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_scan_request);
629 sr->srw_version = version;
630 sr->extra_args = extra_args;
632 yaz_srw_decodeauth(sr, hreq, username, password, decode);
634 sr->u.scan_request->queryType = queryType;
635 sr->u.scan_request->scanClause = scanClause;
638 yaz_add_srw_diagnostic(
639 decode, diag, num_diag,
640 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "scanClause");
641 sr->u.scan_request->database = db;
643 yaz_sru_decode_integer(decode, "maximumTerms",
645 &sr->u.scan_request->maximumTerms,
648 yaz_sru_decode_integer(decode, "responsePosition",
650 &sr->u.scan_request->responsePosition,
653 sr->u.scan_request->stylesheet = stylesheet;
655 (*soap_package) = (Z_SOAP *)
656 odr_malloc(decode, sizeof(**soap_package));
657 (*soap_package)->which = Z_SOAP_generic;
659 (*soap_package)->u.generic = (Z_SOAP_Generic *)
660 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
662 (*soap_package)->u.generic->p = sr;
663 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
664 (*soap_package)->u.generic->no = 0;
666 (*soap_package)->ns = "SRU";
672 /* unsupported operation ... */
673 /* Act as if we received a explain request and throw diagnostic. */
675 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
677 sr->srw_version = version;
679 sr->u.explain_request->recordPacking = recordPacking;
680 sr->u.explain_request->database = db;
682 sr->u.explain_request->stylesheet = stylesheet;
684 (*soap_package) = (Z_SOAP *)
685 odr_malloc(decode, sizeof(**soap_package));
686 (*soap_package)->which = Z_SOAP_generic;
688 (*soap_package)->u.generic = (Z_SOAP_Generic *)
689 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
691 (*soap_package)->u.generic->p = sr;
692 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
693 (*soap_package)->u.generic->no = 0;
695 (*soap_package)->ns = "SRU";
697 yaz_add_srw_diagnostic(decode, diag, num_diag,
698 YAZ_SRW_UNSUPP_OPERATION, operation);
708 Z_SRW_extra_record *yaz_srw_get_extra_record(ODR o)
710 Z_SRW_extra_record *res = (Z_SRW_extra_record *)
711 odr_malloc(o, sizeof(*res));
713 res->extraRecordData_buf = 0;
714 res->extraRecordData_len = 0;
715 res->recordIdentifier = 0;
720 Z_SRW_record *yaz_srw_get_records(ODR o, int n)
722 Z_SRW_record *res = (Z_SRW_record *) odr_malloc(o, n * sizeof(*res));
725 for (i = 0; i<n; i++)
727 res[i].recordSchema = 0;
728 res[i].recordPacking = Z_SRW_recordPacking_string;
729 res[i].recordData_buf = 0;
730 res[i].recordData_len = 0;
731 res[i].recordPosition = 0;
736 Z_SRW_record *yaz_srw_get_record(ODR o)
738 return yaz_srw_get_records(o, 1);
741 static Z_SRW_PDU *yaz_srw_get_core_ver(ODR o, const char *version)
743 Z_SRW_PDU *p = (Z_SRW_PDU *) odr_malloc(o, sizeof(*p));
744 p->srw_version = odr_strdup(o, version);
748 p->extraResponseData_buf = 0;
749 p->extraResponseData_len = 0;
753 Z_SRW_PDU *yaz_srw_get_core_v_2_0(ODR o)
755 return yaz_srw_get_core_ver(o, "2.0");
758 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
760 return yaz_srw_get_pdu(o, which, "2.0");
763 Z_SRW_PDU *yaz_srw_get_pdu(ODR o, int which, const char *version)
765 Z_SRW_PDU *sr = yaz_srw_get_core_ver(o, version);
770 case Z_SRW_searchRetrieve_request:
771 sr->u.request = (Z_SRW_searchRetrieveRequest *)
772 odr_malloc(o, sizeof(*sr->u.request));
773 sr->u.request->queryType = "cql";
774 sr->u.request->query = 0;
775 sr->u.request->sort_type = Z_SRW_sort_type_none;
776 sr->u.request->sort.none = 0;
777 sr->u.request->startRecord = 0;
778 sr->u.request->maximumRecords = 0;
779 sr->u.request->recordSchema = 0;
780 sr->u.request->recordPacking = 0;
781 sr->u.request->packing = 0;
782 sr->u.request->recordXPath = 0;
783 sr->u.request->database = 0;
784 sr->u.request->resultSetTTL = 0;
785 sr->u.request->stylesheet = 0;
786 sr->u.request->facetList = 0;
788 case Z_SRW_searchRetrieve_response:
789 sr->u.response = (Z_SRW_searchRetrieveResponse *)
790 odr_malloc(o, sizeof(*sr->u.response));
791 sr->u.response->numberOfRecords = 0;
792 sr->u.response->resultCountPrecision = 0;
793 sr->u.response->resultSetId = 0;
794 sr->u.response->resultSetIdleTime = 0;
795 sr->u.response->records = 0;
796 sr->u.response->num_records = 0;
797 sr->u.response->diagnostics = 0;
798 sr->u.response->num_diagnostics = 0;
799 sr->u.response->nextRecordPosition = 0;
800 sr->u.response->extra_records = 0;
801 sr->u.response->facetList = 0;
802 sr->u.response->suggestions = 0;
804 case Z_SRW_explain_request:
805 sr->u.explain_request = (Z_SRW_explainRequest *)
806 odr_malloc(o, sizeof(*sr->u.explain_request));
807 sr->u.explain_request->recordPacking = 0;
808 sr->u.explain_request->packing = 0;
809 sr->u.explain_request->database = 0;
810 sr->u.explain_request->stylesheet = 0;
812 case Z_SRW_explain_response:
813 sr->u.explain_response = (Z_SRW_explainResponse *)
814 odr_malloc(o, sizeof(*sr->u.explain_response));
815 sr->u.explain_response->record.recordData_buf = 0;
816 sr->u.explain_response->record.recordData_len = 0;
817 sr->u.explain_response->record.recordSchema = 0;
818 sr->u.explain_response->record.recordPosition = 0;
819 sr->u.explain_response->record.recordPacking =
820 Z_SRW_recordPacking_string;
821 sr->u.explain_response->diagnostics = 0;
822 sr->u.explain_response->num_diagnostics = 0;
823 sr->u.explain_response->extra_record = 0;
825 case Z_SRW_scan_request:
826 sr->u.scan_request = (Z_SRW_scanRequest *)
827 odr_malloc(o, sizeof(*sr->u.scan_request));
828 sr->u.scan_request->database = 0;
829 sr->u.scan_request->stylesheet = 0;
830 sr->u.scan_request->maximumTerms = 0;
831 sr->u.scan_request->responsePosition = 0;
832 sr->u.scan_request->queryType = "cql";
833 sr->u.scan_request->scanClause = 0;
835 case Z_SRW_scan_response:
836 sr->u.scan_response = (Z_SRW_scanResponse *)
837 odr_malloc(o, sizeof(*sr->u.scan_response));
838 sr->u.scan_response->terms = 0;
839 sr->u.scan_response->num_terms = 0;
840 sr->u.scan_response->diagnostics = 0;
841 sr->u.scan_response->num_diagnostics = 0;
843 case Z_SRW_update_request:
844 sr->u.update_request = (Z_SRW_updateRequest *)
845 odr_malloc(o, sizeof(*sr->u.update_request));
846 sr->u.update_request->database = 0;
847 sr->u.update_request->stylesheet = 0;
848 sr->u.update_request->record = 0;
849 sr->u.update_request->recordId = 0;
850 sr->u.update_request->recordVersions = 0;
851 sr->u.update_request->num_recordVersions = 0;
852 sr->u.update_request->extra_record = 0;
853 sr->u.update_request->extraRequestData_buf = 0;
854 sr->u.update_request->extraRequestData_len = 0;
855 sr->u.request->database = 0;
857 case Z_SRW_update_response:
858 sr->u.update_response = (Z_SRW_updateResponse *)
859 odr_malloc(o, sizeof(*sr->u.update_response));
860 sr->u.update_response->operationStatus = 0;
861 sr->u.update_response->recordId = 0;
862 sr->u.update_response->recordVersions = 0;
863 sr->u.update_response->num_recordVersions = 0;
864 sr->u.update_response->record = 0;
865 sr->u.update_response->extra_record = 0;
866 sr->u.update_response->extraResponseData_buf = 0;
867 sr->u.update_response->extraResponseData_len = 0;
868 sr->u.update_response->diagnostics = 0;
869 sr->u.update_response->num_diagnostics = 0;
874 void yaz_add_name_value_int(ODR o, char **name, char **value, int *i,
875 char *a_name, Odr_int *val)
880 value[*i] = (char *) odr_malloc(o, 40);
881 sprintf(value[*i], ODR_INT_PRINTF, *val);
886 void yaz_add_name_value_str(ODR o, char **name, char **value, int *i,
887 char *a_name, char *val)
897 static int yaz_get_sru_parms(const Z_SRW_PDU *srw_pdu, ODR encode,
898 char **name, char **value, int max_names)
900 int version2 = strcmp(srw_pdu->srw_version, "2.") > 0;
903 yaz_add_name_value_str(encode, name, value, &i, "version",
904 srw_pdu->srw_version);
905 name[i] = "operation";
906 switch (srw_pdu->which)
908 case Z_SRW_searchRetrieve_request:
909 value[i++] = "searchRetrieve";
910 queryType = srw_pdu->u.request->queryType;
913 if (queryType && strcmp(queryType, "cql"))
914 yaz_add_name_value_str(encode, name, value, &i, "queryType",
916 yaz_add_name_value_str(encode, name, value, &i, "query",
917 srw_pdu->u.request->query);
921 if (!strcmp(queryType, "cql"))
923 yaz_add_name_value_str(encode, name, value, &i, "query",
924 srw_pdu->u.request->query);
926 else if (!strcmp(queryType, "pqf"))
928 yaz_add_name_value_str(encode, name, value, &i, "x-pquery",
929 srw_pdu->u.request->query);
931 else if (!strcmp(queryType, "xcql"))
933 yaz_add_name_value_str(encode, name, value, &i, "x-cql",
934 srw_pdu->u.request->query);
937 switch (srw_pdu->u.request->sort_type)
939 case Z_SRW_sort_type_none:
941 case Z_SRW_sort_type_sort:
942 yaz_add_name_value_str(encode, name, value, &i, "sortKeys",
943 srw_pdu->u.request->sort.sortKeys);
946 yaz_add_name_value_int(encode, name, value, &i, "startRecord",
947 srw_pdu->u.request->startRecord);
948 yaz_add_name_value_int(encode, name, value, &i, "maximumRecords",
949 srw_pdu->u.request->maximumRecords);
950 yaz_add_name_value_str(encode, name, value, &i, "recordSchema",
951 srw_pdu->u.request->recordSchema);
954 yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping",
955 srw_pdu->u.request->recordPacking);
956 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
957 srw_pdu->u.request->packing);
960 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
961 srw_pdu->u.request->recordPacking);
962 yaz_add_name_value_str(encode, name, value, &i, "recordXPath",
963 srw_pdu->u.request->recordXPath);
964 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
965 srw_pdu->u.request->stylesheet);
966 yaz_add_name_value_int(encode, name, value, &i, "resultSetTTL",
967 srw_pdu->u.request->resultSetTTL);
969 const char *facetLimit = 0;
970 const char *facetStart = 0;
971 const char *facetSort = 0;
972 yaz_sru_facet_request(encode, &srw_pdu->u.request->facetList,
973 &facetLimit, &facetStart, &facetSort);
974 yaz_add_name_value_str(encode, name, value, &i, "facetLimit",
975 (char *) facetLimit);
976 yaz_add_name_value_str(encode, name, value, &i, "facetStart",
977 (char *) facetStart);
978 yaz_add_name_value_str(encode, name, value, &i, "facetSort",
982 case Z_SRW_explain_request:
983 value[i++] = "explain";
987 yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping",
988 srw_pdu->u.explain_request->recordPacking);
989 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
990 srw_pdu->u.explain_request->packing);
993 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
994 srw_pdu->u.explain_request->recordPacking);
995 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
996 srw_pdu->u.explain_request->stylesheet);
998 case Z_SRW_scan_request:
1000 queryType = srw_pdu->u.scan_request->queryType;
1003 if (queryType && strcmp(queryType, "cql"))
1004 yaz_add_name_value_str(encode, name, value, &i, "queryType",
1006 yaz_add_name_value_str(encode, name, value, &i, "scanClause",
1007 srw_pdu->u.scan_request->scanClause);
1011 if (!queryType || !strcmp(queryType, "cql"))
1012 yaz_add_name_value_str(encode, name, value, &i, "scanClause",
1013 srw_pdu->u.scan_request->scanClause);
1014 else if (!strcmp(queryType, "pqf"))
1015 yaz_add_name_value_str(encode, name, value, &i, "x-pScanClause",
1016 srw_pdu->u.scan_request->scanClause);
1017 else if (!strcmp(queryType, "xcql"))
1018 yaz_add_name_value_str(encode, name, value, &i,
1020 srw_pdu->u.scan_request->scanClause);
1022 yaz_add_name_value_int(encode, name, value, &i, "responsePosition",
1023 srw_pdu->u.scan_request->responsePosition);
1024 yaz_add_name_value_int(encode, name, value, &i, "maximumTerms",
1025 srw_pdu->u.scan_request->maximumTerms);
1026 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
1027 srw_pdu->u.scan_request->stylesheet);
1029 case Z_SRW_update_request:
1030 value[i++] = "update";
1035 if (srw_pdu->extra_args)
1037 Z_SRW_extra_arg *ea = srw_pdu->extra_args;
1038 for (; ea && i < max_names-1; ea = ea->next)
1041 value[i] = ea->value;
1050 int yaz_sru_get_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1051 ODR encode, const char *charset)
1053 char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */
1057 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1058 srw_pdu->username, srw_pdu->password);
1059 if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS))
1061 yaz_array_to_uri(&uri_args, encode, name, value);
1063 hreq->method = "GET";
1066 odr_malloc(encode, strlen(hreq->path) + strlen(uri_args) + 4);
1068 sprintf(path, "%s?%s", hreq->path, uri_args);
1071 z_HTTP_header_add_content_type(encode, &hreq->headers,
1072 "text/xml", charset);
1076 int yaz_sru_post_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1077 ODR encode, const char *charset)
1079 char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */
1082 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1083 srw_pdu->username, srw_pdu->password);
1084 if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS))
1087 yaz_array_to_uri(&uri_args, encode, name, value);
1089 hreq->method = "POST";
1091 hreq->content_buf = uri_args;
1092 hreq->content_len = strlen(uri_args);
1094 z_HTTP_header_add_content_type(encode, &hreq->headers,
1095 "application/x-www-form-urlencoded",
1100 int yaz_sru_soap_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1101 ODR odr, const char *charset)
1103 Z_SOAP_Handler handlers[3] = {
1105 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
1106 {YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec},
1110 Z_SOAP *p = (Z_SOAP*) odr_malloc(odr, sizeof(*p));
1112 z_HTTP_header_add_basic_auth(odr, &hreq->headers,
1113 srw_pdu->username, srw_pdu->password);
1114 z_HTTP_header_add_content_type(odr,
1116 "text/xml", charset);
1118 z_HTTP_header_add(odr, &hreq->headers,
1119 "SOAPAction", "\"\"");
1120 p->which = Z_SOAP_generic;
1121 p->u.generic = (Z_SOAP_Generic *) odr_malloc(odr, sizeof(*p->u.generic));
1122 p->u.generic->no = 0;
1123 p->u.generic->ns = 0;
1124 p->u.generic->p = srw_pdu;
1125 p->ns = "http://schemas.xmlsoap.org/soap/envelope/";
1128 if (srw_pdu->which == Z_SRW_update_request ||
1129 srw_pdu->which == Z_SRW_update_response)
1130 p->u.generic->no = 1; /* second handler */
1132 return z_soap_codec_enc(odr, &p,
1134 &hreq->content_len, handlers,
1138 Z_SRW_recordVersion *yaz_srw_get_record_versions(ODR odr, int num)
1140 Z_SRW_recordVersion *ver
1141 = (Z_SRW_recordVersion *) odr_malloc(odr,num * sizeof(*ver));
1143 for (i = 0; i < num; ++i)
1145 ver[i].versionType = 0;
1146 ver[i].versionValue = 0;
1151 const char *yaz_srw_pack_to_str(int pack)
1155 case Z_SRW_recordPacking_string:
1157 case Z_SRW_recordPacking_XML:
1159 case Z_SRW_recordPacking_URL:
1165 int yaz_srw_str_to_pack(const char *str)
1167 if (!yaz_matchstr(str, "string"))
1168 return Z_SRW_recordPacking_string;
1169 if (!yaz_matchstr(str, "xml"))
1170 return Z_SRW_recordPacking_XML;
1171 if (!yaz_matchstr(str, "url"))
1172 return Z_SRW_recordPacking_URL;
1176 void yaz_encode_sru_extra(Z_SRW_PDU *sr, ODR odr, const char *extra_args)
1182 Z_SRW_extra_arg **ea = &sr->extra_args;
1183 yaz_uri_to_array(extra_args, odr, &name, &val);
1185 /** append rather than override */
1190 *ea = (Z_SRW_extra_arg *) odr_malloc(odr, sizeof(**ea));
1191 (*ea)->name = *name;
1192 (*ea)->value = *val;
1205 * c-file-style: "Stroustrup"
1206 * indent-tabs-mode: nil
1208 * vim: shiftwidth=4 tabstop=8 expandtab