2 * Copyright (c) 2002-2005, Index Data.
3 * See the file LICENSE for details.
5 * $Id: srwutil.c,v 1.22 2005-01-11 10:50:06 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;
238 http://www.loc.gov/z3950/agency/zing/srw/service.html
240 int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
241 Z_SOAP **soap_package, ODR decode, char **charset,
242 Z_SRW_diagnostic **diag, int *num_diag)
245 static Z_SOAP_Handler soap_handlers[2] = {
246 {"http://www.loc.gov/zing/srw/", 0,
247 (Z_SOAP_fun) yaz_srw_codec},
251 if (!strcmp(hreq->method, "GET"))
253 char *db = "Default";
254 const char *p0 = hreq->path, *p1;
255 const char *operation = 0;
260 char *stylesheet = 0;
261 char *scanClause = 0;
262 char *pScanClause = 0;
263 char *recordXPath = 0;
264 char *recordSchema = 0;
265 char *recordPacking = "xml"; /* xml packing is default for SRU */
266 char *maximumRecords = 0;
267 char *startRecord = 0;
268 char *maximumTerms = 0;
269 char *responsePosition = 0;
270 char *extraRequestData = 0;
278 p1 = strchr(p0, '?');
280 p1 = p0 + strlen(p0);
283 db = (char*) odr_malloc(decode, p1 - p0 + 1);
284 memcpy (db, p0, p1 - p0);
287 yaz_uri_array(p1, decode, &uri_name, &uri_val);
292 for (i = 0; uri_name[i]; i++)
294 char *n = uri_name[i];
295 char *v = uri_val[i];
296 if (!strcmp(n, "query"))
298 else if (!strcmp(n, "x-pquery"))
300 else if (!strcmp(n, "operation"))
302 else if (!strcmp(n, "stylesheet"))
304 else if (!strcmp(n, "sortKeys"))
306 else if (!strcmp(n, "recordXPath"))
308 else if (!strcmp(n, "recordSchema"))
310 else if (!strcmp(n, "recordPacking"))
312 else if (!strcmp(n, "version"))
314 else if (!strcmp(n, "scanClause"))
316 else if (!strcmp(n, "x-pScanClause"))
318 else if (!strcmp(n, "maximumRecords"))
320 else if (!strcmp(n, "startRecord"))
322 else if (!strcmp(n, "maximumTerms"))
324 else if (!strcmp(n, "responsePosition"))
325 responsePosition = v;
326 else if (!strcmp(n, "extraRequestData"))
327 extraRequestData = v;
329 yaz_add_srw_diagnostic(decode, diag, num_diag, 8, n);
335 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "version");
338 if (strcmp(version, "1.1"))
339 yaz_add_srw_diagnostic(decode, diag, num_diag, 5, "1.1");
343 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "operation");
344 operation = "explain";
346 if (!strcmp(operation, "searchRetrieve"))
348 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
350 sr->srw_version = version;
354 sr->u.request->query_type = Z_SRW_query_type_cql;
355 sr->u.request->query.cql = query;
359 sr->u.request->query_type = Z_SRW_query_type_pqf;
360 sr->u.request->query.pqf = pQuery;
363 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "query");
367 sr->u.request->sort_type = Z_SRW_sort_type_sort;
368 sr->u.request->sort.sortKeys = sortKeys;
370 sr->u.request->recordXPath = recordXPath;
371 sr->u.request->recordSchema = recordSchema;
372 sr->u.request->recordPacking = recordPacking;
373 sr->u.request->stylesheet = stylesheet;
376 sr->u.request->maximumRecords =
377 odr_intdup(decode, atoi(maximumRecords));
379 sr->u.request->startRecord =
380 odr_intdup(decode, atoi(startRecord));
382 sr->u.request->database = db;
384 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
385 (*soap_package)->which = Z_SOAP_generic;
387 (*soap_package)->u.generic =
388 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
390 (*soap_package)->u.generic->p = sr;
391 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
392 (*soap_package)->u.generic->no = 0;
394 (*soap_package)->ns = "SRU";
398 else if (!strcmp(operation, "explain"))
400 /* Transfer SRU explain parameters to common struct */
401 /* http://www.loc.gov/z3950/agency/zing/srw/explain.html */
402 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
404 sr->srw_version = version;
406 sr->u.explain_request->recordPacking = recordPacking;
407 sr->u.explain_request->database = db;
409 sr->u.explain_request->stylesheet = stylesheet;
411 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
412 (*soap_package)->which = Z_SOAP_generic;
414 (*soap_package)->u.generic =
415 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
417 (*soap_package)->u.generic->p = sr;
418 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
419 (*soap_package)->u.generic->no = 0;
421 (*soap_package)->ns = "SRU";
425 else if (!strcmp(operation, "scan"))
427 /* Transfer SRU scan parameters to common struct */
428 /* http://www.loc.gov/z3950/agency/zing/srw/scan.html */
429 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_scan_request);
431 sr->srw_version = version;
436 sr->u.scan_request->query_type = Z_SRW_query_type_cql;
437 sr->u.scan_request->scanClause.cql = scanClause;
439 else if (pScanClause)
441 sr->u.scan_request->query_type = Z_SRW_query_type_pqf;
442 sr->u.scan_request->scanClause.pqf = pScanClause;
445 yaz_add_srw_diagnostic(decode, diag, num_diag, 7,
447 sr->u.scan_request->database = db;
450 sr->u.scan_request->maximumTerms =
451 odr_intdup(decode, atoi(maximumTerms));
452 if (responsePosition)
453 sr->u.scan_request->responsePosition =
454 odr_intdup(decode, atoi(responsePosition));
456 sr->u.scan_request->stylesheet = stylesheet;
458 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
459 (*soap_package)->which = Z_SOAP_generic;
461 (*soap_package)->u.generic =
462 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
464 (*soap_package)->u.generic->p = sr;
465 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
466 (*soap_package)->u.generic->no = 0;
468 (*soap_package)->ns = "SRU";
474 /* unsupported operation ... */
475 /* Act as if we received a explain request and throw diagnostic. */
477 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
479 sr->srw_version = version;
481 sr->u.explain_request->recordPacking = recordPacking;
482 sr->u.explain_request->database = db;
484 sr->u.explain_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";
498 yaz_add_srw_diagnostic(decode, diag, num_diag, 4, operation);
507 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
509 Z_SRW_PDU *sr = (Z_SRW_PDU *) odr_malloc(o, sizeof(*o));
511 sr->srw_version = odr_strdup(o, "1.1");
515 case Z_SRW_searchRetrieve_request:
516 sr->u.request = (Z_SRW_searchRetrieveRequest *)
517 odr_malloc(o, sizeof(*sr->u.request));
518 sr->u.request->query_type = Z_SRW_query_type_cql;
519 sr->u.request->query.cql = 0;
520 sr->u.request->sort_type = Z_SRW_sort_type_none;
521 sr->u.request->sort.none = 0;
522 sr->u.request->startRecord = 0;
523 sr->u.request->maximumRecords = 0;
524 sr->u.request->recordSchema = 0;
525 sr->u.request->recordPacking = 0;
526 sr->u.request->recordXPath = 0;
527 sr->u.request->database = 0;
528 sr->u.request->resultSetTTL = 0;
529 sr->u.request->stylesheet = 0;
531 case Z_SRW_searchRetrieve_response:
532 sr->u.response = (Z_SRW_searchRetrieveResponse *)
533 odr_malloc(o, sizeof(*sr->u.response));
534 sr->u.response->numberOfRecords = 0;
535 sr->u.response->resultSetId = 0;
536 sr->u.response->resultSetIdleTime = 0;
537 sr->u.response->records = 0;
538 sr->u.response->num_records = 0;
539 sr->u.response->diagnostics = 0;
540 sr->u.response->num_diagnostics = 0;
541 sr->u.response->nextRecordPosition = 0;
543 case Z_SRW_explain_request:
544 sr->u.explain_request = (Z_SRW_explainRequest *)
545 odr_malloc(o, sizeof(*sr->u.explain_request));
546 sr->u.explain_request->recordPacking = 0;
547 sr->u.explain_request->database = 0;
548 sr->u.explain_request->stylesheet = 0;
550 case Z_SRW_explain_response:
551 sr->u.explain_response = (Z_SRW_explainResponse *)
552 odr_malloc(o, sizeof(*sr->u.explain_response));
553 sr->u.explain_response->record.recordData_buf = 0;
554 sr->u.explain_response->record.recordData_len = 0;
555 sr->u.explain_response->record.recordSchema = 0;
556 sr->u.explain_response->record.recordPosition = 0;
557 sr->u.explain_response->record.recordPacking =
558 Z_SRW_recordPacking_string;
559 sr->u.explain_response->diagnostics = 0;
560 sr->u.explain_response->num_diagnostics = 0;
562 case Z_SRW_scan_request:
563 sr->u.scan_request = (Z_SRW_scanRequest *)
564 odr_malloc(o, sizeof(*sr->u.scan_request));
565 sr->u.scan_request->database = 0;
566 sr->u.scan_request->stylesheet = 0;
567 sr->u.scan_request->maximumTerms = 0;
568 sr->u.scan_request->responsePosition = 0;
569 sr->u.scan_request->query_type = Z_SRW_query_type_cql;
570 sr->u.scan_request->scanClause.cql = 0;
572 case Z_SRW_scan_response:
573 sr->u.scan_response = (Z_SRW_scanResponse *)
574 odr_malloc(o, sizeof(*sr->u.scan_response));
575 sr->u.scan_response->terms = 0;
576 sr->u.scan_response->num_terms = 0;
577 sr->u.scan_response->diagnostics = 0;
578 sr->u.scan_response->num_diagnostics = 0;
586 static int srw_bib1_map[] = {
596 108, 10, /* Malformed query : Syntax error */
626 100, 1, /* bad map */
674 205, 1, /* bad map */
675 206, 1, /* bad map */
677 208, 1, /* bad map */
688 218, 1, /* bad map */
689 219, 1, /* bad map */
690 220, 1, /* bad map */
691 221, 1, /* bad map */
692 222, 1, /* bad map */
693 223, 1, /* bad map */
694 224, 1, /* bad map */
695 225, 1, /* bad map */
696 226, 1, /* bad map */
698 228, 1, /* bad map */
703 233, 1, /* bad map */
704 234, 1, /* bad map */
710 240, 1, /* bad map */
711 241, 1, /* bad map */
713 243, 1, /* bad map */
718 1001, 1, /* bad map */
719 1002, 1, /* bad map */
720 1003, 1, /* bad map */
721 1004, 1, /* bad map */
722 1005, 1, /* bad map */
723 1006, 1, /* bad map */
755 int yaz_diag_bib1_to_srw (int code)
757 const int *p = srw_bib1_map;
767 int yaz_diag_srw_to_bib1(int code)
769 const int *p = srw_bib1_map;