aboutsummaryrefslogtreecommitdiff
path: root/expat/xmlwf
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2013-10-18 13:29:37 +0200
committermarha <marha@users.sourceforge.net>2013-10-18 13:29:37 +0200
commit72483d25d0f41d48a8e6bdc83ab57c971cfb47b4 (patch)
treec8aa56f1e7dc24ce93287592c07a5f354eb6f86d /expat/xmlwf
parentb821fe861f33d7e8a39fe4c7d885b7ff379dc476 (diff)
parent5880b059e9a156336daf32a73bed72def6ba90f2 (diff)
downloadvcxsrv-72483d25d0f41d48a8e6bdc83ab57c971cfb47b4.tar.gz
vcxsrv-72483d25d0f41d48a8e6bdc83ab57c971cfb47b4.tar.bz2
vcxsrv-72483d25d0f41d48a8e6bdc83ab57c971cfb47b4.zip
Merge remote-tracking branch 'origin/released'
* origin/released: Added expat-2.1.0
Diffstat (limited to 'expat/xmlwf')
-rw-r--r--expat/xmlwf/codepage.c68
-rw-r--r--expat/xmlwf/codepage.h6
-rw-r--r--expat/xmlwf/ct.c147
-rw-r--r--expat/xmlwf/filemap.h17
-rw-r--r--expat/xmlwf/readfilemap.c100
-rw-r--r--expat/xmlwf/unixfilemap.c65
-rw-r--r--expat/xmlwf/win32filemap.c96
-rw-r--r--expat/xmlwf/xmlfile.c244
-rw-r--r--expat/xmlwf/xmlfile.h20
-rw-r--r--expat/xmlwf/xmlmime.c163
-rw-r--r--expat/xmlwf/xmlmime.h19
-rw-r--r--expat/xmlwf/xmltchar.h36
-rw-r--r--expat/xmlwf/xmlurl.h13
-rw-r--r--expat/xmlwf/xmlwf.c861
-rw-r--r--expat/xmlwf/xmlwf.dsp139
-rw-r--r--expat/xmlwf/xmlwin32url.cxx395
16 files changed, 2389 insertions, 0 deletions
diff --git a/expat/xmlwf/codepage.c b/expat/xmlwf/codepage.c
new file mode 100644
index 000000000..57e48ff2d
--- /dev/null
+++ b/expat/xmlwf/codepage.c
@@ -0,0 +1,68 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+#include "codepage.h"
+
+#if (defined(WIN32) || (defined(__WATCOMC__) && defined(__NT__)))
+#define STRICT 1
+#define WIN32_LEAN_AND_MEAN 1
+
+#include <windows.h>
+
+int
+codepageMap(int cp, int *map)
+{
+ int i;
+ CPINFO info;
+ if (!GetCPInfo(cp, &info) || info.MaxCharSize > 2)
+ return 0;
+ for (i = 0; i < 256; i++)
+ map[i] = -1;
+ if (info.MaxCharSize > 1) {
+ for (i = 0; i < MAX_LEADBYTES; i+=2) {
+ int j, lim;
+ if (info.LeadByte[i] == 0 && info.LeadByte[i + 1] == 0)
+ break;
+ lim = info.LeadByte[i + 1];
+ for (j = info.LeadByte[i]; j <= lim; j++)
+ map[j] = -2;
+ }
+ }
+ for (i = 0; i < 256; i++) {
+ if (map[i] == -1) {
+ char c = (char)i;
+ unsigned short n;
+ if (MultiByteToWideChar(cp, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
+ &c, 1, &n, 1) == 1)
+ map[i] = n;
+ }
+ }
+ return 1;
+}
+
+int
+codepageConvert(int cp, const char *p)
+{
+ unsigned short c;
+ if (MultiByteToWideChar(cp, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
+ p, 2, &c, 1) == 1)
+ return c;
+ return -1;
+}
+
+#else /* not WIN32 */
+
+int
+codepageMap(int cp, int *map)
+{
+ return 0;
+}
+
+int
+codepageConvert(int cp, const char *p)
+{
+ return -1;
+}
+
+#endif /* not WIN32 */
diff --git a/expat/xmlwf/codepage.h b/expat/xmlwf/codepage.h
new file mode 100644
index 000000000..6a4df6888
--- /dev/null
+++ b/expat/xmlwf/codepage.h
@@ -0,0 +1,6 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+int codepageMap(int cp, int *map);
+int codepageConvert(int cp, const char *p);
diff --git a/expat/xmlwf/ct.c b/expat/xmlwf/ct.c
new file mode 100644
index 000000000..95903a345
--- /dev/null
+++ b/expat/xmlwf/ct.c
@@ -0,0 +1,147 @@
+#define CHARSET_MAX 41
+
+static const char *
+getTok(const char **pp)
+{
+ enum { inAtom, inString, init, inComment };
+ int state = init;
+ const char *tokStart = 0;
+ for (;;) {
+ switch (**pp) {
+ case '\0':
+ return 0;
+ case ' ':
+ case '\r':
+ case '\t':
+ case '\n':
+ if (state == inAtom)
+ return tokStart;
+ break;
+ case '(':
+ if (state == inAtom)
+ return tokStart;
+ if (state != inString)
+ state++;
+ break;
+ case ')':
+ if (state > init)
+ --state;
+ else if (state != inString)
+ return 0;
+ break;
+ case ';':
+ case '/':
+ case '=':
+ if (state == inAtom)
+ return tokStart;
+ if (state == init)
+ return (*pp)++;
+ break;
+ case '\\':
+ ++*pp;
+ if (**pp == '\0')
+ return 0;
+ break;
+ case '"':
+ switch (state) {
+ case inString:
+ ++*pp;
+ return tokStart;
+ case inAtom:
+ return tokStart;
+ case init:
+ tokStart = *pp;
+ state = inString;
+ break;
+ }
+ break;
+ default:
+ if (state == init) {
+ tokStart = *pp;
+ state = inAtom;
+ }
+ break;
+ }
+ ++*pp;
+ }
+ /* not reached */
+}
+
+/* key must be lowercase ASCII */
+
+static int
+matchkey(const char *start, const char *end, const char *key)
+{
+ if (!start)
+ return 0;
+ for (; start != end; start++, key++)
+ if (*start != *key && *start != 'A' + (*key - 'a'))
+ return 0;
+ return *key == '\0';
+}
+
+void
+getXMLCharset(const char *buf, char *charset)
+{
+ const char *next, *p;
+
+ charset[0] = '\0';
+ next = buf;
+ p = getTok(&next);
+ if (matchkey(p, next, "text"))
+ strcpy(charset, "us-ascii");
+ else if (!matchkey(p, next, "application"))
+ return;
+ p = getTok(&next);
+ if (!p || *p != '/')
+ return;
+ p = getTok(&next);
+ if (matchkey(p, next, "xml"))
+ isXml = 1;
+ p = getTok(&next);
+ while (p) {
+ if (*p == ';') {
+ p = getTok(&next);
+ if (matchkey(p, next, "charset")) {
+ p = getTok(&next);
+ if (p && *p == '=') {
+ p = getTok(&next);
+ if (p) {
+ char *s = charset;
+ if (*p == '"') {
+ while (++p != next - 1) {
+ if (*p == '\\')
+ ++p;
+ if (s == charset + CHARSET_MAX - 1) {
+ charset[0] = '\0';
+ break;
+ }
+ *s++ = *p;
+ }
+ *s++ = '\0';
+ }
+ else {
+ if (next - p > CHARSET_MAX - 1)
+ break;
+ while (p != next)
+ *s++ = *p++;
+ *s = 0;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ p = getTok(&next);
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ char buf[CHARSET_MAX];
+ getXMLCharset(argv[1], buf);
+ printf("charset = \"%s\"\n", buf);
+ return 0;
+}
diff --git a/expat/xmlwf/filemap.h b/expat/xmlwf/filemap.h
new file mode 100644
index 000000000..814edec25
--- /dev/null
+++ b/expat/xmlwf/filemap.h
@@ -0,0 +1,17 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+#include <stddef.h>
+
+#ifdef XML_UNICODE
+int filemap(const wchar_t *name,
+ void (*processor)(const void *, size_t,
+ const wchar_t *, void *arg),
+ void *arg);
+#else
+int filemap(const char *name,
+ void (*processor)(const void *, size_t,
+ const char *, void *arg),
+ void *arg);
+#endif
diff --git a/expat/xmlwf/readfilemap.c b/expat/xmlwf/readfilemap.c
new file mode 100644
index 000000000..bd32b9341
--- /dev/null
+++ b/expat/xmlwf/readfilemap.c
@@ -0,0 +1,100 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifdef __WATCOMC__
+#ifndef __LINUX__
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+#endif
+
+#ifdef __BEOS__
+#include <unistd.h>
+#endif
+
+#ifndef S_ISREG
+#ifndef S_IFREG
+#define S_IFREG _S_IFREG
+#endif
+#ifndef S_IFMT
+#define S_IFMT _S_IFMT
+#endif
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#endif /* not S_ISREG */
+
+#ifndef O_BINARY
+#ifdef _O_BINARY
+#define O_BINARY _O_BINARY
+#else
+#define O_BINARY 0
+#endif
+#endif
+
+#include "filemap.h"
+
+int
+filemap(const char *name,
+ void (*processor)(const void *, size_t, const char *, void *arg),
+ void *arg)
+{
+ size_t nbytes;
+ int fd;
+ int n;
+ struct stat sb;
+ void *p;
+
+ fd = open(name, O_RDONLY|O_BINARY);
+ if (fd < 0) {
+ perror(name);
+ return 0;
+ }
+ if (fstat(fd, &sb) < 0) {
+ perror(name);
+ close(fd);
+ return 0;
+ }
+ if (!S_ISREG(sb.st_mode)) {
+ fprintf(stderr, "%s: not a regular file\n", name);
+ close(fd);
+ return 0;
+ }
+ nbytes = sb.st_size;
+ /* malloc will return NULL with nbytes == 0, handle files with size 0 */
+ if (nbytes == 0) {
+ static const char c = '\0';
+ processor(&c, 0, name, arg);
+ close(fd);
+ return 1;
+ }
+ p = malloc(nbytes);
+ if (!p) {
+ fprintf(stderr, "%s: out of memory\n", name);
+ close(fd);
+ return 0;
+ }
+ n = read(fd, p, nbytes);
+ if (n < 0) {
+ perror(name);
+ free(p);
+ close(fd);
+ return 0;
+ }
+ if (n != nbytes) {
+ fprintf(stderr, "%s: read unexpected number of bytes\n", name);
+ free(p);
+ close(fd);
+ return 0;
+ }
+ processor(p, nbytes, name, arg);
+ free(p);
+ close(fd);
+ return 1;
+}
diff --git a/expat/xmlwf/unixfilemap.c b/expat/xmlwf/unixfilemap.c
new file mode 100644
index 000000000..93adce32e
--- /dev/null
+++ b/expat/xmlwf/unixfilemap.c
@@ -0,0 +1,65 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#ifndef MAP_FILE
+#define MAP_FILE 0
+#endif
+
+#include "filemap.h"
+
+int
+filemap(const char *name,
+ void (*processor)(const void *, size_t, const char *, void *arg),
+ void *arg)
+{
+ int fd;
+ size_t nbytes;
+ struct stat sb;
+ void *p;
+
+ fd = open(name, O_RDONLY);
+ if (fd < 0) {
+ perror(name);
+ return 0;
+ }
+ if (fstat(fd, &sb) < 0) {
+ perror(name);
+ close(fd);
+ return 0;
+ }
+ if (!S_ISREG(sb.st_mode)) {
+ close(fd);
+ fprintf(stderr, "%s: not a regular file\n", name);
+ return 0;
+ }
+
+ nbytes = sb.st_size;
+ /* mmap fails for zero length files */
+ if (nbytes == 0) {
+ static const char c = '\0';
+ processor(&c, 0, name, arg);
+ close(fd);
+ return 1;
+ }
+ p = (void *)mmap((caddr_t)0, (size_t)nbytes, PROT_READ,
+ MAP_FILE|MAP_PRIVATE, fd, (off_t)0);
+ if (p == (void *)-1) {
+ perror(name);
+ close(fd);
+ return 0;
+ }
+ processor(p, nbytes, name, arg);
+ munmap((caddr_t)p, nbytes);
+ close(fd);
+ return 1;
+}
diff --git a/expat/xmlwf/win32filemap.c b/expat/xmlwf/win32filemap.c
new file mode 100644
index 000000000..41dc35b61
--- /dev/null
+++ b/expat/xmlwf/win32filemap.c
@@ -0,0 +1,96 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+#define STRICT 1
+#define WIN32_LEAN_AND_MEAN 1
+
+#ifdef XML_UNICODE_WCHAR_T
+#ifndef XML_UNICODE
+#define XML_UNICODE
+#endif
+#endif
+
+#ifdef XML_UNICODE
+#define UNICODE
+#define _UNICODE
+#endif /* XML_UNICODE */
+#include <windows.h>
+#include <stdio.h>
+#include <tchar.h>
+#include "filemap.h"
+
+static void win32perror(const TCHAR *);
+
+int
+filemap(const TCHAR *name,
+ void (*processor)(const void *, size_t, const TCHAR *, void *arg),
+ void *arg)
+{
+ HANDLE f;
+ HANDLE m;
+ DWORD size;
+ DWORD sizeHi;
+ void *p;
+
+ f = CreateFile(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
+ FILE_FLAG_SEQUENTIAL_SCAN, NULL);
+ if (f == INVALID_HANDLE_VALUE) {
+ win32perror(name);
+ return 0;
+ }
+ size = GetFileSize(f, &sizeHi);
+ if (size == (DWORD)-1) {
+ win32perror(name);
+ return 0;
+ }
+ if (sizeHi) {
+ _ftprintf(stderr, _T("%s: bigger than 2Gb\n"), name);
+ return 0;
+ }
+ /* CreateFileMapping barfs on zero length files */
+ if (size == 0) {
+ static const char c = '\0';
+ processor(&c, 0, name, arg);
+ CloseHandle(f);
+ return 1;
+ }
+ m = CreateFileMapping(f, NULL, PAGE_READONLY, 0, 0, NULL);
+ if (m == NULL) {
+ win32perror(name);
+ CloseHandle(f);
+ return 0;
+ }
+ p = MapViewOfFile(m, FILE_MAP_READ, 0, 0, 0);
+ if (p == NULL) {
+ win32perror(name);
+ CloseHandle(m);
+ CloseHandle(f);
+ return 0;
+ }
+ processor(p, size, name, arg);
+ UnmapViewOfFile(p);
+ CloseHandle(m);
+ CloseHandle(f);
+ return 1;
+}
+
+static void
+win32perror(const TCHAR *s)
+{
+ LPVOID buf;
+ if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
+ | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &buf,
+ 0,
+ NULL)) {
+ _ftprintf(stderr, _T("%s: %s"), s, buf);
+ fflush(stderr);
+ LocalFree(buf);
+ }
+ else
+ _ftprintf(stderr, _T("%s: unknown Windows error\n"), s);
+}
diff --git a/expat/xmlwf/xmlfile.c b/expat/xmlwf/xmlfile.c
new file mode 100644
index 000000000..99eeeaaef
--- /dev/null
+++ b/expat/xmlwf/xmlfile.c
@@ -0,0 +1,244 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <fcntl.h>
+
+#ifdef COMPILED_FROM_DSP
+#include "winconfig.h"
+#elif defined(MACOS_CLASSIC)
+#include "macconfig.h"
+#elif defined(__amigaos__)
+#include "amigaconfig.h"
+#elif defined(__WATCOMC__)
+#include "watcomconfig.h"
+#elif defined(HAVE_EXPAT_CONFIG_H)
+#include <expat_config.h>
+#endif /* ndef COMPILED_FROM_DSP */
+
+#include "expat.h"
+#include "xmlfile.h"
+#include "xmltchar.h"
+#include "filemap.h"
+
+#if (defined(_MSC_VER) || (defined(__WATCOMC__) && !defined(__LINUX__)))
+#include <io.h>
+#endif
+
+#if defined(__amigaos__) && defined(__USE_INLINE__)
+#include <proto/expat.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifndef O_BINARY
+#ifdef _O_BINARY
+#define O_BINARY _O_BINARY
+#else
+#define O_BINARY 0
+#endif
+#endif
+
+#ifdef _DEBUG
+#define READ_SIZE 16
+#else
+#define READ_SIZE (1024*8)
+#endif
+
+
+typedef struct {
+ XML_Parser parser;
+ int *retPtr;
+} PROCESS_ARGS;
+
+static void
+reportError(XML_Parser parser, const XML_Char *filename)
+{
+ enum XML_Error code = XML_GetErrorCode(parser);
+ const XML_Char *message = XML_ErrorString(code);
+ if (message)
+ ftprintf(stdout, T("%s:%" XML_FMT_INT_MOD "u:%" XML_FMT_INT_MOD "u: %s\n"),
+ filename,
+ XML_GetErrorLineNumber(parser),
+ XML_GetErrorColumnNumber(parser),
+ message);
+ else
+ ftprintf(stderr, T("%s: (unknown message %d)\n"), filename, code);
+}
+
+/* This implementation will give problems on files larger than INT_MAX. */
+static void
+processFile(const void *data, size_t size,
+ const XML_Char *filename, void *args)
+{
+ XML_Parser parser = ((PROCESS_ARGS *)args)->parser;
+ int *retPtr = ((PROCESS_ARGS *)args)->retPtr;
+ if (XML_Parse(parser, (const char *)data, (int)size, 1) == XML_STATUS_ERROR) {
+ reportError(parser, filename);
+ *retPtr = 0;
+ }
+ else
+ *retPtr = 1;
+}
+
+#if (defined(WIN32) || defined(__WATCOMC__))
+
+static int
+isAsciiLetter(XML_Char c)
+{
+ return (T('a') <= c && c <= T('z')) || (T('A') <= c && c <= T('Z'));
+}
+
+#endif /* WIN32 */
+
+static const XML_Char *
+resolveSystemId(const XML_Char *base, const XML_Char *systemId,
+ XML_Char **toFree)
+{
+ XML_Char *s;
+ *toFree = 0;
+ if (!base
+ || *systemId == T('/')
+#if (defined(WIN32) || defined(__WATCOMC__))
+ || *systemId == T('\\')
+ || (isAsciiLetter(systemId[0]) && systemId[1] == T(':'))
+#endif
+ )
+ return systemId;
+ *toFree = (XML_Char *)malloc((tcslen(base) + tcslen(systemId) + 2)
+ * sizeof(XML_Char));
+ if (!*toFree)
+ return systemId;
+ tcscpy(*toFree, base);
+ s = *toFree;
+ if (tcsrchr(s, T('/')))
+ s = tcsrchr(s, T('/')) + 1;
+#if (defined(WIN32) || defined(__WATCOMC__))
+ if (tcsrchr(s, T('\\')))
+ s = tcsrchr(s, T('\\')) + 1;
+#endif
+ tcscpy(s, systemId);
+ return *toFree;
+}
+
+static int
+externalEntityRefFilemap(XML_Parser parser,
+ const XML_Char *context,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId)
+{
+ int result;
+ XML_Char *s;
+ const XML_Char *filename;
+ XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0);
+ PROCESS_ARGS args;
+ args.retPtr = &result;
+ args.parser = entParser;
+ filename = resolveSystemId(base, systemId, &s);
+ XML_SetBase(entParser, filename);
+ if (!filemap(filename, processFile, &args))
+ result = 0;
+ free(s);
+ XML_ParserFree(entParser);
+ return result;
+}
+
+static int
+processStream(const XML_Char *filename, XML_Parser parser)
+{
+ /* passing NULL for filename means read intput from stdin */
+ int fd = 0; /* 0 is the fileno for stdin */
+
+ if (filename != NULL) {
+ fd = topen(filename, O_BINARY|O_RDONLY);
+ if (fd < 0) {
+ tperror(filename);
+ return 0;
+ }
+ }
+ for (;;) {
+ int nread;
+ char *buf = (char *)XML_GetBuffer(parser, READ_SIZE);
+ if (!buf) {
+ if (filename != NULL)
+ close(fd);
+ ftprintf(stderr, T("%s: out of memory\n"),
+ filename != NULL ? filename : "xmlwf");
+ return 0;
+ }
+ nread = read(fd, buf, READ_SIZE);
+ if (nread < 0) {
+ tperror(filename != NULL ? filename : "STDIN");
+ if (filename != NULL)
+ close(fd);
+ return 0;
+ }
+ if (XML_ParseBuffer(parser, nread, nread == 0) == XML_STATUS_ERROR) {
+ reportError(parser, filename != NULL ? filename : "STDIN");
+ if (filename != NULL)
+ close(fd);
+ return 0;
+ }
+ if (nread == 0) {
+ if (filename != NULL)
+ close(fd);
+ break;;
+ }
+ }
+ return 1;
+}
+
+static int
+externalEntityRefStream(XML_Parser parser,
+ const XML_Char *context,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId)
+{
+ XML_Char *s;
+ const XML_Char *filename;
+ int ret;
+ XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0);
+ filename = resolveSystemId(base, systemId, &s);
+ XML_SetBase(entParser, filename);
+ ret = processStream(filename, entParser);
+ free(s);
+ XML_ParserFree(entParser);
+ return ret;
+}
+
+int
+XML_ProcessFile(XML_Parser parser,
+ const XML_Char *filename,
+ unsigned flags)
+{
+ int result;
+
+ if (!XML_SetBase(parser, filename)) {
+ ftprintf(stderr, T("%s: out of memory"), filename);
+ exit(1);
+ }
+
+ if (flags & XML_EXTERNAL_ENTITIES)
+ XML_SetExternalEntityRefHandler(parser,
+ (flags & XML_MAP_FILE)
+ ? externalEntityRefFilemap
+ : externalEntityRefStream);
+ if (flags & XML_MAP_FILE) {
+ PROCESS_ARGS args;
+ args.retPtr = &result;
+ args.parser = parser;
+ if (!filemap(filename, processFile, &args))
+ result = 0;
+ }
+ else
+ result = processStream(filename, parser);
+ return result;
+}
diff --git a/expat/xmlwf/xmlfile.h b/expat/xmlwf/xmlfile.h
new file mode 100644
index 000000000..d093ecc06
--- /dev/null
+++ b/expat/xmlwf/xmlfile.h
@@ -0,0 +1,20 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+#define XML_MAP_FILE 01
+#define XML_EXTERNAL_ENTITIES 02
+
+#ifdef XML_LARGE_SIZE
+#if defined(XML_USE_MSC_EXTENSIONS) && _MSC_VER < 1400
+#define XML_FMT_INT_MOD "I64"
+#else
+#define XML_FMT_INT_MOD "ll"
+#endif
+#else
+#define XML_FMT_INT_MOD "l"
+#endif
+
+extern int XML_ProcessFile(XML_Parser parser,
+ const XML_Char *filename,
+ unsigned flags);
diff --git a/expat/xmlwf/xmlmime.c b/expat/xmlwf/xmlmime.c
new file mode 100644
index 000000000..56a0e7f40
--- /dev/null
+++ b/expat/xmlwf/xmlmime.c
@@ -0,0 +1,163 @@
+#include <string.h>
+#include "xmlmime.h"
+
+static const char *
+getTok(const char **pp)
+{
+ /* inComment means one level of nesting; inComment+1 means two levels etc */
+ enum { inAtom, inString, init, inComment };
+ int state = init;
+ const char *tokStart = 0;
+ for (;;) {
+ switch (**pp) {
+ case '\0':
+ if (state == inAtom)
+ return tokStart;
+ return 0;
+ case ' ':
+ case '\r':
+ case '\t':
+ case '\n':
+ if (state == inAtom)
+ return tokStart;
+ break;
+ case '(':
+ if (state == inAtom)
+ return tokStart;
+ if (state != inString)
+ state++;
+ break;
+ case ')':
+ if (state > init)
+ --state;
+ else if (state != inString)
+ return 0;
+ break;
+ case ';':
+ case '/':
+ case '=':
+ if (state == inAtom)
+ return tokStart;
+ if (state == init)
+ return (*pp)++;
+ break;
+ case '\\':
+ ++*pp;
+ if (**pp == '\0')
+ return 0;
+ break;
+ case '"':
+ switch (state) {
+ case inString:
+ ++*pp;
+ return tokStart;
+ case inAtom:
+ return tokStart;
+ case init:
+ tokStart = *pp;
+ state = inString;
+ break;
+ }
+ break;
+ default:
+ if (state == init) {
+ tokStart = *pp;
+ state = inAtom;
+ }
+ break;
+ }
+ ++*pp;
+ }
+ /* not reached */
+}
+
+/* key must be lowercase ASCII */
+
+static int
+matchkey(const char *start, const char *end, const char *key)
+{
+ if (!start)
+ return 0;
+ for (; start != end; start++, key++)
+ if (*start != *key && *start != 'A' + (*key - 'a'))
+ return 0;
+ return *key == '\0';
+}
+
+void
+getXMLCharset(const char *buf, char *charset)
+{
+ const char *next, *p;
+
+ charset[0] = '\0';
+ next = buf;
+ p = getTok(&next);
+ if (matchkey(p, next, "text"))
+ strcpy(charset, "us-ascii");
+ else if (!matchkey(p, next, "application"))
+ return;
+ p = getTok(&next);
+ if (!p || *p != '/')
+ return;
+ p = getTok(&next);
+#if 0
+ if (!matchkey(p, next, "xml") && charset[0] == '\0')
+ return;
+#endif
+ p = getTok(&next);
+ while (p) {
+ if (*p == ';') {
+ p = getTok(&next);
+ if (matchkey(p, next, "charset")) {
+ p = getTok(&next);
+ if (p && *p == '=') {
+ p = getTok(&next);
+ if (p) {
+ char *s = charset;
+ if (*p == '"') {
+ while (++p != next - 1) {
+ if (*p == '\\')
+ ++p;
+ if (s == charset + CHARSET_MAX - 1) {
+ charset[0] = '\0';
+ break;
+ }
+ *s++ = *p;
+ }
+ *s++ = '\0';
+ }
+ else {
+ if (next - p > CHARSET_MAX - 1)
+ break;
+ while (p != next)
+ *s++ = *p++;
+ *s = 0;
+ break;
+ }
+ }
+ }
+ break;
+ }
+ }
+ else
+ p = getTok(&next);
+ }
+}
+
+#ifdef TEST
+
+#include <stdio.h>
+
+int
+main(int argc, char *argv[])
+{
+ char buf[CHARSET_MAX];
+ if (argc <= 1)
+ return 1;
+ printf("%s\n", argv[1]);
+ getXMLCharset(argv[1], buf);
+ printf("charset=\"%s\"\n", buf);
+ return 0;
+}
+
+#endif /* TEST */
diff --git a/expat/xmlwf/xmlmime.h b/expat/xmlwf/xmlmime.h
new file mode 100644
index 000000000..bf0356df0
--- /dev/null
+++ b/expat/xmlwf/xmlmime.h
@@ -0,0 +1,19 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Registered charset names are at most 40 characters long. */
+
+#define CHARSET_MAX 41
+
+/* Figure out the charset to use from the ContentType.
+ buf contains the body of the header field (the part after "Content-Type:").
+ charset gets the charset to use. It must be at least CHARSET_MAX chars
+ long. charset will be empty if the default charset should be used.
+*/
+
+void getXMLCharset(const char *buf, char *charset);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/expat/xmlwf/xmltchar.h b/expat/xmlwf/xmltchar.h
new file mode 100644
index 000000000..108857551
--- /dev/null
+++ b/expat/xmlwf/xmltchar.h
@@ -0,0 +1,36 @@
+#ifdef XML_UNICODE
+#ifndef XML_UNICODE_WCHAR_T
+#error xmlwf requires a 16-bit Unicode-compatible wchar_t
+#endif
+#define T(x) L ## x
+#define ftprintf fwprintf
+#define tfopen _wfopen
+#define fputts fputws
+#define puttc putwc
+#define tcscmp wcscmp
+#define tcscpy wcscpy
+#define tcscat wcscat
+#define tcschr wcschr
+#define tcsrchr wcsrchr
+#define tcslen wcslen
+#define tperror _wperror
+#define topen _wopen
+#define tmain wmain
+#define tremove _wremove
+#else /* not XML_UNICODE */
+#define T(x) x
+#define ftprintf fprintf
+#define tfopen fopen
+#define fputts fputs
+#define puttc putc
+#define tcscmp strcmp
+#define tcscpy strcpy
+#define tcscat strcat
+#define tcschr strchr
+#define tcsrchr strrchr
+#define tcslen strlen
+#define tperror perror
+#define topen open
+#define tmain main
+#define tremove remove
+#endif /* not XML_UNICODE */
diff --git a/expat/xmlwf/xmlurl.h b/expat/xmlwf/xmlurl.h
new file mode 100644
index 000000000..d329913ac
--- /dev/null
+++ b/expat/xmlwf/xmlurl.h
@@ -0,0 +1,13 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int XML_URLInit();
+void XML_URLUninit();
+int XML_ProcessURL(XML_Parser parser,
+ const XML_Char *url,
+ unsigned flags);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/expat/xmlwf/xmlwf.c b/expat/xmlwf/xmlwf.c
new file mode 100644
index 000000000..4fc77da94
--- /dev/null
+++ b/expat/xmlwf/xmlwf.c
@@ -0,0 +1,861 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+
+#include "expat.h"
+#include "codepage.h"
+#include "xmlfile.h"
+#include "xmltchar.h"
+
+#ifdef _MSC_VER
+#include <crtdbg.h>
+#endif
+
+#if defined(__amigaos__) && defined(__USE_INLINE__)
+#include <proto/expat.h>
+#endif
+
+/* This ensures proper sorting. */
+
+#define NSSEP T('\001')
+
+static void XMLCALL
+characterData(void *userData, const XML_Char *s, int len)
+{
+ FILE *fp = (FILE *)userData;
+ for (; len > 0; --len, ++s) {
+ switch (*s) {
+ case T('&'):
+ fputts(T("&amp;"), fp);
+ break;
+ case T('<'):
+ fputts(T("&lt;"), fp);
+ break;
+ case T('>'):
+ fputts(T("&gt;"), fp);
+ break;
+#ifdef W3C14N
+ case 13:
+ fputts(T("&#xD;"), fp);
+ break;
+#else
+ case T('"'):
+ fputts(T("&quot;"), fp);
+ break;
+ case 9:
+ case 10:
+ case 13:
+ ftprintf(fp, T("&#%d;"), *s);
+ break;
+#endif
+ default:
+ puttc(*s, fp);
+ break;
+ }
+ }
+}
+
+static void
+attributeValue(FILE *fp, const XML_Char *s)
+{
+ puttc(T('='), fp);
+ puttc(T('"'), fp);
+ for (;;) {
+ switch (*s) {
+ case 0:
+ case NSSEP:
+ puttc(T('"'), fp);
+ return;
+ case T('&'):
+ fputts(T("&amp;"), fp);
+ break;
+ case T('<'):
+ fputts(T("&lt;"), fp);
+ break;
+ case T('"'):
+ fputts(T("&quot;"), fp);
+ break;
+#ifdef W3C14N
+ case 9:
+ fputts(T("&#x9;"), fp);
+ break;
+ case 10:
+ fputts(T("&#xA;"), fp);
+ break;
+ case 13:
+ fputts(T("&#xD;"), fp);
+ break;
+#else
+ case T('>'):
+ fputts(T("&gt;"), fp);
+ break;
+ case 9:
+ case 10:
+ case 13:
+ ftprintf(fp, T("&#%d;"), *s);
+ break;
+#endif
+ default:
+ puttc(*s, fp);
+ break;
+ }
+ s++;
+ }
+}
+
+/* Lexicographically comparing UTF-8 encoded attribute values,
+is equivalent to lexicographically comparing based on the character number. */
+
+static int
+attcmp(const void *att1, const void *att2)
+{
+ return tcscmp(*(const XML_Char **)att1, *(const XML_Char **)att2);
+}
+
+static void XMLCALL
+startElement(void *userData, const XML_Char *name, const XML_Char **atts)
+{
+ int nAtts;
+ const XML_Char **p;
+ FILE *fp = (FILE *)userData;
+ puttc(T('<'), fp);
+ fputts(name, fp);
+
+ p = atts;
+ while (*p)
+ ++p;
+ nAtts = (int)((p - atts) >> 1);
+ if (nAtts > 1)
+ qsort((void *)atts, nAtts, sizeof(XML_Char *) * 2, attcmp);
+ while (*atts) {
+ puttc(T(' '), fp);
+ fputts(*atts++, fp);
+ attributeValue(fp, *atts);
+ atts++;
+ }
+ puttc(T('>'), fp);
+}
+
+static void XMLCALL
+endElement(void *userData, const XML_Char *name)
+{
+ FILE *fp = (FILE *)userData;
+ puttc(T('<'), fp);
+ puttc(T('/'), fp);
+ fputts(name, fp);
+ puttc(T('>'), fp);
+}
+
+static int
+nsattcmp(const void *p1, const void *p2)
+{
+ const XML_Char *att1 = *(const XML_Char **)p1;
+ const XML_Char *att2 = *(const XML_Char **)p2;
+ int sep1 = (tcsrchr(att1, NSSEP) != 0);
+ int sep2 = (tcsrchr(att1, NSSEP) != 0);
+ if (sep1 != sep2)
+ return sep1 - sep2;
+ return tcscmp(att1, att2);
+}
+
+static void XMLCALL
+startElementNS(void *userData, const XML_Char *name, const XML_Char **atts)
+{
+ int nAtts;
+ int nsi;
+ const XML_Char **p;
+ FILE *fp = (FILE *)userData;
+ const XML_Char *sep;
+ puttc(T('<'), fp);
+
+ sep = tcsrchr(name, NSSEP);
+ if (sep) {
+ fputts(T("n1:"), fp);
+ fputts(sep + 1, fp);
+ fputts(T(" xmlns:n1"), fp);
+ attributeValue(fp, name);
+ nsi = 2;
+ }
+ else {
+ fputts(name, fp);
+ nsi = 1;
+ }
+
+ p = atts;
+ while (*p)
+ ++p;
+ nAtts = (int)((p - atts) >> 1);
+ if (nAtts > 1)
+ qsort((void *)atts, nAtts, sizeof(XML_Char *) * 2, nsattcmp);
+ while (*atts) {
+ name = *atts++;
+ sep = tcsrchr(name, NSSEP);
+ puttc(T(' '), fp);
+ if (sep) {
+ ftprintf(fp, T("n%d:"), nsi);
+ fputts(sep + 1, fp);
+ }
+ else
+ fputts(name, fp);
+ attributeValue(fp, *atts);
+ if (sep) {
+ ftprintf(fp, T(" xmlns:n%d"), nsi++);
+ attributeValue(fp, name);
+ }
+ atts++;
+ }
+ puttc(T('>'), fp);
+}
+
+static void XMLCALL
+endElementNS(void *userData, const XML_Char *name)
+{
+ FILE *fp = (FILE *)userData;
+ const XML_Char *sep;
+ puttc(T('<'), fp);
+ puttc(T('/'), fp);
+ sep = tcsrchr(name, NSSEP);
+ if (sep) {
+ fputts(T("n1:"), fp);
+ fputts(sep + 1, fp);
+ }
+ else
+ fputts(name, fp);
+ puttc(T('>'), fp);
+}
+
+#ifndef W3C14N
+
+static void XMLCALL
+processingInstruction(void *userData, const XML_Char *target,
+ const XML_Char *data)
+{
+ FILE *fp = (FILE *)userData;
+ puttc(T('<'), fp);
+ puttc(T('?'), fp);
+ fputts(target, fp);
+ puttc(T(' '), fp);
+ fputts(data, fp);
+ puttc(T('?'), fp);
+ puttc(T('>'), fp);
+}
+
+#endif /* not W3C14N */
+
+static void XMLCALL
+defaultCharacterData(void *userData, const XML_Char *s, int len)
+{
+ XML_DefaultCurrent((XML_Parser) userData);
+}
+
+static void XMLCALL
+defaultStartElement(void *userData, const XML_Char *name,
+ const XML_Char **atts)
+{
+ XML_DefaultCurrent((XML_Parser) userData);
+}
+
+static void XMLCALL
+defaultEndElement(void *userData, const XML_Char *name)
+{
+ XML_DefaultCurrent((XML_Parser) userData);
+}
+
+static void XMLCALL
+defaultProcessingInstruction(void *userData, const XML_Char *target,
+ const XML_Char *data)
+{
+ XML_DefaultCurrent((XML_Parser) userData);
+}
+
+static void XMLCALL
+nopCharacterData(void *userData, const XML_Char *s, int len)
+{
+}
+
+static void XMLCALL
+nopStartElement(void *userData, const XML_Char *name, const XML_Char **atts)
+{
+}
+
+static void XMLCALL
+nopEndElement(void *userData, const XML_Char *name)
+{
+}
+
+static void XMLCALL
+nopProcessingInstruction(void *userData, const XML_Char *target,
+ const XML_Char *data)
+{
+}
+
+static void XMLCALL
+markup(void *userData, const XML_Char *s, int len)
+{
+ FILE *fp = (FILE *)XML_GetUserData((XML_Parser) userData);
+ for (; len > 0; --len, ++s)
+ puttc(*s, fp);
+}
+
+static void
+metaLocation(XML_Parser parser)
+{
+ const XML_Char *uri = XML_GetBase(parser);
+ if (uri)
+ ftprintf((FILE *)XML_GetUserData(parser), T(" uri=\"%s\""), uri);
+ ftprintf((FILE *)XML_GetUserData(parser),
+ T(" byte=\"%" XML_FMT_INT_MOD "d\" nbytes=\"%d\" \
+ line=\"%" XML_FMT_INT_MOD "u\" col=\"%" XML_FMT_INT_MOD "u\""),
+ XML_GetCurrentByteIndex(parser),
+ XML_GetCurrentByteCount(parser),
+ XML_GetCurrentLineNumber(parser),
+ XML_GetCurrentColumnNumber(parser));
+}
+
+static void
+metaStartDocument(void *userData)
+{
+ fputts(T("<document>\n"), (FILE *)XML_GetUserData((XML_Parser) userData));
+}
+
+static void
+metaEndDocument(void *userData)
+{
+ fputts(T("</document>\n"), (FILE *)XML_GetUserData((XML_Parser) userData));
+}
+
+static void XMLCALL
+metaStartElement(void *userData, const XML_Char *name,
+ const XML_Char **atts)
+{
+ XML_Parser parser = (XML_Parser) userData;
+ FILE *fp = (FILE *)XML_GetUserData(parser);
+ const XML_Char **specifiedAttsEnd
+ = atts + XML_GetSpecifiedAttributeCount(parser);
+ const XML_Char **idAttPtr;
+ int idAttIndex = XML_GetIdAttributeIndex(parser);
+ if (idAttIndex < 0)
+ idAttPtr = 0;
+ else
+ idAttPtr = atts + idAttIndex;
+
+ ftprintf(fp, T("<starttag name=\"%s\""), name);
+ metaLocation(parser);
+ if (*atts) {
+ fputts(T(">\n"), fp);
+ do {
+ ftprintf(fp, T("<attribute name=\"%s\" value=\""), atts[0]);
+ characterData(fp, atts[1], (int)tcslen(atts[1]));
+ if (atts >= specifiedAttsEnd)
+ fputts(T("\" defaulted=\"yes\"/>\n"), fp);
+ else if (atts == idAttPtr)
+ fputts(T("\" id=\"yes\"/>\n"), fp);
+ else
+ fputts(T("\"/>\n"), fp);
+ } while (*(atts += 2));
+ fputts(T("</starttag>\n"), fp);
+ }
+ else
+ fputts(T("/>\n"), fp);
+}
+
+static void XMLCALL
+metaEndElement(void *userData, const XML_Char *name)
+{
+ XML_Parser parser = (XML_Parser) userData;
+ FILE *fp = (FILE *)XML_GetUserData(parser);
+ ftprintf(fp, T("<endtag name=\"%s\""), name);
+ metaLocation(parser);
+ fputts(T("/>\n"), fp);
+}
+
+static void XMLCALL
+metaProcessingInstruction(void *userData, const XML_Char *target,
+ const XML_Char *data)
+{
+ XML_Parser parser = (XML_Parser) userData;
+ FILE *fp = (FILE *)XML_GetUserData(parser);
+ ftprintf(fp, T("<pi target=\"%s\" data=\""), target);
+ characterData(fp, data, (int)tcslen(data));
+ puttc(T('"'), fp);
+ metaLocation(parser);
+ fputts(T("/>\n"), fp);
+}
+
+static void XMLCALL
+metaComment(void *userData, const XML_Char *data)
+{
+ XML_Parser parser = (XML_Parser) userData;
+ FILE *fp = (FILE *)XML_GetUserData(parser);
+ fputts(T("<comment data=\""), fp);
+ characterData(fp, data, (int)tcslen(data));
+ puttc(T('"'), fp);
+ metaLocation(parser);
+ fputts(T("/>\n"), fp);
+}
+
+static void XMLCALL
+metaStartCdataSection(void *userData)
+{
+ XML_Parser parser = (XML_Parser) userData;
+ FILE *fp = (FILE *)XML_GetUserData(parser);
+ fputts(T("<startcdata"), fp);
+ metaLocation(parser);
+ fputts(T("/>\n"), fp);
+}
+
+static void XMLCALL
+metaEndCdataSection(void *userData)
+{
+ XML_Parser parser = (XML_Parser) userData;
+ FILE *fp = (FILE *)XML_GetUserData(parser);
+ fputts(T("<endcdata"), fp);
+ metaLocation(parser);
+ fputts(T("/>\n"), fp);
+}
+
+static void XMLCALL
+metaCharacterData(void *userData, const XML_Char *s, int len)
+{
+ XML_Parser parser = (XML_Parser) userData;
+ FILE *fp = (FILE *)XML_GetUserData(parser);
+ fputts(T("<chars str=\""), fp);
+ characterData(fp, s, len);
+ puttc(T('"'), fp);
+ metaLocation(parser);
+ fputts(T("/>\n"), fp);
+}
+
+static void XMLCALL
+metaStartDoctypeDecl(void *userData,
+ const XML_Char *doctypeName,
+ const XML_Char *sysid,
+ const XML_Char *pubid,
+ int has_internal_subset)
+{
+ XML_Parser parser = (XML_Parser) userData;
+ FILE *fp = (FILE *)XML_GetUserData(parser);
+ ftprintf(fp, T("<startdoctype name=\"%s\""), doctypeName);
+ metaLocation(parser);
+ fputts(T("/>\n"), fp);
+}
+
+static void XMLCALL
+metaEndDoctypeDecl(void *userData)
+{
+ XML_Parser parser = (XML_Parser) userData;
+ FILE *fp = (FILE *)XML_GetUserData(parser);
+ fputts(T("<enddoctype"), fp);
+ metaLocation(parser);
+ fputts(T("/>\n"), fp);
+}
+
+static void XMLCALL
+metaNotationDecl(void *userData,
+ const XML_Char *notationName,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId)
+{
+ XML_Parser parser = (XML_Parser) userData;
+ FILE *fp = (FILE *)XML_GetUserData(parser);
+ ftprintf(fp, T("<notation name=\"%s\""), notationName);
+ if (publicId)
+ ftprintf(fp, T(" public=\"%s\""), publicId);
+ if (systemId) {
+ fputts(T(" system=\""), fp);
+ characterData(fp, systemId, (int)tcslen(systemId));
+ puttc(T('"'), fp);
+ }
+ metaLocation(parser);
+ fputts(T("/>\n"), fp);
+}
+
+
+static void XMLCALL
+metaEntityDecl(void *userData,
+ const XML_Char *entityName,
+ int is_param,
+ const XML_Char *value,
+ int value_length,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId,
+ const XML_Char *notationName)
+{
+ XML_Parser parser = (XML_Parser) userData;
+ FILE *fp = (FILE *)XML_GetUserData(parser);
+
+ if (value) {
+ ftprintf(fp, T("<entity name=\"%s\""), entityName);
+ metaLocation(parser);
+ puttc(T('>'), fp);
+ characterData(fp, value, value_length);
+ fputts(T("</entity/>\n"), fp);
+ }
+ else if (notationName) {
+ ftprintf(fp, T("<entity name=\"%s\""), entityName);
+ if (publicId)
+ ftprintf(fp, T(" public=\"%s\""), publicId);
+ fputts(T(" system=\""), fp);
+ characterData(fp, systemId, (int)tcslen(systemId));
+ puttc(T('"'), fp);
+ ftprintf(fp, T(" notation=\"%s\""), notationName);
+ metaLocation(parser);
+ fputts(T("/>\n"), fp);
+ }
+ else {
+ ftprintf(fp, T("<entity name=\"%s\""), entityName);
+ if (publicId)
+ ftprintf(fp, T(" public=\"%s\""), publicId);
+ fputts(T(" system=\""), fp);
+ characterData(fp, systemId, (int)tcslen(systemId));
+ puttc(T('"'), fp);
+ metaLocation(parser);
+ fputts(T("/>\n"), fp);
+ }
+}
+
+static void XMLCALL
+metaStartNamespaceDecl(void *userData,
+ const XML_Char *prefix,
+ const XML_Char *uri)
+{
+ XML_Parser parser = (XML_Parser) userData;
+ FILE *fp = (FILE *)XML_GetUserData(parser);
+ fputts(T("<startns"), fp);
+ if (prefix)
+ ftprintf(fp, T(" prefix=\"%s\""), prefix);
+ if (uri) {
+ fputts(T(" ns=\""), fp);
+ characterData(fp, uri, (int)tcslen(uri));
+ fputts(T("\"/>\n"), fp);
+ }
+ else
+ fputts(T("/>\n"), fp);
+}
+
+static void XMLCALL
+metaEndNamespaceDecl(void *userData, const XML_Char *prefix)
+{
+ XML_Parser parser = (XML_Parser) userData;
+ FILE *fp = (FILE *)XML_GetUserData(parser);
+ if (!prefix)
+ fputts(T("<endns/>\n"), fp);
+ else
+ ftprintf(fp, T("<endns prefix=\"%s\"/>\n"), prefix);
+}
+
+static int XMLCALL
+unknownEncodingConvert(void *data, const char *p)
+{
+ return codepageConvert(*(int *)data, p);
+}
+
+static int XMLCALL
+unknownEncoding(void *userData, const XML_Char *name, XML_Encoding *info)
+{
+ int cp;
+ static const XML_Char prefixL[] = T("windows-");
+ static const XML_Char prefixU[] = T("WINDOWS-");
+ int i;
+
+ for (i = 0; prefixU[i]; i++)
+ if (name[i] != prefixU[i] && name[i] != prefixL[i])
+ return 0;
+
+ cp = 0;
+ for (; name[i]; i++) {
+ static const XML_Char digits[] = T("0123456789");
+ const XML_Char *s = tcschr(digits, name[i]);
+ if (!s)
+ return 0;
+ cp *= 10;
+ cp += (int)(s - digits);
+ if (cp >= 0x10000)
+ return 0;
+ }
+ if (!codepageMap(cp, info->map))
+ return 0;
+ info->convert = unknownEncodingConvert;
+ /* We could just cast the code page integer to a void *,
+ and avoid the use of release. */
+ info->release = free;
+ info->data = malloc(sizeof(int));
+ if (!info->data)
+ return 0;
+ *(int *)info->data = cp;
+ return 1;
+}
+
+static int XMLCALL
+notStandalone(void *userData)
+{
+ return 0;
+}
+
+static void
+showVersion(XML_Char *prog)
+{
+ XML_Char *s = prog;
+ XML_Char ch;
+ const XML_Feature *features = XML_GetFeatureList();
+ while ((ch = *s) != 0) {
+ if (ch == '/'
+#if (defined(WIN32) || defined(__WATCOMC__))
+ || ch == '\\'
+#endif
+ )
+ prog = s + 1;
+ ++s;
+ }
+ ftprintf(stdout, T("%s using %s\n"), prog, XML_ExpatVersion());
+ if (features != NULL && features[0].feature != XML_FEATURE_END) {
+ int i = 1;
+ ftprintf(stdout, T("%s"), features[0].name);
+ if (features[0].value)
+ ftprintf(stdout, T("=%ld"), features[0].value);
+ while (features[i].feature != XML_FEATURE_END) {
+ ftprintf(stdout, T(", %s"), features[i].name);
+ if (features[i].value)
+ ftprintf(stdout, T("=%ld"), features[i].value);
+ ++i;
+ }
+ ftprintf(stdout, T("\n"));
+ }
+}
+
+static void
+usage(const XML_Char *prog, int rc)
+{
+ ftprintf(stderr,
+ T("usage: %s [-n] [-p] [-r] [-s] [-w] [-x] [-d output-dir] "
+ "[-e encoding] file ...\n"), prog);
+ exit(rc);
+}
+
+int
+tmain(int argc, XML_Char **argv)
+{
+ int i, j;
+ const XML_Char *outputDir = NULL;
+ const XML_Char *encoding = NULL;
+ unsigned processFlags = XML_MAP_FILE;
+ int windowsCodePages = 0;
+ int outputType = 0;
+ int useNamespaces = 0;
+ int requireStandalone = 0;
+ enum XML_ParamEntityParsing paramEntityParsing =
+ XML_PARAM_ENTITY_PARSING_NEVER;
+ int useStdin = 0;
+
+#ifdef _MSC_VER
+ _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
+#endif
+
+ i = 1;
+ j = 0;
+ while (i < argc) {
+ if (j == 0) {
+ if (argv[i][0] != T('-'))
+ break;
+ if (argv[i][1] == T('-') && argv[i][2] == T('\0')) {
+ i++;
+ break;
+ }
+ j++;
+ }
+ switch (argv[i][j]) {
+ case T('r'):
+ processFlags &= ~XML_MAP_FILE;
+ j++;
+ break;
+ case T('s'):
+ requireStandalone = 1;
+ j++;
+ break;
+ case T('n'):
+ useNamespaces = 1;
+ j++;
+ break;
+ case T('p'):
+ paramEntityParsing = XML_PARAM_ENTITY_PARSING_ALWAYS;
+ /* fall through */
+ case T('x'):
+ processFlags |= XML_EXTERNAL_ENTITIES;
+ j++;
+ break;
+ case T('w'):
+ windowsCodePages = 1;
+ j++;
+ break;
+ case T('m'):
+ outputType = 'm';
+ j++;
+ break;
+ case T('c'):
+ outputType = 'c';
+ useNamespaces = 0;
+ j++;
+ break;
+ case T('t'):
+ outputType = 't';
+ j++;
+ break;
+ case T('d'):
+ if (argv[i][j + 1] == T('\0')) {
+ if (++i == argc)
+ usage(argv[0], 2);
+ outputDir = argv[i];
+ }
+ else
+ outputDir = argv[i] + j + 1;
+ i++;
+ j = 0;
+ break;
+ case T('e'):
+ if (argv[i][j + 1] == T('\0')) {
+ if (++i == argc)
+ usage(argv[0], 2);
+ encoding = argv[i];
+ }
+ else
+ encoding = argv[i] + j + 1;
+ i++;
+ j = 0;
+ break;
+ case T('h'):
+ usage(argv[0], 0);
+ return 0;
+ case T('v'):
+ showVersion(argv[0]);
+ return 0;
+ case T('\0'):
+ if (j > 1) {
+ i++;
+ j = 0;
+ break;
+ }
+ /* fall through */
+ default:
+ usage(argv[0], 2);
+ }
+ }
+ if (i == argc) {
+ useStdin = 1;
+ processFlags &= ~XML_MAP_FILE;
+ i--;
+ }
+ for (; i < argc; i++) {
+ FILE *fp = 0;
+ XML_Char *outName = 0;
+ int result;
+ XML_Parser parser;
+ if (useNamespaces)
+ parser = XML_ParserCreateNS(encoding, NSSEP);
+ else
+ parser = XML_ParserCreate(encoding);
+ if (requireStandalone)
+ XML_SetNotStandaloneHandler(parser, notStandalone);
+ XML_SetParamEntityParsing(parser, paramEntityParsing);
+ if (outputType == 't') {
+ /* This is for doing timings; this gives a more realistic estimate of
+ the parsing time. */
+ outputDir = 0;
+ XML_SetElementHandler(parser, nopStartElement, nopEndElement);
+ XML_SetCharacterDataHandler(parser, nopCharacterData);
+ XML_SetProcessingInstructionHandler(parser, nopProcessingInstruction);
+ }
+ else if (outputDir) {
+ const XML_Char * delim = T("/");
+ const XML_Char *file = useStdin ? T("STDIN") : argv[i];
+ if (!useStdin) {
+ /* Jump after last (back)slash */
+ const XML_Char * lastDelim = tcsrchr(file, delim[0]);
+ if (lastDelim)
+ file = lastDelim + 1;
+#if (defined(WIN32) || defined(__WATCOMC__))
+ else {
+ const XML_Char * winDelim = T("\\");
+ lastDelim = tcsrchr(file, winDelim[0]);
+ if (lastDelim) {
+ file = lastDelim + 1;
+ delim = winDelim;
+ }
+ }
+#endif
+ }
+ outName = (XML_Char *)malloc((tcslen(outputDir) + tcslen(file) + 2)
+ * sizeof(XML_Char));
+ tcscpy(outName, outputDir);
+ tcscat(outName, delim);
+ tcscat(outName, file);
+ fp = tfopen(outName, T("wb"));
+ if (!fp) {
+ tperror(outName);
+ exit(1);
+ }
+ setvbuf(fp, NULL, _IOFBF, 16384);
+#ifdef XML_UNICODE
+ puttc(0xFEFF, fp);
+#endif
+ XML_SetUserData(parser, fp);
+ switch (outputType) {
+ case 'm':
+ XML_UseParserAsHandlerArg(parser);
+ XML_SetElementHandler(parser, metaStartElement, metaEndElement);
+ XML_SetProcessingInstructionHandler(parser, metaProcessingInstruction);
+ XML_SetCommentHandler(parser, metaComment);
+ XML_SetCdataSectionHandler(parser, metaStartCdataSection,
+ metaEndCdataSection);
+ XML_SetCharacterDataHandler(parser, metaCharacterData);
+ XML_SetDoctypeDeclHandler(parser, metaStartDoctypeDecl,
+ metaEndDoctypeDecl);
+ XML_SetEntityDeclHandler(parser, metaEntityDecl);
+ XML_SetNotationDeclHandler(parser, metaNotationDecl);
+ XML_SetNamespaceDeclHandler(parser, metaStartNamespaceDecl,
+ metaEndNamespaceDecl);
+ metaStartDocument(parser);
+ break;
+ case 'c':
+ XML_UseParserAsHandlerArg(parser);
+ XML_SetDefaultHandler(parser, markup);
+ XML_SetElementHandler(parser, defaultStartElement, defaultEndElement);
+ XML_SetCharacterDataHandler(parser, defaultCharacterData);
+ XML_SetProcessingInstructionHandler(parser,
+ defaultProcessingInstruction);
+ break;
+ default:
+ if (useNamespaces)
+ XML_SetElementHandler(parser, startElementNS, endElementNS);
+ else
+ XML_SetElementHandler(parser, startElement, endElement);
+ XML_SetCharacterDataHandler(parser, characterData);
+#ifndef W3C14N
+ XML_SetProcessingInstructionHandler(parser, processingInstruction);
+#endif /* not W3C14N */
+ break;
+ }
+ }
+ if (windowsCodePages)
+ XML_SetUnknownEncodingHandler(parser, unknownEncoding, 0);
+ result = XML_ProcessFile(parser, useStdin ? NULL : argv[i], processFlags);
+ if (outputDir) {
+ if (outputType == 'm')
+ metaEndDocument(parser);
+ fclose(fp);
+ if (!result) {
+ tremove(outName);
+ exit(2);
+ }
+ free(outName);
+ }
+ XML_ParserFree(parser);
+ }
+ return 0;
+}
diff --git a/expat/xmlwf/xmlwf.dsp b/expat/xmlwf/xmlwf.dsp
new file mode 100644
index 000000000..52f4eec71
--- /dev/null
+++ b/expat/xmlwf/xmlwf.dsp
@@ -0,0 +1,139 @@
+# Microsoft Developer Studio Project File - Name="xmlwf" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=xmlwf - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "xmlwf.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "xmlwf.mak" CFG="xmlwf - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "xmlwf - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "xmlwf - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "xmlwf - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ".\Release"
+# PROP BASE Intermediate_Dir ".\Release"
+# PROP BASE Target_Dir "."
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\win32\bin\Release"
+# PROP Intermediate_Dir "..\win32\tmp\Release-xmlwf"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir "."
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\lib" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "COMPILED_FROM_DSP" /FD /c
+# SUBTRACT CPP /YX /Yc /Yu
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:console /machine:I386
+# ADD LINK32 libexpat.lib setargv.obj /nologo /subsystem:console /pdb:none /machine:I386 /libpath:"..\win32\bin\Release" /out:"..\win32\bin\Release\xmlwf.exe"
+# SUBTRACT LINK32 /nodefaultlib
+
+!ELSEIF "$(CFG)" == "xmlwf - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ".\Debug"
+# PROP BASE Intermediate_Dir ".\Debug"
+# PROP BASE Target_Dir "."
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\win32\bin\Debug"
+# PROP Intermediate_Dir "..\win32\tmp\Debug-xmlwf"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir "."
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MTd /W3 /GX /ZI /Od /I "..\lib" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "COMPILED_FROM_DSP" /FD /c
+# SUBTRACT CPP /Fr /YX
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:console /debug /machine:I386
+# ADD LINK32 libexpat.lib setargv.obj /nologo /subsystem:console /pdb:none /debug /machine:I386 /libpath:"..\win32\bin\Debug" /out:"..\win32\bin\Debug\xmlwf.exe"
+
+!ENDIF
+
+# Begin Target
+
+# Name "xmlwf - Win32 Release"
+# Name "xmlwf - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"
+# Begin Source File
+
+SOURCE=.\codepage.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\readfilemap.c
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE=.\unixfilemap.c
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE=.\win32filemap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmlfile.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmlwf.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
+# Begin Source File
+
+SOURCE=.\codepage.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmlfile.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmltchar.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/expat/xmlwf/xmlwin32url.cxx b/expat/xmlwf/xmlwin32url.cxx
new file mode 100644
index 000000000..bbfcce22c
--- /dev/null
+++ b/expat/xmlwf/xmlwin32url.cxx
@@ -0,0 +1,395 @@
+#include "expat.h"
+#ifdef XML_UNICODE
+#define UNICODE
+#endif
+#include <windows.h>
+#include <urlmon.h>
+#include <wininet.h>
+#include <stdio.h>
+#include <tchar.h>
+#include "xmlurl.h"
+#include "xmlmime.h"
+
+static int
+processURL(XML_Parser parser, IMoniker *baseMoniker, const XML_Char *url);
+
+typedef void (*StopHandler)(void *, HRESULT);
+
+class Callback : public IBindStatusCallback {
+public:
+ // IUnknown methods
+ STDMETHODIMP QueryInterface(REFIID,void **);
+ STDMETHODIMP_(ULONG) AddRef();
+ STDMETHODIMP_(ULONG) Release();
+ // IBindStatusCallback methods
+ STDMETHODIMP OnStartBinding(DWORD, IBinding *);
+ STDMETHODIMP GetPriority(LONG *);
+ STDMETHODIMP OnLowResource(DWORD);
+ STDMETHODIMP OnProgress(ULONG, ULONG, ULONG, LPCWSTR);
+ STDMETHODIMP OnStopBinding(HRESULT, LPCWSTR);
+ STDMETHODIMP GetBindInfo(DWORD *, BINDINFO *);
+ STDMETHODIMP OnDataAvailable(DWORD, DWORD, FORMATETC *, STGMEDIUM *);
+ STDMETHODIMP OnObjectAvailable(REFIID, IUnknown *);
+ Callback(XML_Parser, IMoniker *, StopHandler, void *);
+ ~Callback();
+ int externalEntityRef(const XML_Char *context,
+ const XML_Char *systemId, const XML_Char *publicId);
+private:
+ XML_Parser parser_;
+ IMoniker *baseMoniker_;
+ DWORD totalRead_;
+ ULONG ref_;
+ IBinding *pBinding_;
+ StopHandler stopHandler_;
+ void *stopArg_;
+};
+
+STDMETHODIMP_(ULONG)
+Callback::AddRef()
+{
+ return ref_++;
+}
+
+STDMETHODIMP_(ULONG)
+Callback::Release()
+{
+ if (--ref_ == 0) {
+ delete this;
+ return 0;
+ }
+ return ref_;
+}
+
+STDMETHODIMP
+Callback::QueryInterface(REFIID riid, void** ppv)
+{
+ if (IsEqualGUID(riid, IID_IUnknown))
+ *ppv = (IUnknown *)this;
+ else if (IsEqualGUID(riid, IID_IBindStatusCallback))
+ *ppv = (IBindStatusCallback *)this;
+ else
+ return E_NOINTERFACE;
+ ((LPUNKNOWN)*ppv)->AddRef();
+ return S_OK;
+}
+
+STDMETHODIMP
+Callback::OnStartBinding(DWORD, IBinding* pBinding)
+{
+ pBinding_ = pBinding;
+ pBinding->AddRef();
+ return S_OK;
+}
+
+STDMETHODIMP
+Callback::GetPriority(LONG *)
+{
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP
+Callback::OnLowResource(DWORD)
+{
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP
+Callback::OnProgress(ULONG, ULONG, ULONG, LPCWSTR)
+{
+ return S_OK;
+}
+
+STDMETHODIMP
+Callback::OnStopBinding(HRESULT hr, LPCWSTR szError)
+{
+ if (pBinding_) {
+ pBinding_->Release();
+ pBinding_ = 0;
+ }
+ if (baseMoniker_) {
+ baseMoniker_->Release();
+ baseMoniker_ = 0;
+ }
+ stopHandler_(stopArg_, hr);
+ return S_OK;
+}
+
+STDMETHODIMP
+Callback::GetBindInfo(DWORD* pgrfBINDF, BINDINFO* pbindinfo)
+{
+ *pgrfBINDF = BINDF_ASYNCHRONOUS;
+ return S_OK;
+}
+
+static void
+reportError(XML_Parser parser)
+{
+ int code = XML_GetErrorCode(parser);
+ const XML_Char *message = XML_ErrorString(code);
+ if (message)
+ _ftprintf(stderr, _T("%s:%d:%ld: %s\n"),
+ XML_GetBase(parser),
+ XML_GetErrorLineNumber(parser),
+ XML_GetErrorColumnNumber(parser),
+ message);
+ else
+ _ftprintf(stderr, _T("%s: (unknown message %d)\n"),
+ XML_GetBase(parser), code);
+}
+
+STDMETHODIMP
+Callback::OnDataAvailable(DWORD grfBSCF,
+ DWORD dwSize,
+ FORMATETC *pfmtetc,
+ STGMEDIUM* pstgmed)
+{
+ if (grfBSCF & BSCF_FIRSTDATANOTIFICATION) {
+ IWinInetHttpInfo *hp;
+ HRESULT hr = pBinding_->QueryInterface(IID_IWinInetHttpInfo,
+ (void **)&hp);
+ if (SUCCEEDED(hr)) {
+ char contentType[1024];
+ DWORD bufSize = sizeof(contentType);
+ DWORD flags = 0;
+ contentType[0] = 0;
+ hr = hp->QueryInfo(HTTP_QUERY_CONTENT_TYPE, contentType,
+ &bufSize, 0, NULL);
+ if (SUCCEEDED(hr)) {
+ char charset[CHARSET_MAX];
+ getXMLCharset(contentType, charset);
+ if (charset[0]) {
+#ifdef XML_UNICODE
+ XML_Char wcharset[CHARSET_MAX];
+ XML_Char *p1 = wcharset;
+ const char *p2 = charset;
+ while ((*p1++ = (unsigned char)*p2++) != 0)
+ ;
+ XML_SetEncoding(parser_, wcharset);
+#else
+ XML_SetEncoding(parser_, charset);
+#endif
+ }
+ }
+ hp->Release();
+ }
+ }
+ if (!parser_)
+ return E_ABORT;
+ if (pstgmed->tymed == TYMED_ISTREAM) {
+ while (totalRead_ < dwSize) {
+#define READ_MAX (64*1024)
+ DWORD nToRead = dwSize - totalRead_;
+ if (nToRead > READ_MAX)
+ nToRead = READ_MAX;
+ void *buf = XML_GetBuffer(parser_, nToRead);
+ if (!buf) {
+ _ftprintf(stderr, _T("out of memory\n"));
+ return E_ABORT;
+ }
+ DWORD nRead;
+ HRESULT hr = pstgmed->pstm->Read(buf, nToRead, &nRead);
+ if (SUCCEEDED(hr)) {
+ totalRead_ += nRead;
+ if (!XML_ParseBuffer(parser_,
+ nRead,
+ (grfBSCF & BSCF_LASTDATANOTIFICATION) != 0
+ && totalRead_ == dwSize)) {
+ reportError(parser_);
+ return E_ABORT;
+ }
+ }
+ }
+ }
+ return S_OK;
+}
+
+STDMETHODIMP
+Callback::OnObjectAvailable(REFIID, IUnknown *)
+{
+ return S_OK;
+}
+
+int
+Callback::externalEntityRef(const XML_Char *context,
+ const XML_Char *systemId,
+ const XML_Char *publicId)
+{
+ XML_Parser entParser = XML_ExternalEntityParserCreate(parser_, context, 0);
+ XML_SetBase(entParser, systemId);
+ int ret = processURL(entParser, baseMoniker_, systemId);
+ XML_ParserFree(entParser);
+ return ret;
+}
+
+Callback::Callback(XML_Parser parser, IMoniker *baseMoniker,
+ StopHandler stopHandler, void *stopArg)
+: parser_(parser),
+ baseMoniker_(baseMoniker),
+ ref_(0),
+ pBinding_(0),
+ totalRead_(0),
+ stopHandler_(stopHandler),
+ stopArg_(stopArg)
+{
+ if (baseMoniker_)
+ baseMoniker_->AddRef();
+}
+
+Callback::~Callback()
+{
+ if (pBinding_)
+ pBinding_->Release();
+ if (baseMoniker_)
+ baseMoniker_->Release();
+}
+
+static int
+externalEntityRef(void *arg,
+ const XML_Char *context,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId)
+{
+ return ((Callback *)arg)->externalEntityRef(context, systemId, publicId);
+}
+
+
+static HRESULT
+openStream(XML_Parser parser,
+ IMoniker *baseMoniker,
+ const XML_Char *uri,
+ StopHandler stopHandler, void *stopArg)
+{
+ if (!XML_SetBase(parser, uri))
+ return E_OUTOFMEMORY;
+ HRESULT hr;
+ IMoniker *m;
+#ifdef XML_UNICODE
+ hr = CreateURLMoniker(0, uri, &m);
+#else
+ LPWSTR uriw = new wchar_t[strlen(uri) + 1];
+ for (int i = 0;; i++) {
+ uriw[i] = uri[i];
+ if (uriw[i] == 0)
+ break;
+ }
+ hr = CreateURLMoniker(baseMoniker, uriw, &m);
+ delete [] uriw;
+#endif
+ if (FAILED(hr))
+ return hr;
+ IBindStatusCallback *cb = new Callback(parser, m, stopHandler, stopArg);
+ XML_SetExternalEntityRefHandler(parser, externalEntityRef);
+ XML_SetExternalEntityRefHandlerArg(parser, cb);
+ cb->AddRef();
+ IBindCtx *b;
+ if (FAILED(hr = CreateAsyncBindCtx(0, cb, 0, &b))) {
+ cb->Release();
+ m->Release();
+ return hr;
+ }
+ cb->Release();
+ IStream *pStream;
+ hr = m->BindToStorage(b, 0, IID_IStream, (void **)&pStream);
+ if (SUCCEEDED(hr)) {
+ if (pStream)
+ pStream->Release();
+ }
+ if (hr == MK_S_ASYNCHRONOUS)
+ hr = S_OK;
+ m->Release();
+ b->Release();
+ return hr;
+}
+
+struct QuitInfo {
+ const XML_Char *url;
+ HRESULT hr;
+ int stop;
+};
+
+static void
+winPerror(const XML_Char *url, HRESULT hr)
+{
+ LPVOID buf;
+ if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
+ | FORMAT_MESSAGE_FROM_HMODULE,
+ GetModuleHandleA("urlmon.dll"),
+ hr,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &buf,
+ 0,
+ NULL)
+ || FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
+ | FORMAT_MESSAGE_FROM_SYSTEM,
+ 0,
+ hr,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &buf,
+ 0,
+ NULL)) {
+ /* The system error messages seem to end with a newline. */
+ _ftprintf(stderr, _T("%s: %s"), url, buf);
+ fflush(stderr);
+ LocalFree(buf);
+ }
+ else
+ _ftprintf(stderr, _T("%s: error %x\n"), url, hr);
+}
+
+static void
+threadQuit(void *p, HRESULT hr)
+{
+ QuitInfo *qi = (QuitInfo *)p;
+ qi->hr = hr;
+ qi->stop = 1;
+}
+
+extern "C"
+int
+XML_URLInit(void)
+{
+ return SUCCEEDED(CoInitialize(0));
+}
+
+extern "C"
+void
+XML_URLUninit(void)
+{
+ CoUninitialize();
+}
+
+static int
+processURL(XML_Parser parser, IMoniker *baseMoniker,
+ const XML_Char *url)
+{
+ QuitInfo qi;
+ qi.stop = 0;
+ qi.url = url;
+
+ XML_SetBase(parser, url);
+ HRESULT hr = openStream(parser, baseMoniker, url, threadQuit, &qi);
+ if (FAILED(hr)) {
+ winPerror(url, hr);
+ return 0;
+ }
+ else if (FAILED(qi.hr)) {
+ winPerror(url, qi.hr);
+ return 0;
+ }
+ MSG msg;
+ while (!qi.stop && GetMessage (&msg, NULL, 0, 0)) {
+ TranslateMessage (&msg);
+ DispatchMessage (&msg);
+ }
+ return 1;
+}
+
+extern "C"
+int
+XML_ProcessURL(XML_Parser parser,
+ const XML_Char *url,
+ unsigned flags)
+{
+ return processURL(parser, 0, url);
+}