static gboolean individual_has_contact (FolksIndividual *individual, TpContact *contact) { GeeSet *personas; GeeIterator *iter; gboolean found = FALSE; personas = folks_individual_get_personas (individual); iter = gee_iterable_iterator (GEE_ITERABLE (personas)); while (!found && gee_iterator_next (iter)) { TpfPersona *persona = gee_iterator_get (iter); if (TPF_IS_PERSONA (persona)) { TpContact *c = tpf_persona_get_contact (persona); if (c == contact) found = TRUE; } g_clear_object (&persona); } g_clear_object (&iter); return found; }
/* Return the TpContact on @conn associated with @individual, if any */ TpContact * empathy_get_tp_contact_for_individual (FolksIndividual *individual, TpConnection *conn) { TpContact *contact = NULL; GeeSet *personas; GeeIterator *iter; personas = folks_individual_get_personas (individual); iter = gee_iterable_iterator (GEE_ITERABLE (personas)); while (contact == NULL && gee_iterator_next (iter)) { TpfPersona *persona = gee_iterator_get (iter); TpConnection *contact_conn; TpContact *contact_cur = NULL; if (TPF_IS_PERSONA (persona)) { contact_cur = tpf_persona_get_contact (persona); if (contact_cur != NULL) { contact_conn = tp_contact_get_connection (contact_cur); if (!tp_strdiff (tp_proxy_get_object_path (contact_conn), tp_proxy_get_object_path (conn))) contact = contact_cur; } } g_clear_object (&persona); } g_clear_object (&iter); return contact; }
/* Returns TRUE if the given Individual contains a TpContact */ gboolean empathy_folks_individual_contains_contact (FolksIndividual *individual) { GeeSet *personas; GeeIterator *iter; gboolean retval = FALSE; g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), FALSE); personas = folks_individual_get_personas (individual); iter = gee_iterable_iterator (GEE_ITERABLE (personas)); while (!retval && gee_iterator_next (iter)) { FolksPersona *persona = gee_iterator_get (iter); TpContact *contact = NULL; if (empathy_folks_persona_is_interesting (persona)) contact = tpf_persona_get_contact (TPF_PERSONA (persona)); g_clear_object (&persona); if (contact != NULL) retval = TRUE; } g_clear_object (&iter); return retval; }
/* @words = tpaw_live_search_strip_utf8_string (@text); * * User has to pass both so we don't have to compute @words ourself each time * this function is called. */ gboolean empathy_individual_match_string (FolksIndividual *individual, const char *text, GPtrArray *words) { const gchar *str; GeeSet *personas; GeeIterator *iter; gboolean retval = FALSE; /* check alias name */ str = folks_alias_details_get_alias (FOLKS_ALIAS_DETAILS (individual)); if (tpaw_live_search_match_words (str, words)) return TRUE; personas = folks_individual_get_personas (individual); /* check contact id, remove the @server.com part */ iter = gee_iterable_iterator (GEE_ITERABLE (personas)); while (retval == FALSE && gee_iterator_next (iter)) { FolksPersona *persona = gee_iterator_get (iter); const gchar *p; if (empathy_folks_persona_is_interesting (persona)) { str = folks_persona_get_display_id (persona); /* Accept the persona if @text is a full prefix of his ID; that allows * user to find, say, a jabber contact by typing his JID. */ if (g_str_has_prefix (str, text)) { retval = TRUE; } else { gchar *dup_str = NULL; gboolean visible; p = strstr (str, "@"); if (p != NULL) str = dup_str = g_strndup (str, p - str); visible = tpaw_live_search_match_words (str, words); g_free (dup_str); if (visible) retval = TRUE; } } g_clear_object (&persona); } g_clear_object (&iter); /* FIXME: Add more rules here, we could check phone numbers in * contact's vCard for example. */ return retval; }
/* Calculate whether the Individual can do audio or video calls. * FIXME: We can remove this once libfolks has grown capabilities support * again: bgo#626179. */ void empathy_individual_can_audio_video_call (FolksIndividual *individual, gboolean *can_audio_call, gboolean *can_video_call, EmpathyContact **out_contact) { GeeSet *personas; GeeIterator *iter; gboolean can_audio = FALSE, can_video = FALSE; personas = folks_individual_get_personas (individual); iter = gee_iterable_iterator (GEE_ITERABLE (personas)); while (gee_iterator_next (iter)) { FolksPersona *persona = gee_iterator_get (iter); TpContact *tp_contact; if (!empathy_folks_persona_is_interesting (persona)) goto while_finish; tp_contact = tpf_persona_get_contact (TPF_PERSONA (persona)); if (tp_contact != NULL) { EmpathyContact *contact; contact = empathy_contact_dup_from_tp_contact (tp_contact); empathy_contact_set_persona (contact, persona); can_audio = can_audio || empathy_contact_get_capabilities (contact) & EMPATHY_CAPABILITIES_AUDIO; can_video = can_video || empathy_contact_get_capabilities (contact) & EMPATHY_CAPABILITIES_VIDEO; if (out_contact != NULL) *out_contact = g_object_ref (contact); g_object_unref (contact); } while_finish: g_clear_object (&persona); if (can_audio && can_video) break; } g_clear_object (&iter); if (can_audio_call != NULL) *can_audio_call = can_audio; if (can_video_call != NULL) *can_video_call = can_video; }
/** * cinnamon_contact_system_get_email_for_display: * @self: A #CinnamonContactSystem * @individual A #FolksIndividual * * Get an email address (either from IM addresses or email), which can be * used to represent @individual. * * Return: (transfer full): a newly allocated string or %NULL if no address * was found */ char * cinnamon_contact_system_get_email_for_display (CinnamonContactSystem *self, FolksIndividual *individual) { GeeMultiMap *im_addr_map = folks_im_details_get_im_addresses (FOLKS_IM_DETAILS (individual)); GeeCollection *im_addrs = gee_multi_map_get_values (im_addr_map); GeeSet *email_addrs = folks_email_details_get_email_addresses (FOLKS_EMAIL_DETAILS (individual)); GeeIterator *addrs_iter; char *email = NULL; addrs_iter = gee_iterable_iterator (GEE_ITERABLE (im_addrs)); if (gee_iterator_first (addrs_iter)) { FolksImFieldDetails *field = gee_iterator_get (addrs_iter); email = g_strdup (folks_abstract_field_details_get_value ((FolksAbstractFieldDetails*)field)); g_object_unref (field); } g_object_unref (addrs_iter); g_object_unref (im_addrs); if (email != NULL) return email; addrs_iter = gee_iterable_iterator (GEE_ITERABLE (email_addrs)); if (gee_iterator_first (addrs_iter)) { FolksEmailFieldDetails *field = gee_iterator_get (addrs_iter); email = g_strdup (folks_abstract_field_details_get_value ((FolksAbstractFieldDetails*)field)); g_object_unref (field); } g_object_unref (addrs_iter); return email; }
static gboolean check_writeable_property (TpConnection *connection, FolksIndividual *individual, gchar *property) { gchar **properties; gint prop_len; gboolean retval = FALSE; GeeSet *personas; GeeIterator *iter; FolksPersonaStore *persona_store; persona_store = FOLKS_PERSONA_STORE ( empathy_dup_persona_store_for_connection (connection)); properties = folks_persona_store_get_always_writeable_properties (persona_store, &prop_len); retval = properties_contains (properties, prop_len, property); if (retval == TRUE) goto out; /* Lets see if the Individual contains a Persona with the given property */ personas = folks_individual_get_personas (individual); iter = gee_iterable_iterator (GEE_ITERABLE (personas)); while (!retval && gee_iterator_next (iter)) { FolksPersona *persona = gee_iterator_get (iter); properties = folks_persona_get_writeable_properties (persona, &prop_len); retval = properties_contains (properties, prop_len, property); g_clear_object (&persona); if (retval == TRUE) break; } g_clear_object (&iter); out: g_clear_object (&persona_store); return retval; }
void empathy_individual_manager_set_blocked (EmpathyIndividualManager *self, FolksIndividual *individual, gboolean blocked, gboolean abusive) { GeeSet *personas; GeeIterator *iter; g_return_if_fail (EMPATHY_IS_INDIVIDUAL_MANAGER (self)); personas = folks_individual_get_personas (individual); iter = gee_iterable_iterator (GEE_ITERABLE (personas)); while (gee_iterator_next (iter)) { TpfPersona *persona = gee_iterator_get (iter); if (TPF_IS_PERSONA (persona)) { TpContact *tp_contact; TpConnection *conn; tp_contact = tpf_persona_get_contact (persona); if (tp_contact == NULL) continue; conn = tp_contact_get_connection (tp_contact); if (!tp_proxy_has_interface_by_id (conn, TP_IFACE_QUARK_CONNECTION_INTERFACE_CONTACT_BLOCKING)) continue; if (blocked) tp_contact_block_async (tp_contact, abusive, NULL, NULL); else tp_contact_unblock_async (tp_contact, NULL, NULL); } g_clear_object (&persona); } g_clear_object (&iter); }
/* Retrieve the EmpathyContact corresponding to the first TpContact contained * within the given Individual. Note that this is a temporary convenience. See * the TODO above. */ EmpathyContact * empathy_contact_dup_from_folks_individual (FolksIndividual *individual) { GeeSet *personas; GeeIterator *iter; EmpathyContact *contact = NULL; g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL); personas = folks_individual_get_personas (individual); iter = gee_iterable_iterator (GEE_ITERABLE (personas)); while (gee_iterator_next (iter) && (contact == NULL)) { TpfPersona *persona = gee_iterator_get (iter); if (empathy_folks_persona_is_interesting (FOLKS_PERSONA (persona))) { TpContact *tp_contact; tp_contact = tpf_persona_get_contact (persona); if (tp_contact != NULL) { contact = empathy_contact_dup_from_tp_contact (tp_contact); empathy_contact_set_persona (contact, FOLKS_PERSONA (persona)); } } g_clear_object (&persona); } g_clear_object (&iter); if (contact == NULL) { DEBUG ("Can't create an EmpathyContact for Individual %s", folks_individual_get_id (individual)); } return contact; }
/** * empathy_individual_manager_supports_blocking * @self: the #EmpathyIndividualManager * @individual: an individual to check * * Indicates whether any personas of an @individual can be blocked. * * Returns: %TRUE if any persona supports contact blocking */ gboolean empathy_individual_manager_supports_blocking (EmpathyIndividualManager *self, FolksIndividual *individual) { GeeSet *personas; GeeIterator *iter; gboolean retval = FALSE; g_return_val_if_fail (EMPATHY_IS_INDIVIDUAL_MANAGER (self), FALSE); personas = folks_individual_get_personas (individual); iter = gee_iterable_iterator (GEE_ITERABLE (personas)); while (!retval && gee_iterator_next (iter)) { TpfPersona *persona = gee_iterator_get (iter); TpConnection *conn; if (TPF_IS_PERSONA (persona)) { TpContact *tp_contact; tp_contact = tpf_persona_get_contact (persona); if (tp_contact != NULL) { conn = tp_contact_get_connection (tp_contact); if (tp_proxy_has_interface_by_id (conn, TP_IFACE_QUARK_CONNECTION_INTERFACE_CONTACT_BLOCKING)) retval = TRUE; } } g_clear_object (&persona); } g_clear_object (&iter); return retval; }
static guint do_match (CinnamonContactSystem *self, FolksIndividual *individual, GSList *terms) { GSList *term_iter; guint weight = 0; char *alias = cinnamon_util_normalize_and_casefold (folks_alias_details_get_alias (FOLKS_ALIAS_DETAILS (individual))); char *name = cinnamon_util_normalize_and_casefold (folks_name_details_get_full_name (FOLKS_NAME_DETAILS (individual))); char *nick = cinnamon_util_normalize_and_casefold (folks_name_details_get_nickname (FOLKS_NAME_DETAILS (individual))); GeeMultiMap *im_addr_map = folks_im_details_get_im_addresses (FOLKS_IM_DETAILS (individual)); GeeCollection *im_addrs = gee_multi_map_get_values (im_addr_map); GeeSet *email_addrs = folks_email_details_get_email_addresses (FOLKS_EMAIL_DETAILS (individual)); GeeIterator *addrs_iter; gboolean have_name_prefix = FALSE; gboolean have_name_substring = FALSE; gboolean have_addr_prefix = FALSE; gboolean have_addr_substring = FALSE; for (term_iter = terms; term_iter; term_iter = term_iter->next) { const char *term = term_iter->data; const char *p; gboolean matched; matched = FALSE; /* Match on alias, name, nickname */ if (alias != NULL) { p = strstr (alias, term); if (p == alias) { have_name_prefix = TRUE; matched = TRUE; } else if (p != NULL) { have_name_substring = TRUE; matched = TRUE; } } if (name != NULL) { p = strstr (name, term); if (p == name) { have_name_prefix = TRUE; matched = TRUE; } else if (p != NULL) { have_name_substring = TRUE; matched = TRUE; } } if (nick != NULL) { p = strstr (nick, term); if (p == nick) { have_name_prefix = TRUE; matched = TRUE; } else if (p != NULL) { have_name_substring = TRUE; matched = TRUE; } } /* Match on one or more IM or email addresses */ addrs_iter = gee_iterable_iterator (GEE_ITERABLE (im_addrs)); while (gee_iterator_next (addrs_iter)) { FolksImFieldDetails *field = gee_iterator_get (addrs_iter); const gchar *addr = folks_abstract_field_details_get_value ((FolksAbstractFieldDetails*)field); p = strstr (addr, term); if (p == addr) { have_addr_prefix = TRUE; matched = TRUE; } else if (p != NULL) { have_addr_substring = TRUE; matched = TRUE; } g_object_unref (field); } g_object_unref (addrs_iter); addrs_iter = gee_iterable_iterator (GEE_ITERABLE (email_addrs)); while (gee_iterator_next (addrs_iter)) { FolksEmailFieldDetails *field = gee_iterator_get (addrs_iter); const gchar *addr = folks_abstract_field_details_get_value ((FolksAbstractFieldDetails*)field); p = strstr (addr, term); if (p == addr) { have_addr_prefix = TRUE; matched = TRUE; } else if (p != NULL) { have_addr_substring = TRUE; matched = TRUE; } g_object_unref (field); } g_object_unref (addrs_iter); if (!matched) { have_name_prefix = FALSE; have_name_substring = FALSE; have_addr_prefix = FALSE; have_addr_substring = FALSE; break; } } if (have_name_prefix) weight += NAME_PREFIX_MATCH_WEIGHT; else if (have_name_substring) weight += NAME_SUBSTRING_MATCH_WEIGHT; if (have_addr_prefix) weight += ADDR_PREFIX_MATCH_WEIGHT; else if (have_addr_substring) weight += ADDR_SUBSTRING_MATCH_WEIGHT; g_free (alias); g_free (name); g_free (nick); g_object_unref (im_addrs); return weight; }
/* * Block contact dialog */ gboolean empathy_block_individual_dialog_show (GtkWindow *parent, FolksIndividual *individual, GdkPixbuf *avatar, gboolean *abusive) { GtkWidget *dialog; GtkWidget *abusive_check = NULL; GeeSet *personas; GeeIterator *iter; GString *text = g_string_new (""); GString *blocked_str = g_string_new (""); GString *notblocked_str = g_string_new (""); guint npersonas_blocked = 0, npersonas_notblocked = 0; gboolean can_report_abuse = FALSE; int res; dialog = gtk_message_dialog_new (parent, GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, _("Block %s?"), folks_alias_details_get_alias (FOLKS_ALIAS_DETAILS (individual))); if (avatar != NULL) { GtkWidget *image = gtk_image_new_from_pixbuf (avatar); gtk_message_dialog_set_image (GTK_MESSAGE_DIALOG (dialog), image); gtk_widget_show (image); } /* build a list of personas that support blocking */ personas = folks_individual_get_personas (individual); iter = gee_iterable_iterator (GEE_ITERABLE (personas)); while (gee_iterator_next (iter)) { TpfPersona *persona = gee_iterator_get (iter); TpContact *contact; GString *s; char *str; TpConnection *conn; if (!TPF_IS_PERSONA (persona)) goto while_finish; contact = tpf_persona_get_contact (persona); if (contact == NULL) goto while_finish; conn = tp_contact_get_connection (contact); if (tp_proxy_has_interface_by_id (conn, TP_IFACE_QUARK_CONNECTION_INTERFACE_CONTACT_BLOCKING)) { s = blocked_str; npersonas_blocked++; } else { s = notblocked_str; npersonas_notblocked++; } if (tp_connection_can_report_abusive (conn)) can_report_abuse = TRUE; str = contact_pretty_name (contact); g_string_append_printf (s, "\n " BULLET_POINT " %s", str); g_free (str); while_finish: g_clear_object (&persona); } g_clear_object (&iter); g_string_append_printf (text, _("Are you sure you want to block '%s' from contacting you again?"), folks_alias_details_get_alias (FOLKS_ALIAS_DETAILS (individual))); if (npersonas_blocked > 0) g_string_append_printf (text, "\n\n%s\n%s", ngettext ("The following identity will be blocked:", "The following identities will be blocked:", npersonas_blocked), blocked_str->str); if (npersonas_notblocked > 0) g_string_append_printf (text, "\n\n%s\n%s", ngettext ("The following identity can not be blocked:", "The following identities can not be blocked:", npersonas_notblocked), notblocked_str->str); gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", text->str); gtk_dialog_add_buttons (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, _("_Block"), GTK_RESPONSE_REJECT, NULL); if (can_report_abuse) { GtkWidget *vbox; vbox = gtk_message_dialog_get_message_area (GTK_MESSAGE_DIALOG (dialog)); abusive_check = gtk_check_button_new_with_mnemonic ( ngettext ("_Report this contact as abusive", "_Report these contacts as abusive", npersonas_blocked)); gtk_box_pack_start (GTK_BOX (vbox), abusive_check, FALSE, TRUE, 0); gtk_widget_show (abusive_check); } g_string_free (text, TRUE); g_string_free (blocked_str, TRUE); g_string_free (notblocked_str, TRUE); res = gtk_dialog_run (GTK_DIALOG (dialog)); if (abusive != NULL) { if (abusive_check != NULL) *abusive = gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON (abusive_check)); else *abusive = FALSE; } gtk_widget_destroy (dialog); return res == GTK_RESPONSE_REJECT; }
static void aggregator_individuals_changed_cb (FolksIndividualAggregator *aggregator, GeeMultiMap *changes, EmpathyIndividualManager *self) { EmpathyIndividualManagerPriv *priv = GET_PRIV (self); GeeIterator *iter; GeeSet *removed; GeeCollection *added; GList *added_set = NULL, *added_filtered = NULL, *removed_list = NULL; /* We're not interested in the relationships between the added and removed * individuals, so just extract collections of them. Note that the added * collection may contain duplicates, while the removed set won't. */ removed = gee_multi_map_get_keys (changes); added = gee_multi_map_get_values (changes); /* Handle the removals first, as one of the added Individuals might have the * same ID as one of the removed Individuals (due to linking). */ iter = gee_iterable_iterator (GEE_ITERABLE (removed)); while (gee_iterator_next (iter)) { FolksIndividual *ind = gee_iterator_get (iter); if (ind == NULL) continue; g_signal_handlers_disconnect_by_func (ind, individual_notify_personas_cb, self); if (g_hash_table_lookup (priv->individuals, folks_individual_get_id (ind)) != NULL) { remove_individual (self, ind); removed_list = g_list_prepend (removed_list, ind); } g_clear_object (&ind); } g_clear_object (&iter); /* Filter the individuals for ones which contain EmpathyContacts */ iter = gee_iterable_iterator (GEE_ITERABLE (added)); while (gee_iterator_next (iter)) { FolksIndividual *ind = gee_iterator_get (iter); /* Make sure we handle each added individual only once. */ if (ind == NULL || g_list_find (added_set, ind) != NULL) continue; added_set = g_list_prepend (added_set, ind); g_signal_connect (ind, "notify::personas", G_CALLBACK (individual_notify_personas_cb), self); if (empathy_folks_individual_contains_contact (ind) == TRUE) { add_individual (self, ind); added_filtered = g_list_prepend (added_filtered, ind); } g_clear_object (&ind); } g_clear_object (&iter); g_list_free (added_set); g_object_unref (added); g_object_unref (removed); /* Bail if we have no individuals left */ if (added_filtered == NULL && removed == NULL) return; added_filtered = g_list_reverse (added_filtered); g_signal_emit (self, signals[MEMBERS_CHANGED], 0, NULL, added_filtered, removed_list, TP_CHANNEL_GROUP_CHANGE_REASON_NONE, TRUE); g_list_free (added_filtered); g_list_free (removed_list); }