diff --git a/resources/desktop/rssguard.appdata.xml b/resources/desktop/com.github.rssguard.appdata.xml
similarity index 100%
rename from resources/desktop/rssguard.appdata.xml
rename to resources/desktop/com.github.rssguard.appdata.xml
diff --git a/resources/desktop/rssguard.desktop b/resources/desktop/com.github.rssguard.desktop
similarity index 100%
rename from resources/desktop/rssguard.desktop
rename to resources/desktop/com.github.rssguard.desktop
diff --git a/resources/rssguard.qrc b/resources/rssguard.qrc
index 559a134ee..e48655830 100755
--- a/resources/rssguard.qrc
+++ b/resources/rssguard.qrc
@@ -1534,7 +1534,7 @@
localizations/rssguard_pt.qm
localizations/rssguard_sv.qm
localizations/rssguard_zh.qm
- desktop/rssguard.desktop
+ desktop/com.github.rssguard.desktop
desktop/rssguard.desktop.autostart
localizations/qt_bg.qm
localizations/qt_ca.qm
diff --git a/rssguard.pro b/rssguard.pro
index 514c329a1..043d3165d 100755
--- a/rssguard.pro
+++ b/rssguard.pro
@@ -66,6 +66,7 @@ lessThan(QT_MAJOR_VERSION, 5)|lessThan(QT_MINOR_VERSION, 8) {
APP_NAME = "RSS Guard"
APP_LOW_NAME = "rssguard"
+APP_REVERSE_NAME = "com.github.rssguard"
APP_LOW_H_NAME = ".rssguard"
APP_AUTHOR = "Martin Rotter"
APP_COPYRIGHT = "(C) 2011-2017 $$APP_AUTHOR"
@@ -682,10 +683,10 @@ win32 {
unix:!mac:!android {
target.path = $$PREFIX/bin
- desktop_file.files = resources/desktop/$${TARGET}.desktop
+ desktop_file.files = resources/desktop/$${APP_REVERSE_NAME}.desktop
desktop_file.path = $$quote($$PREFIX/share/applications/)
- appdata.files = resources/desktop/$${TARGET}.appdata.xml
+ appdata.files = resources/desktop/$${APP_REVERSE_NAME}.appdata.xml
appdata.path = $$quote($$PREFIX/share/metainfo/)
desktop_icon.files = resources/graphics/$${TARGET}.png
diff --git a/src/definitions/definitions.h b/src/definitions/definitions.h
index 5233eaa77..b74a87752 100755
--- a/src/definitions/definitions.h
+++ b/src/definitions/definitions.h
@@ -228,7 +228,7 @@
#if defined(Q_OS_LINUX)
#define APP_DESKTOP_SOURCE_ENTRY_FILE "rssguard.desktop.autostart"
-#define APP_DESKTOP_ENTRY_FILE "rssguard.desktop"
+#define APP_DESKTOP_ENTRY_FILE "com.github.rssguard.desktop"
#define APP_DESKTOP_ENTRY_PATH QSL(":/desktop")
#endif
diff --git a/src/network-web/downloader.cpp b/src/network-web/downloader.cpp
index 2a4d36d58..3d4809475 100755
--- a/src/network-web/downloader.cpp
+++ b/src/network-web/downloader.cpp
@@ -5,13 +5,15 @@
#include "network-web/silentnetworkaccessmanager.h"
#include
+#include
#include
Downloader::Downloader(QObject* parent)
: QObject(parent), m_activeReply(nullptr), m_downloadManager(new SilentNetworkAccessManager(this)),
m_timer(new QTimer(this)), m_customHeaders(QHash()), m_inputData(QByteArray()),
m_inputMultipartData(nullptr), m_targetProtected(false), m_targetUsername(QString()), m_targetPassword(QString()),
- m_lastOutputData(QByteArray()), m_lastOutputError(QNetworkReply::NoError), m_lastContentType(QVariant()) {
+ m_lastOutputData(QByteArray()), m_lastOutputMultipartData(QList()), m_lastOutputError(QNetworkReply::NoError),
+ m_lastContentType(QVariant()) {
m_timer->setInterval(DOWNLOAD_TIMEOUT);
m_timer->setSingleShot(true);
connect(m_timer, &QTimer::timeout, this, &Downloader::cancel);
@@ -124,7 +126,12 @@ void Downloader::finished() {
runGetRequest(request);
}
else if (reply_operation == QNetworkAccessManager::PostOperation) {
- runPostRequest(request, m_inputData);
+ if (m_inputMultipartData == nullptr) {
+ runPostRequest(request, m_inputData);
+ }
+ else {
+ runPostRequest(request, m_inputMultipartData);
+ }
}
else if (reply_operation == QNetworkAccessManager::PutOperation) {
runPutRequest(request, m_inputData);
@@ -136,8 +143,15 @@ void Downloader::finished() {
else {
// No redirection is indicated. Final file is obtained in our "reply" object.
// Read the data into output buffer.
- m_lastOutputData = reply->readAll();
+ if (m_inputMultipartData == nullptr) {
+ m_lastOutputData = reply->readAll();
+ }
+ else {
+ m_lastOutputMultipartData = decodeMultipartAnswer(reply);
+ }
+
m_lastContentType = reply->header(QNetworkRequest::ContentTypeHeader);
+
m_lastOutputError = reply->error();
m_activeReply->deleteLater();
m_activeReply = nullptr;
@@ -158,6 +172,25 @@ void Downloader::progressInternal(qint64 bytes_received, qint64 bytes_total) {
emit progress(bytes_received, bytes_total);
}
+QList Downloader::decodeMultipartAnswer(QNetworkReply* reply) {
+ QByteArray data = reply->readAll();
+
+ if (data.isEmpty()) {
+ return QList();
+ }
+
+ QString content_type = reply->header(QNetworkRequest::KnownHeaders::ContentTypeHeader).toString();
+ QString boundary = content_type.mid(content_type.indexOf(QL1S("boundary=")) + 9);
+ QRegularExpression regex(QL1S("--") + boundary + QL1S("(--)?(\\r\\n)?"));
+ QStringList list = QString::fromUtf8(data).split(regex, QString::SplitBehavior::SkipEmptyParts);
+
+ QList parts;
+
+ parts.reserve(list.size());
+
+ return parts;
+}
+
void Downloader::runDeleteRequest(const QNetworkRequest& request) {
m_timer->start();
m_activeReply = m_downloadManager->deleteResource(request);
@@ -229,6 +262,10 @@ QNetworkReply::NetworkError Downloader::lastOutputError() const {
return m_lastOutputError;
}
+QList Downloader::lastOutputMultipartData() const {
+ return m_lastOutputMultipartData;
+}
+
QByteArray Downloader::lastOutputData() const {
return m_lastOutputData;
}
diff --git a/src/network-web/downloader.h b/src/network-web/downloader.h
index 8c0749b09..35556953e 100755
--- a/src/network-web/downloader.h
+++ b/src/network-web/downloader.h
@@ -12,6 +12,7 @@
class SilentNetworkAccessManager;
class QTimer;
+class QHttpPart;
class Downloader : public QObject {
Q_OBJECT
@@ -25,6 +26,7 @@ class Downloader : public QObject {
// Access to last received full output data/error/content-type.
QByteArray lastOutputData() const;
QNetworkReply::NetworkError lastOutputError() const;
+ QList lastOutputMultipartData() const;
QVariant lastContentType() const;
public slots:
@@ -65,6 +67,7 @@ class Downloader : public QObject {
void progressInternal(qint64 bytes_received, qint64 bytes_total);
private:
+ QList decodeMultipartAnswer(QNetworkReply* reply);
void manipulateData(const QString& url, QNetworkAccessManager::Operation operation,
const QByteArray& data, QHttpMultiPart* multipart_data,
int timeout = DOWNLOAD_TIMEOUT, bool protected_contents = false,
@@ -91,6 +94,8 @@ class Downloader : public QObject {
// Response data.
QByteArray m_lastOutputData;
+ QList m_lastOutputMultipartData;
+
QNetworkReply::NetworkError m_lastOutputError;
QVariant m_lastContentType;
};
diff --git a/src/network-web/networkfactory.cpp b/src/network-web/networkfactory.cpp
index b693712e0..06810dab8 100755
--- a/src/network-web/networkfactory.cpp
+++ b/src/network-web/networkfactory.cpp
@@ -204,3 +204,34 @@ NetworkResult NetworkFactory::performNetworkOperation(const QString& url, int ti
result.second = downloader.lastContentType();
return result;
}
+
+NetworkResult NetworkFactory::performNetworkOperation(const QString& url,
+ int timeout,
+ QHttpMultiPart* input_data,
+ QList& output,
+ QNetworkAccessManager::Operation operation,
+ QList> additional_headers,
+ bool protected_contents,
+ const QString& username,
+ const QString& password) {
+ Downloader downloader;
+ QEventLoop loop;
+ NetworkResult result;
+
+ // We need to quit event loop when the download finishes.
+ QObject::connect(&downloader, &Downloader::completed, &loop, &QEventLoop::quit);
+
+ foreach (const auto& header, additional_headers) {
+ if (!header.first.isEmpty()) {
+ downloader.appendRawHeader(header.first, header.second);
+ }
+ }
+
+ downloader.manipulateData(url, operation, input_data, timeout, protected_contents, username, password);
+ loop.exec();
+
+ output = downloader.lastOutputMultipartData();
+ result.first = downloader.lastOutputError();
+ result.second = downloader.lastContentType();
+ return result;
+}
diff --git a/src/network-web/networkfactory.h b/src/network-web/networkfactory.h
index 822738689..a97a6602b 100755
--- a/src/network-web/networkfactory.h
+++ b/src/network-web/networkfactory.h
@@ -4,6 +4,7 @@
#define NETWORKFACTORY_H
#include
+#include
#include
#include
#include
@@ -39,7 +40,8 @@ class NetworkFactory {
bool protected_contents = false,
const QString& username = QString(),
const QString& password = QString());
- static NetworkResult performNetworkOperation(const QString& url, int timeout, const QByteArray& input_data,
+ static NetworkResult performNetworkOperation(const QString& url, int timeout,
+ const QByteArray& input_data,
QByteArray& output,
QNetworkAccessManager::Operation operation,
QList& output,
+ QNetworkAccessManager::Operation operation,
+ QList> additional_headers = QList>(),
+ bool protected_contents = false,
+ const QString& username = QString(),
+ const QString& password = QString());
};
#endif // NETWORKFACTORY_H
diff --git a/src/services/gmail/network/gmailnetworkfactory.cpp b/src/services/gmail/network/gmailnetworkfactory.cpp
index 02f940183..76fcd6cf8 100755
--- a/src/services/gmail/network/gmailnetworkfactory.cpp
+++ b/src/services/gmail/network/gmailnetworkfactory.cpp
@@ -334,6 +334,8 @@ bool GmailNetworkFactory::obtainAndDecodeFullMessages(const QList& lite
multi->setContentType(QHttpMultiPart::ContentType::MixedType);
+ QHash msgs;
+
foreach (const Message& msg, lite_messages) {
QHttpPart part;
@@ -342,27 +344,34 @@ bool GmailNetworkFactory::obtainAndDecodeFullMessages(const QList& lite
part.setBody(full_msg_endpoint.toUtf8());
multi->append(part);
+ msgs.insert(msg.m_customId, msg);
}
- QEventLoop loop;
- QNetworkRequest req;
QString bearer = m_oauth2->bearer();
- req.setRawHeader(QString(HTTP_HEADERS_AUTHORIZATION).toLocal8Bit(), bearer.toLocal8Bit());
- req.setUrl(QUrl(GMAIL_API_BATCH));
- auto* repl = SilentNetworkAccessManager::instance()->post(req, multi);
+ if (bearer.isEmpty()) {
+ return false;
+ }
- connect(repl, &QNetworkReply::finished, &loop, &QEventLoop::quit);
- loop.exec();
+ QList> headers;
+ QList output;
+ int timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt();
- auto resp = repl->readAll();
- auto aa = repl->error();
+ headers.append(QPair(QString(HTTP_HEADERS_AUTHORIZATION).toLocal8Bit(),
+ bearer.toLocal8Bit()));
- multi->deleteLater();
- repl->deleteLater();
- IOFactory::writeTextFile("b.html", resp);
+ if (NetworkFactory::performNetworkOperation(GMAIL_API_BATCH,
+ timeout,
+ multi,
+ output,
+ QNetworkAccessManager::Operation::PostOperation,
+ headers).first == QNetworkReply::NetworkError::NoError) {
+ // We parse each part of HTTP response (it contains HTTP headers and payload with msg full data).
- return false;
+ }
+ else {
+ return false;
+ }
}
QList GmailNetworkFactory::decodeLiteMessages(const QString& messages_json_data, const QString& stream_id,