2 * Copyright (c) 2002-2004, Index Data.
3 * See the file LICENSE for details.
5 * $Id: srwutil.c,v 1.20 2005-01-08 01:20:19 adam Exp $
9 * \brief Implements SRW/SRU utilities.
13 #include <yaz/yaz-iconv.h>
15 static int hex_digit (int ch)
17 if (ch >= '0' && ch <= '9')
19 else if (ch >= 'a' && ch <= 'f')
21 else if (ch >= 'A' && ch <= 'F')
26 int yaz_uri_array(const char *path, ODR o, char ***name, char ***val)
35 while ((cp = strchr(cp, '&')))
40 *name = odr_malloc(o, no * sizeof(char**));
41 *val = odr_malloc(o, no * sizeof(char**));
43 for (no = 0; *path; no++)
45 const char *p1 = strchr(path, '=');
51 (*name)[no] = odr_malloc(o, (p1-path)+1);
52 memcpy((*name)[no], path, p1-path);
53 (*name)[no][p1-path] = '\0';
56 p1 = strchr(path, '&');
58 p1 = strlen(path) + path;
59 (*val)[no] = ret = odr_malloc(o, p1 - path + 1);
60 while (*path && *path != '&')
67 else if (*path == '%' && path[1] && path[2])
69 ret[i++] = hex_digit (path[1])*16 + hex_digit (path[2]);
85 char *yaz_uri_val(const char *path, const char *name, ODR o)
87 size_t nlen = strlen(name);
93 const char *p1 = strchr(path, '=');
96 if ((size_t)(p1 - path) == nlen && !memcmp(path, name, nlen))
102 p1 = strchr(path, '&');
104 p1 = strlen(path) + path;
105 ret = (char *) odr_malloc(o, p1 - path + 1);
106 while (*path && *path != '&')
113 else if (*path == '%' && path[1] && path[2])
115 ret[i++] = hex_digit (path[1])*16 + hex_digit (path[2]);
124 path = strchr(p1, '&');
131 void yaz_uri_val_int(const char *path, const char *name, ODR o, int **intp)
133 const char *v = yaz_uri_val(path, name, o);
135 *intp = odr_intdup(o, atoi(v));
138 void yaz_mk_std_diagnostic(ODR o, Z_SRW_diagnostic *d,
139 int code, const char *details)
141 d->uri = (char *) odr_malloc(o, 50);
142 sprintf(d->uri, "info:srw/diagnostic/1/%d", code);
145 d->details = odr_strdup(o, details);
150 void yaz_add_srw_diagnostic(ODR o, Z_SRW_diagnostic **d,
151 int *num, int code, const char *addinfo)
153 Z_SRW_diagnostic *d_new;
154 d_new = (Z_SRW_diagnostic *) odr_malloc (o, (*num + 1)* sizeof(**d));
156 memcpy (d_new, *d, *num *sizeof(**d));
159 yaz_mk_std_diagnostic(o, *d + *num, code, addinfo);
163 int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
164 Z_SOAP **soap_package, ODR decode, char **charset)
166 if (!strcmp(hreq->method, "POST"))
168 const char *content_type = z_HTTP_header_lookup(hreq->headers,
170 if (content_type && !yaz_strcmp_del("text/xml", content_type, "; "))
172 char *db = "Default";
173 const char *p0 = hreq->path, *p1;
175 const char *charset_p = 0;
177 static Z_SOAP_Handler soap_handlers[3] = {
179 {"http://www.loc.gov/zing/srw/", 0,
180 (Z_SOAP_fun) yaz_srw_codec},
181 {"http://www.loc.gov/zing/srw/v1.0/", 0,
182 (Z_SOAP_fun) yaz_srw_codec},
189 p1 = strchr(p0, '?');
191 p1 = p0 + strlen(p0);
194 db = (char*) odr_malloc(decode, p1 - p0 + 1);
195 memcpy (db, p0, p1 - p0);
199 if (charset && (charset_p = strstr(content_type, "; charset=")))
203 while (i < 20 && charset_p[i] &&
204 !strchr("; \n\r", charset_p[i]))
206 *charset = (char*) odr_malloc(decode, i+1);
207 memcpy(*charset, charset_p, i);
208 (*charset)[i] = '\0';
210 ret = z_soap_codec(decode, soap_package,
211 &hreq->content_buf, &hreq->content_len,
213 if (ret == 0 && (*soap_package)->which == Z_SOAP_generic)
215 *srw_pdu = (Z_SRW_PDU*) (*soap_package)->u.generic->p;
217 if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request &&
218 (*srw_pdu)->u.request->database == 0)
219 (*srw_pdu)->u.request->database = db;
221 if ((*srw_pdu)->which == Z_SRW_explain_request &&
222 (*srw_pdu)->u.explain_request->database == 0)
223 (*srw_pdu)->u.explain_request->database = db;
225 if ((*srw_pdu)->which == Z_SRW_scan_request &&
226 (*srw_pdu)->u.scan_request->database == 0)
227 (*srw_pdu)->u.scan_request->database = db;
237 int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
238 Z_SOAP **soap_package, ODR decode, char **charset,
239 Z_SRW_diagnostic **diag, int *num_diag)
242 static Z_SOAP_Handler soap_handlers[2] = {
243 {"http://www.loc.gov/zing/srw/", 0,
244 (Z_SOAP_fun) yaz_srw_codec},
248 if (!strcmp(hreq->method, "GET"))
250 char *db = "Default";
251 const char *p0 = hreq->path, *p1;
252 const char *operation = 0;
257 char *stylesheet = 0;
258 char *scanClause = 0;
259 char *pScanClause = 0;
260 char *recordXPath = 0;
261 char *recordSchema = 0;
262 char *recordPacking = "xml"; /* xml packing is default for SRU */
263 char *maximumRecords = 0;
264 char *startRecord = 0;
272 p1 = strchr(p0, '?');
274 p1 = p0 + strlen(p0);
277 db = (char*) odr_malloc(decode, p1 - p0 + 1);
278 memcpy (db, p0, p1 - p0);
281 yaz_uri_array(p1, decode, &uri_name, &uri_val);
286 for (i = 0; uri_name[i]; i++)
288 char *n = uri_name[i];
289 char *v = uri_val[i];
290 if (!strcmp(n, "query"))
292 else if (!strcmp(n, "x-pquery"))
294 else if (!strcmp(n, "operation"))
296 else if (!strcmp(n, "stylesheet"))
298 else if (!strcmp(n, "sortKeys"))
300 else if (!strcmp(n, "recordXPath"))
302 else if (!strcmp(n, "recordSchema"))
304 else if (!strcmp(n, "recordPacking"))
306 else if (!strcmp(n, "version"))
308 else if (!strcmp(n, "scanClause"))
310 else if (!strcmp(n, "x-ScanClause"))
312 else if (!strcmp(n, "maximumRecords"))
314 else if (!strcmp(n, "startRecord"))
317 yaz_add_srw_diagnostic(decode, diag, num_diag, 8, n);
323 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "version");
326 if (strcmp(version, "1.1"))
327 yaz_add_srw_diagnostic(decode, diag, num_diag, 5, "1.1");
331 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "operation");
332 operation = "explain";
334 if (!strcmp(operation, "searchRetrieve"))
336 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
338 sr->srw_version = version;
342 sr->u.request->query_type = Z_SRW_query_type_cql;
343 sr->u.request->query.cql = query;
347 sr->u.request->query_type = Z_SRW_query_type_pqf;
348 sr->u.request->query.pqf = pQuery;
351 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "query");
355 sr->u.request->sort_type = Z_SRW_sort_type_sort;
356 sr->u.request->sort.sortKeys = sortKeys;
358 sr->u.request->recordXPath = recordXPath;
359 sr->u.request->recordSchema = recordSchema;
360 sr->u.request->recordPacking = recordPacking;
361 sr->u.request->stylesheet = stylesheet;
364 sr->u.request->maximumRecords =
365 odr_intdup(decode, atoi(maximumRecords));
367 sr->u.request->startRecord =
368 odr_intdup(decode, atoi(startRecord));
370 sr->u.request->database = db;
372 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
373 (*soap_package)->which = Z_SOAP_generic;
375 (*soap_package)->u.generic =
376 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
378 (*soap_package)->u.generic->p = sr;
379 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
380 (*soap_package)->u.generic->no = 0;
382 (*soap_package)->ns = "SRU";
386 else if (!strcmp(operation, "explain"))
388 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
390 sr->srw_version = version;
392 sr->u.explain_request->recordPacking = recordPacking;
393 sr->u.explain_request->database = db;
395 sr->u.explain_request->stylesheet = stylesheet;
397 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
398 (*soap_package)->which = Z_SOAP_generic;
400 (*soap_package)->u.generic =
401 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
403 (*soap_package)->u.generic->p = sr;
404 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
405 (*soap_package)->u.generic->no = 0;
407 (*soap_package)->ns = "SRU";
411 else if (!strcmp(operation, "scan"))
413 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_scan_request);
417 sr->u.scan_request->query_type = Z_SRW_query_type_cql;
418 sr->u.scan_request->scanClause.cql = scanClause;
420 else if (pScanClause)
422 sr->u.scan_request->query_type = Z_SRW_query_type_pqf;
423 sr->u.scan_request->scanClause.pqf = pScanClause;
426 yaz_add_srw_diagnostic(decode, diag, num_diag, 7,
428 sr->srw_version = version;
430 sr->u.scan_request->database = db;
431 sr->u.scan_request->stylesheet = stylesheet;
433 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
434 (*soap_package)->which = Z_SOAP_generic;
436 (*soap_package)->u.generic =
437 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
439 (*soap_package)->u.generic->p = sr;
440 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
441 (*soap_package)->u.generic->no = 0;
443 (*soap_package)->ns = "SRU";
449 /* unsupported operation ... */
450 /* Act as if we received a explain request and throw diagnostic. */
452 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
454 sr->srw_version = version;
456 sr->u.explain_request->recordPacking = recordPacking;
457 sr->u.explain_request->database = db;
459 sr->u.explain_request->stylesheet = stylesheet;
461 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
462 (*soap_package)->which = Z_SOAP_generic;
464 (*soap_package)->u.generic =
465 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
467 (*soap_package)->u.generic->p = sr;
468 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
469 (*soap_package)->u.generic->no = 0;
471 (*soap_package)->ns = "SRU";
473 yaz_add_srw_diagnostic(decode, diag, num_diag, 4, operation);
482 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
484 Z_SRW_PDU *sr = (Z_SRW_PDU *) odr_malloc(o, sizeof(*o));
486 sr->srw_version = odr_strdup(o, "1.1");
490 case Z_SRW_searchRetrieve_request:
491 sr->u.request = (Z_SRW_searchRetrieveRequest *)
492 odr_malloc(o, sizeof(*sr->u.request));
493 sr->u.request->query_type = Z_SRW_query_type_cql;
494 sr->u.request->query.cql = 0;
495 sr->u.request->sort_type = Z_SRW_sort_type_none;
496 sr->u.request->sort.none = 0;
497 sr->u.request->startRecord = 0;
498 sr->u.request->maximumRecords = 0;
499 sr->u.request->recordSchema = 0;
500 sr->u.request->recordPacking = 0;
501 sr->u.request->recordXPath = 0;
502 sr->u.request->database = 0;
503 sr->u.request->resultSetTTL = 0;
504 sr->u.request->stylesheet = 0;
506 case Z_SRW_searchRetrieve_response:
507 sr->u.response = (Z_SRW_searchRetrieveResponse *)
508 odr_malloc(o, sizeof(*sr->u.response));
509 sr->u.response->numberOfRecords = 0;
510 sr->u.response->resultSetId = 0;
511 sr->u.response->resultSetIdleTime = 0;
512 sr->u.response->records = 0;
513 sr->u.response->num_records = 0;
514 sr->u.response->diagnostics = 0;
515 sr->u.response->num_diagnostics = 0;
516 sr->u.response->nextRecordPosition = 0;
518 case Z_SRW_explain_request:
519 sr->u.explain_request = (Z_SRW_explainRequest *)
520 odr_malloc(o, sizeof(*sr->u.explain_request));
521 sr->u.explain_request->recordPacking = 0;
522 sr->u.explain_request->database = 0;
523 sr->u.explain_request->stylesheet = 0;
525 case Z_SRW_explain_response:
526 sr->u.explain_response = (Z_SRW_explainResponse *)
527 odr_malloc(o, sizeof(*sr->u.explain_response));
528 sr->u.explain_response->record.recordData_buf = 0;
529 sr->u.explain_response->record.recordData_len = 0;
530 sr->u.explain_response->record.recordSchema = 0;
531 sr->u.explain_response->record.recordPosition = 0;
532 sr->u.explain_response->record.recordPacking =
533 Z_SRW_recordPacking_string;
534 sr->u.explain_response->diagnostics = 0;
535 sr->u.explain_response->num_diagnostics = 0;
537 case Z_SRW_scan_request:
538 sr->u.scan_request = (Z_SRW_scanRequest *)
539 odr_malloc(o, sizeof(*sr->u.scan_request));
540 sr->u.scan_request->database = 0;
541 sr->u.scan_request->stylesheet = 0;
542 sr->u.scan_request->maximumTerms = 0;
543 sr->u.scan_request->responsePosition = 0;
544 sr->u.scan_request->query_type = Z_SRW_query_type_cql;
545 sr->u.scan_request->scanClause.cql = 0;
547 case Z_SRW_scan_response:
548 sr->u.scan_response = (Z_SRW_scanResponse *)
549 odr_malloc(o, sizeof(*sr->u.scan_response));
550 sr->u.scan_response->terms = 0;
551 sr->u.scan_response->num_terms = 0;
552 sr->u.scan_response->diagnostics = 0;
553 sr->u.scan_response->num_diagnostics = 0;
561 static int srw_bib1_map[] = {
571 108, 10, /* Malformed query : Syntax error */
601 100, 1, /* bad map */
649 205, 1, /* bad map */
650 206, 1, /* bad map */
652 208, 1, /* bad map */
663 218, 1, /* bad map */
664 219, 1, /* bad map */
665 220, 1, /* bad map */
666 221, 1, /* bad map */
667 222, 1, /* bad map */
668 223, 1, /* bad map */
669 224, 1, /* bad map */
670 225, 1, /* bad map */
671 226, 1, /* bad map */
673 228, 1, /* bad map */
678 233, 1, /* bad map */
679 234, 1, /* bad map */
685 240, 1, /* bad map */
686 241, 1, /* bad map */
688 243, 1, /* bad map */
693 1001, 1, /* bad map */
694 1002, 1, /* bad map */
695 1003, 1, /* bad map */
696 1004, 1, /* bad map */
697 1005, 1, /* bad map */
698 1006, 1, /* bad map */
730 int yaz_diag_bib1_to_srw (int code)
732 const int *p = srw_bib1_map;
742 int yaz_diag_srw_to_bib1(int code)
744 const int *p = srw_bib1_map;