diff --git a/src/networking/urlchecker.cpp b/src/networking/urlchecker.cpp index ea741f83..56fc8ad4 100644 --- a/src/networking/urlchecker.cpp +++ b/src/networking/urlchecker.cpp @@ -1,208 +1,208 @@ /*************************************************************************** * Copyright (C) 2004-2020 by Thomas Fischer * * * * 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. * * * * 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, see . * ***************************************************************************/ #include "urlchecker.h" #include #include #include #include #include #include #include #include "internalnetworkaccessmanager.h" #include "logging_networking.h" class UrlChecker::Private { private: UrlChecker *p; public: QAtomicInteger busyCounter; QSet urlsToCheck; Private(UrlChecker *parent) : p(parent) { /// nothing } void queueMoreOrFinish() { if ( #if QT_VERSION >= 0x050e00 busyCounter.loadRelaxed() <= 0 ///< This function was introduced in Qt 5.14. #else // QT_VERSION < 0x050e00 busyCounter.load() <= 0 #endif // QT_VERSION >= 0x050e00 && urlsToCheck.isEmpty()) { /// In case there are no running checks and the queue of URLs to check is empty, /// wait for a brief moment of time, then fire a 'finished' signal. QTimer::singleShot(100, p, [this]() { if ( #if QT_VERSION >= 0x050e00 busyCounter.loadRelaxed() <= 0 ///< This function was introduced in Qt 5.14. #else // QT_VERSION < 0x050e00 busyCounter.load() <= 0 #endif // QT_VERSION >= 0x050e00 && urlsToCheck.isEmpty()) QMetaObject::invokeMethod(p, "finished", Qt::DirectConnection, QGenericReturnArgument()); else /// It should not happen that when this timer is triggered the original condition is violated qCCritical(LOG_KBIBTEX_NETWORKING) << "This cannot happen:" << #if QT_VERSION >= 0x050e00 busyCounter.loadRelaxed() #else // QT_VERSION < 0x050e00 busyCounter.load() #endif // QT_VERSION >= 0x050e00 << urlsToCheck.count(); }); } else { /// Initiate as many checks as possible while (!urlsToCheck.isEmpty() && #if QT_VERSION >= 0x050e00 busyCounter.loadRelaxed() <= 4 ///< This function was introduced in Qt 5.14. #else // QT_VERSION < 0x050e00 busyCounter.load() <= 4 #endif // QT_VERSION >= 0x050e00 ) checkNextUrl(); } } void checkNextUrl() { /// Immediately return if there are no URLs to check if (urlsToCheck.isEmpty()) return; /// Pop one URL from set of URLS to check auto firstUrlIt = urlsToCheck.begin(); const QUrl url = *firstUrlIt; urlsToCheck.erase(firstUrlIt); QNetworkRequest request(url); request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy); QNetworkReply *reply = InternalNetworkAccessManager::instance().get(request); busyCounter.ref(); QObject::connect(reply, &QNetworkReply::finished, p, [this, reply]() { const QUrl url = reply->url(); if (reply->error() != QNetworkReply::NoError) { /// Instead of an 'emit' ... QMetaObject::invokeMethod(p, "urlChecked", Qt::DirectConnection, QGenericReturnArgument(), Q_ARG(QUrl, url), Q_ARG(UrlChecker::Status, UrlChecker::Status::NetworkError), Q_ARG(QString, reply->errorString())); qCWarning(LOG_KBIBTEX_NETWORKING) << "NetworkError:" << reply->errorString() << url.toDisplayString(); } else { const QByteArray data = reply->read(1024); if (data.isEmpty()) { /// Instead of an 'emit' ... QMetaObject::invokeMethod(p, "urlChecked", Qt::DirectConnection, QGenericReturnArgument(), Q_ARG(QUrl, url), Q_ARG(UrlChecker::Status, UrlChecker::Status::UnknownError), Q_ARG(QString, QStringLiteral("No data received"))); qCWarning(LOG_KBIBTEX_NETWORKING) << "UnknownError: No data received" << url.toDisplayString(); } else { const QString filename = url.fileName().toLower(); const bool filenameSuggestsHTML = filename.isEmpty() || filename.endsWith(QStringLiteral(".html")) || filename.endsWith(QStringLiteral(".htm")); const bool filenameSuggestsPDF = filename.endsWith(QStringLiteral(".pdf")); const bool filenameSuggestsPostScript = filename.endsWith(QStringLiteral(".ps")); const bool containsHTML = data.contains(" element : bibtexFile) { + for (const QSharedPointer &element : bibtexFile) { /// Process only entries, not comments, preambles or macros - QSharedPointer entry = element.dynamicCast(); + const QSharedPointer entry = element.dynamicCast(); if (entry.isNull()) continue; /// Retrieve set of URLs per entry and add to set of URLS to be checked const QSet thisEntryUrls = FileInfo::entryUrls(entry, bibtexFile.property(File::Url).toUrl(), FileInfo::TestExistence::No); for (const QUrl &u : thisEntryUrls) d->urlsToCheck.insert(u); ///< better? } if (d->urlsToCheck.isEmpty()) { /// No URLs identified in bibliography, so nothing to do QTimer::singleShot(100, this, [this]() { emit finished(); }); return; } d->queueMoreOrFinish(); }