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