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 43 typedef struct { 44 XML_Parser parser; 45 int *retPtr; 46 } PROCESS_ARGS; 47 48 static void 49 reportError(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 63 static void 64 processFile(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 79 static int 80 isAsciiLetter(XML_Char c) 81 { 82 return (T('a') <= c && c <= T('z')) || (T('A') <= c && c <= T('Z')); 83 } 84 85 #endif /* WIN32 */ 86 87 static const XML_Char * 88 resolveSystemId(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 117 static int 118 externalEntityRefFilemap(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 140 static int 141 processStream(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 185 static int 186 externalEntityRefStream(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 204 int 205 XML_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