23 #include "ip2cupdater.h" 25 #include <QCryptographicHash> 27 #include <QNetworkAccessManager> 28 #include <QTemporaryFile> 34 IP2CUpdater::IP2CUpdater(QObject *parent)
37 pCurrentNetworkReply = NULL;
38 pNetworkAccessManager =
new QNetworkAccessManager();
41 IP2CUpdater::~IP2CUpdater()
45 if (pNetworkAccessManager != NULL)
47 pNetworkAccessManager->deleteLater();
51 void IP2CUpdater::abort()
53 if (pCurrentNetworkReply != NULL)
55 pCurrentNetworkReply->disconnect();
56 pCurrentNetworkReply->abort();
57 pCurrentNetworkReply->deleteLater();
59 pCurrentNetworkReply = NULL;
62 void IP2CUpdater::checksumDownloadFinished()
64 if (handleRedirect(*pCurrentNetworkReply, SLOT(checksumDownloadFinished())))
69 if (pCurrentNetworkReply->error() != QNetworkReply::NoError)
71 gLog << tr(
"IP2C checksum check network error: %1").arg(pCurrentNetworkReply->errorString());
73 emit updateNeeded(UpdateCheckError);
77 QByteArray remoteMd5 = pCurrentNetworkReply->readAll();
78 remoteMd5 = remoteMd5.trimmed();
80 pCurrentNetworkReply->deleteLater();
81 pCurrentNetworkReply = NULL;
84 QFile file(this->lastAsyncCallPath);
85 if (file.open(QIODevice::ReadOnly))
87 localMd5 = QCryptographicHash::hash(file.readAll(), QCryptographicHash::Md5);
88 localMd5 = localMd5.toHex().toLower();
91 gLog << tr(
"Comparing IP2C hashes: local = %1, remote = %2").arg(
92 QString(localMd5)).arg(QString(remoteMd5));
93 bool needed = localMd5 != remoteMd5;
96 gLog << tr(
"IP2C update needed.");
98 emit updateNeeded(needed ? UpdateNeeded : UpToDate);
101 const QUrl IP2CUpdater::dbChecksumUrl()
103 return QUrl(
"https://doomseeker.drdteam.org/ip2c/md5");
106 const QUrl IP2CUpdater::dbDownloadUrl()
108 return QUrl(
"https://doomseeker.drdteam.org/ip2c/geolite2.gz");
111 void IP2CUpdater::downloadDatabase(
const QString &savePath)
113 this->lastAsyncCallPath = savePath;
114 get(dbDownloadUrl(), SLOT(downloadFinished()));
117 void IP2CUpdater::downloadFinished()
119 if (handleRedirect(*pCurrentNetworkReply, SLOT(downloadFinished())))
124 QByteArray data = pCurrentNetworkReply->readAll();
126 pCurrentNetworkReply->deleteLater();
127 pCurrentNetworkReply = NULL;
130 QTemporaryFile tmpFile;
135 QString tmpFilePath = tmpFile.fileName();
137 QByteArray uncompressedData;
138 gzFile gz = gzopen(tmpFilePath.toUtf8().constData(),
"rb");
141 static const int CHUNK_SIZE = 128 * 1024;
142 char chunk[CHUNK_SIZE];
144 while((bytesRead = gzread(gz, chunk, CHUNK_SIZE)) != 0)
146 uncompressedData.append(QByteArray(chunk, bytesRead));
150 retrievedData = uncompressedData;
154 emit databaseDownloadFinished(retrievedData);
157 bool IP2CUpdater::handleRedirect(QNetworkReply &reply,
const char *finishedSlot)
159 QUrl possibleRedirectUrl = reply.attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
160 QUrl url = reply.request().url();
161 if (!possibleRedirectUrl.isEmpty() && possibleRedirectUrl != url)
164 if (possibleRedirectUrl.isRelative())
166 possibleRedirectUrl = url.resolved(possibleRedirectUrl);
168 get(possibleRedirectUrl, finishedSlot);
174 void IP2CUpdater::get(
const QUrl &url,
const char *finishedSlot)
177 retrievedData.clear();
179 QNetworkRequest request;
183 pCurrentNetworkReply = pNetworkAccessManager->get(request);
184 this->connect(pCurrentNetworkReply, SIGNAL(downloadProgress(qint64, qint64)),
185 SIGNAL(downloadProgress(qint64, qint64)));
186 this->connect(pCurrentNetworkReply, SIGNAL(finished()), finishedSlot);
191 rollbackData.clear();
192 QFile file(databasePath);
193 if (file.open(QIODevice::ReadOnly))
195 rollbackData = file.readAll();
202 bool IP2CUpdater::isWorking()
const 204 return pCurrentNetworkReply != NULL;
209 QFile file(filePath);
212 emit updateNeeded(UpdateNeeded);
216 this->lastAsyncCallPath = filePath;
217 gLog << tr(
"Checking if IP2C database at '%1' needs updating.").arg(filePath);
218 get(dbChecksumUrl(), SLOT(checksumDownloadFinished()));
223 bool bSuccess = save(rollbackData, savePath);
224 rollbackData.clear();
229 bool IP2CUpdater::save(
const QByteArray& saveWhat,
const QString &savePath)
231 if (saveWhat.isEmpty())
234 QFile file(savePath);
235 if (file.open(QIODevice::WriteOnly))
237 file.write(saveWhat);
246 return save(retrievedData, savePath);
bool saveDownloadedData(const QString &savePath)
Saves recently downloaded data to the specified file.
static QString userAgent()
WWW User Agent used for HTTP communications.
bool getRollbackData(const QString &databasePath)
Obtains rollback data from specified file.
void needsUpdate(const QString &filePath)
Checks if IP2C file must be updated.
bool rollback(const QString &savePath)
Saves rollback data to the specified file. This data must be first obtained through the getRollbackDa...