summaryrefslogtreecommitdiffstats
path: root/src/projects/kostore
diff options
context:
space:
mode:
Diffstat (limited to 'src/projects/kostore')
-rw-r--r--src/projects/kostore/Makefile.am11
-rw-r--r--src/projects/kostore/README.k3b2
-rw-r--r--src/projects/kostore/SPEC122
-rw-r--r--src/projects/kostore/koStore.cc629
-rw-r--r--src/projects/kostore/koStore.h384
-rw-r--r--src/projects/kostore/koStoreBase.cc29
-rw-r--r--src/projects/kostore/koStoreBase.h51
-rw-r--r--src/projects/kostore/koStoreDevice.h88
-rw-r--r--src/projects/kostore/koZipStore.cc237
-rw-r--r--src/projects/kostore/koZipStore.h61
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