1
Description: Make mcabber work with libotr v4 api
2
Author: Myhailo Danylenko <isbear@ukrpost.net>
3
Origin: http://www.isbear.org.ua/hg/isbear/mcabber-patches/file/tip/use-otr-v4.diff
4
Bug: https://bitbucket.org/McKael/mcabber-crew/issue/102/libotr-400-support
5
Bug-Debian: http://bugs.debian.org/711072
6
Bug-Ubuntu: http://pad.lv/1201213
7
Last-Update: 2013-07-26
9
diff -r 1b31bdb72d83 mcabber/configure.ac
10
--- a/configure.ac Sun Jan 13 04:35:32 2013 +0200
11
+++ b/configure.ac Fri Jan 18 11:23:47 2013 +0200
16
- AC_HELP_STRING([--enable-otr],
17
- [enable OTR (Off-the-Record) messaging support]),
18
- enable_otr=$enableval, otr="")
19
+ AC_HELP_STRING([--enable-otr],
20
+ [enable OTR (Off-the-Record) messaging support]),
21
+ enable_otr=$enableval,
23
if test "x$enable_otr" = "xyes"; then
24
- # Look for libgcrypt and libotr
25
- AM_PATH_LIBGCRYPT(1.2.2, [
26
- AM_PATH_LIBOTR(3.1.0, ,
27
- AC_MSG_ERROR(libotr 3.1.0 or newer is required.))
28
- ], AC_MSG_ERROR(libgcrypt 1.2.2 or newer is required.)
30
+ # Look for libgcrypt and libotr
31
+ AM_PATH_LIBGCRYPT(1.2.2, [
32
+ AM_PATH_LIBOTR(4.0.0, [
33
+ AC_DEFINE([HAVE_LIBOTR], 1, [Define if you use libotr])
35
+ AM_PATH_LIBOTR(3.1.0, [
36
+ AC_DEFINE([HAVE_LIBOTR], 1, [Define if you use libotr])
37
+ AC_DEFINE([HAVE_LIBOTR3], 1, [Define if you use libotr v3])
39
+ AC_MSG_ERROR(libotr 3.1.0 or newer is required.)
43
+ AC_MSG_ERROR(libgcrypt 1.2.2 or newer is required.)
47
# Check for Enchant stuff
52
+dnl vim: set expandtab cindent cinoptions=>2\:2(0 sw=2 ts=2: For Vim users...
53
diff -r 1b31bdb72d83 mcabber/mcabber/otr.c
54
--- a/mcabber/otr.c Sun Jan 13 04:35:32 2013 +0200
55
+++ b/mcabber/otr.c Fri Jan 18 11:23:47 2013 +0200
58
const char *recipient,
60
+static void cb_update_context_list(void *opdata);
61
+static void cb_new_fingerprint (void *opdata, OtrlUserState us,
62
+ const char *accountname,
63
+ const char *protocol,
64
+ const char *username,
65
+ unsigned char fingerprint[20]);
66
+static void cb_write_fingerprints (void *opdata);
67
+static void cb_gone_secure (void *opdata, ConnContext *context);
68
+static void cb_gone_insecure (void *opdata, ConnContext *context);
69
+static void cb_still_secure (void *opdata, ConnContext *context,
71
+static int cb_max_message_size (void *opdata, ConnContext *context);
74
static void cb_notify (void *opdata,
75
OtrlNotifyLevel level,
76
const char *accountname,
81
-static void cb_update_context_list(void *opdata);
82
static const char *cb_protocol_name (void *opdata, const char *protocol);
83
static void cb_protocol_name_free (void *opdata,
84
const char *protocol_name);
85
-static void cb_new_fingerprint (void *opdata, OtrlUserState us,
86
- const char *accountname,
87
- const char *protocol,
88
- const char *username,
89
- unsigned char fingerprint[20]);
90
-static void cb_write_fingerprints (void *opdata);
91
-static void cb_gone_secure (void *opdata, ConnContext *context);
92
-static void cb_gone_insecure (void *opdata, ConnContext *context);
93
-static void cb_still_secure (void *opdata, ConnContext *context,
95
static void cb_log_message (void *opdata, const char *message);
96
-static int cb_max_message_size (void *opdata, ConnContext *context);
98
+static void otr_handle_smp_tlvs (OtrlTLV *tlvs, ConnContext *ctx);
99
+#else /* HAVE_LIBOTR3 */
100
+static char *tagfile = NULL;
101
+static guint otr_timer_source = 0;
103
+static void cb_handle_smp_event (void *opdata, OtrlSMPEvent event,
104
+ ConnContext *context, unsigned short percent,
106
+static void cb_handle_msg_event (void *opdata, OtrlMessageEvent event,
107
+ ConnContext *context, const char *message,
109
+static void cb_create_instag (void *opdata, const char *accountname,
110
+ const char *protocol);
111
+static void cb_timer_control (void *opdata, unsigned int interval);
112
+#endif /* HAVE_LIBOTR3 */
114
static OtrlMessageAppOps ops =
122
cb_display_otr_message,
124
cb_update_context_list,
127
cb_protocol_name_free,
130
cb_write_fingerprints,
138
- NULL, /*account_name*/
139
- NULL /*account_name_free*/
140
+ NULL, /* account_name */
141
+ NULL, /* account_name_free */
142
+#ifndef HAVE_LIBOTR3
143
+ NULL, /* received_symkey */
144
+ NULL, /* otr_error_message */
145
+ NULL, /* otr_error_message_free */
146
+ NULL, /* resent_msg_prefix */
147
+ NULL, /* resent_msg_prefix_free */
148
+ cb_handle_smp_event,
149
+ cb_handle_msg_event,
151
+ NULL, /* convert_msg */
152
+ NULL, /* convert_free */
157
static void otr_message_disconnect(ConnContext *ctx);
158
static ConnContext *otr_get_context(const char *buddy);
159
static void otr_startstop(const char *buddy, int start);
160
-static void otr_handle_smp_tlvs(OtrlTLV *tlvs, ConnContext *ctx);
162
static char *otr_get_dir(void);
165
account = jidtodisp(fjid);
166
keyfile = g_strdup_printf("%s%s.key", root, account);
167
fprfile = g_strdup_printf("%s%s.fpr", root, account);
170
if (otrl_privkey_read(userstate, keyfile)){
171
scr_LogPrint(LPRINT_LOGNORM, "Could not read OTR key from %s", keyfile);
173
scr_LogPrint(LPRINT_LOGNORM, "Could not read OTR fingerprints from %s",
176
+#ifndef HAVE_LIBOTR3
177
+ tagfile = g_strdup_printf("%s%s.tag", root, account);
178
+ if (otrl_instag_read(userstate, tagfile)) {
179
+ scr_LogPrint(LPRINT_LOGNORM, "Could not read OTR instance tag from %s", tagfile);
180
+ cb_create_instag(NULL, account, OTR_PROTOCOL_NAME);
186
void otr_terminate(void)
191
+#ifndef HAVE_LIBOTR3
192
+ if (otr_timer_source > 0) {
193
+ g_source_remove (otr_timer_source);
194
+ otr_timer_source = 0;
198
for (ctx = userstate->context_root; ctx; ctx = ctx->next)
199
if (ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED)
200
otr_message_disconnect(ctx);
207
+#ifndef HAVE_LIBOTR3
213
static char *otr_get_dir(void)
216
mc_strtolower(lowcasebuddy);
217
ctx = otrl_context_find(userstate, lowcasebuddy, account, OTR_PROTOCOL_NAME,
219
1, &null, NULL, NULL);
222
+ OTRL_INSTAG_BEST, 1, &null, NULL, NULL);
224
g_free(lowcasebuddy);
228
if (ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED)
229
cb_gone_insecure(NULL, ctx);
230
otrl_message_disconnect(userstate, &ops, NULL, ctx->accountname,
232
ctx->protocol, ctx->username);
235
+ ctx->protocol, ctx->username, OTRL_INSTAG_BEST);
239
static void otr_startstop(const char *buddy, int start)
241
cb_write_fingerprints(NULL);
246
static void otr_handle_smp_tlvs(OtrlTLV *tlvs, ConnContext *ctx)
249
@@ -354,6 +422,130 @@
253
+#else /* HAVE_LIBOTR3 */
255
+static void cb_handle_smp_event(void *opdata, OtrlSMPEvent event,
256
+ ConnContext *context, unsigned short percent,
259
+ const char *msg = NULL;
260
+ char *freeme = NULL;
262
+ case OTRL_SMPEVENT_ASK_FOR_SECRET:
263
+ msg = freeme = g_strdup_printf("OTR: Socialist Millionaires' Protocol: "
264
+ "Received SMP Initiation.\n"
265
+ "Answer with /otr smpr %s $secret",
266
+ context->username);
268
+ case OTRL_SMPEVENT_ASK_FOR_ANSWER:
269
+ msg = freeme = g_strdup_printf("OTR: Socialist Millionaires' Protocol: "
270
+ "Received SMP Initiation.\n"
271
+ "Answer with /otr smpr %s $secret\n"
272
+ "Question: %s", context->username,
275
+ case OTRL_SMPEVENT_CHEATED:
276
+ msg = "OTR: Socialist Millionaires' Protocol: Correspondent cancelled negotiation!";
277
+ otrl_message_abort_smp(userstate, &ops, opdata, context);
279
+ case OTRL_SMPEVENT_IN_PROGRESS:
280
+ scr_log_print(LPRINT_DEBUG, "OTR: Socialist Millionaires' Protocol: "
281
+ "Negotiation is in pogress...");
283
+ case OTRL_SMPEVENT_SUCCESS:
284
+ msg = "OTR: Socialist Millionaires' Protocol: Success!";
286
+ case OTRL_SMPEVENT_FAILURE:
287
+ msg = "OTR: Socialist Millionaires' Protocol: Failure.";
289
+ case OTRL_SMPEVENT_ABORT:
290
+ msg = "OTR: Socialist Millionaires' Protocol: Aborted.";
292
+ case OTRL_SMPEVENT_ERROR:
293
+ msg = "OTR: Socialist Millionaires' Protocol: Error occured, aborting negotiations!";
294
+ otrl_message_abort_smp(userstate, &ops, opdata, context);
301
+ scr_WriteIncomingMessage(context->username, msg, 0, HBB_PREFIX_INFO, 0);
306
+static void cb_handle_msg_event(void *opdata, OtrlMessageEvent event,
307
+ ConnContext *context, const char *message,
310
+ const char *msg = NULL;
311
+ char *freeme = NULL;
313
+ case OTRL_MSGEVENT_ENCRYPTION_REQUIRED:
314
+ msg = "OTR: Policy requires encryption on message!";
316
+ case OTRL_MSGEVENT_ENCRYPTION_ERROR:
317
+ msg = "OTR: Encryption error! Message not sent.";
319
+ case OTRL_MSGEVENT_CONNECTION_ENDED:
320
+ msg = "OTR: Connection closed by remote end, message lost. "
321
+ "Close or refresh connection.";
323
+ case OTRL_MSGEVENT_SETUP_ERROR:
325
+ msg = freeme = g_strdup_printf("OTR: Error setting up private conversation: %u",
328
+ case OTRL_MSGEVENT_MSG_REFLECTED:
329
+ msg = "OTR: Received own OTR message!";
331
+ case OTRL_MSGEVENT_MSG_RESENT:
332
+ msg = "OTR: Previous message was resent.";
334
+ case OTRL_MSGEVENT_RCVDMSG_NOT_IN_PRIVATE:
335
+ msg = "OTR: Received encrypted message, but connection is not established " \
336
+ "yet! Message lost.";
338
+ case OTRL_MSGEVENT_RCVDMSG_UNREADABLE:
339
+ msg = "OTR: Unable to read incoming message!";
341
+ case OTRL_MSGEVENT_RCVDMSG_MALFORMED:
342
+ msg = "OTR: Malformed incoming message!";
344
+ case OTRL_MSGEVENT_LOG_HEARTBEAT_RCVD:
345
+ scr_log_print(LPRINT_DEBUG, "OTR: Received heartbeat.");
347
+ case OTRL_MSGEVENT_LOG_HEARTBEAT_SENT:
348
+ scr_log_print(LPRINT_DEBUG, "OTR: Sent heartbeat.");
350
+ case OTRL_MSGEVENT_RCVDMSG_GENERAL_ERR:
351
+ msg = freeme = g_strdup_printf("OTR: Received general otr error: %s",
354
+ case OTRL_MSGEVENT_RCVDMSG_UNENCRYPTED:
355
+ msg = freeme = g_strdup_printf("OTR: Received unencrypted message: %s",
358
+ case OTRL_MSGEVENT_RCVDMSG_UNRECOGNIZED:
359
+ msg = "OTR: Unable to determine type of received OTR message!";
361
+ case OTRL_MSGEVENT_RCVDMSG_FOR_OTHER_INSTANCE:
363
+ scr_log_print(LPRINT_DEBUG, "OTR: Received message for other instance.");
370
+ scr_WriteIncomingMessage(context->username, msg, 0, HBB_PREFIX_INFO, 0);
375
+#endif /* HAVE_LIBOTR3 */
378
* returns whether a otr_message was received
379
* sets *otr_data to NULL, when it was an internal otr message
383
char *newmessage = NULL;
385
OtrlTLV *tlvs = NULL;
390
ctx = otr_get_context(buddy);
392
ignore_message = otrl_message_receiving(userstate, &ops, NULL,
393
ctx->accountname, ctx->protocol,
394
ctx->username, *otr_data,
395
- &newmessage, &tlvs,NULL, NULL);
398
+ &newmessage, &tlvs, NULL, NULL);
400
tlv = otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED);
407
+ &newmessage, NULL, NULL, NULL, NULL);
412
@@ -410,13 +607,27 @@
414
if (ctx->msgstate == OTRL_MSGSTATE_PLAINTEXT)
415
err = otrl_message_sending(userstate, &ops, NULL, ctx->accountname,
417
ctx->protocol, ctx->username, *msg, NULL,
418
&newmessage, NULL, NULL);
421
+ ctx->protocol, ctx->username, OTRL_INSTAG_BEST,
422
+ *msg, NULL, &newmessage, OTRL_FRAGMENT_SEND_SKIP,
426
htmlmsg = html_escape(*msg);
427
err = otrl_message_sending(userstate, &ops, NULL, ctx->accountname,
429
ctx->protocol, ctx->username, htmlmsg, NULL,
430
&newmessage, NULL, NULL);
433
+ ctx->protocol, ctx->username, OTRL_INSTAG_BEST,
434
+ htmlmsg, NULL, &newmessage, OTRL_FRAGMENT_SEND_SKIP,
441
LM_MESSAGE_SUB_TYPE_NOT_SET, NULL);
444
-/* Display a notification message for a particular
445
- * accountname / protocol / username conversation. */
446
-static void cb_notify(void *opdata, OtrlNotifyLevel level,
447
- const char *accountname, const char *protocol,
448
- const char *username, const char *title,
449
- const char *primary, const char *secondary)
454
- case OTRL_NOTIFY_ERROR: type = "error"; break;
455
- case OTRL_NOTIFY_WARNING: type = "warning"; break;
456
- case OTRL_NOTIFY_INFO: type = "info"; break;
457
- default: type = "unknown";
459
- sbuf = g_strdup_printf("OTR %s:%s\n%s\n%s",type,title, primary, secondary);
460
- scr_WriteIncomingMessage(username, sbuf, 0, HBB_PREFIX_INFO, 0);
464
-/* Display an OTR control message for a particular
465
- * accountname / protocol / username conversation. Return 0 if you are able
466
- * to successfully display it. If you return non-0 (or if this
467
- * function is NULL), the control message will be displayed inline,
468
- * as a received message, or else by using the above notify()
470
-static int cb_display_otr_message(void *opdata, const char *accountname,
471
- const char *protocol, const char *username,
474
- char *strippedmsg = html_strip(msg);
475
- scr_WriteIncomingMessage(username, strippedmsg, 0, HBB_PREFIX_INFO, 0);
476
- g_free(strippedmsg);
480
/* When the list of ConnContexts changes (including a change in
481
* state), this is called so the UI can be updated. */
482
static void cb_update_context_list(void *opdata)
484
* then use this function (?!)*/
487
-/* Return a newly allocated string containing a human-friendly name
488
- * for the given protocol id */
489
-static const char *cb_protocol_name(void *opdata, const char *protocol)
494
-/* Deallocate a string allocated by protocol_name */
495
-static void cb_protocol_name_free (void *opdata, const char *protocol_name)
497
- /* We didn't allocated memory, so we don't have to free anything :p */
500
/* A new fingerprint for the given user has been received. */
501
static void cb_new_fingerprint(void *opdata, OtrlUserState us,
502
const char *accountname, const char *protocol,
503
@@ -748,12 +910,92 @@
509
+/* Display a notification message for a particular
510
+ * accountname / protocol / username conversation. */
511
+static void cb_notify(void *opdata, OtrlNotifyLevel level,
512
+ const char *accountname, const char *protocol,
513
+ const char *username, const char *title,
514
+ const char *primary, const char *secondary)
519
+ case OTRL_NOTIFY_ERROR: type = "error"; break;
520
+ case OTRL_NOTIFY_WARNING: type = "warning"; break;
521
+ case OTRL_NOTIFY_INFO: type = "info"; break;
522
+ default: type = "unknown";
524
+ sbuf = g_strdup_printf("OTR %s:%s\n%s\n%s",type,title, primary, secondary);
525
+ scr_WriteIncomingMessage(username, sbuf, 0, HBB_PREFIX_INFO, 0);
529
+/* Display an OTR control message for a particular
530
+ * accountname / protocol / username conversation. Return 0 if you are able
531
+ * to successfully display it. If you return non-0 (or if this
532
+ * function is NULL), the control message will be displayed inline,
533
+ * as a received message, or else by using the above notify()
535
+static int cb_display_otr_message(void *opdata, const char *accountname,
536
+ const char *protocol, const char *username,
539
+ char *strippedmsg = html_strip(msg);
540
+ scr_WriteIncomingMessage(username, strippedmsg, 0, HBB_PREFIX_INFO, 0);
541
+ g_free(strippedmsg);
545
+/* Return a newly allocated string containing a human-friendly name
546
+ * for the given protocol id */
547
+static const char *cb_protocol_name(void *opdata, const char *protocol)
552
+/* Deallocate a string allocated by protocol_name */
553
+static void cb_protocol_name_free (void *opdata, const char *protocol_name)
555
+ /* We didn't allocated memory, so we don't have to free anything :p */
558
/* Log a message. The passed message will end in "\n". */
559
static void cb_log_message(void *opdata, const char *message)
561
scr_LogPrint(LPRINT_DEBUG, "OTR: %s", message);
564
+#else /* HAVE_LIBOTR3 */
566
+/* Generate unique instance tag for account. */
567
+static void cb_create_instag(void *opdata, const char *accountname,
568
+ const char *protocol)
570
+ if (otrl_instag_generate(userstate, tagfile, accountname, protocol)) {
571
+ scr_LogPrint(LPRINT_LOGNORM, "OTR instance tag generation failed!");
575
+static gboolean otr_timer_cb(gpointer userdata)
577
+ otrl_message_poll(userstate, &ops, userdata);
581
+static void cb_timer_control(void *opdata, unsigned int interval)
583
+ if (otr_timer_source > 0) {
584
+ g_source_remove(otr_timer_source);
585
+ otr_timer_source = 0;
588
+ otr_timer_source = g_timeout_add_seconds(interval, otr_timer_cb, opdata);
591
+#endif /* HAVE_LIBOTR3 */
593
/* Find the maximum message size supported by this protocol. */
594
static int cb_max_message_size(void *opdata, ConnContext *context)
596
diff -r 1b31bdb72d83 mcabber/mcabber/otr.h
597
--- a/mcabber/otr.h Sun Jan 13 04:35:32 2013 +0200
598
+++ b/mcabber/otr.h Fri Jan 18 11:23:47 2013 +0200
603
+#ifndef HAVE_LIBOTR3
604
+# include <libotr/instag.h>
606
#include <libotr/proto.h>
607
#include <libotr/message.h>
608
#include <libotr/privkey.h>