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 55typedef struct { 56 XML_Parser parser; 57 int *retPtr; 58} PROCESS_ARGS; 59 60static void 61reportError(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. */ 76static void 77processFile(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 92static int 93isAsciiLetter(XML_Char c) 94{ 95 return (T('a') <= c && c <= T('z')) || (T('A') <= c && c <= T('Z')); 96} 97 98#endif /* WIN32 */ 99 100static const XML_Char * 101resolveSystemId(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 130static int 131externalEntityRefFilemap(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 153static int 154processStream(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 198static int 199externalEntityRefStream(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 217int 218XML_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