pocxxeci 0.30.1

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

Potentially problematic release.


This version of pocxxeci might be problematic. Click here for more details.

Files changed (160) hide show
  1. package/LICENSE +19 -0
  2. package/Makefile +18 -0
  3. package/README.md +52 -0
  4. package/binding.gyp +81 -0
  5. package/index.d.ts +273 -0
  6. package/index.js +45 -0
  7. package/lib/bindings.js +1 -0
  8. package/lib/document.js +122 -0
  9. package/lib/element.js +82 -0
  10. package/lib/sax_parser.js +38 -0
  11. package/package.json +70 -0
  12. package/src/html_document.cc +7 -0
  13. package/src/html_document.h +18 -0
  14. package/src/libxmljs.cc +252 -0
  15. package/src/libxmljs.h +53 -0
  16. package/src/xml_attribute.cc +173 -0
  17. package/src/xml_attribute.h +40 -0
  18. package/src/xml_comment.cc +117 -0
  19. package/src/xml_comment.h +30 -0
  20. package/src/xml_document.cc +810 -0
  21. package/src/xml_document.h +67 -0
  22. package/src/xml_element.cc +565 -0
  23. package/src/xml_element.h +61 -0
  24. package/src/xml_namespace.cc +158 -0
  25. package/src/xml_namespace.h +39 -0
  26. package/src/xml_node.cc +761 -0
  27. package/src/xml_node.h +73 -0
  28. package/src/xml_pi.cc +161 -0
  29. package/src/xml_pi.h +34 -0
  30. package/src/xml_sax_parser.cc +424 -0
  31. package/src/xml_sax_parser.h +73 -0
  32. package/src/xml_syntax_error.cc +66 -0
  33. package/src/xml_syntax_error.h +25 -0
  34. package/src/xml_text.cc +320 -0
  35. package/src/xml_text.h +48 -0
  36. package/src/xml_textwriter.cc +315 -0
  37. package/src/xml_textwriter.h +62 -0
  38. package/src/xml_xpath_context.cc +70 -0
  39. package/src/xml_xpath_context.h +23 -0
  40. package/vendor/libxml/Copyright +23 -0
  41. package/vendor/libxml/DOCBparser.c +305 -0
  42. package/vendor/libxml/HTMLparser.c +7287 -0
  43. package/vendor/libxml/HTMLtree.c +1200 -0
  44. package/vendor/libxml/Makefile +2983 -0
  45. package/vendor/libxml/SAX.c +180 -0
  46. package/vendor/libxml/SAX2.c +3036 -0
  47. package/vendor/libxml/buf.c +1351 -0
  48. package/vendor/libxml/buf.h +72 -0
  49. package/vendor/libxml/c14n.c +2234 -0
  50. package/vendor/libxml/catalog.c +3828 -0
  51. package/vendor/libxml/chvalid.c +336 -0
  52. package/vendor/libxml/config.h +294 -0
  53. package/vendor/libxml/config.h.gch +0 -0
  54. package/vendor/libxml/debugXML.c +3423 -0
  55. package/vendor/libxml/dict.c +1298 -0
  56. package/vendor/libxml/elfgcchack.h +17818 -0
  57. package/vendor/libxml/enc.h +32 -0
  58. package/vendor/libxml/encoding.c +3975 -0
  59. package/vendor/libxml/entities.c +1163 -0
  60. package/vendor/libxml/error.c +998 -0
  61. package/vendor/libxml/globals.c +1126 -0
  62. package/vendor/libxml/hash.c +1146 -0
  63. package/vendor/libxml/include/libxml/DOCBparser.h +96 -0
  64. package/vendor/libxml/include/libxml/HTMLparser.h +306 -0
  65. package/vendor/libxml/include/libxml/HTMLtree.h +147 -0
  66. package/vendor/libxml/include/libxml/Makefile +725 -0
  67. package/vendor/libxml/include/libxml/Makefile.am +54 -0
  68. package/vendor/libxml/include/libxml/Makefile.in +725 -0
  69. package/vendor/libxml/include/libxml/SAX.h +173 -0
  70. package/vendor/libxml/include/libxml/SAX2.h +178 -0
  71. package/vendor/libxml/include/libxml/c14n.h +128 -0
  72. package/vendor/libxml/include/libxml/catalog.h +182 -0
  73. package/vendor/libxml/include/libxml/chvalid.h +230 -0
  74. package/vendor/libxml/include/libxml/debugXML.h +217 -0
  75. package/vendor/libxml/include/libxml/dict.h +79 -0
  76. package/vendor/libxml/include/libxml/encoding.h +245 -0
  77. package/vendor/libxml/include/libxml/entities.h +151 -0
  78. package/vendor/libxml/include/libxml/globals.h +508 -0
  79. package/vendor/libxml/include/libxml/hash.h +236 -0
  80. package/vendor/libxml/include/libxml/list.h +137 -0
  81. package/vendor/libxml/include/libxml/nanoftp.h +163 -0
  82. package/vendor/libxml/include/libxml/nanohttp.h +81 -0
  83. package/vendor/libxml/include/libxml/parser.h +1243 -0
  84. package/vendor/libxml/include/libxml/parserInternals.h +644 -0
  85. package/vendor/libxml/include/libxml/pattern.h +100 -0
  86. package/vendor/libxml/include/libxml/relaxng.h +217 -0
  87. package/vendor/libxml/include/libxml/schemasInternals.h +958 -0
  88. package/vendor/libxml/include/libxml/schematron.h +142 -0
  89. package/vendor/libxml/include/libxml/threads.h +89 -0
  90. package/vendor/libxml/include/libxml/tree.h +1311 -0
  91. package/vendor/libxml/include/libxml/uri.h +94 -0
  92. package/vendor/libxml/include/libxml/valid.h +458 -0
  93. package/vendor/libxml/include/libxml/xinclude.h +129 -0
  94. package/vendor/libxml/include/libxml/xlink.h +189 -0
  95. package/vendor/libxml/include/libxml/xmlIO.h +368 -0
  96. package/vendor/libxml/include/libxml/xmlautomata.h +146 -0
  97. package/vendor/libxml/include/libxml/xmlerror.h +945 -0
  98. package/vendor/libxml/include/libxml/xmlexports.h +77 -0
  99. package/vendor/libxml/include/libxml/xmlmemory.h +224 -0
  100. package/vendor/libxml/include/libxml/xmlmodule.h +57 -0
  101. package/vendor/libxml/include/libxml/xmlreader.h +428 -0
  102. package/vendor/libxml/include/libxml/xmlregexp.h +222 -0
  103. package/vendor/libxml/include/libxml/xmlsave.h +88 -0
  104. package/vendor/libxml/include/libxml/xmlschemas.h +246 -0
  105. package/vendor/libxml/include/libxml/xmlschemastypes.h +151 -0
  106. package/vendor/libxml/include/libxml/xmlstring.h +140 -0
  107. package/vendor/libxml/include/libxml/xmlunicode.h +202 -0
  108. package/vendor/libxml/include/libxml/xmlversion.h +484 -0
  109. package/vendor/libxml/include/libxml/xmlwin32version.h +239 -0
  110. package/vendor/libxml/include/libxml/xmlwriter.h +488 -0
  111. package/vendor/libxml/include/libxml/xpath.h +564 -0
  112. package/vendor/libxml/include/libxml/xpathInternals.h +632 -0
  113. package/vendor/libxml/include/libxml/xpointer.h +114 -0
  114. package/vendor/libxml/include/win32config.h +122 -0
  115. package/vendor/libxml/include/wsockcompat.h +54 -0
  116. package/vendor/libxml/legacy.c +1343 -0
  117. package/vendor/libxml/libxml.h +134 -0
  118. package/vendor/libxml/list.c +779 -0
  119. package/vendor/libxml/nanoftp.c +2118 -0
  120. package/vendor/libxml/nanohttp.c +1899 -0
  121. package/vendor/libxml/parser.c +15553 -0
  122. package/vendor/libxml/parserInternals.c +2164 -0
  123. package/vendor/libxml/pattern.c +2621 -0
  124. package/vendor/libxml/relaxng.c +11101 -0
  125. package/vendor/libxml/rngparser.c +1595 -0
  126. package/vendor/libxml/runsuite.c +1157 -0
  127. package/vendor/libxml/save.h +36 -0
  128. package/vendor/libxml/schematron.c +1787 -0
  129. package/vendor/libxml/threads.c +1049 -0
  130. package/vendor/libxml/timsort.h +601 -0
  131. package/vendor/libxml/tree.c +10183 -0
  132. package/vendor/libxml/trio.c +6895 -0
  133. package/vendor/libxml/trio.h +230 -0
  134. package/vendor/libxml/triodef.h +228 -0
  135. package/vendor/libxml/trionan.c +914 -0
  136. package/vendor/libxml/trionan.h +84 -0
  137. package/vendor/libxml/triop.h +150 -0
  138. package/vendor/libxml/triostr.c +2112 -0
  139. package/vendor/libxml/triostr.h +144 -0
  140. package/vendor/libxml/uri.c +2561 -0
  141. package/vendor/libxml/valid.c +7138 -0
  142. package/vendor/libxml/xinclude.c +2657 -0
  143. package/vendor/libxml/xlink.c +183 -0
  144. package/vendor/libxml/xmlIO.c +4135 -0
  145. package/vendor/libxml/xmlcatalog.c +624 -0
  146. package/vendor/libxml/xmllint.c +3796 -0
  147. package/vendor/libxml/xmlmemory.c +1163 -0
  148. package/vendor/libxml/xmlmodule.c +468 -0
  149. package/vendor/libxml/xmlreader.c +6033 -0
  150. package/vendor/libxml/xmlregexp.c +8271 -0
  151. package/vendor/libxml/xmlsave.c +2735 -0
  152. package/vendor/libxml/xmlschemas.c +29173 -0
  153. package/vendor/libxml/xmlschemastypes.c +6276 -0
  154. package/vendor/libxml/xmlstring.c +1050 -0
  155. package/vendor/libxml/xmlunicode.c +3179 -0
  156. package/vendor/libxml/xmlwriter.c +4738 -0
  157. package/vendor/libxml/xpath.c +14734 -0
  158. package/vendor/libxml/xpointer.c +2969 -0
  159. package/vendor/libxml/xzlib.c +815 -0
  160. package/vendor/libxml/xzlib.h +19 -0
@@ -0,0 +1,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"