[epiphany/wip/sync: 73/86] bookmark: Implement EphySynchronizable
- From: Gabriel Ivașcu <gabrielivascu src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [epiphany/wip/sync: 73/86] bookmark: Implement EphySynchronizable
- Date: Tue, 28 Mar 2017 21:00:03 +0000 (UTC)
commit 17b7d62dba47c2216381644c2d511a370383399a
Author: Gabriel Ivascu <ivascu gabriel59 gmail com>
Date: Tue Mar 21 13:37:47 2017 +0200
bookmark: Implement EphySynchronizable
Note that ID is now a property
src/bookmarks/ephy-add-bookmark-popover.c | 5 +-
src/bookmarks/ephy-bookmark.c | 124 ++++++++++++++++++++------
src/bookmarks/ephy-bookmark.h | 3 +-
src/bookmarks/ephy-bookmarks-import.c | 8 +-
src/profile-migrator/Makefile.am | 1 +
src/profile-migrator/ephy-profile-migrator.c | 7 ++-
src/sync/ephy-sync-crypto.c | 94 +++++++++++--------
src/sync/ephy-sync-crypto.h | 4 +-
8 files changed, 167 insertions(+), 79 deletions(-)
---
diff --git a/src/bookmarks/ephy-add-bookmark-popover.c b/src/bookmarks/ephy-add-bookmark-popover.c
index 5042934..d9054c7 100644
--- a/src/bookmarks/ephy-add-bookmark-popover.c
+++ b/src/bookmarks/ephy-add-bookmark-popover.c
@@ -215,10 +215,13 @@ ephy_add_bookmark_popover_show (EphyAddBookmarkPopover *self)
self->bookmark = ephy_bookmarks_manager_get_bookmark_by_url (manager, address);
if (!self->bookmark) {
+ char *id = ephy_sync_crypto_get_random_sync_id ();
self->bookmark = ephy_bookmark_new (address,
ephy_embed_get_title (embed),
- g_sequence_new (g_free));
+ g_sequence_new (g_free),
+ id);
self->is_new_bookmark = TRUE;
+ g_free (id);
}
g_signal_connect_object (manager, "bookmark-removed",
diff --git a/src/bookmarks/ephy-bookmark.c b/src/bookmarks/ephy-bookmark.c
index 509276c..198118a 100644
--- a/src/bookmarks/ephy-bookmark.c
+++ b/src/bookmarks/ephy-bookmark.c
@@ -27,12 +27,11 @@
#include <string.h>
#ifdef ENABLE_SYNC
+#include "ephy-synchronizable.h"
#include "ephy-sync-crypto.h"
#include "ephy-sync-utils.h"
#endif
-#define ID_LEN 32
-
struct _EphyBookmark {
GObject parent_instance;
@@ -49,12 +48,16 @@ struct _EphyBookmark {
};
static JsonSerializableIface *serializable_iface = NULL;
+static EphySynchronizableInterface *synchronizable_iface = NULL;
static void json_serializable_iface_init (gpointer g_iface);
+static void ephy_synchronizable_iface_init (EphySynchronizableInterface *iface);
G_DEFINE_TYPE_WITH_CODE (EphyBookmark, ephy_bookmark, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (JSON_TYPE_SERIALIZABLE,
- json_serializable_iface_init))
+ json_serializable_iface_init)
+ G_IMPLEMENT_INTERFACE (EPHY_TYPE_SYNCHRONIZABLE,
+ ephy_synchronizable_iface_init))
enum {
PROP_0,
@@ -62,7 +65,9 @@ enum {
PROP_TIME_ADDED,
PROP_TITLE,
PROP_URL,
- LAST_PROP
+ LAST_PROP,
+ /* Firefox related properties. */
+ PROP_ID
};
enum {
@@ -97,6 +102,9 @@ ephy_bookmark_set_property (GObject *object,
case PROP_URL:
ephy_bookmark_set_url (self, g_value_get_string (value));
break;
+ case PROP_ID:
+ ephy_bookmark_set_id (self, g_value_get_string (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -123,6 +131,9 @@ ephy_bookmark_get_property (GObject *object,
case PROP_URL:
g_value_set_string (value, ephy_bookmark_get_url (self));
break;
+ case PROP_ID:
+ g_value_set_string (value, ephy_bookmark_get_id (self));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -181,6 +192,7 @@ ephy_bookmark_class_init (EphyBookmarkClass *klass)
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, LAST_PROP, obj_properties);
+ g_object_class_override_property (object_class, PROP_ID, "id");
signals[TAG_ADDED] =
g_signal_new ("tag-added",
@@ -204,30 +216,6 @@ ephy_bookmark_class_init (EphyBookmarkClass *klass)
static void
ephy_bookmark_init (EphyBookmark *self)
{
-#ifdef ENABLE_SYNC
- self->id = g_malloc0 (ID_LEN + 1);
- ephy_sync_crypto_random_hex_gen (NULL, ID_LEN, (guint8 *)self->id);
-#else
- static const char hex_digits[] = "0123456789abcdef";
- FILE *fp;
- gsize num_bytes;
- guint8 *bytes;
-
- num_bytes = (ID_LEN + 1) / 2;
- bytes = g_malloc (num_bytes);
-
- fp = fopen ("/dev/urandom", "r");
- fread (bytes, sizeof (guint8), num_bytes, fp);
-
- self->id = g_malloc0 (ID_LEN + 1);
- for (gsize i = 0; i < num_bytes; i++) {
- self->id[2 * i] = hex_digits[bytes[i] >> 4];
- self->id[2 * i + 1] = hex_digits[bytes[i] & 0xf];
- }
-
- g_free (bytes);
- fclose (fp);
-#endif
}
static JsonNode *
@@ -304,14 +292,92 @@ json_serializable_iface_init (gpointer g_iface)
iface->deserialize_property = ephy_bookmark_json_serializable_deserialize_property;
}
+static const char *
+ephy_bookmark_synchronizable_get_id (EphySynchronizable *synchronizable)
+{
+ EphyBookmark *bookmark = EPHY_BOOKMARK (synchronizable);
+
+ return bookmark->id;
+}
+
+static void
+ephy_bookmark_synchronizable_set_id (EphySynchronizable *synchronizable,
+ const char *id)
+{
+ EphyBookmark *bookmark = EPHY_BOOKMARK (synchronizable);
+
+ g_free (bookmark->id);
+ bookmark->id = g_strdup (id);
+}
+
+static double
+ephy_bookmark_synchronizable_get_modification_time (EphySynchronizable *synchronizable)
+{
+ EphyBookmark *bookmark = EPHY_BOOKMARK (synchronizable);
+
+ return bookmark->modified;
+}
+
+static void
+ephy_bookmark_synchronizable_set_modification_time (EphySynchronizable *synchronizable,
+ double modified)
+{
+ EphyBookmark *bookmark = EPHY_BOOKMARK (synchronizable);
+
+ bookmark->modified = modified;
+}
+
+static gboolean
+ephy_bookmark_synchronizable_is_uploaded (EphySynchronizable *synchronizable)
+{
+ EphyBookmark *bookmark = EPHY_BOOKMARK (synchronizable);
+
+ return bookmark->uploaded;
+}
+
+static void
+ephy_bookmark_synchronizable_set_is_uploaded (EphySynchronizable *synchronizable,
+ gboolean uploaded)
+{
+
+ EphyBookmark *bookmark = EPHY_BOOKMARK (synchronizable);
+
+ bookmark->uploaded = uploaded;
+}
+
+static char *
+ephy_bookmark_synchronizable_to_bso (EphySynchronizable *synchronizable,
+ GError **error)
+{
+ return NULL;
+}
+
+static void
+ephy_synchronizable_iface_init (EphySynchronizableInterface *iface)
+{
+ synchronizable_iface = g_type_default_interface_peek (EPHY_TYPE_SYNCHRONIZABLE);
+
+ iface->get_id = ephy_bookmark_synchronizable_get_id;
+ iface->set_id = ephy_bookmark_synchronizable_set_id;
+ iface->get_modification_time = ephy_bookmark_synchronizable_get_modification_time;
+ iface->set_modification_time = ephy_bookmark_synchronizable_set_modification_time;
+ iface->is_uploaded = ephy_bookmark_synchronizable_is_uploaded;
+ iface->set_is_uploaded = ephy_bookmark_synchronizable_set_is_uploaded;
+ iface->to_bso = ephy_bookmark_synchronizable_to_bso;
+}
+
EphyBookmark *
-ephy_bookmark_new (const char *url, const char *title, GSequence *tags)
+ephy_bookmark_new (const char *url,
+ const char *title,
+ GSequence *tags,
+ const char *id)
{
return g_object_new (EPHY_TYPE_BOOKMARK,
"url", url,
"title", title,
"tags", tags,
"time-added", g_get_real_time (),
+ "id", id,
NULL);
}
diff --git a/src/bookmarks/ephy-bookmark.h b/src/bookmarks/ephy-bookmark.h
index 8ce771e..328f6a8 100644
--- a/src/bookmarks/ephy-bookmark.h
+++ b/src/bookmarks/ephy-bookmark.h
@@ -31,7 +31,8 @@ G_DECLARE_FINAL_TYPE (EphyBookmark, ephy_bookmark, EPHY, BOOKMARK, GObject)
EphyBookmark *ephy_bookmark_new (const char *url,
const char *title,
- GSequence *tags);
+ GSequence *tags,
+ const char *id);
void ephy_bookmark_set_time_added (EphyBookmark *self,
gint64 time_added);
diff --git a/src/bookmarks/ephy-bookmarks-import.c b/src/bookmarks/ephy-bookmarks-import.c
index 8d252f8..f805db2 100644
--- a/src/bookmarks/ephy-bookmarks-import.c
+++ b/src/bookmarks/ephy-bookmarks-import.c
@@ -77,9 +77,8 @@ get_bookmarks_from_table (GvdbTable *table)
g_variant_iter_free (iter);
/* Create the new bookmark. */
- bookmark = ephy_bookmark_new (list[i], title, tags);
+ bookmark = ephy_bookmark_new (list[i], title, tags, id);
ephy_bookmark_set_time_added (bookmark, time_added);
- ephy_bookmark_set_id (bookmark, id);
ephy_bookmark_set_modification_time (bookmark, modified);
ephy_bookmark_set_is_uploaded (bookmark, uploaded);
g_sequence_prepend (bookmarks, bookmark);
@@ -214,7 +213,7 @@ ephy_bookmarks_import_from_firefox (EphyBookmarksManager *manager,
GSequence *bookmarks = NULL;
gboolean ret = TRUE;
gchar *filename;
- const char *statement_str = "SELECT b.id, p.url, b.title, b.dateAdded "
+ const char *statement_str = "SELECT b.id, p.url, b.title, b.dateAdded, b.guid "
"FROM moz_bookmarks b "
"JOIN moz_places p ON b.fk=p.id "
"WHERE b.type=1 AND p.url NOT LIKE 'about%' "
@@ -260,11 +259,12 @@ ephy_bookmarks_import_from_firefox (EphyBookmarksManager *manager,
const char *url = ephy_sqlite_statement_get_column_as_string (statement, 1);
const char *title = ephy_sqlite_statement_get_column_as_string (statement, 2);
gint64 time_added = ephy_sqlite_statement_get_column_as_int64 (statement, 3);
+ const char *guid = ephy_sqlite_statement_get_column_as_string (statement, 4);
EphyBookmark *bookmark;
GSequence *tags;
tags = g_sequence_new (g_free);
- bookmark = ephy_bookmark_new (url, title, tags);
+ bookmark = ephy_bookmark_new (url, title, tags, guid);
ephy_bookmark_set_time_added (bookmark, time_added);
load_tags_for_bookmark (connection, bookmark, bookmark_id);
diff --git a/src/profile-migrator/Makefile.am b/src/profile-migrator/Makefile.am
index 8cf59bd..24a2709 100644
--- a/src/profile-migrator/Makefile.am
+++ b/src/profile-migrator/Makefile.am
@@ -13,6 +13,7 @@ ephy_profile_migrator_CPPFLAGS = \
-I$(top_srcdir)/lib/history \
-I$(top_srcdir)/src/ \
-I$(top_srcdir)/src/bookmarks \
+ -I$(top_srcdir)/src/sync \
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \
-DLOCALEDIR=\"$(localedir)\" \
$(GLIB_CFLAGS) \
diff --git a/src/profile-migrator/ephy-profile-migrator.c b/src/profile-migrator/ephy-profile-migrator.c
index 0dcf135..9c44247 100644
--- a/src/profile-migrator/ephy-profile-migrator.c
+++ b/src/profile-migrator/ephy-profile-migrator.c
@@ -41,6 +41,7 @@
#include "ephy-search-engine-manager.h"
#include "ephy-settings.h"
#include "ephy-sqlite-connection.h"
+#include "ephy-sync-crypto.h"
#include "ephy-uri-tester-shared.h"
#include "ephy-web-app-utils.h"
@@ -641,10 +642,14 @@ parse_rdf_item (EphyBookmarksManager *manager,
if (link) {
EphyBookmark *bookmark;
+ char *id;
g_sequence_sort (tags, (GCompareDataFunc)ephy_bookmark_tags_compare, NULL);
- bookmark = ephy_bookmark_new ((const char *)link, (const char *)title, tags);
+ id = ephy_sync_crypto_get_random_sync_id ();
+ bookmark = ephy_bookmark_new ((const char *)link, (const char *)title, tags, id);
ephy_bookmarks_manager_add_bookmark (manager, bookmark);
+
+ g_free (id);
} else {
g_sequence_free (tags);
}
diff --git a/src/sync/ephy-sync-crypto.c b/src/sync/ephy-sync-crypto.c
index 13b7cc2..2b4bef5 100644
--- a/src/sync/ephy-sync-crypto.c
+++ b/src/sync/ephy-sync-crypto.c
@@ -33,6 +33,7 @@
#define HAWK_VERSION 1
#define NONCE_LEN 6
#define IV_LEN 16
+#define SYNC_ID_LEN 12
static const char hex_digits[] = "0123456789abcdef";
@@ -655,6 +656,27 @@ ephy_sync_crypto_hmac_is_valid (const char *text,
return retval;
}
+/*
+ * This function is required by Nettle's RSA support.
+ * From Nettle's documentation: random_ctx and random is a randomness generator.
+ * random(random_ctx, length, dst) should generate length random octets and store them at dst.
+ * We don't really use random_ctx, since we have /dev/urandom available.
+ */
+static void
+ephy_sync_crypto_random_bytes_gen (void *random_ctx,
+ gsize length,
+ guint8 *dst)
+{
+ FILE *fp;
+
+ g_assert (length > 0);
+ g_assert (dst);
+
+ fp = fopen ("/dev/urandom", "r");
+ fread (dst, sizeof (guint8), length, fp);
+ fclose (fp);
+}
+
void
ephy_sync_crypto_process_key_fetch_token (const char *keyFetchToken,
guint8 **tokenID,
@@ -935,7 +957,6 @@ ephy_sync_crypto_encrypt_record (const char *cleartext,
SyncCryptoKeyBundle *bundle)
{
char *payload = NULL;
- char *iv_hex;
char *iv_b64;
char *ciphertext_b64;
char *hmac;
@@ -957,13 +978,8 @@ ephy_sync_crypto_encrypt_record (const char *cleartext,
}
/* Generate a random 16 bytes initialization vector. */
- iv_hex = g_malloc0 (2 * IV_LEN + 1);
- ephy_sync_crypto_random_hex_gen (NULL, 2 * IV_LEN, (guint8 *)iv_hex);
- iv = ephy_sync_crypto_decode_hex (iv_hex);
- if (!iv) {
- g_warning ("Failed to decode the hex value of IV");
- goto free_iv;
- }
+ iv = g_malloc (IV_LEN);
+ ephy_sync_crypto_random_bytes_gen (NULL, IV_LEN, iv);
/* Encrypt the record using the AES key. */
ciphertext = ephy_sync_crypto_aes_256_encrypt (cleartext, aes_key, iv, &ciphertext_len);
@@ -984,9 +1000,7 @@ ephy_sync_crypto_encrypt_record (const char *cleartext,
g_free (iv_b64);
g_free (ciphertext_b64);
g_free (ciphertext);
-free_iv:
g_free (iv);
- g_free (iv_hex);
free_keys:
g_free (aes_key);
g_free (hmac_key);
@@ -1012,6 +1026,7 @@ ephy_sync_crypto_compute_hawk_header (const char *url,
char *nonce;
char *payload;
char *timestamp;
+ guint8 *bytes;
gint64 ts;
g_return_val_if_fail (url, NULL);
@@ -1033,8 +1048,10 @@ ephy_sync_crypto_compute_hawk_header (const char *url,
if (options && options->nonce) {
nonce = g_strdup (options->nonce);
} else {
- nonce = g_malloc0 (NONCE_LEN + 1);
- ephy_sync_crypto_random_hex_gen (NULL, NONCE_LEN, (guint8 *)nonce);
+ bytes = g_malloc (NONCE_LEN / 2);
+ ephy_sync_crypto_random_bytes_gen (NULL, NONCE_LEN / 2, bytes);
+ nonce = ephy_sync_crypto_encode_hex (bytes, NONCE_LEN / 2);
+ g_free (bytes);
}
if (timestamp) {
@@ -1127,7 +1144,7 @@ ephy_sync_crypto_generate_rsa_key_pair (void)
/* Key sizes below 2048 are considered breakable and should not be used. */
retval = rsa_generate_keypair (&public, &private,
- NULL, ephy_sync_crypto_random_hex_gen,
+ NULL, ephy_sync_crypto_random_bytes_gen,
NULL, NULL, 2048, 0);
if (retval == 0) {
g_warning ("Failed to generate RSA key pair");
@@ -1178,7 +1195,7 @@ ephy_sync_crypto_create_assertion (const char *certificate,
/* Use the provided key pair to RSA sign the message. */
mpz_init (signature);
if (rsa_sha256_sign_digest_tr (&keypair->public, &keypair->private,
- NULL, ephy_sync_crypto_random_hex_gen,
+ NULL, ephy_sync_crypto_random_bytes_gen,
digest, signature) == 0) {
g_warning ("Failed to sign the message. Giving up.");
goto out;
@@ -1211,32 +1228,6 @@ out:
return assertion;
}
-void
-ephy_sync_crypto_random_hex_gen (void *ctx,
- gsize length,
- guint8 *dst)
-{
- FILE *fp;
- gsize num_bytes;
- guint8 *bytes;
- char *hex;
-
- g_assert (length > 0);
- num_bytes = (length + 1) / 2;
- bytes = g_malloc (num_bytes);
-
- fp = fopen ("/dev/urandom", "r");
- fread (bytes, sizeof (guint8), num_bytes, fp);
- hex = ephy_sync_crypto_encode_hex (bytes, num_bytes);
-
- for (gsize i = 0; i < length; i++)
- dst[i] = hex[i];
-
- g_free (bytes);
- g_free (hex);
- fclose (fp);
-}
-
char *
ephy_sync_crypto_base64_urlsafe_encode (const guint8 *data,
gsize data_len,
@@ -1379,3 +1370,26 @@ ephy_sync_crypto_decode_hex (const char *hex)
return retval;
}
+
+char *
+ephy_sync_crypto_get_random_sync_id (void)
+{
+ char *id;
+ char *base64;
+ guint8 *bytes;
+ gsize bytes_len;
+
+ /* The sync id is a base64-urlsafe string. Base64 uses 4 chars to represent 3 bytes,
+ * therefore we need ceil(len * 3 / 4) bytes to cover the requested length. */
+ bytes_len = (SYNC_ID_LEN + 3) / 4 * 3;
+ bytes = g_malloc (bytes_len);
+
+ ephy_sync_crypto_random_bytes_gen (NULL, bytes_len, bytes);
+ base64 = ephy_sync_crypto_base64_urlsafe_encode (bytes, bytes_len, FALSE);
+ id = g_strndup (base64, SYNC_ID_LEN);
+
+ g_free (base64);
+ g_free (bytes);
+
+ return id;
+}
diff --git a/src/sync/ephy-sync-crypto.h b/src/sync/ephy-sync-crypto.h
index fda35d0..6668449 100644
--- a/src/sync/ephy-sync-crypto.h
+++ b/src/sync/ephy-sync-crypto.h
@@ -119,9 +119,6 @@ char *ephy_sync_crypto_create_assertion (const char
const char *audience,
guint64 duration,
SyncCryptoRSAKeyPair *keypair);
-void ephy_sync_crypto_random_hex_gen (void *ctx,
- gsize length,
- guint8 *dst);
char *ephy_sync_crypto_base64_urlsafe_encode (const guint8 *data,
gsize data_len,
gboolean strip);
@@ -136,5 +133,6 @@ guint8 *ephy_sync_crypto_aes_256 (SyncCryptoAES
char *ephy_sync_crypto_encode_hex (const guint8 *data,
gsize data_len);
guint8 *ephy_sync_crypto_decode_hex (const char *hex);
+char *ephy_sync_crypto_get_random_sync_id (void);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]