diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-03 02:15:56 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-03 02:15:56 +0000 |
commit | 50b48aec6ddd451a6d1709c0942477b503457663 (patch) | |
tree | a9ece53ec06fd0a2819de7a2a6de997193566626 /src/projects/kostore | |
download | k3b-50b48aec6ddd451a6d1709c0942477b503457663.tar.gz k3b-50b48aec6ddd451a6d1709c0942477b503457663.zip |
Added abandoned KDE3 version of K3B
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/k3b@1084400 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/projects/kostore')
-rw-r--r-- | src/projects/kostore/Makefile.am | 11 | ||||
-rw-r--r-- | src/projects/kostore/README.k3b | 2 | ||||
-rw-r--r-- | src/projects/kostore/SPEC | 122 | ||||
-rw-r--r-- | src/projects/kostore/koStore.cc | 629 | ||||
-rw-r--r-- | src/projects/kostore/koStore.h | 384 | ||||
-rw-r--r-- | src/projects/kostore/koStoreBase.cc | 29 | ||||
-rw-r--r-- | src/projects/kostore/koStoreBase.h | 51 | ||||
-rw-r--r-- | src/projects/kostore/koStoreDevice.h | 88 | ||||
-rw-r--r-- | src/projects/kostore/koZipStore.cc | 237 | ||||
-rw-r--r-- | src/projects/kostore/koZipStore.h | 61 |
10 files changed, 1614 insertions, 0 deletions
diff --git a/src/projects/kostore/Makefile.am b/src/projects/kostore/Makefile.am new file mode 100644 index 0000000..d99ae86 --- /dev/null +++ b/src/projects/kostore/Makefile.am @@ -0,0 +1,11 @@ + +KDE_CXXFLAGS = $(USE_RTTI) +noinst_LTLIBRARIES = libkostore.la +INCLUDES = $(all_includes) + +####### Files + +libkostore_la_LIBADD = $(LIB_KIO) +libkostore_la_SOURCES = koStore.cc koZipStore.cc koStoreBase.cc +#libkostore_la_LDFLAGS = $(all_libraries) -version-info 3:0:0 $(KDE_LDFLAGS) -no-undefined +#include_HEADERS = koStore.h diff --git a/src/projects/kostore/README.k3b b/src/projects/kostore/README.k3b new file mode 100644 index 0000000..dbf4db1 --- /dev/null +++ b/src/projects/kostore/README.k3b @@ -0,0 +1,2 @@ +This is a stripped down version of the KoStore lib from Koffice. +It only contains the Zip backend. diff --git a/src/projects/kostore/SPEC b/src/projects/kostore/SPEC new file mode 100644 index 0000000..e72286a --- /dev/null +++ b/src/projects/kostore/SPEC @@ -0,0 +1,122 @@ +------------------------------------------------------------------------------- +- - +- KOffice Storage Format Specification - Version 2.3 - +- - +- by Werner, last changed: 20020306 by Werner Trobin - +- - +- History : - +- Version 1.0 : binary store - +- Version 2.0 : tar.gz store - +- Version 2.1 : cleaned up - +- version 2.2 : shaheed Put each part into its own directory to allow - +- one filter to easily embed the results of another - +- and also to have its own documentinfo etc. - +- Added description of naming convention. - +- Version 2.3 : werner Allow the usage of relative links. It is now - +- possible to refer to any "embedded" image or part - +- via a plain relative URL as you all know it. - +- - +------------------------------------------------------------------------------- + +The purpose of this document is to define a common KOffice Storage Structure. +Torben, Reggie, and all the others agreed on storing embedded KOffice Parts +and binary data (e.g. pictures, movies, sounds) via a simple tar.gz-structure. +The support class for the tar format is kdelibs/kio/ktar.*, written by Torben +and finished by David. + +The obvious benefits of this type of storage are: + - It's 100% non- proprietary as it uses only the already available formats + (XML, pictures, tar.gz, ...) and tools (tar, gzip). + - It enables anybody to edit the document directly; for instance, to update + an image (faster than launching the application), or to write scripts + that generate KOffice documents ! :) + - It is also easy to write an import filter for any other office-suite + application out there by reading the tar.gz file and extracting the XML out + of it (at the worst, the user can extract the XML file by himself, but then + the import loses embedded Parts and pictures). + +The tar.gz format also generates much smaller files than the old binary +store, since everything's gzipped. + +Name of the KOffice Files +------------------------- + +As some people suggested, using a "tgz"-ending is confusing; it's been dropped. +Instead, we use the "normal" endings like ".kwd", ".ksp", ".kpr", etc. To recognize +KOffice documents without a proper extension David Faure <faure@kde.org> +added some magic numbers to the gzip header (to see what I'm talking about +please use the "file" command on a KOffice document or see +http://lists.kde.org/?l=koffice-devel&m=98609092618214&w=2); + +External Structure +------------------ + +Here is a simple example to demonstrate the structure of a KOffice document. +Assume you have to write a lab-report. You surely will have some text, the +readings, some formulas and a few pictures (e.g. circuit diagram,...). +The main document will be a KWord-file. In this file you embed some KSpread- +tables, some KChart-diagramms, the KFormulas, and some picture-frames. You save +the document as "lab-report.kwd". Here is what the contents of the +tar.gz file will look like : + +lab-report.kwd: +--------------- +maindoc.xml -- The main XML file containing the KWord document. +documentinfo.xml -- Author and other "metadata" for KWord document. +pictures/ -- Pictures embedded in the main KWord document. +pictures/picture0.jpg +pictures/picture1.bmp +cliparts/ -- Cliparts embedded in the main KWord document. +cliparts/clipart0.wmf +part0/maindoc.xml -- for instance a KSpread embedded table. +part0/documentinfo.xml -- Author and other "metadata" for KSpread table. +part0/part1/maindoc.xml -- say a KChart diagram within the KSpread table. +part1/maindoc.xml -- say a KChart diagram. +part2/maindoc.xml -- why not a KIllustrator drawing. +part2/pictures/ -- Pictures embedded in the KIllustrator document. +part2/pictures/picture0.jpg +part2/pictures/picture1.bmp +part2/cliparts/ -- Cliparts embedded in the KIllustrator document. +part2/cliparts/clipart0.wmf +... + +Internal Name +------------- + +- Absolute references: + The API provided by this specification does not require application writers + or filter writers to know the details of the external structure: + + tar:/documentinfo.xml is saved as documentinfo.xml + tar:/0 is saved as part0/maindoc.xml + tar:/0/documentinfo.xml is saved as part0/documentinfo.xml + tar:/0/1 is saved as part0/part1/maindoc.xml + tar:/0/1/pictures/picture0.png + is saved as part0/part1/pictures/picture0.png + tar:/Table1/0 is saved as Table1/part0/maindoc.xml + + Note that this is the structure as of version 2.2 of this specification. + The only other format shipped with KDE2.0 is converted (on reading) to look + like this through the services of the "Internal Name". + + If the document does not contain any other Parts or pictures, then the + maindoc.xml and documentinfo.xml files are tarred and gzipped alone, + and saved with the proper extension (.kwd for KWord, .ksp for KSpread, + etc.). + The plan is to use relative paths everywhere, so please try not to use + absolute paths unless neccessary. + +- Relative references: + To allow parts to be self-contained, and to ease the work of filter + developers version 2.3 features relative links within the storage. + This means that the KoStore now has a "state" as in "there is something + like a current directory". You can specify a link like + "pictures/picture0.png" and depending on the current directory this will + be mapped to some absolute path. The surrounding code has to ensure that + the current path is maintained correctly, but due to that we can get rid + of the ugly prefix thingy. + + +Thank you for your attention, +Werner <trobin@kde.org> and David <faure@kde.org> +(edited by Chris Lee <lee@azsites.com> for grammer, spelling, and formatting) diff --git a/src/projects/kostore/koStore.cc b/src/projects/kostore/koStore.cc new file mode 100644 index 0000000..5e7fd06 --- /dev/null +++ b/src/projects/kostore/koStore.cc @@ -0,0 +1,629 @@ +// -*- c-basic-offset: 2 -*- +/* This file is part of the KDE project + Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> + Copyright (C) 2000-2002 David Faure <faure@kde.org>, Werner Trobin <trobin@kde.org> + + 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 <stdio.h> +#include <assert.h> +#include <stdlib.h> + +#include "koStore.h" +//#include "koTarStore.h" +#include "koZipStore.h" +//#include "koDirectoryStore.h" + +#include <qfileinfo.h> +#include <qfile.h> +#include <qdir.h> + +#include <kurl.h> +#include <kdebug.h> +#include <kdeversion.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kio/netaccess.h> + +//#define DefaultFormat KoStore::Tar +#define DefaultFormat KoStore::Zip + +const int KoStore::s_area = 30002; + +KoStore::Backend KoStore::determineBackend( QIODevice* dev ) +{ + unsigned char buf[5]; + if ( dev->readBlock( (char *)buf, 4 ) < 4 ) + return DefaultFormat; // will create a "bad" store (bad()==true) + if ( buf[0] == 0037 && buf[1] == 0213 ) // gzip -> tar.gz + return Tar; + if ( buf[0] == 'P' && buf[1] == 'K' && buf[2] == 3 && buf[3] == 4 ) + return Zip; + return DefaultFormat; // fallback +} + +KoStore* KoStore::createStore( const QString& fileName, Mode mode, const QCString & appIdentification, Backend backend ) +{ + if ( backend == Auto ) { + if ( mode == KoStore::Write ) + backend = DefaultFormat; + else + { + QFileInfo inf( fileName ); + if ( inf.isDir() ) + backend = Directory; + else + { + QFile file( fileName ); + if ( file.open( IO_ReadOnly ) ) + backend = determineBackend( &file ); + else + backend = DefaultFormat; // will create a "bad" store (bad()==true) + } + } + } + switch ( backend ) + { +// case Tar: +// return new KoTarStore( fileName, mode, appIdentification ); + case Zip: + return new KoZipStore( fileName, mode, appIdentification ); +// case Directory: +// return new KoDirectoryStore( fileName /* should be a dir name.... */, mode ); + default: + kdWarning(s_area) << "Unsupported backend requested for KoStore : " << backend << endl; + return 0L; + } +} + +KoStore* KoStore::createStore( QIODevice *device, Mode mode, const QCString & appIdentification, Backend backend ) +{ + if ( backend == Auto ) + { + if ( mode == KoStore::Write ) + backend = DefaultFormat; + else { + if ( device->open( IO_ReadOnly ) ) { + backend = determineBackend( device ); + device->close(); + } + } + } + switch ( backend ) + { +// case Tar: +// return new KoTarStore( device, mode, appIdentification ); +// case Directory: +// kdError(s_area) << "Can't create a Directory store for a memory buffer!" << endl; + // fallback + case Zip: + return new KoZipStore( device, mode, appIdentification ); + default: + kdWarning(s_area) << "Unsupported backend requested for KoStore : " << backend << endl; + return 0L; + } +} + +KoStore* KoStore::createStore( QWidget* window, const KURL& url, Mode mode, const QCString & appIdentification, Backend backend ) +{ + if ( url.isLocalFile() ) + return createStore(url.path(), mode, appIdentification, backend ); + + QString tmpFile; + if ( mode == KoStore::Write ) + { + if ( backend == Auto ) + backend = DefaultFormat; + } + else + { + const bool downloaded = + KIO::NetAccess::download( url, tmpFile, window ); + + if (!downloaded) + { + kdError(s_area) << "Could not download file!" << endl; + backend = DefaultFormat; // will create a "bad" store (bad()==true) + } + else if ( backend == Auto ) + { + QFile file( tmpFile ); + if ( file.open( IO_ReadOnly ) ) + { + backend = determineBackend( &file ); + file.close(); + } + } + } + switch ( backend ) + { +// case Tar: +// return new KoTarStore( window, url, tmpFile, mode, appIdentification ); + case Zip: + return new KoZipStore( window, url, tmpFile, mode, appIdentification ); + default: + kdWarning(s_area) << "Unsupported backend requested for KoStore (KURL) : " << backend << endl; + KMessageBox::sorry( window, + i18n("The directory mode is not supported for remote locations."), + i18n("KOffice Storage")); + return 0L; + } +} + +namespace { + const char* const ROOTPART = "root"; + const char* const MAINNAME = "maindoc.xml"; +} + +bool KoStore::init( Mode _mode ) +{ + d = 0; + m_bIsOpen = false; + m_mode = _mode; + m_stream = 0; + + // Assume new style names. + m_namingVersion = NAMING_VERSION_2_2; + return true; +} + +KoStore::~KoStore() +{ + delete m_stream; +} + +bool KoStore::open( const QString & _name ) +{ + // This also converts from relative to absolute, i.e. merges the currentPath() + m_sName = toExternalNaming( _name ); + + if ( m_bIsOpen ) + { + kdWarning(s_area) << "KoStore: File is already opened" << endl; + //return KIO::ERR_INTERNAL; + return false; + } + + if ( m_sName.length() > 512 ) + { + kdError(s_area) << "KoStore: Filename " << m_sName << " is too long" << endl; + //return KIO::ERR_MALFORMED_URL; + return false; + } + + if ( m_mode == Write ) + { + kdDebug(s_area) << "KoStore: opening for writing '" << m_sName << "'" << endl; + if ( m_strFiles.findIndex( m_sName ) != -1 ) // just check if it's there + { + kdWarning(s_area) << "KoStore: Duplicate filename " << m_sName << endl; + //return KIO::ERR_FILE_ALREADY_EXIST; + return false; + } + + m_strFiles.append( m_sName ); + + m_iSize = 0; + if ( !openWrite( m_sName ) ) + return false; + } + else if ( m_mode == Read ) + { + kdDebug(s_area) << "Opening for reading '" << m_sName << "'" << endl; + if ( !openRead( m_sName ) ) + return false; + } + else + //return KIO::ERR_UNSUPPORTED_ACTION; + return false; + + m_bIsOpen = true; + return true; +} + +bool KoStore::isOpen() const +{ + return m_bIsOpen; +} + +bool KoStore::close() +{ + kdDebug(s_area) << "KoStore: Closing" << endl; + + if ( !m_bIsOpen ) + { + kdWarning(s_area) << "KoStore: You must open before closing" << endl; + //return KIO::ERR_INTERNAL; + return false; + } + + bool ret = m_mode == Write ? closeWrite() : closeRead(); + + delete m_stream; + m_stream = 0L; + m_bIsOpen = false; + return ret; +} + +QIODevice* KoStore::device() const +{ + if ( !m_bIsOpen ) + kdWarning(s_area) << "KoStore: You must open before asking for a device" << endl; + if ( m_mode != Read ) + kdWarning(s_area) << "KoStore: Can not get device from store that is opened for writing" << endl; + return m_stream; +} + +QByteArray KoStore::read( unsigned long int max ) +{ + QByteArray data; // Data is a QArray<char> + + if ( !m_bIsOpen ) + { + kdWarning(s_area) << "KoStore: You must open before reading" << endl; + data.resize( 0 ); + return data; + } + if ( m_mode != Read ) + { + kdError(s_area) << "KoStore: Can not read from store that is opened for writing" << endl; + data.resize( 0 ); + return data; + } + + if ( m_stream->atEnd() ) + { + data.resize( 0 ); + return data; + } + + if ( max > m_iSize - m_stream->at() ) + max = m_iSize - m_stream->at(); + if ( max == 0 ) + { + data.resize( 0 ); + return data; + } + + char *p = new char[ max ]; + m_stream->readBlock( p, max ); + + data.setRawData( p, max ); + return data; +} + +Q_LONG KoStore::write( const QByteArray& data ) +{ + return write( data.data(), data.size() ); // see below +} + +Q_LONG KoStore::read( char *_buffer, Q_ULONG _len ) +{ + if ( !m_bIsOpen ) + { + kdError(s_area) << "KoStore: You must open before reading" << endl; + return -1; + } + if ( m_mode != Read ) + { + kdError(s_area) << "KoStore: Can not read from store that is opened for writing" << endl; + return -1; + } + + if ( m_stream->atEnd() ) + return 0; + + if ( _len > m_iSize - m_stream->at() ) + _len = m_iSize - m_stream->at(); + if ( _len == 0 ) + return 0; + + return m_stream->readBlock( _buffer, _len ); +} + +Q_LONG KoStore::write( const char* _data, Q_ULONG _len ) +{ + if ( _len == 0L ) return 0; + + if ( !m_bIsOpen ) + { + kdError(s_area) << "KoStore: You must open before writing" << endl; + return 0L; + } + if ( m_mode != Write ) + { + kdError(s_area) << "KoStore: Can not write to store that is opened for reading" << endl; + return 0L; + } + + int nwritten = m_stream->writeBlock( _data, _len ); + Q_ASSERT( nwritten == (int)_len ); + m_iSize += nwritten; + + return nwritten; +} + +QIODevice::Offset KoStore::size() const +{ + if ( !m_bIsOpen ) + { + kdWarning(s_area) << "KoStore: You must open before asking for a size" << endl; + return static_cast<QIODevice::Offset>(-1); + } + if ( m_mode != Read ) + { + kdWarning(s_area) << "KoStore: Can not get size from store that is opened for writing" << endl; + return static_cast<QIODevice::Offset>(-1); + } + return m_iSize; +} + +bool KoStore::enterDirectory( const QString& directory ) +{ + //kdDebug(s_area) << "KoStore::enterDirectory " << directory << endl; + int pos; + bool success = true; + QString tmp( directory ); + + while ( ( pos = tmp.find( '/' ) ) != -1 && + ( success = enterDirectoryInternal( tmp.left( pos ) ) ) ) + tmp = tmp.mid( pos + 1 ); + + if ( success && !tmp.isEmpty() ) + return enterDirectoryInternal( tmp ); + return success; +} + +bool KoStore::leaveDirectory() +{ + if ( m_currentPath.isEmpty() ) + return false; + + m_currentPath.pop_back(); + + return enterAbsoluteDirectory( expandEncodedDirectory( currentPath() ) ); +} + +QString KoStore::currentDirectory() const +{ + return expandEncodedDirectory( currentPath() ); +} + +QString KoStore::currentPath() const +{ + QString path; + QStringList::ConstIterator it = m_currentPath.begin(); + QStringList::ConstIterator end = m_currentPath.end(); + for ( ; it != end; ++it ) { + path += *it; + path += '/'; + } + return path; +} + +void KoStore::pushDirectory() +{ + m_directoryStack.push( currentPath() ); +} + +void KoStore::popDirectory() +{ + m_currentPath.clear(); + enterAbsoluteDirectory( QString::null ); + enterDirectory( m_directoryStack.pop() ); +} + +bool KoStore::addLocalFile( const QString &fileName, const QString &destName ) +{ + QFileInfo fi( fileName ); + uint size = fi.size(); + QFile file( fileName ); + if ( !file.open( IO_ReadOnly )) + { + return false; + } + + if ( !open ( destName ) ) + { + return false; + } + + QByteArray data ( 8 * 1024 ); + + uint total = 0; + for ( int block = 0; ( block = file.readBlock ( data.data(), data.size() ) ) > 0; total += block ) + { + data.resize(block); + if ( write( data ) != block ) + return false; + data.resize(8*1024); + } + Q_ASSERT( total == size ); + + close(); + file.close(); + + return true; +} + +bool KoStore::extractFile ( const QString &srcName, const QString &fileName ) +{ + if ( !open ( srcName ) ) + return false; + + QFile file( fileName ); + + if( !file.open ( IO_WriteOnly ) ) + { + close(); + return false; + } + + QByteArray data ( 8 * 1024 ); + uint total = 0; + for( int block = 0; ( block = read ( data.data(), data.size() ) ) > 0; total += block ) + { + file.writeBlock ( data.data(), block ); + } + + if( size() != static_cast<QIODevice::Offset>(-1) ) + Q_ASSERT( total == size() ); + + file.close(); + close(); + + return true; +} + +QStringList KoStore::addLocalDirectory( const QString &dirPath, const QString &destName ) +{ + QString dot = "."; + QString dotdot = ".."; + QStringList content; + + QDir dir(dirPath); + if ( !dir.exists() ) + return 0; + + QStringList files = dir.entryList(); + for ( QStringList::Iterator it = files.begin(); it != files.end(); ++it ) + { + if ( *it != dot && *it != dotdot ) + { + QString currentFile = dirPath + "/" + *it; + QString dest = destName.isEmpty() ? *it : (destName + "/" + *it); + + QFileInfo fi ( currentFile ); + if ( fi.isFile() ) + { + addLocalFile ( currentFile, dest ); + content.append(dest); + } + else if ( fi.isDir() ) + { + content += addLocalDirectory ( currentFile, dest ); + } + } + } + + return content; +} + + +bool KoStore::at( QIODevice::Offset pos ) +{ + return m_stream->at( pos ); +} + +QIODevice::Offset KoStore::at() const +{ + return m_stream->at(); +} + +bool KoStore::atEnd() const +{ + return m_stream->atEnd(); +} + +// See the specification for details of what this function does. +QString KoStore::toExternalNaming( const QString & _internalNaming ) const +{ + if ( _internalNaming == ROOTPART ) + return expandEncodedDirectory( currentPath() ) + MAINNAME; + + QString intern; + if ( _internalNaming.startsWith( "tar:/" ) ) // absolute reference + intern = _internalNaming.mid( 5 ); // remove protocol + else + intern = currentPath() + _internalNaming; + + return expandEncodedPath( intern ); +} + +QString KoStore::expandEncodedPath( QString intern ) const +{ + if ( m_namingVersion == NAMING_VERSION_RAW ) + return intern; + + QString result; + int pos; + + if ( ( pos = intern.findRev( '/', -1 ) ) != -1 ) { + result = expandEncodedDirectory( intern.left( pos ) ) + '/'; + intern = intern.mid( pos + 1 ); + } + + // Now process the filename. If the first character is numeric, we have + // a main document. + if ( QChar(intern.at(0)).isDigit() ) + { + // If this is the first part name, check if we have a store with + // old-style names. + if ( ( m_namingVersion == NAMING_VERSION_2_2 ) && + ( m_mode == Read ) && + ( fileExists( result + "part" + intern + ".xml" ) ) ) + m_namingVersion = NAMING_VERSION_2_1; + + if ( m_namingVersion == NAMING_VERSION_2_1 ) + result = result + "part" + intern + ".xml"; + else + result = result + "part" + intern + "/" + MAINNAME; + } + else + result += intern; + return result; +} + +QString KoStore::expandEncodedDirectory( QString intern ) const +{ + if ( m_namingVersion == NAMING_VERSION_RAW ) + return intern; + + QString result; + int pos; + while ( ( pos = intern.find( '/' ) ) != -1 ) { + if ( QChar(intern.at(0)).isDigit() ) + result += "part"; + result += intern.left( pos + 1 ); // copy numbers (or "pictures") + "/" + intern = intern.mid( pos + 1 ); // remove the dir we just processed + } + + if ( QChar(intern.at(0)).isDigit() ) + result += "part"; + result += intern; + return result; +} + +bool KoStore::enterDirectoryInternal( const QString& directory ) +{ + if ( enterRelativeDirectory( expandEncodedDirectory( directory ) ) ) + { + m_currentPath.append( directory ); + return true; + } + return false; +} + +void KoStore::disallowNameExpansion( void ) +{ + m_namingVersion = NAMING_VERSION_RAW; +} + +bool KoStore::hasFile( const QString& fileName ) const +{ + return fileExists( toExternalNaming( currentPath() + fileName ) ); +} diff --git a/src/projects/kostore/koStore.h b/src/projects/kostore/koStore.h new file mode 100644 index 0000000..a22c5f3 --- /dev/null +++ b/src/projects/kostore/koStore.h @@ -0,0 +1,384 @@ +// -*- c-basic-offset: 2 -*- +/* This file is part of the KDE project + Copyright (C) 1998, 1999 David Faure <faure@kde.org> + + 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. +*/ + +#ifndef __koStore_h_ +#define __koStore_h_ + +#include <qstring.h> +#include <qstringlist.h> +#include <qiodevice.h> +#include <qvaluestack.h> +//#include <koffice_export.h> +#include <kdemacros.h> + +#define KOSTORE_EXPORT KDE_EXPORT + +class QWidget; + +class KURL; + +/** + * Saves and loads KOffice documents using various backends. Currently supported + * backends are ZIP, tar and directory. + * We call a "store" the file on the hard disk (the one the users sees) + * and call a "file" a file inside the store. + */ +class KoStore +{ +public: + + enum Mode { Read, Write }; + enum Backend { Auto, Tar, Zip, Directory }; + + /** + * Open a store (i.e. the representation on disk of a KOffice document). + * + * @param fileName the name of the file to open + * @param mode if KoStore::Read, open an existing store to read it. + * if KoStore::Write, create or replace a store. + * @param backend the backend to use for the data storage. + * Auto means automatically-determined for reading, + * and the current format (now Zip) for writing. + * + * @param appIdentification the application's mimetype, + * to be written in the file for "mime-magic" identification. + * Only meaningful if mode is Write, and if backend!=Directory. + */ + static KoStore* createStore( const QString& fileName, Mode mode, const QCString & appIdentification = "", Backend backend = Auto ); + + /** + * Create a store for any kind of QIODevice: file, memory buffer... + * KoStore will take care of opening the QIODevice. + * This method doesn't support the Directory store! + */ + static KoStore* createStore( QIODevice *device, Mode mode, const QCString & appIdentification = "", Backend backend = Auto ); + + /** + * Open a store (i.e. the representation on disk of a KOffice document). + * + * @param window associated window (for the progress bar dialog and authentication) + * @param url URL of the file to open + * @param mode if KoStore::Read, open an existing store to read it. + * if KoStore::Write, create or replace a store. + * @param backend the backend to use for the data storage. + * Auto means automatically-determined for reading, + * and the current format (now Zip) for writing. + * + * @param appIdentification the application's mimetype, + * to be written in the file for "mime-magic" identification. + * Only meaningful if mode is Write, and if backend!=Directory. + * + * If the file is remote, the backend Directory cannot be used! + * + * @since 1.4 + * @bug saving not completely implemented (fixed temporary file) + */ + static KoStore* createStore( QWidget* window, const KURL& url, Mode mode, const QCString & appIdentification = "", Backend backend = Auto ); + + /** + * Destroys the store (i.e. closes the file on the hard disk) + */ + virtual ~KoStore(); + + /** + * Open a new file inside the store + * @param name The filename, internal representation ("root", "tar:/0"... ). + * If the tar:/ prefix is missing it's assumed to be a relative URI. + * @return true on success. + */ + bool open( const QString & name ); + + /** + * Check whether a file inside the store is currently opened with open(), + * ready to be read or written. + * @return true if a file is currently opened. + */ + bool isOpen() const; + + /** + * Close the file inside the store + * @return true on success. + */ + bool close(); + + /** + * Get a device for reading a file from the store directly + * (slightly faster than read() calls) + * You need to call @ref open first, and @ref close afterwards. + */ + QIODevice* device() const; + + /** + * Read data from the currently opened file. You can also use the streams + * for this. + */ + QByteArray read( unsigned long int max ); + + /** + * Write data into the currently opened file. You can also use the streams + * for this. + */ + Q_LONG write( const QByteArray& _data ); + + /** + * Read data from the currently opened file. You can also use the streams + * for this. + * @return size of data read, -1 on error + */ + Q_LONG read( char *_buffer, Q_ULONG _len ); + + /** + * Write data into the currently opened file. You can also use the streams + * for this. + */ + virtual Q_LONG write( const char* _data, Q_ULONG _len ); + + /** + * @return the size of the currently opened file, -1 on error. + * Can be used as an argument for the read methods, for instance + */ + QIODevice::Offset size() const; + + /** + * @return true if an error occurred + */ + bool bad() const { return !m_bGood; } // :) + + /** + * @return the mode used when opening, read or write + */ + Mode mode() const { return m_mode; } + + /** + * Enters one or multiple directories. In Read mode this actually + * checks whether the specified directories exist and returns false + * if they don't. In Write mode we don't create the directory, we + * just use the "current directory" to generate the absolute path + * if you pass a relative path (one not starting with tar:/) when + * opening a stream. + * Note: Operates on internal names + */ + bool enterDirectory( const QString& directory ); + + /** + * Leaves a directory. Equivalent to "cd .." + * @return true on success, false if we were at the root already to + * make it possible to "loop to the root" + */ + bool leaveDirectory(); + + /** + * Returns the current path including a trailing slash. + * Note: Returns a path in "internal name" style + */ + QString currentPath() const; + + /** + * Returns the current directory. + * Note: Returns a path in "internal name" style + */ + QString currentDirectory() const; + + + /** + * Stacks the current directory. Restore the current path using + * @ref popDirectory . + */ + void pushDirectory(); + + /** + * Restores the previously pushed directory. No-op if the stack is + * empty. + */ + void popDirectory(); + + /** + * @return true if the given file exists in the current directory, + * i.e. if open(fileName) will work. + */ + bool hasFile( const QString& fileName ) const; + + /** + * Imports a local file into a store + * @param fileName file on hard disk + * @param destName file in the store + */ + bool addLocalFile( const QString &fileName, const QString &destName ); + + /** + * Imports a local directory + * @param dirPath path to the directory on a disk + * @param dest path in the store where the directory should get saved + * @return the directory index + */ + QStringList addLocalDirectory( const QString &dirPath, const QString &dest ); + + + /** + * Extracts a file out of the store + * @param srcName file in the store + * @param fileName file on a disk + */ + bool extractFile( const QString &srcName, const QString &fileName ); + + //@{ + /// See QIODevice + bool at( QIODevice::Offset pos ); + QIODevice::Offset at() const; + bool atEnd() const; + //@} + + /** + * Do not expand file and directory names + * Useful when using KoStore on non-KOffice files. + * (This method should be called just after the constructor) + */ + void disallowNameExpansion( void ); + +protected: + + KoStore() {} + + /** + * Init store - called by constructor. + * @return true on success + */ + virtual bool init( Mode mode ); + /** + * Open the file @p name in the store, for writing + * On success, this method must set m_stream to a stream in which we can write. + * @param name "absolute path" (in the archive) to the file to open + * @return true on success + */ + virtual bool openWrite( const QString& name ) = 0; + /** + * Open the file @p name in the store, for reading. + * On success, this method must set m_stream to a stream from which we can read, + * as well as setting m_iSize to the size of the file. + * @param name "absolute path" (in the archive) to the file to open + * @return true on success + */ + virtual bool openRead( const QString& name ) = 0; + + /** + * @return true on success + */ + virtual bool closeRead() = 0; + /** + * @return true on success + */ + virtual bool closeWrite() = 0; + + /** + * Enter a subdirectory of the current directory. + * The directory might not exist yet in Write mode. + */ + virtual bool enterRelativeDirectory( const QString& dirName ) = 0; + /** + * Enter a directory where we've been before. + * It is guaranteed to always exist. + */ + virtual bool enterAbsoluteDirectory( const QString& path ) = 0; + + /** + * Check if a file exists inside the store. + * @param absPath the absolute path inside the store, i.e. not relative to the current directory + */ + virtual bool fileExists( const QString& absPath ) const = 0; + +private: + static Backend determineBackend( QIODevice* dev ); + + /** + * Conversion routine + * @param _internalNaming name used internally : "root", "tar:/0", ... + * @return the name used in the file, more user-friendly ("maindoc.xml", + * "part0/maindoc.xml", ...) + * Examples: + * + * tar:/0 is saved as part0/maindoc.xml + * tar:/0/1 is saved as part0/part1/maindoc.xml + * tar:/0/1/pictures/picture0.png is saved as part0/part1/pictures/picture0.png + * + * see specification (koffice/lib/store/SPEC) for details. + */ + QString toExternalNaming( const QString & _internalNaming ) const; + + /** + * Expands a full path name for a stream (directories+filename) + */ + QString expandEncodedPath( QString intern ) const; + + /** + * Expands only directory names(!) + * Needed for the path handling code, as we only operate on internal names + */ + QString expandEncodedDirectory( QString intern ) const; + + mutable enum + { + NAMING_VERSION_2_1, + NAMING_VERSION_2_2, + NAMING_VERSION_RAW ///< Never expand file and directory names + } m_namingVersion; + + /** + * Enter *one* single directory. Nothing like foo/bar/bleh allowed. + * Performs some checking when in Read mode + */ + bool enterDirectoryInternal( const QString& directory ); + +protected: + + Mode m_mode; + + /// Store the filenames (with full path inside the archive) when writing, to avoid duplicates + QStringList m_strFiles; + + /// The "current directory" (path) + QStringList m_currentPath; + + /// Used to push/pop directories to make it easy to save/restore the state + QValueStack<QString> m_directoryStack; + + /// Current filename (between an open() and a close()) + QString m_sName; + /// Current size of the file named m_sName + QIODevice::Offset m_iSize; + + /// The stream for the current read or write operation + QIODevice * m_stream; + + bool m_bIsOpen; + /// Must be set by the constructor. + bool m_bGood; + + static const int s_area; + +private: + KoStore( const KoStore& store ); ///< don't copy + KoStore& operator=( const KoStore& store ); ///< don't assign + + class Private; + Private * d; + +}; + +#endif diff --git a/src/projects/kostore/koStoreBase.cc b/src/projects/kostore/koStoreBase.cc new file mode 100644 index 0000000..a9cc63e --- /dev/null +++ b/src/projects/kostore/koStoreBase.cc @@ -0,0 +1,29 @@ +// +/* This file is part of the KDE project + Copyright 2004 Nicolas GOUTTE <goutte@kde.org> + + 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 "koStoreBase.h" + +KoStoreBase::KoStoreBase(void) : m_fileMode(Local), m_window(0) +{ +} + +KoStoreBase::~KoStoreBase(void) +{ +} diff --git a/src/projects/kostore/koStoreBase.h b/src/projects/kostore/koStoreBase.h new file mode 100644 index 0000000..0987577 --- /dev/null +++ b/src/projects/kostore/koStoreBase.h @@ -0,0 +1,51 @@ +// +/* This file is part of the KDE project + Copyright 2004 Nicolas GOUTTE <goutte@kde.org> + + 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. +*/ + +#ifndef KOSTORE_BASE_H +#define KOSTORE_BASE_H + +#include <kurl.h> + +#include "koStore.h" + +/** + * Helper class for KoStore (mainly for remote file support) + * @since 1.4 + */ +class KoStoreBase : public KoStore +{ +public: + KoStoreBase(void); + virtual ~KoStoreBase(void); +public: + enum FileMode { /*Bad=0,*/ Local=1, RemoteRead, RemoteWrite }; + +protected: + /** + * original URL of the remote file + * (undefined for a local file) + */ + KURL m_url; + FileMode m_fileMode; + QString m_localFileName; + QWidget* m_window; +}; + +#endif //KOSTORE_BASE_H diff --git a/src/projects/kostore/koStoreDevice.h b/src/projects/kostore/koStoreDevice.h new file mode 100644 index 0000000..b245d60 --- /dev/null +++ b/src/projects/kostore/koStoreDevice.h @@ -0,0 +1,88 @@ +/* This file is part of the KDE project + Copyright (C) 2000 David Faure <faure@kde.org> + + 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. +*/ + +#ifndef koStoreDevice_h +#define koStoreDevice_h + +#include "koStore.h" + +/** + * This class implements a QIODevice around KoStore, so that + * it can be used to create a QDomDocument from it, to be written or read + * using QDataStream or to be written using QTextStream + */ +class KoStoreDevice : public QIODevice +{ +public: + /// Note: KoStore::open() should be called before calling this. + KoStoreDevice( KoStore * store ) : m_store(store) { + setType( IO_Direct ); + } + ~KoStoreDevice() {} + + bool open( int m ) { + if ( m & IO_ReadOnly ) + return ( m_store->mode() == KoStore::Read ); + if ( m & IO_WriteOnly ) + return ( m_store->mode() == KoStore::Write ); + return false; + } + void close() { } + void flush() { } + + Offset size() const { + if ( m_store->mode() == KoStore::Read ) + return m_store->size(); + else + return 0xffffffff; + } + + virtual Q_LONG readBlock( char *data, Q_ULONG maxlen ) { return m_store->read(data, maxlen); } + virtual Q_LONG writeBlock( const char *data, Q_ULONG len ) { return m_store->write( data, len ); } + // Not virtual, only to uncover shadow + Q_LONG writeBlock( const QByteArray& data ) { return QIODevice::writeBlock( data ); } + + int getch() { + char c[2]; + if ( m_store->read(c, 1) == -1) + return -1; + else + return c[0]; + } + int putch( int _c ) { + char c[2]; + c[0] = _c; + c[1] = 0; + if (m_store->write( c, 1 ) == 1) + return _c; + else + return -1; + } + int ungetch( int ) { return -1; } // unsupported + + // See QIODevice + virtual bool at( Offset pos ) { return m_store->at(pos); } + virtual Offset at() const { return m_store->at(); } + virtual bool atEnd() const { return m_store->atEnd(); } + +protected: + KoStore * m_store; +}; + +#endif diff --git a/src/projects/kostore/koZipStore.cc b/src/projects/kostore/koZipStore.cc new file mode 100644 index 0000000..ed3fec4 --- /dev/null +++ b/src/projects/kostore/koZipStore.cc @@ -0,0 +1,237 @@ +/* This file is part of the KDE project + Copyright (C) 2000-2002 David Faure <faure@kde.org> + + 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 "koZipStore.h" + +#include <qbuffer.h> + +#include <kzip.h> +#include <kdebug.h> +#include <kdeversion.h> +#include <kurl.h> +#include <kio/netaccess.h> +#if ! KDE_IS_VERSION( 3, 4, 1 ) +#include <qdir.h> +#include <qfileinfo.h> +#endif + +KoZipStore::KoZipStore( const QString & _filename, Mode _mode, const QCString & appIdentification ) +{ + kdDebug(s_area) << "KoZipStore Constructor filename = " << _filename + << " mode = " << int(_mode) + << " mimetype = " << appIdentification << endl; + + m_pZip = new KZip( _filename ); + +#if ! KDE_IS_VERSION( 3, 4, 1 ) + // Workaround for KZip KSaveFile double deletion in kdelibs-3.4, + // when trying to write to a non-writable directory. + QDir dir( QFileInfo( _filename ).dir() ); + if (_mode == Write && !QFileInfo( dir.path() ).isWritable() ) + { + kdWarning(s_area) << dir.path() << " isn't writable" << endl; + m_bGood = false; + m_currentDir = 0; + KoStore::init( _mode ); + } + else +#endif + { + m_bGood = init( _mode, appIdentification ); // open the zip file and init some vars + } +} + +KoZipStore::KoZipStore( QIODevice *dev, Mode mode, const QCString & appIdentification ) +{ + m_pZip = new KZip( dev ); + m_bGood = init( mode, appIdentification ); +} + +KoZipStore::KoZipStore( QWidget* window, const KURL & _url, const QString & _filename, Mode _mode, const QCString & appIdentification ) +{ + kdDebug(s_area) << "KoZipStore Constructor url" << _url.prettyURL() + << " filename = " << _filename + << " mode = " << int(_mode) + << " mimetype = " << appIdentification << endl; + + m_url = _url; + m_window = window; + + if ( _mode == KoStore::Read ) + { + m_fileMode = KoStoreBase::RemoteRead; + m_localFileName = _filename; + + } + else + { + m_fileMode = KoStoreBase::RemoteWrite; + m_localFileName = "/tmp/kozip"; // ### FIXME with KTempFile + } + + m_pZip = new KZip( m_localFileName ); + m_bGood = init( _mode, appIdentification ); // open the zip file and init some vars +} + +KoZipStore::~KoZipStore() +{ + kdDebug(s_area) << "KoZipStore::~KoZipStore" << endl; + m_pZip->close(); + delete m_pZip; + + // Now we have still some job to do for remote files. + if ( m_fileMode == KoStoreBase::RemoteRead ) + { + KIO::NetAccess::removeTempFile( m_localFileName ); + } + else if ( m_fileMode == KoStoreBase::RemoteWrite ) + { + KIO::NetAccess::upload( m_localFileName, m_url, m_window ); + // ### FIXME: delete temp file + } +} + +bool KoZipStore::init( Mode _mode, const QCString& appIdentification ) +{ + KoStore::init( _mode ); + m_currentDir = 0; + bool good = m_pZip->open( _mode == Write ? IO_WriteOnly : IO_ReadOnly ); + + if ( good && _mode == Read ) + good = m_pZip->directory() != 0; + else if ( good && _mode == Write ) + { + //kdDebug(s_area) << "KoZipStore::init writing mimetype " << appIdentification << endl; + + m_pZip->setCompression( KZip::NoCompression ); + m_pZip->setExtraField( KZip::NoExtraField ); + // Write identification + (void)m_pZip->writeFile( "mimetype", "", "", appIdentification.length(), appIdentification.data() ); + m_pZip->setCompression( KZip::DeflateCompression ); + // We don't need the extra field in KOffice - so we leave it as "no extra field". + } + return good; +} + +bool KoZipStore::openWrite( const QString& name ) +{ +#if 0 + // Prepare memory buffer for writing + m_byteArray.resize( 0 ); + m_stream = new QBuffer( m_byteArray ); + m_stream->open( IO_WriteOnly ); + return true; +#endif + m_stream = 0L; // Don't use! + return m_pZip->prepareWriting( name, "", "" /*m_pZip->rootDir()->user(), m_pZip->rootDir()->group()*/, 0 ); +} + +bool KoZipStore::openRead( const QString& name ) +{ + const KArchiveEntry * entry = m_pZip->directory()->entry( name ); + if ( entry == 0L ) + { + //kdWarning(s_area) << "Unknown filename " << name << endl; + //return KIO::ERR_DOES_NOT_EXIST; + return false; + } + if ( entry->isDirectory() ) + { + kdWarning(s_area) << name << " is a directory !" << endl; + //return KIO::ERR_IS_DIRECTORY; + return false; + } + // Must cast to KZipFileEntry, not only KArchiveFile, because device() isn't virtual! + const KZipFileEntry * f = static_cast<const KZipFileEntry *>(entry); + delete m_stream; + m_stream = f->device(); + m_iSize = f->size(); + return true; +} + +Q_LONG KoZipStore::write( const char* _data, Q_ULONG _len ) +{ + if ( _len == 0L ) return 0; + //kdDebug(s_area) << "KoZipStore::write " << _len << endl; + + if ( !m_bIsOpen ) + { + kdError(s_area) << "KoStore: You must open before writing" << endl; + return 0L; + } + if ( m_mode != Write ) + { + kdError(s_area) << "KoStore: Can not write to store that is opened for reading" << endl; + return 0L; + } + + m_iSize += _len; + if ( m_pZip->writeData( _data, _len ) ) // writeData returns a bool! + return _len; + return 0L; +} + +bool KoZipStore::closeWrite() +{ + kdDebug(s_area) << "Wrote file " << m_sName << " into ZIP archive. size " + << m_iSize << endl; + return m_pZip->doneWriting( m_iSize ); +#if 0 + if ( !m_pZip->writeFile( m_sName , "user", "group", m_iSize, m_byteArray.data() ) ) + kdWarning( s_area ) << "Failed to write " << m_sName << endl; + m_byteArray.resize( 0 ); // save memory + return true; +#endif +} + +bool KoZipStore::enterRelativeDirectory( const QString& dirName ) +{ + if ( m_mode == Read ) { + if ( !m_currentDir ) { + m_currentDir = m_pZip->directory(); // initialize + Q_ASSERT( m_currentPath.isEmpty() ); + } + const KArchiveEntry *entry = m_currentDir->entry( dirName ); + if ( entry && entry->isDirectory() ) { + m_currentDir = dynamic_cast<const KArchiveDirectory*>( entry ); + return m_currentDir != 0; + } + return false; + } + else // Write, no checking here + return true; +} + +bool KoZipStore::enterAbsoluteDirectory( const QString& path ) +{ + if ( path.isEmpty() ) + { + m_currentDir = 0; + return true; + } + m_currentDir = dynamic_cast<const KArchiveDirectory*>( m_pZip->directory()->entry( path ) ); + Q_ASSERT( m_currentDir ); + return m_currentDir != 0; +} + +bool KoZipStore::fileExists( const QString& absPath ) const +{ + const KArchiveEntry *entry = m_pZip->directory()->entry( absPath ); + return entry && entry->isFile(); +} diff --git a/src/projects/kostore/koZipStore.h b/src/projects/kostore/koZipStore.h new file mode 100644 index 0000000..e87f5e4 --- /dev/null +++ b/src/projects/kostore/koZipStore.h @@ -0,0 +1,61 @@ +/* This file is part of the KDE project + Copyright (C) 2002 David Faure <faure@kde.org> + + 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. +*/ + +#ifndef koZipStore_h +#define koZipStore_h + +#include "koStoreBase.h" + +class KZip; +class KArchiveDirectory; +class KURL; + +class KoZipStore : public KoStoreBase +{ +public: + KoZipStore( const QString & _filename, Mode _mode, const QCString & appIdentification ); + KoZipStore( QIODevice *dev, Mode mode, const QCString & appIdentification ); + /** + * KURL-constructor + * @todo saving not completely implemented (fixed temporary file) + * @since 1.4 + */ + KoZipStore( QWidget* window, const KURL& _url, const QString & _filename, Mode _mode, const QCString & appIdentification ); + ~KoZipStore(); + + virtual Q_LONG write( const char* _data, Q_ULONG _len ); +protected: + virtual bool init( Mode _mode, const QCString& appIdentification ); + virtual bool openWrite( const QString& name ); + virtual bool openRead( const QString& name ); + virtual bool closeWrite(); + virtual bool closeRead() { return true; } + virtual bool enterRelativeDirectory( const QString& dirName ); + virtual bool enterAbsoluteDirectory( const QString& path ); + virtual bool fileExists( const QString& absPath ) const; + + /// The archive + KZip * m_pZip; + + /** In "Read" mode this pointer is pointing to the + current directory in the archive to speed up the verification process */ + const KArchiveDirectory* m_currentDir; +}; + +#endif |