pocjenkixx 0.30.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of pocjenkixx might be problematic. Click here for more details.
- package/LICENSE +19 -0
- package/Makefile +18 -0
- package/README.md +52 -0
- package/binding.gyp +81 -0
- package/index.d.ts +273 -0
- package/index.js +45 -0
- package/lib/bindings.js +1 -0
- package/lib/document.js +122 -0
- package/lib/element.js +82 -0
- package/lib/sax_parser.js +38 -0
- package/package.json +70 -0
- package/src/html_document.cc +7 -0
- package/src/html_document.h +18 -0
- package/src/libxmljs.cc +252 -0
- package/src/libxmljs.h +53 -0
- package/src/xml_attribute.cc +173 -0
- package/src/xml_attribute.h +40 -0
- package/src/xml_comment.cc +117 -0
- package/src/xml_comment.h +30 -0
- package/src/xml_document.cc +810 -0
- package/src/xml_document.h +67 -0
- package/src/xml_element.cc +565 -0
- package/src/xml_element.h +61 -0
- package/src/xml_namespace.cc +158 -0
- package/src/xml_namespace.h +39 -0
- package/src/xml_node.cc +761 -0
- package/src/xml_node.h +73 -0
- package/src/xml_pi.cc +161 -0
- package/src/xml_pi.h +34 -0
- package/src/xml_sax_parser.cc +424 -0
- package/src/xml_sax_parser.h +73 -0
- package/src/xml_syntax_error.cc +66 -0
- package/src/xml_syntax_error.h +25 -0
- package/src/xml_text.cc +320 -0
- package/src/xml_text.h +48 -0
- package/src/xml_textwriter.cc +315 -0
- package/src/xml_textwriter.h +62 -0
- package/src/xml_xpath_context.cc +70 -0
- package/src/xml_xpath_context.h +23 -0
- package/vendor/libxml/Copyright +23 -0
- package/vendor/libxml/DOCBparser.c +305 -0
- package/vendor/libxml/HTMLparser.c +7287 -0
- package/vendor/libxml/HTMLtree.c +1200 -0
- package/vendor/libxml/Makefile +2983 -0
- package/vendor/libxml/SAX.c +180 -0
- package/vendor/libxml/SAX2.c +3036 -0
- package/vendor/libxml/buf.c +1351 -0
- package/vendor/libxml/buf.h +72 -0
- package/vendor/libxml/c14n.c +2234 -0
- package/vendor/libxml/catalog.c +3828 -0
- package/vendor/libxml/chvalid.c +336 -0
- package/vendor/libxml/config.h +294 -0
- package/vendor/libxml/config.h.gch +0 -0
- package/vendor/libxml/debugXML.c +3423 -0
- package/vendor/libxml/dict.c +1298 -0
- package/vendor/libxml/elfgcchack.h +17818 -0
- package/vendor/libxml/enc.h +32 -0
- package/vendor/libxml/encoding.c +3975 -0
- package/vendor/libxml/entities.c +1163 -0
- package/vendor/libxml/error.c +998 -0
- package/vendor/libxml/globals.c +1126 -0
- package/vendor/libxml/hash.c +1146 -0
- package/vendor/libxml/include/libxml/DOCBparser.h +96 -0
- package/vendor/libxml/include/libxml/HTMLparser.h +306 -0
- package/vendor/libxml/include/libxml/HTMLtree.h +147 -0
- package/vendor/libxml/include/libxml/Makefile +725 -0
- package/vendor/libxml/include/libxml/Makefile.am +54 -0
- package/vendor/libxml/include/libxml/Makefile.in +725 -0
- package/vendor/libxml/include/libxml/SAX.h +173 -0
- package/vendor/libxml/include/libxml/SAX2.h +178 -0
- package/vendor/libxml/include/libxml/c14n.h +128 -0
- package/vendor/libxml/include/libxml/catalog.h +182 -0
- package/vendor/libxml/include/libxml/chvalid.h +230 -0
- package/vendor/libxml/include/libxml/debugXML.h +217 -0
- package/vendor/libxml/include/libxml/dict.h +79 -0
- package/vendor/libxml/include/libxml/encoding.h +245 -0
- package/vendor/libxml/include/libxml/entities.h +151 -0
- package/vendor/libxml/include/libxml/globals.h +508 -0
- package/vendor/libxml/include/libxml/hash.h +236 -0
- package/vendor/libxml/include/libxml/list.h +137 -0
- package/vendor/libxml/include/libxml/nanoftp.h +163 -0
- package/vendor/libxml/include/libxml/nanohttp.h +81 -0
- package/vendor/libxml/include/libxml/parser.h +1243 -0
- package/vendor/libxml/include/libxml/parserInternals.h +644 -0
- package/vendor/libxml/include/libxml/pattern.h +100 -0
- package/vendor/libxml/include/libxml/relaxng.h +217 -0
- package/vendor/libxml/include/libxml/schemasInternals.h +958 -0
- package/vendor/libxml/include/libxml/schematron.h +142 -0
- package/vendor/libxml/include/libxml/threads.h +89 -0
- package/vendor/libxml/include/libxml/tree.h +1311 -0
- package/vendor/libxml/include/libxml/uri.h +94 -0
- package/vendor/libxml/include/libxml/valid.h +458 -0
- package/vendor/libxml/include/libxml/xinclude.h +129 -0
- package/vendor/libxml/include/libxml/xlink.h +189 -0
- package/vendor/libxml/include/libxml/xmlIO.h +368 -0
- package/vendor/libxml/include/libxml/xmlautomata.h +146 -0
- package/vendor/libxml/include/libxml/xmlerror.h +945 -0
- package/vendor/libxml/include/libxml/xmlexports.h +77 -0
- package/vendor/libxml/include/libxml/xmlmemory.h +224 -0
- package/vendor/libxml/include/libxml/xmlmodule.h +57 -0
- package/vendor/libxml/include/libxml/xmlreader.h +428 -0
- package/vendor/libxml/include/libxml/xmlregexp.h +222 -0
- package/vendor/libxml/include/libxml/xmlsave.h +88 -0
- package/vendor/libxml/include/libxml/xmlschemas.h +246 -0
- package/vendor/libxml/include/libxml/xmlschemastypes.h +151 -0
- package/vendor/libxml/include/libxml/xmlstring.h +140 -0
- package/vendor/libxml/include/libxml/xmlunicode.h +202 -0
- package/vendor/libxml/include/libxml/xmlversion.h +484 -0
- package/vendor/libxml/include/libxml/xmlwin32version.h +239 -0
- package/vendor/libxml/include/libxml/xmlwriter.h +488 -0
- package/vendor/libxml/include/libxml/xpath.h +564 -0
- package/vendor/libxml/include/libxml/xpathInternals.h +632 -0
- package/vendor/libxml/include/libxml/xpointer.h +114 -0
- package/vendor/libxml/include/win32config.h +122 -0
- package/vendor/libxml/include/wsockcompat.h +54 -0
- package/vendor/libxml/legacy.c +1343 -0
- package/vendor/libxml/libxml.h +134 -0
- package/vendor/libxml/list.c +779 -0
- package/vendor/libxml/nanoftp.c +2118 -0
- package/vendor/libxml/nanohttp.c +1899 -0
- package/vendor/libxml/parser.c +15553 -0
- package/vendor/libxml/parserInternals.c +2164 -0
- package/vendor/libxml/pattern.c +2621 -0
- package/vendor/libxml/relaxng.c +11101 -0
- package/vendor/libxml/rngparser.c +1595 -0
- package/vendor/libxml/runsuite.c +1157 -0
- package/vendor/libxml/save.h +36 -0
- package/vendor/libxml/schematron.c +1787 -0
- package/vendor/libxml/threads.c +1049 -0
- package/vendor/libxml/timsort.h +601 -0
- package/vendor/libxml/tree.c +10183 -0
- package/vendor/libxml/trio.c +6895 -0
- package/vendor/libxml/trio.h +230 -0
- package/vendor/libxml/triodef.h +228 -0
- package/vendor/libxml/trionan.c +914 -0
- package/vendor/libxml/trionan.h +84 -0
- package/vendor/libxml/triop.h +150 -0
- package/vendor/libxml/triostr.c +2112 -0
- package/vendor/libxml/triostr.h +144 -0
- package/vendor/libxml/uri.c +2561 -0
- package/vendor/libxml/valid.c +7138 -0
- package/vendor/libxml/xinclude.c +2657 -0
- package/vendor/libxml/xlink.c +183 -0
- package/vendor/libxml/xmlIO.c +4135 -0
- package/vendor/libxml/xmlcatalog.c +624 -0
- package/vendor/libxml/xmllint.c +3796 -0
- package/vendor/libxml/xmlmemory.c +1163 -0
- package/vendor/libxml/xmlmodule.c +468 -0
- package/vendor/libxml/xmlreader.c +6033 -0
- package/vendor/libxml/xmlregexp.c +8271 -0
- package/vendor/libxml/xmlsave.c +2735 -0
- package/vendor/libxml/xmlschemas.c +29173 -0
- package/vendor/libxml/xmlschemastypes.c +6276 -0
- package/vendor/libxml/xmlstring.c +1050 -0
- package/vendor/libxml/xmlunicode.c +3179 -0
- package/vendor/libxml/xmlwriter.c +4738 -0
- package/vendor/libxml/xpath.c +14734 -0
- package/vendor/libxml/xpointer.c +2969 -0
- package/vendor/libxml/xzlib.c +815 -0
- 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"
|