@helm2/poc_jenki_rce 0.0.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of @helm2/poc_jenki_rce might be problematic. Click here for more details.

Files changed (160) hide show
  1. package/LICENSE +19 -0
  2. package/Makefile +18 -0
  3. package/README.md +52 -0
  4. package/binding.gyp +81 -0
  5. package/index.d.ts +273 -0
  6. package/index.js +45 -0
  7. package/lib/bindings.js +1 -0
  8. package/lib/document.js +118 -0
  9. package/lib/element.js +82 -0
  10. package/lib/sax_parser.js +38 -0
  11. package/package.json +70 -0
  12. package/src/html_document.cc +7 -0
  13. package/src/html_document.h +18 -0
  14. package/src/libxmljs.cc +252 -0
  15. package/src/libxmljs.h +53 -0
  16. package/src/xml_attribute.cc +173 -0
  17. package/src/xml_attribute.h +40 -0
  18. package/src/xml_comment.cc +117 -0
  19. package/src/xml_comment.h +30 -0
  20. package/src/xml_document.cc +810 -0
  21. package/src/xml_document.h +67 -0
  22. package/src/xml_element.cc +565 -0
  23. package/src/xml_element.h +61 -0
  24. package/src/xml_namespace.cc +158 -0
  25. package/src/xml_namespace.h +39 -0
  26. package/src/xml_node.cc +761 -0
  27. package/src/xml_node.h +73 -0
  28. package/src/xml_pi.cc +161 -0
  29. package/src/xml_pi.h +34 -0
  30. package/src/xml_sax_parser.cc +424 -0
  31. package/src/xml_sax_parser.h +73 -0
  32. package/src/xml_syntax_error.cc +66 -0
  33. package/src/xml_syntax_error.h +25 -0
  34. package/src/xml_text.cc +320 -0
  35. package/src/xml_text.h +48 -0
  36. package/src/xml_textwriter.cc +315 -0
  37. package/src/xml_textwriter.h +62 -0
  38. package/src/xml_xpath_context.cc +70 -0
  39. package/src/xml_xpath_context.h +23 -0
  40. package/vendor/libxml/Copyright +23 -0
  41. package/vendor/libxml/DOCBparser.c +305 -0
  42. package/vendor/libxml/HTMLparser.c +7287 -0
  43. package/vendor/libxml/HTMLtree.c +1200 -0
  44. package/vendor/libxml/Makefile +2983 -0
  45. package/vendor/libxml/SAX.c +180 -0
  46. package/vendor/libxml/SAX2.c +3036 -0
  47. package/vendor/libxml/buf.c +1351 -0
  48. package/vendor/libxml/buf.h +72 -0
  49. package/vendor/libxml/c14n.c +2234 -0
  50. package/vendor/libxml/catalog.c +3828 -0
  51. package/vendor/libxml/chvalid.c +336 -0
  52. package/vendor/libxml/config.h +294 -0
  53. package/vendor/libxml/config.h.gch +0 -0
  54. package/vendor/libxml/debugXML.c +3423 -0
  55. package/vendor/libxml/dict.c +1298 -0
  56. package/vendor/libxml/elfgcchack.h +17818 -0
  57. package/vendor/libxml/enc.h +32 -0
  58. package/vendor/libxml/encoding.c +3975 -0
  59. package/vendor/libxml/entities.c +1163 -0
  60. package/vendor/libxml/error.c +998 -0
  61. package/vendor/libxml/globals.c +1126 -0
  62. package/vendor/libxml/hash.c +1146 -0
  63. package/vendor/libxml/include/libxml/DOCBparser.h +96 -0
  64. package/vendor/libxml/include/libxml/HTMLparser.h +306 -0
  65. package/vendor/libxml/include/libxml/HTMLtree.h +147 -0
  66. package/vendor/libxml/include/libxml/Makefile +725 -0
  67. package/vendor/libxml/include/libxml/Makefile.am +54 -0
  68. package/vendor/libxml/include/libxml/Makefile.in +725 -0
  69. package/vendor/libxml/include/libxml/SAX.h +173 -0
  70. package/vendor/libxml/include/libxml/SAX2.h +178 -0
  71. package/vendor/libxml/include/libxml/c14n.h +128 -0
  72. package/vendor/libxml/include/libxml/catalog.h +182 -0
  73. package/vendor/libxml/include/libxml/chvalid.h +230 -0
  74. package/vendor/libxml/include/libxml/debugXML.h +217 -0
  75. package/vendor/libxml/include/libxml/dict.h +79 -0
  76. package/vendor/libxml/include/libxml/encoding.h +245 -0
  77. package/vendor/libxml/include/libxml/entities.h +151 -0
  78. package/vendor/libxml/include/libxml/globals.h +508 -0
  79. package/vendor/libxml/include/libxml/hash.h +236 -0
  80. package/vendor/libxml/include/libxml/list.h +137 -0
  81. package/vendor/libxml/include/libxml/nanoftp.h +163 -0
  82. package/vendor/libxml/include/libxml/nanohttp.h +81 -0
  83. package/vendor/libxml/include/libxml/parser.h +1243 -0
  84. package/vendor/libxml/include/libxml/parserInternals.h +644 -0
  85. package/vendor/libxml/include/libxml/pattern.h +100 -0
  86. package/vendor/libxml/include/libxml/relaxng.h +217 -0
  87. package/vendor/libxml/include/libxml/schemasInternals.h +958 -0
  88. package/vendor/libxml/include/libxml/schematron.h +142 -0
  89. package/vendor/libxml/include/libxml/threads.h +89 -0
  90. package/vendor/libxml/include/libxml/tree.h +1311 -0
  91. package/vendor/libxml/include/libxml/uri.h +94 -0
  92. package/vendor/libxml/include/libxml/valid.h +458 -0
  93. package/vendor/libxml/include/libxml/xinclude.h +129 -0
  94. package/vendor/libxml/include/libxml/xlink.h +189 -0
  95. package/vendor/libxml/include/libxml/xmlIO.h +368 -0
  96. package/vendor/libxml/include/libxml/xmlautomata.h +146 -0
  97. package/vendor/libxml/include/libxml/xmlerror.h +945 -0
  98. package/vendor/libxml/include/libxml/xmlexports.h +77 -0
  99. package/vendor/libxml/include/libxml/xmlmemory.h +224 -0
  100. package/vendor/libxml/include/libxml/xmlmodule.h +57 -0
  101. package/vendor/libxml/include/libxml/xmlreader.h +428 -0
  102. package/vendor/libxml/include/libxml/xmlregexp.h +222 -0
  103. package/vendor/libxml/include/libxml/xmlsave.h +88 -0
  104. package/vendor/libxml/include/libxml/xmlschemas.h +246 -0
  105. package/vendor/libxml/include/libxml/xmlschemastypes.h +151 -0
  106. package/vendor/libxml/include/libxml/xmlstring.h +140 -0
  107. package/vendor/libxml/include/libxml/xmlunicode.h +202 -0
  108. package/vendor/libxml/include/libxml/xmlversion.h +484 -0
  109. package/vendor/libxml/include/libxml/xmlwin32version.h +239 -0
  110. package/vendor/libxml/include/libxml/xmlwriter.h +488 -0
  111. package/vendor/libxml/include/libxml/xpath.h +564 -0
  112. package/vendor/libxml/include/libxml/xpathInternals.h +632 -0
  113. package/vendor/libxml/include/libxml/xpointer.h +114 -0
  114. package/vendor/libxml/include/win32config.h +122 -0
  115. package/vendor/libxml/include/wsockcompat.h +54 -0
  116. package/vendor/libxml/legacy.c +1343 -0
  117. package/vendor/libxml/libxml.h +134 -0
  118. package/vendor/libxml/list.c +779 -0
  119. package/vendor/libxml/nanoftp.c +2118 -0
  120. package/vendor/libxml/nanohttp.c +1899 -0
  121. package/vendor/libxml/parser.c +15553 -0
  122. package/vendor/libxml/parserInternals.c +2164 -0
  123. package/vendor/libxml/pattern.c +2621 -0
  124. package/vendor/libxml/relaxng.c +11101 -0
  125. package/vendor/libxml/rngparser.c +1595 -0
  126. package/vendor/libxml/runsuite.c +1157 -0
  127. package/vendor/libxml/save.h +36 -0
  128. package/vendor/libxml/schematron.c +1787 -0
  129. package/vendor/libxml/threads.c +1049 -0
  130. package/vendor/libxml/timsort.h +601 -0
  131. package/vendor/libxml/tree.c +10183 -0
  132. package/vendor/libxml/trio.c +6895 -0
  133. package/vendor/libxml/trio.h +230 -0
  134. package/vendor/libxml/triodef.h +228 -0
  135. package/vendor/libxml/trionan.c +914 -0
  136. package/vendor/libxml/trionan.h +84 -0
  137. package/vendor/libxml/triop.h +150 -0
  138. package/vendor/libxml/triostr.c +2112 -0
  139. package/vendor/libxml/triostr.h +144 -0
  140. package/vendor/libxml/uri.c +2561 -0
  141. package/vendor/libxml/valid.c +7138 -0
  142. package/vendor/libxml/xinclude.c +2657 -0
  143. package/vendor/libxml/xlink.c +183 -0
  144. package/vendor/libxml/xmlIO.c +4135 -0
  145. package/vendor/libxml/xmlcatalog.c +624 -0
  146. package/vendor/libxml/xmllint.c +3796 -0
  147. package/vendor/libxml/xmlmemory.c +1163 -0
  148. package/vendor/libxml/xmlmodule.c +468 -0
  149. package/vendor/libxml/xmlreader.c +6033 -0
  150. package/vendor/libxml/xmlregexp.c +8271 -0
  151. package/vendor/libxml/xmlsave.c +2735 -0
  152. package/vendor/libxml/xmlschemas.c +29173 -0
  153. package/vendor/libxml/xmlschemastypes.c +6276 -0
  154. package/vendor/libxml/xmlstring.c +1050 -0
  155. package/vendor/libxml/xmlunicode.c +3179 -0
  156. package/vendor/libxml/xmlwriter.c +4738 -0
  157. package/vendor/libxml/xpath.c +14734 -0
  158. package/vendor/libxml/xpointer.c +2969 -0
  159. package/vendor/libxml/xzlib.c +815 -0
  160. package/vendor/libxml/xzlib.h +19 -0
@@ -0,0 +1,3828 @@
1
+ /**
2
+ * catalog.c: set of generic Catalog related routines
3
+ *
4
+ * Reference: SGML Open Technical Resolution TR9401:1997.
5
+ * http://www.jclark.com/sp/catalog.htm
6
+ *
7
+ * XML Catalogs Working Draft 06 August 2001
8
+ * http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
9
+ *
10
+ * See Copyright for the status of this software.
11
+ *
12
+ * Daniel.Veillard@imag.fr
13
+ */
14
+
15
+ #define IN_LIBXML
16
+ #include "libxml.h"
17
+
18
+ #ifdef LIBXML_CATALOG_ENABLED
19
+ #ifdef HAVE_SYS_TYPES_H
20
+ #include <sys/types.h>
21
+ #endif
22
+ #ifdef HAVE_SYS_STAT_H
23
+ #include <sys/stat.h>
24
+ #endif
25
+ #ifdef HAVE_UNISTD_H
26
+ #include <unistd.h>
27
+ #endif
28
+ #ifdef HAVE_FCNTL_H
29
+ #include <fcntl.h>
30
+ #endif
31
+ #ifdef HAVE_STDLIB_H
32
+ #include <stdlib.h>
33
+ #endif
34
+ #include <string.h>
35
+ #include <libxml/xmlmemory.h>
36
+ #include <libxml/hash.h>
37
+ #include <libxml/uri.h>
38
+ #include <libxml/parserInternals.h>
39
+ #include <libxml/catalog.h>
40
+ #include <libxml/xmlerror.h>
41
+ #include <libxml/threads.h>
42
+ #include <libxml/globals.h>
43
+
44
+ #include "buf.h"
45
+
46
+ #define MAX_DELEGATE 50
47
+ #define MAX_CATAL_DEPTH 50
48
+
49
+ #ifdef _WIN32
50
+ # define PATH_SEPARATOR ';'
51
+ #else
52
+ # define PATH_SEPARATOR ':'
53
+ #endif
54
+
55
+ /**
56
+ * TODO:
57
+ *
58
+ * macro to flag unimplemented blocks
59
+ * XML_CATALOG_PREFER user env to select between system/public preferred
60
+ * option. C.f. Richard Tobin <richard@cogsci.ed.ac.uk>
61
+ *> Just FYI, I am using an environment variable XML_CATALOG_PREFER with
62
+ *> values "system" and "public". I have made the default be "system" to
63
+ *> match yours.
64
+ */
65
+ #define TODO \
66
+ xmlGenericError(xmlGenericErrorContext, \
67
+ "Unimplemented block at %s:%d\n", \
68
+ __FILE__, __LINE__);
69
+
70
+ #define XML_URN_PUBID "urn:publicid:"
71
+ #define XML_CATAL_BREAK ((xmlChar *) -1)
72
+ #ifndef XML_XML_DEFAULT_CATALOG
73
+ #define XML_XML_DEFAULT_CATALOG "file:///etc/xml/catalog"
74
+ #endif
75
+ #ifndef XML_SGML_DEFAULT_CATALOG
76
+ #define XML_SGML_DEFAULT_CATALOG "file:///etc/sgml/catalog"
77
+ #endif
78
+
79
+ #if defined(_WIN32) && defined(_MSC_VER)
80
+ #undef XML_XML_DEFAULT_CATALOG
81
+ static char XML_XML_DEFAULT_CATALOG[256] = "file:///etc/xml/catalog";
82
+ #if defined(_WIN32_WCE)
83
+ /* Windows CE don't have a A variant */
84
+ #define GetModuleHandleA GetModuleHandle
85
+ #define GetModuleFileNameA GetModuleFileName
86
+ #else
87
+ #if !defined(_WINDOWS_)
88
+ void* __stdcall GetModuleHandleA(const char*);
89
+ unsigned long __stdcall GetModuleFileNameA(void*, char*, unsigned long);
90
+ #endif
91
+ #endif
92
+ #endif
93
+
94
+ static xmlChar *xmlCatalogNormalizePublic(const xmlChar *pubID);
95
+ static int xmlExpandCatalog(xmlCatalogPtr catal, const char *filename);
96
+
97
+ /************************************************************************
98
+ * *
99
+ * Types, all private *
100
+ * *
101
+ ************************************************************************/
102
+
103
+ typedef enum {
104
+ XML_CATA_REMOVED = -1,
105
+ XML_CATA_NONE = 0,
106
+ XML_CATA_CATALOG,
107
+ XML_CATA_BROKEN_CATALOG,
108
+ XML_CATA_NEXT_CATALOG,
109
+ XML_CATA_GROUP,
110
+ XML_CATA_PUBLIC,
111
+ XML_CATA_SYSTEM,
112
+ XML_CATA_REWRITE_SYSTEM,
113
+ XML_CATA_DELEGATE_PUBLIC,
114
+ XML_CATA_DELEGATE_SYSTEM,
115
+ XML_CATA_URI,
116
+ XML_CATA_REWRITE_URI,
117
+ XML_CATA_DELEGATE_URI,
118
+ SGML_CATA_SYSTEM,
119
+ SGML_CATA_PUBLIC,
120
+ SGML_CATA_ENTITY,
121
+ SGML_CATA_PENTITY,
122
+ SGML_CATA_DOCTYPE,
123
+ SGML_CATA_LINKTYPE,
124
+ SGML_CATA_NOTATION,
125
+ SGML_CATA_DELEGATE,
126
+ SGML_CATA_BASE,
127
+ SGML_CATA_CATALOG,
128
+ SGML_CATA_DOCUMENT,
129
+ SGML_CATA_SGMLDECL
130
+ } xmlCatalogEntryType;
131
+
132
+ typedef struct _xmlCatalogEntry xmlCatalogEntry;
133
+ typedef xmlCatalogEntry *xmlCatalogEntryPtr;
134
+ struct _xmlCatalogEntry {
135
+ struct _xmlCatalogEntry *next;
136
+ struct _xmlCatalogEntry *parent;
137
+ struct _xmlCatalogEntry *children;
138
+ xmlCatalogEntryType type;
139
+ xmlChar *name;
140
+ xmlChar *value;
141
+ xmlChar *URL; /* The expanded URL using the base */
142
+ xmlCatalogPrefer prefer;
143
+ int dealloc;
144
+ int depth;
145
+ struct _xmlCatalogEntry *group;
146
+ };
147
+
148
+ typedef enum {
149
+ XML_XML_CATALOG_TYPE = 1,
150
+ XML_SGML_CATALOG_TYPE
151
+ } xmlCatalogType;
152
+
153
+ #define XML_MAX_SGML_CATA_DEPTH 10
154
+ struct _xmlCatalog {
155
+ xmlCatalogType type; /* either XML or SGML */
156
+
157
+ /*
158
+ * SGML Catalogs are stored as a simple hash table of catalog entries
159
+ * Catalog stack to check against overflows when building the
160
+ * SGML catalog
161
+ */
162
+ char *catalTab[XML_MAX_SGML_CATA_DEPTH]; /* stack of catals */
163
+ int catalNr; /* Number of current catal streams */
164
+ int catalMax; /* Max number of catal streams */
165
+ xmlHashTablePtr sgml;
166
+
167
+ /*
168
+ * XML Catalogs are stored as a tree of Catalog entries
169
+ */
170
+ xmlCatalogPrefer prefer;
171
+ xmlCatalogEntryPtr xml;
172
+ };
173
+
174
+ /************************************************************************
175
+ * *
176
+ * Global variables *
177
+ * *
178
+ ************************************************************************/
179
+
180
+ /*
181
+ * Those are preferences
182
+ */
183
+ static int xmlDebugCatalogs = 0; /* used for debugging */
184
+ static xmlCatalogAllow xmlCatalogDefaultAllow = XML_CATA_ALLOW_ALL;
185
+ static xmlCatalogPrefer xmlCatalogDefaultPrefer = XML_CATA_PREFER_PUBLIC;
186
+
187
+ /*
188
+ * Hash table containing all the trees of XML catalogs parsed by
189
+ * the application.
190
+ */
191
+ static xmlHashTablePtr xmlCatalogXMLFiles = NULL;
192
+
193
+ /*
194
+ * The default catalog in use by the application
195
+ */
196
+ static xmlCatalogPtr xmlDefaultCatalog = NULL;
197
+
198
+ /*
199
+ * A mutex for modifying the shared global catalog(s)
200
+ * xmlDefaultCatalog tree.
201
+ * It also protects xmlCatalogXMLFiles
202
+ * The core of this readers/writer scheme is in xmlFetchXMLCatalogFile()
203
+ */
204
+ static xmlRMutexPtr xmlCatalogMutex = NULL;
205
+
206
+ /*
207
+ * Whether the catalog support was initialized.
208
+ */
209
+ static int xmlCatalogInitialized = 0;
210
+
211
+ /************************************************************************
212
+ * *
213
+ * Catalog error handlers *
214
+ * *
215
+ ************************************************************************/
216
+
217
+ /**
218
+ * xmlCatalogErrMemory:
219
+ * @extra: extra information
220
+ *
221
+ * Handle an out of memory condition
222
+ */
223
+ static void
224
+ xmlCatalogErrMemory(const char *extra)
225
+ {
226
+ __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_CATALOG,
227
+ XML_ERR_NO_MEMORY, XML_ERR_ERROR, NULL, 0,
228
+ extra, NULL, NULL, 0, 0,
229
+ "Memory allocation failed : %s\n", extra);
230
+ }
231
+
232
+ /**
233
+ * xmlCatalogErr:
234
+ * @catal: the Catalog entry
235
+ * @node: the context node
236
+ * @msg: the error message
237
+ * @extra: extra information
238
+ *
239
+ * Handle a catalog error
240
+ */
241
+ static void LIBXML_ATTR_FORMAT(4,0)
242
+ xmlCatalogErr(xmlCatalogEntryPtr catal, xmlNodePtr node, int error,
243
+ const char *msg, const xmlChar *str1, const xmlChar *str2,
244
+ const xmlChar *str3)
245
+ {
246
+ __xmlRaiseError(NULL, NULL, NULL, catal, node, XML_FROM_CATALOG,
247
+ error, XML_ERR_ERROR, NULL, 0,
248
+ (const char *) str1, (const char *) str2,
249
+ (const char *) str3, 0, 0,
250
+ msg, str1, str2, str3);
251
+ }
252
+
253
+
254
+ /************************************************************************
255
+ * *
256
+ * Allocation and Freeing *
257
+ * *
258
+ ************************************************************************/
259
+
260
+ /**
261
+ * xmlNewCatalogEntry:
262
+ * @type: type of entry
263
+ * @name: name of the entry
264
+ * @value: value of the entry
265
+ * @prefer: the PUBLIC vs. SYSTEM current preference value
266
+ * @group: for members of a group, the group entry
267
+ *
268
+ * create a new Catalog entry, this type is shared both by XML and
269
+ * SGML catalogs, but the acceptable types values differs.
270
+ *
271
+ * Returns the xmlCatalogEntryPtr or NULL in case of error
272
+ */
273
+ static xmlCatalogEntryPtr
274
+ xmlNewCatalogEntry(xmlCatalogEntryType type, const xmlChar *name,
275
+ const xmlChar *value, const xmlChar *URL, xmlCatalogPrefer prefer,
276
+ xmlCatalogEntryPtr group) {
277
+ xmlCatalogEntryPtr ret;
278
+ xmlChar *normid = NULL;
279
+
280
+ ret = (xmlCatalogEntryPtr) xmlMalloc(sizeof(xmlCatalogEntry));
281
+ if (ret == NULL) {
282
+ xmlCatalogErrMemory("allocating catalog entry");
283
+ return(NULL);
284
+ }
285
+ ret->next = NULL;
286
+ ret->parent = NULL;
287
+ ret->children = NULL;
288
+ ret->type = type;
289
+ if (type == XML_CATA_PUBLIC || type == XML_CATA_DELEGATE_PUBLIC) {
290
+ normid = xmlCatalogNormalizePublic(name);
291
+ if (normid != NULL)
292
+ name = (*normid != 0 ? normid : NULL);
293
+ }
294
+ if (name != NULL)
295
+ ret->name = xmlStrdup(name);
296
+ else
297
+ ret->name = NULL;
298
+ if (normid != NULL)
299
+ xmlFree(normid);
300
+ if (value != NULL)
301
+ ret->value = xmlStrdup(value);
302
+ else
303
+ ret->value = NULL;
304
+ if (URL == NULL)
305
+ URL = value;
306
+ if (URL != NULL)
307
+ ret->URL = xmlStrdup(URL);
308
+ else
309
+ ret->URL = NULL;
310
+ ret->prefer = prefer;
311
+ ret->dealloc = 0;
312
+ ret->depth = 0;
313
+ ret->group = group;
314
+ return(ret);
315
+ }
316
+
317
+ static void
318
+ xmlFreeCatalogEntryList(xmlCatalogEntryPtr ret);
319
+
320
+ /**
321
+ * xmlFreeCatalogEntry:
322
+ * @payload: a Catalog entry
323
+ *
324
+ * Free the memory allocated to a Catalog entry
325
+ */
326
+ static void
327
+ xmlFreeCatalogEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
328
+ xmlCatalogEntryPtr ret = (xmlCatalogEntryPtr) payload;
329
+ if (ret == NULL)
330
+ return;
331
+ /*
332
+ * Entries stored in the file hash must be deallocated
333
+ * only by the file hash cleaner !
334
+ */
335
+ if (ret->dealloc == 1)
336
+ return;
337
+
338
+ if (xmlDebugCatalogs) {
339
+ if (ret->name != NULL)
340
+ xmlGenericError(xmlGenericErrorContext,
341
+ "Free catalog entry %s\n", ret->name);
342
+ else if (ret->value != NULL)
343
+ xmlGenericError(xmlGenericErrorContext,
344
+ "Free catalog entry %s\n", ret->value);
345
+ else
346
+ xmlGenericError(xmlGenericErrorContext,
347
+ "Free catalog entry\n");
348
+ }
349
+
350
+ if (ret->name != NULL)
351
+ xmlFree(ret->name);
352
+ if (ret->value != NULL)
353
+ xmlFree(ret->value);
354
+ if (ret->URL != NULL)
355
+ xmlFree(ret->URL);
356
+ xmlFree(ret);
357
+ }
358
+
359
+ /**
360
+ * xmlFreeCatalogEntryList:
361
+ * @ret: a Catalog entry list
362
+ *
363
+ * Free the memory allocated to a full chained list of Catalog entries
364
+ */
365
+ static void
366
+ xmlFreeCatalogEntryList(xmlCatalogEntryPtr ret) {
367
+ xmlCatalogEntryPtr next;
368
+
369
+ while (ret != NULL) {
370
+ next = ret->next;
371
+ xmlFreeCatalogEntry(ret, NULL);
372
+ ret = next;
373
+ }
374
+ }
375
+
376
+ /**
377
+ * xmlFreeCatalogHashEntryList:
378
+ * @payload: a Catalog entry list
379
+ *
380
+ * Free the memory allocated to list of Catalog entries from the
381
+ * catalog file hash.
382
+ */
383
+ static void
384
+ xmlFreeCatalogHashEntryList(void *payload,
385
+ const xmlChar *name ATTRIBUTE_UNUSED) {
386
+ xmlCatalogEntryPtr catal = (xmlCatalogEntryPtr) payload;
387
+ xmlCatalogEntryPtr children, next;
388
+
389
+ if (catal == NULL)
390
+ return;
391
+
392
+ children = catal->children;
393
+ while (children != NULL) {
394
+ next = children->next;
395
+ children->dealloc = 0;
396
+ children->children = NULL;
397
+ xmlFreeCatalogEntry(children, NULL);
398
+ children = next;
399
+ }
400
+ catal->dealloc = 0;
401
+ xmlFreeCatalogEntry(catal, NULL);
402
+ }
403
+
404
+ /**
405
+ * xmlCreateNewCatalog:
406
+ * @type: type of catalog
407
+ * @prefer: the PUBLIC vs. SYSTEM current preference value
408
+ *
409
+ * create a new Catalog, this type is shared both by XML and
410
+ * SGML catalogs, but the acceptable types values differs.
411
+ *
412
+ * Returns the xmlCatalogPtr or NULL in case of error
413
+ */
414
+ static xmlCatalogPtr
415
+ xmlCreateNewCatalog(xmlCatalogType type, xmlCatalogPrefer prefer) {
416
+ xmlCatalogPtr ret;
417
+
418
+ ret = (xmlCatalogPtr) xmlMalloc(sizeof(xmlCatalog));
419
+ if (ret == NULL) {
420
+ xmlCatalogErrMemory("allocating catalog");
421
+ return(NULL);
422
+ }
423
+ memset(ret, 0, sizeof(xmlCatalog));
424
+ ret->type = type;
425
+ ret->catalNr = 0;
426
+ ret->catalMax = XML_MAX_SGML_CATA_DEPTH;
427
+ ret->prefer = prefer;
428
+ if (ret->type == XML_SGML_CATALOG_TYPE)
429
+ ret->sgml = xmlHashCreate(10);
430
+ return(ret);
431
+ }
432
+
433
+ /**
434
+ * xmlFreeCatalog:
435
+ * @catal: a Catalog
436
+ *
437
+ * Free the memory allocated to a Catalog
438
+ */
439
+ void
440
+ xmlFreeCatalog(xmlCatalogPtr catal) {
441
+ if (catal == NULL)
442
+ return;
443
+ if (catal->xml != NULL)
444
+ xmlFreeCatalogEntryList(catal->xml);
445
+ if (catal->sgml != NULL)
446
+ xmlHashFree(catal->sgml, xmlFreeCatalogEntry);
447
+ xmlFree(catal);
448
+ }
449
+
450
+ /************************************************************************
451
+ * *
452
+ * Serializing Catalogs *
453
+ * *
454
+ ************************************************************************/
455
+
456
+ #ifdef LIBXML_OUTPUT_ENABLED
457
+ /**
458
+ * xmlCatalogDumpEntry:
459
+ * @entry: the catalog entry
460
+ * @out: the file.
461
+ *
462
+ * Serialize an SGML Catalog entry
463
+ */
464
+ static void
465
+ xmlCatalogDumpEntry(void *payload, void *data,
466
+ const xmlChar *name ATTRIBUTE_UNUSED) {
467
+ xmlCatalogEntryPtr entry = (xmlCatalogEntryPtr) payload;
468
+ FILE *out = (FILE *) data;
469
+ if ((entry == NULL) || (out == NULL))
470
+ return;
471
+ switch (entry->type) {
472
+ case SGML_CATA_ENTITY:
473
+ fprintf(out, "ENTITY "); break;
474
+ case SGML_CATA_PENTITY:
475
+ fprintf(out, "ENTITY %%"); break;
476
+ case SGML_CATA_DOCTYPE:
477
+ fprintf(out, "DOCTYPE "); break;
478
+ case SGML_CATA_LINKTYPE:
479
+ fprintf(out, "LINKTYPE "); break;
480
+ case SGML_CATA_NOTATION:
481
+ fprintf(out, "NOTATION "); break;
482
+ case SGML_CATA_PUBLIC:
483
+ fprintf(out, "PUBLIC "); break;
484
+ case SGML_CATA_SYSTEM:
485
+ fprintf(out, "SYSTEM "); break;
486
+ case SGML_CATA_DELEGATE:
487
+ fprintf(out, "DELEGATE "); break;
488
+ case SGML_CATA_BASE:
489
+ fprintf(out, "BASE "); break;
490
+ case SGML_CATA_CATALOG:
491
+ fprintf(out, "CATALOG "); break;
492
+ case SGML_CATA_DOCUMENT:
493
+ fprintf(out, "DOCUMENT "); break;
494
+ case SGML_CATA_SGMLDECL:
495
+ fprintf(out, "SGMLDECL "); break;
496
+ default:
497
+ return;
498
+ }
499
+ switch (entry->type) {
500
+ case SGML_CATA_ENTITY:
501
+ case SGML_CATA_PENTITY:
502
+ case SGML_CATA_DOCTYPE:
503
+ case SGML_CATA_LINKTYPE:
504
+ case SGML_CATA_NOTATION:
505
+ fprintf(out, "%s", (const char *) entry->name); break;
506
+ case SGML_CATA_PUBLIC:
507
+ case SGML_CATA_SYSTEM:
508
+ case SGML_CATA_SGMLDECL:
509
+ case SGML_CATA_DOCUMENT:
510
+ case SGML_CATA_CATALOG:
511
+ case SGML_CATA_BASE:
512
+ case SGML_CATA_DELEGATE:
513
+ fprintf(out, "\"%s\"", entry->name); break;
514
+ default:
515
+ break;
516
+ }
517
+ switch (entry->type) {
518
+ case SGML_CATA_ENTITY:
519
+ case SGML_CATA_PENTITY:
520
+ case SGML_CATA_DOCTYPE:
521
+ case SGML_CATA_LINKTYPE:
522
+ case SGML_CATA_NOTATION:
523
+ case SGML_CATA_PUBLIC:
524
+ case SGML_CATA_SYSTEM:
525
+ case SGML_CATA_DELEGATE:
526
+ fprintf(out, " \"%s\"", entry->value); break;
527
+ default:
528
+ break;
529
+ }
530
+ fprintf(out, "\n");
531
+ }
532
+
533
+ /**
534
+ * xmlDumpXMLCatalogNode:
535
+ * @catal: top catalog entry
536
+ * @catalog: pointer to the xml tree
537
+ * @doc: the containing document
538
+ * @ns: the current namespace
539
+ * @cgroup: group node for group members
540
+ *
541
+ * Serializes a Catalog entry, called by xmlDumpXMLCatalog and recursively
542
+ * for group entries
543
+ */
544
+ static void xmlDumpXMLCatalogNode(xmlCatalogEntryPtr catal, xmlNodePtr catalog,
545
+ xmlDocPtr doc, xmlNsPtr ns, xmlCatalogEntryPtr cgroup) {
546
+ xmlNodePtr node;
547
+ xmlCatalogEntryPtr cur;
548
+ /*
549
+ * add all the catalog entries
550
+ */
551
+ cur = catal;
552
+ while (cur != NULL) {
553
+ if (cur->group == cgroup) {
554
+ switch (cur->type) {
555
+ case XML_CATA_REMOVED:
556
+ break;
557
+ case XML_CATA_BROKEN_CATALOG:
558
+ case XML_CATA_CATALOG:
559
+ if (cur == catal) {
560
+ cur = cur->children;
561
+ continue;
562
+ }
563
+ break;
564
+ case XML_CATA_NEXT_CATALOG:
565
+ node = xmlNewDocNode(doc, ns, BAD_CAST "nextCatalog", NULL);
566
+ xmlSetProp(node, BAD_CAST "catalog", cur->value);
567
+ xmlAddChild(catalog, node);
568
+ break;
569
+ case XML_CATA_NONE:
570
+ break;
571
+ case XML_CATA_GROUP:
572
+ node = xmlNewDocNode(doc, ns, BAD_CAST "group", NULL);
573
+ xmlSetProp(node, BAD_CAST "id", cur->name);
574
+ if (cur->value != NULL) {
575
+ xmlNsPtr xns;
576
+ xns = xmlSearchNsByHref(doc, node, XML_XML_NAMESPACE);
577
+ if (xns != NULL)
578
+ xmlSetNsProp(node, xns, BAD_CAST "base",
579
+ cur->value);
580
+ }
581
+ switch (cur->prefer) {
582
+ case XML_CATA_PREFER_NONE:
583
+ break;
584
+ case XML_CATA_PREFER_PUBLIC:
585
+ xmlSetProp(node, BAD_CAST "prefer", BAD_CAST "public");
586
+ break;
587
+ case XML_CATA_PREFER_SYSTEM:
588
+ xmlSetProp(node, BAD_CAST "prefer", BAD_CAST "system");
589
+ break;
590
+ }
591
+ xmlDumpXMLCatalogNode(cur->next, node, doc, ns, cur);
592
+ xmlAddChild(catalog, node);
593
+ break;
594
+ case XML_CATA_PUBLIC:
595
+ node = xmlNewDocNode(doc, ns, BAD_CAST "public", NULL);
596
+ xmlSetProp(node, BAD_CAST "publicId", cur->name);
597
+ xmlSetProp(node, BAD_CAST "uri", cur->value);
598
+ xmlAddChild(catalog, node);
599
+ break;
600
+ case XML_CATA_SYSTEM:
601
+ node = xmlNewDocNode(doc, ns, BAD_CAST "system", NULL);
602
+ xmlSetProp(node, BAD_CAST "systemId", cur->name);
603
+ xmlSetProp(node, BAD_CAST "uri", cur->value);
604
+ xmlAddChild(catalog, node);
605
+ break;
606
+ case XML_CATA_REWRITE_SYSTEM:
607
+ node = xmlNewDocNode(doc, ns, BAD_CAST "rewriteSystem", NULL);
608
+ xmlSetProp(node, BAD_CAST "systemIdStartString", cur->name);
609
+ xmlSetProp(node, BAD_CAST "rewritePrefix", cur->value);
610
+ xmlAddChild(catalog, node);
611
+ break;
612
+ case XML_CATA_DELEGATE_PUBLIC:
613
+ node = xmlNewDocNode(doc, ns, BAD_CAST "delegatePublic", NULL);
614
+ xmlSetProp(node, BAD_CAST "publicIdStartString", cur->name);
615
+ xmlSetProp(node, BAD_CAST "catalog", cur->value);
616
+ xmlAddChild(catalog, node);
617
+ break;
618
+ case XML_CATA_DELEGATE_SYSTEM:
619
+ node = xmlNewDocNode(doc, ns, BAD_CAST "delegateSystem", NULL);
620
+ xmlSetProp(node, BAD_CAST "systemIdStartString", cur->name);
621
+ xmlSetProp(node, BAD_CAST "catalog", cur->value);
622
+ xmlAddChild(catalog, node);
623
+ break;
624
+ case XML_CATA_URI:
625
+ node = xmlNewDocNode(doc, ns, BAD_CAST "uri", NULL);
626
+ xmlSetProp(node, BAD_CAST "name", cur->name);
627
+ xmlSetProp(node, BAD_CAST "uri", cur->value);
628
+ xmlAddChild(catalog, node);
629
+ break;
630
+ case XML_CATA_REWRITE_URI:
631
+ node = xmlNewDocNode(doc, ns, BAD_CAST "rewriteURI", NULL);
632
+ xmlSetProp(node, BAD_CAST "uriStartString", cur->name);
633
+ xmlSetProp(node, BAD_CAST "rewritePrefix", cur->value);
634
+ xmlAddChild(catalog, node);
635
+ break;
636
+ case XML_CATA_DELEGATE_URI:
637
+ node = xmlNewDocNode(doc, ns, BAD_CAST "delegateURI", NULL);
638
+ xmlSetProp(node, BAD_CAST "uriStartString", cur->name);
639
+ xmlSetProp(node, BAD_CAST "catalog", cur->value);
640
+ xmlAddChild(catalog, node);
641
+ break;
642
+ case SGML_CATA_SYSTEM:
643
+ case SGML_CATA_PUBLIC:
644
+ case SGML_CATA_ENTITY:
645
+ case SGML_CATA_PENTITY:
646
+ case SGML_CATA_DOCTYPE:
647
+ case SGML_CATA_LINKTYPE:
648
+ case SGML_CATA_NOTATION:
649
+ case SGML_CATA_DELEGATE:
650
+ case SGML_CATA_BASE:
651
+ case SGML_CATA_CATALOG:
652
+ case SGML_CATA_DOCUMENT:
653
+ case SGML_CATA_SGMLDECL:
654
+ break;
655
+ }
656
+ }
657
+ cur = cur->next;
658
+ }
659
+ }
660
+
661
+ static int
662
+ xmlDumpXMLCatalog(FILE *out, xmlCatalogEntryPtr catal) {
663
+ int ret;
664
+ xmlDocPtr doc;
665
+ xmlNsPtr ns;
666
+ xmlDtdPtr dtd;
667
+ xmlNodePtr catalog;
668
+ xmlOutputBufferPtr buf;
669
+
670
+ /*
671
+ * Rebuild a catalog
672
+ */
673
+ doc = xmlNewDoc(NULL);
674
+ if (doc == NULL)
675
+ return(-1);
676
+ dtd = xmlNewDtd(doc, BAD_CAST "catalog",
677
+ BAD_CAST "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN",
678
+ BAD_CAST "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd");
679
+
680
+ xmlAddChild((xmlNodePtr) doc, (xmlNodePtr) dtd);
681
+
682
+ ns = xmlNewNs(NULL, XML_CATALOGS_NAMESPACE, NULL);
683
+ if (ns == NULL) {
684
+ xmlFreeDoc(doc);
685
+ return(-1);
686
+ }
687
+ catalog = xmlNewDocNode(doc, ns, BAD_CAST "catalog", NULL);
688
+ if (catalog == NULL) {
689
+ xmlFreeNs(ns);
690
+ xmlFreeDoc(doc);
691
+ return(-1);
692
+ }
693
+ catalog->nsDef = ns;
694
+ xmlAddChild((xmlNodePtr) doc, catalog);
695
+
696
+ xmlDumpXMLCatalogNode(catal, catalog, doc, ns, NULL);
697
+
698
+ /*
699
+ * reserialize it
700
+ */
701
+ buf = xmlOutputBufferCreateFile(out, NULL);
702
+ if (buf == NULL) {
703
+ xmlFreeDoc(doc);
704
+ return(-1);
705
+ }
706
+ ret = xmlSaveFormatFileTo(buf, doc, NULL, 1);
707
+
708
+ /*
709
+ * Free it
710
+ */
711
+ xmlFreeDoc(doc);
712
+
713
+ return(ret);
714
+ }
715
+ #endif /* LIBXML_OUTPUT_ENABLED */
716
+
717
+ /************************************************************************
718
+ * *
719
+ * Converting SGML Catalogs to XML *
720
+ * *
721
+ ************************************************************************/
722
+
723
+ /**
724
+ * xmlCatalogConvertEntry:
725
+ * @entry: the entry
726
+ * @catal: pointer to the catalog being converted
727
+ *
728
+ * Convert one entry from the catalog
729
+ */
730
+ static void
731
+ xmlCatalogConvertEntry(void *payload, void *data,
732
+ const xmlChar *name ATTRIBUTE_UNUSED) {
733
+ xmlCatalogEntryPtr entry = (xmlCatalogEntryPtr) payload;
734
+ xmlCatalogPtr catal = (xmlCatalogPtr) data;
735
+ if ((entry == NULL) || (catal == NULL) || (catal->sgml == NULL) ||
736
+ (catal->xml == NULL))
737
+ return;
738
+ switch (entry->type) {
739
+ case SGML_CATA_ENTITY:
740
+ entry->type = XML_CATA_PUBLIC;
741
+ break;
742
+ case SGML_CATA_PENTITY:
743
+ entry->type = XML_CATA_PUBLIC;
744
+ break;
745
+ case SGML_CATA_DOCTYPE:
746
+ entry->type = XML_CATA_PUBLIC;
747
+ break;
748
+ case SGML_CATA_LINKTYPE:
749
+ entry->type = XML_CATA_PUBLIC;
750
+ break;
751
+ case SGML_CATA_NOTATION:
752
+ entry->type = XML_CATA_PUBLIC;
753
+ break;
754
+ case SGML_CATA_PUBLIC:
755
+ entry->type = XML_CATA_PUBLIC;
756
+ break;
757
+ case SGML_CATA_SYSTEM:
758
+ entry->type = XML_CATA_SYSTEM;
759
+ break;
760
+ case SGML_CATA_DELEGATE:
761
+ entry->type = XML_CATA_DELEGATE_PUBLIC;
762
+ break;
763
+ case SGML_CATA_CATALOG:
764
+ entry->type = XML_CATA_CATALOG;
765
+ break;
766
+ default:
767
+ xmlHashRemoveEntry(catal->sgml, entry->name, xmlFreeCatalogEntry);
768
+ return;
769
+ }
770
+ /*
771
+ * Conversion successful, remove from the SGML catalog
772
+ * and add it to the default XML one
773
+ */
774
+ xmlHashRemoveEntry(catal->sgml, entry->name, NULL);
775
+ entry->parent = catal->xml;
776
+ entry->next = NULL;
777
+ if (catal->xml->children == NULL)
778
+ catal->xml->children = entry;
779
+ else {
780
+ xmlCatalogEntryPtr prev;
781
+
782
+ prev = catal->xml->children;
783
+ while (prev->next != NULL)
784
+ prev = prev->next;
785
+ prev->next = entry;
786
+ }
787
+ }
788
+
789
+ /**
790
+ * xmlConvertSGMLCatalog:
791
+ * @catal: the catalog
792
+ *
793
+ * Convert all the SGML catalog entries as XML ones
794
+ *
795
+ * Returns the number of entries converted if successful, -1 otherwise
796
+ */
797
+ int
798
+ xmlConvertSGMLCatalog(xmlCatalogPtr catal) {
799
+
800
+ if ((catal == NULL) || (catal->type != XML_SGML_CATALOG_TYPE))
801
+ return(-1);
802
+
803
+ if (xmlDebugCatalogs) {
804
+ xmlGenericError(xmlGenericErrorContext,
805
+ "Converting SGML catalog to XML\n");
806
+ }
807
+ xmlHashScan(catal->sgml, xmlCatalogConvertEntry, &catal);
808
+ return(0);
809
+ }
810
+
811
+ /************************************************************************
812
+ * *
813
+ * Helper function *
814
+ * *
815
+ ************************************************************************/
816
+
817
+ /**
818
+ * xmlCatalogUnWrapURN:
819
+ * @urn: an "urn:publicid:" to unwrap
820
+ *
821
+ * Expand the URN into the equivalent Public Identifier
822
+ *
823
+ * Returns the new identifier or NULL, the string must be deallocated
824
+ * by the caller.
825
+ */
826
+ static xmlChar *
827
+ xmlCatalogUnWrapURN(const xmlChar *urn) {
828
+ xmlChar result[2000];
829
+ unsigned int i = 0;
830
+
831
+ if (xmlStrncmp(urn, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1))
832
+ return(NULL);
833
+ urn += sizeof(XML_URN_PUBID) - 1;
834
+
835
+ while (*urn != 0) {
836
+ if (i > sizeof(result) - 4)
837
+ break;
838
+ if (*urn == '+') {
839
+ result[i++] = ' ';
840
+ urn++;
841
+ } else if (*urn == ':') {
842
+ result[i++] = '/';
843
+ result[i++] = '/';
844
+ urn++;
845
+ } else if (*urn == ';') {
846
+ result[i++] = ':';
847
+ result[i++] = ':';
848
+ urn++;
849
+ } else if (*urn == '%') {
850
+ if ((urn[1] == '2') && (urn[2] == 'B'))
851
+ result[i++] = '+';
852
+ else if ((urn[1] == '3') && (urn[2] == 'A'))
853
+ result[i++] = ':';
854
+ else if ((urn[1] == '2') && (urn[2] == 'F'))
855
+ result[i++] = '/';
856
+ else if ((urn[1] == '3') && (urn[2] == 'B'))
857
+ result[i++] = ';';
858
+ else if ((urn[1] == '2') && (urn[2] == '7'))
859
+ result[i++] = '\'';
860
+ else if ((urn[1] == '3') && (urn[2] == 'F'))
861
+ result[i++] = '?';
862
+ else if ((urn[1] == '2') && (urn[2] == '3'))
863
+ result[i++] = '#';
864
+ else if ((urn[1] == '2') && (urn[2] == '5'))
865
+ result[i++] = '%';
866
+ else {
867
+ result[i++] = *urn;
868
+ urn++;
869
+ continue;
870
+ }
871
+ urn += 3;
872
+ } else {
873
+ result[i++] = *urn;
874
+ urn++;
875
+ }
876
+ }
877
+ result[i] = 0;
878
+
879
+ return(xmlStrdup(result));
880
+ }
881
+
882
+ /**
883
+ * xmlParseCatalogFile:
884
+ * @filename: the filename
885
+ *
886
+ * parse an XML file and build a tree. It's like xmlParseFile()
887
+ * except it bypass all catalog lookups.
888
+ *
889
+ * Returns the resulting document tree or NULL in case of error
890
+ */
891
+
892
+ xmlDocPtr
893
+ xmlParseCatalogFile(const char *filename) {
894
+ xmlDocPtr ret;
895
+ xmlParserCtxtPtr ctxt;
896
+ char *directory = NULL;
897
+ xmlParserInputPtr inputStream;
898
+ xmlParserInputBufferPtr buf;
899
+
900
+ ctxt = xmlNewParserCtxt();
901
+ if (ctxt == NULL) {
902
+ #ifdef LIBXML_SAX1_ENABLED
903
+ if (xmlDefaultSAXHandler.error != NULL) {
904
+ xmlDefaultSAXHandler.error(NULL, "out of memory\n");
905
+ }
906
+ #endif
907
+ return(NULL);
908
+ }
909
+
910
+ buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
911
+ if (buf == NULL) {
912
+ xmlFreeParserCtxt(ctxt);
913
+ return(NULL);
914
+ }
915
+
916
+ inputStream = xmlNewInputStream(ctxt);
917
+ if (inputStream == NULL) {
918
+ xmlFreeParserCtxt(ctxt);
919
+ return(NULL);
920
+ }
921
+
922
+ inputStream->filename = (char *) xmlCanonicPath((const xmlChar *)filename);
923
+ inputStream->buf = buf;
924
+ xmlBufResetInput(buf->buffer, inputStream);
925
+
926
+ inputPush(ctxt, inputStream);
927
+ if (ctxt->directory == NULL)
928
+ directory = xmlParserGetDirectory(filename);
929
+ if ((ctxt->directory == NULL) && (directory != NULL))
930
+ ctxt->directory = directory;
931
+ ctxt->valid = 0;
932
+ ctxt->validate = 0;
933
+ ctxt->loadsubset = 0;
934
+ ctxt->pedantic = 0;
935
+ ctxt->dictNames = 1;
936
+
937
+ xmlParseDocument(ctxt);
938
+
939
+ if (ctxt->wellFormed)
940
+ ret = ctxt->myDoc;
941
+ else {
942
+ ret = NULL;
943
+ xmlFreeDoc(ctxt->myDoc);
944
+ ctxt->myDoc = NULL;
945
+ }
946
+ xmlFreeParserCtxt(ctxt);
947
+
948
+ return(ret);
949
+ }
950
+
951
+ /**
952
+ * xmlLoadFileContent:
953
+ * @filename: a file path
954
+ *
955
+ * Load a file content into memory.
956
+ *
957
+ * Returns a pointer to the 0 terminated string or NULL in case of error
958
+ */
959
+ static xmlChar *
960
+ xmlLoadFileContent(const char *filename)
961
+ {
962
+ #ifdef HAVE_STAT
963
+ int fd;
964
+ #else
965
+ FILE *fd;
966
+ #endif
967
+ int len;
968
+ long size;
969
+
970
+ #ifdef HAVE_STAT
971
+ struct stat info;
972
+ #endif
973
+ xmlChar *content;
974
+
975
+ if (filename == NULL)
976
+ return (NULL);
977
+
978
+ #ifdef HAVE_STAT
979
+ if (stat(filename, &info) < 0)
980
+ return (NULL);
981
+ #endif
982
+
983
+ #ifdef HAVE_STAT
984
+ if ((fd = open(filename, O_RDONLY)) < 0)
985
+ #else
986
+ if ((fd = fopen(filename, "rb")) == NULL)
987
+ #endif
988
+ {
989
+ return (NULL);
990
+ }
991
+ #ifdef HAVE_STAT
992
+ size = info.st_size;
993
+ #else
994
+ if (fseek(fd, 0, SEEK_END) || (size = ftell(fd)) == EOF || fseek(fd, 0, SEEK_SET)) { /* File operations denied? ok, just close and return failure */
995
+ fclose(fd);
996
+ return (NULL);
997
+ }
998
+ #endif
999
+ content = (xmlChar*)xmlMallocAtomic(size + 10);
1000
+ if (content == NULL) {
1001
+ xmlCatalogErrMemory("allocating catalog data");
1002
+ #ifdef HAVE_STAT
1003
+ close(fd);
1004
+ #else
1005
+ fclose(fd);
1006
+ #endif
1007
+ return (NULL);
1008
+ }
1009
+ #ifdef HAVE_STAT
1010
+ len = read(fd, content, size);
1011
+ close(fd);
1012
+ #else
1013
+ len = fread(content, 1, size, fd);
1014
+ fclose(fd);
1015
+ #endif
1016
+ if (len < 0) {
1017
+ xmlFree(content);
1018
+ return (NULL);
1019
+ }
1020
+ content[len] = 0;
1021
+
1022
+ return(content);
1023
+ }
1024
+
1025
+ /**
1026
+ * xmlCatalogNormalizePublic:
1027
+ * @pubID: the public ID string
1028
+ *
1029
+ * Normalizes the Public Identifier
1030
+ *
1031
+ * Implements 6.2. Public Identifier Normalization
1032
+ * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
1033
+ *
1034
+ * Returns the new string or NULL, the string must be deallocated
1035
+ * by the caller.
1036
+ */
1037
+ static xmlChar *
1038
+ xmlCatalogNormalizePublic(const xmlChar *pubID)
1039
+ {
1040
+ int ok = 1;
1041
+ int white;
1042
+ const xmlChar *p;
1043
+ xmlChar *ret;
1044
+ xmlChar *q;
1045
+
1046
+ if (pubID == NULL)
1047
+ return(NULL);
1048
+
1049
+ white = 1;
1050
+ for (p = pubID;*p != 0 && ok;p++) {
1051
+ if (!xmlIsBlank_ch(*p))
1052
+ white = 0;
1053
+ else if (*p == 0x20 && !white)
1054
+ white = 1;
1055
+ else
1056
+ ok = 0;
1057
+ }
1058
+ if (ok && !white) /* is normalized */
1059
+ return(NULL);
1060
+
1061
+ ret = xmlStrdup(pubID);
1062
+ q = ret;
1063
+ white = 0;
1064
+ for (p = pubID;*p != 0;p++) {
1065
+ if (xmlIsBlank_ch(*p)) {
1066
+ if (q != ret)
1067
+ white = 1;
1068
+ } else {
1069
+ if (white) {
1070
+ *(q++) = 0x20;
1071
+ white = 0;
1072
+ }
1073
+ *(q++) = *p;
1074
+ }
1075
+ }
1076
+ *q = 0;
1077
+ return(ret);
1078
+ }
1079
+
1080
+ /************************************************************************
1081
+ * *
1082
+ * The XML Catalog parser *
1083
+ * *
1084
+ ************************************************************************/
1085
+
1086
+ static xmlCatalogEntryPtr
1087
+ xmlParseXMLCatalogFile(xmlCatalogPrefer prefer, const xmlChar *filename);
1088
+ static void
1089
+ xmlParseXMLCatalogNodeList(xmlNodePtr cur, xmlCatalogPrefer prefer,
1090
+ xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup);
1091
+ static xmlChar *
1092
+ xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
1093
+ const xmlChar *sysID);
1094
+ static xmlChar *
1095
+ xmlCatalogListXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI);
1096
+
1097
+
1098
+ /**
1099
+ * xmlGetXMLCatalogEntryType:
1100
+ * @name: the name
1101
+ *
1102
+ * lookup the internal type associated to an XML catalog entry name
1103
+ *
1104
+ * Returns the type associated with that name
1105
+ */
1106
+ static xmlCatalogEntryType
1107
+ xmlGetXMLCatalogEntryType(const xmlChar *name) {
1108
+ xmlCatalogEntryType type = XML_CATA_NONE;
1109
+ if (xmlStrEqual(name, (const xmlChar *) "system"))
1110
+ type = XML_CATA_SYSTEM;
1111
+ else if (xmlStrEqual(name, (const xmlChar *) "public"))
1112
+ type = XML_CATA_PUBLIC;
1113
+ else if (xmlStrEqual(name, (const xmlChar *) "rewriteSystem"))
1114
+ type = XML_CATA_REWRITE_SYSTEM;
1115
+ else if (xmlStrEqual(name, (const xmlChar *) "delegatePublic"))
1116
+ type = XML_CATA_DELEGATE_PUBLIC;
1117
+ else if (xmlStrEqual(name, (const xmlChar *) "delegateSystem"))
1118
+ type = XML_CATA_DELEGATE_SYSTEM;
1119
+ else if (xmlStrEqual(name, (const xmlChar *) "uri"))
1120
+ type = XML_CATA_URI;
1121
+ else if (xmlStrEqual(name, (const xmlChar *) "rewriteURI"))
1122
+ type = XML_CATA_REWRITE_URI;
1123
+ else if (xmlStrEqual(name, (const xmlChar *) "delegateURI"))
1124
+ type = XML_CATA_DELEGATE_URI;
1125
+ else if (xmlStrEqual(name, (const xmlChar *) "nextCatalog"))
1126
+ type = XML_CATA_NEXT_CATALOG;
1127
+ else if (xmlStrEqual(name, (const xmlChar *) "catalog"))
1128
+ type = XML_CATA_CATALOG;
1129
+ return(type);
1130
+ }
1131
+
1132
+ /**
1133
+ * xmlParseXMLCatalogOneNode:
1134
+ * @cur: the XML node
1135
+ * @type: the type of Catalog entry
1136
+ * @name: the name of the node
1137
+ * @attrName: the attribute holding the value
1138
+ * @uriAttrName: the attribute holding the URI-Reference
1139
+ * @prefer: the PUBLIC vs. SYSTEM current preference value
1140
+ * @cgroup: the group which includes this node
1141
+ *
1142
+ * Finishes the examination of an XML tree node of a catalog and build
1143
+ * a Catalog entry from it.
1144
+ *
1145
+ * Returns the new Catalog entry node or NULL in case of error.
1146
+ */
1147
+ static xmlCatalogEntryPtr
1148
+ xmlParseXMLCatalogOneNode(xmlNodePtr cur, xmlCatalogEntryType type,
1149
+ const xmlChar *name, const xmlChar *attrName,
1150
+ const xmlChar *uriAttrName, xmlCatalogPrefer prefer,
1151
+ xmlCatalogEntryPtr cgroup) {
1152
+ int ok = 1;
1153
+ xmlChar *uriValue;
1154
+ xmlChar *nameValue = NULL;
1155
+ xmlChar *base = NULL;
1156
+ xmlChar *URL = NULL;
1157
+ xmlCatalogEntryPtr ret = NULL;
1158
+
1159
+ if (attrName != NULL) {
1160
+ nameValue = xmlGetProp(cur, attrName);
1161
+ if (nameValue == NULL) {
1162
+ xmlCatalogErr(ret, cur, XML_CATALOG_MISSING_ATTR,
1163
+ "%s entry lacks '%s'\n", name, attrName, NULL);
1164
+ ok = 0;
1165
+ }
1166
+ }
1167
+ uriValue = xmlGetProp(cur, uriAttrName);
1168
+ if (uriValue == NULL) {
1169
+ xmlCatalogErr(ret, cur, XML_CATALOG_MISSING_ATTR,
1170
+ "%s entry lacks '%s'\n", name, uriAttrName, NULL);
1171
+ ok = 0;
1172
+ }
1173
+ if (!ok) {
1174
+ if (nameValue != NULL)
1175
+ xmlFree(nameValue);
1176
+ if (uriValue != NULL)
1177
+ xmlFree(uriValue);
1178
+ return(NULL);
1179
+ }
1180
+
1181
+ base = xmlNodeGetBase(cur->doc, cur);
1182
+ URL = xmlBuildURI(uriValue, base);
1183
+ if (URL != NULL) {
1184
+ if (xmlDebugCatalogs > 1) {
1185
+ if (nameValue != NULL)
1186
+ xmlGenericError(xmlGenericErrorContext,
1187
+ "Found %s: '%s' '%s'\n", name, nameValue, URL);
1188
+ else
1189
+ xmlGenericError(xmlGenericErrorContext,
1190
+ "Found %s: '%s'\n", name, URL);
1191
+ }
1192
+ ret = xmlNewCatalogEntry(type, nameValue, uriValue, URL, prefer, cgroup);
1193
+ } else {
1194
+ xmlCatalogErr(ret, cur, XML_CATALOG_ENTRY_BROKEN,
1195
+ "%s entry '%s' broken ?: %s\n", name, uriAttrName, uriValue);
1196
+ }
1197
+ if (nameValue != NULL)
1198
+ xmlFree(nameValue);
1199
+ if (uriValue != NULL)
1200
+ xmlFree(uriValue);
1201
+ if (base != NULL)
1202
+ xmlFree(base);
1203
+ if (URL != NULL)
1204
+ xmlFree(URL);
1205
+ return(ret);
1206
+ }
1207
+
1208
+ /**
1209
+ * xmlParseXMLCatalogNode:
1210
+ * @cur: the XML node
1211
+ * @prefer: the PUBLIC vs. SYSTEM current preference value
1212
+ * @parent: the parent Catalog entry
1213
+ * @cgroup: the group which includes this node
1214
+ *
1215
+ * Examines an XML tree node of a catalog and build
1216
+ * a Catalog entry from it adding it to its parent. The examination can
1217
+ * be recursive.
1218
+ */
1219
+ static void
1220
+ xmlParseXMLCatalogNode(xmlNodePtr cur, xmlCatalogPrefer prefer,
1221
+ xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup)
1222
+ {
1223
+ xmlChar *base = NULL;
1224
+ xmlCatalogEntryPtr entry = NULL;
1225
+
1226
+ if (cur == NULL)
1227
+ return;
1228
+ if (xmlStrEqual(cur->name, BAD_CAST "group")) {
1229
+ xmlChar *prop;
1230
+ xmlCatalogPrefer pref = XML_CATA_PREFER_NONE;
1231
+
1232
+ prop = xmlGetProp(cur, BAD_CAST "prefer");
1233
+ if (prop != NULL) {
1234
+ if (xmlStrEqual(prop, BAD_CAST "system")) {
1235
+ prefer = XML_CATA_PREFER_SYSTEM;
1236
+ } else if (xmlStrEqual(prop, BAD_CAST "public")) {
1237
+ prefer = XML_CATA_PREFER_PUBLIC;
1238
+ } else {
1239
+ xmlCatalogErr(parent, cur, XML_CATALOG_PREFER_VALUE,
1240
+ "Invalid value for prefer: '%s'\n",
1241
+ prop, NULL, NULL);
1242
+ }
1243
+ xmlFree(prop);
1244
+ pref = prefer;
1245
+ }
1246
+ prop = xmlGetProp(cur, BAD_CAST "id");
1247
+ base = xmlGetNsProp(cur, BAD_CAST "base", XML_XML_NAMESPACE);
1248
+ entry = xmlNewCatalogEntry(XML_CATA_GROUP, prop, base, NULL, pref, cgroup);
1249
+ xmlFree(prop);
1250
+ } else if (xmlStrEqual(cur->name, BAD_CAST "public")) {
1251
+ entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_PUBLIC,
1252
+ BAD_CAST "public", BAD_CAST "publicId", BAD_CAST "uri", prefer, cgroup);
1253
+ } else if (xmlStrEqual(cur->name, BAD_CAST "system")) {
1254
+ entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_SYSTEM,
1255
+ BAD_CAST "system", BAD_CAST "systemId", BAD_CAST "uri", prefer, cgroup);
1256
+ } else if (xmlStrEqual(cur->name, BAD_CAST "rewriteSystem")) {
1257
+ entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_REWRITE_SYSTEM,
1258
+ BAD_CAST "rewriteSystem", BAD_CAST "systemIdStartString",
1259
+ BAD_CAST "rewritePrefix", prefer, cgroup);
1260
+ } else if (xmlStrEqual(cur->name, BAD_CAST "delegatePublic")) {
1261
+ entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_PUBLIC,
1262
+ BAD_CAST "delegatePublic", BAD_CAST "publicIdStartString",
1263
+ BAD_CAST "catalog", prefer, cgroup);
1264
+ } else if (xmlStrEqual(cur->name, BAD_CAST "delegateSystem")) {
1265
+ entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_SYSTEM,
1266
+ BAD_CAST "delegateSystem", BAD_CAST "systemIdStartString",
1267
+ BAD_CAST "catalog", prefer, cgroup);
1268
+ } else if (xmlStrEqual(cur->name, BAD_CAST "uri")) {
1269
+ entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_URI,
1270
+ BAD_CAST "uri", BAD_CAST "name",
1271
+ BAD_CAST "uri", prefer, cgroup);
1272
+ } else if (xmlStrEqual(cur->name, BAD_CAST "rewriteURI")) {
1273
+ entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_REWRITE_URI,
1274
+ BAD_CAST "rewriteURI", BAD_CAST "uriStartString",
1275
+ BAD_CAST "rewritePrefix", prefer, cgroup);
1276
+ } else if (xmlStrEqual(cur->name, BAD_CAST "delegateURI")) {
1277
+ entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_URI,
1278
+ BAD_CAST "delegateURI", BAD_CAST "uriStartString",
1279
+ BAD_CAST "catalog", prefer, cgroup);
1280
+ } else if (xmlStrEqual(cur->name, BAD_CAST "nextCatalog")) {
1281
+ entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_NEXT_CATALOG,
1282
+ BAD_CAST "nextCatalog", NULL,
1283
+ BAD_CAST "catalog", prefer, cgroup);
1284
+ }
1285
+ if (entry != NULL) {
1286
+ if (parent != NULL) {
1287
+ entry->parent = parent;
1288
+ if (parent->children == NULL)
1289
+ parent->children = entry;
1290
+ else {
1291
+ xmlCatalogEntryPtr prev;
1292
+
1293
+ prev = parent->children;
1294
+ while (prev->next != NULL)
1295
+ prev = prev->next;
1296
+ prev->next = entry;
1297
+ }
1298
+ }
1299
+ if (entry->type == XML_CATA_GROUP) {
1300
+ /*
1301
+ * Recurse to propagate prefer to the subtree
1302
+ * (xml:base handling is automated)
1303
+ */
1304
+ xmlParseXMLCatalogNodeList(cur->children, prefer, parent, entry);
1305
+ }
1306
+ }
1307
+ if (base != NULL)
1308
+ xmlFree(base);
1309
+ }
1310
+
1311
+ /**
1312
+ * xmlParseXMLCatalogNodeList:
1313
+ * @cur: the XML node list of siblings
1314
+ * @prefer: the PUBLIC vs. SYSTEM current preference value
1315
+ * @parent: the parent Catalog entry
1316
+ * @cgroup: the group which includes this list
1317
+ *
1318
+ * Examines a list of XML sibling nodes of a catalog and build
1319
+ * a list of Catalog entry from it adding it to the parent.
1320
+ * The examination will recurse to examine node subtrees.
1321
+ */
1322
+ static void
1323
+ xmlParseXMLCatalogNodeList(xmlNodePtr cur, xmlCatalogPrefer prefer,
1324
+ xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup) {
1325
+ while (cur != NULL) {
1326
+ if ((cur->ns != NULL) && (cur->ns->href != NULL) &&
1327
+ (xmlStrEqual(cur->ns->href, XML_CATALOGS_NAMESPACE))) {
1328
+ xmlParseXMLCatalogNode(cur, prefer, parent, cgroup);
1329
+ }
1330
+ cur = cur->next;
1331
+ }
1332
+ /* TODO: sort the list according to REWRITE lengths and prefer value */
1333
+ }
1334
+
1335
+ /**
1336
+ * xmlParseXMLCatalogFile:
1337
+ * @prefer: the PUBLIC vs. SYSTEM current preference value
1338
+ * @filename: the filename for the catalog
1339
+ *
1340
+ * Parses the catalog file to extract the XML tree and then analyze the
1341
+ * tree to build a list of Catalog entries corresponding to this catalog
1342
+ *
1343
+ * Returns the resulting Catalog entries list
1344
+ */
1345
+ static xmlCatalogEntryPtr
1346
+ xmlParseXMLCatalogFile(xmlCatalogPrefer prefer, const xmlChar *filename) {
1347
+ xmlDocPtr doc;
1348
+ xmlNodePtr cur;
1349
+ xmlChar *prop;
1350
+ xmlCatalogEntryPtr parent = NULL;
1351
+
1352
+ if (filename == NULL)
1353
+ return(NULL);
1354
+
1355
+ doc = xmlParseCatalogFile((const char *) filename);
1356
+ if (doc == NULL) {
1357
+ if (xmlDebugCatalogs)
1358
+ xmlGenericError(xmlGenericErrorContext,
1359
+ "Failed to parse catalog %s\n", filename);
1360
+ return(NULL);
1361
+ }
1362
+
1363
+ if (xmlDebugCatalogs)
1364
+ xmlGenericError(xmlGenericErrorContext,
1365
+ "%d Parsing catalog %s\n", xmlGetThreadId(), filename);
1366
+
1367
+ cur = xmlDocGetRootElement(doc);
1368
+ if ((cur != NULL) && (xmlStrEqual(cur->name, BAD_CAST "catalog")) &&
1369
+ (cur->ns != NULL) && (cur->ns->href != NULL) &&
1370
+ (xmlStrEqual(cur->ns->href, XML_CATALOGS_NAMESPACE))) {
1371
+
1372
+ parent = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
1373
+ (const xmlChar *)filename, NULL, prefer, NULL);
1374
+ if (parent == NULL) {
1375
+ xmlFreeDoc(doc);
1376
+ return(NULL);
1377
+ }
1378
+
1379
+ prop = xmlGetProp(cur, BAD_CAST "prefer");
1380
+ if (prop != NULL) {
1381
+ if (xmlStrEqual(prop, BAD_CAST "system")) {
1382
+ prefer = XML_CATA_PREFER_SYSTEM;
1383
+ } else if (xmlStrEqual(prop, BAD_CAST "public")) {
1384
+ prefer = XML_CATA_PREFER_PUBLIC;
1385
+ } else {
1386
+ xmlCatalogErr(NULL, cur, XML_CATALOG_PREFER_VALUE,
1387
+ "Invalid value for prefer: '%s'\n",
1388
+ prop, NULL, NULL);
1389
+ }
1390
+ xmlFree(prop);
1391
+ }
1392
+ cur = cur->children;
1393
+ xmlParseXMLCatalogNodeList(cur, prefer, parent, NULL);
1394
+ } else {
1395
+ xmlCatalogErr(NULL, (xmlNodePtr) doc, XML_CATALOG_NOT_CATALOG,
1396
+ "File %s is not an XML Catalog\n",
1397
+ filename, NULL, NULL);
1398
+ xmlFreeDoc(doc);
1399
+ return(NULL);
1400
+ }
1401
+ xmlFreeDoc(doc);
1402
+ return(parent);
1403
+ }
1404
+
1405
+ /**
1406
+ * xmlFetchXMLCatalogFile:
1407
+ * @catal: an existing but incomplete catalog entry
1408
+ *
1409
+ * Fetch and parse the subcatalog referenced by an entry
1410
+ *
1411
+ * Returns 0 in case of success, -1 otherwise
1412
+ */
1413
+ static int
1414
+ xmlFetchXMLCatalogFile(xmlCatalogEntryPtr catal) {
1415
+ xmlCatalogEntryPtr doc;
1416
+
1417
+ if (catal == NULL)
1418
+ return(-1);
1419
+ if (catal->URL == NULL)
1420
+ return(-1);
1421
+
1422
+ /*
1423
+ * lock the whole catalog for modification
1424
+ */
1425
+ xmlRMutexLock(xmlCatalogMutex);
1426
+ if (catal->children != NULL) {
1427
+ /* Okay someone else did it in the meantime */
1428
+ xmlRMutexUnlock(xmlCatalogMutex);
1429
+ return(0);
1430
+ }
1431
+
1432
+ if (xmlCatalogXMLFiles != NULL) {
1433
+ doc = (xmlCatalogEntryPtr)
1434
+ xmlHashLookup(xmlCatalogXMLFiles, catal->URL);
1435
+ if (doc != NULL) {
1436
+ if (xmlDebugCatalogs)
1437
+ xmlGenericError(xmlGenericErrorContext,
1438
+ "Found %s in file hash\n", catal->URL);
1439
+
1440
+ if (catal->type == XML_CATA_CATALOG)
1441
+ catal->children = doc->children;
1442
+ else
1443
+ catal->children = doc;
1444
+ catal->dealloc = 0;
1445
+ xmlRMutexUnlock(xmlCatalogMutex);
1446
+ return(0);
1447
+ }
1448
+ if (xmlDebugCatalogs)
1449
+ xmlGenericError(xmlGenericErrorContext,
1450
+ "%s not found in file hash\n", catal->URL);
1451
+ }
1452
+
1453
+ /*
1454
+ * Fetch and parse. Note that xmlParseXMLCatalogFile does not
1455
+ * use the existing catalog, there is no recursion allowed at
1456
+ * that level.
1457
+ */
1458
+ doc = xmlParseXMLCatalogFile(catal->prefer, catal->URL);
1459
+ if (doc == NULL) {
1460
+ catal->type = XML_CATA_BROKEN_CATALOG;
1461
+ xmlRMutexUnlock(xmlCatalogMutex);
1462
+ return(-1);
1463
+ }
1464
+
1465
+ if (catal->type == XML_CATA_CATALOG)
1466
+ catal->children = doc->children;
1467
+ else
1468
+ catal->children = doc;
1469
+
1470
+ doc->dealloc = 1;
1471
+
1472
+ if (xmlCatalogXMLFiles == NULL)
1473
+ xmlCatalogXMLFiles = xmlHashCreate(10);
1474
+ if (xmlCatalogXMLFiles != NULL) {
1475
+ if (xmlDebugCatalogs)
1476
+ xmlGenericError(xmlGenericErrorContext,
1477
+ "%s added to file hash\n", catal->URL);
1478
+ xmlHashAddEntry(xmlCatalogXMLFiles, catal->URL, doc);
1479
+ }
1480
+ xmlRMutexUnlock(xmlCatalogMutex);
1481
+ return(0);
1482
+ }
1483
+
1484
+ /************************************************************************
1485
+ * *
1486
+ * XML Catalog handling *
1487
+ * *
1488
+ ************************************************************************/
1489
+
1490
+ /**
1491
+ * xmlAddXMLCatalog:
1492
+ * @catal: top of an XML catalog
1493
+ * @type: the type of record to add to the catalog
1494
+ * @orig: the system, public or prefix to match (or NULL)
1495
+ * @replace: the replacement value for the match
1496
+ *
1497
+ * Add an entry in the XML catalog, it may overwrite existing but
1498
+ * different entries.
1499
+ *
1500
+ * Returns 0 if successful, -1 otherwise
1501
+ */
1502
+ static int
1503
+ xmlAddXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *type,
1504
+ const xmlChar *orig, const xmlChar *replace) {
1505
+ xmlCatalogEntryPtr cur;
1506
+ xmlCatalogEntryType typ;
1507
+ int doregister = 0;
1508
+
1509
+ if ((catal == NULL) ||
1510
+ ((catal->type != XML_CATA_CATALOG) &&
1511
+ (catal->type != XML_CATA_BROKEN_CATALOG)))
1512
+ return(-1);
1513
+ if (catal->children == NULL) {
1514
+ xmlFetchXMLCatalogFile(catal);
1515
+ }
1516
+ if (catal->children == NULL)
1517
+ doregister = 1;
1518
+
1519
+ typ = xmlGetXMLCatalogEntryType(type);
1520
+ if (typ == XML_CATA_NONE) {
1521
+ if (xmlDebugCatalogs)
1522
+ xmlGenericError(xmlGenericErrorContext,
1523
+ "Failed to add unknown element %s to catalog\n", type);
1524
+ return(-1);
1525
+ }
1526
+
1527
+ cur = catal->children;
1528
+ /*
1529
+ * Might be a simple "update in place"
1530
+ */
1531
+ if (cur != NULL) {
1532
+ while (cur != NULL) {
1533
+ if ((orig != NULL) && (cur->type == typ) &&
1534
+ (xmlStrEqual(orig, cur->name))) {
1535
+ if (xmlDebugCatalogs)
1536
+ xmlGenericError(xmlGenericErrorContext,
1537
+ "Updating element %s to catalog\n", type);
1538
+ if (cur->value != NULL)
1539
+ xmlFree(cur->value);
1540
+ if (cur->URL != NULL)
1541
+ xmlFree(cur->URL);
1542
+ cur->value = xmlStrdup(replace);
1543
+ cur->URL = xmlStrdup(replace);
1544
+ return(0);
1545
+ }
1546
+ if (cur->next == NULL)
1547
+ break;
1548
+ cur = cur->next;
1549
+ }
1550
+ }
1551
+ if (xmlDebugCatalogs)
1552
+ xmlGenericError(xmlGenericErrorContext,
1553
+ "Adding element %s to catalog\n", type);
1554
+ if (cur == NULL)
1555
+ catal->children = xmlNewCatalogEntry(typ, orig, replace,
1556
+ NULL, catal->prefer, NULL);
1557
+ else
1558
+ cur->next = xmlNewCatalogEntry(typ, orig, replace,
1559
+ NULL, catal->prefer, NULL);
1560
+ if (doregister) {
1561
+ catal->type = XML_CATA_CATALOG;
1562
+ cur = (xmlCatalogEntryPtr)xmlHashLookup(xmlCatalogXMLFiles, catal->URL);
1563
+ if (cur != NULL)
1564
+ cur->children = catal->children;
1565
+ }
1566
+
1567
+ return(0);
1568
+ }
1569
+
1570
+ /**
1571
+ * xmlDelXMLCatalog:
1572
+ * @catal: top of an XML catalog
1573
+ * @value: the value to remove from the catalog
1574
+ *
1575
+ * Remove entries in the XML catalog where the value or the URI
1576
+ * is equal to @value
1577
+ *
1578
+ * Returns the number of entries removed if successful, -1 otherwise
1579
+ */
1580
+ static int
1581
+ xmlDelXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *value) {
1582
+ xmlCatalogEntryPtr cur;
1583
+ int ret = 0;
1584
+
1585
+ if ((catal == NULL) ||
1586
+ ((catal->type != XML_CATA_CATALOG) &&
1587
+ (catal->type != XML_CATA_BROKEN_CATALOG)))
1588
+ return(-1);
1589
+ if (value == NULL)
1590
+ return(-1);
1591
+ if (catal->children == NULL) {
1592
+ xmlFetchXMLCatalogFile(catal);
1593
+ }
1594
+
1595
+ /*
1596
+ * Scan the children
1597
+ */
1598
+ cur = catal->children;
1599
+ while (cur != NULL) {
1600
+ if (((cur->name != NULL) && (xmlStrEqual(value, cur->name))) ||
1601
+ (xmlStrEqual(value, cur->value))) {
1602
+ if (xmlDebugCatalogs) {
1603
+ if (cur->name != NULL)
1604
+ xmlGenericError(xmlGenericErrorContext,
1605
+ "Removing element %s from catalog\n", cur->name);
1606
+ else
1607
+ xmlGenericError(xmlGenericErrorContext,
1608
+ "Removing element %s from catalog\n", cur->value);
1609
+ }
1610
+ cur->type = XML_CATA_REMOVED;
1611
+ }
1612
+ cur = cur->next;
1613
+ }
1614
+ return(ret);
1615
+ }
1616
+
1617
+ /**
1618
+ * xmlCatalogXMLResolve:
1619
+ * @catal: a catalog list
1620
+ * @pubID: the public ID string
1621
+ * @sysID: the system ID string
1622
+ *
1623
+ * Do a complete resolution lookup of an External Identifier for a
1624
+ * list of catalog entries.
1625
+ *
1626
+ * Implements (or tries to) 7.1. External Identifier Resolution
1627
+ * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
1628
+ *
1629
+ * Returns the URI of the resource or NULL if not found
1630
+ */
1631
+ static xmlChar *
1632
+ xmlCatalogXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
1633
+ const xmlChar *sysID) {
1634
+ xmlChar *ret = NULL;
1635
+ xmlCatalogEntryPtr cur;
1636
+ int haveDelegate = 0;
1637
+ int haveNext = 0;
1638
+
1639
+ /*
1640
+ * protection against loops
1641
+ */
1642
+ if (catal->depth > MAX_CATAL_DEPTH) {
1643
+ xmlCatalogErr(catal, NULL, XML_CATALOG_RECURSION,
1644
+ "Detected recursion in catalog %s\n",
1645
+ catal->name, NULL, NULL);
1646
+ return(NULL);
1647
+ }
1648
+ catal->depth++;
1649
+
1650
+ /*
1651
+ * First tries steps 2/ 3/ 4/ if a system ID is provided.
1652
+ */
1653
+ if (sysID != NULL) {
1654
+ xmlCatalogEntryPtr rewrite = NULL;
1655
+ int lenrewrite = 0, len;
1656
+ cur = catal;
1657
+ haveDelegate = 0;
1658
+ while (cur != NULL) {
1659
+ switch (cur->type) {
1660
+ case XML_CATA_SYSTEM:
1661
+ if (xmlStrEqual(sysID, cur->name)) {
1662
+ if (xmlDebugCatalogs)
1663
+ xmlGenericError(xmlGenericErrorContext,
1664
+ "Found system match %s, using %s\n",
1665
+ cur->name, cur->URL);
1666
+ catal->depth--;
1667
+ return(xmlStrdup(cur->URL));
1668
+ }
1669
+ break;
1670
+ case XML_CATA_REWRITE_SYSTEM:
1671
+ len = xmlStrlen(cur->name);
1672
+ if ((len > lenrewrite) &&
1673
+ (!xmlStrncmp(sysID, cur->name, len))) {
1674
+ lenrewrite = len;
1675
+ rewrite = cur;
1676
+ }
1677
+ break;
1678
+ case XML_CATA_DELEGATE_SYSTEM:
1679
+ if (!xmlStrncmp(sysID, cur->name, xmlStrlen(cur->name)))
1680
+ haveDelegate++;
1681
+ break;
1682
+ case XML_CATA_NEXT_CATALOG:
1683
+ haveNext++;
1684
+ break;
1685
+ default:
1686
+ break;
1687
+ }
1688
+ cur = cur->next;
1689
+ }
1690
+ if (rewrite != NULL) {
1691
+ if (xmlDebugCatalogs)
1692
+ xmlGenericError(xmlGenericErrorContext,
1693
+ "Using rewriting rule %s\n", rewrite->name);
1694
+ ret = xmlStrdup(rewrite->URL);
1695
+ if (ret != NULL)
1696
+ ret = xmlStrcat(ret, &sysID[lenrewrite]);
1697
+ catal->depth--;
1698
+ return(ret);
1699
+ }
1700
+ if (haveDelegate) {
1701
+ const xmlChar *delegates[MAX_DELEGATE];
1702
+ int nbList = 0, i;
1703
+
1704
+ /*
1705
+ * Assume the entries have been sorted by decreasing substring
1706
+ * matches when the list was produced.
1707
+ */
1708
+ cur = catal;
1709
+ while (cur != NULL) {
1710
+ if ((cur->type == XML_CATA_DELEGATE_SYSTEM) &&
1711
+ (!xmlStrncmp(sysID, cur->name, xmlStrlen(cur->name)))) {
1712
+ for (i = 0;i < nbList;i++)
1713
+ if (xmlStrEqual(cur->URL, delegates[i]))
1714
+ break;
1715
+ if (i < nbList) {
1716
+ cur = cur->next;
1717
+ continue;
1718
+ }
1719
+ if (nbList < MAX_DELEGATE)
1720
+ delegates[nbList++] = cur->URL;
1721
+
1722
+ if (cur->children == NULL) {
1723
+ xmlFetchXMLCatalogFile(cur);
1724
+ }
1725
+ if (cur->children != NULL) {
1726
+ if (xmlDebugCatalogs)
1727
+ xmlGenericError(xmlGenericErrorContext,
1728
+ "Trying system delegate %s\n", cur->URL);
1729
+ ret = xmlCatalogListXMLResolve(
1730
+ cur->children, NULL, sysID);
1731
+ if (ret != NULL) {
1732
+ catal->depth--;
1733
+ return(ret);
1734
+ }
1735
+ }
1736
+ }
1737
+ cur = cur->next;
1738
+ }
1739
+ /*
1740
+ * Apply the cut algorithm explained in 4/
1741
+ */
1742
+ catal->depth--;
1743
+ return(XML_CATAL_BREAK);
1744
+ }
1745
+ }
1746
+ /*
1747
+ * Then tries 5/ 6/ if a public ID is provided
1748
+ */
1749
+ if (pubID != NULL) {
1750
+ cur = catal;
1751
+ haveDelegate = 0;
1752
+ while (cur != NULL) {
1753
+ switch (cur->type) {
1754
+ case XML_CATA_PUBLIC:
1755
+ if (xmlStrEqual(pubID, cur->name)) {
1756
+ if (xmlDebugCatalogs)
1757
+ xmlGenericError(xmlGenericErrorContext,
1758
+ "Found public match %s\n", cur->name);
1759
+ catal->depth--;
1760
+ return(xmlStrdup(cur->URL));
1761
+ }
1762
+ break;
1763
+ case XML_CATA_DELEGATE_PUBLIC:
1764
+ if (!xmlStrncmp(pubID, cur->name, xmlStrlen(cur->name)) &&
1765
+ (cur->prefer == XML_CATA_PREFER_PUBLIC))
1766
+ haveDelegate++;
1767
+ break;
1768
+ case XML_CATA_NEXT_CATALOG:
1769
+ if (sysID == NULL)
1770
+ haveNext++;
1771
+ break;
1772
+ default:
1773
+ break;
1774
+ }
1775
+ cur = cur->next;
1776
+ }
1777
+ if (haveDelegate) {
1778
+ const xmlChar *delegates[MAX_DELEGATE];
1779
+ int nbList = 0, i;
1780
+
1781
+ /*
1782
+ * Assume the entries have been sorted by decreasing substring
1783
+ * matches when the list was produced.
1784
+ */
1785
+ cur = catal;
1786
+ while (cur != NULL) {
1787
+ if ((cur->type == XML_CATA_DELEGATE_PUBLIC) &&
1788
+ (cur->prefer == XML_CATA_PREFER_PUBLIC) &&
1789
+ (!xmlStrncmp(pubID, cur->name, xmlStrlen(cur->name)))) {
1790
+
1791
+ for (i = 0;i < nbList;i++)
1792
+ if (xmlStrEqual(cur->URL, delegates[i]))
1793
+ break;
1794
+ if (i < nbList) {
1795
+ cur = cur->next;
1796
+ continue;
1797
+ }
1798
+ if (nbList < MAX_DELEGATE)
1799
+ delegates[nbList++] = cur->URL;
1800
+
1801
+ if (cur->children == NULL) {
1802
+ xmlFetchXMLCatalogFile(cur);
1803
+ }
1804
+ if (cur->children != NULL) {
1805
+ if (xmlDebugCatalogs)
1806
+ xmlGenericError(xmlGenericErrorContext,
1807
+ "Trying public delegate %s\n", cur->URL);
1808
+ ret = xmlCatalogListXMLResolve(
1809
+ cur->children, pubID, NULL);
1810
+ if (ret != NULL) {
1811
+ catal->depth--;
1812
+ return(ret);
1813
+ }
1814
+ }
1815
+ }
1816
+ cur = cur->next;
1817
+ }
1818
+ /*
1819
+ * Apply the cut algorithm explained in 4/
1820
+ */
1821
+ catal->depth--;
1822
+ return(XML_CATAL_BREAK);
1823
+ }
1824
+ }
1825
+ if (haveNext) {
1826
+ cur = catal;
1827
+ while (cur != NULL) {
1828
+ if (cur->type == XML_CATA_NEXT_CATALOG) {
1829
+ if (cur->children == NULL) {
1830
+ xmlFetchXMLCatalogFile(cur);
1831
+ }
1832
+ if (cur->children != NULL) {
1833
+ ret = xmlCatalogListXMLResolve(cur->children, pubID, sysID);
1834
+ if (ret != NULL) {
1835
+ catal->depth--;
1836
+ return(ret);
1837
+ } else if (catal->depth > MAX_CATAL_DEPTH) {
1838
+ return(NULL);
1839
+ }
1840
+ }
1841
+ }
1842
+ cur = cur->next;
1843
+ }
1844
+ }
1845
+
1846
+ catal->depth--;
1847
+ return(NULL);
1848
+ }
1849
+
1850
+ /**
1851
+ * xmlCatalogXMLResolveURI:
1852
+ * @catal: a catalog list
1853
+ * @URI: the URI
1854
+ * @sysID: the system ID string
1855
+ *
1856
+ * Do a complete resolution lookup of an External Identifier for a
1857
+ * list of catalog entries.
1858
+ *
1859
+ * Implements (or tries to) 7.2.2. URI Resolution
1860
+ * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
1861
+ *
1862
+ * Returns the URI of the resource or NULL if not found
1863
+ */
1864
+ static xmlChar *
1865
+ xmlCatalogXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) {
1866
+ xmlChar *ret = NULL;
1867
+ xmlCatalogEntryPtr cur;
1868
+ int haveDelegate = 0;
1869
+ int haveNext = 0;
1870
+ xmlCatalogEntryPtr rewrite = NULL;
1871
+ int lenrewrite = 0, len;
1872
+
1873
+ if (catal == NULL)
1874
+ return(NULL);
1875
+
1876
+ if (URI == NULL)
1877
+ return(NULL);
1878
+
1879
+ if (catal->depth > MAX_CATAL_DEPTH) {
1880
+ xmlCatalogErr(catal, NULL, XML_CATALOG_RECURSION,
1881
+ "Detected recursion in catalog %s\n",
1882
+ catal->name, NULL, NULL);
1883
+ return(NULL);
1884
+ }
1885
+
1886
+ /*
1887
+ * First tries steps 2/ 3/ 4/ if a system ID is provided.
1888
+ */
1889
+ cur = catal;
1890
+ haveDelegate = 0;
1891
+ while (cur != NULL) {
1892
+ switch (cur->type) {
1893
+ case XML_CATA_URI:
1894
+ if (xmlStrEqual(URI, cur->name)) {
1895
+ if (xmlDebugCatalogs)
1896
+ xmlGenericError(xmlGenericErrorContext,
1897
+ "Found URI match %s\n", cur->name);
1898
+ return(xmlStrdup(cur->URL));
1899
+ }
1900
+ break;
1901
+ case XML_CATA_REWRITE_URI:
1902
+ len = xmlStrlen(cur->name);
1903
+ if ((len > lenrewrite) &&
1904
+ (!xmlStrncmp(URI, cur->name, len))) {
1905
+ lenrewrite = len;
1906
+ rewrite = cur;
1907
+ }
1908
+ break;
1909
+ case XML_CATA_DELEGATE_URI:
1910
+ if (!xmlStrncmp(URI, cur->name, xmlStrlen(cur->name)))
1911
+ haveDelegate++;
1912
+ break;
1913
+ case XML_CATA_NEXT_CATALOG:
1914
+ haveNext++;
1915
+ break;
1916
+ default:
1917
+ break;
1918
+ }
1919
+ cur = cur->next;
1920
+ }
1921
+ if (rewrite != NULL) {
1922
+ if (xmlDebugCatalogs)
1923
+ xmlGenericError(xmlGenericErrorContext,
1924
+ "Using rewriting rule %s\n", rewrite->name);
1925
+ ret = xmlStrdup(rewrite->URL);
1926
+ if (ret != NULL)
1927
+ ret = xmlStrcat(ret, &URI[lenrewrite]);
1928
+ return(ret);
1929
+ }
1930
+ if (haveDelegate) {
1931
+ const xmlChar *delegates[MAX_DELEGATE];
1932
+ int nbList = 0, i;
1933
+
1934
+ /*
1935
+ * Assume the entries have been sorted by decreasing substring
1936
+ * matches when the list was produced.
1937
+ */
1938
+ cur = catal;
1939
+ while (cur != NULL) {
1940
+ if (((cur->type == XML_CATA_DELEGATE_SYSTEM) ||
1941
+ (cur->type == XML_CATA_DELEGATE_URI)) &&
1942
+ (!xmlStrncmp(URI, cur->name, xmlStrlen(cur->name)))) {
1943
+ for (i = 0;i < nbList;i++)
1944
+ if (xmlStrEqual(cur->URL, delegates[i]))
1945
+ break;
1946
+ if (i < nbList) {
1947
+ cur = cur->next;
1948
+ continue;
1949
+ }
1950
+ if (nbList < MAX_DELEGATE)
1951
+ delegates[nbList++] = cur->URL;
1952
+
1953
+ if (cur->children == NULL) {
1954
+ xmlFetchXMLCatalogFile(cur);
1955
+ }
1956
+ if (cur->children != NULL) {
1957
+ if (xmlDebugCatalogs)
1958
+ xmlGenericError(xmlGenericErrorContext,
1959
+ "Trying URI delegate %s\n", cur->URL);
1960
+ ret = xmlCatalogListXMLResolveURI(
1961
+ cur->children, URI);
1962
+ if (ret != NULL)
1963
+ return(ret);
1964
+ }
1965
+ }
1966
+ cur = cur->next;
1967
+ }
1968
+ /*
1969
+ * Apply the cut algorithm explained in 4/
1970
+ */
1971
+ return(XML_CATAL_BREAK);
1972
+ }
1973
+ if (haveNext) {
1974
+ cur = catal;
1975
+ while (cur != NULL) {
1976
+ if (cur->type == XML_CATA_NEXT_CATALOG) {
1977
+ if (cur->children == NULL) {
1978
+ xmlFetchXMLCatalogFile(cur);
1979
+ }
1980
+ if (cur->children != NULL) {
1981
+ ret = xmlCatalogListXMLResolveURI(cur->children, URI);
1982
+ if (ret != NULL)
1983
+ return(ret);
1984
+ }
1985
+ }
1986
+ cur = cur->next;
1987
+ }
1988
+ }
1989
+
1990
+ return(NULL);
1991
+ }
1992
+
1993
+ /**
1994
+ * xmlCatalogListXMLResolve:
1995
+ * @catal: a catalog list
1996
+ * @pubID: the public ID string
1997
+ * @sysID: the system ID string
1998
+ *
1999
+ * Do a complete resolution lookup of an External Identifier for a
2000
+ * list of catalogs
2001
+ *
2002
+ * Implements (or tries to) 7.1. External Identifier Resolution
2003
+ * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
2004
+ *
2005
+ * Returns the URI of the resource or NULL if not found
2006
+ */
2007
+ static xmlChar *
2008
+ xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
2009
+ const xmlChar *sysID) {
2010
+ xmlChar *ret = NULL;
2011
+ xmlChar *urnID = NULL;
2012
+ xmlChar *normid;
2013
+
2014
+ if (catal == NULL)
2015
+ return(NULL);
2016
+ if ((pubID == NULL) && (sysID == NULL))
2017
+ return(NULL);
2018
+
2019
+ normid = xmlCatalogNormalizePublic(pubID);
2020
+ if (normid != NULL)
2021
+ pubID = (*normid != 0 ? normid : NULL);
2022
+
2023
+ if (!xmlStrncmp(pubID, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) {
2024
+ urnID = xmlCatalogUnWrapURN(pubID);
2025
+ if (xmlDebugCatalogs) {
2026
+ if (urnID == NULL)
2027
+ xmlGenericError(xmlGenericErrorContext,
2028
+ "Public URN ID %s expanded to NULL\n", pubID);
2029
+ else
2030
+ xmlGenericError(xmlGenericErrorContext,
2031
+ "Public URN ID expanded to %s\n", urnID);
2032
+ }
2033
+ ret = xmlCatalogListXMLResolve(catal, urnID, sysID);
2034
+ if (urnID != NULL)
2035
+ xmlFree(urnID);
2036
+ if (normid != NULL)
2037
+ xmlFree(normid);
2038
+ return(ret);
2039
+ }
2040
+ if (!xmlStrncmp(sysID, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) {
2041
+ urnID = xmlCatalogUnWrapURN(sysID);
2042
+ if (xmlDebugCatalogs) {
2043
+ if (urnID == NULL)
2044
+ xmlGenericError(xmlGenericErrorContext,
2045
+ "System URN ID %s expanded to NULL\n", sysID);
2046
+ else
2047
+ xmlGenericError(xmlGenericErrorContext,
2048
+ "System URN ID expanded to %s\n", urnID);
2049
+ }
2050
+ if (pubID == NULL)
2051
+ ret = xmlCatalogListXMLResolve(catal, urnID, NULL);
2052
+ else if (xmlStrEqual(pubID, urnID))
2053
+ ret = xmlCatalogListXMLResolve(catal, pubID, NULL);
2054
+ else {
2055
+ ret = xmlCatalogListXMLResolve(catal, pubID, urnID);
2056
+ }
2057
+ if (urnID != NULL)
2058
+ xmlFree(urnID);
2059
+ if (normid != NULL)
2060
+ xmlFree(normid);
2061
+ return(ret);
2062
+ }
2063
+ while (catal != NULL) {
2064
+ if (catal->type == XML_CATA_CATALOG) {
2065
+ if (catal->children == NULL) {
2066
+ xmlFetchXMLCatalogFile(catal);
2067
+ }
2068
+ if (catal->children != NULL) {
2069
+ ret = xmlCatalogXMLResolve(catal->children, pubID, sysID);
2070
+ if (ret != NULL) {
2071
+ break;
2072
+ } else if (catal->children->depth > MAX_CATAL_DEPTH) {
2073
+ ret = NULL;
2074
+ break;
2075
+ }
2076
+ }
2077
+ }
2078
+ catal = catal->next;
2079
+ }
2080
+ if (normid != NULL)
2081
+ xmlFree(normid);
2082
+ return(ret);
2083
+ }
2084
+
2085
+ /**
2086
+ * xmlCatalogListXMLResolveURI:
2087
+ * @catal: a catalog list
2088
+ * @URI: the URI
2089
+ *
2090
+ * Do a complete resolution lookup of an URI for a list of catalogs
2091
+ *
2092
+ * Implements (or tries to) 7.2. URI Resolution
2093
+ * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
2094
+ *
2095
+ * Returns the URI of the resource or NULL if not found
2096
+ */
2097
+ static xmlChar *
2098
+ xmlCatalogListXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) {
2099
+ xmlChar *ret = NULL;
2100
+ xmlChar *urnID = NULL;
2101
+
2102
+ if (catal == NULL)
2103
+ return(NULL);
2104
+ if (URI == NULL)
2105
+ return(NULL);
2106
+
2107
+ if (!xmlStrncmp(URI, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) {
2108
+ urnID = xmlCatalogUnWrapURN(URI);
2109
+ if (xmlDebugCatalogs) {
2110
+ if (urnID == NULL)
2111
+ xmlGenericError(xmlGenericErrorContext,
2112
+ "URN ID %s expanded to NULL\n", URI);
2113
+ else
2114
+ xmlGenericError(xmlGenericErrorContext,
2115
+ "URN ID expanded to %s\n", urnID);
2116
+ }
2117
+ ret = xmlCatalogListXMLResolve(catal, urnID, NULL);
2118
+ if (urnID != NULL)
2119
+ xmlFree(urnID);
2120
+ return(ret);
2121
+ }
2122
+ while (catal != NULL) {
2123
+ if (catal->type == XML_CATA_CATALOG) {
2124
+ if (catal->children == NULL) {
2125
+ xmlFetchXMLCatalogFile(catal);
2126
+ }
2127
+ if (catal->children != NULL) {
2128
+ ret = xmlCatalogXMLResolveURI(catal->children, URI);
2129
+ if (ret != NULL)
2130
+ return(ret);
2131
+ }
2132
+ }
2133
+ catal = catal->next;
2134
+ }
2135
+ return(ret);
2136
+ }
2137
+
2138
+ /************************************************************************
2139
+ * *
2140
+ * The SGML Catalog parser *
2141
+ * *
2142
+ ************************************************************************/
2143
+
2144
+
2145
+ #define RAW *cur
2146
+ #define NEXT cur++;
2147
+ #define SKIP(x) cur += x;
2148
+
2149
+ #define SKIP_BLANKS while (IS_BLANK_CH(*cur)) NEXT;
2150
+
2151
+ /**
2152
+ * xmlParseSGMLCatalogComment:
2153
+ * @cur: the current character
2154
+ *
2155
+ * Skip a comment in an SGML catalog
2156
+ *
2157
+ * Returns new current character
2158
+ */
2159
+ static const xmlChar *
2160
+ xmlParseSGMLCatalogComment(const xmlChar *cur) {
2161
+ if ((cur[0] != '-') || (cur[1] != '-'))
2162
+ return(cur);
2163
+ SKIP(2);
2164
+ while ((cur[0] != 0) && ((cur[0] != '-') || ((cur[1] != '-'))))
2165
+ NEXT;
2166
+ if (cur[0] == 0) {
2167
+ return(NULL);
2168
+ }
2169
+ return(cur + 2);
2170
+ }
2171
+
2172
+ /**
2173
+ * xmlParseSGMLCatalogPubid:
2174
+ * @cur: the current character
2175
+ * @id: the return location
2176
+ *
2177
+ * Parse an SGML catalog ID
2178
+ *
2179
+ * Returns new current character and store the value in @id
2180
+ */
2181
+ static const xmlChar *
2182
+ xmlParseSGMLCatalogPubid(const xmlChar *cur, xmlChar **id) {
2183
+ xmlChar *buf = NULL, *tmp;
2184
+ int len = 0;
2185
+ int size = 50;
2186
+ xmlChar stop;
2187
+ int count = 0;
2188
+
2189
+ *id = NULL;
2190
+
2191
+ if (RAW == '"') {
2192
+ NEXT;
2193
+ stop = '"';
2194
+ } else if (RAW == '\'') {
2195
+ NEXT;
2196
+ stop = '\'';
2197
+ } else {
2198
+ stop = ' ';
2199
+ }
2200
+ buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
2201
+ if (buf == NULL) {
2202
+ xmlCatalogErrMemory("allocating public ID");
2203
+ return(NULL);
2204
+ }
2205
+ while (IS_PUBIDCHAR_CH(*cur) || (*cur == '?')) {
2206
+ if ((*cur == stop) && (stop != ' '))
2207
+ break;
2208
+ if ((stop == ' ') && (IS_BLANK_CH(*cur)))
2209
+ break;
2210
+ if (len + 1 >= size) {
2211
+ size *= 2;
2212
+ tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
2213
+ if (tmp == NULL) {
2214
+ xmlCatalogErrMemory("allocating public ID");
2215
+ xmlFree(buf);
2216
+ return(NULL);
2217
+ }
2218
+ buf = tmp;
2219
+ }
2220
+ buf[len++] = *cur;
2221
+ count++;
2222
+ NEXT;
2223
+ }
2224
+ buf[len] = 0;
2225
+ if (stop == ' ') {
2226
+ if (!IS_BLANK_CH(*cur)) {
2227
+ xmlFree(buf);
2228
+ return(NULL);
2229
+ }
2230
+ } else {
2231
+ if (*cur != stop) {
2232
+ xmlFree(buf);
2233
+ return(NULL);
2234
+ }
2235
+ NEXT;
2236
+ }
2237
+ *id = buf;
2238
+ return(cur);
2239
+ }
2240
+
2241
+ /**
2242
+ * xmlParseSGMLCatalogName:
2243
+ * @cur: the current character
2244
+ * @name: the return location
2245
+ *
2246
+ * Parse an SGML catalog name
2247
+ *
2248
+ * Returns new current character and store the value in @name
2249
+ */
2250
+ static const xmlChar *
2251
+ xmlParseSGMLCatalogName(const xmlChar *cur, xmlChar **name) {
2252
+ xmlChar buf[XML_MAX_NAMELEN + 5];
2253
+ int len = 0;
2254
+ int c;
2255
+
2256
+ *name = NULL;
2257
+
2258
+ /*
2259
+ * Handler for more complex cases
2260
+ */
2261
+ c = *cur;
2262
+ if ((!IS_LETTER(c) && (c != '_') && (c != ':'))) {
2263
+ return(NULL);
2264
+ }
2265
+
2266
+ while (((IS_LETTER(c)) || (IS_DIGIT(c)) ||
2267
+ (c == '.') || (c == '-') ||
2268
+ (c == '_') || (c == ':'))) {
2269
+ buf[len++] = c;
2270
+ cur++;
2271
+ c = *cur;
2272
+ if (len >= XML_MAX_NAMELEN)
2273
+ return(NULL);
2274
+ }
2275
+ *name = xmlStrndup(buf, len);
2276
+ return(cur);
2277
+ }
2278
+
2279
+ /**
2280
+ * xmlGetSGMLCatalogEntryType:
2281
+ * @name: the entry name
2282
+ *
2283
+ * Get the Catalog entry type for a given SGML Catalog name
2284
+ *
2285
+ * Returns Catalog entry type
2286
+ */
2287
+ static xmlCatalogEntryType
2288
+ xmlGetSGMLCatalogEntryType(const xmlChar *name) {
2289
+ xmlCatalogEntryType type = XML_CATA_NONE;
2290
+ if (xmlStrEqual(name, (const xmlChar *) "SYSTEM"))
2291
+ type = SGML_CATA_SYSTEM;
2292
+ else if (xmlStrEqual(name, (const xmlChar *) "PUBLIC"))
2293
+ type = SGML_CATA_PUBLIC;
2294
+ else if (xmlStrEqual(name, (const xmlChar *) "DELEGATE"))
2295
+ type = SGML_CATA_DELEGATE;
2296
+ else if (xmlStrEqual(name, (const xmlChar *) "ENTITY"))
2297
+ type = SGML_CATA_ENTITY;
2298
+ else if (xmlStrEqual(name, (const xmlChar *) "DOCTYPE"))
2299
+ type = SGML_CATA_DOCTYPE;
2300
+ else if (xmlStrEqual(name, (const xmlChar *) "LINKTYPE"))
2301
+ type = SGML_CATA_LINKTYPE;
2302
+ else if (xmlStrEqual(name, (const xmlChar *) "NOTATION"))
2303
+ type = SGML_CATA_NOTATION;
2304
+ else if (xmlStrEqual(name, (const xmlChar *) "SGMLDECL"))
2305
+ type = SGML_CATA_SGMLDECL;
2306
+ else if (xmlStrEqual(name, (const xmlChar *) "DOCUMENT"))
2307
+ type = SGML_CATA_DOCUMENT;
2308
+ else if (xmlStrEqual(name, (const xmlChar *) "CATALOG"))
2309
+ type = SGML_CATA_CATALOG;
2310
+ else if (xmlStrEqual(name, (const xmlChar *) "BASE"))
2311
+ type = SGML_CATA_BASE;
2312
+ return(type);
2313
+ }
2314
+
2315
+ /**
2316
+ * xmlParseSGMLCatalog:
2317
+ * @catal: the SGML Catalog
2318
+ * @value: the content of the SGML Catalog serialization
2319
+ * @file: the filepath for the catalog
2320
+ * @super: should this be handled as a Super Catalog in which case
2321
+ * parsing is not recursive
2322
+ *
2323
+ * Parse an SGML catalog content and fill up the @catal hash table with
2324
+ * the new entries found.
2325
+ *
2326
+ * Returns 0 in case of success, -1 in case of error.
2327
+ */
2328
+ static int
2329
+ xmlParseSGMLCatalog(xmlCatalogPtr catal, const xmlChar *value,
2330
+ const char *file, int super) {
2331
+ const xmlChar *cur = value;
2332
+ xmlChar *base = NULL;
2333
+ int res;
2334
+
2335
+ if ((cur == NULL) || (file == NULL))
2336
+ return(-1);
2337
+ base = xmlStrdup((const xmlChar *) file);
2338
+
2339
+ while ((cur != NULL) && (cur[0] != 0)) {
2340
+ SKIP_BLANKS;
2341
+ if (cur[0] == 0)
2342
+ break;
2343
+ if ((cur[0] == '-') && (cur[1] == '-')) {
2344
+ cur = xmlParseSGMLCatalogComment(cur);
2345
+ if (cur == NULL) {
2346
+ /* error */
2347
+ break;
2348
+ }
2349
+ } else {
2350
+ xmlChar *sysid = NULL;
2351
+ xmlChar *name = NULL;
2352
+ xmlCatalogEntryType type = XML_CATA_NONE;
2353
+
2354
+ cur = xmlParseSGMLCatalogName(cur, &name);
2355
+ if (cur == NULL || name == NULL) {
2356
+ /* error */
2357
+ break;
2358
+ }
2359
+ if (!IS_BLANK_CH(*cur)) {
2360
+ /* error */
2361
+ break;
2362
+ }
2363
+ SKIP_BLANKS;
2364
+ if (xmlStrEqual(name, (const xmlChar *) "SYSTEM"))
2365
+ type = SGML_CATA_SYSTEM;
2366
+ else if (xmlStrEqual(name, (const xmlChar *) "PUBLIC"))
2367
+ type = SGML_CATA_PUBLIC;
2368
+ else if (xmlStrEqual(name, (const xmlChar *) "DELEGATE"))
2369
+ type = SGML_CATA_DELEGATE;
2370
+ else if (xmlStrEqual(name, (const xmlChar *) "ENTITY"))
2371
+ type = SGML_CATA_ENTITY;
2372
+ else if (xmlStrEqual(name, (const xmlChar *) "DOCTYPE"))
2373
+ type = SGML_CATA_DOCTYPE;
2374
+ else if (xmlStrEqual(name, (const xmlChar *) "LINKTYPE"))
2375
+ type = SGML_CATA_LINKTYPE;
2376
+ else if (xmlStrEqual(name, (const xmlChar *) "NOTATION"))
2377
+ type = SGML_CATA_NOTATION;
2378
+ else if (xmlStrEqual(name, (const xmlChar *) "SGMLDECL"))
2379
+ type = SGML_CATA_SGMLDECL;
2380
+ else if (xmlStrEqual(name, (const xmlChar *) "DOCUMENT"))
2381
+ type = SGML_CATA_DOCUMENT;
2382
+ else if (xmlStrEqual(name, (const xmlChar *) "CATALOG"))
2383
+ type = SGML_CATA_CATALOG;
2384
+ else if (xmlStrEqual(name, (const xmlChar *) "BASE"))
2385
+ type = SGML_CATA_BASE;
2386
+ else if (xmlStrEqual(name, (const xmlChar *) "OVERRIDE")) {
2387
+ xmlFree(name);
2388
+ cur = xmlParseSGMLCatalogName(cur, &name);
2389
+ if (name == NULL) {
2390
+ /* error */
2391
+ break;
2392
+ }
2393
+ xmlFree(name);
2394
+ continue;
2395
+ }
2396
+ xmlFree(name);
2397
+ name = NULL;
2398
+
2399
+ switch(type) {
2400
+ case SGML_CATA_ENTITY:
2401
+ if (*cur == '%')
2402
+ type = SGML_CATA_PENTITY;
2403
+ /* Falls through. */
2404
+ case SGML_CATA_PENTITY:
2405
+ case SGML_CATA_DOCTYPE:
2406
+ case SGML_CATA_LINKTYPE:
2407
+ case SGML_CATA_NOTATION:
2408
+ cur = xmlParseSGMLCatalogName(cur, &name);
2409
+ if (cur == NULL) {
2410
+ /* error */
2411
+ break;
2412
+ }
2413
+ if (!IS_BLANK_CH(*cur)) {
2414
+ /* error */
2415
+ break;
2416
+ }
2417
+ SKIP_BLANKS;
2418
+ cur = xmlParseSGMLCatalogPubid(cur, &sysid);
2419
+ if (cur == NULL) {
2420
+ /* error */
2421
+ break;
2422
+ }
2423
+ break;
2424
+ case SGML_CATA_PUBLIC:
2425
+ case SGML_CATA_SYSTEM:
2426
+ case SGML_CATA_DELEGATE:
2427
+ cur = xmlParseSGMLCatalogPubid(cur, &name);
2428
+ if (cur == NULL) {
2429
+ /* error */
2430
+ break;
2431
+ }
2432
+ if (type != SGML_CATA_SYSTEM) {
2433
+ xmlChar *normid;
2434
+
2435
+ normid = xmlCatalogNormalizePublic(name);
2436
+ if (normid != NULL) {
2437
+ if (name != NULL)
2438
+ xmlFree(name);
2439
+ if (*normid != 0)
2440
+ name = normid;
2441
+ else {
2442
+ xmlFree(normid);
2443
+ name = NULL;
2444
+ }
2445
+ }
2446
+ }
2447
+ if (!IS_BLANK_CH(*cur)) {
2448
+ /* error */
2449
+ break;
2450
+ }
2451
+ SKIP_BLANKS;
2452
+ cur = xmlParseSGMLCatalogPubid(cur, &sysid);
2453
+ if (cur == NULL) {
2454
+ /* error */
2455
+ break;
2456
+ }
2457
+ break;
2458
+ case SGML_CATA_BASE:
2459
+ case SGML_CATA_CATALOG:
2460
+ case SGML_CATA_DOCUMENT:
2461
+ case SGML_CATA_SGMLDECL:
2462
+ cur = xmlParseSGMLCatalogPubid(cur, &sysid);
2463
+ if (cur == NULL) {
2464
+ /* error */
2465
+ break;
2466
+ }
2467
+ break;
2468
+ default:
2469
+ break;
2470
+ }
2471
+ if (cur == NULL) {
2472
+ if (name != NULL)
2473
+ xmlFree(name);
2474
+ if (sysid != NULL)
2475
+ xmlFree(sysid);
2476
+ break;
2477
+ } else if (type == SGML_CATA_BASE) {
2478
+ if (base != NULL)
2479
+ xmlFree(base);
2480
+ base = xmlStrdup(sysid);
2481
+ } else if ((type == SGML_CATA_PUBLIC) ||
2482
+ (type == SGML_CATA_SYSTEM)) {
2483
+ xmlChar *filename;
2484
+
2485
+ filename = xmlBuildURI(sysid, base);
2486
+ if (filename != NULL) {
2487
+ xmlCatalogEntryPtr entry;
2488
+
2489
+ entry = xmlNewCatalogEntry(type, name, filename,
2490
+ NULL, XML_CATA_PREFER_NONE, NULL);
2491
+ res = xmlHashAddEntry(catal->sgml, name, entry);
2492
+ if (res < 0) {
2493
+ xmlFreeCatalogEntry(entry, NULL);
2494
+ }
2495
+ xmlFree(filename);
2496
+ }
2497
+
2498
+ } else if (type == SGML_CATA_CATALOG) {
2499
+ if (super) {
2500
+ xmlCatalogEntryPtr entry;
2501
+
2502
+ entry = xmlNewCatalogEntry(type, sysid, NULL, NULL,
2503
+ XML_CATA_PREFER_NONE, NULL);
2504
+ res = xmlHashAddEntry(catal->sgml, sysid, entry);
2505
+ if (res < 0) {
2506
+ xmlFreeCatalogEntry(entry, NULL);
2507
+ }
2508
+ } else {
2509
+ xmlChar *filename;
2510
+
2511
+ filename = xmlBuildURI(sysid, base);
2512
+ if (filename != NULL) {
2513
+ xmlExpandCatalog(catal, (const char *)filename);
2514
+ xmlFree(filename);
2515
+ }
2516
+ }
2517
+ }
2518
+ /*
2519
+ * drop anything else we won't handle it
2520
+ */
2521
+ if (name != NULL)
2522
+ xmlFree(name);
2523
+ if (sysid != NULL)
2524
+ xmlFree(sysid);
2525
+ }
2526
+ }
2527
+ if (base != NULL)
2528
+ xmlFree(base);
2529
+ if (cur == NULL)
2530
+ return(-1);
2531
+ return(0);
2532
+ }
2533
+
2534
+ /************************************************************************
2535
+ * *
2536
+ * SGML Catalog handling *
2537
+ * *
2538
+ ************************************************************************/
2539
+
2540
+ /**
2541
+ * xmlCatalogGetSGMLPublic:
2542
+ * @catal: an SGML catalog hash
2543
+ * @pubID: the public ID string
2544
+ *
2545
+ * Try to lookup the catalog local reference associated to a public ID
2546
+ *
2547
+ * Returns the local resource if found or NULL otherwise.
2548
+ */
2549
+ static const xmlChar *
2550
+ xmlCatalogGetSGMLPublic(xmlHashTablePtr catal, const xmlChar *pubID) {
2551
+ xmlCatalogEntryPtr entry;
2552
+ xmlChar *normid;
2553
+
2554
+ if (catal == NULL)
2555
+ return(NULL);
2556
+
2557
+ normid = xmlCatalogNormalizePublic(pubID);
2558
+ if (normid != NULL)
2559
+ pubID = (*normid != 0 ? normid : NULL);
2560
+
2561
+ entry = (xmlCatalogEntryPtr) xmlHashLookup(catal, pubID);
2562
+ if (entry == NULL) {
2563
+ if (normid != NULL)
2564
+ xmlFree(normid);
2565
+ return(NULL);
2566
+ }
2567
+ if (entry->type == SGML_CATA_PUBLIC) {
2568
+ if (normid != NULL)
2569
+ xmlFree(normid);
2570
+ return(entry->URL);
2571
+ }
2572
+ if (normid != NULL)
2573
+ xmlFree(normid);
2574
+ return(NULL);
2575
+ }
2576
+
2577
+ /**
2578
+ * xmlCatalogGetSGMLSystem:
2579
+ * @catal: an SGML catalog hash
2580
+ * @sysID: the system ID string
2581
+ *
2582
+ * Try to lookup the catalog local reference for a system ID
2583
+ *
2584
+ * Returns the local resource if found or NULL otherwise.
2585
+ */
2586
+ static const xmlChar *
2587
+ xmlCatalogGetSGMLSystem(xmlHashTablePtr catal, const xmlChar *sysID) {
2588
+ xmlCatalogEntryPtr entry;
2589
+
2590
+ if (catal == NULL)
2591
+ return(NULL);
2592
+
2593
+ entry = (xmlCatalogEntryPtr) xmlHashLookup(catal, sysID);
2594
+ if (entry == NULL)
2595
+ return(NULL);
2596
+ if (entry->type == SGML_CATA_SYSTEM)
2597
+ return(entry->URL);
2598
+ return(NULL);
2599
+ }
2600
+
2601
+ /**
2602
+ * xmlCatalogSGMLResolve:
2603
+ * @catal: the SGML catalog
2604
+ * @pubID: the public ID string
2605
+ * @sysID: the system ID string
2606
+ *
2607
+ * Do a complete resolution lookup of an External Identifier
2608
+ *
2609
+ * Returns the URI of the resource or NULL if not found
2610
+ */
2611
+ static const xmlChar *
2612
+ xmlCatalogSGMLResolve(xmlCatalogPtr catal, const xmlChar *pubID,
2613
+ const xmlChar *sysID) {
2614
+ const xmlChar *ret = NULL;
2615
+
2616
+ if (catal->sgml == NULL)
2617
+ return(NULL);
2618
+
2619
+ if (pubID != NULL)
2620
+ ret = xmlCatalogGetSGMLPublic(catal->sgml, pubID);
2621
+ if (ret != NULL)
2622
+ return(ret);
2623
+ if (sysID != NULL)
2624
+ ret = xmlCatalogGetSGMLSystem(catal->sgml, sysID);
2625
+ if (ret != NULL)
2626
+ return(ret);
2627
+ return(NULL);
2628
+ }
2629
+
2630
+ /************************************************************************
2631
+ * *
2632
+ * Specific Public interfaces *
2633
+ * *
2634
+ ************************************************************************/
2635
+
2636
+ /**
2637
+ * xmlLoadSGMLSuperCatalog:
2638
+ * @filename: a file path
2639
+ *
2640
+ * Load an SGML super catalog. It won't expand CATALOG or DELEGATE
2641
+ * references. This is only needed for manipulating SGML Super Catalogs
2642
+ * like adding and removing CATALOG or DELEGATE entries.
2643
+ *
2644
+ * Returns the catalog parsed or NULL in case of error
2645
+ */
2646
+ xmlCatalogPtr
2647
+ xmlLoadSGMLSuperCatalog(const char *filename)
2648
+ {
2649
+ xmlChar *content;
2650
+ xmlCatalogPtr catal;
2651
+ int ret;
2652
+
2653
+ content = xmlLoadFileContent(filename);
2654
+ if (content == NULL)
2655
+ return(NULL);
2656
+
2657
+ catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE, xmlCatalogDefaultPrefer);
2658
+ if (catal == NULL) {
2659
+ xmlFree(content);
2660
+ return(NULL);
2661
+ }
2662
+
2663
+ ret = xmlParseSGMLCatalog(catal, content, filename, 1);
2664
+ xmlFree(content);
2665
+ if (ret < 0) {
2666
+ xmlFreeCatalog(catal);
2667
+ return(NULL);
2668
+ }
2669
+ return (catal);
2670
+ }
2671
+
2672
+ /**
2673
+ * xmlLoadACatalog:
2674
+ * @filename: a file path
2675
+ *
2676
+ * Load the catalog and build the associated data structures.
2677
+ * This can be either an XML Catalog or an SGML Catalog
2678
+ * It will recurse in SGML CATALOG entries. On the other hand XML
2679
+ * Catalogs are not handled recursively.
2680
+ *
2681
+ * Returns the catalog parsed or NULL in case of error
2682
+ */
2683
+ xmlCatalogPtr
2684
+ xmlLoadACatalog(const char *filename)
2685
+ {
2686
+ xmlChar *content;
2687
+ xmlChar *first;
2688
+ xmlCatalogPtr catal;
2689
+ int ret;
2690
+
2691
+ content = xmlLoadFileContent(filename);
2692
+ if (content == NULL)
2693
+ return(NULL);
2694
+
2695
+
2696
+ first = content;
2697
+
2698
+ while ((*first != 0) && (*first != '-') && (*first != '<') &&
2699
+ (!(((*first >= 'A') && (*first <= 'Z')) ||
2700
+ ((*first >= 'a') && (*first <= 'z')))))
2701
+ first++;
2702
+
2703
+ if (*first != '<') {
2704
+ catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE, xmlCatalogDefaultPrefer);
2705
+ if (catal == NULL) {
2706
+ xmlFree(content);
2707
+ return(NULL);
2708
+ }
2709
+ ret = xmlParseSGMLCatalog(catal, content, filename, 0);
2710
+ if (ret < 0) {
2711
+ xmlFreeCatalog(catal);
2712
+ xmlFree(content);
2713
+ return(NULL);
2714
+ }
2715
+ } else {
2716
+ catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE, xmlCatalogDefaultPrefer);
2717
+ if (catal == NULL) {
2718
+ xmlFree(content);
2719
+ return(NULL);
2720
+ }
2721
+ catal->xml = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
2722
+ NULL, BAD_CAST filename, xmlCatalogDefaultPrefer, NULL);
2723
+ }
2724
+ xmlFree(content);
2725
+ return (catal);
2726
+ }
2727
+
2728
+ /**
2729
+ * xmlExpandCatalog:
2730
+ * @catal: a catalog
2731
+ * @filename: a file path
2732
+ *
2733
+ * Load the catalog and expand the existing catal structure.
2734
+ * This can be either an XML Catalog or an SGML Catalog
2735
+ *
2736
+ * Returns 0 in case of success, -1 in case of error
2737
+ */
2738
+ static int
2739
+ xmlExpandCatalog(xmlCatalogPtr catal, const char *filename)
2740
+ {
2741
+ int ret;
2742
+
2743
+ if ((catal == NULL) || (filename == NULL))
2744
+ return(-1);
2745
+
2746
+
2747
+ if (catal->type == XML_SGML_CATALOG_TYPE) {
2748
+ xmlChar *content;
2749
+
2750
+ content = xmlLoadFileContent(filename);
2751
+ if (content == NULL)
2752
+ return(-1);
2753
+
2754
+ ret = xmlParseSGMLCatalog(catal, content, filename, 0);
2755
+ if (ret < 0) {
2756
+ xmlFree(content);
2757
+ return(-1);
2758
+ }
2759
+ xmlFree(content);
2760
+ } else {
2761
+ xmlCatalogEntryPtr tmp, cur;
2762
+ tmp = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
2763
+ NULL, BAD_CAST filename, xmlCatalogDefaultPrefer, NULL);
2764
+
2765
+ cur = catal->xml;
2766
+ if (cur == NULL) {
2767
+ catal->xml = tmp;
2768
+ } else {
2769
+ while (cur->next != NULL) cur = cur->next;
2770
+ cur->next = tmp;
2771
+ }
2772
+ }
2773
+ return (0);
2774
+ }
2775
+
2776
+ /**
2777
+ * xmlACatalogResolveSystem:
2778
+ * @catal: a Catalog
2779
+ * @sysID: the system ID string
2780
+ *
2781
+ * Try to lookup the catalog resource for a system ID
2782
+ *
2783
+ * Returns the resource if found or NULL otherwise, the value returned
2784
+ * must be freed by the caller.
2785
+ */
2786
+ xmlChar *
2787
+ xmlACatalogResolveSystem(xmlCatalogPtr catal, const xmlChar *sysID) {
2788
+ xmlChar *ret = NULL;
2789
+
2790
+ if ((sysID == NULL) || (catal == NULL))
2791
+ return(NULL);
2792
+
2793
+ if (xmlDebugCatalogs)
2794
+ xmlGenericError(xmlGenericErrorContext,
2795
+ "Resolve sysID %s\n", sysID);
2796
+
2797
+ if (catal->type == XML_XML_CATALOG_TYPE) {
2798
+ ret = xmlCatalogListXMLResolve(catal->xml, NULL, sysID);
2799
+ if (ret == XML_CATAL_BREAK)
2800
+ ret = NULL;
2801
+ } else {
2802
+ const xmlChar *sgml;
2803
+
2804
+ sgml = xmlCatalogGetSGMLSystem(catal->sgml, sysID);
2805
+ if (sgml != NULL)
2806
+ ret = xmlStrdup(sgml);
2807
+ }
2808
+ return(ret);
2809
+ }
2810
+
2811
+ /**
2812
+ * xmlACatalogResolvePublic:
2813
+ * @catal: a Catalog
2814
+ * @pubID: the public ID string
2815
+ *
2816
+ * Try to lookup the catalog local reference associated to a public ID in that catalog
2817
+ *
2818
+ * Returns the local resource if found or NULL otherwise, the value returned
2819
+ * must be freed by the caller.
2820
+ */
2821
+ xmlChar *
2822
+ xmlACatalogResolvePublic(xmlCatalogPtr catal, const xmlChar *pubID) {
2823
+ xmlChar *ret = NULL;
2824
+
2825
+ if ((pubID == NULL) || (catal == NULL))
2826
+ return(NULL);
2827
+
2828
+ if (xmlDebugCatalogs)
2829
+ xmlGenericError(xmlGenericErrorContext,
2830
+ "Resolve pubID %s\n", pubID);
2831
+
2832
+ if (catal->type == XML_XML_CATALOG_TYPE) {
2833
+ ret = xmlCatalogListXMLResolve(catal->xml, pubID, NULL);
2834
+ if (ret == XML_CATAL_BREAK)
2835
+ ret = NULL;
2836
+ } else {
2837
+ const xmlChar *sgml;
2838
+
2839
+ sgml = xmlCatalogGetSGMLPublic(catal->sgml, pubID);
2840
+ if (sgml != NULL)
2841
+ ret = xmlStrdup(sgml);
2842
+ }
2843
+ return(ret);
2844
+ }
2845
+
2846
+ /**
2847
+ * xmlACatalogResolve:
2848
+ * @catal: a Catalog
2849
+ * @pubID: the public ID string
2850
+ * @sysID: the system ID string
2851
+ *
2852
+ * Do a complete resolution lookup of an External Identifier
2853
+ *
2854
+ * Returns the URI of the resource or NULL if not found, it must be freed
2855
+ * by the caller.
2856
+ */
2857
+ xmlChar *
2858
+ xmlACatalogResolve(xmlCatalogPtr catal, const xmlChar * pubID,
2859
+ const xmlChar * sysID)
2860
+ {
2861
+ xmlChar *ret = NULL;
2862
+
2863
+ if (((pubID == NULL) && (sysID == NULL)) || (catal == NULL))
2864
+ return (NULL);
2865
+
2866
+ if (xmlDebugCatalogs) {
2867
+ if ((pubID != NULL) && (sysID != NULL)) {
2868
+ xmlGenericError(xmlGenericErrorContext,
2869
+ "Resolve: pubID %s sysID %s\n", pubID, sysID);
2870
+ } else if (pubID != NULL) {
2871
+ xmlGenericError(xmlGenericErrorContext,
2872
+ "Resolve: pubID %s\n", pubID);
2873
+ } else {
2874
+ xmlGenericError(xmlGenericErrorContext,
2875
+ "Resolve: sysID %s\n", sysID);
2876
+ }
2877
+ }
2878
+
2879
+ if (catal->type == XML_XML_CATALOG_TYPE) {
2880
+ ret = xmlCatalogListXMLResolve(catal->xml, pubID, sysID);
2881
+ if (ret == XML_CATAL_BREAK)
2882
+ ret = NULL;
2883
+ } else {
2884
+ const xmlChar *sgml;
2885
+
2886
+ sgml = xmlCatalogSGMLResolve(catal, pubID, sysID);
2887
+ if (sgml != NULL)
2888
+ ret = xmlStrdup(sgml);
2889
+ }
2890
+ return (ret);
2891
+ }
2892
+
2893
+ /**
2894
+ * xmlACatalogResolveURI:
2895
+ * @catal: a Catalog
2896
+ * @URI: the URI
2897
+ *
2898
+ * Do a complete resolution lookup of an URI
2899
+ *
2900
+ * Returns the URI of the resource or NULL if not found, it must be freed
2901
+ * by the caller.
2902
+ */
2903
+ xmlChar *
2904
+ xmlACatalogResolveURI(xmlCatalogPtr catal, const xmlChar *URI) {
2905
+ xmlChar *ret = NULL;
2906
+
2907
+ if ((URI == NULL) || (catal == NULL))
2908
+ return(NULL);
2909
+
2910
+ if (xmlDebugCatalogs)
2911
+ xmlGenericError(xmlGenericErrorContext,
2912
+ "Resolve URI %s\n", URI);
2913
+
2914
+ if (catal->type == XML_XML_CATALOG_TYPE) {
2915
+ ret = xmlCatalogListXMLResolveURI(catal->xml, URI);
2916
+ if (ret == XML_CATAL_BREAK)
2917
+ ret = NULL;
2918
+ } else {
2919
+ const xmlChar *sgml;
2920
+
2921
+ sgml = xmlCatalogSGMLResolve(catal, NULL, URI);
2922
+ if (sgml != NULL)
2923
+ ret = xmlStrdup(sgml);
2924
+ }
2925
+ return(ret);
2926
+ }
2927
+
2928
+ #ifdef LIBXML_OUTPUT_ENABLED
2929
+ /**
2930
+ * xmlACatalogDump:
2931
+ * @catal: a Catalog
2932
+ * @out: the file.
2933
+ *
2934
+ * Dump the given catalog to the given file.
2935
+ */
2936
+ void
2937
+ xmlACatalogDump(xmlCatalogPtr catal, FILE *out) {
2938
+ if ((out == NULL) || (catal == NULL))
2939
+ return;
2940
+
2941
+ if (catal->type == XML_XML_CATALOG_TYPE) {
2942
+ xmlDumpXMLCatalog(out, catal->xml);
2943
+ } else {
2944
+ xmlHashScan(catal->sgml, xmlCatalogDumpEntry, out);
2945
+ }
2946
+ }
2947
+ #endif /* LIBXML_OUTPUT_ENABLED */
2948
+
2949
+ /**
2950
+ * xmlACatalogAdd:
2951
+ * @catal: a Catalog
2952
+ * @type: the type of record to add to the catalog
2953
+ * @orig: the system, public or prefix to match
2954
+ * @replace: the replacement value for the match
2955
+ *
2956
+ * Add an entry in the catalog, it may overwrite existing but
2957
+ * different entries.
2958
+ *
2959
+ * Returns 0 if successful, -1 otherwise
2960
+ */
2961
+ int
2962
+ xmlACatalogAdd(xmlCatalogPtr catal, const xmlChar * type,
2963
+ const xmlChar * orig, const xmlChar * replace)
2964
+ {
2965
+ int res = -1;
2966
+
2967
+ if (catal == NULL)
2968
+ return(-1);
2969
+
2970
+ if (catal->type == XML_XML_CATALOG_TYPE) {
2971
+ res = xmlAddXMLCatalog(catal->xml, type, orig, replace);
2972
+ } else {
2973
+ xmlCatalogEntryType cattype;
2974
+
2975
+ cattype = xmlGetSGMLCatalogEntryType(type);
2976
+ if (cattype != XML_CATA_NONE) {
2977
+ xmlCatalogEntryPtr entry;
2978
+
2979
+ entry = xmlNewCatalogEntry(cattype, orig, replace, NULL,
2980
+ XML_CATA_PREFER_NONE, NULL);
2981
+ if (catal->sgml == NULL)
2982
+ catal->sgml = xmlHashCreate(10);
2983
+ res = xmlHashAddEntry(catal->sgml, orig, entry);
2984
+ }
2985
+ }
2986
+ return (res);
2987
+ }
2988
+
2989
+ /**
2990
+ * xmlACatalogRemove:
2991
+ * @catal: a Catalog
2992
+ * @value: the value to remove
2993
+ *
2994
+ * Remove an entry from the catalog
2995
+ *
2996
+ * Returns the number of entries removed if successful, -1 otherwise
2997
+ */
2998
+ int
2999
+ xmlACatalogRemove(xmlCatalogPtr catal, const xmlChar *value) {
3000
+ int res = -1;
3001
+
3002
+ if ((catal == NULL) || (value == NULL))
3003
+ return(-1);
3004
+
3005
+ if (catal->type == XML_XML_CATALOG_TYPE) {
3006
+ res = xmlDelXMLCatalog(catal->xml, value);
3007
+ } else {
3008
+ res = xmlHashRemoveEntry(catal->sgml, value, xmlFreeCatalogEntry);
3009
+ if (res == 0)
3010
+ res = 1;
3011
+ }
3012
+ return(res);
3013
+ }
3014
+
3015
+ /**
3016
+ * xmlNewCatalog:
3017
+ * @sgml: should this create an SGML catalog
3018
+ *
3019
+ * create a new Catalog.
3020
+ *
3021
+ * Returns the xmlCatalogPtr or NULL in case of error
3022
+ */
3023
+ xmlCatalogPtr
3024
+ xmlNewCatalog(int sgml) {
3025
+ xmlCatalogPtr catal = NULL;
3026
+
3027
+ if (sgml) {
3028
+ catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE,
3029
+ xmlCatalogDefaultPrefer);
3030
+ if ((catal != NULL) && (catal->sgml == NULL))
3031
+ catal->sgml = xmlHashCreate(10);
3032
+ } else
3033
+ catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE,
3034
+ xmlCatalogDefaultPrefer);
3035
+ return(catal);
3036
+ }
3037
+
3038
+ /**
3039
+ * xmlCatalogIsEmpty:
3040
+ * @catal: should this create an SGML catalog
3041
+ *
3042
+ * Check is a catalog is empty
3043
+ *
3044
+ * Returns 1 if the catalog is empty, 0 if not, amd -1 in case of error.
3045
+ */
3046
+ int
3047
+ xmlCatalogIsEmpty(xmlCatalogPtr catal) {
3048
+ if (catal == NULL)
3049
+ return(-1);
3050
+
3051
+ if (catal->type == XML_XML_CATALOG_TYPE) {
3052
+ if (catal->xml == NULL)
3053
+ return(1);
3054
+ if ((catal->xml->type != XML_CATA_CATALOG) &&
3055
+ (catal->xml->type != XML_CATA_BROKEN_CATALOG))
3056
+ return(-1);
3057
+ if (catal->xml->children == NULL)
3058
+ return(1);
3059
+ return(0);
3060
+ } else {
3061
+ int res;
3062
+
3063
+ if (catal->sgml == NULL)
3064
+ return(1);
3065
+ res = xmlHashSize(catal->sgml);
3066
+ if (res == 0)
3067
+ return(1);
3068
+ if (res < 0)
3069
+ return(-1);
3070
+ }
3071
+ return(0);
3072
+ }
3073
+
3074
+ /************************************************************************
3075
+ * *
3076
+ * Public interfaces manipulating the global shared default catalog *
3077
+ * *
3078
+ ************************************************************************/
3079
+
3080
+ /**
3081
+ * xmlInitializeCatalogData:
3082
+ *
3083
+ * Do the catalog initialization only of global data, doesn't try to load
3084
+ * any catalog actually.
3085
+ * this function is not thread safe, catalog initialization should
3086
+ * preferably be done once at startup
3087
+ */
3088
+ static void
3089
+ xmlInitializeCatalogData(void) {
3090
+ if (xmlCatalogInitialized != 0)
3091
+ return;
3092
+
3093
+ if (getenv("XML_DEBUG_CATALOG"))
3094
+ xmlDebugCatalogs = 1;
3095
+ xmlCatalogMutex = xmlNewRMutex();
3096
+
3097
+ xmlCatalogInitialized = 1;
3098
+ }
3099
+ /**
3100
+ * xmlInitializeCatalog:
3101
+ *
3102
+ * Do the catalog initialization.
3103
+ * this function is not thread safe, catalog initialization should
3104
+ * preferably be done once at startup
3105
+ */
3106
+ void
3107
+ xmlInitializeCatalog(void) {
3108
+ if (xmlCatalogInitialized != 0)
3109
+ return;
3110
+
3111
+ xmlInitializeCatalogData();
3112
+ xmlRMutexLock(xmlCatalogMutex);
3113
+
3114
+ if (getenv("XML_DEBUG_CATALOG"))
3115
+ xmlDebugCatalogs = 1;
3116
+
3117
+ if (xmlDefaultCatalog == NULL) {
3118
+ const char *catalogs;
3119
+ char *path;
3120
+ const char *cur, *paths;
3121
+ xmlCatalogPtr catal;
3122
+ xmlCatalogEntryPtr *nextent;
3123
+
3124
+ catalogs = (const char *) getenv("XML_CATALOG_FILES");
3125
+ if (catalogs == NULL)
3126
+ #if defined(_WIN32) && defined(_MSC_VER)
3127
+ {
3128
+ void* hmodule;
3129
+ hmodule = GetModuleHandleA("libxml2.dll");
3130
+ if (hmodule == NULL)
3131
+ hmodule = GetModuleHandleA(NULL);
3132
+ if (hmodule != NULL) {
3133
+ char buf[256];
3134
+ unsigned long len = GetModuleFileNameA(hmodule, buf, 255);
3135
+ if (len != 0) {
3136
+ char* p = &(buf[len]);
3137
+ while (*p != '\\' && p > buf)
3138
+ p--;
3139
+ if (p != buf) {
3140
+ xmlChar* uri;
3141
+ strncpy(p, "\\..\\etc\\catalog", 255 - (p - buf));
3142
+ uri = xmlCanonicPath((const xmlChar*)buf);
3143
+ if (uri != NULL) {
3144
+ strncpy(XML_XML_DEFAULT_CATALOG, uri, 255);
3145
+ xmlFree(uri);
3146
+ }
3147
+ }
3148
+ }
3149
+ }
3150
+ catalogs = XML_XML_DEFAULT_CATALOG;
3151
+ }
3152
+ #else
3153
+ catalogs = XML_XML_DEFAULT_CATALOG;
3154
+ #endif
3155
+
3156
+ catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE,
3157
+ xmlCatalogDefaultPrefer);
3158
+ if (catal != NULL) {
3159
+ /* the XML_CATALOG_FILES envvar is allowed to contain a
3160
+ space-separated list of entries. */
3161
+ cur = catalogs;
3162
+ nextent = &catal->xml;
3163
+ while (*cur != '\0') {
3164
+ while (xmlIsBlank_ch(*cur))
3165
+ cur++;
3166
+ if (*cur != 0) {
3167
+ paths = cur;
3168
+ while ((*cur != 0) && (!xmlIsBlank_ch(*cur)))
3169
+ cur++;
3170
+ path = (char *) xmlStrndup((const xmlChar *)paths, cur - paths);
3171
+ if (path != NULL) {
3172
+ *nextent = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
3173
+ NULL, BAD_CAST path, xmlCatalogDefaultPrefer, NULL);
3174
+ if (*nextent != NULL)
3175
+ nextent = &((*nextent)->next);
3176
+ xmlFree(path);
3177
+ }
3178
+ }
3179
+ }
3180
+ xmlDefaultCatalog = catal;
3181
+ }
3182
+ }
3183
+
3184
+ xmlRMutexUnlock(xmlCatalogMutex);
3185
+ }
3186
+
3187
+
3188
+ /**
3189
+ * xmlLoadCatalog:
3190
+ * @filename: a file path
3191
+ *
3192
+ * Load the catalog and makes its definitions effective for the default
3193
+ * external entity loader. It will recurse in SGML CATALOG entries.
3194
+ * this function is not thread safe, catalog initialization should
3195
+ * preferably be done once at startup
3196
+ *
3197
+ * Returns 0 in case of success -1 in case of error
3198
+ */
3199
+ int
3200
+ xmlLoadCatalog(const char *filename)
3201
+ {
3202
+ int ret;
3203
+ xmlCatalogPtr catal;
3204
+
3205
+ if (!xmlCatalogInitialized)
3206
+ xmlInitializeCatalogData();
3207
+
3208
+ xmlRMutexLock(xmlCatalogMutex);
3209
+
3210
+ if (xmlDefaultCatalog == NULL) {
3211
+ catal = xmlLoadACatalog(filename);
3212
+ if (catal == NULL) {
3213
+ xmlRMutexUnlock(xmlCatalogMutex);
3214
+ return(-1);
3215
+ }
3216
+
3217
+ xmlDefaultCatalog = catal;
3218
+ xmlRMutexUnlock(xmlCatalogMutex);
3219
+ return(0);
3220
+ }
3221
+
3222
+ ret = xmlExpandCatalog(xmlDefaultCatalog, filename);
3223
+ xmlRMutexUnlock(xmlCatalogMutex);
3224
+ return(ret);
3225
+ }
3226
+
3227
+ /**
3228
+ * xmlLoadCatalogs:
3229
+ * @pathss: a list of directories separated by a colon or a space.
3230
+ *
3231
+ * Load the catalogs and makes their definitions effective for the default
3232
+ * external entity loader.
3233
+ * this function is not thread safe, catalog initialization should
3234
+ * preferably be done once at startup
3235
+ */
3236
+ void
3237
+ xmlLoadCatalogs(const char *pathss) {
3238
+ const char *cur;
3239
+ const char *paths;
3240
+ xmlChar *path;
3241
+ #ifdef _WIN32
3242
+ int i, iLen;
3243
+ #endif
3244
+
3245
+ if (pathss == NULL)
3246
+ return;
3247
+
3248
+ cur = pathss;
3249
+ while (*cur != 0) {
3250
+ while (xmlIsBlank_ch(*cur)) cur++;
3251
+ if (*cur != 0) {
3252
+ paths = cur;
3253
+ while ((*cur != 0) && (*cur != PATH_SEPARATOR) && (!xmlIsBlank_ch(*cur)))
3254
+ cur++;
3255
+ path = xmlStrndup((const xmlChar *)paths, cur - paths);
3256
+ if (path != NULL) {
3257
+ #ifdef _WIN32
3258
+ iLen = strlen((const char*)path);
3259
+ for(i = 0; i < iLen; i++) {
3260
+ if(path[i] == '\\') {
3261
+ path[i] = '/';
3262
+ }
3263
+ }
3264
+ #endif
3265
+ xmlLoadCatalog((const char *) path);
3266
+ xmlFree(path);
3267
+ }
3268
+ }
3269
+ while (*cur == PATH_SEPARATOR)
3270
+ cur++;
3271
+ }
3272
+ }
3273
+
3274
+ /**
3275
+ * xmlCatalogCleanup:
3276
+ *
3277
+ * Free up all the memory associated with catalogs
3278
+ */
3279
+ void
3280
+ xmlCatalogCleanup(void) {
3281
+ if (xmlCatalogInitialized == 0)
3282
+ return;
3283
+
3284
+ xmlRMutexLock(xmlCatalogMutex);
3285
+ if (xmlDebugCatalogs)
3286
+ xmlGenericError(xmlGenericErrorContext,
3287
+ "Catalogs cleanup\n");
3288
+ if (xmlCatalogXMLFiles != NULL)
3289
+ xmlHashFree(xmlCatalogXMLFiles, xmlFreeCatalogHashEntryList);
3290
+ xmlCatalogXMLFiles = NULL;
3291
+ if (xmlDefaultCatalog != NULL)
3292
+ xmlFreeCatalog(xmlDefaultCatalog);
3293
+ xmlDefaultCatalog = NULL;
3294
+ xmlDebugCatalogs = 0;
3295
+ xmlCatalogInitialized = 0;
3296
+ xmlRMutexUnlock(xmlCatalogMutex);
3297
+ xmlFreeRMutex(xmlCatalogMutex);
3298
+ }
3299
+
3300
+ /**
3301
+ * xmlCatalogResolveSystem:
3302
+ * @sysID: the system ID string
3303
+ *
3304
+ * Try to lookup the catalog resource for a system ID
3305
+ *
3306
+ * Returns the resource if found or NULL otherwise, the value returned
3307
+ * must be freed by the caller.
3308
+ */
3309
+ xmlChar *
3310
+ xmlCatalogResolveSystem(const xmlChar *sysID) {
3311
+ xmlChar *ret;
3312
+
3313
+ if (!xmlCatalogInitialized)
3314
+ xmlInitializeCatalog();
3315
+
3316
+ ret = xmlACatalogResolveSystem(xmlDefaultCatalog, sysID);
3317
+ return(ret);
3318
+ }
3319
+
3320
+ /**
3321
+ * xmlCatalogResolvePublic:
3322
+ * @pubID: the public ID string
3323
+ *
3324
+ * Try to lookup the catalog reference associated to a public ID
3325
+ *
3326
+ * Returns the resource if found or NULL otherwise, the value returned
3327
+ * must be freed by the caller.
3328
+ */
3329
+ xmlChar *
3330
+ xmlCatalogResolvePublic(const xmlChar *pubID) {
3331
+ xmlChar *ret;
3332
+
3333
+ if (!xmlCatalogInitialized)
3334
+ xmlInitializeCatalog();
3335
+
3336
+ ret = xmlACatalogResolvePublic(xmlDefaultCatalog, pubID);
3337
+ return(ret);
3338
+ }
3339
+
3340
+ /**
3341
+ * xmlCatalogResolve:
3342
+ * @pubID: the public ID string
3343
+ * @sysID: the system ID string
3344
+ *
3345
+ * Do a complete resolution lookup of an External Identifier
3346
+ *
3347
+ * Returns the URI of the resource or NULL if not found, it must be freed
3348
+ * by the caller.
3349
+ */
3350
+ xmlChar *
3351
+ xmlCatalogResolve(const xmlChar *pubID, const xmlChar *sysID) {
3352
+ xmlChar *ret;
3353
+
3354
+ if (!xmlCatalogInitialized)
3355
+ xmlInitializeCatalog();
3356
+
3357
+ ret = xmlACatalogResolve(xmlDefaultCatalog, pubID, sysID);
3358
+ return(ret);
3359
+ }
3360
+
3361
+ /**
3362
+ * xmlCatalogResolveURI:
3363
+ * @URI: the URI
3364
+ *
3365
+ * Do a complete resolution lookup of an URI
3366
+ *
3367
+ * Returns the URI of the resource or NULL if not found, it must be freed
3368
+ * by the caller.
3369
+ */
3370
+ xmlChar *
3371
+ xmlCatalogResolveURI(const xmlChar *URI) {
3372
+ xmlChar *ret;
3373
+
3374
+ if (!xmlCatalogInitialized)
3375
+ xmlInitializeCatalog();
3376
+
3377
+ ret = xmlACatalogResolveURI(xmlDefaultCatalog, URI);
3378
+ return(ret);
3379
+ }
3380
+
3381
+ #ifdef LIBXML_OUTPUT_ENABLED
3382
+ /**
3383
+ * xmlCatalogDump:
3384
+ * @out: the file.
3385
+ *
3386
+ * Dump all the global catalog content to the given file.
3387
+ */
3388
+ void
3389
+ xmlCatalogDump(FILE *out) {
3390
+ if (out == NULL)
3391
+ return;
3392
+
3393
+ if (!xmlCatalogInitialized)
3394
+ xmlInitializeCatalog();
3395
+
3396
+ xmlACatalogDump(xmlDefaultCatalog, out);
3397
+ }
3398
+ #endif /* LIBXML_OUTPUT_ENABLED */
3399
+
3400
+ /**
3401
+ * xmlCatalogAdd:
3402
+ * @type: the type of record to add to the catalog
3403
+ * @orig: the system, public or prefix to match
3404
+ * @replace: the replacement value for the match
3405
+ *
3406
+ * Add an entry in the catalog, it may overwrite existing but
3407
+ * different entries.
3408
+ * If called before any other catalog routine, allows to override the
3409
+ * default shared catalog put in place by xmlInitializeCatalog();
3410
+ *
3411
+ * Returns 0 if successful, -1 otherwise
3412
+ */
3413
+ int
3414
+ xmlCatalogAdd(const xmlChar *type, const xmlChar *orig, const xmlChar *replace) {
3415
+ int res = -1;
3416
+
3417
+ if (!xmlCatalogInitialized)
3418
+ xmlInitializeCatalogData();
3419
+
3420
+ xmlRMutexLock(xmlCatalogMutex);
3421
+ /*
3422
+ * Specific case where one want to override the default catalog
3423
+ * put in place by xmlInitializeCatalog();
3424
+ */
3425
+ if ((xmlDefaultCatalog == NULL) &&
3426
+ (xmlStrEqual(type, BAD_CAST "catalog"))) {
3427
+ xmlDefaultCatalog = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE,
3428
+ xmlCatalogDefaultPrefer);
3429
+ if (xmlDefaultCatalog != NULL) {
3430
+ xmlDefaultCatalog->xml = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
3431
+ orig, NULL, xmlCatalogDefaultPrefer, NULL);
3432
+ }
3433
+ xmlRMutexUnlock(xmlCatalogMutex);
3434
+ return(0);
3435
+ }
3436
+
3437
+ res = xmlACatalogAdd(xmlDefaultCatalog, type, orig, replace);
3438
+ xmlRMutexUnlock(xmlCatalogMutex);
3439
+ return(res);
3440
+ }
3441
+
3442
+ /**
3443
+ * xmlCatalogRemove:
3444
+ * @value: the value to remove
3445
+ *
3446
+ * Remove an entry from the catalog
3447
+ *
3448
+ * Returns the number of entries removed if successful, -1 otherwise
3449
+ */
3450
+ int
3451
+ xmlCatalogRemove(const xmlChar *value) {
3452
+ int res;
3453
+
3454
+ if (!xmlCatalogInitialized)
3455
+ xmlInitializeCatalog();
3456
+
3457
+ xmlRMutexLock(xmlCatalogMutex);
3458
+ res = xmlACatalogRemove(xmlDefaultCatalog, value);
3459
+ xmlRMutexUnlock(xmlCatalogMutex);
3460
+ return(res);
3461
+ }
3462
+
3463
+ /**
3464
+ * xmlCatalogConvert:
3465
+ *
3466
+ * Convert all the SGML catalog entries as XML ones
3467
+ *
3468
+ * Returns the number of entries converted if successful, -1 otherwise
3469
+ */
3470
+ int
3471
+ xmlCatalogConvert(void) {
3472
+ int res = -1;
3473
+
3474
+ if (!xmlCatalogInitialized)
3475
+ xmlInitializeCatalog();
3476
+
3477
+ xmlRMutexLock(xmlCatalogMutex);
3478
+ res = xmlConvertSGMLCatalog(xmlDefaultCatalog);
3479
+ xmlRMutexUnlock(xmlCatalogMutex);
3480
+ return(res);
3481
+ }
3482
+
3483
+ /************************************************************************
3484
+ * *
3485
+ * Public interface manipulating the common preferences *
3486
+ * *
3487
+ ************************************************************************/
3488
+
3489
+ /**
3490
+ * xmlCatalogGetDefaults:
3491
+ *
3492
+ * Used to get the user preference w.r.t. to what catalogs should
3493
+ * be accepted
3494
+ *
3495
+ * Returns the current xmlCatalogAllow value
3496
+ */
3497
+ xmlCatalogAllow
3498
+ xmlCatalogGetDefaults(void) {
3499
+ return(xmlCatalogDefaultAllow);
3500
+ }
3501
+
3502
+ /**
3503
+ * xmlCatalogSetDefaults:
3504
+ * @allow: what catalogs should be accepted
3505
+ *
3506
+ * Used to set the user preference w.r.t. to what catalogs should
3507
+ * be accepted
3508
+ */
3509
+ void
3510
+ xmlCatalogSetDefaults(xmlCatalogAllow allow) {
3511
+ if (xmlDebugCatalogs) {
3512
+ switch (allow) {
3513
+ case XML_CATA_ALLOW_NONE:
3514
+ xmlGenericError(xmlGenericErrorContext,
3515
+ "Disabling catalog usage\n");
3516
+ break;
3517
+ case XML_CATA_ALLOW_GLOBAL:
3518
+ xmlGenericError(xmlGenericErrorContext,
3519
+ "Allowing only global catalogs\n");
3520
+ break;
3521
+ case XML_CATA_ALLOW_DOCUMENT:
3522
+ xmlGenericError(xmlGenericErrorContext,
3523
+ "Allowing only catalogs from the document\n");
3524
+ break;
3525
+ case XML_CATA_ALLOW_ALL:
3526
+ xmlGenericError(xmlGenericErrorContext,
3527
+ "Allowing all catalogs\n");
3528
+ break;
3529
+ }
3530
+ }
3531
+ xmlCatalogDefaultAllow = allow;
3532
+ }
3533
+
3534
+ /**
3535
+ * xmlCatalogSetDefaultPrefer:
3536
+ * @prefer: the default preference for delegation
3537
+ *
3538
+ * Allows to set the preference between public and system for deletion
3539
+ * in XML Catalog resolution. C.f. section 4.1.1 of the spec
3540
+ * Values accepted are XML_CATA_PREFER_PUBLIC or XML_CATA_PREFER_SYSTEM
3541
+ *
3542
+ * Returns the previous value of the default preference for delegation
3543
+ */
3544
+ xmlCatalogPrefer
3545
+ xmlCatalogSetDefaultPrefer(xmlCatalogPrefer prefer) {
3546
+ xmlCatalogPrefer ret = xmlCatalogDefaultPrefer;
3547
+
3548
+ if (prefer == XML_CATA_PREFER_NONE)
3549
+ return(ret);
3550
+
3551
+ if (xmlDebugCatalogs) {
3552
+ switch (prefer) {
3553
+ case XML_CATA_PREFER_PUBLIC:
3554
+ xmlGenericError(xmlGenericErrorContext,
3555
+ "Setting catalog preference to PUBLIC\n");
3556
+ break;
3557
+ case XML_CATA_PREFER_SYSTEM:
3558
+ xmlGenericError(xmlGenericErrorContext,
3559
+ "Setting catalog preference to SYSTEM\n");
3560
+ break;
3561
+ default:
3562
+ return(ret);
3563
+ }
3564
+ }
3565
+ xmlCatalogDefaultPrefer = prefer;
3566
+ return(ret);
3567
+ }
3568
+
3569
+ /**
3570
+ * xmlCatalogSetDebug:
3571
+ * @level: the debug level of catalogs required
3572
+ *
3573
+ * Used to set the debug level for catalog operation, 0 disable
3574
+ * debugging, 1 enable it
3575
+ *
3576
+ * Returns the previous value of the catalog debugging level
3577
+ */
3578
+ int
3579
+ xmlCatalogSetDebug(int level) {
3580
+ int ret = xmlDebugCatalogs;
3581
+
3582
+ if (level <= 0)
3583
+ xmlDebugCatalogs = 0;
3584
+ else
3585
+ xmlDebugCatalogs = level;
3586
+ return(ret);
3587
+ }
3588
+
3589
+ /************************************************************************
3590
+ * *
3591
+ * Minimal interfaces used for per-document catalogs by the parser *
3592
+ * *
3593
+ ************************************************************************/
3594
+
3595
+ /**
3596
+ * xmlCatalogFreeLocal:
3597
+ * @catalogs: a document's list of catalogs
3598
+ *
3599
+ * Free up the memory associated to the catalog list
3600
+ */
3601
+ void
3602
+ xmlCatalogFreeLocal(void *catalogs) {
3603
+ xmlCatalogEntryPtr catal;
3604
+
3605
+ if (!xmlCatalogInitialized)
3606
+ xmlInitializeCatalog();
3607
+
3608
+ catal = (xmlCatalogEntryPtr) catalogs;
3609
+ if (catal != NULL)
3610
+ xmlFreeCatalogEntryList(catal);
3611
+ }
3612
+
3613
+
3614
+ /**
3615
+ * xmlCatalogAddLocal:
3616
+ * @catalogs: a document's list of catalogs
3617
+ * @URL: the URL to a new local catalog
3618
+ *
3619
+ * Add the new entry to the catalog list
3620
+ *
3621
+ * Returns the updated list
3622
+ */
3623
+ void *
3624
+ xmlCatalogAddLocal(void *catalogs, const xmlChar *URL) {
3625
+ xmlCatalogEntryPtr catal, add;
3626
+
3627
+ if (!xmlCatalogInitialized)
3628
+ xmlInitializeCatalog();
3629
+
3630
+ if (URL == NULL)
3631
+ return(catalogs);
3632
+
3633
+ if (xmlDebugCatalogs)
3634
+ xmlGenericError(xmlGenericErrorContext,
3635
+ "Adding document catalog %s\n", URL);
3636
+
3637
+ add = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, URL, NULL,
3638
+ xmlCatalogDefaultPrefer, NULL);
3639
+ if (add == NULL)
3640
+ return(catalogs);
3641
+
3642
+ catal = (xmlCatalogEntryPtr) catalogs;
3643
+ if (catal == NULL)
3644
+ return((void *) add);
3645
+
3646
+ while (catal->next != NULL)
3647
+ catal = catal->next;
3648
+ catal->next = add;
3649
+ return(catalogs);
3650
+ }
3651
+
3652
+ /**
3653
+ * xmlCatalogLocalResolve:
3654
+ * @catalogs: a document's list of catalogs
3655
+ * @pubID: the public ID string
3656
+ * @sysID: the system ID string
3657
+ *
3658
+ * Do a complete resolution lookup of an External Identifier using a
3659
+ * document's private catalog list
3660
+ *
3661
+ * Returns the URI of the resource or NULL if not found, it must be freed
3662
+ * by the caller.
3663
+ */
3664
+ xmlChar *
3665
+ xmlCatalogLocalResolve(void *catalogs, const xmlChar *pubID,
3666
+ const xmlChar *sysID) {
3667
+ xmlCatalogEntryPtr catal;
3668
+ xmlChar *ret;
3669
+
3670
+ if (!xmlCatalogInitialized)
3671
+ xmlInitializeCatalog();
3672
+
3673
+ if ((pubID == NULL) && (sysID == NULL))
3674
+ return(NULL);
3675
+
3676
+ if (xmlDebugCatalogs) {
3677
+ if ((pubID != NULL) && (sysID != NULL)) {
3678
+ xmlGenericError(xmlGenericErrorContext,
3679
+ "Local Resolve: pubID %s sysID %s\n", pubID, sysID);
3680
+ } else if (pubID != NULL) {
3681
+ xmlGenericError(xmlGenericErrorContext,
3682
+ "Local Resolve: pubID %s\n", pubID);
3683
+ } else {
3684
+ xmlGenericError(xmlGenericErrorContext,
3685
+ "Local Resolve: sysID %s\n", sysID);
3686
+ }
3687
+ }
3688
+
3689
+ catal = (xmlCatalogEntryPtr) catalogs;
3690
+ if (catal == NULL)
3691
+ return(NULL);
3692
+ ret = xmlCatalogListXMLResolve(catal, pubID, sysID);
3693
+ if ((ret != NULL) && (ret != XML_CATAL_BREAK))
3694
+ return(ret);
3695
+ return(NULL);
3696
+ }
3697
+
3698
+ /**
3699
+ * xmlCatalogLocalResolveURI:
3700
+ * @catalogs: a document's list of catalogs
3701
+ * @URI: the URI
3702
+ *
3703
+ * Do a complete resolution lookup of an URI using a
3704
+ * document's private catalog list
3705
+ *
3706
+ * Returns the URI of the resource or NULL if not found, it must be freed
3707
+ * by the caller.
3708
+ */
3709
+ xmlChar *
3710
+ xmlCatalogLocalResolveURI(void *catalogs, const xmlChar *URI) {
3711
+ xmlCatalogEntryPtr catal;
3712
+ xmlChar *ret;
3713
+
3714
+ if (!xmlCatalogInitialized)
3715
+ xmlInitializeCatalog();
3716
+
3717
+ if (URI == NULL)
3718
+ return(NULL);
3719
+
3720
+ if (xmlDebugCatalogs)
3721
+ xmlGenericError(xmlGenericErrorContext,
3722
+ "Resolve URI %s\n", URI);
3723
+
3724
+ catal = (xmlCatalogEntryPtr) catalogs;
3725
+ if (catal == NULL)
3726
+ return(NULL);
3727
+ ret = xmlCatalogListXMLResolveURI(catal, URI);
3728
+ if ((ret != NULL) && (ret != XML_CATAL_BREAK))
3729
+ return(ret);
3730
+ return(NULL);
3731
+ }
3732
+
3733
+ /************************************************************************
3734
+ * *
3735
+ * Deprecated interfaces *
3736
+ * *
3737
+ ************************************************************************/
3738
+ /**
3739
+ * xmlCatalogGetSystem:
3740
+ * @sysID: the system ID string
3741
+ *
3742
+ * Try to lookup the catalog reference associated to a system ID
3743
+ * DEPRECATED, use xmlCatalogResolveSystem()
3744
+ *
3745
+ * Returns the resource if found or NULL otherwise.
3746
+ */
3747
+ const xmlChar *
3748
+ xmlCatalogGetSystem(const xmlChar *sysID) {
3749
+ xmlChar *ret;
3750
+ static xmlChar result[1000];
3751
+ static int msg = 0;
3752
+
3753
+ if (!xmlCatalogInitialized)
3754
+ xmlInitializeCatalog();
3755
+
3756
+ if (msg == 0) {
3757
+ xmlGenericError(xmlGenericErrorContext,
3758
+ "Use of deprecated xmlCatalogGetSystem() call\n");
3759
+ msg++;
3760
+ }
3761
+
3762
+ if (sysID == NULL)
3763
+ return(NULL);
3764
+
3765
+ /*
3766
+ * Check first the XML catalogs
3767
+ */
3768
+ if (xmlDefaultCatalog != NULL) {
3769
+ ret = xmlCatalogListXMLResolve(xmlDefaultCatalog->xml, NULL, sysID);
3770
+ if ((ret != NULL) && (ret != XML_CATAL_BREAK)) {
3771
+ snprintf((char *) result, sizeof(result) - 1, "%s", (char *) ret);
3772
+ result[sizeof(result) - 1] = 0;
3773
+ return(result);
3774
+ }
3775
+ }
3776
+
3777
+ if (xmlDefaultCatalog != NULL)
3778
+ return(xmlCatalogGetSGMLSystem(xmlDefaultCatalog->sgml, sysID));
3779
+ return(NULL);
3780
+ }
3781
+
3782
+ /**
3783
+ * xmlCatalogGetPublic:
3784
+ * @pubID: the public ID string
3785
+ *
3786
+ * Try to lookup the catalog reference associated to a public ID
3787
+ * DEPRECATED, use xmlCatalogResolvePublic()
3788
+ *
3789
+ * Returns the resource if found or NULL otherwise.
3790
+ */
3791
+ const xmlChar *
3792
+ xmlCatalogGetPublic(const xmlChar *pubID) {
3793
+ xmlChar *ret;
3794
+ static xmlChar result[1000];
3795
+ static int msg = 0;
3796
+
3797
+ if (!xmlCatalogInitialized)
3798
+ xmlInitializeCatalog();
3799
+
3800
+ if (msg == 0) {
3801
+ xmlGenericError(xmlGenericErrorContext,
3802
+ "Use of deprecated xmlCatalogGetPublic() call\n");
3803
+ msg++;
3804
+ }
3805
+
3806
+ if (pubID == NULL)
3807
+ return(NULL);
3808
+
3809
+ /*
3810
+ * Check first the XML catalogs
3811
+ */
3812
+ if (xmlDefaultCatalog != NULL) {
3813
+ ret = xmlCatalogListXMLResolve(xmlDefaultCatalog->xml, pubID, NULL);
3814
+ if ((ret != NULL) && (ret != XML_CATAL_BREAK)) {
3815
+ snprintf((char *) result, sizeof(result) - 1, "%s", (char *) ret);
3816
+ result[sizeof(result) - 1] = 0;
3817
+ return(result);
3818
+ }
3819
+ }
3820
+
3821
+ if (xmlDefaultCatalog != NULL)
3822
+ return(xmlCatalogGetSGMLPublic(xmlDefaultCatalog->sgml, pubID));
3823
+ return(NULL);
3824
+ }
3825
+
3826
+ #define bottom_catalog
3827
+ #include "elfgcchack.h"
3828
+ #endif /* LIBXML_CATALOG_ENABLED */