Home | History | Annotate | Download | only in xmlwf
      1 /* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
      2    See the file COPYING for copying permission.
      3 */
      4 
      5 #include <stdio.h>
      6 #include <stdlib.h>
      7 #include <stddef.h>
      8 #include <string.h>
      9 #include <fcntl.h>
     10 
     11 #ifdef COMPILED_FROM_DSP
     12 #include "winconfig.h"
     13 #elif defined(MACOS_CLASSIC)
     14 #include "macconfig.h"
     15 #elif defined(__amigaos__)
     16 #include "amigaconfig.h"
     17 #elif defined(__WATCOMC__)
     18 #include "watcomconfig.h"
     19 #elif defined(HAVE_EXPAT_CONFIG_H)
     20 #include <expat_config.h>
     21 #endif /* ndef COMPILED_FROM_DSP */
     22 
     23 #include "expat.h"
     24 #include "xmlfile.h"
     25 #include "xmltchar.h"
     26 #include "filemap.h"
     27 
     28 #if (defined(_MSC_VER) || (defined(__WATCOMC__) && !defined(__LINUX__)))
     29 #include <io.h>
     30 #endif
     31 
     32 #if defined(__amigaos__) && defined(__USE_INLINE__)
     33 #include <proto/expat.h>
     34 #endif
     35 
     36 #ifdef HAVE_UNISTD_H
     37 #include <unistd.h>
     38 #endif
     39 
     40 #ifndef O_BINARY
     41 #ifdef _O_BINARY
     42 #define O_BINARY _O_BINARY
     43 #else
     44 #define O_BINARY 0
     45 #endif
     46 #endif
     47 
     48 #ifdef _DEBUG
     49 #define READ_SIZE 16
     50 #else
     51 #define READ_SIZE (1024*8)
     52 #endif
     53 
     54 
     55 typedef struct {
     56   XML_Parser parser;
     57   int *retPtr;
     58 } PROCESS_ARGS;
     59 
     60 static void
     61 reportError(XML_Parser parser, const XML_Char *filename)
     62 {
     63   enum XML_Error code = XML_GetErrorCode(parser);
     64   const XML_Char *message = XML_ErrorString(code);
     65   if (message)
     66     ftprintf(stdout, T("%s:%" XML_FMT_INT_MOD "u:%" XML_FMT_INT_MOD "u: %s\n"),
     67              filename,
     68              XML_GetErrorLineNumber(parser),
     69              XML_GetErrorColumnNumber(parser),
     70              message);
     71   else
     72     ftprintf(stderr, T("%s: (unknown message %d)\n"), filename, code);
     73 }
     74 
     75 /* This implementation will give problems on files larger than INT_MAX. */
     76 static void
     77 processFile(const void *data, size_t size,
     78             const XML_Char *filename, void *args)
     79 {
     80   XML_Parser parser = ((PROCESS_ARGS *)args)->parser;
     81   int *retPtr = ((PROCESS_ARGS *)args)->retPtr;
     82   if (XML_Parse(parser, (const char *)data, (int)size, 1) == XML_STATUS_ERROR) {
     83     reportError(parser, filename);
     84     *retPtr = 0;
     85   }
     86   else
     87     *retPtr = 1;
     88 }
     89 
     90 #if (defined(WIN32) || defined(__WATCOMC__))
     91 
     92 static int
     93 isAsciiLetter(XML_Char c)
     94 {
     95   return (T('a') <= c && c <= T('z')) || (T('A') <= c && c <= T('Z'));
     96 }
     97 
     98 #endif /* WIN32 */
     99 
    100 static const XML_Char *
    101 resolveSystemId(const XML_Char *base, const XML_Char *systemId,
    102                 XML_Char **toFree)
    103 {
    104   XML_Char *s;
    105   *toFree = 0;
    106   if (!base
    107       || *systemId == T('/')
    108 #if (defined(WIN32) || defined(__WATCOMC__))
    109       || *systemId == T('\\')
    110       || (isAsciiLetter(systemId[0]) && systemId[1] == T(':'))
    111 #endif
    112      )
    113     return systemId;
    114   *toFree = (XML_Char *)malloc((tcslen(base) + tcslen(systemId) + 2)
    115                                * sizeof(XML_Char));
    116   if (!*toFree)
    117     return systemId;
    118   tcscpy(*toFree, base);
    119   s = *toFree;
    120   if (tcsrchr(s, T('/')))
    121     s = tcsrchr(s, T('/')) + 1;
    122 #if (defined(WIN32) || defined(__WATCOMC__))
    123   if (tcsrchr(s, T('\\')))
    124     s = tcsrchr(s, T('\\')) + 1;
    125 #endif
    126   tcscpy(s, systemId);
    127   return *toFree;
    128 }
    129 
    130 static int
    131 externalEntityRefFilemap(XML_Parser parser,
    132                          const XML_Char *context,
    133                          const XML_Char *base,
    134                          const XML_Char *systemId,
    135                          const XML_Char *publicId)
    136 {
    137   int result;
    138   XML_Char *s;
    139   const XML_Char *filename;
    140   XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0);
    141   PROCESS_ARGS args;
    142   args.retPtr = &result;
    143   args.parser = entParser;
    144   filename = resolveSystemId(base, systemId, &s);
    145   XML_SetBase(entParser, filename);
    146   if (!filemap(filename, processFile, &args))
    147     result = 0;
    148   free(s);
    149   XML_ParserFree(entParser);
    150   return result;
    151 }
    152 
    153 static int
    154 processStream(const XML_Char *filename, XML_Parser parser)
    155 {
    156   /* passing NULL for filename means read intput from stdin */
    157   int fd = 0;   /* 0 is the fileno for stdin */
    158 
    159   if (filename != NULL) {
    160     fd = topen(filename, O_BINARY|O_RDONLY);
    161     if (fd < 0) {
    162       tperror(filename);
    163       return 0;
    164     }
    165   }
    166   for (;;) {
    167     int nread;
    168     char *buf = (char *)XML_GetBuffer(parser, READ_SIZE);
    169     if (!buf) {
    170       if (filename != NULL)
    171         close(fd);
    172       ftprintf(stderr, T("%s: out of memory\n"),
    173                filename != NULL ? filename : "xmlwf");
    174       return 0;
    175     }
    176     nread = read(fd, buf, READ_SIZE);
    177     if (nread < 0) {
    178       tperror(filename != NULL ? filename : "STDIN");
    179       if (filename != NULL)
    180         close(fd);
    181       return 0;
    182     }
    183     if (XML_ParseBuffer(parser, nread, nread == 0) == XML_STATUS_ERROR) {
    184       reportError(parser, filename != NULL ? filename : "STDIN");
    185       if (filename != NULL)
    186         close(fd);
    187       return 0;
    188     }
    189     if (nread == 0) {
    190       if (filename != NULL)
    191         close(fd);
    192       break;;
    193     }
    194   }
    195   return 1;
    196 }
    197 
    198 static int
    199 externalEntityRefStream(XML_Parser parser,
    200                         const XML_Char *context,
    201                         const XML_Char *base,
    202                         const XML_Char *systemId,
    203                         const XML_Char *publicId)
    204 {
    205   XML_Char *s;
    206   const XML_Char *filename;
    207   int ret;
    208   XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0);
    209   filename = resolveSystemId(base, systemId, &s);
    210   XML_SetBase(entParser, filename);
    211   ret = processStream(filename, entParser);
    212   free(s);
    213   XML_ParserFree(entParser);
    214   return ret;
    215 }
    216 
    217 int
    218 XML_ProcessFile(XML_Parser parser,
    219                 const XML_Char *filename,
    220                 unsigned flags)
    221 {
    222   int result;
    223 
    224   if (!XML_SetBase(parser, filename)) {
    225     ftprintf(stderr, T("%s: out of memory"), filename);
    226     exit(1);
    227   }
    228 
    229   if (flags & XML_EXTERNAL_ENTITIES)
    230       XML_SetExternalEntityRefHandler(parser,
    231                                       (flags & XML_MAP_FILE)
    232                                       ? externalEntityRefFilemap
    233                                       : externalEntityRefStream);
    234   if (flags & XML_MAP_FILE) {
    235     PROCESS_ARGS args;
    236     args.retPtr = &result;
    237     args.parser = parser;
    238     if (!filemap(filename, processFile, &args))
    239       result = 0;
    240   }
    241   else
    242     result = processStream(filename, parser);
    243   return result;
    244 }
    245