Mercurial > pidgin
changeset 29060:5c9c4557fec2
merge of '20a2cebedc53676ed04bba9375a4e5a9cd97b6fd'
and 'c0adc68d6e21c013beb36f789a05d94234c3696a'
author | Paul Aurich <paul@darkrain42.org> |
---|---|
date | Tue, 16 Feb 2010 15:16:28 +0000 |
parents | 89f072f356ef (diff) e4cf053a1d7a (current diff) |
children | 28714ff543cd 9c5158a62705 e446b56c01e4 cc6d733a192a |
files | |
diffstat | 4 files changed, 167 insertions(+), 182 deletions(-) [+] |
line wrap: on
line diff
--- a/libpurple/protocols/jabber/buddy.c Tue Feb 16 08:38:20 2010 +0000 +++ b/libpurple/protocols/jabber/buddy.c Tue Feb 16 15:16:28 2010 +0000 @@ -57,6 +57,36 @@ gchar *last_message; } JabberBuddyInfo; +static void +jabber_buddy_resource_free(JabberBuddyResource *jbr) +{ + g_return_if_fail(jbr != NULL); + + jbr->jb->resources = g_list_remove(jbr->jb->resources, jbr); + + while(jbr->commands) { + JabberAdHocCommands *cmd = jbr->commands->data; + g_free(cmd->jid); + g_free(cmd->node); + g_free(cmd->name); + g_free(cmd); + jbr->commands = g_list_delete_link(jbr->commands, jbr->commands); + } + + while (jbr->caps.exts) { + g_free(jbr->caps.exts->data); + jbr->caps.exts = g_list_delete_link(jbr->caps.exts, jbr->caps.exts); + } + + g_free(jbr->name); + g_free(jbr->status); + g_free(jbr->thread_id); + g_free(jbr->client.name); + g_free(jbr->client.version); + g_free(jbr->client.os); + g_free(jbr); +} + void jabber_buddy_free(JabberBuddy *jb) { g_return_if_fail(jb != NULL); @@ -91,6 +121,10 @@ return jb; } +/* Returns -1 if a is a higher priority resource than b, or is + * "more available" than b. 0 if they're the same, and 1 if b is + * higher priority/more available than a. + */ static gint resource_compare_cb(gconstpointer a, gconstpointer b) { const JabberBuddyResource *jbra = a; @@ -98,9 +132,10 @@ JabberBuddyState state_a, state_b; if (jbra->priority != jbrb->priority) - return jbra->priority > jbrb->priority ? 1 : -1; + return jbra->priority > jbrb->priority ? -1 : 1; /* Fold the states for easier comparison */ + /* TODO: Differentiate online/chat and away/dnd? */ switch (jbra->state) { case JABBER_BUDDY_STATE_ONLINE: case JABBER_BUDDY_STATE_CHAT: @@ -146,105 +181,74 @@ return 0; else if ((jbra->idle && !jbrb->idle) || (jbra->idle && jbrb->idle && jbra->idle < jbrb->idle)) - return -1; + return 1; else - return 1; + return -1; } if (state_a == JABBER_BUDDY_STATE_ONLINE) - return 1; + return -1; else if (state_a == JABBER_BUDDY_STATE_AWAY && (state_b == JABBER_BUDDY_STATE_XA || state_b == JABBER_BUDDY_STATE_UNAVAILABLE || state_b == JABBER_BUDDY_STATE_UNKNOWN)) - return 1; + return -1; else if (state_a == JABBER_BUDDY_STATE_XA && (state_b == JABBER_BUDDY_STATE_UNAVAILABLE || state_b == JABBER_BUDDY_STATE_UNKNOWN)) - return 1; + return -1; else if (state_a == JABBER_BUDDY_STATE_UNAVAILABLE && state_b == JABBER_BUDDY_STATE_UNKNOWN) - return 1; + return -1; - return -1; + return 1; } JabberBuddyResource *jabber_buddy_find_resource(JabberBuddy *jb, const char *resource) { - JabberBuddyResource *jbr = NULL; GList *l; - if(!jb) + if (!jb) return NULL; - for(l = jb->resources; l; l = l->next) + if (resource == NULL) + return jb->resources ? jb->resources->data : NULL; + + for (l = jb->resources; l; l = l->next) { - JabberBuddyResource *tmp = (JabberBuddyResource *) l->data; - if (!jbr && !resource) { - jbr = tmp; - } else if (!resource) { - if (resource_compare_cb(tmp, jbr) > 0) - jbr = tmp; - } else if(tmp->name) { - if(!strcmp(tmp->name, resource)) { - jbr = tmp; - break; - } - } + JabberBuddyResource *jbr = l->data; + if (g_str_equal(resource, jbr->name)) + return jbr; } - return jbr; + return NULL; } JabberBuddyResource *jabber_buddy_track_resource(JabberBuddy *jb, const char *resource, int priority, JabberBuddyState state, const char *status) { + /* TODO: Optimization: Only reinsert if priority+state changed */ JabberBuddyResource *jbr = jabber_buddy_find_resource(jb, resource); - if(!jbr) { + if (jbr) { + jb->resources = g_list_remove(jb->resources, jbr); + } else { jbr = g_new0(JabberBuddyResource, 1); jbr->jb = jb; jbr->name = g_strdup(resource); jbr->capabilities = JABBER_CAP_NONE; jbr->tz_off = PURPLE_NO_TZ_OFF; - jb->resources = g_list_append(jb->resources, jbr); } jbr->priority = priority; jbr->state = state; g_free(jbr->status); jbr->status = g_strdup(status); + jb->resources = g_list_insert_sorted(jb->resources, jbr, + resource_compare_cb); return jbr; } -void jabber_buddy_resource_free(JabberBuddyResource *jbr) -{ - g_return_if_fail(jbr != NULL); - - jbr->jb->resources = g_list_remove(jbr->jb->resources, jbr); - - while(jbr->commands) { - JabberAdHocCommands *cmd = jbr->commands->data; - g_free(cmd->jid); - g_free(cmd->node); - g_free(cmd->name); - g_free(cmd); - jbr->commands = g_list_delete_link(jbr->commands, jbr->commands); - } - - if (jbr->caps.exts) { - g_list_foreach(jbr->caps.exts, (GFunc)g_free, NULL); - g_list_free(jbr->caps.exts); - } - g_free(jbr->name); - g_free(jbr->status); - g_free(jbr->thread_id); - g_free(jbr->client.name); - g_free(jbr->client.version); - g_free(jbr->client.os); - g_free(jbr); -} - void jabber_buddy_remove_resource(JabberBuddy *jb, const char *resource) { JabberBuddyResource *jbr = jabber_buddy_find_resource(jb, resource); @@ -797,6 +801,8 @@ jbr = jabber_buddy_find_resource(jbi->jb, resource_name); add_jbr_info(jbi, resource_name, jbr); } else { + /* TODO: This is in priority-ascending order (lowest prio first), because + * everything is prepended. Is that ok? */ for (resources = jbi->jb->resources; resources; resources = resources->next) { jbr = resources->data; @@ -1909,116 +1915,6 @@ } -const char * -jabber_buddy_state_get_name(JabberBuddyState state) -{ - switch(state) { - case JABBER_BUDDY_STATE_UNKNOWN: - return _("Unknown"); - case JABBER_BUDDY_STATE_ERROR: - return _("Error"); - case JABBER_BUDDY_STATE_UNAVAILABLE: - return _("Offline"); - case JABBER_BUDDY_STATE_ONLINE: - return _("Available"); - case JABBER_BUDDY_STATE_CHAT: - return _("Chatty"); - case JABBER_BUDDY_STATE_AWAY: - return _("Away"); - case JABBER_BUDDY_STATE_XA: - return _("Extended Away"); - case JABBER_BUDDY_STATE_DND: - return _("Do Not Disturb"); - } - - return _("Unknown"); -} - -JabberBuddyState jabber_buddy_status_id_get_state(const char *id) { - if(!id) - return JABBER_BUDDY_STATE_UNKNOWN; - if(!strcmp(id, "available")) - return JABBER_BUDDY_STATE_ONLINE; - if(!strcmp(id, "freeforchat")) - return JABBER_BUDDY_STATE_CHAT; - if(!strcmp(id, "away")) - return JABBER_BUDDY_STATE_AWAY; - if(!strcmp(id, "extended_away")) - return JABBER_BUDDY_STATE_XA; - if(!strcmp(id, "dnd")) - return JABBER_BUDDY_STATE_DND; - if(!strcmp(id, "offline")) - return JABBER_BUDDY_STATE_UNAVAILABLE; - if(!strcmp(id, "error")) - return JABBER_BUDDY_STATE_ERROR; - - return JABBER_BUDDY_STATE_UNKNOWN; -} - -const struct { - const char *name; - JabberBuddyState state; -} show_state_pairs[] = { - { "available", JABBER_BUDDY_STATE_ONLINE }, - { "chat", JABBER_BUDDY_STATE_CHAT }, - { "away", JABBER_BUDDY_STATE_AWAY }, - { "xa", JABBER_BUDDY_STATE_XA }, - { "dnd", JABBER_BUDDY_STATE_DND }, - { "offline", JABBER_BUDDY_STATE_UNAVAILABLE }, - { "error", JABBER_BUDDY_STATE_ERROR }, - { NULL, JABBER_BUDDY_STATE_UNKNOWN } -}; - -JabberBuddyState jabber_buddy_show_get_state(const char *id) -{ - int i; - - g_return_val_if_fail(id != NULL, JABBER_BUDDY_STATE_UNKNOWN); - - for (i = 0; show_state_pairs[i].name; ++i) - if (g_str_equal(id, show_state_pairs[i].name)) - return show_state_pairs[i].state; - - purple_debug_warning("jabber", "Invalid value of presence <show/> " - "attribute: %s\n", id); - return JABBER_BUDDY_STATE_UNKNOWN; -} - -const char * -jabber_buddy_state_get_show(JabberBuddyState state) -{ - int i; - - for (i = 0; show_state_pairs[i].name; ++i) - if (state == show_state_pairs[i].state) - return show_state_pairs[i].name; - -/* purple_debug_warning("jabber", "Unknown buddy state: %d\n", state); */ - return NULL; -} - -const char *jabber_buddy_state_get_status_id(JabberBuddyState state) { - switch(state) { - case JABBER_BUDDY_STATE_CHAT: - return "freeforchat"; - case JABBER_BUDDY_STATE_AWAY: - return "away"; - case JABBER_BUDDY_STATE_XA: - return "extended_away"; - case JABBER_BUDDY_STATE_DND: - return "dnd"; - case JABBER_BUDDY_STATE_ONLINE: - return "available"; - case JABBER_BUDDY_STATE_UNKNOWN: - return "available"; - case JABBER_BUDDY_STATE_ERROR: - return "error"; - case JABBER_BUDDY_STATE_UNAVAILABLE: - return "offline"; - } - return NULL; -} - static void user_search_result_add_buddy_cb(PurpleConnection *gc, GList *row, void *user_data) { /* XXX find out the jid */
--- a/libpurple/protocols/jabber/buddy.h Tue Feb 16 08:38:20 2010 +0000 +++ b/libpurple/protocols/jabber/buddy.h Tue Feb 16 15:16:28 2010 +0000 @@ -24,23 +24,20 @@ #ifndef PURPLE_JABBER_BUDDY_H_ #define PURPLE_JABBER_BUDDY_H_ -typedef enum { - JABBER_BUDDY_STATE_UNKNOWN = -2, - JABBER_BUDDY_STATE_ERROR = -1, - JABBER_BUDDY_STATE_UNAVAILABLE = 0, - JABBER_BUDDY_STATE_ONLINE, - JABBER_BUDDY_STATE_CHAT, - JABBER_BUDDY_STATE_AWAY, - JABBER_BUDDY_STATE_XA, - JABBER_BUDDY_STATE_DND -} JabberBuddyState; - typedef struct _JabberBuddy JabberBuddy; #include "jabber.h" #include "caps.h" +#include "jutil.h" struct _JabberBuddy { + /** + * A sorted list of resources in priority descending order. + * This means that the first resource in the list is the + * "most available" (see resource_compare_cb in buddy.c for + * details). Don't play with this yourself, let + * jabber_buddy_track_resource and jabber_buddy_remove_resource do it. + */ GList *resources; char *error_msg; enum { @@ -100,7 +97,6 @@ const char *resource); JabberBuddyResource *jabber_buddy_track_resource(JabberBuddy *jb, const char *resource, int priority, JabberBuddyState state, const char *status); -void jabber_buddy_resource_free(JabberBuddyResource *jbr); void jabber_buddy_remove_resource(JabberBuddy *jb, const char *resource); void jabber_buddy_get_info(PurpleConnection *gc, const char *who); @@ -110,12 +106,6 @@ void jabber_setup_set_info(PurplePluginAction *action); void jabber_set_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img); -const char *jabber_buddy_state_get_name(JabberBuddyState state); -const char *jabber_buddy_state_get_status_id(JabberBuddyState state); -const char *jabber_buddy_state_get_show(JabberBuddyState state); -JabberBuddyState jabber_buddy_status_id_get_state(const char *id); -JabberBuddyState jabber_buddy_show_get_state(const char *id); - void jabber_user_search(JabberStream *js, const char *directory); void jabber_user_search_begin(PurplePluginAction *);
--- a/libpurple/protocols/jabber/jutil.c Tue Feb 16 08:38:20 2010 +0000 +++ b/libpurple/protocols/jabber/jutil.c Tue Feb 16 15:16:28 2010 +0000 @@ -651,6 +651,83 @@ return equal; } +static const struct { + const char *status_id; /* link to core */ + const char *show; /* The show child's cdata in a presence stanza */ + const char *readable; /* readable representation */ + JabberBuddyState state; +} jabber_statuses[] = { + { "offline", NULL, N_("Offline"), JABBER_BUDDY_STATE_UNAVAILABLE }, + { "available", NULL, N_("Available"), JABBER_BUDDY_STATE_ONLINE}, + { "freeforchat", "chat", N_("Chatty"), JABBER_BUDDY_STATE_CHAT }, + { "away", "away", N_("Away"), JABBER_BUDDY_STATE_AWAY }, + { "extended_away", "xa", N_("Extended Away"), JABBER_BUDDY_STATE_XA }, + { "dnd", "dnd", N_("Do Not Disturb"), JABBER_BUDDY_STATE_DND }, + { "error", NULL, N_("Error"), JABBER_BUDDY_STATE_ERROR } +}; + +const char * +jabber_buddy_state_get_name(const JabberBuddyState state) +{ + int i; + for (i = 0; i < G_N_ELEMENTS(jabber_statuses); ++i) + if (jabber_statuses[i].state == state) + return _(jabber_statuses[i].readable); + + return _("Unknown"); +} + +JabberBuddyState +jabber_buddy_status_id_get_state(const char *id) +{ + int i; + if (!id) + return JABBER_BUDDY_STATE_UNKNOWN; + + for (i = 0; i < G_N_ELEMENTS(jabber_statuses); ++i) + if (g_str_equal(id, jabber_statuses[i].status_id)) + return jabber_statuses[i].state; + + return JABBER_BUDDY_STATE_UNKNOWN; +} + +JabberBuddyState jabber_buddy_show_get_state(const char *id) +{ + int i; + + g_return_val_if_fail(id != NULL, JABBER_BUDDY_STATE_UNKNOWN); + + for (i = 0; i < G_N_ELEMENTS(jabber_statuses); ++i) + if (jabber_statuses[i].show && g_str_equal(id, jabber_statuses[i].show)) + return jabber_statuses[i].state; + + purple_debug_warning("jabber", "Invalid value of presence <show/> " + "attribute: %s\n", id); + return JABBER_BUDDY_STATE_UNKNOWN; +} + +const char * +jabber_buddy_state_get_show(JabberBuddyState state) +{ + int i; + for (i = 0; i < G_N_ELEMENTS(jabber_statuses); ++i) + if (state == jabber_statuses[i].state) + return jabber_statuses[i].show; + + return NULL; +} + +const char * +jabber_buddy_state_get_status_id(JabberBuddyState state) +{ + int i; + for (i = 0; i < G_N_ELEMENTS(jabber_statuses); ++i) + if (state == jabber_statuses[i].state) + return jabber_statuses[i].status_id; + + return NULL; +} + /* The same as purple_util_get_image_checksum, but guaranteed to remain SHA1 */ char * jabber_calculate_data_sha1sum(gconstpointer data, size_t len)
--- a/libpurple/protocols/jabber/jutil.h Tue Feb 16 08:38:20 2010 +0000 +++ b/libpurple/protocols/jabber/jutil.h Tue Feb 16 15:16:28 2010 +0000 @@ -30,6 +30,17 @@ char *resource; } JabberID; +typedef enum { + JABBER_BUDDY_STATE_UNKNOWN = -2, + JABBER_BUDDY_STATE_ERROR = -1, + JABBER_BUDDY_STATE_UNAVAILABLE = 0, + JABBER_BUDDY_STATE_ONLINE, + JABBER_BUDDY_STATE_CHAT, + JABBER_BUDDY_STATE_AWAY, + JABBER_BUDDY_STATE_XA, + JABBER_BUDDY_STATE_DND +} JabberBuddyState; + #include "jabber.h" JabberID* jabber_id_new(const char *str); @@ -63,5 +74,16 @@ */ char *jabber_saslprep(const char *); +/* state -> readable name */ +const char *jabber_buddy_state_get_name(JabberBuddyState state); +/* state -> core id */ +const char *jabber_buddy_state_get_status_id(JabberBuddyState state); +/* state -> show attr (for presence stanza) */ +const char *jabber_buddy_state_get_show(JabberBuddyState state); +/* core id -> state */ +JabberBuddyState jabber_buddy_status_id_get_state(const char *id); +/* show attr (presence stanza) -> state */ +JabberBuddyState jabber_buddy_show_get_state(const char *id); + char *jabber_calculate_data_sha1sum(gconstpointer data, size_t len); #endif /* PURPLE_JABBER_JUTIL_H_ */