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 - + Executable '%1' doesn't support Windows compatibility mode. - + Executable '%1' requires Qt v%2, but found Qt v%3. - + Executable '%1' was built for Qt '%2', but found Qt '%3'. - + Executable '%1' requires Windows XP or later. @@ -3384,105 +3384,104 @@ - - + + Build - + Unknown - + Testing your internet connection, please wait... - - + It appears that the computer currently is offline! - - + + Please make sure your computer is connected to the internet and try again. - + Network connectivity test has failed! - - Please make sure your internet connection is working properly and try again. - - - - + Checking for new updates online, please wait... - + Failed to fetch update information from server! - + Sorry, the update server might be busy at this time. Plase try again later. - + More information available at: - + A new version of LameXP is available! - + + Initializing, please wait... + + + + We highly recommend all users to install this update as soon as possible. - + No new updates available at this time. - + Your version of LameXP is still up-to-date. Please check for updates regularly! - + Your version appears to be newer than the latest release. - + This usually indicates your are currently using a pre-release version of LameXP. - + Update is being downloaded, please be patient... - + Update ready to install. Applicaion will quit... - + Update failed. Please try again or download manually! 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 @@ BerliOS Developer - + CodePlex - + @@ -2600,7 +2600,7 @@ Executable '%1' requires Windows XP or later. - + Programm '%1' benötigt Windows XP oder neuer. @@ -2667,10 +2667,6 @@ Network connectivity test has failed! Test der Netzwerkverbindung fehlgeschlagen! - - Please make sure your internet connection is working properly and try again. - Bitte prüfen Sie Ihre Internetverbindung und versuchen Sie es dann noch einmal. - Checking for new updates online, please wait... Suche online nach neuen Updates, bitte warten... @@ -2735,5 +2731,9 @@ Please make sure your computer is connected to the internet and try again. Aktivieren Sie Ihre Internetverbindung und versuchen Sie es dann noch einmal. + + Initializing, please wait... + 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 @@ Network connectivity test has failed! ¡La prueba de conexión a internet ha fallado! - - Please make sure your internet connection is working properly and try again. - Por favor, asegúrese de que su conexión a internet funciona correctamente y vuelva a intentarlo. - Checking for new updates online, please wait... Comprobando en busca de nuevas actualizaciones, espere por favor... @@ -2734,5 +2730,9 @@ Please make sure your computer is connected to the internet and try again. Por favor, asegurese de que tiene conexión a internet y vuelva a intentarlo. + + Initializing, please wait... + 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... Network connectivity test has failed! Le test de connectivité réseau a échoué! - - Please make sure your internet connection is working properly and try again. - Assurez-vous que votre connexion internet fonctionne correctement et essayez à nouveau. - Checking for new updates online, please wait... Vérification des nouvelles mises à jour en ligne, patientez... @@ -2745,5 +2741,9 @@ Ouvrir le dossier récursivement... Please make sure your computer is connected to the internet and try again. Veuillez vous assurer que votre ordinateur est connecté à internet et essayez à nouveau. + + Initializing, please wait... + 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 @@ Network connectivity test has failed! Il test di connessione di rete è fallito! - - Please make sure your internet connection is working properly and try again. - Per favore assicurati che la tua connessione internet sia funzionante e prova ancora. - Checking for new updates online, please wait... Ricerca di nuovi aggiornamenti in rete, attendere prego... @@ -2735,5 +2731,9 @@ Please make sure your computer is connected to the internet and try again. + + Initializing, please wait... + 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 @@ Network connectivity test has failed! 네트워크 연결 테스트가 실패되었습니다! - - Please make sure your internet connection is working properly and try again. - 인터넷에 연결되어 있는지 확인하고 다시 시도하시기 바랍니다. - Checking for new updates online, please wait... 새로운 업데이트 점검중, 잠시만 기다려 주십시오... @@ -2717,5 +2713,9 @@ Please make sure your computer is connected to the internet and try again. 인터넷 연결을 확인하고 다시 시도하시기 바랍니다. + + Initializing, please wait... + 초기화중, 잠시만 기다려 주십시오... + 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 - + Executable '%1' doesn't support Windows compatibility mode. Plik wykonywalny '%1' nie działa w trybie kompatybilności z Windows. - + Executable '%1' requires Qt v%2, but found Qt v%3. Plik wykonywalny '%1' wymaga Qt v%2, znaleziono jednak Qt v%3. - + Executable '%1' was built for Qt '%2', but found Qt '%3'. Plik wykonywalny "%1" został skompilowany dla Qt "%2", znaleziono "%3". - + Executable '%1' requires Windows XP or later. @@ -3421,105 +3421,104 @@ Zamknij - - + + Build Build - + Unknown Nieznana - + Testing your internet connection, please wait... Testowanie połączenia internetowego, prosze czekać... - - + It appears that the computer currently is offline! LameXP wykrył brak dostępu do internetu! - - + + Please make sure your computer is connected to the internet and try again. Upewnij się że komputer jest podłączony do internetu i spróbuj ponownie. - + Network connectivity test has failed! Test połączenia internetowego zakończony niepowodzeniem! - - Please make sure your internet connection is working properly and try again. - Upewnij się że połączenie internetowe działa prawidłowo i spróbuj ponownie. - - - + Checking for new updates online, please wait... Sprawdzanie aktualizacji online, prosze czekać... - + Failed to fetch update information from server! Pobieranie informacji z serwera zakończone niepowodzeniem! - + Sorry, the update server might be busy at this time. Plase try again later. Serwer aktualizacji wydaje się nie odpowiadać w tej chwili. Prosze spróbować później. - + More information available at: Więcej informacji tutaj: - + A new version of LameXP is available! Dostępna nowa wersja LameXP! - + + Initializing, please wait... + Inicjowanie, prosze czekać... + + + We highly recommend all users to install this update as soon as possible. Jest wysoce zalecane aby zainstalować tę aktualizację jak najszybciej. - + No new updates available at this time. Nie ma nowych aktualizacji w tej chwili. - + Your version of LameXP is still up-to-date. Please check for updates regularly! Posiadasz najnowszą wersję LameXP. Sprawdzaj aktualizacje regularnie! - + Your version appears to be newer than the latest release. Posiadasz nowszą wersję LameXP niż ostatnie wydanie. - + This usually indicates your are currently using a pre-release version of LameXP. To wskazuje na to, że posiadasz wersję alfa LameXP. - + Update is being downloaded, please be patient... Pobieranie aktualizacji w toku, prosze czekać... - + Update ready to install. Applicaion will quit... Aktualizacja gotowa do instalacji. Teraz program zostanie zamknięty... - + Update failed. Please try again or download manually! 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 @@ Network connectivity test has failed! Нет соединения с сетью! - - Please make sure your internet connection is working properly and try again. - Проверьте доступность интернет соединения и попробуйте снова. - Checking for new updates online, please wait... Проверяю обновления, пожалуйста, подождите... @@ -2760,5 +2756,9 @@ Please make sure your computer is connected to the internet and try again. Пожалуйста, проверьте, что ваш компьютер подключен к интернету и попробуйте снова. + + Initializing, please wait... + Инициализация, пожалуйста, подождите... + 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 - + Executable '%1' doesn't support Windows compatibility mode. EXE-filen '%1' stöder inte Windows kompatibilitetsläge. - + Executable '%1' requires Qt v%2, but found Qt v%3. EXE-filen '%1' kräver Qt v%2, du har Qt v%3. - + Executable '%1' was built for Qt '%2', but found Qt '%3'. EXE-filen '%1' är byggd för Qt '%2', du har Qt '%3'. - + Executable '%1' requires Windows XP or later. @@ -3404,105 +3404,104 @@ Stäng - - + + Build Build - + Unknown Okänd - + Testing your internet connection, please wait... Kontrollerar iInternetanslutningen, vänta... - - + It appears that the computer currently is offline! Datorn verkar inte vara ansluten till Internet! - - + + Please make sure your computer is connected to the internet and try again. Tillse att datorn är ansluten till Internet och försök igen. - + Network connectivity test has failed! Anslutningskontrollen misslyckades! - - Please make sure your internet connection is working properly and try again. - Tillse att Internetuppkopplingen fungerar korrekt och försök igen. - - - + Checking for new updates online, please wait... Söker nya uppdateringar, vänta... - + Failed to fetch update information from server! Kunde inte hämta uppdateringsinformation från servern! - + Sorry, the update server might be busy at this time. Plase try again later. Uppdateringsservern kan vara upptagen. Försök senare. - + More information available at: Mer information hittas på: - + A new version of LameXP is available! En ny version av LameXP finns tillgänglig! - + + Initializing, please wait... + Initierar, vänta... + + + We highly recommend all users to install this update as soon as possible. Vi rekommenderar alla användare att installera denna uppdatering så snart som möjligt. - + No new updates available at this time. Det finns inga nya uppdateringar. - + Your version of LameXP is still up-to-date. Please check for updates regularly! Din version av LameXP är uppdaterad. Kontrollera regelbundet! - + Your version appears to be newer than the latest release. Din version verkar vara nyare än senaste 'Release'. - + This usually indicates your are currently using a pre-release version of LameXP. Det innebär normalt att du använder en beta-version av LameXP. - + Update is being downloaded, please be patient... Uppdatering laddas ner, vänta... - + Update ready to install. Applicaion will quit... Uppdatering klar att installeras. Programmet kommer att avslutas... - + Update failed. Please try again or download manually! 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 @@ Network connectivity test has failed! 網絡連接測試失敗 ! - - Please make sure your internet connection is working properly and try again. - 請確保您的網絡連接正常工作,然后再試. - Checking for new updates online, please wait... 在線更新檢查新的版本,請稍候... @@ -2716,5 +2712,9 @@ Please make sure your computer is connected to the internet and try again. 請確保您的計算機連接到 Internet,然后重試. + + Initializing, please wait... + 正在初始化,請稍候... + 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 @@ Network connectivity test has failed! Збій перевірки мережевого з'єднання! - - Please make sure your internet connection is working properly and try again. - Будь ласка, впевніться, що ваше інтернет-з'єднання працює коректно і спробуйте знову. - Checking for new updates online, please wait... Йде перевірка оновлень онлайн, будь ласка, зачекайте... @@ -2753,5 +2749,9 @@ Update failed. Please try again or download manually! Збій оновлення. Будь ласка, спробуйте ще раз або завантажте оновлення самостійно! + + Initializing, please wait... + Ініціалізація, будь ласка, зачекайте... + 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 @@ Network connectivity test has failed! 网络连接测试失败 ! - - Please make sure your internet connection is working properly and try again. - 请确保您的网络连接正常工作,然后再试。 - Checking for new updates online, please wait... 在线检查新的版本,请稍候... @@ -2716,5 +2712,9 @@ Please make sure your computer is connected to the internet and try again. 请确保您的计算机连接到 Internet,然后重试。 + + Initializing, please wait... + 正在初始化,请稍候... + 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); +};