Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 528812
Collapse All | Expand All

(-)a/libpurple/protocols/jabber/disco.c (-2 / +14 lines)
Lines 295-303 Link Here
295
					capabilities |= JABBER_CAP_PING;
295
					capabilities |= JABBER_CAP_PING;
296
				else if(!strcmp(var, NS_DISCO_ITEMS))
296
				else if(!strcmp(var, NS_DISCO_ITEMS))
297
					capabilities |= JABBER_CAP_ITEMS;
297
					capabilities |= JABBER_CAP_ITEMS;
298
				else if(!strcmp(var, "http://jabber.org/protocol/commands")) {
298
				else if(!strcmp(var, "http://jabber.org/protocol/commands"))
299
					capabilities |= JABBER_CAP_ADHOC;
299
					capabilities |= JABBER_CAP_ADHOC;
300
				}
301
				else if(!strcmp(var, NS_IBB)) {
300
				else if(!strcmp(var, NS_IBB)) {
302
					purple_debug_info("jabber", "remote supports IBB\n");
301
					purple_debug_info("jabber", "remote supports IBB\n");
303
					capabilities |= JABBER_CAP_IBB;
302
					capabilities |= JABBER_CAP_IBB;
Lines 386-391 Link Here
386
		jabber_request_block_list(js);
385
		jabber_request_block_list(js);
387
	}
386
	}
388
387
388
	if ((js->server_caps & JABBER_CAP_CARBONS) && purple_account_get_bool(js->gc->account, "carbons", FALSE)) {
389
		JabberIq *iq = jabber_iq_new(js, JABBER_IQ_SET);
390
		xmlnode *enable = xmlnode_new_child(iq->node, "enable");
391
		
392
		purple_debug_info("jabber", "Automatically enabling Carbons.\n");
393
394
		xmlnode_set_namespace(enable, NS_XMPP_CARBONS);
395
396
		jabber_iq_send(iq);
397
	}
398
389
	/* If there are manually specified bytestream proxies, query them */
399
	/* If there are manually specified bytestream proxies, query them */
390
	ft_proxies = purple_account_get_string(js->gc->account, "ft_proxies", NULL);
400
	ft_proxies = purple_account_get_string(js->gc->account, "ft_proxies", NULL);
391
	if (ft_proxies) {
401
	if (ft_proxies) {
Lines 574-579 Link Here
574
			js->server_caps |= JABBER_CAP_ADHOC;
584
			js->server_caps |= JABBER_CAP_ADHOC;
575
		} else if (!strcmp(NS_SIMPLE_BLOCKING, var)) {
585
		} else if (!strcmp(NS_SIMPLE_BLOCKING, var)) {
576
			js->server_caps |= JABBER_CAP_BLOCKING;
586
			js->server_caps |= JABBER_CAP_BLOCKING;
587
		} else if(!strcmp(var, NS_XMPP_CARBONS)) {
588
			js->server_caps |= JABBER_CAP_CARBONS;
577
		}
589
		}
578
	}
590
	}
579
591
(-)a/libpurple/protocols/jabber/jabber.c (+6 lines)
Lines 2566-2571 Link Here
2566
	JabberStream *js = gc->proto_data;
2566
	JabberStream *js = gc->proto_data;
2567
	GList *m = NULL;
2567
	GList *m = NULL;
2568
	PurplePluginAction *act;
2568
	PurplePluginAction *act;
2569
	gboolean has_carbons = purple_account_get_bool(gc->account, "carbons", FALSE);
2569
2570
2570
	act = purple_plugin_action_new(_("Set User Info..."),
2571
	act = purple_plugin_action_new(_("Set User Info..."),
2571
	                             jabber_setup_set_info);
2572
	                             jabber_setup_set_info);
Lines 2589-2594 Link Here
2589
	if(js->commands)
2590
	if(js->commands)
2590
		jabber_adhoc_init_server_commands(js, &m);
2591
		jabber_adhoc_init_server_commands(js, &m);
2591
2592
2593
	if(js->server_caps & JABBER_CAP_CARBONS) {
2594
		act = purple_plugin_action_new((has_carbons ? _("Disable Message Copies") : _("Enable Message Copies")), jabber_toggle_carbons);
2595
		m = g_list_append(m, act);
2596
	}
2597
2592
	return m;
2598
	return m;
2593
}
2599
}
2594
2600
(-)a/libpurple/protocols/jabber/jabber.h (+2 lines)
Lines 48-53 Link Here
48
48
49
	JABBER_CAP_ITEMS          = 1 << 14,
49
	JABBER_CAP_ITEMS          = 1 << 14,
50
	JABBER_CAP_ROSTER_VERSIONING = 1 << 15,
50
	JABBER_CAP_ROSTER_VERSIONING = 1 << 15,
51
	
52
	JABBER_CAP_CARBONS        = 1 << 16,
51
53
52
	JABBER_CAP_RETRIEVED      = 1 << 31
54
	JABBER_CAP_RETRIEVED      = 1 << 31
53
} JabberCapabilities;
55
} JabberCapabilities;
(-)a/libpurple/protocols/jabber/message.c (-42 / +112 lines)
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
}
(-)a/libpurple/protocols/jabber/message.h (+3 lines)
Lines 62-67 Link Here
62
	} chat_state;
62
	} chat_state;
63
	GList *etc;
63
	GList *etc;
64
	GList *eventitems;
64
	GList *eventitems;
65
	gboolean outgoing;
65
} JabberMessage;
66
} JabberMessage;
66
67
67
void jabber_message_free(JabberMessage *jm);
68
void jabber_message_free(JabberMessage *jm);
Lines 79-82 Link Here
79
80
80
gboolean jabber_custom_smileys_isenabled(JabberStream *js, const const gchar *namespace);
81
gboolean jabber_custom_smileys_isenabled(JabberStream *js, const const gchar *namespace);
81
82
83
void jabber_toggle_carbons(PurplePluginAction *action);
84
82
#endif /* PURPLE_JABBER_MESSAGE_H_ */
85
#endif /* PURPLE_JABBER_MESSAGE_H_ */
(-)a/libpurple/protocols/jabber/namespaces.h (+6 lines)
Lines 95-100 Link Here
95
/* XEP-0264 File Transfer Thumbnails (Thumbs) */
95
/* XEP-0264 File Transfer Thumbnails (Thumbs) */
96
#define NS_THUMBS "urn:xmpp:thumbs:0"
96
#define NS_THUMBS "urn:xmpp:thumbs:0"
97
97
98
/* XEP-0280 Message Carbons */
99
#define NS_XMPP_CARBONS "urn:xmpp:carbons:2"
100
101
/* XEP-0297 Message Forwarding */
102
#define NS_XMPP_FORWARD "urn:xmpp:forward:0"
103
98
/* Google extensions */
104
/* Google extensions */
99
#define NS_GOOGLE_CAMERA "http://www.google.com/xmpp/protocol/camera/v1"
105
#define NS_GOOGLE_CAMERA "http://www.google.com/xmpp/protocol/camera/v1"
100
#define NS_GOOGLE_VIDEO "http://www.google.com/xmpp/protocol/video/v1"
106
#define NS_GOOGLE_VIDEO "http://www.google.com/xmpp/protocol/video/v1"
(-)a/libpurple/server.c (-5 lines)
Lines 567-577 Link Here
567
567
568
	account  = purple_connection_get_account(gc);
568
	account  = purple_connection_get_account(gc);
569
569
570
	/*
571
	 * XXX: Should we be setting this here, or relying on prpls to set it?
572
	 */
573
	flags |= PURPLE_MESSAGE_RECV;
574
575
	if (!purple_privacy_check(account, who)) {
570
	if (!purple_privacy_check(account, who)) {
576
		purple_signal_emit(purple_conversations_get_handle(), "blocked-im-msg",
571
		purple_signal_emit(purple_conversations_get_handle(), "blocked-im-msg",
577
				account, who, msg, flags, (unsigned int)mtime);
572
				account, who, msg, flags, (unsigned int)mtime);

Return to bug 528812