diff --git a/src/main.cpp b/src/main.cpp index b6e79d56f..f78478c22 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -100,7 +100,7 @@ int main(int argc, char *argv[]) { main_window.setWindowTitle(APP_LONG_NAME); // Now is a good time to initialize dynamic keyboard shortcuts. - DynamicShortcuts::load(qApp->userActions()); + DynamicShortcuts::load(qApp->userActions()); // Display main window. if (qApp->settings()->value(GROUP(GUI), SETTING(GUI::MainWindowStartsHidden)).toBool() && SystemTrayIcon::isSystemTrayActivated()) { diff --git a/src/network-web/downloader.cpp b/src/network-web/downloader.cpp index 0851c7fa0..1c468a94b 100755 --- a/src/network-web/downloader.cpp +++ b/src/network-web/downloader.cpp @@ -24,8 +24,8 @@ Downloader::Downloader(QObject *parent) : QObject(parent), m_activeReply(NULL), m_downloadManager(new SilentNetworkAccessManager(this)), - m_timer(new QTimer(this)), m_customHeaders(QHash()), m_lastOutputData(QByteArray()), - m_lastOutputError(QNetworkReply::NoError), m_lastContentType(QVariant()) { + m_timer(new QTimer(this)), m_customHeaders(QHash()), m_inputData(QByteArray()), + m_lastOutputData(QByteArray()), m_lastOutputError(QNetworkReply::NoError), m_lastContentType(QVariant()) { m_timer->setInterval(DOWNLOAD_TIMEOUT); m_timer->setSingleShot(true); @@ -66,8 +66,33 @@ void Downloader::downloadFile(const QString &url, int timeout, bool protected_co runGetRequest(request); } +void Downloader::uploadData(const QString &url, const QByteArray &data, int timeout) { + QNetworkRequest request; + QString non_const_url = url; + + foreach (const QByteArray &header_name, m_customHeaders.keys()) { + request.setRawHeader(header_name, m_customHeaders.value(header_name)); + } + + m_inputData = data; + + // Set url for this request and fire it up. + m_timer->setInterval(timeout); + + if (non_const_url.startsWith(URI_SCHEME_FEED)) { + qDebug("Replacing URI schemes for '%s'.", qPrintable(non_const_url)); + request.setUrl(non_const_url.replace(QRegExp(QString('^') + URI_SCHEME_FEED), QString(URI_SCHEME_HTTP))); + } + else { + request.setUrl(non_const_url); + } + + runPostRequest(request, m_inputData); +} + void Downloader::finished() { QNetworkReply *reply = qobject_cast(sender()); + QNetworkAccessManager::Operation reply_operation = reply->operation(); m_timer->stop(); @@ -89,7 +114,12 @@ void Downloader::finished() { m_activeReply->deleteLater(); m_activeReply = NULL; - runGetRequest(request); + if (reply_operation == QNetworkAccessManager::GetOperation) { + runGetRequest(request); + } + else if (reply_operation == QNetworkAccessManager::PostOperation) { + runPostRequest(request, m_inputData); + } } else { // No redirection is indicated. Final file is obtained in our "reply" object. @@ -120,6 +150,14 @@ void Downloader::timeout() { } } +void Downloader::runPostRequest(const QNetworkRequest &request, const QByteArray &data) { + m_timer->start(); + m_activeReply = m_downloadManager->post(request, data); + + connect(m_activeReply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(progressInternal(qint64,qint64))); + connect(m_activeReply, SIGNAL(finished()), this, SLOT(finished())); +} + void Downloader::runGetRequest(const QNetworkRequest &request) { m_timer->start(); m_activeReply = m_downloadManager->get(request); diff --git a/src/network-web/downloader.h b/src/network-web/downloader.h index 8cbdf0366..621657b64 100755 --- a/src/network-web/downloader.h +++ b/src/network-web/downloader.h @@ -49,6 +49,11 @@ class Downloader : public QObject { void downloadFile(const QString &url, int timeout = DOWNLOAD_TIMEOUT, bool protected_contents = false, const QString &username = QString(), const QString &password = QString()); + // 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); + signals: // Emitted when new progress is known. void progress(qint64 bytes_received, qint64 bytes_total); @@ -65,6 +70,7 @@ class Downloader : public QObject { void timeout(); private: + void runPostRequest(const QNetworkRequest &request, const QByteArray &data); void runGetRequest(const QNetworkRequest &request); private: @@ -72,6 +78,7 @@ class Downloader : public QObject { SilentNetworkAccessManager *m_downloadManager; QTimer *m_timer; QHash m_customHeaders; + QByteArray m_inputData; // Response data. QByteArray m_lastOutputData; diff --git a/src/network-web/networkfactory.cpp b/src/network-web/networkfactory.cpp index 4acac8bf8..d98512f8b 100755 --- a/src/network-web/networkfactory.cpp +++ b/src/network-web/networkfactory.cpp @@ -148,6 +148,26 @@ QNetworkReply::NetworkError NetworkFactory::downloadIcon(const QList &u return network_result; } +NetworkResult NetworkFactory::uploadData(const QString &url, int timeout, const QByteArray &input_data, + const QString &input_content_type, QByteArray &output) { + Downloader downloader; + QEventLoop loop; + NetworkResult result; + + downloader.appendRawHeader("Content-Type", input_content_type.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); + loop.exec(); + output = downloader.lastOutputData(); + result.first = downloader.lastOutputError(); + result.second = downloader.lastContentType(); + + return result; +} + NetworkResult NetworkFactory::downloadFeedFile(const QString &url, int timeout, QByteArray &output, bool protected_contents, const QString &username, const QString &password) { diff --git a/src/network-web/networkfactory.h b/src/network-web/networkfactory.h old mode 100644 new mode 100755 index 8d11e2a08..08aa13c17 --- a/src/network-web/networkfactory.h +++ b/src/network-web/networkfactory.h @@ -43,6 +43,9 @@ class NetworkFactory { // given URL belongs to. static QNetworkReply::NetworkError downloadIcon(const QList &urls, int timeout, QIcon &output); + static NetworkResult uploadData(const QString &url, int timeout, const QByteArray &input_data, + const QString &input_content_type, QByteArray &output); + static NetworkResult downloadFeedFile(const QString &url, int timeout, QByteArray &output, bool protected_contents = false, const QString &username = QString(), const QString &password = QString()); diff --git a/src/services/tt-rss/definitions.h b/src/services/tt-rss/definitions.h new file mode 100755 index 000000000..e26ce4ff7 --- /dev/null +++ b/src/services/tt-rss/definitions.h @@ -0,0 +1,36 @@ +#ifndef DEFINITIONS_H +#define DEFINITIONS_H + +// Error when user needs to login before making an operation. +#define NOT_LOGGED_IN "NOT_LOGGED_IN" + +// General return status codes. +#define API_STATUS_OK 0 +#define API_STATUS_ERR 1 +#define STATUS_OK "OK" + +// Login. +#define API_DISABLED "API_DISABLED" // API is not enabled. +#define LOGIN_ERROR "LOGIN_ERROR" // Incorrect password/username. + +// Logout. +#define LOGOUT_OK "OK" + + +/* //login + * QtJson::JsonObject obj; + obj["op"] = "login"; + obj["user"] = "admin"; + obj["password"] = "Zy69tKWF"; + + QByteArray arr; + NetworkResult res = NetworkFactory::uploadData("http://rss.rotterovi.eu/api/", + 15000, + QtJson::serialize(obj), + "application/json; charset=utf-8", + arr); + + obj = QtJson::parse(QString::fromUtf8(arr)).toMap();*/ + +#endif // DEFINITIONS_H +