[gnome-notes/wip-nextcloud-api: 3/3] Nextcloud API support




commit 22694d4919516cc8b1d1b1e2a024ea3e3ade2a8b
Author: Isaque Galdino <igaldino gmail com>
Date:   Thu Jan 14 19:48:51 2021 -0300

    Nextcloud API support

 build-aux/flatpak/org.gnome.Notes.json         |   11 +
 meson.build                                    |    3 +
 src/libbiji/biji-manager.c                     |    4 +-
 src/libbiji/meson.build                        |    4 +-
 src/libbiji/provider/biji-nextcloud-note.c     |  335 ++++++++
 src/libbiji/provider/biji-nextcloud-note.h     |   39 +
 src/libbiji/provider/biji-nextcloud-provider.c |  395 +++++++++
 src/libbiji/provider/biji-nextcloud-provider.h |   41 +
 src/libbiji/provider/biji-own-cloud-note.c     |  442 ----------
 src/libbiji/provider/biji-own-cloud-note.h     |   34 -
 src/libbiji/provider/biji-own-cloud-provider.c | 1018 ------------------------
 src/libbiji/provider/biji-own-cloud-provider.h |   38 -
 12 files changed, 828 insertions(+), 1536 deletions(-)
---
diff --git a/build-aux/flatpak/org.gnome.Notes.json b/build-aux/flatpak/org.gnome.Notes.json
index 22f20a7..231a247 100644
--- a/build-aux/flatpak/org.gnome.Notes.json
+++ b/build-aux/flatpak/org.gnome.Notes.json
@@ -46,6 +46,17 @@
         "*.a"
     ],
     "modules" : [
+        {
+            "name" : "curl",
+            "builddir" : true,
+            "buildsystem" : "cmake",
+            "sources" : [
+                {
+                    "type" : "git",
+                    "url" : "https://github.com/curl/curl.git";
+                }
+            ]
+        },
         {
             "name" : "libhandy",
             "buildsystem" : "meson",
diff --git a/meson.build b/meson.build
index cb265c4..582a382 100644
--- a/meson.build
+++ b/meson.build
@@ -119,10 +119,13 @@ bijiben_deps = [
   dependency('glib-2.0', version: '>= 2.53.4'),
   dependency('goa-1.0'),
   dependency('gtk+-3.0', version: '>= 3.19.3'),
+  dependency('json-glib-1.0'),
   dependency('libecal-2.0', version: '>= 3.33.2'),
   dependency('libedataserver-1.2', version: '>= 3.13.90'),
   dependency('libhandy-0.0', version: '>= 0.0.10'),
   dependency('libxml-2.0'),
+  dependency('libcurl'),
+  dependency('uuid'),
   dependency('webkit2gtk-4.0', version: '>= 2.26'),
   cc.find_library('m')
 ]
diff --git a/src/libbiji/biji-manager.c b/src/libbiji/biji-manager.c
index 4e2034d..b821ce7 100644
--- a/src/libbiji/biji-manager.c
+++ b/src/libbiji/biji-manager.c
@@ -24,7 +24,7 @@
 #include "provider/biji-import-provider.h"
 #include "provider/biji-local-provider.h"
 #include "provider/biji-memo-provider.h"
-#include "provider/biji-own-cloud-provider.h"
+#include "provider/biji-nextcloud-provider.h"
 
 
 struct _BijiManager
@@ -175,7 +175,7 @@ load_goa_client (BijiManager *self,
       if (g_strcmp0 (type, "owncloud") == 0)
       {
         g_message ("Loading account %s", goa_account_get_id (account));
-        provider = biji_own_cloud_provider_new (self, object);
+        provider = biji_nextcloud_provider_new (self, object);
         _add_provider (self, provider);
         g_object_unref (provider);
       }
diff --git a/src/libbiji/meson.build b/src/libbiji/meson.build
index f6e2d24..b778eed 100644
--- a/src/libbiji/meson.build
+++ b/src/libbiji/meson.build
@@ -8,8 +8,8 @@ sources = files(
   'provider/biji-local-provider.c',
   'provider/biji-memo-note.c',
   'provider/biji-memo-provider.c',
-  'provider/biji-own-cloud-note.c',
-  'provider/biji-own-cloud-provider.c',
+  'provider/biji-nextcloud-note.c',
+  'provider/biji-nextcloud-provider.c',
   'provider/biji-provider.c',
   'serializer/biji-lazy-serializer.c',
   'biji-date-time.c',
diff --git a/src/libbiji/provider/biji-nextcloud-note.c b/src/libbiji/provider/biji-nextcloud-note.c
new file mode 100644
index 0000000..7735203
--- /dev/null
+++ b/src/libbiji/provider/biji-nextcloud-note.c
@@ -0,0 +1,335 @@
+/* biji-nextcloud-note.c
+ *
+ * Copyright 2020 Isaque Galdino <igaldino gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include <curl/curl.h>
+#include <json-glib/json-glib.h>
+
+#include "biji-nextcloud-note.h"
+#include "biji-nextcloud-provider.h"
+#include "biji-tracker.h"
+
+struct _BijiNextcloudNote
+{
+  BijiNoteObj            parent_instance;
+  BijiNextcloudProvider *provider;
+  gint64                 id;
+
+  /* BijiNoteObj::path contains the URL for the note in the server, but when
+   * creating a new note, we don't have that yet, so we fulfill it with a
+   * temporary fake URL.
+   * We do that because BijiNoteObj::path is used as a key for BijiManager and
+   * BijiController notes lists.
+   * Once we save the note for the first time, we receive the new URL from the
+   * server. If we replace BijiNoteObj::path property with that new URL, we'll
+   * have to deal with changing BijiManager and BijiController notes lists keys.
+   * Instead of doing so, it's easier to just use a new property for further
+   * server interactions.
+   */
+  char                  *new_url;
+};
+
+G_DEFINE_TYPE (BijiNextcloudNote, biji_nextcloud_note, BIJI_TYPE_NOTE_OBJ)
+
+static gboolean
+item_no (BijiItem *item)
+{
+  return FALSE;
+}
+
+static gboolean
+note_no (BijiNoteObj *note)
+{
+  return FALSE;
+}
+
+static const char *
+get_place (BijiItem *item)
+{
+  BijiNextcloudNote *self = BIJI_NEXTCLOUD_NOTE (item);
+  const BijiProviderInfo *info = biji_provider_get_info (BIJI_PROVIDER (self->provider));
+
+  return info->name;
+}
+
+static char *
+get_basename (BijiNoteObj *note)
+{
+  BijiItem *item = BIJI_ITEM (note);
+  return (char *) biji_item_get_uuid (item);
+}
+
+static char *
+get_html (BijiNoteObj *note)
+{
+  return html_from_plain_text (biji_note_obj_get_raw_text (note));
+}
+
+static void
+set_html (BijiNoteObj *note,
+          const char  *html)
+{
+}
+
+static void
+save_note_finish (GObject      *source_object,
+                  GAsyncResult *res,
+                  gpointer      user_data)
+{
+  BijiItem *item = BIJI_ITEM (source_object);
+  BijiNoteObj *note = BIJI_NOTE_OBJ (source_object);
+  BijiNextcloudNote *self = BIJI_NEXTCLOUD_NOTE (source_object);
+  const BijiProviderInfo *prov_info = biji_provider_get_info (BIJI_PROVIDER (self->provider));
+  BijiInfoSet *info = biji_info_set_new ();
+
+  info->url = (char *) biji_note_obj_get_path (note);
+  info->title = (char *) biji_note_obj_get_title (note);
+  info->content = (char *) biji_note_obj_get_raw_text (note);
+  info->mtime = biji_item_get_mtime (item);
+  info->created = biji_note_obj_get_create_date (note);
+  info->datasource_urn = g_strdup (prov_info->datasource);
+
+  biji_tracker_ensure_resource_from_info (biji_item_get_manager (item), info);
+}
+
+static size_t
+parse_save_results_cb (void   *contents,
+                       size_t  length,
+                       size_t  nmemb,
+                       void   *user_data)
+{
+  BijiNoteObj *note = BIJI_NOTE_OBJ (user_data);
+  BijiNextcloudNote *self = BIJI_NEXTCLOUD_NOTE (user_data);
+  size_t real_size = length * nmemb;
+  g_autoptr (JsonParser) parser = json_parser_new ();
+  JsonNode *root = NULL;
+  JsonObject *json = NULL;
+  gint64 id = 0;
+  const char *data = (const char *) contents;
+  g_autoptr (GError) error = NULL;
+
+  if (!data)
+    return 0;
+
+  if (!json_parser_load_from_data (parser, data, real_size, &error))
+    {
+      if (error)
+        g_debug ("error:%s", error->message);
+      return 0;
+    }
+
+  root = json_parser_get_root (parser);
+  if (JSON_NODE_TYPE (root) == JSON_NODE_OBJECT)
+    {
+      json = json_node_get_object (root);
+
+      id = json_object_get_int_member (json, "id");
+      if (id > 0 && self->id != id)
+        {
+          self->id = id;
+          g_free (self->new_url);
+          self->new_url = g_strdup_printf ("%s/%ld",
+                                           biji_nextcloud_provider_get_baseurl (self->provider),
+                                           self->id);
+        }
+
+      biji_note_obj_set_mtime (note, json_object_get_int_member (json, "modified"));
+    }
+  else
+    return 0;
+
+  return real_size;
+}
+
+static void
+save_note_thread (GTask        *task,
+                  gpointer      source_object,
+                  gpointer      task_data,
+                  GCancellable *cancellable)
+{
+  BijiNoteObj *note = BIJI_NOTE_OBJ (source_object);
+  BijiNextcloudNote *self = BIJI_NEXTCLOUD_NOTE (source_object);
+  CURL *curl = curl_easy_init ();
+  CURLcode res = 0;
+  struct curl_slist *headers = NULL;
+  g_autofree char *json_text = NULL;
+  g_autofree char *content = NULL;
+
+  if (curl)
+    {
+      headers = curl_slist_append (headers, "Content-Type: application/json");
+      content = biji_str_mass_replace (biji_note_obj_get_raw_text (note), "\n", "\\n", NULL);
+      json_text = g_strdup_printf ("{\"title\": \"%s\", \"content\": \"%s\", \"modified\": %ld}",
+                                   biji_note_obj_get_title (note),
+                                   content,
+                                   biji_item_get_mtime (BIJI_ITEM (source_object)));
+
+      curl_easy_setopt (curl, CURLOPT_HTTPHEADER, headers);
+      curl_easy_setopt (curl, CURLOPT_POSTFIELDS, json_text);
+      if (self->id > 0)
+        {
+          if (self->new_url)
+            curl_easy_setopt (curl, CURLOPT_URL, self->new_url);
+          else
+            curl_easy_setopt (curl, CURLOPT_URL, biji_note_obj_get_path (note));
+          curl_easy_setopt (curl, CURLOPT_CUSTOMREQUEST, "PUT");
+        }
+      else
+        curl_easy_setopt (curl, CURLOPT_URL, biji_nextcloud_provider_get_baseurl (self->provider));
+      curl_easy_setopt (curl, CURLOPT_USERNAME, biji_nextcloud_provider_get_username (self->provider));
+      curl_easy_setopt (curl, CURLOPT_PASSWORD, biji_nextcloud_provider_get_password (self->provider));
+      curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, parse_save_results_cb);
+      curl_easy_setopt (curl, CURLOPT_WRITEDATA, (void *)self);
+
+      res = curl_easy_perform (curl);
+      if (res != CURLE_OK)
+        g_debug ("curl_easy_perform() failed: %s", curl_easy_strerror (res));
+
+      curl_slist_free_all (headers);
+      curl_easy_cleanup (curl);
+    }
+}
+
+static void
+save_note_async (BijiNextcloudNote *self)
+{
+  g_autoptr (GTask) task = g_task_new (self, NULL, save_note_finish, NULL);
+  g_task_run_in_thread (task, save_note_thread);
+}
+
+static void
+save_note (BijiNoteObj *note)
+{
+  BijiItem *item = BIJI_ITEM (note);
+  const char *title = biji_item_get_title (item);
+  const char *content = biji_note_obj_get_raw_text (note);
+
+  if (title && strlen (title) > 0 && content && strlen (content) > 0)
+    save_note_async (BIJI_NEXTCLOUD_NOTE (note));
+}
+
+/* archive function will actually remove the note. This is what the previous
+ * implementation (OwnCloud file notes) was using before but and it'll be
+ * changed in the future.
+ */
+static gboolean
+archive (BijiNoteObj *note)
+{
+  BijiNextcloudNote *self = BIJI_NEXTCLOUD_NOTE (note);
+  CURL *curl = curl_easy_init ();
+  CURLcode res = 0;
+
+  if (curl && self->id > 0)
+    {
+      if (self->new_url)
+        curl_easy_setopt (curl, CURLOPT_URL, self->new_url);
+      else
+        curl_easy_setopt (curl, CURLOPT_URL, biji_note_obj_get_path (note));
+
+      curl_easy_setopt (curl, CURLOPT_CUSTOMREQUEST, "DELETE");
+      curl_easy_setopt (curl, CURLOPT_USERNAME, biji_nextcloud_provider_get_username (self->provider));
+      curl_easy_setopt (curl, CURLOPT_PASSWORD, biji_nextcloud_provider_get_password (self->provider));
+
+      res = curl_easy_perform (curl);
+      if (res == CURLE_OK)
+        {
+          curl_easy_cleanup (curl);
+          biji_note_delete_from_tracker (note);
+          return TRUE;
+        }
+
+      g_warning ("curl_easy_perform() failed: %s", curl_easy_strerror (res));
+      curl_easy_cleanup (curl);
+    }
+
+  return FALSE;
+}
+
+BijiNoteObj *
+biji_nextcloud_note_new (BijiNextcloudProvider *provider,
+                         BijiManager           *manager,
+                         gint64                 id,
+                         const char            *title,
+                         gint64                 mtime,
+                         const char            *content)
+{
+  const char *baseurl = biji_nextcloud_provider_get_baseurl (provider);
+  g_autofree char *url = NULL;
+  g_autofree char *uuid = NULL;
+  BijiNextcloudNote *self = NULL;
+
+  if (id > 0)
+    url = g_strdup_printf ("%s/%ld", baseurl, id);
+  else
+    {
+      uuid = g_uuid_string_random ();
+      url = g_strdup_printf ("%s/temp_%s", baseurl, uuid);
+    }
+
+  self = g_object_new (BIJI_TYPE_NEXTCLOUD_NOTE,
+                       "manager", manager,
+                       "path",    url,
+                       "title",   title,
+                       "mtime",   mtime,
+                       "content", content,
+                       NULL);
+
+  self->provider = provider;
+  self->id = id;
+
+  return BIJI_NOTE_OBJ (self);
+}
+
+static void
+finalize (GObject *object)
+{
+  BijiNextcloudNote *self = (BijiNextcloudNote *)object;
+
+  g_free (self->new_url);
+
+  G_OBJECT_CLASS (biji_nextcloud_note_parent_class)->finalize (object);
+}
+
+static void
+biji_nextcloud_note_class_init (BijiNextcloudNoteClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  BijiItemClass *item_class = BIJI_ITEM_CLASS (klass);
+  BijiNoteObjClass *note_class = BIJI_NOTE_OBJ_CLASS (klass);
+
+  object_class->finalize = finalize;
+
+  item_class->is_collectable = item_no;
+  item_class->has_color = item_no;
+  item_class->get_place = get_place;
+
+  note_class->get_basename = get_basename;
+  note_class->get_html = get_html;
+  note_class->set_html = set_html;
+  note_class->save_note = save_note;
+  note_class->can_format = note_no;
+  note_class->archive = archive;
+  note_class->is_trashed = note_no;
+}
+
+static void
+biji_nextcloud_note_init (BijiNextcloudNote *self)
+{
+}
+
diff --git a/src/libbiji/provider/biji-nextcloud-note.h b/src/libbiji/provider/biji-nextcloud-note.h
new file mode 100644
index 0000000..babbc85
--- /dev/null
+++ b/src/libbiji/provider/biji-nextcloud-note.h
@@ -0,0 +1,39 @@
+/* biji-nextcloud-note.h
+ *
+ * Copyright 2020 Isaque Galdino <igaldino gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include "biji-note-obj.h"
+#include "biji-nextcloud-provider.h"
+
+G_BEGIN_DECLS
+
+#define BIJI_TYPE_NEXTCLOUD_NOTE (biji_nextcloud_note_get_type ())
+
+G_DECLARE_FINAL_TYPE (BijiNextcloudNote, biji_nextcloud_note, BIJI, NEXTCLOUD_NOTE, BijiNoteObj)
+
+BijiNoteObj *biji_nextcloud_note_new (BijiNextcloudProvider *provider,
+                                      BijiManager           *manager,
+                                      gint64                 id,
+                                      const char            *title,
+                                      gint64                 mtime,
+                                      const char            *content);
+
+G_END_DECLS
diff --git a/src/libbiji/provider/biji-nextcloud-provider.c b/src/libbiji/provider/biji-nextcloud-provider.c
new file mode 100644
index 0000000..51b2bd8
--- /dev/null
+++ b/src/libbiji/provider/biji-nextcloud-provider.c
@@ -0,0 +1,395 @@
+/* biji-nextcloud-provider.c
+ *
+ * Copyright 2020 Isaque Galdino <igaldino gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include <curl/curl.h>
+#include <json-glib/json-glib.h>
+
+#include "biji-nextcloud-note.h"
+#include "biji-nextcloud-provider.h"
+
+struct _BijiNextcloudProvider
+{
+  BijiProvider      parent_instance;
+  BijiProviderInfo  info;
+  GoaObject        *goa;
+  char             *password;
+  char             *baseurl;
+  GHashTable       *items;
+};
+
+G_DEFINE_TYPE (BijiNextcloudProvider, biji_nextcloud_provider, BIJI_TYPE_PROVIDER)
+
+enum {
+  PROP_0,
+  PROP_GOA_OBJECT,
+  NEXTCLOUD_PROV_PROP
+};
+
+static GParamSpec *properties [NEXTCLOUD_PROV_PROP] = { NULL, };
+
+static void
+load_all_notes_finish (GObject      *source_object,
+                       GAsyncResult *res,
+                       gpointer      user_data)
+{
+  BijiNextcloudProvider *self = BIJI_NEXTCLOUD_PROVIDER (source_object);
+  g_autoptr (GList) list = g_hash_table_get_values (self->items);
+
+  BIJI_PROVIDER_GET_CLASS (self)->notify_loaded (BIJI_PROVIDER (self), list, BIJI_LIVING_ITEMS);
+}
+
+static void
+parse_json_array_cb (JsonArray *array,
+                     guint      index_,
+                     JsonNode  *node,
+                     gpointer   user_data)
+{
+  BijiNextcloudProvider *self = BIJI_NEXTCLOUD_PROVIDER (user_data);
+  JsonObject *json = json_node_get_object (node);
+
+  gint64 id = json_object_get_int_member (json, "id");
+  const char *title = json_object_get_string_member (json, "title");
+  gint64 modified = json_object_get_int_member (json, "modified");
+  /*const char *category = json_object_get_string_member (json, "category");*/
+  const char *content  = json_object_get_string_member (json, "content");
+
+  BijiNoteObj *note = biji_nextcloud_note_new (self,
+                                               biji_provider_get_manager (BIJI_PROVIDER (self)),
+                                               id,
+                                               title,
+                                               modified,
+                                               content);
+  g_hash_table_replace (self->items, g_strdup_printf ("%ld", id), note);
+}
+
+static size_t
+parse_all_notes_cb (void   *contents,
+                    size_t  length,
+                    size_t  nmemb,
+                    void   *user_data)
+{
+  BijiNextcloudProvider *self = BIJI_NEXTCLOUD_PROVIDER (user_data);
+  size_t real_size = length * nmemb;
+  g_autoptr (JsonParser) parser = json_parser_new ();
+  JsonNode *root = NULL;
+  const char *data = (const char *) contents;
+  g_autoptr (GError) error = NULL;
+
+  if (!data)
+    return 0;
+
+  if (!json_parser_load_from_data (parser, data, real_size, &error))
+    {
+      if (error)
+        g_debug ("error:%s", error->message);
+      return 0;
+    }
+
+  root = json_parser_get_root (parser);
+  if (JSON_NODE_TYPE (root) == JSON_NODE_ARRAY)
+    json_array_foreach_element (json_node_get_array (root), parse_json_array_cb, self);
+  else
+    return 0;
+
+  return real_size;
+}
+
+static void
+load_all_notes_thread(GTask        *task,
+                      gpointer      source_object,
+                      gpointer      task_data,
+                      GCancellable *cancellable)
+{
+  BijiNextcloudProvider *self = BIJI_NEXTCLOUD_PROVIDER (source_object);
+  CURL *curl = curl_easy_init ();
+  CURLcode res = 0;
+
+  if (curl)
+    {
+      curl_easy_setopt (curl, CURLOPT_URL, self->baseurl);
+      curl_easy_setopt (curl, CURLOPT_USERNAME, self->info.user);
+      curl_easy_setopt (curl, CURLOPT_PASSWORD, self->password);
+      curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, parse_all_notes_cb);
+      curl_easy_setopt (curl, CURLOPT_WRITEDATA, (void *)self);
+
+      res = curl_easy_perform (curl);
+      if (res != CURLE_OK)
+        g_debug ("curl_easy_perform() failed: %s", curl_easy_strerror (res));
+
+      curl_easy_cleanup (curl);
+    }
+}
+
+static void
+load_all_notes_async (BijiNextcloudProvider *self)
+{
+  g_autoptr (GTask) task = g_task_new (self, NULL, load_all_notes_finish, NULL);
+  g_task_run_in_thread (task, load_all_notes_thread);
+}
+
+static const BijiProviderInfo *
+get_info (BijiProvider *provider)
+{
+  BijiNextcloudProvider *self = BIJI_NEXTCLOUD_PROVIDER (provider);
+  return &(self->info);
+}
+
+static BijiNoteObj *
+create_new_note (BijiProvider *provider,
+                 const char   *str)
+{
+  BijiManager *manager = biji_provider_get_manager (provider);
+  BijiNextcloudProvider *self = BIJI_NEXTCLOUD_PROVIDER (provider);
+
+  return biji_nextcloud_note_new (self, manager, 0, NULL, 0, "");
+}
+
+static BijiNoteObj *
+create_note_full (BijiProvider  *provider,
+                  const char    *suggested_path,
+                  BijiInfoSet   *info,
+                  const char    *html,
+                  const GdkRGBA *color)
+{
+  BijiManager *manager = biji_provider_get_manager (provider);
+  BijiNextcloudProvider *self = BIJI_NEXTCLOUD_PROVIDER (provider);
+  BijiNoteObj *note = biji_nextcloud_note_new (self, manager, 0, info->title, info->mtime, info->content);
+  GdkRGBA override_color;
+
+  biji_manager_get_default_color (biji_provider_get_manager (provider), &override_color);
+  biji_note_obj_set_html (note, html);
+  biji_note_obj_set_rgba (note, &override_color);
+
+  return note;
+}
+
+static void
+load_archives (BijiProvider *provider)
+{
+  return;
+}
+
+BijiProvider *
+biji_nextcloud_provider_new (BijiManager *manager,
+                             GoaObject   *goa)
+{
+  return g_object_new (BIJI_TYPE_NEXTCLOUD_PROVIDER,
+                       "manager", manager,
+                       "goa",     goa,
+                       NULL);
+}
+
+const char *
+biji_nextcloud_provider_get_baseurl (BijiNextcloudProvider *self)
+{
+  return self->baseurl;
+}
+
+const char *
+biji_nextcloud_provider_get_username (BijiNextcloudProvider *self)
+{
+  return self->info.user;
+}
+
+const char *
+biji_nextcloud_provider_get_password (BijiNextcloudProvider *self)
+{
+  return self->password;
+}
+
+static void
+constructed (GObject *object)
+{
+  BijiNextcloudProvider *self = (BijiNextcloudProvider *)object;
+  GoaAccount *account = NULL;
+  const char *goa_id;
+  g_auto(GStrv) bjb_id = NULL;
+  GoaPasswordBased *goa_pass = NULL;
+  g_autoptr (GIcon) icon = NULL;
+  g_autoptr (GError) error = NULL;
+
+  G_OBJECT_CLASS (biji_nextcloud_provider_parent_class)->constructed (object);
+
+  if (!GOA_IS_OBJECT (self->goa))
+    {
+      biji_provider_abort (BIJI_PROVIDER (self));
+      return;
+    }
+
+  account = goa_object_peek_account (self->goa);
+  if (!account)
+    {
+      biji_provider_abort (BIJI_PROVIDER (self));
+      return;
+    }
+
+  self->items = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+
+  self->info.unique_id = goa_account_get_id (account);
+  self->info.datasource = g_strdup_printf ("gn:goa-account:%s", self->info.unique_id);
+  self->info.name = g_strdup (goa_account_get_provider_name (account));
+
+  goa_id = goa_account_get_presentation_identity (account);
+  if (goa_id)
+    {
+      bjb_id = g_strsplit (goa_id, "@", 2);
+      if (bjb_id[0])
+        {
+          self->info.user = g_strdup (bjb_id[0]);
+          if (bjb_id[1])
+            self->info.domain = g_strdup (bjb_id[1]);
+        }
+    }
+  if (!self->info.user || !self->info.domain)
+    {
+      biji_provider_abort (BIJI_PROVIDER (self));
+      return;
+    }
+
+  if (!goa_account_call_ensure_credentials_sync (account, NULL, NULL, NULL))
+    {
+      g_debug ("FAILED: goa_account_call_ensure_credentials_sync");
+      biji_provider_abort (BIJI_PROVIDER (self));
+      return;
+    }
+
+  goa_pass = goa_object_peek_password_based (self->goa);
+  if (!goa_pass ||
+      !goa_password_based_call_get_password_sync (goa_pass,
+                                                  self->info.user,
+                                                  &self->password,
+                                                  NULL, NULL))
+    {
+      g_debug ("FAILED: goa_password_based_call_get_password_sync");
+      biji_provider_abort (BIJI_PROVIDER (self));
+      return;
+    }
+
+  icon = g_icon_new_for_string (goa_account_get_provider_icon (account), &error);
+  if (error)
+    {
+      g_warning ("%s", error->message);
+      self->info.icon = NULL;
+    }
+  else
+    {
+      self->info.icon = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_INVALID);
+      gtk_image_set_pixel_size (GTK_IMAGE (self->info.icon), 48);
+      g_object_ref_sink (self->info.icon);
+    }
+
+  self->baseurl = g_strdup_printf ("https://%s/index.php/apps/notes/api/v1/notes";,
+                                   self->info.domain);
+
+  curl_global_init (CURL_GLOBAL_DEFAULT);
+
+  load_all_notes_async (self);
+}
+
+static void
+finalize (GObject *object)
+{
+  BijiNextcloudProvider *self = (BijiNextcloudProvider *)object;
+
+  curl_global_cleanup ();
+
+  g_clear_object (&self->goa);
+  g_clear_object (&self->info.icon);
+
+  g_clear_pointer (&self->info.name, g_free);
+  g_clear_pointer (&self->info.user, g_free);
+  g_clear_pointer (&self->info.domain, g_free);
+  g_clear_pointer (&self->password, g_free);
+  g_clear_pointer (&self->baseurl, g_free);
+
+  g_hash_table_unref (self->items);
+
+  G_OBJECT_CLASS (biji_nextcloud_provider_parent_class)->finalize (object);
+}
+
+static void
+get_property (GObject    *object,
+              guint       prop_id,
+              GValue     *value,
+              GParamSpec *pspec)
+{
+  BijiNextcloudProvider *self = BIJI_NEXTCLOUD_PROVIDER (object);
+
+  switch (prop_id)
+    {
+    case PROP_GOA_OBJECT:
+      g_value_set_object (value, self->goa);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+set_property (GObject      *object,
+              guint         prop_id,
+              const GValue *value,
+              GParamSpec   *pspec)
+{
+  BijiNextcloudProvider *self = BIJI_NEXTCLOUD_PROVIDER (object);
+
+  switch (prop_id)
+    {
+    case PROP_GOA_OBJECT:
+      self->goa = g_value_dup_object (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+biji_nextcloud_provider_class_init (BijiNextcloudProviderClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  BijiProviderClass *provider_class = BIJI_PROVIDER_CLASS (klass);
+
+  object_class->constructed = constructed;
+  object_class->finalize = finalize;
+  object_class->get_property = get_property;
+  object_class->set_property = set_property;
+
+  provider_class->get_info = get_info;
+  provider_class->create_new_note = create_new_note;
+  provider_class->create_note_full = create_note_full;
+  provider_class->load_archives = load_archives;
+
+  properties[PROP_GOA_OBJECT] =
+    g_param_spec_object("goa",
+                        "The Goa Object",
+                        "The Goa Object providing notes",
+                        GOA_TYPE_OBJECT,
+                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+
+  g_object_class_install_properties (object_class, NEXTCLOUD_PROV_PROP, properties);
+}
+
+static void
+biji_nextcloud_provider_init (BijiNextcloudProvider *self)
+{
+}
+
diff --git a/src/libbiji/provider/biji-nextcloud-provider.h b/src/libbiji/provider/biji-nextcloud-provider.h
new file mode 100644
index 0000000..bc707a7
--- /dev/null
+++ b/src/libbiji/provider/biji-nextcloud-provider.h
@@ -0,0 +1,41 @@
+/* biji-nextcloud-provider.h
+ *
+ * Copyright 2020 Isaque Galdino <igaldino gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include "biji-provider.h"
+
+G_BEGIN_DECLS
+
+#define BIJI_TYPE_NEXTCLOUD_PROVIDER (biji_nextcloud_provider_get_type ())
+
+G_DECLARE_FINAL_TYPE (BijiNextcloudProvider, biji_nextcloud_provider, BIJI, NEXTCLOUD_PROVIDER, BijiProvider)
+
+BijiProvider *biji_nextcloud_provider_new (BijiManager *manager,
+                                           GoaObject   *goa);
+
+const char *biji_nextcloud_provider_get_baseurl (BijiNextcloudProvider *self);
+
+const char *biji_nextcloud_provider_get_username (BijiNextcloudProvider *self);
+
+const char *biji_nextcloud_provider_get_password (BijiNextcloudProvider *self);
+
+G_END_DECLS
+


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]