1 diff -urN kdenetwork-4.10.5.org/kopete/cmake/modules/FindLibOTR.cmake kdenetwork-4.10.5/kopete/cmake/modules/FindLibOTR.cmake
2 --- kdenetwork-4.10.5.org/kopete/cmake/modules/FindLibOTR.cmake 2013-06-28 20:08:21.924065636 +0200
3 +++ kdenetwork-4.10.5/kopete/cmake/modules/FindLibOTR.cmake 2013-07-10 21:40:19.770555778 +0200
5 EXECUTE_PROCESS(COMMAND grep "OTRL_VERSION" "${LIBOTR_INCLUDE_DIR}/libotr/version.h" OUTPUT_VARIABLE output)
6 STRING(REGEX MATCH "OTRL_VERSION \"[0-9]+\\.[0-9]+\\.[0-9]+" LIBOTR_VERSION "${output}")
7 STRING(REGEX REPLACE "^OTRL_VERSION \"" "" LIBOTR_VERSION "${LIBOTR_VERSION}")
8 - # Check if version is at least 3.2.0
9 - MACRO_ENSURE_VERSION_RANGE("3.2.0" ${LIBOTR_VERSION} "4.0.0" LIBOTR_FOUND)
10 + # Check if version is at least 4.0.0
11 + MACRO_ENSURE_VERSION_RANGE("4.0.0" ${LIBOTR_VERSION} "5.0.0" LIBOTR_FOUND)
14 IF( NOT LIBOTR_FIND_QUIETLY )
15 MESSAGE( STATUS "Found libotr: ${LIBOTR_LIBRARY} (version ${LIBOTR_VERSION})")
16 ENDIF( NOT LIBOTR_FIND_QUIETLY )
18 - MESSAGE(STATUS "libotr version between 3.2.0 and 4.0.0 required but found ${LIBOTR_VERSION}.")
19 + MESSAGE(STATUS "libotr version between 4.0.0 and 5.0.0 required but found ${LIBOTR_VERSION}.")
22 ENDIF( LIBOTR_INCLUDE_DIR AND LIBOTR_LIBRARY )
23 diff -urN kdenetwork-4.10.5.org/kopete/CMakeLists.txt kdenetwork-4.10.5/kopete/CMakeLists.txt
24 --- kdenetwork-4.10.5.org/kopete/CMakeLists.txt 2013-06-28 20:08:21.923065596 +0200
25 +++ kdenetwork-4.10.5/kopete/CMakeLists.txt 2013-07-10 21:41:02.638700604 +0200
27 # TODO: fix otr plugin to make it work sith LibOTR 4
28 macro_optional_find_package(LibOTR)
29 macro_bool_to_01(LIBOTR_FOUND HAVE_LIBOTR)
30 -macro_log_feature(LIBOTR_FOUND "libotr" "A library to encrypt messages with Off-the-Record encryption (versions 3.2.0 to 4.0.0)" "http://www.cypherpunks.ca/otr" FALSE "3.2.0" "Required for the Kopete otr plugin.")
31 +macro_log_feature(LIBOTR_FOUND "libotr" "A library to encrypt messages with Off-the-Record encryption (versions 4.0.0 to 5.0.0)" "http://www.cypherpunks.ca/otr" FALSE "5.0.0" "Required for the Kopete otr plugin.")
33 macro_optional_find_package(Libmsn)
34 macro_bool_to_01(LIBMSN_FOUND HAVE_LIBMSN)
35 diff -urN kdenetwork-4.10.5.org/kopete/plugins/otr/authenticationwizard.cpp kdenetwork-4.10.5/kopete/plugins/otr/authenticationwizard.cpp
36 --- kdenetwork-4.10.5.org/kopete/plugins/otr/authenticationwizard.cpp 2013-06-28 20:08:21.435046148 +0200
37 +++ kdenetwork-4.10.5/kopete/plugins/otr/authenticationwizard.cpp 2013-07-10 21:39:55.593055323 +0200
39 /*************************************************************************
40 - * Copyright <2007> <Michael Zanetti> <michael_zanetti@gmx.net> *
41 + * Copyright <2007 - 2013> <Michael Zanetti> <mzanetti@kde.org> *
43 * This program is free software; you can redistribute it and/or *
44 * modify it under the terms of the GNU General Public License as *
46 setAttribute(Qt::WA_DeleteOnClose);
48 setPage(Page_SelectMethod, createIntroPage());
49 - setPage(Page_QuestionAnswer, createQAPage());
50 - setPage(Page_SharedSecret, createSSPage());
51 - setPage(Page_ManualVerification, createMVPage());
52 + setPage(Page_QuestionAnswer, createQAPage());
53 + setPage(Page_SharedSecret, createSSPage());
54 + setPage(Page_ManualVerification, createMVPage());
55 setPage(Page_Wait1, new WaitPage(i18n("Waiting for %1...", OtrlChatInterface::self()->formatContact(session->members().first()->contactId()))));
56 setPage(Page_Wait2, new WaitPage(i18n("Checking if answers match...")));
57 setPage(Page_Final, createFinalPage());
59 if ( session->account()->isBusy() )
62 + resize(rbMV->width() * 1.5, rbMV->width() * 0.75);
66 if ( !session->view()->mainWidget() || !session->view()->mainWidget()->isActiveWindow() ) {
67 KNotification *notification = new KNotification( "kopete_info_event", KNotification::CloseWhenWidgetActivated | KNotification::CloseOnTimeout );
68 notification->setText( i18n( "Incoming authentication request from %1", OtrlChatInterface::self()->formatContact( session->members().first()->contactId() ) ) );
70 connect( notification, SIGNAL(activated(uint)), SLOT(notificationActivated(uint)) );
71 notification->sendEvent();
79 return wizardList.at(i);
86 QWizardPage *AuthenticationWizard::createIntroPage(){
88 rbQA = new QRadioButton(i18n("Question and Answer"));
89 rbSS = new QRadioButton(i18n("Shared Secret"));
90 rbMV = new QRadioButton(i18n("Manual fingerprint verification"));
93 QGroupBox *frame = new QGroupBox();
94 QVBoxLayout *frameLayout = new QVBoxLayout();
95 frame->setLayout(frameLayout);
97 frameLayout->addWidget(infoLabel);
99 QVBoxLayout *layout = new QVBoxLayout();
100 - layout->addWidget(rbQA);
101 - layout->addWidget(rbSS);
102 + layout->addWidget(rbQA);
103 + layout->addWidget(rbSS);
104 layout->addWidget(rbMV);
106 layout->addSpacing(30);
109 page->setLayout(layout);
111 - rbQA->setChecked(true);
112 + rbQA->setChecked(true);
117 layout->addWidget(new QLabel(i18nc("@info", "Enter the secret passphrase known only to you and %1:", session->members().first()->contactId())));
119 leSecret = new QLineEdit();
120 - layout->addWidget(leSecret);
121 + layout->addWidget(leSecret);
123 page->setLayout(layout);
124 page->setCommitPage(true);
126 QLabel *lMessage1 = new QLabel(i18nc("@info", "Contact %1 via another secure channel and verify that the following fingerprint is correct:", session->members().first()->contactId()));
127 lMessage1->setWordWrap(true);
128 layout->addWidget(lMessage1);
129 - layout->addWidget(new QLabel(OtrlChatInterface::self()->findActiveFingerprint(session)));
130 + layout->addWidget(new QLabel(OtrlChatInterface::self()->fingerprint(session)));
132 cbManualAuth = new QComboBox();
133 cbManualAuth->addItem(i18nc("@item:inlistbox ...verified that", "I have not"));
135 lFinal->setText(i18n("The authentication with %1 failed. To make sure you are not talking to an imposter, try again using the manual fingerprint verification method. Note that the conversation is now insecure.", OtrlChatInterface::self()->formatContact(session->members().first()->contactId())));
140 setOption(QWizard::NoCancelButton, true);
145 void AuthenticationWizard::aborted(){
148 currentPage()->setTitle(i18n("Authentication aborted"));
149 lFinal->setText(i18n("%1 has aborted the authentication process. To make sure you are not talking to an imposter, try again using the manual fingerprint verification method.", OtrlChatInterface::self()->formatContact(session->members().first()->contactId())));
152 setOption(QWizard::NoCancelButton, true);
155 diff -urN kdenetwork-4.10.5.org/kopete/plugins/otr/otrlchatinterface.cpp kdenetwork-4.10.5/kopete/plugins/otr/otrlchatinterface.cpp
156 --- kdenetwork-4.10.5.org/kopete/plugins/otr/otrlchatinterface.cpp 2013-06-28 20:08:21.437046228 +0200
157 +++ kdenetwork-4.10.5/kopete/plugins/otr/otrlchatinterface.cpp 2013-07-10 21:39:55.609722565 +0200
159 /*************************************************************************
160 - * Copyright <2007> <Michael Zanetti> <michael_zanetti@gmx.net> *
161 + * Copyright <2007 - 2013> <Michael Zanetti> <mzanetti@kde.org> *
163 * This program is free software; you can redistribute it and/or *
164 * modify it under the terms of the GNU General Public License as *
166 static Kopete::Plugin *chatPlugin = 0;
168 /***************************** Gui_UI_Ops for libotr **********************************/
169 -static OtrlPolicy policy(void *opdata, ConnContext *context){
170 +OtrlPolicy OtrlChatInterface::policy(void *opdata, ConnContext *context){
174 Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
178 // Disable OTR for IRC
179 if( session->protocol()->pluginId() == "IRCProtocol" ){
180 // kdDebug() << "Disabling OTR for: " << session->protocol()->pluginId() << endl;
185 -static void create_privkey(void *opdata, const char *accountname, const char *protocol){
186 +void OtrlChatInterface::create_privkey(void *opdata, const char *accountname, const char *protocol){
187 + Q_UNUSED(accountname)
189 Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
191 if( !session->view() ){
192 @@ -102,23 +104,21 @@
194 popup->setCloseLock( true );
196 - KeyGenThread *keyGenThread = new KeyGenThread ( accountname, protocol );
197 - keyGenThread->start();
198 - while( !keyGenThread->wait(100) ){
199 - qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers, 100);
201 + OtrlChatInterface::self()->generatePrivateKey(session->account()->accountId(), session->protocol()->displayName());
203 popup->setCloseLock( false );
206 + OtrlChatInterface::self()->replayStoredMessages();
209 -static int is_logged_in(void *opdata, const char *accountname, const char *protocol, const char *recipient){
210 +int OtrlChatInterface::is_logged_in(void *opdata, const char *accountname, const char *protocol, const char *recipient){
212 Q_UNUSED(accountname)
215 Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
216 - Kopete::ContactPtrList list = session->members();
217 + Kopete::ContactPtrList list = session->members();
218 for( int i = 0; i < list.size(); i++ ){
219 if( list.at(i)->contactId().compare( recipient) == 0 ){
220 Kopete::OnlineStatus status = session->contactOnlineStatus( list.at(i) );
225 -static void inject_message( void *opdata, const char *accountname, const char *protocol, const char *recipient, const char *message ){
226 +void OtrlChatInterface::inject_message( void *opdata, const char *accountname, const char *protocol, const char *recipient, const char *message ){
228 Q_UNUSED(accountname)
231 // kDebug(14318) << "Sending message:" << message;
233 Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
234 - Kopete::ContactPtrList list = session->members();
235 + Kopete::ContactPtrList list = session->members();
236 for( int i = 0; i < list.size(); i++ ){
237 if( list.at(i)->contactId().compare( recipient ) == 0 ){
238 Kopete::Message msg( session->account()->myself(), list.at(i) );
239 @@ -154,61 +154,12 @@
243 -static void notify(void *opdata, OtrlNotifyLevel level, const char *accountname, const char *protocol, const char *username, const char *title, const char *primary, const char *secondary){
247 - Q_UNUSED(accountname)
251 - KMessageBox::information(NULL, QString( primary ) + QString( secondary ), QString( title ) );
254 -static int display_otr_message( void *opdata, const char *accountname, const char *protocol, const char *username, const char *message ){
256 - Q_UNUSED(accountname)
259 - Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
260 - Kopete::ContactPtrList list = session->members();
261 - for( int i = 0; i < list.size(); i++ ){
262 - if( list.at(i)->contactId().compare( username ) == 0 ){
263 - Kopete::Message msg( session->members().first(), session->account()->myself() );
264 - msg.setHtmlBody( QString( message ) );
265 - msg.setDirection( Kopete::Message::Internal );
266 - session->appendMessage( msg );
273 -static void update_context_list(void *opdata){
274 +void OtrlChatInterface::update_context_list(void *opdata){
279 -static const char *protocol_name(void *opdata, const char *protocol){
285 -// kdDebug() << "protocol_name called" << endl;
289 -static void protocol_name_free(void *opdata, const char *protocol_name){
293 - Q_UNUSED(protocol_name)
295 -// kdDebug() << "protocol_name_free called" << endl;
298 -static void new_fingerprint(void *opdata, OtrlUserState us, const char *accountname, const char *protocol, const char *username, unsigned char fingerprint[20]){
299 +void OtrlChatInterface::new_fingerprint(void *opdata, OtrlUserState us, const char *accountname, const char *protocol, const char *username, unsigned char fingerprint[20]){
302 Q_UNUSED(accountname)
304 session->appendMessage( msg );
307 -static void write_fingerprints(void *opdata){
308 +void OtrlChatInterface::write_fingerprints(void *opdata){
313 otrl_privkey_write_fingerprints( userstate, savePath.toLocal8Bit() );
316 -static void gone_secure(void *opdata, ConnContext *context){
317 -// kdDebug() << "gone secure" << endl;
318 +void OtrlChatInterface::gone_secure(void *opdata, ConnContext *context){
319 Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
321 if( context->active_fingerprint->trust && context->active_fingerprint->trust[0] ){
323 session->appendMessage( msg );
324 OtrlChatInterface::self()->emitGoneSecure( ((Kopete::ChatSession*)opdata), 1 );
327 + session->setProperty("otr-instag", QString::number(context->their_instance));
330 -static void gone_insecure(void *opdata, ConnContext *context){
331 +void OtrlChatInterface::gone_insecure(void *opdata, ConnContext *context){
335 @@ -265,12 +217,12 @@
336 session->appendMessage( msg );
339 -static void still_secure(void *opdata, ConnContext *context, int is_reply){
340 +void OtrlChatInterface::still_secure(void *opdata, ConnContext *context, int is_reply){
344 -// kdDebug() << "still secure" << endl;
345 Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
347 Kopete::Message msg( session->members().first(), session->account()->myself() );
348 msg.setHtmlBody( i18n("<b>OTR connection refreshed successfully.</b>") );
349 msg.setDirection( Kopete::Message::Internal );
350 @@ -283,18 +235,11 @@
354 -static void log_message(void *opdata, const char *message){
358 - kDebug(14318) << "libotr: "<< message;
361 -static int max_message_size(void *opdata, ConnContext *context){
362 +int OtrlChatInterface::max_message_size(void *opdata, ConnContext *context){
363 Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
368 kDebug(14318) << session->protocol()->pluginId();
370 if( session->protocol()->pluginId() == "WlmProtocol" ){
371 @@ -305,32 +250,264 @@
373 } else if( session->protocol()->pluginId() == "YahooProtocol" ){
378 // Jabber doesn't need fragmentation. Return 0 to disable.
379 // GaduGadu seems to not need fragmentation too.
383 -static OtrlMessageAppOps ui_ops = {
389 - display_otr_message,
390 - update_context_list,
392 - protocol_name_free,
394 - write_fingerprints,
400 - 0, //not used yet...
401 - 0 //not used yet...
402 +const char* OtrlChatInterface::otr_error_message(void *opdata, ConnContext *context, OtrlErrorCode err_code) {
408 + case OTRL_ERRCODE_NONE :
410 + case OTRL_ERRCODE_ENCRYPTION_ERROR : {
411 + QString message = i18n("Error occurred encrypting message.");
412 + err_msg = (char*)malloc(message.length() + 1);
413 + memset(err_msg, 0, message.length() + 1);
414 + memcpy(err_msg, message.toUtf8().data(), message.length());
417 + case OTRL_ERRCODE_MSG_NOT_IN_PRIVATE :
419 + QString message = i18n("You sent encrypted data to %s, who wasn't expecting it.").arg(context->accountname);
420 + err_msg = (char*)malloc(message.length() + 1);
421 + memset(err_msg, 0, message.length() + 1);
422 + memcpy(err_msg, message.toUtf8().data(), message.length());
425 + case OTRL_ERRCODE_MSG_UNREADABLE : {
426 + QString message = i18n("You transmitted an unreadable encrypted message.");
427 + err_msg = (char*)malloc(message.length() + 1);
428 + memset(err_msg, 0, message.length() + 1);
429 + memcpy(err_msg, message.toUtf8().data(), message.length());
432 + case OTRL_ERRCODE_MSG_MALFORMED : {
433 + QString message = i18n("You transmitted a malformed data message.");
434 + err_msg = (char*)malloc(message.length() + 1);
435 + memset(err_msg, 0, message.length() + 1);
436 + memcpy(err_msg, message.toUtf8().data(), message.length());
443 +void OtrlChatInterface::otr_error_message_free(void *opdata, const char *err_msg) {
446 + free((char*)err_msg);
450 +const char *OtrlChatInterface::resent_msg_prefix(void *opdata, ConnContext *context) {
454 + QString message = i18n("[resent]");
455 + char *msg_prefix = (char*)malloc(message.length() + 1);
456 + memset(msg_prefix, 0, message.length() + 1);
457 + memcpy(msg_prefix, message.toUtf8().data(), message.length());
461 +void OtrlChatInterface::resent_msg_prefix_free(void *opdata, const char *prefix) {
465 + free((char*)prefix);
469 +void OtrlChatInterface::handle_smp_event(void *opdata, OtrlSMPEvent smp_event, ConnContext *context, unsigned short progress_percent, char *question) {
470 + Q_UNUSED(progress_percent)
472 + Kopete::ChatSession *chatSession = (Kopete::ChatSession*)opdata;
478 + switch (smp_event) {
479 + case OTRL_SMPEVENT_NONE :
481 + case OTRL_SMPEVENT_ASK_FOR_SECRET :
482 + new AuthenticationWizard( chatSession->view(true)->mainWidget(), context, chatSession, false );
484 + case OTRL_SMPEVENT_ASK_FOR_ANSWER :
485 + new AuthenticationWizard( chatSession->view(true)->mainWidget(), context, chatSession, false, QLatin1String(question) );
487 + case OTRL_SMPEVENT_IN_PROGRESS :
488 + AuthenticationWizard::findWizard(chatSession)->nextState();
490 + case OTRL_SMPEVENT_SUCCESS :
491 + if (context->active_fingerprint->trust && context->active_fingerprint->trust[0]) {
492 + AuthenticationWizard::findWizard(chatSession)->finished(true, true);
493 + kDebug(14318) << "trust found";
494 + Kopete::Message msg( chatSession->members().first(), chatSession->account()->myself() );
495 + msg.setHtmlBody( i18n("Authentication with <b>%1</b> successful. The conversation is now secure.", formatContact(chatSession->members().first()->contactId())));
496 + msg.setDirection( Kopete::Message::Internal );
497 + chatSession->appendMessage( msg );
498 + OtrlChatInterface::self()->emitGoneSecure( chatSession, 2 );
500 + AuthenticationWizard::findWizard(chatSession)->finished(true, false);
501 + kDebug(14318) << "trust _NOT_ found";
502 + Kopete::Message msg( chatSession->members().first(), chatSession->account()->myself() );
503 + msg.setHtmlBody( i18n("<b>%1</b> has successfully authenticated you. You may want to authenticate this contact as well by asking your own question.", formatContact(chatSession->members().first()->contactId())));
504 + msg.setDirection( Kopete::Message::Internal );
505 + chatSession->appendMessage( msg );
506 + OtrlChatInterface::self()->emitGoneSecure( chatSession, 1 );
509 + case OTRL_SMPEVENT_FAILURE : {
510 + AuthenticationWizard::findWizard(chatSession)->finished(false, false);
511 + Kopete::Message msg( chatSession->members().first(), chatSession->account()->myself() );
512 + msg.setHtmlBody( i18n("Authentication with <b>%1</b> failed. The conversation is now insecure.", formatContact(chatSession->members().first()->contactId())));
513 + msg.setDirection( Kopete::Message::Internal );
514 + chatSession->appendMessage( msg );
515 + OtrlChatInterface::self()->emitGoneSecure( chatSession, 1 );
518 + case OTRL_SMPEVENT_ABORT :
519 + case OTRL_SMPEVENT_CHEATED :
520 + case OTRL_SMPEVENT_ERROR :
521 + AuthenticationWizard::findWizard(chatSession)->finished(false, false);
522 + OtrlChatInterface::self()->abortSMP( context, chatSession );
527 +void OtrlChatInterface::handle_msg_event(void *opdata, OtrlMessageEvent msg_event, ConnContext *context, const char* message, gcry_error_t err) {
529 + Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
530 + Kopete::ContactPtrList list = session->members();
531 + Kopete::Message msg( session->members().first(), session->account()->myself() );
535 + case OTRL_MSGEVENT_NONE:
537 + case OTRL_MSGEVENT_ENCRYPTION_REQUIRED:
538 + msg.setHtmlBody( i18n( "You attempted to send an unencrypted message to %1" ).arg(QLatin1String(context->username)) );
539 + msg.setDirection( Kopete::Message::Internal );
541 + case OTRL_MSGEVENT_ENCRYPTION_ERROR:
542 + msg.setHtmlBody( i18n( "An error occurred when encrypting your message. The message was not sent." ).arg(QLatin1String(context->username)) );
543 + msg.setDirection( Kopete::Message::Internal );
545 + case OTRL_MSGEVENT_CONNECTION_ENDED:
546 + msg.setHtmlBody( i18n( "%1 has already closed his/her private connection to you. Your message was not sent. Either end your private conversation, or restart it." ).arg(QLatin1String(context->username)) );
547 + msg.setDirection( Kopete::Message::Internal );
549 + case OTRL_MSGEVENT_SETUP_ERROR:
551 + err = GPG_ERR_INV_VALUE;
553 + switch(gcry_err_code(err)) {
554 + case GPG_ERR_INV_VALUE:
555 + kDebug(14318) << "Error setting up private conversation: Malformed message received";
557 + kDebug(14318) << "Error setting up private conversation:" << err;
560 + msg.setHtmlBody( i18n( "OTR error" ) );
561 + msg.setDirection( Kopete::Message::Internal );
563 + case OTRL_MSGEVENT_MSG_REFLECTED:
564 + msg.setHtmlBody( i18n( "We are receiving our own OTR messages. You are either trying to talk to yourself, or someone is reflecting your messages back at you." ) );
565 + msg.setDirection( Kopete::Message::Internal );
567 + case OTRL_MSGEVENT_MSG_RESENT:
568 + msg.setHtmlBody( i18n( "<b>The last message to %1 was resent.</b>" ).arg(QLatin1String(context->username)) );
569 + msg.setDirection( Kopete::Message::Internal );
571 + case OTRL_MSGEVENT_RCVDMSG_NOT_IN_PRIVATE:
572 + msg.setHtmlBody( i18n( "<b>The encrypted message received from %1 is unreadable, as you are not currently communicating privately.</b>" ).arg(QLatin1String(context->username)) );
573 + msg.setDirection( Kopete::Message::Inbound );
574 + OtrlChatInterface::self()->m_blackistIds.append(msg.id());
576 + case OTRL_MSGEVENT_RCVDMSG_UNREADABLE:
577 + msg.setHtmlBody( i18n( "We received an unreadable encrypted message from %1." ).arg(QLatin1String(context->username)) );
578 + msg.setDirection( Kopete::Message::Internal );
580 + case OTRL_MSGEVENT_RCVDMSG_MALFORMED:
581 + msg.setHtmlBody( i18n( "We received a malformed data message from %1." ).arg(QLatin1String(context->username)) );
582 + msg.setDirection( Kopete::Message::Internal );
584 + case OTRL_MSGEVENT_LOG_HEARTBEAT_RCVD:
585 + kDebug(14318) << "Heartbeat received from" << context->username;
587 + case OTRL_MSGEVENT_LOG_HEARTBEAT_SENT:
588 + kDebug(14318) << "Heartbeat sent to" << context->username;
590 + case OTRL_MSGEVENT_RCVDMSG_GENERAL_ERR:
591 + msg.setHtmlBody( QLatin1String(message) );
592 + msg.setDirection( Kopete::Message::Internal );
593 + session->appendMessage( msg );
595 + case OTRL_MSGEVENT_RCVDMSG_UNENCRYPTED:
596 + msg.setHtmlBody( i18n("<b>The following message received from %1 was <i>not</i> encrypted: [</b>%2<b>]</b>").arg(QLatin1String(context->username), QLatin1String(message) ));
597 + msg.setDirection( Kopete::Message::Inbound );
598 + OtrlChatInterface::self()->m_blackistIds.append(msg.id());
600 + case OTRL_MSGEVENT_RCVDMSG_UNRECOGNIZED:
601 + kDebug(14318) << "Unrecognized OTR message received from" << context->username;
603 + case OTRL_MSGEVENT_RCVDMSG_FOR_OTHER_INSTANCE:
604 + msg.setHtmlBody( i18n( "%1 has sent an encrypted message intended for a different session. If you are logged in multiple times, another session may have received the message.").arg(QLatin1String(context->username) ));
605 + msg.setDirection( Kopete::Message::Inbound );
606 + OtrlChatInterface::self()->m_blackistIds.append(msg.id());
610 + session->appendMessage( msg );
613 +void OtrlChatInterface::create_instag(void *opdata, const char *accountname, const char *protocol) {
615 + QString storeFile = QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "instags";
616 + otrl_instag_generate(OtrlChatInterface::self()->getUserstate(), storeFile.toLocal8Bit(), accountname, protocol);
619 +void OtrlChatInterface::timer_control(void *opdata, unsigned int interval) {
621 + if (interval > 0) {
622 + OtrlChatInterface::self()->m_forwardSecrecyTimer.start(interval * 1000);
624 + OtrlChatInterface::self()->m_forwardSecrecyTimer.stop();
628 +OtrlMessageAppOps OtrlChatInterface::ui_ops = {
629 + OtrlChatInterface::policy,
630 + OtrlChatInterface::create_privkey,
631 + OtrlChatInterface::is_logged_in,
632 + OtrlChatInterface::inject_message,
633 + OtrlChatInterface::update_context_list,
634 + OtrlChatInterface::new_fingerprint,
635 + OtrlChatInterface::write_fingerprints,
636 + OtrlChatInterface::gone_secure,
637 + OtrlChatInterface::gone_insecure,
638 + OtrlChatInterface::still_secure,
639 + OtrlChatInterface::max_message_size,
640 + NULL, /* account_name */
641 + NULL, /* account_name_free */
642 + NULL, /* received symkey */
643 + OtrlChatInterface::otr_error_message,
644 + OtrlChatInterface::otr_error_message_free,
645 + OtrlChatInterface::resent_msg_prefix,
646 + OtrlChatInterface::resent_msg_prefix_free,
647 + OtrlChatInterface::handle_smp_event,
648 + OtrlChatInterface::handle_msg_event,
649 + OtrlChatInterface::create_instag,
650 + NULL, /* convert_data */
651 + NULL, /* convert_data_free */
652 + OtrlChatInterface::timer_control
655 /*********************** Gui_UI_Ops finished *************************/
656 @@ -338,25 +515,31 @@
658 /*********************** Constructor/Destructor **********************/
660 -OtrlChatInterface::OtrlChatInterface(){
661 +OtrlChatInterface::OtrlChatInterface():
668 userstate = otrl_userstate_create();
669 QString readPath = QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "privkeys";
670 otrl_privkey_read( userstate, readPath.toLocal8Bit() );
673 - QString savePath = QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "fingerprints";
674 - otrl_privkey_read_fingerprints(userstate, savePath.toLocal8Bit(), NULL, NULL);
676 + unsigned int interval = otrl_message_poll_get_default_interval(userstate);
677 + m_forwardSecrecyTimer.start(interval * 1000);
678 + QObject::connect(&m_forwardSecrecyTimer, SIGNAL(timeout()), this, SLOT(otrlMessagePoll()));
680 + readPath = QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "fingerprints";
681 + otrl_privkey_read_fingerprints(userstate, readPath.toLocal8Bit(), NULL, NULL);
683 + readPath = QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true)) + "instags";
684 + otrl_instag_read(userstate, readPath.toLocal8Bit());
687 OtrlChatInterface::~ OtrlChatInterface(){
688 otrl_userstate_free(userstate);
692 OtrlChatInterface *OtrlChatInterface::self(){
694 new OtrlChatInterface();
695 @@ -375,159 +558,59 @@
699 -int OtrlChatInterface::decryptMessage( QString *msg, const QString &accountId,
700 - const QString &protocol, const QString &contactId , Kopete::ChatSession *chatSession){
701 +int OtrlChatInterface::decryptMessage( Kopete::Message &message){
704 - char *newMessage = NULL;
705 - OtrlTLV *tlvs = NULL;
706 - OtrlTLV *tlv = NULL;
707 - ConnContext *context;
708 - NextExpectedSMP nextMsg;
710 - ignoremessage = otrl_message_receiving( userstate, &ui_ops, chatSession, accountId.toLocal8Bit(), protocol.toLocal8Bit(), contactId.toLocal8Bit(), msg->toLocal8Bit(), &newMessage, &tlvs, NULL, NULL );
712 - tlv = otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED);
714 - Kopete::Message msg( chatSession->members().first(), chatSession->account()->myself() );
715 - msg.setHtmlBody( i18n("<b>%1</b> has ended the OTR session. You should do the same.",chatSession->members().first()->contactId() ) );
716 - msg.setDirection( Kopete::Message::Internal );
717 - chatSession->appendMessage( msg );
718 - OtrlChatInterface::self()->emitGoneSecure( chatSession, 3 );
719 + if (m_blackistIds.contains(message.id())) {
720 + m_blackistIds.removeAll(message.id());
724 - context = otrl_context_find( userstate, contactId.toLocal8Bit(), accountId.toLocal8Bit(), protocol.toLocal8Bit(), 0, NULL, NULL, NULL);
726 - nextMsg = context->smstate->nextExpected;
727 + Kopete::ChatSession *chatSession = message.manager();
728 + QString accountId = chatSession->account()->accountId();
729 + QString protocol = chatSession->protocol()->displayName();
730 + QString contactId = message.from()->contactId();
731 + QString body = message.plainBody();
733 + OtrlTLV *tlvs = NULL;
734 + char *newMessage = NULL;
736 - if (context->smstate->sm_prog_state == OTRL_SMP_PROG_CHEATED) {
737 - abortSMP(context, chatSession);
738 - context->smstate->nextExpected = OTRL_SMP_EXPECT1;
739 - context->smstate->sm_prog_state = OTRL_SMP_PROG_OK;
741 - tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1Q);
743 - if (nextMsg != OTRL_SMP_EXPECT1){
744 - kDebug(14318) << "Abording SMP: 1Q";
745 - abortSMP( context, chatSession );
747 - kDebug(14318) << "Update SMP state: 1Q";
748 - new AuthenticationWizard( chatSession->view(true)->mainWidget(), context, chatSession, false, QString((char*)tlvs->data) );
751 + if (m_keyGenThread != 0) {
752 + // Currently generating the private key... must be a plaintext message anyways...
754 - tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1);
756 - if (nextMsg != OTRL_SMP_EXPECT1){
757 - kDebug(14318) << "Abording SMP: 1";
758 - abortSMP( context, chatSession );
760 - kDebug(14318) << "Update SMP state: 1 ";
761 - new AuthenticationWizard( chatSession->view(true)->mainWidget(), context, chatSession, false );
763 + if (otrl_proto_message_type(body.toLatin1()) == OTRL_MSGTYPE_DATA) {
764 + // an OTR message while we are generating the key... cache the message and replay once the key is generated...
765 + connect(message.manager(), SIGNAL(closing(Kopete::ChatSession*)), SLOT(chatSessionDestroyed(Kopete::ChatSession*)));
766 + m_storedMessages.append(message);
768 - tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP2);
770 - if (nextMsg != OTRL_SMP_EXPECT2){
771 - kDebug(14318) << "Abording SMP: 2";
772 - abortSMP( context, chatSession );
774 - kDebug(14318) << "Update SMP state: 2 -> 3";
775 - AuthenticationWizard::findWizard(chatSession)->nextState();
776 - context->smstate->nextExpected = OTRL_SMP_EXPECT4;
779 - tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP3);
781 - if (nextMsg != OTRL_SMP_EXPECT3){
782 - kDebug(14318) << "Abording SMP: 3";
783 - abortSMP( context, chatSession );
785 - kDebug(14318) << "SMP: 3";
786 - if(context->smstate->sm_prog_state == OTRL_SMP_PROG_SUCCEEDED){
787 - if (context->active_fingerprint->trust && context->active_fingerprint->trust[0]) {
788 - AuthenticationWizard::findWizard(chatSession)->finished(true, true);
789 - kDebug(14318) << "trust found";
790 - Kopete::Message msg( chatSession->members().first(), chatSession->account()->myself() );
791 - msg.setHtmlBody( i18n("Authentication with <b>%1</b> successful. The conversation is now secure.", formatContact(chatSession->members().first()->contactId())));
792 - msg.setDirection( Kopete::Message::Internal );
793 - chatSession->appendMessage( msg );
794 - OtrlChatInterface::self()->emitGoneSecure( chatSession, 2 );
796 - AuthenticationWizard::findWizard(chatSession)->finished(true, false);
797 - kDebug(14318) << "trust _NOT_ found";
798 - Kopete::Message msg( chatSession->members().first(), chatSession->account()->myself() );
799 - msg.setHtmlBody( i18n("<b>%1</b> has successfully authenticated you. You may want to authenticate this contact as well by asking your own question.", formatContact(chatSession->members().first()->contactId())));
800 - msg.setDirection( Kopete::Message::Internal );
801 - chatSession->appendMessage( msg );
802 - OtrlChatInterface::self()->emitGoneSecure( chatSession, 1 );
806 - AuthenticationWizard::findWizard(chatSession)->finished(false, false);
807 - Kopete::Message msg( chatSession->members().first(), chatSession->account()->myself() );
808 - msg.setHtmlBody( i18n("Authentication with <b>%1</b> failed. The conversation is now insecure.", formatContact(chatSession->members().first()->contactId())));
809 - msg.setDirection( Kopete::Message::Internal );
810 - chatSession->appendMessage( msg );
811 - OtrlChatInterface::self()->emitGoneSecure( chatSession, 1 );
816 - context->smstate->nextExpected = OTRL_SMP_EXPECT1;
819 - tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP4);
821 - if (nextMsg != OTRL_SMP_EXPECT4) {
822 - kDebug(14318) << "Abording SMP: 4";
823 - abortSMP( context, chatSession );
825 - kDebug(14318) << "SMP: 4";
826 - if (context->active_fingerprint->trust && context->active_fingerprint->trust[0]) {
827 - AuthenticationWizard::findWizard(chatSession)->finished(true, true);
828 - kDebug(14318) << "trust found";
829 - Kopete::Message msg( chatSession->members().first(), chatSession->account()->myself() );
830 - msg.setHtmlBody( i18n("<b>Authentication successful. The conversation is now secure.</b>") );
831 - msg.setDirection( Kopete::Message::Internal );
832 - chatSession->appendMessage( msg );
833 - OtrlChatInterface::self()->emitGoneSecure( chatSession, 2 );
835 - AuthenticationWizard::findWizard(chatSession)->finished(false, false);
836 - kDebug(14318) << "trust _NOT_ found";
837 - Kopete::Message msg( chatSession->members().first(), chatSession->account()->myself() );
838 - msg.setHtmlBody( i18n("<b>Authentication failed. Note that the conversation is now insecure.</b>") );
839 - msg.setDirection( Kopete::Message::Internal );
840 - chatSession->appendMessage( msg );
841 - OtrlChatInterface::self()->emitGoneSecure( chatSession, 1 );
843 - context->smstate->nextExpected = OTRL_SMP_EXPECT1;
846 - tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP_ABORT);
848 - kDebug(14318) << "other end aborted SMP";
849 + int ignoremessage = otrl_message_receiving( userstate, &ui_ops, chatSession, accountId.toLocal8Bit(), protocol.toLocal8Bit(), contactId.toLocal8Bit(), body.toLocal8Bit(), &newMessage, &tlvs, NULL, NULL, NULL );
851 + ConnContext *context = otrl_context_find( userstate, contactId.toLocal8Bit(), accountId.toLocal8Bit(), protocol.toLocal8Bit(), 0, 0, NULL, NULL, NULL);
853 + OtrlTLV *tlv = otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED);
855 Kopete::Message msg( chatSession->members().first(), chatSession->account()->myself() );
856 - msg.setHtmlBody( i18n("<b>Authentication error.</b>") );
857 + msg.setHtmlBody( i18n("<b>%1</b> has ended the OTR session. You should do the same.",chatSession->members().first()->contactId() ) );
858 msg.setDirection( Kopete::Message::Internal );
859 chatSession->appendMessage( msg );
860 - AuthenticationWizard *currentWizard = AuthenticationWizard::findWizard(chatSession);
862 - currentWizard->aborted();
864 - context->smstate->nextExpected = OTRL_SMP_EXPECT1;
865 + OtrlChatInterface::self()->emitGoneSecure( chatSession, 3 );
867 + otrl_tlv_free(tlvs);
870 - otrl_tlv_free(tlvs);
876 // message is now decrypted or is a Plaintext message and ready to deliver
877 if( !ignoremessage ){
878 // message is decrypted
879 if( newMessage != NULL ){
880 - *msg = QString::fromUtf8(newMessage);
881 + body = QString::fromUtf8(newMessage);
882 otrl_message_free( newMessage );
883 - msg->replace( QString('\n'), QString("<br>") );
884 + body.replace( QString('\n'), QString("<br>") );
885 + message.setHtmlBody( body );
887 return 0; // message is decrypted and ready to deliver
889 return 1; // message was a plaintext message. Better not touching it :)
890 @@ -536,75 +619,95 @@
891 return 2; // internal OTR message. Ignore it.
894 -int OtrlChatInterface::encryptMessage( QString *msg, const QString &accountId,
895 - const QString &protocol, const QString &contactId , Kopete::ChatSession *chatSession ){
897 +int OtrlChatInterface::encryptMessage( Kopete::Message &message ){
898 char *newMessage = 0;
899 - char *fragment = 0;
901 - if( otrl_proto_message_type( msg->toLocal8Bit() ) == OTRL_MSGTYPE_NOTOTR ){
902 -// msg->replace( QString('<'), QString("<") );
903 - err = otrl_message_sending( userstate, &ui_ops, chatSession, accountId.toLocal8Bit(), protocol.toLocal8Bit(), contactId.toLocal8Bit(), msg->toUtf8(), NULL, &newMessage, NULL, NULL );
907 - } else if( newMessage ){
909 + bool plaintext = message.format() == Qt::PlainText;
911 - /* Fragment the message if needed */
912 - /* If fragmentation is needed libotr will send out all fragments but the last one. */
913 - ConnContext *context = otrl_context_find(userstate, contactId.toLocal8Bit(), accountId.toLocal8Bit(), protocol.toLocal8Bit(), 0, NULL, NULL, NULL);
915 + msgBody = message.plainBody().replace('<', "<");
917 + msgBody = message.escapedBody();
920 - //kDebug(14318) << "message to be sent out: " << newMessage;
921 + Kopete::ChatSession *chatSession = message.manager();
922 + QString accountId = chatSession->account()->accountId();
923 + QString protocol = chatSession->protocol()->displayName();
924 + QString contactId = message.to().first()->contactId();
926 - err = otrl_message_fragment_and_send(&ui_ops, chatSession, context, newMessage,
927 - OTRL_FRAGMENT_SEND_ALL_BUT_LAST, &fragment);
928 + if( otrl_proto_message_type( msgBody.toLocal8Bit() ) == OTRL_MSGTYPE_NOTOTR ){
930 -// kDebug(14318) << "fragment left to be sent by kopete: " << fragment;
931 + otrl_instag_t instance = message.manager()->property("otr-instag").toUInt();
934 - *msg = i18n("Encryption error");
935 - } else if ( fragment ){
936 - *msg = QString::fromUtf8( fragment );
937 - otrl_message_free( newMessage );
938 - otrl_message_free( fragment );
940 - OtrlMessageType type = otrl_proto_message_type( msg->toLocal8Bit() );
941 - if( type == OTRL_MSGTYPE_TAGGEDPLAINTEXT ){
942 - return 1; // Message is still plaintext, but tagged for opportunistic mode
943 + int err = otrl_message_sending( userstate, &ui_ops, chatSession, accountId.toLocal8Bit(), protocol.toLocal8Bit(), contactId.toLocal8Bit(), instance, msgBody.toUtf8(), NULL, &newMessage, OTRL_FRAGMENT_SEND_ALL_BUT_LAST, NULL, NULL, NULL );
946 + message.setPlainBody(i18n("An error occurred while encrypting the message."));
948 + } else if (newMessage) {
949 + msgBody = QString::fromUtf8(newMessage);
950 + otrl_message_free(newMessage);
954 + OtrlMessageType type = otrl_proto_message_type( msgBody.toLatin1() );
955 + if( type == OTRL_MSGTYPE_TAGGEDPLAINTEXT ){
956 + kDebug(14318) << "Tagged plaintext!";
958 + /* Here we have a problem... libotr tags messages with whitespaces to
959 + be recognized by other clients. Those whitespaces are discarded
960 + if we use setHtmlBody() and breaks opportunistic mode.
961 + If we use setPlainBody() for messages containing tags, those tags
962 + are escaped and will be visible in the other sides chatwindow.
964 + This approach should always send out correct messages but will
965 + break opportunistic mode if the user enables RTF formatting.
966 + Sorry folks. No way to deal with this currently (Would need changes
967 + in the rich text handling in libkopete).
970 + message.setPlainBody(msgBody);
972 + message.setHtmlBody(msgBody);
974 - return 0; // Encrypted successfully
978 + // Always set plaintext if the message has been encrypted.
979 + // The parser wouldn't understand anything after encryption anyways...
980 + message.setPlainBody( msgBody );
981 + message.setType(Kopete::Message::TypeNormal);
986 return 2; // Message is still plaintext. Better not touching it
989 QString OtrlChatInterface::getDefaultQuery( const QString &accountId ){
991 - message = otrl_proto_default_query_msg( accountId.toLatin1(), OTRL_POLICY_ALLOW_V2 );
992 + message = otrl_proto_default_query_msg( accountId.toLatin1(), OTRL_POLICY_ALLOW_V3 | OTRL_POLICY_ALLOW_V2 );
993 QString msg( message );
994 otrl_message_free( message );
998 void OtrlChatInterface::disconnectSession( Kopete::ChatSession *chatSession ){
999 - otrl_message_disconnect( userstate, &ui_ops, chatSession, chatSession->account()->accountId().toLatin1(), chatSession->account()->protocol()->displayName().toLatin1(), chatSession->members().first()->contactId().toLocal8Bit() );
1000 + otrl_instag_t instance = chatSession->property("otr-instag").toUInt();
1001 + otrl_message_disconnect( userstate, &ui_ops, chatSession, chatSession->account()->accountId().toLatin1(), chatSession->account()->protocol()->displayName().toLatin1(), chatSession->members().first()->contactId().toLocal8Bit(), instance);
1002 OtrlChatInterface::self()->emitGoneSecure( chatSession, 0 );
1004 Kopete::Message msg( chatSession->account()->myself(), chatSession->members().first() );
1005 msg.setPlainBody( i18n("Terminating OTR session.") );
1006 msg.setDirection( Kopete::Message::Internal );
1007 -// msg.setBody( QString( message ), Kopete::Message::RichText );
1008 chatSession->appendMessage( msg );
1012 bool OtrlChatInterface::shouldDiscard( const QString &message ){
1013 if( !message.isEmpty() && !message.isNull() ){
1014 -// kDebug(14318) << otrl_proto_message_type( message.toLatin1() );
1015 switch( otrl_proto_message_type( message.toLatin1() ) ){
1016 case OTRL_MSGTYPE_TAGGEDPLAINTEXT:
1017 -// case OTRL_MSGTYPE_UNKNOWN: // Fragmented messages seem to be type UNKNOWN
1018 + //case OTRL_MSGTYPE_UNKNOWN: // Fragmented messages seem to be type UNKNOWN
1019 case OTRL_MSGTYPE_NOTOTR:
1022 @@ -622,33 +725,35 @@
1025 int OtrlChatInterface::privState( Kopete::ChatSession *session ){
1026 - ConnContext *context;
1028 - context = otrl_context_find(userstate, session->members().first()->contactId().toLocal8Bit(), session->account()->accountId().toLocal8Bit(), session->account()->protocol()->displayName().toLocal8Bit(), 0, NULL, NULL, NULL);
1029 + otrl_instag_t instance = session->property("otr-instag").toUInt();
1030 + if (instance == 0) {
1031 + instance = OTRL_INSTAG_BEST;
1033 + ConnContext *context = otrl_context_find(userstate, session->members().first()->contactId().toLocal8Bit(), session->account()->accountId().toLocal8Bit(), session->account()->protocol()->displayName().toLocal8Bit(), instance, 0, NULL, NULL, NULL);
1036 switch( context->msgstate ){
1037 - case OTRL_MSGSTATE_PLAINTEXT:
1039 - case OTRL_MSGSTATE_ENCRYPTED:
1040 - if( context->active_fingerprint->trust && context->active_fingerprint->trust[0] != '\0' )
1044 - case OTRL_MSGSTATE_FINISHED:
1046 + case OTRL_MSGSTATE_PLAINTEXT:
1048 + case OTRL_MSGSTATE_ENCRYPTED:
1049 + if( context->active_fingerprint->trust && context->active_fingerprint->trust[0] != '\0' )
1053 + case OTRL_MSGSTATE_FINISHED:
1061 + QString OtrlChatInterface::formatContact(const QString &contactId){
1063 -QString OtrlChatInterface::formatContact(const QString &contactId){
1065 Kopete::MetaContact *metaContact = Kopete::ContactList::self()->findMetaContactByContactId(contactId);
1067 QString displayName = metaContact->displayName();
1068 if((displayName != contactId) && !displayName.isNull()){
1069 - return displayName + " (" + contactId + ')';
1070 + return displayName + " (" + contactId + ')';
1075 void OtrlChatInterface::verifyFingerprint( Kopete::ChatSession *session ){
1076 ConnContext *context;
1078 - context = otrl_context_find( userstate, session->members().first()->contactId().toLocal8Bit(), session->account()->accountId().toLocal8Bit(), session->protocol()->displayName().toLocal8Bit(), 0, NULL, NULL, NULL);
1079 + otrl_instag_t instance = session->property("otr-instag").toUInt();
1080 + context = otrl_context_find( userstate, session->members().first()->contactId().toLocal8Bit(), session->account()->accountId().toLocal8Bit(), session->protocol()->displayName().toLocal8Bit(), instance, 0, NULL, NULL, NULL);
1082 new AuthenticationWizard( session->view()->mainWidget(), context, session, true );
1084 @@ -665,33 +771,34 @@
1085 Fingerprint *OtrlChatInterface::findFingerprint( Kopete::ChatSession *session ){
1086 ConnContext *context;
1088 - for( context = userstate->context_root; context != NULL; context = context->next ){
1089 - if( ( session->members().first()->contactId().toLocal8Bit() == context->username ) &&
1090 - (session->account()->accountId().toLocal8Bit() == context->accountname ) ){
1091 - return context->active_fingerprint ? context->active_fingerprint : NULL;
1094 + otrl_instag_t instance = session->property("otr-instag").toUInt();
1095 + if (instance == 0) {
1096 + instance = OTRL_INSTAG_BEST;
1098 + context = otrl_context_find( userstate, session->members().first()->contactId().toLocal8Bit(), session->account()->accountId().toLocal8Bit(), session->protocol()->displayName().toLocal8Bit(), instance, 0, NULL, NULL, NULL);
1099 + if (context && context->active_fingerprint && context->active_fingerprint->fingerprint) {
1100 + return context->active_fingerprint;
1105 -QString OtrlChatInterface::findActiveFingerprint( Kopete::ChatSession *session ){
1106 - ConnContext *context;
1107 +QString OtrlChatInterface::fingerprint( Kopete::ChatSession *session ){
1109 + memset(hash, 0, 45);
1111 - for( context = userstate->context_root; context != NULL; context = context->next ){
1112 - if( ( session->members().first()->contactId().toLocal8Bit() == context->username ) &&
1113 - (session->account()->accountId().toLocal8Bit() == context->accountname ) ){
1114 - otrl_privkey_hash_to_human( hash, context->active_fingerprint->fingerprint );
1117 + Fingerprint *fp = findFingerprint(session);
1119 + otrl_privkey_hash_to_human( hash, fp->fingerprint );
1120 + return QLatin1String(hash);
1128 -bool OtrlChatInterface::isVerified( Kopete::ChatSession *session ){
1129 + bool OtrlChatInterface::isVerified( Kopete::ChatSession *session ){
1130 Fingerprint *fingerprint = findFingerprint( session );
1132 - kDebug() << "fingerprint" << fingerprint;
1133 if( fingerprint->trust && fingerprint->trust[0] != '\0' ){
1137 privkeysInfo.permission( QFile::ReadOther ) |
1138 privkeysInfo.permission( QFile::WriteOther ) |
1139 privkeysInfo.permission( QFile::ExeOther ) ){
1140 - chmod( file.toLocal8Bit(), 0600);
1141 + chmod( file.toLocal8Bit(), 0600);
1145 @@ -738,6 +845,17 @@
1149 +void OtrlChatInterface::generatePrivateKey(const QString &account, const QString &protocol)
1151 + m_keyGenThread = new KeyGenThread ( account.toLatin1(), protocol.toLatin1() );
1152 + m_keyGenThread->start();
1153 + while( !m_keyGenThread->wait(100) ){
1154 + qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers, 100);
1156 + m_keyGenThread->deleteLater();
1157 + m_keyGenThread = 0;
1160 /****************** SMP implementations ****************/
1162 void OtrlChatInterface::abortSMP( ConnContext *context, Kopete::ChatSession *session ){
1166 void OtrlChatInterface::initSMP( ConnContext *context, Kopete::ChatSession *session, const QString &secret){
1167 - context = otrl_context_find( userstate, session->members().first()->contactId().toLocal8Bit(), session->account()->accountId().toLocal8Bit(), session->protocol()->displayName().toLocal8Bit(), 0, NULL, NULL, NULL);
1168 otrl_message_initiate_smp( userstate, &ui_ops, session, context, (unsigned char*)secret.toLocal8Bit().data(), secret.length() );
1170 Kopete::Message msg( session->members().first(), session->account()->myself() );
1171 @@ -761,11 +878,9 @@
1172 msg.setDirection( Kopete::Message::Internal );
1174 session->appendMessage( msg );
1178 void OtrlChatInterface::initSMPQ( ConnContext *context, Kopete::ChatSession *session, const QString &question, const QString &secret){
1179 - context = otrl_context_find( userstate, session->members().first()->contactId().toLocal8Bit(), session->account()->accountId().toLocal8Bit(), session->protocol()->displayName().toLocal8Bit(), 0, NULL, NULL, NULL);
1180 otrl_message_initiate_smp_q( userstate, &ui_ops, session, context, (const char*)question.toLocal8Bit().data(), (unsigned char*)secret.toLocal8Bit().data(), secret.length() );
1182 Kopete::Message msg( session->members().first(), session->account()->myself() );
1185 void OtrlChatInterface::respondSMP( ConnContext *context, Kopete::ChatSession *session, const QString &secret ){
1187 - kDebug(14318) << "resonding SMP";
1188 + kDebug(14318) << "resonding SMP";
1190 otrl_message_respond_smp( userstate, &ui_ops, session, context, (unsigned char*)secret.toLocal8Bit().data(), secret.length());
1192 @@ -788,6 +903,29 @@
1193 session->appendMessage( msg );
1196 +void OtrlChatInterface::otrlMessagePoll()
1198 + otrl_message_poll(userstate, 0, 0);
1201 +void OtrlChatInterface::replayStoredMessages()
1203 + while (m_storedMessages.isEmpty()) {
1204 + Kopete::Message msg = m_storedMessages.takeFirst();
1205 + msg.manager()->appendMessage(msg);
1209 +void OtrlChatInterface::chatSessionDestroyed(Kopete::ChatSession *chatSession)
1211 + QList<Kopete::Message> tmpList;
1212 + foreach (const Kopete::Message &msg, m_storedMessages) {
1213 + if (msg.manager() != chatSession) {
1214 + tmpList.append(msg);
1217 + m_storedMessages = tmpList;
1219 /****************** KeyGenThread *******************/
1221 KeyGenThread::KeyGenThread( const QString &accountname, const QString &protocol ){
1223 otrl_privkey_generate(OtrlChatInterface::self()->getUserstate(), storeFile.toLocal8Bit(), accountname.toLocal8Bit(), protocol.toLocal8Bit());
1224 OtrlChatInterface::self()->checkFilePermissions( QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "privkeys" );
1227 diff -urN kdenetwork-4.10.5.org/kopete/plugins/otr/otrlchatinterface.h kdenetwork-4.10.5/kopete/plugins/otr/otrlchatinterface.h
1228 --- kdenetwork-4.10.5.org/kopete/plugins/otr/otrlchatinterface.h 2013-06-28 20:08:21.437046228 +0200
1229 +++ kdenetwork-4.10.5/kopete/plugins/otr/otrlchatinterface.h 2013-07-10 21:39:55.606389116 +0200
1231 /*************************************************************************
1232 - * Copyright <2007> <Michael Zanetti> <michael_zanetti@gmx.net> *
1233 + * Copyright <2007 - 2013> <Michael Zanetti> <mzanetti@kde.org> *
1235 * This program is free software; you can redistribute it and/or *
1236 * modify it under the terms of the GNU General Public License as *
1238 #include <qstring.h>
1239 #include <qthread.h>
1241 +#include <qmetatype.h>
1242 +#include <qtimer.h>
1244 #include <kopete_export.h>
1245 #include <kopetechatsession.h>
1247 #include <libotr/userstate.h>
1250 +Q_DECLARE_METATYPE(otrl_instag_t)
1252 +class KeyGenThread;
1254 class KOPETE_OTR_SHARED_EXPORT OtrlChatInterface: public QObject
1257 ~OtrlChatInterface();
1258 static OtrlChatInterface *self();
1260 - int decryptMessage( QString *msg, const QString &accountId, const QString &protocol, const QString &contactId, Kopete::ChatSession *chatSession );
1261 - int encryptMessage( QString *msg, const QString &accountId,
1262 - const QString &protocol, const QString &contactId , Kopete::ChatSession *chatSession );
1263 + int decryptMessage( Kopete::Message &message );
1264 + int encryptMessage( Kopete::Message &message );
1265 QString getDefaultQuery( const QString &accountId );
1266 void disconnectSession( Kopete::ChatSession *chatSession );
1267 void setPolicy( OtrlPolicy policy );
1268 bool shouldDiscard( const QString &message );
1269 OtrlUserState getUserstate();
1270 int privState( Kopete::ChatSession *session );
1271 - QString formatContact( const QString &contactId);
1272 bool isVerified( Kopete::ChatSession *session );
1273 void checkFilePermissions( const QString &file );
1274 - QString findActiveFingerprint( Kopete::ChatSession *session );
1275 + QString fingerprint( Kopete::ChatSession *session );
1276 void verifyFingerprint( Kopete::ChatSession *session );
1277 void setPlugin(Kopete::Plugin *plugin);
1278 void emitGoneSecure(Kopete::ChatSession *sesseion, int state);
1280 void initSMPQ( ConnContext *context, Kopete::ChatSession *session, const QString &question, const QString &secret );
1281 void respondSMP( ConnContext *context, Kopete::ChatSession *session, const QString &secret );
1282 void setTrust( Kopete::ChatSession *session, bool trust );
1283 + void generatePrivateKey(const QString &account, const QString &protocol);
1285 + static QString formatContact( const QString &contactId);
1287 OtrlChatInterface();
1288 static OtrlChatInterface *mSelf;
1289 Fingerprint *findFingerprint( Kopete::ChatSession *session );
1290 + QList<uint> m_blackistIds;
1291 + KeyGenThread *m_keyGenThread;
1292 + QTimer m_forwardSecrecyTimer;
1293 + QList<Kopete::Message> m_storedMessages;
1295 + static OtrlMessageAppOps ui_ops;
1296 + static OtrlPolicy policy(void *opdata, ConnContext *context);
1297 + static void create_privkey(void *opdata, const char *accountname, const char *protocol);
1298 + static int is_logged_in(void *opdata, const char *accountname, const char *protocol, const char *recipient);
1299 + static void inject_message( void *opdata, const char *accountname, const char *protocol, const char *recipient, const char *message );
1300 + static void update_context_list(void *opdata);
1301 + static void new_fingerprint(void *opdata, OtrlUserState us, const char *accountname, const char *protocol, const char *username, unsigned char fingerprint[20]);
1302 + static void write_fingerprints(void *opdata);
1303 + static void gone_secure(void *opdata, ConnContext *context);
1304 + static void gone_insecure(void *opdata, ConnContext *context);
1305 + static void still_secure(void *opdata, ConnContext *context, int is_reply);
1306 + static int max_message_size(void *opdata, ConnContext *context);
1307 + static const char* otr_error_message(void *opdata, ConnContext *context, OtrlErrorCode err_code);
1308 + static void otr_error_message_free(void *opdata, const char *err_msg);
1309 + static const char *resent_msg_prefix(void *opdata, ConnContext *context);
1310 + static void resent_msg_prefix_free(void *opdata, const char *prefix);
1311 + static void handle_msg_event(void *opdata, OtrlMessageEvent msg_event, ConnContext *context, const char* message, gcry_error_t err);
1312 + static void handle_smp_event(void *opdata, OtrlSMPEvent smp_event, ConnContext *context, unsigned short progress_percent, char *question);
1313 + static void create_instag(void *opdata, const char *accountname, const char *protocol);
1314 + static void timer_control(void *opdata, unsigned int interval);
1317 + void otrlMessagePoll();
1318 + void replayStoredMessages();
1319 + void chatSessionDestroyed(Kopete::ChatSession *chatSession);
1322 void goneSecure(Kopete::ChatSession* session, int state);
1325 - class KeyGenThread : public QThread {
1326 +class KeyGenThread : public QThread {
1329 QString accountname;
1330 diff -urN kdenetwork-4.10.5.org/kopete/plugins/otr/otrlconfinterface.cpp kdenetwork-4.10.5/kopete/plugins/otr/otrlconfinterface.cpp
1331 --- kdenetwork-4.10.5.org/kopete/plugins/otr/otrlconfinterface.cpp 2013-06-28 20:08:21.940066273 +0200
1332 +++ kdenetwork-4.10.5/kopete/plugins/otr/otrlconfinterface.cpp 2013-07-10 21:39:55.609722565 +0200
1334 /*************************************************************************
1335 - * Copyright <2007> <Michael Zanetti> <michael_zanetti@gmx.net> *
1336 + * Copyright <2007 - 2013> <Michael Zanetti> <mzanetti@kde.org> *
1338 * This program is free software; you can redistribute it and/or *
1339 * modify it under the terms of the GNU General Public License as *
1342 popup->setCloseLock( true );
1344 - KeyGenThread *keyGenThread = new KeyGenThread ( accountId, protocol );
1345 - keyGenThread->start();
1346 - while( !keyGenThread->wait(100) ){
1347 - qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers, 100);
1349 + OtrlChatInterface::self()->generatePrivateKey(accountId, protocol);
1351 popup->setCloseLock( false );
1353 diff -urN kdenetwork-4.10.5.org/kopete/plugins/otr/otrplugin.cpp kdenetwork-4.10.5/kopete/plugins/otr/otrplugin.cpp
1354 --- kdenetwork-4.10.5.org/kopete/plugins/otr/otrplugin.cpp 2013-06-28 20:08:21.437046228 +0200
1355 +++ kdenetwork-4.10.5/kopete/plugins/otr/otrplugin.cpp 2013-07-10 21:39:55.609722565 +0200
1357 /*************************************************************************
1358 - * Copyright <2007> <Michael Zanetti> <michael_zanetti@gmx.net> *
1359 + * Copyright <2007 - 2013> <Michael Zanetti> <mzanetti@kde.org> *
1361 * This program is free software; you can redistribute it and/or *
1362 * modify it under the terms of the GNU General Public License as *
1363 @@ -153,68 +153,23 @@
1364 void OTRPlugin::slotOutgoingMessage( Kopete::Message& msg )
1366 if( msg.direction() == Kopete::Message::Outbound ){
1367 - QString accountId = msg.manager()->account()->accountId();
1368 - Kopete::Contact *contact = msg.to().first();
1371 - QString cacheBody;
1372 - bool plaintext = msg.format() == Qt::PlainText;
1373 - kDebug(14318) << "Message format is" << (plaintext ? "plaintext" : "richtext");
1375 - msgBody = msg.plainBody().replace('<', "<");
1376 - cacheBody = msgBody;
1378 - msgBody = msg.escapedBody();
1379 - cacheBody = msgBody;
1381 - kDebug(14318) << "Outgoing message before processing:" << msgBody << "escaped" << Kopete::Message::escape(msgBody);
1382 + QString cacheBody;
1383 + if(msg.format() == Qt::PlainText){
1384 + cacheBody = msg.plainBody().replace('<', "<");
1386 + cacheBody = msg.escapedBody();
1389 - int encryptionState = otrlChatInterface->encryptMessage( &msgBody, accountId, msg.manager()->account()->protocol()->displayName(), contact->contactId(), msg.manager() );
1390 + otrlChatInterface->encryptMessage( msg );
1392 - if(encryptionState == -1){
1393 - // Failure. Shouldn't happen. However, if it does DON'T
1394 - // send the message out in plaintext. overwrite with something else...
1395 - msg.setPlainBody(i18n("An error occurred while encrypting the message."));
1397 - } else if(encryptionState == 0){
1398 - kDebug(14318) << "Encrypted successfully";
1400 - // Always set plaintext if the message has been encrypted.
1401 - // The parser wouldn't understand anything after encryption anyways...
1402 - msg.setPlainBody( msgBody );
1403 - msg.setType(Kopete::Message::TypeNormal);
1404 - if( !msg.plainBody().isEmpty() ){
1405 - messageCache.insert( msgBody, cacheBody );
1407 - messageCache.insert( "!OTR:MsgDelByOTR", cacheBody );
1409 - } else if(encryptionState == 1){
1410 - kDebug(14318) << "Tagged plaintext!";
1412 - /* Here we have a problem... libotr tags messages with whitespaces to
1413 - be recognized by other clients. Those whitespaces are discarded
1414 - if we use setHtmlBody() and breaks opportunistic mode.
1415 - If we use setPlainBody() for messages containing tags, those tags
1416 - are escaped and will be visible in the other sides chatwindow.
1418 - This approach should always send out correct messages but will
1419 - break opportunistic mode if the user enables RTF formatting.
1420 - Sorry folks. No way to deal with this currently (Would need changes
1421 - in the rich text handling in libkopete).
1424 - msg.setPlainBody(msgBody);
1426 - msg.setHtmlBody(msgBody);
1429 - messageCache.insert( msgBody, cacheBody );
1431 - Don't touch msg If encryptionState is something else than above!!!
1434 + if( !msg.plainBody().isEmpty() ){
1435 + messageCache.insert( msg.plainBody(), cacheBody );
1437 + messageCache.insert( "!OTR:MsgDelByOTR", cacheBody );
1440 - kDebug(14318) << "Outgoing message after processing:" << msgBody << msg.format();
1441 + kDebug(14318) << "Outgoing message after processing:" << msg.plainBody() << msg.format();
1445 @@ -287,23 +242,22 @@
1450 Kopete::Message msg = event->message();
1451 // Kopete::ChatSession *session = msg.manager();
1452 QMap<QString, QString> messageCache = plugin->getMessageCache();
1454 - if( msg.direction() == Kopete::Message::Inbound ){
1455 - if( msg.type() == Kopete::Message::TypeFileTransferRequest )
1456 + kDebug(14318) << "OtrMessageHandler::handleMessage:" << msg.plainBody();
1458 + if( msg.direction() == Kopete::Message::Inbound){
1459 + if( msg.type() == Kopete::Message::TypeFileTransferRequest )
1461 // file transfers aren't encrypted. Proceed with next plugin
1462 MessageHandler::handleMessage( event );
1465 - QString body = msg.plainBody();
1466 - QString accountId = msg.manager()->account()->accountId();
1467 - QString contactId = msg.from()->contactId();
1468 - int retValue = OtrlChatInterface::self()->decryptMessage( &body, accountId, msg.manager()->account()->protocol()->displayName(), contactId, msg.manager() );
1469 - msg.setHtmlBody( body );
1470 - if( (retValue == 2) | OtrlChatInterface::self()->shouldDiscard( msg.plainBody() ) ){
1471 + int retValue = OtrlChatInterface::self()->decryptMessage( msg );
1472 + if( (retValue == 2) | OtrlChatInterface::self()->shouldDiscard( msg.plainBody() ) ){
1473 // internal OTR message