diff --git a/rbutil/rbutilqt/base/bootloaderinstallbase.cpp b/rbutil/rbutilqt/base/bootloaderinstallbase.cpp index 750e33bef8..7941f24309 100644 --- a/rbutil/rbutilqt/base/bootloaderinstallbase.cpp +++ b/rbutil/rbutilqt/base/bootloaderinstallbase.cpp @@ -31,6 +31,7 @@ #include "bootloaderinstallmpio.h" #include "bootloaderinstallimx.h" #include "utils.h" +#include "ziputil.h" #if defined(Q_OS_MACX) #include @@ -320,3 +321,43 @@ void BootloaderInstallBase::setBlFile(QStringList sl) } } +bool BootloaderInstallBase::setOfFile(QString of, QStringList blfile) +{ + bool found = false; + ZipUtil z(this); + // check if the file set is in zip format + if(z.open(of)) { + emit logItem(tr("Zip file format detected"), LOGINFO); + QStringList contents = z.files(); + qDebug() << "[BootloaderInstallBase] archive contains:" << contents; + for(int i = 0; i < blfile.size(); ++i) { + // strip any path, we don't know the structure in the zip + QString f = QFileInfo(blfile.at(i)).fileName(); + qDebug() << "[BootloaderInstallBase] searching archive for" << f; + int index = contents.indexOf(f); // FIXME: support files in folders + if(index >= 0) { + found = true; + emit logItem(tr("Extracting firmware %1 from archive") + .arg(f), LOGINFO); + // store in class temporary file + m_tempof.open(); + m_offile = m_tempof.fileName(); + m_tempof.close(); + if(!z.extractArchive(m_offile, contents.at(index))) { + emit logItem(tr("Error extracting firmware from archive"), LOGERROR); + found = false; + break; + } + } + } + if(!found) { + emit logItem(tr("Could not find firmware in archive"), LOGERROR); + } + + } + else { + m_offile = of; + found = true; + } + return found; +} diff --git a/rbutil/rbutilqt/base/bootloaderinstallbase.h b/rbutil/rbutilqt/base/bootloaderinstallbase.h index 8198d54e76..0e970c4af6 100644 --- a/rbutil/rbutilqt/base/bootloaderinstallbase.h +++ b/rbutil/rbutilqt/base/bootloaderinstallbase.h @@ -60,8 +60,7 @@ class BootloaderInstallBase : public QObject { m_blurl = u; } void setLogfile(QString f) { m_logfile = f; } - void setOfFile(QString f) - {m_offile = f;} + bool setOfFile(QString of, QStringList blfile); //! returns a port Install Hint or empty if there is none //! static and in the base class, so the installer classes dont need to @@ -90,6 +89,7 @@ class BootloaderInstallBase : public QObject QString m_logfile; //! file for installation log QUrl m_blurl; //! bootloader download URL QTemporaryFile m_tempfile; //! temporary file for download + QTemporaryFile m_tempof; //! temporary file for OF extracted from archive QDateTime m_blversion; //! download timestamp used for version information QString m_offile; //! path to the offile #if defined(Q_OS_MACX) diff --git a/rbutil/rbutilqt/base/ziputil.cpp b/rbutil/rbutilqt/base/ziputil.cpp index 481ad4c2ae..b9218a70bc 100644 --- a/rbutil/rbutilqt/base/ziputil.cpp +++ b/rbutil/rbutilqt/base/ziputil.cpp @@ -70,10 +70,13 @@ bool ZipUtil::close(void) //! @brief extract currently opened archive -//! @brief dest path to extract archive to +//! @brief dest path to extract archive to, can be filename when extracting a +//! single file. +//! @brief file file to extract from archive, full archive if empty. //! @return true on success, false otherwise -bool ZipUtil::extractArchive(QString& dest) +bool ZipUtil::extractArchive(QString& dest, QString file) { + qDebug() << "[ZipUtil] extractArchive" << dest << file; bool result = true; if(!m_zip) { return false; @@ -81,6 +84,16 @@ bool ZipUtil::extractArchive(QString& dest) QuaZipFile *currentFile = new QuaZipFile(m_zip); int entries = m_zip->getEntriesCount(); int current = 0; + // construct the filename when extracting a single file from an archive. + // if the given destination is a full path use it as output name, + // otherwise use it as path to place the file as named in the archive. + QString singleoutfile; + if(!file.isEmpty() && QFileInfo(dest).isDir()) { + singleoutfile = dest + "/" + file; + } + else if(!file.isEmpty()){ + singleoutfile = dest; + } for(bool more = m_zip->goToFirstFile(); more; more = m_zip->goToNextFile()) { ++current; @@ -88,7 +101,16 @@ bool ZipUtil::extractArchive(QString& dest) if(m_zip->getCurrentFileName().split("/").last() == "") continue; - QString outfilename = dest + "/" + m_zip->getCurrentFileName(); + QString outfilename; + if(!singleoutfile.isEmpty() + && QFileInfo(m_zip->getCurrentFileName()).fileName() == file) { + outfilename = singleoutfile; + } + else if(singleoutfile.isEmpty()) { + outfilename = dest + "/" + m_zip->getCurrentFileName(); + } + if(outfilename.isEmpty()) + continue; QFile outputFile(outfilename); // make sure the output path exists if(!QDir().mkpath(QFileInfo(outfilename).absolutePath())) { diff --git a/rbutil/rbutilqt/base/ziputil.h b/rbutil/rbutilqt/base/ziputil.h index 9cbb67488a..a6b0a8ca9c 100644 --- a/rbutil/rbutilqt/base/ziputil.h +++ b/rbutil/rbutilqt/base/ziputil.h @@ -31,9 +31,9 @@ class ZipUtil : public QObject public: ZipUtil(QObject* parent); ~ZipUtil(); - bool open(QString& zipfile, QuaZip::Mode mode); + bool open(QString& zipfile, QuaZip::Mode mode = QuaZip::mdUnzip); bool close(void); - bool extractArchive(QString& dest); + bool extractArchive(QString& dest, QString file = ""); bool appendDirToArchive(QString& source, QString& basedir); bool appendFileToArchive(QString& file, QString& basedir); qint64 totalUncompressedSize(unsigned int clustersize = 0); diff --git a/rbutil/rbutilqt/rbutilqt.cpp b/rbutil/rbutilqt/rbutilqt.cpp index 403d13a760..958550e880 100644 --- a/rbutil/rbutilqt/rbutilqt.cpp +++ b/rbutil/rbutilqt/rbutilqt.cpp @@ -708,7 +708,14 @@ void RbUtilQt::installBootloader() logger->setFinished(); return; } - + + // the bootloader install class does NOT use any GUI stuff. + // All messages are passed via signals. + connect(bl, SIGNAL(done(bool)), logger, SLOT(setFinished())); + connect(bl, SIGNAL(done(bool)), this, SLOT(installBootloaderPost(bool))); + connect(bl, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int))); + connect(bl, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int))); + // set bootloader filename. Do this now as installed() needs it. QStringList blfile = SystemInfo::value(SystemInfo::CurBootloaderFile).toStringList(); QStringList blfilepath; @@ -788,16 +795,14 @@ void RbUtilQt::installBootloader() m_error = true; return; } - bl->setOfFile(offile); + if(!bl->setOfFile(offile, blfile)) { + logger->addItem(tr("Error reading firmware file"), LOGERROR); + logger->setFinished(); + m_error = true; + return; + } } - // the bootloader install class does NOT use any GUI stuff. - // All messages are passed via signals. - connect(bl, SIGNAL(done(bool)), logger, SLOT(setFinished())); - connect(bl, SIGNAL(done(bool)), this, SLOT(installBootloaderPost(bool))); - connect(bl, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int))); - connect(bl, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int))); - // start install. if(!backupDestination.isEmpty()) { if(!bl->backup(backupDestination)) {