YAZ 5.35.1
record_conv.c
Go to the documentation of this file.
1/* This file is part of the YAZ toolkit.
2 * Copyright (C) Index Data
3 * See the file LICENSE for details.
4 */
10#if HAVE_CONFIG_H
11#include <config.h>
12#endif
13
14#include <stdlib.h>
15#include <string.h>
16#include <yaz/log.h>
17#include <yaz/yaz-iconv.h>
18#include <yaz/marcdisp.h>
19#include <yaz/record_conv.h>
20#include <yaz/wrbuf.h>
21#include <yaz/xmalloc.h>
22#include <yaz/nmem.h>
23#include <yaz/tpath.h>
24#include <yaz/z-opac.h>
25#include <yaz/xml_get.h>
26#include <yaz/url.h>
27#include <yaz/srw.h>
28#include <yaz/timing.h>
29
30#if YAZ_HAVE_XML2
31#include <libxml/parser.h>
32#include <libxml/tree.h>
33#include <libxml/xinclude.h>
34#include <libxml/xpath.h>
35#include <libxml/xpathInternals.h>
36#if YAZ_HAVE_XSLT
37#include <libxslt/xsltutils.h>
38#include <libxslt/transform.h>
39#endif
40#if YAZ_HAVE_EXSLT
41#include <libexslt/exslt.h>
42#endif
43
61
70
77
80{
81
82 struct yaz_record_conv_rule *r;
83 for (r = p->rules; r; r = r->next)
84 {
85 r->type->destroy(r->info);
86 }
88 nmem_reset(p->nmem);
89
90 p->rules = 0;
91
92 p->rules_p = &p->rules;
93}
94
96{
97 if (p)
98 {
100 nmem_destroy(p->nmem);
102
103 xfree(p->path);
104 xfree(p);
105 }
106}
107
108#if YAZ_HAVE_XSLT
109struct xslt_info {
111 xmlDocPtr xsp_doc;
112 const char **xsl_parms;
113};
114
115static void *construct_xslt(const xmlNode *ptr,
116 const char *path, WRBUF wr_error)
117{
118 struct _xmlAttr *attr;
119 const char *stylesheet = 0;
120 struct xslt_info *info = 0;
121 NMEM nmem = 0;
122 int max_parms = 10;
123 int no_parms = 0;
124
125 if (strcmp((const char *) ptr->name, "xslt"))
126 return 0;
127
128 for (attr = ptr->properties; attr; attr = attr->next)
129 {
130 if (!xmlStrcmp(attr->name, BAD_CAST "stylesheet") &&
131 attr->children && attr->children->type == XML_TEXT_NODE)
132 stylesheet = (const char *) attr->children->content;
133 else
134 {
135 wrbuf_printf(wr_error, "Bad attribute '%s'"
136 "Expected stylesheet.", attr->name);
137 return 0;
138 }
139 }
140 nmem = nmem_create();
141 info = nmem_malloc(nmem, sizeof(*info));
142 info->nmem = nmem;
143 info->xsl_parms = nmem_malloc(
144 nmem, (2 * max_parms + 1) * sizeof(*info->xsl_parms));
145
146 for (ptr = ptr->children; ptr; ptr = ptr->next)
147 {
148 const char *name = 0;
149 const char *value = 0;
150 char *qvalue = 0;
151 if (ptr->type != XML_ELEMENT_NODE)
152 continue;
153 if (strcmp((const char *) ptr->name, "param"))
154 {
155 wrbuf_printf(wr_error, "Bad element '%s'"
156 "Expected param.", ptr->name);
158 return 0;
159 }
160 for (attr = ptr->properties; attr; attr = attr->next)
161 {
162 if (!xmlStrcmp(attr->name, BAD_CAST "name") &&
163 attr->children && attr->children->type == XML_TEXT_NODE)
164 name = (const char *) attr->children->content;
165 else if (!xmlStrcmp(attr->name, BAD_CAST "value") &&
166 attr->children && attr->children->type == XML_TEXT_NODE)
167 value = (const char *) attr->children->content;
168 else
169 {
170 wrbuf_printf(wr_error, "Bad attribute '%s'"
171 "Expected name or value.", attr->name);
173 return 0;
174 }
175 }
176 if (!name || !value)
177 {
178 wrbuf_printf(wr_error, "Missing attributes name or value");
180 return 0;
181 }
182 if (no_parms >= max_parms)
183 {
184 wrbuf_printf(wr_error, "Too many parameters given");
186 return 0;
187 }
188
189 qvalue = nmem_malloc(nmem, strlen(value) + 3);
190 strcpy(qvalue, "\'");
191 strcat(qvalue, value);
192 strcat(qvalue, "\'");
193
194 info->xsl_parms[2 * no_parms] = nmem_strdup(nmem, name);
195 info->xsl_parms[2 * no_parms + 1] = qvalue;
196 no_parms++;
197 }
198 info->xsl_parms[2 * no_parms] = 0;
199
200 if (!stylesheet)
201 {
202 wrbuf_printf(wr_error, "Element <xslt>: "
203 "attribute 'stylesheet' expected");
205 }
206 else
207 {
208 char fullpath[1024];
209 xsltStylesheetPtr xsp;
210 if (!yaz_filepath_resolve(stylesheet, path, 0, fullpath))
211 {
212 wrbuf_printf(wr_error, "Element <xslt stylesheet=\"%s\"/>:"
213 " could not locate stylesheet '%s'",
214 stylesheet, stylesheet);
215 if (path)
216 wrbuf_printf(wr_error, " with path '%s'", path);
217
219 return 0;
220 }
221 info->xsp_doc = xmlParseFile(fullpath);
222 if (!info->xsp_doc)
223 {
224 wrbuf_printf(wr_error, "Element: <xslt stylesheet=\"%s\"/>:"
225 " xml parse failed: %s", stylesheet, fullpath);
226 if (path)
227 wrbuf_printf(wr_error, " with path '%s'", path);
229 return 0;
230 }
231 /* need to copy this before passing it to the processor. It will
232 be encapsulated in the xsp and destroyed by xsltFreeStylesheet */
233 xsp = xsltParseStylesheetDoc(xmlCopyDoc(info->xsp_doc, 1));
234 if (!xsp)
235 {
236 wrbuf_printf(wr_error, "Element: <xslt stylesheet=\"%s\"/>:"
237 " xslt parse failed: %s", stylesheet, fullpath);
238 if (path)
239 wrbuf_printf(wr_error, " with path '%s'", path);
240 wrbuf_printf(wr_error, " ("
242
243 "EXSLT enabled"
244#else
245 "EXSLT not supported"
246#endif
247 ")");
248 xmlFreeDoc(info->xsp_doc);
249 nmem_destroy(info->nmem);
250 }
251 else
252 {
253 xsltFreeStylesheet(xsp);
254 return info;
255 }
256 }
257 return 0;
258}
259
260static int convert_xslt(void *vinfo, WRBUF record, WRBUF wr_error)
261{
262 int ret = 0;
263 struct xslt_info *info = vinfo;
264
265 xmlDocPtr doc = xmlParseMemory(wrbuf_buf(record),
266 wrbuf_len(record));
267 if (!doc)
268 {
269 wrbuf_printf(wr_error, "xmlParseMemory failed");
270 ret = -1;
271 }
272 else
273 {
274 xmlDocPtr xsp_doc = xmlCopyDoc(info->xsp_doc, 1);
275 xsltStylesheetPtr xsp = xsltParseStylesheetDoc(xsp_doc);
276 xmlDocPtr res = xsltApplyStylesheet(xsp, doc, info->xsl_parms);
277 if (res)
278 {
279 xmlChar *out_buf = 0;
280 int out_len;
281
282#if HAVE_XSLTSAVERESULTTOSTRING
283 xsltSaveResultToString(&out_buf, &out_len, res, xsp);
284#else
285 xmlDocDumpFormatMemory (res, &out_buf, &out_len, 1);
286#endif
287 if (!out_buf)
288 {
289 wrbuf_printf(wr_error,
290 "xsltSaveResultToString failed");
291 ret = -1;
292 }
293 else
294 {
295 wrbuf_rewind(record);
296 wrbuf_write(record, (const char *) out_buf, out_len);
297
298 xmlFree(out_buf);
299 }
300 xmlFreeDoc(res);
301 }
302 else
303 {
304 wrbuf_printf(wr_error, "xsltApplyStylesheet failed");
305 ret = -1;
306 }
307 xmlFreeDoc(doc);
308 xsltFreeStylesheet(xsp); /* frees xsp_doc too */
309 }
310 return ret;
311}
312
313static void destroy_xslt(void *vinfo)
314{
315 struct xslt_info *info = vinfo;
316
317 if (info)
318 {
319 xmlFreeDoc(info->xsp_doc);
320 nmem_destroy(info->nmem);
321 }
322}
323
324/* YAZ_HAVE_XSLT */
325#endif
326
331
332static void *construct_select(const xmlNode *ptr,
333 const char *path, WRBUF wr_error)
334{
335 if (strcmp((const char *) ptr->name, "select"))
336 return 0;
337 else
338 {
339 NMEM nmem = nmem_create();
340 struct select_info *info = nmem_malloc(nmem, sizeof(*info));
341 const char *attr_str;
342 const char *xpath = 0;
343
344 info->nmem = nmem;
345 info->xpath_expr = 0;
346 attr_str = yaz_xml_get_prop(ptr, "path%s", &xpath);
347 if (attr_str)
348 {
349 wrbuf_printf(wr_error, "Bad attribute '%s'"
350 "Expected xpath.", attr_str);
352 return 0;
353 }
354 if (xpath)
355 info->xpath_expr = nmem_strdup(nmem, xpath);
356 return info;
357 }
358}
359
360static int convert_select(void *vinfo, WRBUF record, WRBUF wr_error)
361{
362 int ret = 0;
363 struct select_info *info = vinfo;
364
365 xmlDocPtr doc = xmlParseMemory(wrbuf_buf(record),
366 wrbuf_len(record));
367 if (!doc)
368 {
369 wrbuf_printf(wr_error, "xmlParseMemory failed");
370 ret = -1;
371 }
372 else
373 {
374 xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc);
375 if (xpathCtx && info->xpath_expr)
376 {
377 xmlXPathObjectPtr xpathObj =
378 xmlXPathEvalExpression((const xmlChar *) info->xpath_expr,
379 xpathCtx);
380 if (xpathObj)
381 {
382 xmlNodeSetPtr nodes = xpathObj->nodesetval;
383 if (nodes)
384 {
385 int i;
386 if (nodes->nodeNr > 0)
387 wrbuf_rewind(record);
388 for (i = 0; i < nodes->nodeNr; i++)
389 {
390 xmlNode *ptr = nodes->nodeTab[i];
391 if (ptr->type == XML_ELEMENT_NODE)
392 ptr = ptr->children;
393 for (; ptr; ptr = ptr->next)
394 if (ptr->type == XML_TEXT_NODE)
395 wrbuf_puts(record, (const char *) ptr->content);
396 }
397 }
398 xmlXPathFreeObject(xpathObj);
399 }
400 xmlXPathFreeContext(xpathCtx);
401 }
402 xmlFreeDoc(doc);
403 }
404 return ret;
405}
406
407static void destroy_select(void *vinfo)
408{
409 struct select_info *info = vinfo;
410
411 if (info)
412 nmem_destroy(info->nmem);
413}
414
415
416static void *construct_solrmarc(const xmlNode *ptr,
417 const char *path, WRBUF wr_error)
418{
419 if (strcmp((const char *) ptr->name, "solrmarc"))
420 return 0;
421 return wr_error; /* any non-null ptr will do; we don't use it later*/
422}
423
424static int convert_solrmarc(void *info, WRBUF record, WRBUF wr_error)
425{
426 WRBUF w = wrbuf_alloc();
427 const char *buf = wrbuf_buf(record);
428 size_t i, sz = wrbuf_len(record);
429 for (i = 0; i < sz; i++)
430 {
431 int ch;
432 if (buf[i] == '#' && i < sz - 3 && buf[i+3] == ';'
433 && atoi_n_check(buf+i+1, 2, &ch))
434 i += 3;
435 else
436 ch = buf[i];
437 wrbuf_putc(w, ch);
438 }
439 wrbuf_rewind(record);
440 wrbuf_write(record, wrbuf_buf(w), wrbuf_len(w));
441 wrbuf_destroy(w);
442 return 0;
443}
444
445static void destroy_solrmarc(void *info)
446{
447}
448
449static void *construct_marc(const xmlNode *ptr,
450 const char *path, WRBUF wr_error)
451{
453 struct marc_info *info = nmem_malloc(nmem, sizeof(*info));
454 struct _xmlAttr *attr;
455 const char *input_format = 0;
456 const char *output_format = 0;
457
458 if (strcmp((const char *) ptr->name, "marc"))
459 {
460 nmem_destroy(nmem);
461 return 0;
462 }
463 info->nmem = nmem;
464 info->input_charset = 0;
465 info->output_charset = 0;
466 info->input_format_mode = 0;
467 info->output_format_mode = 0;
468 info->leader_spec = 0;
469
470 for (attr = ptr->properties; attr; attr = attr->next)
471 {
472 if (!xmlStrcmp(attr->name, BAD_CAST "inputcharset") &&
473 attr->children && attr->children->type == XML_TEXT_NODE)
474 info->input_charset = (const char *) attr->children->content;
475 else if (!xmlStrcmp(attr->name, BAD_CAST "outputcharset") &&
476 attr->children && attr->children->type == XML_TEXT_NODE)
477 info->output_charset = (const char *) attr->children->content;
478 else if (!xmlStrcmp(attr->name, BAD_CAST "inputformat") &&
479 attr->children && attr->children->type == XML_TEXT_NODE)
480 input_format = (const char *) attr->children->content;
481 else if (!xmlStrcmp(attr->name, BAD_CAST "outputformat") &&
482 attr->children && attr->children->type == XML_TEXT_NODE)
483 output_format = (const char *) attr->children->content;
484 else if (!xmlStrcmp(attr->name, BAD_CAST "leaderspec") &&
485 attr->children && attr->children->type == XML_TEXT_NODE)
486 info->leader_spec =
487 nmem_strdup(info->nmem, (const char *) attr->children->content);
488 else
489 {
490 wrbuf_printf(wr_error, "Element <marc>: expected attributes"
491 "'inputformat', 'inputcharset', 'outputformat' or"
492 " 'outputcharset', got attribute '%s'",
493 attr->name);
494 nmem_destroy(info->nmem);
495 return 0;
496 }
497 }
498 if (!input_format)
499 {
500 wrbuf_printf(wr_error, "Element <marc>: "
501 "attribute 'inputformat' required");
502 nmem_destroy(info->nmem);
503 return 0;
504 }
505 else if (!strcmp(input_format, "marc"))
506 {
508 }
509 else if (!strcmp(input_format, "xml"))
510 {
515 if (!info->input_charset && info->output_charset)
516 info->input_charset = "utf-8";
517 }
518 else if (!strcmp(input_format, "json"))
519 {
521 }
522 else
523 {
524 wrbuf_printf(wr_error, "Element <marc inputformat='%s'>: "
525 " Unsupported input format"
526 " defined by attribute value",
527 input_format);
528 nmem_destroy(info->nmem);
529 return 0;
530 }
531
532 if (!output_format)
533 {
534 wrbuf_printf(wr_error,
535 "Element <marc>: attribute 'outputformat' required");
536 nmem_destroy(info->nmem);
537 return 0;
538 }
539 else if (!strcmp(output_format, "line"))
540 {
542 }
543 else if (!strcmp(output_format, "marcxml"))
544 {
546 if (info->input_charset && !info->output_charset)
547 info->output_charset = "utf-8";
548 }
549 else if (!strcmp(output_format, "turbomarc"))
550 {
552 if (info->input_charset && !info->output_charset)
553 info->output_charset = "utf-8";
554 }
555 else if (!strcmp(output_format, "marc"))
556 {
558 }
559 else if (!strcmp(output_format, "marcxchange"))
560 {
562 if (info->input_charset && !info->output_charset)
563 info->output_charset = "utf-8";
564 }
565 else if (!strcmp(output_format, "json"))
566 {
568 if (info->input_charset && !info->output_charset)
569 info->output_charset = "utf-8";
570 }
571 else
572 {
573 wrbuf_printf(wr_error, "Element <marc outputformat='%s'>: "
574 " Unsupported output format"
575 " defined by attribute value",
576 output_format);
577 nmem_destroy(info->nmem);
578 return 0;
579 }
580 if (info->input_charset && info->output_charset)
581 {
583 info->input_charset);
584 if (!cd)
585 {
586 wrbuf_printf(wr_error,
587 "Element <marc inputcharset='%s' outputcharset='%s'>:"
588 " Unsupported character set mapping"
589 " defined by attribute values",
590 info->input_charset, info->output_charset);
591 nmem_destroy(info->nmem);
592 return 0;
593 }
594 yaz_iconv_close(cd);
595 }
596 else if (!info->output_charset)
597 {
598 wrbuf_printf(wr_error, "Element <marc>: "
599 "attribute 'outputcharset' missing");
600 nmem_destroy(info->nmem);
601 return 0;
602 }
603 else if (!info->input_charset)
604 {
605 wrbuf_printf(wr_error, "Element <marc>: "
606 "attribute 'inputcharset' missing");
607 nmem_destroy(info->nmem);
608 return 0;
609 }
610 info->input_charset = nmem_strdup(info->nmem, info->input_charset);
611 info->output_charset = nmem_strdup(info->nmem, info->output_charset);
612 return info;
613}
614
615static int convert_marc(void *info, WRBUF record, WRBUF wr_error)
616{
617 struct marc_info *mi = info;
618 const char *input_charset = mi->input_charset;
619 int ret = 0;
621
623 if (mi->leader_spec)
625
627 {
628 int sz = yaz_marc_read_iso2709(mt, wrbuf_buf(record),
629 wrbuf_len(record));
630 if (sz > 0)
631 {
633 wrbuf_len(record)))
634 input_charset = "utf-8";
635 ret = 0;
636 }
637 else
638 ret = -1;
639 }
640 else if (mi->input_format_mode == YAZ_MARC_MARCXML ||
642 {
643 xmlDocPtr doc = xmlParseMemory(wrbuf_buf(record),
644 wrbuf_len(record));
645 if (!doc)
646 {
647 wrbuf_printf(wr_error, "xmlParseMemory failed");
648 ret = -1;
649 }
650 else
651 {
652 ret = yaz_marc_read_xml(mt, xmlDocGetRootElement(doc));
653 if (ret)
654 wrbuf_printf(wr_error, "yaz_marc_read_xml failed");
655 }
656 xmlFreeDoc(doc);
657 }
658 else
659 {
660 wrbuf_printf(wr_error, "unsupported input format");
661 ret = -1;
662 }
663 if (ret == 0)
664 {
666
667 if (cd)
668 yaz_marc_iconv(mt, cd);
669
670 wrbuf_rewind(record);
671 ret = yaz_marc_write_mode(mt, record);
672 if (ret)
673 wrbuf_printf(wr_error, "yaz_marc_write_mode failed");
674 if (cd)
675 yaz_iconv_close(cd);
676 }
678 return ret;
679}
680
681static void destroy_marc(void *info)
682{
683 struct marc_info *mi = info;
684 nmem_destroy(mi->nmem);
685}
686
687
688
689/* each info covers one lookup xpath. They all share the nmem and namespaces*/
690#define RDF_LOOKUP_MAX_KEYS 20
691#define RDF_LOOKUP_MAX_NAMESPACES 20
703
705 const xmlNode *ptr,
706 WRBUF wr_error,
707 int timeout)
708{
709 struct _xmlAttr *attr;
710 struct rdf_lookup_info *info = nmem_malloc(nmem, sizeof(*info));
711 int nkeys = 0;
712 info->nmem = nmem;
713 info->next = 0;
714 info->xpath = 0;
715 info->server = 0;
716 info->method = 0;
717 info->debug = 0;
718 info->timeout = timeout;
719 info->namespacelist = 0;
720 for (attr = ptr->properties; attr; attr = attr->next)
721 {
722 if (!xmlStrcmp(attr->name, BAD_CAST "xpath") &&
723 attr->children && attr->children->type == XML_TEXT_NODE)
724 info->xpath = nmem_strdup(nmem, (const char *) attr->children->content);
725 else
726 {
727 wrbuf_printf(wr_error, "Bad attribute '%s'"
728 "Expected xpath.", attr->name);
729 return 0;
730 }
731 }
732 ptr = ptr->children;
733 for ( ; ptr ; ptr = ptr->next)
734 {
735 if (ptr->type == XML_ELEMENT_NODE)
736 {
737 if (!xmlStrcmp(ptr->name, BAD_CAST "key"))
738 {
739 for (attr = ptr->properties; attr; attr = attr->next)
740 {
741 if (!xmlStrcmp(attr->name, BAD_CAST "field") &&
742 attr->children && attr->children->type == XML_TEXT_NODE)
743 {
744 info->keys[nkeys++] =
745 nmem_strdup(nmem, (const char *) attr->children->content);
746 if (nkeys >= RDF_LOOKUP_MAX_KEYS)
747 {
748 wrbuf_printf(wr_error, "Too many keys, max %d", RDF_LOOKUP_MAX_KEYS);
749 return 0;
750 }
751 info->keys[nkeys] = 0;
752 }
753 else
754 {
755 wrbuf_printf(wr_error, "Bad attribute '%s'. "
756 "Expected xpath.", attr->name);
757 return 0;
758 }
759 }
760 }
761 else if (!xmlStrcmp(ptr->name, BAD_CAST "server"))
762 {
763 for (attr = ptr->properties; attr; attr = attr->next)
764 {
765 if (!xmlStrcmp(attr->name, BAD_CAST "url") &&
766 attr->children && attr->children->type == XML_TEXT_NODE)
767 {
768 info->server = nmem_strdup(nmem, (const char *) attr->children->content);
769 }
770 else if (!xmlStrcmp(attr->name, BAD_CAST "method") &&
771 attr->children && attr->children->type == XML_TEXT_NODE)
772 {
773 info->method = nmem_strdup(nmem, (const char *) attr->children->content);
774 }
775 else
776 {
777 wrbuf_printf(wr_error, "Bad attribute '%s'. "
778 "Expected url or method.", attr->name);
779 return 0;
780 }
781 }
782 }
783 else
784 {
785 wrbuf_printf(wr_error, "Bad tag '%s'. "
786 "Expected 'key' or 'server'.", ptr->name);
787 return 0;
788 }
789 }
790 }
791 return info;
792}
793
794static void *construct_rdf_lookup(const xmlNode *ptr,
795 const char *path, WRBUF wr_error)
796{
797 NMEM nmem = 0;
798 struct rdf_lookup_info *info = 0;
799 struct rdf_lookup_info **next = &info;
800 const char *defserver = "http://id.loc.gov/authorities/names/label/%s";
801 char ** namespaces = 0;
802 int debug = 0;
803 int nns = 0;
804 int timeout = 0;
805 struct _xmlAttr *attr;
806 if (strcmp((const char *) ptr->name, "rdf-lookup"))
807 return 0;
808 yaz_log(YLOG_DEBUG, "Constructing rdf_lookup.");
809
810 for (attr = ptr->properties; attr; attr = attr->next)
811 {
812 if (!xmlStrcmp(attr->name, BAD_CAST "debug") &&
813 attr->children && attr->children->type == XML_TEXT_NODE)
814 {
815 debug = atoi((const char *) attr->children->content);
816 }
817 else if (!xmlStrcmp(attr->name, BAD_CAST "timeout") &&
818 attr->children && attr->children->type == XML_TEXT_NODE)
819 {
820 timeout = atoi((const char *) attr->children->content);
821 }
822 else
823 {
824 wrbuf_printf(wr_error, "Bad attribute '%s' for <rdf-lookup>. "
825 "Expected 'debug'", attr->name);
826 return 0;
827 }
828 }
829 nmem = nmem_create();
830 namespaces = nmem_malloc(nmem, RDF_LOOKUP_MAX_NAMESPACES *
831 2 * sizeof(char *));
832 namespaces[0] = 0;
833
834 ptr = ptr->children;
835 for ( ; ptr ; ptr = ptr->next) {
836 if (ptr->type == XML_ELEMENT_NODE)
837 {
838 if (!strcmp((const char *)ptr->name, "lookup"))
839 {
840 struct rdf_lookup_info *i = construct_one_rdf_lookup(nmem, ptr, wr_error, timeout);
841 if (!i)
842 {
844 return 0; /* error already in wr_error */
845 }
846 else
847 {
848 i->namespacelist = namespaces;
849 i->debug = debug;
850 *next = i;
851 next = &((*next)->next);
852 if (! i->server)
853 i->server = nmem_strdup(nmem, defserver);
854 else
855 defserver = i->server;
856 if (! i->method)
857 i->method = nmem_strdup(nmem, "GET");
858 yaz_log(YLOG_DEBUG, "lookup: x=%s k[0]:%s, %s %s",
859 i->xpath, i->keys[0], i->method, i->server);
860 }
861 }
862 else if (!strcmp((const char *)ptr->name, "namespace"))
863 {
864 char * prefix = 0;
865 char * href = 0;
866 struct _xmlAttr *attr;
867 for (attr = ptr->properties; attr; attr = attr->next)
868 {
869 if (!xmlStrcmp(attr->name, BAD_CAST "prefix") &&
870 attr->children && attr->children->type == XML_TEXT_NODE)
871 {
872 prefix = nmem_strdup(nmem, (const char *) attr->children->content);
873 }
874 else if (!xmlStrcmp(attr->name, BAD_CAST "href") &&
875 attr->children && attr->children->type == XML_TEXT_NODE)
876 {
877 href = nmem_strdup(nmem, (const char *) attr->children->content);
878 }
879 else
880 {
881 wrbuf_printf(wr_error, "Bad attribute '%s'. "
882 "Expected 'prefix' or 'href'", attr->name);
883 nmem_destroy(nmem);
884 return 0;
885 }
886 }
887 if (prefix && href)
888 {
889 namespaces[nns++] = prefix;
890 namespaces[nns++] = href;
891 namespaces[nns] = 0 ; /* signal end */
892 }
893 else
894 {
895 wrbuf_printf(wr_error, "Bad namespace, need both 'prefix' and 'href'");
896 nmem_destroy(nmem);
897 return 0;
898 }
899 }
900 else
901 {
902 wrbuf_printf(wr_error, "Expected a <lookup> tag under rdf-lookup, not <%s>",
903 ptr->name);
904 nmem_destroy(nmem);
905 return 0;
906 }
907 }
908 }
909 return info;
910}
911
912static void destroy_rdf_lookup(void *info)
913{
914 struct rdf_lookup_info *inf = info;
915 yaz_log(YLOG_DEBUG, "Destroying rdf_lookup");
916 nmem_destroy(inf->nmem);
917}
918
919/* Little helper to add a XML comment */
920static void rdf_lookup_debug_comment(xmlNode *n,
921 WRBUF uri,
922 Z_HTTP_Response *resp,
923 struct rdf_lookup_info *info,
924 yaz_timing_t tim,
925 const char *msg,
926 int yloglevel)
927{
928 WRBUF com = wrbuf_alloc();
929 wrbuf_printf(com, " rdf-lookup %s ", info->method);
930 wrbuf_puts_replace_str(com, wrbuf_cstr(uri), "--", "%2D%2D");
931 wrbuf_printf(com, " took %g sec", yaz_timing_get_real(tim));
932 if (resp)
933 wrbuf_printf(com, " and resulted in %d", resp->code);
934 if (msg)
935 {
936 wrbuf_puts(com, " ");
937 wrbuf_puts(com, msg);
938 }
939 yaz_log(yloglevel, "%s", wrbuf_cstr(com) + 1); /* no leading space here */
940 wrbuf_puts(com, " "); /* lead+suffix space in XML comment */
941 if (info->debug)
942 {
943 xmlNodePtr comnode = xmlNewComment((const xmlChar *)wrbuf_cstr(com));
944 xmlAddNextSibling(n, comnode);
945 }
946 wrbuf_destroy(com);
947}
948
949static void rdf_lookup_node(xmlNode *n, xmlXPathContextPtr xpathCtx,
950 struct rdf_lookup_info *info)
951{
952 int i;
953 int nkey;
954 int done = 0;
955 WRBUF uri = wrbuf_alloc();
956 xpathCtx->node = n;
957 for (nkey = 0; !done && info->keys[nkey]; nkey++)
958 {
959 xmlXPathObjectPtr xpo =
960 xmlXPathEvalExpression((const xmlChar *)info->keys[nkey], xpathCtx);
961 xmlNodeSetPtr fldNodes = xpo->nodesetval;
962 yaz_log(YLOG_DEBUG, "lookup_node: %d: %s", nkey, info->keys[nkey]);
963 if (fldNodes)
964 {
965 for (i = 0; !done && i < fldNodes->nodeNr; i++)
966 {
967 xmlNode *f = fldNodes->nodeTab[i];
968 if (f->type == XML_ELEMENT_NODE)
969 f = f->children;
970 for (; f && !done; f = f->next)
971 if (f->type == XML_TEXT_NODE)
972 {
974 Z_HTTP_Response *resp;
975 char *keybuf = xmalloc(3*strlen((const char*) f->content)+1);
977 yaz_url_set_max_redirects(url, 0); /* we just want the first redirect */
978 if (info->timeout)
979 yaz_url_set_timeout(url, info->timeout, 0);
980 yaz_log(YLOG_DEBUG, "Found key '%s'", (const char*) f->content);
981 yaz_encode_uri_component(keybuf, (const char*) f->content);
982 wrbuf_rewind(uri);
983 wrbuf_printf(uri, info->server, keybuf);
984 xfree(keybuf);
985 yaz_log(YLOG_DEBUG, "Fetching '%s'", wrbuf_cstr(uri));
986 yaz_timing_start(tim);
987 /* no hdrs, no body */
988 resp = yaz_url_exec(url, wrbuf_cstr(uri),
989 info->method, 0, 0, 0);
990 yaz_timing_stop(tim);
991 if (resp)
992 {
993 yaz_log(YLOG_DEBUG, "resp code %d, headers %p", resp->code, resp->headers);
994 if ((resp->code == 302 || resp->code == 200)
995 && resp->headers)
996 {
997 const char *newuri = z_HTTP_header_lookup(resp->headers, "X-Uri");
998 if (newuri && *newuri)
999 {
1000 xmlSetProp(n, (const xmlChar *)"rdf:about",
1001 (const xmlChar *)newuri);
1002 done = 1;
1003 rdf_lookup_debug_comment(f->parent, uri,
1004 resp, info, tim, newuri, YLOG_DEBUG);
1005 }
1006 else
1007 {
1008 yaz_log(YLOG_LOG, "rdf-lookup: Got no X-Uri for %s",
1009 wrbuf_cstr(uri));
1010 rdf_lookup_debug_comment(f->parent, uri, resp, info, tim,
1011 "No X-URI Header in response!", YLOG_LOG);
1012 }
1013 }
1014 else
1015 {
1016 rdf_lookup_debug_comment(f->parent, uri, resp,
1017 info, tim, NULL, YLOG_LOG);
1018 }
1019 if (!done)
1020 { /* something went wrong, dump headers and message */
1021 const char *err = yaz_url_get_error(url);
1022 Z_HTTP_Header *r = resp->headers;
1023 for ( ; r; r = r->next)
1024 yaz_log(YLOG_DEBUG, " %s: %s", r->name, r->value);
1025 if (resp->content_len > 0)
1026 {
1027 int i = 0;
1028 for (i = 0; i < resp->content_len; i++)
1029 {
1030 if (strchr(" \r\n", resp->content_buf[i]))
1031 i++;
1032 }
1033 if (i < resp->content_len)
1034 yaz_log(YLOG_LOG, "Response: %*.s",
1035 resp->content_len - i,
1036 resp->content_buf + i);
1037 }
1038 if (err && *err)
1039 yaz_log(YLOG_LOG, "Error: %s", err);
1040 }
1041 }
1042 else
1043 {
1044 rdf_lookup_debug_comment(f->parent, uri, resp, info, tim,
1045 "NO RESPONSE", YLOG_LOG);
1046 }
1047 yaz_timing_destroy(&tim);
1048 yaz_url_destroy(url);
1049 }
1050 }
1051 }
1052 xmlXPathFreeObject(xpo);
1053 }
1054 wrbuf_destroy(uri);
1055}
1056
1057static int convert_rdf_lookup(void *rinfo, WRBUF record, WRBUF wr_error)
1058{
1059 int ret = 0;
1060 struct rdf_lookup_info *info = rinfo;
1061
1062 xmlDocPtr doc = xmlParseMemory(wrbuf_buf(record),
1063 wrbuf_len(record));
1064 yaz_log(YLOG_DEBUG, "rdf_lookup convert starting");
1065 if (!doc)
1066 {
1067 wrbuf_printf(wr_error, "xmlParseMemory failed");
1068 ret = -1;
1069 }
1070 else
1071 {
1072 xmlChar *out_buf = 0;
1073 int out_len;
1074 xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc);
1075 if (xpathCtx)
1076 {
1077 char **ns = info->namespacelist;
1078 while (*ns)
1079 {
1080 xmlXPathRegisterNs(xpathCtx, (const xmlChar *)ns[0],
1081 (const xmlChar *)ns[1]);
1082 ns += 2;
1083 }
1084 while (info)
1085 {
1086 xmlXPathObjectPtr xpathObj =
1087 xmlXPathEvalExpression((xmlChar *)(info->xpath), xpathCtx);
1088 yaz_log(YLOG_DEBUG, "xpath: %p %s", xpathObj, info->xpath);
1089 if (xpathObj)
1090 {
1091 xmlNodeSetPtr nodes = xpathObj->nodesetval;
1092 yaz_log(YLOG_DEBUG, "nodeset: %p", nodes);
1093 if (nodes)
1094 {
1095 int i;
1096 for (i = 0; i < nodes->nodeNr; i++)
1097 {
1098 xmlNode *ptr = nodes->nodeTab[i];
1099 yaz_log(YLOG_DEBUG, " node %d: t=%d n='%s' c='%s'", i, ptr->type,
1100 (const char*) ptr->name, ptr->content);
1101 rdf_lookup_node(ptr, xpathCtx, info);
1102 }
1103 }
1104 xmlXPathFreeObject(xpathObj);
1105 }
1106 else
1107 {
1108 wrbuf_printf(wr_error,
1109 "Cannot compile X-Path expr: %s",
1110 info->xpath);
1111 ret = -1;
1112 }
1113 info = info->next;
1114 }
1115 xmlXPathFreeContext(xpathCtx);
1116 }
1117 xmlDocDumpFormatMemory (doc, &out_buf, &out_len, 1);
1118 if (!out_buf)
1119 {
1120 wrbuf_printf(wr_error,
1121 "xmlDocDumpFormatMemory failed");
1122 ret = -1;
1123 }
1124 else
1125 {
1126 wrbuf_rewind(record);
1127 wrbuf_write(record, (const char *) out_buf, out_len);
1128
1129 xmlFree(out_buf);
1130 }
1131 xmlFreeDoc(doc);
1132 }
1133 return ret;
1134}
1135
1137 struct yaz_record_conv_type *types)
1138{
1139 struct yaz_record_conv_type bt[5];
1140 size_t i = 0;
1141
1142 /* register marc */
1143 bt[i].construct = construct_marc;
1144 bt[i].convert = convert_marc;
1145 bt[i++].destroy = destroy_marc;
1146
1147 bt[i-1].next = &bt[i];
1149 bt[i].convert = convert_solrmarc;
1150 bt[i++].destroy = destroy_solrmarc;
1151
1152 bt[i-1].next = &bt[i];
1154 bt[i].convert = convert_select;
1155 bt[i++].destroy = destroy_select;
1156
1157#if YAZ_HAVE_XSLT
1158 /* register xslt */
1159 bt[i-1].next = &bt[i];
1160 bt[i].construct = construct_xslt;
1161 bt[i].convert = convert_xslt;
1162 bt[i++].destroy = destroy_xslt;
1163
1164 /* register rdf_lookup */
1165 bt[i-1].next = &bt[i];
1168 bt[i++].destroy = destroy_rdf_lookup;
1169#endif
1170
1171 bt[i-1].next = types;
1173
1174 /* parsing element children */
1175 for (ptr = ptr->children; ptr; ptr = ptr->next)
1176 {
1177 struct yaz_record_conv_type *t;
1178 struct yaz_record_conv_rule *r;
1179 void *info = 0;
1180 if (ptr->type != XML_ELEMENT_NODE)
1181 continue;
1182 for (t = &bt[0]; t; t = t->next)
1183 {
1185 info = t->construct(ptr, p->path, p->wr_error);
1186
1187 if (info || wrbuf_len(p->wr_error))
1188 break;
1189 /* info== 0 and no error reported , ie not handled by it */
1190 }
1191 if (!info)
1192 {
1193 if (wrbuf_len(p->wr_error) == 0)
1194 wrbuf_printf(p->wr_error, "Element <backend>: "
1195 "unsupported element <%s>", ptr->name);
1196 return -1;
1197 }
1198 r = (struct yaz_record_conv_rule *) nmem_malloc(p->nmem, sizeof(*r));
1199 r->next = 0;
1200 r->info = info;
1201 r->type = nmem_malloc(p->nmem, sizeof(*t));
1202 memcpy(r->type, t, sizeof(*t));
1203 *p->rules_p = r;
1204 p->rules_p = &r->next;
1205 }
1206 return 0;
1207}
1208
1210{
1211 return yaz_record_conv_configure_t(p, ptr, 0);
1212}
1213
1215 struct yaz_record_conv_rule *r,
1216 const char *input_record_buf,
1217 size_t input_record_len,
1218 WRBUF output_record)
1219{
1220 int ret = 0;
1221 WRBUF record = output_record; /* pointer transfer */
1223
1224 wrbuf_write(record, input_record_buf, input_record_len);
1225 for (; ret == 0 && r; r = r->next)
1226 ret = r->type->convert(r->info, record, p->wr_error);
1227 return ret;
1228}
1229
1231{
1232 struct yaz_record_conv_rule *r = p->rules;
1233 if (r && r->type->construct == construct_marc)
1234 {
1235 struct marc_info *mi = r->info;
1236 return mi->output_charset;
1237 }
1238 return 0;
1239}
1240
1242 Z_OPACRecord *input_record,
1243 WRBUF output_record)
1244{
1245 int ret = 0;
1246 struct yaz_record_conv_rule *r = p->rules;
1247 if (!r || r->type->construct != construct_marc)
1248 {
1249 wrbuf_puts(p->wr_error, "Expecting MARC rule as first rule for OPAC");
1250 ret = -1; /* no marc rule so we can't do OPAC */
1251 }
1252 else
1253 {
1254 struct marc_info *mi = r->info;
1255 const char *input_charset = mi->input_charset;
1256 yaz_iconv_t cd;
1257
1258 WRBUF res = wrbuf_alloc();
1260
1262 input_charset = "utf-8";
1263 cd = yaz_iconv_open("utf-8", input_charset);
1264
1267
1268 if (mi->leader_spec)
1270
1271 yaz_marc_iconv(mt, cd);
1272
1273 yaz_opac_decode_wrbuf(mt, input_record, res);
1274 if (ret != -1)
1275 {
1277 r->next,
1278 wrbuf_buf(res), wrbuf_len(res),
1279 output_record);
1280 }
1281 yaz_marc_destroy(mt);
1282 if (cd)
1283 yaz_iconv_close(cd);
1284 wrbuf_destroy(res);
1285 }
1286 return ret;
1287}
1288
1290 const char *input_record_buf,
1291 size_t input_record_len,
1292 WRBUF output_record)
1293{
1295 input_record_buf,
1296 input_record_len, output_record);
1297}
1298
1300{
1301 return wrbuf_cstr(p->wr_error);
1302}
1303
1305{
1306 xfree(p->path);
1307 p->path = 0;
1308 if (path)
1309 p->path = xstrdup(path);
1310}
1311
1313{
1315 p->nmem = nmem_create();
1316 p->wr_error = wrbuf_alloc();
1317 p->rules = 0;
1318 p->path = 0;
1319 return p;
1320}
1321
1322/* YAZ_HAVE_XML2 */
1323#endif
1324
1325/*
1326 * Local variables:
1327 * c-basic-offset: 4
1328 * c-file-style: "Stroustrup"
1329 * indent-tabs-mode: nil
1330 * End:
1331 * vim: shiftwidth=4 tabstop=8 expandtab
1332 */
1333
int atoi_n_check(const char *buf, int size, int *val)
like atoi_n but checks for proper formatting
Definition atoin.c:32
#define YAZ_HAVE_EXSLT
Definition config.h:218
void debug(struct SN_env *z, int number, int line_count)
const char * z_HTTP_header_lookup(const Z_HTTP_Header *hp, const char *n)
Definition http.c:233
char * name
Definition initopt.c:18
void yaz_log(int level, const char *fmt,...)
Writes log message.
Definition log.c:487
Logging utility.
#define YLOG_DEBUG
log level: debugging
Definition log.h:44
#define YLOG_LOG
log level: log (regular)
Definition log.h:48
int yaz_marc_read_iso2709(yaz_marc_t mt, const char *buf, int bsize)
read ISO2709/MARC record from buffer
int yaz_marc_read_xml(yaz_marc_t mt, const xmlNode *ptr)
parses MARCXML/MarcXchange/TurboMARC record from xmlNode pointer
int yaz_marc_leader_spec(yaz_marc_t mt, const char *leader_spec)
sets leader spec (for modifying bytes in 24 byte leader)
Definition marcdisp.c:1410
int yaz_marc_check_marc21_coding(const char *charset, const char *marc_buf, int sz)
check if MARC21 is UTF-8 encoded
Definition marcdisp.c:1490
yaz_marc_t yaz_marc_create(void)
construct yaz_marc_t handle
Definition marcdisp.c:102
void yaz_marc_iconv(yaz_marc_t mt, yaz_iconv_t cd)
set iconv handle for character set conversion
Definition marcdisp.c:1387
void yaz_marc_xml(yaz_marc_t mt, int xmlmode)
set XML mode YAZ_MARC_LINE, YAZ_MARCXML, YAZ_MARC_ISO2709 ..
Definition marcdisp.c:1376
void yaz_marc_destroy(yaz_marc_t mt)
destroy yaz_marc_t handle
Definition marcdisp.c:120
int yaz_marc_write_mode(yaz_marc_t mt, WRBUF wr)
writes record in mode - given by yaz_marc_xml mode
Definition marcdisp.c:623
MARC conversion.
#define YAZ_MARC_MARCXML
Output format: MARCXML.
Definition marcdisp.h:70
#define YAZ_MARC_XCHANGE
Output format: MarcXchange (ISO25577)
Definition marcdisp.h:74
#define YAZ_MARC_ISO2709
Output format: ISO2709.
Definition marcdisp.h:72
#define YAZ_MARC_LINE
Output format: Line-format.
Definition marcdisp.h:64
#define YAZ_MARC_JSON
Output format: JSON.
Definition marcdisp.h:80
#define YAZ_MARC_TURBOMARC
Output format: Turbo MARC Index Data format (XML based)
Definition marcdisp.h:78
void nmem_reset(NMEM n)
releases memory associaged with an NMEM handle
Definition nmem.c:129
NMEM nmem_create(void)
returns new NMEM handle
Definition nmem.c:181
void * nmem_malloc(NMEM n, size_t size)
allocates memory block on NMEM handle
Definition nmem.c:145
void nmem_destroy(NMEM n)
destroys NMEM handle and memory associated with it
Definition nmem.c:204
Header for Nibble Memory functions.
char * nmem_strdup(NMEM mem, const char *src)
allocates string on NMEM handle (similar strdup)
Definition nmemsdup.c:18
int yaz_opac_check_marc21_coding(const char *charset, Z_OPACRecord *r)
void yaz_opac_decode_wrbuf(yaz_marc_t mt, Z_OPACRecord *r, WRBUF wrbuf)
Performs "pretty" display of OPAC record to WRBUF using marc_t.
static void * construct_marc(const xmlNode *ptr, const char *path, WRBUF wr_error)
static void destroy_marc(void *info)
int yaz_record_conv_configure_t(yaz_record_conv_t p, const xmlNode *ptr, struct yaz_record_conv_type *types)
static void * construct_rdf_lookup(const xmlNode *ptr, const char *path, WRBUF wr_error)
void yaz_record_conv_destroy(yaz_record_conv_t p)
Definition record_conv.c:95
static void destroy_rdf_lookup(void *info)
static int convert_solrmarc(void *info, WRBUF record, WRBUF wr_error)
const char * yaz_record_conv_get_error(yaz_record_conv_t p)
const char * yaz_record_get_output_charset(yaz_record_conv_t p)
void yaz_record_conv_set_path(yaz_record_conv_t p, const char *path)
#define RDF_LOOKUP_MAX_NAMESPACES
static int yaz_record_conv_record_rule(yaz_record_conv_t p, struct yaz_record_conv_rule *r, const char *input_record_buf, size_t input_record_len, WRBUF output_record)
int yaz_record_conv_record(yaz_record_conv_t p, const char *input_record_buf, size_t input_record_len, WRBUF output_record)
static struct rdf_lookup_info * construct_one_rdf_lookup(NMEM nmem, const xmlNode *ptr, WRBUF wr_error, int timeout)
#define RDF_LOOKUP_MAX_KEYS
static void * construct_solrmarc(const xmlNode *ptr, const char *path, WRBUF wr_error)
yaz_record_conv_t yaz_record_conv_create()
static void * construct_select(const xmlNode *ptr, const char *path, WRBUF wr_error)
static void rdf_lookup_debug_comment(xmlNode *n, WRBUF uri, Z_HTTP_Response *resp, struct rdf_lookup_info *info, yaz_timing_t tim, const char *msg, int yloglevel)
static int convert_rdf_lookup(void *rinfo, WRBUF record, WRBUF wr_error)
static void rdf_lookup_node(xmlNode *n, xmlXPathContextPtr xpathCtx, struct rdf_lookup_info *info)
static void destroy_xslt(void *vinfo)
int yaz_record_conv_configure(yaz_record_conv_t p, const xmlNode *ptr)
static int convert_marc(void *info, WRBUF record, WRBUF wr_error)
int yaz_record_conv_opac_record(yaz_record_conv_t p, Z_OPACRecord *input_record, WRBUF output_record)
static void destroy_solrmarc(void *info)
static int convert_select(void *vinfo, WRBUF record, WRBUF wr_error)
static void * construct_xslt(const xmlNode *ptr, const char *path, WRBUF wr_error)
static void destroy_select(void *vinfo)
static void yaz_record_conv_reset(yaz_record_conv_t p)
reset rules+configuration
Definition record_conv.c:79
static int convert_xslt(void *vinfo, WRBUF record, WRBUF wr_error)
Record Conversions Utility.
struct yaz_record_conv_struct * yaz_record_conv_t
Definition record_conv.h:45
int yaz_iconv_close(yaz_iconv_t cd)
just like iconv_close(3)
Definition siconv.c:284
yaz_iconv_t yaz_iconv_open(const char *tocode, const char *fromcode)
just like iconv_open(3)
Definition siconv.c:95
Header for SRW/SRU.
char * name
Definition zgdu.h:43
Z_HTTP_Header * next
Definition zgdu.h:45
char * value
Definition zgdu.h:44
char * content_buf
Definition zgdu.h:61
Z_HTTP_Header * headers
Definition zgdu.h:60
int content_len
Definition zgdu.h:62
int output_format_mode
Definition record_conv.c:67
const char * leader_spec
Definition record_conv.c:68
const char * output_charset
Definition record_conv.c:65
int input_format_mode
Definition record_conv.c:66
const char * input_charset
Definition record_conv.c:64
char ** namespacelist
char * keys[RDF_LOOKUP_MAX_KEYS]
struct rdf_lookup_info * next
char * xpath_expr
string buffer
Definition wrbuf.h:43
const char ** xsl_parms
xmlDocPtr xsp_doc
the internals of a yaz_marc_t handle
Definition marcdisp.c:86
transformation info (rule info)
Definition record_conv.c:72
struct yaz_record_conv_type * type
Definition record_conv.c:73
struct yaz_record_conv_rule * next
Definition record_conv.c:75
The internal structure for yaz_record_conv_t.
Definition record_conv.c:45
NMEM nmem
memory for configuration
Definition record_conv.c:47
WRBUF wr_error
string buffer for error messages
Definition record_conv.c:56
char * path
path for opening files
Definition record_conv.c:59
struct yaz_record_conv_rule * rules
conversion rules (allocated using NMEM)
Definition record_conv.c:50
struct yaz_record_conv_rule ** rules_p
pointer to last conversion rule pointer in chain
Definition record_conv.c:53
struct yaz_record_conv_type * next
pointer to next type ; NULL for last
Definition record_conv.h:61
int(* convert)(void *info, WRBUF record, WRBUF error_msg)
converts a record
Definition record_conv.h:68
void *(* construct)(const xmlNode *, const char *path, WRBUF error_msg)
construct and configure a type of ours
Definition record_conv.h:64
void(* destroy)(void *info)
destroys our conversion handler
Definition record_conv.h:71
Definition url.c:20
yaz_timing_t yaz_timing_create(void)
create timing handle
Definition timing.c:47
void yaz_timing_stop(yaz_timing_t t)
stop timer
Definition timing.c:106
void yaz_timing_destroy(yaz_timing_t *tp)
destroys timing handle
Definition timing.c:145
void yaz_timing_start(yaz_timing_t t)
start timer
Definition timing.c:81
double yaz_timing_get_real(yaz_timing_t t)
returns real time in seconds
Definition timing.c:130
Timing utilities.
char * yaz_filepath_resolve(const char *fname, const char *path, const char *base, char *fullpath)
resolve file on path
Definition tpath.c:74
File Path utilities.
void yaz_encode_uri_component(char *dst, const char *uri)
encodes URI component
Definition uri.c:45
void yaz_url_set_timeout(yaz_url_t p, int sec, int ns)
sets I/O timeout
Definition url.c:78
yaz_url_t yaz_url_create(void)
creates a URL fetcher handle
Definition url.c:32
Z_HTTP_Response * yaz_url_exec(yaz_url_t p, const char *uri, const char *method, Z_HTTP_Header *user_headers, const char *buf, size_t len)
executes the actual HTTP request (including redirects, etc)
Definition url.c:132
void yaz_url_set_max_redirects(yaz_url_t p, int num)
sets maximum number of redirects
Definition url.c:68
void yaz_url_destroy(yaz_url_t p)
destroys a URL fetcher
Definition url.c:47
const char * yaz_url_get_error(yaz_url_t p)
get last error from yaz_url_exec
Definition url.c:122
URL fetch utility.
void wrbuf_destroy(WRBUF b)
destroy WRBUF and its buffer
Definition wrbuf.c:38
const char * wrbuf_cstr(WRBUF b)
returns WRBUF content as C-string
Definition wrbuf.c:299
void wrbuf_rewind(WRBUF b)
empty WRBUF content (length of buffer set to 0)
Definition wrbuf.c:47
WRBUF wrbuf_alloc(void)
construct WRBUF
Definition wrbuf.c:25
void wrbuf_printf(WRBUF b, const char *fmt,...)
writes printf result to WRBUF
Definition wrbuf.c:189
void wrbuf_puts_replace_str(WRBUF b, const char *buf, const char *from, const char *to)
puts buf to WRBUF and replaces a string with another
Definition wrbuf.c:113
void wrbuf_puts(WRBUF b, const char *buf)
appends C-string to WRBUF
Definition wrbuf.c:89
void wrbuf_write(WRBUF b, const char *buf, size_t size)
append constant size buffer to WRBUF
Definition wrbuf.c:68
Header for WRBUF (growing buffer)
#define wrbuf_putc(b, c)
Definition wrbuf.h:287
#define wrbuf_buf(b)
Definition wrbuf.h:270
#define wrbuf_len(b)
Definition wrbuf.h:269
Header for memory handling functions.
#define xstrdup(s)
utility macro which calls xstrdup_f
Definition xmalloc.h:55
#define xfree(x)
utility macro which calls xfree_f
Definition xmalloc.h:53
#define xmalloc(x)
utility macro which calls malloc_f
Definition xmalloc.h:49
const char * yaz_xml_get_prop(const xmlNode *n, const char *fmt,...)
Definition xml_get.c:19
XML node getter/creation utilities.
Header for YAZ iconv interface.
ASN.1 Module RecordSyntax-opac.