diff --git a/Makefile.am b/Makefile.am index a7337174..63e46796 100644 --- a/Makefile.am +++ b/Makefile.am @@ -14,7 +14,7 @@ check_PROGRAMS = tests/testsuite tests_testsuite_SOURCES = tests/test_contact_list.c src/contact_list.c src/contact.c \ tests/test_common.c tests/test_prof_history.c src/prof_history.c src/common.c \ tests/test_prof_autocomplete.c src/prof_autocomplete.c tests/testsuite.c \ - tests/test_chat_session.c src/chat_session.c + tests/test_chat_session.c src/chat_session.c src/log.c tests_testsuite_LDADD = -lheadunit -lstdc++ man_MANS = docs/profanity.1 diff --git a/src/chat_session.c b/src/chat_session.c index 6f1d624e..f352fea0 100644 --- a/src/chat_session.c +++ b/src/chat_session.c @@ -1,8 +1,8 @@ -/* +/* * chat_session.c * * Copyright (C) 2012 James Booth - * + * * This file is part of Profanity. * * Profanity is free software: you can redistribute it and/or modify @@ -26,30 +26,37 @@ #include #include "chat_session.h" +#include "log.h" -static ChatSession _chat_session_new(const char * const recipient); +static ChatSession _chat_session_new(const char * const recipient, + gboolean recipient_supports); static void _chat_session_free(ChatSession session); struct chat_session_t { char *recipient; - chat_state_t state; - gboolean sent; + gboolean recipient_supports; }; static GHashTable *sessions; void -chat_session_init(void) +chat_sessions_init(void) { - sessions = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, + sessions = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)_chat_session_free); } void -chat_session_start(const char * const recipient) +chat_sessions_clear(void) +{ + g_hash_table_remove_all(sessions); +} + +void +chat_session_start(const char * const recipient, gboolean recipient_supports) { char *key = strdup(recipient); - ChatSession session = _chat_session_new(key); + ChatSession session = _chat_session_new(key, recipient_supports); g_hash_table_insert(sessions, key, session); } @@ -59,46 +66,26 @@ chat_session_end(const char * const recipient) g_hash_table_remove(sessions, recipient); } -chat_state_t -chat_session_get_state(const char * const recipient) +gboolean +chat_session_recipient_supports(const char * const recipient) { ChatSession session = g_hash_table_lookup(sessions, recipient); + if (session == NULL) { - return SESSION_ERR; + log_error("No chat session found for %s.", recipient); + return FALSE; } else { - return session->state; + return session->recipient_supports; } } -void -chat_session_set_state(const char * const recipient, chat_state_t state) -{ - ChatSession session = g_hash_table_lookup(sessions, recipient); - session->state = state; -} - -gboolean -chat_session_get_sent(const char * const recipient) -{ - ChatSession session = g_hash_table_lookup(sessions, recipient); - return session->sent; -} - -void -chat_session_sent(const char * const recipient) -{ - ChatSession session = g_hash_table_lookup(sessions, recipient); - session->sent = TRUE; -} - static ChatSession -_chat_session_new(const char * const recipient) +_chat_session_new(const char * const recipient, gboolean recipient_supports) { ChatSession new_session = malloc(sizeof(struct chat_session_t)); new_session->recipient = strdup(recipient); - new_session->state = ACTIVE; - new_session->sent = FALSE; - + new_session->recipient_supports = recipient_supports; + return new_session; } diff --git a/src/chat_session.h b/src/chat_session.h index b17fb2ee..aecc47da 100644 --- a/src/chat_session.h +++ b/src/chat_session.h @@ -1,8 +1,8 @@ -/* +/* * chat_session.h * * Copyright (C) 2012 James Booth - * + * * This file is part of Profanity. * * Profanity is free software: you can redistribute it and/or modify @@ -27,21 +27,11 @@ typedef struct chat_session_t *ChatSession; -typedef enum { - ACTIVE, - INACTIVE, - GONE, - COMPOSING, - PAUSED, - SESSION_ERR -} chat_state_t; - -void chat_session_init(void); -void chat_session_start(const char * const recipient); +void chat_sessions_init(void); +void chat_sessions_clear(void); +void chat_session_start(const char * const recipient, + gboolean recipient_supports); void chat_session_end(const char * const recipient); -chat_state_t chat_session_get_state(const char * const recipient); -void chat_session_set_state(const char * const recipient, chat_state_t state); -gboolean chat_session_get_sent(const char * const recipient); -void chat_session_sent(const char * const recipient); +gboolean chat_session_recipient_supports(const char * const recipient); #endif diff --git a/src/command.c b/src/command.c index e9f40409..f8c5b1e9 100644 --- a/src/command.c +++ b/src/command.c @@ -82,6 +82,7 @@ static gboolean _cmd_prefs(const char * const inp, struct cmd_help_t help); static gboolean _cmd_who(const char * const inp, struct cmd_help_t help); static gboolean _cmd_connect(const char * const inp, struct cmd_help_t help); static gboolean _cmd_disconnect(const char * const inp, struct cmd_help_t help); +static gboolean _cmd_sub(const char * const inp, struct cmd_help_t help); static gboolean _cmd_msg(const char * const inp, struct cmd_help_t help); static gboolean _cmd_tiny(const char * const inp, struct cmd_help_t help); static gboolean _cmd_close(const char * const inp, struct cmd_help_t help); @@ -178,6 +179,16 @@ static struct cmd_t main_commands[] = "Example : /msg boothj5@gmail.com Hey, here's a message!", NULL } } }, + { "/sub", + _cmd_sub, + { "/sub user@host", "Subscribe to presence notifications of user.", + { "/sub user@host", + "------------------", + "Send a subscription request to the user to be informed of their presence.", + "", + "Example: /sub myfriend@jabber.org", + NULL } } }, + { "/tiny", _cmd_tiny, { "/tiny url", "Send url as tinyurl in current chat.", @@ -442,7 +453,7 @@ cmd_init(void) p_autocomplete_add(who_ac, (gchar *)strdup(pcmd->cmd+1)); } - p_autocomplete_add(who_ac, "offline"); + p_autocomplete_add(who_ac, strdup("offline")); history_init(); } @@ -691,6 +702,32 @@ _cmd_connect(const char * const inp, struct cmd_help_t help) return result; } +static gboolean +_cmd_sub(const char * const inp, struct cmd_help_t help) +{ + gboolean result = FALSE; + jabber_conn_status_t conn_status = jabber_get_connection_status(); + + if (conn_status != JABBER_CONNECTED) { + cons_show("You are currently not connected."); + result = TRUE; + } else if (strlen(inp) < 6) { + cons_show("Usage: %s", help.usage); + result = TRUE; + } else { + char *user, *lower; + user = strndup(inp+5, strlen(inp)-5); + lower = g_utf8_strdown(user, -1); + + jabber_subscribe(lower); + cons_show("Sent subscription request to %s.", user); + + result = TRUE; + } + + return result; +} + static gboolean _cmd_disconnect(const char * const inp, struct cmd_help_t help) { @@ -788,16 +825,16 @@ _cmd_who(const char * const inp, struct cmd_help_t help) // get show strtok(inp_cpy, " "); - char *show = strtok(NULL, " "); + char *presence = strtok(NULL, " "); // bad arg - if ((show != NULL) - && (strcmp(show, "online") != 0) - && (strcmp(show, "offline") != 0) - && (strcmp(show, "away") != 0) - && (strcmp(show, "chat") != 0) - && (strcmp(show, "xa") != 0) - && (strcmp(show, "dnd") != 0)) { + if ((presence != NULL) + && (strcmp(presence, "online") != 0) + && (strcmp(presence, "offline") != 0) + && (strcmp(presence, "away") != 0) + && (strcmp(presence, "chat") != 0) + && (strcmp(presence, "xa") != 0) + && (strcmp(presence, "dnd") != 0)) { cons_show("Usage: %s", help.usage); // valid arg @@ -805,23 +842,23 @@ _cmd_who(const char * const inp, struct cmd_help_t help) GSList *list = get_contact_list(); // no arg, show all contacts - if (show == NULL) { + if (presence == NULL) { cons_show("All contacts:"); cons_show_contacts(list); // online, show all status that indicate online - } else if (strcmp("online", show) == 0) { - cons_show("Contacts (%s):", show); + } else if (strcmp("online", presence) == 0) { + cons_show("Contacts (%s):", presence); GSList *filtered = NULL; while (list != NULL) { PContact contact = list->data; - const char * const contact_show = (p_contact_show(contact)); - if ((strcmp(contact_show, "online") == 0) - || (strcmp(contact_show, "away") == 0) - || (strcmp(contact_show, "dnd") == 0) - || (strcmp(contact_show, "xa") == 0) - || (strcmp(contact_show, "chat") == 0)) { + const char * const contact_presence = (p_contact_presence(contact)); + if ((strcmp(contact_presence, "online") == 0) + || (strcmp(contact_presence, "away") == 0) + || (strcmp(contact_presence, "dnd") == 0) + || (strcmp(contact_presence, "xa") == 0) + || (strcmp(contact_presence, "chat") == 0)) { filtered = g_slist_append(filtered, contact); } list = g_slist_next(list); @@ -831,12 +868,12 @@ _cmd_who(const char * const inp, struct cmd_help_t help) // show specific status } else { - cons_show("Contacts (%s):", show); + cons_show("Contacts (%s):", presence); GSList *filtered = NULL; while (list != NULL) { PContact contact = list->data; - if (strcmp(p_contact_show(contact), show) == 0) { + if (strcmp(p_contact_presence(contact), presence) == 0) { filtered = g_slist_append(filtered, contact); } list = g_slist_next(list); diff --git a/src/contact.c b/src/contact.c index 12a2e500..3b0d1944 100644 --- a/src/contact.c +++ b/src/contact.c @@ -28,28 +28,42 @@ #include "contact.h" struct p_contact_t { + char *jid; char *name; - char *show; + char *presence; char *status; + char *subscription; }; PContact -p_contact_new(const char * const name, const char * const show, - const char * const status) +p_contact_new(const char * const jid, const char * const name, + const char * const presence, const char * const status, + const char * const subscription) { PContact contact = malloc(sizeof(struct p_contact_t)); - contact->name = strdup(name); + contact->jid = strdup(jid); - if (show == NULL || (strcmp(show, "") == 0)) - contact->show = strdup("online"); + if (name != NULL) { + contact->name = strdup(name); + } else { + contact->name = NULL; + } + + if (presence == NULL || (strcmp(presence, "") == 0)) + contact->presence = strdup("online"); else - contact->show = strdup(show); + contact->presence = strdup(presence); if (status != NULL) contact->status = strdup(status); else contact->status = NULL; + if (subscription != NULL) + contact->subscription = strdup(subscription); + else + contact->subscription = NULL; + return contact; } @@ -57,35 +71,67 @@ PContact p_contact_copy(PContact contact) { PContact copy = malloc(sizeof(struct p_contact_t)); - copy->name = strdup(contact->name); - copy->show = strdup(contact->show); + copy->jid = strdup(contact->jid); + + if (contact->name != NULL) { + copy->name = strdup(contact->name); + } else { + copy->name = NULL; + } + + copy->presence = strdup(contact->presence); if (contact->status != NULL) copy->status = strdup(contact->status); else copy->status = NULL; + if (contact->subscription != NULL) + copy->subscription = strdup(contact->subscription); + else + copy->subscription = NULL; + return copy; } void p_contact_free(PContact contact) { - free(contact->name); - - if (contact->show != NULL) { - free(contact->show); - contact->show = NULL; + if (contact->jid != NULL) { + free(contact->jid); + contact->jid = NULL; } + + if (contact->name != NULL) { + free(contact->name); + contact->name = NULL; + } + + if (contact->presence != NULL) { + free(contact->presence); + contact->presence = NULL; + } + if (contact->status != NULL) { free(contact->status); contact->status = NULL; } + if (contact->subscription != NULL) { + free(contact->subscription); + contact->subscription = NULL; + } + free(contact); contact = NULL; } +const char * +p_contact_jid(const PContact contact) +{ + return contact->jid; +} + const char * p_contact_name(const PContact contact) { @@ -93,9 +139,9 @@ p_contact_name(const PContact contact) } const char * -p_contact_show(const PContact contact) +p_contact_presence(const PContact contact) { - return contact->show; + return contact->presence; } const char * @@ -104,12 +150,50 @@ p_contact_status(const PContact contact) return contact->status; } +const char * +p_contact_subscription(const PContact contact) +{ + return contact->subscription; +} + +void +p_contact_set_presence(const PContact contact, const char * const presence) +{ + if (contact->presence != NULL) { + free(contact->presence); + contact->presence = NULL; + } + + if (presence == NULL) { + contact->presence = NULL; + } else { + contact->presence = strdup(presence); + } +} + +void +p_contact_set_status(const PContact contact, const char * const status) +{ + if (contact->status != NULL) { + free(contact->status); + contact->status = NULL; + } + + if (status == NULL) { + contact->status = NULL; + } else { + contact->status = strdup(status); + } +} + int p_contacts_equal_deep(const PContact c1, const PContact c2) { + int jid_eq = (g_strcmp0(c1->jid, c2->jid) == 0); int name_eq = (g_strcmp0(c1->name, c2->name) == 0); - int show_eq = (g_strcmp0(c1->show, c2->show) == 0); + int presence_eq = (g_strcmp0(c1->presence, c2->presence) == 0); int status_eq = (g_strcmp0(c1->status, c2->status) == 0); + int subscription_eq = (g_strcmp0(c1->subscription, c2->subscription) == 0); - return (name_eq && show_eq && status_eq); + return (jid_eq && name_eq && presence_eq && status_eq && subscription_eq); } diff --git a/src/contact.h b/src/contact.h index 8f778ca9..a4f487e8 100644 --- a/src/contact.h +++ b/src/contact.h @@ -25,13 +25,18 @@ typedef struct p_contact_t *PContact; -PContact p_contact_new(const char * const name, const char * const show, - const char * const status); +PContact p_contact_new(const char * const jid, const char * const name, + const char * const presence, const char * const status, + const char * const subscription); PContact p_contact_copy(PContact contact); void p_contact_free(PContact contact); +const char * p_contact_jid(PContact contact); const char * p_contact_name(PContact contact); -const char * p_contact_show(PContact contact); +const char * p_contact_presence(PContact contact); const char * p_contact_status(PContact contact); +const char * p_contact_subscription(const PContact contact); +void p_contact_set_presence(const PContact contact, const char * const presence); +void p_contact_set_status(const PContact contact, const char * const status); int p_contacts_equal_deep(const PContact c1, const PContact c2); #endif diff --git a/src/contact_list.c b/src/contact_list.c index e266e25e..d05d7412 100644 --- a/src/contact_list.c +++ b/src/contact_list.c @@ -22,24 +22,30 @@ #include +#include + #include "contact.h" +#include "log.h" #include "prof_autocomplete.h" static PAutocomplete ac; +static GHashTable *contacts; + +static gboolean _key_equals(void *key1, void *key2); void contact_list_init(void) { - ac = p_obj_autocomplete_new((PStrFunc)p_contact_name, - (PCopyFunc)p_contact_copy, - (PEqualDeepFunc)p_contacts_equal_deep, - (GDestroyNotify)p_contact_free); + ac = p_autocomplete_new(); + contacts = g_hash_table_new_full(g_str_hash, (GEqualFunc)_key_equals, g_free, + (GDestroyNotify)p_contact_free); } void contact_list_clear(void) { p_autocomplete_clear(ac); + g_hash_table_remove_all(contacts); } void @@ -49,22 +55,63 @@ contact_list_reset_search_attempts(void) } gboolean -contact_list_remove(const char * const name) +contact_list_add(const char * const jid, const char * const name, + const char * const presence, const char * const status, + const char * const subscription) { - return p_autocomplete_remove(ac, name); + gboolean added = FALSE; + PContact contact = g_hash_table_lookup(contacts, jid); + + if (contact == NULL) { + contact = p_contact_new(jid, name, presence, status, subscription); + g_hash_table_insert(contacts, strdup(jid), contact); + p_autocomplete_add(ac, strdup(jid)); + added = TRUE; + } + + return added; } gboolean -contact_list_add(const char * const name, const char * const show, +contact_list_update_contact(const char * const jid, const char * const presence, const char * const status) { - return p_autocomplete_add(ac, p_contact_new(name, show, status)); + gboolean changed = FALSE; + PContact contact = g_hash_table_lookup(contacts, jid); + + if (contact == NULL) { + log_warning("Contact not in list: %s", jid); + return FALSE; + } + + if (g_strcmp0(p_contact_presence(contact), presence) != 0) { + p_contact_set_presence(contact, presence); + changed = TRUE; + } + + if (g_strcmp0(p_contact_status(contact), status) != 0) { + p_contact_set_status(contact, status); + changed = TRUE; + } + + return changed; } GSList * get_contact_list(void) { - return p_autocomplete_get_list(ac); + 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_append(result, value); + } + + // resturn all contact structs + return result; } char * @@ -76,15 +123,14 @@ contact_list_find_contact(char *search_str) PContact contact_list_get_contact(const char const *jid) { - GSList *contacts = get_contact_list(); - - while (contacts != NULL) { - PContact contact = contacts->data; - if (strcmp(p_contact_name(contact), jid) == 0) { - return contact; - } - contacts = g_slist_next(contacts); - } - - return NULL; + return g_hash_table_lookup(contacts, jid); +} + +static +gboolean _key_equals(void *key1, void *key2) +{ + gchar *str1 = (gchar *) key1; + gchar *str2 = (gchar *) key2; + + return (g_strcmp0(str1, str2) == 0); } diff --git a/src/contact_list.h b/src/contact_list.h index bc239111..90ae947b 100644 --- a/src/contact_list.h +++ b/src/contact_list.h @@ -30,9 +30,11 @@ void contact_list_init(void); void contact_list_clear(void); void contact_list_reset_search_attempts(void); -gboolean contact_list_add(const char * const name, const char * const show, +gboolean contact_list_add(const char * const jid, const char * const name, + const char * const presence, const char * const status, + const char * const subscription); +gboolean contact_list_update_contact(const char * const jid, const char * const presence, const char * const status); -gboolean contact_list_remove(const char * const name); GSList * get_contact_list(void); char * contact_list_find_contact(char *search_str); PContact contact_list_get_contact(const char const *jid); diff --git a/src/jabber.c b/src/jabber.c index 4913618e..472aa015 100644 --- a/src/jabber.c +++ b/src/jabber.c @@ -25,7 +25,9 @@ #include +#include "chat_session.h" #include "common.h" +#include "contact_list.h" #include "jabber.h" #include "log.h" #include "preferences.h" @@ -49,6 +51,8 @@ static void _xmpp_file_logger(void * const userdata, const char * const msg); static xmpp_log_t * _xmpp_get_file_logger(); +static void _jabber_roster_request(void); + // XMPP event handlers static void _connection_handler(xmpp_conn_t * const conn, const xmpp_conn_event_t status, const int error, @@ -165,23 +169,16 @@ jabber_send(const char * const msg, const char * const recipient) } void -jabber_roster_request(void) +jabber_subscribe(const char * const recipient) { - xmpp_stanza_t *iq, *query; + xmpp_stanza_t *presence; - iq = xmpp_stanza_new(jabber_conn.ctx); - xmpp_stanza_set_name(iq, "iq"); - xmpp_stanza_set_type(iq, "get"); - xmpp_stanza_set_id(iq, "roster"); - - query = xmpp_stanza_new(jabber_conn.ctx); - xmpp_stanza_set_name(query, "query"); - xmpp_stanza_set_ns(query, XMPP_NS_ROSTER); - - xmpp_stanza_add_child(iq, query); - xmpp_stanza_release(query); - xmpp_send(jabber_conn.conn, iq); - xmpp_stanza_release(iq); + presence = xmpp_stanza_new(jabber_conn.ctx); + xmpp_stanza_set_name(presence, "presence"); + xmpp_stanza_set_type(presence, "subscribe"); + xmpp_stanza_set_attribute(presence, "to", recipient); + xmpp_send(jabber_conn.conn, presence); + xmpp_stanza_release(presence); } void @@ -248,11 +245,32 @@ jabber_get_jid(void) void jabber_free_resources(void) { + chat_sessions_clear(); xmpp_conn_release(jabber_conn.conn); xmpp_ctx_free(jabber_conn.ctx); xmpp_shutdown(); } +static void +_jabber_roster_request(void) +{ + xmpp_stanza_t *iq, *query; + + iq = xmpp_stanza_new(jabber_conn.ctx); + xmpp_stanza_set_name(iq, "iq"); + xmpp_stanza_set_type(iq, "get"); + xmpp_stanza_set_id(iq, "roster"); + + query = xmpp_stanza_new(jabber_conn.ctx); + xmpp_stanza_set_name(query, "query"); + xmpp_stanza_set_ns(query, XMPP_NS_ROSTER); + + xmpp_stanza_add_child(iq, query); + xmpp_stanza_release(query); + xmpp_send(jabber_conn.conn, iq); + xmpp_stanza_release(iq); +} + static int _message_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata) @@ -319,21 +337,16 @@ _connection_handler(xmpp_conn_t * const conn, if (status == XMPP_CONN_CONNECT) { const char *jid = xmpp_conn_get_jid(conn); prof_handle_login_success(jid); + chat_sessions_init(); - xmpp_stanza_t* pres; xmpp_handler_add(conn, _message_handler, NULL, "message", NULL, ctx); xmpp_handler_add(conn, _presence_handler, NULL, "presence", NULL, ctx); xmpp_id_handler_add(conn, _roster_handler, "roster", ctx); xmpp_timed_handler_add(conn, _ping_timed_handler, PING_INTERVAL, ctx); - pres = xmpp_stanza_new(ctx); - xmpp_stanza_set_name(pres, "presence"); - xmpp_send(conn, pres); - xmpp_stanza_release(pres); - + _jabber_roster_request(); jabber_conn.conn_status = JABBER_CONNECTED; jabber_conn.presence = PRESENCE_ONLINE; - jabber_roster_request(); } else { // received close stream response from server after disconnect @@ -362,6 +375,7 @@ static int _roster_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata) { + xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata; xmpp_stanza_t *query, *item; char *type = xmpp_stanza_get_type(stanza); @@ -369,27 +383,25 @@ _roster_handler(xmpp_conn_t * const conn, log_error("Roster query failed"); else { query = xmpp_stanza_get_child_by_name(stanza, "query"); - GSList *roster = NULL; item = xmpp_stanza_get_children(query); while (item != NULL) { - const char *name = xmpp_stanza_get_attribute(item, "name"); const char *jid = xmpp_stanza_get_attribute(item, "jid"); + const char *name = xmpp_stanza_get_attribute(item, "name"); + const char *sub = xmpp_stanza_get_attribute(item, "subscription"); + gboolean added = contact_list_add(jid, name, "offline", NULL, sub); - jabber_roster_entry *entry = malloc(sizeof(jabber_roster_entry)); - - if (name != NULL) { - entry->name = strdup(name); - } else { - entry->name = NULL; + if (!added) { + log_warning("Attempt to add contact twice: %s", jid); } - entry->jid = strdup(jid); - roster = g_slist_append(roster, entry); item = xmpp_stanza_get_next(item); } - - prof_handle_roster(roster); + xmpp_stanza_t* pres; + pres = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(pres, "presence"); + xmpp_send(conn, pres); + xmpp_stanza_release(pres); } return 1; @@ -434,26 +446,28 @@ _presence_handler(xmpp_conn_t * const conn, char *from = xmpp_stanza_get_attribute(stanza, "from"); char *short_from = strtok(from, "/"); char *type = xmpp_stanza_get_attribute(stanza, "type"); - char *show_str, *status_str; - xmpp_stanza_t *show = xmpp_stanza_get_child_by_name(stanza, "show"); - if (show != NULL) - show_str = xmpp_stanza_get_text(show); - else - show_str = NULL; - xmpp_stanza_t *status = xmpp_stanza_get_child_by_name(stanza, "status"); if (status != NULL) status_str = xmpp_stanza_get_text(status); else status_str = NULL; - if (strcmp(short_jid, short_from) !=0) { - if (type == NULL) { + if ((type != NULL) && (strcmp(type, "unavailable") == 0)) { + if (strcmp(short_jid, short_from) !=0) { + prof_handle_contact_offline(short_from, "offline", status_str); + } + } else { + + xmpp_stanza_t *show = xmpp_stanza_get_child_by_name(stanza, "show"); + if (show != NULL) + show_str = xmpp_stanza_get_text(show); + else + show_str = "online"; + + if (strcmp(short_jid, short_from) !=0) { prof_handle_contact_online(short_from, show_str, status_str); - } else { - prof_handle_contact_offline(short_from, show_str, status_str); } } diff --git a/src/jabber.h b/src/jabber.h index d12d00b3..726fb1a5 100644 --- a/src/jabber.h +++ b/src/jabber.h @@ -44,8 +44,8 @@ void jabber_init(const int disable_tls); jabber_conn_status_t jabber_connect(const char * const user, const char * const passwd); void jabber_disconnect(void); -void jabber_roster_request(void); void jabber_process_events(void); +void jabber_subscribe(const char * const recipient); void jabber_send(const char * const msg, const char * const recipient); void jabber_update_presence(jabber_presence_t status, const char * const msg); const char * jabber_get_jid(void); diff --git a/src/prof_autocomplete.c b/src/prof_autocomplete.c index 79d44498..b41c5368 100644 --- a/src/prof_autocomplete.c +++ b/src/prof_autocomplete.c @@ -29,59 +29,25 @@ struct p_autocomplete_t { GSList *items; GSList *last_found; gchar *search_str; - PStrFunc str_func; - PCopyFunc copy_func; - PEqualDeepFunc equal_deep_func; - GDestroyNotify free_func; }; static gchar * _search_from(PAutocomplete ac, GSList *curr); -static const char *_str_func_default(const char *orig); -static const char *_copy_func_default(const char *orig); -static int _deep_equals_func_default(const char *o1, const char *o2); PAutocomplete p_autocomplete_new(void) -{ - return p_obj_autocomplete_new(NULL, NULL, NULL, NULL); -} - -PAutocomplete -p_obj_autocomplete_new(PStrFunc str_func, PCopyFunc copy_func, - PEqualDeepFunc equal_deep_func, GDestroyNotify free_func) { PAutocomplete new = malloc(sizeof(struct p_autocomplete_t)); new->items = NULL; new->last_found = NULL; new->search_str = NULL; - if (str_func) - new->str_func = str_func; - else - new->str_func = (PStrFunc)_str_func_default; - - if (copy_func) - new->copy_func = copy_func; - else - new->copy_func = (PCopyFunc)_copy_func_default; - - if (free_func) - new->free_func = free_func; - else - new->free_func = (GDestroyNotify)free; - - if (equal_deep_func) - new->equal_deep_func = equal_deep_func; - else - new->equal_deep_func = (PEqualDeepFunc)_deep_equals_func_default; - return new; } void p_autocomplete_clear(PAutocomplete ac) { - g_slist_free_full(ac->items, ac->free_func); + g_slist_free_full(ac->items, free); ac->items = NULL; p_autocomplete_reset(ac); @@ -109,16 +75,16 @@ p_autocomplete_add(PAutocomplete ac, void *item) while(curr) { // insert - if (g_strcmp0(ac->str_func(curr->data), ac->str_func(item)) > 0) { + if (g_strcmp0(curr->data, item) > 0) { ac->items = g_slist_insert_before(ac->items, curr, item); return TRUE; // update - } else if (g_strcmp0(ac->str_func(curr->data), ac->str_func(item)) == 0) { + } else if (g_strcmp0(curr->data, item) == 0) { // only update if data different - if (!ac->equal_deep_func(curr->data, item)) { - ac->free_func(curr->data); + if (strcmp(curr->data, item) != 0) { + free(curr->data); curr->data = item; return TRUE; } else { @@ -141,7 +107,7 @@ p_autocomplete_remove(PAutocomplete ac, const char * const item) { // reset last found if it points to the item to be removed if (ac->last_found != NULL) - if (g_strcmp0(ac->str_func(ac->last_found->data), item) == 0) + if (g_strcmp0(ac->last_found->data, item) == 0) ac->last_found = NULL; if (!ac->items) { @@ -150,10 +116,10 @@ p_autocomplete_remove(PAutocomplete ac, const char * const item) GSList *curr = ac->items; while(curr) { - if (g_strcmp0(ac->str_func(curr->data), item) == 0) { + if (g_strcmp0(curr->data, item) == 0) { void *current_item = curr->data; ac->items = g_slist_remove(ac->items, curr->data); - ac->free_func(current_item); + free(current_item); return TRUE; } @@ -172,7 +138,7 @@ p_autocomplete_get_list(PAutocomplete ac) GSList *curr = ac->items; while(curr) { - copy = g_slist_append(copy, ac->copy_func(curr->data)); + copy = g_slist_append(copy, strdup(curr->data)); curr = g_slist_next(curr); } @@ -221,17 +187,17 @@ _search_from(PAutocomplete ac, GSList *curr) while(curr) { // match found - if (strncmp(ac->str_func(curr->data), + if (strncmp(curr->data, ac->search_str, strlen(ac->search_str)) == 0) { gchar *result = - (gchar *) malloc((strlen(ac->str_func(curr->data)) + 1) * sizeof(gchar)); + (gchar *) malloc((strlen(curr->data) + 1) * sizeof(gchar)); // set pointer to last found ac->last_found = curr; // return the string, must be free'd by caller - strcpy(result, ac->str_func(curr->data)); + strcpy(result, curr->data); return result; } @@ -240,21 +206,3 @@ _search_from(PAutocomplete ac, GSList *curr) return NULL; } - -static const char * -_str_func_default(const char *orig) -{ - return orig; -} - -static const char * -_copy_func_default(const char *orig) -{ - return strdup(orig); -} - -static int -_deep_equals_func_default(const char *o1, const char *o2) -{ - return (strcmp(o1, o2) == 0); -} diff --git a/src/profanity.c b/src/profanity.c index 4dd618cb..885c55ea 100644 --- a/src/profanity.c +++ b/src/profanity.c @@ -41,7 +41,6 @@ static log_level_t _get_log_level(char *log_level); static gboolean _process_input(char *inp); static void _create_config_directory(); -static void _free_roster_entry(jabber_roster_entry *entry); static void _init(const int disable_tls, char *log_level); static void _shutdown(void); @@ -168,38 +167,33 @@ prof_handle_failed_login(void) void prof_handle_contact_online(char *contact, char *show, char *status) { - gboolean result = contact_list_add(contact, show, status); - if (result) { - win_contact_online(contact, show, status); + gboolean updated = contact_list_update_contact(contact, show, status); + + if (updated) { + PContact result = contact_list_get_contact(contact); + if (p_contact_subscription(result) != NULL) { + if (strcmp(p_contact_subscription(result), "none") != 0) { + win_contact_online(contact, show, status); + win_page_off(); + } + } } - win_page_off(); } void prof_handle_contact_offline(char *contact, char *show, char *status) { - gboolean result = contact_list_add(contact, "offline", status); - if (result) { - win_contact_offline(contact, show, status); - } - win_page_off(); -} + gboolean updated = contact_list_update_contact(contact, "offline", status); -void -prof_handle_roster(GSList *roster) -{ - while (roster != NULL) { - jabber_roster_entry *entry = roster->data; - - // if contact not in contact list add them as offline - if (contact_list_find_contact(entry->jid) == NULL) { - contact_list_add(entry->jid, "offline", NULL); + if (updated) { + PContact result = contact_list_get_contact(contact); + if (p_contact_subscription(result) != NULL) { + if (strcmp(p_contact_subscription(result), "none") != 0) { + win_contact_offline(contact, show, status); + win_page_off(); + } } - - roster = g_slist_next(roster); } - - g_slist_free_full(roster, (GDestroyNotify)_free_roster_entry); } static void @@ -211,16 +205,6 @@ _create_config_directory(void) g_string_free(dir, TRUE); } -static void -_free_roster_entry(jabber_roster_entry *entry) -{ - if (entry->name != NULL) { - free(entry->name); - entry->name = NULL; - } - free(entry->jid); -} - static log_level_t _get_log_level(char *log_level) { diff --git a/src/profanity.h b/src/profanity.h index 430148e2..a67fb2df 100644 --- a/src/profanity.h +++ b/src/profanity.h @@ -23,11 +23,6 @@ #ifndef PROFANITY_H #define PROFANITY_H -typedef struct roster_entry_t { - char *name; - char *jid; -} jabber_roster_entry; - void prof_run(const int disable_tls, char *log_level); void prof_handle_login_success(const char *jid); diff --git a/src/windows.c b/src/windows.c index f1c8f0fe..c7e49020 100644 --- a/src/windows.c +++ b/src/windows.c @@ -427,8 +427,8 @@ win_show_outgoing_msg(const char * const from, const char * const to, } if (contact != NULL) { - if (strcmp(p_contact_show(contact), "offline") == 0) { - const char const *show = p_contact_show(contact); + if (strcmp(p_contact_presence(contact), "offline") == 0) { + const char const *show = p_contact_presence(contact); const char const *status = p_contact_status(contact); _show_status_string(win, to, show, status, "--", "offline"); } @@ -703,44 +703,56 @@ cons_show_contacts(GSList *list) while(curr) { PContact contact = curr->data; - const char *show = p_contact_show(contact); + const char *jid = p_contact_jid(contact); + const char *name = p_contact_name(contact); + const char *presence = p_contact_presence(contact); + const char *status = p_contact_status(contact); + const char *sub = p_contact_subscription(contact); - _win_show_time(_cons_win); + if (strcmp(sub, "none") != 0) { + _win_show_time(_cons_win); - if (strcmp(show, "online") == 0) { - wattron(_cons_win, COLOUR_ONLINE); - } else if (strcmp(show, "away") == 0) { - wattron(_cons_win, COLOUR_AWAY); - } else if (strcmp(show, "chat") == 0) { - wattron(_cons_win, COLOUR_CHAT); - } else if (strcmp(show, "dnd") == 0) { - wattron(_cons_win, COLOUR_DND); - } else if (strcmp(show, "xa") == 0) { - wattron(_cons_win, COLOUR_XA); - } else { - wattron(_cons_win, COLOUR_OFFLINE); - } + if (strcmp(presence, "online") == 0) { + wattron(_cons_win, COLOUR_ONLINE); + } else if (strcmp(presence, "away") == 0) { + wattron(_cons_win, COLOUR_AWAY); + } else if (strcmp(presence, "chat") == 0) { + wattron(_cons_win, COLOUR_CHAT); + } else if (strcmp(presence, "dnd") == 0) { + wattron(_cons_win, COLOUR_DND); + } else if (strcmp(presence, "xa") == 0) { + wattron(_cons_win, COLOUR_XA); + } else { + wattron(_cons_win, COLOUR_OFFLINE); + } - wprintw(_cons_win, "%s", p_contact_name(contact)); - wprintw(_cons_win, " is %s", show); + wprintw(_cons_win, "%s", jid); - if (p_contact_status(contact)) - wprintw(_cons_win, ", \"%s\"", p_contact_status(contact)); + if (name != NULL) { + wprintw(_cons_win, " (%s)", name); + } - wprintw(_cons_win, "\n"); + wprintw(_cons_win, " is %s", presence); - if (strcmp(show, "online") == 0) { - wattroff(_cons_win, COLOUR_ONLINE); - } else if (strcmp(show, "away") == 0) { - wattroff(_cons_win, COLOUR_AWAY); - } else if (strcmp(show, "chat") == 0) { - wattroff(_cons_win, COLOUR_CHAT); - } else if (strcmp(show, "dnd") == 0) { - wattroff(_cons_win, COLOUR_DND); - } else if (strcmp(show, "xa") == 0) { - wattroff(_cons_win, COLOUR_XA); - } else { - wattroff(_cons_win, COLOUR_OFFLINE); + if (status != NULL) { + wprintw(_cons_win, ", \"%s\"", p_contact_status(contact)); + } + + wprintw(_cons_win, "\n"); + + if (strcmp(presence, "online") == 0) { + wattroff(_cons_win, COLOUR_ONLINE); + } else if (strcmp(presence, "away") == 0) { + wattroff(_cons_win, COLOUR_AWAY); + } else if (strcmp(presence, "chat") == 0) { + wattroff(_cons_win, COLOUR_CHAT); + } else if (strcmp(presence, "dnd") == 0) { + wattroff(_cons_win, COLOUR_DND); + } else if (strcmp(presence, "xa") == 0) { + wattroff(_cons_win, COLOUR_XA); + } else { + wattroff(_cons_win, COLOUR_OFFLINE); + } } curr = g_slist_next(curr); diff --git a/tests/test_contact_list.c b/tests/test_contact_list.c index 18d5a6e4..ef31abbc 100644 --- a/tests/test_contact_list.c +++ b/tests/test_contact_list.c @@ -31,24 +31,24 @@ static void empty_list_when_none_added(void) static void contains_one_element(void) { - contact_list_add("James", NULL, NULL); + contact_list_add("James", NULL, NULL, NULL, NULL); GSList *list = get_contact_list(); assert_int_equals(1, g_slist_length(list)); } static void first_element_correct(void) { - contact_list_add("James", NULL, NULL); + contact_list_add("James", NULL, NULL, NULL, NULL); GSList *list = get_contact_list(); PContact james = list->data; - assert_string_equals("James", p_contact_name(james)); + assert_string_equals("James", p_contact_jid(james)); } static void contains_two_elements(void) { - contact_list_add("James", NULL, NULL); - contact_list_add("Dave", NULL, NULL); + contact_list_add("James", NULL, NULL, NULL, NULL); + contact_list_add("Dave", NULL, NULL, NULL, NULL); GSList *list = get_contact_list(); assert_int_equals(2, g_slist_length(list)); @@ -56,22 +56,22 @@ static void contains_two_elements(void) static void first_and_second_elements_correct(void) { - contact_list_add("James", NULL, NULL); - contact_list_add("Dave", NULL, NULL); + contact_list_add("James", NULL, NULL, NULL, NULL); + contact_list_add("Dave", NULL, NULL, NULL, NULL); GSList *list = get_contact_list(); - PContact dave = list->data; - PContact james = (g_slist_next(list))->data; + PContact first = list->data; + PContact second = (g_slist_next(list))->data; - assert_string_equals("James", p_contact_name(james)); - assert_string_equals("Dave", p_contact_name(dave)); + assert_string_equals("James", p_contact_jid(first)); + assert_string_equals("Dave", p_contact_jid(second)); } static void contains_three_elements(void) { - contact_list_add("James", NULL, NULL); - contact_list_add("Bob", NULL, NULL); - contact_list_add("Dave", NULL, NULL); + contact_list_add("James", NULL, NULL, NULL, NULL); + contact_list_add("Bob", NULL, NULL, NULL, NULL); + contact_list_add("Dave", NULL, NULL, NULL, NULL); GSList *list = get_contact_list(); assert_int_equals(3, g_slist_length(list)); @@ -79,194 +79,100 @@ static void contains_three_elements(void) static void first_three_elements_correct(void) { - contact_list_add("Bob", NULL, NULL); - contact_list_add("Dave", NULL, NULL); - contact_list_add("James", NULL, NULL); + contact_list_add("Bob", NULL, NULL, NULL, NULL); + contact_list_add("Dave", NULL, NULL, NULL, NULL); + contact_list_add("James", NULL, NULL, NULL, NULL); GSList *list = get_contact_list(); PContact bob = list->data; PContact dave = (g_slist_next(list))->data; PContact james = (g_slist_next(g_slist_next(list)))->data; - assert_string_equals("James", p_contact_name(james)); - assert_string_equals("Dave", p_contact_name(dave)); - assert_string_equals("Bob", p_contact_name(bob)); + assert_string_equals("James", p_contact_jid(james)); + assert_string_equals("Dave", p_contact_jid(dave)); + assert_string_equals("Bob", p_contact_jid(bob)); } static void add_twice_at_beginning_adds_once(void) { - contact_list_add("James", NULL, NULL); - contact_list_add("James", NULL, NULL); - contact_list_add("Dave", NULL, NULL); - contact_list_add("Bob", NULL, NULL); + contact_list_add("James", NULL, NULL, NULL, NULL); + contact_list_add("James", NULL, NULL, NULL, NULL); + contact_list_add("Dave", NULL, NULL, NULL, NULL); + contact_list_add("Bob", NULL, NULL, NULL, NULL); GSList *list = get_contact_list(); - PContact bob = list->data; - PContact dave = (g_slist_next(list))->data; - PContact james = (g_slist_next(g_slist_next(list)))->data; + PContact first = list->data; + PContact second = (g_slist_next(list))->data; + PContact third = (g_slist_next(g_slist_next(list)))->data; assert_int_equals(3, g_slist_length(list)); - assert_string_equals("James", p_contact_name(james)); - assert_string_equals("Dave", p_contact_name(dave)); - assert_string_equals("Bob", p_contact_name(bob)); + assert_string_equals("James", p_contact_jid(first)); + assert_string_equals("Dave", p_contact_jid(second)); + assert_string_equals("Bob", p_contact_jid(third)); } static void add_twice_in_middle_adds_once(void) { - contact_list_add("James", NULL, NULL); - contact_list_add("Dave", NULL, NULL); - contact_list_add("James", NULL, NULL); - contact_list_add("Bob", NULL, NULL); + contact_list_add("James", NULL, NULL, NULL, NULL); + contact_list_add("Dave", NULL, NULL, NULL, NULL); + contact_list_add("James", NULL, NULL, NULL, NULL); + contact_list_add("Bob", NULL, NULL, NULL, NULL); GSList *list = get_contact_list(); - PContact bob = list->data; - PContact dave = (g_slist_next(list))->data; - PContact james = (g_slist_next(g_slist_next(list)))->data; + PContact first = list->data; + PContact second = (g_slist_next(list))->data; + PContact third = (g_slist_next(g_slist_next(list)))->data; assert_int_equals(3, g_slist_length(list)); - assert_string_equals("James", p_contact_name(james)); - assert_string_equals("Dave", p_contact_name(dave)); - assert_string_equals("Bob", p_contact_name(bob)); + assert_string_equals("James", p_contact_jid(first)); + assert_string_equals("Dave", p_contact_jid(second)); + assert_string_equals("Bob", p_contact_jid(third)); } static void add_twice_at_end_adds_once(void) { - contact_list_add("James", NULL, NULL); - contact_list_add("Dave", NULL, NULL); - contact_list_add("Bob", NULL, NULL); - contact_list_add("James", NULL, NULL); + contact_list_add("James", NULL, NULL, NULL, NULL); + contact_list_add("Dave", NULL, NULL, NULL, NULL); + contact_list_add("Bob", NULL, NULL, NULL, NULL); + contact_list_add("James", NULL, NULL, NULL, NULL); GSList *list = get_contact_list(); - PContact bob = list->data; - PContact dave = (g_slist_next(list))->data; - PContact james = (g_slist_next(g_slist_next(list)))->data; + PContact first = list->data; + PContact second = (g_slist_next(list))->data; + PContact third = (g_slist_next(g_slist_next(list)))->data; assert_int_equals(3, g_slist_length(list)); - assert_string_equals("James", p_contact_name(james)); - assert_string_equals("Dave", p_contact_name(dave)); - assert_string_equals("Bob", p_contact_name(bob)); -} - -static void remove_when_none_does_nothing(void) -{ - contact_list_remove("James"); - GSList *list = get_contact_list(); - - assert_int_equals(0, g_slist_length(list)); -} - -static void remove_when_one_removes(void) -{ - contact_list_add("James", NULL, NULL); - contact_list_remove("James"); - GSList *list = get_contact_list(); - - assert_int_equals(0, g_slist_length(list)); -} - -static void remove_first_when_two(void) -{ - contact_list_add("James", NULL, NULL); - contact_list_add("Dave", NULL, NULL); - - contact_list_remove("James"); - GSList *list = get_contact_list(); - - assert_int_equals(1, g_slist_length(list)); - PContact dave = list->data; - assert_string_equals("Dave", p_contact_name(dave)); -} - -static void remove_second_when_two(void) -{ - contact_list_add("James", NULL, NULL); - contact_list_add("Dave", NULL, NULL); - - contact_list_remove("Dave"); - GSList *list = get_contact_list(); - - assert_int_equals(1, g_slist_length(list)); - PContact james = list->data; - assert_string_equals("James", p_contact_name(james)); -} - -static void remove_first_when_three(void) -{ - contact_list_add("James", NULL, NULL); - contact_list_add("Dave", NULL, NULL); - contact_list_add("Bob", NULL, NULL); - - contact_list_remove("James"); - GSList *list = get_contact_list(); - - assert_int_equals(2, g_slist_length(list)); - PContact bob = list->data; - PContact dave = (g_slist_next(list))->data; - - assert_string_equals("Dave", p_contact_name(dave)); - assert_string_equals("Bob", p_contact_name(bob)); -} - -static void remove_second_when_three(void) -{ - contact_list_add("James", NULL, NULL); - contact_list_add("Dave", NULL, NULL); - contact_list_add("Bob", NULL, NULL); - - contact_list_remove("Dave"); - GSList *list = get_contact_list(); - - assert_int_equals(2, g_slist_length(list)); - PContact bob = list->data; - PContact james = (g_slist_next(list))->data; - - assert_string_equals("James", p_contact_name(james)); - assert_string_equals("Bob", p_contact_name(bob)); -} - -static void remove_third_when_three(void) -{ - contact_list_add("James", NULL, NULL); - contact_list_add("Dave", NULL, NULL); - contact_list_add("Bob", NULL, NULL); - - contact_list_remove("Bob"); - GSList *list = get_contact_list(); - - assert_int_equals(2, g_slist_length(list)); - PContact dave = list->data; - PContact james = (g_slist_next(list))->data; - - assert_string_equals("James", p_contact_name(james)); - assert_string_equals("Dave", p_contact_name(dave)); + assert_string_equals("James", p_contact_jid(first)); + assert_string_equals("Dave", p_contact_jid(second)); + assert_string_equals("Bob", p_contact_jid(third)); } static void test_show_when_value(void) { - contact_list_add("James", "away", NULL); + contact_list_add("James", NULL, "away", NULL, NULL); GSList *list = get_contact_list(); PContact james = list->data; - assert_string_equals("away", p_contact_show(james)); + assert_string_equals("away", p_contact_presence(james)); } static void test_show_online_when_no_value(void) { - contact_list_add("James", NULL, NULL); + contact_list_add("James", NULL, NULL, NULL, NULL); GSList *list = get_contact_list(); PContact james = list->data; - assert_string_equals("online", p_contact_show(james)); + assert_string_equals("online", p_contact_presence(james)); } static void test_show_online_when_empty_string(void) { - contact_list_add("James", "", NULL); + contact_list_add("James", NULL, "", NULL, NULL); GSList *list = get_contact_list(); PContact james = list->data; - assert_string_equals("online", p_contact_show(james)); + assert_string_equals("online", p_contact_presence(james)); } static void test_status_when_value(void) { - contact_list_add("James", NULL, "I'm not here right now"); + contact_list_add("James", NULL, NULL, "I'm not here right now", NULL); GSList *list = get_contact_list(); PContact james = list->data; @@ -275,7 +181,7 @@ static void test_status_when_value(void) static void test_status_when_no_value(void) { - contact_list_add("James", NULL, NULL); + contact_list_add("James", NULL, NULL, NULL, NULL); GSList *list = get_contact_list(); PContact james = list->data; @@ -284,57 +190,57 @@ static void test_status_when_no_value(void) static void update_show(void) { - contact_list_add("James", "away", NULL); - contact_list_add("James", "dnd", NULL); + contact_list_add("James", NULL, "away", NULL, NULL); + contact_list_update_contact("James", "dnd", NULL); GSList *list = get_contact_list(); assert_int_equals(1, g_slist_length(list)); - PContact james = list->data; - assert_string_equals("James", p_contact_name(james)); - assert_string_equals("dnd", p_contact_show(james)); + PContact first = list->data; + assert_string_equals("James", p_contact_jid(first)); + assert_string_equals("dnd", p_contact_presence(first)); } static void set_show_to_null(void) { - contact_list_add("James", "away", NULL); - contact_list_add("James", NULL, NULL); + contact_list_add("James", NULL, "away", NULL, NULL); + contact_list_update_contact("James", NULL, NULL); GSList *list = get_contact_list(); assert_int_equals(1, g_slist_length(list)); PContact james = list->data; - assert_string_equals("James", p_contact_name(james)); - assert_string_equals("online", p_contact_show(james)); + assert_string_equals("James", p_contact_jid(james)); + assert_is_null(p_contact_presence(james)); } static void update_status(void) { - contact_list_add("James", NULL, "I'm not here right now"); - contact_list_add("James", NULL, "Gone to lunch"); + contact_list_add("James", NULL, NULL, "I'm not here right now", NULL); + contact_list_update_contact("James", NULL, "Gone to lunch"); GSList *list = get_contact_list(); assert_int_equals(1, g_slist_length(list)); PContact james = list->data; - assert_string_equals("James", p_contact_name(james)); + assert_string_equals("James", p_contact_jid(james)); assert_string_equals("Gone to lunch", p_contact_status(james)); } static void set_status_to_null(void) { - contact_list_add("James", NULL, "Gone to lunch"); - contact_list_add("James", NULL, NULL); + contact_list_add("James", NULL, NULL, "Gone to lunch", NULL); + contact_list_update_contact("James", NULL, NULL); GSList *list = get_contact_list(); assert_int_equals(1, g_slist_length(list)); PContact james = list->data; - assert_string_equals("James", p_contact_name(james)); + assert_string_equals("James", p_contact_jid(james)); assert_is_null(p_contact_status(james)); } static void find_first_exists(void) { - contact_list_add("James", NULL, NULL); - contact_list_add("Dave", NULL, NULL); - contact_list_add("Bob", NULL, NULL); + contact_list_add("James", NULL, NULL, NULL, NULL); + contact_list_add("Dave", NULL, NULL, NULL, NULL); + contact_list_add("Bob", NULL, NULL, NULL, NULL); char *search = (char *) malloc(2 * sizeof(char)); strcpy(search, "B"); @@ -347,9 +253,9 @@ static void find_first_exists(void) static void find_second_exists(void) { - contact_list_add("James", NULL, NULL); - contact_list_add("Dave", NULL, NULL); - contact_list_add("Bob", NULL, NULL); + contact_list_add("James", NULL, NULL, NULL, NULL); + contact_list_add("Dave", NULL, NULL, NULL, NULL); + contact_list_add("Bob", NULL, NULL, NULL, NULL); char *result = contact_list_find_contact("Dav"); assert_string_equals("Dave", result); @@ -358,9 +264,9 @@ static void find_second_exists(void) static void find_third_exists(void) { - contact_list_add("James", NULL, NULL); - contact_list_add("Dave", NULL, NULL); - contact_list_add("Bob", NULL, NULL); + contact_list_add("James", NULL, NULL, NULL, NULL); + contact_list_add("Dave", NULL, NULL, NULL, NULL); + contact_list_add("Bob", NULL, NULL, NULL, NULL); char *result = contact_list_find_contact("Ja"); assert_string_equals("James", result); @@ -369,9 +275,9 @@ static void find_third_exists(void) static void find_returns_null(void) { - contact_list_add("James", NULL, NULL); - contact_list_add("Dave", NULL, NULL); - contact_list_add("Bob", NULL, NULL); + contact_list_add("James", NULL, NULL, NULL, NULL); + contact_list_add("Dave", NULL, NULL, NULL, NULL); + contact_list_add("Bob", NULL, NULL, NULL, NULL); char *result = contact_list_find_contact("Mike"); assert_is_null(result); @@ -385,9 +291,9 @@ static void find_on_empty_returns_null(void) static void find_twice_returns_second_when_two_match(void) { - contact_list_add("James", NULL, NULL); - contact_list_add("Jamie", NULL, NULL); - contact_list_add("Bob", NULL, NULL); + contact_list_add("James", NULL, NULL, NULL, NULL); + contact_list_add("Jamie", NULL, NULL, NULL, NULL); + contact_list_add("Bob", NULL, NULL, NULL, NULL); char *result1 = contact_list_find_contact("Jam"); char *result2 = contact_list_find_contact(result1); @@ -398,16 +304,16 @@ static void find_twice_returns_second_when_two_match(void) static void find_five_times_finds_fifth(void) { - contact_list_add("Jama", NULL, NULL); - contact_list_add("Jamb", NULL, NULL); - contact_list_add("Mike", NULL, NULL); - contact_list_add("Dave", NULL, NULL); - contact_list_add("Jamm", NULL, NULL); - contact_list_add("Jamn", NULL, NULL); - contact_list_add("Matt", NULL, NULL); - contact_list_add("Jamo", NULL, NULL); - contact_list_add("Jamy", NULL, NULL); - contact_list_add("Jamz", NULL, NULL); + contact_list_add("Jama", NULL, NULL, NULL, NULL); + contact_list_add("Jamb", NULL, NULL, NULL, NULL); + contact_list_add("Mike", NULL, NULL, NULL, NULL); + contact_list_add("Dave", NULL, NULL, NULL, NULL); + contact_list_add("Jamm", NULL, NULL, NULL, NULL); + contact_list_add("Jamn", NULL, NULL, NULL, NULL); + contact_list_add("Matt", NULL, NULL, NULL, NULL); + contact_list_add("Jamo", NULL, NULL, NULL, NULL); + contact_list_add("Jamy", NULL, NULL, NULL, NULL); + contact_list_add("Jamz", NULL, NULL, NULL, NULL); char *result1 = contact_list_find_contact("Jam"); char *result2 = contact_list_find_contact(result1); @@ -424,9 +330,9 @@ static void find_five_times_finds_fifth(void) static void find_twice_returns_first_when_two_match_and_reset(void) { - contact_list_add("James", NULL, NULL); - contact_list_add("Jamie", NULL, NULL); - contact_list_add("Bob", NULL, NULL); + contact_list_add("James", NULL, NULL, NULL, NULL); + contact_list_add("Jamie", NULL, NULL, NULL, NULL); + contact_list_add("Bob", NULL, NULL, NULL, NULL); char *result1 = contact_list_find_contact("Jam"); contact_list_reset_search_attempts(); @@ -436,24 +342,6 @@ static void find_twice_returns_first_when_two_match_and_reset(void) free(result2); } -static void removed_contact_not_in_search(void) -{ - contact_list_add("Jamatron", NULL, NULL); - contact_list_add("Bob", NULL, NULL); - contact_list_add("Jambo", NULL, NULL); - contact_list_add("James", NULL, NULL); - contact_list_add("Jamie", NULL, NULL); - - char *result1 = contact_list_find_contact("Jam"); // Jamatron - char *result2 = contact_list_find_contact(result1); // Jambo - contact_list_remove("James"); - char *result3 = contact_list_find_contact(result2); - assert_string_equals("Jamie", result3); - free(result1); - free(result2); - free(result3); -} - void register_contact_list_tests(void) { TEST_MODULE("contact_list tests"); @@ -470,13 +358,6 @@ void register_contact_list_tests(void) TEST(add_twice_at_beginning_adds_once); TEST(add_twice_in_middle_adds_once); TEST(add_twice_at_end_adds_once); - TEST(remove_when_none_does_nothing); - TEST(remove_when_one_removes); - TEST(remove_first_when_two); - TEST(remove_second_when_two); - TEST(remove_first_when_three); - TEST(remove_second_when_three); - TEST(remove_third_when_three); TEST(test_show_when_value); TEST(test_show_online_when_no_value); TEST(test_show_online_when_empty_string); @@ -493,6 +374,5 @@ void register_contact_list_tests(void) TEST(find_on_empty_returns_null); TEST(find_twice_returns_second_when_two_match); TEST(find_twice_returns_first_when_two_match_and_reset); - TEST(removed_contact_not_in_search); TEST(find_five_times_finds_fifth); } diff --git a/tests/test_prof_autocomplete.c b/tests/test_prof_autocomplete.c index 895a4a44..b61c9cf6 100644 --- a/tests/test_prof_autocomplete.c +++ b/tests/test_prof_autocomplete.c @@ -13,16 +13,6 @@ static void clear_empty(void) p_autocomplete_clear(ac); } -static void clear_empty_with_free_func(void) -{ - PAutocomplete ac = - p_obj_autocomplete_new((PStrFunc)p_contact_name, - (PCopyFunc)p_contact_copy, - (PEqualDeepFunc)p_contacts_equal_deep, - (GDestroyNotify)p_contact_free); - p_autocomplete_clear(ac); -} - static void reset_after_create(void) { PAutocomplete ac = p_autocomplete_new(); @@ -47,20 +37,6 @@ static void get_after_create_returns_null(void) p_autocomplete_clear(ac); } -static void get_after_create_with_copy_func_returns_null(void) -{ - PAutocomplete ac = - p_obj_autocomplete_new((PStrFunc)p_contact_name, - (PCopyFunc)p_contact_copy, - (PEqualDeepFunc)p_contacts_equal_deep, - (GDestroyNotify)p_contact_free); - GSList *result = p_autocomplete_get_list(ac); - - assert_is_null(result); - - p_autocomplete_clear(ac); -} - static void add_one_and_complete(void) { char *item = strdup("Hello"); @@ -73,22 +49,6 @@ static void add_one_and_complete(void) p_autocomplete_clear(ac); } -static void add_one_and_complete_with_funcs(void) -{ - PContact contact = p_contact_new("James", "Online", "I'm here"); - PAutocomplete ac = - p_obj_autocomplete_new((PStrFunc)p_contact_name, - (PCopyFunc)p_contact_copy, - (PEqualDeepFunc)p_contacts_equal_deep, - (GDestroyNotify)p_contact_free); - p_autocomplete_add(ac, contact); - char *result = p_autocomplete_complete(ac, "Jam"); - - assert_string_equals("James", result); - - p_autocomplete_clear(ac); -} - static void add_two_and_complete_returns_first(void) { char *item1 = strdup("Hello"); @@ -103,24 +63,6 @@ static void add_two_and_complete_returns_first(void) p_autocomplete_clear(ac); } -static void add_two_and_complete_returns_first_with_funcs(void) -{ - PContact contact1 = p_contact_new("James", "Online", "I'm here"); - PContact contact2 = p_contact_new("Jamie", "Away", "Out to lunch"); - PAutocomplete ac = - p_obj_autocomplete_new((PStrFunc)p_contact_name, - (PCopyFunc)p_contact_copy, - (PEqualDeepFunc)p_contacts_equal_deep, - (GDestroyNotify)p_contact_free); - p_autocomplete_add(ac, contact1); - p_autocomplete_add(ac, contact2); - char *result = p_autocomplete_complete(ac, "Jam"); - - assert_string_equals("James", result); - - p_autocomplete_clear(ac); -} - static void add_two_and_complete_returns_second(void) { char *item1 = strdup("Hello"); @@ -136,25 +78,6 @@ static void add_two_and_complete_returns_second(void) p_autocomplete_clear(ac); } -static void add_two_and_complete_returns_second_with_funcs(void) -{ - PContact contact1 = p_contact_new("James", "Online", "I'm here"); - PContact contact2 = p_contact_new("Jamie", "Away", "Out to lunch"); - PAutocomplete ac = - p_obj_autocomplete_new((PStrFunc)p_contact_name, - (PCopyFunc)p_contact_copy, - (PEqualDeepFunc)p_contacts_equal_deep, - (GDestroyNotify)p_contact_free); - p_autocomplete_add(ac, contact1); - p_autocomplete_add(ac, contact2); - char *result1 = p_autocomplete_complete(ac, "Jam"); - char *result2 = p_autocomplete_complete(ac, result1); - - assert_string_equals("Jamie", result2); - - p_autocomplete_clear(ac); -} - static void add_two_adds_two(void) { char *item1 = strdup("Hello"); @@ -169,24 +92,6 @@ static void add_two_adds_two(void) p_autocomplete_clear(ac); } -static void add_two_adds_two_with_funcs(void) -{ - PContact contact1 = p_contact_new("James", "Online", "I'm here"); - PContact contact2 = p_contact_new("Jamie", "Away", "Out to lunch"); - PAutocomplete ac = - p_obj_autocomplete_new((PStrFunc)p_contact_name, - (PCopyFunc)p_contact_copy, - (PEqualDeepFunc)p_contacts_equal_deep, - (GDestroyNotify)p_contact_free); - p_autocomplete_add(ac, contact1); - p_autocomplete_add(ac, contact2); - GSList *result = p_autocomplete_get_list(ac); - - assert_int_equals(2, g_slist_length(result)); - - p_autocomplete_clear(ac); -} - static void add_two_same_adds_one(void) { char *item1 = strdup("Hello"); @@ -201,24 +106,6 @@ static void add_two_same_adds_one(void) p_autocomplete_clear(ac); } -static void add_two_same_adds_one_with_funcs(void) -{ - PContact contact1 = p_contact_new("James", "Online", "I'm here"); - PContact contact2 = p_contact_new("James", "Away", "Out to lunch"); - PAutocomplete ac = - p_obj_autocomplete_new((PStrFunc)p_contact_name, - (PCopyFunc)p_contact_copy, - (PEqualDeepFunc)p_contacts_equal_deep, - (GDestroyNotify)p_contact_free); - p_autocomplete_add(ac, contact1); - p_autocomplete_add(ac, contact2); - GSList *result = p_autocomplete_get_list(ac); - - assert_int_equals(1, g_slist_length(result)); - - p_autocomplete_clear(ac); -} - static void add_two_same_updates(void) { char *item1 = strdup("Hello"); @@ -237,29 +124,6 @@ static void add_two_same_updates(void) p_autocomplete_clear(ac); } -static void add_two_same_updates_with_funcs(void) -{ - PContact contact1 = p_contact_new("James", "Online", "I'm here"); - PContact contact2 = p_contact_new("James", "Away", "Out to lunch"); - PAutocomplete ac = - p_obj_autocomplete_new((PStrFunc)p_contact_name, - (PCopyFunc)p_contact_copy, - (PEqualDeepFunc)p_contacts_equal_deep, - (GDestroyNotify)p_contact_free); - p_autocomplete_add(ac, contact1); - p_autocomplete_add(ac, contact2); - GSList *result = p_autocomplete_get_list(ac); - - GSList *first = g_slist_nth(result, 0); - PContact contact = first->data; - - assert_string_equals("James", p_contact_name(contact)); - assert_string_equals("Away", p_contact_show(contact)); - assert_string_equals("Out to lunch", p_contact_status(contact)); - - p_autocomplete_clear(ac); -} - static void add_one_returns_true(void) { char *item = strdup("Hello"); @@ -271,21 +135,6 @@ static void add_one_returns_true(void) p_autocomplete_clear(ac); } -static void add_one_returns_true_with_funcs(void) -{ - PContact contact = p_contact_new("James", "Online", "I'm here"); - PAutocomplete ac = - p_obj_autocomplete_new((PStrFunc)p_contact_name, - (PCopyFunc)p_contact_copy, - (PEqualDeepFunc)p_contacts_equal_deep, - (GDestroyNotify)p_contact_free); - int result = p_autocomplete_add(ac, contact); - - assert_true(result); - - p_autocomplete_clear(ac); -} - static void add_two_different_returns_true(void) { char *item1 = strdup("Hello"); @@ -300,24 +149,6 @@ static void add_two_different_returns_true(void) p_autocomplete_clear(ac); } -static void add_two_different_returns_true_with_funcs(void) -{ - PContact contact1 = p_contact_new("James", "Online", "I'm here"); - PContact contact2 = p_contact_new("JamesB", "Away", "Out to lunch"); - PAutocomplete ac = - p_obj_autocomplete_new((PStrFunc)p_contact_name, - (PCopyFunc)p_contact_copy, - (PEqualDeepFunc)p_contacts_equal_deep, - (GDestroyNotify)p_contact_free); - int result1 = p_autocomplete_add(ac, contact1); - int result2 = p_autocomplete_add(ac, contact2); - - assert_true(result1); - assert_true(result2); - - p_autocomplete_clear(ac); -} - static void add_two_same_returns_false(void) { char *item1 = strdup("Hello"); @@ -332,68 +163,20 @@ static void add_two_same_returns_false(void) p_autocomplete_clear(ac); } -static void add_two_same_returns_false_with_funcs(void) -{ - PContact contact1 = p_contact_new("James", "Online", "I'm here"); - PContact contact2 = p_contact_new("James", "Online", "I'm here"); - PAutocomplete ac = - p_obj_autocomplete_new((PStrFunc)p_contact_name, - (PCopyFunc)p_contact_copy, - (PEqualDeepFunc)p_contacts_equal_deep, - (GDestroyNotify)p_contact_free); - int result1 = p_autocomplete_add(ac, contact1); - int result2 = p_autocomplete_add(ac, contact2); - - assert_true(result1); - assert_false(result2); - - p_autocomplete_clear(ac); -} - -static void add_two_same_different_data_returns_true(void) -{ - PContact contact1 = p_contact_new("James", "Online", "I'm here"); - PContact contact2 = p_contact_new("James", "Away", "I'm not here right now"); - PAutocomplete ac = - p_obj_autocomplete_new((PStrFunc)p_contact_name, - (PCopyFunc)p_contact_copy, - (PEqualDeepFunc)p_contacts_equal_deep, - (GDestroyNotify)p_contact_free); - int result1 = p_autocomplete_add(ac, contact1); - int result2 = p_autocomplete_add(ac, contact2); - - assert_true(result1); - assert_true(result2); - - p_autocomplete_clear(ac); -} - void register_prof_autocomplete_tests(void) { TEST_MODULE("prof_autocomplete tests"); TEST(clear_empty); - TEST(clear_empty_with_free_func); TEST(reset_after_create); TEST(find_after_create); TEST(get_after_create_returns_null); - TEST(get_after_create_with_copy_func_returns_null); TEST(add_one_and_complete); - TEST(add_one_and_complete_with_funcs); TEST(add_two_and_complete_returns_first); - TEST(add_two_and_complete_returns_first_with_funcs); TEST(add_two_and_complete_returns_second); - TEST(add_two_and_complete_returns_second_with_funcs); TEST(add_two_adds_two); - TEST(add_two_adds_two_with_funcs); TEST(add_two_same_adds_one); - TEST(add_two_same_adds_one_with_funcs); TEST(add_two_same_updates); - TEST(add_two_same_updates_with_funcs); TEST(add_one_returns_true); - TEST(add_one_returns_true_with_funcs); TEST(add_two_different_returns_true); - TEST(add_two_different_returns_true_with_funcs); TEST(add_two_same_returns_false); - TEST(add_two_same_returns_false_with_funcs); - TEST(add_two_same_different_data_returns_true); }