[packages/kde4-kopete] - initial
arekm
arekm at pld-linux.org
Fri Nov 1 23:01:51 CET 2013
commit a28bb93533dff593e0babc3038c0a49c4474f892
Author: Arkadiusz Miśkiewicz <arekm at maven.pl>
Date: Fri Nov 1 23:01:36 2013 +0100
- initial
kde4-kopete-FindLibgadu.patch | 42 ++
kde4-kopete.spec | 209 ++++++
linphone-fix.patch | 20 +
otr.patch | 1476 +++++++++++++++++++++++++++++++++++++++++
4 files changed, 1747 insertions(+)
---
diff --git a/kde4-kopete.spec b/kde4-kopete.spec
new file mode 100644
index 0000000..0a07555
--- /dev/null
+++ b/kde4-kopete.spec
@@ -0,0 +1,209 @@
+# TODO:
+# - add missing obsoletes and such
+
+%define _state stable
+%define orgname kopete
+%define qtver 4.8.3
+
+Summary: Multi-protocol plugin-based instant messenger
+Summary(pl.UTF-8): Komunikator obsługujący wiele protokołów
+Name: kde4-kopete
+Version: 4.11.3
+Release: 1
+License: GPL v2+
+Group: X11/Applications
+Source0: ftp://ftp.kde.org/pub/kde/%{_state}/%{version}/src/%{orgname}-%{version}.tar.xz
+# Source0-md5: cf98891ab800ff565b8077bfd6f2e498
+Patch0: %{name}-FindLibgadu.patch
+Patch1: linphone-fix.patch
+Patch2: otr.patch
+URL: http://www.kde.org/
+BuildRequires: cmake >= 2.8.0
+BuildRequires: kde4-kdebase-devel >= %{version}
+BuildRequires: libgadu-devel >= 1.8.0
+BuildRequires: libktorrent-devel >= 1.0.2
+BuildRequires: libmms-devel
+BuildRequires: libmsn-devel >= 4.1
+BuildRequires: libotr-devel >= 4.0.0
+BuildRequires: openssl-devel >= 0.9.7d
+BuildRequires: ortp-devel >= 0.16.1-3
+BuildRequires: qt4-build >= %{qtver}
+BuildRequires: qt4-qmake >= %{qtver}
+BuildRequires: rpm-pythonprov
+BuildRequires: rpmbuild(macros) >= 1.600
+BuildRequires: speex-devel
+BuildRequires: telepathy-qt4-devel >= 0.9.0
+BuildRequires: xmms-devel
+BuildRequires: xorg-lib-libXdamage-devel
+BuildRequires: xorg-lib-libXtst-devel
+Obsoletes: kde4-kdenetwork-kopete
+Obsoletes: kde4-kdenetwork-kopete-protocol-aim
+Obsoletes: kde4-kdenetwork-kopete-protocol-bonjour
+Obsoletes: kde4-kdenetwork-kopete-protocol-gg
+Obsoletes: kde4-kdenetwork-kopete-protocol-groupwise
+Obsoletes: kde4-kdenetwork-kopete-protocol-icq
+Obsoletes: kde4-kdenetwork-kopete-protocol-jabber
+Obsoletes: kde4-kdenetwork-kopete-protocol-meanwhile
+Obsoletes: kde4-kdenetwork-kopete-protocol-skype
+Obsoletes: kde4-kdenetwork-kopete-protocol-sms
+Obsoletes: kde4-kdenetwork-kopete-protocol-winpopup
+Obsoletes: kde4-kdenetwork-kopete-protocol-wlm
+Obsoletes: kde4-kdenetwork-kopete-protocol-yahoo
+Obsoletes: kde4-kdenetwork-kopete-tool-autoreplace
+Obsoletes: kde4-kdenetwork-kopete-tool-avdeviceconfig
+Obsoletes: kde4-kdenetwork-kopete-tool-contactnotes
+Obsoletes: kde4-kdenetwork-kopete-tool-highlight
+Obsoletes: kde4-kdenetwork-kopete-tool-history
+Obsoletes: kde4-kdenetwork-kopete-tool-latex
+Obsoletes: kde4-kdenetwork-kopete-tool-nowlistening
+Obsoletes: kde4-kdenetwork-kopete-tool-texteffect
+Obsoletes: kde4-kdenetwork-kopete-tool-translator
+Obsoletes: kde4-kdenetwork-kopete-tool-webpresence
+Obsoletes: kde4-kdenetwork-libkopete
+Obsoletes: kde4-kdenetwork-libkopete_oscar
+Obsoletes: kde4-kdenetwork-libkopete_otr
+Obsoletes: kde4-kdenetwork-libkopete_videodevice
+Obsoletes: kopete
+Obsoletes: kopete-plugin-protocols-aim
+Obsoletes: kopete-plugin-protocols-gg
+Obsoletes: kopete-plugin-protocols-icq
+Obsoletes: kopete-plugin-protocols-irc
+Obsoletes: kopete-plugin-protocols-jabber
+Obsoletes: kopete-plugin-protocols-msn
+Obsoletes: kopete-plugin-protocols-oscar
+Obsoletes: kopete-plugin-protocols-sms
+Obsoletes: kopete-plugin-protocols-winpopup
+Obsoletes: kopete-plugin-protocols-yahoo
+Obsoletes: kopete-plugin-tools-autoaway
+Obsoletes: kopete-plugin-tools-autoreplace
+Obsoletes: kopete-plugin-tools-conectionstatus
+Obsoletes: kopete-plugin-tools-contactnotes
+Obsoletes: kopete-plugin-tools-cryptography
+Obsoletes: kopete-plugin-tools-highlight
+Obsoletes: kopete-plugin-tools-history
+Obsoletes: kopete-plugin-tools-importer
+Obsoletes: kopete-plugin-tools-motionaway
+Obsoletes: kopete-plugin-tools-nowlistening
+Obsoletes: kopete-plugin-tools-spellcheck
+Obsoletes: kopete-plugin-tools-texteffect
+Obsoletes: kopete-plugin-tools-translator
+Obsoletes: kopete-plugin-tools-webpresence
+BuildRoot: %{tmpdir}/%{name}-%{version}-root-%(id -u -n)
+
+%description
+Kopete is a flexible and extendable multiple protocol instant
+messaging system designed as a plugin-based system. All protocols are
+plugins and allow modular installment, configuration, and usage
+without the main application knowing anything about the plugin being
+loaded. The goal of Kopete is to provide users with a standard and
+easy to use interface between all of their instant messaging systems,
+but at the same time also providing developers with the ease of
+writing plugins to support a new protocol. The core Kopete development
+team provides a handful of plugins that most users can use, in
+addition to templates for new developers to base a plugin off of.
+
+%description -l pl.UTF-8
+Kopete to rozszerzalny i rozbudowywalny komunikator obsługujący wiele
+protokołów, zaprojektowany w oparciu o wtyczki. Wszystkie protokoły są
+wtyczkami, co pozwala na modularną instalację, konfigurację i używanie
+bez potrzeby obsługi ładowanych wtyczek w głównej aplikacji. Celem
+Kopete jest wyposażenie użytkowników w standardowy i łatwy w użyciu
+interfejs pomiędzy wszystkimi systemami komunikatorów, a jednocześnie
+zapewnienie programistom łatwości pisania wtyczek obsługujących nowe
+protokoły. Załoga programistów Kopete udostępnia podręczny zestaw
+wtyczek używanych przez większość użytkowników oraz szablony dla
+nowych programistów, na których można opierać nowe wtyczki.
+
+%package devel
+Summary: kopete header files
+Summary(pl.UTF-8): Pliki nagłówkowe kopete
+Group: X11/Development/Libraries
+Requires: %{name} = %{version}-%{release}
+Requires: kde4-kdelibs-devel >= %{version}
+
+%description devel
+kopete header files.
+
+%description devel -l pl.UTF-8
+Pliki nagłówkowe kopete.
+
+%description devel -l pt_BR.UTF-8
+Arquivos de inclusão para compilar aplicações que usem as bibliotecas
+do kopete.
+
+%prep
+%setup -q -n %{orgname}-%{version}
+%patch0 -p1
+%patch1 -p2
+%patch2 -p2
+
+%build
+install -d build
+cd build
+%cmake \
+ -DMOZPLUGIN_INSTALL_DIR=%{_browserpluginsdir} \
+ ../
+
+%{__make}
+
+%install
+rm -rf $RPM_BUILD_ROOT
+
+%{__make} -C build install \
+ DESTDIR=$RPM_BUILD_ROOT \
+ kde_htmldir=%{_kdedocdir}
+
+%find_lang kopete --with-kde
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post
+/sbin/ldconfig
+%update_browser_plugins
+
+%postun
+/sbin/ldconfig
+if [ "$1" = 0 ]; then
+ %update_browser_plugins
+fi
+
+%files -f kopete.lang
+%defattr(644,root,root,755)
+%attr(755,root,root) %{_bindir}/googletalk-call
+%attr(755,root,root) %{_bindir}/kopete
+%attr(755,root,root) %{_bindir}/kopete_latexconvert.sh
+%attr(755,root,root) %{_bindir}/winpopup-install
+%attr(755,root,root) %{_bindir}/winpopup-send
+%attr(755,root,root) %{_libdir}/kde4/kcm_kopete_*.so
+%attr(755,root,root) %{_libdir}/kde4/kopete_*.so
+%attr(755,root,root) %{_libdir}/kde4/libchattexteditpart.so
+%attr(755,root,root) %{_libdir}/kde4/plugins/accessible/chatwindowaccessiblewidgetfactory.so
+%attr(755,root,root) %{_libdir}/libkopete*.so.*.*
+%attr(755,root,root) %ghost %{_libdir}/libkopete*.so.?
+%attr(755,root,root) %{_libdir}/libkyahoo.so.*.*
+%attr(755,root,root) %ghost %{_libdir}/libkyahoo.so.1
+%attr(755,root,root) %{_libdir}/liboscar.so.*.*
+%attr(755,root,root) %ghost %{_libdir}/liboscar.so.1
+%{_desktopdir}/kde4/kopete.desktop
+%attr(755,root,root) %{_datadir}/apps/kconf_update/kopete-*.pl
+%attr(755,root,root) %{_datadir}/apps/kconf_update/kopete-*.sh
+%{_datadir}/apps/kconf_update/kopete-*.upd
+%{_datadir}/apps/kopete*
+%{_datadir}/config.kcfg/*.kcfg
+%{_datadir}/config/kopeterc
+%{_datadir}/dbus-1/interfaces/*Kopete.xml
+%{_datadir}/dbus-1/interfaces/*kopete*.xml
+%{_iconsdir}/*/*/*/*.mng
+%{_iconsdir}/*/*/*/*.png
+%{_iconsdir}/*/*/*/*.svgz
+%{_datadir}/kde4/services/*.protocol
+%{_datadir}/kde4/services/*.desktop
+%{_datadir}/kde4/services/kconfiguredialog/*.desktop
+%{_datadir}/kde4/servicetypes/*.desktop
+%{_datadir}/sounds/Kopete*.ogg
+
+%files devel
+%defattr(644,root,root,755)
+%attr(755,root,root) %{_libdir}/lib*.so
+%{_includedir}/kopete
diff --git a/kde4-kopete-FindLibgadu.patch b/kde4-kopete-FindLibgadu.patch
new file mode 100644
index 0000000..829db5c
--- /dev/null
+++ b/kde4-kopete-FindLibgadu.patch
@@ -0,0 +1,42 @@
+--- kopete/cmake/modules/FindLibgadu.cmake 2009-06-17 22:08:12.000000000 +0200
++++ kopete/cmake/modules/FindLibgadu.cmake-new 2009-07-04 16:49:57.586710508 +0200
+@@ -23,32 +23,18 @@
+ find_package (PkgConfig)
+ pkg_check_modules (PC_LIBGADU libgadu)
+
+- # If pkgconfig found libgadu, get the full path to the library using find_library()
+- # but only in the path reported by pkgconfig.
+- # Otherwise do a normal search.
+- if (PC_LIBGADU_FOUND)
+-
+- set (LIBGADU_DEFINITIONS ${PC_LIBGADU_CFLAGS})
+-
+- if (PC_LIBGADU_INCLUDE_DIRS)
+- set (LIBGADU_INCLUDE_DIR ${PC_LIBGADU_INCLUDE_DIRS})
+- else (PC_LIBGADU_INCLUDE_DIRS)
+- find_path (LIBGADU_INCLUDE_DIR libgadu.h PATH_SUFFIXES libgadu)
+- endif (PC_LIBGADU_INCLUDE_DIRS)
++ find_path (LIBGADU_INCLUDE_DIR libgadu.h
++ PATHS
++ /usr/include
++ )
+
+ find_library (LIBGADU_LIBRARIES NAMES gadu
+ PATHS
+- ${PC_LIBGADU_LIBDIR}
++ /usr/lib64
++ /usr/lib
+ NO_DEFAULT_PATH
+ )
+
+- else (PC_LIBGADU_FOUND)
+-
+- find_library (LIBGADU_LIBRARIES NAMES gadu)
+- find_path (LIBGADU_INCLUDE_DIR libgadu.h PATH_SUFFIXES libgadu)
+-
+- endif (PC_LIBGADU_FOUND)
+-
+ else (NOT WIN32)
+
+ find_library_with_debug (LIBGADU_LIBRARIES
+
diff --git a/linphone-fix.patch b/linphone-fix.patch
new file mode 100644
index 0000000..bcb4a01
--- /dev/null
+++ b/linphone-fix.patch
@@ -0,0 +1,20 @@
+--- kde4-kdenetwork/kopete/protocols/jabber/googletalk/libjingle/talk/session/phone/linphonemediaengine.cc~ 2013-06-20 09:15:17.773243467 +0200
++++ kde4-kdenetwork/kopete/protocols/jabber/googletalk/libjingle/talk/session/phone/linphonemediaengine.cc 2013-06-20 09:27:03.157408216 +0200
+@@ -200,7 +200,7 @@
+ LOG(LS_INFO) << "Using " << i->name << "/" << i->clockrate;
+ pt_ = i->id;
+ audio_stream_ = audio_stream_start(&av_profile, -1, "localhost", port1, i->id, 250, 0); /* -1 means that function will choose some free port */
+- port2 = rtp_session_get_local_port(audio_stream_->session);
++ port2 = rtp_session_get_local_port(audio_stream_->ms.session);
+ first = false;
+ }
+ }
+@@ -211,7 +211,7 @@
+ // working with a buggy client; let's try PCMU.
+ LOG(LS_WARNING) << "Received empty list of codces; using PCMU/8000";
+ audio_stream_ = audio_stream_start(&av_profile, -1, "localhost", port1, 0, 250, 0); /* -1 means that function will choose some free port */
+- port2 = rtp_session_get_local_port(audio_stream_->session);
++ port2 = rtp_session_get_local_port(audio_stream_->ms.session);
+ }
+
+ return true;
diff --git a/otr.patch b/otr.patch
new file mode 100644
index 0000000..1fa2162
--- /dev/null
+++ b/otr.patch
@@ -0,0 +1,1476 @@
+diff -urN kdenetwork-4.10.5.org/kopete/cmake/modules/FindLibOTR.cmake kdenetwork-4.10.5/kopete/cmake/modules/FindLibOTR.cmake
+--- kdenetwork-4.10.5.org/kopete/cmake/modules/FindLibOTR.cmake 2013-06-28 20:08:21.924065636 +0200
++++ kdenetwork-4.10.5/kopete/cmake/modules/FindLibOTR.cmake 2013-07-10 21:40:19.770555778 +0200
+@@ -22,15 +22,15 @@
+ EXECUTE_PROCESS(COMMAND grep "OTRL_VERSION" "${LIBOTR_INCLUDE_DIR}/libotr/version.h" OUTPUT_VARIABLE output)
+ STRING(REGEX MATCH "OTRL_VERSION \"[0-9]+\\.[0-9]+\\.[0-9]+" LIBOTR_VERSION "${output}")
+ STRING(REGEX REPLACE "^OTRL_VERSION \"" "" LIBOTR_VERSION "${LIBOTR_VERSION}")
+- # Check if version is at least 3.2.0
+- MACRO_ENSURE_VERSION_RANGE("3.2.0" ${LIBOTR_VERSION} "4.0.0" LIBOTR_FOUND)
++ # Check if version is at least 4.0.0
++ MACRO_ENSURE_VERSION_RANGE("4.0.0" ${LIBOTR_VERSION} "5.0.0" LIBOTR_FOUND)
+
+ IF( LIBOTR_FOUND )
+ IF( NOT LIBOTR_FIND_QUIETLY )
+ MESSAGE( STATUS "Found libotr: ${LIBOTR_LIBRARY} (version ${LIBOTR_VERSION})")
+ ENDIF( NOT LIBOTR_FIND_QUIETLY )
+ ELSE( LIBOTR_FOUND )
+- MESSAGE(STATUS "libotr version between 3.2.0 and 4.0.0 required but found ${LIBOTR_VERSION}.")
++ MESSAGE(STATUS "libotr version between 4.0.0 and 5.0.0 required but found ${LIBOTR_VERSION}.")
+ ENDIF( LIBOTR_FOUND )
+
+ ENDIF( LIBOTR_INCLUDE_DIR AND LIBOTR_LIBRARY )
+diff -urN kdenetwork-4.10.5.org/kopete/CMakeLists.txt kdenetwork-4.10.5/kopete/CMakeLists.txt
+--- kdenetwork-4.10.5.org/kopete/CMakeLists.txt 2013-06-28 20:08:21.923065596 +0200
++++ kdenetwork-4.10.5/kopete/CMakeLists.txt 2013-07-10 21:41:02.638700604 +0200
+@@ -92,7 +92,7 @@
+ # TODO: fix otr plugin to make it work sith LibOTR 4
+ macro_optional_find_package(LibOTR)
+ macro_bool_to_01(LIBOTR_FOUND HAVE_LIBOTR)
+-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.")
++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.")
+
+ macro_optional_find_package(Libmsn)
+ macro_bool_to_01(LIBMSN_FOUND HAVE_LIBMSN)
+diff -urN kdenetwork-4.10.5.org/kopete/plugins/otr/authenticationwizard.cpp kdenetwork-4.10.5/kopete/plugins/otr/authenticationwizard.cpp
+--- kdenetwork-4.10.5.org/kopete/plugins/otr/authenticationwizard.cpp 2013-06-28 20:08:21.435046148 +0200
++++ kdenetwork-4.10.5/kopete/plugins/otr/authenticationwizard.cpp 2013-07-10 21:39:55.593055323 +0200
+@@ -1,5 +1,5 @@
+ /*************************************************************************
+- * Copyright <2007> <Michael Zanetti> <michael_zanetti at gmx.net> *
++ * Copyright <2007 - 2013> <Michael Zanetti> <mzanetti at kde.org> *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+@@ -47,9 +47,9 @@
+ setAttribute(Qt::WA_DeleteOnClose);
+
+ setPage(Page_SelectMethod, createIntroPage());
+- setPage(Page_QuestionAnswer, createQAPage());
+- setPage(Page_SharedSecret, createSSPage());
+- setPage(Page_ManualVerification, createMVPage());
++ setPage(Page_QuestionAnswer, createQAPage());
++ setPage(Page_SharedSecret, createSSPage());
++ setPage(Page_ManualVerification, createMVPage());
+ setPage(Page_Wait1, new WaitPage(i18n("Waiting for %1...", OtrlChatInterface::self()->formatContact(session->members().first()->contactId()))));
+ setPage(Page_Wait2, new WaitPage(i18n("Checking if answers match...")));
+ setPage(Page_Final, createFinalPage());
+@@ -72,8 +72,9 @@
+ if ( session->account()->isBusy() )
+ return;
+
++ resize(rbMV->width() * 1.5, rbMV->width() * 0.75);
+ show();
+-
++
+ if ( !session->view()->mainWidget() || !session->view()->mainWidget()->isActiveWindow() ) {
+ KNotification *notification = new KNotification( "kopete_info_event", KNotification::CloseWhenWidgetActivated | KNotification::CloseOnTimeout );
+ notification->setText( i18n( "Incoming authentication request from %1", OtrlChatInterface::self()->formatContact( session->members().first()->contactId() ) ) );
+@@ -83,7 +84,7 @@
+ connect( notification, SIGNAL(activated(uint)), SLOT(notificationActivated(uint)) );
+ notification->sendEvent();
+ }
+-
++
+ }
+
+
+@@ -97,7 +98,7 @@
+ return wizardList.at(i);
+ }
+ }
+- return 0;
++ return 0;
+ }
+
+ QWizardPage *AuthenticationWizard::createIntroPage(){
+@@ -108,7 +109,7 @@
+ rbQA = new QRadioButton(i18n("Question and Answer"));
+ rbSS = new QRadioButton(i18n("Shared Secret"));
+ rbMV = new QRadioButton(i18n("Manual fingerprint verification"));
+-
++
+ QGroupBox *frame = new QGroupBox();
+ QVBoxLayout *frameLayout = new QVBoxLayout();
+ frame->setLayout(frameLayout);
+@@ -117,8 +118,8 @@
+ frameLayout->addWidget(infoLabel);
+
+ QVBoxLayout *layout = new QVBoxLayout();
+- layout->addWidget(rbQA);
+- layout->addWidget(rbSS);
++ layout->addWidget(rbQA);
++ layout->addWidget(rbSS);
+ layout->addWidget(rbMV);
+
+ layout->addSpacing(30);
+@@ -126,7 +127,7 @@
+
+ page->setLayout(layout);
+
+- rbQA->setChecked(true);
++ rbQA->setChecked(true);
+
+ return page;
+ }
+@@ -176,7 +177,7 @@
+ layout->addWidget(new QLabel(i18nc("@info", "Enter the secret passphrase known only to you and %1:", session->members().first()->contactId())));
+ }
+ leSecret = new QLineEdit();
+- layout->addWidget(leSecret);
++ layout->addWidget(leSecret);
+
+ page->setLayout(layout);
+ page->setCommitPage(true);
+@@ -192,7 +193,7 @@
+ QLabel *lMessage1 = new QLabel(i18nc("@info", "Contact %1 via another secure channel and verify that the following fingerprint is correct:", session->members().first()->contactId()));
+ lMessage1->setWordWrap(true);
+ layout->addWidget(lMessage1);
+- layout->addWidget(new QLabel(OtrlChatInterface::self()->findActiveFingerprint(session)));
++ layout->addWidget(new QLabel(OtrlChatInterface::self()->fingerprint(session)));
+
+ cbManualAuth = new QComboBox();
+ cbManualAuth->addItem(i18nc("@item:inlistbox ...verified that", "I have not"));
+@@ -330,9 +331,9 @@
+ 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())));
+ }
+ }
+-
++
+ setOption(QWizard::NoCancelButton, true);
+-
++
+ }
+
+ void AuthenticationWizard::aborted(){
+@@ -347,7 +348,7 @@
+ }
+ currentPage()->setTitle(i18n("Authentication aborted"));
+ 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())));
+-
++
+ setOption(QWizard::NoCancelButton, true);
+ }
+
+diff -urN kdenetwork-4.10.5.org/kopete/plugins/otr/otrlchatinterface.cpp kdenetwork-4.10.5/kopete/plugins/otr/otrlchatinterface.cpp
+--- kdenetwork-4.10.5.org/kopete/plugins/otr/otrlchatinterface.cpp 2013-06-28 20:08:21.437046228 +0200
++++ kdenetwork-4.10.5/kopete/plugins/otr/otrlchatinterface.cpp 2013-07-10 21:39:55.609722565 +0200
+@@ -1,5 +1,5 @@
+ /*************************************************************************
+- * Copyright <2007> <Michael Zanetti> <michael_zanetti at gmx.net> *
++ * Copyright <2007 - 2013> <Michael Zanetti> <mzanetti at kde.org> *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+@@ -63,13 +63,13 @@
+ static Kopete::Plugin *chatPlugin = 0;
+
+ /***************************** Gui_UI_Ops for libotr **********************************/
+-static OtrlPolicy policy(void *opdata, ConnContext *context){
++OtrlPolicy OtrlChatInterface::policy(void *opdata, ConnContext *context){
+
+ Q_UNUSED(context)
+
+ Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
+ bool noerr;
+-
++
+ // Disable OTR for IRC
+ if( session->protocol()->pluginId() == "IRCProtocol" ){
+ // kdDebug() << "Disabling OTR for: " << session->protocol()->pluginId() << endl;
+@@ -92,7 +92,9 @@
+ }
+ }
+
+-static void create_privkey(void *opdata, const char *accountname, const char *protocol){
++void OtrlChatInterface::create_privkey(void *opdata, const char *accountname, const char *protocol){
++ Q_UNUSED(accountname)
++ Q_UNUSED(protocol)
+ Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
+
+ if( !session->view() ){
+@@ -102,23 +104,21 @@
+ popup->show();
+ popup->setCloseLock( true );
+
+- KeyGenThread *keyGenThread = new KeyGenThread ( accountname, protocol );
+- keyGenThread->start();
+- while( !keyGenThread->wait(100) ){
+- qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers, 100);
+- }
++ OtrlChatInterface::self()->generatePrivateKey(session->account()->accountId(), session->protocol()->displayName());
+
+ popup->setCloseLock( false );
+ popup->close();
++
++ OtrlChatInterface::self()->replayStoredMessages();
+ }
+
+-static int is_logged_in(void *opdata, const char *accountname, const char *protocol, const char *recipient){
++int OtrlChatInterface::is_logged_in(void *opdata, const char *accountname, const char *protocol, const char *recipient){
+
+ Q_UNUSED(accountname)
+ Q_UNUSED(protocol)
+
+ Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
+- Kopete::ContactPtrList list = session->members();
++ Kopete::ContactPtrList list = session->members();
+ for( int i = 0; i < list.size(); i++ ){
+ if( list.at(i)->contactId().compare( recipient) == 0 ){
+ Kopete::OnlineStatus status = session->contactOnlineStatus( list.at(i) );
+@@ -134,7 +134,7 @@
+ return -1;
+ }
+
+-static void inject_message( void *opdata, const char *accountname, const char *protocol, const char *recipient, const char *message ){
++void OtrlChatInterface::inject_message( void *opdata, const char *accountname, const char *protocol, const char *recipient, const char *message ){
+
+ Q_UNUSED(accountname)
+ Q_UNUSED(protocol)
+@@ -142,7 +142,7 @@
+ // kDebug(14318) << "Sending message:" << message;
+
+ Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
+- Kopete::ContactPtrList list = session->members();
++ Kopete::ContactPtrList list = session->members();
+ for( int i = 0; i < list.size(); i++ ){
+ if( list.at(i)->contactId().compare( recipient ) == 0 ){
+ Kopete::Message msg( session->account()->myself(), list.at(i) );
+@@ -154,61 +154,12 @@
+ }
+ }
+
+-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){
+-
+- Q_UNUSED(opdata)
+- Q_UNUSED(level)
+- Q_UNUSED(accountname)
+- Q_UNUSED(protocol)
+- Q_UNUSED(username)
+-
+- KMessageBox::information(NULL, QString( primary ) + QString( secondary ), QString( title ) );
+-}
+-
+-static int display_otr_message( void *opdata, const char *accountname, const char *protocol, const char *username, const char *message ){
+-
+- Q_UNUSED(accountname)
+- Q_UNUSED(protocol)
+-
+- Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
+- Kopete::ContactPtrList list = session->members();
+- for( int i = 0; i < list.size(); i++ ){
+- if( list.at(i)->contactId().compare( username ) == 0 ){
+- Kopete::Message msg( session->members().first(), session->account()->myself() );
+- msg.setHtmlBody( QString( message ) );
+- msg.setDirection( Kopete::Message::Internal );
+- session->appendMessage( msg );
+- return 0;
+- }
+- }
+- return 1;
+-}
+-
+-static void update_context_list(void *opdata){
++void OtrlChatInterface::update_context_list(void *opdata){
+ //Not used...
+ Q_UNUSED(opdata)
+ }
+
+-static const char *protocol_name(void *opdata, const char *protocol){
+-//Never seen...
+-
+- Q_UNUSED(opdata)
+- Q_UNUSED(protocol)
+-
+-// kdDebug() << "protocol_name called" << endl;
+- return 0;
+-}
+-
+-static void protocol_name_free(void *opdata, const char *protocol_name){
+-//Never seen...
+-
+- Q_UNUSED(opdata)
+- Q_UNUSED(protocol_name)
+-
+-// kdDebug() << "protocol_name_free called" << endl;
+-}
+-
+-static void new_fingerprint(void *opdata, OtrlUserState us, const char *accountname, const char *protocol, const char *username, unsigned char fingerprint[20]){
++void OtrlChatInterface::new_fingerprint(void *opdata, OtrlUserState us, const char *accountname, const char *protocol, const char *username, unsigned char fingerprint[20]){
+
+ Q_UNUSED(us)
+ Q_UNUSED(accountname)
+@@ -224,7 +175,7 @@
+ session->appendMessage( msg );
+ }
+
+-static void write_fingerprints(void *opdata){
++void OtrlChatInterface::write_fingerprints(void *opdata){
+
+ Q_UNUSED(opdata)
+
+@@ -233,8 +184,7 @@
+ otrl_privkey_write_fingerprints( userstate, savePath.toLocal8Bit() );
+ }
+
+-static void gone_secure(void *opdata, ConnContext *context){
+-// kdDebug() << "gone secure" << endl;
++void OtrlChatInterface::gone_secure(void *opdata, ConnContext *context){
+ Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
+
+ if( context->active_fingerprint->trust && context->active_fingerprint->trust[0] ){
+@@ -250,9 +200,11 @@
+ session->appendMessage( msg );
+ OtrlChatInterface::self()->emitGoneSecure( ((Kopete::ChatSession*)opdata), 1 );
+ }
++
++ session->setProperty("otr-instag", QString::number(context->their_instance));
+ }
+
+-static void gone_insecure(void *opdata, ConnContext *context){
++void OtrlChatInterface::gone_insecure(void *opdata, ConnContext *context){
+
+ Q_UNUSED(context)
+
+@@ -265,12 +217,12 @@
+ session->appendMessage( msg );
+ }
+
+-static void still_secure(void *opdata, ConnContext *context, int is_reply){
++void OtrlChatInterface::still_secure(void *opdata, ConnContext *context, int is_reply){
+
+ Q_UNUSED(is_reply)
+
+-// kdDebug() << "still secure" << endl;
+ Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
++
+ Kopete::Message msg( session->members().first(), session->account()->myself() );
+ msg.setHtmlBody( i18n("<b>OTR connection refreshed successfully.</b>") );
+ msg.setDirection( Kopete::Message::Internal );
+@@ -283,18 +235,11 @@
+ }
+ }
+
+-static void log_message(void *opdata, const char *message){
+-
+- Q_UNUSED(opdata)
+-
+- kDebug(14318) << "libotr: "<< message;
+-}
+-
+-static int max_message_size(void *opdata, ConnContext *context){
++int OtrlChatInterface::max_message_size(void *opdata, ConnContext *context){
+ Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
+
+ Q_UNUSED(context)
+-
++
+ kDebug(14318) << session->protocol()->pluginId();
+
+ if( session->protocol()->pluginId() == "WlmProtocol" ){
+@@ -305,32 +250,264 @@
+ return 1274;
+ } else if( session->protocol()->pluginId() == "YahooProtocol" ){
+ return 700;
+- }
++ }
+
+ // Jabber doesn't need fragmentation. Return 0 to disable.
+ // GaduGadu seems to not need fragmentation too.
+ return 0;
+ }
+
+-static OtrlMessageAppOps ui_ops = {
+- policy,
+- create_privkey,
+- is_logged_in,
+- inject_message,
+- notify,
+- display_otr_message,
+- update_context_list,
+- protocol_name,
+- protocol_name_free,
+- new_fingerprint,
+- write_fingerprints,
+- gone_secure,
+- gone_insecure,
+- still_secure,
+- log_message,
+- max_message_size,
+- 0, //not used yet...
+- 0 //not used yet...
++const char* OtrlChatInterface::otr_error_message(void *opdata, ConnContext *context, OtrlErrorCode err_code) {
++ Q_UNUSED(opdata)
++
++ char *err_msg = 0;
++ switch (err_code)
++ {
++ case OTRL_ERRCODE_NONE :
++ break;
++ case OTRL_ERRCODE_ENCRYPTION_ERROR : {
++ QString message = i18n("Error occurred encrypting message.");
++ err_msg = (char*)malloc(message.length() + 1);
++ memset(err_msg, 0, message.length() + 1);
++ memcpy(err_msg, message.toUtf8().data(), message.length());
++ break;
++ }
++ case OTRL_ERRCODE_MSG_NOT_IN_PRIVATE :
++ if (context) {
++ QString message = i18n("You sent encrypted data to %s, who wasn't expecting it.").arg(context->accountname);
++ err_msg = (char*)malloc(message.length() + 1);
++ memset(err_msg, 0, message.length() + 1);
++ memcpy(err_msg, message.toUtf8().data(), message.length());
++ }
++ break;
++ case OTRL_ERRCODE_MSG_UNREADABLE : {
++ QString message = i18n("You transmitted an unreadable encrypted message.");
++ err_msg = (char*)malloc(message.length() + 1);
++ memset(err_msg, 0, message.length() + 1);
++ memcpy(err_msg, message.toUtf8().data(), message.length());
++ break;
++ }
++ case OTRL_ERRCODE_MSG_MALFORMED : {
++ QString message = i18n("You transmitted a malformed data message.");
++ err_msg = (char*)malloc(message.length() + 1);
++ memset(err_msg, 0, message.length() + 1);
++ memcpy(err_msg, message.toUtf8().data(), message.length());
++ break;
++ }
++ }
++ return err_msg;
++}
++
++void OtrlChatInterface::otr_error_message_free(void *opdata, const char *err_msg) {
++ Q_UNUSED(opdata)
++ if (err_msg) {
++ free((char*)err_msg);
++ }
++}
++
++const char *OtrlChatInterface::resent_msg_prefix(void *opdata, ConnContext *context) {
++ Q_UNUSED(opdata)
++ Q_UNUSED(context)
++
++ QString message = i18n("[resent]");
++ char *msg_prefix = (char*)malloc(message.length() + 1);
++ memset(msg_prefix, 0, message.length() + 1);
++ memcpy(msg_prefix, message.toUtf8().data(), message.length());
++ return msg_prefix;
++}
++
++void OtrlChatInterface::resent_msg_prefix_free(void *opdata, const char *prefix) {
++ Q_UNUSED(opdata)
++
++ if (prefix) {
++ free((char*)prefix);
++ }
++}
++
++void OtrlChatInterface::handle_smp_event(void *opdata, OtrlSMPEvent smp_event, ConnContext *context, unsigned short progress_percent, char *question) {
++ Q_UNUSED(progress_percent)
++
++ Kopete::ChatSession *chatSession = (Kopete::ChatSession*)opdata;
++
++ if (!context) {
++ return;
++ }
++
++ switch (smp_event) {
++ case OTRL_SMPEVENT_NONE :
++ break;
++ case OTRL_SMPEVENT_ASK_FOR_SECRET :
++ new AuthenticationWizard( chatSession->view(true)->mainWidget(), context, chatSession, false );
++ break;
++ case OTRL_SMPEVENT_ASK_FOR_ANSWER :
++ new AuthenticationWizard( chatSession->view(true)->mainWidget(), context, chatSession, false, QLatin1String(question) );
++ break;
++ case OTRL_SMPEVENT_IN_PROGRESS :
++ AuthenticationWizard::findWizard(chatSession)->nextState();
++ break;
++ case OTRL_SMPEVENT_SUCCESS :
++ if (context->active_fingerprint->trust && context->active_fingerprint->trust[0]) {
++ AuthenticationWizard::findWizard(chatSession)->finished(true, true);
++ kDebug(14318) << "trust found";
++ Kopete::Message msg( chatSession->members().first(), chatSession->account()->myself() );
++ msg.setHtmlBody( i18n("Authentication with <b>%1</b> successful. The conversation is now secure.", formatContact(chatSession->members().first()->contactId())));
++ msg.setDirection( Kopete::Message::Internal );
++ chatSession->appendMessage( msg );
++ OtrlChatInterface::self()->emitGoneSecure( chatSession, 2 );
++ } else {
++ AuthenticationWizard::findWizard(chatSession)->finished(true, false);
++ kDebug(14318) << "trust _NOT_ found";
++ Kopete::Message msg( chatSession->members().first(), chatSession->account()->myself() );
++ 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())));
++ msg.setDirection( Kopete::Message::Internal );
++ chatSession->appendMessage( msg );
++ OtrlChatInterface::self()->emitGoneSecure( chatSession, 1 );
++ }
++ break;
++ case OTRL_SMPEVENT_FAILURE : {
++ AuthenticationWizard::findWizard(chatSession)->finished(false, false);
++ Kopete::Message msg( chatSession->members().first(), chatSession->account()->myself() );
++ msg.setHtmlBody( i18n("Authentication with <b>%1</b> failed. The conversation is now insecure.", formatContact(chatSession->members().first()->contactId())));
++ msg.setDirection( Kopete::Message::Internal );
++ chatSession->appendMessage( msg );
++ OtrlChatInterface::self()->emitGoneSecure( chatSession, 1 );
++ break;
++ }
++ case OTRL_SMPEVENT_ABORT :
++ case OTRL_SMPEVENT_CHEATED :
++ case OTRL_SMPEVENT_ERROR :
++ AuthenticationWizard::findWizard(chatSession)->finished(false, false);
++ OtrlChatInterface::self()->abortSMP( context, chatSession );
++ break;
++ }
++}
++
++void OtrlChatInterface::handle_msg_event(void *opdata, OtrlMessageEvent msg_event, ConnContext *context, const char* message, gcry_error_t err) {
++
++ Kopete::ChatSession *session= ((Kopete::ChatSession*)opdata);
++ Kopete::ContactPtrList list = session->members();
++ Kopete::Message msg( session->members().first(), session->account()->myself() );
++
++ switch (msg_event)
++ {
++ case OTRL_MSGEVENT_NONE:
++ break;
++ case OTRL_MSGEVENT_ENCRYPTION_REQUIRED:
++ msg.setHtmlBody( i18n( "You attempted to send an unencrypted message to %1" ).arg(QLatin1String(context->username)) );
++ msg.setDirection( Kopete::Message::Internal );
++ break;
++ case OTRL_MSGEVENT_ENCRYPTION_ERROR:
++ msg.setHtmlBody( i18n( "An error occurred when encrypting your message. The message was not sent." ).arg(QLatin1String(context->username)) );
++ msg.setDirection( Kopete::Message::Internal );
++ break;
++ case OTRL_MSGEVENT_CONNECTION_ENDED:
++ 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)) );
++ msg.setDirection( Kopete::Message::Internal );
++ break;
++ case OTRL_MSGEVENT_SETUP_ERROR:
++ if (!err) {
++ err = GPG_ERR_INV_VALUE;
++ }
++ switch(gcry_err_code(err)) {
++ case GPG_ERR_INV_VALUE:
++ kDebug(14318) << "Error setting up private conversation: Malformed message received";
++ default:
++ kDebug(14318) << "Error setting up private conversation:" << err;
++ }
++
++ msg.setHtmlBody( i18n( "OTR error" ) );
++ msg.setDirection( Kopete::Message::Internal );
++ break;
++ case OTRL_MSGEVENT_MSG_REFLECTED:
++ 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." ) );
++ msg.setDirection( Kopete::Message::Internal );
++ break;
++ case OTRL_MSGEVENT_MSG_RESENT:
++ msg.setHtmlBody( i18n( "<b>The last message to %1 was resent.</b>" ).arg(QLatin1String(context->username)) );
++ msg.setDirection( Kopete::Message::Internal );
++ break;
++ case OTRL_MSGEVENT_RCVDMSG_NOT_IN_PRIVATE:
++ msg.setHtmlBody( i18n( "<b>The encrypted message received from %1 is unreadable, as you are not currently communicating privately.</b>" ).arg(QLatin1String(context->username)) );
++ msg.setDirection( Kopete::Message::Inbound );
++ OtrlChatInterface::self()->m_blackistIds.append(msg.id());
++ break;
++ case OTRL_MSGEVENT_RCVDMSG_UNREADABLE:
++ msg.setHtmlBody( i18n( "We received an unreadable encrypted message from %1." ).arg(QLatin1String(context->username)) );
++ msg.setDirection( Kopete::Message::Internal );
++ break;
++ case OTRL_MSGEVENT_RCVDMSG_MALFORMED:
++ msg.setHtmlBody( i18n( "We received a malformed data message from %1." ).arg(QLatin1String(context->username)) );
++ msg.setDirection( Kopete::Message::Internal );
++ break;
++ case OTRL_MSGEVENT_LOG_HEARTBEAT_RCVD:
++ kDebug(14318) << "Heartbeat received from" << context->username;
++ return;
++ case OTRL_MSGEVENT_LOG_HEARTBEAT_SENT:
++ kDebug(14318) << "Heartbeat sent to" << context->username;
++ break;
++ case OTRL_MSGEVENT_RCVDMSG_GENERAL_ERR:
++ msg.setHtmlBody( QLatin1String(message) );
++ msg.setDirection( Kopete::Message::Internal );
++ session->appendMessage( msg );
++ break;
++ case OTRL_MSGEVENT_RCVDMSG_UNENCRYPTED:
++ 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) ));
++ msg.setDirection( Kopete::Message::Inbound );
++ OtrlChatInterface::self()->m_blackistIds.append(msg.id());
++ break;
++ case OTRL_MSGEVENT_RCVDMSG_UNRECOGNIZED:
++ kDebug(14318) << "Unrecognized OTR message received from" << context->username;
++ break;
++ case OTRL_MSGEVENT_RCVDMSG_FOR_OTHER_INSTANCE:
++ 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) ));
++ msg.setDirection( Kopete::Message::Inbound );
++ OtrlChatInterface::self()->m_blackistIds.append(msg.id());
++ break;
++ }
++
++ session->appendMessage( msg );
++}
++
++void OtrlChatInterface::create_instag(void *opdata, const char *accountname, const char *protocol) {
++ Q_UNUSED(opdata)
++ QString storeFile = QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "instags";
++ otrl_instag_generate(OtrlChatInterface::self()->getUserstate(), storeFile.toLocal8Bit(), accountname, protocol);
++}
++
++void OtrlChatInterface::timer_control(void *opdata, unsigned int interval) {
++ Q_UNUSED(opdata)
++ if (interval > 0) {
++ OtrlChatInterface::self()->m_forwardSecrecyTimer.start(interval * 1000);
++ } else {
++ OtrlChatInterface::self()->m_forwardSecrecyTimer.stop();
++ }
++}
++
++OtrlMessageAppOps OtrlChatInterface::ui_ops = {
++ OtrlChatInterface::policy,
++ OtrlChatInterface::create_privkey,
++ OtrlChatInterface::is_logged_in,
++ OtrlChatInterface::inject_message,
++ OtrlChatInterface::update_context_list,
++ OtrlChatInterface::new_fingerprint,
++ OtrlChatInterface::write_fingerprints,
++ OtrlChatInterface::gone_secure,
++ OtrlChatInterface::gone_insecure,
++ OtrlChatInterface::still_secure,
++ OtrlChatInterface::max_message_size,
++ NULL, /* account_name */
++ NULL, /* account_name_free */
++ NULL, /* received symkey */
++ OtrlChatInterface::otr_error_message,
++ OtrlChatInterface::otr_error_message_free,
++ OtrlChatInterface::resent_msg_prefix,
++ OtrlChatInterface::resent_msg_prefix_free,
++ OtrlChatInterface::handle_smp_event,
++ OtrlChatInterface::handle_msg_event,
++ OtrlChatInterface::create_instag,
++ NULL, /* convert_data */
++ NULL, /* convert_data_free */
++ OtrlChatInterface::timer_control
+ };
+
+ /*********************** Gui_UI_Ops finished *************************/
+@@ -338,25 +515,31 @@
+
+ /*********************** Constructor/Destructor **********************/
+
+-OtrlChatInterface::OtrlChatInterface(){
++OtrlChatInterface::OtrlChatInterface():
++ m_keyGenThread(0)
++{
+ mSelf = this;
+- OTRL_INIT;
++ OTRL_INIT;
+
+ userstate = otrl_userstate_create();
+ QString readPath = QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "privkeys";
+ otrl_privkey_read( userstate, readPath.toLocal8Bit() );
+-
+-
+- QString savePath = QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "fingerprints";
+- otrl_privkey_read_fingerprints(userstate, savePath.toLocal8Bit(), NULL, NULL);
+
++ unsigned int interval = otrl_message_poll_get_default_interval(userstate);
++ m_forwardSecrecyTimer.start(interval * 1000);
++ QObject::connect(&m_forwardSecrecyTimer, SIGNAL(timeout()), this, SLOT(otrlMessagePoll()));
++
++ readPath = QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "fingerprints";
++ otrl_privkey_read_fingerprints(userstate, readPath.toLocal8Bit(), NULL, NULL);
++
++ readPath = QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true)) + "instags";
++ otrl_instag_read(userstate, readPath.toLocal8Bit());
+ }
+
+ OtrlChatInterface::~ OtrlChatInterface(){
+ otrl_userstate_free(userstate);
+ }
+
+-
+ OtrlChatInterface *OtrlChatInterface::self(){
+ if( !mSelf ){
+ new OtrlChatInterface();
+@@ -375,159 +558,59 @@
+ }
+
+
+-int OtrlChatInterface::decryptMessage( QString *msg, const QString &accountId,
+- const QString &protocol, const QString &contactId , Kopete::ChatSession *chatSession){
++int OtrlChatInterface::decryptMessage( Kopete::Message &message){
+
+- int ignoremessage;
+- char *newMessage = NULL;
+- OtrlTLV *tlvs = NULL;
+- OtrlTLV *tlv = NULL;
+- ConnContext *context;
+- NextExpectedSMP nextMsg;
+-
+- ignoremessage = otrl_message_receiving( userstate, &ui_ops, chatSession, accountId.toLocal8Bit(), protocol.toLocal8Bit(), contactId.toLocal8Bit(), msg->toLocal8Bit(), &newMessage, &tlvs, NULL, NULL );
+-
+- tlv = otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED);
+- if( tlv ){
+- Kopete::Message msg( chatSession->members().first(), chatSession->account()->myself() );
+- msg.setHtmlBody( i18n("<b>%1</b> has ended the OTR session. You should do the same.",chatSession->members().first()->contactId() ) );
+- msg.setDirection( Kopete::Message::Internal );
+- chatSession->appendMessage( msg );
+- OtrlChatInterface::self()->emitGoneSecure( chatSession, 3 );
++ if (m_blackistIds.contains(message.id())) {
++ m_blackistIds.removeAll(message.id());
++ return 1;
+ }
+
+- context = otrl_context_find( userstate, contactId.toLocal8Bit(), accountId.toLocal8Bit(), protocol.toLocal8Bit(), 0, NULL, NULL, NULL);
+- if (context) {
+- nextMsg = context->smstate->nextExpected;
++ Kopete::ChatSession *chatSession = message.manager();
++ QString accountId = chatSession->account()->accountId();
++ QString protocol = chatSession->protocol()->displayName();
++ QString contactId = message.from()->contactId();
++ QString body = message.plainBody();
+
++ OtrlTLV *tlvs = NULL;
++ char *newMessage = NULL;
+
+- if (context->smstate->sm_prog_state == OTRL_SMP_PROG_CHEATED) {
+- abortSMP(context, chatSession);
+- context->smstate->nextExpected = OTRL_SMP_EXPECT1;
+- context->smstate->sm_prog_state = OTRL_SMP_PROG_OK;
+- } else {
+- tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1Q);
+- if (tlv) {
+- if (nextMsg != OTRL_SMP_EXPECT1){
+- kDebug(14318) << "Abording SMP: 1Q";
+- abortSMP( context, chatSession );
+- } else {
+- kDebug(14318) << "Update SMP state: 1Q";
+- new AuthenticationWizard( chatSession->view(true)->mainWidget(), context, chatSession, false, QString((char*)tlvs->data) );
+- }
+- }
++ if (m_keyGenThread != 0) {
++ // Currently generating the private key... must be a plaintext message anyways...
+
+- tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1);
+- if (tlv) {
+- if (nextMsg != OTRL_SMP_EXPECT1){
+- kDebug(14318) << "Abording SMP: 1";
+- abortSMP( context, chatSession );
+- } else {
+- kDebug(14318) << "Update SMP state: 1 ";
+- new AuthenticationWizard( chatSession->view(true)->mainWidget(), context, chatSession, false );
+- }
++ if (otrl_proto_message_type(body.toLatin1()) == OTRL_MSGTYPE_DATA) {
++ // an OTR message while we are generating the key... cache the message and replay once the key is generated...
++ connect(message.manager(), SIGNAL(closing(Kopete::ChatSession*)), SLOT(chatSessionDestroyed(Kopete::ChatSession*)));
++ m_storedMessages.append(message);
+ }
+- tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP2);
+- if (tlv) {
+- if (nextMsg != OTRL_SMP_EXPECT2){
+- kDebug(14318) << "Abording SMP: 2";
+- abortSMP( context, chatSession );
+- } else {
+- kDebug(14318) << "Update SMP state: 2 -> 3";
+- AuthenticationWizard::findWizard(chatSession)->nextState();
+- context->smstate->nextExpected = OTRL_SMP_EXPECT4;
+- }
+- }
+- tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP3);
+- if (tlv) {
+- if (nextMsg != OTRL_SMP_EXPECT3){
+- kDebug(14318) << "Abording SMP: 3";
+- abortSMP( context, chatSession );
+- } else {
+- kDebug(14318) << "SMP: 3";
+- if(context->smstate->sm_prog_state == OTRL_SMP_PROG_SUCCEEDED){
+- if (context->active_fingerprint->trust && context->active_fingerprint->trust[0]) {
+- AuthenticationWizard::findWizard(chatSession)->finished(true, true);
+- kDebug(14318) << "trust found";
+- Kopete::Message msg( chatSession->members().first(), chatSession->account()->myself() );
+- msg.setHtmlBody( i18n("Authentication with <b>%1</b> successful. The conversation is now secure.", formatContact(chatSession->members().first()->contactId())));
+- msg.setDirection( Kopete::Message::Internal );
+- chatSession->appendMessage( msg );
+- OtrlChatInterface::self()->emitGoneSecure( chatSession, 2 );
+- } else {
+- AuthenticationWizard::findWizard(chatSession)->finished(true, false);
+- kDebug(14318) << "trust _NOT_ found";
+- Kopete::Message msg( chatSession->members().first(), chatSession->account()->myself() );
+- 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())));
+- msg.setDirection( Kopete::Message::Internal );
+- chatSession->appendMessage( msg );
+- OtrlChatInterface::self()->emitGoneSecure( chatSession, 1 );
+- }
+-
+- } else {
+- AuthenticationWizard::findWizard(chatSession)->finished(false, false);
+- Kopete::Message msg( chatSession->members().first(), chatSession->account()->myself() );
+- msg.setHtmlBody( i18n("Authentication with <b>%1</b> failed. The conversation is now insecure.", formatContact(chatSession->members().first()->contactId())));
+- msg.setDirection( Kopete::Message::Internal );
+- chatSession->appendMessage( msg );
+- OtrlChatInterface::self()->emitGoneSecure( chatSession, 1 );
++ return 1;
++ }
+
+- }
+- context->smstate->nextExpected = OTRL_SMP_EXPECT1;
+- }
+- }
+- tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP4);
+- if (tlv) {
+- if (nextMsg != OTRL_SMP_EXPECT4) {
+- kDebug(14318) << "Abording SMP: 4";
+- abortSMP( context, chatSession );
+- } else {
+- kDebug(14318) << "SMP: 4";
+- if (context->active_fingerprint->trust && context->active_fingerprint->trust[0]) {
+- AuthenticationWizard::findWizard(chatSession)->finished(true, true);
+- kDebug(14318) << "trust found";
+- Kopete::Message msg( chatSession->members().first(), chatSession->account()->myself() );
+- msg.setHtmlBody( i18n("<b>Authentication successful. The conversation is now secure.</b>") );
+- msg.setDirection( Kopete::Message::Internal );
+- chatSession->appendMessage( msg );
+- OtrlChatInterface::self()->emitGoneSecure( chatSession, 2 );
+- } else {
+- AuthenticationWizard::findWizard(chatSession)->finished(false, false);
+- kDebug(14318) << "trust _NOT_ found";
+- Kopete::Message msg( chatSession->members().first(), chatSession->account()->myself() );
+- msg.setHtmlBody( i18n("<b>Authentication failed. Note that the conversation is now insecure.</b>") );
+- msg.setDirection( Kopete::Message::Internal );
+- chatSession->appendMessage( msg );
+- OtrlChatInterface::self()->emitGoneSecure( chatSession, 1 );
+- }
+- context->smstate->nextExpected = OTRL_SMP_EXPECT1;
+- }
+- }
+- tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP_ABORT);
+- if (tlv) {
+- kDebug(14318) << "other end aborted SMP";
++ int ignoremessage = otrl_message_receiving( userstate, &ui_ops, chatSession, accountId.toLocal8Bit(), protocol.toLocal8Bit(), contactId.toLocal8Bit(), body.toLocal8Bit(), &newMessage, &tlvs, NULL, NULL, NULL );
++
++ ConnContext *context = otrl_context_find( userstate, contactId.toLocal8Bit(), accountId.toLocal8Bit(), protocol.toLocal8Bit(), 0, 0, NULL, NULL, NULL);
++ if (context) {
++ OtrlTLV *tlv = otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED);
++ if( tlv ){
+ Kopete::Message msg( chatSession->members().first(), chatSession->account()->myself() );
+- msg.setHtmlBody( i18n("<b>Authentication error.</b>") );
++ msg.setHtmlBody( i18n("<b>%1</b> has ended the OTR session. You should do the same.",chatSession->members().first()->contactId() ) );
+ msg.setDirection( Kopete::Message::Internal );
+ chatSession->appendMessage( msg );
+- AuthenticationWizard *currentWizard = AuthenticationWizard::findWizard(chatSession);
+- if(currentWizard){
+- currentWizard->aborted();
+- }
+- context->smstate->nextExpected = OTRL_SMP_EXPECT1;
++ OtrlChatInterface::self()->emitGoneSecure( chatSession, 3 );
++
++ otrl_tlv_free(tlvs);
+ }
+-
+- otrl_tlv_free(tlvs);
+- }
++
+ }
+-
++
+ // message is now decrypted or is a Plaintext message and ready to deliver
+ if( !ignoremessage ){
+ // message is decrypted
+ if( newMessage != NULL ){
+- *msg = QString::fromUtf8(newMessage);
++ body = QString::fromUtf8(newMessage);
+ otrl_message_free( newMessage );
+- msg->replace( QString('\n'), QString("<br>") );
++ body.replace( QString('\n'), QString("<br>") );
++ message.setHtmlBody( body );
++
+ return 0; // message is decrypted and ready to deliver
+ } else {
+ return 1; // message was a plaintext message. Better not touching it :)
+@@ -536,75 +619,95 @@
+ return 2; // internal OTR message. Ignore it.
+ }
+
+-int OtrlChatInterface::encryptMessage( QString *msg, const QString &accountId,
+- const QString &protocol, const QString &contactId , Kopete::ChatSession *chatSession ){
+- int err;
++int OtrlChatInterface::encryptMessage( Kopete::Message &message ){
+ char *newMessage = 0;
+- char *fragment = 0;
+
+- if( otrl_proto_message_type( msg->toLocal8Bit() ) == OTRL_MSGTYPE_NOTOTR ){
+-// msg->replace( QString('<'), QString("<") );
+- err = otrl_message_sending( userstate, &ui_ops, chatSession, accountId.toLocal8Bit(), protocol.toLocal8Bit(), contactId.toLocal8Bit(), msg->toUtf8(), NULL, &newMessage, NULL, NULL );
+-
+- if( err != 0 ){
+- return -1;
+- } else if( newMessage ){
++ QString msgBody;
++ bool plaintext = message.format() == Qt::PlainText;
+
+- /* Fragment the message if needed */
+- /* If fragmentation is needed libotr will send out all fragments but the last one. */
+- ConnContext *context = otrl_context_find(userstate, contactId.toLocal8Bit(), accountId.toLocal8Bit(), protocol.toLocal8Bit(), 0, NULL, NULL, NULL);
++ if(plaintext){
++ msgBody = message.plainBody().replace('<', "<");
++ } else {
++ msgBody = message.escapedBody();
++ }
+
+- //kDebug(14318) << "message to be sent out: " << newMessage;
++ Kopete::ChatSession *chatSession = message.manager();
++ QString accountId = chatSession->account()->accountId();
++ QString protocol = chatSession->protocol()->displayName();
++ QString contactId = message.to().first()->contactId();
+
+- err = otrl_message_fragment_and_send(&ui_ops, chatSession, context, newMessage,
+- OTRL_FRAGMENT_SEND_ALL_BUT_LAST, &fragment);
++ if( otrl_proto_message_type( msgBody.toLocal8Bit() ) == OTRL_MSGTYPE_NOTOTR ){
+
+-// kDebug(14318) << "fragment left to be sent by kopete: " << fragment;
++ otrl_instag_t instance = message.manager()->property("otr-instag").toUInt();
+
+- if( err != 0){
+- *msg = i18n("Encryption error");
+- } else if ( fragment ){
+- *msg = QString::fromUtf8( fragment );
+- otrl_message_free( newMessage );
+- otrl_message_free( fragment );
+- }
+- OtrlMessageType type = otrl_proto_message_type( msg->toLocal8Bit() );
+- if( type == OTRL_MSGTYPE_TAGGEDPLAINTEXT ){
+- return 1; // Message is still plaintext, but tagged for opportunistic mode
++ 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 );
++
++ if( err != 0 ){
++ message.setPlainBody(i18n("An error occurred while encrypting the message."));
++ return -1;
++ } else if (newMessage) {
++ msgBody = QString::fromUtf8(newMessage);
++ otrl_message_free(newMessage);
++ }
++
++
++ OtrlMessageType type = otrl_proto_message_type( msgBody.toLatin1() );
++ if( type == OTRL_MSGTYPE_TAGGEDPLAINTEXT ){
++ kDebug(14318) << "Tagged plaintext!";
++
++ /* Here we have a problem... libotr tags messages with whitespaces to
++ be recognized by other clients. Those whitespaces are discarded
++ if we use setHtmlBody() and breaks opportunistic mode.
++ If we use setPlainBody() for messages containing tags, those tags
++ are escaped and will be visible in the other sides chatwindow.
++
++ This approach should always send out correct messages but will
++ break opportunistic mode if the user enables RTF formatting.
++ Sorry folks. No way to deal with this currently (Would need changes
++ in the rich text handling in libkopete).
++ */
++ if(plaintext){
++ message.setPlainBody(msgBody);
++ } else {
++ message.setHtmlBody(msgBody);
+ }
+- return 0; // Encrypted successfully
++ return 1;
+ }
++
++ // Always set plaintext if the message has been encrypted.
++ // The parser wouldn't understand anything after encryption anyways...
++ message.setPlainBody( msgBody );
++ message.setType(Kopete::Message::TypeNormal);
++ return 0;
+ }
+-
++
+ return 2; // Message is still plaintext. Better not touching it
+ }
+
+ QString OtrlChatInterface::getDefaultQuery( const QString &accountId ){
+ char *message;
+- message = otrl_proto_default_query_msg( accountId.toLatin1(), OTRL_POLICY_ALLOW_V2 );
++ message = otrl_proto_default_query_msg( accountId.toLatin1(), OTRL_POLICY_ALLOW_V3 | OTRL_POLICY_ALLOW_V2 );
+ QString msg( message );
+ otrl_message_free( message );
+ return msg;
+ }
+
+ void OtrlChatInterface::disconnectSession( Kopete::ChatSession *chatSession ){
+- otrl_message_disconnect( userstate, &ui_ops, chatSession, chatSession->account()->accountId().toLatin1(), chatSession->account()->protocol()->displayName().toLatin1(), chatSession->members().first()->contactId().toLocal8Bit() );
++ otrl_instag_t instance = chatSession->property("otr-instag").toUInt();
++ otrl_message_disconnect( userstate, &ui_ops, chatSession, chatSession->account()->accountId().toLatin1(), chatSession->account()->protocol()->displayName().toLatin1(), chatSession->members().first()->contactId().toLocal8Bit(), instance);
+ OtrlChatInterface::self()->emitGoneSecure( chatSession, 0 );
+
+ Kopete::Message msg( chatSession->account()->myself(), chatSession->members().first() );
+ msg.setPlainBody( i18n("Terminating OTR session.") );
+ msg.setDirection( Kopete::Message::Internal );
+-// msg.setBody( QString( message ), Kopete::Message::RichText );
+ chatSession->appendMessage( msg );
+-
+ }
+
+ bool OtrlChatInterface::shouldDiscard( const QString &message ){
+ if( !message.isEmpty() && !message.isNull() ){
+-// kDebug(14318) << otrl_proto_message_type( message.toLatin1() );
+ switch( otrl_proto_message_type( message.toLatin1() ) ){
+ case OTRL_MSGTYPE_TAGGEDPLAINTEXT:
+-// case OTRL_MSGTYPE_UNKNOWN: // Fragmented messages seem to be type UNKNOWN
++ //case OTRL_MSGTYPE_UNKNOWN: // Fragmented messages seem to be type UNKNOWN
+ case OTRL_MSGTYPE_NOTOTR:
+ return false;
+ default:
+@@ -622,33 +725,35 @@
+
+
+ int OtrlChatInterface::privState( Kopete::ChatSession *session ){
+- ConnContext *context;
+-
+- context = otrl_context_find(userstate, session->members().first()->contactId().toLocal8Bit(), session->account()->accountId().toLocal8Bit(), session->account()->protocol()->displayName().toLocal8Bit(), 0, NULL, NULL, NULL);
++ otrl_instag_t instance = session->property("otr-instag").toUInt();
++ if (instance == 0) {
++ instance = OTRL_INSTAG_BEST;
++ }
++ 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);
+
+ if( context ){
+ switch( context->msgstate ){
+- case OTRL_MSGSTATE_PLAINTEXT:
+- return 0;
+- case OTRL_MSGSTATE_ENCRYPTED:
+- if( context->active_fingerprint->trust && context->active_fingerprint->trust[0] != '\0' )
+- return 2;
+- else
+- return 1;
+- case OTRL_MSGSTATE_FINISHED:
+- return 3;
++ case OTRL_MSGSTATE_PLAINTEXT:
++ return 0;
++ case OTRL_MSGSTATE_ENCRYPTED:
++ if( context->active_fingerprint->trust && context->active_fingerprint->trust[0] != '\0' )
++ return 2;
++ else
++ return 1;
++ case OTRL_MSGSTATE_FINISHED:
++ return 3;
+ }
+ }
+ return 0;
+-}
++ }
++
++ QString OtrlChatInterface::formatContact(const QString &contactId){
+
+-QString OtrlChatInterface::formatContact(const QString &contactId){
+-
+ Kopete::MetaContact *metaContact = Kopete::ContactList::self()->findMetaContactByContactId(contactId);
+ if( metaContact ){
+ QString displayName = metaContact->displayName();
+ if((displayName != contactId) && !displayName.isNull()){
+- return displayName + " (" + contactId + ')';
++ return displayName + " (" + contactId + ')';
+ }
+ }
+ return contactId;
+@@ -657,7 +762,8 @@
+ void OtrlChatInterface::verifyFingerprint( Kopete::ChatSession *session ){
+ ConnContext *context;
+
+- context = otrl_context_find( userstate, session->members().first()->contactId().toLocal8Bit(), session->account()->accountId().toLocal8Bit(), session->protocol()->displayName().toLocal8Bit(), 0, NULL, NULL, NULL);
++ otrl_instag_t instance = session->property("otr-instag").toUInt();
++ context = otrl_context_find( userstate, session->members().first()->contactId().toLocal8Bit(), session->account()->accountId().toLocal8Bit(), session->protocol()->displayName().toLocal8Bit(), instance, 0, NULL, NULL, NULL);
+
+ new AuthenticationWizard( session->view()->mainWidget(), context, session, true );
+ }
+@@ -665,33 +771,34 @@
+ Fingerprint *OtrlChatInterface::findFingerprint( Kopete::ChatSession *session ){
+ ConnContext *context;
+
+- for( context = userstate->context_root; context != NULL; context = context->next ){
+- if( ( session->members().first()->contactId().toLocal8Bit() == context->username ) &&
+- (session->account()->accountId().toLocal8Bit() == context->accountname ) ){
+- return context->active_fingerprint ? context->active_fingerprint : NULL;
+- }
++
++ otrl_instag_t instance = session->property("otr-instag").toUInt();
++ if (instance == 0) {
++ instance = OTRL_INSTAG_BEST;
++ }
++ context = otrl_context_find( userstate, session->members().first()->contactId().toLocal8Bit(), session->account()->accountId().toLocal8Bit(), session->protocol()->displayName().toLocal8Bit(), instance, 0, NULL, NULL, NULL);
++ if (context && context->active_fingerprint && context->active_fingerprint->fingerprint) {
++ return context->active_fingerprint;
+ }
+ return NULL;
+ }
+
+-QString OtrlChatInterface::findActiveFingerprint( Kopete::ChatSession *session ){
+- ConnContext *context;
++QString OtrlChatInterface::fingerprint( Kopete::ChatSession *session ){
+ char hash[45];
++ memset(hash, 0, 45);
+
+- for( context = userstate->context_root; context != NULL; context = context->next ){
+- if( ( session->members().first()->contactId().toLocal8Bit() == context->username ) &&
+- (session->account()->accountId().toLocal8Bit() == context->accountname ) ){
+- otrl_privkey_hash_to_human( hash, context->active_fingerprint->fingerprint );
+- return hash;
+- }
++ Fingerprint *fp = findFingerprint(session);
++ if (fp) {
++ otrl_privkey_hash_to_human( hash, fp->fingerprint );
++ return QLatin1String(hash);
++ }
++
++ return QString();
+ }
+- return NULL;
+-}
+
+-bool OtrlChatInterface::isVerified( Kopete::ChatSession *session ){
++ bool OtrlChatInterface::isVerified( Kopete::ChatSession *session ){
+ Fingerprint *fingerprint = findFingerprint( session );
+
+- kDebug() << "fingerprint" << fingerprint;
+ if( fingerprint->trust && fingerprint->trust[0] != '\0' ){
+ return true;
+ } else {
+@@ -710,7 +817,7 @@
+ privkeysInfo.permission( QFile::ReadOther ) |
+ privkeysInfo.permission( QFile::WriteOther ) |
+ privkeysInfo.permission( QFile::ExeOther ) ){
+- chmod( file.toLocal8Bit(), 0600);
++ chmod( file.toLocal8Bit(), 0600);
+ }
+ }
+
+@@ -738,6 +845,17 @@
+ }
+ }
+
++void OtrlChatInterface::generatePrivateKey(const QString &account, const QString &protocol)
++{
++ m_keyGenThread = new KeyGenThread ( account.toLatin1(), protocol.toLatin1() );
++ m_keyGenThread->start();
++ while( !m_keyGenThread->wait(100) ){
++ qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers, 100);
++ }
++ m_keyGenThread->deleteLater();
++ m_keyGenThread = 0;
++}
++
+ /****************** SMP implementations ****************/
+
+ void OtrlChatInterface::abortSMP( ConnContext *context, Kopete::ChatSession *session ){
+@@ -753,7 +871,6 @@
+ }
+
+ void OtrlChatInterface::initSMP( ConnContext *context, Kopete::ChatSession *session, const QString &secret){
+- context = otrl_context_find( userstate, session->members().first()->contactId().toLocal8Bit(), session->account()->accountId().toLocal8Bit(), session->protocol()->displayName().toLocal8Bit(), 0, NULL, NULL, NULL);
+ otrl_message_initiate_smp( userstate, &ui_ops, session, context, (unsigned char*)secret.toLocal8Bit().data(), secret.length() );
+
+ Kopete::Message msg( session->members().first(), session->account()->myself() );
+@@ -761,11 +878,9 @@
+ msg.setDirection( Kopete::Message::Internal );
+
+ session->appendMessage( msg );
+-
+ }
+
+ void OtrlChatInterface::initSMPQ( ConnContext *context, Kopete::ChatSession *session, const QString &question, const QString &secret){
+- context = otrl_context_find( userstate, session->members().first()->contactId().toLocal8Bit(), session->account()->accountId().toLocal8Bit(), session->protocol()->displayName().toLocal8Bit(), 0, NULL, NULL, NULL);
+ otrl_message_initiate_smp_q( userstate, &ui_ops, session, context, (const char*)question.toLocal8Bit().data(), (unsigned char*)secret.toLocal8Bit().data(), secret.length() );
+
+ Kopete::Message msg( session->members().first(), session->account()->myself() );
+@@ -777,7 +892,7 @@
+
+ void OtrlChatInterface::respondSMP( ConnContext *context, Kopete::ChatSession *session, const QString &secret ){
+
+- kDebug(14318) << "resonding SMP";
++ kDebug(14318) << "resonding SMP";
+
+ otrl_message_respond_smp( userstate, &ui_ops, session, context, (unsigned char*)secret.toLocal8Bit().data(), secret.length());
+
+@@ -788,6 +903,29 @@
+ session->appendMessage( msg );
+ }
+
++void OtrlChatInterface::otrlMessagePoll()
++{
++ otrl_message_poll(userstate, 0, 0);
++}
++
++void OtrlChatInterface::replayStoredMessages()
++{
++ while (m_storedMessages.isEmpty()) {
++ Kopete::Message msg = m_storedMessages.takeFirst();
++ msg.manager()->appendMessage(msg);
++ }
++}
++
++void OtrlChatInterface::chatSessionDestroyed(Kopete::ChatSession *chatSession)
++{
++ QList<Kopete::Message> tmpList;
++ foreach (const Kopete::Message &msg, m_storedMessages) {
++ if (msg.manager() != chatSession) {
++ tmpList.append(msg);
++ }
++ }
++ m_storedMessages = tmpList;
++}
+ /****************** KeyGenThread *******************/
+
+ KeyGenThread::KeyGenThread( const QString &accountname, const QString &protocol ){
+@@ -802,3 +940,4 @@
+ otrl_privkey_generate(OtrlChatInterface::self()->getUserstate(), storeFile.toLocal8Bit(), accountname.toLocal8Bit(), protocol.toLocal8Bit());
+ OtrlChatInterface::self()->checkFilePermissions( QString(KGlobal::dirs()->saveLocation("data", "kopete_otr/", true )) + "privkeys" );
+ }
++
+diff -urN kdenetwork-4.10.5.org/kopete/plugins/otr/otrlchatinterface.h kdenetwork-4.10.5/kopete/plugins/otr/otrlchatinterface.h
+--- kdenetwork-4.10.5.org/kopete/plugins/otr/otrlchatinterface.h 2013-06-28 20:08:21.437046228 +0200
++++ kdenetwork-4.10.5/kopete/plugins/otr/otrlchatinterface.h 2013-07-10 21:39:55.606389116 +0200
+@@ -1,5 +1,5 @@
+ /*************************************************************************
+- * Copyright <2007> <Michael Zanetti> <michael_zanetti at gmx.net> *
++ * Copyright <2007 - 2013> <Michael Zanetti> <mzanetti at kde.org> *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+@@ -28,6 +28,8 @@
+ #include <qstring.h>
+ #include <qthread.h>
+ #include <qmutex.h>
++#include <qmetatype.h>
++#include <qtimer.h>
+
+ #include <kopete_export.h>
+ #include <kopetechatsession.h>
+@@ -42,6 +44,9 @@
+ #include <libotr/userstate.h>
+ }
+
++Q_DECLARE_METATYPE(otrl_instag_t)
++
++class KeyGenThread;
+
+ class KOPETE_OTR_SHARED_EXPORT OtrlChatInterface: public QObject
+ {
+@@ -50,19 +55,17 @@
+ ~OtrlChatInterface();
+ static OtrlChatInterface *self();
+
+- int decryptMessage( QString *msg, const QString &accountId, const QString &protocol, const QString &contactId, Kopete::ChatSession *chatSession );
+- int encryptMessage( QString *msg, const QString &accountId,
+- const QString &protocol, const QString &contactId , Kopete::ChatSession *chatSession );
++ int decryptMessage( Kopete::Message &message );
++ int encryptMessage( Kopete::Message &message );
+ QString getDefaultQuery( const QString &accountId );
+ void disconnectSession( Kopete::ChatSession *chatSession );
+ void setPolicy( OtrlPolicy policy );
+ bool shouldDiscard( const QString &message );
+ OtrlUserState getUserstate();
+ int privState( Kopete::ChatSession *session );
+- QString formatContact( const QString &contactId);
+ bool isVerified( Kopete::ChatSession *session );
+ void checkFilePermissions( const QString &file );
+- QString findActiveFingerprint( Kopete::ChatSession *session );
++ QString fingerprint( Kopete::ChatSession *session );
+ void verifyFingerprint( Kopete::ChatSession *session );
+ void setPlugin(Kopete::Plugin *plugin);
+ void emitGoneSecure(Kopete::ChatSession *sesseion, int state);
+@@ -71,17 +74,49 @@
+ void initSMPQ( ConnContext *context, Kopete::ChatSession *session, const QString &question, const QString &secret );
+ void respondSMP( ConnContext *context, Kopete::ChatSession *session, const QString &secret );
+ void setTrust( Kopete::ChatSession *session, bool trust );
++ void generatePrivateKey(const QString &account, const QString &protocol);
+
++ static QString formatContact( const QString &contactId);
+ private:
+ OtrlChatInterface();
+ static OtrlChatInterface *mSelf;
+ Fingerprint *findFingerprint( Kopete::ChatSession *session );
++ QList<uint> m_blackistIds;
++ KeyGenThread *m_keyGenThread;
++ QTimer m_forwardSecrecyTimer;
++ QList<Kopete::Message> m_storedMessages;
++
++ static OtrlMessageAppOps ui_ops;
++ static OtrlPolicy policy(void *opdata, ConnContext *context);
++ static void create_privkey(void *opdata, const char *accountname, const char *protocol);
++ static int is_logged_in(void *opdata, const char *accountname, const char *protocol, const char *recipient);
++ static void inject_message( void *opdata, const char *accountname, const char *protocol, const char *recipient, const char *message );
++ static void update_context_list(void *opdata);
++ static void new_fingerprint(void *opdata, OtrlUserState us, const char *accountname, const char *protocol, const char *username, unsigned char fingerprint[20]);
++ static void write_fingerprints(void *opdata);
++ static void gone_secure(void *opdata, ConnContext *context);
++ static void gone_insecure(void *opdata, ConnContext *context);
++ static void still_secure(void *opdata, ConnContext *context, int is_reply);
++ static int max_message_size(void *opdata, ConnContext *context);
++ static const char* otr_error_message(void *opdata, ConnContext *context, OtrlErrorCode err_code);
++ static void otr_error_message_free(void *opdata, const char *err_msg);
++ static const char *resent_msg_prefix(void *opdata, ConnContext *context);
++ static void resent_msg_prefix_free(void *opdata, const char *prefix);
++ static void handle_msg_event(void *opdata, OtrlMessageEvent msg_event, ConnContext *context, const char* message, gcry_error_t err);
++ static void handle_smp_event(void *opdata, OtrlSMPEvent smp_event, ConnContext *context, unsigned short progress_percent, char *question);
++ static void create_instag(void *opdata, const char *accountname, const char *protocol);
++ static void timer_control(void *opdata, unsigned int interval);
++
++private slots:
++ void otrlMessagePoll();
++ void replayStoredMessages();
++ void chatSessionDestroyed(Kopete::ChatSession *chatSession);
+
+ signals:
+ void goneSecure(Kopete::ChatSession* session, int state);
+ };
+
+- class KeyGenThread : public QThread {
++class KeyGenThread : public QThread {
+
+ private:
+ QString accountname;
+diff -urN kdenetwork-4.10.5.org/kopete/plugins/otr/otrlconfinterface.cpp kdenetwork-4.10.5/kopete/plugins/otr/otrlconfinterface.cpp
+--- kdenetwork-4.10.5.org/kopete/plugins/otr/otrlconfinterface.cpp 2013-06-28 20:08:21.940066273 +0200
++++ kdenetwork-4.10.5/kopete/plugins/otr/otrlconfinterface.cpp 2013-07-10 21:39:55.609722565 +0200
+@@ -1,5 +1,5 @@
+ /*************************************************************************
+- * Copyright <2007> <Michael Zanetti> <michael_zanetti at gmx.net> *
++ * Copyright <2007 - 2013> <Michael Zanetti> <mzanetti at kde.org> *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+@@ -83,11 +83,7 @@
+ popup->show();
+ popup->setCloseLock( true );
+
+- KeyGenThread *keyGenThread = new KeyGenThread ( accountId, protocol );
+- keyGenThread->start();
+- while( !keyGenThread->wait(100) ){
+- qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers, 100);
+- }
++ OtrlChatInterface::self()->generatePrivateKey(accountId, protocol);
+
+ popup->setCloseLock( false );
+ popup->close();
+diff -urN kdenetwork-4.10.5.org/kopete/plugins/otr/otrplugin.cpp kdenetwork-4.10.5/kopete/plugins/otr/otrplugin.cpp
+--- kdenetwork-4.10.5.org/kopete/plugins/otr/otrplugin.cpp 2013-06-28 20:08:21.437046228 +0200
++++ kdenetwork-4.10.5/kopete/plugins/otr/otrplugin.cpp 2013-07-10 21:39:55.609722565 +0200
+@@ -1,5 +1,5 @@
+ /*************************************************************************
+- * Copyright <2007> <Michael Zanetti> <michael_zanetti at gmx.net> *
++ * Copyright <2007 - 2013> <Michael Zanetti> <mzanetti at kde.org> *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+@@ -153,68 +153,23 @@
+ void OTRPlugin::slotOutgoingMessage( Kopete::Message& msg )
+ {
+ if( msg.direction() == Kopete::Message::Outbound ){
+- QString accountId = msg.manager()->account()->accountId();
+- Kopete::Contact *contact = msg.to().first();
+
+- QString msgBody;
+- QString cacheBody;
+- bool plaintext = msg.format() == Qt::PlainText;
+- kDebug(14318) << "Message format is" << (plaintext ? "plaintext" : "richtext");
+- if(plaintext){
+- msgBody = msg.plainBody().replace('<', "<");
+- cacheBody = msgBody;
+- } else {
+- msgBody = msg.escapedBody();
+- cacheBody = msgBody;
+- }
+- kDebug(14318) << "Outgoing message before processing:" << msgBody << "escaped" << Kopete::Message::escape(msgBody);
++ QString cacheBody;
++ if(msg.format() == Qt::PlainText){
++ cacheBody = msg.plainBody().replace('<', "<");
++ } else {
++ cacheBody = msg.escapedBody();
++ }
+
+- int encryptionState = otrlChatInterface->encryptMessage( &msgBody, accountId, msg.manager()->account()->protocol()->displayName(), contact->contactId(), msg.manager() );
++ otrlChatInterface->encryptMessage( msg );
+
+- if(encryptionState == -1){
+- // Failure. Shouldn't happen. However, if it does DON'T
+- // send the message out in plaintext. overwrite with something else...
+- msg.setPlainBody(i18n("An error occurred while encrypting the message."));
+-
+- } else if(encryptionState == 0){
+- kDebug(14318) << "Encrypted successfully";
+-
+- // Always set plaintext if the message has been encrypted.
+- // The parser wouldn't understand anything after encryption anyways...
+- msg.setPlainBody( msgBody );
+- msg.setType(Kopete::Message::TypeNormal);
+- if( !msg.plainBody().isEmpty() ){
+- messageCache.insert( msgBody, cacheBody );
+- } else {
+- messageCache.insert( "!OTR:MsgDelByOTR", cacheBody );
+- }
+- } else if(encryptionState == 1){
+- kDebug(14318) << "Tagged plaintext!";
+-
+- /* Here we have a problem... libotr tags messages with whitespaces to
+- be recognized by other clients. Those whitespaces are discarded
+- if we use setHtmlBody() and breaks opportunistic mode.
+- If we use setPlainBody() for messages containing tags, those tags
+- are escaped and will be visible in the other sides chatwindow.
+-
+- This approach should always send out correct messages but will
+- break opportunistic mode if the user enables RTF formatting.
+- Sorry folks. No way to deal with this currently (Would need changes
+- in the rich text handling in libkopete).
+- */
+- if(plaintext){
+- msg.setPlainBody(msgBody);
+- } else {
+- msg.setHtmlBody(msgBody);
+- }
+-
+- messageCache.insert( msgBody, cacheBody );
+- } /* else {
+- Don't touch msg If encryptionState is something else than above!!!
+- } */
+-
++ if( !msg.plainBody().isEmpty() ){
++ messageCache.insert( msg.plainBody(), cacheBody );
++ } else {
++ messageCache.insert( "!OTR:MsgDelByOTR", cacheBody );
++ }
+
+- kDebug(14318) << "Outgoing message after processing:" << msgBody << msg.format();
++ kDebug(14318) << "Outgoing message after processing:" << msg.plainBody() << msg.format();
+ }
+ }
+
+@@ -287,23 +242,22 @@
+ return;
+ }
+
++
+ Kopete::Message msg = event->message();
+ // Kopete::ChatSession *session = msg.manager();
+ QMap<QString, QString> messageCache = plugin->getMessageCache();
+
+- if( msg.direction() == Kopete::Message::Inbound ){
+- if( msg.type() == Kopete::Message::TypeFileTransferRequest )
++ kDebug(14318) << "OtrMessageHandler::handleMessage:" << msg.plainBody();
++
++ if( msg.direction() == Kopete::Message::Inbound){
++ if( msg.type() == Kopete::Message::TypeFileTransferRequest )
+ {
+ // file transfers aren't encrypted. Proceed with next plugin
+ MessageHandler::handleMessage( event );
+ return;
+ }
+- QString body = msg.plainBody();
+- QString accountId = msg.manager()->account()->accountId();
+- QString contactId = msg.from()->contactId();
+- int retValue = OtrlChatInterface::self()->decryptMessage( &body, accountId, msg.manager()->account()->protocol()->displayName(), contactId, msg.manager() );
+- msg.setHtmlBody( body );
+- if( (retValue == 2) | OtrlChatInterface::self()->shouldDiscard( msg.plainBody() ) ){
++ int retValue = OtrlChatInterface::self()->decryptMessage( msg );
++ if( (retValue == 2) | OtrlChatInterface::self()->shouldDiscard( msg.plainBody() ) ){
+ // internal OTR message
+ event->discard();
+ return;
+
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/packages/kde4-kopete.git/commitdiff/a28bb93533dff593e0babc3038c0a49c4474f892
More information about the pld-cvs-commit
mailing list