initial load of upstream version 1.06.32
[xmlrpc-c] / lib / expat / xmlwf / xmlfile.c
1 /*
2 Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
3 See the file copying.txt for copying permission.
4 */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <stddef.h>
9 #include <string.h>
10 #include <fcntl.h>
11 #include "xmlparse.h"
12 #include "xmlfile.h"
13 #include "xmltchar.h"
14 #include "filemap.h"
15
16 #ifdef _MSC_VER
17 #include <io.h>
18 #endif
19
20 #ifdef _POSIX_SOURCE
21 #include <unistd.h>
22 #endif
23
24 #ifndef O_BINARY
25 #ifdef _O_BINARY
26 #define O_BINARY _O_BINARY
27 #else
28 #define O_BINARY 0
29 #endif
30 #endif
31
32 #ifdef _DEBUG
33 #define READ_SIZE 16
34 #else
35 #define READ_SIZE (1024*8)
36 #endif
37
38
39
40 typedef struct {
41   XML_Parser parser;
42   int *retPtr;
43 } PROCESS_ARGS;
44
45 static
46 void reportError(XML_Parser parser, const XML_Char *filename)
47 {
48   int code = XML_GetErrorCode(parser);
49   const XML_Char *message = XML_ErrorString(code);
50   if (message)
51     ftprintf(stdout, T("%s:%d:%d: %s\n"),
52              filename,
53              XML_GetErrorLineNumber(parser),
54              XML_GetErrorColumnNumber(parser),
55              message);
56   else
57     ftprintf(stderr, T("%s: (unknown message %d)\n"), filename, code);
58 }
59
60 static
61 void processFile(const void *data,
62                  size_t size,
63                  const XML_Char *filename,
64                  void *args)
65 {
66   XML_Parser parser = ((PROCESS_ARGS *)args)->parser;
67   int *retPtr = ((PROCESS_ARGS *)args)->retPtr;
68   if (!XML_Parse(parser, data, size, 1)) {
69     reportError(parser, filename);
70     *retPtr = 0;
71   }
72   else
73     *retPtr = 1;
74 }
75
76 #ifdef WIN32
77
78 static
79 int isAsciiLetter(XML_Char c)
80 {
81   return (T('a') <= c && c <= T('z')) || (T('A') <= c && c <= T('Z'));
82 }
83
84 #endif /* WIN32 */
85
86 static
87 const XML_Char *resolveSystemId(const XML_Char *base, const XML_Char *systemId, XML_Char **toFree)
88 {
89   XML_Char *s;
90   *toFree = 0;
91   if (!base
92       || *systemId == T('/')
93 #ifdef WIN32
94       || *systemId == T('\\')
95       || (isAsciiLetter(systemId[0]) && systemId[1] == T(':'))
96 #endif
97      )
98     return systemId;
99   *toFree = (XML_Char *)malloc((tcslen(base) + tcslen(systemId) + 2)*sizeof(XML_Char));
100   if (!*toFree)
101     return systemId;
102   tcscpy(*toFree, base);
103   s = *toFree;
104   if (tcsrchr(s, T('/')))
105     s = tcsrchr(s, T('/')) + 1;
106 #ifdef WIN32
107   if (tcsrchr(s, T('\\')))
108     s = tcsrchr(s, T('\\')) + 1;
109 #endif
110   tcscpy(s, systemId);
111   return *toFree;
112 }
113
114 static
115 int externalEntityRefFilemap(XML_Parser parser,
116                              const XML_Char *context,
117                              const XML_Char *base,
118                              const XML_Char *systemId,
119                              const XML_Char *publicId)
120 {
121   int result;
122   XML_Char *s;
123   const XML_Char *filename;
124   XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0);
125   PROCESS_ARGS args;
126   args.retPtr = &result;
127   args.parser = entParser;
128   filename = resolveSystemId(base, systemId, &s);
129   XML_SetBase(entParser, filename);
130   if (!filemap(filename, processFile, &args))
131     result = 0;
132   free(s);
133   XML_ParserFree(entParser);
134   return result;
135 }
136
137 static
138 int processStream(const XML_Char *filename, XML_Parser parser)
139 {
140   int fd = topen(filename, O_BINARY|O_RDONLY);
141   if (fd < 0) {
142     tperror(filename);
143     return 0;
144   }
145   for (;;) {
146     int nread;
147     char *buf = XML_GetBuffer(parser, READ_SIZE);
148     if (!buf) {
149       close(fd);
150       ftprintf(stderr, T("%s: out of memory\n"), filename);
151       return 0;
152     }
153     nread = read(fd, buf, READ_SIZE);
154     if (nread < 0) {
155       tperror(filename);
156       close(fd);
157       return 0;
158     }
159     if (!XML_ParseBuffer(parser, nread, nread == 0)) {
160       reportError(parser, filename);
161       close(fd);
162       return 0;
163     }
164     if (nread == 0) {
165       close(fd);
166       break;;
167     }
168   }
169   return 1;
170 }
171
172 static
173 int externalEntityRefStream(XML_Parser parser,
174                             const XML_Char *context,
175                             const XML_Char *base,
176                             const XML_Char *systemId,
177                             const XML_Char *publicId)
178 {
179   XML_Char *s;
180   const XML_Char *filename;
181   int ret;
182   XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0);
183   filename = resolveSystemId(base, systemId, &s);
184   XML_SetBase(entParser, filename);
185   ret = processStream(filename, entParser);
186   free(s);
187   XML_ParserFree(entParser);
188   return ret;
189 }
190
191 int XML_ProcessFile(XML_Parser parser,
192                     const XML_Char *filename,
193                     unsigned flags)
194 {
195   int result;
196
197   if (!XML_SetBase(parser, filename)) {
198     ftprintf(stderr, T("%s: out of memory"), filename);
199     exit(1);
200   }
201
202   if (flags & XML_EXTERNAL_ENTITIES)
203       XML_SetExternalEntityRefHandler(parser,
204                                       (flags & XML_MAP_FILE)
205                                       ? externalEntityRefFilemap
206                                       : externalEntityRefStream);
207   if (flags & XML_MAP_FILE) {
208     PROCESS_ARGS args;
209     args.retPtr = &result;
210     args.parser = parser;
211     if (!filemap(filename, processFile, &args))
212       result = 0;
213   }
214   else
215     result = processStream(filename, parser);
216   return result;
217 }