# HG changeset patch # User Myhailo Danylenko # Date 1368613962 -10800 # Node ID 9fb1ccf291cc1c28eab019f9416c0d407a47be4f # Parent f52b47f29ca0475dc4823333cb24090287c37599 Switch to libotr v4 API Patch merged from isbear's mcabber-patches repository (Mikael) diff -r f52b47f29ca0 -r 9fb1ccf291cc mcabber/configure.ac --- a/mcabber/configure.ac Wed May 15 13:32:42 2013 +0300 +++ b/mcabber/configure.ac Wed May 15 13:32:42 2013 +0300 @@ -184,16 +184,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 @@ -290,3 +300,4 @@ mcabber.pc Makefile]) AC_OUTPUT +dnl vim: set expandtab cindent cinoptions=>2\:2(0 sw=2 ts=2: For Vim users... diff -r f52b47f29ca0 -r 9fb1ccf291cc mcabber/mcabber/otr.c --- a/mcabber/mcabber/otr.c Wed May 15 13:32:42 2013 +0300 +++ b/mcabber/mcabber/otr.c Wed May 15 13:32:42 2013 +0300 @@ -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 f52b47f29ca0 -r 9fb1ccf291cc mcabber/mcabber/otr.h --- a/mcabber/mcabber/otr.h Wed May 15 13:32:42 2013 +0300 +++ b/mcabber/mcabber/otr.h Wed May 15 13:32:42 2013 +0300 @@ -5,6 +5,9 @@ #ifdef HAVE_LIBOTR +#ifndef HAVE_LIBOTR3 +# include +#endif #include #include #include