File indexing completed on 2024-05-19 04:52:44

0001 /* This file is part of the KDE project
0002     SPDX-FileCopyrightText: 2000-2002 David Faure <faure@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "KoZipStore.h"
0008 
0009 #include "kostore_log.h"
0010 
0011 #include <KZip>
0012 #include <KIO/StoredTransferJob>
0013 #include <KJobWidgets>
0014 #include <QBuffer>
0015 #include <QByteArray>
0016 #include <QUrl>
0017 
0018 KoZipStore::KoZipStore( const QString & _filename, Mode _mode, const QByteArray & appIdentification )
0019 {
0020     qCDebug(K3B_KOSTORE_LOG) <<"KoZipStore Constructor filename =" << _filename
0021                     << " mode = " << int(_mode)
0022                     << " mimetype = " << appIdentification << Qt::endl;
0023 
0024     m_pZip = new KZip( _filename );
0025 
0026         m_bGood = initZipStore( _mode, appIdentification ); // open the zip file and init some vars
0027 }
0028 
0029 KoZipStore::KoZipStore( QIODevice *dev, Mode mode, const QByteArray & appIdentification )
0030 {
0031     m_pZip = new KZip( dev );
0032     m_bGood = initZipStore( mode, appIdentification );
0033 }
0034 
0035 KoZipStore::KoZipStore( QWidget* window, const QUrl & _url, const QString & _filename, Mode _mode, const QByteArray & appIdentification )
0036 {
0037     qCDebug(K3B_KOSTORE_LOG) <<"KoZipStore Constructor url" << _url.toDisplayString( QUrl::PreferLocalFile )
0038                     << " filename = " << _filename
0039                     << " mode = " << int(_mode)
0040                     << " mimetype = " << appIdentification << Qt::endl;
0041 
0042     m_url = _url;
0043     m_window = window;
0044 
0045     if ( _mode == KoStore::Read )
0046     {
0047         m_fileMode = KoStoreBase::RemoteRead;
0048         m_localFileName = _filename;
0049 
0050     }
0051     else
0052     {
0053         m_fileMode = KoStoreBase::RemoteWrite;
0054         m_localFileName = "/var/tmp/kozip"; // ### FIXME with KTempFile
0055     }
0056 
0057     m_pZip = new KZip( m_localFileName );
0058     m_bGood = initZipStore( _mode, appIdentification ); // open the zip file and init some vars
0059 }
0060 
0061 KoZipStore::~KoZipStore()
0062 {
0063     qCDebug(K3B_KOSTORE_LOG) <<"KoZipStore::~KoZipStore";
0064     if ( !m_bFinalized )
0065         finalize(); // ### no error checking when the app forgot to call finalize itself
0066     delete m_pZip;
0067 
0068     // Now we have still some job to do for remote files.
0069     if ( m_fileMode == KoStoreBase::RemoteRead )
0070     {
0071         QFile::remove( m_localFileName );
0072     }
0073     else if ( m_fileMode == KoStoreBase::RemoteWrite )
0074     {
0075         QFile file( m_localFileName );
0076         if( file.open( QFile::ReadOnly ) )
0077         {
0078             KIO::StoredTransferJob* transferJob = KIO::storedPut( file.readAll(), m_url, -1 );
0079             KJobWidgets::setWindow( transferJob, m_window );
0080             transferJob->exec();
0081         }
0082         // ### FIXME: delete temp file
0083     }
0084 }
0085 
0086 bool KoZipStore::initZipStore( Mode _mode, const QByteArray& appIdentification )
0087 {
0088     KoStore::init( _mode );
0089     m_currentDir = 0;
0090     bool good = m_pZip->open( _mode == Write ? QIODevice::WriteOnly : QIODevice::ReadOnly );
0091 
0092     if ( good && _mode == Read )
0093         good = m_pZip->directory() != 0;
0094     else if ( good && _mode == Write )
0095     {
0096         //qCDebug(K3B_KOSTORE_LOG) <<"KoZipStore::init writing mimetype" << appIdentification;
0097 
0098         m_pZip->setCompression( KZip::NoCompression );
0099         m_pZip->setExtraField( KZip::NoExtraField );
0100         // Write identification
0101         m_pZip->writeFile( "mimetype", appIdentification );
0102         m_pZip->setCompression( KZip::DeflateCompression );
0103         // We don't need the extra field in KOffice - so we leave it as "no extra field".
0104     }
0105     return good;
0106 }
0107 
0108 bool KoZipStore::doFinalize()
0109 {
0110     return m_pZip->close();
0111 }
0112 
0113 bool KoZipStore::openWrite( const QString& name )
0114 {
0115 #if 0
0116     // Prepare memory buffer for writing
0117     m_byteArray.resize( 0 );
0118     m_stream = new QBuffer( m_byteArray );
0119     m_stream->open( QIODevice::WriteOnly );
0120     return true;
0121 #endif
0122     m_stream = 0L; // Don't use!
0123     return m_pZip->prepareWriting( name, "", "" /*m_pZip->rootDir()->user(), m_pZip->rootDir()->group()*/, 0 );
0124 }
0125 
0126 bool KoZipStore::openRead( const QString& name )
0127 {
0128     const KArchiveEntry * entry = m_pZip->directory()->entry( name );
0129     if ( entry == 0L )
0130     {
0131         //qCWarning(K3B_KOSTORE_LOG) << "Unknown filename " << name;
0132         //return KIO::ERR_DOES_NOT_EXIST;
0133         return false;
0134     }
0135     if ( entry->isDirectory() )
0136     {
0137         qCWarning(K3B_KOSTORE_LOG) << name << " is a directory !";
0138         //return KIO::ERR_IS_DIRECTORY;
0139         return false;
0140     }
0141     // Must cast to KZipFileEntry, not only KArchiveFile, because device() isn't virtual!
0142     const KZipFileEntry * f = static_cast<const KZipFileEntry *>(entry);
0143     delete m_stream;
0144     m_stream = f->createDevice();
0145     m_iSize = f->size();
0146     return true;
0147 }
0148 
0149 qint64 KoZipStore::write( const char* _data, qint64 _len )
0150 {
0151   if ( _len == 0L ) return 0;
0152   //qCDebug(K3B_KOSTORE_LOG) <<"KoZipStore::write" << _len;
0153 
0154   if ( !m_bIsOpen )
0155   {
0156     qCCritical(K3B_KOSTORE_LOG) << "KoStore: You must open before writing" << Qt::endl;
0157     return 0L;
0158   }
0159   if ( m_mode != Write  )
0160   {
0161     qCCritical(K3B_KOSTORE_LOG) << "KoStore: Can not write to store that is opened for reading" << Qt::endl;
0162     return 0L;
0163   }
0164 
0165   m_iSize += _len;
0166   if ( m_pZip->writeData( _data, _len ) ) // writeData returns a bool!
0167       return _len;
0168   return 0L;
0169 }
0170 
0171 bool KoZipStore::closeWrite()
0172 {
0173     qCDebug(K3B_KOSTORE_LOG) <<"Wrote file" << m_sName <<" into ZIP archive. size"
0174                     << m_iSize << Qt::endl;
0175     return m_pZip->finishWriting( m_iSize );
0176 #if 0
0177     if ( !m_pZip->writeFile( m_sName , "user", "group", m_iSize, m_byteArray.data() ) )
0178         qCWarning( KOSTORE ) << "Failed to write " << m_sName;
0179     m_byteArray.resize( 0 ); // save memory
0180     return true;
0181 #endif
0182 }
0183 
0184 bool KoZipStore::enterRelativeDirectory( const QString& dirName )
0185 {
0186     if ( m_mode == Read ) {
0187         if ( !m_currentDir ) {
0188             m_currentDir = m_pZip->directory(); // initialize
0189             Q_ASSERT( m_currentPath.isEmpty() );
0190         }
0191         const KArchiveEntry *entry = m_currentDir->entry( dirName );
0192         if ( entry && entry->isDirectory() ) {
0193             m_currentDir = dynamic_cast<const KArchiveDirectory*>( entry );
0194             return m_currentDir != 0;
0195         }
0196         return false;
0197     }
0198     else  // Write, no checking here
0199         return true;
0200 }
0201 
0202 bool KoZipStore::enterAbsoluteDirectory( const QString& path )
0203 {
0204     if ( path.isEmpty() )
0205     {
0206         m_currentDir = 0;
0207         return true;
0208     }
0209     m_currentDir = dynamic_cast<const KArchiveDirectory*>( m_pZip->directory()->entry( path ) );
0210     Q_ASSERT( m_currentDir );
0211     return m_currentDir != 0;
0212 }
0213 
0214 bool KoZipStore::fileExists( const QString& absPath ) const
0215 {
0216     const KArchiveEntry *entry = m_pZip->directory()->entry( absPath );
0217     return entry && entry->isFile();
0218 }