/* 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 #ifdef HAVE_LIBWPD_090 #include #define uint8_t uchar #else #include #endif #include "DocumentHandler.hxx" #include "WordPerfectCollector.hxx" #ifdef HAVE_LIBWPD_090 class WPXMemoryInputStream : public WPXInputStream { public: WPXMemoryInputStream(unsigned char *data, unsigned long size); virtual ~WPXMemoryInputStream(); virtual bool isOLEStream() { return false; } virtual WPXInputStream * getDocumentOLEStream(const char *name) { return NULL; } const virtual unsigned char *read(unsigned long numBytes, unsigned long &numBytesRead); virtual int seek(long offset, WPX_SEEK_TYPE seekType); virtual long tell(); virtual bool atEOS(); private: long m_offset; size_t m_size; unsigned char *m_data; }; WPXMemoryInputStream::WPXMemoryInputStream(unsigned char *data, unsigned long size) : WPXInputStream(), m_offset(0), m_size(size), m_data(data) { } WPXMemoryInputStream::~WPXMemoryInputStream() { } const unsigned char * WPXMemoryInputStream::read(unsigned long numBytes, unsigned long &numBytesRead) { 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 WPXMemoryInputStream::seek(long offset, WPX_SEEK_TYPE seekType) { if (seekType == WPX_SEEK_CUR) m_offset += offset; else if (seekType == WPX_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 WPXMemoryInputStream::tell() { return m_offset; } bool WPXMemoryInputStream::atEOS() { if ((long)m_offset == (long)m_size) return true; return false; } #else // HAVE_LIBWPD_090 class WPXMemoryInputStream : public WPXInputStream { public: WPXMemoryInputStream(uint8_t *data, size_t size); virtual ~WPXMemoryInputStream(); virtual bool isOLEStream() { return false; } virtual WPXInputStream * getDocumentOLEStream() { return NULL; } const virtual uint8_t *read(size_t numBytes, size_t &numBytesRead); virtual int seek(long offset, WPX_SEEK_TYPE seekType); virtual long tell(); virtual bool atEOS(); private: long m_offset; size_t m_size; uint8_t *m_data; uint8_t *m_tmpBuf; }; WPXMemoryInputStream::WPXMemoryInputStream(uint8_t *data, size_t size) : #ifdef HAVE_LIBWPD_090 WPXInputStream(), #else WPXInputStream(false), #endif m_offset(0), m_data(data), m_size(size), m_tmpBuf(NULL) { } WPXMemoryInputStream::~WPXMemoryInputStream() { delete [] m_tmpBuf; delete [] m_data; } const uint8_t * WPXMemoryInputStream::read(size_t numBytes, size_t &numBytesRead) { delete [] m_tmpBuf; 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 NULL; m_tmpBuf = new uint8_t[numBytesToRead]; for (size_t i=0; i= m_size) m_offset = m_size; return 0; } long WPXMemoryInputStream::tell() { return m_offset; } bool WPXMemoryInputStream::atEOS() { if (m_offset >= m_size ) return true; return false; } #endif // HAVE_LIBWPD_090 class KWordHandler : public DocumentHandler { public: KWordHandler(); virtual ~KWordHandler() {}; void startDocument(); void endDocument(); void startElement(const char *psName, const WPXPropertyList &xPropList); void endElement(const char *psName); void characters(const WPXString &sCharacters); WPXString documentstring; private: bool isTagOpened; WPXString openedTagName; }; KWordHandler::KWordHandler() : isTagOpened(false) { } void KWordHandler::startDocument() { documentstring.clear(); } void KWordHandler::startElement(const char *psName, const WPXPropertyList &xPropList) { if (isTagOpened) { documentstring.append( ">" ); isTagOpened = false; } WPXString tempString; tempString.sprintf("<%s", psName); documentstring.append( tempString ); WPXPropertyList::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 { WPXString tempString; tempString.sprintf("", psName); documentstring.append( tempString ); } isTagOpened = false; } void KWordHandler::characters(const WPXString &sCharacters) { if (isTagOpened) { documentstring.append( ">" ); isTagOpened = false; } documentstring.append( WPXString(sCharacters, true) ); } 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 WPXMemoryInputStream instream = WPXMemoryInputStream( buf, fsize ); #ifdef HAVE_LIBWPD_090 WPDConfidence confidence = WPDocument::isFileFormatSupported(&instream); #else // HAVE_LIBWPD_090 WPDConfidence confidence = WPDocument::isFileFormatSupported(&instream, false); #endif // HAVE_LIBWPD_090 if( confidence == WPD_CONFIDENCE_NONE ) { fprintf(stderr, "ERROR: We have no confidence that you are giving us a valid WordPerfect document.\n"); return KoFilter::StupidError; } instream.seek(0, WPX_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"