2 # define C_FUNCTION extern "C"
3 # define PROTO_NAME "psyc"
7 ///////////////////////////////////////////////////////////////////////////////
10 static char *strToC (const QString
&s
) {
11 //QTextCodec *tc = QTextCodec::codecForCStrings();
12 QTextCodec
*tc
= QTextCodec::codecForLocale();
14 if (tc
) ba
= tc
->fromUnicode(s
); else ba
= s
.toLatin1();
15 char *res
= (char *)malloc(ba
.size()+8);
16 strcpy(res
, ba
.constData());
17 res
[ba
.size()] = '\0';
23 static FILE *qxfopen (char *fname
, bool readOnly
) {
26 if (!mQF
.open(readOnly
? QIODevice::ReadOnly
: QIODevice::ReadWrite
)) return 0;
27 int hh
= dup(mQF
.handle());
29 FILE *res
= fdopen(hh
, readOnly
? "rb" : "r+b");
36 char *ChatForm::getOTRKeyFile (void) {
38 QString
otp(settingsDBPath(mAccName
));
41 otp
.append("keys.otr");
46 char *ChatForm::getOTRFingerFile (void) {
48 QString
otp(settingsDBPath(mAccName
));
51 otp
.append("fingers.otr");
56 /* Return a pointer to a newly-allocated OTR query message, customized
57 * with our name. The caller should free() the result when he's done
59 static char *otrDefaultQueryMsg (const char *ourname
, OtrlPolicy policy
) {
60 char *msg
= otrl_proto_default_query_msg(ourname
, policy
);
61 char *e
= strchr(msg
, '\n');
63 char *res
= (char *)malloc(8192); //???
66 "%s\n%s has requested an Off-the-Record private conversation.\n"
67 "However, you do not have a plugin to support that.\n"
68 "See http://otr.cypherpunks.ca/ for more information.",
76 ///////////////////////////////////////////////////////////////////////////////
77 // return the OTR policy for the given context
78 C_FUNCTION OtrlPolicy
otrPolicyCB (void *opdata
, ConnContext
*context
) {
79 //ChatForm *mForm = static_cast<ChatForm *>(opdata);
82 //!dlogf("otrPolicyCB()\n");
83 return OTRL_POLICY_OPPORTUNISTIC
;
87 ///////////////////////////////////////////////////////////////////////////////
88 class GenKeyThread
: public QThread
{
94 const char *protoName
;
98 void GenKeyThread::run () {
100 FILE *fl
= qxfopen(mForm
->getOTRKeyFile(), false);
102 mError
= otrl_privkey_generate_FILEp(mForm
->mOTRState
, fl
, accName
, protoName
) != 0;
108 void ChatForm::genOTRKey (const char *accName
, const char *protoName
) {
109 GenKeyWin
*gkw
= new GenKeyWin(accName
, this);
112 //!dlogf("dialog shown");
116 gtrd
.accName
= accName
;
117 gtrd
.protoName
= protoName
;
118 connect(>rd
, SIGNAL(finished()), &eloop
, SLOT(quit()));
120 //!dlogf("thread started");
123 //!dlogf("all done");
124 //TODO: check for error!
129 // create a private key for the given accountname/protocol if desired
130 C_FUNCTION
void otrCreateKeyCB (void *opdata
, const char *accName
, const char *protoName
) {
134 ChatForm
*mForm
= static_cast<ChatForm
*>(opdata
);
135 //!dlogf("otrCreateKeyCB(): acc:[%s]; proto:[%s]\n", accName, protoName);
136 //!dlogf(" otrl_privkey_generate()...");
137 mForm
->genOTRKey(accName
, protoName
);
138 //otrl_privkey_generate(mOTRState, mForm->getOTRKeyFile(), accName, protoName);
143 ///////////////////////////////////////////////////////////////////////////////
144 /* Report whether you think the given user is online. Return 1 if
145 * you think he is, 0 if you think he isn't, -1 if you're not sure.
147 * If you return 1, messages such as heartbeats or other
148 * notifications may be sent to the user, which could result in "not
149 * logged in" errors if you're wrong. */
150 C_FUNCTION
int otrIsLoggedInCB (void *opdata
, const char *accName
, const char *protoName
, const char *recipient
) {
155 ChatForm
*mForm
= static_cast<ChatForm
*>(opdata
);
156 //!dlogf("otrIsLoggedInCB(): acc:[%s]; proto:[%s]; rcp:[%s]\n", accName, protoName, recipient);
157 if (!mForm
|| !recipient
|| !recipient
[0]) return 0;
158 PsycContact
*cc
= mForm
->findContact(recipient
);
159 if (!cc
|| cc
->isPlace()) return 0;
160 switch (cc
->status()) {
161 case PsycProto::Internal
:
162 case PsycProto::Offline
:
171 ///////////////////////////////////////////////////////////////////////////////
172 // send the given IM to the given recipient from the given accountname/protocol
173 C_FUNCTION
void otrSendMessageCB (void *opdata
, const char *accName
, const char *protoName
,
174 const char *recipient
, const char *message
)
181 ChatForm
*mForm
= static_cast<ChatForm
*>(opdata
);
182 //dlogf("otrSendMessageCB(): acc:[%s]; proto:[%s]; rcp:[%s]\nmsg:[%s]\n", accName, protoName, recipient, message);
183 //!dlogf("otrSendMessageCB(): acc:[%s]; proto:[%s]; rcp:[%s]\n", accName, protoName, recipient);
184 if (!mForm
->proto()) return;
185 mForm
->proto()->sendMessage(QString(recipient
), QString::fromUtf8(message
), QString());
189 ///////////////////////////////////////////////////////////////////////////////
190 // display a notification message for a particular accountname/protocol/username conversation
191 C_FUNCTION
void otrNotifyCB (void *opdata
, OtrlNotifyLevel level
, const char *accName
, const char *protoName
,
192 const char *userName
, const char *title
, const char *primary
, const char *secondary
)
202 //ChatForm *mForm = static_cast<ChatForm *>(opdata);
203 dlogf("otrNotifyCB(): acc:[%s]; proto:[%s]; user:[%s]\ntitle:[%s]\nprim:[%s]\nsec:[%s]\n",
204 accName
, protoName
, userName
, title
, primary
, secondary
);
206 case OTRL_NOTIFY_ERROR
:
207 dlogf(" OTRL_NOTIFY_ERROR\n");
209 case OTRL_NOTIFY_WARNING
:
210 dlogf(" OTRL_NOTIFY_WARNING\n");
212 case OTRL_NOTIFY_INFO
:
213 dlogf(" OTRL_NOTIFY_INFO\n");
220 ///////////////////////////////////////////////////////////////////////////////
221 /* Display an OTR control message for a particular accountname /
222 * protocol / username conversation. Return 0 if you are able to
223 * successfully display it. If you return non-0 (or if this
224 * function is NULL), the control message will be displayed inline,
225 * as a received message, or else by using the above notify()
227 C_FUNCTION
int otrDisplayMessageCB (void *opdata
, const char *accName
, const char *protoName
,
228 const char *userName
, const char *msg
)
235 //ChatForm *mForm = static_cast<ChatForm *>(opdata);
236 dlogf("otrDisplayMessageCB(): acc:[%s]; proto:[%s]; user:[%s]\nmsg:[%s]\n",
237 accName
, protoName
, userName
, msg
);
242 ///////////////////////////////////////////////////////////////////////////////
243 // When the list of ConnContexts changes (including a change in state), this is called so the UI can be updated
244 C_FUNCTION
void otrUpdateContextListCB (void *opdata
) {
246 ChatForm
*mForm
= static_cast<ChatForm
*>(opdata
);
247 //!dlogf("otrUpdateContextListCB()\n");
248 ConnContext
*context
= mForm
->mOTRState
->context_root
;
250 ConnContext
*next
= context
->next
;
251 PsycContact
*cc
= mForm
->findContact(context
->username
);
253 cc
->setOTRVerified(context
->active_fingerprint
&& context
->active_fingerprint
->trust
&&
254 (!strcmp(context
->active_fingerprint
->trust
, "verified") || !strcmp(context
->active_fingerprint
->trust
, "smp"))
256 if (cc
->isOTRActive() != (context
->msgstate
== OTRL_MSGSTATE_ENCRYPTED
)) {
257 cc
->setOTRActive(context
->msgstate
== OTRL_MSGSTATE_ENCRYPTED
);
258 mForm
->redrawContact(cc
);
266 ///////////////////////////////////////////////////////////////////////////////
267 /* Return a newly-allocated string containing a human-friendly name
268 * for the given protocol id */
269 C_FUNCTION
const char *otrProtoNameCB (void *opdata
, const char *protoName
) {
272 //ChatForm *mForm = static_cast<ChatForm *>(opdata);
273 //!dlogf("otrProtoNameCB(): proto:[%s]\n", protoName);
278 ///////////////////////////////////////////////////////////////////////////////
279 /* Deallocate a string allocated by protocol_name */
280 C_FUNCTION
void otrProtoNameFreeCB (void *opdata
, const char *protoName
) {
283 //ChatForm *mForm = static_cast<ChatForm *>(opdata);
284 //!dlogf("otrProtoNameFreeCB(): proto:[%s]\n", protoName);
288 ///////////////////////////////////////////////////////////////////////////////
289 /* A new fingerprint for the given user has been received. */
290 C_FUNCTION
void otrNewFingerCB (void *opdata
, OtrlUserState us
, const char *accName
, const char *protoName
,
291 const char *userName
, unsigned char fingerprint
[20])
298 Q_UNUSED(fingerprint
)
299 ChatForm
*mForm
= static_cast<ChatForm
*>(opdata
);
300 //!dlogf("otrNewFingerCB(): acc:[%s]; proto:[%s]; user:[%s]\n", accName, protoName, userName);
301 ConnContext
*context
= otrl_context_find(us
, userName
, accName
, protoName
, TRUE
, 0, NULL
/*add_appdata*/, NULL
/*opdata*/);
302 Fingerprint
*fp
= otrl_context_find_fingerprint(context
, fingerprint
, TRUE
, 0);
305 otrl_privkey_hash_to_human(hash
, fp
->fingerprint
);
306 //!dlogf(" hash: [%s]\n", hash);
307 QMessageBox::StandardButton qres
=
308 QMessageBox::question(mForm
, "Dyskinesia: new OTR fingerprint",
309 QString("New OTR fingerpring received from %1.\n%2\nDo you trust it?").arg(userName
).arg(hash
),
310 QMessageBox::Yes
| QMessageBox::No
, QMessageBox::Yes
);
311 if (qres
== QMessageBox::Yes
) otrl_context_set_trust(fp
, "verified");
312 else otrl_context_set_trust(fp
, "unknown");
313 FILE *fl
= qxfopen(mForm
->getOTRFingerFile(), false);
315 otrl_privkey_write_fingerprints_FILEp(mForm
->mOTRState
, fl
);
322 ///////////////////////////////////////////////////////////////////////////////
323 /* The list of known fingerprints has changed. Write them to disk. */
324 C_FUNCTION
void otrWriteFingersCB (void *opdata
) {
326 ChatForm
*mForm
= static_cast<ChatForm
*>(opdata
);
327 //!dlogf("otrWriteFingersCB()\n");
328 FILE *fl
= qxfopen(mForm
->getOTRFingerFile(), false);
330 otrl_privkey_write_fingerprints_FILEp(mForm
->mOTRState
, fl
);
336 ///////////////////////////////////////////////////////////////////////////////
337 /* A ConnContext has entered a secure state. */
338 C_FUNCTION
void otrGoneSecureCB (void *opdata
, ConnContext
*context
) {
341 ChatForm
*mForm
= static_cast<ChatForm
*>(opdata
);
342 dlogf("otrGoneSecureCB()\n");
343 int trusted
= (context
->active_fingerprint
&& context
->active_fingerprint
->trust
&&
344 (!strcmp(context
->active_fingerprint
->trust
, "verified") || !strcmp(context
->active_fingerprint
->trust
, "smp"))
346 PsycContact
*cc
= mForm
->findContact(context
->username
);
347 //!k8:if (cc) cc->setOTRActive(true);
349 dlogf(" Beginning OTR encrypted session with [%s]", context
->username
);
350 if (cc
) cc
->setOTRVerified(true);
351 // opdata is hContact
352 //SetEncryptionStatus((HANDLE)opdata, true);
354 //!!CloseHandle((HANDLE)_beginthreadex(0, 0, verify_fp_thread, context, 0, 0));
355 dlogf(" Beginning OTR encrypted session with [%s] (NOT VERIFIED)", context
->username
);
356 if (cc
) cc
->setOTRVerified(false);
357 // opdata is hContact
358 //SetEncryptionStatus((HANDLE)opdata, true);
360 //!k8:if (cc) mForm->redrawContact(cc);
364 ///////////////////////////////////////////////////////////////////////////////
365 // a ConnContext has left a secure state
366 C_FUNCTION
void otrGoneInsecureCB (void *opdata
, ConnContext
*context
) {
369 ChatForm
*mForm
= static_cast<ChatForm
*>(opdata
);
370 //dlogf("otrGoneInsecureCB()\n");
371 dlogf(" OTR encrypted session with [%s] has ended", context
->username
);
373 PsycContact *cc = mForm->findContact(context->username);
374 if (cc && cc->isOTRActive()) {
375 cc->setOTRActive(false);
376 mForm->redrawContact(cc);
379 mForm
->otrDisconnect(context
->username
);
380 // opdata is hContact
381 //SetEncryptionStatus((HANDLE)opdata, false);
385 ///////////////////////////////////////////////////////////////////////////////
386 /* We have completed an authentication, using the D-H keys we
387 * already knew. isReply indicates whether we initiated the AKE. */
388 C_FUNCTION
void otrStillSecureCB (void *opdata
, ConnContext
*context
, int isReply
) {
392 //ChatForm *mForm = static_cast<ChatForm *>(opdata);
394 dlogf("otrStillSecureCB()\n");
396 dlogf(" OTR encrypted session with [%s] is being continued", context->username);
400 PsycContact *cc = mForm->findContact(context->username);
401 if (cc && !cc->isOTRActive()) {
402 cc->setOTRActive(true);
403 mForm->redrawContact(cc);
406 // opdata is hContact
407 //SetEncryptionStatus((HANDLE)opdata, true);
411 ///////////////////////////////////////////////////////////////////////////////
412 /* Log a message. The passed message will end in "\n". */
413 C_FUNCTION
void otrLogCB (void *opdata
, const char *message
) {
414 //ChatForm *mForm = static_cast<ChatForm *>(opdata);
417 dlogf("otrLogCB: >>%s", message
);
421 ///////////////////////////////////////////////////////////////////////////////
422 C_FUNCTION
int otrMaxMessageSizeCB (void *opdata
, ConnContext
*context
) {
423 //ChatForm *mForm = static_cast<ChatForm *>(opdata);
426 //dlogf("max_message_size()\n");
432 ///////////////////////////////////////////////////////////////////////////////
433 C_FUNCTION const char *otrAccountNameCB (void *opdata, const char *accName, const char *protoName) {
434 ChatForm *mForm = static_cast<ChatForm *>(opdata);
435 dlogf("account_name(): acc:[%s]; proto:[%s]\n", accName, protoName);
439 ///////////////////////////////////////////////////////////////////////////////
440 C_FUNCTION void otrAccountNameFreeCB(void *opdata, const char *accName) {
441 ChatForm *mForm = static_cast<ChatForm *>(opdata);
442 dlogf("account_name_free(): acc:[%s]\n", accName);
447 static OtrlMessageAppOps ops
= {
454 otrUpdateContextListCB
,
464 NULL
, /* account_name */
465 NULL
/* account_name_free */
473 ///////////////////////////////////////////////////////////////////////////////
474 void ChatForm::otrSendMessage (const QString
&auni
, const QString
&txt
, const QString
&act
) {
475 QString
uni(auni
.toLower());
476 PsycContact
*cc
= findContact(uni
);
477 if (!cc
|| cc
->isPlace() || !cc
->isOTRActive() || txt
.startsWith("?OTR")) {
478 // internal OTR message or room message
479 mProto
->sendMessage(uni
, txt
, act
);
481 // not OTR message, encrypt it
484 QByteArray
me(mProto
->uni().toLower().toUtf8());
485 QByteArray
to(uni
.toUtf8());
486 QByteArray
msg(txt
.toUtf8());
487 err
= otrl_message_sending(mOTRState
, &ops
, (void *)this, me
, PROTO_NAME
, to
, msg
, 0, &newMsg
, 0, 0);
489 dlogf("failure to encrypt message!\n");
493 dlogf("WTF?! an empty OTR resulting message!\n");
494 mProto
->sendMessage(uni
, txt
, act
);
497 //QByteArray mx(newMsg);
498 //mProto->sendMessage(uni, mx, act);
499 ConnContext
*context
= otrl_context_find(mOTRState
, to
, me
, PROTO_NAME
, FALSE
, 0, 0, 0);
502 err
= otrl_message_fragment_and_send(&ops
, (void *)this, context
, newMsg
, OTRL_FRAGMENT_SEND_ALL
, &frag
);
503 if (frag
) free(frag
);
505 dlogf("WTF?! no context found for otrl_message_fragment_and_send()\n");
507 otrl_message_free(newMsg
);
512 ///////////////////////////////////////////////////////////////////////////////
513 QString
ChatForm::otrGotMessage (const QString
&auni
, const QString
&txt
) {
519 QString
uni(auni
.toLower());
520 QByteArray
me(mProto
->uni().toLower().toUtf8());
521 QByteArray
sender(uni
.toUtf8());
522 QByteArray
msg(txt
.toUtf8());
523 isInternal
= otrl_message_receiving(mOTRState
, &ops
, (void *)this, me
, PROTO_NAME
, sender
, msg
,
524 &newMsg
, &tlvs
, NULL
, NULL
);
525 ConnContext
*context
= otrl_context_find(mOTRState
, sender
, me
, PROTO_NAME
, FALSE
, 0, 0, 0);
527 bool disconnected
= false;
528 tlv
= otrl_tlv_find(tlvs
, OTRL_TLV_DISCONNECTED
);
529 if (tlv
) disconnected
= true;
533 if (context->smstate->sm_prog_state == OTRL_SMP_PROG_CHEATED) {
534 otrg_plugin_abort_smp(context);
535 otrg_dialog_update_smp(context, 0.0);
536 context->smstate->nextExpected = OTRL_SMP_EXPECT1;
537 context->smstate->sm_prog_state = OTRL_SMP_PROG_OK;
542 NextExpectedSMP nextMsg
= context
->smstate
->nextExpected
;
543 bool abortIt
= false;
544 QString smpQuestion
, smpSecret
;
545 tlv
= otrl_tlv_find(tlvs
, OTRL_TLV_SMP1Q
);
547 // SMP query with question
548 if (nextMsg
!= OTRL_SMP_EXPECT1
) {
550 dlogf("OTR: SMP error! aborted!\n");
553 // question should be here
554 const char *question
= (const char *)tlv
->data
;
555 const char *eoq
= (const char *)memchr(question
, '\0', tlv
->len
);
557 if (question
[0]) smpQuestion
= QString("secret question:\n%1").arg(QString::fromUtf8(question
));
558 else smpQuestion
= tr("input secret:");
559 } else abortIt
= true;
562 tlv
= otrl_tlv_find(tlvs
, OTRL_TLV_SMP1
);
564 // SMP query without question
565 if (nextMsg
!= OTRL_SMP_EXPECT1
) {
567 dlogf("OTR: SMP error! aborted!\n");
570 smpQuestion
= tr("input secret:");
574 if (!abortIt
&& !smpQuestion
.isEmpty()) {
577 smpQuestion
= QString("OTR SMP query from %1\n%2").arg(auni
).arg(smpQuestion
);
578 reply
= QInputDialog::getText(this, "OTR SMP query", smpQuestion
, QLineEdit::Normal
, QString(), &ok
);
579 if (!ok
|| reply
.isEmpty()) abortIt
= true;
582 QByteArray
ba(smpSecret
.toUtf8());
583 otrl_message_respond_smp(mOTRState
, &ops
, (void *)this, context
, (const unsigned char *)ba
.constData(), ba
.size());
587 tlv
= otrl_tlv_find(tlvs
, OTRL_TLV_SMP2
);
589 if (nextMsg
!= OTRL_SMP_EXPECT2
) abortIt
= true;
591 // If we received TLV2, we will send TLV3 and expect TLV4
592 context
->smstate
->nextExpected
= OTRL_SMP_EXPECT4
;
596 tlv
= otrl_tlv_find(tlvs
, OTRL_TLV_SMP3
);
598 // SMP initiated by the other side
599 if (nextMsg
!= OTRL_SMP_EXPECT3
) abortIt
= true;
601 // If we received TLV3, we will send TLV4
602 // We will not expect more messages, so prepare for next SMP
603 context
->smstate
->nextExpected
= OTRL_SMP_EXPECT1
;
604 // Report result to user
605 dlogf("1: OTR SMP: [%s]\n", context
->active_fingerprint
->trust
? context
->active_fingerprint
->trust
: "(null)");
606 otrSetTrust(auni
, context
->active_fingerprint
->trust
&&
607 (!strcmp(context
->active_fingerprint
->trust
, "verified") || !strcmp(context
->active_fingerprint
->trust
, "smp"))
610 if (context->active_fingerprint->trust && context->active_fingerprint->trust[0]) otrSetTrust(auni, true);
611 else otrSetTrust(auni, false);
616 tlv
= otrl_tlv_find(tlvs
, OTRL_TLV_SMP4
);
618 // SMP initiated by us
619 if (nextMsg
!= OTRL_SMP_EXPECT4
) abortIt
= true;
621 // We will not expect more messages, so prepare for next SMP
622 context
->smstate
->nextExpected
= OTRL_SMP_EXPECT1
;
623 // Report result to user
624 dlogf("0: OTR SMP: [%s]\n", context
->active_fingerprint
->trust
? context
->active_fingerprint
->trust
: "(null)");
625 if (context
->active_fingerprint
->trust
&& context
->active_fingerprint
->trust
[0]) otrSetTrust(auni
, true);
626 else otrSetTrust(auni
, false);
630 tlv
= otrl_tlv_find(tlvs
, OTRL_TLV_SMP_ABORT
);
632 // The message we are waiting for will not arrive, so reset and prepare for the next SMP
633 otrl_message_abort_smp(mOTRState
, &ops
, (void *)this, context
);
634 context
->smstate
->nextExpected
= OTRL_SMP_EXPECT1
;
637 if (abortIt
) otrl_message_abort_smp(mOTRState
, &ops
, (void *)this, context
);
641 if (tlvs
) otrl_tlv_free(tlvs
);
644 dlogf("internal message\n");
645 if (newMsg
) otrl_message_free(newMsg
);
647 dlogf("[%s] has terminated the OTR session\n", me
.constData());
653 // it may not be encrypted however (e.g. tagged plaintext with tags stripped)
654 //!if (context && context->msgstate == OTRL_MSGSTATE_PLAINTEXT) dlogf("PLAIN TEXT!\n");
658 QByteArray
ba(txt
.toUtf8());
659 dlogf("plain message: [%s]\n", ba
.constData());
662 res
= QString::fromUtf8(newMsg
);
663 dlogf("decrypted message: [%s]\n", newMsg
);
666 if (newMsg
) otrl_message_free(newMsg
);
669 dlogf("[%s] has terminated the OTR session\n", me
.constData());
675 ///////////////////////////////////////////////////////////////////////////////
679 const QString
ChatForm::otrGetFinger (const QString
&aUNI
) {
682 PsycContact
*cc
= findContact(aUNI
);
683 if (!cc
|| cc
->isPlace()) return QString();
684 QByteArray
me(mProto
->uni().toLower().toUtf8());
685 QByteArray
usr(aUNI
.toLower().toUtf8());
686 ConnContext
*context
= otrl_context_find(mOTRState
, usr
, me
, PROTO_NAME
, false, 0, NULL
, NULL
);
687 if (context
&& context
->active_fingerprint
) {
689 otrl_privkey_hash_to_human(hash
, context
->active_fingerprint
->fingerprint
);
690 return QString(hash
);
697 void ChatForm::otrSetTrust (const QString
&aUNI
, bool tflag
) {
701 PsycContact
*cc
= findContact(aUNI
);
702 if (!cc
|| cc
->isPlace()) return;
703 QByteArray
me(mProto
->uni().toLower().toUtf8());
704 QByteArray
usr(aUNI
.toLower().toUtf8());
705 ConnContext
*context
= otrl_context_find(mOTRState
, usr
, me
, PROTO_NAME
, false, 0, NULL
, NULL
);
706 if (context
&& context
->active_fingerprint
) {
707 otrl_context_set_trust(context
->active_fingerprint
, tflag
? "verified" : "unknown");
709 if (cc
->isOTRVerified() != tflag
) {
710 cc
->setOTRVerified(tflag
);
717 void ChatForm::otrForget (const QString
&aUNI
) {
720 PsycContact
*cc
= findContact(aUNI
);
721 if (!cc
|| cc
->isPlace()) return;
723 QByteArray
me(mProto
->uni().toLower().toUtf8());
724 QByteArray
usr(aUNI
.toLower().toUtf8());
725 ConnContext
*context
= otrl_context_find(mOTRState
, usr
, me
, PROTO_NAME
, false, 0, NULL
, NULL
);
727 otrl_context_forget(context
);
728 cc
->setOTRVerified(false);
735 void ChatForm::otrInitiateSMP (const QString
&aUNI
, const QString
&secret
, const QString
&question
) {
740 PsycContact
*cc
= findContact(aUNI
);
741 if (!cc
|| cc
->isPlace() || !cc
->isOTRActive()) return;
742 //cc->setOTRVerified(false);
744 QByteArray
me(mProto
->uni().toLower().toUtf8());
745 QByteArray
user(aUNI
.toLower().toUtf8());
746 ConnContext
*context
= otrl_context_find(mOTRState
, user
, me
, PROTO_NAME
, FALSE
, 0, 0, 0);
747 if (context
&& !secret
.isEmpty()) {
748 otrSetTrust(aUNI
, false);
749 QByteArray
ba(secret
.toUtf8());
750 if (!question
.isEmpty()) {
751 QByteArray
ba1(question
.toUtf8());
752 otrl_message_initiate_smp_q(mOTRState
, &ops
, (void *)this, context
, ba1
.constData(), (const unsigned char *)ba
.constData(), ba
.size());
754 otrl_message_initiate_smp(mOTRState
, &ops
, (void *)this, context
, (const unsigned char *)ba
.constData(), ba
.size());
761 void ChatForm::deactivateAllOTR () {
762 foreach (PsycContact
*cc
, mContactList
) {
763 cc
->setOTRVerified(false);
764 if (cc
->isOTRActive()) {
765 cc
->setOTRActive(false);
772 void ChatForm::disconnectAllOTR () {
776 ConnContext
*context
= mOTRState
->context_root
;
778 ConnContext
*next
= context
->next
;
779 if (context
->msgstate
== OTRL_MSGSTATE_ENCRYPTED
&& context
->protocol_version
> 1) {
780 otrDisconnect(context
->username
);
781 //otrl_message_disconnect(mOTRState, &ops, (void *)this, context->accountname, context->protocol, context->username);
790 void ChatForm::otrDisconnect (const QString
&uni
) {
792 QByteArray
user(uni
.toLower().toUtf8());
793 QByteArray
me(mProto
->uni().toLower().toUtf8());
794 dlogf(" sending OTR disconnect to [%s]", user
.constData());
795 otrl_message_disconnect(mOTRState
, &ops
, (void *)this, me
, PROTO_NAME
, user
);
800 PsycContact *cc = findContact(uni);
801 if (cc && cc->isOTRActive()) {
802 cc->setOTRActive(false);
809 void ChatForm::otrConnect (const QString
&uni
) {
811 QByteArray
me(mProto
->uni().toLower().toUtf8());
812 QByteArray
to(uni
.toLower().toUtf8());
813 char *msg
= otrDefaultQueryMsg(me
.constData(), OTRL_POLICY_OPPORTUNISTIC
);
814 otrSendMessageCB((void *)this, me
.constData(), PROTO_NAME
, to
.constData(), msg
? msg
: "?OTRv2?");