summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Silva <typ0@pidgin.im>2007-08-31 18:15:23 +0000
committerCarlos Silva <typ0@pidgin.im>2007-08-31 18:15:23 +0000
commitac97db9d061a985f630e107b2f6f9bbd70874083 (patch)
treef4223ec74666fc3bd8416a85dfe1e490dc088db9
parent45d62c492073747968ca09a8695b7fa15c7beeb1 (diff)
parent164dcf9f22bbabb984f5a91d9443d48841972ba8 (diff)
downloadpidgin-ac97db9d061a985f630e107b2f6f9bbd70874083.tar.gz
propagate from branch 'im.pidgin.pidgin' (head 1f9c8875c10101c0380abef463bf71576cfaefe7)
to branch 'im.pidgin.cpw.khc.msnp14' (head 2417aff6ff3b6aa0389bdc822c61de13737f4eab)
-rw-r--r--ChangeLog.API12
-rw-r--r--ChangeLog.win326
-rw-r--r--doc/gtkconv-signals.dox20
-rw-r--r--finch/Makefile.am2
-rw-r--r--finch/finch.c4
-rw-r--r--finch/gntcertmgr.c340
-rw-r--r--finch/gntcertmgr.h31
-rw-r--r--finch/gntconv.c1
-rw-r--r--finch/gntrequest.c4
-rw-r--r--finch/gntui.c2
-rwxr-xr-xfinch/libgnt/pygnt/dbus-gnt31
-rwxr-xr-xfinch/libgnt/pygnt/gendef.sh2
-rw-r--r--libpurple/Makefile.am6
-rw-r--r--libpurple/certificate.c55
-rw-r--r--libpurple/conversation.c114
-rw-r--r--libpurple/conversation.h70
-rw-r--r--libpurple/core.c3
-rw-r--r--libpurple/dbus-analyze-functions.py1
-rw-r--r--libpurple/example/nullclient.c46
-rw-r--r--libpurple/plugins/ssl/ssl-gnutls.c182
-rw-r--r--libpurple/prefs.c3
-rw-r--r--libpurple/protocols/Makefile.mingw2
-rw-r--r--libpurple/protocols/bonjour/issues.txt1
-rw-r--r--libpurple/protocols/silc/Makefile.mingw4
-rw-r--r--libpurple/protocols/silc/silc.c3
-rw-r--r--libpurple/protocols/yahoo/yahoo.c49
-rw-r--r--libpurple/protocols/yahoo/yahoo.h4
-rw-r--r--libpurple/protocols/yahoo/yahoochat.c263
-rw-r--r--libpurple/prpl.c6
-rw-r--r--libpurple/server.c5
-rw-r--r--libpurple/win32/global.mak2
-rw-r--r--pidgin/gtkaccount.c7
-rw-r--r--pidgin/gtkblist.c71
-rw-r--r--pidgin/gtkcertmgr.c9
-rw-r--r--pidgin/gtkconv.c104
-rw-r--r--pidgin/gtkconv.h16
-rw-r--r--pidgin/gtkdialogs.c2
-rw-r--r--pidgin/gtkimhtmltoolbar.c15
-rw-r--r--pidgin/gtkmain.c19
-rw-r--r--pidgin/gtkprefs.c18
-rw-r--r--pidgin/gtksound.c2
-rw-r--r--pidgin/gtksourceundomanager.c4
-rw-r--r--pidgin/gtkstatusbox.c9
-rw-r--r--pidgin/plugins/notify.c10
-rw-r--r--pidgin/win32/nsis/pidgin-installer.nsi10
-rw-r--r--share/ca-certs/GTE_CyberTrust_Global_Root.pem16
-rw-r--r--share/ca-certs/Makefile.am9
-rw-r--r--share/ca-certs/Verisign_Class3_Primary_CA.pem14
48 files changed, 1231 insertions, 378 deletions
diff --git a/ChangeLog.API b/ChangeLog.API
index b0fec8feb9..e6e00615a7 100644
--- a/ChangeLog.API
+++ b/ChangeLog.API
@@ -1,10 +1,22 @@
Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
Version 2.2.0 (??/??/????):
+ libpurple:
+ Added:
+ * PURPLE_MESSAGE_INVISIBLE flag, which can be used by
+ purple_conv_im_send_with_flags to send a message, but not display it
+ in the conversation
+ Changed:
+ * purple_prefs_load is now called within purple_prefs_init.
+ The UI no longer needs to call it.
+
Pidgin:
Added:
* pidgin_set_accessible_relations, sets up label-for and labelled-by
ATK relations (broken out from pidgin_set_accessible_label)
+ * pidgin_conv_attach_to_conversation, to reattach the Pidgin UI to a
+ conversation
+ * conversation-hiding and conversation-displayed signals.
Finch:
Added:
diff --git a/ChangeLog.win32 b/ChangeLog.win32
index e3a7e1b55b..c91b5f0b3c 100644
--- a/ChangeLog.win32
+++ b/ChangeLog.win32
@@ -1,5 +1,9 @@
+version 2.2.0 (??/??/2007):
+ * Updated gtkspell to 2.0.11
+ * Upgrade SILC to use the 1.1.2 toolkit
+
version 2.1.1 (08/20/2007):
- * No changes
+ * No changes
version 2.1.0 (7/28/2007):
* Updated launcher application (pidgin.exe) to support portable mode
diff --git a/doc/gtkconv-signals.dox b/doc/gtkconv-signals.dox
index 94747b5d55..c414280b79 100644
--- a/doc/gtkconv-signals.dox
+++ b/doc/gtkconv-signals.dox
@@ -8,6 +8,8 @@
@signal displaying-chat-msg
@signal displayed-chat-msg
@signal conversation-switched
+ @signal conversation-hiding
+ @signal conversation-displayed
@endsignals
<hr>
@@ -116,5 +118,23 @@ void (*conversation_switched)(PurpleConversation *conv);
@param new_conv The now active conversation.
@endsignaldef
+ @signaldef conversation-hiding
+ @signalproto
+void (*conversation_hiding)(PidginConversation *gtkconv);
+ @endsignalproto
+ @signaldesc
+ Emitted immediately before an existing conversation is hidden.
+ @param gtkconv The PidginConversation
+ @endsignaldef
+
+ @signaldef conversation-displayed
+ @signalproto
+void (*conversation_displayed)(PidginConversation *gtkconv);
+ @endsignalproto
+ @signaldesc
+ Emitted right after the Pidgin UI is reattached to a conversation.
+ @param gtkconv The PidginConversation
+ @endsignaldef
+
*/
// vim: syntax=c tw=75 et
diff --git a/finch/Makefile.am b/finch/Makefile.am
index 39b20723c9..bebf945903 100644
--- a/finch/Makefile.am
+++ b/finch/Makefile.am
@@ -14,6 +14,7 @@ endif
finch_SOURCES = \
gntaccount.c \
gntblist.c \
+ gntcertmgr.c \
gntconn.c \
gntconv.c \
gntdebug.c \
@@ -32,6 +33,7 @@ finch_SOURCES = \
finch_headers = \
gntaccount.h \
gntblist.h \
+ gntcertmgr.h \
gntconn.h \
gntconv.h \
gntdebug.h \
diff --git a/finch/finch.c b/finch/finch.c
index 0a433cbcff..120732f8fa 100644
--- a/finch/finch.c
+++ b/finch/finch.c
@@ -360,9 +360,7 @@ init_libpurple(int argc, char **argv)
purple_set_blist(purple_blist_new());
purple_blist_load();
- /* TODO: Move prefs loading into purple_prefs_init() */
- purple_prefs_load();
- purple_prefs_update_old();
+ /* TODO: should this be moved into finch_prefs_init() ? */
finch_prefs_update_old();
/* load plugins we had when we quit */
diff --git a/finch/gntcertmgr.c b/finch/gntcertmgr.c
new file mode 100644
index 0000000000..a20be82301
--- /dev/null
+++ b/finch/gntcertmgr.c
@@ -0,0 +1,340 @@
+/**
+ * @file gntcertmgr.c GNT Certificate Manager API
+ * @ingroup finch
+ *
+ * finch
+ *
+ * Finch is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "internal.h"
+
+#include "certificate.h"
+#include "debug.h"
+#include "notify.h"
+#include "request.h"
+
+#include "finch.h"
+#include "gntcertmgr.h"
+
+#include "gntbutton.h"
+#include "gntlabel.h"
+#include "gnttree.h"
+#include "gntutils.h"
+#include "gntwindow.h"
+
+struct {
+ GntWidget *window;
+ GntWidget *tree;
+ PurpleCertificatePool *pool;
+} certmgr;
+
+/* Pretty much Xerox of gtkcertmgr */
+
+/* Add certificate */
+static void
+tls_peers_mgmt_import_ok2_cb(gpointer data, const char *result)
+{
+ PurpleCertificate *crt = (PurpleCertificate *) data;
+ const char *id = result;
+
+ /* TODO: Perhaps prompt if you're overwriting a cert? */
+
+ purple_certificate_pool_store(purple_certificate_find_pool("x509", "tls_peers"), id, crt);
+ purple_certificate_destroy(crt);
+}
+
+static void
+tls_peers_mgmt_import_cancel2_cb(gpointer data, const char *result)
+{
+ PurpleCertificate *crt = (PurpleCertificate *) data;
+ purple_certificate_destroy(crt);
+}
+
+static void
+tls_peers_mgmt_import_ok_cb(gpointer data, const char *filename)
+{
+ PurpleCertificateScheme *x509;
+ PurpleCertificate *crt;
+
+ x509 = purple_certificate_pool_get_scheme(purple_certificate_find_pool("x509", "tls_peers"));
+
+ crt = purple_certificate_import(x509, filename);
+
+ if (crt != NULL) {
+ gchar *default_hostname;
+ default_hostname = purple_certificate_get_subject_name(crt);
+ purple_request_input(NULL,
+ _("Certificate Import"),
+ _("Specify a hostname"),
+ _("Type the host name this certificate is for."),
+ default_hostname, FALSE, FALSE, NULL,
+ _("OK"), G_CALLBACK(tls_peers_mgmt_import_ok2_cb),
+ _("Cancel"), G_CALLBACK(tls_peers_mgmt_import_cancel2_cb),
+ NULL, NULL, NULL,
+ crt);
+ g_free(default_hostname);
+ } else {
+ gchar * secondary;
+ secondary = g_strdup_printf(_("File %s could not be imported.\nMake sure that the file is readable and in PEM format.\n"), filename);
+ purple_notify_error(NULL,
+ _("Certificate Import Error"),
+ _("X.509 certificate import failed"),
+ secondary);
+ g_free(secondary);
+ }
+}
+
+static void
+add_cert_cb(GntWidget *button, gpointer null)
+{
+ purple_request_file(NULL,
+ _("Select a PEM certificate"),
+ "certificate.pem",
+ FALSE,
+ G_CALLBACK(tls_peers_mgmt_import_ok_cb),
+ NULL,
+ NULL, NULL, NULL, NULL );
+}
+
+/* Save certs in some file */
+static void
+tls_peers_mgmt_export_ok_cb(gpointer data, const char *filename)
+{
+ PurpleCertificate *crt = (PurpleCertificate *) data;
+
+ if (!purple_certificate_export(filename, crt)) {
+ gchar * secondary;
+
+ secondary = g_strdup_printf(_("Export to file %s failed.\nCheck that you have write permission to the target path\n"), filename);
+ purple_notify_error(NULL,
+ _("Certificate Export Error"),
+ _("X.509 certificate export failed"),
+ secondary);
+ g_free(secondary);
+ }
+
+ purple_certificate_destroy(crt);
+}
+
+static void
+save_cert_cb(GntWidget *button, gpointer null)
+{
+ PurpleCertificate *crt;
+ const char *key;
+
+ if (!certmgr.window)
+ return;
+
+ key = gnt_tree_get_selection_data(GNT_TREE(certmgr.tree));
+ if (!key)
+ return;
+
+ crt = purple_certificate_pool_retrieve(certmgr.pool, key);
+ if (!crt) {
+ purple_debug_error("gntcertmgr/tls_peers_mgmt",
+ "Id %s was not in the peers cache?!\n", key);
+ return;
+ }
+
+ purple_request_file((void*)key,
+ _("PEM X.509 Certificate Export"),
+ "certificate.pem", TRUE,
+ G_CALLBACK(tls_peers_mgmt_export_ok_cb),
+ G_CALLBACK(purple_certificate_destroy),
+ NULL, NULL, NULL,
+ crt);
+}
+
+/* Show information about a cert */
+static void
+info_cert_cb(GntWidget *button, gpointer null)
+{
+ const char *key;
+ PurpleCertificate *crt;
+ gchar *subject;
+ GByteArray *fpr_sha1;
+ gchar *fpr_sha1_asc;
+ gchar *primary, *secondary;
+
+ if (!certmgr.window)
+ return;
+
+ key = gnt_tree_get_selection_data(GNT_TREE(certmgr.tree));
+ if (!key)
+ return;
+
+ crt = purple_certificate_pool_retrieve(certmgr.pool, key);
+ g_return_if_fail(crt);
+
+ primary = g_strdup_printf(_("Certificate for %s"), key);
+
+ fpr_sha1 = purple_certificate_get_fingerprint_sha1(crt);
+ fpr_sha1_asc = purple_base16_encode_chunked(fpr_sha1->data,
+ fpr_sha1->len);
+ subject = purple_certificate_get_subject_name(crt);
+
+ secondary = g_strdup_printf(_("Common name: %s\n\nSHA1 fingerprint:\n%s"), subject, fpr_sha1_asc);
+
+ purple_notify_info(NULL,
+ _("SSL Host Certificate"), primary, secondary);
+
+ g_free(primary);
+ g_free(secondary);
+ g_byte_array_free(fpr_sha1, TRUE);
+ g_free(fpr_sha1_asc);
+ g_free(subject);
+ purple_certificate_destroy(crt);
+}
+
+/* Delete a cert */
+static void
+tls_peers_mgmt_delete_confirm_cb(gchar *id, gint dontcare)
+{
+ if (!purple_certificate_pool_delete(certmgr.pool, id)) {
+ purple_debug_warning("gntcertmgr/tls_peers_mgmt",
+ "Deletion failed on id %s\n", id);
+ };
+
+ g_free(id);
+}
+
+static void
+delete_cert_cb(GntWidget *button, gpointer null)
+{
+ gchar *primary;
+ const char *key;
+
+ if (!certmgr.window)
+ return;
+
+ key = gnt_tree_get_selection_data(GNT_TREE(certmgr.tree));
+ if (!key)
+ return;
+
+ primary = g_strdup_printf(_("Really delete certificate for %s?"), key);
+
+ purple_request_close_with_handle((void *)key);
+ purple_request_yes_no((void *)key, _("Confirm certificate delete"),
+ primary, NULL,
+ 2,
+ NULL, NULL, NULL,
+ g_strdup(key),
+ tls_peers_mgmt_delete_confirm_cb,
+ g_free);
+
+ g_free(primary);
+}
+
+/* populate the list */
+static void
+populate_cert_list()
+{
+ GList *idlist, *l;
+
+ if (!certmgr.window)
+ return;
+
+ gnt_tree_remove_all(GNT_TREE(certmgr.tree));
+
+ idlist = purple_certificate_pool_get_idlist(purple_certificate_find_pool("x509", "tls_peers"));
+ for (l = idlist; l; l = l->next) {
+ gnt_tree_add_row_last(GNT_TREE(certmgr.tree), g_strdup(l->data),
+ gnt_tree_create_row(GNT_TREE(certmgr.tree), l->data), NULL);
+ }
+ purple_certificate_pool_destroy_idlist(idlist);
+}
+
+static void
+cert_list_added(PurpleCertificatePool *pool, const char *id, gpointer null)
+{
+ g_return_if_fail(certmgr.window);
+ gnt_tree_add_row_last(GNT_TREE(certmgr.tree), g_strdup(id),
+ gnt_tree_create_row(GNT_TREE(certmgr.tree), id), NULL);
+}
+
+static void
+cert_list_removed(PurpleCertificatePool *pool, const char *id, gpointer null)
+{
+ g_return_if_fail(certmgr.window);
+ purple_request_close_with_handle((void*)id);
+ gnt_tree_remove(GNT_TREE(certmgr.tree), (void*)id);
+}
+
+void finch_certmgr_show(void)
+{
+ GntWidget *win, *tree, *box, *button;
+ PurpleCertificatePool *pool;
+
+ if (certmgr.window) {
+ gnt_window_present(certmgr.window);
+ return;
+ }
+
+ certmgr.window = win = gnt_vwindow_new(FALSE);
+ gnt_box_set_title(GNT_BOX(win), _("Certificate Manager"));
+ gnt_box_set_pad(GNT_BOX(win), 0);
+
+ certmgr.tree = tree = gnt_tree_new();
+ gnt_tree_set_hash_fns(GNT_TREE(tree), g_str_hash, g_str_equal, g_free);
+ gnt_tree_set_column_title(GNT_TREE(tree), 0, _("Hostname"));
+ gnt_tree_set_show_title(GNT_TREE(tree), TRUE);
+
+ gnt_box_add_widget(GNT_BOX(win), tree);
+
+ box = gnt_hbox_new(FALSE);
+ gnt_box_add_widget(GNT_BOX(win), box);
+
+ button = gnt_button_new(_("Add"));
+ gnt_box_add_widget(GNT_BOX(box), button);
+ g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(add_cert_cb), NULL);
+ gnt_util_set_trigger_widget(GNT_WIDGET(tree), GNT_KEY_INS, button);
+
+ button = gnt_button_new(_("Save"));
+ gnt_box_add_widget(GNT_BOX(box), button);
+ g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(save_cert_cb), NULL);
+
+ button = gnt_button_new(_("Info"));
+ gnt_box_add_widget(GNT_BOX(box), button);
+ g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(info_cert_cb), NULL);
+
+ button = gnt_button_new(_("Delete"));
+ gnt_box_add_widget(GNT_BOX(box), button);
+ g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(delete_cert_cb), NULL);
+ gnt_util_set_trigger_widget(GNT_WIDGET(tree), GNT_KEY_DEL, button);
+
+ button = gnt_button_new(_("Close"));
+ gnt_box_add_widget(GNT_BOX(box), button);
+ g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gnt_widget_destroy), win);
+
+ g_signal_connect_swapped(G_OBJECT(win), "destroy", G_CALLBACK(g_nullify_pointer), &certmgr.window);
+
+ populate_cert_list();
+
+ pool = certmgr.pool = purple_certificate_find_pool("x509", "tls_peers");
+ purple_signal_connect(pool, "certificate-stored",
+ win, PURPLE_CALLBACK(cert_list_added), NULL);
+ purple_signal_connect(pool, "certificate-deleted",
+ win, PURPLE_CALLBACK(cert_list_removed), NULL);
+ g_signal_connect(G_OBJECT(win), "destroy", G_CALLBACK(purple_signals_disconnect_by_handle), NULL);
+
+ gnt_widget_show(certmgr.window);
+}
+
diff --git a/finch/gntcertmgr.h b/finch/gntcertmgr.h
new file mode 100644
index 0000000000..4ad56bb8b7
--- /dev/null
+++ b/finch/gntcertmgr.h
@@ -0,0 +1,31 @@
+/**
+ * @file gntcertmgr.h GNT Certificate Manager API
+ * @ingroup finch
+ *
+ * finch
+ *
+ * Finch is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef _GNT_CERTMGR_H
+#define _GNT_CERTMGR_H
+
+void finch_certmgr_show(void);
+
+#endif
diff --git a/finch/gntconv.c b/finch/gntconv.c
index 0d042d942b..b4af38545d 100644
--- a/finch/gntconv.c
+++ b/finch/gntconv.c
@@ -1006,6 +1006,7 @@ clear_command_cb(PurpleConversation *conv,
{
FinchConv *ggconv = conv->ui_data;
gnt_text_view_clear(GNT_TEXT_VIEW(ggconv->tv));
+ purple_conversation_clear_message_history(conv);
return PURPLE_CMD_STATUS_OK;
}
diff --git a/finch/gntrequest.c b/finch/gntrequest.c
index 18c04e25f8..c84c129ff3 100644
--- a/finch/gntrequest.c
+++ b/finch/gntrequest.c
@@ -198,7 +198,7 @@ request_choice_cb(GntWidget *button, GntComboBox *combo)
static void *
finch_request_choice(const char *title, const char *primary,
- const char *secondary, unsigned int default_value,
+ const char *secondary, int default_value,
const char *ok_text, GCallback ok_cb,
const char *cancel_text, GCallback cancel_cb,
PurpleAccount *account, const char *who, PurpleConversation *conv,
@@ -244,7 +244,7 @@ request_action_cb(GntWidget *button, GntWidget *window)
static void*
finch_request_action(const char *title, const char *primary,
- const char *secondary, unsigned int default_value,
+ const char *secondary, int default_value,
PurpleAccount *account, const char *who, PurpleConversation *conv,
void *user_data, size_t actioncount,
va_list actions)
diff --git a/finch/gntui.c b/finch/gntui.c
index c69b2c7949..266815cfda 100644
--- a/finch/gntui.c
+++ b/finch/gntui.c
@@ -25,6 +25,7 @@
#include "gntaccount.h"
#include "gntblist.h"
+#include "gntcertmgr.h"
#include "gntconn.h"
#include "gntconv.h"
#include "gntdebug.h"
@@ -81,6 +82,7 @@ void gnt_ui_init()
gnt_register_action(_("Accounts"), finch_accounts_show_all);
gnt_register_action(_("Buddy List"), finch_blist_show);
gnt_register_action(_("Buddy Pounces"), finch_pounces_manager_show);
+ gnt_register_action(_("Certificates"), finch_certmgr_show);
gnt_register_action(_("Debug Window"), finch_debug_window_show);
gnt_register_action(_("File Transfers"), finch_xfer_dialog_show);
gnt_register_action(_("Plugins"), finch_plugins_show_all);
diff --git a/finch/libgnt/pygnt/dbus-gnt b/finch/libgnt/pygnt/dbus-gnt
index 8c0d3bfa22..00351ed083 100755
--- a/finch/libgnt/pygnt/dbus-gnt
+++ b/finch/libgnt/pygnt/dbus-gnt
@@ -13,7 +13,7 @@ import os
import gnt
import sys
-from time import strftime
+import time
convwins = {}
@@ -27,19 +27,26 @@ def conv_closed(conv):
# if a conv window is closed, then reopened, this thing crashes
convwins[key] = None
-def wrote_msg(account, who, msg, conv, flags):
- stuff = show_conversation(conv)
+def add_message(conv, who, msg, flags, timestamp):
+ stuff = show_conversation(conv, False)
tv = stuff[1]
tv.append_text_with_flags("\n", 0)
- tv.append_text_with_flags(strftime("(%X) "), 8)
+ if timestamp:
+ tv.append_text_with_flags(time.strftime("(%X) ", time.localtime(timestamp)), 8)
+ else:
+ tv.append_text_with_flags(time.strftime("(%X) "), 8)
if flags & 3:
tv.append_text_with_flags(who + ": ", 1)
+ msg = purple.PurpleMarkupStripHtml(msg)
tv.append_text_with_flags(msg, 0)
stuff[0].set_urgent()
else:
tv.append_text_with_flags(msg, 8)
tv.scroll(0)
+def wrote_msg(account, who, msg, conv, flags):
+ add_message(conv, who, msg, flags, None)
+
bus = dbus.SessionBus()
obj = bus.get_object("im.pidgin.purple.PurpleService", "/im/pidgin/purple/PurpleObject")
purple = dbus.Interface(obj, "im.pidgin.purple.PurpleInterface")
@@ -79,7 +86,7 @@ def send_im_cb(entry, key, conv):
def conv_window_destroyed(win, key):
del convwins[key]
-def show_conversation(conv):
+def show_conversation(conv, history):
key = get_dict_key(conv)
if key in convwins:
return convwins[key]
@@ -96,9 +103,21 @@ def show_conversation(conv):
vbox.add_widget(entry)
entry.connect("key_pressed", send_im_cb, conv)
tv.clear()
+ tv.attach_scroll_widget(entry)
win.show()
convwins[key] = [win, tv, entry]
win.connect("destroy", conv_window_destroyed, key)
+
+ if history:
+ msgs = purple.PurpleConversationGetMessageHistory(conv)
+ msgs.reverse()
+ for msg in msgs:
+ who = purple.PurpleConversationMessageGetSender(msg)
+ what = purple.PurpleConversationMessageGetMessage(msg)
+ flags = purple.PurpleConversationMessageGetFlags(msg)
+ when = purple.PurpleConversationMessageGetTimestamp(msg)
+ add_message(conv, who, what, flags, when)
+
return convwins[key]
def show_buddylist():
@@ -127,7 +146,7 @@ gnt.gnt_init()
convs = purple.PurpleGetConversations()
for conv in convs:
- show_conversation(conv)
+ show_conversation(conv, True)
gnt.gnt_main()
diff --git a/finch/libgnt/pygnt/gendef.sh b/finch/libgnt/pygnt/gendef.sh
index c50caff155..b3ccbd78ae 100755
--- a/finch/libgnt/pygnt/gendef.sh
+++ b/finch/libgnt/pygnt/gendef.sh
@@ -31,7 +31,9 @@ FILES="
rm -f gnt.def
for file in $FILES
do
+ echo -n "Generating definitions for ${file} ... "
python /usr/share/pygtk/2.0/codegen/h2def.py ../$file >> gnt.def
+ echo "Done"
done
# Remove the definitions about the enums
diff --git a/libpurple/Makefile.am b/libpurple/Makefile.am
index 7f89fa8873..8e6548ffd1 100644
--- a/libpurple/Makefile.am
+++ b/libpurple/Makefile.am
@@ -22,9 +22,9 @@ EXTRA_DIST = \
win32/giowin32.c \
win32/win32dep.h
-# if USE_GCONFTOOL
-# GCONF_DIR=gconf
-# endif
+if USE_GCONFTOOL
+GCONF_DIR=gconf
+endif
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = purple.pc
diff --git a/libpurple/certificate.c b/libpurple/certificate.c
index 240e48e471..39a64e0c2b 100644
--- a/libpurple/certificate.c
+++ b/libpurple/certificate.c
@@ -30,6 +30,7 @@
#include "internal.h"
#include "certificate.h"
+#include "dbus-maybe.h"
#include "debug.h"
#include "request.h"
#include "signals.h"
@@ -1124,6 +1125,18 @@ x509_tls_cached_user_auth_cb (x509_tls_cached_ua_ctx *c, gint id)
}
}
+static void
+x509_tls_cached_user_auth_accept_cb(x509_tls_cached_ua_ctx *c, gint ignore)
+{
+ x509_tls_cached_user_auth_cb(c, 2);
+}
+
+static void
+x509_tls_cached_user_auth_reject_cb(x509_tls_cached_ua_ctx *c, gint ignore)
+{
+ x509_tls_cached_user_auth_cb(c, 1);
+}
+
/** Validates a certificate by asking the user
* @param reason String to explain why the user needs to accept/refuse the
* certificate.
@@ -1151,8 +1164,8 @@ x509_tls_cached_user_auth(PurpleCertificateVerificationRequest *vrq,
NULL, /* No associated conversation */
x509_tls_cached_ua_ctx_new(vrq, reason),
3, /* Number of actions */
- _("Yes"), x509_tls_cached_user_auth_cb,
- _("No"), x509_tls_cached_user_auth_cb,
+ _("Accept"), x509_tls_cached_user_auth_accept_cb,
+ _("Reject"), x509_tls_cached_user_auth_reject_cb,
_("_View Certificate..."), x509_tls_cached_show_cert);
/* Cleanup */
@@ -1192,7 +1205,14 @@ x509_tls_cached_cert_in_cache(PurpleCertificateVerificationRequest *vrq)
/* Load up the cached certificate */
cached_crt = purple_certificate_pool_retrieve(
tls_peers, vrq->subject_name);
- g_assert(cached_crt);
+ if ( !cached_crt ) {
+ purple_debug_error("certificate/x509/tls_cached",
+ "Lookup failed on cached certificate!\n"
+ "It was here just a second ago. Forwarding "
+ "to cert_changed.\n");
+ /* vrq now becomes the problem of cert_changed */
+ x509_tls_cached_peer_cert_changed(vrq);
+ }
/* Now get SHA1 sums for both and compare them */
/* TODO: This is not an elegant way to compare certs */
@@ -1325,7 +1345,14 @@ x509_tls_cached_unknown_peer(PurpleCertificateVerificationRequest *vrq)
ca_crt = purple_certificate_pool_retrieve(ca, ca_id);
g_free(ca_id);
- g_assert(ca_crt);
+ if (!ca_crt) {
+ purple_debug_error("certificate/x509/tls_cached",
+ "Certificate authority disappeared out "
+ "underneath me!\n");
+ purple_certificate_verify_complete(vrq,
+ PURPLE_CERTIFICATE_INVALID);
+ return;
+ }
/* Check the signature */
if ( !purple_certificate_signed_by(end_crt, ca_crt) ) {
@@ -1362,9 +1389,11 @@ x509_tls_cached_unknown_peer(PurpleCertificateVerificationRequest *vrq)
"tls_peers");
if (tls_peers) {
- g_assert(purple_certificate_pool_store(tls_peers,
- vrq->subject_name,
- peer_crt) );
+ if (!purple_certificate_pool_store(tls_peers,vrq->subject_name,
+ peer_crt) ) {
+ purple_debug_error("certificate/x509/tls_cached",
+ "FAILED to cache peer certificate\n");
+ }
} else {
purple_debug_error("certificate/x509/tls_cached",
"Unable to locate tls_peers certificate "
@@ -1700,6 +1729,7 @@ purple_certificate_register_pool(PurpleCertificatePool *pool)
/* TODO: Emit a signal that the pool got registered */
+ PURPLE_DBUS_REGISTER_POINTER(pool, PurpleCertificatePool);
purple_signal_register(pool, /* Signals emitted from pool */
"certificate-stored",
purple_marshal_VOID__POINTER_POINTER,
@@ -1748,6 +1778,7 @@ purple_certificate_unregister_pool(PurpleCertificatePool *pool)
}
/* Uninit the pool if needed */
+ PURPLE_DBUS_UNREGISTER_POINTER(pool);
if (pool->uninit) {
pool->uninit();
}
@@ -1775,7 +1806,6 @@ purple_certificate_display_x509(PurpleCertificate *crt)
GByteArray *sha_bin;
gchar *cn;
time_t activation, expiration;
- /* Length of these buffers is dictated by 'man ctime_r' */
gchar *activ_str, *expir_str;
gchar *secondary;
@@ -1792,7 +1822,11 @@ purple_certificate_display_x509(PurpleCertificate *crt)
/* Get the certificate times */
/* TODO: Check the times against localtime */
/* TODO: errorcheck? */
- g_assert(purple_certificate_get_times(crt, &activation, &expiration));
+ if (!purple_certificate_get_times(crt, &activation, &expiration)) {
+ purple_debug_error("certificate",
+ "Failed to get certificate times!\n");
+ activation = expiration = 0;
+ }
activ_str = g_strdup(ctime(&activation));
expir_str = g_strdup(ctime(&expiration));
@@ -1819,6 +1853,3 @@ purple_certificate_display_x509(PurpleCertificate *crt)
g_byte_array_free(sha_bin, TRUE);
}
-
-
-
diff --git a/libpurple/conversation.c b/libpurple/conversation.c
index f596e86a51..eaa53fff9f 100644
--- a/libpurple/conversation.c
+++ b/libpurple/conversation.c
@@ -39,6 +39,7 @@ static GList *conversations = NULL;
static GList *ims = NULL;
static GList *chats = NULL;
static PurpleConversationUiOps *default_ops = NULL;
+static GHashTable *histories = NULL;
void
purple_conversations_set_ui_ops(PurpleConversationUiOps *ops)
@@ -111,17 +112,17 @@ common_send(PurpleConversation *conv, const char *message, PurpleMessageFlags ms
/* Always linkfy the text for display, unless we're
* explicitly asked to do otheriwse*/
- if(msgflags & PURPLE_MESSAGE_NO_LINKIFY)
- displayed = g_strdup(message);
- else
- displayed = purple_markup_linkify(message);
+ if (!(msgflags & PURPLE_MESSAGE_INVISIBLE)) {
+ if(msgflags & PURPLE_MESSAGE_NO_LINKIFY)
+ displayed = g_strdup(message);
+ else
+ displayed = purple_markup_linkify(message);
+ }
- if ((conv->features & PURPLE_CONNECTION_HTML) &&
- !(msgflags & PURPLE_MESSAGE_RAW))
- {
+ if (displayed && (conv->features & PURPLE_CONNECTION_HTML) &&
+ !(msgflags & PURPLE_MESSAGE_RAW)) {
sent = g_strdup(displayed);
- }
- else
+ } else
sent = g_strdup(message);
msgflags |= PURPLE_MESSAGE_SEND;
@@ -202,6 +203,51 @@ open_log(PurpleConversation *conv)
conv, time(NULL), NULL));
}
+/* Functions that deal with PurpleConvMessage */
+
+static void
+add_message_to_history(PurpleConversation *conv, const char *who, const char *message,
+ PurpleMessageFlags flags, time_t when)
+{
+ GList *list;
+ PurpleConvMessage *msg;
+
+ if (flags & PURPLE_MESSAGE_SEND) {
+ const char *me = NULL;
+ if (conv->account->gc)
+ me = conv->account->gc->display_name;
+ if (!me)
+ me = conv->account->username;
+ who = me;
+ }
+
+ msg = g_new0(PurpleConvMessage, 1);
+ PURPLE_DBUS_REGISTER_POINTER(msg, PurpleConvMessage);
+ msg->who = g_strdup(who);
+ msg->flags = flags;
+ msg->what = g_strdup(message);
+ msg->when = when;
+
+ list = g_hash_table_lookup(histories, conv);
+ list = g_list_prepend(list, msg);
+ g_hash_table_insert(histories, conv, list);
+}
+
+static void
+free_conv_message(PurpleConvMessage *msg)
+{
+ g_free(msg->who);
+ g_free(msg->what);
+ PURPLE_DBUS_UNREGISTER_POINTER(msg);
+ g_free(msg);
+}
+
+static void
+message_history_free(GList *list)
+{
+ g_list_foreach(list, (GFunc)free_conv_message, NULL);
+ g_list_free(list);
+}
/**************************************************************************
* Conversation API
@@ -473,6 +519,8 @@ purple_conversation_destroy(PurpleConversation *conv)
purple_conversation_close_logs(conv);
+ purple_conversation_clear_message_history(conv);
+
PURPLE_DBUS_UNREGISTER_POINTER(conv);
g_free(conv);
conv = NULL;
@@ -805,9 +853,6 @@ purple_conversation_write(PurpleConversation *conv, const char *who,
ops = purple_conversation_get_ui_ops(conv);
- if (ops == NULL || ops->write_conv == NULL)
- return;
-
account = purple_conversation_get_account(conv);
type = purple_conversation_get_type(conv);
@@ -891,7 +936,9 @@ purple_conversation_write(PurpleConversation *conv, const char *who,
}
}
- ops->write_conv(conv, who, alias, displayed, flags, mtime);
+ if (ops && ops->write_conv)
+ ops->write_conv(conv, who, alias, displayed, flags, mtime);
+ add_message_to_history(conv, who, message, flags, mtime);
purple_signal_emit(purple_conversations_get_handle(),
(type == PURPLE_CONV_TYPE_IM ? "wrote-im-msg" : "wrote-chat-msg"),
@@ -2020,6 +2067,42 @@ purple_conversation_get_extended_menu(PurpleConversation *conv)
return menu;
}
+void purple_conversation_clear_message_history(PurpleConversation *conv)
+{
+ GList *list = g_hash_table_lookup(histories, conv);
+ message_history_free(list);
+ g_hash_table_remove(histories, conv);
+}
+
+GList *purple_conversation_get_message_history(PurpleConversation *conv)
+{
+ return g_hash_table_lookup(histories, conv);
+}
+
+const char *purple_conversation_message_get_sender(PurpleConvMessage *msg)
+{
+ g_return_val_if_fail(msg, NULL);
+ return msg->who;
+}
+
+const char *purple_conversation_message_get_message(PurpleConvMessage *msg)
+{
+ g_return_val_if_fail(msg, NULL);
+ return msg->what;
+}
+
+PurpleMessageFlags purple_conversation_message_get_flags(PurpleConvMessage *msg)
+{
+ g_return_val_if_fail(msg, 0);
+ return msg->flags;
+}
+
+time_t purple_conversation_message_get_timestamp(PurpleConvMessage *msg)
+{
+ g_return_val_if_fail(msg, 0);
+ return msg->when;
+}
+
gboolean
purple_conversation_do_command(PurpleConversation *conv, const gchar *cmdline,
const gchar *markup, gchar **error)
@@ -2300,6 +2383,9 @@ purple_conversations_init(void)
purple_value_new(PURPLE_TYPE_SUBTYPE,
PURPLE_SUBTYPE_CONVERSATION),
purple_value_new(PURPLE_TYPE_BOXED, "GList **"));
+
+ /* Initialize the history */
+ histories = g_hash_table_new(g_direct_hash, g_direct_equal);
}
void
@@ -2308,4 +2394,6 @@ purple_conversations_uninit(void)
while (conversations)
purple_conversation_destroy((PurpleConversation*)conversations->data);
purple_signals_unregister_by_instance(purple_conversations_get_handle());
+ g_hash_table_destroy(histories);
+ histories = NULL;
}
diff --git a/libpurple/conversation.h b/libpurple/conversation.h
index 97b37b1f8e..78b599d47a 100644
--- a/libpurple/conversation.h
+++ b/libpurple/conversation.h
@@ -37,6 +37,7 @@ typedef struct _PurpleConversation PurpleConversation;
typedef struct _PurpleConvIm PurpleConvIm;
typedef struct _PurpleConvChat PurpleConvChat;
typedef struct _PurpleConvChatBuddy PurpleConvChatBuddy;
+typedef struct _PurpleConvMessage PurpleConvMessage;
/**
* A type of conversation.
@@ -117,9 +118,9 @@ typedef enum
apply formatting */
PURPLE_MESSAGE_IMAGES = 0x1000, /**< Message contains images */
PURPLE_MESSAGE_NOTIFY = 0x2000, /**< Message is a notification */
- PURPLE_MESSAGE_NO_LINKIFY = 0x4000 /**< Message should not be auto-
+ PURPLE_MESSAGE_NO_LINKIFY = 0x4000, /**< Message should not be auto-
linkified */
-
+ PURPLE_MESSAGE_INVISIBLE = 0x8000, /**< Message should not be displayed */
} PurpleMessageFlags;
/**
@@ -283,6 +284,17 @@ struct _PurpleConvChatBuddy
};
/**
+ * Description of a conversation message
+ */
+struct _PurpleConvMessage
+{
+ char *who;
+ char *what;
+ PurpleMessageFlags flags;
+ time_t when;
+};
+
+/**
* A core representation of a conversation between two or more people.
*
* The conversation can be an IM or a chat.
@@ -650,6 +662,60 @@ void purple_conversation_update(PurpleConversation *conv, PurpleConvUpdateType t
*/
void purple_conversation_foreach(void (*func)(PurpleConversation *conv));
+/**
+ * Retrieve the message history of a conversation.
+ *
+ * @param conv The conversation
+ *
+ * @return A GList of PurpleConvMessage's. The must not modify the list or the data within.
+ * The list contains the newest message at the beginning, and the oldest message at
+ * the end.
+ */
+GList *purple_conversation_get_message_history(PurpleConversation *conv);
+
+/**
+ * Clear the message history of a conversation.
+ *
+ * @param conv The conversation
+ */
+void purple_conversation_clear_message_history(PurpleConversation *conv);
+
+/**
+ * Get the sender from a PurpleConvMessage
+ *
+ * @param msg A PurpleConvMessage
+ *
+ * @return The name of the sender of the message
+ */
+const char *purple_conversation_message_get_sender(PurpleConvMessage *msg);
+
+/**
+ * Get the message from a PurpleConvMessage
+ *
+ * @param msg A PurpleConvMessage
+ *
+ * @return The name of the sender of the message
+ */
+const char *purple_conversation_message_get_message(PurpleConvMessage *msg);
+
+/**
+ * Get the message-flags of a PurpleConvMessage
+ *
+ * @param msg A PurpleConvMessage
+ *
+ * @return The name of the sender of the message
+ */
+PurpleMessageFlags purple_conversation_message_get_flags(PurpleConvMessage *msg);
+
+/**
+ * Get the timestamp of a PurpleConvMessage
+ *
+ * @param msg A PurpleConvMessage
+ *
+ * @return The name of the sender of the message
+ */
+time_t purple_conversation_message_get_timestamp(PurpleConvMessage *msg);
+
/*@}*/
diff --git a/libpurple/core.c b/libpurple/core.c
index 5f1e31739f..956eaaa173 100644
--- a/libpurple/core.c
+++ b/libpurple/core.c
@@ -161,9 +161,8 @@ purple_core_init(const char *ui)
/*
* Call this early on to try to auto-detect our IP address and
* hopefully save some time later.
- * TODO: do this here after purple_prefs_load() has been moved into purple_prefs_init()
*/
- /*purple_network_get_my_ip(-1);*/
+ purple_network_get_my_ip(-1);
if (ops != NULL && ops->ui_init != NULL)
ops->ui_init();
diff --git a/libpurple/dbus-analyze-functions.py b/libpurple/dbus-analyze-functions.py
index 36a0667a78..2a18f5e5c0 100644
--- a/libpurple/dbus-analyze-functions.py
+++ b/libpurple/dbus-analyze-functions.py
@@ -66,6 +66,7 @@ constlists = [
"purple_savedstatuses_get_all",
"purple_status_type_get_attrs",
"purple_presence_get_statuses",
+ "purple_conversation_get_message_history",
]
pointer = "#pointer#"
diff --git a/libpurple/example/nullclient.c b/libpurple/example/nullclient.c
index 1ed4c1eb0a..894e7d5fa9 100644
--- a/libpurple/example/nullclient.c
+++ b/libpurple/example/nullclient.c
@@ -197,7 +197,7 @@ init_libpurple()
purple_util_set_user_dir(CUSTOM_USER_DIRECTORY);
/* We do not want any debugging for now to keep the noise to a minimum. */
- purple_debug_set_enabled(TRUE);
+ purple_debug_set_enabled(FALSE);
/* Set the core-uiops, which is used to
* - initialize the ui specific preferences.
@@ -257,24 +257,6 @@ connect_to_signals_for_demonstration_purposes_only()
PURPLE_CALLBACK(signed_on), NULL);
}
-
-
-
-void signedOn( PurpleConnection *gc, gpointer dummy ) {
-
-
- if( gc ) {
-
- PurpleAccount* a = purple_connection_get_account( gc );
-
- if( a ) {
-
- purple_presence_set_idle( purple_account_get_presence( a ), TRUE, time( NULL ) );
- }
- }
-}
-
-
int main()
{
GList *iter;
@@ -300,26 +282,30 @@ int main()
names = g_list_append(names, info->id);
}
}
+ printf("Select the protocol [0-%d]: ", i-1);
+ fgets(name, sizeof(name), stdin);
+ sscanf(name, "%d", &num);
+ prpl = g_list_nth_data(names, num);
+
+ printf("Username: ");
+ fgets(name, sizeof(name), stdin);
+ name[strlen(name) - 1] = 0; /* strip the \n at the end */
/* Create the account */
- account = purple_account_new("msimprpl@xyzzy.cjb.net", "prpl-myspace" );
- purple_account_set_password(account, "4224jc" );
+ account = purple_account_new(name, prpl);
+
+ /* Get the password for the account */
+ password = getpass("Password: ");
+ purple_account_set_password(account, password);
/* It's necessary to enable the account first. */
purple_account_set_enabled(account, UI_ID, TRUE);
-#if 0
- static int handle;
- purple_signal_connect( purple_connections_get_handle(),
- "signed-on", &handle,
- PURPLE_CALLBACK( signedOn ),
- NULL );
-
/* Now, to connect the account(s), create a status and activate it. */
- purple_savedstatus_activate( purple_savedstatus_get_default() );
+ status = purple_savedstatus_new(NULL, PURPLE_STATUS_AVAILABLE);
+ purple_savedstatus_activate(status);
connect_to_signals_for_demonstration_purposes_only();
-#endif
g_main_loop_run(loop);
diff --git a/libpurple/plugins/ssl/ssl-gnutls.c b/libpurple/plugins/ssl/ssl-gnutls.c
index d74aa7fa4a..e028ce3278 100644
--- a/libpurple/plugins/ssl/ssl-gnutls.c
+++ b/libpurple/plugins/ssl/ssl-gnutls.c
@@ -60,7 +60,7 @@ ssl_gnutls_init_gnutls(void)
(gnutls_realloc_function) g_realloc, /* realloc */
(gnutls_free_function) g_free /* free */
);
-
+
gnutls_global_init();
gnutls_certificate_allocate_credentials(&xcred);
@@ -73,7 +73,7 @@ ssl_gnutls_init_gnutls(void)
static gboolean
ssl_gnutls_init(void)
{
- return TRUE;
+ return TRUE;
}
static void
@@ -130,17 +130,18 @@ static void ssl_gnutls_handshake_cb(gpointer data, gint source,
purple_ssl_close(gsc);
} else {
- purple_debug_info("gnutls", "Handshake complete\n");
-
- /* TODO: Remove all this debugging babble */
/* Now we are cooking with gas! */
PurpleSslOps *ops = purple_ssl_get_ops();
GList * peers = ops->get_peer_certificates(gsc);
-
+
PurpleCertificateScheme *x509 =
purple_certificate_find_scheme("x509");
GList * l;
+
+ /* TODO: Remove all this debugging babble */
+ purple_debug_info("gnutls", "Handshake complete\n");
+
for (l=peers; l; l = l->next) {
PurpleCertificate *crt = l->data;
GByteArray *z =
@@ -155,72 +156,71 @@ static void ssl_gnutls_handshake_cb(gpointer data, gint source,
/* Kill the cert! */
x509->destroy_certificate(crt);
-
+
g_free(fpr);
g_byte_array_free(z, TRUE);
}
g_list_free(peers);
-
+
{
- const gnutls_datum_t *cert_list;
- unsigned int cert_list_size = 0;
- gnutls_session_t session=gnutls_data->session;
-
- cert_list =
- gnutls_certificate_get_peers(session, &cert_list_size);
-
- purple_debug_info("gnutls",
- "Peer provided %d certs\n",
- cert_list_size);
- int i;
- for (i=0; i<cert_list_size; i++)
- {
- gchar fpr_bin[256];
- gsize fpr_bin_sz = sizeof(fpr_bin);
- gchar * fpr_asc = NULL;
- gchar tbuf[256];
- gsize tsz=sizeof(tbuf);
- gchar * tasc = NULL;
- gnutls_x509_crt_t cert;
-
- gnutls_x509_crt_init(&cert);
- gnutls_x509_crt_import (cert, &cert_list[i],
- GNUTLS_X509_FMT_DER);
-
- gnutls_x509_crt_get_fingerprint(cert, GNUTLS_MAC_SHA,
- fpr_bin, &fpr_bin_sz);
-
- fpr_asc =
- purple_base16_encode_chunked(fpr_bin,fpr_bin_sz);
-
- purple_debug_info("gnutls",
- "Lvl %d SHA1 fingerprint: %s\n",
- i, fpr_asc);
-
- tsz=sizeof(tbuf);
- gnutls_x509_crt_get_serial(cert,tbuf,&tsz);
- tasc=
- purple_base16_encode_chunked(tbuf, tsz);
- purple_debug_info("gnutls",
- "Serial: %s\n",
- tasc);
- g_free(tasc);
-
- tsz=sizeof(tbuf);
- gnutls_x509_crt_get_dn (cert, tbuf, &tsz);
- purple_debug_info("gnutls",
- "Cert DN: %s\n",
- tbuf);
- tsz=sizeof(tbuf);
- gnutls_x509_crt_get_issuer_dn (cert, tbuf, &tsz);
- purple_debug_info("gnutls",
- "Cert Issuer DN: %s\n",
- tbuf);
-
- g_free(fpr_asc); fpr_asc = NULL;
- gnutls_x509_crt_deinit(cert);
- }
-
+ const gnutls_datum_t *cert_list;
+ unsigned int cert_list_size = 0;
+ gnutls_session_t session=gnutls_data->session;
+ int i;
+
+ cert_list =
+ gnutls_certificate_get_peers(session, &cert_list_size);
+
+ purple_debug_info("gnutls",
+ "Peer provided %d certs\n",
+ cert_list_size);
+ for (i=0; i<cert_list_size; i++)
+ {
+ gchar fpr_bin[256];
+ gsize fpr_bin_sz = sizeof(fpr_bin);
+ gchar * fpr_asc = NULL;
+ gchar tbuf[256];
+ gsize tsz=sizeof(tbuf);
+ gchar * tasc = NULL;
+ gnutls_x509_crt_t cert;
+
+ gnutls_x509_crt_init(&cert);
+ gnutls_x509_crt_import (cert, &cert_list[i],
+ GNUTLS_X509_FMT_DER);
+
+ gnutls_x509_crt_get_fingerprint(cert, GNUTLS_MAC_SHA,
+ fpr_bin, &fpr_bin_sz);
+
+ fpr_asc =
+ purple_base16_encode_chunked((const guchar *)fpr_bin, fpr_bin_sz);
+
+ purple_debug_info("gnutls",
+ "Lvl %d SHA1 fingerprint: %s\n",
+ i, fpr_asc);
+
+ tsz=sizeof(tbuf);
+ gnutls_x509_crt_get_serial(cert,tbuf,&tsz);
+ tasc=purple_base16_encode_chunked((const guchar *)tbuf, tsz);
+ purple_debug_info("gnutls",
+ "Serial: %s\n",
+ tasc);
+ g_free(tasc);
+
+ tsz=sizeof(tbuf);
+ gnutls_x509_crt_get_dn (cert, tbuf, &tsz);
+ purple_debug_info("gnutls",
+ "Cert DN: %s\n",
+ tbuf);
+ tsz=sizeof(tbuf);
+ gnutls_x509_crt_get_issuer_dn (cert, tbuf, &tsz);
+ purple_debug_info("gnutls",
+ "Cert Issuer DN: %s\n",
+ tbuf);
+
+ g_free(fpr_asc);
+ fpr_asc = NULL;
+ gnutls_x509_crt_deinit(cert);
+ }
}
/* TODO: The following logic should really be in libpurple */
@@ -378,7 +378,7 @@ ssl_gnutls_get_peer_certificates(PurpleSslConnection * gsc)
unsigned int cert_list_size = 0;
unsigned int i;
-
+
/* This should never, ever happen. */
g_return_val_if_fail( gnutls_certificate_type_get (gnutls_data->session) == GNUTLS_CRT_X509, NULL);
@@ -426,12 +426,14 @@ x509_crtdata_addref(x509_crtdata_t *cd)
static void
x509_crtdata_delref(x509_crtdata_t *cd)
{
- g_assert(cd->refcount > 0);
-
(cd->refcount)--;
+ if (cd->refcount < 0)
+ g_critical("Refcount of x509_crtdata_t is %d, which is less "
+ "than zero!\n", cd->refcount);
+
/* If the refcount reaches zero, kill the structure */
- if (cd->refcount == 0) {
+ if (cd->refcount <= 0) {
purple_debug_info("gnutls/x509",
"Freeing unused cert data at %p\n",
cd);
@@ -466,11 +468,11 @@ x509_import_from_datum(const gnutls_datum_t dt, gnutls_x509_crt_fmt_t mode)
certdat = g_new0(x509_crtdata_t, 1);
gnutls_x509_crt_init(&(certdat->crt));
certdat->refcount = 0;
-
+
/* Perform the actual certificate parse */
/* Yes, certdat->crt should be passed as-is */
gnutls_x509_crt_import(certdat->crt, &dt, mode);
-
+
/* Allocate the certificate and load it with data */
crt = g_new0(PurpleCertificate, 1);
crt->scheme = &x509_gnutls;
@@ -495,7 +497,7 @@ x509_import_from_file(const gchar * filename)
purple_debug_info("gnutls",
"Attempting to load X.509 certificate from %s\n",
filename);
-
+
/* Next, we'll simply yank the entire contents of the file
into memory */
/* TODO: Should I worry about very large files here? */
@@ -506,7 +508,7 @@ x509_import_from_file(const gchar * filename)
NULL /* No error checking for now */
),
NULL);
-
+
/* Load the datum struct */
dt.data = (unsigned char *) buf;
dt.size = buf_sz;
@@ -514,7 +516,7 @@ x509_import_from_file(const gchar * filename)
/* Perform the conversion */
crt = x509_import_from_datum(dt,
GNUTLS_X509_FMT_PEM); // files should be in PEM format
-
+
/* Cleanup */
g_free(buf);
@@ -571,7 +573,6 @@ x509_export_certificate(const gchar *filename, PurpleCertificate *crt)
success = purple_util_write_data_to_file_absolute(filename,
out_buf, out_size);
-
g_free(out_buf);
g_return_val_if_fail(success, FALSE);
return success;
@@ -596,10 +597,10 @@ x509_copy_certificate(PurpleCertificate *crt)
}
/** Frees a Certificate
*
- * Destroys a Certificate's internal data structures and frees the pointer
- * given.
- * @param crt Certificate instance to be destroyed. It WILL NOT be destroyed
- * if it is not of the correct CertificateScheme. Can be NULL
+ * Destroys a Certificate's internal data structures and frees the pointer
+ * given.
+ * @param crt Certificate instance to be destroyed. It WILL NOT be destroyed
+ * if it is not of the correct CertificateScheme. Can be NULL
*
*/
static void
@@ -622,7 +623,7 @@ x509_destroy_certificate(PurpleCertificate * crt)
/* Use the reference counting system to free (or not) the
underlying data */
x509_crtdata_delref((x509_crtdata_t *)crt->data);
-
+
/* Kill the structure itself */
g_free(crt);
}
@@ -643,7 +644,7 @@ x509_certificate_signed_by(PurpleCertificate * crt,
gnutls_x509_crt_t issuer_dat;
unsigned int verify; /* used to store result from GnuTLS verifier */
int ret;
-
+
g_return_val_if_fail(crt, FALSE);
g_return_val_if_fail(issuer, FALSE);
@@ -685,7 +686,7 @@ x509_certificate_signed_by(PurpleCertificate * crt,
/* The issuer is not correct, or there were errors */
return FALSE;
}
-
+
/* Now, check the signature */
/* The second argument is a ptr to an array of "trusted" issuer certs,
but we're only using one trusted one */
@@ -696,7 +697,7 @@ x509_certificate_signed_by(PurpleCertificate * crt,
current standard) */
GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT,
&verify);
-
+
if (ret != 0) {
purple_debug_error("gnutls/x509",
"Attempted certificate verification caused a GnuTLS error code %d. I will just say the signature is bad, but you should look into this.\n", ret);
@@ -713,7 +714,7 @@ x509_certificate_signed_by(PurpleCertificate * crt,
issuer_id, crt_id);
g_free(crt_id);
g_free(issuer_id);
-
+
return FALSE;
} /* if (ret, etc.) */
@@ -742,7 +743,7 @@ x509_sha1sum(PurpleCertificate *crt)
/* This shouldn't happen */
g_return_val_if_fail(tmpsz == hashlen, NULL);
-
+
/* Okay, now create and fill hash array */
hash = g_byte_array_new();
g_byte_array_append(hash, hashbuf, hashlen);
@@ -776,7 +777,7 @@ x509_cert_dn (PurpleCertificate *crt)
g_free(dn);
return NULL;
}
-
+
return dn;
}
@@ -807,7 +808,7 @@ x509_issuer_dn (PurpleCertificate *crt)
g_free(dn);
return NULL;
}
-
+
return dn;
}
@@ -848,7 +849,6 @@ x509_common_name (PurpleCertificate *crt)
return NULL;
}
-
return cn;
}
@@ -893,7 +893,7 @@ x509_times (PurpleCertificate *crt, time_t *activation, time_t *expiration)
if (*activation == errval || *expiration == errval) {
return FALSE;
}
-
+
return TRUE;
}
diff --git a/libpurple/prefs.c b/libpurple/prefs.c
index 212adf32da..f595012f14 100644
--- a/libpurple/prefs.c
+++ b/libpurple/prefs.c
@@ -1446,6 +1446,9 @@ purple_prefs_init(void)
purple_prefs_remove("/purple/contact/offline_score");
purple_prefs_remove("/purple/contact/away_score");
purple_prefs_remove("/purple/contact/idle_score");
+
+ purple_prefs_load();
+ purple_prefs_update_old();
}
void
diff --git a/libpurple/protocols/Makefile.mingw b/libpurple/protocols/Makefile.mingw
index 0ccf0232ed..602758f5f5 100644
--- a/libpurple/protocols/Makefile.mingw
+++ b/libpurple/protocols/Makefile.mingw
@@ -8,7 +8,7 @@
PIDGIN_TREE_TOP := ../..
include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
-SUBDIRS = gg irc jabber msn novell null oscar qq sametime silc10 simple yahoo bonjour myspace
+SUBDIRS = gg irc jabber msn novell null oscar qq sametime silc simple yahoo bonjour myspace
.PHONY: all install clean
diff --git a/libpurple/protocols/bonjour/issues.txt b/libpurple/protocols/bonjour/issues.txt
index 2222394449..2a4a9917cb 100644
--- a/libpurple/protocols/bonjour/issues.txt
+++ b/libpurple/protocols/bonjour/issues.txt
@@ -2,6 +2,5 @@
============= Known issues ===============
==========================================
-* Status changes don't work
* File transfers
* Typing notifications
diff --git a/libpurple/protocols/silc/Makefile.mingw b/libpurple/protocols/silc/Makefile.mingw
index 66bcffab68..557b2c3511 100644
--- a/libpurple/protocols/silc/Makefile.mingw
+++ b/libpurple/protocols/silc/Makefile.mingw
@@ -8,8 +8,8 @@ PIDGIN_TREE_TOP := ../../..
include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
TARGET = libsilc
-NEEDED_DLLS = $(SILC_TOOLKIT)/lib/silc.dll \
- $(SILC_TOOLKIT)/lib/silcclient.dll
+NEEDED_DLLS = $(SILC_TOOLKIT)/bin/libsilc-1-1-2.dll \
+ $(SILC_TOOLKIT)/bin/libsilcclient-1-1-2.dll
TYPE = PLUGIN
# Static or Plugin...
diff --git a/libpurple/protocols/silc/silc.c b/libpurple/protocols/silc/silc.c
index 70374d6714..cc3774b2ec 100644
--- a/libpurple/protocols/silc/silc.c
+++ b/libpurple/protocols/silc/silc.c
@@ -1975,9 +1975,6 @@ silc_log_debug(TRUE);
silc_log_set_debug_string("*client*");
#endif
-#ifdef _WIN32
- silc_net_win32_init();
-#endif
}
PURPLE_INIT_PLUGIN(silc, init_plugin, info);
diff --git a/libpurple/protocols/yahoo/yahoo.c b/libpurple/protocols/yahoo/yahoo.c
index cd39550f31..ec364c5dfe 100644
--- a/libpurple/protocols/yahoo/yahoo.c
+++ b/libpurple/protocols/yahoo/yahoo.c
@@ -969,7 +969,6 @@ struct yahoo_add_request {
PurpleConnection *gc;
char *id;
char *who;
- char *msg;
int protocol;
};
@@ -987,7 +986,6 @@ yahoo_buddy_add_authorize_cb(gpointer data) {
g_free(add_req->id);
g_free(add_req->who);
- g_free(add_req->msg);
g_free(add_req);
}
@@ -1018,7 +1016,6 @@ yahoo_buddy_add_deny_cb(struct yahoo_add_request *add_req, const char *msg) {
g_free(add_req->id);
g_free(add_req->who);
- g_free(add_req->msg);
g_free(add_req);
}
@@ -1132,10 +1129,18 @@ static void yahoo_buddy_auth_req_15(PurpleConnection *gc, struct yahoo_packet *p
l = l->next;
}
- if (add_req->id) {
- char *alias = NULL;
+ if (add_req->id && add_req->who) {
+ char *alias = NULL, *dec_msg = NULL;
+
+ if (!yahoo_privacy_check(gc, add_req->who)) {
+ purple_debug_misc("yahoo", "Auth. request from %s dropped and automatically denied due to privacy settings!\n",
+ add_req->who);
+ yahoo_buddy_add_deny_cb(add_req, NULL);
+ return;
+ }
+
if (msg)
- add_req->msg = yahoo_string_decode(gc, msg, FALSE);
+ dec_msg = yahoo_string_decode(gc, msg, FALSE);
if (firstname && lastname)
alias = g_strdup_printf("%s %s", firstname, lastname);
@@ -1144,20 +1149,19 @@ static void yahoo_buddy_auth_req_15(PurpleConnection *gc, struct yahoo_packet *p
else if (lastname)
alias = g_strdup(lastname);
-
/* DONE! this is almost exactly the same as what MSN does,
* this should probably be moved to the core.
*/
purple_account_request_authorization(purple_connection_get_account(gc), add_req->who, add_req->id,
- alias, add_req->msg, purple_find_buddy(purple_connection_get_account(gc),add_req->who) != NULL,
+ alias, dec_msg, purple_find_buddy(purple_connection_get_account(gc), add_req->who) != NULL,
yahoo_buddy_add_authorize_cb,
yahoo_buddy_add_deny_reason_cb,
add_req);
g_free(alias);
+ g_free(dec_msg);
} else {
g_free(add_req->id);
g_free(add_req->who);
- /*g_free(add_req->msg);*/
g_free(add_req);
}
} else {
@@ -1165,6 +1169,7 @@ static void yahoo_buddy_auth_req_15(PurpleConnection *gc, struct yahoo_packet *p
}
}
+/* I don't think this happens anymore in Version 15 */
static void yahoo_buddy_added_us(PurpleConnection *gc, struct yahoo_packet *pkt) {
struct yahoo_add_request *add_req;
char *msg = NULL;
@@ -1192,22 +1197,31 @@ static void yahoo_buddy_added_us(PurpleConnection *gc, struct yahoo_packet *pkt)
l = l->next;
}
- if (add_req->id) {
+ if (add_req->id && add_req->who) {
+ char *dec_msg = NULL;
+
+ if (!yahoo_privacy_check(gc, add_req->who)) {
+ purple_debug_misc("yahoo", "Auth. request from %s dropped and automatically denied due to privacy settings!\n",
+ add_req->who);
+ yahoo_buddy_add_deny_cb(add_req, NULL);
+ return;
+ }
+
if (msg)
- add_req->msg = yahoo_string_decode(gc, msg, FALSE);
+ dec_msg = yahoo_string_decode(gc, msg, FALSE);
/* DONE! this is almost exactly the same as what MSN does,
* this should probably be moved to the core.
*/
purple_account_request_authorization(purple_connection_get_account(gc), add_req->who, add_req->id,
- NULL, add_req->msg, purple_find_buddy(purple_connection_get_account(gc),add_req->who) != NULL,
+ NULL, dec_msg, purple_find_buddy(purple_connection_get_account(gc),add_req->who) != NULL,
yahoo_buddy_add_authorize_cb,
yahoo_buddy_add_deny_reason_cb,
add_req);
+ g_free(dec_msg);
} else {
g_free(add_req->id);
g_free(add_req->who);
- /*g_free(add_req->msg);*/
g_free(add_req);
}
}
@@ -3016,6 +3030,11 @@ static void yahoo_close(PurpleConnection *gc) {
if (yd->ycht)
ycht_connection_close(yd->ycht);
+ g_free(yd->pending_chat_room);
+ g_free(yd->pending_chat_id);
+ g_free(yd->pending_chat_topic);
+ g_free(yd->pending_chat_goto);
+
g_free(yd);
gc->proto_data = NULL;
}
@@ -4096,9 +4115,7 @@ gboolean yahoo_send_attention(PurpleConnection *gc, const char *username, guint
purple_debug(PURPLE_DEBUG_INFO, "yahoo",
"Sending <ding> on account %s to buddy %s.\n", username, c->name);
- /* TODO: find out how to send a <ding> without showing up as a blank line on
- * the conversation window. */
- purple_conv_im_send(PURPLE_CONV_IM(c), "<ding>");
+ purple_conv_im_send_with_flags(PURPLE_CONV_IM(c), "<ding>", PURPLE_MESSAGE_INVISIBLE);
return TRUE;
}
diff --git a/libpurple/protocols/yahoo/yahoo.h b/libpurple/protocols/yahoo/yahoo.h
index 74e3c65719..0a377d2f4b 100644
--- a/libpurple/protocols/yahoo/yahoo.h
+++ b/libpurple/protocols/yahoo/yahoo.h
@@ -130,6 +130,10 @@ struct yahoo_data {
gboolean chat_online;
gboolean in_chat;
char *chat_name;
+ char *pending_chat_room;
+ char *pending_chat_id;
+ char *pending_chat_topic;
+ char *pending_chat_goto;
char *auth;
gsize auth_written;
char *cookie_y;
diff --git a/libpurple/protocols/yahoo/yahoochat.c b/libpurple/protocols/yahoo/yahoochat.c
index 47e1c00560..f772097a44 100644
--- a/libpurple/protocols/yahoo/yahoochat.c
+++ b/libpurple/protocols/yahoo/yahoochat.c
@@ -55,16 +55,24 @@ static void yahoo_chat_online(PurpleConnection *gc)
{
struct yahoo_data *yd = gc->proto_data;
struct yahoo_packet *pkt;
+ const char *rll;
if (yd->wm) {
ycht_connection_open(gc);
return;
}
+ rll = purple_account_get_string(purple_connection_get_account(gc),
+ "room_list_locale", YAHOO_ROOMLIST_LOCALE);
+
pkt = yahoo_packet_new(YAHOO_SERVICE_CHATONLINE, YAHOO_STATUS_AVAILABLE,0);
- yahoo_packet_hash(pkt, "ssss", 1, purple_connection_get_display_name(gc),
- 109, purple_connection_get_display_name(gc), 6, "abcde",
- 135, "ym8.1.0.415");
+ yahoo_packet_hash(pkt, "sssss",
+ 109, purple_connection_get_display_name(gc),
+ 1, purple_connection_get_display_name(gc),
+ 6, "abcde",
+ /* I'm not sure this is the correct way to set this. */
+ 98, rll,
+ 135, "ym8.1.0.415");
yahoo_packet_send_and_free(pkt, yd);
}
@@ -125,6 +133,7 @@ void yahoo_process_conference_invite(PurpleConnection *gc, struct yahoo_packet *
case 1: /* us, but we already know who we are */
break;
case 57:
+ g_free(room);
room = yahoo_string_decode(gc, pair->value, FALSE);
break;
case 50: /* inviter */
@@ -136,6 +145,7 @@ void yahoo_process_conference_invite(PurpleConnection *gc, struct yahoo_packet *
g_string_append_printf(members, "%s\n", pair->value);
break;
case 58:
+ g_free(msg);
msg = yahoo_string_decode(gc, pair->value, FALSE);
break;
case 13: /* ? */
@@ -145,27 +155,28 @@ void yahoo_process_conference_invite(PurpleConnection *gc, struct yahoo_packet *
if (!room) {
g_string_free(members, TRUE);
+ g_free(msg);
return;
}
- components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
- g_hash_table_replace(components, g_strdup("room"), room);
- if (msg)
- g_hash_table_replace(components, g_strdup("topic"), msg);
- g_hash_table_replace(components, g_strdup("type"), g_strdup("Conference"));
- if (members) {
- g_hash_table_replace(components, g_strdup("members"), g_strdup(members->str));
- }
if (!yahoo_privacy_check(gc, who) ||
- (purple_account_get_bool(purple_connection_get_account(gc), "ignore_invites", FALSE))) {
+ (purple_account_get_bool(purple_connection_get_account(gc), "ignore_invites", FALSE))) {
purple_debug_info("yahoo",
"Invite to conference %s from %s has been dropped.\n", room, who);
+ g_free(room);
+ g_free(msg);
g_string_free(members, TRUE);
return;
}
+
+ components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+ g_hash_table_replace(components, g_strdup("room"), room);
+ if (msg)
+ g_hash_table_replace(components, g_strdup("topic"), msg);
+ g_hash_table_replace(components, g_strdup("type"), g_strdup("Conference"));
+ g_hash_table_replace(components, g_strdup("members"), g_string_free(members, FALSE));
serv_got_chat_invite(gc, room, who, msg, components);
- g_string_free(members, TRUE);
}
void yahoo_process_conference_decline(PurpleConnection *gc, struct yahoo_packet *pkt)
@@ -180,20 +191,21 @@ void yahoo_process_conference_decline(PurpleConnection *gc, struct yahoo_packet
switch (pair->key) {
case 57:
+ g_free(room);
room = yahoo_string_decode(gc, pair->value, FALSE);
break;
case 54:
who = pair->value;
break;
case 14:
+ g_free(msg);
msg = yahoo_string_decode(gc, pair->value, FALSE);
break;
}
}
if (!yahoo_privacy_check(gc, who)) {
g_free(room);
- if (msg != NULL)
- g_free(msg);
+ g_free(msg);
return;
}
@@ -209,8 +221,7 @@ void yahoo_process_conference_decline(PurpleConnection *gc, struct yahoo_packet
}
g_free(room);
- if (msg)
- g_free(msg);
+ g_free(msg);
}
}
@@ -226,6 +237,7 @@ void yahoo_process_conference_logon(PurpleConnection *gc, struct yahoo_packet *p
switch (pair->key) {
case 57:
+ g_free(room);
room = yahoo_string_decode(gc, pair->value, FALSE);
break;
case 53:
@@ -254,6 +266,7 @@ void yahoo_process_conference_logoff(PurpleConnection *gc, struct yahoo_packet *
switch (pair->key) {
case 57:
+ g_free(room);
room = yahoo_string_decode(gc, pair->value, FALSE);
break;
case 56:
@@ -276,7 +289,6 @@ void yahoo_process_conference_message(PurpleConnection *gc, struct yahoo_packet
char *room = NULL;
char *who = NULL;
char *msg = NULL;
- char *msg2;
int utf8 = 0;
PurpleConversation *c;
@@ -285,6 +297,7 @@ void yahoo_process_conference_message(PurpleConnection *gc, struct yahoo_packet
switch (pair->key) {
case 57:
+ g_free(room);
room = yahoo_string_decode(gc, pair->value, FALSE);
break;
case 3:
@@ -299,28 +312,82 @@ void yahoo_process_conference_message(PurpleConnection *gc, struct yahoo_packet
}
}
- if (room && who && msg) {
- msg2 = yahoo_string_decode(gc, msg, utf8);
- c = yahoo_find_conference(gc, room);
- if (!c)
- return;
- msg = yahoo_codes_to_html(msg2);
- serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(c)), who, 0, msg, time(NULL));
- g_free(msg);
- g_free(msg2);
- }
- if (room)
+ if (room && who && msg) {
+ char *msg2;
+
+ c = yahoo_find_conference(gc, room);
+ if (!c) {
g_free(room);
+ return;
+ }
+
+ msg2 = yahoo_string_decode(gc, msg, utf8);
+ msg = yahoo_codes_to_html(msg2);
+ serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(c)), who, 0, msg, time(NULL));
+ g_free(msg);
+ g_free(msg2);
+ }
+
+ g_free(room);
}
+static void yahoo_chat_join(PurpleConnection *gc, const char *dn, const char *room, const char *topic, const char *id)
+{
+ struct yahoo_data *yd = gc->proto_data;
+ struct yahoo_packet *pkt;
+ char *room2;
+ gboolean utf8 = TRUE;
+
+ if (yd->wm) {
+ g_return_if_fail(yd->ycht != NULL);
+ ycht_chat_join(yd->ycht, room);
+ return;
+ }
+
+ /* apparently room names are always utf8, or else always not utf8,
+ * so we don't have to actually pass the flag in the packet. Or something. */
+ room2 = yahoo_string_encode(gc, room, &utf8);
+
+ pkt = yahoo_packet_new(YAHOO_SERVICE_CHATJOIN, YAHOO_STATUS_AVAILABLE, 0);
+ yahoo_packet_hash(pkt, "ssss",
+ 1, purple_connection_get_display_name(gc),
+ 104, room2,
+ 62, "2",
+ 129, id ? id : "0");
+ yahoo_packet_send_and_free(pkt, yd);
+ g_free(room2);
+}
/* this is a confirmation of yahoo_chat_online(); */
void yahoo_process_chat_online(PurpleConnection *gc, struct yahoo_packet *pkt)
{
struct yahoo_data *yd = (struct yahoo_data *) gc->proto_data;
- if (pkt->status == 1)
+ if (pkt->status == 1) {
yd->chat_online = 1;
+
+ /* We need to goto a user in chat */
+ if (yd->pending_chat_goto) {
+ struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_CHATGOTO, YAHOO_STATUS_AVAILABLE, 0);
+ yahoo_packet_hash(pkt, "sss",
+ 109, yd->pending_chat_goto,
+ 1, purple_connection_get_display_name(gc),
+ 62, "2");
+ yahoo_packet_send_and_free(pkt, yd);
+ } else if (yd->pending_chat_room) {
+ yahoo_chat_join(gc, purple_connection_get_display_name(gc), yd->pending_chat_room,
+ yd->pending_chat_topic, yd->pending_chat_id);
+ }
+
+ g_free(yd->pending_chat_room);
+ yd->pending_chat_room = NULL;
+ g_free(yd->pending_chat_id);
+ yd->pending_chat_id = NULL;
+ g_free(yd->pending_chat_topic);
+ yd->pending_chat_topic = NULL;
+ g_free(yd->pending_chat_goto);
+ yd->pending_chat_goto = NULL;
+ }
}
/* this is basicly the opposite of chat_online */
@@ -340,6 +407,14 @@ void yahoo_process_chat_logout(PurpleConnection *gc, struct yahoo_packet *pkt)
if (pkt->status == 1) {
yd->chat_online = 0;
+ g_free(yd->pending_chat_room);
+ yd->pending_chat_room = NULL;
+ g_free(yd->pending_chat_id);
+ yd->pending_chat_id = NULL;
+ g_free(yd->pending_chat_topic);
+ yd->pending_chat_topic = NULL;
+ g_free(yd->pending_chat_goto);
+ yd->pending_chat_goto = NULL;
if (yd->in_chat)
yahoo_c_leave(gc, YAHOO_CHAT_ID);
}
@@ -384,9 +459,11 @@ void yahoo_process_chat_join(PurpleConnection *gc, struct yahoo_packet *pkt)
switch (pair->key) {
case 104:
+ g_free(room);
room = yahoo_string_decode(gc, pair->value, TRUE);
break;
case 105:
+ g_free(topic);
topic = yahoo_string_decode(gc, pair->value, TRUE);
break;
case 128:
@@ -445,8 +522,11 @@ void yahoo_process_chat_join(PurpleConnection *gc, struct yahoo_packet *pkt)
purple_conversation_set_name(c, room);
c = serv_got_joined_chat(gc, YAHOO_CHAT_ID, room);
- if (topic)
+ if (topic) {
purple_conv_chat_set_topic(PURPLE_CONV_CHAT(c), NULL, topic);
+ /* Also print the topic to the backlog so that the captcha link is clickable */
+ purple_conv_chat_write(PURPLE_CONV_CHAT(c), "", topic, PURPLE_MESSAGE_SYSTEM, time(NULL));
+ }
yd->in_chat = 1;
yd->chat_name = g_strdup(room);
purple_conv_chat_add_users(PURPLE_CONV_CHAT(c), members, NULL, flags, FALSE);
@@ -456,14 +536,22 @@ void yahoo_process_chat_join(PurpleConnection *gc, struct yahoo_packet *pkt)
g_free(tmpmsg);
} else {
c = serv_got_joined_chat(gc, YAHOO_CHAT_ID, room);
- if (topic)
+ if (topic) {
purple_conv_chat_set_topic(PURPLE_CONV_CHAT(c), NULL, topic);
+ /* Also print the topic to the backlog so that the captcha link is clickable */
+ purple_conv_chat_write(PURPLE_CONV_CHAT(c), "", topic, PURPLE_MESSAGE_SYSTEM, time(NULL));
+ }
yd->in_chat = 1;
yd->chat_name = g_strdup(room);
purple_conv_chat_add_users(PURPLE_CONV_CHAT(c), members, NULL, flags, FALSE);
}
g_list_free(flags);
} else if (c) {
+ if (topic) {
+ const char *cur_topic = purple_conv_chat_get_topic(PURPLE_CONV_CHAT(c));
+ if (cur_topic == NULL || strcmp(cur_topic, topic) != 0)
+ purple_conv_chat_set_topic(PURPLE_CONV_CHAT(c), NULL, topic);
+ }
yahoo_chat_add_users(PURPLE_CONV_CHAT(c), members);
}
@@ -497,8 +585,10 @@ void yahoo_process_chat_exit(PurpleConnection *gc, struct yahoo_packet *pkt)
for (l = pkt->hash; l; l = l->next) {
struct yahoo_pair *pair = l->data;
- if (pair->key == 104)
+ if (pair->key == 104) {
+ g_free(room);
room = yahoo_string_decode(gc, pair->value, TRUE);
+ }
if (pair->key == 109)
who = pair->value;
}
@@ -529,6 +619,7 @@ void yahoo_process_chat_message(PurpleConnection *gc, struct yahoo_packet *pkt)
utf8 = strtol(pair->value, NULL, 10);
break;
case 104:
+ g_free(room);
room = yahoo_string_decode(gc, pair->value, TRUE);
break;
case 109:
@@ -583,6 +674,7 @@ void yahoo_process_chat_addinvite(PurpleConnection *gc, struct yahoo_packet *pkt
switch (pair->key) {
case 104:
+ g_free(room);
room = yahoo_string_decode(gc, pair->value, TRUE);
break;
case 129: /* room id? */
@@ -590,6 +682,7 @@ void yahoo_process_chat_addinvite(PurpleConnection *gc, struct yahoo_packet *pkt
case 126: /* ??? */
break;
case 117:
+ g_free(msg);
msg = yahoo_string_decode(gc, pair->value, FALSE);
break;
case 119:
@@ -603,24 +696,21 @@ void yahoo_process_chat_addinvite(PurpleConnection *gc, struct yahoo_packet *pkt
if (room && who) {
GHashTable *components;
- components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
- g_hash_table_replace(components, g_strdup("room"), g_strdup(room));
if (!yahoo_privacy_check(gc, who) ||
- (purple_account_get_bool(purple_connection_get_account(gc), "ignore_invites", FALSE))) {
- purple_debug_info("yahoo",
- "Invite to room %s from %s has been dropped.\n", room, who);
- if (room != NULL)
- g_free(room);
- if (msg != NULL)
- g_free(msg);
+ (purple_account_get_bool(purple_connection_get_account(gc), "ignore_invites", FALSE))) {
+ purple_debug_info("yahoo", "Invite to room %s from %s has been dropped.\n", room, who);
+ g_free(room);
+ g_free(msg);
return;
}
+
+ components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+ g_hash_table_replace(components, g_strdup("room"), g_strdup(room));
serv_got_chat_invite(gc, room, who, msg, components);
}
- if (room)
- g_free(room);
- if (msg)
- g_free(msg);
+
+ g_free(room);
+ g_free(msg);
}
void yahoo_process_chat_goto(PurpleConnection *gc, struct yahoo_packet *pkt)
@@ -783,6 +873,14 @@ static void yahoo_chat_leave(PurpleConnection *gc, const char *room, const char
yahoo_packet_send_and_free(pkt, yd);
yd->chat_online = 0;
+ g_free(yd->pending_chat_room);
+ yd->pending_chat_room = NULL;
+ g_free(yd->pending_chat_id);
+ yd->pending_chat_id = NULL;
+ g_free(yd->pending_chat_topic);
+ yd->pending_chat_topic = NULL;
+ g_free(yd->pending_chat_goto);
+ yd->pending_chat_goto = NULL;
g_free(eroom);
}
@@ -829,29 +927,6 @@ static int yahoo_chat_send(PurpleConnection *gc, const char *dn, const char *roo
return 0;
}
-static void yahoo_chat_join(PurpleConnection *gc, const char *dn, const char *room, const char *topic)
-{
- struct yahoo_data *yd = gc->proto_data;
- struct yahoo_packet *pkt;
- char *room2;
- gboolean utf8 = TRUE;
-
- if (yd->wm) {
- g_return_if_fail(yd->ycht != NULL);
- ycht_chat_join(yd->ycht, room);
- return;
- }
-
- /* apparently room names are always utf8, or else always not utf8,
- * so we don't have to actually pass the flag in the packet. Or something. */
- room2 = yahoo_string_encode(gc, room, &utf8);
-
- pkt = yahoo_packet_new(YAHOO_SERVICE_CHATJOIN, YAHOO_STATUS_AVAILABLE, 0);
- yahoo_packet_hash(pkt, "ssss", 1, purple_connection_get_display_name(gc),
- 62, "2", 104, room2, 129, "0");
- yahoo_packet_send_and_free(pkt, yd);
- g_free(room2);
-}
static void yahoo_chat_invite(PurpleConnection *gc, const char *dn, const char *buddy,
const char *room, const char *msg)
@@ -892,8 +967,18 @@ void yahoo_chat_goto(PurpleConnection *gc, const char *name)
return;
}
- if (!yd->chat_online)
+ if (!yd->chat_online) {
yahoo_chat_online(gc);
+ g_free(yd->pending_chat_room);
+ yd->pending_chat_room = NULL;
+ g_free(yd->pending_chat_id);
+ yd->pending_chat_id = NULL;
+ g_free(yd->pending_chat_topic);
+ yd->pending_chat_topic = NULL;
+ g_free(yd->pending_chat_goto);
+ yd->pending_chat_goto = g_strdup(name);
+ return;
+ }
pkt = yahoo_packet_new(YAHOO_SERVICE_CHATGOTO, YAHOO_STATUS_AVAILABLE, 0);
yahoo_packet_hash(pkt, "sss", 109, name, 1, purple_connection_get_display_name(gc), 62, "2");
@@ -988,8 +1073,7 @@ char *yahoo_get_chat_name(GHashTable *data)
void yahoo_c_join(PurpleConnection *gc, GHashTable *data)
{
struct yahoo_data *yd;
- char *room, *topic, *members, *type;
- int id;
+ char *room, *topic, *type;
PurpleConversation *c;
yd = (struct yahoo_data *) gc->proto_data;
@@ -1004,9 +1088,9 @@ void yahoo_c_join(PurpleConnection *gc, GHashTable *data)
if (!topic)
topic = "";
- members = g_hash_table_lookup(data, "members");
-
if ((type = g_hash_table_lookup(data, "type")) && !strcmp(type, "Conference")) {
+ int id;
+ const char *members = g_hash_table_lookup(data, "members");
id = yd->conf_id++;
c = serv_got_joined_chat(gc, id, room);
yd->confs = g_slist_prepend(yd->confs, c);
@@ -1014,13 +1098,27 @@ void yahoo_c_join(PurpleConnection *gc, GHashTable *data)
yahoo_conf_join(yd, c, purple_connection_get_display_name(gc), room, topic, members);
return;
} else {
- if (yd->in_chat)
+ const char *id;
+ /*if (yd->in_chat)
yahoo_chat_leave(gc, room,
purple_connection_get_display_name(gc),
- FALSE);
- if (!yd->chat_online)
+ FALSE);*/
+
+ id = g_hash_table_lookup(data, "id");
+
+ if (!yd->chat_online) {
yahoo_chat_online(gc);
- yahoo_chat_join(gc, purple_connection_get_display_name(gc), room, topic);
+ g_free(yd->pending_chat_room);
+ yd->pending_chat_room = g_strdup(room);
+ g_free(yd->pending_chat_id);
+ yd->pending_chat_id = g_strdup(id);
+ g_free(yd->pending_chat_topic);
+ yd->pending_chat_topic = g_strdup(topic);
+ g_free(yd->pending_chat_goto);
+ yd->pending_chat_goto = NULL;
+ } else {
+ yahoo_chat_join(gc, purple_connection_get_display_name(gc), room, topic, id);
+ }
return;
}
}
@@ -1148,16 +1246,13 @@ static void yahoo_chatlist_start_element(GMarkupParseContext *context,
for (i = 0; anames[i]; i++) {
if (!strcmp(anames[i], "id")) {
- if (s->room.id)
- g_free(s->room.id);
+ g_free(s->room.id);
s->room.id = g_strdup(avalues[i]);
} else if (!strcmp(anames[i], "name")) {
- if (s->room.name)
- g_free(s->room.name);
+ g_free(s->room.name);
s->room.name = g_strdup(avalues[i]);
} else if (!strcmp(anames[i], "topic")) {
- if (s->room.topic)
- g_free(s->room.topic);
+ g_free(s->room.topic);
s->room.topic = g_strdup(avalues[i]);
} else if (!strcmp(anames[i], "type")) {
if (!strcmp("yahoo", avalues[i]))
diff --git a/libpurple/prpl.c b/libpurple/prpl.c
index 21f9a6c750..08fba7d087 100644
--- a/libpurple/prpl.c
+++ b/libpurple/prpl.c
@@ -199,8 +199,10 @@ void purple_prpl_got_user_status_deactive(PurpleAccount *account, const char *na
if(NULL == status)
continue;
- purple_status_set_active(status, FALSE);
- purple_blist_update_buddy_status(buddy, status);
+ if (purple_status_is_active(status)) {
+ purple_status_set_active(status, FALSE);
+ purple_blist_update_buddy_status(buddy, status);
+ }
}
g_slist_free(list);
diff --git a/libpurple/server.c b/libpurple/server.c
index b2b2b72ba9..f6fa839db6 100644
--- a/libpurple/server.c
+++ b/libpurple/server.c
@@ -272,6 +272,7 @@ serv_send_attention(PurpleConnection *gc, const char *who, guint type_code)
PurpleAttentionType *attn;
PurpleMessageFlags flags;
PurplePlugin *prpl;
+ PurpleConversation *conv;
gboolean (*send_attention)(PurpleConnection *, const char *, guint);
gchar *description;
@@ -302,8 +303,8 @@ serv_send_attention(PurpleConnection *gc, const char *who, guint type_code)
if (!send_attention(gc, who, type_code))
return;
- /* TODO: icons, sound, shaking... same as serv_got_attention(). */
- serv_got_im(gc, who, description, flags, mtime);
+ conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, gc->account, who);
+ purple_conv_im_write(PURPLE_CONV_IM(conv), NULL, description, flags, mtime);
g_free(description);
}
diff --git a/libpurple/win32/global.mak b/libpurple/win32/global.mak
index e51f756d9f..1d1f41d434 100644
--- a/libpurple/win32/global.mak
+++ b/libpurple/win32/global.mak
@@ -20,7 +20,7 @@ MEANWHILE_TOP ?= $(WIN32_DEV_TOP)/meanwhile-1.0.2
NSPR_TOP ?= $(WIN32_DEV_TOP)/nspr-4.6.4
NSS_TOP ?= $(WIN32_DEV_TOP)/nss-3.11.4
PERL_LIB_TOP ?= $(WIN32_DEV_TOP)/perl58
-SILC_TOOLKIT ?= $(WIN32_DEV_TOP)/silc-toolkit-1.0.2
+SILC_TOOLKIT ?= $(WIN32_DEV_TOP)/silc-toolkit-1.1.2
TCL_LIB_TOP ?= $(WIN32_DEV_TOP)/tcl-8.4.5
# Where we installing this stuff to?
diff --git a/pidgin/gtkaccount.c b/pidgin/gtkaccount.c
index e95a2e8dfe..ed4aa5d738 100644
--- a/pidgin/gtkaccount.c
+++ b/pidgin/gtkaccount.c
@@ -2405,13 +2405,6 @@ pidgin_accounts_window_hide(void)
g_free(accounts_window);
accounts_window = NULL;
-
- /* See if we're the main window here. */
- if (PIDGIN_BLIST(purple_get_blist())->window == NULL &&
- purple_connections_get_all() == NULL) {
-
- purple_core_quit();
- }
}
static void
diff --git a/pidgin/gtkblist.c b/pidgin/gtkblist.c
index f6ae442469..2ba9499d35 100644
--- a/pidgin/gtkblist.c
+++ b/pidgin/gtkblist.c
@@ -125,7 +125,7 @@ static void sort_method_log(PurpleBlistNode *node, PurpleBuddyList *blist, GtkTr
static PidginBuddyList *gtkblist = NULL;
static gboolean pidgin_blist_refresh_timer(PurpleBuddyList *list);
-static void pidgin_blist_update_buddy(PurpleBuddyList *list, PurpleBlistNode *node, gboolean statusChange);
+static void pidgin_blist_update_buddy(PurpleBuddyList *list, PurpleBlistNode *node, gboolean status_change);
static void pidgin_blist_selection_changed(GtkTreeSelection *selection, gpointer data);
static void pidgin_blist_update(PurpleBuddyList *list, PurpleBlistNode *node);
static void pidgin_blist_update_group(PurpleBuddyList *list, PurpleBlistNode *node);
@@ -332,8 +332,10 @@ static void gtk_blist_join_chat(PurpleChat *chat)
conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, name,
chat->account);
- if (conv != NULL)
+ if (conv != NULL) {
+ pidgin_conv_attach_to_conversation(conv);
purple_conversation_present(conv);
+ }
serv_join_chat(chat->account->gc, chat->components);
g_free(chat_name);
@@ -612,6 +614,8 @@ joinchat_set_sensitive_if_input_cb(GtkWidget *entry, gpointer user_data)
static void
pidgin_blist_update_privacy_cb(PurpleBuddy *buddy)
{
+ if (buddy->node.ui_data == NULL || ((struct _pidgin_blist_node*)buddy->node.ui_data)->row == NULL)
+ return;
pidgin_blist_update_buddy(purple_get_blist(), (PurpleBlistNode*)(buddy), TRUE);
}
@@ -3205,6 +3209,7 @@ pidgin_blist_get_status_icon(PurpleBlistNode *node, PidginStatusIconSize size)
{
GdkPixbuf *ret;
const char *protoname = NULL;
+ const char *icon = NULL;
struct _pidgin_blist_node *gtknode = node->ui_data;
struct _pidgin_blist_node *gtkbuddynode = NULL;
PurpleBuddy *buddy = NULL;
@@ -3253,62 +3258,54 @@ pidgin_blist_get_status_icon(PurpleBlistNode *node, PidginStatusIconSize size)
purple_buddy_get_name(buddy),
purple_buddy_get_account(buddy));
PurplePresence *p;
+ gboolean trans;
+
if(conv != NULL) {
PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
- if(gtkconv != NULL && pidgin_conv_is_hidden(gtkconv) && size == PIDGIN_STATUS_ICON_SMALL) {
+ if((gtkconv == NULL || pidgin_conv_is_hidden(gtkconv)) && size == PIDGIN_STATUS_ICON_SMALL) {
return gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_MESSAGE,
icon_size, "GtkTreeView");
}
}
+
p = purple_buddy_get_presence(buddy);
+ trans = (purple_presence_is_idle(p) && size == PIDGIN_STATUS_ICON_SMALL);
if (PURPLE_BUDDY_IS_ONLINE(buddy) && gtkbuddynode && gtkbuddynode->recent_signonoff)
- ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_LOGIN,
- icon_size, "GtkTreeView");
+ icon = PIDGIN_STOCK_STATUS_LOGIN;
else if (gtkbuddynode && gtkbuddynode->recent_signonoff)
- ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_LOGOUT,
- icon_size, "GtkTreeView");
+ icon = PIDGIN_STOCK_STATUS_LOGOUT;
else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_UNAVAILABLE))
- if (purple_presence_is_idle(p) && size == PIDGIN_STATUS_ICON_SMALL)
- ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_BUSY_I,
- icon_size, "GtkTreeView");
+ if (trans)
+ icon = PIDGIN_STOCK_STATUS_BUSY_I;
else
- ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_BUSY,
- icon_size, "GtkTreeView");
+ icon = PIDGIN_STOCK_STATUS_BUSY;
else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_AWAY))
- if (purple_presence_is_idle(p) && size == PIDGIN_STATUS_ICON_SMALL)
- ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_AWAY_I,
- icon_size, "GtkTreeView");
+ if (trans)
+ icon = PIDGIN_STOCK_STATUS_AWAY_I;
else
- ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_AWAY,
- icon_size, "GtkTreeView");
+ icon = PIDGIN_STOCK_STATUS_AWAY;
else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_EXTENDED_AWAY))
- if (purple_presence_is_idle(p) && size == PIDGIN_STATUS_ICON_SMALL)
- ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_XA_I,
- icon_size, "GtkTreeView");
+ if (trans)
+ icon = PIDGIN_STOCK_STATUS_XA_I;
else
- ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_XA,
- icon_size, "GtkTreeView");
+ icon = PIDGIN_STOCK_STATUS_XA;
else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_OFFLINE))
- ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_OFFLINE,
- icon_size, "GtkTreeView");
- else if (purple_presence_is_idle(p) && size == PIDGIN_STATUS_ICON_SMALL)
- ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_AVAILABLE_I,
- icon_size, "GtkTreeView");
+ icon = PIDGIN_STOCK_STATUS_OFFLINE;
+ else if (trans)
+ icon = PIDGIN_STOCK_STATUS_AVAILABLE_I;
else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_INVISIBLE))
- ret = gtk_widget_render_icon(GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_INVISIBLE,
- icon_size, "GtkTreeView");
+ icon = PIDGIN_STOCK_STATUS_INVISIBLE;
else
- ret = gtk_widget_render_icon(GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_AVAILABLE,
- icon_size, "GtkTreeView");
+ icon = PIDGIN_STOCK_STATUS_AVAILABLE;
} else if (chat) {
- ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_CHAT,
- icon_size, "GtkTreeView");
+ icon = PIDGIN_STOCK_STATUS_CHAT;
} else {
- ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_PERSON,
- icon_size, "GtkTreeView");
+ icon = PIDGIN_STOCK_STATUS_PERSON;
}
+ ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), icon,
+ icon_size, "GtkTreeView");
return ret;
}
@@ -3331,7 +3328,7 @@ gchar *pidgin_blist_get_name_markup(PurpleBuddy *b, gboolean selected, gboolean
if(conv != NULL) {
gtkconv = PIDGIN_CONVERSATION(conv);
- if(gtkconv != NULL && pidgin_conv_is_hidden(gtkconv)) {
+ if(gtkconv == NULL || pidgin_conv_is_hidden(gtkconv)) {
hidden_conv = TRUE;
}
}
@@ -5156,7 +5153,7 @@ static void pidgin_blist_update_contact(PurpleBuddyList *list, PurpleBlistNode *
-static void pidgin_blist_update_buddy(PurpleBuddyList *list, PurpleBlistNode *node, gboolean statusChange)
+static void pidgin_blist_update_buddy(PurpleBuddyList *list, PurpleBlistNode *node, gboolean status_change)
{
PurpleBuddy *buddy;
struct _pidgin_blist_node *gtkparentnode;
diff --git a/pidgin/gtkcertmgr.c b/pidgin/gtkcertmgr.c
index 6af2b5bb63..c76a318e33 100644
--- a/pidgin/gtkcertmgr.c
+++ b/pidgin/gtkcertmgr.c
@@ -597,7 +597,7 @@ pidgin_certmgr_show(void)
for (l=idlist; l; l = l->next) {
purple_debug_info("gtkcertmgr",
"- %s\n",
- (gchar *) l->data);
+ l->data ? (gchar *) l->data : "(null)");
} /* idlist */
purple_certificate_pool_destroy_idlist(idlist);
} /* poollist */
@@ -676,11 +676,4 @@ pidgin_certmgr_hide(void)
gtk_widget_destroy(certmgr_dialog->window);
g_free(certmgr_dialog);
certmgr_dialog = NULL;
-
- /* If this was the only window left, quit */
- if (PIDGIN_BLIST(purple_get_blist())->window == NULL &&
- purple_connections_get_all() == NULL) {
-
- purple_core_quit();
- }
}
diff --git a/pidgin/gtkconv.c b/pidgin/gtkconv.c
index 8edee59340..91258b6a1e 100644
--- a/pidgin/gtkconv.c
+++ b/pidgin/gtkconv.c
@@ -326,6 +326,7 @@ clear_command_cb(PurpleConversation *conv,
const char *cmd, char **args, char **error, void *data)
{
clear_conversation_scrollback(conv);
+ purple_conversation_clear_message_history(conv);
return PURPLE_CMD_STATUS_OK;
}
@@ -1299,6 +1300,17 @@ menu_add_remove_cb(gpointer data, guint action, GtkWidget *widget)
}
static void
+menu_hide_conv_cb(gpointer data, guint action, GtkWidget *widget)
+{
+ PidginWindow *win = data;
+ PidginConversation *gtkconv = pidgin_conv_window_get_active_gtkconv(win);
+ PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win);
+ purple_signal_emit(pidgin_conversations_get_handle(),
+ "conversation-hiding", gtkconv);
+ purple_conversation_set_ui_ops(conv, NULL);
+}
+
+static void
menu_close_conv_cb(gpointer data, guint action, GtkWidget *widget)
{
PidginWindow *win = data;
@@ -2697,6 +2709,7 @@ void
pidgin_conv_present_conversation(PurpleConversation *conv)
{
PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
+ GdkModifierType state;
if(gtkconv->win==hidden_convwin) {
pidgin_conv_window_remove_gtkconv(hidden_convwin, gtkconv);
@@ -2704,7 +2717,10 @@ pidgin_conv_present_conversation(PurpleConversation *conv)
}
pidgin_conv_switch_active_conversation(conv);
- pidgin_conv_window_switch_gtkconv(gtkconv->win, gtkconv);
+ /* Switch the tab only if the user initiated the event by pressing
+ * a button or hitting a key. */
+ if (gtk_get_current_event_state(&state))
+ pidgin_conv_window_switch_gtkconv(gtkconv->win, gtkconv);
gtk_window_present(GTK_WINDOW(gtkconv->win->window));
}
@@ -2730,7 +2746,7 @@ pidgin_conversations_find_unseen_list(PurpleConversationType type,
PurpleConversation *conv = (PurpleConversation*)l->data;
PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
- if(gtkconv->active_conv != conv)
+ if(gtkconv == NULL || gtkconv->active_conv != conv)
continue;
if (gtkconv->unseen_state >= min_state
@@ -2844,6 +2860,8 @@ static GtkItemFactoryEntry menu_items[] =
{ "/Conversation/sep4", NULL, NULL, 0, "<Separator>", NULL },
+ { N_("/Conversation/_Hide"), NULL, menu_hide_conv_cb, 0,
+ "<StockItem>", NULL},
{ N_("/Conversation/_Close"), NULL, menu_close_conv_cb, 0,
"<StockItem>", GTK_STOCK_CLOSE },
@@ -5011,6 +5029,10 @@ pidgin_conv_destroy(PurpleConversation *conv)
g_list_foreach(gtkconv->send_history, (GFunc)g_free, NULL);
g_list_free(gtkconv->send_history);
+ if (gtkconv->attach.timer) {
+ g_source_remove(gtkconv->attach.timer);
+ }
+
if (tooltip.gtkconv == gtkconv)
reset_tooltip();
@@ -5227,6 +5249,15 @@ pidgin_conv_write_conv(PurpleConversation *conv, const char *name, const char *a
gtkconv = PIDGIN_CONVERSATION(conv);
g_return_if_fail(gtkconv != NULL);
+ if (gtkconv->attach.timer) {
+ /* We are currently in the process of filling up the buffer with the message
+ * history of the conversation. So we do not need to add the message here.
+ * Instead, this message will be added to the message-list, which in turn will
+ * be processed and displayed by the attach-callback.
+ */
+ return;
+ }
+
if (conv != gtkconv->active_conv)
{
if (flags & PURPLE_MESSAGE_ACTIVE_ONLY)
@@ -7161,6 +7192,60 @@ update_chat_topic(PurpleConversation *conv, const char *old, const char *new)
pidgin_conv_update_fields(conv, PIDGIN_CONV_TOPIC);
}
+static gboolean
+add_message_history_to_gtkconv(gpointer data)
+{
+ PidginConversation *gtkconv = data;
+ int count = 0;
+ int timer = gtkconv->attach.timer;
+ gtkconv->attach.timer = 0;
+ while (gtkconv->attach.current && count < 100) { /* XXX: 100 is a random value here */
+ PurpleConvMessage *msg = gtkconv->attach.current->data;
+ pidgin_conv_write_conv(gtkconv->active_conv, msg->who, msg->who, msg->what, msg->flags, msg->when);
+ gtkconv->attach.current = gtkconv->attach.current->prev;
+ count++;
+ }
+ gtkconv->attach.timer = timer;
+ if (gtkconv->attach.current)
+ return TRUE;
+
+ purple_signal_emit(pidgin_conversations_get_handle(),
+ "conversation-displayed", gtkconv);
+ g_source_remove(gtkconv->attach.timer);
+ gtkconv->attach.timer = 0;
+ return FALSE;
+}
+
+gboolean pidgin_conv_attach_to_conversation(PurpleConversation *conv)
+{
+ GList *list;
+ PidginConversation *gtkconv;
+
+ if (PIDGIN_IS_PIDGIN_CONVERSATION(conv))
+ return FALSE;
+
+ purple_conversation_set_ui_ops(conv, pidgin_conversations_get_conv_ui_ops());
+ private_gtkconv_new(conv, FALSE);
+ gtkconv = PIDGIN_CONVERSATION(conv);
+
+ list = purple_conversation_get_message_history(conv);
+ if (list) {
+ list = g_list_last(list);
+ gtkconv->attach.current = list;
+ gtkconv->attach.timer = g_idle_add(add_message_history_to_gtkconv, gtkconv);
+ } else {
+ purple_signal_emit(pidgin_conversations_get_handle(),
+ "conversation-displayed", gtkconv);
+ }
+
+ /* XXX: If this is a chat:
+ * - populate the userlist
+ * - set the topic
+ */
+
+ return TRUE;
+}
+
void *
pidgin_conversations_get_handle(void)
{
@@ -7338,6 +7423,16 @@ pidgin_conversations_init(void)
purple_value_new(PURPLE_TYPE_SUBTYPE,
PURPLE_SUBTYPE_CONVERSATION));
+ purple_signal_register(handle, "conversation-hiding",
+ purple_marshal_VOID__POINTER_POINTER, NULL, 1,
+ purple_value_new(PURPLE_TYPE_BOXED,
+ "PidginConversation *"));
+
+ purple_signal_register(handle, "conversation-displayed",
+ purple_marshal_VOID__POINTER_POINTER, NULL, 1,
+ purple_value_new(PURPLE_TYPE_BOXED,
+ "PidginConversation *"));
+
/**********************************************************************
* Register commands
**********************************************************************/
@@ -8803,9 +8898,8 @@ pidgin_conv_tab_pack(PidginWindow *win, PidginConversation *gtkconv)
if (pidgin_conv_window_get_gtkconv_count(win) == 1)
gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook),
purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/tabs") &&
- (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons") ||
- purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/tab_side") == GTK_POS_LEFT ||
- purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/tab_side") == GTK_POS_RIGHT));
+ (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons") ||
+ purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/tab_side") != GTK_POS_TOP));
/* show the widgets */
/* gtk_widget_show(gtkconv->icon); */
diff --git a/pidgin/gtkconv.h b/pidgin/gtkconv.h
index 9502b840af..8bb9082f30 100644
--- a/pidgin/gtkconv.h
+++ b/pidgin/gtkconv.h
@@ -162,6 +162,13 @@ struct _PidginConversation
GtkWidget *infopane;
GtkListStore *infopane_model;
GtkTreeIter infopane_iter;
+
+ /* Used when attaching a PidginConversation to a PurpleConversation
+ * with message history */
+ struct {
+ int timer;
+ GList *current;
+ } attach;
};
/*@}*/
@@ -238,6 +245,15 @@ pidgin_conversations_fill_menu(GtkWidget *menu, GList *convs);
*/
void pidgin_conv_present_conversation(PurpleConversation *conv);
+/**
+ * Reattach Pidgin UI to a conversation.
+ *
+ * @param conv The conversation.
+ *
+ * @return Wheter Pidgin UI was successfully attached.
+ */
+gboolean pidgin_conv_attach_to_conversation(PurpleConversation *conv);
+
PidginWindow *pidgin_conv_get_window(PidginConversation *gtkconv);
GdkPixbuf *pidgin_conv_get_tab_icon(PurpleConversation *conv, gboolean small_icon);
void pidgin_conv_new(PurpleConversation *conv);
diff --git a/pidgin/gtkdialogs.c b/pidgin/gtkdialogs.c
index d7c5ea1c31..7aaf6da3d5 100644
--- a/pidgin/gtkdialogs.c
+++ b/pidgin/gtkdialogs.c
@@ -99,6 +99,7 @@ static struct developer patch_writers[] = {
{"Dennis 'EvilDennisR' Ristuccia", N_("Senior Contributor/QA"), NULL},
{"Peter 'Fmoo' Ruibal", NULL, NULL},
{"Gabriel 'Nix' Schulhof", NULL, NULL},
+ {"Will 'resiak' Thompson", NULL, NULL},
{NULL, NULL, NULL}
};
@@ -768,6 +769,7 @@ pidgin_dialogs_im_with_user(PurpleAccount *account, const char *username)
if (conv == NULL)
conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, username);
+ pidgin_conv_attach_to_conversation(conv);
purple_conversation_present(conv);
}
diff --git a/pidgin/gtkimhtmltoolbar.c b/pidgin/gtkimhtmltoolbar.c
index 398f378003..1e0b6c09c9 100644
--- a/pidgin/gtkimhtmltoolbar.c
+++ b/pidgin/gtkimhtmltoolbar.c
@@ -786,6 +786,7 @@ static void update_buttons_cb(GtkIMHtml *imhtml, GtkIMHtmlButtons buttons, GtkIM
gtk_widget_set_sensitive(GTK_WIDGET(toolbar->bold), buttons & GTK_IMHTML_BOLD);
gtk_widget_set_sensitive(GTK_WIDGET(toolbar->italic), buttons & GTK_IMHTML_ITALIC);
gtk_widget_set_sensitive(GTK_WIDGET(toolbar->underline), buttons & GTK_IMHTML_UNDERLINE);
+ gtk_widget_set_sensitive(GTK_WIDGET(toolbar->strikethrough), buttons & GTK_IMHTML_STRIKE);
gtk_widget_set_sensitive(GTK_WIDGET(toolbar->larger_size), buttons & GTK_IMHTML_GROW);
gtk_widget_set_sensitive(GTK_WIDGET(toolbar->smaller_size), buttons & GTK_IMHTML_SHRINK);
@@ -798,6 +799,7 @@ static void update_buttons_cb(GtkIMHtml *imhtml, GtkIMHtmlButtons buttons, GtkIM
(buttons & GTK_IMHTML_BOLD ||
buttons & GTK_IMHTML_ITALIC ||
buttons & GTK_IMHTML_UNDERLINE ||
+ buttons & GTK_IMHTML_STRIKE ||
buttons & GTK_IMHTML_GROW ||
buttons & GTK_IMHTML_SHRINK ||
buttons & GTK_IMHTML_FACE ||
@@ -831,7 +833,7 @@ static void toggle_button_set_active_block(GtkToggleButton *button,
static void update_buttons(GtkIMHtmlToolbar *toolbar)
{
- gboolean bold, italic, underline;
+ gboolean bold, italic, underline, strike;
char *tmp;
char *tmp2;
GtkLabel *label = g_object_get_data(G_OBJECT(toolbar), "font_label");
@@ -840,6 +842,7 @@ static void update_buttons(GtkIMHtmlToolbar *toolbar)
gtk_imhtml_get_current_format(GTK_IMHTML(toolbar->imhtml),
&bold, &italic, &underline);
+ strike = GTK_IMHTML(toolbar->imhtml)->edit.strike;
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toolbar->bold)) != bold)
toggle_button_set_active_block(GTK_TOGGLE_BUTTON(toolbar->bold), bold,
@@ -847,10 +850,12 @@ static void update_buttons(GtkIMHtmlToolbar *toolbar)
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toolbar->italic)) != italic)
toggle_button_set_active_block(GTK_TOGGLE_BUTTON(toolbar->italic), italic,
toolbar);
-
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toolbar->underline)) != underline)
toggle_button_set_active_block(GTK_TOGGLE_BUTTON(toolbar->underline),
underline, toolbar);
+ if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toolbar->strikethrough)) != strike)
+ toggle_button_set_active_block(GTK_TOGGLE_BUTTON(toolbar->strikethrough),
+ strike, toolbar);
/* These buttons aren't ever "active". */
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toolbar->smaller_size), FALSE);
@@ -874,6 +879,12 @@ static void update_buttons(GtkIMHtmlToolbar *toolbar)
gtk_label_set_markup_with_mnemonic(label, markup);
g_free(markup);
}
+ if (strike) {
+ gchar *markup = g_strdup_printf("<s>%s</s>",
+ gtk_label_get_label(label));
+ gtk_label_set_markup_with_mnemonic(label, markup);
+ g_free(markup);
+ }
tmp = gtk_imhtml_get_current_fontface(GTK_IMHTML(toolbar->imhtml));
toggle_button_set_active_block(GTK_TOGGLE_BUTTON(toolbar->font),
diff --git a/pidgin/gtkmain.c b/pidgin/gtkmain.c
index e7006802f3..b6c8025352 100644
--- a/pidgin/gtkmain.c
+++ b/pidgin/gtkmain.c
@@ -768,22 +768,12 @@ int main(int argc, char *argv[])
purple_set_blist(purple_blist_new());
purple_blist_load();
- /* TODO: Move prefs loading into purple_prefs_init() */
- purple_prefs_load();
- purple_prefs_update_old();
- pidgin_prefs_update_old();
-
/* load plugins we had when we quit */
purple_plugins_load_saved(PIDGIN_PREFS_ROOT "/plugins/loaded");
/* TODO: Move pounces loading into purple_pounces_init() */
purple_pounces_load();
- /* Call this early on to try to auto-detect our IP address and
- * hopefully save some time later.
- * TODO: move this (back) into purple_core_init() when purple_prefs_load() is in purple_prefs_init() */
- purple_network_get_my_ip(-1);
-
/* HACK BY SEANEGAN:
* We've renamed prpl-oscar to prpl-aim and prpl-icq, accordingly.
* Let's do that change right here... after everything's loaded, but
@@ -837,10 +827,7 @@ int main(int argc, char *argv[])
g_free(opt_login_arg);
opt_login_arg = NULL;
}
- }
-
- if (opt_nologin && !opt_login)
- {
+ } else if (opt_nologin) {
/* Set all accounts to "offline" */
PurpleSavedStatus *saved_status;
@@ -854,9 +841,7 @@ int main(int argc, char *argv[])
/* Set the status for each account */
purple_savedstatus_activate(saved_status);
- }
- else if (!opt_login)
- {
+ } else {
/* Everything is good to go--sign on already */
if (!purple_prefs_get_bool("/purple/savedstatus/startup_current_status"))
purple_savedstatus_activate(purple_savedstatus_get_startup());
diff --git a/pidgin/gtkprefs.c b/pidgin/gtkprefs.c
index 5196cd651b..e559144336 100644
--- a/pidgin/gtkprefs.c
+++ b/pidgin/gtkprefs.c
@@ -887,7 +887,7 @@ interface_page()
ret = gtk_vbox_new(FALSE, PIDGIN_HIG_CAT_SPACE);
gtk_container_set_border_width(GTK_CONTAINER(ret), PIDGIN_HIG_BORDER);
-
+
sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
vbox = pidgin_make_frame(ret, _("System Tray Icon"));
@@ -899,7 +899,7 @@ interface_page()
NULL);
gtk_size_group_add_widget(sg, label);
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
-
+
vbox = pidgin_make_frame(ret, _("Conversation Window Hiding"));
label = pidgin_prefs_dropdown(vbox, _("_Hide new IM conversations:"),
PURPLE_PREF_STRING, PIDGIN_PREFS_ROOT "/conversations/im/hide_new",
@@ -909,11 +909,11 @@ interface_page()
NULL);
gtk_size_group_add_widget(sg, label);
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
-
+
/* All the tab options! */
vbox = pidgin_make_frame(ret, _("Tabs"));
-
+
pidgin_prefs_checkbox(_("Show IMs and chats in _tabbed windows"),
PIDGIN_PREFS_ROOT "/conversations/tabs", vbox);
@@ -944,12 +944,12 @@ interface_page()
NULL);
gtk_size_group_add_widget(sg, label);
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
-
+
names = pidgin_conv_placement_get_options();
label = pidgin_prefs_dropdown_from_list(vbox2, _("N_ew conversations:"),
PURPLE_PREF_STRING, PIDGIN_PREFS_ROOT "/conversations/placement", names);
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
-
+
gtk_size_group_add_widget(sg, label);
g_list_free(names);
@@ -1620,7 +1620,7 @@ static void select_sound(GtkWidget *button, gpointer being_NULL_is_fun)
filename = NULL;
purple_request_file(prefs, _("Sound Selection"), filename, FALSE,
- G_CALLBACK(sound_chosen_cb), NULL,
+ G_CALLBACK(sound_chosen_cb), NULL,
NULL, NULL, NULL,
GINT_TO_POINTER(sound_row_sel));
}
@@ -2010,7 +2010,7 @@ away_page()
return ret;
}
-static int
+static int
prefs_notebook_add_page(const char *text,
GtkWidget *page,
int ind) {
@@ -2164,6 +2164,8 @@ pidgin_prefs_init(void)
/* Smiley Callbacks */
purple_prefs_connect_callback(prefs, PIDGIN_PREFS_ROOT "/smileys/theme",
smiley_theme_pref_cb, NULL);
+
+ pidgin_prefs_update_old();
}
void pidgin_prefs_update_old()
diff --git a/pidgin/gtksound.c b/pidgin/gtksound.c
index 5b5d8de51f..e662fe9acc 100644
--- a/pidgin/gtksound.c
+++ b/pidgin/gtksound.c
@@ -114,7 +114,7 @@ static void
play_conv_event(PurpleConversation *conv, PurpleSoundEventID event)
{
/* If we should not play the sound for some reason, then exit early */
- if (conv != NULL)
+ if (conv != NULL && PIDGIN_IS_PIDGIN_CONVERSATION(conv))
{
PidginConversation *gtkconv;
PidginWindow *win;
diff --git a/pidgin/gtksourceundomanager.c b/pidgin/gtksourceundomanager.c
index 14528f3595..55564d0da9 100644
--- a/pidgin/gtksourceundomanager.c
+++ b/pidgin/gtksourceundomanager.c
@@ -677,8 +677,6 @@ gtk_source_undo_manager_insert_text_handler (GtkTextBuffer *buffer,
if (um->priv->running_not_undoable_actions > 0)
return;
- g_return_if_fail (strlen (text) >= (guint)length);
-
undo_action.action_type = GTK_SOURCE_UNDO_ACTION_INSERT;
undo_action.action.insert.pos = gtk_text_iter_get_offset (pos);
@@ -774,7 +772,7 @@ gtk_source_undo_manager_add_action (GtkSourceUndoManager *um,
*action = *undo_action;
if (action->action_type == GTK_SOURCE_UNDO_ACTION_INSERT)
- action->action.insert.text = g_strdup (undo_action->action.insert.text);
+ action->action.insert.text = g_strndup (undo_action->action.insert.text, undo_action->action.insert.length);
else if (action->action_type == GTK_SOURCE_UNDO_ACTION_DELETE)
action->action.delete.text = g_strdup (undo_action->action.delete.text);
else
diff --git a/pidgin/gtkstatusbox.c b/pidgin/gtkstatusbox.c
index 1d520851f1..0250c06bd1 100644
--- a/pidgin/gtkstatusbox.c
+++ b/pidgin/gtkstatusbox.c
@@ -1394,7 +1394,7 @@ pidgin_status_box_popup(PidginStatusBox *box)
return;
}
gtk_grab_add (box->popup_window);
- box->popup_in_progress = TRUE;
+// box->popup_in_progress = TRUE;
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (box->toggle_button),
TRUE);
@@ -1590,14 +1590,15 @@ treeview_button_release_cb(GtkWidget *widget, GdkEventButton *event, PidginStatu
gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (status_box->toggle_button))) {
pidgin_status_box_popdown (status_box);
return TRUE;
+ } else if (ewidget == status_box->toggle_button) {
+ status_box->popup_in_progress = TRUE;
}
/* released outside treeview */
- if (ewidget != status_box->toggle_button)
- {
+ if (ewidget != status_box->toggle_button) {
pidgin_status_box_popdown (status_box);
return TRUE;
- }
+ }
return FALSE;
}
diff --git a/pidgin/plugins/notify.c b/pidgin/plugins/notify.c
index 921bfe9050..d9b8cf8a48 100644
--- a/pidgin/plugins/notify.c
+++ b/pidgin/plugins/notify.c
@@ -167,7 +167,7 @@ notify(PurpleConversation *conv, gboolean increment)
gboolean has_focus;
PidginWindow *purplewin = NULL;
- if (conv == NULL)
+ if (conv == NULL || PIDGIN_CONVERSATION(conv) == NULL)
return 0;
/* We want to remove the notifications, but not reset the counter */
@@ -224,6 +224,8 @@ unnotify(PurpleConversation *conv, gboolean reset)
PidginWindow *purplewin = NULL;
g_return_if_fail(conv != NULL);
+ if (PIDGIN_CONVERSATION(conv) == NULL)
+ return;
purplewin = PIDGIN_CONVERSATION(conv)->win;
active_conv = pidgin_conv_window_get_active_conversation(purplewin);
@@ -417,10 +419,14 @@ static void
deleting_conv(PurpleConversation *conv)
{
PidginWindow *purplewin = NULL;
+ PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
+
+ if (gtkconv == NULL)
+ return;
detach_signals(conv);
- purplewin = PIDGIN_CONVERSATION(conv)->win;
+ purplewin = gtkconv->win;
handle_urgent(purplewin, FALSE);
purple_conversation_set_data(conv, "notify-message-count", GINT_TO_POINTER(0));
diff --git a/pidgin/win32/nsis/pidgin-installer.nsi b/pidgin/win32/nsis/pidgin-installer.nsi
index 7234783d25..b488b72f4e 100644
--- a/pidgin/win32/nsis/pidgin-installer.nsi
+++ b/pidgin/win32/nsis/pidgin-installer.nsi
@@ -503,8 +503,8 @@ Section $(PIDGIN_SECTION_TITLE) SecPidgin
${If} ${IsNT}
${AndIf} ${IsWinNT4}
Delete "$INSTDIR\plugins\libsilc.dll"
- Delete "$INSTDIR\silcclient.dll"
- Delete "$INSTDIR\silc.dll"
+ Delete "$INSTDIR\libsilcclient-1-1-2.dll"
+ Delete "$INSTDIR\libsilc-1-1-2.dll"
${EndIf}
SetOutPath "$INSTDIR"
@@ -693,6 +693,8 @@ Section Uninstall
; Remove Language preference info (TODO: check if NSIS removes this)
Delete "$INSTDIR\ca-certs\Equifax_Secure_CA.pem"
+ Delete "$INSTDIR\ca-certs\GTE_CyberTrust_Global_Root.pem"
+ Delete "$INSTDIR\ca-certs\Verisign_Class3_Primary_CA.pem"
Delete "$INSTDIR\ca-certs\Verisign_RSA_Secure_Server_CA.pem"
RMDir "$INSTDIR\ca-certs"
RMDir /r "$INSTDIR\locale"
@@ -764,8 +766,8 @@ Section Uninstall
Delete "$INSTDIR\pidgin.dll"
Delete "$INSTDIR\plc4.dll"
Delete "$INSTDIR\plds4.dll"
- Delete "$INSTDIR\silc.dll"
- Delete "$INSTDIR\silcclient.dll"
+ Delete "$INSTDIR\libsilc-1-1-2.dll"
+ Delete "$INSTDIR\libsilcclient-1-1-2.dll"
Delete "$INSTDIR\smime3.dll"
Delete "$INSTDIR\softokn3.dll"
Delete "$INSTDIR\ssl3.dll"
diff --git a/share/ca-certs/GTE_CyberTrust_Global_Root.pem b/share/ca-certs/GTE_CyberTrust_Global_Root.pem
new file mode 100644
index 0000000000..63d8d23fe3
--- /dev/null
+++ b/share/ca-certs/GTE_CyberTrust_Global_Root.pem
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgw
+FgYDVQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRy
+dXN0IFNvbHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3Qg
+R2xvYmFsIFJvb3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1
+MQswCQYDVQQGEwJVUzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYD
+VQQLEx5HVEUgQ3liZXJUcnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMT
+GkdURSBDeWJlclRydXN0IEdsb2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUA
+A4GNADCBiQKBgQCVD6C28FCc6HrHiM3dFw4usJTQGz0O9pTAipTHBsiQl8i4
+ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTSr41tiGeA5u2ylc9yMcqlHHK6XALn
+ZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X404Wqk2kmhXBIgD8SFcd5tB8F
+LztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3rGwnpXtlR22ciYaQqPEh3
+46B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l93PR2VX2bY1QY6fDq
+81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0PlZPvy5TYnh+d
+XIVtx6quTx8itc2VrbqnzPmrC3p/
+-----END CERTIFICATE-----
diff --git a/share/ca-certs/Makefile.am b/share/ca-certs/Makefile.am
index d4bbd60ffe..56350ca42d 100644
--- a/share/ca-certs/Makefile.am
+++ b/share/ca-certs/Makefile.am
@@ -1,8 +1,11 @@
cacertsdir = $(datadir)/purple/ca-certs
cacerts_DATA = \
Equifax_Secure_CA.pem \
- Verisign_RSA_Secure_Server_CA.pem
+ GTE_CyberTrust_Global_Root.pem \
+ Verisign_RSA_Secure_Server_CA.pem \
+ Verisign_Class3_Primary_CA.pem
-EXTRA_DIST = \
- $(cacerts_DATA)
+EXTRA_DIST = \
+ Makefile.mingw \
+ $(cacerts_DATA)
diff --git a/share/ca-certs/Verisign_Class3_Primary_CA.pem b/share/ca-certs/Verisign_Class3_Primary_CA.pem
new file mode 100644
index 0000000000..87676acf5f
--- /dev/null
+++ b/share/ca-certs/Verisign_Class3_Primary_CA.pem
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG
+A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
+cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
+MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
+BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt
+YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE
+BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is
+I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G
+CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do
+lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc
+AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k
+-----END CERTIFICATE-----