1104349Sphk/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd 2104349Sphk See the file COPYING for copying permission. 3104349Sphk*/ 4104349Sphk 5104349Sphk#include <stdio.h> 6104349Sphk#include <stdlib.h> 7104349Sphk#include <stddef.h> 8104349Sphk#include <string.h> 9104349Sphk#include <fcntl.h> 10178848Scokane 11302385Sdelphij#ifdef WIN32 12104349Sphk#include "winconfig.h" 13178848Scokane#elif defined(MACOS_CLASSIC) 14178848Scokane#include "macconfig.h" 15178848Scokane#elif defined(__amigaos__) 16178848Scokane#include "amigaconfig.h" 17178848Scokane#elif defined(__WATCOMC__) 18178848Scokane#include "watcomconfig.h" 19178848Scokane#elif defined(HAVE_EXPAT_CONFIG_H) 20178848Scokane#include <expat_config.h> 21302385Sdelphij#endif /* ndef WIN32 */ 22178848Scokane 23104349Sphk#include "expat.h" 24302385Sdelphij#include "internal.h" /* for UNUSED_P only */ 25104349Sphk#include "xmlfile.h" 26104349Sphk#include "xmltchar.h" 27104349Sphk#include "filemap.h" 28104349Sphk 29178848Scokane#if (defined(_MSC_VER) || (defined(__WATCOMC__) && !defined(__LINUX__))) 30104349Sphk#include <io.h> 31104349Sphk#endif 32104349Sphk 33178848Scokane#if defined(__amigaos__) && defined(__USE_INLINE__) 34178848Scokane#include <proto/expat.h> 35178848Scokane#endif 36178848Scokane 37104349Sphk#ifdef HAVE_UNISTD_H 38104349Sphk#include <unistd.h> 39104349Sphk#endif 40104349Sphk 41104349Sphk#ifndef O_BINARY 42104349Sphk#ifdef _O_BINARY 43104349Sphk#define O_BINARY _O_BINARY 44104349Sphk#else 45104349Sphk#define O_BINARY 0 46104349Sphk#endif 47104349Sphk#endif 48104349Sphk 49104349Sphk#ifdef _DEBUG 50104349Sphk#define READ_SIZE 16 51104349Sphk#else 52104349Sphk#define READ_SIZE (1024*8) 53104349Sphk#endif 54104349Sphk 55104349Sphk 56104349Sphktypedef struct { 57104349Sphk XML_Parser parser; 58104349Sphk int *retPtr; 59104349Sphk} PROCESS_ARGS; 60104349Sphk 61104349Sphkstatic void 62104349SphkreportError(XML_Parser parser, const XML_Char *filename) 63104349Sphk{ 64178848Scokane enum XML_Error code = XML_GetErrorCode(parser); 65104349Sphk const XML_Char *message = XML_ErrorString(code); 66104349Sphk if (message) 67178848Scokane ftprintf(stdout, T("%s:%" XML_FMT_INT_MOD "u:%" XML_FMT_INT_MOD "u: %s\n"), 68104349Sphk filename, 69104349Sphk XML_GetErrorLineNumber(parser), 70104349Sphk XML_GetErrorColumnNumber(parser), 71104349Sphk message); 72104349Sphk else 73104349Sphk ftprintf(stderr, T("%s: (unknown message %d)\n"), filename, code); 74104349Sphk} 75178848Scokane 76178848Scokane/* This implementation will give problems on files larger than INT_MAX. */ 77104349Sphkstatic void 78104349SphkprocessFile(const void *data, size_t size, 79104349Sphk const XML_Char *filename, void *args) 80104349Sphk{ 81104349Sphk XML_Parser parser = ((PROCESS_ARGS *)args)->parser; 82104349Sphk int *retPtr = ((PROCESS_ARGS *)args)->retPtr; 83178848Scokane if (XML_Parse(parser, (const char *)data, (int)size, 1) == XML_STATUS_ERROR) { 84104349Sphk reportError(parser, filename); 85104349Sphk *retPtr = 0; 86104349Sphk } 87104349Sphk else 88104349Sphk *retPtr = 1; 89104349Sphk} 90104349Sphk 91178848Scokane#if (defined(WIN32) || defined(__WATCOMC__)) 92104349Sphk 93104349Sphkstatic int 94104349SphkisAsciiLetter(XML_Char c) 95104349Sphk{ 96104349Sphk return (T('a') <= c && c <= T('z')) || (T('A') <= c && c <= T('Z')); 97104349Sphk} 98104349Sphk 99104349Sphk#endif /* WIN32 */ 100104349Sphk 101104349Sphkstatic const XML_Char * 102104349SphkresolveSystemId(const XML_Char *base, const XML_Char *systemId, 103104349Sphk XML_Char **toFree) 104104349Sphk{ 105104349Sphk XML_Char *s; 106104349Sphk *toFree = 0; 107104349Sphk if (!base 108104349Sphk || *systemId == T('/') 109178848Scokane#if (defined(WIN32) || defined(__WATCOMC__)) 110104349Sphk || *systemId == T('\\') 111104349Sphk || (isAsciiLetter(systemId[0]) && systemId[1] == T(':')) 112104349Sphk#endif 113104349Sphk ) 114104349Sphk return systemId; 115104349Sphk *toFree = (XML_Char *)malloc((tcslen(base) + tcslen(systemId) + 2) 116104349Sphk * sizeof(XML_Char)); 117104349Sphk if (!*toFree) 118104349Sphk return systemId; 119104349Sphk tcscpy(*toFree, base); 120104349Sphk s = *toFree; 121104349Sphk if (tcsrchr(s, T('/'))) 122104349Sphk s = tcsrchr(s, T('/')) + 1; 123178848Scokane#if (defined(WIN32) || defined(__WATCOMC__)) 124104349Sphk if (tcsrchr(s, T('\\'))) 125104349Sphk s = tcsrchr(s, T('\\')) + 1; 126104349Sphk#endif 127104349Sphk tcscpy(s, systemId); 128104349Sphk return *toFree; 129104349Sphk} 130104349Sphk 131104349Sphkstatic int 132104349SphkexternalEntityRefFilemap(XML_Parser parser, 133104349Sphk const XML_Char *context, 134104349Sphk const XML_Char *base, 135104349Sphk const XML_Char *systemId, 136302385Sdelphij const XML_Char *UNUSED_P(publicId)) 137104349Sphk{ 138104349Sphk int result; 139104349Sphk XML_Char *s; 140104349Sphk const XML_Char *filename; 141104349Sphk XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0); 142104349Sphk PROCESS_ARGS args; 143104349Sphk args.retPtr = &result; 144104349Sphk args.parser = entParser; 145104349Sphk filename = resolveSystemId(base, systemId, &s); 146104349Sphk XML_SetBase(entParser, filename); 147104349Sphk if (!filemap(filename, processFile, &args)) 148104349Sphk result = 0; 149104349Sphk free(s); 150104349Sphk XML_ParserFree(entParser); 151104349Sphk return result; 152104349Sphk} 153104349Sphk 154104349Sphkstatic int 155104349SphkprocessStream(const XML_Char *filename, XML_Parser parser) 156104349Sphk{ 157104349Sphk /* passing NULL for filename means read intput from stdin */ 158104349Sphk int fd = 0; /* 0 is the fileno for stdin */ 159104349Sphk 160104349Sphk if (filename != NULL) { 161104349Sphk fd = topen(filename, O_BINARY|O_RDONLY); 162104349Sphk if (fd < 0) { 163104349Sphk tperror(filename); 164104349Sphk return 0; 165104349Sphk } 166104349Sphk } 167104349Sphk for (;;) { 168104349Sphk int nread; 169178848Scokane char *buf = (char *)XML_GetBuffer(parser, READ_SIZE); 170104349Sphk if (!buf) { 171104349Sphk if (filename != NULL) 172104349Sphk close(fd); 173104349Sphk ftprintf(stderr, T("%s: out of memory\n"), 174104349Sphk filename != NULL ? filename : "xmlwf"); 175104349Sphk return 0; 176104349Sphk } 177104349Sphk nread = read(fd, buf, READ_SIZE); 178104349Sphk if (nread < 0) { 179104349Sphk tperror(filename != NULL ? filename : "STDIN"); 180104349Sphk if (filename != NULL) 181104349Sphk close(fd); 182104349Sphk return 0; 183104349Sphk } 184104349Sphk if (XML_ParseBuffer(parser, nread, nread == 0) == XML_STATUS_ERROR) { 185104349Sphk reportError(parser, filename != NULL ? filename : "STDIN"); 186104349Sphk if (filename != NULL) 187104349Sphk close(fd); 188104349Sphk return 0; 189104349Sphk } 190104349Sphk if (nread == 0) { 191104349Sphk if (filename != NULL) 192104349Sphk close(fd); 193104349Sphk break;; 194104349Sphk } 195104349Sphk } 196104349Sphk return 1; 197104349Sphk} 198104349Sphk 199104349Sphkstatic int 200104349SphkexternalEntityRefStream(XML_Parser parser, 201104349Sphk const XML_Char *context, 202104349Sphk const XML_Char *base, 203104349Sphk const XML_Char *systemId, 204302385Sdelphij const XML_Char *UNUSED_P(publicId)) 205104349Sphk{ 206104349Sphk XML_Char *s; 207104349Sphk const XML_Char *filename; 208104349Sphk int ret; 209104349Sphk XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0); 210104349Sphk filename = resolveSystemId(base, systemId, &s); 211104349Sphk XML_SetBase(entParser, filename); 212104349Sphk ret = processStream(filename, entParser); 213104349Sphk free(s); 214104349Sphk XML_ParserFree(entParser); 215104349Sphk return ret; 216104349Sphk} 217104349Sphk 218104349Sphkint 219104349SphkXML_ProcessFile(XML_Parser parser, 220104349Sphk const XML_Char *filename, 221104349Sphk unsigned flags) 222104349Sphk{ 223104349Sphk int result; 224104349Sphk 225104349Sphk if (!XML_SetBase(parser, filename)) { 226104349Sphk ftprintf(stderr, T("%s: out of memory"), filename); 227104349Sphk exit(1); 228104349Sphk } 229104349Sphk 230104349Sphk if (flags & XML_EXTERNAL_ENTITIES) 231104349Sphk XML_SetExternalEntityRefHandler(parser, 232104349Sphk (flags & XML_MAP_FILE) 233104349Sphk ? externalEntityRefFilemap 234104349Sphk : externalEntityRefStream); 235104349Sphk if (flags & XML_MAP_FILE) { 236104349Sphk PROCESS_ARGS args; 237104349Sphk args.retPtr = &result; 238104349Sphk args.parser = parser; 239104349Sphk if (!filemap(filename, processFile, &args)) 240104349Sphk result = 0; 241104349Sphk } 242104349Sphk else 243104349Sphk result = processStream(filename, parser); 244104349Sphk return result; 245104349Sphk} 246