From 1d323dd7b4202781b14fb04c3474d4c21b4a15e8 Mon Sep 17 00:00:00 2001
From: Akira Ohgaki <akiraohgaki@gmail.com>
Date: Wed, 23 Nov 2016 16:02:54 +0900
Subject: [PATCH] Update qtlibs

---
 src/libs/qtlibs/networkresource.cpp | 123 +++++++++++++----
 src/libs/qtlibs/networkresource.h   |  25 +++-
 src/libs/qtlibs/ocsapi.cpp          | 199 ++++++++++++++++++++++++++++
 src/libs/qtlibs/ocsapi.h            |  60 +++++++++
 src/libs/qtlibs/qtlibs.pri          |   2 +
 5 files changed, 376 insertions(+), 33 deletions(-)
 create mode 100644 src/libs/qtlibs/ocsapi.cpp
 create mode 100644 src/libs/qtlibs/ocsapi.h

diff --git a/src/libs/qtlibs/networkresource.cpp b/src/libs/qtlibs/networkresource.cpp
index 1745a1c..9452d2c 100644
--- a/src/libs/qtlibs/networkresource.cpp
+++ b/src/libs/qtlibs/networkresource.cpp
@@ -17,8 +17,8 @@
 
 namespace qtlibs {
 
-NetworkResource::NetworkResource(const QString &name, const QUrl &url, bool async, QObject *parent)
-    : QObject(parent), name_(name), url_(url), async_(async)
+NetworkResource::NetworkResource(const QString &id, const QUrl &url, bool async, QObject *parent)
+    : QObject(parent), id_(id), url_(url), async_(async)
 {
     setManager(new QNetworkAccessManager(this));
 }
@@ -31,7 +31,7 @@ NetworkResource::~NetworkResource()
 NetworkResource::NetworkResource(const NetworkResource &other, QObject *parent)
     : QObject(parent)
 {
-    setName(other.name());
+    setId(other.id());
     setUrl(other.url());
     setAsync(other.async());
     setRequest(other.request());
@@ -40,21 +40,21 @@ NetworkResource::NetworkResource(const NetworkResource &other, QObject *parent)
 
 NetworkResource &NetworkResource::operator =(const NetworkResource &other)
 {
-    setName(other.name());
+    setId(other.id());
     setUrl(other.url());
     setAsync(other.async());
     setRequest(other.request());
     return *this;
 }
 
-QString NetworkResource::name() const
+QString NetworkResource::id() const
 {
-    return name_;
+    return id_;
 }
 
-void NetworkResource::setName(const QString &name)
+void NetworkResource::setId(const QString &id)
 {
-    name_ = name;
+    id_ = id;
 }
 
 QUrl NetworkResource::url() const
@@ -102,20 +102,64 @@ QString NetworkResource::method() const
     return method_;
 }
 
+QString NetworkResource::contentType() const
+{
+    return contentType_;
+}
+
+QByteArray NetworkResource::contentData() const
+{
+    return contentData_;
+}
+
 NetworkResource *NetworkResource::head()
 {
     setMethod("HEAD");
-    QNetworkRequest networkRequest = request();
-    networkRequest.setUrl(url());
-    return send(async(), networkRequest);
+    return send(url(), async());
 }
 
 NetworkResource *NetworkResource::get()
 {
     setMethod("GET");
-    QNetworkRequest networkRequest = request();
-    networkRequest.setUrl(url());
-    return send(async(), networkRequest);
+    return send(url(), async());
+}
+
+NetworkResource *NetworkResource::post(const QByteArray &contentData, const QString &contentType)
+{
+    setMethod("POST");
+    setContentType(contentType);
+    setContentData(contentData);
+    return send(url(), async());
+}
+
+NetworkResource *NetworkResource::post(const QUrlQuery &contentData)
+{
+    setMethod("POST");
+    setContentType("application/x-www-form-urlencoded");
+    setContentData(contentData.toString(QUrl::FullyEncoded).toUtf8());
+    return send(url(), async());
+}
+
+NetworkResource *NetworkResource::put(const QByteArray &contentData, const QString &contentType)
+{
+    setMethod("PUT");
+    setContentType(contentType);
+    setContentData(contentData);
+    return send(url(), async());
+}
+
+NetworkResource *NetworkResource::put(const QUrlQuery &contentData)
+{
+    setMethod("PUT");
+    setContentType("application/x-www-form-urlencoded");
+    setContentData(contentData.toString(QUrl::FullyEncoded).toUtf8());
+    return send(url(), async());
+}
+
+NetworkResource *NetworkResource::deleteResource()
+{
+    setMethod("DELETE");
+    return send(url(), async());
 }
 
 bool NetworkResource::isFinishedWithNoError()
@@ -155,21 +199,19 @@ void NetworkResource::replyFinished()
     if (isFinishedWithNoError()) {
         // Check if redirection
         // Note: An auto redirection option is available since Qt 5.6
-        QString newUrl;
+        QUrl redirectUrl;
         if (reply()->hasRawHeader("Location")) {
-            newUrl = QString(reply()->rawHeader("Location"));
+            redirectUrl.setUrl(QString(reply()->rawHeader("Location")));
         }
         else if (reply()->hasRawHeader("Refresh")) {
-            newUrl = QString(reply()->rawHeader("Refresh")).split("url=").last();
+            redirectUrl.setUrl(QString(reply()->rawHeader("Refresh")).split("url=").last());
         }
-        if (!newUrl.isEmpty()) {
-            if (newUrl.startsWith("/")) {
-                newUrl = reply()->url().authority() + newUrl;
+        if (!redirectUrl.isEmpty()) {
+            if (redirectUrl.isRelative()) {
+                redirectUrl = reply()->url().resolved(redirectUrl);
             }
-            QNetworkRequest networkRequest = request();
-            networkRequest.setUrl(QUrl(newUrl));
             reply()->deleteLater();
-            send(true, networkRequest);
+            send(redirectUrl, true);
             return;
         }
     }
@@ -191,16 +233,43 @@ void NetworkResource::setMethod(const QString &method)
     method_ = method;
 }
 
-NetworkResource *NetworkResource::send(bool async, const QNetworkRequest &request)
+void NetworkResource::setContentType(const QString &contentType)
+{
+    contentType_ = contentType;
+}
+
+void NetworkResource::setContentData(const QByteArray &contentData)
 {
+    contentData_ = contentData;
+}
+
+NetworkResource *NetworkResource::send(const QUrl &url, bool async)
+{
+    QNetworkRequest networkRequest = request();
+    networkRequest.setUrl(url);
     if (method() == "HEAD") {
-        setReply(manager()->head(request));
+        setReply(manager()->head(networkRequest));
     }
     else if (method() == "GET") {
-        setReply(manager()->get(request));
-        connect(reply(), &QNetworkReply::downloadProgress, this, &NetworkResource::downloadProgress);
+        setReply(manager()->get(networkRequest));
+    }
+    else if (method() == "POST") {
+        networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(contentType()));
+        setReply(manager()->post(networkRequest, contentData()));
+    }
+    else if (method() == "PUT") {
+        networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(contentType()));
+        setReply(manager()->put(networkRequest, contentData()));
+    }
+    else if (method() == "DELETE") {
+        setReply(manager()->deleteResource(networkRequest));
+    }
+    else {
+        Q_ASSERT(false);
     }
     connect(reply(), &QNetworkReply::finished, this, &NetworkResource::replyFinished);
+    connect(reply(), &QNetworkReply::downloadProgress, this, &NetworkResource::downloadProgress);
+    connect(reply(), &QNetworkReply::uploadProgress, this, &NetworkResource::uploadProgress);
     if (!async) {
         QEventLoop eventLoop;
         connect(this, &NetworkResource::finished, &eventLoop, &QEventLoop::quit);
diff --git a/src/libs/qtlibs/networkresource.h b/src/libs/qtlibs/networkresource.h
index 0a95190..4d9e041 100644
--- a/src/libs/qtlibs/networkresource.h
+++ b/src/libs/qtlibs/networkresource.h
@@ -13,6 +13,7 @@
 
 #include <QObject>
 #include <QUrl>
+#include <QUrlQuery>
 #include <QNetworkRequest>
 #include <QNetworkAccessManager>
 #include <QNetworkReply>
@@ -24,14 +25,14 @@ class NetworkResource : public QObject
     Q_OBJECT
 
 public:
-    explicit NetworkResource(const QString &name = "", const QUrl &url = QUrl(), bool async = true, QObject *parent = 0);
+    explicit NetworkResource(const QString &id = "", const QUrl &url = QUrl(), bool async = true, QObject *parent = 0);
     ~NetworkResource();
 
     NetworkResource(const NetworkResource &other, QObject *parent = 0);
     NetworkResource &operator =(const NetworkResource &other);
 
-    QString name() const;
-    void setName(const QString &name);
+    QString id() const;
+    void setId(const QString &id);
     QUrl url() const;
     void setUrl(const QUrl &url);
     bool async() const;
@@ -41,16 +42,24 @@ public:
     QNetworkAccessManager *manager() const;
     QNetworkReply *reply() const;
     QString method() const;
+    QString contentType() const;
+    QByteArray contentData() const;
 
     NetworkResource *head();
     NetworkResource *get();
+    NetworkResource *post(const QByteArray &contentData, const QString &contentType);
+    NetworkResource *post(const QUrlQuery &contentData);
+    NetworkResource *put(const QByteArray &contentData, const QString &contentType);
+    NetworkResource *put(const QUrlQuery &contentData);
+    NetworkResource *deleteResource();
     bool isFinishedWithNoError();
     QByteArray readData();
     bool saveData(const QString &path);
 
 signals:
     void finished(NetworkResource *resource);
-    void downloadProgress(const qint64 &bytesReceived, const qint64 &bytesTotal);
+    void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
+    void uploadProgress(qint64 bytesSent, qint64 bytesTotal);
 
 public slots:
     void abort();
@@ -62,16 +71,20 @@ private:
     void setManager(QNetworkAccessManager *manager);
     void setReply(QNetworkReply *reply);
     void setMethod(const QString &method);
+    void setContentType(const QString &contentType);
+    void setContentData(const QByteArray &contentData);
 
-    NetworkResource *send(bool async, const QNetworkRequest &request);
+    NetworkResource *send(const QUrl &url, bool async);
 
-    QString name_;
+    QString id_;
     QUrl url_;
     bool async_;
     QNetworkRequest request_;
     QNetworkAccessManager *manager_;
     QNetworkReply *reply_;
     QString method_;
+    QString contentType_;
+    QByteArray contentData_;
 };
 
 } // namespace qtlibs
diff --git a/src/libs/qtlibs/ocsapi.cpp b/src/libs/qtlibs/ocsapi.cpp
new file mode 100644
index 0000000..389c2bf
--- /dev/null
+++ b/src/libs/qtlibs/ocsapi.cpp
@@ -0,0 +1,199 @@
+/**
+ * A library for Qt app
+ *
+ * LICENSE: The GNU Lesser General Public License, version 3.0
+ *
+ * @author      Akira Ohgaki <akiraohgaki@gmail.com>
+ * @copyright   Akira Ohgaki
+ * @license     https://opensource.org/licenses/LGPL-3.0  The GNU Lesser General Public License, version 3.0
+ * @link        https://github.com/akiraohgaki/qtlibs
+ */
+
+#include "ocsapi.h"
+
+#include <QXmlStreamReader>
+
+#include "json.h"
+#include "networkresource.h"
+
+namespace qtlibs {
+
+// OCS-API Specification
+// https://www.freedesktop.org/wiki/Specifications/open-collaboration-services/
+
+OcsApi::OcsApi(const QString &id, const QUrl &baseUrl, const QString &userName, const QString &password, QObject *parent)
+    : QObject(parent), id_(id), baseUrl_(baseUrl), userName_(userName), password_(password)
+{}
+
+OcsApi::OcsApi(const OcsApi &other, QObject *parent)
+    : QObject(parent)
+{
+    setId(other.id());
+    setBaseUrl(other.baseUrl());
+    setUserName(other.userName());
+    setPassword(other.password());
+}
+
+OcsApi &OcsApi::operator =(const OcsApi &other)
+{
+    setId(other.id());
+    setBaseUrl(other.baseUrl());
+    setUserName(other.userName());
+    setPassword(other.password());
+    return *this;
+}
+
+QString OcsApi::id() const
+{
+    return id_;
+}
+
+void OcsApi::setId(const QString &id)
+{
+    id_ = id;
+}
+
+QUrl OcsApi::baseUrl() const
+{
+    return baseUrl_;
+}
+
+void OcsApi::setBaseUrl(const QUrl &baseUrl)
+{
+    baseUrl_ = baseUrl;
+}
+
+QString OcsApi::userName() const
+{
+    return userName_;
+}
+
+void OcsApi::setUserName(const QString &userName)
+{
+    userName_ = userName;
+}
+
+QString OcsApi::password() const
+{
+    return password_;
+}
+
+void OcsApi::setPassword(const QString &password)
+{
+    password_ = password;
+}
+
+QJsonObject OcsApi::getConfig()
+{
+    QUrl url = baseUrl().resolved(QUrl("config"));
+    url.setQuery("format=json");
+    qtlibs::NetworkResource resource(url.toString(), url, false);
+    return qtlibs::Json(resource.get()->readData()).toObject();
+}
+
+QJsonObject OcsApi::checkPerson()
+{
+    QUrl url = baseUrl().resolved(QUrl("person/check"));
+    QUrlQuery formData;
+    formData.addQueryItem("login", userName());
+    formData.addQueryItem("password", password());
+    formData.addQueryItem("format", "json");
+    qtlibs::NetworkResource resource(url.toString(), url, false);
+    return qtlibs::Json(resource.post(formData)->readData()).toObject();
+}
+
+QJsonObject OcsApi::getPersonDataSet(const QUrlQuery &query)
+{
+    QUrl url = baseUrl().resolved(QUrl("person/data"));
+    url.setUserName(userName());
+    url.setPassword(password());
+    QUrlQuery newQuery(query);
+    newQuery.removeQueryItem("format");
+    newQuery.addQueryItem("format", "json");
+    url.setQuery(newQuery);
+    qtlibs::NetworkResource resource(url.toString(), url, false);
+    return qtlibs::Json(resource.get()->readData()).toObject();
+}
+
+QJsonObject OcsApi::getPersonData(const QString &personId)
+{
+    QUrl url = baseUrl().resolved(QUrl("person/data/" + personId));
+    url.setUserName(userName());
+    url.setPassword(password());
+    url.setQuery("format=json");
+    qtlibs::NetworkResource resource(url.toString(), url, false);
+    return qtlibs::Json(resource.get()->readData()).toObject();
+}
+
+QJsonObject OcsApi::getPersonSelf()
+{
+    QUrl url = baseUrl().resolved(QUrl("person/self"));
+    url.setUserName(userName());
+    url.setPassword(password());
+    url.setQuery("format=json");
+    qtlibs::NetworkResource resource(url.toString(), url, false);
+    return qtlibs::Json(resource.get()->readData()).toObject();
+}
+
+QJsonObject OcsApi::getContentCategories()
+{
+    QUrl url = baseUrl().resolved(QUrl("content/categories"));
+    url.setQuery("format=json");
+    qtlibs::NetworkResource resource(url.toString(), url, false);
+    return qtlibs::Json(resource.get()->readData()).toObject();
+}
+
+QJsonObject OcsApi::getContentDataSet(const QUrlQuery &query)
+{
+    QUrl url = baseUrl().resolved(QUrl("content/data"));
+    QUrlQuery newQuery(query);
+    newQuery.removeQueryItem("format");
+    newQuery.addQueryItem("format", "json");
+    url.setQuery(newQuery);
+    qtlibs::NetworkResource resource(url.toString(), url, false);
+    return qtlibs::Json(resource.get()->readData()).toObject();
+}
+
+QJsonObject OcsApi::getContentData(const QString &contentId)
+{
+    QUrl url = baseUrl().resolved(QUrl("content/data/" + contentId));
+    url.setQuery("format=json");
+    qtlibs::NetworkResource resource(url.toString(), url, false);
+    return qtlibs::Json(resource.get()->readData()).toObject();
+}
+
+QJsonObject OcsApi::getContentDownload(const QString &contentId, const QString &itemId)
+{
+    QUrl url = baseUrl().resolved(QUrl("content/download/" + contentId + "/" + itemId));
+    url.setQuery("format=json");
+    qtlibs::NetworkResource resource(url.toString(), url, false);
+    return qtlibs::Json(resource.get()->readData()).toObject();
+}
+
+QJsonArray OcsApi::getProviderFile(const QUrl &url)
+{
+    QJsonArray providers;
+    qtlibs::NetworkResource resource(url.toString(), url, false);
+    QXmlStreamReader reader(resource.get()->readData());
+    QStringList whitelist;
+    whitelist << "id" << "location" << "name" << "icon" << "termsofuse" << "register";
+    while (!reader.atEnd() && !reader.hasError()) {
+        reader.readNext();
+        if (reader.isStartElement() && reader.name() == "provider") {
+            QJsonObject provider;
+            provider["_providerfile"] = url.toString();
+            providers.append(provider);
+            continue;
+        }
+        QString elementName = reader.name().toString();
+        if (!providers.isEmpty() && whitelist.contains(elementName)) {
+            int i(providers.size() - 1);
+            QJsonObject provider = providers[i].toObject();
+            provider[elementName] = reader.readElementText();
+            providers[i] = provider;
+        }
+    }
+    return providers;
+}
+
+} // namespace qtlibs
diff --git a/src/libs/qtlibs/ocsapi.h b/src/libs/qtlibs/ocsapi.h
new file mode 100644
index 0000000..3e43748
--- /dev/null
+++ b/src/libs/qtlibs/ocsapi.h
@@ -0,0 +1,60 @@
+/**
+ * A library for Qt app
+ *
+ * LICENSE: The GNU Lesser General Public License, version 3.0
+ *
+ * @author      Akira Ohgaki <akiraohgaki@gmail.com>
+ * @copyright   Akira Ohgaki
+ * @license     https://opensource.org/licenses/LGPL-3.0  The GNU Lesser General Public License, version 3.0
+ * @link        https://github.com/akiraohgaki/qtlibs
+ */
+
+#pragma once
+
+#include <QObject>
+#include <QUrl>
+#include <QUrlQuery>
+#include <QJsonObject>
+#include <QJsonArray>
+
+namespace qtlibs {
+
+class OcsApi : public QObject
+{
+    Q_OBJECT
+
+public:
+    explicit OcsApi(const QString &id = "", const QUrl &baseUrl = QUrl(), const QString &userName = "", const QString &password = "", QObject *parent = 0);
+
+    OcsApi(const OcsApi &other, QObject *parent = 0);
+    OcsApi &operator =(const OcsApi &other);
+
+    QString id() const;
+    void setId(const QString &id);
+    QUrl baseUrl() const;
+    void setBaseUrl(const QUrl &baseUrl);
+    QString userName() const;
+    void setUserName(const QString &userName);
+    QString password() const;
+    void setPassword(const QString &password);
+
+    QJsonObject getConfig();
+    QJsonObject checkPerson();
+    QJsonObject getPersonDataSet(const QUrlQuery &query = QUrlQuery());
+    QJsonObject getPersonData(const QString &personId);
+    QJsonObject getPersonSelf();
+    QJsonObject getContentCategories();
+    QJsonObject getContentDataSet(const QUrlQuery &query = QUrlQuery());
+    QJsonObject getContentData(const QString &contentId);
+    QJsonObject getContentDownload(const QString &contentId, const QString &itemId);
+
+    static QJsonArray getProviderFile(const QUrl &url);
+
+private:
+    QString id_;
+    QUrl baseUrl_;
+    QString userName_;
+    QString password_;
+};
+
+} // namespace qtlibs
diff --git a/src/libs/qtlibs/qtlibs.pri b/src/libs/qtlibs/qtlibs.pri
index 1050283..09fce3e 100644
--- a/src/libs/qtlibs/qtlibs.pri
+++ b/src/libs/qtlibs/qtlibs.pri
@@ -8,6 +8,7 @@ HEADERS += \
     $${PWD}/json.h \
     $${PWD}/config.h \
     $${PWD}/networkresource.h \
+    $${PWD}/ocsapi.h \
     $${PWD}/package.h
 
 SOURCES += \
@@ -16,6 +17,7 @@ SOURCES += \
     $${PWD}/json.cpp \
     $${PWD}/config.cpp \
     $${PWD}/networkresource.cpp \
+    $${PWD}/ocsapi.cpp \
     $${PWD}/package.cpp
 
 unix:!ios:!android {
-- 
GitLab