OSDN Git Service

Actually implement the auto-updater.
authorlordmulder <mulder2@gmx.de>
Sun, 28 Nov 2010 21:18:07 +0000 (22:18 +0100)
committerlordmulder <mulder2@gmx.de>
Sun, 28 Nov 2010 21:18:07 +0000 (22:18 +0100)
gui/UpdateDialog.ui
res/Icons.qrc
res/Tools.qrc
res/tools/gpgv.gpg [new file with mode: 0644]
src/Config.h
src/Dialog_Update.cpp
src/Dialog_Update.h
src/Thread_Initialization.cpp

index 35b4af3..a0937d3 100644 (file)
@@ -6,7 +6,7 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>622</width>
+    <width>642</width>
     <height>364</height>
    </rect>
   </property>
           <number>0</number>
          </property>
          <layout class="QVBoxLayout" name="verticalLayout_4">
-          <property name="margin">
-           <number>18</number>
+          <property name="leftMargin">
+           <number>32</number>
+          </property>
+          <property name="topMargin">
+           <number>42</number>
+          </property>
+          <property name="rightMargin">
+           <number>32</number>
+          </property>
+          <property name="bottomMargin">
+           <number>32</number>
           </property>
           <item>
            <layout class="QVBoxLayout" name="verticalLayout_3">
             <item>
-             <spacer name="verticalSpacer_2">
-              <property name="orientation">
-               <enum>Qt::Vertical</enum>
-              </property>
-              <property name="sizeType">
-               <enum>QSizePolicy::Fixed</enum>
-              </property>
-              <property name="sizeHint" stdset="0">
-               <size>
-                <width>20</width>
-                <height>40</height>
-               </size>
-              </property>
-             </spacer>
-            </item>
-            <item>
              <widget class="QLabel" name="statusLabel">
               <property name="font">
                <font>
               </property>
              </spacer>
             </item>
+            <item>
+             <layout class="QGridLayout" name="gridLayout">
+              <item row="1" column="0">
+               <widget class="QLabel" name="label">
+                <property name="text">
+                 <string>Latest version available:</string>
+                </property>
+               </widget>
+              </item>
+              <item row="1" column="2">
+               <widget class="QLabel" name="labelVersionLatest">
+                <property name="text">
+                 <string>(Unknown)</string>
+                </property>
+               </widget>
+              </item>
+              <item row="0" column="0">
+               <widget class="QLabel" name="label_3">
+                <property name="text">
+                 <string>Currently installed version:</string>
+                </property>
+               </widget>
+              </item>
+              <item row="0" column="2">
+               <widget class="QLabel" name="labelVersionInstalled">
+                <property name="text">
+                 <string>(Unknown)</string>
+                </property>
+               </widget>
+              </item>
+              <item row="0" column="3">
+               <spacer name="horizontalSpacer_2">
+                <property name="orientation">
+                 <enum>Qt::Horizontal</enum>
+                </property>
+                <property name="sizeHint" stdset="0">
+                 <size>
+                  <width>40</width>
+                  <height>20</height>
+                 </size>
+                </property>
+               </spacer>
+              </item>
+              <item row="1" column="3">
+               <spacer name="horizontalSpacer_3">
+                <property name="orientation">
+                 <enum>Qt::Horizontal</enum>
+                </property>
+                <property name="sizeHint" stdset="0">
+                 <size>
+                  <width>40</width>
+                  <height>20</height>
+                 </size>
+                </property>
+               </spacer>
+              </item>
+              <item row="0" column="1">
+               <spacer name="horizontalSpacer_4">
+                <property name="orientation">
+                 <enum>Qt::Horizontal</enum>
+                </property>
+                <property name="sizeType">
+                 <enum>QSizePolicy::Fixed</enum>
+                </property>
+                <property name="sizeHint" stdset="0">
+                 <size>
+                  <width>15</width>
+                  <height>20</height>
+                 </size>
+                </property>
+               </spacer>
+              </item>
+              <item row="1" column="1">
+               <spacer name="horizontalSpacer_5">
+                <property name="orientation">
+                 <enum>Qt::Horizontal</enum>
+                </property>
+                <property name="sizeType">
+                 <enum>QSizePolicy::Fixed</enum>
+                </property>
+                <property name="sizeHint" stdset="0">
+                 <size>
+                  <width>15</width>
+                  <height>20</height>
+                 </size>
+                </property>
+               </spacer>
+              </item>
+             </layout>
+            </item>
+            <item>
+             <spacer name="verticalSpacer_2">
+              <property name="orientation">
+               <enum>Qt::Vertical</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>20</width>
+                <height>40</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+            <item>
+             <widget class="QLabel" name="infoLabel">
+              <property name="text">
+               <string>$(INFORMATION)</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <spacer name="verticalSpacer_4">
+              <property name="orientation">
+               <enum>Qt::Vertical</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>20</width>
+                <height>40</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+            <item>
+             <layout class="QHBoxLayout" name="horizontalLayout_4">
+              <item>
+               <widget class="QPushButton" name="retryButton">
+                <property name="minimumSize">
+                 <size>
+                  <width>100</width>
+                  <height>0</height>
+                 </size>
+                </property>
+                <property name="text">
+                 <string>Retry</string>
+                </property>
+                <property name="icon">
+                 <iconset resource="../res/Icons.qrc">
+                  <normaloff>:/icons/arrow_refresh.png</normaloff>:/icons/arrow_refresh.png</iconset>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <spacer name="horizontalSpacer_6">
+                <property name="orientation">
+                 <enum>Qt::Horizontal</enum>
+                </property>
+                <property name="sizeHint" stdset="0">
+                 <size>
+                  <width>40</width>
+                  <height>20</height>
+                 </size>
+                </property>
+               </spacer>
+              </item>
+             </layout>
+            </item>
            </layout>
           </item>
          </layout>
   <include location="../res/Images.qrc"/>
   <include location="../res/Images.qrc"/>
   <include location="../res/Images.qrc"/>
+  <include location="../res/Images.qrc"/>
+  <include location="../res/Images.qrc"/>
+  <include location="../res/Images.qrc"/>
  </resources>
  <connections>
   <connection>
index 0f8a555..ab39e21 100644 (file)
@@ -9,6 +9,7 @@
     <file>icons/application_xp_terminal.png</file>
     <file>icons/arrow_down.png</file>
     <file>icons/arrow_up.png</file>
+    <file>icons/arrow_refresh.png</file>
     <file>icons/bin.png</file>
     <file>icons/bomb.png</file>
     <file>icons/calendar.png</file>
index 1487593..0154dfe 100644 (file)
@@ -5,6 +5,7 @@
     <file>tools/faad.exe</file>
     <file>tools/flac.exe</file>
     <file>tools/gpgv.exe</file>
+    <file>tools/gpgv.gpg</file>
     <file>tools/lame.exe</file>
     <file>tools/MAC.exe</file>
     <file>tools/mediainfo_icl11.exe</file>
diff --git a/res/tools/gpgv.gpg b/res/tools/gpgv.gpg
new file mode 100644 (file)
index 0000000..8ac5f57
Binary files /dev/null and b/res/tools/gpgv.gpg differ
index bb9bcd2..c1c8d77 100644 (file)
@@ -25,7 +25,7 @@
 #define VER_LAMEXP_MAJOR                               4
 #define VER_LAMEXP_MINOR_HI                            0
 #define VER_LAMEXP_MINOR_LO                            0
-#define VER_LAMEXP_BUILD                               89
+#define VER_LAMEXP_BUILD                               95
 #define VER_LAMEXP_SUFFIX                              TechPreview
 
 /*
index 0d86a2f..e9ccf99 100644 (file)
 
 #include "Dialog_Update.h"
 
+#include "Global.h"
+#include "Resource.h"
+
 #include <QClipboard>
 #include <QFileDialog>
 #include <QTimer>
+#include <QProcess>
+#include <QUuid>
+#include <QDate>
+#include <QRegExp>
+#include <QDesktopServices>
+#include <QUrl>
+#include <QCloseEvent>
 
 #include <Windows.h>
 
+///////////////////////////////////////////////////////////////////////////////
+
+static const char *section_id = "LameXP";
+
+static const char *mirror_url_postfix = "update_beta.ver";
+
+static const char *mirrors[] =
+{
+       "http://mulder.dummwiedeutsch.de/",
+       "http://mulder.brhack.net/",
+       "http://free.pages.at/borschdfresser/",
+       "http://mplayer.savedonthe.net/",
+       "http://www.tricksoft.de/",
+       NULL
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class UpdateInfo
+{
+public:
+       UpdateInfo(void)
+       :
+               m_buildNo(0),
+               m_buildDate(1900, 1, 1),
+               m_downloadSite(""),
+               m_downloadAddress(""),
+               m_downloadFilename(""),
+               m_downloadFilecode("")
+       {
+       }
+       
+       unsigned int m_buildNo;
+       QDate m_buildDate;
+       QString m_downloadSite;
+       QString m_downloadAddress;
+       QString m_downloadFilename;
+       QString m_downloadFilecode;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
 UpdateDialog::UpdateDialog(QWidget *parent)
 :
-       QDialog(parent)
+       QDialog(parent),
+       m_binaryWGet(lamexp_lookup_tool("wget.exe")),
+       m_binaryGnuPG(lamexp_lookup_tool("gpgv.exe")),
+       m_binaryUpdater(lamexp_lookup_tool("wupdate.exe")),
+       m_binaryKeys(lamexp_lookup_tool("gpgv.gpg")),
+       m_updateInfo(NULL)
 {
+       if(m_binaryWGet.isEmpty() || m_binaryGnuPG.isEmpty() || m_binaryUpdater.isEmpty() || m_binaryKeys.isEmpty())
+       {
+               throw "Tools not initialized correctly!";
+       }
+       
        //Init the dialog, from the .ui file
        setupUi(this);
        setWindowFlags(windowFlags() ^ Qt::WindowContextHelpButtonHint);
-       setMinimumSize(size());
-       setMaximumHeight(height());
 
        //Disable "X" button
        HMENU hMenu = GetSystemMenu((HWND) winId(), FALSE);
        EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);
 
-       //Init flags
-       m_clipboardUsed = false;
+       //Enable button
+       connect(retryButton, SIGNAL(clicked()), this, SLOT(checkForUpdates()));
+       connect(installButton, SIGNAL(clicked()), this, SLOT(applyUpdate()));
+       connect(infoLabel, SIGNAL(linkActivated(QString)), this, SLOT(linkActivated(QString)));
 }
 
 UpdateDialog::~UpdateDialog(void)
 {
-       if(m_clipboardUsed)
-       {
-               QApplication::clipboard()->clear();
-       }
+       LAMEXP_DELETE(m_updateInfo);
 }
 
 void UpdateDialog::showEvent(QShowEvent *event)
 {
+       QDialog::showEvent(event);
+       
        statusLabel->setText("Checking for new updates online, please wait...");
-       QTimer::singleShot(8000, this, SLOT(updateCompleted()));
+       labelVersionInstalled->setText(QString("Build %1 (%2)").arg(QString::number(lamexp_version_build()), lamexp_version_date().toString(Qt::ISODate)));
+       labelVersionLatest->setText("(Unknown)");
+
+       QTimer::singleShot(0, this, SLOT(updateInit()));
        installButton->setEnabled(false);
        closeButton->setEnabled(false);
+       retryButton->setEnabled(false);
+       retryButton->hide();
+       infoLabel->hide();
+       
+       for(int i = 0; mirrors[i]; i++)
+       {
+               progressBar->setMaximum(i+2);
+       }
+
+       progressBar->setValue(0);
+}
+
+void UpdateDialog::closeEvent(QCloseEvent *event)
+{
+       if(!closeButton->isEnabled()) event->ignore();
 }
 
-void UpdateDialog::updateCompleted(void)
+void UpdateDialog::updateInit(void)
 {
-       statusLabel->setText("No new updates avialbale. Your version of LameXP is up-to-date.");
+       setMinimumSize(size());
+       setMaximumHeight(height());
+
+       checkForUpdates();
+}
+
+void UpdateDialog::checkForUpdates(void)
+{
+       bool success = false;
+       m_updateInfo = new UpdateInfo;
+
+       progressBar->setValue(0);
+       installButton->setEnabled(false);
+       closeButton->setEnabled(false);
+       retryButton->setEnabled(false);
+       if(infoLabel->isVisible()) infoLabel->hide();
+
+       QApplication::processEvents();
+       QApplication::setOverrideCursor(Qt::WaitCursor);
+
+       for(int i = 0; mirrors[i]; i++)
+       {
+               progressBar->setValue(i+1);
+               if(tryUpdateMirror(m_updateInfo, mirrors[i]))
+               {
+                       success = true;
+                       break;
+               }
+       }
+       
+       QApplication::restoreOverrideCursor();
+
+       if(!success)
+       {
+               if(!retryButton->isVisible()) retryButton->show();
+               closeButton->setEnabled(true);
+               retryButton->setEnabled(true);
+               statusLabel->setText("Failed to fetch update information. Check internet connection!");
+               progressBar->setValue(progressBar->maximum());
+               LAMEXP_DELETE(m_updateInfo);
+               PlaySound(MAKEINTRESOURCE(IDR_WAVE_ERROR), GetModuleHandle(NULL), SND_RESOURCE | SND_ASYNC);
+               return;
+       }
+       
+       labelVersionLatest->setText(QString("Build %1 (%2)").arg(QString::number(m_updateInfo->m_buildNo), m_updateInfo->m_buildDate.toString(Qt::ISODate)));
+       infoLabel->show();
+       infoLabel->setText(QString("More information available at:<br><a href=\"%1\">%1</a>").arg(m_updateInfo->m_downloadSite));
+       QApplication::processEvents();
+       
+       if(m_updateInfo->m_buildNo > lamexp_version_build())
+       {
+               installButton->setEnabled(true);
+               statusLabel->setText("A new version of LameXP is available. Update highly recommended!");
+               MessageBeep(MB_ICONINFORMATION);
+       }
+       else if(m_updateInfo->m_buildNo == lamexp_version_build())
+       {
+               statusLabel->setText("No new updates avialbale. Your version of LameXP is up-to-date.");
+               MessageBeep(MB_ICONINFORMATION);
+       }
+       else
+       {
+               statusLabel->setText("Your version appears to be newer than the latest release.");
+               MessageBeep(MB_ICONEXCLAMATION);
+       }
+
        closeButton->setEnabled(true);
+       if(retryButton->isVisible()) retryButton->hide();
+       progressBar->setValue(progressBar->maximum());
 }
 
+bool UpdateDialog::tryUpdateMirror(UpdateInfo *updateInfo, const QString &url)
+{
+       bool success = false;
+       
+       QUuid uuid = QUuid::createUuid();
+       QString outFileVersionInfo = QString("%1/%2.ver").arg(QDir::tempPath(), uuid.toString());
+       QString outFileSignature = QString("%1/%2.sig").arg(QDir::tempPath(), uuid.toString());
+
+       qDebug("\nDownloading update info:");
+       bool ok1 = getFile(QString("%1%2").arg(url,mirror_url_postfix), outFileVersionInfo);
+
+       qDebug("\nDownloading signature file:");
+       bool ok2 = getFile(QString("%1%2.sig").arg(url,mirror_url_postfix), outFileSignature);
+
+       if(ok1 && ok2)
+       {
+               qDebug("\nDownload okay, checking signature:");
+               if(checkSignature(outFileVersionInfo, outFileSignature))
+               {
+                       qDebug("\nSignature okay, parsing info:");
+                       success = parseVersionInfo(outFileVersionInfo, updateInfo);
+               }
+               else
+               {
+                       qDebug("\nBad signature, take care!");
+               }
+       }
+       else
+       {
+               qDebug("\nDownload has failed!");
+       }
+
+       QFile::remove(outFileVersionInfo);
+       QFile::remove(outFileSignature);
+       
+       return success;
+}
+
+bool UpdateDialog::getFile(const QString &url, const QString &outFile)
+{
+       QFileInfo output(outFile);
+       output.setCaching(false);
+
+       if(output.exists())
+       {
+               QFile::remove(output.canonicalFilePath());
+               if(output.exists())
+               {
+                       return false;
+               }
+       }
+
+       QProcess process;
+       process.setProcessChannelMode(QProcess::MergedChannels);
+       process.setReadChannel(QProcess::StandardOutput);
+
+       QEventLoop loop;
+       connect(&process, SIGNAL(error(QProcess::ProcessError)), &loop, SLOT(quit()));
+       connect(&process, SIGNAL(finished(int,QProcess::ExitStatus)), &loop, SLOT(quit()));
+       connect(&process, SIGNAL(readyRead()), &loop, SLOT(quit()));
+
+       process.start(m_binaryWGet, QStringList() << "-O" << output.absoluteFilePath() << url);
+       
+       if(!process.waitForStarted())
+       {
+               return false;
+       }
+
+       while(process.state() == QProcess::Running)
+       {
+               loop.exec();
+               while(process.canReadLine())
+               {
+                       qDebug("WGet: %s", QString::fromLatin1(process.readLine()).simplified().toLatin1().constData());
+               }
+       }
+       
+       qDebug("WGet: Exited with code %d", process.exitCode());
+       return (process.exitCode() == 0) && output.exists() && output.isFile();
+}
+
+bool UpdateDialog::checkSignature(const QString &file, const QString &signature)
+{
+       QProcess process;
+       process.setProcessChannelMode(QProcess::MergedChannels);
+       process.setReadChannel(QProcess::StandardOutput);
+
+       QEventLoop loop;
+       connect(&process, SIGNAL(error(QProcess::ProcessError)), &loop, SLOT(quit()));
+       connect(&process, SIGNAL(finished(int,QProcess::ExitStatus)), &loop, SLOT(quit()));
+       connect(&process, SIGNAL(readyRead()), &loop, SLOT(quit()));
+       
+       process.start(m_binaryGnuPG, QStringList() << "--homedir" << lamexp_temp_folder() << "--keyring" << QDir::toNativeSeparators(m_binaryKeys) << QDir::toNativeSeparators(signature) << QDir::toNativeSeparators(file));
+
+       if(!process.waitForStarted())
+       {
+               return false;
+       }
+
+       while(process.state() == QProcess::Running)
+       {
+               loop.exec();
+               while(process.canReadLine())
+               {
+                       qDebug("GnuPG: %s", QString::fromLatin1(process.readLine()).simplified().toLatin1().constData());
+               }
+       }
+       
+       qDebug("GnuPG: Exited with code %d", process.exitCode());
+       return (process.exitCode() == 0);
+}
+
+bool UpdateDialog::parseVersionInfo(const QString &file, UpdateInfo *updateInfo)
+{
+       
+       QRegExp value("^(\\w+)=(.+)$");
+       QRegExp section("^\\[(.+)\\]$");
+
+       QFile data(file);
+       if(!data.open(QIODevice::ReadOnly))
+       {
+               qWarning("Cannot open update info file for reading!");
+               return false;
+       }
+       
+       bool inSection = false;
+       
+       while(!data.atEnd())
+       {
+               QString line = QString::fromLatin1(data.readLine()).trimmed();
+               if(section.indexIn(line) >= 0)
+               {
+                       qDebug("Section: '%s'", section.cap(1).toLatin1().constData());
+                       inSection = (section.cap(1).compare(section_id, Qt::CaseInsensitive) == 0);
+                       continue;
+               }
+               if(inSection && value.indexIn(line) >= 0)
+               {
+                       qDebug("Value: '%s' ==> '%s'", value.cap(1).toLatin1().constData(), value.cap(2).toLatin1().constData());
+                       if(value.cap(1).compare("BuildNo", Qt::CaseInsensitive) == 0)
+                       {
+                               bool ok = false;
+                               unsigned int temp = value.cap(2).toUInt(&ok);
+                               if(ok) updateInfo->m_buildNo = temp;
+                       }
+                       else if(value.cap(1).compare("BuildDate", Qt::CaseInsensitive) == 0)
+                       {
+                               QDate temp = QDate::fromString(value.cap(2).trimmed(), Qt::ISODate);
+                               if(temp.isValid()) updateInfo->m_buildDate = temp;
+                       }
+                       else if(value.cap(1).compare("DownloadSite", Qt::CaseInsensitive) == 0)
+                       {
+                               updateInfo->m_downloadSite = value.cap(2).trimmed();
+                       }
+                       else if(value.cap(1).compare("DownloadAddress", Qt::CaseInsensitive) == 0)
+                       {
+                               updateInfo->m_downloadAddress = value.cap(2).trimmed();
+                       }
+                       else if(value.cap(1).compare("DownloadFilename", Qt::CaseInsensitive) == 0)
+                       {
+                               updateInfo->m_downloadFilename = value.cap(2).trimmed();
+                       }
+                       else if(value.cap(1).compare("DownloadFilecode", Qt::CaseInsensitive) == 0)
+                       {
+                               updateInfo->m_downloadFilecode = value.cap(2).trimmed();
+                       }
+               }
+       }
+       
+       bool complete = true;
+
+       if(!(updateInfo->m_buildNo > 0)) complete = false;
+       if(!(updateInfo->m_buildDate.year() >= 2010)) complete = false;
+       if(updateInfo->m_downloadSite.isEmpty()) complete = false;
+       if(updateInfo->m_downloadAddress.isEmpty()) complete = false;
+       if(updateInfo->m_downloadFilename.isEmpty()) complete = false;
+       if(updateInfo->m_downloadFilecode.isEmpty()) complete = false;
+
+       return complete;
+}
+
+void UpdateDialog::linkActivated(const QString &link)
+{
+       QDesktopServices::openUrl(QUrl(link));
+}
+
+void UpdateDialog::applyUpdate(void)
+{
+       installButton->setEnabled(false);
+       closeButton->setEnabled(false);
+       retryButton->setEnabled(false);
+
+       if(m_updateInfo)
+       {
+               statusLabel->setText("Update is being downloaded, please be patient...");
+               QApplication::processEvents();
+               
+               QProcess process;
+               QStringList args;
+               QEventLoop loop;
+
+               connect(&process, SIGNAL(error(QProcess::ProcessError)), &loop, SLOT(quit()));
+               connect(&process, SIGNAL(finished(int,QProcess::ExitStatus)), &loop, SLOT(quit()));
+
+               args << QString("/Location=%1").arg(m_updateInfo->m_downloadAddress);
+               args << QString("/Filename=%1").arg(m_updateInfo->m_downloadFilename);
+               args << QString("/TicketID=%1").arg(m_updateInfo->m_downloadFilecode);
+               args << QString("/ToFolder=%1").arg(QDir::toNativeSeparators(QApplication::applicationDirPath()));
+               args << QString("/AppTitle=LameXP (Build #%1)").arg(QString::number(m_updateInfo->m_buildNo));
+
+               QApplication::setOverrideCursor(Qt::WaitCursor);
+               process.start(m_binaryUpdater, args);
+               loop.exec();
+               QApplication::restoreOverrideCursor();
+               
+               if(process.exitCode() == 0)
+               {
+                       statusLabel->setText("Update ready to install. Applicaion will quit...");
+                       QApplication::quit();
+               }
+               else
+               {
+                       statusLabel->setText("Update failed. Please try again or download manually!");
+               }
+       }
+
+       installButton->setEnabled(true);
+       closeButton->setEnabled(true);
+}
index 5958594..7b200d8 100644 (file)
@@ -25,6 +25,8 @@
 
 #include <QDialog>
 
+class UpdateInfo;
+
 class UpdateDialog : public QDialog, private Ui::UpdateDialog
 {
        Q_OBJECT
@@ -34,12 +36,25 @@ public:
        ~UpdateDialog(void);
 
 private slots:
-       void updateCompleted(void);
+       void updateInit(void);
+       void checkForUpdates(void);
+       void linkActivated(const QString &link);
+       void applyUpdate(void);
 
 protected:
        void showEvent(QShowEvent *event);
-
+       void closeEvent(QCloseEvent *event);
 
 private:
-       bool m_clipboardUsed;
+       bool tryUpdateMirror(UpdateInfo *updateInfo, const QString &url);
+       bool getFile(const QString &url, const QString &outFile);
+       bool checkSignature(const QString &file, const QString &signature);
+       bool parseVersionInfo(const QString &file, UpdateInfo *updateInfo);
+
+       UpdateInfo *m_updateInfo;
+       
+       const QString m_binaryWGet;
+       const QString m_binaryGnuPG;
+       const QString m_binaryUpdater;
+       const QString m_binaryKeys;
 };
index edfd306..1d6bfe0 100644 (file)
@@ -44,6 +44,7 @@ static const struct lamexp_tool_t g_lamexp_tools[] =
        {"09e5a07555a24b8c9d6af880b81eb8ed75be16fd", "faad.exe"},
        {"070bf98f78e572a97e4703ef5720c682567a6a56", "flac.exe"},
        {"cf379081035ae6bfb6f7bc22f13bfb7ac6302ac5", "gpgv.exe"},
+       {"d837bf6ee4dab557d8b02d46c75a24e58980fffa", "gpgv.gpg"},
        {"143fc001a2f6c56fe1b9e6f8a2eb2b53b9e1e504", "lame.exe"},
        {"775b260b3f64101beaeb317b74746f9bccdab842", "MAC.exe"},
        {"e8719fbfd7b690b3e518489f7aae3915305711c2", "mediainfo_icl11.exe"},