2 * Copyright (C) 2003-2007 Imendio AB
3 * Copyright (C) 2007-2011 Collabora Ltd.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public
16 * License along with this program; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301 USA
20 * Authors: Richard Hult <richard@imendio.com>
21 * Martyn Russell <martyn@imendio.com>
22 * Xavier Claessens <xclaesse@gmail.com>
24 * Some snippets are taken from GnuTLS 2.8.6, which is distributed under the
25 * same GNU Lesser General Public License 2.1 (or later) version. See
26 * empathy_get_x509_certified_hostname ().
33 #include <sys/types.h>
35 #include <glib/gi18n-lib.h>
37 #include <libxml/uri.h>
39 #include <folks/folks.h>
40 #include <folks/folks-telepathy.h>
42 #include <telepathy-glib/account-manager.h>
43 #include <telepathy-glib/connection.h>
44 #include <telepathy-glib/channel.h>
45 #include <telepathy-glib/dbus.h>
46 #include <telepathy-glib/util.h>
48 #include "empathy-utils.h"
49 #include "empathy-contact-manager.h"
50 #include "empathy-individual-manager.h"
51 #include "empathy-presence-manager.h"
52 #include "empathy-request-util.h"
53 #include "empathy-tp-contact-factory.h"
55 #include <extensions/extensions.h>
57 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER
58 #include "empathy-debug.h"
60 /* Translation between presence types and string */
63 TpConnectionPresenceType type;
64 } presence_types[] = {
65 { "available", TP_CONNECTION_PRESENCE_TYPE_AVAILABLE },
66 { "busy", TP_CONNECTION_PRESENCE_TYPE_BUSY },
67 { "away", TP_CONNECTION_PRESENCE_TYPE_AWAY },
68 { "ext_away", TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY },
69 { "hidden", TP_CONNECTION_PRESENCE_TYPE_HIDDEN },
70 { "offline", TP_CONNECTION_PRESENCE_TYPE_OFFLINE },
71 { "unset", TP_CONNECTION_PRESENCE_TYPE_UNSET },
72 { "unknown", TP_CONNECTION_PRESENCE_TYPE_UNKNOWN },
73 { "error", TP_CONNECTION_PRESENCE_TYPE_ERROR },
74 /* alternative names */
75 { "dnd", TP_CONNECTION_PRESENCE_TYPE_BUSY },
76 { "brb", TP_CONNECTION_PRESENCE_TYPE_AWAY },
77 { "xa", TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY },
86 static gboolean initialized = FALSE;
94 bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
95 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
97 /* Setup debug output for empathy and telepathy-glib */
98 if (g_getenv ("EMPATHY_TIMING") != NULL) {
99 g_log_set_default_handler (tp_debug_timestamped_log_handler, NULL);
101 empathy_debug_set_flags (g_getenv ("EMPATHY_DEBUG"));
102 tp_debug_divert_messages (g_getenv ("EMPATHY_LOGFILE"));
110 empathy_substring (const gchar *str,
114 return g_strndup (str + start, end - start);
118 empathy_strcasecmp (const gchar *s1,
121 return empathy_strncasecmp (s1, s2, -1);
125 empathy_strncasecmp (const gchar *s1,
132 u1 = g_utf8_casefold (s1, n);
133 u2 = g_utf8_casefold (s2, n);
135 ret_val = g_utf8_collate (u1, u2);
143 empathy_xml_validate (xmlDoc *doc,
144 const gchar *dtd_filename)
152 path = g_build_filename (g_getenv ("EMPATHY_SRCDIR"), "libempathy",
154 if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
156 path = g_build_filename (DATADIR, "empathy", dtd_filename, NULL);
158 DEBUG ("Loading dtd file %s", path);
160 /* The list of valid chars is taken from libxml. */
161 escaped = xmlURIEscapeStr ((const xmlChar *) path,
162 (const xmlChar *)":@&=+$,/?;");
165 memset (&cvp, 0, sizeof (cvp));
166 dtd = xmlParseDTD (NULL, escaped);
167 ret = xmlValidateDtd (&cvp, doc, dtd);
176 empathy_xml_node_get_child (xmlNodePtr node,
177 const gchar *child_name)
181 g_return_val_if_fail (node != NULL, NULL);
182 g_return_val_if_fail (child_name != NULL, NULL);
184 for (l = node->children; l; l = l->next) {
185 if (l->name && strcmp ((const gchar *) l->name, child_name) == 0) {
194 empathy_xml_node_get_child_content (xmlNodePtr node,
195 const gchar *child_name)
199 g_return_val_if_fail (node != NULL, NULL);
200 g_return_val_if_fail (child_name != NULL, NULL);
202 l = empathy_xml_node_get_child (node, child_name);
204 return xmlNodeGetContent (l);
211 empathy_xml_node_find_child_prop_value (xmlNodePtr node,
212 const gchar *prop_name,
213 const gchar *prop_value)
216 xmlNodePtr found = NULL;
218 g_return_val_if_fail (node != NULL, NULL);
219 g_return_val_if_fail (prop_name != NULL, NULL);
220 g_return_val_if_fail (prop_value != NULL, NULL);
222 for (l = node->children; l && !found; l = l->next) {
225 if (!xmlHasProp (l, (const xmlChar *) prop_name)) {
229 prop = xmlGetProp (l, (const xmlChar *) prop_name);
230 if (prop && strcmp ((const gchar *) prop, prop_value) == 0) {
241 empathy_call_create_streamed_media_request (EmpathyContact *contact,
242 gboolean initial_audio,
243 gboolean initial_video)
246 TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
247 TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA,
248 TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT,
249 TP_HANDLE_TYPE_CONTACT,
250 TP_PROP_CHANNEL_TARGET_HANDLE, G_TYPE_UINT,
251 empathy_contact_get_handle (contact),
252 TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_AUDIO, G_TYPE_BOOLEAN,
254 TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_VIDEO, G_TYPE_BOOLEAN,
260 create_media_channel_cb (GObject *source,
261 GAsyncResult *result,
264 GError *error = NULL;
266 if (!tp_account_channel_request_create_channel_finish (TP_ACCOUNT_CHANNEL_REQUEST (source),
269 DEBUG ("Failed to create StreamedMedia channel: %s", error->message);
270 g_error_free (error);
275 empathy_call_new_with_streams (EmpathyContact *contact,
276 gboolean initial_audio,
277 gboolean initial_video,
282 TpAccountChannelRequest *req;
284 request = empathy_call_create_streamed_media_request (contact,
288 account = empathy_contact_get_account (contact);
290 req = tp_account_channel_request_new (account, request, timestamp);
292 tp_account_channel_request_create_channel_async (req, EMPATHY_AV_BUS_NAME,
293 NULL, create_media_channel_cb, NULL);
295 g_hash_table_unref (request);
296 g_object_unref (req);
300 empathy_presence_get_default_message (TpConnectionPresenceType presence)
303 case TP_CONNECTION_PRESENCE_TYPE_AVAILABLE:
304 return _("Available");
305 case TP_CONNECTION_PRESENCE_TYPE_BUSY:
307 case TP_CONNECTION_PRESENCE_TYPE_AWAY:
308 case TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY:
310 case TP_CONNECTION_PRESENCE_TYPE_HIDDEN:
311 return _("Invisible");
312 case TP_CONNECTION_PRESENCE_TYPE_OFFLINE:
314 case TP_CONNECTION_PRESENCE_TYPE_UNKNOWN:
316 case TP_CONNECTION_PRESENCE_TYPE_UNSET:
317 case TP_CONNECTION_PRESENCE_TYPE_ERROR:
326 empathy_presence_to_str (TpConnectionPresenceType presence)
330 for (i = 0 ; presence_types[i].name != NULL; i++)
331 if (presence == presence_types[i].type)
332 return presence_types[i].name;
337 TpConnectionPresenceType
338 empathy_presence_from_str (const gchar *str)
342 for (i = 0 ; presence_types[i].name != NULL; i++)
343 if (!tp_strdiff (str, presence_types[i].name))
344 return presence_types[i].type;
346 return TP_CONNECTION_PRESENCE_TYPE_UNSET;
350 empathy_status_reason_get_default_message (TpConnectionStatusReason reason)
353 case TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED:
354 return _("No reason specified");
355 case TP_CONNECTION_STATUS_REASON_REQUESTED:
356 return _("Status is set to offline");
357 case TP_CONNECTION_STATUS_REASON_NETWORK_ERROR:
358 return _("Network error");
359 case TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED:
360 return _("Authentication failed");
361 case TP_CONNECTION_STATUS_REASON_ENCRYPTION_ERROR:
362 return _("Encryption error");
363 case TP_CONNECTION_STATUS_REASON_NAME_IN_USE:
364 return _("Name in use");
365 case TP_CONNECTION_STATUS_REASON_CERT_NOT_PROVIDED:
366 return _("Certificate not provided");
367 case TP_CONNECTION_STATUS_REASON_CERT_UNTRUSTED:
368 return _("Certificate untrusted");
369 case TP_CONNECTION_STATUS_REASON_CERT_EXPIRED:
370 return _("Certificate expired");
371 case TP_CONNECTION_STATUS_REASON_CERT_NOT_ACTIVATED:
372 return _("Certificate not activated");
373 case TP_CONNECTION_STATUS_REASON_CERT_HOSTNAME_MISMATCH:
374 return _("Certificate hostname mismatch");
375 case TP_CONNECTION_STATUS_REASON_CERT_FINGERPRINT_MISMATCH:
376 return _("Certificate fingerprint mismatch");
377 case TP_CONNECTION_STATUS_REASON_CERT_SELF_SIGNED:
378 return _("Certificate self-signed");
379 case TP_CONNECTION_STATUS_REASON_CERT_OTHER_ERROR:
380 return _("Certificate error");
382 return _("Unknown reason");
387 create_errors_to_message_hash (void)
391 errors = g_hash_table_new (g_str_hash, g_str_equal);
392 g_hash_table_insert (errors, TP_ERROR_STR_NETWORK_ERROR, _("Network error"));
393 g_hash_table_insert (errors, TP_ERROR_STR_AUTHENTICATION_FAILED,
394 _("Authentication failed"));
395 g_hash_table_insert (errors, TP_ERROR_STR_ENCRYPTION_ERROR,
396 _("Encryption error"));
397 g_hash_table_insert (errors, TP_ERROR_STR_CERT_NOT_PROVIDED,
398 _("Certificate not provided"));
399 g_hash_table_insert (errors, TP_ERROR_STR_CERT_UNTRUSTED,
400 _("Certificate untrusted"));
401 g_hash_table_insert (errors, TP_ERROR_STR_CERT_EXPIRED,
402 _("Certificate expired"));
403 g_hash_table_insert (errors, TP_ERROR_STR_CERT_NOT_ACTIVATED,
404 _("Certificate not activated"));
405 g_hash_table_insert (errors, TP_ERROR_STR_CERT_HOSTNAME_MISMATCH,
406 _("Certificate hostname mismatch"));
407 g_hash_table_insert (errors, TP_ERROR_STR_CERT_FINGERPRINT_MISMATCH,
408 _("Certificate fingerprint mismatch"));
409 g_hash_table_insert (errors, TP_ERROR_STR_CERT_SELF_SIGNED,
410 _("Certificate self-signed"));
411 g_hash_table_insert (errors, TP_ERROR_STR_CANCELLED,
412 _("Status is set to offline"));
413 g_hash_table_insert (errors, TP_ERROR_STR_ENCRYPTION_NOT_AVAILABLE,
414 _("Encryption is not available"));
415 g_hash_table_insert (errors, TP_ERROR_STR_CERT_INVALID,
416 _("Certificate is invalid"));
417 g_hash_table_insert (errors, TP_ERROR_STR_CONNECTION_REFUSED,
418 _("Connection has been refused"));
419 g_hash_table_insert (errors, TP_ERROR_STR_CONNECTION_FAILED,
420 _("Connection can't be established"));
421 g_hash_table_insert (errors, TP_ERROR_STR_CONNECTION_LOST,
422 _("Connection has been lost"));
423 g_hash_table_insert (errors, TP_ERROR_STR_ALREADY_CONNECTED,
424 _("This resource is already connected to the server"));
425 g_hash_table_insert (errors, TP_ERROR_STR_CONNECTION_REPLACED,
426 _("Connection has been replaced by a new connection using the "
428 g_hash_table_insert (errors, TP_ERROR_STR_REGISTRATION_EXISTS,
429 _("The account already exists on the server"));
430 g_hash_table_insert (errors, TP_ERROR_STR_SERVICE_BUSY,
431 _("Server is currently too busy to handle the connection"));
432 g_hash_table_insert (errors, TP_ERROR_STR_CERT_REVOKED,
433 _("Certificate has been revoked"));
434 g_hash_table_insert (errors, TP_ERROR_STR_CERT_INSECURE,
435 _("Certificate uses an insecure cipher algorithm or is "
436 "cryptographically weak"));
437 g_hash_table_insert (errors, TP_ERROR_STR_CERT_LIMIT_EXCEEDED,
438 _("The length of the server certificate, or the depth of the "
439 "server certificate chain, exceed the limits imposed by the "
440 "cryptography library"));
446 empathy_dbus_error_name_get_default_message (const gchar *error)
448 static GHashTable *errors_to_message = NULL;
453 if (G_UNLIKELY (errors_to_message == NULL)) {
454 errors_to_message = create_errors_to_message_hash ();
457 return g_hash_table_lookup (errors_to_message, error);
461 empathy_account_get_error_message (TpAccount *account,
462 gboolean *user_requested)
464 const gchar *dbus_error;
465 const gchar *message;
466 const GHashTable *details = NULL;
467 TpConnectionStatusReason reason;
469 dbus_error = tp_account_get_detailed_error (account, &details);
471 if (user_requested != NULL)
473 if (tp_asv_get_boolean (details, "user-requested", NULL))
474 *user_requested = TRUE;
476 *user_requested = FALSE;
479 message = empathy_dbus_error_name_get_default_message (dbus_error);
483 DEBUG ("Don't understand error '%s'; fallback to the status reason (%u)",
486 tp_account_get_connection_status (account, &reason);
488 return empathy_status_reason_get_default_message (reason);
492 empathy_file_lookup (const gchar *filename, const gchar *subdir)
500 path = g_build_filename (g_getenv ("EMPATHY_SRCDIR"), subdir, filename, NULL);
501 if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
503 path = g_build_filename (DATADIR, "empathy", filename, NULL);
510 empathy_proxy_hash (gconstpointer key)
512 TpProxy *proxy = TP_PROXY (key);
513 TpProxyClass *proxy_class = TP_PROXY_GET_CLASS (key);
515 g_return_val_if_fail (TP_IS_PROXY (proxy), 0);
516 g_return_val_if_fail (proxy_class->must_have_unique_name, 0);
518 return g_str_hash (proxy->object_path) ^ g_str_hash (proxy->bus_name);
522 empathy_proxy_equal (gconstpointer a,
525 TpProxy *proxy_a = TP_PROXY (a);
526 TpProxy *proxy_b = TP_PROXY (b);
527 TpProxyClass *proxy_a_class = TP_PROXY_GET_CLASS (a);
528 TpProxyClass *proxy_b_class = TP_PROXY_GET_CLASS (b);
530 g_return_val_if_fail (TP_IS_PROXY (proxy_a), FALSE);
531 g_return_val_if_fail (TP_IS_PROXY (proxy_b), FALSE);
532 g_return_val_if_fail (proxy_a_class->must_have_unique_name, 0);
533 g_return_val_if_fail (proxy_b_class->must_have_unique_name, 0);
535 return g_str_equal (proxy_a->object_path, proxy_b->object_path) &&
536 g_str_equal (proxy_a->bus_name, proxy_b->bus_name);
540 empathy_check_available_state (void)
542 TpConnectionPresenceType presence;
543 EmpathyPresenceManager *presence_mgr;
545 presence_mgr = empathy_presence_manager_dup_singleton ();
546 presence = empathy_presence_manager_get_state (presence_mgr);
547 g_object_unref (presence_mgr);
549 if (presence != TP_CONNECTION_PRESENCE_TYPE_AVAILABLE &&
550 presence != TP_CONNECTION_PRESENCE_TYPE_UNSET) {
558 empathy_uint_compare (gconstpointer a,
561 return *(guint *) a - *(guint *) b;
565 empathy_protocol_icon_name (const gchar *protocol)
567 if (!tp_strdiff (protocol, "yahoojp"))
568 /* Yahoo Japan uses the same icon as Yahoo */
570 else if (!tp_strdiff (protocol, "simple"))
571 /* SIMPLE uses the same icon as SIP */
573 else if (!tp_strdiff (protocol, "sms"))
574 return g_strdup ("phone");
576 return g_strdup_printf ("im-%s", protocol);
580 empathy_type_dbus_ao (void)
584 if (G_UNLIKELY (t == 0))
585 t = dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH);
591 empathy_protocol_name_to_display_name (const gchar *proto_name)
596 const gchar *display;
599 { "jabber", "Jabber", FALSE },
600 { "msn", "Windows Live (MSN)", FALSE, },
601 { "local-xmpp", N_("People Nearby"), TRUE },
602 { "irc", "IRC", FALSE },
603 { "icq", "ICQ", FALSE },
604 { "aim", "AIM", FALSE },
605 { "yahoo", "Yahoo!", FALSE },
606 { "yahoojp", N_("Yahoo! Japan"), TRUE },
607 { "groupwise", "GroupWise", FALSE },
608 { "sip", "SIP", FALSE },
612 for (i = 0; names[i].proto != NULL; i++)
614 if (!tp_strdiff (proto_name, names[i].proto))
616 if (names[i].translated)
617 return gettext (names[i].display);
619 return names[i].display;
627 empathy_service_name_to_display_name (const gchar *service_name)
631 const gchar *service;
632 const gchar *display;
635 { "google-talk", N_("Google Talk"), FALSE },
636 { "facebook", N_("Facebook Chat"), TRUE },
640 for (i = 0; names[i].service != NULL; i++)
642 if (!tp_strdiff (service_name, names[i].service))
644 if (names[i].translated)
645 return gettext (names[i].display);
647 return names[i].display;
654 /* Note: this function depends on the account manager having its core feature
657 empathy_get_account_for_connection (TpConnection *connection)
659 TpAccountManager *manager;
660 TpAccount *account = NULL;
663 manager = tp_account_manager_dup ();
665 accounts = tp_account_manager_get_valid_accounts (manager);
667 for (l = accounts; l != NULL; l = l->next)
669 TpAccount *a = l->data;
671 if (tp_account_get_connection (a) == connection)
678 g_list_free (accounts);
679 g_object_unref (manager);
685 empathy_account_manager_get_accounts_connected (gboolean *connecting)
687 TpAccountManager *manager;
689 gboolean out_connecting = FALSE;
690 gboolean out_connected = FALSE;
692 manager = tp_account_manager_dup ();
694 if (G_UNLIKELY (!tp_account_manager_is_prepared (manager,
695 TP_ACCOUNT_MANAGER_FEATURE_CORE)))
696 g_critical (G_STRLOC ": %s called before AccountManager ready", G_STRFUNC);
698 accounts = tp_account_manager_get_valid_accounts (manager);
700 for (l = accounts; l != NULL; l = l->next)
702 TpConnectionStatus s = tp_account_get_connection_status (
703 TP_ACCOUNT (l->data), NULL);
705 if (s == TP_CONNECTION_STATUS_CONNECTING)
706 out_connecting = TRUE;
707 else if (s == TP_CONNECTION_STATUS_CONNECTED)
708 out_connected = TRUE;
710 if (out_connecting && out_connected)
714 g_list_free (accounts);
715 g_object_unref (manager);
717 if (connecting != NULL)
718 *connecting = out_connecting;
720 return out_connected;
723 /* Change the RequestedPresence of a newly created account to ensure that it
724 * is actually connected. */
726 empathy_connect_new_account (TpAccount *account,
727 TpAccountManager *account_manager)
729 TpConnectionPresenceType presence;
730 gchar *status, *message;
732 /* only force presence if presence was offline, unknown or unset */
733 presence = tp_account_get_requested_presence (account, NULL, NULL);
736 case TP_CONNECTION_PRESENCE_TYPE_OFFLINE:
737 case TP_CONNECTION_PRESENCE_TYPE_UNKNOWN:
738 case TP_CONNECTION_PRESENCE_TYPE_UNSET:
739 presence = tp_account_manager_get_most_available_presence (
740 account_manager, &status, &message);
742 if (presence == TP_CONNECTION_PRESENCE_TYPE_OFFLINE)
743 /* Global presence is offline; we force it so user doesn't have to
744 * manually change the presence to connect his new account. */
745 presence = TP_CONNECTION_PRESENCE_TYPE_AVAILABLE;
747 tp_account_request_presence_async (account, presence,
748 status, NULL, NULL, NULL);
754 case TP_CONNECTION_PRESENCE_TYPE_AVAILABLE:
755 case TP_CONNECTION_PRESENCE_TYPE_AWAY:
756 case TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY:
757 case TP_CONNECTION_PRESENCE_TYPE_HIDDEN:
758 case TP_CONNECTION_PRESENCE_TYPE_BUSY:
759 case TP_CONNECTION_PRESENCE_TYPE_ERROR:
761 /* do nothing if the presence is not offline */
766 /* Translate Folks' general presence type to the Tp presence type */
767 TpConnectionPresenceType
768 empathy_folks_presence_type_to_tp (FolksPresenceType type)
770 return (TpConnectionPresenceType) type;
773 /* Returns TRUE if the given Individual contains a TpContact */
775 empathy_folks_individual_contains_contact (FolksIndividual *individual)
779 g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), FALSE);
781 personas = folks_individual_get_personas (individual);
782 for (l = personas; l != NULL; l = l->next)
784 if (empathy_folks_persona_is_interesting (FOLKS_PERSONA (l->data)))
785 return (tpf_persona_get_contact (TPF_PERSONA (l->data)) != NULL);
791 /* TODO: this needs to be eliminated (and replaced in some cases with user
792 * prompts) when we break the assumption that FolksIndividuals are 1:1 with
795 /* Retrieve the EmpathyContact corresponding to the first TpContact contained
796 * within the given Individual. Note that this is a temporary convenience. See
799 empathy_contact_dup_from_folks_individual (FolksIndividual *individual)
802 EmpathyContact *contact = NULL;
804 g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);
806 personas = folks_individual_get_personas (individual);
807 for (l = personas; (l != NULL) && (contact == NULL); l = l->next)
809 TpfPersona *persona = l->data;
811 if (empathy_folks_persona_is_interesting (FOLKS_PERSONA (persona)))
813 TpContact *tp_contact;
815 tp_contact = tpf_persona_get_contact (persona);
816 contact = empathy_contact_dup_from_tp_contact (tp_contact);
817 empathy_contact_set_persona (contact, FOLKS_PERSONA (persona));
824 TpChannelGroupChangeReason
825 tp_channel_group_change_reason_from_folks_groups_change_reason (
826 FolksGroupDetailsChangeReason reason)
828 return (TpChannelGroupChangeReason) reason;
832 empathy_get_persona_store_for_connection (TpConnection *connection)
834 FolksBackendStore *backend_store;
835 FolksBackend *backend;
836 TpfPersonaStore *result = NULL;
838 backend_store = folks_backend_store_dup ();
839 backend = folks_backend_store_dup_backend_by_name (backend_store,
843 GHashTable *stores_hash;
846 stores_hash = folks_backend_get_persona_stores (backend);
847 stores = g_hash_table_get_values (stores_hash);
848 for (l = stores; l != NULL && result == NULL; l = l->next)
850 TpfPersonaStore *persona_store = TPF_PERSONA_STORE (l->data);
852 TpConnection *conn_cur;
854 account = tpf_persona_store_get_account (persona_store);
855 conn_cur = tp_account_get_connection (account);
856 if (conn_cur == connection)
857 result = persona_store;
860 g_list_free (stores);
863 g_object_unref (backend);
864 g_object_unref (backend_store);
870 empathy_connection_can_add_personas (TpConnection *connection)
872 FolksPersonaStore *persona_store;
874 g_return_val_if_fail (TP_IS_CONNECTION (connection), FALSE);
876 persona_store = FOLKS_PERSONA_STORE (
877 empathy_get_persona_store_for_connection (connection));
879 return (folks_persona_store_get_can_add_personas (persona_store) ==
880 FOLKS_MAYBE_BOOL_TRUE);
884 empathy_connection_can_alias_personas (TpConnection *connection)
886 FolksPersonaStore *persona_store;
888 g_return_val_if_fail (TP_IS_CONNECTION (connection), FALSE);
890 persona_store = FOLKS_PERSONA_STORE (
891 empathy_get_persona_store_for_connection (connection));
893 return (folks_persona_store_get_can_alias_personas (persona_store) ==
894 FOLKS_MAYBE_BOOL_TRUE);
898 empathy_connection_can_group_personas (TpConnection *connection)
900 FolksPersonaStore *persona_store;
902 g_return_val_if_fail (TP_IS_CONNECTION (connection), FALSE);
904 persona_store = FOLKS_PERSONA_STORE (
905 empathy_get_persona_store_for_connection (connection));
907 return (folks_persona_store_get_can_group_personas (persona_store) ==
908 FOLKS_MAYBE_BOOL_TRUE);
912 empathy_folks_persona_is_interesting (FolksPersona *persona)
914 /* We're not interested in non-Telepathy personas */
915 if (!TPF_IS_PERSONA (persona))
918 /* We're not interested in user personas which haven't been added to the
919 * contact list (see bgo#637151). */
920 if (folks_persona_get_is_user (persona) &&
921 !tpf_persona_get_is_in_contact_list (TPF_PERSONA (persona)))
930 empathy_get_x509_certificate_hostname (gnutls_x509_crt_t cert)
937 /* this snippet is taken from GnuTLS.
938 * see gnutls/lib/x509/rfc2818_hostname.c
940 for (idx = 0; res >= 0; idx++)
942 dns_name_size = sizeof (dns_name);
943 res = gnutls_x509_crt_get_subject_alt_name (cert, idx,
944 dns_name, &dns_name_size, NULL);
946 if (res == GNUTLS_SAN_DNSNAME || res == GNUTLS_SAN_IPADDRESS)
947 return g_strndup (dns_name, dns_name_size);
950 dns_name_size = sizeof (dns_name);
951 res = gnutls_x509_crt_get_dn_by_oid (cert, GNUTLS_OID_X520_COMMON_NAME,
952 0, 0, dns_name, &dns_name_size);
955 return g_strndup (dns_name, dns_name_size);