commit e28c7b747da24fe88b0b7b5a9975f042e4eab3c9 Author: dequis Date: Tue Sep 29 02:21:53 2015 -0300 Backport bitlbee-plugin-otr bug fixes to 3.2.1+otr4-1 Includes the following git commits, slightly adapted to apply cleanly after removing a commit that was a failed fix attempt. 367ea3c: work around libotr 4 not sending outgoing plaintext messages 329f9fe: use OTRL_INSTAG_BEST instead of _RECENT to work around a segfault in libotr 74c9e7f: fix a segfault when otr-coloring /me messages 820a2a7: fix 'otr connect' command Relevant bugs: - https://bugs.bitlbee.org/bitlbee/ticket/1109 - https://bugs.bitlbee.org/bitlbee/ticket/1110 - https://bugs.otr.im/issues/16 (not fixed, but workarounded here) diff --git a/otr.c b/otr.c index 8af3add..c63d047 100644 --- a/otr.c +++ b/otr.c @@ -440,11 +440,13 @@ char *otr_filter_msg_out(irc_user_t *iu, char *msg, int flags) { int st; char *otrmsg = NULL; - char *emsg = msg; /* the message as we hand it to libotr */ ConnContext *ctx = NULL; irc_t *irc = iu->irc; struct im_connection *ic = iu->bu->ic; - otrl_instag_t instag = OTRL_INSTAG_RECENT; // XXX? + otrl_instag_t instag = OTRL_INSTAG_BEST; // XXX? + /* NB: in libotr 4.0.0 OTRL_INSTAG_RECENT will cause a null-pointer deref + * in otrl_message_sending with newly-added OTR contexts. + */ /* don't do OTR on certain (not classic IM) protocols, e.g. twitter */ if(ic->acc->prpl->options & OPT_NOOTR) { @@ -453,19 +455,21 @@ char *otr_filter_msg_out(irc_user_t *iu, char *msg, int flags) st = otrl_message_sending(irc->otr->us, &otr_ops, ic, ic->acc->user, ic->acc->prpl->name, iu->bu->handle, instag, - emsg, NULL, &otrmsg, OTRL_FRAGMENT_SEND_ALL, &ctx, NULL, NULL); - /* in libotr 4.0.0 with OTRL_FRAGMENT_SEND_ALL, otrmsg must be passed - * but the value it gets carries no meaning. it can be set even though - * the message has been injected. */ + msg, NULL, &otrmsg, OTRL_FRAGMENT_SEND_ALL_BUT_LAST, &ctx, NULL, NULL); - if(emsg != msg) { - g_free(emsg); /* we're done with this one */ + if(otrmsg && otrmsg != msg) { + /* libotr wants us to replace our message */ + /* NB: caller will free old msg */ + msg = g_strdup(otrmsg); + otrl_message_free(otrmsg); } + if(st) { - /* TODO: Error reporting? */ + irc_usernotice(iu, "otr: error handling outgoing message: %d", st); + msg = NULL; /* do not send plaintext! */ } - - return NULL; + + return msg; } static const struct irc_plugin otr_plugin = @@ -718,6 +722,7 @@ void op_convert_msg(void *opdata, ConnContext *ctx, OtrlConvertType typ, if(typ == OTRL_CONVERT_RECEIVING) { char *msg = g_strdup(src); + char *buf = msg; /* HTML decoding */ if(set_getbool(&ic->bee->set, "otr_does_html") && @@ -753,7 +758,7 @@ void op_convert_msg(void *opdata, ConnContext *ctx, OtrlConvertType typ, *dst = g_strdup_printf("%s\x03%.2d%s%s\x0F", pre, color, sep, msg); - g_free(msg); + g_free(buf); } } else { /* HTML encoding */ @@ -973,6 +978,7 @@ void cmd_otr_disconnect(irc_t *irc, char **args) void cmd_otr_connect(irc_t *irc, char **args) { irc_user_t *u; + char *msg, *query = "?OTR?"; u = irc_user_by_name(irc, args[1]); if(!u || !u->bu || !u->bu->ic) { @@ -986,7 +992,16 @@ void cmd_otr_connect(irc_t *irc, char **args) /* passing this through the filter so it goes through libotr which * will replace the simple query string with a proper one */ - otr_filter_msg_out(u, "?OTR?", 0); + msg = otr_filter_msg_out(u, query, 0); + + /* send the message */ + if(msg) { + u->bu->ic->acc->prpl->buddy_msg(u->bu->ic, u->bu->handle, msg, 0); /* XXX flags? */ + /* XXX error message? */ + + if(msg != query) + g_free(msg); + } } void cmd_otr_smp(irc_t *irc, char **args) @@ -1343,7 +1358,7 @@ void otr_smp_or_smpq(irc_t *irc, const char *nick, const char *question, { irc_user_t *u; ConnContext *ctx; - otrl_instag_t instag = OTRL_INSTAG_RECENT; // XXX + otrl_instag_t instag = OTRL_INSTAG_BEST; // XXX u = irc_user_by_name(irc, nick); if(!u || !u->bu || !u->bu->ic) {