diff options
-rw-r--r-- | protocols/jabber/conference.c | 120 | ||||
-rw-r--r-- | protocols/jabber/jabber.h | 1 | ||||
-rw-r--r-- | protocols/jabber/jabber_util.c | 16 |
3 files changed, 82 insertions, 55 deletions
diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index bcf05b3c..be63e115 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -353,78 +353,88 @@ void jabber_chat_pkt_message(struct im_connection *ic, struct jabber_buddy *bud, { struct xt_node *subject = xt_find_node(node->children, "subject"); struct xt_node *body = xt_find_node(node->children, "body"); - struct groupchat *chat = bud ? jabber_chat_by_jid(ic, bud->bare_jid) : NULL; - struct jabber_chat *jc = chat ? chat->data : NULL; - char *s; + struct groupchat *chat = NULL; + struct jabber_chat *jc = NULL; + char *from = NULL; + char *nick = NULL; + char *final_from = NULL; + char *bare_jid = NULL; - if (subject && chat) { - s = (bud && bud->ext_jid) ? strchr(bud->ext_jid, '/') : NULL; - if (s) { - *s = 0; + from = (bud) ? bud->full_jid : xt_find_attr(node, "from"); + + if (from) { + nick = strchr(from, '/'); + if (nick) { + *nick = 0; } - imcb_chat_topic(chat, bud ? bud->ext_jid : NULL, subject->text_len > 0 ? - subject->text : NULL, jabber_get_timestamp(node)); - if (s) { - *s = '/'; + chat = jabber_chat_by_jid(ic, from); + if (nick) { + *nick = '/'; + nick++; } } - if (bud == NULL || (jc && ~jc->flags & JCFLAG_MESSAGE_SENT && bud == jc->me)) { - char *nick; + jc = (chat) ? chat->data : NULL; - if (body == NULL || body->text_len == 0) { - /* Meh. Empty messages aren't very interesting, no matter - how much some servers love to send them. */ - return; + if (!bud) { + struct xt_node *c; + char *s; + + /* Try some clever stuff to find out the real JID here */ + c = xt_find_node_by_attr(node->children, "delay", "xmlns", XMLNS_DELAY); + + if (c && ((s = xt_find_attr(c, "from")) || + (s = xt_find_attr(c, "from_jid")))) { + /* This won't be useful if it's the MUC JID */ + if (!(jc && jabber_compare_jid(s, jc->name))) { + /* Hopefully this one makes more sense! */ + bud = jabber_buddy_by_jid(ic, s, GET_BUDDY_FIRST | GET_BUDDY_CREAT); + } } - s = xt_find_attr(node, "from"); /* pkt_message() already NULL-checked this one. */ - nick = strchr(s, '/'); - if (nick) { - /* If this message included a resource/nick we don't know, - we might still know the groupchat itself. */ - *nick = 0; - chat = jabber_chat_by_jid(ic, s); - *nick = '/'; + } - nick++; - } else { - /* message.c uses the EXACT_JID option, so bud should - always be NULL here for bare JIDs. */ - chat = jabber_chat_by_jid(ic, s); + if (subject && chat) { + char *subject_text = subject->text_len > 0 ? subject->text : NULL; + if (g_strcmp0(chat->topic, subject_text) != 0) { + bare_jid = (bud) ? jabber_get_bare_jid(bud->ext_jid) : NULL; + imcb_chat_topic(chat, bare_jid, subject_text, + jabber_get_timestamp(node)); + g_free(bare_jid); } + } + if (body == NULL || body->text_len == 0) { + /* Meh. Empty messages aren't very interesting, no matter + how much some servers love to send them. */ + return; + } + + if (chat == NULL) { if (nick == NULL) { - /* This is fine, the groupchat itself isn't in jd->buddies. */ - if (chat) { - imcb_chat_log(chat, "From conference server: %s", body->text); - } else { - imcb_log(ic, "System message from unknown groupchat %s: %s", s, body->text); - } + imcb_log(ic, "System message from unknown groupchat %s: %s", from, body->text); } else { - /* This can happen too, at least when receiving a backlog when - just joining a channel. */ - if (chat) { - imcb_chat_log(chat, "Message from unknown participant %s: %s", nick, body->text); - } else { - imcb_log(ic, "Groupchat message from unknown JID %s: %s", s, body->text); - } + imcb_log(ic, "Groupchat message from unknown JID %s: %s", from, body->text); } return; - } else if (chat == NULL) { - /* How could this happen?? We could do kill( self, 11 ) - now or just wait for the OS to do it. :-) */ + } else if (chat != NULL && bud == NULL && nick == NULL) { + imcb_chat_log(chat, "From conference server: %s", body->text); + return; + } else if (jc && jc->flags & JCFLAG_MESSAGE_SENT && bud == jc->me) { + /* exclude self-messages since they would get filtered out + * but not the ones in the backlog */ return; } - if (body && body->text_len > 0) { - s = (bud->ext_jid) ? strchr(bud->ext_jid, '/') : NULL; - if (s) { - *s = 0; - } - imcb_chat_msg(chat, bud->ext_jid, body->text, 0, jabber_get_timestamp(node)); - if (s) { - *s = '/'; - } + + if (bud && jc && bud != jc->me) { + bare_jid = jabber_get_bare_jid(bud->ext_jid ? bud->ext_jid : bud->full_jid); + final_from = bare_jid; + } else { + final_from = nick; } + + imcb_chat_msg(chat, final_from, body->text, 0, jabber_get_timestamp(node)); + + g_free(bare_jid); } diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 8416e1a7..b8ef8b08 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -311,6 +311,7 @@ time_t jabber_get_timestamp(struct xt_node *xt); struct jabber_error *jabber_error_parse(struct xt_node *node, char *xmlns); void jabber_error_free(struct jabber_error *err); gboolean jabber_set_me(struct im_connection *ic, const char *me); +char *jabber_get_bare_jid(char *jid); extern const struct jabber_away_state jabber_away_state_list[]; diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 779d502b..38daaa26 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -819,3 +819,19 @@ gboolean jabber_set_me(struct im_connection *ic, const char *me) return TRUE; } + +/* Returns new reference! g_free() afterwards. */ +char *jabber_get_bare_jid(char *jid) +{ + char *s = NULL; + + if (jid == NULL) { + return NULL; + } + + if ((s = strchr(jid, '/'))) { + return g_strndup(jid, s - jid); + } else { + return g_strdup(jid); + } +} |