MUtilities development repository
修订版 | ba7fa5aea592ce7e103c3d977b263b73b3944e99 (tree) |
---|---|
时间 | 2018-10-16 06:26:36 |
作者 | ![]() |
Commiter | LoRd_MuldeR |
Updated the UpdateChecker class to use cURL instead of Wget.
@@ -81,7 +81,7 @@ namespace MUtils | ||
81 | 81 | } |
82 | 82 | update_status_t; |
83 | 83 | |
84 | - UpdateChecker(const QString &binWGet, const QString &binMCat, const QString &binGnuPG, const QString &binKeys, const QString &applicationId, const quint32 &installedBuildNo, const bool betaUpdates, const bool testMode = false); | |
84 | + UpdateChecker(const QString &binCurl, const QString &binGnuPG, const QString &binKeys, const QString &applicationId, const quint32 &installedBuildNo, const bool betaUpdates, const bool testMode = false); | |
85 | 85 | ~UpdateChecker(void); |
86 | 86 | |
87 | 87 | const int getUpdateStatus(void) const { return m_status; } |
@@ -115,11 +115,12 @@ namespace MUtils | ||
115 | 115 | const QString m_applicationId; |
116 | 116 | const quint32 m_installedBuildNo; |
117 | 117 | |
118 | - const QString m_binaryWGet; | |
119 | - const QString m_binaryMCat; | |
118 | + const QString m_binaryCurl; | |
120 | 119 | const QString m_binaryGnuPG; |
121 | 120 | const QString m_binaryKeys; |
122 | 121 | |
122 | + const QScopedPointer<const QHash<QString, QString>> m_environment; | |
123 | + | |
123 | 124 | QAtomicInt m_success; |
124 | 125 | QAtomicInt m_cancelled; |
125 | 126 |
@@ -131,11 +132,10 @@ namespace MUtils | ||
131 | 132 | inline void log(const QString &str1, const QString &str2 = QString(), const QString &str3 = QString(), const QString &str4 = QString()); |
132 | 133 | |
133 | 134 | bool getUpdateInfo(const QString &url, const QString &outFileVers, const QString &outFileSign); |
134 | - bool tryContactHost(const QString &hostname, const int &timeoutMsec, quint32 *const ipAddrOut = NULL); | |
135 | + bool tryContactHost(const QString &hostname, const int &timeoutMsec); | |
135 | 136 | bool parseVersionInfo(const QString &file, UpdateCheckerInfo *updateInfo); |
136 | 137 | |
137 | - bool getFile(const QString &url, const QString &outFile, const unsigned int maxRedir = 5U); | |
138 | - bool getFile(const QString &url, const bool forceIp4, const QString &outFile, const unsigned int maxRedir = 5U); | |
138 | + bool getFile(const QString &url, const QString &outFile, const unsigned int maxRedir = 8U); | |
139 | 139 | bool checkSignature(const QString &file, const QString &signature); |
140 | 140 | bool tryUpdateMirror(UpdateCheckerInfo *updateInfo, const QString &url, const bool &quick); |
141 | 141 | }; |
@@ -27,12 +27,14 @@ | ||
27 | 27 | #include <QStringList> |
28 | 28 | #include <QFile> |
29 | 29 | #include <QFileInfo> |
30 | +#include <QDir> | |
30 | 31 | #include <QProcess> |
31 | 32 | #include <QUrl> |
32 | 33 | #include <QEventLoop> |
33 | 34 | #include <QTimer> |
34 | 35 | #include <QElapsedTimer> |
35 | 36 | #include <QSet> |
37 | +#include <QHash> | |
36 | 38 | |
37 | 39 | #include "Mirrors.h" |
38 | 40 |
@@ -55,7 +57,7 @@ static const int MAX_CONN_TIMEOUT = 16000; | ||
55 | 57 | static const int DOWNLOAD_TIMEOUT = 30000; |
56 | 58 | |
57 | 59 | static const int VERSION_INFO_EXPIRES_MONTHS = 6; |
58 | -static char *USER_AGENT_STR = "Mozilla/5.0 (X11; Linux i686; rv:10.0) Gecko/20100101 Firefox/10.0"; /*use something innocuous*/ | |
60 | +static char *USER_AGENT_STR = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0"; /*use something innocuous*/ | |
59 | 61 | |
60 | 62 | #define CHECK_CANCELLED() do \ |
61 | 63 | { \ |
@@ -96,6 +98,13 @@ static QStringList buildRandomList(const char *const values[]) | ||
96 | 98 | return list; |
97 | 99 | } |
98 | 100 | |
101 | +static const QHash<QString, QString> *initEnvVars(void) | |
102 | +{ | |
103 | + QHash<QString, QString> *const environment = new QHash<QString, QString>(); | |
104 | + environment->insert(QLatin1String("CURL_HOME"), QDir::toNativeSeparators(MUtils::temp_folder())); | |
105 | + return environment; | |
106 | +} | |
107 | + | |
99 | 108 | //////////////////////////////////////////////////////////// |
100 | 109 | // Update Info Class |
101 | 110 | //////////////////////////////////////////////////////////// |
@@ -133,23 +142,23 @@ bool MUtils::UpdateCheckerInfo::isComplete(void) | ||
133 | 142 | // Constructor & Destructor |
134 | 143 | //////////////////////////////////////////////////////////// |
135 | 144 | |
136 | -MUtils::UpdateChecker::UpdateChecker(const QString &binWGet, const QString &binMCat, const QString &binGnuPG, const QString &binKeys, const QString &applicationId, const quint32 &installedBuildNo, const bool betaUpdates, const bool testMode) | |
145 | +MUtils::UpdateChecker::UpdateChecker(const QString &binCurl, const QString &binGnuPG, const QString &binKeys, const QString &applicationId, const quint32 &installedBuildNo, const bool betaUpdates, const bool testMode) | |
137 | 146 | : |
138 | 147 | m_updateInfo(new UpdateCheckerInfo()), |
139 | - m_binaryWGet(binWGet), | |
140 | - m_binaryMCat(binMCat), | |
148 | + m_binaryCurl(binCurl), | |
141 | 149 | m_binaryGnuPG(binGnuPG), |
142 | 150 | m_binaryKeys(binKeys), |
143 | 151 | m_applicationId(applicationId), |
144 | 152 | m_installedBuildNo(installedBuildNo), |
145 | 153 | m_betaUpdates(betaUpdates), |
146 | 154 | m_testMode(testMode), |
147 | - m_maxProgress(getMaxProgress()) | |
155 | + m_maxProgress(getMaxProgress()), | |
156 | + m_environment(initEnvVars()) | |
148 | 157 | { |
149 | 158 | m_status = UpdateStatus_NotStartedYet; |
150 | 159 | m_progress = 0; |
151 | 160 | |
152 | - if(m_binaryWGet.isEmpty() || m_binaryGnuPG.isEmpty() || m_binaryKeys.isEmpty()) | |
161 | + if(m_binaryCurl.isEmpty() || m_binaryGnuPG.isEmpty() || m_binaryKeys.isEmpty()) | |
153 | 162 | { |
154 | 163 | MUTILS_THROW("Tools not initialized correctly!"); |
155 | 164 | } |
@@ -209,7 +218,7 @@ void MUtils::UpdateChecker::checkForUpdates(void) | ||
209 | 218 | int connectionScore = 0; |
210 | 219 | QStringList mirrorList = buildRandomList(known_hosts); |
211 | 220 | |
212 | - for(int connectionTimout = 500; connectionTimout <= MAX_CONN_TIMEOUT; connectionTimout *= 2) | |
221 | + for(int connectionTimout = 1000; connectionTimout <= MAX_CONN_TIMEOUT; connectionTimout *= 2) | |
213 | 222 | { |
214 | 223 | QElapsedTimer elapsedTimer; |
215 | 224 | elapsedTimer.start(); |
@@ -348,25 +357,12 @@ void MUtils::UpdateChecker::testMirrorsList(void) | ||
348 | 357 | qDebug("\n[Known Hosts]"); |
349 | 358 | log("Testing all known hosts...", "", "---"); |
350 | 359 | |
351 | - QSet<quint32> ipAddrSet; | |
352 | - quint32 ipAddr; | |
353 | 360 | while(!knownHostList.isEmpty()) |
354 | 361 | { |
355 | 362 | const QString currentHost = knownHostList.takeFirst(); |
356 | 363 | qDebug("Testing: %s", MUTILS_L1STR(currentHost)); |
357 | 364 | log(QLatin1String(""), "Testing:", currentHost, ""); |
358 | - if (tryContactHost(currentHost, DOWNLOAD_TIMEOUT, &ipAddr)) | |
359 | - { | |
360 | - if (ipAddrSet.contains(ipAddr)) | |
361 | - { | |
362 | - qWarning("Duplicate IP-address 0x%08X was encountered!", ipAddr); | |
363 | - } | |
364 | - else | |
365 | - { | |
366 | - ipAddrSet << ipAddr; /*not encountered yet*/ | |
367 | - } | |
368 | - } | |
369 | - else | |
365 | + if (!tryContactHost(currentHost, DOWNLOAD_TIMEOUT)) | |
370 | 366 | { |
371 | 367 | qWarning("\nConnectivity test FAILED on the following host:\n%s\n", MUTILS_L1STR(currentHost)); |
372 | 368 | } |
@@ -572,22 +568,6 @@ bool MUtils::UpdateChecker::parseVersionInfo(const QString &file, UpdateCheckerI | ||
572 | 568 | |
573 | 569 | bool MUtils::UpdateChecker::getFile(const QString &url, const QString &outFile, const unsigned int maxRedir) |
574 | 570 | { |
575 | - for (int i = 0; i < 2; i++) | |
576 | - { | |
577 | - if (getFile(url, (i > 0), outFile, maxRedir)) | |
578 | - { | |
579 | - return true; | |
580 | - } | |
581 | - if (MUTILS_BOOLIFY(m_cancelled)) | |
582 | - { | |
583 | - break; /*cancelled*/ | |
584 | - } | |
585 | - } | |
586 | - return false; | |
587 | -} | |
588 | - | |
589 | -bool MUtils::UpdateChecker::getFile(const QString &url, const bool forceIp4, const QString &outFile, const unsigned int maxRedir) | |
590 | -{ | |
591 | 571 | QFileInfo output(outFile); |
592 | 572 | output.setCaching(false); |
593 | 573 |
@@ -601,18 +581,13 @@ bool MUtils::UpdateChecker::getFile(const QString &url, const bool forceIp4, con | ||
601 | 581 | } |
602 | 582 | |
603 | 583 | QProcess process; |
604 | - init_process(process, output.absolutePath()); | |
584 | + init_process(process, output.absolutePath(), true, NULL, m_environment.data()); | |
605 | 585 | |
606 | - QStringList args; | |
607 | - if (forceIp4) | |
608 | - { | |
609 | - args << "-4"; | |
610 | - } | |
611 | - | |
612 | - args << "--no-config" << "--no-cache" << "--no-dns-cache" << "--no-check-certificate" << "--no-hsts"; | |
613 | - args << QString().sprintf("--max-redirect=%u", maxRedir) << QString().sprintf("--timeout=%u", DOWNLOAD_TIMEOUT / 1000); | |
614 | - args << QString("--referer=%1://%2/").arg(QUrl(url).scheme(), QUrl(url).host()) << "-U" << USER_AGENT_STR; | |
615 | - args << "-O" << output.fileName() << url; | |
586 | + QStringList args(QLatin1String("-vsSqkfL")); | |
587 | + args << "-m" << QString::number(DOWNLOAD_TIMEOUT / 1000); | |
588 | + args << "--max-redirs" << QString::number(maxRedir); | |
589 | + args << "-U" << USER_AGENT_STR; | |
590 | + args << "-o" << output.fileName() << url; | |
616 | 591 | |
617 | 592 | QEventLoop loop; |
618 | 593 | connect(&process, SIGNAL(error(QProcess::ProcessError)), &loop, SLOT(quit())); |
@@ -623,16 +598,13 @@ bool MUtils::UpdateChecker::getFile(const QString &url, const bool forceIp4, con | ||
623 | 598 | timer.setSingleShot(true); |
624 | 599 | connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); |
625 | 600 | |
626 | - const QRegExp httpResponseOK("200 OK$"); | |
627 | - | |
628 | - process.start(m_binaryWGet, args); | |
629 | - | |
601 | + process.start(m_binaryCurl, args); | |
630 | 602 | if (!process.waitForStarted()) |
631 | 603 | { |
632 | 604 | return false; |
633 | 605 | } |
634 | 606 | |
635 | - timer.start(DOWNLOAD_TIMEOUT); | |
607 | + timer.start(2 * DOWNLOAD_TIMEOUT); | |
636 | 608 | |
637 | 609 | while (process.state() != QProcess::NotRunning) |
638 | 610 | { |
@@ -641,14 +613,17 @@ bool MUtils::UpdateChecker::getFile(const QString &url, const bool forceIp4, con | ||
641 | 613 | while (process.canReadLine()) |
642 | 614 | { |
643 | 615 | const QString line = QString::fromLatin1(process.readLine()).simplified(); |
644 | - log(line); | |
616 | + if (!line.isEmpty()) | |
617 | + { | |
618 | + log(line); | |
619 | + } | |
645 | 620 | } |
646 | 621 | if (bTimeOut || MUTILS_BOOLIFY(m_cancelled)) |
647 | 622 | { |
648 | - qWarning("WGet process timed out <-- killing!"); | |
623 | + qWarning("cURL process timed out <-- killing!"); | |
649 | 624 | process.kill(); |
650 | 625 | process.waitForFinished(); |
651 | - log(bTimeOut ? "!!! TIMEOUT !!!": "!!! CANCELLED !!!"); | |
626 | + log(bTimeOut ? "PROCESS TIMEOUT !!!" : "CANCELLED BY USER !!!", ""); | |
652 | 627 | return false; |
653 | 628 | } |
654 | 629 | } |
@@ -660,16 +635,18 @@ bool MUtils::UpdateChecker::getFile(const QString &url, const bool forceIp4, con | ||
660 | 635 | return (process.exitCode() == 0) && output.exists() && output.isFile(); |
661 | 636 | } |
662 | 637 | |
663 | -bool MUtils::UpdateChecker::tryContactHost(const QString &hostname, const int &timeoutMsec, quint32 *const ipAddrOut) | |
638 | +bool MUtils::UpdateChecker::tryContactHost(const QString &hostname, const int &timeoutMsec) | |
664 | 639 | { |
665 | 640 | log(QString("Connecting to host: %1").arg(hostname), ""); |
666 | 641 | |
667 | 642 | QProcess process; |
668 | - init_process(process, temp_folder()); | |
669 | - | |
670 | - QStringList args; | |
671 | - args << "--retry" << QString::number(3) << hostname << QString::number(80); | |
643 | + init_process(process, temp_folder(), true, NULL, m_environment.data()); | |
672 | 644 | |
645 | + QStringList args(QLatin1String("-vsSqkI")); | |
646 | + args << "-m" << QString::number(qMax(timeoutMsec, 1000) / 1000); | |
647 | + args << "-U" << USER_AGENT_STR; | |
648 | + args << "-o" << OS::null_device() << QString("http://%1/").arg(hostname); | |
649 | + | |
673 | 650 | QEventLoop loop; |
674 | 651 | connect(&process, SIGNAL(error(QProcess::ProcessError)), &loop, SLOT(quit())); |
675 | 652 | connect(&process, SIGNAL(finished(int, QProcess::ExitStatus)), &loop, SLOT(quit())); |
@@ -678,22 +655,14 @@ bool MUtils::UpdateChecker::tryContactHost(const QString &hostname, const int &t | ||
678 | 655 | QTimer timer; |
679 | 656 | timer.setSingleShot(true); |
680 | 657 | connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); |
681 | - | |
682 | - QScopedPointer<QRegExp> ipAddr; | |
683 | - if (ipAddrOut) | |
684 | - { | |
685 | - *ipAddrOut = 0; | |
686 | - ipAddr.reset(new QRegExp("Connecting\\s+to\\s+(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+):(\\d+)", Qt::CaseInsensitive)); | |
687 | - } | |
688 | 658 | |
689 | - process.start(m_binaryMCat, args); | |
690 | - | |
659 | + process.start(m_binaryCurl, args); | |
691 | 660 | if (!process.waitForStarted()) |
692 | 661 | { |
693 | 662 | return false; |
694 | 663 | } |
695 | 664 | |
696 | - timer.start(timeoutMsec); | |
665 | + timer.start(2 * qMax(timeoutMsec, 1000)); | |
697 | 666 | |
698 | 667 | while (process.state() != QProcess::NotRunning) |
699 | 668 | { |
@@ -702,28 +671,17 @@ bool MUtils::UpdateChecker::tryContactHost(const QString &hostname, const int &t | ||
702 | 671 | while (process.canReadLine()) |
703 | 672 | { |
704 | 673 | const QString line = QString::fromLatin1(process.readLine()).simplified(); |
705 | - if (!ipAddr.isNull()) | |
674 | + if (!line.isEmpty()) | |
706 | 675 | { |
707 | - if (ipAddr->indexIn(line) >= 0) | |
708 | - { | |
709 | - quint32 values[4]; | |
710 | - if (MUtils::regexp_parse_uint32((*ipAddr), values, 4)) | |
711 | - { | |
712 | - *ipAddrOut |= ((values[0] & 0xFF) << 0x18); | |
713 | - *ipAddrOut |= ((values[1] & 0xFF) << 0x10); | |
714 | - *ipAddrOut |= ((values[2] & 0xFF) << 0x08); | |
715 | - *ipAddrOut |= ((values[3] & 0xFF) << 0x00); | |
716 | - } | |
717 | - } | |
676 | + log(line); | |
718 | 677 | } |
719 | - log(line); | |
720 | 678 | } |
721 | 679 | if (bTimeOut || MUTILS_BOOLIFY(m_cancelled)) |
722 | 680 | { |
723 | - qWarning("MCat process timed out <-- killing!"); | |
681 | + qWarning("cURL process timed out <-- killing!"); | |
724 | 682 | process.kill(); |
725 | 683 | process.waitForFinished(); |
726 | - log(bTimeOut ? "!!! TIMEOUT !!!" : "!!! CANCELLED !!!"); | |
684 | + log(bTimeOut ? "PROCESS TIMEOUT !!!" : "CANCELLED BY USER !!!", ""); | |
727 | 685 | return false; |
728 | 686 | } |
729 | 687 | } |
@@ -785,7 +743,11 @@ bool MUtils::UpdateChecker::checkSignature(const QString &file, const QString &s | ||
785 | 743 | loop.exec(); |
786 | 744 | while (process.canReadLine()) |
787 | 745 | { |
788 | - log(QString::fromLatin1(process.readLine()).simplified()); | |
746 | + const QString line = QString::fromLatin1(process.readLine()).simplified(); | |
747 | + if (!line.isEmpty()) | |
748 | + { | |
749 | + log(line); | |
750 | + } | |
789 | 751 | } |
790 | 752 | } |
791 | 753 |