23 #include "ip2cloader.h"
25 #include "configuration/doomseekerconfig.h"
26 #include "doomseekerfilepaths.h"
28 #include "ip2c/ip2c.h"
29 #include "ip2c/ip2cparser.h"
30 #include "ip2c/ip2cupdater.h"
32 #include <QElapsedTimer>
39 class IP2CParserThread :
public QThread
48 IP2CParserThread(QString filePath)
52 virtual void run()
override
55 if (file.open(QIODevice::ReadOnly))
59 this->success = parser.parse(file);
63 gLog << tr(
"IP2C database read in %1 ms; IP ranges: %2").arg(time.elapsed()).arg(parser.ranges().size());
68 gLog << tr(
"Unable to open IP2C file: %1").arg(filePath);
69 this->success =
false;
79 IP2CParserThread *parserThread;
80 QScopedPointer<IP2CUpdater> ip2cUpdater;
81 bool parsingInProgress;
82 bool updateInProgress;
93 d->parserThread =
nullptr;
94 d->parsingInProgress =
false;
95 d->updateInProgress =
false;
96 d->inFallbackMode =
false;
100 this, &IP2CLoader::onUpdateFinished);
101 connect(d->ip2cUpdater.data(), &IP2CUpdater::downloadProgress,
102 this, &IP2CLoader::downloadProgress);
104 this, &IP2CLoader::onUpdateNeeded);
107 void IP2CLoader::load()
109 if (gConfig.doomseeker.bIP2CountryAutoUpdate)
112 if (d->parsingInProgress)
116 if (!filePath.isEmpty())
118 d->inFallbackMode =
false;
119 d->ip2c->setDataAccessLockEnabled(
true);
120 ip2cReadDatabase(filePath);
124 if (!gConfig.doomseeker.bIP2CountryAutoUpdate)
126 gLog << tr(
"Did not find any IP2C database. IP2C functionality will be disabled.");
127 gLog << tr(
"You may install an IP2C database from the \"File\" menu.");
133 void IP2CLoader::onUpdateNeeded(
int status)
135 if (status == IP2CUpdater::UpdateNeeded)
143 case IP2CUpdater::UpToDate:
144 gLog << tr(
"IP2C update not needed.");
146 case IP2CUpdater::UpdateCheckError:
147 gLog << tr(
"IP2C update errored. See log for details.");
150 gLog << tr(
"IP2C update bugged out.");
157 void IP2CLoader::update()
159 d->updateInProgress =
true;
160 if (!d->parsingInProgress)
162 gLog << tr(
"Starting IP2C update.");
163 IP2C::instance()->setDataAccessLockEnabled(
true);
168 void IP2CLoader::onUpdateFinished(
const QByteArray &downloadedData)
170 d->updateInProgress =
false;
171 if (!downloadedData.isEmpty())
173 gLog << tr(
"IP2C database finished downloading.");
175 d->ip2cUpdater->getRollbackData(filePath);
176 if (!d->ip2cUpdater->saveDownloadedData(filePath))
177 gLog << tr(
"Unable to save IP2C database at path: %1").arg(filePath);
178 ip2cReadDatabase(filePath);
182 gLog << tr(
"IP2C download has failed.");
187 void IP2CLoader::onParsingFinished()
189 d->parsingInProgress =
false;
190 auto finally = [
this]() {
191 if (d->updateInProgress) {
193 QTimer::singleShot(0,
this, &IP2CLoader::update);
195 this->ip2cJobsFinished();
198 IP2CParserThread *parserThread = d->parserThread;
199 if (parserThread ==
nullptr) {
200 gLog << tr(
"IP2C unable to retrieve the parsing result.");
204 d->parserThread =
nullptr;
206 if (!parserThread->success)
208 if (d->inFallbackMode)
210 gLog << tr(
"Failed to read the IP2C fallback. Stopping.");
214 gLog << tr(
"Failed to read the IP2C database. Reverting...");
216 d->inFallbackMode =
true;
217 if (d->ip2cUpdater ==
nullptr || !d->ip2cUpdater->hasRollbackData())
219 gLog << tr(
"IP2C revert attempt failed. Nothing to go back to.");
222 QFile file(filePath);
226 if (!preinstalledDbPath.isEmpty())
228 gLog << tr(
"Trying to use the preinstalled IP2C database.");
229 ip2cReadDatabase(preinstalledDbPath);
239 d->ip2cUpdater->rollback(filePath);
242 ip2cReadDatabase(filePath);
247 const IP2CParser &parser = parserThread->parser;
248 gLog << tr(
"IP2C parsing finished.");
249 d->ip2c->setRangesDatabase(parser.ranges());
250 d->ip2c->setLicence(parser.licences());
251 d->ip2c->setUrl(parser.url());
256 void IP2CLoader::ip2cJobsFinished()
258 if (!d->ip2cUpdater->isWorking() && !d->parsingInProgress && !d->updateInProgress)
260 d->ip2c->setDataAccessLockEnabled(
false);
265 void IP2CLoader::ip2cReadDatabase(
const QString &filePath)
267 gLog << tr(
"IP2C database is being read. This may take some time.");
269 if (d->parserThread !=
nullptr) {
270 d->parserThread->disconnect(
this);
273 d->parsingInProgress =
true;
274 d->parserThread =
new IP2CParserThread(filePath);
275 connect(d->parserThread, &IP2CParserThread::finished,
276 this, &IP2CLoader::onParsingFinished);
277 connect(d->parserThread, &IP2CParserThread::finished,
278 d->parserThread, &QObject::deleteLater);
279 d->parserThread->start();
282 #include "ip2cloader.moc"