diff --git a/src/command.c b/src/command.c index 82374b3a..01b01588 100644 --- a/src/command.c +++ b/src/command.c @@ -36,6 +36,7 @@ #include "chat_log.h" #include "history.h" #include "jabber.h" +#include "jid.h" #include "log.h" #include "parser.h" #include "preferences.h" @@ -1592,34 +1593,37 @@ _cmd_info(gchar **args, struct cmd_help_t help) static gboolean _cmd_join(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 currently connected."); + return TRUE; + } + + if (ui_windows_full()) { + cons_bad_show("Windows all used, close a window and try again."); + return TRUE; + } + char *room = args[0]; char *nick = NULL; int num_args = g_strv_length(args); if (num_args == 2) { nick = args[1]; - } - - jabber_conn_status_t conn_status = jabber_get_connection_status(); - - if (conn_status != JABBER_CONNECTED) { - cons_show("You are not currently connected."); - } else if (ui_windows_full()) { - cons_bad_show("Windows all used, close a window and try again."); } else { - // if no nick, set to first part of jid - if (nick == NULL) { - const char *jid = jabber_get_jid(); - char jid_cpy[strlen(jid) + 1]; - strcpy(jid_cpy, jid); - nick = strdup(strtok(jid_cpy, "@")); - } - if (!muc_room_is_active(room)) { - jabber_join(room, nick); - } - win_join_chat(room, nick); + Jid *jid = jid_create(jabber_get_jid()); + nick = strdup(jid->localpart); + jid_destroy(jid); } + Jid *room_jid = jid_create_room_jid(room, nick); + + if (!muc_room_is_active(room_jid)) { + jabber_join(room_jid); + } + win_join_chat(room_jid); + return TRUE; } diff --git a/src/jabber.c b/src/jabber.c index f65deb93..9ae9de9e 100644 --- a/src/jabber.c +++ b/src/jabber.c @@ -313,17 +313,14 @@ jabber_get_subscription_requests(void) } void -jabber_join(const char * const room, const char * const nick) +jabber_join(Jid *jid) { - char *full_room_jid = create_full_room_jid(room, nick); xmpp_stanza_t *presence = stanza_create_room_join_presence(jabber_conn.ctx, - full_room_jid); + jid->fulljid); xmpp_send(jabber_conn.conn, presence); xmpp_stanza_release(presence); - muc_join_room(room, nick); - - free(full_room_jid); + muc_join_room(jid->barejid, jid->resourcepart); } void @@ -563,18 +560,16 @@ _groupchat_message_handler(xmpp_stanza_t * const stanza) } } - // room jid not of form room/nick - if (!parse_room_jid(room_jid, &room, &nick)) { - log_error("Could not parse room jid: %s", room_jid); + Jid *jid = jid_create(room_jid); + + if (!jid_is_valid_room_form(jid)) { + log_error("Invalid room JID: %s", jid->str); return 1; } - + // room not active in profanity - if (!muc_room_is_active(room_jid)) { - log_error("Message recieved for inactive groupchat: %s", room_jid); - free(room); - free(nick); - + if (!muc_room_is_active(jid)) { + log_error("Message recieved for inactive chat room: %s", jid->str); return 1; } @@ -641,72 +636,80 @@ _error_handler(xmpp_stanza_t * const stanza) static int _chat_message_handler(xmpp_stanza_t * const stanza) { - gboolean priv = FALSE; gchar *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM); - - char from_cpy[strlen(from) + 1]; - strcpy(from_cpy, from); - char *short_from = strtok(from_cpy, "/"); - char *jid = NULL; + Jid *jid = jid_create(from); // private message from chat room use full jid (room/nick) - if (muc_room_is_active(short_from)) { - jid = strdup(from); - priv = TRUE; + if (muc_room_is_active(jid)) { + // determine if the notifications happened whilst offline + GTimeVal tv_stamp; + gboolean delayed = stanza_get_delay(stanza, &tv_stamp); + + // check for and deal with message + xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY); + if (body != NULL) { + char *message = xmpp_stanza_get_text(body); + if (delayed) { + prof_handle_delayed_message(jid->str, message, tv_stamp, TRUE); + } else { + prof_handle_incoming_message(jid->str, message, TRUE); + } + } + + free(jid); + return 1; + // standard chat message, use jid without resource } else { - jid = strdup(short_from); - priv = FALSE; - } - - // determine chatstate support of recipient - gboolean recipient_supports = FALSE; - if (stanza_contains_chat_state(stanza)) { - recipient_supports = TRUE; - } - - // create or update chat session - if (!chat_session_exists(jid)) { - chat_session_start(jid, recipient_supports); - } else { - chat_session_set_recipient_supports(jid, recipient_supports); - } - - // determine if the notifications happened whilst offline - GTimeVal tv_stamp; - gboolean delayed = stanza_get_delay(stanza, &tv_stamp); - - // deal with chat states if recipient supports them - if (recipient_supports && (!delayed)) { - if (xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_COMPOSING) != NULL) { - if (prefs_get_notify_typing() || prefs_get_intype()) { - prof_handle_typing(jid); - } - } else if (xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_GONE) != NULL) { - prof_handle_gone(jid); - } else if (xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_PAUSED) != NULL) { - // do something - } else if (xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_INACTIVE) != NULL) { - // do something - } else { // handle - // do something + // determine chatstate support of recipient + gboolean recipient_supports = FALSE; + if (stanza_contains_chat_state(stanza)) { + recipient_supports = TRUE; } - } - // check for and deal with message - xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY); - if (body != NULL) { - char *message = xmpp_stanza_get_text(body); - if (delayed) { - prof_handle_delayed_message(jid, message, tv_stamp, priv); + // create or update chat session + if (!chat_session_exists(jid->barejid)) { + chat_session_start(jid->barejid, recipient_supports); } else { - prof_handle_incoming_message(jid, message, priv); + chat_session_set_recipient_supports(jid->barejid, recipient_supports); } + + // determine if the notifications happened whilst offline + GTimeVal tv_stamp; + gboolean delayed = stanza_get_delay(stanza, &tv_stamp); + + // deal with chat states if recipient supports them + if (recipient_supports && (!delayed)) { + if (xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_COMPOSING) != NULL) { + if (prefs_get_notify_typing() || prefs_get_intype()) { + prof_handle_typing(jid->barejid); + } + } else if (xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_GONE) != NULL) { + prof_handle_gone(jid->barejid); + } else if (xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_PAUSED) != NULL) { + // do something + } else if (xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_INACTIVE) != NULL) { + // do something + } else { // handle + // do something + } + } + + // check for and deal with message + xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY); + if (body != NULL) { + char *message = xmpp_stanza_get_text(body); + if (delayed) { + prof_handle_delayed_message(jid->barejid, message, tv_stamp, FALSE); + } else { + prof_handle_incoming_message(jid->barejid, message, FALSE); + } + } + + free(jid); + return 1; } - free(jid); - - return 1; } static void @@ -1029,24 +1032,22 @@ _presence_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata) { const char *jid = xmpp_conn_get_jid(jabber_conn.conn); - char jid_cpy[strlen(jid) + 1]; - strcpy(jid_cpy, jid); - char *short_jid = strtok(jid_cpy, "/"); - char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM); char *type = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_TYPE); + + Jid *my_jid = jid_create(jid); + Jid *from_jid = jid_create(from); if ((type != NULL) && (strcmp(type, STANZA_TYPE_ERROR) == 0)) { return _error_handler(stanza); } // handle chat room presence - if (muc_room_is_active(from)) { - return _room_presence_handler(from, stanza); + if (muc_room_is_active(from_jid)) { + return _room_presence_handler(from_jid->str, stanza); // handle regular presence } else { - char *short_from = strtok(from, "/"); char *type = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_TYPE); char *show_str, *status_str; int idle_seconds = stanza_get_idle_time(stanza); @@ -1071,12 +1072,12 @@ _presence_handler(xmpp_conn_t * const conn, else show_str = "online"; - if (strcmp(short_jid, short_from) !=0) { - prof_handle_contact_online(short_from, show_str, status_str, last_activity); + if (strcmp(my_jid->barejid, from_jid->barejid) !=0) { + prof_handle_contact_online(from_jid->barejid, show_str, status_str, last_activity); } } else if (strcmp(type, STANZA_TYPE_UNAVAILABLE) == 0) { - if (strcmp(short_jid, short_from) !=0) { - prof_handle_contact_offline(short_from, "offline", status_str); + if (strcmp(my_jid->barejid, from_jid->barejid) !=0) { + prof_handle_contact_offline(from_jid->barejid, "offline", status_str); } if (last_activity != NULL) { @@ -1085,14 +1086,14 @@ _presence_handler(xmpp_conn_t * const conn, // subscriptions } else if (strcmp(type, STANZA_TYPE_SUBSCRIBE) == 0) { - prof_handle_subscription(short_from, PRESENCE_SUBSCRIBE); - g_hash_table_insert(sub_requests, strdup(short_from), strdup(short_from)); + prof_handle_subscription(from_jid->barejid, PRESENCE_SUBSCRIBE); + g_hash_table_insert(sub_requests, strdup(from_jid->barejid), strdup(from_jid->barejid)); } else if (strcmp(type, STANZA_TYPE_SUBSCRIBED) == 0) { - prof_handle_subscription(short_from, PRESENCE_SUBSCRIBED); - g_hash_table_remove(sub_requests, short_from); + prof_handle_subscription(from_jid->barejid, PRESENCE_SUBSCRIBED); + g_hash_table_remove(sub_requests, from_jid->barejid); } else if (strcmp(type, STANZA_TYPE_UNSUBSCRIBED) == 0) { - prof_handle_subscription(short_from, PRESENCE_UNSUBSCRIBED); - g_hash_table_remove(sub_requests, short_from); + prof_handle_subscription(from_jid->barejid, PRESENCE_UNSUBSCRIBED); + g_hash_table_remove(sub_requests, from_jid->barejid); } else { /* unknown type */ log_debug("Received presence with unknown type '%s'", type); } diff --git a/src/jabber.h b/src/jabber.h index 326328cc..e1494851 100644 --- a/src/jabber.h +++ b/src/jabber.h @@ -24,6 +24,7 @@ #define JABBER_H #include "accounts.h" +#include "jid.h" typedef enum { JABBER_UNDEFINED, @@ -59,7 +60,7 @@ jabber_conn_status_t jabber_connect_with_account(ProfAccount *account, const char * const passwd); void jabber_disconnect(void); void jabber_process_events(void); -void jabber_join(const char * const room, const char * const nick); +void jabber_join(Jid *jid); void jabber_change_room_nick(const char * const room, const char * const nick); void jabber_leave_chat_room(const char * const room_jid); void jabber_subscription(const char * const jid, jabber_subscr_t action); diff --git a/src/jid.c b/src/jid.c index 7955b98c..8f98d211 100644 --- a/src/jid.c +++ b/src/jid.c @@ -55,6 +55,7 @@ jid_create(const gchar * const str) // has resourcepart if (slashp != NULL) { result = malloc(sizeof(struct jid_t)); + result->str = strdup(trimmed); result->resourcepart = g_strdup(slashp + 1); result->barejid = g_strndup(trimmed, strlen(trimmed) - strlen(result->resourcepart) - 1); result->fulljid = g_strdup(trimmed); @@ -78,6 +79,7 @@ jid_create(const gchar * const str) // no resourcepart } else { result = malloc(sizeof(struct jid_t)); + result->str = strdup(trimmed); result->resourcepart = NULL; result->barejid = g_strdup(trimmed); result->fulljid = NULL; @@ -114,6 +116,7 @@ jid_create_room_jid(const char * const room, const char * const nick) void jid_destroy(Jid *jid) { + FREE_SET_NULL(jid->str); FREE_SET_NULL(jid->localpart); FREE_SET_NULL(jid->domainpart); FREE_SET_NULL(jid->resourcepart); @@ -122,6 +125,12 @@ jid_destroy(Jid *jid) FREE_SET_NULL(jid); } +gboolean +jid_is_valid_room_form(Jid *jid) +{ + return (jid->fulljid != NULL); +} + /* * Given a full room JID of the form * room@server/nick diff --git a/src/jid.h b/src/jid.h index 5a34c02e..ab44090c 100644 --- a/src/jid.h +++ b/src/jid.h @@ -26,6 +26,7 @@ #include struct jid_t { + char *str; char *localpart; char *domainpart; char *resourcepart; @@ -37,7 +38,9 @@ typedef struct jid_t Jid; Jid * jid_create(const gchar * const str); Jid * jid_create_room_jid(const char * const room, const char * const nick); +void jid_destroy(Jid *jid); +gboolean jid_is_valid_room_form(Jid *jid); gboolean jid_is_room(const char * const room_jid); char * create_full_room_jid(const char * const room, const char * const nick); diff --git a/src/muc.c b/src/muc.c index 344df588..67c38ee5 100644 --- a/src/muc.c +++ b/src/muc.c @@ -26,10 +26,10 @@ #include #include "contact.h" +#include "jid.h" #include "prof_autocomplete.h" typedef struct _muc_room_t { - char *room; // e.g. test@conference.server char *nick; // e.g. Some User char *subject; @@ -82,13 +82,10 @@ muc_leave_room(const char * const room) * Returns TRUE if the user is currently in the room */ gboolean -muc_room_is_active(const char * const full_room_jid) +muc_room_is_active(Jid *jid) { - char **tokens = g_strsplit(full_room_jid, "/", 0); - char *room_part = tokens[0]; - if (rooms != NULL) { - ChatRoom *chat_room = g_hash_table_lookup(rooms, room_part); + ChatRoom *chat_room = g_hash_table_lookup(rooms, jid->barejid); if (chat_room != NULL) { return TRUE; diff --git a/src/muc.h b/src/muc.h index 0cabd9b8..b0722e96 100644 --- a/src/muc.h +++ b/src/muc.h @@ -29,7 +29,7 @@ void muc_join_room(const char * const room, const char * const nick); void muc_leave_room(const char * const room); -gboolean muc_room_is_active(const char * const full_room_jid); +gboolean muc_room_is_active(Jid *jid); GList* muc_get_active_room_list(void); char * muc_get_room_nick(const char * const room); diff --git a/src/ui.h b/src/ui.h index fcf4f5d6..223b6a0c 100644 --- a/src/ui.h +++ b/src/ui.h @@ -36,6 +36,7 @@ #endif #include "jabber.h" +#include "jid.h" #define INP_WIN_MAX 1000 #define PAD_SIZE 1000 @@ -113,7 +114,7 @@ void win_show_outgoing_msg(const char * const from, const char * const to, const char * const message); void win_new_chat_win(const char * const to); -void win_join_chat(const char * const room, const char * const nick); +void win_join_chat(Jid *jid); void win_show_room_roster(const char * const room); void win_show_room_history(const char * const room_jid, const char * const nick, GTimeVal tv_stamp, const char * const message); diff --git a/src/windows.c b/src/windows.c index ccba1631..28b63c74 100644 --- a/src/windows.c +++ b/src/windows.c @@ -753,13 +753,16 @@ win_show_outgoing_msg(const char * const from, const char * const to, // create new window if (win_index == NUM_WINS) { + Jid *jid = jid_create(to); - if (muc_room_is_active(to)) { + if (muc_room_is_active(jid)) { win_index = _new_prof_win(to, WIN_PRIVATE); } else { win_index = _new_prof_win(to, WIN_CHAT); } + jid_destroy(jid); + win = windows[win_index]->win; if (prefs_get_chlog() && prefs_get_history()) { @@ -794,13 +797,13 @@ win_show_outgoing_msg(const char * const from, const char * const to, } void -win_join_chat(const char * const room, const char * const nick) +win_join_chat(Jid *jid) { - int win_index = _find_prof_win_index(room); + int win_index = _find_prof_win_index(jid->barejid); // create new window if (win_index == NUM_WINS) { - win_index = _new_prof_win(room, WIN_MUC); + win_index = _new_prof_win(jid->barejid, WIN_MUC); } ui_switch_win(win_index);