# 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 Fri Jan 18 11:23:47 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 Fri Jan 18 11:23:47 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);
@@ -135,7 +171,6 @@
account = jidtodisp(fjid);
keyfile = g_strdup_printf("%s%s.key", root, account);
fprfile = g_strdup_printf("%s%s.fpr", root, account);
- g_free(root);
if (otrl_privkey_read(userstate, keyfile)){
scr_LogPrint(LPRINT_LOGNORM, "Could not read OTR key from %s", keyfile);
@@ -145,6 +180,14 @@
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
+ g_free(root);
}
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 Fri Jan 18 11:23:47 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>