YAZ 5.35.1
xml_include.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 */
5
9#if HAVE_CONFIG_H
10#include <config.h>
11#endif
12
13#include <yaz/yconfig.h>
14
15#if HAVE_SYS_TYPES_H
16#include <sys/types.h>
17#endif
18#include <sys/stat.h>
19#if HAVE_UNISTD_H
20#include <unistd.h>
21#endif
22#include <stdio.h>
23#include <string.h>
24#include <assert.h>
25#include <yaz/wrbuf.h>
26#include <yaz/tpath.h>
27#include <yaz/log.h>
28#include <yaz/xml_include.h>
29
30#ifdef WIN32
31#define S_ISREG(x) (x & _S_IFREG)
32#endif
33
34#if YAZ_HAVE_XML2
35
36#include <libxml/parser.h>
37#include <libxml/tree.h>
38#include <libxml/xinclude.h>
39
41 const char *confdir;
42 unsigned glob_flags;
43};
44
46
47static int process_config_includes(yaz_xml_include_t config, xmlNode *n);
48
49static void conf_dir_path(yaz_xml_include_t config, WRBUF w, const char *src)
50{
51 if (config->confdir && *config->confdir > 0 &&
52 !yaz_is_abspath(src))
53 {
54 wrbuf_printf(w, "%s/%s", config->confdir, src);
55 }
56 else
57 wrbuf_puts(w, src);
58}
59
60static int config_include_one(yaz_xml_include_t config, xmlNode **sib,
61 const char *path)
62{
63 struct stat st;
64 if (stat(path, &st) < 0)
65 {
66 yaz_log(YLOG_FATAL|YLOG_ERRNO, "stat %s", path);
67 return -1;
68 }
69 else
70 {
71 if (S_ISREG(st.st_mode))
72 {
73 xmlDoc *doc = xmlReadFile(path,
74 NULL,
75 XML_PARSE_XINCLUDE
76 + XML_PARSE_NSCLEAN + XML_PARSE_NONET);
77 int r = xmlXIncludeProcess(doc);
78 if (r == -1)
79 {
80 yaz_log(YLOG_FATAL, "XInclude processing failed");
81 return -1;
82 }
83
84 if (doc)
85 {
86 xmlNodePtr t = xmlDocGetRootElement(doc);
87 int ret = process_config_includes(config, t);
88 *sib = xmlAddNextSibling(*sib, xmlCopyNode(t, 1));
89 xmlFreeDoc(doc);
90 if (ret)
91 return -1;
92 }
93 else
94 {
95 yaz_log(YLOG_FATAL, "Could not parse %s", path);
96 return -1;
97 }
98 }
99 }
100 return 0;
101}
102
103static int config_include_src(yaz_xml_include_t config, xmlNode **np,
104 const char *src)
105{
106 int ret = 0; /* return code. OK so far */
107 WRBUF w = wrbuf_alloc();
108 xmlNodePtr sib; /* our sibling that we append */
109 xmlNodePtr c; /* tmp node */
110
111 wrbuf_printf(w, " begin include src=\"%s\" ", src);
112
113 /* replace include element with a 'begin' comment */
114 sib = xmlNewComment((const xmlChar *) wrbuf_cstr(w));
115 xmlReplaceNode(*np, sib);
116
117 xmlFreeNode(*np);
118
119 wrbuf_rewind(w);
120 conf_dir_path(config, w, src);
121 {
122 int glob_ret;
124
125 glob_ret = yaz_file_glob2(wrbuf_cstr(w), &glob_res, config->glob_flags);
126 if (glob_ret == 0)
127 {
128 size_t i;
129 const char *path;
130 for (i = 0; (path = yaz_file_glob_get_file(glob_res, i)); i++)
131 ret = config_include_one(config, &sib, path);
133 }
134 }
135 wrbuf_rewind(w);
136 wrbuf_printf(w, " end include src=\"%s\" ", src);
137 c = xmlNewComment((const xmlChar *) wrbuf_cstr(w));
138 sib = xmlAddNextSibling(sib, c);
139
140 *np = sib;
141 wrbuf_destroy(w);
142 return ret;
143}
144
145static int process_config_includes(yaz_xml_include_t config, xmlNode *n)
146{
147 for (n = n->children; n; n = n->next)
148 {
149 if (n->type == XML_ELEMENT_NODE)
150 {
151 if (!strcmp((const char *) n->name, "include"))
152 {
153 xmlChar *src = xmlGetProp(n, (xmlChar *) "src");
154 if (src)
155 {
156 /* src must be preserved, because n is destroyed */
157 int ret = config_include_src(config, &n,
158 (const char *) src);
159 xmlFree(src);
160 if (ret)
161 return ret;
162
163 }
164 }
165 else
166 {
167 if (process_config_includes(config, n))
168 return -1;
169 }
170 }
171 }
172 return 0;
173}
174
175int yaz_xml_include_glob(xmlNode *n, const char *base_path,
176 unsigned glob_flags)
177{
178 struct yaz_xml_include_s s;
179
180 s.confdir = base_path;
182 return process_config_includes(&s, n);
183}
184
185int yaz_xml_include_simple(xmlNode *n, const char *base_path)
186{
187 return yaz_xml_include_glob(n, base_path, 0);
188}
189
190
191/* YAZ_HAVE_XML2 */
192#endif
193
194/*
195 * Local variables:
196 * c-basic-offset: 4
197 * c-file-style: "Stroustrup"
198 * indent-tabs-mode: nil
199 * End:
200 * vim: shiftwidth=4 tabstop=8 expandtab
201 */
202
const char * yaz_file_glob_get_file(yaz_glob_res_t res, size_t idx)
return resulting matching file
Definition file_glob.c:173
void yaz_file_globfree(yaz_glob_res_t *res)
release glob result
Definition file_glob.c:163
int yaz_file_glob2(const char *pattern, yaz_glob_res_t *res, unsigned flags)
perform glob (with flags)
Definition file_glob.c:146
void yaz_log(int level, const char *fmt,...)
Writes log message.
Definition log.c:487
Logging utility.
#define YLOG_FATAL
log level: fatal
Definition log.h:42
#define YLOG_ERRNO
log level: append system error message
Definition log.h:50
string buffer
Definition wrbuf.h:43
unsigned glob_flags
Definition xml_include.c:42
const char * confdir
Definition xml_include.c:41
int yaz_is_abspath(const char *p)
checks whether path is absolute
Definition tpath.c:127
File Path utilities.
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(WRBUF b, const char *buf)
appends C-string to WRBUF
Definition wrbuf.c:89
Header for WRBUF (growing buffer)
static int config_include_one(yaz_xml_include_t config, xmlNode **sib, const char *path)
Definition xml_include.c:60
int yaz_xml_include_glob(xmlNode *n, const char *base_path, unsigned glob_flags)
substitute include nodes in a tree
static int config_include_src(yaz_xml_include_t config, xmlNode **np, const char *src)
static void conf_dir_path(yaz_xml_include_t config, WRBUF w, const char *src)
Definition xml_include.c:49
struct yaz_xml_include_s * yaz_xml_include_t
Definition xml_include.c:45
static int process_config_includes(yaz_xml_include_t config, xmlNode *n)
int yaz_xml_include_simple(xmlNode *n, const char *base_path)
substitute include nodes in a tree
XML Include (not to be confused with W3C XInclude)
Header with fundamental macros.