This commit is contained in:
Martin Rotter 2015-12-15 07:43:41 +01:00
parent 796bc43dd6
commit 7861641612
20 changed files with 327 additions and 141 deletions

View File

@ -25,6 +25,9 @@ CREATE TABLE IF NOT EXISTS TtRssAccounts (
id INTEGER,
username TEXT NOT NULL,
password TEXT,
auth_protected INTEGER(1) NOT NULL CHECK (auth_protected >= 0 AND auth_protected <= 1) DEFAULT 0,
auth_username TEXT,
auth_password TEXT,
url TEXT NOT NULL,
FOREIGN KEY (id) REFERENCES Accounts (id)

View File

@ -19,6 +19,9 @@ CREATE TABLE IF NOT EXISTS TtRssAccounts (
id INTEGER,
username TEXT NOT NULL,
password TEXT,
auth_protected INTEGER(1) NOT NULL CHECK (auth_protected >= 0 AND auth_protected <= 1) DEFAULT 0,
auth_username TEXT,
auth_password TEXT,
url TEXT NOT NULL,
FOREIGN KEY (id) REFERENCES Accounts (id)

View File

@ -11,6 +11,9 @@ CREATE TABLE TtRssAccounts (
id INTEGER,
username TEXT NOT NULL,
password TEXT,
auth_protected INTEGER(1) NOT NULL CHECK (auth_protected >= 0 AND auth_protected <= 1) DEFAULT 0,
auth_username TEXT,
auth_password TEXT,
url TEXT NOT NULL,
FOREIGN KEY (id) REFERENCES Accounts (id)

View File

@ -11,6 +11,9 @@ CREATE TABLE TtRssAccounts (
id INTEGER,
username TEXT NOT NULL,
password TEXT,
auth_protected INTEGER(1) NOT NULL CHECK (auth_protected >= 0 AND auth_protected <= 1) DEFAULT 0,
auth_username TEXT,
auth_password TEXT,
url TEXT NOT NULL,
FOREIGN KEY (id) REFERENCES Accounts (id)

View File

@ -24,6 +24,7 @@
Fixed:
<ul>
<li>Tiny Tiny RSS plugin now supports HTTP authentication (Basic, NTLM, Digest). (bug #132)
<li>Fixed bug with updating feed. (bug #131)</li>
<li>Solved problem when user selects HUGE number of individual messages and marks them read/unread. Reselecting them after change may cause RSS Guard to hang.</li>
<li>Better info in popup notification when many feeds are updated.</li>

View File

@ -128,6 +128,9 @@ void FeedsView::loadExpandedStates() {
setExpanded(model()->mapFromSource(sourceModel()->indexForItem(item)),
settings->value(GROUP(Categories), setting_name, item->childCount() > 0).toBool());
}
sortByColumn(qApp->settings()->value(GROUP(GUI), SETTING(GUI::DefaultSortColumnFeeds)).toInt(),
static_cast<Qt::SortOrder>(qApp->settings()->value(GROUP(GUI), SETTING(GUI::DefaultSortOrderFeeds)).toInt()));
}
void FeedsView::expandCollapseCurrentItem() {
@ -407,9 +410,6 @@ void FeedsView::setupAppearance() {
setItemDelegate(new StyledItemDelegateWithoutFocus(this));
header()->setStretchLastSection(false);
header()->setSortIndicatorShown(false);
sortByColumn(qApp->settings()->value(GROUP(GUI), SETTING(GUI::DefaultSortColumnFeeds)).toInt(),
static_cast<Qt::SortOrder>(qApp->settings()->value(GROUP(GUI), SETTING(GUI::DefaultSortOrderFeeds)).toInt()));
}
void FeedsView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) {

View File

@ -25,6 +25,7 @@
Downloader::Downloader(QObject *parent)
: QObject(parent), m_activeReply(NULL), m_downloadManager(new SilentNetworkAccessManager(this)),
m_timer(new QTimer(this)), m_customHeaders(QHash<QByteArray, QByteArray>()), m_inputData(QByteArray()),
m_targetProtected(false), m_targetUsername(QString()), m_targetPassword(QString()),
m_lastOutputData(QByteArray()), m_lastOutputError(QNetworkReply::NoError), m_lastContentType(QVariant()) {
m_timer->setInterval(DOWNLOAD_TIMEOUT);
@ -37,17 +38,11 @@ Downloader::~Downloader() {
m_downloadManager->deleteLater();
}
void Downloader::downloadFile(const QString &url, int timeout, bool protected_contents, const QString &username, const QString &password) {
void Downloader::downloadFile(const QString &url, int timeout, bool protected_contents, const QString &username,
const QString &password) {
QNetworkRequest request;
QObject originatingObject;
QString non_const_url = url;
// Set credential information as originating object.
originatingObject.setProperty("protected", protected_contents);
originatingObject.setProperty("username", username);
originatingObject.setProperty("password", password);
request.setOriginatingObject(&originatingObject);
foreach (const QByteArray &header_name, m_customHeaders.keys()) {
request.setRawHeader(header_name, m_customHeaders.value(header_name));
}
@ -63,10 +58,15 @@ void Downloader::downloadFile(const QString &url, int timeout, bool protected_co
request.setUrl(non_const_url);
}
m_targetProtected = protected_contents;
m_targetUsername = username;
m_targetPassword = password;
runGetRequest(request);
}
void Downloader::uploadData(const QString &url, const QByteArray &data, int timeout) {
void Downloader::uploadData(const QString &url, const QByteArray &data, int timeout,
bool protected_contents, const QString &username, const QString &password) {
QNetworkRequest request;
QString non_const_url = url;
@ -87,6 +87,10 @@ void Downloader::uploadData(const QString &url, const QByteArray &data, int time
request.setUrl(non_const_url);
}
m_targetProtected = protected_contents;
m_targetUsername = username;
m_targetPassword = password;
runPostRequest(request, m_inputData);
}
@ -154,6 +158,10 @@ void Downloader::runPostRequest(const QNetworkRequest &request, const QByteArray
m_timer->start();
m_activeReply = m_downloadManager->post(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()));
}
@ -162,6 +170,10 @@ void Downloader::runGetRequest(const QNetworkRequest &request) {
m_timer->start();
m_activeReply = m_downloadManager->get(request);
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()));
}

View File

@ -52,7 +52,8 @@ 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);
void uploadData(const QString &url, const QByteArray &data, int timeout = DOWNLOAD_TIMEOUT,
bool protected_contents = false, const QString &username = QString(), const QString &password = QString());
signals:
// Emitted when new progress is known.
@ -80,6 +81,10 @@ class Downloader : public QObject {
QHash<QByteArray, QByteArray> m_customHeaders;
QByteArray m_inputData;
bool m_targetProtected;
QString m_targetUsername;
QString m_targetPassword;
// Response data.
QByteArray m_lastOutputData;
QNetworkReply::NetworkError m_lastOutputError;

View File

@ -149,7 +149,8 @@ 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) {
const QString &input_content_type, QByteArray &output,
bool protected_contents, const QString &username, const QString &password) {
Downloader downloader;
QEventLoop loop;
NetworkResult result;
@ -159,7 +160,7 @@ NetworkResult NetworkFactory::uploadData(const QString &url, int timeout, const
// 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);
downloader.uploadData(url, input_data, timeout, protected_contents, username, password);
loop.exec();
output = downloader.lastOutputData();
result.first = downloader.lastOutputError();

View File

@ -44,7 +44,9 @@ class NetworkFactory {
static QNetworkReply::NetworkError downloadIcon(const QList<QString> &urls, int timeout, QIcon &output);
static NetworkResult uploadData(const QString &url, int timeout, const QByteArray &input_data,
const QString &input_content_type, QByteArray &output);
const QString &input_content_type, QByteArray &output,
bool protected_contents = false, const QString &username = QString(),
const QString &password = QString());
static NetworkResult downloadFeedFile(const QString &url, int timeout, QByteArray &output,
bool protected_contents = false, const QString &username = QString(),

12
src/network-web/silentnetworkaccessmanager.cpp Normal file → Executable file
View File

@ -44,20 +44,20 @@ SilentNetworkAccessManager *SilentNetworkAccessManager::instance() {
}
void SilentNetworkAccessManager::onAuthenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator) {
QObject *originating_object = reply->request().originatingObject();
QList<QString> keys = authenticator->options().keys();
if (originating_object->property("protected").toBool()) {
if (reply->property("protected").toBool()) {
// This feed contains authentication information, it is good.
authenticator->setUser(originating_object->property("username").toString());
authenticator->setPassword(originating_object->property("password").toString());
authenticator->setUser(reply->property("username").toString());
authenticator->setPassword(reply->property("password").toString());
reply->setProperty("authentication-given", true);
qDebug("Feed '%s' requested authentication and got it.", qPrintable(reply->url().toString()));
qDebug("Item '%s' requested authentication and got it.", qPrintable(reply->url().toString()));
}
else {
reply->setProperty("authentication-given", false);
// Authentication is required but this feed does not contain it.
qWarning("Feed '%s' requested authentication but username/password is not available.", qPrintable(reply->url().toString()));
qWarning("Item '%s' requested authentication but username/password is not available.", qPrintable(reply->url().toString()));
}
}

View File

@ -238,7 +238,7 @@
<string>Some feeds require authentication, including GMail feeds. BASIC, NTLM-2 and DIGEST-MD5 authentication schemes are supported.</string>
</property>
<property name="title">
<string>Requires authentication</string>
<string>Requires HTTP authentication</string>
</property>
<property name="flat">
<bool>false</bool>

View File

@ -22,6 +22,7 @@
#include "services/tt-rss/ttrssserviceroot.h"
#include "services/tt-rss/network/ttrssnetworkfactory.h"
#include "miscellaneous/iconfactory.h"
#include "network-web/networkfactory.h"
FormEditAccount::FormEditAccount(QWidget *parent)
@ -32,6 +33,8 @@ FormEditAccount::FormEditAccount(QWidget *parent)
setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint);
setWindowIcon(qApp->icons()->fromTheme(QSL("application-ttrss")));
m_ui->m_txtHttpUsername->lineEdit()->setPlaceholderText(tr("HTTP authentication username"));
m_ui->m_txtHttpPassword->lineEdit()->setPlaceholderText(tr("HTTP authentication password"));
m_ui->m_txtPassword->lineEdit()->setPlaceholderText(tr("Password for your TT-RSS account"));
m_ui->m_txtUsername->lineEdit()->setPlaceholderText(tr("Username for your TT-RSS account"));
m_ui->m_txtUrl->lineEdit()->setPlaceholderText(tr("FULL URL of your TT-RSS instance WITH trailing \"/api/\" string"));
@ -50,17 +53,25 @@ FormEditAccount::FormEditAccount(QWidget *parent)
connect(m_ui->m_buttonBox, SIGNAL(rejected()), this, SLOT(onClickedCancel()));
connect(m_ui->m_txtPassword->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(onPasswordChanged()));
connect(m_ui->m_txtUsername->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(onUsernameChanged()));
connect(m_ui->m_txtHttpPassword->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(onHttpPasswordChanged()));
connect(m_ui->m_txtHttpUsername->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(onHttpUsernameChanged()));
connect(m_ui->m_txtUrl->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(onUrlChanged()));
connect(m_ui->m_txtPassword->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(checkOkButton()));
connect(m_ui->m_txtUsername->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(checkOkButton()));
connect(m_ui->m_txtUrl->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(checkOkButton()));
connect(m_ui->m_btnTestSetup, SIGNAL(clicked()), this, SLOT(performTest()));
connect(m_ui->m_gbHttpAuthentication, SIGNAL(toggled(bool)), this, SLOT(onHttpPasswordChanged()));
connect(m_ui->m_gbHttpAuthentication, SIGNAL(toggled(bool)), this, SLOT(onHttpUsernameChanged()));
connect(m_ui->m_checkShowHttpPassword, SIGNAL(toggled(bool)), this, SLOT(displayHttpPassword(bool)));
onPasswordChanged();
onUsernameChanged();
onUrlChanged();
onHttpPasswordChanged();
onHttpUsernameChanged();
checkOkButton();
displayPassword(false);
displayHttpPassword(false);
}
FormEditAccount::~FormEditAccount() {
@ -77,6 +88,9 @@ void FormEditAccount::execForEdit(TtRssServiceRoot *existing_root) {
setWindowTitle(tr("Edit existing Tiny Tiny RSS account"));
m_editableRoot = existing_root;
m_ui->m_gbHttpAuthentication->setChecked(existing_root->network()->authIsUsed());
m_ui->m_txtHttpPassword->lineEdit()->setText(existing_root->network()->authPassword());
m_ui->m_txtHttpUsername->lineEdit()->setText(existing_root->network()->authUsername());
m_ui->m_txtUsername->lineEdit()->setText(existing_root->network()->username());
m_ui->m_txtPassword->lineEdit()->setText(existing_root->network()->password());
m_ui->m_txtUrl->lineEdit()->setText(existing_root->network()->url());
@ -88,12 +102,19 @@ void FormEditAccount::displayPassword(bool display) {
m_ui->m_txtPassword->lineEdit()->setEchoMode(display ? QLineEdit::Normal : QLineEdit::Password);
}
void FormEditAccount::displayHttpPassword(bool display) {
m_ui->m_txtHttpPassword->lineEdit()->setEchoMode(display ? QLineEdit::Normal : QLineEdit::Password);
}
void FormEditAccount::performTest() {
TtRssNetworkFactory factory;
factory.setUsername(m_ui->m_txtUsername->lineEdit()->text());
factory.setPassword(m_ui->m_txtPassword->lineEdit()->text());
factory.setUrl(m_ui->m_txtUrl->lineEdit()->text());
factory.setAuthIsUsed(m_ui->m_gbHttpAuthentication->isChecked());
factory.setAuthUsername(m_ui->m_txtHttpUsername->lineEdit()->text());
factory.setAuthPassword(m_ui->m_txtHttpPassword->lineEdit()->text());
TtRssLoginResponse result = factory.login();
@ -132,8 +153,8 @@ void FormEditAccount::performTest() {
}
else {
m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Error,
tr("Network error, have you entered correct Tiny Tiny RSS API endpoint?"),
tr("Network error, have you entered correct Tiny Tiny RSS API endpoint?"));
tr("Network error: '%1'.").arg(NetworkFactory::networkErrorText(factory.lastError())),
tr("Network error, have you entered correct Tiny Tiny RSS API endpoint and password?"));
}
}
@ -150,15 +171,18 @@ void FormEditAccount::onClickedOk() {
m_editableRoot->network()->setUrl(m_ui->m_txtUrl->lineEdit()->text());
m_editableRoot->network()->setUsername(m_ui->m_txtUsername->lineEdit()->text());
m_editableRoot->network()->setPassword(m_ui->m_txtPassword->lineEdit()->text());
m_editableRoot->network()->setAuthIsUsed(m_ui->m_gbHttpAuthentication->isChecked());
m_editableRoot->network()->setAuthUsername(m_ui->m_txtHttpUsername->lineEdit()->text());
m_editableRoot->network()->setAuthPassword(m_ui->m_txtHttpPassword->lineEdit()->text());
m_editableRoot->saveAccountDataToDatabase();
accept();
if (editing_account) {
m_editableRoot->network()->logout();
m_editableRoot->completelyRemoveAllData();
m_editableRoot->syncIn();
}
accept();
}
void FormEditAccount::onClickedCancel() {
@ -187,6 +211,28 @@ void FormEditAccount::onPasswordChanged() {
}
}
void FormEditAccount::onHttpUsernameChanged() {
bool is_username_ok = !m_ui->m_gbHttpAuthentication->isChecked() || !m_ui->m_txtHttpUsername->lineEdit()->text().isEmpty();
m_ui->m_txtHttpUsername->setStatus(is_username_ok ?
LineEditWithStatus::Ok :
LineEditWithStatus::Warning,
is_username_ok ?
tr("Username is ok or it is not needed.") :
tr("Username is empty."));
}
void FormEditAccount::onHttpPasswordChanged() {
bool is_username_ok = !m_ui->m_gbHttpAuthentication->isChecked() || !m_ui->m_txtHttpPassword->lineEdit()->text().isEmpty();
m_ui->m_txtHttpPassword->setStatus(is_username_ok ?
LineEditWithStatus::Ok :
LineEditWithStatus::Warning,
is_username_ok ?
tr("Password is ok or it is not needed.") :
tr("Password is empty."));
}
void FormEditAccount::onUrlChanged() {
QString url = m_ui->m_txtUrl->lineEdit()->text();

View File

@ -42,12 +42,15 @@ class FormEditAccount : public QDialog {
private slots:
void displayPassword(bool display);
void displayHttpPassword(bool display);
void performTest();
void onClickedOk();
void onClickedCancel();
void onUsernameChanged();
void onPasswordChanged();
void onHttpUsernameChanged();
void onHttpPasswordChanged();
void onUrlChanged();
void checkOkButton();

View File

@ -7,106 +7,132 @@
<x>0</x>
<y>0</y>
<width>465</width>
<height>235</height>
<height>304</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QFormLayout" name="formLayout">
<item row="2" column="0">
<widget class="QPushButton" name="m_btnTestSetup">
<property name="text">
<string>&amp;Test setup</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="LabelWithStatus" name="m_lblTestResult" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="m_gbAuthentication">
<property name="toolTip">
<string>Some feeds require authentication, including GMail feeds. BASIC, NTLM-2 and DIGEST-MD5 authentication schemes are supported.</string>
</property>
<property name="title">
<string>Authentication</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Username</string>
</property>
<property name="buddy">
<cstring>m_txtUsername</cstring>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Password</string>
</property>
<property name="buddy">
<cstring>m_txtPassword</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="LineEditWithStatus" name="m_txtPassword" native="true"/>
</item>
<item row="0" column="1">
<widget class="LineEditWithStatus" name="m_txtUsername" native="true"/>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="m_checkShowPassword">
<property name="text">
<string>Show password</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="m_lblTitle">
<property name="text">
<string>URL</string>
</property>
<property name="buddy">
<cstring>m_txtUrl</cstring>
</property>
</widget>
</item>
<item>
<widget class="LineEditWithStatus" name="m_txtUrl" native="true"/>
</item>
</layout>
</item>
</layout>
<layout class="QFormLayout" name="formLayout">
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="m_gbAuthentication">
<property name="toolTip">
<string>Some feeds require authentication, including GMail feeds. BASIC, NTLM-2 and DIGEST-MD5 authentication schemes are supported.</string>
</property>
<property name="title">
<string>Authentication</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Username</string>
</property>
<property name="buddy">
<cstring>m_txtUsername</cstring>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Password</string>
</property>
<property name="buddy">
<cstring>m_txtPassword</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="LineEditWithStatus" name="m_txtPassword" native="true"/>
</item>
<item row="0" column="1">
<widget class="LineEditWithStatus" name="m_txtUsername" native="true"/>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="m_checkShowPassword">
<property name="text">
<string>Show password</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<item row="2" column="0" colspan="2">
<widget class="QGroupBox" name="m_gbHttpAuthentication">
<property name="toolTip">
<string>Some feeds require authentication, including GMail feeds. BASIC, NTLM-2 and DIGEST-MD5 authentication schemes are supported.</string>
</property>
<property name="title">
<string>Requires HTTP authentication</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<layout class="QFormLayout" name="formLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Username</string>
</property>
<property name="buddy">
<cstring>m_txtUsername</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="LineEditWithStatus" name="m_txtHttpUsername" native="true"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Password</string>
</property>
<property name="buddy">
<cstring>m_txtPassword</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="LineEditWithStatus" name="m_txtHttpPassword" native="true"/>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="m_checkShowHttpPassword">
<property name="text">
<string>Show password</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="3" column="1">
<widget class="LabelWithStatus" name="m_lblTestResult" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
</widget>
</item>
<item row="5" column="0" colspan="2">
<widget class="QDialogButtonBox" name="m_buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@ -116,6 +142,30 @@
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="m_lblTitle">
<property name="text">
<string>URL</string>
</property>
<property name="buddy">
<cstring>m_txtUrl</cstring>
</property>
</widget>
</item>
<item>
<widget class="LineEditWithStatus" name="m_txtUrl" native="true"/>
</item>
</layout>
</item>
<item row="3" column="0">
<widget class="QPushButton" name="m_btnTestSetup">
<property name="text">
<string>&amp;Test setup</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
@ -132,9 +182,6 @@
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>m_btnTestSetup</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@ -31,7 +31,8 @@
TtRssNetworkFactory::TtRssNetworkFactory()
: m_url(QString()), m_username(QString()), m_password(QString()), m_sessionId(QString()),
: m_url(QString()), m_username(QString()), m_password(QString()), m_authIsUsed(false),
m_authUsername(QString()), m_authPassword(QString()), m_sessionId(QString()),
m_lastLoginTime(QDateTime()), m_lastError(QNetworkReply::NoError) {
}
@ -81,7 +82,8 @@ TtRssLoginResponse TtRssNetworkFactory::login() {
json["password"] = m_password;
QByteArray result_raw;
NetworkResult network_reply = NetworkFactory::uploadData(m_url, DOWNLOAD_TIMEOUT, QtJson::serialize(json), CONTENT_TYPE, result_raw);
NetworkResult network_reply = NetworkFactory::uploadData(m_url, DOWNLOAD_TIMEOUT, QtJson::serialize(json), CONTENT_TYPE, result_raw,
m_authIsUsed, m_authUsername, m_authPassword);
TtRssLoginResponse login_response(QString::fromUtf8(result_raw));
if (network_reply.first == QNetworkReply::NoError) {
@ -101,7 +103,8 @@ TtRssResponse TtRssNetworkFactory::logout() {
json["sid"] = m_sessionId;
QByteArray result_raw;
NetworkResult network_reply = NetworkFactory::uploadData(m_url, DOWNLOAD_TIMEOUT, QtJson::serialize(json), CONTENT_TYPE, result_raw);
NetworkResult network_reply = NetworkFactory::uploadData(m_url, DOWNLOAD_TIMEOUT, QtJson::serialize(json), CONTENT_TYPE, result_raw,
m_authIsUsed, m_authUsername, m_authPassword);
m_lastError = network_reply.first;
@ -124,7 +127,8 @@ TtRssGetFeedsCategoriesResponse TtRssNetworkFactory::getFeedsCategories() {
json["include_empty"] = false;
QByteArray result_raw;
NetworkResult network_reply = NetworkFactory::uploadData(m_url, DOWNLOAD_TIMEOUT, QtJson::serialize(json), CONTENT_TYPE, result_raw);
NetworkResult network_reply = NetworkFactory::uploadData(m_url, DOWNLOAD_TIMEOUT, QtJson::serialize(json), CONTENT_TYPE, result_raw,
m_authIsUsed, m_authUsername, m_authPassword);
TtRssGetFeedsCategoriesResponse result(QString::fromUtf8(result_raw));
if (result.isNotLoggedIn()) {
@ -132,7 +136,8 @@ TtRssGetFeedsCategoriesResponse TtRssNetworkFactory::getFeedsCategories() {
login();
json["sid"] = m_sessionId;
network_reply = NetworkFactory::uploadData(m_url, DOWNLOAD_TIMEOUT, QtJson::serialize(json), CONTENT_TYPE, result_raw);
network_reply = NetworkFactory::uploadData(m_url, DOWNLOAD_TIMEOUT, QtJson::serialize(json), CONTENT_TYPE, result_raw,
m_authIsUsed, m_authUsername, m_authPassword);
result = TtRssGetFeedsCategoriesResponse(QString::fromUtf8(result_raw));
}
@ -155,7 +160,8 @@ TtRssGetHeadlinesResponse TtRssNetworkFactory::getHeadlines(int feed_id, bool fo
json["sanitize"] = sanitize;
QByteArray result_raw;
NetworkResult network_reply = NetworkFactory::uploadData(m_url, DOWNLOAD_TIMEOUT, QtJson::serialize(json), CONTENT_TYPE, result_raw);
NetworkResult network_reply = NetworkFactory::uploadData(m_url, DOWNLOAD_TIMEOUT, QtJson::serialize(json), CONTENT_TYPE, result_raw,
m_authIsUsed, m_authUsername, m_authPassword);
TtRssGetHeadlinesResponse result(QString::fromUtf8(result_raw));
if (result.isNotLoggedIn()) {
@ -163,7 +169,8 @@ TtRssGetHeadlinesResponse TtRssNetworkFactory::getHeadlines(int feed_id, bool fo
login();
json["sid"] = m_sessionId;
network_reply = NetworkFactory::uploadData(m_url, DOWNLOAD_TIMEOUT, QtJson::serialize(json), CONTENT_TYPE, result_raw);
network_reply = NetworkFactory::uploadData(m_url, DOWNLOAD_TIMEOUT, QtJson::serialize(json), CONTENT_TYPE, result_raw,
m_authIsUsed, m_authUsername, m_authPassword);
result = TtRssGetHeadlinesResponse(QString::fromUtf8(result_raw));
}
@ -182,7 +189,8 @@ TtRssUpdateArticleResponse TtRssNetworkFactory::updateArticles(const QStringList
json["field"] = (int) field;
QByteArray result_raw;
NetworkResult network_reply = NetworkFactory::uploadData(m_url, DOWNLOAD_TIMEOUT, QtJson::serialize(json), CONTENT_TYPE, result_raw);
NetworkResult network_reply = NetworkFactory::uploadData(m_url, DOWNLOAD_TIMEOUT, QtJson::serialize(json), CONTENT_TYPE, result_raw,
m_authIsUsed, m_authUsername, m_authPassword);
TtRssUpdateArticleResponse result(QString::fromUtf8(result_raw));
if (result.isNotLoggedIn()) {
@ -190,13 +198,38 @@ TtRssUpdateArticleResponse TtRssNetworkFactory::updateArticles(const QStringList
login();
json["sid"] = m_sessionId;
network_reply = NetworkFactory::uploadData(m_url, DOWNLOAD_TIMEOUT, QtJson::serialize(json), CONTENT_TYPE, result_raw);
network_reply = NetworkFactory::uploadData(m_url, DOWNLOAD_TIMEOUT, QtJson::serialize(json), CONTENT_TYPE, result_raw,
m_authIsUsed, m_authUsername, m_authPassword);
result = TtRssUpdateArticleResponse(QString::fromUtf8(result_raw));
}
m_lastError = network_reply.first;
return result;
}
bool TtRssNetworkFactory::authIsUsed() const
{
return m_authIsUsed;
}
void TtRssNetworkFactory::setAuthIsUsed(bool auth_is_used) {
m_authIsUsed = auth_is_used;
}
QString TtRssNetworkFactory::authUsername() const {
return m_authUsername;
}
void TtRssNetworkFactory::setAuthUsername(const QString &auth_username) {
m_authUsername = auth_username;
}
QString TtRssNetworkFactory::authPassword() const {
return m_authPassword;
}
void TtRssNetworkFactory::setAuthPassword(const QString &auth_password) {
m_authPassword = auth_password;
}
TtRssResponse::TtRssResponse(const QString &raw_content) {
m_rawContent = QtJson::parse(raw_content).toMap();

View File

@ -111,6 +111,15 @@ class TtRssNetworkFactory {
QString password() const;
void setPassword(const QString &password);
bool authIsUsed() const;
void setAuthIsUsed(bool auth_is_used);
QString authUsername() const;
void setAuthUsername(const QString &auth_username);
QString authPassword() const;
void setAuthPassword(const QString &auth_password);
// Metadata.
QDateTime lastLoginTime() const;
@ -139,6 +148,9 @@ class TtRssNetworkFactory {
QString m_url;
QString m_username;
QString m_password;
bool m_authIsUsed;
QString m_authUsername;
QString m_authPassword;
QString m_sessionId;
QDateTime m_lastLoginTime;
QNetworkReply::NetworkError m_lastError;

View File

@ -96,6 +96,7 @@ int TtRssFeed::update() {
if (serviceRoot()->network()->lastError() != QNetworkReply::NoError) {
setStatus(Feed::Error);
serviceRoot()->itemChanged(QList<RootItem*>() << this);
return 0;
}
else {

View File

@ -20,6 +20,7 @@
#include "definitions/definitions.h"
#include "miscellaneous/application.h"
#include "miscellaneous/iconfactory.h"
#include "miscellaneous/textfactory.h"
#include "gui/dialogs/formmain.h"
#include "services/tt-rss/gui/formeditaccount.h"
#include "services/tt-rss/ttrssserviceroot.h"
@ -79,14 +80,19 @@ QList<ServiceRoot*> TtRssServiceEntryPoint::initializeSubtree() {
QSqlQuery query(database);
QList<ServiceRoot*> roots;
if (query.exec("SELECT id, username, password, url FROM TtRssAccounts;")) {
if (query.exec("SELECT * FROM TtRssAccounts;")) {
while (query.next()) {
TtRssServiceRoot *root = new TtRssServiceRoot();
root->setId(query.value(0).toInt());
root->setAccountId(query.value(0).toInt());
root->network()->setUsername(query.value(1).toString());
root->network()->setPassword(query.value(2).toString());
root->network()->setUrl(query.value(3).toString());
root->network()->setPassword(TextFactory::decrypt(query.value(2).toString()));
root->network()->setAuthIsUsed(query.value(3).toBool());
root->network()->setAuthUsername(query.value(4).toString());
root->network()->setAuthPassword(TextFactory::decrypt(query.value(5).toString()));
root->network()->setUrl(query.value(6).toString());
root->updateTitle();
roots.append(root);
}

View File

@ -19,6 +19,7 @@
#include "miscellaneous/application.h"
#include "miscellaneous/settings.h"
#include "miscellaneous/textfactory.h"
#include "gui/dialogs/formmain.h"
#include "network-web/networkfactory.h"
#include "services/tt-rss/ttrssserviceentrypoint.h"
@ -424,12 +425,16 @@ void TtRssServiceRoot::saveAccountDataToDatabase() {
QSqlQuery query(database);
query.prepare("UPDATE TtRssAccounts "
"SET username = :username, password = :password, url = :url "
"SET username = :username, password = :password, url = :url, auth_protected = :auth_protected, "
"auth_username = :auth_username, auth_password = :auth_password "
"WHERE id = :id;");
query.bindValue(":username", m_network->username());
query.bindValue(":password", m_network->password());
query.bindValue(":url", m_network->url());
query.bindValue(":id", accountId());
query.bindValue(QSL(":username"), m_network->username());
query.bindValue(QSL(":password"), TextFactory::encrypt(m_network->password()));
query.bindValue(QSL(":url"), m_network->url());
query.bindValue(QSL(":auth_protected"), m_network->authIsUsed());
query.bindValue(QSL(":auth_username"), m_network->authUsername());
query.bindValue(QSL(":auth_password"), TextFactory::encrypt(m_network->authPassword()));
query.bindValue(QSL(":id"), accountId());
if (query.exec()) {
updateTitle();