diff --git a/LameXP_VS2013.vcxproj b/LameXP_VS2013.vcxproj
index 7e3f6528..c992b772 100644
--- a/LameXP_VS2013.vcxproj
+++ b/LameXP_VS2013.vcxproj
@@ -348,6 +348,7 @@ del "$(TargetDir)imageformats\q???d4.dll"
+
@@ -393,6 +394,7 @@ del "$(TargetDir)imageformats\q???d4.dll"
+
@@ -569,6 +571,17 @@ del "$(TargetDir)imageformats\q???d4.dll"
$(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs)
+
+ "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)"
+ "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)"
+ "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)"
+ MOC "$(SolutionDir)tmp\MOC_%(Filename).cpp"
+ MOC "$(SolutionDir)tmp\MOC_%(Filename).cpp"
+ MOC "$(SolutionDir)tmp\MOC_%(Filename).cpp"
+ $(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs)
+ $(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs)
+ $(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs)
+
"$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)"
diff --git a/LameXP_VS2013.vcxproj.filters b/LameXP_VS2013.vcxproj.filters
index 863d7a9d..1bd46623 100644
--- a/LameXP_VS2013.vcxproj.filters
+++ b/LameXP_VS2013.vcxproj.filters
@@ -415,6 +415,12 @@
Source Files
+
+ Source Files\Threads
+
+
+ Generated Files\MOC
+
@@ -549,6 +555,9 @@
Header Files\Misc\3rd Party
+
+ Header Files\Threads
+
diff --git a/etc/Translation/Blank.ts b/etc/Translation/Blank.ts
index a4162abe..56893d71 100644
--- a/etc/Translation/Blank.ts
+++ b/etc/Translation/Blank.ts
@@ -3300,22 +3300,22 @@
QApplication
-
+
-
+
-
+
-
+
@@ -3384,105 +3384,104 @@
-
-
+
+
-
+
-
+
-
-
+
-
-
+
+
-
+
-
-
-
-
-
-
+
-
+
-
+
-
+
-
+
-
+
+
+
+
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
diff --git a/etc/Translation/LameXP_DE.ts b/etc/Translation/LameXP_DE.ts
index b3fce7e3..6178b630 100644
--- a/etc/Translation/LameXP_DE.ts
+++ b/etc/Translation/LameXP_DE.ts
@@ -293,11 +293,11 @@
-
+
-
+
@@ -2600,7 +2600,7 @@
-
+ Programm '%1' benötigt Windows XP oder neuer.
@@ -2667,10 +2667,6 @@
Test der Netzwerkverbindung fehlgeschlagen!
-
-
- Bitte prüfen Sie Ihre Internetverbindung und versuchen Sie es dann noch einmal.
-
Suche online nach neuen Updates, bitte warten...
@@ -2735,5 +2731,9 @@
Aktivieren Sie Ihre Internetverbindung und versuchen Sie es dann noch einmal.
+
+
+ Initialisiere, bitte warten...
+
diff --git a/etc/Translation/LameXP_ES.ts b/etc/Translation/LameXP_ES.ts
index 8b7cc290..da50506b 100644
--- a/etc/Translation/LameXP_ES.ts
+++ b/etc/Translation/LameXP_ES.ts
@@ -2670,10 +2670,6 @@
¡La prueba de conexión a internet ha fallado!
-
-
- Por favor, asegúrese de que su conexión a internet funciona correctamente y vuelva a intentarlo.
-
Comprobando en busca de nuevas actualizaciones, espere por favor...
@@ -2734,5 +2730,9 @@
Por favor, asegurese de que tiene conexión a internet y vuelva a intentarlo.
+
+
+ Iniciando, espere por favor...
+
diff --git a/etc/Translation/LameXP_FR.ts b/etc/Translation/LameXP_FR.ts
index b0f44424..6bc38741 100644
--- a/etc/Translation/LameXP_FR.ts
+++ b/etc/Translation/LameXP_FR.ts
@@ -2681,10 +2681,6 @@ Ouvrir le dossier récursivement...
Le test de connectivité réseau a échoué!
-
-
- Assurez-vous que votre connexion internet fonctionne correctement et essayez à nouveau.
-
Vérification des nouvelles mises à jour en ligne, patientez...
@@ -2745,5 +2741,9 @@ Ouvrir le dossier récursivement...
Veuillez vous assurer que votre ordinateur est connecté à internet et essayez à nouveau.
+
+
+ Initialisation, patientez...
+
diff --git a/etc/Translation/LameXP_IT.ts b/etc/Translation/LameXP_IT.ts
index 0f9aa9c2..bcb6e570 100644
--- a/etc/Translation/LameXP_IT.ts
+++ b/etc/Translation/LameXP_IT.ts
@@ -2667,10 +2667,6 @@
Il test di connessione di rete è fallito!
-
-
- Per favore assicurati che la tua connessione internet sia funzionante e prova ancora.
-
Ricerca di nuovi aggiornamenti in rete, attendere prego...
@@ -2735,5 +2731,9 @@
+
+
+ Inizializzazione, attendere prego...
+
diff --git a/etc/Translation/LameXP_KR.ts b/etc/Translation/LameXP_KR.ts
index 9fa32696..b014b020 100644
--- a/etc/Translation/LameXP_KR.ts
+++ b/etc/Translation/LameXP_KR.ts
@@ -2653,10 +2653,6 @@
네트워크 연결 테스트가 실패되었습니다!
-
-
- 인터넷에 연결되어 있는지 확인하고 다시 시도하시기 바랍니다.
-
새로운 업데이트 점검중, 잠시만 기다려 주십시오...
@@ -2717,5 +2713,9 @@
인터넷 연결을 확인하고 다시 시도하시기 바랍니다.
+
+
+ 초기화중, 잠시만 기다려 주십시오...
+
diff --git a/etc/Translation/LameXP_PL.ts b/etc/Translation/LameXP_PL.ts
index 05a90c64..5102610f 100644
--- a/etc/Translation/LameXP_PL.ts
+++ b/etc/Translation/LameXP_PL.ts
@@ -3337,22 +3337,22 @@
QApplication
-
+
Plik wykonywalny '%1' nie działa w trybie kompatybilności z Windows.
-
+
Plik wykonywalny '%1' wymaga Qt v%2, znaleziono jednak Qt v%3.
-
+
Plik wykonywalny "%1" został skompilowany dla Qt "%2", znaleziono "%3".
-
+
@@ -3421,105 +3421,104 @@
Zamknij
-
-
+
+
Build
-
+
Nieznana
-
+
Testowanie połączenia internetowego, prosze czekać...
-
-
+
LameXP wykrył brak dostępu do internetu!
-
-
+
+
Upewnij się że komputer jest podłączony do internetu i spróbuj ponownie.
-
+
Test połączenia internetowego zakończony niepowodzeniem!
-
-
- Upewnij się że połączenie internetowe działa prawidłowo i spróbuj ponownie.
-
-
-
+
Sprawdzanie aktualizacji online, prosze czekać...
-
+
Pobieranie informacji z serwera zakończone niepowodzeniem!
-
+
Serwer aktualizacji wydaje się nie odpowiadać w tej chwili. Prosze spróbować później.
-
+
Więcej informacji tutaj:
-
+
Dostępna nowa wersja LameXP!
-
+
+
+ Inicjowanie, prosze czekać...
+
+
+
Jest wysoce zalecane aby zainstalować tę aktualizację jak najszybciej.
-
+
Nie ma nowych aktualizacji w tej chwili.
-
+
Posiadasz najnowszą wersję LameXP. Sprawdzaj aktualizacje regularnie!
-
+
Posiadasz nowszą wersję LameXP niż ostatnie wydanie.
-
+
To wskazuje na to, że posiadasz wersję alfa LameXP.
-
+
Pobieranie aktualizacji w toku, prosze czekać...
-
+
Aktualizacja gotowa do instalacji. Teraz program zostanie zamknięty...
-
+
Aktualizacja zakończona niepowodzeniem. Prosze spróbować ponownie lub zainstalować ręcznie!
diff --git a/etc/Translation/LameXP_RU.ts b/etc/Translation/LameXP_RU.ts
index f1c19354..a8870dca 100644
--- a/etc/Translation/LameXP_RU.ts
+++ b/etc/Translation/LameXP_RU.ts
@@ -2695,10 +2695,6 @@
Нет соединения с сетью!
-
-
- Проверьте доступность интернет соединения и попробуйте снова.
-
Проверяю обновления, пожалуйста, подождите...
@@ -2760,5 +2756,9 @@
Пожалуйста, проверьте, что ваш компьютер подключен к интернету и попробуйте снова.
+
+
+ Инициализация, пожалуйста, подождите...
+
diff --git a/etc/Translation/LameXP_SV.ts b/etc/Translation/LameXP_SV.ts
index 82346cd3..9da779ed 100644
--- a/etc/Translation/LameXP_SV.ts
+++ b/etc/Translation/LameXP_SV.ts
@@ -3320,22 +3320,22 @@
QApplication
-
+
EXE-filen '%1' stöder inte Windows kompatibilitetsläge.
-
+
EXE-filen '%1' kräver Qt v%2, du har Qt v%3.
-
+
EXE-filen '%1' är byggd för Qt '%2', du har Qt '%3'.
-
+
@@ -3404,105 +3404,104 @@
Stäng
-
-
+
+
Build
-
+
Okänd
-
+
Kontrollerar iInternetanslutningen, vänta...
-
-
+
Datorn verkar inte vara ansluten till Internet!
-
-
+
+
Tillse att datorn är ansluten till Internet och försök igen.
-
+
Anslutningskontrollen misslyckades!
-
-
- Tillse att Internetuppkopplingen fungerar korrekt och försök igen.
-
-
-
+
Söker nya uppdateringar, vänta...
-
+
Kunde inte hämta uppdateringsinformation från servern!
-
+
Uppdateringsservern kan vara upptagen. Försök senare.
-
+
Mer information hittas på:
-
+
En ny version av LameXP finns tillgänglig!
-
+
+
+ Initierar, vänta...
+
+
+
Vi rekommenderar alla användare att installera denna uppdatering så snart som möjligt.
-
+
Det finns inga nya uppdateringar.
-
+
Din version av LameXP är uppdaterad. Kontrollera regelbundet!
-
+
Din version verkar vara nyare än senaste 'Release'.
-
+
Det innebär normalt att du använder en beta-version av LameXP.
-
+
Uppdatering laddas ner, vänta...
-
+
Uppdatering klar att installeras. Programmet kommer att avslutas...
-
+
Uppdateringen misslyckades. Försök igen, eller ladda ner manuellt!
diff --git a/etc/Translation/LameXP_TW.ts b/etc/Translation/LameXP_TW.ts
index 71945bd4..30b41515 100644
--- a/etc/Translation/LameXP_TW.ts
+++ b/etc/Translation/LameXP_TW.ts
@@ -2652,10 +2652,6 @@
網絡連接測試失敗 !
-
-
- 請確保您的網絡連接正常工作,然后再試.
-
在線更新檢查新的版本,請稍候...
@@ -2716,5 +2712,9 @@
請確保您的計算機連接到 Internet,然后重試.
+
+
+ 正在初始化,請稍候...
+
diff --git a/etc/Translation/LameXP_UK.ts b/etc/Translation/LameXP_UK.ts
index 7b50ffb0..5cd002ec 100644
--- a/etc/Translation/LameXP_UK.ts
+++ b/etc/Translation/LameXP_UK.ts
@@ -2689,10 +2689,6 @@
Збій перевірки мережевого з'єднання!
-
-
- Будь ласка, впевніться, що ваше інтернет-з'єднання працює коректно і спробуйте знову.
-
Йде перевірка оновлень онлайн, будь ласка, зачекайте...
@@ -2753,5 +2749,9 @@
Збій оновлення. Будь ласка, спробуйте ще раз або завантажте оновлення самостійно!
+
+
+ Ініціалізація, будь ласка, зачекайте...
+
diff --git a/etc/Translation/LameXP_ZH.ts b/etc/Translation/LameXP_ZH.ts
index 63bb0996..6b7ab122 100644
--- a/etc/Translation/LameXP_ZH.ts
+++ b/etc/Translation/LameXP_ZH.ts
@@ -2652,10 +2652,6 @@
网络连接测试失败 !
-
-
- 请确保您的网络连接正常工作,然后再试。
-
在线检查新的版本,请稍候...
@@ -2716,5 +2712,9 @@
请确保您的计算机连接到 Internet,然后重试。
+
+
+ 正在初始化,请稍候...
+
diff --git a/res/localization/LameXP_DE.qm b/res/localization/LameXP_DE.qm
index b82fdbe8..a36efa1c 100644
Binary files a/res/localization/LameXP_DE.qm and b/res/localization/LameXP_DE.qm differ
diff --git a/res/localization/LameXP_ES.qm b/res/localization/LameXP_ES.qm
index 4efe025f..908286f2 100644
Binary files a/res/localization/LameXP_ES.qm and b/res/localization/LameXP_ES.qm differ
diff --git a/res/localization/LameXP_FR.qm b/res/localization/LameXP_FR.qm
index 60cad153..3495c24f 100644
Binary files a/res/localization/LameXP_FR.qm and b/res/localization/LameXP_FR.qm differ
diff --git a/res/localization/LameXP_IT.qm b/res/localization/LameXP_IT.qm
index 9da67cef..3006badf 100644
Binary files a/res/localization/LameXP_IT.qm and b/res/localization/LameXP_IT.qm differ
diff --git a/res/localization/LameXP_KR.qm b/res/localization/LameXP_KR.qm
index ba4d72e9..dee84393 100644
Binary files a/res/localization/LameXP_KR.qm and b/res/localization/LameXP_KR.qm differ
diff --git a/res/localization/LameXP_PL.qm b/res/localization/LameXP_PL.qm
index 56fc710e..a70efa18 100644
Binary files a/res/localization/LameXP_PL.qm and b/res/localization/LameXP_PL.qm differ
diff --git a/res/localization/LameXP_RU.qm b/res/localization/LameXP_RU.qm
index bc11ca25..d2943268 100644
Binary files a/res/localization/LameXP_RU.qm and b/res/localization/LameXP_RU.qm differ
diff --git a/res/localization/LameXP_SV.qm b/res/localization/LameXP_SV.qm
index af747bef..102e5d9d 100644
Binary files a/res/localization/LameXP_SV.qm and b/res/localization/LameXP_SV.qm differ
diff --git a/res/localization/LameXP_TW.qm b/res/localization/LameXP_TW.qm
index 496f8b13..4ec877a8 100644
Binary files a/res/localization/LameXP_TW.qm and b/res/localization/LameXP_TW.qm differ
diff --git a/res/localization/LameXP_UK.qm b/res/localization/LameXP_UK.qm
index 5bc114a9..dc97bc6f 100644
Binary files a/res/localization/LameXP_UK.qm and b/res/localization/LameXP_UK.qm differ
diff --git a/res/localization/LameXP_ZH.qm b/res/localization/LameXP_ZH.qm
index 557af9d6..13c70e6e 100644
Binary files a/res/localization/LameXP_ZH.qm and b/res/localization/LameXP_ZH.qm differ
diff --git a/src/Config.h b/src/Config.h
index 108cf6ce..c668d235 100644
--- a/src/Config.h
+++ b/src/Config.h
@@ -35,7 +35,7 @@
#define VER_LAMEXP_MINOR_LO 9
#define VER_LAMEXP_TYPE Alpha
#define VER_LAMEXP_PATCH 7
-#define VER_LAMEXP_BUILD 1454
+#define VER_LAMEXP_BUILD 1458
#define VER_LAMEXP_CONFG 1348
///////////////////////////////////////////////////////////////////////////////
diff --git a/src/Dialog_Update.cpp b/src/Dialog_Update.cpp
index adbb8eaa..312c4a27 100644
--- a/src/Dialog_Update.cpp
+++ b/src/Dialog_Update.cpp
@@ -28,146 +28,24 @@
//LameXP includes
#include "Global.h"
#include "Resource.h"
+#include "Thread_CheckUpdate.h"
#include "Dialog_LogView.h"
#include "Model_Settings.h"
#include "WinSevenTaskbar.h"
-#include "Tool_Abstract.h"
//Qt includes
#include
#include
#include
#include
-#include
-#include
#include
#include
#include
#include
-#include
-#include
-
-///////////////////////////////////////////////////////////////////////////////
-
-static const char *header_id = "!Update";
-static const char *section_id = "LameXP";
-
-static const char *mirror_url_postfix[] =
-{
- "update.ver",
- "update_beta.ver",
- NULL
-};
-
-static const char *update_mirrors_prim[] =
-{
- "http://muldersoft.com/",
- "http://mulder.bplaced.net/",
- "http://mulder.cwsurf.de/",
- "http://mulder.6te.net/",
- "http://mulder.webuda.com/",
- "http://mulder.byethost13.com/",
- "http://muldersoft.kilu.de/",
- "http://muldersoft.zxq.net/",
- "http://lamexp.sourceforge.net/",
- "http://lamexp.berlios.de/",
- "http://lordmulder.github.com/LameXP/",
- "http://lord_mulder.bitbucket.org/",
- "http://www.tricksoft.de/",
- NULL
-};
-
-static const char *update_mirrors_back[] =
-{
- "http://mplayer.savedonthe.net/",
- NULL
-};
-
-static const char *known_hosts[] = //Taken form: http://www.alexa.com/topsites !!!
-{
- "http://www.163.com/",
- "http://www.ac3filter.net/",
- "http://www.amazon.com/",
- "http://www.aol.com/",
- "http://www.apache.org/",
- "http://www.apple.com/",
- "http://www.adobe.com/",
- "http://www.avidemux.org/",
- "http://www.babylon.com/",
- "http://www.baidu.com/",
- "http://www.bbc.co.uk/",
- "http://www.berlios.de/",
- "http://www.bing.com/",
- "http://www.cnet.com/",
- "http://cnzz.com/",
- "http://codecs.com/",
- "http://www.codeplex.com/",
- "http://qt.digia.com/",
- "http://www.ebay.com/",
- "http://www.equation.com/",
- "http://fc2.com/",
- "http://www.ffmpeg.org/",
- "http://www.flickr.com/",
- "http://blog.gitorious.org/",
- "http://git-scm.com/",
- "http://www.gnome.org/",
- "http://www.gnu.org/",
- "http://go.com/",
- "http://code.google.com/",
- "http://www.heise.de/",
- "http://www.huffingtonpost.co.uk/",
- "http://www.iana.org/",
- "http://www.imdb.com/",
- "http://www.imgburn.com/",
- "http://imgur.com/",
- "http://en.jd.com/",
- "http://mirrors.kernel.org/",
- "http://www.libav.org/",
- "http://www.linkedin.com/",
- "http://www.livedoor.com/",
- "http://www.livejournal.com/",
- "http://mail.ru/",
- "http://www.mediafire.com/",
- "http://www.mozilla.org/en-US/",
- "http://mplayerhq.hu/",
- "http://www.msn.com/?st=1",
- "http://oss.netfarm.it/",
- "http://www.nytimes.com/",
- "http://www.opera.com/",
- "http://www.portablefreeware.com/",
- "http://qt-project.org/",
- "http://www.quakelive.com/",
- "http://www.seamonkey-project.org/",
- "http://www.sina.com.cn/",
- "http://www.sohu.com/",
- "http://www.soso.com/",
- "http://sourceforge.net/",
- "http://www.spiegel.de/",
- "http://tdm-gcc.tdragon.net/",
- "http://www.tdrsmusic.com/",
- "http://www.ubuntu.com/",
- "http://status.twitter.com/",
- "http://www.uol.com.br/",
- "http://www.videohelp.com/",
- "http://www.videolan.org/",
- "http://www.weibo.com/",
- "http://www.wikipedia.org/",
- "http://www.winamp.com/",
- "http://wordpress.com/",
- "http://us.yahoo.com/",
- "http://www.yandex.ru/",
- "http://www.youtube.com/",
- "http://www.zedo.com/",
- "http://ffmpeg.zeranoe.com/",
- NULL
-};
-
-static const int MIN_CONNSCORE = 8;
-static const int VERSION_INFO_EXPIRES_MONTHS = 6;
-static char *USER_AGENT_STR = "Mozilla/5.0 (X11; Linux i686; rv:7.0.1) Gecko/20111106 IceCat/7.0.1";
///////////////////////////////////////////////////////////////////////////////
+/*
template
T DO_ASYNC(T (*functionPointer)())
{
@@ -177,31 +55,23 @@ T DO_ASYNC(T (*functionPointer)())
loop.exec(QEventLoop::ExcludeUserInputEvents);
return watcher.result();
}
+*/
-///////////////////////////////////////////////////////////////////////////////
+#define SHOW_HINT(TEXT, ICON) do \
+{ \
+ ui->hintLabel->setText((TEXT)); \
+ ui->hintIcon->setPixmap(QIcon((ICON)).pixmap(16,16)); \
+ ui->hintIcon->show(); \
+ ui->hintLabel->show(); \
+} \
+while(0)
-class UpdateInfo
-{
-public:
- UpdateInfo(void) { resetInfo(); }
-
- void resetInfo(void)
- {
- m_buildNo = 0;
- m_buildDate.setDate(1900, 1, 1);
- m_downloadSite.clear();
- m_downloadAddress.clear();
- m_downloadFilename.clear();
- m_downloadFilecode.clear();
- }
-
- unsigned int m_buildNo;
- QDate m_buildDate;
- QString m_downloadSite;
- QString m_downloadAddress;
- QString m_downloadFilename;
- QString m_downloadFilecode;
-};
+#define UPDATE_TASKBAR(STATE, ICON) do \
+{ \
+ WinSevenTaskbar::setTaskbarState(this->parentWidget(), (STATE)); \
+ WinSevenTaskbar::setOverlayIcon(this->parentWidget(), &QIcon((ICON))); \
+} \
+while(0)
///////////////////////////////////////////////////////////////////////////////
@@ -209,24 +79,21 @@ UpdateDialog::UpdateDialog(SettingsModel *settings, QWidget *parent)
:
QDialog(parent),
ui(new Ui::UpdateDialog),
- 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),
+ m_thread(NULL),
m_settings(settings),
m_logFile(new QStringList()),
m_betaUpdates(settings ? (settings->autoUpdateCheckBeta() || lamexp_version_demo()) : lamexp_version_demo()),
m_success(false),
m_firstShow(true),
m_updateReadyToInstall(false),
- m_updaterProcess(NULL)
+ m_updaterProcess(NULL),
+ m_binaryUpdater(lamexp_lookup_tool("wupdate.exe"))
{
- if(m_binaryWGet.isEmpty() || m_binaryGnuPG.isEmpty() || m_binaryUpdater.isEmpty() || m_binaryKeys.isEmpty())
+ if(m_binaryUpdater.isEmpty())
{
THROW("Tools not initialized correctly!");
}
-
+
//Init the dialog, from the .ui file
ui->setupUi(this);
setWindowFlags(windowFlags() ^ Qt::WindowContextHelpButtonHint);
@@ -257,9 +124,21 @@ UpdateDialog::UpdateDialog(SettingsModel *settings, QWidget *parent)
UpdateDialog::~UpdateDialog(void)
{
- if(m_animator) m_animator->stop();
-
- LAMEXP_DELETE(m_updateInfo);
+ if(m_animator)
+ {
+ m_animator->stop();
+ }
+
+ if(m_thread)
+ {
+ if(!m_thread->wait(1000))
+ {
+ m_thread->terminate();
+ m_thread->wait();
+ }
+ }
+
+ LAMEXP_DELETE(m_thread);
LAMEXP_DELETE(m_logFile);
LAMEXP_DELETE(m_animator);
@@ -275,6 +154,17 @@ void UpdateDialog::showEvent(QShowEvent *event)
if(m_firstShow)
{
+ if(!m_thread)
+ {
+ m_thread = new UpdateCheckThread(m_betaUpdates);
+ connect(m_thread, SIGNAL(statusChanged(int)), this, SLOT(threadStatusChanged(int)));
+ connect(m_thread, SIGNAL(progressChanged(int)), this, SLOT(threadProgressChanged(int)));
+ connect(m_thread, SIGNAL(messageLogged(QString)), this, SLOT(threadMessageLogged(QString)));
+ connect(m_thread, SIGNAL(finished()), this, SLOT(threadFinished()));
+ connect(m_thread, SIGNAL(terminated()), this, SLOT(threadFinished()));
+ }
+
+ threadStatusChanged(m_thread->getUpdateStatus());
ui->labelVersionInstalled->setText(QString("%1 %2 (%3)").arg(tr("Build"), QString::number(lamexp_version_build()), lamexp_version_date().toString(Qt::ISODate)));
ui->labelVersionLatest->setText(QString("(%1)").arg(tr("Unknown")));
@@ -289,11 +179,7 @@ void UpdateDialog::showEvent(QShowEvent *event)
ui->hintIcon->hide();
ui->frameAnimation->hide();
- int counter = MIN_CONNSCORE + 2;
- for(int i = 0; update_mirrors_prim[i]; i++) counter++;
- for(int i = 0; update_mirrors_back[i]; i++) counter++;
-
- ui->progressBar->setMaximum(counter);
+ ui->progressBar->setMaximum(m_thread->getMaximumProgress());
ui->progressBar->setValue(0);
m_updaterProcess = NULL;
@@ -324,11 +210,7 @@ void UpdateDialog::keyPressEvent(QKeyEvent *e)
}
else if((e->key() == Qt::Key_F12) && e->modifiers().testFlag(Qt::ControlModifier))
{
- if(ui->closeButton->isEnabled())
- {
- testKnownWebSites();
- logButtonClicked();
- }
+ if(ui->closeButton->isEnabled()) testKnownHosts();
}
else
{
@@ -360,16 +242,15 @@ void UpdateDialog::updateInit(void)
void UpdateDialog::checkForUpdates(void)
{
- bool success = false;
- int connectionScore = 0;
+ if(m_thread->isRunning())
+ {
+ qWarning("Update in progress, cannot check for updates now!");
+ }
- // ----- Initialization ----- //
-
- m_updateInfo = new UpdateInfo;
-
- ui->progressBar->setValue(0);
WinSevenTaskbar::setTaskbarState(this->parentWidget(), WinSevenTaskbar::WinSevenTaskbarNormalState);
WinSevenTaskbar::setOverlayIcon(this->parentWidget(), &QIcon(":/icons/transmit_blue.png"));
+
+ ui->progressBar->setValue(0);
ui->installButton->setEnabled(false);
ui->closeButton->setEnabled(false);
ui->retryButton->setEnabled(false);
@@ -382,477 +263,102 @@ void UpdateDialog::checkForUpdates(void)
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
QApplication::setOverrideCursor(Qt::WaitCursor);
- // ----- Test Internet Connection ----- //
-
- ui->statusLabel->setText(tr("Testing your internet connection, please wait..."));
-
m_logFile->clear();
- m_logFile->append("Checking internet connection...");
-
- const int networkStatus = DO_ASYNC(lamexp_network_status);
- if(networkStatus == lamexp_network_non)
+ m_thread->start();
+}
+
+void UpdateDialog::threadStatusChanged(const int status)
+{
+ switch(status)
{
- m_logFile->append(QStringList() << "" << "Operating system reports that the computer is currently offline !!!");
- if(!ui->retryButton->isVisible()) ui->retryButton->show();
- if(!ui->logButton->isVisible()) ui->logButton->show();
- ui->closeButton->setEnabled(true);
- ui->retryButton->setEnabled(true);
- ui->logButton->setEnabled(true);
- if(ui->frameAnimation->isVisible()) ui->frameAnimation->hide();
- ui->statusLabel->setText(tr("It appears that the computer currently is offline!"));
- ui->progressBar->setValue(ui->progressBar->maximum());
- ui->hintIcon->setPixmap(QIcon(":/icons/network_error.png").pixmap(16,16));
- ui->hintLabel->setText(tr("Please make sure your computer is connected to the internet and try again."));
- ui->hintIcon->show();
- ui->hintLabel->show();
- LAMEXP_DELETE(m_updateInfo);
- if(m_settings->soundsEnabled()) lamexp_play_sound(IDR_WAVE_ERROR, true);
- QApplication::restoreOverrideCursor();
- ui->progressBar->setValue(ui->progressBar->maximum());
- WinSevenTaskbar::setTaskbarState(this->parentWidget(), WinSevenTaskbar::WinSevenTaskbarErrorState);
- WinSevenTaskbar::setOverlayIcon(this->parentWidget(), &QIcon(":/icons/exclamation.png"));
- return;
- }
-
- ui->progressBar->setValue(1);
- QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
-
- // ----- Test Known Hosts Connectivity ----- //
-
- QStringList hostList;
- for(int i = 0; known_hosts[i]; i++)
- {
- hostList << QString::fromLatin1(known_hosts[i]);
- }
-
- lamexp_seed_rand();
- while(!hostList.isEmpty())
- {
- QString currentHost = hostList.takeAt(lamexp_rand() % hostList.count());
- if(connectionScore < MIN_CONNSCORE)
- {
- m_logFile->append(QStringList() << "" << "Testing host:" << currentHost << "");
- QString outFile = QString("%1/%2.htm").arg(lamexp_temp_folder2(), lamexp_rand_str());
- bool httpOk = false;
- if(getFile(currentHost, outFile, 0, &httpOk))
- {
- connectionScore++;
- ui->progressBar->setValue(qBound(1, connectionScore + 1, MIN_CONNSCORE + 1));
- QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
- lamexp_sleep(64);
- }
- if(httpOk)
- {
- connectionScore++;
- ui->progressBar->setValue(qBound(1, connectionScore + 1, MIN_CONNSCORE + 1));
- QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
- lamexp_sleep(64);
- }
- QFile::remove(outFile);
- }
- }
-
- if(connectionScore < MIN_CONNSCORE)
- {
- if(!ui->retryButton->isVisible()) ui->retryButton->show();
- if(!ui->logButton->isVisible()) ui->logButton->show();
- ui->closeButton->setEnabled(true);
- ui->retryButton->setEnabled(true);
- ui->logButton->setEnabled(true);
- if(ui->frameAnimation->isVisible()) ui->frameAnimation->hide();
- ui->statusLabel->setText(tr("Network connectivity test has failed!"));
- ui->progressBar->setValue(ui->progressBar->maximum());
- ui->hintIcon->setPixmap(QIcon(":/icons/network_error.png").pixmap(16,16));
- ui->hintLabel->setText(tr("Please make sure your internet connection is working properly and try again."));
- ui->hintIcon->show();
- ui->hintLabel->show();
- LAMEXP_DELETE(m_updateInfo);
- if(m_settings->soundsEnabled()) lamexp_play_sound(IDR_WAVE_ERROR, true);
- QApplication::restoreOverrideCursor();
- ui->progressBar->setValue(ui->progressBar->maximum());
- WinSevenTaskbar::setTaskbarState(this->parentWidget(), WinSevenTaskbar::WinSevenTaskbarErrorState);
- WinSevenTaskbar::setOverlayIcon(this->parentWidget(), &QIcon(":/icons/exclamation.png"));
- return;
- }
-
- // ----- Build Mirror List ----- //
-
- ui->statusLabel->setText(tr("Checking for new updates online, please wait..."));
- m_logFile->append(QStringList() << "" << "----" << "" << "Checking for updates online...");
-
- QStringList mirrorList;
- for(int index = 0; update_mirrors_prim[index]; index++)
- {
- mirrorList << QString::fromLatin1(update_mirrors_prim[index]);
- }
-
- lamexp_seed_rand();
- if(const int len = mirrorList.count())
- {
- const int rounds = len * 1097;
- for(int i = 0; i < rounds; i++)
- {
- mirrorList.swap(i % len, lamexp_rand() % len);
- }
- }
-
- for(int index = 0; update_mirrors_back[index]; index++)
- {
- mirrorList << QString::fromLatin1(update_mirrors_back[index]);
- }
-
- // ----- Fetch Update Info From Server ----- //
-
- while(!mirrorList.isEmpty())
- {
- QString currentMirror = mirrorList.takeFirst();
- ui->progressBar->setValue(ui->progressBar->value() + 1);
- if(!success)
- {
- if(tryUpdateMirror(m_updateInfo, currentMirror))
- {
- success = true;
- }
- }
- else
- {
- QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
- lamexp_sleep(64);
- }
- }
-
- QApplication::restoreOverrideCursor();
- ui->progressBar->setValue(ui->progressBar->maximum());
-
- if(!success)
- {
- if(!ui->retryButton->isVisible()) ui->retryButton->show();
- if(!ui->logButton->isVisible()) ui->logButton->show();
- ui->closeButton->setEnabled(true);
- ui->retryButton->setEnabled(true);
- ui->logButton->setEnabled(true);
- if(ui->frameAnimation->isVisible()) ui->frameAnimation->hide();
- ui->statusLabel->setText(tr("Failed to fetch update information from server!"));
- ui->progressBar->setValue(ui->progressBar->maximum());
- WinSevenTaskbar::setTaskbarState(this->parentWidget(), WinSevenTaskbar::WinSevenTaskbarErrorState);
- WinSevenTaskbar::setOverlayIcon(this->parentWidget(), &QIcon(":/icons/exclamation.png"));
- ui->hintIcon->setPixmap(QIcon(":/icons/server_error.png").pixmap(16,16));
- ui->hintLabel->setText(tr("Sorry, the update server might be busy at this time. Plase try again later."));
- ui->hintIcon->show();
- ui->hintLabel->show();
- LAMEXP_DELETE(m_updateInfo);
- if(m_settings->soundsEnabled()) lamexp_play_sound(IDR_WAVE_ERROR, true);
- return;
- }
-
- // ----- Download New Program Version ----- //
-
- ui->labelVersionLatest->setText(QString("%1 %2 (%3)").arg(tr("Build"), QString::number(m_updateInfo->m_buildNo), m_updateInfo->m_buildDate.toString(Qt::ISODate)));
- ui->infoLabel->show();
- ui->infoLabel->setText(QString("%1
%2").arg(tr("More information available at:"), m_updateInfo->m_downloadSite));
- QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
-
- if(m_updateInfo->m_buildNo > lamexp_version_build())
- {
- ui->installButton->setEnabled(true);
+ case UpdateCheckThread::UpdateStatus_NotStartedYet:
+ ui->statusLabel->setText(tr("Initializing, please wait..."));
+ break;
+ case UpdateCheckThread::UpdateStatus_CheckingConnection:
+ ui->statusLabel->setText(tr("Testing your internet connection, please wait..."));
+ break;
+ case UpdateCheckThread::UpdateStatus_FetchingUpdates:
+ ui->statusLabel->setText(tr("Checking for new updates online, please wait..."));
+ break;
+ case UpdateCheckThread::UpdateStatus_CompletedUpdateAvailable:
ui->statusLabel->setText(tr("A new version of LameXP is available!"));
- ui->hintIcon->setPixmap(QIcon(":/icons/shield_exclamation.png").pixmap(16,16));
- ui->hintLabel->setText(tr("We highly recommend all users to install this update as soon as possible."));
- if(ui->frameAnimation->isVisible()) ui->frameAnimation->hide();
- ui->hintIcon->show();
- ui->hintLabel->show();
- WinSevenTaskbar::setOverlayIcon(this->parentWidget(), &QIcon(":/icons/shield_exclamation.png"));
- lamexp_beep(lamexp_beep_info);
- }
- else if(m_updateInfo->m_buildNo == lamexp_version_build())
- {
+ SHOW_HINT(tr("We highly recommend all users to install this update as soon as possible."), ":/icons/shield_exclamation.png");
+ UPDATE_TASKBAR(WinSevenTaskbar::WinSevenTaskbarNormalState, ":/icons/shield_exclamation.png");
+ break;
+ case UpdateCheckThread::UpdateStatus_CompletedNoUpdates:
ui->statusLabel->setText(tr("No new updates available at this time."));
- ui->hintIcon->setPixmap(QIcon(":/icons/shield_green.png").pixmap(16,16));
- ui->hintLabel->setText(tr("Your version of LameXP is still up-to-date. Please check for updates regularly!"));
- if(ui->frameAnimation->isVisible()) ui->frameAnimation->hide();
- ui->hintIcon->show();
- ui->hintLabel->show();
- WinSevenTaskbar::setOverlayIcon(this->parentWidget(), &QIcon(":/icons/shield_green.png"));
- lamexp_beep(lamexp_beep_info);
- }
- else
- {
+ SHOW_HINT(tr("Your version of LameXP is still up-to-date. Please check for updates regularly!"), ":/icons/shield_green.png");
+ UPDATE_TASKBAR(WinSevenTaskbar::WinSevenTaskbarNormalState, ":/icons/shield_green.png");
+ break;
+ case UpdateCheckThread::UpdateStatus_CompletedNewVersionOlder:
ui->statusLabel->setText(tr("Your version appears to be newer than the latest release."));
- ui->hintIcon->setPixmap(QIcon(":/icons/shield_error.png").pixmap(16,16));
- ui->hintLabel->setText(tr("This usually indicates your are currently using a pre-release version of LameXP."));
- if(ui->frameAnimation->isVisible()) ui->frameAnimation->hide();
- ui->hintIcon->show();
- ui->hintLabel->show();
- WinSevenTaskbar::setOverlayIcon(this->parentWidget(), &QIcon(":/icons/shield_error.png"));
- lamexp_beep(lamexp_beep_warning);
+ SHOW_HINT(tr("This usually indicates your are currently using a pre-release version of LameXP."), ":/icons/shield_error.png");
+ UPDATE_TASKBAR(WinSevenTaskbar::WinSevenTaskbarNormalState, ":/icons/shield_error.png");
+ break;
+ case UpdateCheckThread::UpdateStatus_ErrorNoConnection:
+ ui->statusLabel->setText(tr("It appears that the computer currently is offline!"));
+ SHOW_HINT(tr("Please make sure your computer is connected to the internet and try again."), ":/icons/network_error.png");
+ UPDATE_TASKBAR(WinSevenTaskbar::WinSevenTaskbarErrorState, ":/icons/exclamation.png");
+ break;
+ case UpdateCheckThread::UpdateStatus_ErrorConnectionTestFailed:
+ ui->statusLabel->setText(tr("Network connectivity test has failed!"));
+ SHOW_HINT(tr("Please make sure your computer is connected to the internet and try again."), ":/icons/network_error.png");
+ UPDATE_TASKBAR(WinSevenTaskbar::WinSevenTaskbarErrorState, ":/icons/exclamation.png");
+ break;
+ case UpdateCheckThread::UpdateStatus_ErrorFetchUpdateInfo:
+ ui->statusLabel->setText(tr("Failed to fetch update information from server!"));
+ SHOW_HINT(tr("Sorry, the update server might be busy at this time. Plase try again later."), ":/icons/server_error.png");
+ UPDATE_TASKBAR(WinSevenTaskbar::WinSevenTaskbarErrorState, ":/icons/exclamation.png");
+ break;
+ default:
+ qWarning("Unknown status %d !!!", int(status));
}
-
- ui->closeButton->setEnabled(true);
- if(ui->retryButton->isVisible()) ui->retryButton->hide();
- if(ui->logButton->isVisible()) ui->logButton->hide();
- if(ui->frameAnimation->isVisible()) ui->frameAnimation->hide();
-
- m_success = true;
}
-bool UpdateDialog::tryUpdateMirror(UpdateInfo *updateInfo, const QString &url)
+void UpdateDialog::threadProgressChanged(const int progress)
{
- bool success = false;
- m_logFile->append(QStringList() << "" << "Trying mirror:" << url);
+ ui->progressBar->setValue(progress);
+}
- QString randPart = lamexp_rand_str();
- QString outFileVersionInfo = QString("%1/%2.ver").arg(lamexp_temp_folder2(), randPart);
- QString outFileSignature = QString("%1/%2.sig").arg(lamexp_temp_folder2(), randPart);
+void UpdateDialog::threadMessageLogged(const QString &message)
+{
+ (*m_logFile) << message;
+}
- m_logFile->append(QStringList() << "" << "Downloading update info:");
- bool ok1 = getFile(QString("%1%2").arg(url, mirror_url_postfix[m_betaUpdates ? 1 : 0]), outFileVersionInfo);
+void UpdateDialog::threadFinished(void)
+{
+ const bool bSuccess = m_thread->getSuccess();
+
+ ui->closeButton->setEnabled(true);
+ if(ui->frameAnimation->isVisible()) ui->frameAnimation->hide();
+ ui->progressBar->setValue(ui->progressBar->maximum());
- m_logFile->append(QStringList() << "" << "Downloading signature:");
- bool ok2 = getFile(QString("%1%2.sig").arg(url, mirror_url_postfix[m_betaUpdates ? 1 : 0]), outFileSignature);
-
- if(ok1 && ok2)
+ if(!bSuccess)
{
- m_logFile->append(QStringList() << "" << "Download okay, checking signature:");
- if(checkSignature(outFileVersionInfo, outFileSignature))
- {
- m_logFile->append(QStringList() << "" << "Signature okay, parsing info:");
- success = parseVersionInfo(outFileVersionInfo, updateInfo);
- }
- else
- {
- m_logFile->append(QStringList() << "" << "Bad signature, take care!");
- }
+ if(m_settings->soundsEnabled()) lamexp_play_sound(IDR_WAVE_ERROR, true);
}
else
{
- m_logFile->append(QStringList() << "" << "Download has failed!");
- }
+ const bool bHaveUpdate = (m_thread->getUpdateStatus() == UpdateCheckThread::UpdateStatus_CompletedUpdateAvailable);
+ ui->installButton->setEnabled(bHaveUpdate);
+ lamexp_beep(bHaveUpdate ? lamexp_beep_info : lamexp_beep_warning);
- QFile::remove(outFileVersionInfo);
- QFile::remove(outFileSignature);
-
- return success;
-}
-
-bool UpdateDialog::getFile(const QString &url, const QString &outFile, unsigned int maxRedir, bool *httpOk)
-{
- QFileInfo output(outFile);
- output.setCaching(false);
- if(httpOk) *httpOk = false;
-
- if(output.exists())
- {
- QFile::remove(output.canonicalFilePath());
- if(output.exists())
+ if(const UpdateInfo *const updateInfo = m_thread->getUpdateInfo())
{
- return false;
+ ui->infoLabel->setText(QString("%1
%2").arg(tr("More information available at:"), updateInfo->m_downloadSite));
+ ui->labelVersionLatest->setText(QString("%1 %2 (%3)").arg(tr("Build"), QString::number(updateInfo->m_buildNo), updateInfo->m_buildDate.toString(Qt::ISODate)));
+ ui->infoLabel->show();
}
+
+ m_success = true;
}
- QProcess process;
- lamexp_init_process(process, output.absolutePath());
+ ui->retryButton->setVisible(!bSuccess);
+ ui->logButton->setVisible(!bSuccess);
+ ui->retryButton->setEnabled(!bSuccess);
+ ui->logButton->setEnabled(!bSuccess);
- QStringList args;
- args << "--no-cache" << "--no-dns-cache" << QString().sprintf("--max-redirect=%u", maxRedir);
- args << QString("--referer=%1://%2/").arg(QUrl(url).scheme(), QUrl(url).host()) << "-U" << USER_AGENT_STR;
- args << "-O" << output.fileName() << url;
-
- 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()));
-
- QTimer timer;
- timer.setSingleShot(true);
- timer.setInterval(25000);
- connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
-
- const QRegExp httpResponseOK("200 OK$");
-
- process.start(m_binaryWGet, args);
-
- if(!process.waitForStarted())
- {
- return false;
- }
-
- timer.start();
-
- while(process.state() == QProcess::Running)
- {
- loop.exec();
- bool bTimeOut = (!timer.isActive());
- while(process.canReadLine())
- {
- QString line = QString::fromLatin1(process.readLine()).simplified();
- if(line.contains(httpResponseOK))
- {
- line.append(" [OK]");
- if(httpOk) *httpOk = true;
- }
- m_logFile->append(line);
- }
- if(bTimeOut)
- {
- qWarning("WGet process timed out <-- killing!");
- process.kill();
- process.waitForFinished();
- m_logFile->append("!!! TIMEOUT !!!");
- return false;
- }
- }
-
- timer.stop();
- timer.disconnect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
-
- m_logFile->append(QString().sprintf("Exited with code %d", process.exitCode()));
- return (process.exitCode() == 0) && output.exists() && output.isFile();
-}
-
-bool UpdateDialog::checkSignature(const QString &file, const QString &signature)
-{
- if(QFileInfo(file).absolutePath().compare(QFileInfo(signature).absolutePath(), Qt::CaseInsensitive) != 0)
- {
- qWarning("CheckSignature: File and signature should be in same folder!");
- return false;
- }
- if(QFileInfo(file).absolutePath().compare(QFileInfo(m_binaryKeys).absolutePath(), Qt::CaseInsensitive) != 0)
- {
- qWarning("CheckSignature: File and keyring should be in same folder!");
- return false;
- }
-
- QProcess process;
- lamexp_init_process(process, QFileInfo(file).absolutePath());
-
- 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" << "." << "--keyring" << QFileInfo(m_binaryKeys).fileName() << QFileInfo(signature).fileName() << QFileInfo(file).fileName());
-
- if(!process.waitForStarted())
- {
- return false;
- }
-
- while(process.state() == QProcess::Running)
- {
- loop.exec();
- while(process.canReadLine())
- {
- m_logFile->append(QString::fromLatin1(process.readLine()).simplified());
- }
- }
-
- m_logFile->append(QString().sprintf("Exited with code %d", process.exitCode()));
- return (process.exitCode() == 0);
-}
-
-bool UpdateDialog::parseVersionInfo(const QString &file, UpdateInfo *updateInfo)
-{
- QRegExp value("^(\\w+)=(.+)$");
- QRegExp section("^\\[(.+)\\]$");
-
- QDate updateInfoDate;
- updateInfo->resetInfo();
-
- QFile data(file);
- if(!data.open(QIODevice::ReadOnly))
- {
- qWarning("Cannot open update info file for reading!");
- return false;
- }
-
- bool inHeader = false;
- bool inSection = false;
-
- while(!data.atEnd())
- {
- QString line = QString::fromLatin1(data.readLine()).trimmed();
- if(section.indexIn(line) >= 0)
- {
- m_logFile->append(QString("Sec: [%1]").arg(section.cap(1)));
- inSection = (section.cap(1).compare(section_id, Qt::CaseInsensitive) == 0);
- inHeader = (section.cap(1).compare(header_id, Qt::CaseInsensitive) == 0);
- continue;
- }
- if(inSection && (value.indexIn(line) >= 0))
- {
- m_logFile->append(QString("Val: '%1' ==> '%2").arg(value.cap(1), value.cap(2)));
- 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();
- }
- }
- if(inHeader && (value.indexIn(line) >= 0))
- {
- m_logFile->append(QString("Val: '%1' ==> '%2").arg(value.cap(1), value.cap(2)));
- if(value.cap(1).compare("TimestampCreated", Qt::CaseInsensitive) == 0)
- {
- QDate temp = QDate::fromString(value.cap(2).trimmed(), Qt::ISODate);
- if(temp.isValid()) updateInfoDate = temp;
- }
- }
- }
-
- if(!updateInfoDate.isValid())
- {
- updateInfo->resetInfo();
- m_logFile->append("WARNING: Version info timestamp is missing!");
- return false;
- }
- else if(updateInfoDate.addMonths(VERSION_INFO_EXPIRES_MONTHS) < lamexp_current_date_safe())
- {
- updateInfo->resetInfo();
- m_logFile->append(QString::fromLatin1("WARNING: This version info has expired at %1!").arg(updateInfoDate.addMonths(VERSION_INFO_EXPIRES_MONTHS).toString(Qt::ISODate)));
- return false;
- }
- else if(lamexp_current_date_safe() < updateInfoDate)
- {
- m_logFile->append("Version info is from the future, take care!");
- qWarning("Version info is from the future, take care!");
- }
-
- 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;
-
- if(!complete)
- {
- m_logFile->append("WARNING: Version info is incomplete!");
- }
-
- return complete;
+ QApplication::restoreOverrideCursor();
}
void UpdateDialog::linkActivated(const QString &link)
@@ -866,7 +372,7 @@ void UpdateDialog::applyUpdate(void)
ui->closeButton->setEnabled(false);
ui->retryButton->setEnabled(false);
- if(m_updateInfo)
+ if(const UpdateInfo *updateInfo = m_thread->getUpdateInfo())
{
ui->statusLabel->setText(tr("Update is being downloaded, please be patient..."));
ui->frameAnimation->show();
@@ -886,16 +392,15 @@ void UpdateDialog::applyUpdate(void)
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("/Location=%1").arg(updateInfo->m_downloadAddress);
+ args << QString("/Filename=%1").arg(updateInfo->m_downloadFilename);
+ args << QString("/TicketID=%1").arg(updateInfo->m_downloadFilecode);
args << QString("/ToFolder=%1").arg(QDir::toNativeSeparators(QDir(QApplication::applicationDirPath()).canonicalPath()));
args << QString("/ToExFile=%1.exe").arg(QFileInfo(QFileInfo(QApplication::applicationFilePath()).canonicalFilePath()).completeBaseName());
- args << QString("/AppTitle=LameXP (Build #%1)").arg(QString::number(m_updateInfo->m_buildNo));
+ args << QString("/AppTitle=LameXP (Build #%1)").arg(QString::number(updateInfo->m_buildNo));
QApplication::setOverrideCursor(Qt::WaitCursor);
- WinSevenTaskbar::setTaskbarState(this->parentWidget(), WinSevenTaskbar::WinSevenTaskbarIndeterminateState);
- WinSevenTaskbar::setOverlayIcon(this->parentWidget(), &QIcon(":/icons/transmit_blue.png"));
+ UPDATE_TASKBAR(WinSevenTaskbar::WinSevenTaskbarIndeterminateState, ":/icons/transmit_blue.png");
process.start(m_binaryUpdater, args);
bool updateStarted = process.waitForStarted();
@@ -946,136 +451,30 @@ void UpdateDialog::progressBarValueChanged(int value)
WinSevenTaskbar::setTaskbarProgress(this->parentWidget(), value, ui->progressBar->maximum());
}
-void UpdateDialog::testKnownWebSites(void)
+void UpdateDialog::testKnownHosts(void)
{
- int connectionScore = 0;
-
- // ----- Initialization ----- //
-
- ui->progressBar->setValue(0);
- WinSevenTaskbar::setTaskbarState(this->parentWidget(), WinSevenTaskbar::WinSevenTaskbarNormalState);
- WinSevenTaskbar::setOverlayIcon(this->parentWidget(), &QIcon(":/icons/transmit_blue.png"));
- ui->installButton->setEnabled(false);
- ui->closeButton->setEnabled(false);
- ui->retryButton->setEnabled(false);
- ui->logButton->setEnabled(false);
- if(ui->infoLabel->isVisible()) ui->infoLabel->hide();
- if(ui->hintLabel->isVisible()) ui->hintLabel->hide();
- if(ui->hintIcon->isVisible()) ui->hintIcon->hide();
- ui->frameAnimation->show();
-
- QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
- QApplication::setOverrideCursor(Qt::WaitCursor);
-
- // ----- Test Internet Connection ----- //
-
ui->statusLabel->setText("Testing all known hosts, this may take a few minutes...");
-
- m_logFile->clear();
- m_logFile->append("Checking internet connection...");
- const int networkStatus = DO_ASYNC(lamexp_network_status);
- if(networkStatus == lamexp_network_non)
+ if(UpdateCheckThread *testThread = new UpdateCheckThread(m_betaUpdates, true))
{
- m_logFile->append(QStringList() << "" << "Operating system reports that the computer is currently offline !!!");
- if(!ui->retryButton->isVisible()) ui->retryButton->show();
- if(!ui->logButton->isVisible()) ui->logButton->show();
- ui->closeButton->setEnabled(true);
- ui->retryButton->setEnabled(true);
- ui->logButton->setEnabled(true);
- if(ui->frameAnimation->isVisible()) ui->frameAnimation->hide();
- ui->statusLabel->setText(tr("It appears that the computer currently is offline!"));
- ui->progressBar->setValue(ui->progressBar->maximum());
- ui->hintIcon->setPixmap(QIcon(":/icons/network_error.png").pixmap(16,16));
- ui->hintLabel->setText(tr("Please make sure your computer is connected to the internet and try again."));
- ui->hintIcon->show();
- ui->hintLabel->show();
- LAMEXP_DELETE(m_updateInfo);
- if(m_settings->soundsEnabled()) lamexp_play_sound(IDR_WAVE_ERROR, true);
- QApplication::restoreOverrideCursor();
- ui->progressBar->setValue(ui->progressBar->maximum());
- WinSevenTaskbar::setTaskbarState(this->parentWidget(), WinSevenTaskbar::WinSevenTaskbarErrorState);
- WinSevenTaskbar::setOverlayIcon(this->parentWidget(), &QIcon(":/icons/exclamation.png"));
- return;
- }
-
- // ----- Test Known Hosts Connectivity ----- //
+ QEventLoop loop;
+ m_logFile->clear();
- QStringList hostList;
- for(int i = 0; known_hosts[i]; i++)
- {
- hostList << QString::fromLatin1(known_hosts[i]);
- }
+ connect(testThread, SIGNAL(messageLogged(QString)), this, SLOT(threadMessageLogged(QString)));
+ connect(testThread, SIGNAL(finished()), &loop, SLOT(quit()));
+ connect(testThread, SIGNAL(terminated()), &loop, SLOT(quit()));
- qDebug("[Known Hosts]");
-
- int hostCount = hostList.count();
- while(!hostList.isEmpty())
- {
- QString currentHost = hostList.takeFirst();
- ui->progressBar->setValue(qRound((static_cast(ui->progressBar->maximum() - 1) / static_cast(hostCount)) * static_cast(connectionScore)) + 1);
- qDebug("Testing: %s", currentHost.toLatin1().constData());
- m_logFile->append(QStringList() << "" << "Testing host:" << currentHost << "");
- QString outFile = QString("%1/%2.htm").arg(lamexp_temp_folder2(), lamexp_rand_str());
- bool httpOk = false;
- if(getFile(currentHost, outFile, 0, &httpOk))
+ testThread->start();
+ while(testThread->isRunning())
{
- connectionScore++;
+ QTimer::singleShot(5000, &loop, SLOT(quit()));
+ loop.exec(QEventLoop::ExcludeUserInputEvents);
}
- else
- {
- if(httpOk)
- {
- qWarning("\nConnectivity test was SLOW on the following site:\n%s\n", currentHost.toLatin1().constData());
- connectionScore++;
- }
- else
- {
- qWarning("\nConnectivity test FAILED on the following site:\n%s\n", currentHost.toLatin1().constData());
- }
- }
- QFile::remove(outFile);
- }
- if(connectionScore < hostCount)
- {
- if(!ui->retryButton->isVisible()) ui->retryButton->show();
- if(!ui->logButton->isVisible()) ui->logButton->show();
- ui->closeButton->setEnabled(true);
- ui->retryButton->setEnabled(true);
- ui->logButton->setEnabled(true);
- if(ui->frameAnimation->isVisible()) ui->frameAnimation->hide();
- ui->statusLabel->setText("At least one host could not be reached!");
- ui->progressBar->setValue(ui->progressBar->maximum());
- ui->hintIcon->setPixmap(QIcon(":/icons/network_error.png").pixmap(16,16));
- ui->hintLabel->setText("Please make sure your internet connection is working properly and try again.");
- ui->hintIcon->show();
- ui->hintLabel->show();
- LAMEXP_DELETE(m_updateInfo);
- if(m_settings->soundsEnabled()) lamexp_play_sound(IDR_WAVE_ERROR, true);
- QApplication::restoreOverrideCursor();
- ui->progressBar->setValue(ui->progressBar->maximum());
- WinSevenTaskbar::setTaskbarState(this->parentWidget(), WinSevenTaskbar::WinSevenTaskbarErrorState);
- WinSevenTaskbar::setOverlayIcon(this->parentWidget(), &QIcon(":/icons/exclamation.png"));
- return;
+ LAMEXP_DELETE(testThread);
+ logButtonClicked();
}
- // ----- Done ----- //
-
- QApplication::restoreOverrideCursor();
- ui->progressBar->setValue(ui->progressBar->maximum());
-
ui->statusLabel->setText("Test completed.");
- ui->hintIcon->setPixmap(QIcon(":/icons/shield_green.png").pixmap(16,16));
- ui->hintLabel->setText("Congratulations, the test has completed.");
- if(ui->frameAnimation->isVisible()) ui->frameAnimation->hide();
- ui->hintIcon->show();
- ui->hintLabel->show();
- WinSevenTaskbar::setOverlayIcon(this->parentWidget(), &QIcon(":/icons/shield_green.png"));
lamexp_beep(lamexp_beep_info);
-
- ui->closeButton->setEnabled(true);
- if(ui->retryButton->isVisible()) ui->retryButton->hide();
- if(ui->logButton->isVisible()) ui->logButton->hide();
- if(ui->frameAnimation->isVisible()) ui->frameAnimation->hide();
}
diff --git a/src/Dialog_Update.h b/src/Dialog_Update.h
index c029f412..accbf970 100644
--- a/src/Dialog_Update.h
+++ b/src/Dialog_Update.h
@@ -27,6 +27,7 @@
class UpdateInfo;
class SettingsModel;
class QMovie;
+class UpdateCheckThread;
//UIC forward declartion
namespace Ui {
@@ -53,6 +54,11 @@ private slots:
void logButtonClicked(void);
void progressBarValueChanged(int value);
+ void threadStatusChanged(const int status);
+ void threadProgressChanged(const int progress);
+ void threadMessageLogged(const QString &message);
+ void threadFinished(void);
+
protected:
virtual void showEvent(QShowEvent *event);
virtual void closeEvent(QCloseEvent *event);
@@ -65,24 +71,19 @@ protected:
private:
Ui::UpdateDialog *ui; //for Qt UIC
- bool tryUpdateMirror(UpdateInfo *updateInfo, const QString &url);
- bool getFile(const QString &url, const QString &outFile, unsigned int maxRedir = 5, bool *httpOk = NULL);
- bool checkSignature(const QString &file, const QString &signature);
- bool parseVersionInfo(const QString &file, UpdateInfo *updateInfo);
- void testKnownWebSites(void);
+ const QString m_binaryUpdater;
- UpdateInfo *m_updateInfo;
+ UpdateCheckThread *m_thread;
QStringList *m_logFile;
SettingsModel *m_settings;
QMovie *m_animator;
-
- const QString m_binaryWGet;
- const QString m_binaryGnuPG;
- const QString m_binaryUpdater;
- const QString m_binaryKeys;
+
unsigned long m_updaterProcess;
bool m_success;
bool m_updateReadyToInstall;
bool m_firstShow;
+
+ void testKnownHosts(void);
+
};
diff --git a/src/Thread_CheckUpdate.cpp b/src/Thread_CheckUpdate.cpp
new file mode 100644
index 00000000..e528f886
--- /dev/null
+++ b/src/Thread_CheckUpdate.cpp
@@ -0,0 +1,710 @@
+///////////////////////////////////////////////////////////////////////////////
+// LameXP - Audio Encoder Front-End
+// Copyright (C) 2004-2013 LoRd_MuldeR
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version, but always including the *additional*
+// restrictions defined in the "License.txt" file.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// http://www.gnu.org/licenses/gpl-2.0.txt
+///////////////////////////////////////////////////////////////////////////////
+
+#include "Thread_CheckUpdate.h"
+
+#include "Global.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+///////////////////////////////////////////////////////////////////////////////
+// CONSTANTS
+///////////////////////////////////////////////////////////////////////////////
+
+static const char *header_id = "!Update";
+static const char *section_id = "LameXP";
+
+static const char *mirror_url_postfix[] =
+{
+ "update.ver",
+ "update_beta.ver",
+ NULL
+};
+
+static const char *update_mirrors_prim[] =
+{
+ "http://muldersoft.com/",
+ "http://mulder.bplaced.net/",
+ "http://mulder.cwsurf.de/",
+ "http://mulder.6te.net/",
+ "http://mulder.webuda.com/",
+ "http://mulder.byethost13.com/",
+ "http://muldersoft.kilu.de/",
+ "http://muldersoft.zxq.net/",
+ "http://lamexp.sourceforge.net/",
+ "http://lamexp.berlios.de/",
+ "http://lordmulder.github.com/LameXP/",
+ "http://lord_mulder.bitbucket.org/",
+ "http://www.tricksoft.de/",
+ NULL
+};
+
+static const char *update_mirrors_back[] =
+{
+ "http://mplayer.savedonthe.net/",
+ NULL
+};
+
+static const char *known_hosts[] = //Taken form: http://www.alexa.com/topsites !!!
+{
+ "http://www.163.com/",
+ "http://www.ac3filter.net/",
+ "http://www.amazon.com/",
+ "http://www.aol.com/",
+ "http://www.apache.org/",
+ "http://www.apple.com/",
+ "http://www.adobe.com/",
+ "http://www.avidemux.org/",
+ "http://www.babylon.com/",
+ "http://www.baidu.com/",
+ "http://www.bbc.co.uk/",
+ "http://www.berlios.de/",
+ "http://www.bing.com/",
+ "http://www.cnet.com/",
+ "http://cnzz.com/",
+ "http://codecs.com/",
+ "http://www.codeplex.com/",
+ "http://qt.digia.com/",
+ "http://www.ebay.com/",
+ "http://www.equation.com/",
+ "http://fc2.com/",
+ "http://www.ffmpeg.org/",
+ "http://www.flickr.com/",
+ "http://blog.gitorious.org/",
+ "http://git-scm.com/",
+ "http://www.gnome.org/",
+ "http://www.gnu.org/",
+ "http://go.com/",
+ "http://code.google.com/",
+ "http://www.heise.de/",
+ "http://www.huffingtonpost.co.uk/",
+ "http://www.iana.org/",
+ "http://www.imdb.com/",
+ "http://www.imgburn.com/",
+ "http://imgur.com/",
+ "http://en.jd.com/",
+ "http://mirrors.kernel.org/",
+ "http://www.libav.org/",
+ "http://www.linkedin.com/about-us",
+ "http://www.livedoor.com/",
+ "http://www.livejournal.com/",
+ "http://mail.ru/",
+ "http://www.mediafire.com/",
+ "http://www.mozilla.org/en-US/",
+ "http://mplayerhq.hu/",
+ "http://www.msn.com/?st=1",
+ "http://oss.netfarm.it/",
+ "http://www.nytimes.com/",
+ "http://www.opera.com/",
+ "http://www.portablefreeware.com/",
+ "http://qt-project.org/",
+ "http://www.quakelive.com/",
+ "http://www.seamonkey-project.org/",
+ "http://www.sina.com.cn/",
+ "http://www.sohu.com/",
+ "http://www.soso.com/",
+ "http://sourceforge.net/",
+ "http://www.spiegel.de/",
+ "http://tdm-gcc.tdragon.net/",
+ "http://www.tdrsmusic.com/",
+ "http://www.ubuntu.com/",
+ "http://status.twitter.com/",
+ "http://www.uol.com.br/",
+ "http://www.videohelp.com/",
+ "http://www.videolan.org/",
+ "http://www.weibo.com/",
+ "http://www.wikipedia.org/",
+ "http://www.winamp.com/",
+ "http://wordpress.com/",
+ "http://us.yahoo.com/",
+ "http://www.yandex.ru/",
+ "http://www.youtube.com/",
+ "http://www.zedo.com/",
+ "http://ffmpeg.zeranoe.com/",
+ NULL
+};
+
+static const int MIN_CONNSCORE = 8;
+static const int VERSION_INFO_EXPIRES_MONTHS = 6;
+static char *USER_AGENT_STR = "Mozilla/5.0 (X11; Linux i686; rv:7.0.1) Gecko/20111106 IceCat/7.0.1";
+
+//Helper function
+static int getMaxProgress(void)
+{
+ int counter = MIN_CONNSCORE + 2;
+ for(int i = 0; update_mirrors_prim[i]; i++) counter++;
+ for(int i = 0; update_mirrors_back[i]; i++) counter++;
+ return counter;
+}
+
+////////////////////////////////////////////////////////////
+// Update Info Class
+////////////////////////////////////////////////////////////
+
+UpdateInfo::UpdateInfo(void)
+{
+ resetInfo();
+}
+
+void UpdateInfo::resetInfo(void)
+{
+ m_buildNo = 0;
+ m_buildDate.setDate(1900, 1, 1);
+ m_downloadSite.clear();
+ m_downloadAddress.clear();
+ m_downloadFilename.clear();
+ m_downloadFilecode.clear();
+}
+
+////////////////////////////////////////////////////////////
+// Constructor & Destructor
+////////////////////////////////////////////////////////////
+
+UpdateCheckThread::UpdateCheckThread(const bool betaUpdates, const bool testMode)
+:
+ m_updateInfo(new UpdateInfo()),
+ m_betaUpdates(betaUpdates),
+ m_testMode(testMode),
+ m_binaryWGet(lamexp_lookup_tool("wget.exe")),
+ m_binaryGnuPG(lamexp_lookup_tool("gpgv.exe")),
+ m_binaryKeys(lamexp_lookup_tool("gpgv.gpg")),
+ m_maxProgress(getMaxProgress())
+{
+ m_success = false;
+ m_status = UpdateStatus_NotStartedYet;
+ m_progress = 0;
+
+ if(m_binaryWGet.isEmpty() || m_binaryGnuPG.isEmpty() || m_binaryKeys.isEmpty())
+ {
+ THROW("Tools not initialized correctly!");
+ }
+}
+
+UpdateCheckThread::~UpdateCheckThread(void)
+{
+ delete m_updateInfo;
+}
+
+////////////////////////////////////////////////////////////
+// Protected functions
+////////////////////////////////////////////////////////////
+
+void UpdateCheckThread::run(void)
+{
+ qDebug("Update checker thread started!");
+
+ try
+ {
+ m_testMode ? testKnownHosts() : checkForUpdates();
+ }
+ catch(const std::exception &error)
+ {
+ fflush(stdout); fflush(stderr);
+ fprintf(stderr, "\nGURU MEDITATION !!!\n\nException error:\n%s\n", error.what());
+ lamexp_fatal_exit(L"Unhandeled C++ exception error, application will exit!");
+ }
+ catch(...)
+ {
+ fflush(stdout); fflush(stderr);
+ fprintf(stderr, "\nGURU MEDITATION !!!\n\nUnknown exception error!\n");
+ lamexp_fatal_exit(L"Unhandeled C++ exception error, application will exit!");
+ }
+
+ qDebug("Update checker thread completed.");
+}
+
+void UpdateCheckThread::checkForUpdates(void)
+{
+ // ----- Initialization ----- //
+
+ m_success = false;
+ m_updateInfo->resetInfo();
+ setProgress(0);
+
+ // ----- Test Internet Connection ----- //
+
+ int connectionScore = 0;
+
+ log("Checking internet connection...");
+ setStatus(UpdateStatus_CheckingConnection);
+
+ const int networkStatus = lamexp_network_status();
+ if(networkStatus == lamexp_network_non)
+ {
+ log("", "Operating system reports that the computer is currently offline !!!");
+ setProgress(m_maxProgress);
+ setStatus(UpdateStatus_ErrorNoConnection);
+ return;
+ }
+
+ setProgress(1);
+
+ // ----- Test Known Hosts Connectivity ----- //
+
+ QStringList hostList;
+ for(int i = 0; known_hosts[i]; i++)
+ {
+ hostList << QString::fromLatin1(known_hosts[i]);
+ }
+
+ lamexp_seed_rand();
+ while(!hostList.isEmpty())
+ {
+ QString currentHost = hostList.takeAt(lamexp_rand() % hostList.count());
+ if(connectionScore < MIN_CONNSCORE)
+ {
+ log("", "Testing host:", currentHost);
+ QString outFile = QString("%1/%2.htm").arg(lamexp_temp_folder2(), lamexp_rand_str());
+ bool httpOk = false;
+ if(getFile(currentHost, outFile, 0, &httpOk))
+ {
+ connectionScore++;
+ setProgress(qBound(1, connectionScore + 1, MIN_CONNSCORE + 1));
+ lamexp_sleep(64);
+ }
+ if(httpOk)
+ {
+ connectionScore++;
+ setProgress(qBound(1, connectionScore + 1, MIN_CONNSCORE + 1));
+ lamexp_sleep(64);
+ }
+ QFile::remove(outFile);
+ }
+ }
+
+ if(connectionScore < MIN_CONNSCORE)
+ {
+ setProgress(m_maxProgress);
+ setStatus(UpdateStatus_ErrorConnectionTestFailed);
+ return;
+ }
+
+ // ----- Build Mirror List ----- //
+
+ log("", "----", "", "Checking for updates online...");
+ setStatus(UpdateStatus_FetchingUpdates);
+
+ QStringList mirrorList;
+ for(int index = 0; update_mirrors_prim[index]; index++)
+ {
+ mirrorList << QString::fromLatin1(update_mirrors_prim[index]);
+ }
+
+ lamexp_seed_rand();
+ if(const int len = mirrorList.count())
+ {
+ const int rounds = len * 1097;
+ for(int i = 0; i < rounds; i++)
+ {
+ mirrorList.swap(i % len, lamexp_rand() % len);
+ }
+ }
+
+ for(int index = 0; update_mirrors_back[index]; index++)
+ {
+ mirrorList << QString::fromLatin1(update_mirrors_back[index]);
+ }
+
+ // ----- Fetch Update Info From Server ----- //
+
+ while(!mirrorList.isEmpty())
+ {
+ QString currentMirror = mirrorList.takeFirst();
+ setProgress(m_progress + 1);
+ if(!m_success)
+ {
+ if(tryUpdateMirror(m_updateInfo, currentMirror))
+ {
+ m_success = true;
+ }
+ }
+ else
+ {
+ lamexp_sleep(64);
+ }
+ }
+
+ setProgress(m_maxProgress);
+
+ if(m_success)
+ {
+ if(m_updateInfo->m_buildNo > lamexp_version_build())
+ {
+ setStatus(UpdateStatus_CompletedUpdateAvailable);
+ }
+ else if(m_updateInfo->m_buildNo == lamexp_version_build())
+ {
+ setStatus(UpdateStatus_CompletedNoUpdates);
+ }
+ else
+ {
+ setStatus(UpdateStatus_CompletedNewVersionOlder);
+ }
+ }
+ else
+ {
+ setStatus(UpdateStatus_ErrorFetchUpdateInfo);
+ }
+}
+
+void UpdateCheckThread::testKnownHosts(void)
+{
+ QStringList hostList;
+ for(int i = 0; known_hosts[i]; i++)
+ {
+ hostList << QString::fromLatin1(known_hosts[i]);
+ }
+
+ qDebug("\n[Known Hosts]");
+ log("Testing all known hosts...", "", "---");
+
+ int hostCount = hostList.count();
+ while(!hostList.isEmpty())
+ {
+ QString currentHost = hostList.takeFirst();
+ qDebug("Testing: %s", currentHost.toLatin1().constData());
+ log("", "Testing:", currentHost, "");
+ QString outFile = QString("%1/%2.htm").arg(lamexp_temp_folder2(), lamexp_rand_str());
+ bool httpOk = false;
+ if(!getFile(currentHost, outFile, 0, &httpOk))
+ {
+ if(httpOk)
+ {
+ qWarning("\nConnectivity test was SLOW on the following site:\n%s\n", currentHost.toLatin1().constData());
+ }
+ else
+ {
+ qWarning("\nConnectivity test FAILED on the following site:\n%s\n", currentHost.toLatin1().constData());
+ }
+ }
+ log("", "---");
+ QFile::remove(outFile);
+ }
+}
+
+////////////////////////////////////////////////////////////
+// PRIVATE FUNCTIONS
+////////////////////////////////////////////////////////////
+
+void UpdateCheckThread::setStatus(const int status)
+{
+ if(m_status != status)
+ {
+ m_status = status;
+ emit statusChanged(status);
+ }
+}
+
+void UpdateCheckThread::setProgress(const int progress)
+{
+ if(m_progress != progress)
+ {
+ m_progress = progress;
+ emit progressChanged(progress);
+ }
+}
+
+void UpdateCheckThread::log(const QString &str1, const QString &str2, const QString &str3, const QString &str4)
+{
+ if(!str1.isNull()) emit messageLogged(str1);
+ if(!str2.isNull()) emit messageLogged(str2);
+ if(!str3.isNull()) emit messageLogged(str3);
+ if(!str4.isNull()) emit messageLogged(str4);
+}
+
+bool UpdateCheckThread::tryUpdateMirror(UpdateInfo *updateInfo, const QString &url)
+{
+ bool success = false;
+ log("", "Trying mirror:", url);
+
+ QString randPart = lamexp_rand_str();
+ QString outFileVersionInfo = QString("%1/%2.ver").arg(lamexp_temp_folder2(), randPart);
+ QString outFileSignature = QString("%1/%2.sig").arg(lamexp_temp_folder2(), randPart);
+
+ log("", "Downloading update info:");
+ bool ok1 = getFile(QString("%1%2").arg(url, mirror_url_postfix[m_betaUpdates ? 1 : 0]), outFileVersionInfo);
+
+ log("", "Downloading signature:");
+ bool ok2 = getFile(QString("%1%2.sig").arg(url, mirror_url_postfix[m_betaUpdates ? 1 : 0]), outFileSignature);
+
+ if(ok1 && ok2)
+ {
+ log("", "Download okay, checking signature:");
+ if(checkSignature(outFileVersionInfo, outFileSignature))
+ {
+ log("", "Signature okay, parsing info:");
+ success = parseVersionInfo(outFileVersionInfo, updateInfo);
+ }
+ else
+ {
+ log("", "Bad signature, take care!");
+ }
+ }
+ else
+ {
+ log("", "Download has failed!");
+ }
+
+ QFile::remove(outFileVersionInfo);
+ QFile::remove(outFileSignature);
+
+ return success;
+}
+
+bool UpdateCheckThread::getFile(const QString &url, const QString &outFile, unsigned int maxRedir, bool *httpOk)
+{
+ QFileInfo output(outFile);
+ output.setCaching(false);
+ if(httpOk) *httpOk = false;
+
+ if(output.exists())
+ {
+ QFile::remove(output.canonicalFilePath());
+ if(output.exists())
+ {
+ return false;
+ }
+ }
+
+ QProcess process;
+ lamexp_init_process(process, output.absolutePath());
+
+ QStringList args;
+ args << "--no-cache" << "--no-dns-cache" << QString().sprintf("--max-redirect=%u", maxRedir);
+ args << QString("--referer=%1://%2/").arg(QUrl(url).scheme(), QUrl(url).host()) << "-U" << USER_AGENT_STR;
+ args << "-O" << output.fileName() << url;
+
+ 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()));
+
+ QTimer timer;
+ timer.setSingleShot(true);
+ timer.setInterval(25000);
+ connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
+
+ const QRegExp httpResponseOK("200 OK$");
+
+ process.start(m_binaryWGet, args);
+
+ if(!process.waitForStarted())
+ {
+ return false;
+ }
+
+ timer.start();
+
+ while(process.state() == QProcess::Running)
+ {
+ loop.exec();
+ bool bTimeOut = (!timer.isActive());
+ while(process.canReadLine())
+ {
+ QString line = QString::fromLatin1(process.readLine()).simplified();
+ if(line.contains(httpResponseOK))
+ {
+ line.append(" [OK]");
+ if(httpOk) *httpOk = true;
+ }
+ log(line);
+ }
+ if(bTimeOut)
+ {
+ qWarning("WGet process timed out <-- killing!");
+ process.kill();
+ process.waitForFinished();
+ log("!!! TIMEOUT !!!");
+ return false;
+ }
+ }
+
+ timer.stop();
+ timer.disconnect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
+
+ log(QString().sprintf("Exited with code %d", process.exitCode()));
+ return (process.exitCode() == 0) && output.exists() && output.isFile();
+}
+
+bool UpdateCheckThread::checkSignature(const QString &file, const QString &signature)
+{
+ if(QFileInfo(file).absolutePath().compare(QFileInfo(signature).absolutePath(), Qt::CaseInsensitive) != 0)
+ {
+ qWarning("CheckSignature: File and signature should be in same folder!");
+ return false;
+ }
+ if(QFileInfo(file).absolutePath().compare(QFileInfo(m_binaryKeys).absolutePath(), Qt::CaseInsensitive) != 0)
+ {
+ qWarning("CheckSignature: File and keyring should be in same folder!");
+ return false;
+ }
+
+ QProcess process;
+ lamexp_init_process(process, QFileInfo(file).absolutePath());
+
+ 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" << "." << "--keyring" << QFileInfo(m_binaryKeys).fileName() << QFileInfo(signature).fileName() << QFileInfo(file).fileName());
+
+ if(!process.waitForStarted())
+ {
+ return false;
+ }
+
+ while(process.state() == QProcess::Running)
+ {
+ loop.exec();
+ while(process.canReadLine())
+ {
+ log(QString::fromLatin1(process.readLine()).simplified());
+ }
+ }
+
+ log(QString().sprintf("Exited with code %d", process.exitCode()));
+ return (process.exitCode() == 0);
+}
+
+bool UpdateCheckThread::parseVersionInfo(const QString &file, UpdateInfo *updateInfo)
+{
+ QRegExp value("^(\\w+)=(.+)$");
+ QRegExp section("^\\[(.+)\\]$");
+
+ QDate updateInfoDate;
+ updateInfo->resetInfo();
+
+ QFile data(file);
+ if(!data.open(QIODevice::ReadOnly))
+ {
+ qWarning("Cannot open update info file for reading!");
+ return false;
+ }
+
+ bool inHeader = false;
+ bool inSection = false;
+
+ while(!data.atEnd())
+ {
+ QString line = QString::fromLatin1(data.readLine()).trimmed();
+ if(section.indexIn(line) >= 0)
+ {
+ log(QString("Sec: [%1]").arg(section.cap(1)));
+ inSection = (section.cap(1).compare(section_id, Qt::CaseInsensitive) == 0);
+ inHeader = (section.cap(1).compare(header_id, Qt::CaseInsensitive) == 0);
+ continue;
+ }
+ if(inSection && (value.indexIn(line) >= 0))
+ {
+ log(QString("Val: '%1' ==> '%2").arg(value.cap(1), value.cap(2)));
+ 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();
+ }
+ }
+ if(inHeader && (value.indexIn(line) >= 0))
+ {
+ log(QString("Val: '%1' ==> '%2").arg(value.cap(1), value.cap(2)));
+ if(value.cap(1).compare("TimestampCreated", Qt::CaseInsensitive) == 0)
+ {
+ QDate temp = QDate::fromString(value.cap(2).trimmed(), Qt::ISODate);
+ if(temp.isValid()) updateInfoDate = temp;
+ }
+ }
+ }
+
+ if(!updateInfoDate.isValid())
+ {
+ updateInfo->resetInfo();
+ log("WARNING: Version info timestamp is missing!");
+ return false;
+ }
+ else if(updateInfoDate.addMonths(VERSION_INFO_EXPIRES_MONTHS) < lamexp_current_date_safe())
+ {
+ updateInfo->resetInfo();
+ log(QString::fromLatin1("WARNING: This version info has expired at %1!").arg(updateInfoDate.addMonths(VERSION_INFO_EXPIRES_MONTHS).toString(Qt::ISODate)));
+ return false;
+ }
+ else if(lamexp_current_date_safe() < updateInfoDate)
+ {
+ log("Version info is from the future, take care!");
+ qWarning("Version info is from the future, take care!");
+ }
+
+ 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;
+
+ if(!complete)
+ {
+ log("WARNING: Version info is incomplete!");
+ }
+
+ return complete;
+}
+
+////////////////////////////////////////////////////////////
+// SLOTS
+////////////////////////////////////////////////////////////
+
+/*NONE*/
+
+////////////////////////////////////////////////////////////
+// EVENTS
+////////////////////////////////////////////////////////////
+
+/*NONE*/
diff --git a/src/Thread_CheckUpdate.h b/src/Thread_CheckUpdate.h
new file mode 100644
index 00000000..6d9a5ae5
--- /dev/null
+++ b/src/Thread_CheckUpdate.h
@@ -0,0 +1,108 @@
+///////////////////////////////////////////////////////////////////////////////
+// LameXP - Audio Encoder Front-End
+// Copyright (C) 2004-2013 LoRd_MuldeR
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version, but always including the *additional*
+// restrictions defined in the "License.txt" file.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// http://www.gnu.org/licenses/gpl-2.0.txt
+///////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+#include
+#include
+
+///////////////////////////////////////////////////////////////////////////////
+
+class UpdateInfo
+{
+public:
+ UpdateInfo(void);
+ void resetInfo(void);
+
+ unsigned int m_buildNo;
+ QDate m_buildDate;
+ QString m_downloadSite;
+ QString m_downloadAddress;
+ QString m_downloadFilename;
+ QString m_downloadFilecode;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class UpdateCheckThread : public QThread
+{
+ Q_OBJECT
+
+public:
+ enum
+ {
+ UpdateStatus_NotStartedYet = 0,
+ UpdateStatus_CheckingConnection = 1,
+ UpdateStatus_FetchingUpdates = 2,
+ UpdateStatus_CompletedUpdateAvailable = 3,
+ UpdateStatus_CompletedNoUpdates = 4,
+ UpdateStatus_CompletedNewVersionOlder = 5,
+ UpdateStatus_ErrorNoConnection = 6,
+ UpdateStatus_ErrorConnectionTestFailed = 7,
+ UpdateStatus_ErrorFetchUpdateInfo = 8
+ }
+ update_status_t;
+
+ UpdateCheckThread(const bool betaUpdates, const bool testMode = false);
+ ~UpdateCheckThread(void);
+
+ const int getUpdateStatus(void) const { return m_status; }
+ const bool getSuccess(void) const { return m_success; };
+ const int getMaximumProgress(void) const { return m_maxProgress; };
+ const int getCurrentProgress(void) const { return m_progress; };
+ const UpdateInfo *getUpdateInfo(void) const { return m_updateInfo; }
+
+protected:
+ void run(void);
+ void checkForUpdates(void);
+ void testKnownHosts(void);
+
+signals:
+ void statusChanged(const int status);
+ void progressChanged(const int progress);
+ void messageLogged(const QString &text);
+
+private:
+ const int m_maxProgress;
+ UpdateInfo *const m_updateInfo;
+
+ const bool m_betaUpdates;
+ const bool m_testMode;
+
+ const QString m_binaryWGet;
+ const QString m_binaryGnuPG;
+ const QString m_binaryKeys;
+
+ volatile bool m_success;
+
+ int m_status;
+ int m_progress;
+
+ inline void setStatus(const int status);
+ inline void setProgress(const int progress);
+ inline void log(const QString &str1, const QString &str2 = QString(), const QString &str3 = QString(), const QString &str4 = QString());
+
+ bool getFile(const QString &url, const QString &outFile, unsigned int maxRedir = 5, bool *httpOk = NULL);
+ bool tryUpdateMirror(UpdateInfo *updateInfo, const QString &url);
+ bool checkSignature(const QString &file, const QString &signature);
+ bool parseVersionInfo(const QString &file, UpdateInfo *updateInfo);
+};