• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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