* Authors: Richard Hult <richard@imendio.com>
* Martyn Russell <martyn@imendio.com>
* Xavier Claessens <xclaesse@gmail.com>
+ *
+ * Some snippets are taken from GnuTLS 2.8.6, which is distributed under the
+ * same GNU Lesser General Public License 2.1 (or later) version. See
+ * empathy_get_x509_certified_hostname ().
*/
#include "config.h"
#include "empathy-contact-manager.h"
#include "empathy-individual-manager.h"
#include "empathy-dispatcher.h"
-#include "empathy-dispatch-operation.h"
#include "empathy-idle.h"
#include "empathy-tp-call.h"
#include "empathy-tp-contact-factory.h"
/* Translation between presence types and string */
static struct {
- gchar *name;
+ const gchar *name;
TpConnectionPresenceType type;
} presence_types[] = {
{ "available", TP_CONNECTION_PRESENCE_TYPE_AVAILABLE },
return _("Unknown");
case TP_CONNECTION_PRESENCE_TYPE_UNSET:
case TP_CONNECTION_PRESENCE_TYPE_ERROR:
+ default:
return NULL;
}
return TP_CONNECTION_PRESENCE_TYPE_UNSET;
}
-const gchar *
+static const gchar *
empathy_status_reason_get_default_message (TpConnectionStatusReason reason)
{
switch (reason) {
}
}
+static GHashTable *
+create_errors_to_message_hash (void)
+{
+ GHashTable *errors;
+
+ errors = g_hash_table_new (g_str_hash, g_str_equal);
+ g_hash_table_insert (errors, TP_ERROR_STR_NETWORK_ERROR, _("Network error"));
+ g_hash_table_insert (errors, TP_ERROR_STR_AUTHENTICATION_FAILED,
+ _("Authentication failed"));
+ g_hash_table_insert (errors, TP_ERROR_STR_ENCRYPTION_ERROR,
+ _("Encryption error"));
+ g_hash_table_insert (errors, TP_ERROR_STR_CERT_NOT_PROVIDED,
+ _("Certificate not provided"));
+ g_hash_table_insert (errors, TP_ERROR_STR_CERT_UNTRUSTED,
+ _("Certificate untrusted"));
+ g_hash_table_insert (errors, TP_ERROR_STR_CERT_EXPIRED,
+ _("Certificate expired"));
+ g_hash_table_insert (errors, TP_ERROR_STR_CERT_NOT_ACTIVATED,
+ _("Certificate not activated"));
+ g_hash_table_insert (errors, TP_ERROR_STR_CERT_HOSTNAME_MISMATCH,
+ _("Certificate hostname mismatch"));
+ g_hash_table_insert (errors, TP_ERROR_STR_CERT_FINGERPRINT_MISMATCH,
+ _("Certificate fingerprint mismatch"));
+ g_hash_table_insert (errors, TP_ERROR_STR_CERT_SELF_SIGNED,
+ _("Certificate self-signed"));
+ g_hash_table_insert (errors, TP_ERROR_STR_CANCELLED,
+ _("Status is set to offline"));
+ g_hash_table_insert (errors, TP_ERROR_STR_ENCRYPTION_NOT_AVAILABLE,
+ _("Encryption is not available"));
+ g_hash_table_insert (errors, TP_ERROR_STR_CERT_INVALID,
+ _("Certificate is invalid"));
+ g_hash_table_insert (errors, TP_ERROR_STR_CONNECTION_REFUSED,
+ _("Connection has been refused"));
+ g_hash_table_insert (errors, TP_ERROR_STR_CONNECTION_FAILED,
+ _("Connection can't be established"));
+ g_hash_table_insert (errors, TP_ERROR_STR_CONNECTION_LOST,
+ _("Connection has been lost"));
+ g_hash_table_insert (errors, TP_ERROR_STR_ALREADY_CONNECTED,
+ _("This resource is already connected to the server"));
+ g_hash_table_insert (errors, TP_ERROR_STR_CONNECTION_REPLACED,
+ _("Connection has been replaced by a new connection using the "
+ "same resource"));
+ g_hash_table_insert (errors, TP_ERROR_STR_REGISTRATION_EXISTS,
+ _("The account already exists on the server"));
+ g_hash_table_insert (errors, TP_ERROR_STR_SERVICE_BUSY,
+ _("Server is currently too busy to handle the connection"));
+ g_hash_table_insert (errors, TP_ERROR_STR_CERT_REVOKED,
+ _("Certificate has been revoked"));
+ g_hash_table_insert (errors, TP_ERROR_STR_CERT_INSECURE,
+ _("Certificate uses an insecure cipher algorithm or is "
+ "cryptographically weak"));
+ g_hash_table_insert (errors, TP_ERROR_STR_CERT_LIMIT_EXCEEDED,
+ _("The length of the server certificate, or the depth of the "
+ "server certificate chain, exceed the limits imposed by the "
+ "cryptography library"));
+
+ return errors;
+}
+
+static const gchar *
+empathy_dbus_error_name_get_default_message (const gchar *error)
+{
+ static GHashTable *errors_to_message = NULL;
+
+ if (error == NULL)
+ return NULL;
+
+ if (G_UNLIKELY (errors_to_message == NULL)) {
+ errors_to_message = create_errors_to_message_hash ();
+ }
+
+ return g_hash_table_lookup (errors_to_message, error);
+}
+
+const gchar *
+empathy_account_get_error_message (TpAccount *account,
+ gboolean *user_requested)
+{
+ const gchar *dbus_error;
+ const gchar *message;
+ const GHashTable *details = NULL;
+ TpConnectionStatusReason reason;
+
+ dbus_error = tp_account_get_detailed_error (account, &details);
+
+ if (user_requested != NULL)
+ {
+ if (tp_asv_get_boolean (details, "user-requested", NULL))
+ *user_requested = TRUE;
+ else
+ *user_requested = FALSE;
+ }
+
+ message = empathy_dbus_error_name_get_default_message (dbus_error);
+ if (message != NULL)
+ return message;
+
+ DEBUG ("Don't understand error '%s'; fallback to the status reason (%u)",
+ dbus_error, reason);
+
+ tp_account_get_connection_status (account, &reason);
+
+ return empathy_status_reason_get_default_message (reason);
+}
+
gchar *
empathy_file_lookup (const gchar *filename, const gchar *subdir)
{
gboolean translated;
} names[] = {
{ "jabber", "Jabber", FALSE },
- { "gtalk", "Google Talk", FALSE },
{ "msn", "MSN", FALSE, },
{ "local-xmpp", N_("People Nearby"), TRUE },
{ "irc", "IRC", FALSE },
{ "aim", "AIM", FALSE },
{ "yahoo", "Yahoo!", FALSE },
{ "yahoojp", N_("Yahoo! Japan"), TRUE },
- { "facebook", N_("Facebook Chat"), TRUE },
{ "groupwise", "GroupWise", FALSE },
{ "sip", "SIP", FALSE },
{ NULL, NULL }
if (!tp_strdiff (proto_name, names[i].proto))
{
if (names[i].translated)
- return _(names[i].display);
+ return gettext (names[i].display);
else
return names[i].display;
}
}
- return NULL;
+ return proto_name;
+}
+
+const char *
+empathy_service_name_to_display_name (const gchar *service_name)
+{
+ int i;
+ static struct {
+ const gchar *service;
+ const gchar *display;
+ gboolean translated;
+ } names[] = {
+ { "google-talk", N_("Google Talk"), FALSE },
+ { "facebook", N_("Facebook Chat"), TRUE },
+ { NULL, NULL }
+ };
+
+ for (i = 0; names[i].service != NULL; i++)
+ {
+ if (!tp_strdiff (service_name, names[i].service))
+ {
+ if (names[i].translated)
+ return gettext (names[i].display);
+ else
+ return names[i].display;
+ }
+ }
+
+ return service_name;
}
/* Note: this function depends on the account manager having its core feature
g_free (message);
break;
+ case TP_CONNECTION_PRESENCE_TYPE_AVAILABLE:
+ case TP_CONNECTION_PRESENCE_TYPE_AWAY:
+ case TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY:
+ case TP_CONNECTION_PRESENCE_TYPE_HIDDEN:
+ case TP_CONNECTION_PRESENCE_TYPE_BUSY:
+ case TP_CONNECTION_PRESENCE_TYPE_ERROR:
default:
/* do nothing if the presence is not offline */
break;
}
}
+/* Translate Folks' general presence type to the Tp presence type */
TpConnectionPresenceType
empathy_folks_presence_type_to_tp (FolksPresenceType type)
{
return (TpConnectionPresenceType) type;
}
+/* Returns TRUE if the given Individual contains a TpContact */
gboolean
empathy_folks_individual_contains_contact (FolksIndividual *individual)
{
personas = folks_individual_get_personas (individual);
for (l = personas; l != NULL; l = l->next)
{
- TpfPersona *persona = l->data;
-
- if (TPF_IS_PERSONA (persona))
- {
- TpContact *contact = tpf_persona_get_contact (persona);
-
- if (TP_IS_CONTACT (contact))
- return TRUE;
- }
+ if (TPF_IS_PERSONA (l->data))
+ return (tpf_persona_get_contact (TPF_PERSONA (l->data)) != NULL);
}
return FALSE;
/* TODO: this needs to be eliminated (and replaced in some cases with user
* prompts) when we break the assumption that FolksIndividuals are 1:1 with
* TpContacts */
+
+/* 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_from_folks_individual (FolksIndividual *individual)
+empathy_contact_dup_from_folks_individual (FolksIndividual *individual)
{
GList *personas, *l;
EmpathyContact *contact = NULL;
tp_contact = tpf_persona_get_contact (persona);
contact = empathy_contact_dup_from_tp_contact (tp_contact);
+ empathy_contact_set_persona (contact, FOLKS_PERSONA (persona));
}
}
return contact;
}
-/* TODO: This also needs to be eliminated, and is horrifically slow. */
-FolksIndividual *
-folks_individual_from_empathy_contact (EmpathyContact *contact)
+TpChannelGroupChangeReason
+tp_channel_group_change_reason_from_folks_groups_change_reason (
+ FolksGroupableChangeReason reason)
{
- EmpathyIndividualManager *manager;
- FolksIndividual *individual = NULL;
- GList *individuals, *l;
-
- manager = empathy_individual_manager_dup_singleton ();
- individuals = empathy_individual_manager_get_members (manager);
+ return (TpChannelGroupChangeReason) reason;
+}
- for (l = individuals; (l != NULL) && (individual == NULL); l = l->next)
+TpfPersonaStore *
+empathy_get_persona_store_for_connection (TpConnection *connection)
+{
+ FolksBackendStore *backend_store;
+ FolksBackend *backend;
+ TpfPersonaStore *result = NULL;
+
+ backend_store = folks_backend_store_dup ();
+ backend = folks_backend_store_get_backend_by_name (backend_store,
+ "telepathy");
+ if (backend != NULL)
{
- FolksIndividual *i = FOLKS_INDIVIDUAL (l->data);
- EmpathyContact *c = empathy_contact_from_folks_individual (i);
+ GHashTable *stores_hash;
+ GList *stores, *l;
- if (c == contact)
- individual = g_object_ref (i);
+ stores_hash = folks_backend_get_persona_stores (backend);
+ stores = g_hash_table_get_values (stores_hash);
+ for (l = stores; l != NULL && result == NULL; l = l->next)
+ {
+ TpfPersonaStore *persona_store = TPF_PERSONA_STORE (l->data);
+ TpAccount *account;
+ TpConnection *conn_cur;
+
+ account = tpf_persona_store_get_account (persona_store);
+ conn_cur = tp_account_get_connection (account);
+ if (conn_cur == connection)
+ result = persona_store;
+ }
- g_object_unref (c);
+ g_list_free (stores);
}
- g_list_free (individuals);
- g_object_unref (manager);
+ g_object_unref (backend);
+ g_object_unref (backend_store);
+
+ return result;
+}
+
+gboolean
+empathy_connection_can_add_personas (TpConnection *connection)
+{
+ FolksPersonaStore *persona_store;
+
+ g_return_val_if_fail (TP_IS_CONNECTION (connection), FALSE);
+
+ persona_store = FOLKS_PERSONA_STORE (
+ empathy_get_persona_store_for_connection (connection));
+
+ return (folks_persona_store_get_can_add_personas (persona_store) ==
+ FOLKS_MAYBE_BOOL_TRUE);
+}
- return individual;
+gboolean
+empathy_connection_can_alias_personas (TpConnection *connection)
+{
+ FolksPersonaStore *persona_store;
+
+ g_return_val_if_fail (TP_IS_CONNECTION (connection), FALSE);
+
+ persona_store = FOLKS_PERSONA_STORE (
+ empathy_get_persona_store_for_connection (connection));
+
+ return (folks_persona_store_get_can_alias_personas (persona_store) ==
+ FOLKS_MAYBE_BOOL_TRUE);
+}
+
+gboolean
+empathy_connection_can_group_personas (TpConnection *connection)
+{
+ FolksPersonaStore *persona_store;
+
+ g_return_val_if_fail (TP_IS_CONNECTION (connection), FALSE);
+
+ persona_store = FOLKS_PERSONA_STORE (
+ empathy_get_persona_store_for_connection (connection));
+
+ return (folks_persona_store_get_can_group_personas (persona_store) ==
+ FOLKS_MAYBE_BOOL_TRUE);
+}
+
+gchar *
+empathy_get_x509_certificate_hostname (gnutls_x509_crt_t cert)
+{
+ gchar dns_name[256];
+ gsize dns_name_size;
+ gint idx;
+ gint res = 0;
+
+ /* this snippet is taken from GnuTLS.
+ * see gnutls/lib/x509/rfc2818_hostname.c
+ */
+ for (idx = 0; res >= 0; idx++)
+ {
+ dns_name_size = sizeof (dns_name);
+ res = gnutls_x509_crt_get_subject_alt_name (cert, idx,
+ dns_name, &dns_name_size, NULL);
+
+ if (res == GNUTLS_SAN_DNSNAME || res == GNUTLS_SAN_IPADDRESS)
+ return g_strndup (dns_name, dns_name_size);
+ }
+
+ dns_name_size = sizeof (dns_name);
+ res = gnutls_x509_crt_get_dn_by_oid (cert, GNUTLS_OID_X520_COMMON_NAME,
+ 0, 0, dns_name, &dns_name_size);
+
+ if (res >= 0)
+ return g_strndup (dns_name, dns_name_size);
+
+ return NULL;
}