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