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