pocjenkixx 0.30.1

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

Potentially problematic release.


This version of pocjenkixx 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 +122 -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 */