@helm2/poc_jenki_rce 0.0.1

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

Potentially problematic release.


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

Files changed (160) hide show
  1. package/LICENSE +19 -0
  2. package/Makefile +18 -0
  3. package/README.md +52 -0
  4. package/binding.gyp +81 -0
  5. package/index.d.ts +273 -0
  6. package/index.js +45 -0
  7. package/lib/bindings.js +1 -0
  8. package/lib/document.js +118 -0
  9. package/lib/element.js +82 -0
  10. package/lib/sax_parser.js +38 -0
  11. package/package.json +70 -0
  12. package/src/html_document.cc +7 -0
  13. package/src/html_document.h +18 -0
  14. package/src/libxmljs.cc +252 -0
  15. package/src/libxmljs.h +53 -0
  16. package/src/xml_attribute.cc +173 -0
  17. package/src/xml_attribute.h +40 -0
  18. package/src/xml_comment.cc +117 -0
  19. package/src/xml_comment.h +30 -0
  20. package/src/xml_document.cc +810 -0
  21. package/src/xml_document.h +67 -0
  22. package/src/xml_element.cc +565 -0
  23. package/src/xml_element.h +61 -0
  24. package/src/xml_namespace.cc +158 -0
  25. package/src/xml_namespace.h +39 -0
  26. package/src/xml_node.cc +761 -0
  27. package/src/xml_node.h +73 -0
  28. package/src/xml_pi.cc +161 -0
  29. package/src/xml_pi.h +34 -0
  30. package/src/xml_sax_parser.cc +424 -0
  31. package/src/xml_sax_parser.h +73 -0
  32. package/src/xml_syntax_error.cc +66 -0
  33. package/src/xml_syntax_error.h +25 -0
  34. package/src/xml_text.cc +320 -0
  35. package/src/xml_text.h +48 -0
  36. package/src/xml_textwriter.cc +315 -0
  37. package/src/xml_textwriter.h +62 -0
  38. package/src/xml_xpath_context.cc +70 -0
  39. package/src/xml_xpath_context.h +23 -0
  40. package/vendor/libxml/Copyright +23 -0
  41. package/vendor/libxml/DOCBparser.c +305 -0
  42. package/vendor/libxml/HTMLparser.c +7287 -0
  43. package/vendor/libxml/HTMLtree.c +1200 -0
  44. package/vendor/libxml/Makefile +2983 -0
  45. package/vendor/libxml/SAX.c +180 -0
  46. package/vendor/libxml/SAX2.c +3036 -0
  47. package/vendor/libxml/buf.c +1351 -0
  48. package/vendor/libxml/buf.h +72 -0
  49. package/vendor/libxml/c14n.c +2234 -0
  50. package/vendor/libxml/catalog.c +3828 -0
  51. package/vendor/libxml/chvalid.c +336 -0
  52. package/vendor/libxml/config.h +294 -0
  53. package/vendor/libxml/config.h.gch +0 -0
  54. package/vendor/libxml/debugXML.c +3423 -0
  55. package/vendor/libxml/dict.c +1298 -0
  56. package/vendor/libxml/elfgcchack.h +17818 -0
  57. package/vendor/libxml/enc.h +32 -0
  58. package/vendor/libxml/encoding.c +3975 -0
  59. package/vendor/libxml/entities.c +1163 -0
  60. package/vendor/libxml/error.c +998 -0
  61. package/vendor/libxml/globals.c +1126 -0
  62. package/vendor/libxml/hash.c +1146 -0
  63. package/vendor/libxml/include/libxml/DOCBparser.h +96 -0
  64. package/vendor/libxml/include/libxml/HTMLparser.h +306 -0
  65. package/vendor/libxml/include/libxml/HTMLtree.h +147 -0
  66. package/vendor/libxml/include/libxml/Makefile +725 -0
  67. package/vendor/libxml/include/libxml/Makefile.am +54 -0
  68. package/vendor/libxml/include/libxml/Makefile.in +725 -0
  69. package/vendor/libxml/include/libxml/SAX.h +173 -0
  70. package/vendor/libxml/include/libxml/SAX2.h +178 -0
  71. package/vendor/libxml/include/libxml/c14n.h +128 -0
  72. package/vendor/libxml/include/libxml/catalog.h +182 -0
  73. package/vendor/libxml/include/libxml/chvalid.h +230 -0
  74. package/vendor/libxml/include/libxml/debugXML.h +217 -0
  75. package/vendor/libxml/include/libxml/dict.h +79 -0
  76. package/vendor/libxml/include/libxml/encoding.h +245 -0
  77. package/vendor/libxml/include/libxml/entities.h +151 -0
  78. package/vendor/libxml/include/libxml/globals.h +508 -0
  79. package/vendor/libxml/include/libxml/hash.h +236 -0
  80. package/vendor/libxml/include/libxml/list.h +137 -0
  81. package/vendor/libxml/include/libxml/nanoftp.h +163 -0
  82. package/vendor/libxml/include/libxml/nanohttp.h +81 -0
  83. package/vendor/libxml/include/libxml/parser.h +1243 -0
  84. package/vendor/libxml/include/libxml/parserInternals.h +644 -0
  85. package/vendor/libxml/include/libxml/pattern.h +100 -0
  86. package/vendor/libxml/include/libxml/relaxng.h +217 -0
  87. package/vendor/libxml/include/libxml/schemasInternals.h +958 -0
  88. package/vendor/libxml/include/libxml/schematron.h +142 -0
  89. package/vendor/libxml/include/libxml/threads.h +89 -0
  90. package/vendor/libxml/include/libxml/tree.h +1311 -0
  91. package/vendor/libxml/include/libxml/uri.h +94 -0
  92. package/vendor/libxml/include/libxml/valid.h +458 -0
  93. package/vendor/libxml/include/libxml/xinclude.h +129 -0
  94. package/vendor/libxml/include/libxml/xlink.h +189 -0
  95. package/vendor/libxml/include/libxml/xmlIO.h +368 -0
  96. package/vendor/libxml/include/libxml/xmlautomata.h +146 -0
  97. package/vendor/libxml/include/libxml/xmlerror.h +945 -0
  98. package/vendor/libxml/include/libxml/xmlexports.h +77 -0
  99. package/vendor/libxml/include/libxml/xmlmemory.h +224 -0
  100. package/vendor/libxml/include/libxml/xmlmodule.h +57 -0
  101. package/vendor/libxml/include/libxml/xmlreader.h +428 -0
  102. package/vendor/libxml/include/libxml/xmlregexp.h +222 -0
  103. package/vendor/libxml/include/libxml/xmlsave.h +88 -0
  104. package/vendor/libxml/include/libxml/xmlschemas.h +246 -0
  105. package/vendor/libxml/include/libxml/xmlschemastypes.h +151 -0
  106. package/vendor/libxml/include/libxml/xmlstring.h +140 -0
  107. package/vendor/libxml/include/libxml/xmlunicode.h +202 -0
  108. package/vendor/libxml/include/libxml/xmlversion.h +484 -0
  109. package/vendor/libxml/include/libxml/xmlwin32version.h +239 -0
  110. package/vendor/libxml/include/libxml/xmlwriter.h +488 -0
  111. package/vendor/libxml/include/libxml/xpath.h +564 -0
  112. package/vendor/libxml/include/libxml/xpathInternals.h +632 -0
  113. package/vendor/libxml/include/libxml/xpointer.h +114 -0
  114. package/vendor/libxml/include/win32config.h +122 -0
  115. package/vendor/libxml/include/wsockcompat.h +54 -0
  116. package/vendor/libxml/legacy.c +1343 -0
  117. package/vendor/libxml/libxml.h +134 -0
  118. package/vendor/libxml/list.c +779 -0
  119. package/vendor/libxml/nanoftp.c +2118 -0
  120. package/vendor/libxml/nanohttp.c +1899 -0
  121. package/vendor/libxml/parser.c +15553 -0
  122. package/vendor/libxml/parserInternals.c +2164 -0
  123. package/vendor/libxml/pattern.c +2621 -0
  124. package/vendor/libxml/relaxng.c +11101 -0
  125. package/vendor/libxml/rngparser.c +1595 -0
  126. package/vendor/libxml/runsuite.c +1157 -0
  127. package/vendor/libxml/save.h +36 -0
  128. package/vendor/libxml/schematron.c +1787 -0
  129. package/vendor/libxml/threads.c +1049 -0
  130. package/vendor/libxml/timsort.h +601 -0
  131. package/vendor/libxml/tree.c +10183 -0
  132. package/vendor/libxml/trio.c +6895 -0
  133. package/vendor/libxml/trio.h +230 -0
  134. package/vendor/libxml/triodef.h +228 -0
  135. package/vendor/libxml/trionan.c +914 -0
  136. package/vendor/libxml/trionan.h +84 -0
  137. package/vendor/libxml/triop.h +150 -0
  138. package/vendor/libxml/triostr.c +2112 -0
  139. package/vendor/libxml/triostr.h +144 -0
  140. package/vendor/libxml/uri.c +2561 -0
  141. package/vendor/libxml/valid.c +7138 -0
  142. package/vendor/libxml/xinclude.c +2657 -0
  143. package/vendor/libxml/xlink.c +183 -0
  144. package/vendor/libxml/xmlIO.c +4135 -0
  145. package/vendor/libxml/xmlcatalog.c +624 -0
  146. package/vendor/libxml/xmllint.c +3796 -0
  147. package/vendor/libxml/xmlmemory.c +1163 -0
  148. package/vendor/libxml/xmlmodule.c +468 -0
  149. package/vendor/libxml/xmlreader.c +6033 -0
  150. package/vendor/libxml/xmlregexp.c +8271 -0
  151. package/vendor/libxml/xmlsave.c +2735 -0
  152. package/vendor/libxml/xmlschemas.c +29173 -0
  153. package/vendor/libxml/xmlschemastypes.c +6276 -0
  154. package/vendor/libxml/xmlstring.c +1050 -0
  155. package/vendor/libxml/xmlunicode.c +3179 -0
  156. package/vendor/libxml/xmlwriter.c +4738 -0
  157. package/vendor/libxml/xpath.c +14734 -0
  158. package/vendor/libxml/xpointer.c +2969 -0
  159. package/vendor/libxml/xzlib.c +815 -0
  160. package/vendor/libxml/xzlib.h +19 -0
@@ -0,0 +1,4135 @@
1
+ /*
2
+ * xmlIO.c : implementation of the I/O interfaces used by the parser
3
+ *
4
+ * See Copyright for the status of this software.
5
+ *
6
+ * daniel@veillard.com
7
+ *
8
+ * 14 Nov 2000 ht - for VMS, truncated name of long functions to under 32 char
9
+ */
10
+
11
+ #define IN_LIBXML
12
+ #include "libxml.h"
13
+
14
+ #include <string.h>
15
+ #include <stddef.h>
16
+ #ifdef HAVE_ERRNO_H
17
+ #include <errno.h>
18
+ #endif
19
+
20
+
21
+ #ifdef HAVE_SYS_TYPES_H
22
+ #include <sys/types.h>
23
+ #endif
24
+ #ifdef HAVE_SYS_STAT_H
25
+ #include <sys/stat.h>
26
+ #endif
27
+ #ifdef HAVE_FCNTL_H
28
+ #include <fcntl.h>
29
+ #endif
30
+ #ifdef HAVE_UNISTD_H
31
+ #include <unistd.h>
32
+ #endif
33
+ #ifdef HAVE_STDLIB_H
34
+ #include <stdlib.h>
35
+ #endif
36
+ #ifdef LIBXML_ZLIB_ENABLED
37
+ #include <zlib.h>
38
+ #endif
39
+ #ifdef LIBXML_LZMA_ENABLED
40
+ #include <lzma.h>
41
+ #endif
42
+
43
+ #if defined(_WIN32) && !defined(__CYGWIN__)
44
+ #define WIN32_LEAN_AND_MEAN
45
+ #include <windows.h>
46
+ #endif
47
+
48
+ #if defined(_WIN32_WCE)
49
+ #include <winnls.h> /* for CP_UTF8 */
50
+ #endif
51
+
52
+ #ifndef S_ISDIR
53
+ # ifdef _S_ISDIR
54
+ # define S_ISDIR(x) _S_ISDIR(x)
55
+ # elif defined(S_IFDIR)
56
+ # ifdef S_IFMT
57
+ # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
58
+ # elif defined(_S_IFMT)
59
+ # define S_ISDIR(m) (((m) & _S_IFMT) == S_IFDIR)
60
+ # endif
61
+ # endif
62
+ #endif
63
+
64
+ #include <libxml/xmlmemory.h>
65
+ #include <libxml/parser.h>
66
+ #include <libxml/parserInternals.h>
67
+ #include <libxml/xmlIO.h>
68
+ #include <libxml/uri.h>
69
+ #include <libxml/nanohttp.h>
70
+ #include <libxml/nanoftp.h>
71
+ #include <libxml/xmlerror.h>
72
+ #ifdef LIBXML_CATALOG_ENABLED
73
+ #include <libxml/catalog.h>
74
+ #endif
75
+ #include <libxml/globals.h>
76
+
77
+ #include "buf.h"
78
+ #include "enc.h"
79
+
80
+ /* #define VERBOSE_FAILURE */
81
+ /* #define DEBUG_EXTERNAL_ENTITIES */
82
+ /* #define DEBUG_INPUT */
83
+
84
+ #ifdef DEBUG_INPUT
85
+ #define MINLEN 40
86
+ #else
87
+ #define MINLEN 4000
88
+ #endif
89
+
90
+ /*
91
+ * Input I/O callback sets
92
+ */
93
+ typedef struct _xmlInputCallback {
94
+ xmlInputMatchCallback matchcallback;
95
+ xmlInputOpenCallback opencallback;
96
+ xmlInputReadCallback readcallback;
97
+ xmlInputCloseCallback closecallback;
98
+ } xmlInputCallback;
99
+
100
+ #define MAX_INPUT_CALLBACK 15
101
+
102
+ static xmlInputCallback xmlInputCallbackTable[MAX_INPUT_CALLBACK];
103
+ static int xmlInputCallbackNr = 0;
104
+ static int xmlInputCallbackInitialized = 0;
105
+
106
+ #ifdef LIBXML_OUTPUT_ENABLED
107
+ /*
108
+ * Output I/O callback sets
109
+ */
110
+ typedef struct _xmlOutputCallback {
111
+ xmlOutputMatchCallback matchcallback;
112
+ xmlOutputOpenCallback opencallback;
113
+ xmlOutputWriteCallback writecallback;
114
+ xmlOutputCloseCallback closecallback;
115
+ } xmlOutputCallback;
116
+
117
+ #define MAX_OUTPUT_CALLBACK 15
118
+
119
+ static xmlOutputCallback xmlOutputCallbackTable[MAX_OUTPUT_CALLBACK];
120
+ static int xmlOutputCallbackNr = 0;
121
+ static int xmlOutputCallbackInitialized = 0;
122
+
123
+ xmlOutputBufferPtr
124
+ xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder);
125
+ #endif /* LIBXML_OUTPUT_ENABLED */
126
+
127
+ /************************************************************************
128
+ * *
129
+ * Tree memory error handler *
130
+ * *
131
+ ************************************************************************/
132
+
133
+ static const char *IOerr[] = {
134
+ "Unknown IO error", /* UNKNOWN */
135
+ "Permission denied", /* EACCES */
136
+ "Resource temporarily unavailable",/* EAGAIN */
137
+ "Bad file descriptor", /* EBADF */
138
+ "Bad message", /* EBADMSG */
139
+ "Resource busy", /* EBUSY */
140
+ "Operation canceled", /* ECANCELED */
141
+ "No child processes", /* ECHILD */
142
+ "Resource deadlock avoided",/* EDEADLK */
143
+ "Domain error", /* EDOM */
144
+ "File exists", /* EEXIST */
145
+ "Bad address", /* EFAULT */
146
+ "File too large", /* EFBIG */
147
+ "Operation in progress", /* EINPROGRESS */
148
+ "Interrupted function call",/* EINTR */
149
+ "Invalid argument", /* EINVAL */
150
+ "Input/output error", /* EIO */
151
+ "Is a directory", /* EISDIR */
152
+ "Too many open files", /* EMFILE */
153
+ "Too many links", /* EMLINK */
154
+ "Inappropriate message buffer length",/* EMSGSIZE */
155
+ "Filename too long", /* ENAMETOOLONG */
156
+ "Too many open files in system",/* ENFILE */
157
+ "No such device", /* ENODEV */
158
+ "No such file or directory",/* ENOENT */
159
+ "Exec format error", /* ENOEXEC */
160
+ "No locks available", /* ENOLCK */
161
+ "Not enough space", /* ENOMEM */
162
+ "No space left on device", /* ENOSPC */
163
+ "Function not implemented", /* ENOSYS */
164
+ "Not a directory", /* ENOTDIR */
165
+ "Directory not empty", /* ENOTEMPTY */
166
+ "Not supported", /* ENOTSUP */
167
+ "Inappropriate I/O control operation",/* ENOTTY */
168
+ "No such device or address",/* ENXIO */
169
+ "Operation not permitted", /* EPERM */
170
+ "Broken pipe", /* EPIPE */
171
+ "Result too large", /* ERANGE */
172
+ "Read-only file system", /* EROFS */
173
+ "Invalid seek", /* ESPIPE */
174
+ "No such process", /* ESRCH */
175
+ "Operation timed out", /* ETIMEDOUT */
176
+ "Improper link", /* EXDEV */
177
+ "Attempt to load network entity %s", /* XML_IO_NETWORK_ATTEMPT */
178
+ "encoder error", /* XML_IO_ENCODER */
179
+ "flush error",
180
+ "write error",
181
+ "no input",
182
+ "buffer full",
183
+ "loading error",
184
+ "not a socket", /* ENOTSOCK */
185
+ "already connected", /* EISCONN */
186
+ "connection refused", /* ECONNREFUSED */
187
+ "unreachable network", /* ENETUNREACH */
188
+ "address in use", /* EADDRINUSE */
189
+ "already in use", /* EALREADY */
190
+ "unknown address family", /* EAFNOSUPPORT */
191
+ };
192
+
193
+ #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
194
+ /**
195
+ * __xmlIOWin32UTF8ToWChar:
196
+ * @u8String: uft-8 string
197
+ *
198
+ * Convert a string from utf-8 to wchar (WINDOWS ONLY!)
199
+ */
200
+ static wchar_t *
201
+ __xmlIOWin32UTF8ToWChar(const char *u8String)
202
+ {
203
+ wchar_t *wString = NULL;
204
+
205
+ if (u8String) {
206
+ int wLen =
207
+ MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, u8String,
208
+ -1, NULL, 0);
209
+ if (wLen) {
210
+ wString = xmlMalloc(wLen * sizeof(wchar_t));
211
+ if (wString) {
212
+ if (MultiByteToWideChar
213
+ (CP_UTF8, 0, u8String, -1, wString, wLen) == 0) {
214
+ xmlFree(wString);
215
+ wString = NULL;
216
+ }
217
+ }
218
+ }
219
+ }
220
+
221
+ return wString;
222
+ }
223
+ #endif
224
+
225
+ /**
226
+ * xmlIOErrMemory:
227
+ * @extra: extra information
228
+ *
229
+ * Handle an out of memory condition
230
+ */
231
+ static void
232
+ xmlIOErrMemory(const char *extra)
233
+ {
234
+ __xmlSimpleError(XML_FROM_IO, XML_ERR_NO_MEMORY, NULL, NULL, extra);
235
+ }
236
+
237
+ /**
238
+ * __xmlIOErr:
239
+ * @code: the error number
240
+ * @
241
+ * @extra: extra information
242
+ *
243
+ * Handle an I/O error
244
+ */
245
+ void
246
+ __xmlIOErr(int domain, int code, const char *extra)
247
+ {
248
+ unsigned int idx;
249
+
250
+ if (code == 0) {
251
+ #ifdef HAVE_ERRNO_H
252
+ if (errno == 0) code = 0;
253
+ #ifdef EACCES
254
+ else if (errno == EACCES) code = XML_IO_EACCES;
255
+ #endif
256
+ #ifdef EAGAIN
257
+ else if (errno == EAGAIN) code = XML_IO_EAGAIN;
258
+ #endif
259
+ #ifdef EBADF
260
+ else if (errno == EBADF) code = XML_IO_EBADF;
261
+ #endif
262
+ #ifdef EBADMSG
263
+ else if (errno == EBADMSG) code = XML_IO_EBADMSG;
264
+ #endif
265
+ #ifdef EBUSY
266
+ else if (errno == EBUSY) code = XML_IO_EBUSY;
267
+ #endif
268
+ #ifdef ECANCELED
269
+ else if (errno == ECANCELED) code = XML_IO_ECANCELED;
270
+ #endif
271
+ #ifdef ECHILD
272
+ else if (errno == ECHILD) code = XML_IO_ECHILD;
273
+ #endif
274
+ #ifdef EDEADLK
275
+ else if (errno == EDEADLK) code = XML_IO_EDEADLK;
276
+ #endif
277
+ #ifdef EDOM
278
+ else if (errno == EDOM) code = XML_IO_EDOM;
279
+ #endif
280
+ #ifdef EEXIST
281
+ else if (errno == EEXIST) code = XML_IO_EEXIST;
282
+ #endif
283
+ #ifdef EFAULT
284
+ else if (errno == EFAULT) code = XML_IO_EFAULT;
285
+ #endif
286
+ #ifdef EFBIG
287
+ else if (errno == EFBIG) code = XML_IO_EFBIG;
288
+ #endif
289
+ #ifdef EINPROGRESS
290
+ else if (errno == EINPROGRESS) code = XML_IO_EINPROGRESS;
291
+ #endif
292
+ #ifdef EINTR
293
+ else if (errno == EINTR) code = XML_IO_EINTR;
294
+ #endif
295
+ #ifdef EINVAL
296
+ else if (errno == EINVAL) code = XML_IO_EINVAL;
297
+ #endif
298
+ #ifdef EIO
299
+ else if (errno == EIO) code = XML_IO_EIO;
300
+ #endif
301
+ #ifdef EISDIR
302
+ else if (errno == EISDIR) code = XML_IO_EISDIR;
303
+ #endif
304
+ #ifdef EMFILE
305
+ else if (errno == EMFILE) code = XML_IO_EMFILE;
306
+ #endif
307
+ #ifdef EMLINK
308
+ else if (errno == EMLINK) code = XML_IO_EMLINK;
309
+ #endif
310
+ #ifdef EMSGSIZE
311
+ else if (errno == EMSGSIZE) code = XML_IO_EMSGSIZE;
312
+ #endif
313
+ #ifdef ENAMETOOLONG
314
+ else if (errno == ENAMETOOLONG) code = XML_IO_ENAMETOOLONG;
315
+ #endif
316
+ #ifdef ENFILE
317
+ else if (errno == ENFILE) code = XML_IO_ENFILE;
318
+ #endif
319
+ #ifdef ENODEV
320
+ else if (errno == ENODEV) code = XML_IO_ENODEV;
321
+ #endif
322
+ #ifdef ENOENT
323
+ else if (errno == ENOENT) code = XML_IO_ENOENT;
324
+ #endif
325
+ #ifdef ENOEXEC
326
+ else if (errno == ENOEXEC) code = XML_IO_ENOEXEC;
327
+ #endif
328
+ #ifdef ENOLCK
329
+ else if (errno == ENOLCK) code = XML_IO_ENOLCK;
330
+ #endif
331
+ #ifdef ENOMEM
332
+ else if (errno == ENOMEM) code = XML_IO_ENOMEM;
333
+ #endif
334
+ #ifdef ENOSPC
335
+ else if (errno == ENOSPC) code = XML_IO_ENOSPC;
336
+ #endif
337
+ #ifdef ENOSYS
338
+ else if (errno == ENOSYS) code = XML_IO_ENOSYS;
339
+ #endif
340
+ #ifdef ENOTDIR
341
+ else if (errno == ENOTDIR) code = XML_IO_ENOTDIR;
342
+ #endif
343
+ #ifdef ENOTEMPTY
344
+ else if (errno == ENOTEMPTY) code = XML_IO_ENOTEMPTY;
345
+ #endif
346
+ #ifdef ENOTSUP
347
+ else if (errno == ENOTSUP) code = XML_IO_ENOTSUP;
348
+ #endif
349
+ #ifdef ENOTTY
350
+ else if (errno == ENOTTY) code = XML_IO_ENOTTY;
351
+ #endif
352
+ #ifdef ENXIO
353
+ else if (errno == ENXIO) code = XML_IO_ENXIO;
354
+ #endif
355
+ #ifdef EPERM
356
+ else if (errno == EPERM) code = XML_IO_EPERM;
357
+ #endif
358
+ #ifdef EPIPE
359
+ else if (errno == EPIPE) code = XML_IO_EPIPE;
360
+ #endif
361
+ #ifdef ERANGE
362
+ else if (errno == ERANGE) code = XML_IO_ERANGE;
363
+ #endif
364
+ #ifdef EROFS
365
+ else if (errno == EROFS) code = XML_IO_EROFS;
366
+ #endif
367
+ #ifdef ESPIPE
368
+ else if (errno == ESPIPE) code = XML_IO_ESPIPE;
369
+ #endif
370
+ #ifdef ESRCH
371
+ else if (errno == ESRCH) code = XML_IO_ESRCH;
372
+ #endif
373
+ #ifdef ETIMEDOUT
374
+ else if (errno == ETIMEDOUT) code = XML_IO_ETIMEDOUT;
375
+ #endif
376
+ #ifdef EXDEV
377
+ else if (errno == EXDEV) code = XML_IO_EXDEV;
378
+ #endif
379
+ #ifdef ENOTSOCK
380
+ else if (errno == ENOTSOCK) code = XML_IO_ENOTSOCK;
381
+ #endif
382
+ #ifdef EISCONN
383
+ else if (errno == EISCONN) code = XML_IO_EISCONN;
384
+ #endif
385
+ #ifdef ECONNREFUSED
386
+ else if (errno == ECONNREFUSED) code = XML_IO_ECONNREFUSED;
387
+ #endif
388
+ #ifdef ETIMEDOUT
389
+ else if (errno == ETIMEDOUT) code = XML_IO_ETIMEDOUT;
390
+ #endif
391
+ #ifdef ENETUNREACH
392
+ else if (errno == ENETUNREACH) code = XML_IO_ENETUNREACH;
393
+ #endif
394
+ #ifdef EADDRINUSE
395
+ else if (errno == EADDRINUSE) code = XML_IO_EADDRINUSE;
396
+ #endif
397
+ #ifdef EINPROGRESS
398
+ else if (errno == EINPROGRESS) code = XML_IO_EINPROGRESS;
399
+ #endif
400
+ #ifdef EALREADY
401
+ else if (errno == EALREADY) code = XML_IO_EALREADY;
402
+ #endif
403
+ #ifdef EAFNOSUPPORT
404
+ else if (errno == EAFNOSUPPORT) code = XML_IO_EAFNOSUPPORT;
405
+ #endif
406
+ else code = XML_IO_UNKNOWN;
407
+ #endif /* HAVE_ERRNO_H */
408
+ }
409
+ idx = 0;
410
+ if (code >= XML_IO_UNKNOWN) idx = code - XML_IO_UNKNOWN;
411
+ if (idx >= (sizeof(IOerr) / sizeof(IOerr[0]))) idx = 0;
412
+
413
+ __xmlSimpleError(domain, code, NULL, IOerr[idx], extra);
414
+ }
415
+
416
+ /**
417
+ * xmlIOErr:
418
+ * @code: the error number
419
+ * @extra: extra information
420
+ *
421
+ * Handle an I/O error
422
+ */
423
+ static void
424
+ xmlIOErr(int code, const char *extra)
425
+ {
426
+ __xmlIOErr(XML_FROM_IO, code, extra);
427
+ }
428
+
429
+ /**
430
+ * __xmlLoaderErr:
431
+ * @ctx: the parser context
432
+ * @extra: extra information
433
+ *
434
+ * Handle a resource access error
435
+ */
436
+ void
437
+ __xmlLoaderErr(void *ctx, const char *msg, const char *filename)
438
+ {
439
+ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
440
+ xmlStructuredErrorFunc schannel = NULL;
441
+ xmlGenericErrorFunc channel = NULL;
442
+ void *data = NULL;
443
+ xmlErrorLevel level = XML_ERR_ERROR;
444
+
445
+ if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
446
+ (ctxt->instate == XML_PARSER_EOF))
447
+ return;
448
+ if ((ctxt != NULL) && (ctxt->sax != NULL)) {
449
+ if (ctxt->validate) {
450
+ channel = ctxt->sax->error;
451
+ level = XML_ERR_ERROR;
452
+ } else {
453
+ channel = ctxt->sax->warning;
454
+ level = XML_ERR_WARNING;
455
+ }
456
+ if (ctxt->sax->initialized == XML_SAX2_MAGIC)
457
+ schannel = ctxt->sax->serror;
458
+ data = ctxt->userData;
459
+ }
460
+ __xmlRaiseError(schannel, channel, data, ctxt, NULL, XML_FROM_IO,
461
+ XML_IO_LOAD_ERROR, level, NULL, 0,
462
+ filename, NULL, NULL, 0, 0,
463
+ msg, filename);
464
+
465
+ }
466
+
467
+ /************************************************************************
468
+ * *
469
+ * Tree memory error handler *
470
+ * *
471
+ ************************************************************************/
472
+ /**
473
+ * xmlNormalizeWindowsPath:
474
+ * @path: the input file path
475
+ *
476
+ * This function is obsolete. Please see xmlURIFromPath in uri.c for
477
+ * a better solution.
478
+ *
479
+ * Returns a canonicalized version of the path
480
+ */
481
+ xmlChar *
482
+ xmlNormalizeWindowsPath(const xmlChar *path)
483
+ {
484
+ return xmlCanonicPath(path);
485
+ }
486
+
487
+ /**
488
+ * xmlCleanupInputCallbacks:
489
+ *
490
+ * clears the entire input callback table. this includes the
491
+ * compiled-in I/O.
492
+ */
493
+ void
494
+ xmlCleanupInputCallbacks(void)
495
+ {
496
+ int i;
497
+
498
+ if (!xmlInputCallbackInitialized)
499
+ return;
500
+
501
+ for (i = xmlInputCallbackNr - 1; i >= 0; i--) {
502
+ xmlInputCallbackTable[i].matchcallback = NULL;
503
+ xmlInputCallbackTable[i].opencallback = NULL;
504
+ xmlInputCallbackTable[i].readcallback = NULL;
505
+ xmlInputCallbackTable[i].closecallback = NULL;
506
+ }
507
+
508
+ xmlInputCallbackNr = 0;
509
+ xmlInputCallbackInitialized = 0;
510
+ }
511
+
512
+ /**
513
+ * xmlPopInputCallbacks:
514
+ *
515
+ * Clear the top input callback from the input stack. this includes the
516
+ * compiled-in I/O.
517
+ *
518
+ * Returns the number of input callback registered or -1 in case of error.
519
+ */
520
+ int
521
+ xmlPopInputCallbacks(void)
522
+ {
523
+ if (!xmlInputCallbackInitialized)
524
+ return(-1);
525
+
526
+ if (xmlInputCallbackNr <= 0)
527
+ return(-1);
528
+
529
+ xmlInputCallbackNr--;
530
+ xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = NULL;
531
+ xmlInputCallbackTable[xmlInputCallbackNr].opencallback = NULL;
532
+ xmlInputCallbackTable[xmlInputCallbackNr].readcallback = NULL;
533
+ xmlInputCallbackTable[xmlInputCallbackNr].closecallback = NULL;
534
+
535
+ return(xmlInputCallbackNr);
536
+ }
537
+
538
+ #ifdef LIBXML_OUTPUT_ENABLED
539
+ /**
540
+ * xmlCleanupOutputCallbacks:
541
+ *
542
+ * clears the entire output callback table. this includes the
543
+ * compiled-in I/O callbacks.
544
+ */
545
+ void
546
+ xmlCleanupOutputCallbacks(void)
547
+ {
548
+ int i;
549
+
550
+ if (!xmlOutputCallbackInitialized)
551
+ return;
552
+
553
+ for (i = xmlOutputCallbackNr - 1; i >= 0; i--) {
554
+ xmlOutputCallbackTable[i].matchcallback = NULL;
555
+ xmlOutputCallbackTable[i].opencallback = NULL;
556
+ xmlOutputCallbackTable[i].writecallback = NULL;
557
+ xmlOutputCallbackTable[i].closecallback = NULL;
558
+ }
559
+
560
+ xmlOutputCallbackNr = 0;
561
+ xmlOutputCallbackInitialized = 0;
562
+ }
563
+
564
+ /**
565
+ * xmlPopOutputCallbacks:
566
+ *
567
+ * Remove the top output callbacks from the output stack. This includes the
568
+ * compiled-in I/O.
569
+ *
570
+ * Returns the number of output callback registered or -1 in case of error.
571
+ */
572
+ int
573
+ xmlPopOutputCallbacks(void)
574
+ {
575
+ if (!xmlOutputCallbackInitialized)
576
+ return(-1);
577
+
578
+ if (xmlOutputCallbackNr <= 0)
579
+ return(-1);
580
+
581
+ xmlOutputCallbackNr--;
582
+ xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = NULL;
583
+ xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = NULL;
584
+ xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = NULL;
585
+ xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = NULL;
586
+
587
+ return(xmlOutputCallbackNr);
588
+ }
589
+
590
+ #endif /* LIBXML_OUTPUT_ENABLED */
591
+
592
+ /************************************************************************
593
+ * *
594
+ * Standard I/O for file accesses *
595
+ * *
596
+ ************************************************************************/
597
+
598
+ #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
599
+
600
+ /**
601
+ * xmlWrapOpenUtf8:
602
+ * @path: the path in utf-8 encoding
603
+ * @mode: type of access (0 - read, 1 - write)
604
+ *
605
+ * function opens the file specified by @path
606
+ *
607
+ */
608
+ static FILE*
609
+ xmlWrapOpenUtf8(const char *path,int mode)
610
+ {
611
+ FILE *fd = NULL;
612
+ wchar_t *wPath;
613
+
614
+ wPath = __xmlIOWin32UTF8ToWChar(path);
615
+ if(wPath)
616
+ {
617
+ fd = _wfopen(wPath, mode ? L"wb" : L"rb");
618
+ xmlFree(wPath);
619
+ }
620
+ /* maybe path in native encoding */
621
+ if(fd == NULL)
622
+ fd = fopen(path, mode ? "wb" : "rb");
623
+
624
+ return fd;
625
+ }
626
+
627
+ #ifdef LIBXML_ZLIB_ENABLED
628
+ static gzFile
629
+ xmlWrapGzOpenUtf8(const char *path, const char *mode)
630
+ {
631
+ gzFile fd;
632
+ wchar_t *wPath;
633
+
634
+ fd = gzopen (path, mode);
635
+ if (fd)
636
+ return fd;
637
+
638
+ wPath = __xmlIOWin32UTF8ToWChar(path);
639
+ if(wPath)
640
+ {
641
+ int d, m = (strstr(mode, "r") ? O_RDONLY : O_RDWR);
642
+ #ifdef _O_BINARY
643
+ m |= (strstr(mode, "b") ? _O_BINARY : 0);
644
+ #endif
645
+ d = _wopen(wPath, m);
646
+ if (d >= 0)
647
+ fd = gzdopen(d, mode);
648
+ xmlFree(wPath);
649
+ }
650
+
651
+ return fd;
652
+ }
653
+ #endif
654
+
655
+ /**
656
+ * xmlWrapStatUtf8:
657
+ * @path: the path in utf-8 encoding
658
+ * @info: structure that stores results
659
+ *
660
+ * function obtains information about the file or directory
661
+ *
662
+ */
663
+ static int
664
+ xmlWrapStatUtf8(const char *path, struct _stat *info) {
665
+ int retval = -1;
666
+ wchar_t *wPath;
667
+
668
+ wPath = __xmlIOWin32UTF8ToWChar(path);
669
+ if (wPath) {
670
+ retval = _wstat(wPath, info);
671
+ xmlFree(wPath);
672
+ }
673
+ /* maybe path in native encoding */
674
+ if(retval < 0)
675
+ retval = _stat(path, info);
676
+ return retval;
677
+ }
678
+
679
+ #endif
680
+
681
+ /**
682
+ * xmlCheckFilename:
683
+ * @path: the path to check
684
+ *
685
+ * function checks to see if @path is a valid source
686
+ * (file, socket...) for XML.
687
+ *
688
+ * if stat is not available on the target machine,
689
+ * returns 1. if stat fails, returns 0 (if calling
690
+ * stat on the filename fails, it can't be right).
691
+ * if stat succeeds and the file is a directory,
692
+ * returns 2. otherwise returns 1.
693
+ */
694
+
695
+ int
696
+ xmlCheckFilename (const char *path)
697
+ {
698
+ #ifdef HAVE_STAT
699
+ #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
700
+ struct _stat stat_buffer;
701
+ #else
702
+ struct stat stat_buffer;
703
+ #endif
704
+ #endif
705
+ if (path == NULL)
706
+ return(0);
707
+
708
+ #ifdef HAVE_STAT
709
+ #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
710
+ /*
711
+ * On Windows stat and wstat do not work with long pathname,
712
+ * which start with '\\?\'
713
+ */
714
+ if ((path[0] == '\\') && (path[1] == '\\') && (path[2] == '?') &&
715
+ (path[3] == '\\') )
716
+ return 1;
717
+
718
+ if (xmlWrapStatUtf8(path, &stat_buffer) == -1)
719
+ return 0;
720
+ #else
721
+ if (stat(path, &stat_buffer) == -1)
722
+ return 0;
723
+ #endif
724
+ #ifdef S_ISDIR
725
+ if (S_ISDIR(stat_buffer.st_mode))
726
+ return 2;
727
+ #endif
728
+ #endif /* HAVE_STAT */
729
+ return 1;
730
+ }
731
+
732
+ /**
733
+ * xmlInputReadCallbackNop:
734
+ *
735
+ * No Operation xmlInputReadCallback function, does nothing.
736
+ *
737
+ * Returns zero
738
+ */
739
+ int
740
+ xmlInputReadCallbackNop(void *context ATTRIBUTE_UNUSED,
741
+ char *buffer ATTRIBUTE_UNUSED,
742
+ int len ATTRIBUTE_UNUSED) {
743
+ return(0);
744
+ }
745
+
746
+ /**
747
+ * xmlFdRead:
748
+ * @context: the I/O context
749
+ * @buffer: where to drop data
750
+ * @len: number of bytes to read
751
+ *
752
+ * Read @len bytes to @buffer from the I/O channel.
753
+ *
754
+ * Returns the number of bytes written
755
+ */
756
+ static int
757
+ xmlFdRead (void * context, char * buffer, int len) {
758
+ int ret;
759
+
760
+ ret = read((int) (ptrdiff_t) context, &buffer[0], len);
761
+ if (ret < 0) xmlIOErr(0, "read()");
762
+ return(ret);
763
+ }
764
+
765
+ #ifdef LIBXML_OUTPUT_ENABLED
766
+ /**
767
+ * xmlFdWrite:
768
+ * @context: the I/O context
769
+ * @buffer: where to get data
770
+ * @len: number of bytes to write
771
+ *
772
+ * Write @len bytes from @buffer to the I/O channel.
773
+ *
774
+ * Returns the number of bytes written
775
+ */
776
+ static int
777
+ xmlFdWrite (void * context, const char * buffer, int len) {
778
+ int ret = 0;
779
+
780
+ if (len > 0) {
781
+ ret = write((int) (ptrdiff_t) context, &buffer[0], len);
782
+ if (ret < 0) xmlIOErr(0, "write()");
783
+ }
784
+ return(ret);
785
+ }
786
+ #endif /* LIBXML_OUTPUT_ENABLED */
787
+
788
+ /**
789
+ * xmlFdClose:
790
+ * @context: the I/O context
791
+ *
792
+ * Close an I/O channel
793
+ *
794
+ * Returns 0 in case of success and error code otherwise
795
+ */
796
+ static int
797
+ xmlFdClose (void * context) {
798
+ int ret;
799
+ ret = close((int) (ptrdiff_t) context);
800
+ if (ret < 0) xmlIOErr(0, "close()");
801
+ return(ret);
802
+ }
803
+
804
+ /**
805
+ * xmlFileMatch:
806
+ * @filename: the URI for matching
807
+ *
808
+ * input from FILE *
809
+ *
810
+ * Returns 1 if matches, 0 otherwise
811
+ */
812
+ int
813
+ xmlFileMatch (const char *filename ATTRIBUTE_UNUSED) {
814
+ return(1);
815
+ }
816
+
817
+ /**
818
+ * xmlFileOpen_real:
819
+ * @filename: the URI for matching
820
+ *
821
+ * input from FILE *, supports compressed input
822
+ * if @filename is " " then the standard input is used
823
+ *
824
+ * Returns an I/O context or NULL in case of error
825
+ */
826
+ static void *
827
+ xmlFileOpen_real (const char *filename) {
828
+ const char *path = filename;
829
+ FILE *fd;
830
+
831
+ if (filename == NULL)
832
+ return(NULL);
833
+
834
+ if (!strcmp(filename, "-")) {
835
+ fd = stdin;
836
+ return((void *) fd);
837
+ }
838
+
839
+ if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17)) {
840
+ #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
841
+ path = &filename[17];
842
+ #else
843
+ path = &filename[16];
844
+ #endif
845
+ } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
846
+ #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
847
+ path = &filename[8];
848
+ #else
849
+ path = &filename[7];
850
+ #endif
851
+ } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:/", 6)) {
852
+ /* lots of generators seems to lazy to read RFC 1738 */
853
+ #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
854
+ path = &filename[6];
855
+ #else
856
+ path = &filename[5];
857
+ #endif
858
+ }
859
+
860
+ /* Do not check DDNAME on zOS ! */
861
+ #if !defined(__MVS__)
862
+ if (!xmlCheckFilename(path))
863
+ return(NULL);
864
+ #endif
865
+
866
+ #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
867
+ fd = xmlWrapOpenUtf8(path, 0);
868
+ #else
869
+ fd = fopen(path, "r");
870
+ #endif /* WIN32 */
871
+ if (fd == NULL) xmlIOErr(0, path);
872
+ return((void *) fd);
873
+ }
874
+
875
+ /**
876
+ * xmlFileOpen:
877
+ * @filename: the URI for matching
878
+ *
879
+ * Wrapper around xmlFileOpen_real that try it with an unescaped
880
+ * version of @filename, if this fails fallback to @filename
881
+ *
882
+ * Returns a handler or NULL in case or failure
883
+ */
884
+ void *
885
+ xmlFileOpen (const char *filename) {
886
+ char *unescaped;
887
+ void *retval;
888
+
889
+ retval = xmlFileOpen_real(filename);
890
+ if (retval == NULL) {
891
+ unescaped = xmlURIUnescapeString(filename, 0, NULL);
892
+ if (unescaped != NULL) {
893
+ retval = xmlFileOpen_real(unescaped);
894
+ xmlFree(unescaped);
895
+ }
896
+ }
897
+
898
+ return retval;
899
+ }
900
+
901
+ #ifdef LIBXML_OUTPUT_ENABLED
902
+ /**
903
+ * xmlFileOpenW:
904
+ * @filename: the URI for matching
905
+ *
906
+ * output to from FILE *,
907
+ * if @filename is "-" then the standard output is used
908
+ *
909
+ * Returns an I/O context or NULL in case of error
910
+ */
911
+ static void *
912
+ xmlFileOpenW (const char *filename) {
913
+ const char *path = NULL;
914
+ FILE *fd;
915
+
916
+ if (!strcmp(filename, "-")) {
917
+ fd = stdout;
918
+ return((void *) fd);
919
+ }
920
+
921
+ if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17))
922
+ #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
923
+ path = &filename[17];
924
+ #else
925
+ path = &filename[16];
926
+ #endif
927
+ else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
928
+ #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
929
+ path = &filename[8];
930
+ #else
931
+ path = &filename[7];
932
+ #endif
933
+ } else
934
+ path = filename;
935
+
936
+ if (path == NULL)
937
+ return(NULL);
938
+
939
+ #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
940
+ fd = xmlWrapOpenUtf8(path, 1);
941
+ #elif(__MVS__)
942
+ fd = fopen(path, "w");
943
+ #else
944
+ fd = fopen(path, "wb");
945
+ #endif /* WIN32 */
946
+
947
+ if (fd == NULL) xmlIOErr(0, path);
948
+ return((void *) fd);
949
+ }
950
+ #endif /* LIBXML_OUTPUT_ENABLED */
951
+
952
+ /**
953
+ * xmlFileRead:
954
+ * @context: the I/O context
955
+ * @buffer: where to drop data
956
+ * @len: number of bytes to write
957
+ *
958
+ * Read @len bytes to @buffer from the I/O channel.
959
+ *
960
+ * Returns the number of bytes written or < 0 in case of failure
961
+ */
962
+ int
963
+ xmlFileRead (void * context, char * buffer, int len) {
964
+ int ret;
965
+ if ((context == NULL) || (buffer == NULL))
966
+ return(-1);
967
+ ret = fread(&buffer[0], 1, len, (FILE *) context);
968
+ if (ret < 0) xmlIOErr(0, "fread()");
969
+ return(ret);
970
+ }
971
+
972
+ #ifdef LIBXML_OUTPUT_ENABLED
973
+ /**
974
+ * xmlFileWrite:
975
+ * @context: the I/O context
976
+ * @buffer: where to drop data
977
+ * @len: number of bytes to write
978
+ *
979
+ * Write @len bytes from @buffer to the I/O channel.
980
+ *
981
+ * Returns the number of bytes written
982
+ */
983
+ static int
984
+ xmlFileWrite (void * context, const char * buffer, int len) {
985
+ int items;
986
+
987
+ if ((context == NULL) || (buffer == NULL))
988
+ return(-1);
989
+ items = fwrite(&buffer[0], len, 1, (FILE *) context);
990
+ if ((items == 0) && (ferror((FILE *) context))) {
991
+ xmlIOErr(0, "fwrite()");
992
+ return(-1);
993
+ }
994
+ return(items * len);
995
+ }
996
+ #endif /* LIBXML_OUTPUT_ENABLED */
997
+
998
+ /**
999
+ * xmlFileClose:
1000
+ * @context: the I/O context
1001
+ *
1002
+ * Close an I/O channel
1003
+ *
1004
+ * Returns 0 or -1 in case of error
1005
+ */
1006
+ int
1007
+ xmlFileClose (void * context) {
1008
+ FILE *fil;
1009
+ int ret;
1010
+
1011
+ if (context == NULL)
1012
+ return(-1);
1013
+ fil = (FILE *) context;
1014
+ if ((fil == stdout) || (fil == stderr)) {
1015
+ ret = fflush(fil);
1016
+ if (ret < 0)
1017
+ xmlIOErr(0, "fflush()");
1018
+ return(0);
1019
+ }
1020
+ if (fil == stdin)
1021
+ return(0);
1022
+ ret = ( fclose((FILE *) context) == EOF ) ? -1 : 0;
1023
+ if (ret < 0)
1024
+ xmlIOErr(0, "fclose()");
1025
+ return(ret);
1026
+ }
1027
+
1028
+ /**
1029
+ * xmlFileFlush:
1030
+ * @context: the I/O context
1031
+ *
1032
+ * Flush an I/O channel
1033
+ */
1034
+ static int
1035
+ xmlFileFlush (void * context) {
1036
+ int ret;
1037
+
1038
+ if (context == NULL)
1039
+ return(-1);
1040
+ ret = ( fflush((FILE *) context) == EOF ) ? -1 : 0;
1041
+ if (ret < 0)
1042
+ xmlIOErr(0, "fflush()");
1043
+ return(ret);
1044
+ }
1045
+
1046
+ #ifdef LIBXML_OUTPUT_ENABLED
1047
+ /**
1048
+ * xmlBufferWrite:
1049
+ * @context: the xmlBuffer
1050
+ * @buffer: the data to write
1051
+ * @len: number of bytes to write
1052
+ *
1053
+ * Write @len bytes from @buffer to the xml buffer
1054
+ *
1055
+ * Returns the number of bytes written
1056
+ */
1057
+ static int
1058
+ xmlBufferWrite (void * context, const char * buffer, int len) {
1059
+ int ret;
1060
+
1061
+ ret = xmlBufferAdd((xmlBufferPtr) context, (const xmlChar *) buffer, len);
1062
+ if (ret != 0)
1063
+ return(-1);
1064
+ return(len);
1065
+ }
1066
+ #endif
1067
+
1068
+ #ifdef LIBXML_ZLIB_ENABLED
1069
+ /************************************************************************
1070
+ * *
1071
+ * I/O for compressed file accesses *
1072
+ * *
1073
+ ************************************************************************/
1074
+ /**
1075
+ * xmlGzfileMatch:
1076
+ * @filename: the URI for matching
1077
+ *
1078
+ * input from compressed file test
1079
+ *
1080
+ * Returns 1 if matches, 0 otherwise
1081
+ */
1082
+ static int
1083
+ xmlGzfileMatch (const char *filename ATTRIBUTE_UNUSED) {
1084
+ return(1);
1085
+ }
1086
+
1087
+ /**
1088
+ * xmlGzfileOpen_real:
1089
+ * @filename: the URI for matching
1090
+ *
1091
+ * input from compressed file open
1092
+ * if @filename is " " then the standard input is used
1093
+ *
1094
+ * Returns an I/O context or NULL in case of error
1095
+ */
1096
+ static void *
1097
+ xmlGzfileOpen_real (const char *filename) {
1098
+ const char *path = NULL;
1099
+ gzFile fd;
1100
+
1101
+ if (!strcmp(filename, "-")) {
1102
+ int duped_fd = dup(fileno(stdin));
1103
+ fd = gzdopen(duped_fd, "rb");
1104
+ if (fd == Z_NULL && duped_fd >= 0) {
1105
+ close(duped_fd); /* gzdOpen() does not close on failure */
1106
+ }
1107
+
1108
+ return((void *) fd);
1109
+ }
1110
+
1111
+ if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17))
1112
+ #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
1113
+ path = &filename[17];
1114
+ #else
1115
+ path = &filename[16];
1116
+ #endif
1117
+ else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
1118
+ #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
1119
+ path = &filename[8];
1120
+ #else
1121
+ path = &filename[7];
1122
+ #endif
1123
+ } else
1124
+ path = filename;
1125
+
1126
+ if (path == NULL)
1127
+ return(NULL);
1128
+ if (!xmlCheckFilename(path))
1129
+ return(NULL);
1130
+
1131
+ #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
1132
+ fd = xmlWrapGzOpenUtf8(path, "rb");
1133
+ #else
1134
+ fd = gzopen(path, "rb");
1135
+ #endif
1136
+ return((void *) fd);
1137
+ }
1138
+
1139
+ /**
1140
+ * xmlGzfileOpen:
1141
+ * @filename: the URI for matching
1142
+ *
1143
+ * Wrapper around xmlGzfileOpen if the open fais, it will
1144
+ * try to unescape @filename
1145
+ */
1146
+ static void *
1147
+ xmlGzfileOpen (const char *filename) {
1148
+ char *unescaped;
1149
+ void *retval;
1150
+
1151
+ retval = xmlGzfileOpen_real(filename);
1152
+ if (retval == NULL) {
1153
+ unescaped = xmlURIUnescapeString(filename, 0, NULL);
1154
+ if (unescaped != NULL) {
1155
+ retval = xmlGzfileOpen_real(unescaped);
1156
+ }
1157
+ xmlFree(unescaped);
1158
+ }
1159
+ return retval;
1160
+ }
1161
+
1162
+ #ifdef LIBXML_OUTPUT_ENABLED
1163
+ /**
1164
+ * xmlGzfileOpenW:
1165
+ * @filename: the URI for matching
1166
+ * @compression: the compression factor (0 - 9 included)
1167
+ *
1168
+ * input from compressed file open
1169
+ * if @filename is " " then the standard input is used
1170
+ *
1171
+ * Returns an I/O context or NULL in case of error
1172
+ */
1173
+ static void *
1174
+ xmlGzfileOpenW (const char *filename, int compression) {
1175
+ const char *path = NULL;
1176
+ char mode[15];
1177
+ gzFile fd;
1178
+
1179
+ snprintf(mode, sizeof(mode), "wb%d", compression);
1180
+ if (!strcmp(filename, "-")) {
1181
+ int duped_fd = dup(fileno(stdout));
1182
+ fd = gzdopen(duped_fd, "rb");
1183
+ if (fd == Z_NULL && duped_fd >= 0) {
1184
+ close(duped_fd); /* gzdOpen() does not close on failure */
1185
+ }
1186
+
1187
+ return((void *) fd);
1188
+ }
1189
+
1190
+ if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17))
1191
+ #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
1192
+ path = &filename[17];
1193
+ #else
1194
+ path = &filename[16];
1195
+ #endif
1196
+ else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
1197
+ #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
1198
+ path = &filename[8];
1199
+ #else
1200
+ path = &filename[7];
1201
+ #endif
1202
+ } else
1203
+ path = filename;
1204
+
1205
+ if (path == NULL)
1206
+ return(NULL);
1207
+
1208
+ #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
1209
+ fd = xmlWrapGzOpenUtf8(path, mode);
1210
+ #else
1211
+ fd = gzopen(path, mode);
1212
+ #endif
1213
+ return((void *) fd);
1214
+ }
1215
+ #endif /* LIBXML_OUTPUT_ENABLED */
1216
+
1217
+ /**
1218
+ * xmlGzfileRead:
1219
+ * @context: the I/O context
1220
+ * @buffer: where to drop data
1221
+ * @len: number of bytes to write
1222
+ *
1223
+ * Read @len bytes to @buffer from the compressed I/O channel.
1224
+ *
1225
+ * Returns the number of bytes read.
1226
+ */
1227
+ static int
1228
+ xmlGzfileRead (void * context, char * buffer, int len) {
1229
+ int ret;
1230
+
1231
+ ret = gzread((gzFile) context, &buffer[0], len);
1232
+ if (ret < 0) xmlIOErr(0, "gzread()");
1233
+ return(ret);
1234
+ }
1235
+
1236
+ #ifdef LIBXML_OUTPUT_ENABLED
1237
+ /**
1238
+ * xmlGzfileWrite:
1239
+ * @context: the I/O context
1240
+ * @buffer: where to drop data
1241
+ * @len: number of bytes to write
1242
+ *
1243
+ * Write @len bytes from @buffer to the compressed I/O channel.
1244
+ *
1245
+ * Returns the number of bytes written
1246
+ */
1247
+ static int
1248
+ xmlGzfileWrite (void * context, const char * buffer, int len) {
1249
+ int ret;
1250
+
1251
+ ret = gzwrite((gzFile) context, (char *) &buffer[0], len);
1252
+ if (ret < 0) xmlIOErr(0, "gzwrite()");
1253
+ return(ret);
1254
+ }
1255
+ #endif /* LIBXML_OUTPUT_ENABLED */
1256
+
1257
+ /**
1258
+ * xmlGzfileClose:
1259
+ * @context: the I/O context
1260
+ *
1261
+ * Close a compressed I/O channel
1262
+ */
1263
+ static int
1264
+ xmlGzfileClose (void * context) {
1265
+ int ret;
1266
+
1267
+ ret = (gzclose((gzFile) context) == Z_OK ) ? 0 : -1;
1268
+ if (ret < 0) xmlIOErr(0, "gzclose()");
1269
+ return(ret);
1270
+ }
1271
+ #endif /* LIBXML_ZLIB_ENABLED */
1272
+
1273
+ #ifdef LIBXML_LZMA_ENABLED
1274
+ /************************************************************************
1275
+ * *
1276
+ * I/O for compressed file accesses *
1277
+ * *
1278
+ ************************************************************************/
1279
+ #include "xzlib.h"
1280
+ /**
1281
+ * xmlXzfileMatch:
1282
+ * @filename: the URI for matching
1283
+ *
1284
+ * input from compressed file test
1285
+ *
1286
+ * Returns 1 if matches, 0 otherwise
1287
+ */
1288
+ static int
1289
+ xmlXzfileMatch (const char *filename ATTRIBUTE_UNUSED) {
1290
+ return(1);
1291
+ }
1292
+
1293
+ /**
1294
+ * xmlXzFileOpen_real:
1295
+ * @filename: the URI for matching
1296
+ *
1297
+ * input from compressed file open
1298
+ * if @filename is " " then the standard input is used
1299
+ *
1300
+ * Returns an I/O context or NULL in case of error
1301
+ */
1302
+ static void *
1303
+ xmlXzfileOpen_real (const char *filename) {
1304
+ const char *path = NULL;
1305
+ xzFile fd;
1306
+
1307
+ if (!strcmp(filename, "-")) {
1308
+ fd = __libxml2_xzdopen(dup(fileno(stdin)), "rb");
1309
+ return((void *) fd);
1310
+ }
1311
+
1312
+ if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17)) {
1313
+ path = &filename[16];
1314
+ } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
1315
+ path = &filename[7];
1316
+ } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:/", 6)) {
1317
+ /* lots of generators seems to lazy to read RFC 1738 */
1318
+ path = &filename[5];
1319
+ } else
1320
+ path = filename;
1321
+
1322
+ if (path == NULL)
1323
+ return(NULL);
1324
+ if (!xmlCheckFilename(path))
1325
+ return(NULL);
1326
+
1327
+ fd = __libxml2_xzopen(path, "rb");
1328
+ return((void *) fd);
1329
+ }
1330
+
1331
+ /**
1332
+ * xmlXzfileOpen:
1333
+ * @filename: the URI for matching
1334
+ *
1335
+ * Wrapper around xmlXzfileOpen_real that try it with an unescaped
1336
+ * version of @filename, if this fails fallback to @filename
1337
+ *
1338
+ * Returns a handler or NULL in case or failure
1339
+ */
1340
+ static void *
1341
+ xmlXzfileOpen (const char *filename) {
1342
+ char *unescaped;
1343
+ void *retval;
1344
+
1345
+ retval = xmlXzfileOpen_real(filename);
1346
+ if (retval == NULL) {
1347
+ unescaped = xmlURIUnescapeString(filename, 0, NULL);
1348
+ if (unescaped != NULL) {
1349
+ retval = xmlXzfileOpen_real(unescaped);
1350
+ }
1351
+ xmlFree(unescaped);
1352
+ }
1353
+
1354
+ return retval;
1355
+ }
1356
+
1357
+ /**
1358
+ * xmlXzfileRead:
1359
+ * @context: the I/O context
1360
+ * @buffer: where to drop data
1361
+ * @len: number of bytes to write
1362
+ *
1363
+ * Read @len bytes to @buffer from the compressed I/O channel.
1364
+ *
1365
+ * Returns the number of bytes written
1366
+ */
1367
+ static int
1368
+ xmlXzfileRead (void * context, char * buffer, int len) {
1369
+ int ret;
1370
+
1371
+ ret = __libxml2_xzread((xzFile) context, &buffer[0], len);
1372
+ if (ret < 0) xmlIOErr(0, "xzread()");
1373
+ return(ret);
1374
+ }
1375
+
1376
+ /**
1377
+ * xmlXzfileClose:
1378
+ * @context: the I/O context
1379
+ *
1380
+ * Close a compressed I/O channel
1381
+ */
1382
+ static int
1383
+ xmlXzfileClose (void * context) {
1384
+ int ret;
1385
+
1386
+ ret = (__libxml2_xzclose((xzFile) context) == LZMA_OK ) ? 0 : -1;
1387
+ if (ret < 0) xmlIOErr(0, "xzclose()");
1388
+ return(ret);
1389
+ }
1390
+ #endif /* LIBXML_LZMA_ENABLED */
1391
+
1392
+ #ifdef LIBXML_HTTP_ENABLED
1393
+ /************************************************************************
1394
+ * *
1395
+ * I/O for HTTP file accesses *
1396
+ * *
1397
+ ************************************************************************/
1398
+
1399
+ #ifdef LIBXML_OUTPUT_ENABLED
1400
+ typedef struct xmlIOHTTPWriteCtxt_
1401
+ {
1402
+ int compression;
1403
+
1404
+ char * uri;
1405
+
1406
+ void * doc_buff;
1407
+
1408
+ } xmlIOHTTPWriteCtxt, *xmlIOHTTPWriteCtxtPtr;
1409
+
1410
+ #ifdef LIBXML_ZLIB_ENABLED
1411
+
1412
+ #define DFLT_WBITS ( -15 )
1413
+ #define DFLT_MEM_LVL ( 8 )
1414
+ #define GZ_MAGIC1 ( 0x1f )
1415
+ #define GZ_MAGIC2 ( 0x8b )
1416
+ #define LXML_ZLIB_OS_CODE ( 0x03 )
1417
+ #define INIT_HTTP_BUFF_SIZE ( 32768 )
1418
+ #define DFLT_ZLIB_RATIO ( 5 )
1419
+
1420
+ /*
1421
+ ** Data structure and functions to work with sending compressed data
1422
+ ** via HTTP.
1423
+ */
1424
+
1425
+ typedef struct xmlZMemBuff_
1426
+ {
1427
+ unsigned long size;
1428
+ unsigned long crc;
1429
+
1430
+ unsigned char * zbuff;
1431
+ z_stream zctrl;
1432
+
1433
+ } xmlZMemBuff, *xmlZMemBuffPtr;
1434
+
1435
+ /**
1436
+ * append_reverse_ulong
1437
+ * @buff: Compressed memory buffer
1438
+ * @data: Unsigned long to append
1439
+ *
1440
+ * Append a unsigned long in reverse byte order to the end of the
1441
+ * memory buffer.
1442
+ */
1443
+ static void
1444
+ append_reverse_ulong( xmlZMemBuff * buff, unsigned long data ) {
1445
+
1446
+ int idx;
1447
+
1448
+ if ( buff == NULL )
1449
+ return;
1450
+
1451
+ /*
1452
+ ** This is plagiarized from putLong in gzio.c (zlib source) where
1453
+ ** the number "4" is hardcoded. If zlib is ever patched to
1454
+ ** support 64 bit file sizes, this code would need to be patched
1455
+ ** as well.
1456
+ */
1457
+
1458
+ for ( idx = 0; idx < 4; idx++ ) {
1459
+ *buff->zctrl.next_out = ( data & 0xff );
1460
+ data >>= 8;
1461
+ buff->zctrl.next_out++;
1462
+ }
1463
+
1464
+ return;
1465
+ }
1466
+
1467
+ /**
1468
+ *
1469
+ * xmlFreeZMemBuff
1470
+ * @buff: The memory buffer context to clear
1471
+ *
1472
+ * Release all the resources associated with the compressed memory buffer.
1473
+ */
1474
+ static void
1475
+ xmlFreeZMemBuff( xmlZMemBuffPtr buff ) {
1476
+
1477
+ #ifdef DEBUG_HTTP
1478
+ int z_err;
1479
+ #endif
1480
+
1481
+ if ( buff == NULL )
1482
+ return;
1483
+
1484
+ xmlFree( buff->zbuff );
1485
+ #ifdef DEBUG_HTTP
1486
+ z_err = deflateEnd( &buff->zctrl );
1487
+ if ( z_err != Z_OK )
1488
+ xmlGenericError( xmlGenericErrorContext,
1489
+ "xmlFreeZMemBuff: Error releasing zlib context: %d\n",
1490
+ z_err );
1491
+ #else
1492
+ deflateEnd( &buff->zctrl );
1493
+ #endif
1494
+
1495
+ xmlFree( buff );
1496
+ return;
1497
+ }
1498
+
1499
+ /**
1500
+ * xmlCreateZMemBuff
1501
+ *@compression: Compression value to use
1502
+ *
1503
+ * Create a memory buffer to hold the compressed XML document. The
1504
+ * compressed document in memory will end up being identical to what
1505
+ * would be created if gzopen/gzwrite/gzclose were being used to
1506
+ * write the document to disk. The code for the header/trailer data to
1507
+ * the compression is plagiarized from the zlib source files.
1508
+ */
1509
+ static void *
1510
+ xmlCreateZMemBuff( int compression ) {
1511
+
1512
+ int z_err;
1513
+ int hdr_lgth;
1514
+ xmlZMemBuffPtr buff = NULL;
1515
+
1516
+ if ( ( compression < 1 ) || ( compression > 9 ) )
1517
+ return ( NULL );
1518
+
1519
+ /* Create the control and data areas */
1520
+
1521
+ buff = xmlMalloc( sizeof( xmlZMemBuff ) );
1522
+ if ( buff == NULL ) {
1523
+ xmlIOErrMemory("creating buffer context");
1524
+ return ( NULL );
1525
+ }
1526
+
1527
+ (void)memset( buff, 0, sizeof( xmlZMemBuff ) );
1528
+ buff->size = INIT_HTTP_BUFF_SIZE;
1529
+ buff->zbuff = xmlMalloc( buff->size );
1530
+ if ( buff->zbuff == NULL ) {
1531
+ xmlFreeZMemBuff( buff );
1532
+ xmlIOErrMemory("creating buffer");
1533
+ return ( NULL );
1534
+ }
1535
+
1536
+ z_err = deflateInit2( &buff->zctrl, compression, Z_DEFLATED,
1537
+ DFLT_WBITS, DFLT_MEM_LVL, Z_DEFAULT_STRATEGY );
1538
+ if ( z_err != Z_OK ) {
1539
+ xmlChar msg[500];
1540
+ xmlFreeZMemBuff( buff );
1541
+ buff = NULL;
1542
+ xmlStrPrintf(msg, 500,
1543
+ "xmlCreateZMemBuff: %s %d\n",
1544
+ "Error initializing compression context. ZLIB error:",
1545
+ z_err );
1546
+ xmlIOErr(XML_IO_WRITE, (const char *) msg);
1547
+ return ( NULL );
1548
+ }
1549
+
1550
+ /* Set the header data. The CRC will be needed for the trailer */
1551
+ buff->crc = crc32( 0L, NULL, 0 );
1552
+ hdr_lgth = snprintf( (char *)buff->zbuff, buff->size,
1553
+ "%c%c%c%c%c%c%c%c%c%c",
1554
+ GZ_MAGIC1, GZ_MAGIC2, Z_DEFLATED,
1555
+ 0, 0, 0, 0, 0, 0, LXML_ZLIB_OS_CODE );
1556
+ buff->zctrl.next_out = buff->zbuff + hdr_lgth;
1557
+ buff->zctrl.avail_out = buff->size - hdr_lgth;
1558
+
1559
+ return ( buff );
1560
+ }
1561
+
1562
+ /**
1563
+ * xmlZMemBuffExtend
1564
+ * @buff: Buffer used to compress and consolidate data.
1565
+ * @ext_amt: Number of bytes to extend the buffer.
1566
+ *
1567
+ * Extend the internal buffer used to store the compressed data by the
1568
+ * specified amount.
1569
+ *
1570
+ * Returns 0 on success or -1 on failure to extend the buffer. On failure
1571
+ * the original buffer still exists at the original size.
1572
+ */
1573
+ static int
1574
+ xmlZMemBuffExtend( xmlZMemBuffPtr buff, size_t ext_amt ) {
1575
+
1576
+ int rc = -1;
1577
+ size_t new_size;
1578
+ size_t cur_used;
1579
+
1580
+ unsigned char * tmp_ptr = NULL;
1581
+
1582
+ if ( buff == NULL )
1583
+ return ( -1 );
1584
+
1585
+ else if ( ext_amt == 0 )
1586
+ return ( 0 );
1587
+
1588
+ cur_used = buff->zctrl.next_out - buff->zbuff;
1589
+ new_size = buff->size + ext_amt;
1590
+
1591
+ #ifdef DEBUG_HTTP
1592
+ if ( cur_used > new_size )
1593
+ xmlGenericError( xmlGenericErrorContext,
1594
+ "xmlZMemBuffExtend: %s\n%s %d bytes.\n",
1595
+ "Buffer overwrite detected during compressed memory",
1596
+ "buffer extension. Overflowed by",
1597
+ (cur_used - new_size ) );
1598
+ #endif
1599
+
1600
+ tmp_ptr = xmlRealloc( buff->zbuff, new_size );
1601
+ if ( tmp_ptr != NULL ) {
1602
+ rc = 0;
1603
+ buff->size = new_size;
1604
+ buff->zbuff = tmp_ptr;
1605
+ buff->zctrl.next_out = tmp_ptr + cur_used;
1606
+ buff->zctrl.avail_out = new_size - cur_used;
1607
+ }
1608
+ else {
1609
+ xmlChar msg[500];
1610
+ xmlStrPrintf(msg, 500,
1611
+ "xmlZMemBuffExtend: %s %lu bytes.\n",
1612
+ "Allocation failure extending output buffer to",
1613
+ (unsigned long) new_size );
1614
+ xmlIOErr(XML_IO_WRITE, (const char *) msg);
1615
+ }
1616
+
1617
+ return ( rc );
1618
+ }
1619
+
1620
+ /**
1621
+ * xmlZMemBuffAppend
1622
+ * @buff: Buffer used to compress and consolidate data
1623
+ * @src: Uncompressed source content to append to buffer
1624
+ * @len: Length of source data to append to buffer
1625
+ *
1626
+ * Compress and append data to the internal buffer. The data buffer
1627
+ * will be expanded if needed to store the additional data.
1628
+ *
1629
+ * Returns the number of bytes appended to the buffer or -1 on error.
1630
+ */
1631
+ static int
1632
+ xmlZMemBuffAppend( xmlZMemBuffPtr buff, const char * src, int len ) {
1633
+
1634
+ int z_err;
1635
+ size_t min_accept;
1636
+
1637
+ if ( ( buff == NULL ) || ( src == NULL ) )
1638
+ return ( -1 );
1639
+
1640
+ buff->zctrl.avail_in = len;
1641
+ buff->zctrl.next_in = (unsigned char *)src;
1642
+ while ( buff->zctrl.avail_in > 0 ) {
1643
+ /*
1644
+ ** Extend the buffer prior to deflate call if a reasonable amount
1645
+ ** of output buffer space is not available.
1646
+ */
1647
+ min_accept = buff->zctrl.avail_in / DFLT_ZLIB_RATIO;
1648
+ if ( buff->zctrl.avail_out <= min_accept ) {
1649
+ if ( xmlZMemBuffExtend( buff, buff->size ) == -1 )
1650
+ return ( -1 );
1651
+ }
1652
+
1653
+ z_err = deflate( &buff->zctrl, Z_NO_FLUSH );
1654
+ if ( z_err != Z_OK ) {
1655
+ xmlChar msg[500];
1656
+ xmlStrPrintf(msg, 500,
1657
+ "xmlZMemBuffAppend: %s %d %s - %d",
1658
+ "Compression error while appending",
1659
+ len, "bytes to buffer. ZLIB error", z_err );
1660
+ xmlIOErr(XML_IO_WRITE, (const char *) msg);
1661
+ return ( -1 );
1662
+ }
1663
+ }
1664
+
1665
+ buff->crc = crc32( buff->crc, (unsigned char *)src, len );
1666
+
1667
+ return ( len );
1668
+ }
1669
+
1670
+ /**
1671
+ * xmlZMemBuffGetContent
1672
+ * @buff: Compressed memory content buffer
1673
+ * @data_ref: Pointer reference to point to compressed content
1674
+ *
1675
+ * Flushes the compression buffers, appends gzip file trailers and
1676
+ * returns the compressed content and length of the compressed data.
1677
+ * NOTE: The gzip trailer code here is plagiarized from zlib source.
1678
+ *
1679
+ * Returns the length of the compressed data or -1 on error.
1680
+ */
1681
+ static int
1682
+ xmlZMemBuffGetContent( xmlZMemBuffPtr buff, char ** data_ref ) {
1683
+
1684
+ int zlgth = -1;
1685
+ int z_err;
1686
+
1687
+ if ( ( buff == NULL ) || ( data_ref == NULL ) )
1688
+ return ( -1 );
1689
+
1690
+ /* Need to loop until compression output buffers are flushed */
1691
+
1692
+ do
1693
+ {
1694
+ z_err = deflate( &buff->zctrl, Z_FINISH );
1695
+ if ( z_err == Z_OK ) {
1696
+ /* In this case Z_OK means more buffer space needed */
1697
+
1698
+ if ( xmlZMemBuffExtend( buff, buff->size ) == -1 )
1699
+ return ( -1 );
1700
+ }
1701
+ }
1702
+ while ( z_err == Z_OK );
1703
+
1704
+ /* If the compression state is not Z_STREAM_END, some error occurred */
1705
+
1706
+ if ( z_err == Z_STREAM_END ) {
1707
+
1708
+ /* Need to append the gzip data trailer */
1709
+
1710
+ if ( buff->zctrl.avail_out < ( 2 * sizeof( unsigned long ) ) ) {
1711
+ if ( xmlZMemBuffExtend(buff, (2 * sizeof(unsigned long))) == -1 )
1712
+ return ( -1 );
1713
+ }
1714
+
1715
+ /*
1716
+ ** For whatever reason, the CRC and length data are pushed out
1717
+ ** in reverse byte order. So a memcpy can't be used here.
1718
+ */
1719
+
1720
+ append_reverse_ulong( buff, buff->crc );
1721
+ append_reverse_ulong( buff, buff->zctrl.total_in );
1722
+
1723
+ zlgth = buff->zctrl.next_out - buff->zbuff;
1724
+ *data_ref = (char *)buff->zbuff;
1725
+ }
1726
+
1727
+ else {
1728
+ xmlChar msg[500];
1729
+ xmlStrPrintf(msg, 500,
1730
+ "xmlZMemBuffGetContent: %s - %d\n",
1731
+ "Error flushing zlib buffers. Error code", z_err );
1732
+ xmlIOErr(XML_IO_WRITE, (const char *) msg);
1733
+ }
1734
+
1735
+ return ( zlgth );
1736
+ }
1737
+ #endif /* LIBXML_OUTPUT_ENABLED */
1738
+ #endif /* LIBXML_ZLIB_ENABLED */
1739
+
1740
+ #ifdef LIBXML_OUTPUT_ENABLED
1741
+ /**
1742
+ * xmlFreeHTTPWriteCtxt
1743
+ * @ctxt: Context to cleanup
1744
+ *
1745
+ * Free allocated memory and reclaim system resources.
1746
+ *
1747
+ * No return value.
1748
+ */
1749
+ static void
1750
+ xmlFreeHTTPWriteCtxt( xmlIOHTTPWriteCtxtPtr ctxt )
1751
+ {
1752
+ if ( ctxt->uri != NULL )
1753
+ xmlFree( ctxt->uri );
1754
+
1755
+ if ( ctxt->doc_buff != NULL ) {
1756
+
1757
+ #ifdef LIBXML_ZLIB_ENABLED
1758
+ if ( ctxt->compression > 0 ) {
1759
+ xmlFreeZMemBuff( ctxt->doc_buff );
1760
+ }
1761
+ else
1762
+ #endif
1763
+ {
1764
+ xmlOutputBufferClose( ctxt->doc_buff );
1765
+ }
1766
+ }
1767
+
1768
+ xmlFree( ctxt );
1769
+ return;
1770
+ }
1771
+ #endif /* LIBXML_OUTPUT_ENABLED */
1772
+
1773
+
1774
+ /**
1775
+ * xmlIOHTTPMatch:
1776
+ * @filename: the URI for matching
1777
+ *
1778
+ * check if the URI matches an HTTP one
1779
+ *
1780
+ * Returns 1 if matches, 0 otherwise
1781
+ */
1782
+ int
1783
+ xmlIOHTTPMatch (const char *filename) {
1784
+ if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "http://", 7))
1785
+ return(1);
1786
+ return(0);
1787
+ }
1788
+
1789
+ /**
1790
+ * xmlIOHTTPOpen:
1791
+ * @filename: the URI for matching
1792
+ *
1793
+ * open an HTTP I/O channel
1794
+ *
1795
+ * Returns an I/O context or NULL in case of error
1796
+ */
1797
+ void *
1798
+ xmlIOHTTPOpen (const char *filename) {
1799
+ return(xmlNanoHTTPOpen(filename, NULL));
1800
+ }
1801
+
1802
+ #ifdef LIBXML_OUTPUT_ENABLED
1803
+ /**
1804
+ * xmlIOHTTPOpenW:
1805
+ * @post_uri: The destination URI for the document
1806
+ * @compression: The compression desired for the document.
1807
+ *
1808
+ * Open a temporary buffer to collect the document for a subsequent HTTP POST
1809
+ * request. Non-static as is called from the output buffer creation routine.
1810
+ *
1811
+ * Returns an I/O context or NULL in case of error.
1812
+ */
1813
+
1814
+ void *
1815
+ xmlIOHTTPOpenW(const char *post_uri, int compression ATTRIBUTE_UNUSED)
1816
+ {
1817
+
1818
+ xmlIOHTTPWriteCtxtPtr ctxt = NULL;
1819
+
1820
+ if (post_uri == NULL)
1821
+ return (NULL);
1822
+
1823
+ ctxt = xmlMalloc(sizeof(xmlIOHTTPWriteCtxt));
1824
+ if (ctxt == NULL) {
1825
+ xmlIOErrMemory("creating HTTP output context");
1826
+ return (NULL);
1827
+ }
1828
+
1829
+ (void) memset(ctxt, 0, sizeof(xmlIOHTTPWriteCtxt));
1830
+
1831
+ ctxt->uri = (char *) xmlStrdup((const xmlChar *)post_uri);
1832
+ if (ctxt->uri == NULL) {
1833
+ xmlIOErrMemory("copying URI");
1834
+ xmlFreeHTTPWriteCtxt(ctxt);
1835
+ return (NULL);
1836
+ }
1837
+
1838
+ /*
1839
+ * ** Since the document length is required for an HTTP post,
1840
+ * ** need to put the document into a buffer. A memory buffer
1841
+ * ** is being used to avoid pushing the data to disk and back.
1842
+ */
1843
+
1844
+ #ifdef LIBXML_ZLIB_ENABLED
1845
+ if ((compression > 0) && (compression <= 9)) {
1846
+
1847
+ ctxt->compression = compression;
1848
+ ctxt->doc_buff = xmlCreateZMemBuff(compression);
1849
+ } else
1850
+ #endif
1851
+ {
1852
+ /* Any character conversions should have been done before this */
1853
+
1854
+ ctxt->doc_buff = xmlAllocOutputBufferInternal(NULL);
1855
+ }
1856
+
1857
+ if (ctxt->doc_buff == NULL) {
1858
+ xmlFreeHTTPWriteCtxt(ctxt);
1859
+ ctxt = NULL;
1860
+ }
1861
+
1862
+ return (ctxt);
1863
+ }
1864
+ #endif /* LIBXML_OUTPUT_ENABLED */
1865
+
1866
+ #ifdef LIBXML_OUTPUT_ENABLED
1867
+ /**
1868
+ * xmlIOHTTPDfltOpenW
1869
+ * @post_uri: The destination URI for this document.
1870
+ *
1871
+ * Calls xmlIOHTTPOpenW with no compression to set up for a subsequent
1872
+ * HTTP post command. This function should generally not be used as
1873
+ * the open callback is short circuited in xmlOutputBufferCreateFile.
1874
+ *
1875
+ * Returns a pointer to the new IO context.
1876
+ */
1877
+ static void *
1878
+ xmlIOHTTPDfltOpenW( const char * post_uri ) {
1879
+ return ( xmlIOHTTPOpenW( post_uri, 0 ) );
1880
+ }
1881
+ #endif /* LIBXML_OUTPUT_ENABLED */
1882
+
1883
+ /**
1884
+ * xmlIOHTTPRead:
1885
+ * @context: the I/O context
1886
+ * @buffer: where to drop data
1887
+ * @len: number of bytes to write
1888
+ *
1889
+ * Read @len bytes to @buffer from the I/O channel.
1890
+ *
1891
+ * Returns the number of bytes written
1892
+ */
1893
+ int
1894
+ xmlIOHTTPRead(void * context, char * buffer, int len) {
1895
+ if ((buffer == NULL) || (len < 0)) return(-1);
1896
+ return(xmlNanoHTTPRead(context, &buffer[0], len));
1897
+ }
1898
+
1899
+ #ifdef LIBXML_OUTPUT_ENABLED
1900
+ /**
1901
+ * xmlIOHTTPWrite
1902
+ * @context: previously opened writing context
1903
+ * @buffer: data to output to temporary buffer
1904
+ * @len: bytes to output
1905
+ *
1906
+ * Collect data from memory buffer into a temporary file for later
1907
+ * processing.
1908
+ *
1909
+ * Returns number of bytes written.
1910
+ */
1911
+
1912
+ static int
1913
+ xmlIOHTTPWrite( void * context, const char * buffer, int len ) {
1914
+
1915
+ xmlIOHTTPWriteCtxtPtr ctxt = context;
1916
+
1917
+ if ( ( ctxt == NULL ) || ( ctxt->doc_buff == NULL ) || ( buffer == NULL ) )
1918
+ return ( -1 );
1919
+
1920
+ if ( len > 0 ) {
1921
+
1922
+ /* Use gzwrite or fwrite as previously setup in the open call */
1923
+
1924
+ #ifdef LIBXML_ZLIB_ENABLED
1925
+ if ( ctxt->compression > 0 )
1926
+ len = xmlZMemBuffAppend( ctxt->doc_buff, buffer, len );
1927
+
1928
+ else
1929
+ #endif
1930
+ len = xmlOutputBufferWrite( ctxt->doc_buff, len, buffer );
1931
+
1932
+ if ( len < 0 ) {
1933
+ xmlChar msg[500];
1934
+ xmlStrPrintf(msg, 500,
1935
+ "xmlIOHTTPWrite: %s\n%s '%s'.\n",
1936
+ "Error appending to internal buffer.",
1937
+ "Error sending document to URI",
1938
+ ctxt->uri );
1939
+ xmlIOErr(XML_IO_WRITE, (const char *) msg);
1940
+ }
1941
+ }
1942
+
1943
+ return ( len );
1944
+ }
1945
+ #endif /* LIBXML_OUTPUT_ENABLED */
1946
+
1947
+
1948
+ /**
1949
+ * xmlIOHTTPClose:
1950
+ * @context: the I/O context
1951
+ *
1952
+ * Close an HTTP I/O channel
1953
+ *
1954
+ * Returns 0
1955
+ */
1956
+ int
1957
+ xmlIOHTTPClose (void * context) {
1958
+ xmlNanoHTTPClose(context);
1959
+ return 0;
1960
+ }
1961
+
1962
+ #ifdef LIBXML_OUTPUT_ENABLED
1963
+ /**
1964
+ * xmlIOHTTCloseWrite
1965
+ * @context: The I/O context
1966
+ * @http_mthd: The HTTP method to be used when sending the data
1967
+ *
1968
+ * Close the transmit HTTP I/O channel and actually send the data.
1969
+ */
1970
+ static int
1971
+ xmlIOHTTPCloseWrite( void * context, const char * http_mthd ) {
1972
+
1973
+ int close_rc = -1;
1974
+ int http_rtn = 0;
1975
+ int content_lgth = 0;
1976
+ xmlIOHTTPWriteCtxtPtr ctxt = context;
1977
+
1978
+ char * http_content = NULL;
1979
+ char * content_encoding = NULL;
1980
+ char * content_type = (char *) "text/xml";
1981
+ void * http_ctxt = NULL;
1982
+
1983
+ if ( ( ctxt == NULL ) || ( http_mthd == NULL ) )
1984
+ return ( -1 );
1985
+
1986
+ /* Retrieve the content from the appropriate buffer */
1987
+
1988
+ #ifdef LIBXML_ZLIB_ENABLED
1989
+
1990
+ if ( ctxt->compression > 0 ) {
1991
+ content_lgth = xmlZMemBuffGetContent( ctxt->doc_buff, &http_content );
1992
+ content_encoding = (char *) "Content-Encoding: gzip";
1993
+ }
1994
+ else
1995
+ #endif
1996
+ {
1997
+ /* Pull the data out of the memory output buffer */
1998
+
1999
+ xmlOutputBufferPtr dctxt = ctxt->doc_buff;
2000
+ http_content = (char *) xmlBufContent(dctxt->buffer);
2001
+ content_lgth = xmlBufUse(dctxt->buffer);
2002
+ }
2003
+
2004
+ if ( http_content == NULL ) {
2005
+ xmlChar msg[500];
2006
+ xmlStrPrintf(msg, 500,
2007
+ "xmlIOHTTPCloseWrite: %s '%s' %s '%s'.\n",
2008
+ "Error retrieving content.\nUnable to",
2009
+ http_mthd, "data to URI", ctxt->uri );
2010
+ xmlIOErr(XML_IO_WRITE, (const char *) msg);
2011
+ }
2012
+
2013
+ else {
2014
+
2015
+ http_ctxt = xmlNanoHTTPMethod( ctxt->uri, http_mthd, http_content,
2016
+ &content_type, content_encoding,
2017
+ content_lgth );
2018
+
2019
+ if ( http_ctxt != NULL ) {
2020
+ #ifdef DEBUG_HTTP
2021
+ /* If testing/debugging - dump reply with request content */
2022
+
2023
+ FILE * tst_file = NULL;
2024
+ char buffer[ 4096 ];
2025
+ char * dump_name = NULL;
2026
+ int avail;
2027
+
2028
+ xmlGenericError( xmlGenericErrorContext,
2029
+ "xmlNanoHTTPCloseWrite: HTTP %s to\n%s returned %d.\n",
2030
+ http_mthd, ctxt->uri,
2031
+ xmlNanoHTTPReturnCode( http_ctxt ) );
2032
+
2033
+ /*
2034
+ ** Since either content or reply may be gzipped,
2035
+ ** dump them to separate files instead of the
2036
+ ** standard error context.
2037
+ */
2038
+
2039
+ dump_name = tempnam( NULL, "lxml" );
2040
+ if ( dump_name != NULL ) {
2041
+ (void)snprintf( buffer, sizeof(buffer), "%s.content", dump_name );
2042
+
2043
+ tst_file = fopen( buffer, "wb" );
2044
+ if ( tst_file != NULL ) {
2045
+ xmlGenericError( xmlGenericErrorContext,
2046
+ "Transmitted content saved in file: %s\n", buffer );
2047
+
2048
+ fwrite( http_content, sizeof( char ),
2049
+ content_lgth, tst_file );
2050
+ fclose( tst_file );
2051
+ }
2052
+
2053
+ (void)snprintf( buffer, sizeof(buffer), "%s.reply", dump_name );
2054
+ tst_file = fopen( buffer, "wb" );
2055
+ if ( tst_file != NULL ) {
2056
+ xmlGenericError( xmlGenericErrorContext,
2057
+ "Reply content saved in file: %s\n", buffer );
2058
+
2059
+
2060
+ while ( (avail = xmlNanoHTTPRead( http_ctxt,
2061
+ buffer, sizeof( buffer ) )) > 0 ) {
2062
+
2063
+ fwrite( buffer, sizeof( char ), avail, tst_file );
2064
+ }
2065
+
2066
+ fclose( tst_file );
2067
+ }
2068
+
2069
+ free( dump_name );
2070
+ }
2071
+ #endif /* DEBUG_HTTP */
2072
+
2073
+ http_rtn = xmlNanoHTTPReturnCode( http_ctxt );
2074
+ if ( ( http_rtn >= 200 ) && ( http_rtn < 300 ) )
2075
+ close_rc = 0;
2076
+ else {
2077
+ xmlChar msg[500];
2078
+ xmlStrPrintf(msg, 500,
2079
+ "xmlIOHTTPCloseWrite: HTTP '%s' of %d %s\n'%s' %s %d\n",
2080
+ http_mthd, content_lgth,
2081
+ "bytes to URI", ctxt->uri,
2082
+ "failed. HTTP return code:", http_rtn );
2083
+ xmlIOErr(XML_IO_WRITE, (const char *) msg);
2084
+ }
2085
+
2086
+ xmlNanoHTTPClose( http_ctxt );
2087
+ xmlFree( content_type );
2088
+ }
2089
+ }
2090
+
2091
+ /* Final cleanups */
2092
+
2093
+ xmlFreeHTTPWriteCtxt( ctxt );
2094
+
2095
+ return ( close_rc );
2096
+ }
2097
+
2098
+ /**
2099
+ * xmlIOHTTPClosePut
2100
+ *
2101
+ * @context: The I/O context
2102
+ *
2103
+ * Close the transmit HTTP I/O channel and actually send data using a PUT
2104
+ * HTTP method.
2105
+ */
2106
+ static int
2107
+ xmlIOHTTPClosePut( void * ctxt ) {
2108
+ return ( xmlIOHTTPCloseWrite( ctxt, "PUT" ) );
2109
+ }
2110
+
2111
+
2112
+ /**
2113
+ * xmlIOHTTPClosePost
2114
+ *
2115
+ * @context: The I/O context
2116
+ *
2117
+ * Close the transmit HTTP I/O channel and actually send data using a POST
2118
+ * HTTP method.
2119
+ */
2120
+ static int
2121
+ xmlIOHTTPClosePost( void * ctxt ) {
2122
+ return ( xmlIOHTTPCloseWrite( ctxt, "POST" ) );
2123
+ }
2124
+ #endif /* LIBXML_OUTPUT_ENABLED */
2125
+
2126
+ #endif /* LIBXML_HTTP_ENABLED */
2127
+
2128
+ #ifdef LIBXML_FTP_ENABLED
2129
+ /************************************************************************
2130
+ * *
2131
+ * I/O for FTP file accesses *
2132
+ * *
2133
+ ************************************************************************/
2134
+ /**
2135
+ * xmlIOFTPMatch:
2136
+ * @filename: the URI for matching
2137
+ *
2138
+ * check if the URI matches an FTP one
2139
+ *
2140
+ * Returns 1 if matches, 0 otherwise
2141
+ */
2142
+ int
2143
+ xmlIOFTPMatch (const char *filename) {
2144
+ if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "ftp://", 6))
2145
+ return(1);
2146
+ return(0);
2147
+ }
2148
+
2149
+ /**
2150
+ * xmlIOFTPOpen:
2151
+ * @filename: the URI for matching
2152
+ *
2153
+ * open an FTP I/O channel
2154
+ *
2155
+ * Returns an I/O context or NULL in case of error
2156
+ */
2157
+ void *
2158
+ xmlIOFTPOpen (const char *filename) {
2159
+ return(xmlNanoFTPOpen(filename));
2160
+ }
2161
+
2162
+ /**
2163
+ * xmlIOFTPRead:
2164
+ * @context: the I/O context
2165
+ * @buffer: where to drop data
2166
+ * @len: number of bytes to write
2167
+ *
2168
+ * Read @len bytes to @buffer from the I/O channel.
2169
+ *
2170
+ * Returns the number of bytes written
2171
+ */
2172
+ int
2173
+ xmlIOFTPRead(void * context, char * buffer, int len) {
2174
+ if ((buffer == NULL) || (len < 0)) return(-1);
2175
+ return(xmlNanoFTPRead(context, &buffer[0], len));
2176
+ }
2177
+
2178
+ /**
2179
+ * xmlIOFTPClose:
2180
+ * @context: the I/O context
2181
+ *
2182
+ * Close an FTP I/O channel
2183
+ *
2184
+ * Returns 0
2185
+ */
2186
+ int
2187
+ xmlIOFTPClose (void * context) {
2188
+ return ( xmlNanoFTPClose(context) );
2189
+ }
2190
+ #endif /* LIBXML_FTP_ENABLED */
2191
+
2192
+
2193
+ /**
2194
+ * xmlRegisterInputCallbacks:
2195
+ * @matchFunc: the xmlInputMatchCallback
2196
+ * @openFunc: the xmlInputOpenCallback
2197
+ * @readFunc: the xmlInputReadCallback
2198
+ * @closeFunc: the xmlInputCloseCallback
2199
+ *
2200
+ * Register a new set of I/O callback for handling parser input.
2201
+ *
2202
+ * Returns the registered handler number or -1 in case of error
2203
+ */
2204
+ int
2205
+ xmlRegisterInputCallbacks(xmlInputMatchCallback matchFunc,
2206
+ xmlInputOpenCallback openFunc, xmlInputReadCallback readFunc,
2207
+ xmlInputCloseCallback closeFunc) {
2208
+ if (xmlInputCallbackNr >= MAX_INPUT_CALLBACK) {
2209
+ return(-1);
2210
+ }
2211
+ xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = matchFunc;
2212
+ xmlInputCallbackTable[xmlInputCallbackNr].opencallback = openFunc;
2213
+ xmlInputCallbackTable[xmlInputCallbackNr].readcallback = readFunc;
2214
+ xmlInputCallbackTable[xmlInputCallbackNr].closecallback = closeFunc;
2215
+ xmlInputCallbackInitialized = 1;
2216
+ return(xmlInputCallbackNr++);
2217
+ }
2218
+
2219
+ #ifdef LIBXML_OUTPUT_ENABLED
2220
+ /**
2221
+ * xmlRegisterOutputCallbacks:
2222
+ * @matchFunc: the xmlOutputMatchCallback
2223
+ * @openFunc: the xmlOutputOpenCallback
2224
+ * @writeFunc: the xmlOutputWriteCallback
2225
+ * @closeFunc: the xmlOutputCloseCallback
2226
+ *
2227
+ * Register a new set of I/O callback for handling output.
2228
+ *
2229
+ * Returns the registered handler number or -1 in case of error
2230
+ */
2231
+ int
2232
+ xmlRegisterOutputCallbacks(xmlOutputMatchCallback matchFunc,
2233
+ xmlOutputOpenCallback openFunc, xmlOutputWriteCallback writeFunc,
2234
+ xmlOutputCloseCallback closeFunc) {
2235
+ if (xmlOutputCallbackNr >= MAX_OUTPUT_CALLBACK) {
2236
+ return(-1);
2237
+ }
2238
+ xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = matchFunc;
2239
+ xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = openFunc;
2240
+ xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = writeFunc;
2241
+ xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = closeFunc;
2242
+ xmlOutputCallbackInitialized = 1;
2243
+ return(xmlOutputCallbackNr++);
2244
+ }
2245
+ #endif /* LIBXML_OUTPUT_ENABLED */
2246
+
2247
+ /**
2248
+ * xmlRegisterDefaultInputCallbacks:
2249
+ *
2250
+ * Registers the default compiled-in I/O handlers.
2251
+ */
2252
+ void
2253
+ xmlRegisterDefaultInputCallbacks(void) {
2254
+ if (xmlInputCallbackInitialized)
2255
+ return;
2256
+
2257
+ xmlRegisterInputCallbacks(xmlFileMatch, xmlFileOpen,
2258
+ xmlFileRead, xmlFileClose);
2259
+ #ifdef LIBXML_ZLIB_ENABLED
2260
+ xmlRegisterInputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
2261
+ xmlGzfileRead, xmlGzfileClose);
2262
+ #endif /* LIBXML_ZLIB_ENABLED */
2263
+ #ifdef LIBXML_LZMA_ENABLED
2264
+ xmlRegisterInputCallbacks(xmlXzfileMatch, xmlXzfileOpen,
2265
+ xmlXzfileRead, xmlXzfileClose);
2266
+ #endif /* LIBXML_LZMA_ENABLED */
2267
+
2268
+ #ifdef LIBXML_HTTP_ENABLED
2269
+ xmlRegisterInputCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen,
2270
+ xmlIOHTTPRead, xmlIOHTTPClose);
2271
+ #endif /* LIBXML_HTTP_ENABLED */
2272
+
2273
+ #ifdef LIBXML_FTP_ENABLED
2274
+ xmlRegisterInputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
2275
+ xmlIOFTPRead, xmlIOFTPClose);
2276
+ #endif /* LIBXML_FTP_ENABLED */
2277
+ xmlInputCallbackInitialized = 1;
2278
+ }
2279
+
2280
+ #ifdef LIBXML_OUTPUT_ENABLED
2281
+ /**
2282
+ * xmlRegisterDefaultOutputCallbacks:
2283
+ *
2284
+ * Registers the default compiled-in I/O handlers.
2285
+ */
2286
+ void
2287
+ xmlRegisterDefaultOutputCallbacks (void) {
2288
+ if (xmlOutputCallbackInitialized)
2289
+ return;
2290
+
2291
+ xmlRegisterOutputCallbacks(xmlFileMatch, xmlFileOpenW,
2292
+ xmlFileWrite, xmlFileClose);
2293
+
2294
+ #ifdef LIBXML_HTTP_ENABLED
2295
+ xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPDfltOpenW,
2296
+ xmlIOHTTPWrite, xmlIOHTTPClosePut);
2297
+ #endif
2298
+
2299
+ /*********************************
2300
+ No way a-priori to distinguish between gzipped files from
2301
+ uncompressed ones except opening if existing then closing
2302
+ and saving with same compression ratio ... a pain.
2303
+
2304
+ #ifdef LIBXML_ZLIB_ENABLED
2305
+ xmlRegisterOutputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
2306
+ xmlGzfileWrite, xmlGzfileClose);
2307
+ #endif
2308
+
2309
+ Nor FTP PUT ....
2310
+ #ifdef LIBXML_FTP_ENABLED
2311
+ xmlRegisterOutputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
2312
+ xmlIOFTPWrite, xmlIOFTPClose);
2313
+ #endif
2314
+ **********************************/
2315
+ xmlOutputCallbackInitialized = 1;
2316
+ }
2317
+
2318
+ #ifdef LIBXML_HTTP_ENABLED
2319
+ /**
2320
+ * xmlRegisterHTTPPostCallbacks:
2321
+ *
2322
+ * By default, libxml submits HTTP output requests using the "PUT" method.
2323
+ * Calling this method changes the HTTP output method to use the "POST"
2324
+ * method instead.
2325
+ *
2326
+ */
2327
+ void
2328
+ xmlRegisterHTTPPostCallbacks( void ) {
2329
+
2330
+ /* Register defaults if not done previously */
2331
+
2332
+ if ( xmlOutputCallbackInitialized == 0 )
2333
+ xmlRegisterDefaultOutputCallbacks( );
2334
+
2335
+ xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPDfltOpenW,
2336
+ xmlIOHTTPWrite, xmlIOHTTPClosePost);
2337
+ return;
2338
+ }
2339
+ #endif
2340
+ #endif /* LIBXML_OUTPUT_ENABLED */
2341
+
2342
+ /**
2343
+ * xmlAllocParserInputBuffer:
2344
+ * @enc: the charset encoding if known
2345
+ *
2346
+ * Create a buffered parser input for progressive parsing
2347
+ *
2348
+ * Returns the new parser input or NULL
2349
+ */
2350
+ xmlParserInputBufferPtr
2351
+ xmlAllocParserInputBuffer(xmlCharEncoding enc) {
2352
+ xmlParserInputBufferPtr ret;
2353
+
2354
+ ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
2355
+ if (ret == NULL) {
2356
+ xmlIOErrMemory("creating input buffer");
2357
+ return(NULL);
2358
+ }
2359
+ memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
2360
+ ret->buffer = xmlBufCreateSize(2 * xmlDefaultBufferSize);
2361
+ if (ret->buffer == NULL) {
2362
+ xmlFree(ret);
2363
+ return(NULL);
2364
+ }
2365
+ xmlBufSetAllocationScheme(ret->buffer, XML_BUFFER_ALLOC_DOUBLEIT);
2366
+ ret->encoder = xmlGetCharEncodingHandler(enc);
2367
+ if (ret->encoder != NULL)
2368
+ ret->raw = xmlBufCreateSize(2 * xmlDefaultBufferSize);
2369
+ else
2370
+ ret->raw = NULL;
2371
+ ret->readcallback = NULL;
2372
+ ret->closecallback = NULL;
2373
+ ret->context = NULL;
2374
+ ret->compressed = -1;
2375
+ ret->rawconsumed = 0;
2376
+
2377
+ return(ret);
2378
+ }
2379
+
2380
+ #ifdef LIBXML_OUTPUT_ENABLED
2381
+ /**
2382
+ * xmlAllocOutputBuffer:
2383
+ * @encoder: the encoding converter or NULL
2384
+ *
2385
+ * Create a buffered parser output
2386
+ *
2387
+ * Returns the new parser output or NULL
2388
+ */
2389
+ xmlOutputBufferPtr
2390
+ xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder) {
2391
+ xmlOutputBufferPtr ret;
2392
+
2393
+ ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
2394
+ if (ret == NULL) {
2395
+ xmlIOErrMemory("creating output buffer");
2396
+ return(NULL);
2397
+ }
2398
+ memset(ret, 0, (size_t) sizeof(xmlOutputBuffer));
2399
+ ret->buffer = xmlBufCreate();
2400
+ if (ret->buffer == NULL) {
2401
+ xmlFree(ret);
2402
+ return(NULL);
2403
+ }
2404
+
2405
+ /* try to avoid a performance problem with Windows realloc() */
2406
+ if (xmlBufGetAllocationScheme(ret->buffer) == XML_BUFFER_ALLOC_EXACT)
2407
+ xmlBufSetAllocationScheme(ret->buffer, XML_BUFFER_ALLOC_DOUBLEIT);
2408
+
2409
+ ret->encoder = encoder;
2410
+ if (encoder != NULL) {
2411
+ ret->conv = xmlBufCreateSize(4000);
2412
+ if (ret->conv == NULL) {
2413
+ xmlBufFree(ret->buffer);
2414
+ xmlFree(ret);
2415
+ return(NULL);
2416
+ }
2417
+
2418
+ /*
2419
+ * This call is designed to initiate the encoder state
2420
+ */
2421
+ xmlCharEncOutput(ret, 1);
2422
+ } else
2423
+ ret->conv = NULL;
2424
+ ret->writecallback = NULL;
2425
+ ret->closecallback = NULL;
2426
+ ret->context = NULL;
2427
+ ret->written = 0;
2428
+
2429
+ return(ret);
2430
+ }
2431
+
2432
+ /**
2433
+ * xmlAllocOutputBufferInternal:
2434
+ * @encoder: the encoding converter or NULL
2435
+ *
2436
+ * Create a buffered parser output
2437
+ *
2438
+ * Returns the new parser output or NULL
2439
+ */
2440
+ xmlOutputBufferPtr
2441
+ xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder) {
2442
+ xmlOutputBufferPtr ret;
2443
+
2444
+ ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
2445
+ if (ret == NULL) {
2446
+ xmlIOErrMemory("creating output buffer");
2447
+ return(NULL);
2448
+ }
2449
+ memset(ret, 0, (size_t) sizeof(xmlOutputBuffer));
2450
+ ret->buffer = xmlBufCreate();
2451
+ if (ret->buffer == NULL) {
2452
+ xmlFree(ret);
2453
+ return(NULL);
2454
+ }
2455
+
2456
+
2457
+ /*
2458
+ * For conversion buffers we use the special IO handling
2459
+ */
2460
+ xmlBufSetAllocationScheme(ret->buffer, XML_BUFFER_ALLOC_IO);
2461
+
2462
+ ret->encoder = encoder;
2463
+ if (encoder != NULL) {
2464
+ ret->conv = xmlBufCreateSize(4000);
2465
+ if (ret->conv == NULL) {
2466
+ xmlBufFree(ret->buffer);
2467
+ xmlFree(ret);
2468
+ return(NULL);
2469
+ }
2470
+
2471
+ /*
2472
+ * This call is designed to initiate the encoder state
2473
+ */
2474
+ xmlCharEncOutput(ret, 1);
2475
+ } else
2476
+ ret->conv = NULL;
2477
+ ret->writecallback = NULL;
2478
+ ret->closecallback = NULL;
2479
+ ret->context = NULL;
2480
+ ret->written = 0;
2481
+
2482
+ return(ret);
2483
+ }
2484
+
2485
+ #endif /* LIBXML_OUTPUT_ENABLED */
2486
+
2487
+ /**
2488
+ * xmlFreeParserInputBuffer:
2489
+ * @in: a buffered parser input
2490
+ *
2491
+ * Free up the memory used by a buffered parser input
2492
+ */
2493
+ void
2494
+ xmlFreeParserInputBuffer(xmlParserInputBufferPtr in) {
2495
+ if (in == NULL) return;
2496
+
2497
+ if (in->raw) {
2498
+ xmlBufFree(in->raw);
2499
+ in->raw = NULL;
2500
+ }
2501
+ if (in->encoder != NULL) {
2502
+ xmlCharEncCloseFunc(in->encoder);
2503
+ }
2504
+ if (in->closecallback != NULL) {
2505
+ in->closecallback(in->context);
2506
+ }
2507
+ if (in->buffer != NULL) {
2508
+ xmlBufFree(in->buffer);
2509
+ in->buffer = NULL;
2510
+ }
2511
+
2512
+ xmlFree(in);
2513
+ }
2514
+
2515
+ #ifdef LIBXML_OUTPUT_ENABLED
2516
+ /**
2517
+ * xmlOutputBufferClose:
2518
+ * @out: a buffered output
2519
+ *
2520
+ * flushes and close the output I/O channel
2521
+ * and free up all the associated resources
2522
+ *
2523
+ * Returns the number of byte written or -1 in case of error.
2524
+ */
2525
+ int
2526
+ xmlOutputBufferClose(xmlOutputBufferPtr out)
2527
+ {
2528
+ int written;
2529
+ int err_rc = 0;
2530
+
2531
+ if (out == NULL)
2532
+ return (-1);
2533
+ if (out->writecallback != NULL)
2534
+ xmlOutputBufferFlush(out);
2535
+ if (out->closecallback != NULL) {
2536
+ err_rc = out->closecallback(out->context);
2537
+ }
2538
+ written = out->written;
2539
+ if (out->conv) {
2540
+ xmlBufFree(out->conv);
2541
+ out->conv = NULL;
2542
+ }
2543
+ if (out->encoder != NULL) {
2544
+ xmlCharEncCloseFunc(out->encoder);
2545
+ }
2546
+ if (out->buffer != NULL) {
2547
+ xmlBufFree(out->buffer);
2548
+ out->buffer = NULL;
2549
+ }
2550
+
2551
+ if (out->error)
2552
+ err_rc = -1;
2553
+ xmlFree(out);
2554
+ return ((err_rc == 0) ? written : err_rc);
2555
+ }
2556
+ #endif /* LIBXML_OUTPUT_ENABLED */
2557
+
2558
+ xmlParserInputBufferPtr
2559
+ __xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
2560
+ xmlParserInputBufferPtr ret;
2561
+ int i = 0;
2562
+ void *context = NULL;
2563
+
2564
+ if (xmlInputCallbackInitialized == 0)
2565
+ xmlRegisterDefaultInputCallbacks();
2566
+
2567
+ if (URI == NULL) return(NULL);
2568
+
2569
+ /*
2570
+ * Try to find one of the input accept method accepting that scheme
2571
+ * Go in reverse to give precedence to user defined handlers.
2572
+ */
2573
+ if (context == NULL) {
2574
+ for (i = xmlInputCallbackNr - 1;i >= 0;i--) {
2575
+ if ((xmlInputCallbackTable[i].matchcallback != NULL) &&
2576
+ (xmlInputCallbackTable[i].matchcallback(URI) != 0)) {
2577
+ context = xmlInputCallbackTable[i].opencallback(URI);
2578
+ if (context != NULL) {
2579
+ break;
2580
+ }
2581
+ }
2582
+ }
2583
+ }
2584
+ if (context == NULL) {
2585
+ return(NULL);
2586
+ }
2587
+
2588
+ /*
2589
+ * Allocate the Input buffer front-end.
2590
+ */
2591
+ ret = xmlAllocParserInputBuffer(enc);
2592
+ if (ret != NULL) {
2593
+ ret->context = context;
2594
+ ret->readcallback = xmlInputCallbackTable[i].readcallback;
2595
+ ret->closecallback = xmlInputCallbackTable[i].closecallback;
2596
+ #ifdef LIBXML_ZLIB_ENABLED
2597
+ if ((xmlInputCallbackTable[i].opencallback == xmlGzfileOpen) &&
2598
+ (strcmp(URI, "-") != 0)) {
2599
+ #if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1230
2600
+ ret->compressed = !gzdirect(context);
2601
+ #else
2602
+ if (((z_stream *)context)->avail_in > 4) {
2603
+ char *cptr, buff4[4];
2604
+ cptr = (char *) ((z_stream *)context)->next_in;
2605
+ if (gzread(context, buff4, 4) == 4) {
2606
+ if (strncmp(buff4, cptr, 4) == 0)
2607
+ ret->compressed = 0;
2608
+ else
2609
+ ret->compressed = 1;
2610
+ gzrewind(context);
2611
+ }
2612
+ }
2613
+ #endif
2614
+ }
2615
+ #endif
2616
+ #ifdef LIBXML_LZMA_ENABLED
2617
+ if ((xmlInputCallbackTable[i].opencallback == xmlXzfileOpen) &&
2618
+ (strcmp(URI, "-") != 0)) {
2619
+ ret->compressed = __libxml2_xzcompressed(context);
2620
+ }
2621
+ #endif
2622
+ }
2623
+ else
2624
+ xmlInputCallbackTable[i].closecallback (context);
2625
+
2626
+ return(ret);
2627
+ }
2628
+
2629
+ /**
2630
+ * xmlParserInputBufferCreateFilename:
2631
+ * @URI: a C string containing the URI or filename
2632
+ * @enc: the charset encoding if known
2633
+ *
2634
+ * Create a buffered parser input for the progressive parsing of a file
2635
+ * If filename is "-' then we use stdin as the input.
2636
+ * Automatic support for ZLIB/Compress compressed document is provided
2637
+ * by default if found at compile-time.
2638
+ * Do an encoding check if enc == XML_CHAR_ENCODING_NONE
2639
+ *
2640
+ * Returns the new parser input or NULL
2641
+ */
2642
+ xmlParserInputBufferPtr
2643
+ xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
2644
+ if ((xmlParserInputBufferCreateFilenameValue)) {
2645
+ return xmlParserInputBufferCreateFilenameValue(URI, enc);
2646
+ }
2647
+ return __xmlParserInputBufferCreateFilename(URI, enc);
2648
+ }
2649
+
2650
+ #ifdef LIBXML_OUTPUT_ENABLED
2651
+ xmlOutputBufferPtr
2652
+ __xmlOutputBufferCreateFilename(const char *URI,
2653
+ xmlCharEncodingHandlerPtr encoder,
2654
+ int compression ATTRIBUTE_UNUSED) {
2655
+ xmlOutputBufferPtr ret;
2656
+ xmlURIPtr puri;
2657
+ int i = 0;
2658
+ void *context = NULL;
2659
+ char *unescaped = NULL;
2660
+ #ifdef LIBXML_ZLIB_ENABLED
2661
+ int is_file_uri = 1;
2662
+ #endif
2663
+
2664
+ if (xmlOutputCallbackInitialized == 0)
2665
+ xmlRegisterDefaultOutputCallbacks();
2666
+
2667
+ if (URI == NULL) return(NULL);
2668
+
2669
+ puri = xmlParseURI(URI);
2670
+ if (puri != NULL) {
2671
+ #ifdef LIBXML_ZLIB_ENABLED
2672
+ if ((puri->scheme != NULL) &&
2673
+ (!xmlStrEqual(BAD_CAST puri->scheme, BAD_CAST "file")))
2674
+ is_file_uri = 0;
2675
+ #endif
2676
+ /*
2677
+ * try to limit the damages of the URI unescaping code.
2678
+ */
2679
+ if ((puri->scheme == NULL) ||
2680
+ (xmlStrEqual(BAD_CAST puri->scheme, BAD_CAST "file")))
2681
+ unescaped = xmlURIUnescapeString(URI, 0, NULL);
2682
+ xmlFreeURI(puri);
2683
+ }
2684
+
2685
+ /*
2686
+ * Try to find one of the output accept method accepting that scheme
2687
+ * Go in reverse to give precedence to user defined handlers.
2688
+ * try with an unescaped version of the URI
2689
+ */
2690
+ if (unescaped != NULL) {
2691
+ #ifdef LIBXML_ZLIB_ENABLED
2692
+ if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) {
2693
+ context = xmlGzfileOpenW(unescaped, compression);
2694
+ if (context != NULL) {
2695
+ ret = xmlAllocOutputBufferInternal(encoder);
2696
+ if (ret != NULL) {
2697
+ ret->context = context;
2698
+ ret->writecallback = xmlGzfileWrite;
2699
+ ret->closecallback = xmlGzfileClose;
2700
+ }
2701
+ xmlFree(unescaped);
2702
+ return(ret);
2703
+ }
2704
+ }
2705
+ #endif
2706
+ for (i = xmlOutputCallbackNr - 1;i >= 0;i--) {
2707
+ if ((xmlOutputCallbackTable[i].matchcallback != NULL) &&
2708
+ (xmlOutputCallbackTable[i].matchcallback(unescaped) != 0)) {
2709
+ #if defined(LIBXML_HTTP_ENABLED) && defined(LIBXML_ZLIB_ENABLED)
2710
+ /* Need to pass compression parameter into HTTP open calls */
2711
+ if (xmlOutputCallbackTable[i].matchcallback == xmlIOHTTPMatch)
2712
+ context = xmlIOHTTPOpenW(unescaped, compression);
2713
+ else
2714
+ #endif
2715
+ context = xmlOutputCallbackTable[i].opencallback(unescaped);
2716
+ if (context != NULL)
2717
+ break;
2718
+ }
2719
+ }
2720
+ xmlFree(unescaped);
2721
+ }
2722
+
2723
+ /*
2724
+ * If this failed try with a non-escaped URI this may be a strange
2725
+ * filename
2726
+ */
2727
+ if (context == NULL) {
2728
+ #ifdef LIBXML_ZLIB_ENABLED
2729
+ if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) {
2730
+ context = xmlGzfileOpenW(URI, compression);
2731
+ if (context != NULL) {
2732
+ ret = xmlAllocOutputBufferInternal(encoder);
2733
+ if (ret != NULL) {
2734
+ ret->context = context;
2735
+ ret->writecallback = xmlGzfileWrite;
2736
+ ret->closecallback = xmlGzfileClose;
2737
+ }
2738
+ return(ret);
2739
+ }
2740
+ }
2741
+ #endif
2742
+ for (i = xmlOutputCallbackNr - 1;i >= 0;i--) {
2743
+ if ((xmlOutputCallbackTable[i].matchcallback != NULL) &&
2744
+ (xmlOutputCallbackTable[i].matchcallback(URI) != 0)) {
2745
+ #if defined(LIBXML_HTTP_ENABLED) && defined(LIBXML_ZLIB_ENABLED)
2746
+ /* Need to pass compression parameter into HTTP open calls */
2747
+ if (xmlOutputCallbackTable[i].matchcallback == xmlIOHTTPMatch)
2748
+ context = xmlIOHTTPOpenW(URI, compression);
2749
+ else
2750
+ #endif
2751
+ context = xmlOutputCallbackTable[i].opencallback(URI);
2752
+ if (context != NULL)
2753
+ break;
2754
+ }
2755
+ }
2756
+ }
2757
+
2758
+ if (context == NULL) {
2759
+ return(NULL);
2760
+ }
2761
+
2762
+ /*
2763
+ * Allocate the Output buffer front-end.
2764
+ */
2765
+ ret = xmlAllocOutputBufferInternal(encoder);
2766
+ if (ret != NULL) {
2767
+ ret->context = context;
2768
+ ret->writecallback = xmlOutputCallbackTable[i].writecallback;
2769
+ ret->closecallback = xmlOutputCallbackTable[i].closecallback;
2770
+ }
2771
+ return(ret);
2772
+ }
2773
+
2774
+ /**
2775
+ * xmlOutputBufferCreateFilename:
2776
+ * @URI: a C string containing the URI or filename
2777
+ * @encoder: the encoding converter or NULL
2778
+ * @compression: the compression ration (0 none, 9 max).
2779
+ *
2780
+ * Create a buffered output for the progressive saving of a file
2781
+ * If filename is "-' then we use stdout as the output.
2782
+ * Automatic support for ZLIB/Compress compressed document is provided
2783
+ * by default if found at compile-time.
2784
+ * TODO: currently if compression is set, the library only support
2785
+ * writing to a local file.
2786
+ *
2787
+ * Returns the new output or NULL
2788
+ */
2789
+ xmlOutputBufferPtr
2790
+ xmlOutputBufferCreateFilename(const char *URI,
2791
+ xmlCharEncodingHandlerPtr encoder,
2792
+ int compression ATTRIBUTE_UNUSED) {
2793
+ if ((xmlOutputBufferCreateFilenameValue)) {
2794
+ return xmlOutputBufferCreateFilenameValue(URI, encoder, compression);
2795
+ }
2796
+ return __xmlOutputBufferCreateFilename(URI, encoder, compression);
2797
+ }
2798
+ #endif /* LIBXML_OUTPUT_ENABLED */
2799
+
2800
+ /**
2801
+ * xmlParserInputBufferCreateFile:
2802
+ * @file: a FILE*
2803
+ * @enc: the charset encoding if known
2804
+ *
2805
+ * Create a buffered parser input for the progressive parsing of a FILE *
2806
+ * buffered C I/O
2807
+ *
2808
+ * Returns the new parser input or NULL
2809
+ */
2810
+ xmlParserInputBufferPtr
2811
+ xmlParserInputBufferCreateFile(FILE *file, xmlCharEncoding enc) {
2812
+ xmlParserInputBufferPtr ret;
2813
+
2814
+ if (xmlInputCallbackInitialized == 0)
2815
+ xmlRegisterDefaultInputCallbacks();
2816
+
2817
+ if (file == NULL) return(NULL);
2818
+
2819
+ ret = xmlAllocParserInputBuffer(enc);
2820
+ if (ret != NULL) {
2821
+ ret->context = file;
2822
+ ret->readcallback = xmlFileRead;
2823
+ ret->closecallback = xmlFileFlush;
2824
+ }
2825
+
2826
+ return(ret);
2827
+ }
2828
+
2829
+ #ifdef LIBXML_OUTPUT_ENABLED
2830
+ /**
2831
+ * xmlOutputBufferCreateFile:
2832
+ * @file: a FILE*
2833
+ * @encoder: the encoding converter or NULL
2834
+ *
2835
+ * Create a buffered output for the progressive saving to a FILE *
2836
+ * buffered C I/O
2837
+ *
2838
+ * Returns the new parser output or NULL
2839
+ */
2840
+ xmlOutputBufferPtr
2841
+ xmlOutputBufferCreateFile(FILE *file, xmlCharEncodingHandlerPtr encoder) {
2842
+ xmlOutputBufferPtr ret;
2843
+
2844
+ if (xmlOutputCallbackInitialized == 0)
2845
+ xmlRegisterDefaultOutputCallbacks();
2846
+
2847
+ if (file == NULL) return(NULL);
2848
+
2849
+ ret = xmlAllocOutputBufferInternal(encoder);
2850
+ if (ret != NULL) {
2851
+ ret->context = file;
2852
+ ret->writecallback = xmlFileWrite;
2853
+ ret->closecallback = xmlFileFlush;
2854
+ }
2855
+
2856
+ return(ret);
2857
+ }
2858
+
2859
+ /**
2860
+ * xmlOutputBufferCreateBuffer:
2861
+ * @buffer: a xmlBufferPtr
2862
+ * @encoder: the encoding converter or NULL
2863
+ *
2864
+ * Create a buffered output for the progressive saving to a xmlBuffer
2865
+ *
2866
+ * Returns the new parser output or NULL
2867
+ */
2868
+ xmlOutputBufferPtr
2869
+ xmlOutputBufferCreateBuffer(xmlBufferPtr buffer,
2870
+ xmlCharEncodingHandlerPtr encoder) {
2871
+ xmlOutputBufferPtr ret;
2872
+
2873
+ if (buffer == NULL) return(NULL);
2874
+
2875
+ ret = xmlOutputBufferCreateIO(xmlBufferWrite, NULL, (void *) buffer,
2876
+ encoder);
2877
+
2878
+ return(ret);
2879
+ }
2880
+
2881
+ /**
2882
+ * xmlOutputBufferGetContent:
2883
+ * @out: an xmlOutputBufferPtr
2884
+ *
2885
+ * Gives a pointer to the data currently held in the output buffer
2886
+ *
2887
+ * Returns a pointer to the data or NULL in case of error
2888
+ */
2889
+ const xmlChar *
2890
+ xmlOutputBufferGetContent(xmlOutputBufferPtr out) {
2891
+ if ((out == NULL) || (out->buffer == NULL))
2892
+ return(NULL);
2893
+
2894
+ return(xmlBufContent(out->buffer));
2895
+ }
2896
+
2897
+ /**
2898
+ * xmlOutputBufferGetSize:
2899
+ * @out: an xmlOutputBufferPtr
2900
+ *
2901
+ * Gives the length of the data currently held in the output buffer
2902
+ *
2903
+ * Returns 0 in case or error or no data is held, the size otherwise
2904
+ */
2905
+ size_t
2906
+ xmlOutputBufferGetSize(xmlOutputBufferPtr out) {
2907
+ if ((out == NULL) || (out->buffer == NULL))
2908
+ return(0);
2909
+
2910
+ return(xmlBufUse(out->buffer));
2911
+ }
2912
+
2913
+
2914
+ #endif /* LIBXML_OUTPUT_ENABLED */
2915
+
2916
+ /**
2917
+ * xmlParserInputBufferCreateFd:
2918
+ * @fd: a file descriptor number
2919
+ * @enc: the charset encoding if known
2920
+ *
2921
+ * Create a buffered parser input for the progressive parsing for the input
2922
+ * from a file descriptor
2923
+ *
2924
+ * Returns the new parser input or NULL
2925
+ */
2926
+ xmlParserInputBufferPtr
2927
+ xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) {
2928
+ xmlParserInputBufferPtr ret;
2929
+
2930
+ if (fd < 0) return(NULL);
2931
+
2932
+ ret = xmlAllocParserInputBuffer(enc);
2933
+ if (ret != NULL) {
2934
+ ret->context = (void *) (ptrdiff_t) fd;
2935
+ ret->readcallback = xmlFdRead;
2936
+ ret->closecallback = xmlFdClose;
2937
+ }
2938
+
2939
+ return(ret);
2940
+ }
2941
+
2942
+ /**
2943
+ * xmlParserInputBufferCreateMem:
2944
+ * @mem: the memory input
2945
+ * @size: the length of the memory block
2946
+ * @enc: the charset encoding if known
2947
+ *
2948
+ * Create a buffered parser input for the progressive parsing for the input
2949
+ * from a memory area.
2950
+ *
2951
+ * Returns the new parser input or NULL
2952
+ */
2953
+ xmlParserInputBufferPtr
2954
+ xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) {
2955
+ xmlParserInputBufferPtr ret;
2956
+ int errcode;
2957
+
2958
+ if (size < 0) return(NULL);
2959
+ if (mem == NULL) return(NULL);
2960
+
2961
+ ret = xmlAllocParserInputBuffer(enc);
2962
+ if (ret != NULL) {
2963
+ ret->context = (void *) mem;
2964
+ ret->readcallback = xmlInputReadCallbackNop;
2965
+ ret->closecallback = NULL;
2966
+ errcode = xmlBufAdd(ret->buffer, (const xmlChar *) mem, size);
2967
+ if (errcode != 0) {
2968
+ xmlFree(ret);
2969
+ return(NULL);
2970
+ }
2971
+ }
2972
+
2973
+ return(ret);
2974
+ }
2975
+
2976
+ /**
2977
+ * xmlParserInputBufferCreateStatic:
2978
+ * @mem: the memory input
2979
+ * @size: the length of the memory block
2980
+ * @enc: the charset encoding if known
2981
+ *
2982
+ * Create a buffered parser input for the progressive parsing for the input
2983
+ * from an immutable memory area. This will not copy the memory area to
2984
+ * the buffer, but the memory is expected to be available until the end of
2985
+ * the parsing, this is useful for example when using mmap'ed file.
2986
+ *
2987
+ * Returns the new parser input or NULL
2988
+ */
2989
+ xmlParserInputBufferPtr
2990
+ xmlParserInputBufferCreateStatic(const char *mem, int size,
2991
+ xmlCharEncoding enc) {
2992
+ xmlParserInputBufferPtr ret;
2993
+
2994
+ if (size < 0) return(NULL);
2995
+ if (mem == NULL) return(NULL);
2996
+
2997
+ ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
2998
+ if (ret == NULL) {
2999
+ xmlIOErrMemory("creating input buffer");
3000
+ return(NULL);
3001
+ }
3002
+ memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
3003
+ ret->buffer = xmlBufCreateStatic((void *)mem, (size_t) size);
3004
+ if (ret->buffer == NULL) {
3005
+ xmlFree(ret);
3006
+ return(NULL);
3007
+ }
3008
+ ret->encoder = xmlGetCharEncodingHandler(enc);
3009
+ if (ret->encoder != NULL)
3010
+ ret->raw = xmlBufCreateSize(2 * xmlDefaultBufferSize);
3011
+ else
3012
+ ret->raw = NULL;
3013
+ ret->compressed = -1;
3014
+ ret->context = (void *) mem;
3015
+ ret->readcallback = NULL;
3016
+ ret->closecallback = NULL;
3017
+
3018
+ return(ret);
3019
+ }
3020
+
3021
+ #ifdef LIBXML_OUTPUT_ENABLED
3022
+ /**
3023
+ * xmlOutputBufferCreateFd:
3024
+ * @fd: a file descriptor number
3025
+ * @encoder: the encoding converter or NULL
3026
+ *
3027
+ * Create a buffered output for the progressive saving
3028
+ * to a file descriptor
3029
+ *
3030
+ * Returns the new parser output or NULL
3031
+ */
3032
+ xmlOutputBufferPtr
3033
+ xmlOutputBufferCreateFd(int fd, xmlCharEncodingHandlerPtr encoder) {
3034
+ xmlOutputBufferPtr ret;
3035
+
3036
+ if (fd < 0) return(NULL);
3037
+
3038
+ ret = xmlAllocOutputBufferInternal(encoder);
3039
+ if (ret != NULL) {
3040
+ ret->context = (void *) (ptrdiff_t) fd;
3041
+ ret->writecallback = xmlFdWrite;
3042
+ ret->closecallback = NULL;
3043
+ }
3044
+
3045
+ return(ret);
3046
+ }
3047
+ #endif /* LIBXML_OUTPUT_ENABLED */
3048
+
3049
+ /**
3050
+ * xmlParserInputBufferCreateIO:
3051
+ * @ioread: an I/O read function
3052
+ * @ioclose: an I/O close function
3053
+ * @ioctx: an I/O handler
3054
+ * @enc: the charset encoding if known
3055
+ *
3056
+ * Create a buffered parser input for the progressive parsing for the input
3057
+ * from an I/O handler
3058
+ *
3059
+ * Returns the new parser input or NULL
3060
+ */
3061
+ xmlParserInputBufferPtr
3062
+ xmlParserInputBufferCreateIO(xmlInputReadCallback ioread,
3063
+ xmlInputCloseCallback ioclose, void *ioctx, xmlCharEncoding enc) {
3064
+ xmlParserInputBufferPtr ret;
3065
+
3066
+ if (ioread == NULL) return(NULL);
3067
+
3068
+ ret = xmlAllocParserInputBuffer(enc);
3069
+ if (ret != NULL) {
3070
+ ret->context = (void *) ioctx;
3071
+ ret->readcallback = ioread;
3072
+ ret->closecallback = ioclose;
3073
+ }
3074
+
3075
+ return(ret);
3076
+ }
3077
+
3078
+ #ifdef LIBXML_OUTPUT_ENABLED
3079
+ /**
3080
+ * xmlOutputBufferCreateIO:
3081
+ * @iowrite: an I/O write function
3082
+ * @ioclose: an I/O close function
3083
+ * @ioctx: an I/O handler
3084
+ * @encoder: the charset encoding if known
3085
+ *
3086
+ * Create a buffered output for the progressive saving
3087
+ * to an I/O handler
3088
+ *
3089
+ * Returns the new parser output or NULL
3090
+ */
3091
+ xmlOutputBufferPtr
3092
+ xmlOutputBufferCreateIO(xmlOutputWriteCallback iowrite,
3093
+ xmlOutputCloseCallback ioclose, void *ioctx,
3094
+ xmlCharEncodingHandlerPtr encoder) {
3095
+ xmlOutputBufferPtr ret;
3096
+
3097
+ if (iowrite == NULL) return(NULL);
3098
+
3099
+ ret = xmlAllocOutputBufferInternal(encoder);
3100
+ if (ret != NULL) {
3101
+ ret->context = (void *) ioctx;
3102
+ ret->writecallback = iowrite;
3103
+ ret->closecallback = ioclose;
3104
+ }
3105
+
3106
+ return(ret);
3107
+ }
3108
+ #endif /* LIBXML_OUTPUT_ENABLED */
3109
+
3110
+ /**
3111
+ * xmlParserInputBufferCreateFilenameDefault:
3112
+ * @func: function pointer to the new ParserInputBufferCreateFilenameFunc
3113
+ *
3114
+ * Registers a callback for URI input file handling
3115
+ *
3116
+ * Returns the old value of the registration function
3117
+ */
3118
+ xmlParserInputBufferCreateFilenameFunc
3119
+ xmlParserInputBufferCreateFilenameDefault(xmlParserInputBufferCreateFilenameFunc func)
3120
+ {
3121
+ xmlParserInputBufferCreateFilenameFunc old = xmlParserInputBufferCreateFilenameValue;
3122
+ if (old == NULL) {
3123
+ old = __xmlParserInputBufferCreateFilename;
3124
+ }
3125
+
3126
+ xmlParserInputBufferCreateFilenameValue = func;
3127
+ return(old);
3128
+ }
3129
+
3130
+ /**
3131
+ * xmlOutputBufferCreateFilenameDefault:
3132
+ * @func: function pointer to the new OutputBufferCreateFilenameFunc
3133
+ *
3134
+ * Registers a callback for URI output file handling
3135
+ *
3136
+ * Returns the old value of the registration function
3137
+ */
3138
+ xmlOutputBufferCreateFilenameFunc
3139
+ xmlOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func)
3140
+ {
3141
+ xmlOutputBufferCreateFilenameFunc old = xmlOutputBufferCreateFilenameValue;
3142
+ #ifdef LIBXML_OUTPUT_ENABLED
3143
+ if (old == NULL) {
3144
+ old = __xmlOutputBufferCreateFilename;
3145
+ }
3146
+ #endif
3147
+ xmlOutputBufferCreateFilenameValue = func;
3148
+ return(old);
3149
+ }
3150
+
3151
+ /**
3152
+ * xmlParserInputBufferPush:
3153
+ * @in: a buffered parser input
3154
+ * @len: the size in bytes of the array.
3155
+ * @buf: an char array
3156
+ *
3157
+ * Push the content of the arry in the input buffer
3158
+ * This routine handle the I18N transcoding to internal UTF-8
3159
+ * This is used when operating the parser in progressive (push) mode.
3160
+ *
3161
+ * Returns the number of chars read and stored in the buffer, or -1
3162
+ * in case of error.
3163
+ */
3164
+ int
3165
+ xmlParserInputBufferPush(xmlParserInputBufferPtr in,
3166
+ int len, const char *buf) {
3167
+ int nbchars = 0;
3168
+ int ret;
3169
+
3170
+ if (len < 0) return(0);
3171
+ if ((in == NULL) || (in->error)) return(-1);
3172
+ if (in->encoder != NULL) {
3173
+ unsigned int use;
3174
+
3175
+ /*
3176
+ * Store the data in the incoming raw buffer
3177
+ */
3178
+ if (in->raw == NULL) {
3179
+ in->raw = xmlBufCreate();
3180
+ }
3181
+ ret = xmlBufAdd(in->raw, (const xmlChar *) buf, len);
3182
+ if (ret != 0)
3183
+ return(-1);
3184
+
3185
+ /*
3186
+ * convert as much as possible to the parser reading buffer.
3187
+ */
3188
+ use = xmlBufUse(in->raw);
3189
+ nbchars = xmlCharEncInput(in, 1);
3190
+ if (nbchars < 0) {
3191
+ xmlIOErr(XML_IO_ENCODER, NULL);
3192
+ in->error = XML_IO_ENCODER;
3193
+ return(-1);
3194
+ }
3195
+ in->rawconsumed += (use - xmlBufUse(in->raw));
3196
+ } else {
3197
+ nbchars = len;
3198
+ ret = xmlBufAdd(in->buffer, (xmlChar *) buf, nbchars);
3199
+ if (ret != 0)
3200
+ return(-1);
3201
+ }
3202
+ #ifdef DEBUG_INPUT
3203
+ xmlGenericError(xmlGenericErrorContext,
3204
+ "I/O: pushed %d chars, buffer %d/%d\n",
3205
+ nbchars, xmlBufUse(in->buffer), xmlBufLength(in->buffer));
3206
+ #endif
3207
+ return(nbchars);
3208
+ }
3209
+
3210
+ /**
3211
+ * endOfInput:
3212
+ *
3213
+ * When reading from an Input channel indicated end of file or error
3214
+ * don't reread from it again.
3215
+ */
3216
+ static int
3217
+ endOfInput (void * context ATTRIBUTE_UNUSED,
3218
+ char * buffer ATTRIBUTE_UNUSED,
3219
+ int len ATTRIBUTE_UNUSED) {
3220
+ return(0);
3221
+ }
3222
+
3223
+ /**
3224
+ * xmlParserInputBufferGrow:
3225
+ * @in: a buffered parser input
3226
+ * @len: indicative value of the amount of chars to read
3227
+ *
3228
+ * Grow up the content of the input buffer, the old data are preserved
3229
+ * This routine handle the I18N transcoding to internal UTF-8
3230
+ * This routine is used when operating the parser in normal (pull) mode
3231
+ *
3232
+ * TODO: one should be able to remove one extra copy by copying directly
3233
+ * onto in->buffer or in->raw
3234
+ *
3235
+ * Returns the number of chars read and stored in the buffer, or -1
3236
+ * in case of error.
3237
+ */
3238
+ int
3239
+ xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
3240
+ char *buffer = NULL;
3241
+ int res = 0;
3242
+ int nbchars = 0;
3243
+
3244
+ if ((in == NULL) || (in->error)) return(-1);
3245
+ if ((len <= MINLEN) && (len != 4))
3246
+ len = MINLEN;
3247
+
3248
+ if (xmlBufAvail(in->buffer) <= 0) {
3249
+ xmlIOErr(XML_IO_BUFFER_FULL, NULL);
3250
+ in->error = XML_IO_BUFFER_FULL;
3251
+ return(-1);
3252
+ }
3253
+
3254
+ if (xmlBufGrow(in->buffer, len + 1) < 0) {
3255
+ xmlIOErrMemory("growing input buffer");
3256
+ in->error = XML_ERR_NO_MEMORY;
3257
+ return(-1);
3258
+ }
3259
+ buffer = (char *)xmlBufEnd(in->buffer);
3260
+
3261
+ /*
3262
+ * Call the read method for this I/O type.
3263
+ */
3264
+ if (in->readcallback != NULL) {
3265
+ res = in->readcallback(in->context, &buffer[0], len);
3266
+ if (res <= 0)
3267
+ in->readcallback = endOfInput;
3268
+ } else {
3269
+ xmlIOErr(XML_IO_NO_INPUT, NULL);
3270
+ in->error = XML_IO_NO_INPUT;
3271
+ return(-1);
3272
+ }
3273
+ if (res < 0) {
3274
+ return(-1);
3275
+ }
3276
+
3277
+ /*
3278
+ * try to establish compressed status of input if not done already
3279
+ */
3280
+ if (in->compressed == -1) {
3281
+ #ifdef LIBXML_LZMA_ENABLED
3282
+ if (in->readcallback == xmlXzfileRead)
3283
+ in->compressed = __libxml2_xzcompressed(in->context);
3284
+ #endif
3285
+ }
3286
+
3287
+ len = res;
3288
+ if (in->encoder != NULL) {
3289
+ unsigned int use;
3290
+
3291
+ /*
3292
+ * Store the data in the incoming raw buffer
3293
+ */
3294
+ if (in->raw == NULL) {
3295
+ in->raw = xmlBufCreate();
3296
+ }
3297
+ res = xmlBufAdd(in->raw, (const xmlChar *) buffer, len);
3298
+ if (res != 0)
3299
+ return(-1);
3300
+
3301
+ /*
3302
+ * convert as much as possible to the parser reading buffer.
3303
+ */
3304
+ use = xmlBufUse(in->raw);
3305
+ nbchars = xmlCharEncInput(in, 1);
3306
+ if (nbchars < 0) {
3307
+ xmlIOErr(XML_IO_ENCODER, NULL);
3308
+ in->error = XML_IO_ENCODER;
3309
+ return(-1);
3310
+ }
3311
+ in->rawconsumed += (use - xmlBufUse(in->raw));
3312
+ } else {
3313
+ nbchars = len;
3314
+ xmlBufAddLen(in->buffer, nbchars);
3315
+ }
3316
+ #ifdef DEBUG_INPUT
3317
+ xmlGenericError(xmlGenericErrorContext,
3318
+ "I/O: read %d chars, buffer %d\n",
3319
+ nbchars, xmlBufUse(in->buffer));
3320
+ #endif
3321
+ return(nbchars);
3322
+ }
3323
+
3324
+ /**
3325
+ * xmlParserInputBufferRead:
3326
+ * @in: a buffered parser input
3327
+ * @len: indicative value of the amount of chars to read
3328
+ *
3329
+ * Refresh the content of the input buffer, the old data are considered
3330
+ * consumed
3331
+ * This routine handle the I18N transcoding to internal UTF-8
3332
+ *
3333
+ * Returns the number of chars read and stored in the buffer, or -1
3334
+ * in case of error.
3335
+ */
3336
+ int
3337
+ xmlParserInputBufferRead(xmlParserInputBufferPtr in, int len) {
3338
+ if ((in == NULL) || (in->error)) return(-1);
3339
+ if (in->readcallback != NULL)
3340
+ return(xmlParserInputBufferGrow(in, len));
3341
+ else if (xmlBufGetAllocationScheme(in->buffer) == XML_BUFFER_ALLOC_IMMUTABLE)
3342
+ return(0);
3343
+ else
3344
+ return(-1);
3345
+ }
3346
+
3347
+ #ifdef LIBXML_OUTPUT_ENABLED
3348
+ /**
3349
+ * xmlOutputBufferWrite:
3350
+ * @out: a buffered parser output
3351
+ * @len: the size in bytes of the array.
3352
+ * @buf: an char array
3353
+ *
3354
+ * Write the content of the array in the output I/O buffer
3355
+ * This routine handle the I18N transcoding from internal UTF-8
3356
+ * The buffer is lossless, i.e. will store in case of partial
3357
+ * or delayed writes.
3358
+ *
3359
+ * Returns the number of chars immediately written, or -1
3360
+ * in case of error.
3361
+ */
3362
+ int
3363
+ xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) {
3364
+ int nbchars = 0; /* number of chars to output to I/O */
3365
+ int ret; /* return from function call */
3366
+ int written = 0; /* number of char written to I/O so far */
3367
+ int chunk; /* number of byte current processed from buf */
3368
+
3369
+ if ((out == NULL) || (out->error)) return(-1);
3370
+ if (len < 0) return(0);
3371
+ if (out->error) return(-1);
3372
+
3373
+ do {
3374
+ chunk = len;
3375
+ if (chunk > 4 * MINLEN)
3376
+ chunk = 4 * MINLEN;
3377
+
3378
+ /*
3379
+ * first handle encoding stuff.
3380
+ */
3381
+ if (out->encoder != NULL) {
3382
+ /*
3383
+ * Store the data in the incoming raw buffer
3384
+ */
3385
+ if (out->conv == NULL) {
3386
+ out->conv = xmlBufCreate();
3387
+ }
3388
+ ret = xmlBufAdd(out->buffer, (const xmlChar *) buf, chunk);
3389
+ if (ret != 0)
3390
+ return(-1);
3391
+
3392
+ if ((xmlBufUse(out->buffer) < MINLEN) && (chunk == len))
3393
+ goto done;
3394
+
3395
+ /*
3396
+ * convert as much as possible to the parser reading buffer.
3397
+ */
3398
+ ret = xmlCharEncOutput(out, 0);
3399
+ if ((ret < 0) && (ret != -3)) {
3400
+ xmlIOErr(XML_IO_ENCODER, NULL);
3401
+ out->error = XML_IO_ENCODER;
3402
+ return(-1);
3403
+ }
3404
+ if (out->writecallback)
3405
+ nbchars = xmlBufUse(out->conv);
3406
+ else
3407
+ nbchars = ret >= 0 ? ret : 0;
3408
+ } else {
3409
+ ret = xmlBufAdd(out->buffer, (const xmlChar *) buf, chunk);
3410
+ if (ret != 0)
3411
+ return(-1);
3412
+ if (out->writecallback)
3413
+ nbchars = xmlBufUse(out->buffer);
3414
+ else
3415
+ nbchars = chunk;
3416
+ }
3417
+ buf += chunk;
3418
+ len -= chunk;
3419
+
3420
+ if (out->writecallback) {
3421
+ if ((nbchars < MINLEN) && (len <= 0))
3422
+ goto done;
3423
+
3424
+ /*
3425
+ * second write the stuff to the I/O channel
3426
+ */
3427
+ if (out->encoder != NULL) {
3428
+ ret = out->writecallback(out->context,
3429
+ (const char *)xmlBufContent(out->conv), nbchars);
3430
+ if (ret >= 0)
3431
+ xmlBufShrink(out->conv, ret);
3432
+ } else {
3433
+ ret = out->writecallback(out->context,
3434
+ (const char *)xmlBufContent(out->buffer), nbchars);
3435
+ if (ret >= 0)
3436
+ xmlBufShrink(out->buffer, ret);
3437
+ }
3438
+ if (ret < 0) {
3439
+ xmlIOErr(XML_IO_WRITE, NULL);
3440
+ out->error = XML_IO_WRITE;
3441
+ return(ret);
3442
+ }
3443
+ if (out->written > INT_MAX - ret)
3444
+ out->written = INT_MAX;
3445
+ else
3446
+ out->written += ret;
3447
+ }
3448
+ written += nbchars;
3449
+ } while (len > 0);
3450
+
3451
+ done:
3452
+ #ifdef DEBUG_INPUT
3453
+ xmlGenericError(xmlGenericErrorContext,
3454
+ "I/O: wrote %d chars\n", written);
3455
+ #endif
3456
+ return(written);
3457
+ }
3458
+
3459
+ /**
3460
+ * xmlEscapeContent:
3461
+ * @out: a pointer to an array of bytes to store the result
3462
+ * @outlen: the length of @out
3463
+ * @in: a pointer to an array of unescaped UTF-8 bytes
3464
+ * @inlen: the length of @in
3465
+ *
3466
+ * Take a block of UTF-8 chars in and escape them.
3467
+ * Returns 0 if success, or -1 otherwise
3468
+ * The value of @inlen after return is the number of octets consumed
3469
+ * if the return value is positive, else unpredictable.
3470
+ * The value of @outlen after return is the number of octets consumed.
3471
+ */
3472
+ static int
3473
+ xmlEscapeContent(unsigned char* out, int *outlen,
3474
+ const xmlChar* in, int *inlen) {
3475
+ unsigned char* outstart = out;
3476
+ const unsigned char* base = in;
3477
+ unsigned char* outend = out + *outlen;
3478
+ const unsigned char* inend;
3479
+
3480
+ inend = in + (*inlen);
3481
+
3482
+ while ((in < inend) && (out < outend)) {
3483
+ if (*in == '<') {
3484
+ if (outend - out < 4) break;
3485
+ *out++ = '&';
3486
+ *out++ = 'l';
3487
+ *out++ = 't';
3488
+ *out++ = ';';
3489
+ } else if (*in == '>') {
3490
+ if (outend - out < 4) break;
3491
+ *out++ = '&';
3492
+ *out++ = 'g';
3493
+ *out++ = 't';
3494
+ *out++ = ';';
3495
+ } else if (*in == '&') {
3496
+ if (outend - out < 5) break;
3497
+ *out++ = '&';
3498
+ *out++ = 'a';
3499
+ *out++ = 'm';
3500
+ *out++ = 'p';
3501
+ *out++ = ';';
3502
+ } else if (*in == '\r') {
3503
+ if (outend - out < 5) break;
3504
+ *out++ = '&';
3505
+ *out++ = '#';
3506
+ *out++ = '1';
3507
+ *out++ = '3';
3508
+ *out++ = ';';
3509
+ } else {
3510
+ *out++ = (unsigned char) *in;
3511
+ }
3512
+ ++in;
3513
+ }
3514
+ *outlen = out - outstart;
3515
+ *inlen = in - base;
3516
+ return(0);
3517
+ }
3518
+
3519
+ /**
3520
+ * xmlOutputBufferWriteEscape:
3521
+ * @out: a buffered parser output
3522
+ * @str: a zero terminated UTF-8 string
3523
+ * @escaping: an optional escaping function (or NULL)
3524
+ *
3525
+ * Write the content of the string in the output I/O buffer
3526
+ * This routine escapes the characters and then handle the I18N
3527
+ * transcoding from internal UTF-8
3528
+ * The buffer is lossless, i.e. will store in case of partial
3529
+ * or delayed writes.
3530
+ *
3531
+ * Returns the number of chars immediately written, or -1
3532
+ * in case of error.
3533
+ */
3534
+ int
3535
+ xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str,
3536
+ xmlCharEncodingOutputFunc escaping) {
3537
+ int nbchars = 0; /* number of chars to output to I/O */
3538
+ int ret; /* return from function call */
3539
+ int written = 0; /* number of char written to I/O so far */
3540
+ int oldwritten=0;/* loop guard */
3541
+ int chunk; /* number of byte currently processed from str */
3542
+ int len; /* number of bytes in str */
3543
+ int cons; /* byte from str consumed */
3544
+
3545
+ if ((out == NULL) || (out->error) || (str == NULL) ||
3546
+ (out->buffer == NULL) ||
3547
+ (xmlBufGetAllocationScheme(out->buffer) == XML_BUFFER_ALLOC_IMMUTABLE))
3548
+ return(-1);
3549
+ len = strlen((const char *)str);
3550
+ if (len < 0) return(0);
3551
+ if (out->error) return(-1);
3552
+ if (escaping == NULL) escaping = xmlEscapeContent;
3553
+
3554
+ do {
3555
+ oldwritten = written;
3556
+
3557
+ /*
3558
+ * how many bytes to consume and how many bytes to store.
3559
+ */
3560
+ cons = len;
3561
+ chunk = xmlBufAvail(out->buffer) - 1;
3562
+
3563
+ /*
3564
+ * make sure we have enough room to save first, if this is
3565
+ * not the case force a flush, but make sure we stay in the loop
3566
+ */
3567
+ if (chunk < 40) {
3568
+ if (xmlBufGrow(out->buffer, 100) < 0)
3569
+ return(-1);
3570
+ oldwritten = -1;
3571
+ continue;
3572
+ }
3573
+
3574
+ /*
3575
+ * first handle encoding stuff.
3576
+ */
3577
+ if (out->encoder != NULL) {
3578
+ /*
3579
+ * Store the data in the incoming raw buffer
3580
+ */
3581
+ if (out->conv == NULL) {
3582
+ out->conv = xmlBufCreate();
3583
+ }
3584
+ ret = escaping(xmlBufEnd(out->buffer) ,
3585
+ &chunk, str, &cons);
3586
+ if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */
3587
+ return(-1);
3588
+ xmlBufAddLen(out->buffer, chunk);
3589
+
3590
+ if ((xmlBufUse(out->buffer) < MINLEN) && (cons == len))
3591
+ goto done;
3592
+
3593
+ /*
3594
+ * convert as much as possible to the output buffer.
3595
+ */
3596
+ ret = xmlCharEncOutput(out, 0);
3597
+ if ((ret < 0) && (ret != -3)) {
3598
+ xmlIOErr(XML_IO_ENCODER, NULL);
3599
+ out->error = XML_IO_ENCODER;
3600
+ return(-1);
3601
+ }
3602
+ if (out->writecallback)
3603
+ nbchars = xmlBufUse(out->conv);
3604
+ else
3605
+ nbchars = ret >= 0 ? ret : 0;
3606
+ } else {
3607
+ ret = escaping(xmlBufEnd(out->buffer), &chunk, str, &cons);
3608
+ if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */
3609
+ return(-1);
3610
+ xmlBufAddLen(out->buffer, chunk);
3611
+ if (out->writecallback)
3612
+ nbchars = xmlBufUse(out->buffer);
3613
+ else
3614
+ nbchars = chunk;
3615
+ }
3616
+ str += cons;
3617
+ len -= cons;
3618
+
3619
+ if (out->writecallback) {
3620
+ if ((nbchars < MINLEN) && (len <= 0))
3621
+ goto done;
3622
+
3623
+ /*
3624
+ * second write the stuff to the I/O channel
3625
+ */
3626
+ if (out->encoder != NULL) {
3627
+ ret = out->writecallback(out->context,
3628
+ (const char *)xmlBufContent(out->conv), nbchars);
3629
+ if (ret >= 0)
3630
+ xmlBufShrink(out->conv, ret);
3631
+ } else {
3632
+ ret = out->writecallback(out->context,
3633
+ (const char *)xmlBufContent(out->buffer), nbchars);
3634
+ if (ret >= 0)
3635
+ xmlBufShrink(out->buffer, ret);
3636
+ }
3637
+ if (ret < 0) {
3638
+ xmlIOErr(XML_IO_WRITE, NULL);
3639
+ out->error = XML_IO_WRITE;
3640
+ return(ret);
3641
+ }
3642
+ if (out->written > INT_MAX - ret)
3643
+ out->written = INT_MAX;
3644
+ else
3645
+ out->written += ret;
3646
+ } else if (xmlBufAvail(out->buffer) < MINLEN) {
3647
+ xmlBufGrow(out->buffer, MINLEN);
3648
+ }
3649
+ written += nbchars;
3650
+ } while ((len > 0) && (oldwritten != written));
3651
+
3652
+ done:
3653
+ #ifdef DEBUG_INPUT
3654
+ xmlGenericError(xmlGenericErrorContext,
3655
+ "I/O: wrote %d chars\n", written);
3656
+ #endif
3657
+ return(written);
3658
+ }
3659
+
3660
+ /**
3661
+ * xmlOutputBufferWriteString:
3662
+ * @out: a buffered parser output
3663
+ * @str: a zero terminated C string
3664
+ *
3665
+ * Write the content of the string in the output I/O buffer
3666
+ * This routine handle the I18N transcoding from internal UTF-8
3667
+ * The buffer is lossless, i.e. will store in case of partial
3668
+ * or delayed writes.
3669
+ *
3670
+ * Returns the number of chars immediately written, or -1
3671
+ * in case of error.
3672
+ */
3673
+ int
3674
+ xmlOutputBufferWriteString(xmlOutputBufferPtr out, const char *str) {
3675
+ int len;
3676
+
3677
+ if ((out == NULL) || (out->error)) return(-1);
3678
+ if (str == NULL)
3679
+ return(-1);
3680
+ len = strlen(str);
3681
+
3682
+ if (len > 0)
3683
+ return(xmlOutputBufferWrite(out, len, str));
3684
+ return(len);
3685
+ }
3686
+
3687
+ /**
3688
+ * xmlOutputBufferFlush:
3689
+ * @out: a buffered output
3690
+ *
3691
+ * flushes the output I/O channel
3692
+ *
3693
+ * Returns the number of byte written or -1 in case of error.
3694
+ */
3695
+ int
3696
+ xmlOutputBufferFlush(xmlOutputBufferPtr out) {
3697
+ int nbchars = 0, ret = 0;
3698
+
3699
+ if ((out == NULL) || (out->error)) return(-1);
3700
+ /*
3701
+ * first handle encoding stuff.
3702
+ */
3703
+ if ((out->conv != NULL) && (out->encoder != NULL)) {
3704
+ /*
3705
+ * convert as much as possible to the parser output buffer.
3706
+ */
3707
+ do {
3708
+ nbchars = xmlCharEncOutput(out, 0);
3709
+ if (nbchars < 0) {
3710
+ xmlIOErr(XML_IO_ENCODER, NULL);
3711
+ out->error = XML_IO_ENCODER;
3712
+ return(-1);
3713
+ }
3714
+ } while (nbchars);
3715
+ }
3716
+
3717
+ /*
3718
+ * second flush the stuff to the I/O channel
3719
+ */
3720
+ if ((out->conv != NULL) && (out->encoder != NULL) &&
3721
+ (out->writecallback != NULL)) {
3722
+ ret = out->writecallback(out->context,
3723
+ (const char *)xmlBufContent(out->conv),
3724
+ xmlBufUse(out->conv));
3725
+ if (ret >= 0)
3726
+ xmlBufShrink(out->conv, ret);
3727
+ } else if (out->writecallback != NULL) {
3728
+ ret = out->writecallback(out->context,
3729
+ (const char *)xmlBufContent(out->buffer),
3730
+ xmlBufUse(out->buffer));
3731
+ if (ret >= 0)
3732
+ xmlBufShrink(out->buffer, ret);
3733
+ }
3734
+ if (ret < 0) {
3735
+ xmlIOErr(XML_IO_FLUSH, NULL);
3736
+ out->error = XML_IO_FLUSH;
3737
+ return(ret);
3738
+ }
3739
+ if (out->written > INT_MAX - ret)
3740
+ out->written = INT_MAX;
3741
+ else
3742
+ out->written += ret;
3743
+
3744
+ #ifdef DEBUG_INPUT
3745
+ xmlGenericError(xmlGenericErrorContext,
3746
+ "I/O: flushed %d chars\n", ret);
3747
+ #endif
3748
+ return(ret);
3749
+ }
3750
+ #endif /* LIBXML_OUTPUT_ENABLED */
3751
+
3752
+ /**
3753
+ * xmlParserGetDirectory:
3754
+ * @filename: the path to a file
3755
+ *
3756
+ * lookup the directory for that file
3757
+ *
3758
+ * Returns a new allocated string containing the directory, or NULL.
3759
+ */
3760
+ char *
3761
+ xmlParserGetDirectory(const char *filename) {
3762
+ char *ret = NULL;
3763
+ char dir[1024];
3764
+ char *cur;
3765
+
3766
+ #ifdef _WIN32_WCE /* easy way by now ... wince does not have dirs! */
3767
+ return NULL;
3768
+ #endif
3769
+
3770
+ if (xmlInputCallbackInitialized == 0)
3771
+ xmlRegisterDefaultInputCallbacks();
3772
+
3773
+ if (filename == NULL) return(NULL);
3774
+
3775
+ #if defined(_WIN32) && !defined(__CYGWIN__)
3776
+ # define IS_XMLPGD_SEP(ch) ((ch=='/')||(ch=='\\'))
3777
+ #else
3778
+ # define IS_XMLPGD_SEP(ch) (ch=='/')
3779
+ #endif
3780
+
3781
+ strncpy(dir, filename, 1023);
3782
+ dir[1023] = 0;
3783
+ cur = &dir[strlen(dir)];
3784
+ while (cur > dir) {
3785
+ if (IS_XMLPGD_SEP(*cur)) break;
3786
+ cur --;
3787
+ }
3788
+ if (IS_XMLPGD_SEP(*cur)) {
3789
+ if (cur == dir) dir[1] = 0;
3790
+ else *cur = 0;
3791
+ ret = xmlMemStrdup(dir);
3792
+ } else {
3793
+ if (getcwd(dir, 1024) != NULL) {
3794
+ dir[1023] = 0;
3795
+ ret = xmlMemStrdup(dir);
3796
+ }
3797
+ }
3798
+ return(ret);
3799
+ #undef IS_XMLPGD_SEP
3800
+ }
3801
+
3802
+ /****************************************************************
3803
+ * *
3804
+ * External entities loading *
3805
+ * *
3806
+ ****************************************************************/
3807
+
3808
+ /**
3809
+ * xmlCheckHTTPInput:
3810
+ * @ctxt: an XML parser context
3811
+ * @ret: an XML parser input
3812
+ *
3813
+ * Check an input in case it was created from an HTTP stream, in that
3814
+ * case it will handle encoding and update of the base URL in case of
3815
+ * redirection. It also checks for HTTP errors in which case the input
3816
+ * is cleanly freed up and an appropriate error is raised in context
3817
+ *
3818
+ * Returns the input or NULL in case of HTTP error.
3819
+ */
3820
+ xmlParserInputPtr
3821
+ xmlCheckHTTPInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr ret) {
3822
+ #ifdef LIBXML_HTTP_ENABLED
3823
+ if ((ret != NULL) && (ret->buf != NULL) &&
3824
+ (ret->buf->readcallback == xmlIOHTTPRead) &&
3825
+ (ret->buf->context != NULL)) {
3826
+ const char *encoding;
3827
+ const char *redir;
3828
+ const char *mime;
3829
+ int code;
3830
+
3831
+ code = xmlNanoHTTPReturnCode(ret->buf->context);
3832
+ if (code >= 400) {
3833
+ /* fatal error */
3834
+ if (ret->filename != NULL)
3835
+ __xmlLoaderErr(ctxt, "failed to load HTTP resource \"%s\"\n",
3836
+ (const char *) ret->filename);
3837
+ else
3838
+ __xmlLoaderErr(ctxt, "failed to load HTTP resource\n", NULL);
3839
+ xmlFreeInputStream(ret);
3840
+ ret = NULL;
3841
+ } else {
3842
+
3843
+ mime = xmlNanoHTTPMimeType(ret->buf->context);
3844
+ if ((xmlStrstr(BAD_CAST mime, BAD_CAST "/xml")) ||
3845
+ (xmlStrstr(BAD_CAST mime, BAD_CAST "+xml"))) {
3846
+ encoding = xmlNanoHTTPEncoding(ret->buf->context);
3847
+ if (encoding != NULL) {
3848
+ xmlCharEncodingHandlerPtr handler;
3849
+
3850
+ handler = xmlFindCharEncodingHandler(encoding);
3851
+ if (handler != NULL) {
3852
+ xmlSwitchInputEncoding(ctxt, ret, handler);
3853
+ } else {
3854
+ __xmlErrEncoding(ctxt, XML_ERR_UNKNOWN_ENCODING,
3855
+ "Unknown encoding %s",
3856
+ BAD_CAST encoding, NULL);
3857
+ }
3858
+ if (ret->encoding == NULL)
3859
+ ret->encoding = xmlStrdup(BAD_CAST encoding);
3860
+ }
3861
+ #if 0
3862
+ } else if (xmlStrstr(BAD_CAST mime, BAD_CAST "html")) {
3863
+ #endif
3864
+ }
3865
+ redir = xmlNanoHTTPRedir(ret->buf->context);
3866
+ if (redir != NULL) {
3867
+ if (ret->filename != NULL)
3868
+ xmlFree((xmlChar *) ret->filename);
3869
+ if (ret->directory != NULL) {
3870
+ xmlFree((xmlChar *) ret->directory);
3871
+ ret->directory = NULL;
3872
+ }
3873
+ ret->filename =
3874
+ (char *) xmlStrdup((const xmlChar *) redir);
3875
+ }
3876
+ }
3877
+ }
3878
+ #endif
3879
+ return(ret);
3880
+ }
3881
+
3882
+ static int xmlNoNetExists(const char *URL) {
3883
+ const char *path;
3884
+
3885
+ if (URL == NULL)
3886
+ return(0);
3887
+
3888
+ if (!xmlStrncasecmp(BAD_CAST URL, BAD_CAST "file://localhost/", 17))
3889
+ #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
3890
+ path = &URL[17];
3891
+ #else
3892
+ path = &URL[16];
3893
+ #endif
3894
+ else if (!xmlStrncasecmp(BAD_CAST URL, BAD_CAST "file:///", 8)) {
3895
+ #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
3896
+ path = &URL[8];
3897
+ #else
3898
+ path = &URL[7];
3899
+ #endif
3900
+ } else
3901
+ path = URL;
3902
+
3903
+ return xmlCheckFilename(path);
3904
+ }
3905
+
3906
+ #ifdef LIBXML_CATALOG_ENABLED
3907
+
3908
+ /**
3909
+ * xmlResolveResourceFromCatalog:
3910
+ * @URL: the URL for the entity to load
3911
+ * @ID: the System ID for the entity to load
3912
+ * @ctxt: the context in which the entity is called or NULL
3913
+ *
3914
+ * Resolves the URL and ID against the appropriate catalog.
3915
+ * This function is used by xmlDefaultExternalEntityLoader and
3916
+ * xmlNoNetExternalEntityLoader.
3917
+ *
3918
+ * Returns a new allocated URL, or NULL.
3919
+ */
3920
+ static xmlChar *
3921
+ xmlResolveResourceFromCatalog(const char *URL, const char *ID,
3922
+ xmlParserCtxtPtr ctxt) {
3923
+ xmlChar *resource = NULL;
3924
+ xmlCatalogAllow pref;
3925
+
3926
+ /*
3927
+ * If the resource doesn't exists as a file,
3928
+ * try to load it from the resource pointed in the catalogs
3929
+ */
3930
+ pref = xmlCatalogGetDefaults();
3931
+
3932
+ if ((pref != XML_CATA_ALLOW_NONE) && (!xmlNoNetExists(URL))) {
3933
+ /*
3934
+ * Do a local lookup
3935
+ */
3936
+ if ((ctxt != NULL) && (ctxt->catalogs != NULL) &&
3937
+ ((pref == XML_CATA_ALLOW_ALL) ||
3938
+ (pref == XML_CATA_ALLOW_DOCUMENT))) {
3939
+ resource = xmlCatalogLocalResolve(ctxt->catalogs,
3940
+ (const xmlChar *)ID,
3941
+ (const xmlChar *)URL);
3942
+ }
3943
+ /*
3944
+ * Try a global lookup
3945
+ */
3946
+ if ((resource == NULL) &&
3947
+ ((pref == XML_CATA_ALLOW_ALL) ||
3948
+ (pref == XML_CATA_ALLOW_GLOBAL))) {
3949
+ resource = xmlCatalogResolve((const xmlChar *)ID,
3950
+ (const xmlChar *)URL);
3951
+ }
3952
+ if ((resource == NULL) && (URL != NULL))
3953
+ resource = xmlStrdup((const xmlChar *) URL);
3954
+
3955
+ /*
3956
+ * TODO: do an URI lookup on the reference
3957
+ */
3958
+ if ((resource != NULL) && (!xmlNoNetExists((const char *)resource))) {
3959
+ xmlChar *tmp = NULL;
3960
+
3961
+ if ((ctxt != NULL) && (ctxt->catalogs != NULL) &&
3962
+ ((pref == XML_CATA_ALLOW_ALL) ||
3963
+ (pref == XML_CATA_ALLOW_DOCUMENT))) {
3964
+ tmp = xmlCatalogLocalResolveURI(ctxt->catalogs, resource);
3965
+ }
3966
+ if ((tmp == NULL) &&
3967
+ ((pref == XML_CATA_ALLOW_ALL) ||
3968
+ (pref == XML_CATA_ALLOW_GLOBAL))) {
3969
+ tmp = xmlCatalogResolveURI(resource);
3970
+ }
3971
+
3972
+ if (tmp != NULL) {
3973
+ xmlFree(resource);
3974
+ resource = tmp;
3975
+ }
3976
+ }
3977
+ }
3978
+
3979
+ return resource;
3980
+ }
3981
+
3982
+ #endif
3983
+
3984
+ /**
3985
+ * xmlDefaultExternalEntityLoader:
3986
+ * @URL: the URL for the entity to load
3987
+ * @ID: the System ID for the entity to load
3988
+ * @ctxt: the context in which the entity is called or NULL
3989
+ *
3990
+ * By default we don't load external entities, yet.
3991
+ *
3992
+ * Returns a new allocated xmlParserInputPtr, or NULL.
3993
+ */
3994
+ static xmlParserInputPtr
3995
+ xmlDefaultExternalEntityLoader(const char *URL, const char *ID,
3996
+ xmlParserCtxtPtr ctxt)
3997
+ {
3998
+ xmlParserInputPtr ret = NULL;
3999
+ xmlChar *resource = NULL;
4000
+
4001
+ #ifdef DEBUG_EXTERNAL_ENTITIES
4002
+ xmlGenericError(xmlGenericErrorContext,
4003
+ "xmlDefaultExternalEntityLoader(%s, xxx)\n", URL);
4004
+ #endif
4005
+ if ((ctxt != NULL) && (ctxt->options & XML_PARSE_NONET)) {
4006
+ int options = ctxt->options;
4007
+
4008
+ ctxt->options -= XML_PARSE_NONET;
4009
+ ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
4010
+ ctxt->options = options;
4011
+ return(ret);
4012
+ }
4013
+ #ifdef LIBXML_CATALOG_ENABLED
4014
+ resource = xmlResolveResourceFromCatalog(URL, ID, ctxt);
4015
+ #endif
4016
+
4017
+ if (resource == NULL)
4018
+ resource = (xmlChar *) URL;
4019
+
4020
+ if (resource == NULL) {
4021
+ if (ID == NULL)
4022
+ ID = "NULL";
4023
+ __xmlLoaderErr(ctxt, "failed to load external entity \"%s\"\n", ID);
4024
+ return (NULL);
4025
+ }
4026
+ ret = xmlNewInputFromFile(ctxt, (const char *) resource);
4027
+ if ((resource != NULL) && (resource != (xmlChar *) URL))
4028
+ xmlFree(resource);
4029
+ return (ret);
4030
+ }
4031
+
4032
+ static xmlExternalEntityLoader xmlCurrentExternalEntityLoader =
4033
+ xmlDefaultExternalEntityLoader;
4034
+
4035
+ /**
4036
+ * xmlSetExternalEntityLoader:
4037
+ * @f: the new entity resolver function
4038
+ *
4039
+ * Changes the defaultexternal entity resolver function for the application
4040
+ */
4041
+ void
4042
+ xmlSetExternalEntityLoader(xmlExternalEntityLoader f) {
4043
+ xmlCurrentExternalEntityLoader = f;
4044
+ }
4045
+
4046
+ /**
4047
+ * xmlGetExternalEntityLoader:
4048
+ *
4049
+ * Get the default external entity resolver function for the application
4050
+ *
4051
+ * Returns the xmlExternalEntityLoader function pointer
4052
+ */
4053
+ xmlExternalEntityLoader
4054
+ xmlGetExternalEntityLoader(void) {
4055
+ return(xmlCurrentExternalEntityLoader);
4056
+ }
4057
+
4058
+ /**
4059
+ * xmlLoadExternalEntity:
4060
+ * @URL: the URL for the entity to load
4061
+ * @ID: the Public ID for the entity to load
4062
+ * @ctxt: the context in which the entity is called or NULL
4063
+ *
4064
+ * Load an external entity, note that the use of this function for
4065
+ * unparsed entities may generate problems
4066
+ *
4067
+ * Returns the xmlParserInputPtr or NULL
4068
+ */
4069
+ xmlParserInputPtr
4070
+ xmlLoadExternalEntity(const char *URL, const char *ID,
4071
+ xmlParserCtxtPtr ctxt) {
4072
+ if ((URL != NULL) && (xmlNoNetExists(URL) == 0)) {
4073
+ char *canonicFilename;
4074
+ xmlParserInputPtr ret;
4075
+
4076
+ canonicFilename = (char *) xmlCanonicPath((const xmlChar *) URL);
4077
+ if (canonicFilename == NULL) {
4078
+ xmlIOErrMemory("building canonical path\n");
4079
+ return(NULL);
4080
+ }
4081
+
4082
+ ret = xmlCurrentExternalEntityLoader(canonicFilename, ID, ctxt);
4083
+ xmlFree(canonicFilename);
4084
+ return(ret);
4085
+ }
4086
+ return(xmlCurrentExternalEntityLoader(URL, ID, ctxt));
4087
+ }
4088
+
4089
+ /************************************************************************
4090
+ * *
4091
+ * Disabling Network access *
4092
+ * *
4093
+ ************************************************************************/
4094
+
4095
+ /**
4096
+ * xmlNoNetExternalEntityLoader:
4097
+ * @URL: the URL for the entity to load
4098
+ * @ID: the System ID for the entity to load
4099
+ * @ctxt: the context in which the entity is called or NULL
4100
+ *
4101
+ * A specific entity loader disabling network accesses, though still
4102
+ * allowing local catalog accesses for resolution.
4103
+ *
4104
+ * Returns a new allocated xmlParserInputPtr, or NULL.
4105
+ */
4106
+ xmlParserInputPtr
4107
+ xmlNoNetExternalEntityLoader(const char *URL, const char *ID,
4108
+ xmlParserCtxtPtr ctxt) {
4109
+ xmlParserInputPtr input = NULL;
4110
+ xmlChar *resource = NULL;
4111
+
4112
+ #ifdef LIBXML_CATALOG_ENABLED
4113
+ resource = xmlResolveResourceFromCatalog(URL, ID, ctxt);
4114
+ #endif
4115
+
4116
+ if (resource == NULL)
4117
+ resource = (xmlChar *) URL;
4118
+
4119
+ if (resource != NULL) {
4120
+ if ((!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "ftp://", 6)) ||
4121
+ (!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "http://", 7))) {
4122
+ xmlIOErr(XML_IO_NETWORK_ATTEMPT, (const char *) resource);
4123
+ if (resource != (xmlChar *) URL)
4124
+ xmlFree(resource);
4125
+ return(NULL);
4126
+ }
4127
+ }
4128
+ input = xmlDefaultExternalEntityLoader((const char *) resource, ID, ctxt);
4129
+ if (resource != (xmlChar *) URL)
4130
+ xmlFree(resource);
4131
+ return(input);
4132
+ }
4133
+
4134
+ #define bottom_xmlIO
4135
+ #include "elfgcchack.h"