After some troubles with weird ownCloud behavior, message operation work partially.

This commit is contained in:
Martin Rotter 2016-02-25 14:01:52 +01:00
parent c44d71b7c9
commit d3c2a1e1e4
15 changed files with 177 additions and 50 deletions

View File

@ -64,8 +64,8 @@ void Downloader::downloadFile(const QString &url, int timeout, bool protected_co
runGetRequest(request);
}
void Downloader::uploadData(const QString &url, const QByteArray &data, int timeout,
bool protected_contents, const QString &username, const QString &password) {
void Downloader::uploadData(const QString &url, const QByteArray &data, QNetworkAccessManager::Operation operation,
int timeout, bool protected_contents, const QString &username, const QString &password) {
QNetworkRequest request;
QString non_const_url = url;
@ -90,7 +90,12 @@ void Downloader::uploadData(const QString &url, const QByteArray &data, int time
m_targetUsername = username;
m_targetPassword = password;
runPostRequest(request, m_inputData);
if (operation == QNetworkAccessManager::PostOperation) {
runPostRequest(request, m_inputData);
}
else {
runPutRequest(request, m_inputData);
}
}
void Downloader::finished() {
@ -123,6 +128,9 @@ void Downloader::finished() {
else if (reply_operation == QNetworkAccessManager::PostOperation) {
runPostRequest(request, m_inputData);
}
else if (reply_operation == QNetworkAccessManager::PutOperation) {
runPutRequest(request, m_inputData);
}
}
else {
// No redirection is indicated. Final file is obtained in our "reply" object.
@ -148,11 +156,23 @@ void Downloader::progressInternal(qint64 bytes_received, qint64 bytes_total) {
void Downloader::timeout() {
if (m_activeReply != NULL) {
// Download action timed-out, too slow connection or target is no reachable.
// Download action timed-out, too slow connection or target is not reachable.
m_activeReply->abort();
}
}
void Downloader::runPutRequest(const QNetworkRequest &request, const QByteArray &data) {
m_timer->start();
m_activeReply = m_downloadManager->put(request, data);
m_activeReply->setProperty("protected", m_targetProtected);
m_activeReply->setProperty("username", m_targetUsername);
m_activeReply->setProperty("password", m_targetPassword);
connect(m_activeReply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(progressInternal(qint64,qint64)));
connect(m_activeReply, SIGNAL(finished()), this, SLOT(finished()));
}
void Downloader::runPostRequest(const QNetworkRequest &request, const QByteArray &data) {
m_timer->start();
m_activeReply = m_downloadManager->post(request, data);

View File

@ -52,8 +52,9 @@ class Downloader : public QObject {
// Performs asynchronous upload of given data as HTTP POST.
// User needs to setup "Content-Encoding" header which
// matches encoding of the data.
void uploadData(const QString &url, const QByteArray &data, int timeout = DOWNLOAD_TIMEOUT,
bool protected_contents = false, const QString &username = QString(), const QString &password = QString());
void uploadData(const QString &url, const QByteArray &data, QNetworkAccessManager::Operation operation,
int timeout = DOWNLOAD_TIMEOUT, bool protected_contents = false,
const QString &username = QString(), const QString &password = QString());
signals:
// Emitted when new progress is known.
@ -71,6 +72,7 @@ class Downloader : public QObject {
void timeout();
private:
void runPutRequest(const QNetworkRequest &request, const QByteArray &data);
void runPostRequest(const QNetworkRequest &request, const QByteArray &data);
void runGetRequest(const QNetworkRequest &request);

View File

@ -150,17 +150,27 @@ QNetworkReply::NetworkError NetworkFactory::downloadIcon(const QList<QString> &u
NetworkResult NetworkFactory::uploadData(const QString &url, int timeout, const QByteArray &input_data,
const QString &input_content_type, QByteArray &output,
bool protected_contents, const QString &username, const QString &password) {
QNetworkAccessManager::Operation operation, bool protected_contents,
const QString &username, const QString &password, bool forcefully_embed_basic_header) {
Downloader downloader;
QEventLoop loop;
NetworkResult result;
downloader.appendRawHeader("Content-Type", input_content_type.toLocal8Bit());
if (forcefully_embed_basic_header) {
QString concatenated = username + ":" + password;
QByteArray data = concatenated.toLocal8Bit().toBase64();
QString headerData = "Basic " + data;
downloader.appendRawHeader("Authorization", headerData.toLocal8Bit());
}
// We need to quit event loop when the download finishes.
QObject::connect(&downloader, SIGNAL(completed(QNetworkReply::NetworkError)), &loop, SLOT(quit()));
downloader.uploadData(url, input_data, timeout, protected_contents, username, password);
downloader.uploadData(url, input_data, operation,
timeout, protected_contents, username, password);
loop.exec();
output = downloader.lastOutputData();
result.first = downloader.lastOutputError();

View File

@ -45,8 +45,9 @@ class NetworkFactory {
static NetworkResult uploadData(const QString &url, int timeout, const QByteArray &input_data,
const QString &input_content_type, QByteArray &output,
QNetworkAccessManager::Operation operation,
bool protected_contents = false, const QString &username = QString(),
const QString &password = QString());
const QString &password = QString(), bool forcefully_embed_basic_header = false);
static NetworkResult downloadFeedFile(const QString &url, int timeout, QByteArray &output,
bool protected_contents = false, const QString &username = QString(),

View File

@ -28,7 +28,7 @@ QPointer<SilentNetworkAccessManager> SilentNetworkAccessManager::s_instance;
SilentNetworkAccessManager::SilentNetworkAccessManager(QObject *parent)
: BaseNetworkAccessManager(parent) {
connect(this, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)),
this, SLOT(onAuthenticationRequired(QNetworkReply*,QAuthenticator*)));
this, SLOT(onAuthenticationRequired(QNetworkReply*,QAuthenticator*)), Qt::DirectConnection);
}
SilentNetworkAccessManager::~SilentNetworkAccessManager() {
@ -43,9 +43,7 @@ SilentNetworkAccessManager *SilentNetworkAccessManager::instance() {
return s_instance;
}
void SilentNetworkAccessManager::onAuthenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator) {
QList<QString> keys = authenticator->options().keys();
void SilentNetworkAccessManager::onAuthenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator) {
if (reply->property("protected").toBool()) {
// This feed contains authentication information, it is good.
authenticator->setUser(reply->property("username").toString());

View File

@ -36,9 +36,9 @@ class SilentNetworkAccessManager : public BaseNetworkAccessManager {
// Returns pointer to global silent network manager
static SilentNetworkAccessManager *instance();
protected slots:
public slots:
// This cannot do any GUI stuff.
void onAuthenticationRequired(QNetworkReply * reply, QAuthenticator *authenticator);
void onAuthenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator);
private:
static QPointer<SilentNetworkAccessManager> s_instance;

View File

@ -299,6 +299,26 @@ QStringList ServiceRoot::textualFeedIds(const QList<Feed*> &feeds) const {
return stringy_ids;
}
QStringList ServiceRoot::customIDsOfMessages(const QList<QPair<Message,RootItem::Importance> > &changes) {
QStringList list;
for (int i = 0; i < changes.size(); i++) {
list.append(changes.at(i).first.m_customId);
}
return list;
}
QStringList ServiceRoot::customIDsOfMessages(const QList<Message> &messages) {
QStringList list;
foreach (const Message &message, messages) {
list.append(message.m_customId);
}
return list;
}
int ServiceRoot::accountId() const {
return m_accountId;
}

View File

@ -176,6 +176,9 @@ class ServiceRoot : public RootItem {
QStringList textualFeedIds(const QList<Feed*> &feeds) const;
QStringList customIDsOfMessages(const QList<QPair<Message,Importance> > &changes);
QStringList customIDsOfMessages(const QList<Message> &messages);
// Takes lists of feeds/categories and assembles them into the tree structure.
void assembleCategories(Assignment categories);
void assembleFeeds(Assignment feeds);

View File

@ -30,7 +30,7 @@
OwnCloudNetworkFactory::OwnCloudNetworkFactory()
: m_url(QString()), m_forceServerSideUpdate(false),
: m_url(QString()), m_fixedUrl(QString()), m_forceServerSideUpdate(false),
m_authUsername(QString()), m_authPassword(QString()), m_urlUser(QString()), m_urlStatus(QString()),
m_urlFolders(QString()), m_urlFeeds(QString()), m_urlMessages(QString()), m_userId(QString()) {
}
@ -44,21 +44,20 @@ QString OwnCloudNetworkFactory::url() const {
void OwnCloudNetworkFactory::setUrl(const QString &url) {
m_url = url;
QString working_url;
if (url.endsWith('/')) {
working_url = url;
m_fixedUrl = url;
}
else {
working_url = url + '/';
m_fixedUrl = url + '/';
}
// Store endpoints.
m_urlUser = working_url + API_PATH + "user";
m_urlStatus = working_url + API_PATH + "status";
m_urlFolders = working_url + API_PATH + "folders";
m_urlFeeds = working_url + API_PATH + "feeds";
m_urlMessages = working_url + API_PATH + "items?id=%1&batchSize=%2&type=%3";
m_urlUser = m_fixedUrl + API_PATH + "user";
m_urlStatus = m_fixedUrl + API_PATH + "status";
m_urlFolders = m_fixedUrl + API_PATH + "folders";
m_urlFeeds = m_fixedUrl + API_PATH + "feeds";
m_urlMessages = m_fixedUrl + API_PATH + "items?id=%1&batchSize=%2&type=%3";
}
bool OwnCloudNetworkFactory::forceServerSideUpdate() const {
@ -182,6 +181,54 @@ OwnCloudGetMessagesResponse OwnCloudNetworkFactory::getMessages(int feed_id) {
return msgs_response;
}
QNetworkReply::NetworkError OwnCloudNetworkFactory::markMessagesRead(RootItem::ReadStatus status,
const QStringList &custom_ids) {
QList<QVariant> var_ids;
QtJson::JsonObject json;
QtJson::JsonArray ids;
QByteArray raw_output;
QString final_url;
if (status == RootItem::Read) {
final_url = m_fixedUrl + API_PATH + "items/read/multiple";
}
else {
final_url = m_fixedUrl + API_PATH + "items/unread/multiple";
}
foreach (const QString &id, custom_ids) {
var_ids.append(id.toInt());
}
ids.append(var_ids);
json["items"] = ids;
NetworkResult network_reply = NetworkFactory::uploadData(final_url,
qApp->settings()->value(GROUP(Feeds),
SETTING(Feeds::UpdateTimeout)).toInt(),
QtJson::serialize(json),
"application/json",
raw_output,
QNetworkAccessManager::PutOperation,
true, m_authUsername, m_authPassword,
true);
if (network_reply.first != QNetworkReply::NoError) {
qWarning("ownCloud: Marking messages as (un)read failed with error %d.", network_reply.first);
}
return (m_lastError = network_reply.first);
}
QNetworkReply::NetworkError OwnCloudNetworkFactory::markMessagesStarred(const QList<int> &custom_ids) {
return QNetworkReply::NoError;
}
QNetworkReply::NetworkError OwnCloudNetworkFactory::markMessagesUnstarred(const QList<int> &custom_ids) {
return QNetworkReply::NoError;
}
QString OwnCloudNetworkFactory::userId() const {
return m_userId;
}

View File

@ -25,6 +25,7 @@
#include "qt-json/json.h"
#include "core/message.h"
#include "services/abstract/rootitem.h"
class OwnCloudResponse {
@ -121,8 +122,13 @@ class OwnCloudNetworkFactory {
// Get messages for given feed.
OwnCloudGetMessagesResponse getMessages(int feed_id);
QNetworkReply::NetworkError markMessagesRead(RootItem::ReadStatus status, const QStringList &custom_ids);
QNetworkReply::NetworkError markMessagesStarred(const QList<int> &custom_ids);
QNetworkReply::NetworkError markMessagesUnstarred(const QList<int> &custom_ids);
private:
QString m_url;
QString m_fixedUrl;
bool m_forceServerSideUpdate;
QString m_authUsername;
QString m_authPassword;
@ -134,7 +140,6 @@ class OwnCloudNetworkFactory {
QString m_urlFolders;
QString m_urlFeeds;
QString m_urlMessages;
QString m_userId;
};

View File

@ -112,6 +112,35 @@ OwnCloudNetworkFactory *OwnCloudServiceRoot::network() const {
return m_network;
}
bool OwnCloudServiceRoot::onBeforeSetMessagesRead(RootItem *selected_item, const QList<Message> &messages,
RootItem::ReadStatus read) {
Q_UNUSED(selected_item)
QNetworkReply::NetworkError reply = network()->markMessagesRead(read, customIDsOfMessages(messages));
return reply == QNetworkReply::NoError;
}
bool OwnCloudServiceRoot::onBeforeSwitchMessageImportance(RootItem *selected_item,
const QList<QPair<Message,RootItem::Importance> > &changes) {
Q_UNUSED(selected_item)
QNetworkReply::NetworkError reply;
/*if (read == RootItem::Read) {
//reply = network()->markMessagesRead();
}
else {
reply = network()->markMessagesUnread();
}*/
if (reply == QNetworkReply::NoError) {
return true;
}
else {
return false;
}
}
void OwnCloudServiceRoot::updateTitle() {
QString host = QUrl(m_network->url()).host();

View File

@ -45,6 +45,9 @@ class OwnCloudServiceRoot : public ServiceRoot {
OwnCloudNetworkFactory *network() const;
bool onBeforeSetMessagesRead(RootItem *selected_item, const QList<Message> &messages, ReadStatus read);
bool onBeforeSwitchMessageImportance(RootItem *selected_item, const QList<QPair<Message,RootItem::Importance> > &changes);
void updateTitle();
void saveAccountDataToDatabase();

View File

@ -86,7 +86,9 @@ TtRssLoginResponse TtRssNetworkFactory::login() {
QByteArray result_raw;
NetworkResult network_reply = NetworkFactory::uploadData(m_url, qApp->settings()->value(GROUP(Feeds),
SETTING(Feeds::UpdateTimeout)).toInt(), QtJson::serialize(json), CONTENT_TYPE, result_raw,
SETTING(Feeds::UpdateTimeout)).toInt(),
QtJson::serialize(json), CONTENT_TYPE, result_raw,
QNetworkAccessManager::PostOperation,
m_authIsUsed, m_authUsername, m_authPassword);
TtRssLoginResponse login_response(QString::fromUtf8(result_raw));
@ -113,6 +115,7 @@ TtRssResponse TtRssNetworkFactory::logout() {
NetworkResult network_reply = NetworkFactory::uploadData(m_url, qApp->settings()->value(GROUP(Feeds),
SETTING(Feeds::UpdateTimeout)).toInt(),
QtJson::serialize(json), CONTENT_TYPE, result_raw,
QNetworkAccessManager::PostOperation,
m_authIsUsed, m_authUsername, m_authPassword);
m_lastError = network_reply.first;
@ -143,6 +146,7 @@ TtRssGetFeedsCategoriesResponse TtRssNetworkFactory::getFeedsCategories() {
const int timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt();
QByteArray result_raw;
NetworkResult network_reply = NetworkFactory::uploadData(m_url, timeout, QtJson::serialize(json), CONTENT_TYPE, result_raw,
QNetworkAccessManager::PostOperation,
m_authIsUsed, m_authUsername, m_authPassword);
TtRssGetFeedsCategoriesResponse result(QString::fromUtf8(result_raw));
@ -152,6 +156,7 @@ TtRssGetFeedsCategoriesResponse TtRssNetworkFactory::getFeedsCategories() {
json["sid"] = m_sessionId;
network_reply = NetworkFactory::uploadData(m_url, timeout, QtJson::serialize(json), CONTENT_TYPE, result_raw,
QNetworkAccessManager::PostOperation,
m_authIsUsed, m_authUsername, m_authPassword);
result = TtRssGetFeedsCategoriesResponse(QString::fromUtf8(result_raw));
}
@ -181,6 +186,7 @@ TtRssGetHeadlinesResponse TtRssNetworkFactory::getHeadlines(int feed_id, int lim
const int timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt();
QByteArray result_raw;
NetworkResult network_reply = NetworkFactory::uploadData(m_url, timeout, QtJson::serialize(json), CONTENT_TYPE, result_raw,
QNetworkAccessManager::PostOperation,
m_authIsUsed, m_authUsername, m_authPassword);
TtRssGetHeadlinesResponse result(QString::fromUtf8(result_raw));
@ -190,6 +196,7 @@ TtRssGetHeadlinesResponse TtRssNetworkFactory::getHeadlines(int feed_id, int lim
json["sid"] = m_sessionId;
network_reply = NetworkFactory::uploadData(m_url, timeout, QtJson::serialize(json), CONTENT_TYPE, result_raw,
QNetworkAccessManager::PostOperation,
m_authIsUsed, m_authUsername, m_authPassword);
result = TtRssGetHeadlinesResponse(QString::fromUtf8(result_raw));
}
@ -215,6 +222,7 @@ TtRssUpdateArticleResponse TtRssNetworkFactory::updateArticles(const QStringList
const int timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt();
QByteArray result_raw;
NetworkResult network_reply = NetworkFactory::uploadData(m_url, timeout, QtJson::serialize(json), CONTENT_TYPE, result_raw,
QNetworkAccessManager::PostOperation,
m_authIsUsed, m_authUsername, m_authPassword);
TtRssUpdateArticleResponse result(QString::fromUtf8(result_raw));
@ -224,6 +232,7 @@ TtRssUpdateArticleResponse TtRssNetworkFactory::updateArticles(const QStringList
json["sid"] = m_sessionId;
network_reply = NetworkFactory::uploadData(m_url, timeout, QtJson::serialize(json), CONTENT_TYPE, result_raw,
QNetworkAccessManager::PostOperation,
m_authIsUsed, m_authUsername, m_authPassword);
result = TtRssUpdateArticleResponse(QString::fromUtf8(result_raw));
}
@ -253,6 +262,7 @@ TtRssSubscribeToFeedResponse TtRssNetworkFactory::subscribeToFeed(const QString
const int timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt();
QByteArray result_raw;
NetworkResult network_reply = NetworkFactory::uploadData(m_url, timeout, QtJson::serialize(json), CONTENT_TYPE, result_raw,
QNetworkAccessManager::PostOperation,
m_authIsUsed, m_authUsername, m_authPassword);
TtRssSubscribeToFeedResponse result(QString::fromUtf8(result_raw));
@ -262,6 +272,7 @@ TtRssSubscribeToFeedResponse TtRssNetworkFactory::subscribeToFeed(const QString
json["sid"] = m_sessionId;
network_reply = NetworkFactory::uploadData(m_url, timeout, QtJson::serialize(json), CONTENT_TYPE, result_raw,
QNetworkAccessManager::PostOperation,
m_authIsUsed, m_authUsername, m_authPassword);
result = TtRssSubscribeToFeedResponse(QString::fromUtf8(result_raw));
}
@ -283,6 +294,7 @@ TtRssUnsubscribeFeedResponse TtRssNetworkFactory::unsubscribeFeed(int feed_id) {
const int timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt();
QByteArray result_raw;
NetworkResult network_reply = NetworkFactory::uploadData(m_url, timeout, QtJson::serialize(json), CONTENT_TYPE, result_raw,
QNetworkAccessManager::PostOperation,
m_authIsUsed, m_authUsername, m_authPassword);
TtRssUnsubscribeFeedResponse result(QString::fromUtf8(result_raw));
@ -292,6 +304,7 @@ TtRssUnsubscribeFeedResponse TtRssNetworkFactory::unsubscribeFeed(int feed_id) {
json["sid"] = m_sessionId;
network_reply = NetworkFactory::uploadData(m_url, timeout, QtJson::serialize(json), CONTENT_TYPE, result_raw,
QNetworkAccessManager::PostOperation,
m_authIsUsed, m_authUsername, m_authPassword);
result = TtRssUnsubscribeFeedResponse(QString::fromUtf8(result_raw));
}

View File

@ -513,23 +513,3 @@ void TtRssServiceRoot::syncIn() {
setIcon(original_icon);
itemChanged(QList<RootItem*>() << this);
}
QStringList TtRssServiceRoot::customIDsOfMessages(const QList<QPair<Message,RootItem::Importance> > &changes) {
QStringList list;
for (int i = 0; i < changes.size(); i++) {
list.append(changes.at(i).first.m_customId);
}
return list;
}
QStringList TtRssServiceRoot::customIDsOfMessages(const QList<Message> &messages) {
QStringList list;
foreach (const Message &message, messages) {
list.append(message.m_customId);
}
return list;
}

View File

@ -59,7 +59,6 @@ class TtRssServiceRoot : public ServiceRoot {
QStringList customIDSOfMessagesForItem(RootItem *item);
bool markFeedsReadUnread(QList<Feed*> items, ReadStatus read);
void saveAccountDataToDatabase();
void updateTitle();
void completelyRemoveAllData();
@ -70,9 +69,6 @@ class TtRssServiceRoot : public ServiceRoot {
void syncIn();
private:
QStringList customIDsOfMessages(const QList<QPair<Message,Importance> > &changes);
QStringList customIDsOfMessages(const QList<Message> &messages);
void loadFromDatabase();
TtRssRecycleBin *m_recycleBin;