[folks] Tidy up UIDs and IIDs in the backends
- From: Travis Reitter <treitter src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [folks] Tidy up UIDs and IIDs in the backends
- Date: Tue, 3 Aug 2010 21:22:13 +0000 (UTC)
commit 6e9544b47635d2128549241709c2cc169943a278
Author: Philip Withnall <philip withnall collabora co uk>
Date: Tue Jul 20 17:51:46 2010 +0100
Tidy up UIDs and IIDs in the backends
IIDs are now defined as unique within a backend, and formatted to make them
most useful for linking. UIDs are now defined as unique across all backends,
and formatted as Backend.name:PersonaStore.id:Persona ID.
backends/key-file/kf-persona.vala | 11 ++--
backends/telepathy/tpf-persona.vala | 17 +++---
folks/individual-aggregator.vala | 12 ++--
folks/persona.vala | 102 +++++++++++++++++++++++++++++++++-
4 files changed, 119 insertions(+), 23 deletions(-)
---
diff --git a/backends/key-file/kf-persona.vala b/backends/key-file/kf-persona.vala
index a40dd0a..8f755f1 100644
--- a/backends/key-file/kf-persona.vala
+++ b/backends/key-file/kf-persona.vala
@@ -80,13 +80,12 @@ public class Folks.Backends.Kf.Persona : Folks.Persona,
* Create a new persona for the { link PersonaStore} `store`, representing
* the Persona given by the group `uid` in the key file `key_file`.
*/
- public Persona (KeyFile key_file, string uid, Folks.PersonaStore store)
+ public Persona (KeyFile key_file, string id, Folks.PersonaStore store)
{
- string iid = "key-file:" + uid;
string[] linkable_properties = { "im-addresses" };
- Object (iid: iid,
- uid: uid,
+ Object (iid: id,
+ uid: this.build_uid ("key-file", store.id, id),
store: store,
linkable_properties: linkable_properties);
@@ -97,10 +96,10 @@ public class Folks.Backends.Kf.Persona : Folks.Persona,
/* Load the IM addresses from the key file */
try
{
- string[] keys = this.key_file.get_keys (uid);
+ string[] keys = this.key_file.get_keys (id);
foreach (string protocol in keys)
{
- string[] im_addresses = this.key_file.get_string_list (uid,
+ string[] im_addresses = this.key_file.get_string_list (id,
protocol);
/* FIXME: We have to convert our nice efficient string[] to a
diff --git a/backends/telepathy/tpf-persona.vala b/backends/telepathy/tpf-persona.vala
index 14d7d63..f6fdf79 100644
--- a/backends/telepathy/tpf-persona.vala
+++ b/backends/telepathy/tpf-persona.vala
@@ -173,16 +173,13 @@ public class Tpf.Persona : Folks.Persona,
/* FIXME: There is the possibility of a crash in the error condition below
* due to bgo#604299, where the C self variable isn't initialised until we
* chain up to the Object constructor, below. */
- var uid = contact.get_identifier ();
- if (uid == null || uid == "")
+ unowned string id = contact.get_identifier ();
+ if (id == null || id == "")
throw new Tpf.PersonaError.INVALID_ARGUMENT ("contact has an " +
- "invalid UID");
+ "invalid ID");
var account = account_for_connection (contact.get_connection ());
- var account_id = ((Proxy) account).object_path;
- /* this isn't meant to convey any real information, so no need to escape
- * existing delimiters */
- var iid = "telepathy:" + account_id + ":" + uid;
+ string uid = this.build_uid ("telepathy", account.get_protocol (), id);
var alias = contact.get_alias ();
if (alias == null || alias.strip () == "")
@@ -190,7 +187,11 @@ public class Tpf.Persona : Folks.Persona,
Object (alias: alias,
contact: contact,
- iid: iid,
+ /* FIXME: This IID format should be moved out to the IMable
+ * interface along with the code in
+ * Kf.Persona.linkable_property_to_links(), but that depends on
+ * bgo#624842 being fixed. */
+ iid: account.get_protocol () + ":" + id,
uid: uid,
store: store);
diff --git a/folks/individual-aggregator.vala b/folks/individual-aggregator.vala
index 9f900e0..4f79a79 100644
--- a/folks/individual-aggregator.vala
+++ b/folks/individual-aggregator.vala
@@ -213,11 +213,11 @@ public class Folks.IndividualAggregator : Object
/* If we don't trust the PersonaStore at all, we can't link the
* Persona to any existing Individual */
if (trust_level != PersonaStoreTrust.NONE)
- candidate_ind = this.link_map.lookup (persona.uid);
+ candidate_ind = this.link_map.lookup (persona.iid);
if (candidate_ind != null)
{
- /* The Persona's UID matches a linkable field which is already in
+ /* The Persona's IID matches a linkable field which is already in
* the link map, so we add the new Persona to that Individual. */
GLib.List<unowned Persona> personas =
candidate_ind.personas.copy ();
@@ -237,12 +237,12 @@ public class Folks.IndividualAggregator : Object
new_individuals.prepend (candidate_ind);
this.individuals.insert (candidate_ind.id, candidate_ind);
- /* Only add the Persona to the link map if we trust its UID. */
+ /* Only add the Persona to the link map if we trust its IID. */
if (trust_level != PersonaStoreTrust.NONE)
- this.link_map.insert (persona.uid, candidate_ind);
+ this.link_map.insert (persona.iid, candidate_ind);
}
- /* Only allow linking on non-UID properties of the Persona if we fully
+ /* Only allow linking on non-IID properties of the Persona if we fully
* trust the PersonaStore it came from. */
if (persona.store.trust_level == PersonaStoreTrust.FULL)
{
@@ -272,7 +272,7 @@ public class Folks.IndividualAggregator : Object
PersonaStoreTrust trust_level = persona.store.trust_level;
if (trust_level != PersonaStoreTrust.NONE)
- this.link_map.remove (persona.uid);
+ this.link_map.remove (persona.iid);
if (trust_level == PersonaStoreTrust.FULL)
{
diff --git a/folks/persona.vala b/folks/persona.vala
index f79b1dd..4f43e70 100644
--- a/folks/persona.vala
+++ b/folks/persona.vala
@@ -30,20 +30,39 @@ using Folks;
public abstract class Folks.Persona : Object
{
/**
- * The internal ID used to represent the Persona within its { link Backend}.
+ * The internal ID used to represent the Persona for linking.
*
- * This should not be used by client code.
+ * This is opaque, and shouldn't be parsed or considered meaningful by
+ * clients.
+ *
+ * The internal ID should be unique within a backend, but may not be unique
+ * across backends, so that links can be made between Personas with similar
+ * internal IDs.
*/
+ /* For example: jabber:foo xmpp example org or joe example org */
public string iid { get; construct; }
/**
* The universal ID used to represent the Persona outside its { link Backend}.
*
- * For example: `foo@@xmpp.example.org`.
+ * This is opaque, and should only be parsed by clients using
+ * { link Persona.split_uid}.
*
* This is the canonical way to refer to any Persona. It is guaranteed to be
* unique within the Persona's { link PersonaStore}.
+ *
+ * @see Persona.build_uid
+ * @see Persona.split_uid
*/
+ /* For example: telepathy:jabber:foo xmpp example org or
+ * key-file:relationships.ini:joe example org
+ *
+ * It comprises three components, separated by colons:
+ * # { link Backend.name}
+ * # { link PersonaStore.id}
+ * # Persona identifier
+ * Each component is escaped by replacing all colons with double underscores
+ * before building the UID.*/
public string uid { get; construct; }
/**
@@ -101,4 +120,81 @@ public abstract class Folks.Persona : Object
* any linkable properties */
assert_not_reached ();
}
+
+ private static string escape_uid_component (string component)
+ {
+ /* Escape colons with backslashes */
+ string escaped = component.replace ("\\", "\\\\");
+ return escaped.replace (":", "\\:");
+ }
+
+ private static string unescape_uid_component (string component)
+ {
+ /* Unescape colons and backslashes */
+ string unescaped = component.replace ("\\:", ":");
+ return unescaped.replace ("\\", "\\\\");
+ }
+
+ /**
+ * Build a UID from the given components.
+ *
+ * Each component is escaped before the UID is built.
+ *
+ * @param backend_name the { link Backend.name}
+ * @param persona_store_id the { link PersonaStore.id}
+ * @param persona_id the Persona identifier (backend-specific)
+ * @return a valid UID
+ * @see Persona.split_uid
+ */
+ public static string build_uid (string backend_name,
+ string persona_store_id, string persona_id)
+ {
+ return "%s:%s:%s".printf (Persona.escape_uid_component (backend_name),
+ Persona.escape_uid_component (persona_store_id),
+ Persona.escape_uid_component (persona_id));
+ }
+
+ /**
+ * Split a UID into its component parts.
+ *
+ * Each component is unescaped before being returned. The UID //must// be
+ * correctly formed.
+ *
+ * @param uid a valid UID
+ * @param backend_name the { link Backend.name}
+ * @param persona_store_id the { link PersonaStore.id}
+ * @param persona_id the Persona identifier (backend-specific)
+ * @see Persona.build_uid
+ */
+ public static void split_uid (string uid, out string backend_name,
+ out string persona_store_id, out string persona_id)
+ {
+ assert (uid.validate ());
+
+ size_t backend_name_length = 0, persona_store_id_length = 0;
+ bool escaped = false;
+ for (unowned string i = uid; i.get_char () != '\0'; i = i.next_char ())
+ {
+ if (i.get_char () == '\\')
+ escaped = !escaped;
+ else if (escaped == false && i.get_char () == ':')
+ {
+ if (backend_name_length == 0)
+ backend_name_length = ((char*) i) - ((char*) uid);
+ else
+ persona_store_id_length = ((char*) i) - ((char*) uid);
+ }
+ }
+
+ assert (backend_name_length != 0 && persona_store_id_length != 0);
+
+ backend_name = Persona.unescape_uid_component (
+ uid.ndup (backend_name_length));
+ persona_store_id = Persona.unescape_uid_component (
+ ((string) ((char*) uid + backend_name_length + 1)).ndup (
+ persona_store_id_length));
+ persona_id = Persona.unescape_uid_component (
+ ((string) ((char*) uid + backend_name_length +
+ persona_store_id_length + 2)));
+ }
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]