Warning, file /office/calligra/libs/store/KoZipStore.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /* This file is part of the KDE project
0002    Copyright (C) 2000-2002 David Faure <faure@kde.org>
0003    Copyright (C) 2010 C. Boemann <cbo@boemann.dk>
0004 
0005    This library is free software; you can redistribute it and/or
0006    modify it under the terms of the GNU Library General Public
0007    License as published by the Free Software Foundation; either
0008    version 2 of the License, or (at your option) any later version.
0009 
0010    This library is distributed in the hope that it will be useful,
0011    but WITHOUT ANY WARRANTY; without even the implied warranty of
0012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013    Library General Public License for more details.
0014 
0015    You should have received a copy of the GNU Library General Public License
0016    along with this library; see the file COPYING.LIB.  If not, write to
0017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018  * Boston, MA 02110-1301, USA.
0019 */
0020 
0021 #include "KoZipStore.h"
0022 #include "KoStore_p.h"
0023 
0024 #include <QBuffer>
0025 #include <QByteArray>
0026 
0027 #include <kzip.h>
0028 #include <StoreDebug.h>
0029 
0030 #include <QUrl>
0031 #include <KoNetAccess.h>
0032 
0033 KoZipStore::KoZipStore(const QString & _filename, Mode mode, const QByteArray & appIdentification,
0034                        bool writeMimetype)
0035   : KoStore(mode, writeMimetype)
0036 {
0037     debugStore << "KoZipStore Constructor filename =" << _filename
0038     << " mode = " << int(mode)
0039     << " mimetype = " << appIdentification << endl;
0040     Q_D(KoStore);
0041 
0042     d->localFileName = _filename;
0043 
0044     m_pZip = new KZip(_filename);
0045 
0046     init(appIdentification);   // open the zip file and init some vars
0047 }
0048 
0049 KoZipStore::KoZipStore(QIODevice *dev, Mode mode, const QByteArray & appIdentification,
0050                        bool writeMimetype)
0051   : KoStore(mode, writeMimetype)
0052 {
0053     m_pZip = new KZip(dev);
0054     init(appIdentification);
0055 }
0056 
0057 KoZipStore::KoZipStore(QWidget* window, const QUrl &_url, const QString & _filename, Mode mode,
0058                        const QByteArray & appIdentification, bool writeMimetype)
0059   : KoStore(mode, writeMimetype)
0060 {
0061     debugStore << "KoZipStore Constructor url" << _url.url(QUrl::PreferLocalFile)
0062     << " filename = " << _filename
0063     << " mode = " << int(mode)
0064     << " mimetype = " << appIdentification << endl;
0065     Q_D(KoStore);
0066 
0067     d->url = _url;
0068     d->window = window;
0069 
0070     if (mode == KoStore::Read) {
0071         d->fileMode = KoStorePrivate::RemoteRead;
0072         d->localFileName = _filename;
0073 
0074     } else {
0075         d->fileMode = KoStorePrivate::RemoteWrite;
0076         d->localFileName = QLatin1String("/tmp/kozip"); // ### FIXME with KTempFile
0077     }
0078 
0079     m_pZip = new KZip(d->localFileName);
0080     init(appIdentification);   // open the zip file and init some vars
0081 }
0082 
0083 KoZipStore::~KoZipStore()
0084 {
0085     Q_D(KoStore);
0086     debugStore << "KoZipStore::~KoZipStore";
0087     if (!d->finalized)
0088         finalize(); // ### no error checking when the app forgot to call finalize itself
0089     delete m_pZip;
0090 
0091     // Now we have still some job to do for remote files.
0092     if (d->fileMode == KoStorePrivate::RemoteRead) {
0093         KIO::NetAccess::removeTempFile(d->localFileName);
0094     } else if (d->fileMode == KoStorePrivate::RemoteWrite) {
0095         KIO::NetAccess::upload(d->localFileName, d->url, d->window);
0096         // ### FIXME: delete temp file
0097     }
0098 }
0099 
0100 void KoZipStore::init(const QByteArray& appIdentification)
0101 {
0102     Q_D(KoStore);
0103 
0104     m_currentDir = 0;
0105     d->good = m_pZip->open(d->mode == Write ? QIODevice::WriteOnly : QIODevice::ReadOnly);
0106 
0107     if (!d->good)
0108         return;
0109 
0110     if (d->mode == Write) {
0111         //debugStore <<"KoZipStore::init writing mimetype" << appIdentification;
0112 
0113         m_pZip->setCompression(KZip::NoCompression);
0114         m_pZip->setExtraField(KZip::NoExtraField);
0115 
0116         // Write identification
0117         if (d->writeMimetype) {
0118             (void)m_pZip->writeFile(QLatin1String("mimetype"), appIdentification);
0119         }
0120 
0121         m_pZip->setCompression(KZip::DeflateCompression);
0122         // We don't need the extra field in Calligra - so we leave it as "no extra field".
0123     } else {
0124         d->good = m_pZip->directory() != 0;
0125     }
0126 }
0127 
0128 void KoZipStore::setCompressionEnabled(bool e)
0129 {
0130     if (e) {
0131         m_pZip->setCompression(KZip::DeflateCompression);
0132     } else {
0133         m_pZip->setCompression(KZip::NoCompression);        
0134     }
0135 }
0136 
0137 bool KoZipStore::doFinalize()
0138 {
0139     return m_pZip->close();
0140 }
0141 
0142 bool KoZipStore::openWrite(const QString& name)
0143 {
0144     Q_D(KoStore);
0145     d->stream = 0; // Don't use!
0146     return m_pZip->prepareWriting(name, "", "" /*m_pZip->rootDir()->user(), m_pZip->rootDir()->group()*/, 0);
0147 }
0148 
0149 bool KoZipStore::openRead(const QString& name)
0150 {
0151     Q_D(KoStore);
0152     const KArchiveEntry * entry = m_pZip->directory()->entry(name);
0153     if (entry == 0) {
0154         return false;
0155     }
0156     if (entry->isDirectory()) {
0157         warnStore << name << " is a directory !";
0158         return false;
0159     }
0160     // Must cast to KZipFileEntry, not only KArchiveFile, because device() isn't virtual!
0161     const KZipFileEntry * f = static_cast<const KZipFileEntry *>(entry);
0162     delete d->stream;
0163     d->stream = f->createDevice();
0164     d->size = f->size();
0165     return true;
0166 }
0167 
0168 qint64 KoZipStore::write(const char* _data, qint64 _len)
0169 {
0170     Q_D(KoStore);
0171     if (_len == 0) return 0;
0172     //debugStore <<"KoZipStore::write" << _len;
0173 
0174     if (!d->isOpen) {
0175         errorStore << "KoStore: You must open before writing" << endl;
0176         return 0;
0177     }
0178     if (d->mode != Write) {
0179         errorStore << "KoStore: Can not write to store that is opened for reading" << endl;
0180         return 0;
0181     }
0182 
0183     d->size += _len;
0184     if (m_pZip->writeData(_data, _len))     // writeData returns a bool!
0185         return _len;
0186     return 0;
0187 }
0188 
0189 QStringList KoZipStore::directoryList() const
0190 {
0191     QStringList retval;
0192     const KArchiveDirectory *directory = m_pZip->directory();
0193     foreach(const QString &name, directory->entries()) {
0194         const KArchiveEntry* fileArchiveEntry = m_pZip->directory()->entry(name);
0195         if (fileArchiveEntry->isDirectory()) {
0196             retval << name;
0197         }
0198     }
0199     return retval;
0200 }
0201 
0202 bool KoZipStore::closeWrite()
0203 {
0204     Q_D(KoStore);
0205     debugStore << "Wrote file" << d->fileName << " into ZIP archive. size" << d->size;
0206     return m_pZip->finishWriting(d->size);
0207 }
0208 
0209 bool KoZipStore::enterRelativeDirectory(const QString& dirName)
0210 {
0211     Q_D(KoStore);
0212     if (d->mode == Read) {
0213         if (!m_currentDir) {
0214             m_currentDir = m_pZip->directory(); // initialize
0215             Q_ASSERT(d->currentPath.isEmpty());
0216         }
0217         const KArchiveEntry *entry = m_currentDir->entry(dirName);
0218         if (entry && entry->isDirectory()) {
0219             m_currentDir = dynamic_cast<const KArchiveDirectory*>(entry);
0220             return m_currentDir != 0;
0221         }
0222         return false;
0223     } else // Write, no checking here
0224         return true;
0225 }
0226 
0227 bool KoZipStore::enterAbsoluteDirectory(const QString& path)
0228 {
0229     if (path.isEmpty()) {
0230         m_currentDir = 0;
0231         return true;
0232     }
0233     m_currentDir = dynamic_cast<const KArchiveDirectory*>(m_pZip->directory()->entry(path));
0234     Q_ASSERT(m_currentDir);
0235     return m_currentDir != 0;
0236 }
0237 
0238 bool KoZipStore::fileExists(const QString& absPath) const
0239 {
0240     const KArchiveEntry *entry = m_pZip->directory()->entry(absPath);
0241     return entry && entry->isFile();
0242 }