File indexing completed on 2024-05-05 05:13:00
0001 /* 0002 This file is part of Akregator. 0003 0004 SPDX-FileCopyrightText: 2008 Frank Osterfeld <osterfeld@kde.org> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0 0007 */ 0008 0009 #include "loadfeedlistcommand.h" 0010 0011 #include "feedlist.h" 0012 0013 #include <KLocalizedString> 0014 #include <KMessageBox> 0015 0016 #include <QDateTime> 0017 #include <QDomDocument> 0018 #include <QFile> 0019 #include <QFileInfo> 0020 #include <QPointer> 0021 #include <QRandomGenerator> 0022 #include <QString> 0023 #include <QTimer> 0024 0025 #include <cassert> 0026 0027 using namespace Akregator; 0028 using namespace Akregator::Backend; 0029 0030 class Akregator::LoadFeedListCommandPrivate 0031 { 0032 LoadFeedListCommand *const q; 0033 0034 public: 0035 explicit LoadFeedListCommandPrivate(LoadFeedListCommand *qq) 0036 : q(qq) 0037 { 0038 } 0039 0040 void handleDocument(const QDomDocument &doc); 0041 [[nodiscard]] QString createBackup(const QString &path, bool *ok); 0042 void emitResult(const QSharedPointer<FeedList> &list); 0043 void doLoad(); 0044 0045 QString fileName; 0046 QDomDocument defaultFeedList; 0047 Storage *storage = nullptr; 0048 }; 0049 0050 void LoadFeedListCommandPrivate::emitResult(const QSharedPointer<FeedList> &list) 0051 { 0052 Q_EMIT q->result(list); 0053 q->done(); 0054 } 0055 0056 void LoadFeedListCommandPrivate::handleDocument(const QDomDocument &doc) 0057 { 0058 QSharedPointer<FeedList> feedList(new FeedList(storage)); 0059 if (!feedList->readFromOpml(doc)) { 0060 bool backupCreated; 0061 const QString backupFile = createBackup(fileName, &backupCreated); 0062 const QString msg = backupCreated ? i18n( 0063 "<qt>The standard feed list is corrupted (invalid OPML). " 0064 "A backup was created:<p><b>%1</b></p></qt>", 0065 backupFile) 0066 : i18n( 0067 "<qt>The standard feed list is corrupted (invalid OPML). " 0068 "Could not create a backup.</qt>"); 0069 0070 QPointer<QObject> that(q); 0071 KMessageBox::error(q->parentWidget(), msg, i18nc("@title:window", "OPML Parsing Error")); 0072 if (!that) { 0073 return; 0074 } 0075 feedList.reset(); 0076 } 0077 emitResult(feedList); 0078 } 0079 0080 QString LoadFeedListCommandPrivate::createBackup(const QString &path, bool *ok) 0081 { 0082 const QString backup = path + QLatin1StringView("-backup.") + QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch()); 0083 0084 const bool copied = QFile::copy(path, backup); 0085 if (ok) { 0086 *ok = copied; 0087 } 0088 return backup; 0089 } 0090 0091 LoadFeedListCommand::LoadFeedListCommand(QObject *parent) 0092 : Command(parent) 0093 , d(new LoadFeedListCommandPrivate(this)) 0094 { 0095 } 0096 0097 LoadFeedListCommand::~LoadFeedListCommand() = default; 0098 0099 void LoadFeedListCommand::setFileName(const QString &fileName) 0100 { 0101 d->fileName = fileName; 0102 } 0103 0104 void LoadFeedListCommand::setDefaultFeedList(const QDomDocument &doc) 0105 { 0106 d->defaultFeedList = doc; 0107 } 0108 0109 void LoadFeedListCommand::setStorage(Backend::Storage *s) 0110 { 0111 d->storage = s; 0112 } 0113 0114 void LoadFeedListCommand::doStart() 0115 { 0116 QTimer::singleShot(QRandomGenerator::global()->bounded(400), this, [this]() { 0117 d->doLoad(); 0118 }); 0119 } 0120 0121 void LoadFeedListCommand::doAbort() 0122 { 0123 } 0124 0125 void LoadFeedListCommandPrivate::doLoad() 0126 { 0127 Q_ASSERT(storage); 0128 Q_ASSERT(!fileName.isNull()); 0129 Q_EMIT q->progress(0, i18n("Opening Feed List...")); 0130 0131 QDomDocument doc; 0132 0133 if (!QFileInfo::exists(fileName)) { 0134 handleDocument(defaultFeedList); 0135 return; 0136 } 0137 0138 QFile file(fileName); 0139 0140 if (!file.open(QIODevice::ReadOnly)) { 0141 QPointer<QObject> that(q); 0142 KMessageBox::error(q->parentWidget(), 0143 i18n("<qt>Could not open feed list (%1) for reading.</qt>", file.fileName()), 0144 i18nc("@title:window", "Read Error")); 0145 if (that) { 0146 handleDocument(defaultFeedList); 0147 } 0148 return; 0149 } 0150 0151 const auto result = doc.setContent(&file); 0152 if (!result) { 0153 bool backupCreated = false; 0154 const QString backupFile = createBackup(fileName, &backupCreated); 0155 const QString title = i18nc("error message window caption", "XML Parsing Error"); 0156 const QString details = xi18n( 0157 "<qt><p>XML parsing error in line %1, " 0158 "column %2 of %3:</p><p>%4</p></qt>", 0159 QString::number(result.errorLine), 0160 QString::number(result.errorColumn), 0161 fileName, 0162 result.errorMessage); 0163 const QString msg = backupCreated ? i18n( 0164 "<qt>The standard feed list is corrupted (invalid XML). " 0165 "A backup was created:<p><b>%1</b></p></qt>", 0166 backupFile) 0167 : i18n( 0168 "<qt>The standard feed list is corrupted (invalid XML). " 0169 "Could not create a backup.</qt>"); 0170 0171 QPointer<QObject> that(q); 0172 0173 KMessageBox::detailedError(q->parentWidget(), msg, details, title); 0174 0175 if (that) { 0176 handleDocument(defaultFeedList); 0177 } 0178 return; 0179 } 0180 0181 handleDocument(doc); 0182 } 0183 0184 #include "moc_loadfeedlistcommand.cpp"