/* This file is part of the KDE project Copyright (C) 2001-2005 Ariya Hidayat This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #ifdef HAVE_UNISTD_H #include #endif #include #include #include #include #include // debug typedef KGenericFactory WPImportFactory; K_EXPORT_COMPONENT_FACTORY( libwpimport, WPImportFactory( "kofficefilters" ) ) #include #include "DocumentHandler.hxx" #include "WordPerfectCollector.hxx" class _SH_MemoryInputStream : public _SH_InputStream { public: _SH_MemoryInputStream(unsigned char *data, unsigned long size); virtual ~_SH_MemoryInputStream(); virtual bool isOLEStream() { return false; } #if defined(HAVE_LIBWPD_0100) || defined(HAVE_LIBWPD_090) virtual _SH_InputStream * getDocumentOLEStream(const char *name = NULL) { return NULL; } const virtual unsigned char *read(unsigned long numBytes, unsigned long &numBytesRead); #else virtual _SH_InputStream * getDocumentOLEStream() { return NULL; } const virtual uint8_t *read(size_t numBytes, size_t &numBytesRead); #endif virtual int seek(long offset, _SH_SEEK_TYPE seekType); virtual long tell(); virtual bool atEOS(); #ifdef HAVE_LIBWPD_0100 virtual bool isStructured() { return false; } virtual unsigned subStreamCount() { return 0U; } virtual const char *subStreamName(unsigned id) { return NULL; } virtual bool existsSubStream(const char *name) { return false; } virtual RVNGInputStream *getSubStreamByName(const char *name) { return NULL; } virtual RVNGInputStream *getSubStreamById(unsigned id) { return NULL; } virtual bool isEnd() { return false; } #endif private: long m_offset; size_t m_size; unsigned char *m_data; }; _SH_MemoryInputStream::_SH_MemoryInputStream(unsigned char *data, unsigned long size) : #if defined(HAVE_LIBWPD_090) || defined(HAVE_LIBWPD_0100) _SH_InputStream(), #else _SH_InputStream(false), #endif m_offset(0), m_size(size), m_data(data) { } _SH_MemoryInputStream::~_SH_MemoryInputStream() { if (m_data) delete [] m_data; } #if defined(HAVE_LIBWPD_090) || defined(HAVE_LIBWPD_0100) const unsigned char * _SH_MemoryInputStream::read(unsigned long numBytes, unsigned long &numBytesRead) #else const uint8_t * _SH_MemoryInputStream::read(size_t numBytes, size_t &numBytesRead) #endif { numBytesRead = 0; if (numBytes == 0) return 0; int numBytesToRead; if ((m_offset+numBytes) < m_size) numBytesToRead = numBytes; else numBytesToRead = m_size - m_offset; numBytesRead = numBytesToRead; // about as paranoid as we can be.. if (numBytesToRead == 0) return 0; long oldOffset = m_offset; m_offset += numBytesToRead; return &m_data[oldOffset]; } int _SH_MemoryInputStream::seek(long offset, _SH_SEEK_TYPE seekType) { if (seekType == _SH_SEEK_CUR) m_offset += offset; else if (seekType == _SH_SEEK_SET) m_offset = offset; if (m_offset < 0) { m_offset = 0; return 1; } if ((long)m_offset > (long)m_size) { m_offset = m_size; return 1; } return 0; } long _SH_MemoryInputStream::tell() { return m_offset; } bool _SH_MemoryInputStream::atEOS() { if ((long)m_offset == (long)m_size) return true; return false; } class KWordHandler : public DocumentHandler { public: KWordHandler(); virtual ~KWordHandler() {}; void startDocument(); void endDocument(); void startElement(const char *psName, const _SH_PropertyList &xPropList); void endElement(const char *psName); void characters(const _SH_String &sCharacters); _SH_String documentstring; private: bool isTagOpened; _SH_String openedTagName; }; KWordHandler::KWordHandler() : isTagOpened(false) { } void KWordHandler::startDocument() { documentstring.clear(); } void KWordHandler::startElement(const char *psName, const _SH_PropertyList &xPropList) { if (isTagOpened) { documentstring.append( ">" ); isTagOpened = false; } _SH_String tempString; tempString.sprintf("<%s", psName); documentstring.append( tempString ); _SH_PropertyList::Iter i(xPropList); for (i.rewind(); i.next(); ) { // filter out libwpd elements if (strlen(i.key()) > 6 && strncmp(i.key(), "libwpd", 6) != 0) { tempString.sprintf(" %s=\"%s\"", i.key(), i()->getStr().cstr()); documentstring.append( tempString ); } } isTagOpened = true; openedTagName.sprintf("%s", psName); } void KWordHandler::endElement(const char *psName) { if ((isTagOpened) && (openedTagName == psName)) documentstring.append( " />" ); else { _SH_String tempString; tempString.sprintf("", psName); documentstring.append( tempString ); } isTagOpened = false; } void KWordHandler::characters(const _SH_String &sCharacters) { if (isTagOpened) { documentstring.append( ">" ); isTagOpened = false; } #ifdef HAVE_LIBWPD_0100 documentstring.append( _SH_String::escapeXML(sCharacters) ); #else documentstring.append( _SH_String(sCharacters, true) ); #endif } void KWordHandler::endDocument() { if (isTagOpened) { documentstring.append( ">" ); isTagOpened = false; } } WPImport::WPImport( KoFilter *, const char *, const TQStringList& ): KoFilter() { } KoFilter::ConversionStatus WPImport::convert( const TQCString& from, const TQCString& to ) { // check for proper conversion if(to!= "application/vnd.sun.xml.writer" || from != "application/wordperfect" ) return KoFilter::NotImplemented; // open input file const char* infile = m_chain->inputFile().latin1(); FILE *f = fopen( infile, "rb" ); if( !f ) return KoFilter::StupidError; fseek( f, 0, SEEK_END ); long fsize = ftell( f ); fseek( f, 0, SEEK_SET ); unsigned char* buf = new unsigned char[fsize]; fread( buf, 1, fsize, f ); fclose( f ); // instream now owns buf, no need to delete buf later _SH_MemoryInputStream instream = _SH_MemoryInputStream( buf, fsize ); #if defined(HAVE_LIBWPD_0100) libwpd::WPDConfidence confidence = libwpd::WPDocument::isFileFormatSupported(&instream); #elif defined(HAVE_LIBWPD_090) WPDConfidence confidence = WPDocument::isFileFormatSupported(&instream); #else WPDConfidence confidence = WPDocument::isFileFormatSupported(&instream, false); #endif #if defined(HAVE_LIBWPD_0100) if( confidence == libwpd::WPD_CONFIDENCE_NONE ) #else if( confidence == WPD_CONFIDENCE_NONE ) #endif { fprintf(stderr, "ERROR: We have no confidence that you are giving us a valid WordPerfect document.\n"); return KoFilter::StupidError; } instream.seek(0, _SH_SEEK_SET); // open and parse the file KWordHandler handler; WordPerfectCollector collector(&instream, &handler); if ( !collector.filter() ) return KoFilter::StupidError; // prepare storage KoStoreDevice* manifest = m_chain->storageFile( "META-INF/manifest.xml", KoStore::Write ); if ( manifest ) { TQCString manifeststring = "\n\ \n\ \n\ \n\ \n\ \n\ \n"; manifest->writeBlock( (const char*) manifeststring, manifeststring.length() ); } KoStoreDevice* styles = m_chain->storageFile( "styles.xml", KoStore::Write ); if ( styles ) { TQCString stylesstring = "\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ "; styles->writeBlock( (const char*) stylesstring, stylesstring.length() ); } KoStoreDevice* out = m_chain->storageFile( "content.xml", KoStore::Write ); if( out ) out->writeBlock( (const char*) handler.documentstring.cstr(), strlen(handler.documentstring.cstr()) ); return KoFilter::OK; } #include "wpimport.moc"