diff -rc bitlbee-1.2.3-orig/Makefile bitlbee-otr/Makefile
*** bitlbee-1.2.3-orig/Makefile	Sat Sep  6 05:33:14 2008
--- bitlbee-otr/Makefile	Tue Dec  2 00:11:21 2008
***************
*** 10,16 ****
  
  # Program variables
  objects = account.o bitlbee.o crypting.o help.o ipc.o irc.o irc_commands.o nick.o query.o root_commands.o set.o storage.o $(STORAGE_OBJS) user.o
! headers = account.h bitlbee.h commands.h conf.h config.h crypting.h help.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h user.h lib/events.h lib/http_client.h lib/ini.h lib/md5.h lib/misc.h lib/proxy.h lib/sha1.h lib/ssl_client.h lib/url.h protocols/nogaim.h
  subdirs = lib protocols
  
  ifeq ($(TARGET),i586-mingw32msvc)
--- 10,16 ----
  
  # Program variables
  objects = account.o bitlbee.o crypting.o help.o ipc.o irc.o irc_commands.o nick.o query.o root_commands.o set.o storage.o $(STORAGE_OBJS) user.o
! headers = account.h bitlbee.h commands.h conf.h config.h crypting.h help.h ipc.h irc.h log.h nick.h otr.h query.h set.h sock.h storage.h user.h lib/events.h lib/http_client.h lib/ini.h lib/md5.h lib/misc.h lib/proxy.h lib/sha1.h lib/ssl_client.h lib/url.h protocols/nogaim.h
  subdirs = lib protocols
  
  ifeq ($(TARGET),i586-mingw32msvc)
***************
*** 19,25 ****
  EFLAGS+=-lsecur32
  OUTFILE=bitlbee.exe
  else
! objects += unix.o conf.o log.o
  OUTFILE=bitlbee
  endif
  
--- 19,25 ----
  EFLAGS+=-lsecur32
  OUTFILE=bitlbee.exe
  else
! objects += unix.o conf.o log.o otr.o
  OUTFILE=bitlbee
  endif
  
diff -rc bitlbee-1.2.3-orig/bitlbee.h bitlbee-otr/bitlbee.h
*** bitlbee-1.2.3-orig/bitlbee.h	Sun Sep  7 05:07:07 2008
--- bitlbee-otr/bitlbee.h	Mon Dec  1 21:38:40 2008
***************
*** 136,141 ****
--- 136,142 ----
  #include "sock.h"
  #include "misc.h"
  #include "proxy.h"
+ #include "otr.h"
  
  typedef struct global {
  	/* In forked mode, child processes store the fd of the IPC socket here. */
***************
*** 147,152 ****
--- 148,154 ----
  	GList *storage; /* The first backend in the list will be used for saving */
  	char *helpfile;
  	int restart;
+ 	OtrlMessageAppOps otr_ops;   /* collects interface functions required by OTR */
  } global_t;
  
  int bitlbee_daemon_init( void );
diff -rc bitlbee-1.2.3-orig/configure bitlbee-otr/configure
*** bitlbee-1.2.3-orig/configure	Sat Sep  6 05:33:13 2008
--- bitlbee-otr/configure	Thu Aug  7 17:58:00 2008
***************
*** 30,35 ****
--- 30,36 ----
  strip=1
  gcov=0
  plugins=1
+ otr=auto
  
  events=glib
  ldap=0
***************
*** 70,75 ****
--- 71,77 ----
  --strip=0/1	Disable/enable binary stripping		$strip
  --gcov=0/1	Disable/enable test coverage reporting	$gcov
  --plugins=0/1	Disable/enable plugins support		$plugins
+ --otr=0/1/auto	Disable/enable OTR encryption support	$otr
  
  --events=...	Event handler (glib, libevent)		$events
  --ssl=...	SSL library to use (gnutls, nss, openssl, bogus, auto)
***************
*** 410,415 ****
--- 412,439 ----
  	echo '#define WITH_PLUGINS' >> config.h
  fi
  
+ otrprefix=""
+ for i in / /usr /usr/local /home/noel/bitlbee; do
+ 	if [ -f ${i}/lib/libotr.a ]; then
+ 		otrprefix=${i}
+ 		break
+ 	fi
+ done
+ if [ "$otr" = "auto" ]; then
+ 	if [ -n "$otrprefix" ]; then
+ 		otr=1
+ 	else
+ 		otr=0
+ 	fi
+ fi
+ if [ "$otr" = 1 ]; then
+ 	echo '#define WITH_OTR' >> config.h
+ 	echo "EFLAGS+=-L${otrprefix}/lib -lotr" >> Makefile.settings
+ 	echo "CFLAGS+=-I${otrprefix}/include" >> Makefile.settings
+ else
+ 	echo '#undef WITH_OTR' >> config.h
+ fi
+ 
  echo
  if [ -z "$BITLBEE_VERSION" -a -d .bzr ] && type bzr > /dev/null 2> /dev/null; then
  	nick=`bzr nick`
***************
*** 535,540 ****
--- 559,570 ----
  	echo '  Binary stripping disabled.'
  fi
  
+ if [ "$otr" = "1" ]; then
+ 	echo '  Off-the-Record (OTR) Messaging enabled.'
+ else
+ 	echo '  Off-the-Record (OTR) Messaging disabled.'
+ fi
+ 
  echo '  Using event handler: '$events
  echo '  Using SSL library: '$ssl
  echo '  Building with these storage backends: '$STORAGES
diff -rc bitlbee-1.2.3-orig/doc/README bitlbee-otr/doc/README
*** bitlbee-1.2.3-orig/doc/README	Sat Sep  6 05:33:13 2008
--- bitlbee-otr/doc/README	Mon Dec  1 22:06:54 2008
***************
*** 67,72 ****
--- 67,76 ----
  BitlBee's only real dependency is GLib. This is available on virtually every
  platform. Any recent version of GLib (2.4 or higher) will work.
  
+ Off-the-Record encryption support will be included by default if the
+ configure script finds libotr in one of the usual places. You can pass
+ --otr=1 or --otr=0 to force it on or off, respectively.
+ 
  These days, MSN Messenger clients have to connect to the MS Passport servers
  through HTTPS. BitlBee can use several SSL libraries for this: GnuTLS, NSS
  (which comes with Mozilla) and OpenSSL. OpenSSL is not GPL-compatible in some
diff -rc bitlbee-1.2.3-orig/irc.c bitlbee-otr/irc.c
*** bitlbee-1.2.3-orig/irc.c	Sat Sep  6 08:17:52 2008
--- bitlbee-otr/irc.c	Mon Dec  1 23:52:03 2008
***************
*** 149,160 ****
--- 149,163 ----
  	s = set_add( &irc->set, "buddy_sendbuffer", "false", set_eval_bool, irc );
  	s = set_add( &irc->set, "buddy_sendbuffer_delay", "200", set_eval_int, irc );
  	s = set_add( &irc->set, "charset", "utf-8", set_eval_charset, irc );
+ 	s = set_add( &irc->set, "color_encrypted", "true", set_eval_bool, irc );
  	s = set_add( &irc->set, "debug", "false", set_eval_bool, irc );
  	s = set_add( &irc->set, "default_target", "root", NULL, irc );
  	s = set_add( &irc->set, "display_namechanges", "false", set_eval_bool, irc );
  	s = set_add( &irc->set, "handle_unknown", "root", NULL, irc );
  	s = set_add( &irc->set, "lcnicks", "true", set_eval_bool, irc );
  	s = set_add( &irc->set, "ops", "both", set_eval_ops, irc );
+ 	s = set_add( &irc->set, "otr_ops", "true", set_eval_bool, irc );
+ 	s = set_add( &irc->set, "otr_policy", "opportunistic", set_eval_otr_policy, irc );
  	s = set_add( &irc->set, "password", NULL, set_eval_password, irc );
  	s->flags |= SET_NULL_OK;
  	s = set_add( &irc->set, "private", "true", set_eval_bool, irc );
***************
*** 167,172 ****
--- 170,177 ----
  	s = set_add( &irc->set, "typing_notice", "false", set_eval_bool, irc );
  	
  	conf_loaddefaults( irc );
+ 
+ 	irc->otr = otr_new();
  	
  	/* Evaluator sets the iconv/oconv structures. */
  	set_eval_charset( set_find( &irc->set, "charset" ), set_getstr( &irc->set, "charset" ) );
***************
*** 320,325 ****
--- 325,332 ----
  	
  	g_free( irc->last_target );
  	
+ 	otr_free(irc->otr);
+ 	
  	g_free( irc );
  	
  	if( global.conf->runmode == RUNMODE_INETD ||
***************
*** 715,723 ****
  			if( u->ic && !u->away && set_getbool( &irc->set, "away_devoice" ) )
  				strcat( namelist, "+" );
  			else if( ( strcmp( u->nick, irc->mynick ) == 0 && ( strcmp( ops, "root" ) == 0 || strcmp( ops, "both" ) == 0 ) ) ||
! 			         ( strcmp( u->nick, irc->nick ) == 0 && ( strcmp( ops, "user" ) == 0 || strcmp( ops, "both" ) == 0 ) ) )
! 				strcat( namelist, "@" );
! 			
  			strcat( namelist, u->nick );
  			strcat( namelist, " " );
  		}
--- 722,732 ----
  			if( u->ic && !u->away && set_getbool( &irc->set, "away_devoice" ) )
  				strcat( namelist, "+" );
  			else if( ( strcmp( u->nick, irc->mynick ) == 0 && ( strcmp( ops, "root" ) == 0 || strcmp( ops, "both" ) == 0 ) ) ||
! 			         ( strcmp( u->nick, irc->nick ) == 0 && ( strcmp( ops, "user" ) == 0 || strcmp( ops, "both" ) == 0 ) ) ||
! 				 ( u->encrypted > 1 && set_getbool( &irc->set, "otr_ops" ) ) )
! 			  strcat( namelist, "@" );
! 			else if ( u->encrypted > 1 && set_getbool( &irc->set, "otr_ops" ) )
! 			  strcat ( namelist, "%" );
  			strcat( namelist, u->nick );
  			strcat( namelist, " " );
  		}
***************
*** 739,744 ****
--- 748,757 ----
  				*namelist = 0;
  			}
  			
+ 			if( u->encrypted > 1 && set_getbool( &irc->set, "otr_ops" ) )
+ 			  strcat( namelist, "@" );
+ 			else if ( u->encrypted > 1 && set_getbool( &irc->set, "otr_ops" ) )
+ 			  strcat ( namelist, "%" );
  			strcat( namelist, u->nick );
  			strcat( namelist, " " );
  		}
***************
*** 780,786 ****
  	irc_reply( irc,   2, ":Host %s is running BitlBee " BITLBEE_VERSION " " ARCH "/" CPU ".", irc->myhost );
  	irc_reply( irc,   3, ":%s", IRCD_INFO );
  	irc_reply( irc,   4, "%s %s %s %s", irc->myhost, BITLBEE_VERSION, UMODES UMODES_PRIV, CMODES );
! 	irc_reply( irc,   5, "PREFIX=(ov)@+ CHANTYPES=#& CHANMODES=,,,%s NICKLEN=%d NETWORK=BitlBee CASEMAPPING=rfc1459 MAXTARGETS=1 WATCH=128 :are supported by this server", CMODES, MAX_NICK_LENGTH - 1 );
  	irc_motd( irc );
  	irc->umode[0] = '\0';
  	irc_umode_set( irc, "+" UMODE, 1 );
--- 793,799 ----
  	irc_reply( irc,   2, ":Host %s is running BitlBee " BITLBEE_VERSION " " ARCH "/" CPU ".", irc->myhost );
  	irc_reply( irc,   3, ":%s", IRCD_INFO );
  	irc_reply( irc,   4, "%s %s %s %s", irc->myhost, BITLBEE_VERSION, UMODES UMODES_PRIV, CMODES );
! 	irc_reply( irc,   5, "PREFIX=(ohv)@%%+ CHANTYPES=#& CHANMODES=,,,%s NICKLEN=%d NETWORK=BitlBee CASEMAPPING=rfc1459 MAXTARGETS=1 WATCH=128 :are supported by this server", CMODES, MAX_NICK_LENGTH - 1 );
  	irc_motd( irc );
  	irc->umode[0] = '\0';
  	irc_umode_set( irc, "+" UMODE, 1 );
diff -rc bitlbee-1.2.3-orig/irc.h bitlbee-otr/irc.h
*** bitlbee-1.2.3-orig/irc.h	Sat Sep  6 05:33:14 2008
--- bitlbee-otr/irc.h	Thu Aug  7 17:11:13 2008
***************
*** 26,33 ****
  #ifndef _IRC_H
  #define _IRC_H
  
  #define IRC_MAX_LINE 512
! #define IRC_MAX_ARGS 8
  
  #define IRC_LOGIN_TIMEOUT 60
  #define IRC_PING_STRING "PinglBee"
--- 26,35 ----
  #ifndef _IRC_H
  #define _IRC_H
  
+ #include "otr.h"
+ 
  #define IRC_MAX_LINE 512
! #define IRC_MAX_ARGS 16
  
  #define IRC_LOGIN_TIMEOUT 60
  #define IRC_PING_STRING "PinglBee"
***************
*** 96,101 ****
--- 98,105 ----
  	gint r_watch_source_id;
  	gint w_watch_source_id;
  	gint ping_source_id;
+ 	
+ 	otr_t *otr;            /* OTR state and book keeping */
  } irc_t;
  
  #include "user.h"
diff -rc bitlbee-1.2.3-orig/lib/misc.c bitlbee-otr/lib/misc.c
*** bitlbee-1.2.3-orig/lib/misc.c	Sat Sep  6 05:33:13 2008
--- bitlbee-otr/lib/misc.c	Thu Aug  7 17:11:13 2008
***************
*** 87,92 ****
--- 87,93 ----
  	{ "lt",     "<" },
  	{ "gt",     ">" },
  	{ "amp",    "&" },
+ 	{ "apos",   "'" },
  	{ "quot",   "\"" },
  	{ "aacute", "á" },
  	{ "eacute", "é" },
***************
*** 118,123 ****
--- 119,125 ----
  	char *out = g_malloc( strlen( in ) + 1 );
  	char *s = out, *cs;
  	int i, matched;
+ 	int taglen;
  	
  	memset( out, 0, strlen( in ) + 1 );
  	
***************
*** 134,142 ****
  			while( *in && *in != '>' )
  				in ++;
  			
  			if( *in )
  			{
! 				if( g_strncasecmp( cs+1, "br", 2) == 0 )
  					*(s++) = '\n';
  				in ++;
  			}
--- 136,153 ----
  			while( *in && *in != '>' )
  				in ++;
  			
+ 			taglen = in-cs-1;   /* not <0 because the above loop runs at least once */
  			if( *in )
  			{
! 				if( g_strncasecmp( cs+1, "b", taglen) == 0 )
! 					*(s++) = '\x02';
! 				else if( g_strncasecmp( cs+1, "/b", taglen) == 0 )
! 					*(s++) = '\x02';
! 				else if( g_strncasecmp( cs+1, "i", taglen) == 0 )
! 					*(s++) = '\x1f';
! 				else if( g_strncasecmp( cs+1, "/i", taglen) == 0 )
! 					*(s++) = '\x1f';
! 				else if( g_strncasecmp( cs+1, "br", 2) == 0 )
  					*(s++) = '\n';
  				in ++;
  			}
diff -rc bitlbee-1.2.3-orig/lib/ssl_bogus.c bitlbee-otr/lib/ssl_bogus.c
*** bitlbee-1.2.3-orig/lib/ssl_bogus.c	Sat Sep  6 05:33:13 2008
--- bitlbee-otr/lib/ssl_bogus.c	Thu Aug  7 17:11:13 2008
***************
*** 27,32 ****
--- 27,36 ----
  
  int ssl_errno;
  
+ void ssl_init( void )
+ {
+ }
+ 
  void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )
  {
  	return( NULL );
diff -rc bitlbee-1.2.3-orig/lib/ssl_client.h bitlbee-otr/lib/ssl_client.h
*** bitlbee-1.2.3-orig/lib/ssl_client.h	Sat Sep  6 05:33:13 2008
--- bitlbee-otr/lib/ssl_client.h	Thu Aug  7 17:11:13 2008
***************
*** 46,51 ****
--- 46,54 ----
  typedef gboolean (*ssl_input_function)(gpointer, void*, b_input_condition);
  
  
+ /* Perform any global initialization the SSL library might need. */
+ G_MODULE_EXPORT void ssl_init( void );
+ 
  /* Connect to host:port, call the given function when the connection is
     ready to be used for SSL traffic. This is all done asynchronously, no
     blocking I/O! (Except for the DNS lookups, for now...) */
diff -rc bitlbee-1.2.3-orig/lib/ssl_gnutls.c bitlbee-otr/lib/ssl_gnutls.c
*** bitlbee-1.2.3-orig/lib/ssl_gnutls.c	Sat Sep  6 05:33:13 2008
--- bitlbee-otr/lib/ssl_gnutls.c	Thu Aug  7 17:11:13 2008
***************
*** 60,65 ****
--- 60,72 ----
  static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond );
  
  
+ void ssl_init( void )
+ {
+ 	gnutls_global_init();
+ 	initialized = TRUE;
+ 	atexit( gnutls_global_deinit );
+ }
+ 
  void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )
  {
  	struct scd *conn = g_new0( struct scd, 1 );
***************
*** 121,129 ****
  	
  	if( !initialized )
  	{
! 		gnutls_global_init();
! 		initialized = TRUE;
! 		atexit( gnutls_global_deinit );
  	}
  	
  	gnutls_certificate_allocate_credentials( &conn->xcred );
--- 128,134 ----
  	
  	if( !initialized )
  	{
! 		ssl_init();
  	}
  	
  	gnutls_certificate_allocate_credentials( &conn->xcred );
diff -rc bitlbee-1.2.3-orig/lib/ssl_nss.c bitlbee-otr/lib/ssl_nss.c
*** bitlbee-1.2.3-orig/lib/ssl_nss.c	Sat Sep  6 05:33:13 2008
--- bitlbee-otr/lib/ssl_nss.c	Thu Aug  7 17:11:13 2008
***************
*** 90,95 ****
--- 90,103 ----
  }
  
  
+ void ssl_init( void )
+ {
+ 	PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ 	NSS_NoDB_Init(NULL);
+ 	NSS_SetDomesticPolicy();
+ 	initialized = TRUE;
+ }
+ 
  void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )
  {
  	struct scd *conn = g_new0( struct scd, 1 );
***************
*** 106,114 ****
  	
  	if( !initialized )
  	{
! 		PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
! 		NSS_NoDB_Init(NULL);
! 		NSS_SetDomesticPolicy();
  	}
  
  	
--- 114,120 ----
  	
  	if( !initialized )
  	{
! 		ssl_init();
  	}
  
  	
diff -rc bitlbee-1.2.3-orig/lib/ssl_openssl.c bitlbee-otr/lib/ssl_openssl.c
*** bitlbee-1.2.3-orig/lib/ssl_openssl.c	Sat Sep  6 05:33:13 2008
--- bitlbee-otr/lib/ssl_openssl.c	Thu Aug  7 17:11:13 2008
***************
*** 56,61 ****
--- 56,67 ----
  static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond );
  
  
+ void ssl_init( void )
+ {
+ 	initialized = TRUE;
+ 	SSLeay_add_ssl_algorithms();
+ }
+ 
  void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )
  {
  	struct scd *conn = g_new0( struct scd, 1 );
***************
*** 114,121 ****
  	
  	if( !initialized )
  	{
! 		initialized = TRUE;
! 		SSLeay_add_ssl_algorithms();
  	}
  	
  	meth = TLSv1_client_method();
--- 120,126 ----
  	
  	if( !initialized )
  	{
! 		ssl_init();
  	}
  	
  	meth = TLSv1_client_method();
diff -rc bitlbee-1.2.3-orig/log.c bitlbee-otr/log.c
*** bitlbee-1.2.3-orig/log.c	Sat Sep  6 05:33:13 2008
--- bitlbee-otr/log.c	Thu Aug  7 17:11:13 2008
***************
*** 29,38 ****
  
  static log_t logoutput;
  
! static void log_null(int level, char *logmessage);
! static void log_irc(int level, char *logmessage);
! static void log_syslog(int level, char *logmessage);
! static void log_console(int level, char *logmessage);
  
  void log_init(void) {
  	openlog("bitlbee", LOG_PID, LOG_DAEMON);	
--- 29,38 ----
  
  static log_t logoutput;
  
! static void log_null(int level, const char *logmessage);
! static void log_irc(int level, const char *logmessage);
! static void log_syslog(int level, const char *logmessage);
! static void log_console(int level, const char *logmessage);
  
  void log_init(void) {
  	openlog("bitlbee", LOG_PID, LOG_DAEMON);	
***************
*** 96,102 ****
  
  }
  
! void log_message(int level, char *message, ... ) {
  
  	va_list ap;
  	char *msgstring;
--- 96,102 ----
  
  }
  
! void log_message(int level, const char *message, ... ) {
  
  	va_list ap;
  	char *msgstring;
***************
*** 121,137 ****
  	return;
  }
  
! void log_error(char *functionname) {
  	log_message(LOGLVL_ERROR, "%s: %s", functionname, strerror(errno));
  	
  	return;
  }
  
! static void log_null(int level, char *message) {
  	return;
  }
  
! static void log_irc(int level, char *message) {
  	if(level == LOGLVL_ERROR)
  		irc_write_all(1, "ERROR :Error: %s", message);
  	if(level == LOGLVL_WARNING)
--- 121,137 ----
  	return;
  }
  
! void log_error(const char *functionname) {
  	log_message(LOGLVL_ERROR, "%s: %s", functionname, strerror(errno));
  	
  	return;
  }
  
! static void log_null(int level, const char *message) {
  	return;
  }
  
! static void log_irc(int level, const char *message) {
  	if(level == LOGLVL_ERROR)
  		irc_write_all(1, "ERROR :Error: %s", message);
  	if(level == LOGLVL_WARNING)
***************
*** 146,152 ****
  	return;
  }
  
! static void log_syslog(int level, char *message) {
  	if(level == LOGLVL_ERROR)
  		syslog(LOG_ERR, "%s", message);
  	if(level == LOGLVL_WARNING)
--- 146,152 ----
  	return;
  }
  
! static void log_syslog(int level, const char *message) {
  	if(level == LOGLVL_ERROR)
  		syslog(LOG_ERR, "%s", message);
  	if(level == LOGLVL_WARNING)
***************
*** 160,166 ****
  	return;
  }
  
! static void log_console(int level, char *message) {
  	if(level == LOGLVL_ERROR)
  		fprintf(stderr, "Error: %s\n", message);
  	if(level == LOGLVL_WARNING)
--- 160,166 ----
  	return;
  }
  
! static void log_console(int level, const char *message) {
  	if(level == LOGLVL_ERROR)
  		fprintf(stderr, "Error: %s\n", message);
  	if(level == LOGLVL_WARNING)
diff -rc bitlbee-1.2.3-orig/log.h bitlbee-otr/log.h
*** bitlbee-1.2.3-orig/log.h	Sat Sep  6 05:33:13 2008
--- bitlbee-otr/log.h	Thu Aug  7 17:11:13 2008
***************
*** 43,59 ****
  } logoutput_t;
  
  typedef struct log_t {
! 	void (*error)(int level, char *logmessage);
! 	void (*warning)(int level, char *logmessage); 
! 	void (*informational)(int level, char *logmessage);
  #ifdef DEBUG
! 	void (*debug)(int level, char *logmessage);
  #endif
  } log_t;
  
  void log_init(void);
  void log_link(int level, int output);
! void log_message(int level, char *message, ...) G_GNUC_PRINTF( 2, 3 );
! void log_error(char *functionname);
  
  #endif
--- 43,59 ----
  } logoutput_t;
  
  typedef struct log_t {
! 	void (*error)(int level, const char *logmessage);
! 	void (*warning)(int level, const char *logmessage); 
! 	void (*informational)(int level, const char *logmessage);
  #ifdef DEBUG
! 	void (*debug)(int level, const char *logmessage);
  #endif
  } log_t;
  
  void log_init(void);
  void log_link(int level, int output);
! void log_message(int level, const char *message, ...) G_GNUC_PRINTF( 2, 3 );
! void log_error(const char *functionname);
  
  #endif
diff -rc bitlbee-1.2.3-orig/protocols/jabber/jabber.c bitlbee-otr/protocols/jabber/jabber.c
*** bitlbee-1.2.3-orig/protocols/jabber/jabber.c	Sat Sep  6 05:33:13 2008
--- bitlbee-otr/protocols/jabber/jabber.c	Mon Dec  1 21:57:59 2008
***************
*** 527,532 ****
--- 527,533 ----
  	struct prpl *ret = g_new0( struct prpl, 1 );
  	
  	ret->name = "jabber";
+     ret->mms = 0;                        /* no limit */
  	ret->login = jabber_login;
  	ret->init = jabber_init;
  	ret->logout = jabber_logout;
diff -rc bitlbee-1.2.3-orig/protocols/msn/msn.c bitlbee-otr/protocols/msn/msn.c
*** bitlbee-1.2.3-orig/protocols/msn/msn.c	Sat Sep  6 05:33:13 2008
--- bitlbee-otr/protocols/msn/msn.c	Mon Dec  1 22:00:04 2008
***************
*** 316,321 ****
--- 316,322 ----
  	struct prpl *ret = g_new0(struct prpl, 1);
  	
  	ret->name = "msn";
+     ret->mms = 1409;         /* this guess taken from libotr UPGRADING file */
  	ret->login = msn_login;
  	ret->init = msn_init;
  	ret->logout = msn_logout;
diff -rc bitlbee-1.2.3-orig/protocols/nogaim.c bitlbee-otr/protocols/nogaim.c
*** bitlbee-1.2.3-orig/protocols/nogaim.c	Sat Sep  6 05:33:14 2008
--- bitlbee-otr/protocols/nogaim.c	Tue Dec  2 00:04:17 2008
***************
*** 627,632 ****
--- 627,641 ----
  		}
  		irc_write( ic->irc, ":%s MODE %s %cv %s", from, ic->irc->channel,
  		                                          u->away?'-':'+', u->nick );
+ 		if( set_getbool( &ic->irc->set, "otr_ops" ) )
+ 		{
+ 			if( u->encrypted > 1 )
+ 				irc_write( ic->irc, ":%s MODE %s %co %s", from, ic->irc->channel,
+ 									  u->away?'-':'+', u->nick );
+ 			else if( u->encrypted )
+ 				irc_write( ic->irc, ":%s MODE %s %ch %s", from, ic->irc->channel,
+ 									  u->away?'-':'+', u->nick );
+ 		}
  		g_free( from );
  	}
  }
***************
*** 636,644 ****
  	irc_t *irc = ic->irc;
  	char *wrapped;
  	user_t *u;
! 	
  	u = user_findhandle( ic, handle );
- 	
  	if( !u )
  	{
  		char *h = set_getstr( &irc->set, "handle_unknown" );
--- 645,659 ----
  	irc_t *irc = ic->irc;
  	char *wrapped;
  	user_t *u;
! 
! 	/* pass the message through OTR */
! 	msg = otr_handle_message(ic, handle, msg);
! 	if(!msg) {
! 		/* this was an internal OTR protocol message */
! 		return;
! 	}
! 
  	u = user_findhandle( ic, handle );
  	if( !u )
  	{
  		char *h = set_getstr( &irc->set, "handle_unknown" );
***************
*** 648,653 ****
--- 663,669 ----
  			if( set_getbool( &irc->set, "debug" ) )
  				imcb_log( ic, "Ignoring message from unknown handle %s", handle );
  			
+ 			g_free(msg);
  			return;
  		}
  		else if( g_strncasecmp( h, "add", 3 ) == 0 )
***************
*** 680,685 ****
--- 696,702 ----
  	wrapped = word_wrap( msg, 425 );
  	irc_msgfrom( irc, u->nick, wrapped );
  	g_free( wrapped );
+ 	g_free( msg );
  }
  
  void imcb_buddy_typing( struct im_connection *ic, char *handle, uint32_t flags )
***************
*** 972,977 ****
--- 989,995 ----
  		for( i = 0; i < count; v[i++] = 'v' ); v[i] = 0;
  		irc_write( irc, ":%s MODE %s %c%s%s", irc->myhost,
  		                                            irc->channel, pm, v, list );
+ 		/* FIXME: do the same thing for op and halfop */
  	}
  	
  	return value;
***************
*** 993,1002 ****
  		buf = escape_html( msg );
  		msg = buf;
  	}
  	
! 	st = ic->acc->prpl->buddy_msg( ic, handle, msg, flags );
! 	g_free( buf );
! 	
  	return st;
  }
  
--- 1011,1021 ----
  		buf = escape_html( msg );
  		msg = buf;
  	}
+ 
+ 	/* if compiled without otr support, this just calls the prpl buddy_msg */
+ 	st = otr_send_message(ic, handle, msg, flags);
  	
! 	g_free(buf);
  	return st;
  }
  
diff -rc bitlbee-1.2.3-orig/protocols/nogaim.h bitlbee-otr/protocols/nogaim.h
*** bitlbee-1.2.3-orig/protocols/nogaim.h	Sat Sep  6 05:33:13 2008
--- bitlbee-otr/protocols/nogaim.h	Tue Dec  2 00:04:40 2008
***************
*** 131,136 ****
--- 131,140 ----
  	/* You should set this to the name of your protocol.
  	 * - The user sees this name ie. when imcb_log() is used. */
  	const char *name;
+     /* Maximum Message Size of this protocol.
+      * - Introduced for OTR, in order to fragment large protocol messages.
+      * - 0 means "unlimited". */
+     unsigned int mms;
  
  	/* Added this one to be able to add per-account settings, don't think
  	 * it should be used for anything else. You are supposed to use the
diff -rc bitlbee-1.2.3-orig/protocols/oscar/oscar.c bitlbee-otr/protocols/oscar/oscar.c
*** bitlbee-1.2.3-orig/protocols/oscar/oscar.c	Sat Sep  6 05:33:13 2008
--- bitlbee-otr/protocols/oscar/oscar.c	Thu Aug  7 17:11:13 2008
***************
*** 2642,2647 ****
--- 2642,2648 ----
  {
  	struct prpl *ret = g_new0(struct prpl, 1);
  	ret->name = "oscar";
+     ret->mms = 2343;       /* this guess taken from libotr UPGRADING file */
  	ret->away_states = oscar_away_states;
  	ret->init = oscar_init;
  	ret->login = oscar_login;
diff -rc bitlbee-1.2.3-orig/protocols/yahoo/yahoo.c bitlbee-otr/protocols/yahoo/yahoo.c
*** bitlbee-1.2.3-orig/protocols/yahoo/yahoo.c	Sat Sep  6 05:33:13 2008
--- bitlbee-otr/protocols/yahoo/yahoo.c	Thu Aug  7 17:11:13 2008
***************
*** 350,355 ****
--- 350,356 ----
  {
  	struct prpl *ret = g_new0(struct prpl, 1);
  	ret->name = "yahoo";
+     ret->mms = 832;           /* this guess taken from libotr UPGRADING file */
  	ret->init = byahoo_init;
  	
  	ret->login = byahoo_login;
***************
*** 664,669 ****
--- 665,673 ----
  	struct im_connection *ic = byahoo_get_ic_by_id( id );
  	
  	imcb_error( ic, "%s", err );
+ 	
+ 	if( fatal )
+ 		imc_logout( ic, TRUE );
  }
  
  /* TODO: Clear up the mess of inp and d structures */
diff -rc bitlbee-1.2.3-orig/query.c bitlbee-otr/query.c
*** bitlbee-1.2.3-orig/query.c	Sat Sep  6 05:33:13 2008
--- bitlbee-otr/query.c	Thu Aug  7 17:11:13 2008
***************
*** 102,107 ****
--- 102,110 ----
  	query_t *q, *n, *def;
  	int count = 0;
  	
+ 	if(!ic)
+ 		return;
+ 	
  	q = irc->queries;
  	def = query_default( irc );
  	
***************
*** 144,150 ****
  			imcb_log( q->ic, "Accepted: %s", q->question );
  		else
  			irc_usermsg( irc, "Accepted: %s", q->question );
! 		q->yes( q->data );
  	}
  	else
  	{
--- 147,154 ----
  			imcb_log( q->ic, "Accepted: %s", q->question );
  		else
  			irc_usermsg( irc, "Accepted: %s", q->question );
! 		if( q->yes )
! 			q->yes( q->data );
  	}
  	else
  	{
***************
*** 152,158 ****
  			imcb_log( q->ic, "Rejected: %s", q->question );
  		else
  			irc_usermsg( irc, "Rejected: %s", q->question );
! 		q->no( q->data );
  	}
  	q->data = NULL;
  	
--- 156,163 ----
  			imcb_log( q->ic, "Rejected: %s", q->question );
  		else
  			irc_usermsg( irc, "Rejected: %s", q->question );
! 		if( q->no )
! 			q->no( q->data );
  	}
  	q->data = NULL;
  	
diff -rc bitlbee-1.2.3-orig/root_commands.c bitlbee-otr/root_commands.c
*** bitlbee-1.2.3-orig/root_commands.c	Sat Sep  6 06:10:19 2008
--- bitlbee-otr/root_commands.c	Mon Dec  1 21:53:05 2008
***************
*** 28,33 ****
--- 28,34 ----
  #include "crypting.h"
  #include "bitlbee.h"
  #include "help.h"
+ #include "otr.h"
  
  #include <string.h>
  
***************
*** 1096,1100 ****
--- 1097,1102 ----
  	{ "nick",           1, cmd_nick,           0 },
  	{ "qlist",          0, cmd_qlist,          0 },
  	{ "join_chat",      2, cmd_join_chat,      0 },
+ 	{ "otr",            1, cmd_otr,            0 },	
  	{ NULL }
  };
diff -rc bitlbee-1.2.3-orig/set.c bitlbee-otr/set.c
*** bitlbee-1.2.3-orig/set.c	Sat Sep  6 05:33:13 2008
--- bitlbee-otr/set.c	Mon Dec  1 23:51:44 2008
***************
*** 245,247 ****
--- 245,261 ----
  	
  	return value;
  }
+ 
+ /* possible values: never, opportunistic, manual, always */
+ char *set_eval_otr_policy( set_t *set, char *value )
+ {
+ 	if ( !strcmp(value, "never") )
+ 		return value;
+ 	if ( !strcmp(value, "opportunistic") )
+ 		return value;
+ 	if ( !strcmp(value, "manual") )
+ 		return value;
+ 	if ( !strcmp(value, "always") )
+ 		return value;
+ 	return SET_INVALID;
+ }
diff -rc bitlbee-1.2.3-orig/set.h bitlbee-otr/set.h
*** bitlbee-1.2.3-orig/set.h	Sat Sep  6 05:33:13 2008
--- bitlbee-otr/set.h	Mon Dec  1 23:52:49 2008
***************
*** 100,104 ****
--- 100,105 ----
  /* Some not very generic evaluators that really shouldn't be here... */
  char *set_eval_to_char( set_t *set, char *value );
  char *set_eval_ops( set_t *set, char *value );
+ char *set_eval_otr_policy( set_t *set, char *value );
  
  #endif /* __SET_H__ */
diff -rc bitlbee-1.2.3-orig/storage.c bitlbee-otr/storage.c
*** bitlbee-1.2.3-orig/storage.c	Sat Sep  6 15:35:56 2008
--- bitlbee-otr/storage.c	Mon Dec  1 21:47:36 2008
***************
*** 28,33 ****
--- 28,34 ----
  #define BITLBEE_CORE
  #include "bitlbee.h"
  #include "crypting.h"
+ #include "otr.h"
  
  extern storage_t storage_text;
  extern storage_t storage_xml;
***************
*** 139,144 ****
--- 140,147 ----
  		return STORAGE_NO_SUCH_USER;
  	}
  	
+ 	otr_save(irc);
+ 	
  	st = ((storage_t *)global.storage->data)->save(irc, overwrite);
  	
  	if (password != NULL) {
***************
*** 181,188 ****
  	/* First, try to rename in the current write backend, assuming onick 
  	 * is stored there */
  	status = primary_storage->rename(onick, nnick, password);
! 	if (status != STORAGE_NO_SUCH_USER)
  		return status;
  
  	/* Try to load from a migration backend and save to the current backend. 
  	 * Explicitly remove the account from the migration backend as otherwise 
--- 184,193 ----
  	/* First, try to rename in the current write backend, assuming onick 
  	 * is stored there */
  	status = primary_storage->rename(onick, nnick, password);
! 	if (status != STORAGE_NO_SUCH_USER) {
! 		otr_rename(onick, nnick);
  		return status;
+ 	}
  
  	/* Try to load from a migration backend and save to the current backend. 
  	 * Explicitly remove the account from the migration backend as otherwise 
***************
*** 206,211 ****
--- 211,217 ----
  	irc_free(irc);
  
  	storage_remove(onick, password);
+ 	otr_rename(onick, nnick);
  
  	return STORAGE_OK;
  }
diff -rc bitlbee-1.2.3-orig/unix.c bitlbee-otr/unix.c
*** bitlbee-1.2.3-orig/unix.c	Sat Sep  6 05:33:13 2008
--- bitlbee-otr/unix.c	Thu Aug  7 17:11:13 2008
***************
*** 26,34 ****
--- 26,36 ----
  #include "bitlbee.h"
  #include "commands.h"
  #include "crypting.h"
+ #include "otr.h"
  #include "protocols/nogaim.h"
  #include "help.h"
  #include "ipc.h"
+ #include "lib/ssl_client.h"
  #include <signal.h>
  #include <unistd.h>
  #include <sys/time.h>
***************
*** 53,58 ****
--- 55,67 ----
  	
  	b_main_init();
  	nogaim_init();
+ 	/* Ugly Note: libotr and gnutls both use libgcrypt. libgcrypt
+ 	   has a process-global config state whose initialization happpens
+ 	   twice if libotr and gnutls are used together. libotr installs custom
+ 	   memory management functions for libgcrypt while our gnutls module
+ 	   uses the defaults. Therefore we initialize OTR after SSL. *sigh* */
+ 	ssl_init();
+ 	otr_init();
  	
  	srand( time( NULL ) ^ getpid() );
  	global.helpfile = g_strdup( HELP_FILE );
diff -rc bitlbee-1.2.3-orig/user.c bitlbee-otr/user.c
*** bitlbee-1.2.3-orig/user.c	Sat Sep  6 05:33:13 2008
--- bitlbee-otr/user.c	Mon Dec  1 22:15:04 2008
***************
*** 140,146 ****
  		return( NULL );
  }
  
! user_t *user_findhandle( struct im_connection *ic, char *handle )
  {
  	user_t *u;
  	char *nick;
--- 140,146 ----
  		return( NULL );
  }
  
! user_t *user_findhandle( struct im_connection *ic, const char *handle )
  {
  	user_t *u;
  	char *nick;
diff -rc bitlbee-1.2.3-orig/user.h bitlbee-otr/user.h
*** bitlbee-1.2.3-orig/user.h	Sat Sep  6 05:33:13 2008
--- bitlbee-otr/user.h	Mon Dec  1 22:15:11 2008
***************
*** 36,41 ****
--- 36,42 ----
  	
  	char is_private;
  	char online;
+ 	char encrypted;
  	
  	char *handle;
  	char *group;
***************
*** 55,61 ****
  user_t *user_add( struct irc *irc, char *nick );
  int user_del( irc_t *irc, char *nick );
  G_MODULE_EXPORT user_t *user_find( irc_t *irc, char *nick );
! G_MODULE_EXPORT user_t *user_findhandle( struct im_connection *ic, char *handle );
  void user_rename( irc_t *irc, char *oldnick, char *newnick );
  
  #endif /* __USER_H__ */
--- 56,62 ----
  user_t *user_add( struct irc *irc, char *nick );
  int user_del( irc_t *irc, char *nick );
  G_MODULE_EXPORT user_t *user_find( irc_t *irc, char *nick );
! G_MODULE_EXPORT user_t *user_findhandle( struct im_connection *ic, const char *handle );
  void user_rename( irc_t *irc, char *oldnick, char *newnick );
  
  #endif /* __USER_H__ */
