YAZ  5.34.0
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 
47 static int process_config_includes(yaz_xml_include_t config, xmlNode *n);
48 
49 static 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 
60 static 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 
103 static 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 
145 static 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 
175 int 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 
185 int 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 
void yaz_file_globfree(yaz_glob_res_t *res)
release glob result
Definition: file_glob.c:163
const char * yaz_file_glob_get_file(yaz_glob_res_t res, size_t idx)
return resulting matching file
Definition: file_glob.c:173
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
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:178
const char * wrbuf_cstr(WRBUF b)
returns WRBUF content as C-string
Definition: wrbuf.c:281
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
Definition: xml_include.c:175
static int config_include_src(yaz_xml_include_t config, xmlNode **np, const char *src)
Definition: xml_include.c:103
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)
Definition: xml_include.c:145
int yaz_xml_include_simple(xmlNode *n, const char *base_path)
substitute include nodes in a tree
Definition: xml_include.c:185
XML Include (not to be confused with W3C XInclude)
Header with fundamental macros.