File indexing completed on 2024-04-14 15:46:43

0001 /*  This file is part of inqludeclient
0002  *  Copyright 2014  David Faure  <faure@kde.org>
0003  *
0004  *  This library is free software; you can redistribute it and/or modify
0005  *  it under the terms of the GNU Lesser General Public License as published by
0006  *  the Free Software Foundation; either version 2 of the License or ( at
0007  *  your option ) version 3 or, at the discretion of KDE e.V. ( which shall
0008  *  act as a proxy as in section 14 of the GPLv3 ), any later version.
0009  *
0010  *  This library is distributed in the hope that it will be useful,
0011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013  *  Library General Public License for more details.
0014  *
0015  *  You should have received a copy of the GNU Lesser General Public License
0016  *  along with this library; see the file COPYING.LIB.  If not, write to
0017  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018  *  Boston, MA 02110-1301, USA.
0019  */
0020 
0021 #include "downloadhandler.h"
0022 
0023 #include <QCoreApplication>
0024 #include <QUrl>
0025 #include <QFile>
0026 #include <QTextStream>
0027 #include <QJsonArray>
0028 #include <QJsonDocument>
0029 #include <QJsonObject>
0030 #include <QNetworkAccessManager>
0031 #include <QNetworkRequest>
0032 #include <QNetworkReply>
0033 
0034 DownloadHandler::DownloadHandler(QTextStream &errorStream, const QString &library)
0035     : m_errorStream(errorStream), m_library(library), m_reply(Q_NULLPTR), m_destFile(Q_NULLPTR)
0036 {
0037 }
0038 
0039 DownloadHandler::~DownloadHandler()
0040 {
0041     m_errorStream.flush();
0042     delete m_destFile;
0043     delete m_reply;
0044 }
0045 
0046 void DownloadHandler::download(const QJsonDocument &doc)
0047 {
0048     const QJsonArray libs = doc.array();
0049     for (int i = 0; i < libs.count(); ++i) {
0050         const QJsonObject details = libs.at(i).toObject();
0051         const QString name = details.value("name").toString();
0052         if (name == m_library) {
0053             const QJsonObject packages = details.value("packages").toObject();
0054             const QString source = packages.value("source").toString();
0055             if (source.isEmpty()) {
0056                 m_errorStream << "Library " << m_library << " has no source package\n";
0057                 const QJsonObject urls = details.value("urls").toObject();
0058                 const QString vcs = urls.value("vcs").toString();
0059                 if (!vcs.isEmpty()) {
0060                     m_errorStream << "Suggestion: see " << vcs << " for access to the sources\n";
0061                 }
0062                 handlingCompleted();
0063             } else {
0064                 const QUrl sourceUrl(source);
0065                 m_errorStream << "Downloading " << sourceUrl.toDisplayString() << "...\n";
0066                 startDownload(sourceUrl);
0067             }
0068             return;
0069         }
0070     }
0071     m_errorStream << "Library " << m_library << " not found\n";
0072     handlingCompleted();
0073 }
0074 
0075 void DownloadHandler::startDownload(const QUrl &sourceUrl)
0076 {
0077     m_destFile = new QFile(sourceUrl.fileName());
0078     if (!m_destFile->open(QIODevice::WriteOnly)) {
0079         m_errorStream << "Cannot write to " << m_destFile->fileName() << "\n";
0080         handlingCompleted();
0081         return;
0082     }
0083     m_qnam = new QNetworkAccessManager(this);
0084     QNetworkRequest request(sourceUrl);
0085     m_reply = m_qnam->get(request);
0086     connect(m_reply, &QNetworkReply::readyRead, this, &DownloadHandler::slotReadyRead);
0087     connect(m_qnam, &QNetworkAccessManager::finished, this, &DownloadHandler::slotFinished);
0088 }
0089 
0090 void DownloadHandler::slotReadyRead()
0091 {
0092     if (m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute).isNull()) {
0093         m_destFile->write(m_reply->readAll());
0094     }
0095 }
0096 
0097 void DownloadHandler::slotFinished(QNetworkReply* reply)
0098 {
0099     if (reply->error() != QNetworkReply::NoError) {
0100         m_errorStream << reply->errorString() << '\n';
0101     }
0102 
0103     // Handle redirections
0104     const QUrl possibleRedirectUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
0105     if (!possibleRedirectUrl.isEmpty() && possibleRedirectUrl != m_urlRedirect) {
0106         m_urlRedirect = reply->url().resolved(possibleRedirectUrl);
0107         if (m_urlRedirect.scheme().startsWith("http")) {
0108             m_errorStream << "Redirected to " << m_urlRedirect.toDisplayString() << "...\n";
0109             reply->deleteLater();
0110             m_reply = m_qnam->get(QNetworkRequest(m_urlRedirect));
0111             connect(m_reply, &QNetworkReply::readyRead, this, &DownloadHandler::slotReadyRead);
0112             return;
0113         } else {
0114             m_errorStream << "Redirection to" << m_urlRedirect.toDisplayString() << "forbidden.\n";
0115         }
0116     }
0117     m_urlRedirect.clear();
0118     m_destFile->close();
0119     handlingCompleted();
0120 }