blob: 788d026d075095f2149e27875ced053fe237c705 [file] [log] [blame]
Owen Taylor3473f882001-02-23 17:55:21 +00001/*
2 * xmlIO.c : implementation of the I/O interfaces used by the parser
3 *
4 * See Copyright for the status of this software.
5 *
Daniel Veillard344cee72001-08-20 00:08:40 +00006 * daniel@veillard.com
Owen Taylor3473f882001-02-23 17:55:21 +00007 *
8 * 14 Nov 2000 ht - for VMS, truncated name of long functions to under 32 char
9 */
10
Daniel Veillard34ce8be2002-03-18 19:37:11 +000011#define IN_LIBXML
Bjorn Reese70a9da52001-04-21 16:57:29 +000012#include "libxml.h"
Owen Taylor3473f882001-02-23 17:55:21 +000013
Owen Taylor3473f882001-02-23 17:55:21 +000014#include <string.h>
Daniel Veillard92727042002-09-17 17:59:20 +000015#ifdef HAVE_ERRNO_H
Owen Taylor3473f882001-02-23 17:55:21 +000016#include <errno.h>
Daniel Veillard92727042002-09-17 17:59:20 +000017#endif
18
Owen Taylor3473f882001-02-23 17:55:21 +000019
20#ifdef HAVE_SYS_TYPES_H
21#include <sys/types.h>
22#endif
23#ifdef HAVE_SYS_STAT_H
24#include <sys/stat.h>
25#endif
26#ifdef HAVE_FCNTL_H
27#include <fcntl.h>
28#endif
29#ifdef HAVE_UNISTD_H
30#include <unistd.h>
31#endif
32#ifdef HAVE_STDLIB_H
33#include <stdlib.h>
34#endif
35#ifdef HAVE_ZLIB_H
36#include <zlib.h>
37#endif
38
Daniel Veillard59d3ed82007-04-17 12:44:58 +000039#if defined(WIN32) || defined(_WIN32)
Daniel Veillardf7416012006-04-27 08:15:20 +000040#include <windows.h>
41#endif
42
Daniel Veillard59d3ed82007-04-17 12:44:58 +000043#if defined(_WIN32_WCE)
44#include <winnls.h> /* for CP_UTF8 */
45#endif
46
Owen Taylor3473f882001-02-23 17:55:21 +000047/* Figure a portable way to know if a file is a directory. */
48#ifndef HAVE_STAT
49# ifdef HAVE__STAT
Daniel Veillard50f34372001-08-03 12:06:36 +000050 /* MS C library seems to define stat and _stat. The definition
51 is identical. Still, mapping them to each other causes a warning. */
52# ifndef _MSC_VER
53# define stat(x,y) _stat(x,y)
54# endif
Owen Taylor3473f882001-02-23 17:55:21 +000055# define HAVE_STAT
56# endif
Daniel Veillard8ca85b22006-09-01 09:56:07 +000057#else
58# ifdef HAVE__STAT
Daniel Veillard0da41662006-10-10 09:05:36 +000059# if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
Daniel Veillard8ca85b22006-09-01 09:56:07 +000060# define stat _stat
Daniel Veillard0da41662006-10-10 09:05:36 +000061# endif
Daniel Veillard8ca85b22006-09-01 09:56:07 +000062# endif
Owen Taylor3473f882001-02-23 17:55:21 +000063#endif
64#ifdef HAVE_STAT
65# ifndef S_ISDIR
66# ifdef _S_ISDIR
67# define S_ISDIR(x) _S_ISDIR(x)
68# else
69# ifdef S_IFDIR
70# ifndef S_IFMT
71# ifdef _S_IFMT
72# define S_IFMT _S_IFMT
73# endif
74# endif
75# ifdef S_IFMT
76# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
77# endif
78# endif
79# endif
80# endif
81#endif
82
83#include <libxml/xmlmemory.h>
84#include <libxml/parser.h>
85#include <libxml/parserInternals.h>
86#include <libxml/xmlIO.h>
Daniel Veillard388236f2001-07-08 18:35:48 +000087#include <libxml/uri.h>
Owen Taylor3473f882001-02-23 17:55:21 +000088#include <libxml/nanohttp.h>
89#include <libxml/nanoftp.h>
90#include <libxml/xmlerror.h>
Daniel Veillard7d6fd212001-05-10 15:34:11 +000091#ifdef LIBXML_CATALOG_ENABLED
92#include <libxml/catalog.h>
93#endif
Daniel Veillard3c01b1d2001-10-17 15:58:35 +000094#include <libxml/globals.h>
Owen Taylor3473f882001-02-23 17:55:21 +000095
Daniel Veillardf012a642001-07-23 19:10:52 +000096/* #define VERBOSE_FAILURE */
Daniel Veillard1fd36d22001-07-04 22:54:28 +000097/* #define DEBUG_EXTERNAL_ENTITIES */
Owen Taylor3473f882001-02-23 17:55:21 +000098/* #define DEBUG_INPUT */
99
100#ifdef DEBUG_INPUT
101#define MINLEN 40
102#else
103#define MINLEN 4000
104#endif
105
106/*
107 * Input I/O callback sets
108 */
109typedef struct _xmlInputCallback {
110 xmlInputMatchCallback matchcallback;
111 xmlInputOpenCallback opencallback;
112 xmlInputReadCallback readcallback;
113 xmlInputCloseCallback closecallback;
114} xmlInputCallback;
115
116#define MAX_INPUT_CALLBACK 15
117
Daniel Veillard22090732001-07-16 00:06:07 +0000118static xmlInputCallback xmlInputCallbackTable[MAX_INPUT_CALLBACK];
119static int xmlInputCallbackNr = 0;
120static int xmlInputCallbackInitialized = 0;
Owen Taylor3473f882001-02-23 17:55:21 +0000121
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000122#ifdef LIBXML_OUTPUT_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +0000123/*
124 * Output I/O callback sets
125 */
126typedef struct _xmlOutputCallback {
127 xmlOutputMatchCallback matchcallback;
128 xmlOutputOpenCallback opencallback;
129 xmlOutputWriteCallback writecallback;
130 xmlOutputCloseCallback closecallback;
131} xmlOutputCallback;
132
133#define MAX_OUTPUT_CALLBACK 15
134
Daniel Veillard22090732001-07-16 00:06:07 +0000135static xmlOutputCallback xmlOutputCallbackTable[MAX_OUTPUT_CALLBACK];
136static int xmlOutputCallbackNr = 0;
137static int xmlOutputCallbackInitialized = 0;
Daniel Veillardda3fee42008-09-01 13:08:57 +0000138
139xmlOutputBufferPtr
140xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000141#endif /* LIBXML_OUTPUT_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +0000142
Daniel Veillard05d987b2003-10-08 11:54:57 +0000143/************************************************************************
144 * *
Hans Breuer2ad41ca2009-08-11 17:51:22 +0200145 * Tree memory error handler *
Daniel Veillard05d987b2003-10-08 11:54:57 +0000146 * *
147 ************************************************************************/
Daniel Veillardf4862f02002-09-10 11:13:43 +0000148
Daniel Veillard05d987b2003-10-08 11:54:57 +0000149static const char *IOerr[] = {
Daniel Veillarda8856222003-10-08 19:26:03 +0000150 "Unknown IO error", /* UNKNOWN */
Daniel Veillard05d987b2003-10-08 11:54:57 +0000151 "Permission denied", /* EACCES */
152 "Resource temporarily unavailable",/* EAGAIN */
153 "Bad file descriptor", /* EBADF */
154 "Bad message", /* EBADMSG */
155 "Resource busy", /* EBUSY */
156 "Operation canceled", /* ECANCELED */
157 "No child processes", /* ECHILD */
158 "Resource deadlock avoided",/* EDEADLK */
159 "Domain error", /* EDOM */
160 "File exists", /* EEXIST */
161 "Bad address", /* EFAULT */
162 "File too large", /* EFBIG */
163 "Operation in progress", /* EINPROGRESS */
164 "Interrupted function call",/* EINTR */
165 "Invalid argument", /* EINVAL */
166 "Input/output error", /* EIO */
167 "Is a directory", /* EISDIR */
168 "Too many open files", /* EMFILE */
169 "Too many links", /* EMLINK */
170 "Inappropriate message buffer length",/* EMSGSIZE */
171 "Filename too long", /* ENAMETOOLONG */
172 "Too many open files in system",/* ENFILE */
173 "No such device", /* ENODEV */
174 "No such file or directory",/* ENOENT */
175 "Exec format error", /* ENOEXEC */
176 "No locks available", /* ENOLCK */
177 "Not enough space", /* ENOMEM */
178 "No space left on device", /* ENOSPC */
179 "Function not implemented", /* ENOSYS */
180 "Not a directory", /* ENOTDIR */
181 "Directory not empty", /* ENOTEMPTY */
182 "Not supported", /* ENOTSUP */
183 "Inappropriate I/O control operation",/* ENOTTY */
184 "No such device or address",/* ENXIO */
185 "Operation not permitted", /* EPERM */
186 "Broken pipe", /* EPIPE */
187 "Result too large", /* ERANGE */
188 "Read-only file system", /* EROFS */
189 "Invalid seek", /* ESPIPE */
190 "No such process", /* ESRCH */
191 "Operation timed out", /* ETIMEDOUT */
192 "Improper link", /* EXDEV */
Daniel Veillard2b0f8792003-10-10 19:36:36 +0000193 "Attempt to load network entity %s", /* XML_IO_NETWORK_ATTEMPT */
Daniel Veillard05d987b2003-10-08 11:54:57 +0000194 "encoder error", /* XML_IO_ENCODER */
Daniel Veillard2b0f8792003-10-10 19:36:36 +0000195 "flush error",
196 "write error",
197 "no input",
198 "buffer full",
199 "loading error",
200 "not a socket", /* ENOTSOCK */
201 "already connected", /* EISCONN */
Daniel Veillard29b17482004-08-16 00:39:03 +0000202 "connection refused", /* ECONNREFUSED */
Daniel Veillard2b0f8792003-10-10 19:36:36 +0000203 "unreachable network", /* ENETUNREACH */
204 "adddress in use", /* EADDRINUSE */
205 "already in use", /* EALREADY */
206 "unknown address familly", /* EAFNOSUPPORT */
Daniel Veillard05d987b2003-10-08 11:54:57 +0000207};
208
Daniel Veillard8ca85b22006-09-01 09:56:07 +0000209#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
Daniel Veillardf7416012006-04-27 08:15:20 +0000210/**
211 * __xmlIOWin32UTF8ToWChar:
212 * @u8String: uft-8 string
213 *
214 * Convert a string from utf-8 to wchar (WINDOWS ONLY!)
215 */
216static wchar_t *
217__xmlIOWin32UTF8ToWChar(const char *u8String)
218{
Daniel Veillard6ad5c4a2006-10-11 16:43:06 +0000219 wchar_t *wString = NULL;
Daniel Veillardf7416012006-04-27 08:15:20 +0000220
Daniel Veillard6ad5c4a2006-10-11 16:43:06 +0000221 if (u8String) {
222 int wLen =
223 MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, u8String,
224 -1, NULL, 0);
225 if (wLen) {
226 wString = xmlMalloc(wLen * sizeof(wchar_t));
227 if (wString) {
228 if (MultiByteToWideChar
229 (CP_UTF8, 0, u8String, -1, wString, wLen) == 0) {
230 xmlFree(wString);
231 wString = NULL;
232 }
233 }
234 }
235 }
236
237 return wString;
Daniel Veillardf7416012006-04-27 08:15:20 +0000238}
239#endif
240
Daniel Veillard05d987b2003-10-08 11:54:57 +0000241/**
242 * xmlIOErrMemory:
243 * @extra: extra informations
244 *
245 * Handle an out of memory condition
246 */
247static void
248xmlIOErrMemory(const char *extra)
249{
250 __xmlSimpleError(XML_FROM_IO, XML_ERR_NO_MEMORY, NULL, NULL, extra);
251}
252
253/**
Daniel Veillard2b0f8792003-10-10 19:36:36 +0000254 * __xmlIOErr:
Daniel Veillard05d987b2003-10-08 11:54:57 +0000255 * @code: the error number
Daniel Veillard2b0f8792003-10-10 19:36:36 +0000256 * @
Daniel Veillard05d987b2003-10-08 11:54:57 +0000257 * @extra: extra informations
258 *
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000259 * Handle an I/O error
Daniel Veillard05d987b2003-10-08 11:54:57 +0000260 */
Daniel Veillard2b0f8792003-10-10 19:36:36 +0000261void
262__xmlIOErr(int domain, int code, const char *extra)
Daniel Veillard05d987b2003-10-08 11:54:57 +0000263{
264 unsigned int idx;
265
266 if (code == 0) {
267#ifdef HAVE_ERRNO_H
268 if (errno == 0) code = 0;
269#ifdef EACCES
270 else if (errno == EACCES) code = XML_IO_EACCES;
271#endif
272#ifdef EAGAIN
273 else if (errno == EAGAIN) code = XML_IO_EAGAIN;
274#endif
275#ifdef EBADF
276 else if (errno == EBADF) code = XML_IO_EBADF;
277#endif
278#ifdef EBADMSG
279 else if (errno == EBADMSG) code = XML_IO_EBADMSG;
280#endif
281#ifdef EBUSY
282 else if (errno == EBUSY) code = XML_IO_EBUSY;
283#endif
284#ifdef ECANCELED
285 else if (errno == ECANCELED) code = XML_IO_ECANCELED;
286#endif
287#ifdef ECHILD
288 else if (errno == ECHILD) code = XML_IO_ECHILD;
289#endif
290#ifdef EDEADLK
291 else if (errno == EDEADLK) code = XML_IO_EDEADLK;
292#endif
293#ifdef EDOM
294 else if (errno == EDOM) code = XML_IO_EDOM;
295#endif
296#ifdef EEXIST
297 else if (errno == EEXIST) code = XML_IO_EEXIST;
298#endif
299#ifdef EFAULT
300 else if (errno == EFAULT) code = XML_IO_EFAULT;
301#endif
302#ifdef EFBIG
303 else if (errno == EFBIG) code = XML_IO_EFBIG;
304#endif
305#ifdef EINPROGRESS
306 else if (errno == EINPROGRESS) code = XML_IO_EINPROGRESS;
307#endif
308#ifdef EINTR
309 else if (errno == EINTR) code = XML_IO_EINTR;
310#endif
311#ifdef EINVAL
312 else if (errno == EINVAL) code = XML_IO_EINVAL;
313#endif
314#ifdef EIO
315 else if (errno == EIO) code = XML_IO_EIO;
316#endif
317#ifdef EISDIR
318 else if (errno == EISDIR) code = XML_IO_EISDIR;
319#endif
320#ifdef EMFILE
321 else if (errno == EMFILE) code = XML_IO_EMFILE;
322#endif
323#ifdef EMLINK
324 else if (errno == EMLINK) code = XML_IO_EMLINK;
325#endif
326#ifdef EMSGSIZE
327 else if (errno == EMSGSIZE) code = XML_IO_EMSGSIZE;
328#endif
329#ifdef ENAMETOOLONG
330 else if (errno == ENAMETOOLONG) code = XML_IO_ENAMETOOLONG;
331#endif
332#ifdef ENFILE
333 else if (errno == ENFILE) code = XML_IO_ENFILE;
334#endif
335#ifdef ENODEV
336 else if (errno == ENODEV) code = XML_IO_ENODEV;
337#endif
338#ifdef ENOENT
339 else if (errno == ENOENT) code = XML_IO_ENOENT;
340#endif
341#ifdef ENOEXEC
342 else if (errno == ENOEXEC) code = XML_IO_ENOEXEC;
343#endif
344#ifdef ENOLCK
345 else if (errno == ENOLCK) code = XML_IO_ENOLCK;
346#endif
347#ifdef ENOMEM
348 else if (errno == ENOMEM) code = XML_IO_ENOMEM;
349#endif
350#ifdef ENOSPC
351 else if (errno == ENOSPC) code = XML_IO_ENOSPC;
352#endif
353#ifdef ENOSYS
354 else if (errno == ENOSYS) code = XML_IO_ENOSYS;
355#endif
356#ifdef ENOTDIR
357 else if (errno == ENOTDIR) code = XML_IO_ENOTDIR;
358#endif
359#ifdef ENOTEMPTY
360 else if (errno == ENOTEMPTY) code = XML_IO_ENOTEMPTY;
361#endif
362#ifdef ENOTSUP
363 else if (errno == ENOTSUP) code = XML_IO_ENOTSUP;
364#endif
365#ifdef ENOTTY
366 else if (errno == ENOTTY) code = XML_IO_ENOTTY;
367#endif
368#ifdef ENXIO
369 else if (errno == ENXIO) code = XML_IO_ENXIO;
370#endif
371#ifdef EPERM
372 else if (errno == EPERM) code = XML_IO_EPERM;
373#endif
374#ifdef EPIPE
375 else if (errno == EPIPE) code = XML_IO_EPIPE;
376#endif
377#ifdef ERANGE
378 else if (errno == ERANGE) code = XML_IO_ERANGE;
379#endif
380#ifdef EROFS
381 else if (errno == EROFS) code = XML_IO_EROFS;
382#endif
383#ifdef ESPIPE
384 else if (errno == ESPIPE) code = XML_IO_ESPIPE;
385#endif
386#ifdef ESRCH
387 else if (errno == ESRCH) code = XML_IO_ESRCH;
388#endif
389#ifdef ETIMEDOUT
390 else if (errno == ETIMEDOUT) code = XML_IO_ETIMEDOUT;
391#endif
392#ifdef EXDEV
393 else if (errno == EXDEV) code = XML_IO_EXDEV;
394#endif
Daniel Veillard2b0f8792003-10-10 19:36:36 +0000395#ifdef ENOTSOCK
396 else if (errno == ENOTSOCK) code = XML_IO_ENOTSOCK;
397#endif
398#ifdef EISCONN
399 else if (errno == EISCONN) code = XML_IO_EISCONN;
400#endif
401#ifdef ECONNREFUSED
402 else if (errno == ECONNREFUSED) code = XML_IO_ECONNREFUSED;
403#endif
404#ifdef ETIMEDOUT
405 else if (errno == ETIMEDOUT) code = XML_IO_ETIMEDOUT;
406#endif
407#ifdef ENETUNREACH
408 else if (errno == ENETUNREACH) code = XML_IO_ENETUNREACH;
409#endif
410#ifdef EADDRINUSE
411 else if (errno == EADDRINUSE) code = XML_IO_EADDRINUSE;
412#endif
413#ifdef EINPROGRESS
414 else if (errno == EINPROGRESS) code = XML_IO_EINPROGRESS;
415#endif
416#ifdef EALREADY
417 else if (errno == EALREADY) code = XML_IO_EALREADY;
418#endif
419#ifdef EAFNOSUPPORT
420 else if (errno == EAFNOSUPPORT) code = XML_IO_EAFNOSUPPORT;
421#endif
Daniel Veillard05d987b2003-10-08 11:54:57 +0000422 else code = XML_IO_UNKNOWN;
423#endif /* HAVE_ERRNO_H */
424 }
425 idx = 0;
426 if (code >= XML_IO_UNKNOWN) idx = code - XML_IO_UNKNOWN;
427 if (idx >= (sizeof(IOerr) / sizeof(IOerr[0]))) idx = 0;
Hans Breuer2ad41ca2009-08-11 17:51:22 +0200428
Daniel Veillard2b0f8792003-10-10 19:36:36 +0000429 __xmlSimpleError(domain, code, NULL, IOerr[idx], extra);
430}
431
432/**
433 * xmlIOErr:
434 * @code: the error number
435 * @extra: extra informations
436 *
437 * Handle an I/O error
438 */
439static void
440xmlIOErr(int code, const char *extra)
441{
442 __xmlIOErr(XML_FROM_IO, code, extra);
Daniel Veillard05d987b2003-10-08 11:54:57 +0000443}
444
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000445/**
Daniel Veillarde8039df2003-10-27 11:25:13 +0000446 * __xmlLoaderErr:
447 * @ctx: the parser context
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000448 * @extra: extra informations
449 *
450 * Handle a resource access error
451 */
Daniel Veillarde8039df2003-10-27 11:25:13 +0000452void
453__xmlLoaderErr(void *ctx, const char *msg, const char *filename)
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000454{
Daniel Veillarde8039df2003-10-27 11:25:13 +0000455 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000456 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000457 xmlGenericErrorFunc channel = NULL;
458 void *data = NULL;
459 xmlErrorLevel level = XML_ERR_ERROR;
460
Daniel Veillard157fee02003-10-31 10:36:03 +0000461 if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
462 (ctxt->instate == XML_PARSER_EOF))
463 return;
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000464 if ((ctxt != NULL) && (ctxt->sax != NULL)) {
465 if (ctxt->validate) {
466 channel = ctxt->sax->error;
467 level = XML_ERR_ERROR;
468 } else {
469 channel = ctxt->sax->warning;
470 level = XML_ERR_WARNING;
471 }
Daniel Veillard5ea30d72004-11-08 11:54:28 +0000472 if (ctxt->sax->initialized == XML_SAX2_MAGIC)
473 schannel = ctxt->sax->serror;
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000474 data = ctxt->userData;
475 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000476 __xmlRaiseError(schannel, channel, data, ctxt, NULL, XML_FROM_IO,
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000477 XML_IO_LOAD_ERROR, level, NULL, 0,
478 filename, NULL, NULL, 0, 0,
479 msg, filename);
Hans Breuer2ad41ca2009-08-11 17:51:22 +0200480
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000481}
482
Daniel Veillard05d987b2003-10-08 11:54:57 +0000483/************************************************************************
484 * *
Hans Breuer2ad41ca2009-08-11 17:51:22 +0200485 * Tree memory error handler *
Daniel Veillard05d987b2003-10-08 11:54:57 +0000486 * *
487 ************************************************************************/
Daniel Veillardf4862f02002-09-10 11:13:43 +0000488/**
Daniel Veillard01c13b52002-12-10 15:19:08 +0000489 * xmlNormalizeWindowsPath:
Daniel Veillard33300b42003-04-17 09:09:19 +0000490 * @path: the input file path
Daniel Veillardf4862f02002-09-10 11:13:43 +0000491 *
Igor Zlatkovic5f9fada2003-02-19 14:51:00 +0000492 * This function is obsolete. Please see xmlURIFromPath in uri.c for
493 * a better solution.
Daniel Veillard33300b42003-04-17 09:09:19 +0000494 *
495 * Returns a canonicalized version of the path
Daniel Veillardf4862f02002-09-10 11:13:43 +0000496 */
497xmlChar *
498xmlNormalizeWindowsPath(const xmlChar *path)
499{
Igor Zlatkovic5f9fada2003-02-19 14:51:00 +0000500 return xmlCanonicPath(path);
Daniel Veillardf4862f02002-09-10 11:13:43 +0000501}
502
Daniel Veillardacf7ff02001-10-29 20:21:47 +0000503/**
504 * xmlCleanupInputCallbacks:
505 *
506 * clears the entire input callback table. this includes the
Hans Breuer2ad41ca2009-08-11 17:51:22 +0200507 * compiled-in I/O.
Daniel Veillardacf7ff02001-10-29 20:21:47 +0000508 */
509void
510xmlCleanupInputCallbacks(void)
511{
512 int i;
513
514 if (!xmlInputCallbackInitialized)
515 return;
516
Daniel Veillard107ccaa2001-11-27 16:23:50 +0000517 for (i = xmlInputCallbackNr - 1; i >= 0; i--) {
Daniel Veillardacf7ff02001-10-29 20:21:47 +0000518 xmlInputCallbackTable[i].matchcallback = NULL;
519 xmlInputCallbackTable[i].opencallback = NULL;
520 xmlInputCallbackTable[i].readcallback = NULL;
521 xmlInputCallbackTable[i].closecallback = NULL;
522 }
523
524 xmlInputCallbackNr = 0;
Aleksey Sanin9c45ba82002-06-06 21:46:13 +0000525 xmlInputCallbackInitialized = 0;
Daniel Veillardacf7ff02001-10-29 20:21:47 +0000526}
527
Daniel Veillardaecc0dc2004-05-08 02:32:07 +0000528/**
William M. Brack4e3a9fa2004-08-03 22:41:11 +0000529 * xmlPopInputCallbacks:
Daniel Veillardaecc0dc2004-05-08 02:32:07 +0000530 *
531 * Clear the top input callback from the input stack. this includes the
Hans Breuer2ad41ca2009-08-11 17:51:22 +0200532 * compiled-in I/O.
Daniel Veillardaecc0dc2004-05-08 02:32:07 +0000533 *
534 * Returns the number of input callback registered or -1 in case of error.
535 */
536int
537xmlPopInputCallbacks(void)
538{
539 if (!xmlInputCallbackInitialized)
540 return(-1);
541
542 if (xmlInputCallbackNr <= 0)
543 return(-1);
Hans Breuer2ad41ca2009-08-11 17:51:22 +0200544
Daniel Veillardaecc0dc2004-05-08 02:32:07 +0000545 xmlInputCallbackNr--;
546 xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = NULL;
547 xmlInputCallbackTable[xmlInputCallbackNr].opencallback = NULL;
548 xmlInputCallbackTable[xmlInputCallbackNr].readcallback = NULL;
549 xmlInputCallbackTable[xmlInputCallbackNr].closecallback = NULL;
550
551 return(xmlInputCallbackNr);
552}
553
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000554#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardacf7ff02001-10-29 20:21:47 +0000555/**
556 * xmlCleanupOutputCallbacks:
557 *
558 * clears the entire output callback table. this includes the
Hans Breuer2ad41ca2009-08-11 17:51:22 +0200559 * compiled-in I/O callbacks.
Daniel Veillardacf7ff02001-10-29 20:21:47 +0000560 */
561void
562xmlCleanupOutputCallbacks(void)
563{
564 int i;
565
566 if (!xmlOutputCallbackInitialized)
567 return;
568
Daniel Veillard107ccaa2001-11-27 16:23:50 +0000569 for (i = xmlOutputCallbackNr - 1; i >= 0; i--) {
Daniel Veillardacf7ff02001-10-29 20:21:47 +0000570 xmlOutputCallbackTable[i].matchcallback = NULL;
571 xmlOutputCallbackTable[i].opencallback = NULL;
572 xmlOutputCallbackTable[i].writecallback = NULL;
573 xmlOutputCallbackTable[i].closecallback = NULL;
574 }
575
576 xmlOutputCallbackNr = 0;
Aleksey Sanin9c45ba82002-06-06 21:46:13 +0000577 xmlOutputCallbackInitialized = 0;
Daniel Veillardacf7ff02001-10-29 20:21:47 +0000578}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000579#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillardacf7ff02001-10-29 20:21:47 +0000580
Owen Taylor3473f882001-02-23 17:55:21 +0000581/************************************************************************
582 * *
583 * Standard I/O for file accesses *
584 * *
585 ************************************************************************/
586
Daniel Veillard8ca85b22006-09-01 09:56:07 +0000587#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
588
589/**
590 * xmlWrapOpenUtf8:
591 * @path: the path in utf-8 encoding
592 * @mode: type of access (0 - read, 1 - write)
593 *
594 * function opens the file specified by @path
595 *
596 */
597static FILE*
598xmlWrapOpenUtf8(const char *path,int mode)
599{
600 FILE *fd = NULL;
601 wchar_t *wPath;
602
603 wPath = __xmlIOWin32UTF8ToWChar(path);
604 if(wPath)
605 {
606 fd = _wfopen(wPath, mode ? L"wb" : L"rb");
607 xmlFree(wPath);
608 }
Daniel Veillard0da41662006-10-10 09:05:36 +0000609 /* maybe path in native encoding */
Daniel Veillard8ca85b22006-09-01 09:56:07 +0000610 if(fd == NULL)
611 fd = fopen(path, mode ? "wb" : "rb");
612
613 return fd;
614}
615
Hans Breuer2ad41ca2009-08-11 17:51:22 +0200616static gzFile
617xmlWrapGzOpenUtf8(const char *path, const char *mode)
618{
619 gzFile fd;
620 wchar_t *wPath;
621
622 fd = gzopen (path, mode);
623 if (fd)
624 return fd;
625
626 wPath = __xmlIOWin32UTF8ToWChar(path);
627 if(wPath)
628 {
629 int d, m = (strstr(mode, "r") ? O_RDONLY : O_RDWR);
630#ifdef _O_BINARY
631 m |= (strstr(mode, "b") ? _O_BINARY : 0);
632#endif
633 d = _wopen(wPath, m);
634 if (d >= 0)
635 fd = gzdopen(d, mode);
636 xmlFree(wPath);
637 }
638
639 return fd;
640}
641
Daniel Veillard8ca85b22006-09-01 09:56:07 +0000642/**
643 * xmlWrapStatUtf8:
644 * @path: the path in utf-8 encoding
645 * @info: structure that stores results
646 *
647 * function obtains information about the file or directory
648 *
649 */
650static int
651xmlWrapStatUtf8(const char *path,struct stat *info)
652{
653#ifdef HAVE_STAT
654 int retval = -1;
655 wchar_t *wPath;
656
657 wPath = __xmlIOWin32UTF8ToWChar(path);
658 if (wPath)
659 {
660 retval = _wstat(wPath,info);
661 xmlFree(wPath);
662 }
Daniel Veillard0da41662006-10-10 09:05:36 +0000663 /* maybe path in native encoding */
Daniel Veillard8ca85b22006-09-01 09:56:07 +0000664 if(retval < 0)
665 retval = stat(path,info);
666 return retval;
667#else
668 return -1;
669#endif
670}
671
672/**
673 * xmlWrapOpenNative:
674 * @path: the path
675 * @mode: type of access (0 - read, 1 - write)
676 *
677 * function opens the file specified by @path
678 *
679 */
680static FILE*
681xmlWrapOpenNative(const char *path,int mode)
682{
683 return fopen(path,mode ? "wb" : "rb");
684}
685
686/**
687 * xmlWrapStatNative:
688 * @path: the path
689 * @info: structure that stores results
690 *
691 * function obtains information about the file or directory
692 *
693 */
694static int
695xmlWrapStatNative(const char *path,struct stat *info)
696{
697#ifdef HAVE_STAT
698 return stat(path,info);
699#else
700 return -1;
701#endif
702}
703
Daniel Veillard6ad5c4a2006-10-11 16:43:06 +0000704typedef int (* xmlWrapStatFunc) (const char *f, struct stat *s);
705static xmlWrapStatFunc xmlWrapStat = xmlWrapStatNative;
706typedef FILE* (* xmlWrapOpenFunc)(const char *f,int mode);
Rob Richards6460f922006-10-12 21:08:29 +0000707static xmlWrapOpenFunc xmlWrapOpen = xmlWrapOpenNative;
Hans Breuer2ad41ca2009-08-11 17:51:22 +0200708typedef gzFile (* xmlWrapGzOpenFunc) (const char *f, const char *mode);
709static xmlWrapGzOpenFunc xmlWrapGzOpen = gzopen;
Daniel Veillard8ca85b22006-09-01 09:56:07 +0000710
711/**
712 * xmlInitPlatformSpecificIo:
713 *
714 * Initialize platform specific features.
715 */
716static void
Daniel Veillard6ad5c4a2006-10-11 16:43:06 +0000717xmlInitPlatformSpecificIo(void)
718{
Daniel Veillard8ca85b22006-09-01 09:56:07 +0000719 static int xmlPlatformIoInitialized = 0;
720 OSVERSIONINFO osvi;
721
722 if(xmlPlatformIoInitialized)
723 return;
724
725 osvi.dwOSVersionInfoSize = sizeof(osvi);
726
727 if(GetVersionEx(&osvi) && (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)) {
728 xmlWrapStat = xmlWrapStatUtf8;
729 xmlWrapOpen = xmlWrapOpenUtf8;
Hans Breuer2ad41ca2009-08-11 17:51:22 +0200730 xmlWrapGzOpen = xmlWrapGzOpenUtf8;
Daniel Veillard8ca85b22006-09-01 09:56:07 +0000731 } else {
732 xmlWrapStat = xmlWrapStatNative;
733 xmlWrapOpen = xmlWrapOpenNative;
Hans Breuer2ad41ca2009-08-11 17:51:22 +0200734 xmlWrapGzOpen = gzopen;
Daniel Veillard8ca85b22006-09-01 09:56:07 +0000735 }
736
737 xmlPlatformIoInitialized = 1;
738 return;
739}
740
741#endif
742
Owen Taylor3473f882001-02-23 17:55:21 +0000743/**
Daniel Veillarda9b66d02002-12-11 14:23:49 +0000744 * xmlCheckFilename:
Owen Taylor3473f882001-02-23 17:55:21 +0000745 * @path: the path to check
746 *
747 * function checks to see if @path is a valid source
748 * (file, socket...) for XML.
749 *
750 * if stat is not available on the target machine,
751 * returns 1. if stat fails, returns 0 (if calling
752 * stat on the filename fails, it can't be right).
753 * if stat succeeds and the file is a directory,
Daniel Veillard819d5cb2002-10-14 11:15:18 +0000754 * returns 2. otherwise returns 1.
Owen Taylor3473f882001-02-23 17:55:21 +0000755 */
756
Daniel Veillard819d5cb2002-10-14 11:15:18 +0000757int
Owen Taylor3473f882001-02-23 17:55:21 +0000758xmlCheckFilename (const char *path)
759{
Daniel Veillard8ca85b22006-09-01 09:56:07 +0000760#ifdef HAVE_STAT
Daniel Veillard0b309952006-05-02 20:34:38 +0000761 struct stat stat_buffer;
762#endif
Daniel Veillardf7416012006-04-27 08:15:20 +0000763 if (path == NULL)
Daniel Veillard0b309952006-05-02 20:34:38 +0000764 return(0);
Daniel Veillarde5a3f372006-08-30 13:11:36 +0000765
Owen Taylor3473f882001-02-23 17:55:21 +0000766#ifdef HAVE_STAT
Daniel Veillard8ca85b22006-09-01 09:56:07 +0000767#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
768 if (xmlWrapStat(path, &stat_buffer) == -1)
769 return 0;
770#else
Owen Taylor3473f882001-02-23 17:55:21 +0000771 if (stat(path, &stat_buffer) == -1)
772 return 0;
Daniel Veillard8ca85b22006-09-01 09:56:07 +0000773#endif
Daniel Veillard819d5cb2002-10-14 11:15:18 +0000774#ifdef S_ISDIR
Daniel Veillardf7416012006-04-27 08:15:20 +0000775 if (S_ISDIR(stat_buffer.st_mode))
Daniel Veillard819d5cb2002-10-14 11:15:18 +0000776 return 2;
Daniel Veillard8ca85b22006-09-01 09:56:07 +0000777#endif
Daniel Veillardf7416012006-04-27 08:15:20 +0000778#endif /* HAVE_STAT */
Owen Taylor3473f882001-02-23 17:55:21 +0000779 return 1;
780}
781
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000782static int
Owen Taylor3473f882001-02-23 17:55:21 +0000783xmlNop(void) {
784 return(0);
785}
786
787/**
Owen Taylor3473f882001-02-23 17:55:21 +0000788 * xmlFdRead:
789 * @context: the I/O context
790 * @buffer: where to drop data
791 * @len: number of bytes to read
792 *
793 * Read @len bytes to @buffer from the I/O channel.
794 *
795 * Returns the number of bytes written
796 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000797static int
Owen Taylor3473f882001-02-23 17:55:21 +0000798xmlFdRead (void * context, char * buffer, int len) {
Daniel Veillard05d987b2003-10-08 11:54:57 +0000799 int ret;
800
801 ret = read((int) (long) context, &buffer[0], len);
802 if (ret < 0) xmlIOErr(0, "read()");
803 return(ret);
Owen Taylor3473f882001-02-23 17:55:21 +0000804}
805
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000806#ifdef LIBXML_OUTPUT_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +0000807/**
808 * xmlFdWrite:
809 * @context: the I/O context
810 * @buffer: where to get data
811 * @len: number of bytes to write
812 *
813 * Write @len bytes from @buffer to the I/O channel.
814 *
815 * Returns the number of bytes written
816 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000817static int
Owen Taylor3473f882001-02-23 17:55:21 +0000818xmlFdWrite (void * context, const char * buffer, int len) {
Daniel Veillard9b693b42005-10-28 14:54:17 +0000819 int ret = 0;
Daniel Veillard05d987b2003-10-08 11:54:57 +0000820
Daniel Veillard9b693b42005-10-28 14:54:17 +0000821 if (len > 0) {
822 ret = write((int) (long) context, &buffer[0], len);
823 if (ret < 0) xmlIOErr(0, "write()");
824 }
Daniel Veillard05d987b2003-10-08 11:54:57 +0000825 return(ret);
Owen Taylor3473f882001-02-23 17:55:21 +0000826}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000827#endif /* LIBXML_OUTPUT_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +0000828
829/**
830 * xmlFdClose:
831 * @context: the I/O context
832 *
833 * Close an I/O channel
Daniel Veillardf012a642001-07-23 19:10:52 +0000834 *
835 * Returns 0 in case of success and error code otherwise
Owen Taylor3473f882001-02-23 17:55:21 +0000836 */
Daniel Veillardf012a642001-07-23 19:10:52 +0000837static int
Owen Taylor3473f882001-02-23 17:55:21 +0000838xmlFdClose (void * context) {
Daniel Veillard05d987b2003-10-08 11:54:57 +0000839 int ret;
840 ret = close((int) (long) context);
841 if (ret < 0) xmlIOErr(0, "close()");
842 return(ret);
Owen Taylor3473f882001-02-23 17:55:21 +0000843}
844
845/**
846 * xmlFileMatch:
847 * @filename: the URI for matching
848 *
849 * input from FILE *
850 *
851 * Returns 1 if matches, 0 otherwise
852 */
Aleksey Sanin5aac8b82002-05-01 18:32:28 +0000853int
Daniel Veillardc86a4fa2001-03-26 16:28:29 +0000854xmlFileMatch (const char *filename ATTRIBUTE_UNUSED) {
Owen Taylor3473f882001-02-23 17:55:21 +0000855 return(1);
856}
857
858/**
Daniel Veillardcacbe5d2003-01-10 16:09:51 +0000859 * xmlFileOpen_real:
Owen Taylor3473f882001-02-23 17:55:21 +0000860 * @filename: the URI for matching
861 *
862 * input from FILE *, supports compressed input
863 * if @filename is " " then the standard input is used
864 *
865 * Returns an I/O context or NULL in case of error
866 */
Daniel Veillardcacbe5d2003-01-10 16:09:51 +0000867static void *
868xmlFileOpen_real (const char *filename) {
Owen Taylor3473f882001-02-23 17:55:21 +0000869 const char *path = NULL;
Daniel Veillard8ca85b22006-09-01 09:56:07 +0000870 FILE *fd;
Owen Taylor3473f882001-02-23 17:55:21 +0000871
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000872 if (filename == NULL)
873 return(NULL);
874
Owen Taylor3473f882001-02-23 17:55:21 +0000875 if (!strcmp(filename, "-")) {
876 fd = stdin;
877 return((void *) fd);
878 }
879
Daniel Veillard5cdbbd22007-06-12 09:39:14 +0000880 if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17)) {
Daniel Veillard1997c3e2003-07-05 20:43:43 +0000881#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
Daniel Veillardb212bbb2002-08-25 14:39:16 +0000882 path = &filename[17];
883#else
Owen Taylor3473f882001-02-23 17:55:21 +0000884 path = &filename[16];
Daniel Veillardb212bbb2002-08-25 14:39:16 +0000885#endif
Daniel Veillard5cdbbd22007-06-12 09:39:14 +0000886 } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
Daniel Veillard1997c3e2003-07-05 20:43:43 +0000887#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
Daniel Veillardfe703322001-08-14 12:18:09 +0000888 path = &filename[8];
889#else
Daniel Veillard3c2758d2001-05-31 18:43:43 +0000890 path = &filename[7];
Daniel Veillardfe703322001-08-14 12:18:09 +0000891#endif
Daniel Veillard5cdbbd22007-06-12 09:39:14 +0000892 } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:/", 6)) {
893 /* lots of generators seems to lazy to read RFC 1738 */
894#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
895 path = &filename[6];
896#else
897 path = &filename[5];
898#endif
Hans Breuer2ad41ca2009-08-11 17:51:22 +0200899 } else
Owen Taylor3473f882001-02-23 17:55:21 +0000900 path = filename;
901
902 if (path == NULL)
903 return(NULL);
904 if (!xmlCheckFilename(path))
905 return(NULL);
906
Daniel Veillard8ca85b22006-09-01 09:56:07 +0000907#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
908 fd = xmlWrapOpen(path, 0);
909#else
910 fd = fopen(path, "r");
Owen Taylor3473f882001-02-23 17:55:21 +0000911#endif /* WIN32 */
Daniel Veillard8ca85b22006-09-01 09:56:07 +0000912 if (fd == NULL) xmlIOErr(0, path);
Owen Taylor3473f882001-02-23 17:55:21 +0000913 return((void *) fd);
914}
915
916/**
Daniel Veillardcacbe5d2003-01-10 16:09:51 +0000917 * xmlFileOpen:
918 * @filename: the URI for matching
919 *
920 * Wrapper around xmlFileOpen_real that try it with an unescaped
921 * version of @filename, if this fails fallback to @filename
Daniel Veillard71531f32003-02-05 13:19:53 +0000922 *
923 * Returns a handler or NULL in case or failure
Daniel Veillardcacbe5d2003-01-10 16:09:51 +0000924 */
925void *
926xmlFileOpen (const char *filename) {
927 char *unescaped;
928 void *retval;
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000929
Daniel Veillardbd672bc2007-03-30 12:39:25 +0000930 retval = xmlFileOpen_real(filename);
931 if (retval == NULL) {
932 unescaped = xmlURIUnescapeString(filename, 0, NULL);
933 if (unescaped != NULL) {
934 retval = xmlFileOpen_real(unescaped);
935 xmlFree(unescaped);
936 }
Daniel Veillardcacbe5d2003-01-10 16:09:51 +0000937 }
Daniel Veillardbd672bc2007-03-30 12:39:25 +0000938
Daniel Veillardcacbe5d2003-01-10 16:09:51 +0000939 return retval;
940}
941
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000942#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardcacbe5d2003-01-10 16:09:51 +0000943/**
Owen Taylor3473f882001-02-23 17:55:21 +0000944 * xmlFileOpenW:
945 * @filename: the URI for matching
946 *
947 * output to from FILE *,
948 * if @filename is "-" then the standard output is used
949 *
950 * Returns an I/O context or NULL in case of error
951 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000952static void *
Owen Taylor3473f882001-02-23 17:55:21 +0000953xmlFileOpenW (const char *filename) {
954 const char *path = NULL;
Daniel Veillard8ca85b22006-09-01 09:56:07 +0000955 FILE *fd;
Owen Taylor3473f882001-02-23 17:55:21 +0000956
957 if (!strcmp(filename, "-")) {
958 fd = stdout;
959 return((void *) fd);
960 }
961
Daniel Veillardf4862f02002-09-10 11:13:43 +0000962 if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17))
Daniel Veillard1997c3e2003-07-05 20:43:43 +0000963#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
Daniel Veillardf4862f02002-09-10 11:13:43 +0000964 path = &filename[17];
965#else
Owen Taylor3473f882001-02-23 17:55:21 +0000966 path = &filename[16];
Daniel Veillardf4862f02002-09-10 11:13:43 +0000967#endif
Aleksey Sanin5aac8b82002-05-01 18:32:28 +0000968 else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
Daniel Veillard1997c3e2003-07-05 20:43:43 +0000969#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
Daniel Veillardfe703322001-08-14 12:18:09 +0000970 path = &filename[8];
971#else
Daniel Veillard3c2758d2001-05-31 18:43:43 +0000972 path = &filename[7];
Daniel Veillardfe703322001-08-14 12:18:09 +0000973#endif
Hans Breuer2ad41ca2009-08-11 17:51:22 +0200974 } else
Owen Taylor3473f882001-02-23 17:55:21 +0000975 path = filename;
976
977 if (path == NULL)
978 return(NULL);
979
Daniel Veillard8ca85b22006-09-01 09:56:07 +0000980#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
981 fd = xmlWrapOpen(path, 1);
982#else
Hans Breuer2ad41ca2009-08-11 17:51:22 +0200983 fd = fopen(path, "wb");
Daniel Veillard8ca85b22006-09-01 09:56:07 +0000984#endif /* WIN32 */
Daniel Veillarde5a3f372006-08-30 13:11:36 +0000985
Daniel Veillardf7416012006-04-27 08:15:20 +0000986 if (fd == NULL) xmlIOErr(0, path);
Owen Taylor3473f882001-02-23 17:55:21 +0000987 return((void *) fd);
988}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000989#endif /* LIBXML_OUTPUT_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +0000990
991/**
992 * xmlFileRead:
993 * @context: the I/O context
994 * @buffer: where to drop data
995 * @len: number of bytes to write
996 *
997 * Read @len bytes to @buffer from the I/O channel.
998 *
Daniel Veillardce682bc2004-11-05 17:22:25 +0000999 * Returns the number of bytes written or < 0 in case of failure
Owen Taylor3473f882001-02-23 17:55:21 +00001000 */
Aleksey Sanin5aac8b82002-05-01 18:32:28 +00001001int
Owen Taylor3473f882001-02-23 17:55:21 +00001002xmlFileRead (void * context, char * buffer, int len) {
Daniel Veillard05d987b2003-10-08 11:54:57 +00001003 int ret;
Hans Breuer2ad41ca2009-08-11 17:51:22 +02001004 if ((context == NULL) || (buffer == NULL))
Daniel Veillardce682bc2004-11-05 17:22:25 +00001005 return(-1);
Daniel Veillard05d987b2003-10-08 11:54:57 +00001006 ret = fread(&buffer[0], 1, len, (FILE *) context);
1007 if (ret < 0) xmlIOErr(0, "fread()");
1008 return(ret);
Owen Taylor3473f882001-02-23 17:55:21 +00001009}
1010
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001011#ifdef LIBXML_OUTPUT_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00001012/**
1013 * xmlFileWrite:
1014 * @context: the I/O context
1015 * @buffer: where to drop data
1016 * @len: number of bytes to write
1017 *
1018 * Write @len bytes from @buffer to the I/O channel.
1019 *
1020 * Returns the number of bytes written
1021 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +00001022static int
Owen Taylor3473f882001-02-23 17:55:21 +00001023xmlFileWrite (void * context, const char * buffer, int len) {
Daniel Veillard4a6d39b2002-12-17 18:33:01 +00001024 int items;
1025
Hans Breuer2ad41ca2009-08-11 17:51:22 +02001026 if ((context == NULL) || (buffer == NULL))
Daniel Veillardce682bc2004-11-05 17:22:25 +00001027 return(-1);
Daniel Veillard4a6d39b2002-12-17 18:33:01 +00001028 items = fwrite(&buffer[0], len, 1, (FILE *) context);
Daniel Veillard97bf4d02003-10-08 18:58:28 +00001029 if ((items == 0) && (ferror((FILE *) context))) {
Daniel Veillard05d987b2003-10-08 11:54:57 +00001030 xmlIOErr(0, "fwrite()");
Daniel Veillard97bf4d02003-10-08 18:58:28 +00001031 return(-1);
1032 }
Daniel Veillard4a6d39b2002-12-17 18:33:01 +00001033 return(items * len);
Owen Taylor3473f882001-02-23 17:55:21 +00001034}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001035#endif /* LIBXML_OUTPUT_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00001036
1037/**
1038 * xmlFileClose:
1039 * @context: the I/O context
1040 *
1041 * Close an I/O channel
Daniel Veillarda9b66d02002-12-11 14:23:49 +00001042 *
1043 * Returns 0 or -1 in case of error
Owen Taylor3473f882001-02-23 17:55:21 +00001044 */
Aleksey Sanin5aac8b82002-05-01 18:32:28 +00001045int
Owen Taylor3473f882001-02-23 17:55:21 +00001046xmlFileClose (void * context) {
Daniel Veillarda9e65e82001-10-30 10:32:36 +00001047 FILE *fil;
Daniel Veillard05d987b2003-10-08 11:54:57 +00001048 int ret;
Daniel Veillarda9e65e82001-10-30 10:32:36 +00001049
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +00001050 if (context == NULL)
1051 return(-1);
Daniel Veillarda9e65e82001-10-30 10:32:36 +00001052 fil = (FILE *) context;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001053 if ((fil == stdout) || (fil == stderr)) {
1054 ret = fflush(fil);
1055 if (ret < 0)
1056 xmlIOErr(0, "fflush()");
1057 return(0);
1058 }
Daniel Veillarda9e65e82001-10-30 10:32:36 +00001059 if (fil == stdin)
1060 return(0);
Daniel Veillard05d987b2003-10-08 11:54:57 +00001061 ret = ( fclose((FILE *) context) == EOF ) ? -1 : 0;
1062 if (ret < 0)
1063 xmlIOErr(0, "fclose()");
1064 return(ret);
Owen Taylor3473f882001-02-23 17:55:21 +00001065}
1066
1067/**
1068 * xmlFileFlush:
1069 * @context: the I/O context
1070 *
1071 * Flush an I/O channel
1072 */
Daniel Veillardf012a642001-07-23 19:10:52 +00001073static int
Owen Taylor3473f882001-02-23 17:55:21 +00001074xmlFileFlush (void * context) {
Daniel Veillard05d987b2003-10-08 11:54:57 +00001075 int ret;
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +00001076
1077 if (context == NULL)
1078 return(-1);
Daniel Veillard05d987b2003-10-08 11:54:57 +00001079 ret = ( fflush((FILE *) context) == EOF ) ? -1 : 0;
1080 if (ret < 0)
1081 xmlIOErr(0, "fflush()");
1082 return(ret);
Owen Taylor3473f882001-02-23 17:55:21 +00001083}
1084
Daniel Veillard9a00fd22005-11-09 08:56:26 +00001085#ifdef LIBXML_OUTPUT_ENABLED
1086/**
1087 * xmlBufferWrite:
1088 * @context: the xmlBuffer
1089 * @buffer: the data to write
1090 * @len: number of bytes to write
1091 *
1092 * Write @len bytes from @buffer to the xml buffer
1093 *
1094 * Returns the number of bytes written
1095 */
1096static int
1097xmlBufferWrite (void * context, const char * buffer, int len) {
1098 int ret;
1099
1100 ret = xmlBufferAdd((xmlBufferPtr) context, (const xmlChar *) buffer, len);
1101 if (ret != 0)
1102 return(-1);
1103 return(len);
1104}
Daniel Veillard9a00fd22005-11-09 08:56:26 +00001105#endif
1106
Owen Taylor3473f882001-02-23 17:55:21 +00001107#ifdef HAVE_ZLIB_H
1108/************************************************************************
1109 * *
1110 * I/O for compressed file accesses *
1111 * *
1112 ************************************************************************/
1113/**
1114 * xmlGzfileMatch:
1115 * @filename: the URI for matching
1116 *
1117 * input from compressed file test
1118 *
1119 * Returns 1 if matches, 0 otherwise
1120 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +00001121static int
Daniel Veillardc86a4fa2001-03-26 16:28:29 +00001122xmlGzfileMatch (const char *filename ATTRIBUTE_UNUSED) {
Owen Taylor3473f882001-02-23 17:55:21 +00001123 return(1);
1124}
1125
1126/**
Daniel Veillardcacbe5d2003-01-10 16:09:51 +00001127 * xmlGzfileOpen_real:
Owen Taylor3473f882001-02-23 17:55:21 +00001128 * @filename: the URI for matching
1129 *
1130 * input from compressed file open
1131 * if @filename is " " then the standard input is used
1132 *
1133 * Returns an I/O context or NULL in case of error
1134 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +00001135static void *
Daniel Veillardcacbe5d2003-01-10 16:09:51 +00001136xmlGzfileOpen_real (const char *filename) {
Owen Taylor3473f882001-02-23 17:55:21 +00001137 const char *path = NULL;
1138 gzFile fd;
1139
1140 if (!strcmp(filename, "-")) {
Daniel Veillarda9e65e82001-10-30 10:32:36 +00001141 fd = gzdopen(dup(0), "rb");
Owen Taylor3473f882001-02-23 17:55:21 +00001142 return((void *) fd);
1143 }
1144
Daniel Veillardf4862f02002-09-10 11:13:43 +00001145 if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17))
Daniel Veillard1997c3e2003-07-05 20:43:43 +00001146#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
Daniel Veillardf4862f02002-09-10 11:13:43 +00001147 path = &filename[17];
1148#else
Owen Taylor3473f882001-02-23 17:55:21 +00001149 path = &filename[16];
Daniel Veillardf4862f02002-09-10 11:13:43 +00001150#endif
Aleksey Sanin5aac8b82002-05-01 18:32:28 +00001151 else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
Daniel Veillard1997c3e2003-07-05 20:43:43 +00001152#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
Daniel Veillardfe703322001-08-14 12:18:09 +00001153 path = &filename[8];
1154#else
Owen Taylor3473f882001-02-23 17:55:21 +00001155 path = &filename[7];
Daniel Veillardfe703322001-08-14 12:18:09 +00001156#endif
Hans Breuer2ad41ca2009-08-11 17:51:22 +02001157 } else
Owen Taylor3473f882001-02-23 17:55:21 +00001158 path = filename;
1159
1160 if (path == NULL)
1161 return(NULL);
1162 if (!xmlCheckFilename(path))
1163 return(NULL);
1164
Hans Breuer2ad41ca2009-08-11 17:51:22 +02001165#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
1166 fd = xmlWrapGzOpen(path, "rb");
1167#else
Owen Taylor3473f882001-02-23 17:55:21 +00001168 fd = gzopen(path, "rb");
Hans Breuer2ad41ca2009-08-11 17:51:22 +02001169#endif
Owen Taylor3473f882001-02-23 17:55:21 +00001170 return((void *) fd);
1171}
1172
1173/**
Daniel Veillardcacbe5d2003-01-10 16:09:51 +00001174 * xmlGzfileOpen:
1175 * @filename: the URI for matching
1176 *
Daniel Veillard4e9b1bc2003-06-09 10:30:33 +00001177 * Wrapper around xmlGzfileOpen if the open fais, it will
1178 * try to unescape @filename
Daniel Veillardcacbe5d2003-01-10 16:09:51 +00001179 */
1180static void *
1181xmlGzfileOpen (const char *filename) {
1182 char *unescaped;
1183 void *retval;
Daniel Veillard4e9b1bc2003-06-09 10:30:33 +00001184
1185 retval = xmlGzfileOpen_real(filename);
1186 if (retval == NULL) {
1187 unescaped = xmlURIUnescapeString(filename, 0, NULL);
1188 if (unescaped != NULL) {
1189 retval = xmlGzfileOpen_real(unescaped);
1190 }
1191 xmlFree(unescaped);
Daniel Veillardcacbe5d2003-01-10 16:09:51 +00001192 }
Daniel Veillardcacbe5d2003-01-10 16:09:51 +00001193 return retval;
1194}
1195
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001196#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardcacbe5d2003-01-10 16:09:51 +00001197/**
Owen Taylor3473f882001-02-23 17:55:21 +00001198 * xmlGzfileOpenW:
1199 * @filename: the URI for matching
1200 * @compression: the compression factor (0 - 9 included)
1201 *
1202 * input from compressed file open
1203 * if @filename is " " then the standard input is used
1204 *
1205 * Returns an I/O context or NULL in case of error
1206 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +00001207static void *
Owen Taylor3473f882001-02-23 17:55:21 +00001208xmlGzfileOpenW (const char *filename, int compression) {
1209 const char *path = NULL;
1210 char mode[15];
1211 gzFile fd;
1212
Aleksey Sanin49cc9752002-06-14 17:07:10 +00001213 snprintf(mode, sizeof(mode), "wb%d", compression);
Owen Taylor3473f882001-02-23 17:55:21 +00001214 if (!strcmp(filename, "-")) {
Daniel Veillarda9e65e82001-10-30 10:32:36 +00001215 fd = gzdopen(dup(1), mode);
Owen Taylor3473f882001-02-23 17:55:21 +00001216 return((void *) fd);
1217 }
1218
Daniel Veillardf4862f02002-09-10 11:13:43 +00001219 if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17))
Daniel Veillard1997c3e2003-07-05 20:43:43 +00001220#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
Daniel Veillardf4862f02002-09-10 11:13:43 +00001221 path = &filename[17];
1222#else
Owen Taylor3473f882001-02-23 17:55:21 +00001223 path = &filename[16];
Daniel Veillardf4862f02002-09-10 11:13:43 +00001224#endif
Aleksey Sanin5aac8b82002-05-01 18:32:28 +00001225 else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
Daniel Veillard1997c3e2003-07-05 20:43:43 +00001226#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
Daniel Veillardfe703322001-08-14 12:18:09 +00001227 path = &filename[8];
1228#else
Daniel Veillard3c2758d2001-05-31 18:43:43 +00001229 path = &filename[7];
Daniel Veillardfe703322001-08-14 12:18:09 +00001230#endif
Hans Breuer2ad41ca2009-08-11 17:51:22 +02001231 } else
Owen Taylor3473f882001-02-23 17:55:21 +00001232 path = filename;
1233
1234 if (path == NULL)
1235 return(NULL);
1236
Hans Breuer2ad41ca2009-08-11 17:51:22 +02001237#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
1238 fd = xmlWrapGzOpen(path, mode);
1239#else
Owen Taylor3473f882001-02-23 17:55:21 +00001240 fd = gzopen(path, mode);
Hans Breuer2ad41ca2009-08-11 17:51:22 +02001241#endif
Owen Taylor3473f882001-02-23 17:55:21 +00001242 return((void *) fd);
1243}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001244#endif /* LIBXML_OUTPUT_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00001245
1246/**
1247 * xmlGzfileRead:
1248 * @context: the I/O context
1249 * @buffer: where to drop data
1250 * @len: number of bytes to write
1251 *
1252 * Read @len bytes to @buffer from the compressed I/O channel.
1253 *
1254 * Returns the number of bytes written
1255 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +00001256static int
Owen Taylor3473f882001-02-23 17:55:21 +00001257xmlGzfileRead (void * context, char * buffer, int len) {
Daniel Veillard05d987b2003-10-08 11:54:57 +00001258 int ret;
1259
1260 ret = gzread((gzFile) context, &buffer[0], len);
1261 if (ret < 0) xmlIOErr(0, "gzread()");
1262 return(ret);
Owen Taylor3473f882001-02-23 17:55:21 +00001263}
1264
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001265#ifdef LIBXML_OUTPUT_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00001266/**
1267 * xmlGzfileWrite:
1268 * @context: the I/O context
1269 * @buffer: where to drop data
1270 * @len: number of bytes to write
1271 *
1272 * Write @len bytes from @buffer to the compressed I/O channel.
1273 *
1274 * Returns the number of bytes written
1275 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +00001276static int
Owen Taylor3473f882001-02-23 17:55:21 +00001277xmlGzfileWrite (void * context, const char * buffer, int len) {
Daniel Veillard05d987b2003-10-08 11:54:57 +00001278 int ret;
1279
1280 ret = gzwrite((gzFile) context, (char *) &buffer[0], len);
1281 if (ret < 0) xmlIOErr(0, "gzwrite()");
1282 return(ret);
Owen Taylor3473f882001-02-23 17:55:21 +00001283}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001284#endif /* LIBXML_OUTPUT_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00001285
1286/**
1287 * xmlGzfileClose:
1288 * @context: the I/O context
1289 *
1290 * Close a compressed I/O channel
1291 */
Daniel Veillardf012a642001-07-23 19:10:52 +00001292static int
Owen Taylor3473f882001-02-23 17:55:21 +00001293xmlGzfileClose (void * context) {
Daniel Veillard05d987b2003-10-08 11:54:57 +00001294 int ret;
1295
1296 ret = (gzclose((gzFile) context) == Z_OK ) ? 0 : -1;
1297 if (ret < 0) xmlIOErr(0, "gzclose()");
1298 return(ret);
Owen Taylor3473f882001-02-23 17:55:21 +00001299}
1300#endif /* HAVE_ZLIB_H */
1301
1302#ifdef LIBXML_HTTP_ENABLED
1303/************************************************************************
1304 * *
1305 * I/O for HTTP file accesses *
1306 * *
1307 ************************************************************************/
Daniel Veillardf012a642001-07-23 19:10:52 +00001308
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001309#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardf012a642001-07-23 19:10:52 +00001310typedef struct xmlIOHTTPWriteCtxt_
1311{
1312 int compression;
1313
1314 char * uri;
1315
1316 void * doc_buff;
1317
1318} xmlIOHTTPWriteCtxt, *xmlIOHTTPWriteCtxtPtr;
1319
1320#ifdef HAVE_ZLIB_H
1321
1322#define DFLT_WBITS ( -15 )
1323#define DFLT_MEM_LVL ( 8 )
1324#define GZ_MAGIC1 ( 0x1f )
1325#define GZ_MAGIC2 ( 0x8b )
1326#define LXML_ZLIB_OS_CODE ( 0x03 )
1327#define INIT_HTTP_BUFF_SIZE ( 32768 )
1328#define DFLT_ZLIB_RATIO ( 5 )
1329
1330/*
1331** Data structure and functions to work with sending compressed data
1332** via HTTP.
1333*/
1334
1335typedef struct xmlZMemBuff_
1336{
1337 unsigned long size;
1338 unsigned long crc;
1339
1340 unsigned char * zbuff;
1341 z_stream zctrl;
1342
1343} xmlZMemBuff, *xmlZMemBuffPtr;
1344
1345/**
1346 * append_reverse_ulong
1347 * @buff: Compressed memory buffer
1348 * @data: Unsigned long to append
1349 *
1350 * Append a unsigned long in reverse byte order to the end of the
1351 * memory buffer.
1352 */
1353static void
1354append_reverse_ulong( xmlZMemBuff * buff, unsigned long data ) {
1355
1356 int idx;
1357
1358 if ( buff == NULL )
1359 return;
1360
1361 /*
1362 ** This is plagiarized from putLong in gzio.c (zlib source) where
Hans Breuer2ad41ca2009-08-11 17:51:22 +02001363 ** the number "4" is hardcoded. If zlib is ever patched to
Daniel Veillardf012a642001-07-23 19:10:52 +00001364 ** support 64 bit file sizes, this code would need to be patched
1365 ** as well.
1366 */
1367
1368 for ( idx = 0; idx < 4; idx++ ) {
1369 *buff->zctrl.next_out = ( data & 0xff );
1370 data >>= 8;
1371 buff->zctrl.next_out++;
1372 }
1373
1374 return;
1375}
1376
1377/**
1378 *
1379 * xmlFreeZMemBuff
1380 * @buff: The memory buffer context to clear
1381 *
1382 * Release all the resources associated with the compressed memory buffer.
1383 */
1384static void
1385xmlFreeZMemBuff( xmlZMemBuffPtr buff ) {
William M. Brack78637da2003-07-31 14:47:38 +00001386
1387#ifdef DEBUG_HTTP
Daniel Veillardf012a642001-07-23 19:10:52 +00001388 int z_err;
William M. Brack78637da2003-07-31 14:47:38 +00001389#endif
Daniel Veillardf012a642001-07-23 19:10:52 +00001390
1391 if ( buff == NULL )
1392 return;
1393
1394 xmlFree( buff->zbuff );
Daniel Veillardf012a642001-07-23 19:10:52 +00001395#ifdef DEBUG_HTTP
William M. Brack78637da2003-07-31 14:47:38 +00001396 z_err = deflateEnd( &buff->zctrl );
Daniel Veillardf012a642001-07-23 19:10:52 +00001397 if ( z_err != Z_OK )
1398 xmlGenericError( xmlGenericErrorContext,
1399 "xmlFreeZMemBuff: Error releasing zlib context: %d\n",
1400 z_err );
William M. Brack78637da2003-07-31 14:47:38 +00001401#else
1402 deflateEnd( &buff->zctrl );
William M. Brack779af002003-08-01 15:55:39 +00001403#endif
Daniel Veillardf012a642001-07-23 19:10:52 +00001404
1405 xmlFree( buff );
1406 return;
1407}
1408
1409/**
1410 * xmlCreateZMemBuff
1411 *@compression: Compression value to use
1412 *
1413 * Create a memory buffer to hold the compressed XML document. The
1414 * compressed document in memory will end up being identical to what
Hans Breuer2ad41ca2009-08-11 17:51:22 +02001415 * would be created if gzopen/gzwrite/gzclose were being used to
Daniel Veillardf012a642001-07-23 19:10:52 +00001416 * write the document to disk. The code for the header/trailer data to
1417 * the compression is plagiarized from the zlib source files.
1418 */
1419static void *
1420xmlCreateZMemBuff( int compression ) {
1421
1422 int z_err;
1423 int hdr_lgth;
1424 xmlZMemBuffPtr buff = NULL;
1425
1426 if ( ( compression < 1 ) || ( compression > 9 ) )
1427 return ( NULL );
1428
1429 /* Create the control and data areas */
1430
1431 buff = xmlMalloc( sizeof( xmlZMemBuff ) );
1432 if ( buff == NULL ) {
Daniel Veillard05d987b2003-10-08 11:54:57 +00001433 xmlIOErrMemory("creating buffer context");
Daniel Veillardf012a642001-07-23 19:10:52 +00001434 return ( NULL );
1435 }
1436
1437 (void)memset( buff, 0, sizeof( xmlZMemBuff ) );
1438 buff->size = INIT_HTTP_BUFF_SIZE;
1439 buff->zbuff = xmlMalloc( buff->size );
1440 if ( buff->zbuff == NULL ) {
1441 xmlFreeZMemBuff( buff );
Daniel Veillard05d987b2003-10-08 11:54:57 +00001442 xmlIOErrMemory("creating buffer");
Daniel Veillardf012a642001-07-23 19:10:52 +00001443 return ( NULL );
1444 }
1445
1446 z_err = deflateInit2( &buff->zctrl, compression, Z_DEFLATED,
1447 DFLT_WBITS, DFLT_MEM_LVL, Z_DEFAULT_STRATEGY );
1448 if ( z_err != Z_OK ) {
Daniel Veillard05d987b2003-10-08 11:54:57 +00001449 xmlChar msg[500];
Daniel Veillardf012a642001-07-23 19:10:52 +00001450 xmlFreeZMemBuff( buff );
1451 buff = NULL;
Daniel Veillard05d987b2003-10-08 11:54:57 +00001452 xmlStrPrintf(msg, 500,
1453 (const xmlChar *) "xmlCreateZMemBuff: %s %d\n",
1454 "Error initializing compression context. ZLIB error:",
1455 z_err );
1456 xmlIOErr(XML_IO_WRITE, (const char *) msg);
Daniel Veillardf012a642001-07-23 19:10:52 +00001457 return ( NULL );
1458 }
1459
1460 /* Set the header data. The CRC will be needed for the trailer */
Daniel Veillard24505b02005-07-28 23:49:35 +00001461 buff->crc = crc32( 0L, NULL, 0 );
Aleksey Sanin49cc9752002-06-14 17:07:10 +00001462 hdr_lgth = snprintf( (char *)buff->zbuff, buff->size,
1463 "%c%c%c%c%c%c%c%c%c%c",
Hans Breuer2ad41ca2009-08-11 17:51:22 +02001464 GZ_MAGIC1, GZ_MAGIC2, Z_DEFLATED,
Daniel Veillardf012a642001-07-23 19:10:52 +00001465 0, 0, 0, 0, 0, 0, LXML_ZLIB_OS_CODE );
1466 buff->zctrl.next_out = buff->zbuff + hdr_lgth;
1467 buff->zctrl.avail_out = buff->size - hdr_lgth;
1468
1469 return ( buff );
1470}
1471
1472/**
1473 * xmlZMemBuffExtend
1474 * @buff: Buffer used to compress and consolidate data.
1475 * @ext_amt: Number of bytes to extend the buffer.
1476 *
1477 * Extend the internal buffer used to store the compressed data by the
1478 * specified amount.
1479 *
1480 * Returns 0 on success or -1 on failure to extend the buffer. On failure
1481 * the original buffer still exists at the original size.
1482 */
1483static int
1484xmlZMemBuffExtend( xmlZMemBuffPtr buff, size_t ext_amt ) {
1485
1486 int rc = -1;
1487 size_t new_size;
1488 size_t cur_used;
1489
1490 unsigned char * tmp_ptr = NULL;
1491
1492 if ( buff == NULL )
1493 return ( -1 );
1494
1495 else if ( ext_amt == 0 )
1496 return ( 0 );
1497
1498 cur_used = buff->zctrl.next_out - buff->zbuff;
1499 new_size = buff->size + ext_amt;
1500
1501#ifdef DEBUG_HTTP
Hans Breuer2ad41ca2009-08-11 17:51:22 +02001502 if ( cur_used > new_size )
Daniel Veillardf012a642001-07-23 19:10:52 +00001503 xmlGenericError( xmlGenericErrorContext,
1504 "xmlZMemBuffExtend: %s\n%s %d bytes.\n",
1505 "Buffer overwrite detected during compressed memory",
Hans Breuer2ad41ca2009-08-11 17:51:22 +02001506 "buffer extension. Overflowed by",
Daniel Veillardf012a642001-07-23 19:10:52 +00001507 (cur_used - new_size ) );
1508#endif
1509
1510 tmp_ptr = xmlRealloc( buff->zbuff, new_size );
1511 if ( tmp_ptr != NULL ) {
1512 rc = 0;
1513 buff->size = new_size;
1514 buff->zbuff = tmp_ptr;
1515 buff->zctrl.next_out = tmp_ptr + cur_used;
1516 buff->zctrl.avail_out = new_size - cur_used;
1517 }
1518 else {
Daniel Veillard05d987b2003-10-08 11:54:57 +00001519 xmlChar msg[500];
1520 xmlStrPrintf(msg, 500,
1521 (const xmlChar *) "xmlZMemBuffExtend: %s %lu bytes.\n",
1522 "Allocation failure extending output buffer to",
1523 new_size );
1524 xmlIOErr(XML_IO_WRITE, (const char *) msg);
Daniel Veillardf012a642001-07-23 19:10:52 +00001525 }
1526
1527 return ( rc );
1528}
1529
1530/**
1531 * xmlZMemBuffAppend
1532 * @buff: Buffer used to compress and consolidate data
1533 * @src: Uncompressed source content to append to buffer
1534 * @len: Length of source data to append to buffer
1535 *
1536 * Compress and append data to the internal buffer. The data buffer
1537 * will be expanded if needed to store the additional data.
1538 *
1539 * Returns the number of bytes appended to the buffer or -1 on error.
1540 */
1541static int
1542xmlZMemBuffAppend( xmlZMemBuffPtr buff, const char * src, int len ) {
1543
1544 int z_err;
1545 size_t min_accept;
1546
1547 if ( ( buff == NULL ) || ( src == NULL ) )
1548 return ( -1 );
1549
1550 buff->zctrl.avail_in = len;
1551 buff->zctrl.next_in = (unsigned char *)src;
1552 while ( buff->zctrl.avail_in > 0 ) {
1553 /*
1554 ** Extend the buffer prior to deflate call if a reasonable amount
1555 ** of output buffer space is not available.
1556 */
1557 min_accept = buff->zctrl.avail_in / DFLT_ZLIB_RATIO;
1558 if ( buff->zctrl.avail_out <= min_accept ) {
1559 if ( xmlZMemBuffExtend( buff, buff->size ) == -1 )
1560 return ( -1 );
1561 }
1562
1563 z_err = deflate( &buff->zctrl, Z_NO_FLUSH );
1564 if ( z_err != Z_OK ) {
Daniel Veillard05d987b2003-10-08 11:54:57 +00001565 xmlChar msg[500];
1566 xmlStrPrintf(msg, 500,
1567 (const xmlChar *) "xmlZMemBuffAppend: %s %d %s - %d",
Daniel Veillardf012a642001-07-23 19:10:52 +00001568 "Compression error while appending",
1569 len, "bytes to buffer. ZLIB error", z_err );
Daniel Veillard05d987b2003-10-08 11:54:57 +00001570 xmlIOErr(XML_IO_WRITE, (const char *) msg);
Daniel Veillardf012a642001-07-23 19:10:52 +00001571 return ( -1 );
1572 }
1573 }
1574
1575 buff->crc = crc32( buff->crc, (unsigned char *)src, len );
1576
1577 return ( len );
1578}
1579
1580/**
1581 * xmlZMemBuffGetContent
1582 * @buff: Compressed memory content buffer
1583 * @data_ref: Pointer reference to point to compressed content
1584 *
1585 * Flushes the compression buffers, appends gzip file trailers and
1586 * returns the compressed content and length of the compressed data.
1587 * NOTE: The gzip trailer code here is plagiarized from zlib source.
1588 *
1589 * Returns the length of the compressed data or -1 on error.
1590 */
1591static int
1592xmlZMemBuffGetContent( xmlZMemBuffPtr buff, char ** data_ref ) {
1593
1594 int zlgth = -1;
1595 int z_err;
1596
1597 if ( ( buff == NULL ) || ( data_ref == NULL ) )
1598 return ( -1 );
1599
1600 /* Need to loop until compression output buffers are flushed */
1601
1602 do
1603 {
1604 z_err = deflate( &buff->zctrl, Z_FINISH );
1605 if ( z_err == Z_OK ) {
1606 /* In this case Z_OK means more buffer space needed */
1607
1608 if ( xmlZMemBuffExtend( buff, buff->size ) == -1 )
1609 return ( -1 );
1610 }
1611 }
1612 while ( z_err == Z_OK );
1613
1614 /* If the compression state is not Z_STREAM_END, some error occurred */
1615
1616 if ( z_err == Z_STREAM_END ) {
1617
1618 /* Need to append the gzip data trailer */
1619
1620 if ( buff->zctrl.avail_out < ( 2 * sizeof( unsigned long ) ) ) {
1621 if ( xmlZMemBuffExtend(buff, (2 * sizeof(unsigned long))) == -1 )
1622 return ( -1 );
1623 }
1624
1625 /*
1626 ** For whatever reason, the CRC and length data are pushed out
1627 ** in reverse byte order. So a memcpy can't be used here.
1628 */
1629
1630 append_reverse_ulong( buff, buff->crc );
1631 append_reverse_ulong( buff, buff->zctrl.total_in );
1632
1633 zlgth = buff->zctrl.next_out - buff->zbuff;
1634 *data_ref = (char *)buff->zbuff;
1635 }
1636
Daniel Veillard05d987b2003-10-08 11:54:57 +00001637 else {
1638 xmlChar msg[500];
1639 xmlStrPrintf(msg, 500,
1640 (const xmlChar *) "xmlZMemBuffGetContent: %s - %d\n",
1641 "Error flushing zlib buffers. Error code", z_err );
1642 xmlIOErr(XML_IO_WRITE, (const char *) msg);
1643 }
Hans Breuer2ad41ca2009-08-11 17:51:22 +02001644
Daniel Veillardf012a642001-07-23 19:10:52 +00001645 return ( zlgth );
1646}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001647#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillardf012a642001-07-23 19:10:52 +00001648#endif /* HAVE_ZLIB_H */
1649
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001650#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardf012a642001-07-23 19:10:52 +00001651/**
1652 * xmlFreeHTTPWriteCtxt
1653 * @ctxt: Context to cleanup
1654 *
1655 * Free allocated memory and reclaim system resources.
1656 *
1657 * No return value.
1658 */
1659static void
1660xmlFreeHTTPWriteCtxt( xmlIOHTTPWriteCtxtPtr ctxt )
1661{
1662 if ( ctxt->uri != NULL )
Daniel Veillard819d5cb2002-10-14 11:15:18 +00001663 xmlFree( ctxt->uri );
Daniel Veillardf012a642001-07-23 19:10:52 +00001664
1665 if ( ctxt->doc_buff != NULL ) {
1666
1667#ifdef HAVE_ZLIB_H
1668 if ( ctxt->compression > 0 ) {
1669 xmlFreeZMemBuff( ctxt->doc_buff );
1670 }
1671 else
1672#endif
1673 {
1674 xmlOutputBufferClose( ctxt->doc_buff );
1675 }
1676 }
1677
Daniel Veillard819d5cb2002-10-14 11:15:18 +00001678 xmlFree( ctxt );
Daniel Veillardf012a642001-07-23 19:10:52 +00001679 return;
1680}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001681#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillardf012a642001-07-23 19:10:52 +00001682
1683
Owen Taylor3473f882001-02-23 17:55:21 +00001684/**
1685 * xmlIOHTTPMatch:
1686 * @filename: the URI for matching
1687 *
1688 * check if the URI matches an HTTP one
1689 *
1690 * Returns 1 if matches, 0 otherwise
1691 */
Aleksey Sanin5aac8b82002-05-01 18:32:28 +00001692int
Owen Taylor3473f882001-02-23 17:55:21 +00001693xmlIOHTTPMatch (const char *filename) {
Aleksey Sanin5aac8b82002-05-01 18:32:28 +00001694 if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "http://", 7))
Owen Taylor3473f882001-02-23 17:55:21 +00001695 return(1);
1696 return(0);
1697}
1698
1699/**
1700 * xmlIOHTTPOpen:
1701 * @filename: the URI for matching
1702 *
1703 * open an HTTP I/O channel
1704 *
1705 * Returns an I/O context or NULL in case of error
1706 */
Aleksey Sanin5aac8b82002-05-01 18:32:28 +00001707void *
Owen Taylor3473f882001-02-23 17:55:21 +00001708xmlIOHTTPOpen (const char *filename) {
1709 return(xmlNanoHTTPOpen(filename, NULL));
1710}
1711
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001712#ifdef LIBXML_OUTPUT_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00001713/**
Daniel Veillarda9b66d02002-12-11 14:23:49 +00001714 * xmlIOHTTPOpenW:
Daniel Veillardf012a642001-07-23 19:10:52 +00001715 * @post_uri: The destination URI for the document
1716 * @compression: The compression desired for the document.
1717 *
1718 * Open a temporary buffer to collect the document for a subsequent HTTP POST
1719 * request. Non-static as is called from the output buffer creation routine.
1720 *
1721 * Returns an I/O context or NULL in case of error.
1722 */
1723
1724void *
Daniel Veillard572577e2002-01-18 16:23:55 +00001725xmlIOHTTPOpenW(const char *post_uri, int compression)
1726{
Daniel Veillardf012a642001-07-23 19:10:52 +00001727
Daniel Veillard572577e2002-01-18 16:23:55 +00001728 xmlIOHTTPWriteCtxtPtr ctxt = NULL;
Daniel Veillardf012a642001-07-23 19:10:52 +00001729
Daniel Veillard572577e2002-01-18 16:23:55 +00001730 if (post_uri == NULL)
1731 return (NULL);
Daniel Veillardf012a642001-07-23 19:10:52 +00001732
Daniel Veillard572577e2002-01-18 16:23:55 +00001733 ctxt = xmlMalloc(sizeof(xmlIOHTTPWriteCtxt));
1734 if (ctxt == NULL) {
Daniel Veillard05d987b2003-10-08 11:54:57 +00001735 xmlIOErrMemory("creating HTTP output context");
Daniel Veillard572577e2002-01-18 16:23:55 +00001736 return (NULL);
Daniel Veillardf012a642001-07-23 19:10:52 +00001737 }
1738
Daniel Veillard572577e2002-01-18 16:23:55 +00001739 (void) memset(ctxt, 0, sizeof(xmlIOHTTPWriteCtxt));
Daniel Veillardf012a642001-07-23 19:10:52 +00001740
Daniel Veillard572577e2002-01-18 16:23:55 +00001741 ctxt->uri = (char *) xmlStrdup((const xmlChar *)post_uri);
1742 if (ctxt->uri == NULL) {
Daniel Veillard05d987b2003-10-08 11:54:57 +00001743 xmlIOErrMemory("copying URI");
Daniel Veillard572577e2002-01-18 16:23:55 +00001744 xmlFreeHTTPWriteCtxt(ctxt);
1745 return (NULL);
Daniel Veillardf012a642001-07-23 19:10:52 +00001746 }
1747
1748 /*
Daniel Veillard572577e2002-01-18 16:23:55 +00001749 * ** Since the document length is required for an HTTP post,
1750 * ** need to put the document into a buffer. A memory buffer
1751 * ** is being used to avoid pushing the data to disk and back.
1752 */
Daniel Veillardf012a642001-07-23 19:10:52 +00001753
1754#ifdef HAVE_ZLIB_H
Daniel Veillard572577e2002-01-18 16:23:55 +00001755 if ((compression > 0) && (compression <= 9)) {
1756
1757 ctxt->compression = compression;
1758 ctxt->doc_buff = xmlCreateZMemBuff(compression);
1759 } else
Daniel Veillardf012a642001-07-23 19:10:52 +00001760#endif
1761 {
Daniel Veillard572577e2002-01-18 16:23:55 +00001762 /* Any character conversions should have been done before this */
Daniel Veillardf012a642001-07-23 19:10:52 +00001763
Daniel Veillardda3fee42008-09-01 13:08:57 +00001764 ctxt->doc_buff = xmlAllocOutputBufferInternal(NULL);
Daniel Veillardf012a642001-07-23 19:10:52 +00001765 }
1766
Daniel Veillard572577e2002-01-18 16:23:55 +00001767 if (ctxt->doc_buff == NULL) {
1768 xmlFreeHTTPWriteCtxt(ctxt);
1769 ctxt = NULL;
Daniel Veillardf012a642001-07-23 19:10:52 +00001770 }
1771
Daniel Veillard572577e2002-01-18 16:23:55 +00001772 return (ctxt);
Daniel Veillardf012a642001-07-23 19:10:52 +00001773}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001774#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillardda3fee42008-09-01 13:08:57 +00001775
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001776#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardf012a642001-07-23 19:10:52 +00001777/**
1778 * xmlIOHTTPDfltOpenW
1779 * @post_uri: The destination URI for this document.
1780 *
1781 * Calls xmlIOHTTPOpenW with no compression to set up for a subsequent
1782 * HTTP post command. This function should generally not be used as
1783 * the open callback is short circuited in xmlOutputBufferCreateFile.
1784 *
1785 * Returns a pointer to the new IO context.
1786 */
1787static void *
1788xmlIOHTTPDfltOpenW( const char * post_uri ) {
1789 return ( xmlIOHTTPOpenW( post_uri, 0 ) );
1790}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001791#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillardf012a642001-07-23 19:10:52 +00001792
1793/**
Owen Taylor3473f882001-02-23 17:55:21 +00001794 * xmlIOHTTPRead:
1795 * @context: the I/O context
1796 * @buffer: where to drop data
1797 * @len: number of bytes to write
1798 *
1799 * Read @len bytes to @buffer from the I/O channel.
1800 *
1801 * Returns the number of bytes written
1802 */
Hans Breuer2ad41ca2009-08-11 17:51:22 +02001803int
Owen Taylor3473f882001-02-23 17:55:21 +00001804xmlIOHTTPRead(void * context, char * buffer, int len) {
Daniel Veillard5ea30d72004-11-08 11:54:28 +00001805 if ((buffer == NULL) || (len < 0)) return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001806 return(xmlNanoHTTPRead(context, &buffer[0], len));
1807}
1808
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001809#ifdef LIBXML_OUTPUT_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00001810/**
Daniel Veillardf012a642001-07-23 19:10:52 +00001811 * xmlIOHTTPWrite
1812 * @context: previously opened writing context
1813 * @buffer: data to output to temporary buffer
1814 * @len: bytes to output
1815 *
1816 * Collect data from memory buffer into a temporary file for later
1817 * processing.
1818 *
1819 * Returns number of bytes written.
1820 */
1821
1822static int
Hans Breuer2ad41ca2009-08-11 17:51:22 +02001823xmlIOHTTPWrite( void * context, const char * buffer, int len ) {
Daniel Veillardf012a642001-07-23 19:10:52 +00001824
1825 xmlIOHTTPWriteCtxtPtr ctxt = context;
1826
1827 if ( ( ctxt == NULL ) || ( ctxt->doc_buff == NULL ) || ( buffer == NULL ) )
1828 return ( -1 );
1829
1830 if ( len > 0 ) {
1831
1832 /* Use gzwrite or fwrite as previously setup in the open call */
1833
1834#ifdef HAVE_ZLIB_H
Hans Breuer2ad41ca2009-08-11 17:51:22 +02001835 if ( ctxt->compression > 0 )
Daniel Veillardf012a642001-07-23 19:10:52 +00001836 len = xmlZMemBuffAppend( ctxt->doc_buff, buffer, len );
1837
1838 else
1839#endif
1840 len = xmlOutputBufferWrite( ctxt->doc_buff, len, buffer );
1841
1842 if ( len < 0 ) {
Daniel Veillard05d987b2003-10-08 11:54:57 +00001843 xmlChar msg[500];
1844 xmlStrPrintf(msg, 500,
1845 (const xmlChar *) "xmlIOHTTPWrite: %s\n%s '%s'.\n",
Daniel Veillardf012a642001-07-23 19:10:52 +00001846 "Error appending to internal buffer.",
1847 "Error sending document to URI",
1848 ctxt->uri );
Daniel Veillard05d987b2003-10-08 11:54:57 +00001849 xmlIOErr(XML_IO_WRITE, (const char *) msg);
Daniel Veillardf012a642001-07-23 19:10:52 +00001850 }
1851 }
1852
1853 return ( len );
1854}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001855#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillardf012a642001-07-23 19:10:52 +00001856
1857
1858/**
Owen Taylor3473f882001-02-23 17:55:21 +00001859 * xmlIOHTTPClose:
1860 * @context: the I/O context
1861 *
1862 * Close an HTTP I/O channel
Daniel Veillarda9b66d02002-12-11 14:23:49 +00001863 *
1864 * Returns 0
Owen Taylor3473f882001-02-23 17:55:21 +00001865 */
Aleksey Sanin5aac8b82002-05-01 18:32:28 +00001866int
Owen Taylor3473f882001-02-23 17:55:21 +00001867xmlIOHTTPClose (void * context) {
1868 xmlNanoHTTPClose(context);
Daniel Veillardf012a642001-07-23 19:10:52 +00001869 return 0;
Owen Taylor3473f882001-02-23 17:55:21 +00001870}
Daniel Veillardf012a642001-07-23 19:10:52 +00001871
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001872#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardf012a642001-07-23 19:10:52 +00001873/**
1874 * xmlIOHTTCloseWrite
1875 * @context: The I/O context
1876 * @http_mthd: The HTTP method to be used when sending the data
1877 *
1878 * Close the transmit HTTP I/O channel and actually send the data.
1879 */
1880static int
1881xmlIOHTTPCloseWrite( void * context, const char * http_mthd ) {
1882
1883 int close_rc = -1;
1884 int http_rtn = 0;
1885 int content_lgth = 0;
1886 xmlIOHTTPWriteCtxtPtr ctxt = context;
1887
1888 char * http_content = NULL;
1889 char * content_encoding = NULL;
1890 char * content_type = (char *) "text/xml";
1891 void * http_ctxt = NULL;
1892
1893 if ( ( ctxt == NULL ) || ( http_mthd == NULL ) )
1894 return ( -1 );
1895
1896 /* Retrieve the content from the appropriate buffer */
1897
1898#ifdef HAVE_ZLIB_H
1899
1900 if ( ctxt->compression > 0 ) {
1901 content_lgth = xmlZMemBuffGetContent( ctxt->doc_buff, &http_content );
1902 content_encoding = (char *) "Content-Encoding: gzip";
1903 }
1904 else
1905#endif
1906 {
1907 /* Pull the data out of the memory output buffer */
1908
1909 xmlOutputBufferPtr dctxt = ctxt->doc_buff;
1910 http_content = (char *)dctxt->buffer->content;
1911 content_lgth = dctxt->buffer->use;
1912 }
1913
1914 if ( http_content == NULL ) {
Daniel Veillard05d987b2003-10-08 11:54:57 +00001915 xmlChar msg[500];
1916 xmlStrPrintf(msg, 500,
1917 (const xmlChar *) "xmlIOHTTPCloseWrite: %s '%s' %s '%s'.\n",
1918 "Error retrieving content.\nUnable to",
1919 http_mthd, "data to URI", ctxt->uri );
1920 xmlIOErr(XML_IO_WRITE, (const char *) msg);
Daniel Veillardf012a642001-07-23 19:10:52 +00001921 }
1922
1923 else {
1924
1925 http_ctxt = xmlNanoHTTPMethod( ctxt->uri, http_mthd, http_content,
Hans Breuer2ad41ca2009-08-11 17:51:22 +02001926 &content_type, content_encoding,
Daniel Veillardf012a642001-07-23 19:10:52 +00001927 content_lgth );
1928
1929 if ( http_ctxt != NULL ) {
1930#ifdef DEBUG_HTTP
1931 /* If testing/debugging - dump reply with request content */
1932
1933 FILE * tst_file = NULL;
1934 char buffer[ 4096 ];
1935 char * dump_name = NULL;
1936 int avail;
1937
1938 xmlGenericError( xmlGenericErrorContext,
1939 "xmlNanoHTTPCloseWrite: HTTP %s to\n%s returned %d.\n",
1940 http_mthd, ctxt->uri,
1941 xmlNanoHTTPReturnCode( http_ctxt ) );
1942
1943 /*
1944 ** Since either content or reply may be gzipped,
Hans Breuer2ad41ca2009-08-11 17:51:22 +02001945 ** dump them to separate files instead of the
Daniel Veillardf012a642001-07-23 19:10:52 +00001946 ** standard error context.
1947 */
1948
1949 dump_name = tempnam( NULL, "lxml" );
1950 if ( dump_name != NULL ) {
Aleksey Sanin49cc9752002-06-14 17:07:10 +00001951 (void)snprintf( buffer, sizeof(buffer), "%s.content", dump_name );
Daniel Veillardf012a642001-07-23 19:10:52 +00001952
Daniel Veillardcbbd78d2003-07-20 15:21:30 +00001953 tst_file = fopen( buffer, "wb" );
Daniel Veillardf012a642001-07-23 19:10:52 +00001954 if ( tst_file != NULL ) {
1955 xmlGenericError( xmlGenericErrorContext,
1956 "Transmitted content saved in file: %s\n", buffer );
1957
1958 fwrite( http_content, sizeof( char ),
1959 content_lgth, tst_file );
1960 fclose( tst_file );
1961 }
1962
Aleksey Sanin49cc9752002-06-14 17:07:10 +00001963 (void)snprintf( buffer, sizeof(buffer), "%s.reply", dump_name );
Daniel Veillardcbbd78d2003-07-20 15:21:30 +00001964 tst_file = fopen( buffer, "wb" );
Daniel Veillardf012a642001-07-23 19:10:52 +00001965 if ( tst_file != NULL ) {
1966 xmlGenericError( xmlGenericErrorContext,
1967 "Reply content saved in file: %s\n", buffer );
1968
1969
1970 while ( (avail = xmlNanoHTTPRead( http_ctxt,
1971 buffer, sizeof( buffer ) )) > 0 ) {
1972
1973 fwrite( buffer, sizeof( char ), avail, tst_file );
1974 }
1975
1976 fclose( tst_file );
1977 }
1978
1979 free( dump_name );
1980 }
1981#endif /* DEBUG_HTTP */
1982
1983 http_rtn = xmlNanoHTTPReturnCode( http_ctxt );
1984 if ( ( http_rtn >= 200 ) && ( http_rtn < 300 ) )
1985 close_rc = 0;
Daniel Veillard05d987b2003-10-08 11:54:57 +00001986 else {
1987 xmlChar msg[500];
1988 xmlStrPrintf(msg, 500,
1989 (const xmlChar *) "xmlIOHTTPCloseWrite: HTTP '%s' of %d %s\n'%s' %s %d\n",
Daniel Veillardf012a642001-07-23 19:10:52 +00001990 http_mthd, content_lgth,
1991 "bytes to URI", ctxt->uri,
1992 "failed. HTTP return code:", http_rtn );
Daniel Veillard05d987b2003-10-08 11:54:57 +00001993 xmlIOErr(XML_IO_WRITE, (const char *) msg);
1994 }
Daniel Veillardf012a642001-07-23 19:10:52 +00001995
1996 xmlNanoHTTPClose( http_ctxt );
1997 xmlFree( content_type );
1998 }
1999 }
2000
2001 /* Final cleanups */
2002
2003 xmlFreeHTTPWriteCtxt( ctxt );
2004
2005 return ( close_rc );
2006}
2007
2008/**
2009 * xmlIOHTTPClosePut
2010 *
2011 * @context: The I/O context
2012 *
2013 * Close the transmit HTTP I/O channel and actually send data using a PUT
2014 * HTTP method.
2015 */
2016static int
2017xmlIOHTTPClosePut( void * ctxt ) {
2018 return ( xmlIOHTTPCloseWrite( ctxt, "PUT" ) );
2019}
2020
2021
2022/**
2023 * xmlIOHTTPClosePost
2024 *
2025 * @context: The I/O context
2026 *
2027 * Close the transmit HTTP I/O channel and actually send data using a POST
2028 * HTTP method.
2029 */
2030static int
2031xmlIOHTTPClosePost( void * ctxt ) {
2032 return ( xmlIOHTTPCloseWrite( ctxt, "POST" ) );
2033}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002034#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillardf012a642001-07-23 19:10:52 +00002035
Owen Taylor3473f882001-02-23 17:55:21 +00002036#endif /* LIBXML_HTTP_ENABLED */
2037
2038#ifdef LIBXML_FTP_ENABLED
2039/************************************************************************
2040 * *
2041 * I/O for FTP file accesses *
2042 * *
2043 ************************************************************************/
2044/**
2045 * xmlIOFTPMatch:
2046 * @filename: the URI for matching
2047 *
2048 * check if the URI matches an FTP one
2049 *
2050 * Returns 1 if matches, 0 otherwise
2051 */
Aleksey Sanin5aac8b82002-05-01 18:32:28 +00002052int
Owen Taylor3473f882001-02-23 17:55:21 +00002053xmlIOFTPMatch (const char *filename) {
Aleksey Sanin5aac8b82002-05-01 18:32:28 +00002054 if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "ftp://", 6))
Owen Taylor3473f882001-02-23 17:55:21 +00002055 return(1);
2056 return(0);
2057}
2058
2059/**
2060 * xmlIOFTPOpen:
2061 * @filename: the URI for matching
2062 *
2063 * open an FTP I/O channel
2064 *
2065 * Returns an I/O context or NULL in case of error
2066 */
Aleksey Sanin5aac8b82002-05-01 18:32:28 +00002067void *
Owen Taylor3473f882001-02-23 17:55:21 +00002068xmlIOFTPOpen (const char *filename) {
2069 return(xmlNanoFTPOpen(filename));
2070}
2071
2072/**
2073 * xmlIOFTPRead:
2074 * @context: the I/O context
2075 * @buffer: where to drop data
2076 * @len: number of bytes to write
2077 *
2078 * Read @len bytes to @buffer from the I/O channel.
2079 *
2080 * Returns the number of bytes written
2081 */
Hans Breuer2ad41ca2009-08-11 17:51:22 +02002082int
Owen Taylor3473f882001-02-23 17:55:21 +00002083xmlIOFTPRead(void * context, char * buffer, int len) {
Daniel Veillard5ea30d72004-11-08 11:54:28 +00002084 if ((buffer == NULL) || (len < 0)) return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00002085 return(xmlNanoFTPRead(context, &buffer[0], len));
2086}
2087
2088/**
2089 * xmlIOFTPClose:
2090 * @context: the I/O context
2091 *
2092 * Close an FTP I/O channel
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002093 *
2094 * Returns 0
Owen Taylor3473f882001-02-23 17:55:21 +00002095 */
Aleksey Sanin5aac8b82002-05-01 18:32:28 +00002096int
Owen Taylor3473f882001-02-23 17:55:21 +00002097xmlIOFTPClose (void * context) {
Daniel Veillardf012a642001-07-23 19:10:52 +00002098 return ( xmlNanoFTPClose(context) );
Owen Taylor3473f882001-02-23 17:55:21 +00002099}
2100#endif /* LIBXML_FTP_ENABLED */
2101
2102
2103/**
2104 * xmlRegisterInputCallbacks:
Daniel Veillard56a4cb82001-03-24 17:00:36 +00002105 * @matchFunc: the xmlInputMatchCallback
2106 * @openFunc: the xmlInputOpenCallback
2107 * @readFunc: the xmlInputReadCallback
2108 * @closeFunc: the xmlInputCloseCallback
Owen Taylor3473f882001-02-23 17:55:21 +00002109 *
2110 * Register a new set of I/O callback for handling parser input.
2111 *
2112 * Returns the registered handler number or -1 in case of error
2113 */
2114int
Daniel Veillard56a4cb82001-03-24 17:00:36 +00002115xmlRegisterInputCallbacks(xmlInputMatchCallback matchFunc,
2116 xmlInputOpenCallback openFunc, xmlInputReadCallback readFunc,
2117 xmlInputCloseCallback closeFunc) {
Owen Taylor3473f882001-02-23 17:55:21 +00002118 if (xmlInputCallbackNr >= MAX_INPUT_CALLBACK) {
2119 return(-1);
2120 }
Daniel Veillard56a4cb82001-03-24 17:00:36 +00002121 xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = matchFunc;
2122 xmlInputCallbackTable[xmlInputCallbackNr].opencallback = openFunc;
2123 xmlInputCallbackTable[xmlInputCallbackNr].readcallback = readFunc;
2124 xmlInputCallbackTable[xmlInputCallbackNr].closecallback = closeFunc;
Daniel Veillard9ec26532003-09-23 07:43:19 +00002125 xmlInputCallbackInitialized = 1;
Owen Taylor3473f882001-02-23 17:55:21 +00002126 return(xmlInputCallbackNr++);
2127}
2128
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002129#ifdef LIBXML_OUTPUT_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00002130/**
2131 * xmlRegisterOutputCallbacks:
Daniel Veillard56a4cb82001-03-24 17:00:36 +00002132 * @matchFunc: the xmlOutputMatchCallback
2133 * @openFunc: the xmlOutputOpenCallback
2134 * @writeFunc: the xmlOutputWriteCallback
2135 * @closeFunc: the xmlOutputCloseCallback
Owen Taylor3473f882001-02-23 17:55:21 +00002136 *
2137 * Register a new set of I/O callback for handling output.
2138 *
2139 * Returns the registered handler number or -1 in case of error
2140 */
2141int
Daniel Veillard56a4cb82001-03-24 17:00:36 +00002142xmlRegisterOutputCallbacks(xmlOutputMatchCallback matchFunc,
2143 xmlOutputOpenCallback openFunc, xmlOutputWriteCallback writeFunc,
2144 xmlOutputCloseCallback closeFunc) {
Owen Taylor3473f882001-02-23 17:55:21 +00002145 if (xmlOutputCallbackNr >= MAX_INPUT_CALLBACK) {
2146 return(-1);
2147 }
Daniel Veillard56a4cb82001-03-24 17:00:36 +00002148 xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = matchFunc;
2149 xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = openFunc;
2150 xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = writeFunc;
2151 xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = closeFunc;
Daniel Veillard9ec26532003-09-23 07:43:19 +00002152 xmlOutputCallbackInitialized = 1;
Owen Taylor3473f882001-02-23 17:55:21 +00002153 return(xmlOutputCallbackNr++);
2154}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002155#endif /* LIBXML_OUTPUT_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00002156
2157/**
2158 * xmlRegisterDefaultInputCallbacks:
2159 *
2160 * Registers the default compiled-in I/O handlers.
2161 */
2162void
Daniel Veillard6ad5c4a2006-10-11 16:43:06 +00002163xmlRegisterDefaultInputCallbacks(void) {
Owen Taylor3473f882001-02-23 17:55:21 +00002164 if (xmlInputCallbackInitialized)
2165 return;
2166
Daniel Veillard8ca85b22006-09-01 09:56:07 +00002167#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
2168 xmlInitPlatformSpecificIo();
2169#endif
2170
Owen Taylor3473f882001-02-23 17:55:21 +00002171 xmlRegisterInputCallbacks(xmlFileMatch, xmlFileOpen,
2172 xmlFileRead, xmlFileClose);
2173#ifdef HAVE_ZLIB_H
2174 xmlRegisterInputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
2175 xmlGzfileRead, xmlGzfileClose);
2176#endif /* HAVE_ZLIB_H */
2177
2178#ifdef LIBXML_HTTP_ENABLED
2179 xmlRegisterInputCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen,
2180 xmlIOHTTPRead, xmlIOHTTPClose);
2181#endif /* LIBXML_HTTP_ENABLED */
2182
2183#ifdef LIBXML_FTP_ENABLED
2184 xmlRegisterInputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
2185 xmlIOFTPRead, xmlIOFTPClose);
2186#endif /* LIBXML_FTP_ENABLED */
2187 xmlInputCallbackInitialized = 1;
2188}
2189
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002190#ifdef LIBXML_OUTPUT_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00002191/**
2192 * xmlRegisterDefaultOutputCallbacks:
2193 *
2194 * Registers the default compiled-in I/O handlers.
2195 */
2196void
Daniel Veillard6ad5c4a2006-10-11 16:43:06 +00002197xmlRegisterDefaultOutputCallbacks (void) {
Owen Taylor3473f882001-02-23 17:55:21 +00002198 if (xmlOutputCallbackInitialized)
2199 return;
2200
Daniel Veillard8ca85b22006-09-01 09:56:07 +00002201#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
2202 xmlInitPlatformSpecificIo();
2203#endif
2204
Owen Taylor3473f882001-02-23 17:55:21 +00002205 xmlRegisterOutputCallbacks(xmlFileMatch, xmlFileOpenW,
2206 xmlFileWrite, xmlFileClose);
Daniel Veillardf012a642001-07-23 19:10:52 +00002207
2208#ifdef LIBXML_HTTP_ENABLED
2209 xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPDfltOpenW,
2210 xmlIOHTTPWrite, xmlIOHTTPClosePut);
2211#endif
2212
Owen Taylor3473f882001-02-23 17:55:21 +00002213/*********************************
2214 No way a-priori to distinguish between gzipped files from
2215 uncompressed ones except opening if existing then closing
2216 and saving with same compression ratio ... a pain.
2217
2218#ifdef HAVE_ZLIB_H
2219 xmlRegisterOutputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
2220 xmlGzfileWrite, xmlGzfileClose);
2221#endif
Owen Taylor3473f882001-02-23 17:55:21 +00002222
2223 Nor FTP PUT ....
2224#ifdef LIBXML_FTP_ENABLED
2225 xmlRegisterOutputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
2226 xmlIOFTPWrite, xmlIOFTPClose);
2227#endif
2228 **********************************/
2229 xmlOutputCallbackInitialized = 1;
2230}
2231
Daniel Veillardf012a642001-07-23 19:10:52 +00002232#ifdef LIBXML_HTTP_ENABLED
2233/**
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002234 * xmlRegisterHTTPPostCallbacks:
Daniel Veillardf012a642001-07-23 19:10:52 +00002235 *
2236 * By default, libxml submits HTTP output requests using the "PUT" method.
2237 * Calling this method changes the HTTP output method to use the "POST"
2238 * method instead.
2239 *
2240 */
2241void
2242xmlRegisterHTTPPostCallbacks( void ) {
2243
2244 /* Register defaults if not done previously */
2245
2246 if ( xmlOutputCallbackInitialized == 0 )
2247 xmlRegisterDefaultOutputCallbacks( );
2248
2249 xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPDfltOpenW,
2250 xmlIOHTTPWrite, xmlIOHTTPClosePost);
2251 return;
2252}
2253#endif
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002254#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillardf012a642001-07-23 19:10:52 +00002255
Owen Taylor3473f882001-02-23 17:55:21 +00002256/**
2257 * xmlAllocParserInputBuffer:
2258 * @enc: the charset encoding if known
2259 *
2260 * Create a buffered parser input for progressive parsing
2261 *
2262 * Returns the new parser input or NULL
2263 */
2264xmlParserInputBufferPtr
2265xmlAllocParserInputBuffer(xmlCharEncoding enc) {
2266 xmlParserInputBufferPtr ret;
2267
2268 ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
2269 if (ret == NULL) {
Daniel Veillard05d987b2003-10-08 11:54:57 +00002270 xmlIOErrMemory("creating input buffer");
Owen Taylor3473f882001-02-23 17:55:21 +00002271 return(NULL);
2272 }
2273 memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
Daniel Veillard6155d8a2003-08-19 15:01:28 +00002274 ret->buffer = xmlBufferCreateSize(2 * xmlDefaultBufferSize);
Owen Taylor3473f882001-02-23 17:55:21 +00002275 if (ret->buffer == NULL) {
2276 xmlFree(ret);
2277 return(NULL);
2278 }
2279 ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT;
2280 ret->encoder = xmlGetCharEncodingHandler(enc);
2281 if (ret->encoder != NULL)
Daniel Veillard6155d8a2003-08-19 15:01:28 +00002282 ret->raw = xmlBufferCreateSize(2 * xmlDefaultBufferSize);
Owen Taylor3473f882001-02-23 17:55:21 +00002283 else
2284 ret->raw = NULL;
2285 ret->readcallback = NULL;
2286 ret->closecallback = NULL;
2287 ret->context = NULL;
William M. Brackc07329e2003-09-08 01:57:30 +00002288 ret->compressed = -1;
Daniel Veillard36711902004-02-11 13:25:26 +00002289 ret->rawconsumed = 0;
Owen Taylor3473f882001-02-23 17:55:21 +00002290
2291 return(ret);
2292}
2293
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002294#ifdef LIBXML_OUTPUT_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00002295/**
2296 * xmlAllocOutputBuffer:
2297 * @encoder: the encoding converter or NULL
2298 *
2299 * Create a buffered parser output
2300 *
2301 * Returns the new parser output or NULL
2302 */
2303xmlOutputBufferPtr
2304xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder) {
2305 xmlOutputBufferPtr ret;
2306
2307 ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
2308 if (ret == NULL) {
Daniel Veillard05d987b2003-10-08 11:54:57 +00002309 xmlIOErrMemory("creating output buffer");
Owen Taylor3473f882001-02-23 17:55:21 +00002310 return(NULL);
2311 }
2312 memset(ret, 0, (size_t) sizeof(xmlOutputBuffer));
2313 ret->buffer = xmlBufferCreate();
2314 if (ret->buffer == NULL) {
2315 xmlFree(ret);
2316 return(NULL);
2317 }
Daniel Veillarde83e93e2008-08-30 12:52:26 +00002318
Daniel Veillard43bc89c2009-03-23 19:32:04 +00002319 /* try to avoid a performance problem with Windows realloc() */
2320 if (ret->buffer->alloc == XML_BUFFER_ALLOC_EXACT)
2321 ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT;
2322
Daniel Veillardda3fee42008-09-01 13:08:57 +00002323 ret->encoder = encoder;
2324 if (encoder != NULL) {
2325 ret->conv = xmlBufferCreateSize(4000);
2326 if (ret->conv == NULL) {
2327 xmlFree(ret);
2328 return(NULL);
2329 }
2330
2331 /*
2332 * This call is designed to initiate the encoder state
2333 */
Hans Breuer2ad41ca2009-08-11 17:51:22 +02002334 xmlCharEncOutFunc(encoder, ret->conv, NULL);
Daniel Veillardda3fee42008-09-01 13:08:57 +00002335 } else
2336 ret->conv = NULL;
2337 ret->writecallback = NULL;
2338 ret->closecallback = NULL;
2339 ret->context = NULL;
2340 ret->written = 0;
2341
2342 return(ret);
2343}
2344
2345/**
2346 * xmlAllocOutputBufferInternal:
2347 * @encoder: the encoding converter or NULL
2348 *
2349 * Create a buffered parser output
2350 *
2351 * Returns the new parser output or NULL
2352 */
2353xmlOutputBufferPtr
2354xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder) {
2355 xmlOutputBufferPtr ret;
2356
2357 ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
2358 if (ret == NULL) {
2359 xmlIOErrMemory("creating output buffer");
2360 return(NULL);
2361 }
2362 memset(ret, 0, (size_t) sizeof(xmlOutputBuffer));
2363 ret->buffer = xmlBufferCreate();
2364 if (ret->buffer == NULL) {
2365 xmlFree(ret);
2366 return(NULL);
2367 }
2368
2369
Daniel Veillarde83e93e2008-08-30 12:52:26 +00002370 /*
2371 * For conversion buffers we use the special IO handling
Daniel Veillardda3fee42008-09-01 13:08:57 +00002372 * We don't do that from the exported API to avoid confusing
2373 * user's code.
Daniel Veillarde83e93e2008-08-30 12:52:26 +00002374 */
2375 ret->buffer->alloc = XML_BUFFER_ALLOC_IO;
2376 ret->buffer->contentIO = ret->buffer->content;
2377
Owen Taylor3473f882001-02-23 17:55:21 +00002378 ret->encoder = encoder;
2379 if (encoder != NULL) {
2380 ret->conv = xmlBufferCreateSize(4000);
Daniel Veillarde83e93e2008-08-30 12:52:26 +00002381 if (ret->conv == NULL) {
2382 xmlFree(ret);
2383 return(NULL);
2384 }
2385
Owen Taylor3473f882001-02-23 17:55:21 +00002386 /*
2387 * This call is designed to initiate the encoder state
2388 */
Hans Breuer2ad41ca2009-08-11 17:51:22 +02002389 xmlCharEncOutFunc(encoder, ret->conv, NULL);
Owen Taylor3473f882001-02-23 17:55:21 +00002390 } else
2391 ret->conv = NULL;
2392 ret->writecallback = NULL;
2393 ret->closecallback = NULL;
2394 ret->context = NULL;
2395 ret->written = 0;
2396
2397 return(ret);
2398}
Daniel Veillardda3fee42008-09-01 13:08:57 +00002399
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002400#endif /* LIBXML_OUTPUT_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00002401
2402/**
2403 * xmlFreeParserInputBuffer:
2404 * @in: a buffered parser input
2405 *
2406 * Free up the memory used by a buffered parser input
2407 */
2408void
2409xmlFreeParserInputBuffer(xmlParserInputBufferPtr in) {
Daniel Veillard8d8bf2c2003-09-17 19:36:25 +00002410 if (in == NULL) return;
2411
Owen Taylor3473f882001-02-23 17:55:21 +00002412 if (in->raw) {
2413 xmlBufferFree(in->raw);
2414 in->raw = NULL;
2415 }
2416 if (in->encoder != NULL) {
2417 xmlCharEncCloseFunc(in->encoder);
2418 }
2419 if (in->closecallback != NULL) {
2420 in->closecallback(in->context);
2421 }
2422 if (in->buffer != NULL) {
2423 xmlBufferFree(in->buffer);
2424 in->buffer = NULL;
2425 }
2426
Owen Taylor3473f882001-02-23 17:55:21 +00002427 xmlFree(in);
2428}
2429
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002430#ifdef LIBXML_OUTPUT_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00002431/**
2432 * xmlOutputBufferClose:
2433 * @out: a buffered output
2434 *
2435 * flushes and close the output I/O channel
2436 * and free up all the associated resources
2437 *
2438 * Returns the number of byte written or -1 in case of error.
2439 */
2440int
Daniel Veillard828ce832003-10-08 19:19:10 +00002441xmlOutputBufferClose(xmlOutputBufferPtr out)
2442{
Owen Taylor3473f882001-02-23 17:55:21 +00002443 int written;
Daniel Veillardf012a642001-07-23 19:10:52 +00002444 int err_rc = 0;
Owen Taylor3473f882001-02-23 17:55:21 +00002445
2446 if (out == NULL)
Daniel Veillard828ce832003-10-08 19:19:10 +00002447 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00002448 if (out->writecallback != NULL)
Daniel Veillard828ce832003-10-08 19:19:10 +00002449 xmlOutputBufferFlush(out);
Owen Taylor3473f882001-02-23 17:55:21 +00002450 if (out->closecallback != NULL) {
Daniel Veillard828ce832003-10-08 19:19:10 +00002451 err_rc = out->closecallback(out->context);
Owen Taylor3473f882001-02-23 17:55:21 +00002452 }
2453 written = out->written;
2454 if (out->conv) {
2455 xmlBufferFree(out->conv);
Daniel Veillard828ce832003-10-08 19:19:10 +00002456 out->conv = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00002457 }
2458 if (out->encoder != NULL) {
2459 xmlCharEncCloseFunc(out->encoder);
2460 }
2461 if (out->buffer != NULL) {
2462 xmlBufferFree(out->buffer);
Daniel Veillard828ce832003-10-08 19:19:10 +00002463 out->buffer = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00002464 }
2465
Daniel Veillard828ce832003-10-08 19:19:10 +00002466 if (out->error)
2467 err_rc = -1;
Owen Taylor3473f882001-02-23 17:55:21 +00002468 xmlFree(out);
Daniel Veillard828ce832003-10-08 19:19:10 +00002469 return ((err_rc == 0) ? written : err_rc);
Owen Taylor3473f882001-02-23 17:55:21 +00002470}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002471#endif /* LIBXML_OUTPUT_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00002472
Daniel Veillard1b243b42004-06-08 10:16:42 +00002473xmlParserInputBufferPtr
Daniel Veillard0335a842004-06-02 16:18:40 +00002474__xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
Owen Taylor3473f882001-02-23 17:55:21 +00002475 xmlParserInputBufferPtr ret;
Daniel Veillard388236f2001-07-08 18:35:48 +00002476 int i = 0;
Owen Taylor3473f882001-02-23 17:55:21 +00002477 void *context = NULL;
2478
2479 if (xmlInputCallbackInitialized == 0)
2480 xmlRegisterDefaultInputCallbacks();
2481
2482 if (URI == NULL) return(NULL);
2483
2484 /*
Daniel Veillardcbaf3992001-12-31 16:16:02 +00002485 * Try to find one of the input accept method accepting that scheme
Owen Taylor3473f882001-02-23 17:55:21 +00002486 * Go in reverse to give precedence to user defined handlers.
Daniel Veillard388236f2001-07-08 18:35:48 +00002487 */
2488 if (context == NULL) {
2489 for (i = xmlInputCallbackNr - 1;i >= 0;i--) {
2490 if ((xmlInputCallbackTable[i].matchcallback != NULL) &&
2491 (xmlInputCallbackTable[i].matchcallback(URI) != 0)) {
Igor Zlatkovic5f9fada2003-02-19 14:51:00 +00002492 context = xmlInputCallbackTable[i].opencallback(URI);
Daniel Veillard847332a2003-10-18 11:29:40 +00002493 if (context != NULL) {
Daniel Veillard388236f2001-07-08 18:35:48 +00002494 break;
Daniel Veillard847332a2003-10-18 11:29:40 +00002495 }
Daniel Veillard388236f2001-07-08 18:35:48 +00002496 }
Owen Taylor3473f882001-02-23 17:55:21 +00002497 }
2498 }
2499 if (context == NULL) {
2500 return(NULL);
2501 }
2502
2503 /*
2504 * Allocate the Input buffer front-end.
2505 */
2506 ret = xmlAllocParserInputBuffer(enc);
2507 if (ret != NULL) {
2508 ret->context = context;
2509 ret->readcallback = xmlInputCallbackTable[i].readcallback;
2510 ret->closecallback = xmlInputCallbackTable[i].closecallback;
William M. Brackc07329e2003-09-08 01:57:30 +00002511#ifdef HAVE_ZLIB_H
William M. Brackc5cbf992003-10-29 22:15:13 +00002512 if ((xmlInputCallbackTable[i].opencallback == xmlGzfileOpen) &&
2513 (strcmp(URI, "-") != 0)) {
William M. Brackc07329e2003-09-08 01:57:30 +00002514 if (((z_stream *)context)->avail_in > 4) {
2515 char *cptr, buff4[4];
Daniel Veillard07cb8222003-09-10 10:51:05 +00002516 cptr = (char *) ((z_stream *)context)->next_in;
William M. Brackc07329e2003-09-08 01:57:30 +00002517 if (gzread(context, buff4, 4) == 4) {
2518 if (strncmp(buff4, cptr, 4) == 0)
2519 ret->compressed = 0;
2520 else
2521 ret->compressed = 1;
2522 gzrewind(context);
2523 }
2524 }
2525 }
2526#endif
Owen Taylor3473f882001-02-23 17:55:21 +00002527 }
William M. Brack42331a92004-07-29 07:07:16 +00002528 else
2529 xmlInputCallbackTable[i].closecallback (context);
2530
Owen Taylor3473f882001-02-23 17:55:21 +00002531 return(ret);
2532}
2533
2534/**
Daniel Veillard0335a842004-06-02 16:18:40 +00002535 * xmlParserInputBufferCreateFilename:
Owen Taylor3473f882001-02-23 17:55:21 +00002536 * @URI: a C string containing the URI or filename
Daniel Veillard0335a842004-06-02 16:18:40 +00002537 * @enc: the charset encoding if known
Owen Taylor3473f882001-02-23 17:55:21 +00002538 *
Daniel Veillard0335a842004-06-02 16:18:40 +00002539 * Create a buffered parser input for the progressive parsing of a file
2540 * If filename is "-' then we use stdin as the input.
Owen Taylor3473f882001-02-23 17:55:21 +00002541 * Automatic support for ZLIB/Compress compressed document is provided
2542 * by default if found at compile-time.
Daniel Veillard0335a842004-06-02 16:18:40 +00002543 * Do an encoding check if enc == XML_CHAR_ENCODING_NONE
Owen Taylor3473f882001-02-23 17:55:21 +00002544 *
Daniel Veillard0335a842004-06-02 16:18:40 +00002545 * Returns the new parser input or NULL
Owen Taylor3473f882001-02-23 17:55:21 +00002546 */
Daniel Veillard0335a842004-06-02 16:18:40 +00002547xmlParserInputBufferPtr
2548xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
2549 if ((xmlParserInputBufferCreateFilenameValue)) {
2550 return xmlParserInputBufferCreateFilenameValue(URI, enc);
2551 }
2552 return __xmlParserInputBufferCreateFilename(URI, enc);
2553}
2554
2555#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard1b243b42004-06-08 10:16:42 +00002556xmlOutputBufferPtr
Daniel Veillard0335a842004-06-02 16:18:40 +00002557__xmlOutputBufferCreateFilename(const char *URI,
Owen Taylor3473f882001-02-23 17:55:21 +00002558 xmlCharEncodingHandlerPtr encoder,
Daniel Veillard0335a842004-06-02 16:18:40 +00002559 int compression ATTRIBUTE_UNUSED) {
Owen Taylor3473f882001-02-23 17:55:21 +00002560 xmlOutputBufferPtr ret;
Daniel Veillard966a31e2004-05-09 02:58:44 +00002561 xmlURIPtr puri;
Daniel Veillardecb6f5b2001-08-15 08:47:42 +00002562 int i = 0;
Owen Taylor3473f882001-02-23 17:55:21 +00002563 void *context = NULL;
Daniel Veillard966a31e2004-05-09 02:58:44 +00002564 char *unescaped = NULL;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +00002565#ifdef HAVE_ZLIB_H
Daniel Veillard966a31e2004-05-09 02:58:44 +00002566 int is_file_uri = 1;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +00002567#endif
Daniel Veillardf012a642001-07-23 19:10:52 +00002568
Owen Taylor3473f882001-02-23 17:55:21 +00002569 if (xmlOutputCallbackInitialized == 0)
2570 xmlRegisterDefaultOutputCallbacks();
2571
2572 if (URI == NULL) return(NULL);
2573
Daniel Veillard966a31e2004-05-09 02:58:44 +00002574 puri = xmlParseURI(URI);
2575 if (puri != NULL) {
Daniel Veillard8fcd2ca2005-07-03 14:42:56 +00002576#ifdef HAVE_ZLIB_H
Daniel Veillard18a65092004-05-11 15:57:42 +00002577 if ((puri->scheme != NULL) &&
2578 (!xmlStrEqual(BAD_CAST puri->scheme, BAD_CAST "file")))
Daniel Veillard966a31e2004-05-09 02:58:44 +00002579 is_file_uri = 0;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +00002580#endif
Daniel Veillard966a31e2004-05-09 02:58:44 +00002581 /*
2582 * try to limit the damages of the URI unescaping code.
2583 */
Daniel Veillarde8967e02006-10-11 09:15:00 +00002584 if ((puri->scheme == NULL) ||
2585 (xmlStrEqual(BAD_CAST puri->scheme, BAD_CAST "file")))
Daniel Veillard966a31e2004-05-09 02:58:44 +00002586 unescaped = xmlURIUnescapeString(URI, 0, NULL);
2587 xmlFreeURI(puri);
2588 }
Owen Taylor3473f882001-02-23 17:55:21 +00002589
2590 /*
Daniel Veillardcbaf3992001-12-31 16:16:02 +00002591 * Try to find one of the output accept method accepting that scheme
Owen Taylor3473f882001-02-23 17:55:21 +00002592 * Go in reverse to give precedence to user defined handlers.
Daniel Veillardecb6f5b2001-08-15 08:47:42 +00002593 * try with an unescaped version of the URI
Owen Taylor3473f882001-02-23 17:55:21 +00002594 */
Daniel Veillardecb6f5b2001-08-15 08:47:42 +00002595 if (unescaped != NULL) {
2596#ifdef HAVE_ZLIB_H
Daniel Veillard966a31e2004-05-09 02:58:44 +00002597 if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) {
Daniel Veillardecb6f5b2001-08-15 08:47:42 +00002598 context = xmlGzfileOpenW(unescaped, compression);
2599 if (context != NULL) {
Daniel Veillardda3fee42008-09-01 13:08:57 +00002600 ret = xmlAllocOutputBufferInternal(encoder);
Daniel Veillardecb6f5b2001-08-15 08:47:42 +00002601 if (ret != NULL) {
2602 ret->context = context;
2603 ret->writecallback = xmlGzfileWrite;
2604 ret->closecallback = xmlGzfileClose;
2605 }
2606 xmlFree(unescaped);
2607 return(ret);
2608 }
2609 }
Daniel Veillardf012a642001-07-23 19:10:52 +00002610#endif
Daniel Veillardecb6f5b2001-08-15 08:47:42 +00002611 for (i = xmlOutputCallbackNr - 1;i >= 0;i--) {
2612 if ((xmlOutputCallbackTable[i].matchcallback != NULL) &&
2613 (xmlOutputCallbackTable[i].matchcallback(unescaped) != 0)) {
2614#if defined(LIBXML_HTTP_ENABLED) && defined(HAVE_ZLIB_H)
2615 /* Need to pass compression parameter into HTTP open calls */
2616 if (xmlOutputCallbackTable[i].matchcallback == xmlIOHTTPMatch)
2617 context = xmlIOHTTPOpenW(unescaped, compression);
2618 else
2619#endif
2620 context = xmlOutputCallbackTable[i].opencallback(unescaped);
2621 if (context != NULL)
2622 break;
2623 }
2624 }
2625 xmlFree(unescaped);
2626 }
Daniel Veillardf012a642001-07-23 19:10:52 +00002627
Daniel Veillardecb6f5b2001-08-15 08:47:42 +00002628 /*
2629 * If this failed try with a non-escaped URI this may be a strange
2630 * filename
2631 */
2632 if (context == NULL) {
2633#ifdef HAVE_ZLIB_H
Daniel Veillard966a31e2004-05-09 02:58:44 +00002634 if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) {
Igor Zlatkovic5f9fada2003-02-19 14:51:00 +00002635 context = xmlGzfileOpenW(URI, compression);
Daniel Veillardecb6f5b2001-08-15 08:47:42 +00002636 if (context != NULL) {
Daniel Veillardda3fee42008-09-01 13:08:57 +00002637 ret = xmlAllocOutputBufferInternal(encoder);
Daniel Veillardecb6f5b2001-08-15 08:47:42 +00002638 if (ret != NULL) {
2639 ret->context = context;
2640 ret->writecallback = xmlGzfileWrite;
2641 ret->closecallback = xmlGzfileClose;
2642 }
2643 return(ret);
2644 }
2645 }
2646#endif
2647 for (i = xmlOutputCallbackNr - 1;i >= 0;i--) {
2648 if ((xmlOutputCallbackTable[i].matchcallback != NULL) &&
Igor Zlatkovic5f9fada2003-02-19 14:51:00 +00002649 (xmlOutputCallbackTable[i].matchcallback(URI) != 0)) {
Daniel Veillardecb6f5b2001-08-15 08:47:42 +00002650#if defined(LIBXML_HTTP_ENABLED) && defined(HAVE_ZLIB_H)
2651 /* Need to pass compression parameter into HTTP open calls */
2652 if (xmlOutputCallbackTable[i].matchcallback == xmlIOHTTPMatch)
2653 context = xmlIOHTTPOpenW(URI, compression);
2654 else
2655#endif
2656 context = xmlOutputCallbackTable[i].opencallback(URI);
2657 if (context != NULL)
2658 break;
2659 }
Owen Taylor3473f882001-02-23 17:55:21 +00002660 }
2661 }
Daniel Veillardf012a642001-07-23 19:10:52 +00002662
Owen Taylor3473f882001-02-23 17:55:21 +00002663 if (context == NULL) {
2664 return(NULL);
2665 }
2666
2667 /*
2668 * Allocate the Output buffer front-end.
2669 */
Daniel Veillardda3fee42008-09-01 13:08:57 +00002670 ret = xmlAllocOutputBufferInternal(encoder);
Owen Taylor3473f882001-02-23 17:55:21 +00002671 if (ret != NULL) {
2672 ret->context = context;
2673 ret->writecallback = xmlOutputCallbackTable[i].writecallback;
2674 ret->closecallback = xmlOutputCallbackTable[i].closecallback;
2675 }
2676 return(ret);
2677}
Daniel Veillard0335a842004-06-02 16:18:40 +00002678
2679/**
2680 * xmlOutputBufferCreateFilename:
2681 * @URI: a C string containing the URI or filename
2682 * @encoder: the encoding converter or NULL
2683 * @compression: the compression ration (0 none, 9 max).
2684 *
2685 * Create a buffered output for the progressive saving of a file
2686 * If filename is "-' then we use stdout as the output.
2687 * Automatic support for ZLIB/Compress compressed document is provided
2688 * by default if found at compile-time.
2689 * TODO: currently if compression is set, the library only support
2690 * writing to a local file.
2691 *
2692 * Returns the new output or NULL
2693 */
2694xmlOutputBufferPtr
2695xmlOutputBufferCreateFilename(const char *URI,
2696 xmlCharEncodingHandlerPtr encoder,
2697 int compression ATTRIBUTE_UNUSED) {
2698 if ((xmlOutputBufferCreateFilenameValue)) {
2699 return xmlOutputBufferCreateFilenameValue(URI, encoder, compression);
2700 }
2701 return __xmlOutputBufferCreateFilename(URI, encoder, compression);
2702}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002703#endif /* LIBXML_OUTPUT_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00002704
2705/**
2706 * xmlParserInputBufferCreateFile:
Hans Breuer2ad41ca2009-08-11 17:51:22 +02002707 * @file: a FILE*
Owen Taylor3473f882001-02-23 17:55:21 +00002708 * @enc: the charset encoding if known
2709 *
2710 * Create a buffered parser input for the progressive parsing of a FILE *
2711 * buffered C I/O
2712 *
2713 * Returns the new parser input or NULL
2714 */
2715xmlParserInputBufferPtr
2716xmlParserInputBufferCreateFile(FILE *file, xmlCharEncoding enc) {
2717 xmlParserInputBufferPtr ret;
2718
2719 if (xmlInputCallbackInitialized == 0)
2720 xmlRegisterDefaultInputCallbacks();
2721
2722 if (file == NULL) return(NULL);
2723
2724 ret = xmlAllocParserInputBuffer(enc);
2725 if (ret != NULL) {
2726 ret->context = file;
2727 ret->readcallback = xmlFileRead;
2728 ret->closecallback = xmlFileFlush;
2729 }
2730
2731 return(ret);
2732}
2733
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002734#ifdef LIBXML_OUTPUT_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00002735/**
2736 * xmlOutputBufferCreateFile:
Hans Breuer2ad41ca2009-08-11 17:51:22 +02002737 * @file: a FILE*
Owen Taylor3473f882001-02-23 17:55:21 +00002738 * @encoder: the encoding converter or NULL
2739 *
2740 * Create a buffered output for the progressive saving to a FILE *
2741 * buffered C I/O
2742 *
2743 * Returns the new parser output or NULL
2744 */
2745xmlOutputBufferPtr
2746xmlOutputBufferCreateFile(FILE *file, xmlCharEncodingHandlerPtr encoder) {
2747 xmlOutputBufferPtr ret;
2748
2749 if (xmlOutputCallbackInitialized == 0)
2750 xmlRegisterDefaultOutputCallbacks();
2751
2752 if (file == NULL) return(NULL);
2753
Daniel Veillardda3fee42008-09-01 13:08:57 +00002754 ret = xmlAllocOutputBufferInternal(encoder);
Owen Taylor3473f882001-02-23 17:55:21 +00002755 if (ret != NULL) {
2756 ret->context = file;
2757 ret->writecallback = xmlFileWrite;
2758 ret->closecallback = xmlFileFlush;
2759 }
2760
2761 return(ret);
2762}
Daniel Veillard9a00fd22005-11-09 08:56:26 +00002763
2764/**
2765 * xmlOutputBufferCreateBuffer:
2766 * @buffer: a xmlBufferPtr
2767 * @encoder: the encoding converter or NULL
2768 *
2769 * Create a buffered output for the progressive saving to a xmlBuffer
2770 *
2771 * Returns the new parser output or NULL
2772 */
2773xmlOutputBufferPtr
2774xmlOutputBufferCreateBuffer(xmlBufferPtr buffer,
2775 xmlCharEncodingHandlerPtr encoder) {
2776 xmlOutputBufferPtr ret;
2777
2778 if (buffer == NULL) return(NULL);
2779
Rob Richardsa44f2342005-11-09 18:03:45 +00002780 ret = xmlOutputBufferCreateIO((xmlOutputWriteCallback)
2781 xmlBufferWrite,
2782 (xmlOutputCloseCallback)
Daniel Veillard4d3866c2005-11-13 12:43:59 +00002783 NULL, (void *) buffer, encoder);
Daniel Veillard9a00fd22005-11-09 08:56:26 +00002784
2785 return(ret);
2786}
2787
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002788#endif /* LIBXML_OUTPUT_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00002789
2790/**
2791 * xmlParserInputBufferCreateFd:
2792 * @fd: a file descriptor number
2793 * @enc: the charset encoding if known
2794 *
2795 * Create a buffered parser input for the progressive parsing for the input
2796 * from a file descriptor
2797 *
2798 * Returns the new parser input or NULL
2799 */
2800xmlParserInputBufferPtr
2801xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) {
2802 xmlParserInputBufferPtr ret;
2803
2804 if (fd < 0) return(NULL);
2805
2806 ret = xmlAllocParserInputBuffer(enc);
2807 if (ret != NULL) {
Daniel Veillard8fcc4942001-07-17 20:07:33 +00002808 ret->context = (void *) (long) fd;
Owen Taylor3473f882001-02-23 17:55:21 +00002809 ret->readcallback = xmlFdRead;
2810 ret->closecallback = xmlFdClose;
2811 }
2812
2813 return(ret);
2814}
2815
2816/**
2817 * xmlParserInputBufferCreateMem:
2818 * @mem: the memory input
2819 * @size: the length of the memory block
2820 * @enc: the charset encoding if known
2821 *
2822 * Create a buffered parser input for the progressive parsing for the input
2823 * from a memory area.
2824 *
2825 * Returns the new parser input or NULL
2826 */
2827xmlParserInputBufferPtr
2828xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) {
2829 xmlParserInputBufferPtr ret;
William M. Bracka3215c72004-07-31 16:24:01 +00002830 int errcode;
Owen Taylor3473f882001-02-23 17:55:21 +00002831
2832 if (size <= 0) return(NULL);
2833 if (mem == NULL) return(NULL);
2834
2835 ret = xmlAllocParserInputBuffer(enc);
2836 if (ret != NULL) {
2837 ret->context = (void *) mem;
2838 ret->readcallback = (xmlInputReadCallback) xmlNop;
2839 ret->closecallback = NULL;
William M. Bracka3215c72004-07-31 16:24:01 +00002840 errcode = xmlBufferAdd(ret->buffer, (const xmlChar *) mem, size);
2841 if (errcode != 0) {
2842 xmlFree(ret);
2843 return(NULL);
2844 }
Owen Taylor3473f882001-02-23 17:55:21 +00002845 }
2846
2847 return(ret);
2848}
2849
2850/**
Daniel Veillard53350552003-09-18 13:35:51 +00002851 * xmlParserInputBufferCreateStatic:
2852 * @mem: the memory input
2853 * @size: the length of the memory block
2854 * @enc: the charset encoding if known
2855 *
2856 * Create a buffered parser input for the progressive parsing for the input
2857 * from an immutable memory area. This will not copy the memory area to
2858 * the buffer, but the memory is expected to be available until the end of
2859 * the parsing, this is useful for example when using mmap'ed file.
2860 *
2861 * Returns the new parser input or NULL
2862 */
2863xmlParserInputBufferPtr
2864xmlParserInputBufferCreateStatic(const char *mem, int size,
2865 xmlCharEncoding enc) {
2866 xmlParserInputBufferPtr ret;
2867
2868 if (size <= 0) return(NULL);
2869 if (mem == NULL) return(NULL);
2870
2871 ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
2872 if (ret == NULL) {
Daniel Veillard05d987b2003-10-08 11:54:57 +00002873 xmlIOErrMemory("creating input buffer");
Daniel Veillard53350552003-09-18 13:35:51 +00002874 return(NULL);
2875 }
2876 memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
Daniel Veillarde72c5082003-09-19 12:44:05 +00002877 ret->buffer = xmlBufferCreateStatic((void *)mem, (size_t) size);
Daniel Veillard53350552003-09-18 13:35:51 +00002878 if (ret->buffer == NULL) {
2879 xmlFree(ret);
2880 return(NULL);
2881 }
2882 ret->encoder = xmlGetCharEncodingHandler(enc);
2883 if (ret->encoder != NULL)
2884 ret->raw = xmlBufferCreateSize(2 * xmlDefaultBufferSize);
2885 else
2886 ret->raw = NULL;
2887 ret->compressed = -1;
2888 ret->context = (void *) mem;
2889 ret->readcallback = NULL;
2890 ret->closecallback = NULL;
2891
2892 return(ret);
2893}
2894
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002895#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard53350552003-09-18 13:35:51 +00002896/**
Owen Taylor3473f882001-02-23 17:55:21 +00002897 * xmlOutputBufferCreateFd:
2898 * @fd: a file descriptor number
2899 * @encoder: the encoding converter or NULL
2900 *
Hans Breuer2ad41ca2009-08-11 17:51:22 +02002901 * Create a buffered output for the progressive saving
Owen Taylor3473f882001-02-23 17:55:21 +00002902 * to a file descriptor
2903 *
2904 * Returns the new parser output or NULL
2905 */
2906xmlOutputBufferPtr
2907xmlOutputBufferCreateFd(int fd, xmlCharEncodingHandlerPtr encoder) {
2908 xmlOutputBufferPtr ret;
2909
2910 if (fd < 0) return(NULL);
2911
Daniel Veillardda3fee42008-09-01 13:08:57 +00002912 ret = xmlAllocOutputBufferInternal(encoder);
Owen Taylor3473f882001-02-23 17:55:21 +00002913 if (ret != NULL) {
Daniel Veillard8fcc4942001-07-17 20:07:33 +00002914 ret->context = (void *) (long) fd;
Owen Taylor3473f882001-02-23 17:55:21 +00002915 ret->writecallback = xmlFdWrite;
Daniel Veillard7db38712002-02-07 16:39:11 +00002916 ret->closecallback = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00002917 }
2918
2919 return(ret);
2920}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002921#endif /* LIBXML_OUTPUT_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00002922
2923/**
2924 * xmlParserInputBufferCreateIO:
2925 * @ioread: an I/O read function
2926 * @ioclose: an I/O close function
2927 * @ioctx: an I/O handler
2928 * @enc: the charset encoding if known
2929 *
2930 * Create a buffered parser input for the progressive parsing for the input
2931 * from an I/O handler
2932 *
2933 * Returns the new parser input or NULL
2934 */
2935xmlParserInputBufferPtr
2936xmlParserInputBufferCreateIO(xmlInputReadCallback ioread,
2937 xmlInputCloseCallback ioclose, void *ioctx, xmlCharEncoding enc) {
2938 xmlParserInputBufferPtr ret;
2939
2940 if (ioread == NULL) return(NULL);
2941
2942 ret = xmlAllocParserInputBuffer(enc);
2943 if (ret != NULL) {
2944 ret->context = (void *) ioctx;
2945 ret->readcallback = ioread;
2946 ret->closecallback = ioclose;
2947 }
2948
2949 return(ret);
2950}
2951
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002952#ifdef LIBXML_OUTPUT_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00002953/**
2954 * xmlOutputBufferCreateIO:
2955 * @iowrite: an I/O write function
2956 * @ioclose: an I/O close function
2957 * @ioctx: an I/O handler
Daniel Veillard9d06d302002-01-22 18:15:52 +00002958 * @encoder: the charset encoding if known
Owen Taylor3473f882001-02-23 17:55:21 +00002959 *
2960 * Create a buffered output for the progressive saving
2961 * to an I/O handler
2962 *
2963 * Returns the new parser output or NULL
2964 */
2965xmlOutputBufferPtr
2966xmlOutputBufferCreateIO(xmlOutputWriteCallback iowrite,
2967 xmlOutputCloseCallback ioclose, void *ioctx,
2968 xmlCharEncodingHandlerPtr encoder) {
2969 xmlOutputBufferPtr ret;
2970
2971 if (iowrite == NULL) return(NULL);
2972
Daniel Veillardda3fee42008-09-01 13:08:57 +00002973 ret = xmlAllocOutputBufferInternal(encoder);
Owen Taylor3473f882001-02-23 17:55:21 +00002974 if (ret != NULL) {
2975 ret->context = (void *) ioctx;
2976 ret->writecallback = iowrite;
2977 ret->closecallback = ioclose;
2978 }
2979
2980 return(ret);
2981}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002982#endif /* LIBXML_OUTPUT_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00002983
2984/**
Daniel Veillard1b243b42004-06-08 10:16:42 +00002985 * xmlParserInputBufferCreateFilenameDefault:
2986 * @func: function pointer to the new ParserInputBufferCreateFilenameFunc
2987 *
2988 * Registers a callback for URI input file handling
2989 *
2990 * Returns the old value of the registration function
2991 */
2992xmlParserInputBufferCreateFilenameFunc
2993xmlParserInputBufferCreateFilenameDefault(xmlParserInputBufferCreateFilenameFunc func)
2994{
2995 xmlParserInputBufferCreateFilenameFunc old = xmlParserInputBufferCreateFilenameValue;
2996 if (old == NULL) {
2997 old = __xmlParserInputBufferCreateFilename;
2998 }
2999
3000 xmlParserInputBufferCreateFilenameValue = func;
3001 return(old);
3002}
3003
3004/**
3005 * xmlOutputBufferCreateFilenameDefault:
3006 * @func: function pointer to the new OutputBufferCreateFilenameFunc
3007 *
3008 * Registers a callback for URI output file handling
3009 *
3010 * Returns the old value of the registration function
3011 */
3012xmlOutputBufferCreateFilenameFunc
3013xmlOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func)
3014{
3015 xmlOutputBufferCreateFilenameFunc old = xmlOutputBufferCreateFilenameValue;
3016#ifdef LIBXML_OUTPUT_ENABLED
3017 if (old == NULL) {
3018 old = __xmlOutputBufferCreateFilename;
3019 }
3020#endif
3021 xmlOutputBufferCreateFilenameValue = func;
3022 return(old);
3023}
3024
3025/**
Owen Taylor3473f882001-02-23 17:55:21 +00003026 * xmlParserInputBufferPush:
3027 * @in: a buffered parser input
3028 * @len: the size in bytes of the array.
3029 * @buf: an char array
3030 *
3031 * Push the content of the arry in the input buffer
3032 * This routine handle the I18N transcoding to internal UTF-8
3033 * This is used when operating the parser in progressive (push) mode.
3034 *
3035 * Returns the number of chars read and stored in the buffer, or -1
3036 * in case of error.
3037 */
3038int
3039xmlParserInputBufferPush(xmlParserInputBufferPtr in,
3040 int len, const char *buf) {
3041 int nbchars = 0;
William M. Bracka3215c72004-07-31 16:24:01 +00003042 int ret;
Owen Taylor3473f882001-02-23 17:55:21 +00003043
3044 if (len < 0) return(0);
Daniel Veillard97bf4d02003-10-08 18:58:28 +00003045 if ((in == NULL) || (in->error)) return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00003046 if (in->encoder != NULL) {
Daniel Veillard36711902004-02-11 13:25:26 +00003047 unsigned int use;
3048
Owen Taylor3473f882001-02-23 17:55:21 +00003049 /*
3050 * Store the data in the incoming raw buffer
3051 */
3052 if (in->raw == NULL) {
3053 in->raw = xmlBufferCreate();
3054 }
William M. Bracka3215c72004-07-31 16:24:01 +00003055 ret = xmlBufferAdd(in->raw, (const xmlChar *) buf, len);
3056 if (ret != 0)
3057 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00003058
3059 /*
3060 * convert as much as possible to the parser reading buffer.
3061 */
Daniel Veillard36711902004-02-11 13:25:26 +00003062 use = in->raw->use;
Owen Taylor3473f882001-02-23 17:55:21 +00003063 nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
3064 if (nbchars < 0) {
Daniel Veillard05d987b2003-10-08 11:54:57 +00003065 xmlIOErr(XML_IO_ENCODER, NULL);
Daniel Veillard97bf4d02003-10-08 18:58:28 +00003066 in->error = XML_IO_ENCODER;
Owen Taylor3473f882001-02-23 17:55:21 +00003067 return(-1);
3068 }
Daniel Veillard36711902004-02-11 13:25:26 +00003069 in->rawconsumed += (use - in->raw->use);
Owen Taylor3473f882001-02-23 17:55:21 +00003070 } else {
3071 nbchars = len;
William M. Bracka3215c72004-07-31 16:24:01 +00003072 ret = xmlBufferAdd(in->buffer, (xmlChar *) buf, nbchars);
3073 if (ret != 0)
3074 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00003075 }
3076#ifdef DEBUG_INPUT
3077 xmlGenericError(xmlGenericErrorContext,
3078 "I/O: pushed %d chars, buffer %d/%d\n",
3079 nbchars, in->buffer->use, in->buffer->size);
3080#endif
3081 return(nbchars);
3082}
3083
3084/**
Daniel Veillardddffd2a2002-03-05 20:28:20 +00003085 * endOfInput:
3086 *
3087 * When reading from an Input channel indicated end of file or error
3088 * don't reread from it again.
3089 */
3090static int
3091endOfInput (void * context ATTRIBUTE_UNUSED,
3092 char * buffer ATTRIBUTE_UNUSED,
3093 int len ATTRIBUTE_UNUSED) {
3094 return(0);
3095}
3096
3097/**
Owen Taylor3473f882001-02-23 17:55:21 +00003098 * xmlParserInputBufferGrow:
3099 * @in: a buffered parser input
3100 * @len: indicative value of the amount of chars to read
3101 *
3102 * Grow up the content of the input buffer, the old data are preserved
3103 * This routine handle the I18N transcoding to internal UTF-8
3104 * This routine is used when operating the parser in normal (pull) mode
3105 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +00003106 * TODO: one should be able to remove one extra copy by copying directly
Owen Taylor3473f882001-02-23 17:55:21 +00003107 * onto in->buffer or in->raw
3108 *
3109 * Returns the number of chars read and stored in the buffer, or -1
3110 * in case of error.
3111 */
3112int
3113xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
3114 char *buffer = NULL;
3115 int res = 0;
3116 int nbchars = 0;
3117 int buffree;
Daniel Veillard9e412302002-06-10 15:59:44 +00003118 unsigned int needSize;
Owen Taylor3473f882001-02-23 17:55:21 +00003119
Daniel Veillard97bf4d02003-10-08 18:58:28 +00003120 if ((in == NULL) || (in->error)) return(-1);
Daniel Veillard6155d8a2003-08-19 15:01:28 +00003121 if ((len <= MINLEN) && (len != 4))
Owen Taylor3473f882001-02-23 17:55:21 +00003122 len = MINLEN;
Daniel Veillard6155d8a2003-08-19 15:01:28 +00003123
Owen Taylor3473f882001-02-23 17:55:21 +00003124 buffree = in->buffer->size - in->buffer->use;
3125 if (buffree <= 0) {
Daniel Veillard05d987b2003-10-08 11:54:57 +00003126 xmlIOErr(XML_IO_BUFFER_FULL, NULL);
Daniel Veillard97bf4d02003-10-08 18:58:28 +00003127 in->error = XML_IO_BUFFER_FULL;
William M. Bracka3215c72004-07-31 16:24:01 +00003128 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00003129 }
Owen Taylor3473f882001-02-23 17:55:21 +00003130
Daniel Veillarde5354492002-05-16 08:43:22 +00003131 needSize = in->buffer->use + len + 1;
3132 if (needSize > in->buffer->size){
3133 if (!xmlBufferResize(in->buffer, needSize)){
Daniel Veillard05d987b2003-10-08 11:54:57 +00003134 xmlIOErrMemory("growing input buffer");
Daniel Veillard97bf4d02003-10-08 18:58:28 +00003135 in->error = XML_ERR_NO_MEMORY;
William M. Bracka3215c72004-07-31 16:24:01 +00003136 return(-1);
Daniel Veillarde5354492002-05-16 08:43:22 +00003137 }
Owen Taylor3473f882001-02-23 17:55:21 +00003138 }
Daniel Veillarde5354492002-05-16 08:43:22 +00003139 buffer = (char *)&in->buffer->content[in->buffer->use];
Owen Taylor3473f882001-02-23 17:55:21 +00003140
3141 /*
3142 * Call the read method for this I/O type.
3143 */
3144 if (in->readcallback != NULL) {
3145 res = in->readcallback(in->context, &buffer[0], len);
Daniel Veillardddffd2a2002-03-05 20:28:20 +00003146 if (res <= 0)
3147 in->readcallback = endOfInput;
Owen Taylor3473f882001-02-23 17:55:21 +00003148 } else {
Daniel Veillard05d987b2003-10-08 11:54:57 +00003149 xmlIOErr(XML_IO_NO_INPUT, NULL);
Daniel Veillard97bf4d02003-10-08 18:58:28 +00003150 in->error = XML_IO_NO_INPUT;
Owen Taylor3473f882001-02-23 17:55:21 +00003151 return(-1);
3152 }
3153 if (res < 0) {
Owen Taylor3473f882001-02-23 17:55:21 +00003154 return(-1);
3155 }
3156 len = res;
3157 if (in->encoder != NULL) {
Daniel Veillard36711902004-02-11 13:25:26 +00003158 unsigned int use;
3159
Owen Taylor3473f882001-02-23 17:55:21 +00003160 /*
3161 * Store the data in the incoming raw buffer
3162 */
3163 if (in->raw == NULL) {
3164 in->raw = xmlBufferCreate();
3165 }
William M. Bracka3215c72004-07-31 16:24:01 +00003166 res = xmlBufferAdd(in->raw, (const xmlChar *) buffer, len);
3167 if (res != 0)
3168 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00003169
3170 /*
3171 * convert as much as possible to the parser reading buffer.
3172 */
Daniel Veillard36711902004-02-11 13:25:26 +00003173 use = in->raw->use;
Owen Taylor3473f882001-02-23 17:55:21 +00003174 nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
3175 if (nbchars < 0) {
Daniel Veillard05d987b2003-10-08 11:54:57 +00003176 xmlIOErr(XML_IO_ENCODER, NULL);
Daniel Veillard97bf4d02003-10-08 18:58:28 +00003177 in->error = XML_IO_ENCODER;
Owen Taylor3473f882001-02-23 17:55:21 +00003178 return(-1);
3179 }
Daniel Veillard36711902004-02-11 13:25:26 +00003180 in->rawconsumed += (use - in->raw->use);
Owen Taylor3473f882001-02-23 17:55:21 +00003181 } else {
3182 nbchars = len;
Hans Breuer2ad41ca2009-08-11 17:51:22 +02003183 in->buffer->use += nbchars;
Daniel Veillarde5354492002-05-16 08:43:22 +00003184 buffer[nbchars] = 0;
Owen Taylor3473f882001-02-23 17:55:21 +00003185 }
3186#ifdef DEBUG_INPUT
3187 xmlGenericError(xmlGenericErrorContext,
3188 "I/O: read %d chars, buffer %d/%d\n",
3189 nbchars, in->buffer->use, in->buffer->size);
3190#endif
Owen Taylor3473f882001-02-23 17:55:21 +00003191 return(nbchars);
3192}
3193
3194/**
3195 * xmlParserInputBufferRead:
3196 * @in: a buffered parser input
3197 * @len: indicative value of the amount of chars to read
3198 *
3199 * Refresh the content of the input buffer, the old data are considered
3200 * consumed
3201 * This routine handle the I18N transcoding to internal UTF-8
3202 *
3203 * Returns the number of chars read and stored in the buffer, or -1
3204 * in case of error.
3205 */
3206int
3207xmlParserInputBufferRead(xmlParserInputBufferPtr in, int len) {
Daniel Veillard97bf4d02003-10-08 18:58:28 +00003208 if ((in == NULL) || (in->error)) return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00003209 if (in->readcallback != NULL)
3210 return(xmlParserInputBufferGrow(in, len));
Daniel Veillard53350552003-09-18 13:35:51 +00003211 else if ((in->buffer != NULL) &&
3212 (in->buffer->alloc == XML_BUFFER_ALLOC_IMMUTABLE))
3213 return(0);
Owen Taylor3473f882001-02-23 17:55:21 +00003214 else
3215 return(-1);
3216}
3217
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003218#ifdef LIBXML_OUTPUT_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00003219/**
3220 * xmlOutputBufferWrite:
3221 * @out: a buffered parser output
3222 * @len: the size in bytes of the array.
3223 * @buf: an char array
3224 *
3225 * Write the content of the array in the output I/O buffer
3226 * This routine handle the I18N transcoding from internal UTF-8
3227 * The buffer is lossless, i.e. will store in case of partial
3228 * or delayed writes.
3229 *
3230 * Returns the number of chars immediately written, or -1
3231 * in case of error.
3232 */
3233int
3234xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) {
3235 int nbchars = 0; /* number of chars to output to I/O */
3236 int ret; /* return from function call */
3237 int written = 0; /* number of char written to I/O so far */
3238 int chunk; /* number of byte curreent processed from buf */
3239
Daniel Veillard97bf4d02003-10-08 18:58:28 +00003240 if ((out == NULL) || (out->error)) return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00003241 if (len < 0) return(0);
Daniel Veillard97bf4d02003-10-08 18:58:28 +00003242 if (out->error) return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00003243
3244 do {
3245 chunk = len;
3246 if (chunk > 4 * MINLEN)
3247 chunk = 4 * MINLEN;
3248
3249 /*
3250 * first handle encoding stuff.
3251 */
3252 if (out->encoder != NULL) {
3253 /*
3254 * Store the data in the incoming raw buffer
3255 */
3256 if (out->conv == NULL) {
3257 out->conv = xmlBufferCreate();
3258 }
William M. Bracka3215c72004-07-31 16:24:01 +00003259 ret = xmlBufferAdd(out->buffer, (const xmlChar *) buf, chunk);
3260 if (ret != 0)
3261 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00003262
3263 if ((out->buffer->use < MINLEN) && (chunk == len))
3264 goto done;
3265
3266 /*
3267 * convert as much as possible to the parser reading buffer.
3268 */
3269 ret = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer);
Daniel Veillard809faa52003-02-10 15:43:53 +00003270 if ((ret < 0) && (ret != -3)) {
Daniel Veillard05d987b2003-10-08 11:54:57 +00003271 xmlIOErr(XML_IO_ENCODER, NULL);
Daniel Veillard97bf4d02003-10-08 18:58:28 +00003272 out->error = XML_IO_ENCODER;
Owen Taylor3473f882001-02-23 17:55:21 +00003273 return(-1);
3274 }
3275 nbchars = out->conv->use;
3276 } else {
William M. Bracka3215c72004-07-31 16:24:01 +00003277 ret = xmlBufferAdd(out->buffer, (const xmlChar *) buf, chunk);
3278 if (ret != 0)
3279 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00003280 nbchars = out->buffer->use;
3281 }
3282 buf += chunk;
3283 len -= chunk;
3284
3285 if ((nbchars < MINLEN) && (len <= 0))
3286 goto done;
3287
3288 if (out->writecallback) {
3289 /*
3290 * second write the stuff to the I/O channel
3291 */
3292 if (out->encoder != NULL) {
Hans Breuer2ad41ca2009-08-11 17:51:22 +02003293 ret = out->writecallback(out->context,
Owen Taylor3473f882001-02-23 17:55:21 +00003294 (const char *)out->conv->content, nbchars);
3295 if (ret >= 0)
Daniel Veillardedddff92001-05-02 10:58:52 +00003296 xmlBufferShrink(out->conv, ret);
Owen Taylor3473f882001-02-23 17:55:21 +00003297 } else {
Hans Breuer2ad41ca2009-08-11 17:51:22 +02003298 ret = out->writecallback(out->context,
Owen Taylor3473f882001-02-23 17:55:21 +00003299 (const char *)out->buffer->content, nbchars);
3300 if (ret >= 0)
Daniel Veillardedddff92001-05-02 10:58:52 +00003301 xmlBufferShrink(out->buffer, ret);
Owen Taylor3473f882001-02-23 17:55:21 +00003302 }
3303 if (ret < 0) {
Daniel Veillard05d987b2003-10-08 11:54:57 +00003304 xmlIOErr(XML_IO_WRITE, NULL);
Daniel Veillard97bf4d02003-10-08 18:58:28 +00003305 out->error = XML_IO_WRITE;
Owen Taylor3473f882001-02-23 17:55:21 +00003306 return(ret);
3307 }
3308 out->written += ret;
3309 }
3310 written += nbchars;
3311 } while (len > 0);
3312
3313done:
3314#ifdef DEBUG_INPUT
3315 xmlGenericError(xmlGenericErrorContext,
3316 "I/O: wrote %d chars\n", written);
3317#endif
3318 return(written);
3319}
3320
3321/**
Daniel Veillard5d1a4d82004-05-13 14:31:25 +00003322 * xmlEscapeContent:
3323 * @out: a pointer to an array of bytes to store the result
3324 * @outlen: the length of @out
3325 * @in: a pointer to an array of unescaped UTF-8 bytes
3326 * @inlen: the length of @in
3327 *
3328 * Take a block of UTF-8 chars in and escape them.
3329 * Returns 0 if success, or -1 otherwise
3330 * The value of @inlen after return is the number of octets consumed
3331 * if the return value is positive, else unpredictable.
3332 * The value of @outlen after return is the number of octets consumed.
3333 */
3334static int
3335xmlEscapeContent(unsigned char* out, int *outlen,
3336 const xmlChar* in, int *inlen) {
3337 unsigned char* outstart = out;
3338 const unsigned char* base = in;
3339 unsigned char* outend = out + *outlen;
3340 const unsigned char* inend;
3341
3342 inend = in + (*inlen);
Hans Breuer2ad41ca2009-08-11 17:51:22 +02003343
Daniel Veillard5d1a4d82004-05-13 14:31:25 +00003344 while ((in < inend) && (out < outend)) {
Hans Breuer2ad41ca2009-08-11 17:51:22 +02003345 if (*in == '<') {
Daniel Veillard5d1a4d82004-05-13 14:31:25 +00003346 if (outend - out < 4) break;
3347 *out++ = '&';
3348 *out++ = 'l';
3349 *out++ = 't';
3350 *out++ = ';';
3351 } else if (*in == '>') {
3352 if (outend - out < 4) break;
3353 *out++ = '&';
3354 *out++ = 'g';
3355 *out++ = 't';
3356 *out++ = ';';
3357 } else if (*in == '&') {
3358 if (outend - out < 5) break;
3359 *out++ = '&';
3360 *out++ = 'a';
3361 *out++ = 'm';
3362 *out++ = 'p';
3363 *out++ = ';';
3364 } else if (*in == '\r') {
3365 if (outend - out < 5) break;
3366 *out++ = '&';
3367 *out++ = '#';
3368 *out++ = '1';
3369 *out++ = '3';
3370 *out++ = ';';
3371 } else {
3372 *out++ = (unsigned char) *in;
3373 }
3374 ++in;
Hans Breuer2ad41ca2009-08-11 17:51:22 +02003375 }
Daniel Veillard5d1a4d82004-05-13 14:31:25 +00003376 *outlen = out - outstart;
3377 *inlen = in - base;
3378 return(0);
3379}
3380
3381/**
3382 * xmlOutputBufferWriteEscape:
3383 * @out: a buffered parser output
3384 * @str: a zero terminated UTF-8 string
Daniel Veillardee8960b2004-05-14 03:25:14 +00003385 * @escaping: an optional escaping function (or NULL)
Daniel Veillard5d1a4d82004-05-13 14:31:25 +00003386 *
3387 * Write the content of the string in the output I/O buffer
3388 * This routine escapes the caracters and then handle the I18N
3389 * transcoding from internal UTF-8
3390 * The buffer is lossless, i.e. will store in case of partial
3391 * or delayed writes.
3392 *
3393 * Returns the number of chars immediately written, or -1
3394 * in case of error.
3395 */
3396int
Daniel Veillardee8960b2004-05-14 03:25:14 +00003397xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str,
3398 xmlCharEncodingOutputFunc escaping) {
Daniel Veillard5d1a4d82004-05-13 14:31:25 +00003399 int nbchars = 0; /* number of chars to output to I/O */
3400 int ret; /* return from function call */
3401 int written = 0; /* number of char written to I/O so far */
Daniel Veillard71b95632004-08-31 12:15:36 +00003402 int oldwritten=0;/* loop guard */
Daniel Veillard5d1a4d82004-05-13 14:31:25 +00003403 int chunk; /* number of byte currently processed from str */
3404 int len; /* number of bytes in str */
3405 int cons; /* byte from str consumed */
3406
Daniel Veillardce244ad2004-11-05 10:03:46 +00003407 if ((out == NULL) || (out->error) || (str == NULL) ||
3408 (out->buffer == NULL) ||
3409 (out->buffer->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) return(-1);
Daniel Veillardee8960b2004-05-14 03:25:14 +00003410 len = strlen((const char *)str);
Daniel Veillard5d1a4d82004-05-13 14:31:25 +00003411 if (len < 0) return(0);
3412 if (out->error) return(-1);
Daniel Veillardee8960b2004-05-14 03:25:14 +00003413 if (escaping == NULL) escaping = xmlEscapeContent;
Daniel Veillard5d1a4d82004-05-13 14:31:25 +00003414
3415 do {
Daniel Veillard71b95632004-08-31 12:15:36 +00003416 oldwritten = written;
3417
Daniel Veillard5d1a4d82004-05-13 14:31:25 +00003418 /*
3419 * how many bytes to consume and how many bytes to store.
3420 */
3421 cons = len;
3422 chunk = (out->buffer->size - out->buffer->use) - 1;
3423
Daniel Veillardc4ba8a42008-02-16 10:08:14 +00003424 /*
3425 * make sure we have enough room to save first, if this is
3426 * not the case force a flush, but make sure we stay in the loop
3427 */
3428 if (chunk < 40) {
Daniel Veillarde83e93e2008-08-30 12:52:26 +00003429 if (xmlBufferGrow(out->buffer, out->buffer->size + 100) < 0)
3430 return(-1);
3431 oldwritten = -1;
3432 continue;
Daniel Veillardc4ba8a42008-02-16 10:08:14 +00003433 }
3434
Daniel Veillard5d1a4d82004-05-13 14:31:25 +00003435 /*
3436 * first handle encoding stuff.
3437 */
3438 if (out->encoder != NULL) {
3439 /*
3440 * Store the data in the incoming raw buffer
3441 */
3442 if (out->conv == NULL) {
3443 out->conv = xmlBufferCreate();
3444 }
Daniel Veillardee8960b2004-05-14 03:25:14 +00003445 ret = escaping(out->buffer->content + out->buffer->use ,
3446 &chunk, str, &cons);
William M. Brack66e40b12004-11-26 15:45:19 +00003447 if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */
Daniel Veillard5d1a4d82004-05-13 14:31:25 +00003448 return(-1);
3449 out->buffer->use += chunk;
3450 out->buffer->content[out->buffer->use] = 0;
3451
3452 if ((out->buffer->use < MINLEN) && (cons == len))
3453 goto done;
3454
3455 /*
3456 * convert as much as possible to the output buffer.
3457 */
3458 ret = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer);
3459 if ((ret < 0) && (ret != -3)) {
3460 xmlIOErr(XML_IO_ENCODER, NULL);
3461 out->error = XML_IO_ENCODER;
3462 return(-1);
3463 }
3464 nbchars = out->conv->use;
3465 } else {
Daniel Veillardee8960b2004-05-14 03:25:14 +00003466 ret = escaping(out->buffer->content + out->buffer->use ,
3467 &chunk, str, &cons);
William M. Brack66e40b12004-11-26 15:45:19 +00003468 if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */
Daniel Veillard5d1a4d82004-05-13 14:31:25 +00003469 return(-1);
3470 out->buffer->use += chunk;
3471 out->buffer->content[out->buffer->use] = 0;
3472 nbchars = out->buffer->use;
3473 }
3474 str += cons;
3475 len -= cons;
3476
3477 if ((nbchars < MINLEN) && (len <= 0))
3478 goto done;
3479
3480 if (out->writecallback) {
3481 /*
3482 * second write the stuff to the I/O channel
3483 */
3484 if (out->encoder != NULL) {
Hans Breuer2ad41ca2009-08-11 17:51:22 +02003485 ret = out->writecallback(out->context,
Daniel Veillard5d1a4d82004-05-13 14:31:25 +00003486 (const char *)out->conv->content, nbchars);
3487 if (ret >= 0)
3488 xmlBufferShrink(out->conv, ret);
3489 } else {
Hans Breuer2ad41ca2009-08-11 17:51:22 +02003490 ret = out->writecallback(out->context,
Daniel Veillard5d1a4d82004-05-13 14:31:25 +00003491 (const char *)out->buffer->content, nbchars);
3492 if (ret >= 0)
3493 xmlBufferShrink(out->buffer, ret);
3494 }
3495 if (ret < 0) {
3496 xmlIOErr(XML_IO_WRITE, NULL);
3497 out->error = XML_IO_WRITE;
3498 return(ret);
3499 }
3500 out->written += ret;
Daniel Veillard83a75e02004-05-14 21:50:42 +00003501 } else if (out->buffer->size - out->buffer->use < MINLEN) {
3502 xmlBufferResize(out->buffer, out->buffer->size + MINLEN);
Daniel Veillard5d1a4d82004-05-13 14:31:25 +00003503 }
3504 written += nbchars;
Daniel Veillard71b95632004-08-31 12:15:36 +00003505 } while ((len > 0) && (oldwritten != written));
Daniel Veillard5d1a4d82004-05-13 14:31:25 +00003506
3507done:
3508#ifdef DEBUG_INPUT
3509 xmlGenericError(xmlGenericErrorContext,
3510 "I/O: wrote %d chars\n", written);
3511#endif
3512 return(written);
3513}
3514
3515/**
Owen Taylor3473f882001-02-23 17:55:21 +00003516 * xmlOutputBufferWriteString:
3517 * @out: a buffered parser output
3518 * @str: a zero terminated C string
3519 *
3520 * Write the content of the string in the output I/O buffer
3521 * This routine handle the I18N transcoding from internal UTF-8
3522 * The buffer is lossless, i.e. will store in case of partial
3523 * or delayed writes.
3524 *
3525 * Returns the number of chars immediately written, or -1
3526 * in case of error.
3527 */
3528int
3529xmlOutputBufferWriteString(xmlOutputBufferPtr out, const char *str) {
3530 int len;
Hans Breuer2ad41ca2009-08-11 17:51:22 +02003531
Daniel Veillard97bf4d02003-10-08 18:58:28 +00003532 if ((out == NULL) || (out->error)) return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00003533 if (str == NULL)
3534 return(-1);
3535 len = strlen(str);
3536
3537 if (len > 0)
3538 return(xmlOutputBufferWrite(out, len, str));
3539 return(len);
3540}
3541
3542/**
3543 * xmlOutputBufferFlush:
3544 * @out: a buffered output
3545 *
3546 * flushes the output I/O channel
3547 *
3548 * Returns the number of byte written or -1 in case of error.
3549 */
3550int
3551xmlOutputBufferFlush(xmlOutputBufferPtr out) {
3552 int nbchars = 0, ret = 0;
3553
Daniel Veillard97bf4d02003-10-08 18:58:28 +00003554 if ((out == NULL) || (out->error)) return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00003555 /*
3556 * first handle encoding stuff.
3557 */
3558 if ((out->conv != NULL) && (out->encoder != NULL)) {
3559 /*
3560 * convert as much as possible to the parser reading buffer.
3561 */
3562 nbchars = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer);
3563 if (nbchars < 0) {
Daniel Veillard05d987b2003-10-08 11:54:57 +00003564 xmlIOErr(XML_IO_ENCODER, NULL);
Daniel Veillard97bf4d02003-10-08 18:58:28 +00003565 out->error = XML_IO_ENCODER;
Owen Taylor3473f882001-02-23 17:55:21 +00003566 return(-1);
3567 }
3568 }
3569
3570 /*
3571 * second flush the stuff to the I/O channel
3572 */
3573 if ((out->conv != NULL) && (out->encoder != NULL) &&
3574 (out->writecallback != NULL)) {
3575 ret = out->writecallback(out->context,
3576 (const char *)out->conv->content, out->conv->use);
3577 if (ret >= 0)
3578 xmlBufferShrink(out->conv, ret);
3579 } else if (out->writecallback != NULL) {
3580 ret = out->writecallback(out->context,
3581 (const char *)out->buffer->content, out->buffer->use);
3582 if (ret >= 0)
3583 xmlBufferShrink(out->buffer, ret);
3584 }
3585 if (ret < 0) {
Daniel Veillard05d987b2003-10-08 11:54:57 +00003586 xmlIOErr(XML_IO_FLUSH, NULL);
Daniel Veillard97bf4d02003-10-08 18:58:28 +00003587 out->error = XML_IO_FLUSH;
Owen Taylor3473f882001-02-23 17:55:21 +00003588 return(ret);
3589 }
3590 out->written += ret;
3591
3592#ifdef DEBUG_INPUT
3593 xmlGenericError(xmlGenericErrorContext,
3594 "I/O: flushed %d chars\n", ret);
3595#endif
3596 return(ret);
3597}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003598#endif /* LIBXML_OUTPUT_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00003599
Daniel Veillard5e2dace2001-07-18 19:30:27 +00003600/**
Owen Taylor3473f882001-02-23 17:55:21 +00003601 * xmlParserGetDirectory:
3602 * @filename: the path to a file
3603 *
3604 * lookup the directory for that file
3605 *
3606 * Returns a new allocated string containing the directory, or NULL.
3607 */
3608char *
3609xmlParserGetDirectory(const char *filename) {
3610 char *ret = NULL;
3611 char dir[1024];
3612 char *cur;
Owen Taylor3473f882001-02-23 17:55:21 +00003613
Igor Zlatkovic9181cc02002-09-29 17:51:06 +00003614#ifdef _WIN32_WCE /* easy way by now ... wince does not have dirs! */
3615 return NULL;
3616#endif
3617
Owen Taylor3473f882001-02-23 17:55:21 +00003618 if (xmlInputCallbackInitialized == 0)
3619 xmlRegisterDefaultInputCallbacks();
3620
3621 if (filename == NULL) return(NULL);
Rob Richardsf779da32007-08-14 09:41:21 +00003622
Daniel Veillard3c5ed912002-01-08 10:36:16 +00003623#if defined(WIN32) && !defined(__CYGWIN__)
Rob Richardsf779da32007-08-14 09:41:21 +00003624# define IS_XMLPGD_SEP(ch) ((ch=='/')||(ch=='\\'))
3625#else
3626# define IS_XMLPGD_SEP(ch) (ch=='/')
Owen Taylor3473f882001-02-23 17:55:21 +00003627#endif
3628
3629 strncpy(dir, filename, 1023);
3630 dir[1023] = 0;
3631 cur = &dir[strlen(dir)];
3632 while (cur > dir) {
Rob Richardsf779da32007-08-14 09:41:21 +00003633 if (IS_XMLPGD_SEP(*cur)) break;
Owen Taylor3473f882001-02-23 17:55:21 +00003634 cur --;
3635 }
Rob Richardsf779da32007-08-14 09:41:21 +00003636 if (IS_XMLPGD_SEP(*cur)) {
Owen Taylor3473f882001-02-23 17:55:21 +00003637 if (cur == dir) dir[1] = 0;
3638 else *cur = 0;
3639 ret = xmlMemStrdup(dir);
3640 } else {
3641 if (getcwd(dir, 1024) != NULL) {
3642 dir[1023] = 0;
3643 ret = xmlMemStrdup(dir);
3644 }
3645 }
3646 return(ret);
Rob Richardsf779da32007-08-14 09:41:21 +00003647#undef IS_XMLPGD_SEP
Owen Taylor3473f882001-02-23 17:55:21 +00003648}
3649
3650/****************************************************************
3651 * *
3652 * External entities loading *
3653 * *
3654 ****************************************************************/
3655
Daniel Veillarda840b692003-10-19 13:35:37 +00003656/**
3657 * xmlCheckHTTPInput:
3658 * @ctxt: an XML parser context
3659 * @ret: an XML parser input
3660 *
3661 * Check an input in case it was created from an HTTP stream, in that
3662 * case it will handle encoding and update of the base URL in case of
3663 * redirection. It also checks for HTTP errors in which case the input
3664 * is cleanly freed up and an appropriate error is raised in context
3665 *
3666 * Returns the input or NULL in case of HTTP error.
3667 */
3668xmlParserInputPtr
3669xmlCheckHTTPInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr ret) {
3670#ifdef LIBXML_HTTP_ENABLED
3671 if ((ret != NULL) && (ret->buf != NULL) &&
3672 (ret->buf->readcallback == xmlIOHTTPRead) &&
3673 (ret->buf->context != NULL)) {
3674 const char *encoding;
3675 const char *redir;
3676 const char *mime;
3677 int code;
3678
3679 code = xmlNanoHTTPReturnCode(ret->buf->context);
3680 if (code >= 400) {
3681 /* fatal error */
3682 if (ret->filename != NULL)
Daniel Veillarde8039df2003-10-27 11:25:13 +00003683 __xmlLoaderErr(ctxt, "failed to load HTTP resource \"%s\"\n",
Daniel Veillarda840b692003-10-19 13:35:37 +00003684 (const char *) ret->filename);
3685 else
Daniel Veillarde8039df2003-10-27 11:25:13 +00003686 __xmlLoaderErr(ctxt, "failed to load HTTP resource\n", NULL);
Daniel Veillarda840b692003-10-19 13:35:37 +00003687 xmlFreeInputStream(ret);
3688 ret = NULL;
3689 } else {
3690
3691 mime = xmlNanoHTTPMimeType(ret->buf->context);
3692 if ((xmlStrstr(BAD_CAST mime, BAD_CAST "/xml")) ||
3693 (xmlStrstr(BAD_CAST mime, BAD_CAST "+xml"))) {
3694 encoding = xmlNanoHTTPEncoding(ret->buf->context);
3695 if (encoding != NULL) {
3696 xmlCharEncodingHandlerPtr handler;
3697
3698 handler = xmlFindCharEncodingHandler(encoding);
3699 if (handler != NULL) {
3700 xmlSwitchInputEncoding(ctxt, ret, handler);
3701 } else {
3702 __xmlErrEncoding(ctxt, XML_ERR_UNKNOWN_ENCODING,
3703 "Unknown encoding %s",
3704 BAD_CAST encoding, NULL);
3705 }
3706 if (ret->encoding == NULL)
3707 ret->encoding = xmlStrdup(BAD_CAST encoding);
3708 }
3709#if 0
3710 } else if (xmlStrstr(BAD_CAST mime, BAD_CAST "html")) {
3711#endif
3712 }
3713 redir = xmlNanoHTTPRedir(ret->buf->context);
3714 if (redir != NULL) {
3715 if (ret->filename != NULL)
3716 xmlFree((xmlChar *) ret->filename);
3717 if (ret->directory != NULL) {
3718 xmlFree((xmlChar *) ret->directory);
3719 ret->directory = NULL;
3720 }
3721 ret->filename =
3722 (char *) xmlStrdup((const xmlChar *) redir);
3723 }
3724 }
3725 }
3726#endif
3727 return(ret);
3728}
3729
Daniel Veillarde5a3f372006-08-30 13:11:36 +00003730static int xmlNoNetExists(const char *URL) {
Daniel Veillard6990bf32001-08-23 21:17:48 +00003731 const char *path;
3732
3733 if (URL == NULL)
3734 return(0);
3735
Daniel Veillardf4862f02002-09-10 11:13:43 +00003736 if (!xmlStrncasecmp(BAD_CAST URL, BAD_CAST "file://localhost/", 17))
Daniel Veillard1997c3e2003-07-05 20:43:43 +00003737#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
Daniel Veillardf4862f02002-09-10 11:13:43 +00003738 path = &URL[17];
3739#else
Daniel Veillard6990bf32001-08-23 21:17:48 +00003740 path = &URL[16];
Daniel Veillardf4862f02002-09-10 11:13:43 +00003741#endif
Aleksey Sanin5aac8b82002-05-01 18:32:28 +00003742 else if (!xmlStrncasecmp(BAD_CAST URL, BAD_CAST "file:///", 8)) {
Daniel Veillard1997c3e2003-07-05 20:43:43 +00003743#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
Daniel Veillard6990bf32001-08-23 21:17:48 +00003744 path = &URL[8];
3745#else
3746 path = &URL[7];
3747#endif
Hans Breuer2ad41ca2009-08-11 17:51:22 +02003748 } else
Daniel Veillard6990bf32001-08-23 21:17:48 +00003749 path = URL;
Hans Breuer2ad41ca2009-08-11 17:51:22 +02003750
Daniel Veillarde5a3f372006-08-30 13:11:36 +00003751 return xmlCheckFilename(path);
Daniel Veillard6990bf32001-08-23 21:17:48 +00003752}
Daniel Veillard6990bf32001-08-23 21:17:48 +00003753
Daniel Veillardad4e2962006-09-21 08:36:38 +00003754#ifdef LIBXML_CATALOG_ENABLED
3755
3756/**
3757 * xmlResolveResourceFromCatalog:
3758 * @URL: the URL for the entity to load
3759 * @ID: the System ID for the entity to load
3760 * @ctxt: the context in which the entity is called or NULL
3761 *
3762 * Resolves the URL and ID against the appropriate catalog.
3763 * This function is used by xmlDefaultExternalEntityLoader and
3764 * xmlNoNetExternalEntityLoader.
3765 *
3766 * Returns a new allocated URL, or NULL.
3767 */
William M. Brack38d452a2007-05-22 16:00:06 +00003768static xmlChar *
Daniel Veillardad4e2962006-09-21 08:36:38 +00003769xmlResolveResourceFromCatalog(const char *URL, const char *ID,
3770 xmlParserCtxtPtr ctxt) {
3771 xmlChar *resource = NULL;
3772 xmlCatalogAllow pref;
3773
3774 /*
3775 * If the resource doesn't exists as a file,
3776 * try to load it from the resource pointed in the catalogs
3777 */
3778 pref = xmlCatalogGetDefaults();
3779
3780 if ((pref != XML_CATA_ALLOW_NONE) && (!xmlNoNetExists(URL))) {
3781 /*
3782 * Do a local lookup
3783 */
3784 if ((ctxt != NULL) && (ctxt->catalogs != NULL) &&
3785 ((pref == XML_CATA_ALLOW_ALL) ||
3786 (pref == XML_CATA_ALLOW_DOCUMENT))) {
3787 resource = xmlCatalogLocalResolve(ctxt->catalogs,
3788 (const xmlChar *)ID,
3789 (const xmlChar *)URL);
3790 }
3791 /*
3792 * Try a global lookup
3793 */
3794 if ((resource == NULL) &&
3795 ((pref == XML_CATA_ALLOW_ALL) ||
3796 (pref == XML_CATA_ALLOW_GLOBAL))) {
3797 resource = xmlCatalogResolve((const xmlChar *)ID,
3798 (const xmlChar *)URL);
3799 }
3800 if ((resource == NULL) && (URL != NULL))
3801 resource = xmlStrdup((const xmlChar *) URL);
3802
3803 /*
3804 * TODO: do an URI lookup on the reference
3805 */
3806 if ((resource != NULL) && (!xmlNoNetExists((const char *)resource))) {
3807 xmlChar *tmp = NULL;
3808
3809 if ((ctxt != NULL) && (ctxt->catalogs != NULL) &&
3810 ((pref == XML_CATA_ALLOW_ALL) ||
3811 (pref == XML_CATA_ALLOW_DOCUMENT))) {
3812 tmp = xmlCatalogLocalResolveURI(ctxt->catalogs, resource);
3813 }
3814 if ((tmp == NULL) &&
3815 ((pref == XML_CATA_ALLOW_ALL) ||
3816 (pref == XML_CATA_ALLOW_GLOBAL))) {
3817 tmp = xmlCatalogResolveURI(resource);
3818 }
3819
3820 if (tmp != NULL) {
3821 xmlFree(resource);
3822 resource = tmp;
3823 }
3824 }
3825 }
3826
3827 return resource;
3828}
3829
3830#endif
3831
Daniel Veillard5e2dace2001-07-18 19:30:27 +00003832/**
Owen Taylor3473f882001-02-23 17:55:21 +00003833 * xmlDefaultExternalEntityLoader:
3834 * @URL: the URL for the entity to load
3835 * @ID: the System ID for the entity to load
3836 * @ctxt: the context in which the entity is called or NULL
3837 *
3838 * By default we don't load external entitites, yet.
3839 *
3840 * Returns a new allocated xmlParserInputPtr, or NULL.
3841 */
Daniel Veillarda840b692003-10-19 13:35:37 +00003842static xmlParserInputPtr
Owen Taylor3473f882001-02-23 17:55:21 +00003843xmlDefaultExternalEntityLoader(const char *URL, const char *ID,
Daniel Veillarda840b692003-10-19 13:35:37 +00003844 xmlParserCtxtPtr ctxt)
3845{
Owen Taylor3473f882001-02-23 17:55:21 +00003846 xmlParserInputPtr ret = NULL;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003847 xmlChar *resource = NULL;
Daniel Veillarda840b692003-10-19 13:35:37 +00003848
Owen Taylor3473f882001-02-23 17:55:21 +00003849#ifdef DEBUG_EXTERNAL_ENTITIES
3850 xmlGenericError(xmlGenericErrorContext,
Daniel Veillarda840b692003-10-19 13:35:37 +00003851 "xmlDefaultExternalEntityLoader(%s, xxx)\n", URL);
Owen Taylor3473f882001-02-23 17:55:21 +00003852#endif
Daniel Veillard61b93382003-11-03 14:28:31 +00003853 if ((ctxt != NULL) && (ctxt->options & XML_PARSE_NONET)) {
3854 int options = ctxt->options;
3855
3856 ctxt->options -= XML_PARSE_NONET;
3857 ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
3858 ctxt->options = options;
3859 return(ret);
3860 }
Daniel Veillardad4e2962006-09-21 08:36:38 +00003861#ifdef LIBXML_CATALOG_ENABLED
3862 resource = xmlResolveResourceFromCatalog(URL, ID, ctxt);
Daniel Veillard7d6fd212001-05-10 15:34:11 +00003863#endif
3864
3865 if (resource == NULL)
Daniel Veillarda840b692003-10-19 13:35:37 +00003866 resource = (xmlChar *) URL;
Daniel Veillard7d6fd212001-05-10 15:34:11 +00003867
3868 if (resource == NULL) {
Daniel Veillarda840b692003-10-19 13:35:37 +00003869 if (ID == NULL)
3870 ID = "NULL";
Daniel Veillarde8039df2003-10-27 11:25:13 +00003871 __xmlLoaderErr(ctxt, "failed to load external entity \"%s\"\n", ID);
Daniel Veillarda840b692003-10-19 13:35:37 +00003872 return (NULL);
Owen Taylor3473f882001-02-23 17:55:21 +00003873 }
Daniel Veillarda840b692003-10-19 13:35:37 +00003874 ret = xmlNewInputFromFile(ctxt, (const char *) resource);
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003875 if ((resource != NULL) && (resource != (xmlChar *) URL))
Daniel Veillarda840b692003-10-19 13:35:37 +00003876 xmlFree(resource);
3877 return (ret);
Owen Taylor3473f882001-02-23 17:55:21 +00003878}
3879
3880static xmlExternalEntityLoader xmlCurrentExternalEntityLoader =
3881 xmlDefaultExternalEntityLoader;
3882
Daniel Veillard5e2dace2001-07-18 19:30:27 +00003883/**
Owen Taylor3473f882001-02-23 17:55:21 +00003884 * xmlSetExternalEntityLoader:
3885 * @f: the new entity resolver function
3886 *
3887 * Changes the defaultexternal entity resolver function for the application
3888 */
3889void
3890xmlSetExternalEntityLoader(xmlExternalEntityLoader f) {
3891 xmlCurrentExternalEntityLoader = f;
3892}
3893
Daniel Veillard5e2dace2001-07-18 19:30:27 +00003894/**
Owen Taylor3473f882001-02-23 17:55:21 +00003895 * xmlGetExternalEntityLoader:
3896 *
3897 * Get the default external entity resolver function for the application
3898 *
3899 * Returns the xmlExternalEntityLoader function pointer
3900 */
3901xmlExternalEntityLoader
3902xmlGetExternalEntityLoader(void) {
3903 return(xmlCurrentExternalEntityLoader);
3904}
3905
Daniel Veillard5e2dace2001-07-18 19:30:27 +00003906/**
Owen Taylor3473f882001-02-23 17:55:21 +00003907 * xmlLoadExternalEntity:
3908 * @URL: the URL for the entity to load
Daniel Veillard9f7b84b2001-08-23 15:31:19 +00003909 * @ID: the Public ID for the entity to load
Owen Taylor3473f882001-02-23 17:55:21 +00003910 * @ctxt: the context in which the entity is called or NULL
3911 *
3912 * Load an external entity, note that the use of this function for
3913 * unparsed entities may generate problems
Owen Taylor3473f882001-02-23 17:55:21 +00003914 *
3915 * Returns the xmlParserInputPtr or NULL
3916 */
3917xmlParserInputPtr
3918xmlLoadExternalEntity(const char *URL, const char *ID,
3919 xmlParserCtxtPtr ctxt) {
Daniel Veillarde5a3f372006-08-30 13:11:36 +00003920 if ((URL != NULL) && (xmlNoNetExists(URL) == 0)) {
Daniel Veillard4e9b1bc2003-06-09 10:30:33 +00003921 char *canonicFilename;
3922 xmlParserInputPtr ret;
3923
3924 canonicFilename = (char *) xmlCanonicPath((const xmlChar *) URL);
3925 if (canonicFilename == NULL) {
Daniel Veillard05d987b2003-10-08 11:54:57 +00003926 xmlIOErrMemory("building canonical path\n");
Daniel Veillard4e9b1bc2003-06-09 10:30:33 +00003927 return(NULL);
3928 }
3929
3930 ret = xmlCurrentExternalEntityLoader(canonicFilename, ID, ctxt);
3931 xmlFree(canonicFilename);
3932 return(ret);
3933 }
Owen Taylor3473f882001-02-23 17:55:21 +00003934 return(xmlCurrentExternalEntityLoader(URL, ID, ctxt));
3935}
3936
Daniel Veillard8bdb91d2001-10-31 17:52:43 +00003937/************************************************************************
Hans Breuer2ad41ca2009-08-11 17:51:22 +02003938 * *
3939 * Disabling Network access *
3940 * *
Daniel Veillard8bdb91d2001-10-31 17:52:43 +00003941 ************************************************************************/
3942
Daniel Veillard8bdb91d2001-10-31 17:52:43 +00003943/**
3944 * xmlNoNetExternalEntityLoader:
3945 * @URL: the URL for the entity to load
3946 * @ID: the System ID for the entity to load
3947 * @ctxt: the context in which the entity is called or NULL
3948 *
3949 * A specific entity loader disabling network accesses, though still
3950 * allowing local catalog accesses for resolution.
3951 *
3952 * Returns a new allocated xmlParserInputPtr, or NULL.
3953 */
3954xmlParserInputPtr
3955xmlNoNetExternalEntityLoader(const char *URL, const char *ID,
3956 xmlParserCtxtPtr ctxt) {
3957 xmlParserInputPtr input = NULL;
3958 xmlChar *resource = NULL;
3959
3960#ifdef LIBXML_CATALOG_ENABLED
Daniel Veillardad4e2962006-09-21 08:36:38 +00003961 resource = xmlResolveResourceFromCatalog(URL, ID, ctxt);
Daniel Veillard8bdb91d2001-10-31 17:52:43 +00003962#endif
Daniel Veillardad4e2962006-09-21 08:36:38 +00003963
Daniel Veillard8bdb91d2001-10-31 17:52:43 +00003964 if (resource == NULL)
3965 resource = (xmlChar *) URL;
3966
3967 if (resource != NULL) {
Aleksey Sanin5aac8b82002-05-01 18:32:28 +00003968 if ((!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "ftp://", 6)) ||
3969 (!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "http://", 7))) {
Daniel Veillard05d987b2003-10-08 11:54:57 +00003970 xmlIOErr(XML_IO_NETWORK_ATTEMPT, (const char *) resource);
Daniel Veillard8bdb91d2001-10-31 17:52:43 +00003971 if (resource != (xmlChar *) URL)
3972 xmlFree(resource);
3973 return(NULL);
3974 }
3975 }
3976 input = xmlDefaultExternalEntityLoader((const char *) resource, ID, ctxt);
3977 if (resource != (xmlChar *) URL)
3978 xmlFree(resource);
3979 return(input);
3980}
3981
Daniel Veillard5d4644e2005-04-01 13:11:58 +00003982#define bottom_xmlIO
3983#include "elfgcchack.h"