--- a/libpurple/meson.build Mon Nov 28 23:20:24 2022 -0600
+++ b/libpurple/meson.build Mon Nov 28 23:48:33 2022 -0600
@@ -46,6 +46,7 @@
'purpleconnectionerrorinfo.c',
'purplecontactmanager.c',
'purpleconversationmanager.c',
@@ -150,6 +151,7 @@
'purpleconnectionerrorinfo.h',
'purplecontactmanager.h',
'purpleconversationmanager.h',
@@ -260,7 +262,7 @@
'purpleconnectionerrorinfo.h',
'purpleimconversation.h',
--- a/libpurple/purplecontact.c Mon Nov 28 23:20:24 2022 -0600
+++ b/libpurple/purplecontact.c Mon Nov 28 23:48:33 2022 -0600
@@ -21,71 +21,34 @@
- PurpleAccount *account;
+ PurpleContactInfo parent;
- PurplePresence *presence;
- PurpleContactPermission permission;
+ PurpleAccount *account;
static GParamSpec *properties[N_PROPERTIES] = {NULL, };
-G_DEFINE_TYPE_WITH_PRIVATE(PurpleContact, purple_contact, G_TYPE_OBJECT)
+G_DEFINE_TYPE(PurpleContact, purple_contact, PURPLE_TYPE_CONTACT_INFO) /******************************************************************************
*****************************************************************************/
purple_contact_set_account(PurpleContact *contact, PurpleAccount *account) {
- PurpleContactPrivate *priv = NULL;
g_return_if_fail(PURPLE_IS_CONTACT(contact));
g_return_if_fail(PURPLE_IS_ACCOUNT(account));
- priv = purple_contact_get_instance_private(contact);
- if(g_set_object(&priv->account, account)) {
+ if(g_set_object(&contact->account, account)) { g_object_notify_by_pspec(G_OBJECT(contact), properties[PROP_ACCOUNT]);
-purple_contact_default_get_account(PurpleContact *contact) {
- PurpleContactPrivate *priv = NULL;
- g_return_val_if_fail(PURPLE_IS_CONTACT(contact), NULL);
- priv = purple_contact_get_instance_private(contact);
/******************************************************************************
*****************************************************************************/
@@ -96,36 +59,9 @@
PurpleContact *contact = PURPLE_CONTACT(obj);
- g_value_set_string(value, purple_contact_get_id(contact));
g_value_set_object(value, purple_contact_get_account(contact));
- g_value_set_string(value, purple_contact_get_username(contact));
- case PROP_DISPLAY_NAME:
- g_value_set_string(value, purple_contact_get_display_name(contact));
- g_value_set_string(value, purple_contact_get_alias(contact));
- g_value_set_object(value, purple_contact_get_avatar(contact));
- g_value_set_object(value, purple_contact_get_presence(contact));
- g_value_set_object(value, purple_contact_get_tags(contact));
- g_value_set_object(value, purple_contact_get_person(contact));
- g_value_set_enum(value, purple_contact_get_permission(contact));
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
@@ -139,30 +75,9 @@
PurpleContact *contact = PURPLE_CONTACT(obj);
- purple_contact_set_id(contact, g_value_get_string(value));
purple_contact_set_account(contact, g_value_get_object(value));
- purple_contact_set_username(contact, g_value_get_string(value));
- case PROP_DISPLAY_NAME:
- purple_contact_set_display_name(contact, g_value_get_string(value));
- purple_contact_set_alias(contact, g_value_get_string(value));
- purple_contact_set_avatar(contact, g_value_get_object(value));
- purple_contact_set_person(contact, g_value_get_object(value));
- purple_contact_set_permission(contact, g_value_get_enum(value));
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
@@ -172,79 +87,25 @@
purple_contact_dispose(GObject *obj) {
PurpleContact *contact = PURPLE_CONTACT(obj);
- PurpleContactPrivate *priv = purple_contact_get_instance_private(contact);
- g_clear_object(&priv->account);
- g_clear_object(&priv->avatar);
- g_clear_object(&priv->presence);
- g_clear_object(&priv->tags);
- g_clear_object(&priv->person);
+ g_clear_object(&contact->account); G_OBJECT_CLASS(purple_contact_parent_class)->dispose(obj);
-purple_contact_finalize(GObject *obj) {
- PurpleContact *contact = PURPLE_CONTACT(obj);
- PurpleContactPrivate *priv = purple_contact_get_instance_private(contact);
- g_clear_pointer(&priv->id, g_free);
- g_clear_pointer(&priv->username, g_free);
- g_clear_pointer(&priv->display_name, g_free);
- g_clear_pointer(&priv->alias, g_free);
- G_OBJECT_CLASS(purple_contact_parent_class)->finalize(obj);
-purple_contact_constructed(GObject *obj) {
- PurpleContact *contact = NULL;
- PurpleContactPrivate *priv = NULL;
- G_OBJECT_CLASS(purple_contact_parent_class)->constructed(obj);
- contact = PURPLE_CONTACT(obj);
- priv = purple_contact_get_instance_private(contact);
- purple_contact_set_id(contact, NULL);
purple_contact_init(PurpleContact *contact) {
- PurpleContactPrivate *priv = purple_contact_get_instance_private(contact);
- priv->tags = purple_tags_new();
- priv->presence = g_object_new(PURPLE_TYPE_PRESENCE, NULL);
purple_contact_class_init(PurpleContactClass *klass) {
GObjectClass *obj_class = G_OBJECT_CLASS(klass);
- klass->get_account = purple_contact_default_get_account;
- obj_class->constructed = purple_contact_constructed;
obj_class->dispose = purple_contact_dispose;
- obj_class->finalize = purple_contact_finalize;
obj_class->get_property = purple_contact_get_property;
obj_class->set_property = purple_contact_set_property;
- * The protocol specific id for the contact.
- properties[PROP_ID] = g_param_spec_string(
- "The id of the contact",
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
* The account that this contact belongs to.
@@ -257,116 +118,6 @@
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
- * PurpleContact:username:
- * The username for this contact. In rare cases this can change, like when
- * a user changes their "nick" on IRC which is their user name.
- properties[PROP_USERNAME] = g_param_spec_string(
- "username", "username",
- "The username of the contact",
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- * PurpleContact:display-name:
- * The display name for this contact. This is generally set by the person
- * the contact is representing and controlled via the protocol plugin.
- properties[PROP_DISPLAY_NAME] = g_param_spec_string(
- "display-name", "display-name",
- "The display name of the contact",
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- * The alias for this contact. This is controlled by the libpurple user and
- * may be used by the protocol if it allows for aliasing.
- properties[PROP_ALIAS] = g_param_spec_string(
- "The alias of the contact.",
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- * PurpleContact:avatar:
- * The avatar for this contact. This is typically controlled by the protocol
- * and should only be read by others.
- properties[PROP_AVATAR] = g_param_spec_object(
- "The avatar of the contact",
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- * PurpleContact:presence:
- * The [class@Purple.Presence] for this contact. This is typically
- * controlled by the protocol and should only be read by others.
- properties[PROP_PRESENCE] = g_param_spec_object(
- "presence", "presence",
- "The presence of the contact",
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- * The [class@Purple.Tags] for this contact.
- properties[PROP_TAGS] = g_param_spec_object(
- "The tags for the contact",
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- * PurpleContact:person:
- * The [class@Purple.Person] that this contact belongs to.
- properties[PROP_PERSON] = g_param_spec_object(
- "The person this contact belongs to.",
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- * PurpleContact:permission:
- * The permission level for the contact.
- properties[PROP_PERMISSION] = g_param_spec_enum(
- "permission", "permission",
- "The permission level of the contact",
- PURPLE_TYPE_CONTACT_PERMISSION,
- PURPLE_CONTACT_PERMISSION_UNSET,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
@@ -386,285 +137,7 @@
purple_contact_get_account(PurpleContact *contact) {
- PurpleContactClass *klass = NULL;
- g_return_val_if_fail(PURPLE_IS_CONTACT(contact), NULL);
- klass = PURPLE_CONTACT_GET_CLASS(contact);
- if(klass != NULL && klass->get_account != NULL) {
- return klass->get_account(contact);
-purple_contact_get_id(PurpleContact *contact) {
- PurpleContactPrivate *priv = NULL;
- g_return_val_if_fail(PURPLE_IS_CONTACT(contact), NULL);
- priv = purple_contact_get_instance_private(contact);
-purple_contact_set_id(PurpleContact *contact, const gchar *id) {
- PurpleContactPrivate *priv = NULL;
- g_return_if_fail(PURPLE_IS_CONTACT(contact));
- priv = purple_contact_get_instance_private(contact);
- priv->id = g_strdup(id);
- g_object_notify_by_pspec(G_OBJECT(contact), properties[PROP_ID]);
-purple_contact_get_username(PurpleContact *contact) {
- PurpleContactPrivate *priv = NULL;
- g_return_val_if_fail(PURPLE_IS_CONTACT(contact), NULL);
- priv = purple_contact_get_instance_private(contact);
-purple_contact_set_username(PurpleContact *contact, const gchar *username) {
- PurpleContactPrivate *priv = NULL;
- g_return_if_fail(PURPLE_IS_CONTACT(contact));
- g_return_if_fail(username != NULL);
- priv = purple_contact_get_instance_private(contact);
- g_free(priv->username);
- priv->username = g_strdup(username);
- g_object_notify_by_pspec(G_OBJECT(contact), properties[PROP_USERNAME]);
-purple_contact_get_display_name(PurpleContact *contact) {
- PurpleContactPrivate *priv = NULL;
- g_return_val_if_fail(PURPLE_IS_CONTACT(contact), NULL);
- priv = purple_contact_get_instance_private(contact);
- return priv->display_name;
-purple_contact_set_display_name(PurpleContact *contact,
- const gchar *display_name)
- PurpleContactPrivate *priv = NULL;
- g_return_if_fail(PURPLE_IS_CONTACT(contact));
- priv = purple_contact_get_instance_private(contact);
- g_free(priv->display_name);
- priv->display_name = g_strdup(display_name);
- g_object_notify_by_pspec(G_OBJECT(contact), properties[PROP_DISPLAY_NAME]);
-purple_contact_get_alias(PurpleContact *contact) {
- PurpleContactPrivate *priv = NULL;
- g_return_val_if_fail(PURPLE_IS_CONTACT(contact), NULL);
- priv = purple_contact_get_instance_private(contact);
-purple_contact_set_alias(PurpleContact *contact, const gchar *alias) {
- PurpleContactPrivate *priv = NULL;
- g_return_if_fail(PURPLE_IS_CONTACT(contact));
- priv = purple_contact_get_instance_private(contact);
- priv->alias = g_strdup(alias);
- g_object_notify_by_pspec(G_OBJECT(contact), properties[PROP_ALIAS]);
-purple_contact_get_avatar(PurpleContact *contact) {
- PurpleContactPrivate *priv = NULL;
g_return_val_if_fail(PURPLE_IS_CONTACT(contact), NULL);
- priv = purple_contact_get_instance_private(contact);
-purple_contact_set_avatar(PurpleContact *contact, GdkPixbuf *avatar) {
- PurpleContactPrivate *priv = NULL;
- g_return_if_fail(PURPLE_IS_CONTACT(contact));
- priv = purple_contact_get_instance_private(contact);
- if(g_set_object(&priv->avatar, avatar)) {
- g_object_notify_by_pspec(G_OBJECT(contact), properties[PROP_AVATAR]);
-purple_contact_get_presence(PurpleContact *contact) {
- PurpleContactPrivate *priv = NULL;
- g_return_val_if_fail(PURPLE_IS_CONTACT(contact), NULL);
- priv = purple_contact_get_instance_private(contact);
-purple_contact_get_tags(PurpleContact *contact) {
- PurpleContactPrivate *priv = NULL;
- g_return_val_if_fail(PURPLE_IS_CONTACT(contact), NULL);
- priv = purple_contact_get_instance_private(contact);
-purple_contact_set_person(PurpleContact *contact, PurplePerson *person) {
- PurpleContactPrivate *priv = NULL;
- g_return_if_fail(PURPLE_IS_CONTACT(contact));
- priv = purple_contact_get_instance_private(contact);
- if(g_set_object(&priv->person, person)) {
- g_object_notify_by_pspec(G_OBJECT(contact), properties[PROP_PERSON]);
-purple_contact_get_person(PurpleContact *contact) {
- PurpleContactPrivate *priv = NULL;
- g_return_val_if_fail(PURPLE_IS_CONTACT(contact), NULL);
- priv = purple_contact_get_instance_private(contact);
-purple_contact_get_permission(PurpleContact *contact) {
- PurpleContactPrivate *priv = NULL;
- g_return_val_if_fail(PURPLE_IS_CONTACT(contact),
- PURPLE_CONTACT_PERMISSION_UNSET);
- priv = purple_contact_get_instance_private(contact);
- return priv->permission;
+ return contact->account;
-purple_contact_set_permission(PurpleContact *contact,
- PurpleContactPermission permission)
- PurpleContactPrivate *priv = NULL;
- g_return_if_fail(PURPLE_IS_CONTACT(contact));
- priv = purple_contact_get_instance_private(contact);
- priv->permission = permission;
- g_object_notify_by_pspec(G_OBJECT(contact), properties[PROP_PERMISSION]);
-purple_contact_get_name_for_display(PurpleContact *contact) {
- PurpleContactPrivate *priv = NULL;
- g_return_val_if_fail(PURPLE_IS_CONTACT(contact), NULL);
- priv = purple_contact_get_instance_private(contact);
- /* If contact is associated with a PurplePerson that has an alias set,
- * return the alias of that PurplePerson.
- if(priv->person != NULL) {
- const char *alias = purple_person_get_alias(priv->person);
- if(alias != NULL && alias[0] != '\0') {
- /* If the purple user set an alias for the contact, return that. */
- if(priv->alias != NULL && priv->alias[0] != '\0') {
- /* If the contact has a display name set, return that. */
- if(priv->display_name != NULL && priv->display_name[0] != '\0') {
- return priv->display_name;
- /* Fallback to the username if that is set. */
- if(priv->username != NULL && priv->username[0] != '\0') {
- /* Finally, in a last ditch effort, return the id of the contact. */
-purple_contact_compare(PurpleContact *a, PurpleContact *b) {
- PurplePerson *person_a = NULL;
- PurplePerson *person_b = NULL;
- const char *name_a = NULL;
- const char *name_b = NULL;
- /* Check for NULL values. */
- if(a != NULL && b == NULL) {
- } else if(a == NULL && b != NULL) {
- } else if(a == NULL && b == NULL) {
- /* Check if the contacts have persons associated with them. */
- person_a = purple_contact_get_person(a);
- person_b = purple_contact_get_person(b);
- if(person_a != NULL && person_b == NULL) {
- } else if(person_a == NULL && person_b != NULL) {
- /* Finally get the names for the displaying and compare those. */
- name_a = purple_contact_get_name_for_display(a);
- name_b = purple_contact_get_name_for_display(b);
- return purple_utf8_strcasecmp(name_a, name_b);
--- a/libpurple/purplecontactmanager.c Mon Nov 28 23:20:24 2022 -0600
+++ b/libpurple/purplecontactmanager.c Mon Nov 28 23:48:33 2022 -0600
@@ -46,26 +46,26 @@
purple_contact_manager_find_with_username_helper(gconstpointer a,
- PurpleContact *contact_a = (gpointer)a;
- PurpleContact *contact_b = (gpointer)b;
+ PurpleContactInfo *info_a = PURPLE_CONTACT_INFO(a); + PurpleContactInfo *info_b = PURPLE_CONTACT_INFO(b); const gchar *username_a = NULL;
const gchar *username_b = NULL;
- username_a = purple_contact_get_username(contact_a);
- username_b = purple_contact_get_username(contact_b);
+ username_a = purple_contact_info_get_username(info_a); + username_b = purple_contact_info_get_username(info_b); return purple_strequal(username_a, username_b);
purple_contact_manager_find_with_id_helper(gconstpointer a, gconstpointer b) {
- PurpleContact *contact_a = (gpointer)a;
- PurpleContact *contact_b = (gpointer)b;
+ PurpleContactInfo *info_a = PURPLE_CONTACT_INFO(a); + PurpleContactInfo *info_b = PURPLE_CONTACT_INFO(b); const gchar *id_a = NULL;
const gchar *id_b = NULL;
- id_a = purple_contact_get_id(contact_a);
- id_b = purple_contact_get_id(contact_b);
+ id_a = purple_contact_info_get_id(info_a); + id_b = purple_contact_info_get_id(info_b); return purple_strequal(id_a, id_b);
@@ -260,8 +260,9 @@
if(g_list_store_find(contacts, contact, NULL)) {
- const gchar *username = purple_contact_get_username(contact);
- const gchar *id = purple_contact_get_id(contact);
+ PurpleContactInfo *info = PURPLE_CONTACT_INFO(contact); + const gchar *username = purple_contact_info_get_username(info); + const gchar *id = purple_contact_info_get_id(info); g_warning("double add detected for contact %s:%s", id, username);
@@ -382,7 +383,7 @@
needle = purple_contact_new(account, NULL);
- purple_contact_set_username(needle, username);
+ purple_contact_info_set_username(PURPLE_CONTACT_INFO(needle), username); found = g_list_store_find_with_equal_func(contacts, needle,
purple_contact_manager_find_with_username_helper,
@@ -435,6 +436,7 @@
PurpleAccount *account = NULL;
PurpleContact *contact = NULL;
+ PurpleContactInfo *info = NULL; PurplePresence *buddy_presence = NULL;
PurplePresence *contact_presence = NULL;
@@ -446,6 +448,7 @@
account = purple_buddy_get_account(buddy);
id = purple_buddy_get_id(buddy);
contact = purple_contact_new(account, id);
+ info = PURPLE_CONTACT_INFO(contact); /* Bind all of the properties. */
g_object_bind_property(buddy, "name", contact, "username",
@@ -456,7 +459,7 @@
G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
buddy_presence = purple_buddy_get_presence(buddy);
- contact_presence = purple_contact_get_presence(contact);
+ contact_presence = purple_contact_info_get_presence(info); g_object_bind_property(buddy_presence, "idle", contact_presence, "idle",
G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
--- a/libpurple/purpleperson.c Mon Nov 28 23:20:24 2022 -0600
+++ b/libpurple/purpleperson.c Mon Nov 28 23:48:33 2022 -0600
@@ -36,7 +36,7 @@
+ PROP_PRIORITY_CONTACT_INFO, static GParamSpec *properties[N_PROPERTIES] = {NULL, };
@@ -61,33 +61,33 @@
purple_person_contact_compare(gconstpointer a, gconstpointer b) {
- PurpleContact *c1 = *(PurpleContact **)a;
- PurpleContact *c2 = *(PurpleContact **)b;
+ PurpleContactInfo *c1 = *(PurpleContactInfo **)a; + PurpleContactInfo *c2 = *(PurpleContactInfo **)b; PurplePresence *p1 = NULL;
PurplePresence *p2 = NULL;
- p1 = purple_contact_get_presence(c1);
- p2 = purple_contact_get_presence(c2);
+ p1 = purple_contact_info_get_presence(c1); + p2 = purple_contact_info_get_presence(c2); return purple_presence_compare(p1, p2);
purple_person_sort_contacts(PurplePerson *person) {
- PurpleContact *original_priority = NULL;
- PurpleContact *new_priority = NULL;
+ PurpleContactInfo *original_priority = NULL; + PurpleContactInfo *new_priority = NULL; guint n_items = person->contacts->len;
g_object_notify_by_pspec(G_OBJECT(person),
- properties[PROP_PRIORITY_CONTACT]);
+ properties[PROP_PRIORITY_CONTACT_INFO]); g_list_model_items_changed(G_LIST_MODEL(person), 0, n_items, n_items);
- original_priority = purple_person_get_priority_contact(person);
+ original_priority = purple_person_get_priority_contact_info(person); g_ptr_array_sort(person->contacts, purple_person_contact_compare);
@@ -98,7 +98,7 @@
new_priority = g_ptr_array_index(person->contacts, 0);
if(original_priority != new_priority) {
g_object_notify_by_pspec(G_OBJECT(person),
- properties[PROP_PRIORITY_CONTACT]);
+ properties[PROP_PRIORITY_CONTACT_INFO]); @@ -118,7 +118,7 @@
*****************************************************************************/
purple_person_get_item_type(G_GNUC_UNUSED GListModel *list) {
- return PURPLE_TYPE_CONTACT;
+ return PURPLE_TYPE_CONTACT_INFO; @@ -131,14 +131,14 @@
purple_person_get_item(GListModel *list, guint position) {
PurplePerson *person = PURPLE_PERSON(list);
- PurpleContact *contact = NULL;
+ PurpleContactInfo *info = NULL; if(position < person->contacts->len) {
- contact = g_ptr_array_index(person->contacts, position);
+ info = g_ptr_array_index(person->contacts, position);
@@ -174,9 +174,9 @@
g_value_set_object(value, purple_person_get_tags(person));
- case PROP_PRIORITY_CONTACT:
+ case PROP_PRIORITY_CONTACT_INFO: g_value_set_object(value,
- purple_person_get_priority_contact(person));
+ purple_person_get_priority_contact_info(person)); G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
@@ -313,19 +313,19 @@
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- * PurplePerson:priority-contact:
+ * PurplePerson:priority-contact-info: - * The [class@Purple.Contact] that currently has the highest priority.
+ * The [class@Purple.ContactInfo] that currently has the highest priority. - * This is used by user interfaces to determine which [class@Purple.Contact]
- * to use when messaging and so on.
+ * This is used by user interfaces to determine which + * [class@Purple.ContactInfo] to use when messaging and so on. - properties[PROP_PRIORITY_CONTACT] = g_param_spec_object(
- "priority-contact", "priority-contact",
- "The priority contact for the person",
+ properties[PROP_PRIORITY_CONTACT_INFO] = g_param_spec_object( + "priority-contact-info", "priority-contact-info", + "The priority contact info for the person", + PURPLE_TYPE_CONTACT_INFO, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
@@ -387,59 +387,63 @@
-purple_person_add_contact(PurplePerson *person, PurpleContact *contact) {
+purple_person_add_contact_info(PurplePerson *person, + PurpleContactInfo *info) PurplePresence *presence = NULL;
g_return_if_fail(PURPLE_IS_PERSON(person));
- g_return_if_fail(PURPLE_IS_CONTACT(contact));
+ g_return_if_fail(PURPLE_IS_CONTACT_INFO(info)); - g_ptr_array_add(person->contacts, g_object_ref(contact));
+ g_ptr_array_add(person->contacts, g_object_ref(info)); - presence = purple_contact_get_presence(contact);
+ presence = purple_contact_info_get_presence(info); g_signal_connect_object(presence, "notify",
G_CALLBACK(purple_person_presence_notify_cb),
- purple_contact_set_person(contact, person);
+ purple_contact_info_set_person(info, person); purple_person_sort_contacts(person);
-purple_person_remove_contact(PurplePerson *person, PurpleContact *contact) {
+purple_person_remove_contact_info(PurplePerson *person, + PurpleContactInfo *info) gboolean removed = FALSE;
g_return_val_if_fail(PURPLE_IS_PERSON(person), FALSE);
- g_return_val_if_fail(PURPLE_IS_CONTACT(contact), FALSE);
+ g_return_val_if_fail(PURPLE_IS_CONTACT_INFO(info), FALSE); - /* Ref the contact to avoid a use-after free. */
+ /* Ref the contact info to avoid a use-after free. */ /* g_ptr_array_remove calls g_object_unref because we passed it in as a
- removed = g_ptr_array_remove(person->contacts, contact);
+ removed = g_ptr_array_remove(person->contacts, info); - PurplePresence *presence = purple_contact_get_presence(contact);
+ PurplePresence *presence = purple_contact_info_get_presence(info); g_signal_handlers_disconnect_by_func(presence,
purple_person_presence_notify_cb,
- purple_contact_set_person(contact, NULL);
+ purple_contact_info_set_person(info, NULL); purple_person_sort_contacts(person);
/* Remove our reference. */
- g_object_unref(contact);
-purple_person_get_priority_contact(PurplePerson *person) {
+purple_person_get_priority_contact_info(PurplePerson *person) { g_return_val_if_fail(PURPLE_IS_PERSON(person), NULL);
if(person->contacts->len == 0) {
--- a/libpurple/tests/test_contact.c Mon Nov 28 23:20:24 2022 -0600
+++ b/libpurple/tests/test_contact.c Mon Nov 28 23:48:33 2022 -0600
@@ -29,12 +29,14 @@
test_purple_contact_new(void) {
PurpleAccount *account = NULL;
PurpleContact *contact = NULL;
+ PurpleContactInfo *info = NULL; account = purple_account_new("test", "test");
contact = purple_contact_new(account, "id");
+ info = PURPLE_CONTACT_INFO(contact); g_assert_true(purple_contact_get_account(contact) == account);
- g_assert_cmpstr(purple_contact_get_id(contact), ==, "id");
+ g_assert_cmpstr(purple_contact_info_get_id(info), ==, "id"); g_clear_object(&contact);
g_clear_object(&account);
@@ -45,21 +47,9 @@
PurpleAccount *account = NULL;
PurpleAccount *account1 = NULL;
PurpleContact *contact = NULL;
- PurpleContactPermission permission;
- PurplePerson *person = NULL;
- PurplePerson *person1 = NULL;
- PurplePresence *presence1 = NULL;
- PurpleTags *tags = NULL;
- GdkPixbuf *avatar = NULL;
- GdkPixbuf *avatar1 = NULL;
- gchar *username = NULL;
- gchar *display_name = NULL;
account = purple_account_new("test", "test");
- avatar = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, 1, 1);
- person = purple_person_new();
/* Use g_object_new so we can test setting properties by name. All of them
* call the setter methods, so by doing it this way we exercise more of the
@@ -69,280 +59,26 @@
- "username", "username",
- "display-name", "display-name",
- "permission", PURPLE_CONTACT_PERMISSION_ALLOW,
/* Now use g_object_get to read all of the properties. */
- "display-name", &display_name,
- "presence", &presence1,
- "permission", &permission,
/* Compare all the things. */
g_assert_cmpstr(id, ==, "id1");
g_assert_true(account1 == account);
- g_assert_cmpstr(username, ==, "username");
- g_assert_cmpstr(display_name, ==, "display-name");
- g_assert_cmpstr(alias, ==, "alias");
- g_assert_true(avatar1 == avatar);
- g_assert_nonnull(presence1);
- g_assert_nonnull(tags);
- g_assert_true(person1 == person);
- g_assert_true(permission == PURPLE_CONTACT_PERMISSION_ALLOW);
/* Free/unref all the things. */
g_clear_pointer(&id, g_free);
g_clear_object(&account1);
- g_clear_pointer(&username, g_free);
- g_clear_pointer(&display_name, g_free);
- g_clear_pointer(&alias, g_free);
- g_clear_object(&avatar1);
- g_clear_object(&presence1);
- g_clear_object(&person);
- g_clear_object(&person1);
- g_clear_object(&avatar);
g_clear_object(&contact);
g_clear_object(&account);
/******************************************************************************
- * get_name_for_display tests
- *****************************************************************************/
-test_purple_contact_get_name_for_display_person_with_alias(void) {
- PurpleAccount *account = NULL;
- PurpleContact *contact = NULL;
- PurplePerson *person = NULL;
- const char *alias = NULL;
- account = purple_account_new("test", "test");
- person = purple_person_new();
- purple_person_set_alias(person, "this is the alias");
- contact = purple_contact_new(account, NULL);
- purple_contact_set_person(contact, person);
- alias = purple_contact_get_name_for_display(contact);
- g_assert_cmpstr(alias, ==, "this is the alias");
- g_clear_object(&account);
- g_clear_object(&contact);
- g_clear_object(&person);
-test_purple_contact_get_name_for_display_contact_with_alias(void) {
- PurpleAccount *account = NULL;
- PurpleContact *contact = NULL;
- PurplePerson *person = NULL;
- const char *alias = NULL;
- account = purple_account_new("test", "test");
- person = purple_person_new();
- contact = purple_contact_new(account, NULL);
- purple_contact_set_person(contact, person);
- purple_contact_set_alias(contact, "this is the alias");
- alias = purple_contact_get_name_for_display(contact);
- g_assert_cmpstr(alias, ==, "this is the alias");
- g_clear_object(&account);
- g_clear_object(&contact);
- g_clear_object(&person);
-test_purple_contact_get_name_for_display_contact_with_display_name(void) {
- PurpleAccount *account = NULL;
- PurpleContact *contact = NULL;
- PurplePerson *person = NULL;
- const char *alias = NULL;
- account = purple_account_new("test", "test");
- person = purple_person_new();
- contact = purple_contact_new(account, NULL);
- purple_contact_set_person(contact, person);
- purple_contact_set_display_name(contact, "this is the display name");
- alias = purple_contact_get_name_for_display(contact);
- g_assert_cmpstr(alias, ==, "this is the display name");
- g_clear_object(&account);
- g_clear_object(&contact);
- g_clear_object(&person);
-test_purple_contact_get_name_for_display_username_fallback(void) {
- PurpleAccount *account = NULL;
- PurpleContact *contact = NULL;
- PurplePerson *person = NULL;
- const char *alias = NULL;
- account = purple_account_new("test", "test");
- person = purple_person_new();
- contact = purple_contact_new(account, NULL);
- purple_contact_set_username(contact, "username");
- purple_contact_set_person(contact, person);
- alias = purple_contact_get_name_for_display(contact);
- g_assert_cmpstr(alias, ==, "username");
- g_clear_object(&account);
- g_clear_object(&contact);
- g_clear_object(&person);
-test_purple_contact_get_name_for_display_id_fallback(void) {
- PurpleAccount *account = NULL;
- PurpleContact *contact = NULL;
- PurplePerson *person = NULL;
- const char *alias = NULL;
- account = purple_account_new("test", "test");
- person = purple_person_new();
- contact = purple_contact_new(account, "id");
- purple_contact_set_person(contact, person);
- alias = purple_contact_get_name_for_display(contact);
- g_assert_cmpstr(alias, ==, "id");
- g_clear_object(&account);
- g_clear_object(&contact);
- g_clear_object(&person);
-/******************************************************************************
- * purple_contact_compare tests
- *****************************************************************************/
-test_purple_contact_compare_not_null__null(void) {
- PurpleAccount *account = NULL;
- PurpleContact *contact = NULL;
- account = purple_account_new("test", "test");
- contact = purple_contact_new(account, NULL);
- g_assert_cmpint(purple_contact_compare(contact, NULL), <, 0);
- g_clear_object(&account);
- g_clear_object(&contact);
-test_purple_contact_compare_null__not_null(void) {
- PurpleAccount *account = NULL;
- PurpleContact *contact = NULL;
- account = purple_account_new("test", "test");
- contact = purple_contact_new(account, NULL);
- g_assert_cmpint(purple_contact_compare(NULL, contact), >, 0);
- g_clear_object(&account);
- g_clear_object(&contact);
-test_purple_contact_compare_null__null(void) {
- g_assert_cmpint(purple_contact_compare(NULL, NULL), ==, 0);
-test_purple_contact_compare_person__no_person(void) {
- PurpleAccount *account = NULL;
- PurpleContact *contact_a = NULL;
- PurpleContact *contact_b = NULL;
- PurplePerson *person = NULL;
- account = purple_account_new("test", "test");
- contact_a = purple_contact_new(account, NULL);
- person = purple_person_new();
- purple_contact_set_person(contact_a, person);
- contact_b = purple_contact_new(account, NULL);
- g_assert_cmpint(purple_contact_compare(contact_a, contact_b), <, 0);
- g_clear_object(&account);
- g_clear_object(&contact_a);
- g_clear_object(&contact_b);
- g_clear_object(&person);
-test_purple_contact_compare_no_person__person(void) {
- PurpleAccount *account = NULL;
- PurpleContact *contact_a = NULL;
- PurpleContact *contact_b = NULL;
- PurplePerson *person = NULL;
- account = purple_account_new("test", "test");
- contact_a = purple_contact_new(account, NULL);
- contact_b = purple_contact_new(account, NULL);
- person = purple_person_new();
- purple_contact_set_person(contact_b, person);
- g_assert_cmpint(purple_contact_compare(contact_a, contact_b), >, 0);
- g_clear_object(&account);
- g_clear_object(&contact_a);
- g_clear_object(&contact_b);
- g_clear_object(&person);
-test_purple_contact_compare_name__name(void) {
- PurpleAccount *account = NULL;
- PurpleContact *contact_a = NULL;
- PurpleContact *contact_b = NULL;
- account = purple_account_new("test", "test");
- contact_a = purple_contact_new(account, NULL);
- purple_contact_set_username(contact_a, "aaa");
- contact_b = purple_contact_new(account, NULL);
- purple_contact_set_username(contact_b, "zzz");
- g_assert_cmpint(purple_contact_compare(contact_a, contact_b), <, 0);
- g_assert_cmpint(purple_contact_compare(contact_b, contact_a), >, 0);
- purple_contact_set_username(contact_b, "aaa");
- g_assert_cmpint(purple_contact_compare(contact_b, contact_a), ==, 0);
- g_clear_object(&account);
- g_clear_object(&contact_a);
- g_clear_object(&contact_b);
-/******************************************************************************
*****************************************************************************/
@@ -356,29 +92,5 @@
g_test_add_func("/contact/properties",
test_purple_contact_properties);
- g_test_add_func("/contact/get_name_for_display/person_with_alias",
- test_purple_contact_get_name_for_display_person_with_alias);
- g_test_add_func("/contact/get_name_for_display/contact_with_alias",
- test_purple_contact_get_name_for_display_contact_with_alias);
- g_test_add_func("/contact/get_name_for_display/contact_with_display_name",
- test_purple_contact_get_name_for_display_contact_with_display_name);
- g_test_add_func("/contact/get_name_for_display/username_fallback",
- test_purple_contact_get_name_for_display_username_fallback);
- g_test_add_func("/contact/get_name_for_display/id_fallback",
- test_purple_contact_get_name_for_display_id_fallback);
- g_test_add_func("/contact/compare/not_null__null",
- test_purple_contact_compare_not_null__null);
- g_test_add_func("/contact/compare/null__not_null",
- test_purple_contact_compare_null__not_null);
- g_test_add_func("/contact/compare/null__null",
- test_purple_contact_compare_null__null);
- g_test_add_func("/contact/compare/person__no_person",
- test_purple_contact_compare_person__no_person);
- g_test_add_func("/contact/compare/no_person__person",
- test_purple_contact_compare_no_person__person);
- g_test_add_func("/contact/compare/name__name",
- test_purple_contact_compare_name__name);
--- a/libpurple/tests/test_contact_manager.c Mon Nov 28 23:20:24 2022 -0600
+++ b/libpurple/tests/test_contact_manager.c Mon Nov 28 23:48:33 2022 -0600
@@ -199,11 +199,11 @@
account = purple_account_new("test", "test");
contact1 = purple_contact_new(account, NULL);
- purple_contact_set_username(contact1, "user1");
+ purple_contact_info_set_username(PURPLE_CONTACT_INFO(contact1), "user1"); purple_contact_manager_add(manager, contact1);
contact2 = purple_contact_new(account, NULL);
- purple_contact_set_username(contact2, "user2");
+ purple_contact_info_set_username(PURPLE_CONTACT_INFO(contact2), "user2"); purple_contact_manager_add(manager, contact2);
found = purple_contact_manager_find_with_username(manager, account,
@@ -265,6 +265,7 @@
PurpleAccount *account = NULL;
PurpleBuddy *buddy = NULL;
PurpleContact *contact = NULL;
+ PurpleContactInfo *info = NULL; PurpleContactManager *manager = NULL;
PurpleStatusType *type = NULL;
@@ -298,15 +299,17 @@
g_assert_nonnull(contact);
g_assert_true(PURPLE_IS_CONTACT(contact));
+ info = PURPLE_CONTACT_INFO(contact); /* Now check the alias and display name to make sure they were synced as
source = purple_buddy_get_local_alias(buddy);
- destination = purple_contact_get_alias(contact);
+ destination = purple_contact_info_get_alias(info); g_assert_cmpstr(destination, ==, source);
source = purple_buddy_get_server_alias(buddy);
- destination = purple_contact_get_display_name(contact);
+ destination = purple_contact_info_get_display_name(info); g_assert_cmpstr(destination, ==, source);
/* Now let's change the settings in the buddy and verify they made it to the
@@ -319,16 +322,16 @@
purple_buddy_set_local_alias(buddy, "guy-alias");
- g_assert_cmpstr(purple_contact_get_alias(contact), ==, "guy-alias");
+ g_assert_cmpstr(purple_contact_info_get_alias(info), ==, "guy-alias"); purple_buddy_set_server_alias(buddy, "server-guy");
- g_assert_cmpstr(purple_contact_get_display_name(contact), ==,
+ g_assert_cmpstr(purple_contact_info_get_display_name(info), ==, - purple_contact_set_alias(contact, "friend-alias");
+ purple_contact_info_set_alias(info, "friend-alias"); g_assert_cmpstr(purple_buddy_get_local_alias(buddy), ==, "friend-alias");
- purple_contact_set_display_name(contact, "server-friend");
+ purple_contact_info_set_display_name(info, "server-friend"); g_assert_cmpstr(purple_buddy_get_server_alias(buddy), ==, "server-friend");
/* We can't verify the presences changes because PurpleBuddy has to be in
--- a/libpurple/tests/test_person.c Mon Nov 28 23:20:24 2022 -0600
+++ b/libpurple/tests/test_person.c Mon Nov 28 23:48:33 2022 -0600
@@ -109,63 +109,58 @@
test_purple_person_contacts_single(void) {
- PurpleAccount *account = NULL;
- PurpleContact *contact = NULL;
+ PurpleContactInfo *info = NULL; PurplePerson *person = NULL;
PurplePerson *person1 = NULL;
gboolean removed = FALSE;
gboolean changed = FALSE;
- account = purple_account_new("test", "test");
- contact = purple_contact_new(account, "username");
+ info = purple_contact_info_new("id"); person = purple_person_new();
g_signal_connect(person, "items-changed",
G_CALLBACK(test_purple_person_items_changed_cb), &changed);
n_items = g_list_model_get_n_items(G_LIST_MODEL(person));
g_assert_cmpuint(n_items, ==, 0);
- purple_person_add_contact(person, contact);
+ purple_person_add_contact_info(person, info); n_items = g_list_model_get_n_items(G_LIST_MODEL(person));
g_assert_cmpuint(n_items, ==, 1);
- person1 = purple_contact_get_person(contact);
+ person1 = purple_contact_info_get_person(info); g_assert_true(person1 == person);
- removed = purple_person_remove_contact(person, contact);
+ removed = purple_person_remove_contact_info(person, info); n_items = g_list_model_get_n_items(G_LIST_MODEL(person));
g_assert_cmpuint(n_items, ==, 0);
- person1 = purple_contact_get_person(contact);
+ person1 = purple_contact_info_get_person(info); - g_clear_object(&account);
- g_clear_object(&contact);
test_purple_person_contacts_multiple(void) {
- PurpleAccount *account = NULL;
PurplePerson *person = NULL;
- GPtrArray *contacts = NULL;
+ GPtrArray *infos = NULL; - const gint n_contacts = 5;
+ const gint n_infos = 5; gboolean changed = FALSE;
- account = purple_account_new("test", "test");
person = purple_person_new();
g_signal_connect(person, "items-changed",
G_CALLBACK(test_purple_person_items_changed_cb), &changed);
- contacts = g_ptr_array_new_full(n_contacts, g_object_unref);
- for(gint i = 0; i < n_contacts; i++) {
- PurpleContact *contact = NULL;
+ infos = g_ptr_array_new_full(n_infos, g_object_unref); + for(gint i = 0; i < n_infos; i++) { + PurpleContactInfo *info = NULL; @@ -174,35 +169,36 @@
g_assert_cmpuint(n_items, ==, i);
username = g_strdup_printf("username%d", i);
- contact = purple_contact_new(account, username);
+ info = purple_contact_info_new(NULL); + purple_contact_info_set_username(info, username); - /* Add the contact to the ptr array so we can remove it below. */
- g_ptr_array_add(contacts, contact);
+ /* Add the contact info to the ptr array so we can remove it below. */ + g_ptr_array_add(infos, info); - /* Add the contact to the person and make sure that all the magic
+ /* Add the contact info to the person and make sure that all the magic - purple_person_add_contact(person, contact);
+ purple_person_add_contact_info(person, info); n_items = g_list_model_get_n_items(G_LIST_MODEL(person));
g_assert_cmpuint(n_items, ==, i + 1);
- for(gint i = 0; i < n_contacts; i++) {
- PurpleContact *contact = contacts->pdata[i];
+ for(gint i = 0; i < n_infos; i++) { + PurpleContactInfo *info = g_ptr_array_index(infos, i); gboolean removed = FALSE;
n_items = g_list_model_get_n_items(G_LIST_MODEL(person));
- g_assert_cmpuint(n_items, ==, n_contacts - i);
+ g_assert_cmpuint(n_items, ==, n_infos - i); - removed = purple_person_remove_contact(person, contact);
+ removed = purple_person_remove_contact_info(person, info); n_items = g_list_model_get_n_items(G_LIST_MODEL(person));
- g_assert_cmpuint(n_items, ==, n_contacts - (i + 1));
+ g_assert_cmpuint(n_items, ==, n_infos - (i + 1)); @@ -211,37 +207,33 @@
n_items = g_list_model_get_n_items(G_LIST_MODEL(person));
g_assert_cmpuint(n_items, ==, 0);
- g_ptr_array_free(contacts, TRUE);
+ g_ptr_array_free(infos, TRUE); - g_clear_object(&account);
test_purple_person_priority_single(void) {
- PurpleAccount *account = NULL;
- PurpleContact *contact = NULL;
- PurpleContact *priority = NULL;
+ PurpleContactInfo *info = NULL; + PurpleContactInfo *priority = NULL; PurplePerson *person = NULL;
PurplePresence *presence = NULL;
PurpleStatus *status = NULL;
PurpleStatusType *status_type = NULL;
- account = purple_account_new("test", "test");
person = purple_person_new();
- g_signal_connect(person, "notify::priority-contact",
+ g_signal_connect(person, "notify::priority-contact-info", G_CALLBACK(test_purple_person_notify_cb), &called);
- priority = purple_person_get_priority_contact(person);
+ priority = purple_person_get_priority_contact_info(person); /* Now create a real contact. */
- contact = purple_contact_new(account, "username");
- purple_person_add_contact(person, contact);
+ info = purple_contact_info_new(NULL); + purple_person_add_contact_info(person, info); /* Set the status of the contact. */
- presence = purple_contact_get_presence(contact);
+ presence = purple_contact_info_get_presence(info); status_type = purple_status_type_new(PURPLE_STATUS_AVAILABLE, "available",
status = purple_status_new(status_type, presence);
@@ -250,40 +242,37 @@
- priority = purple_person_get_priority_contact(person);
- g_assert_true(priority == contact);
+ priority = purple_person_get_priority_contact_info(person); + g_assert_true(priority == info); purple_status_type_destroy(status_type);
- g_clear_object(&account);
- g_clear_object(&contact);
g_clear_object(&presence);
test_purple_person_priority_multiple_with_change(void) {
- PurpleAccount *account = NULL;
- PurpleContact *priority = NULL;
- PurpleContact *first = NULL;
- PurpleContact *sorted_contact = NULL;
+ PurpleContactInfo *priority = NULL; + PurpleContactInfo *first = NULL; + PurpleContactInfo *sorted_contact = NULL; PurplePerson *person = NULL;
PurplePresence *sorted_presence = NULL;
PurpleStatus *status = NULL;
PurpleStatusType *available = NULL;
PurpleStatusType *offline = NULL;
gboolean changed = FALSE;
- /* This unit test is a bit complicated, but it adds 5 contacts to a person
- * all whose presences are set to offline. After adding all the contacts,
- * we verify that the first contact we added is the priority contact. Then
- * we flip the active status of the n_contacts - 2 contact to available.
- * This should make it the priority contact which we then assert.
+ /* This unit test is a bit complicated, but it adds 5 contact infos to a + * person all whose presences are set to offline. After adding all the + * contact infos, we verify that the first contact info we added is the + * priority contact info. Then we flip the active status of the n_infos - 2 + * infos to available. This should make it the priority contact info which - account = purple_account_new("test", "test");
/* Create our status types. */
available = purple_status_type_new(PURPLE_STATUS_AVAILABLE, "available",
@@ -294,14 +283,14 @@
* priority-contact property.
person = purple_person_new();
- g_signal_connect(person, "notify::priority-contact",
+ g_signal_connect(person, "notify::priority-contact-info", G_CALLBACK(test_purple_person_notify_cb), &changed);
- priority = purple_person_get_priority_contact(person);
+ priority = purple_person_get_priority_contact_info(person); - /* Create and add all contacts. */
- for(gint i = 0; i < n_contacts; i++) {
- PurpleContact *contact = NULL;
+ /* Create and add all contact infos. */ + for(gint i = 0; i < n_infos; i++) { + PurpleContactInfo *info = NULL; PurplePresence *presence = NULL;
@@ -310,48 +299,49 @@
/* Now create a real contact. */
username = g_strdup_printf("username%d", i + 1);
- contact = purple_contact_new(account, username);
+ info = purple_contact_info_new(NULL); + purple_contact_info_set_username(info, username); /* Set the status for the contact. */
- presence = purple_contact_get_presence(contact);
+ presence = purple_contact_info_get_presence(info); status = purple_status_new(offline, presence);
g_object_set(G_OBJECT(presence), "active-status", status, NULL);
- purple_person_add_contact(person, contact);
+ purple_person_add_contact_info(person, info); - first = g_object_ref(contact);
+ first = g_object_ref(info); - if(i == n_contacts - 2) {
- sorted_contact = g_object_ref(contact);
+ sorted_contact = g_object_ref(info); sorted_presence = g_object_ref(presence);
- g_clear_object(&contact);
n_items = g_list_model_get_n_items(G_LIST_MODEL(person));
- g_assert_cmpuint(n_items, ==, n_contacts);
+ g_assert_cmpuint(n_items, ==, n_infos); - priority = purple_person_get_priority_contact(person);
+ priority = purple_person_get_priority_contact_info(person); g_assert_true(priority == first);
- /* Now set the second from the last contact's status to available, and
- * verify that that contact is now the priority contact.
+ /* Now set the second from the last contact info's status to available, and + * verify that that contact info is now the priority contact info. status = purple_status_new(available, sorted_presence);
g_object_set(G_OBJECT(sorted_presence), "active-status", status, NULL);
- priority = purple_person_get_priority_contact(person);
+ priority = purple_person_get_priority_contact_info(person); g_assert_true(priority == sorted_contact);
@@ -361,7 +351,6 @@
g_clear_object(&sorted_contact);
g_clear_object(&sorted_presence);
- g_clear_object(&account);