summaryrefslogtreecommitdiffstats
path: root/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterufuncompressor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterufuncompressor.cpp')
-rw-r--r--installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterufuncompressor.cpp220
1 files changed, 220 insertions, 0 deletions
diff --git a/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterufuncompressor.cpp b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterufuncompressor.cpp
new file mode 100644
index 000000000..f5c36e44f
--- /dev/null
+++ b/installerbuilder/libinstaller/kdtools/KDUpdater/kdupdaterufuncompressor.cpp
@@ -0,0 +1,220 @@
+/****************************************************************************
+** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
+**
+** This file is part of the KD Tools library.
+**
+** Licensees holding valid commercial KD Tools licenses may use this file in
+** accordance with the KD Tools Commercial License Agreement provided with
+** the Software.
+**
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU Lesser General Public License version 2 and version 3 as published by the
+** Free Software Foundation and appearing in the file LICENSE.LGPL included.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Contact info@kdab.com if any conditions of this licensing are not
+** clear to you.
+**
+**********************************************************************/
+
+#include "kdupdaterufuncompressor_p.h"
+#include "kdupdaterufcompresscommon_p.h"
+
+#include <QCryptographicHash>
+#include <QDir>
+#include <QFile>
+#include <QFileInfo>
+#include <QFSFileEngine>
+#include <QDebug>
+
+using namespace KDUpdater;
+
+class UFUncompressor::Private
+{
+public:
+ QString ufFileName;
+ QString destination;
+ QString errorMessage;
+
+ void setError(const QString& msg);
+};
+
+void UFUncompressor::Private::setError(const QString& msg)
+{
+ errorMessage = msg;
+}
+
+UFUncompressor::UFUncompressor()
+{
+}
+
+UFUncompressor::~UFUncompressor()
+{
+}
+
+QString UFUncompressor::errorString() const
+{
+ return d->errorMessage;
+}
+
+void UFUncompressor::setFileName(const QString& fileName)
+{
+ d->ufFileName = fileName;
+}
+
+QString UFUncompressor::fileName() const
+{
+ return d->ufFileName;
+}
+
+void UFUncompressor::setDestination(const QString& dest)
+{
+ d->destination = dest;
+}
+
+QString UFUncompressor::destination() const
+{
+ return d->destination;
+}
+
+bool UFUncompressor::uncompress()
+{
+ d->errorMessage.clear();
+
+ // First open the uf file for reading
+ QFile ufFile( d->ufFileName );
+ if( !ufFile.open(QFile::ReadOnly) ) {
+ d->setError(tr("Couldn't open file for reading: %1").arg( ufFile.errorString() ));
+ return false;
+ }
+
+ QDataStream ufDS( &ufFile );
+ ufDS.setVersion( QDataStream::Qt_4_2 );
+ QCryptographicHash hash( QCryptographicHash::Md5 );
+
+ // Now read the header.
+ UFHeader header;
+ ufDS >> header;
+ if( ufDS.status() != QDataStream::Ok || !header.isValid() )
+ {
+ d->setError( tr( "Couldn't read the file header." ) );
+ return false;
+ }
+ header.addToHash(hash);
+
+ // Some basic checks.
+ if( header.magic != QLatin1String( KD_UPDATER_UF_HEADER_MAGIC ) ) {
+ d->setError(tr("Wrong file format (magic number not found)"));
+ return false;
+ }
+
+ // Lets get to the destination directory
+ const QDir dir(d->destination);
+ QFSFileEngine fileEngine;
+
+ // Lets create the required directory structure
+ int numExpectedFiles = 0;
+ for(int i=0; i<header.fileList.count(); i++)
+ {
+ const QString fileName = header.fileList[i];
+ // qDebug("ToUncompress %s", qPrintable(fileName));
+ if( header.isDirList[i] )
+ {
+ if ( !dir.mkpath( fileName ) )
+ {
+ d->setError(tr("Could not create folder: %1/%2").arg( d->destination, fileName ));
+ return false;
+ }
+ fileEngine.setFileName( QString(QLatin1String( "%1/%2" )).arg(d->destination, fileName) );
+ fileEngine.setPermissions( header.permList[i] | QAbstractFileEngine::ExeOwnerPerm );
+ } else {
+ ++numExpectedFiles;
+ }
+ }
+
+ // Lets now create files within these directories
+ int numActualFiles = 0;
+ while( !ufDS.atEnd() && numActualFiles < numExpectedFiles )
+ {
+ UFEntry ufEntry;
+ ufDS >> ufEntry;
+ if( ufDS.status() != QDataStream::Ok || !ufEntry.isValid() )
+ {
+ d->setError( tr( "Could not read information for entry %1." ).arg( numActualFiles ) );
+ return false;
+ }
+ ufEntry.addToHash(hash);
+
+ const QString completeFileName = QString(QLatin1String( "%1/%2" )).arg(d->destination, ufEntry.fileName);
+
+ const QByteArray ba = qUncompress( ufEntry.fileData );
+ // check the size
+ QDataStream stream( ufEntry.fileData );
+ stream.setVersion( QDataStream::Qt_4_2 );
+ qint32 length = 0;
+ stream >> length;
+ if( ba.length() != length ) // uncompress failed
+ {
+ d->setError(tr("Could not uncompress entry %1, corrupt data").arg( ufEntry.fileName ) );
+ return false;
+
+ }
+
+
+ QFile ufeFile( completeFileName );
+ if ( !ufeFile.open( QFile::WriteOnly ) )
+ {
+ d->setError(tr("Could not open file %1 for writing: %2").arg( completeFileName, ufeFile.errorString() ));
+ return false;
+ }
+
+
+ const char* const data = ba.constData();
+ const qint64 total = ba.size();
+ qint64 written = 0;
+
+ while ( written < total )
+ {
+ const qint64 num = ufeFile.write( data+written, total-written );
+ if ( num == -1 )
+ {
+ d->setError( tr("Failed writing uncompressed data to %1: %2").arg( completeFileName, ufeFile.errorString() ) );
+ return false;
+ }
+ written += num;
+ }
+
+ ufeFile.close();
+
+ const QFile::Permissions perm = static_cast< QFile::Permissions >( ufEntry.permissions );
+ ufeFile.setPermissions( perm );
+
+ if ( ufeFile.error() != QFile::NoError )
+ {
+ ufeFile.remove();
+ d->setError( tr("Failed writing uncompressed data to %1: %2").arg( completeFileName, ufeFile.errorString() ) );
+ return false;
+ }
+
+ qDebug("Uncompressed %s", qPrintable(completeFileName));
+ ++numActualFiles;
+ }
+
+ if( numExpectedFiles != numActualFiles ) {
+ d->errorMessage = tr("Corrupt file (wrong number of files)");
+ return false;
+ }
+
+ QByteArray hashdata;
+ ufDS >> hashdata;
+
+ if( hashdata != hash.result() ) {
+ d->errorMessage = tr("Corrupt file (wrong hash)");
+ return false;
+ }
+
+ return true;
+}