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