2 * Copyright (C) 1995-2005, Index Data ApS
3 * See the file LICENSE for details.
5 * $Id: srwutil.c,v 1.28 2005-06-25 15:46:05 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)
36 while ((cp = strchr(cp, '&')))
41 *name = odr_malloc(o, no * sizeof(char**));
42 *val = odr_malloc(o, no * sizeof(char**));
44 for (no = 0; *path; no++)
46 const char *p1 = strchr(path, '=');
52 (*name)[no] = odr_malloc(o, (p1-path)+1);
53 memcpy((*name)[no], path, p1-path);
54 (*name)[no][p1-path] = '\0';
57 p1 = strchr(path, '&');
59 p1 = strlen(path) + path;
60 (*val)[no] = ret = odr_malloc(o, p1 - path + 1);
61 while (*path && *path != '&')
68 else if (*path == '%' && path[1] && path[2])
70 ret[i++] = hex_digit (path[1])*16 + hex_digit (path[2]);
86 char *yaz_uri_val(const char *path, const char *name, ODR o)
88 size_t nlen = strlen(name);
94 const char *p1 = strchr(path, '=');
97 if ((size_t)(p1 - path) == nlen && !memcmp(path, name, nlen))
103 p1 = strchr(path, '&');
105 p1 = strlen(path) + path;
106 ret = (char *) odr_malloc(o, p1 - path + 1);
107 while (*path && *path != '&')
114 else if (*path == '%' && path[1] && path[2])
116 ret[i++] = hex_digit (path[1])*16 + hex_digit (path[2]);
125 path = strchr(p1, '&');
132 void yaz_uri_val_int(const char *path, const char *name, ODR o, int **intp)
134 const char *v = yaz_uri_val(path, name, o);
136 *intp = odr_intdup(o, atoi(v));
139 void yaz_mk_std_diagnostic(ODR o, Z_SRW_diagnostic *d,
140 int code, const char *details)
142 d->uri = (char *) odr_malloc(o, 50);
143 sprintf(d->uri, "info:srw/diagnostic/1/%d", code);
146 d->details = odr_strdup(o, details);
151 void yaz_add_srw_diagnostic(ODR o, Z_SRW_diagnostic **d,
152 int *num, int code, const char *addinfo)
154 Z_SRW_diagnostic *d_new;
155 d_new = (Z_SRW_diagnostic *) odr_malloc (o, (*num + 1)* sizeof(**d));
157 memcpy (d_new, *d, *num *sizeof(**d));
160 yaz_mk_std_diagnostic(o, *d + *num, code, addinfo);
164 int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
165 Z_SOAP **soap_package, ODR decode, char **charset)
167 if (!strcmp(hreq->method, "POST"))
169 const char *content_type = z_HTTP_header_lookup(hreq->headers,
172 (!yaz_strcmp_del("text/xml", content_type, "; ") ||
173 !yaz_strcmp_del("text/plain", content_type, "; ")))
175 char *db = "Default";
176 const char *p0 = hreq->path, *p1;
178 const char *charset_p = 0;
180 static Z_SOAP_Handler soap_handlers[3] = {
182 {"http://www.loc.gov/zing/srw/", 0,
183 (Z_SOAP_fun) yaz_srw_codec},
184 {"http://www.loc.gov/zing/srw/v1.0/", 0,
185 (Z_SOAP_fun) yaz_srw_codec},
192 p1 = strchr(p0, '?');
194 p1 = p0 + strlen(p0);
197 db = (char*) odr_malloc(decode, p1 - p0 + 1);
198 memcpy (db, p0, p1 - p0);
202 if (charset && (charset_p = strstr(content_type, "; charset=")))
206 while (i < 20 && charset_p[i] &&
207 !strchr("; \n\r", charset_p[i]))
209 *charset = (char*) odr_malloc(decode, i+1);
210 memcpy(*charset, charset_p, i);
211 (*charset)[i] = '\0';
213 ret = z_soap_codec(decode, soap_package,
214 &hreq->content_buf, &hreq->content_len,
216 if (ret == 0 && (*soap_package)->which == Z_SOAP_generic)
218 *srw_pdu = (Z_SRW_PDU*) (*soap_package)->u.generic->p;
220 if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request &&
221 (*srw_pdu)->u.request->database == 0)
222 (*srw_pdu)->u.request->database = db;
224 if ((*srw_pdu)->which == Z_SRW_explain_request &&
225 (*srw_pdu)->u.explain_request->database == 0)
226 (*srw_pdu)->u.explain_request->database = db;
228 if ((*srw_pdu)->which == Z_SRW_scan_request &&
229 (*srw_pdu)->u.scan_request->database == 0)
230 (*srw_pdu)->u.scan_request->database = db;
241 http://www.loc.gov/z3950/agency/zing/srw/service.html
243 int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
244 Z_SOAP **soap_package, ODR decode, char **charset,
245 Z_SRW_diagnostic **diag, int *num_diag)
248 static Z_SOAP_Handler soap_handlers[2] = {
249 {"http://www.loc.gov/zing/srw/", 0,
250 (Z_SOAP_fun) yaz_srw_codec},
254 if (!strcmp(hreq->method, "GET"))
256 char *db = "Default";
257 const char *p0 = hreq->path, *p1;
259 const char *operation = 0;
264 char *stylesheet = 0;
265 char *scanClause = 0;
266 char *pScanClause = 0;
267 char *recordXPath = 0;
268 char *recordSchema = 0;
269 char *recordPacking = "xml"; /* xml packing is default for SRU */
270 char *maximumRecords = 0;
271 char *startRecord = 0;
272 char *maximumTerms = 0;
273 char *responsePosition = 0;
274 char *extraRequestData = 0;
283 p1 = strchr(p0, '?');
285 p1 = p0 + strlen(p0);
288 db = (char*) odr_malloc(decode, p1 - p0 + 1);
289 memcpy (db, p0, p1 - p0);
292 yaz_uri_array(p1, decode, &uri_name, &uri_val);
297 for (i = 0; uri_name[i]; i++)
299 char *n = uri_name[i];
300 char *v = uri_val[i];
301 if (!strcmp(n, "query"))
303 else if (!strcmp(n, "x-pquery"))
305 else if (!strcmp(n, "operation"))
307 else if (!strcmp(n, "stylesheet"))
309 else if (!strcmp(n, "sortKeys"))
311 else if (!strcmp(n, "recordXPath"))
313 else if (!strcmp(n, "recordSchema"))
315 else if (!strcmp(n, "recordPacking"))
317 else if (!strcmp(n, "version"))
319 else if (!strcmp(n, "scanClause"))
321 else if (!strcmp(n, "x-pScanClause"))
323 else if (!strcmp(n, "maximumRecords"))
325 else if (!strcmp(n, "startRecord"))
327 else if (!strcmp(n, "maximumTerms"))
329 else if (!strcmp(n, "responsePosition"))
330 responsePosition = v;
331 else if (!strcmp(n, "extraRequestData"))
332 extraRequestData = v;
334 yaz_add_srw_diagnostic(decode, diag, num_diag, 8, n);
340 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "version");
343 if (strcmp(version, "1.1"))
344 yaz_add_srw_diagnostic(decode, diag, num_diag, 5, "1.1");
348 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "operation");
349 operation = "explain";
351 if (!strcmp(operation, "searchRetrieve"))
353 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
355 sr->srw_version = version;
359 sr->u.request->query_type = Z_SRW_query_type_cql;
360 sr->u.request->query.cql = query;
364 sr->u.request->query_type = Z_SRW_query_type_pqf;
365 sr->u.request->query.pqf = pQuery;
368 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "query");
372 sr->u.request->sort_type = Z_SRW_sort_type_sort;
373 sr->u.request->sort.sortKeys = sortKeys;
375 sr->u.request->recordXPath = recordXPath;
376 sr->u.request->recordSchema = recordSchema;
377 sr->u.request->recordPacking = recordPacking;
378 sr->u.request->stylesheet = stylesheet;
381 sr->u.request->maximumRecords =
382 odr_intdup(decode, atoi(maximumRecords));
384 sr->u.request->startRecord =
385 odr_intdup(decode, atoi(startRecord));
387 sr->u.request->database = db;
389 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
390 (*soap_package)->which = Z_SOAP_generic;
392 (*soap_package)->u.generic =
393 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
395 (*soap_package)->u.generic->p = sr;
396 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
397 (*soap_package)->u.generic->no = 0;
399 (*soap_package)->ns = "SRU";
403 else if (!strcmp(operation, "explain"))
405 /* Transfer SRU explain parameters to common struct */
406 /* http://www.loc.gov/z3950/agency/zing/srw/explain.html */
407 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
409 sr->srw_version = version;
411 sr->u.explain_request->recordPacking = recordPacking;
412 sr->u.explain_request->database = db;
414 sr->u.explain_request->stylesheet = stylesheet;
416 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
417 (*soap_package)->which = Z_SOAP_generic;
419 (*soap_package)->u.generic =
420 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
422 (*soap_package)->u.generic->p = sr;
423 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
424 (*soap_package)->u.generic->no = 0;
426 (*soap_package)->ns = "SRU";
430 else if (!strcmp(operation, "scan"))
432 /* Transfer SRU scan parameters to common struct */
433 /* http://www.loc.gov/z3950/agency/zing/srw/scan.html */
434 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_scan_request);
436 sr->srw_version = version;
441 sr->u.scan_request->query_type = Z_SRW_query_type_cql;
442 sr->u.scan_request->scanClause.cql = scanClause;
444 else if (pScanClause)
446 sr->u.scan_request->query_type = Z_SRW_query_type_pqf;
447 sr->u.scan_request->scanClause.pqf = pScanClause;
450 yaz_add_srw_diagnostic(decode, diag, num_diag, 7,
452 sr->u.scan_request->database = db;
455 sr->u.scan_request->maximumTerms =
456 odr_intdup(decode, atoi(maximumTerms));
457 if (responsePosition)
458 sr->u.scan_request->responsePosition =
459 odr_intdup(decode, atoi(responsePosition));
461 sr->u.scan_request->stylesheet = stylesheet;
463 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
464 (*soap_package)->which = Z_SOAP_generic;
466 (*soap_package)->u.generic =
467 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
469 (*soap_package)->u.generic->p = sr;
470 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
471 (*soap_package)->u.generic->no = 0;
473 (*soap_package)->ns = "SRU";
479 /* unsupported operation ... */
480 /* Act as if we received a explain request and throw diagnostic. */
482 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
484 sr->srw_version = version;
486 sr->u.explain_request->recordPacking = recordPacking;
487 sr->u.explain_request->database = db;
489 sr->u.explain_request->stylesheet = stylesheet;
491 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
492 (*soap_package)->which = Z_SOAP_generic;
494 (*soap_package)->u.generic =
495 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
497 (*soap_package)->u.generic->p = sr;
498 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
499 (*soap_package)->u.generic->no = 0;
501 (*soap_package)->ns = "SRU";
503 yaz_add_srw_diagnostic(decode, diag, num_diag, 4, operation);
512 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
514 Z_SRW_PDU *sr = (Z_SRW_PDU *) odr_malloc(o, sizeof(*o));
516 sr->srw_version = odr_strdup(o, "1.1");
520 case Z_SRW_searchRetrieve_request:
521 sr->u.request = (Z_SRW_searchRetrieveRequest *)
522 odr_malloc(o, sizeof(*sr->u.request));
523 sr->u.request->query_type = Z_SRW_query_type_cql;
524 sr->u.request->query.cql = 0;
525 sr->u.request->sort_type = Z_SRW_sort_type_none;
526 sr->u.request->sort.none = 0;
527 sr->u.request->startRecord = 0;
528 sr->u.request->maximumRecords = 0;
529 sr->u.request->recordSchema = 0;
530 sr->u.request->recordPacking = 0;
531 sr->u.request->recordXPath = 0;
532 sr->u.request->database = 0;
533 sr->u.request->resultSetTTL = 0;
534 sr->u.request->stylesheet = 0;
536 case Z_SRW_searchRetrieve_response:
537 sr->u.response = (Z_SRW_searchRetrieveResponse *)
538 odr_malloc(o, sizeof(*sr->u.response));
539 sr->u.response->numberOfRecords = 0;
540 sr->u.response->resultSetId = 0;
541 sr->u.response->resultSetIdleTime = 0;
542 sr->u.response->records = 0;
543 sr->u.response->num_records = 0;
544 sr->u.response->diagnostics = 0;
545 sr->u.response->num_diagnostics = 0;
546 sr->u.response->nextRecordPosition = 0;
548 case Z_SRW_explain_request:
549 sr->u.explain_request = (Z_SRW_explainRequest *)
550 odr_malloc(o, sizeof(*sr->u.explain_request));
551 sr->u.explain_request->recordPacking = 0;
552 sr->u.explain_request->database = 0;
553 sr->u.explain_request->stylesheet = 0;
555 case Z_SRW_explain_response:
556 sr->u.explain_response = (Z_SRW_explainResponse *)
557 odr_malloc(o, sizeof(*sr->u.explain_response));
558 sr->u.explain_response->record.recordData_buf = 0;
559 sr->u.explain_response->record.recordData_len = 0;
560 sr->u.explain_response->record.recordSchema = 0;
561 sr->u.explain_response->record.recordPosition = 0;
562 sr->u.explain_response->record.recordPacking =
563 Z_SRW_recordPacking_string;
564 sr->u.explain_response->diagnostics = 0;
565 sr->u.explain_response->num_diagnostics = 0;
567 case Z_SRW_scan_request:
568 sr->u.scan_request = (Z_SRW_scanRequest *)
569 odr_malloc(o, sizeof(*sr->u.scan_request));
570 sr->u.scan_request->database = 0;
571 sr->u.scan_request->stylesheet = 0;
572 sr->u.scan_request->maximumTerms = 0;
573 sr->u.scan_request->responsePosition = 0;
574 sr->u.scan_request->query_type = Z_SRW_query_type_cql;
575 sr->u.scan_request->scanClause.cql = 0;
577 case Z_SRW_scan_response:
578 sr->u.scan_response = (Z_SRW_scanResponse *)
579 odr_malloc(o, sizeof(*sr->u.scan_response));
580 sr->u.scan_response->terms = 0;
581 sr->u.scan_response->num_terms = 0;
582 sr->u.scan_response->diagnostics = 0;
583 sr->u.scan_response->num_diagnostics = 0;
591 static int srw_bib1_map[] = {
601 108, 10, /* Malformed query : Syntax error */
631 100, 1, /* bad map */
679 205, 1, /* bad map */
680 206, 1, /* bad map */
682 208, 1, /* bad map */
693 218, 1, /* bad map */
694 219, 1, /* bad map */
695 220, 1, /* bad map */
696 221, 1, /* bad map */
697 222, 1, /* bad map */
698 223, 1, /* bad map */
699 224, 1, /* bad map */
700 225, 1, /* bad map */
701 226, 1, /* bad map */
703 228, 1, /* bad map */
708 233, 1, /* bad map */
709 234, 1, /* bad map */
715 240, 1, /* bad map */
716 241, 1, /* bad map */
718 243, 1, /* bad map */
723 1001, 1, /* bad map */
724 1002, 1, /* bad map */
725 1003, 1, /* bad map */
726 1004, 1, /* bad map */
727 1005, 1, /* bad map */
728 1006, 1, /* bad map */
760 int yaz_diag_bib1_to_srw (int code)
762 const int *p = srw_bib1_map;
772 int yaz_diag_srw_to_bib1(int code)
774 const int *p = srw_bib1_map;
787 * indent-tabs-mode: nil
789 * vim: shiftwidth=4 tabstop=8 expandtab