[pkg-otr-team] [irssi-plugin-otr] 26/167: Merged Version_3_Dev branch
Holger Levsen
holger at moszumanska.debian.org
Mon Mar 3 21:55:29 UTC 2014
This is an automated email from the git hooks/post-receive script.
holger pushed a commit to tag 4.0.0
in repository irssi-plugin-otr.
commit f0c6b8e1391b7d1397b9c973477d75a31fbfea5c
Author: cypherpunk <cypherpunk>
Date: Tue Jul 24 19:34:04 2007 +0000
Merged Version_3_Dev branch
---
AUTHORS | 2 +-
ChangeLog | 81 ++
INSTALL | 19 +-
Makefile.am | 16 +-
Makefile.mingw | 20 +-
Makefile.static | 21 +
NEWS | 11 +
README | 19 +-
configure.ac | 22 +-
dialogs.c | 26 +-
dialogs.h | 23 +-
gtk-dialog.c | 1034 ++++++++++++++++----
gtk-dialog.h | 2 +-
gtk-ui.c | 234 +++--
gtk-ui.h | 2 +-
makedist | 1 +
otr-plugin.c | 364 +++++--
otr-plugin.h | 19 +-
.../fedora/{gaim-otr.spec => pidgin-otr.spec} | 18 +-
packaging/windows/gaim-otr.nsi | 221 -----
po/ChangeLog | 0
po/Makefile.mingw | 57 ++
po/POTFILES.in | 12 +
po/README | 7 +
ui.c | 50 +-
ui.h | 26 +-
26 files changed, 1693 insertions(+), 614 deletions(-)
diff --git a/AUTHORS b/AUTHORS
index dc38a08..f9406d8 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -2,6 +2,6 @@ Off-the-Record Messaging plugin for pidgin
Authors:
- Nikita Borisov and Ian Goldberg <otr at cypherpunks.ca>
+ Ian Goldberg, Chris Alexander, Nikita Borisov <otr at cypherpunks.ca>
See the README file for mailing list information
diff --git a/ChangeLog b/ChangeLog
index 18bdd3e..b9fd875 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,84 @@
+2007-07-24
+
+ * INSTALL: Added information about i18n; added information about
+ linking libgcrypt statically
+
+ * otr-plugin.c: Added support for transparent fragmentation of
+ large messages
+
+ * Most files: Updated copyright information
+
+2007-07-22
+
+ * configure.ac: Check for libpurple and use a recent format for
+ AC_INIT/AM_INIT_AUTOMAKE, based on a patch from <synx13 at sf.net>.
+
+2007-07-18
+
+ * gtk-ui.c: Simplify account list option menu in Config UI,
+ thanks to Gabriel Schulhof <nix at go-nix.ca>.
+
+ * gtk-ui.c: Reorder the tabs in the Config UI so that Config is
+ first.
+
+ * README: Updated to reflect new tab ordering, and new
+ "Don't log OTR conversations" option.
+
+ * gtk-dialog.c: Fixed a bug in the verify fingerprint dialog in
+ the unlikely event that a fingerprint exists in the fingerprints
+ file with no corresponding key for the local account in the
+ private keys file.
+
+2007-07-17
+
+ * dialogs.c:
+ * dialogs.h:
+ * gtk-dialog.c: Removed Verify fingerprint and View secure
+ session id menu options. Added "Advanced..." button to
+ Authenticate buddy dialog, which brings up the old Verify
+ fingerprint dialog. The Authenticate buddy dialog now allows
+ users to authenticate their buddies without ever seeing a
+ fingerprint.
+
+2007-07-10
+
+ * dialogs.c:
+ * dialogs.h:
+ * gtk-dialog.c:
+ * gtk-ui.c:
+ * otr-plugin.c:
+ * ui.c:
+ * ui.h: Added init() and cleanup() callbacks to the ui and
+ dialog subsystems that are called when the plugin is loaded and
+ unloaded respectively.
+
+ * gtk-dialog.c: Fixed bug where multiple OTR buttons in one
+ window would cause pidgin to crash when the window is closed.
+
+2007-07-08
+
+ * otr-plugin.c:
+ * gtk-dialog.c:
+ * gtk-ui.c: Added an option to not log OTR conversations.
+
+ * gtk-ui.c:
+ * ui.c:
+ * ui.h: Generalized find_policy to get_prefs, allowing for other
+ preferences to be available.
+
+2007-07-07
+
+ * INSTALL: Update dependency information
+
+ * Makefile.am:
+ * Makefile.mingw:
+ * configure.ac:
+ * gtk-dialog.c:
+ * gtk-ui.c:
+ * makedist:
+ * otr-plugin.c:
+ * ui.c: i18n, thanks to Thomas B. <Tommy.B at gmx.net>.
+
2007-05-06
* Makefile.am:
diff --git a/INSTALL b/INSTALL
index ea0437e..7c4aacc 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,12 +1,15 @@
REQUIREMENTS
-To compile the OTR plugin for gaim, you'll need at least:
+To compile the OTR plugin for pidgin, you'll need at least:
- libgpg-error 1.0 [ftp://ftp.gnupg.org/gcrypt/libgpg-error/]
- libgcrypt 1.2.0 [ftp://ftp.gnupg.org/gcrypt/libgcrypt/]
- - libotr 1.99.0 [http://www.cypherpunks.ca/otr/]
- - glib 2.4 [http://www.gtk.org/download/]
- - gtk+ 2.4 [http://www.gtk.org/download/]
- - gaim 1.x [http://gaim.sourceforge.net/downloads.php]
+ - libotr 3.1.0 [http://otr.cypherpunks.ca/]
+ - glib 2.6 [http://www.gtk.org/download/]
+ - gtk+ 2.6 [http://www.gtk.org/download/]
+ - pidgin 2.x [http://pidgin.im/]
+
+You'll also need the usual autotools, such as automake-1.9, autoreconf,
+libtool, intltool, etc.
If you install these with a package manager, you'll probably need the
-dev or -devel versions of the packages.
@@ -16,6 +19,7 @@ COMPILING (non-Win32)
If you're got a CVS copy, you will need to regenerate the configure
script using:
+ intltoolize --force --copy
autoreconf -s -i
[If you installed libotr.m4 somewhere that autoreconf can't find it,
@@ -36,6 +40,11 @@ NETBSD:
Once the configure script writes a Makefile, you should be able to just
run "make".
+If you want a plugin that has libgcrypt linked statically, use
+"make -f Makefile.static". Makefile.static assumes libotr.a and libgcrypt.a
+are available in /usr/lib. If they're somewhere else, use something like
+"LIBOTRDIR=/usr/local/lib make -f Makefile.static".
+
COMPILING (Win32)
Use the provided Makefile.mingw:
diff --git a/Makefile.am b/Makefile.am
index ac0235a..509a8c5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,14 +1,22 @@
AM_CFLAGS= @LIBGCRYPT_CFLAGS@ @LIBOTR_CFLAGS@ @EXTRA_CFLAGS@
AM_CFLAGS+= -DUSING_GTK -DPURPLE_PLUGINS \
- -DPIDGIN_OTR_VERSION=\"@VERSION@\"
+ -DPIDGIN_OTR_VERSION=\"@VERSION@\" \
+ -DLOCALEDIR=\"$(datadir)/locale\"
+
+SUBDIRS= po
plugindir= ${libdir}/pidgin
plugin_LTLIBRARIES= pidgin-otr.la
-pidgin_otr_la_SOURCES= otr-plugin.c ui.c dialogs.c gtk-ui.c gtk-dialog.c
-pidgin_otr_la_LDFLAGS= -module -avoid-version
+pidgin_otr_la_SOURCES= otr-plugin.c ui.c dialogs.c gtk-ui.c gtk-dialog.c
+pidgin_otr_la_LDFLAGS= -module -avoid-version
pidgin_otr_la_LDFLAGS+= @LIBGCRYPT_LIBS@ @LIBOTR_LIBS@
EXTRA_DIST= dialogs.h gtk-dialog.h gtk-ui.h otr-plugin.h ui.h \
- Makefile.mingw packaging
+ Makefile.mingw packaging/windows/pidgin-otr.nsi \
+ packaging/fedora/pidgin-otr.spec po/Makefile.mingw \
+ po/README intltool-extract.in intltool-merge.in \
+ intltool-update.in Makefile.static
+
+DISTCLEANFILES= intltool-extract intltool-merge intltool-update
diff --git a/Makefile.mingw b/Makefile.mingw
index 3850847..45100f2 100644
--- a/Makefile.mingw
+++ b/Makefile.mingw
@@ -1,7 +1,10 @@
WIN32=1
# The version number to put in the plugin info
-PIDGIN_OTR_VERSION = 3.0.0
+PIDGIN_OTR_VERSION = 3.1.0
+
+# Name of the gettext domain
+GETTEXT_PACKAGE = pidgin-otr
# Replace this with the path to the pidgin and purple headers
PIDGIN_HEADERS ?= /usr/i586-mingw32msvc/include/pidgin
@@ -18,6 +21,12 @@ LIBOTRINCDIR = /usr/include
# The locataion of libotr.a.
LIBOTRLIBDIR = /usr/lib
+# Location of libintl.h
+LIBINTLINCDIR = /usr/i586-mingw32msvc/include
+
+# Location of libintl.a
+LIBINTLLIBDIR = /usr/i586-mingw32msvc/lib
+
# The target
TARGET = pidgin-otr.so
@@ -28,7 +37,8 @@ LIBOTRLIBDIR = /usr/i586-mingw32msvc/lib
TARGET = pidgin-otr.dll
LDFLAGS = -Wl,--enable-auto-image-base
LDLIBS = $(LIBOTRLIBDIR)/libotr.a -lgtk-win32-2.0 -lglib-2.0 -lgdk_pixbuf-2.0 \
- -lgobject-2.0 -lpidgin -llibpurple -lgcrypt -lgpg-error
+ -lgobject-2.0 -lpidgin -llibpurple -lgcrypt -lgpg-error \
+ -L$(LIBINTLLIBDIR) -lintl
else
FPIC = -fPIC
LDFLAGS = -module -avoid-version
@@ -42,7 +52,9 @@ INSTALLDIR = $(DESTDIR)$(PIDGINDIR)
CC ?= gcc
override CFLAGS += -g -Wall -I$(PIDGIN_HEADERS) -I$(PURPLE_HEADERS) \
$(GTK_HDRS) -I$(LIBOTRINCDIR) $(FPIC) -DUSING_GTK -DPURPLE_PLUGINS \
- -DPIDGIN_OTR_VERSION=\"$(PIDGIN_OTR_VERSION)\" -DPIDGIN_NAME=\"Pidgin\"
+ -DPIDGIN_OTR_VERSION=\"$(PIDGIN_OTR_VERSION)\" \
+ -DPIDGIN_NAME=\"Pidgin\" -I$(LIBINTLINCDIR) -DENABLE_NLS \
+ -DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\"
all: $(TARGET)
@@ -52,6 +64,8 @@ $(TARGET): otr-plugin.o ui.o dialogs.o gtk-ui.o gtk-dialog.o
install: all
install -d $(INSTALLDIR)
install -m 0755 $(TARGET) $(INSTALLDIR)
+ $(MAKE) -C po -f Makefile.mingw install
+
clean:
rm -f *.o
rm -f $(TARGET)
diff --git a/Makefile.static b/Makefile.static
new file mode 100644
index 0000000..2533bb4
--- /dev/null
+++ b/Makefile.static
@@ -0,0 +1,21 @@
+LIBOTRDIR?=/usr/lib
+LIBGCRYPTDIR?=/usr/lib
+
+.libs/pidgin-otr.so: FORCE
+ # Build everything from the standard Makefile
+ make
+ # Link everything, including libotr and libgcrypt, together into
+ # a single .o file
+ ld -r .libs/otr-plugin.o .libs/ui.o .libs/dialogs.o .libs/gtk-ui.o \
+ .libs/gtk-dialog.o $(LIBOTRDIR)/libotr.a \
+ $(LIBGCRYPTDIR)/libgcrypt.a /usr/lib/libgpg-error.a \
+ -o .libs/pidgin-otr-shared.o
+ # Make all the libgcrypt references local to that .o file
+ objcopy -w -L '*gcry*' .libs/pidgin-otr-shared.o \
+ .libs/pidgin-otr-static.o
+ # Turn the .o into a .so
+ gcc -shared .libs/pidgin-otr-static.o -Wl,-soname -Wl,pidgin-otr.so \
+ -o .libs/pidgin-otr.so
+
+FORCE:
+
diff --git a/NEWS b/NEWS
index bb7cd07..ac96c6d 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,14 @@
+24 Jul 2007:
+- Added option to not log OTR conversations
+- Large messages are now fragmented transparently instead of failing
+- Removed "view secure session id" and "verify fingerprint" options from
+ OTR button menu. Added "authenticate buddy" option in its place. This
+ new option allows you to authenticate your buddies by entering some
+ secret that only the two of you know, rather than by using a long
+ user-unfriendly sequence of hex characters. [The old "verify
+ fingerprint" dialog is still available via an "Advanced..." button
+ from the new "authenticate buddy" dialog.]
+
06 May 2007:
- Ported to Pidgin 2.0.0
diff --git a/README b/README
index 55b8eac..ac4ed38 100644
--- a/README
+++ b/README
@@ -1,5 +1,5 @@
Off-the-Record Messaging plugin for pidgin
- v3.0.0, 6 May 2007
+ v3.1.0, XX XXX 2007
This is a pidgin plugin which implements Off-the-Record (OTR) Messaging.
It is known to work (at least) under the Linux and Windows versions of
@@ -21,7 +21,7 @@ OTR allows you to have private conversations over IM by providing:
is compromised.
For more information on Off-the-Record Messaging, see
-http://www.cypherpunks.ca/otr/
+http://otr.cypherpunks.ca/
USAGE
@@ -29,7 +29,7 @@ Run pidgin, and open the Plugins panel. (If you had a copy of pidgin
running before you installed pidgin-otr, you will need to restart it.)
Find the Off-the-Record Messaging plugin, and enable it by selecting the
checkbox next to it. Click "Configure Plugin" to bring up the OTR UI.
-The UI has two "pages": "Known fingerprints" and "Config".
+The UI has two "pages": "Config" and "Known fingerprints".
The "Config" page allows you generate private keys, and to set OTR
options.
@@ -52,6 +52,7 @@ options.
[X] Enable private messaging
[X] Automatically initiate private messaging
[ ] Require private messaging
+ [ ] Don't log OTR conversations
If the "enable private messaging" box is unchecked, private messages
will be disabled completely (and the other two boxes will be greyed
@@ -68,9 +69,13 @@ options.
understand OTR private messages, and if so, automatically start a
private conversation.
- If all three boxes are checked, messages will not be sent to your
+ If the first three boxes are checked, messages will not be sent to your
buddy unless you are in a private conversation.
+ If the fourth box is checked, OTR-protected conversations will not
+ be logged, even if logging of instant messages is turned on in
+ pidgin.
+
The "Known fingerprints" page allows you to see the fingerprints of any
buddies you have previously communicated with privately.
@@ -222,7 +227,7 @@ The Off-the-Record Messaging plugin for pidgin is covered by the following
(GPL) license:
Off-the-Record Messaging plugin for pidgin
- Copyright (C) 2004-2005 Nikita Borisov and Ian Goldberg
+ Copyright (C) 2004-2007 Ian Goldberg, Chris Alexander, Nikita Borisov
<otr at cypherpunks.ca>
This program is free software; you can redistribute it and/or modify
@@ -244,7 +249,7 @@ CONTACT
To report problems, comments, suggestions, patches, etc., you can email
the authors:
-Nikita Borisov and Ian Goldberg <otr at cypherpunks.ca>
+Ian Goldberg, Chris Alexander, and Nikita Borisov <otr at cypherpunks.ca>
For more information on Off-the-Record Messaging, visit
-http://www.cypherpunks.ca/otr/
+http://otr.cypherpunks.ca/
diff --git a/configure.ac b/configure.ac
index afb5e6d..c98eb23 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,13 +1,10 @@
dnl Process this file with autoconf to produce configure.
-dnl XXX Check for headers, etc.
-
-dnl Not yet used.
-AC_INIT(otr-plugin.c)
+AC_INIT(pidgin-otr, 3.1.0)
AM_CONFIG_HEADER(config.h)
-AM_INIT_AUTOMAKE(pidgin-otr, 3.0.0)
+AM_INIT_AUTOMAKE([-Wall -Werror])
AC_PROG_CC
@@ -17,8 +14,17 @@ AM_PROG_LIBTOOL
AM_PATH_LIBGCRYPT(1:1.2.0,,AC_MSG_ERROR(libgcrypt 1.2.0 or newer is required.))
-AM_PATH_LIBOTR(3.0.0,,AC_MSG_ERROR(libotr 3.0.0 or newer is required.))
+AM_PATH_LIBOTR(3.1.0,,AC_MSG_ERROR(libotr 3.1.0 or newer is required.))
+
+PKG_CHECK_MODULES(EXTRA, glib-2.0 >= 2.6 gtk+-2.0 >= 2.6 pidgin >= 2.0 purple >= 2.0, , AC_MSG_ERROR(glib, gtk, pidgin and purple required))
+
+AC_PROG_INTLTOOL
+
+GETTEXT_PACKAGE=pidgin-otr
+AC_SUBST(GETTEXT_PACKAGE)
+AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, ["$GETTEXT_PACKAGE"], [Define the gettext package to be used])
-PKG_CHECK_MODULES(EXTRA, glib-2.0 >= 2.4 gtk+-2.0 >= 2.4 pidgin >= 2.0, , AC_MSG_ERROR(glib, gtk and pidgin required))
+ALL_LINGUAS=""
+AM_GLIB_GNU_GETTEXT
-AC_OUTPUT([Makefile])
+AC_OUTPUT([Makefile po/Makefile.in])
diff --git a/dialogs.c b/dialogs.c
index 0266278..997d8ba 100644
--- a/dialogs.c
+++ b/dialogs.c
@@ -1,6 +1,6 @@
/*
* Off-the-Record Messaging plugin for pidgin
- * Copyright (C) 2004-2005 Nikita Borisov and Ian Goldberg
+ * Copyright (C) 2004-2007 Ian Goldberg, Chris Alexander, Nikita Borisov
* <otr at cypherpunks.ca>
*
* This program is free software; you can redistribute it and/or modify
@@ -49,6 +49,18 @@ const OtrgDialogUiOps *otrg_dialog_get_ui_ops(void)
return ui_ops;
}
+/* Initialize the OTR dialog subsystem */
+void otrg_dialog_init(void)
+{
+ ui_ops->init();
+}
+
+/* Deinitialize the OTR dialog subsystem */
+void otrg_dialog_cleanup(void)
+{
+ ui_ops->cleanup();
+}
+
/* This is just like pidgin_notify_message, except: (a) it doesn't grab
* keyboard focus, (b) the button is "OK" instead of "Close", and (c)
* the labels aren't limited to 2K. */
@@ -125,6 +137,18 @@ void otrg_dialog_verify_fingerprint(Fingerprint *fprint)
ui_ops->verify_fingerprint(fprint);
}
+/* Show a dialog asking the user to give an SMP secret. */
+void otrg_dialog_socialist_millionaires(ConnContext *context)
+{
+ ui_ops->socialist_millionaires(context, TRUE);
+}
+
+/* Update the status of an ongoing socialist millionaires protocol. */
+void otrg_dialog_update_smp(ConnContext *context, double progress_level)
+{
+ ui_ops->update_smp(context, progress_level);
+}
+
/* Call this when a context transitions to ENCRYPTED. */
void otrg_dialog_connected(ConnContext *context)
{
diff --git a/dialogs.h b/dialogs.h
index 733208e..f3eaf64 100644
--- a/dialogs.h
+++ b/dialogs.h
@@ -1,6 +1,6 @@
/*
* Off-the-Record Messaging plugin for pidgin
- * Copyright (C) 2004-2005 Nikita Borisov and Ian Goldberg
+ * Copyright (C) 2004-2007 Ian Goldberg, Chris Alexander, Nikita Borisov
* <otr at cypherpunks.ca>
*
* This program is free software; you can redistribute it and/or modify
@@ -29,6 +29,7 @@
/* The various help URLs */
#define BASE_HELPURL "http://otr-help.cypherpunks.ca/"
+#define AUTHENTICATE_HELPURL BASE_HELPURL "authenticate.php"
#define FINGERPRINT_HELPURL BASE_HELPURL "fingerprint.php"
#define SESSIONID_HELPURL BASE_HELPURL "sessionid.php"
#define UNVERIFIED_HELPURL BASE_HELPURL "unverified.php"
@@ -37,6 +38,10 @@
typedef struct s_OtrgDialogWait *OtrgDialogWaitHandle;
typedef struct {
+ void (*init)(void);
+
+ void (*cleanup)(void);
+
void (*notify_message)(PurpleNotifyMsgType type,
const char *accountname, const char *protocol, const char *username,
const char *title, const char *primary, const char *secondary);
@@ -54,6 +59,10 @@ typedef struct {
void (*verify_fingerprint)(Fingerprint *fprint);
+ void (*socialist_millionaires)(ConnContext *context, gboolean responder);
+
+ void (*update_smp)(ConnContext *context, double progress_level);
+
void (*connected)(ConnContext *context);
void (*disconnected)(ConnContext *context);
@@ -76,6 +85,12 @@ void otrg_dialog_set_ui_ops(const OtrgDialogUiOps *ops);
/* Get the UI ops */
const OtrgDialogUiOps *otrg_dialog_get_ui_ops(void);
+/* Initialize the OTR dialog subsystem */
+void otrg_dialog_init(void);
+
+/* Deinitialize the OTR dialog subsystem */
+void otrg_dialog_cleanup(void);
+
/* This is just like pidgin_notify_message, except: (a) it doesn't grab
* keyboard focus, (b) the button is "OK" instead of "Close", and (c)
* the labels aren't limited to 2K. */
@@ -121,6 +136,12 @@ void otrg_dialog_unknown_fingerprint(OtrlUserState us, const char *accountname,
/* Show a dialog asking the user to verify the given fingerprint. */
void otrg_dialog_verify_fingerprint(Fingerprint *fprint);
+/* Show a dialog asking the user to give an SMP secret. */
+void otrg_dialog_socialist_millionaires(ConnContext *context);
+
+/* Update the status of an ongoing socialist millionaires protocol. */
+void otrg_dialog_update_smp(ConnContext *context, double progress_level);
+
/* Call this when a context transitions to ENCRYPTED. */
void otrg_dialog_connected(ConnContext *context);
diff --git a/gtk-dialog.c b/gtk-dialog.c
index df5a97d..8006ee6 100644
--- a/gtk-dialog.c
+++ b/gtk-dialog.c
@@ -1,6 +1,6 @@
/*
* Off-the-Record Messaging plugin for pidgin
- * Copyright (C) 2004-2005 Nikita Borisov and Ian Goldberg
+ * Copyright (C) 2004-2007 Ian Goldberg, Chris Alexander, Nikita Borisov
* <otr at cypherpunks.ca>
*
* This program is free software; you can redistribute it and/or modify
@@ -17,6 +17,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+/* config.h */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
/* system headers */
#include <stdio.h>
#include <stdlib.h>
@@ -35,6 +40,11 @@
#include "gtkimhtml.h"
#include "util.h"
+#ifdef ENABLE_NLS
+/* internationalisation headers */
+#include <glib/gi18n-lib.h>
+#endif
+
/* libotr headers */
#include <libotr/dh.h>
#include <libotr/privkey.h>
@@ -45,6 +55,7 @@
/* purple-otr headers */
#include "otr-plugin.h"
#include "dialogs.h"
+#include "gtk-dialog.h"
#include "ui.h"
/* The OTR icons */
@@ -593,6 +604,69 @@ static const char * finished_xpm[] = {
" + + &.+ + *.+ + ",
" + + + + + "};
+typedef struct {
+ ConnContext *context; /* The context used to fire library code */
+ GtkEntry *entry; /* The text entry field containing the secret */
+ gboolean responder; /* Whether or not this is the first side to give
+ their secret */
+} SmpResponsePair;
+
+/* The response code returned by pushing the "Advanced..." button on the
+ * SMP dialog */
+#define OTRG_RESPONSE_ADVANCED 1
+
+/* Information used by the plugin that is specific to both the
+ * application and connection. */
+typedef struct dialog_context_data {
+ GtkWidget *smp_secret_dialog;
+ SmpResponsePair *smp_secret_smppair;
+ GtkWidget *smp_progress_dialog;
+ GtkWidget *smp_progress_bar;
+ GtkWidget *smp_progress_label;
+} SMPData;
+
+static void close_progress_window(SMPData *smp_data)
+{
+ if (smp_data->smp_progress_dialog) {
+ gtk_dialog_response(GTK_DIALOG(smp_data->smp_progress_dialog),
+ GTK_RESPONSE_REJECT);
+ }
+ smp_data->smp_progress_dialog = NULL;
+ smp_data->smp_progress_bar = NULL;
+ smp_data->smp_progress_label = NULL;
+}
+
+static void otrg_gtk_dialog_free_smp_data(PurpleConversation *conv)
+{
+ SMPData *smp_data = purple_conversation_get_data(conv, "otr-smpdata");
+ if (!smp_data) return;
+
+ if (smp_data->smp_secret_dialog) {
+ gtk_dialog_response(GTK_DIALOG(smp_data->smp_secret_dialog),
+ GTK_RESPONSE_REJECT);
+ }
+ smp_data->smp_secret_dialog = NULL;
+ smp_data->smp_secret_smppair = NULL;
+
+ close_progress_window(smp_data);
+
+ free(smp_data);
+
+ g_hash_table_remove(conv->data, "otr-smpdata");
+}
+
+static void otrg_gtk_dialog_add_smp_data(PurpleConversation *conv)
+{
+ SMPData *smp_data = malloc(sizeof(SMPData));
+ smp_data->smp_secret_dialog = NULL;
+ smp_data->smp_secret_smppair = NULL;
+ smp_data->smp_progress_dialog = NULL;
+ smp_data->smp_progress_bar = NULL;
+ smp_data->smp_progress_label = NULL;
+
+ purple_conversation_set_data(conv, "otr-smpdata", smp_data);
+}
+
static GtkWidget *otr_icon(GtkWidget *image, TrustLevel level)
{
GdkPixbuf *pixbuf = NULL;
@@ -629,7 +703,111 @@ static void message_response_cb(GtkDialog *dialog, gint id, GtkWidget *widget)
gtk_widget_destroy(GTK_WIDGET(widget));
}
-static GtkWidget *create_dialog(PurpleNotifyMsgType type, const char *title,
+/* Forward declarations for the benefit of smp_message_response_cb */
+static void verify_fingerprint(GtkWindow *parent, Fingerprint *fprint);
+static GtkWidget *create_smp_progress_dialog(GtkWindow *parent,
+ ConnContext *context);
+
+/* Called when a button is pressed on the "progress bar" smp dialog */
+static void smp_progress_response_cb(GtkDialog *dialog, gint response,
+ ConnContext *context)
+{
+ PurpleConversation *conv = otrg_plugin_context_to_conv(context, 0);
+ SMPData *smp_data = NULL;
+
+ if (conv) {
+ gdouble frac;
+
+ smp_data = purple_conversation_get_data(conv, "otr-smpdata");
+ frac = gtk_progress_bar_get_fraction(
+ GTK_PROGRESS_BAR(smp_data->smp_progress_bar));
+
+ if (frac != 0.0 && frac != 1.0 && response == GTK_RESPONSE_REJECT) {
+ otrg_plugin_abort_smp(context);
+ }
+ }
+ /* In all cases, destroy the current window */
+ gtk_widget_destroy(GTK_WIDGET(dialog));
+
+ /* Clean up variables pointing to the destroyed objects */
+
+ if (smp_data) {
+ smp_data->smp_progress_bar = NULL;
+ smp_data->smp_progress_label = NULL;
+ smp_data->smp_progress_dialog = NULL;
+ }
+}
+
+/* Called when a button is pressed on the "enter the secret" smp dialog
+ * The data passed contains a pointer to the text entry field containing
+ * the entered secret as well as the current context.
+ */
+static void smp_secret_response_cb(GtkDialog *dialog, gint response,
+ SmpResponsePair *smppair)
+{
+ if (!smppair) return;
+
+ ConnContext* context = smppair->context;
+ if (response == GTK_RESPONSE_ACCEPT) {
+ GtkEntry* entry = smppair->entry;
+ char *secret;
+ size_t secret_len;
+
+ if (context == NULL || context->msgstate != OTRL_MSGSTATE_ENCRYPTED)
+ return;
+
+ secret = g_strdup(gtk_entry_get_text(entry));
+
+ secret_len = strlen(secret);
+
+ if (smppair->responder) {
+ otrg_plugin_continue_smp(context, (const unsigned char *)secret,
+ secret_len);
+ } else {
+ otrg_plugin_start_smp(context, (const unsigned char *)secret,
+ secret_len);
+ }
+ g_free(secret);
+
+ /* launch progress bar window */
+ create_smp_progress_dialog(GTK_WINDOW(dialog), context);
+ } else if (response == OTRG_RESPONSE_ADVANCED) {
+ ConnContext* context = smppair->context;
+
+ if (context == NULL || context->msgstate != OTRL_MSGSTATE_ENCRYPTED)
+ return;
+
+ verify_fingerprint(GTK_WINDOW(dialog), context->active_fingerprint);
+ } else {
+ otrg_plugin_abort_smp(context);
+ }
+ /* In all cases, destroy the current window */
+ gtk_widget_destroy(GTK_WIDGET(dialog));
+
+ /* Clean up references to this window */
+ PurpleConversation *conv =
+ otrg_plugin_context_to_conv(smppair->context, 0);
+ SMPData *smp_data = purple_conversation_get_data(conv, "otr-smpdata");
+ if (smp_data) {
+ smp_data->smp_secret_dialog = NULL;
+ smp_data->smp_secret_smppair = NULL;
+ }
+
+ /* Free the smppair memory */
+ free(smppair);
+}
+
+static void close_smp_window(PurpleConversation *conv)
+{
+ SMPData *smp_data = purple_conversation_get_data(conv, "otr-smpdata");
+ if (smp_data && smp_data->smp_secret_dialog) {
+ gtk_dialog_response(GTK_DIALOG(smp_data->smp_secret_dialog),
+ GTK_RESPONSE_REJECT);
+ }
+}
+
+static GtkWidget *create_dialog(GtkWindow *parent,
+ PurpleNotifyMsgType type, const char *title,
const char *primary, const char *secondary, int sensitive,
GtkWidget **labelp, void (*add_custom)(GtkWidget *vbox, void *data),
void *add_custom_data)
@@ -661,21 +839,22 @@ static GtkWidget *create_dialog(PurpleNotifyMsgType type, const char *title,
}
if (icon_name != NULL) {
- img = gtk_image_new_from_stock(icon_name, GTK_ICON_SIZE_DIALOG);
+ img = gtk_image_new_from_stock(icon_name,
+ gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_HUGE));
gtk_misc_set_alignment(GTK_MISC(img), 0, 0);
}
- dialog = gtk_dialog_new_with_buttons(title ? title : PIDGIN_ALERT_TITLE,
- NULL, 0, GTK_STOCK_OK,
- GTK_RESPONSE_ACCEPT, NULL);
- gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT,
- sensitive);
+ dialog = gtk_dialog_new_with_buttons(
+ title ? title : PIDGIN_ALERT_TITLE, parent, 0,
+ GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL);
- gtk_window_set_accept_focus(GTK_WINDOW(dialog), FALSE);
+ gtk_window_set_focus_on_map(GTK_WINDOW(dialog), FALSE);
gtk_window_set_role(GTK_WINDOW(dialog), "notify_dialog");
g_signal_connect(G_OBJECT(dialog), "response",
- G_CALLBACK(message_response_cb), dialog);
+ G_CALLBACK(message_response_cb), dialog);
+ gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT,
+ sensitive);
gtk_container_set_border_width(GTK_CONTAINER(dialog), 6);
gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
@@ -716,6 +895,287 @@ static GtkWidget *create_dialog(PurpleNotifyMsgType type, const char *title,
return dialog;
}
+/* Adds a "What's this?" expander to a vbox, containing { some "whatsthis"
+ * markup (displayed in a GtkLabel) and a "More..." expander, containing
+ * { some "more" markup (displayed in a GtkIMHTML) } }. */
+static void add_whatsthis_more(GtkWidget *vbox, const char *whatsthismarkup,
+ const char *moremarkup)
+{
+ GtkWidget *expander;
+ GtkWidget *ebox;
+ GtkWidget *whatsthis;
+ GtkWidget *more;
+ GtkWidget *frame;
+ GtkWidget *scrl;
+ GtkWidget *imh;
+ GdkFont *font;
+
+ expander = gtk_expander_new_with_mnemonic(_("_What's this?"));
+ gtk_box_pack_start(GTK_BOX(vbox), expander, FALSE, FALSE, 0);
+ frame = gtk_frame_new(NULL);
+ gtk_container_add(GTK_CONTAINER(expander), frame);
+ ebox = gtk_vbox_new(FALSE, 10);
+ gtk_container_add(GTK_CONTAINER(frame), ebox);
+ whatsthis = gtk_label_new(NULL);
+ gtk_label_set_line_wrap(GTK_LABEL(whatsthis), TRUE);
+ gtk_label_set_markup(GTK_LABEL(whatsthis), whatsthismarkup);
+
+ gtk_box_pack_start(GTK_BOX(ebox), whatsthis, FALSE, FALSE, 0);
+ more = gtk_expander_new_with_mnemonic(_("_More..."));
+ gtk_box_pack_start(GTK_BOX(ebox), more, FALSE, FALSE, 0);
+ scrl = gtk_scrolled_window_new(NULL, NULL);
+ gtk_container_add(GTK_CONTAINER(more), scrl);
+
+ imh = gtk_imhtml_new(NULL, NULL);
+ pidgin_setup_imhtml(imh);
+ gtk_imhtml_append_text(GTK_IMHTML(imh), moremarkup, GTK_IMHTML_NO_SCROLL);
+
+ gtk_container_add(GTK_CONTAINER(scrl), imh);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrl),
+ GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+ /* This is a deprecated API, but mucking with PangoFontDescriptions
+ * is (a) complicated, and (b) not fully supported by older versions
+ * of libpango, which some people may have. */
+ font = gtk_style_get_font(imh->style);
+ gtk_widget_set_size_request(scrl, -1, 6 * (font->ascent + font->descent));
+}
+
+static GtkWidget *create_smp_dialog(const char *title,
+ const char *primary, const char *secondary, int sensitive,
+ GtkWidget **labelp, ConnContext *context, gboolean responder)
+{
+ GtkWidget *dialog;
+
+ PurpleConversation *conv = otrg_plugin_context_to_conv(context, 1);
+ SMPData *smp_data = purple_conversation_get_data(conv, "otr-smpdata");
+
+ close_progress_window(smp_data);
+ if (!(smp_data->smp_secret_dialog)) {
+ GtkWidget *advbutton;
+ GtkWidget *buttonspacer;
+ GtkWidget *hbox;
+ GtkWidget *vbox;
+ GtkWidget *entry;
+ GtkWidget *label;
+ GtkWidget *label2;
+ GtkWidget *img = NULL;
+ char *label_text;
+ const char *icon_name = NULL;
+ SmpResponsePair* smppair;
+
+ icon_name = PIDGIN_STOCK_DIALOG_INFO;
+ img = gtk_image_new_from_stock(icon_name, gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_HUGE));
+ gtk_misc_set_alignment(GTK_MISC(img), 0, 0);
+
+ dialog = gtk_dialog_new_with_buttons(title ? title : PIDGIN_ALERT_TITLE, NULL, 0,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+ GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL);
+ gtk_dialog_set_default_response(GTK_DIALOG(dialog),
+ GTK_RESPONSE_ACCEPT);
+
+ /* Create the Advanced... button, and left-justify it. This
+ * involves adding the button, and a blank label as a spacer, and
+ * reordering them so that they're at the beginning. */
+ advbutton = gtk_dialog_add_button(GTK_DIALOG(dialog), _("Advanced..."),
+ OTRG_RESPONSE_ADVANCED);
+ buttonspacer = gtk_label_new("");
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+ buttonspacer, TRUE, TRUE, 0);
+ gtk_box_reorder_child(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+ advbutton, 0);
+ gtk_box_reorder_child(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+ buttonspacer, 1);
+
+ gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog),
+ GTK_RESPONSE_ACCEPT, sensitive);
+
+ gtk_window_set_focus_on_map(GTK_WINDOW(dialog), FALSE);
+ gtk_window_set_role(GTK_WINDOW(dialog), "notify_dialog");
+
+ gtk_container_set_border_width(GTK_CONTAINER(dialog), 6);
+ gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
+ gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
+ gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), 12);
+ gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), 6);
+
+ hbox = gtk_hbox_new(FALSE, 12);
+ vbox = gtk_vbox_new(FALSE, 0);
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox);
+
+ gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0);
+
+ label_text = g_strdup_printf(
+ "<span weight=\"bold\" size=\"larger\">%s</span>%s%s",
+ (primary ? primary : ""),
+ (primary ? "\n\n" : ""),
+ (secondary ? secondary : ""));
+
+ label = gtk_label_new(NULL);
+
+ gtk_label_set_markup(GTK_LABEL(label), label_text);
+ gtk_label_set_selectable(GTK_LABEL(label), 1);
+ g_free(label_text);
+ gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
+
+ /* Create the text view where the user enters their secret */
+ entry = gtk_entry_new();
+ gtk_entry_set_text(GTK_ENTRY(entry), _("Enter secret here"));
+ gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
+
+ if (context->active_fingerprint->trust &&
+ context->active_fingerprint->trust[0]) {
+ label2 = gtk_label_new(_("This buddy is already authenticated."));
+ } else {
+ label2 = NULL;
+ }
+
+ gtk_box_pack_start(GTK_BOX(vbox), entry, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
+
+ /* Leave a blank line */
+ gtk_box_pack_start(GTK_BOX(vbox), gtk_label_new(NULL), FALSE,
+ FALSE, 0);
+ if (label2) {
+ gtk_box_pack_start(GTK_BOX(vbox), label2, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), gtk_label_new(NULL), FALSE,
+ FALSE, 0);
+ }
+
+ char *moremarkup = g_strdup_printf(
+ "%s\n\n%s\n\n<a href=\"%s%s\">%s</a>",
+ _("To authenticate, pick a secret known "
+ "only to you and your buddy. Enter this secret, then "
+ "wait for your buddy to enter it too. If the secrets "
+ "don't match, then you may be talking to an imposter."),
+ _("If your buddy uses multiple IM accounts or multiple "
+ "computers, you may have to authenticate multiple "
+ "times. However, as long as they use an account and "
+ "computer that you've seen before, you don't need to "
+ "authenticate each individual conversation."),
+ AUTHENTICATE_HELPURL, _("?lang=en"),
+ _("Click here for more information about authentication "
+ "in OTR."));
+
+ add_whatsthis_more(vbox,
+ _("Authenticating a buddy helps ensure that the person "
+ "you are talking to is who they claim to be."),
+ moremarkup);
+
+ g_free(moremarkup);
+
+ gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
+
+ smppair = malloc(sizeof(SmpResponsePair));
+ smppair->context = context;
+ smppair->entry = GTK_ENTRY(entry);
+ smppair->responder = responder;
+ g_signal_connect(G_OBJECT(dialog), "response",
+ G_CALLBACK(smp_secret_response_cb),
+ smppair);
+
+ gtk_widget_show_all(dialog);
+ smp_data->smp_secret_dialog = dialog;
+ smp_data->smp_secret_smppair = smppair;
+
+ if (labelp) *labelp = label;
+ } else {
+ /* Set the responder field to TRUE if we were passed that value,
+ * even if the window was already up. */
+ if (responder) {
+ smp_data->smp_secret_smppair->responder = responder;
+ }
+ }
+
+ return smp_data->smp_secret_dialog;
+}
+
+static GtkWidget *create_smp_progress_dialog(GtkWindow *parent,
+ ConnContext *context)
+{
+ GtkWidget *dialog;
+ GtkWidget *hbox;
+ GtkWidget *vbox;
+ GtkWidget *label;
+ GtkWidget *proglabel;
+ GtkWidget *bar;
+ GtkWidget *img = NULL;
+ char *label_text;
+ const char *icon_name = NULL;
+
+ icon_name = PIDGIN_STOCK_DIALOG_INFO;
+ img = gtk_image_new_from_stock(icon_name,
+ gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_HUGE));
+ gtk_misc_set_alignment(GTK_MISC(img), 0, 0);
+
+ dialog = gtk_dialog_new_with_buttons(_("Authenticating Buddy"),
+ parent, 0, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+ GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL);
+ gtk_dialog_set_default_response(GTK_DIALOG(dialog),
+ GTK_RESPONSE_ACCEPT);
+ gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog),
+ GTK_RESPONSE_REJECT, 1);
+ gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog),
+ GTK_RESPONSE_ACCEPT, 0);
+
+ gtk_window_set_focus_on_map(GTK_WINDOW(dialog), FALSE);
+ gtk_window_set_role(GTK_WINDOW(dialog), "notify_dialog");
+
+ gtk_container_set_border_width(GTK_CONTAINER(dialog), 6);
+ gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
+ gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
+ gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), 12);
+ gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), 6);
+
+ hbox = gtk_hbox_new(FALSE, 12);
+ vbox = gtk_vbox_new(FALSE, 0);
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox);
+
+ gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0);
+
+ label_text = g_strdup_printf(
+ "<span weight=\"bold\" size=\"larger\">%s %s</span>\n",
+ _("Authenticating"), context->username);
+
+ label = gtk_label_new(NULL);
+
+ gtk_label_set_markup(GTK_LABEL(label), label_text);
+ gtk_label_set_selectable(GTK_LABEL(label), 1);
+ g_free(label_text);
+ gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
+
+ proglabel = gtk_label_new(NULL);
+ gtk_label_set_selectable(GTK_LABEL(proglabel), 1);
+ gtk_label_set_line_wrap(GTK_LABEL(proglabel), TRUE);
+ gtk_misc_set_alignment(GTK_MISC(proglabel), 0, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), proglabel, FALSE, FALSE, 0);
+
+ /* Create the progress bar */
+ bar = gtk_progress_bar_new();
+ gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(bar), 0.1);
+ gtk_box_pack_start(GTK_BOX(vbox), bar, FALSE, FALSE, 0);
+
+ gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
+
+ PurpleConversation *conv = otrg_plugin_context_to_conv(context, 0);
+ SMPData *smp_data = purple_conversation_get_data(conv, "otr-smpdata");
+ smp_data->smp_progress_dialog = dialog;
+ smp_data->smp_progress_bar = bar;
+ smp_data->smp_progress_label = proglabel;
+
+ g_signal_connect(G_OBJECT(dialog), "response",
+ G_CALLBACK(smp_progress_response_cb),
+ context);
+
+ gtk_widget_show_all(dialog);
+
+ return dialog;
+}
+
/* This is just like purple_notify_message, except: (a) it doesn't grab
* keyboard focus, (b) the button is "OK" instead of "Close", and (c)
* the labels aren't limited to 2K. */
@@ -723,7 +1183,7 @@ static void otrg_gtk_dialog_notify_message(PurpleNotifyMsgType type,
const char *accountname, const char *protocol, const char *username,
const char *title, const char *primary, const char *secondary)
{
- create_dialog(type, title, primary, secondary, 1, NULL, NULL, NULL);
+ create_dialog(NULL, type, title, primary, secondary, 1, NULL, NULL, NULL);
}
struct s_OtrgDialogWait {
@@ -738,8 +1198,8 @@ static OtrgDialogWaitHandle otrg_gtk_dialog_private_key_wait_start(
const char *account, const char *protocol)
{
PurplePlugin *p;
- const char *title = "Generating private key";
- const char *primary = "Please wait";
+ const char *title = _("Generating private key");
+ const char *primary = _("Please wait");
char *secondary;
const char *protocol_print;
GtkWidget *label;
@@ -747,14 +1207,14 @@ static OtrgDialogWaitHandle otrg_gtk_dialog_private_key_wait_start(
OtrgDialogWaitHandle handle;
p = purple_find_prpl(protocol);
- protocol_print = (p ? p->info->name : "Unknown");
+ protocol_print = (p ? p->info->name : _("Unknown"));
/* Create the Please Wait... dialog */
- secondary = g_strdup_printf("Generating private key for %s (%s)...",
+ secondary = g_strdup_printf(_("Generating private key for %s (%s)..."),
account, protocol_print);
- dialog = create_dialog(PURPLE_NOTIFY_MSG_INFO, title, primary, secondary,
- 0, &label, NULL, NULL);
+ dialog = create_dialog(NULL, PURPLE_NOTIFY_MSG_INFO, title, primary,
+ secondary, 0, &label, NULL, NULL);
handle = malloc(sizeof(struct s_OtrgDialogWait));
handle->dialog = dialog;
handle->label = label;
@@ -795,7 +1255,7 @@ static void otrg_gtk_dialog_private_key_wait_done(OtrgDialogWaitHandle handle)
char *newmarkup;
oldmarkup = gtk_label_get_label(GTK_LABEL(handle->label));
- newmarkup = g_strdup_printf("%s Done.", oldmarkup);
+ newmarkup = g_strdup_printf(_("%s Done."), oldmarkup);
gtk_label_set_markup(GTK_LABEL(handle->label), newmarkup);
gtk_widget_show(handle->label);
@@ -806,94 +1266,71 @@ static void otrg_gtk_dialog_private_key_wait_done(OtrgDialogWaitHandle handle)
free(handle);
}
-/* Adds a "What's this?" expander to a vbox, containing { some "whatsthis"
- * markup (displayed in a GtkLabel) and a "More..." expander, containing
- * { some "more" markup (displayed in a GtkIMHTML) } }. */
-static void add_whatsthis_more(GtkWidget *vbox, const char *whatsthismarkup,
- const char *moremarkup)
-{
- GtkWidget *expander;
- GtkWidget *ebox;
- GtkWidget *whatsthis;
- GtkWidget *more;
- GtkWidget *frame;
- GtkWidget *scrl;
- GtkWidget *imh;
- GdkFont *font;
-
- expander = gtk_expander_new_with_mnemonic("_What's this?");
- gtk_box_pack_start(GTK_BOX(vbox), expander, FALSE, FALSE, 0);
- frame = gtk_frame_new(NULL);
- gtk_container_add(GTK_CONTAINER(expander), frame);
- ebox = gtk_vbox_new(FALSE, 10);
- gtk_container_add(GTK_CONTAINER(frame), ebox);
- whatsthis = gtk_label_new(NULL);
- gtk_label_set_line_wrap(GTK_LABEL(whatsthis), TRUE);
- gtk_label_set_markup(GTK_LABEL(whatsthis), whatsthismarkup);
-
- gtk_box_pack_start(GTK_BOX(ebox), whatsthis, FALSE, FALSE, 0);
- more = gtk_expander_new_with_mnemonic("_More...");
- gtk_box_pack_start(GTK_BOX(ebox), more, FALSE, FALSE, 0);
- scrl = gtk_scrolled_window_new(NULL, NULL);
- gtk_container_add(GTK_CONTAINER(more), scrl);
-
- imh = gtk_imhtml_new(NULL, NULL);
- pidgin_setup_imhtml(imh);
- gtk_imhtml_append_text(GTK_IMHTML(imh), moremarkup, GTK_IMHTML_NO_SCROLL);
-
- gtk_container_add(GTK_CONTAINER(scrl), imh);
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrl),
- GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
-
- /* This is a deprecated API, but mucking with PangoFontDescriptions
- * is (a) complicated, and (b) not fully supported by older versions
- * of libpango, which some people may have. */
- font = gtk_style_get_font(imh->style);
- gtk_widget_set_size_request(scrl, -1, 6 * (font->ascent + font->descent));
-}
-
+#if 0
static void add_unk_fingerprint_expander(GtkWidget *vbox, void *data)
{
+ char *moremarkup = g_strdup_printf(
+ "%s\n\n%s\n\n<a href=\"%s\">%s%s</a>",
+ __("If your buddy has more than one IM account, or uses more than "
+ "one computer, he may have multiple fingerprints."),
+ __("However, the only way an imposter could duplicate one of your "
+ "buddy's fingerprints is by stealing information from his "
+ "computer."),
+ FINGERPRINT_HELPURL, __("?lang=en"),
+ __("Click here for more information about fingerprints."));
+
add_whatsthis_more(vbox,
- "A <b>fingerprint</b> is a unique identifier that you should "
+ __("A <b>fingerprint</b> is a unique identifier that you should "
"use to authenticate your buddy. Right-click on the OTR button "
"in your buddy's conversation window, and choose \"Verify "
- "fingerprint\".",
+ "fingerprint\"."), moremarkup);
- "If your buddy has more than one IM account, or uses more than "
- "one computer, he may have multiple fingerprints.\n\n"
- "However, the only way an imposter could duplicate one of your "
- "buddy's fingerprints is by stealing information from his "
- "computer.\n\n"
- "<a href=\"" FINGERPRINT_HELPURL "\">"
- "Click here for more information about fingerprints.</a>");
+ g_free(moremarkup);
}
+#endif
-/* Show a dialog informing the user that a correspondent (who) has sent
- * us a Key Exchange Message (kem) that contains an unknown fingerprint.
- * Ask the user whether to accept the fingerprint or not. If yes, call
- * response_cb(ops, opdata, response_data, resp) with resp = 1. If no,
- * set resp = 0. If the user destroys the dialog without answering, set
- * resp = -1. */
+/* Inform the user that an unknown fingerprint was received. */
static void otrg_gtk_dialog_unknown_fingerprint(OtrlUserState us,
const char *accountname, const char *protocol, const char *who,
unsigned char fingerprint[20])
{
- char hash[45];
- char *primary, *secondary;
- PurplePlugin *p = purple_find_prpl(protocol);
-
- otrl_privkey_hash_to_human(hash, fingerprint);
- primary = g_strdup_printf("%s (%s) has received an unknown fingerprint "
- "from %s:", accountname,
- (p && p->info->name) ? p->info->name : "Unknown", who);
- secondary = g_strdup_printf("%s\n", hash);
+ PurpleConversation *conv;
+ char *buf;
+ ConnContext *context;
+ int seenbefore = FALSE;
+
+ /* Figure out if this is the first fingerprint we've seen for this
+ * user. */
+ context = otrl_context_find(us, who, accountname, protocol, FALSE,
+ NULL, NULL, NULL);
+ if (context) {
+ Fingerprint *fp = context->fingerprint_root.next;
+ while(fp) {
+ if (memcmp(fingerprint, fp->fingerprint, 20)) {
+ /* This is a previously seen fingerprint for this user,
+ * different from the one we were passed. */
+ seenbefore = TRUE;
+ break;
+ }
+ fp = fp->next;
+ }
+ }
- create_dialog(PURPLE_NOTIFY_MSG_WARNING, "Unknown fingerprint",
- primary, secondary, 1, NULL, add_unk_fingerprint_expander, NULL);
+ if (seenbefore) {
+ buf = g_strdup_printf(_("%s is contacting you from an unrecognized "
+ "computer. You should <a href=\"%s%s\">authenticate</a> "
+ "this buddy."), who, AUTHENTICATE_HELPURL, _("?lang=en"));
+ } else {
+ buf = g_strdup_printf(_("%s has not been authenticated yet. You "
+ "should <a href=\"%s%s\">authenticate</a> this buddy."),
+ who, AUTHENTICATE_HELPURL, _("?lang=en"));
+ }
- g_free(primary);
- g_free(secondary);
+ conv = otrg_plugin_userinfo_to_conv(accountname, protocol, who, TRUE);
+
+ purple_conversation_write(conv, NULL, buf, PURPLE_MESSAGE_SYSTEM,
+ time(NULL));
+ g_free(buf);
}
static void otrg_gtk_dialog_clicked_connect(GtkWidget *widget, gpointer data);
@@ -909,6 +1346,7 @@ static void dialog_update_label_conv(PurpleConversation *conv, TrustLevel level)
GtkWidget *menuquerylabel;
GtkWidget *menuview;
GtkWidget *menuverf;
+ GtkWidget *menusmp;
PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
label = purple_conversation_get_data(conv, "otr-label");
icon = purple_conversation_get_data(conv, "otr-icon");
@@ -919,27 +1357,29 @@ static void dialog_update_label_conv(PurpleConversation *conv, TrustLevel level)
menuend = purple_conversation_get_data(conv, "otr-menuend");
menuview = purple_conversation_get_data(conv, "otr-menuview");
menuverf = purple_conversation_get_data(conv, "otr-menuverf");
+ menusmp = purple_conversation_get_data(conv, "otr-menusmp");
/* Set the button's icon, label and tooltip. */
otr_icon(icon, level);
gtk_label_set_text(GTK_LABEL(label),
- level == TRUST_FINISHED ? "Finished" :
- level == TRUST_PRIVATE ? "Private" :
- level == TRUST_UNVERIFIED ? "Unverified" :
- "Not private");
+ level == TRUST_FINISHED ? _("Finished") :
+ level == TRUST_PRIVATE ? _("Private") :
+ level == TRUST_UNVERIFIED ? _("Unverified") :
+ _("Not private"));
gtk_tooltips_set_tip(gtkconv->tooltips, button,
- level == TRUST_NOT_PRIVATE ? "Start a private conversation" :
- "Refresh the private conversation", NULL);
+ level == TRUST_NOT_PRIVATE ? _("Start a private conversation") :
+ _("Refresh the private conversation"), NULL);
/* Set the menu item label for the OTR Query item. */
gtk_label_set_markup_with_mnemonic(GTK_LABEL(menuquerylabel),
- level == TRUST_NOT_PRIVATE ? "Start _private conversation" :
- "Refresh _private conversation");
+ level == TRUST_NOT_PRIVATE ? _("Start _private conversation") :
+ _("Refresh _private conversation"));
/* Sensitize the menu items as appropriate. */
gtk_widget_set_sensitive(GTK_WIDGET(menuend), level != TRUST_NOT_PRIVATE);
gtk_widget_set_sensitive(GTK_WIDGET(menuview), level != TRUST_NOT_PRIVATE);
gtk_widget_set_sensitive(GTK_WIDGET(menuverf), level != TRUST_NOT_PRIVATE);
+ gtk_widget_set_sensitive(GTK_WIDGET(menusmp), level != TRUST_NOT_PRIVATE);
/* Use any non-NULL value for "private", NULL for "not private" */
purple_conversation_set_data(conv, "otr-private",
@@ -962,27 +1402,32 @@ static void dialog_update_label(ConnContext *context)
dialog_update_label_conv(conv, level);
}
+#if 0
/* Add the help text for the "view session id" dialog. */
static void add_sessid_expander(GtkWidget *vbox, void *data)
{
- add_whatsthis_more(vbox,
- "You can use this <b>secure session id</b> to double-check "
- "the privacy of <i>this one conversation</i>.",
-
- "To verify the session id, contact your buddy via some "
+ char *moremarkup = g_strdup_printf(
+ "%s\n\n%s\n\n%s\n\n<a href=\"%s%s\">%s</a>",
+ __("To verify the session id, contact your buddy via some "
"<i>other</i> authenticated channel, such as the telephone "
"or GPG-signed email. Each of you should tell your bold "
"half of the above session id to the other "
"(your buddy will have the same session id as you, but with the "
- "other half bold).\n\nIf everything matches up, then <i>the "
+ "other half bold)."),
+ __("If everything matches up, then <i>the "
"current conversation</i> between your computer and your buddy's "
- "computer is private.\n\n"
- "<b>Note:</b> You will probably never have to do this. You "
+ "computer is private."),
+ __("<b>Note:</b> You will probably never have to do this. You "
"should normally use the \"Verify fingerprint\" functionality "
- "instead.\n\n"
- "<a href=\"" SESSIONID_HELPURL "\">"
- "Click here for more information about the secure "
- "session id.</a>");
+ "instead."),
+ SESSIONID_HELPURL, _("?lang=en"),
+ __("Click here for more information about the secure session id."));
+
+ add_whatsthis_more(vbox,
+ __("You can use this <b>secure session id</b> to double-check "
+ "the privacy of <i>this one conversation</i>."), moremarkup);
+
+ g_free(moremarkup);
}
static GtkWidget* otrg_gtk_dialog_view_sessionid(ConnContext *context)
@@ -990,8 +1435,8 @@ static GtkWidget* otrg_gtk_dialog_view_sessionid(ConnContext *context)
GtkWidget *dialog;
unsigned char *sessionid;
char sess1[21], sess2[21];
- char *primary = g_strdup_printf("Private connection with %s "
- "established.", context->username);
+ char *primary = g_strdup_printf(__("Private connection with %s "
+ "established."), context->username);
char *secondary;
int i;
OtrlSessionIdHalf whichhalf = context->sessionid_half;
@@ -1003,15 +1448,16 @@ static GtkWidget* otrg_gtk_dialog_view_sessionid(ConnContext *context)
for(i=0;i<idhalflen;++i) sprintf(sess2+(2*i), "%02x",
sessionid[i+idhalflen]);
- secondary = g_strdup_printf("Secure session id:\n"
+ secondary = g_strdup_printf("%s\n"
"<span %s>%s</span> <span %s>%s</span>\n",
+ __("Secure session id:"),
whichhalf == OTRL_SESSIONID_FIRST_HALF_BOLD ?
"weight=\"bold\"" : "", sess1,
whichhalf == OTRL_SESSIONID_SECOND_HALF_BOLD ?
"weight=\"bold\"" : "", sess2);
- dialog = create_dialog(PURPLE_NOTIFY_MSG_INFO, "Private connection "
- "established", primary, secondary, 1, NULL,
+ dialog = create_dialog(PURPLE_NOTIFY_MSG_INFO,
+ __("Private connection established"), primary, secondary, 1, NULL,
add_sessid_expander, NULL);
g_free(primary);
@@ -1019,6 +1465,7 @@ static GtkWidget* otrg_gtk_dialog_view_sessionid(ConnContext *context)
return dialog;
}
+#endif
struct vrfy_fingerprint_data {
Fingerprint *fprint; /* You can use this pointer right away, but
@@ -1097,6 +1544,7 @@ static void add_vrfy_fingerprint(GtkWidget *vbox, void *data)
struct vrfy_fingerprint_data *vfd = data;
char *labelt;
int verified = 0;
+ char *moremarkup;
if (vfd->fprint->trust && vfd->fprint->trust[0]) {
verified = 1;
@@ -1104,10 +1552,10 @@ static void add_vrfy_fingerprint(GtkWidget *vbox, void *data)
hbox = gtk_hbox_new(FALSE, 0);
combo = gtk_combo_box_new_text();
- gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "I have not");
- gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "I have");
+ gtk_combo_box_append_text(GTK_COMBO_BOX(combo), _("I have not"));
+ gtk_combo_box_append_text(GTK_COMBO_BOX(combo), _("I have"));
gtk_combo_box_set_active(GTK_COMBO_BOX(combo), verified);
- label = gtk_label_new(" verified that this is in fact the correct");
+ label = gtk_label_new(_(" verified that this is in fact the correct"));
gtk_box_pack_start(GTK_BOX(hbox), combo, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
@@ -1116,7 +1564,7 @@ static void add_vrfy_fingerprint(GtkWidget *vbox, void *data)
G_CALLBACK(vrfy_fingerprint_changed), vfd);
hbox = gtk_hbox_new(FALSE, 0);
- labelt = g_strdup_printf("fingerprint for %s.",
+ labelt = g_strdup_printf(_("fingerprint for %s."),
vfd->username);
label = gtk_label_new(labelt);
g_free(labelt);
@@ -1126,26 +1574,30 @@ static void add_vrfy_fingerprint(GtkWidget *vbox, void *data)
/* Leave a blank line */
gtk_box_pack_start(GTK_BOX(vbox), gtk_label_new(NULL), FALSE, FALSE, 0);
- add_whatsthis_more(vbox,
- "A <b>fingerprint</b> is a unique identifier that you should "
- "use to authenticate your buddy.",
-
- "To verify the fingerprint, contact your buddy via some "
+ moremarkup = g_strdup_printf(
+ "%s\n\n%s\n\n%s\n\n%s\n\n<a href=\"%s%s\">%s</a>",
+ _("To verify the fingerprint, contact your buddy via some "
"<i>other</i> authenticated channel, such as the telephone "
"or GPG-signed email. Each of you should tell your fingerprint "
- "to the other.\n\n"
- "If everything matches up, you should indicate in the above "
- "dialog that you <b>have</b> verified the fingerprint.\n\n"
- "If your buddy has more than one IM account, or uses more than "
- "one computer, he may have multiple fingerprints.\n\n"
- "However, the only way an imposter could duplicate one of your "
- "buddy's fingerprints is by stealing information from his "
- "computer.\n\n"
- "<a href=\"" FINGERPRINT_HELPURL "\">"
- "Click here for more information about fingerprints.</a>");
+ "to the other."),
+ _("If everything matches up, you should indicate in the above "
+ "dialog that you <b>have</b> verified the fingerprint."),
+ _("If your buddy has more than one IM account, or uses more than "
+ "one computer, he may have multiple fingerprints."),
+ _("However, the only way an imposter could duplicate one of your "
+ "buddy's fingerprints is by stealing information from her/his "
+ "computer."),
+ FINGERPRINT_HELPURL, _("?lang=en"),
+ _("Click here for more information about fingerprints."));
+
+ add_whatsthis_more(vbox,
+ _("A <b>fingerprint</b> is a unique identifier that you should "
+ "use to authenticate your buddy."), moremarkup);
+ g_free(moremarkup);
+
}
-static void otrg_gtk_dialog_verify_fingerprint(Fingerprint *fprint)
+static void verify_fingerprint(GtkWindow *parent, Fingerprint *fprint)
{
GtkWidget *dialog;
char our_hash[45], their_hash[45];
@@ -1161,23 +1613,25 @@ static void otrg_gtk_dialog_verify_fingerprint(Fingerprint *fprint)
context = fprint->context;
if (context == NULL) return;
- primary = g_strdup_printf("Verify fingerprint for %s",
+ primary = g_strdup_printf(_("Verify fingerprint for %s"),
context->username);
vfd = vrfy_fingerprint_data_new(fprint);
+ strcpy(our_hash, _("[none]"));
otrl_privkey_fingerprint(otrg_plugin_userstate, our_hash,
context->accountname, context->protocol);
otrl_privkey_hash_to_human(their_hash, fprint->fingerprint);
p = purple_find_prpl(context->protocol);
- proto_name = (p && p->info->name) ? p->info->name : "Unknown";
- secondary = g_strdup_printf("Fingerprint for you, %s (%s):\n%s\n\n"
- "Purported fingerprint for %s:\n%s\n", context->accountname,
+ proto_name = (p && p->info->name) ? p->info->name : _("Unknown");
+ secondary = g_strdup_printf(_("Fingerprint for you, %s (%s):\n%s\n\n"
+ "Purported fingerprint for %s:\n%s\n"), context->accountname,
proto_name, our_hash, context->username, their_hash);
- dialog = create_dialog(PURPLE_NOTIFY_MSG_INFO, "Verify fingerprint",
- primary, secondary, 1, NULL, add_vrfy_fingerprint, vfd);
+ dialog = create_dialog(parent, PURPLE_NOTIFY_MSG_INFO,
+ _("Verify fingerprint"), primary, secondary, 1, NULL,
+ add_vrfy_fingerprint, vfd);
g_signal_connect(G_OBJECT(dialog), "destroy",
G_CALLBACK(vrfy_fingerprint_destroyed), vfd);
@@ -1185,29 +1639,133 @@ static void otrg_gtk_dialog_verify_fingerprint(Fingerprint *fprint)
g_free(secondary);
}
+static void otrg_gtk_dialog_verify_fingerprint(Fingerprint *fprint)
+{
+ verify_fingerprint(NULL, fprint);
+}
+
+/* Create the SMP dialog. responder is true if this is called in
+ * response to someone else's run of SMP. */
+static void otrg_gtk_dialog_socialist_millionaires(ConnContext *context,
+ gboolean responder)
+{
+ GtkWidget *dialog;
+ char *primary;
+ char *secondary;
+ PurplePlugin *p;
+ char *proto_name;
+
+ if (context == NULL) return;
+
+ primary = g_strdup_printf(_("Authenticate %s"),
+ context->username);
+
+ p = purple_find_prpl(context->protocol);
+ proto_name = (p && p->info->name) ? p->info->name : _("Unknown");
+ secondary = g_strdup_printf(_("Enter a secret known only to %s and "
+ "yourself.\n"), context->username);
+
+ dialog = create_smp_dialog(_("Authenticate buddy"),
+ primary, secondary, 1, NULL, context, responder);
+
+ g_free(primary);
+ g_free(secondary);
+}
+
+/* Call this to update the status of an ongoing socialist millionaires
+ * protocol. Progress_level is a percentage, from 0.0 (aborted) to
+ * 1.0 (complete). Any other value represents an intermediate state. */
+static void otrg_gtk_dialog_update_smp(ConnContext *context,
+ double progress_level)
+{
+ PurpleConversation *conv = otrg_plugin_context_to_conv(context, 0);
+ GtkProgressBar *bar;
+ SMPData *smp_data = purple_conversation_get_data(conv, "otr-smpdata");
+
+ if (!smp_data) return;
+
+ bar = GTK_PROGRESS_BAR(smp_data->smp_progress_bar);
+ gtk_progress_bar_set_fraction(bar, progress_level);
+
+ /* If the counter is reset to absolute zero, the protocol has aborted */
+ if (progress_level == 0.0) {
+ GtkDialog *dialog = GTK_DIALOG(smp_data->smp_progress_dialog);
+
+ gtk_dialog_set_response_sensitive(dialog, GTK_RESPONSE_ACCEPT, 1);
+ gtk_dialog_set_response_sensitive(dialog, GTK_RESPONSE_REJECT, 0);
+ gtk_dialog_set_default_response(GTK_DIALOG(dialog),
+ GTK_RESPONSE_ACCEPT);
+
+ gtk_label_set_text(GTK_LABEL(smp_data->smp_progress_label),
+ _("An error occurred during authentication."));
+ return;
+ }
+
+ /* If the counter reaches 1.0, the protocol is complete */
+ if (progress_level == 1.0) {
+ GtkDialog *dialog = GTK_DIALOG(smp_data->smp_progress_dialog);
+
+ gtk_dialog_set_response_sensitive(dialog, GTK_RESPONSE_ACCEPT, 1);
+ gtk_dialog_set_response_sensitive(dialog, GTK_RESPONSE_REJECT, 0);
+ gtk_dialog_set_default_response(GTK_DIALOG(dialog),
+ GTK_RESPONSE_ACCEPT);
+
+ if (context->active_fingerprint->trust &&
+ context->active_fingerprint->trust[0]) {
+ gtk_label_set_text(GTK_LABEL(smp_data->smp_progress_label),
+ _("Authentication successful."));
+ } else {
+ gtk_label_set_text(GTK_LABEL(smp_data->smp_progress_label),
+ _("Authentication failed."));
+ }
+ }
+}
+
/* Call this when a context transitions to ENCRYPTED. */
static void otrg_gtk_dialog_connected(ConnContext *context)
{
PurpleConversation *conv;
char *buf;
+ char *format_buf;
TrustLevel level;
+ OtrgUiPrefs prefs;
- conv = otrg_plugin_context_to_conv(context, 1);
+ conv = otrg_plugin_context_to_conv(context, TRUE);
level = otrg_plugin_context_to_trust(context);
- buf = g_strdup_printf("%s conversation with %s started.%s",
- level == TRUST_PRIVATE ? "Private" :
- level == TRUST_UNVERIFIED ? "<a href=\"" UNVERIFIED_HELPURL
- "\">Unverified</a>" :
- /* This last case should never happen, since we know
- * we're in ENCRYPTED. */
- "Not private",
+ otrg_ui_get_prefs(&prefs, purple_conversation_get_account(conv),
+ context->username);
+ if (prefs.avoid_logging_otr) {
+ purple_conversation_set_logging(conv, FALSE);
+ }
+
+ switch(level) {
+ case TRUST_PRIVATE:
+ format_buf = g_strdup(_("Private conversation with %s started.%s"));
+ break;
+
+ case TRUST_UNVERIFIED:
+ format_buf = g_strdup_printf(_("<a href=\"%s%s\">Unverified</a> "
+ "conversation with %%s started.%%s"),
+ UNVERIFIED_HELPURL, _("?lang=en"));
+ break;
+
+ default:
+ /* This last case should never happen, since we know
+ * we're in ENCRYPTED. */
+ format_buf = g_strdup(_("Not private conversation with %s "
+ "started.%s"));
+ break;
+ }
+ buf = g_strdup_printf(format_buf,
purple_conversation_get_name(conv),
- context->protocol_version == 1 ? " Warning: using old "
- "protocol version 1." : "");
+ context->protocol_version == 1 ? _(" Warning: using old "
+ "protocol version 1.") : "");
- purple_conversation_write(conv, NULL, buf, PURPLE_MESSAGE_SYSTEM, time(NULL));
+ purple_conversation_write(conv, NULL, buf, PURPLE_MESSAGE_SYSTEM,
+ time(NULL));
g_free(buf);
+ g_free(format_buf);
dialog_update_label(context);
}
@@ -1217,15 +1775,26 @@ static void otrg_gtk_dialog_disconnected(ConnContext *context)
{
PurpleConversation *conv;
char *buf;
+ OtrgUiPrefs prefs;
conv = otrg_plugin_context_to_conv(context, 1);
- buf = g_strdup_printf("Private conversation with %s lost.",
+ buf = g_strdup_printf(_("Private conversation with %s lost."),
purple_conversation_get_name(conv));
purple_conversation_write(conv, NULL, buf, PURPLE_MESSAGE_SYSTEM, time(NULL));
g_free(buf);
+ otrg_ui_get_prefs(&prefs, purple_conversation_get_account(conv),
+ context->username);
+ if (prefs.avoid_logging_otr) {
+ if (purple_prefs_get_bool("/purple/logging/log_ims"))
+ {
+ purple_conversation_set_logging(conv, TRUE);
+ }
+ }
+
dialog_update_label(context);
+ close_smp_window(conv);
}
/* Call this if the remote user terminates his end of an ENCRYPTED
@@ -1241,15 +1810,19 @@ static void otrg_gtk_dialog_finished(const char *accountname,
account = purple_accounts_find(accountname, protocol);
if (!account) return;
- conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, username, account);
+ conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
+ username, account);
if (!conv) return;
- buf = g_strdup_printf("%s has ended his private conversation with you; "
- "you should do the same.", purple_conversation_get_name(conv));
- purple_conversation_write(conv, NULL, buf, PURPLE_MESSAGE_SYSTEM, time(NULL));
+ buf = g_strdup_printf(_("%s has ended his/her private conversation with "
+ "you; you should do the same."),
+ purple_conversation_get_name(conv));
+ purple_conversation_write(conv, NULL, buf, PURPLE_MESSAGE_SYSTEM,
+ time(NULL));
g_free(buf);
dialog_update_label_conv(conv, TRUST_FINISHED);
+ close_smp_window(conv);
}
/* Call this when we receive a Key Exchange message that doesn't cause
@@ -1258,25 +1831,42 @@ static void otrg_gtk_dialog_stillconnected(ConnContext *context)
{
PurpleConversation *conv;
char *buf;
+ char *format_buf;
TrustLevel level;
conv = otrg_plugin_context_to_conv(context, 1);
level = otrg_plugin_context_to_trust(context);
- buf = g_strdup_printf("Successfully refreshed the %s conversation "
- "with %s.%s",
- level == TRUST_PRIVATE ? "private" :
- level == TRUST_UNVERIFIED ? "<a href=\"" UNVERIFIED_HELPURL
- "\">unverified</a>" :
- /* This last case should never happen, since we know
- * we're in ENCRYPTED. */
- "not private",
+ switch(level) {
+ case TRUST_PRIVATE:
+ format_buf = g_strdup(_("Successfully refreshed the private "
+ "conversation with %s.%s"));
+ break;
+
+ case TRUST_UNVERIFIED:
+ format_buf = g_strdup_printf(_("Successfully refreshed the "
+ "<a href=\"%s%s\">unverified</a> conversation with "
+ "%%s.%%s"),
+ UNVERIFIED_HELPURL, _("?lang=en"));
+ break;
+
+ default:
+ /* This last case should never happen, since we know
+ * we're in ENCRYPTED. */
+ format_buf = g_strdup(_("Successfully refreshed the not private "
+ "conversation with %s.%s"));
+ break;
+ }
+
+ buf = g_strdup_printf(format_buf,
purple_conversation_get_name(conv),
- context->protocol_version == 1 ? " Warning: using old "
- "protocol version 1." : "");
+ context->protocol_version == 1 ? _(" Warning: using old "
+ "protocol version 1.") : "");
- purple_conversation_write(conv, NULL, buf, PURPLE_MESSAGE_SYSTEM, time(NULL));
+ purple_conversation_write(conv, NULL, buf, PURPLE_MESSAGE_SYSTEM,
+ time(NULL));
g_free(buf);
+ g_free(format_buf);
dialog_update_label(context);
}
@@ -1290,17 +1880,19 @@ static void otrg_gtk_dialog_clicked_connect(GtkWidget *widget, gpointer data)
PurpleConversation *conv = data;
if (purple_conversation_get_data(conv, "otr-private")) {
- format = "Attempting to refresh the private conversation with %s...";
+ format = _("Attempting to refresh the private conversation with %s...");
} else {
- format = "Attempting to start a private conversation with %s...";
+ format = _("Attempting to start a private conversation with %s...");
}
buf = g_strdup_printf(format, purple_conversation_get_name(conv));
- purple_conversation_write(conv, NULL, buf, PURPLE_MESSAGE_SYSTEM, time(NULL));
+ purple_conversation_write(conv, NULL, buf, PURPLE_MESSAGE_SYSTEM,
+ time(NULL));
g_free(buf);
otrg_plugin_send_default_query_conv(conv);
}
+#if 0
static void view_sessionid(GtkWidget *widget, gpointer data)
{
PurpleConversation *conv = data;
@@ -1311,7 +1903,21 @@ static void view_sessionid(GtkWidget *widget, gpointer data)
otrg_gtk_dialog_view_sessionid(context);
}
+#endif
+
+/* Called when SMP verification option selected from menu */
+static void socialist_millionaires(GtkWidget *widget, gpointer data)
+{
+ PurpleConversation *conv = data;
+ ConnContext *context = otrg_plugin_conv_to_context(conv);
+ if (context == NULL || context->msgstate != OTRL_MSGSTATE_ENCRYPTED)
+ return;
+
+ otrg_gtk_dialog_socialist_millionaires(context, FALSE);
+}
+
+#if 0
static void verify_fingerprint(GtkWidget *widget, gpointer data)
{
PurpleConversation *conv = data;
@@ -1322,10 +1928,13 @@ static void verify_fingerprint(GtkWidget *widget, gpointer data)
otrg_gtk_dialog_verify_fingerprint(context->active_fingerprint);
}
+#endif
static void menu_whatsthis(GtkWidget *widget, gpointer data)
{
- purple_notify_uri(otrg_plugin_handle, BUTTON_HELPURL);
+ char *uri = g_strdup_printf("%s%s", BUTTON_HELPURL, _("?lang=en"));
+ purple_notify_uri(otrg_plugin_handle, uri);
+ g_free(uri);
}
static void menu_end_private_conversation(GtkWidget *widget, gpointer data)
@@ -1355,9 +1964,9 @@ static gboolean button_pressed(GtkWidget *w, GdkEventButton *event,
return FALSE;
}
-/* If the OTR button gets destroyed on us, clean up the data we stored
+/* If the conversation gets destroyed on us, clean up the data we stored
* pointing to it. */
-static void button_destroyed(GtkWidget *w, PurpleConversation *conv)
+static void conversation_destroyed(PurpleConversation *conv, void *data)
{
GtkWidget *menu = purple_conversation_get_data(conv, "otr-menu");
if (menu) gtk_object_destroy(GTK_OBJECT(menu));
@@ -1371,6 +1980,8 @@ static void button_destroyed(GtkWidget *w, PurpleConversation *conv)
g_hash_table_remove(conv->data, "otr-menuend");
g_hash_table_remove(conv->data, "otr-menuview");
g_hash_table_remove(conv->data, "otr-menuverf");
+ g_hash_table_remove(conv->data, "otr-menusmp");
+ otrg_gtk_dialog_free_smp_data(conv);
}
/* Set up the per-conversation information display */
@@ -1390,8 +2001,11 @@ static void otrg_gtk_dialog_new_conv(PurpleConversation *conv)
GtkWidget *menuquery;
GtkWidget *menuend;
GtkWidget *menusep;
+ /*
GtkWidget *menuview;
GtkWidget *menuverf;
+ */
+ GtkWidget *menusmp;
GtkWidget *whatsthis;
/* Do nothing if this isn't an IM conversation */
@@ -1428,7 +2042,7 @@ static void otrg_gtk_dialog_new_conv(PurpleConversation *conv)
gtk_box_pack_start(GTK_BOX(bvbox), iconbox, FALSE, FALSE, 0);
label = gtk_label_new(NULL);
gtk_box_pack_start(GTK_BOX(bvbox), label, FALSE, FALSE, 0);
- icontext = gtk_label_new("OTR:");
+ icontext = gtk_label_new(_("OTR:"));
gtk_box_pack_start(GTK_BOX(iconbox), icontext, FALSE, FALSE, 0);
icon = otr_icon(NULL, TRUST_NOT_PRIVATE);
gtk_box_pack_start(GTK_BOX(iconbox), icon, TRUE, FALSE, 0);
@@ -1437,13 +2051,13 @@ static void otrg_gtk_dialog_new_conv(PurpleConversation *conv)
/* Make the context menu */
menu = gtk_menu_new();
- gtk_menu_set_title(GTK_MENU(menu), "OTR Messaging");
+ gtk_menu_set_title(GTK_MENU(menu), _("OTR Messaging"));
menuquery = gtk_menu_item_new_with_mnemonic("");
gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuquery);
gtk_widget_show(menuquery);
- menuend = gtk_menu_item_new_with_mnemonic("_End private conversation");
+ menuend = gtk_menu_item_new_with_mnemonic(_("_End private conversation"));
gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuend);
gtk_widget_show(menuend);
@@ -1451,19 +2065,34 @@ static void otrg_gtk_dialog_new_conv(PurpleConversation *conv)
gtk_menu_shell_append(GTK_MENU_SHELL(menu), menusep);
gtk_widget_show(menusep);
- menuverf = gtk_menu_item_new_with_mnemonic("_Verify fingerprint");
+ /*
+ * Don't show the Verify fingerprint menu option any more. You can
+ * still get to the dialog through Authenticate connection ->
+ * Advanced...
+ *
+ menuverf = gtk_menu_item_new_with_mnemonic(_("_Verify fingerprint"));
gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuverf);
gtk_widget_show(menuverf);
+ */
+
+ menusmp = gtk_menu_item_new_with_mnemonic(_("_Authenticate buddy"));
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menusmp);
+ gtk_widget_show(menusmp);
- menuview = gtk_menu_item_new_with_mnemonic("View _secure session id");
+ /*
+ * Don't show the View secure session id menu option any more. It's
+ * not really useful at all.
+ *
+ menuview = gtk_menu_item_new_with_mnemonic(_("View _secure session id"));
gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuview);
gtk_widget_show(menuview);
+ */
menusep = gtk_separator_menu_item_new();
gtk_menu_shell_append(GTK_MENU_SHELL(menu), menusep);
gtk_widget_show(menusep);
- whatsthis = gtk_menu_item_new_with_mnemonic("_What's this?");
+ whatsthis = gtk_menu_item_new_with_mnemonic(_("_What's this?"));
gtk_menu_shell_append(GTK_MENU_SHELL(menu), whatsthis);
gtk_widget_show(whatsthis);
@@ -1474,27 +2103,37 @@ static void otrg_gtk_dialog_new_conv(PurpleConversation *conv)
purple_conversation_set_data(conv, "otr-menu", menu);
purple_conversation_set_data(conv, "otr-menuquery", menuquery);
purple_conversation_set_data(conv, "otr-menuend", menuend);
+ /*
purple_conversation_set_data(conv, "otr-menuview", menuview);
purple_conversation_set_data(conv, "otr-menuverf", menuverf);
+ */
+ purple_conversation_set_data(conv, "otr-menusmp", menusmp);
gtk_signal_connect(GTK_OBJECT(menuquery), "activate",
GTK_SIGNAL_FUNC(otrg_gtk_dialog_clicked_connect), conv);
gtk_signal_connect(GTK_OBJECT(menuend), "activate",
GTK_SIGNAL_FUNC(menu_end_private_conversation), conv);
+ /*
gtk_signal_connect(GTK_OBJECT(menuverf), "activate",
GTK_SIGNAL_FUNC(verify_fingerprint), conv);
+ */
+ gtk_signal_connect(GTK_OBJECT(menusmp), "activate",
+ GTK_SIGNAL_FUNC(socialist_millionaires), conv);
+ /*
gtk_signal_connect(GTK_OBJECT(menuview), "activate",
GTK_SIGNAL_FUNC(view_sessionid), conv);
+ */
gtk_signal_connect(GTK_OBJECT(whatsthis), "activate",
GTK_SIGNAL_FUNC(menu_whatsthis), conv);
gtk_signal_connect(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(otrg_gtk_dialog_clicked_connect), conv);
- g_signal_connect(G_OBJECT(button), "destroy",
- G_CALLBACK(button_destroyed), conv);
g_signal_connect(G_OBJECT(button), "button-press-event",
G_CALLBACK(button_pressed), conv);
dialog_update_label_conv(conv, otrg_plugin_context_to_trust(context));
dialog_resensitize(conv);
+
+ /* Finally, add the state for the socialist millionaires dialogs */
+ otrg_gtk_dialog_add_smp_data(conv);
}
/* Remove the per-conversation information display */
@@ -1507,6 +2146,7 @@ static void otrg_gtk_dialog_remove_conv(PurpleConversation *conv)
button = purple_conversation_get_data(conv, "otr-button");
if (button) gtk_object_destroy(GTK_OBJECT(button));
+ conversation_destroyed(conv, NULL);
}
/* Set the OTR button to "sensitive" or "insensitive" as appropriate. */
@@ -1516,16 +2156,16 @@ static void dialog_resensitize(PurpleConversation *conv)
PurpleConnection *connection;
GtkWidget *button;
const char *name;
- OtrlPolicy policy;
+ OtrgUiPrefs prefs;
/* Do nothing if this isn't an IM conversation */
if (purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_IM) return;
account = purple_conversation_get_account(conv);
name = purple_conversation_get_name(conv);
- policy = otrg_ui_find_policy(account, name);
+ otrg_ui_get_prefs(&prefs, account, name);
- if (policy == OTRL_POLICY_NEVER) {
+ if (prefs.policy == OTRL_POLICY_NEVER) {
otrg_gtk_dialog_remove_conv(conv);
} else {
otrg_gtk_dialog_new_conv(conv);
@@ -1551,13 +2191,33 @@ static void otrg_gtk_dialog_resensitize_all(void)
purple_conversation_foreach(dialog_resensitize);
}
+/* Initialize the OTR dialog subsystem */
+static void otrg_gtk_dialog_init(void)
+{
+ purple_signal_connect(purple_conversations_get_handle(),
+ "deleting-conversation", otrg_plugin_handle,
+ PURPLE_CALLBACK(conversation_destroyed), NULL);
+}
+
+/* Deinitialize the OTR dialog subsystem */
+static void otrg_gtk_dialog_cleanup(void)
+{
+ purple_signal_disconnect(purple_conversations_get_handle(),
+ "deleting-conversation", otrg_plugin_handle,
+ PURPLE_CALLBACK(conversation_destroyed));
+}
+
static const OtrgDialogUiOps gtk_dialog_ui_ops = {
+ otrg_gtk_dialog_init,
+ otrg_gtk_dialog_cleanup,
otrg_gtk_dialog_notify_message,
otrg_gtk_dialog_display_otr_message,
otrg_gtk_dialog_private_key_wait_start,
otrg_gtk_dialog_private_key_wait_done,
otrg_gtk_dialog_unknown_fingerprint,
otrg_gtk_dialog_verify_fingerprint,
+ otrg_gtk_dialog_socialist_millionaires,
+ otrg_gtk_dialog_update_smp,
otrg_gtk_dialog_connected,
otrg_gtk_dialog_disconnected,
otrg_gtk_dialog_stillconnected,
diff --git a/gtk-dialog.h b/gtk-dialog.h
index a9951a5..2a1098c 100644
--- a/gtk-dialog.h
+++ b/gtk-dialog.h
@@ -1,6 +1,6 @@
/*
* Off-the-Record Messaging plugin for pidgin
- * Copyright (C) 2004-2005 Nikita Borisov and Ian Goldberg
+ * Copyright (C) 2004-2007 Ian Goldberg, Chris Alexander, Nikita Borisov
* <otr at cypherpunks.ca>
*
* This program is free software; you can redistribute it and/or modify
diff --git a/gtk-ui.c b/gtk-ui.c
index efc01dd..37f1b8e 100644
--- a/gtk-ui.c
+++ b/gtk-ui.c
@@ -1,6 +1,6 @@
/*
* Off-the-Record Messaging plugin for pidgin
- * Copyright (C) 2004-2005 Nikita Borisov and Ian Goldberg
+ * Copyright (C) 2004-2007 Ian Goldberg, Chris Alexander, Nikita Borisov
* <otr at cypherpunks.ca>
*
* This program is free software; you can redistribute it and/or modify
@@ -17,6 +17,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+/* config.h */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
/* system headers */
#include <gtk/gtk.h>
@@ -32,6 +37,11 @@
#include "notify.h"
#include "gtkutils.h"
+#ifdef ENABLE_NLS
+/* internationalisation header */
+#include <glib/gi18n-lib.h>
+#endif
+
/* purple-otr headers */
#include "dialogs.h"
#include "ui.h"
@@ -41,6 +51,7 @@ struct otroptionsdata {
GtkWidget *enablebox;
GtkWidget *automaticbox;
GtkWidget *onlyprivatebox;
+ GtkWidget *avoidloggingotrbox;
};
static struct {
@@ -59,10 +70,10 @@ static struct {
} ui_layout;
static const gchar *trust_states[] = {
- "Not private",
- "Unverified",
- "Private",
- "Finished"
+ N_("Not private"),
+ N_("Unverified"),
+ N_("Private"),
+ N_("Finished")
};
static void account_menu_changed_cb(GtkWidget *item, PurpleAccount *account,
@@ -82,16 +93,16 @@ static void account_menu_changed_cb(GtkWidget *item, PurpleAccount *account,
fingerprint_buf, accountname, protocol);
if (fingerprint) {
- sprintf(s, "Fingerprint: %.80s", fingerprint);
+ sprintf(s, _("Fingerprint: %.80s"), fingerprint);
if (ui_layout.generate_button)
gtk_widget_set_sensitive(ui_layout.generate_button, 0);
} else {
- sprintf(s, "No key present");
+ sprintf(s, _("No key present"));
if (ui_layout.generate_button)
gtk_widget_set_sensitive(ui_layout.generate_button, 1);
}
} else {
- sprintf(s, "No account available");
+ sprintf(s, _("No account available"));
if (ui_layout.generate_button)
gtk_widget_set_sensitive(ui_layout.generate_button, 0);
}
@@ -101,39 +112,11 @@ static void account_menu_changed_cb(GtkWidget *item, PurpleAccount *account,
}
}
-static GtkWidget *accountmenu_get_selected_item(void)
-{
- GtkWidget *menu;
-
- if (ui_layout.accountmenu == NULL) return NULL;
-
- menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(ui_layout.accountmenu));
- return gtk_menu_get_active(GTK_MENU(menu));
-}
-
-static PurpleAccount *item_get_account(GtkWidget *item)
-{
- if (!item) return NULL;
- return g_object_get_data(G_OBJECT(item), "account");
-}
-
/* Call this function when the DSA key is updated; it will redraw the
* UI, if visible. */
static void otrg_gtk_ui_update_fingerprint(void)
{
- GtkWidget *item;
- PurpleAccount *account;
- gpointer user_data;
-
- item = accountmenu_get_selected_item();
-
- if (!item) return;
-
- account = item_get_account(item);
- user_data = g_object_get_data(G_OBJECT(ui_layout.accountmenu),
- "user_data");
-
- account_menu_changed_cb(item, account, user_data);
+ g_signal_emit_by_name(G_OBJECT(ui_layout.accountmenu), "changed");
}
static void account_menu_added_removed_cb(PurpleAccount *account, void *data)
@@ -179,17 +162,17 @@ static void otrg_gtk_ui_update_keylist(void)
titles[0] = context->username;
if (context->msgstate == OTRL_MSGSTATE_ENCRYPTED &&
context->active_fingerprint != fingerprint) {
- titles[1] = "Unused";
+ titles[1] = _("Unused");
} else {
titles[1] = (gchar *)
- trust_states[otrg_plugin_context_to_trust(context)];
+ _(trust_states[otrg_plugin_context_to_trust(context)]);
}
titles[2] = (fingerprint->trust && fingerprint->trust[0]) ?
- "Yes" : "No";
+ _("Yes") : _("No");
otrl_privkey_hash_to_human(hash, fingerprint->fingerprint);
titles[3] = hash;
p = purple_find_prpl(context->protocol);
- proto_name = (p && p->info->name) ? p->info->name : "Unknown";
+ proto_name = (p && p->info->name) ? p->info->name : _("Unknown");
titles[4] = g_strdup_printf("%s (%s)", context->accountname,
proto_name);
i = gtk_clist_append(GTK_CLIST(keylist), titles);
@@ -217,7 +200,7 @@ static void otrg_gtk_ui_update_keylist(void)
static void generate(GtkWidget *widget, gpointer data)
{
PurpleAccount *account;
- account = item_get_account(accountmenu_get_selected_item());
+ account = pidgin_account_option_menu_get_selected(ui_layout.accountmenu);
if (account == NULL) return;
@@ -397,9 +380,11 @@ static void otroptions_clicked_cb(GtkButton *button, struct otroptionsdata *oo)
} else {
gtk_widget_set_sensitive(oo->onlyprivatebox, FALSE);
}
+ gtk_widget_set_sensitive(oo->avoidloggingotrbox, TRUE);
} else {
gtk_widget_set_sensitive(oo->automaticbox, FALSE);
gtk_widget_set_sensitive(oo->onlyprivatebox, FALSE);
+ gtk_widget_set_sensitive(oo->avoidloggingotrbox, FALSE);
}
}
@@ -408,12 +393,14 @@ static void create_otroption_buttons(struct otroptionsdata *oo,
{
GtkWidget *tempbox1, *tempbox2;
- oo->enablebox = gtk_check_button_new_with_label("Enable private "
- "messaging");
- oo->automaticbox = gtk_check_button_new_with_label("Automatically "
- "initiate private messaging");
- oo->onlyprivatebox = gtk_check_button_new_with_label("Require private "
- "messaging");
+ oo->enablebox = gtk_check_button_new_with_label(_("Enable private "
+ "messaging"));
+ oo->automaticbox = gtk_check_button_new_with_label(_("Automatically "
+ "initiate private messaging"));
+ oo->onlyprivatebox = gtk_check_button_new_with_label(_("Require private "
+ "messaging"));
+ oo->avoidloggingotrbox = gtk_check_button_new_with_label(
+ _("Don't log OTR conversations"));
gtk_box_pack_start(GTK_BOX(vbox), oo->enablebox,
FALSE, FALSE, 0);
@@ -433,32 +420,39 @@ static void create_otroption_buttons(struct otroptionsdata *oo,
gtk_box_pack_start(GTK_BOX(tempbox2), oo->onlyprivatebox,
FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), oo->avoidloggingotrbox, FALSE, FALSE, 5);
+
g_signal_connect(G_OBJECT(oo->enablebox), "clicked",
G_CALLBACK(otroptions_clicked_cb), oo);
g_signal_connect(G_OBJECT(oo->automaticbox), "clicked",
G_CALLBACK(otroptions_clicked_cb), oo);
g_signal_connect(G_OBJECT(oo->onlyprivatebox), "clicked",
G_CALLBACK(otroptions_clicked_cb), oo);
+ g_signal_connect(G_OBJECT(oo->avoidloggingotrbox), "clicked",
+ G_CALLBACK(otroptions_clicked_cb), oo);
}
/* Load the global OTR prefs */
static void otrg_gtk_ui_global_prefs_load(gboolean *enabledp,
- gboolean *automaticp, gboolean *onlyprivatep)
+ gboolean *automaticp, gboolean *onlyprivatep,
+ gboolean *avoidloggingotrp)
{
if (purple_prefs_exists("/OTR/enabled")) {
*enabledp = purple_prefs_get_bool("/OTR/enabled");
*automaticp = purple_prefs_get_bool("/OTR/automatic");
*onlyprivatep = purple_prefs_get_bool("/OTR/onlyprivate");
+ *avoidloggingotrp = purple_prefs_get_bool("/OTR/avoidloggingotr");
} else {
*enabledp = TRUE;
*automaticp = TRUE;
*onlyprivatep = FALSE;
+ *avoidloggingotrp = FALSE;
}
}
/* Save the global OTR prefs */
static void otrg_gtk_ui_global_prefs_save(gboolean enabled,
- gboolean automatic, gboolean onlyprivate)
+ gboolean automatic, gboolean onlyprivate, gboolean avoidloggingotr)
{
if (! purple_prefs_exists("/OTR")) {
purple_prefs_add_none("/OTR");
@@ -466,30 +460,34 @@ static void otrg_gtk_ui_global_prefs_save(gboolean enabled,
purple_prefs_set_bool("/OTR/enabled", enabled);
purple_prefs_set_bool("/OTR/automatic", automatic);
purple_prefs_set_bool("/OTR/onlyprivate", onlyprivate);
+ purple_prefs_set_bool("/OTR/avoidloggingotr", avoidloggingotr);
}
/* Load the OTR prefs for a particular buddy */
static void otrg_gtk_ui_buddy_prefs_load(PurpleBuddy *buddy,
gboolean *usedefaultp, gboolean *enabledp, gboolean *automaticp,
- gboolean *onlyprivatep)
+ gboolean *onlyprivatep, gboolean *avoidloggingotrp)
{
PurpleBlistNode *node = &(buddy->node);
*usedefaultp = ! purple_blist_node_get_bool(node, "OTR/overridedefault");
if (*usedefaultp) {
- otrg_gtk_ui_global_prefs_load(enabledp, automaticp, onlyprivatep);
+ otrg_gtk_ui_global_prefs_load(enabledp, automaticp, onlyprivatep,
+ avoidloggingotrp);
} else {
*enabledp = purple_blist_node_get_bool(node, "OTR/enabled");
*automaticp = purple_blist_node_get_bool(node, "OTR/automatic");
*onlyprivatep = purple_blist_node_get_bool(node, "OTR/onlyprivate");
+ *avoidloggingotrp =
+ purple_blist_node_get_bool(node, "OTR/avoidloggingotr");
}
}
/* Save the OTR prefs for a particular buddy */
static void otrg_gtk_ui_buddy_prefs_save(PurpleBuddy *buddy,
gboolean usedefault, gboolean enabled, gboolean automatic,
- gboolean onlyprivate)
+ gboolean onlyprivate, gboolean avoidloggingotr)
{
PurpleBlistNode *node = &(buddy->node);
@@ -497,6 +495,7 @@ static void otrg_gtk_ui_buddy_prefs_save(PurpleBuddy *buddy,
purple_blist_node_set_bool(node, "OTR/enabled", enabled);
purple_blist_node_set_bool(node, "OTR/automatic", automatic);
purple_blist_node_set_bool(node, "OTR/onlyprivate", onlyprivate);
+ purple_blist_node_set_bool(node, "OTR/avoidloggingotr", avoidloggingotr);
}
static void load_otroptions(struct otroptionsdata *oo)
@@ -504,8 +503,10 @@ static void load_otroptions(struct otroptionsdata *oo)
gboolean otrenabled;
gboolean otrautomatic;
gboolean otronlyprivate;
+ gboolean otravoidloggingotr;
- otrg_gtk_ui_global_prefs_load(&otrenabled, &otrautomatic, &otronlyprivate);
+ otrg_gtk_ui_global_prefs_load(&otrenabled, &otrautomatic, &otronlyprivate,
+ &otravoidloggingotr);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(oo->enablebox),
otrenabled);
@@ -513,6 +514,8 @@ static void load_otroptions(struct otroptionsdata *oo)
otrautomatic);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(oo->onlyprivatebox),
otronlyprivate);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(oo->avoidloggingotrbox),
+ otravoidloggingotr);
otroptions_clicked_cb(GTK_BUTTON(oo->enablebox), oo);
}
@@ -525,7 +528,7 @@ static void make_privkeys_ui(GtkWidget *vbox)
GtkWidget *label;
GtkWidget *frame;
- frame = gtk_frame_new("My private keys");
+ frame = gtk_frame_new(_("My private keys"));
gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0);
fbox = gtk_vbox_new(FALSE, 5);
@@ -534,7 +537,7 @@ static void make_privkeys_ui(GtkWidget *vbox)
hbox = gtk_hbox_new(FALSE, 5);
gtk_box_pack_start(GTK_BOX(fbox), hbox, FALSE, FALSE, 0);
- label = gtk_label_new("Key for account:");
+ label = gtk_label_new(_("Key for account:"));
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
ui_layout.accountmenu = pidgin_account_option_menu_new(NULL, 1,
@@ -559,7 +562,7 @@ static void make_privkeys_ui(GtkWidget *vbox)
gtk_signal_connect(GTK_OBJECT(ui_layout.generate_button), "clicked",
GTK_SIGNAL_FUNC(generate), NULL);
- label = gtk_label_new("Generate");
+ label = gtk_label_new(_("Generate"));
gtk_container_add(GTK_CONTAINER(ui_layout.generate_button), label);
otrg_gtk_ui_update_fingerprint();
@@ -577,7 +580,9 @@ static void otroptions_save_cb(GtkButton *button, struct otroptionsdata *oo)
gtk_toggle_button_get_active(
GTK_TOGGLE_BUTTON(oo->automaticbox)),
gtk_toggle_button_get_active(
- GTK_TOGGLE_BUTTON(oo->onlyprivatebox)));
+ GTK_TOGGLE_BUTTON(oo->onlyprivatebox)),
+ gtk_toggle_button_get_active(
+ GTK_TOGGLE_BUTTON(oo->avoidloggingotrbox)));
otrg_dialog_resensitize_all();
}
@@ -588,7 +593,7 @@ static void make_options_ui(GtkWidget *vbox)
GtkWidget *fbox;
GtkWidget *frame;
- frame = gtk_frame_new("Default OTR Settings");
+ frame = gtk_frame_new(_("Default OTR Settings"));
gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0);
fbox = gtk_vbox_new(FALSE, 0);
@@ -605,6 +610,8 @@ static void make_options_ui(GtkWidget *vbox)
G_CALLBACK(otroptions_save_cb), &(ui_layout.oo));
g_signal_connect(G_OBJECT(ui_layout.oo.onlyprivatebox), "clicked",
G_CALLBACK(otroptions_save_cb), &(ui_layout.oo));
+ g_signal_connect(G_OBJECT(ui_layout.oo.avoidloggingotrbox), "clicked",
+ G_CALLBACK(otroptions_save_cb), &(ui_layout.oo));
}
/* Create the fingerprint UI, and pack it into the vbox */
@@ -613,8 +620,13 @@ static void make_fingerprints_ui(GtkWidget *vbox)
GtkWidget *hbox;
GtkWidget *table;
GtkWidget *label;
- char *titles[5] = { "Screenname", "Status", "Verified",
- "Fingerprint", "Account" };
+ char *titles[5];
+
+ titles[0] = _("Screenname");
+ titles[1] = _("Status");
+ titles[2] = _("Verified");
+ titles[3] = _("Fingerprint");
+ titles[4] = _("Account");
ui_layout.scrollwin = gtk_scrolled_window_new(0, 0);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ui_layout.scrollwin),
@@ -650,7 +662,7 @@ static void make_fingerprints_ui(GtkWidget *vbox)
ui_layout.connect_button = gtk_button_new();
gtk_signal_connect(GTK_OBJECT(ui_layout.connect_button), "clicked",
GTK_SIGNAL_FUNC(connect_connection), NULL);
- label = gtk_label_new("Start private connection");
+ label = gtk_label_new(_("Start private connection"));
gtk_container_add(GTK_CONTAINER(ui_layout.connect_button), label);
gtk_table_attach_defaults(GTK_TABLE(table), ui_layout.connect_button,
0, 1, 0, 1);
@@ -658,7 +670,7 @@ static void make_fingerprints_ui(GtkWidget *vbox)
ui_layout.disconnect_button = gtk_button_new();
gtk_signal_connect(GTK_OBJECT(ui_layout.disconnect_button), "clicked",
GTK_SIGNAL_FUNC(disconnect_connection), NULL);
- label = gtk_label_new("End private connection");
+ label = gtk_label_new(_("End private connection"));
gtk_container_add(GTK_CONTAINER(ui_layout.disconnect_button), label);
gtk_table_attach_defaults(GTK_TABLE(table), ui_layout.disconnect_button,
0, 1, 1, 2);
@@ -666,7 +678,7 @@ static void make_fingerprints_ui(GtkWidget *vbox)
ui_layout.verify_button = gtk_button_new();
gtk_signal_connect(GTK_OBJECT(ui_layout.verify_button), "clicked",
GTK_SIGNAL_FUNC(verify_fingerprint), NULL);
- label = gtk_label_new("Verify fingerprint");
+ label = gtk_label_new(_("Verify fingerprint"));
gtk_container_add(GTK_CONTAINER(ui_layout.verify_button), label);
gtk_table_attach_defaults(GTK_TABLE(table), ui_layout.verify_button,
1, 2, 0, 1);
@@ -674,7 +686,7 @@ static void make_fingerprints_ui(GtkWidget *vbox)
ui_layout.forget_button = gtk_button_new();
gtk_signal_connect(GTK_OBJECT(ui_layout.forget_button), "clicked",
GTK_SIGNAL_FUNC(forget_fingerprint), NULL);
- label = gtk_label_new("Forget fingerprint");
+ label = gtk_label_new(_("Forget fingerprint"));
gtk_container_add(GTK_CONTAINER(ui_layout.forget_button), label);
gtk_table_attach_defaults(GTK_TABLE(table), ui_layout.forget_button,
1, 2, 1, 2);
@@ -722,10 +734,10 @@ GtkWidget* otrg_gtk_ui_make_widget(PurplePlugin *plugin)
make_fingerprints_ui(fingerprintbox);
- gtk_notebook_append_page(GTK_NOTEBOOK(notebook), fingerprintbox,
- gtk_label_new("Known fingerprints"));
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), configbox,
- gtk_label_new("Config"));
+ gtk_label_new(_("Config")));
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook), fingerprintbox,
+ gtk_label_new(_("Known fingerprints")));
gtk_widget_show_all(vbox);
@@ -747,6 +759,7 @@ static void default_clicked_cb(GtkButton *button, struct cbdata *data)
gtk_widget_set_sensitive(data->oo.enablebox, FALSE);
gtk_widget_set_sensitive(data->oo.automaticbox, FALSE);
gtk_widget_set_sensitive(data->oo.onlyprivatebox, FALSE);
+ gtk_widget_set_sensitive(data->oo.avoidloggingotrbox, FALSE);
} else {
otroptions_clicked_cb(button, &(data->oo));
}
@@ -754,10 +767,10 @@ static void default_clicked_cb(GtkButton *button, struct cbdata *data)
static void load_buddyprefs(struct cbdata *data)
{
- gboolean usedefault, enabled, automatic, onlyprivate;
+ gboolean usedefault, enabled, automatic, onlyprivate, avoidloggingotr;
otrg_gtk_ui_buddy_prefs_load(data->buddy, &usedefault, &enabled,
- &automatic, &onlyprivate);
+ &automatic, &onlyprivate, &avoidloggingotr);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->defaultbox),
usedefault);
@@ -773,6 +786,9 @@ static void load_buddyprefs(struct cbdata *data)
GTK_TOGGLE_BUTTON(data->oo.automaticbox), automatic);
gtk_toggle_button_set_active(
GTK_TOGGLE_BUTTON(data->oo.onlyprivatebox), onlyprivate);
+ gtk_toggle_button_set_active(
+ GTK_TOGGLE_BUTTON(data->oo.avoidloggingotrbox),
+ avoidloggingotr);
}
default_clicked_cb(GTK_BUTTON(data->defaultbox), data);
@@ -796,7 +812,9 @@ static void config_buddy_clicked_cb(GtkButton *button, struct cbdata *data)
gtk_toggle_button_get_active(
GTK_TOGGLE_BUTTON(data->oo.automaticbox)),
gtk_toggle_button_get_active(
- GTK_TOGGLE_BUTTON(data->oo.onlyprivatebox)));
+ GTK_TOGGLE_BUTTON(data->oo.onlyprivatebox)),
+ gtk_toggle_button_get_active(
+ GTK_TOGGLE_BUTTON(data->oo.avoidloggingotrbox)));
otrg_dialog_resensitize_all();
}
@@ -812,11 +830,12 @@ static void otrg_gtk_ui_config_buddy(PurpleBuddy *buddy)
GtkWidget *dialog;
GtkWidget *label;
char *label_text;
+ char *label_markup;
struct cbdata *data = malloc(sizeof(struct cbdata));
if (!data) return;
- dialog = gtk_dialog_new_with_buttons("OTR Settings",
+ dialog = gtk_dialog_new_with_buttons(_("OTR Settings"),
NULL, 0,
GTK_STOCK_OK, GTK_RESPONSE_OK,
NULL);
@@ -834,12 +853,15 @@ static void otrg_gtk_ui_config_buddy(PurpleBuddy *buddy)
/* Set the title */
- label_text = g_strdup_printf("<span weight=\"bold\" size=\"larger\">"
- "OTR Settings for %s</span>", purple_buddy_get_contact_alias(buddy));
+ label_text = g_strdup_printf(_("OTR Settings for %s"),
+ purple_buddy_get_contact_alias(buddy));
+ label_markup = g_strdup_printf("<span weight=\"bold\" size=\"larger\">"
+ "%s</span>", label_text);
label = gtk_label_new(NULL);
- gtk_label_set_markup(GTK_LABEL(label), label_text);
+ gtk_label_set_markup(GTK_LABEL(label), label_markup);
+ g_free(label_markup);
g_free(label_text);
gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
@@ -848,8 +870,8 @@ static void otrg_gtk_ui_config_buddy(PurpleBuddy *buddy)
/* Make the cascaded checkboxes */
- data->defaultbox = gtk_check_button_new_with_label("Use default "
- "OTR settings for this buddy");
+ data->defaultbox = gtk_check_button_new_with_label(_("Use default "
+ "OTR settings for this buddy"));
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), data->defaultbox,
FALSE, FALSE, 0);
@@ -869,6 +891,8 @@ static void otrg_gtk_ui_config_buddy(PurpleBuddy *buddy)
G_CALLBACK(config_buddy_clicked_cb), data);
g_signal_connect(G_OBJECT(data->oo.onlyprivatebox), "clicked",
G_CALLBACK(config_buddy_clicked_cb), data);
+ g_signal_connect(G_OBJECT(data->oo.avoidloggingotrbox), "clicked",
+ G_CALLBACK(config_buddy_clicked_cb), data);
/* Set the inital states of the buttons */
load_buddyprefs(data);
@@ -881,63 +905,81 @@ static void otrg_gtk_ui_config_buddy(PurpleBuddy *buddy)
gtk_widget_show_all(dialog);
}
-/* Calculate the policy for a particular account / username */
-static OtrlPolicy otrg_gtk_ui_find_policy(PurpleAccount *account,
+/* Load the preferences for a particular account / username */
+static void otrg_gtk_ui_get_prefs(OtrgUiPrefs *prefsp, PurpleAccount *account,
const char *name)
{
PurpleBuddy *buddy;
- gboolean otrenabled, otrautomatic, otronlyprivate;
- gboolean buddyusedefault, buddyenabled, buddyautomatic, buddyonlyprivate;
- OtrlPolicy policy = OTRL_POLICY_DEFAULT;
+ gboolean otrenabled, otrautomatic, otronlyprivate, otravoidloggingotr;
+ gboolean buddyusedefault, buddyenabled, buddyautomatic, buddyonlyprivate,
+ buddyavoidloggingotr;
+
+ prefsp->policy = OTRL_POLICY_DEFAULT;
+ prefsp->avoid_logging_otr = FALSE;
/* Get the default policy */
- otrg_gtk_ui_global_prefs_load(&otrenabled, &otrautomatic, &otronlyprivate);
+ otrg_gtk_ui_global_prefs_load(&otrenabled, &otrautomatic, &otronlyprivate,
+ &otravoidloggingotr);
if (otrenabled) {
if (otrautomatic) {
if (otronlyprivate) {
- policy = OTRL_POLICY_ALWAYS;
+ prefsp->policy = OTRL_POLICY_ALWAYS;
} else {
- policy = OTRL_POLICY_OPPORTUNISTIC;
+ prefsp->policy = OTRL_POLICY_OPPORTUNISTIC;
}
} else {
- policy = OTRL_POLICY_MANUAL;
+ prefsp->policy = OTRL_POLICY_MANUAL;
}
+ prefsp->avoid_logging_otr = otravoidloggingotr;
} else {
- policy = OTRL_POLICY_NEVER;
+ prefsp->policy = OTRL_POLICY_NEVER;
}
buddy = purple_find_buddy(account, name);
- if (!buddy) return policy;
+ if (!buddy) return;
/* Get the buddy-specific policy, if present */
otrg_gtk_ui_buddy_prefs_load(buddy, &buddyusedefault, &buddyenabled,
- &buddyautomatic, &buddyonlyprivate);
+ &buddyautomatic, &buddyonlyprivate, &buddyavoidloggingotr);
- if (buddyusedefault) return policy;
+ if (buddyusedefault) return;
if (buddyenabled) {
if (buddyautomatic) {
if (buddyonlyprivate) {
- policy = OTRL_POLICY_ALWAYS;
+ prefsp->policy = OTRL_POLICY_ALWAYS;
} else {
- policy = OTRL_POLICY_OPPORTUNISTIC;
+ prefsp->policy = OTRL_POLICY_OPPORTUNISTIC;
}
} else {
- policy = OTRL_POLICY_MANUAL;
+ prefsp->policy = OTRL_POLICY_MANUAL;
}
+ prefsp->avoid_logging_otr = buddyavoidloggingotr;
} else {
- policy = OTRL_POLICY_NEVER;
+ prefsp->policy = OTRL_POLICY_NEVER;
}
+}
- return policy;
+/* Initialize the OTR UI subsystem */
+static void otrg_gtk_ui_init(void)
+{
+ /* Nothing to do */
+}
+
+/* Deinitialize the OTR UI subsystem */
+static void otrg_gtk_ui_cleanup(void)
+{
+ /* Nothing to do */
}
static const OtrgUiUiOps gtk_ui_ui_ops = {
+ otrg_gtk_ui_init,
+ otrg_gtk_ui_cleanup,
otrg_gtk_ui_update_fingerprint,
otrg_gtk_ui_update_keylist,
otrg_gtk_ui_config_buddy,
- otrg_gtk_ui_find_policy
+ otrg_gtk_ui_get_prefs
};
/* Get the GTK UI ops */
diff --git a/gtk-ui.h b/gtk-ui.h
index 3e82cb6..64d4452 100644
--- a/gtk-ui.h
+++ b/gtk-ui.h
@@ -1,6 +1,6 @@
/*
* Off-the-Record Messaging plugin for pidgin
- * Copyright (C) 2004-2005 Nikita Borisov and Ian Goldberg
+ * Copyright (C) 2004-2007 Ian Goldberg, Chris Alexander, Nikita Borisov
* <otr at cypherpunks.ca>
*
* This program is free software; you can redistribute it and/or modify
diff --git a/makedist b/makedist
index c10610b..0dade7f 100644
--- a/makedist
+++ b/makedist
@@ -2,6 +2,7 @@
# Make the distribution tar.gz file from the CVS exported version
+intltoolize --force --copy
autoreconf -s -i
./configure --mandir=/usr/share/man --prefix=/usr
fakeroot make dist
diff --git a/otr-plugin.c b/otr-plugin.c
index 18f3845..8e2bab3 100644
--- a/otr-plugin.c
+++ b/otr-plugin.c
@@ -1,6 +1,6 @@
/*
* Off-the-Record Messaging plugin for pidgin
- * Copyright (C) 2004-2005 Nikita Borisov and Ian Goldberg
+ * Copyright (C) 2004-2007 Ian Goldberg, Chris Alexander, Nikita Borisov
* <otr at cypherpunks.ca>
*
* This program is free software; you can redistribute it and/or modify
@@ -43,9 +43,23 @@
#include "gtkplugin.h"
#endif
+#ifdef ENABLE_NLS
+
+#ifdef WIN32
+/* On Win32, include win32dep.h from pidgin for correct definition
+ * of LOCALEDIR */
+#include "win32dep.h"
+#endif /* WIN32 */
+
+/* internationalisation header */
+#include <glib/gi18n-lib.h>
+
+#endif /* ENABLE_NLS */
+
/* libotr headers */
#include <libotr/privkey.h>
#include <libotr/proto.h>
+#include <libotr/tlv.h>
#include <libotr/message.h>
#include <libotr/userstate.h>
@@ -56,6 +70,7 @@
#ifdef USING_GTK
/* purple-otr GTK headers */
+#include <glib.h>
#include "gtk-ui.h"
#include "gtk-dialog.h"
#endif
@@ -79,6 +94,10 @@ PurplePlugin *otrg_plugin_handle;
/* We'll only use the one OtrlUserState. */
OtrlUserState otrg_plugin_userstate = NULL;
+/* GLib HashTable for storing the maximum message size for various
+ * protocols. */
+GHashTable* mms_table;
+
/* Send an IM from the given account to the given recipient. Display an
* error dialog if that account isn't currently logged in. */
void otrg_plugin_inject_message(PurpleAccount *account, const char *recipient,
@@ -91,11 +110,11 @@ void otrg_plugin_inject_message(PurpleAccount *account, const char *recipient,
const char *protocol = purple_account_get_protocol_id(account);
const char *accountname = purple_account_get_username(account);
PurplePlugin *p = purple_find_prpl(protocol);
- char *msg = g_strdup_printf("You are not currently connected to "
- "account %s (%s).", accountname,
- (p && p->info->name) ? p->info->name : "Unknown");
+ char *msg = g_strdup_printf(_("You are not currently connected to "
+ "account %s (%s)."), accountname,
+ (p && p->info->name) ? p->info->name : _("Unknown"));
otrg_dialog_notify_error(accountname, protocol, recipient,
- "Not connected", msg, NULL);
+ _("Not connected"), msg, NULL);
g_free(msg);
return;
}
@@ -106,13 +125,15 @@ static OtrlPolicy policy_cb(void *opdata, ConnContext *context)
{
PurpleAccount *account;
OtrlPolicy policy = OTRL_POLICY_DEFAULT;
+ OtrgUiPrefs prefs;
if (!context) return policy;
account = purple_accounts_find(context->accountname, context->protocol);
if (!account) return policy;
- return otrg_ui_find_policy(account, context->username);
+ otrg_ui_get_prefs(&prefs, account, context->username);
+ return prefs.policy;
}
static const char *protocol_name_cb(void *opdata, const char *protocol)
@@ -137,13 +158,13 @@ void otrg_plugin_create_privkey(const char *accountname,
gchar *privkeyfile = g_build_filename(purple_user_dir(), PRIVKEYFNAME, NULL);
if (!privkeyfile) {
- fprintf(stderr, "Out of memory building filenames!\n");
+ fprintf(stderr, _("Out of memory building filenames!\n"));
return;
}
privf = g_fopen(privkeyfile, "w+b");
g_free(privkeyfile);
if (!privf) {
- fprintf(stderr, "Could not write private key file\n");
+ fprintf(stderr, _("Could not write private key file\n"));
return;
}
@@ -186,10 +207,11 @@ static void inject_message_cb(void *opdata, const char *accountname,
PurpleAccount *account = purple_accounts_find(accountname, protocol);
if (!account) {
PurplePlugin *p = purple_find_prpl(protocol);
- char *msg = g_strdup_printf("Unknown account %s (%s).", accountname,
- (p && p->info->name) ? p->info->name : "Unknown");
+ char *msg = g_strdup_printf(_("Unknown account %s (%s)."),
+ accountname,
+ (p && p->info->name) ? p->info->name : _("Unknown"));
otrg_dialog_notify_error(accountname, protocol, recipient,
- "Unknown account", msg, NULL);
+ _("Unknown account"), msg, NULL);
g_free(msg);
return;
}
@@ -241,6 +263,8 @@ static void confirm_fingerprint_cb(void *opdata, OtrlUserState us,
static void write_fingerprints_cb(void *opdata)
{
otrg_plugin_write_fingerprints();
+ otrg_ui_update_keylist();
+ otrg_dialog_resensitize_all();
}
static void gone_secure_cb(void *opdata, ConnContext *context)
@@ -265,6 +289,15 @@ static void log_message_cb(void *opdata, const char *message)
purple_debug_info("otr", message);
}
+static int max_message_size_cb(void *opdata, ConnContext *context)
+{
+ void* lookup_result = g_hash_table_lookup(mms_table, context->protocol);
+ if (!lookup_result)
+ return 0;
+ else
+ return *((int*)lookup_result);
+}
+
static OtrlMessageAppOps ui_ops = {
policy_cb,
create_privkey_cb,
@@ -280,11 +313,14 @@ static OtrlMessageAppOps ui_ops = {
gone_secure_cb,
gone_insecure_cb,
still_secure_cb,
- log_message_cb
+ log_message_cb,
+ max_message_size_cb,
+ NULL, /* account_name */
+ NULL /* account_name_free */
};
-static void process_sending_im(PurpleAccount *account, char *who, char **message,
- void *m)
+static void process_sending_im(PurpleAccount *account, char *who,
+ char **message, void *m)
{
char *newmessage = NULL;
const char *accountname = purple_account_get_username(account);
@@ -307,17 +343,45 @@ static void process_sending_im(PurpleAccount *account, char *who, char **message
free(*message);
*message = ourm;
} else if (newmessage) {
- char *ourm = malloc(strlen(newmessage) + 1);
- if (ourm) {
- strcpy(ourm, newmessage);
- }
- otrl_message_free(newmessage);
+ /* Fragment the message if necessary, and send all but the last
+ * fragment over the network. Pidgin will send the last
+ * fragment for us. */
+ ConnContext *context = otrl_context_find(otrg_plugin_userstate,
+ username, accountname, protocol, 0, NULL, NULL, NULL);
free(*message);
- *message = ourm;
+ *message = NULL;
+ err = otrl_message_fragment_and_send(&ui_ops, NULL, context,
+ newmessage, OTRL_FRAGMENT_SEND_ALL_BUT_LAST, message);
+ otrl_message_free(newmessage);
}
free(username);
}
+/* Abort the SMP protocol. Used when malformed or unexpected messages
+ * are received. */
+void otrg_plugin_abort_smp(ConnContext *context)
+{
+ otrl_message_abort_smp(otrg_plugin_userstate, &ui_ops, NULL, context);
+}
+
+/* Start the Socialist Millionaires' Protocol over the current connection,
+ * using the given initial secret. */
+void otrg_plugin_start_smp(ConnContext *context,
+ const unsigned char *secret, size_t secretlen)
+{
+ otrl_message_initiate_smp(otrg_plugin_userstate, &ui_ops, NULL,
+ context, secret, secretlen);
+}
+
+/* Continue the Socialist Millionaires' Protocol over the current connection,
+ * using the given initial secret (ie finish step 2). */
+void otrg_plugin_continue_smp(ConnContext *context,
+ const unsigned char *secret, size_t secretlen)
+{
+ otrl_message_respond_smp(otrg_plugin_userstate, &ui_ops, NULL,
+ context, secret, secretlen);
+}
+
/* Send the default OTR Query message to the correspondent of the given
* context, from the given account. [account is actually a
* PurpleAccount*, but it's declared here as void* so this can be passed
@@ -325,8 +389,10 @@ static void process_sending_im(PurpleAccount *account, char *who, char **message
void otrg_plugin_send_default_query(ConnContext *context, void *vaccount)
{
PurpleAccount *account = vaccount;
+ OtrgUiPrefs prefs;
+ otrg_ui_get_prefs(&prefs, account, context->username);
char *msg = otrl_proto_default_query_msg(context->accountname,
- otrg_ui_find_policy(account, context->username));
+ prefs.policy);
otrg_plugin_inject_message(account, context->username,
msg ? msg : "?OTRv2?");
free(msg);
@@ -339,13 +405,14 @@ void otrg_plugin_send_default_query_conv(PurpleConversation *conv)
PurpleAccount *account;
const char *username, *accountname;
char *msg;
+ OtrgUiPrefs prefs;
account = purple_conversation_get_account(conv);
accountname = purple_account_get_username(account);
username = purple_conversation_get_name(conv);
- msg = otrl_proto_default_query_msg(accountname,
- otrg_ui_find_policy(account, username));
+ otrg_ui_get_prefs(&prefs, account, username);
+ msg = otrl_proto_default_query_msg(accountname, prefs.policy);
otrg_plugin_inject_message(account, username, msg ? msg : "?OTRv2?");
free(msg);
}
@@ -388,6 +455,53 @@ static gboolean process_receiving_im(PurpleAccount *account, char **who,
otrg_dialog_finished(accountname, protocol, username);
otrg_ui_update_keylist();
}
+
+ /* Keep track of our current progress in the Socialist Millionaires'
+ * Protocol. */
+ ConnContext *context = otrl_context_find(otrg_plugin_userstate, username,
+ accountname, protocol, 0, NULL, NULL, NULL);
+ NextExpectedSMP nextMsg = context->smstate->nextExpected;
+
+ tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1);
+ if (tlv) {
+ if (nextMsg != OTRL_SMP_EXPECT1)
+ otrg_plugin_abort_smp(context);
+ else {
+ otrg_dialog_socialist_millionaires(context);
+ }
+ }
+ tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP2);
+ if (tlv) {
+ if (nextMsg != OTRL_SMP_EXPECT2)
+ otrg_plugin_abort_smp(context);
+ else {
+ otrg_dialog_update_smp(context, 0.6);
+ context->smstate->nextExpected = OTRL_SMP_EXPECT4;
+ }
+ }
+ tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP3);
+ if (tlv) {
+ if (nextMsg != OTRL_SMP_EXPECT3)
+ otrg_plugin_abort_smp(context);
+ else {
+ otrg_dialog_update_smp(context, 1.0);
+ context->smstate->nextExpected = OTRL_SMP_EXPECT1;
+ }
+ }
+ tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP4);
+ if (tlv) {
+ if (nextMsg != OTRL_SMP_EXPECT4)
+ otrg_plugin_abort_smp(context);
+ else {
+ otrg_dialog_update_smp(context, 1.0);
+ context->smstate->nextExpected = OTRL_SMP_EXPECT1;
+ }
+ }
+ tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP_ABORT);
+ if (tlv) {
+ otrg_dialog_update_smp(context, 0.0);
+ context->smstate->nextExpected = OTRL_SMP_EXPECT1;
+ }
otrl_tlv_free(tlvs);
@@ -409,6 +523,25 @@ static void process_conv_create(PurpleConversation *conv, void *data)
if (conv) otrg_dialog_new_conv(conv);
}
+static void process_conv_updated(PurpleConversation *conv,
+ PurpleConvUpdateType type, void *data)
+{
+ /* See if someone's trying to turn logging on for this conversation,
+ * and we don't want them to. */
+ if (type == PURPLE_CONV_UPDATE_LOGGING) {
+ OtrgUiPrefs prefs;
+ PurpleAccount *account = purple_conversation_get_account(conv);
+ otrg_ui_get_prefs(&prefs, account, purple_conversation_get_name(conv));
+
+ ConnContext *context = otrg_plugin_conv_to_context(conv);
+ if (context && prefs.avoid_logging_otr &&
+ context->msgstate == OTRL_MSGSTATE_ENCRYPTED &&
+ conv->logging == TRUE) {
+ purple_conversation_set_logging(conv, FALSE);
+ }
+ }
+}
+
static void process_connection_change(PurpleConnection *conn, void *data)
{
/* If we log in or out of a connection, make sure all of the OTR
@@ -441,8 +574,8 @@ static void supply_extended_menu(PurpleBlistNode *node, GList **menu)
proto = purple_account_get_protocol_id(acct);
if (!otrg_plugin_proto_supports_otr(proto)) return;
- act = purple_menu_action_new("OTR Settings", (PurpleCallback)otr_options_cb,
- NULL, NULL);
+ act = purple_menu_action_new(_("OTR Settings"),
+ (PurpleCallback)otr_options_cb, NULL, NULL);
*menu = g_list_append(*menu, act);
}
@@ -487,25 +620,35 @@ ConnContext *otrg_plugin_conv_to_context(PurpleConversation *conv)
return context;
}
-/* Find the PurpleConversation appropriate to the given ConnContext. If
+/* Find the PurpleConversation appropriate to the given userinfo. If
* one doesn't yet exist, create it if force_create is true. */
-PurpleConversation *otrg_plugin_context_to_conv(ConnContext *context,
- int force_create)
+PurpleConversation *otrg_plugin_userinfo_to_conv(const char *accountname,
+ const char *protocol, const char *username, int force_create)
{
PurpleAccount *account;
PurpleConversation *conv;
- account = purple_accounts_find(context->accountname, context->protocol);
+ account = purple_accounts_find(accountname, protocol);
if (account == NULL) return NULL;
- conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, context->username, account);
+ conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
+ username, account);
if (conv == NULL && force_create) {
- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, context->username);
+ conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, username);
}
return conv;
}
+/* Find the PurpleConversation appropriate to the given ConnContext. If
+ * one doesn't yet exist, create it if force_create is true. */
+PurpleConversation *otrg_plugin_context_to_conv(ConnContext *context,
+ int force_create)
+{
+ return otrg_plugin_userinfo_to_conv(context->accountname,
+ context->protocol, context->username, force_create);
+}
+
/* What level of trust do we have in the privacy of this ConnContext? */
TrustLevel otrg_plugin_context_to_trust(ConnContext *context)
{
@@ -539,6 +682,98 @@ static void process_quitting(void)
}
}
+/* Read the maxmsgsizes from a FILE* into the given GHashTable.
+ * The FILE* must be open for reading. */
+static void mms_read_FILEp(FILE *mmsf, GHashTable *ght)
+{
+ char storeline[50];
+ size_t maxsize = sizeof(storeline);
+
+ if (!mmsf) return;
+
+ while(fgets(storeline, maxsize, mmsf)) {
+ char *protocol;
+ char *prot_in_table;
+ char *mms;
+ int *mms_in_table;
+ char *tab;
+ char *eol;
+ /* Parse the line, which should be of the form:
+ * protocol\tmaxmsgsize\n */
+ protocol = storeline;
+ tab = strchr(protocol, '\t');
+ if (!tab) continue;
+ *tab = '\0';
+
+ mms = tab + 1;
+ tab = strchr(mms, '\t');
+ if (tab) continue;
+ eol = strchr(mms, '\r');
+ if (!eol) eol = strchr(mms, '\n');
+ if (!eol) continue;
+ *eol = '\0';
+
+ prot_in_table = strdup(protocol);
+ mms_in_table = malloc(sizeof(int));
+ *mms_in_table = atoi(mms);
+ g_hash_table_insert(ght, prot_in_table, mms_in_table);
+ }
+}
+
+static void otrg_str_free(gpointer data)
+{
+ g_free((char*)data);
+}
+
+static void otrg_int_free(gpointer data)
+{
+ g_free((int*)data);
+}
+
+static void otrg_init_mms_table()
+{
+ mms_table = g_hash_table_new_full(g_str_hash, g_str_equal,
+ otrg_str_free, otrg_int_free);
+
+ /* Hardcoded defaults for maximum message sizes for various
+ * protocols. These can be overridden in the user's MAXMSGSIZEFNAME
+ * file. */
+ static const struct s_OtrgIdProtPair {
+ char *protid;
+ int maxmsgsize;
+ } mmsPairs[8] = {{"prpl-msn", 1409}, {"prpl-icq", 2346},
+ {"prpl-aim", 2343}, {"prpl-yahoo", 832}, {"prpl-gg", 1999},
+ {"prpl-irc", 417}, {"prpl-oscar", 2343}, {NULL, 0}};
+
+ int i = 0;
+ for (i=0; mmsPairs[i].protid != NULL; i++) {
+ char* nextprot = g_strdup(mmsPairs[i].protid);
+ int* nextsize = g_malloc(sizeof(int));
+ *nextsize = mmsPairs[i].maxmsgsize;
+ g_hash_table_insert(mms_table, nextprot, nextsize);
+ }
+
+ gchar *maxmsgsizefile = g_build_filename(purple_user_dir(),
+ MAXMSGSIZEFNAME, NULL);
+ FILE *mmsf;
+
+ if (maxmsgsizefile) {
+ mmsf = g_fopen(maxmsgsizefile, "rt");
+ /* Actually read the file here */
+ if (mmsf) {
+ mms_read_FILEp(mmsf, mms_table);
+ fclose(mmsf);
+ }
+ }
+
+ g_free(maxmsgsizefile);
+}
+
+static void otrg_free_mms_table()
+{
+ g_hash_table_destroy(mms_table);
+}
+
static gboolean otr_plugin_load(PurplePlugin *handle)
{
gchar *privkeyfile = g_build_filename(purple_user_dir(), PRIVKEYFNAME,
@@ -562,6 +797,8 @@ static gboolean otr_plugin_load(PurplePlugin *handle)
g_free(privkeyfile);
g_free(storefile);
+ otrg_init_mms_table();
+
otrg_plugin_handle = handle;
/* Make our OtrlUserState; we'll only use the one. */
@@ -581,6 +818,8 @@ static gboolean otr_plugin_load(PurplePlugin *handle)
PURPLE_CALLBACK(process_sending_im), NULL);
purple_signal_connect(conv_handle, "receiving-im-msg", otrg_plugin_handle,
PURPLE_CALLBACK(process_receiving_im), NULL);
+ purple_signal_connect(conv_handle, "conversation-updated",
+ otrg_plugin_handle, PURPLE_CALLBACK(process_conv_updated), NULL);
purple_signal_connect(conv_handle, "conversation-created",
otrg_plugin_handle, PURPLE_CALLBACK(process_conv_create), NULL);
purple_signal_connect(conn_handle, "signed-on", otrg_plugin_handle,
@@ -590,6 +829,9 @@ static gboolean otr_plugin_load(PurplePlugin *handle)
purple_signal_connect(blist_handle, "blist-node-extended-menu",
otrg_plugin_handle, PURPLE_CALLBACK(supply_extended_menu), NULL);
+ otrg_ui_init();
+ otrg_dialog_init();
+
purple_conversation_foreach(otrg_dialog_new_conv);
return 1;
@@ -606,12 +848,16 @@ static gboolean otr_plugin_unload(PurplePlugin *handle)
otrl_userstate_free(otrg_plugin_userstate);
otrg_plugin_userstate = NULL;
+ otrg_free_mms_table();
+
purple_signal_disconnect(core_handle, "quitting", otrg_plugin_handle,
PURPLE_CALLBACK(process_quitting));
- purple_signal_disconnect(conv_handle, "sending-im-msg", otrg_plugin_handle,
- PURPLE_CALLBACK(process_sending_im));
- purple_signal_disconnect(conv_handle, "receiving-im-msg", otrg_plugin_handle,
- PURPLE_CALLBACK(process_receiving_im));
+ purple_signal_disconnect(conv_handle, "sending-im-msg",
+ otrg_plugin_handle, PURPLE_CALLBACK(process_sending_im));
+ purple_signal_disconnect(conv_handle, "receiving-im-msg",
+ otrg_plugin_handle, PURPLE_CALLBACK(process_receiving_im));
+ purple_signal_disconnect(conv_handle, "conversation-updated",
+ otrg_plugin_handle, PURPLE_CALLBACK(process_conv_updated));
purple_signal_disconnect(conv_handle, "conversation-created",
otrg_plugin_handle, PURPLE_CALLBACK(process_conv_create));
purple_signal_disconnect(conn_handle, "signed-on", otrg_plugin_handle,
@@ -623,23 +869,23 @@ static gboolean otr_plugin_unload(PurplePlugin *handle)
purple_conversation_foreach(otrg_dialog_remove_conv);
+ otrg_dialog_cleanup();
+ otrg_ui_cleanup();
+
return 1;
}
/* Return 1 if the given protocol supports OTR, 0 otherwise. */
int otrg_plugin_proto_supports_otr(const char *proto)
{
- /* IRC is the only protocol we know of that OTR doesn't work on (its
- * maximum message size is too small to fit a Key Exchange Message). */
- if (proto && !strcmp(proto, "prpl-irc")) {
- return 0;
- }
+ /* Right now, OTR should work on all protocols, possibly
+ * with the help of fragmentation. */
return 1;
}
#ifdef USING_GTK
-static PurplePluginUiInfo ui_info =
+static PidginPluginUiInfo ui_info =
{
otrg_gtk_ui_make_widget
};
@@ -662,26 +908,23 @@ static PurplePluginInfo info =
2, /* major version */
0, /* minor version */
- PURPLE_PLUGIN_STANDARD, /* type */
+ PURPLE_PLUGIN_STANDARD, /* type */
PLUGIN_TYPE, /* ui_requirement */
0, /* flags */
NULL, /* dependencies */
- PURPLE_PRIORITY_DEFAULT, /* priority */
+ PURPLE_PRIORITY_DEFAULT, /* priority */
"otr", /* id */
- "Off-the-Record Messaging", /* name */
- PIDGIN_OTR_VERSION, /* version */
- /* summary */
- "Provides private and secure conversations",
- /* description */
- "Preserves the privacy of IM communications by providing "
- "encryption, authentication, deniability, and perfect "
- "forward secrecy.",
+ NULL, /* name */
+ PIDGIN_OTR_VERSION, /* version */
+ NULL, /* summary */
+ NULL, /* description */
/* author */
- "Nikita Borisov and Ian Goldberg\n\t\t\t<otr at cypherpunks.ca>",
- "http://www.cypherpunks.ca/otr/", /* homepage */
+ "Ian Goldberg, Chris Alexander, Nikita Borisov\n"
+ "\t\t\t<otr at cypherpunks.ca>",
+ "http://otr.cypherpunks.ca/", /* homepage */
- otr_plugin_load, /* load */
- otr_plugin_unload, /* unload */
+ otr_plugin_load, /* load */
+ otr_plugin_unload, /* unload */
NULL, /* destroy */
UI_INFO, /* ui_info */
@@ -701,6 +944,17 @@ __init_plugin(PurplePlugin *plugin)
/* Initialize the OTR library */
OTRL_INIT;
+
+#ifdef ENABLE_NLS
+ bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
+ bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
+#endif
+
+ info.name = _("Off-the-Record Messaging");
+ info.summary = _("Provides private and secure conversations");
+ info.description = _("Preserves the privacy of IM communications "
+ "by providing encryption, authentication, "
+ "deniability, and perfect forward secrecy.");
}
PURPLE_INIT_PLUGIN(otr, __init_plugin, info)
diff --git a/otr-plugin.h b/otr-plugin.h
index cbdf322..db10632 100644
--- a/otr-plugin.h
+++ b/otr-plugin.h
@@ -1,6 +1,6 @@
/*
* Off-the-Record Messaging plugin for pidgin
- * Copyright (C) 2004-2005 Nikita Borisov and Ian Goldberg
+ * Copyright (C) 2004-2007 Ian Goldberg, Chris Alexander, Nikita Borisov
* <otr at cypherpunks.ca>
*
* This program is free software; you can redistribute it and/or modify
@@ -30,6 +30,7 @@
#define PRIVKEYFNAME "otr.private_key"
#define STOREFNAME "otr.fingerprints"
+#define MAXMSGSIZEFNAME "otr.max_message_size"
extern PurplePlugin *otrg_plugin_handle;
@@ -44,6 +45,17 @@ void otrg_plugin_inject_message(PurpleAccount *account, const char *recipient,
void otrg_plugin_create_privkey(const char *accountname,
const char *protocol);
+/* Start or continue the Socialist Millionaires' Protocol over the current
+ * connection, using the given initial secret. */
+void otrg_plugin_start_smp(ConnContext *context,
+ const unsigned char *secret, size_t secretlen);
+void otrg_plugin_continue_smp(ConnContext *context,
+ const unsigned char *secret, size_t secretlen);
+
+/* Abort the SMP protocol. Used when malformed or unexpected messages
+ * are received. */
+void otrg_plugin_abort_smp(ConnContext *context);
+
/* Send the default OTR Query message to the correspondent of the given
* context, from the given account. [account is actually a
* PurpleAccount*, but it's declared here as void* so this can be passed
@@ -64,6 +76,11 @@ void otrg_plugin_write_fingerprints(void);
/* Find the ConnContext appropriate to a given PurpleConversation. */
ConnContext *otrg_plugin_conv_to_context(PurpleConversation *conv);
+/* Find the PurpleConversation appropriate to the given userinfo. If
+ * one doesn't yet exist, create it if force_create is true. */
+PurpleConversation *otrg_plugin_userinfo_to_conv(const char *accountname,
+ const char *protocol, const char *username, int force_create);
+
/* Find the PurpleConversation appropriate to the given ConnContext. If
* one doesn't yet exist, create it if force_create is true. */
PurpleConversation *otrg_plugin_context_to_conv(ConnContext *context,
diff --git a/packaging/fedora/gaim-otr.spec b/packaging/fedora/pidgin-otr.spec
similarity index 86%
rename from packaging/fedora/gaim-otr.spec
rename to packaging/fedora/pidgin-otr.spec
index d5edbd6..c88c2d1 100644
--- a/packaging/fedora/gaim-otr.spec
+++ b/packaging/fedora/pidgin-otr.spec
@@ -1,6 +1,6 @@
-Summary: Off-The-Record Messaging plugin for GAIM
-Name: gaim-otr
-Version: 3.0.0
+Summary: Off-The-Record Messaging plugin for pidgin
+Name: pidgin-otr
+Version: 3.1.0
Release: 1%{?dist}
Source: http://www.cypherpunks.ca/otr/%{name}-%{version}.tar.gz
Url: http://www.cypherpunks.ca/otr/
@@ -9,14 +9,14 @@ Group: Applications/Internet
Provides: otr-plugin = %{version}
Obsoletes: otr-plugin
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
-Requires: gaim >= 1.0.0, libotr >= 3.0.0
-BuildRequires: glib2-devel, gtk2-devel, libgcrypt-devel >= 1.2.0, libgpg-error-devel, gaim >= 1.0.0, libotr-devel >= 3.0.0
+Requires: pidgin >= 2.0.0, libotr >= 3.1.0
+BuildRequires: glib2-devel, gtk2-devel, libgcrypt-devel >= 1.2.0, libgpg-error-devel, pidgin >= 2.0.0, libotr-devel >= 3.1.0
%description
-This is a gaim plugin which implements Off-the-Record (OTR) Messaging.
+This is a pidgin plugin which implements Off-the-Record (OTR) Messaging.
It is known to work (at least) under the Linux and Windows versions of
-gaim (1.x).
+pidgin (2.x).
%prep
%setup -q
@@ -30,7 +30,7 @@ make %{?_smp_mflags} all
rm -rf $RPM_BUILD_ROOT
make DESTDIR=$RPM_BUILD_ROOT install
# libtool insists on creating this
-rm $RPM_BUILD_ROOT/%{_libdir}/gaim/gaim-otr.la
+rm $RPM_BUILD_ROOT/%{_libdir}/pidgin/pidgin-otr.la
%clean
rm -rf $RPM_BUILD_ROOT
@@ -38,7 +38,7 @@ rm -rf $RPM_BUILD_ROOT
%files
%defattr(-, root, root, 0755)
%doc README COPYING
-%{_libdir}/gaim/gaim-otr.so
+%{_libdir}/pidgin/pidgin-otr.so
%changelog
* Mon Oct 17 2005 Paul Wouters <paul at cypherpunks.ca> 3.0.0
diff --git a/packaging/windows/gaim-otr.nsi b/packaging/windows/gaim-otr.nsi
deleted file mode 100644
index a7ff749..0000000
--- a/packaging/windows/gaim-otr.nsi
+++ /dev/null
@@ -1,221 +0,0 @@
-; Script based on generated HM NIS Edit Script Wizard.
-; Forgive me, i am new at this. -- paul at cypherpunks.ca
-;
-; known issue. installer induced uninstaller abortion causes overwrite by installer without
-; uninstall.
-; v3.0.1 - Version for gaim-2.0.0 beta5
-; v3.0.0 - Bump version number.
-; v2.0.2 - Bump version number.
-; v2.0.1 - Bump version number.
-; v2.0.0-2 - linking to libotr-2.0.1
-; v2.0.0 - Bump version number. Fixed upgrading gaim2-otr (it didn't overwrite the dll)
-; bug reported by Aldert Hazenberg <aldert at xelerance.com>
-; - Added many safeguards and fixed conditions of failures when gaim is running
-; during install, or failed to (un)install previously.
-; - Removed popup signifying gaim is found
-; v1.99.0-1 - Bump version number, install Protocol.txt file
-; v1.0.3-2 - Fix for detecting gaim if not installed by Administrator
-; bug report by Joanna Rutkowska <joanna at mailsnare.net>
-; - Fix for uninstalling the dll when not installed as Administrator
-; v1.0.3 - Initial version
-
-
-; todo: SetBrandingImage
-; HM NIS Edit Wizard helper defines
-!define PRODUCT_NAME "gaim-otr"
-!define PRODUCT_VERSION "3.0.1"
-!define PRODUCT_PUBLISHER "Cypherpunks CA"
-!define PRODUCT_WEB_SITE "http://www.cypherpunks.ca/otr/"
-!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
-!define PRODUCT_UNINST_ROOT_KEY "HKLM"
-
-; MUI 1.67 compatible ------
-!include "MUI.nsh"
-
-; MUI Settings
-!define MUI_ABORTWARNING
-!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install.ico"
-!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico"
-
-; Welcome page
-!insertmacro MUI_PAGE_WELCOME
-; License page
-!insertmacro MUI_PAGE_LICENSE "c:\otr\COPYING.txt"
-; Directory page
-!insertmacro MUI_PAGE_DIRECTORY
-; Instfiles page
-!insertmacro MUI_PAGE_INSTFILES
-; Finish page
-!define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\README.txt"
-!insertmacro MUI_PAGE_FINISH
-
-; Uninstaller pages
-!insertmacro MUI_UNPAGE_INSTFILES
-
-; Language files
-!insertmacro MUI_LANGUAGE "English"
-
-; MUI end ------
-
-Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
-OutFile "${PRODUCT_NAME}-${PRODUCT_VERSION}.exe"
-InstallDir "$PROGRAMFILES\gaim2-otr"
-InstallDirRegKey HKEY_LOCAL_MACHINE SOFTWARE\gaim-otr "Install_Dir"
-;WriteRegStr HKLM "SOFTWARE\gaim2-otr" "gaimdir" ""
-
-Var "GaimDir"
-
-ShowInstDetails show
-ShowUnInstDetails show
-
-Section "MainSection" SEC01
-;InstallDir "$PROGRAMFILES\Gaim\plugins"
-
-; uninstall previous gaim2-otr install if found.
-Call UnInstOld
- ;Check for gaim installation
-Call GetGaimInstPath
-WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "SOFTWARE\gaim2-otr" "gaimdir" "$GaimDir"
-
- SetOutPath "$INSTDIR"
- SetOverwrite on
- File "c:\otr\gaim2-otr.dll"
- ; move to gaim plugin directory, check if not busy (gaim is running)
- call CopyDLL
- ; hard part is done, do the rest now.
- SetOverwrite on
- File "c:\otr\README.Toolkit.txt"
- File "c:\otr\README.txt"
- File "c:\otr\Protocol-v2.html"
- File "c:\otr\COPYING.txt"
- File "c:\otr\COPYING.LIB.txt"
- File "c:\otr\otr_mackey.exe"
- File "c:\otr\otr_modify.exe"
- File "c:\otr\otr_parse.exe"
- File "c:\otr\otr_readforge.exe"
- File "c:\otr\otr_remac.exe"
- File "c:\otr\otr_sesskeys.exe"
- File "c:\otr\gaim-otr.nsi"
-SectionEnd
-
-Section -AdditionalIcons
- CreateDirectory "$SMPROGRAMS\gaim2-otr"
- CreateShortCut "$SMPROGRAMS\gaim2-otr\Uninstall.lnk" "$INSTDIR\gaim2-otr-uninst.exe"
-SectionEnd
-
-Section -Post
- WriteUninstaller "$INSTDIR\gaim2-otr-uninst.exe"
- WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
- WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\gaim2-otr-uninst.exe"
- WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
- WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
- WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
-
-SectionEnd
-
-Function un.onUninstSuccess
- HideWindow
- MessageBox MB_ICONINFORMATION|MB_OK "$(^Name) was successfully removed from your computer."
-FunctionEnd
-
-Function un.onInit
- MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "Are you sure you want to completely remove $(^Name) and all of its components?" IDYES +2
- Abort
-FunctionEnd
-
-Section Uninstall
- Delete "$INSTDIR\gaim2-otr-uninst.exe"
- Delete "$INSTDIR\README.Toolkit.txt"
- Delete "$INSTDIR\README.txt"
- Delete "$INSTDIR\Protocol-v2.txt"
- Delete "$INSTDIR\COPYING.txt"
- Delete "$INSTDIR\COPYING.LIB.txt"
- Delete "$INSTDIR\otr_mackey.exe"
- Delete "$INSTDIR\otr_modify.exe"
- Delete "$INSTDIR\otr_parse.exe"
- Delete "$INSTDIR\otr_readforge.exe"
- Delete "$INSTDIR\otr_remac.exe"
- Delete "$INSTDIR\otr_sesskeys.exe"
- Delete "$INSTDIR\gaim2-otr.nsi"
- Delete "$SMPROGRAMS\gaim2-otr\Uninstall.lnk"
- RMDir "$SMPROGRAMS\gaim2-otr"
- RMDir "$INSTDIR"
-
- ReadRegStr $GaimDir HKLM Software\gaim-otr "gaimdir"
- IfFileExists "$GaimDir\plugins\gaim-otr.dll" dodelete
- ReadRegStr $GaimDir HKCU Software\gaim-otr "gaimdir"
- IfFileExists "$GaimDir\plugins\gaim-otr.dll" dodelete
-
- ReadRegStr $GaimDir HKLM Software\gaim2-otr "gaimdir"
- IfFileExists "$GaimDir\plugins\gaim2-otr.dll" dodelete
- ReadRegStr $GaimDir HKCU Software\gaim2-otr "gaimdir"
- IfFileExists "$GaimDir\plugins\gaim2-otr.dll" dodelete
- MessageBox MB_OK|MB_ICONINFORMATION "Could not find gaim plugin directory, gaim2-otr.dll not uninstalled!" IDOK ok
-dodelete:
- Delete "$GaimDir\plugins\gaim-otr.dll"
- Delete "$GaimDir\plugins\gaim2-otr.dll"
-
- IfFileExists "$GaimDir\plugins\gaim2-otr.dll" 0 +2
- MessageBox MB_OK|MB_ICONINFORMATION "gaim2-otr.dll is busy. Probably Gaim is still running. Please delete $GaimDir\plugins\gaim2-otr.dll manually."
- DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
- DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "SOFTWARE\gaim2-otr\gaimdir"
-ok:
-SetAutoClose true
-SectionEnd
-Function GetGaimInstPath
- Push $0
- ReadRegStr $0 HKLM "Software\gaim" ""
- IfFileExists "$0\gaim.exe" cont
- ReadRegStr $0 HKCU "Software\gaim" ""
- IfFileExists "$0\gaim.exe" cont
- MessageBox MB_OK|MB_ICONINFORMATION "Failed to find GAIM installation."
- Abort "Failed to find GAIM installation. Please install GAIM first."
-cont:
- StrCpy $GaimDir $0
- ;MessageBox MB_OK|MB_ICONINFORMATION "Gaim plugin directory found at $GaimDir\plugins ."
- WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "SOFTWARE\gaim2-otr" "gaimdir" "$GaimDir"
-FunctionEnd
-
-Function UnInstOld
- Push $0
- ReadRegStr $0 ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString"
- IfFileExists "$0" deinst cont
- deinst:
- MessageBox MB_OK|MB_ICONEXCLAMATION "gaim2-otr was already found on your system and will first be uninstalled"
- ; the uninstaller copies itself to temp and execs itself there, so it can delete
- ; everything including its own original file location. To prevent the installer and
- ; uninstaller racing you can't simply ExecWait.
- ; We hide the uninstall because otherwise it gets really confusing window-wise
- ;HideWindow
- ClearErrors
- ExecWait '"$0" _?=$INSTDIR'
- IfErrors 0 cont
- MessageBox MB_OK|MB_ICONEXCLAMATION "Uninstall failed or aborted"
- Abort "Uninstalling of the previous version gave an error. Install aborted."
-
- ;BringToFront
- cont:
- ;MessageBox MB_OK|MB_ICONINFORMATION "No old gaim2-otr found, continuing."
-
-FunctionEnd
-
-Function CopyDLL
-SetOverwrite try
-ClearErrors
-; 3 hours wasted so you guys don't need a reboot!
-; Rename /REBOOTOK "$INSTDIR\gaim2-otr.dll" "$GaimDir\plugins\gaim2-otr.dll"
-IfFileExists "$GaimDir\plugins\gaim2-otr.dll" 0 copy ; remnant or uninstall prev version failed
-Delete "$GaimDir\plugins\gaim2-otr.dll"
-copy:
-ClearErrors
-Rename "$INSTDIR\gaim2-otr.dll" "$GaimDir\plugins\gaim2-otr.dll"
-IfErrors dllbusy
- Return
-dllbusy:
- MessageBox MB_RETRYCANCEL "gaim2-otr.dll is busy. Please close Gaim (including tray icon) and try again" IDCANCEL cancel
- Delete "$GaimDir\plugins\gaim2-otr.dll"
- Goto copy
- Return
-cancel:
- Abort "Installation of gaim2-otr aborted"
-FunctionEnd
diff --git a/po/ChangeLog b/po/ChangeLog
new file mode 100644
index 0000000..e69de29
diff --git a/po/Makefile.mingw b/po/Makefile.mingw
new file mode 100644
index 0000000..c1fbfe8
--- /dev/null
+++ b/po/Makefile.mingw
@@ -0,0 +1,57 @@
+# Makefile.mingw
+#
+# Description: Makefile to generate mo files
+#
+# based on Gaim's po/Makefile.mingw
+#
+
+# Name of the gettext domain
+GETTEXT_PACKAGE = pidgin-otr
+
+# msgfmt command
+GMSGFMT ?= /usr/bin/msgfmt
+
+# Path where the mo files should be installed
+PIDGIN_PO_DIR ?= /usr/share/locale
+INSTALL_PO_DIR = $(DESTDIR)$(PIDGIN_PO_DIR)
+
+.SUFFIXES:
+.SUFFIXES: .po .gmo
+
+##
+## SOURCES, OBJECTS
+##
+
+CATALOGS = $(patsubst %.po,%.gmo,$(wildcard *.po))
+
+##
+## RULES
+##
+
+.po.gmo:
+ rm -f $@ && $(GMSGFMT) --statistics -o $@ $<
+
+##
+## TARGETS
+##
+
+.PHONY: all install clean
+
+all: $(CATALOGS)
+
+install: all
+ mkdir -p $(INSTALL_PO_DIR)
+ @catalogs='$(CATALOGS)'; \
+ for cat in $$catalogs; do \
+ cat=`basename $$cat`; \
+ lang=`echo $$cat | sed 's/\.gmo$$//'`; \
+ dir=$(INSTALL_PO_DIR)/$$lang/LC_MESSAGES; \
+ mkdir -p $$dir; \
+ if test -r $$cat; then \
+ cp $$cat $$dir/$(PACKAGE).mo; \
+ echo "installing $$cat as $$dir/$(GETTEXT_PACKAGE).mo"; \
+ fi; \
+ done
+
+clean:
+ rm -f *.gmo
diff --git a/po/POTFILES.in b/po/POTFILES.in
new file mode 100644
index 0000000..e10e88e
--- /dev/null
+++ b/po/POTFILES.in
@@ -0,0 +1,12 @@
+# List of files that (could) contain strings for translation
+
+dialogs.c
+dialogs.h
+gtk-dialog.c
+gtk-dialog.h
+gtk-ui.c
+gtk-ui.h
+otr-plugin.c
+otr-plugin.h
+ui.c
+ui.h
diff --git a/po/README b/po/README
new file mode 100644
index 0000000..44982cf
--- /dev/null
+++ b/po/README
@@ -0,0 +1,7 @@
+To get the latest list of strings to translate:
+
+intltool-update --pot
+
+To merge the latest list into an existing translation file fr.po:
+
+intltool-update fr
diff --git a/ui.c b/ui.c
index 11dff02..886b2c7 100644
--- a/ui.c
+++ b/ui.c
@@ -1,6 +1,6 @@
/*
* Off-the-Record Messaging plugin for pidgin
- * Copyright (C) 2004-2005 Nikita Borisov and Ian Goldberg
+ * Copyright (C) 2004-2007 Ian Goldberg, Chris Alexander, Nikita Borisov
* <otr at cypherpunks.ca>
*
* This program is free software; you can redistribute it and/or modify
@@ -17,6 +17,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+/* config.h */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
/* system headers */
#include <stdlib.h>
@@ -24,6 +29,11 @@
#include "util.h"
#include "account.h"
+#ifdef ENABLE_NLS
+/* internationalisation header */
+#include <glib/gi18n-lib.h>
+#endif
+
/* libotr headers */
#include <libotr/privkey.h>
#include <libotr/proto.h>
@@ -48,6 +58,22 @@ const OtrgUiUiOps *otrg_ui_get_ui_ops(void)
return ui_ops;
}
+/* Initialize the OTR UI subsystem */
+void otrg_ui_init(void)
+{
+ if (ui_ops != NULL) {
+ ui_ops->init();
+ }
+}
+
+/* Deinitialize the OTR UI subsystem */
+void otrg_ui_cleanup(void)
+{
+ if (ui_ops != NULL) {
+ ui_ops->cleanup();
+ }
+}
+
/* Call this function when the DSA key is updated; it will redraw the
* UI, if visible. */
void otrg_ui_update_fingerprint(void)
@@ -79,11 +105,11 @@ void otrg_ui_connect_connection(ConnContext *context)
account = purple_accounts_find(context->accountname, context->protocol);
if (!account) {
PurplePlugin *p = purple_find_prpl(context->protocol);
- msg = g_strdup_printf("Account %s (%s) could not be found",
+ msg = g_strdup_printf(_("Account %s (%s) could not be found"),
context->accountname,
- (p && p->info->name) ? p->info->name : "Unknown");
+ (p && p->info->name) ? p->info->name : _("Unknown"));
otrg_dialog_notify_error(context->accountname, context->protocol,
- context->username, "Account not found", msg, NULL);
+ context->username, _("Account not found"), msg, NULL);
g_free(msg);
return;
}
@@ -128,17 +154,23 @@ void otrg_ui_config_buddy(PurpleBuddy *buddy)
}
}
-/* Calculate the policy for a particular account / username */
-OtrlPolicy otrg_ui_find_policy(PurpleAccount *account, const char *name)
+/* Load the preferences for a particular account / username */
+void otrg_ui_get_prefs(OtrgUiPrefs *prefsp, PurpleAccount *account,
+ const char *name)
{
/* Check to see if the protocol for this account supports OTR at all. */
const char *proto = purple_account_get_protocol_id(account);
if (!otrg_plugin_proto_supports_otr(proto)) {
- return OTRL_POLICY_NEVER;
+ prefsp->policy = OTRL_POLICY_NEVER;
+ prefsp->avoid_logging_otr = FALSE;
+ return;
}
if (ui_ops != NULL) {
- return ui_ops->find_policy(account, name);
+ ui_ops->get_prefs(prefsp, account, name);
+ return;
}
- return OTRL_POLICY_DEFAULT;
+ /* If we've got no other way to get the prefs, use sensible defaults */
+ prefsp->policy = OTRL_POLICY_DEFAULT;
+ prefsp->avoid_logging_otr = FALSE;
}
diff --git a/ui.h b/ui.h
index c510928..3da58af 100644
--- a/ui.h
+++ b/ui.h
@@ -1,6 +1,6 @@
/*
* Off-the-Record Messaging plugin for pidgin
- * Copyright (C) 2004-2005 Nikita Borisov and Ian Goldberg
+ * Copyright (C) 2004-2007 Ian Goldberg, Chris Alexander, Nikita Borisov
* <otr at cypherpunks.ca>
*
* This program is free software; you can redistribute it and/or modify
@@ -22,14 +22,25 @@
#include <libotr/context.h>
+/* Global and per-buddy preferences */
typedef struct {
+ OtrlPolicy policy;
+ gboolean avoid_logging_otr;
+} OtrgUiPrefs;
+
+typedef struct {
+ void (*init)(void);
+
+ void (*cleanup)(void);
+
void (*update_fingerprint)(void);
void (*update_keylist)(void);
void (*config_buddy)(PurpleBuddy *buddy);
- OtrlPolicy (*find_policy)(PurpleAccount *account, const char *name);
+ void (*get_prefs)(OtrgUiPrefs *prefsp, PurpleAccount *account,
+ const char *name);
} OtrgUiUiOps;
/* Set the UI ops */
@@ -38,6 +49,12 @@ void otrg_ui_set_ui_ops(const OtrgUiUiOps *ops);
/* Get the UI ops */
const OtrgUiUiOps *otrg_ui_get_ui_ops(void);
+/* Initialize the UI subsystem */
+void otrg_ui_init(void);
+
+/* Deinitialize the UI subsystem */
+void otrg_ui_cleanup(void);
+
/* Call this function when the DSA key is updated; it will redraw the
* UI. */
void otrg_ui_update_fingerprint(void);
@@ -57,7 +74,8 @@ void otrg_ui_forget_fingerprint(Fingerprint *fingerprint);
/* Configure OTR for a particular buddy */
void otrg_ui_config_buddy(PurpleBuddy *buddy);
-/* Calculate the policy for a particular account / username */
-OtrlPolicy otrg_ui_find_policy(PurpleAccount *account, const char *name);
+/* Load the preferences for a particular account / username */
+void otrg_ui_get_prefs(OtrgUiPrefs *prefsp, PurpleAccount *account,
+ const char *name);
#endif
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-otr/packages/irssi-plugin-otr.git
More information about the Pkg-otr-team
mailing list