changeset 27403:659345e5473b

merge of '0866182af6b0894f55f42ac5dd8d01f9a2c3160c' and '921a6693312cc38dd6dbc93e91d6bf5c60938634'
author Elliott Sales de Andrade <qulogic@pidgin.im>
date Tue, 07 Jul 2009 06:31:45 +0000
parents 4f0fcb2526e6 (diff) 12edccab4944 (current diff)
children 52298a298260
files
diffstat 4 files changed, 200 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Tue Jul 07 04:32:58 2009 +0000
+++ b/ChangeLog	Tue Jul 07 06:31:45 2009 +0000
@@ -124,6 +124,8 @@
 	* Draw the user's buddy icon at the bottom of the Buddy List with rounded
 	  corners for visual consistency with the actual icons in the Buddy List.
 	  (Kosta Arvanitis)
+	* When file transfers are complete, the received file name written to the
+	  conversation window is now linked to the file.
 
 	Finch:
 	* The hardware cursor is updated correctly. This will be useful
--- a/libpurple/ft.c	Tue Jul 07 04:32:58 2009 +0000
+++ b/libpurple/ft.c	Tue Jul 07 06:31:45 2009 +0000
@@ -696,14 +696,34 @@
 
 	if (completed == TRUE) {
 		char *msg = NULL;
+		PurpleConversation *conv;
+
 		purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_DONE);
 
 		if (purple_xfer_get_filename(xfer) != NULL)
-			msg = g_strdup_printf(_("Transfer of file %s complete"),
-								purple_xfer_get_filename(xfer));
+		{
+			char *filename = g_markup_escape_text(purple_xfer_get_filename(xfer), -1);
+			if (purple_xfer_get_local_filename(xfer)
+			 && purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE)
+			{
+				char *local = g_markup_escape_text(purple_xfer_get_local_filename(xfer), -1);
+				msg = g_strdup_printf(_("Transfer of file <A HREF=\"file://%s\">%s</A> complete"),
+				                      local, filename);
+				g_free(local);
+			}
+			else
+				msg = g_strdup_printf(_("Transfer of file %s complete"),
+				                      filename);
+			g_free(filename);
+		}
 		else
 			msg = g_strdup(_("File transfer complete"));
-		purple_xfer_conversation_write(xfer, msg, FALSE);
+
+		conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, xfer->who,
+		                                             purple_xfer_get_account(xfer));
+
+		if (conv != NULL)
+			purple_conversation_write(conv, NULL, msg, PURPLE_MESSAGE_SYSTEM, time(NULL));
 		g_free(msg);
 	}
 
--- a/libpurple/protocols/msn/msn.c	Tue Jul 07 04:32:58 2009 +0000
+++ b/libpurple/protocols/msn/msn.c	Tue Jul 07 06:31:45 2009 +0000
@@ -1389,40 +1389,70 @@
                   MsnNetwork network,
                   MsnUser *user)
 {
-	MsnUserList *userlist = session->userlist;
-	MsnUser *user2;
 	char *group;
 
 	g_return_if_fail(user != NULL);
 
 	group = msn_user_remove_pending_group(user);
 
-	user2 = msn_userlist_find_user(userlist, who);
-	if (user2 != NULL) {
-		/* User already in userlist, so just update it. */
+	if (network != MSN_NETWORK_UNKNOWN) {
+		MsnUserList *userlist = session->userlist;
+		MsnUser *user2 = msn_userlist_find_user(userlist, who);
+		if (user2 != NULL) {
+			/* User already in userlist, so just update it. */
+			msn_user_destroy(user);
+			user = user2;
+		} else {
+			msn_userlist_add_user(userlist, user);
+		}
+
+		msn_user_set_network(user, network);
+		msn_userlist_add_buddy(userlist, who, group);
+	}
+	else
+	{
+		PurpleBuddy * buddy = purple_find_buddy(session->account, who);
+		gchar *buf;
+		buf = g_strdup_printf(_("Unable to add the buddy %s because the username is invalid.  Usernames must be a valid email address."), who);
+		if (!purple_conv_present_error(who, session->account, buf))
+			purple_notify_error(purple_account_get_connection(session->account), NULL, _("Unable to Add"), buf);
+		g_free(buf);
+
+		/* Remove from local list */
+		purple_blist_remove_buddy(buddy);
 		msn_user_destroy(user);
-		user = user2;
-	} else {
-		msn_userlist_add_user(userlist, user);
 	}
-
-	msn_user_set_network(user, network);
-	msn_userlist_add_buddy(userlist, who, group);
 	g_free(group);
 }
 
 static void
 msn_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
 {
+	PurpleAccount *account;
 	MsnSession *session;
 	MsnUserList *userlist;
-	const char *who, *gname;
+	const char *bname, *who, *gname;
 	MsnUser *user;
 
+	account = purple_connection_get_account(gc);
 	session = gc->proto_data;
 	userlist = session->userlist;
-	who = msn_normalize(purple_connection_get_account(gc), purple_buddy_get_name(buddy));
-
+	bname = purple_buddy_get_name(buddy);
+
+	if (!purple_email_is_valid(bname)) {
+		gchar *buf;
+		buf = g_strdup_printf(_("Unable to add the buddy %s because the username is invalid.  Usernames must be a valid email address."), bname);
+		if (!purple_conv_present_error(bname, account, buf))
+			purple_notify_error(gc, NULL, _("Unable to Add"), buf);
+		g_free(buf);
+
+		/* Remove from local list */
+		purple_blist_remove_buddy(buddy);
+
+		return;
+	}
+
+	who = msn_normalize(account, bname);
 	gname = group ? purple_group_get_name(group) : NULL;
 	purple_debug_info("msn", "Add user:%s to group:%s\n", who, gname ? gname : "(null)");
 	if (!session->logged_in)
--- a/pidgin/gtkutils.c	Tue Jul 07 04:32:58 2009 +0000
+++ b/pidgin/gtkutils.c	Tue Jul 07 06:31:45 2009 +0000
@@ -3578,6 +3578,135 @@
 	return TRUE;
 }
 
+static void
+file_open_uri(GtkIMHtml *imhtml, const char *uri)
+{
+	/* Copied from gtkft.c:open_button_cb */
+#ifdef _WIN32
+	/* If using Win32... */
+	int code;
+	if (G_WIN32_HAVE_WIDECHAR_API()) {
+		wchar_t *wc_filename = g_utf8_to_utf16(
+				uri, -1, NULL, NULL, NULL);
+
+		code = (int)ShellExecuteW(NULL, NULL, wc_filename, NULL, NULL,
+				SW_SHOW);
+
+		g_free(wc_filename);
+	} else {
+		char *l_filename = g_locale_from_utf8(
+				uri, -1, NULL, NULL, NULL);
+
+		code = (int)ShellExecuteA(NULL, NULL, l_filename, NULL, NULL,
+				SW_SHOW);
+
+		g_free(l_filename);
+	}
+
+	if (code == SE_ERR_ASSOCINCOMPLETE || code == SE_ERR_NOASSOC)
+	{
+		purple_notify_error(imhtml, NULL,
+				_("There is no application configured to open this type of file."), NULL);
+	}
+	else if (code < 32)
+	{
+		purple_notify_error(imhtml, NULL,
+				_("An error occurred while opening the file."), NULL);
+		purple_debug_warning("gtkutils", "filename: %s; code: %d\n", uri, code);
+	}
+#else
+	char *command = NULL;
+	char *tmp = NULL;
+	GError *error = NULL;
+
+	if (purple_running_gnome())
+	{
+		char *escaped = g_shell_quote(uri);
+		command = g_strdup_printf("gnome-open %s", escaped);
+		g_free(escaped);
+	}
+	else if (purple_running_kde())
+	{
+		char *escaped = g_shell_quote(uri);
+
+		if (purple_str_has_suffix(uri, ".desktop"))
+			command = g_strdup_printf("kfmclient openURL %s 'text/plain'", escaped);
+		else
+			command = g_strdup_printf("kfmclient openURL %s", escaped);
+		g_free(escaped);
+	}
+	else
+	{
+		purple_notify_uri(NULL, uri);
+		return;
+	}
+
+	if (purple_program_is_valid(command))
+	{
+		gint exit_status;
+		if (!g_spawn_command_line_sync(command, NULL, NULL, &exit_status, &error))
+		{
+			tmp = g_strdup_printf(_("Error launching %s: %s"),
+							uri, error->message);
+			purple_notify_error(imhtml, NULL, _("Unable to open file."), tmp);
+			g_free(tmp);
+			g_error_free(error);
+		}
+		if (exit_status != 0)
+		{
+			char *primary = g_strdup_printf(_("Error running %s"), command);
+			char *secondary = g_strdup_printf(_("Process returned error code %d"),
+									exit_status);
+			purple_notify_error(imhtml, NULL, primary, secondary);
+			g_free(tmp);
+		}
+	}
+#endif
+}
+
+#define FILELINKSIZE  (sizeof("file://") - 1)
+static gboolean
+file_clicked_cb(GtkIMHtml *imhtml, GtkIMHtmlLink *link)
+{
+	const char *uri = gtk_imhtml_link_get_url(link) + FILELINKSIZE;
+	file_open_uri(imhtml, uri);
+	return TRUE;
+}
+
+static gboolean
+open_containing_cb(GtkIMHtml *imhtml, const char *url)
+{
+	char *dir = g_path_get_dirname(url + FILELINKSIZE);
+	file_open_uri(imhtml, dir);
+	g_free(dir);
+	return TRUE;
+}
+
+static gboolean
+file_context_menu(GtkIMHtml *imhtml, GtkIMHtmlLink *link, GtkWidget *menu)
+{
+	GtkWidget *img, *item;
+	const char *url;
+
+	url = gtk_imhtml_link_get_url(link);
+
+	/* Open File */
+	img = gtk_image_new_from_stock(GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_MENU);
+	item = gtk_image_menu_item_new_with_mnemonic(_("_Open File"));
+	gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img);
+	g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_link_activate), link);
+	gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+
+	/* Open Containing Directory */
+	img = gtk_image_new_from_stock(GTK_STOCK_COPY, GTK_ICON_SIZE_MENU);
+	item = gtk_image_menu_item_new_with_mnemonic(_("Open _Containing Directory"));
+	gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img);
+	g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(open_containing_cb), (gpointer)url);
+	gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+
+	return TRUE;
+}
+
 /* XXX: The following two functions are for demonstration purposes only! */
 static gboolean
 open_dialog(GtkIMHtml *imhtml, GtkIMHtmlLink *link)
@@ -3684,6 +3813,8 @@
 	gtk_imhtml_class_register_protocol("gopher://", url_clicked_cb, link_context_menu);
 	gtk_imhtml_class_register_protocol("mailto:", url_clicked_cb, copy_email_address);
 
+	gtk_imhtml_class_register_protocol("file://", file_clicked_cb, file_context_menu);
+
 	/* Example custom URL handler. */
 	gtk_imhtml_class_register_protocol("open://", open_dialog, dummy);