2 * Copyright (C) 1995-2005, Index Data ApS
3 * See the file LICENSE for details.
5 * $Id: srwutil.c,v 1.33 2005-11-09 17:48:11 adam Exp $
9 * \brief Implements SRW/SRU utilities.
14 #include <yaz/yaz-iconv.h>
16 static int hex_digit (int ch)
18 if (ch >= '0' && ch <= '9')
20 else if (ch >= 'a' && ch <= 'f')
22 else if (ch >= 'A' && ch <= 'F')
27 int yaz_uri_array(const char *path, ODR o, char ***name, char ***val)
37 while ((cp = strchr(cp, '&')))
42 *name = odr_malloc(o, no * sizeof(char*));
43 *val = odr_malloc(o, no * sizeof(char*));
45 for (no = 0; *path; no++)
47 const char *p1 = strchr(path, '=');
53 (*name)[no] = odr_malloc(o, (p1-path)+1);
54 memcpy((*name)[no], path, p1-path);
55 (*name)[no][p1-path] = '\0';
58 p1 = strchr(path, '&');
60 p1 = strlen(path) + path;
61 (*val)[no] = ret = odr_malloc(o, p1 - path + 1);
62 while (*path && *path != '&')
69 else if (*path == '%' && path[1] && path[2])
71 ret[i++] = hex_digit (path[1])*16 + hex_digit (path[2]);
87 char *yaz_uri_val(const char *path, const char *name, ODR o)
89 size_t nlen = strlen(name);
95 const char *p1 = strchr(path, '=');
98 if ((size_t)(p1 - path) == nlen && !memcmp(path, name, nlen))
104 p1 = strchr(path, '&');
106 p1 = strlen(path) + path;
107 ret = (char *) odr_malloc(o, p1 - path + 1);
108 while (*path && *path != '&')
115 else if (*path == '%' && path[1] && path[2])
117 ret[i++] = hex_digit (path[1])*16 + hex_digit (path[2]);
126 path = strchr(p1, '&');
133 void yaz_uri_val_int(const char *path, const char *name, ODR o, int **intp)
135 const char *v = yaz_uri_val(path, name, o);
137 *intp = odr_intdup(o, atoi(v));
140 void yaz_mk_std_diagnostic(ODR o, Z_SRW_diagnostic *d,
141 int code, const char *details)
143 d->uri = (char *) odr_malloc(o, 50);
144 sprintf(d->uri, "info:srw/diagnostic/1/%d", code);
147 d->details = odr_strdup(o, details);
152 void yaz_add_srw_diagnostic(ODR o, Z_SRW_diagnostic **d,
153 int *num, int code, const char *addinfo)
155 Z_SRW_diagnostic *d_new;
156 d_new = (Z_SRW_diagnostic *) odr_malloc (o, (*num + 1)* sizeof(**d));
158 memcpy (d_new, *d, *num *sizeof(**d));
161 yaz_mk_std_diagnostic(o, *d + *num, code, addinfo);
165 int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
166 Z_SOAP **soap_package, ODR decode, char **charset)
168 if (!strcmp(hreq->method, "POST"))
170 const char *content_type = z_HTTP_header_lookup(hreq->headers,
173 (!yaz_strcmp_del("text/xml", content_type, "; ") ||
174 !yaz_strcmp_del("text/plain", content_type, "; ")))
176 char *db = "Default";
177 const char *p0 = hreq->path, *p1;
179 const char *charset_p = 0;
181 static Z_SOAP_Handler soap_handlers[4] = {
183 {"http://www.loc.gov/zing/srw/", 0,
184 (Z_SOAP_fun) yaz_srw_codec},
185 {"http://www.loc.gov/zing/srw/v1.0/", 0,
186 (Z_SOAP_fun) yaz_srw_codec},
187 {"http://www.loc.gov/zing/srw/update/", 0,
188 (Z_SOAP_fun) yaz_ucp_codec},
195 p1 = strchr(p0, '?');
197 p1 = p0 + strlen(p0);
200 db = (char*) odr_malloc(decode, p1 - p0 + 1);
201 memcpy (db, p0, p1 - p0);
205 if (charset && (charset_p = strstr(content_type, "; charset=")))
209 while (i < 20 && charset_p[i] &&
210 !strchr("; \n\r", charset_p[i]))
212 *charset = (char*) odr_malloc(decode, i+1);
213 memcpy(*charset, charset_p, i);
214 (*charset)[i] = '\0';
216 ret = z_soap_codec(decode, soap_package,
217 &hreq->content_buf, &hreq->content_len,
219 if (ret == 0 && (*soap_package)->which == Z_SOAP_generic)
221 *srw_pdu = (Z_SRW_PDU*) (*soap_package)->u.generic->p;
223 if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request &&
224 (*srw_pdu)->u.request->database == 0)
225 (*srw_pdu)->u.request->database = db;
227 if ((*srw_pdu)->which == Z_SRW_explain_request &&
228 (*srw_pdu)->u.explain_request->database == 0)
229 (*srw_pdu)->u.explain_request->database = db;
231 if ((*srw_pdu)->which == Z_SRW_scan_request &&
232 (*srw_pdu)->u.scan_request->database == 0)
233 (*srw_pdu)->u.scan_request->database = db;
235 if ((*srw_pdu)->which == Z_SRW_update_request &&
236 (*srw_pdu)->u.update_request->database == 0)
237 (*srw_pdu)->u.update_request->database = db;
248 http://www.loc.gov/z3950/agency/zing/srw/service.html
250 int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
251 Z_SOAP **soap_package, ODR decode, char **charset,
252 Z_SRW_diagnostic **diag, int *num_diag)
255 static Z_SOAP_Handler soap_handlers[2] = {
256 {"http://www.loc.gov/zing/srw/", 0,
257 (Z_SOAP_fun) yaz_srw_codec},
261 const char *content_type = z_HTTP_header_lookup(hreq->headers,
264 SRU GET: allow any content type.
265 SRU POST: we support "application/x-www-form-urlencoded";
266 not "multipart/form-data" .
268 if (!strcmp(hreq->method, "GET")
270 (!strcmp(hreq->method, "POST")
272 !yaz_strcmp_del("application/x-www-form-urlencoded",
277 char *db = "Default";
278 const char *p0 = hreq->path, *p1;
280 const char *operation = 0;
285 char *stylesheet = 0;
286 char *scanClause = 0;
287 char *pScanClause = 0;
288 char *recordXPath = 0;
289 char *recordSchema = 0;
290 char *recordPacking = "xml"; /* xml packing is default for SRU */
291 char *maximumRecords = 0;
292 char *startRecord = 0;
293 char *maximumTerms = 0;
294 char *responsePosition = 0;
295 char *extraRequestData = 0;
304 p1 = strchr(p0, '?');
306 p1 = p0 + strlen(p0);
309 db = (char*) odr_malloc(decode, p1 - p0 + 1);
310 memcpy (db, p0, p1 - p0);
313 if (!strcmp(hreq->method, "POST"))
314 p1 = hreq->content_buf;
315 yaz_uri_array(p1, decode, &uri_name, &uri_val);
320 for (i = 0; uri_name[i]; i++)
322 char *n = uri_name[i];
323 char *v = uri_val[i];
324 if (!strcmp(n, "query"))
326 else if (!strcmp(n, "x-pquery"))
328 else if (!strcmp(n, "operation"))
330 else if (!strcmp(n, "stylesheet"))
332 else if (!strcmp(n, "sortKeys"))
334 else if (!strcmp(n, "recordXPath"))
336 else if (!strcmp(n, "recordSchema"))
338 else if (!strcmp(n, "recordPacking"))
340 else if (!strcmp(n, "version"))
342 else if (!strcmp(n, "scanClause"))
344 else if (!strcmp(n, "x-pScanClause"))
346 else if (!strcmp(n, "maximumRecords"))
348 else if (!strcmp(n, "startRecord"))
350 else if (!strcmp(n, "maximumTerms"))
352 else if (!strcmp(n, "responsePosition"))
353 responsePosition = v;
354 else if (!strcmp(n, "extraRequestData"))
355 extraRequestData = v;
357 yaz_add_srw_diagnostic(decode, diag, num_diag, 8, n);
363 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "version");
366 if (strcmp(version, "1.1"))
367 yaz_add_srw_diagnostic(decode, diag, num_diag, 5, "1.1");
371 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "operation");
372 operation = "explain";
374 if (!strcmp(operation, "searchRetrieve"))
376 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
378 sr->srw_version = version;
382 sr->u.request->query_type = Z_SRW_query_type_cql;
383 sr->u.request->query.cql = query;
387 sr->u.request->query_type = Z_SRW_query_type_pqf;
388 sr->u.request->query.pqf = pQuery;
391 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "query");
395 sr->u.request->sort_type = Z_SRW_sort_type_sort;
396 sr->u.request->sort.sortKeys = sortKeys;
398 sr->u.request->recordXPath = recordXPath;
399 sr->u.request->recordSchema = recordSchema;
400 sr->u.request->recordPacking = recordPacking;
401 sr->u.request->stylesheet = stylesheet;
404 sr->u.request->maximumRecords =
405 odr_intdup(decode, atoi(maximumRecords));
407 sr->u.request->startRecord =
408 odr_intdup(decode, atoi(startRecord));
410 sr->u.request->database = db;
412 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
413 (*soap_package)->which = Z_SOAP_generic;
415 (*soap_package)->u.generic =
416 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
418 (*soap_package)->u.generic->p = sr;
419 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
420 (*soap_package)->u.generic->no = 0;
422 (*soap_package)->ns = "SRU";
426 else if (!strcmp(operation, "explain"))
428 /* Transfer SRU explain parameters to common struct */
429 /* http://www.loc.gov/z3950/agency/zing/srw/explain.html */
430 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
432 sr->srw_version = version;
434 sr->u.explain_request->recordPacking = recordPacking;
435 sr->u.explain_request->database = db;
437 sr->u.explain_request->stylesheet = stylesheet;
439 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
440 (*soap_package)->which = Z_SOAP_generic;
442 (*soap_package)->u.generic =
443 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
445 (*soap_package)->u.generic->p = sr;
446 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
447 (*soap_package)->u.generic->no = 0;
449 (*soap_package)->ns = "SRU";
453 else if (!strcmp(operation, "scan"))
455 /* Transfer SRU scan parameters to common struct */
456 /* http://www.loc.gov/z3950/agency/zing/srw/scan.html */
457 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_scan_request);
459 sr->srw_version = version;
464 sr->u.scan_request->query_type = Z_SRW_query_type_cql;
465 sr->u.scan_request->scanClause.cql = scanClause;
467 else if (pScanClause)
469 sr->u.scan_request->query_type = Z_SRW_query_type_pqf;
470 sr->u.scan_request->scanClause.pqf = pScanClause;
473 yaz_add_srw_diagnostic(decode, diag, num_diag, 7,
475 sr->u.scan_request->database = db;
478 sr->u.scan_request->maximumTerms =
479 odr_intdup(decode, atoi(maximumTerms));
480 if (responsePosition)
481 sr->u.scan_request->responsePosition =
482 odr_intdup(decode, atoi(responsePosition));
484 sr->u.scan_request->stylesheet = stylesheet;
486 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
487 (*soap_package)->which = Z_SOAP_generic;
489 (*soap_package)->u.generic =
490 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
492 (*soap_package)->u.generic->p = sr;
493 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
494 (*soap_package)->u.generic->no = 0;
496 (*soap_package)->ns = "SRU";
502 /* unsupported operation ... */
503 /* Act as if we received a explain request and throw diagnostic. */
505 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
507 sr->srw_version = version;
509 sr->u.explain_request->recordPacking = recordPacking;
510 sr->u.explain_request->database = db;
512 sr->u.explain_request->stylesheet = stylesheet;
514 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
515 (*soap_package)->which = Z_SOAP_generic;
517 (*soap_package)->u.generic =
518 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
520 (*soap_package)->u.generic->p = sr;
521 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
522 (*soap_package)->u.generic->no = 0;
524 (*soap_package)->ns = "SRU";
526 yaz_add_srw_diagnostic(decode, diag, num_diag, 4, operation);
535 Z_SRW_extra_record *yaz_srw_get_extra_record(ODR o)
537 Z_SRW_extra_record *res = (Z_SRW_extra_record *)
538 odr_malloc(o, sizeof(*res));
540 res->recordReviewCode = 0;
541 res->recordReviewNote = 0;
543 res->nonDupRecordId = 0;
544 res->recordLockStatus = 0;
545 res->recordOldVersion = 0;
549 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
551 Z_SRW_PDU *sr = (Z_SRW_PDU *) odr_malloc(o, sizeof(*o));
553 sr->srw_version = odr_strdup(o, "1.1");
557 case Z_SRW_searchRetrieve_request:
558 sr->u.request = (Z_SRW_searchRetrieveRequest *)
559 odr_malloc(o, sizeof(*sr->u.request));
560 sr->u.request->query_type = Z_SRW_query_type_cql;
561 sr->u.request->query.cql = 0;
562 sr->u.request->sort_type = Z_SRW_sort_type_none;
563 sr->u.request->sort.none = 0;
564 sr->u.request->startRecord = 0;
565 sr->u.request->maximumRecords = 0;
566 sr->u.request->recordSchema = 0;
567 sr->u.request->recordPacking = 0;
568 sr->u.request->recordXPath = 0;
569 sr->u.request->database = 0;
570 sr->u.request->resultSetTTL = 0;
571 sr->u.request->stylesheet = 0;
573 case Z_SRW_searchRetrieve_response:
574 sr->u.response = (Z_SRW_searchRetrieveResponse *)
575 odr_malloc(o, sizeof(*sr->u.response));
576 sr->u.response->numberOfRecords = 0;
577 sr->u.response->resultSetId = 0;
578 sr->u.response->resultSetIdleTime = 0;
579 sr->u.response->records = 0;
580 sr->u.response->num_records = 0;
581 sr->u.response->diagnostics = 0;
582 sr->u.response->num_diagnostics = 0;
583 sr->u.response->nextRecordPosition = 0;
584 sr->u.response->extra_records = 0;
586 case Z_SRW_explain_request:
587 sr->u.explain_request = (Z_SRW_explainRequest *)
588 odr_malloc(o, sizeof(*sr->u.explain_request));
589 sr->u.explain_request->recordPacking = 0;
590 sr->u.explain_request->database = 0;
591 sr->u.explain_request->stylesheet = 0;
593 case Z_SRW_explain_response:
594 sr->u.explain_response = (Z_SRW_explainResponse *)
595 odr_malloc(o, sizeof(*sr->u.explain_response));
596 sr->u.explain_response->record.recordData_buf = 0;
597 sr->u.explain_response->record.recordData_len = 0;
598 sr->u.explain_response->record.recordSchema = 0;
599 sr->u.explain_response->record.recordPosition = 0;
600 sr->u.explain_response->record.recordPacking =
601 Z_SRW_recordPacking_string;
602 sr->u.explain_response->diagnostics = 0;
603 sr->u.explain_response->num_diagnostics = 0;
604 sr->u.explain_response->extra_record = 0;
606 case Z_SRW_scan_request:
607 sr->u.scan_request = (Z_SRW_scanRequest *)
608 odr_malloc(o, sizeof(*sr->u.scan_request));
609 sr->u.scan_request->database = 0;
610 sr->u.scan_request->stylesheet = 0;
611 sr->u.scan_request->maximumTerms = 0;
612 sr->u.scan_request->responsePosition = 0;
613 sr->u.scan_request->query_type = Z_SRW_query_type_cql;
614 sr->u.scan_request->scanClause.cql = 0;
616 case Z_SRW_scan_response:
617 sr->u.scan_response = (Z_SRW_scanResponse *)
618 odr_malloc(o, sizeof(*sr->u.scan_response));
619 sr->u.scan_response->terms = 0;
620 sr->u.scan_response->num_terms = 0;
621 sr->u.scan_response->diagnostics = 0;
622 sr->u.scan_response->num_diagnostics = 0;
623 case Z_SRW_update_request:
624 sr->u.update_request = (Z_SRW_updateRequest *)
625 odr_malloc(o, sizeof(*sr->u.update_request));
626 sr->u.update_request->database = 0;
627 sr->u.update_request->stylesheet = 0;
628 sr->u.update_request->record.recordSchema = 0;
629 sr->u.update_request->record.recordPacking = Z_SRW_recordPacking_XML;
630 sr->u.update_request->recordId = 0;
631 sr->u.update_request->recordVersion = 0;
632 sr->u.update_request->recordOldVersion = 0;
633 sr->u.update_request->record.recordData_buf = 0;
634 sr->u.update_request->record.recordData_len = 0;
635 sr->u.update_request->extra_record = 0;
636 sr->u.update_request->extraRequestData = 0;
637 sr->u.request->database = 0;
639 case Z_SRW_update_response:
640 sr->u.update_response = (Z_SRW_updateResponse *)
641 odr_malloc(o, sizeof(*sr->u.update_response));
642 sr->u.update_response->operationStatus = 0;
643 sr->u.update_response->recordId = 0;
644 sr->u.update_response->recordVersion = 0;
645 sr->u.update_response->recordChecksum = 0;
646 sr->u.update_response->record.recordData_buf = 0;
647 sr->u.update_response->record.recordData_len = 0;
648 sr->u.update_response->record.recordSchema = 0;
649 sr->u.update_response->record.recordPacking =
650 Z_SRW_recordPacking_XML;
651 sr->u.update_response->extra_record = 0;
652 sr->u.update_response->extraResponseData = 0;
653 sr->u.update_response->diagnostics = 0;
654 sr->u.update_response->num_diagnostics = 0;
660 static int srw_bib1_map[] = {
670 108, 10, /* Malformed query : Syntax error */
700 100, 1, /* bad map */
748 205, 1, /* bad map */
749 206, 1, /* bad map */
751 208, 1, /* bad map */
762 218, 1, /* bad map */
763 219, 1, /* bad map */
764 220, 1, /* bad map */
765 221, 1, /* bad map */
767 223, 1, /* bad map */
768 224, 1, /* bad map */
769 225, 1, /* bad map */
770 226, 1, /* bad map */
772 228, 1, /* bad map */
777 233, 1, /* bad map */
778 234, 1, /* bad map */
784 240, 1, /* bad map */
785 241, 1, /* bad map */
787 243, 1, /* bad map */
792 1001, 1, /* bad map */
793 1002, 1, /* bad map */
794 1003, 1, /* bad map */
795 1004, 1, /* bad map */
796 1005, 1, /* bad map */
797 1006, 1, /* bad map */
829 int yaz_diag_bib1_to_srw (int code)
831 const int *p = srw_bib1_map;
841 int yaz_diag_srw_to_bib1(int code)
843 const int *p = srw_bib1_map;
856 * indent-tabs-mode: nil
858 * vim: shiftwidth=4 tabstop=8 expandtab