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