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 |
} |