--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/use-otr-v4.diff Sun Jan 13 06:42:35 2013 +0200
@@ -0,0 +1,595 @@
+# HG changeset patch
+# Parent 1b31bdb72d83850b146a0e1e135eba35bad73d29
+Switch to libotr v4 API
+
+diff -r 1b31bdb72d83 mcabber/configure.ac
+--- a/mcabber/configure.ac Sun Jan 13 04:35:32 2013 +0200
++++ b/mcabber/configure.ac Sun Jan 13 06:15:55 2013 +0200
+@@ -183,16 +183,26 @@
+
+ # Check for otr
+ AC_ARG_ENABLE(otr,
+- AC_HELP_STRING([--enable-otr],
+- [enable OTR (Off-the-Record) messaging support]),
+- enable_otr=$enableval, otr="")
++ AC_HELP_STRING([--enable-otr],
++ [enable OTR (Off-the-Record) messaging support]),
++ enable_otr=$enableval,
++ otr="")
+ if test "x$enable_otr" = "xyes"; then
+- # Look for libgcrypt and libotr
+- AM_PATH_LIBGCRYPT(1.2.2, [
+- AM_PATH_LIBOTR(3.1.0, ,
+- AC_MSG_ERROR(libotr 3.1.0 or newer is required.))
+- ], AC_MSG_ERROR(libgcrypt 1.2.2 or newer is required.)
+- )
++ # Look for libgcrypt and libotr
++ AM_PATH_LIBGCRYPT(1.2.2, [
++ AM_PATH_LIBOTR(4.0.0, [
++ AC_DEFINE([HAVE_LIBOTR], 1, [Define if you use libotr])
++ ], [
++ AM_PATH_LIBOTR(3.1.0, [
++ AC_DEFINE([HAVE_LIBOTR], 1, [Define if you use libotr])
++ AC_DEFINE([HAVE_LIBOTR3], 1, [Define if you use libotr v3])
++ ], [
++ AC_MSG_ERROR(libotr 3.1.0 or newer is required.)
++ ])
++ ])
++ ], [
++ AC_MSG_ERROR(libgcrypt 1.2.2 or newer is required.)
++ ])
+ fi
+
+ # Check for Enchant stuff
+@@ -289,3 +299,4 @@
+ mcabber.pc
+ Makefile])
+ AC_OUTPUT
++dnl vim: set expandtab cindent cinoptions=>2\:2(0 sw=2 ts=2: For Vim users...
+diff -r 1b31bdb72d83 mcabber/mcabber/otr.c
+--- a/mcabber/mcabber/otr.c Sun Jan 13 04:35:32 2013 +0200
++++ b/mcabber/mcabber/otr.c Sun Jan 13 06:15:55 2013 +0200
+@@ -56,6 +56,20 @@
+ const char *protocol,
+ const char *recipient,
+ const char *message);
++static void cb_update_context_list(void *opdata);
++static void cb_new_fingerprint (void *opdata, OtrlUserState us,
++ const char *accountname,
++ const char *protocol,
++ const char *username,
++ unsigned char fingerprint[20]);
++static void cb_write_fingerprints (void *opdata);
++static void cb_gone_secure (void *opdata, ConnContext *context);
++static void cb_gone_insecure (void *opdata, ConnContext *context);
++static void cb_still_secure (void *opdata, ConnContext *context,
++ int is_reply);
++static int cb_max_message_size (void *opdata, ConnContext *context);
++
++#ifdef HAVE_LIBOTR3
+ static void cb_notify (void *opdata,
+ OtrlNotifyLevel level,
+ const char *accountname,
+@@ -69,22 +83,26 @@
+ const char *protocol,
+ const char *username,
+ const char *msg);
+-static void cb_update_context_list(void *opdata);
+ static const char *cb_protocol_name (void *opdata, const char *protocol);
+ static void cb_protocol_name_free (void *opdata,
+ const char *protocol_name);
+-static void cb_new_fingerprint (void *opdata, OtrlUserState us,
+- const char *accountname,
+- const char *protocol,
+- const char *username,
+- unsigned char fingerprint[20]);
+-static void cb_write_fingerprints (void *opdata);
+-static void cb_gone_secure (void *opdata, ConnContext *context);
+-static void cb_gone_insecure (void *opdata, ConnContext *context);
+-static void cb_still_secure (void *opdata, ConnContext *context,
+- int is_reply);
+ static void cb_log_message (void *opdata, const char *message);
+-static int cb_max_message_size (void *opdata, ConnContext *context);
++
++static void otr_handle_smp_tlvs (OtrlTLV *tlvs, ConnContext *ctx);
++#else /* HAVE_LIBOTR3 */
++static char *tagfile = NULL;
++static guint otr_timer_source = 0;
++
++static void cb_handle_smp_event (void *opdata, OtrlSMPEvent event,
++ ConnContext *context, unsigned short percent,
++ char *question);
++static void cb_handle_msg_event (void *opdata, OtrlMessageEvent event,
++ ConnContext *context, const char *message,
++ gcry_error_t err);
++static void cb_create_instag (void *opdata, const char *accountname,
++ const char *protocol);
++static void cb_timer_control (void *opdata, unsigned int interval);
++#endif /* HAVE_LIBOTR3 */
+
+ static OtrlMessageAppOps ops =
+ {
+@@ -92,26 +110,44 @@
+ cb_create_privkey,
+ cb_is_logged_in,
+ cb_inject_message,
++#ifdef HAVE_LIBOTR3
+ cb_notify,
+ cb_display_otr_message,
++#endif
+ cb_update_context_list,
++#ifdef HAVE_LIBOTR3
+ cb_protocol_name,
+ cb_protocol_name_free,
++#endif
+ cb_new_fingerprint,
+ cb_write_fingerprints,
+ cb_gone_secure,
+ cb_gone_insecure,
+ cb_still_secure,
++#ifdef HAVE_LIBOTR3
+ cb_log_message,
++#endif
+ cb_max_message_size,
+- NULL, /*account_name*/
+- NULL /*account_name_free*/
++ NULL, /* account_name */
++ NULL, /* account_name_free */
++#ifndef HAVE_LIBOTR3
++ NULL, /* received_symkey */
++ NULL, /* otr_error_message */
++ NULL, /* otr_error_message_free */
++ NULL, /* resent_msg_prefix */
++ NULL, /* resent_msg_prefix_free */
++ cb_handle_smp_event,
++ cb_handle_msg_event,
++ cb_create_instag,
++ NULL, /* convert_msg */
++ NULL, /* convert_free */
++ cb_timer_control,
++#endif
+ };
+
+ static void otr_message_disconnect(ConnContext *ctx);
+ static ConnContext *otr_get_context(const char *buddy);
+ static void otr_startstop(const char *buddy, int start);
+-static void otr_handle_smp_tlvs(OtrlTLV *tlvs, ConnContext *ctx);
+
+ static char *otr_get_dir(void);
+
+@@ -145,6 +181,13 @@
+ scr_LogPrint(LPRINT_LOGNORM, "Could not read OTR fingerprints from %s",
+ fprfile);
+ }
++#ifndef HAVE_LIBOTR3
++ tagfile = g_strdup_printf("%s%s.tag", root, account);
++ if (otrl_instag_read(userstate, tagfile)) {
++ scr_LogPrint(LPRINT_LOGNORM, "Could not read OTR instance tag from %s", tagfile);
++ cb_create_instag(NULL, account, OTR_PROTOCOL_NAME);
++ }
++#endif
+ }
+
+ void otr_terminate(void)
+@@ -154,6 +197,13 @@
+ if (!otr_is_enabled)
+ return;
+
++#ifndef HAVE_LIBOTR3
++ if (otr_timer_source > 0) {
++ g_source_remove (otr_timer_source);
++ otr_timer_source = 0;
++ }
++#endif
++
+ for (ctx = userstate->context_root; ctx; ctx = ctx->next)
+ if (ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED)
+ otr_message_disconnect(ctx);
+@@ -175,6 +225,12 @@
+ userstate = NULL;
+ g_free(keyfile);
+ keyfile = NULL;
++ g_free(fprfile);
++ fprfile = NULL;
++#ifndef HAVE_LIBOTR3
++ g_free(tagfile);
++ tagfile = NULL;
++#endif
+ }
+
+ static char *otr_get_dir(void)
+@@ -206,7 +262,12 @@
+
+ mc_strtolower(lowcasebuddy);
+ ctx = otrl_context_find(userstate, lowcasebuddy, account, OTR_PROTOCOL_NAME,
++#ifdef HAVE_LIBOTR3
+ 1, &null, NULL, NULL);
++#else
++ // INSTAG XXX
++ OTRL_INSTAG_BEST, 1, &null, NULL, NULL);
++#endif
+ g_free(lowcasebuddy);
+ return ctx;
+ }
+@@ -216,7 +277,12 @@
+ if (ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED)
+ cb_gone_insecure(NULL, ctx);
+ otrl_message_disconnect(userstate, &ops, NULL, ctx->accountname,
++#ifdef HAVE_LIBOTR3
+ ctx->protocol, ctx->username);
++#else
++ // INSTAG XXX
++ ctx->protocol, ctx->username, OTRL_INSTAG_BEST);
++#endif
+ }
+
+ static void otr_startstop(const char *buddy, int start)
+@@ -283,6 +349,8 @@
+ cb_write_fingerprints(NULL);
+ }
+
++#ifdef HAVE_LIBOTR3
++
+ static void otr_handle_smp_tlvs(OtrlTLV *tlvs, ConnContext *ctx)
+ {
+ OtrlTLV *tlv = NULL;
+@@ -354,6 +422,130 @@
+ }
+ }
+
++#else /* HAVE_LIBOTR3 */
++
++static void cb_handle_smp_event(void *opdata, OtrlSMPEvent event,
++ ConnContext *context, unsigned short percent,
++ char *question)
++{
++ const char *msg = NULL;
++ char *freeme = NULL;
++ switch (event) {
++ case OTRL_SMPEVENT_ASK_FOR_SECRET:
++ msg = freeme = g_strdup_printf("OTR: Socialist Millionaires' Protocol: "
++ "Received SMP Initiation.\n"
++ "Answer with /otr smpr %s $secret",
++ context->username);
++ break;
++ case OTRL_SMPEVENT_ASK_FOR_ANSWER:
++ msg = freeme = g_strdup_printf("OTR: Socialist Millionaires' Protocol: "
++ "Received SMP Initiation.\n"
++ "Answer with /otr smpr %s $secret\n"
++ "Question: %s", context->username,
++ question);
++ break;
++ case OTRL_SMPEVENT_CHEATED:
++ msg = "OTR: Socialist Millionaires' Protocol: Correspondent cancelled negotiation!";
++ otrl_message_abort_smp(userstate, &ops, opdata, context);
++ break;
++ case OTRL_SMPEVENT_IN_PROGRESS:
++ scr_log_print(LPRINT_DEBUG, "OTR: Socialist Millionaires' Protocol: "
++ "Negotiation is in pogress...");
++ break;
++ case OTRL_SMPEVENT_SUCCESS:
++ msg = "OTR: Socialist Millionaires' Protocol: Success!";
++ break;
++ case OTRL_SMPEVENT_FAILURE:
++ msg = "OTR: Socialist Millionaires' Protocol: Failure.";
++ break;
++ case OTRL_SMPEVENT_ABORT:
++ msg = "OTR: Socialist Millionaires' Protocol: Aborted.";
++ break;
++ case OTRL_SMPEVENT_ERROR:
++ msg = "OTR: Socialist Millionaires' Protocol: Error occured, aborting negotiations!";
++ otrl_message_abort_smp(userstate, &ops, opdata, context);
++ break;
++ default:
++ break;
++ }
++
++ if (msg) {
++ scr_WriteIncomingMessage(context->username, msg, 0, HBB_PREFIX_INFO, 0);
++ g_free(freeme);
++ }
++}
++
++static void cb_handle_msg_event(void *opdata, OtrlMessageEvent event,
++ ConnContext *context, const char *message,
++ gcry_error_t err)
++{
++ const char *msg = NULL;
++ char *freeme = NULL;
++ switch (event) {
++ case OTRL_MSGEVENT_ENCRYPTION_REQUIRED:
++ msg = "OTR: Policy requires encryption on message!";
++ break;
++ case OTRL_MSGEVENT_ENCRYPTION_ERROR:
++ msg = "OTR: Encryption error! Message not sent.";
++ break;
++ case OTRL_MSGEVENT_CONNECTION_ENDED:
++ msg = "OTR: Connection closed by remote end, message lost. "
++ "Close or refresh connection.";
++ break;
++ case OTRL_MSGEVENT_SETUP_ERROR:
++ // FIXME
++ msg = freeme = g_strdup_printf("OTR: Error setting up private conversation: %u",
++ err);
++ break;
++ case OTRL_MSGEVENT_MSG_REFLECTED:
++ msg = "OTR: Received own OTR message!";
++ break;
++ case OTRL_MSGEVENT_MSG_RESENT:
++ msg = "OTR: Previous message was resent.";
++ break;
++ case OTRL_MSGEVENT_RCVDMSG_NOT_IN_PRIVATE:
++ msg = "OTR: Received encrypted message, but connection is not established " \
++ "yet! Message lost.";
++ break;
++ case OTRL_MSGEVENT_RCVDMSG_UNREADABLE:
++ msg = "OTR: Unable to read incoming message!";
++ break;
++ case OTRL_MSGEVENT_RCVDMSG_MALFORMED:
++ msg = "OTR: Malformed incoming message!";
++ break;
++ case OTRL_MSGEVENT_LOG_HEARTBEAT_RCVD:
++ scr_log_print(LPRINT_DEBUG, "OTR: Received heartbeat.");
++ break;
++ case OTRL_MSGEVENT_LOG_HEARTBEAT_SENT:
++ scr_log_print(LPRINT_DEBUG, "OTR: Sent heartbeat.");
++ break;
++ case OTRL_MSGEVENT_RCVDMSG_GENERAL_ERR:
++ msg = freeme = g_strdup_printf("OTR: Received general otr error: %s",
++ message);
++ break;
++ case OTRL_MSGEVENT_RCVDMSG_UNENCRYPTED:
++ msg = freeme = g_strdup_printf("OTR: Received unencrypted message: %s",
++ message);
++ break;
++ case OTRL_MSGEVENT_RCVDMSG_UNRECOGNIZED:
++ msg = "OTR: Unable to determine type of received OTR message!";
++ break;
++ case OTRL_MSGEVENT_RCVDMSG_FOR_OTHER_INSTANCE:
++ // XXX
++ scr_log_print(LPRINT_DEBUG, "OTR: Received message for other instance.");
++ break;
++ default:
++ break;
++ }
++
++ if (msg) {
++ scr_WriteIncomingMessage(context->username, msg, 0, HBB_PREFIX_INFO, 0);
++ g_free(freeme);
++ }
++}
++
++#endif /* HAVE_LIBOTR3 */
++
+ /*
+ * returns whether a otr_message was received
+ * sets *otr_data to NULL, when it was an internal otr message
+@@ -362,8 +554,10 @@
+ {
+ int ignore_message;
+ char *newmessage = NULL;
++#ifdef HAVE_LIBOTR3
+ OtrlTLV *tlvs = NULL;
+ OtrlTLV *tlv = NULL;
++#endif
+ ConnContext *ctx;
+
+ ctx = otr_get_context(buddy);
+@@ -371,8 +565,8 @@
+ ignore_message = otrl_message_receiving(userstate, &ops, NULL,
+ ctx->accountname, ctx->protocol,
+ ctx->username, *otr_data,
+- &newmessage, &tlvs,NULL, NULL);
+-
++#ifdef HAVE_LIBOTR3
++ &newmessage, &tlvs, NULL, NULL);
+
+ tlv = otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED);
+ if (tlv) {
+@@ -387,6 +581,9 @@
+
+ if (tlvs != NULL)
+ otrl_tlv_free(tlvs);
++#else
++ &newmessage, NULL, NULL, NULL, NULL);
++#endif
+
+ if (ignore_message)
+ *otr_data = NULL;
+@@ -410,13 +607,27 @@
+
+ if (ctx->msgstate == OTRL_MSGSTATE_PLAINTEXT)
+ err = otrl_message_sending(userstate, &ops, NULL, ctx->accountname,
++#ifdef HAVE_LIBOTR3
+ ctx->protocol, ctx->username, *msg, NULL,
+ &newmessage, NULL, NULL);
++#else
++ // INSTAG XXX
++ ctx->protocol, ctx->username, OTRL_INSTAG_BEST,
++ *msg, NULL, &newmessage, OTRL_FRAGMENT_SEND_SKIP,
++ NULL, NULL, NULL);
++#endif
+ else {
+ htmlmsg = html_escape(*msg);
+ err = otrl_message_sending(userstate, &ops, NULL, ctx->accountname,
++#ifdef HAVE_LIBOTR3
+ ctx->protocol, ctx->username, htmlmsg, NULL,
+ &newmessage, NULL, NULL);
++#else
++ // INSTAG XXX
++ ctx->protocol, ctx->username, OTRL_INSTAG_BEST,
++ htmlmsg, NULL, &newmessage, OTRL_FRAGMENT_SEND_SKIP,
++ NULL, NULL, NULL);
++#endif
+ g_free(htmlmsg);
+ }
+
+@@ -648,42 +859,6 @@
+ LM_MESSAGE_SUB_TYPE_NOT_SET, NULL);
+ }
+
+-/* Display a notification message for a particular
+- * accountname / protocol / username conversation. */
+-static void cb_notify(void *opdata, OtrlNotifyLevel level,
+- const char *accountname, const char *protocol,
+- const char *username, const char *title,
+- const char *primary, const char *secondary)
+-{
+- char *type;
+- char *sbuf = NULL;
+- switch (level) {
+- case OTRL_NOTIFY_ERROR: type = "error"; break;
+- case OTRL_NOTIFY_WARNING: type = "warning"; break;
+- case OTRL_NOTIFY_INFO: type = "info"; break;
+- default: type = "unknown";
+- }
+- sbuf = g_strdup_printf("OTR %s:%s\n%s\n%s",type,title, primary, secondary);
+- scr_WriteIncomingMessage(username, sbuf, 0, HBB_PREFIX_INFO, 0);
+- g_free(sbuf);
+-}
+-
+-/* Display an OTR control message for a particular
+- * accountname / protocol / username conversation. Return 0 if you are able
+- * to successfully display it. If you return non-0 (or if this
+- * function is NULL), the control message will be displayed inline,
+- * as a received message, or else by using the above notify()
+- * callback. */
+-static int cb_display_otr_message(void *opdata, const char *accountname,
+- const char *protocol, const char *username,
+- const char *msg)
+-{
+- char *strippedmsg = html_strip(msg);
+- scr_WriteIncomingMessage(username, strippedmsg, 0, HBB_PREFIX_INFO, 0);
+- g_free(strippedmsg);
+- return 0;
+-}
+-
+ /* When the list of ConnContexts changes (including a change in
+ * state), this is called so the UI can be updated. */
+ static void cb_update_context_list(void *opdata)
+@@ -692,19 +867,6 @@
+ * then use this function (?!)*/
+ }
+
+-/* Return a newly allocated string containing a human-friendly name
+- * for the given protocol id */
+-static const char *cb_protocol_name(void *opdata, const char *protocol)
+-{
+- return protocol;
+-}
+-
+-/* Deallocate a string allocated by protocol_name */
+-static void cb_protocol_name_free (void *opdata, const char *protocol_name)
+-{
+- /* We didn't allocated memory, so we don't have to free anything :p */
+-}
+-
+ /* A new fingerprint for the given user has been received. */
+ static void cb_new_fingerprint(void *opdata, OtrlUserState us,
+ const char *accountname, const char *protocol,
+@@ -748,12 +910,92 @@
+ HBB_PREFIX_INFO, 0);
+ }
+
++#ifdef HAVE_LIBOTR3
++
++/* Display a notification message for a particular
++ * accountname / protocol / username conversation. */
++static void cb_notify(void *opdata, OtrlNotifyLevel level,
++ const char *accountname, const char *protocol,
++ const char *username, const char *title,
++ const char *primary, const char *secondary)
++{
++ char *type;
++ char *sbuf = NULL;
++ switch (level) {
++ case OTRL_NOTIFY_ERROR: type = "error"; break;
++ case OTRL_NOTIFY_WARNING: type = "warning"; break;
++ case OTRL_NOTIFY_INFO: type = "info"; break;
++ default: type = "unknown";
++ }
++ sbuf = g_strdup_printf("OTR %s:%s\n%s\n%s",type,title, primary, secondary);
++ scr_WriteIncomingMessage(username, sbuf, 0, HBB_PREFIX_INFO, 0);
++ g_free(sbuf);
++}
++
++/* Display an OTR control message for a particular
++ * accountname / protocol / username conversation. Return 0 if you are able
++ * to successfully display it. If you return non-0 (or if this
++ * function is NULL), the control message will be displayed inline,
++ * as a received message, or else by using the above notify()
++ * callback. */
++static int cb_display_otr_message(void *opdata, const char *accountname,
++ const char *protocol, const char *username,
++ const char *msg)
++{
++ char *strippedmsg = html_strip(msg);
++ scr_WriteIncomingMessage(username, strippedmsg, 0, HBB_PREFIX_INFO, 0);
++ g_free(strippedmsg);
++ return 0;
++}
++
++/* Return a newly allocated string containing a human-friendly name
++ * for the given protocol id */
++static const char *cb_protocol_name(void *opdata, const char *protocol)
++{
++ return protocol;
++}
++
++/* Deallocate a string allocated by protocol_name */
++static void cb_protocol_name_free (void *opdata, const char *protocol_name)
++{
++ /* We didn't allocated memory, so we don't have to free anything :p */
++}
++
+ /* Log a message. The passed message will end in "\n". */
+ static void cb_log_message(void *opdata, const char *message)
+ {
+ scr_LogPrint(LPRINT_DEBUG, "OTR: %s", message);
+ }
+
++#else /* HAVE_LIBOTR3 */
++
++/* Generate unique instance tag for account. */
++static void cb_create_instag(void *opdata, const char *accountname,
++ const char *protocol)
++{
++ if (otrl_instag_generate(userstate, tagfile, accountname, protocol)) {
++ scr_LogPrint(LPRINT_LOGNORM, "OTR instance tag generation failed!");
++ }
++}
++
++static gboolean otr_timer_cb(gpointer userdata)
++{
++ otrl_message_poll(userstate, &ops, userdata);
++ return TRUE;
++}
++
++static void cb_timer_control(void *opdata, unsigned int interval)
++{
++ if (otr_timer_source > 0) {
++ g_source_remove(otr_timer_source);
++ otr_timer_source = 0;
++ }
++ if (interval > 0)
++ otr_timer_source = g_timeout_add_seconds(interval, otr_timer_cb, opdata);
++}
++
++#endif /* HAVE_LIBOTR3 */
++
+ /* Find the maximum message size supported by this protocol. */
+ static int cb_max_message_size(void *opdata, ConnContext *context)
+ {
+diff -r 1b31bdb72d83 mcabber/mcabber/otr.h
+--- a/mcabber/mcabber/otr.h Sun Jan 13 04:35:32 2013 +0200
++++ b/mcabber/mcabber/otr.h Sun Jan 13 06:15:55 2013 +0200
+@@ -5,6 +5,9 @@
+
+ #ifdef HAVE_LIBOTR
+
++#ifndef HAVE_LIBOTR3
++# include <libotr/instag.h>
++#endif
+ #include <libotr/proto.h>
+ #include <libotr/message.h>
+ #include <libotr/privkey.h>