aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordequis <dx@dxzone.com.ar>2014-07-24 07:41:47 -0300
committerdequis <dx@dxzone.com.ar>2015-05-28 01:10:55 -0300
commit3d31618b5f50552b71d8c6f1b3fa733a212ee89c (patch)
tree84dffdab1c8f7f5a69f1c5568ea222891e75fdf6
parent24f113b01e1117ab031a1ede6d418030fc69d63d (diff)
jabber: Refactor conference message handling
- Improve handling of "unknown 'from'" - Try a bit harder to detect the source of the message, and fall back to messages sent from a fake temporary user. - Fix receiving topic when it was set by someone who left the room. - Add jabber_get_bare_jid() utility function
-rw-r--r--protocols/jabber/conference.c120
-rw-r--r--protocols/jabber/jabber.h1
-rw-r--r--protocols/jabber/jabber_util.c16
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);
+ }
+}