#include "config.h"
#include <string.h>
+#include <math.h>
#include <time.h>
#include <sys/types.h>
#include <telepathy-glib/dbus.h>
#include <telepathy-glib/util.h>
+#include "empathy-client-factory.h"
#include "empathy-utils.h"
#include "empathy-contact-manager.h"
#include "empathy-individual-manager.h"
-#include "empathy-dispatcher.h"
#include "empathy-presence-manager.h"
+#include "empathy-request-util.h"
#include "empathy-tp-contact-factory.h"
#include <extensions/extensions.h>
/* Translation between presence types and string */
static struct {
- const gchar *name;
- TpConnectionPresenceType type;
+ const gchar *name;
+ TpConnectionPresenceType type;
} presence_types[] = {
- { "available", TP_CONNECTION_PRESENCE_TYPE_AVAILABLE },
- { "busy", TP_CONNECTION_PRESENCE_TYPE_BUSY },
- { "away", TP_CONNECTION_PRESENCE_TYPE_AWAY },
- { "ext_away", TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY },
- { "hidden", TP_CONNECTION_PRESENCE_TYPE_HIDDEN },
- { "offline", TP_CONNECTION_PRESENCE_TYPE_OFFLINE },
- { "unset", TP_CONNECTION_PRESENCE_TYPE_UNSET },
- { "unknown", TP_CONNECTION_PRESENCE_TYPE_UNKNOWN },
- { "error", TP_CONNECTION_PRESENCE_TYPE_ERROR },
- /* alternative names */
- { "dnd", TP_CONNECTION_PRESENCE_TYPE_BUSY },
- { "brb", TP_CONNECTION_PRESENCE_TYPE_AWAY },
- { "xa", TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY },
- { NULL, },
+ { "available", TP_CONNECTION_PRESENCE_TYPE_AVAILABLE },
+ { "busy", TP_CONNECTION_PRESENCE_TYPE_BUSY },
+ { "away", TP_CONNECTION_PRESENCE_TYPE_AWAY },
+ { "ext_away", TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY },
+ { "hidden", TP_CONNECTION_PRESENCE_TYPE_HIDDEN },
+ { "offline", TP_CONNECTION_PRESENCE_TYPE_OFFLINE },
+ { "unset", TP_CONNECTION_PRESENCE_TYPE_UNSET },
+ { "unknown", TP_CONNECTION_PRESENCE_TYPE_UNKNOWN },
+ { "error", TP_CONNECTION_PRESENCE_TYPE_ERROR },
+ /* alternative names */
+ { "dnd", TP_CONNECTION_PRESENCE_TYPE_BUSY },
+ { "brb", TP_CONNECTION_PRESENCE_TYPE_AWAY },
+ { "xa", TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY },
+ { NULL, },
};
+static gboolean
+properties_contains (gchar **list,
+ gint length,
+ const gchar *property);
+static gboolean
+check_writeable_property (TpConnection *connection,
+ FolksIndividual *individual,
+ gchar *property);
void
empathy_init (void)
{
- static gboolean initialized = FALSE;
+ static gboolean initialized = FALSE;
+ TpAccountManager *am;
+ EmpathyClientFactory *factory;
- if (initialized)
- return;
+ if (initialized)
+ return;
- g_type_init ();
+ g_type_init ();
- /* Setup gettext */
- bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
- bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ /* Setup gettext */
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
- /* Setup debug output for empathy and telepathy-glib */
- if (g_getenv ("EMPATHY_TIMING") != NULL) {
- g_log_set_default_handler (tp_debug_timestamped_log_handler, NULL);
- }
- empathy_debug_set_flags (g_getenv ("EMPATHY_DEBUG"));
- tp_debug_divert_messages (g_getenv ("EMPATHY_LOGFILE"));
+ /* Setup debug output for empathy and telepathy-glib */
+ if (g_getenv ("EMPATHY_TIMING") != NULL)
+ g_log_set_default_handler (tp_debug_timestamped_log_handler, NULL);
- emp_cli_init ();
+ empathy_debug_set_flags (g_getenv ("EMPATHY_DEBUG"));
+ tp_debug_divert_messages (g_getenv ("EMPATHY_LOGFILE"));
- initialized = TRUE;
-}
-
-gchar *
-empathy_substring (const gchar *str,
- gint start,
- gint end)
-{
- return g_strndup (str + start, end - start);
-}
-
-gint
-empathy_strcasecmp (const gchar *s1,
- const gchar *s2)
-{
- return empathy_strncasecmp (s1, s2, -1);
-}
-
-gint
-empathy_strncasecmp (const gchar *s1,
- const gchar *s2,
- gsize n)
-{
- gchar *u1, *u2;
- gint ret_val;
+ emp_cli_init ();
- u1 = g_utf8_casefold (s1, n);
- u2 = g_utf8_casefold (s2, n);
+ initialized = TRUE;
- ret_val = g_utf8_collate (u1, u2);
- g_free (u1);
- g_free (u2);
+ factory = empathy_client_factory_dup ();
+ am = tp_account_manager_new_with_factory (TP_SIMPLE_CLIENT_FACTORY (factory));
+ tp_account_manager_set_default (am);
- return ret_val;
+ g_object_unref (factory);
+ g_object_unref (am);
}
gboolean
empathy_xml_validate (xmlDoc *doc,
- const gchar *dtd_filename)
+ const gchar *dtd_filename)
{
- gchar *path;
- xmlChar *escaped;
- xmlValidCtxt cvp;
- xmlDtd *dtd;
- gboolean ret;
+ gchar *path;
+ xmlChar *escaped;
+ xmlValidCtxt cvp;
+ xmlDtd *dtd;
+ gboolean ret;
+
+ path = g_build_filename (g_getenv ("EMPATHY_SRCDIR"), "libempathy",
+ dtd_filename, NULL);
+ if (!g_file_test (path, G_FILE_TEST_EXISTS))
+ {
+ g_free (path);
+ path = g_build_filename (DATADIR, "empathy", dtd_filename, NULL);
+ }
- path = g_build_filename (g_getenv ("EMPATHY_SRCDIR"), "libempathy",
- dtd_filename, NULL);
- if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
- g_free (path);
- path = g_build_filename (DATADIR, "empathy", dtd_filename, NULL);
- }
- DEBUG ("Loading dtd file %s", path);
+ DEBUG ("Loading dtd file %s", path);
- /* The list of valid chars is taken from libxml. */
- escaped = xmlURIEscapeStr ((const xmlChar *) path,
- (const xmlChar *)":@&=+$,/?;");
- g_free (path);
+ /* The list of valid chars is taken from libxml. */
+ escaped = xmlURIEscapeStr ((const xmlChar *) path,
+ (const xmlChar *)":@&=+$,/?;");
+ g_free (path);
- memset (&cvp, 0, sizeof (cvp));
- dtd = xmlParseDTD (NULL, escaped);
- ret = xmlValidateDtd (&cvp, doc, dtd);
+ memset (&cvp, 0, sizeof (cvp));
+ dtd = xmlParseDTD (NULL, escaped);
+ ret = xmlValidateDtd (&cvp, doc, dtd);
- xmlFree (escaped);
- xmlFreeDtd (dtd);
+ xmlFree (escaped);
+ xmlFreeDtd (dtd);
- return ret;
+ return ret;
}
xmlNodePtr
empathy_xml_node_get_child (xmlNodePtr node,
- const gchar *child_name)
+ const gchar *child_name)
{
- xmlNodePtr l;
+ xmlNodePtr l;
- g_return_val_if_fail (node != NULL, NULL);
- g_return_val_if_fail (child_name != NULL, NULL);
+ g_return_val_if_fail (node != NULL, NULL);
+ g_return_val_if_fail (child_name != NULL, NULL);
- for (l = node->children; l; l = l->next) {
- if (l->name && strcmp ((const gchar *) l->name, child_name) == 0) {
- return l;
- }
- }
+ for (l = node->children; l; l = l->next)
+ {
+ if (l->name && strcmp ((const gchar *) l->name, child_name) == 0)
+ return l;
+ }
- return NULL;
+ return NULL;
}
xmlChar *
empathy_xml_node_get_child_content (xmlNodePtr node,
- const gchar *child_name)
+ const gchar *child_name)
{
- xmlNodePtr l;
+ xmlNodePtr l;
- g_return_val_if_fail (node != NULL, NULL);
- g_return_val_if_fail (child_name != NULL, NULL);
+ g_return_val_if_fail (node != NULL, NULL);
+ g_return_val_if_fail (child_name != NULL, NULL);
- l = empathy_xml_node_get_child (node, child_name);
- if (l) {
- return xmlNodeGetContent (l);
- }
+ l = empathy_xml_node_get_child (node, child_name);
+ if (l != NULL)
+ return xmlNodeGetContent (l);
- return NULL;
+ return NULL;
}
xmlNodePtr
empathy_xml_node_find_child_prop_value (xmlNodePtr node,
- const gchar *prop_name,
- const gchar *prop_value)
+ const gchar *prop_name,
+ const gchar *prop_value)
{
- xmlNodePtr l;
- xmlNodePtr found = NULL;
-
- g_return_val_if_fail (node != NULL, NULL);
- g_return_val_if_fail (prop_name != NULL, NULL);
- g_return_val_if_fail (prop_value != NULL, NULL);
-
- for (l = node->children; l && !found; l = l->next) {
- xmlChar *prop;
-
- if (!xmlHasProp (l, (const xmlChar *) prop_name)) {
- continue;
- }
-
- prop = xmlGetProp (l, (const xmlChar *) prop_name);
- if (prop && strcmp ((const gchar *) prop, prop_value) == 0) {
- found = l;
- }
+ xmlNodePtr l;
+ xmlNodePtr found = NULL;
- xmlFree (prop);
- }
+ g_return_val_if_fail (node != NULL, NULL);
+ g_return_val_if_fail (prop_name != NULL, NULL);
+ g_return_val_if_fail (prop_value != NULL, NULL);
- return found;
-}
-
-GHashTable *
-empathy_call_create_streamed_media_request (EmpathyContact *contact,
- gboolean initial_audio,
- gboolean initial_video)
-{
- return tp_asv_new (
- TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
- TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA,
- TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT,
- TP_HANDLE_TYPE_CONTACT,
- TP_PROP_CHANNEL_TARGET_HANDLE, G_TYPE_UINT,
- empathy_contact_get_handle (contact),
- TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_AUDIO, G_TYPE_BOOLEAN,
- initial_audio,
- TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_VIDEO, G_TYPE_BOOLEAN,
- initial_video,
- NULL);
-}
-
-static void
-create_media_channel_cb (GObject *source,
- GAsyncResult *result,
- gpointer user_data)
-{
- GError *error = NULL;
-
- if (!tp_account_channel_request_create_channel_finish (TP_ACCOUNT_CHANNEL_REQUEST (source),
- result,
- &error)) {
- DEBUG ("Failed to create StreamedMedia channel: %s", error->message);
- g_error_free (error);
- }
-}
-
-void
-empathy_call_new_with_streams (EmpathyContact *contact,
- gboolean initial_audio,
- gboolean initial_video,
- gint64 timestamp)
-{
- GHashTable *request;
- TpAccount *account;
- TpAccountChannelRequest *req;
-
- request = empathy_call_create_streamed_media_request (contact,
- initial_audio,
- initial_video);
+ for (l = node->children; l && !found; l = l->next)
+ {
+ xmlChar *prop;
- account = empathy_contact_get_account (contact);
+ if (!xmlHasProp (l, (const xmlChar *) prop_name))
+ continue;
- req = tp_account_channel_request_new (account, request, timestamp);
+ prop = xmlGetProp (l, (const xmlChar *) prop_name);
+ if (prop && strcmp ((const gchar *) prop, prop_value) == 0)
+ found = l;
- tp_account_channel_request_create_channel_async (req, NULL, NULL,
- create_media_channel_cb,
- NULL);
+ xmlFree (prop);
+ }
- g_hash_table_unref (request);
- g_object_unref (req);
+ return found;
}
const gchar *
empathy_presence_get_default_message (TpConnectionPresenceType presence)
{
- switch (presence) {
- case TP_CONNECTION_PRESENCE_TYPE_AVAILABLE:
- return _("Available");
- case TP_CONNECTION_PRESENCE_TYPE_BUSY:
- return _("Busy");
- case TP_CONNECTION_PRESENCE_TYPE_AWAY:
- case TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY:
- return _("Away");
- case TP_CONNECTION_PRESENCE_TYPE_HIDDEN:
- return _("Invisible");
- case TP_CONNECTION_PRESENCE_TYPE_OFFLINE:
- return _("Offline");
- case TP_CONNECTION_PRESENCE_TYPE_UNKNOWN:
- return _("Unknown");
- case TP_CONNECTION_PRESENCE_TYPE_UNSET:
- case TP_CONNECTION_PRESENCE_TYPE_ERROR:
- default:
- return NULL;
- }
-
- return NULL;
+ switch (presence)
+ {
+ case TP_CONNECTION_PRESENCE_TYPE_AVAILABLE:
+ return _("Available");
+ case TP_CONNECTION_PRESENCE_TYPE_BUSY:
+ return _("Busy");
+ case TP_CONNECTION_PRESENCE_TYPE_AWAY:
+ case TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY:
+ return _("Away");
+ case TP_CONNECTION_PRESENCE_TYPE_HIDDEN:
+ return _("Invisible");
+ case TP_CONNECTION_PRESENCE_TYPE_OFFLINE:
+ return _("Offline");
+ case TP_CONNECTION_PRESENCE_TYPE_UNKNOWN:
+ /* translators: presence type is unknown */
+ return C_("presence", "Unknown");
+ case TP_CONNECTION_PRESENCE_TYPE_UNSET:
+ case TP_CONNECTION_PRESENCE_TYPE_ERROR:
+ default:
+ return NULL;
+ }
+
+ return NULL;
}
const gchar *
empathy_presence_to_str (TpConnectionPresenceType presence)
{
- int i;
+ int i;
- for (i = 0 ; presence_types[i].name != NULL; i++)
- if (presence == presence_types[i].type)
- return presence_types[i].name;
+ for (i = 0 ; presence_types[i].name != NULL; i++)
+ if (presence == presence_types[i].type)
+ return presence_types[i].name;
- return NULL;
+ return NULL;
}
TpConnectionPresenceType
empathy_presence_from_str (const gchar *str)
{
- int i;
+ int i;
- for (i = 0 ; presence_types[i].name != NULL; i++)
- if (!tp_strdiff (str, presence_types[i].name))
- return presence_types[i].type;
+ for (i = 0 ; presence_types[i].name != NULL; i++)
+ if (!tp_strdiff (str, presence_types[i].name))
+ return presence_types[i].type;
- return TP_CONNECTION_PRESENCE_TYPE_UNSET;
+ return TP_CONNECTION_PRESENCE_TYPE_UNSET;
}
static const gchar *
empathy_status_reason_get_default_message (TpConnectionStatusReason reason)
{
- switch (reason) {
- case TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED:
- return _("No reason specified");
- case TP_CONNECTION_STATUS_REASON_REQUESTED:
- return _("Status is set to offline");
- case TP_CONNECTION_STATUS_REASON_NETWORK_ERROR:
- return _("Network error");
- case TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED:
- return _("Authentication failed");
- case TP_CONNECTION_STATUS_REASON_ENCRYPTION_ERROR:
- return _("Encryption error");
- case TP_CONNECTION_STATUS_REASON_NAME_IN_USE:
- return _("Name in use");
- case TP_CONNECTION_STATUS_REASON_CERT_NOT_PROVIDED:
- return _("Certificate not provided");
- case TP_CONNECTION_STATUS_REASON_CERT_UNTRUSTED:
- return _("Certificate untrusted");
- case TP_CONNECTION_STATUS_REASON_CERT_EXPIRED:
- return _("Certificate expired");
- case TP_CONNECTION_STATUS_REASON_CERT_NOT_ACTIVATED:
- return _("Certificate not activated");
- case TP_CONNECTION_STATUS_REASON_CERT_HOSTNAME_MISMATCH:
- return _("Certificate hostname mismatch");
- case TP_CONNECTION_STATUS_REASON_CERT_FINGERPRINT_MISMATCH:
- return _("Certificate fingerprint mismatch");
- case TP_CONNECTION_STATUS_REASON_CERT_SELF_SIGNED:
- return _("Certificate self-signed");
- case TP_CONNECTION_STATUS_REASON_CERT_OTHER_ERROR:
- return _("Certificate error");
- default:
- return _("Unknown reason");
- }
+ switch (reason)
+ {
+ case TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED:
+ return _("No reason specified");
+ case TP_CONNECTION_STATUS_REASON_REQUESTED:
+ return _("Status is set to offline");
+ case TP_CONNECTION_STATUS_REASON_NETWORK_ERROR:
+ return _("Network error");
+ case TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED:
+ return _("Authentication failed");
+ case TP_CONNECTION_STATUS_REASON_ENCRYPTION_ERROR:
+ return _("Encryption error");
+ case TP_CONNECTION_STATUS_REASON_NAME_IN_USE:
+ return _("Name in use");
+ case TP_CONNECTION_STATUS_REASON_CERT_NOT_PROVIDED:
+ return _("Certificate not provided");
+ case TP_CONNECTION_STATUS_REASON_CERT_UNTRUSTED:
+ return _("Certificate untrusted");
+ case TP_CONNECTION_STATUS_REASON_CERT_EXPIRED:
+ return _("Certificate expired");
+ case TP_CONNECTION_STATUS_REASON_CERT_NOT_ACTIVATED:
+ return _("Certificate not activated");
+ case TP_CONNECTION_STATUS_REASON_CERT_HOSTNAME_MISMATCH:
+ return _("Certificate hostname mismatch");
+ case TP_CONNECTION_STATUS_REASON_CERT_FINGERPRINT_MISMATCH:
+ return _("Certificate fingerprint mismatch");
+ case TP_CONNECTION_STATUS_REASON_CERT_SELF_SIGNED:
+ return _("Certificate self-signed");
+ case TP_CONNECTION_STATUS_REASON_CERT_OTHER_ERROR:
+ return _("Certificate error");
+ default:
+ return _("Unknown 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;
+ 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"));
+ g_hash_table_insert (errors, TP_ERROR_STR_SOFTWARE_UPGRADE_REQUIRED,
+ _("Your software is too old"));
+
+ return errors;
}
static const gchar *
empathy_dbus_error_name_get_default_message (const gchar *error)
{
- static GHashTable *errors_to_message = NULL;
+ static GHashTable *errors_to_message = NULL;
- if (error == NULL)
- return NULL;
+ if (error == NULL)
+ return NULL;
- if (G_UNLIKELY (errors_to_message == NULL)) {
- errors_to_message = create_errors_to_message_hash ();
- }
+ if (G_UNLIKELY (errors_to_message == NULL))
+ errors_to_message = create_errors_to_message_hash ();
- return g_hash_table_lookup (errors_to_message, error);
+ 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 gchar *dbus_error;
+ const gchar *message;
const GHashTable *details = NULL;
- TpConnectionStatusReason reason;
+ TpConnectionStatusReason reason;
- dbus_error = tp_account_get_detailed_error (account, &details);
+ 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;
- }
+ 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;
+ 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);
+ DEBUG ("Don't understand error '%s'; fallback to the status reason (%u)",
+ dbus_error, reason);
- tp_account_get_connection_status (account, &reason);
+ tp_account_get_connection_status (account, &reason);
- return empathy_status_reason_get_default_message (reason);
+ return empathy_status_reason_get_default_message (reason);
}
gchar *
empathy_file_lookup (const gchar *filename, const gchar *subdir)
{
- gchar *path;
+ gchar *path;
- if (!subdir) {
- subdir = ".";
- }
+ if (subdir == NULL)
+ subdir = ".";
- path = g_build_filename (g_getenv ("EMPATHY_SRCDIR"), subdir, filename, NULL);
- if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
- g_free (path);
- path = g_build_filename (DATADIR, "empathy", filename, NULL);
- }
+ path = g_build_filename (g_getenv ("EMPATHY_SRCDIR"), subdir, filename, NULL);
+ if (!g_file_test (path, G_FILE_TEST_EXISTS))
+ {
+ g_free (path);
+ path = g_build_filename (DATADIR, "empathy", filename, NULL);
+ }
- return path;
+ return path;
}
guint
empathy_proxy_hash (gconstpointer key)
{
- TpProxy *proxy = TP_PROXY (key);
- TpProxyClass *proxy_class = TP_PROXY_GET_CLASS (key);
+ TpProxy *proxy = TP_PROXY (key);
+ TpProxyClass *proxy_class = TP_PROXY_GET_CLASS (key);
- g_return_val_if_fail (TP_IS_PROXY (proxy), 0);
- g_return_val_if_fail (proxy_class->must_have_unique_name, 0);
+ g_return_val_if_fail (TP_IS_PROXY (proxy), 0);
+ g_return_val_if_fail (proxy_class->must_have_unique_name, 0);
- return g_str_hash (proxy->object_path) ^ g_str_hash (proxy->bus_name);
+ return g_str_hash (proxy->object_path) ^ g_str_hash (proxy->bus_name);
}
gboolean
empathy_proxy_equal (gconstpointer a,
- gconstpointer b)
+ gconstpointer b)
{
- TpProxy *proxy_a = TP_PROXY (a);
- TpProxy *proxy_b = TP_PROXY (b);
- TpProxyClass *proxy_a_class = TP_PROXY_GET_CLASS (a);
- TpProxyClass *proxy_b_class = TP_PROXY_GET_CLASS (b);
-
- g_return_val_if_fail (TP_IS_PROXY (proxy_a), FALSE);
- g_return_val_if_fail (TP_IS_PROXY (proxy_b), FALSE);
- g_return_val_if_fail (proxy_a_class->must_have_unique_name, 0);
- g_return_val_if_fail (proxy_b_class->must_have_unique_name, 0);
-
- return g_str_equal (proxy_a->object_path, proxy_b->object_path) &&
- g_str_equal (proxy_a->bus_name, proxy_b->bus_name);
+ TpProxy *proxy_a = TP_PROXY (a);
+ TpProxy *proxy_b = TP_PROXY (b);
+ TpProxyClass *proxy_a_class = TP_PROXY_GET_CLASS (a);
+ TpProxyClass *proxy_b_class = TP_PROXY_GET_CLASS (b);
+
+ g_return_val_if_fail (TP_IS_PROXY (proxy_a), FALSE);
+ g_return_val_if_fail (TP_IS_PROXY (proxy_b), FALSE);
+ g_return_val_if_fail (proxy_a_class->must_have_unique_name, 0);
+ g_return_val_if_fail (proxy_b_class->must_have_unique_name, 0);
+
+ return g_str_equal (proxy_a->object_path, proxy_b->object_path) &&
+ g_str_equal (proxy_a->bus_name, proxy_b->bus_name);
}
gboolean
empathy_check_available_state (void)
{
- TpConnectionPresenceType presence;
- EmpathyPresenceManager *presence_mgr;
+ TpConnectionPresenceType presence;
+ EmpathyPresenceManager *presence_mgr;
- presence_mgr = empathy_presence_manager_dup_singleton ();
- presence = empathy_presence_manager_get_state (presence_mgr);
- g_object_unref (presence_mgr);
+ presence_mgr = empathy_presence_manager_dup_singleton ();
+ presence = empathy_presence_manager_get_state (presence_mgr);
+ g_object_unref (presence_mgr);
- if (presence != TP_CONNECTION_PRESENCE_TYPE_AVAILABLE &&
- presence != TP_CONNECTION_PRESENCE_TYPE_UNSET) {
- return FALSE;
- }
+ if (presence != TP_CONNECTION_PRESENCE_TYPE_AVAILABLE &&
+ presence != TP_CONNECTION_PRESENCE_TYPE_UNSET)
+ return FALSE;
- return TRUE;
+ return TRUE;
}
gint
empathy_uint_compare (gconstpointer a,
- gconstpointer b)
+ gconstpointer b)
{
- return *(guint *) a - *(guint *) b;
+ return *(guint *) a - *(guint *) b;
}
gchar *
gboolean translated;
} names[] = {
{ "jabber", "Jabber", FALSE },
- { "msn", "MSN", FALSE, },
+ { "msn", "Windows Live (MSN)", FALSE, },
{ "local-xmpp", N_("People Nearby"), TRUE },
{ "irc", "IRC", FALSE },
{ "icq", "ICQ", FALSE },
return service_name;
}
-/* Note: this function depends on the account manager having its core feature
- * prepared. */
-TpAccount *
-empathy_get_account_for_connection (TpConnection *connection)
-{
- TpAccountManager *manager;
- TpAccount *account = NULL;
- GList *accounts, *l;
-
- manager = tp_account_manager_dup ();
-
- accounts = tp_account_manager_get_valid_accounts (manager);
-
- for (l = accounts; l != NULL; l = l->next)
- {
- TpAccount *a = l->data;
-
- if (tp_account_get_connection (a) == connection)
- {
- account = a;
- break;
- }
- }
-
- g_list_free (accounts);
- g_object_unref (manager);
-
- return account;
-}
-
gboolean
empathy_account_manager_get_accounts_connected (gboolean *connecting)
{
gboolean
empathy_folks_individual_contains_contact (FolksIndividual *individual)
{
- GList *personas, *l;
+ GeeSet *personas;
+ GeeIterator *iter;
+ gboolean retval = FALSE;
g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), FALSE);
personas = folks_individual_get_personas (individual);
- for (l = personas; l != NULL; l = l->next)
+ iter = gee_iterable_iterator (GEE_ITERABLE (personas));
+ while (!retval && gee_iterator_next (iter))
{
- if (TPF_IS_PERSONA (l->data))
- return (tpf_persona_get_contact (TPF_PERSONA (l->data)) != NULL);
+ 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 FALSE;
+ return retval;
}
/* TODO: this needs to be eliminated (and replaced in some cases with user
EmpathyContact *
empathy_contact_dup_from_folks_individual (FolksIndividual *individual)
{
- GList *personas, *l;
+ GeeSet *personas;
+ GeeIterator *iter;
EmpathyContact *contact = NULL;
g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);
personas = folks_individual_get_personas (individual);
- for (l = personas; (l != NULL) && (contact == NULL); l = l->next)
+ iter = gee_iterable_iterator (GEE_ITERABLE (personas));
+ while (gee_iterator_next (iter) && (contact == NULL))
{
- TpfPersona *persona = l->data;
+ TpfPersona *persona = gee_iterator_get (iter);
- if (TPF_IS_PERSONA (persona))
+ if (empathy_folks_persona_is_interesting (FOLKS_PERSONA (persona)))
{
TpContact *tp_contact;
tp_contact = tpf_persona_get_contact (persona);
- contact = empathy_contact_dup_from_tp_contact (tp_contact);
- empathy_contact_set_persona (contact, FOLKS_PERSONA (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;
TpChannelGroupChangeReason
tp_channel_group_change_reason_from_folks_groups_change_reason (
- FolksGroupableChangeReason reason)
+ FolksGroupDetailsChangeReason reason)
{
return (TpChannelGroupChangeReason) reason;
}
TpfPersonaStore *
-empathy_get_persona_store_for_connection (TpConnection *connection)
+empathy_dup_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,
+ backend = folks_backend_store_dup_backend_by_name (backend_store,
"telepathy");
if (backend != NULL)
{
- GHashTable *stores_hash;
- GList *stores, *l;
+ GeeMap *stores_map;
+ GeeMapIterator *iter;
- 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)
+ stores_map = folks_backend_get_persona_stores (backend);
+ iter = gee_map_map_iterator (stores_map);
+ while (gee_map_iterator_next (iter))
{
- TpfPersonaStore *persona_store = TPF_PERSONA_STORE (l->data);
+ TpfPersonaStore *persona_store = gee_map_iterator_get_value (iter);
TpAccount *account;
TpConnection *conn_cur;
if (conn_cur == connection)
result = persona_store;
}
-
- g_list_free (stores);
+ g_clear_object (&iter);
}
g_object_unref (backend);
gboolean
empathy_connection_can_add_personas (TpConnection *connection)
{
+ gboolean retval;
FolksPersonaStore *persona_store;
g_return_val_if_fail (TP_IS_CONNECTION (connection), FALSE);
+ if (tp_connection_get_status (connection, NULL) !=
+ TP_CONNECTION_STATUS_CONNECTED)
+ return FALSE;
+
persona_store = FOLKS_PERSONA_STORE (
- empathy_get_persona_store_for_connection (connection));
+ empathy_dup_persona_store_for_connection (connection));
- return (folks_persona_store_get_can_add_personas (persona_store) ==
+ retval = (folks_persona_store_get_can_add_personas (persona_store) ==
FOLKS_MAYBE_BOOL_TRUE);
+
+ g_clear_object (&persona_store);
+
+ return retval;
}
gboolean
-empathy_connection_can_alias_personas (TpConnection *connection)
+empathy_connection_can_alias_personas (TpConnection *connection,
+ FolksIndividual *individual)
{
- FolksPersonaStore *persona_store;
+ gboolean retval;
g_return_val_if_fail (TP_IS_CONNECTION (connection), FALSE);
- persona_store = FOLKS_PERSONA_STORE (
- empathy_get_persona_store_for_connection (connection));
+ if (tp_connection_get_status (connection, NULL) !=
+ TP_CONNECTION_STATUS_CONNECTED)
+ return FALSE;
- return (folks_persona_store_get_can_alias_personas (persona_store) ==
- FOLKS_MAYBE_BOOL_TRUE);
+ retval = check_writeable_property (connection, individual, "alias");
+
+ return retval;
}
gboolean
-empathy_connection_can_group_personas (TpConnection *connection)
+empathy_connection_can_group_personas (TpConnection *connection,
+ FolksIndividual *individual)
{
- FolksPersonaStore *persona_store;
+ gboolean retval;
g_return_val_if_fail (TP_IS_CONNECTION (connection), FALSE);
- persona_store = FOLKS_PERSONA_STORE (
- empathy_get_persona_store_for_connection (connection));
+ if (tp_connection_get_status (connection, NULL) !=
+ TP_CONNECTION_STATUS_CONNECTED)
+ return FALSE;
- return (folks_persona_store_get_can_group_personas (persona_store) ==
- FOLKS_MAYBE_BOOL_TRUE);
+ retval = check_writeable_property (connection, individual, "groups");
+
+ return retval;
+}
+
+gboolean
+empathy_folks_persona_is_interesting (FolksPersona *persona)
+{
+ /* We're not interested in non-Telepathy personas */
+ if (!TPF_IS_PERSONA (persona))
+ return FALSE;
+
+ /* We're not interested in user personas which haven't been added to the
+ * contact list (see bgo#637151). */
+ if (folks_persona_get_is_user (persona) &&
+ !tpf_persona_get_is_in_contact_list (TPF_PERSONA (persona)))
+ {
+ return FALSE;
+ }
+
+ return TRUE;
}
gchar *
return NULL;
}
+
+gchar *
+empathy_format_currency (gint amount,
+ guint scale,
+ const gchar *currency)
+{
+#define MINUS "\342\210\222"
+#define EURO "\342\202\254"
+#define YEN "\302\245"
+#define POUND "\302\243"
+
+ /* localised representations of currency */
+ /* FIXME: check these, especially negatives and decimals */
+ static const struct {
+ const char *currency;
+ const char *positive;
+ const char *negative;
+ const char *decimal;
+ } currencies[] = {
+ /* sym positive negative decimal */
+ { "EUR", EURO "%s", MINUS EURO "%s", "." },
+ { "USD", "$%s", MINUS "$%s", "." },
+ { "JPY", YEN "%s" MINUS YEN "%s", "." },
+ { "GBP", POUND "%s", MINUS POUND "%s", "." },
+ { "PLN", "%s zl", MINUS "%s zl", "." },
+ { "BRL", "R$%s", MINUS "R$%s", "." },
+ { "SEK", "%s kr", MINUS "%s kr", "." },
+ { "DKK", "kr %s", "kr " MINUS "%s", "." },
+ { "HKD", "$%s", MINUS "$%s", "." },
+ { "CHF", "%s Fr.", MINUS "%s Fr.", "." },
+ { "NOK", "kr %s", "kr" MINUS "%s", "," },
+ { "CAD", "$%s", MINUS "$%s", "." },
+ { "TWD", "$%s", MINUS "$%s", "." },
+ { "AUD", "$%s", MINUS "$%s", "." },
+ };
+
+ const char *positive = "%s";
+ const char *negative = MINUS "%s";
+ const char *decimal = ".";
+ char *fmt_amount, *money;
+ guint i;
+
+ /* get the localised currency format */
+ for (i = 0; i < G_N_ELEMENTS (currencies); i++)
+ {
+ if (!tp_strdiff (currency, currencies[i].currency))
+ {
+ positive = currencies[i].positive;
+ negative = currencies[i].negative;
+ decimal = currencies[i].decimal;
+ break;
+ }
+ }
+
+ /* format the amount using the scale */
+ if (scale == 0)
+ {
+ /* no decimal point required */
+ fmt_amount = g_strdup_printf ("%d", amount);
+ }
+ else
+ {
+ /* don't use floating point arithmatic, it's noisy;
+ * we take the absolute values, because we want the minus
+ * sign to appear before the $ */
+ int divisor = pow (10, scale);
+ int dollars = abs (amount / divisor);
+ int cents = abs (amount % divisor);
+
+ fmt_amount = g_strdup_printf ("%d%s%0*d",
+ dollars, decimal, scale, cents);
+ }
+
+ money = g_strdup_printf (amount < 0 ? negative : positive, fmt_amount);
+ g_free (fmt_amount);
+
+ return money;
+}
+
+gboolean
+empathy_account_has_uri_scheme_tel (TpAccount *account)
+{
+ const gchar * const * uri_schemes;
+ guint i;
+
+ uri_schemes = tp_account_get_uri_schemes (account);
+ if (uri_schemes == NULL)
+ return FALSE;
+
+ for (i = 0; uri_schemes[i] != NULL; i++)
+ {
+ if (!tp_strdiff (uri_schemes[i], "tel"))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/* 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;
+}
+
+static gboolean
+properties_contains (gchar **list,
+ gint length,
+ const gchar *property)
+{
+ gint i;
+
+ for (i = 0; i < length; i++)
+ {
+ if (!tp_strdiff (list[i], property))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+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;
+}