2 * Copyright (C) 1995-2005, Index Data ApS
3 * See the file LICENSE for details.
5 * $Id: srwutil.c,v 1.30 2005-09-12 09:14:57 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[3] = {
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},
193 p1 = strchr(p0, '?');
195 p1 = p0 + strlen(p0);
198 db = (char*) odr_malloc(decode, p1 - p0 + 1);
199 memcpy (db, p0, p1 - p0);
203 if (charset && (charset_p = strstr(content_type, "; charset=")))
207 while (i < 20 && charset_p[i] &&
208 !strchr("; \n\r", charset_p[i]))
210 *charset = (char*) odr_malloc(decode, i+1);
211 memcpy(*charset, charset_p, i);
212 (*charset)[i] = '\0';
214 ret = z_soap_codec(decode, soap_package,
215 &hreq->content_buf, &hreq->content_len,
217 if (ret == 0 && (*soap_package)->which == Z_SOAP_generic)
219 *srw_pdu = (Z_SRW_PDU*) (*soap_package)->u.generic->p;
221 if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request &&
222 (*srw_pdu)->u.request->database == 0)
223 (*srw_pdu)->u.request->database = db;
225 if ((*srw_pdu)->which == Z_SRW_explain_request &&
226 (*srw_pdu)->u.explain_request->database == 0)
227 (*srw_pdu)->u.explain_request->database = db;
229 if ((*srw_pdu)->which == Z_SRW_scan_request &&
230 (*srw_pdu)->u.scan_request->database == 0)
231 (*srw_pdu)->u.scan_request->database = db;
242 http://www.loc.gov/z3950/agency/zing/srw/service.html
244 int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
245 Z_SOAP **soap_package, ODR decode, char **charset,
246 Z_SRW_diagnostic **diag, int *num_diag)
249 static Z_SOAP_Handler soap_handlers[2] = {
250 {"http://www.loc.gov/zing/srw/", 0,
251 (Z_SOAP_fun) yaz_srw_codec},
255 if (!strcmp(hreq->method, "GET") ||
256 !strcmp(hreq->method, "POST") )
258 char *db = "Default";
259 const char *p0 = hreq->path, *p1;
261 const char *operation = 0;
266 char *stylesheet = 0;
267 char *scanClause = 0;
268 char *pScanClause = 0;
269 char *recordXPath = 0;
270 char *recordSchema = 0;
271 char *recordPacking = "xml"; /* xml packing is default for SRU */
272 char *maximumRecords = 0;
273 char *startRecord = 0;
274 char *maximumTerms = 0;
275 char *responsePosition = 0;
276 char *extraRequestData = 0;
285 p1 = strchr(p0, '?');
287 p1 = p0 + strlen(p0);
290 db = (char*) odr_malloc(decode, p1 - p0 + 1);
291 memcpy (db, p0, p1 - p0);
294 if (!strcmp(hreq->method, "POST"))
295 p1 = hreq->content_buf;
296 yaz_uri_array(p1, decode, &uri_name, &uri_val);
301 for (i = 0; uri_name[i]; i++)
303 char *n = uri_name[i];
304 char *v = uri_val[i];
305 if (!strcmp(n, "query"))
307 else if (!strcmp(n, "x-pquery"))
309 else if (!strcmp(n, "operation"))
311 else if (!strcmp(n, "stylesheet"))
313 else if (!strcmp(n, "sortKeys"))
315 else if (!strcmp(n, "recordXPath"))
317 else if (!strcmp(n, "recordSchema"))
319 else if (!strcmp(n, "recordPacking"))
321 else if (!strcmp(n, "version"))
323 else if (!strcmp(n, "scanClause"))
325 else if (!strcmp(n, "x-pScanClause"))
327 else if (!strcmp(n, "maximumRecords"))
329 else if (!strcmp(n, "startRecord"))
331 else if (!strcmp(n, "maximumTerms"))
333 else if (!strcmp(n, "responsePosition"))
334 responsePosition = v;
335 else if (!strcmp(n, "extraRequestData"))
336 extraRequestData = v;
338 yaz_add_srw_diagnostic(decode, diag, num_diag, 8, n);
344 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "version");
347 if (strcmp(version, "1.1"))
348 yaz_add_srw_diagnostic(decode, diag, num_diag, 5, "1.1");
352 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "operation");
353 operation = "explain";
355 if (!strcmp(operation, "searchRetrieve"))
357 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
359 sr->srw_version = version;
363 sr->u.request->query_type = Z_SRW_query_type_cql;
364 sr->u.request->query.cql = query;
368 sr->u.request->query_type = Z_SRW_query_type_pqf;
369 sr->u.request->query.pqf = pQuery;
372 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "query");
376 sr->u.request->sort_type = Z_SRW_sort_type_sort;
377 sr->u.request->sort.sortKeys = sortKeys;
379 sr->u.request->recordXPath = recordXPath;
380 sr->u.request->recordSchema = recordSchema;
381 sr->u.request->recordPacking = recordPacking;
382 sr->u.request->stylesheet = stylesheet;
385 sr->u.request->maximumRecords =
386 odr_intdup(decode, atoi(maximumRecords));
388 sr->u.request->startRecord =
389 odr_intdup(decode, atoi(startRecord));
391 sr->u.request->database = db;
393 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
394 (*soap_package)->which = Z_SOAP_generic;
396 (*soap_package)->u.generic =
397 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
399 (*soap_package)->u.generic->p = sr;
400 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
401 (*soap_package)->u.generic->no = 0;
403 (*soap_package)->ns = "SRU";
407 else if (!strcmp(operation, "explain"))
409 /* Transfer SRU explain parameters to common struct */
410 /* http://www.loc.gov/z3950/agency/zing/srw/explain.html */
411 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
413 sr->srw_version = version;
415 sr->u.explain_request->recordPacking = recordPacking;
416 sr->u.explain_request->database = db;
418 sr->u.explain_request->stylesheet = stylesheet;
420 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
421 (*soap_package)->which = Z_SOAP_generic;
423 (*soap_package)->u.generic =
424 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
426 (*soap_package)->u.generic->p = sr;
427 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
428 (*soap_package)->u.generic->no = 0;
430 (*soap_package)->ns = "SRU";
434 else if (!strcmp(operation, "scan"))
436 /* Transfer SRU scan parameters to common struct */
437 /* http://www.loc.gov/z3950/agency/zing/srw/scan.html */
438 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_scan_request);
440 sr->srw_version = version;
445 sr->u.scan_request->query_type = Z_SRW_query_type_cql;
446 sr->u.scan_request->scanClause.cql = scanClause;
448 else if (pScanClause)
450 sr->u.scan_request->query_type = Z_SRW_query_type_pqf;
451 sr->u.scan_request->scanClause.pqf = pScanClause;
454 yaz_add_srw_diagnostic(decode, diag, num_diag, 7,
456 sr->u.scan_request->database = db;
459 sr->u.scan_request->maximumTerms =
460 odr_intdup(decode, atoi(maximumTerms));
461 if (responsePosition)
462 sr->u.scan_request->responsePosition =
463 odr_intdup(decode, atoi(responsePosition));
465 sr->u.scan_request->stylesheet = stylesheet;
467 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
468 (*soap_package)->which = Z_SOAP_generic;
470 (*soap_package)->u.generic =
471 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
473 (*soap_package)->u.generic->p = sr;
474 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
475 (*soap_package)->u.generic->no = 0;
477 (*soap_package)->ns = "SRU";
483 /* unsupported operation ... */
484 /* Act as if we received a explain request and throw diagnostic. */
486 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
488 sr->srw_version = version;
490 sr->u.explain_request->recordPacking = recordPacking;
491 sr->u.explain_request->database = db;
493 sr->u.explain_request->stylesheet = stylesheet;
495 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
496 (*soap_package)->which = Z_SOAP_generic;
498 (*soap_package)->u.generic =
499 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
501 (*soap_package)->u.generic->p = sr;
502 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
503 (*soap_package)->u.generic->no = 0;
505 (*soap_package)->ns = "SRU";
507 yaz_add_srw_diagnostic(decode, diag, num_diag, 4, operation);
516 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
518 Z_SRW_PDU *sr = (Z_SRW_PDU *) odr_malloc(o, sizeof(*o));
520 sr->srw_version = odr_strdup(o, "1.1");
524 case Z_SRW_searchRetrieve_request:
525 sr->u.request = (Z_SRW_searchRetrieveRequest *)
526 odr_malloc(o, sizeof(*sr->u.request));
527 sr->u.request->query_type = Z_SRW_query_type_cql;
528 sr->u.request->query.cql = 0;
529 sr->u.request->sort_type = Z_SRW_sort_type_none;
530 sr->u.request->sort.none = 0;
531 sr->u.request->startRecord = 0;
532 sr->u.request->maximumRecords = 0;
533 sr->u.request->recordSchema = 0;
534 sr->u.request->recordPacking = 0;
535 sr->u.request->recordXPath = 0;
536 sr->u.request->database = 0;
537 sr->u.request->resultSetTTL = 0;
538 sr->u.request->stylesheet = 0;
540 case Z_SRW_searchRetrieve_response:
541 sr->u.response = (Z_SRW_searchRetrieveResponse *)
542 odr_malloc(o, sizeof(*sr->u.response));
543 sr->u.response->numberOfRecords = 0;
544 sr->u.response->resultSetId = 0;
545 sr->u.response->resultSetIdleTime = 0;
546 sr->u.response->records = 0;
547 sr->u.response->num_records = 0;
548 sr->u.response->diagnostics = 0;
549 sr->u.response->num_diagnostics = 0;
550 sr->u.response->nextRecordPosition = 0;
552 case Z_SRW_explain_request:
553 sr->u.explain_request = (Z_SRW_explainRequest *)
554 odr_malloc(o, sizeof(*sr->u.explain_request));
555 sr->u.explain_request->recordPacking = 0;
556 sr->u.explain_request->database = 0;
557 sr->u.explain_request->stylesheet = 0;
559 case Z_SRW_explain_response:
560 sr->u.explain_response = (Z_SRW_explainResponse *)
561 odr_malloc(o, sizeof(*sr->u.explain_response));
562 sr->u.explain_response->record.recordData_buf = 0;
563 sr->u.explain_response->record.recordData_len = 0;
564 sr->u.explain_response->record.recordSchema = 0;
565 sr->u.explain_response->record.recordPosition = 0;
566 sr->u.explain_response->record.recordPacking =
567 Z_SRW_recordPacking_string;
568 sr->u.explain_response->diagnostics = 0;
569 sr->u.explain_response->num_diagnostics = 0;
571 case Z_SRW_scan_request:
572 sr->u.scan_request = (Z_SRW_scanRequest *)
573 odr_malloc(o, sizeof(*sr->u.scan_request));
574 sr->u.scan_request->database = 0;
575 sr->u.scan_request->stylesheet = 0;
576 sr->u.scan_request->maximumTerms = 0;
577 sr->u.scan_request->responsePosition = 0;
578 sr->u.scan_request->query_type = Z_SRW_query_type_cql;
579 sr->u.scan_request->scanClause.cql = 0;
581 case Z_SRW_scan_response:
582 sr->u.scan_response = (Z_SRW_scanResponse *)
583 odr_malloc(o, sizeof(*sr->u.scan_response));
584 sr->u.scan_response->terms = 0;
585 sr->u.scan_response->num_terms = 0;
586 sr->u.scan_response->diagnostics = 0;
587 sr->u.scan_response->num_diagnostics = 0;
595 static int srw_bib1_map[] = {
605 108, 10, /* Malformed query : Syntax error */
635 100, 1, /* bad map */
683 205, 1, /* bad map */
684 206, 1, /* bad map */
686 208, 1, /* bad map */
697 218, 1, /* bad map */
698 219, 1, /* bad map */
699 220, 1, /* bad map */
700 221, 1, /* bad map */
701 222, 1, /* bad map */
702 223, 1, /* bad map */
703 224, 1, /* bad map */
704 225, 1, /* bad map */
705 226, 1, /* bad map */
707 228, 1, /* bad map */
712 233, 1, /* bad map */
713 234, 1, /* bad map */
719 240, 1, /* bad map */
720 241, 1, /* bad map */
722 243, 1, /* bad map */
727 1001, 1, /* bad map */
728 1002, 1, /* bad map */
729 1003, 1, /* bad map */
730 1004, 1, /* bad map */
731 1005, 1, /* bad map */
732 1006, 1, /* bad map */
764 int yaz_diag_bib1_to_srw (int code)
766 const int *p = srw_bib1_map;
776 int yaz_diag_srw_to_bib1(int code)
778 const int *p = srw_bib1_map;
791 * indent-tabs-mode: nil
793 * vim: shiftwidth=4 tabstop=8 expandtab