summaryrefslogtreecommitdiff
path: root/backends/bluez/bluez-persona.vala
diff options
context:
space:
mode:
Diffstat (limited to 'backends/bluez/bluez-persona.vala')
-rw-r--r--backends/bluez/bluez-persona.vala305
1 files changed, 182 insertions, 123 deletions
diff --git a/backends/bluez/bluez-persona.vala b/backends/bluez/bluez-persona.vala
index b93eb469..ac6e2d5c 100644
--- a/backends/bluez/bluez-persona.vala
+++ b/backends/bluez/bluez-persona.vala
@@ -41,17 +41,6 @@ public class Folks.Backends.BlueZ.Persona : Folks.Persona,
PhoneDetails,
UrlDetails
{
- private StructuredName? _structured_name = null;
- private string _full_name = "";
- private string _nickname = "";
- private Set<UrlFieldDetails>? _urls = null;
- private Set<UrlFieldDetails>? _urls_ro = null;
- private LoadableIcon? _avatar = null;
- private HashSet<PhoneFieldDetails> _phone_numbers;
- private Set<PhoneFieldDetails> _phone_numbers_ro;
- private HashSet<EmailFieldDetails> _email_addresses;
- private Set<EmailFieldDetails> _email_addresses_ro;
-
private const string[] _linkable_properties =
{
"phone-numbers",
@@ -69,6 +58,9 @@ public class Folks.Backends.BlueZ.Persona : Folks.Persona,
get { return BlueZ.Persona._linkable_properties; }
}
+ private SmallSet<UrlFieldDetails>? _urls = null;
+ private Set<UrlFieldDetails> _urls_ro;
+
/**
* {@inheritDoc}
*
@@ -81,6 +73,8 @@ public class Folks.Backends.BlueZ.Persona : Folks.Persona,
set { this.change_urls.begin (value); } /* not writeable */
}
+ private LoadableIcon? _avatar = null;
+
/**
* {@inheritDoc}
*
@@ -103,6 +97,9 @@ public class Folks.Backends.BlueZ.Persona : Folks.Persona,
get { return BlueZ.Persona._writeable_properties; }
}
+ private SmallSet<PhoneFieldDetails>? _phone_numbers = null;
+ private Set<PhoneFieldDetails> _phone_numbers_ro;
+
/**
* {@inheritDoc}
*
@@ -115,6 +112,8 @@ public class Folks.Backends.BlueZ.Persona : Folks.Persona,
set { this.change_phone_numbers.begin (value); } /* not writeable */
}
+ private StructuredName? _structured_name = null;
+
/**
* {@inheritDoc}
*
@@ -127,6 +126,8 @@ public class Folks.Backends.BlueZ.Persona : Folks.Persona,
set { this.change_structured_name.begin (value); } /* not writeable */
}
+ private string _full_name = "";
+
/**
* {@inheritDoc}
*
@@ -139,6 +140,8 @@ public class Folks.Backends.BlueZ.Persona : Folks.Persona,
set { this.change_full_name.begin (value); } /* not writeable */
}
+ private string _nickname = "";
+
/**
* {@inheritDoc}
*
@@ -151,6 +154,9 @@ public class Folks.Backends.BlueZ.Persona : Folks.Persona,
set { this.change_nickname.begin (value); } /* not writeable */
}
+ private SmallSet<EmailFieldDetails>? _email_addresses = null;
+ private Set<EmailFieldDetails> _email_addresses_ro;
+
/**
* {@inheritDoc}
*
@@ -197,16 +203,35 @@ public class Folks.Backends.BlueZ.Persona : Folks.Persona,
{
debug ("Adding BlueZ Persona '%s' (IID '%s')", this.uid, this.iid);
- this._phone_numbers = new HashSet<PhoneFieldDetails> ();
+ this._phone_numbers = new SmallSet<PhoneFieldDetails> (
+ AbstractFieldDetails<string>.hash_static,
+ AbstractFieldDetails<string>.equal_static);
this._phone_numbers_ro = this._phone_numbers.read_only_view;
-
- this._email_addresses = new HashSet<EmailFieldDetails> ();
+ this._email_addresses = new SmallSet<EmailFieldDetails> (
+ AbstractFieldDetails<string>.hash_static,
+ AbstractFieldDetails<string>.equal_static);
this._email_addresses_ro = this._email_addresses.read_only_view;
-
- this._urls = new HashSet<UrlFieldDetails> ();
+ this._urls = new SmallSet<UrlFieldDetails> (
+ AbstractFieldDetails<string>.hash_static,
+ AbstractFieldDetails<string>.equal_static);
this._urls_ro = this._urls.read_only_view;
}
+ private void _update_params (AbstractFieldDetails details,
+ E.VCardAttribute attr)
+ {
+ foreach (unowned E.VCardAttributeParam param in attr.get_params ())
+ {
+ /* EVCard handles parameter names and values entirely
+ * case-insensitively, so we’ll do the same. */
+ foreach (unowned string param_value in param.get_values ())
+ {
+ details.add_parameter (param.get_name ().down (),
+ param_value.down ());
+ }
+ }
+ }
+
/**
* Update the Persona’s properties from a vCard.
*
@@ -222,69 +247,136 @@ public class Folks.Backends.BlueZ.Persona : Folks.Persona,
{
var properties_changed = false;
- this.freeze_notify ();
+ /* Somewhere to store the new property values. */
+ var new_phone_numbers = new SmallSet<PhoneFieldDetails> (
+ AbstractFieldDetails<string>.hash_static,
+ AbstractFieldDetails<string>.equal_static);
+ var new_uris = new SmallSet<UrlFieldDetails> (
+ AbstractFieldDetails<string>.hash_static,
+ AbstractFieldDetails<string>.equal_static);
+ var new_email_addresses = new SmallSet<EmailFieldDetails> (
+ AbstractFieldDetails<string>.hash_static,
+ AbstractFieldDetails<string>.equal_static);
+ BytesIcon? new_avatar = null;
+ var new_full_name = "";
+ var new_nickname = "";
+ StructuredName? new_structured_name = null;
- /* Phone numbers. */
- var attribute = card.get_attribute ("TEL");
- var new_phone_numbers = new HashSet<PhoneFieldDetails> ();
+ /* Parse the attributes by iterating over the vCard’s attribute list once
+ * only. Convenience functions like E.VCard.get_attribute() cause multiple
+ * iterations over the list. */
+ unowned GLib.List<unowned E.VCardAttribute> attrs =
+ card.get_attributes ();
- if (attribute != null)
+ foreach (var attr in attrs)
{
- unowned GLib.List<unowned StringBuilder> vals =
- attribute.get_values_decoded ();
- foreach (unowned StringBuilder v in vals)
- new_phone_numbers.add (new PhoneFieldDetails (v.str));
- }
+ unowned string attr_name = attr.get_name ();
- if (!Folks.Internal.equal_sets<PhoneFieldDetails> (this._phone_numbers,
- new_phone_numbers))
- {
- this._phone_numbers = new_phone_numbers;
- this._phone_numbers_ro = new_phone_numbers.read_only_view;
- this.notify_property ("phone-numbers");
- properties_changed = true;
- }
+ if (attr_name == "TEL")
+ {
+ var val = attr.get_value ();
+ if (val == null || (!) val == "")
+ continue;
- /* Full name. */
- attribute = card.get_attribute ("FN");
- var new_full_name = "";
+ var new_field_details = new PhoneFieldDetails ((!) val);
+ this._update_params (new_field_details, attr);
+ new_phone_numbers.add (new_field_details);
+ }
+ else if (attr_name == "URL")
+ {
+ var val = attr.get_value ();
+ if (val == null || (!) val == "")
+ continue;
- if (attribute != null)
- new_full_name = attribute.get_value_decoded ().str;
+ var new_field_details = new UrlFieldDetails ((!) val);
+ this._update_params (new_field_details, attr);
+ new_uris.add (new_field_details);
+ }
+ else if (attr_name == "EMAIL")
+ {
+ var val = attr.get_value ();
+ if (val == null || (!) val == "")
+ continue;
- if (this._full_name != new_full_name)
- {
- this._full_name = new_full_name;
- this.notify_property ("full-name");
- properties_changed = true;
+ var new_field_details = new EmailFieldDetails ((!) val);
+ this._update_params (new_field_details, attr);
+ new_email_addresses.add (new_field_details);
+ }
+ else if (attr_name == "PHOTO")
+ {
+ var encoded_data = (string) attr.get_value ().data;
+ var bytes = new Bytes (Base64.decode (encoded_data));
+ new_avatar = new BytesIcon (bytes);
+ }
+ else if (attr_name == "FN")
+ new_full_name = attr.get_value ();
+ else if (attr_name == "NICKNAME")
+ new_nickname = attr.get_value ();
+ else if (attr_name == "N")
+ {
+ unowned GLib.List<unowned string> values = attr.get_values ();
+ unowned string? family_name = null, given_name = null,
+ additional_names = null, prefixes = null, suffixes = null;
+
+ if (values != null)
+ {
+ family_name = values.data;
+ values = values.next;
+ }
+ if (values != null)
+ {
+ given_name = values.data;
+ values = values.next;
+ }
+ if (values != null)
+ {
+ additional_names = values.data;
+ values = values.next;
+ }
+ if (values != null)
+ {
+ prefixes = values.data;
+ values = values.next;
+ }
+ if (values != null)
+ {
+ suffixes = values.data;
+ values = values.next;
+ }
+
+ if (suffixes == null || values != null)
+ {
+ debug ("Expected 5 components in N attribute of vCard, " +
+ "but got %s.", (suffixes == null) ? "fewer" : "more");
+ }
+
+ new_structured_name =
+ new StructuredName (family_name, given_name, additional_names,
+ prefixes, suffixes);
+ }
+ else if (attr_name != "VERSION" && attr_name != "UID")
+ {
+ /* Unknown attribute. */
+ warning ("Unknown attribute ‘%s’ in vCard for persona %s.",
+ attr_name, this.uid);
+ }
}
- /* Nickname. */
- attribute = card.get_attribute ("NICKNAME");
- var new_nickname = "";
-
- if (attribute != null)
- new_nickname = attribute.get_value_decoded ().str;
+ /* Now test the new property values to see if they’ve changed; if so, emit
+ * property change notifications. */
+ this.freeze_notify ();
- if (this._nickname != new_nickname)
+ /* Phone numbers. */
+ if (!Folks.Internal.equal_sets<PhoneFieldDetails> (this._phone_numbers,
+ new_phone_numbers))
{
- this._nickname = new_nickname;
- this.notify_property ("nickname");
+ this._phone_numbers = new_phone_numbers;
+ this._phone_numbers_ro = new_phone_numbers.read_only_view;
+ this.notify_property ("phone-numbers");
properties_changed = true;
}
/* URIs. */
- attribute = card.get_attribute ("URL");
- var new_uris = new HashSet<UrlFieldDetails> ();
-
- if (attribute != null)
- {
- unowned GLib.List<unowned StringBuilder> vals =
- attribute.get_values_decoded ();
- foreach (unowned StringBuilder v in vals)
- new_uris.add (new UrlFieldDetails (v.str));
- }
-
if (!Folks.Internal.equal_sets<UrlFieldDetails> (this._urls, new_uris))
{
this._urls = new_uris;
@@ -293,56 +385,7 @@ public class Folks.Backends.BlueZ.Persona : Folks.Persona,
properties_changed = true;
}
- /* Structured name. */
- attribute = card.get_attribute ("N");
- StructuredName? new_structured_name = null;
-
- if (attribute != null)
- {
- string[] components = { "", "", "", "", "" };
- unowned GLib.List<unowned StringBuilder> values =
- attribute.get_values_decoded ();
-
- uint i = 0;
- foreach (unowned StringBuilder b in values)
- {
- if (i >= components.length)
- break;
-
- components[i++] = b.str;
- }
-
- this._structured_name = new StructuredName (components[0],
- components[1], components[2], components[3], components[4]);
-
- if (i != 5)
- {
- debug ("Expected 5 components in N value of vCard, but got %u.",
- i);
- }
- }
-
- if ((new_structured_name == null) != (this._structured_name == null) ||
- (new_structured_name != null && this._structured_name != null &&
- !new_structured_name.equal (this._structured_name)))
- {
- this._structured_name = new_structured_name;
- this.notify_property ("structured-name");
- properties_changed = true;
- }
-
/* E-mail addresses. */
- attribute = card.get_attribute ("EMAIL");
- var new_email_addresses = new HashSet<EmailFieldDetails> ();
-
- if (attribute != null)
- {
- unowned GLib.List<unowned StringBuilder> vals =
- attribute.get_values_decoded ();
- foreach (unowned StringBuilder v in vals)
- new_email_addresses.add (new EmailFieldDetails (v.str));
- }
-
if (!Folks.Internal.equal_sets<EmailFieldDetails> (this._email_addresses,
new_email_addresses))
{
@@ -353,16 +396,6 @@ public class Folks.Backends.BlueZ.Persona : Folks.Persona,
}
/* Photo. */
- attribute = card.get_attribute ("PHOTO");
- BytesIcon? new_avatar = null;
-
- if (attribute != null)
- {
- var encoded_data = (string) attribute.get_value ().data;
- var bytes = new Bytes (Base64.decode (encoded_data));
- new_avatar = new BytesIcon (bytes);
- }
-
if ((new_avatar == null) != (this._avatar == null) ||
(new_avatar != null && this._avatar != null &&
!new_avatar.equal (this._avatar)))
@@ -372,6 +405,32 @@ public class Folks.Backends.BlueZ.Persona : Folks.Persona,
properties_changed = true;
}
+ /* Full name. */
+ if (this._full_name != new_full_name)
+ {
+ this._full_name = new_full_name;
+ this.notify_property ("full-name");
+ properties_changed = true;
+ }
+
+ /* Nickname. */
+ if (this._nickname != new_nickname)
+ {
+ this._nickname = new_nickname;
+ this.notify_property ("nickname");
+ properties_changed = true;
+ }
+
+ /* Structured name. */
+ if ((new_structured_name == null) != (this._structured_name == null) ||
+ (new_structured_name != null && this._structured_name != null &&
+ !new_structured_name.equal (this._structured_name)))
+ {
+ this._structured_name = new_structured_name;
+ this.notify_property ("structured-name");
+ properties_changed = true;
+ }
+
this.thaw_notify ();
return properties_changed;