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