diff options
author | James Booth <boothj5@gmail.com> | 2013-12-14 15:34:17 +0000 |
---|---|---|
committer | James Booth <boothj5@gmail.com> | 2013-12-14 15:34:17 +0000 |
commit | 107fdd355e487793e53799ce3ebed0659263a2f7 (patch) | |
tree | e7b2996921be06fd6ab4c8ff25f30e1b82dda3a4 /src | |
parent | 3f6b40246a243c072770700d67c9818a7d293f6c (diff) | |
download | profani-tty-107fdd355e487793e53799ce3ebed0659263a2f7.tar.gz |
Added simple mock test, refactored roster
Diffstat (limited to 'src')
-rw-r--r-- | src/command/command.c | 8 | ||||
-rw-r--r-- | src/command/command.h | 2 | ||||
-rw-r--r-- | src/profanity.c | 2 | ||||
-rw-r--r-- | src/roster_list.c | 475 | ||||
-rw-r--r-- | src/roster_list.h | 58 | ||||
-rw-r--r-- | src/ui/console.c | 2 | ||||
-rw-r--r-- | src/ui/core.c | 2 | ||||
-rw-r--r-- | src/ui/inputwin.c | 1 | ||||
-rw-r--r-- | src/ui/muc_window.h | 4 | ||||
-rw-r--r-- | src/ui/notifier.h | 33 | ||||
-rw-r--r-- | src/ui/ui.h | 17 | ||||
-rw-r--r-- | src/ui/window.h | 4 | ||||
-rw-r--r-- | src/ui/windows.c | 1 | ||||
-rw-r--r-- | src/ui/windows.h | 4 | ||||
-rw-r--r-- | src/xmpp/bookmark.h | 9 | ||||
-rw-r--r-- | src/xmpp/capabilities.h | 4 | ||||
-rw-r--r-- | src/xmpp/connection.h | 4 | ||||
-rw-r--r-- | src/xmpp/iq.c | 1 | ||||
-rw-r--r-- | src/xmpp/iq.h | 4 | ||||
-rw-r--r-- | src/xmpp/message.c | 1 | ||||
-rw-r--r-- | src/xmpp/message.h | 4 | ||||
-rw-r--r-- | src/xmpp/presence.h | 4 | ||||
-rw-r--r-- | src/xmpp/roster.c | 531 | ||||
-rw-r--r-- | src/xmpp/roster.h | 4 | ||||
-rw-r--r-- | src/xmpp/stanza.h | 4 | ||||
-rw-r--r-- | src/xmpp/xmpp.h | 40 |
26 files changed, 652 insertions, 571 deletions
diff --git a/src/command/command.c b/src/command/command.c index a213d141..0ab8b013 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -36,6 +36,7 @@ #include "config/preferences.h" #include "config/theme.h" #include "contact.h" +#include "roster_list.h" #include "jid.h" #include "log.h" #include "muc.h" @@ -133,7 +134,6 @@ static gboolean _cmd_prefs(gchar **args, struct cmd_help_t help); static gboolean _cmd_priority(gchar **args, struct cmd_help_t help); static gboolean _cmd_quit(gchar **args, struct cmd_help_t help); static gboolean _cmd_reconnect(gchar **args, struct cmd_help_t help); -static gboolean _cmd_rooms(gchar **args, struct cmd_help_t help); static gboolean _cmd_bookmark(gchar **args, struct cmd_help_t help); static gboolean _cmd_roster(gchar **args, struct cmd_help_t help); static gboolean _cmd_software(gchar **args, struct cmd_help_t help); @@ -2455,7 +2455,7 @@ _cmd_roster(gchar **args, struct cmd_help_t help) char *jid = args[1]; - roster_remove(jid); + roster_send_remove(jid); return TRUE; } @@ -2916,13 +2916,13 @@ _cmd_decline(gchar **args, struct cmd_help_t help) return TRUE; } -static gboolean +gboolean _cmd_rooms(gchar **args, struct cmd_help_t help) { jabber_conn_status_t conn_status = jabber_get_connection_status(); if (conn_status != JABBER_CONNECTED) { - cons_show("You are not currenlty connected."); + cons_show("You are not currently connected."); return TRUE; } diff --git a/src/command/command.h b/src/command/command.h index c20413c8..8743d662 100644 --- a/src/command/command.h +++ b/src/command/command.h @@ -49,4 +49,6 @@ void cmd_history_append(char *inp); char *cmd_history_previous(char *inp, int *size); char *cmd_history_next(char *inp, int *size); +gboolean _cmd_rooms(gchar **args, struct cmd_help_t help); + #endif diff --git a/src/profanity.c b/src/profanity.c index 6bd7e2f0..d712d426 100644 --- a/src/profanity.c +++ b/src/profanity.c @@ -42,10 +42,10 @@ #include "command/command.h" #include "common.h" #include "contact.h" +#include "roster_list.h" #include "log.h" #include "muc.h" #include "resource.h" -#include "ui/notifier.h" #include "ui/ui.h" #include "xmpp/xmpp.h" diff --git a/src/roster_list.c b/src/roster_list.c new file mode 100644 index 00000000..37031ca4 --- /dev/null +++ b/src/roster_list.c @@ -0,0 +1,475 @@ +/* + * roster_list.c + * + * Copyright (C) 2012, 2013 James Booth <boothj5@gmail.com> + * + * This file is part of Profanity. + * + * Profanity is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Profanity is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Profanity. If not, see <http://www.gnu.org/licenses/>. + * + */ + + +#include <string.h> +#include <glib.h> +#include <assert.h> + +#include "roster_list.h" +#include "resource.h" +#include "contact.h" +#include "jid.h" +#include "tools/autocomplete.h" +#include "xmpp/xmpp.h" +#include "profanity.h" + +// nicknames +static Autocomplete name_ac; + +// barejids +static Autocomplete barejid_ac; + +// fulljids +static Autocomplete fulljid_ac; + +// groups +static Autocomplete groups_ac; + +// contacts, indexed on barejid +static GHashTable *contacts; + +// nickname to jid map +static GHashTable *name_to_barejid; + +static gboolean _key_equals(void *key1, void *key2); +static gboolean _datetimes_equal(GDateTime *dt1, GDateTime *dt2); +static void _replace_name(const char * const current_name, + const char * const new_name, const char * const barejid); +static void _add_name_and_barejid(const char * const name, + const char * const barejid); +static gint _compare_contacts(PContact a, PContact b); + +void +roster_clear(void) +{ + autocomplete_clear(name_ac); + autocomplete_clear(barejid_ac); + autocomplete_clear(fulljid_ac); + autocomplete_clear(groups_ac); + g_hash_table_destroy(contacts); + contacts = g_hash_table_new_full(g_str_hash, (GEqualFunc)_key_equals, g_free, + (GDestroyNotify)p_contact_free); + g_hash_table_destroy(name_to_barejid); + name_to_barejid = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, + g_free); +} + +gboolean +roster_update_presence(const char * const barejid, Resource *resource, + GDateTime *last_activity) +{ + assert(barejid != NULL); + assert(resource != NULL); + + PContact contact = g_hash_table_lookup(contacts, barejid); + if (contact == NULL) { + return FALSE; + } + if (!_datetimes_equal(p_contact_last_activity(contact), last_activity)) { + p_contact_set_last_activity(contact, last_activity); + } + p_contact_set_presence(contact, resource); + Jid *jid = jid_create_from_bare_and_resource(barejid, resource->name); + autocomplete_add(fulljid_ac, jid->fulljid); + jid_destroy(jid); + + return TRUE; +} + +PContact +roster_get_contact(const char * const barejid) +{ + return g_hash_table_lookup(contacts, barejid); +} + +gboolean +roster_contact_offline(const char * const barejid, + const char * const resource, const char * const status) +{ + PContact contact = g_hash_table_lookup(contacts, barejid); + + if (contact == NULL) { + return FALSE; + } + if (resource == NULL) { + return TRUE; + } else { + gboolean result = p_contact_remove_resource(contact, resource); + if (result == TRUE) { + Jid *jid = jid_create_from_bare_and_resource(barejid, resource); + autocomplete_remove(fulljid_ac, jid->fulljid); + jid_destroy(jid); + } + + return result; + } +} + +void +roster_reset_search_attempts(void) +{ + autocomplete_reset(name_ac); + autocomplete_reset(barejid_ac); + autocomplete_reset(fulljid_ac); + autocomplete_reset(groups_ac); +} + +void +roster_init(void) +{ + name_ac = autocomplete_new(); + barejid_ac = autocomplete_new(); + fulljid_ac = autocomplete_new(); + groups_ac = autocomplete_new(); + contacts = g_hash_table_new_full(g_str_hash, (GEqualFunc)_key_equals, g_free, + (GDestroyNotify)p_contact_free); + name_to_barejid = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, + g_free); +} + +void +roster_free(void) +{ + autocomplete_free(name_ac); + autocomplete_free(barejid_ac); + autocomplete_free(fulljid_ac); + autocomplete_free(groups_ac); +} + +void +roster_change_name(const char * const barejid, const char * const new_name) +{ + PContact contact = g_hash_table_lookup(contacts, barejid); + const char * current_name = NULL; + if (p_contact_name(contact) != NULL) { + current_name = strdup(p_contact_name(contact)); + } + + if (contact != NULL) { + p_contact_set_name(contact, new_name); + _replace_name(current_name, new_name, barejid); + + GSList *groups = p_contact_groups(contact); + roster_send_name_change(barejid, new_name, groups); + } +} + +void +roster_remove(const char * const name, const char * const barejid) +{ + autocomplete_remove(barejid_ac, barejid); + autocomplete_remove(name_ac, name); + g_hash_table_remove(name_to_barejid, name); + + // remove each fulljid + PContact contact = roster_get_contact(barejid); + if (contact != NULL) { + GList *resources = p_contact_get_available_resources(contact); + while (resources != NULL) { + GString *fulljid = g_string_new(strdup(barejid)); + g_string_append(fulljid, "/"); + g_string_append(fulljid, resources->data); + autocomplete_remove(fulljid_ac, fulljid->str); + g_string_free(fulljid, TRUE); + resources = g_list_next(resources); + } + } + + // remove the contact + g_hash_table_remove(contacts, barejid); +} + +void +roster_update(const char * const barejid, const char * const name, + GSList *groups, const char * const subscription, gboolean pending_out) +{ + PContact contact = g_hash_table_lookup(contacts, barejid); + + if (contact == NULL) { + roster_add(barejid, name, groups, subscription, pending_out, FALSE); + } else { + p_contact_set_subscription(contact, subscription); + p_contact_set_pending_out(contact, pending_out); + + const char * const new_name = name; + const char * current_name = NULL; + if (p_contact_name(contact) != NULL) { + current_name = strdup(p_contact_name(contact)); + } + + p_contact_set_name(contact, new_name); + p_contact_set_groups(contact, groups); + _replace_name(current_name, new_name, barejid); + + // add groups + while (groups != NULL) { + autocomplete_add(groups_ac, groups->data); + groups = g_slist_next(groups); + } + } +} + +gboolean +roster_add(const char * const barejid, const char * const name, GSList *groups, + const char * const subscription, gboolean pending_out, gboolean from_initial) +{ + gboolean added = FALSE; + PContact contact = g_hash_table_lookup(contacts, barejid); + + if (contact == NULL) { + contact = p_contact_new(barejid, name, groups, subscription, NULL, + pending_out); + + // add groups + while (groups != NULL) { + autocomplete_add(groups_ac, groups->data); + groups = g_slist_next(groups); + } + + g_hash_table_insert(contacts, strdup(barejid), contact); + autocomplete_add(barejid_ac, barejid); + _add_name_and_barejid(name, barejid); + + if (!from_initial) { + prof_handle_roster_add(barejid, name); + } + + added = TRUE; + } + + return added; +} + +char * +roster_barejid_from_name(const char * const name) +{ + return g_hash_table_lookup(name_to_barejid, name); +} + +GSList * +roster_get_contacts(void) +{ + GSList *result = NULL; + GHashTableIter iter; + gpointer key; + gpointer value; + + g_hash_table_iter_init(&iter, contacts); + while (g_hash_table_iter_next(&iter, &key, &value)) { + result = g_slist_insert_sorted(result, value, (GCompareFunc)_compare_contacts); + } + + // resturn all contact structs + return result; +} + +gboolean +roster_has_pending_subscriptions(void) +{ + GHashTableIter iter; + gpointer key; + gpointer value; + + g_hash_table_iter_init(&iter, contacts); + while (g_hash_table_iter_next(&iter, &key, &value)) { + PContact contact = (PContact) value; + if (p_contact_pending_out(contact)) { + return TRUE; + } + } + + return FALSE; +} + +char * +roster_find_contact(char *search_str) +{ + return autocomplete_complete(name_ac, search_str); +} + +char * +roster_find_resource(char *search_str) +{ + return autocomplete_complete(fulljid_ac, search_str); +} + +GSList * +roster_get_group(const char * const group) +{ + GSList *result = NULL; + GHashTableIter iter; + gpointer key; + gpointer value; + + g_hash_table_iter_init(&iter, contacts); + while (g_hash_table_iter_next(&iter, &key, &value)) { + GSList *groups = p_contact_groups(value); + while (groups != NULL) { + if (strcmp(groups->data, group) == 0) { + result = g_slist_insert_sorted(result, value, (GCompareFunc)_compare_contacts); + break; + } + groups = g_slist_next(groups); + } + } + + // resturn all contact structs + return result; +} + +void +roster_add_to_group(const char * const group, const char * const barejid) +{ + PContact contact = g_hash_table_lookup(contacts, barejid); + + if (contact != NULL) { + if (p_contact_in_group(contact, group)) { + if (p_contact_name(contact) != NULL) { + prof_handle_already_in_group(p_contact_name(contact), group); + } else { + prof_handle_already_in_group(p_contact_barejid(contact), group); + } + return; + } + + roster_send_add_to_group(group, contact); + + } +} + +void +roster_remove_from_group(const char * const group, const char * const barejid) +{ + PContact contact = g_hash_table_lookup(contacts, barejid); + + if (contact != NULL) { + if (!p_contact_in_group(contact, group)) { + if (p_contact_name(contact) != NULL) { + prof_handle_not_in_group(p_contact_name(contact), group); + } else { + prof_handle_not_in_group(p_contact_barejid(contact), group); + } + return; + } + + roster_send_remove_from_group(group, contact); + } +} + +GSList * +roster_get_groups(void) +{ + return autocomplete_get_list(groups_ac); +} + +char * +roster_find_group(char *search_str) +{ + return autocomplete_complete(groups_ac, search_str); +} + +char * +roster_find_jid(char *search_str) +{ + return autocomplete_complete(barejid_ac, search_str); +} + +static +gboolean _key_equals(void *key1, void *key2) +{ + gchar *str1 = (gchar *) key1; + gchar *str2 = (gchar *) key2; + + return (g_strcmp0(str1, str2) == 0); +} + +static gboolean +_datetimes_equal(GDateTime *dt1, GDateTime *dt2) +{ + if ((dt1 == NULL) && (dt2 == NULL)) { + return TRUE; + } else if ((dt1 == NULL) && (dt2 != NULL)) { + return FALSE; + } else if ((dt1 != NULL) && (dt2 == NULL)) { + return FALSE; + } else { + return g_date_time_equal(dt1, dt2); + } +} + +static void +_replace_name(const char * const current_name, const char * const new_name, + const char * const barejid) +{ + // current handle exists already + if (current_name != NULL) { + autocomplete_remove(name_ac, current_name); + g_hash_table_remove(name_to_barejid, current_name); + _add_name_and_barejid(new_name, barejid); + // no current handle + } else if (new_name != NULL) { + autocomplete_remove(name_ac, barejid); + g_hash_table_remove(name_to_barejid, barejid); + _add_name_and_barejid(new_name, barejid); + } +} + +static void +_add_name_and_barejid(const char * const name, const char * const barejid) +{ + if (name != NULL) { + autocomplete_add(name_ac, name); + g_hash_table_insert(name_to_barejid, strdup(name), strdup(barejid)); + } else { + autocomplete_add(name_ac, barejid); + g_hash_table_insert(name_to_barejid, strdup(barejid), strdup(barejid)); + } +} + +static +gint _compare_contacts(PContact a, PContact b) +{ + const char * utf8_str_a = NULL; + const char * utf8_str_b = NULL; + + if (p_contact_name(a) != NULL) { + utf8_str_a = p_contact_name(a); + } else { + utf8_str_a = p_contact_barejid(a); + } + if (p_contact_name(b) != NULL) { + utf8_str_b = p_contact_name(b); + } else { + utf8_str_b = p_contact_barejid(b); + } + + gchar *key_a = g_utf8_collate_key(utf8_str_a, -1); + gchar *key_b = g_utf8_collate_key(utf8_str_b, -1); + + gint result = g_strcmp0(key_a, key_b); + + g_free(key_a); + g_free(key_b); + + return result; +} diff --git a/src/roster_list.h b/src/roster_list.h new file mode 100644 index 00000000..9382081b --- /dev/null +++ b/src/roster_list.h @@ -0,0 +1,58 @@ +/* + * roster_list.h + * + * Copyright (C) 2012, 2013 James Booth <boothj5@gmail.com> + * + * This file is part of Profanity. + * + * Profanity is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Profanity is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Profanity. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifndef ROSTER_LIST_H +#define ROSTER_LIST_H + +#include <glib.h> + +#include "resource.h" +#include "contact.h" + +void roster_clear(void); +gboolean roster_update_presence(const char * const barejid, Resource *resource, + GDateTime *last_activity); +PContact roster_get_contact(const char * const barejid); +gboolean roster_contact_offline(const char * const barejid, + const char * const resource, const char * const status); +void roster_reset_search_attempts(void); +void roster_init(void); +void roster_free(void); +void roster_change_name(const char * const barejid, const char * const new_name); +void roster_remove(const char * const name, const char * const barejid); +void roster_update(const char * const barejid, const char * const name, + GSList *groups, const char * const subscription, gboolean pending_out); +gboolean roster_add(const char * const barejid, const char * const name, GSList *groups, + const char * const subscription, gboolean pending_out, gboolean from_initial); +char * roster_barejid_from_name(const char * const name); +GSList * roster_get_contacts(void); +gboolean roster_has_pending_subscriptions(void); +char * roster_find_contact(char *search_str); +char * roster_find_resource(char *search_str); +GSList * roster_get_group(const char * const group); +GSList * roster_get_groups(void); +void roster_add_to_group(const char * const group, const char * const barejid); +void roster_remove_from_group(const char * const group, const char * const barejid); +char * roster_find_group(char *search_str); +char * roster_find_jid(char *search_str); + +#endif diff --git a/src/ui/console.c b/src/ui/console.c index 822da420..00e891db 100644 --- a/src/ui/console.c +++ b/src/ui/console.c @@ -31,9 +31,9 @@ #include "command/command.h" #include "common.h" +#include "roster_list.h" #include "config/preferences.h" #include "config/theme.h" -#include "ui/notifier.h" #include "ui/window.h" #include "ui/windows.h" #include "ui/ui.h" diff --git a/src/ui/core.c b/src/ui/core.c index c5cfe284..507cfb02 100644 --- a/src/ui/core.c +++ b/src/ui/core.c @@ -44,10 +44,10 @@ #include "config/preferences.h" #include "config/theme.h" #include "contact.h" +#include "roster_list.h" #include "jid.h" #include "log.h" #include "muc.h" -#include "ui/notifier.h" #include "ui/ui.h" #include "ui/window.h" #include "ui/windows.h" diff --git a/src/ui/inputwin.c b/src/ui/inputwin.c index d5b882d7..3306a246 100644 --- a/src/ui/inputwin.c +++ b/src/ui/inputwin.c @@ -40,6 +40,7 @@ #include "config/theme.h" #include "log.h" #include "profanity.h" +#include "roster_list.h" #include "ui/ui.h" #include "ui/windows.h" #include "xmpp/xmpp.h" diff --git a/src/ui/muc_window.h b/src/ui/muc_window.h index e67954a7..0b1f13ab 100644 --- a/src/ui/muc_window.h +++ b/src/ui/muc_window.h @@ -20,8 +20,8 @@ * */ -#ifndef MUC_WINDOW_H -#define MUC_WINDOW_H +#ifndef UI_MUC_WINDOW_H +#define UI_MUC_WINDOW_H #include <glib.h> diff --git a/src/ui/notifier.h b/src/ui/notifier.h deleted file mode 100644 index 9db789e8..00000000 --- a/src/ui/notifier.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * notifier.h - * - * Copyright (C) 2012, 2013 James Booth <boothj5@gmail.com> - * - * This file is part of Profanity. - * - * Profanity is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Profanity is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Profanity. If not, see <http://www.gnu.org/licenses/>. - * - */ - -void notifier_init(void); -void notifier_uninit(void); - -void notify_typing(const char * const handle); -void notify_message(const char * const handle, int win); -void notify_room_message(const char * const handle, const char * const room, - int win); -void notify_remind(void); -void notify_invite(const char * const from, const char * const room, - const char * const reason); -void notify_subscription(const char * const from); diff --git a/src/ui/ui.h b/src/ui/ui.h index 13e96f27..5ec4debd 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -20,8 +20,8 @@ * */ -#ifndef UI_H -#define UI_H +#ifndef UI_UI_H +#define UI_UI_H #include "config.h" @@ -242,4 +242,17 @@ void inp_block(void); void inp_get_password(char *passwd); void inp_replace_input(char *input, const char * const new_input, int *size); +// desktop notifier actions +void notifier_init(void); +void notifier_uninit(void); + +void notify_typing(const char * const handle); +void notify_message(const char * const handle, int win); +void notify_room_message(const char * const handle, const char * const room, + int win); +void notify_remind(void); +void notify_invite(const char * const from, const char * const room, + const char * const reason); +void notify_subscription(const char * const from); + #endif diff --git a/src/ui/window.h b/src/ui/window.h index dea6214d..69e446fa 100644 --- a/src/ui/window.h +++ b/src/ui/window.h @@ -20,8 +20,8 @@ * */ -#ifndef WINDOW_H -#define WINDOW_H +#ifndef UI_WINDOW_H +#define UI_WINDOW_H #include "config.h" diff --git a/src/ui/windows.c b/src/ui/windows.c index 88c811e5..001f1bfc 100644 --- a/src/ui/windows.c +++ b/src/ui/windows.c @@ -33,6 +33,7 @@ #endif #include "common.h" +#include "roster_list.h" #include "config/theme.h" #include "ui/ui.h" #include "ui/window.h" diff --git a/src/ui/windows.h b/src/ui/windows.h index 3cf593e8..4467e507 100644 --- a/src/ui/windows.h +++ b/src/ui/windows.h @@ -20,8 +20,8 @@ * */ -#ifndef WINDOWS_H -#define WINDOWS_H +#ifndef UI_WINDOWS_H +#define UI_WINDOWS_H void wins_init(void); ProfWin * wins_get_console(void); diff --git a/src/xmpp/bookmark.h b/src/xmpp/bookmark.h index e15b6eab..8b5418b0 100644 --- a/src/xmpp/bookmark.h +++ b/src/xmpp/bookmark.h @@ -1,6 +1,6 @@ -#ifndef BOOKMARK_H -#define BOOKMARK_H +#ifndef XMPP_BOOKMARK_H +#define XMPP_BOOKMARK_H #include <glib.h> @@ -13,10 +13,5 @@ struct bookmark_t { typedef struct bookmark_t Bookmark; void bookmark_request(void); -void bookmark_add(const char *jid, const char *nick, gboolean autojoin); -void bookmark_remove(const char *jid, gboolean autojoin); -const GList *bookmark_get_list(void); -char *bookmark_find(char *search_str); -void bookmark_autocomplete_reset(void); #endif diff --git a/src/xmpp/capabilities.h b/src/xmpp/capabilities.h index d97b84b2..45d97e0f 100644 --- a/src/xmpp/capabilities.h +++ b/src/xmpp/capabilities.h @@ -20,8 +20,8 @@ * */ -#ifndef CAPABILITIES_H -#define CAPABILITIES_H +#ifndef XMPP_CAPABILITIES_H +#define XMPP_CAPABILITIES_H #include <strophe.h> diff --git a/src/xmpp/connection.h b/src/xmpp/connection.h index b5701252..f11bc8c8 100644 --- a/src/xmpp/connection.h +++ b/src/xmpp/connection.h @@ -20,8 +20,8 @@ * */ -#ifndef CONNECTION_H -#define CONNECTION_H +#ifndef XMPP_CONNECTION_H +#define XMPP_CONNECTION_H #include <strophe.h> diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c index 1ddfcb34..fdabe771 100644 --- a/src/xmpp/iq.c +++ b/src/xmpp/iq.c @@ -38,6 +38,7 @@ #include "xmpp/capabilities.h" #include "xmpp/connection.h" #include "xmpp/stanza.h" +#include "roster_list.h" #include "xmpp/xmpp.h" #define HANDLE(ns, type, func) xmpp_handler_add(conn, func, ns, STANZA_NAME_IQ, type, ctx) diff --git a/src/xmpp/iq.h b/src/xmpp/iq.h index 86966e26..64844228 100644 --- a/src/xmpp/iq.h +++ b/src/xmpp/iq.h @@ -20,8 +20,8 @@ * */ -#ifndef IQ_H -#define IQ_H +#ifndef XMPP_IQ_H +#define XMPP_IQ_H void iq_add_handlers(void); void iq_roster_request(void); diff --git a/src/xmpp/message.c b/src/xmpp/message.c index 8a977490..a1644587 100644 --- a/src/xmpp/message.c +++ b/src/xmpp/message.c @@ -33,6 +33,7 @@ #include "xmpp/connection.h" #include "xmpp/message.h" #include "xmpp/roster.h" +#include "roster_list.h" #include "xmpp/stanza.h" #include "xmpp/xmpp.h" diff --git a/src/xmpp/message.h b/src/xmpp/message.h index 639ae558..3bfa60ef 100644 --- a/src/xmpp/message.h +++ b/src/xmpp/message.h @@ -20,8 +20,8 @@ * */ -#ifndef MESSAGE_H -#define MESSAGE_H +#ifndef XMPP_MESSAGE_H +#define XMPP_MESSAGE_H void message_add_handlers(void); diff --git a/src/xmpp/presence.h b/src/xmpp/presence.h index fa63d78e..fb13a699 100644 --- a/src/xmpp/presence.h +++ b/src/xmpp/presence.h @@ -20,8 +20,8 @@ * */ -#ifndef PRESENCE_H -#define PRESENCE_H +#ifndef XMPP_PRESENCE_H +#define XMPP_PRESENCE_H void presence_sub_requests_init(void); void presence_add_handlers(void); diff --git a/src/xmpp/roster.c b/src/xmpp/roster.c index 5fbb7be7..51c34ea1 100644 --- a/src/xmpp/roster.c +++ b/src/xmpp/roster.c @@ -32,30 +32,13 @@ #include "tools/autocomplete.h" #include "xmpp/connection.h" #include "xmpp/roster.h" +#include "roster_list.h" #include "xmpp/stanza.h" #include "xmpp/xmpp.h" #define HANDLE(type, func) xmpp_handler_add(conn, func, XMPP_NS_ROSTER, \ STANZA_NAME_IQ, type, ctx) -// nicknames -static Autocomplete name_ac; - -// barejids -static Autocomplete barejid_ac; - -// fulljids -static Autocomplete fulljid_ac; - -// groups -static Autocomplete groups_ac; - -// contacts, indexed on barejid -static GHashTable *contacts; - -// nickname to jid map -static GHashTable *name_to_barejid; - // callback data for group commands typedef struct _group_data { char *name; @@ -77,14 +60,7 @@ _group_remove_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata); // helper functions -static void _add_name_and_barejid(const char * const name, - const char * const barejid); -static void _replace_name(const char * const current_name, - const char * const new_name, const char * const barejid); GSList * _get_groups_from_item(xmpp_stanza_t *item); -static gboolean _key_equals(void *key1, void *key2); -static gboolean _datetimes_equal(GDateTime *dt1, GDateTime *dt2); -static gint _compare_contacts(PContact a, PContact b); void roster_add_handlers(void) @@ -106,52 +82,6 @@ roster_request(void) } void -roster_init(void) -{ - name_ac = autocomplete_new(); - barejid_ac = autocomplete_new(); - fulljid_ac = autocomplete_new(); - groups_ac = autocomplete_new(); - contacts = g_hash_table_new_full(g_str_hash, (GEqualFunc)_key_equals, g_free, - (GDestroyNotify)p_contact_free); - name_to_barejid = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, - g_free); -} - -void -roster_clear(void) -{ - autocomplete_clear(name_ac); - autocomplete_clear(barejid_ac); - autocomplete_clear(fulljid_ac); - autocomplete_clear(groups_ac); - g_hash_table_destroy(contacts); - contacts = g_hash_table_new_full(g_str_hash, (GEqualFunc)_key_equals, g_free, - (GDestroyNotify)p_contact_free); - g_hash_table_destroy(name_to_barejid); - name_to_barejid = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, - g_free); -} - -void -roster_free() -{ - autocomplete_free(name_ac); - autocomplete_free(barejid_ac); - autocomplete_free(fulljid_ac); - autocomplete_free(groups_ac); -} - -void -roster_reset_search_attempts(void) -{ - autocomplete_reset(name_ac); - autocomplete_reset(barejid_ac); - autocomplete_reset(fulljid_ac); - autocomplete_reset(groups_ac); -} - -void roster_add_new(const char * const barejid, const char * const name) { xmpp_conn_t * const conn = connection_get_conn(); @@ -162,7 +92,7 @@ roster_add_new(const char * const barejid, const char * const name) } void -roster_remove(const char * const barejid) +roster_send_remove(const char * const barejid) { xmpp_conn_t * const conn = connection_get_conn(); xmpp_ctx_t * const ctx = connection_get_ctx(); @@ -171,180 +101,46 @@ roster_remove(const char * const barejid) xmpp_stanza_release(iq); } -gboolean -roster_add(const char * const barejid, const char * const name, GSList *groups, - const char * const subscription, gboolean pending_out, gboolean from_initial) -{ - gboolean added = FALSE; - PContact contact = g_hash_table_lookup(contacts, barejid); - - if (contact == NULL) { - contact = p_contact_new(barejid, name, groups, subscription, NULL, - pending_out); - - // add groups - while (groups != NULL) { - autocomplete_add(groups_ac, groups->data); - groups = g_slist_next(groups); - } - - g_hash_table_insert(contacts, strdup(barejid), contact); - autocomplete_add(barejid_ac, barejid); - _add_name_and_barejid(name, barejid); - - if (!from_initial) { - prof_handle_roster_add(barejid, name); - } - - added = TRUE; - } - - return added; -} - void -roster_update(const char * const barejid, const char * const name, - GSList *groups, const char * const subscription, gboolean pending_out) -{ - PContact contact = g_hash_table_lookup(contacts, barejid); - - if (contact == NULL) { - roster_add(barejid, name, groups, subscription, pending_out, FALSE); - } else { - p_contact_set_subscription(contact, subscription); - p_contact_set_pending_out(contact, pending_out); - - const char * const new_name = name; - const char * current_name = NULL; - if (p_contact_name(contact) != NULL) { - current_name = strdup(p_contact_name(contact)); - } - - p_contact_set_name(contact, new_name); - p_contact_set_groups(contact, groups); - _replace_name(current_name, new_name, barejid); - - // add groups - while (groups != NULL) { - autocomplete_add(groups_ac, groups->data); - groups = g_slist_next(groups); - } - } -} - -gboolean -roster_update_presence(const char * const barejid, Resource *resource, - GDateTime *last_activity) +roster_send_name_change(const char * const barejid, const char * const new_name, GSList *groups) { - assert(barejid != NULL); - assert(resource != NULL); - - PContact contact = g_hash_table_lookup(contacts, barejid); - if (contact == NULL) { - return FALSE; - } - if (!_datetimes_equal(p_contact_last_activity(contact), last_activity)) { - p_contact_set_last_activity(contact, last_activity); - } - p_contact_set_presence(contact, resource); - Jid *jid = jid_create_from_bare_and_resource(barejid, resource->name); - autocomplete_add(fulljid_ac, jid->fulljid); - jid_destroy(jid); - - return TRUE; -} - -gboolean -roster_contact_offline(const char * const barejid, - const char * const resource, const char * const status) -{ - PContact contact = g_hash_table_lookup(contacts, barejid); - - if (contact == NULL) { - return FALSE; - } - if (resource == NULL) { - return TRUE; - } else { - gboolean result = p_contact_remove_resource(contact, resource); - if (result == TRUE) { - Jid *jid = jid_create_from_bare_and_resource(barejid, resource); - autocomplete_remove(fulljid_ac, jid->fulljid); - jid_destroy(jid); - } - - return result; - } + xmpp_conn_t * const conn = connection_get_conn(); + xmpp_ctx_t * const ctx = connection_get_ctx(); + xmpp_stanza_t *iq = stanza_create_roster_set(ctx, NULL, barejid, new_name, + groups); + xmpp_send(conn, iq); + xmpp_stanza_release(iq); } void -roster_change_name(const char * const barejid, const char * const new_name) +roster_send_add_to_group(const char * const group, PContact contact) { - PContact contact = g_hash_table_lookup(contacts, barejid); - const char * current_name = NULL; - if (p_contact_name(contact) != NULL) { - current_name = strdup(p_contact_name(contact)); + GSList *groups = p_contact_groups(contact); + GSList *new_groups = NULL; + while (groups != NULL) { + new_groups = g_slist_append(new_groups, strdup(groups->data)); + groups = g_slist_next(groups); } - if (contact != NULL) { - p_contact_set_name(contact, new_name); - _replace_name(current_name, new_name, barejid); - - GSList *groups = p_contact_groups(contact); - - xmpp_conn_t * const conn = connection_get_conn(); - xmpp_ctx_t * const ctx = connection_get_ctx(); - xmpp_stanza_t *iq = stanza_create_roster_set(ctx, NULL, barejid, new_name, - groups); - xmpp_send(conn, iq); - xmpp_stanza_release(iq); + new_groups = g_slist_append(new_groups, strdup(group)); + // add an id handler to handle the response + char *unique_id = get_unique_id(); + GroupData *data = malloc(sizeof(GroupData)); + data->group = strdup(group); + if (p_contact_name(contact) != NULL) { + data->name = strdup(p_contact_name(contact)); + } else { + data->name = strdup(p_contact_barejid(contact)); } -} - -void -roster_add_to_group(const char * const group, const char * const barejid) -{ - PContact contact = g_hash_table_lookup(contacts, barejid); - - if (contact != NULL) { - if (p_contact_in_group(contact, group)) { - if (p_contact_name(contact) != NULL) { - prof_handle_already_in_group(p_contact_name(contact), group); - } else { - prof_handle_already_in_group(p_contact_barejid(contact), group); - } - return; - } - - GSList *groups = p_contact_groups(contact); - GSList *new_groups = NULL; - while (groups != NULL) { - new_groups = g_slist_append(new_groups, strdup(groups->data)); - groups = g_slist_next(groups); - } - new_groups = g_slist_append(new_groups, strdup(group)); - - xmpp_conn_t * const conn = connection_get_conn(); - xmpp_ctx_t * const ctx = connection_get_ctx(); - - // add an id handler to handle the response - char *unique_id = get_unique_id(); - GroupData *data = malloc(sizeof(GroupData)); - data->group = strdup(group); - if (p_contact_name(contact) != NULL) { - data->name = strdup(p_contact_name(contact)); - } else { - data->name = strdup(p_contact_barejid(contact)); - } - - xmpp_id_handler_add(conn, _group_add_handler, unique_id, data); - xmpp_stanza_t *iq = stanza_create_roster_set(ctx, unique_id, barejid, - p_contact_name(contact), new_groups); - xmpp_send(conn, iq); - xmpp_stanza_release(iq); - free(unique_id); - } + xmpp_conn_t * const conn = connection_get_conn(); + xmpp_ctx_t * const ctx = connection_get_ctx(); + xmpp_id_handler_add(conn, _group_add_handler, unique_id, data); + xmpp_stanza_t *iq = stanza_create_roster_set(ctx, unique_id, p_contact_barejid(contact), + p_contact_name(contact), new_groups); + xmpp_send(conn, iq); + xmpp_stanza_release(iq); + free(unique_id); } static int @@ -362,50 +158,36 @@ _group_add_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, } void -roster_remove_from_group(const char * const group, const char * const barejid) +roster_send_remove_from_group(const char * const group, PContact contact) { - PContact contact = g_hash_table_lookup(contacts, barejid); - - if (contact != NULL) { - if (!p_contact_in_group(contact, group)) { - if (p_contact_name(contact) != NULL) { - prof_handle_not_in_group(p_contact_name(contact), group); - } else { - prof_handle_not_in_group(p_contact_barejid(contact), group); - } - return; - } - - GSList *groups = p_contact_groups(contact); - GSList *new_groups = NULL; - while (groups != NULL) { - if (strcmp(groups->data, group) != 0) { - new_groups = g_slist_append(new_groups, strdup(groups->data)); - } - groups = g_slist_next(groups); + GSList *groups = p_contact_groups(contact); + GSList *new_groups = NULL; + while (groups != NULL) { + if (strcmp(groups->data, group) != 0) { + new_groups = g_slist_append(new_groups, strdup(groups->data)); } + groups = g_slist_next(groups); + } - xmpp_conn_t * const conn = connection_get_conn(); - xmpp_ctx_t * const ctx = connection_get_ctx(); - - // add an id handler to handle the response - char *unique_id = get_unique_id(); - GroupData *data = malloc(sizeof(GroupData)); - data->group = strdup(group); - if (p_contact_name(contact) != NULL) { - data->name = strdup(p_contact_name(contact)); - } else { - data->name = strdup(p_contact_barejid(contact)); - } + xmpp_conn_t * const conn = connection_get_conn(); + xmpp_ctx_t * const ctx = connection_get_ctx(); - xmpp_id_handler_add(conn, _group_remove_handler, unique_id, data); - xmpp_stanza_t *iq = stanza_create_roster_set(ctx, unique_id, barejid, - p_contact_name(contact), new_groups); - xmpp_send(conn, iq); - xmpp_stanza_release(iq); - free(unique_id); + // add an id handler to handle the response + char *unique_id = get_unique_id(); + GroupData *data = malloc(sizeof(GroupData)); + data->group = strdup(group); + if (p_contact_name(contact) != NULL) { + data->name = strdup(p_contact_name(contact)); + } else { + data->name = strdup(p_contact_barejid(contact)); } + xmpp_id_handler_add(conn, _group_remove_handler, unique_id, data); + xmpp_stanza_t *iq = stanza_create_roster_set(ctx, unique_id, p_contact_barejid(contact), + p_contact_name(contact), new_groups); + xmpp_send(conn, iq); + xmpp_stanza_release(iq); + free(unique_id); } static int @@ -422,107 +204,6 @@ _group_remove_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, return 0; } -gboolean -roster_has_pending_subscriptions(void) -{ - GHashTableIter iter; - gpointer key; - gpointer value; - - g_hash_table_iter_init(&iter, contacts); - while (g_hash_table_iter_next(&iter, &key, &value)) { - PContact contact = (PContact) value; - if (p_contact_pending_out(contact)) { - return TRUE; - } - } - - return FALSE; -} - -GSList * -roster_get_contacts(void) -{ - GSList *result = NULL; - GHashTableIter iter; - gpointer key; - gpointer value; - - g_hash_table_iter_init(&iter, contacts); - while (g_hash_table_iter_next(&iter, &key, &value)) { - result = g_slist_insert_sorted(result, value, (GCompareFunc)_compare_contacts); - } - - // resturn all contact structs - return result; -} - -GSList * -roster_get_groups(void) -{ - return autocomplete_get_list(groups_ac); -} - -GSList * -roster_get_group(const char * const group) -{ - GSList *result = NULL; - GHashTableIter iter; - gpointer key; - gpointer value; - - g_hash_table_iter_init(&iter, contacts); - while (g_hash_table_iter_next(&iter, &key, &value)) { - GSList *groups = p_contact_groups(value); - while (groups != NULL) { - if (strcmp(groups->data, group) == 0) { - result = g_slist_insert_sorted(result, value, (GCompareFunc)_compare_contacts); - break; - } - groups = g_slist_next(groups); - } - } - - // resturn all contact structs - return result; -} - -char * -roster_find_contact(char *search_str) -{ - return autocomplete_complete(name_ac, search_str); -} - -char * -roster_find_jid(char *search_str) -{ - return autocomplete_complete(barejid_ac, search_str); -} - -char * -roster_find_resource(char *search_str) -{ - return autocomplete_complete(fulljid_ac, search_str); -} - -char * -roster_find_group(char *search_str) -{ - return autocomplete_complete(groups_ac, search_str); -} - -char * -roster_barejid_from_name(const char * const name) -{ - return g_hash_table_lookup(name_to_barejid, name); -} - -PContact -roster_get_contact(const char * const barejid) -{ - return g_hash_table_lookup(contacts, barejid); -} - static int _roster_handle_push(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata) @@ -556,26 +237,8 @@ _roster_handle_push(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, if (name == NULL) { name = barejid; } - autocomplete_remove(barejid_ac, barejid); - autocomplete_remove(name_ac, name); - g_hash_table_remove(name_to_barejid, name); - - // remove each fulljid - PContact contact = roster_get_contact(barejid); - if (contact != NULL) { - GList *resources = p_contact_get_available_resources(contact); - while (resources != NULL) { - GString *fulljid = g_string_new(strdup(barejid)); - g_string_append(fulljid, "/"); - g_string_append(fulljid, resources->data); - autocomplete_remove(fulljid_ac, fulljid->str); - g_string_free(fulljid, TRUE); - resources = g_list_next(resources); - } - } - // remove the contact - g_hash_table_remove(contacts, barejid); + roster_remove(name, barejid); prof_handle_roster_remove(barejid); @@ -642,35 +305,6 @@ _roster_handle_result(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, return 1; } -static void -_add_name_and_barejid(const char * const name, const char * const barejid) -{ - if (name != NULL) { - autocomplete_add(name_ac, name); - g_hash_table_insert(name_to_barejid, strdup(name), strdup(barejid)); - } else { - autocomplete_add(name_ac, barejid); - g_hash_table_insert(name_to_barejid, strdup(barejid), strdup(barejid)); - } -} - -static void -_replace_name(const char * const current_name, const char * const new_name, - const char * const barejid) -{ - // current handle exists already - if (current_name != NULL) { - autocomplete_remove(name_ac, current_name); - g_hash_table_remove(name_to_barejid, current_name); - _add_name_and_barejid(new_name, barejid); - // no current handle - } else if (new_name != NULL) { - autocomplete_remove(name_ac, barejid); - g_hash_table_remove(name_to_barejid, barejid); - _add_name_and_barejid(new_name, barejid); - } -} - GSList * _get_groups_from_item(xmpp_stanza_t *item) { @@ -689,54 +323,3 @@ _get_groups_from_item(xmpp_stanza_t *item) return groups; } - -static -gboolean _key_equals(void *key1, void *key2) -{ - gchar *str1 = (gchar *) key1; - gchar *str2 = (gchar *) key2; - - return (g_strcmp0(str1, str2) == 0); -} - -static -gint _compare_contacts(PContact a, PContact b) -{ - const char * utf8_str_a = NULL; - const char * utf8_str_b = NULL; - - if (p_contact_name(a) != NULL) { - utf8_str_a = p_contact_name(a); - } else { - utf8_str_a = p_contact_barejid(a); - } - if (p_contact_name(b) != NULL) { - utf8_str_b = p_contact_name(b); - } else { - utf8_str_b = p_contact_barejid(b); - } - - gchar *key_a = g_utf8_collate_key(utf8_str_a, -1); - gchar *key_b = g_utf8_collate_key(utf8_str_b, -1); - - gint result = g_strcmp0(key_a, key_b); - - g_free(key_a); - g_free(key_b); - - return result; -} - -static gboolean -_datetimes_equal(GDateTime *dt1, GDateTime *dt2) -{ - if ((dt1 == NULL) && (dt2 == NULL)) { - return TRUE; - } else if ((dt1 == NULL) && (dt2 != NULL)) { - return FALSE; - } else if ((dt1 != NULL) && (dt2 == NULL)) { - return FALSE; - } else { - return g_date_time_equal(dt1, dt2); - } -} diff --git a/src/xmpp/roster.h b/src/xmpp/roster.h index 8aba28f4..1faaba86 100644 --- a/src/xmpp/roster.h +++ b/src/xmpp/roster.h @@ -20,8 +20,8 @@ * */ -#ifndef ROSTER_H -#define ROSTER_H +#ifndef XMPP_ROSTER_H +#define XMPP_ROSTER_H void roster_add_handlers(void); void roster_request(void); diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h index 108b0806..6b647258 100644 --- a/src/xmpp/stanza.h +++ b/src/xmpp/stanza.h @@ -20,8 +20,8 @@ * */ -#ifndef STANZA_H -#define STANZA_H +#ifndef XMPP_STANZA_H +#define XMPP_STANZA_H #include <strophe.h> diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h index f1b3ba6c..21c25aa4 100644 --- a/src/xmpp/xmpp.h +++ b/src/xmpp/xmpp.h @@ -20,8 +20,8 @@ * */ -#ifndef XMPP_H -#define XMPP_H +#ifndef XMPP_XMPP_H +#define XMPP_XMPP_H #include <strophe.h> @@ -124,32 +124,16 @@ void iq_disco_items_request(gchar *jid); Capabilities* caps_get(const char * const caps_str); void caps_close(void); -void roster_clear(void); -gboolean roster_update_presence(const char * const barejid, - Resource *resource, GDateTime *last_activity); -PContact roster_get_contact(const char * const barejid); -gboolean roster_contact_offline(const char * const barejid, - const char * const resource, const char * const status); -void roster_reset_search_attempts(void); -void roster_init(void); -void roster_free(void); -gboolean roster_has_pending_subscriptions(void); -GSList * roster_get_contacts(void); -char * roster_find_contact(char *search_str); -char * roster_find_jid(char *search_str); -char * roster_find_resource(char *search_str); -char * roster_find_group(char *search_str); -gboolean roster_add(const char * const barejid, const char * const name, - GSList *groups, const char * const subscription, gboolean pending_out, - gboolean from_initial); -void roster_change_name(const char * const barejid, const char * const new_name); -char * roster_barejid_from_name(const char * const name); +void bookmark_add(const char *jid, const char *nick, gboolean autojoin); +void bookmark_remove(const char *jid, gboolean autojoin); +const GList *bookmark_get_list(void); +char *bookmark_find(char *search_str); +void bookmark_autocomplete_reset(void); + +void roster_send_name_change(const char * const barejid, const char * const new_name, GSList *groups); +void roster_send_add_to_group(const char * const group, PContact contact); +void roster_send_remove_from_group(const char * const group, PContact contact); void roster_add_new(const char * const barejid, const char * const name); -void roster_remove(const char * const barejid); -GSList * roster_get_group(const char * const group); -void roster_add_to_group(const char * const group, const char * const barejid); -void roster_remove_from_group(const char * const group, - const char * const barejid); -GSList * roster_get_groups(void); +void roster_send_remove(const char * const barejid); #endif |