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
53 typedef struct {
54 XML_Parser parser;
55 int *retPtr;
56 } PROCESS_ARGS;
57
58 static void
reportError(XML_Parser parser,const XML_Char * filename)59 reportError(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
73 static void
processFile(const void * data,size_t size,const XML_Char * filename,void * args)74 processFile(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
89 static int
isAsciiLetter(XML_Char c)90 isAsciiLetter(XML_Char c)
91 {
92 return (T('a') <= c && c <= T('z')) || (T('A') <= c && c <= T('Z'));
93 }
94
95 #endif /* WIN32 */
96
97 static const XML_Char *
resolveSystemId(const XML_Char * base,const XML_Char * systemId,XML_Char ** toFree)98 resolveSystemId(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
127 static int
externalEntityRefFilemap(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)128 externalEntityRefFilemap(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
150 static int
processStream(const XML_Char * filename,XML_Parser parser)151 processStream(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
195 static int
externalEntityRefStream(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)196 externalEntityRefStream(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
214 int
XML_ProcessFile(XML_Parser parser,const XML_Char * filename,unsigned flags)215 XML_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