libpurple/protocols/jabber/jabber.c

branch
cpw.attention_ui
changeset 27990
3de06f2e0daa
parent 27766
7c7acc54590e
parent 27924
ef40c7484edc
child 28264
d57edb4145aa
--- a/libpurple/protocols/jabber/jabber.c	Sun Jul 12 20:48:50 2009 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Tue Jul 28 20:52:33 2009 +0000
@@ -457,14 +457,21 @@
 void jabber_send_signal_cb(PurpleConnection *pc, xmlnode **packet,
                            gpointer unused)
 {
+	JabberStream *js;
 	char *txt;
 	int len;
 
 	if (NULL == packet)
 		return;
 
+	js = purple_connection_get_protocol_data(pc);
+	if (js->use_bosh)
+		if (g_str_equal((*packet)->name, "message") ||
+				g_str_equal((*packet)->name, "iq") ||
+				g_str_equal((*packet)->name, "presence"))
+			xmlnode_set_namespace(*packet, "jabber:client");
 	txt = xmlnode_to_str(*packet, &len);
-	jabber_send_raw(purple_connection_get_protocol_data(pc), txt, len);
+	jabber_send_raw(js, txt, len);
 	g_free(txt);
 }
 
@@ -658,7 +665,8 @@
 			try_srv_connect(js);
 		} else {
 			purple_debug_info("jabber","Couldn't connect directly to %s. Trying to find alternative connection methods, like BOSH.\n", js->user->domain);
-			js->srv_query_data = purple_txt_resolve("_xmppconnect", js->user->domain, txt_resolved_cb, js);
+			js->srv_query_data = purple_txt_resolve("_xmppconnect",
+					js->user->domain, txt_resolved_cb, js);
 		}
 		return;
 	}
@@ -698,6 +706,8 @@
 	js->gc->inpa = 0;
 	js->gsc = purple_ssl_connect_with_host_fd(js->gc->account, js->fd,
 			jabber_login_callback_ssl, jabber_ssl_connect_failure, js->certificate_CN, js->gc);
+	/* The fd is no longer our concern */
+	js->fd = -1;
 }
 
 static gboolean jabber_login_connect(JabberStream *js, const char *domain, const char *host, int port,
@@ -713,8 +723,8 @@
 	else
 		js->serverFQDN = g_strdup(host);
 
-	if (purple_proxy_connect(js->gc, js->gc->account, host,
-			port, jabber_login_callback, js->gc) == NULL) {
+	if (purple_proxy_connect(js->gc, purple_connection_get_account(js->gc),
+			host, port, jabber_login_callback, js->gc) == NULL) {
 		if (fatal_failure) {
 			purple_connection_error_reason(js->gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
@@ -740,7 +750,8 @@
 
 	/* Fall back to the defaults (I'm not sure if we should actually do this) */
 	jabber_login_connect(js, js->user->domain, js->user->domain,
-		purple_account_get_int(js->gc->account, "port", 5222), TRUE);
+			purple_account_get_int(purple_connection_get_account(js->gc), "port", 5222),
+			TRUE);
 }
 
 static void srv_resolved_cb(PurpleSrvResponse *resp, int results, gpointer data)
@@ -755,35 +766,68 @@
 		try_srv_connect(js);
 	} else {
 		jabber_login_connect(js, js->user->domain, js->user->domain,
-			purple_account_get_int(js->gc->account, "port", 5222), TRUE);
+				purple_account_get_int(purple_connection_get_account(js->gc), "port", 5222),
+				TRUE);
 	}
 }
 
-void
-jabber_login(PurpleAccount *account)
+static JabberStream *
+jabber_stream_new(PurpleAccount *account)
 {
 	PurpleConnection *gc = purple_account_get_connection(account);
-	const char *connect_server = purple_account_get_string(account,
-			"connect_server", "");
-	const char *bosh_url = purple_account_get_string(account,
-			"bosh_url", "");
 	JabberStream *js;
+	JabberBuddy *my_jb;
 	PurplePresence *presence;
-	PurpleStoredImage *image;
-	JabberBuddy *my_jb = NULL;
-
-	gc->flags |= PURPLE_CONNECTION_HTML |
-		PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY;
+	gchar *user;
+	gchar *slash;
+
 	js = gc->proto_data = g_new0(JabberStream, 1);
 	js->gc = gc;
 	js->fd = -1;
-	js->iq_callbacks = g_hash_table_new_full(g_str_hash, g_str_equal,
-			g_free, g_free);
+
+	user = g_strdup(purple_account_get_username(account));
+	/* jabber_id_new doesn't accept "user@domain/" as valid */
+	slash = strchr(user, '/');
+	if (slash && *(slash + 1) == '\0')
+		*slash = '\0';
+	js->user = jabber_id_new(user);
+
+	if (!js->user) {
+		purple_connection_error_reason(gc,
+			PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
+			_("Invalid XMPP ID"));
+		/* Destroying the connection will free the JabberStream */
+		return NULL;
+	}
+
+	if (!js->user->domain || *(js->user->domain) == '\0') {
+		purple_connection_error_reason(gc,
+			PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
+			_("Invalid XMPP ID. Domain must be set."));
+		/* Destroying the connection will free the JabberStream */
+		return NULL;
+	}
+
 	js->buddies = g_hash_table_new_full(g_str_hash, g_str_equal,
 			g_free, (GDestroyNotify)jabber_buddy_free);
+
+	my_jb = jabber_buddy_find(js, user, TRUE);
+	g_free(user);
+	if (!my_jb) {
+		/* This basically *can't* fail, but for good measure... */
+		purple_connection_error_reason(gc,
+			PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
+			_("Invalid XMPP ID"));
+		/* Destroying the connection will free the JabberStream */
+		g_return_val_if_reached(NULL);
+	}
+
+	my_jb->subscription |= JABBER_SUB_BOTH;
+
+	js->iq_callbacks = g_hash_table_new_full(g_str_hash, g_str_equal,
+			g_free, g_free);
 	js->chats = g_hash_table_new_full(g_str_hash, g_str_equal,
 			g_free, (GDestroyNotify)jabber_chat_free);
-	js->user = jabber_id_new(purple_account_get_username(account));
 	js->next_id = g_random_int();
 	js->write_buffer = purple_circ_buffer_new(512);
 	js->old_length = 0;
@@ -802,37 +846,21 @@
 	if (purple_presence_is_idle(presence))
 		js->idle = purple_presence_get_idle_time(presence);
 
-	if(!js->user) {
-		purple_connection_error_reason(gc,
-			PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
-			_("Invalid XMPP ID"));
-		return;
-	}
-
-	if (!js->user->domain || *(js->user->domain) == '\0') {
-		purple_connection_error_reason(gc,
-			PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
-			_("Invalid XMPP ID. Domain must be set."));
-		return;
-	}
-
-	/*
-	 * Calculate the avatar hash for our current image so we know (when we
-	 * fetch our vCard and PEP avatar) if we should send our avatar to the
-	 * server.
-	 */
-	if ((image = purple_buddy_icons_find_account_icon(account))) {
-		js->initial_avatar_hash = jabber_calculate_data_sha1sum(purple_imgstore_get_data(image),
-					purple_imgstore_get_size(image));
-		purple_imgstore_unref(image);
-	}
-
-	if((my_jb = jabber_buddy_find(js, purple_account_get_username(account), TRUE)))
-		my_jb->subscription |= JABBER_SUB_BOTH;
+	return js;
+}
+
+static void
+jabber_stream_connect(JabberStream *js)
+{
+	PurpleConnection *gc = js->gc;
+	PurpleAccount *account = purple_connection_get_account(gc);
+	const char *connect_server = purple_account_get_string(account,
+			"connect_server", "");
+	const char *bosh_url = purple_account_get_string(account,
+			"bosh_url", "");
 
 	jabber_stream_set_state(js, JABBER_STREAM_CONNECTING);
 
-	/* TODO: Just use purple_url_parse? */
 	/* If both BOSH and a Connect Server are specified, we prefer BOSH. I'm not
 	 * attached to that choice, though.
 	 */
@@ -842,7 +870,7 @@
 		if (js->bosh)
 			jabber_bosh_connection_connect(js->bosh);
 		else {
-			purple_connection_error_reason(js->gc,
+			purple_connection_error_reason(gc,
 				PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
 				_("Malformed BOSH URL"));
 		}
@@ -853,19 +881,18 @@
 	js->certificate_CN = g_strdup(connect_server[0] ? connect_server : js->user->domain);
 
 	/* if they've got old-ssl mode going, we probably want to ignore SRV lookups */
-	if(purple_account_get_bool(js->gc->account, "old_ssl", FALSE)) {
+	if(purple_account_get_bool(account, "old_ssl", FALSE)) {
 		if(purple_ssl_is_supported()) {
-			js->gsc = purple_ssl_connect(js->gc->account,
-					js->certificate_CN,
-					purple_account_get_int(account, "port", 5223), jabber_login_callback_ssl,
-					jabber_ssl_connect_failure, js->gc);
+			js->gsc = purple_ssl_connect(account, js->certificate_CN,
+					purple_account_get_int(account, "port", 5223),
+					jabber_login_callback_ssl, jabber_ssl_connect_failure, gc);
 			if (!js->gsc) {
-				purple_connection_error_reason(js->gc,
+				purple_connection_error_reason(gc,
 					PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
 					_("Unable to establish SSL connection"));
 			}
 		} else {
-			purple_connection_error_reason(js->gc,
+			purple_connection_error_reason(gc,
 				PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
 				_("SSL support unavailable"));
 		}
@@ -876,13 +903,43 @@
 	/* no old-ssl, so if they've specified a connect server, we'll use that, otherwise we'll
 	 * invoke the magic of SRV lookups, to figure out host and port */
 	if(connect_server[0]) {
-		jabber_login_connect(js, js->user->domain, connect_server, purple_account_get_int(account, "port", 5222), TRUE);
+		jabber_login_connect(js, js->user->domain, connect_server,
+				purple_account_get_int(account, "port", 5222), TRUE);
 	} else {
 		js->srv_query_data = purple_srv_resolve("xmpp-client",
 				"tcp", js->user->domain, srv_resolved_cb, js);
 	}
 }
 
+void
+jabber_login(PurpleAccount *account)
+{
+	PurpleConnection *gc = purple_account_get_connection(account);
+	JabberStream *js;
+	PurpleStoredImage *image;
+
+	gc->flags |= PURPLE_CONNECTION_HTML |
+		PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY;
+	js = jabber_stream_new(account);
+	if (js == NULL)
+		return;
+
+	/*
+	 * Calculate the avatar hash for our current image so we know (when we
+	 * fetch our vCard and PEP avatar) if we should send our avatar to the
+	 * server.
+	 */
+	image = purple_buddy_icons_find_account_icon(account);
+	if (image != NULL) {
+		js->initial_avatar_hash =
+			jabber_calculate_data_sha1sum(purple_imgstore_get_data(image),
+					purple_imgstore_get_size(image));
+		purple_imgstore_unref(image);
+	}
+
+	jabber_stream_connect(js);
+}
+
 
 static gboolean
 conn_close_cb(gpointer data)
@@ -1293,90 +1350,14 @@
 
 void jabber_register_account(PurpleAccount *account)
 {
-	PurpleConnection *gc = purple_account_get_connection(account);
 	JabberStream *js;
-	JabberBuddy *my_jb = NULL;
-	const char *connect_server = purple_account_get_string(account,
-			"connect_server", "");
-	const char *server;
-
-	js = gc->proto_data = g_new0(JabberStream, 1);
-	js->gc = gc;
-	js->registration = TRUE;
-	js->iq_callbacks = g_hash_table_new_full(g_str_hash, g_str_equal,
-			g_free, g_free);
-	js->user = jabber_id_new(purple_account_get_username(account));
-	js->next_id = g_random_int();
-	js->old_length = 0;
-	js->keepalive_timeout = 0;
-
-	if(!js->user) {
-		purple_connection_error_reason(gc,
-			PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
-			_("Invalid XMPP ID"));
+
+	js = jabber_stream_new(account);
+	if (js == NULL)
 		return;
-	}
-
-	js->write_buffer = purple_circ_buffer_new(512);
-
-	if((my_jb = jabber_buddy_find(js, purple_account_get_username(account), TRUE)))
-		my_jb->subscription |= JABBER_SUB_BOTH;
-
-	server = connect_server[0] ? connect_server : js->user->domain;
-	js->certificate_CN = g_strdup(server);
-
-	js->stun_ip = NULL;
-	js->stun_port = 0;
-	js->stun_query = NULL;
-
-	jabber_stream_set_state(js, JABBER_STREAM_CONNECTING);
-
-	/* TODO: Just use purple_url_parse? */
-	if (!g_ascii_strncasecmp(connect_server, "http://", 7) || !g_ascii_strncasecmp(connect_server, "https://", 8)) {
-		js->use_bosh = TRUE;
-		js->bosh = jabber_bosh_connection_init(js, connect_server);
-		if (!js->bosh) {
-			purple_connection_error_reason(js->gc,
-				PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
-				_("Malformed BOSH Connect Server"));
-			return;
-		}
-		jabber_bosh_connection_connect(js->bosh);
-		return;
-	} else {
-		js->certificate_CN = g_strdup(connect_server[0] ? connect_server : js->user->domain);
-	}
-
-	if(purple_account_get_bool(account, "old_ssl", FALSE)) {
-		if(purple_ssl_is_supported()) {
-			js->gsc = purple_ssl_connect(account, server,
-					purple_account_get_int(account, "port", 5222),
-					jabber_login_callback_ssl, jabber_ssl_connect_failure, gc);
-			if (!js->gsc) {
-				purple_connection_error_reason(js->gc,
-					PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
-					_("Unable to establish SSL connection"));
-			}
-		} else {
-			purple_connection_error_reason(gc,
-				PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
-				_("SSL support unavailable"));
-		}
-
-		return;
-	}
-
-	if (connect_server[0]) {
-		jabber_login_connect(js, js->user->domain, server,
-		                     purple_account_get_int(account,
-		                                            "port", 5222), TRUE);
-	} else {
-		js->srv_query_data = purple_srv_resolve("xmpp-client",
-		                                        "tcp",
-		                                        js->user->domain,
-		                                        srv_resolved_cb,
-		                                        js);
-	}
+
+	js->registration = TRUE;
+	jabber_stream_connect(js);
 }
 
 static void
@@ -1466,7 +1447,7 @@
 	if (!gc->disconnect_timeout) {
 		if (js->use_bosh)
 			jabber_bosh_connection_close(js->bosh);
-		else
+		else if ((js->gsc && js->gsc->fd > 0) || js->fd > 0)
 			jabber_send_raw(js, "</stream:stream>", -1);
 	}
 
@@ -1975,19 +1956,17 @@
 		ret = g_strdup(jb->error_msg);
 	} else {
 		PurplePresence *presence = purple_buddy_get_presence(b);
-		PurpleStatus *status =purple_presence_get_active_status(presence);
-		char *stripped;
-
-		if(!(stripped = purple_markup_strip_html(purple_status_get_attr_string(status, "message")))) {
-			if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {
-				PurpleStatus *status = purple_presence_get_status(presence, "tune");
-				stripped = g_strdup(purple_status_get_attr_string(status, PURPLE_TUNE_TITLE));
-			}
-		}
-
-		if(stripped) {
-			ret = g_markup_escape_text(stripped, -1);
-			g_free(stripped);
+		PurpleStatus *status = purple_presence_get_active_status(presence);
+		const char *message;
+
+		if((message = purple_status_get_attr_string(status, "message"))) {
+			ret = g_markup_escape_text(message, -1);
+		} else if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {
+			PurpleStatus *status = purple_presence_get_status(presence, "tune");
+			const char *title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE);
+			const char *artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST);
+			const char *album = purple_status_get_attr_string(status, PURPLE_TUNE_ALBUM);
+			ret = purple_util_format_song_info(title, artist, album, NULL);
 		}
 	}
 
@@ -2004,12 +1983,7 @@
 	const char *state;
 
 	if(jbr->status) {
-		char *tmp;
-		text = purple_strreplace(jbr->status, "\n", "<br />\n");
-		tmp = purple_markup_strip_html(text);
-		g_free(text);
-		text = g_markup_escape_text(tmp, -1);
-		g_free(tmp);
+		text = g_markup_escape_text(jbr->status, -1);
 	}
 
 	if(jbr->name)
@@ -3433,8 +3407,9 @@
 {
 	GHashTable *ui_info = purple_core_get_ui_info();
 	const gchar *ui_type;
-	const gchar *type = "pc"; /* default client type, if unknown or 
+	const gchar *type = "pc"; /* default client type, if unknown or
 								unspecified */
+	const gchar *ui_name = NULL;
 
 	jabber_plugin = plugin;
 
@@ -3450,7 +3425,12 @@
 		}
 	}
 
-	jabber_add_identity("client", type, NULL, PACKAGE);
+	if (ui_info)
+		ui_name = g_hash_table_lookup(ui_info, "name");
+	if (ui_name == NULL)
+		ui_name = PACKAGE;
+
+	jabber_add_identity("client", type, NULL, ui_name);
 
 	/* initialize jabber_features list */
 	jabber_add_feature("jabber:iq:last", 0);

mercurial