mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2026-01-03 14:12:30 -06:00
Don't read unlimited data from files
It now guards against reading infinite files such as `/dev/zero`. And most readings are bound with a (lax) limit. As a side effect, more checking are done when reading a file and overall the reading procedure is more robust. PR #19095.
This commit is contained in:
@@ -28,11 +28,10 @@
|
||||
|
||||
#include "aboutdialog.h"
|
||||
|
||||
#include <QFile>
|
||||
|
||||
#include "base/global.h"
|
||||
#include "base/path.h"
|
||||
#include "base/unicodestrings.h"
|
||||
#include "base/utils/io.h"
|
||||
#include "base/utils/misc.h"
|
||||
#include "base/version.h"
|
||||
#include "ui_aboutdialog.h"
|
||||
@@ -75,27 +74,24 @@ AboutDialog::AboutDialog(QWidget *parent)
|
||||
m_ui->labelMascot->setPixmap(Utils::Gui::scaledPixmap(Path(u":/icons/mascot.png"_qs), this));
|
||||
|
||||
// Thanks
|
||||
QFile thanksfile(u":/thanks.html"_qs);
|
||||
if (thanksfile.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
if (const auto readResult = Utils::IO::readFile(Path(u":/thanks.html"_qs), -1, QIODevice::Text)
|
||||
; readResult)
|
||||
{
|
||||
m_ui->textBrowserThanks->setHtml(QString::fromUtf8(thanksfile.readAll().constData()));
|
||||
thanksfile.close();
|
||||
m_ui->textBrowserThanks->setHtml(QString::fromUtf8(readResult.value()));
|
||||
}
|
||||
|
||||
// Translation
|
||||
QFile translatorsfile(u":/translators.html"_qs);
|
||||
if (translatorsfile.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
if (const auto readResult = Utils::IO::readFile(Path(u":/translators.html"_qs), -1, QIODevice::Text)
|
||||
; readResult)
|
||||
{
|
||||
m_ui->textBrowserTranslation->setHtml(QString::fromUtf8(translatorsfile.readAll().constData()));
|
||||
translatorsfile.close();
|
||||
m_ui->textBrowserTranslation->setHtml(QString::fromUtf8(readResult.value()));
|
||||
}
|
||||
|
||||
// License
|
||||
QFile licensefile(u":/gpl.html"_qs);
|
||||
if (licensefile.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
if (const auto readResult = Utils::IO::readFile(Path(u":/gpl.html"_qs), -1, QIODevice::Text)
|
||||
; readResult)
|
||||
{
|
||||
m_ui->textBrowserLicense->setHtml(QString::fromUtf8(licensefile.readAll().constData()));
|
||||
licensefile.close();
|
||||
m_ui->textBrowserLicense->setHtml(QString::fromUtf8(readResult.value()));
|
||||
}
|
||||
|
||||
// Software Used
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
#include "base/rss/rss_session.h"
|
||||
#include "base/torrentfileguard.h"
|
||||
#include "base/torrentfileswatcher.h"
|
||||
#include "base/utils/io.h"
|
||||
#include "base/utils/misc.h"
|
||||
#include "base/utils/net.h"
|
||||
#include "base/utils/password.h"
|
||||
@@ -1751,46 +1752,22 @@ Path OptionsDialog::getFilter() const
|
||||
#ifndef DISABLE_WEBUI
|
||||
void OptionsDialog::webUIHttpsCertChanged(const Path &path)
|
||||
{
|
||||
const auto isCertFileValid = [&path]() -> bool
|
||||
{
|
||||
if (path.isEmpty())
|
||||
return false;
|
||||
|
||||
QFile file {path.data()};
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
return false;
|
||||
|
||||
if (!Utils::Net::isSSLCertificatesValid(file.read(Utils::Net::MAX_SSL_FILE_SIZE)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
const auto readResult = Utils::IO::readFile(path, Utils::Net::MAX_SSL_FILE_SIZE);
|
||||
const bool isCertValid = Utils::Net::isSSLCertificatesValid(readResult.value_or(QByteArray()));
|
||||
|
||||
m_ui->textWebUIHttpsCert->setSelectedPath(path);
|
||||
m_ui->lblSslCertStatus->setPixmap(UIThemeManager::instance()->getScaledPixmap(
|
||||
(isCertFileValid() ? u"security-high"_qs : u"security-low"_qs), 24));
|
||||
(isCertValid ? u"security-high"_qs : u"security-low"_qs), 24));
|
||||
}
|
||||
|
||||
void OptionsDialog::webUIHttpsKeyChanged(const Path &path)
|
||||
{
|
||||
const auto isKeyFileValid = [&path]() -> bool
|
||||
{
|
||||
if (path.isEmpty())
|
||||
return false;
|
||||
|
||||
QFile file {path.data()};
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
return false;
|
||||
|
||||
if (!Utils::Net::isSSLKeyValid(file.read(Utils::Net::MAX_SSL_FILE_SIZE)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
const auto readResult = Utils::IO::readFile(path, Utils::Net::MAX_SSL_FILE_SIZE);
|
||||
const bool isKeyValid = Utils::Net::isSSLKeyValid(readResult.value_or(QByteArray()));
|
||||
|
||||
m_ui->textWebUIHttpsKey->setSelectedPath(path);
|
||||
m_ui->lblSslKeyStatus->setPixmap(UIThemeManager::instance()->getScaledPixmap(
|
||||
(isKeyFileValid() ? u"security-high"_qs : u"security-low"_qs), 24));
|
||||
(isKeyValid ? u"security-high"_qs : u"security-low"_qs), 24));
|
||||
}
|
||||
|
||||
bool OptionsDialog::isWebUiEnabled() const
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
|
||||
#include <QAction>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QHeaderView>
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
|
||||
@@ -458,15 +458,16 @@ void AutomatedRssDownloader::onImportBtnClicked()
|
||||
const Path path {QFileDialog::getOpenFileName(
|
||||
this, tr("Import RSS rules"), QDir::homePath()
|
||||
, u"%1;;%2"_qs.arg(m_formatFilterJSON, m_formatFilterLegacy), &selectedFilter)};
|
||||
if (!path.exists())
|
||||
return;
|
||||
|
||||
QFile file {path.data()};
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
const int fileMaxSize = 10 * 1024 * 1024;
|
||||
const auto readResult = Utils::IO::readFile(path, fileMaxSize);
|
||||
if (!readResult)
|
||||
{
|
||||
QMessageBox::critical(
|
||||
this, tr("I/O Error")
|
||||
, tr("Failed to open the file. Reason: %1").arg(file.errorString()));
|
||||
if (readResult.error().status == Utils::IO::ReadError::NotExist)
|
||||
return;
|
||||
|
||||
QMessageBox::critical(this, tr("Import error")
|
||||
, tr("Failed to read the file. %1").arg(readResult.error().message));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -479,13 +480,12 @@ void AutomatedRssDownloader::onImportBtnClicked()
|
||||
|
||||
try
|
||||
{
|
||||
RSS::AutoDownloader::instance()->importRules(file.readAll(),format);
|
||||
RSS::AutoDownloader::instance()->importRules(readResult.value(), format);
|
||||
}
|
||||
catch (const RSS::ParsingError &error)
|
||||
{
|
||||
QMessageBox::critical(
|
||||
this, tr("Import Error")
|
||||
, tr("Failed to import the selected rules file. Reason: %1").arg(error.message()));
|
||||
QMessageBox::critical(this, tr("Import error")
|
||||
, tr("Failed to import the selected rules file. Reason: %1").arg(error.message()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
|
||||
#include <QColor>
|
||||
#include <QColorDialog>
|
||||
#include <QFile>
|
||||
#include <QFileDialog>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
@@ -30,30 +30,17 @@
|
||||
|
||||
#include "uithemesource.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "base/global.h"
|
||||
#include "base/logger.h"
|
||||
#include "base/profile.h"
|
||||
#include "base/utils/io.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
QByteArray readFile(const Path &filePath)
|
||||
{
|
||||
QFile file {filePath.data()};
|
||||
if (!file.exists())
|
||||
return {};
|
||||
|
||||
if (file.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
return file.readAll();
|
||||
|
||||
LogMsg(UIThemeSource::tr("UITheme - Failed to open \"%1\". Reason: %2")
|
||||
.arg(filePath.filename(), file.errorString())
|
||||
, Log::WARNING);
|
||||
return {};
|
||||
}
|
||||
const qint64 FILE_MAX_SIZE = 1024 * 1024;
|
||||
|
||||
QJsonObject parseThemeConfig(const QByteArray &data)
|
||||
{
|
||||
@@ -165,7 +152,16 @@ Path DefaultThemeSource::getIconPath(const QString &iconId, const ColorMode colo
|
||||
|
||||
void DefaultThemeSource::loadColors()
|
||||
{
|
||||
const QByteArray configData = readFile(m_userPath / Path(CONFIG_FILE_NAME));
|
||||
const auto readResult = Utils::IO::readFile((m_userPath / Path(CONFIG_FILE_NAME)), FILE_MAX_SIZE, QIODevice::Text);
|
||||
if (!readResult)
|
||||
{
|
||||
if (readResult.error().status != Utils::IO::ReadError::NotExist)
|
||||
LogMsg(tr("Failed to load default theme colors. %1").arg(readResult.error().message), Log::WARNING);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const QByteArray configData = readResult.value();
|
||||
if (configData.isEmpty())
|
||||
return;
|
||||
|
||||
@@ -233,7 +229,16 @@ Path CustomThemeSource::getIconPath(const QString &iconId, const ColorMode color
|
||||
|
||||
QByteArray CustomThemeSource::readStyleSheet()
|
||||
{
|
||||
return readFile(themeRootPath() / Path(STYLESHEET_FILE_NAME));
|
||||
const auto readResult = Utils::IO::readFile((themeRootPath() / Path(STYLESHEET_FILE_NAME)), FILE_MAX_SIZE, QIODevice::Text);
|
||||
if (!readResult)
|
||||
{
|
||||
if (readResult.error().status != Utils::IO::ReadError::NotExist)
|
||||
LogMsg(tr("Failed to load custom theme style sheet. %1").arg(readResult.error().message), Log::WARNING);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
return readResult.value();
|
||||
}
|
||||
|
||||
DefaultThemeSource *CustomThemeSource::defaultThemeSource() const
|
||||
@@ -243,7 +248,16 @@ DefaultThemeSource *CustomThemeSource::defaultThemeSource() const
|
||||
|
||||
void CustomThemeSource::loadColors()
|
||||
{
|
||||
const QByteArray configData = readFile(themeRootPath() / Path(CONFIG_FILE_NAME));
|
||||
const auto readResult = Utils::IO::readFile((themeRootPath() / Path(CONFIG_FILE_NAME)), FILE_MAX_SIZE, QIODevice::Text);
|
||||
if (!readResult)
|
||||
{
|
||||
if (readResult.error().status != Utils::IO::ReadError::NotExist)
|
||||
LogMsg(tr("Failed to load custom theme colors. %1").arg(readResult.error().message), Log::WARNING);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const QByteArray configData = readResult.value();
|
||||
if (configData.isEmpty())
|
||||
return;
|
||||
|
||||
|
||||
@@ -177,10 +177,12 @@ void Utils::Gui::openFolderSelect(const Path &path)
|
||||
QObject::connect(thread, &QThread::finished, thread, &QObject::deleteLater);
|
||||
thread->start();
|
||||
#elif defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||
const int lineMaxLength = 64;
|
||||
|
||||
QProcess proc;
|
||||
proc.start(u"xdg-mime"_qs, {u"query"_qs, u"default"_qs, u"inode/directory"_qs});
|
||||
proc.waitForFinished();
|
||||
const auto output = QString::fromLocal8Bit(proc.readLine().simplified());
|
||||
const auto output = QString::fromLocal8Bit(proc.readLine(lineMaxLength).simplified());
|
||||
if ((output == u"dolphin.desktop") || (output == u"org.kde.dolphin.desktop"))
|
||||
{
|
||||
proc.startDetached(u"dolphin"_qs, {u"--select"_qs, path.toString()});
|
||||
@@ -190,7 +192,7 @@ void Utils::Gui::openFolderSelect(const Path &path)
|
||||
{
|
||||
proc.start(u"nautilus"_qs, {u"--version"_qs});
|
||||
proc.waitForFinished();
|
||||
const auto nautilusVerStr = QString::fromLocal8Bit(proc.readLine()).remove(QRegularExpression(u"[^0-9.]"_qs));
|
||||
const auto nautilusVerStr = QString::fromLocal8Bit(proc.readLine(lineMaxLength)).remove(QRegularExpression(u"[^0-9.]"_qs));
|
||||
using NautilusVersion = Utils::Version<3>;
|
||||
if (NautilusVersion::fromString(nautilusVerStr, {1, 0, 0}) > NautilusVersion(3, 28, 0))
|
||||
proc.startDetached(u"nautilus"_qs, {(Fs::isDir(path) ? path.parentPath() : path).toString()});
|
||||
|
||||
Reference in New Issue
Block a user