1/* 2The contents of this file are subject to the Mozilla Public License 3Version 1.1 (the "License"); you may not use this file except in 4compliance with the License. You may obtain a copy of the License at 5http://www.mozilla.org/MPL/ 6 7Software distributed under the License is distributed on an "AS IS" 8basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the 9License for the specific language governing rights and limitations 10under the License. 11 12The Original Code is expat. 13 14The Initial Developer of the Original Code is James Clark. 15Portions created by James Clark are Copyright (C) 1998, 1999 16James Clark. All Rights Reserved. 17 18Contributor(s): 19 20Alternatively, the contents of this file may be used under the terms 21of the GNU General Public License (the "GPL"), in which case the 22provisions of the GPL are applicable instead of those above. If you 23wish to allow use of your version of this file only under the terms of 24the GPL and not to allow others to use your version of this file under 25the MPL, indicate your decision by deleting the provisions above and 26replace them with the notice and other provisions required by the 27GPL. If you do not delete the provisions above, a recipient may use 28your version of this file under either the MPL or the GPL. 29*/ 30 31#include <stdio.h> 32#include <stdlib.h> 33#include <stddef.h> 34#include <string.h> 35#include <fcntl.h> 36#include "xmlparse.h" 37#include "xmlfile.h" 38#include "xmltchar.h" 39#include "filemap.h" 40 41#ifdef _MSC_VER 42#include <io.h> 43#endif 44 45#ifdef _POSIX_SOURCE 46#include <unistd.h> 47#endif 48 49#ifndef O_BINARY 50#ifdef _O_BINARY 51#define O_BINARY _O_BINARY 52#else 53#define O_BINARY 0 54#endif 55#endif 56 57#ifdef _DEBUG 58#define READ_SIZE 16 59#else 60#define READ_SIZE (1024*8) 61#endif 62 63 64 65typedef struct { 66 XML_Parser parser; 67 int *retPtr; 68} PROCESS_ARGS; 69 70static 71void reportError(XML_Parser parser, const XML_Char *filename) 72{ 73 int code = XML_GetErrorCode(parser); 74 const XML_Char *message = XML_ErrorString(code); 75 if (message) 76 ftprintf(stdout, T("%s:%d:%ld: %s\n"), 77 filename, 78 XML_GetErrorLineNumber(parser), 79 XML_GetErrorColumnNumber(parser), 80 message); 81 else 82 ftprintf(stderr, T("%s: (unknown message %d)\n"), filename, code); 83} 84 85static 86void processFile(const void *data, 87 size_t size, 88 const XML_Char *filename, 89 void *args) 90{ 91 XML_Parser parser = ((PROCESS_ARGS *)args)->parser; 92 int *retPtr = ((PROCESS_ARGS *)args)->retPtr; 93 if (!XML_Parse(parser, data, size, 1)) { 94 reportError(parser, filename); 95 *retPtr = 0; 96 } 97 else 98 *retPtr = 1; 99} 100 101static 102int isAsciiLetter(XML_Char c) 103{ 104 return (T('a') <= c && c <= T('z')) || (T('A') <= c && c <= T('Z')); 105} 106 107static 108const XML_Char *resolveSystemId(const XML_Char *base, const XML_Char *systemId, XML_Char **toFree) 109{ 110 XML_Char *s; 111 *toFree = 0; 112 if (!base 113 || *systemId == T('/') 114#ifdef WIN32 115 || *systemId == T('\\') 116 || (isAsciiLetter(systemId[0]) && systemId[1] == T(':')) 117#endif 118 ) 119 return systemId; 120 *toFree = (XML_Char *)malloc((tcslen(base) + tcslen(systemId) + 2)*sizeof(XML_Char)); 121 if (!*toFree) 122 return systemId; 123 tcscpy(*toFree, base); 124 s = *toFree; 125 if (tcsrchr(s, T('/'))) 126 s = tcsrchr(s, T('/')) + 1; 127#ifdef WIN32 128 if (tcsrchr(s, T('\\'))) 129 s = tcsrchr(s, T('\\')) + 1; 130#endif 131 tcscpy(s, systemId); 132 return *toFree; 133} 134 135static 136int externalEntityRefFilemap(XML_Parser parser, 137 const XML_Char *context, 138 const XML_Char *base, 139 const XML_Char *systemId, 140 const XML_Char *publicId) 141{ 142 int result; 143 XML_Char *s; 144 const XML_Char *filename; 145 XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0); 146 PROCESS_ARGS args; 147 args.retPtr = &result; 148 args.parser = entParser; 149 filename = resolveSystemId(base, systemId, &s); 150 XML_SetBase(entParser, filename); 151 if (!filemap(filename, processFile, &args)) 152 result = 0; 153 free(s); 154 XML_ParserFree(entParser); 155 return result; 156} 157 158static 159int processStream(const XML_Char *filename, XML_Parser parser) 160{ 161 int fd = topen(filename, O_BINARY|O_RDONLY); 162 if (fd < 0) { 163 tperror(filename); 164 return 0; 165 } 166 for (;;) { 167 int nread; 168 char *buf = XML_GetBuffer(parser, READ_SIZE); 169 if (!buf) { 170 close(fd); 171 ftprintf(stderr, T("%s: out of memory\n"), filename); 172 return 0; 173 } 174 nread = read(fd, buf, READ_SIZE); 175 if (nread < 0) { 176 tperror(filename); 177 close(fd); 178 return 0; 179 } 180 if (!XML_ParseBuffer(parser, nread, nread == 0)) { 181 reportError(parser, filename); 182 close(fd); 183 return 0; 184 } 185 if (nread == 0) { 186 close(fd); 187 break;; 188 } 189 } 190 return 1; 191} 192 193static 194int externalEntityRefStream(XML_Parser parser, 195 const XML_Char *context, 196 const XML_Char *base, 197 const XML_Char *systemId, 198 const XML_Char *publicId) 199{ 200 XML_Char *s; 201 const XML_Char *filename; 202 int ret; 203 XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0); 204 filename = resolveSystemId(base, systemId, &s); 205 XML_SetBase(entParser, filename); 206 ret = processStream(filename, entParser); 207 free(s); 208 XML_ParserFree(entParser); 209 return ret; 210} 211 212int XML_ProcessFile(XML_Parser parser, 213 const XML_Char *filename, 214 unsigned flags) 215{ 216 int result; 217 218 if (!XML_SetBase(parser, filename)) { 219 ftprintf(stderr, T("%s: out of memory"), filename); 220 exit(1); 221 } 222 223 if (flags & XML_EXTERNAL_ENTITIES) 224 XML_SetExternalEntityRefHandler(parser, 225 (flags & XML_MAP_FILE) 226 ? externalEntityRefFilemap 227 : externalEntityRefStream); 228 if (flags & XML_MAP_FILE) { 229 PROCESS_ARGS args; 230 args.retPtr = &result; 231 args.parser = parser; 232 if (!filemap(filename, processFile, &args)) 233 result = 0; 234 } 235 else 236 result = processStream(filename, parser); 237 return result; 238} 239