Lines 58-64
Link Here
|
58 |
|
58 |
|
59 |
static void handle_chat(JabberMessage *jm) |
59 |
static void handle_chat(JabberMessage *jm) |
60 |
{ |
60 |
{ |
61 |
JabberID *jid = jabber_id_new(jm->from); |
61 |
gchar *contact = jm->outgoing ? jm->to : jm->from; |
|
|
62 |
JabberID *jid = jabber_id_new(contact); |
62 |
|
63 |
|
63 |
PurpleConnection *gc; |
64 |
PurpleConnection *gc; |
64 |
PurpleAccount *account; |
65 |
PurpleAccount *account; |
Lines 71-118
Link Here
|
71 |
gc = jm->js->gc; |
72 |
gc = jm->js->gc; |
72 |
account = purple_connection_get_account(gc); |
73 |
account = purple_connection_get_account(gc); |
73 |
|
74 |
|
74 |
jb = jabber_buddy_find(jm->js, jm->from, TRUE); |
75 |
jb = jabber_buddy_find(jm->js, contact, TRUE); |
75 |
jbr = jabber_buddy_find_resource(jb, jid->resource); |
76 |
jbr = jabber_buddy_find_resource(jb, jid->resource); |
76 |
|
77 |
|
77 |
if(!jm->xhtml && !jm->body) { |
78 |
if(!jm->xhtml && !jm->body) { |
78 |
if (jbr && jm->chat_state != JM_STATE_NONE) |
79 |
if (!jm->outgoing) { |
79 |
jbr->chat_states = JABBER_CHAT_STATES_SUPPORTED; |
80 |
if (jbr && jm->chat_state != JM_STATE_NONE) |
|
|
81 |
jbr->chat_states = JABBER_CHAT_STATES_SUPPORTED; |
80 |
|
82 |
|
81 |
if(JM_STATE_COMPOSING == jm->chat_state) { |
83 |
if(JM_STATE_COMPOSING == jm->chat_state) { |
82 |
serv_got_typing(gc, jm->from, 0, PURPLE_TYPING); |
84 |
serv_got_typing(gc, contact, 0, PURPLE_TYPING); |
83 |
} else if(JM_STATE_PAUSED == jm->chat_state) { |
85 |
} else if(JM_STATE_PAUSED == jm->chat_state) { |
84 |
serv_got_typing(gc, jm->from, 0, PURPLE_TYPED); |
86 |
serv_got_typing(gc, contact, 0, PURPLE_TYPED); |
85 |
} else if(JM_STATE_GONE == jm->chat_state) { |
87 |
} else if(JM_STATE_GONE == jm->chat_state) { |
86 |
PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, |
88 |
PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, |
87 |
jm->from, account); |
89 |
contact, account); |
88 |
if (conv && jid->node && jid->domain) { |
90 |
if (conv && jid->node && jid->domain) { |
89 |
char buf[256]; |
91 |
char buf[256]; |
90 |
PurpleBuddy *buddy; |
92 |
PurpleBuddy *buddy; |
91 |
|
93 |
|
92 |
g_snprintf(buf, sizeof(buf), "%s@%s", jid->node, jid->domain); |
94 |
g_snprintf(buf, sizeof(buf), "%s@%s", jid->node, jid->domain); |
93 |
|
95 |
|
94 |
if ((buddy = purple_find_buddy(account, buf))) { |
96 |
if ((buddy = purple_find_buddy(account, buf))) { |
95 |
const char *who; |
97 |
const char *who; |
96 |
char *escaped; |
98 |
char *escaped; |
97 |
|
99 |
|
98 |
who = purple_buddy_get_alias(buddy); |
100 |
who = purple_buddy_get_alias(buddy); |
99 |
escaped = g_markup_escape_text(who, -1); |
101 |
escaped = g_markup_escape_text(who, -1); |
100 |
|
102 |
|
101 |
g_snprintf(buf, sizeof(buf), |
103 |
g_snprintf(buf, sizeof(buf), |
102 |
_("%s has left the conversation."), escaped); |
104 |
_("%s has left the conversation."), escaped); |
103 |
g_free(escaped); |
105 |
g_free(escaped); |
104 |
|
106 |
|
105 |
/* At some point when we restructure PurpleConversation, |
107 |
/* At some point when we restructure PurpleConversation, |
106 |
* this should be able to be implemented by removing the |
108 |
* this should be able to be implemented by removing the |
107 |
* user from the conversation like we do with chats now. */ |
109 |
* user from the conversation like we do with chats now. */ |
108 |
purple_conversation_write(conv, "", buf, |
110 |
purple_conversation_write(conv, "", buf, |
109 |
PURPLE_MESSAGE_SYSTEM, time(NULL)); |
111 |
PURPLE_MESSAGE_SYSTEM, time(NULL)); |
|
|
112 |
} |
110 |
} |
113 |
} |
|
|
114 |
serv_got_typing_stopped(gc, contact); |
115 |
|
116 |
} else { |
117 |
serv_got_typing_stopped(gc, contact); |
111 |
} |
118 |
} |
112 |
serv_got_typing_stopped(gc, jm->from); |
|
|
113 |
|
114 |
} else { |
115 |
serv_got_typing_stopped(gc, jm->from); |
116 |
} |
119 |
} |
117 |
} else { |
120 |
} else { |
118 |
if (jid->resource) { |
121 |
if (jid->resource) { |
Lines 128-139
Link Here
|
128 |
PurpleConversation *conv; |
131 |
PurpleConversation *conv; |
129 |
|
132 |
|
130 |
conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, |
133 |
conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, |
131 |
jm->from, account); |
134 |
contact, account); |
132 |
if (conv && !g_str_equal(jm->from, |
135 |
if (conv && !g_str_equal(contact, |
133 |
purple_conversation_get_name(conv))) { |
136 |
purple_conversation_get_name(conv))) { |
134 |
purple_debug_info("jabber", "Binding conversation to %s\n", |
137 |
purple_debug_info("jabber", "Binding conversation to %s\n", |
135 |
jm->from); |
138 |
contact); |
136 |
purple_conversation_set_name(conv, jm->from); |
139 |
purple_conversation_set_name(conv, contact); |
137 |
} |
140 |
} |
138 |
} |
141 |
} |
139 |
|
142 |
|
Lines 156-162
Link Here
|
156 |
jm->body = jabber_google_format_to_html(jm->body); |
159 |
jm->body = jabber_google_format_to_html(jm->body); |
157 |
g_free(tmp); |
160 |
g_free(tmp); |
158 |
} |
161 |
} |
159 |
serv_got_im(gc, jm->from, jm->xhtml ? jm->xhtml : jm->body, 0, jm->sent); |
162 |
serv_got_im(gc, contact, jm->xhtml ? jm->xhtml : jm->body, |
|
|
163 |
(jm->outgoing ? PURPLE_MESSAGE_SEND : PURPLE_MESSAGE_RECV), jm->sent); |
160 |
} |
164 |
} |
161 |
|
165 |
|
162 |
jabber_id_free(jid); |
166 |
jabber_id_free(jid); |
Lines 502-508
Link Here
|
502 |
JabberMessage *jm; |
506 |
JabberMessage *jm; |
503 |
const char *id, *from, *to, *type; |
507 |
const char *id, *from, *to, *type; |
504 |
xmlnode *child; |
508 |
xmlnode *child; |
505 |
gboolean signal_return; |
509 |
gboolean signal_return, is_outgoing = FALSE; |
|
|
510 |
time_t message_timestamp = time(NULL); |
511 |
gboolean delayed = FALSE; |
512 |
|
513 |
/* Check if this is a carbon-copy of a message. |
514 |
* If so, use that instead for the rest of this function, |
515 |
* but keep track of wether the from and to should be swapped. |
516 |
*/ |
517 |
from = xmlnode_get_attrib(packet, "from"); |
518 |
|
519 |
if (jabber_is_own_account(js, from)) { |
520 |
xmlnode *received = xmlnode_get_child_with_namespace(packet, "received", NS_XMPP_CARBONS); |
521 |
xmlnode *sent = xmlnode_get_child_with_namespace(packet, "sent", NS_XMPP_CARBONS); |
522 |
|
523 |
if (sent) |
524 |
is_outgoing = TRUE; |
525 |
|
526 |
if (received || sent) { |
527 |
xmlnode *forwarded = xmlnode_get_child_with_namespace(received ? received : sent, "forwarded", NS_XMPP_FORWARD); |
528 |
|
529 |
if (forwarded) { |
530 |
xmlnode *message = xmlnode_get_child_with_namespace(forwarded, "message", NS_XMPP_CLIENT); |
531 |
xmlnode *delay = xmlnode_get_child_with_namespace(forwarded, "delay", NS_DELAYED_DELIVERY); |
532 |
|
533 |
if (message) { |
534 |
purple_debug_info("jabber", "It's a carbon-copy message, using the wrapped message instead.\n"); |
535 |
packet = message; |
536 |
|
537 |
if (delay) { |
538 |
const char *timestamp = xmlnode_get_attrib(delay, "stamp"); |
539 |
|
540 |
if(timestamp) { |
541 |
purple_debug_info("jabber", "Found a delay stamp: %s\n", timestamp); |
542 |
|
543 |
delayed = TRUE; |
544 |
|
545 |
message_timestamp = purple_str_to_time(timestamp, TRUE, NULL, NULL, NULL); |
546 |
} |
547 |
} |
548 |
} |
549 |
} |
550 |
} |
551 |
} |
506 |
|
552 |
|
507 |
from = xmlnode_get_attrib(packet, "from"); |
553 |
from = xmlnode_get_attrib(packet, "from"); |
508 |
id = xmlnode_get_attrib(packet, "id"); |
554 |
id = xmlnode_get_attrib(packet, "id"); |
Lines 516-524
Link Here
|
516 |
|
562 |
|
517 |
jm = g_new0(JabberMessage, 1); |
563 |
jm = g_new0(JabberMessage, 1); |
518 |
jm->js = js; |
564 |
jm->js = js; |
519 |
jm->sent = time(NULL); |
565 |
jm->sent = message_timestamp; |
520 |
jm->delayed = FALSE; |
566 |
jm->delayed = delayed; |
521 |
jm->chat_state = JM_STATE_NONE; |
567 |
jm->chat_state = JM_STATE_NONE; |
|
|
568 |
jm->outgoing = is_outgoing; |
522 |
|
569 |
|
523 |
if(type) { |
570 |
if(type) { |
524 |
if(!strcmp(type, "normal")) |
571 |
if(!strcmp(type, "normal")) |
Lines 624-635
Link Here
|
624 |
jm->type == JABBER_MESSAGE_CHAT) { |
671 |
jm->type == JABBER_MESSAGE_CHAT) { |
625 |
conv = |
672 |
conv = |
626 |
purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, |
673 |
purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, |
627 |
from, account); |
674 |
is_outgoing ? to : from, account); |
628 |
if (!conv) { |
675 |
if (!conv) { |
629 |
/* we need to create the conversation here */ |
676 |
/* we need to create the conversation here */ |
630 |
conv = |
677 |
conv = |
631 |
purple_conversation_new(PURPLE_CONV_TYPE_IM, |
678 |
purple_conversation_new(PURPLE_CONV_TYPE_IM, |
632 |
account, from); |
679 |
account, is_outgoing ? to : from); |
633 |
} |
680 |
} |
634 |
} |
681 |
} |
635 |
} |
682 |
} |
Lines 709-714
Link Here
|
709 |
} else if(!strcmp(child->name, "attention") && !strcmp(xmlns, NS_ATTENTION)) { |
756 |
} else if(!strcmp(child->name, "attention") && !strcmp(xmlns, NS_ATTENTION)) { |
710 |
jm->hasBuzz = TRUE; |
757 |
jm->hasBuzz = TRUE; |
711 |
} else if(!strcmp(child->name, "delay") && !strcmp(xmlns, NS_DELAYED_DELIVERY)) { |
758 |
} else if(!strcmp(child->name, "delay") && !strcmp(xmlns, NS_DELAYED_DELIVERY)) { |
|
|
759 |
/* Carbons/Stanza fowarding might have already set jm->delayed. However, this timestamp was certainly applied earlier, so it overrides Carbons. */ |
712 |
const char *timestamp = xmlnode_get_attrib(child, "stamp"); |
760 |
const char *timestamp = xmlnode_get_attrib(child, "stamp"); |
713 |
jm->delayed = TRUE; |
761 |
jm->delayed = TRUE; |
714 |
if(timestamp) |
762 |
if(timestamp) |
Lines 1305-1307
Link Here
|
1305 |
|
1353 |
|
1306 |
return purple_account_get_bool(account, "custom_smileys", TRUE); |
1354 |
return purple_account_get_bool(account, "custom_smileys", TRUE); |
1307 |
} |
1355 |
} |
|
|
1356 |
|
1357 |
void jabber_toggle_carbons(PurplePluginAction *action) { |
1358 |
PurpleConnection *gc = (PurpleConnection *) action->context; |
1359 |
JabberStream *js = purple_connection_get_protocol_data(gc); |
1360 |
JabberIq *iq = jabber_iq_new(js, JABBER_IQ_SET); |
1361 |
gboolean has_carbons = !purple_account_get_bool(purple_connection_get_account(gc), "carbons", FALSE); |
1362 |
xmlnode *node; |
1363 |
|
1364 |
if (has_carbons) { |
1365 |
node = xmlnode_new_child(iq->node, "enable"); |
1366 |
} else { |
1367 |
node = xmlnode_new_child(iq->node, "disable"); |
1368 |
} |
1369 |
|
1370 |
purple_account_set_bool(gc->account, "carbons", has_carbons); |
1371 |
|
1372 |
xmlnode_set_namespace(node, NS_XMPP_CARBONS); |
1373 |
jabber_iq_send(iq); |
1374 |
|
1375 |
/* Force an update of the account actions. */ |
1376 |
purple_prpl_got_account_actions(purple_connection_get_account(gc)); |
1377 |
} |