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 11104349Sphk#ifdef COMPILED_FROM_DSP 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> 21178848Scokane#endif /* ndef COMPILED_FROM_DSP */ 22178848Scokane 23104349Sphk#include "expat.h" 24104349Sphk#include "xmlfile.h" 25104349Sphk#include "xmltchar.h" 26104349Sphk#include "filemap.h" 27104349Sphk 28178848Scokane#if (defined(_MSC_VER) || (defined(__WATCOMC__) && !defined(__LINUX__))) 29104349Sphk#include <io.h> 30104349Sphk#endif 31104349Sphk 32178848Scokane#if defined(__amigaos__) && defined(__USE_INLINE__) 33178848Scokane#include <proto/expat.h> 34178848Scokane#endif 35178848Scokane 36104349Sphk#ifdef HAVE_UNISTD_H 37104349Sphk#include <unistd.h> 38104349Sphk#endif 39104349Sphk 40104349Sphk#ifndef O_BINARY 41104349Sphk#ifdef _O_BINARY 42104349Sphk#define O_BINARY _O_BINARY 43104349Sphk#else 44104349Sphk#define O_BINARY 0 45104349Sphk#endif 46104349Sphk#endif 47104349Sphk 48104349Sphk#ifdef _DEBUG 49104349Sphk#define READ_SIZE 16 50104349Sphk#else 51104349Sphk#define READ_SIZE (1024*8) 52104349Sphk#endif 53104349Sphk 54104349Sphk 55104349Sphktypedef struct { 56104349Sphk XML_Parser parser; 57104349Sphk int *retPtr; 58104349Sphk} PROCESS_ARGS; 59104349Sphk 60104349Sphkstatic void 61104349SphkreportError(XML_Parser parser, const XML_Char *filename) 62104349Sphk{ 63178848Scokane enum XML_Error code = XML_GetErrorCode(parser); 64104349Sphk const XML_Char *message = XML_ErrorString(code); 65104349Sphk if (message) 66178848Scokane ftprintf(stdout, T("%s:%" XML_FMT_INT_MOD "u:%" XML_FMT_INT_MOD "u: %s\n"), 67104349Sphk filename, 68104349Sphk XML_GetErrorLineNumber(parser), 69104349Sphk XML_GetErrorColumnNumber(parser), 70104349Sphk message); 71104349Sphk else 72104349Sphk ftprintf(stderr, T("%s: (unknown message %d)\n"), filename, code); 73104349Sphk} 74178848Scokane 75178848Scokane/* This implementation will give problems on files larger than INT_MAX. */ 76104349Sphkstatic void 77104349SphkprocessFile(const void *data, size_t size, 78104349Sphk const XML_Char *filename, void *args) 79104349Sphk{ 80104349Sphk XML_Parser parser = ((PROCESS_ARGS *)args)->parser; 81104349Sphk int *retPtr = ((PROCESS_ARGS *)args)->retPtr; 82178848Scokane if (XML_Parse(parser, (const char *)data, (int)size, 1) == XML_STATUS_ERROR) { 83104349Sphk reportError(parser, filename); 84104349Sphk *retPtr = 0; 85104349Sphk } 86104349Sphk else 87104349Sphk *retPtr = 1; 88104349Sphk} 89104349Sphk 90178848Scokane#if (defined(WIN32) || defined(__WATCOMC__)) 91104349Sphk 92104349Sphkstatic int 93104349SphkisAsciiLetter(XML_Char c) 94104349Sphk{ 95104349Sphk return (T('a') <= c && c <= T('z')) || (T('A') <= c && c <= T('Z')); 96104349Sphk} 97104349Sphk 98104349Sphk#endif /* WIN32 */ 99104349Sphk 100104349Sphkstatic const XML_Char * 101104349SphkresolveSystemId(const XML_Char *base, const XML_Char *systemId, 102104349Sphk XML_Char **toFree) 103104349Sphk{ 104104349Sphk XML_Char *s; 105104349Sphk *toFree = 0; 106104349Sphk if (!base 107104349Sphk || *systemId == T('/') 108178848Scokane#if (defined(WIN32) || defined(__WATCOMC__)) 109104349Sphk || *systemId == T('\\') 110104349Sphk || (isAsciiLetter(systemId[0]) && systemId[1] == T(':')) 111104349Sphk#endif 112104349Sphk ) 113104349Sphk return systemId; 114104349Sphk *toFree = (XML_Char *)malloc((tcslen(base) + tcslen(systemId) + 2) 115104349Sphk * sizeof(XML_Char)); 116104349Sphk if (!*toFree) 117104349Sphk return systemId; 118104349Sphk tcscpy(*toFree, base); 119104349Sphk s = *toFree; 120104349Sphk if (tcsrchr(s, T('/'))) 121104349Sphk s = tcsrchr(s, T('/')) + 1; 122178848Scokane#if (defined(WIN32) || defined(__WATCOMC__)) 123104349Sphk if (tcsrchr(s, T('\\'))) 124104349Sphk s = tcsrchr(s, T('\\')) + 1; 125104349Sphk#endif 126104349Sphk tcscpy(s, systemId); 127104349Sphk return *toFree; 128104349Sphk} 129104349Sphk 130104349Sphkstatic int 131104349SphkexternalEntityRefFilemap(XML_Parser parser, 132104349Sphk const XML_Char *context, 133104349Sphk const XML_Char *base, 134104349Sphk const XML_Char *systemId, 135104349Sphk const XML_Char *publicId) 136104349Sphk{ 137104349Sphk int result; 138104349Sphk XML_Char *s; 139104349Sphk const XML_Char *filename; 140104349Sphk XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0); 141104349Sphk PROCESS_ARGS args; 142104349Sphk args.retPtr = &result; 143104349Sphk args.parser = entParser; 144104349Sphk filename = resolveSystemId(base, systemId, &s); 145104349Sphk XML_SetBase(entParser, filename); 146104349Sphk if (!filemap(filename, processFile, &args)) 147104349Sphk result = 0; 148104349Sphk free(s); 149104349Sphk XML_ParserFree(entParser); 150104349Sphk return result; 151104349Sphk} 152104349Sphk 153104349Sphkstatic int 154104349SphkprocessStream(const XML_Char *filename, XML_Parser parser) 155104349Sphk{ 156104349Sphk /* passing NULL for filename means read intput from stdin */ 157104349Sphk int fd = 0; /* 0 is the fileno for stdin */ 158104349Sphk 159104349Sphk if (filename != NULL) { 160104349Sphk fd = topen(filename, O_BINARY|O_RDONLY); 161104349Sphk if (fd < 0) { 162104349Sphk tperror(filename); 163104349Sphk return 0; 164104349Sphk } 165104349Sphk } 166104349Sphk for (;;) { 167104349Sphk int nread; 168178848Scokane char *buf = (char *)XML_GetBuffer(parser, READ_SIZE); 169104349Sphk if (!buf) { 170104349Sphk if (filename != NULL) 171104349Sphk close(fd); 172104349Sphk ftprintf(stderr, T("%s: out of memory\n"), 173104349Sphk filename != NULL ? filename : "xmlwf"); 174104349Sphk return 0; 175104349Sphk } 176104349Sphk nread = read(fd, buf, READ_SIZE); 177104349Sphk if (nread < 0) { 178104349Sphk tperror(filename != NULL ? filename : "STDIN"); 179104349Sphk if (filename != NULL) 180104349Sphk close(fd); 181104349Sphk return 0; 182104349Sphk } 183104349Sphk if (XML_ParseBuffer(parser, nread, nread == 0) == XML_STATUS_ERROR) { 184104349Sphk reportError(parser, filename != NULL ? filename : "STDIN"); 185104349Sphk if (filename != NULL) 186104349Sphk close(fd); 187104349Sphk return 0; 188104349Sphk } 189104349Sphk if (nread == 0) { 190104349Sphk if (filename != NULL) 191104349Sphk close(fd); 192104349Sphk break;; 193104349Sphk } 194104349Sphk } 195104349Sphk return 1; 196104349Sphk} 197104349Sphk 198104349Sphkstatic int 199104349SphkexternalEntityRefStream(XML_Parser parser, 200104349Sphk const XML_Char *context, 201104349Sphk const XML_Char *base, 202104349Sphk const XML_Char *systemId, 203104349Sphk const XML_Char *publicId) 204104349Sphk{ 205104349Sphk XML_Char *s; 206104349Sphk const XML_Char *filename; 207104349Sphk int ret; 208104349Sphk XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0); 209104349Sphk filename = resolveSystemId(base, systemId, &s); 210104349Sphk XML_SetBase(entParser, filename); 211104349Sphk ret = processStream(filename, entParser); 212104349Sphk free(s); 213104349Sphk XML_ParserFree(entParser); 214104349Sphk return ret; 215104349Sphk} 216104349Sphk 217104349Sphkint 218104349SphkXML_ProcessFile(XML_Parser parser, 219104349Sphk const XML_Char *filename, 220104349Sphk unsigned flags) 221104349Sphk{ 222104349Sphk int result; 223104349Sphk 224104349Sphk if (!XML_SetBase(parser, filename)) { 225104349Sphk ftprintf(stderr, T("%s: out of memory"), filename); 226104349Sphk exit(1); 227104349Sphk } 228104349Sphk 229104349Sphk if (flags & XML_EXTERNAL_ENTITIES) 230104349Sphk XML_SetExternalEntityRefHandler(parser, 231104349Sphk (flags & XML_MAP_FILE) 232104349Sphk ? externalEntityRefFilemap 233104349Sphk : externalEntityRefStream); 234104349Sphk if (flags & XML_MAP_FILE) { 235104349Sphk PROCESS_ARGS args; 236104349Sphk args.retPtr = &result; 237104349Sphk args.parser = parser; 238104349Sphk if (!filemap(filename, processFile, &args)) 239104349Sphk result = 0; 240104349Sphk } 241104349Sphk else 242104349Sphk result = processStream(filename, parser); 243104349Sphk return result; 244104349Sphk} 245