]>
Commit | Line | Data |
---|---|---|
a28bb935 AM |
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 | |
4 | @@ -22,15 +22,15 @@ | |
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) | |
12 | ||
13 | IF( LIBOTR_FOUND ) | |
14 | IF( NOT LIBOTR_FIND_QUIETLY ) | |
15 | MESSAGE( STATUS "Found libotr: ${LIBOTR_LIBRARY} (version ${LIBOTR_VERSION})") | |
16 | ENDIF( NOT LIBOTR_FIND_QUIETLY ) | |
17 | ELSE( LIBOTR_FOUND ) | |
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}.") | |
20 | ENDIF( LIBOTR_FOUND ) | |
21 | ||
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 | |
26 | @@ -92,7 +92,7 @@ | |
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.") | |
32 | ||
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 | |
38 | @@ -1,5 +1,5 @@ | |
39 | /************************************************************************* | |
40 | - * Copyright <2007> <Michael Zanetti> <michael_zanetti@gmx.net> * | |
41 | + * Copyright <2007 - 2013> <Michael Zanetti> <mzanetti@kde.org> * | |
42 | * * | |
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 * | |
45 | @@ -47,9 +47,9 @@ | |
46 | setAttribute(Qt::WA_DeleteOnClose); | |
47 | ||
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()); | |
58 | @@ -72,8 +72,9 @@ | |
59 | if ( session->account()->isBusy() ) | |
60 | return; | |
61 | ||
62 | + resize(rbMV->width() * 1.5, rbMV->width() * 0.75); | |
63 | show(); | |
64 | - | |
65 | + | |
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() ) ) ); | |
69 | @@ -83,7 +84,7 @@ | |
70 | connect( notification, SIGNAL(activated(uint)), SLOT(notificationActivated(uint)) ); | |
71 | notification->sendEvent(); | |
72 | } | |
73 | - | |
74 | + | |
75 | } | |
76 | ||
77 | ||
78 | @@ -97,7 +98,7 @@ | |
79 | return wizardList.at(i); | |
80 | } | |
81 | } | |
82 | - return 0; | |
83 | + return 0; | |
84 | } | |
85 | ||
86 | QWizardPage *AuthenticationWizard::createIntroPage(){ | |
87 | @@ -108,7 +109,7 @@ | |
88 | rbQA = new QRadioButton(i18n("Question and Answer")); | |
89 | rbSS = new QRadioButton(i18n("Shared Secret")); | |
90 | rbMV = new QRadioButton(i18n("Manual fingerprint verification")); | |
91 | - | |
92 | + | |
93 | QGroupBox *frame = new QGroupBox(); | |
94 | QVBoxLayout *frameLayout = new QVBoxLayout(); | |
95 | frame->setLayout(frameLayout); | |
96 | @@ -117,8 +118,8 @@ | |
97 | frameLayout->addWidget(infoLabel); | |
98 | ||
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); | |
105 | ||
106 | layout->addSpacing(30); | |
107 | @@ -126,7 +127,7 @@ | |
108 | ||
109 | page->setLayout(layout); | |
110 | ||
111 | - rbQA->setChecked(true); | |
112 | + rbQA->setChecked(true); | |
113 | ||
114 | return page; | |
115 | } | |
116 | @@ -176,7 +177,7 @@ | |
117 | layout->addWidget(new QLabel(i18nc("@info", "Enter the secret passphrase known only to you and %1:", session->members().first()->contactId()))); | |
118 | } | |
119 | leSecret = new QLineEdit(); | |
120 | - layout->addWidget(leSecret); | |
121 | + layout->addWidget(leSecret); | |
122 | ||
123 | page->setLayout(layout); | |
124 | page->setCommitPage(true); | |
125 | @@ -192,7 +193,7 @@ | |
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))); | |
131 | ||
132 | cbManualAuth = new QComboBox(); | |
133 | cbManualAuth->addItem(i18nc("@item:inlistbox ...verified that", "I have not")); | |
134 | @@ -330,9 +331,9 @@ | |
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()))); | |
136 | } | |
137 | } | |
138 | - | |
139 | + | |
140 | setOption(QWizard::NoCancelButton, true); | |
141 | - | |
142 | + | |
143 | } | |
144 | ||
145 | void AuthenticationWizard::aborted(){ | |
146 | @@ -347,7 +348,7 @@ | |
147 | } | |
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()))); | |
150 | - | |
151 | + | |
152 | setOption(QWizard::NoCancelButton, true); | |
153 | } | |
154 | ||
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 | |
158 | @@ -1,5 +1,5 @@ | |
159 | /************************************************************************* | |
160 | - * Copyright <2007> <Michael Zanetti> <michael_zanetti@gmx.net> * | |
161 | + * Copyright <2007 - 2013> <Michael Zanetti> <mzanetti@kde.org> * | |
162 | * * | |
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 * | |
165 | @@ -63,13 +63,13 @@ | |
166 | static Kopete::Plugin *chatPlugin = 0; | |
167 | ||
168 | /***************************** Gui_UI_Ops for libotr **********************************/ | |
169 | -static OtrlPolicy policy(void *opdata, ConnContext *context){ | |
170 | +OtrlPolicy OtrlChatInterface::policy(void *opdata, ConnContext *context){ | |
171 | ||
172 | Q_UNUSED(context) | |
173 | ||
174 | Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata); | |
175 | bool noerr; | |
176 | - | |
177 | + | |
178 | // Disable OTR for IRC | |
179 | if( session->protocol()->pluginId() == "IRCProtocol" ){ | |
180 | // kdDebug() << "Disabling OTR for: " << session->protocol()->pluginId() << endl; | |
181 | @@ -92,7 +92,9 @@ | |
182 | } | |
183 | } | |
184 | ||
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) | |
188 | + Q_UNUSED(protocol) | |
189 | Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata); | |
190 | ||
191 | if( !session->view() ){ | |
192 | @@ -102,23 +104,21 @@ | |
193 | popup->show(); | |
194 | popup->setCloseLock( true ); | |
195 | ||
196 | - KeyGenThread *keyGenThread = new KeyGenThread ( accountname, protocol ); | |
197 | - keyGenThread->start(); | |
198 | - while( !keyGenThread->wait(100) ){ | |
199 | - qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers, 100); | |
200 | - } | |
201 | + OtrlChatInterface::self()->generatePrivateKey(session->account()->accountId(), session->protocol()->displayName()); | |
202 | ||
203 | popup->setCloseLock( false ); | |
204 | popup->close(); | |
205 | + | |
206 | + OtrlChatInterface::self()->replayStoredMessages(); | |
207 | } | |
208 | ||
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){ | |
211 | ||
212 | Q_UNUSED(accountname) | |
213 | Q_UNUSED(protocol) | |
214 | ||
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) ); | |
221 | @@ -134,7 +134,7 @@ | |
222 | return -1; | |
223 | } | |
224 | ||
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 ){ | |
227 | ||
228 | Q_UNUSED(accountname) | |
229 | Q_UNUSED(protocol) | |
230 | @@ -142,7 +142,7 @@ | |
231 | // kDebug(14318) << "Sending message:" << message; | |
232 | ||
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 @@ | |
240 | } | |
241 | } | |
242 | ||
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){ | |
244 | - | |
245 | - Q_UNUSED(opdata) | |
246 | - Q_UNUSED(level) | |
247 | - Q_UNUSED(accountname) | |
248 | - Q_UNUSED(protocol) | |
249 | - Q_UNUSED(username) | |
250 | - | |
251 | - KMessageBox::information(NULL, QString( primary ) + QString( secondary ), QString( title ) ); | |
252 | -} | |
253 | - | |
254 | -static int display_otr_message( void *opdata, const char *accountname, const char *protocol, const char *username, const char *message ){ | |
255 | - | |
256 | - Q_UNUSED(accountname) | |
257 | - Q_UNUSED(protocol) | |
258 | - | |
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 ); | |
267 | - return 0; | |
268 | - } | |
269 | - } | |
270 | - return 1; | |
271 | -} | |
272 | - | |
273 | -static void update_context_list(void *opdata){ | |
274 | +void OtrlChatInterface::update_context_list(void *opdata){ | |
275 | //Not used... | |
276 | Q_UNUSED(opdata) | |
277 | } | |
278 | ||
279 | -static const char *protocol_name(void *opdata, const char *protocol){ | |
280 | -//Never seen... | |
281 | - | |
282 | - Q_UNUSED(opdata) | |
283 | - Q_UNUSED(protocol) | |
284 | - | |
285 | -// kdDebug() << "protocol_name called" << endl; | |
286 | - return 0; | |
287 | -} | |
288 | - | |
289 | -static void protocol_name_free(void *opdata, const char *protocol_name){ | |
290 | -//Never seen... | |
291 | - | |
292 | - Q_UNUSED(opdata) | |
293 | - Q_UNUSED(protocol_name) | |
294 | - | |
295 | -// kdDebug() << "protocol_name_free called" << endl; | |
296 | -} | |
297 | - | |
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]){ | |
300 | ||
301 | Q_UNUSED(us) | |
302 | Q_UNUSED(accountname) | |
303 | @@ -224,7 +175,7 @@ | |
304 | session->appendMessage( msg ); | |
305 | } | |
306 | ||
307 | -static void write_fingerprints(void *opdata){ | |
308 | +void OtrlChatInterface::write_fingerprints(void *opdata){ | |
309 | ||
310 | Q_UNUSED(opdata) | |
311 | ||
312 | @@ -233,8 +184,7 @@ | |
313 | otrl_privkey_write_fingerprints( userstate, savePath.toLocal8Bit() ); | |
314 | } | |
315 | ||
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); | |
320 | ||
321 | if( context->active_fingerprint->trust && context->active_fingerprint->trust[0] ){ | |
322 | @@ -250,9 +200,11 @@ | |
323 | session->appendMessage( msg ); | |
324 | OtrlChatInterface::self()->emitGoneSecure( ((Kopete::ChatSession*)opdata), 1 ); | |
325 | } | |
326 | + | |
327 | + session->setProperty("otr-instag", QString::number(context->their_instance)); | |
328 | } | |
329 | ||
330 | -static void gone_insecure(void *opdata, ConnContext *context){ | |
331 | +void OtrlChatInterface::gone_insecure(void *opdata, ConnContext *context){ | |
332 | ||
333 | Q_UNUSED(context) | |
334 | ||
335 | @@ -265,12 +217,12 @@ | |
336 | session->appendMessage( msg ); | |
337 | } | |
338 | ||
339 | -static void still_secure(void *opdata, ConnContext *context, int is_reply){ | |
340 | +void OtrlChatInterface::still_secure(void *opdata, ConnContext *context, int is_reply){ | |
341 | ||
342 | Q_UNUSED(is_reply) | |
343 | ||
344 | -// kdDebug() << "still secure" << endl; | |
345 | Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata); | |
346 | + | |
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 @@ | |
351 | } | |
352 | } | |
353 | ||
354 | -static void log_message(void *opdata, const char *message){ | |
355 | - | |
356 | - Q_UNUSED(opdata) | |
357 | - | |
358 | - kDebug(14318) << "libotr: "<< message; | |
359 | -} | |
360 | - | |
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); | |
364 | ||
365 | Q_UNUSED(context) | |
366 | - | |
367 | + | |
368 | kDebug(14318) << session->protocol()->pluginId(); | |
369 | ||
370 | if( session->protocol()->pluginId() == "WlmProtocol" ){ | |
371 | @@ -305,32 +250,264 @@ | |
372 | return 1274; | |
373 | } else if( session->protocol()->pluginId() == "YahooProtocol" ){ | |
374 | return 700; | |
375 | - } | |
376 | + } | |
377 | ||
378 | // Jabber doesn't need fragmentation. Return 0 to disable. | |
379 | // GaduGadu seems to not need fragmentation too. | |
380 | return 0; | |
381 | } | |
382 | ||
383 | -static OtrlMessageAppOps ui_ops = { | |
384 | - policy, | |
385 | - create_privkey, | |
386 | - is_logged_in, | |
387 | - inject_message, | |
388 | - notify, | |
389 | - display_otr_message, | |
390 | - update_context_list, | |
391 | - protocol_name, | |
392 | - protocol_name_free, | |
393 | - new_fingerprint, | |
394 | - write_fingerprints, | |
395 | - gone_secure, | |
396 | - gone_insecure, | |
397 | - still_secure, | |
398 | - log_message, | |
399 | - max_message_size, | |
400 | - 0, //not used yet... | |
401 | - 0 //not used yet... | |
402 | +const char* OtrlChatInterface::otr_error_message(void *opdata, ConnContext *context, OtrlErrorCode err_code) { | |
403 | + Q_UNUSED(opdata) | |
404 | + | |
405 | + char *err_msg = 0; | |
406 | + switch (err_code) | |
407 | + { | |
408 | + case OTRL_ERRCODE_NONE : | |
409 | + break; | |
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()); | |
415 | + break; | |
416 | + } | |
417 | + case OTRL_ERRCODE_MSG_NOT_IN_PRIVATE : | |
418 | + if (context) { | |
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()); | |
423 | + } | |
424 | + break; | |
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()); | |
430 | + break; | |
431 | + } | |
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()); | |
437 | + break; | |
438 | + } | |
439 | + } | |
440 | + return err_msg; | |
441 | +} | |
442 | + | |
443 | +void OtrlChatInterface::otr_error_message_free(void *opdata, const char *err_msg) { | |
444 | + Q_UNUSED(opdata) | |
445 | + if (err_msg) { | |
446 | + free((char*)err_msg); | |
447 | + } | |
448 | +} | |
449 | + | |
450 | +const char *OtrlChatInterface::resent_msg_prefix(void *opdata, ConnContext *context) { | |
451 | + Q_UNUSED(opdata) | |
452 | + Q_UNUSED(context) | |
453 | + | |
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()); | |
458 | + return msg_prefix; | |
459 | +} | |
460 | + | |
461 | +void OtrlChatInterface::resent_msg_prefix_free(void *opdata, const char *prefix) { | |
462 | + Q_UNUSED(opdata) | |
463 | + | |
464 | + if (prefix) { | |
465 | + free((char*)prefix); | |
466 | + } | |
467 | +} | |
468 | + | |
469 | +void OtrlChatInterface::handle_smp_event(void *opdata, OtrlSMPEvent smp_event, ConnContext *context, unsigned short progress_percent, char *question) { | |
470 | + Q_UNUSED(progress_percent) | |
471 | + | |
472 | + Kopete::ChatSession *chatSession = (Kopete::ChatSession*)opdata; | |
473 | + | |
474 | + if (!context) { | |
475 | + return; | |
476 | + } | |
477 | + | |
478 | + switch (smp_event) { | |
479 | + case OTRL_SMPEVENT_NONE : | |
480 | + break; | |
481 | + case OTRL_SMPEVENT_ASK_FOR_SECRET : | |
482 | + new AuthenticationWizard( chatSession->view(true)->mainWidget(), context, chatSession, false ); | |
483 | + break; | |
484 | + case OTRL_SMPEVENT_ASK_FOR_ANSWER : | |
485 | + new AuthenticationWizard( chatSession->view(true)->mainWidget(), context, chatSession, false, QLatin1String(question) ); | |
486 | + break; | |
487 | + case OTRL_SMPEVENT_IN_PROGRESS : | |
488 | + AuthenticationWizard::findWizard(chatSession)->nextState(); | |
489 | + break; | |
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 ); | |
499 | + } else { | |
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 ); | |
507 | + } | |
508 | + break; | |
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 ); | |
516 | + break; | |
517 | + } | |
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 ); | |
523 | + break; | |
524 | + } | |
525 | +} | |
526 | + | |
527 | +void OtrlChatInterface::handle_msg_event(void *opdata, OtrlMessageEvent msg_event, ConnContext *context, const char* message, gcry_error_t err) { | |
528 | + | |
529 | + Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata); | |
530 | + Kopete::ContactPtrList list = session->members(); | |
531 | + Kopete::Message msg( session->members().first(), session->account()->myself() ); | |
532 | + | |
533 | + switch (msg_event) | |
534 | + { | |
535 | + case OTRL_MSGEVENT_NONE: | |
536 | + break; | |
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 ); | |
540 | + break; | |
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 ); | |
544 | + break; | |
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 ); | |
548 | + break; | |
549 | + case OTRL_MSGEVENT_SETUP_ERROR: | |
550 | + if (!err) { | |
551 | + err = GPG_ERR_INV_VALUE; | |
552 | + } | |
553 | + switch(gcry_err_code(err)) { | |
554 | + case GPG_ERR_INV_VALUE: | |
555 | + kDebug(14318) << "Error setting up private conversation: Malformed message received"; | |
556 | + default: | |
557 | + kDebug(14318) << "Error setting up private conversation:" << err; | |
558 | + } | |
559 | + | |
560 | + msg.setHtmlBody( i18n( "OTR error" ) ); | |
561 | + msg.setDirection( Kopete::Message::Internal ); | |
562 | + break; | |
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 ); | |
566 | + break; | |
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 ); | |
570 | + break; | |
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()); | |
575 | + break; | |
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 ); | |
579 | + break; | |
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 ); | |
583 | + break; | |
584 | + case OTRL_MSGEVENT_LOG_HEARTBEAT_RCVD: | |
585 | + kDebug(14318) << "Heartbeat received from" << context->username; | |
586 | + return; | |
587 | + case OTRL_MSGEVENT_LOG_HEARTBEAT_SENT: | |
588 | + kDebug(14318) << "Heartbeat sent to" << context->username; | |
589 | + break; | |
590 | + case OTRL_MSGEVENT_RCVDMSG_GENERAL_ERR: | |
591 | + msg.setHtmlBody( QLatin1String(message) ); | |
592 | + msg.setDirection( Kopete::Message::Internal ); | |
593 | + session->appendMessage( msg ); | |
594 | + break; | |
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()); | |
599 | + break; | |
600 | + case OTRL_MSGEVENT_RCVDMSG_UNRECOGNIZED: | |
601 | + kDebug(14318) << "Unrecognized OTR message received from" << context->username; | |
602 | + break; | |
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()); | |
607 | + break; | |
608 | + } | |
609 | + | |
610 | + session->appendMessage( msg ); | |
611 | +} | |
612 | + | |
613 | +void OtrlChatInterface::create_instag(void *opdata, const char *accountname, const char *protocol) { | |
614 | + Q_UNUSED(opdata) | |
615 | + QString storeFile = QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "instags"; | |
616 | + otrl_instag_generate(OtrlChatInterface::self()->getUserstate(), storeFile.toLocal8Bit(), accountname, protocol); | |
617 | +} | |
618 | + | |
619 | +void OtrlChatInterface::timer_control(void *opdata, unsigned int interval) { | |
620 | + Q_UNUSED(opdata) | |
621 | + if (interval > 0) { | |
622 | + OtrlChatInterface::self()->m_forwardSecrecyTimer.start(interval * 1000); | |
623 | + } else { | |
624 | + OtrlChatInterface::self()->m_forwardSecrecyTimer.stop(); | |
625 | + } | |
626 | +} | |
627 | + | |
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 | |
653 | }; | |
654 | ||
655 | /*********************** Gui_UI_Ops finished *************************/ | |
656 | @@ -338,25 +515,31 @@ | |
657 | ||
658 | /*********************** Constructor/Destructor **********************/ | |
659 | ||
660 | -OtrlChatInterface::OtrlChatInterface(){ | |
661 | +OtrlChatInterface::OtrlChatInterface(): | |
662 | + m_keyGenThread(0) | |
663 | +{ | |
664 | mSelf = this; | |
665 | - OTRL_INIT; | |
666 | + OTRL_INIT; | |
667 | ||
668 | userstate = otrl_userstate_create(); | |
669 | QString readPath = QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "privkeys"; | |
670 | otrl_privkey_read( userstate, readPath.toLocal8Bit() ); | |
671 | - | |
672 | - | |
673 | - QString savePath = QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "fingerprints"; | |
674 | - otrl_privkey_read_fingerprints(userstate, savePath.toLocal8Bit(), NULL, NULL); | |
675 | ||
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())); | |
679 | + | |
680 | + readPath = QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "fingerprints"; | |
681 | + otrl_privkey_read_fingerprints(userstate, readPath.toLocal8Bit(), NULL, NULL); | |
682 | + | |
683 | + readPath = QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true)) + "instags"; | |
684 | + otrl_instag_read(userstate, readPath.toLocal8Bit()); | |
685 | } | |
686 | ||
687 | OtrlChatInterface::~ OtrlChatInterface(){ | |
688 | otrl_userstate_free(userstate); | |
689 | } | |
690 | ||
691 | - | |
692 | OtrlChatInterface *OtrlChatInterface::self(){ | |
693 | if( !mSelf ){ | |
694 | new OtrlChatInterface(); | |
695 | @@ -375,159 +558,59 @@ | |
696 | } | |
697 | ||
698 | ||
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){ | |
702 | ||
703 | - int ignoremessage; | |
704 | - char *newMessage = NULL; | |
705 | - OtrlTLV *tlvs = NULL; | |
706 | - OtrlTLV *tlv = NULL; | |
707 | - ConnContext *context; | |
708 | - NextExpectedSMP nextMsg; | |
709 | - | |
710 | - ignoremessage = otrl_message_receiving( userstate, &ui_ops, chatSession, accountId.toLocal8Bit(), protocol.toLocal8Bit(), contactId.toLocal8Bit(), msg->toLocal8Bit(), &newMessage, &tlvs, NULL, NULL ); | |
711 | - | |
712 | - tlv = otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED); | |
713 | - if( tlv ){ | |
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()); | |
721 | + return 1; | |
722 | } | |
723 | ||
724 | - context = otrl_context_find( userstate, contactId.toLocal8Bit(), accountId.toLocal8Bit(), protocol.toLocal8Bit(), 0, NULL, NULL, NULL); | |
725 | - if (context) { | |
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(); | |
732 | ||
733 | + OtrlTLV *tlvs = NULL; | |
734 | + char *newMessage = NULL; | |
735 | ||
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; | |
740 | - } else { | |
741 | - tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1Q); | |
742 | - if (tlv) { | |
743 | - if (nextMsg != OTRL_SMP_EXPECT1){ | |
744 | - kDebug(14318) << "Abording SMP: 1Q"; | |
745 | - abortSMP( context, chatSession ); | |
746 | - } else { | |
747 | - kDebug(14318) << "Update SMP state: 1Q"; | |
748 | - new AuthenticationWizard( chatSession->view(true)->mainWidget(), context, chatSession, false, QString((char*)tlvs->data) ); | |
749 | - } | |
750 | - } | |
751 | + if (m_keyGenThread != 0) { | |
752 | + // Currently generating the private key... must be a plaintext message anyways... | |
753 | ||
754 | - tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1); | |
755 | - if (tlv) { | |
756 | - if (nextMsg != OTRL_SMP_EXPECT1){ | |
757 | - kDebug(14318) << "Abording SMP: 1"; | |
758 | - abortSMP( context, chatSession ); | |
759 | - } else { | |
760 | - kDebug(14318) << "Update SMP state: 1 "; | |
761 | - new AuthenticationWizard( chatSession->view(true)->mainWidget(), context, chatSession, false ); | |
762 | - } | |
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); | |
767 | } | |
768 | - tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP2); | |
769 | - if (tlv) { | |
770 | - if (nextMsg != OTRL_SMP_EXPECT2){ | |
771 | - kDebug(14318) << "Abording SMP: 2"; | |
772 | - abortSMP( context, chatSession ); | |
773 | - } else { | |
774 | - kDebug(14318) << "Update SMP state: 2 -> 3"; | |
775 | - AuthenticationWizard::findWizard(chatSession)->nextState(); | |
776 | - context->smstate->nextExpected = OTRL_SMP_EXPECT4; | |
777 | - } | |
778 | - } | |
779 | - tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP3); | |
780 | - if (tlv) { | |
781 | - if (nextMsg != OTRL_SMP_EXPECT3){ | |
782 | - kDebug(14318) << "Abording SMP: 3"; | |
783 | - abortSMP( context, chatSession ); | |
784 | - } else { | |
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 ); | |
795 | - } else { | |
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 ); | |
803 | - } | |
804 | - | |
805 | - } else { | |
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 ); | |
812 | + return 1; | |
813 | + } | |
814 | ||
815 | - } | |
816 | - context->smstate->nextExpected = OTRL_SMP_EXPECT1; | |
817 | - } | |
818 | - } | |
819 | - tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP4); | |
820 | - if (tlv) { | |
821 | - if (nextMsg != OTRL_SMP_EXPECT4) { | |
822 | - kDebug(14318) << "Abording SMP: 4"; | |
823 | - abortSMP( context, chatSession ); | |
824 | - } else { | |
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 ); | |
834 | - } else { | |
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 ); | |
842 | - } | |
843 | - context->smstate->nextExpected = OTRL_SMP_EXPECT1; | |
844 | - } | |
845 | - } | |
846 | - tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP_ABORT); | |
847 | - if (tlv) { | |
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 ); | |
850 | + | |
851 | + ConnContext *context = otrl_context_find( userstate, contactId.toLocal8Bit(), accountId.toLocal8Bit(), protocol.toLocal8Bit(), 0, 0, NULL, NULL, NULL); | |
852 | + if (context) { | |
853 | + OtrlTLV *tlv = otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED); | |
854 | + if( tlv ){ | |
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); | |
861 | - if(currentWizard){ | |
862 | - currentWizard->aborted(); | |
863 | - } | |
864 | - context->smstate->nextExpected = OTRL_SMP_EXPECT1; | |
865 | + OtrlChatInterface::self()->emitGoneSecure( chatSession, 3 ); | |
866 | + | |
867 | + otrl_tlv_free(tlvs); | |
868 | } | |
869 | - | |
870 | - otrl_tlv_free(tlvs); | |
871 | - } | |
872 | + | |
873 | } | |
874 | - | |
875 | + | |
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 ); | |
886 | + | |
887 | return 0; // message is decrypted and ready to deliver | |
888 | } else { | |
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. | |
892 | } | |
893 | ||
894 | -int OtrlChatInterface::encryptMessage( QString *msg, const QString &accountId, | |
895 | - const QString &protocol, const QString &contactId , Kopete::ChatSession *chatSession ){ | |
896 | - int err; | |
897 | +int OtrlChatInterface::encryptMessage( Kopete::Message &message ){ | |
898 | char *newMessage = 0; | |
899 | - char *fragment = 0; | |
900 | ||
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 ); | |
904 | - | |
905 | - if( err != 0 ){ | |
906 | - return -1; | |
907 | - } else if( newMessage ){ | |
908 | + QString msgBody; | |
909 | + bool plaintext = message.format() == Qt::PlainText; | |
910 | ||
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); | |
914 | + if(plaintext){ | |
915 | + msgBody = message.plainBody().replace('<', "<"); | |
916 | + } else { | |
917 | + msgBody = message.escapedBody(); | |
918 | + } | |
919 | ||
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(); | |
925 | ||
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 ){ | |
929 | ||
930 | -// kDebug(14318) << "fragment left to be sent by kopete: " << fragment; | |
931 | + otrl_instag_t instance = message.manager()->property("otr-instag").toUInt(); | |
932 | ||
933 | - if( err != 0){ | |
934 | - *msg = i18n("Encryption error"); | |
935 | - } else if ( fragment ){ | |
936 | - *msg = QString::fromUtf8( fragment ); | |
937 | - otrl_message_free( newMessage ); | |
938 | - otrl_message_free( fragment ); | |
939 | - } | |
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 ); | |
944 | + | |
945 | + if( err != 0 ){ | |
946 | + message.setPlainBody(i18n("An error occurred while encrypting the message.")); | |
947 | + return -1; | |
948 | + } else if (newMessage) { | |
949 | + msgBody = QString::fromUtf8(newMessage); | |
950 | + otrl_message_free(newMessage); | |
951 | + } | |
952 | + | |
953 | + | |
954 | + OtrlMessageType type = otrl_proto_message_type( msgBody.toLatin1() ); | |
955 | + if( type == OTRL_MSGTYPE_TAGGEDPLAINTEXT ){ | |
956 | + kDebug(14318) << "Tagged plaintext!"; | |
957 | + | |
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. | |
963 | + | |
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). | |
968 | + */ | |
969 | + if(plaintext){ | |
970 | + message.setPlainBody(msgBody); | |
971 | + } else { | |
972 | + message.setHtmlBody(msgBody); | |
973 | } | |
974 | - return 0; // Encrypted successfully | |
975 | + return 1; | |
976 | } | |
977 | + | |
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); | |
982 | + return 0; | |
983 | } | |
984 | - | |
985 | + | |
986 | return 2; // Message is still plaintext. Better not touching it | |
987 | } | |
988 | ||
989 | QString OtrlChatInterface::getDefaultQuery( const QString &accountId ){ | |
990 | char *message; | |
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 ); | |
995 | return msg; | |
996 | } | |
997 | ||
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 ); | |
1003 | ||
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 ); | |
1009 | - | |
1010 | } | |
1011 | ||
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: | |
1020 | return false; | |
1021 | default: | |
1022 | @@ -622,33 +725,35 @@ | |
1023 | ||
1024 | ||
1025 | int OtrlChatInterface::privState( Kopete::ChatSession *session ){ | |
1026 | - ConnContext *context; | |
1027 | - | |
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; | |
1032 | + } | |
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); | |
1034 | ||
1035 | if( context ){ | |
1036 | switch( context->msgstate ){ | |
1037 | - case OTRL_MSGSTATE_PLAINTEXT: | |
1038 | - return 0; | |
1039 | - case OTRL_MSGSTATE_ENCRYPTED: | |
1040 | - if( context->active_fingerprint->trust && context->active_fingerprint->trust[0] != '\0' ) | |
1041 | - return 2; | |
1042 | - else | |
1043 | - return 1; | |
1044 | - case OTRL_MSGSTATE_FINISHED: | |
1045 | - return 3; | |
1046 | + case OTRL_MSGSTATE_PLAINTEXT: | |
1047 | + return 0; | |
1048 | + case OTRL_MSGSTATE_ENCRYPTED: | |
1049 | + if( context->active_fingerprint->trust && context->active_fingerprint->trust[0] != '\0' ) | |
1050 | + return 2; | |
1051 | + else | |
1052 | + return 1; | |
1053 | + case OTRL_MSGSTATE_FINISHED: | |
1054 | + return 3; | |
1055 | } | |
1056 | } | |
1057 | return 0; | |
1058 | -} | |
1059 | + } | |
1060 | + | |
1061 | + QString OtrlChatInterface::formatContact(const QString &contactId){ | |
1062 | ||
1063 | -QString OtrlChatInterface::formatContact(const QString &contactId){ | |
1064 | - | |
1065 | Kopete::MetaContact *metaContact = Kopete::ContactList::self()->findMetaContactByContactId(contactId); | |
1066 | if( metaContact ){ | |
1067 | QString displayName = metaContact->displayName(); | |
1068 | if((displayName != contactId) && !displayName.isNull()){ | |
1069 | - return displayName + " (" + contactId + ')'; | |
1070 | + return displayName + " (" + contactId + ')'; | |
1071 | } | |
1072 | } | |
1073 | return contactId; | |
1074 | @@ -657,7 +762,8 @@ | |
1075 | void OtrlChatInterface::verifyFingerprint( Kopete::ChatSession *session ){ | |
1076 | ConnContext *context; | |
1077 | ||
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); | |
1081 | ||
1082 | new AuthenticationWizard( session->view()->mainWidget(), context, session, true ); | |
1083 | } | |
1084 | @@ -665,33 +771,34 @@ | |
1085 | Fingerprint *OtrlChatInterface::findFingerprint( Kopete::ChatSession *session ){ | |
1086 | ConnContext *context; | |
1087 | ||
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; | |
1092 | - } | |
1093 | + | |
1094 | + otrl_instag_t instance = session->property("otr-instag").toUInt(); | |
1095 | + if (instance == 0) { | |
1096 | + instance = OTRL_INSTAG_BEST; | |
1097 | + } | |
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; | |
1101 | } | |
1102 | return NULL; | |
1103 | } | |
1104 | ||
1105 | -QString OtrlChatInterface::findActiveFingerprint( Kopete::ChatSession *session ){ | |
1106 | - ConnContext *context; | |
1107 | +QString OtrlChatInterface::fingerprint( Kopete::ChatSession *session ){ | |
1108 | char hash[45]; | |
1109 | + memset(hash, 0, 45); | |
1110 | ||
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 ); | |
1115 | - return hash; | |
1116 | - } | |
1117 | + Fingerprint *fp = findFingerprint(session); | |
1118 | + if (fp) { | |
1119 | + otrl_privkey_hash_to_human( hash, fp->fingerprint ); | |
1120 | + return QLatin1String(hash); | |
1121 | + } | |
1122 | + | |
1123 | + return QString(); | |
1124 | } | |
1125 | - return NULL; | |
1126 | -} | |
1127 | ||
1128 | -bool OtrlChatInterface::isVerified( Kopete::ChatSession *session ){ | |
1129 | + bool OtrlChatInterface::isVerified( Kopete::ChatSession *session ){ | |
1130 | Fingerprint *fingerprint = findFingerprint( session ); | |
1131 | ||
1132 | - kDebug() << "fingerprint" << fingerprint; | |
1133 | if( fingerprint->trust && fingerprint->trust[0] != '\0' ){ | |
1134 | return true; | |
1135 | } else { | |
1136 | @@ -710,7 +817,7 @@ | |
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); | |
1142 | } | |
1143 | } | |
1144 | ||
1145 | @@ -738,6 +845,17 @@ | |
1146 | } | |
1147 | } | |
1148 | ||
1149 | +void OtrlChatInterface::generatePrivateKey(const QString &account, const QString &protocol) | |
1150 | +{ | |
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); | |
1155 | + } | |
1156 | + m_keyGenThread->deleteLater(); | |
1157 | + m_keyGenThread = 0; | |
1158 | +} | |
1159 | + | |
1160 | /****************** SMP implementations ****************/ | |
1161 | ||
1162 | void OtrlChatInterface::abortSMP( ConnContext *context, Kopete::ChatSession *session ){ | |
1163 | @@ -753,7 +871,6 @@ | |
1164 | } | |
1165 | ||
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() ); | |
1169 | ||
1170 | Kopete::Message msg( session->members().first(), session->account()->myself() ); | |
1171 | @@ -761,11 +878,9 @@ | |
1172 | msg.setDirection( Kopete::Message::Internal ); | |
1173 | ||
1174 | session->appendMessage( msg ); | |
1175 | - | |
1176 | } | |
1177 | ||
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() ); | |
1181 | ||
1182 | Kopete::Message msg( session->members().first(), session->account()->myself() ); | |
1183 | @@ -777,7 +892,7 @@ | |
1184 | ||
1185 | void OtrlChatInterface::respondSMP( ConnContext *context, Kopete::ChatSession *session, const QString &secret ){ | |
1186 | ||
1187 | - kDebug(14318) << "resonding SMP"; | |
1188 | + kDebug(14318) << "resonding SMP"; | |
1189 | ||
1190 | otrl_message_respond_smp( userstate, &ui_ops, session, context, (unsigned char*)secret.toLocal8Bit().data(), secret.length()); | |
1191 | ||
1192 | @@ -788,6 +903,29 @@ | |
1193 | session->appendMessage( msg ); | |
1194 | } | |
1195 | ||
1196 | +void OtrlChatInterface::otrlMessagePoll() | |
1197 | +{ | |
1198 | + otrl_message_poll(userstate, 0, 0); | |
1199 | +} | |
1200 | + | |
1201 | +void OtrlChatInterface::replayStoredMessages() | |
1202 | +{ | |
1203 | + while (m_storedMessages.isEmpty()) { | |
1204 | + Kopete::Message msg = m_storedMessages.takeFirst(); | |
1205 | + msg.manager()->appendMessage(msg); | |
1206 | + } | |
1207 | +} | |
1208 | + | |
1209 | +void OtrlChatInterface::chatSessionDestroyed(Kopete::ChatSession *chatSession) | |
1210 | +{ | |
1211 | + QList<Kopete::Message> tmpList; | |
1212 | + foreach (const Kopete::Message &msg, m_storedMessages) { | |
1213 | + if (msg.manager() != chatSession) { | |
1214 | + tmpList.append(msg); | |
1215 | + } | |
1216 | + } | |
1217 | + m_storedMessages = tmpList; | |
1218 | +} | |
1219 | /****************** KeyGenThread *******************/ | |
1220 | ||
1221 | KeyGenThread::KeyGenThread( const QString &accountname, const QString &protocol ){ | |
1222 | @@ -802,3 +940,4 @@ | |
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" ); | |
1225 | } | |
1226 | + | |
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 | |
1230 | @@ -1,5 +1,5 @@ | |
1231 | /************************************************************************* | |
1232 | - * Copyright <2007> <Michael Zanetti> <michael_zanetti@gmx.net> * | |
1233 | + * Copyright <2007 - 2013> <Michael Zanetti> <mzanetti@kde.org> * | |
1234 | * * | |
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 * | |
1237 | @@ -28,6 +28,8 @@ | |
1238 | #include <qstring.h> | |
1239 | #include <qthread.h> | |
1240 | #include <qmutex.h> | |
1241 | +#include <qmetatype.h> | |
1242 | +#include <qtimer.h> | |
1243 | ||
1244 | #include <kopete_export.h> | |
1245 | #include <kopetechatsession.h> | |
1246 | @@ -42,6 +44,9 @@ | |
1247 | #include <libotr/userstate.h> | |
1248 | } | |
1249 | ||
1250 | +Q_DECLARE_METATYPE(otrl_instag_t) | |
1251 | + | |
1252 | +class KeyGenThread; | |
1253 | ||
1254 | class KOPETE_OTR_SHARED_EXPORT OtrlChatInterface: public QObject | |
1255 | { | |
1256 | @@ -50,19 +55,17 @@ | |
1257 | ~OtrlChatInterface(); | |
1258 | static OtrlChatInterface *self(); | |
1259 | ||
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); | |
1279 | @@ -71,17 +74,49 @@ | |
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); | |
1284 | ||
1285 | + static QString formatContact( const QString &contactId); | |
1286 | private: | |
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; | |
1294 | + | |
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); | |
1315 | + | |
1316 | +private slots: | |
1317 | + void otrlMessagePoll(); | |
1318 | + void replayStoredMessages(); | |
1319 | + void chatSessionDestroyed(Kopete::ChatSession *chatSession); | |
1320 | ||
1321 | signals: | |
1322 | void goneSecure(Kopete::ChatSession* session, int state); | |
1323 | }; | |
1324 | ||
1325 | - class KeyGenThread : public QThread { | |
1326 | +class KeyGenThread : public QThread { | |
1327 | ||
1328 | private: | |
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 | |
1333 | @@ -1,5 +1,5 @@ | |
1334 | /************************************************************************* | |
1335 | - * Copyright <2007> <Michael Zanetti> <michael_zanetti@gmx.net> * | |
1336 | + * Copyright <2007 - 2013> <Michael Zanetti> <mzanetti@kde.org> * | |
1337 | * * | |
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 * | |
1340 | @@ -83,11 +83,7 @@ | |
1341 | popup->show(); | |
1342 | popup->setCloseLock( true ); | |
1343 | ||
1344 | - KeyGenThread *keyGenThread = new KeyGenThread ( accountId, protocol ); | |
1345 | - keyGenThread->start(); | |
1346 | - while( !keyGenThread->wait(100) ){ | |
1347 | - qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers, 100); | |
1348 | - } | |
1349 | + OtrlChatInterface::self()->generatePrivateKey(accountId, protocol); | |
1350 | ||
1351 | popup->setCloseLock( false ); | |
1352 | popup->close(); | |
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 | |
1356 | @@ -1,5 +1,5 @@ | |
1357 | /************************************************************************* | |
1358 | - * Copyright <2007> <Michael Zanetti> <michael_zanetti@gmx.net> * | |
1359 | + * Copyright <2007 - 2013> <Michael Zanetti> <mzanetti@kde.org> * | |
1360 | * * | |
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 ) | |
1365 | { | |
1366 | if( msg.direction() == Kopete::Message::Outbound ){ | |
1367 | - QString accountId = msg.manager()->account()->accountId(); | |
1368 | - Kopete::Contact *contact = msg.to().first(); | |
1369 | ||
1370 | - QString msgBody; | |
1371 | - QString cacheBody; | |
1372 | - bool plaintext = msg.format() == Qt::PlainText; | |
1373 | - kDebug(14318) << "Message format is" << (plaintext ? "plaintext" : "richtext"); | |
1374 | - if(plaintext){ | |
1375 | - msgBody = msg.plainBody().replace('<', "<"); | |
1376 | - cacheBody = msgBody; | |
1377 | - } else { | |
1378 | - msgBody = msg.escapedBody(); | |
1379 | - cacheBody = msgBody; | |
1380 | - } | |
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('<', "<"); | |
1385 | + } else { | |
1386 | + cacheBody = msg.escapedBody(); | |
1387 | + } | |
1388 | ||
1389 | - int encryptionState = otrlChatInterface->encryptMessage( &msgBody, accountId, msg.manager()->account()->protocol()->displayName(), contact->contactId(), msg.manager() ); | |
1390 | + otrlChatInterface->encryptMessage( msg ); | |
1391 | ||
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.")); | |
1396 | - | |
1397 | - } else if(encryptionState == 0){ | |
1398 | - kDebug(14318) << "Encrypted successfully"; | |
1399 | - | |
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 ); | |
1406 | - } else { | |
1407 | - messageCache.insert( "!OTR:MsgDelByOTR", cacheBody ); | |
1408 | - } | |
1409 | - } else if(encryptionState == 1){ | |
1410 | - kDebug(14318) << "Tagged plaintext!"; | |
1411 | - | |
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. | |
1417 | - | |
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). | |
1422 | - */ | |
1423 | - if(plaintext){ | |
1424 | - msg.setPlainBody(msgBody); | |
1425 | - } else { | |
1426 | - msg.setHtmlBody(msgBody); | |
1427 | - } | |
1428 | - | |
1429 | - messageCache.insert( msgBody, cacheBody ); | |
1430 | - } /* else { | |
1431 | - Don't touch msg If encryptionState is something else than above!!! | |
1432 | - } */ | |
1433 | - | |
1434 | + if( !msg.plainBody().isEmpty() ){ | |
1435 | + messageCache.insert( msg.plainBody(), cacheBody ); | |
1436 | + } else { | |
1437 | + messageCache.insert( "!OTR:MsgDelByOTR", cacheBody ); | |
1438 | + } | |
1439 | ||
1440 | - kDebug(14318) << "Outgoing message after processing:" << msgBody << msg.format(); | |
1441 | + kDebug(14318) << "Outgoing message after processing:" << msg.plainBody() << msg.format(); | |
1442 | } | |
1443 | } | |
1444 | ||
1445 | @@ -287,23 +242,22 @@ | |
1446 | return; | |
1447 | } | |
1448 | ||
1449 | + | |
1450 | Kopete::Message msg = event->message(); | |
1451 | // Kopete::ChatSession *session = msg.manager(); | |
1452 | QMap<QString, QString> messageCache = plugin->getMessageCache(); | |
1453 | ||
1454 | - if( msg.direction() == Kopete::Message::Inbound ){ | |
1455 | - if( msg.type() == Kopete::Message::TypeFileTransferRequest ) | |
1456 | + kDebug(14318) << "OtrMessageHandler::handleMessage:" << msg.plainBody(); | |
1457 | + | |
1458 | + if( msg.direction() == Kopete::Message::Inbound){ | |
1459 | + if( msg.type() == Kopete::Message::TypeFileTransferRequest ) | |
1460 | { | |
1461 | // file transfers aren't encrypted. Proceed with next plugin | |
1462 | MessageHandler::handleMessage( event ); | |
1463 | return; | |
1464 | } | |
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 | |
1474 | event->discard(); | |
1475 | return; | |
1476 |