blob: aeee1abc64f2fbfa2db423f90079fc176d29da65 [file] [log] [blame]
Daniel Veillarde2d034d1999-07-27 19:52:06 +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 *
6 * Daniel.Veillard@w3.org
7 */
8
Daniel Veillard7f7d1111999-09-22 09:46:25 +00009#ifdef WIN32
Daniel Veillard3c558c31999-12-22 11:30:41 +000010#include "win32config.h"
Daniel Veillard7f7d1111999-09-22 09:46:25 +000011#else
Daniel Veillarde2d034d1999-07-27 19:52:06 +000012#include "config.h"
Daniel Veillard7f7d1111999-09-22 09:46:25 +000013#endif
Daniel Veillarde2d034d1999-07-27 19:52:06 +000014
Daniel Veillard7f7d1111999-09-22 09:46:25 +000015#include <stdio.h>
16#include <string.h>
17
18#ifdef HAVE_SYS_TYPES_H
Daniel Veillarde2d034d1999-07-27 19:52:06 +000019#include <sys/types.h>
Daniel Veillard7f7d1111999-09-22 09:46:25 +000020#endif
21#ifdef HAVE_SYS_STAT_H
Daniel Veillarde2d034d1999-07-27 19:52:06 +000022#include <sys/stat.h>
Daniel Veillard7f7d1111999-09-22 09:46:25 +000023#endif
24#ifdef HAVE_FCNTL_H
Daniel Veillarde2d034d1999-07-27 19:52:06 +000025#include <fcntl.h>
Daniel Veillard7f7d1111999-09-22 09:46:25 +000026#endif
Daniel Veillarde2d034d1999-07-27 19:52:06 +000027#ifdef HAVE_UNISTD_H
28#include <unistd.h>
29#endif
Daniel Veillard7f7d1111999-09-22 09:46:25 +000030#ifdef HAVE_STDLIB_H
31#include <stdlib.h>
32#endif
Daniel Veillarde2d034d1999-07-27 19:52:06 +000033#ifdef HAVE_ZLIB_H
34#include <zlib.h>
35#endif
36
Daniel Veillard6454aec1999-09-02 22:04:43 +000037#include "xmlmemory.h"
Daniel Veillardb96e6431999-08-29 21:02:19 +000038#include "parser.h"
Daniel Veillard686d6b62000-01-03 11:08:02 +000039#include "parserInternals.h"
Daniel Veillarde2d034d1999-07-27 19:52:06 +000040#include "xmlIO.h"
Daniel Veillard7f7d1111999-09-22 09:46:25 +000041#include "nanohttp.h"
Daniel Veillardda07c342000-01-25 18:31:22 +000042#include "nanoftp.h"
Daniel Veillarde2d034d1999-07-27 19:52:06 +000043
44/* #define DEBUG_INPUT */
45/* #define VERBOSE_FAILURE */
Daniel Veillardb96e6431999-08-29 21:02:19 +000046/* #define DEBUG_EXTERNAL_ENTITIES */
Daniel Veillarde2d034d1999-07-27 19:52:06 +000047
48#ifdef DEBUG_INPUT
49#define MINLEN 40
50#else
51#define MINLEN 4000
52#endif
53
54/**
55 * xmlAllocParserInputBuffer:
56 * @enc: the charset encoding if known
57 *
58 * Create a buffered parser input for progressive parsing
59 *
60 * Returns the new parser input or NULL
61 */
62xmlParserInputBufferPtr
63xmlAllocParserInputBuffer(xmlCharEncoding enc) {
64 xmlParserInputBufferPtr ret;
65
Daniel Veillard6454aec1999-09-02 22:04:43 +000066 ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
Daniel Veillarde2d034d1999-07-27 19:52:06 +000067 if (ret == NULL) {
68 fprintf(stderr, "xmlAllocParserInputBuffer : out of memory!\n");
69 return(NULL);
70 }
71 memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
72 ret->buffer = xmlBufferCreate();
Daniel Veillarddbfd6411999-12-28 16:35:14 +000073 if (ret->buffer == NULL) {
74 xmlFree(ret);
75 return(NULL);
76 }
77 ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT;
Daniel Veillarde2d034d1999-07-27 19:52:06 +000078 ret->encoder = xmlGetCharEncodingHandler(enc);
79 ret->fd = -1;
Daniel Veillardda07c342000-01-25 18:31:22 +000080 ret->httpIO = NULL;
81 ret->ftpIO = NULL;
Daniel Veillarde2d034d1999-07-27 19:52:06 +000082
83 return(ret);
84}
85
86/**
87 * xmlFreeParserInputBuffer:
88 * @in: a buffered parser input
89 *
90 * Free up the memory used by a buffered parser input
91 */
92void
93xmlFreeParserInputBuffer(xmlParserInputBufferPtr in) {
94 if (in->buffer != NULL) {
95 xmlBufferFree(in->buffer);
96 in->buffer = NULL;
97 }
98#ifdef HAVE_ZLIB_H
99 if (in->gzfile != NULL)
100 gzclose(in->gzfile);
101#endif
Daniel Veillardda07c342000-01-25 18:31:22 +0000102 if (in->httpIO != NULL)
103 xmlNanoHTTPClose(in->httpIO);
104 if (in->ftpIO != NULL)
105 xmlNanoFTPClose(in->ftpIO);
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000106 if (in->fd >= 0)
107 close(in->fd);
108 memset(in, 0xbe, (size_t) sizeof(xmlParserInputBuffer));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000109 xmlFree(in);
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000110}
111
112/**
113 * xmlParserInputBufferCreateFilename:
114 * @filename: a C string containing the filename
115 * @enc: the charset encoding if known
116 *
117 * Create a buffered parser input for the progressive parsing of a file
118 * If filename is "-' then we use stdin as the input.
119 * Automatic support for ZLIB/Compress compressed document is provided
120 * by default if found at compile-time.
121 *
122 * Returns the new parser input or NULL
123 */
124xmlParserInputBufferPtr
125xmlParserInputBufferCreateFilename(const char *filename, xmlCharEncoding enc) {
126 xmlParserInputBufferPtr ret;
127#ifdef HAVE_ZLIB_H
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000128 gzFile input = 0;
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000129#else
130 int input = -1;
131#endif
Daniel Veillardda07c342000-01-25 18:31:22 +0000132 void *httpIO = NULL;
133 void *ftpIO = NULL;
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000134
135 if (filename == NULL) return(NULL);
136
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000137 if (!strncmp(filename, "http://", 7)) {
Daniel Veillardda07c342000-01-25 18:31:22 +0000138 httpIO = xmlNanoHTTPOpen(filename, NULL);
139 if (httpIO == NULL) {
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000140#ifdef VERBOSE_FAILURE
141 fprintf (stderr, "Cannot read URL %s\n", filename);
142 perror ("xmlNanoHTTPOpen failed");
143#endif
144 return(NULL);
145 }
Daniel Veillardda07c342000-01-25 18:31:22 +0000146 } else if (!strncmp(filename, "ftp://", 6)) {
147 ftpIO = xmlNanoFTPOpen(filename);
148 if (ftpIO == NULL) {
149#ifdef VERBOSE_FAILURE
150 fprintf (stderr, "Cannot read URL %s\n", filename);
151 perror ("xmlNanoFTPOpen failed");
152#endif
153 return(NULL);
154 }
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000155 } else if (!strcmp(filename, "-")) {
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000156#ifdef HAVE_ZLIB_H
157 input = gzdopen (fileno(stdin), "r");
158 if (input == NULL) {
159#ifdef VERBOSE_FAILURE
160 fprintf (stderr, "Cannot read from stdin\n");
161 perror ("gzdopen failed");
162#endif
163 return(NULL);
164 }
165#else
166#ifdef WIN32
167 input = -1;
168#else
169 input = fileno(stdin);
170#endif
171 if (input < 0) {
172#ifdef VERBOSE_FAILURE
173 fprintf (stderr, "Cannot read from stdin\n");
174 perror ("open failed");
175#endif
176 return(NULL);
177 }
178#endif
179 } else {
180#ifdef HAVE_ZLIB_H
181 input = gzopen (filename, "r");
182 if (input == NULL) {
183#ifdef VERBOSE_FAILURE
184 fprintf (stderr, "Cannot read file %s :\n", filename);
185 perror ("gzopen failed");
186#endif
187 return(NULL);
188 }
189#else
190#ifdef WIN32
191 input = _open (filename, O_RDONLY | _O_BINARY);
192#else
193 input = open (filename, O_RDONLY);
194#endif
195 if (input < 0) {
196#ifdef VERBOSE_FAILURE
197 fprintf (stderr, "Cannot read file %s :\n", filename);
198 perror ("open failed");
199#endif
200 return(NULL);
201 }
202#endif
203 }
204 /*
Daniel Veillardb96e6431999-08-29 21:02:19 +0000205 * TODO : get the 4 first bytes and decode the charset
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000206 * if enc == XML_CHAR_ENCODING_NONE
207 * plug some encoding conversion routines here. !!!
208 * enc = xmlDetectCharEncoding(buffer);
209 */
210
211 ret = xmlAllocParserInputBuffer(enc);
212 if (ret != NULL) {
213#ifdef HAVE_ZLIB_H
214 ret->gzfile = input;
215#else
216 ret->fd = input;
217#endif
Daniel Veillardda07c342000-01-25 18:31:22 +0000218 ret->httpIO = httpIO;
219 ret->ftpIO = ftpIO;
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000220 }
221 xmlParserInputBufferRead(ret, 4);
222
223 return(ret);
224}
225
226/**
227 * xmlParserInputBufferCreateFile:
228 * @file: a FILE*
229 * @enc: the charset encoding if known
230 *
231 * Create a buffered parser input for the progressive parsing of a FILE *
232 * buffered C I/O
233 *
234 * Returns the new parser input or NULL
235 */
236xmlParserInputBufferPtr
237xmlParserInputBufferCreateFile(FILE *file, xmlCharEncoding enc) {
238 xmlParserInputBufferPtr ret;
239
240 if (file == NULL) return(NULL);
241
242 ret = xmlAllocParserInputBuffer(enc);
243 if (ret != NULL)
244 ret->file = file;
245
246 return(ret);
247}
248
249/**
250 * xmlParserInputBufferCreateFd:
251 * @fd: a file descriptor number
252 * @enc: the charset encoding if known
253 *
254 * Create a buffered parser input for the progressive parsing for the input
255 * from a file descriptor
256 *
257 * Returns the new parser input or NULL
258 */
259xmlParserInputBufferPtr
260xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) {
261 xmlParserInputBufferPtr ret;
262
263 if (fd < 0) return(NULL);
264
265 ret = xmlAllocParserInputBuffer(enc);
266 if (ret != NULL)
267 ret->fd = fd;
268
269 return(ret);
270}
271
272/**
Daniel Veillard7f858501999-11-17 17:32:38 +0000273 * xmlParserInputBufferPush:
274 * @in: a buffered parser input
275 * @buf: an char array
276 * @len: the size in bytes of the array.
277 *
278 * Push the content of the arry in the input buffer
279 * This routine handle the I18N transcoding to internal UTF-8
280 * This is used when operating the parser in progressive (push) mode.
281 *
282 * Returns the number of chars read and stored in the buffer, or -1
283 * in case of error.
284 */
285int
Daniel Veillarda819dac1999-11-24 18:04:22 +0000286xmlParserInputBufferPush(xmlParserInputBufferPtr in, int len, const char *buf) {
Daniel Veillard7f858501999-11-17 17:32:38 +0000287 int nbchars = 0;
288
289 if (len < 0) return(0);
290 if (in->encoder != NULL) {
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000291 xmlChar *buffer;
Daniel Veillard7f858501999-11-17 17:32:38 +0000292
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000293 buffer = (xmlChar *) xmlMalloc((len + 1) * 2 * sizeof(xmlChar));
294 if (buffer == NULL) {
Daniel Veillard7f858501999-11-17 17:32:38 +0000295 fprintf(stderr, "xmlParserInputBufferGrow : out of memory !\n");
296 xmlFree(buffer);
297 return(-1);
298 }
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000299 nbchars = in->encoder->input(buffer, (len + 1) * 2 * sizeof(xmlChar),
300 (xmlChar *) buf, len);
Daniel Veillard7f858501999-11-17 17:32:38 +0000301 /*
302 * TODO : we really need to have something atomic or the
303 * encoder must report the number of bytes read
304 */
Daniel Veillard7f858501999-11-17 17:32:38 +0000305 buffer[nbchars] = 0;
306 xmlBufferAdd(in->buffer, (xmlChar *) buffer, nbchars);
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000307 xmlFree(buffer);
308 } else {
309 nbchars = len;
310 xmlBufferAdd(in->buffer, (xmlChar *) buf, nbchars);
Daniel Veillard7f858501999-11-17 17:32:38 +0000311 }
312#ifdef DEBUG_INPUT
313 fprintf(stderr, "I/O: pushed %d chars, buffer %d/%d\n",
314 nbchars, in->buffer->use, in->buffer->size);
315#endif
316 return(nbchars);
317}
318
319/**
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000320 * xmlParserInputBufferGrow:
321 * @in: a buffered parser input
322 * @len: indicative value of the amount of chars to read
323 *
324 * Grow up the content of the input buffer, the old data are preserved
325 * This routine handle the I18N transcoding to internal UTF-8
Daniel Veillard7f858501999-11-17 17:32:38 +0000326 * This routine is used when operating the parser in normal (pull) mode
Daniel Veillardb96e6431999-08-29 21:02:19 +0000327 * TODO: one should be able to remove one extra copy
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000328 *
329 * Returns the number of chars read and stored in the buffer, or -1
330 * in case of error.
331 */
332int
333xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
334 char *buffer = NULL;
335#ifdef HAVE_ZLIB_H
336 gzFile input = (gzFile) in->gzfile;
337#endif
338 int res = 0;
339 int nbchars = 0;
340 int buffree;
341
342 if ((len <= MINLEN) && (len != 4))
343 len = MINLEN;
344 buffree = in->buffer->size - in->buffer->use;
345 if (buffree <= 0) {
346 fprintf(stderr, "xmlParserInputBufferGrow : buffer full !\n");
347 return(0);
348 }
349 if (len > buffree)
350 len = buffree;
351
Daniel Veillard6454aec1999-09-02 22:04:43 +0000352 buffer = xmlMalloc((len + 1) * sizeof(char));
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000353 if (buffer == NULL) {
354 fprintf(stderr, "xmlParserInputBufferGrow : out of memory !\n");
355 return(-1);
356 }
Daniel Veillardda07c342000-01-25 18:31:22 +0000357 if (in->httpIO != NULL) {
358 res = xmlNanoHTTPRead(in->httpIO, &buffer[0], len);
359 } else if (in->ftpIO != NULL) {
360 res = xmlNanoFTPRead(in->ftpIO, &buffer[0], len);
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000361 } else if (in->file != NULL) {
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000362 res = fread(&buffer[0], 1, len, in->file);
363#ifdef HAVE_ZLIB_H
364 } else if (in->gzfile != NULL) {
365 res = gzread(input, &buffer[0], len);
366#endif
367 } else if (in->fd >= 0) {
368 res = read(in->fd, &buffer[0], len);
369 } else {
370 fprintf(stderr, "xmlParserInputBufferGrow : no input !\n");
Daniel Veillard6454aec1999-09-02 22:04:43 +0000371 xmlFree(buffer);
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000372 return(-1);
373 }
374 if (res == 0) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000375 xmlFree(buffer);
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000376 return(0);
377 }
378 if (res < 0) {
379 perror ("read error");
Daniel Veillard6454aec1999-09-02 22:04:43 +0000380 xmlFree(buffer);
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000381 return(-1);
382 }
383 if (in->encoder != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000384 xmlChar *buf;
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000385
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000386 buf = (xmlChar *) xmlMalloc((res + 1) * 2 * sizeof(xmlChar));
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000387 if (buf == NULL) {
388 fprintf(stderr, "xmlParserInputBufferGrow : out of memory !\n");
Daniel Veillard6454aec1999-09-02 22:04:43 +0000389 xmlFree(buffer);
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000390 return(-1);
391 }
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000392 nbchars = in->encoder->input(buf, (res + 1) * 2 * sizeof(xmlChar),
Daniel Veillardb96e6431999-08-29 21:02:19 +0000393 BAD_CAST buffer, res);
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000394 buf[nbchars] = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000395 xmlBufferAdd(in->buffer, (xmlChar *) buf, nbchars);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000396 xmlFree(buf);
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000397 } else {
398 nbchars = res;
399 buffer[nbchars] = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000400 xmlBufferAdd(in->buffer, (xmlChar *) buffer, nbchars);
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000401 }
402#ifdef DEBUG_INPUT
403 fprintf(stderr, "I/O: read %d chars, buffer %d/%d\n",
404 nbchars, in->buffer->use, in->buffer->size);
405#endif
Daniel Veillard6454aec1999-09-02 22:04:43 +0000406 xmlFree(buffer);
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000407 return(nbchars);
408}
409
410/**
411 * xmlParserInputBufferRead:
412 * @in: a buffered parser input
413 * @len: indicative value of the amount of chars to read
414 *
415 * Refresh the content of the input buffer, the old data are considered
416 * consumed
417 * This routine handle the I18N transcoding to internal UTF-8
418 *
419 * Returns the number of chars read and stored in the buffer, or -1
420 * in case of error.
421 */
422int
423xmlParserInputBufferRead(xmlParserInputBufferPtr in, int len) {
424 /* xmlBufferEmpty(in->buffer); */
Daniel Veillardda07c342000-01-25 18:31:22 +0000425 if ((in->httpIO != NULL) || (in->ftpIO != NULL) || (in->file != NULL) ||
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000426#ifdef HAVE_ZLIB_H
427 (in->gzfile != NULL) ||
428#endif
429 (in->fd >= 0))
430 return(xmlParserInputBufferGrow(in, len));
431 else
432 return(0);
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000433}
434
Daniel Veillardb05deb71999-08-10 19:04:08 +0000435/*
436 * xmlParserGetDirectory:
437 * @filename: the path to a file
438 *
439 * lookup the directory for that file
440 *
441 * Returns a new allocated string containing the directory, or NULL.
442 */
443char *
444xmlParserGetDirectory(const char *filename) {
445 char *ret = NULL;
446 char dir[1024];
447 char *cur;
448 char sep = '/';
449
450 if (filename == NULL) return(NULL);
451#ifdef WIN32
452 sep = '\\';
453#endif
454
455 strncpy(dir, filename, 1023);
456 dir[1023] = 0;
457 cur = &dir[strlen(dir)];
458 while (cur > dir) {
459 if (*cur == sep) break;
460 cur --;
461 }
462 if (*cur == sep) {
463 if (cur == dir) dir[1] = 0;
464 else *cur = 0;
Daniel Veillard6454aec1999-09-02 22:04:43 +0000465 ret = xmlMemStrdup(dir);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000466 } else {
467 if (getcwd(dir, 1024) != NULL) {
468 dir[1023] = 0;
Daniel Veillard6454aec1999-09-02 22:04:43 +0000469 ret = xmlMemStrdup(dir);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000470 }
471 }
472 return(ret);
473}
474
Daniel Veillardb96e6431999-08-29 21:02:19 +0000475/****************************************************************
476 * *
477 * External entities loading *
478 * *
479 ****************************************************************/
480
481/*
482 * xmlDefaultExternalEntityLoader:
483 * @URL: the URL for the entity to load
484 * @ID: the System ID for the entity to load
Daniel Veillard686d6b62000-01-03 11:08:02 +0000485 * @ctxt: the context in which the entity is called or NULL
Daniel Veillardb96e6431999-08-29 21:02:19 +0000486 *
487 * By default we don't load external entitites, yet.
Daniel Veillardb96e6431999-08-29 21:02:19 +0000488 *
489 * Returns a new allocated xmlParserInputPtr, or NULL.
490 */
491static
492xmlParserInputPtr
493xmlDefaultExternalEntityLoader(const char *URL, const char *ID,
Daniel Veillard686d6b62000-01-03 11:08:02 +0000494 xmlParserCtxtPtr ctxt) {
495 xmlParserInputPtr ret = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000496#ifdef DEBUG_EXTERNAL_ENTITIES
497 fprintf(stderr, "xmlDefaultExternalEntityLoader(%s, xxx)\n", URL);
498#endif
Daniel Veillard686d6b62000-01-03 11:08:02 +0000499 if (URL == NULL) {
500 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
501 ctxt->sax->warning(ctxt, "failed to load external entity \"%s\"\n",
502 ID);
503 return(NULL);
504 }
505 ret = xmlNewInputFromFile(ctxt, URL);
506 if (ret == NULL) {
507 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
508 ctxt->sax->warning(ctxt, "failed to load external entity \"%s\"\n",
509 URL);
510 }
511 return(ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000512}
513
514static xmlExternalEntityLoader xmlCurrentExternalEntityLoader =
515 xmlDefaultExternalEntityLoader;
516
517/*
518 * xmlSetExternalEntityLoader:
519 * @f: the new entity resolver function
520 *
521 * Changes the defaultexternal entity resolver function for the application
522 */
523void
524xmlSetExternalEntityLoader(xmlExternalEntityLoader f) {
525 xmlCurrentExternalEntityLoader = f;
526}
527
528/*
529 * xmlGetExternalEntityLoader:
530 *
531 * Get the default external entity resolver function for the application
532 *
533 * Returns the xmlExternalEntityLoader function pointer
534 */
535xmlExternalEntityLoader
536xmlGetExternalEntityLoader(void) {
537 return(xmlCurrentExternalEntityLoader);
538}
539
540/*
541 * xmlLoadExternalEntity:
542 * @URL: the URL for the entity to load
543 * @ID: the System ID for the entity to load
Daniel Veillard686d6b62000-01-03 11:08:02 +0000544 * @ctxt: the context in which the entity is called or NULL
Daniel Veillardb96e6431999-08-29 21:02:19 +0000545 *
546 * Load an external entity, note that the use of this function for
547 * unparsed entities may generate problems
548 * TODO: a more generic External entitiy API must be designed
549 *
550 * Returns the xmlParserInputPtr or NULL
551 */
552xmlParserInputPtr
553xmlLoadExternalEntity(const char *URL, const char *ID,
Daniel Veillard686d6b62000-01-03 11:08:02 +0000554 xmlParserCtxtPtr ctxt) {
555 return(xmlCurrentExternalEntityLoader(URL, ID, ctxt));
Daniel Veillardb96e6431999-08-29 21:02:19 +0000556}
557