summaryrefslogtreecommitdiff
path: root/src/bookmarks
diff options
context:
space:
mode:
authorBastien Nocera <hadess@hadess.net>2014-03-21 10:07:30 +0100
committerBastien Nocera <hadess@hadess.net>2014-05-07 18:17:24 +0200
commit06812aaa8b8dce640dd5317735bd1b95bdf2047a (patch)
tree25754eaed4160391714b1b01ea8de42304cdd907 /src/bookmarks
parent539c92a1e7761ff35cd6ef7dc392cdd7079c76e8 (diff)
downloadgrilo-plugins-06812aaa8b8dce640dd5317735bd1b95bdf2047a.tar.gz
bookmarks: Use gom to access the database
Instead of SQLite directly. gom is currently available at: https://github.com/chergert/gom/ Fixes: - No injection security holes - Easy DB extension Functional changes: - Boxes don't have a childcount anymore - Query has a different syntax which more closely matches the database names (as opposed to the undiscoverable names used in the queries) - Orphans are cleaned up on startup rather than when removing items https://bugzilla.gnome.org/show_bug.cgi?id=673912
Diffstat (limited to 'src/bookmarks')
-rw-r--r--src/bookmarks/Makefile.am6
-rw-r--r--src/bookmarks/bookmarks-resource.c266
-rw-r--r--src/bookmarks/bookmarks-resource.h68
-rw-r--r--src/bookmarks/grl-bookmarks.c562
4 files changed, 608 insertions, 294 deletions
diff --git a/src/bookmarks/Makefile.am b/src/bookmarks/Makefile.am
index aa987af..979bb2b 100644
--- a/src/bookmarks/Makefile.am
+++ b/src/bookmarks/Makefile.am
@@ -22,7 +22,11 @@ libgrlbookmarks_la_LDFLAGS = \
-module \
-avoid-version
-libgrlbookmarks_la_SOURCES = grl-bookmarks.c grl-bookmarks.h
+libgrlbookmarks_la_SOURCES = \
+ grl-bookmarks.c \
+ grl-bookmarks.h \
+ bookmarks-resource.c \
+ bookmarks-resource.h
extdir = $(GRL_PLUGINS_DIR)
bookmarksxmldir = $(GRL_PLUGINS_DIR)
diff --git a/src/bookmarks/bookmarks-resource.c b/src/bookmarks/bookmarks-resource.c
new file mode 100644
index 0000000..8f0d554
--- /dev/null
+++ b/src/bookmarks/bookmarks-resource.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2014 Bastien Nocera <hadess@hadess.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <glib/gi18n.h>
+
+#include "bookmarks-resource.h"
+
+G_DEFINE_TYPE(BookmarksResource, bookmarks_resource, GOM_TYPE_RESOURCE)
+
+struct _BookmarksResourcePrivate
+{
+ int id;
+ int parent;
+ BookmarksType type;
+ char *url;
+ char *title;
+ char *date;
+ char *mime;
+ char *desc;
+};
+
+enum
+{
+ PROP_0,
+ PROP_ID,
+ PROP_PARENT,
+ PROP_TYPE,
+ PROP_URL,
+ PROP_TITLE,
+ PROP_DATE,
+ PROP_MIME,
+ PROP_DESC,
+ LAST_PROP
+};
+
+static GParamSpec *specs[LAST_PROP];
+
+static void
+bookmarks_resource_finalize (GObject *object)
+{
+ BookmarksResourcePrivate *priv = BOOKMARKS_RESOURCE(object)->priv;
+
+ g_free (priv->url);
+ g_free (priv->title);
+ g_free (priv->date);
+ g_free (priv->mime);
+ g_free (priv->desc);
+
+ G_OBJECT_CLASS(bookmarks_resource_parent_class)->finalize(object);
+}
+
+static void
+bookmarks_resource_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ BookmarksResource *resource = BOOKMARKS_RESOURCE(object);
+
+ switch (prop_id) {
+ case PROP_ID:
+ g_value_set_int64(value, resource->priv->id);
+ break;
+ case PROP_PARENT:
+ g_value_set_int64(value, resource->priv->parent);
+ break;
+ case PROP_TYPE:
+ g_value_set_enum(value, resource->priv->type);
+ break;
+ case PROP_URL:
+ g_value_set_string(value, resource->priv->url);
+ break;
+ case PROP_TITLE:
+ g_value_set_string(value, resource->priv->title);
+ break;
+ case PROP_DATE:
+ g_value_set_string(value, resource->priv->date);
+ break;
+ case PROP_MIME:
+ g_value_set_string(value, resource->priv->mime);
+ break;
+ case PROP_DESC:
+ g_value_set_string(value, resource->priv->desc);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ }
+}
+
+static void
+bookmarks_resource_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ BookmarksResource *resource = BOOKMARKS_RESOURCE(object);
+
+ switch (prop_id) {
+ case PROP_ID:
+ resource->priv->id = g_value_get_int64 (value);
+ break;
+ case PROP_PARENT:
+ resource->priv->parent = g_value_get_int64 (value);
+ break;
+ case PROP_TYPE:
+ resource->priv->type = g_value_get_enum (value);
+ break;
+ case PROP_URL:
+ g_free (resource->priv->url);
+ resource->priv->url = g_value_dup_string (value);
+ break;
+ case PROP_TITLE:
+ g_free (resource->priv->title);
+ resource->priv->title = g_value_dup_string (value);
+ break;
+ case PROP_DATE:
+ g_free (resource->priv->date);
+ resource->priv->date = g_value_dup_string (value);
+ break;
+ case PROP_MIME:
+ g_free (resource->priv->mime);
+ resource->priv->mime = g_value_dup_string (value);
+ break;
+ case PROP_DESC:
+ g_free (resource->priv->desc);
+ resource->priv->desc = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ }
+}
+
+static void
+bookmarks_resource_class_init (BookmarksResourceClass *klass)
+{
+ GObjectClass *object_class;
+ GomResourceClass *resource_class;
+
+ object_class = G_OBJECT_CLASS(klass);
+ object_class->finalize = bookmarks_resource_finalize;
+ object_class->get_property = bookmarks_resource_get_property;
+ object_class->set_property = bookmarks_resource_set_property;
+ g_type_class_add_private(object_class, sizeof(BookmarksResourcePrivate));
+
+ resource_class = GOM_RESOURCE_CLASS(klass);
+ gom_resource_class_set_table(resource_class, "bookmarks");
+
+ specs[PROP_ID] =
+ g_param_spec_int64 ("id",
+ NULL,
+ NULL,
+ 0, G_MAXINT64,
+ 0, G_PARAM_READWRITE);
+ g_object_class_install_property(object_class, PROP_ID,
+ specs[PROP_ID]);
+ gom_resource_class_set_primary_key(resource_class, "id");
+
+ specs[PROP_PARENT] =
+ g_param_spec_int64 ("parent",
+ NULL,
+ NULL,
+ 0, G_MAXINT64,
+ 0, G_PARAM_READWRITE);
+ g_object_class_install_property(object_class, PROP_PARENT,
+ specs[PROP_PARENT]);
+ gom_resource_class_set_reference(resource_class, "parent",
+ NULL, "id");
+
+ specs[PROP_TYPE] =
+ g_param_spec_enum ("type",
+ NULL,
+ NULL,
+ BOOKMARKS_TYPE_TYPE,
+ BOOKMARKS_TYPE_STREAM,
+ G_PARAM_READWRITE);
+ g_object_class_install_property(object_class, PROP_TYPE,
+ specs[PROP_TYPE]);
+
+ specs[PROP_URL] =
+ g_param_spec_string("url",
+ NULL,
+ NULL,
+ NULL,
+ G_PARAM_READWRITE);
+ g_object_class_install_property(object_class, PROP_URL,
+ specs[PROP_URL]);
+
+ specs[PROP_TITLE] =
+ g_param_spec_string("title",
+ NULL,
+ NULL,
+ NULL,
+ G_PARAM_READWRITE);
+ g_object_class_install_property(object_class, PROP_TITLE,
+ specs[PROP_TITLE]);
+
+ specs[PROP_DATE] =
+ g_param_spec_string("date",
+ NULL,
+ NULL,
+ NULL,
+ G_PARAM_READWRITE);
+ g_object_class_install_property(object_class, PROP_DATE,
+ specs[PROP_DATE]);
+
+ specs[PROP_MIME] =
+ g_param_spec_string("mime",
+ NULL,
+ NULL,
+ NULL,
+ G_PARAM_READWRITE);
+ g_object_class_install_property(object_class, PROP_MIME,
+ specs[PROP_MIME]);
+
+ specs[PROP_DESC] =
+ g_param_spec_string("desc",
+ NULL,
+ NULL,
+ NULL,
+ G_PARAM_READWRITE);
+ g_object_class_install_property(object_class, PROP_DESC,
+ specs[PROP_DESC]);
+}
+
+static void
+bookmarks_resource_init (BookmarksResource *resource)
+{
+ resource->priv = G_TYPE_INSTANCE_GET_PRIVATE(resource,
+ BOOKMARKS_TYPE_RESOURCE,
+ BookmarksResourcePrivate);
+}
+
+GType
+bookmarks_type_get_type (void)
+{
+ static GType type_id = 0;
+ static gsize initialized = FALSE;
+ static GEnumValue values[] = {
+ { BOOKMARKS_TYPE_CATEGORY, "BOOKMARK_TYPE_CATEGORY", "CATEGORY" },
+ { BOOKMARKS_TYPE_STREAM, "BOOKMARK_TYPE_STREAM", "STREAM" }
+ };
+
+ if (g_once_init_enter(&initialized)) {
+ type_id = g_enum_register_static("BookmarksType", values);
+ g_once_init_leave(&initialized, TRUE);
+ }
+
+ return type_id;
+}
diff --git a/src/bookmarks/bookmarks-resource.h b/src/bookmarks/bookmarks-resource.h
new file mode 100644
index 0000000..6bf7fae
--- /dev/null
+++ b/src/bookmarks/bookmarks-resource.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2014 Bastien Nocera <hadess@hadess.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef BOOKMARKS_RESOURCE_H
+#define BOOKMARKS_RESOURCE_H
+
+#include <gom/gom.h>
+
+G_BEGIN_DECLS
+
+#define BOOKMARKS_TYPE_RESOURCE (bookmarks_resource_get_type())
+#define BOOKMARKS_TYPE_TYPE (bookmarks_type_get_type())
+#define BOOKMARKS_RESOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BOOKMARKS_TYPE_RESOURCE, BookmarksResource))
+#define BOOKMARKS_RESOURCE_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BOOKMARKS_TYPE_RESOURCE, BookmarksResource const))
+#define BOOKMARKS_RESOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), BOOKMARKS_TYPE_RESOURCE, BookmarksResourceClass))
+#define BOOKMARKS_IS_RESOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BOOKMARKS_TYPE_RESOURCE))
+#define BOOKMARKS_IS_RESOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), BOOKMARKS_TYPE_RESOURCE))
+#define BOOKMARKS_RESOURCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), BOOKMARKS_TYPE_RESOURCE, BookmarksResourceClass))
+#define BOOKMARKS_RESOURCE_ERROR (bookmarks_resource_error_quark())
+
+typedef struct _BookmarksResource BookmarksResource;
+typedef struct _BookmarksResourceClass BookmarksResourceClass;
+typedef struct _BookmarksResourcePrivate BookmarksResourcePrivate;
+typedef enum _BookmarksResourceError BookmarksResourceError;
+typedef enum _BookmarksType BookmarksType;
+
+enum _BookmarksType
+{
+ BOOKMARKS_TYPE_CATEGORY = 0,
+ BOOKMARKS_TYPE_STREAM
+};
+
+struct _BookmarksResource
+{
+ GomResource parent;
+
+ /*< private >*/
+ BookmarksResourcePrivate *priv;
+};
+
+struct _BookmarksResourceClass
+{
+ GomResourceClass parent_class;
+};
+
+GType bookmarks_type_get_type (void) G_GNUC_CONST;
+GType bookmarks_resource_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* BOOKMARKS_RESOURCE_H */
diff --git a/src/bookmarks/grl-bookmarks.c b/src/bookmarks/grl-bookmarks.c
index 9d6120a..528a558 100644
--- a/src/bookmarks/grl-bookmarks.c
+++ b/src/bookmarks/grl-bookmarks.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2010, 2011 Igalia S.L.
+ * Copyright (C) 2014 Bastien Nocera <hadess@hadess.net>
*
* Contact: Iago Toral Quiroga <itoral@igalia.com>
*
@@ -28,14 +29,14 @@
#include <glib/gstdio.h>
#include <glib/gi18n-lib.h>
#include <grilo.h>
-#include <sqlite3.h>
#include <string.h>
#include <stdlib.h>
#include "grl-bookmarks.h"
+#include "bookmarks-resource.h"
-#define GRL_BOOKMARKS_GET_PRIVATE(object) \
- (G_TYPE_INSTANCE_GET_PRIVATE((object), \
+#define GRL_BOOKMARKS_GET_PRIVATE(object) \
+ (G_TYPE_INSTANCE_GET_PRIVATE((object), \
GRL_BOOKMARKS_SOURCE_TYPE, \
GrlBookmarksPrivate))
@@ -50,67 +51,14 @@ GRL_LOG_DOMAIN_STATIC(bookmarks_log_domain);
#define GRL_SQL_DB "grl-bookmarks.db"
-#define GRL_SQL_CREATE_TABLE_BOOKMARKS \
- "CREATE TABLE IF NOT EXISTS bookmarks (" \
- "id INTEGER PRIMARY KEY AUTOINCREMENT," \
- "parent INTEGER REFERENCES bookmarks (id)," \
- "type INTEGER," \
- "url TEXT," \
- "title TEXT," \
- "date TEXT," \
- "mime TEXT," \
- "desc TEXT)"
-
-#define GRL_SQL_GET_BOOKMARKS_BY_PARENT \
- "SELECT b1.*, count(b2.parent <> '') " \
- "FROM bookmarks b1 LEFT OUTER JOIN bookmarks b2 " \
- " ON b1.id = b2.parent " \
- "WHERE b1.parent='%s' " \
- "GROUP BY b1.id " \
- "LIMIT %u OFFSET %u"
-
-#define GRL_SQL_GET_BOOKMARK_BY_ID \
- "SELECT b1.*, count(b2.parent <> '') " \
- "FROM bookmarks b1 LEFT OUTER JOIN bookmarks b2 " \
- " ON b1.id = b2.parent " \
- "WHERE b1.id='%s' " \
- "GROUP BY b1.id " \
- "LIMIT 1"
-
-#define GRL_SQL_STORE_BOOKMARK \
- "INSERT INTO bookmarks " \
- "(parent, type, url, title, date, mime, desc) " \
- "VALUES (?, ?, ?, ?, ?, ?, ?)"
-
-#define GRL_SQL_REMOVE_BOOKMARK \
- "DELETE FROM bookmarks " \
- "WHERE id='%s' or parent='%s'"
-
-#define GRL_SQL_REMOVE_ORPHAN \
- "DELETE FROM bookmarks " \
- "WHERE id in ( " \
- " SELECT DISTINCT id FROM bookmarks " \
- " WHERE parent NOT IN ( " \
- " SELECT DISTINCT id FROM bookmarks) " \
+#define GRL_SQL_REMOVE_ORPHAN \
+ "DELETE FROM bookmarks " \
+ "WHERE id in ( " \
+ " SELECT DISTINCT id FROM bookmarks " \
+ " WHERE parent NOT IN ( " \
+ " SELECT DISTINCT id FROM bookmarks) " \
" and parent <> 0)"
-#define GRL_SQL_GET_BOOKMARKS_BY_TEXT \
- "SELECT b1.*, count(b2.parent <> '') " \
- "FROM bookmarks b1 LEFT OUTER JOIN bookmarks b2 " \
- " ON b1.id = b2.parent " \
- "WHERE (b1.title LIKE '%%%s%%' OR b1.desc LIKE '%%%s%%') " \
- " AND b1.type = 1 " \
- "GROUP BY b1.id " \
- "LIMIT %u OFFSET %u"
-
-#define GRL_SQL_GET_BOOKMARKS_BY_QUERY \
- "SELECT b1.*, count(b2.parent <> '') " \
- "FROM bookmarks b1 LEFT OUTER JOIN bookmarks b2 " \
- " ON b1.id = b2.parent " \
- "WHERE %s " \
- "GROUP BY b1.id " \
- "LIMIT %u OFFSET %u"
-
/* --- Plugin information --- */
#define PLUGIN_ID BOOKMARKS_PLUGIN_ID
@@ -126,20 +74,9 @@ enum {
BOOKMARK_TYPE_STREAM,
};
-enum {
- BOOKMARK_ID = 0,
- BOOKMARK_PARENT,
- BOOKMARK_TYPE,
- BOOKMARK_URL,
- BOOKMARK_TITLE,
- BOOKMARK_DATE,
- BOOKMARK_MIME,
- BOOKMARK_DESC,
- BOOKMARK_CHILDCOUNT
-};
-
struct _GrlBookmarksPrivate {
- sqlite3 *db;
+ GomAdapter *adapter;
+ GomRepository *repository;
gboolean notify_changes;
};
@@ -264,12 +201,27 @@ static gboolean grl_bookmarks_source_notify_change_stop (GrlSource *source,
}
static void
+migrate_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ gboolean ret;
+ GError *error = NULL;
+
+ ret = gom_repository_migrate_finish (GOM_REPOSITORY (object), result, &error);
+ if (!ret) {
+ GRL_WARNING ("Failed to migrate database: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+static void
grl_bookmarks_source_init (GrlBookmarksSource *source)
{
- gint r;
+ GError *error = NULL;
gchar *path;
gchar *db_path;
- gchar *sql_error = NULL;
+ GList *object_types;
source->priv = GRL_BOOKMARKS_GET_PRIVATE (source);
@@ -283,33 +235,21 @@ grl_bookmarks_source_init (GrlBookmarksSource *source)
GRL_DEBUG ("Opening database connection...");
db_path = g_strconcat (path, G_DIR_SEPARATOR_S, GRL_SQL_DB, NULL);
- r = sqlite3_open (db_path, &source->priv->db);
g_free (path);
- g_free (db_path);
- if (r) {
- g_critical ("Failed to open database '%s': %s",
- db_path, sqlite3_errmsg (source->priv->db));
- sqlite3_close (source->priv->db);
+ source->priv->adapter = gom_adapter_new ();
+ if (!gom_adapter_open_sync (source->priv->adapter, db_path, &error)) {
+ GRL_WARNING ("Could not open database '%s': %s", db_path, error->message);
+ g_error_free (error);
+ g_free (db_path);
return;
}
- GRL_DEBUG (" OK");
-
- GRL_DEBUG ("Checking database tables...");
- r = sqlite3_exec (source->priv->db, GRL_SQL_CREATE_TABLE_BOOKMARKS,
- NULL, NULL, &sql_error);
+ g_free (db_path);
- if (r) {
- if (sql_error) {
- GRL_WARNING ("Failed to create database tables: %s", sql_error);
- g_clear_pointer (&sql_error, (GDestroyNotify) sqlite3_free);
- } else {
- GRL_WARNING ("Failed to create database tables.");
- }
- sqlite3_close (source->priv->db);
- return;
- }
- GRL_DEBUG (" OK");
+ source->priv->repository = gom_repository_new (source->priv->adapter);
+ object_types = g_list_prepend(NULL, GINT_TO_POINTER(BOOKMARKS_TYPE_RESOURCE));
+ gom_repository_automatic_migrate_async (source->priv->repository, 1, object_types, migrate_cb, source);
+ g_list_free(object_types);
}
G_DEFINE_TYPE (GrlBookmarksSource, grl_bookmarks_source, GRL_TYPE_SOURCE);
@@ -323,7 +263,12 @@ grl_bookmarks_source_finalize (GObject *object)
source = GRL_BOOKMARKS_SOURCE (object);
- sqlite3_close (source->priv->db);
+ g_clear_object (&source->priv->repository);
+
+ if (source->priv->adapter) {
+ gom_adapter_close_sync (source->priv->adapter, NULL);
+ g_clear_object (&source->priv->adapter);
+ }
G_OBJECT_CLASS (grl_bookmarks_source_parent_class)->finalize (object);
}
@@ -349,30 +294,32 @@ mime_is_image (const gchar *mime)
}
static GrlMedia *
-build_media_from_stmt (GrlMedia *content, sqlite3_stmt *sql_stmt)
+build_media_from_resource (GrlMedia *content,
+ GomResource *resource)
{
GrlMedia *media = NULL;
- gchar *id;
+ gint64 id;
+ gchar *str_id;
gchar *title;
gchar *url;
gchar *desc;
gchar *date;
gchar *mime;
guint type;
- guint childcount;
if (content) {
media = content;
}
- id = (gchar *) sqlite3_column_text (sql_stmt, BOOKMARK_ID);
- title = (gchar *) sqlite3_column_text (sql_stmt, BOOKMARK_TITLE);
- url = (gchar *) sqlite3_column_text (sql_stmt, BOOKMARK_URL);
- desc = (gchar *) sqlite3_column_text (sql_stmt, BOOKMARK_DESC);
- date = (gchar *) sqlite3_column_text (sql_stmt, BOOKMARK_DATE);
- mime = (gchar *) sqlite3_column_text (sql_stmt, BOOKMARK_MIME);
- type = (guint) sqlite3_column_int (sql_stmt, BOOKMARK_TYPE);
- childcount = (guint) sqlite3_column_int (sql_stmt, BOOKMARK_CHILDCOUNT);
+ g_object_get (resource,
+ "id", &id,
+ "title", &title,
+ "url", &url,
+ "desc", &desc,
+ "date", &date,
+ "mime", &mime,
+ "type", &type,
+ NULL);
if (!media) {
if (type == BOOKMARK_TYPE_CATEGORY) {
@@ -388,7 +335,9 @@ build_media_from_stmt (GrlMedia *content, sqlite3_stmt *sql_stmt)
}
}
- grl_media_set_id (media, id);
+ str_id = g_strdup_printf ("%" G_GINT64_FORMAT, id);
+ grl_media_set_id (media, str_id);
+ g_free (str_id);
grl_media_set_title (media, title);
if (url) {
grl_media_set_url (media, url);
@@ -407,9 +356,11 @@ build_media_from_stmt (GrlMedia *content, sqlite3_stmt *sql_stmt)
}
}
- if (type == BOOKMARK_TYPE_CATEGORY) {
- grl_media_box_set_childcount (GRL_MEDIA_BOX (media), childcount);
- }
+ g_free (title);
+ g_free (url);
+ g_free (desc);
+ g_free (date);
+ g_free (mime);
return media;
}
@@ -417,18 +368,18 @@ build_media_from_stmt (GrlMedia *content, sqlite3_stmt *sql_stmt)
static void
bookmark_resolve (GrlSourceResolveSpec *rs)
{
- gint r;
- sqlite3_stmt *sql_stmt = NULL;
- sqlite3 *db;
+ GomRepository *repository;
+ GValue value = { 0, };
+ GomFilter *filter;
+ GomResource *resource;
GError *error = NULL;
- gchar *sql;
- const gchar *id;
+ gint64 id;
GRL_DEBUG (__FUNCTION__);
- db = GRL_BOOKMARKS_SOURCE (rs->source)->priv->db;
+ repository = GRL_BOOKMARKS_SOURCE (rs->source)->priv->repository;
- id = grl_media_get_id (rs->media);
+ id = g_ascii_strtoll (grl_media_get_id (rs->media), NULL, 0);
if (!id) {
/* Root category: special case */
grl_media_set_title (rs->media, GRL_ROOT_TITLE);
@@ -436,143 +387,193 @@ bookmark_resolve (GrlSourceResolveSpec *rs)
return;
}
- sql = g_strdup_printf (GRL_SQL_GET_BOOKMARK_BY_ID, id);
- GRL_DEBUG ("%s", sql);
- r = sqlite3_prepare_v2 (db, sql, strlen (sql), &sql_stmt, NULL);
- g_free (sql);
+ g_value_init (&value, G_TYPE_INT64);
+ g_value_set_int64 (&value, id);
+ filter = gom_filter_new_eq (BOOKMARKS_TYPE_RESOURCE, "id", &value);
+ g_value_unset (&value);
+ resource = gom_repository_find_one_sync (repository,
+ BOOKMARKS_TYPE_RESOURCE,
+ filter,
+ &error);
+ g_object_unref (filter);
- if (r != SQLITE_OK) {
- GRL_WARNING ("Failed to get bookmark: %s", sqlite3_errmsg (db));
- error = g_error_new_literal (GRL_CORE_ERROR,
- GRL_CORE_ERROR_RESOLVE_FAILED,
- _("Failed to get bookmark metadata"));
- rs->callback (rs->source, rs->operation_id, rs->media, rs->user_data, error);
+ if (!resource) {
+ GRL_WARNING ("Failed to get bookmark: %s", error->message);
g_error_free (error);
- return;
- }
- while ((r = sqlite3_step (sql_stmt)) == SQLITE_BUSY);
-
- if (r == SQLITE_ROW) {
- build_media_from_stmt (rs->media, sql_stmt);
- rs->callback (rs->source, rs->operation_id, rs->media, rs->user_data, NULL);
- } else {
- GRL_WARNING ("Failed to get bookmark: %s", sqlite3_errmsg (db));
error = g_error_new_literal (GRL_CORE_ERROR,
GRL_CORE_ERROR_RESOLVE_FAILED,
_("Failed to get bookmark metadata"));
rs->callback (rs->source, rs->operation_id, rs->media, rs->user_data, error);
g_error_free (error);
+ return;
}
- sqlite3_finalize (sql_stmt);
+ build_media_from_resource (rs->media, resource);
+ g_object_unref (resource);
+ rs->callback (rs->source, rs->operation_id, rs->media, rs->user_data, NULL);
}
static void
-produce_bookmarks_from_sql (OperationSpec *os, const gchar *sql)
+find_cb (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
{
- gint r;
- sqlite3_stmt *sql_stmt = NULL;
- sqlite3 *db;
- GrlMedia *media;
+ GomResourceGroup *group;
+ OperationSpec *os = user_data;
+ GError *local_error = NULL;
GError *error = NULL;
- GList *medias = NULL;
- guint count = 0;
- GList *iter;
-
- GRL_DEBUG ("produce_bookmarks_from_sql");
+ guint idx, count, num_left;
- GRL_DEBUG ("%s", sql);
- db = GRL_BOOKMARKS_SOURCE (os->source)->priv->db;
- r = sqlite3_prepare_v2 (db, sql, strlen (sql), &sql_stmt, NULL);
-
- if (r != SQLITE_OK) {
- GRL_WARNING ("Failed to retrieve bookmarks: %s", sqlite3_errmsg (db));
+ group = gom_repository_find_finish (GOM_REPOSITORY (object),
+ res,
+ &local_error);
+ if (!group) {
+ GRL_WARNING ("Failed to find bookmarks: %s", local_error->message);
error = g_error_new (GRL_CORE_ERROR,
os->error_code,
- _("Failed to get bookmarks list: %s"),
- sqlite3_errmsg (db));
+ _("Failed to find bookmarks: %s"), local_error->message);
+ g_error_free (local_error);
os->callback (os->source, os->operation_id, NULL, 0, os->user_data, error);
g_error_free (error);
- goto free_resources;
+ goto out;
}
- while ((r = sqlite3_step (sql_stmt)) == SQLITE_BUSY);
-
- while (r == SQLITE_ROW) {
- media = build_media_from_stmt (NULL, sql_stmt);
- medias = g_list_prepend (medias, media);
- count++;
- r = sqlite3_step (sql_stmt);
+ count = gom_resource_group_get_count (group);
+ if (os->skip >= count) {
+ os->callback (os->source, os->operation_id, NULL, 0, os->user_data, NULL);
+ goto out;
}
- if (r != SQLITE_DONE) {
- GRL_WARNING ("Failed to retrieve bookmarks: %s", sqlite3_errmsg (db));
+ if (!gom_resource_group_fetch_sync (group, os->skip, os->count, &local_error)) {
+ GRL_WARNING ("Failed to find bookmarks: %s", local_error->message);
error = g_error_new (GRL_CORE_ERROR,
os->error_code,
- _("Failed to get bookmarks list: %s"),
- sqlite3_errmsg (db));
+ _("Failed to find bookmarks: %s"), local_error->message);
+ g_error_free (local_error);
os->callback (os->source, os->operation_id, NULL, 0, os->user_data, error);
g_error_free (error);
- goto free_resources;
+ goto out;
}
- if (count > 0) {
- medias = g_list_reverse (medias);
- iter = medias;
- while (iter) {
- media = GRL_MEDIA (iter->data);
- os->callback (os->source,
- os->operation_id,
- media,
- --count,
- os->user_data,
- NULL);
- iter = g_list_next (iter);
- }
- g_list_free (medias);
- } else {
- os->callback (os->source, os->operation_id, NULL, 0, os->user_data, NULL);
+ idx = os->skip;
+ num_left = MIN (count - os->skip, os->count);
+ for (idx = os->skip; num_left > 0 ; idx++) {
+ GomResource *resource;
+ GrlMedia *media;
+
+ resource = gom_resource_group_get_index (group, idx);
+ media = build_media_from_resource (NULL, resource);
+ os->callback (os->source,
+ os->operation_id,
+ media,
+ --num_left,
+ os->user_data,
+ NULL);
}
- free_resources:
- g_clear_pointer (&sql_stmt, (GDestroyNotify) sqlite3_finalize);
+ g_object_unref (group);
+
+out:
+ g_slice_free (OperationSpec, os);
+}
+
+static void
+produce_bookmarks_from_filter (OperationSpec *os,
+ GomFilter *filter)
+{
+ GomRepository *repository;
+
+ GRL_DEBUG ("produce_bookmarks_from_filter");
+
+ repository = GRL_BOOKMARKS_SOURCE (os->source)->priv->repository;
+ gom_repository_find_async (repository,
+ BOOKMARKS_TYPE_RESOURCE,
+ filter,
+ find_cb,
+ os);
}
static void
-produce_bookmarks_by_query (OperationSpec *os, const gchar *query)
+produce_bookmarks_from_category (OperationSpec *os, const gchar *category_id)
{
- gchar *sql;
- GRL_DEBUG ("produce_bookmarks_by_query");
- sql = g_strdup_printf (GRL_SQL_GET_BOOKMARKS_BY_QUERY,
- query, os->count, os->skip);
- produce_bookmarks_from_sql (os, sql);
- g_free (sql);
+ GomFilter *filter;
+ GValue value = { 0, };
+ int parent_id;
+
+ GRL_DEBUG ("produce_bookmarks_from_category");
+ parent_id = atoi (category_id);
+
+ g_value_init (&value, G_TYPE_INT64);
+ g_value_set_int64 (&value, parent_id);
+ filter = gom_filter_new_eq (BOOKMARKS_TYPE_RESOURCE, "parent", &value);
+ g_value_unset (&value);
+
+ produce_bookmarks_from_filter (os, filter);
+ g_object_unref (filter);
}
static void
-produce_bookmarks_by_text (OperationSpec *os, const gchar *text)
+produce_bookmarks_from_query (OperationSpec *os, const gchar *query)
+{
+ GomFilter *filter;
+ GArray *array;
+
+ GRL_DEBUG ("produce_bookmarks_from_query");
+
+ array = g_array_new(FALSE, FALSE, sizeof(GValue));
+ filter = gom_filter_new_sql (query, array);
+ g_array_unref (array);
+ produce_bookmarks_from_filter (os, filter);
+ g_object_unref (filter);
+}
+
+static GomFilter *
+substr_filter (const char *column,
+ const char *text)
{
- gchar *sql;
- GRL_DEBUG ("produce_bookmarks_by_text");
- sql = g_strdup_printf (GRL_SQL_GET_BOOKMARKS_BY_TEXT,
- text? text: "",
- text? text: "",
- os->count,
- os->skip);
- produce_bookmarks_from_sql (os, sql);
- g_free (sql);
+ GValue value = { 0, };
+ GomFilter *filter;
+ char *str;
+
+ g_value_init (&value, G_TYPE_STRING);
+ str = g_strdup_printf ("%%%s%%", text);
+ g_value_set_string (&value, str);
+ g_free (str);
+
+ filter = gom_filter_new_like (BOOKMARKS_TYPE_RESOURCE, column, &value);
+ g_value_unset (&value);
+
+ return filter;
}
static void
-produce_bookmarks_from_category (OperationSpec *os, const gchar *category_id)
+produce_bookmarks_from_text (OperationSpec *os, const gchar *text)
{
- gchar *sql;
- GRL_DEBUG ("produce_bookmarks_from_category");
- sql = g_strdup_printf (GRL_SQL_GET_BOOKMARKS_BY_PARENT,
- category_id, os->count, os->skip);
- produce_bookmarks_from_sql (os, sql);
- g_free (sql);
+ GomFilter *like1, *like2, *likes, *type1, *filter;
+ GValue value = { 0, };
+
+ GRL_DEBUG ("produce_bookmarks_from_text");
+
+ /* WHERE (title LIKE '%text%' OR desc LIKE '%text%') AND type == BOOKMARKS_TYPE_STREAM */
+
+ like1 = substr_filter ("title", text);
+ like2 = substr_filter ("desc", text);
+ likes = gom_filter_new_or (like1, like2);
+ g_object_unref (like1);
+ g_object_unref (like2);
+
+ g_value_init (&value, G_TYPE_INT);
+ g_value_set_int (&value, BOOKMARKS_TYPE_STREAM);
+ type1 = gom_filter_new_eq (BOOKMARKS_TYPE_RESOURCE, "type", &value);
+ g_value_unset (&value);
+
+ filter = gom_filter_new_and (likes, type1);
+ g_object_unref (likes);
+ g_object_unref (type1);
+
+ produce_bookmarks_from_filter (os, filter);
+ g_object_unref (filter);
}
static void
@@ -581,31 +582,26 @@ remove_bookmark (GrlBookmarksSource *bookmarks_source,
GrlMedia *media,
GError **error)
{
- gint r;
- gchar *sql_error;
- gchar *sql;
+ GomResource *resource;
+ gint64 id;
+ GError *local_error = NULL;
GRL_DEBUG ("remove_bookmark");
- sql = g_strdup_printf (GRL_SQL_REMOVE_BOOKMARK, bookmark_id, bookmark_id);
- GRL_DEBUG ("%s", sql);
- r = sqlite3_exec (bookmarks_source->priv->db, sql, NULL, NULL, &sql_error);
- g_free (sql);
-
- if (r != SQLITE_OK) {
- GRL_WARNING ("Failed to remove bookmark '%s': %s", bookmark_id, sql_error);
+ id = g_ascii_strtoll (bookmark_id, NULL, 0);
+ resource = g_object_new (BOOKMARKS_TYPE_RESOURCE, "id", id,
+ "repository", bookmarks_source->priv->repository,
+ NULL);
+ if (!gom_resource_delete_sync (resource, &local_error)) {
+ GRL_WARNING ("Failed to remove bookmark '%s': %s", bookmark_id, local_error->message);
*error = g_error_new (GRL_CORE_ERROR,
GRL_CORE_ERROR_REMOVE_FAILED,
_("Failed to remove: %s"),
- sql_error);
- sqlite3_free (sql_error);
+ local_error->message);
+ g_error_free (local_error);
}
- /* Remove orphan nodes from database */
- GRL_DEBUG ("%s", GRL_SQL_REMOVE_ORPHAN);
- sqlite3_exec (bookmarks_source->priv->db,
- GRL_SQL_REMOVE_ORPHAN,
- NULL, NULL, NULL);
+ g_object_unref (resource);
if (bookmarks_source->priv->notify_changes) {
/* We can improve accuracy computing the parent container of removed
@@ -624,17 +620,19 @@ store_bookmark (GrlBookmarksSource *bookmarks_source,
GrlMedia *bookmark,
GError **error)
{
- gint r;
- sqlite3_stmt *sql_stmt = NULL;
+ GomResource *resource;
const gchar *title;
const gchar *url;
const gchar *desc;
GTimeVal now;
- const gchar *parent_id;
+ gint64 parent_id;
const gchar *mime;
gchar *date;
guint type;
- gchar *id;
+ gint64 id;
+ gchar *str_id;
+ GError *local_error = NULL;
+ gboolean ret;
GRL_DEBUG ("store_bookmark");
@@ -646,27 +644,12 @@ store_bookmark (GrlBookmarksSource *bookmarks_source,
date = g_time_val_to_iso8601 (&now);
if (!parent) {
- parent_id = "0";
+ parent_id = 0;
} else {
- parent_id = grl_media_get_id (GRL_MEDIA (parent));
+ parent_id = g_ascii_strtoll (grl_media_get_id (GRL_MEDIA (parent)), NULL, 0);
}
- if (!parent_id) {
- parent_id = "0";
- }
-
- GRL_DEBUG ("%s", GRL_SQL_STORE_BOOKMARK);
- r = sqlite3_prepare_v2 (bookmarks_source->priv->db,
- GRL_SQL_STORE_BOOKMARK,
- strlen (GRL_SQL_STORE_BOOKMARK),
- &sql_stmt, NULL);
- if (r != SQLITE_OK) {
- GRL_WARNING ("Failed to store bookmark '%s': %s", title,
- sqlite3_errmsg (bookmarks_source->priv->db));
- *error = g_error_new (GRL_CORE_ERROR,
- GRL_CORE_ERROR_STORE_FAILED,
- _("Failed to store: %s"),
- sqlite3_errmsg (bookmarks_source->priv->db));
- return;
+ if (parent_id < 0) {
+ parent_id = 0;
}
GRL_DEBUG ("URL: '%s'", url);
@@ -677,63 +660,59 @@ store_bookmark (GrlBookmarksSource *bookmarks_source,
type = BOOKMARK_TYPE_STREAM;
}
- sqlite3_bind_text (sql_stmt, BOOKMARK_PARENT, parent_id, -1, SQLITE_STATIC);
- sqlite3_bind_int (sql_stmt, BOOKMARK_TYPE, type);
+ resource = g_object_new (BOOKMARKS_TYPE_RESOURCE,
+ "repository", bookmarks_source->priv->repository,
+ "parent", parent_id,
+ "type", type,
+ NULL);
+
if (type == BOOKMARK_TYPE_STREAM) {
- sqlite3_bind_text (sql_stmt, BOOKMARK_URL, url, -1, SQLITE_STATIC);
+ g_object_set (G_OBJECT (resource), "url", url, NULL);
*keylist = g_list_remove (*keylist,
GRLKEYID_TO_POINTER (GRL_METADATA_KEY_URL));
- } else {
- sqlite3_bind_null (sql_stmt, BOOKMARK_URL);
}
if (title) {
- sqlite3_bind_text (sql_stmt, BOOKMARK_TITLE, title, -1, SQLITE_STATIC);
+ g_object_set (G_OBJECT (resource), "title", title, NULL);
*keylist = g_list_remove (*keylist,
GRLKEYID_TO_POINTER (GRL_METADATA_KEY_TITLE));
} else if (url) {
- sqlite3_bind_text (sql_stmt, BOOKMARK_TITLE, url, -1, SQLITE_STATIC);
+ g_object_set (G_OBJECT (resource), "title", url, NULL);
} else {
- sqlite3_bind_text (sql_stmt, BOOKMARK_TITLE, "(unknown)", -1, SQLITE_STATIC);
+ g_object_set (G_OBJECT (resource), "title", "(unknown)", NULL);
}
if (date) {
- sqlite3_bind_text (sql_stmt, BOOKMARK_DATE, date, -1, SQLITE_STATIC);
- } else {
- sqlite3_bind_null (sql_stmt, BOOKMARK_DATE);
+ g_object_set (G_OBJECT (resource), "date", date, NULL);
}
if (mime) {
- sqlite3_bind_text (sql_stmt, BOOKMARK_MIME, mime, -1, SQLITE_STATIC);
+ g_object_set (G_OBJECT (resource), "mime", mime, NULL);
*keylist = g_list_remove (*keylist,
GRLKEYID_TO_POINTER (GRL_METADATA_KEY_MIME));
- } else {
- sqlite3_bind_null (sql_stmt, BOOKMARK_MIME);
}
if (desc) {
- sqlite3_bind_text (sql_stmt, BOOKMARK_DESC, desc, -1, SQLITE_STATIC);
+ g_object_set (G_OBJECT (resource), "desc", desc, NULL);
*keylist = g_list_remove (*keylist,
GRLKEYID_TO_POINTER (GRL_METADATA_KEY_DESCRIPTION));
- } else {
- sqlite3_bind_null (sql_stmt, BOOKMARK_DESC);
}
- while ((r = sqlite3_step (sql_stmt)) == SQLITE_BUSY);
-
- if (r != SQLITE_DONE) {
+ ret = gom_resource_save_sync (resource, &local_error);
+ if (!ret) {
GRL_WARNING ("Failed to store bookmark '%s': %s", title,
- sqlite3_errmsg (bookmarks_source->priv->db));
+ local_error->message);
*error = g_error_new (GRL_CORE_ERROR,
GRL_CORE_ERROR_STORE_FAILED,
_("Failed to store: %s"),
- sqlite3_errmsg (bookmarks_source->priv->db));
- sqlite3_finalize (sql_stmt);
+ local_error->message);
+ g_error_free (local_error);
+ g_object_unref (resource);
return;
}
- sqlite3_finalize (sql_stmt);
+ g_object_get (resource, "id", &id, NULL);
+ str_id = g_strdup_printf ("%" G_GINT64_FORMAT, id);
+ grl_media_set_id (bookmark, str_id);
+ g_free (str_id);
- id = g_strdup_printf ("%llu",
- sqlite3_last_insert_rowid (bookmarks_source->priv->db));
- grl_media_set_id (bookmark, id);
- g_free (id);
+ g_object_unref (resource);
if (bookmarks_source->priv->notify_changes) {
grl_source_notify_change (GRL_SOURCE (bookmarks_source),
@@ -772,7 +751,7 @@ grl_bookmarks_source_browse (GrlSource *source,
GError *error = NULL;
bookmarks_source = GRL_BOOKMARKS_SOURCE (source);
- if (!bookmarks_source->priv->db) {
+ if (!bookmarks_source->priv->adapter) {
GRL_WARNING ("Can't execute operation: no database connection.");
error = g_error_new_literal (GRL_CORE_ERROR,
GRL_CORE_ERROR_BROWSE_FAILED,
@@ -793,7 +772,6 @@ grl_bookmarks_source_browse (GrlSource *source,
os->error_code = GRL_CORE_ERROR_BROWSE_FAILED;
produce_bookmarks_from_category (os, os->media_id ? os->media_id : "0");
- g_slice_free (OperationSpec, os);
}
static void
@@ -807,7 +785,7 @@ grl_bookmarks_source_search (GrlSource *source,
GError *error = NULL;
bookmarks_source = GRL_BOOKMARKS_SOURCE (source);
- if (!bookmarks_source->priv->db) {
+ if (!bookmarks_source->priv->adapter) {
GRL_WARNING ("Can't execute operation: no database connection.");
error = g_error_new_literal (GRL_CORE_ERROR,
GRL_CORE_ERROR_QUERY_FAILED,
@@ -824,8 +802,7 @@ grl_bookmarks_source_search (GrlSource *source,
os->callback = ss->callback;
os->user_data = ss->user_data;
os->error_code = GRL_CORE_ERROR_SEARCH_FAILED;
- produce_bookmarks_by_text (os, ss->text);
- g_slice_free (OperationSpec, os);
+ produce_bookmarks_from_text (os, ss->text);
}
static void
@@ -839,7 +816,7 @@ grl_bookmarks_source_query (GrlSource *source,
GError *error = NULL;
bookmarks_source = GRL_BOOKMARKS_SOURCE (source);
- if (!bookmarks_source->priv->db) {
+ if (!bookmarks_source->priv->adapter) {
GRL_WARNING ("Can't execute operation: no database connection.");
error = g_error_new_literal (GRL_CORE_ERROR,
GRL_CORE_ERROR_QUERY_FAILED,
@@ -856,8 +833,7 @@ grl_bookmarks_source_query (GrlSource *source,
os->callback = qs->callback;
os->user_data = qs->user_data;
os->error_code = GRL_CORE_ERROR_SEARCH_FAILED;
- produce_bookmarks_by_query (os, qs->query);
- g_slice_free (OperationSpec, os);
+ produce_bookmarks_from_query (os, qs->query);
}
static void
@@ -882,7 +858,7 @@ static void grl_bookmarks_source_remove (GrlSource *source,
GRL_DEBUG (__FUNCTION__);
GError *error = NULL;
remove_bookmark (GRL_BOOKMARKS_SOURCE (rs->source),
- rs->media_id, rs->media, &error);
+ rs->media_id, rs->media, &error);
rs->callback (rs->source, rs->media, rs->user_data, error);
g_clear_error (&error);
}
@@ -897,7 +873,7 @@ grl_bookmarks_source_resolve (GrlSource *source,
GError *error = NULL;
bookmarks_source = GRL_BOOKMARKS_SOURCE (source);
- if (!bookmarks_source->priv->db) {
+ if (!bookmarks_source->priv->repository) {
GRL_WARNING ("Can't execute operation: no database connection.");
error = g_error_new_literal (GRL_CORE_ERROR,
GRL_CORE_ERROR_RESOLVE_FAILED,