Index: irc.h
===================================================================
--- irc.h	(revision 0c85c08d210e16bb10dc283b4a1478ce53c0c1b1)
+++ irc.h	(revision 934db064a58ebec2edea83df4fa07e2c83220344)
@@ -230,10 +230,14 @@
 	void (*irc_free)( irc_t *irc );
 	
+	/* Problem with the following two functions is ordering if multiple
+	   plugins are handling them. Let's keep fixing that problem for
+	   whenever it becomes important. */
+	
 	/* Called by bee_irc_user_privmsg_cb(). Return NULL if you want to
 	   abort sending the msg. */
-	char* (*filter_msg_out)( irc_user_t *iu, const char *msg, int flags );
+	char* (*filter_msg_out)( irc_user_t *iu, char *msg, int flags );
 	/* Called by bee_irc_user_msg(). Return NULL if you swallowed the
 	   message and don't want anything to go to the user. */
-	char* (*filter_msg_in)( irc_user_t *iu, const char *msg, int flags );
+	char* (*filter_msg_in)( irc_user_t *iu, char *msg, int flags );
 } irc_plugin_t;
 
Index: irc_im.c
===================================================================
--- irc_im.c	(revision 0c85c08d210e16bb10dc283b4a1478ce53c0c1b1)
+++ irc_im.c	(revision 934db064a58ebec2edea83df4fa07e2c83220344)
@@ -192,5 +192,5 @@
 }
 
-static gboolean bee_irc_user_msg( bee_t *bee, bee_user_t *bu, const char *msg, time_t sent_at )
+static gboolean bee_irc_user_msg( bee_t *bee, bee_user_t *bu, const char *msg_, time_t sent_at )
 {
 	irc_t *irc = bee->ui_data;
@@ -199,4 +199,6 @@
 	char *wrapped, *ts = NULL;
 	irc_channel_t *ic = NULL;
+	char *msg = g_strdup( msg_ );
+	GSList *l;
 	
 	if( sent_at > 0 && set_getbool( &irc->b->set, "display_timestamps" ) )
@@ -224,4 +226,33 @@
 	}
 	
+	for( l = irc_plugins; l; l = l->next )
+	{
+		irc_plugin_t *p = l->data;
+		if( p->filter_msg_in )
+		{
+			char *s = p->filter_msg_in( iu, msg, 0 );
+			if( s )
+			{
+				if( s != msg )
+					g_free( msg );
+				msg = s;
+			}
+			else
+			{
+				/* Modules can swallow messages. */
+				return TRUE;
+			}
+		}
+	}
+	
+	if( ( g_strcasecmp( set_getstr( &bee->set, "strip_html" ), "always" ) == 0 ) ||
+	    ( ( bu->ic->flags & OPT_DOES_HTML ) && set_getbool( &bee->set, "strip_html" ) ) )
+	{
+		char *s = g_strdup( msg );
+		strip_html( s );
+		g_free( msg );
+		msg = s;
+	}
+	
 	wrapped = word_wrap( msg, 425 );
 	irc_send_msg( iu, "PRIVMSG", dst, wrapped, prefix );
@@ -229,4 +260,5 @@
 	g_free( wrapped );
 	g_free( prefix );
+	g_free( msg );
 	g_free( ts );
 	
@@ -349,15 +381,15 @@
 	}
 	
+	if( iu->pastebuf == NULL )
+		iu->pastebuf = g_string_new( msg );
+	else
+	{
+		b_event_remove( iu->pastebuf_timer );
+		g_string_append_printf( iu->pastebuf, "\n%s", msg );
+	}
+	
 	if( set_getbool( &iu->irc->b->set, "paste_buffer" ) )
 	{
 		int delay;
-		
-		if( iu->pastebuf == NULL )
-			iu->pastebuf = g_string_new( msg );
-		else
-		{
-			b_event_remove( iu->pastebuf_timer );
-			g_string_append_printf( iu->pastebuf, "\n%s", msg );
-		}
 		
 		if( ( delay = set_getint( &iu->irc->b->set, "paste_buffer_delay" ) ) <= 5 )
@@ -369,5 +401,9 @@
 	}
 	else
-		return bee_user_msg( iu->irc->b, iu->bu, msg, 0 );
+	{
+		bee_irc_user_privmsg_cb( iu, 0, 0 );
+		
+		return TRUE;
+	}
 }
 
@@ -375,9 +411,33 @@
 {
 	irc_user_t *iu = data;
-	
-	bee_user_msg( iu->irc->b, iu->bu, iu->pastebuf->str, 0 );
-	
-	g_string_free( iu->pastebuf, TRUE );
-	iu->pastebuf = 0;
+	char *msg = g_string_free( iu->pastebuf, FALSE );
+	GSList *l;
+	
+	for( l = irc_plugins; l; l = l->next )
+	{
+		irc_plugin_t *p = l->data;
+		if( p->filter_msg_out )
+		{
+			char *s = p->filter_msg_out( iu, msg, 0 );
+			if( s )
+			{
+				if( s != msg )
+					g_free( msg );
+				msg = s;
+			}
+			else
+			{
+				/* Modules can swallow messages. */
+				iu->pastebuf = NULL;
+				g_free( msg );
+				return FALSE;
+			}
+		}
+	}
+	
+	bee_user_msg( iu->irc->b, iu->bu, msg, 0 );
+	
+	g_free( msg );
+	iu->pastebuf = NULL;
 	iu->pastebuf_timer = 0;
 	
Index: otr.c
===================================================================
--- otr.c	(revision 0c85c08d210e16bb10dc283b4a1478ce53c0c1b1)
+++ otr.c	(revision 934db064a58ebec2edea83df4fa07e2c83220344)
@@ -344,5 +344,5 @@
 }
 
-char *otr_handle_message(struct im_connection *ic, const char *handle, const char *msg)
+char *otr_filter_msg_in(irc_user_t *iu, char *msg, int flags)
 {
 	int ignore_msg;
@@ -350,16 +350,17 @@
 	OtrlTLV *tlvs = NULL;
 	char *colormsg;
-	irc_t *irc = ic->bee->ui_data;
+	irc_t *irc = iu->irc;
+	struct im_connection *ic = iu->bu->ic;
 	
 	/* don't do OTR on certain (not classic IM) protocols, e.g. twitter */
 	if(ic->acc->prpl->options & OPT_NOOTR) {
-		return (g_strdup(msg));
+		return msg;
 	}
 	
 	ignore_msg = otrl_message_receiving(irc->otr->us, &otr_ops, ic,
-		ic->acc->user, ic->acc->prpl->name, handle, msg, &newmsg,
+		ic->acc->user, ic->acc->prpl->name, iu->bu->handle, msg, &newmsg,
 		&tlvs, NULL, NULL);
 
-	otr_handle_smp(ic, handle, tlvs);
+	otr_handle_smp(ic, iu->bu->handle, tlvs);
 	
 	if(ignore_msg) {
@@ -371,8 +372,8 @@
 	} else {
 		/* OTR has processed this message */
-		ConnContext *context = otrl_context_find(irc->otr->us, handle,
+		ConnContext *context = otrl_context_find(irc->otr->us, iu->bu->handle,
 			ic->acc->user, ic->acc->prpl->name, 0, NULL, NULL, NULL);
 		if(context && context->msgstate == OTRL_MSGSTATE_ENCRYPTED &&
-		   set_getbool(&ic->bee->set, "color_encrypted")) {
+		   set_getbool(&ic->bee->set, "otr_color_encrypted")) {
 			/* color according to f'print trust */
 			int color;
@@ -398,26 +399,26 @@
 }
 
-int otr_send_message(struct im_connection *ic, const char *handle, const char *msg, int flags)
+char *otr_filter_msg_out(irc_user_t *iu, char *msg, int flags)
 {	
 	int st;
 	char *otrmsg = NULL;
 	ConnContext *ctx = NULL;
-	irc_t *irc = ic->bee->ui_data;
+	irc_t *irc = iu->irc;
+	struct im_connection *ic = iu->bu->ic;
 
 	/* don't do OTR on certain (not classic IM) protocols, e.g. twitter */
 	if(ic->acc->prpl->options & OPT_NOOTR) {
-		/* TODO(wilmer): const */
-		return (ic->acc->prpl->buddy_msg(ic, (char*) handle, (char*) msg, flags));
+		return msg;
 	}
 	
 	st = otrl_message_sending(irc->otr->us, &otr_ops, ic,
-		ic->acc->user, ic->acc->prpl->name, handle,
+		ic->acc->user, ic->acc->prpl->name, iu->bu->handle,
 		msg, NULL, &otrmsg, NULL, NULL);
 	if(st) {
-		return st;
+		return NULL;
 	}
 
 	ctx = otrl_context_find(irc->otr->us,
-			handle, ic->acc->user, ic->acc->prpl->name,
+			iu->bu->handle, ic->acc->user, ic->acc->prpl->name,
 			1, NULL, NULL, NULL);
 
@@ -425,5 +426,5 @@
 		if(!ctx) {
 			otrl_message_free(otrmsg);
-			return 1;
+			return NULL;
 		}
 		st = otrl_message_fragment_and_send(&otr_ops, ic, ctx,
@@ -433,8 +434,10 @@
 		/* note: otrl_message_sending handles policy, so that if REQUIRE_ENCRYPTION is set,
 		   this case does not occur */
-		st = ic->acc->prpl->buddy_msg( ic, (char *)handle, (char *)msg, flags );
-	}
-	
-	return st;
+		return msg;
+	}
+	
+	/* TODO: Error reporting should be done here now (if st!=0), probably. */
+	
+	return NULL;
 }
 
@@ -443,4 +446,6 @@
 	otr_irc_new,
 	otr_irc_free,
+	otr_filter_msg_out,
+	otr_filter_msg_in,
 };
 
@@ -716,5 +721,5 @@
 	}
 	
-	/* TODO(wilmer): imc_buddy_msg(u->bu->ic, u->bu->handle, "?OTR?", 0); */
+	bee_user_msg(irc->b, u->bu, "?OTR?", 0);
 }
 
Index: otr.h
===================================================================
--- otr.h	(revision 0c85c08d210e16bb10dc283b4a1478ce53c0c1b1)
+++ otr.h	(revision 934db064a58ebec2edea83df4fa07e2c83220344)
@@ -41,5 +41,4 @@
 
 
-#ifdef WITH_OTR
 #include <libotr/proto.h>
 #include <libotr/message.h>
@@ -81,28 +80,3 @@
 int otr_check_for_key(struct account *a);
 
-/* called from imcb_buddy_msg() */
-char *otr_handle_message(struct im_connection *ic, const char *handle,
-	const char *msg);
-	
-/* called from imc_buddy_msg() */
-int otr_send_message(struct im_connection *ic, const char *handle, const char *msg,
-	int flags);
-
-#else
-
-typedef void otr_t;
-typedef void *OtrlMessageAppOps;
-
-#define otr_free(otr) {}
-#define otr_load(irc) {}
-#define otr_save(irc) {}
-#define otr_remove(nick) {}
-#define otr_rename(onick,nnick) {}
-#define otr_check_for_key(acc) (0)
-#define otr_handle_message(ic,handle,msg) (g_strdup(msg))
-#define otr_send_message(ic,h,m,f) (ic->acc->prpl->buddy_msg(ic,h,m,f))
-
-void cmd_otr_nosupport(void *, char **);
-
 #endif
-#endif
Index: protocols/bee_user.c
===================================================================
--- protocols/bee_user.c	(revision 0c85c08d210e16bb10dc283b4a1478ce53c0c1b1)
+++ protocols/bee_user.c	(revision 934db064a58ebec2edea83df4fa07e2c83220344)
@@ -238,8 +238,4 @@
 	}
 	
-	if( ( g_strcasecmp( set_getstr( &ic->bee->set, "strip_html" ), "always" ) == 0 ) ||
-	    ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->bee->set, "strip_html" ) ) )
-		strip_html( msg );
-	
 	if( bee->ui->user_msg && bu )
 		bee->ui->user_msg( bee, bu, msg, sent_at );
