# HG changeset patch # User Elliott Sales de Andrade # Date 1246948305 0 # Node ID 659345e5473be1a424d01a68232e12fe0b6566d9 # Parent 4f0fcb2526e6ee5e7288383e9d289ad77fe276cf# Parent 12edccab4944ce5439346f13c1adb20da63952d7 merge of '0866182af6b0894f55f42ac5dd8d01f9a2c3160c' and '921a6693312cc38dd6dbc93e91d6bf5c60938634' diff -r 12edccab4944 -r 659345e5473b ChangeLog --- 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 diff -r 12edccab4944 -r 659345e5473b libpurple/ft.c --- 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 %s 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); } diff -r 12edccab4944 -r 659345e5473b libpurple/protocols/msn/msn.c --- 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) diff -r 12edccab4944 -r 659345e5473b pidgin/gtkutils.c --- 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);