summaryrefslogtreecommitdiff
path: root/MirOTR
diff options
context:
space:
mode:
authoradmin@progandy.co.cc <admin@progandy.co.cc@eced67a3-f377-a0ae-92ae-d6de1850b05a>2010-08-19 20:12:06 +0000
committeradmin@progandy.co.cc <admin@progandy.co.cc@eced67a3-f377-a0ae-92ae-d6de1850b05a>2010-08-19 20:12:06 +0000
commit11e5e8749eb7d4d3cfebfa49bbb7ea4624608647 (patch)
treec773fee94a63a078e5cb59bdbfd3165f1830b7ea /MirOTR
parentc7e64af067562167b6941f3ad8383e3ceb817633 (diff)
initial commit with v0.8.6.1
git-svn-id: http://mirotr.googlecode.com/svn/trunk@2 eced67a3-f377-a0ae-92ae-d6de1850b05a
Diffstat (limited to 'MirOTR')
-rw-r--r--MirOTR/DLG_smp.cpp96
-rw-r--r--MirOTR/MirOTR.vcproj510
-rw-r--r--MirOTR/ReadMe.txt45
-rw-r--r--MirOTR/dbfilter.cpp236
-rw-r--r--MirOTR/dbfilter.h4
-rw-r--r--MirOTR/dialogs.cpp153
-rw-r--r--MirOTR/dialogs.h2
-rw-r--r--MirOTR/dllmain.cpp202
-rw-r--r--MirOTR/dllmain.h9
-rw-r--r--MirOTR/icons.cpp59
-rw-r--r--MirOTR/icons.h12
-rw-r--r--MirOTR/language.h84
-rw-r--r--MirOTR/options.cpp875
-rw-r--r--MirOTR/options.h66
-rw-r--r--MirOTR/otr.cpp383
-rw-r--r--MirOTR/otr.h53
-rw-r--r--MirOTR/resource.h103
-rw-r--r--MirOTR/resources/finished.icobin0 -> 2550 bytes
-rw-r--r--MirOTR/resources/insecure.icobin0 -> 2550 bytes
-rw-r--r--MirOTR/resources/otr.icobin0 -> 17542 bytes
-rw-r--r--MirOTR/resources/private.icobin0 -> 2550 bytes
-rw-r--r--MirOTR/resources/refresh.icobin0 -> 7886 bytes
-rw-r--r--MirOTR/resources/resource.rc133
-rw-r--r--MirOTR/resources/unverified.icobin0 -> 2550 bytes
-rw-r--r--MirOTR/resources/version.rc35
-rw-r--r--MirOTR/stdafx.cpp8
-rw-r--r--MirOTR/stdafx.h89
-rw-r--r--MirOTR/svcs_menu.cpp169
-rw-r--r--MirOTR/svcs_menu.h7
-rw-r--r--MirOTR/svcs_proto.cpp370
-rw-r--r--MirOTR/svcs_proto.h13
-rw-r--r--MirOTR/svcs_srmm.cpp224
-rw-r--r--MirOTR/svcs_srmm.h7
-rw-r--r--MirOTR/targetver.h24
-rw-r--r--MirOTR/utils.cpp400
-rw-r--r--MirOTR/utils.h47
-rw-r--r--MirOTR/version.h37
37 files changed, 4455 insertions, 0 deletions
diff --git a/MirOTR/DLG_smp.cpp b/MirOTR/DLG_smp.cpp
new file mode 100644
index 0000000..b701b7f
--- /dev/null
+++ b/MirOTR/DLG_smp.cpp
@@ -0,0 +1,96 @@
+#include "stdafx.h"
+#include <map>
+//TODO: Social Millionaire Protocol
+typedef std::map<HANDLE, HWND> SmpForContactMap;
+SmpForContactMap smp_for_contact;
+
+HWND smp_find_for_contact(HANDLE hContact) {
+ SmpForContactMap::iterator iter = smp_for_contact.find(hContact);
+ if (iter == smp_for_contact.end()) return null;
+ return iter->second;
+}
+
+/* Create the SMP dialog. responder is true if this is called in
+ * response to someone else's run of SMP. */
+static void dialog_socialist_millionaires(ConnContext *context,
+ TCHAR *question, bool responder)
+{
+ if (context == NULL) return;
+ TCHAR primary[1024];
+
+ if (responder && question) {
+ (HANDLE)context->app_data
+ mir_sntprintf(primary, 1024, TranslateT(LANG_SMP_AUTH_FROM),
+ contact_get_nameT((HANDLE)context->app_data));
+ } else {
+ mir_sntprintf(primary, 1024, TranslateT(LANG_SMP_AUTH),
+ contact_get_nameT((HANDLE)context->app_data));
+ }
+
+ /* fprintf(stderr, "Question = ``%s''\n", question); */
+ //TCHAR* proto_name = mir_a2t(context->protocol);
+ //if (!proto_name) proto_name = mir_tstrdup(TranslateT(LANG_UNKNOWN));
+
+
+ dialog = create_smp_dialog(_("Authenticate Buddy"),
+ primary, context, responder, question);
+
+ //mir_free(proto_name);
+}
+
+/* Call this to update the status of an ongoing socialist millionaires
+ * protocol. Progress_level is a percentage, from 0.0 (aborted) to
+ * 1.0 (complete). Any other value represents an intermediate state. */
+static void otrg_gtk_dialog_update_smp(ConnContext *context,
+ double progress_level)
+{
+ PurpleConversation *conv = otrg_plugin_context_to_conv(context, 0);
+ GtkProgressBar *bar;
+ SMPData *smp_data = purple_conversation_get_data(conv, "otr-smpdata");
+
+ if (!smp_data) return;
+
+ bar = GTK_PROGRESS_BAR(smp_data->smp_progress_bar);
+ gtk_progress_bar_set_fraction(bar, progress_level);
+
+ /* If the counter is reset to absolute zero, the protocol has aborted */
+ if (progress_level == 0.0) {
+ GtkDialog *dialog = GTK_DIALOG(smp_data->smp_progress_dialog);
+
+ gtk_dialog_set_response_sensitive(dialog, GTK_RESPONSE_ACCEPT, 1);
+ gtk_dialog_set_response_sensitive(dialog, GTK_RESPONSE_REJECT, 0);
+ gtk_dialog_set_default_response(GTK_DIALOG(dialog),
+ GTK_RESPONSE_ACCEPT);
+
+ gtk_label_set_text(GTK_LABEL(smp_data->smp_progress_label),
+ _("An error occurred during authentication."));
+ return;
+ } else if (progress_level == 1.0) {
+ /* If the counter reaches 1.0, the protocol is complete */
+ GtkDialog *dialog = GTK_DIALOG(smp_data->smp_progress_dialog);
+
+ gtk_dialog_set_response_sensitive(dialog, GTK_RESPONSE_ACCEPT, 1);
+ gtk_dialog_set_response_sensitive(dialog, GTK_RESPONSE_REJECT, 0);
+ gtk_dialog_set_default_response(GTK_DIALOG(dialog),
+ GTK_RESPONSE_ACCEPT);
+
+ if (context->smstate->sm_prog_state == OTRL_SMP_PROG_SUCCEEDED) {
+ if (context->active_fingerprint->trust &&
+ context->active_fingerprint->trust[0]) {
+ gtk_label_set_text(GTK_LABEL(smp_data->smp_progress_label),
+ _("Authentication successful."));
+ } else {
+ gtk_label_set_text(GTK_LABEL(smp_data->smp_progress_label),
+ _("Your buddy has successfully authenticated you. "
+ "You may want to authenticate your buddy as "
+ "well by asking your own question."));
+ }
+ } else {
+ gtk_label_set_text(GTK_LABEL(smp_data->smp_progress_label),
+ _("Authentication failed."));
+ }
+ } else {
+ /* Clear the progress label */
+ gtk_label_set_text(GTK_LABEL(smp_data->smp_progress_label), "");
+ }
+} \ No newline at end of file
diff --git a/MirOTR/MirOTR.vcproj b/MirOTR/MirOTR.vcproj
new file mode 100644
index 0000000..4b46162
--- /dev/null
+++ b/MirOTR/MirOTR.vcproj
@@ -0,0 +1,510 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="MirOTR"
+ ProjectGUID="{53F841E8-284F-4545-9176-B131896E43F8}"
+ RootNamespace="MirOTR"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\obj\$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D &quot;_CRT_SECURE_NO_WARNINGS&quot; /D &quot;_CRT_NON_CONFORMING_SWPRINTFS&quot;"
+ Optimization="0"
+ AdditionalIncludeDirectories="&quot;$(SolutionDir)\miranda\include&quot;;&quot;$(SolutionDir)\libotr-3.2.0\src&quot;;&quot;$(SolutionDir)\libgcrypt-1.4.6\src&quot;;&quot;$(SolutionDir)\libgpg-error-1.9\src&quot;"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;MIROTR_EXPORTS"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="2"
+ ProgramDataBaseFileName="$(TargetDir)$(TargetName).pdb"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="libgcrypt.lib libotr.lib Comctl32.lib"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="..\gpg.vs\bin.vs\libgcrypt\debug\static;..\otr.vs\bin.vs\libotr\debug\static"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\obj\$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D &quot;_CRT_SECURE_NO_WARNINGS&quot; /D &quot;_CRT_NON_CONFORMING_SWPRINTFS&quot;"
+ Optimization="3"
+ InlineFunctionExpansion="1"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
+ AdditionalIncludeDirectories="&quot;$(SolutionDir)\miranda\include&quot;;&quot;$(SolutionDir)\libotr-3.2.0\src&quot;;&quot;$(SolutionDir)\libgcrypt-1.4.6\src&quot;;&quot;$(SolutionDir)\libgpg-error-1.9\src&quot;"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MIROTR_EXPORTS"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ RuntimeTypeInfo="true"
+ UsePrecompiledHeader="2"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="libgcrypt.lib libotr.lib Comctl32.lib"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="..\gpg.vs\bin.vs\libgcrypt\release\static;..\otr.vs\bin.vs\libotr\release\static"
+ GenerateDebugInformation="false"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release ANSI|Win32"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\obj\$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D &quot;_CRT_SECURE_NO_WARNINGS&quot; /D &quot;_CRT_NON_CONFORMING_SWPRINTFS&quot;"
+ Optimization="3"
+ InlineFunctionExpansion="1"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
+ AdditionalIncludeDirectories="&quot;$(SolutionDir)\miranda\include&quot;;&quot;$(SolutionDir)\libotr-3.2.0\src&quot;;&quot;$(SolutionDir)\libgcrypt-1.4.6\src&quot;;&quot;$(SolutionDir)\libgpg-error-1.9\src&quot;"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MIROTR_EXPORTS"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ RuntimeTypeInfo="true"
+ UsePrecompiledHeader="2"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="libgcrypt.lib libotr.lib Comctl32.lib"
+ OutputFile="$(OutDir)\$(ProjectName)A.dll"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="..\gpg.vs\bin.vs\libgcrypt\release\static;..\otr.vs\bin.vs\libotr\release\static"
+ GenerateDebugInformation="false"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ <ProjectReference
+ ReferencedProjectIdentifier="{1423FC8F-AA52-4562-8275-4BF0838CA378}"
+ RelativePathToProject=".\otr.vs\libotr-3.2.0.vs\libotr320.vcproj"
+ />
+ <ProjectReference
+ ReferencedProjectIdentifier="{40FE7861-E54E-4DA9-BE4D-A5178014E477}"
+ RelativePathToProject=".\gpg.vs\libgcrypt-1.4.6.vs\libgcrypt146lib.vcproj"
+ />
+ </References>
+ <Files>
+ <Filter
+ Name="Quelldateien"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\dbfilter.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\dialogs.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\DLG_smp.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release ANSI|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\dllmain.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ CompileAsManaged="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ CompileAsManaged="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release ANSI|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ CompileAsManaged="0"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\icons.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\options.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\otr.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\stdafx.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release ANSI|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\svcs_menu.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\svcs_proto.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\svcs_srmm.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\utils.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Headerdateien"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\dbfilter.h"
+ >
+ </File>
+ <File
+ RelativePath=".\dialogs.h"
+ >
+ </File>
+ <File
+ RelativePath=".\dllmain.h"
+ >
+ </File>
+ <File
+ RelativePath=".\icons.h"
+ >
+ </File>
+ <File
+ RelativePath=".\language.h"
+ >
+ </File>
+ <File
+ RelativePath=".\options.h"
+ >
+ </File>
+ <File
+ RelativePath=".\otr.h"
+ >
+ </File>
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ <File
+ RelativePath=".\stdafx.h"
+ >
+ </File>
+ <File
+ RelativePath=".\svcs_menu.h"
+ >
+ </File>
+ <File
+ RelativePath=".\svcs_proto.h"
+ >
+ </File>
+ <File
+ RelativePath=".\svcs_srmm.h"
+ >
+ </File>
+ <File
+ RelativePath=".\targetver.h"
+ >
+ </File>
+ <File
+ RelativePath=".\utils.h"
+ >
+ </File>
+ <File
+ RelativePath=".\version.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Ressourcendateien"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\resources\resource.rc"
+ >
+ </File>
+ <File
+ RelativePath=".\resources\version.rc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release ANSI|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <File
+ RelativePath=".\ReadMe.txt"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/MirOTR/ReadMe.txt b/MirOTR/ReadMe.txt
new file mode 100644
index 0000000..2c41343
--- /dev/null
+++ b/MirOTR/ReadMe.txt
@@ -0,0 +1,45 @@
+========================================================================
+ DYNAMIC LINK LIBRARY: MirOTR-Projektübersicht
+========================================================================
+
+Diese MirOTR-DLL wurde vom Anwendungs-Assistenten für Sie
+erstellt.
+
+Die Datei enthält eine Zusammenfassung des Inhalts der Dateien,
+aus denen die MirOTR-Anwendung besteht.
+
+
+MirOTR.vcproj
+ Dies ist die Hauptprojektdatei für VC++-Projekte, die mit dem Anwendungs-
+ Assistenten generiert werden.
+ Sie enthält Informationen zu der Version von Visual C++, mit der die Datei
+ generiert wurde, sowie Informationen zu Plattformen, Konfigurationen und
+ Projektfeatures, die mit dem dem Anwendungs-Assistenten generiert werden.
+
+MirOTR.cpp
+ Dies ist die Hauptquelldatei der DLL.
+
+ Diese DLL exportiert keine Symbole, deshalb wird beim Erstellen keine
+ LIB-Datei generiert. Wenn dieses Projekt eine Projektabhängigkeit
+ eines anderen Projekts sein soll, müssen Sie Code hinzufügen, um
+ Symbole aus der DLL zu exportieren, damit eine Exportbibliothek
+ erstellt wird, oder Sie können die Eigenschaft "Eingabebibliothek
+ ignorieren" auf der Eigenschaftenseite "Allgemein" in den
+ Projekteigenschaften auf "Ja" festlegen.
+ Dialogfeld "Seiten".
+
+/////////////////////////////////////////////////////////////////////////////
+Andere Standarddateien:
+
+StdAfx.h, StdAfx.cpp
+ Mit diesen Dateien werden eine vorkompilierte Headerdatei (PCH)
+ mit dem Namen MirOTR.pch sowie eine vorkompilierte
+ Typendatei mit dem Namen StdAfx.obj erstellt.
+
+/////////////////////////////////////////////////////////////////////////////
+Weitere Hinweise:
+
+Der Anwendungs-Assistent verwendet "TODO:"-Kommentare, um die Teile des
+Quellcodes anzugeben, die hinzugefügt oder bearbeitet werden müssen.
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/MirOTR/dbfilter.cpp b/MirOTR/dbfilter.cpp
new file mode 100644
index 0000000..cfd7537
--- /dev/null
+++ b/MirOTR/dbfilter.cpp
@@ -0,0 +1,236 @@
+#include "stdafx.h"
+#include "dbfilter.h"
+static HANDLE hDBEventPreAdd, hDBEventAdded;
+static CRITICAL_SECTION RemoveChainCS={0}, *lpRemoveChainCS = &RemoveChainCS;
+static UINT_PTR timerId = 0;
+
+struct DeleteEventNode {
+ DeleteEventNode *next;
+ time_t timestamp;
+ HANDLE hContact;
+ HANDLE hDbEvent;
+};
+struct DeleteEventHead {
+ DeleteEventNode *first;
+ DeleteEventNode *last;
+};
+static DeleteEventHead DeleteEvents = {0,0};
+
+VOID CALLBACK DeleteTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) {
+ if (!DeleteEvents.first) return;
+ EnterCriticalSection(lpRemoveChainCS);
+ DeleteEventNode *prev =0, *current, *next;
+ DBEVENTINFO info = {0};
+ info.cbSize = sizeof(info);
+ next = DeleteEvents.first;
+ while (current = next) {
+ if (difftime(time(0), current->timestamp) < 1) break;
+ if(!CallService(MS_DB_EVENT_GET, (WPARAM)current->hDbEvent, (LPARAM)&info)) // && info.flags&DBEF_READ)
+ {
+ CallService(MS_DB_EVENT_DELETE, (WPARAM)current->hContact, (LPARAM)current->hDbEvent);
+ next = current->next;
+ if (prev) prev->next = next;
+ else if (DeleteEvents.first == current) DeleteEvents.first = next;
+ delete current;
+ } else {
+ prev = current;
+ next = current->next;
+ }
+ }
+ if (!DeleteEvents.first) DeleteEvents.last = 0;
+ LeaveCriticalSection(lpRemoveChainCS);
+}
+
+
+// add prefix to sent messages
+INT_PTR OnDatabaseEventPreAdd(WPARAM wParam, LPARAM lParam) {
+ if(!options.prefix_messages || !lParam) return 0;
+ HANDLE hContact = (HANDLE)wParam;
+ DBEVENTINFO *dbei = (DBEVENTINFO *)lParam;
+ if ((dbei->eventType != EVENTTYPE_MESSAGE) || !(dbei->flags & DBEF_SENT) || (dbei->flags & DBEF_OTR_PREFIXED))
+ return 0;
+ if(dbei->cbBlob == 0 || dbei->pBlob == 0)
+ return 0; // just to be safe
+
+ const char *proto = contact_get_proto(hContact);
+ if(!proto ) return 0;
+ if (DBGetContactSettingByte(hContact, proto, "ChatRoom", 0) == 1)
+ return 0;
+
+ if(g_metaproto && strcmp(proto, g_metaproto) == 0) {
+ hContact = (HANDLE)CallService(MS_MC_GETMOSTONLINECONTACT, (WPARAM)hContact, 0);
+ if(!hContact) return 0;
+ proto = contact_get_proto(hContact);
+ if(!proto ) return 0;
+ }
+
+
+ ConnContext *context = otrl_context_find_miranda(otr_user_state, hContact);
+ bool encrypted = otr_context_get_trust(context) != TRUST_NOT_PRIVATE;
+ if(!encrypted) return 0;
+
+ DBEVENTINFO my_dbei = *dbei; // copy the other event
+
+ char *msg = (char *)dbei->pBlob;
+ char *newmsg = 0;
+ DWORD alloclen = 0;
+ DWORD msglen = strlen(msg);
+ if (dbei->flags & DBEF_UTF) {
+ int prefixlen = strnlen(options.prefix, 64);
+ if (strncmp(msg, options.prefix, prefixlen) == 0) return 0;
+ alloclen = (msglen+prefixlen+1)*sizeof(char);
+
+ // get additional data
+ DWORD len2 = alloclen- prefixlen*sizeof(char);
+ int datalen = dbei->cbBlob - len2;
+ if (datalen < 0) datalen = 0;
+
+ newmsg = (char*)mir_alloc(alloclen);
+ memset(newmsg, 0, alloclen+datalen);
+ strncpy(newmsg, options.prefix, prefixlen);
+ strncat(newmsg, msg, msglen);
+ // append additional data
+ if (datalen) {
+ memcpy(newmsg+alloclen, msg+len2, datalen);
+ alloclen += datalen;
+ }
+ } else {
+ bool dz = false;
+ if(msglen < dbei->cbBlob) {
+ for(unsigned int i = msglen; i < dbei->cbBlob; i++) {
+ if(msg[i] == 0 && msg[i - 1] == 0) {
+ dz = true;
+ break;
+ }
+ }
+ }
+ if(dz) {
+ // yes, unicode
+ wchar_t* msgw = (wchar_t *)&msg[msglen];
+ wchar_t *prefixw = mir_utf8decodeW(options.prefix);
+ int prefixlenw = wcslen(prefixw);
+ if (wcsncmp(msgw, prefixw, prefixlenw) == 0) {
+ mir_free(prefixw);
+ return 0;
+ }
+ int msglenw = wcslen(msgw);
+
+ char *prefix = mir_utf8decodeA(options.prefix);
+ int prefixlen = strlen(prefix);
+
+ alloclen = (msglen+prefixlen+1)* sizeof(char) + (msglenw + prefixlenw +1) * sizeof(wchar_t);
+ // get additional data
+ DWORD len2 = (msglen+1)* sizeof(char) + (msglenw+1) * sizeof(wchar_t);
+ int datalen = dbei->cbBlob - len2;
+ if (datalen < 0) datalen = 0;
+
+ newmsg = (char*)mir_alloc(alloclen+datalen);
+ memset(newmsg, 0, alloclen+datalen);
+ strncpy(newmsg, prefix, prefixlen);
+ strncat(newmsg, msg, msglen);
+ wchar_t *p = (wchar_t*) newmsg + (msglen + prefixlen + 1) * sizeof(char);
+ wcsncpy(p, prefixw, prefixlenw);
+ wcsncat(p, msgw, msglenw);
+ mir_free(prefix);
+ mir_free(prefixw);
+ // append additional data
+ if (datalen) {
+ memcpy(newmsg+alloclen, msg+len2, datalen);
+ alloclen += datalen;
+ }
+
+ } else {
+ char *prefix = mir_utf8decodeA(options.prefix);
+ int prefixlen = strlen(prefix);
+ if (strncmp(msg, prefix, prefixlen) == 0) {
+ mir_free(prefix);
+ return 0;
+ }
+ alloclen = msglen+prefixlen+sizeof(char);
+ // get additional data
+ DWORD len2 = alloclen-prefixlen;
+ int datalen = dbei->cbBlob - len2;
+ if (datalen < 0) datalen = 0;
+
+ newmsg = (char*)mir_alloc(alloclen+datalen);
+ memset(newmsg, 0, alloclen+datalen);
+ strncpy(newmsg, prefix, prefixlen);
+ strncat(newmsg, msg, msglen);
+ mir_free(prefix);
+ // append additional data
+ if (datalen) {
+ memcpy(newmsg+alloclen, msg+len2, datalen);
+ alloclen += datalen;
+ }
+ }
+
+ }
+
+ my_dbei.pBlob = (BYTE *)newmsg;
+ my_dbei.cbBlob = alloclen;
+ my_dbei.flags |= DBEF_OTR_PREFIXED;
+
+ CallService(MS_DB_EVENT_ADD, wParam, (LPARAM)&my_dbei);
+ if (newmsg) mir_free(newmsg);
+
+ // stop original event from being added
+ return 1;
+}
+
+INT_PTR OnDatabaseEventAdded(WPARAM wParam, LPARAM lParam) {
+ if(!options.no_history) return 0;
+
+ DBEVENTINFO info = {0};
+ info.cbSize = sizeof(info);
+
+ static char* prefixutf = mir_utf8encodeT(TranslateT(LANG_INLINE_PREFIX));
+ static char* prefix = Translate(LANG_INLINE_PREFIX);
+ static DWORD lenutf = strlen(prefixutf);
+ static DWORD len = strlen(prefix);
+ info.cbBlob = lenutf*2;
+ info.pBlob = (PBYTE)mir_alloc(info.cbBlob);
+ if(!CallService(MS_DB_EVENT_GET, (WPARAM)lParam, (LPARAM)&info)) {
+ if(info.eventType == EVENTTYPE_MESSAGE) {
+ HANDLE hContact = (HANDLE)wParam;
+ ConnContext *context = otrl_context_find_miranda(otr_user_state, hContact);
+ if (context && otr_context_get_trust(context) != TRUST_NOT_PRIVATE
+ && ( (info.flags&DBEF_UTF && !(info.cbBlob >lenutf && 0==strncmp((char*)info.pBlob, prefixutf, lenutf)))
+ || (!(info.flags&DBEF_UTF) && !(info.cbBlob >len && 0==strncmp((char*)info.pBlob, prefix, len)))
+ )
+ ) // only delete encrypted messages that are no OTR system messages
+ {
+ DeleteEventNode *node = new DeleteEventNode();
+ node->hContact = hContact;
+ node->hDbEvent = (HANDLE) lParam;
+ node->timestamp = time(0);
+ node->next = 0;
+ EnterCriticalSection(lpRemoveChainCS);
+ if (DeleteEvents.last)
+ DeleteEvents.last->next = node;
+ else
+ DeleteEvents.first = node;
+ DeleteEvents.last = node;
+ LeaveCriticalSection(lpRemoveChainCS);
+ }
+ }
+ }
+ mir_free(prefixutf);
+ mir_free(info.pBlob);
+ return 0;
+}
+
+void InitDBFilter() {
+ InitializeCriticalSectionAndSpinCount(lpRemoveChainCS, 500);
+ hDBEventPreAdd = HookEvent(ME_DB_EVENT_FILTER_ADD, OnDatabaseEventPreAdd);
+ hDBEventAdded = HookEvent(ME_DB_EVENT_ADDED, OnDatabaseEventAdded);
+ timerId = SetTimer(0, 0, 1000, DeleteTimerProc);
+}
+void DeinitDBFilter() {
+ UnhookEvent(hDBEventPreAdd);
+ hDBEventPreAdd = 0;
+ UnhookEvent(hDBEventAdded);
+ hDBEventAdded = 0;
+ if (timerId) KillTimer(0, timerId);
+ DeleteTimerProc(0,0,0,0);
+ DeleteCriticalSection(lpRemoveChainCS);
+} \ No newline at end of file
diff --git a/MirOTR/dbfilter.h b/MirOTR/dbfilter.h
new file mode 100644
index 0000000..99a6d50
--- /dev/null
+++ b/MirOTR/dbfilter.h
@@ -0,0 +1,4 @@
+#define DBEF_OTR_PREFIXED 0x8000
+
+void InitDBFilter();
+void DeinitDBFilter(); \ No newline at end of file
diff --git a/MirOTR/dialogs.cpp b/MirOTR/dialogs.cpp
new file mode 100644
index 0000000..15630cf
--- /dev/null
+++ b/MirOTR/dialogs.cpp
@@ -0,0 +1,153 @@
+#include "stdafx.h"
+#include "dialogs.h"
+#include <Prsht.h>
+#include <commctrl.h>
+#include <process.h>
+
+unsigned int CALLBACK verify_context_thread(void *param);
+void VerifyContextDialog(ConnContext* context) {
+ if (!context) return;
+ CloseHandle((HANDLE)_beginthreadex(0, 0, verify_context_thread, context, 0, 0));
+}
+
+INT_PTR CALLBACK DlgProcVerifyContext(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch ( msg ) {
+ case WM_INITDIALOG:
+ {
+ if (!lParam) {
+ EndDialog(hwndDlg, IDCANCEL);
+ return FALSE;
+ }
+ SendMessage(hwndDlg, WM_SETTEXT, 0, (LPARAM)_T(LANG_OTR_FPVERIFY_TITLE));
+ SetDlgItemText(hwndDlg, IDC_STC_SMP_HEAD, _T(LANG_OTR_FPVERIFY_TITLE));
+ TranslateDialogDefault( hwndDlg );
+ SetWindowLongPtr(hwndDlg, GWL_USERDATA, lParam);
+
+ // Move window to screen center
+ // Get the owner window and dialog box rectangles.
+ HWND hwndOwner; RECT rcOwner, rcDlg, rc;
+ if ((hwndOwner = GetParent(hwndDlg)) == NULL)
+ {
+ hwndOwner = GetDesktopWindow();
+ }
+
+ GetWindowRect(hwndOwner, &rcOwner);
+ GetWindowRect(hwndDlg, &rcDlg);
+ CopyRect(&rc, &rcOwner);
+
+ // Offset the owner and dialog box rectangles so that right and bottom
+ // values represent the width and height, and then offset the owner again
+ // to discard space taken up by the dialog box.
+
+ OffsetRect(&rcDlg, -rcDlg.left, -rcDlg.top);
+ OffsetRect(&rc, -rc.left, -rc.top);
+ OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom);
+
+ // The new position is the sum of half the remaining space and the owner's
+ // original position.
+
+ SetWindowPos(hwndDlg,
+ HWND_TOP,
+ rcOwner.left + (rc.right / 2),
+ rcOwner.top + (rc.bottom / 2),
+ 0, 0, // Ignores size arguments.
+ SWP_NOSIZE);
+
+ // end center dialog
+
+ ConnContext *context = (ConnContext*)lParam;
+ Fingerprint *fp = context->active_fingerprint;
+ if (!fp) {
+ EndDialog(hwndDlg, IDCANCEL);
+ return FALSE;
+ }
+ TCHAR buff[512];
+ if (!fp->trust || fp->trust[0] == '\0')
+ mir_sntprintf(buff, 512, TranslateT(LANG_OTR_FPVERIFY_DESC), contact_get_nameT((HANDLE)context->app_data));
+ else
+ mir_sntprintf(buff, 512, TranslateT(LANG_OTR_FPVERIFIED_DESC), contact_get_nameT((HANDLE)context->app_data));
+
+ SetDlgItemText(hwndDlg, IDC_STC_SMP_INFO, buff);
+
+ unsigned char hash[20];
+ lib_cs_lock();
+ if (!otrl_privkey_fingerprint_raw(otr_user_state, hash, context->accountname, context->protocol)) {
+ lib_cs_unlock();
+ EndDialog(hwndDlg, IDCANCEL);
+ return FALSE;
+ }
+ otrl_privkey_hash_to_humanT(buff, hash);
+ lib_cs_unlock();
+ SetDlgItemText(hwndDlg, IDC_EDT_SMP_FIELD1, buff);
+ SendDlgItemMessage(hwndDlg, IDC_EDT_SMP_FIELD1, EM_SETREADONLY, TRUE, 0);
+ SetDlgItemText(hwndDlg, IDC_STC_SMP_FIELD1, TranslateT(LANG_YOUR_PRIVKEY));
+
+ otrl_privkey_hash_to_humanT(buff, fp->fingerprint);
+ SetDlgItemText(hwndDlg, IDC_EDT_SMP_FIELD2, buff);
+ SendDlgItemMessage(hwndDlg, IDC_EDT_SMP_FIELD2, EM_SETREADONLY, TRUE, 0);
+ SetDlgItemText(hwndDlg, IDC_STC_SMP_FIELD2, TranslateT(LANG_CONTACT_FINGERPRINT));
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CBO_SMP_CHOOSE), FALSE);
+
+ ShowWindow(GetDlgItem(hwndDlg, IDOK), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg, IDYES), SW_SHOWNA);
+ ShowWindow(GetDlgItem(hwndDlg, IDNO), SW_SHOWNA);
+ SetFocus(GetDlgItem(hwndDlg, IDCANCEL));
+
+ return FALSE;
+ }
+
+ case WM_COMMAND:
+ switch ( HIWORD( wParam )) {
+ case BN_CLICKED:
+ switch ( LOWORD( wParam )) {
+ case IDYES:
+ case IDNO:
+ case IDCANCEL:
+ case IDOK:
+ EndDialog(hwndDlg, LOWORD( wParam ));
+ break;
+ }
+ }
+ break;
+
+ }
+
+ return FALSE;
+}
+
+unsigned int CALLBACK verify_context_thread(void *param) {
+ CallService(MS_SYSTEM_THREAD_PUSH, 0, 0);
+
+ if (param) {
+ ConnContext *context = (ConnContext *)param;
+ TCHAR msg[1024];
+ switch ( DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SMP_INPUT), 0, DlgProcVerifyContext, (LPARAM)param) ) {
+ case IDOK:
+ case IDYES:
+ lib_cs_lock();
+ otrl_context_set_trust(context->active_fingerprint, "verified");
+ otrl_privkey_write_fingerprints(otr_user_state, g_fingerprint_store_filename);
+ lib_cs_unlock();
+ mir_sntprintf(msg, 1024, TranslateT(LANG_FINGERPRINT_VERIFIED), contact_get_nameT((HANDLE)context->app_data));
+ msg[1023] = '\0';
+ ShowMessage((HANDLE)context->app_data, msg);
+ SetEncryptionStatus(context->app_data, otr_context_get_trust(context));
+ break;
+ case IDNO:
+ lib_cs_lock();
+ otrl_context_set_trust(context->active_fingerprint, NULL);
+ otrl_privkey_write_fingerprints(otr_user_state, g_fingerprint_store_filename);
+ lib_cs_unlock();
+ mir_sntprintf(msg, 1024, TranslateT(LANG_FINGERPRINT_NOT_VERIFIED), contact_get_nameT((HANDLE)context->app_data));
+ msg[1023] = '\0';
+ ShowMessage((HANDLE)context->app_data, msg);
+ SetEncryptionStatus(context->app_data, otr_context_get_trust(context));
+ break;
+ }
+ }
+
+ CallService(MS_SYSTEM_THREAD_POP, 0, 0);
+ return 0;
+} \ No newline at end of file
diff --git a/MirOTR/dialogs.h b/MirOTR/dialogs.h
new file mode 100644
index 0000000..528622f
--- /dev/null
+++ b/MirOTR/dialogs.h
@@ -0,0 +1,2 @@
+void VerifyContextDialog(ConnContext* context);
+INT_PTR CALLBACK DlgProcVerifyContext(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); \ No newline at end of file
diff --git a/MirOTR/dllmain.cpp b/MirOTR/dllmain.cpp
new file mode 100644
index 0000000..38f6bac
--- /dev/null
+++ b/MirOTR/dllmain.cpp
@@ -0,0 +1,202 @@
+// dllmain.cpp : Definiert den Einstiegspunkt für die DLL-Anwendung.
+#include "stdafx.h"
+#include "dllmain.h"
+#include "otr.h"
+#include "dbfilter.h"
+#include <commctrl.h>
+
+HANDLE hEventWindow;
+HINSTANCE hInst;
+PLUGINLINK *pluginLink;
+MM_INTERFACE mmi;
+UTF8_INTERFACE utfi;
+char* g_metaproto;
+
+
+PLUGININFOEX pluginInfo={
+ sizeof(PLUGININFOEX),
+ SHORT_NAME_STRING,
+ PLUGIN_MAKE_VERSION(VER_MAJOR,VER_MINOR,VER_RELEASE,VER_BUILD),
+ LONGDESC_STRING,
+ AUTHOR,
+ AUTHOR_MAIL,
+ LEGAL_COPYRIGHT_LONG,
+ HOMEPAGE,
+ UNICODE_AWARE, //not transient
+ 0, //doesn't replace anything built-in
+ MIID_OTRPLUGIN // ANSI and Unicode have different IDs
+};
+
+BOOL APIENTRY DllMain( HMODULE hModule,
+ DWORD ul_reason_for_call,
+ LPVOID lpReserved
+ )
+{
+ if (ul_reason_for_call == DLL_PROCESS_ATTACH) {
+ hInst=hModule;
+ OTRL_INIT;
+ INITCOMMONCONTROLSEX icce = {0};
+ icce.dwSize = sizeof(icce);
+ icce.dwICC = ICC_LISTVIEW_CLASSES|ICC_PROGRESS_CLASS;
+ InitCommonControlsEx(&icce);
+ }
+ return TRUE;
+}
+
+DLLFUNC PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ return &pluginInfo;
+}
+
+static const MUUID interfaces[] = {MIID_OTR, MIID_LAST};
+DLLFUNC const MUUID* MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+
+int ModulesLoaded(WPARAM wParam, LPARAM lParam) {
+ if(ServiceExists(MS_MC_GETPROTOCOLNAME))
+ g_metaproto = (char *)CallService(MS_MC_GETPROTOCOLNAME, 0, 0);
+
+ if(ServiceExists(MS_UPDATE_REGISTER)) {
+ // register with updater
+ Update update = {0};
+ char szVersion[16];
+
+ update.cbSize = sizeof(Update);
+
+ update.szComponentName = pluginInfo.shortName;
+ update.pbVersion = (BYTE *)CreateVersionString(pluginInfo.version, szVersion);
+ update.cpbVersion = strlen((char *)update.pbVersion);
+ update.szBetaChangelogURL = "https://server.scottellis.com.au/wsvn/mim_plugs/otr/?op=log&rev=0&sc=0&isdir=1";
+
+ update.szUpdateURL = UPDATER_AUTOREGISTER;
+
+ // these are the three lines that matter - the archive, the page containing the version string, and the text (or data)
+ // before the version that we use to locate it on the page
+ // (note that if the update URL and the version URL point to standard file listing entries, the backend xml
+ // data will be used to check for updates rather than the actual web page - this is not true for beta urls)
+ update.szBetaUpdateURL = "http://www.scottellis.com.au/miranda_plugins/otr.zip";
+ update.szBetaVersionURL = "http://www.scottellis.com.au/miranda_plugins/ver_otr.html";
+ update.pbBetaVersionPrefix = (BYTE *)"OTR (Off The Record) encryption plugin, version ";
+
+ update.cpbBetaVersionPrefix = strlen((char *)update.pbBetaVersionPrefix);
+
+
+ // DISABLED UPDATE CHECK FOR NOW
+ // CallService(MS_UPDATE_REGISTER, 0, (WPARAM)&update);
+ }
+
+ InitUtils();
+
+ lib_cs_lock();
+ otr_user_state = otrl_userstate_create();
+ lib_cs_unlock();
+
+ // this calls ReadPrivkeyFiles (above) to set filename values (also called on ME_FOLDERS_PATH_CHANGED)
+ InitOptions();
+
+ InitDBFilter();
+ InitIcons();
+ InitMenu();
+
+ InitSRMM();
+
+ hEventWindow = HookEvent(ME_MSG_WINDOWEVENT, WindowEvent);
+
+ // HookEvent(ME_OPT_INITIALISE, OptInit);
+
+ // hook setting changed to monitor status
+ //hSettingChanged = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, SettingChanged);
+
+ // hook status mode changes to terminate sessions when we go offline
+ // (this would be hooked as the ME_CLIST_STATUSMODECHANGE handler except that event is sent *after* the proto goes offline)
+ // (instead, it's called from the SettingChanged handler for protocol status db setting changes)
+ //HookEvent(ME_CLIST_STATUSMODECHANGE, StatusModeChange);
+
+ return 0;
+}
+
+int NewContact(WPARAM wParam, LPARAM lParam) {
+ // add filter
+ HANDLE hContact = (HANDLE)wParam;
+ CallService( MS_PROTO_ADDTOCONTACT, ( WPARAM )hContact, ( LPARAM )MODULENAME );
+
+ return 0;
+}
+
+DLLFUNC int Load(PLUGINLINK *link)
+{
+ DEBUGOUT_T("LOAD MIROTR")
+ pluginLink=link;
+ mir_getMMI(&mmi);
+ mir_getUTFI(&utfi);
+
+ CallService(MS_DB_SETSETTINGRESIDENT, TRUE, (LPARAM)(MODULENAME "/TrustLevel"));
+
+ /////////////
+ ////// init plugin
+ PROTOCOLDESCRIPTOR pd = {0};
+ pd.cbSize = sizeof(pd);
+ pd.szName = MODULENAME;
+ pd.type = PROTOTYPE_ENCRYPTION;
+ CallService(MS_PROTO_REGISTERMODULE,0,(LPARAM)&pd);
+
+ // remove us as a filter to all contacts - fix filter type problem
+ /*
+ if(DBGetContactSettingByte(0, MODULENAME, "FilterOrderFix", 0) != 2) {
+ HANDLE hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 );
+ while ( hContact != NULL ) {
+ CallService( MS_PROTO_REMOVEFROMCONTACT, ( WPARAM )hContact, ( LPARAM )MODULENAME );
+ hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 );
+ }
+ DBWriteContactSettingByte(0, MODULENAME, "FilterOrderFix", 2);
+ }
+ */
+ // add us as a filter to all contacts
+ HANDLE hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 );
+ char *proto;
+ while ( hContact != NULL ) {
+ proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ if ( !(proto && DBGetContactSettingByte(hContact, proto, "ChatRoom", 0)) )
+ CallService( MS_PROTO_ADDTOCONTACT, ( WPARAM )hContact, ( LPARAM )MODULENAME );
+ hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 );
+ }
+ HookEvent(ME_DB_CONTACT_ADDED, NewContact);
+
+ // create our services
+ CreateProtoServiceFunction(MODULENAME, PSS_MESSAGE, SVC_OTRSendMessage);
+ CreateProtoServiceFunction(MODULENAME, PSS_MESSAGE"W", SVC_OTRSendMessageW);
+ CreateProtoServiceFunction(MODULENAME, PSR_MESSAGE, SVC_OTRRecvMessage);
+
+ CreateServiceFunction(MS_OTR_MENUSTART, SVC_StartOTR);
+ CreateServiceFunction(MS_OTR_MENUSTOP, SVC_StopOTR);
+
+ // hook modules loaded for updater support
+ HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded);
+
+ return 0;
+}
+
+DLLFUNC int Unload(void)
+{
+ //UnhookEvent(hSettingChanged);
+ UnhookEvent(hEventWindow);
+ //UnhookEvent(hEventDbEventAddedFilter);
+ //UnhookEvent(hEventDbEventAdded);
+ DEBUGOUT_T("UNLOAD MIROTR")
+ DeinitSRMM();
+ DeinitOptions();
+ DeinitMenu();
+ DeinitDBFilter();
+
+ lib_cs_lock();
+ otrl_userstate_free(otr_user_state);
+ lib_cs_unlock();
+
+ DeinitIcons();
+ DeinitUtils();
+
+ return 0;
+} \ No newline at end of file
diff --git a/MirOTR/dllmain.h b/MirOTR/dllmain.h
new file mode 100644
index 0000000..7a99b05
--- /dev/null
+++ b/MirOTR/dllmain.h
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "stdafx.h"
+#include "version.h"
+
+#define DLLFUNC extern "C" __declspec(dllexport)
+
+extern HINSTANCE hInst;
+extern PLUGINLINK *pluginLink; \ No newline at end of file
diff --git a/MirOTR/icons.cpp b/MirOTR/icons.cpp
new file mode 100644
index 0000000..7b26df9
--- /dev/null
+++ b/MirOTR/icons.cpp
@@ -0,0 +1,59 @@
+#include "stdafx.h"
+#include "icons.h"
+TCHAR g_dllpath[1024];
+
+struct
+{
+ const TCHAR* stzDescr;
+ const char* szName;
+ int defIconID;
+}
+static iconList[] = {
+ { _T(LANG_ICON_OTR), ICON_OTR, IDI_OTR },
+ { _T(LANG_ICON_PRIVATE), ICON_PRIVATE, IDI_PRIVATE },
+ { _T(LANG_ICON_UNVERIFIED), ICON_UNVERIFIED, IDI_UNVERIFIED },
+ { _T(LANG_ICON_FINISHED), ICON_FINISHED, IDI_FINISHED },
+ { _T(LANG_ICON_NOT_PRIVATE), ICON_NOT_PRIVATE, IDI_INSECURE }
+
+};
+
+HANDLE hIconLibItem[SIZEOF(iconList)];
+
+void InitIcons() {
+ TCHAR szFile[MAX_PATH+500];
+
+ GetModuleFileName(hInst, szFile, SIZEOF(szFile));
+
+ SKINICONDESC sid = {0};
+ sid.cbSize = sizeof(SKINICONDESC);
+ sid.ptszDefaultFile = szFile;
+ sid.ptszSection = _T(MODULENAME);
+ sid.flags = SIDF_ALL_TCHAR;
+
+ for ( int i = 0; i < SIZEOF(iconList); i++ ) {
+ sid.pszName = (char*)iconList[i].szName;
+ sid.ptszDescription = (TCHAR*)iconList[i].stzDescr;
+ sid.iDefaultIndex = -iconList[i].defIconID;
+ hIconLibItem[i] = (HANDLE)CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+ }
+
+}
+
+void DeinitIcons() {
+ for ( int i = 0; i < SIZEOF(iconList); i++ ) {
+ (HANDLE)CallService(MS_SKIN2_REMOVEICON, 0, (LPARAM)iconList[i].szName);
+ hIconLibItem[i] = NULL;
+ }
+}
+
+HICON LoadIcon(const char* name, int big) {
+ return ( HICON )CallService( MS_SKIN2_GETICON, big, (LPARAM)name );
+}
+
+HANDLE GetIconHandle(const char* name) {
+ return ( HANDLE )CallService( MS_SKIN2_GETICONHANDLE, 0, (LPARAM)name );
+}
+
+void ReleaseIcon(const char* name, int big) {
+ CallService( big ? MS_SKIN2_RELEASEICONBIG : MS_SKIN2_RELEASEICON, 0, (LPARAM)name );
+}
diff --git a/MirOTR/icons.h b/MirOTR/icons.h
new file mode 100644
index 0000000..86605d4
--- /dev/null
+++ b/MirOTR/icons.h
@@ -0,0 +1,12 @@
+#pragma once
+#define ICON_FINISHED (MODULENAME"_finished")
+#define ICON_UNVERIFIED (MODULENAME"_unverified")
+#define ICON_PRIVATE (MODULENAME"_private")
+#define ICON_NOT_PRIVATE (MODULENAME"_not_private")
+#define ICON_OTR (MODULENAME"_otr")
+
+void InitIcons();
+void DeinitIcons();
+HICON LoadIcon(const char* name, int big);
+HANDLE GetIconHandle(const char* name);
+void ReleaseIcon(const char* name, int big); \ No newline at end of file
diff --git a/MirOTR/language.h b/MirOTR/language.h
new file mode 100644
index 0000000..41f4525
--- /dev/null
+++ b/MirOTR/language.h
@@ -0,0 +1,84 @@
+#pragma once
+
+#include "m_langpack.h"
+
+#define LANG_START_OTR LPGEN("Start OTR")
+#define LANG_STOP_OTR LPGEN("Stop OTR")
+
+#define LANG_YES LPGEN("Yes")
+#define LANG_NO LPGEN("No")
+
+#define LANG_OTR_TOOLTIP LPGEN("OTR status (Click for more options)")
+#define LANG_STATUS_DISABLED LPGEN("OTR Encryption: Disabled")
+#define LANG_STATUS_UNVERIFIED LPGEN("OTR Encryption: UNVERIFIED")
+#define LANG_STATUS_PRIVATE LPGEN("OTR Encryption: Private")
+#define LANG_STATUS_FINISHED LPGEN("OTR Encryption: Finished")
+
+#define LANG_SESSION_TERMINATED_OTR LPGEN("OTR encrypted session with '%s' has been terminated")
+#define LANG_SESSION_REQUEST_OTR LPGEN("Requesting OTR encrypted session with '%s'")
+#define LANG_SESSION_START_OTR LPGEN("Beginning OTR encrypted session with '%s'")
+#define LANG_SESSION_START_OTR_VERIFY LPGEN("Beginning OTR encrypted session with '%s' (NOT VERIFIED)")
+#define LANG_SESSION_TRY_CONTINUE_OTR LPGEN("Trying to refresh OTR encrypted session with '%s'")
+#define LANG_SESSION_HAS_CONTINUE_OTR LPGEN("OTR encrypted session was refreshed by '%s'")
+#define LANG_SESSION_HAS_CONTINUE_OTR_VERIFY LPGEN("OTR encrypted session was refreshed by '%s' (NOT VERIFIED)")
+#define LANG_SESSION_REQUEST_CONTINUE_OTR LPGEN("OTR encrypted session with '%s' sucessfully refreshed")
+#define LANG_SESSION_CONTINUE_OTR LPGEN("OTR encrypted session with '%s' sucessfully refreshed")
+#define LANG_SESSION_CONTINUE_OTR_VERIFY LPGEN("OTR encrypted session with '%s' sucessfully refreshed (NOT VERIFIED)")
+#define LANG_SESSION_TERMINATED_BY_OTR LPGEN("OTR encrypted session has been terminated by '%s'. You should do that, too!")
+#define LANG_SESSION_NOT_STARTED_OTR LPGEN("OTR encrypted session with '%s' could not be started")
+
+#define LANG_ENCRYPTION_ERROR LPGEN("OTR could not encrypt when sending message")
+
+#define LANG_OTR_INFO LPGEN("OTR Information")
+#define LANG_INLINE_PREFIX LPGEN("[OTR INFO] ")
+
+#define LANG_SMP_AUTH_FROM LPGEN("Authentication from %s")
+#define LANG_SMP_AUTH LPGEN("Authenticae %s")
+
+#define LANG_UNKNOWN LPGEN("Unknown")
+#define LANG_OTR_USERMESSAGE LPGEN("OTR: %s (%s)")
+#define LANG_OTR_NOTIFY LPGEN("OTR %s (%s)")
+
+#define LANG_FINGERPRINT_CAPTION LPGEN("OTR New Fingerprint")
+#define LANG_FINGERPRINT_ASK_VERIFY LPGEN("OTR encrypted session with '%s'.\n\nFingerprint is UNVERIFIED.\n\n%s\n\nVerify?")
+#define LANG_FINGERPRINT_ASK_NEW LPGEN("A new fingerprint has been recieved from '%s'\n\n%s\n\nDo you trust it?")
+#define LANG_FINGERPRINT_VERIFIED LPGEN("OTR encrypted session with '%s' is now using a VERIFIED fingerprint")
+#define LANG_FINGERPRINT_NOT_VERIFIED LPGEN("OTR encrypted session with '%s' is now using a NOT VERIFIED fingerprint")
+
+#define LANG_ICON_UNVERIFIED LPGEN("OTR unverified")
+#define LANG_ICON_FINISHED LPGEN("OTR finished")
+#define LANG_ICON_PRIVATE LPGEN("OTR private")
+#define LANG_ICON_NOT_PRIVATE LPGEN("OTR not secure")
+#define LANG_ICON_OTR LPGEN("OTR")
+
+#define LANG_GENERATE_KEY LPGEN("Generating new private key for protocol '%s'.\nPlease Wait...")
+
+#define LANG_OPT_GENERAL LPGEN("General")
+#define LANG_OPT_PROTO LPGEN("Protocols")
+#define LANG_OPT_CONTACTS LPGEN("Contacts")
+#define LANG_OPT_FINGER LPGEN("Fingerprints")
+
+#define LANG_CONTACT LPGEN("Contact")
+#define LANG_PROTO LPGEN("Protocol")
+#define LANG_POLICY LPGEN("Policy")
+#define LANG_VERIFIED LPGEN("Verified")
+#define LANG_ACTIVE LPGEN("Active")
+#define LANG_FINGERPRINT LPGEN("Fingerprint")
+
+#define LANG_POLICY_DEFAULT LPGEN("Default")
+#define LANG_POLICY_ALWAYS LPGEN("Always")
+#define LANG_POLICY_OPP LPGEN("Opportunistic")
+#define LANG_POLICY_MANUAL LPGEN("Manual")
+#define LANG_POLICY_NEVER LPGEN("Never")
+
+#define LANG_OTR_ASK_NEWKEY LPGEN("Generating new key for '%s'. Continue?")
+#define LANG_OTR_ASK_REMOVEKEY LPGEN("Removing key for '%s'. Continue?")
+
+#define LANG_OTR_FPVERIFY_TITLE LPGEN("OTR Fingerprint Verification")
+#define LANG_OTR_FPVERIFY_DESC LPGEN("OTR encrypted session with '%s'.\nThe OTR fingerprint used by your contact is NOT VERIFIED.\nDo you trust it?")
+#define LANG_OTR_FPVERIFIED_DESC LPGEN("OTR encrypted session with '%s'.\nThe OTR fingerprint used by your contact is already verified.\nDo you still trust it?")
+#define LANG_YOUR_PRIVKEY LPGEN("Your Fingerprint to tell your contact (use a trusted channel!)")
+#define LANG_CONTACT_FINGERPRINT LPGEN("VERIFY: Fingerprint from contact")
+
+#define LANG_FINGERPRINT_STILL_IN_USE LPGEN("Fingerprint '%s' still in use in conversation with '%s'. You cannot delete it!")
+#define LANG_FINGERPRINT_NOT_DELETED LPGEN("Fingerprint '%s' in use in conversation with '%s'. It could not be deleted!") \ No newline at end of file
diff --git a/MirOTR/options.cpp b/MirOTR/options.cpp
new file mode 100644
index 0000000..993f7fd
--- /dev/null
+++ b/MirOTR/options.cpp
@@ -0,0 +1,875 @@
+#include "stdafx.h"
+#include "options.h"
+#include "utils.h"
+#include "m_options.h"
+#include <Prsht.h>
+#include <commctrl.h>
+#include <process.h>
+
+char g_fingerprint_store_filename[MAX_PATH];
+char g_private_key_filename[MAX_PATH];
+HANDLE hPATH_MIROTR;
+Options options;
+#define DATA_DIRECTORY MIRANDA_USERDATA "\\" MODULENAME
+HANDLE hHookOptions;
+struct PROTOREGENKEYOPTIONS {
+ HWND refresh;
+ TCHAR proto[129];
+};
+
+void SetFilenames(const char *path) {
+ if (!path || !path[0]) return;
+ strcpy(g_fingerprint_store_filename, path);
+ strcpy(g_private_key_filename, path);
+ strcat(g_fingerprint_store_filename, ("\\"));
+ strcat(g_private_key_filename, ("\\"));
+
+ strcat(g_fingerprint_store_filename, FINGERPRINT_STORE_FILENAME);
+ strcat(g_private_key_filename, PRIVATE_KEY_FILENAME);
+}
+
+int FoldersChanged(WPARAM wParam, LPARAM lParam) {
+ char path[MAX_PATH];
+
+ FOLDERSGETDATA fgd = {0};
+ fgd.cbSize = sizeof(FOLDERSGETDATA);
+ fgd.nMaxPathSize = MAX_PATH;
+ fgd.szPath = path;
+
+ CallService(MS_FOLDERS_GET_PATH, (LPARAM)hPATH_MIROTR, (LPARAM)&fgd);
+
+ SetFilenames(path);
+ ReadPrivkeyFiles();
+ return 0;
+}
+
+void LoadFilenames() {
+ char *path = Utils_ReplaceVars(DATA_DIRECTORY);
+ CallService(MS_UTILS_CREATEDIRTREE, 0, (LPARAM) path);
+ SetFilenames(path);
+ mir_free(path);
+
+ if(ServiceExists(MS_FOLDERS_REGISTER_PATH)) {
+ FoldersRegisterCustomPath(MODULENAME, "Private Data", DATA_DIRECTORY);
+ HookEvent(ME_FOLDERS_PATH_CHANGED, FoldersChanged);
+
+ // get the path - above are only defaults - there may be a different value in the db
+ FoldersChanged(0, 0);
+ } else {
+ ReadPrivkeyFiles();
+ }
+}
+
+void LoadOptions() {
+ options.default_policy = DBGetContactSettingWord(0, MODULENAME, "DefaultPolicy", OTRL_POLICY_OPPORTUNISTIC);
+ // deal with changed flags in proto.h and new interpretation of 'manual' mode (see common.h)
+ switch(options.default_policy) {
+ case OTRL_POLICY_MANUAL:
+ options.default_policy = OTRL_POLICY_MANUAL_MOD;
+ break;
+ case OTRL_POLICY_OPPORTUNISTIC:
+ case OTRL_POLICY_MANUAL_MOD:
+ case OTRL_POLICY_ALWAYS:
+ case OTRL_POLICY_NEVER:
+ break;
+ default:
+ options.default_policy = OTRL_POLICY_OPPORTUNISTIC;
+ break;
+ }
+ options.err_method = (ErrorDisplay)DBGetContactSettingWord(0, MODULENAME, "ErrorDisplay", ED_POP);
+ options.prefix_messages = (DBGetContactSettingByte(0, MODULENAME, "PrefixMessages", 0) == 1);
+ options.msg_inline = (DBGetContactSettingByte(0, MODULENAME, "MsgInline", 0) == 1);
+ options.msg_popup = (DBGetContactSettingByte(0, MODULENAME, "MsgPopup", 1) == 1);
+ options.no_history = (DBGetContactSettingByte(0, MODULENAME, "NoHistory", 0) == 1);
+ options.autoshow_verify = (DBGetContactSettingByte(0, MODULENAME, "AutoShowVerify", 1) == 1);
+
+ DBVARIANT dbv;
+ if(!DBGetContactSettingUTF8String(0, MODULENAME, "Prefix", &dbv)) {
+ strncpy(options.prefix, dbv.pszVal, OPTIONS_PREFIXLEN);
+ options.prefix[OPTIONS_PREFIXLEN-1] = 0;
+ DBFreeVariant(&dbv);
+ } else
+ strcpy(options.prefix, ("OTR: "));
+
+ options.timeout_finished = (DBGetContactSettingByte(0, MODULENAME, "TimeoutFinished", 0) == 1);
+
+ options.end_offline = (DBGetContactSettingByte(0, MODULENAME, "EndOffline", 1) == 1);
+ options.end_window_close = (DBGetContactSettingByte(0, MODULENAME, "EndWindowClose", 0) == 1);
+
+ options.bHaveMetaContacts = 0!=ServiceExists(MS_MC_GETMETACONTACT);
+ options.bHavePopups = 0!=ServiceExists(MS_POPUP_ADDPOPUPT) && ServiceExists(MS_POPUP_SHOWMESSAGE);
+ options.bHaveSRMMIcons = 0!=ServiceExists(MS_MSG_MODIFYICON);
+
+ LoadFilenames();
+}
+
+extern "C" INT_PTR OpenOptions(WPARAM wParam, LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp = { 0 };
+
+ odp.cbSize = sizeof(odp);
+ odp.position = 100;
+ odp.hInstance = hInst;
+ odp.ptszGroup = LPGENT("Plugins");
+ odp.ptszTitle = _T(MODULENAME);
+ odp.flags = ODPF_BOLDGROUPS|ODPF_TCHAR;
+
+ odp.ptszTab = _T(LANG_OPT_GENERAL);
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_GENERAL);
+ odp.pfnDlgProc = DlgProcMirOTROpts;
+ CallService( MS_OPT_ADDPAGE, wParam,( LPARAM )&odp );
+
+ odp.ptszTab = _T(LANG_OPT_PROTO);
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_PROTO);
+ odp.pfnDlgProc = DlgProcMirOTROptsProto;
+ CallService( MS_OPT_ADDPAGE, wParam,( LPARAM )&odp );
+
+ odp.ptszTab = _T(LANG_OPT_CONTACTS);
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_CONTACTS);
+ odp.pfnDlgProc = DlgProcMirOTROptsContacts;
+ CallService( MS_OPT_ADDPAGE, wParam,( LPARAM )&odp );
+
+ odp.ptszTab = _T(LANG_OPT_FINGER);
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_FINGER);
+ odp.pfnDlgProc = DlgProcMirOTROptsFinger;
+ CallService( MS_OPT_ADDPAGE, wParam,( LPARAM )&odp );
+
+ return 0;
+}
+
+void InitOptions() {
+ LoadOptions();
+ hHookOptions = HookEvent(ME_OPT_INITIALISE, OpenOptions);
+}
+
+void DeinitOptions() {
+ UnhookEvent(hHookOptions);
+}
+
+void SaveOptions() {
+ DBWriteContactSettingWord(0, MODULENAME, "DefaultPolicy", options.default_policy);
+ DBWriteContactSettingWord(0, MODULENAME, "ErrorDisplay", (int)options.err_method);
+ DBWriteContactSettingByte(0, MODULENAME, "PrefixMessages", options.prefix_messages ? 1 : 0);
+ DBWriteContactSettingByte(0, MODULENAME, "MsgInline", options.msg_inline ? 1 : 0);
+ DBWriteContactSettingByte(0, MODULENAME, "MsgPopup", options.msg_popup ? 1 : 0);
+
+ DBWriteContactSettingByte(0, MODULENAME, "NoHistory", options.no_history ? 1 : 0);
+ DBWriteContactSettingByte(0, MODULENAME, "AutoShowVerify", options.autoshow_verify ? 1 : 0);
+
+ /*
+ if (contact_policies) {
+ for(ContactPolicyMap::iterator i = contact_policies->begin(); i != contact_policies->end(); i++) {
+ DBWriteContactSettingWord(i->first, MODULENAME, "Policy", i->second);
+ }
+ }
+ */
+
+ DBWriteContactSettingStringUtf(0, MODULENAME, "Prefix", options.prefix);
+
+ DBWriteContactSettingByte(0, MODULENAME, "TimeoutFinished", options.timeout_finished ? 1 : 0);
+
+ DBWriteContactSettingByte(0, MODULENAME, "EndOffline", options.end_offline ? 1 : 0);
+ DBWriteContactSettingByte(0, MODULENAME, "EndWindowClose", options.end_window_close ? 1 : 0);
+}
+
+extern "C" void set_context_contact(void *data, ConnContext *context) {
+ HANDLE hContact = find_contact(context->username, context->protocol);
+ context->app_data = hContact;
+ }
+
+void ReadPrivkeyFiles() {
+ DEBUGOUT_T("READ privkey");
+ lib_cs_lock();
+ otrl_privkey_read(otr_user_state, g_private_key_filename);
+ otrl_privkey_read_fingerprints(otr_user_state, g_fingerprint_store_filename, set_context_contact, 0);
+ lib_cs_unlock();
+}
+
+static INT_PTR CALLBACK DlgProcMirOTROpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ TCHAR *prefix; char* prefix_utf;
+ switch ( msg ) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault( hwndDlg );
+
+ // set default policy radio
+ switch(options.default_policy) {
+ case OTRL_POLICY_OPPORTUNISTIC:
+ CheckDlgButton(hwndDlg, IDC_RAD_OPP, TRUE);
+ break;
+ case OTRL_POLICY_MANUAL_MOD:
+ CheckDlgButton(hwndDlg, IDC_RAD_MANUAL, TRUE);
+ break;
+ case OTRL_POLICY_ALWAYS:
+ CheckDlgButton(hwndDlg, IDC_RAD_ALWAYS, TRUE);
+ break;
+ case OTRL_POLICY_NEVER:
+ CheckDlgButton(hwndDlg, IDC_RAD_NEVER, TRUE);
+ break;
+ }
+
+ CheckDlgButton(hwndDlg, IDC_CHK_PREFIX, options.prefix_messages ? TRUE : FALSE);
+ CheckDlgButton(hwndDlg, IDC_CHK_MSGINLINE, options.msg_inline ? TRUE : FALSE);
+ CheckDlgButton(hwndDlg, IDC_CHK_MSGPOPUP, options.msg_popup ? TRUE : FALSE);
+ CheckDlgButton(hwndDlg, IDC_CHK_TIMEFINISH, options.timeout_finished ? TRUE : FALSE);
+ CheckDlgButton(hwndDlg, IDC_CHK_PREVENTSAVE, options.no_history ? TRUE : FALSE);
+ CheckDlgButton(hwndDlg, IDC_CHK_AUTOSHOW_VERIFY, options.autoshow_verify ? TRUE : FALSE);
+ CheckDlgButton(hwndDlg, IDC_CHK_ENDOFFLINE, options.end_offline ? TRUE : FALSE);
+ CheckDlgButton(hwndDlg, IDC_CHK_ENDCLOSE, options.end_window_close ? TRUE : FALSE);
+
+ prefix = mir_utf8decodeT(options.prefix);
+ SetDlgItemText(hwndDlg, IDC_ED_PREFIX, prefix);
+ mir_free(prefix);
+
+ return TRUE;
+ break;
+
+ case WM_COMMAND:
+ switch ( HIWORD( wParam )) {
+ case BN_CLICKED:
+ switch ( LOWORD( wParam )) {
+ case IDC_RAD_OPP:
+ case IDC_RAD_MANUAL:
+ case IDC_RAD_ALWAYS:
+ case IDC_RAD_NEVER:
+ case IDC_CHK_PREFIX:
+ case IDC_CHK_MSGINLINE:
+ case IDC_CHK_MSGPOPUP:
+ case IDC_CHK_TIMEFINISH:
+ case IDC_CHK_PREVENTSAVE:
+ case IDC_CHK_AUTOSHOW_VERIFY:
+ case IDC_CHK_ENDOFFLINE:
+ case IDC_CHK_ENDCLOSE:
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+ case EN_CHANGE:
+ if (LOWORD( wParam ) == IDC_ED_PREFIX && ( HWND )lParam == GetFocus())
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+
+ if (((LPNMHDR)lParam)->code == (UINT) PSN_APPLY ) {
+ // handle apply
+
+ if (IsDlgButtonChecked(hwndDlg, IDC_RAD_OPP))
+ options.default_policy = OTRL_POLICY_OPPORTUNISTIC;
+ else if (IsDlgButtonChecked(hwndDlg, IDC_RAD_MANUAL))
+ options.default_policy = OTRL_POLICY_MANUAL_MOD;
+ else if (IsDlgButtonChecked(hwndDlg, IDC_RAD_ALWAYS))
+ options.default_policy = OTRL_POLICY_ALWAYS;
+ else
+ options.default_policy = OTRL_POLICY_NEVER;
+
+ options.prefix_messages = (TRUE==IsDlgButtonChecked(hwndDlg, IDC_CHK_PREFIX));
+ options.msg_inline = (TRUE==IsDlgButtonChecked(hwndDlg, IDC_CHK_MSGINLINE));
+ options.msg_popup = (TRUE==IsDlgButtonChecked(hwndDlg, IDC_CHK_MSGPOPUP));
+ options.timeout_finished = (TRUE==IsDlgButtonChecked(hwndDlg, IDC_CHK_TIMEFINISH));
+ options.no_history = (TRUE==IsDlgButtonChecked(hwndDlg, IDC_CHK_PREVENTSAVE));
+ options.autoshow_verify = (TRUE==IsDlgButtonChecked(hwndDlg, IDC_CHK_AUTOSHOW_VERIFY));
+ options.end_offline = (TRUE==IsDlgButtonChecked(hwndDlg, IDC_CHK_ENDOFFLINE));
+ options.end_window_close = (TRUE==IsDlgButtonChecked(hwndDlg, IDC_CHK_ENDCLOSE));
+
+ prefix = (TCHAR*)mir_alloc(sizeof(TCHAR)*OPTIONS_PREFIXLEN);
+ GetDlgItemText(hwndDlg, IDC_ED_PREFIX, prefix, OPTIONS_PREFIXLEN);
+ prefix_utf = mir_utf8encodeT(prefix);
+ mir_free(prefix);
+ strncpy(options.prefix, prefix_utf, OPTIONS_PREFIXLEN);
+ mir_free(prefix_utf);
+
+ SaveOptions();
+
+ return TRUE;
+ }
+
+ break;
+ }
+ return FALSE;
+}
+
+static unsigned int CALLBACK regen_key_thread(void* param) {
+ CallService(MS_SYSTEM_THREAD_PUSH, 0, 0);
+ PROTOREGENKEYOPTIONS *opts = (PROTOREGENKEYOPTIONS *)param;
+ TCHAR *buff = (TCHAR*) mir_alloc(512*sizeof(TCHAR));
+ mir_sntprintf(buff, 512, TranslateT(LANG_OTR_ASK_NEWKEY), opts->proto);
+ EnableWindow(opts->refresh, FALSE);
+ if (IDYES == MessageBox(opts->refresh, buff, TranslateT(LANG_OTR_INFO), MB_ICONQUESTION|MB_YESNO))
+ {
+ mir_free(buff);
+
+ char* proto = mir_t2a(opts->proto);
+ otr_gui_create_privkey(0, proto, proto);
+ SendMessage(opts->refresh, WMU_REFRESHPROTOLIST, 0, 0);
+ /*
+ char *fp = (char*)mir_alloc(20);
+ otrl_privkey_fingerprint(otr_user_state, fp, proto, proto);
+ TCHAR *fpt = mir_a2t(fp);
+ mir_free(fp);
+ ListView_SetItemText(GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS), sel, 2, fpt);
+ mir_free(fpt);
+ mir_free(proto);
+ */
+ } else {
+ mir_free(buff);
+ }
+ EnableWindow(opts->refresh, TRUE);
+ delete opts;
+ CallService(MS_SYSTEM_THREAD_POP, 0, 0);
+ return 0;
+}
+
+static INT_PTR CALLBACK DlgProcMirOTROptsProto(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HWND lv;
+ switch ( msg ) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault( hwndDlg );
+ lv = GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS);
+
+ {
+ HWND cmb = GetDlgItem(hwndDlg, IDC_CMB_PROTO_POLICY);
+ SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_DEFAULT));
+ SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_ALWAYS));
+ SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_OPP));
+ SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_MANUAL));
+ SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_NEVER));
+ SendMessage(GetDlgItem(hwndDlg, IDC_CMB_PROTO_POLICY), CB_SETCURSEL, (LPARAM)-1, 0);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CMB_PROTO_POLICY), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BTN_PROTO_NEWKEY), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BTN_PROTO_FORGET), FALSE);
+ }
+
+ SendMessage(lv,LVM_SETEXTENDEDLISTVIEWSTYLE, 0,LVS_EX_FULLROWSELECT);// | LVS_EX_CHECKBOXES);
+ {
+ // add list columns
+ LVCOLUMN lvc;
+ // Initialize the LVCOLUMN structure.
+ // The mask specifies that the format, width, text, and
+ // subitem members of the structure are valid.
+ lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
+ lvc.fmt = LVCFMT_LEFT;
+
+ lvc.iSubItem = 0;
+ lvc.pszText = TranslateT(LANG_PROTO);
+ lvc.cx = 85; // width of column in pixels
+ ListView_InsertColumn(lv, 0, &lvc);
+
+ lvc.iSubItem = 1;
+ lvc.pszText = TranslateT(LANG_POLICY);
+ lvc.cx = 80; // width of column in pixels
+ ListView_InsertColumn(lv, 1, &lvc);
+
+ lvc.iSubItem = 2;
+ lvc.pszText = TranslateT(LANG_FINGERPRINT);
+ lvc.cx = 275; // width of column in pixels
+ ListView_InsertColumn(lv, 2, &lvc);
+ }
+ PostMessage(hwndDlg, WMU_REFRESHPROTOLIST, 0, 0);
+
+ return TRUE;
+ case WMU_REFRESHPROTOLIST:
+ {
+ lv = GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS);
+ ListView_DeleteAllItems(lv);
+ int num_protocols;
+ PROTOCOLDESCRIPTOR **pppDesc;
+ int ilvItem;
+ LV_ITEM item = {0};
+ char fprint[45];
+ TCHAR* temp;
+ //BOOL unicode = ListView_GetUnicodeFormat(lv);
+
+ CallService(MS_PROTO_ENUMPROTOCOLS, (LPARAM)&num_protocols, (WPARAM)&pppDesc);
+ for(int i = 0; i < num_protocols; i++) {
+ if(pppDesc[i]->type == PROTOTYPE_PROTOCOL && (!g_metaproto || strcmp(pppDesc[i]->szName, g_metaproto) != 0)
+ && (CallProtoService(pppDesc[i]->szName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_IM) == PF1_IM)
+ {
+ //if (unicode) {
+ item.mask = LVIF_TEXT;
+ temp = mir_a2t(pppDesc[i]->szName);
+ item.pszText = temp;
+ ilvItem = ListView_InsertItem(lv, &item);
+ mir_free(temp);
+
+
+ ListView_SetItemText(lv, ilvItem, 1, (TCHAR*)policy_to_string(db_dword_get(0,MODULENAME"_ProtoPol", pppDesc[i]->szName, CONTACT_DEFAULT_POLICY)) );
+ if(otrl_privkey_fingerprint(otr_user_state, fprint, pppDesc[i]->szName, pppDesc[i]->szName)) {
+ temp = mir_a2t(fprint);
+ ListView_SetItemText(lv, ilvItem, 2, temp);
+ mir_free(temp);
+ }
+ /*} else { //using ASCII
+ item.pszText = (TCHAR*)pppDesc[i]->szName;
+ ilvItem = ListView_InsertItem(lv, &item);
+ if(otrl_privkey_fingerprint(otr_user_state, fprint, pppDesc[i]->szName, pppDesc[i]->szName)) {
+ ListView_SetItemText(lv, ilvItem, 2, (TCHAR*)fprint);
+ }
+ }*/
+
+
+ }
+ }
+ }
+ return TRUE;
+ case WM_COMMAND:
+ switch ( HIWORD( wParam )) {
+ case BN_CLICKED:
+ switch ( LOWORD( wParam )) {
+ case IDC_BTN_PROTO_NEWKEY:
+ {
+ int sel = ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS));
+ if (sel != -1) {
+ PROTOREGENKEYOPTIONS *opts = new PROTOREGENKEYOPTIONS();
+ opts->refresh = hwndDlg;
+ ListView_GetItemText(GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS), sel, 0, opts->proto, 128);
+ CloseHandle((HANDLE)_beginthreadex(0, 0, regen_key_thread, opts, 0, 0));
+ }
+ }break;
+ case IDC_BTN_PROTO_FORGET:
+ {
+ int sel = ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS));
+ if (sel != -1) {
+ TCHAR buff_proto[128];
+ ListView_GetItemText(GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS), sel, 0, buff_proto, 128);
+ TCHAR buff[512];
+ mir_sntprintf(buff, 512, TranslateT(LANG_OTR_ASK_REMOVEKEY), buff_proto);
+ if (IDYES == MessageBox(hwndDlg, buff, TranslateT(LANG_OTR_INFO), MB_ICONQUESTION|MB_YESNO))
+ {
+ char* proto = mir_t2a(buff_proto);
+ OtrlPrivKey *key = otrl_privkey_find(otr_user_state, proto, proto);
+ mir_free(proto);
+ if (key) {
+ otrl_privkey_forget(key);
+ otrl_privkey_write(otr_user_state, g_private_key_filename);
+ ListView_SetItemText(GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS), sel, 2, _T(""));
+ }
+ }
+ }
+ }break;
+ }
+ case CBN_SELCHANGE:
+ switch ( LOWORD( wParam )) {
+ case IDC_CMB_PROTO_POLICY:
+ {
+ int proto = ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS));
+ if (proto == -1) break;
+ int sel = SendDlgItemMessage(hwndDlg, IDC_CMB_PROTO_POLICY, CB_GETCURSEL, 0, 0);
+ if (sel==CB_ERR) break;
+ int len = SendDlgItemMessage(hwndDlg, IDC_CMB_PROTO_POLICY, CB_GETLBTEXTLEN, sel, 0);
+ if (len < 0) break;
+ TCHAR *text = new TCHAR[len+1];
+ SendDlgItemMessage(hwndDlg, IDC_CMB_PROTO_POLICY, CB_GETLBTEXT, sel, (LPARAM)text);
+ ListView_SetItemText(GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS), proto, 1, text);
+ delete text;
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }break;
+ }
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ if (((LPNMHDR) lParam)->code == (UINT) LVN_ITEMCHANGED && ((LPNMHDR) lParam)->hwndFrom == GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS)
+ && (((LPNMLISTVIEW)lParam)->uNewState & LVIS_SELECTED )) {
+ int sel = ListView_GetSelectionMark(((LPNMHDR) lParam)->hwndFrom);
+ if (sel == -1) {
+ SendMessage(GetDlgItem(hwndDlg, IDC_CMB_PROTO_POLICY), CB_SETCURSEL, (LPARAM)-1, 0);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CMB_PROTO_POLICY), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BTN_PROTO_NEWKEY), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BTN_PROTO_FORGET), FALSE);
+ } else {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CMB_PROTO_POLICY), TRUE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BTN_PROTO_NEWKEY), TRUE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BTN_PROTO_FORGET), TRUE);
+ TCHAR buff[50];
+ ListView_GetItemText(((LPNMHDR)lParam)->hwndFrom, sel, 1, buff, 50);
+ SendMessage(GetDlgItem(hwndDlg, IDC_CMB_PROTO_POLICY), CB_SELECTSTRING, (LPARAM)-1, (WPARAM)buff);
+ }
+
+ } else if (((LPNMHDR)lParam)->code == (UINT) PSN_APPLY ) {
+ lv = GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS);
+ int cnt = ListView_GetItemCount(lv);
+ TCHAR proto_t[128], policy[64];
+ char* proto;
+ for (int i = 0; i < cnt; ++i) {
+ ListView_GetItemText(lv, i, 0, proto_t, 128);
+ ListView_GetItemText(lv, i, 1, policy, 64);
+ proto = mir_t2a(proto_t);
+ db_dword_set(0, MODULENAME"_ProtoPol", proto, policy_from_string(policy));
+ mir_free(proto);
+ }
+ // handle apply
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static INT_PTR CALLBACK DlgProcMirOTROptsContacts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch ( msg ) {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault( hwndDlg );
+
+ SetWindowLongPtr(hwndDlg, GWL_USERDATA, (ULONG_PTR) new ContactPolicyMap());
+
+ HWND cmb = GetDlgItem(hwndDlg, IDC_CMB_CONT_POLICY);
+ SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_DEFAULT));
+ SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_ALWAYS));
+ SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_OPP));
+ SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_MANUAL));
+ SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_NEVER));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CMB_CONT_POLICY), FALSE);
+
+ SendDlgItemMessage(hwndDlg, IDC_LV_CONT_CONTACTS ,LVM_SETEXTENDEDLISTVIEWSTYLE, 0,LVS_EX_FULLROWSELECT);// | LVS_EX_CHECKBOXES);
+
+
+ HWND lv = GetDlgItem(hwndDlg, IDC_LV_CONT_CONTACTS);
+
+
+ // add list columns
+ LVCOLUMN lvc;
+ // Initialize the LVCOLUMN structure.
+ // The mask specifies that the format, width, text, and
+ // subitem members of the structure are valid.
+ lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
+ lvc.fmt = LVCFMT_LEFT;
+
+ lvc.iSubItem = 0;
+ lvc.pszText = TranslateT(LANG_CONTACT);
+ lvc.cx = 150; // width of column in pixels
+ ListView_InsertColumn(lv, 0, &lvc);
+
+ lvc.iSubItem = 1;
+ lvc.pszText = TranslateT(LANG_PROTO);
+ lvc.cx = 150; // width of column in pixels
+ ListView_InsertColumn(lv, 1, &lvc);
+
+ lvc.iSubItem = 2;
+ lvc.pszText = TranslateT(LANG_POLICY);
+ lvc.cx = 100; // width of column in pixels
+ ListView_InsertColumn(lv, 2, &lvc);
+ }
+ SendMessage(hwndDlg, WMU_REFRESHLIST, 0, 0);
+
+ return TRUE;
+ case WMU_REFRESHLIST:
+ {
+ HWND lv = GetDlgItem(hwndDlg, IDC_LV_CONT_CONTACTS);
+
+ ListView_DeleteAllItems(lv);
+
+ LVITEM lvI = {0};
+
+ // Some code to create the list-view control.
+ // Initialize LVITEM members that are common to all
+ // items.
+ lvI.mask = LVIF_TEXT | LVIF_PARAM;// | LVIF_NORECOMPUTE;// | LVIF_IMAGE;
+
+ const char *proto;
+ TCHAR *proto_t;
+ HANDLE hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 );
+ while ( hContact != NULL )
+ {
+ proto = contact_get_proto(hContact);
+ if(proto && db_byte_get(hContact, proto, "ChatRoom", 0) == 0 && CallService(MS_PROTO_ISPROTOONCONTACT, (WPARAM)hContact, (LPARAM)MODULENAME) // ignore chatrooms
+ && (g_metaproto == 0 || strcmp(proto, g_metaproto) != 0)) // and MetaContacts
+ {
+ lvI.iItem = 0;
+ lvI.iSubItem = 0;
+ lvI.lParam = (LPARAM)hContact;
+ lvI.pszText = (TCHAR*)contact_get_nameT(hContact);
+ lvI.iItem = ListView_InsertItem(lv , &lvI);
+
+ proto_t = mir_a2t(proto);
+ ListView_SetItemText(lv, lvI.iItem, 1, proto_t);
+ mir_free(proto_t);
+
+ ListView_SetItemText(lv, lvI.iItem, 2, (TCHAR*)policy_to_string((OtrlPolicy)db_dword_get(hContact, MODULENAME, "Policy", CONTACT_DEFAULT_POLICY)) );
+ }
+
+
+ hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 );
+ }
+ }
+ return TRUE;
+ break;
+ case WM_COMMAND:
+ switch ( HIWORD( wParam )) {
+ case CBN_SELCHANGE:
+ switch ( LOWORD( wParam )) {
+ case IDC_CMB_CONT_POLICY:
+ {
+ HANDLE hContact = 0;
+ int iUser = ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_LV_CONT_CONTACTS));
+ if (iUser == -1) break;
+ int sel = SendDlgItemMessage(hwndDlg, IDC_CMB_CONT_POLICY, CB_GETCURSEL, 0, 0);
+ if (sel==CB_ERR) break;
+ int len = SendDlgItemMessage(hwndDlg, IDC_CMB_CONT_POLICY, CB_GETLBTEXTLEN, sel, 0);
+ if (len < 0) break;
+ TCHAR *text = new TCHAR[len+1];
+ SendDlgItemMessage(hwndDlg, IDC_CMB_CONT_POLICY, CB_GETLBTEXT, sel, (LPARAM)text);
+ ListView_SetItemText(GetDlgItem(hwndDlg, IDC_LV_CONT_CONTACTS), iUser, 2, text);
+ OtrlPolicy policy = policy_from_string(text);
+ delete text;
+ LVITEM lvi = {0};
+ lvi.mask = LVIF_PARAM;
+ lvi.iItem = iUser;
+ lvi.iSubItem = 0;
+ ListView_GetItem(GetDlgItem(hwndDlg, IDC_LV_CONT_CONTACTS), &lvi);
+ ContactPolicyMap* cpm = (ContactPolicyMap*) GetWindowLongPtr(hwndDlg, GWL_USERDATA);
+ hContact = (HANDLE)lvi.lParam;
+ (*cpm)[hContact] = policy;
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }break;
+ }
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ if (((LPNMHDR) lParam)->code == (UINT) LVN_ITEMCHANGED && ((LPNMHDR) lParam)->hwndFrom == GetDlgItem(hwndDlg, IDC_LV_CONT_CONTACTS)
+ && (((LPNMLISTVIEW)lParam)->uNewState & LVIS_SELECTED )) {
+ int sel = ListView_GetSelectionMark(((LPNMHDR) lParam)->hwndFrom);
+ if (sel == -1) {
+ SendMessage(GetDlgItem(hwndDlg, IDC_CMB_CONT_POLICY), CB_SETCURSEL, (LPARAM)-1, 0);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CMB_CONT_POLICY), FALSE);
+ } else {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CMB_CONT_POLICY), TRUE);
+ TCHAR buff[50];
+ ListView_GetItemText(((LPNMHDR)lParam)->hwndFrom, sel, 2, buff, 50);
+ SendMessage(GetDlgItem(hwndDlg, IDC_CMB_CONT_POLICY), CB_SELECTSTRING, (LPARAM)-1, (WPARAM)buff);
+ }
+
+ } else if (((LPNMHDR)lParam)->code == (UINT) PSN_APPLY ) {
+ // handle apply
+
+ ContactPolicyMap *cpm = (ContactPolicyMap*) GetWindowLongPtr(hwndDlg, GWL_USERDATA);
+ // Iterate over the map and print out all key/value pairs.
+ // Using a const_iterator since we are not going to change the values.
+ for(ContactPolicyMap::const_iterator it = cpm->begin(); it != cpm->end(); ++it)
+ {
+ if (!it->first) continue;
+ DBWriteContactSettingDword(it->first, MODULENAME, "Policy", (DWORD)it->second);
+ }
+ return TRUE;
+ }
+ break;
+ case WM_DESTROY:
+ ContactPolicyMap *cpm = (ContactPolicyMap*) GetWindowLongPtr(hwndDlg, GWL_USERDATA);
+ cpm->clear();
+ delete cpm;
+ break;
+ }
+ return FALSE;
+}
+
+static INT_PTR CALLBACK DlgProcMirOTROptsFinger(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch ( msg ) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault( hwndDlg );
+ SetWindowLongPtr(hwndDlg, GWL_USERDATA, (ULONG_PTR) new FPModifyMap());
+
+ SendDlgItemMessage(hwndDlg, IDC_LV_FINGER_LIST ,LVM_SETEXTENDEDLISTVIEWSTYLE, 0,LVS_EX_FULLROWSELECT);// | LVS_EX_CHECKBOXES);
+
+ {
+ HWND lv = GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST);
+ // add list columns
+ LVCOLUMN lvc;
+ // Initialize the LVCOLUMN structure.
+ // The mask specifies that the format, width, text, and
+ // subitem members of the structure are valid.
+ lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
+ lvc.fmt = LVCFMT_LEFT;
+
+ lvc.iSubItem = 0;
+ lvc.pszText = TranslateT(LANG_CONTACT);
+ lvc.cx = 100; // width of column in pixels
+ ListView_InsertColumn(lv, 0, &lvc);
+
+ lvc.iSubItem = 1;
+ lvc.pszText = TranslateT(LANG_PROTO);
+ lvc.cx = 90; // width of column in pixels
+ ListView_InsertColumn(lv, 1, &lvc);
+
+ lvc.iSubItem = 2;
+ lvc.pszText = TranslateT(LANG_ACTIVE);
+ lvc.cx = 50; // width of column in pixels
+ ListView_InsertColumn(lv, 2, &lvc);
+
+ lvc.iSubItem = 3;
+ lvc.pszText = TranslateT(LANG_VERIFIED);
+ lvc.cx = 50; // width of column in pixels
+ ListView_InsertColumn(lv, 3, &lvc);
+
+ lvc.iSubItem = 4;
+ lvc.pszText = TranslateT(LANG_FINGERPRINT);
+ lvc.cx = 300; // width of column in pixels
+ ListView_InsertColumn(lv, 4, &lvc);
+ }
+ SendMessage(hwndDlg, WMU_REFRESHLIST, 0, 0);
+
+ return TRUE;
+
+ case WMU_REFRESHLIST:
+ //enumerate contacts, fill in list
+ {
+ HWND lv = GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST);
+ ListView_DeleteAllItems(lv);
+
+ LVITEM lvI = {0};
+
+ // Some code to create the list-view control.
+ // Initialize LVITEM members that are common to all
+ // items.
+ lvI.mask = LVIF_TEXT | LVIF_PARAM;// | LVIF_NORECOMPUTE;// | LVIF_IMAGE;
+ ConnContext * context = otr_user_state->context_root;
+ TCHAR *proto, *user, hash[45] = {0};
+ Fingerprint *fp;
+ while (context) {
+ if (context->app_data) {
+ user = (TCHAR*)contact_get_nameT((HANDLE)context->app_data);
+ if (user) {
+ proto = mir_a2t(context->protocol);
+ fp = context->fingerprint_root.next;
+ while(fp) {
+ otrl_privkey_hash_to_humanT(hash, fp->fingerprint);
+ if (hash) {
+ lvI.iSubItem = 0;
+ lvI.lParam = (LPARAM)fp;
+ lvI.pszText = user;
+ int d = ListView_InsertItem(lv, &lvI);
+
+ ListView_SetItemText(lv,d, 1, proto);
+ ListView_SetItemText(lv,d, 2, (context->active_fingerprint == fp)? TranslateT(LANG_YES) : TranslateT(LANG_NO));
+ ListView_SetItemText(lv,d, 3, (fp->trust && fp->trust != '\0')? TranslateT(LANG_YES) : TranslateT(LANG_NO));
+ ListView_SetItemText(lv,d, 4, hash );
+ }
+ fp = fp->next;
+ }
+ mir_free(proto);
+ }
+ }
+ context = context->next;
+ }
+ }
+
+ return TRUE;
+ case WM_COMMAND:
+ switch ( HIWORD( wParam )) {
+ case BN_CLICKED:
+ switch ( LOWORD( wParam )) {
+ case IDC_BTN_FINGER_DONTTRUST:
+ {
+ int sel = ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST));
+ if (sel != -1) {
+ LVITEM lvi = {0};
+ lvi.mask = LVIF_PARAM;
+ lvi.iItem = sel;
+ Fingerprint *fp = NULL;
+ ListView_GetItem(GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST), &lvi);
+ fp = (Fingerprint*) lvi.lParam;
+ FPModifyMap* fpm = (FPModifyMap*) GetWindowLongPtr(hwndDlg, GWL_USERDATA);
+ (*fpm)[fp] = FPM_NOTRUST;
+ ListView_SetItemText(GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST), sel, 3, TranslateT(LANG_NO));
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ }break;
+ case IDC_BTN_FINGER_TRUST:
+ {
+ int sel = ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST));
+ if (sel != -1) {
+ LVITEM lvi = {0};
+ lvi.mask = LVIF_PARAM;
+ lvi.iItem = sel;
+ Fingerprint *fp = NULL;
+ ListView_GetItem(GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST), &lvi);
+ fp = (Fingerprint*) lvi.lParam;
+ FPModifyMap* fpm = (FPModifyMap*) GetWindowLongPtr(hwndDlg, GWL_USERDATA);
+ (*fpm)[fp] = FPM_VERIFY;
+ ListView_SetItemText(GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST), sel, 3, TranslateT(LANG_YES));
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ }break;
+ case IDC_BTN_FINGER_FORGET:
+ {
+ int sel = ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST));
+ if (sel != -1) {
+ LVITEM lvi = {0};
+ lvi.mask = LVIF_PARAM;
+ lvi.iItem = sel;
+ Fingerprint *fp = NULL;
+ ListView_GetItem(GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST), &lvi);
+ fp = (Fingerprint*) lvi.lParam;
+ if (fp->context->active_fingerprint == fp) {
+ TCHAR buff[1024], hash[45];
+ otrl_privkey_hash_to_humanT(hash, fp->fingerprint);
+ mir_sntprintf(buff, 1024, TranslateT(LANG_FINGERPRINT_STILL_IN_USE), hash, contact_get_nameT((HANDLE)fp->context->app_data));
+ ShowError(buff);
+ } else {
+ FPModifyMap* fpm = (FPModifyMap*) GetWindowLongPtr(hwndDlg, GWL_USERDATA);
+ (*fpm)[fp] = FPM_DELETE;
+ ListView_DeleteItem(GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST), sel);
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ }
+ }break;
+ }
+ }
+ break;
+
+ case WM_NOTIFY:
+ if (((LPNMHDR)lParam)->code == (UINT) PSN_APPLY ) {
+ // handle apply
+
+ FPModifyMap *fpm = (FPModifyMap*) GetWindowLongPtr(hwndDlg, GWL_USERDATA);
+ // Iterate over the map and print out all key/value pairs.
+ // Using a const_iterator since we are not going to change the values.
+ for(FPModifyMap::const_iterator it = fpm->begin(); it != fpm->end(); ++it)
+ {
+ if (!it->first) continue;
+ switch (it->second) {
+ case FPM_DELETE:
+ if (it->first->context->active_fingerprint == it->first) {
+ TCHAR buff[1024], hash[45];
+ otrl_privkey_hash_to_humanT(hash, it->first->fingerprint);
+ mir_sntprintf(buff, 1024, TranslateT(LANG_FINGERPRINT_NOT_DELETED), hash, contact_get_nameT((HANDLE)it->first->context->app_data));
+ ShowError(buff);
+ } else {
+ otrl_context_forget_fingerprint(it->first, 1);
+ }
+ break;
+ case FPM_VERIFY:
+ otrl_context_set_trust(it->first, "verified");
+ if (it->first == it->first->context->active_fingerprint)
+ SetEncryptionStatus((HANDLE)it->first->context->app_data, otr_context_get_trust(it->first->context));
+ break;
+ case FPM_NOTRUST:
+ otrl_context_set_trust(it->first, NULL);
+ if (it->first == it->first->context->active_fingerprint)
+ SetEncryptionStatus((HANDLE)it->first->context->app_data, otr_context_get_trust(it->first->context));
+ break;
+ }
+ }
+ if (!fpm->empty()) otr_gui_write_fingerprints(0);
+ fpm->clear();
+ SendMessage(hwndDlg, WMU_REFRESHLIST, 0, 0);
+
+ return TRUE;
+ }
+ break;
+ case WM_DESTROY:
+ FPModifyMap *fpm = (FPModifyMap*) GetWindowLongPtr(hwndDlg, GWL_USERDATA);
+ fpm->clear();
+ delete fpm;
+ break;
+ }
+
+ return FALSE;
+} \ No newline at end of file
diff --git a/MirOTR/options.h b/MirOTR/options.h
new file mode 100644
index 0000000..94149d1
--- /dev/null
+++ b/MirOTR/options.h
@@ -0,0 +1,66 @@
+#ifndef _OPTIONS_INC
+#define _OPTIONS_INC
+
+//#include "stdafx.h"
+
+extern char* g_metaproto;
+
+#define PRIVATE_KEY_FILENAME "otr.private_key"
+#define FINGERPRINT_STORE_FILENAME "otr.fingerprints"
+
+extern char g_fingerprint_store_filename[MAX_PATH];
+extern char g_private_key_filename[MAX_PATH];
+
+#define CONTACT_DEFAULT_POLICY 0xFFFF
+
+typedef enum {ED_POP, ED_BAL, ED_MB} ErrorDisplay;
+
+#define OPTIONS_PREFIXLEN 64
+
+typedef struct {
+ OtrlPolicy default_policy;
+ ErrorDisplay err_method;
+ bool prefix_messages;
+ bool msg_inline;
+ bool msg_popup;
+ char prefix[OPTIONS_PREFIXLEN];
+
+ bool timeout_finished;
+
+ bool no_history;
+ bool autoshow_verify;
+
+ bool end_offline, end_window_close;
+
+ // temporary options
+ bool bHaveMetaContacts, bHavePopups, bHaveSRMMIcons;
+
+} Options;
+
+extern Options options;
+
+#define WMU_REFRESHLIST (WM_USER + 241)
+#define WMU_REFRESHPROTOLIST (WM_USER + 242)
+#define CONTACT_DEFAULT_POLICY 0xFFFF
+
+#include <map>
+typedef std::map<HANDLE, OtrlPolicy> ContactPolicyMap;
+typedef enum {FPM_VERIFY, FPM_NOTRUST, FPM_DELETE } FPModify;
+typedef std::map<Fingerprint*, FPModify> FPModifyMap;
+
+int OptInit(WPARAM wParam, LPARAM lParam);
+
+void LoadOptions();
+void SaveOptions(ContactPolicyMap *contact_policies);
+extern "C" INT_PTR OpenOptions(WPARAM wParam, LPARAM lParam);
+void InitOptions();
+void DeinitOptions();
+
+void ReadPrivkeyFiles();
+
+static INT_PTR CALLBACK DlgProcMirOTROpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static INT_PTR CALLBACK DlgProcMirOTROptsProto(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static INT_PTR CALLBACK DlgProcMirOTROptsContacts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static INT_PTR CALLBACK DlgProcMirOTROptsFinger(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+#endif
diff --git a/MirOTR/otr.cpp b/MirOTR/otr.cpp
new file mode 100644
index 0000000..9779800
--- /dev/null
+++ b/MirOTR/otr.cpp
@@ -0,0 +1,383 @@
+#include <stdafx.h>
+#include "otr.h"
+#include <process.h>
+
+OtrlUserState otr_user_state;
+#define WMU_ENDDIALOG (WM_USER+244)
+
+OtrlMessageAppOps ops = {
+ otr_gui_policy,
+ otr_gui_create_privkey,
+ otr_gui_is_logged_in,
+ otr_gui_inject_message,
+ otr_gui_notify,
+ otr_gui_display_otr_message,
+ otr_gui_update_context_list,
+ otr_gui_protocol_name,
+ otr_gui_protocol_name_free,
+ otr_gui_new_fingerprint,
+ otr_gui_write_fingerprints,
+ otr_gui_gone_secure,
+ otr_gui_gone_insecure,
+ otr_gui_still_secure,
+ otr_gui_log_message,
+ max_message_size,
+ account_name,
+ account_name_free
+};
+
+struct GenKeyData{
+ HWND dialog;
+ char *proto;
+};
+
+static unsigned int CALLBACK generate_key_thread(void* param) {
+ CallService(MS_SYSTEM_THREAD_PUSH, 0, 0);
+ GenKeyData *data = (GenKeyData *)param;
+ lib_cs_lock();
+ otrl_privkey_generate(otr_user_state, g_private_key_filename, data->proto, data->proto);
+ lib_cs_unlock();
+ PostMessage(data->dialog, WMU_ENDDIALOG, 0, 0);
+ CallService(MS_SYSTEM_THREAD_POP, 0, 0);
+ return 0;
+}
+
+INT_PTR CALLBACK GenKeyDlgFunc(HWND hWndDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
+ switch(msg) {
+ case WM_INITDIALOG:
+ {
+ if (!lParam) {
+ EndDialog(hWndDlg, 0);
+ return 0;
+ }
+ TranslateDialogDefault(hWndDlg);
+ SetClassLongPtr(hWndDlg, GCL_HICON, (LONG_PTR)LoadIcon(ICON_OTR,1) );
+ TCHAR buff[256];
+ TCHAR *proto = mir_a2t((char*)lParam);
+ mir_sntprintf(buff, 256, TranslateT(LANG_GENERATE_KEY), proto);
+ mir_free(proto);
+ SetDlgItemText(hWndDlg, IDC_GENERATE, buff);
+ GenKeyData *data = new GenKeyData();
+ data->dialog = hWndDlg;
+ data->proto = (char*)lParam;
+ CloseHandle((HANDLE)_beginthreadex(0, 0, generate_key_thread, (void*)data, 0, 0));
+ }break;
+ case WMU_ENDDIALOG:
+ EndDialog(hWndDlg, 0);
+ return TRUE;
+ case WM_DESTROY:
+ SetClassLongPtr(hWndDlg, GCL_HICON, 0);
+ ReleaseIcon(ICON_OTR,1);
+ }
+ return FALSE;
+}
+
+extern "C" {
+ /* Return the OTR policy for the given context. */
+ OtrlPolicy otr_gui_policy(void *opdata, ConnContext *context) {
+ DEBUGOUT_T("OTR_GUI_POLICY")
+ HANDLE hContact = (HANDLE)opdata;
+ DWORD pol;
+ if(hContact) {
+ pol = DBGetContactSettingDword(hContact, MODULENAME, "Policy", CONTACT_DEFAULT_POLICY);
+ if(pol != CONTACT_DEFAULT_POLICY) return pol ;
+ }
+ if(context->protocol) {
+ pol = db_dword_get(0,MODULENAME"_ProtoPol", context->protocol, CONTACT_DEFAULT_POLICY);
+ if(pol != CONTACT_DEFAULT_POLICY) return pol ;
+ }
+
+ return options.default_policy ;
+ }
+
+ /* Create a private key for the given accountname/protocol if
+ * desired. */
+ void otr_gui_create_privkey(void *opdata, const char *account_name, const char *protocol) {
+ DEBUGOUT_T("OTR_GUI_CREATE_PRIVKEY")
+ //if(MessageBox(0, Translate("Would you like to generate a new private key for this protocol?"), Translate("OTR"), MB_YESNO) == IDYES)
+ //if(options.err_method == ED_POP)
+ //ShowPopup(Translate("Generating new private key."), 0 /*Translate("Please wait.")*/, 5);
+
+ //NewKeyData *nkd = (NewKeyData *)malloc(sizeof(NewKeyData));
+ //nkd->account_name = strdup(account_name);
+ //nkd->protocol = strdup(protocol);
+
+ //DWORD tid;
+ //CloseHandle(CreateThread(0, 0, newKeyThread, (VOID *)nkd, 0, &tid));
+ //QueueUserAPC(newKeyAPC, Global::mainThread, (DWORD)nkd);
+ DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_GENKEYNOTIFY), GetDesktopWindow(), GenKeyDlgFunc, (LPARAM)protocol );
+
+ }
+
+ /* Report whether you think the given user is online. Return 1 if
+ * you think he is, 0 if you think he isn't, -1 if you're not sure.
+ *
+ * If you return 1, messages such as heartbeats or other
+ * notifications may be sent to the user, which could result in "not
+ * logged in" errors if you're wrong. */
+ int otr_gui_is_logged_in(void *opdata, const char *accountname, const char *protocol, const char *recipient) {
+ DEBUGOUT_T("OTR_GUI_IS_LOGGED_IN")
+ HANDLE hContact = (HANDLE)opdata;
+ if(hContact) {
+ WORD status = DBGetContactSettingWord(hContact, contact_get_proto(hContact), "Status", ID_STATUS_OFFLINE);
+ if(status == ID_STATUS_OFFLINE) return 0;
+ else return 1;
+ }
+
+ return -1;
+ }
+
+ /* Send the given IM to the given recipient from the given
+ * accountname/protocol. */
+ void otr_gui_inject_message(void *opdata, const char *accountname, const char *protocol, const char *recipient, const char *message) {
+ DEBUGOUT_T("OTR_GUI_INJECT_MESSAGE")
+ //MessageBox(0, message, "OTR Inject", MB_OK);
+ HANDLE hContact = (HANDLE)opdata;
+
+ if(protocol && DBGetContactSettingWord(hContact, protocol, "Status", ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE) {
+ /* this would be with translation
+ TCHAR *decode = mir_utf8decodeT(message);
+ TCHAR *encode = mir_utf8encodeT(TranslateT(decide));
+ mir_free(decode);
+ CallContactService(hContact, PSS_MESSAGE, PREF_UTF|PREF_BYPASS_OTR, (LPARAM)encode);
+ mir_free(encode);
+ */
+ CallContactService(hContact, PSS_MESSAGE, PREF_UTF|PREF_BYPASS_OTR, (LPARAM)message);
+ //DEBUGOUT_T("INJECT")
+ }
+ }
+
+ /* Display a notification message for a particular accountname /
+ * protocol / username conversation. */
+ void otr_gui_notify(void *opdata, OtrlNotifyLevel level, const char *accountname, const char *protocol, const char *username, const char *title, const char *primary, const char *secondary) {
+ DEBUGOUT_T("OTR_GUI_NOTIFY")
+ const TCHAR* uname = contact_get_nameT((HANDLE)opdata);
+ TCHAR* title_t = mir_utf8decodeT(title);
+ TCHAR *notify = TranslateT(LANG_OTR_NOTIFY);
+
+ int len = _tcslen(uname) + _tcslen(title_t) + _tcslen(notify);
+ TCHAR *buff1 = new TCHAR[len];
+ mir_sntprintf(buff1, len, notify, TranslateTS(title_t), uname);
+ mir_free(title_t);
+
+ len = strlen(primary) + strlen(secondary) + 5;
+ char *buff2 = new char[len];
+ mir_snprintf(buff2, len, "%s\n%s", Translate(primary), Translate(secondary));
+ TCHAR* buff2_t = mir_utf8decodeT(buff2);
+ delete buff2;
+
+ DEBUGOUT_T("OTR_GUI_NOTIFY")
+
+ ShowPopup(buff1, buff2_t, 0);
+ mir_free(buff2_t);
+ delete buff1;
+ }
+
+ /* Display an OTR control message for a particular accountname /
+ * protocol / username conversation. Return 0 if you are able to
+ * successfully display it. If you return non-0 (or if this
+ * function is NULL), the control message will be displayed inline,
+ * as a received message, or else by using the above notify()
+ * callback. */
+ int otr_gui_display_otr_message(void *opdata, const char *accountname, const char *protocol, const char *username, const char *msg) {
+ DEBUGOUT_T("OTR_GUI_DISPLAY_OTR_MESSAGE")
+ if(options.msg_inline)
+ ShowMessageInlineUtf((HANDLE)opdata, Translate(msg));
+ if(options.msg_popup) {
+ TCHAR buff[512];
+ TCHAR* proto = mir_a2t(protocol);
+ mir_sntprintf(buff, 512, TranslateT(LANG_OTR_USERMESSAGE), contact_get_nameT((HANDLE)opdata), proto);
+ mir_free(proto);
+ TCHAR *msg_t = mir_utf8decodeT(msg);
+ ShowPopup(buff, TranslateTS(msg_t), 0);
+ mir_free(msg_t);
+ }
+ return 0;
+ }
+
+ /* When the list of ConnContexts changes (including a change in
+ * state), this is called so the UI can be updated. */
+ void otr_gui_update_context_list(void *opdata) {
+ //MessageBox(0, "Update Context List", "OTR Callback", MB_OK);
+ DEBUGOUT_T("OTR: Update Context List");
+ }
+
+ /* Return a newly-allocated string containing a human-friendly name
+ * for the given protocol id */
+ const char *otr_gui_protocol_name(void *opdata, const char *protocol) {
+ //return strdup(protocol);
+ DEBUGOUT_T("OTR_GUI_PROTOCOL_NAME")
+ return protocol;
+ }
+
+ /* Deallocate a string allocated by protocol_name */
+ void otr_gui_protocol_name_free(void *opdata, const char *protocol_name) {
+ //free((void *)protocol_name);
+ }
+
+ /* A new fingerprint for the given user has been received. */
+ void otr_gui_new_fingerprint(void *opdata, OtrlUserState us, const char *accountname, const char *protocol, const char *username, unsigned char fingerprint[20]) {
+ DEBUGOUT_T("OTR_GUI_NEW_FUNGERPRINT")
+ //MessageBox(0, username, Translate("OTR New Fingerprint"), MB_OK);
+ ConnContext *context = otrl_context_find(us, username, accountname, protocol, TRUE, 0, add_appdata, opdata);
+ Fingerprint *fp = otrl_context_find_fingerprint(context, fingerprint, TRUE, 0);
+
+ //CloseHandle((HANDLE)_beginthreadex(0, 0, trust_fp_thread, (void *)fp, 0, 0));
+
+ otrl_context_set_trust(fp, NULL);
+ otrl_privkey_write_fingerprints(otr_user_state, g_fingerprint_store_filename);
+ }
+
+ /* The list of known fingerprints has changed. Write them to disk. */
+ void otr_gui_write_fingerprints(void *opdata) {
+ DEBUGOUT_T("OTR_GUI_WRITE_FINGERPRINTS")
+ //if(MessageBox(0, Translate("Would you like to save the current fingerprint list?"), Translate(MODULE), MB_YESNO) == IDYES)
+ otrl_privkey_write_fingerprints(otr_user_state, g_fingerprint_store_filename);
+ }
+
+ /* A ConnContext has entered a secure state. */
+ void otr_gui_gone_secure(void *opdata, ConnContext *context) {
+ DEBUGOUT_T("OTR_GUI_GONE_SECURE")
+ TrustLevel trusted = otr_context_get_trust(context);
+ // opdata is hContact
+ SetEncryptionStatus((HANDLE)opdata, trusted);
+ TCHAR buff[1024];
+ if(trusted == TRUST_PRIVATE) {
+ mir_sntprintf(buff, 1024, TranslateT(LANG_SESSION_START_OTR), contact_get_nameT((HANDLE)opdata));
+ } else if (trusted == TRUST_UNVERIFIED) {
+ if (options.autoshow_verify) VerifyContextDialog(context);
+ mir_sntprintf(buff, 1024, TranslateT(LANG_SESSION_START_OTR_VERIFY), contact_get_nameT((HANDLE)opdata));
+ } else { // should never happen
+ mir_sntprintf(buff, 1024, TranslateT(LANG_SESSION_NOT_STARTED_OTR), contact_get_nameT((HANDLE)opdata));
+ }
+ // opdata is hContact
+ ShowMessage((HANDLE)opdata, buff);
+
+ }
+
+ /* A ConnContext has left a secure state. */
+ void otr_gui_gone_insecure(void *opdata, ConnContext *context) {
+ DEBUGOUT_T("OTR_GUI_GONE_INSECURE")
+ TCHAR buff[512];
+ mir_sntprintf(buff, 512, TranslateT(LANG_SESSION_TERMINATED_BY_OTR), contact_get_nameT((HANDLE)opdata));
+ //MessageBox(0, buff, Translate("OTR Information"), MB_OK);
+ ShowMessage((HANDLE)opdata, buff);
+
+ // opdata is hContact
+ SetEncryptionStatus((HANDLE)opdata, otr_context_get_trust(context));
+ }
+
+ /* We have completed an authentication, using the D-H keys we
+ * already knew. is_reply indicates whether we initiated the AKE. */
+ void otr_gui_still_secure(void *opdata, ConnContext *context, int is_reply) {
+ DEBUGOUT_T("OTR_GUI_STILL_SECURE")
+ TrustLevel trusted = otr_context_get_trust(context);
+ SetEncryptionStatus((HANDLE)opdata, trusted);
+ TCHAR buff[1024];
+ if(!is_reply) {
+ if(trusted == TRUST_PRIVATE) {
+ mir_sntprintf(buff, 1024, TranslateT(LANG_SESSION_CONTINUE_OTR), contact_get_nameT((HANDLE)opdata));
+ } else if (trusted == TRUST_UNVERIFIED) {
+ if (options.autoshow_verify) VerifyContextDialog(context);
+ mir_sntprintf(buff, 1024, TranslateT(LANG_SESSION_CONTINUE_OTR_VERIFY), contact_get_nameT((HANDLE)opdata));
+ } else { // should never happen
+ mir_sntprintf(buff, 1024, TranslateT(LANG_SESSION_NOT_STARTED_OTR), contact_get_nameT((HANDLE)opdata));
+ }
+ // opdata is hContact
+ ShowMessage((HANDLE)opdata, buff);
+ } else {
+ if(trusted == TRUST_PRIVATE) {
+ mir_sntprintf(buff, 1024, TranslateT(LANG_SESSION_HAS_CONTINUE_OTR), contact_get_nameT((HANDLE)opdata));
+ } else if (trusted == TRUST_UNVERIFIED) {
+ mir_sntprintf(buff, 1024, TranslateT(LANG_SESSION_HAS_CONTINUE_OTR_VERIFY), contact_get_nameT((HANDLE)opdata));
+ } else { // should never happen
+ mir_sntprintf(buff, 1024, TranslateT(LANG_SESSION_NOT_STARTED_OTR), contact_get_nameT((HANDLE)opdata));
+ }
+
+ }
+ SetEncryptionStatus((HANDLE)opdata, trusted);
+ }
+
+ /* Log a message. The passed message will end in "\n". */
+ void otr_gui_log_message(void *opdata, const char *message) {
+ //MessageBox(0, message, Translate("OTR Log Message"), MB_OK);
+ //ShowMessageInline((HANDLE)opdata, message);
+#ifdef _DEBUG
+ char* msg = strcpy((char*)mir_alloc(strlen(message)+15), "OTR message: ");
+ strcat(msg, message);
+ DEBUGOUTA(msg)
+ mir_free(msg);
+#endif
+ }
+
+ int max_message_size(void *opdata, ConnContext *context) {
+ int s = CallProtoService(context->protocol, PS_GETCAPS, PFLAG_MAXLENOFMESSAGE, 0);
+ return s;
+ }
+
+ const char *account_name(void *opdata, const char *account, const char *protocol) {
+ return account;
+ }
+
+ void account_name_free(void *opdata, const char *account_name) {
+ }
+
+ void add_appdata(void *data, ConnContext *context) {
+ if(context) context->app_data = data;
+ }
+}
+
+// Forward decl
+gcry_error_t otrl_privkey_write_FILEp(OtrlUserState us, FILE *privf);
+/* Generate a private DSA key for a given account, storing it into a
+ * file on disk, and loading it into the given OtrlUserState. Overwrite any
+ * previously generated keys for that account in that OtrlUserState. */
+gcry_error_t otrl_privkey_write(OtrlUserState us, const char *filename)
+{
+ gcry_error_t err;
+ FILE *privf;
+#ifndef WIN32
+ mode_t oldmask;
+#endif
+
+#ifndef WIN32
+ oldmask = umask(077);
+#endif
+ privf = fopen(filename, "w+b");
+ if (!privf) {
+#ifndef WIN32
+ umask(oldmask);
+#endif
+ err = gcry_error_from_errno(errno);
+ return err;
+ }
+
+ err = otrl_privkey_write_FILEp(us, privf);
+
+ fclose(privf);
+#ifndef WIN32
+ umask(oldmask);
+#endif
+ return err;
+}
+
+/* Just store the private keys of an OtrlUserState.
+ * The FILE* must be open for reading and writing. */
+gcry_error_t otrl_privkey_write_FILEp(OtrlUserState us, FILE *privf)
+{
+ OtrlPrivKey *p;
+
+ if (!privf) return gcry_error(GPG_ERR_NO_ERROR);
+
+
+
+ /* Output the other keys we know */
+ fprintf(privf, "(privkeys\n");
+ for (p=us->privkey_root; p; p=p->next) {
+ otrl_account_write(privf, p->accountname, p->protocol, p->privkey);
+ }
+ if ( fprintf(privf, ")\n") < 0 )
+ return gcry_error_from_errno(errno);
+ return gcry_error(GPG_ERR_NO_ERROR);
+
+} \ No newline at end of file
diff --git a/MirOTR/otr.h b/MirOTR/otr.h
new file mode 100644
index 0000000..933a9c8
--- /dev/null
+++ b/MirOTR/otr.h
@@ -0,0 +1,53 @@
+#pragma once
+
+#include "stdafx.h"
+
+extern OtrlUserState otr_user_state;
+extern OtrlMessageAppOps ops;
+
+extern "C" {
+
+ /* Return the OTR policy for the given context. */
+ OtrlPolicy otr_gui_policy(void *opdata, ConnContext *context);
+
+ /* Create a private key for the given accountname/protocol if
+ * desired. */
+ void otr_gui_create_privkey(void *opdata, const char *account_name, const char *protocol);
+
+ int otr_gui_is_logged_in(void *opdata, const char *accountname, const char *protocol, const char *recipient);
+
+ void otr_gui_inject_message(void *opdata, const char *accountname, const char *protocol, const char *recipient, const char *message);
+
+ void otr_gui_notify(void *opdata, OtrlNotifyLevel level, const char *accountname, const char *protocol, const char *username, const char *title, const char *primary, const char *secondary);
+
+ int otr_gui_display_otr_message(void *opdata, const char *accountname, const char *protocol, const char *username, const char *msg);
+
+ void otr_gui_update_context_list(void *opdata);
+
+ const char *otr_gui_protocol_name(void *opdata, const char *protocol);
+
+ void otr_gui_protocol_name_free(void *opdata, const char *protocol_name);
+
+ void otr_gui_new_fingerprint(void *opdata, OtrlUserState us, const char *accountname, const char *protocol, const char *username, unsigned char fingerprint[20]);
+
+ void otr_gui_write_fingerprints(void *opdata);
+
+ void otr_gui_gone_secure(void *opdata, ConnContext *context);
+
+ void otr_gui_gone_insecure(void *opdata, ConnContext *context);
+
+ void otr_gui_still_secure(void *opdata, ConnContext *context, int is_reply);
+
+ void otr_gui_log_message(void *opdata, const char *message);
+
+ int max_message_size(void *opdata, ConnContext *context);
+
+ const char *account_name(void *opdata, const char *account, const char *protocol);
+
+ void account_name_free(void *opdata, const char *account_name);
+
+ void add_appdata(void *data, ConnContext *context);
+
+}
+
+gcry_error_t otrl_privkey_write(OtrlUserState us, const char *filename); \ No newline at end of file
diff --git a/MirOTR/resource.h b/MirOTR/resource.h
new file mode 100644
index 0000000..c810a6d
--- /dev/null
+++ b/MirOTR/resource.h
@@ -0,0 +1,103 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by resource.rc
+//
+#ifndef IDOK
+ #define IDOK 1
+#endif
+#ifndef IDCANCEL
+ #define IDCANCEL 2
+#endif
+#define IDD_GENKEYNOTIFY 101
+#define IDD_OPT_GENERAL 102
+#define IDD_OPT_PROTO 103
+#define IDD_OPT_CONTACTS 104
+#define IDD_OPT_FINGER 105
+#define IDD_SMP_INPUT 106
+#define IDD_SMP_PROGRESS 107
+
+// General Options
+#define IDC_GRP_POLICY 1051
+#define IDC_RAD_ALWAYS 1052
+#define IDC_RAD_OPP 1053
+#define IDC_RAD_MANUAL 1054
+#define IDC_RAD_NEVER 1055
+
+#define IDC_CHK_PREFIX 1056
+#define IDC_ED_PREFIX 1057
+#define IDC_CHK_MSGINLINE 1058
+#define IDC_CHK_MSGPOPUP 1059
+#define IDC_CHK_PREVENTSAVE 1060
+#define IDC_CHK_AUTOSHOW_VERIFY 1061
+#define IDC_CHK_TIMEFINISH 1062
+#define IDC_CHK_ENDOFFLINE 1063
+#define IDC_CHK_ENDCLOSE 1064
+
+// Proto policy & keys
+#define IDC_LV_PROTO_PROTOS 1101
+#define IDC_BTN_PROTO_NEWKEY 1102
+#define IDC_CMB_PROTO_POLICY 1103
+#define IDC_BTN_PROTO_FORGET 1104
+#define IDC_STC_PROTO1 1151
+#define IDC_STC_PROTO2 1152
+
+// User policy
+#define IDC_LV_CONT_CONTACTS 1201
+#define IDC_CMB_CONT_POLICY 1202
+#define IDC_STC_CONT1 1251
+#define IDC_STC_CONT2 1252
+
+// User fingerprints
+#define IDC_LV_FINGER_LIST 1301
+#define IDC_BTN_FINGER_FORGET 1302
+#define IDC_BTN_FINGER_TRUST 1303
+#define IDC_BTN_FINGER_DONTTRUST 1304
+#define IDC_STC_FINGER1 1351
+
+// Generate dialog
+#define IDC_GENERATE 1401
+#define IDC_ICOOTR 1402
+#define IDC_ICOREFRESH 1403
+
+// SMP Progress
+#define IDC_PGB_SMP 1501
+#define IDC_STC_SMP_HEADPRO 1502
+#define IDC_ICO_SMP 1503
+#define IDC_STC_SMP_PROGRESS 1504
+
+// SMP Dialog
+#define IDC_STC_SMP_HEAD 1602
+#define IDC_CBO_SMP_CHOOSE 1603
+#define IDC_STC_SMP_INFO 1604
+#define IDC_STC_SMP_FIELD1 1605
+#define IDC_EDT_SMP_FIELD1 1606
+#define IDC_STC_SMP_FIELD2 1607
+#define IDC_EDT_SMP_FIELD2 1608
+
+#define IDI_OTR 2000
+#define IDI_REFRESH 2001
+#define IDI_INSECURE 2002
+#define IDI_UNVERIFIED 2003
+#define IDI_PRIVATE 2004
+#define IDI_FINISHED 2005
+
+#define IDC_STATIC -1
+
+#define IDM_OTR_MENU 10001
+#define IDR_CONTEXT 10000
+#define IDM_OTR_STATUS 10001
+#define IDM_OTR_START 10002
+#define IDM_OTR_REFRESH 10003
+#define IDM_OTR_STOP 10004
+#define IDM_OTR_VERIFY 10005
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/MirOTR/resources/finished.ico b/MirOTR/resources/finished.ico
new file mode 100644
index 0000000..870cd0a
--- /dev/null
+++ b/MirOTR/resources/finished.ico
Binary files differ
diff --git a/MirOTR/resources/insecure.ico b/MirOTR/resources/insecure.ico
new file mode 100644
index 0000000..4a72fe3
--- /dev/null
+++ b/MirOTR/resources/insecure.ico
Binary files differ
diff --git a/MirOTR/resources/otr.ico b/MirOTR/resources/otr.ico
new file mode 100644
index 0000000..298a3ba
--- /dev/null
+++ b/MirOTR/resources/otr.ico
Binary files differ
diff --git a/MirOTR/resources/private.ico b/MirOTR/resources/private.ico
new file mode 100644
index 0000000..b7c8585
--- /dev/null
+++ b/MirOTR/resources/private.ico
Binary files differ
diff --git a/MirOTR/resources/refresh.ico b/MirOTR/resources/refresh.ico
new file mode 100644
index 0000000..45fbbf2
--- /dev/null
+++ b/MirOTR/resources/refresh.ico
Binary files differ
diff --git a/MirOTR/resources/resource.rc b/MirOTR/resources/resource.rc
new file mode 100644
index 0000000..35564ac
--- /dev/null
+++ b/MirOTR/resources/resource.rc
@@ -0,0 +1,133 @@
+#ifndef IDCANCEL
+ #define IDCANCEL 2
+#endif
+#ifndef IDOK
+ #define IDOK 1
+#endif
+
+#include "windows.h"
+#include "../resource.h"
+#include "version.rc"
+
+LANGUAGE 9,0
+
+IDI_OTR ICON DISCARDABLE "otr.ico"
+IDI_REFRESH ICON DISCARDABLE "refresh.ico"
+IDI_INSECURE ICON DISCARDABLE "insecure.ico"
+IDI_UNVERIFIED ICON DISCARDABLE "unverified.ico"
+IDI_PRIVATE ICON DISCARDABLE "private.ico"
+IDI_FINISHED ICON DISCARDABLE "finished.ico"
+
+IDD_GENKEYNOTIFY DIALOGEX 0,0,270,33
+CAPTION "OTR Generating Private Key"
+FONT 8,"MS Shell Dlg",0,0,0
+STYLE WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|DS_CENTER|DS_SETFOREGROUND|DS_MODALFRAME|DS_SETFONT|0xC0000000
+BEGIN
+ CONTROL "Generating new private key - please wait.",IDC_GENERATE,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_CENTER,33,3,201,27
+ CONTROL IDI_OTR,IDC_ICOOTR,"Static",WS_CHILDWINDOW|WS_VISIBLE|SS_CENTERIMAGE|SS_ICON,0,0,32,32
+ CONTROL IDI_REFRESH,IDC_ICOREFRESH,"Static",WS_CHILDWINDOW|WS_VISIBLE|SS_CENTERIMAGE|SS_ICON,237,0,32,32
+END
+
+IDD_OPT_GENERAL DIALOGEX 0,0,296,220
+FONT 8,"MS Shell Dlg",0,0,1
+STYLE WS_CHILDWINDOW|WS_VISIBLE|DS_SHELLFONT
+EXSTYLE WS_EX_CONTROLPARENT
+BEGIN
+ CONTROL "",IDC_STATIC,"Static",WS_VISIBLE|WS_TABSTOP,0,0,1,1
+ CONTROL "Default Policy",IDC_GRP_POLICY,"Button",WS_CHILDWINDOW|WS_VISIBLE|BS_GROUPBOX,5,3,139,60
+ CONTROL "Always",IDC_RAD_ALWAYS,"Button",WS_VISIBLE|WS_TABSTOP|BS_AUTORADIOBUTTON,12,12,126,10
+ CONTROL "Opportunistic",IDC_RAD_OPP,"Button",WS_VISIBLE|WS_TABSTOP|BS_AUTORADIOBUTTON,12,24,126,10
+ CONTROL "Manual",IDC_RAD_MANUAL,"Button",WS_VISIBLE|WS_GROUP|WS_TABSTOP|BS_AUTORADIOBUTTON,12,36,126,10
+ CONTROL "Never",IDC_RAD_NEVER,"Button",WS_VISIBLE|WS_TABSTOP|BS_AUTORADIOBUTTON,12,48,126,10
+ CONTROL "End sessions on window close",IDC_CHK_ENDCLOSE,"Button",WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX,12,70,265,10
+ CONTROL "End sessions when contacts go offline",IDC_CHK_ENDOFFLINE,"Button",WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX,12,82,265,10
+ CONTROL "Prefix encrypted IMs:",IDC_CHK_PREFIX,"Button",WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX,12,94,108,10
+ CONTROL "",IDC_ED_PREFIX,"Edit",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|ES_AUTOHSCROLL,120,93,159,12,WS_EX_CLIENTEDGE
+ CONTROL "Don't add encrypted messages to the history",IDC_CHK_PREVENTSAVE,"Button",WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX,12,106,265,10
+ CONTROL "Show OTR system messages inline",IDC_CHK_MSGINLINE,"Button",WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX,12,118,265,10
+ CONTROL "Show OTR system messages as popup",IDC_CHK_MSGPOPUP,"Button",WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX,12,130,265,10
+ CONTROL "Timeout FINISHED sessions back to PLAINTEXT (TAKE CARE!)",IDC_CHK_TIMEFINISH,"Button",WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX,12,142,265,10
+ CONTROL "Show verification dialog when receiving unverified fingerprint",IDC_CHK_AUTOSHOW_VERIFY,"Button",WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX,12,154,265,10
+END
+
+IDD_OPT_PROTO DIALOGEX 0,0,296,220
+FONT 8,"MS Shell Dlg",0,0,1
+STYLE WS_CHILDWINDOW|WS_VISIBLE|DS_SHELLFONT
+EXSTYLE WS_EX_CONTROLPARENT
+BEGIN
+ CONTROL "Set OTR policy per protocol",IDC_STC_PROTO1,"Static",WS_CHILDWINDOW|WS_VISIBLE|SS_NOPREFIX,3,3,291,12
+ CONTROL "",IDC_LV_PROTO_PROTOS,"SysListView32",WS_VISIBLE|WS_BORDER|WS_TABSTOP|LVS_SORTASCENDING|LVS_SHOWSELALWAYS|LVS_SINGLESEL|LVS_REPORT,0,18,296,165
+ CONTROL "Current policy:",IDC_STC_PROTO2,"Static",WS_CHILDWINDOW|WS_VISIBLE|SS_NOPREFIX,3,189,138,9
+ CONTROL "",IDC_CMB_PROTO_POLICY,"ComboBox",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|CBS_HASSTRINGS|CBS_DROPDOWNLIST,3,201,138,12
+ CONTROL "Generate new private key",IDC_BTN_PROTO_NEWKEY,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,162,186,123,18
+ CONTROL "Forget private key",IDC_BTN_PROTO_FORGET,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,162,207,123,12
+END
+
+IDD_OPT_CONTACTS DIALOGEX 0,0,296,220
+FONT 8,"MS Shell Dlg",0,0,1
+STYLE WS_CHILDWINDOW|WS_VISIBLE|DS_SHELLFONT
+EXSTYLE WS_EX_CONTROLPARENT
+BEGIN
+ CONTROL "Set OTR policy per contact",IDC_STC_CONT1,"Static",WS_CHILDWINDOW|WS_VISIBLE|SS_NOPREFIX,3,3,291,12
+ CONTROL "",IDC_LV_CONT_CONTACTS,"SysListView32",WS_VISIBLE|WS_BORDER|WS_TABSTOP|LVS_SORTASCENDING|LVS_SHOWSELALWAYS|LVS_SINGLESEL|LVS_REPORT,0,18,296,180
+ CONTROL "Current policy:",IDC_STC_CONT2,"Static",WS_CHILDWINDOW|WS_VISIBLE|SS_NOPREFIX,3,204,129,9
+ CONTROL "",IDC_CMB_CONT_POLICY,"ComboBox",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|CBS_HASSTRINGS|CBS_DROPDOWNLIST,138,201,153,12
+END
+
+IDD_OPT_FINGER DIALOGEX 0,0,296,220
+FONT 8,"MS Shell Dlg",0,0,1
+STYLE WS_CHILDWINDOW|WS_VISIBLE|DS_SHELLFONT
+EXSTYLE WS_EX_CONTROLPARENT
+BEGIN
+ CONTROL "View & Modify status of known fingerprints",IDC_STC_FINGER1,"Static",WS_CHILDWINDOW|WS_VISIBLE|SS_NOPREFIX,3,3,291,12
+ CONTROL "",IDC_LV_FINGER_LIST,"SysListView32",WS_VISIBLE|WS_BORDER|WS_TABSTOP|LVS_SORTASCENDING|LVS_SHOWSELALWAYS|LVS_SINGLESEL|LVS_REPORT,0,18,296,171
+ CONTROL "Set verified",IDC_BTN_FINGER_TRUST,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,3,195,66,18
+ CONTROL "Set unknown",IDC_BTN_FINGER_DONTTRUST,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,72,195,66,18
+ CONTROL "Forget",IDC_BTN_FINGER_FORGET,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,225,195,66,18
+END
+
+IDR_CONTEXT MENU
+BEGIN
+ POPUP "MirOTR"
+ BEGIN
+ MENUITEM "OTR status",IDM_OTR_STATUS,GRAYED
+ MENUITEM SEPARATOR
+ MENUITEM "&Start OTR session",IDM_OTR_START
+ MENUITEM "&Refresh OTR session",IDM_OTR_REFRESH
+ MENUITEM "Sto&p OTR session",IDM_OTR_STOP
+ MENUITEM SEPARATOR
+ MENUITEM "&Verify Fingerprint",IDM_OTR_VERIFY
+ END
+END
+
+IDD_SMP_PROGRESS DIALOGEX 10,10,200,100
+CAPTION "Socialist Millionaires Protocol"
+FONT 8,"MS Sans Serif",0,0,0
+STYLE WS_POPUP|WS_VISIBLE|WS_CAPTION|DS_CENTER|DS_SETFOREGROUND|DS_MODALFRAME
+BEGIN
+ CONTROL IDI_OTR,IDC_ICO_SMP,"Static",WS_CHILDWINDOW|WS_VISIBLE|SS_CENTERIMAGE|SS_ICON,3,3,32,32
+ CONTROL "Socialist Millionaires Protocol\r\nVerification progress",IDC_STC_SMP_HEADPRO,"Static",WS_CHILDWINDOW|WS_VISIBLE|SS_NOPREFIX,39,9,156,21
+ CONTROL "",IDC_PGB_SMP,"msctls_progress32",WS_CHILDWINDOW|WS_VISIBLE|PBS_SMOOTH,3,36,194,18
+ CONTROL "",IDC_STC_SMP_PROGRESS,"Static",WS_CHILDWINDOW|WS_VISIBLE,3,57,194,20
+ CONTROL "&Cancel",IDCANCEL,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,70,80,60,16
+END
+
+IDD_SMP_INPUT DIALOGEX 10,10,200,200
+CAPTION "Socialist Millionaires Protocol"
+FONT 8,"MS Sans Serif",0,0,0
+STYLE WS_VISIBLE|WS_CAPTION|WS_SYSMENU|DS_SETFOREGROUND|DS_MODALFRAME
+BEGIN
+ CONTROL IDI_OTR,IDC_ICO_SMP,"Static",WS_CHILDWINDOW|WS_VISIBLE|SS_CENTERIMAGE|SS_ICON,3,3,32,32
+ CONTROL "Socialist Millionaires Protocol\r\nVerification",IDC_STC_SMP_HEAD,"Static",WS_CHILDWINDOW|WS_VISIBLE|SS_NOPREFIX,39,9,156,21
+ CONTROL "",IDC_CBO_SMP_CHOOSE,"ComboBox",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|CBS_HASSTRINGS|CBS_DROPDOWNLIST,3,36,194,60
+ CONTROL "",IDC_STC_SMP_INFO,"Static",WS_CHILDWINDOW|WS_VISIBLE,3,60,195,35
+ CONTROL "",IDC_STC_SMP_FIELD1,"Static",WS_CHILDWINDOW|WS_VISIBLE,3,105,194,10
+ CONTROL "",IDC_EDT_SMP_FIELD1,"Edit",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,3,117,194,13,WS_EX_CLIENTEDGE
+ CONTROL "",IDC_STC_SMP_FIELD2,"Static",WS_CHILDWINDOW|WS_VISIBLE,3,141,194,10
+ CONTROL "",IDC_EDT_SMP_FIELD2,"Edit",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,3,153,194,13,WS_EX_CLIENTEDGE
+ CONTROL "&Cancel",IDCANCEL,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,3,180,60,16
+ CONTROL "&OK",IDOK,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,135,180,60,16
+ CONTROL "&No",IDNO,"Button",NOT WS_VISIBLE|WS_CHILDWINDOW|WS_TABSTOP,70,180,60,16
+ CONTROL "&Yes",IDYES,"Button",NOT WS_VISIBLE|WS_CHILDWINDOW|WS_TABSTOP,135,180,60,16
+END
+
diff --git a/MirOTR/resources/unverified.ico b/MirOTR/resources/unverified.ico
new file mode 100644
index 0000000..95cc662
--- /dev/null
+++ b/MirOTR/resources/unverified.ico
Binary files differ
diff --git a/MirOTR/resources/version.rc b/MirOTR/resources/version.rc
new file mode 100644
index 0000000..b7007af
--- /dev/null
+++ b/MirOTR/resources/version.rc
@@ -0,0 +1,35 @@
+/* THIS FILE WILL BE OVERWRITTEN BY DEV-C++ */
+/* DO NOT EDIT! */
+
+#include "version.h"
+#include "windows.h"
+
+//
+// TO CHANGE VERSION INFORMATION, EDIT PROJECT OPTIONS...
+//
+1 VERSIONINFO
+FILEVERSION VER_MAJOR,VER_MINOR,VER_RELEASE,VER_BUILD
+PRODUCTVERSION VER_MAJOR,VER_MINOR,VER_RELEASE,VER_BUILD
+FILETYPE VFT_DLL
+{
+ BLOCK "StringFileInfo"
+ {
+ BLOCK "0C0904E4"
+ {
+ VALUE "CompanyName", COMPANY_NAME
+ VALUE "FileVersion", FILE_VERSION
+ VALUE "FileDescription", FILE_DESCRIPTION
+ VALUE "InternalName", INTERNAL_NAME
+ VALUE "LegalCopyright", LEGAL_COPYRIGHT
+ VALUE "LegalTrademarks", LEGAL_TRADEMARKS
+ VALUE "OriginalFilename", ORIGINAL_FILENAME
+ VALUE "ProductName", PRODUCT_NAME
+ VALUE "ProductVersion", PRODUCT_VERSION
+ }
+ }
+ BLOCK "VarFileInfo"
+ {
+ VALUE "Translation", 0x0C09, 1252
+ }
+}
+
diff --git a/MirOTR/stdafx.cpp b/MirOTR/stdafx.cpp
new file mode 100644
index 0000000..98540cb
--- /dev/null
+++ b/MirOTR/stdafx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : Quelldatei, die nur die Standard-Includes einbindet.
+// MirOTR.pch ist der vorkompilierte Header.
+// stdafx.obj enthält die vorkompilierten Typinformationen.
+
+#include "stdafx.h"
+
+// TODO: Auf zusätzliche Header verweisen, die in STDAFX.H
+// und nicht in dieser Datei erforderlich sind.
diff --git a/MirOTR/stdafx.h b/MirOTR/stdafx.h
new file mode 100644
index 0000000..ebb3f07
--- /dev/null
+++ b/MirOTR/stdafx.h
@@ -0,0 +1,89 @@
+// stdafx.h : Includedatei für Standardsystem-Includedateien
+// oder häufig verwendete projektspezifische Includedateien,
+// die nur in unregelmäßigen Abständen geändert werden.
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#define WIN32_LEAN_AND_MEAN // Selten verwendete Teile der Windows-Header nicht einbinden.
+// Windows-Headerdateien:
+#include <windows.h>
+#include <string.h>
+#include <assert.h>
+
+#ifdef _DEBUG
+ #define DEBUGOUTA(x) OutputDebugStringA(x);
+ #define DEBUGOUT(x) OutputDebugString(x);
+ #define DEBUGOUT_T(x) OutputDebugString(__T(x));
+#else
+ #define DEBUGOUTA(x);
+ #define DEBUGOUT(x)
+ #define DEBUGOUT_T(x)
+#endif
+#define MIRANDA_VER 0x0800
+
+#include <newpluginapi.h>
+#include <m_system.h>
+#include <m_langpack.h>
+#include <m_utils.h>
+#include <m_database.h>
+#include <m_folders.h>
+#include <m_clist.h>
+#include <m_message.h>
+#include <m_metacontacts.h>
+#include <m_protocols.h>
+#include <m_protomod.h>
+#include <m_protosvc.h>
+#include <m_updater.h>
+#include <m_popup.h>
+#include <m_contacts.h>
+#include <m_utils.h>
+#include <m_icolib.h>
+
+#include <gcrypt.h>
+extern "C" {
+ #include <privkey.h>
+ #include <proto.h>
+ #include <tlv.h>
+ #include <message.h>
+ #include <userstate.h>
+}
+
+#include "dllmain.h"
+#include "language.h"
+#include "options.h"
+#include "utils.h"
+#include "svcs_menu.h"
+#include "svcs_proto.h"
+#include "svcs_srmm.h"
+#include "resource.h"
+#include "otr.h"
+#include "icons.h"
+#include "dialogs.h"
+
+// modified manual policy - so that users set to 'opportunistic' will automatically start OTR with users set to 'manual'
+#define OTRL_POLICY_MANUAL_MOD (OTRL_POLICY_MANUAL | OTRL_POLICY_WHITESPACE_START_AKE | OTRL_POLICY_ERROR_START_AKE)
+
+// {030F37D6-DD32-434d-BC64-5B6541EB9299}
+static const MUUID MIID_OTR = { 0x30f37d6, 0xdd32, 0x434d, { 0xbc, 0x64, 0x5b, 0x65, 0x41, 0xeb, 0x92, 0x99 } };
+#ifdef _UNICODE
+ // {12D8FAAD-78AB-4e3c-9854-320E9EA5CC9F}
+ static const MUUID MIID_OTRPLUGIN = { 0x12d8faad, 0x78ab, 0x4e3c, { 0x98, 0x54, 0x32, 0xe, 0x9e, 0xa5, 0xcc, 0x9f } };
+#else
+ // {16E2E7B0-D398-4ea8-A5CC-A0F3689C7608}
+ static const MUUID MIID_OTRPLUGIN = { 0x16e2e7b0, 0xd398, 0x4ea8, { 0xa5, 0xcc, 0xa0, 0xf3, 0x68, 0x9c, 0x76, 0x8 } };
+#endif
+
+#define MODULENAME "MirOTR"
+
+#define MS_OTR_MENUSTART MODULENAME"/Start"
+#define MS_OTR_MENUSTOP MODULENAME"/Stop"
+
+#define PREF_BYPASS_OTR 0x8000
+#define PREF_NO_HISTORY 0x10000
+
+#define SIZEOF(X) (sizeof(X)/sizeof(X[0]))
+
+// TODO: Hier auf zusätzliche Header, die das Programm erfordert, verweisen.
diff --git a/MirOTR/svcs_menu.cpp b/MirOTR/svcs_menu.cpp
new file mode 100644
index 0000000..5a2944c
--- /dev/null
+++ b/MirOTR/svcs_menu.cpp
@@ -0,0 +1,169 @@
+#include "stdafx.h"
+#include "otr.h"
+
+HANDLE hMenuBuildEvent, hStopItem, hStartItem;
+
+////////////////////////////////
+///////// Menu Services
+///////////////////////
+int StartOTR(HANDLE hContact) {
+
+ const char *proto = contact_get_proto(hContact);
+ if(!proto) return 1; // error
+ char *uname = contact_get_id(hContact);
+ if(!uname) return 1; // error
+ WORD pol = DBGetContactSettingWord(hContact, MODULENAME, "Policy", CONTACT_DEFAULT_POLICY);
+ if(pol == CONTACT_DEFAULT_POLICY) pol = options.default_policy;
+
+ lib_cs_lock();
+ char *msg = otrl_proto_default_query_msg(MODULENAME, pol);
+ otr_gui_inject_message(hContact, proto, proto, uname, msg ? msg : "?OTRv2?");
+ lib_cs_unlock();
+ otrl_message_free(msg);
+ mir_free(uname);
+ return 0;
+}
+int SVC_StartOTR(WPARAM wParam, LPARAM lParam) {
+ HANDLE hContact = (HANDLE)wParam, hSub;
+ if(options.bHaveMetaContacts && (hSub = (HANDLE)CallService(MS_MC_GETMOSTONLINECONTACT, (WPARAM)hContact, 0)) != 0) {
+ hContact = hSub;
+ }
+
+ TCHAR buff[512];
+ mir_sntprintf(buff, 512, TranslateT(LANG_SESSION_REQUEST_OTR), contact_get_nameT(hContact));
+ ShowMessage(hContact, buff);
+
+ int res = StartOTR(hContact);
+ if (res) return res;
+
+ return 0;
+}
+int SVC_RefreshOTR(WPARAM wParam, LPARAM lParam) {
+ HANDLE hContact = (HANDLE)wParam, hSub;
+ if(options.bHaveMetaContacts && (hSub = (HANDLE)CallService(MS_MC_GETMOSTONLINECONTACT, (WPARAM)hContact, 0)) != 0) {
+ hContact = hSub;
+ }
+
+ TCHAR buff[512];
+ mir_sntprintf(buff, 512, TranslateT(LANG_SESSION_TRY_CONTINUE_OTR), contact_get_nameT(hContact));
+ ShowMessage(hContact, buff);
+
+ int res = StartOTR(hContact);
+ if (res) return res;
+
+ return 0;
+}
+int otr_disconnect_contact(HANDLE hContact) {
+ HANDLE hSub;
+ if(ServiceExists(MS_MC_GETMOSTONLINECONTACT) && (hSub = (HANDLE)CallService(MS_MC_GETMOSTONLINECONTACT, (WPARAM)hContact, 0)) != 0) {
+ hContact = hSub;
+ }
+
+ const char *proto = contact_get_proto(hContact);
+ if(!proto) return 1; // error
+ char *uname = contact_get_id(hContact);
+ if(!uname) return 1; // error
+
+ lib_cs_lock();
+ otrl_message_disconnect(otr_user_state, &ops, hContact, proto, proto, uname);
+ lib_cs_unlock();
+ mir_free(uname);
+ return 0;
+}
+
+int SVC_StopOTR(WPARAM wParam, LPARAM lParam) {
+ HANDLE hContact = (HANDLE)wParam;
+
+ // prevent this filter from acting on injeceted messages for metas, when they are passed though the subcontact's proto send chain
+ if (otr_disconnect_contact(hContact)) return 0;
+
+ SetEncryptionStatus(hContact, TRUST_NOT_PRIVATE);
+
+ TCHAR buff[512];
+ mir_sntprintf(buff, 512, TranslateT(LANG_SESSION_TERMINATED_OTR), contact_get_nameT(hContact));
+ ShowMessage(hContact, buff);
+
+ return 0;
+}
+
+void InitMenu() {
+ CLISTMENUITEM mi = {0};
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIF_NOTOFFLINE | CMIF_TCHAR | CMIF_ICONFROMICOLIB;
+ mi.position = -400000;
+
+ mi.ptszName = _T(LANG_STOP_OTR);
+ mi.pszService = MS_OTR_MENUSTOP;
+ mi.icolibItem = GetIconHandle(ICON_PRIVATE);
+
+ hStopItem = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
+
+ mi.ptszName = _T(LANG_START_OTR);
+ mi.pszService = MS_OTR_MENUSTART;
+ mi.icolibItem = GetIconHandle(ICON_NOT_PRIVATE);
+
+ hStartItem = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
+
+ hMenuBuildEvent = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, SVC_PrebuildContactMenu);
+
+}
+
+void DeinitMenu() {
+ UnhookEvent(hMenuBuildEvent);
+}
+
+int SVC_PrebuildContactMenu(WPARAM wParam, LPARAM lParam) {
+ HANDLE hContact = (HANDLE)wParam;
+
+ CLISTMENUITEM mi = {0};
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_FLAGS | CMIF_NOTOFFLINE | CMIF_TCHAR | CMIF_ICONFROMICOLIB;
+
+ const char *proto = contact_get_proto(hContact);
+ WORD pol = CONTACT_DEFAULT_POLICY;
+
+ if(!proto || DBGetContactSettingByte(hContact, proto, "ChatRoom", 0) == 1) {
+ goto hide_all;
+ }
+
+ if(proto && g_metaproto && strcmp(proto, g_metaproto) == 0) {
+ // make menu act as per most online subcontact
+ hContact = (HANDLE)CallService(MS_MC_GETMOSTONLINECONTACT, (WPARAM)hContact, 0);
+ if(!hContact)
+ goto hide_all;
+ proto = contact_get_proto(hContact);
+ }
+
+ pol = DBGetContactSettingWord(hContact, MODULENAME, "Policy", CONTACT_DEFAULT_POLICY);
+ if(pol == CONTACT_DEFAULT_POLICY) pol = options.default_policy;
+
+ if(pol == OTRL_POLICY_NEVER || pol == OTRL_POLICY_ALWAYS) {
+ goto hide_all;
+ }
+
+ {
+ ConnContext *context = otrl_context_find_miranda(otr_user_state, hContact);
+ TrustLevel encrypted = otr_context_get_trust(context);
+ if(encrypted != TRUST_NOT_PRIVATE) {
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hStopItem, (LPARAM)&mi);
+ mi.flags |= CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hStartItem, (LPARAM)&mi);
+ } else {
+ //if(pol == OTRL_POLICY_MANUAL_MOD) {
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hStartItem, (LPARAM)&mi);
+ mi.flags |= CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hStopItem, (LPARAM)&mi);
+ //} else { // should only be 'opportunistic'
+ // goto hide_all;
+ //}
+ }
+ }
+
+ return 0;
+
+hide_all:
+ mi.flags |= CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hStopItem, (LPARAM)&mi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hStartItem, (LPARAM)&mi);
+ return 0;
+} \ No newline at end of file
diff --git a/MirOTR/svcs_menu.h b/MirOTR/svcs_menu.h
new file mode 100644
index 0000000..43e6d03
--- /dev/null
+++ b/MirOTR/svcs_menu.h
@@ -0,0 +1,7 @@
+#pragma once
+int SVC_StartOTR(WPARAM wParam, LPARAM lParam);
+int SVC_RefreshOTR(WPARAM wParam, LPARAM lParam);
+int SVC_StopOTR(WPARAM wParam, LPARAM lParam);
+int SVC_PrebuildContactMenu(WPARAM wParam, LPARAM lParam);
+void InitMenu();
+void DeinitMenu(); \ No newline at end of file
diff --git a/MirOTR/svcs_proto.cpp b/MirOTR/svcs_proto.cpp
new file mode 100644
index 0000000..b46b33f
--- /dev/null
+++ b/MirOTR/svcs_proto.cpp
@@ -0,0 +1,370 @@
+#include "stdafx.h"
+#include "svcs_proto.h"
+
+//TODO: Social-Millionaire-Dialoge
+int SVC_OTRSendMessage(WPARAM wParam,LPARAM lParam){
+ if(!lParam) return 0;
+
+ CCSDATA *ccs = (CCSDATA *) lParam;
+
+ DEBUGOUT_T("SENDING")
+
+ if (ccs->wParam & PREF_BYPASS_OTR) // bypass for OTR-messages
+ return CallService(MS_PROTO_CHAINSEND, wParam, lParam);
+
+ char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)ccs->hContact, 0);
+ if(proto && g_metaproto && strcmp(proto, g_metaproto) == 0) // bypass for metacontacts
+ return CallService(MS_PROTO_CHAINSEND, wParam, lParam);
+ char *username = contact_get_id(ccs->hContact);
+ if(!proto || !username) return 1; // error
+
+ gcry_error_t err;
+ char *newmessage = 0;
+ char *oldmessage = (char *)ccs->lParam;
+ char *oldmessage_utf = 0;
+
+ //MessageBox(0, "Send message - converting to UTF-8", "msg", MB_OK);
+
+ if(ccs->wParam & PREF_UTF) {
+ oldmessage_utf = oldmessage;
+ } else if(ccs->wParam & PREF_UNICODE) {
+ //TODO: check if this is correct or oldmessage[strlen(oldmessage)+1] is needed
+ oldmessage_utf = mir_utf8encodeW((wchar_t*)oldmessage);
+ } else {
+ oldmessage_utf = mir_utf8encode(oldmessage);
+ }
+ if(!oldmessage_utf) return 1;
+
+ // don't filter OTR messages being sent (OTR messages should only happen *after* the otrl_message_sending call below)
+ if(strncmp(oldmessage_utf, "?OTR", 4) == 0) {
+ DEBUGOUT_T("OTR message without PREF_BYPASS_OTR")
+ if (!(ccs->wParam & PREF_UTF)) mir_free(oldmessage_utf);
+ return CallService(MS_PROTO_CHAINSEND, wParam, lParam);
+ }
+
+ err = otrl_message_sending(otr_user_state, &ops, (void*)ccs->hContact,
+ proto, proto, username, oldmessage_utf, NULL, &newmessage,
+ add_appdata, (void*)ccs->hContact);
+ if (!(ccs->wParam & PREF_UTF)) mir_free(oldmessage_utf);
+ oldmessage_utf = NULL;
+ mir_free(username);
+
+ if (err && newmessage == NULL) {
+ /* Be *sure* not to send out plaintext */
+ ShowError(TranslateT(LANG_ENCRYPTION_ERROR));
+ /* should not be needed
+ char t[3] = {0, 0, 0};
+ if(ccs->wParam & PREF_UNICODE) { //TODO!! lstrlen(pre->szMessage)+1 ??
+ if (strlen(oldmessage)) memcpy(oldmessage, t,3 );
+ } else {
+ if (strlen(oldmessage)) memcpy(oldmessage, t, 1);
+ }
+ */
+ return 1;
+ } else if (newmessage) {
+ /* Fragment the message if necessary, and send all but the last
+ * fragment over the network. We will send the last segment later */
+ ConnContext *context = otrl_context_find_miranda(otr_user_state,
+ (void*)ccs->hContact);
+
+ // oldmessage_utf is not used anymore, so use it as buffer
+ err = otrl_message_fragment_and_send(&ops, (void*)ccs->hContact, context,
+ newmessage, OTRL_FRAGMENT_SEND_ALL_BUT_LAST, &oldmessage_utf);
+ // newmessage is not needed anymore
+ otrl_message_free(newmessage);
+ // move the last fragment to newmessage, oldmessage_utf will be buffer later
+ newmessage = oldmessage_utf;
+
+ WPARAM oldflags = ccs->wParam;
+ if(ccs->wParam & PREF_UTF) {
+ ccs->lParam = (LPARAM)newmessage;
+ } else if(ccs->wParam & PREF_UNICODE) {
+ // just send UTF, hope that proto supports it.
+ // don't want to create the Unicode-Format
+ // oldmessage_utf = (char*)mir_utf8decodeW(newmessage);
+ ccs->lParam = (LPARAM)newmessage;
+ ccs->wParam &= ~PREF_UNICODE;
+ ccs->wParam |= PREF_UTF;
+ } else {
+ mir_utf8decode(newmessage, NULL);
+ ccs->lParam = (LPARAM)newmessage;
+ }
+ if (otr_context_get_trust(context) >= TRUST_UNVERIFIED) ccs->wParam;
+ int ret = CallService(MS_PROTO_CHAINSEND, wParam, lParam);
+
+/*#ifdef _DEBUG
+ if(ccs->wParam & PREF_UNICODE)
+ MessageBox(0, (wchar_t *)ccs->lParam, _T("OTR - sending raw message"), MB_OK);
+ else
+ MessageBoxA(0, (char *)ccs->lParam, ("OTR - sending raw message"), MB_OK);
+#endif*/
+
+ // reset to original values
+ ccs->lParam = (LPARAM)oldmessage;
+ ccs->wParam = oldflags;
+ otrl_message_free(newmessage);
+ return ret;
+
+ }
+
+ return CallService(MS_PROTO_CHAINSEND, wParam, lParam);
+}
+
+int SVC_OTRSendMessageW(WPARAM wParam, LPARAM lParam){
+ if(!lParam) return 0;
+
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ if (!(ccs->wParam & PREF_UTF)) ccs->wParam |= PREF_UNICODE;
+
+ return SVC_OTRSendMessage(wParam, lParam);
+}
+
+/*
+#define MESSAGE_PREFIX "(OTR) "
+#define MESSAGE_PREFIXW L"(OTR) "
+#define MESSAGE_PREFIX_LEN 6
+*/
+
+int SVC_OTRRecvMessage(WPARAM wParam,LPARAM lParam){
+ //PUShowMessage("OTR Recv Message", SM_NOTIFY);
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ PROTORECVEVENT *pre = (PROTORECVEVENT *) ccs->lParam;
+
+#ifdef _DEBUG
+ if(pre->flags & PREF_UNICODE)
+ MessageBox(0, (wchar_t *)pre->szMessage, _T("OTR - receiving message"), MB_OK);
+ else
+ MessageBoxA(0, (char *)pre->szMessage, ("OTR - receiving message"), MB_OK);
+#endif
+
+ if (pre->flags & PREF_BYPASS_OTR) { // bypass for our inline messages
+ //TODO: check, whether this can be removed (then OTR status info should be still saved)
+ return CallService(MS_PROTO_CHAINRECV, wParam, lParam);
+ }
+
+ char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)ccs->hContact, 0);
+ if(!proto)
+ return 1; //error
+ else if(proto && g_metaproto && strcmp(proto, g_metaproto) == 0) // bypass for metacontacts
+ return CallService(MS_PROTO_CHAINRECV, wParam, lParam);
+
+ char *uname = contact_get_id(ccs->hContact);
+ if(!uname) return 1; // error
+
+ char *oldmessage = pre->szMessage;
+ char *oldmessage_utf = NULL;
+ // convert oldmessage to utf-8
+ if(pre->flags & PREF_UTF) {
+ oldmessage_utf = oldmessage;
+ } else if(pre->flags & PREF_UNICODE) { //UNSURE!!
+ oldmessage_utf = mir_utf8encodeW((wchar_t*)(&oldmessage[strlen(oldmessage)+1]));
+ } else {
+ oldmessage_utf = mir_utf8encode(oldmessage);
+ }
+ if(!oldmessage_utf) return 1;
+
+
+ char *newmessage = NULL;
+ OtrlTLV *tlvs = NULL;
+ OtrlTLV *tlv = NULL;
+ BOOL ignore_msg;
+ ConnContext *context;
+ //NextExpectedSMP nextMsg;
+
+ lib_cs_lock();
+ ignore_msg = otrl_message_receiving(otr_user_state, &ops, (void*)ccs->hContact,
+ proto, proto, uname, oldmessage_utf,
+ &newmessage, &tlvs, add_appdata, (void*)ccs->hContact);
+ lib_cs_unlock();
+
+ if( !(pre->flags & PREF_UTF)) mir_free(oldmessage_utf);
+ oldmessage_utf = NULL;
+
+
+ tlv = otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED);
+ if (tlv) {
+ /* Notify the user that the other side disconnected. */
+ TCHAR buff[256];
+ mir_sntprintf(buff, 256, TranslateT(LANG_SESSION_TERMINATED_BY_OTR), contact_get_nameT(ccs->hContact));
+ //MessageBox(0, buff, Translate("OTR Information"), MB_OK);
+ ShowMessage((HANDLE)ccs->hContact, buff);
+
+ //if(options.timeout_finished) ResetFinishedTimer();
+ }
+
+ lib_cs_lock();
+ context = otrl_context_find_miranda(otr_user_state, ccs->hContact);
+ lib_cs_unlock();
+ /* Keep track of our current progress in the Socialist Millionaires'
+ * Protocol. */
+ if (context && ( (context->smstate->sm_prog_state == OTRL_SMP_PROG_CHEATED) ||
+ otrl_tlv_find(tlvs, OTRL_TLV_SMP1Q) ||
+ otrl_tlv_find(tlvs, OTRL_TLV_SMP1) ||
+ otrl_tlv_find(tlvs, OTRL_TLV_SMP2) ||
+ otrl_tlv_find(tlvs, OTRL_TLV_SMP3) ||
+ otrl_tlv_find(tlvs, OTRL_TLV_SMP4) )
+ )
+ {
+ otr_abort_smp(context); // we do not support it (yet), notify partner to shorten wait time
+ }
+
+
+ /*
+ if (context) {
+ nextMsg = context->smstate->nextExpected;
+
+ if (context->smstate->sm_prog_state == OTRL_SMP_PROG_CHEATED) {
+ otr_abort_smp(context);
+ otrg_dialog_update_smp(context, 0.0);
+ 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)
+ otr_abort_smp(context);
+ else {
+ char *question = (char *)tlv->data;
+ char *eoq = (char*)memchr(question, '\0', tlv->len);
+ if (eoq) {
+ otrg_dialog_socialist_millionaires_q(context,
+ question);
+ }
+ }
+ }
+ tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1);
+ if (tlv) {
+ if (nextMsg != OTRL_SMP_EXPECT1)
+ otr_abort_smp(context);
+ else {
+ otrg_dialog_socialist_millionaires(context);
+ }
+ }
+ tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP2);
+ if (tlv) {
+ if (nextMsg != OTRL_SMP_EXPECT2)
+ otr_abort_smp(context);
+ else {
+ otrg_dialog_update_smp(context, 0.6);
+ context->smstate->nextExpected = OTRL_SMP_EXPECT4;
+ }
+ }
+ tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP3);
+ if (tlv) {
+ if (nextMsg != OTRL_SMP_EXPECT3)
+ otr_abort_smp(context);
+ else {
+ otrg_dialog_update_smp(context, 1.0);
+ context->smstate->nextExpected = OTRL_SMP_EXPECT1;
+ }
+ }
+ tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP4);
+ if (tlv) {
+ if (nextMsg != OTRL_SMP_EXPECT4)
+ otr_abort_smp(context);
+ else {
+ otrg_dialog_update_smp(context, 1.0);
+ context->smstate->nextExpected = OTRL_SMP_EXPECT1;
+ }
+ }
+ tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP_ABORT);
+ if (tlv) {
+ otrg_dialog_update_smp(context, 0.0);
+ context->smstate->nextExpected = OTRL_SMP_EXPECT1;
+ }
+ }
+ }
+ */
+
+ otrl_tlv_free(tlvs);
+
+ mir_free(uname);
+
+ /* If we're supposed to ignore this incoming message (because it's a
+ * protocol message), set it to NULL, so that other plugins that
+ * catch receiving-im-msg don't return 0, and cause it to be
+ * displayed anyway. */
+ if (ignore_msg) {
+ /* should not be required ;)
+ char t[3] = {0, 0, 0};
+ if(pre->flags & PREF_UNICODE) { //TODO!! lstrlen(pre->szMessage)+1 ??
+ if (pre->szMessage && strlen(pre->szMessage)) memcpy(pre->szMessage, t,3 );
+ } else {
+ if (pre->szMessage && strlen(pre->szMessage)) memcpy(pre->szMessage, t, 1);
+ }
+ */
+ if (newmessage) otrl_message_free(newmessage);
+ return 1;
+ } else if (newmessage) {
+ //bool free=false;
+ DWORD flags = pre->flags;
+ /* if(pre->flags & PREF_UTF) {
+ oldmessage_utf = newmessage;
+ } else if(pre->flags & PREF_UNICODE) { //TODO!! lstrlen(pre->szMessage)+1 ??
+ oldmessage_utf = (char*)mir_utf8decodeW(newmessage);
+ free = true;
+ } else {
+ mir_utf8decode(newmessage, NULL);
+ oldmessage_utf = newmessage;
+ } */
+
+ //pre->szMessage = oldmessage_utf;
+ pre->flags &= ~PREF_UNICODE;
+ pre->flags |= PREF_UTF; // just use UTF, so we do not have to recode the message
+
+ bool is_miralloc = false;
+ if (context) {
+ TrustLevel level = otr_context_get_trust(context);
+ if (options.prefix_messages && (level == TRUST_PRIVATE || level == TRUST_UNVERIFIED)) {
+ DWORD len = (strlen(options.prefix)+strlen(newmessage)+1)*sizeof(char);
+ char* premsg = (char*)mir_alloc( len );
+ memset(premsg, 0, len);
+ strcpy(premsg, options.prefix);
+ strcat(premsg, newmessage);
+ otrl_message_free(newmessage);
+ newmessage = premsg;
+ is_miralloc = true;
+ }
+ }
+ pre->szMessage = newmessage;
+ BOOL ret = CallService(MS_PROTO_CHAINRECV, wParam, lParam);
+ pre->flags = flags;
+ pre->szMessage = oldmessage;
+ if (is_miralloc)
+ mir_free(newmessage);
+ else
+ otrl_message_free(newmessage);
+
+ // if (free) mir_free(oldmessage_utf);
+ return ret;
+ }
+ return CallService(MS_PROTO_CHAINRECV, wParam, lParam);
+
+}
+
+/* Abort the SMP protocol. Used when malformed or unexpected messages
+ * are received. */
+void otr_abort_smp(ConnContext *context)
+{
+ otrl_message_abort_smp(otr_user_state, &ops, context->app_data, context);
+}
+
+/* Start the Socialist Millionaires' Protocol over the current connection,
+ * using the given initial secret, and optionally a question to pass to
+ * the buddy. */
+void otr_start_smp(ConnContext *context, const char *question,
+ const unsigned char *secret, size_t secretlen)
+{
+ otrl_message_initiate_smp_q(otr_user_state, &ops, context->app_data,
+ context, question, secret, secretlen);
+}
+
+/* Continue the Socialist Millionaires' Protocol over the current connection,
+ * using the given initial secret (ie finish step 2). */
+void otr_continue_smp(ConnContext *context,
+ const unsigned char *secret, size_t secretlen)
+{
+ otrl_message_respond_smp(otr_user_state, &ops, context->app_data,
+ context, secret, secretlen);
+} \ No newline at end of file
diff --git a/MirOTR/svcs_proto.h b/MirOTR/svcs_proto.h
new file mode 100644
index 0000000..7040d79
--- /dev/null
+++ b/MirOTR/svcs_proto.h
@@ -0,0 +1,13 @@
+#pragma once
+
+int SVC_OTRSendMessage(WPARAM wParam,LPARAM lParam);
+int SVC_OTRSendMessageW(WPARAM wParam, LPARAM lParam);
+int SVC_OTRRecvMessage(WPARAM wParam,LPARAM lParam);
+
+void otr_abort_smp(ConnContext *context);
+
+void otr_start_smp(ConnContext *context, const char *question,
+ const unsigned char *secret, size_t secretlen);
+
+void otr_continue_smp(ConnContext *context,
+ const unsigned char *secret, size_t secretlen); \ No newline at end of file
diff --git a/MirOTR/svcs_srmm.cpp b/MirOTR/svcs_srmm.cpp
new file mode 100644
index 0000000..e562725
--- /dev/null
+++ b/MirOTR/svcs_srmm.cpp
@@ -0,0 +1,224 @@
+#include "stdafx.h"
+HANDLE hEventIconPressed;
+HICON hIconNotSecure, hIconFinished, hIconPrivate, hIconUnverified;
+
+int WindowEvent(WPARAM wParam, LPARAM lParam) {
+ MessageWindowEventData *mwd = (MessageWindowEventData *)lParam;
+
+ if(mwd->uType == MSG_WINDOW_EVT_CLOSE && options.end_window_close) {
+ // FinishSession(mwd->hContact);
+ return 0;
+ }
+ if(mwd->uType != MSG_WINDOW_EVT_OPEN) return 0;
+ if(!options.bHaveSRMMIcons) return 0;
+
+ HANDLE hContact = mwd->hContact, hTemp;
+ if(options.bHaveMetaContacts && (hTemp = (HANDLE)CallService(MS_MC_GETMOSTONLINECONTACT, (WPARAM)hContact, 0)) != 0)
+ hContact = hTemp;
+
+ if(!CallService(MS_PROTO_ISPROTOONCONTACT, (WPARAM)hContact, (LPARAM)MODULENAME))
+ return 0;
+
+ lib_cs_lock();
+ ConnContext *context = otrl_context_find_miranda(otr_user_state, hContact);
+ lib_cs_unlock();
+
+ SetEncryptionStatus(hContact, otr_context_get_trust(context));
+
+ return 0;
+}
+
+int SVC_IconPressed(WPARAM wParam, LPARAM lParam) {
+ HANDLE hContact = (HANDLE)wParam;
+ StatusIconClickData *sicd = (StatusIconClickData *)lParam;
+ if(sicd->cbSize < (int)sizeof(StatusIconClickData))
+ return 0;
+
+ if(strcmp(sicd->szModule, MODULENAME) == 0) {
+ char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ if(proto && DBGetContactSettingByte(hContact, proto, "ChatRoom", 0))
+ return 0;
+ HMENU hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_CONTEXT));
+ CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM)hMenu, 0);
+ TrustLevel level = (TrustLevel) db_dword_get(hContact, MODULENAME, "TrustLevel", TRUST_NOT_PRIVATE);
+ MENUITEMINFO minfo = {0};
+ minfo.cbSize = sizeof(MENUITEMINFO);
+ minfo.fMask = MIIM_STRING|MIIM_STATE|MIIM_BITMAP;
+ minfo.fState = MF_DISABLED;
+
+ HWND wnd = GetFocus();
+ HDC dc = GetDC(wnd), hdc = CreateCompatibleDC(dc);
+ HBITMAP bmpIconPrivate = CreateCompatibleBitmap(dc, 16, 16);
+ HGDIOBJ old = SelectObject(hdc, bmpIconPrivate);
+ DrawIconEx(hdc, 0, 0, hIconPrivate,16, 16, 0, GetSysColorBrush(COLOR_MENU), DI_NORMAL);
+
+ HBITMAP bmpIconUnverified = CreateCompatibleBitmap(dc, 16, 16);
+ SelectObject(hdc, bmpIconUnverified);
+ DrawIconEx(hdc, 0, 0, hIconUnverified,16, 16, 0, GetSysColorBrush(COLOR_MENU), DI_NORMAL);
+
+ HBITMAP bmpIconFinished = CreateCompatibleBitmap(dc, 16, 16);
+ SelectObject(hdc, bmpIconFinished);
+ DrawIconEx(hdc, 0, 0, hIconFinished,16, 16, 0, GetSysColorBrush(COLOR_MENU), DI_NORMAL);
+
+ HBITMAP bmpIconNotSecure = CreateCompatibleBitmap(dc, 16, 16);
+ SelectObject(hdc, bmpIconNotSecure);
+ DrawIconEx(hdc, 0, 0, hIconNotSecure,16, 16, 0, GetSysColorBrush(COLOR_MENU), DI_NORMAL);
+
+ switch (level) {
+ case TRUST_PRIVATE:
+ minfo.hbmpItem = bmpIconPrivate;
+ minfo.dwTypeData = TranslateT(LANG_STATUS_PRIVATE);
+ break;
+ case TRUST_UNVERIFIED:
+ minfo.hbmpItem = bmpIconUnverified;
+ minfo.dwTypeData = TranslateT(LANG_STATUS_UNVERIFIED);
+ break;
+ case TRUST_FINISHED:
+ minfo.hbmpItem = bmpIconFinished;
+ minfo.dwTypeData = TranslateT(LANG_STATUS_FINISHED);
+ break;
+ default:
+ minfo.hbmpItem = bmpIconNotSecure;
+ minfo.dwTypeData = TranslateT(LANG_STATUS_DISABLED);
+ }
+
+ SelectObject(hdc, old);
+ DeleteDC(hdc);
+ ReleaseDC(wnd, dc);
+
+ SetMenuItemInfo(hMenu, IDM_OTR_STATUS, FALSE, &minfo);
+
+ minfo.fMask = MIIM_STATE|MIIM_BITMAP;
+ minfo.fState = (level==TRUST_NOT_PRIVATE)?MF_ENABLED:MF_GRAYED;
+ minfo.hbmpItem = bmpIconUnverified;
+ SetMenuItemInfo(hMenu, IDM_OTR_START, FALSE, &minfo);
+
+ minfo.fState = (level==TRUST_NOT_PRIVATE)?MF_GRAYED:MF_ENABLED;
+ minfo.hbmpItem = bmpIconNotSecure;
+ SetMenuItemInfo(hMenu, IDM_OTR_STOP, FALSE, &minfo);
+
+ minfo.fState = (level==TRUST_NOT_PRIVATE)?MF_GRAYED:MF_ENABLED;
+ minfo.hbmpItem = bmpIconFinished;
+ SetMenuItemInfo(hMenu, IDM_OTR_REFRESH, FALSE, &minfo);
+
+ minfo.fState = (level==TRUST_NOT_PRIVATE||level==TRUST_FINISHED)?MF_GRAYED:MF_ENABLED;
+ minfo.hbmpItem = bmpIconPrivate;
+ SetMenuItemInfo(hMenu, IDM_OTR_VERIFY, FALSE, &minfo);
+
+ switch ( (DWORD) TrackPopupMenu(GetSubMenu(hMenu, 0), TPM_NONOTIFY|TPM_RETURNCMD, sicd->clickLocation.x, sicd->clickLocation.y, 0, GetFocus(), 0) )
+ {
+ case IDM_OTR_START:
+ SVC_StartOTR(wParam, 0);
+ break;
+ case IDM_OTR_REFRESH:
+ SVC_RefreshOTR(wParam, 0);
+ break;
+ case IDM_OTR_STOP:
+ SVC_StopOTR(wParam, 0);
+ break;
+ case IDM_OTR_VERIFY:
+ ConnContext *context = otrl_context_find_miranda(otr_user_state, (HANDLE)wParam);
+ if (context) VerifyContextDialog(context);
+ break;
+ }
+ DeleteObject(bmpIconPrivate);
+ DeleteObject(bmpIconFinished);
+ DeleteObject(bmpIconNotSecure);
+ DeleteObject(bmpIconUnverified);
+ }
+
+ return 0;
+}
+
+// set SRMM icon status, if applicable
+void SetEncryptionStatus(HANDLE hContact, TrustLevel level) {
+ //char dbg_msg[2048];
+ //dbg_msg[0] = 0;
+
+ //strcat(dbg_msg, "Set encyption status: ");
+ //strcat(dbg_msg, (encrypted ? "true" : "false"));
+
+ char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ bool chat_room = (proto && DBGetContactSettingByte(hContact, proto, "ChatRoom", 0));
+
+ // if(!chat_room) DBWriteContactSettingByte(hContact, MODULENAME, "Encrypted", (encrypted ? 1 : 0));
+
+ if(options.bHaveSRMMIcons) {
+ //strcat(dbg_msg, "\nchanging icon");
+ StatusIconData sid = {0}, sid2={0};
+ sid.cbSize = sizeof(sid);
+ sid.szModule = MODULENAME;
+ sid.dwId = 0;
+ sid.flags = MBF_HIDDEN;
+
+ sid2.cbSize = sid.cbSize;
+ sid2.szModule = MODULENAME;
+ sid2.dwId = 1;
+ sid2.flags = MBF_HIDDEN;
+ if (!chat_room) {
+ switch (level) {
+ case TRUST_FINISHED:
+ sid.flags = 0;
+ break;
+ case TRUST_UNVERIFIED:
+ sid2.flags = MBF_DISABLED;
+ break;
+ case TRUST_PRIVATE:
+ sid2.flags = 0;
+ break;
+ default:
+ sid.flags = MBF_DISABLED;
+ break;
+ }
+ }
+ CallService(MS_MSG_MODIFYICON, (WPARAM)hContact, (LPARAM)&sid);
+ CallService(MS_MSG_MODIFYICON, (WPARAM)hContact, (LPARAM)&sid2);
+ db_dword_set(hContact, MODULENAME, "TrustLevel", level);
+
+ if(!chat_room && options.bHaveMetaContacts) {
+ HANDLE hMeta = (HANDLE)CallService(MS_MC_GETMETACONTACT, (WPARAM)hContact, 0);
+ if(hMeta && hContact == (HANDLE)CallService(MS_MC_GETMOSTONLINECONTACT, (WPARAM)hMeta, 0)) {
+ //strcat(dbg_msg, "\nrecursing for meta");
+ SetEncryptionStatus(hMeta, level);
+ }
+ }
+ }
+ //PUShowMessage(dbg_msg, SM_NOTIFY);
+}
+
+void InitSRMM() {
+ // add icon to srmm status icons
+ if(options.bHaveSRMMIcons) {
+ hIconNotSecure = LoadIcon(ICON_NOT_PRIVATE, 0);
+ hIconFinished = LoadIcon(ICON_FINISHED, 0);
+ hIconPrivate = LoadIcon(ICON_PRIVATE, 0);
+ hIconUnverified = LoadIcon(ICON_UNVERIFIED, 0);
+
+ StatusIconData sid = {0};
+ sid.cbSize = sizeof(sid);
+ sid.szModule = MODULENAME;
+ sid.dwId = 0;
+ sid.hIcon = hIconFinished;
+ sid.hIconDisabled = hIconNotSecure;
+ sid.flags = MBF_DISABLED | MBF_HIDDEN;
+ sid.szTooltip = Translate(LANG_OTR_TOOLTIP);
+ CallService(MS_MSG_ADDICON, 0, (LPARAM)&sid);
+
+ sid.dwId = 1;
+ sid.hIcon = hIconPrivate;
+ sid.hIconDisabled = hIconUnverified;
+ CallService(MS_MSG_ADDICON, 0, (LPARAM)&sid);
+
+ // hook the window events so that we can can change the status of the icon
+
+ hEventIconPressed = HookEvent(ME_MSG_ICONPRESSED, SVC_IconPressed);
+ }
+}
+void DeinitSRMM() {
+ UnhookEvent(hEventIconPressed);
+ ReleaseIcon(ICON_NOT_PRIVATE, 0);
+ ReleaseIcon(ICON_FINISHED, 0);
+ ReleaseIcon(ICON_PRIVATE, 0);
+ ReleaseIcon(ICON_UNVERIFIED, 0);
+ hIconNotSecure = hIconFinished = hIconPrivate = hIconUnverified =0;
+} \ No newline at end of file
diff --git a/MirOTR/svcs_srmm.h b/MirOTR/svcs_srmm.h
new file mode 100644
index 0000000..4bc2046
--- /dev/null
+++ b/MirOTR/svcs_srmm.h
@@ -0,0 +1,7 @@
+#pragma once
+
+int WindowEvent(WPARAM wParam, LPARAM lParam);
+int SVC_IconPressed(WPARAM wParam, LPARAM lParam);
+void SetEncryptionStatus(HANDLE hContact, TrustLevel level);
+void InitSRMM();
+void DeinitSRMM(); \ No newline at end of file
diff --git a/MirOTR/targetver.h b/MirOTR/targetver.h
new file mode 100644
index 0000000..c448111
--- /dev/null
+++ b/MirOTR/targetver.h
@@ -0,0 +1,24 @@
+#pragma once
+
+// Die folgenden Makros definieren die mindestens erforderliche Plattform. Die mindestens erforderliche Plattform
+// ist die früheste Windows-, Internet Explorer-Version usw., die über die erforderlichen Features zur Ausführung
+// Ihrer Anwendung verfügt. Die Makros aktivieren alle Funktionen, die auf den Plattformversionen bis
+// einschließlich der angegebenen Version verfügbar sind.
+
+// Ändern Sie folgende Definitionen für Plattformen, die älter als die unten angegebenen sind.
+// Unter MSDN finden Sie die neuesten Informationen über die entsprechenden Werte für die unterschiedlichen Plattformen.
+#ifndef WINVER // Gibt an, dass Windows 2000 die mindestens erforderliche Plattform ist.
+#define WINVER 0x0500 // Ändern Sie den entsprechenden Wert, um auf andere Versionen von Windows abzuzielen.
+#endif
+
+#ifndef _WIN32_WINNT // Gibt an, dass Windows 2000 die mindestens erforderliche Plattform ist.
+#define _WIN32_WINNT 0x0500 // Ändern Sie den entsprechenden Wert, um auf andere Versionen von Windows abzuzielen.
+#endif
+
+#ifndef _WIN32_WINDOWS // Gibt an, dass Windows 98 die mindestens erforderliche Plattform ist.
+#define _WIN32_WINDOWS 0x0410 // Ändern Sie den entsprechenden Wert, um auf mindestens Windows Me abzuzielen.
+#endif
+
+#ifndef _WIN32_IE // Gibt an, dass Internet Explorer 7.0 die mindestens erforderliche Plattform ist.
+#define _WIN32_IE 0x0700 // Ändern Sie den entsprechenden Wert, um auf andere Versionen von IE abzuzielen.
+#endif
diff --git a/MirOTR/utils.cpp b/MirOTR/utils.cpp
new file mode 100644
index 0000000..59dd5b2
--- /dev/null
+++ b/MirOTR/utils.cpp
@@ -0,0 +1,400 @@
+#include "stdafx.h"
+#include "utils.h"
+
+CRITICAL_SECTION lib_cs;
+
+void InitUtils() {
+ InitializeCriticalSection(&lib_cs);
+}
+void DeinitUtils() {
+ DeleteCriticalSection(&lib_cs);
+}
+
+void lib_cs_lock() {
+ EnterCriticalSection(&lib_cs);
+}
+
+void lib_cs_unlock() {
+ LeaveCriticalSection(&lib_cs);
+}
+
+HANDLE find_contact(const char* userid, const char* protocol) {
+ HANDLE hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 );
+ while ( hContact != NULL )
+ {
+ const char *proto = contact_get_proto(hContact);
+ if(proto && strcmp(proto, protocol) == 0) {
+ char *name = contact_get_id(hContact);
+ if(name && strcmp(name, userid) == 0) {
+ mir_free(name);
+ return hContact;
+ }
+ mir_free(name);
+ }
+ hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 );
+ }
+
+ return 0;
+}
+
+/* Look up a connection context by hContact from the given
+* OtrlUserState. If add_if_missing is true, allocate and return a new
+* context if one does not currently exist. In that event, call
+* add_app_data(data, context) so that app_data and app_data_free can be
+* filled in by the application, and set *addedp to 1. */
+ConnContext * otrl_context_find_miranda(OtrlUserState us, HANDLE hContact)
+{
+ ConnContext ** curp;
+ if (!hContact) return NULL;
+ for (curp = &(us->context_root); *curp; curp = &((*curp)->next)) {
+ if ((*curp)->app_data == hContact ) return *curp;
+ }
+ return NULL;
+}
+
+/* What level of trust do we have in the privacy of this ConnContext? */
+TrustLevel otr_context_get_trust(ConnContext *context)
+{
+ TrustLevel level = TRUST_NOT_PRIVATE;
+
+ if (context && context->msgstate == OTRL_MSGSTATE_ENCRYPTED) {
+ if (context->active_fingerprint->trust &&
+ context->active_fingerprint->trust[0] != '\0') {
+ level = TRUST_PRIVATE;
+ } else {
+ level = TRUST_UNVERIFIED;
+ }
+ } else if (context && context->msgstate == OTRL_MSGSTATE_FINISHED) {
+ level = TRUST_FINISHED;
+ }
+
+ return level;
+}
+
+/* Convert a 20-byte hash value to a 45-byte human-readable value */
+void otrl_privkey_hash_to_humanT(TCHAR human[45], const unsigned char hash[20])
+{
+ int word, byte;
+ TCHAR *p = human;
+
+ for(word=0; word<5; ++word) {
+ for(byte=0; byte<4; ++byte) {
+ _stprintf(p, _T("%02X"), hash[word*4+byte]);
+ p += 2;
+ }
+ *(p++) = ' ';
+ }
+ /* Change that last ' ' to a '\0' */
+ --p;
+ *p = '\0';
+}
+
+char* contact_get_id(HANDLE hContact, bool bNameOnError) {
+ char* pszUniqueID = NULL;
+ CONTACTINFO ci;
+ ZeroMemory(&ci, sizeof(ci));
+ ci.cbSize = sizeof(ci);
+ ci.hContact = hContact;
+ ci.dwFlag = CNF_UNIQUEID;
+
+ if (CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci) == 0)
+ {
+ if (ci.type == CNFT_ASCIIZ) {
+ pszUniqueID = (char*)ci.pszVal; // MS_CONTACT_GETCONTACTINFO uses mir_alloc
+ } else if (ci.type == CNFT_DWORD) {
+ pszUniqueID = (char*)mir_alloc(15);
+ if (pszUniqueID)
+ mir_snprintf(pszUniqueID, 15, ("%u"), ci.dVal);
+ } else if (ci.type == CNFT_WORD) {
+ pszUniqueID = (char*)mir_alloc(15);
+ if (pszUniqueID)
+ mir_snprintf(pszUniqueID, 15, ("%u"), ci.wVal);
+ } else if (ci.type == CNFT_BYTE) {
+ pszUniqueID = (char*)mir_alloc(15);
+ if (pszUniqueID)
+ mir_snprintf(pszUniqueID, 15, ("%u"), ci.bVal);
+ }
+ }
+ if (!pszUniqueID && bNameOnError) {
+ char *name = (char *)CallService( MS_CLIST_GETCONTACTDISPLAYNAME, ( WPARAM )hContact, 0 );
+ if (name) pszUniqueID = mir_strdup(name);
+ }
+ return pszUniqueID;
+}
+
+__inline const TCHAR* contact_get_nameT(HANDLE hContact) {
+ return (TCHAR*)CallService( MS_CLIST_GETCONTACTDISPLAYNAME, ( WPARAM )hContact, GCDNF_TCHAR );
+}
+
+__inline const char* contact_get_proto(HANDLE hContact) {
+ char *uproto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ return uproto;
+}
+
+__inline const char* contact_get_account(HANDLE hContact) {
+ char *uacc = (char *)CallService(MS_PROTO_GETCONTACTBASEACCOUNT, (WPARAM)hContact, 0);
+ return uacc;
+}
+
+void ShowPopup(const TCHAR* line1, const TCHAR* line2, int timeout, const HANDLE hContact) {
+ if(CallService(MS_SYSTEM_TERMINATED, 0, 0)) return;
+
+ if ( !options.bHavePopups) {
+ TCHAR title[256];
+ _stprintf(title, _T("%s Message"), _T(MODULENAME));
+
+ if(line1 && line2) {
+ TCHAR *message = new TCHAR[_tcslen(line1) + _tcslen(line2) + 3]; // newline and null terminator
+ _stprintf(message, _T("%s\r\n%s"), line1, line2);
+ MessageBox( NULL, message, title, MB_OK | MB_ICONINFORMATION );
+ delete message;
+ } else if(line1) {
+ MessageBox( NULL, line1, title, MB_OK | MB_ICONINFORMATION );
+ } else if(line2) {
+ MessageBox( NULL, line2, title, MB_OK | MB_ICONINFORMATION );
+ }
+ return;
+ }
+
+ POPUPDATAT ppd = {0};
+ //memset((void *)&ppd, 0, sizeof(POPUPDATAT));
+
+ ppd.lchContact = hContact;
+ ppd.lchIcon = NULL;
+
+ if(line1 && line2) {
+ _tcsncpy( ppd.lptzContactName, line1, MAX_CONTACTNAME-1 );
+ _tcsncpy( ppd.lptzText, line2, MAX_SECONDLINE-1 );
+ } else if(line1) {
+ if (PUIsSecondLineShown()) _tcsncpy( ppd.lptzText, line1, MAX_SECONDLINE-1 );
+ else _tcsncpy( ppd.lptzContactName, line1, MAX_CONTACTNAME-1 );
+ }
+ else if(line2) {
+ if (PUIsSecondLineShown()) _tcsncpy( ppd.lptzText, line2, MAX_SECONDLINE-1 );
+ else _tcsncpy( ppd.lptzContactName, line2, MAX_CONTACTNAME-1 );
+ }
+
+ ppd.iSeconds = timeout;
+
+ ppd.PluginWindowProc = NULL;
+ ppd.PluginData = NULL;
+
+ PUAddPopUpT(&ppd);
+
+}
+
+void ShowWarning(TCHAR *msg) {
+ TCHAR buffer[512];
+ ErrorDisplay disp = options.err_method;
+ // funny logic :) ... try to avoid message boxes
+ // if want baloons but no balloons, try popups
+ // if want popups but no popups, try baloons
+ // if, after that, you want balloons but no balloons, revert to message boxes
+ if(disp == ED_BAL && !ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) disp = ED_POP;
+ if(disp == ED_POP && !options.bHavePopups) disp = ED_BAL;
+ if(disp == ED_BAL && !ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) disp = ED_MB;
+
+ _stprintf(buffer, _T("%s Warning"), _T(MODULENAME));
+
+ TCHAR *message;
+ switch(disp) {
+ case ED_POP:
+ message = new TCHAR[_tcslen(msg) + 515]; // newline and null terminator
+ _stprintf(message, _T("%s\r\n%s"), buffer, msg);
+ PUShowMessageT(message, SM_WARNING);
+ delete message;
+ break;
+ case ED_MB:
+ MessageBox(0, msg, buffer, MB_OK | MB_ICONWARNING);
+ break;
+ case ED_BAL:
+ {
+ MIRANDASYSTRAYNOTIFY sn = {0};
+ sn.cbSize = sizeof(sn);
+ sn.szProto= MODULENAME;
+ sn.tszInfoTitle = buffer;
+ sn.tszInfo = msg;
+#ifdef _UNICODE
+ sn.dwInfoFlags = NIIF_WARNING | NIIF_INTERN_UNICODE;
+#else
+ sn.dwInfoFlags = NIIF_WARNING;
+#endif
+ sn.uTimeout = 10;
+
+ CallService(MS_CLIST_SYSTRAY_NOTIFY, 0, (LPARAM)&sn);
+ }
+
+ break;
+ }
+}
+
+void ShowError(TCHAR *msg) {
+ TCHAR buffer[512];
+ ErrorDisplay disp = options.err_method;
+ // funny logic :) ... try to avoid message boxes
+ // if want baloons but no balloons, try popups
+ // if want popups but no popups, try baloons
+ // if, after that, you want balloons but no balloons, revert to message boxes
+ if(disp == ED_BAL && !ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) disp = ED_POP;
+ if(disp == ED_POP && !options.bHavePopups) disp = ED_BAL;
+ if(disp == ED_BAL && !ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) disp = ED_MB;
+
+ _stprintf(buffer, _T("%s Error"), _T(MODULENAME));
+
+
+ TCHAR *message;
+ switch(disp) {
+ case ED_POP:
+ message = new TCHAR[_tcslen(msg) + 515]; // newline and null terminator
+ _stprintf(message, _T("%s\r\n%s"), buffer, msg);
+ PUShowMessageT(message, SM_WARNING);
+ delete message;
+ break;
+ case ED_MB:
+ MessageBox(0, msg, buffer, MB_OK | MB_ICONERROR);
+ break;
+ case ED_BAL:
+ {
+ MIRANDASYSTRAYNOTIFY sn = {0};
+ sn.cbSize = sizeof(sn);
+ sn.szProto = MODULENAME;
+ sn.tszInfoTitle = buffer;
+ sn.tszInfo = msg;
+#ifdef _UNICODE
+ sn.dwInfoFlags = NIIF_ERROR | NIIF_INTERN_UNICODE;
+#else
+ sn.dwInfoFlags = NIIF_ERROR;
+#endif
+ sn.uTimeout = 10;
+
+ CallService(MS_CLIST_SYSTRAY_NOTIFY, 0, (LPARAM)&sn);
+ }
+
+ break;
+ }
+}
+
+
+void ShowPopupUtf(const char* line1, const char* line2, int timeout, const HANDLE hContact) {
+ TCHAR* l1 = (line1) ? mir_utf8decodeT(line1) : NULL;
+ TCHAR* l2 = (line2) ? mir_utf8decodeT(line2) : NULL;
+ ShowPopup(l1, l2, timeout, hContact);
+ if (l1) mir_free(l1);
+ if (l2) mir_free(l2);
+}
+
+void ShowWarningUtf(char* msg) {
+ TCHAR* m = (msg) ? mir_utf8decodeT(msg) : NULL;
+ ShowWarning(m);
+ if (m) mir_free(m);
+}
+void ShowErrorUtf(char* msg) {
+ TCHAR* m = (msg) ? mir_utf8decodeT(msg) : NULL;
+ ShowError(m);
+ if (m) mir_free(m);
+}
+
+void ShowMessageInline(const HANDLE hContact, const TCHAR *msg) {
+ TCHAR buff[1024];
+ mir_sntprintf(buff, 1024, _T("%s%s"), TranslateT(LANG_INLINE_PREFIX), msg);
+
+ PROTORECVEVENT pre = {0};
+ pre.timestamp = time(0);
+ char *utf = mir_utf8encodeT(buff);
+ pre.szMessage = utf;
+ pre.flags = PREF_UTF|PREF_BYPASS_OTR;
+ //CallContactService(hContact, PSR_MESSAGE, 0, (LPARAM)&pre);
+
+ CCSDATA ccs = {0};
+ ccs.hContact = hContact;
+ ccs.szProtoService = PSR_MESSAGE;
+ ccs.lParam = (LPARAM)&pre;
+
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
+ mir_free(utf);
+}
+
+void ShowMessageInlineUtf(const HANDLE hContact, const char *msg) {
+ char buff[1024];
+ mir_snprintf(buff, 1024, "%s%s", Translate(LANG_INLINE_PREFIX), msg);
+
+ PROTORECVEVENT pre = {0};
+ pre.timestamp = time(0);
+ pre.szMessage = buff;
+ pre.flags = PREF_UTF|PREF_BYPASS_OTR;
+ //CallContactService(hContact, PSR_MESSAGE, 0, (LPARAM)&pre);
+
+ CCSDATA ccs = {0};
+ ccs.hContact = hContact;
+ ccs.szProtoService = PSR_MESSAGE;
+ ccs.lParam = (LPARAM)&pre;
+
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
+}
+
+
+void ShowMessageUtf(const HANDLE hContact, const char *msg) {
+ if(options.msg_inline)
+ ShowMessageInlineUtf(hContact, msg);
+ if(options.msg_popup)
+ ShowPopupUtf(Translate(LANG_OTR_INFO), msg, 0, hContact);
+}
+
+void ShowMessage(const HANDLE hContact, const TCHAR *msg) {
+ if(options.msg_inline)
+ ShowMessageInline(hContact, msg);
+ if(options.msg_popup)
+ ShowPopup(TranslateT(LANG_OTR_INFO), msg, 0, hContact);
+}
+
+
+/*
+bool GetEncryptionStatus(HANDLE hContact) {
+ char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ bool chat_room = (proto && DBGetContactSettingByte(hContact, proto, "ChatRoom", 0));
+
+ if(!chat_room) {
+ if (options.bHaveMetaContacts) {
+ HANDLE hMeta = (HANDLE)CallService(MS_MC_GETMETACONTACT, (WPARAM)hContact, 0);
+ if(hMeta && hContact == (HANDLE)CallService(MS_MC_GETMOSTONLINECONTACT, (WPARAM)hMeta, 0)) {
+ //strcat(dbg_msg, "\nrecursing for meta");
+ return GetEncryptionStatus(hMeta);
+ }
+ return 0!=DBGetContactSettingByte(hContact, MODULENAME, "Encrypted", 0 );
+ }
+ }
+ return 0;
+}
+*/
+
+const TCHAR *policy_to_string(OtrlPolicy policy) {
+ switch (policy) {
+ case OTRL_POLICY_NEVER:
+ return TranslateT(LANG_POLICY_NEVER);
+ break;
+ case OTRL_POLICY_OPPORTUNISTIC:
+ return TranslateT(LANG_POLICY_OPP);
+ break;
+ case OTRL_POLICY_MANUAL:
+ case OTRL_POLICY_MANUAL_MOD:
+ return TranslateT(LANG_POLICY_MANUAL);
+ break;
+ case OTRL_POLICY_ALWAYS:
+ return TranslateT(LANG_POLICY_ALWAYS);
+ break;
+ }
+ return TranslateT(LANG_POLICY_DEFAULT);
+}
+
+OtrlPolicy policy_from_string(const TCHAR *polstring) {
+ if (_tcscmp(polstring, TranslateT(LANG_POLICY_NEVER)) == 0)
+ return OTRL_POLICY_NEVER;
+ else if (_tcscmp(polstring, TranslateT(LANG_POLICY_OPP)) == 0)
+ return OTRL_POLICY_OPPORTUNISTIC;
+ else if (_tcscmp(polstring, TranslateT(LANG_POLICY_MANUAL)) == 0)
+ return OTRL_POLICY_MANUAL_MOD;
+ else if (_tcscmp(polstring, TranslateT(LANG_POLICY_ALWAYS)) == 0)
+ return OTRL_POLICY_ALWAYS;
+ else
+ return CONTACT_DEFAULT_POLICY;
+} \ No newline at end of file
diff --git a/MirOTR/utils.h b/MirOTR/utils.h
new file mode 100644
index 0000000..ac1ad1b
--- /dev/null
+++ b/MirOTR/utils.h
@@ -0,0 +1,47 @@
+#pragma once
+#ifndef __HEADER_UTILS_H
+#define __HEADER_UTILS_H
+#include "stdafx.h"
+
+
+void lib_cs_lock();
+void lib_cs_unlock();
+
+HANDLE find_contact(const char* userid, const char* protocol);
+ConnContext * otrl_context_find_miranda(OtrlUserState us, HANDLE hContact);
+
+typedef enum {
+ TRUST_NOT_PRIVATE,
+ TRUST_FINISHED,
+ TRUST_UNVERIFIED,
+ TRUST_PRIVATE
+} TrustLevel;
+TrustLevel otr_context_get_trust(ConnContext *context);
+
+void otrl_privkey_hash_to_humanT(TCHAR human[45], const unsigned char hash[20]);
+
+char* contact_get_id(HANDLE hContact, bool bNameOnError=true);
+__inline const char* contact_get_proto(HANDLE hContact);
+__inline const char* contact_get_account(HANDLE hContact);
+extern __inline const TCHAR* contact_get_nameT(HANDLE hContact);
+
+void ShowPopup(const TCHAR* line1, const TCHAR* line2, int timeout, const HANDLE hContact = NULL);
+void ShowWarning(TCHAR* msg);
+void ShowError(TCHAR* msg);
+void ShowPopupUtf(const char* line1, const char* line2, int timeout, const HANDLE hContact = NULL);
+void ShowWarningUtf(char* msg);
+void ShowErrorUtf(char* msg);
+
+void ShowMessageInline(const HANDLE hContact, const TCHAR *msg);
+void ShowMessageInlineUtf(const HANDLE hContact, const char *msg);
+
+void ShowMessage(const HANDLE hContact, const TCHAR *msg);
+void ShowMessageUtf(const HANDLE hContact, const char *msg);
+
+void InitUtils();
+void DeinitUtils();
+
+const TCHAR *policy_to_string(OtrlPolicy policy);
+OtrlPolicy policy_from_string(const TCHAR *polstring);
+
+#endif \ No newline at end of file
diff --git a/MirOTR/version.h b/MirOTR/version.h
new file mode 100644
index 0000000..bdfa60a
--- /dev/null
+++ b/MirOTR/version.h
@@ -0,0 +1,37 @@
+#ifndef OTR_PRIVATE_H
+#define OTR_PRIVATE_H
+
+/* VERSION DEFINITIONS */
+#define VER_MAJOR 0
+#define VER_MINOR 8
+#define VER_RELEASE 6
+#define VER_BUILD 1
+
+#define __STRINGIZE(x) #x
+#define VER_STRING "0.8.6.1"
+
+#ifdef _UNICODE
+ #define SHORT_NAME_STRING "Miranda OTR"
+ #define DESC_STRING "OTR (Off-the-Record) plugin for Miranda IM"
+#else
+ #define SHORT_NAME_STRING "Miranda OTR (ANSI)"
+ #define DESC_STRING "OTR (Off-the-Record) plugin for Miranda IM (ANSI)"
+#endif
+#define LONGDESC_STRING DESC_STRING" ("__DATE__")\r\n(using some code and ideas from SecureIM, Pidgin-OTR and old Miranda OTR (by SJE))"
+#define COMPANY_NAME ""
+#define FILE_VERSION VER_STRING
+#define FILE_DESCRIPTION DESC_STRING
+#define INTERNAL_NAME ""
+#define LEGAL_COPYRIGHT "© ProgAndy"
+#define LEGAL_COPYRIGHT_LONG "© ProgAndy"
+#define LEGAL_TRADEMARKS ""
+#define ORIGINAL_FILENAME "mirotr.dll"
+#define PRODUCT_NAME DESC_STRING
+#define PRODUCT_VERSION VER_STRING
+
+
+#define AUTHOR "ProgAndy"
+#define AUTHOR_MAIL ""
+#define HOMEPAGE "http://progandy.co.cc"
+
+#endif /*OTR_PRIVATE_H*/