summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xplugins/Msg_Export/msg_export_10.vcxproj162
-rwxr-xr-xplugins/Msg_Export/msg_export_10.vcxproj.filters63
-rwxr-xr-xplugins/Msg_Export/res/export_m.icobin0 -> 9062 bytes
-rwxr-xr-xplugins/Msg_Export/res/langpack_msg_export.txt325
-rwxr-xr-xplugins/Msg_Export/res/notick.icobin0 -> 318 bytes
-rwxr-xr-xplugins/Msg_Export/res/resource.rc327
-rwxr-xr-xplugins/Msg_Export/res/tick.icobin0 -> 318 bytes
-rwxr-xr-xplugins/Msg_Export/src/FileViewer.cpp1424
-rwxr-xr-xplugins/Msg_Export/src/FileViewer.h38
-rwxr-xr-xplugins/Msg_Export/src/Glob.h29
-rwxr-xr-xplugins/Msg_Export/src/main.cpp404
-rwxr-xr-xplugins/Msg_Export/src/options.cpp1483
-rwxr-xr-xplugins/Msg_Export/src/options.h26
-rwxr-xr-xplugins/Msg_Export/src/resource.h59
-rwxr-xr-xplugins/Msg_Export/src/utils.cpp1738
-rwxr-xr-xplugins/Msg_Export/src/utils.h125
-rwxr-xr-xplugins/New_GPG/Makefile23
-rwxr-xr-xplugins/New_GPG/README6
-rwxr-xr-xplugins/New_GPG/dependencies/include/utf8.h34
-rwxr-xr-xplugins/New_GPG/dependencies/include/utf8/checked.h327
-rwxr-xr-xplugins/New_GPG/dependencies/include/utf8/core.h329
-rwxr-xr-xplugins/New_GPG/dependencies/include/utf8/unchecked.h228
-rwxr-xr-xplugins/New_GPG/new_gpg_10.vcxproj1031
-rwxr-xr-xplugins/New_GPG/new_gpg_10.vcxproj.filters103
-rwxr-xr-xplugins/New_GPG/new_gpg_lang_ru.txt115
-rwxr-xr-xplugins/New_GPG/res/icons/secured.icobin0 -> 2550 bytes
-rwxr-xr-xplugins/New_GPG/res/icons/unsecured.icobin0 -> 2550 bytes
-rwxr-xr-xplugins/New_GPG/res/new_gpg.rc419
-rwxr-xr-xplugins/New_GPG/src/clist.cpp41
-rwxr-xr-xplugins/New_GPG/src/commonheaders.h88
-rwxr-xr-xplugins/New_GPG/src/constants.h5
-rwxr-xr-xplugins/New_GPG/src/globals.h22
-rwxr-xr-xplugins/New_GPG/src/gpg_wrapper.cpp163
-rwxr-xr-xplugins/New_GPG/src/gpg_wrapper.h50
-rwxr-xr-xplugins/New_GPG/src/icons.cpp152
-rwxr-xr-xplugins/New_GPG/src/init.cpp288
-rwxr-xr-xplugins/New_GPG/src/jabber_account.cpp85
-rwxr-xr-xplugins/New_GPG/src/jabber_account.h43
-rwxr-xr-xplugins/New_GPG/src/log.cpp91
-rwxr-xr-xplugins/New_GPG/src/log.h35
-rwxr-xr-xplugins/New_GPG/src/m_extraicons.h158
-rwxr-xr-xplugins/New_GPG/src/m_metacontacts.h166
-rwxr-xr-xplugins/New_GPG/src/main.cpp2305
-rwxr-xr-xplugins/New_GPG/src/main.h31
-rwxr-xr-xplugins/New_GPG/src/messages.cpp1058
-rwxr-xr-xplugins/New_GPG/src/metacontacts.cpp88
-rwxr-xr-xplugins/New_GPG/src/metacontacts.h24
-rwxr-xr-xplugins/New_GPG/src/options.cpp1387
-rwxr-xr-xplugins/New_GPG/src/resource.h96
-rwxr-xr-xplugins/New_GPG/src/srmm.cpp88
-rwxr-xr-xplugins/New_GPG/src/utilities.cpp1824
-rwxr-xr-xplugins/New_GPG/src/utilities.h104
52 files changed, 17210 insertions, 0 deletions
diff --git a/plugins/Msg_Export/msg_export_10.vcxproj b/plugins/Msg_Export/msg_export_10.vcxproj
new file mode 100755
index 0000000000..59f399d181
--- /dev/null
+++ b/plugins/Msg_Export/msg_export_10.vcxproj
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="src\FileViewer.cpp" />
+ <ClCompile Include="src\main.cpp" />
+ <ClCompile Include="src\options.cpp" />
+ <ClCompile Include="src\utils.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\FileViewer.h" />
+ <ClInclude Include="src\Glob.h" />
+ <ClInclude Include="src\options.h" />
+ <ClInclude Include="src\resource.h" />
+ <ClInclude Include="src\utils.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="res\export_m.ico" />
+ <None Include="res\notick.ico" />
+ <None Include="res\tick.ico" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\resource.rc" />
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{4CE78D43-FF23-4134-A5AC-B2CF0F8D9F3B}</ProjectGuid>
+ <RootNamespace>msg_export</RootNamespace>
+ <ProjectName>msg_export</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</GenerateManifest>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</IgnoreImportLibrary>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</GenerateManifest>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Release/msg_export.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MinSpace</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);_CRT_SECURE_NO_DEPRECATE;UNICODE;_UNICODE</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <AdditionalIncludeDirectories>..\..\include;..\..\plugins\ExternalAPI;libgadu;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalOptions>/filealign:0x200 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
+ <BaseAddress>0x22100000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\msg_export___Win32_Debug/msg_export.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_DEBUG;WIN32;_WINDOWS;%(PreprocessorDefinitions);_CRT_SECURE_NO_DEPRECATE;UNICODE;_UNICODE</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <BrowseInformation>true</BrowseInformation>
+ <WarningLevel>Level4</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <AdditionalIncludeDirectories>..\..\include;..\..\plugins\ExternalAPI;libgadu;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalOptions>/filealign:0x200 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <BaseAddress>0x22100000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <TargetMachine>MachineX86</TargetMachine>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ </Link>
+ </ItemDefinitionGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/Msg_Export/msg_export_10.vcxproj.filters b/plugins/Msg_Export/msg_export_10.vcxproj.filters
new file mode 100755
index 0000000000..ada2a79e40
--- /dev/null
+++ b/plugins/Msg_Export/msg_export_10.vcxproj.filters
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{8b9237c4-9104-49cd-9e02-a216d059bfb6}</UniqueIdentifier>
+ <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{f8f2c8ef-4b67-43be-b1c4-cf53c2e15bd7}</UniqueIdentifier>
+ <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
+ </Filter>
+ <Filter Include="Headers">
+ <UniqueIdentifier>{a4d03f87-3170-4821-9a81-648b77757e88}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="src\FileViewer.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\main.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\options.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\utils.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\FileViewer.h">
+ <Filter>Headers</Filter>
+ </ClInclude>
+ <ClInclude Include="src\Glob.h">
+ <Filter>Headers</Filter>
+ </ClInclude>
+ <ClInclude Include="src\options.h">
+ <Filter>Headers</Filter>
+ </ClInclude>
+ <ClInclude Include="src\resource.h">
+ <Filter>Headers</Filter>
+ </ClInclude>
+ <ClInclude Include="src\utils.h">
+ <Filter>Headers</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="res\export_m.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\notick.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\tick.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\resource.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/Msg_Export/res/export_m.ico b/plugins/Msg_Export/res/export_m.ico
new file mode 100755
index 0000000000..5f85a18803
--- /dev/null
+++ b/plugins/Msg_Export/res/export_m.ico
Binary files differ
diff --git a/plugins/Msg_Export/res/langpack_msg_export.txt b/plugins/Msg_Export/res/langpack_msg_export.txt
new file mode 100755
index 0000000000..2397ac0acb
--- /dev/null
+++ b/plugins/Msg_Export/res/langpack_msg_export.txt
@@ -0,0 +1,325 @@
+;; ====== Message Export ===========
+; This file contains all the strings used in the Message Export
+; plugin.
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Contact menu item
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+[Open E&xported History]
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Main options Tree
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+[Plugins]
+[Message export]
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Main options dialog
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Static
+[Export directory]
+[Browse]
+[Default file]
+[Export format]
+[Max column width]
+[Time format]
+
+; ListCtrl
+[File]
+[Nick]
+[UIN]
+
+; Buttons
+[Auto filename]
+[Clear all]
+[Help]
+[Export all history]
+
+; Errors / Questions
+[You have unapplyed changes do you wish to apply these first ?]
+[No contacts found to export]
+[Failed to export at least one contact]
+[Max line width must be at least %d]
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Dialog Export all, Progress bar
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+[Exporting old messages]
+[Reading database information ( Phase 1 of 2 )]
+[Sorting and writing database information ( Phase 2 of 2 )]
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Folder Browse dialog
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+[Select Destination Directory]
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Strings written to export file
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+[The following user added you to their contact list:]
+[The following user made an authorization request:]
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; General Error dialogs
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+[Message has not been saved !]
+[Failed to get the path to Msg_Export.dll\nPlease locate Msg_Export.txt your self]
+[Failed to move to the end of the file :\n]
+[Failed to open or create file :\n]
+
+;/////////////////////
+;// Version 1.4.0 //
+;/////////////////////
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Strings written to export file
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+[The following user added you to their contact list:]
+[The following user made an authorization request:]
+[Nick :]
+[FirstName :]
+[LastName :]
+[e-mail :]
+[Reason :]
+
+; Errors
+
+;/////////////////////
+;// Version 1.4.1 //
+;/////////////////////
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; General Error dialogs
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+[Failed to write message to the file :\n]
+[Failed to write URL/File to the file :\n]
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Strings written to export file
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+[URL: ]
+[File: ]
+[Description: ]
+
+
+;/////////////////////
+;// Version 1.5.0 //
+;/////////////////////
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Strings written to export file
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+[EmailExpress from:]
+[No from address]
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; General Error dialogs
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+[Failed to write EmailExpress to the file :\n]
+
+
+;/////////////////////
+;// Version 1.6.0 //
+;/////////////////////
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; General Error dialogs
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+[Failed to write SMS to the file :\n]
+
+
+
+;/////////////////////
+;// Version 1.7.0 //
+;/////////////////////
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Main options dialog
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+[Replace miranda history]
+[Use internal viewer]
+[You need to restart miranda to change the history function]
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; File Viewer dialog
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+[History file for %s (%s)]
+[Find...]
+[Close]
+[External]
+
+[Search string was not found !]
+
+;/////////////////////
+;// Version 1.8.0 //
+;/////////////////////
+
+[File name for the user \"%s\" has changed !\n\nfrom:\t%s\nto:\t%s\n\nDo you wish to rename file ?]
+[Failed to rename file\n\nfrom:\t%s\nto:\t%s\n\nFailed with error: %s]
+[&Yes]
+[Yes to &All]
+[&No]
+[No to A&ll]
+
+;/////////////////////
+;// Version 1.9.0 //
+;/////////////////////
+
+; File Viewer menu item
+[Color...]
+
+;/////////////////////
+;// Version 1.9.1 //
+;/////////////////////
+
+; File Viewer menu item
+[Font...]
+
+
+;/////////////////////
+;// Version 1.9.5 //
+;/////////////////////
+
+; Errors / Questions
+[Failed to delete the file]
+
+
+;/////////////////////
+;// Version 1.9.6 //
+;/////////////////////
+
+Removed : [Failed to read ProfileDir from mirandaboot.ini]
+Removed : [Failed to get path to Miranda.exe]
+
+;/////////////////////
+;// Version 1.9.7 //
+;/////////////////////
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Main options dialog
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+[Prompt to delete file]
+
+
+;/////////////////////
+;// Version 1.9.8 //
+;/////////////////////
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; General Error dialogs
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+[Failed to replace Miranda History.\r\nThis is most likely due to changes in Miranda.]
+
+
+;/////////////////////
+;// Version 2.0.1 //
+;/////////////////////
+
+Removed : [Unknowen event type %d, size %d]
+Removed : [Invalid Database event received. Type %d, size %d]
+Removed : [User has been deleted do you want to delete the file ?\r\n%s]
+Removed : [Failed to HookEvent ME_DB_EVENT_ADDED]
+Removed : [Failed to HookEvent ME_OPT_INITIALISE]
+Removed : [Failed to HookEvent ME_SYSTEM_MODULESLOADED]
+Removed : [Failed to add menu item Open Exported History\nCallService(MS_CLIST_ADDCONTACTMENUITEM,...)]
+Removed : [Failed to CreateServiceFunction MS_SHOW_EXPORT_HISTORY]
+Removed : [Failed to get the shells allocator !]
+Removed : [Failed to Allocate buffer space]
+
+; Errors / Questions
+[User has been deleted do you want to delete the file ?]
+
+;///////////////////////
+;// Version 2.03.00 //
+;///////////////////////
+
+; File Viewer menu item
+[Syntax highlight]
+
+
+;///////////////////////
+;// Version 2.04.00 //
+;///////////////////////
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Main options dialog
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+[File viewer]
+[Append extra new line]
+
+
+;///////////////////////
+;// Version 2.05.00 //
+;///////////////////////
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Strings written to export file
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+[WebPager from:]
+
+;///////////////////////
+;// Version 2.06.00 //
+;///////////////////////
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Main options dialog
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; ListCtrl right click menu
+[User &Details]
+; These were not added in 2.06.00 but were forgotten in previous versions.
+[Export selected]
+[Set to default filename]
+
+;///////////////////////
+;// Version 2.09.00 //
+;///////////////////////
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Main options dialog
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+[Use << and >>]
+
+
+;///////////////////////
+;// Version 2.12.00 //
+;///////////////////////
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Main options dialog
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+Removed : [User has been deleted do you want to delete the file ?]
+
+[When filename changes]
+[When user is deleted]
+[Prompt for action]
+[Rename file]
+[Do nothing]
+[Delete file]
+
+
+;///////////////////////
+;// Version 2.15.00 //
+;///////////////////////
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Main options dialog
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+[Export Protocols]
+
+
+;///////////////////////
+;// Version 3.00.00 //
+;///////////////////////
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Main options dialog
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+[Use UTF8 in new files] \ No newline at end of file
diff --git a/plugins/Msg_Export/res/notick.ico b/plugins/Msg_Export/res/notick.ico
new file mode 100755
index 0000000000..4ff17dfa7b
--- /dev/null
+++ b/plugins/Msg_Export/res/notick.ico
Binary files differ
diff --git a/plugins/Msg_Export/res/resource.rc b/plugins/Msg_Export/res/resource.rc
new file mode 100755
index 0000000000..cb3a5fd4e0
--- /dev/null
+++ b/plugins/Msg_Export/res/resource.rc
@@ -0,0 +1,327 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "src/resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include <windows.h>
+#include <richedit.h>
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Neutral (Default) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEUD)
+#ifdef _WIN32
+LANGUAGE LANG_NEUTRAL, SUBLANG_DEFAULT
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 3,1,0,3
+ PRODUCTVERSION 3,1,0,3
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "Comments", "Message export plugin for Miranda IM (mod by ring0)"
+ VALUE "CompanyName", "Tip Top Tools"
+ VALUE "FileDescription", "Message export"
+ VALUE "FileVersion", "3, 1, 0, 3"
+ VALUE "InternalName", "Msg_export"
+ VALUE "LegalCopyright", "© 2002 Kennet Nielsen, mod by ring0"
+ VALUE "OriginalFilename", "Msg_Export"
+ VALUE "ProductName", "Message export (mod by ring0)"
+ VALUE "ProductVersion", "3, 1, 0, 3"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END
+
+#endif // Neutral (Default) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Danish resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DAN)
+#ifdef _WIN32
+LANGUAGE LANG_DANISH, SUBLANG_DEFAULT
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ ID_EDIT_COPY "Copies the selection and puts it on the Clipboard\nCopy"
+END
+
+#endif // Danish resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// German (Germany) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU)
+#ifdef _WIN32
+LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include <windows.h>\r\n"
+ "#include <richedit.h>\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // German (Germany) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_OPT_MSGEXPORT DIALOGEX 0, 0, 314, 240
+STYLE DS_SETFONT | DS_3DLOOK | DS_CENTER | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ COMBOBOX IDC_EXPORT_DIR,11,12,125,114,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "Browse",IDC_EXPORT_DIR_BROWSE,141,11,43,14
+ COMBOBOX IDC_DEFAULT_FILE,53,29,83,112,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP
+ CONTROL "Use internal viewer",IDC_USE_INTERNAL_VIEWER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,61,76,10
+ CONTROL "Replace miranda history",IDC_REPLACE_MIRANDA_HISTORY,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,96,61,91,10
+ COMBOBOX IDC_FILE_VIEWER,11,75,125,89,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "Browse",IDC_FILE_VIEWER_BROWSE,141,74,43,14
+ EDITTEXT IDC_MAX_CLOUMN_WIDTH,264,11,39,14,ES_AUTOHSCROLL | ES_NUMBER
+ COMBOBOX IDC_EXPORT_TIMEFORMAT,246,29,57,122,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP
+ CONTROL "Use UTF8 in new files",IDC_USE_UTF8_IN_NEW_FILES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,201,46,85,10
+ CONTROL "Append extra new line",IDC_APPEND_NEWLINE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,201,59,86,10
+ CONTROL "Use << and >>",IDC_USE_LESS_AND_GREATER_IN_EXPORT,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,201,72,63,10
+ CONTROL "List1",IDC_MAP_USER_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_EDITLABELS | WS_BORDER | WS_TABSTOP,5,100,304,120
+ PUSHBUTTON "Auto filename",IDC_AUTO_FILENAME,5,226,63,14
+ PUSHBUTTON "Clear all",IDC_CLEAR_ALL,86,226,63,14
+ PUSHBUTTON "Help",IDC_OPEN_HELP,161,226,63,14
+ PUSHBUTTON "Export all history",IDC_EXPORTALL,242,226,63,14
+ GROUPBOX "Export directory",IDC_STATIC,5,0,186,46
+ LTEXT "Max column width",IDC_STATIC,201,14,58,8
+ LTEXT "Time format",IDC_STATIC,201,31,38,8
+ GROUPBOX "Export format",IDC_STATIC,195,0,114,94
+ LTEXT "Default file",IDC_STATIC,11,32,34,8
+ GROUPBOX "File viewer",IDC_STATIC,5,49,186,45
+END
+
+IDD_EXPORT_ALL_DLG DIALOGEX 0, 0, 252, 46
+STYLE DS_SETFONT | WS_POPUP | WS_CAPTION
+EXSTYLE WS_EX_TOOLWINDOW
+CAPTION "Exporting old messages"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "Progress1",IDC_EXPORT_PROGRESS,"msctls_progress32",WS_BORDER,7,7,238,15
+ LTEXT "",IDC_EXP_ALL_STATUS,7,31,238,8
+END
+
+IDD_FILE_VIEWER DIALOG 0, 0, 346, 259
+STYLE DS_SETFONT | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
+CAPTION "History file for %s (%s format %s)"
+FONT 8, "MS Sans Serif"
+BEGIN
+ CONTROL "",IDC_RICHEDIT,"RICHEDIT",TCS_HOTTRACK | TCS_VERTICAL | TCS_BUTTONS | TCS_RAGGEDRIGHT | TCS_MULTISELECT | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP,6,7,333,224
+ PUSHBUTTON "&Find...",IDC_FV_FIND,46,238,50,14
+ PUSHBUTTON "&External",IDC_FV_EXTERNAL,142,238,50,14
+ DEFPUSHBUTTON "&Close",IDOK,246,238,50,14
+END
+
+IDD_OPT_MSGEXPORT2 DIALOGEX 0, 0, 314, 240
+STYLE DS_SETFONT | DS_3DLOOK | DS_CENTER | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+ CONTROL "Prompt for action",IDC_FC_PROMPT,"Button",BS_AUTORADIOBUTTON | WS_GROUP,51,53,69,10
+ GROUPBOX "When filename changes",IDC_STATIC,43,38,100,56
+ CONTROL "Rename file",IDC_FC_RENAME,"Button",BS_AUTORADIOBUTTON,51,66,53,10
+ CONTROL "Do nothing",IDC_FC_NOTHING,"Button",BS_AUTORADIOBUTTON,51,79,51,10
+ GROUPBOX "When user is deleted",IDC_STATIC,171,39,100,56
+ CONTROL "Prompt for action",IDC_FD_PROMPT,"Button",BS_AUTORADIOBUTTON | WS_GROUP,180,53,69,10
+ CONTROL "Delete file",IDC_FD_DELETE,"Button",BS_AUTORADIOBUTTON,180,66,47,10
+ CONTROL "Do nothing",IDC_FD_NOTHING,"Button",BS_AUTORADIOBUTTON,180,79,51,10
+ CONTROL "List1",IDC_EXPORT_PROTOS,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_EDITLABELS | WS_BORDER | WS_TABSTOP,44,101,227,106
+ PUSHBUTTON "Debug",IDC_DEBUG_INFO,237,214,32,10
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_OPT_MSGEXPORT, DIALOG
+ BEGIN
+ RIGHTMARGIN, 313
+ VERTGUIDE, 5
+ VERTGUIDE, 11
+ VERTGUIDE, 136
+ VERTGUIDE, 141
+ VERTGUIDE, 201
+ VERTGUIDE, 303
+ VERTGUIDE, 309
+ HORZGUIDE, 18
+ HORZGUIDE, 36
+ HORZGUIDE, 46
+ HORZGUIDE, 66
+ END
+
+ IDD_EXPORT_ALL_DLG, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 245
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 39
+ END
+
+ IDD_FILE_VIEWER, DIALOG
+ BEGIN
+ LEFTMARGIN, 6
+ RIGHTMARGIN, 339
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 252
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_EXPORT_MESSAGE ICON "export_m.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_MSG_EXPORT MENU
+BEGIN
+ POPUP "UserList"
+ BEGIN
+ MENUITEM "User &Details", ID_USERLIST_USERDETAILS
+ MENUITEM "Export selected", ID_EXPORTSELECTED
+ MENUITEM "Set to default filename", ID_SET_TO_DEFAULT
+ MENUITEM SEPARATOR
+ MENUITEM "Auto filename", IDC_AUTO_FILENAME
+ MENUITEM "Clear all", IDC_CLEAR_ALL
+ END
+END
+
+IDR_FV_EDIT MENU
+BEGIN
+ POPUP "1"
+ BEGIN
+ MENUITEM "Copy", ID_EDIT_COPY
+ END
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.K.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_TICK ICON "tick.ico"
+IDI_NOTICK ICON "notick.ico"
+#endif // English (U.K.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/plugins/Msg_Export/res/tick.ico b/plugins/Msg_Export/res/tick.ico
new file mode 100755
index 0000000000..d24d6adbbf
--- /dev/null
+++ b/plugins/Msg_Export/res/tick.ico
Binary files differ
diff --git a/plugins/Msg_Export/src/FileViewer.cpp b/plugins/Msg_Export/src/FileViewer.cpp
new file mode 100755
index 0000000000..191f744571
--- /dev/null
+++ b/plugins/Msg_Export/src/FileViewer.cpp
@@ -0,0 +1,1424 @@
+
+//This file is part of Msg_Export a Miranda IM plugin
+//Copyright (C)2002 Kennet Nielsen ( http://sourceforge.net/projects/msg-export/ )
+//
+//This program is free software; you can redistribute it and/or
+//modify it under the terms of the GNU General Public License
+//as published by the Free Software Foundation; either
+//version 2 of the License, or (at your option) any later version.
+//
+//This program is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//GNU General Public License for more details.
+//
+//You should have received a copy of the GNU General Public License
+//along with this program; if not, write to the Free Software
+//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+#include <windows.h>
+#include <Richedit.h>
+
+#include <iostream>
+#include <fstream>
+
+using namespace std;
+
+
+#include "Utils.h"
+#include "Glob.h"
+#include "FileViewer.h"
+
+#include "resource.h"
+
+#include <stdio.h>
+#include <basetsd.h>
+
+//#include <map>
+
+#define szFileViewDB "FileV_"
+
+#define WM_RELOAD_FILE (WM_USER+10)
+
+using namespace std;
+
+static UINT UM_FIND_CMD = RegisterWindowMessage( FINDMSGSTRING );
+
+#define ID_FV_FONT 0x0010
+#define ID_FV_COLOR 0x0020
+#define ID_FV_SYNTAX_HL 0x0030
+#define ID_FV_SAVE_AS_RTF 0x0040
+// ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
+// ASSERT(IDM_ABOUTBOX < 0xF000);
+
+
+// Specifies if history is opened internaly or externaly
+bool bUseIntViewer = true;
+
+// External program used to view files
+tstring sFileViewerPrg;
+
+// handle to the RichEditDll. We need to load this dll to use a RichEdit.
+HMODULE hRichEditDll = NULL;
+
+
+#define CONT(i) ((in[i]&0xc0) == 0x80)
+#define VAL(i, s) ((in[i]&0x3f) << s)
+
+void swap(char &c1, char &c2) {
+ char ch;
+ ch=c1;
+ c1=c2;
+ c2=ch;
+}
+
+int DecodeUTF8(const char *pcBuff,int /*iBufSize*/,char *pcOutBuf) {
+ int iBytesInOut=0;
+ int /*cp,*/i;
+ char ch,*p;
+
+//Parse UTF-8 sequence
+//Support only chars up to three bytes (UCS-4 - go away!)
+//Warning: Partial decoding is possible!
+ i=0;
+ ch=pcBuff[i];
+ if(!(ch&0x80)) {
+ pcOutBuf[iBytesInOut++]=ch;
+ pcOutBuf[iBytesInOut++]='\0';
+ }
+ else if(!(ch&0x20)) {
+ pcOutBuf[iBytesInOut++]=(ch>>2)&0x07;
+ i++;
+ pcOutBuf[iBytesInOut++]=(pcBuff[i]&0x3F)|(ch<<6);
+ swap(pcOutBuf[iBytesInOut-1],pcOutBuf[iBytesInOut-2]);
+ }
+ else if(!(ch&0x10)) {
+ i++;
+
+ pcOutBuf[iBytesInOut++]=(ch<<4)|((pcBuff[i]>>2)&0x0F);
+ ch=pcBuff[i];
+ i++;
+ pcOutBuf[iBytesInOut++]=(pcBuff[i]&0x3F)|(ch<<6);
+ swap(pcOutBuf[iBytesInOut-1],pcOutBuf[iBytesInOut-2]);
+ }
+ else {
+ p=(char*)&pcBuff[i];
+ pcOutBuf[iBytesInOut++]='\x3F';
+ pcOutBuf[iBytesInOut++]='\0';
+ if(!(ch&0x08)) i+=3;
+ else if(!(ch&0x04)) i+=4;
+ else if(!(ch&0x02)) i+=5;
+ }
+
+ i++;
+
+ return i;
+}
+
+
+int __utf8_get_char(const char *in, int *chr)
+{ /* 2-byte, 0x80-0x7ff */
+ return DecodeUTF8(in,256,(char *)chr);
+}
+
+// there is one instance of CLHistoryDlg for every history dialog on screeen.
+class CLHistoryDlg
+{
+ public:
+ HWND hWnd;
+
+ HANDLE hContact;
+ tstring sPath;
+
+ WNDPROC wpOrigEditProc;
+
+ HWND hFindDlg;
+ FINDREPLACE fr;
+ _TCHAR acFindStr[100];
+
+ bool bFirstLoad;
+ bool bUtf8File;
+
+ CLHistoryDlg( HANDLE hContact ) : hContact( hContact )
+ {
+ hFindDlg = NULL;
+ acFindStr[0] = 0;
+ ZeroMemory( &fr , sizeof( fr ));
+ fr.lStructSize = sizeof( fr );
+ fr.hInstance = hInstance;
+ fr.Flags = FR_NOUPDOWN|FR_HIDEUPDOWN;//|FR_MATCHCASE|FR_WHOLEWORD;
+ // FR_DOWN|FR_FINDNEXT|FR_NOMATCHCASE;
+ fr.lpstrFindWhat = acFindStr;
+ fr.wFindWhatLen = sizeof(acFindStr);
+ bFirstLoad = true;
+ bUtf8File = false;
+ }
+};
+
+// List of all open history windows
+list< CLHistoryDlg* > clHistoryDlgList;
+// CRITICAL_SECTION used to access the window list
+// this is nesery because UpdateFileViews is called from callback thread.
+CRITICAL_SECTION csHistoryList;
+
+
+// CLStreamRTFInfo is used when reading RTF into rich edit from a stream.
+// RTF is used when Syntax highlighting is used.
+class CLStreamRTFInfo
+{
+ private:
+ HANDLE hFile;
+ bool bHeaderWriten;
+ bool bTailWriten;
+ bool bCheckFirstForNick;
+ bool bLastColorMyNick;
+
+ // buffer size supplyed on win XP 4092 byte when streamin in
+ // optimal size it to fully use this buffer but we can guess
+ // how may bytes need converting in the file we are reading.
+ BYTE abBuf[3300];
+ char szMyNick[100];
+ int nNickLen;
+ static int nOptimalReadLen;
+
+ int nWriteHeader( char * pszTarget , int nLen );
+ public:
+ bool bUtf8File;
+ CLStreamRTFInfo( HANDLE hFile )
+ {
+ this->hFile = hFile;
+ bHeaderWriten = false;
+ bTailWriten = false;
+ bCheckFirstForNick = false;
+ bLastColorMyNick = false;
+ bUtf8File = false;
+ nNickLen = 0;
+ }
+ int nLoadFileStream( LPBYTE pbBuff , LONG cb );
+};
+int CLStreamRTFInfo::nOptimalReadLen = 3300;
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : nWriteHeader
+// Type : Private / Public / Protected
+// Parameters : pszTarget - ?
+// nLen - ?
+// Returns : int
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 030204 , 04 February 2003
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+int CLStreamRTFInfo::nWriteHeader( char * pszTarget , int nLen )
+{
+ COLORREF cMyText = DBGetContactSettingDword(NULL,"SRMsg","Font3Col",RGB(64,0,128));
+ COLORREF cYourText = DBGetContactSettingDword(NULL,"SRMsg","Font0Col",RGB(240,0,0));
+
+/* original header !!
+ "{\\rtf1\\ansi\\deff0{\\fonttbl{\\f0\\fnil\\fcharset0 Courier New;}}\r\n"
+ "{\\colortbl ;\\red%d\\green%d\\blue%d;\\red%d\\green%d\\blue%d;}\r\n"
+ "\\viewkind4\\uc1\\pard\\cf2\\lang1033\\f0\\fs16 " ,
+
+*/
+ char szRtfHeader[400];
+ int nSrcLen = _snprintf( szRtfHeader , sizeof( szRtfHeader ) ,
+ "{\\rtf1\\ansi\r\n"
+ "{\\colortbl ;\\red%d\\green%d\\blue%d;\\red%d\\green%d\\blue%d;}\r\n"
+ "\\viewkind4\\uc1\\pard\\cf2 " ,
+ GetRValue( cMyText ) ,GetGValue( cMyText ) ,GetBValue( cMyText ) ,
+ GetRValue( cYourText ) ,GetGValue( cYourText ) ,GetBValue( cYourText ) );
+
+ if( nSrcLen > nLen )
+ {
+ MessageBox( NULL , _T("Failed to write to the RichEdit the buffer was to small."),MSG_BOX_TITEL,MB_OK );
+ return 0; // target buffer to small
+ }
+
+ memcpy( pszTarget , szRtfHeader , nSrcLen );
+ bHeaderWriten = true;
+ return nSrcLen;
+}
+
+const char szNewLine[] = "\n\\par ";
+const char szRtfEnd[] = "\r\n\\par }\r\n\0";
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : nLoadFileStream
+// Type : Private / Public / Protected
+// Parameters : pbBuff - ?
+// cb - ?
+// Returns : int
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 030204 , 04 February 2003
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+int CLStreamRTFInfo::nLoadFileStream( LPBYTE pbBuff , LONG cb )
+{
+ if( bTailWriten )
+ return 0;
+
+ if( nOptimalReadLen < 500 )
+ {
+ MessageBox( NULL , _T("Error: Optimal buffer size decrecied to a to low size !!"),MSG_BOX_TITEL,MB_OK );
+ return 0;
+ }
+
+ DWORD dwRead;
+ DWORD dwToRead = nOptimalReadLen;
+
+ if( ! ReadFile(hFile , abBuf, dwToRead , &dwRead, (LPOVERLAPPED)NULL) )
+ return 0;
+
+ DWORD dwCurrent = 0;
+ DWORD n = 0;
+ if( ! bHeaderWriten )
+ {
+ if( dwRead >= 3 )
+ {
+ bUtf8File = bIsUtf8Header( abBuf );
+ if( bUtf8File )
+ n = 3;
+ }
+ dwCurrent += nWriteHeader( (char*)pbBuff , cb );
+
+ tstring sMyNick = NickFromHandle(0);
+#ifdef _UNICODE
+ nNickLen = WideCharToMultiByte(bUtf8File ? CP_UTF8 : CP_ACP , 0, sMyNick.c_str(), sMyNick.length() , szMyNick , sizeof( szMyNick ), NULL , NULL );
+#else
+ strcpy( szMyNick , sMyNick.c_str() );
+ nNickLen = sMyNick.length();
+#endif
+ }
+ else
+ {
+ if( bCheckFirstForNick )
+ {
+ // Test against "<<" also
+ if( ( (memcmp( abBuf , szMyNick , nNickLen ) == 0) ||
+ (abBuf[0] == '<' && abBuf[1] == '<')
+ ) != bLastColorMyNick )
+ {
+ // we shut only get here if we need to change color !!
+ bLastColorMyNick = !bLastColorMyNick;
+ // change color
+ memcpy( &pbBuff[dwCurrent] , bLastColorMyNick ? "\\cf1 " : "\\cf2 ", 5 );
+ }
+ bCheckFirstForNick = false;
+ }
+ }
+
+ bool bIsFileEnd = dwRead < dwToRead;
+
+ for( ; n < dwRead ; n++ )
+ {
+ // worst case is a file ending with \n or a unicode letter. resulting in a big unicode string
+ // here we need szNewLine and szRtfEnd. the 10 is a small safty margin.
+ if( dwCurrent + (sizeof( szNewLine ) + sizeof( szRtfEnd ) + 10 ) > (DWORD)cb )
+ {
+ // oh no !!! we have almost reached the end of the windows supplyed buffer
+ // we are writing to. we need to abort mision *S*!!
+ // and rewinde file
+ // we will adjust the optima buffer size
+ nOptimalReadLen -= 50;
+ SetFilePointer( hFile , n - dwRead , NULL , FILE_CURRENT );
+ return dwCurrent;
+ }
+
+ if( abBuf[n] == '\n' )
+ {
+ memcpy( &pbBuff[dwCurrent] , szNewLine , sizeof( szNewLine )-1 );
+ dwCurrent += sizeof( szNewLine )-1;
+
+ if( n + 1 >= dwRead )
+ {
+ // this is an anoing case because here we have read \n as the last char in the file
+ // this means that the if the next data read from file begins with <UserNick> it has
+ // to be highlighted
+ if( !bIsFileEnd )
+ bCheckFirstForNick = true;
+ break;
+ }
+
+ if( abBuf[n+1] == ' ' || abBuf[n+1] == '\t' || abBuf[n+1] == '\r' )
+ continue;
+
+ if( n + nNickLen >= dwRead )
+ {
+ if( !bIsFileEnd )
+ {
+ // here we have a problem we haven't read this data yet
+ // the data we need to compare to is still in the file.
+ // we can't read more data from the file because the we
+ // might just move the problem. if file contains \n\n\n\n\n ...
+
+ LONG lExtraRead = (n+1) - dwRead;
+ if( lExtraRead >= 0 )
+ MessageBox( NULL , _T("Internal error !! (lExtraRead >= 0)"),MSG_BOX_TITEL,MB_OK );
+ SetFilePointer( hFile , lExtraRead , NULL , FILE_CURRENT );
+ bCheckFirstForNick = true;
+ return dwCurrent;
+ }
+
+ if( ! bLastColorMyNick )
+ continue;
+ // else the last color user was my nick
+ // we needd to change color to the other user color.
+
+
+ /* old code !!
+ DWORD dwAddedToBuf;
+ if( ! ReadFile(hFile , &abBuf[dwRead], dwNeeded , &dwAddedToBuf, (LPOVERLAPPED)NULL) )
+ return 0;
+ dwToRead += dwNeeded;
+ dwRead += dwAddedToBuf;*/
+ }
+ else
+ {
+ // the data we need is here just compare
+ if( ( ( memcmp( &abBuf[n+1] , szMyNick , nNickLen ) == 0) ||
+ ( abBuf[n+1] == '<' && abBuf[n+2] == '<')
+ ) == bLastColorMyNick )
+ continue;
+ }
+ // we shut only get here if we need to change color !!
+ bLastColorMyNick = !bLastColorMyNick;
+
+ // change color
+ memcpy( &pbBuff[dwCurrent] , bLastColorMyNick ? "\\cf1 " : "\\cf2 ", 5 );
+ dwCurrent += 5;
+ continue;
+ }
+ else if( abBuf[n] == '\\' || abBuf[n] == '}' || abBuf[n] == '{')
+ {
+ pbBuff[dwCurrent++]='\\';
+ }
+ else if( bUtf8File && (abBuf[n] & 0x80) )
+ {
+ int nValue;
+ int nLen = __utf8_get_char( (const char *)&abBuf[n] , &nValue );
+ if(nLen+n>dwRead) {
+ SetFilePointer(hFile,n-dwRead,NULL,FILE_CURRENT);
+ break;
+ }
+ dwCurrent += sprintf( (char*)&pbBuff[dwCurrent] , "\\u%d?" , nValue );
+ //continue;
+/* // Then we have an extended char in the UTF8 file.
+ // we need to convert this to UCS-2 and then to \uN in the RTF
+ int nUtf8Len = 1;
+ while( ( (n + nUtf8Len) < dwRead ) && ((abBuf[ n + nUtf8Len ] & 0xC0) == 0x80) )
+ nUtf8Len++;
+ wchar_t szWstr[2];
+ if( MultiByteToWideChar( CP_UTF8 , 0 , (char*)&abBuf[n] , nUtf8Len , szWstr , 2 ) == 1 )
+ {
+ if( (int)(szWstr[0]) != nValue )
+ __utf8_get_char( (const char *)&abBuf[n] , &nValue );
+
+// dwCurrent += sprintf( (char*)&pbBuff[dwCurrent] , "\\u%d?" , (int)(szWstr[0]) );
+// n += nUtf8Len - 1;
+// continue;
+ }*/
+ n += nLen-1;
+ continue;
+ }
+ pbBuff[dwCurrent++] = abBuf[n];
+ }
+
+ if( bIsFileEnd )
+ {// write end
+ memcpy( &pbBuff[dwCurrent] , szRtfEnd , sizeof( szRtfEnd )-1 );
+ dwCurrent += sizeof( szRtfEnd )-1;
+ bTailWriten = true;
+ }
+ //memcpy( pbBuff , abBuf , dwRead );
+ return dwCurrent;
+}
+
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : Initilize
+// Type : Global
+// Parameters : None
+// Returns : void
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 021213 , 13 December 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+void Initilize()
+{
+ InitializeCriticalSection( &csHistoryList );
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : Uninitilize
+// Type : Global
+// Parameters : None
+// Returns : void
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 021213 , 13 December 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+void Uninitilize()
+{
+ DeleteCriticalSection( &csHistoryList );
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : UpdateFileViews
+// Type : Global
+// Parameters : pszFile - File which has been updated
+// Returns : void
+// Description : Send a message to alle to windows that need updating
+//
+// References : -
+// Remarks : -
+// Created : 021213 , 13 December 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+void UpdateFileViews( const _TCHAR * pszFile )
+{
+ EnterCriticalSection( &csHistoryList );
+
+ list< CLHistoryDlg* >::const_iterator iterator;
+ for( iterator = clHistoryDlgList.begin() ; iterator != clHistoryDlgList.end() ; ++iterator )
+ {
+ CLHistoryDlg* pcl = (*iterator);
+ if( pcl->sPath == pszFile )
+ {
+ PostMessage( pcl->hWnd , WM_RELOAD_FILE , 0 , 0 );
+ }
+ }
+ LeaveCriticalSection( &csHistoryList );
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : bOpenExternaly
+// Type : Global
+// Parameters : hContact - ?
+// Returns : Returns true if
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 021010 , 10 October 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+bool bOpenExternaly( HANDLE hContact )
+{
+ tstring sPath = GetFilePathFromUser( hContact );
+
+ if( sFileViewerPrg.empty() )
+ {
+ SHELLEXECUTEINFO st = {0};
+ st.cbSize = sizeof(st);
+ st.fMask = SEE_MASK_INVOKEIDLIST;
+ st.hwnd = NULL;
+ st.lpFile = sPath.c_str();
+ st.nShow = SW_SHOWDEFAULT;
+ ShellExecuteEx(&st);
+ return true;
+ }
+ tstring sTmp = sFileViewerPrg;
+ sTmp += _T(" ");
+ sTmp += sPath;
+ //sTmp += '\"';
+
+ STARTUPINFO sStartupInfo = { 0 };
+ GetStartupInfo(&sStartupInfo); // we parse oure owne info on
+ sStartupInfo.lpTitle = (_TCHAR*)sFileViewerPrg.c_str();
+ PROCESS_INFORMATION stProcesses = {0};
+
+ if( ! CreateProcess( NULL,
+ (_TCHAR*)sTmp.c_str(),
+ NULL,
+ NULL,
+ FALSE,
+ CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP ,
+ NULL,
+ NULL,
+ &sStartupInfo,
+ &stProcesses ) )
+ {
+ DisplayLastError( _T("Faile to execute external file view") );
+ }
+ return true;
+}
+
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : bGetInternalViewer
+// Type : Global
+// Parameters : None
+// Returns : Returns true if
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 021016 , 16 October 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+bool bUseInternalViewer()
+{
+ return bUseIntViewer;
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : bUseInternalViewer
+// Type : Global
+// Parameters : bNew - ?
+// Returns : Returns true if
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 021016 , 16 October 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+bool bUseInternalViewer( bool bNew )
+{
+ bUseIntViewer = bNew;
+ if( bUseIntViewer && !hRichEditDll )
+ {
+ hRichEditDll = LoadLibraryA("RICHED32.DLL");
+ if( !hRichEditDll )
+ {
+ DisplayLastError( _T("Failed to load Rich Edit ( RICHED32.DLL )" ));
+ return false;
+ }
+ }
+ else if( !bUseIntViewer && hRichEditDll )
+ {
+ if( ::FreeLibrary(hRichEditDll) == 0 )
+ {
+ DisplayLastError( _T("Failed to unload Rich Edit ( RICHED32.DLL )") );
+ hRichEditDll = NULL;
+ return false;
+ }
+ hRichEditDll = NULL;
+ }
+ return true;
+}
+
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : RichEditStreamLoadFile
+// Type : Global
+// Parameters : dwCookie - ?
+// pbBuff - ?
+// cb - ?
+// pcb - ?
+// Returns : DWORD CALLBACK
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 021010 , 10 October 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+DWORD CALLBACK RichEditStreamLoadFile(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
+{
+ ReadFile((HANDLE)dwCookie, pbBuff, (DWORD)cb, (DWORD *)pcb, (LPOVERLAPPED)NULL);
+ return (DWORD) ( *pcb >= 0 ? NOERROR : ( *pcb = 0, E_FAIL ) );
+}
+
+DWORD CALLBACK RichEditRTFStreamLoadFile(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
+{
+ *pcb = ((CLStreamRTFInfo *)dwCookie)->nLoadFileStream( pbBuff, cb );
+ if( *pcb )
+ return NOERROR;
+ return (DWORD)E_FAIL;
+}
+
+DWORD CALLBACK RichEditStreamSaveFile(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
+{
+ WriteFile((HANDLE)dwCookie, pbBuff, cb , (DWORD*)pcb, (LPOVERLAPPED)NULL);
+ return *pcb != cb;
+}
+
+/*
+DWORD dwCurPos = 0;
+DWORD dwDataRead = 0;
+BYTE * pabFileData = NULL;
+
+DWORD CALLBACK RichEditStreamLoadFile(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
+{
+ *pcb = 0;
+ while( dwCurPos < dwDataRead && *pcb < cb )
+ {
+ pbBuff[ *pcb ] = pabFileData[ dwCurPos ];
+ dwCurPos++;
+ (*pcb)++;
+ }
+ return (DWORD) ( *pcb >= 0 ? NOERROR : ( *pcb = 0, E_FAIL ) );
+}
+*/
+/////////////////////////////////////////////////////////////////////
+// Member Function : bLoadFile
+// Type : Global
+// Parameters : hwndDlg - ?
+// hContact - ?
+// Returns : Returns true if
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 021010 , 10 October 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+bool bLoadFile( HWND hwndDlg , CLHistoryDlg * pclDlg )
+{
+ DWORD dwStart = GetTickCount();
+
+ HWND hRichEdit = GetDlgItem( hwndDlg , IDC_RICHEDIT );
+ if( ! hRichEdit )
+ {
+ MessageBox( hwndDlg , _T("Failed to get handle to RichEdit!"),MSG_BOX_TITEL,MB_OK );
+ return false;
+ }
+
+
+ HANDLE hFile = CreateFile( pclDlg->sPath.c_str() , GENERIC_READ ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE , NULL ,
+ OPEN_EXISTING , FILE_ATTRIBUTE_NORMAL , NULL );
+
+
+ if( hFile == INVALID_HANDLE_VALUE )
+ {
+ int nDBCount = CallService( MS_DB_EVENT_GETCOUNT , (WPARAM)(pclDlg->hContact) ,0 );
+ _TCHAR szTmp[1500];
+
+ if( nDBCount == -1 )
+ {
+ mir_sntprintf(szTmp, 1499, _T("Failed to open file\r\n%s\r\n\r\nContact handle is invalid") , pclDlg->sPath.c_str());
+ }
+ else
+ {
+ mir_sntprintf( szTmp , 1499, _T("Failed to open file\r\n%s\r\n\r\nMiranda database contains %d events") , pclDlg->sPath.c_str() , nDBCount );
+ }
+
+ SETTEXTEX stText = {0};
+ stText.codepage = CP_ACP;
+ SendMessage( hRichEdit , EM_SETTEXTEX, (WPARAM) &stText, (LPARAM) szTmp );
+ return false;
+ }
+
+ POINT ptOldPos;
+ SendMessage( hRichEdit , EM_GETSCROLLPOS , 0 , (LPARAM) &ptOldPos );
+
+ bool bScrollToBottom = true;
+ if( pclDlg->bFirstLoad )
+ pclDlg->bFirstLoad = false;
+ else
+ {
+ SCROLLINFO sScrollInfo = { 0 };
+ sScrollInfo.cbSize = sizeof( SCROLLINFO );
+ sScrollInfo.fMask = SIF_POS | SIF_RANGE | SIF_PAGE;
+ if( GetScrollInfo( hRichEdit,SB_VERT,&sScrollInfo) )
+ bScrollToBottom = sScrollInfo.nPos + (int)sScrollInfo.nPage + 50 > sScrollInfo.nMax;
+ }
+
+
+ HMENU hSysMenu = GetSystemMenu( hwndDlg , FALSE );
+ bool bUseSyntaxHL = (GetMenuState( hSysMenu , ID_FV_SYNTAX_HL , MF_BYCOMMAND ) & MF_CHECKED)!=0;
+
+/*
+ DWORD dwSize = GetFileSize( hFile , NULL );
+ dwCurPos = 0;
+ pabFileData = new BYTE[ dwSize ];
+ ReadFile( hFile , pabFileData, dwSize , &dwDataRead, (LPOVERLAPPED)NULL);
+*/
+
+
+ // SendMessage( hRichEdit , EM_SETBKGNDCOLOR, 0 , RGB( 0 , 0 , 128 ) );
+ // SendMessage( hRichEdit , EM_SETTEXTMODE, TM_RICHTEXT ,0);
+
+ // DWORD dw = SendMessage( hRichEdit , EM_GETLIMITTEXT, NULL, NULL);
+
+ EDITSTREAM eds;
+ eds.dwError = 0;
+
+ if( bUseSyntaxHL )
+ {
+ SendMessage( hRichEdit , // handle to destination window
+ EM_EXLIMITTEXT, // message to send
+ 0, // not used; must be zero
+ 0x7FFFFFFF );
+
+ CLStreamRTFInfo clInfo( hFile );
+ eds.dwCookie = (DWORD)&clInfo;
+ eds.pfnCallback = RichEditRTFStreamLoadFile;
+
+ SendMessage(hRichEdit, EM_STREAMIN, (WPARAM)SF_RTF , (LPARAM)&eds);
+ pclDlg->bUtf8File = clInfo.bUtf8File;
+ }
+ else
+ {
+ eds.dwCookie = (DWORD )hFile;
+ eds.pfnCallback = RichEditStreamLoadFile;
+
+ SendMessage(hRichEdit, EM_STREAMIN, (WPARAM)SF_TEXT , (LPARAM)&eds);
+ }
+
+ CloseHandle( hFile );
+ //delete [] pabFileData;
+
+ _TCHAR szTmp[100];
+ mir_sntprintf( szTmp , 99, _T("File open time %d\n") , GetTickCount() - dwStart );
+ OutputDebugString( szTmp );
+
+
+ GETTEXTLENGTHEX sData = { 0 };
+ sData.flags = GTL_NUMCHARS;
+ sData.flags = GTL_DEFAULT;
+
+ DWORD dwDataRead = SendMessage( hRichEdit , EM_GETTEXTLENGTHEX, (WPARAM)&sData , 0 );
+ SendMessage( hRichEdit , EM_SETSEL , dwDataRead - 1, dwDataRead - 1 );
+
+ if( ! bScrollToBottom )
+ SendMessage( hRichEdit , EM_SETSCROLLPOS , 0 , (LPARAM) &ptOldPos );
+
+ mir_sntprintf( szTmp , 99, _T("With scroll to bottom %d\n") , GetTickCount() - dwStart );
+ OutputDebugString( szTmp );
+
+ return true;
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : bAdvancedCopy
+// Type : Global
+// Parameters : hwnd - handle to RichEdit control
+// Returns : Returns true if text was copied to the clipboard
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 030730 , 30 juli 2003
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+bool bAdvancedCopy(HWND hwnd)
+{
+ CHARRANGE sSelectRange;
+ SendMessage( hwnd, EM_EXGETSEL, 0 , (LPARAM)&sSelectRange );
+ int nSelLenght = sSelectRange.cpMax - sSelectRange.cpMin + 1; // +1 for null termination
+ if( nSelLenght > 1 )
+ {
+ OpenClipboard(NULL);
+ EmptyClipboard();
+
+ _TCHAR * pszSrcBuf = new _TCHAR[ nSelLenght];
+ pszSrcBuf[0] = 0;
+ SendMessage( hwnd, EM_GETSELTEXT, 0 , (LPARAM)pszSrcBuf );
+
+ HANDLE hDecMem = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE, nSelLenght );
+ _TCHAR * pszCurDec = (_TCHAR*)GlobalLock(hDecMem);
+
+ bool bInSpaces = false;
+ for( _TCHAR * pszCur = pszSrcBuf ; pszCur[0] ; pszCur++ )
+ {
+ if( bInSpaces )
+ {
+ if( pszCur[0] == ' ' )
+ continue;
+ bInSpaces = false;
+ }
+
+ if( pszCur[0] == '\n' )
+ {
+ bInSpaces = true;
+ }
+ pszCurDec[0] = pszCur[0];
+ pszCurDec++;
+ }
+ pszCurDec[0] = 0;
+ GlobalUnlock(hDecMem);
+
+ SetClipboardData(CF_TEXT,hDecMem);
+ delete [] pszSrcBuf;
+ CloseClipboard();
+ return true;
+ }
+ return false;
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : EditSubclassProc
+// Type : Global
+// Parameters : hwnd - ?
+// uMsg - ?
+// wParam - ?
+// lParam - ?
+// Returns : LRESULT CALLBACK
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 021013 , 13 October 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+LRESULT CALLBACK EditSubclassProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ CLHistoryDlg * pclDlg = (CLHistoryDlg *)GetWindowLong(hwnd,GWL_USERDATA);
+
+ switch( msg )
+ {
+ case WM_CONTEXTMENU:
+ {
+ HMENU nMenu = LoadMenu( hInstance, MAKEINTRESOURCE( IDR_FV_EDIT ) );
+ HMENU nSubMenu = GetSubMenu( nMenu , 0 );
+ POINT pt;
+ pt.x=(short)LOWORD(lParam);
+ pt.y=(short)HIWORD(lParam);
+
+ if(pt.x==-1 && pt.y==-1)
+ {
+ DWORD dwStart,dwEnd;
+ SendMessage( hwnd , EM_GETSEL , (WPARAM)&dwStart, (LPARAM)&dwEnd );
+ SendMessage( hwnd , EM_POSFROMCHAR, (WPARAM)&pt, (LPARAM)dwEnd);
+ ClientToScreen( hwnd , &pt );
+ }
+ TrackPopupMenu( nSubMenu , TPM_RIGHTBUTTON , pt.x , pt.y , 0 , hwnd , 0 );
+
+ DestroyMenu( nSubMenu );
+ DestroyMenu( nMenu );
+ return TRUE;
+ }
+ case WM_GETDLGCODE:
+ {
+ return DLGC_WANTARROWS;
+ }
+ case WM_COPY:
+ { // not working for "CTRL + C"
+ if( bAdvancedCopy( hwnd ) )
+ return TRUE;
+ break;
+ }
+ case WM_KEYDOWN:
+ {
+ if( (wParam == VK_INSERT || wParam == 'C') && (GetKeyState(VK_CONTROL) & 0x80) )
+ {
+ if( bAdvancedCopy( hwnd ) )
+ return TRUE;
+ }
+ break;
+ }
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case ID_EDIT_COPY:
+ {
+ SendMessage( hwnd , WM_COPY, 0, 0 );
+ return TRUE;
+ }
+ }
+ }
+ }
+ if( msg == UM_FIND_CMD )
+ {
+ FINDREPLACE *fr = (FINDREPLACE *)lParam;
+ if( fr->Flags & FR_DIALOGTERM )
+ {
+ pclDlg->hFindDlg = NULL;
+ return 0;
+ }
+
+ FINDTEXT ft = { 0 };
+
+ if( fr->Flags & FR_FINDNEXT)
+ {
+ ft.lpstrText = fr->lpstrFindWhat;
+
+ SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&ft.chrg);
+ ft.chrg.cpMin = ft.chrg.cpMax+1;
+ ft.chrg.cpMax = -1;
+ int res = SendMessage(hwnd, EM_FINDTEXT, (WPARAM)fr->Flags,(LPARAM)&ft);
+ if(res == -1)
+ {
+ ft.chrg.cpMin = 0;
+ res = SendMessage(hwnd, EM_FINDTEXT, (WPARAM)fr->Flags,(LPARAM)&ft);
+ if(res == -1)
+ {
+ MessageBox( hwnd , TranslateTS(_T("Search string was not found !")),MSG_BOX_TITEL,MB_OK );
+ return 0;
+ }
+ }
+ ft.chrg.cpMin = res;
+ ft.chrg.cpMax = res + _tcslen(fr->lpstrFindWhat);
+ SendMessage(hwnd , EM_EXSETSEL, 0, (LPARAM)&ft.chrg);
+ return 0;
+ }
+
+ }
+ return CallWindowProc(pclDlg->wpOrigEditProc, hwnd, msg, wParam, lParam);
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : SetWindowsCtrls
+// Type : Global
+// Parameters : hwndDlg - ?
+// Returns : void
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 021001 , 01 October 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+void SetWindowsCtrls( HWND hwndDlg )
+{
+ RECT rNewSize;
+ GetClientRect( hwndDlg , &rNewSize );
+
+ RECT rCurSize;
+
+ const int nSpacing = 12;
+
+
+ HWND hButton = GetDlgItem( hwndDlg , IDOK );
+ GetWindowRect( hButton , &rCurSize );
+ int nButtonHeight = rCurSize.bottom - rCurSize.top;
+
+ SetWindowPos( GetDlgItem( hwndDlg , IDC_RICHEDIT ) , 0 ,
+ nSpacing , nSpacing ,
+ rNewSize.right - (nSpacing * 2) ,
+ rNewSize.bottom - ( nSpacing * 3 + nButtonHeight ),
+ SWP_NOZORDER );
+
+
+ int nButtonWidth = rCurSize.right - rCurSize.left;
+ int nButtonSpace = (rNewSize.right - ( 3 * nButtonWidth )) / 4;
+ int nButtonTop = rNewSize.bottom - ( nSpacing + nButtonHeight );
+ int nCurLeft = nButtonSpace;
+
+ SetWindowPos( GetDlgItem( hwndDlg , IDC_FV_FIND ) , 0 ,
+ nCurLeft , nButtonTop , 0 , 0 , SWP_NOZORDER | SWP_NOSIZE );
+
+ nCurLeft += nButtonSpace + nButtonWidth;
+
+ SetWindowPos( GetDlgItem( hwndDlg , IDC_FV_EXTERNAL ) , 0 ,
+ nCurLeft , nButtonTop , 0 , 0 , SWP_NOZORDER | SWP_NOSIZE );
+
+ nCurLeft += nButtonSpace + nButtonWidth;
+
+ SetWindowPos( hButton , 0 ,
+ nCurLeft , nButtonTop , 0 , 0 , SWP_NOZORDER | SWP_NOSIZE );
+
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : SetRichEditFont
+// Type : Global
+// Parameters : hRichEdit - RichEdit to set the font in
+// bUseSyntaxHL - Is Syntax hilighting is used the color
+// will not be set
+// Returns : void
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 030205 , 05 February 2003
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+void SetRichEditFont(HWND hRichEdit, bool bUseSyntaxHL )
+{
+ CHARFORMAT ncf = { 0 };
+ ncf.cbSize = sizeof( CHARFORMAT );
+ ncf.dwMask = CFM_BOLD | CFM_FACE | CFM_ITALIC | CFM_SIZE | CFM_UNDERLINE;
+ ncf.dwEffects = DBGetContactSettingDword( NULL , MODULE , szFileViewDB "TEffects" , 0 );
+ ncf.yHeight = DBGetContactSettingDword( NULL , MODULE , szFileViewDB "THeight" , 165 );
+ _tcscpy( ncf.szFaceName , _DBGetString( NULL , MODULE , szFileViewDB "TFace" , _T("Courier New")).c_str() );
+
+ if( ! bUseSyntaxHL )
+ {
+ ncf.dwMask |= CFM_COLOR;
+ ncf.crTextColor = DBGetContactSettingDword( NULL , MODULE , szFileViewDB "TColor" , 0 );
+ }
+ SendMessage(hRichEdit, EM_SETCHARFORMAT, (WPARAM)SCF_ALL, (LPARAM)&ncf);
+
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : DlgProcFileViewer
+// Type : Global
+// Parameters : hwndDlg - ?
+// msg - ?
+// wParam - ?
+// lParam - ?
+// Returns : static BOOL CALLBACK
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 020929 , 29 September 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+static BOOL CALLBACK DlgProcFileViewer(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ CLHistoryDlg * pclDlg = (CLHistoryDlg *)GetWindowLong(hwndDlg,GWL_USERDATA);
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ SetWindowLong(hwndDlg,GWL_USERDATA,lParam);
+ CLHistoryDlg * pclDlg = (CLHistoryDlg *)lParam;
+#ifdef _UNICODE
+ EnableWindow( GetDlgItem( hwndDlg , IDC_FV_FIND ) , FALSE );
+#endif
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG,
+ (LPARAM)LoadIcon( hInstance, MAKEINTRESOURCE(IDI_EXPORT_MESSAGE)));
+
+ HWND hRichEdit = GetDlgItem( hwndDlg , IDC_RICHEDIT );
+ pclDlg->wpOrigEditProc = (WNDPROC) SetWindowLongPtr( hRichEdit, GWL_WNDPROC, (LONG) EditSubclassProc);
+
+ SetWindowLongPtr( hRichEdit, GWLP_USERDATA, (LONG) pclDlg );
+
+ SendMessage( hRichEdit , EM_SETEVENTMASK , 0 , ENM_LINK);
+ SendMessage( hRichEdit , EM_AUTOURLDETECT , TRUE , 0 );
+
+ HMENU hSysMenu = GetSystemMenu( hwndDlg , FALSE );
+
+ InsertMenu( hSysMenu , 0 , MF_SEPARATOR | MF_BYPOSITION , 0 , 0 );
+ InsertMenu( hSysMenu , 0 , MF_STRING | MF_BYPOSITION , ID_FV_SAVE_AS_RTF, TranslateTS(_T("Save as RTF")) );
+
+ InsertMenu( hSysMenu , 0 , MF_SEPARATOR | MF_BYPOSITION , 0 , 0 );
+
+ BYTE bUseCC = (BYTE)DBGetContactSettingByte( NULL , MODULE , szFileViewDB "UseCC" , 0 );
+ InsertMenu( hSysMenu , 0 , MF_STRING | MF_BYPOSITION | ( bUseCC ? MF_CHECKED : 0 ) , ID_FV_COLOR, TranslateTS(_T("Color...")) );
+
+ if( bUseCC )
+ {
+ SendMessage( hRichEdit , EM_SETBKGNDCOLOR, 0 ,
+ DBGetContactSettingDword( NULL , MODULE , szFileViewDB "CustomC" , RGB(255,255,255) )
+ );
+ }
+
+ InsertMenu( hSysMenu , 0 , MF_STRING | MF_BYPOSITION , ID_FV_FONT, TranslateTS(_T("Font...")) );
+
+
+ bool bUseSyntaxHL = DBGetContactSettingByte( NULL , MODULE , szFileViewDB "UseSyntaxHL" , 1 )!=0;
+ InsertMenu( hSysMenu , 0 , MF_STRING | MF_BYPOSITION | ( bUseSyntaxHL ? MF_CHECKED : 0 ) , ID_FV_SYNTAX_HL, TranslateTS(_T("Syntax highlight")) );
+
+ SetRichEditFont( hRichEdit , bUseSyntaxHL );
+
+ TranslateDialogDefault(hwndDlg);
+
+ int cx= DBGetContactSettingDword( NULL , MODULE , szFileViewDB "cx" , 0 );
+ int cy= DBGetContactSettingDword( NULL , MODULE , szFileViewDB "cy" , 0 );
+
+ if( cx > 0 && cy > 0)
+ {
+ int x = DBGetContactSettingDword( NULL , MODULE , szFileViewDB "x" , 0 );
+ int y = DBGetContactSettingDword( NULL , MODULE , szFileViewDB "y" , 0 );
+
+ SetWindowPos( hwndDlg , NULL , x , y , cx , cy , SWP_NOZORDER );
+ }
+
+ pclDlg->sPath = GetFilePathFromUser( pclDlg->hContact );
+
+ SetWindowsCtrls( hwndDlg );
+
+
+ bLoadFile(hwndDlg , pclDlg );
+
+ { // set Title
+ _TCHAR szFormat[200];
+ _TCHAR szTitle[200];
+ if( GetWindowText( hwndDlg , szFormat , sizeof( szFormat ) ) )
+ {
+ const _TCHAR * pszNick = NickFromHandle( pclDlg->hContact );
+ tstring sPath = pclDlg->sPath;
+ string::size_type n = sPath.find_last_of( '\\' );
+ if( n != sPath.npos )
+ sPath.erase( 0 , n + 1 );
+
+ if( _sntprintf( szTitle , sizeof( szTitle ) , szFormat , pszNick , sPath.c_str() , (pclDlg->bUtf8File ? _T("UTF8"):_T("ANSI")) ) > 0 )
+ {
+ SetWindowText( hwndDlg , szTitle);
+ }
+ }
+ }
+
+ return TRUE;
+ }
+ case WM_RELOAD_FILE:
+ {
+ bLoadFile(hwndDlg , pclDlg );
+ return TRUE;
+ }
+ case WM_SIZE:
+ case WM_SIZING:
+ {
+ SetWindowsCtrls( hwndDlg );
+ return TRUE;
+ }
+ case WM_NCDESTROY:
+ {
+ EnterCriticalSection( &csHistoryList );
+ clHistoryDlgList.remove( pclDlg );
+ LeaveCriticalSection( &csHistoryList );
+
+ delete pclDlg;
+ SetWindowLong(hwndDlg,GWL_USERDATA,NULL);
+ return 0;
+ }
+ case WM_DESTROY:
+ {
+ RECT rSize;
+ if( GetWindowRect( hwndDlg , &rSize ) )
+ {
+ // first we make sure the window has resonable dimentions.
+ // if it is minimized it will not have that.
+ if( rSize.left <= -32000 || rSize.top <= -32000 )
+ return 0;
+ if( rSize.right <= -32000 || rSize.bottom <= -32000 )
+ return 0;
+ DBWriteContactSettingDword( NULL , MODULE , szFileViewDB "x" , rSize.left );
+ DBWriteContactSettingDword( NULL , MODULE , szFileViewDB "y" , rSize.top );
+ DBWriteContactSettingDword( NULL , MODULE , szFileViewDB "cx" , rSize.right - rSize.left );
+ DBWriteContactSettingDword( NULL , MODULE , szFileViewDB "cy" , rSize.bottom - rSize.top );
+ }
+ return 0;
+ }
+ case WM_SYSCOMMAND:
+ {
+ HMENU hSysMenu = GetSystemMenu( hwndDlg , FALSE );
+ bool bUseSyntaxHL = (GetMenuState( hSysMenu , ID_FV_SYNTAX_HL , MF_BYCOMMAND ) & MF_CHECKED)!=0;
+ HWND hRichEdit = GetDlgItem( hwndDlg , IDC_RICHEDIT );
+
+ if ((wParam & 0xFFF0) == ID_FV_FONT)
+ {
+ LOGFONT lf = { 0 };
+ lf.lfHeight = 14L;
+
+ { DWORD dwEffects = DBGetContactSettingDword( NULL , MODULE , szFileViewDB "TEffects" , 0 );
+ lf.lfWeight = (dwEffects & CFE_BOLD) ? FW_BOLD : 0;
+ lf.lfUnderline = (dwEffects & CFE_UNDERLINE) != 0;
+ lf.lfStrikeOut = (dwEffects & CFE_STRIKEOUT) != 0;
+ lf.lfItalic = (dwEffects & CFE_ITALIC) != 0;
+ }
+ _tcscpy(lf.lfFaceName, _DBGetString( NULL , MODULE , szFileViewDB "TFace" , _T("Courier New")).c_str());
+ CHOOSEFONT cf = { 0 };
+ cf.lStructSize = sizeof( cf );
+ cf.hwndOwner = hwndDlg;
+ cf.lpLogFont = &lf;
+ cf.rgbColors = DBGetContactSettingDword( NULL , MODULE , szFileViewDB "TColor" , 0 );
+ cf.Flags = CF_EFFECTS | CF_SCREENFONTS | CF_INITTOLOGFONTSTRUCT;
+
+ if( ChooseFont( &cf ) )
+ {
+ DWORD dwEffects = (lf.lfWeight == FW_BOLD ? CFE_BOLD : 0) |
+ (lf.lfItalic ? CFE_ITALIC : 0) |
+ (lf.lfStrikeOut ? CFE_STRIKEOUT : 0) |
+ (lf.lfUnderline ? CFE_UNDERLINE : 0);
+
+ DBWriteContactSettingDword( NULL , MODULE , szFileViewDB "TEffects" , dwEffects );
+ DBWriteContactSettingDword( NULL , MODULE , szFileViewDB "THeight" , cf.iPointSize * 2 );
+ DBWriteContactSettingDword( NULL , MODULE , szFileViewDB "TColor" , cf.rgbColors );
+ DBWriteContactSettingTString( NULL , MODULE , szFileViewDB "TFace" , lf.lfFaceName );
+ SetRichEditFont( hRichEdit , bUseSyntaxHL );
+ }
+ return TRUE;
+ }
+ else if ((wParam & 0xFFF0) == ID_FV_COLOR)
+ {
+ BYTE bUseCC = ! DBGetContactSettingByte( NULL , MODULE , szFileViewDB "UseCC" , 0 );
+ if( bUseCC )
+ {
+ CHOOSECOLOR cc = {0};
+ cc.lStructSize = sizeof( cc );
+ cc.hwndOwner = hwndDlg;
+ cc.rgbResult = DBGetContactSettingDword( NULL , MODULE , szFileViewDB "CustomC" , RGB(255,255,255) );
+ cc.Flags = CC_ANYCOLOR | CC_FULLOPEN | CC_RGBINIT;
+ static COLORREF MyCustColors[16] = { 0xFFFFFFFF };
+ cc.lpCustColors = MyCustColors;
+ if( ChooseColor( &cc ) )
+ {
+ SendMessage( hRichEdit , EM_SETBKGNDCOLOR, 0 , cc.rgbResult );
+ DBWriteContactSettingDword( NULL , MODULE , szFileViewDB "CustomC" , cc.rgbResult );
+ }
+ else
+ {
+ /*DWORD dwError =*/ CommDlgExtendedError();
+ return TRUE;
+ }
+ }
+ else
+ {
+ SendMessage( hRichEdit , EM_SETBKGNDCOLOR, TRUE , 0 );
+ }
+ CheckMenuItem( hSysMenu , ID_FV_COLOR , MF_BYCOMMAND | (bUseCC ? MF_CHECKED : 0) );
+ DBWriteContactSettingByte( NULL , MODULE , szFileViewDB "UseCC" , bUseCC );
+ return TRUE;
+ }
+ else if ((wParam & 0xFFF0) == ID_FV_SYNTAX_HL)
+ {
+ // we use the current state from the menu not the DB value
+ // because we want to toggel the option for this window
+ // still the new option selected will be stored.
+ // so user may open 2 windows, now he can set SyntaxHL in both.
+
+ bUseSyntaxHL = !bUseSyntaxHL;
+ CheckMenuItem( hSysMenu , ID_FV_SYNTAX_HL , MF_BYCOMMAND | (bUseSyntaxHL ? MF_CHECKED : 0) );
+ DBWriteContactSettingByte( NULL , MODULE , szFileViewDB "UseSyntaxHL" , bUseSyntaxHL );
+
+ if( bUseSyntaxHL )
+ bLoadFile(hwndDlg , pclDlg );
+ else
+ SetRichEditFont( hRichEdit , bUseSyntaxHL );
+
+ return TRUE;
+ }
+ else if ((wParam & 0xFFF0) == ID_FV_SAVE_AS_RTF)
+ {
+ tstring sFile = pclDlg->sPath;
+ sFile += _T(".rtf");
+ HANDLE hFile = CreateFile( sFile.c_str() , GENERIC_WRITE ,
+ FILE_SHARE_READ , NULL , CREATE_ALWAYS , FILE_ATTRIBUTE_NORMAL , NULL );
+
+ if( hFile == INVALID_HANDLE_VALUE )
+ {
+ DisplayLastError( _T("Failed to create file") );
+ return TRUE;
+ }
+
+ EDITSTREAM eds;
+ eds.dwCookie = (DWORD )hFile;
+ eds.dwError = 0;
+ eds.pfnCallback = RichEditStreamSaveFile;
+ int nWriteOk = SendMessage(hRichEdit, EM_STREAMOUT, (WPARAM)SF_RTF , (LPARAM)&eds);
+ if( nWriteOk <= 0 || eds.dwError != 0 )
+ {
+ DisplayLastError( _T("Failed to save file") );
+ CloseHandle( hFile );
+ return TRUE;
+ }
+ CloseHandle( hFile );
+ tstring sReport = _T("History was saved successfully in file\r\n");
+ sReport += sFile;
+ MessageBox( NULL , sReport.c_str() ,MSG_BOX_TITEL ,MB_OK );
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDCANCEL:
+ case IDOK:
+ DestroyWindow(hwndDlg);
+ return TRUE;
+ case IDC_FV_EXTERNAL:
+ bOpenExternaly( pclDlg->hContact );
+ return TRUE;
+ case IDC_FV_FIND:
+ {
+ if( pclDlg->hFindDlg )
+ {
+ BringWindowToTop( pclDlg->hFindDlg );
+ return TRUE;
+ }
+ pclDlg->fr.hwndOwner = GetDlgItem( hwndDlg , IDC_RICHEDIT );
+ pclDlg->hFindDlg = FindText( &pclDlg->fr );
+ return TRUE;
+ }
+ }
+ break;
+ }
+ case WM_NOTIFY:
+ {
+ if( ((NMHDR*)lParam)->idFrom == IDC_RICHEDIT )
+ {
+ if( ((NMHDR*)lParam)->code == EN_LINK )
+ {
+ ENLINK* pstLink = (ENLINK*)lParam;
+ if( pstLink->msg == WM_LBUTTONUP )
+ {
+ _TCHAR szUrl[ 500 ];
+ if( (pstLink->chrg.cpMax - pstLink->chrg.cpMin) > (sizeof( szUrl ) - 2) )
+ return FALSE;
+
+ TEXTRANGE stToGet;
+ stToGet.chrg = pstLink->chrg;
+ stToGet.lpstrText = szUrl;
+ if( SendMessage( pstLink->nmhdr.hwndFrom , EM_GETTEXTRANGE , 0 , (LPARAM)&stToGet ) > 0 )
+ {
+ CallService(MS_UTILS_OPENURL,1,(LPARAM)szUrl);
+ }
+ return TRUE;
+ }
+ }
+ }
+ break;
+ }
+ case WM_CLOSE:
+ {
+ DestroyWindow(hwndDlg);
+ return TRUE;
+ }
+ }
+ return FALSE;
+//FALSE;//DefWindowProc( hwndDlg, msg, wParam, lParam );
+//DefDlgProc( hwndDlg, msg, wParam, lParam );
+}
+
+
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : bShowFileViewer
+// Type : Global
+// Parameters : hContact - ?
+// Returns : Returns true if
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 020929 , 29 September 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+bool bShowFileViewer( HANDLE hContact )
+{
+ CLHistoryDlg * pcl = new CLHistoryDlg( hContact );
+ pcl->hWnd = CreateDialogParam( hInstance,MAKEINTRESOURCE(IDD_FILE_VIEWER),NULL,DlgProcFileViewer,(LPARAM)pcl);
+ if( pcl->hWnd )
+ {
+ EnterCriticalSection( &csHistoryList );
+ clHistoryDlgList.push_front( pcl );
+ LeaveCriticalSection( &csHistoryList );
+
+ ShowWindow( pcl->hWnd , SW_SHOWNORMAL );
+ return true;
+ }
+ DisplayLastError( _T("Failed to create history dialog") );
+ delete pcl;
+ return false;
+}
diff --git a/plugins/Msg_Export/src/FileViewer.h b/plugins/Msg_Export/src/FileViewer.h
new file mode 100755
index 0000000000..6da79c9620
--- /dev/null
+++ b/plugins/Msg_Export/src/FileViewer.h
@@ -0,0 +1,38 @@
+
+//This file is part of Msg_Export a Miranda IM plugin
+//Copyright (C)2002 Kennet Nielsen ( http://sourceforge.net/projects/msg-export/ )
+//
+//This program is free software; you can redistribute it and/or
+//modify it under the terms of the GNU General Public License
+//as published by the Free Software Foundation; either
+//version 2 of the License, or (at your option) any later version.
+//
+//This program is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//GNU General Public License for more details.
+//
+//You should have received a copy of the GNU General Public License
+//along with this program; if not, write to the Free Software
+//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#ifndef MSG_EXP_FILE_VIEWER
+#define MSG_EXP_FILE_VIEWER
+
+#include <windows.h>
+
+void Initilize();
+void Uninitilize();
+
+void UpdateFileViews( const _TCHAR * pszFile );
+
+bool bOpenExternaly( HANDLE hContact );
+bool bShowFileViewer( HANDLE hContact );
+
+bool bUseInternalViewer( bool bNew );
+bool bUseInternalViewer();
+
+extern tstring sFileViewerPrg;
+
+#endif
+
diff --git a/plugins/Msg_Export/src/Glob.h b/plugins/Msg_Export/src/Glob.h
new file mode 100755
index 0000000000..8de2c0843e
--- /dev/null
+++ b/plugins/Msg_Export/src/Glob.h
@@ -0,0 +1,29 @@
+
+//This file is part of Msg_Export a Miranda IM plugin
+//Copyright (C)2002 Kennet Nielsen ( http://sourceforge.net/projects/msg-export/ )
+//
+//This program is free software; you can redistribute it and/or
+//modify it under the terms of the GNU General Public License
+//as published by the Free Software Foundation; either
+//version 2 of the License, or (at your option) any later version.
+//
+//This program is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//GNU General Public License for more details.
+//
+//You should have received a copy of the GNU General Public License
+//along with this program; if not, write to the Free Software
+//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#ifndef MSG_EXP_GLOB_H
+#define MSG_EXP_GLOB_H
+
+#include <windows.h>
+
+#define MODULE "Msg_Export"
+#define MSG_BOX_TITEL _T("Miranda (Msg_Export.dll)")
+
+extern HINSTANCE hInstance;
+
+#endif \ No newline at end of file
diff --git a/plugins/Msg_Export/src/main.cpp b/plugins/Msg_Export/src/main.cpp
new file mode 100755
index 0000000000..5d9ce233dc
--- /dev/null
+++ b/plugins/Msg_Export/src/main.cpp
@@ -0,0 +1,404 @@
+
+//This file is part of Msg_Export a Miranda IM plugin
+//Copyright (C)2002 Kennet Nielsen ( http://sourceforge.net/projects/msg-export/ )
+//
+//This program is free software; you can redistribute it and/or
+//modify it under the terms of the GNU General Public License
+//as published by the Free Software Foundation; either
+//version 2 of the License, or (at your option) any later version.
+//
+//This program is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//GNU General Public License for more details.
+//
+//You should have received a copy of the GNU General Public License
+//along with this program; if not, write to the Free Software
+//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#include <windows.h>
+#include <Shellapi.h>
+
+//#include "../Miranda-IM/resource.h"
+
+#include "utils.h"
+#include "options.h"
+#include "FileViewer.h"
+#include "Glob.h"
+
+#include "resource.h"
+
+
+#define MS_SHOW_EXPORT_HISTORY "History/ShowExportHistory"
+
+HINSTANCE hInstance = NULL;
+int hLangpack = 0;
+
+// static so they can not be used from other modules ( sourcefiles )
+static HANDLE hEventOptionsInitialize = 0;
+static HANDLE hDBEventAdded = 0;
+static HANDLE hDBContactDeleted = 0;
+static HANDLE hEventSystemInit = 0;
+static HANDLE hEventSystemShutdown = 0;
+
+static HANDLE hServiceFunc = 0;
+
+static HANDLE hOpenHistoryMenuItem = 0;
+
+/////////////////////////////////////////////////////
+// Remember to update the Version in the resource !!!
+/////////////////////////////////////////////////////
+
+PLUGININFOEX pluginInfo = {
+ sizeof(PLUGININFOEX),
+ "Message export (mod by ring0)",
+ PLUGIN_MAKE_VERSION(3,1,0,3),
+ "Exports every message, URL or File you receive to a text file.\r\n"
+ "Messages are exported to one file per user, users may be set to use the same file",
+ "Kennet Nielsen, mod by ring0",
+ "Kennet_N@ofir.dk",
+ "© 2002 Kennet Nielsen",
+ "http://sourceforge.net/projects/msg-export/",
+ UNICODE_AWARE,
+ #ifdef _UNICODE
+ { 0x46102b07, 0xc215, 0x4162, { 0x9c, 0x83, 0xd3, 0x77, 0x88, 0x1d, 0xa7, 0xcc } } // {46102B07-C215-4162-9C83-D377881DA7CC}
+ #else
+ { 0x13ff3b7e, 0x4976, 0x471f, { 0xa4, 0x75, 0x16, 0x62, 0xa4, 0xdd, 0xc, 0x3e } } // {13FF3B7E-4976-471f-A475-1662A4DD0C3E}
+ #endif
+};
+
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : ShowExportHistory
+// Type : Global
+// Parameters : wParam - (WPARAM)(HANDLE)hContact
+// lParam - ?
+// Returns : static int
+// Description : Called when user selects my menu item "Open Exported History"
+//
+// References : -
+// Remarks : -
+// Created : 020422 , 22 April 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+static int ShowExportHistory(WPARAM wParam,LPARAM /*lParam*/)
+{
+ if( bUseInternalViewer() )
+ {
+ bShowFileViewer( (HANDLE)wParam );
+ return 0;
+ }
+ bOpenExternaly( (HANDLE)wParam );
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : nSystemShutdown
+// Type : Global
+// Parameters : wparam - 0
+// lparam - 0
+// Returns : int
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 020428 , 28 April 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+int nSystemShutdown(WPARAM /*wparam*/,LPARAM /*lparam*/)
+{
+ if( hEventOptionsInitialize )
+ {
+ UnhookEvent(hEventOptionsInitialize);
+ hEventOptionsInitialize = 0;
+ }
+
+ if( hDBEventAdded )
+ {
+ UnhookEvent(hDBEventAdded);
+ hDBEventAdded = 0;
+ }
+
+ if( hDBContactDeleted )
+ {
+ UnhookEvent(hDBContactDeleted);
+ hDBContactDeleted = 0;
+ }
+
+ if( hServiceFunc )
+ {
+ DestroyServiceFunction( hServiceFunc );
+ hServiceFunc = 0;
+ }
+
+ if( hEventSystemInit )
+ {
+ UnhookEvent(hEventSystemInit);
+ hEventSystemInit = 0;
+ }
+
+ if( hEventSystemShutdown )
+ {
+ UnhookEvent(hEventSystemShutdown); // here we unhook the fun we are in, might not bee good
+ hEventSystemShutdown = 0;
+ }
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : MainInit
+// Type : Global
+// Parameters : wparam - ?
+// lparam - ?
+// Returns : int
+// Description : Called when system modules has been loaded
+//
+// References : -
+// Remarks : -
+// Created : 020422 , 22 April 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+int MainInit(WPARAM /*wparam*/,LPARAM /*lparam*/)
+{
+
+ Initilize();
+
+ bReadMirandaDirAndPath();
+ UpdateFileToColWidth();
+
+ hDBEventAdded = HookEvent( ME_DB_EVENT_ADDED , nExportEvent );
+ if( !hDBEventAdded )
+ MessageBox( NULL , _T("Failed to HookEvent ME_DB_EVENT_ADDED") , MSG_BOX_TITEL , MB_OK );
+
+
+ hDBContactDeleted = HookEvent( ME_DB_CONTACT_DELETED , nContactDeleted );
+ if( !hDBContactDeleted )
+ MessageBox( NULL , _T("Failed to HookEvent ME_DB_CONTACT_DELETED") , MSG_BOX_TITEL , MB_OK );
+
+
+ hEventOptionsInitialize = HookEvent( ME_OPT_INITIALISE , OptionsInitialize );
+ if( !hEventOptionsInitialize )
+ MessageBox( NULL , _T("Failed to HookEvent ME_OPT_INITIALISE") , MSG_BOX_TITEL , MB_OK );
+
+
+ CLISTMENUITEM mi;
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize=sizeof(mi);
+ mi.flags=0;
+ mi.pszContactOwner=NULL; //all contacts
+ mi.hIcon=LoadIcon(hInstance,MAKEINTRESOURCE(IDI_EXPORT_MESSAGE));
+
+ if( bReplaceHistory )
+ {
+ mi.position= 1000090000;
+ mi.pszName=Translate("View &History");
+ mi.pszService=MS_HISTORY_SHOWCONTACTHISTORY;
+ }
+ else
+ {
+ mi.position = 1000090100;
+ mi.pszName=Translate("Open E&xported History");
+ mi.pszService=MS_SHOW_EXPORT_HISTORY;
+ }
+ hOpenHistoryMenuItem = Menu_AddContactMenuItem(&mi);
+
+ if( !hOpenHistoryMenuItem )
+ MessageBox( NULL , _T("Failed to add menu item Open Exported History\nCallService(MS_CLIST_ADDCONTACTMENUITEM,...)") , MSG_BOX_TITEL , MB_OK );
+
+/*
+ hEventSystemShutdown = HookEvent( ME_SYSTEM_SHUTDOWN , nSystemShutdown );
+
+ if( !hEventSystemShutdown )
+ MessageBox( NULL , "Failed to HookEvent ME_SYSTEM_SHUTDOWN" , MSG_BOX_TITEL , MB_OK );
+*/
+
+/*
+ _TCHAR szBuf[ 10000 ];
+ for( int n = 0 ; n < 1000 ; n++ )
+ {
+ for( int y = 0 ; y < n ; y++ )
+ {
+ szBuf[ y ] = '0' + y%10;//((n + y) % 8 ) ? ('0' + ((n + y) % 10)) : ' ' ;
+ }
+ szBuf[ y ] = 0;
+
+ HANDLE hFile = CreateFile( "C:\\test.txt" , GENERIC_WRITE , FILE_SHARE_READ , 0 ,OPEN_ALWAYS , FILE_ATTRIBUTE_NORMAL , NULL );
+ SetFilePointer( hFile , 0 , 0 , FILE_END );
+
+ bWriteNewLine( hFile , 10 );
+ bWriteNewLine( hFile , 0 );
+ bWriteNewLine( hFile , 120 );
+
+ DWORD dwBytesWritten;
+ WriteFile( hFile , "\r\n\r\n" , 4 , &dwBytesWritten , NULL );
+
+ CloseHandle( hFile );
+ //}*/
+
+ return 0;
+}
+
+
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : DllMain
+// Type : Global
+// Parameters : hinst - ?
+// fdwReason - ?
+// lpvReserved - ?
+// Returns : BOOL WINAPI
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 020422 , 22 April 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+BOOL WINAPI DllMain(HINSTANCE hinst,DWORD /*fdwReason*/,LPVOID /*lpvReserved*/)
+{
+ hInstance=hinst;
+ return 1;
+}
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : MirandaPluginInfo
+// Type : Global
+// Parameters : mirandaVersion - ?
+// Returns :
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 020422 , 22 April 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+__declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD /*mirandaVersion*/)
+{
+ return &pluginInfo;
+}
+
+static const MUUID interfaces[] = { MIID_HISTORYEXPORT, MIID_LAST};
+extern "C" __declspec(dllexport) const MUUID * MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : Load
+// Type : Global
+// Parameters : link - ?
+// Returns : int
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 020422 , 22 April 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+int __declspec(dllexport)Load()
+{
+ mir_getLP(&pluginInfo);
+ hEventSystemInit = HookEvent(ME_SYSTEM_MODULESLOADED,MainInit);
+
+ if( !hEventSystemInit )
+ {
+ MessageBox( NULL , _T("Failed to HookEvent ME_SYSTEM_MODULESLOADED") , MSG_BOX_TITEL , MB_OK );
+ return 0;
+ }
+
+ nMaxLineWidth = DBGetContactSettingWord( NULL , MODULE , "MaxLineWidth" , nMaxLineWidth );
+ if( nMaxLineWidth < 5 )
+ nMaxLineWidth = 5;
+
+ sExportDir = _DBGetString( NULL , MODULE , "ExportDir" , _T("%dbpath%\\MsgExport\\") );
+ sDefaultFile = _DBGetString( NULL , MODULE , "DefaultFile" , _T("%nick%.txt") );
+
+ sTimeFormat = _DBGetString( NULL , MODULE , "TimeFormat" , _T("d s") );
+
+ sFileViewerPrg = _DBGetString( NULL , MODULE , "FileViewerPrg" , _T("") );
+ bUseInternalViewer( DBGetContactSettingByte( NULL , MODULE , "UseInternalViewer" , bUseInternalViewer() ) != 0 );
+
+ bReplaceHistory = DBGetContactSettingByte( NULL , MODULE , "ReplaceHistory" , bReplaceHistory ) != 0;
+ bAppendNewLine = DBGetContactSettingByte( NULL , MODULE , "AppendNewLine" , bAppendNewLine ) != 0;
+ bUseUtf8InNewFiles = DBGetContactSettingByte( NULL , MODULE , "UseUtf8InNewFiles" , bUseUtf8InNewFiles ) != 0;
+ bUseLessAndGreaterInExport = DBGetContactSettingByte( NULL , MODULE , "UseLessAndGreaterInExport" , bUseLessAndGreaterInExport ) != 0;
+
+ enRenameAction = (ENDialogAction)DBGetContactSettingByte( NULL , MODULE , "RenameAction" , enRenameAction );
+ enDeleteAction = (ENDialogAction)DBGetContactSettingByte( NULL , MODULE , "DeleteAction" , enDeleteAction );;
+
+ // Plugin sweeper support
+ DBWriteContactSettingTString(NULL,"Uninstall","Message Export",_T(MODULE));
+
+ if( bReplaceHistory )
+ {
+ hServiceFunc = CreateServiceFunction(MS_HISTORY_SHOWCONTACTHISTORY,ShowExportHistory); //this need new code
+/* if( hServiceFunc )
+ {
+ int *disableDefaultModule=(int*)CallService(MS_PLUGINS_GETDISABLEDEFAULTARRAY,0,0);
+ if( disableDefaultModule )
+ {
+ disableDefaultModule[DEFMOD_UIHISTORY] = TRUE;
+ }
+ else
+ {
+ DestroyServiceFunction( hServiceFunc );
+ hServiceFunc = 0;
+ }
+ }*/
+
+ if( ! hServiceFunc )
+ MessageBox( NULL , TranslateTS(_T("Failed to replace Miranda History.\r\nThis is most likely due to changes in Miranda.")) , MSG_BOX_TITEL , MB_OK );
+ }
+
+ if( ! hServiceFunc )
+ {
+ hServiceFunc = CreateServiceFunction(MS_SHOW_EXPORT_HISTORY,ShowExportHistory);
+ }
+
+ if( ! hServiceFunc )
+ {
+ MessageBox( NULL , _T("Failed to CreateServiceFunction MS_SHOW_EXPORT_HISTORY") , MSG_BOX_TITEL , MB_OK );
+ }
+
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : Unload
+// Type : Global
+// Parameters : none
+// Returns :
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 020422 , 22 April 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+__declspec(dllexport)int Unload(void)
+{
+ //if( !hEventSystemShutdown ) // we will try to unload anyway
+ {
+ nSystemShutdown(0,0);
+ }
+ Uninitilize();
+ bUseInternalViewer( false );
+ return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/plugins/Msg_Export/src/options.cpp b/plugins/Msg_Export/src/options.cpp
new file mode 100755
index 0000000000..17bc917bb7
--- /dev/null
+++ b/plugins/Msg_Export/src/options.cpp
@@ -0,0 +1,1483 @@
+
+//This file is part of Msg_Export a Miranda IM plugin
+//Copyright (C)2002 Kennet Nielsen ( http://sourceforge.net/projects/msg-export/ )
+//
+//This program is free software; you can redistribute it and/or
+//modify it under the terms of the GNU General Public License
+//as published by the Free Software Foundation; either
+//version 2 of the License, or (at your option) any later version.
+//
+//This program is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//GNU General Public License for more details.
+//
+//You should have received a copy of the GNU General Public License
+//along with this program; if not, write to the Free Software
+//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+#include <windows.h>
+#include <commctrl.h>
+#include "Shlobj.h"
+
+
+#include "Utils.h"
+#include "Glob.h"
+#include "FileViewer.h"
+
+#include "resource.h"
+
+#include <stdio.h>
+#include <list>
+//#include <algorithm>
+
+#define STRINGIZE(x) #x
+#define EVAL_STRINGIZE(x) STRINGIZE(x)
+#define __LOC__ __FILE__ "("EVAL_STRINGIZE(__LINE__)") : "
+
+
+#pragma message ( __LOC__ "My warning: STD list contains a bug when sorting lists of more than 32,768 elements, you need to fix this")
+/* Change code for VC 6.0
+ if (_I == _MAXN)
+ _A[_I].merge(_X);
+ SHOULD BE
+ if (_I == _MAXN)
+ _A[_I - 1].merge(_X);
+
+ - And -
+
+ if (_I == _MAXN)
+ _A[_I].merge(_X, _Pr);
+ SHOULD BE
+ if (_I == _MAXN)
+ _A[_I - 1].merge(_X, _Pr);
+
+You need to change this in the file <list> function sort() and sort(_Pr3 _Pr)
+*/
+
+using namespace std;
+
+
+// width in pixels of the UIN column in the List Ctrl
+const int nUINColWitdh = 80;
+// width in pixels of the UIN column in the List Ctrl
+const int nProtoColWitdh = 40;
+
+
+// Used to controle the sending of the PSM_CHANGED to miranda
+// and to se if the user has unapplyed changes when he presses the
+// Export All button
+BOOL bUnaplyedChanges = FALSE;
+
+
+/////////////////////////////////////////////////////////////////////
+// Class : CLDBEvent
+// Superclass :
+// Project : Mes_export
+// Designer : Kennet Nielsen
+// Version : 1.0.0
+// Date : 020422 , 22 April 2002
+//
+//
+// Description: This class is used to store one DB event dyring the export
+// All history function
+//
+// Version History:
+// Ver: Initials: Date: Text:
+// 1.0.0 KN 020422 First edition
+//
+/////////////////////////////////////////////////////////////////////
+
+class CLDBEvent
+{
+ DWORD time;
+ public:
+ HANDLE hUser;
+ HANDLE hDbEvent;
+
+ CLDBEvent( HANDLE hU , HANDLE hDBE )
+ {
+ hUser = hU;
+ hDbEvent = hDBE;
+
+ DBEVENTINFO dbei={0}; //dbei.cbBlob=0;
+ dbei.cbSize=sizeof(dbei);
+ CallService(MS_DB_EVENT_GET,(WPARAM)hDbEvent,(LPARAM)&dbei);
+ time = dbei.timestamp;
+ }
+ bool operator <(const CLDBEvent& rOther) const
+ {
+ return time < rOther.time;
+ }
+};
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : CompareFunc
+// Type : Global
+// Parameters : lParam1 - ?
+// lParam2 - ?
+// lParamSort - ?
+// Returns : int CALLBACK
+// Description : Used to sort list view by Nick
+//
+// References : -
+// Remarks : -
+// Created : 020422 , 22 April 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
+{
+ if( lParamSort == 1 )
+ {
+ return _tcsicmp( NickFromHandle((HANDLE)lParam1) , NickFromHandle((HANDLE)lParam2) );
+ }
+
+ if( lParamSort == 2 )
+ {
+ return _DBGetString( (HANDLE)lParam1 , "Protocol" , "p" , _T("") ).compare(
+ _DBGetString( (HANDLE)lParam2 , "Protocol" , "p" , _T("") )
+ );
+ }
+ if( lParamSort == 3 )
+ {
+ DWORD dwUin1 = DBGetContactSettingDword(
+ (HANDLE)lParam1,
+ _DBGetStringA( (HANDLE)lParam1 , "Protocol" , "p" , "" ).c_str(),
+ "UIN",
+ 0);
+ DWORD dwUin2 = DBGetContactSettingDword(
+ (HANDLE)lParam2,
+ _DBGetStringA( (HANDLE)lParam2 , "Protocol" , "p" , "" ).c_str(),
+ "UIN",
+ 0);
+
+ if( dwUin1 == dwUin2 )
+ return 0;
+ if( dwUin1 > dwUin2 )
+ return -1;
+ return 1;
+ }
+ return 0;
+}
+
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : DialogProc
+// Type : Global
+// Parameters : hwndDlg - ?
+// uMsg - ?
+// wParam - ?
+// parameter - ?
+// Returns : INT_PTR CALLBACK
+// Description : Progress bar window function
+//
+// References : -
+// Remarks : -
+// Created : 020422 , 22 April 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+INT_PTR CALLBACK __stdcall DialogProc(
+ HWND hwndDlg, // handle to dialog box
+ UINT uMsg, // message
+ WPARAM /*wParam*/, // first message parameter
+ LPARAM /*lParam*/ // second message parameter
+)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : nExportCompleatList
+// Type : Global
+// Parameters : hParent - handle to the parrent, ( Options Dlg )
+// bOnlySelected - Only Export the userges that hase been selected in the list view
+// Returns : int not used currently
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 020422 , 22 April 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+int nExportCompleatList(HWND hParent , bool bOnlySelected )
+{
+ HWND hMapUser = GetDlgItem( hParent , IDC_MAP_USER_LIST );
+
+ int nTotalContacts = ListView_GetItemCount( hMapUser );
+
+ int nContacts;
+ if( bOnlySelected )
+ nContacts = ListView_GetSelectedCount( hMapUser );
+ else
+ nContacts = nTotalContacts;
+
+ if( !hMapUser || nContacts <= 0 )
+ {
+ MessageBox( hParent , TranslateTS(_T("No contacts found to export")),MSG_BOX_TITEL,MB_OK );
+ return 0;
+ }
+
+ HWND hDlg = CreateDialog( hInstance, MAKEINTRESOURCE( IDD_EXPORT_ALL_DLG ) , hParent , DialogProc );
+ HWND hProg = GetDlgItem( hDlg , IDC_EXPORT_PROGRESS );
+ HWND hStatus = GetDlgItem( hDlg , IDC_EXP_ALL_STATUS );
+
+ SendMessage( hProg , PBM_SETRANGE , 0 , MAKELPARAM( 0 , nContacts ) );
+
+ SetWindowText( hStatus , TranslateTS(_T("Reading database information ( Phase 1 of 2 )")) );
+
+ { // position and show proigrassbar dialog
+
+ RECT rParrent;
+ RECT rDlg;
+ if( GetWindowRect( hParent , &rParrent ) && GetWindowRect( hDlg , &rDlg ) )
+ {
+ int x = ( (rParrent.right + rParrent.left) / 2 ) - ( (rDlg.right - rDlg.left) / 2 );
+ int y = ( (rParrent.bottom + rParrent.top) / 2 ) - ( (rDlg.bottom - rDlg.top) / 2 );
+ SetWindowPos( hDlg , 0 , x , y , 0 ,0 , SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW );
+ }
+ else
+ ShowWindow( hDlg , SW_SHOWNORMAL );
+ }
+
+ // map with list to stored all DB history before it is exported
+ map<tstring, list< CLDBEvent >, less<tstring> > AllEvents;
+
+ { // reading from the database !!!
+ LVITEM sItem = { 0 };
+ sItem.mask = LVIF_PARAM;
+
+ for( int nCur = 0 ; nCur < nTotalContacts ; nCur++ )
+ {
+ if( bOnlySelected )
+ {
+ if( ! (ListView_GetItemState( hMapUser , nCur , LVIS_SELECTED ) & LVIS_SELECTED) )
+ continue;
+ }
+
+ sItem.iItem = nCur;
+ if( ! ListView_GetItem( hMapUser, &sItem ) )
+ {
+ MessageBox( hParent , TranslateTS(_T("Failed to export at least one contact")),MSG_BOX_TITEL,MB_OK );
+ continue;
+ }
+
+ HANDLE hContact = (HANDLE)sItem.lParam;
+
+ list< CLDBEvent > & rclCurList = AllEvents[ GetFilePathFromUser( hContact ) ];
+
+ HANDLE hDbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDFIRST,(WPARAM)hContact,0);
+ while( hDbEvent )
+ {
+ rclCurList.push_back( CLDBEvent( hContact , hDbEvent ) );
+
+ // Get next event in chain
+ hDbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDNEXT,(WPARAM)hDbEvent,0);
+ }
+
+ SendMessage( hProg , PBM_SETPOS , nCur , 0);
+ RedrawWindow( hDlg , NULL , NULL , RDW_ALLCHILDREN | RDW_UPDATENOW );
+ }
+
+/*
+ if( hContact )
+ MessageBox( hParent , TranslateTS(_T("Failed to export at least one contact")),MSG_BOX_TITEL,MB_OK );
+ */
+ }
+
+
+ { // window text update
+
+ SetWindowText( hStatus , TranslateTS(_T("Sorting and writing database information ( Phase 2 of 2 )")) );
+ SendMessage( hProg , PBM_SETRANGE , 0 , MAKELPARAM( 0 , AllEvents.size() ) );
+ SendMessage( hProg , PBM_SETPOS , 0 , 0);
+ }
+
+ { // time to write to files !!!
+ map<tstring, list< CLDBEvent >, less<tstring> >::iterator FileIterator;
+
+ int nCur=0;
+ for( FileIterator = AllEvents.begin() ; FileIterator != AllEvents.end() ; ++FileIterator )
+ {
+ (FileIterator->second).sort(); // Sort is preformed here !!
+ // events with same time will not be swaped, they will
+ // remain in there original order
+
+ list< CLDBEvent >::const_iterator iterator;
+ for( iterator = FileIterator->second.begin() ; iterator != FileIterator->second.end() ; ++iterator )
+ {
+ HANDLE hDbEvent = (*iterator).hDbEvent;
+ nExportEvent( (WPARAM) (*iterator).hUser , (LPARAM) hDbEvent );
+ }
+ SendMessage( hProg , PBM_SETPOS , ++nCur , 0);
+ RedrawWindow( hDlg , NULL , NULL , RDW_ALLCHILDREN | RDW_UPDATENOW );
+ }
+ }
+
+ DestroyWindow( hDlg );
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : SetToDefault
+// Type : Global
+// Parameters : hwndDlg - ?
+// Returns : void
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 021228 , 28 December 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+void SetToDefault( HWND hParent )
+{
+ HWND hMapUser = GetDlgItem( hParent , IDC_MAP_USER_LIST );
+
+ int nContacts = ListView_GetItemCount( hMapUser );
+
+ if( !hMapUser || nContacts <= 0 )
+ {
+ return;
+ }
+
+ _TCHAR szTemp[ 500 ];
+ if( ! GetDlgItemText( hParent , IDC_DEFAULT_FILE , szTemp , sizeof( szTemp ) ) )
+ return;
+
+ LVITEM sItem = { 0 };
+
+ for( int nCur = 0 ; nCur < nContacts ; nCur++ )
+ {
+ if( ! (ListView_GetItemState( hMapUser , nCur , LVIS_SELECTED ) & LVIS_SELECTED) )
+ continue;
+
+ sItem.iItem = nCur;
+ sItem.mask = LVIF_PARAM;
+ if( ! ListView_GetItem( hMapUser, &sItem ) )
+ continue;
+
+ tstring sFileName = szTemp;
+ ReplaceDefines( (HANDLE)sItem.lParam , sFileName );
+ ReplaceTimeVariables( sFileName );
+
+ sItem.mask = LVIF_TEXT;
+ sItem.pszText = (_TCHAR*)sFileName.c_str();
+ ListView_SetItem( hMapUser, &sItem );
+
+ if( ! bUnaplyedChanges )
+ {
+ bUnaplyedChanges = TRUE;
+ SendMessage(GetParent(hParent), PSM_CHANGED, 0, 0);
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : bApplyChanges
+// Type : Global
+// Parameters : hwndDlg - handle to the parrent, ( Options Dlg )
+// Returns : Returns true if the changes was applyed
+// Description : but since we cant abort an apply opperation ,
+// this can not currently be used
+// References : -
+// Remarks : -
+// Created : 020422 , 22 April 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+BOOL bApplyChanges( HWND hwndDlg )
+{
+ BOOL bTrans;
+ BOOL bRet = true;
+ _TCHAR szTemp[500];
+
+ int nTmp = GetDlgItemInt( hwndDlg , IDC_MAX_CLOUMN_WIDTH , &bTrans , TRUE );
+ if( !bTrans || nTmp < 5 )
+ {
+ _sntprintf( szTemp , sizeof( szTemp ) ,CheckedTranslate(_T("Max line width must be at least %d"),1) , 5 );
+ MessageBox( hwndDlg , szTemp ,MSG_BOX_TITEL,MB_OK );
+ bRet = false;
+ }
+ else
+ {
+ nMaxLineWidth = nTmp;
+ }
+
+ GetDlgItemText( hwndDlg , IDC_EXPORT_TIMEFORMAT , szTemp , sizeof( szTemp ) );
+ sTimeFormat = szTemp;
+
+ GetDlgItemText( hwndDlg , IDC_EXPORT_DIR , szTemp , sizeof( szTemp ) );
+ sExportDir = szTemp;
+
+ GetDlgItemText( hwndDlg , IDC_DEFAULT_FILE , szTemp , sizeof( szTemp ) );
+ sDefaultFile = szTemp;
+
+ GetDlgItemText( hwndDlg , IDC_FILE_VIEWER , szTemp , sizeof( szTemp ) );
+ sFileViewerPrg = szTemp;
+
+ bUseInternalViewer( IsDlgButtonChecked( hwndDlg , IDC_USE_INTERNAL_VIEWER ) == BST_CHECKED );
+
+ bool bNewRp = IsDlgButtonChecked( hwndDlg , IDC_REPLACE_MIRANDA_HISTORY ) == BST_CHECKED;
+ if( bReplaceHistory != bNewRp )
+ {
+ bReplaceHistory = bNewRp;
+ MessageBox( hwndDlg , TranslateTS(_T("You need to restart miranda to change the history function")) ,MSG_BOX_TITEL,MB_OK );
+ }
+
+ bAppendNewLine = IsDlgButtonChecked( hwndDlg , IDC_APPEND_NEWLINE ) == BST_CHECKED;
+ bUseUtf8InNewFiles = IsDlgButtonChecked( hwndDlg , IDC_USE_UTF8_IN_NEW_FILES ) == BST_CHECKED;
+
+ bUseLessAndGreaterInExport = IsDlgButtonChecked( hwndDlg , IDC_USE_LESS_AND_GREATER_IN_EXPORT ) == BST_CHECKED;
+
+
+ HWND hMapUser = GetDlgItem( hwndDlg , IDC_MAP_USER_LIST );
+ int nCount = ListView_GetItemCount( hMapUser );
+ for( int nCur = 0 ; nCur < nCount ; nCur++ )
+ {
+ LVITEM sItem = { 0 };
+ sItem.iItem = nCur;
+ sItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
+ sItem.pszText = szTemp;
+ sItem.cchTextMax = sizeof( szTemp );
+
+ if( ListView_GetItem( hMapUser, &sItem ) )
+ {
+ HANDLE hUser = (HANDLE)sItem.lParam;
+ if( _tcslen( szTemp ) > 0 )
+ DBWriteContactSettingTString( hUser , MODULE , "FileName" , szTemp );
+ else
+ DBDeleteContactSetting( hUser , MODULE , "FileName" );
+
+ if( sItem.iImage )
+ DBDeleteContactSetting( hUser , MODULE , "EnableLog" ); // default is Enabled !!
+ else
+ DBWriteContactSettingByte( hUser , MODULE , "EnableLog",0);
+ }
+ }
+ UpdateFileToColWidth();
+
+ SaveSettings();
+
+
+ bUnaplyedChanges = FALSE;
+ return bRet;
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : ClearAllFileNames
+// Type : Global
+// Parameters : hwndDlg - handle to the parrent, ( Options Dlg )
+// Returns : void
+// Description : Just clear all file name's entered
+//
+// References : -
+// Remarks : -
+// Created : 020422 , 23 April 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+void ClearAllFileNames(HWND hwndDlg)
+{
+ LVITEM sItem = { 0 };
+ sItem.mask = LVIF_TEXT;
+ sItem.pszText = _T("");
+
+ HWND hMapUser = GetDlgItem( hwndDlg , IDC_MAP_USER_LIST );
+ int nCount = ListView_GetItemCount( hMapUser );
+ for( int nCur = 0 ; nCur < nCount ; nCur++ )
+ {
+ sItem.iItem = nCur;
+ ListView_SetItem( hMapUser, &sItem );
+ }
+ if( ! bUnaplyedChanges )
+ {
+ bUnaplyedChanges = TRUE;
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : AutoFindeFileNames
+// Type : Global
+// Parameters : hwndDlg - handle to the parrent, ( Options Dlg )
+// Returns : void
+// Description : Try to finde new file names for user's with 2or more UIN's
+//
+// References : -
+// Remarks : -
+// Created : 020422 , 23 April 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+void AutoFindeFileNames(HWND hwndDlg)
+{
+
+ _TCHAR szDefaultFile[500];
+ GetDlgItemText( hwndDlg , IDC_DEFAULT_FILE , szDefaultFile , sizeof( szDefaultFile ) );
+
+ LVITEM sItem = { 0 };
+
+ HWND hMapUser = GetDlgItem( hwndDlg , IDC_MAP_USER_LIST );
+ int nCount = ListView_GetItemCount( hMapUser );
+ for( int nCur = 0 ; nCur < nCount ; nCur++ )
+ {
+ _TCHAR szSearch[ 100 ];
+
+ sItem.mask = LVIF_TEXT;
+ sItem.iItem = nCur;
+ sItem.iSubItem = 1;
+ sItem.pszText = szSearch;
+ sItem.cchTextMax = sizeof( szSearch );
+
+ if( ! ListView_GetItem( hMapUser, &sItem ) )
+ {
+ continue;
+ }
+
+ int nShortestMatch = 0xFFFF;
+ HANDLE hStortest = 0;
+ int nStortestIndex = -1;
+ for( int nSubCur = 0 ; nSubCur < nCount ; nSubCur++ )
+ {
+ if( nSubCur == nCur )
+ continue;
+ _TCHAR szSubCur[ 100 ];
+ sItem.mask = LVIF_TEXT | LVIF_PARAM;
+ sItem.iItem = nSubCur;
+ sItem.iSubItem = 1;
+ sItem.pszText = szSubCur;
+ sItem.cchTextMax = sizeof( szSubCur );
+ if( ListView_GetItem( hMapUser, &sItem ) )
+ {
+ int nLen = _tcslen( szSubCur );
+ if( _tcsncicmp( szSubCur , szSearch , nLen ) == 0 )
+ {
+ if( nLen < nShortestMatch )
+ {
+ nShortestMatch = nLen;
+ nStortestIndex = nSubCur;
+ hStortest = (HANDLE)sItem.lParam;
+ }
+ }
+ }
+ }
+ if( nShortestMatch != 0xFFFF )
+ {
+ tstring sFileName;
+ szSearch[0] = 0;
+ ListView_GetItemText( hMapUser, nCur , 0 , szSearch , sizeof( szSearch ));
+ bool bPriHasFileName = szSearch[0] != 0;
+ if( bPriHasFileName )
+ sFileName = szSearch;
+
+ szSearch[0] = 0;
+ ListView_GetItemText( hMapUser, nStortestIndex , 0 , szSearch , sizeof( szSearch ));
+ bool bSubHasFileName = szSearch[0] != 0;
+ if( bSubHasFileName )
+ sFileName = szSearch;
+
+ if( sFileName.empty() )
+ {
+ sFileName = szDefaultFile;
+ ReplaceDefines( hStortest , sFileName );
+ ReplaceTimeVariables( sFileName );
+ }
+
+ if( !bPriHasFileName )
+ ListView_SetItemText( hMapUser, nCur , 0 , (_TCHAR*)sFileName.c_str() );
+
+ if( !bSubHasFileName )
+ ListView_SetItemText( hMapUser, nStortestIndex , 0 , (_TCHAR*)sFileName.c_str() );
+
+ if( ! bUnaplyedChanges )
+ {
+ bUnaplyedChanges = TRUE;
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ }
+ }
+}
+
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : OpenHelp
+// Type : Global
+// Parameters : hwndDlg - handle to the parrent, ( Options Dlg )
+// Returns : void
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 020427 , 27 April 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+void OpenHelp(HWND hwndDlg)
+{
+ _TCHAR szPath[MAX_PATH];
+ if( GetModuleFileName( hInstance , szPath , sizeof( szPath ) ) )
+ {
+ int nLen = _tcslen( szPath );
+ if( nLen > 3 )
+ {
+ szPath[nLen-1] = 't';
+ szPath[nLen-2] = 'x';
+ szPath[nLen-3] = 't';
+
+ SHELLEXECUTEINFO st = {0};
+ st.cbSize = sizeof(st);
+ st.fMask = SEE_MASK_INVOKEIDLIST;
+ st.hwnd = NULL;
+ st.lpFile = szPath;
+ st.nShow = SW_SHOWDEFAULT;
+ ShellExecuteEx(&st);
+
+ return;
+ }
+ }
+
+ MessageBox( hwndDlg , TranslateTS(_T("Failed to get the path to Msg_Export.dll\nPlease locate Msg_Export.txt your self")),MSG_BOX_TITEL,MB_OK );
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : DlgProcMsgExportOpts
+// Type : Global
+// Parameters : hwndDlg - handle to this dialog
+// msg - ?
+// wParam - ?
+// lParam - ?
+// Returns : static BOOL CALLBACK
+// Description : Main message prossing fore my options dialog
+//
+// References : -
+// Remarks : -
+// Created : 020422 , 22 April 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+static BOOL CALLBACK DlgProcMsgExportOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+// Used to prevent sending the PSM_CHANGED to miranda
+// when initilizing
+ static BOOL bWindowTextSet = FALSE;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ bWindowTextSet = FALSE;
+
+ HWND hMapUser = GetDlgItem( hwndDlg , IDC_MAP_USER_LIST );
+
+ { // init adv. win styles
+ DWORD dw = ListView_GetExtendedListViewStyle( hMapUser );
+ dw |= LVS_EX_HEADERDRAGDROP | LVS_EX_FULLROWSELECT;
+ ListView_SetExtendedListViewStyle( hMapUser , dw /*| LVS_EX_LABELTIP*/);
+ }
+
+
+ int nColumnWidth = 100;
+ RECT rListSize;
+ if( GetWindowRect( hMapUser , &rListSize ) )
+ {
+ nColumnWidth = (rListSize.right - rListSize.left- GetSystemMetrics(SM_CXVSCROLL) - 5 - nUINColWitdh - nProtoColWitdh) / 2;
+ if( nColumnWidth < 10 )
+ nColumnWidth = 10;
+ }
+
+ { // header setup !!
+
+ LVCOLUMN cCol = { 0 };
+ cCol.mask = LVCF_TEXT | LVCF_WIDTH;
+ cCol.cx = nColumnWidth;
+ cCol.pszText = TranslateTS(_T("File"));
+ ListView_InsertColumn( hMapUser , 0 , &cCol );
+ cCol.pszText = TranslateTS(_T("Nick"));
+ ListView_InsertColumn( hMapUser , 1 , &cCol );
+ cCol.cx = nProtoColWitdh;
+ cCol.pszText = TranslateTS(_T("Proto"));
+ ListView_InsertColumn( hMapUser , 2 , &cCol );
+ cCol.cx = nUINColWitdh;
+ cCol.mask |= LVCF_FMT;
+ cCol.fmt = LVCFMT_RIGHT;
+ cCol.pszText = TranslateTS(_T("UIN"));
+
+ ListView_InsertColumn( hMapUser , 3 , &cCol );
+
+ /*
+ int nOrder[3] = { 1 , 2 , 0 };
+ ListView_SetColumnOrderArray( hMapUser , 3 , nOrder );*/
+ }
+
+ {
+ HIMAGELIST hIml;
+ hIml = ImageList_Create( GetSystemMetrics(SM_CXSMICON) , GetSystemMetrics(SM_CYSMICON),ILC_COLOR4|ILC_MASK,2,2);
+ ImageList_AddIcon(hIml,LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_NOTICK)));
+ ImageList_AddIcon(hIml,LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_TICK)));
+ ListView_SetImageList( hMapUser, hIml, LVSIL_SMALL);
+ }
+
+ {
+ tstring sTmp;
+ LVITEM sItem = { 0 };
+ HANDLE hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ for( int nUser = 0; /*hContact*/ ; nUser++ )
+ {
+ sItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
+ sItem.iItem = nUser;
+ sItem.iSubItem = 0;
+ sItem.iImage = DBGetContactSettingByte(hContact,MODULE,"EnableLog",1);
+ sItem.lParam = (LPARAM) hContact;
+
+
+ sTmp = _DBGetString( hContact , MODULE , "FileName" , _T("") );
+ sItem.pszText = (_TCHAR*)sTmp.c_str();
+
+ ListView_InsertItem( hMapUser , &sItem );
+
+ sItem.mask = LVIF_TEXT;
+ sItem.iSubItem = 1;
+ sItem.pszText = (_TCHAR*)NickFromHandle(hContact);
+ ListView_SetItem( hMapUser , &sItem );
+
+ sItem.iSubItem = 2;
+
+ sTmp = _DBGetString( hContact , "Protocol" , "p" , _T("") );
+ string sTmpA = _DBGetStringA( hContact , "Protocol" , "p" , "" );
+ sItem.pszText = (_TCHAR*)sTmp.c_str();
+ ListView_SetItem( hMapUser , &sItem );
+
+
+ DWORD dwUIN = DBGetContactSettingDword(hContact, sTmpA.c_str(), "UIN", 0);
+ _TCHAR szTmp[50];
+ _sntprintf( szTmp , sizeof(szTmp) ,_T("%d") , dwUIN );
+ sItem.iSubItem = 3;
+ sItem.pszText = szTmp;
+ ListView_SetItem( hMapUser , &sItem );
+
+ if( ! hContact ) // written like this to add the current user ( handle = 0 )
+ break;
+
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0);
+ }
+ ListView_SortItems( hMapUser , CompareFunc , 1 );
+
+ sItem.mask = LVIF_STATE;
+ sItem.iItem = 0;
+ sItem.iSubItem = 0;
+ sItem.state = LVIS_FOCUSED;
+ sItem.stateMask = LVIS_FOCUSED;
+ ListView_SetItem( hMapUser , &sItem );
+
+ }
+ HWND hComboBox;
+
+ SetDlgItemInt( hwndDlg , IDC_MAX_CLOUMN_WIDTH , nMaxLineWidth , TRUE );
+
+ {// Export dir
+ SetDlgItemText( hwndDlg , IDC_EXPORT_DIR , sExportDir.c_str() );
+ hComboBox = GetDlgItem( hwndDlg , IDC_EXPORT_DIR );
+ SendMessage( hComboBox , CB_ADDSTRING, 0 , (LPARAM)_T("%dbpath%\\MsgExport\\") );
+ SendMessage( hComboBox , CB_ADDSTRING, 0 , (LPARAM)_T("C:\\Backup\\MsgExport\\") );
+ SendMessage( hComboBox , CB_ADDSTRING, 0 , (LPARAM)_T("%dbpath%\\MsgExport\\%group% - ") );
+ SendMessage( hComboBox , CB_ADDSTRING, 0 , (LPARAM)_T("%dbpath%\\MsgExport\\%group%\\") );
+ }
+ {// default file
+ SetDlgItemText( hwndDlg , IDC_DEFAULT_FILE , sDefaultFile.c_str() );
+ hComboBox = GetDlgItem( hwndDlg , IDC_DEFAULT_FILE );
+ SendMessage( hComboBox , CB_ADDSTRING, 0 , (LPARAM)_T("%nick%.txt") );
+ SendMessage( hComboBox , CB_ADDSTRING, 0 , (LPARAM)_T("%UIN%.txt") );
+ SendMessage( hComboBox , CB_ADDSTRING, 0 , (LPARAM)_T("%group%.txt") );
+ SendMessage( hComboBox , CB_ADDSTRING, 0 , (LPARAM)_T("%e-mail%.txt") );
+ SendMessage( hComboBox , CB_ADDSTRING, 0 , (LPARAM)_T("%identifier%.txt") );
+ SendMessage( hComboBox , CB_ADDSTRING, 0 , (LPARAM)_T("%year%-%month%-%day%.txt") );
+ SendMessage( hComboBox , CB_ADDSTRING, 0 , (LPARAM)_T("%group%\\%nick%.txt") );
+ SendMessage( hComboBox , CB_ADDSTRING, 0 , (LPARAM)_T("%group%\\%UIN%.txt") );
+ SendMessage( hComboBox , CB_ADDSTRING, 0 , (LPARAM)_T("%group%\\%identifier%.txt") );
+ SendMessage( hComboBox , CB_ADDSTRING, 0 , (LPARAM)_T("%protocol%\\%nick%.txt") );
+ SendMessage( hComboBox , CB_ADDSTRING, 0 , (LPARAM)_T("History.txt"));
+ }
+ {// time format
+ SetDlgItemText( hwndDlg , IDC_EXPORT_TIMEFORMAT , sTimeFormat.c_str() );
+ hComboBox = GetDlgItem( hwndDlg , IDC_EXPORT_TIMEFORMAT );
+ SendMessage( hComboBox , CB_ADDSTRING, 0 , (LPARAM)_T("d t") );
+ SendMessage( hComboBox , CB_ADDSTRING, 0 , (LPARAM)_T("d s") );
+ SendMessage( hComboBox , CB_ADDSTRING, 0 , (LPARAM)_T("d m") );
+ SendMessage( hComboBox , CB_ADDSTRING, 0 , (LPARAM)_T("D s") );
+ SendMessage( hComboBox , CB_ADDSTRING, 0 , (LPARAM)_T("D m :"));
+ }
+ {// File viewer
+ SetDlgItemText( hwndDlg , IDC_FILE_VIEWER , sFileViewerPrg.c_str() );
+ hComboBox = GetDlgItem( hwndDlg , IDC_FILE_VIEWER );
+ SendMessage( hComboBox , CB_ADDSTRING, 0 , (LPARAM)_T("") );
+ SendMessage( hComboBox , CB_ADDSTRING, 0 , (LPARAM)_T("C:\\Windows\\Notepad.exe") );
+ SendMessage( hComboBox , CB_ADDSTRING, 0 , (LPARAM)_T("C:\\WinNT\\Notepad.exe") );
+ //EnableWindow( GetDlgItem( hwndDlg , IDC_FILE_VIEWER ) , ! bUseInternalViewer() );
+ }
+
+
+ CheckDlgButton( hwndDlg , IDC_USE_INTERNAL_VIEWER , bUseInternalViewer() ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton( hwndDlg , IDC_REPLACE_MIRANDA_HISTORY , bReplaceHistory ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton( hwndDlg , IDC_APPEND_NEWLINE , bAppendNewLine ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton( hwndDlg , IDC_USE_UTF8_IN_NEW_FILES , bUseUtf8InNewFiles ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton( hwndDlg , IDC_USE_LESS_AND_GREATER_IN_EXPORT , bUseLessAndGreaterInExport ? BST_CHECKED : BST_UNCHECKED );
+
+
+ TranslateDialogDefault(hwndDlg);
+
+ bWindowTextSet = TRUE;
+ return TRUE;
+ }
+ case WM_COMMAND:
+ {
+ switch(LOWORD(wParam))
+ {
+ case ID_EXPORTSELECTED:
+ case IDC_EXPORTALL:
+ {
+ if( bUnaplyedChanges )
+ {
+ DWORD res = MessageBox( hwndDlg , TranslateTS(_T("You have unapplyed changes do you wish to apply these first ?")),MSG_BOX_TITEL,MB_YESNOCANCEL );
+ if( res == IDCANCEL )
+ return TRUE;
+ if( res == IDYES )
+ {
+ if( ! bApplyChanges( hwndDlg ) )
+ {
+ return TRUE;
+ }
+ }
+ }
+ nExportCompleatList( hwndDlg , LOWORD(wParam) == ID_EXPORTSELECTED );
+ return TRUE;
+ }
+ case IDC_EXPORT_DIR:
+ case IDC_EXPORT_TIMEFORMAT:
+ case IDC_DEFAULT_FILE:
+ case IDC_FILE_VIEWER:
+ {
+ if( !bWindowTextSet )
+ return TRUE;
+
+ if( HIWORD(wParam) == CBN_EDITUPDATE || HIWORD(wParam) == CBN_SELCHANGE )
+ {
+ bUnaplyedChanges = TRUE;
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ return TRUE;
+ }
+ case IDC_MAX_CLOUMN_WIDTH:
+ {
+ if( !bWindowTextSet )
+ return TRUE;
+
+ if( HIWORD(wParam) == EN_CHANGE )
+ {
+ bUnaplyedChanges = TRUE;
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ return TRUE;
+ }
+ case IDC_USE_INTERNAL_VIEWER:
+/* {
+ EnableWindow(
+ GetDlgItem( hwndDlg , IDC_FILE_VIEWER ) ,
+ !IsDlgButtonChecked( hwndDlg , IDC_USE_INTERNAL_VIEWER )
+ );
+ }// fall thru here !!*/
+ case IDC_REPLACE_MIRANDA_HISTORY:
+ case IDC_APPEND_NEWLINE:
+ case IDC_USE_UTF8_IN_NEW_FILES:
+ case IDC_USE_LESS_AND_GREATER_IN_EXPORT:
+ {
+ if( HIWORD(wParam) == BN_CLICKED )
+ {
+ bUnaplyedChanges = TRUE;
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ return TRUE;
+ }
+ case ID_USERLIST_USERDETAILS:
+ {
+ LVITEM sItem = { 0 };
+ sItem.mask = LVIF_PARAM;
+ HWND hMapUser = GetDlgItem( hwndDlg , IDC_MAP_USER_LIST );
+ sItem.iItem = ListView_GetNextItem( hMapUser , -1 , LVIS_SELECTED );
+ if( sItem.iItem >= 0 && ListView_GetItem( hMapUser, &sItem ))
+ {
+ CallService(MS_USERINFO_SHOWDIALOG,(WPARAM)sItem.lParam ,0);
+ }
+ return TRUE;
+ }
+ case IDC_AUTO_FILENAME:
+ {
+ AutoFindeFileNames(hwndDlg);
+ return TRUE;
+ }
+ case IDC_CLEAR_ALL:
+ {
+ ClearAllFileNames(hwndDlg);
+ return TRUE;
+
+ }
+ case IDC_OPEN_HELP:
+ {
+ OpenHelp(hwndDlg);
+ return TRUE;
+ }
+ case ID_SET_TO_DEFAULT:
+ {
+ SetToDefault( hwndDlg );
+ return TRUE;
+ }
+ case IDC_FILE_VIEWER_BROWSE:
+ {
+ OPENFILENAME ofn = { 0 }; // common dialog box structure
+ _TCHAR szFile[260]; // buffer for file name
+
+ GetDlgItemText( hwndDlg , IDC_FILE_VIEWER , szFile , sizeof(szFile));
+ // Initialize OPENFILENAME
+ //ZeroMemory(&ofn, sizeof(OPENFILENAME));
+ ofn.lStructSize = sizeof(OPENFILENAME);
+ ofn.hwndOwner = hwndDlg;
+ ofn.lpstrFile = szFile;
+ ofn.nMaxFile = sizeof(szFile);
+ ofn.lpstrFilter = _T("Executable files (*.exe;*.com;*.bat;*.cmd)\0*.exe;*.com;*.bat;*.cmd\0All files(*.*)\0*.*\0");
+ ofn.nFilterIndex = 1;
+ //ofn.lpstrFileTitle = NULL;
+ //ofn.nMaxFileTitle = 0;
+ //ofn.lpstrInitialDir = NULL;
+ ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
+
+ // Display the Open dialog box.
+
+ if (GetOpenFileName(&ofn))
+ {
+ SetDlgItemText( hwndDlg , IDC_FILE_VIEWER , szFile );
+ bUnaplyedChanges = TRUE;
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ // OPENFILENAME
+ //GetOpenFileName(
+ return TRUE;
+ }
+ case IDC_EXPORT_DIR_BROWSE:
+ {
+ LPMALLOC pMalloc;
+
+ //CoInitializeEx(NULL,COINIT_APARTMENTTHREADED );
+ // Get the shells allocator
+ if (FAILED(SHGetMalloc(&pMalloc))) // we need to use this to support old Windows versions
+ {
+ MessageBox( hwndDlg , _T("Failed to get the shells allocator !"),MSG_BOX_TITEL,MB_OK );
+ return TRUE; // TRUE because we have handled the message , sort of *S*
+ }
+
+ // Allocate the Dest Dir buffer to receive browse info
+ _TCHAR * lpDestDir = (_TCHAR * ) pMalloc->Alloc(MAX_PATH+100);
+ if ( ! lpDestDir )
+ {
+ pMalloc->Release();
+ MessageBox( hwndDlg , _T("Failed to Allocate buffer space"),MSG_BOX_TITEL,MB_OK );
+ return TRUE;
+ }
+
+ BROWSEINFO sBrowseInfo;
+ sBrowseInfo.hwndOwner = hwndDlg;
+ sBrowseInfo.pidlRoot = NULL;
+ sBrowseInfo.pszDisplayName = lpDestDir;
+ sBrowseInfo.lpszTitle = TranslateTS(_T("Select Destination Directory"));
+ sBrowseInfo.ulFlags = BIF_NEWDIALOGSTYLE | BIF_EDITBOX;;
+ sBrowseInfo.lpfn = NULL;
+ sBrowseInfo.lParam = 0;
+ sBrowseInfo.iImage = 0;
+
+ LPITEMIDLIST psItemIDList = SHBrowseForFolder(&sBrowseInfo);
+ if( psItemIDList )
+ {
+ SHGetPathFromIDList(psItemIDList, lpDestDir);
+ int n = _tcslen( lpDestDir );
+ if( n > 0 && lpDestDir[n] != '\\' )
+ {
+ lpDestDir[n] = '\\' ;
+ lpDestDir[n+1] = 0;
+ }
+ SetDlgItemText( hwndDlg , IDC_EXPORT_DIR , lpDestDir );
+ bUnaplyedChanges = TRUE;
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ // Clean up
+ pMalloc->Free( psItemIDList );
+ }
+ pMalloc->Free( lpDestDir );
+ pMalloc->Release();
+ return TRUE;
+ }
+ }
+ break;
+ }
+ case WM_CONTEXTMENU:
+ {
+ if( wParam != (WPARAM)GetDlgItem( hwndDlg , IDC_MAP_USER_LIST ) )
+ return FALSE;
+
+ HMENU hMainMenu = LoadMenu(hInstance ,MAKEINTRESOURCE(IDR_MSG_EXPORT));
+ if( hMainMenu )
+ {
+ HMENU hMenu = GetSubMenu(hMainMenu,0);
+
+ POINT pt;
+ pt.x=(short)LOWORD(lParam);
+ pt.y=(short)HIWORD(lParam);
+ if( pt.x == -1 && pt.y == -1 )
+ {
+ HWND hMapUser = GetDlgItem( hwndDlg , IDC_MAP_USER_LIST );
+ int nFirst = ListView_GetNextItem( hMapUser , -1 , LVNI_FOCUSED );
+ if( nFirst >= 0 )
+ {
+ ListView_GetItemPosition( hMapUser , nFirst , &pt );
+ }
+
+ if( pt.y < 16 )
+ pt.y = 16;
+ else
+ {
+ RECT rUserList;
+ GetClientRect( hMapUser , &rUserList );
+ if( pt.y > rUserList.bottom - 16 )
+ pt.y = rUserList.bottom - 16;
+ else
+ pt.y += 8;
+ }
+ pt.x = 8;
+ ClientToScreen(hMapUser,&pt);
+ }
+
+ CallService(MS_LANGPACK_TRANSLATEMENU,(WPARAM)hMenu,0);
+ TrackPopupMenu(hMenu,TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON,pt.x,pt.y,0,hwndDlg,NULL);
+
+ DestroyMenu(hMainMenu);
+ }
+ return TRUE;
+ }
+ case WM_NOTIFY:
+ {
+ NMHDR * p = ((LPNMHDR)lParam);
+ if( p->idFrom == IDC_MAP_USER_LIST )
+ {
+ switch (p->code)
+ {
+ case NM_CLICK:
+ { LVHITTESTINFO hti;
+ LVITEM lvi;
+ hti.pt=((NMLISTVIEW*)lParam)->ptAction;
+ ListView_SubItemHitTest( p->hwndFrom ,&hti);
+
+ if( hti.flags != LVHT_ONITEMICON )
+ break;
+
+ lvi.mask=LVIF_IMAGE;
+ lvi.iItem=hti.iItem;
+ lvi.iSubItem=0;
+ ListView_GetItem( p->hwndFrom , &lvi);
+ lvi.iImage^=1;
+ ListView_SetItem( p->hwndFrom , &lvi);
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+ case LVN_ENDLABELEDIT:
+ {
+ NMLVDISPINFO * pdi = (NMLVDISPINFO *) lParam;
+ if( pdi->item.mask & LVIF_TEXT )
+ {
+ pdi->item.mask &= LVIF_TEXT;
+ ListView_SetItem( p->hwndFrom , &pdi->item );
+
+ bUnaplyedChanges = TRUE;
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ return TRUE;
+ }
+ case LVN_KEYDOWN:
+ {
+ NMLVKEYDOWN * lpnmk = (NMLVKEYDOWN *) lParam;
+ if( lpnmk->wVKey == 'A' && (GetKeyState( VK_CONTROL ) & 0x8000) )
+ {
+ // select all
+ int nCount = ListView_GetItemCount( p->hwndFrom );
+ for( int nCur = 0 ; nCur < nCount ; nCur++ )
+ {
+ ListView_SetItemState( p->hwndFrom , nCur , LVIS_SELECTED , LVIS_SELECTED );
+ }
+ return TRUE;
+ }
+
+
+ if( lpnmk->wVKey == VK_F2 ||
+ ( lpnmk->wVKey >= 'A' && lpnmk->wVKey <= 'Z') ||
+ ( lpnmk->wVKey >= '1' && lpnmk->wVKey <= '9') ||
+ lpnmk->wVKey == VK_BACK
+ )
+ {
+ HWND hEdit = ListView_EditLabel( p->hwndFrom , ListView_GetSelectionMark(p->hwndFrom) );
+ if( hEdit && lpnmk->wVKey != VK_F2 )
+ {
+ if( isupper( lpnmk->wVKey ) )
+ SendMessage( hEdit , WM_CHAR , tolower( lpnmk->wVKey ) , 0 );
+ else
+ SendMessage( hEdit , WM_CHAR , lpnmk->wVKey , 0 );
+ }
+ }
+ return TRUE;
+ }
+ case NM_DBLCLK:
+ {
+ NMITEMACTIVATE * pdi = (NMITEMACTIVATE *) lParam;
+ if( pdi->iItem >= 0 )
+ {
+ ListView_EditLabel( p->hwndFrom , pdi->iItem );
+ }
+ return TRUE;
+ }
+ case NM_CUSTOMDRAW:
+ {
+ LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)lParam;
+ switch(lplvcd->nmcd.dwDrawStage)
+ {
+ case CDDS_PREPAINT:
+ {
+ SetWindowLong(hwndDlg, DWL_MSGRESULT, CDRF_NOTIFYITEMDRAW);
+ return true;
+ }
+ case CDDS_ITEMPREPAINT:
+ {
+ if( lplvcd->nmcd.lItemlParam == 0 )
+ {
+ lplvcd->clrText = RGB( 0 , 0 , 255 );
+ }
+ SetWindowLong(hwndDlg, DWL_MSGRESULT, CDRF_NEWFONT);
+ return true;
+ }
+ }
+ return FALSE;
+ }
+ }
+ }
+ else
+ {
+ switch (p->code)
+ {
+ case PSN_APPLY:
+ {
+ bApplyChanges( hwndDlg );
+ return TRUE;
+ }
+ case HDN_ITEMCLICK:
+ {
+ NMHEADER * phdr = (LPNMHEADER) p;
+ if( phdr->iButton == 0 )// 0 => Left button
+ {
+ HWND hMapUser = GetDlgItem( hwndDlg , IDC_MAP_USER_LIST );
+ ListView_SortItems( hMapUser , CompareFunc , phdr->iItem );
+ return TRUE;
+ }
+ return FALSE;
+ }
+ }
+ }
+ break;
+ }
+ }
+ return FALSE;
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : bApplyChanges2
+// Type : Global
+// Parameters : hwndDlg - ?
+// Returns : Returns true if
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 050429 , 29 april 2005
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+BOOL bApplyChanges2( HWND hwndDlg )
+{
+ if( IsDlgButtonChecked( hwndDlg , IDC_FC_PROMPT ) == BST_CHECKED )
+ enRenameAction = eDAPromptUser;
+ else if( IsDlgButtonChecked( hwndDlg , IDC_FC_RENAME ) == BST_CHECKED )
+ enRenameAction = eDAAutomatic;
+ else if( IsDlgButtonChecked( hwndDlg , IDC_FC_NOTHING ) == BST_CHECKED )
+ enRenameAction = eDANothing;
+
+ if( IsDlgButtonChecked( hwndDlg , IDC_FD_PROMPT ) == BST_CHECKED )
+ enDeleteAction = eDAPromptUser;
+ else if( IsDlgButtonChecked( hwndDlg , IDC_FD_DELETE ) == BST_CHECKED )
+ enDeleteAction = eDAAutomatic;
+ else if( IsDlgButtonChecked( hwndDlg , IDC_FD_NOTHING ) == BST_CHECKED )
+ enDeleteAction = eDANothing;
+
+ char szTemp[ 500 ];
+ strcpy( szTemp , "DisableProt_" );
+
+ HWND hMapUser = GetDlgItem( hwndDlg , IDC_EXPORT_PROTOS );
+ int nCount = ListView_GetItemCount( hMapUser );
+ for( int nCur = 0 ; nCur < nCount ; nCur++ )
+ {
+ LVITEMA sItem = { 0 };
+ sItem.iItem = nCur;
+ sItem.mask = LVIF_TEXT | LVIF_IMAGE;
+ sItem.pszText = &szTemp[12];
+ sItem.cchTextMax = sizeof( szTemp )-15;
+ if( ::SendMessage(hMapUser, LVM_GETITEMA, 0, (LPARAM)&sItem ) )
+ {
+ if( sItem.iImage )
+ DBDeleteContactSetting( NULL , MODULE , szTemp ); // default is Enabled !!
+ else
+ DBWriteContactSettingByte( NULL , MODULE , szTemp,0);
+ }
+ }
+ SaveSettings();
+ return TRUE;
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : DlgProcMsgExportOpts2
+// Type : Global
+// Parameters : hwndDlg - ?
+// msg - ?
+// wParam - ?
+// lParam - ?
+// Returns : static BOOL CALLBACK
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 040205 , 05 februar 2004
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+static BOOL CALLBACK DlgProcMsgExportOpts2(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static BOOL bWindowTextSet = FALSE;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ bWindowTextSet = FALSE;
+ switch( enRenameAction )
+ {
+ case eDAPromptUser:
+ CheckDlgButton( hwndDlg , IDC_FC_PROMPT , true );
+ break;
+ case eDAAutomatic:
+ CheckDlgButton( hwndDlg , IDC_FC_RENAME , true );
+ break;
+ case eDANothing:
+ CheckDlgButton( hwndDlg , IDC_FC_NOTHING , true );
+ break;
+ }
+ switch( enDeleteAction )
+ {
+ case eDAPromptUser:
+ CheckDlgButton( hwndDlg , IDC_FD_PROMPT , true );
+ break;
+ case eDAAutomatic:
+ CheckDlgButton( hwndDlg , IDC_FD_DELETE , true );
+ break;
+ case eDANothing:
+ CheckDlgButton( hwndDlg , IDC_FD_NOTHING , true );
+ break;
+ }
+ HWND hMapUser = GetDlgItem( hwndDlg , IDC_EXPORT_PROTOS );
+/*
+ { // init adv. win styles
+ DWORD dw = ListView_GetExtendedListViewStyle( hMapUser );
+ dw |= LVS_EX_HEADERDRAGDROP | LVS_EX_FULLROWSELECT;
+ ListView_SetExtendedListViewStyle( hMapUser , dw /);
+ }
+*/
+ int nColumnWidth = 100;
+ RECT rListSize;
+ if( GetWindowRect( hMapUser , &rListSize ) )
+ {
+ nColumnWidth = (rListSize.right - rListSize.left- GetSystemMetrics(SM_CXVSCROLL) - 5 );
+ if( nColumnWidth < 10 )
+ nColumnWidth = 10;
+ }
+
+ { // header setup !!
+ LVCOLUMN cCol = { 0 };
+ cCol.mask = LVCF_TEXT | LVCF_WIDTH;
+ cCol.cx = nColumnWidth;
+ cCol.pszText = TranslateTS(_T("Export Protocols"));
+ ListView_InsertColumn( hMapUser , 0 , &cCol );
+ }
+
+ {
+ HIMAGELIST hIml;
+ hIml = ImageList_Create( GetSystemMetrics(SM_CXSMICON) , GetSystemMetrics(SM_CYSMICON),ILC_COLOR4|ILC_MASK,2,2);
+ ImageList_AddIcon(hIml,LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_NOTICK)));
+ ImageList_AddIcon(hIml,LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_TICK)));
+ ListView_SetImageList( hMapUser, hIml, LVSIL_SMALL);
+ }
+
+ {
+ PROTOCOLDESCRIPTOR **proto;
+ int nCount;
+ LVITEMA sItem = { 0 };
+ sItem.mask = LVIF_TEXT | LVIF_IMAGE;
+ char szTemp[ 500 ];
+
+ CallService(MS_PROTO_ENUMPROTOCOLS,(WPARAM)&nCount,(LPARAM)&proto);
+
+ for( int i=0 ; i < nCount ; i++)
+ {
+ if( proto[i]->type==PROTOTYPE_IGNORE) //PROTOTYPE_PROTOCOL
+ continue;
+ _snprintf( szTemp , sizeof( szTemp ) , "DisableProt_%s" , proto[i]->szName );
+ sItem.pszText = proto[i]->szName;
+ sItem.iImage = DBGetContactSettingByte(NULL,MODULE,szTemp,1);
+ ::SendMessage( hMapUser , LVM_INSERTITEMA , 0 ,(LPARAM)&sItem );
+ sItem.iItem++;
+ }
+ }
+
+ TranslateDialogDefault(hwndDlg);
+
+ bWindowTextSet = TRUE;
+ return TRUE;
+ }
+ case WM_COMMAND:
+ {
+ switch(LOWORD(wParam))
+ {
+ case IDC_FC_PROMPT:
+ case IDC_FC_RENAME:
+ case IDC_FC_NOTHING:
+ case IDC_FD_PROMPT:
+ case IDC_FD_DELETE:
+ case IDC_FD_NOTHING:
+ {
+ if( !bWindowTextSet )
+ return TRUE;
+
+ if( HIWORD(wParam) == BN_CLICKED )
+ {
+ bUnaplyedChanges = TRUE;
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ return TRUE;
+ }
+ case IDC_DEBUG_INFO:
+ {
+ ShowDebugInfo();
+ return TRUE;
+ }
+ }
+ break;
+ }
+ case WM_NOTIFY:
+ {
+ NMHDR * p = ((LPNMHDR)lParam);
+ if( p->idFrom == IDC_EXPORT_PROTOS )
+ {
+ switch (p->code)
+ {
+ case NM_CLICK:
+ { LVHITTESTINFO hti;
+ LVITEM lvi;
+ hti.pt=((NMLISTVIEW*)lParam)->ptAction;
+ ListView_SubItemHitTest( p->hwndFrom ,&hti);
+
+ if( hti.flags != LVHT_ONITEMICON )
+ break;
+
+ lvi.mask=LVIF_IMAGE;
+ lvi.iItem=hti.iItem;
+ lvi.iSubItem=0;
+ ListView_GetItem( p->hwndFrom , &lvi);
+ lvi.iImage^=1;
+ ListView_SetItem( p->hwndFrom , &lvi);
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+ }
+ break;
+ }
+ switch (p->code)
+ {
+ case PSN_APPLY:
+ {
+ bApplyChanges2(hwndDlg);
+ return TRUE;
+ }
+ case HDN_ITEMCLICK:
+ {
+ return FALSE;
+ }
+ }
+ break;
+ }
+ }
+ //
+ return FALSE;
+}
+
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : OptionsInitialize
+// Type : Global
+// Parameters : wParam - ?
+// lParam - ?
+// Returns : int
+// Description : Called when the user openes the options dialog
+// I need to add my options page.
+// References : -
+// Remarks : -
+// Created : 020422 , 22 April 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+int OptionsInitialize(WPARAM wParam,LPARAM /*lParam*/)
+{
+ OPTIONSDIALOGPAGE odp;
+
+ bUnaplyedChanges = FALSE;
+
+ ZeroMemory(&odp,sizeof(odp));
+ odp.cbSize = sizeof(odp);
+ odp.position = 100000000;
+ odp.hInstance = hInstance;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_MSGEXPORT);
+ odp.flags = ODPF_BOLDGROUPS;
+ odp.pszTitle = Translate("Message export");
+ odp.pszGroup = Translate("Plugins");
+ odp.groupPosition = 100000000;
+ odp.pfnDlgProc = DlgProcMsgExportOpts;
+ Options_AddPage(wParam,&odp);
+
+
+ odp.position = 100000001;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_MSGEXPORT2);
+ odp.pszTitle = Translate("Message export2");
+ odp.pfnDlgProc = DlgProcMsgExportOpts2;
+ Options_AddPage(wParam,&odp);
+ return 0;
+}
diff --git a/plugins/Msg_Export/src/options.h b/plugins/Msg_Export/src/options.h
new file mode 100755
index 0000000000..60debd4b77
--- /dev/null
+++ b/plugins/Msg_Export/src/options.h
@@ -0,0 +1,26 @@
+
+//This file is part of Msg_Export a Miranda IM plugin
+//Copyright (C)2002 Kennet Nielsen ( http://sourceforge.net/projects/msg-export/ )
+//
+//This program is free software; you can redistribute it and/or
+//modify it under the terms of the GNU General Public License
+//as published by the Free Software Foundation; either
+//version 2 of the License, or (at your option) any later version.
+//
+//This program is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//GNU General Public License for more details.
+//
+//You should have received a copy of the GNU General Public License
+//along with this program; if not, write to the Free Software
+//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+#ifndef MSG_EXP_OPTIONS_H
+#define MSG_EXP_OPTIONS_H
+
+int OptionsInitialize( WPARAM , LPARAM );
+int nExportCompleatList(HWND hParent , bool bOnlySelected );
+
+#endif \ No newline at end of file
diff --git a/plugins/Msg_Export/src/resource.h b/plugins/Msg_Export/src/resource.h
new file mode 100755
index 0000000000..cd12714f9a
--- /dev/null
+++ b/plugins/Msg_Export/src/resource.h
@@ -0,0 +1,59 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by resource.rc
+//
+#define IDI_EXPORT_MESSAGE 108
+#define IDD_EXPORT_ALL_DLG 110
+#define IDR_MSG_EXPORT 114
+#define IDD_FILE_VIEWER 116
+#define IDR_FV_EDIT 117
+#define IDD_OPT_MSGEXPORT2 123
+#define IDI_NOTICK 205
+#define IDI_TICK 206
+#define IDD_OPT_MSGEXPORT 999
+#define IDC_EXPORTALL 1001
+#define IDC_EXPORT_DIR 1002
+#define IDC_MAX_CLOUMN_WIDTH 1003
+#define IDC_EXPORT_TIMEFORMAT 1004
+#define IDC_EXPORT_DIR_BROWSE 1032
+#define IDC_MAP_USER_LIST 1034
+#define IDC_AUTO_FILENAME 1035
+#define IDC_CLEAR_ALL 1036
+#define IDC_EXPORT_PROGRESS 1037
+#define IDC_EXP_ALL_STATUS 1039
+#define IDC_OPEN_HELP 1041
+#define IDC_DEFAULT_FILE 1043
+#define IDC_RICHEDIT 1046
+#define IDC_USE_INTERNAL_VIEWER 1048
+#define IDC_FV_EXTERNAL 1049
+#define IDC_FV_FIND 1050
+#define IDC_REPLACE_MIRANDA_HISTORY 1054
+#define IDC_DEBUG_INFO 1060
+#define IDC_FILE_VIEWER_BROWSE 1063
+#define IDC_FILE_VIEWER 1064
+#define IDC_APPEND_NEWLINE 1065
+#define IDC_USE_LESS_AND_GREATER_IN_EXPORT 1066
+#define IDC_FC_PROMPT 1067
+#define IDC_FC_RENAME 1068
+#define IDC_FC_NOTHING 1069
+#define IDC_FD_PROMPT 1070
+#define IDC_FD_DELETE 1071
+#define IDC_FD_NOTHING 1072
+#define IDC_EXPORT_PROTOS 1073
+#define IDC_USE_UTF8_IN_NEW_FILES 1074
+#define ID_EXPORTSELECTED 40002
+#define ID_EDIT_COPY 40003
+#define ID_SET_TO_DEFAULT 40004
+#define ID_USERLIST_USERDETAILS 40005
+#define IDC_STATIC -1
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 124
+#define _APS_NEXT_COMMAND_VALUE 40006
+#define _APS_NEXT_CONTROL_VALUE 1075
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/Msg_Export/src/utils.cpp b/plugins/Msg_Export/src/utils.cpp
new file mode 100755
index 0000000000..15ed559553
--- /dev/null
+++ b/plugins/Msg_Export/src/utils.cpp
@@ -0,0 +1,1738 @@
+
+//This file is part of Msg_Export a Miranda IM plugin
+//Copyright (C)2002 Kennet Nielsen ( http://sourceforge.net/projects/msg-export/ )
+//
+//This program is free software; you can redistribute it and/or
+//modify it under the terms of the GNU General Public License
+//as published by the Free Software Foundation; either
+//version 2 of the License, or (at your option) any later version.
+//
+//This program is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//GNU General Public License for more details.
+//
+//You should have received a copy of the GNU General Public License
+//along with this program; if not, write to the Free Software
+//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+
+#include <stdio.h>
+
+#include "Glob.h"
+#include "Utils.h"
+#include "FileViewer.h"
+
+#pragma warning (disable:4996)
+#include <m_protosvc.h>
+#include <m_icq.h>
+#pragma warning (default:4996)
+
+// Default error string used upon errors
+const _TCHAR *pszNickError = _T("No_Nick");
+const _TCHAR *pszGroupError = _T("No_Group");
+const _TCHAR *pszDbPathError = _T(".");
+
+// Replacement for chareteres not alowed in file names.
+const _TCHAR cBadCharReplace = _T('_');
+
+// sTimeFormat
+tstring sTimeFormat;
+
+// path from options dialog
+tstring sExportDir;
+
+// The default filename. Used if no other file name is specifyed in DB.
+tstring sDefaultFile;
+
+// path used then %dbpath% is used in export file path
+tstring sDBPath = pszDbPathError;
+
+// path to miranda exe file used when to avoid relative paths
+tstring sMirandaPath = pszDbPathError;
+
+// Used to store the width of the user name for a file.
+// if a file contains events from many users the one user name
+// may be shorter. so to make all event have the same first
+// column width this map contains the largest user name
+map<tstring , string::size_type , less<tstring> > clFileTo1ColWidth;
+
+// default line width
+int nMaxLineWidth = 80;
+
+const _TCHAR *pszReplaceList[] =
+{
+ _T("%FirstName%") ,
+ _T("%LastName%") ,
+ _T("%e-mail%") ,
+ _T("%Nick%") ,
+ _T("%City%") ,
+ _T("%State%") ,
+ _T("%Phone%") ,
+ _T("%Homepage%") ,
+ _T("%About%")
+};
+const char *pszReplaceListA[] =
+{
+ "FirstName" ,
+ "LastName" ,
+ "e-mail" ,
+ "Nick" ,
+ "City" ,
+ "State" ,
+ "Phone" ,
+ "Homepage" ,
+ "About"
+};
+
+// Alowes this plugin to replace the history function of miranda !!
+bool bReplaceHistory = false;
+
+// This enum define the actions which MsgExport must take when a File is renamed
+ENDialogAction enRenameAction = eDAPromptUser;
+
+// This enum define the actions which MsgExport must take when a user is delete
+ENDialogAction enDeleteAction = eDAPromptUser;
+
+// If true MsgExport will use << and >> insted of the nick in the exported format
+bool bUseLessAndGreaterInExport = false;
+
+bool bAppendNewLine = true;
+bool bUseUtf8InNewFiles = true;
+
+const char szUtf8ByteOrderHeader[] = "\xEF\xBB\xBF";
+bool bIsUtf8Header( BYTE * pucByteOrder )
+{
+ return memcmp( pucByteOrder , szUtf8ByteOrderHeader , 3 ) == 0;
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : ShowDebugInfo
+// Type : Global
+// Parameters : None
+// Returns : void
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 021228 , 28 December 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+void ShowDebugInfo()
+{
+ tstring sDebug = _T("Debug information\r\nsDBPath :");
+ sDebug += sDBPath;
+ sDebug += _T("\r\nsMirandaPath :");
+ sDebug += sMirandaPath;
+ sDebug += _T("\r\nsDefaultFile :");
+ sDebug += sDefaultFile;
+
+ sDebug += _T("\r\nGetFilePathFromUser( NULL ) :");
+ sDebug += GetFilePathFromUser( NULL );
+
+ MessageBox( NULL , sDebug.c_str() ,MSG_BOX_TITEL,MB_OK );
+}
+
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : nGetFormatCount
+// Type : Global
+// Parameters : pszToCheck - ?
+// Returns : int
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 030107 , 07 January 2003
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+int nGetFormatCount( const _TCHAR * pszToCheck )
+{
+ if( !pszToCheck || pszToCheck[0] == 0 )
+ return 0;
+
+ int nCount = 0;
+ for( ; pszToCheck[1] != 0 ; pszToCheck++)
+ {
+ if( pszToCheck[0] == '%' && pszToCheck[1] != '%' )
+ nCount++;
+ }
+ return nCount;
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : CheckedTranslate
+// Type : Global
+// Parameters : szEng - ?
+// nFormatCount - ?
+// Returns : _TCHAR *
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 030107 , 07 January 2003
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+_TCHAR * CheckedTranslate( const _TCHAR *szEng , int nFormatCount /*= -1*/ )
+{
+ _TCHAR * szRet = TranslateTS( szEng );
+ if( szEng == szRet )
+ return (_TCHAR*)szEng;
+
+ if( nFormatCount == -1 )
+ nFormatCount = nGetFormatCount( szEng );
+
+ if( nFormatCount != nGetFormatCount( szRet ) )
+ {
+ tstring sError = _T("The language pack you are using has an error in the transalation of\r\n");
+ sError += szEng;
+ sError += _T("\r\n--------------- It was translated to ---------------\r\n");
+ sError += szRet;
+ MessageBox( NULL , sError.c_str() ,MSG_BOX_TITEL ,MB_OK );
+ return (_TCHAR*)szEng;
+ }
+ return szRet;
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : sGetErrorString
+// Type : Global
+// Parameters : dwError - ?
+// Returns : string
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 021012 , 12 October 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+tstring sGetErrorString(DWORD dwError)
+{
+ LPVOID lpMsgBuf;
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ dwError,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPTSTR) &lpMsgBuf,
+ 0,
+ NULL );
+ // Process any inserts in lpMsgBuf.
+ // ...
+ // Display the string.
+ tstring ret = (LPCTSTR)lpMsgBuf;
+ ReplaceAll( ret , _T("\r") , _T(" "));
+ ReplaceAll( ret , _T("\n") , _T(" "));
+ ReplaceAll( ret , _T(" ") , _T(" "));
+
+ // Free the buffer.
+ LocalFree( lpMsgBuf );
+ return ret;
+}
+
+tstring sGetErrorString()
+{
+ return sGetErrorString(GetLastError());
+}
+
+void DisplayLastError(const _TCHAR * pszError)
+{
+ tstring sError = pszError;
+ DWORD error = GetLastError();
+
+ _TCHAR szTemp[50];
+ _sntprintf( szTemp , sizeof( szTemp ) , _T("\r\nErrorCode : %d\r\n") , error );
+ sError += szTemp;
+ sError += sGetErrorString(error);
+ MessageBox( NULL , sError.c_str() ,MSG_BOX_TITEL ,MB_OK );
+}
+
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : NickFromHandle
+// Type : Global
+// Parameters : hContact - ?
+// Returns : _TCHAR*
+// Description : Reads a Nick from the database and returns a
+// pointer to this.
+// References : -
+// Remarks : -
+// Created : 020422 , 22 April 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+const _TCHAR* NickFromHandle(HANDLE hContact)
+{
+ const _TCHAR * psz = (const _TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR );
+ if( psz )
+ return psz;
+ return pszNickError;
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : _DBGetString
+// Type : Global
+// Parameters : hContact - ?
+// szModule - ?
+// szSetting - ?
+// pszError - ?
+// Returns : string
+// Description : Reads a string from the database
+// Just like those in database.h
+// References : -
+// Remarks : -
+// Created : 020422 , 22 April 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+tstring _DBGetStringW(HANDLE hContact,const char *szModule,const char *szSetting , const _TCHAR * pszError )
+{
+ tstring ret;
+ DBVARIANT dbv = {0};
+ //DBGetContactSetting
+ if( ! DBGetContactSettingWString( hContact , szModule , szSetting , &dbv ) )
+ {
+ if( dbv.type != DBVT_WCHAR)
+ {
+ MessageBox(NULL,_T("DB: Attempt to get wrong type of value, string"),MSG_BOX_TITEL,MB_OK);
+ ret = pszError;
+ }
+ else
+ {
+ ret = (_TCHAR*)dbv.pszVal;
+ }
+ }
+ else
+ ret = pszError;
+ DBFreeVariant(&dbv);
+ return ret;
+}
+
+string _DBGetStringA(HANDLE hContact,const char *szModule,const char *szSetting , const char * pszError )
+{
+ string ret;
+ DBVARIANT dbv = {0};
+ if( ! DBGetContactSetting( hContact , szModule , szSetting , &dbv ) )
+ {
+ if( dbv.type != DBVT_ASCIIZ)
+ {
+ MessageBox(NULL,_T("DB: Attempt to get wrong type of value, string"),MSG_BOX_TITEL,MB_OK);
+ ret = pszError;
+ }
+ else
+ {
+ ret = dbv.pszVal;
+ }
+ }
+ else
+ ret = pszError;
+ DBFreeVariant(&dbv);
+ return ret;
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : ReplaceAll
+// Type : Global
+// Parameters : sSrc - string to replace in
+// pszReplace - what to replace
+// sNew - the string to insert insted of pszReplace
+// Returns : void
+// Description : will replace all acurances of a string with another string
+// used to replace %user% , and other user
+// References : -
+// Remarks : -
+// Created : 020422 , 22 April 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+void ReplaceAll( tstring &sSrc , const _TCHAR * pszReplace , const tstring &sNew)
+{
+ string::size_type nCur = 0;
+ while( (nCur = sSrc.find(pszReplace,nCur)) != sSrc.npos )
+ {
+ sSrc.replace( nCur , _tcslen( pszReplace ) , sNew );
+ nCur += sNew.size();
+ }
+}
+
+void ReplaceAll( tstring &sSrc , const _TCHAR * pszReplace , const _TCHAR * pszNew)
+{
+ tstring sNew = pszNew;
+ ReplaceAll( sSrc , pszReplace , sNew );
+}
+
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : bCreatePathToFile
+// Type : Global
+// Parameters : sFilePath - File name to create path to ( file name may be empty ( i.e. c:\Folder\ )
+// Returns : Returns true if the path is created or already exists
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 020525 , 25 May 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+bool bCreatePathToFile( tstring sFilePath )
+{
+ string::size_type nPos = sFilePath.rfind( '\\' );
+ if( nPos != string::npos )
+ {
+ if( nPos + 1 < sFilePath.size() )
+ sFilePath.erase( nPos + 1);
+ }
+ else
+ {
+ // cant find \
+ return false;
+ }
+
+ // create directory
+ if( ! CreateDirectory( sFilePath.c_str() , NULL ) )
+ {
+ DWORD dwE = GetLastError();
+ if( dwE == 183 ) // Cannot create a file when that file already exists.
+ return true;
+ if( ! bCreatePathToFile( sFilePath.substr( 0 , nPos ) ) )
+ return false;
+
+ // try again
+ if( ! CreateDirectory( sFilePath.c_str() , NULL ) )
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : bWriteToFile
+// Type : Global
+// Parameters : hFile - ?
+// pszSrc - in UTF8 or ANSII
+// nLen - ?
+// Returns : Returns true if all the data was written to the file
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 020629 , 29 June 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+bool bWriteToFile( HANDLE hFile , const char * pszSrc , int nLen = -1 )
+{
+ if( nLen < 0 )
+ nLen = strlen( pszSrc );
+ DWORD dwBytesWritten;
+ return WriteFile( hFile , pszSrc , nLen , &dwBytesWritten , NULL ) && (dwBytesWritten == (DWORD)nLen);
+}
+
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : bWriteTextToFile
+// Type : Global
+// Parameters : hFile - ?
+// pszSrc - ?
+// bUtf8File - ?
+// Returns : Returns true if
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 060130 , 30 januar 2006
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+bool bWriteTextToFile( HANDLE hFile , const _TCHAR * pszSrc , bool bUtf8File ,int nLen = -1 )
+{
+ if( nLen < 0 )
+ nLen = _tcslen( pszSrc );
+ if( ! bUtf8File )
+ {
+#ifdef _UNICODE // We need to downgrade text to ansi
+ char * pszAstr = new char[nLen];
+ int nAnsiLen = WideCharToMultiByte(CP_ACP, 0, pszSrc, nLen, pszAstr , nLen , NULL , NULL );
+ bool bRet = bWriteToFile( hFile , pszAstr , nAnsiLen );
+ delete [] pszAstr;
+ return bRet;
+#else
+ return bWriteToFile( hFile , pszSrc , nLen );
+#endif
+ }
+#ifndef _UNICODE
+ wchar_t * pszWstr = new wchar_t[nLen];
+ if( MultiByteToWideChar(CP_ACP, 0, pszSrc, nLen, pszWstr, nLen ) != nLen )
+ {
+ delete [] pszWstr;
+ return false;
+ }
+ char * pszUtf8 = new char[nLen*2];// Ansi can't generate more then this.
+ int nUtf8Len = WideCharToMultiByte(CP_UTF8, 0, pszWstr, nLen, pszUtf8 , nLen * 2 , NULL , NULL );
+ delete [] pszWstr;
+ if( nUtf8Len < nLen ) // Not all was converted ?
+ {
+ delete [] pszUtf8;
+ return false;
+ }
+ bool bRet = bWriteToFile( hFile , pszUtf8 , nUtf8Len );
+ delete [] pszUtf8;
+#else
+ char * pszUtf8 = new char[nLen*3];// UCS-2 can't generate more then this.
+ int nUtf8Len = WideCharToMultiByte(CP_UTF8, 0, pszSrc, nLen, pszUtf8 , nLen * 3 , NULL , NULL );
+ bool bRet = bWriteToFile( hFile , pszUtf8 , nUtf8Len );
+#endif
+ return bRet;
+}
+
+#ifdef _UNICODE
+bool bWriteTextToFile( HANDLE hFile , const char * pszSrc , bool bUtf8File ,int nLen = -1 )
+{
+ if( nLen == -1 )
+ nLen = strlen( pszSrc );
+ wchar_t * pszWstr = new wchar_t[nLen];
+ bool bRet = false;
+ if( MultiByteToWideChar(CP_ACP, 0, pszSrc, nLen, pszWstr, nLen ) == nLen )
+ {
+ bRet = bWriteTextToFile( hFile , pszWstr , bUtf8File , nLen );
+ }
+ return bRet;
+}
+#endif
+
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : bWriteNewLine
+// Type : Global
+// Parameters : hFile - ?
+// nIndent - ?
+// Returns : Returns true if all the data was written to the file
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 020629 , 29 June 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+const char szNewLineIndent[] = "\r\n ";
+bool bWriteNewLine( HANDLE hFile , DWORD dwIndent )
+{
+ if( dwIndent > sizeof( szNewLineIndent ) - 2 )
+ dwIndent = sizeof( szNewLineIndent ) - 2;
+ return bWriteToFile( hFile , szNewLineIndent , dwIndent + 2 );
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : bWriteHexToFile
+// Type : Global
+// Parameters : hFile - ?
+// - ?
+// nSize - ?
+// Returns : void
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 021203 , 03 December 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+bool bWriteHexToFile( HANDLE hFile , void * pData, int nSize )
+{
+ char cBuf[10];
+ BYTE * p = (BYTE*)pData;
+ for( int n = 0 ; n < nSize ; n++ )
+ {
+ sprintf( cBuf , "%.2X " , p[n] );
+ if( ! bWriteToFile( hFile , cBuf , 3 ) )
+ return false;
+ }
+ return true;
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : bReadMirandaDirAndPath
+// Type : Global
+// Parameters : None
+// Returns : void
+// Description : Used to set the internal path.
+// Handles the reading from the mirandaboot.ini to get the %dbpath%
+// References : -
+// Remarks : -
+// Created : 020422 , 22 April 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+
+bool bReadMirandaDirAndPath()
+{
+ _TCHAR szDBPath[MAX_PATH];
+ char tmp[MAX_PATH];
+ TCHAR *tmp2;
+ _tcscpy( szDBPath , pszDbPathError );
+ CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)"miranda32.exe", (LPARAM)tmp);
+ tmp2 = mir_utf8decodeT(tmp);
+ sMirandaPath = tmp2;
+ sMirandaPath.erase(sMirandaPath.find_last_of(_T("\\")));
+ CallService(MS_DB_GETPROFILEPATHT, (WPARAM)MAX_PATH - 1, (LPARAM)szDBPath);
+ sDBPath = szDBPath;
+ CallService(MS_DB_GETPROFILENAMET, (WPARAM)MAX_PATH - 1, (LPARAM)szDBPath);
+ sDBPath.append(_T("\\")).append(szDBPath);
+ sDBPath.erase(sDBPath.size()-4);
+ return true;
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : ReplaceDBPath
+// Type : Global
+// Parameters : sRet - ?
+// Returns : void
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 021020 , 20 October 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+void ReplaceDBPath( tstring &sRet )
+{
+ ReplaceAll( sRet , _T("%dbpath%") , sDBPath );
+ // Try to firure out if it is a relative path ( ..\..\MsgExport\ )
+ if( sRet.size() <= 2 || ! ( sRet[1] == ':' ||
+ ( sRet[0] == '\\' && sRet[1] == '\\' ) )
+ )
+ {
+ // Relative path
+ // we will prepend the mirande exe path to avoid problems
+ // if the current directory changes ( User receives a file )
+ sRet = sMirandaPath + sRet;
+ }
+}
+
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : GetFilePathFromUser
+// Type : Global
+// Parameters : hContact - Handle to user
+// Returns : string contaning the compleate file name and path
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 020422 , 22 April 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+tstring GetFilePathFromUser( HANDLE hContact )
+{
+ tstring sFilePath = sExportDir + _DBGetString( hContact , MODULE , "FileName" , sDefaultFile.c_str() );
+
+ bool bNickUsed = sFilePath.find( _T("%nick%") ) != string::npos;
+
+ ReplaceDefines( hContact , sFilePath );
+
+ tstring sNoDBPath = sFilePath;
+
+ ReplaceTimeVariables( sFilePath );
+ ReplaceDBPath( sFilePath );
+
+ // Previous file name check to see if it has changed !!
+ tstring sPrevFileName = _DBGetString( hContact , MODULE , "PrevFileName" , _T("") );
+ if( sNoDBPath != sPrevFileName )
+ {
+ if( ! sPrevFileName.empty() )
+ {
+ ReplaceDBPath( sPrevFileName );
+
+ // Here we will try to avoide the (Unknown Contact) in cases where the protocol for
+ // this user has been removed.
+ if( bNickUsed && ( _tcsstr( NickFromHandle( hContact ),TranslateTS(_T("(Unknown Contact)"))) != 0) )
+ {
+ // Then the filename must have changed from a correct path to one including the (Unknown Contact)
+ return sPrevFileName;
+ }
+
+ // file name has changed
+
+ if( enRenameAction != eDANothing )
+ {
+
+ // we can not use FILE_SHARE_DELETE because this is not supported by
+ // win 98 / ME
+ HANDLE hPrevFile = CreateFile( sPrevFileName.c_str() ,
+ GENERIC_READ ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE ,
+ NULL,
+ OPEN_EXISTING ,
+ FILE_ATTRIBUTE_NORMAL ,
+ NULL );
+
+ if( hPrevFile != INVALID_HANDLE_VALUE )
+ {
+ CloseHandle( hPrevFile );
+ _TCHAR szTemp[500];
+ // There is a previous file we can move
+ // ask user ?
+ bool bTryRename;
+
+ if( enRenameAction != eDAAutomatic )
+ {
+ tstring sRemoteUser = NickFromHandle(hContact);
+ _sntprintf( szTemp , sizeof( szTemp ) ,
+ CheckedTranslate(_T("File name for the user \"%s\" has changed !\n\nfrom:\t%s\nto:\t%s\n\nDo you wish to rename file ?"),3) ,
+ sRemoteUser.c_str(),
+ sPrevFileName.c_str(),
+ sFilePath.c_str() );
+ bTryRename = MessageBox( NULL , szTemp ,MSG_BOX_TITEL ,MB_YESNO ) == IDYES;
+ }
+ else
+ bTryRename = true;
+
+
+ if( bTryRename )
+ {
+ if( ! MoveFile( sPrevFileName.c_str(), sFilePath.c_str() ) )
+ {
+ // this might be because the new path isent created
+ // so we will try to create it
+ bCreatePathToFile( sFilePath );
+
+ while( ! MoveFile( sPrevFileName.c_str(), sFilePath.c_str() ) )
+ {
+ _sntprintf( szTemp , sizeof( szTemp ) ,
+ CheckedTranslate(_T("Failed to rename file\n\nfrom:\t%s\nto:\t%s\n\nFailed with error: %s"),3) ,
+ sPrevFileName.c_str(),
+ sFilePath.c_str() ,
+ sGetErrorString().c_str() );
+
+ if( MessageBox( NULL , szTemp ,MSG_BOX_TITEL,MB_RETRYCANCEL ) != IDRETRY )
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Store the Filename used so that we can check if it changes.
+ DBWriteContactSettingTString( hContact , MODULE , "PrevFileName" , sNoDBPath.c_str() );
+ }
+
+ return sFilePath;
+}
+
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : FileNickFromHandle
+// Type : Global
+// Parameters : hContact - ?
+// Returns : string
+// Description : Replaceses invalid file name chars
+// References : -
+// Remarks : -
+// Created : 030107 , 07 January 2003
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+tstring FileNickFromHandle( HANDLE hContact)
+{
+ tstring ret = NickFromHandle( hContact );
+ string::size_type nCur = 0;
+ while( (nCur = ret.find_first_of(_T(":\\"),nCur)) != ret.npos )
+ ret[nCur] = cBadCharReplace;
+ return ret;
+}
+
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : ReplaceAllNoColon
+// Type : Global
+// Parameters : sSrc - ?
+// pszReplace - ?
+// sNew - ?
+// Returns : void
+// Description : Removes any ':' in the new string
+//
+// References : -
+// Remarks : -
+// Created : 040205 , 05 februar 2004
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+void ReplaceAllNoColon( tstring &sSrc , const _TCHAR * pszReplace , tstring &sNew)
+{
+ tstring::size_type nCur = 0;
+ while( (nCur = sNew.find_first_of(_T(':'),nCur)) != sNew.npos )
+ sNew[nCur] = cBadCharReplace;
+ ReplaceAll( sSrc , pszReplace , sNew );
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : ReplaceDefines
+// Type : Global
+// Parameters : hContact - Handle to user
+// sTarget - String with either %user% or %UIN%, to replace in
+// Returns : void
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 020525 , 25 May 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+void ReplaceDefines( HANDLE hContact , tstring & sTarget )
+{
+ if( sTarget.find( _T("%nick%") ) != string::npos )
+ {
+ ReplaceAll( sTarget , _T("%nick%") , FileNickFromHandle( hContact ) );
+ }
+
+ bool bUINUsed = sTarget.find( _T("%UIN%") ) != string::npos;
+ bool bEMailUsed = sTarget.find( _T("%e-mail%") ) != string::npos;
+ bool bProtoUsed = sTarget.find( _T("%protocol%") ) != string::npos;
+ bool bIdentifierUsed = sTarget.find( _T("%identifier%") ) != string::npos;
+
+ if( bUINUsed || bEMailUsed || bProtoUsed || bIdentifierUsed )
+ {
+ string sProto = _DBGetStringA( hContact , "Protocol" , "p" , "" );
+ if( bUINUsed || ( bIdentifierUsed && sProto == "ICQ" ) )
+ {
+ DWORD dwUIN = DBGetContactSettingDword(hContact, sProto.c_str(), "UIN", 0);
+ tstring sReplaceUin;
+ if( dwUIN )
+ {
+ _TCHAR sTmp[20];
+ _sntprintf( sTmp , sizeof( sTmp ) ,_T("%d") , dwUIN );
+ sReplaceUin = sTmp;
+ }
+ else
+ {
+ sReplaceUin = FileNickFromHandle( hContact );
+ }
+
+ if( bUINUsed )
+ ReplaceAll( sTarget , _T("%UIN%") , sReplaceUin );
+ if( bIdentifierUsed && sProto == "ICQ" )
+ {
+ bIdentifierUsed = false;
+ ReplaceAll( sTarget , _T("%identifier%") , sReplaceUin );
+ }
+ }
+
+ if( bEMailUsed || ( bIdentifierUsed && sProto == "MSN"))
+ {
+ tstring sEMail = _DBGetString( hContact , sProto.c_str() , "e-mail" , _T("") );
+ if( sEMail.empty() )
+ {
+ sEMail = _DBGetString( hContact , "MSN" , "e-mail" , _T("") );
+ if( sEMail.empty() )
+ {
+ // We can't finde the E-mail address we will use the the nick
+ sEMail = FileNickFromHandle( hContact );
+ }
+ }
+ if( bEMailUsed )
+ ReplaceAllNoColon( sTarget , _T("%e-mail%") , sEMail );
+ if( bIdentifierUsed && sProto == "MSN")
+ {
+ bIdentifierUsed = false;
+ ReplaceAllNoColon( sTarget , _T("%identifier%") , sEMail );
+ }
+ }
+ if( bIdentifierUsed && sProto == "Jabber" )
+ {
+ tstring sReplace = _DBGetString( hContact , "Jabber" , "jid" , _T("") );
+ if( sReplace.empty() )
+ {
+ sReplace = FileNickFromHandle( hContact );
+ }
+ bIdentifierUsed = false;
+ ReplaceAll( sTarget , _T("%identifier%") , sReplace );
+ }
+ if( bProtoUsed )
+ {
+ tstring tmp = _DBGetString( hContact , "Protocol" , "p" , _T("") );
+ ReplaceAllNoColon( sTarget , _T("%protocol%") , tmp );
+ }
+ if( bIdentifierUsed )
+ {
+ // It has still not been replaced we will just use nick
+ ReplaceAll( sTarget , _T("%nick%") , FileNickFromHandle( hContact ) );
+ }
+ }
+
+ if( sTarget.find( _T("%group%") ) != string::npos )
+ {
+ tstring sGroup = _DBGetString( hContact , "CList" , "Group" , _T("") );
+ ReplaceAllNoColon( sTarget , _T("%group%") , sGroup );
+ }
+
+ // We can't replace the : here because if the user uses C:\... in the file path
+ // this will also be replaced
+ string::size_type nCur = 0;
+ while( (nCur = sTarget.find_first_of(_T("/*?<>|\""),nCur)) != sTarget.npos )
+ sTarget[nCur] = cBadCharReplace;
+
+}
+
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : ReplaceTimeVariables
+// Type : Global
+// Parameters : sRet - ?
+// Returns : void
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 040219 , 19 februar 2004
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+void ReplaceTimeVariables( tstring &sRet )
+{
+ if( sRet.find( _T("%year%") ) != string::npos ||
+ sRet.find( _T("%month%") ) != string::npos ||
+ sRet.find( _T("%day%") ) != string::npos )
+ {
+ SYSTEMTIME stTime;
+ GetLocalTime( &stTime );
+ _TCHAR sTmp[20];
+
+ _sntprintf( sTmp , sizeof( sTmp ) ,_T("%d") , stTime.wYear );
+ ReplaceAll( sRet , _T("%year%") , sTmp );
+ _sntprintf( sTmp , sizeof( sTmp ) ,_T("%.2d") , stTime.wMonth );
+ ReplaceAll( sRet , _T("%month%") , sTmp );
+ _sntprintf( sTmp , sizeof( sTmp ) ,_T("%.2d") , stTime.wDay );
+ ReplaceAll( sRet , _T("%day%") , sTmp );
+ }
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : UpdateFileToColWidth
+// Type : Global
+// Parameters : None
+// Returns : void
+// Description : updates clFileTo1ColWidth,
+//
+// References : -
+// Remarks : -
+// Created : 020422 , 22 April 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+void UpdateFileToColWidth()
+{
+ clFileTo1ColWidth.clear();
+
+ HANDLE hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ for(;;)
+ {
+ tstring sNick = NickFromHandle( hContact );
+ string::size_type &rnValue = clFileTo1ColWidth[ GetFilePathFromUser( hContact ) ];
+ if( rnValue < sNick.size() )
+ rnValue = sNick.size();
+
+ if( ! hContact )
+ break;
+
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0);
+ }
+}
+
+
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : DisplayErrorDialog
+// Type : Global
+// Parameters : pszError - ?
+// sFile - ?
+// dbei - ?
+// Returns : void
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 021203 , 03 December 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+void DisplayErrorDialog( const _TCHAR * pszError , tstring& sFilePath , DBEVENTINFO * dbei )
+{
+ tstring sError = TranslateTS( pszError );
+ sError += sFilePath;
+ sError += _T("\nError :");
+ sError += sGetErrorString();
+ sError += _T("\n");
+ sError += TranslateTS(_T("Message has not been saved !\n"));
+ sError += TranslateTS(_T("Do you wish to save debug information ?"));
+ if( MessageBox( NULL , sError.c_str() ,MSG_BOX_TITEL,MB_YESNO ) == IDYES )
+ {
+ OPENFILENAME ofn; // common dialog box structure
+ _TCHAR szFile[260]; // buffer for file name
+ _tcscpy( szFile , _T("DebugInfo.txt") );
+
+ // Initialize OPENFILENAME
+ ZeroMemory(&ofn, sizeof(OPENFILENAME));
+ ofn.lStructSize = sizeof(OPENFILENAME);
+ //ofn.hwndOwner = NULL;
+ ofn.lpstrFile = szFile;
+ ofn.nMaxFile = sizeof(szFile);
+ ofn.lpstrFilter = _T("All\0*.*\0Text\0*.TXT\0\0");
+ ofn.nFilterIndex = 1;
+ ofn.lpstrFileTitle = NULL;
+ ofn.nMaxFileTitle = 0;
+ ofn.lpstrInitialDir = NULL;
+ ofn.Flags = 0 /*OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST*/;
+ ofn.lpstrDefExt = _T("TXT");
+
+ // Display the Open dialog box.
+
+ if( GetSaveFileName(&ofn) )
+ {
+ HANDLE hf; // file handle
+ hf = CreateFile(ofn.lpstrFile, GENERIC_WRITE,
+ 0, (LPSECURITY_ATTRIBUTES) NULL,
+ CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
+ (HANDLE) NULL);
+
+ bWriteTextToFile( hf , sError.c_str() , false );
+ if( dbei )
+ {
+ bWriteToFile( hf , "\r\ndbei :" );
+
+ bWriteHexToFile( hf , dbei , sizeof( DBEVENTINFO ));
+ if( dbei->pBlob )
+ {
+ bWriteToFile( hf , "\r\ndbei.pBlob :" );
+ bWriteHexToFile( hf , dbei->pBlob , min( dbei->cbBlob , 10000 ));
+ }
+ if( dbei->szModule )
+ {
+ bWriteToFile( hf , "\r\ndbei.szModule :" );
+ bWriteToFile( hf , dbei->szModule );
+ }
+ }
+ CloseHandle( hf );
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : ExportDBEventInfo
+// Type : Global
+// Parameters : hContact - handle to contact
+// dbei - Event to export
+// Returns : void
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 050429 , 29 april 2005
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+void ExportDBEventInfo(HANDLE hContact, DBEVENTINFO &dbei )
+{
+ _TCHAR szTemp[500];
+ tstring sFilePath = GetFilePathFromUser( hContact );
+
+ GetLastError();// Clear last error !!
+
+ HANDLE hFile = CreateFile( sFilePath.c_str() , GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ , 0 ,OPEN_ALWAYS , FILE_ATTRIBUTE_NORMAL , NULL );
+ if( hFile == INVALID_HANDLE_VALUE )
+ {
+ // this might be because the path isent created
+ // so we will try to create it
+ if( bCreatePathToFile( sFilePath ) )
+ {
+ hFile = CreateFile( sFilePath.c_str() , GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ , 0 ,OPEN_ALWAYS , FILE_ATTRIBUTE_NORMAL , NULL );
+ }
+ }
+
+ if( hFile == INVALID_HANDLE_VALUE )
+ {
+ DisplayErrorDialog( _T("Failed to open or create file :\n") , sFilePath , NULL );
+ return;
+ }
+
+ tstring sLocalUser;
+ tstring sRemoteUser;
+ string::size_type nFirstColumnWidth;
+
+ if( bUseLessAndGreaterInExport )
+ {
+ sLocalUser = _T("<<");
+ sRemoteUser = _T(">>");
+ nFirstColumnWidth = 4;
+ }
+ else
+ {
+ sLocalUser = NickFromHandle(0);
+ sRemoteUser = NickFromHandle(hContact);
+ nFirstColumnWidth = max( sRemoteUser.size() , clFileTo1ColWidth[sFilePath] );
+ nFirstColumnWidth = max( sLocalUser.size() , nFirstColumnWidth );
+ nFirstColumnWidth += 2;
+ }
+
+ bool bWriteUTF8Format = false;
+
+ {
+ DWORD dwLowSize;
+ DWORD dwHighSize = 0;
+
+ dwLowSize = GetFileSize( hFile , &dwHighSize );
+
+ if( dwLowSize == INVALID_FILE_SIZE || dwLowSize != 0 || dwHighSize != 0 )
+ {
+ DWORD dwDataRead = 0;
+ BYTE ucByteOrder[3];
+ if( ReadFile( hFile , ucByteOrder , 3 , &dwDataRead , NULL ) )
+ {
+ bWriteUTF8Format = bIsUtf8Header( ucByteOrder );
+ }
+ DWORD dwPtr = SetFilePointer( hFile , 0 , 0 , FILE_END );
+ if( dwPtr == INVALID_SET_FILE_POINTER )
+ {
+ // we need to aborte mission here because if we continue we risk
+ // overwriting old log.
+ DisplayErrorDialog( _T("Failed to move to the end of the file :\n") , sFilePath , NULL );
+ CloseHandle( hFile );
+ return;
+ }
+ }
+ else
+ {
+ bWriteUTF8Format = bUseUtf8InNewFiles;
+ if( bWriteUTF8Format )
+ {
+ if( ! bWriteToFile( hFile , szUtf8ByteOrderHeader, sizeof( szUtf8ByteOrderHeader ) - 1 ) )
+ {
+ DisplayErrorDialog( _T("Failed to UTF8 byte order code to file :\n") , sFilePath , NULL );
+ CloseHandle( hFile );
+ return;
+ }
+ }
+ tstring output = _T("------------------------------------------------\r\n")
+ _T(" History for\r\n")
+ _T("User : %User%\r\n")
+ _T("Protocol : %Proto%\r\n")
+ _T("UIN : %UIN%\r\n")
+ _T("FirstName : %FirstName%\r\n")
+ _T("LastName : %LastName%\r\n")
+ _T("Age : %Age%\r\n")
+ _T("Gender : %Gender%\r\n")
+ _T("e-mail : %e-mail%\r\n")
+ _T("Nick : %Nick% \r\n")
+ _T("City : %City%\r\n")
+ _T("State : %State%\r\n")
+ _T("Phone : %Phone%\r\n")
+ _T("Homepage : %Homepage%\r\n")
+ _T("- About -\r\n%About%\r\n")
+ _T("------------------------------------------------\r\n");
+
+ // This is written this way because I expect this will become a string the user may set
+ // in the options dialog.
+ ReplaceAll( output , _T("%User%") , sRemoteUser );
+
+ string sProto = _DBGetStringA( hContact , "Protocol" , "p" , "" );
+ ReplaceAll( output , _T("%Proto%") , _DBGetString( hContact , "Protocol" , "p" , _T("") ) );
+
+ for( int nCur = 0 ; nCur < 9 ; nCur++ )
+ {
+ ReplaceAll( output , pszReplaceList[nCur] , _DBGetString( hContact , sProto.c_str() , pszReplaceListA[nCur] , _T("") ) );
+ }
+
+ _sntprintf( szTemp , sizeof( szTemp ) , _T("%d") , DBGetContactSettingDword(hContact, sProto.c_str(), "UIN", 0) );
+ ReplaceAll( output , _T("%UIN%") , szTemp );
+
+ _sntprintf( szTemp , sizeof( szTemp ) , _T("%d") , DBGetContactSettingWord(hContact, sProto.c_str(), "Age", 0));
+ ReplaceAll( output , _T("%Age%") , szTemp );
+
+ szTemp[0] = (_TCHAR)DBGetContactSettingByte(hContact, sProto.c_str(), "Gender", 0);
+ szTemp[1] = 0;
+ ReplaceAll( output , _T("%Gender%") , szTemp );
+
+ if( ! bWriteTextToFile( hFile , output.data(), bWriteUTF8Format, output.size() ) )
+ {
+ DisplayErrorDialog( _T("Failed to write user details to file :\n") , sFilePath , NULL );
+ CloseHandle( hFile );
+ return;
+ }
+ }
+ }
+
+ int nIndent;
+ { // Get time stamp
+
+ nIndent = _sntprintf( szTemp , sizeof( szTemp ) , _T("%-*s") ,
+ nFirstColumnWidth ,
+ dbei.flags & DBEF_SENT ? sLocalUser.c_str() : sRemoteUser.c_str() );
+
+ DBTIMETOSTRINGT dbtts;
+ dbtts.cbDest = sizeof(szTemp) - nIndent - 2;
+ dbtts.szDest = &szTemp[nIndent];
+ dbtts.szFormat = (_TCHAR*)sTimeFormat.c_str();
+#ifdef _UNICODE
+ CallService(MS_DB_TIME_TIMESTAMPTOSTRINGT,dbei.timestamp,(LPARAM)&dbtts);
+#else
+ CallService(MS_DB_TIME_TIMESTAMPTOSTRING,dbei.timestamp,(LPARAM)&dbtts);
+#endif
+ nIndent = _tcslen( szTemp );
+ szTemp[nIndent++] = ' ';
+
+ // Write first part of line with name and timestamp
+ if( ! bWriteTextToFile( hFile , szTemp , bWriteUTF8Format , nIndent ) )
+ {
+ DisplayErrorDialog( _T("Failed to write timestamp and username to file :\n") , sFilePath , &dbei );
+ CloseHandle( hFile );
+ return;
+ }
+ }
+
+ if( dbei.pBlob != NULL && dbei.cbBlob >= 2 )
+ {
+ dbei.pBlob[ dbei.cbBlob ] = 0;
+
+ switch(dbei.eventType)
+ {
+ case EVENTTYPE_MESSAGE:
+ {
+ TCHAR* msg = DbGetEventTextT( &dbei, CP_ACP );
+ if( ! bWriteIndentedToFile( hFile , nIndent , msg , bWriteUTF8Format ) )
+ {
+ DisplayErrorDialog( _T("Failed to write message to the file :\n") , sFilePath , &dbei );
+ }
+ mir_free(msg);
+ break;
+/*
+ const char * pszData = (const char*)dbei.pBlob;
+ bool bConvertedToUtf8 = false;
+ if( bWriteUTF8Format )// Write UTF-8 format in file ?
+ {
+ int nAnsiLen = strlen((char *) dbei.pBlob)+1;
+ if( nAnsiLen < (int)dbei.cbBlob )
+ {
+ // Message is also encoded in unicode UTF-16/UCS-2, little endian.
+ if( WideCharToMultiByte( CP_UTF8 , 0 , (wchar_t*)&dbei.pBlob[ nAnsiLen ] , nAnsiLen , szTemp , sizeof(szTemp) , 0 , 0 ) )
+ {
+ pszData = szTemp;
+ bConvertedToUtf8 = true;
+ }
+ }
+ // We need to write in UTF8 format so we have to convert ansi string to UTF8
+ }
+ if( ! bWriteIndentedToFile( hFile , nIndent , pszData , bWriteUTF8Format ) )
+ {
+ DisplayErrorDialog( _T("Failed to write message to the file :\n") , sFilePath , &dbei );
+ }
+ break;*/
+ }
+ case EVENTTYPE_URL:
+ case EVENTTYPE_FILE:
+ {
+ const _TCHAR * pszType;
+ const char * pszData;
+
+ if( dbei.eventType == EVENTTYPE_URL )
+ {
+ pszType = TranslateTS(_T("URL: "));
+ pszData = (char *)dbei.pBlob;
+ }
+ else
+ {
+ pszType = TranslateTS(_T("File: "));
+ pszData = (char *)(dbei.pBlob + sizeof( DWORD ));
+ }
+
+ bool bWriteOk = false;
+
+ int nLen = strlen( pszData );
+ if( (pszData - (char *)dbei.pBlob) + nLen < (int)dbei.cbBlob )
+ {
+ if( bWriteTextToFile( hFile , pszType , bWriteUTF8Format ) &&
+ bWriteIndentedToFile( hFile , nIndent , pszData , bWriteUTF8Format ) )
+ {
+ pszData += nLen + 1;
+ if( (pszData - (char *)dbei.pBlob) >= (int)dbei.cbBlob )
+ {
+ bWriteOk = true;
+ }
+ else
+ {
+ nLen = strlen( pszData );
+ if( (pszData - (char *)dbei.pBlob) + nLen < (int)dbei.cbBlob )
+ {
+ if( bWriteNewLine( hFile , nIndent ) &&
+ bWriteTextToFile( hFile , TranslateTS(_T("Description: ")) , bWriteUTF8Format) &&
+ bWriteIndentedToFile( hFile , nIndent , pszData , bWriteUTF8Format ) )
+ {
+ bWriteOk = true;
+ }
+ }
+ }
+ }
+ }
+
+ if( ! bWriteOk )
+ DisplayErrorDialog( _T("Failed to write URL/File to the file :\n") , sFilePath , &dbei );
+ break;
+ }
+ case EVENTTYPE_AUTHREQUEST:
+ case EVENTTYPE_ADDED:
+ {
+ const _TCHAR * pszTypes[] = {
+ _T("Nick :"),
+ _T("FirstName :"),
+ _T("LastName :"),
+ _T("e-mail :"),
+ _T("Reason :")};
+
+ /*// test code
+ dbei.pBlob = (BYTE*)("\xED\xA8\x29\x09nick\0first\0last\0email");
+ dbei.cbBlob = 26;
+ */
+
+ if( dbei.cbBlob < 8 || dbei.cbBlob > 5000 )
+ {
+ int n = _sntprintf( szTemp , sizeof( szTemp ) ,_T("Invalid Database event received. Type %d, size %d"),dbei.eventType, dbei.cbBlob );
+ if( ! bWriteTextToFile( hFile , szTemp , bWriteUTF8Format , n ) )
+ DisplayErrorDialog( _T("Failed to write Invalid Database event the file :\n") , sFilePath , &dbei );
+ break;
+ }
+
+ bool bWriteOk = false;
+
+ int nStringCount;
+ const _TCHAR * pszTitle;
+ if( dbei.eventType == EVENTTYPE_AUTHREQUEST )
+ { // request
+ //blob is: uin(DWORD), nick(ASCIIZ), first(ASCIIZ), last(ASCIIZ), email(ASCIIZ), reason(ASCIIZ)
+ nStringCount = 5;
+ pszTitle = TranslateTS(_T("The following user made an authorization request:"));
+ }
+ else
+ { // Added
+ //blob is: uin(DWORD), nick(ASCIIZ), first(ASCIIZ), last(ASCIIZ), email(ASCIIZ)
+ nStringCount = 4;
+ pszTitle = TranslateTS(_T("The following user added you to their contact list:"));
+ }
+
+ if( bWriteTextToFile( hFile , pszTitle , bWriteUTF8Format ) &&
+ bWriteNewLine( hFile , nIndent ) &&
+ bWriteTextToFile( hFile , TranslateTS(_T("UIN :")) , bWriteUTF8Format ) )
+ {
+ DWORD uin = *((PDWORD)(dbei.pBlob));
+ int n = _sntprintf( szTemp , sizeof( szTemp ) ,_T("%d"), uin );
+ if( bWriteTextToFile( hFile , szTemp , bWriteUTF8Format , n ) )
+ {
+ char * pszCurBlobPos = (char *) (dbei.pBlob + sizeof( DWORD ));
+ char * pszEnd = (char *) (dbei.pBlob + dbei.cbSize);
+ for( int n = 0 ; n < nStringCount && pszCurBlobPos < pszEnd ; n++ )
+ {
+ if( *pszCurBlobPos )
+ {
+ if( ! bWriteNewLine( hFile , nIndent ) ||
+ ! bWriteTextToFile( hFile , TranslateTS(pszTypes[ n ]) , bWriteUTF8Format ) ||
+ ! bWriteIndentedToFile( hFile , nIndent , pszCurBlobPos , bWriteUTF8Format ) )
+ {
+ break;
+ }
+ pszCurBlobPos += strlen( pszCurBlobPos );
+ }
+ pszCurBlobPos++;
+ }
+ bWriteOk = true;
+ }
+ }
+
+ if( ! bWriteOk )
+ DisplayErrorDialog( _T("Failed to write AUTHREQUEST or ADDED to the file :\n") , sFilePath , &dbei );
+
+ break;
+ }
+ case ICQEVENTTYPE_EMAILEXPRESS:
+ case ICQEVENTTYPE_WEBPAGER:
+ {
+ //e-mail express
+ //db event added to NULL contact
+ //blob format is:
+ //ASCIIZ text, usually of the form "Subject: %s\r\n%s"
+ //ASCIIZ from name
+ //ASCIIZ from e-mail
+
+ //www pager
+ //db event added to NULL contact
+ //blob format is:
+ //ASCIIZ text, usually "Sender IP: xxx.xxx.xxx.xxx\r\n%s"
+ //ASCIIZ from name
+ //ASCIIZ from e-mail
+ const char* pszStr = (const char*)dbei.pBlob;
+
+ if( dbei.eventType == ICQEVENTTYPE_EMAILEXPRESS )
+ bWriteTextToFile( hFile , TranslateTS(_T("EmailExpress from:")) , bWriteUTF8Format);
+ else
+ bWriteTextToFile( hFile , TranslateTS(_T("WebPager from:")) , bWriteUTF8Format );
+
+ bWriteNewLine( hFile , nIndent );
+
+ size_t nMsgLenght = strlen( pszStr ) + 1;
+ if( nMsgLenght < dbei.cbBlob )
+ {
+ size_t nFriendlyLen = strlen( &pszStr[nMsgLenght] );
+ bWriteTextToFile( hFile , &pszStr[nMsgLenght] , bWriteUTF8Format , nFriendlyLen );
+ size_t nEmailOffset = nMsgLenght + nFriendlyLen + 1;
+ if( nEmailOffset < dbei.cbBlob )
+ {
+ bWriteTextToFile( hFile , _T("<") , bWriteUTF8Format );
+ size_t nEmailLen = strlen( &pszStr[nEmailOffset] );
+ bWriteTextToFile( hFile , &pszStr[nEmailOffset] , bWriteUTF8Format , nEmailLen );
+ bWriteTextToFile( hFile , _T(">") , bWriteUTF8Format );
+ }
+ }
+ else
+ {
+ bWriteTextToFile( hFile , TranslateTS(_T("No from address")) , bWriteUTF8Format );
+ }
+
+ if( ! bWriteNewLine( hFile , nIndent ) ||
+ ! bWriteIndentedToFile( hFile , nIndent , pszStr , bWriteUTF8Format ) )
+ {
+ DisplayErrorDialog( _T("Failed to write EmailExpress to the file :\n") , sFilePath , &dbei );
+ }
+ break;
+ }
+ case ICQEVENTTYPE_SMS:
+ {
+ if( ! bWriteIndentedToFile( hFile , nIndent , (const char*)dbei.pBlob , bWriteUTF8Format ) )
+ {
+ DisplayErrorDialog( _T("Failed to write SMS to the file :\n") , sFilePath , &dbei );
+ }
+ break;
+ }
+ default:
+ {
+ int n = _sntprintf( szTemp , sizeof( szTemp ) ,_T("Unknown event type %d, size %d") , dbei.eventType, dbei.cbBlob );
+ if( ! bWriteTextToFile( hFile , szTemp , bWriteUTF8Format , n ) )
+ {
+ DisplayErrorDialog( _T("Failed to write Unknown event to the file :\n") , sFilePath , &dbei );
+ }
+ break;
+ }
+ }
+ }
+ else
+ {
+ int n = _sntprintf( szTemp , sizeof( szTemp ) ,_T("Unknown event type %d, size %d") , dbei.eventType, dbei.cbBlob );
+ bWriteTextToFile( hFile , szTemp , bWriteUTF8Format , n );
+ }
+ bWriteToFile( hFile , bAppendNewLine ? "\r\n\r\n" : "\r\n" );
+
+ CloseHandle( hFile );
+
+ UpdateFileViews( sFilePath.c_str() );
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : nExportEvent
+// Type : Global
+// Parameters : wparam - handle to contact
+// lparam - handle to the new DB event
+// Returns : int
+// Description : Called when an event is added to the DB
+// Or from the Export All funktion
+// References : -
+// Remarks : -
+// Created : 020422 , 22 April 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+
+int nExportEvent(WPARAM wparam,LPARAM lparam)
+{
+ HANDLE hContact = (HANDLE)wparam;
+
+ if( ! DBGetContactSettingByte(hContact,MODULE,"EnableLog",1) )
+ return 0;
+
+ DBEVENTINFO dbei={0};
+ dbei.cbSize=sizeof(dbei);
+ char szTemp[500];
+
+ { // Get Blob data size
+
+ int nSize = CallService(MS_DB_EVENT_GETBLOBSIZE,(WPARAM)lparam,0);
+ if( nSize > 0 )
+ {
+ dbei.cbBlob = nSize;
+ dbei.pBlob = (PBYTE)malloc(dbei.cbBlob + 2 );
+ dbei.pBlob[dbei.cbBlob] = 0;
+ dbei.pBlob[dbei.cbBlob+1] = 0;
+ // Double null terminate, this shut pervent most errors
+ // where the blob received has an invalid format
+ }
+ // else dbei.cbBlob will be 0
+ }
+
+ if( ! CallService(MS_DB_EVENT_GET,(WPARAM)lparam,(LPARAM)&dbei) )
+ {
+ if( dbei.eventType != EVENTTYPE_STATUSCHANGE )
+ {
+ _snprintf( szTemp , sizeof( szTemp ) , "DisableProt_%s" , dbei.szModule );
+ if( DBGetContactSettingByte(NULL,MODULE,szTemp,1) )
+ {
+ ExportDBEventInfo( hContact , dbei );
+ }
+ }
+ }
+ if( dbei.pBlob )
+ free(dbei.pBlob);
+ return 0;
+}
+
+#ifdef _UNICODE
+bool bWriteIndentedToFile( HANDLE hFile , int nIndent , const char * pszSrc , bool bUtf8File )
+{
+ int nLen = strlen( pszSrc );
+ wchar_t * pszWstr = new wchar_t[nLen+1];
+ bool bRet = false;
+ if( MultiByteToWideChar(CP_ACP, 0, pszSrc, nLen, pszWstr, nLen ) == nLen )
+ {
+ pszWstr[nLen] = NULL;
+ bRet = bWriteIndentedToFile( hFile , nIndent , pszWstr , bUtf8File );
+ }
+ return bRet;
+}
+#endif
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : bWriteIndentedToFile
+// Type : Global
+// Parameters : hFile - ?
+// nIndent - ?
+// pszSrc -
+// Returns : Returns true if
+// Description :
+//
+// References : -
+// Remarks : -
+// Created : 020629 , 29 June 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+bool bWriteIndentedToFile( HANDLE hFile , int nIndent , const _TCHAR * pszSrc , bool bUtf8File )
+{
+ bool bOk = true;
+ bool bFirstLine = true;
+
+ while( *pszSrc )
+ { // first we will scan forward in string to finde either new line or "max line with"
+ int nLineLen = 0;
+ do
+ {
+/* if( bUtf8Src )
+ { // need to do some stuff here
+ }*/
+ if( pszSrc[nLineLen] == _T('\n') || pszSrc[nLineLen] == _T('\r'))
+ { // the line naturly broken here stop scan
+ break;
+ }
+
+ if( nLineLen >= nMaxLineWidth )
+ { // ok the line was not broken. we need to force a break
+ // we will scan backwards again to finde a space !!
+ // then we will look for a ? and so on.
+
+ const _TCHAR ac[] = { _T(' '),_T('?'),_T('-'),_T('.'),_T(',') };
+ for( int y = 0 ; y < sizeof( ac ) ; y++)
+ {
+ for( int n = nLineLen ; n > 0 ; n-- )
+ {
+ if( pszSrc[n] == ac[y] )
+ {
+ nLineLen = n;
+ goto SuperBreak;
+ }
+ }
+ }
+ break;
+ }
+ nLineLen++;
+ }
+ while( pszSrc[nLineLen] );
+
+ // trim away traling spaces !!
+ if( nLineLen > 0 )
+ {
+ while( pszSrc[nLineLen-1] == ' ' )
+ nLineLen--;
+ }
+
+SuperBreak:
+
+
+ // nLineLen should contain the number af chars we need to write to the file
+ if( nLineLen > 0 )
+ {
+ if( !bFirstLine )
+ {
+ if( ! bWriteNewLine( hFile , nIndent ) )
+ {
+ bOk = false;
+ }
+ }
+/* if( bUtf8Src )
+ {
+ // Programming error writing UTF8 string to ansi file
+ if( ! bUtf8File )
+ {
+ MessageBox( NULL , _T("Programming error writing UTF8 string to ansi file") ,MSG_BOX_TITEL,MB_OK );
+ // bUtf8File must be true here
+ }
+ if( !bWriteToFile( hFile , pszSrc , nLineLen ) )
+ {
+ bOk = false;
+ }
+ }
+ else*/
+ {// Text format !!
+ if( ! bWriteTextToFile( hFile , pszSrc , bUtf8File , nLineLen ) )
+ bOk = false;
+ }
+ }
+ bFirstLine = false;
+
+ // skip any noice chars, MAC style '\r' '\r' '\n'
+ // and excess spaces
+ const _TCHAR * pszPrev = pszSrc;
+ pszSrc += nLineLen;
+ while( *pszSrc == _T(' ') || *pszSrc == _T('\n') || *pszSrc == _T('\r') )
+ pszSrc++;
+
+ if( pszPrev == pszSrc )
+ {
+ // this is an programming error we have not moved forward in string
+ MessageBox( NULL , _T("Programming error on line __LINE__ please report this") ,MSG_BOX_TITEL,MB_OK );
+ break;
+ }
+ }
+
+ // if bOk if false file writing failed
+ return bOk;
+}
+
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : nContactDeleted
+// Type : Global
+// Parameters : wparam - handle to the deleted Contact
+// lparam - 0
+// Returns : int
+// Description : Called when an contact is about to be deleted
+//
+// References : -
+// Remarks : -
+// Created : 021222 , 22 December 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+int nContactDeleted(WPARAM wparam,LPARAM /*lparam*/)
+{
+ if( enDeleteAction == eDANothing )
+ return 0;
+
+ HANDLE hContact = (HANDLE)wparam;
+
+ tstring sFilePath = GetFilePathFromUser( hContact );
+
+ { // Test if there is another user using this file
+ HANDLE hOtherContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ for(;;)
+ {
+ if( hContact != hOtherContact && sFilePath == GetFilePathFromUser( hOtherContact ) )
+ {
+ return 0; // we found another contact abort mission :-)
+ }
+
+ if( ! hOtherContact )
+ break;
+ hOtherContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hOtherContact, 0);
+ }
+ }
+
+ // Test to see if there is a file to delete
+ HANDLE hPrevFile = CreateFile( sFilePath.c_str() ,
+ GENERIC_READ ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE ,
+ NULL,
+ OPEN_EXISTING ,
+ FILE_ATTRIBUTE_NORMAL ,
+ NULL );
+
+ if( hPrevFile != INVALID_HANDLE_VALUE )
+ {
+ CloseHandle( hPrevFile );
+
+ _TCHAR szTemp[500];
+ _sntprintf( szTemp , sizeof( szTemp ) , _T("%s\r\n%s") ,
+ TranslateTS(_T("User has been deleted do you want to delete the file ?")) ,
+ sFilePath.c_str() );
+
+ if( enDeleteAction == eDAAutomatic ||
+ MessageBox( NULL , szTemp ,MSG_BOX_TITEL,MB_YESNO ) == IDYES )
+ {
+ if( ! DeleteFile( sFilePath.c_str() ) )
+ {
+ _sntprintf( szTemp , sizeof( szTemp ) ,
+ _T("%s\r\n%s"),
+ TranslateTS(_T("Failed to delete the file")),
+ sFilePath.c_str() );
+
+ DisplayLastError( szTemp );
+ }
+ }
+ }
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////
+// Member Function : SaveSettings
+// Type : Global
+// Parameters : None
+// Returns : void
+// Description : Save Settings
+//
+// References : -
+// Remarks : -
+// Created : 020429 , 29 April 2002
+// Developer : KN
+/////////////////////////////////////////////////////////////////////
+
+void SaveSettings()
+{
+ DBWriteContactSettingWord( NULL , MODULE , "MaxLineWidth" , (WORD) nMaxLineWidth );
+ DBWriteContactSettingTString( NULL , MODULE , "ExportDir" , sExportDir.c_str() );
+ DBWriteContactSettingTString( NULL , MODULE , "DefaultFile" , sDefaultFile.c_str() );
+ DBWriteContactSettingTString( NULL , MODULE , "TimeFormat" , sTimeFormat.c_str() );
+
+ DBWriteContactSettingTString( NULL , MODULE , "FileViewerPrg" , sFileViewerPrg.c_str() );
+ DBWriteContactSettingByte( NULL , MODULE , "UseInternalViewer" , bUseInternalViewer() );
+ DBWriteContactSettingByte( NULL , MODULE , "ReplaceHistory" , bReplaceHistory );
+ DBWriteContactSettingByte( NULL , MODULE , "AppendNewLine" , bAppendNewLine );
+ DBWriteContactSettingByte( NULL , MODULE , "UseUtf8InNewFiles" , bUseUtf8InNewFiles );
+ DBWriteContactSettingByte( NULL , MODULE , "UseLessAndGreaterInExport" , bUseLessAndGreaterInExport );
+
+ DBWriteContactSettingByte( NULL , MODULE , "RenameAction" , (BYTE)enRenameAction );
+ DBWriteContactSettingByte( NULL , MODULE , "DeleteAction" , (BYTE)enDeleteAction );
+}
+
diff --git a/plugins/Msg_Export/src/utils.h b/plugins/Msg_Export/src/utils.h
new file mode 100755
index 0000000000..f2ca584cde
--- /dev/null
+++ b/plugins/Msg_Export/src/utils.h
@@ -0,0 +1,125 @@
+
+//This file is part of Msg_Export a Miranda IM plugin
+//Copyright (C)2002 Kennet Nielsen ( http://sourceforge.net/projects/msg-export/ )
+//
+//This program is free software; you can redistribute it and/or
+//modify it under the terms of the GNU General Public License
+//as published by the Free Software Foundation; either
+//version 2 of the License, or (at your option) any later version.
+//
+//This program is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//GNU General Public License for more details.
+//
+//You should have received a copy of the GNU General Public License
+//along with this program; if not, write to the Free Software
+//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+#ifndef MSG_EXP_UTILS_H
+#define MSG_EXP_UTILS_H
+
+#include <windows.h>
+
+#if defined ( _MSC_VER ) // A Microsoft C Compiler
+ #ifdef _DEBUG // The _ASSERT macro contains a constant expression
+ #pragma warning( disable : 4786 )
+ #endif
+#endif // defined ( _MSC_VER )
+
+#pragma warning (push, 3 )
+#pragma warning (disable:4996)
+
+#include "stdio.h"
+
+#include <newpluginapi.h>
+#include <m_database.h>
+#include <m_clist.h>
+#include <m_skin.h>
+#include <m_langpack.h>
+#include <m_options.h>
+#include <m_system.h>
+#include <m_history.h>
+#include <m_userinfo.h>
+#include <m_utils.h>
+#include <m_protocols.h>
+
+#define EVENTTYPE_STATUSCHANGE 25368
+
+#include <list>
+#include <string>
+#include <map>
+#pragma warning (default:4996)
+#pragma warning (pop)
+
+using namespace std;
+
+#ifdef _UNICODE
+ #define tstring wstring
+ #define _DBGetString _DBGetStringW
+#else
+ #define tstring string
+ #define _DBGetString _DBGetStringA
+#endif
+
+enum ENDialogAction
+{
+ eDAPromptUser,
+ eDAAutomatic,
+ eDANothing
+};
+
+extern ENDialogAction enRenameAction;
+extern ENDialogAction enDeleteAction;
+
+extern int nMaxLineWidth;
+extern tstring sExportDir;
+extern tstring sDefaultFile;
+extern tstring sTimeFormat;
+extern map<tstring , string::size_type , less<tstring> > clFileTo1ColWidth;
+
+extern bool bAppendNewLine;
+extern bool bUseUtf8InNewFiles;
+extern bool bUseLessAndGreaterInExport;
+
+extern bool bReplaceHistory;
+
+tstring sGetErrorString(DWORD dwError);
+tstring sGetErrorString();
+void DisplayLastError(const _TCHAR * pszError);
+
+_TCHAR * CheckedTranslate( const _TCHAR *szEng , int nFormatCount = -1 );
+
+void SaveSettings();
+void ShowDebugInfo();
+
+int nExportEvent(WPARAM wparam,LPARAM lparam);
+int nContactDeleted(WPARAM wparam,LPARAM lparam);
+
+const _TCHAR *NickFromHandle(HANDLE hContact);
+
+tstring __inline _DBGetStringW(HANDLE hContact,const char *szModule,const char *szSetting , const _TCHAR * pszError );
+string __inline _DBGetStringA(HANDLE hContact,const char *szModule,const char *szSetting , const char * pszError );
+
+void ReplaceAll( tstring &sSrc , const _TCHAR * pszReplace , const tstring &sNew);
+void ReplaceAll( tstring &sSrc , const _TCHAR * pszReplace , const _TCHAR * pszNew);
+
+void UpdateFileToColWidth();
+
+bool bReadMirandaDirAndPath();
+tstring GetFilePathFromUser( HANDLE hContact );
+
+void ReplaceDefines( HANDLE hContact , tstring & sTarget );
+void ReplaceTimeVariables( tstring &sRet );
+
+bool bCreatePathToFile( tstring sFilePath );
+#ifdef _UNICODE
+bool bWriteIndentedToFile( HANDLE hFile , int nIndent , const char * pszSrc , bool bUtf8File );
+#endif
+bool bWriteIndentedToFile( HANDLE hFile , int nIndent , const _TCHAR * pszSrc , bool bUtf8File );
+bool bWriteNewLine( HANDLE hFile , DWORD dwIndent );
+bool bIsUtf8Header( BYTE * pucByteOrder );
+
+
+#endif \ No newline at end of file
diff --git a/plugins/New_GPG/Makefile b/plugins/New_GPG/Makefile
new file mode 100755
index 0000000000..183390389b
--- /dev/null
+++ b/plugins/New_GPG/Makefile
@@ -0,0 +1,23 @@
+CFLAGS=-g -mdll -mwindows -I../miranda-im/miranda/include -I./ -I/home/sss/temp/windows/libs/utf8cpp/include -D DEBUG -D _UNICODE -D UNICODE -DBOOST_SYSTEM_STATIC_LINK=1 -DBOOST_THREAD_USE_LIB
+CXXFLAGS=${CFLAGS}
+LDFLAGS=-static-libgcc -Wl,-O1 -shared -s -Wl,--subsystem,windows,--kill-at -lshlwapi -lcomdlg32 -lboost_system-mt -lboost_thread_win32-mt -lboost_random-mt -lboost_date_time-mt
+CPPFLAGS =
+CC=i686-pc-mingw32-gcc
+CXX=i686-pc-mingw32-g++
+STRIP=i686-pc-mingw32-strip
+LD=i686-pc-mingw32-ld
+LNK_COMMON=-lkernel32
+
+MAINOBJS=jabber_account.o clist.o init.o options.o gpg_wrapper.o srmm.o messages.o utilities.o metacontacts.o main.o log.o icons.o
+
+WINDRES=i686-pc-mingw32-windres
+
+all: main
+main: $(MAINOBJS)
+ $(WINDRES) -i new_gpg.rc -o resources.o
+ $(CXX) $(MAINOBJS) resources.o $(LNK_COMMON) $(LDFLAGS) -o new_gpg.dll
+ $(STRIP) new_gpg.dll
+ upx --best --compress-icons=0 new_gpg.dll
+clean:
+ rm *.o
+ rm new_gpg.dll
diff --git a/plugins/New_GPG/README b/plugins/New_GPG/README
new file mode 100755
index 0000000000..be5551c7ac
--- /dev/null
+++ b/plugins/New_GPG/README
@@ -0,0 +1,6 @@
+* Build Dependencies
+ 1. boost (http://www.boost.org/)
+ 2. utf8cpp (http://utfcpp.sourceforge.net/)
+ 3. c++ compiller (because of miranda have compiled with MSVC, only msvc compiled builds working fine (i have no success with mingw, please report your result :) ))
+* Runtime Dependencies
+ 1. MIranda NG
diff --git a/plugins/New_GPG/dependencies/include/utf8.h b/plugins/New_GPG/dependencies/include/utf8.h
new file mode 100755
index 0000000000..4e4451403f
--- /dev/null
+++ b/plugins/New_GPG/dependencies/include/utf8.h
@@ -0,0 +1,34 @@
+// Copyright 2006 Nemanja Trifunovic
+
+/*
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+
+#ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include "utf8/checked.h"
+#include "utf8/unchecked.h"
+
+#endif // header guard
diff --git a/plugins/New_GPG/dependencies/include/utf8/checked.h b/plugins/New_GPG/dependencies/include/utf8/checked.h
new file mode 100755
index 0000000000..3b00644444
--- /dev/null
+++ b/plugins/New_GPG/dependencies/include/utf8/checked.h
@@ -0,0 +1,327 @@
+// Copyright 2006 Nemanja Trifunovic
+
+/*
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+
+#ifndef UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include "core.h"
+#include <stdexcept>
+
+namespace utf8
+{
+ // Base for the exceptions that may be thrown from the library
+ class exception : public ::std::exception {
+ };
+
+ // Exceptions that may be thrown from the library functions.
+ class invalid_code_point : public exception {
+ uint32_t cp;
+ public:
+ invalid_code_point(uint32_t cp) : cp(cp) {}
+ virtual const char* what() const throw() { return "Invalid code point"; }
+ uint32_t code_point() const {return cp;}
+ };
+
+ class invalid_utf8 : public exception {
+ uint8_t u8;
+ public:
+ invalid_utf8 (uint8_t u) : u8(u) {}
+ virtual const char* what() const throw() { return "Invalid UTF-8"; }
+ uint8_t utf8_octet() const {return u8;}
+ };
+
+ class invalid_utf16 : public exception {
+ uint16_t u16;
+ public:
+ invalid_utf16 (uint16_t u) : u16(u) {}
+ virtual const char* what() const throw() { return "Invalid UTF-16"; }
+ uint16_t utf16_word() const {return u16;}
+ };
+
+ class not_enough_room : public exception {
+ public:
+ virtual const char* what() const throw() { return "Not enough space"; }
+ };
+
+ /// The library API - functions intended to be called by the users
+
+ template <typename octet_iterator>
+ octet_iterator append(uint32_t cp, octet_iterator result)
+ {
+ if (!utf8::internal::is_code_point_valid(cp))
+ throw invalid_code_point(cp);
+
+ if (cp < 0x80) // one octet
+ *(result++) = static_cast<uint8_t>(cp);
+ else if (cp < 0x800) { // two octets
+ *(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ else if (cp < 0x10000) { // three octets
+ *(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0);
+ *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ else { // four octets
+ *(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0);
+ *(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ return result;
+ }
+
+ template <typename octet_iterator, typename output_iterator>
+ output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement)
+ {
+ while (start != end) {
+ octet_iterator sequence_start = start;
+ internal::utf_error err_code = utf8::internal::validate_next(start, end);
+ switch (err_code) {
+ case internal::UTF8_OK :
+ for (octet_iterator it = sequence_start; it != start; ++it)
+ *out++ = *it;
+ break;
+ case internal::NOT_ENOUGH_ROOM:
+ throw not_enough_room();
+ case internal::INVALID_LEAD:
+ utf8::append (replacement, out);
+ ++start;
+ break;
+ case internal::INCOMPLETE_SEQUENCE:
+ case internal::OVERLONG_SEQUENCE:
+ case internal::INVALID_CODE_POINT:
+ utf8::append (replacement, out);
+ ++start;
+ // just one replacement mark for the sequence
+ while (start != end && utf8::internal::is_trail(*start))
+ ++start;
+ break;
+ }
+ }
+ return out;
+ }
+
+ template <typename octet_iterator, typename output_iterator>
+ inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out)
+ {
+ static const uint32_t replacement_marker = utf8::internal::mask16(0xfffd);
+ return utf8::replace_invalid(start, end, out, replacement_marker);
+ }
+
+ template <typename octet_iterator>
+ uint32_t next(octet_iterator& it, octet_iterator end)
+ {
+ uint32_t cp = 0;
+ internal::utf_error err_code = utf8::internal::validate_next(it, end, cp);
+ switch (err_code) {
+ case internal::UTF8_OK :
+ break;
+ case internal::NOT_ENOUGH_ROOM :
+ throw not_enough_room();
+ case internal::INVALID_LEAD :
+ case internal::INCOMPLETE_SEQUENCE :
+ case internal::OVERLONG_SEQUENCE :
+ throw invalid_utf8(*it);
+ case internal::INVALID_CODE_POINT :
+ throw invalid_code_point(cp);
+ }
+ return cp;
+ }
+
+ template <typename octet_iterator>
+ uint32_t peek_next(octet_iterator it, octet_iterator end)
+ {
+ return utf8::next(it, end);
+ }
+
+ template <typename octet_iterator>
+ uint32_t prior(octet_iterator& it, octet_iterator start)
+ {
+ // can't do much if it == start
+ if (it == start)
+ throw not_enough_room();
+
+ octet_iterator end = it;
+ // Go back until we hit either a lead octet or start
+ while (utf8::internal::is_trail(*(--it)))
+ if (it == start)
+ throw invalid_utf8(*it); // error - no lead byte in the sequence
+ return utf8::peek_next(it, end);
+ }
+
+ /// Deprecated in versions that include "prior"
+ template <typename octet_iterator>
+ uint32_t previous(octet_iterator& it, octet_iterator pass_start)
+ {
+ octet_iterator end = it;
+ while (utf8::internal::is_trail(*(--it)))
+ if (it == pass_start)
+ throw invalid_utf8(*it); // error - no lead byte in the sequence
+ octet_iterator temp = it;
+ return utf8::next(temp, end);
+ }
+
+ template <typename octet_iterator, typename distance_type>
+ void advance (octet_iterator& it, distance_type n, octet_iterator end)
+ {
+ for (distance_type i = 0; i < n; ++i)
+ utf8::next(it, end);
+ }
+
+ template <typename octet_iterator>
+ typename std::iterator_traits<octet_iterator>::difference_type
+ distance (octet_iterator first, octet_iterator last)
+ {
+ typename std::iterator_traits<octet_iterator>::difference_type dist;
+ for (dist = 0; first < last; ++dist)
+ utf8::next(first, last);
+ return dist;
+ }
+
+ template <typename u16bit_iterator, typename octet_iterator>
+ octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
+ {
+ while (start != end) {
+ uint32_t cp = utf8::internal::mask16(*start++);
+ // Take care of surrogate pairs first
+ if (utf8::internal::is_lead_surrogate(cp)) {
+ if (start != end) {
+ uint32_t trail_surrogate = utf8::internal::mask16(*start++);
+ if (utf8::internal::is_trail_surrogate(trail_surrogate))
+ cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
+ else
+ throw invalid_utf16(static_cast<uint16_t>(trail_surrogate));
+ }
+ else
+ throw invalid_utf16(static_cast<uint16_t>(cp));
+
+ }
+ // Lone trail surrogate
+ else if (utf8::internal::is_trail_surrogate(cp))
+ throw invalid_utf16(static_cast<uint16_t>(cp));
+
+ result = utf8::append(cp, result);
+ }
+ return result;
+ }
+
+ template <typename u16bit_iterator, typename octet_iterator>
+ u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
+ {
+ while (start != end) {
+ uint32_t cp = utf8::next(start, end);
+ if (cp > 0xffff) { //make a surrogate pair
+ *result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET);
+ *result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
+ }
+ else
+ *result++ = static_cast<uint16_t>(cp);
+ }
+ return result;
+ }
+
+ template <typename octet_iterator, typename u32bit_iterator>
+ octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
+ {
+ while (start != end)
+ result = utf8::append(*(start++), result);
+
+ return result;
+ }
+
+ template <typename octet_iterator, typename u32bit_iterator>
+ u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
+ {
+ while (start != end)
+ (*result++) = utf8::next(start, end);
+
+ return result;
+ }
+
+ // The iterator class
+ template <typename octet_iterator>
+ class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> {
+ octet_iterator it;
+ octet_iterator range_start;
+ octet_iterator range_end;
+ public:
+ iterator () {};
+ explicit iterator (const octet_iterator& octet_it,
+ const octet_iterator& range_start,
+ const octet_iterator& range_end) :
+ it(octet_it), range_start(range_start), range_end(range_end)
+ {
+ if (it < range_start || it > range_end)
+ throw std::out_of_range("Invalid utf-8 iterator position");
+ }
+ // the default "big three" are OK
+ octet_iterator base () const { return it; }
+ uint32_t operator * () const
+ {
+ octet_iterator temp = it;
+ return utf8::next(temp, range_end);
+ }
+ bool operator == (const iterator& rhs) const
+ {
+ if (range_start != rhs.range_start || range_end != rhs.range_end)
+ throw std::logic_error("Comparing utf-8 iterators defined with different ranges");
+ return (it == rhs.it);
+ }
+ bool operator != (const iterator& rhs) const
+ {
+ return !(operator == (rhs));
+ }
+ iterator& operator ++ ()
+ {
+ utf8::next(it, range_end);
+ return *this;
+ }
+ iterator operator ++ (int)
+ {
+ iterator temp = *this;
+ utf8::next(it, range_end);
+ return temp;
+ }
+ iterator& operator -- ()
+ {
+ utf8::prior(it, range_start);
+ return *this;
+ }
+ iterator operator -- (int)
+ {
+ iterator temp = *this;
+ utf8::prior(it, range_start);
+ return temp;
+ }
+ }; // class iterator
+
+} // namespace utf8
+
+#endif //header guard
+
+
diff --git a/plugins/New_GPG/dependencies/include/utf8/core.h b/plugins/New_GPG/dependencies/include/utf8/core.h
new file mode 100755
index 0000000000..693d388c07
--- /dev/null
+++ b/plugins/New_GPG/dependencies/include/utf8/core.h
@@ -0,0 +1,329 @@
+// Copyright 2006 Nemanja Trifunovic
+
+/*
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+
+#ifndef UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include <iterator>
+
+namespace utf8
+{
+ // The typedefs for 8-bit, 16-bit and 32-bit unsigned integers
+ // You may need to change them to match your system.
+ // These typedefs have the same names as ones from cstdint, or boost/cstdint
+ typedef unsigned char uint8_t;
+ typedef unsigned short uint16_t;
+ typedef unsigned int uint32_t;
+
+// Helper code - not intended to be directly called by the library users. May be changed at any time
+namespace internal
+{
+ // Unicode constants
+ // Leading (high) surrogates: 0xd800 - 0xdbff
+ // Trailing (low) surrogates: 0xdc00 - 0xdfff
+ const uint16_t LEAD_SURROGATE_MIN = 0xd800u;
+ const uint16_t LEAD_SURROGATE_MAX = 0xdbffu;
+ const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u;
+ const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu;
+ const uint16_t LEAD_OFFSET = LEAD_SURROGATE_MIN - (0x10000 >> 10);
+ const uint32_t SURROGATE_OFFSET = 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN;
+
+ // Maximum valid value for a Unicode code point
+ const uint32_t CODE_POINT_MAX = 0x0010ffffu;
+
+ template<typename octet_type>
+ inline uint8_t mask8(octet_type oc)
+ {
+ return static_cast<uint8_t>(0xff & oc);
+ }
+ template<typename u16_type>
+ inline uint16_t mask16(u16_type oc)
+ {
+ return static_cast<uint16_t>(0xffff & oc);
+ }
+ template<typename octet_type>
+ inline bool is_trail(octet_type oc)
+ {
+ return ((utf8::internal::mask8(oc) >> 6) == 0x2);
+ }
+
+ template <typename u16>
+ inline bool is_lead_surrogate(u16 cp)
+ {
+ return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX);
+ }
+
+ template <typename u16>
+ inline bool is_trail_surrogate(u16 cp)
+ {
+ return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
+ }
+
+ template <typename u16>
+ inline bool is_surrogate(u16 cp)
+ {
+ return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
+ }
+
+ template <typename u32>
+ inline bool is_code_point_valid(u32 cp)
+ {
+ return (cp <= CODE_POINT_MAX && !utf8::internal::is_surrogate(cp));
+ }
+
+ template <typename octet_iterator>
+ inline typename std::iterator_traits<octet_iterator>::difference_type
+ sequence_length(octet_iterator lead_it)
+ {
+ uint8_t lead = utf8::internal::mask8(*lead_it);
+ if (lead < 0x80)
+ return 1;
+ else if ((lead >> 5) == 0x6)
+ return 2;
+ else if ((lead >> 4) == 0xe)
+ return 3;
+ else if ((lead >> 3) == 0x1e)
+ return 4;
+ else
+ return 0;
+ }
+
+ template <typename octet_difference_type>
+ inline bool is_overlong_sequence(uint32_t cp, octet_difference_type length)
+ {
+ if (cp < 0x80) {
+ if (length != 1)
+ return true;
+ }
+ else if (cp < 0x800) {
+ if (length != 2)
+ return true;
+ }
+ else if (cp < 0x10000) {
+ if (length != 3)
+ return true;
+ }
+
+ return false;
+ }
+
+ enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT};
+
+ /// Helper for get_sequence_x
+ template <typename octet_iterator>
+ utf_error increase_safely(octet_iterator& it, octet_iterator end)
+ {
+ if (++it == end)
+ return NOT_ENOUGH_ROOM;
+
+ if (!utf8::internal::is_trail(*it))
+ return INCOMPLETE_SEQUENCE;
+
+ return UTF8_OK;
+ }
+
+ #define UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(IT, END) {utf_error ret = increase_safely(IT, END); if (ret != UTF8_OK) return ret;}
+
+ /// get_sequence_x functions decode utf-8 sequences of the length x
+ template <typename octet_iterator>
+ utf_error get_sequence_1(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ if (it == end)
+ return NOT_ENOUGH_ROOM;
+
+ code_point = utf8::internal::mask8(*it);
+
+ return UTF8_OK;
+ }
+
+ template <typename octet_iterator>
+ utf_error get_sequence_2(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ if (it == end)
+ return NOT_ENOUGH_ROOM;
+
+ code_point = utf8::internal::mask8(*it);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point = ((code_point << 6) & 0x7ff) + ((*it) & 0x3f);
+
+ return UTF8_OK;
+ }
+
+ template <typename octet_iterator>
+ utf_error get_sequence_3(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ if (it == end)
+ return NOT_ENOUGH_ROOM;
+
+ code_point = utf8::internal::mask8(*it);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point = ((code_point << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point += (*it) & 0x3f;
+
+ return UTF8_OK;
+ }
+
+ template <typename octet_iterator>
+ utf_error get_sequence_4(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ if (it == end)
+ return NOT_ENOUGH_ROOM;
+
+ code_point = utf8::internal::mask8(*it);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point = ((code_point << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point += (utf8::internal::mask8(*it) << 6) & 0xfff;
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point += (*it) & 0x3f;
+
+ return UTF8_OK;
+ }
+
+ #undef UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR
+
+ template <typename octet_iterator>
+ utf_error validate_next(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ // Save the original value of it so we can go back in case of failure
+ // Of course, it does not make much sense with i.e. stream iterators
+ octet_iterator original_it = it;
+
+ uint32_t cp = 0;
+ // Determine the sequence length based on the lead octet
+ typedef typename std::iterator_traits<octet_iterator>::difference_type octet_difference_type;
+ const octet_difference_type length = utf8::internal::sequence_length(it);
+
+ // Get trail octets and calculate the code point
+ utf_error err = UTF8_OK;
+ switch (length) {
+ case 0:
+ return INVALID_LEAD;
+ case 1:
+ err = utf8::internal::get_sequence_1(it, end, cp);
+ break;
+ case 2:
+ err = utf8::internal::get_sequence_2(it, end, cp);
+ break;
+ case 3:
+ err = utf8::internal::get_sequence_3(it, end, cp);
+ break;
+ case 4:
+ err = utf8::internal::get_sequence_4(it, end, cp);
+ break;
+ }
+
+ if (err == UTF8_OK) {
+ // Decoding succeeded. Now, security checks...
+ if (utf8::internal::is_code_point_valid(cp)) {
+ if (!utf8::internal::is_overlong_sequence(cp, length)){
+ // Passed! Return here.
+ code_point = cp;
+ ++it;
+ return UTF8_OK;
+ }
+ else
+ err = OVERLONG_SEQUENCE;
+ }
+ else
+ err = INVALID_CODE_POINT;
+ }
+
+ // Failure branch - restore the original value of the iterator
+ it = original_it;
+ return err;
+ }
+
+ template <typename octet_iterator>
+ inline utf_error validate_next(octet_iterator& it, octet_iterator end) {
+ uint32_t ignored;
+ return utf8::internal::validate_next(it, end, ignored);
+ }
+
+} // namespace internal
+
+ /// The library API - functions intended to be called by the users
+
+ // Byte order mark
+ const uint8_t bom[] = {0xef, 0xbb, 0xbf};
+
+ template <typename octet_iterator>
+ octet_iterator find_invalid(octet_iterator start, octet_iterator end)
+ {
+ octet_iterator result = start;
+ while (result != end) {
+ utf8::internal::utf_error err_code = utf8::internal::validate_next(result, end);
+ if (err_code != internal::UTF8_OK)
+ return result;
+ }
+ return result;
+ }
+
+ template <typename octet_iterator>
+ inline bool is_valid(octet_iterator start, octet_iterator end)
+ {
+ return (utf8::find_invalid(start, end) == end);
+ }
+
+ template <typename octet_iterator>
+ inline bool starts_with_bom (octet_iterator it, octet_iterator end)
+ {
+ return (
+ ((it != end) && (utf8::internal::mask8(*it++)) == bom[0]) &&
+ ((it != end) && (utf8::internal::mask8(*it++)) == bom[1]) &&
+ ((it != end) && (utf8::internal::mask8(*it)) == bom[2])
+ );
+ }
+
+ //Deprecated in release 2.3
+ template <typename octet_iterator>
+ inline bool is_bom (octet_iterator it)
+ {
+ return (
+ (utf8::internal::mask8(*it++)) == bom[0] &&
+ (utf8::internal::mask8(*it++)) == bom[1] &&
+ (utf8::internal::mask8(*it)) == bom[2]
+ );
+ }
+} // namespace utf8
+
+#endif // header guard
+
+
diff --git a/plugins/New_GPG/dependencies/include/utf8/unchecked.h b/plugins/New_GPG/dependencies/include/utf8/unchecked.h
new file mode 100755
index 0000000000..b4547fad94
--- /dev/null
+++ b/plugins/New_GPG/dependencies/include/utf8/unchecked.h
@@ -0,0 +1,228 @@
+// Copyright 2006 Nemanja Trifunovic
+
+/*
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+
+#ifndef UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include "core.h"
+
+namespace utf8
+{
+ namespace unchecked
+ {
+ template <typename octet_iterator>
+ octet_iterator append(uint32_t cp, octet_iterator result)
+ {
+ if (cp < 0x80) // one octet
+ *(result++) = static_cast<uint8_t>(cp);
+ else if (cp < 0x800) { // two octets
+ *(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ else if (cp < 0x10000) { // three octets
+ *(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0);
+ *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ else { // four octets
+ *(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0);
+ *(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f)| 0x80);
+ *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ return result;
+ }
+
+ template <typename octet_iterator>
+ uint32_t next(octet_iterator& it)
+ {
+ uint32_t cp = utf8::internal::mask8(*it);
+ typename std::iterator_traits<octet_iterator>::difference_type length = utf8::internal::sequence_length(it);
+ switch (length) {
+ case 1:
+ break;
+ case 2:
+ it++;
+ cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f);
+ break;
+ case 3:
+ ++it;
+ cp = ((cp << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff);
+ ++it;
+ cp += (*it) & 0x3f;
+ break;
+ case 4:
+ ++it;
+ cp = ((cp << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff);
+ ++it;
+ cp += (utf8::internal::mask8(*it) << 6) & 0xfff;
+ ++it;
+ cp += (*it) & 0x3f;
+ break;
+ }
+ ++it;
+ return cp;
+ }
+
+ template <typename octet_iterator>
+ uint32_t peek_next(octet_iterator it)
+ {
+ return utf8::unchecked::next(it);
+ }
+
+ template <typename octet_iterator>
+ uint32_t prior(octet_iterator& it)
+ {
+ while (utf8::internal::is_trail(*(--it))) ;
+ octet_iterator temp = it;
+ return utf8::unchecked::next(temp);
+ }
+
+ // Deprecated in versions that include prior, but only for the sake of consistency (see utf8::previous)
+ template <typename octet_iterator>
+ inline uint32_t previous(octet_iterator& it)
+ {
+ return utf8::unchecked::prior(it);
+ }
+
+ template <typename octet_iterator, typename distance_type>
+ void advance (octet_iterator& it, distance_type n)
+ {
+ for (distance_type i = 0; i < n; ++i)
+ utf8::unchecked::next(it);
+ }
+
+ template <typename octet_iterator>
+ typename std::iterator_traits<octet_iterator>::difference_type
+ distance (octet_iterator first, octet_iterator last)
+ {
+ typename std::iterator_traits<octet_iterator>::difference_type dist;
+ for (dist = 0; first < last; ++dist)
+ utf8::unchecked::next(first);
+ return dist;
+ }
+
+ template <typename u16bit_iterator, typename octet_iterator>
+ octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
+ {
+ while (start != end) {
+ uint32_t cp = utf8::internal::mask16(*start++);
+ // Take care of surrogate pairs first
+ if (utf8::internal::is_lead_surrogate(cp)) {
+ uint32_t trail_surrogate = utf8::internal::mask16(*start++);
+ cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
+ }
+ result = utf8::unchecked::append(cp, result);
+ }
+ return result;
+ }
+
+ template <typename u16bit_iterator, typename octet_iterator>
+ u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
+ {
+ while (start < end) {
+ uint32_t cp = utf8::unchecked::next(start);
+ if (cp > 0xffff) { //make a surrogate pair
+ *result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET);
+ *result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
+ }
+ else
+ *result++ = static_cast<uint16_t>(cp);
+ }
+ return result;
+ }
+
+ template <typename octet_iterator, typename u32bit_iterator>
+ octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
+ {
+ while (start != end)
+ result = utf8::unchecked::append(*(start++), result);
+
+ return result;
+ }
+
+ template <typename octet_iterator, typename u32bit_iterator>
+ u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
+ {
+ while (start < end)
+ (*result++) = utf8::unchecked::next(start);
+
+ return result;
+ }
+
+ // The iterator class
+ template <typename octet_iterator>
+ class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> {
+ octet_iterator it;
+ public:
+ iterator () {};
+ explicit iterator (const octet_iterator& octet_it): it(octet_it) {}
+ // the default "big three" are OK
+ octet_iterator base () const { return it; }
+ uint32_t operator * () const
+ {
+ octet_iterator temp = it;
+ return utf8::unchecked::next(temp);
+ }
+ bool operator == (const iterator& rhs) const
+ {
+ return (it == rhs.it);
+ }
+ bool operator != (const iterator& rhs) const
+ {
+ return !(operator == (rhs));
+ }
+ iterator& operator ++ ()
+ {
+ ::std::advance(it, utf8::internal::sequence_length(it));
+ return *this;
+ }
+ iterator operator ++ (int)
+ {
+ iterator temp = *this;
+ ::std::advance(it, utf8::internal::sequence_length(it));
+ return temp;
+ }
+ iterator& operator -- ()
+ {
+ utf8::unchecked::prior(it);
+ return *this;
+ }
+ iterator operator -- (int)
+ {
+ iterator temp = *this;
+ utf8::unchecked::prior(it);
+ return temp;
+ }
+ }; // class iterator
+
+ } // namespace utf8::unchecked
+} // namespace utf8
+
+
+#endif // header guard
+
diff --git a/plugins/New_GPG/new_gpg_10.vcxproj b/plugins/New_GPG/new_gpg_10.vcxproj
new file mode 100755
index 0000000000..7dfa1d30fb
--- /dev/null
+++ b/plugins/New_GPG/new_gpg_10.vcxproj
@@ -0,0 +1,1031 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|X64">
+ <Configuration>Debug</Configuration>
+ <Platform>X64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|X64">
+ <Configuration>Release</Configuration>
+ <Platform>X64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="src\clist.cpp" />
+ <ClCompile Include="src\gpg_wrapper.cpp" />
+ <ClCompile Include="src\icons.cpp" />
+ <ClCompile Include="src\init.cpp" />
+ <ClCompile Include="src\jabber_account.cpp" />
+ <ClCompile Include="src\log.cpp" />
+ <ClCompile Include="src\main.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|X64'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|X64'">Create</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\messages.cpp" />
+ <ClCompile Include="src\metacontacts.cpp" />
+ <ClCompile Include="src\options.cpp" />
+ <ClCompile Include="src\srmm.cpp" />
+ <ClCompile Include="src\utilities.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\commonheaders.h" />
+ <ClInclude Include="src\constants.h" />
+ <ClInclude Include="src\globals.h" />
+ <ClInclude Include="src\gpg_wrapper.h" />
+ <ClInclude Include="src\jabber_account.h" />
+ <ClInclude Include="src\log.h" />
+ <ClInclude Include="src\main.h" />
+ <ClInclude Include="src\metacontacts.h" />
+ <ClInclude Include="src\m_extraicons.h" />
+ <ClInclude Include="src\m_metacontacts.h" />
+ <ClInclude Include="src\resource.h" />
+ <ClInclude Include="src\utilities.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\new_gpg.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="res\icons\secured.ico" />
+ <None Include="res\icons\unsecured.ico" />
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{F29D0C8D-141A-43CF-86B2-34A04653F8D4}</ProjectGuid>
+ <RootNamespace>new_gpg</RootNamespace>
+ <ProjectName>new_gpg</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug(service)|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)|X64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)(static)|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)(static)|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)(static)|X64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode (static)|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode (static) x64|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|X64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug x64|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|X64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|X64'">$(SolutionDir)$(Configuration)64\Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Configuration)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|X64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|X64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\Debug\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|X64'">$(SolutionDir)$(Configuration)64\Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\Debug\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|X64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|X64'">true</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug x64|x64'">true</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode (static)|x64'">$(SolutionDir)$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode (static) x64|x64'">$(SolutionDir)$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode (static)|x64'">$(Configuration)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode (static) x64|x64'">$(Configuration)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release Unicode (static)|x64'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release Unicode (static) x64|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)(static)|x64'">$(SolutionDir)$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)(static)|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)(static)|X64'">$(SolutionDir)$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)(static)|x64'">$(Configuration)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)(static)|Win32'">$(Configuration)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)(static)|X64'">$(Configuration)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)(static)|x64'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)(static)|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)(static)|X64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)|x64'">$(SolutionDir)$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)|X64'">$(SolutionDir)$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)|x64'">$(Configuration)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)|Win32'">$(Configuration)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)|X64'">$(Configuration)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)|x64'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)|X64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug(service)|x64'">$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug(service)|x64'">$(Configuration)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug(service)|x64'">true</LinkIncremental>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug(service)|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug(service)|x64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug(service)|x64'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|X64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug x64|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|X64'" />
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug x64|x64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|X64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug x64|x64'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)(static)|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)(static)|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)(static)|X64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)(static)|x64'" />
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)(static)|Win32'" />
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)(static)|X64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)(static)|x64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)(static)|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)(static)|X64'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)|X64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)|x64'" />
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)|Win32'" />
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)|X64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)|x64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)|X64'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release Unicode (static)|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release Unicode (static) x64|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release Unicode (static)|x64'" />
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release Unicode (static) x64|x64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release Unicode (static)|x64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release Unicode (static) x64|x64'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|X64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|X64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|X64'" />
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TypeLibraryName>.\Release Unicode/testplug.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <OmitFramePointers>true</OmitFramePointers>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <AdditionalIncludeDirectories>X:\install\git\miranda\mim_plugs;X:\install\git\miranda\miranda-im\miranda\include;../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;_UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
+ <FloatingPointModel>Precise</FloatingPointModel>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0809</Culture>
+ </ResourceCompile>
+ <Link>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <AdditionalLibraryDirectories>X:\install\git\miranda\mim_plugs\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>.\Release Unicode/testplug.lib</ImportLibrary>
+ </Link>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>.\Release Unicode/testplug.bsc</OutputFile>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TypeLibraryName>.\Release Unicode/testplug.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <OmitFramePointers>true</OmitFramePointers>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <AdditionalIncludeDirectories>.\dependencies\include;..\..\..\boost_1_49_0;..\..\include</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;_UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>commonheaders.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0809</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib;..\..\..\boost_1_49_0\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <SubSystem>Windows</SubSystem>
+ </Link>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>.\Release Unicode/testplug.bsc</OutputFile>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|X64'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TypeLibraryName>.\Release Unicode/testplug.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <OmitFramePointers>true</OmitFramePointers>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <AdditionalIncludeDirectories>.\dependencies\include;..\..\..\boost_1_49_0;..\..\include</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;_UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>commonheaders.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0809</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib;..\..\..\boost_1_49_0\lib64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <SubSystem>Windows</SubSystem>
+ </Link>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>.\Release Unicode/testplug.bsc</OutputFile>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TypeLibraryName>.\Debug/testplug.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>x:\temp\windows\libs\utf8cpp\include;x:\temp\windows\libs\boost;x:\install\git\miranda\miranda-im\miranda\include;x:\install\git\miranda\mim_plugs;../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;TESTPLUG_EXPORTS;_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>commonheaders.h</PrecompiledHeaderFile>
+ <AssemblerOutput>
+ </AssemblerOutput>
+ <BrowseInformation>true</BrowseInformation>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0809</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <AdditionalLibraryDirectories>x:\temp\windows\libs\boost\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>.\Debug/testplug.lib</ImportLibrary>
+ </Link>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>.\Debug/testplug.bsc</OutputFile>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TypeLibraryName>.\Debug/testplug.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>.\dependencies\include;..\..\..\boost_1_49_0;..\..\include</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;TESTPLUG_EXPORTS;_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>commonheaders.h</PrecompiledHeaderFile>
+ <BrowseInformation>true</BrowseInformation>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <RuntimeTypeInfo>true</RuntimeTypeInfo>
+ <CompileAs>CompileAsCpp</CompileAs>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0809</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib;..\..\..\boost_1_49_0\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ </Link>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>.\Debug/testplug.bsc</OutputFile>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|X64'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TypeLibraryName>.\Debug/testplug.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>.\dependencies\include;..\..\..\boost_1_49_0;..\..\include</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;_USRDLL;TESTPLUG_EXPORTS;_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>commonheaders.h</PrecompiledHeaderFile>
+ <BrowseInformation>true</BrowseInformation>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <RuntimeTypeInfo>true</RuntimeTypeInfo>
+ <CompileAs>CompileAsCpp</CompileAs>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0809</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib;..\..\..\boost_1_49_0\lib64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ </Link>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>.\Debug/testplug.bsc</OutputFile>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug x64|x64'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TypeLibraryName>.\Debug/testplug.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>x:\temp\windows\libs\utf8cpp\include;X:\temp\windows\libs\Boost\include;x:\install\git\miranda\miranda-im\miranda\include;x:\install\git\miranda\mim_plugs;../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;TESTPLUG_EXPORTS;_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>commonheaders.h</PrecompiledHeaderFile>
+ <PrecompiledHeaderOutputFile>c:\temp\new_gpg.pch</PrecompiledHeaderOutputFile>
+ <AssemblerOutput>
+ </AssemblerOutput>
+ <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
+ <ObjectFileName>.\Debug/</ObjectFileName>
+ <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0809</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <AdditionalLibraryDirectories>X:\temp\windows\libs\Boost\lib64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AssemblyDebug>true</AssemblyDebug>
+ <GenerateMapFile>false</GenerateMapFile>
+ <MapExports>false</MapExports>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>.\Debug/testplug.lib</ImportLibrary>
+ <ProgramDatabaseFile>c:\debug\$(TargetName).pdb</ProgramDatabaseFile>
+ </Link>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>.\Debug/testplug.bsc</OutputFile>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode (static)|x64'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TypeLibraryName>.\Release Unicode (static)/testplug.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MinSpace</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <OmitFramePointers>true</OmitFramePointers>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <AdditionalIncludeDirectories>x:\temp\windows\libs\utf8cpp\include;C:\Boost\include\boost-1_45;x:\install\git\miranda\miranda-im\miranda\include;x:\install\git\miranda\mim_plugs;../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;_UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
+ <FloatingPointModel>Precise</FloatingPointModel>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>commonheaders.h</PrecompiledHeaderFile>
+ <PrecompiledHeaderOutputFile>c:\temp\new_gpg.pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\Release Unicode (static)/</AssemblerListingLocation>
+ <ObjectFileName>.\Release Unicode (static)/</ObjectFileName>
+ <ProgramDataBaseFileName>.\Release Unicode (static)/</ProgramDataBaseFileName>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0809</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <AdditionalLibraryDirectories>x:\temp\windows\libs\boost\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <SubSystem>NotSet</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>.\Release Unicode (static)/testplug.lib</ImportLibrary>
+ </Link>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>.\Release Unicode (static)/testplug.bsc</OutputFile>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode (static) x64|x64'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TypeLibraryName>.\Release Unicode (static)/testplug.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MinSpace</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <OmitFramePointers>true</OmitFramePointers>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <AdditionalIncludeDirectories>x:\temp\windows\libs\utf8cpp\include;x:\temp\windows\libs\Boost\include;x:\install\git\miranda\miranda-im\miranda\include;x:\install\git\miranda\mim_plugs;../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;_UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
+ <FloatingPointModel>Precise</FloatingPointModel>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>commonheaders.h</PrecompiledHeaderFile>
+ <PrecompiledHeaderOutputFile>c:\temp\new_gpg.pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\Release Unicode (static)/</AssemblerListingLocation>
+ <ObjectFileName>.\Release Unicode (static)/</ObjectFileName>
+ <ProgramDataBaseFileName>.\Release Unicode (static)/</ProgramDataBaseFileName>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0809</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <AdditionalLibraryDirectories>x:\temp\windows\libs\Boost\lib64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>NotSet</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>.\Release Unicode (static)/testplug.lib</ImportLibrary>
+ <ProgramDatabaseFile>c:\debug\$(TargetName).pdb</ProgramDatabaseFile>
+ </Link>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>.\Release Unicode (static)/testplug.bsc</OutputFile>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)(static)|x64'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TypeLibraryName>.\Release Unicode (static)/testplug.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <OmitFramePointers>true</OmitFramePointers>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <AdditionalIncludeDirectories>../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
+ <FloatingPointModel>Precise</FloatingPointModel>
+ <PrecompiledHeaderOutputFile>.\Release Unicode (static)/testplug.pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\Release Unicode (static)/</AssemblerListingLocation>
+ <ObjectFileName>.\Release Unicode (static)/</ObjectFileName>
+ <ProgramDataBaseFileName>.\Release Unicode (static)/</ProgramDataBaseFileName>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0809</Culture>
+ </ResourceCompile>
+ <Link>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>.\Release Unicode (static)/testplug.lib</ImportLibrary>
+ </Link>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>.\Release Unicode (static)/testplug.bsc</OutputFile>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)(static)|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TypeLibraryName>.\Release Unicode (static)/testplug.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <OmitFramePointers>true</OmitFramePointers>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <AdditionalIncludeDirectories>../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
+ <FloatingPointModel>Precise</FloatingPointModel>
+ <PrecompiledHeaderOutputFile>.\Release Unicode (static)/testplug.pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\Release Unicode (static)/</AssemblerListingLocation>
+ <ObjectFileName>.\Release Unicode (static)/</ObjectFileName>
+ <ProgramDataBaseFileName>.\Release Unicode (static)/</ProgramDataBaseFileName>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0809</Culture>
+ </ResourceCompile>
+ <Link>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>.\Release Unicode (static)/testplug.lib</ImportLibrary>
+ </Link>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>.\Release Unicode (static)/testplug.bsc</OutputFile>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)(static)|X64'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TypeLibraryName>.\Release Unicode (static)/testplug.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <OmitFramePointers>true</OmitFramePointers>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <AdditionalIncludeDirectories>../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
+ <FloatingPointModel>Precise</FloatingPointModel>
+ <PrecompiledHeaderOutputFile>.\Release Unicode (static)/testplug.pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\Release Unicode (static)/</AssemblerListingLocation>
+ <ObjectFileName>.\Release Unicode (static)/</ObjectFileName>
+ <ProgramDataBaseFileName>.\Release Unicode (static)/</ProgramDataBaseFileName>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0809</Culture>
+ </ResourceCompile>
+ <Link>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>.\Release Unicode (static)/testplug.lib</ImportLibrary>
+ </Link>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>.\Release Unicode (static)/testplug.bsc</OutputFile>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)|x64'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TypeLibraryName>.\Release Unicode (static)/testplug.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <OmitFramePointers>true</OmitFramePointers>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <AdditionalIncludeDirectories>../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
+ <FloatingPointModel>Precise</FloatingPointModel>
+ <PrecompiledHeaderOutputFile>.\Release Unicode (static)/testplug.pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\Release Unicode (static)/</AssemblerListingLocation>
+ <ObjectFileName>.\Release Unicode (static)/</ObjectFileName>
+ <ProgramDataBaseFileName>.\Release Unicode (static)/</ProgramDataBaseFileName>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0809</Culture>
+ </ResourceCompile>
+ <Link>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>.\Release Unicode (static)/testplug.lib</ImportLibrary>
+ </Link>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>.\Release Unicode (static)/testplug.bsc</OutputFile>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TypeLibraryName>.\Release Unicode (static)/testplug.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <OmitFramePointers>true</OmitFramePointers>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <AdditionalIncludeDirectories>../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
+ <FloatingPointModel>Precise</FloatingPointModel>
+ <PrecompiledHeaderOutputFile>.\Release Unicode (static)/testplug.pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\Release Unicode (static)/</AssemblerListingLocation>
+ <ObjectFileName>.\Release Unicode (static)/</ObjectFileName>
+ <ProgramDataBaseFileName>.\Release Unicode (static)/</ProgramDataBaseFileName>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0809</Culture>
+ </ResourceCompile>
+ <Link>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>.\Release Unicode (static)/testplug.lib</ImportLibrary>
+ </Link>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>.\Release Unicode (static)/testplug.bsc</OutputFile>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode (service only)|X64'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TypeLibraryName>.\Release Unicode (static)/testplug.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <OmitFramePointers>true</OmitFramePointers>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <AdditionalIncludeDirectories>../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
+ <FloatingPointModel>Precise</FloatingPointModel>
+ <PrecompiledHeaderOutputFile>.\Release Unicode (static)/testplug.pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\Release Unicode (static)/</AssemblerListingLocation>
+ <ObjectFileName>.\Release Unicode (static)/</ObjectFileName>
+ <ProgramDataBaseFileName>.\Release Unicode (static)/</ProgramDataBaseFileName>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0809</Culture>
+ </ResourceCompile>
+ <Link>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>.\Release Unicode (static)/testplug.lib</ImportLibrary>
+ </Link>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>.\Release Unicode (static)/testplug.bsc</OutputFile>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug(service)|x64'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TypeLibraryName>.\Debug/testplug.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;TESTPLUG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeaderOutputFile>.\Debug/testplug.pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
+ <ObjectFileName>.\Debug/</ObjectFileName>
+ <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0809</Culture>
+ </ResourceCompile>
+ <Link>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>.\Debug/testplug.lib</ImportLibrary>
+ </Link>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>.\Debug/testplug.bsc</OutputFile>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+ <ProjectExtensions>
+ <VisualStudio>
+ <UserProperties RESOURCE_FILE="new_gpg.rc" />
+ </VisualStudio>
+ </ProjectExtensions>
+</Project> \ No newline at end of file
diff --git a/plugins/New_GPG/new_gpg_10.vcxproj.filters b/plugins/New_GPG/new_gpg_10.vcxproj.filters
new file mode 100755
index 0000000000..37e663c898
--- /dev/null
+++ b/plugins/New_GPG/new_gpg_10.vcxproj.filters
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Sources">
+ <UniqueIdentifier>{56a6d5fd-c491-4d42-95e0-d0e98979acff}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Resources">
+ <UniqueIdentifier>{8159144c-7020-4568-8bb4-53f4699faac6}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Headers">
+ <UniqueIdentifier>{65abe24a-f835-47f5-9ebf-fbd3f55f993c}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="src\clist.cpp">
+ <Filter>Sources</Filter>
+ </ClCompile>
+ <ClCompile Include="src\gpg_wrapper.cpp">
+ <Filter>Sources</Filter>
+ </ClCompile>
+ <ClCompile Include="src\icons.cpp">
+ <Filter>Sources</Filter>
+ </ClCompile>
+ <ClCompile Include="src\init.cpp">
+ <Filter>Sources</Filter>
+ </ClCompile>
+ <ClCompile Include="src\jabber_account.cpp">
+ <Filter>Sources</Filter>
+ </ClCompile>
+ <ClCompile Include="src\log.cpp">
+ <Filter>Sources</Filter>
+ </ClCompile>
+ <ClCompile Include="src\main.cpp">
+ <Filter>Sources</Filter>
+ </ClCompile>
+ <ClCompile Include="src\messages.cpp">
+ <Filter>Sources</Filter>
+ </ClCompile>
+ <ClCompile Include="src\metacontacts.cpp">
+ <Filter>Sources</Filter>
+ </ClCompile>
+ <ClCompile Include="src\options.cpp">
+ <Filter>Sources</Filter>
+ </ClCompile>
+ <ClCompile Include="src\srmm.cpp">
+ <Filter>Sources</Filter>
+ </ClCompile>
+ <ClCompile Include="src\utilities.cpp">
+ <Filter>Sources</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\commonheaders.h">
+ <Filter>Headers</Filter>
+ </ClInclude>
+ <ClInclude Include="src\constants.h">
+ <Filter>Headers</Filter>
+ </ClInclude>
+ <ClInclude Include="src\globals.h">
+ <Filter>Headers</Filter>
+ </ClInclude>
+ <ClInclude Include="src\gpg_wrapper.h">
+ <Filter>Headers</Filter>
+ </ClInclude>
+ <ClInclude Include="src\jabber_account.h">
+ <Filter>Headers</Filter>
+ </ClInclude>
+ <ClInclude Include="src\log.h">
+ <Filter>Headers</Filter>
+ </ClInclude>
+ <ClInclude Include="src\m_extraicons.h">
+ <Filter>Headers</Filter>
+ </ClInclude>
+ <ClInclude Include="src\m_metacontacts.h">
+ <Filter>Headers</Filter>
+ </ClInclude>
+ <ClInclude Include="src\main.h">
+ <Filter>Headers</Filter>
+ </ClInclude>
+ <ClInclude Include="src\utilities.h">
+ <Filter>Headers</Filter>
+ </ClInclude>
+ <ClInclude Include="src\resource.h">
+ <Filter>Headers</Filter>
+ </ClInclude>
+ <ClInclude Include="src\metacontacts.h">
+ <Filter>Headers</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\new_gpg.rc">
+ <Filter>Resources</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="res\icons\secured.ico">
+ <Filter>Resources</Filter>
+ </None>
+ <None Include="res\icons\unsecured.ico">
+ <Filter>Resources</Filter>
+ </None>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/New_GPG/new_gpg_lang_ru.txt b/plugins/New_GPG/new_gpg_lang_ru.txt
new file mode 100755
index 0000000000..4cf3659695
--- /dev/null
+++ b/plugins/New_GPG/new_gpg_lang_ru.txt
@@ -0,0 +1,115 @@
+;============================================================
+; File: new_gpg.dll
+; Module: new GPG encryption plugin
+; Versions: 0.0.0.11
+; URL: http://addons.miranda-im.org/details.php?action=viewfile&id=958
+; Source: git://sss.chaoslab.ru/mim_plugs.git (checkout new_gpg)
+; Authors: sss
+;============================================================
+
+[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
+Âàøà âåðñèÿ GPG ïîääåðæèâàåòñÿ. ßçûêîâûå ôàéëû íàéäåíû.\nGPG Äîëæåí ðàáîòàòü íîðìàëüíî.\nÍàæìèòå ÎÊ.
+[Copy own key]
+Êîïèð. ñâîé êëþ÷
+[Select own key]
+Âûáðàòü ñâîé êëþ÷
+[Export PubKey]
+Ñîõðàíèòü êëþ÷
+[GnuPG Variables]
+Ïóòè ê GPG
+[Turn on debug log]
+Âêë. çàïèñü îòëàäêè
+[Accept]
+Ïðèíÿòü
+[Accept and enable encryption]
+Ïðèíÿòü è âêëþ÷èòü øèôðîâàíèå
+[Replace]
+Çàìåíèòü
+[Import key]
+Èìïîðò êëþ÷à
+[Load from file]
+Èìïîðò èç ôàéëà
+[Load other]
+Çàãðóçèòü
+[Delete key]
+Óäàëèòü êëþ÷
+[Select existing]
+Âûáðàòü ñóùåñòâóþùèé
+[Turn on encryption]
+Âêëþ÷èòü øèôðîâàíèå
+[Import key from keyserver]
+Èìïîðò êëþ÷à ñ ñåðâåðà êëþ÷åé
+[New public key was received, do you want to import it?]
+Ïîëó÷åí íîâûé îòðûòûé êëþ÷. Âû õîòèòå åãî ïðèíÿòü?
+[There is existing key for contact, would you like to replace with new key ?]
+Ïîëó÷åí êëþ÷, íî ó êîíòàêòà óæå åñòü êëþ÷. Âû õîòèòå åãî çàìåíèòü íîâûì?
+[The new public key was recieved]
+Ïîëó÷åí íîâûé îòðûòûé êëþ÷.
+[Received key from]
+Ïîëó÷åí êëþ÷ îò
+[Do you want to remove key from entire metacontact (all subcontacts) ?]
+Âû õîòèòå óáðàòü êëþ÷ äëÿ ìåòàêîíòàêòà (âñåõ ñóáêîíòàêòîâ)?
+[Select existing public key from list]
+Âûáðàòü îòêðûòûé êëþ÷ èç ñïèñêà
+[Encrypt file transfers]
+Øèôðîâàííàÿ ïåðåäà÷à ôàéëîâ
+[Use jabber api on Miranda IM >= 0.9 (recomended)]
+Èñïîëüçîâàòü jabber api åñëè Miranda IM >= 0.9 (Ðåêîìåíäóåòñÿ)
+[Current private key id]
+Çàêðûòûé êëþ÷
+[This is not gnupg binary !\nrecommended to use GnuPG v1.x.x with this plugn.]
+Âûáðàííûé âàìè exe íå GnuPG!\nÐåêîìåíäóåòñÿ èñïîëüçîâàòü GnuPG v1.x.x ñ ýòèì ïëàãèíîì.
+[Unsupported gnupg version found, use at you own risk!\nrecommended to use GnuPG v1.x.x with this plugn.]
+Âàøà âåðñèÿ GnuPG íå ïîääåðæèâàåòñÿ è ìîæåò ðàáîòàòü íå ïðàâèëüíî!\nÐåêîìåíäóåòñÿ èñïîëüçîâàòü GnuPG v1.x.x ñ ýòèì ïëàãèíîì.
+[Generate key]
+Ñãåíåðèðîâàòü
+[Select key for use]
+Âûáðàòü êëþ÷
+[Generate and use random key]
+Ñãåíåðèðîâàòü è èñïîëüçîâàòü êëþ÷
+[GnuPG binary:]
+Ïóòü ê exe:
+[Home directory:]
+Äîìàøíèé êàòàëîã:
+[Turn on key autoexchange]
+Âêëþ÷èòü àâòîîáìåí êëþ÷àìè
+[Key type:]
+Òèï êëþ÷à:
+[Key length:]
+Äëèííà êëþ÷à
+[Key password:]
+Ïàðîëü êëþ÷à:
+[Real name:]
+Èìÿ/Íèê:
+[Comment:]
+Êîììåíòàðèé:
+[Expire date:]
+Îêîí÷àíèå äåéñòâèÿ êëþ÷à:
+[ex.: 2010-08-15]
+ïðèìåð: 2010-08-15
+[From 1024 to 4096]
+îò 1024 äî 4096
+[It can take a long time, be patient]
+* Ýòî ìîæåò çàíÿòü íåñêîëüêî ìèíóò.
+[0 - does not expire]
+0 - íèêîãäà íå çàêàí÷èâàåòñÿ
+[Save password to database]
+Ñîõðàíèòü ïàðîëü â áàçó
+[Default password]
+Ïàðîëü ïî óìîë÷àíèþ
+[Import]
+Èìïîðòèðîâàòü
+[Select keyserver for key search:]
+Âûáðàòü ñåðâåð êëþ÷åé äëÿ ïîèñêà:
+[Userlist:]
+Ëèñò ïîëüçîâàòåëåé:
+[Add tags to encoded and decoded messages]
+Äîáàâëÿòü ìåòêè ê ñîîáùåíèÿì
+[Incomming message tags:]
+Äîáàâëÿòü ìåòêè ê âõîäÿùèì ñîîáùåíèÿì:
+[Outgoing message tags:]
+Äîáàâëÿòü ìåòêè èñõîäÿùèì ñîîáùåíèÿñ:
+[Open:]
+Íà÷àëî
+[Close:]
+Êîíåö
diff --git a/plugins/New_GPG/res/icons/secured.ico b/plugins/New_GPG/res/icons/secured.ico
new file mode 100755
index 0000000000..8d84167e56
--- /dev/null
+++ b/plugins/New_GPG/res/icons/secured.ico
Binary files differ
diff --git a/plugins/New_GPG/res/icons/unsecured.ico b/plugins/New_GPG/res/icons/unsecured.ico
new file mode 100755
index 0000000000..567367b389
--- /dev/null
+++ b/plugins/New_GPG/res/icons/unsecured.ico
Binary files differ
diff --git a/plugins/New_GPG/res/new_gpg.rc b/plugins/New_GPG/res/new_gpg.rc
new file mode 100755
index 0000000000..f72f9ea9c5
--- /dev/null
+++ b/plugins/New_GPG/res/new_gpg.rc
@@ -0,0 +1,419 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "src/resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Ðóññêèé (Ðîññèÿ) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)
+LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
+#pragma code_page(1251)
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_LOAD_PUBLIC_KEY DIALOGEX 0, 0, 338, 190
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Load Public GPG key"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "ÎÊ",ID_OK,7,169,50,14
+ PUSHBUTTON "Load from file",ID_LOAD_FROM_FILE,273,169,58,14
+ EDITTEXT IDC_PUBLIC_KEY_EDIT,7,7,324,134,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | WS_VSCROLL,WS_EX_STATICEDGE
+ PUSHBUTTON "Select existing",IDC_SELECT_EXISTING,113,169,97,14
+ CONTROL "Turn on encryption",IDC_ENABLE_ENCRYPTION,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,143,196,10
+ PUSHBUTTON "Import key from keyserver",IDC_IMPORT,140,152,188,14,WS_DISABLED
+END
+
+IDD_FIRST_RUN DIALOGEX 0, 0, 291, 230
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Set own key"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "ÎÊ",ID_OK,12,209,50,14,WS_DISABLED
+ CONTROL "",IDC_KEY_LIST,"SysListView32",LVS_REPORT | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,44,277,105
+ PUSHBUTTON "Generate key",IDC_GENERATE_KEY,8,152,74,14
+ LTEXT "Select key for use",IDC_STATIC,16,33,186,8
+ EDITTEXT IDC_KEY_PASSWORD,94,168,77,14,ES_PASSWORD | ES_AUTOHSCROLL
+ RTEXT "Key password:",IDC_STATIC,12,170,76,8
+ PUSHBUTTON "Load other",IDC_OTHER,83,152,64,14
+ PUSHBUTTON "Delete key",IDC_DELETE_KEY,149,152,70,14
+ PUSHBUTTON "Generate and use random key",IDC_GENERATE_RANDOM,99,184,118,14
+ LTEXT "",IDC_GENERATING_KEY,82,207,174,8
+ LTEXT "Account:",IDC_STATIC,15,12,42,8
+ LTEXT "key id: ",IDC_KEY_ID,178,12,99,8
+ COMBOBOX IDC_ACCOUNT,66,9,104,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+END
+
+IDD_BIN_PATH DIALOGEX 0, 0, 354, 108
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Set GPG bin path and keyring home dir."
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "Continue",ID_OK,7,87,50,14
+ LTEXT "Home directory:",IDC_STATIC,9,34,325,8
+ LTEXT "GnuPG binary:",IDC_STATIC,10,7,147,8
+ PUSHBUTTON "Browse",IDC_SET_BIN_PATH,293,18,54,14
+ PUSHBUTTON "Browse",IDC_SET_HOME_DIR,293,44,54,14
+ EDITTEXT IDC_HOME_DIR,7,44,277,14,ES_AUTOHSCROLL
+ EDITTEXT IDC_BIN_PATH,7,17,277,14,ES_AUTOHSCROLL
+ PUSHBUTTON "Generate and use random key",IDC_GENERATE_RANDOM,166,87,118,14
+ CONTROL "Turn on key autoexchange",IDC_AUTO_EXCHANGE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,64,277,10
+END
+
+IDD_NEW_KEY DIALOGEX 0, 0, 427, 68
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "The new public key was recieved"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "Import key",ID_IMPORT,9,47,46,14
+ PUSHBUTTON "Accept and enable encryption",IDC_IMPORT_AND_USE,156,47,119,14
+ PUSHBUTTON "Ignore",IDC_IGNORE_KEY,368,47,52,14
+ CTEXT "Ñòàòè÷åñêèé",IDC_MESSAGE,18,25,392,8
+ CTEXT "Ñòàòè÷åñêèé",IDC_KEY_FROM,16,12,395,8
+END
+
+IDD_KEY_GEN DIALOGEX 0, 0, 284, 169
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Key Generation dialog"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,7,148,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,227,148,50,14
+ COMBOBOX IDC_KEY_TYPE,120,14,48,30,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_GROUP | WS_TABSTOP
+ EDITTEXT IDC_KEY_LENGTH,120,30,40,14,ES_AUTOHSCROLL | ES_NUMBER | WS_GROUP
+ EDITTEXT IDC_KEY_PASSWD,120,46,55,14,ES_AUTOHSCROLL | WS_GROUP
+ EDITTEXT IDC_KEY_REAL_NAME,120,61,55,14,ES_AUTOHSCROLL | WS_GROUP
+ EDITTEXT IDC_KEY_EMAIL,120,76,55,14,ES_AUTOHSCROLL | WS_GROUP
+ EDITTEXT IDC_KEY_COMMENT,120,91,55,14,ES_AUTOHSCROLL | WS_GROUP
+ EDITTEXT IDC_KEY_EXPIRE_DATE,120,106,55,14,ES_AUTOHSCROLL | WS_GROUP
+ LTEXT "Key type:",IDC_STATIC,8,16,96,8
+ LTEXT "Key length:",IDC_STATIC,7,32,106,8
+ LTEXT "Key password:",IDC_STATIC,7,49,105,8
+ LTEXT "Real name:",IDC_STATIC,7,63,105,8
+ LTEXT "Email:",IDC_STATIC,7,79,108,8
+ LTEXT "Comment:",IDC_STATIC,7,92,107,8
+ LTEXT "Expire date:",IDC_STATIC,7,109,111,8
+ LTEXT "ex.: 2010-08-15",IDC_STATIC,182,108,75,8
+ LTEXT "From 1024 to 4096",IDC_STATIC,168,33,89,8
+ LTEXT "It can take a long time, be patient",IDC_GENERATING_TEXT,15,132,246,8
+ LTEXT "0 - does not expire",IDC_STATIC,122,122,141,8
+END
+
+IDD_LOAD_EXISTING_KEY DIALOGEX 0, 0, 370, 257
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Select existing public key from list"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "ÎÊ",IDOK,7,236,50,14,WS_DISABLED
+ PUSHBUTTON "Cancel",IDCANCEL,313,236,50,14
+ CONTROL "",IDC_EXISTING_KEY_LIST,"SysListView32",LVS_REPORT | LVS_ALIGNLEFT | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,14,356,217
+END
+
+IDD_KEY_PASSWD DIALOGEX 0, 0, 207, 108
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Enter password for your secret key"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "ÎÊ",IDOK,7,87,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,150,87,50,14
+ EDITTEXT IDC_PASSWORD,13,38,179,14,ES_PASSWORD | ES_AUTOHSCROLL
+ LTEXT "Password:",IDC_STATIC,14,28,34,8
+ CONTROL "Save password to database",IDC_SAVE_PASSWORD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,56,124,10
+ LTEXT "",IDC_KEYID,14,14,179,8
+ CONTROL "Default password",IDC_DEFAULT_PASSWORD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,67,151,10
+END
+
+IDD_IMPORT_KEY DIALOGEX 0, 0, 161, 81
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Set GPG bin path and keyring home dir."
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ PUSHBUTTON "Import",IDC_IMPORT,15,56,50,14
+ LTEXT "Select keyserver for key search:",IDC_STATIC,16,20,122,8
+ COMBOBOX IDC_KEYSERVER,15,34,125,30,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_LOAD_PUBLIC_KEY, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 331
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 183
+ END
+
+ IDD_FIRST_RUN, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 284
+ VERTGUIDE, 15
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 223
+ HORZGUIDE, 20
+ END
+
+ IDD_BIN_PATH, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 347
+ VERTGUIDE, 284
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 101
+ END
+
+ IDD_NEW_KEY, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 420
+ TOPMARGIN, 6
+ BOTTOMMARGIN, 61
+ END
+
+ IDD_KEY_GEN, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 277
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 162
+ END
+
+ IDD_LOAD_EXISTING_KEY, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 363
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 250
+ END
+
+ IDD_KEY_PASSWD, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 200
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 101
+ END
+
+ IDD_IMPORT_KEY, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 154
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 74
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_SECURED ICON "icons\\secured.ico"
+IDI_UNSECURED ICON "icons\\unsecured.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 0,0,0,11
+ PRODUCTVERSION 0,9,0,0
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x0L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "041904b0"
+ BEGIN
+ VALUE "FileDescription", "new_gpg"
+ VALUE "FileVersion", "0.0.0.11"
+ VALUE "InternalName", "new_gpg"
+ VALUE "LegalCopyright", "Copyright (C) 2010-2011 sss"
+ VALUE "OriginalFilename", "new_gpg"
+ VALUE "ProductName", "new_gpg"
+ VALUE "ProductVersion", "0.9.0.0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x419, 1200
+ END
+END
+
+#endif // Ðóññêèé (Ðîññèÿ) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Àíãëèéñêèé (ÑØÀ) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_OPT_GPG DIALOGEX 0, 0, 286, 214
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+FONT 8, "MS Shell Dlg", 400, 0, 0x0
+BEGIN
+ CONTROL "",IDC_USERLIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,17,272,112
+ CTEXT "Userlist:",IDC_STATIC,25,7,201,8
+ PUSHBUTTON "Export PubKey",IDC_SAVE_KEY_BUTTON,8,135,75,14
+ PUSHBUTTON "Delete key",IDC_DELETE_KEY_BUTTON,90,135,70,14
+ PUSHBUTTON "Select own key",IDC_SELECT_KEY,205,193,74,14
+ CONTROL "Turn on debug log",IDC_DEBUG_LOG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,181,159,89,10
+ EDITTEXT IDC_LOG_FILE_EDIT,11,157,98,14,ES_AUTOHSCROLL
+ PUSHBUTTON "Browse",IDC_LOG_FILE_SET,119,156,50,14
+ CONTROL "Use jabber api on Miranda IM >= 0.9 (recomended)",IDC_JABBER_API,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,175,251,10
+ LTEXT "Default key",IDC_CURRENT_KEY,12,196,110,8
+ CONTROL "Encrypt file transfers",IDC_FILE_TRANSFERS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,185,137,10
+ CONTROL "Automatic key exchange",IDC_AUTO_EXCHANGE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,163,137,111,10
+ PUSHBUTTON "Copy own key",IDC_COPY_KEY,127,193,74,14
+END
+
+IDD_OPT_GPG_BIN DIALOGEX 0, 0, 282, 214
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+FONT 8, "MS Shell Dlg", 400, 0, 0x0
+BEGIN
+ PUSHBUTTON "Browse",IDC_SET_BIN_PATH,216,17,60,14
+ PUSHBUTTON "Browse",IDC_SET_HOME_DIR,217,44,57,14
+ EDITTEXT IDC_BIN_PATH,7,17,195,14,ES_AUTOHSCROLL
+ EDITTEXT IDC_HOME_DIR,7,44,195,14,ES_AUTOHSCROLL
+ LTEXT "GnuPG binary:",IDC_STATIC,10,7,147,8
+ LTEXT "Home directory:",IDC_STATIC,9,34,144,8
+END
+
+IDD_OPT_GPG_MESSAGES DIALOGEX 0, 0, 302, 241
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+FONT 8, "MS Shell Dlg", 400, 0, 0x0
+BEGIN
+ CONTROL "Add tags to encoded and decoded messages",IDC_APPEND_TAGS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,3,65,243,10
+ EDITTEXT IDC_IN_OPEN_TAG,39,20,88,14,ES_AUTOHSCROLL
+ EDITTEXT IDC_IN_CLOSE_TAG,151,20,90,14,ES_AUTOHSCROLL
+ LTEXT "Incomming message tags:",IDC_STATIC,15,10,84,8
+ LTEXT "Outgoing message tags:",IDC_STATIC,13,36,79,8
+ RTEXT "Open:",IDC_STATIC,13,23,26,8
+ RTEXT "Close:",IDC_STATIC,127,23,23,8
+ EDITTEXT IDC_OUT_OPEN_TAG,39,46,88,14,ES_AUTOHSCROLL
+ EDITTEXT IDC_OUT_CLOSE_TAG,151,46,90,14,ES_AUTOHSCROLL
+ RTEXT "Open:",IDC_STATIC,13,49,26,8
+ RTEXT "Close:",IDC_STATIC,127,49,23,8
+ CONTROL "Strip all tags in outgoing messages",IDC_STRIP_TAGS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,3,76,233,10
+END
+
+IDD_OPT_GPG_ADVANCED DIALOGEX 0, 0, 286, 214
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+FONT 8, "MS Shell Dlg", 400, 0, 0x0
+BEGIN
+ CONTROL "Turn on presence signing (Jabber)",IDC_PRESCENSE_SUBSCRIPTION,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,9,190,10
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_OPT_GPG, DIALOG
+ BEGIN
+ END
+
+ IDD_OPT_GPG_BIN, DIALOG
+ BEGIN
+ END
+
+ IDD_OPT_GPG_MESSAGES, DIALOG
+ BEGIN
+ END
+
+ IDD_OPT_GPG_ADVANCED, DIALOG
+ BEGIN
+ VERTGUIDE, 12
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // Àíãëèéñêèé (ÑØÀ) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/plugins/New_GPG/src/clist.cpp b/plugins/New_GPG/src/clist.cpp
new file mode 100755
index 0000000000..c64fb17798
--- /dev/null
+++ b/plugins/New_GPG/src/clist.cpp
@@ -0,0 +1,41 @@
+// Copyright © 2010-2012 SecureIM developers (baloo and others), sss
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include "commonheaders.h"
+
+extern HANDLE g_hCLIcon;
+void RefreshContactListIcons(void);
+
+int onExtraImageListRebuilding(WPARAM, LPARAM)
+{
+ if(g_hCLIcon && ServiceExists(MS_CLIST_EXTRA_ADD_ICON) )
+ RefreshContactListIcons();
+ return 0;
+}
+
+
+int onExtraImageApplying(WPARAM wParam, LPARAM)
+{
+ void setClistIcon(HANDLE);
+ if(g_hCLIcon && ServiceExists(MS_CLIST_EXTRA_SET_ICON))
+ {
+// IconExtraColumn iec = {0}; //need to init this
+ if( g_hCLIcon )
+ setClistIcon((HANDLE)wParam);
+// ExtraIcon_SetIcon(g_hCLIcon, (HANDLE)wParam, iec.hImage);
+ }
+ return 0;
+}
diff --git a/plugins/New_GPG/src/commonheaders.h b/plugins/New_GPG/src/commonheaders.h
new file mode 100755
index 0000000000..459d76ef64
--- /dev/null
+++ b/plugins/New_GPG/src/commonheaders.h
@@ -0,0 +1,88 @@
+// Copyright © 2010-2012 sss
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#ifndef COMMONHEADERS_H
+#define COMMONHEADERS_H
+#define MIRANDA_VER 0x0901
+//windows
+#include <windows.h>
+#include <shlobj.h>
+#include <io.h>
+#include <uxtheme.h>
+#include <shlwapi.h>
+#include <richedit.h>
+//c
+#include <locale.h>
+#include <errno.h>
+#include <time.h>
+//c++
+#include <iostream>
+#include <map>
+using std::map;
+#include <list>
+using std::list;
+#include <vector>
+using std::vector;
+#include <string>
+using std::string;
+using std::wstring;
+#include <fstream>
+using std::wfstream;
+using std::fstream;
+
+//boost
+#include <boost/thread/thread.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/nondet_random.hpp>
+#include <boost/random/variate_generator.hpp>
+#include <boost/random/uniform_int.hpp>
+#include <boost/date_time.hpp>
+
+
+//utf8cpp
+#include <utf8.h>
+
+//miranda
+#include <newpluginapi.h>
+#include <m_database.h>
+#include <m_options.h>
+#include <m_langpack.h>
+#include <m_clist.h>
+#include <m_clui.h>
+#include <m_icolib.h>
+#include <m_skin.h>
+#include <m_protomod.h>
+#include <m_protosvc.h>
+#include <m_netlib.h>
+#include <m_jabber.h>
+#include <m_icqplus.h>
+#include <m_message.h>
+#include <m_cluiframes.h>
+#include <m_icolib.h>
+#include "m_extraicons.h"
+#include "m_metacontacts.h"
+#include "resource.h"
+
+
+//internal
+#include "constants.h"
+#include "log.h"
+#include "globals.h"
+#include "utilities.h"
+#include "main.h"
+#include "gpg_wrapper.h"
+#include "jabber_account.h"
+#include "metacontacts.h"
+#endif
diff --git a/plugins/New_GPG/src/constants.h b/plugins/New_GPG/src/constants.h
new file mode 100755
index 0000000000..2982f31489
--- /dev/null
+++ b/plugins/New_GPG/src/constants.h
@@ -0,0 +1,5 @@
+#ifndef CONSTANTS_H
+#define CONSTANTS_H
+#define szGPGModuleName "GPG"
+#define PREF_METANODB 0x2000
+#endif
diff --git a/plugins/New_GPG/src/globals.h b/plugins/New_GPG/src/globals.h
new file mode 100755
index 0000000000..e84ae1e505
--- /dev/null
+++ b/plugins/New_GPG/src/globals.h
@@ -0,0 +1,22 @@
+// Copyright © 2010-2012 sss
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#ifndef GLOBALS_H
+#define GLOBALS_H
+extern bool bAppendTags, bPresenceSigning, bStripTags, gpg_valid, gpg_keyexist, tabsrmm_used;
+extern TCHAR *inopentag, *inclosetag, *outopentag, *outclosetag;
+extern logtofile debuglog;
+#endif
diff --git a/plugins/New_GPG/src/gpg_wrapper.cpp b/plugins/New_GPG/src/gpg_wrapper.cpp
new file mode 100755
index 0000000000..38f86889a4
--- /dev/null
+++ b/plugins/New_GPG/src/gpg_wrapper.cpp
@@ -0,0 +1,163 @@
+// Copyright © 2010-2012 sss
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include "commonheaders.h"
+
+//thx gpg module from Harald Treder, Zakhar V. Bardymov
+
+//boost::mutex gpg_mutex;
+
+
+pxResult pxExecute(wstring *acommandline, char *ainput, string *aoutput, LPDWORD aexitcode, pxResult *result, HANDLE hProcess, PROCESS_INFORMATION *pr)
+{
+// gpg_mutex.lock();
+ if(!gpg_valid)
+ return pxNotConfigured;
+ extern logtofile debuglog;
+ BOOL success;
+ STARTUPINFO sinfo = {0};
+ SECURITY_ATTRIBUTES sattrs = {0};
+ SECURITY_DESCRIPTOR sdesc = {0};
+ PROCESS_INFORMATION pri = {0};
+ HANDLE newstdin, newstdout, readstdout, writestdin;
+ char *inputpos;
+ unsigned long transfered;
+ int size;
+
+ wstring commandline;
+
+ sattrs.nLength=sizeof(SECURITY_ATTRIBUTES);
+ sattrs.bInheritHandle=TRUE;
+ InitializeSecurityDescriptor(&sdesc,SECURITY_DESCRIPTOR_REVISION);
+ SetSecurityDescriptorDacl(&sdesc,TRUE,NULL,FALSE);
+ sattrs.lpSecurityDescriptor=&sdesc;
+
+ success=CreatePipe(&newstdin,&writestdin,&sattrs,0);
+ if (!success)
+ {
+ *result = pxCreatePipeFailed;
+ return pxCreatePipeFailed;
+ }
+
+ success=CreatePipe(&readstdout,&newstdout,&sattrs,0);
+ if (!success)
+ {
+ CloseHandle(newstdin);
+ CloseHandle(writestdin);
+ *result = pxCreatePipeFailed;
+ return pxCreatePipeFailed;
+ }
+
+ GetStartupInfo(&sinfo);
+ sinfo.dwFlags=STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
+ sinfo.wShowWindow=SW_HIDE;
+ sinfo.hStdOutput=newstdout;
+ sinfo.hStdError=newstdout;
+ sinfo.hStdInput=newstdin;
+
+ char *mir_path = new char [MAX_PATH];
+ CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)"\\", (LPARAM)mir_path);
+ SetCurrentDirectoryA(mir_path);
+ delete [] mir_path;
+
+ TCHAR *bin_path = UniGetContactSettingUtf(NULL, szGPGModuleName, "szGpgBinPath", _T(""));
+ {
+ if(_waccess(bin_path, 0) == -1)
+ {
+ if(errno == ENOENT)
+ {
+ mir_free(bin_path);
+ debuglog<<time_str()<<": GPG executable not found\n";
+ *result = pxNotFound;
+ return pxNotFound;
+ }
+ }
+ }
+ TCHAR *home_dir = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T(""));
+ { //form initial command
+ commandline += _T("\"");
+ commandline += bin_path;
+ commandline += _T("\" --homedir \"");
+ commandline += home_dir;
+ commandline += _T("\" ");
+ commandline += _T("--display-charset utf-8 ");
+ commandline += _T("-z 9 ");
+ commandline += *acommandline;
+ mir_free(bin_path);
+ mir_free(home_dir);
+ }
+
+ debuglog<<time_str()<<": gpg in: "<<commandline<<"\n";
+
+ success = CreateProcess(NULL, (TCHAR*)commandline.c_str(), NULL, NULL, TRUE, CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT, (void*)_T("LANGUAGE=en@quot\0LC_ALL=English\0"), NULL, &sinfo, &pri);
+
+ if (!success)
+ {
+ CloseHandle(newstdin);
+ CloseHandle(writestdin);
+ CloseHandle(newstdout);
+ CloseHandle(readstdout);
+ debuglog<<time_str()<<": Failed to create process\n";
+// gpg_mutex.unlock();
+ *result = pxCreateProcessFailed;
+ return pxCreateProcessFailed;
+ }
+
+ hProcess = pri.hProcess;
+
+ inputpos=ainput;
+
+ while (TRUE)
+ {
+ if(!pri.hProcess)
+ break;
+ success=GetExitCodeProcess(pri.hProcess,aexitcode);
+ if (success && *aexitcode!=STILL_ACTIVE)
+ break;
+
+ storeOutput(readstdout,aoutput);
+
+ if (*inputpos!='\0') size=1;
+ else size=0;
+
+ success=WriteFile(writestdin,inputpos,size,&transfered,NULL);
+ inputpos+=transfered;
+ boost::this_thread::sleep(boost::posix_time::milliseconds(200));
+ }
+
+ storeOutput(readstdout,aoutput);
+
+ debuglog<<time_str()<<": gpg out: "<<aoutput->c_str();
+
+ WaitForSingleObject(pri.hProcess,INFINITE);
+
+ CloseHandle(pri.hThread);
+ CloseHandle(pri.hProcess);
+ CloseHandle(newstdin);
+ CloseHandle(newstdout);
+ CloseHandle(readstdout);
+ CloseHandle(writestdin);
+
+ *result = pxSuccess;
+// gpg_mutex.unlock();
+ return pxSuccess;
+}
+
+void pxEexcute_thread(void *param)
+{
+ gpg_execution_params *params = (gpg_execution_params*)param;
+ pxResult result = pxExecute(params->cmd, params->useless, params->out, params->code, params->result, params->hProcess, params->proc);
+}
diff --git a/plugins/New_GPG/src/gpg_wrapper.h b/plugins/New_GPG/src/gpg_wrapper.h
new file mode 100755
index 0000000000..5501297baf
--- /dev/null
+++ b/plugins/New_GPG/src/gpg_wrapper.h
@@ -0,0 +1,50 @@
+// Copyright © 2010-2012 sss
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+#ifndef GPG_WRAPPER_H
+#define GPG_WRAPPER_H
+typedef enum {
+ pxSuccess,
+ pxSuccessExitCodeInvalid,
+ pxCreatePipeFailed,
+ pxDuplicateHandleFailed,
+ pxCloseHandleFailed,
+ pxCreateProcessFailed,
+ pxThreadWaitFailed,
+ pxReadFileFailed,
+ pxBufferOverflow,
+ pxNotFound,
+ pxNotConfigured
+}
+pxResult;
+
+pxResult pxExecute(wstring *acommandline, char *ainput, string *aoutput, LPDWORD aexitcode, pxResult *result);
+
+struct gpg_execution_params
+{
+ wstring *cmd;
+ char *useless;
+ string *out;
+ LPDWORD code;
+ pxResult *result;
+ HANDLE hProcess;
+ PROCESS_INFORMATION *proc;
+};
+
+void pxEexcute_thread(void *param);
+
+#endif \ No newline at end of file
diff --git a/plugins/New_GPG/src/icons.cpp b/plugins/New_GPG/src/icons.cpp
new file mode 100755
index 0000000000..c981eea46c
--- /dev/null
+++ b/plugins/New_GPG/src/icons.cpp
@@ -0,0 +1,152 @@
+// Copyright © 2010-2012 SecureIM developers (baloo and others), sss
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include "commonheaders.h"
+
+HANDLE IconLibDefine(TCHAR* desc, TCHAR* section, char* ident, HICON icon, char* def_file, int def_idx, int size)
+{
+ SKINICONDESC sid = {0};
+ HANDLE hIcon;
+
+ if(!size)
+ size = 16;
+
+ sid.cbSize = sizeof( SKINICONDESC );
+ sid.ptszSection = section;
+ sid.ptszDescription = desc;
+ sid.flags = SIDF_TCHAR;
+
+ sid.pszName = ident;
+ sid.pszDefaultFile = def_file;
+ sid.iDefaultIndex = def_idx;
+ sid.hDefaultIcon = icon;
+ sid.cx = sid.cy = size;
+
+ hIcon = Skin_AddIcon(&sid);
+
+ return hIcon;
+}
+
+
+void InitIconLib()
+{
+ extern HINSTANCE hInst;
+ char lib[MAX_PATH];
+ GetModuleFileNameA(hInst, lib, MAX_PATH);
+ TCHAR *module = mir_a2t(szGPGModuleName);
+
+ IconLibDefine(_T("Secured"), module, "secured", NULL, lib, -IDI_SECURED,0);
+ IconLibDefine(_T("Unsecured"), module, "unsecured", NULL, lib, -IDI_UNSECURED,0);
+ mir_free(module);
+}
+
+
+
+
+
+HICON IconLibGetIcon(const char* ident)
+{
+ return (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)ident);
+}
+
+
+
+void IconLibReleaseIcon(const char* ident)
+{
+ CallService(MS_SKIN2_RELEASEICON, 0, (LPARAM)ident);
+}
+
+
+
+HANDLE IconLibHookIconsChanged(MIRANDAHOOK hook)
+{
+ return HookEvent(ME_SKIN2_ICONSCHANGED, hook);
+}
+
+
+void setClistIcon(HANDLE hContact)
+{
+ bool enabled = isContactSecured(hContact);
+ extern HANDLE g_hCLIcon;
+ HANDLE hMC = hContact;
+ if(metaIsSubcontact(hContact))
+ hMC = metaGetContact(hContact);
+ else if(metaIsProtoMetaContacts(hContact))
+ hMC = metaGetContact(hContact);
+ if(g_hCLIcon && enabled)
+ {
+ HICON icon = IconLibGetIcon("secured");
+ IconExtraColumn iec = {0};
+ iec.cbSize = sizeof(iec);
+ iec.hImage = (HANDLE)CallService(MS_CLIST_EXTRA_ADD_ICON, (WPARAM)icon, (LPARAM)0);
+ ExtraIcon_SetIcon(g_hCLIcon, hContact, iec.hImage);
+ if(hMC)
+ ExtraIcon_SetIcon(g_hCLIcon, hMC, iec.hImage);
+ }
+ else
+ {
+ ExtraIcon_SetIcon(g_hCLIcon, hContact, (HANDLE)0); // is it right ? hmm.., at least working....
+ if(hMC)
+ ExtraIcon_SetIcon(g_hCLIcon, hMC, (HANDLE)0);
+ }
+}
+
+void setSrmmIcon(HANDLE h)
+{
+ HANDLE hContact = metaIsProtoMetaContacts(h)?metaGetMostOnline(h):h;
+ bool enabled = isContactSecured(hContact);
+ HANDLE hMC = hContact;
+ if(metaIsSubcontact(hContact))
+ hMC = metaGetContact(hContact);
+ else if(metaIsProtoMetaContacts(hContact))
+ hMC = metaGetContact(hContact);
+ if(ServiceExists(MS_MSG_MODIFYICON))
+ {
+ StatusIconData sid = {0};
+ sid.cbSize = sizeof(sid);
+ sid.szModule = szGPGModuleName;
+ sid.hIcon = IconLibGetIcon("secured");
+ sid.dwId = 0x00000001;
+ sid.flags = enabled?0:MBF_HIDDEN;
+ CallService(MS_MSG_MODIFYICON, (WPARAM)hContact, (LPARAM)&sid);
+ if( hMC )
+ CallService(MS_MSG_MODIFYICON, (WPARAM)hMC, (LPARAM)&sid);
+ ZeroMemory(&sid, sizeof(sid));
+ sid.cbSize = sizeof(sid);
+ sid.szModule = szGPGModuleName;
+ sid.hIcon = IconLibGetIcon("unsecured");
+ sid.dwId = 0x00000002;
+ sid.flags = enabled?MBF_HIDDEN:0;
+ CallService(MS_MSG_MODIFYICON, (WPARAM)hContact, (LPARAM)&sid);
+ if( hMC )
+ CallService(MS_MSG_MODIFYICON, (WPARAM)hMC, (LPARAM)&sid);
+ }
+}
+
+
+void RefreshContactListIcons()
+{
+ HANDLE hContact;
+ extern HANDLE g_hCLIcon;
+ CallService(MS_CLUI_LISTBEGINREBUILD,0,0);
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while (hContact)
+ {
+ setClistIcon(hContact);
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+ }
+ CallService(MS_CLUI_LISTENDREBUILD,0,0);
+}
diff --git a/plugins/New_GPG/src/init.cpp b/plugins/New_GPG/src/init.cpp
new file mode 100755
index 0000000000..90030b0547
--- /dev/null
+++ b/plugins/New_GPG/src/init.cpp
@@ -0,0 +1,288 @@
+// Copyright © 2010-2012 sss
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include "commonheaders.h"
+
+//global variables
+bool bAppendTags = false, bDebugLog = false, bJabberAPI = false, bPresenceSigning = false, bIsMiranda09 = false, bMetaContacts = false, bFileTransfers = false, bAutoExchange = false, bStripTags = false, tabsrmm_used = false;
+TCHAR *inopentag = NULL, *inclosetag = NULL, *outopentag = NULL, *outclosetag = NULL, *password = NULL;
+
+list <JabberAccount*> Accounts;
+
+HINSTANCE hInst;
+HANDLE hLoadPubKey = NULL, hToggleEncryption = NULL, hOnPreBuildContactMenu = NULL, hSendKey = NULL, g_hCLIcon = NULL, hExportGpgKeys = NULL, hImportGpgKeys = NULL;
+IconExtraColumn g_IEC = {0};
+static int OnModulesLoaded(WPARAM wParam,LPARAM lParam);
+extern char *date();
+RECT key_from_keyserver_rect = {0}, firstrun_rect = {0}, new_key_rect = {0}, key_gen_rect = {0}, load_key_rect = {0}, import_key_rect = {0}, key_password_rect = {0}, load_existing_key_rect = {0};
+XML_API xi = {0};
+int hLangpack = 0;
+logtofile debuglog;
+bool gpg_valid = false, gpg_keyexist = false;
+std::map<HANDLE, contact_data> hcontact_data;
+
+
+#define MIID_GPG { 0x4227c050, 0x8d97, 0x48d2, { 0x91, 0xec, 0x6a, 0x95, 0x2b, 0x3d, 0xab, 0x94 } }
+
+PLUGININFOEX pluginInfo={
+ sizeof(PLUGININFOEX),
+ 0,
+ PLUGIN_MAKE_VERSION(0,0,0,11),
+ "new GPG encryption support plugin, based on code from old gpg plugin and secureim",
+ "sss",
+ "sss123next@list.ru",
+ "© 2010-2012 sss",
+ "http://sss.chaoslab.ru/tracker/mim_plugs/",
+ 1, //unicode
+ MIID_GPG
+};
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
+{
+ hInst=hinstDLL;
+ return TRUE;
+}
+
+
+extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ static char plugname[52];
+ strcpy(plugname, szGPGModuleName" [");
+ strcat(plugname, date());
+ strcat(plugname, " ");
+ strcat(plugname, __TIME__);
+ strcat(plugname, "]");
+ pluginInfo.shortName = plugname;
+ return &pluginInfo;
+}
+
+static const MUUID interfaces[] = {MIID_GPG, MIID_LAST};
+extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+int LoadKey(WPARAM w, LPARAM l);
+int ToggleEncryption(WPARAM w, LPARAM l);
+int SendKey(WPARAM w, LPARAM l);
+int ExportGpGKeys(WPARAM w, LPARAM l);
+int ImportGpGKeys(WPARAM w, LPARAM l);
+
+void init_vars()
+{
+ bAppendTags = DBGetContactSettingByte(NULL, szGPGModuleName, "bAppendTags", 0);
+ bStripTags = DBGetContactSettingByte(NULL, szGPGModuleName, "bStripTags", 0);
+ inopentag = UniGetContactSettingUtf(NULL, szGPGModuleName, "szInOpenTag", _T("<GPGdec>"));
+ inclosetag = UniGetContactSettingUtf(NULL, szGPGModuleName, "szInCloseTag", _T("</GPGdec>"));
+ outopentag = UniGetContactSettingUtf(NULL, szGPGModuleName, "szOutOpenTag", _T("<GPGenc>"));
+ outclosetag = UniGetContactSettingUtf(NULL, szGPGModuleName, "szOutCloseTag", _T("</GPGenc>"));
+ bDebugLog = DBGetContactSettingByte(NULL, szGPGModuleName, "bDebugLog", 0);
+ bAutoExchange = DBGetContactSettingByte(NULL, szGPGModuleName, "bAutoExchange", 0);
+ password = UniGetContactSettingUtf(NULL, szGPGModuleName, "szKeyPassword", _T(""));
+ debuglog.init();
+ bJabberAPI = DBGetContactSettingByte(NULL, szGPGModuleName, "bJabberAPI", bIsMiranda09?1:0);
+ bPresenceSigning = DBGetContactSettingByte(NULL, szGPGModuleName, "bPresenceSigning", 0);
+ bFileTransfers = DBGetContactSettingByte(NULL, szGPGModuleName, "bFileTransfers", 0);
+ firstrun_rect.left = DBGetContactSettingDword(NULL, szGPGModuleName, "FirstrunWindowX", 0);
+ firstrun_rect.top = DBGetContactSettingDword(NULL, szGPGModuleName, "FirstrunWindowY", 0);
+ key_password_rect.left = DBGetContactSettingDword(NULL, szGPGModuleName, "PasswordWindowX", 0);
+ key_password_rect.top = DBGetContactSettingDword(NULL, szGPGModuleName, "PasswordWindowY", 0);
+ key_gen_rect.left = DBGetContactSettingDword(NULL, szGPGModuleName, "KeyGenWindowX", 0);
+ key_gen_rect.top = DBGetContactSettingDword(NULL, szGPGModuleName, "KeyGenWindowY", 0);
+ load_key_rect.left = DBGetContactSettingDword(NULL, szGPGModuleName, "LoadKeyWindowX", 0);
+ load_key_rect.top = DBGetContactSettingDword(NULL, szGPGModuleName, "LoadKeyWindowY", 0);
+ import_key_rect.left = DBGetContactSettingDword(NULL, szGPGModuleName, "ImportKeyWindowX", 0);
+ import_key_rect.top = DBGetContactSettingDword(NULL, szGPGModuleName, "ImportKeyWindowY", 0);
+ new_key_rect.left = DBGetContactSettingDword(NULL, szGPGModuleName, "NewKeyWindowX", 0);
+ new_key_rect.top = DBGetContactSettingDword(NULL, szGPGModuleName, "NewKeyWindowY", 0);
+ load_existing_key_rect.left = DBGetContactSettingDword(NULL, szGPGModuleName, "LoadExistingKeyWindowX", 0);
+ load_existing_key_rect.top = DBGetContactSettingDword(NULL, szGPGModuleName, "LoadExistingKeyWindowY", 0);
+ tabsrmm_used = isTabsrmmUsed();
+}
+
+extern "C" int __declspec(dllexport) Load()
+{
+ HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded);
+ mir_getXI(&xi); //TODO: check if we have access to api
+ mir_getLP(&pluginInfo);
+ init_vars();
+ CreateServiceFunction("/LoadPubKey",(MIRANDASERVICE)LoadKey);
+ CreateServiceFunction("/ToggleEncryption",(MIRANDASERVICE)ToggleEncryption);
+ CreateServiceFunction("/SendKey",(MIRANDASERVICE)SendKey);
+ CreateServiceFunction("/ExportGPGKeys",(MIRANDASERVICE)ExportGpGKeys);
+ CreateServiceFunction("/ImportGPGKeys",(MIRANDASERVICE)ImportGpGKeys);
+ CLISTMENUITEM mi = {0};
+ mi.cbSize=sizeof(mi);
+ mi.position=-0x7FFFFFFF;
+ mi.flags=0;
+ mi.hIcon=LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);
+ mi.pszName="Load GPG public key";
+ mi.pszService="/LoadPubKey";
+ hLoadPubKey = Menu_AddContactMenuItem(&mi);
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize=sizeof(mi);
+ mi.position=-0x7FFFFFFe;
+ mi.flags=0;
+ mi.hIcon=LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);
+ mi.pszName="Toggle GPG encryption";
+ mi.pszService="/ToggleEncryption";
+ hToggleEncryption = Menu_AddContactMenuItem(&mi);
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize=sizeof(mi);
+ mi.position=-0x7FFFFFFe;
+ mi.flags=0;
+ mi.hIcon=LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);
+ mi.pszName="Send public key";
+ mi.pszService="/SendKey";
+ hSendKey = Menu_AddContactMenuItem(&mi);
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize=sizeof(mi);
+ mi.position=-0x7FFFFFFF;
+ mi.flags=0;
+ mi.hIcon=LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);
+ mi.pszName="Export GPG Public keys from all users";
+ mi.pszService="/ExportGPGKeys";
+ hExportGpgKeys = Menu_AddMainMenuItem(&mi);
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize=sizeof(mi);
+ mi.position=-0x7FFFFFFF;
+ mi.flags=0;
+ mi.hIcon=LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);
+ mi.pszName="Import GPG Public keys from all users";
+ mi.pszService="/ImportGPGKeys";
+ hImportGpgKeys = Menu_AddMainMenuItem(&mi);
+
+ return 0;
+}
+
+int AddContact(WPARAM w, LPARAM l)
+{
+ CallService(MS_PROTO_ADDTOCONTACT,w,(LPARAM)szGPGModuleName);
+ return 0;
+}
+
+
+static int OnModulesLoaded(WPARAM wParam,LPARAM lParam)
+{
+
+ int GpgOptInit(WPARAM wParam,LPARAM lParam);
+ int OnPreBuildContactMenu(WPARAM w, LPARAM l);
+ int RecvMsgSvc(WPARAM w, LPARAM l);
+ int SendMsgSvc(WPARAM w, LPARAM l);
+ int HookSendMsg(WPARAM w, LPARAM l);
+// int TestHook(WPARAM w, LPARAM l);
+ int GetJabberInterface(WPARAM w, LPARAM l);
+ int onWindowEvent(WPARAM wParam, LPARAM lParam);
+ int onIconPressed(WPARAM wParam, LPARAM lParam);
+ int onExtraImageListRebuilding(WPARAM, LPARAM);
+ int onExtraImageApplying(WPARAM wParam, LPARAM);
+ int onProtoAck(WPARAM, LPARAM);
+ int onSendFile(WPARAM, LPARAM);
+ void InitIconLib();
+
+ void InitCheck();
+ void FirstRun();
+ bIsMiranda09 = (DWORD)CallService(MS_SYSTEM_GETVERSION, 0, 0) >= 0x00090001?true:false;
+ FirstRun();
+ InitCheck();
+ InitIconLib();
+ if(ServiceExists(MS_MSG_ADDICON))
+ {
+ HICON IconLibGetIcon(const char* ident);
+ StatusIconData sid = {0};
+ sid.cbSize = sizeof(sid);
+ sid.szModule = szGPGModuleName;
+ sid.flags = MBF_HIDDEN;
+ sid.dwId = 0x00000001;
+ sid.hIcon = IconLibGetIcon("secured");
+ sid.szTooltip = Translate("GPG Turn off encryption");
+ CallService(MS_MSG_ADDICON, 0, (LPARAM)&sid);
+ ZeroMemory(&sid, sizeof(sid));
+ sid.cbSize = sizeof(sid);
+ sid.szModule = szGPGModuleName;
+ sid.flags = MBF_HIDDEN;
+ sid.dwId = 0x00000002;
+ sid.hIcon = IconLibGetIcon("unsecured");
+ sid.szTooltip = Translate("GPG Turn on encryption");
+ CallService(MS_MSG_ADDICON, 0, (LPARAM)&sid);
+ }
+
+
+ bMetaContacts = ServiceExists(MS_MC_GETMETACONTACT);
+
+ if(bJabberAPI && bIsMiranda09)
+ GetJabberInterface(0,0);
+
+ HookEvent(ME_OPT_INITIALISE, GpgOptInit);
+ HookEvent(ME_DB_EVENT_FILTER_ADD, HookSendMsg);
+ if(bJabberAPI && bIsMiranda09)
+ HookEvent(ME_PROTO_ACCLISTCHANGED, GetJabberInterface);
+
+ HookEvent(ME_PROTO_ACK, onProtoAck); //filetransfer unimplemented now
+
+ HookEvent(ME_CLIST_PREBUILDCONTACTMENU, OnPreBuildContactMenu);
+
+ HookEvent(ME_MSG_WINDOWEVENT, onWindowEvent);
+ HookEvent(ME_MSG_ICONPRESSED, onIconPressed);
+
+ if(ServiceExists(MS_EXTRAICON_REGISTER))
+ g_hCLIcon = ExtraIcon_Register(szGPGModuleName, Translate("GPG encryption status"), "secured", (MIRANDAHOOK)onExtraImageListRebuilding, (MIRANDAHOOK)onExtraImageApplying);
+
+
+
+ PROTOCOLDESCRIPTOR pd = {0};
+ pd.cbSize=sizeof(PROTOCOLDESCRIPTOR);
+ pd.szName=szGPGModuleName;
+ pd.type=PROTOTYPE_ENCRYPTION;
+ CallService(MS_PROTO_REGISTERMODULE,0,(LPARAM)&pd);
+
+ CreateProtoServiceFunction(szGPGModuleName, PSR_MESSAGE, (MIRANDASERVICE)RecvMsgSvc);
+ CreateProtoServiceFunction(szGPGModuleName, PSS_MESSAGE, (MIRANDASERVICE)SendMsgSvc);
+ CreateProtoServiceFunction(szGPGModuleName, PSR_MESSAGE"W", (MIRANDASERVICE)RecvMsgSvc);
+ CreateProtoServiceFunction(szGPGModuleName, PSS_MESSAGE"W", (MIRANDASERVICE)SendMsgSvc);
+
+ CreateProtoServiceFunction(szGPGModuleName, PSS_FILE, (MIRANDASERVICE)onSendFile);
+ CreateProtoServiceFunction(szGPGModuleName, PSS_FILE"W", (MIRANDASERVICE)onSendFile);
+
+ for (HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); hContact; hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0))
+ if (!CallService(MS_PROTO_ISPROTOONCONTACT, (WPARAM)hContact, (LPARAM)szGPGModuleName))
+ CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)szGPGModuleName);
+
+ HookEvent(ME_DB_CONTACT_ADDED,AddContact);
+
+
+ return 0;
+}
+
+extern list<wstring> transfers;
+extern "C" int __declspec(dllexport) Unload(void)
+{
+// for (HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); hContact; hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0))
+// DBDeleteContactSetting(hContact, szGPGModuleName, "KeyID_Prescense");
+ if(!transfers.empty())
+ {
+ for(list<wstring>::iterator p = transfers.begin(); p != transfers.end(); p++)
+ if(!(*p).empty())
+ DeleteFile((*p).c_str());
+ }
+ mir_free(inopentag);
+ mir_free(inclosetag);
+ mir_free(outopentag);
+ mir_free(outclosetag);
+ if(password)
+ mir_free(password);
+ return 0;
+}
diff --git a/plugins/New_GPG/src/jabber_account.cpp b/plugins/New_GPG/src/jabber_account.cpp
new file mode 100755
index 0000000000..6a264a490d
--- /dev/null
+++ b/plugins/New_GPG/src/jabber_account.cpp
@@ -0,0 +1,85 @@
+// Copyright © 2010-2012 sss
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include "commonheaders.h"
+
+void JabberAccount::setAccountName(TCHAR *Name)
+{
+ AccountName = Name;
+}
+void JabberAccount::setAccountNumber(int Number)
+{
+ AccountNumber = Number;
+}
+void JabberAccount::setJabberInterface(IJabberInterface *JIf)
+{
+ JabberInterface = JIf;
+}
+void JabberAccount::setSendHandler(HJHANDLER hHandler)
+{
+ hSendHandler = hHandler;
+}
+void JabberAccount::setPrescenseHandler(HJHANDLER hHandler)
+{
+ hPrescenseHandler = hHandler;
+}
+void JabberAccount::setMessageHandler(HJHANDLER hHandler)
+{
+ hMessageHandler = hHandler;
+}
+
+
+TCHAR *JabberAccount::getAccountName()
+{
+ return AccountName;
+}
+int JabberAccount::getAccountNumber()
+{
+ return AccountNumber;
+}
+IJabberInterface *JabberAccount::getJabberInterface()
+{
+ return JabberInterface;
+}
+HJHANDLER JabberAccount::getSendHandler()
+{
+ return hSendHandler;
+}
+HJHANDLER JabberAccount::getPrescenseHandler()
+{
+ return hPrescenseHandler;
+}
+
+HJHANDLER JabberAccount::getMessageHandler()
+{
+ return hMessageHandler;
+}
+
+
+JabberAccount::JabberAccount()
+{
+ AccountName = NULL;
+ hSendHandler = INVALID_HANDLE_VALUE;
+ hPrescenseHandler = INVALID_HANDLE_VALUE;
+ hMessageHandler = INVALID_HANDLE_VALUE;
+ AccountNumber = -1;
+ JabberInterface = NULL;
+}
+JabberAccount::~JabberAccount()
+{
+ if(AccountName)
+ mir_free(AccountName);
+} \ No newline at end of file
diff --git a/plugins/New_GPG/src/jabber_account.h b/plugins/New_GPG/src/jabber_account.h
new file mode 100755
index 0000000000..b643ed1636
--- /dev/null
+++ b/plugins/New_GPG/src/jabber_account.h
@@ -0,0 +1,43 @@
+// Copyright © 2010-2012 sss
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#ifndef JABBER_ACCOUNT_H
+#define JABBER_ACCOUNT_H
+class JabberAccount
+{
+public:
+ void setAccountName(TCHAR *Name);
+ void setAccountNumber(int Number);
+ void setJabberInterface(IJabberInterface *JIf);
+ void setSendHandler(HJHANDLER hHandler);
+ void setPrescenseHandler(HJHANDLER hHandler);
+ void setMessageHandler(HJHANDLER hHandler);
+
+ TCHAR *getAccountName();
+ int getAccountNumber();
+ IJabberInterface *getJabberInterface();
+ HJHANDLER getSendHandler();
+ HJHANDLER getPrescenseHandler();
+ HJHANDLER getMessageHandler();
+ ~JabberAccount();
+ JabberAccount();
+private:
+ TCHAR *AccountName;
+ int AccountNumber;
+ IJabberInterface *JabberInterface;
+ HJHANDLER hSendHandler, hPrescenseHandler, hMessageHandler;
+};
+
+#endif \ No newline at end of file
diff --git a/plugins/New_GPG/src/log.cpp b/plugins/New_GPG/src/log.cpp
new file mode 100755
index 0000000000..7618914f66
--- /dev/null
+++ b/plugins/New_GPG/src/log.cpp
@@ -0,0 +1,91 @@
+// Copyright © 2010-2012 sss
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include "commonheaders.h"
+
+
+logtofile& logtofile::operator<<(TCHAR *buf)
+{
+ extern bool bDebugLog;
+ if(bDebugLog)
+ {
+ log_mutex.lock();
+ log.open(toUTF8(path).c_str(), std::ios::app |std::ios::ate);
+ log<<toUTF8(buf);
+ log.close();
+ log_mutex.unlock();
+ }
+ return *this;
+}
+logtofile& logtofile::operator<<(char *buf)
+{
+ extern bool bDebugLog;
+ if(bDebugLog)
+ {
+ log_mutex.lock();
+ log.open(toUTF8(path).c_str(), std::ios::app |std::ios::ate);
+ log<<buf;
+ log.close();
+ log_mutex.unlock();
+ }
+ return *this;
+}
+logtofile& logtofile::operator<<(string buf)
+{
+ extern bool bDebugLog;
+ if(bDebugLog)
+ {
+ log_mutex.lock();
+ char *tmp = mir_utf8encode(buf.c_str());
+ log.open(toUTF8(path).c_str(), std::ios::app |std::ios::ate);
+ log<<tmp;
+ log.close();
+ log_mutex.unlock();
+ mir_free(tmp);
+ }
+ return *this;
+}
+logtofile& logtofile::operator<<(wstring buf)
+{
+ extern bool bDebugLog;
+ if(bDebugLog)
+ {
+ log_mutex.lock();
+ log.open(toUTF8(path).c_str(), std::ios::app |std::ios::ate);
+ log<<toUTF8(buf);
+ log.close();
+ log_mutex.unlock();
+ }
+ return *this;
+}
+void logtofile::init()
+{
+ extern bool bDebugLog;
+ if(bDebugLog)
+ {
+ if(path)
+ mir_free(path);
+ path = UniGetContactSettingUtf(NULL, szGPGModuleName, "szLogFilePath", _T("C:\\GPGdebug.log"));
+ }
+}
+logtofile::logtofile()
+{
+ path = NULL;
+}
+logtofile::~logtofile()
+{
+ mir_free(path);
+}
diff --git a/plugins/New_GPG/src/log.h b/plugins/New_GPG/src/log.h
new file mode 100755
index 0000000000..ed1950947c
--- /dev/null
+++ b/plugins/New_GPG/src/log.h
@@ -0,0 +1,35 @@
+// Copyright © 2010-2012 sss
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#ifndef LOG_H
+#define LOG_H
+
+class logtofile
+{
+public:
+ logtofile& operator<<(TCHAR *buf);
+ logtofile& operator<<(char *buf);
+ logtofile& operator<<(string buf);
+ logtofile& operator<<(wstring buf);
+ void init();
+ ~logtofile();
+ logtofile();
+private:
+ fstream log;
+ TCHAR *path;
+ boost::mutex log_mutex;
+};
+
+#endif
diff --git a/plugins/New_GPG/src/m_extraicons.h b/plugins/New_GPG/src/m_extraicons.h
new file mode 100755
index 0000000000..589d040cef
--- /dev/null
+++ b/plugins/New_GPG/src/m_extraicons.h
@@ -0,0 +1,158 @@
+/*
+ Copyright (C) 2009 Ricardo Pescuma Domenecci
+
+ This is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this file; see the file license.txt. If
+ not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __M_EXTRAICONS_H__
+#define __M_EXTRAICONS_H__
+
+#define MIID_EXTRAICONSSERVICE { 0x62d80749, 0xf169, 0x4592, { 0xb4, 0x4d, 0x3d, 0xd6, 0xde, 0x9d, 0x50, 0xc5 } }
+
+
+#define EXTRAICON_TYPE_CALLBACK 0 // Similar to old clist callbacks, it fires 2 notifications
+#define EXTRAICON_TYPE_ICOLIB 1 // This extra icon will use only icons registered with icolib. No callbacks
+ // needed. Just call MS_EXTRAICON_SET_ICON passing the name of the extraicon to set one.
+
+
+typedef struct {
+ int cbSize;
+ int type; // One of EXTRAICON_TYPE_*
+ const char *name; // Internal name. More than one plugin can register extra icons with the same name
+ // if both have the same type. In this case, both will be handled as one.
+ // This is usefull for ex for extra status, where icq and jabber can share the same slot.
+ // If the types are different the second one will be denied.
+ const char *description; // [Translated by plugin] Description to be used in GUI
+ const char *descIcon; // [Optional] Name of an icon registered with icolib to be used in GUI.
+
+ // If type == EXTRAICON_TYPE_CALLBACK this two must be set
+
+ // Callback to add icons to clist, calling MS_CLIST_EXTRA_ADD_ICON
+ // wParam=lParam=0
+ MIRANDAHOOK RebuildIcons;
+
+ // Callback to set the icon to clist, calling MS_CLIST_EXTRA_SET_ICON or MS_EXTRAICON_SET_ICON
+ // wParam = HANDLE hContact
+ // lParam = int slot
+ MIRANDAHOOK ApplyIcon;
+
+ // Other optional callbacks
+
+ // [Optional] Callback called when extra icon was clicked
+ // wParam = HANDLE hContact
+ // lParam = int slot
+ // param = onClickParam
+ MIRANDAHOOKPARAM OnClick;
+
+ LPARAM onClickParam;
+
+} EXTRAICON_INFO;
+
+
+// Register an extra icon
+// wParam = (EXTRAICON_INFO *) Extra icon info
+// lParam = 0
+// Return: (HANDLE) id of extra icon on success, 0 on error
+#define MS_EXTRAICON_REGISTER "ExtraIcon/Register"
+
+
+typedef struct {
+ int cbSize;
+ HANDLE hExtraIcon; // Value returned by MS_EXTRAICON_REGISTER
+ HANDLE hContact; // Contact to set the extra icon
+ union { // The icon to be set. This depends on the type of the extra icon:
+ HANDLE hImage; // Value returned by MS_CLIST_EXTRA_ADD_ICON (if EXTRAICON_TYPE_CALLBACK)
+ const char *icoName; // Name of the icon registered with icolib (if EXTRAICON_TYPE_ICOLIB)
+ };
+} EXTRAICON;
+
+// Set an extra icon icon
+// wParam = (EXTRAICON *) Extra icon
+// Return: 0 on success
+#define MS_EXTRAICON_SET_ICON "ExtraIcon/SetIcon"
+
+
+
+#ifndef _NO_WRAPPERS
+#ifdef __cplusplus
+
+static HANDLE ExtraIcon_Register(const char *name, const char *description, const char *descIcon,
+ MIRANDAHOOK RebuildIcons,
+ MIRANDAHOOK ApplyIcon,
+ MIRANDAHOOKPARAM OnClick = NULL, LPARAM onClickParam = NULL)
+{
+ if (!ServiceExists(MS_EXTRAICON_REGISTER))
+ return NULL;
+
+ EXTRAICON_INFO ei = {0};
+ ei.cbSize = sizeof(ei);
+ ei.type = EXTRAICON_TYPE_CALLBACK;
+ ei.name = name;
+ ei.description = description;
+ ei.descIcon = descIcon;
+ ei.RebuildIcons = RebuildIcons;
+ ei.ApplyIcon = ApplyIcon;
+ ei.OnClick = OnClick;
+ ei.onClickParam = onClickParam;
+
+ return (HANDLE) CallService(MS_EXTRAICON_REGISTER, (WPARAM) &ei, 0);
+}
+
+static HANDLE ExtraIcon_Register(const char *name, const char *description, const char *descIcon = NULL,
+ MIRANDAHOOKPARAM OnClick = NULL, LPARAM onClickParam = NULL)
+{
+ if (!ServiceExists(MS_EXTRAICON_REGISTER))
+ return NULL;
+
+ EXTRAICON_INFO ei = {0};
+ ei.cbSize = sizeof(ei);
+ ei.type = EXTRAICON_TYPE_ICOLIB;
+ ei.name = name;
+ ei.description = description;
+ ei.descIcon = descIcon;
+ ei.OnClick = OnClick;
+ ei.onClickParam = onClickParam;
+
+ return (HANDLE) CallService(MS_EXTRAICON_REGISTER, (WPARAM) &ei, 0);
+}
+
+static int ExtraIcon_SetIcon(HANDLE hExtraIcon, HANDLE hContact, HANDLE hImage)
+{
+ EXTRAICON ei = {0};
+ ei.cbSize = sizeof(ei);
+ ei.hExtraIcon = hExtraIcon;
+ ei.hContact = hContact;
+ ei.hImage = hImage;
+
+ return CallService(MS_EXTRAICON_SET_ICON, (WPARAM) &ei, 0);
+}
+
+static int ExtraIcon_SetIcon(HANDLE hExtraIcon, HANDLE hContact, const char *icoName)
+{
+ EXTRAICON ei = {0};
+ ei.cbSize = sizeof(ei);
+ ei.hExtraIcon = hExtraIcon;
+ ei.hContact = hContact;
+ ei.icoName = icoName;
+
+ return CallService(MS_EXTRAICON_SET_ICON, (WPARAM) &ei, 0);
+}
+
+#endif
+#endif
+
+
+#endif // __M_EXTRAICONS_H__
diff --git a/plugins/New_GPG/src/m_metacontacts.h b/plugins/New_GPG/src/m_metacontacts.h
new file mode 100755
index 0000000000..9f348bd2c6
--- /dev/null
+++ b/plugins/New_GPG/src/m_metacontacts.h
@@ -0,0 +1,166 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright © 2004 Universite Louis PASTEUR, STRASBOURG.
+Copyright © 2004 Scott Ellis (www.scottellis.com.au mail@scottellis.com.au)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef M_METACONTACTS_H__
+#define M_METACONTACTS_H__ 1
+
+#ifndef MIID_METACONTACTS
+#define MIID_METACONTACTS {0xc0325019, 0xc1a7, 0x40f5, { 0x83, 0x65, 0x4f, 0x46, 0xbe, 0x21, 0x86, 0x3e}}
+#endif
+
+//get the handle for a contact's parent metacontact
+//wParam=(HANDLE)hSubContact
+//lParam=0
+//returns a handle to the parent metacontact, or null if this contact is not a subcontact
+#define MS_MC_GETMETACONTACT "MetaContacts/GetMeta"
+
+//gets the handle for the default contact
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns a handle to the default contact, or null on failure
+#define MS_MC_GETDEFAULTCONTACT "MetaContacts/GetDefault"
+
+//gets the contact number for the default contact
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns a DWORD contact number, or -1 on failure
+#define MS_MC_GETDEFAULTCONTACTNUM "MetaContacts/GetDefaultNum"
+
+//gets the handle for the 'most online' contact
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns a handle to the 'most online' contact
+#define MS_MC_GETMOSTONLINECONTACT "MetaContacts/GetMostOnline"
+
+//gets the number of subcontacts for a metacontact
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns a DWORD representing the number of subcontacts for the given metacontact
+#define MS_MC_GETNUMCONTACTS "MetaContacts/GetNumContacts"
+
+//gets the handle of a subcontact, using the subcontact's number
+//wParam=(HANDLE)hMetaContact
+//lParam=(DWORD)contact number
+//returns a handle to the specified subcontact
+#define MS_MC_GETSUBCONTACT "MetaContacts/GetSubContact"
+
+//sets the default contact, using the subcontact's contact number
+//wParam=(HANDLE)hMetaContact
+//lParam=(DWORD)contact number
+//returns 0 on success
+#define MS_MC_SETDEFAULTCONTACTNUM "MetaContacts/SetDefault"
+
+//sets the default contact, using the subcontact's handle
+//wParam=(HANDLE)hMetaContact
+//lParam=(HANDLE)hSubcontact
+//returns 0 on success
+#define MS_MC_SETDEFAULTCONTACT "MetaContacts/SetDefaultByHandle"
+
+//forces the metacontact to send using a specific subcontact, using the subcontact's contact number
+//wParam=(HANDLE)hMetaContact
+//lParam=(DWORD)contact number
+//returns 0 on success
+#define MS_MC_FORCESENDCONTACTNUM "MetaContacts/ForceSendContact"
+
+//forces the metacontact to send using a specific subcontact, using the subcontact's handle
+//wParam=(HANDLE)hMetaContact
+//lParam=(HANDLE)hSubcontact
+//returns 0 on success (will fail if 'force default' is in effect)
+#define MS_MC_FORCESENDCONTACT "MetaContacts/ForceSendContactByHandle"
+
+//'unforces' the metacontact to send using a specific subcontact
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns 0 on success (will fail if 'force default' is in effect)
+#define MS_MC_UNFORCESENDCONTACT "MetaContacts/UnforceSendContact"
+
+//'forces' or 'unforces' (i.e. toggles) the metacontact to send using it's default contact
+// overrides (and clears) 'force send' above, and will even force use of offline contacts
+// will send ME_MC_FORCESEND or ME_MC_UNFORCESEND event
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns 1(true) or 0(false) representing new state of 'force default'
+#define MS_MC_FORCEDEFAULT "MetaContacts/ForceSendDefault"
+
+// method to get state of 'force' for a metacontact
+// wParam=(HANDLE)hMetaContact
+// lParam= (DWORD)&contact_number or NULL
+//
+// if lparam supplied, the contact_number of the contatct 'in force' will be copied to the address it points to,
+// or if none is in force, the value (DWORD)-1 will be copied
+// (v0.8.0.8+ returns 1 if 'force default' is true with *lParam == default contact number, else returns 0 with *lParam as above)
+#define MS_MC_GETFORCESTATE "MetaContacts/GetForceState"
+
+// fired when a metacontact's default contact changes (fired upon creation of metacontact also, when default is initially set)
+// wParam=(HANDLE)hMetaContact
+// lParam=(HANDLE)hDefaultContact
+#define ME_MC_DEFAULTTCHANGED "MetaContacts/DefaultChanged"
+
+// fired when a metacontact's subcontacts change (fired upon creation of metacontact, when contacts are added or removed, and when
+// contacts are reordered) - a signal to re-read metacontact data
+// wParam=(HANDLE)hMetaContact
+// lParam=0
+#define ME_MC_SUBCONTACTSCHANGED "MetaContacts/SubcontactsChanged"
+
+// fired when a metacontact is forced to send using a specific subcontact
+// wParam=(HANDLE)hMetaContact
+// lParam=(HANDLE)hForceContact
+#define ME_MC_FORCESEND "MetaContacts/ForceSend"
+
+// fired when a metacontact is 'unforced' to send using a specific subcontact
+// wParam=(HANDLE)hMetaContact
+// lParam=0
+#define ME_MC_UNFORCESEND "MetaContacts/UnforceSend"
+
+// method to get protocol name - used to be sure you're dealing with a "real" metacontacts plugin :)
+// wParam=lParam=0
+#define MS_MC_GETPROTOCOLNAME "MetaContacts/GetProtoName"
+
+
+// added 0.9.5.0 (22/3/05)
+// wParam=(HANDLE)hContact
+// lParam=0
+// convert a given contact into a metacontact
+#define MS_MC_CONVERTTOMETA "MetaContacts/ConvertToMetacontact"
+
+// added 0.9.5.0 (22/3/05)
+// wParam=(HANDLE)hContact
+// lParam=(HANDLE)hMeta
+// add an existing contact to a metacontact
+#define MS_MC_ADDTOMETA "MetaContacts/AddToMetacontact"
+
+// added 0.9.5.0 (22/3/05)
+// wParam=0
+// lParam=(HANDLE)hContact
+// remove a contact from a metacontact
+#define MS_MC_REMOVEFROMMETA "MetaContacts/RemoveFromMetacontact"
+
+
+// added 0.9.13.2 (6/10/05)
+// wParam=(BOOL)disable
+// lParam=0
+// enable/disable the 'hidden group hack' - for clists that support subcontact hiding using 'IsSubcontact' setting
+// should be called once in the clist 'onmodulesloaded' event handler (which, since it's loaded after the db, will be called
+// before the metacontact onmodulesloaded handler where the subcontact hiding is usually done)
+#define MS_MC_DISABLEHIDDENGROUP "MetaContacts/DisableHiddenGroup"
+
+#endif
diff --git a/plugins/New_GPG/src/main.cpp b/plugins/New_GPG/src/main.cpp
new file mode 100755
index 0000000000..0c212d4e07
--- /dev/null
+++ b/plugins/New_GPG/src/main.cpp
@@ -0,0 +1,2305 @@
+// Copyright © 2010-2012 sss
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+
+
+#include "commonheaders.h"
+
+
+HWND hwndFirstRun = NULL, hwndSetDirs = NULL, hwndNewKey = NULL, hwndKeyGen = NULL, hwndSelectExistingKey = NULL;
+
+int itemnum = 0;
+
+HWND hwndList_g = NULL;
+BOOL CheckStateStoreDB(HWND hwndDlg, int idCtrl, const char* szSetting);
+
+static BOOL CALLBACK DlgProcFirstRun(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ HWND hwndList=GetDlgItem(hwndDlg, IDC_KEY_LIST);
+ hwndList_g = hwndList;
+ LVCOLUMN col = {0};
+ LVITEM item = {0};
+ NMLISTVIEW * hdr = (NMLISTVIEW *) lParam;
+ TCHAR fp[16] = {0};
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ SetWindowPos(hwndDlg, 0, firstrun_rect.left, firstrun_rect.top, 0, 0, SWP_NOSIZE|SWP_SHOWWINDOW);
+ TranslateDialogDefault(hwndDlg);
+ SetWindowText(hwndDlg, TranslateW(_T("Set own key")));
+ col.pszText = _T("Key ID");
+ col.mask = LVCF_TEXT | LVCF_WIDTH;
+ col.fmt = LVCFMT_LEFT;
+ col.cx = 50;
+ ListView_InsertColumn(hwndList, 0, &col);
+ ZeroMemory(&col,sizeof(col));
+ col.pszText = TranslateW(_T("Email"));
+ col.mask = LVCF_TEXT | LVCF_WIDTH;
+ col.fmt = LVCFMT_LEFT;
+ col.cx = 30;
+ ListView_InsertColumn(hwndList, 1, &col);
+ ZeroMemory(&col,sizeof(col));
+ col.pszText = TranslateW(_T("Name"));
+ col.mask = LVCF_TEXT | LVCF_WIDTH;
+ col.fmt = LVCFMT_LEFT;
+ col.cx = 250;
+ ListView_InsertColumn(hwndList, 2, &col);
+ ZeroMemory(&col,sizeof(col));
+ col.pszText = TranslateW(_T("Creation date"));
+ col.mask = LVCF_TEXT | LVCF_WIDTH;
+ col.fmt = LVCFMT_LEFT;
+ col.cx = 30;
+ ListView_InsertColumn(hwndList, 3, &col);
+ ZeroMemory(&col,sizeof(col));
+ col.pszText = TranslateW(_T("Key length"));
+ col.mask = LVCF_TEXT | LVCF_WIDTH;
+ col.fmt = LVCFMT_LEFT;
+ col.cx = 30;
+ ListView_InsertColumn(hwndList, 4, &col);
+ ListView_SetExtendedListViewStyleEx(hwndList, 0, LVS_EX_FULLROWSELECT);
+ int i = 1, iRow = 0;
+ {
+ item.mask = LVIF_TEXT;
+ item.iItem = i;
+ item.iSubItem = 0;
+ item.pszText = _T("");
+ {//parse gpg output
+ string out;
+ DWORD code;
+ pxResult result;
+ wstring::size_type p = 0, p2 = 0, stop = 0;
+ {
+ gpg_execution_params params;
+ wstring cmd = _T("--batch --list-secret-keys");
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::seconds(10)))
+ {
+ gpg_thread.~thread();
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ break;
+ }
+ if(result == pxNotFound)
+ break;
+ }
+ while(p != string::npos)
+ {
+ if((p = out.find("sec ", p)) == string::npos)
+ break;
+ p += 5;
+ if(p < stop)
+ break;
+ stop = p;
+ p2 = out.find("/", p) - 1;
+ TCHAR *tmp = mir_wstrdup(toUTF16(out.substr(p,p2-p)).c_str());
+ item.pszText = tmp;
+ iRow = ListView_InsertItem(hwndList, &item);
+ ListView_SetItemText(hwndList, iRow, 4, tmp);
+ mir_free(tmp);
+ p2+=2;
+ p = out.find(" ", p2);
+ tmp = mir_wstrdup(toUTF16(out.substr(p2,p-p2)).c_str());
+ ListView_SetItemText(hwndList, iRow, 0, tmp);
+ mir_free(tmp);
+ p = out.find("uid ", p);
+ p2 = out.find_first_not_of(" ", p+5);
+ p = out.find("<", p2);
+ tmp = mir_wstrdup(toUTF16(out.substr(p2,p-p2)).c_str());
+ ListView_SetItemText(hwndList, iRow, 2, tmp);
+ mir_free(tmp);
+ p++;
+ p2 = out.find(">", p);
+ tmp = mir_wstrdup(toUTF16(out.substr(p,p2-p)).c_str());
+ ListView_SetItemText(hwndList, iRow, 1, tmp);
+ mir_free(tmp);
+ p = out.find("ssb ", p2) + 6;
+ p = out.find(" ", p) + 1;
+ p2 = out.find("\n", p);
+ tmp = mir_wstrdup(toUTF16(out.substr(p,p2-p-1)).c_str());
+ ListView_SetItemText(hwndList, iRow, 3, tmp);
+ mir_free(tmp);
+ ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE);// not sure about this
+ ListView_SetColumnWidth(hwndList, 1, LVSCW_AUTOSIZE);
+ ListView_SetColumnWidth(hwndList, 2, LVSCW_AUTOSIZE);
+ ListView_SetColumnWidth(hwndList, 3, LVSCW_AUTOSIZE);
+ ListView_SetColumnWidth(hwndList, 4, LVSCW_AUTOSIZE);
+ i++;
+ }
+ }
+ }
+ {
+ SendMessageA(GetDlgItem(hwndDlg, IDC_ACCOUNT), CB_ADDSTRING, 0, (LPARAM)Translate("Default"));
+ int count = 0;
+ PROTOACCOUNT **accounts;
+ ProtoEnumAccounts(&count, &accounts);
+ for(int i = 0; i < count; i++)
+ {
+ if(StriStr(accounts[i]->szModuleName, "metacontacts"))
+ continue;
+ if(StriStr(accounts[i]->szModuleName, "weather"))
+ continue;
+ SendMessageA(GetDlgItem(hwndDlg, IDC_ACCOUNT), CB_ADDSTRING, 0, (LPARAM)accounts[i]->szModuleName);
+ }
+ SendMessageA(GetDlgItem(hwndDlg, IDC_ACCOUNT), CB_SELECTSTRING, 0, (LPARAM)Translate("Default"));
+ string keyinfo = Translate("key id");
+ keyinfo += ": ";
+ char *keyid = UniGetContactSettingUtf(NULL, szGPGModuleName, "KeyID", "");
+ keyinfo += (strlen(keyid) > 0)?keyid:Translate("not set");
+ mir_free(keyid);
+ SetDlgItemTextA(hwndDlg, IDC_KEY_ID, keyinfo.c_str());
+ }
+ return TRUE;
+ }
+
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_GENERATE_KEY:
+ void ShowKeyGenDialog();
+ ShowKeyGenDialog();
+ break;
+ case ID_OK:
+ {
+ ListView_GetItemText(hwndList, itemnum, 0, fp, 16);
+ TCHAR *name = new TCHAR [64];
+ ListView_GetItemText(hwndList, itemnum, 2, name, 64);
+ {
+ if(_tcschr(name, _T('(')))
+ {
+ wstring str = name;
+ wstring::size_type p = str.find(_T("("))-1;
+ _tcscpy(name, str.substr(0, p).c_str());
+ }
+ }
+ string out;
+ DWORD code;
+ wstring cmd = _T("--batch -a --export ");
+ cmd += fp;
+// cmd += _T("\"");
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::seconds(10)))
+ {
+ gpg_thread.~thread();
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ break;
+ }
+ if(result == pxNotFound)
+ break;
+ string::size_type s = 0;
+ while((s = out.find("\r", s)) != string::npos)
+ {
+ out.erase(s, 1);
+ }
+ {
+ char buf[64];
+ GetDlgItemTextA(hwndDlg, IDC_ACCOUNT, buf, 63);
+ if(!strcmp(buf, Translate("Default")))
+ {
+ DBWriteContactSettingString(NULL, szGPGModuleName, "GPGPubKey", out.c_str());
+ DBWriteContactSettingTString(NULL, szGPGModuleName, "KeyMainName", name);
+ DBWriteContactSettingTString(NULL, szGPGModuleName, "KeyID", fp);
+ }
+ else
+ {
+ char setting[64];
+ strcpy(setting, buf);
+ strcat(setting, "_GPGPubKey");
+ DBWriteContactSettingString(NULL, szGPGModuleName, setting, out.c_str());
+ strcpy(setting, buf);
+ strcat(setting, "_KeyMainName");
+ DBWriteContactSettingTString(NULL, szGPGModuleName, setting, name);
+ strcpy(setting, buf);
+ strcat(setting, "_KeyID");
+ DBWriteContactSettingTString(NULL, szGPGModuleName, setting, fp);
+ }
+ }
+ TCHAR passwd[64];
+ GetDlgItemText(hwndDlg, IDC_KEY_PASSWORD, passwd, 64);
+ if(passwd[0])
+ {
+ string dbsetting = "szKey_";
+ char *keyid = mir_t2a(fp);
+ dbsetting += keyid;
+ mir_free(keyid);
+ dbsetting += "_Password";
+ DBWriteContactSettingTString(NULL, szGPGModuleName, dbsetting.c_str(), passwd);
+ }
+ {
+ wstring keyinfo = TranslateT("Default private key id");
+ keyinfo += _T(": ");
+ keyinfo += (fp[0])?fp:_T("not set");
+ extern HWND hwndCurKey_p;
+ SetWindowText(hwndCurKey_p, keyinfo.c_str());
+ }
+ delete [] name;
+ }
+ bAutoExchange = CheckStateStoreDB(hwndDlg, IDC_AUTO_EXCHANGE, "bAutoExchange");
+ gpg_valid = isGPGValid();
+ gpg_keyexist = isGPGKeyExist();
+ DestroyWindow(hwndDlg);
+ break;
+ case IDC_OTHER:
+ {
+ void ShowLoadPublicKeyDialog();
+ extern map<int, HANDLE> user_data;
+ extern int item_num;
+ item_num = 0; //black magic here
+ user_data[1] = 0;
+ ShowLoadPublicKeyDialog();
+ ListView_DeleteAllItems(hwndList);
+ {
+ int i = 1, iRow = 0;
+ item.mask = LVIF_TEXT;
+ item.iItem = i;
+ item.iSubItem = 0;
+ item.pszText = _T("");
+ {//parse gpg output
+ string out;
+ DWORD code;
+ wstring::size_type p = 0, p2 = 0, stop = 0;
+ {
+ wstring cmd = _T("--batch --list-secret-keys");
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::seconds(10)))
+ {
+ gpg_thread.~thread();
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ break;
+ }
+ if(result == pxNotFound)
+ break;
+ }
+ while(p != string::npos)
+ {
+ if((p = out.find("sec ", p)) == string::npos)
+ break;
+ p += 5;
+ if(p < stop)
+ break;
+ stop = p;
+ p2 = out.find("/", p) - 1;
+ TCHAR *tmp = mir_wstrdup(toUTF16(out.substr(p,p2-p)).c_str());
+ item.pszText = tmp;
+ iRow = ListView_InsertItem(hwndList, &item);
+ ListView_SetItemText(hwndList, iRow, 4, tmp);
+ mir_free(tmp);
+ p2+=2;
+ p = out.find(" ", p2);
+ tmp = mir_wstrdup(toUTF16(out.substr(p2,p-p2)).c_str());
+ ListView_SetItemText(hwndList, iRow, 0, tmp);
+ mir_free(tmp);
+ p = out.find("uid ", p);
+ p2 = out.find_first_not_of(" ", p+5);
+ p = out.find("<", p2);
+ tmp = mir_wstrdup(toUTF16(out.substr(p2,p-p2)).c_str());
+ ListView_SetItemText(hwndList, iRow, 2, tmp);
+ mir_free(tmp);
+ p++;
+ p2 = out.find(">", p);
+ tmp = mir_wstrdup(toUTF16(out.substr(p,p2-p)).c_str());
+ ListView_SetItemText(hwndList, iRow, 1, tmp);
+ mir_free(tmp);
+ p = out.find("ssb ", p2) + 6;
+ p = out.find(" ", p) + 1;
+ p2 = out.find("\n", p);
+ tmp = mir_wstrdup(toUTF16(out.substr(p,p2-p-1)).c_str());
+ ListView_SetItemText(hwndList, iRow, 3, tmp);
+ mir_free(tmp);
+ ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE);// not sure about this
+ ListView_SetColumnWidth(hwndList, 1, LVSCW_AUTOSIZE);
+ ListView_SetColumnWidth(hwndList, 2, LVSCW_AUTOSIZE);
+ ListView_SetColumnWidth(hwndList, 3, LVSCW_AUTOSIZE);
+ ListView_SetColumnWidth(hwndList, 4, LVSCW_AUTOSIZE);
+ i++;
+ }
+ }
+ }
+ }
+ break;
+ case IDC_DELETE_KEY:
+ ListView_GetItemText(hwndList, itemnum, 0, fp, 16);
+ {
+ string out;
+ DWORD code;
+ wstring cmd = _T("--batch --fingerprint ");
+ cmd += fp;
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ boost::thread *gpg_thread = new boost::thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread->timed_join(boost::posix_time::seconds(10)))
+ {
+ delete gpg_thread;
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ break;
+ }
+ if(result == pxNotFound)
+ break;
+ string::size_type s = out.find("Key fingerprint = ");
+ s += strlen("Key fingerprint = ");
+ string::size_type s2 = out.find("\n", s);
+ TCHAR *fp = NULL;
+ {
+ string tmp = out.substr(s, s2-s-1).c_str();
+ string::size_type p = 0;
+ while((p = tmp.find(" ", p)) != string::npos)
+ {
+ tmp.erase(p, 1);
+ }
+ fp = mir_a2t(tmp.c_str());
+ }
+ cmd.clear();
+ out.clear();
+ cmd += _T("--batch --delete-secret-and-public-key --fingerprint ");
+ cmd += fp;
+ mir_free(fp);
+ gpg_thread = new boost::thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread->timed_join(boost::posix_time::seconds(10)))
+ {
+ delete gpg_thread;
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ break;
+ }
+ if(result == pxNotFound)
+ break;
+ }
+ {
+ char buf[64];
+ GetDlgItemTextA(hwndDlg, IDC_ACCOUNT, buf, 63);
+ if(!strcmp(buf, Translate("Default")))
+ {
+ DBDeleteContactSetting(NULL, szGPGModuleName, "GPGPubKey");
+ DBDeleteContactSetting(NULL, szGPGModuleName, "KeyID");
+ DBDeleteContactSetting(NULL, szGPGModuleName, "KeyComment");
+ DBDeleteContactSetting(NULL, szGPGModuleName, "KeyMainName");
+ DBDeleteContactSetting(NULL, szGPGModuleName, "KeyMainEmail");
+ DBDeleteContactSetting(NULL, szGPGModuleName, "KeyType");
+ }
+ else
+ {
+ char setting[64];
+ strcpy(setting, buf);
+ strcat(setting, "_GPGPubKey");
+ DBDeleteContactSetting(NULL, szGPGModuleName, setting);
+ strcpy(setting, buf);
+ strcat(setting, "_KeyMainName");
+ DBDeleteContactSetting(NULL, szGPGModuleName, setting);
+ strcpy(setting, buf);
+ strcat(setting, "_KeyID");
+ DBDeleteContactSetting(NULL, szGPGModuleName, setting);
+ strcpy(setting, buf);
+ strcat(setting, "_KeyComment");
+ DBDeleteContactSetting(NULL, szGPGModuleName, setting);
+ strcpy(setting, buf);
+ strcat(setting, "_KeyMainEmail");
+ DBDeleteContactSetting(NULL, szGPGModuleName, setting);
+ strcpy(setting, buf);
+ strcat(setting, "_KeyType");
+ DBDeleteContactSetting(NULL, szGPGModuleName, setting);
+ }
+ }
+ ListView_DeleteItem(hwndList, itemnum);
+ break;
+ case IDC_GENERATE_RANDOM:
+ {
+ wstring path;
+ { //generating key file
+ TCHAR *tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T(""));
+ path = tmp;
+ mir_free(tmp);
+ path.append(_T("\\new_key"));
+ wfstream f(path.c_str(), std::ios::out);
+ if(!f.is_open())
+ {
+ MessageBox(0, TranslateT("Failed to open file"), TranslateT("Error"), MB_OK);
+ break;
+ }
+ f<<"Key-Type: RSA";
+ f<<"\n";
+ f<<"Key-Length: 4096";
+ f<<"\n";
+ f<<"Subkey-Type: RSA";
+ f<<"\n";
+ f<<"Name-Real: ";
+ f<<get_random(6).c_str();
+ f<<"\n";
+ f<<"Name-Email: ";
+ f<<get_random(5).c_str();
+ f<<"@";
+ f<<get_random(5).c_str();
+ f<<".";
+ f<<get_random(3).c_str();
+ f<<"\n";
+ f.close();
+ }
+ { //gpg execution
+ DWORD code;
+ string out;
+ wstring cmd;
+ cmd += _T("--batch --yes --gen-key \"");
+ cmd += path;
+ cmd += _T("\"");
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ SetWindowTextA(GetDlgItem(hwndDlg, IDC_GENERATING_KEY), Translate("Generating new random key, please wait"));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_GENERATE_KEY), 0);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_OTHER), 0);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE_KEY), 0);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_KEY_LIST), 0);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_GENERATE_RANDOM), 0);
+ boost::thread gpg_thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::minutes(10)))
+ {
+ gpg_thread.~thread();
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted";
+ break;
+ }
+ if(result == pxNotFound)
+ break;
+
+ DeleteFile(path.c_str());
+ string::size_type p1 = 0;
+ if((p1 = out.find("key ")) != string::npos)
+ path = toUTF16(out.substr(p1+4, 8));
+ else
+ path.clear();
+ }
+ if(!path.empty())
+ {
+ string out;
+ DWORD code;
+ wstring cmd = _T("--batch -a --export ");
+ cmd += path;
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::seconds(10)))
+ {
+ gpg_thread.~thread();
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<"GPG execution timed out, aborted\n";
+ break;
+ }
+ if(result == pxNotFound)
+ break;
+ string::size_type s = 0;
+ while((s = out.find("\r", s)) != string::npos)
+ {
+ out.erase(s, 1);
+ }
+ {
+ char buf[64];
+ GetDlgItemTextA(hwndDlg, IDC_ACCOUNT, buf, 63);
+ if(!strcmp(buf, Translate("Default")))
+ {
+ DBWriteContactSettingString(NULL, szGPGModuleName, "GPGPubKey", out.c_str());
+ DBWriteContactSettingTString(NULL, szGPGModuleName, "KeyID", fp);
+ }
+ else
+ {
+ char setting[64];
+ strcpy(setting, buf);
+ strcat(setting, "_GPGPubKey");
+ DBWriteContactSettingString(NULL, szGPGModuleName, setting, out.c_str());
+ strcpy(setting, buf);
+ strcat(setting, "_KeyID");
+ DBWriteContactSettingTString(NULL, szGPGModuleName, setting, fp);
+ }
+ }
+ extern HWND hwndCurKey_p;
+ SetWindowText(hwndCurKey_p, path.c_str());
+ }
+ }
+ DestroyWindow(hwndDlg);
+ break;
+ case IDC_ACCOUNT:
+ {
+ char buf[64];
+ GetDlgItemTextA(hwndDlg, IDC_ACCOUNT, buf, 63);
+ if(!strcmp(buf, Translate("Default")))
+ {
+ string keyinfo = Translate("key id");
+ keyinfo += ": ";
+ char *keyid = UniGetContactSettingUtf(NULL, szGPGModuleName, "KeyID", "");
+ keyinfo += (strlen(keyid) > 0)?keyid:Translate("not set");
+ mir_free(keyid);
+ SetDlgItemTextA(hwndDlg, IDC_KEY_ID, keyinfo.c_str());
+ }
+ else
+ {
+ string keyinfo = Translate("key id");
+ keyinfo += ": ";
+ char setting[64];
+ strcpy(setting, buf);
+ strcat(setting, "_KeyID");
+ char *keyid = UniGetContactSettingUtf(NULL, szGPGModuleName, setting, "");
+ keyinfo += (strlen(keyid) > 0)?keyid:Translate("not set");
+ mir_free(keyid);
+ SetDlgItemTextA(hwndDlg, IDC_KEY_ID, keyinfo.c_str());
+ }
+ }
+ break;
+
+ }
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+ if(hdr && IsWindowVisible(hdr->hdr.hwndFrom) && hdr->iItem != (-1))
+ {
+ if(hdr->hdr.code == NM_CLICK)
+ {
+ EnableWindow(GetDlgItem(hwndDlg, ID_OK), 1);
+ itemnum = hdr->iItem;
+ }
+ }
+/* switch(LOWORD(wParam))
+ {
+ default:
+ break;
+ }; */
+/* switch (((LPNMHDR)lParam)->code)
+ {
+ default:
+ break;
+ } */
+ }
+ break;
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+ case WM_DESTROY:
+ {
+ GetWindowRect(hwndDlg, &firstrun_rect);
+ DBWriteContactSettingDword(NULL, szGPGModuleName, "FirstrunWindowX", firstrun_rect.left);
+ DBWriteContactSettingDword(NULL, szGPGModuleName, "FirstrunWindowY", firstrun_rect.top);
+ }
+ hwndFirstRun = NULL;
+ break;
+
+ }
+
+ return FALSE;
+}
+
+void ShowFirstRunDialog();
+
+static BOOL CALLBACK DlgProcGpgBinOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ TCHAR *tmp = NULL;
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ TCHAR *path = new TCHAR [MAX_PATH];
+ bool gpg_exists = false, lang_exists = false;
+ {
+ char *mir_path = new char [MAX_PATH];
+ CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)"\\", (LPARAM)mir_path);
+ SetCurrentDirectoryA(mir_path);
+ tmp = mir_a2t(mir_path);
+ mir_free(mir_path);
+ mir_realloc(path, (_tcslen(path)+128)*sizeof(TCHAR));
+ TCHAR *gpg_path = new TCHAR [MAX_PATH], *gpg_lang_path = new TCHAR [MAX_PATH];
+ _tcscpy(gpg_path, tmp);
+ _tcscat(gpg_path, _T("\\GnuPG\\gpg.exe"));
+ _tcscpy(gpg_lang_path, tmp);
+ _tcscat(gpg_lang_path, _T("\\GnuPG\\gnupg.nls\\en@quot.mo"));
+ mir_free(tmp);
+ if(_waccess(gpg_path, 0) != -1)
+ {
+ gpg_exists = true;
+ _tcscpy(path, _T("GnuPG\\gpg.exe"));
+ }
+ if(_waccess(gpg_lang_path, 0) != -1)
+ lang_exists = true;
+ if(gpg_exists && !lang_exists) //TODO: check gpg version
+ MessageBox(0, TranslateT("gpg binary found in miranda folder, but english locale does not exists.\nit's highly recommended to place \\gnupg.nls\\en@quot.mo in gnupg folder under miranda root.\nwithout this file you may expirense many problem with gpg output on non english systems.\nand plugin may completely do not work.\nyou have beed warned."), TranslateT("Warning"), MB_OK);
+ mir_free(gpg_path);
+ mir_free(gpg_lang_path);
+ }
+ DWORD len = MAX_PATH;
+ if(!gpg_exists)
+ {
+ tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szGpgBinPath", (SHGetValue(HKEY_CURRENT_USER, _T("Software\\GNU\\GnuPG"), _T("gpgProgram"), 0, path, &len) == ERROR_SUCCESS)?path:_T(""));
+ if(tmp[0])
+ {
+ char *mir_path = new char [MAX_PATH];
+ CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)"\\", (LPARAM)mir_path);
+ SetCurrentDirectoryA(mir_path);
+ delete [] mir_path;
+ if(_waccess(tmp, 0) == -1)
+ {
+ if(errno == ENOENT)
+ MessageBox(0, TranslateT("wrong gpg binary location found in system.\nplease choose another location"), TranslateT("Warning"), MB_OK);
+ }
+ }
+ }
+ else
+ tmp = mir_wstrdup(path);
+ delete [] path;
+ SetDlgItemText(hwndDlg, IDC_BIN_PATH, tmp);
+ bool bad_version = false;
+ if(gpg_exists && lang_exists)
+ {
+ DBWriteContactSettingTString(NULL, szGPGModuleName, "szGpgBinPath", tmp);
+ string out;
+ DWORD code;
+ wstring cmd = _T("--version");
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ gpg_valid = true;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::seconds(10)))
+ {
+ gpg_thread.~thread();
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ }
+ gpg_valid = false;
+ DBDeleteContactSetting(NULL, szGPGModuleName, "szGpgBinPath");
+ string::size_type p1 = out.find("(GnuPG) ");
+ if(p1 != string::npos)
+ {
+ p1 += strlen("(GnuPG) ");
+ if(out[p1] != '1')
+ bad_version = true;
+ }
+ else
+ {
+ bad_version = false;
+ MessageBox(0, TranslateT("This is not gnupg binary !\nrecommended to use GnuPG v1.x.x with this plugn."), TranslateT("Warning"), MB_OK);
+ }
+ if(bad_version)
+ MessageBox(0, TranslateT("Unsupported gnupg version found, use at you own risk!\nrecommended to use GnuPG v1.x.x with this plugn."), TranslateT("Warning"), MB_OK);
+ }
+ mir_free(tmp);
+ if(!gpg_exists)
+ {
+ wstring path_ = _wgetenv(_T("APPDATA"));
+ path_ += _T("\\GnuPG");
+ tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", (TCHAR*)path_.c_str());
+ }
+ SetDlgItemText(hwndDlg, IDC_HOME_DIR, !gpg_exists?tmp:_T("gpg"));
+ mir_free(tmp);
+ if(gpg_exists && lang_exists && !bad_version)
+ MessageBox(0, TranslateT("Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue."), TranslateT("Info"), MB_OK);
+ extern bool bIsMiranda09;
+ EnableWindow(GetDlgItem(hwndDlg, IDC_AUTO_EXCHANGE), bIsMiranda09);
+ return TRUE;
+ }
+
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_SET_BIN_PATH:
+ {
+ GetFilePath(_T("Choose gpg.exe"), "szGpgBinPath", _T("*.exe"), _T("EXE Executables"));
+ tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szGpgBinPath", _T("gpg.exe"));
+ SetDlgItemText(hwndDlg, IDC_BIN_PATH, tmp);
+ char mir_path[MAX_PATH];
+ char *atmp = mir_t2a(tmp);
+ mir_free(tmp);
+ CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)"\\", (LPARAM)mir_path);
+ char* p_path = NULL;
+ if(StriStr(atmp, mir_path))
+ {
+ p_path = atmp + strlen(mir_path);
+ tmp = mir_a2t(p_path);
+ SetDlgItemText(hwndDlg, IDC_BIN_PATH, tmp);
+ }
+ }
+ break;
+ case IDC_SET_HOME_DIR:
+ {
+ GetFolderPath(_T("Set home diractory"), "szHomePath");
+ tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T(""));
+ SetDlgItemText(hwndDlg, IDC_HOME_DIR, tmp);
+ char mir_path[MAX_PATH];
+ char *atmp = mir_t2a(tmp);
+ mir_free(tmp);
+ CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)"\\", (LPARAM)mir_path);
+ char* p_path = NULL;
+ if(StriStr(atmp, mir_path))
+ {
+ p_path = atmp + strlen(mir_path);
+ tmp = mir_a2t(p_path);
+ SetDlgItemText(hwndDlg, IDC_HOME_DIR, tmp);
+ }
+ }
+ break;
+ case ID_OK:
+ {
+ TCHAR tmp[512];
+ GetDlgItemText(hwndDlg, IDC_BIN_PATH, tmp, 512);
+ if(tmp[0])
+ {
+ char *mir_path = new char [MAX_PATH];
+ CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)"\\", (LPARAM)mir_path);
+ SetCurrentDirectoryA(mir_path);
+ delete [] mir_path;
+ if(_waccess(tmp, 0) == -1)
+ {
+ if(errno == ENOENT)
+ {
+ MessageBox(0, TranslateT("gpg binary does not exists.\nplease choose another location"), TranslateT("Warning"), MB_OK);
+ break;
+ }
+ }
+ }
+ else
+ {
+ MessageBox(0, TranslateT("please choose gpg binary location"), TranslateT("Warning"), MB_OK);
+ break;
+ }
+ {
+ bool bad_version = false;
+ DBWriteContactSettingTString(NULL, szGPGModuleName, "szGpgBinPath", tmp);
+ string out;
+ DWORD code;
+ wstring cmd = _T("--version");
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ gpg_valid = true;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::seconds(10)))
+ {
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ gpg_thread.~thread();
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ }
+ gpg_valid = false;
+ DBDeleteContactSetting(NULL, szGPGModuleName, "szGpgBinPath");
+ string::size_type p1 = out.find("(GnuPG) ");
+ if(p1 != string::npos)
+ {
+ p1 += strlen("(GnuPG) ");
+ if(out[p1] != '1')
+ bad_version = true;
+ }
+ else
+ {
+ bad_version = false;
+ MessageBox(0, TranslateT("This is not gnupg binary !\nrecommended to use GnuPG v1.x.x with this plugn."), TranslateT("Warning"), MB_OK);
+ }
+ if(bad_version)
+ MessageBox(0, TranslateT("Unsupported gnupg version found, use at you own risk!\nrecommended to use GnuPG v1.x.x with this plugn."), TranslateT("Warning"), MB_OK);
+ }
+ DBWriteContactSettingTString(NULL, szGPGModuleName, "szGpgBinPath", tmp);
+ GetDlgItemText(hwndDlg, IDC_HOME_DIR, tmp, 512);
+ while(tmp[_tcslen(tmp)-1] == '\\')
+ tmp[_tcslen(tmp)-1] = '\0';
+ if(!tmp[0])
+ {
+ MessageBox(0, TranslateT("please set keyring's home directory"), TranslateT("Warning"), MB_OK);
+ break;
+ }
+ DBWriteContactSettingTString(NULL, szGPGModuleName, "szHomePath", tmp);
+ {
+ TCHAR *path = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T(""));
+ DWORD dwFileAttr = GetFileAttributes(path);
+ if (dwFileAttr != INVALID_FILE_ATTRIBUTES)
+ {
+ dwFileAttr &=~ FILE_ATTRIBUTE_READONLY;
+ SetFileAttributes(path, dwFileAttr);
+ }
+ mir_free(path);
+ }
+ gpg_valid = true;
+ DBWriteContactSettingByte(NULL, szGPGModuleName, "FirstRun", 0);
+ DestroyWindow(hwndDlg);
+ ShowFirstRunDialog();
+ }
+ break;
+ case IDC_GENERATE_RANDOM:
+ {
+ TCHAR tmp[512];
+ GetDlgItemText(hwndDlg, IDC_BIN_PATH, tmp, 512);
+ if(tmp[0])
+ {
+ char *mir_path = new char [MAX_PATH];
+ CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)"\\", (LPARAM)mir_path);
+ SetCurrentDirectoryA(mir_path);
+ delete [] mir_path;
+ if(_waccess(tmp, 0) == -1)
+ {
+ if(errno == ENOENT)
+ {
+ MessageBox(0, TranslateT("gpg binary does not exists.\nplease choose another location"), TranslateT("Warning"), MB_OK);
+ break;
+ }
+ }
+ }
+ else
+ {
+ MessageBox(0, TranslateT("please choose gpg binary location"), TranslateT("Warning"), MB_OK);
+ break;
+ }
+ {
+ bool bad_version = false;
+ DBWriteContactSettingTString(NULL, szGPGModuleName, "szGpgBinPath", tmp);
+ string out;
+ DWORD code;
+ wstring cmd = _T("--version");
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ gpg_valid = true;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::seconds(10)))
+ {
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ gpg_thread.~thread();
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ }
+ gpg_valid = false;
+ DBDeleteContactSetting(NULL, szGPGModuleName, "szGpgBinPath");
+ string::size_type p1 = out.find("(GnuPG) ");
+ if(p1 != string::npos)
+ {
+ p1 += strlen("(GnuPG) ");
+ if(out[p1] != '1')
+ bad_version = true;
+ }
+ else
+ {
+ bad_version = false;
+ MessageBox(0, TranslateT("This is not gnupg binary !\nrecommended to use GnuPG v1.x.x with this plugn."), TranslateT("Warning"), MB_OK);
+ }
+ if(bad_version)
+ MessageBox(0, TranslateT("Unsupported gnupg version found, use at you own risk!\nrecommended to use GnuPG v1.x.x with this plugn."), TranslateT("Warning"), MB_OK);
+ }
+ DBWriteContactSettingTString(NULL, szGPGModuleName, "szGpgBinPath", tmp);
+ GetDlgItemText(hwndDlg, IDC_HOME_DIR, tmp, 512);
+ while(tmp[_tcslen(tmp)-1] == '\\')
+ tmp[_tcslen(tmp)-1] = '\0';
+ if(!tmp[0])
+ {
+ MessageBox(0, TranslateT("please set keyring's home directory"), TranslateT("Warning"), MB_OK);
+ break;
+ }
+ DBWriteContactSettingTString(NULL, szGPGModuleName, "szHomePath", tmp);
+ {
+ TCHAR *path = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T(""));
+ DWORD dwFileAttr = GetFileAttributes(path);
+ if (dwFileAttr != INVALID_FILE_ATTRIBUTES)
+ {
+ dwFileAttr &=~ FILE_ATTRIBUTE_READONLY;
+ SetFileAttributes(path, dwFileAttr);
+ }
+ mir_free(path);
+ }
+ }
+ {
+ wstring path;
+ { //generating key file
+ TCHAR *tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T(""));
+ path = tmp;
+ mir_free(tmp);
+ path.append(_T("\\new_key"));
+ wfstream f(path.c_str(), std::ios::out);
+ if(!f.is_open())
+ {
+ MessageBox(0, TranslateT("Failed to open file"), TranslateT("Error"), MB_OK);
+ break;
+ }
+ f<<"Key-Type: RSA";
+ f<<"\n";
+ f<<"Key-Length: 2048";
+ f<<"\n";
+ f<<"Subkey-Type: RSA";
+ f<<"\n";
+ f<<"Name-Real: ";
+ f<<get_random(6).c_str();
+ f<<"\n";
+ f<<"Name-Email: ";
+ f<<get_random(5).c_str();
+ f<<"@";
+ f<<get_random(5).c_str();
+ f<<".";
+ f<<get_random(3).c_str();
+ f<<"\n";
+ f.close();
+ }
+ { //gpg execution
+ DWORD code;
+ string out;
+ wstring cmd;
+ cmd += _T("--batch --yes --gen-key \"");
+ cmd += path;
+ cmd += _T("\"");
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ gpg_valid = true;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::minutes(10)))
+ {
+ gpg_thread.~thread();
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted";
+ gpg_valid = false;
+ break;
+ }
+ gpg_valid = false;
+ if(result == pxNotFound)
+ break;
+ DeleteFile(path.c_str());
+ string::size_type p1 = 0;
+ if((p1 = out.find("key ")) != string::npos)
+ path = toUTF16(out.substr(p1+4, 8));
+ else
+ path.clear();
+ }
+ if(!path.empty())
+ {
+ string out;
+ DWORD code;
+ wstring cmd = _T("--batch -a --export ");
+ cmd += path;
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ gpg_valid = true;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::seconds(10)))
+ {
+ gpg_thread.~thread();
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<"GPG execution timed out, aborted\n";
+ gpg_valid = false;
+ break;
+ }
+ gpg_valid = false;
+ if(result == pxNotFound)
+ break;
+ string::size_type s = 0;
+ while((s = out.find("\r", s)) != string::npos)
+ {
+ out.erase(s, 1);
+ }
+ DBWriteContactSettingString(NULL, szGPGModuleName, "GPGPubKey", out.c_str());
+ DBWriteContactSettingTString(NULL, szGPGModuleName, "KeyID", path.c_str());
+ extern HWND hwndCurKey_p;
+ SetWindowText(hwndCurKey_p, path.c_str());
+ }
+ }
+ bAutoExchange = CheckStateStoreDB(hwndDlg, IDC_AUTO_EXCHANGE, "bAutoExchange");
+ gpg_valid = true;
+ DBWriteContactSettingByte(NULL, szGPGModuleName, "FirstRun", 0);
+ DestroyWindow(hwndDlg);
+ break;
+ default:
+ break;
+ }
+
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+/* switch (((LPNMHDR)lParam)->code)
+ {
+ default:
+ break;
+ }*/
+ }
+ break;
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+ case WM_DESTROY:
+ hwndSetDirs = NULL;
+ break;
+
+ }
+ return FALSE;
+}
+
+static BOOL CALLBACK DlgProcNewKeyDialog(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ extern HANDLE new_key_hcnt;
+ extern boost::mutex new_key_hcnt_mutex;
+ static HANDLE hContact = INVALID_HANDLE_VALUE;
+ void ImportKey();
+ TCHAR *tmp = NULL;
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ hContact = new_key_hcnt;
+ new_key_hcnt_mutex.unlock();
+ SetWindowPos(hwndDlg, 0, new_key_rect.left, new_key_rect.top, 0, 0, SWP_NOSIZE|SWP_SHOWWINDOW);
+ TranslateDialogDefault(hwndDlg);
+ TCHAR *tmp = UniGetContactSettingUtf(hContact, szGPGModuleName, "GPGPubKey", _T(""));
+ SetDlgItemText(hwndDlg, IDC_MESSAGE, tmp[0]?TranslateT("There is existing key for contact, would you like to replace with new key ?"):TranslateT("New public key was received, do you want to import it?"));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_IMPORT_AND_USE), DBGetContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 0)?0:1);
+ SetDlgItemText(hwndDlg, ID_IMPORT, tmp[0]?TranslateT("Replace"):TranslateT("Accept"));
+ mir_free(tmp);
+ tmp = new TCHAR [256];
+ _tcscpy(tmp, TranslateT("Received key from "));
+ _tcscat(tmp, (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, (LPARAM)GCDNF_TCHAR));
+ SetDlgItemText(hwndDlg, IDC_KEY_FROM, tmp);
+ delete [] tmp;
+ return TRUE;
+ }
+
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case ID_IMPORT:
+ ImportKey();
+ DestroyWindow(hwndDlg);
+ break;
+ case IDC_IMPORT_AND_USE:
+ ImportKey();
+ DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 1);
+ void setSrmmIcon(HANDLE hContact);
+ void setClistIcon(HANDLE hContact);
+ setSrmmIcon(hContact);
+ setClistIcon(hContact);
+ DestroyWindow(hwndDlg);
+ break;
+ case IDC_IGNORE_KEY:
+ DestroyWindow(hwndDlg);
+ break;
+ default:
+ break;
+ }
+
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+/* switch (((LPNMHDR)lParam)->code)
+ {
+ default:
+ break;
+ }*/
+ }
+ break;
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+ case WM_DESTROY:
+ {
+ GetWindowRect(hwndDlg, &new_key_rect);
+ DBWriteContactSettingDword(NULL, szGPGModuleName, "NewKeyWindowX", new_key_rect.left);
+ DBWriteContactSettingDword(NULL, szGPGModuleName, "NewKeyWindowY", new_key_rect.top);
+ }
+ hwndNewKey = NULL;
+ break;
+
+ }
+ return FALSE;
+}
+static BOOL CALLBACK DlgProcKeyGenDialog(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ SetWindowPos(hwndDlg, 0, key_gen_rect.left, key_gen_rect.top, 0, 0, SWP_NOSIZE|SWP_SHOWWINDOW);
+ TranslateDialogDefault(hwndDlg);
+ SetWindowText(hwndDlg, TranslateT("Key Generation dialog"));
+ ComboBoxAddStringUtf(GetDlgItem(hwndDlg, IDC_KEY_TYPE), _T("RSA"), 0);
+ ComboBoxAddStringUtf(GetDlgItem(hwndDlg, IDC_KEY_TYPE), _T("DSA"), 1);
+ SendDlgItemMessage(hwndDlg, IDC_KEY_TYPE, CB_SETCURSEL, (WPARAM)1, 0);
+ SetDlgItemInt(hwndDlg, IDC_KEY_EXPIRE_DATE, 0, 0);
+ SetDlgItemInt(hwndDlg, IDC_KEY_LENGTH, 4096, 0);
+ return TRUE;
+ }
+
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDCANCEL:
+ DestroyWindow(hwndDlg);
+ break;
+ case IDOK:
+ {
+ wstring path;
+ { //data sanity checks
+ TCHAR *tmp = (TCHAR*)mir_alloc(sizeof(TCHAR)*5);
+ GetDlgItemText(hwndDlg, IDC_KEY_TYPE, tmp, 5);
+ if(_tcslen(tmp) < 3)
+ {
+ mir_free(tmp); tmp = NULL;
+ MessageBox(0, TranslateT("You must set encryption algorythm first"), TranslateT("Error"), MB_OK);
+ break;
+ }
+ if(tmp)
+ mir_free(tmp);
+ tmp = (TCHAR*)mir_alloc(sizeof(TCHAR)*6);
+ GetDlgItemText(hwndDlg, IDC_KEY_LENGTH, tmp, 5);
+ int length = _ttoi(tmp);
+ mir_free(tmp);
+ if(length < 1024 || length > 4096)
+ {
+ MessageBox(0, TranslateT("Key length must be of length from 1024 to 4096 bits"), TranslateT("Error"), MB_OK);
+ break;
+ }
+ tmp = (TCHAR*)mir_alloc(sizeof(TCHAR)*12);
+ GetDlgItemText(hwndDlg, IDC_KEY_EXPIRE_DATE, tmp, 11);
+ if(_tcslen(tmp) != 10 && tmp[0] != '0')
+ {
+ MessageBox(0, TranslateT("Invalid date"), TranslateT("Error"), MB_OK);
+ mir_free(tmp);
+ break;
+ }
+ mir_free(tmp);
+ tmp = (TCHAR*)mir_alloc(sizeof(TCHAR)*128);
+ GetDlgItemText(hwndDlg, IDC_KEY_REAL_NAME, tmp, 127);
+ if(_tcslen(tmp) < 5)
+ {
+ MessageBox(0, TranslateT("Name must contain at least 5 characters"), TranslateT("Error"), MB_OK);
+ mir_free(tmp);
+ break;
+ }
+ else if (_tcschr(tmp, _T('(')) || _tcschr(tmp, _T(')')))
+ {
+ MessageBox(0, TranslateT("Name cannot contain '(' or ')'"), TranslateT("Error"), MB_OK);
+ mir_free(tmp);
+ break;
+ }
+ mir_free(tmp);
+ tmp = (TCHAR*)mir_alloc(sizeof(TCHAR)*128);
+ GetDlgItemText(hwndDlg, IDC_KEY_EMAIL, tmp, 128);
+ if((_tcslen(tmp)) < 5 || (!_tcschr(tmp, _T('@'))) || (!_tcschr(tmp, _T('.'))))
+ {
+ MessageBox(0, TranslateT("Invalid Email"), TranslateT("Error"), MB_OK);
+ mir_free(tmp);
+ break;
+ }
+ mir_free(tmp);
+ }
+ { //generating key file
+ TCHAR *tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T(""));
+ char *tmp2;// = mir_t2a(tmp);
+ path = tmp;
+ mir_free(tmp);
+ // mir_free(tmp2);
+ path.append(_T("\\new_key"));
+ wfstream f(path.c_str(), std::ios::out);
+ if(!f.is_open())
+ {
+ MessageBox(0, TranslateT("Failed to open file"), TranslateT("Error"), MB_OK);
+ break;
+ }
+ f<<"Key-Type: ";
+ tmp = (TCHAR*)mir_alloc(sizeof(TCHAR)*5);
+ GetDlgItemText(hwndDlg, IDC_KEY_TYPE, tmp, 5);
+ tmp2 = mir_t2a(tmp);
+ mir_free(tmp);
+ char *subkeytype = (char*)mir_alloc(6);
+ if(strstr(tmp2, "RSA"))
+ strcpy(subkeytype, "RSA");
+ else if(strstr(tmp2, "DSA")) //this is useless check for now, but it will be required if someone add another key types support
+ strcpy(subkeytype, "ELG-E");
+ f<<tmp2;
+ mir_free(tmp2);
+ f<<"\n";
+ f<<"Key-Length: ";
+ tmp = (TCHAR*)mir_alloc(sizeof(TCHAR)*5);
+ GetDlgItemText(hwndDlg, IDC_KEY_LENGTH, tmp, 5);
+ int length = _ttoi(tmp);
+ mir_free(tmp);
+ f<<length;
+ f<<"\n";
+ f<<"Subkey-Length: ";
+ f<<length;
+ f<<"\n";
+ f<<"Subkey-Type: ";
+ f<<subkeytype;
+ mir_free(subkeytype);
+ f<<"\n";
+ tmp = (TCHAR*)mir_alloc(sizeof(TCHAR)*64); //i hope this is enough for password
+ GetDlgItemText(hwndDlg, IDC_KEY_PASSWD, tmp, 64);
+ if(tmp[0])
+ {
+ f<<"Passphrase: ";
+ tmp2 = mir_strdup(toUTF8(tmp).c_str());
+ f<<tmp2;
+ f<<"\n";
+ mir_free(tmp2);
+ }
+ mir_free(tmp);
+ f<<"Name-Real: ";
+ tmp = (TCHAR*)mir_alloc(sizeof(TCHAR)*128);
+ GetDlgItemText(hwndDlg, IDC_KEY_REAL_NAME, tmp, 128);
+ tmp2 = mir_strdup(toUTF8(tmp).c_str());
+ f<<tmp2;
+ mir_free(tmp2);
+ mir_free(tmp);
+ f<<"\n";
+ tmp = (TCHAR*)mir_alloc(sizeof(TCHAR)*512);
+ GetDlgItemText(hwndDlg, IDC_KEY_COMMENT, tmp, 512);
+ if(tmp[0])
+ {
+ tmp2 = mir_strdup(toUTF8(tmp).c_str());
+ f<<"Name-Comment: ";
+ f<<tmp2;
+ f<<"\n";
+ }
+ mir_free(tmp2);
+ mir_free(tmp);
+ f<<"Name-Email: ";
+ tmp = (TCHAR*)mir_alloc(sizeof(TCHAR)*128);
+ GetDlgItemText(hwndDlg, IDC_KEY_EMAIL, tmp, 128);
+ tmp2 = mir_strdup(toUTF8(tmp).c_str());
+ f<<tmp2;
+ mir_free(tmp2);
+ mir_free(tmp);
+ f<<"\n";
+ f<<"Expire-Date: ";
+ tmp = (TCHAR*)mir_alloc(sizeof(TCHAR)*12);
+ GetDlgItemText(hwndDlg, IDC_KEY_EXPIRE_DATE, tmp, 12);
+ tmp2 = mir_strdup(toUTF8(tmp).c_str());
+ f<<tmp2;
+ mir_free(tmp2);
+ mir_free(tmp);
+ f<<"\n";
+ f.close();
+ }
+ { //gpg execution
+ DWORD code;
+ string out;
+ wstring cmd;
+ cmd += _T("--batch --yes --gen-key \"");
+ cmd += path;
+ cmd += _T("\"");
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ SetWindowTextA(GetDlgItem(hwndDlg, IDC_GENERATING_TEXT), Translate("Generating new key, please wait..."));
+ EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), 0);
+ EnableWindow(GetDlgItem(hwndDlg, IDOK), 0);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_KEY_TYPE), 0);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_KEY_LENGTH), 0);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_KEY_PASSWD), 0);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_KEY_REAL_NAME), 0);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_KEY_EMAIL), 0);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_KEY_COMMENT), 0);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_KEY_EXPIRE_DATE), 0);
+ boost::thread gpg_thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::minutes(10)))
+ {
+ gpg_thread.~thread();
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ break;
+ }
+ if(result == pxNotFound)
+ break;
+ }
+ DeleteFile(path.c_str());
+ DestroyWindow(hwndDlg);
+ {//parse gpg output
+ LVITEM item = {0};
+ int i = 1, iRow = 0;
+ item.mask = LVIF_TEXT;
+ item.iItem = i;
+ item.iSubItem = 0;
+ item.pszText = _T("");
+ string out;
+ DWORD code;
+ string::size_type p = 0, p2 = 0, stop = 0;
+ {
+ wstring cmd = _T("--list-secret-keys");
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::seconds(10)))
+ {
+ gpg_thread.~thread();
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ break;
+ }
+ if(result == pxNotFound)
+ break;
+ }
+ ListView_DeleteAllItems(hwndList_g);
+ while(p != string::npos)
+ {
+ if((p = out.find("sec ", p)) == string::npos)
+ break;
+ p += 5;
+ if(p < stop)
+ break;
+ stop = p;
+ p2 = out.find("/", p) - 1;
+ TCHAR *tmp = mir_wstrdup(toUTF16(out.substr(p,p2-p)).c_str());
+ item.pszText = tmp;
+ iRow = ListView_InsertItem(hwndList_g, &item);
+ ListView_SetItemText(hwndList_g, iRow, 4, tmp);
+ mir_free(tmp);
+ p2+=2;
+ p = out.find(" ", p2);
+ tmp = mir_wstrdup(toUTF16(out.substr(p2,p-p2)).c_str());
+ ListView_SetItemText(hwndList_g, iRow, 0, tmp);
+ mir_free(tmp);
+ p = out.find("uid ", p);
+ p2 = out.find_first_not_of(" ", p+5);
+ p = out.find("<", p2);
+ tmp = mir_wstrdup(toUTF16(out.substr(p2,p-p2)).c_str());
+ ListView_SetItemText(hwndList_g, iRow, 2, tmp);
+ mir_free(tmp);
+ p++;
+ p2 = out.find(">", p);
+ tmp = mir_wstrdup(toUTF16(out.substr(p,p2-p)).c_str());
+ ListView_SetItemText(hwndList_g, iRow, 1, tmp);
+ mir_free(tmp);
+ p = out.find("ssb ", p2) + 6;
+ p = out.find(" ", p) + 1;
+ p2 = out.find("\n", p);
+ tmp = mir_wstrdup(toUTF16(out.substr(p,p2-p-1)).c_str());
+ ListView_SetItemText(hwndList_g, iRow, 3, tmp);
+ mir_free(tmp);
+ ListView_SetColumnWidth(hwndList_g, 0, LVSCW_AUTOSIZE);// not sure about this
+ ListView_SetColumnWidth(hwndList_g, 1, LVSCW_AUTOSIZE);
+ ListView_SetColumnWidth(hwndList_g, 2, LVSCW_AUTOSIZE);
+ ListView_SetColumnWidth(hwndList_g, 3, LVSCW_AUTOSIZE);
+ ListView_SetColumnWidth(hwndList_g, 4, LVSCW_AUTOSIZE);
+ i++;
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+/* switch (((LPNMHDR)lParam)->code)
+ {
+ default:
+ break;
+ } */
+ }
+ break;
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+ case WM_DESTROY:
+ {
+ GetWindowRect(hwndDlg, &key_gen_rect);
+ DBWriteContactSettingDword(NULL, szGPGModuleName, "KeyGenWindowX", key_gen_rect.left);
+ DBWriteContactSettingDword(NULL, szGPGModuleName, "KeyGenWindowY", key_gen_rect.top);
+ }
+ hwndKeyGen = NULL;
+ break;
+
+ }
+ return FALSE;
+}
+
+int itemnum2 = 0;
+
+static BOOL CALLBACK DlgProcLoadExistingKey(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ HWND hwndList=GetDlgItem(hwndDlg, IDC_EXISTING_KEY_LIST);
+ hwndList_g = hwndList;
+ LVCOLUMN col = {0};
+ LVITEM item = {0};
+ NMLISTVIEW * hdr = (NMLISTVIEW *) lParam;
+ TCHAR id[16] = {0};
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ SetWindowPos(hwndDlg, 0, load_existing_key_rect.left, load_existing_key_rect.top, 0, 0, SWP_NOSIZE|SWP_SHOWWINDOW);
+ TranslateDialogDefault(hwndDlg);
+ col.pszText = _T("Key ID");
+ col.mask = LVCF_TEXT | LVCF_WIDTH;
+ col.fmt = LVCFMT_LEFT;
+ col.cx = 50;
+ ListView_InsertColumn(hwndList, 0, &col);
+ ZeroMemory(&col,sizeof(col));
+ col.pszText = _T("Email");
+ col.mask = LVCF_TEXT | LVCF_WIDTH;
+ col.fmt = LVCFMT_LEFT;
+ col.cx = 30;
+ ListView_InsertColumn(hwndList, 1, &col);
+ ZeroMemory(&col,sizeof(col));
+ col.pszText = _T("Name");
+ col.mask = LVCF_TEXT | LVCF_WIDTH;
+ col.fmt = LVCFMT_LEFT;
+ col.cx = 250;
+ ListView_InsertColumn(hwndList, 2, &col);
+ ZeroMemory(&col,sizeof(col));
+ col.pszText = _T("Creation date");
+ col.mask = LVCF_TEXT | LVCF_WIDTH;
+ col.fmt = LVCFMT_LEFT;
+ col.cx = 30;
+ ListView_InsertColumn(hwndList, 3, &col);
+ ZeroMemory(&col,sizeof(col));
+ col.pszText = _T("Expiration date");
+ col.mask = LVCF_TEXT | LVCF_WIDTH;
+ col.fmt = LVCFMT_LEFT;
+ col.cx = 30;
+ ListView_InsertColumn(hwndList, 4, &col);
+ ZeroMemory(&col,sizeof(col));
+ col.pszText = _T("Key length");
+ col.mask = LVCF_TEXT | LVCF_WIDTH;
+ col.fmt = LVCFMT_LEFT;
+ col.cx = 30;
+ ListView_InsertColumn(hwndList, 5, &col);
+ ListView_SetExtendedListViewStyleEx(hwndList, 0, LVS_EX_FULLROWSELECT);
+ int i = 1, iRow = 0;
+ {
+ item.mask = LVIF_TEXT;
+ item.iItem = i;
+ item.iSubItem = 0;
+ item.pszText = _T("");
+ {//parse gpg output
+ string out;
+ DWORD code;
+ string::size_type p = 0, p2 = 0, stop = 0;
+ {
+ wstring cmd = _T("--batch --list-keys");
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::seconds(10)))
+ {
+ gpg_thread.~thread();
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ break;
+ }
+ if(result == pxNotFound)
+ break;
+ }
+ while(p != string::npos)
+ {
+ if((p = out.find("pub ", p)) == string::npos)
+ break;
+ p += 5;
+ if(p < stop)
+ break;
+ stop = p;
+ p2 = out.find("/", p) - 1;
+ TCHAR *tmp = mir_wstrdup(toUTF16(out.substr(p,p2-p)).c_str());
+ item.pszText = tmp;
+ iRow = ListView_InsertItem(hwndList, &item);
+ ListView_SetItemText(hwndList, iRow, 5, tmp);
+ mir_free(tmp);
+ p2+=2;
+ p = out.find(" ", p2);
+ tmp = mir_wstrdup(toUTF16(out.substr(p2,p-p2)).c_str());
+ ListView_SetItemText(hwndList, iRow, 0, tmp);
+ mir_free(tmp);
+ p++;
+ p2 = out.find("\n", p);
+ string::size_type p3 = out.substr(p, p2-p).find("[");
+ if(p3 != string::npos)
+ {
+ p3+=p;
+ p2 = p3;
+ p2--;
+ p3++;
+ p3+=strlen("expires: ");
+ string::size_type p4 = out.find("]", p3);
+ tmp = mir_wstrdup(toUTF16(out.substr(p3,p4-p3)).c_str());
+ ListView_SetItemText(hwndList, iRow, 4, tmp);
+ mir_free(tmp);
+ }
+ else
+ p2--;
+ tmp = mir_wstrdup(toUTF16(out.substr(p,p2-p)).c_str());
+ ListView_SetItemText(hwndList, iRow, 3, tmp);
+ mir_free(tmp);
+ p = out.find("uid ", p);
+ p+= strlen("uid ");
+ p2 = out.find("\n", p);
+ p3 = out.substr(p, p2-p).find("<");
+ if(p3 != string::npos)
+ {
+ p3+=p;
+ p2=p3;
+ p2--;
+ p3++;
+ string::size_type p4 = out.find(">", p3);
+ tmp = mir_wstrdup(toUTF16(out.substr(p3,p4-p3)).c_str());
+ ListView_SetItemText(hwndList, iRow, 1, tmp);
+ mir_free(tmp);
+ }
+ else
+ p2--;
+ p = out.find_first_not_of(" ", p);
+ tmp = mir_wstrdup(toUTF16(out.substr(p,p2-p)).c_str());
+ ListView_SetItemText(hwndList, iRow, 2, tmp);
+ mir_free(tmp);
+// p = out.find("sub ", p2) + 6;
+// p = out.find(" ", p) + 1;
+// p2 = out.find("\n", p);
+// tmp = mir_wstrdup(toUTF16(out.substr(p,p2-p-1)).c_str());
+// ListView_SetItemText(hwndList, iRow, 3, tmp);
+// mir_free(tmp);
+ ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE);// not sure about this
+ ListView_SetColumnWidth(hwndList, 1, LVSCW_AUTOSIZE);
+ ListView_SetColumnWidth(hwndList, 2, LVSCW_AUTOSIZE);
+ ListView_SetColumnWidth(hwndList, 3, LVSCW_AUTOSIZE);
+ ListView_SetColumnWidth(hwndList, 4, LVSCW_AUTOSIZE);
+ ListView_SetColumnWidth(hwndList, 5, LVSCW_AUTOSIZE);
+ i++;
+ }
+ }
+ }
+ return TRUE;
+ }
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+ {
+ ListView_GetItemText(hwndList, itemnum2, 0, id, 16);
+ extern HWND hPubKeyEdit;
+ string out;
+ DWORD code;
+ wstring cmd = _T("--batch -a --export ");
+ cmd += id;
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::seconds(10)))
+ {
+ gpg_thread.~thread();
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ break;
+ }
+ if(result == pxNotFound)
+ break;
+ string::size_type s = 0;
+ while((s = out.find("\r", s)) != string::npos)
+ {
+ out.erase(s, 1);
+ }
+ std::string::size_type p1 = 0, p2 = 0;
+ p1 = out.find("-----BEGIN PGP PUBLIC KEY BLOCK-----");
+ if(p1 != std::string::npos)
+ {
+ p2 = out.find("-----END PGP PUBLIC KEY BLOCK-----", p1);
+ if(p2 != std::string::npos)
+ {
+ p2 += strlen("-----END PGP PUBLIC KEY BLOCK-----");
+ out = out.substr(p1, p2-p1);
+ TCHAR *tmp = mir_a2t(out.c_str());
+ SetWindowText(hPubKeyEdit, tmp);
+ mir_free(tmp);
+ }
+ else
+ MessageBox(NULL, TranslateT("Failed to export public key."), TranslateT("Error"), MB_OK);
+ }
+ else
+ MessageBox(NULL, TranslateT("Failed to export public key."), TranslateT("Error"), MB_OK);
+// SetDlgItemText(hPubKeyEdit, IDC_PUBLIC_KEY_EDIT, tmp);
+ }
+ DestroyWindow(hwndDlg);
+ break;
+ case IDCANCEL:
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+ if(hdr && IsWindowVisible(hdr->hdr.hwndFrom) && hdr->iItem != (-1))
+ {
+ if(hdr->hdr.code == NM_CLICK)
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDOK), 1);
+ itemnum2 = hdr->iItem;
+ }
+ }
+
+ switch (((LPNMHDR)lParam)->code)
+ {
+
+ case PSN_APPLY:
+ {
+ return TRUE;
+ }
+ }
+ }
+ break;
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+ case WM_DESTROY:
+ {
+ GetWindowRect(hwndDlg, &load_existing_key_rect);
+ DBWriteContactSettingDword(NULL, szGPGModuleName, "LoadExistingKeyWindowX", load_existing_key_rect.left);
+ DBWriteContactSettingDword(NULL, szGPGModuleName, "LoadExistingKeyWindowY", load_existing_key_rect.top);
+ }
+ hwndSelectExistingKey = NULL;
+ break;
+
+ }
+
+ return FALSE;
+}
+static BOOL CALLBACK DlgProcImportKeyDialog(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ extern HANDLE new_key_hcnt;
+ extern boost::mutex new_key_hcnt_mutex;
+ HANDLE hContact = INVALID_HANDLE_VALUE;
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ hContact = new_key_hcnt;
+ new_key_hcnt_mutex.unlock();
+ SetWindowPos(hwndDlg, 0 , import_key_rect.left, import_key_rect.top, 0, 0, SWP_NOSIZE|SWP_SHOWWINDOW);
+ TranslateDialogDefault(hwndDlg);
+ ComboBoxAddStringUtf(GetDlgItem(hwndDlg, IDC_KEYSERVER), _T("subkeys.pgp.net"), 0);
+ ComboBoxAddStringUtf(GetDlgItem(hwndDlg, IDC_KEYSERVER), _T("keys.gnupg.net"), 0);
+ return TRUE;
+ }
+
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_IMPORT:
+ {
+ string out;
+ DWORD code;
+ wstring cmd = _T(" --keyserver \"");
+ TCHAR *server= new TCHAR [128];
+ GetDlgItemText(hwndDlg, IDC_KEYSERVER, server, 128);
+ cmd += server;
+ delete [] server;
+ cmd += _T("\" --recv-keys ");
+// char *tmp = UniGetContactSettingUtf(hContact, szGPGModuleName, "KeyID_Prescense", "");
+// TCHAR *tmp2 = mir_a2t(tmp);
+// mir_free(tmp);
+ cmd += toUTF16(hcontact_data[hContact].key_in_prescense);
+// mir_free(tmp2);
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::seconds(10)))
+ {
+ gpg_thread.~thread();
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ }
+ MessageBoxA(0, out.c_str(), "GPG output", MB_OK);
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+/* switch (((LPNMHDR)lParam)->code)
+ {
+ default:
+ break;
+ } */
+ }
+ break;
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+ case WM_DESTROY:
+ {
+ GetWindowRect(hwndDlg, &import_key_rect);
+ DBWriteContactSettingDword(NULL, szGPGModuleName, "ImportKeyWindowX", import_key_rect.left);
+ DBWriteContactSettingDword(NULL, szGPGModuleName, "ImportKeyWindowY", import_key_rect.top);
+ }
+ break;
+
+ }
+ return FALSE;
+}
+
+
+extern HINSTANCE hInst;
+
+
+void ShowFirstRunDialog()
+{
+ if (hwndFirstRun == NULL)
+ {
+ hwndFirstRun = CreateDialog(hInst, MAKEINTRESOURCE(IDD_FIRST_RUN), NULL, (DLGPROC)DlgProcFirstRun);
+ }
+ SetForegroundWindow(hwndFirstRun);
+}
+
+
+void ShowSetDirsDialog()
+{
+ if (hwndSetDirs == NULL)
+ {
+ hwndSetDirs = CreateDialog(hInst, MAKEINTRESOURCE(IDD_BIN_PATH), NULL, (DLGPROC)DlgProcGpgBinOpts);
+ }
+ SetForegroundWindow(hwndSetDirs);
+}
+
+void ShowNewKeyDialog()
+{
+ hwndNewKey = CreateDialog(hInst, MAKEINTRESOURCE(IDD_NEW_KEY), NULL, (DLGPROC)DlgProcNewKeyDialog);
+ SetForegroundWindow(hwndNewKey);
+}
+
+void ShowKeyGenDialog()
+{
+ if (hwndKeyGen == NULL)
+ {
+ hwndKeyGen = CreateDialog(hInst, MAKEINTRESOURCE(IDD_KEY_GEN), NULL, (DLGPROC)DlgProcKeyGenDialog);
+ }
+ SetForegroundWindow(hwndKeyGen);
+}
+
+void ShowSelectExistingKeyDialog()
+{
+ if (hwndSelectExistingKey == NULL)
+ {
+ hwndSelectExistingKey = CreateDialog(hInst, MAKEINTRESOURCE(IDD_LOAD_EXISTING_KEY), NULL, (DLGPROC)DlgProcLoadExistingKey);
+ }
+ SetForegroundWindow(hwndSelectExistingKey);
+}
+
+void ShowImportKeyDialog()
+{
+ CreateDialog(hInst, MAKEINTRESOURCE(IDD_IMPORT_KEY), NULL, (DLGPROC)DlgProcImportKeyDialog);
+}
+
+
+
+
+void FirstRun()
+{
+ DWORD pid = 0;
+ if(!DBGetContactSettingByte(NULL, szGPGModuleName, "FirstRun", 1))
+ return;
+ ShowSetDirsDialog();
+}
+
+void InitCheck()
+{
+ {//parse gpg output
+ gpg_valid = isGPGValid();
+ bool home_dir_access = false, temp_access = false;
+ TCHAR *home_dir = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T(""));
+ std::wstring test_path = home_dir;
+ mir_free(home_dir);
+ test_path += _T("/");
+ test_path += toUTF16(get_random(13));
+ wfstream test_file;
+ test_file.open(test_path, std::ios::trunc | std::ios::out);
+ if(test_file.is_open() && test_file.good())
+ {
+ test_file<<_T("access_test\n");
+ if(test_file.good())
+ home_dir_access = true;
+ test_file.close();
+ DeleteFile(test_path.c_str());
+ }
+ home_dir = _tgetenv(_T("TEMP"));
+ test_path = home_dir;
+ test_path += _T("/");
+ test_path += toUTF16(get_random(13));
+ test_file.open(test_path, std::ios::trunc | std::ios::out);
+ if(test_file.is_open() && test_file.good())
+ {
+ test_file<<_T("access_test\n");
+ if(test_file.good())
+ temp_access = true;
+ test_file.close();
+ DeleteFile(test_path.c_str());
+ }
+ if(!home_dir_access || !temp_access || !gpg_valid)
+ {
+ char buf[4096];
+ strcpy(buf, gpg_valid?Translate("GPG binary is set and valid (this is good).\n"):Translate("GPG binary unset or invalid (plugin will not work).\n"));
+ strcat(buf, home_dir_access?Translate("Home dir write access granted (this is good).\n"):Translate("Home dir have not write access (plugin most probably will not work).\n"));
+ strcat(buf, temp_access?Translate("Temp dir write access granted (this is good).\n"):Translate("Temp dir have not write access (plugin should work, but may have some problems, filetransfers will not work)."));
+ if(!gpg_valid)
+ strcat(buf, Translate("\nGPG will be disabled until you solve this problems"));
+ MessageBoxA(0, buf, Translate("GPG plugin problems"), MB_OK);
+ }
+ if(!gpg_valid)
+ return;
+ gpg_keyexist = isGPGKeyExist();
+ string out;
+ DWORD code;
+ pxResult result;
+ wstring::size_type p = 0, p2 = 0, stop = 0;
+ {
+ gpg_execution_params params;
+ wstring cmd = _T("--batch --list-secret-keys");
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::seconds(10)))
+ {
+ gpg_thread.~thread();
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ return;
+ }
+ if(result == pxNotFound)
+ return;
+ }
+ home_dir = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T(""));
+ wstring tmp_dir = home_dir;
+ mir_free(home_dir);
+ tmp_dir += _T("\\tmp");
+ _wmkdir(tmp_dir.c_str());
+ string question = Translate("Your secret key whith id: ");
+ char *keyid = UniGetContactSettingUtf(NULL, szGPGModuleName, "KeyID", "");
+ char *key = UniGetContactSettingUtf(NULL, szGPGModuleName, "GPGPubKey", "");
+ void ShowFirstRunDialog();
+ if(!DBGetContactSettingByte(NULL, szGPGModuleName, "FirstRun", 1) && (!keyid[0] || !key[0]))
+ {
+ question = Translate("You have not set public key for gpg, it's recommended to do it.\nDo you want to do it now ?");
+ if(MessageBoxA(0, question.c_str(), Translate("Own public key warning"), MB_YESNO) == IDYES)
+ ShowFirstRunDialog();
+ }
+ if(out.find(keyid) == string::npos)
+ {
+ question += keyid;
+ question += Translate(" deleted from gpg secret keyring\nDo you want to set another key ?");
+ if(MessageBoxA(0, question.c_str(), Translate("Own secret key warning"), MB_YESNO) == IDYES)
+ ShowFirstRunDialog();
+ }
+ mir_free(keyid);
+ mir_free(key);
+ }
+ {
+ TCHAR *path = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T(""));
+ DWORD dwFileAttr = GetFileAttributes(path);
+ if (dwFileAttr != INVALID_FILE_ATTRIBUTES)
+ {
+ dwFileAttr &=~ FILE_ATTRIBUTE_READONLY;
+ SetFileAttributes(path, dwFileAttr);
+ }
+ mir_free(path);
+ }
+ extern bool bAutoExchange;
+ if(bAutoExchange)
+ {
+ int count = 0;
+ PROTOACCOUNT **accounts;
+ ProtoEnumAccounts(&count, &accounts);
+ ICQ_CUSTOMCAP cap;
+ cap.cbSize = sizeof(ICQ_CUSTOMCAP);
+ cap.hIcon = 0;
+ strcpy(cap.name, "GPG Key AutoExchange");
+ strcpy(cap.caps, "GPG AutoExchange");
+
+ for(int i = 0; i < count; i++)
+ {
+ char svc[64];
+ strcpy(svc, accounts[i]->szProtoName);
+ strcat(svc, PS_ICQ_ADDCAPABILITY);
+ if(ServiceExists(svc))
+ CallService(svc, 0, (LPARAM)&cap);
+ }
+ }
+}
+
+void ImportKey()
+{
+ extern wstring new_key;
+ extern HANDLE new_key_hcnt;
+ extern boost::mutex new_key_hcnt_mutex;
+ HANDLE hContact = new_key_hcnt;
+ new_key_hcnt_mutex.unlock();
+ bool for_all_sub = false;
+ if(metaIsProtoMetaContacts(hContact))
+ if(MessageBox(0, TranslateT("Do you want load key for all subcontacts ?"), TranslateT("Metacontact detected"), MB_YESNO) == IDYES)
+ for_all_sub = true;
+ if(metaIsProtoMetaContacts(hContact))
+ {
+ HANDLE hcnt = NULL;
+ if(for_all_sub)
+ {
+ int count = metaGetContactsNum(hContact);
+ for(int i = 0; i < count; i++)
+ {
+ hcnt = metaGetSubcontact(hContact, i);
+ if(hcnt)
+ DBWriteContactSettingTString(hcnt, szGPGModuleName, "GPGPubKey", new_key.c_str());
+ }
+ }
+ else
+ DBWriteContactSettingTString(metaGetMostOnline(hContact), szGPGModuleName, "GPGPubKey", new_key.c_str());
+ }
+ else
+ DBWriteContactSettingTString(hContact, szGPGModuleName, "GPGPubKey", new_key.c_str());
+ new_key.clear();
+ { //gpg execute block
+ wstring cmd;
+ TCHAR tmp2[MAX_PATH] = {0};
+ TCHAR *ptmp;
+ string output;
+ DWORD exitcode;
+ {
+ ptmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T(""));
+ _tcscpy(tmp2, ptmp);
+ mir_free(ptmp);
+ _tcscat(tmp2, _T("\\"));
+ _tcscat(tmp2, _T("temporary_exported.asc"));
+ DeleteFile(tmp2);
+ wfstream f(tmp2, std::ios::out);
+ if(metaIsProtoMetaContacts(hContact))
+ ptmp = UniGetContactSettingUtf(metaGetMostOnline(hContact), szGPGModuleName, "GPGPubKey", _T(""));
+ else
+ ptmp = UniGetContactSettingUtf(hContact, szGPGModuleName, "GPGPubKey", _T(""));
+ wstring new_key = ptmp;
+ mir_free(ptmp);
+ f<<new_key.c_str();
+ f.close();
+ cmd += _T(" --batch ");
+ cmd += _T(" --import \"");
+ cmd += tmp2;
+ cmd += _T("\"");
+ }
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &output;
+ params.code = &exitcode;
+ params.result = &result;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::seconds(10)))
+ {
+ gpg_thread.~thread();
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ return;
+ }
+ if(result == pxNotFound)
+ return;
+ {
+ if(metaIsProtoMetaContacts(hContact))
+ {
+ HANDLE hcnt = NULL;
+ if(for_all_sub)
+ {
+ int count = metaGetContactsNum(hContact);
+ for(int i = 0; i < count; i++)
+ {
+ hcnt = metaGetSubcontact(hContact, i);
+ if(hcnt)
+ {
+ char *tmp = NULL;
+ string::size_type s = output.find("gpg: key ") + strlen("gpg: key ");
+ string::size_type s2 = output.find(":", s);
+ DBWriteContactSettingString(hcnt, szGPGModuleName, "KeyID", output.substr(s,s2-s).c_str());
+ s2+=2;
+ s = output.find("“", s2);
+ if(s == string::npos)
+ {
+ s = output.find("\"", s2);
+ s += 1;
+ }
+ else
+ s += 3;
+ if((s2 = output.find("(", s)) == string::npos)
+ s2 = output.find("<", s);
+ else if(s2 > output.find("<", s))
+ s2 = output.find("<", s);
+ tmp = new char [output.substr(s,s2-s-1).length()+1];
+ strcpy(tmp, output.substr(s,s2-s-1).c_str());
+ mir_utf8decode(tmp, 0);
+ DBWriteContactSettingString(hcnt, szGPGModuleName, "KeyMainName", tmp);
+ mir_free(tmp);
+ if((s = output.find(")", s2)) == string::npos)
+ s = output.find(">", s2);
+ else if(s > output.find(">", s2))
+ s = output.find(">", s2);
+ s2++;
+ if(output[s] == ')')
+ {
+ tmp = new char [output.substr(s2,s-s2).length()+1];
+ strcpy(tmp, output.substr(s2,s-s2).c_str());
+ mir_utf8decode(tmp, 0);
+ DBWriteContactSettingString(hcnt, szGPGModuleName, "KeyComment", tmp);
+ mir_free(tmp);
+ s+=3;
+ s2 = output.find(">", s);
+ tmp = new char [output.substr(s,s2-s).length()+1];
+ strcpy(tmp, output.substr(s,s2-s).c_str());
+ mir_utf8decode(tmp, 0);
+ DBWriteContactSettingString(hcnt, szGPGModuleName, "KeyMainEmail", tmp);
+ mir_free(tmp);
+ }
+ else
+ {
+ tmp = new char [output.substr(s2,s-s2).length()+1];
+ strcpy(tmp, output.substr(s2,s-s2).c_str());
+ mir_utf8decode(tmp, 0);
+ DBWriteContactSettingString(hcnt, szGPGModuleName, "KeyMainEmail", output.substr(s2,s-s2).c_str());
+ mir_free(tmp);
+ }
+ DBDeleteContactSetting(hcnt, szGPGModuleName, "bAlwatsTrust");
+ }
+ }
+ }
+ else
+ {
+ char *tmp = NULL;
+ string::size_type s = output.find("gpg: key ") + strlen("gpg: key ");
+ string::size_type s2 = output.find(":", s);
+ DBWriteContactSettingString(metaGetMostOnline(hContact), szGPGModuleName, "KeyID", output.substr(s,s2-s).c_str());
+ s2+=2;
+ s = output.find("“", s2);
+ if(s == string::npos)
+ {
+ s = output.find("\"", s2);
+ s += 1;
+ }
+ else
+ s += 3;
+ if((s2 = output.find("(", s)) == string::npos)
+ s2 = output.find("<", s);
+ else if(s2 > output.find("<", s))
+ s2 = output.find("<", s);
+ tmp = new char [output.substr(s,s2-s-1).length()+1];
+ strcpy(tmp, output.substr(s,s2-s-1).c_str());
+ mir_utf8decode(tmp, 0);
+ DBWriteContactSettingString(metaGetMostOnline(hContact), szGPGModuleName, "KeyMainName", tmp);
+ mir_free(tmp);
+ if((s = output.find(")", s2)) == string::npos)
+ s = output.find(">", s2);
+ else if(s > output.find(">", s2))
+ s = output.find(">", s2);
+ s2++;
+ if(output[s] == ')')
+ {
+ tmp = new char [output.substr(s2,s-s2).length()+1];
+ strcpy(tmp, output.substr(s2,s-s2).c_str());
+ mir_utf8decode(tmp, 0);
+ DBWriteContactSettingString(metaGetMostOnline(hContact), szGPGModuleName, "KeyComment", tmp);
+ mir_free(tmp);
+ s+=3;
+ s2 = output.find(">", s);
+ tmp = new char [output.substr(s,s2-s).length()+1];
+ strcpy(tmp, output.substr(s,s2-s).c_str());
+ mir_utf8decode(tmp, 0);
+ DBWriteContactSettingString(metaGetMostOnline(hContact), szGPGModuleName, "KeyMainEmail", tmp);
+ mir_free(tmp);
+ }
+ else
+ {
+ tmp = new char [output.substr(s2,s-s2).length()+1];
+ strcpy(tmp, output.substr(s2,s-s2).c_str());
+ mir_utf8decode(tmp, 0);
+ DBWriteContactSettingString(metaGetMostOnline(hContact), szGPGModuleName, "KeyMainEmail", output.substr(s2,s-s2).c_str());
+ mir_free(tmp);
+ }
+ DBDeleteContactSetting(metaGetMostOnline(hContact), szGPGModuleName, "bAlwatsTrust");
+ }
+ }
+ else
+ {
+ char *tmp = NULL;
+ string::size_type s = output.find("gpg: key ") + strlen("gpg: key ");
+ string::size_type s2 = output.find(":", s);
+ DBWriteContactSettingString(hContact, szGPGModuleName, "KeyID", output.substr(s,s2-s).c_str());
+ s2+=2;
+ s = output.find("“", s2);
+ if(s == string::npos)
+ {
+ s = output.find("\"", s2);
+ s += 1;
+ }
+ else
+ s += 3;
+ if((s2 = output.find("(", s)) == string::npos)
+ s2 = output.find("<", s);
+ else if(s2 > output.find("<", s))
+ s2 = output.find("<", s);
+ tmp = new char [output.substr(s,s2-s-1).length()+1];
+ strcpy(tmp, output.substr(s,s2-s-1).c_str());
+ mir_utf8decode(tmp, 0);
+ DBWriteContactSettingString(hContact, szGPGModuleName, "KeyMainName", tmp);
+ mir_free(tmp);
+ if((s = output.find(")", s2)) == string::npos)
+ s = output.find(">", s2);
+ else if(s > output.find(">", s2))
+ s = output.find(">", s2);
+ s2++;
+ if(output[s] == ')')
+ {
+ tmp = new char [output.substr(s2,s-s2).length()+1];
+ strcpy(tmp, output.substr(s2,s-s2).c_str());
+ mir_utf8decode(tmp, 0);
+ DBWriteContactSettingString(hContact, szGPGModuleName, "KeyComment", tmp);
+ mir_free(tmp);
+ s+=3;
+ s2 = output.find(">", s);
+ tmp = new char [output.substr(s,s2-s).length()+1];
+ strcpy(tmp, output.substr(s,s2-s).c_str());
+ mir_utf8decode(tmp, 0);
+ DBWriteContactSettingString(hContact, szGPGModuleName, "KeyMainEmail", tmp);
+ mir_free(tmp);
+ }
+ else
+ {
+ tmp = new char [output.substr(s2,s-s2).length()+1];
+ strcpy(tmp, output.substr(s2,s-s2).c_str());
+ mir_utf8decode(tmp, 0);
+ DBWriteContactSettingString(hContact, szGPGModuleName, "KeyMainEmail", output.substr(s2,s-s2).c_str());
+ mir_free(tmp);
+ }
+ DBDeleteContactSetting(hContact, szGPGModuleName, "bAlwatsTrust");
+ }
+ }
+ ptmp = mir_wstrdup(toUTF16(output).c_str());
+ MessageBox(0, ptmp, _T(""), MB_OK);
+ mir_free(ptmp);
+ DeleteFile(tmp2);
+ }
+} \ No newline at end of file
diff --git a/plugins/New_GPG/src/main.h b/plugins/New_GPG/src/main.h
new file mode 100755
index 0000000000..23627a415a
--- /dev/null
+++ b/plugins/New_GPG/src/main.h
@@ -0,0 +1,31 @@
+// Copyright © 2010-2012 sss
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#ifndef MAIN_H
+#define MAIN_H
+
+struct contact_data
+{
+ list<string> msgs_to_send, msgs_to_pass;
+ string key_in_prescense;
+};
+
+extern std::map<HANDLE, contact_data> hcontact_data;
+extern bool bAutoExchange;
+extern RECT key_from_keyserver_rect, firstrun_rect, new_key_rect, key_gen_rect, load_key_rect, import_key_rect, key_password_rect, load_existing_key_rect;
+
+#endif
+
+
diff --git a/plugins/New_GPG/src/messages.cpp b/plugins/New_GPG/src/messages.cpp
new file mode 100755
index 0000000000..ba9a36c29c
--- /dev/null
+++ b/plugins/New_GPG/src/messages.cpp
@@ -0,0 +1,1058 @@
+// Copyright © 2010-2012 sss
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include "commonheaders.h"
+
+
+wstring new_key;
+HANDLE new_key_hcnt = NULL;
+boost::mutex new_key_hcnt_mutex;
+bool _terminate = false;
+int returnNoError(HANDLE hContact);
+
+std::list<HANDLE> sent_msgs;
+
+int RecvMsgSvc_func(HANDLE hContact, std::wstring str, char *msg, DWORD flags, DWORD timestamp)
+{
+ DWORD dbflags = DBEF_UTF;
+ { //check for gpg related data
+ wstring::size_type s1 = wstring::npos, s2 = wstring::npos;
+
+ s1 = str.find(_T("-----BEGIN PGP MESSAGE-----"));
+ s2 = str.find(_T("-----END PGP MESSAGE-----"));
+ if((s2 != wstring::npos) && (s1 != wstring::npos))
+ { //this is generic encrypted data block
+ void setSrmmIcon(HANDLE);
+ void setClistIcon(HANDLE);
+ bool isContactHaveKey(HANDLE hContact);
+ if(!isContactSecured(hContact))
+ {
+ debuglog<<time_str()<<": info: "<<"received message from: "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)<<" with turned off encryption\n";
+ if(MessageBox(0, _T("We received encrypted message from contact with encryption turned off.\nDo you want turn on encryption for this contact ?"), _T("Warning"), MB_YESNO) == IDYES)
+ {
+ if(!isContactHaveKey(hContact))
+ {
+ void ShowLoadPublicKeyDialog();
+ extern map<int, HANDLE> user_data;
+ extern int item_num;
+ item_num = 0; //black magic here
+ user_data[1] = hContact;
+ ShowLoadPublicKeyDialog();
+ }
+ else
+ {
+ DBWriteContactSettingByte(metaIsProtoMetaContacts(hContact)?metaGetMostOnline(hContact):hContact, szGPGModuleName, "GPGEncryption", 1);
+ setSrmmIcon(hContact);
+ setClistIcon(hContact);
+ }
+ if(isContactHaveKey(hContact))
+ {
+ DBWriteContactSettingByte(metaIsProtoMetaContacts(hContact)?metaGetMostOnline(hContact):hContact, szGPGModuleName, "GPGEncryption", 1);
+ setSrmmIcon(hContact);
+ setClistIcon(hContact);
+ }
+ }
+ else if(MessageBox(0, _T("Do you want try to decrypt encrypted message ?"), _T("Warning"), MB_YESNO) == IDNO)
+ {
+
+ HistoryLog(hContact, db_event(msg, timestamp, 0, dbflags));
+ return 0;
+ }
+ }
+ {
+ wstring::size_type p = 0;
+ while((p = str.find(_T("\r"), p)) != wstring::npos)
+ str.erase(p, 1);
+ }
+ s2 += _tcslen(_T("-----END PGP MESSAGE-----"));
+ char *tmp = mir_t2a(str.substr(s1,s2-s1).c_str());
+ TCHAR *tmp2 = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T(""));
+ wstring path = tmp2;
+ wstring encfile = toUTF16(get_random(10));
+ wstring decfile = toUTF16(get_random(10));
+ path.append(_T("\\tmp\\"));
+ path.append(encfile);
+ DeleteFile(path.c_str());
+ fstream f(path.c_str(), std::ios::out);
+ while(!f.is_open())
+ f.open(path.c_str(), std::ios::out);
+ f<<tmp;
+ mir_free(tmp);
+ f.close();
+ {
+ extern TCHAR *password;
+ string out;
+ DWORD code;
+ wstring cmd;
+ cmd += _T("--batch ");
+ {
+ char *inkeyid = UniGetContactSettingUtf(metaIsProtoMetaContacts(hContact)?metaGetMostOnline(hContact):hContact, szGPGModuleName, "InKeyID", "");
+ TCHAR *pass = NULL;
+ if(inkeyid[0])
+ {
+ string dbsetting = "szKey_";
+ dbsetting += inkeyid;
+ dbsetting += "_Password";
+ pass = UniGetContactSettingUtf(NULL, szGPGModuleName, dbsetting.c_str(), _T(""));
+ if(pass[0])
+ debuglog<<time_str()<<": info: found password in database for key id: "<<inkeyid<<", trying to decrypt message from "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)<<" with password\n";
+ }
+ else
+ {
+ pass = UniGetContactSettingUtf(NULL, szGPGModuleName, "szKeyPassword", _T(""));
+ if(pass[0])
+ debuglog<<time_str()<<": info: found password for all keys in database, trying to decrypt message from "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)<<" with password\n";
+ }
+ if(pass && pass[0])
+ {
+ cmd += _T("--passphrase \"");
+ cmd += pass;
+ cmd += _T("\" ");
+ }
+ else if(password && password[0])
+ {
+ debuglog<<time_str()<<": info: found password in memory, trying to decrypt message from "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)<<" with password\n";
+ cmd += _T("--passphrase \"");
+ cmd += password;
+ cmd += _T("\" ");
+ }
+ else
+ debuglog<<time_str()<<": info: passwords not found in database or memory, trying to decrypt message from "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)<<" with out password\n";
+ mir_free(pass);
+ mir_free(inkeyid);
+ }
+ {
+ wstring path = tmp2;
+ path += _T("\\tmp\\");
+ path += decfile;
+ DeleteFile(path.c_str());
+ }
+ cmd += _T("--output \"");
+ cmd += tmp2;
+ cmd += _T("\\tmp\\");
+ cmd += decfile;
+ cmd += _T("\"");
+ cmd += _T(" -d -a \"");
+ cmd += path;
+ cmd += _T("\"");
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ boost::thread *gpg_thread = new boost::thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread->timed_join(boost::posix_time::seconds(10)))
+ {
+ delete gpg_thread;
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ DeleteFile(path.c_str());
+ HistoryLog(hContact, db_event(msg, timestamp, 0, dbflags));
+ BYTE enc = DBGetContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 0);
+ DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 0);
+ CallContactService(hContact, PSS_MESSAGE, (WPARAM)PREF_UTF, (LPARAM)"Unable to decrypt PGP encrypted message");
+ HistoryLog(hContact, db_event("Error message sent", 0, 0, DBEF_SENT));
+ DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", enc);
+ return 0;
+ }
+ if(result == pxNotFound)
+ {
+ DeleteFile(path.c_str());
+ HistoryLog(hContact, db_event(msg, timestamp, 0, dbflags));
+ return 0;
+ }
+ //TODO: check gpg output for errors
+ _terminate = false;
+ while(out.find("public key decryption failed: bad passphrase") != string::npos)
+ {
+ debuglog<<time_str()<<": info: failed to decrypt messaage from "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)<<" password needed, trying to get one\n";
+ if(_terminate)
+ {
+ BYTE enc = DBGetContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 0);
+ DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 0);
+ CallContactService(hContact, PSS_MESSAGE, (WPARAM)PREF_UTF, (LPARAM)"Unable to decrypt PGP encrypted message");
+ HistoryLog(hContact, db_event("Error message sent", 0, 0, DBEF_SENT));
+ DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", enc);
+ break;
+ }
+ { //save inkey id
+ string::size_type s = out.find(" encrypted with ");
+ s = out.find(" ID ", s);
+ s += strlen(" ID ");
+ string::size_type s2 = out.find(",",s);
+ DBWriteContactSettingString(metaIsProtoMetaContacts(hContact)?metaGetMostOnline(hContact):hContact, szGPGModuleName, "InKeyID", out.substr(s, s2-s).c_str());
+ }
+ void ShowLoadKeyPasswordWindow();
+ new_key_hcnt_mutex.lock();
+ new_key_hcnt = hContact;
+ ShowLoadKeyPasswordWindow();
+ wstring cmd2 = cmd;
+ if(password)
+ {
+ debuglog<<time_str()<<": info: found password in memory, trying to decrypt message from "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)<<"\n";
+ wstring tmp = _T("--passphrase \"");
+ tmp += password;
+ tmp += _T("\" ");
+ cmd2.insert(0, tmp);
+ }
+ out.clear();
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd2;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ gpg_thread = gpg_thread = new boost::thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread->timed_join(boost::posix_time::seconds(10)))
+ {
+ delete gpg_thread;
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ DeleteFile(path.c_str());
+ HistoryLog(hContact, db_event(msg, timestamp, 0, dbflags));
+ BYTE enc = DBGetContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 0);
+ DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 0);
+ CallContactService(hContact, PSS_MESSAGE, (WPARAM)PREF_UTF, (LPARAM)"Unable to decrypt PGP encrypted message");
+ HistoryLog(hContact, db_event("Error message sent", 0, 0, DBEF_SENT));
+ DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", enc);
+ return 0;
+ }
+ if(result == pxNotFound)
+ {
+ DeleteFile(path.c_str());
+ HistoryLog(hContact, db_event(msg, timestamp, 0, dbflags));
+ return 0;
+ }
+ //TODO: check gpg output for errors
+ }
+ out.clear();
+ gpg_thread = new boost::thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread->timed_join(boost::posix_time::seconds(10)))
+ {
+ delete gpg_thread;
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ DeleteFile(path.c_str());
+ HistoryLog(hContact, db_event(msg, timestamp, 0, dbflags));
+ BYTE enc = DBGetContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 0);
+ DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 0);
+ CallContactService(hContact, PSS_MESSAGE, (WPARAM)PREF_UTF, (LPARAM)"Unable to decrypt PGP encrypted message");
+ HistoryLog(hContact, db_event("Error message sent", 0, 0, DBEF_SENT));
+ DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", enc);
+ return 0;
+ }
+ if(result == pxNotFound)
+ {
+ DeleteFile(path.c_str());
+ HistoryLog(hContact, db_event(msg, timestamp, 0, dbflags));
+ }
+ //TODO: check gpg output for errors
+ {
+ wstring tmp = tmp2;
+ tmp += _T("\\tmp\\");
+ tmp += encfile;
+ DeleteFile(tmp.c_str());
+ }
+ {
+ wstring tmp = tmp2;
+ tmp += _T("\\tmp\\");
+ tmp += decfile;
+ if(_waccess(tmp.c_str(), 0) == -1)
+ {
+ if(errno == ENOENT)
+ {
+ string str = msg;
+ str.insert(0, "Received unencrypted message:\n");
+ debuglog<<time_str()<<": info: Failed to decrypt GPG encrypted message.\n";
+ char *tmp = new char [str.length()+1];
+ strcpy(tmp, str.c_str());
+ HistoryLog(hContact, db_event(msg, timestamp, 0, dbflags));
+ BYTE enc = DBGetContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 0);
+ DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 0);
+ CallContactService(hContact, PSS_MESSAGE, (WPARAM)PREF_UTF, (LPARAM)"Unable to decrypt PGP encrypted message");
+ HistoryLog(hContact, db_event("Error message sent", 0, 0, DBEF_SENT));
+ DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", enc);
+ mir_free(tmp);
+ return 0;
+ }
+ }
+ }
+ str.clear();
+ {
+ wstring path = tmp2;
+ mir_free(tmp2);
+ path += _T("\\tmp\\");
+ path += decfile;
+ fstream f(path.c_str(), std::ios::in | std::ios::ate | std::ios::binary);
+ if(f.is_open())
+ {
+ std::wifstream::pos_type size = f.tellg();
+ char *tmp = new char [(std::ifstream::pos_type)size+(std::ifstream::pos_type)1];
+ f.seekg(0, std::ios::beg);
+ f.read(tmp, size);
+ tmp[size] = '\0';
+ toUTF16(tmp);
+ str.append(toUTF16(tmp));
+ delete [] tmp;
+ f.close();
+ DeleteFile(path.c_str());
+ }
+ if(str.empty())
+ {
+ string str = msg;
+ str.insert(0, "Failed to decrypt GPG encrypted message.\nMessage body for manual decryption:\n");
+ debuglog<<time_str()<<": info: Failed to decrypt GPG encrypted message.\n";
+ char *tmp = mir_strdup(str.c_str());
+ HistoryLog(hContact, db_event(msg, timestamp, 0, dbflags));
+ BYTE enc = DBGetContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 0);
+ DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 0);
+ CallContactService(hContact, PSS_MESSAGE, (WPARAM)PREF_UTF, (LPARAM)"Unable to decrypt PGP encrypted message");
+ HistoryLog(hContact, db_event("Error message sent", 0, 0, DBEF_SENT));
+ DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", enc);
+ mir_free(tmp);
+ return 0;
+ }
+ else
+ {
+ if(bAppendTags)
+ {
+ str.insert(0, inopentag);
+ str.append(inclosetag);
+ }
+ if(metaIsSubcontact(hContact))
+ {
+ char *msg = mir_strdup(toUTF8(str).c_str());
+ HistoryLog(hContact, db_event(msg, timestamp, 0, dbflags|DBEF_READ));
+ HistoryLog(metaGetContact(hContact), db_event(msg, timestamp, 0, dbflags));
+ mir_free(msg);
+ return 0;
+ }
+ char *tmp = mir_strdup(toUTF8(str).c_str());
+ HistoryLog(hContact, db_event(tmp, timestamp, 0, dbflags));
+ mir_free(tmp);
+ return 0;
+ }
+ }
+ }
+ }
+ }
+ if(DBGetContactSettingByte(metaIsProtoMetaContacts(hContact)?metaGetMostOnline(hContact):hContact, szGPGModuleName, "GPGEncryption", 0))
+ {
+ if(metaIsSubcontact(hContact))
+ {
+ HistoryLog(hContact, db_event(msg, timestamp, 0, dbflags|DBEF_READ));
+ HistoryLog(metaGetContact(hContact), db_event(msg, timestamp, 0, dbflags));
+ return 0;
+ }
+ HistoryLog(hContact, db_event(msg, timestamp, 0, dbflags|DBEF_READ));
+ return 0;
+ }
+ HistoryLog(hContact, db_event(msg, timestamp, 0, dbflags));
+ return 0;
+}
+
+int RecvMsgSvc(WPARAM w, LPARAM l)
+{
+ CCSDATA *ccs = (CCSDATA*)l;
+ if (!ccs)
+ return CallService(MS_PROTO_CHAINRECV, w, l);
+ PROTORECVEVENT *pre = (PROTORECVEVENT*)(ccs->lParam);
+ if (!pre)
+ return CallService(MS_PROTO_CHAINRECV, w, l);
+ char *msg = pre->szMessage;
+ if (!msg)
+ return CallService(MS_PROTO_CHAINRECV, w, l);
+ wstring str = toUTF16(msg);
+ wstring::size_type s1 = wstring::npos, s2 = wstring::npos;
+ DWORD dbflags = DBEF_UTF;
+ if((str.find(_T("-----PGP KEY RESPONSE-----")) != wstring::npos) && !metaIsProtoMetaContacts(ccs->hContact))
+ {
+ s2 = str.find(_T("-----END PGP PUBLIC KEY BLOCK-----"));
+ s1 = str.find(_T("-----BEGIN PGP PUBLIC KEY BLOCK-----"));
+ if(s1 != wstring::npos && s2 != wstring::npos)
+ {
+ s2 += _tcslen(_T("-----END PGP PUBLIC KEY BLOCK-----"));
+ DBWriteContactSettingTString(ccs->hContact, szGPGModuleName, "GPGPubKey", str.substr(s1,s2-s1).c_str());
+ DBWriteContactSettingByte(ccs->hContact, szGPGModuleName, "GPGEncryption", 1);
+ { //gpg execute block
+ wstring cmd;
+ TCHAR tmp2[MAX_PATH] = {0};
+ TCHAR *ptmp;
+ string output;
+ DWORD exitcode;
+ {
+ ptmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T(""));
+ _tcscpy(tmp2, ptmp);
+ mir_free(ptmp);
+ _tcscat(tmp2, _T("\\"));
+ _tcscat(tmp2, _T("temporary_exported.asc"));
+ DeleteFile(tmp2);
+ wfstream f(tmp2, std::ios::out);
+ while(!f.is_open())
+ f.open(tmp2, std::ios::out);
+ ptmp = UniGetContactSettingUtf(ccs->hContact, szGPGModuleName, "GPGPubKey", _T(""));
+ wstring new_key = ptmp;
+ mir_free(ptmp);
+ f<<new_key.c_str();
+ f.close();
+ cmd += _T(" --batch ");
+ cmd += _T(" --import \"");
+ cmd += tmp2;
+ cmd += _T("\"");
+ }
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &output;
+ params.code = &exitcode;
+ params.result = &result;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::seconds(10)))
+ {
+ gpg_thread.~thread();
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ return 1;
+ }
+ if(result == pxNotFound)
+ return 1;
+ //TODO: check gpg output for errors
+ {
+ char *tmp = NULL;
+ string::size_type s = output.find("gpg: key ") + strlen("gpg: key ");
+ string::size_type s2 = output.find(":", s);
+ DBWriteContactSettingString(ccs->hContact, szGPGModuleName, "KeyID", output.substr(s,s2-s).c_str());
+ s2+=2;
+ s = output.find("“", s2);
+ if(s == string::npos)
+ {
+ s = output.find("\"", s2);
+ s += 1;
+ }
+ else
+ s += 3;
+ if((s2 = output.find("(", s)) == string::npos)
+ s2 = output.find("<", s);
+ else if(s2 > output.find("<", s))
+ s2 = output.find("<", s);
+ tmp = (char*)mir_alloc(output.substr(s,s2-s-1).length()+1);
+ strcpy(tmp, output.substr(s,s2-s-1).c_str());
+ mir_utf8decode(tmp, 0);
+ DBWriteContactSettingString(ccs->hContact, szGPGModuleName, "KeyMainName", tmp);
+ mir_free(tmp);
+ if((s = output.find(")", s2)) == string::npos)
+ s = output.find(">", s2);
+ else if(s > output.find(">", s2))
+ s = output.find(">", s2);
+ s2++;
+ if(output[s] == ')')
+ {
+ tmp = (char*)mir_alloc(output.substr(s2,s-s2).length()+1);
+ strcpy(tmp, output.substr(s2,s-s2).c_str());
+ mir_utf8decode(tmp, 0);
+ DBWriteContactSettingString(ccs->hContact, szGPGModuleName, "KeyComment", tmp);
+ mir_free(tmp);
+ s+=3;
+ s2 = output.find(">", s);
+ tmp = (char*)mir_alloc(output.substr(s,s2-s).length()+1);
+ strcpy(tmp, output.substr(s,s2-s).c_str());
+ mir_utf8decode(tmp, 0);
+ DBWriteContactSettingString(ccs->hContact, szGPGModuleName, "KeyMainEmail", tmp);
+ mir_free(tmp);
+ }
+ else
+ {
+ tmp = (char*)mir_alloc(output.substr(s2,s-s2).length()+1);
+ strcpy(tmp, output.substr(s2,s-s2).c_str());
+ mir_utf8decode(tmp, 0);
+ DBWriteContactSettingString(ccs->hContact, szGPGModuleName, "KeyMainEmail", output.substr(s2,s-s2).c_str());
+ mir_free(tmp);
+ }
+ DBWriteContactSettingByte(ccs->hContact, szGPGModuleName, "bAlwatsTrust", 1);
+ void setSrmmIcon(HANDLE);
+ void setClistIcon(HANDLE);
+ setSrmmIcon(ccs->hContact);
+ setClistIcon(ccs->hContact);
+ if(metaIsSubcontact(ccs->hContact))
+ {
+ setSrmmIcon(metaGetContact(ccs->hContact));
+ setClistIcon(metaGetContact(ccs->hContact));
+ HistoryLog(metaGetContact(ccs->hContact), "PGP Encryption turned on by key autoexchange feature");
+ }
+ HistoryLog(ccs->hContact, "PGP Encryption turned on by key autoexchange feature");
+ }
+ }
+ return 1;
+ }
+ }
+ if((str.find(_T("-----END PGP PUBLIC KEY BLOCK-----")) != wstring::npos) && (str.find(_T("-----BEGIN PGP PUBLIC KEY BLOCK-----")) != wstring::npos))
+ {
+ s2 = str.find(_T("-----END PGP PUBLIC KEY BLOCK-----"));
+ s1 = str.find(_T("-----BEGIN PGP PUBLIC KEY BLOCK-----"));
+ }
+ else if((str.find(_T("-----BEGIN PGP PRIVATE KEY BLOCK-----")) != wstring::npos) && (str.find(_T("-----END PGP PRIVATE KEY BLOCK-----")) != wstring::npos))
+ {
+ s2 = str.find(_T("-----END PGP PRIVATE KEY BLOCK-----"));
+ s1 = str.find(_T("-----BEGIN PGP PRIVATE KEY BLOCK-----"));
+ }
+ if((s2 != wstring::npos) && (s1 != wstring::npos))
+ { //this is public key
+ if(metaIsProtoMetaContacts(ccs->hContact))
+ {
+ HistoryLog(ccs->hContact, db_event(msg, 0, 0, dbflags));
+ return 0;
+ }
+ debuglog<<time_str()<<": info: "<<"received key from: "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ccs->hContact, GCDNF_TCHAR)<<"\n";
+ s1 = 0;
+ while((s1 = str.find(_T("\r"), s1)) != wstring::npos)
+ {
+ str.erase(s1, 1);
+ }
+ void ShowNewKeyDialog();
+ if((str.find(_T("-----END PGP PUBLIC KEY BLOCK-----")) != wstring::npos) && (str.find(_T("-----BEGIN PGP PUBLIC KEY BLOCK-----")) != wstring::npos))
+ {
+ s2 = str.find(_T("-----END PGP PUBLIC KEY BLOCK-----"));
+ s1 = str.find(_T("-----BEGIN PGP PUBLIC KEY BLOCK-----"));
+ s2 += _tcslen(_T("-----END PGP PUBLIC KEY BLOCK-----"));
+ }
+ else if((str.find(_T("-----BEGIN PGP PRIVATE KEY BLOCK-----")) != wstring::npos) && (str.find(_T("-----END PGP PRIVATE KEY BLOCK-----")) != wstring::npos))
+ {
+ s2 = str.find(_T("-----END PGP PRIVATE KEY BLOCK-----"));
+ s1 = str.find(_T("-----BEGIN PGP PRIVATE KEY BLOCK-----"));
+ s2 += _tcslen(_T("-----END PGP PRIVATE KEY BLOCK-----"));
+ }
+ new_key.append(str.substr(s1,s2-s1));
+ new_key_hcnt_mutex.lock();
+ new_key_hcnt = ccs->hContact;
+ ShowNewKeyDialog();
+ HistoryLog(ccs->hContact, db_event(msg, 0, 0, dbflags));
+ return 0;
+ }
+ if(bAutoExchange && strstr(msg, "-----PGP KEY REQUEST-----") && gpg_valid && gpg_keyexist)
+ {
+ char *tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "GPGPubKey", "");
+ if(tmp[0])
+ {
+ DBWriteContactSettingByte(ccs->hContact, szGPGModuleName, "GPGEncryption", 0);
+ string str = "-----PGP KEY RESPONSE-----";
+ str.append(tmp);
+ CallContactService(ccs->hContact, PSS_MESSAGE, (WPARAM)PREF_UTF, (LPARAM)str.c_str());
+ DBWriteContactSettingByte(ccs->hContact, szGPGModuleName, "GPGEncryption", 1);
+ }
+ mir_free(tmp);
+ return returnNoError(ccs->hContact);
+ }
+ else if(!isContactHaveKey(ccs->hContact) && bAutoExchange && gpg_valid && gpg_keyexist)
+ {
+ LPSTR proto = (LPSTR)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)ccs->hContact, 0);
+ DWORD uin = DBGetContactSettingDword(ccs->hContact, proto, "UIN", 0);
+ if(uin)
+ {
+ char *proto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)ccs->hContact, 0);
+ char svc[64];
+ strcpy(svc, proto);
+ strcat(svc, PS_ICQ_CHECKCAPABILITY);
+ if(ServiceExists(svc))
+ {
+ ICQ_CUSTOMCAP cap = {0};
+ strcpy(cap.caps, "GPG AutoExchange");
+ if(CallService(svc, (WPARAM)ccs->hContact, (LPARAM)&cap))
+ {
+ CallContactService(ccs->hContact, PSS_MESSAGE, (WPARAM)PREF_UTF, (LPARAM)"-----PGP KEY REQUEST-----");
+ return returnNoError(ccs->hContact);
+ }
+ }
+ }
+ else
+ {
+ TCHAR *jid = UniGetContactSettingUtf(ccs->hContact, proto, "jid", _T(""));
+ if(jid[0])
+ {
+ extern list <JabberAccount*> Accounts;
+ list<JabberAccount*>::iterator end = Accounts.end();
+ for(list<JabberAccount*>::iterator p = Accounts.begin(); p != end; p++)
+ {
+ TCHAR *caps = (*p)->getJabberInterface()->Net()->GetResourceFeatures(jid);
+ if(caps)
+ {
+ wstring str;
+ for(int i =0;;i++)
+ {
+ str.push_back(caps[i]);
+ if(caps[i] == '\0')
+ if(caps[i+1] == '\0')
+ break;
+ }
+ mir_free(caps);
+ if(str.find(_T("GPG_Key_Auto_Exchange:0")) != string::npos)
+ {
+ CallContactService(ccs->hContact, PSS_MESSAGE, (WPARAM)0, (LPARAM)"-----PGP KEY REQUEST-----");
+ return returnNoError(ccs->hContact);
+ }
+ }
+ }
+ }
+ }
+ }
+ if(!(strstr(msg, "-----BEGIN PGP MESSAGE-----") && strstr(msg, "-----END PGP MESSAGE-----")))
+ return CallService(MS_PROTO_CHAINRECV, w, l);
+ boost::thread *thr = new boost::thread(boost::bind(RecvMsgSvc_func, ccs->hContact, str, msg, ccs->wParam, pre->timestamp));
+ return returnNoError(ccs->hContact);
+}
+
+int SendMsgSvc_func(HANDLE hContact, char *msg, DWORD flags)
+{
+ wstring str;
+ bool isansi = false;
+ DWORD dbflags = 0;
+ if(flags & PREF_UTF)
+ dbflags |= DBEF_UTF;
+ if(!metaIsSubcontact(hContact))
+ str = toUTF16(msg);
+ else
+ {//workaround ...
+ wchar_t *tmp = mir_utf8decodeW(msg);
+ if(!tmp)
+ {
+ tmp = mir_a2t(msg);
+ isansi = true;
+ }
+ str.append(tmp);
+ mir_free(tmp);
+ }
+ if(bStripTags && bAppendTags)
+ {
+ std::wstring::size_type p;
+ for(p = str.find(inopentag); p != std::wstring::npos; p = str.find(inopentag))
+ str.erase(p, _tcslen(inopentag));
+ for(p = str.find(inclosetag); p != std::wstring::npos; p = str.find(inclosetag))
+ str.erase(p, _tcslen(inclosetag));
+ for(p = str.find(outopentag); p != std::wstring::npos; p = str.find(outopentag))
+ str.erase(p, _tcslen(outopentag));
+ for(p = str.find(outclosetag); p != std::wstring::npos; p = str.find(outclosetag))
+ str.erase(p, _tcslen(outclosetag));
+ }
+/* for(std::wstring::size_type i = str.find(_T("\r\n")); i != std::wstring::npos; i = str.find(_T("\r\n"), i+1))
+ str.replace(i, 2, _T("\n")); */
+ string out;
+ DWORD code;
+ wstring cmd;
+ wstring file = toUTF16(get_random(10));
+ wstring path;
+ extern bool bJabberAPI, bIsMiranda09;
+ char *tmp = UniGetContactSettingUtf(hContact, szGPGModuleName, "KeyID", "");
+ if(!tmp[0])
+ {
+ mir_free(tmp);
+ HistoryLog(hContact, db_event("Failed to encrypt message with GPG", 0,0, DBEF_SENT));
+ hcontact_data[hContact].msgs_to_pass.push_back("Failed to encrypt message with GPG");
+ mir_free(msg);
+ return CallContactService(hContact, PSS_MESSAGE, (WPARAM)flags, (LPARAM)msg);
+ }
+ if(!bJabberAPI || !bIsMiranda09) //force jabber to handle encrypted message by itself
+ cmd += _T("--comment \"\" --no-version ");
+ if(DBGetContactSettingByte(hContact, szGPGModuleName, "bAlwaysTrust", 0))
+ cmd += _T("--trust-model always ");
+ cmd += _T("--batch --yes -e -a -t -r ");
+ TCHAR *tmp2 = mir_a2t(tmp);
+ mir_free(tmp);
+ cmd += tmp2;
+ mir_free(tmp2);
+ cmd += _T(" \"");
+ tmp2 = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T(""));
+ path.append(tmp2);
+ cmd += tmp2;
+ mir_free(tmp2);
+ cmd += _T("\\tmp\\");
+ cmd += file;
+ path.append(_T("\\tmp\\"));
+ path += file;
+ cmd += _T("\"");
+ {
+ char *tmp;
+ tmp = mir_strdup(toUTF8(str).c_str());
+ fstream f(path.c_str(), std::ios::out);
+ while(!f.is_open())
+ f.open(path.c_str(), std::ios::out);
+ f<<tmp;
+ mir_free(tmp);
+ f.close();
+ }
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::seconds(10)))
+ {
+ gpg_thread.~thread();
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ mir_free(msg);
+ return CallContactService(hContact, PSS_MESSAGE, (WPARAM)flags, (LPARAM)msg);
+ }
+ if(result == pxNotFound)
+ {
+ mir_free(msg);
+ return CallContactService(hContact, PSS_MESSAGE, (WPARAM)flags, (LPARAM)msg);
+ }
+ //TODO: check gpg output for errors
+ if(out.find("There is no assurance this key belongs to the named user") != string::npos)
+ {
+ out.clear();
+ if(MessageBox(0, _T("We trying to encrypt with untrusted key, do you want to trust this key permanently ?"), _T("Warning"), MB_YESNO) == IDYES)
+ {
+ DBWriteContactSettingByte(hContact, szGPGModuleName, "bAlwaysTrust", 1);
+ cmd.insert(0, _T("--trust-model always "));
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::seconds(10)))
+ {
+ gpg_thread.~thread();
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ mir_free(msg);
+ return CallContactService(hContact, PSS_MESSAGE, (WPARAM)flags, (LPARAM)msg);
+ }
+ if(result == pxNotFound)
+ {
+ mir_free(msg);
+ return CallContactService(hContact, PSS_MESSAGE, (WPARAM)flags, (LPARAM)msg);
+ }
+ //TODO: check gpg output for errors
+ }
+ else
+ {
+ mir_free(msg);
+ return 0;
+ }
+ }
+ if(out.find("usage: ") != string::npos)
+ {
+ MessageBox(0, _T("Something wrong, gpg does not understand us, aborting encryption."), _T("Warning"), MB_OK);
+ DeleteFile(path.c_str());
+ mir_free(msg);
+ return CallContactService(hContact, PSS_MESSAGE, (WPARAM)flags, (LPARAM)msg);
+ }
+ DeleteFile(path.c_str());
+ path.append(_T(".asc"));
+ wfstream f(path.c_str(), std::ios::in | std::ios::ate | std::ios::binary);
+ while(!f.is_open())
+ f.open(path.c_str(), std::ios::in | std::ios::ate | std::ios::binary);
+ str.clear();
+ if(f.is_open())
+ {
+ std::wifstream::pos_type size = f.tellg();
+ TCHAR *tmp = new TCHAR [(std::ifstream::pos_type)size+(std::ifstream::pos_type)1];
+ f.seekg(0, std::ios::beg);
+ f.read(tmp, size);
+ tmp[size]= '\0';
+ str.append(tmp);
+ delete [] tmp;
+ f.close();
+ DeleteFile(path.c_str());
+ }
+ if(str.empty())
+ {
+ HistoryLog(hContact, db_event("Failed to encrypt message with GPG", 0,0, DBEF_SENT));
+ hcontact_data[hContact].msgs_to_pass.push_back("Failed to encrypt message with GPG");
+ debuglog<<time_str()<<": info: Failed to encrypt message with GPG\n";
+ mir_free(msg);
+ return CallContactService(hContact, PSS_MESSAGE, (WPARAM)flags, (LPARAM)msg);
+ }
+ string str_event = msg;
+ if(bAppendTags)
+ {
+ str_event.insert(0, toUTF8(outopentag));
+ str_event.append(toUTF8(outclosetag));
+ }
+ if(metaIsSubcontact(hContact))
+ {
+ hcontact_data[metaGetContact(hContact)].msgs_to_pass.push_back(str_event);
+ debuglog<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)<<"is subcontact of"<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)metaGetContact(hContact), GCDNF_TCHAR)<<"\n";
+ debuglog<<time_str()<<": adding event to metacontact: "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)metaGetContact(hContact), GCDNF_TCHAR)<<" on send message.\n";
+ HistoryLog(metaGetContact(hContact), db_event((char*)str_event.c_str(), 0,0, DBEF_SENT|dbflags));
+ }
+ hcontact_data[hContact].msgs_to_pass.push_back(str_event);
+ debuglog<<time_str()<<": adding event to contact: "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)<<" on send message.\n";
+ HistoryLog(hContact, db_event((char*)str_event.c_str(), 0,0, dbflags|DBEF_SENT));
+ if(!(flags & PREF_UTF))
+ flags |= PREF_UTF;
+ sent_msgs.push_back((HANDLE)CallContactService(hContact, PSS_MESSAGE, (WPARAM)flags, (LPARAM)toUTF8(str).c_str()));
+ mir_free(msg);
+ return 0;
+}
+
+int SendMsgSvc(WPARAM w, LPARAM l)
+{
+ CCSDATA *ccs = (CCSDATA*)l;
+ if (!ccs)
+ return CallService(MS_PROTO_CHAINSEND, w, l);
+ char *msg = mir_strdup((char*)(ccs->lParam));
+ if (!msg)
+ {
+ mir_free(msg);
+ return CallService(MS_PROTO_CHAINSEND, w, l);
+ }
+ if(strstr(msg,"-----BEGIN PGP MESSAGE-----"))
+ return CallService(MS_PROTO_CHAINSEND, w, l);
+ if(!isContactHaveKey(ccs->hContact))
+ {
+ if(bAutoExchange && !strstr(msg, "-----PGP KEY REQUEST-----") && !strstr(msg, "-----BEGIN PGP PUBLIC KEY BLOCK-----") && gpg_valid)
+ {
+ void send_encrypted_msgs_thread(HANDLE hContact);
+ LPSTR proto = (LPSTR)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)ccs->hContact, 0);
+ DWORD uin = DBGetContactSettingDword(ccs->hContact, proto, "UIN", 0);
+ if(uin)
+ {
+ char *proto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)ccs->hContact, 0);
+ char svc[64];
+ strcpy(svc, proto);
+ strcat(svc, PS_ICQ_CHECKCAPABILITY);
+
+ if(ServiceExists(svc))
+ {
+ ICQ_CUSTOMCAP cap = {0};
+ strcpy(cap.caps, "GPG AutoExchange");
+ if(CallService(svc, (WPARAM)ccs->hContact, (LPARAM)&cap))
+ {
+ CallContactService(ccs->hContact, PSS_MESSAGE, (WPARAM)ccs->wParam, (LPARAM)"-----PGP KEY REQUEST-----");
+ hcontact_data[ccs->hContact].msgs_to_send.push_back(msg);
+ boost::thread *thr = new boost::thread(boost::bind(send_encrypted_msgs_thread, ccs->hContact));
+ mir_free(msg);
+ return returnNoError(ccs->hContact);
+ }
+ }
+ }
+ else
+ {
+ TCHAR *jid = UniGetContactSettingUtf(ccs->hContact, proto, "jid", _T(""));
+ if(jid[0])
+ {
+ extern list <JabberAccount*> Accounts;
+ list<JabberAccount*>::iterator end = Accounts.end();
+ for(list<JabberAccount*>::iterator p = Accounts.begin(); p != end; p++)
+ {
+ TCHAR *caps = (*p)->getJabberInterface()->Net()->GetResourceFeatures(jid);
+ if(caps)
+ {
+ wstring str;
+ for(int i=0;;i++)
+ {
+ str.push_back(caps[i]);
+ if(caps[i] == '\0')
+ if(caps[i+1] == '\0')
+ break;
+ }
+ mir_free(caps);
+ if(str.find(_T("GPG_Key_Auto_Exchange:0")) != string::npos)
+ {
+ CallContactService(ccs->hContact, PSS_MESSAGE, (WPARAM)ccs->wParam, (LPARAM)"-----PGP KEY REQUEST-----");
+ hcontact_data[ccs->hContact].msgs_to_send.push_back(msg);
+ boost::thread *thr = new boost::thread(boost::bind(send_encrypted_msgs_thread, ccs->hContact));
+ mir_free(msg);
+ return returnNoError(ccs->hContact);
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ mir_free(msg);
+ return CallService(MS_PROTO_CHAINSEND, w, l);
+ }
+ }
+ if(!isContactSecured(ccs->hContact) || metaIsProtoMetaContacts(ccs->hContact))
+ {
+ mir_free(msg);
+ return CallService(MS_PROTO_CHAINSEND, w, l);
+ }
+ boost::thread *thr = new boost::thread(boost::bind(SendMsgSvc_func, ccs->hContact, msg, (DWORD)ccs->wParam));
+ return returnNoError(ccs->hContact);
+}
+
+boost::mutex event_processing_mutex;
+
+int HookSendMsg(WPARAM w, LPARAM l)
+{
+ if(!l)
+ return 0;
+ DBEVENTINFO * dbei = (DBEVENTINFO*)l;
+ if(dbei->eventType != EVENTTYPE_MESSAGE)
+ return 0;
+ if(dbei->flags & DBEF_SENT)
+ {
+ if(strstr((char*)dbei->pBlob, "-----BEGIN PGP MESSAGE-----") || strstr((char*)dbei->pBlob, "-----PGP KEY RESPONSE-----") || strstr((char*)dbei->pBlob, "-----PGP KEY REQUEST-----") || strstr((char*)dbei->pBlob, "-----PGP KEY RESPONSE-----")) //our service data, can be double added by metacontacts e.t.c.
+ return 1;
+ }
+ HANDLE hContact = (HANDLE)w;
+ if(isContactSecured(hContact) && (dbei->flags & DBEF_SENT)) //aggressive outgoing events filtering
+ {
+ if(!hcontact_data[hContact].msgs_to_pass.empty())
+ {
+ event_processing_mutex.lock();
+ std::list<string>::iterator end = hcontact_data[hContact].msgs_to_pass.end();
+ for(std::list<string>::iterator i = hcontact_data[hContact].msgs_to_pass.begin(); i != end; ++i)
+ {
+ if(!strcmp((*i).c_str(), (char*)dbei->pBlob))
+ {
+ hcontact_data[hContact].msgs_to_pass.erase(i);
+ debuglog<<time_str()<<": event message: \""<<(char*)dbei->pBlob<<"\" passed event filter, contact "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)<<", message is in allowed list\n";
+ event_processing_mutex.unlock();
+ return 0;
+ }
+ }
+ event_processing_mutex.unlock();
+ }
+ if(metaIsProtoMetaContacts(hContact) && !isContactSecured(metaGetMostOnline(hContact)))
+ return 0;
+ return 1;
+ }
+ if(!isContactSecured(hContact))
+ {
+ debuglog<<time_str()<<": event message: \""<<(char*)dbei->pBlob<<"\" passed event filter, contact "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)<<" is unsecured\n";
+ return 0;
+ }
+ if(!(dbei->flags & DBEF_SENT) && metaIsProtoMetaContacts((HANDLE)w))
+ {
+ char tmp[29];
+ strncpy(tmp, (char*)dbei->pBlob, 27);
+ tmp[28] = '\0';
+ if(strstr(tmp, "-----BEGIN PGP MESSAGE-----"))
+ return 1;
+ }
+ return 0;
+}
+
+
+static BOOL CALLBACK DlgProcKeyPassword(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ char *inkeyid = NULL;
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ inkeyid = UniGetContactSettingUtf(new_key_hcnt, szGPGModuleName, "InKeyID", "");
+ new_key_hcnt_mutex.unlock();
+ TCHAR *tmp = NULL;
+
+ SetWindowPos(hwndDlg, 0, key_password_rect.left, key_password_rect.top, 0, 0, SWP_NOSIZE|SWP_SHOWWINDOW);
+ TranslateDialogDefault(hwndDlg);
+ string questionstr = "Please enter password for key with ID: ";
+ questionstr += inkeyid;
+ SetDlgItemTextA(hwndDlg, IDC_KEYID, questionstr.c_str());
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DEFAULT_PASSWORD), 0);
+ return TRUE;
+ }
+
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+ {
+ TCHAR tmp[64];
+ GetDlgItemText(hwndDlg, IDC_KEY_PASSWORD, tmp, 64);
+ if(tmp[0])
+ {
+ extern TCHAR *password;
+ if(IsDlgButtonChecked(hwndDlg, IDC_SAVE_PASSWORD))
+ {
+ if(inkeyid && inkeyid[0] && !IsDlgButtonChecked(hwndDlg, IDC_DEFAULT_PASSWORD))
+ {
+ string dbsetting = "szKey_";
+ dbsetting += inkeyid;
+ dbsetting += "_Password";
+ DBWriteContactSettingTString(NULL, szGPGModuleName, dbsetting.c_str(), tmp);
+ }
+ else
+ DBWriteContactSettingTString(NULL, szGPGModuleName, "szKeyPassword", tmp);
+ }
+ if(password)
+ delete [] password;
+ password = new TCHAR [_tcslen(tmp)+1];
+ _tcscpy(password, tmp);
+ }
+ mir_free(tmp);
+ mir_free(inkeyid);
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ case IDCANCEL:
+ mir_free(inkeyid);
+ _terminate = true;
+ DestroyWindow(hwndDlg);
+ break;
+ default:
+ break;
+ }
+
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+/* switch (((LPNMHDR)lParam)->code)
+ {
+ default:
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DEFAULT_PASSWORD), IsDlgButtonChecked(hwndDlg, IDC_SAVE_PASSWORD)?1:0);
+ break;
+ }*/
+ }
+ break;
+ case WM_CLOSE:
+ mir_free(inkeyid);
+ DestroyWindow(hwndDlg);
+ break;
+ case WM_DESTROY:
+ {
+ GetWindowRect(hwndDlg, &key_password_rect);
+ DBWriteContactSettingDword(NULL, szGPGModuleName, "PasswordWindowX", key_password_rect.left);
+ DBWriteContactSettingDword(NULL, szGPGModuleName, "PasswordWindowY", key_password_rect.top);
+ }
+ break;
+
+ }
+ return FALSE;
+}
+
+void ShowLoadKeyPasswordWindow()
+{
+ extern HINSTANCE hInst;
+ DialogBox(hInst, MAKEINTRESOURCE(IDD_KEY_PASSWD), NULL, (DLGPROC)DlgProcKeyPassword);
+}
diff --git a/plugins/New_GPG/src/metacontacts.cpp b/plugins/New_GPG/src/metacontacts.cpp
new file mode 100755
index 0000000000..1abc2aaeac
--- /dev/null
+++ b/plugins/New_GPG/src/metacontacts.cpp
@@ -0,0 +1,88 @@
+// Copyright © 2010-2012 SecureIM developers (baloo and others), sss
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include "commonheaders.h"
+
+extern bool bMetaContacts;
+
+bool metaIsProtoMetaContacts(HANDLE hContact)
+{
+ if(bMetaContacts) {
+ LPSTR proto = (LPSTR)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ if( proto && strcmp(proto,"MetaContacts")==0 ) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+bool metaIsDefaultSubContact(HANDLE hContact)
+{
+
+ if(bMetaContacts)
+ return (HANDLE)CallService(MS_MC_GETDEFAULTCONTACT,(WPARAM)CallService(MS_MC_GETMETACONTACT,(WPARAM)hContact,0),0)==hContact;
+ return false;
+}
+
+
+HANDLE metaGetContact(HANDLE hContact)
+{
+ if(bMetaContacts)
+ if(metaIsSubcontact(hContact))
+ return (HANDLE)CallService(MS_MC_GETMETACONTACT,(WPARAM)hContact,0);
+ return NULL;
+}
+bool metaIsSubcontact(HANDLE hContact)
+{
+ if(bMetaContacts)
+ return (HANDLE)CallService(MS_MC_GETMETACONTACT,(WPARAM)hContact,0);
+ return false;
+}
+
+
+HANDLE metaGetMostOnline(HANDLE hContact)
+{
+
+ if(bMetaContacts)
+ if(metaIsProtoMetaContacts(hContact))
+ return (HANDLE)CallService(MS_MC_GETMOSTONLINECONTACT,(WPARAM)hContact,0);
+ return NULL;
+}
+HANDLE metaGetDefault(HANDLE hContact)
+{
+
+ if(bMetaContacts)
+ if(metaIsProtoMetaContacts(hContact))
+ return (HANDLE)CallService(MS_MC_GETDEFAULTCONTACT,(WPARAM)hContact,0);
+ return NULL;
+}
+
+
+DWORD metaGetContactsNum(HANDLE hContact)
+{
+ if(bMetaContacts)
+ return CallService(MS_MC_GETNUMCONTACTS, (WPARAM)hContact, 0);
+ return 0;
+}
+HANDLE metaGetSubcontact(HANDLE hContact, int num)
+{
+ if(bMetaContacts)
+ return (HANDLE)CallService(MS_MC_GETSUBCONTACT, (WPARAM)hContact, (LPARAM)num);
+ return 0;
+}
+
+
diff --git a/plugins/New_GPG/src/metacontacts.h b/plugins/New_GPG/src/metacontacts.h
new file mode 100755
index 0000000000..8b8873edcc
--- /dev/null
+++ b/plugins/New_GPG/src/metacontacts.h
@@ -0,0 +1,24 @@
+// Copyright © 2010-2012 sss
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+bool metaIsProtoMetaContacts(HANDLE hContact);
+bool metaIsDefaultSubContact(HANDLE hContact) ;
+HANDLE metaGetContact(HANDLE hContact);
+bool metaIsSubcontact(HANDLE hContact);
+HANDLE metaGetMostOnline(HANDLE hContact);
+HANDLE metaGetDefault(HANDLE hContact);
+DWORD metaGetContactsNum(HANDLE hContact);
+HANDLE metaGetSubcontact(HANDLE hContact, int num); \ No newline at end of file
diff --git a/plugins/New_GPG/src/options.cpp b/plugins/New_GPG/src/options.cpp
new file mode 100755
index 0000000000..f03879c48b
--- /dev/null
+++ b/plugins/New_GPG/src/options.cpp
@@ -0,0 +1,1387 @@
+// Copyright © 2010-2012 sss
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include "commonheaders.h"
+
+extern HINSTANCE hInst;
+
+static BOOL CALLBACK DlgProcGpgOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static BOOL CALLBACK DlgProcGpgBinOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static BOOL CALLBACK DlgProcGpgMsgOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static BOOL CALLBACK DlgProcGpgAdvOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+BOOL CheckStateLoadDB(HWND hwndDlg, int idCtrl, const char* szSetting, BYTE bDef)
+{
+ BOOL state = DBGetContactSettingByte(NULL, szGPGModuleName, szSetting, bDef);
+ CheckDlgButton(hwndDlg, idCtrl, state);
+ return state;
+}
+
+BOOL CheckStateStoreDB(HWND hwndDlg, int idCtrl, const char* szSetting)
+{
+ BOOL state = IsDlgButtonChecked(hwndDlg, idCtrl);
+ DBWriteContactSettingByte(NULL, szGPGModuleName, szSetting, (BYTE)state);
+ return state;
+}
+
+
+int GpgOptInit(WPARAM wParam,LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp = { 0 };
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = hInst;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_GPG);
+ odp.pszTitle = szGPGModuleName;
+ odp.pszGroup = "Services";
+ odp.pszTab = "Main";
+ odp.flags=ODPF_BOLDGROUPS;
+ odp.pfnDlgProc = (DLGPROC)DlgProcGpgOpts;
+ Options_AddPage(wParam, &odp);
+
+ ZeroMemory(&odp, sizeof(odp));
+
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = hInst;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_GPG_BIN);
+ odp.pszTitle = szGPGModuleName;
+ odp.pszGroup = "Services";
+ odp.pszTab = "GnuPG Variables";
+ odp.flags=ODPF_BOLDGROUPS;
+ odp.pfnDlgProc = (DLGPROC)DlgProcGpgBinOpts;
+ Options_AddPage(wParam, &odp);
+
+ ZeroMemory(&odp, sizeof(odp));
+
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = hInst;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_GPG_MESSAGES);
+ odp.pszTitle = szGPGModuleName;
+ odp.pszGroup = "Services";
+ odp.pszTab = "Messages";
+ odp.flags=ODPF_BOLDGROUPS;
+ odp.pfnDlgProc = (DLGPROC)DlgProcGpgMsgOpts;
+ Options_AddPage(wParam, &odp);
+
+ ZeroMemory(&odp, sizeof(odp));
+
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = hInst;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_GPG_ADVANCED);
+ odp.pszTitle = szGPGModuleName;
+ odp.pszGroup = "Services";
+ odp.pszTab = "Advanced";
+ odp.flags=ODPF_BOLDGROUPS | ODPF_EXPERTONLY;
+ odp.pfnDlgProc = (DLGPROC)DlgProcGpgAdvOpts;
+ Options_AddPage(wParam, &odp);
+
+ return 0;
+}
+
+map<int, HANDLE> user_data;
+
+int item_num = 0;
+HWND hwndList_p = NULL;
+HWND hwndCurKey_p = NULL;
+
+void ShowLoadPublicKeyDialog();
+static BOOL CALLBACK DlgProcGpgOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HWND hwndList=GetDlgItem(hwndDlg, IDC_USERLIST);
+ hwndList_p = hwndList;
+ hwndCurKey_p = GetDlgItem(hwndDlg, IDC_CURRENT_KEY);
+ LVCOLUMN col = {0};
+ LVITEM item = {0};
+ TCHAR *tmp = NULL;
+ char *tmp2 = NULL;
+ extern bool bIsMiranda09, bJabberAPI;
+ NMLISTVIEW * hdr = (NMLISTVIEW *) lParam;
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ col.pszText = TranslateW(_T("Contact"));
+ col.mask = LVCF_TEXT | LVCF_WIDTH;
+ col.fmt = LVCFMT_LEFT;
+ col.cx = 60;
+ ListView_InsertColumn(hwndList, 0, &col);
+ ZeroMemory(&col,sizeof(col));
+ col.pszText = TranslateW(_T("Key ID"));
+ col.mask = LVCF_TEXT | LVCF_WIDTH;
+ col.fmt = LVCFMT_LEFT;
+ col.cx = 50;
+ ListView_InsertColumn(hwndList, 1, &col);
+ ZeroMemory(&col,sizeof(col));
+ col.pszText = TranslateW(_T("Name"));
+ col.mask = LVCF_TEXT | LVCF_WIDTH;
+ col.fmt = LVCFMT_LEFT;
+ col.cx = 50;
+ ListView_InsertColumn(hwndList, 2, &col);
+ ZeroMemory(&col,sizeof(col));
+ col.pszText = TranslateW(_T("Email"));
+ col.mask = LVCF_TEXT | LVCF_WIDTH;
+ col.fmt = LVCFMT_LEFT;
+ col.cx = 50;
+ ListView_InsertColumn(hwndList, 3, &col);
+ ZeroMemory(&col,sizeof(col));
+ col.pszText = TranslateW(_T("Protocol"));
+ col.mask = LVCF_TEXT | LVCF_WIDTH;
+ col.fmt = LVCFMT_LEFT;
+ col.cx = 60;
+ ListView_InsertColumn(hwndList, 4, &col);
+ ListView_SetExtendedListViewStyleEx(hwndList, 0, LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
+ int i = 1, iRow = 0;
+ bool isContactHaveKey(HANDLE);
+ for(HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); hContact != NULL; hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0))
+ {
+ if(isContactHaveKey(hContact))
+ {
+ TCHAR *name = (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR);
+ item.mask = LVIF_TEXT;
+ item.iItem = i;
+ item.iSubItem = 0;
+ item.pszText = name;
+ iRow = ListView_InsertItem(hwndList, &item);
+ ListView_SetItemText(hwndList, iRow, 0, name);
+ TCHAR *tmp = mir_a2t((char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0));
+ ListView_SetItemText(hwndList, iRow, 4, tmp);
+ mir_free(tmp);
+ tmp2 = UniGetContactSettingUtf(hContact, szGPGModuleName, "KeyID", "");
+ tmp = mir_a2t(tmp2);
+ mir_free(tmp2);
+ ListView_SetItemText(hwndList, iRow, 1, (_tcslen(tmp) > 1)?tmp:_T("not set"));
+ mir_free(tmp);
+ char *tmp2 = UniGetContactSettingUtf(hContact, szGPGModuleName, "KeyMainName", "");
+ if(!toUTF16(tmp2).empty())
+ tmp = mir_wstrdup(toUTF16(tmp2).c_str());
+ else
+ tmp = UniGetContactSettingUtf(hContact, szGPGModuleName, "KeyMainName", _T(""));
+ mir_free(tmp2);
+ ListView_SetItemText(hwndList, iRow, 2, (_tcslen(tmp) > 1)?tmp:_T("not set"));
+ mir_free(tmp);
+ tmp2 = UniGetContactSettingUtf(hContact, szGPGModuleName, "KeyMainEmail", "");
+ if(!toUTF16(tmp2).empty())
+ tmp = mir_wstrdup(toUTF16(tmp2).c_str());
+ else
+ tmp = UniGetContactSettingUtf(hContact, szGPGModuleName, "KeyMainEmail", _T(""));
+ mir_free(tmp2);
+ ListView_SetItemText(hwndList, iRow, 3, (_tcslen(tmp) > 1)?tmp:_T("not set"));
+ mir_free(tmp);
+ if(DBGetContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 0))
+ ListView_SetCheckState(hwndList, iRow, 1);
+ user_data[i] = hContact;
+ ZeroMemory(&item,sizeof(item));
+ ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE);// not sure about this
+ ListView_SetColumnWidth(hwndList, 1, LVSCW_AUTOSIZE);
+ ListView_SetColumnWidth(hwndList, 2, LVSCW_AUTOSIZE);
+ ListView_SetColumnWidth(hwndList, 3, LVSCW_AUTOSIZE);
+ ListView_SetColumnWidth(hwndList, 4, LVSCW_AUTOSIZE);
+ i++;
+ }
+ }
+ tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szLogFilePath", _T(""));
+ SetDlgItemText(hwndDlg, IDC_LOG_FILE_EDIT, (_tcslen(tmp) > 1)?tmp:_T("c:\\GPGdebug.log"));
+ mir_free(tmp);
+ CheckStateLoadDB(hwndDlg, IDC_DEBUG_LOG, "bDebugLog", 0);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_JABBER_API), bIsMiranda09);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_AUTO_EXCHANGE), (bIsMiranda09 && bJabberAPI));
+ {
+ string keyinfo = Translate("Default private key id");
+ keyinfo += ": ";
+ char *keyid = UniGetContactSettingUtf(NULL, szGPGModuleName, "KeyID", "");
+ keyinfo += (strlen(keyid) > 0)?keyid:Translate("not set");
+ mir_free(keyid);
+ SetDlgItemTextA(hwndDlg, IDC_CURRENT_KEY, keyinfo.c_str());
+ }
+ if(bIsMiranda09)
+ CheckStateLoadDB(hwndDlg, IDC_JABBER_API, "bJabberAPI", 1);
+ CheckStateLoadDB(hwndDlg, IDC_FILE_TRANSFERS, "bFileTransfers", 0);
+ CheckStateLoadDB(hwndDlg, IDC_AUTO_EXCHANGE, "bAutoExchange", 0);
+ return TRUE;
+ }
+
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_DELETE_KEY_BUTTON:
+ void setClistIcon(HANDLE hContact);
+ void setSrmmIcon(HANDLE hContact);
+ { //gpg execute block
+ TCHAR tmp2[MAX_PATH] = {0};
+ TCHAR *ptmp;
+ char *tmp;
+ bool keep = false;
+ bool ismetacontact = false;
+ HANDLE meta = NULL;
+ HANDLE hContact = user_data[item_num+1];
+ if(metaIsProtoMetaContacts(hContact))
+ {
+ meta = hContact;
+ hContact = metaGetMostOnline(hContact);
+ ismetacontact = true;
+ }
+ else if((meta = metaGetContact(user_data[item_num+1])) != NULL)
+ {
+ hContact = metaGetMostOnline(meta);
+ ismetacontact = true;
+ }
+ tmp = UniGetContactSettingUtf(hContact, szGPGModuleName, "KeyID", "");
+ for(HANDLE hcnttmp = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); hcnttmp != NULL; hcnttmp = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hcnttmp, 0))
+ {
+ if(hcnttmp != hContact)
+ {
+ char *tmp2 = UniGetContactSettingUtf(hcnttmp, szGPGModuleName, "KeyID", "");
+ if(!strcmp(tmp, tmp2))
+ {
+ mir_free(tmp2);
+ keep = true;
+ break;
+ }
+ mir_free(tmp2);
+ }
+ }
+ if(!keep)
+ if(MessageBox(0, _T("This key not used by any contact, do you want to remove it from public keyring ?"), _T("Key info"), MB_YESNO) == IDYES)
+ {
+ wstring cmd;
+ string output;
+ DWORD exitcode;
+ cmd += _T(" --batch --yes --delete-key ");
+ ptmp = mir_a2t(tmp);
+ cmd += ptmp;
+ mir_free(ptmp);
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &output;
+ params.code = &exitcode;
+ params.result = &result;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::seconds(10)))
+ {
+ gpg_thread.~thread();
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ mir_free(tmp);
+ break;
+ }
+ if(result == pxNotFound)
+ {
+ mir_free(tmp);
+ break;
+ }
+ if(output.find("--delete-secret-keys") != string::npos)
+ MessageBoxA(0, "we have secret key for this public key, do not removing from GPG keyring", "info", MB_OK);
+ else
+ MessageBoxA(0, "Key removed from GPG keyring", "info", MB_OK);
+ }
+ mir_free(tmp);
+ if(ismetacontact)
+ {
+ if(MessageBox(0, _T("Do you want to remove key from entire metacontact (all subcontacts) ?"), _T("Metacontact detected"), MB_YESNO) == IDYES)
+ {
+ HANDLE hcnt = NULL;
+ int count = metaGetContactsNum(meta);
+ for(int i = 0; i < count; i++)
+ {
+ hcnt = metaGetSubcontact(meta, i);
+ if(hcnt)
+ {
+ DBDeleteContactSetting(hcnt, szGPGModuleName, "KeyID");
+ DBDeleteContactSetting(hcnt, szGPGModuleName, "GPGPubKey");
+ DBDeleteContactSetting(hcnt, szGPGModuleName, "KeyMainName");
+ DBDeleteContactSetting(hcnt, szGPGModuleName, "KeyType");
+ DBDeleteContactSetting(hcnt, szGPGModuleName, "KeyMainEmail");
+ DBDeleteContactSetting(hcnt, szGPGModuleName, "KeyComment");
+ setClistIcon(hcnt);
+ setSrmmIcon(hcnt);
+ }
+ }
+ }
+ else
+ {
+ DBDeleteContactSetting(hContact, szGPGModuleName, "KeyID");
+ DBDeleteContactSetting(hContact, szGPGModuleName, "GPGPubKey");
+ DBDeleteContactSetting(hContact, szGPGModuleName, "KeyMainName");
+ DBDeleteContactSetting(hContact, szGPGModuleName, "KeyType");
+ DBDeleteContactSetting(hContact, szGPGModuleName, "KeyMainEmail");
+ DBDeleteContactSetting(hContact, szGPGModuleName, "KeyComment");
+ setClistIcon(hContact);
+ setSrmmIcon(hContact);
+ }
+ }
+ else
+ {
+ DBDeleteContactSetting(user_data[item_num+1], szGPGModuleName, "KeyID");
+ DBDeleteContactSetting(user_data[item_num+1], szGPGModuleName, "GPGPubKey");
+ DBDeleteContactSetting(user_data[item_num+1], szGPGModuleName, "KeyMainName");
+ DBDeleteContactSetting(user_data[item_num+1], szGPGModuleName, "KeyType");
+ DBDeleteContactSetting(user_data[item_num+1], szGPGModuleName, "KeyMainEmail");
+ DBDeleteContactSetting(user_data[item_num+1], szGPGModuleName, "KeyComment");
+ setClistIcon(user_data[item_num+1]);
+ setSrmmIcon(user_data[item_num+1]);
+ }
+ }
+ ListView_SetItemText(hwndList, item_num, 3, _T("not set"));
+ ListView_SetItemText(hwndList, item_num, 2, _T("not set"));
+ ListView_SetItemText(hwndList, item_num, 1, _T("not set"));
+ break;
+ case IDC_SELECT_KEY:
+ {
+ void ShowFirstRunDialog();
+ ShowFirstRunDialog();
+ }
+ break;
+ case IDC_SAVE_KEY_BUTTON:
+ {
+ tmp = GetFilePath(_T("Export public key"), _T("*"), _T(".asc pubkey file"), true);
+ if(!tmp)
+ {
+ break;
+ }
+ wstring str;
+ {
+ TCHAR *tmp = UniGetContactSettingUtf(user_data[item_num+1], szGPGModuleName, "GPGPubKey", _T(""));
+ str.append(tmp);
+ mir_free(tmp);
+ }
+ wstring::size_type s = 0;
+ while((s = str.find(_T("\r"), s)) != wstring::npos)
+ {
+ str.erase(s, 1);
+ }
+ wfstream f(tmp, std::ios::out);
+ delete [] tmp;
+ f<<str.c_str();
+ f.close();
+ }
+ break;
+ case IDC_COPY_KEY:
+ {
+ if(OpenClipboard(hwndDlg))
+ {
+ char *szKey = UniGetContactSettingUtf(NULL, szGPGModuleName, "GPGPubKey", "");
+ std::string str = szKey;;
+ mir_free(szKey);
+ for(std::string::size_type i = str.find("\n"); i != std::string::npos; i = str.find("\n", i+2))
+ str.replace(i, 1, "\r\n");
+ HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, str.size() +1);
+ if(!hMem)
+ {
+ MessageBoxA(0, "Failed to alocate memory", "Error", MB_OK);
+ break;
+ }
+ szKey = (char*)GlobalLock(hMem);
+ if(!szKey)
+ {
+ char msg[64];
+ mir_snprintf(msg, 127, "Failed to lock memory with error %d", GetLastError());
+ MessageBoxA(0, msg, "Error", MB_OK);
+ GlobalFree(hMem);
+ }
+ memcpy(szKey, str.c_str(), str.size());
+ szKey[str.size()] = '\0';
+ str.clear();
+ EmptyClipboard();
+ GlobalUnlock(hMem);
+ if(!SetClipboardData(CF_OEMTEXT, hMem))
+ {
+ GlobalFree(hMem);
+ char msg[64];
+ mir_snprintf(msg, 127, "Failed write to clipboard with error %d", GetLastError());
+ MessageBoxA(0, msg, "Error", MB_OK);
+ }
+ CloseClipboard();
+ }
+ else
+ {
+ char msg[64];
+ mir_snprintf(msg, 127, "Failed to open clipboard with error %d", GetLastError());
+ MessageBoxA(0, msg, "Error", MB_OK);
+ }
+ }
+ break;
+ case IDC_LOG_FILE_SET:
+ {
+ tmp = GetFilePath(_T("Set log file"), _T("*"), _T("LOG files"), 1);
+ SetDlgItemText(hwndDlg, IDC_LOG_FILE_EDIT, tmp);
+ mir_free(tmp);
+ }
+ break;
+ default:
+ break;
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_AUTO_EXCHANGE), (bIsMiranda09 && IsDlgButtonChecked(hwndDlg, IDC_JABBER_API)));
+ if(hdr && IsWindowVisible(hdr->hdr.hwndFrom) && hdr->iItem != (-1))
+ {
+ if(hdr->hdr.code == NM_CLICK)
+ {
+ item_num = hdr->iItem;
+ }
+ else if(hdr->hdr.code == LVN_ITEMCHANGED)
+ {
+ void setClistIcon(HANDLE hContact);
+ void setSrmmIcon(HANDLE hContact);
+ if(ListView_GetCheckState(hwndList, item_num))
+ DBWriteContactSettingByte(user_data[item_num+1], szGPGModuleName, "GPGEncryption", 1);
+ else
+ DBWriteContactSettingByte(user_data[item_num+1], szGPGModuleName, "GPGEncryption", 0);
+ setClistIcon(user_data[item_num+1]);
+ setSrmmIcon(user_data[item_num+1]);
+ }
+ }
+ switch (((LPNMHDR)lParam)->code)
+ {
+
+ case PSN_APPLY:
+ {
+ extern bool bDebugLog, bJabberAPI, bFileTransfers;
+ bDebugLog = CheckStateStoreDB(hwndDlg, IDC_DEBUG_LOG, "bDebugLog");
+ if(bDebugLog)
+ debuglog.init();
+ bJabberAPI = CheckStateStoreDB(hwndDlg, IDC_JABBER_API, "bJabberAPI");
+ bFileTransfers = CheckStateStoreDB(hwndDlg, IDC_FILE_TRANSFERS, "bFileTransfers");
+ bAutoExchange = CheckStateStoreDB(hwndDlg, IDC_AUTO_EXCHANGE, "bAutoExchange");
+ {
+ TCHAR tmp[512];
+ GetDlgItemText(hwndDlg, IDC_LOG_FILE_EDIT, tmp, 512);
+ DBWriteContactSettingTString(NULL, szGPGModuleName, "szLogFilePath", tmp);
+ }
+ return TRUE;
+ }
+ }
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+
+static BOOL CALLBACK DlgProcGpgBinOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ TCHAR *tmp = NULL;
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szGpgBinPath", _T("gpg.exe"));
+ SetDlgItemText(hwndDlg, IDC_BIN_PATH, tmp);
+ mir_free(tmp);
+ tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T("gpg"));
+ SetDlgItemText(hwndDlg, IDC_HOME_DIR, tmp);
+ mir_free(tmp);
+ return TRUE;
+ }
+
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_SET_BIN_PATH:
+ {
+ GetFilePath(_T("Choose gpg.exe"), "szGpgBinPath", _T("*.exe"), _T("EXE Executables"));
+ tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szGpgBinPath", _T("gpg.exe"));
+ SetDlgItemText(hwndDlg, IDC_BIN_PATH, tmp);
+ bool gpg_exists = false;
+ {
+ if(_waccess(tmp, 0) != -1)
+ gpg_exists = true;
+ if(gpg_exists)
+ {
+ bool bad_version = false;
+ TCHAR *tmp_path = UniGetContactSettingUtf(NULL, szGPGModuleName, "szGpgBinPath", _T(""));
+ DBWriteContactSettingTString(NULL, szGPGModuleName, "szGpgBinPath", tmp);
+ string out;
+ DWORD code;
+ wstring cmd = _T("--version");
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::seconds(10)))
+ {
+ gpg_thread.~thread();
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ }
+ DBWriteContactSettingTString(NULL, szGPGModuleName, "szGpgBinPath", tmp_path);
+ mir_free(tmp_path);
+ string::size_type p1 = out.find("(GnuPG) ");
+ if(p1 != string::npos)
+ {
+ p1 += strlen("(GnuPG) ");
+ if(out[p1] != '1')
+ bad_version = true;
+ }
+ else
+ {
+ bad_version = false;
+ MessageBox(0, TranslateT("This is not gnupg binary !\nrecommended to use GnuPG v1.x.x with this plugn."), _T("Warning"), MB_OK);
+ }
+/* if(bad_version) //looks like working fine with gpg2
+ MessageBox(0, TranslateT("Unsupported gnupg version found, use at you own risk!\nrecommended to use GnuPG v1.x.x with this plugn."), _T("Warning"), MB_OK); */
+ }
+ }
+ char mir_path[MAX_PATH];
+ char *atmp = mir_t2a(tmp);
+ mir_free(tmp);
+ CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)"\\", (LPARAM)mir_path);
+ char* p_path = NULL;
+ if(StriStr(atmp, mir_path))
+ {
+ p_path = atmp + strlen(mir_path);
+ tmp = mir_a2t(p_path);
+ SetDlgItemText(hwndDlg, IDC_BIN_PATH, tmp);
+ }
+ }
+ break;
+ case IDC_SET_HOME_DIR:
+ {
+ GetFolderPath(_T("Set home diractory"), "szHomePath");
+ tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T(""));
+ SetDlgItemText(hwndDlg, IDC_HOME_DIR, tmp);
+ char mir_path[MAX_PATH];
+ char *atmp = mir_t2a(tmp);
+ mir_free(tmp);
+ CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)"\\", (LPARAM)mir_path);
+ char* p_path = NULL;
+ if(StriStr(atmp, mir_path))
+ {
+ p_path = atmp + strlen(mir_path);
+ tmp = mir_a2t(p_path);
+ SetDlgItemText(hwndDlg, IDC_HOME_DIR, tmp);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+ switch (((LPNMHDR)lParam)->code)
+ {
+
+ case PSN_APPLY:
+ {
+ TCHAR tmp[512];
+ GetDlgItemText(hwndDlg, IDC_BIN_PATH, tmp, 512);
+ DBWriteContactSettingTString(NULL, szGPGModuleName, "szGpgBinPath", tmp);
+ GetDlgItemText(hwndDlg, IDC_HOME_DIR, tmp, 512);
+ while(tmp[_tcslen(tmp)-1] == '\\')
+ tmp[_tcslen(tmp)-1] = '\0';
+ DBWriteContactSettingTString(NULL, szGPGModuleName, "szHomePath", tmp);
+ return TRUE;
+ }
+ }
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static BOOL CALLBACK DlgProcGpgMsgOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ CheckStateLoadDB(hwndDlg, IDC_APPEND_TAGS, "bAppendTags", 0);
+ CheckStateLoadDB(hwndDlg, IDC_STRIP_TAGS, "bStripTags", 0);
+ {
+ TCHAR *tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szInOpenTag", _T("<GPGdec>"));
+ SetDlgItemText(hwndDlg, IDC_IN_OPEN_TAG, tmp);
+ mir_free(tmp);
+ tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szInCloseTag", _T("</GPGdec>"));
+ SetDlgItemText(hwndDlg, IDC_IN_CLOSE_TAG, tmp);
+ mir_free(tmp);
+ tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szOutOpenTag", _T("<GPGenc>"));
+ SetDlgItemText(hwndDlg, IDC_OUT_OPEN_TAG, tmp);
+ mir_free(tmp);
+ tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szOutCloseTag", _T("</GPGenc>"));
+ SetDlgItemText(hwndDlg, IDC_OUT_CLOSE_TAG, tmp);
+ mir_free(tmp);
+ }
+ return TRUE;
+ }
+
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_APPEND_TAGS:
+ break;
+ default:
+ break;
+ }
+
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+ switch (((LPNMHDR)lParam)->code)
+ {
+
+ case PSN_APPLY:
+ {
+ bAppendTags = CheckStateStoreDB(hwndDlg, IDC_APPEND_TAGS, "bAppendTags");
+ bStripTags = CheckStateStoreDB(hwndDlg, IDC_STRIP_TAGS, "bStripTags");
+ {
+ TCHAR tmp[128];
+ GetDlgItemText(hwndDlg, IDC_IN_OPEN_TAG, tmp, 128);
+ DBWriteContactSettingTString(NULL, szGPGModuleName, "szInOpenTag", tmp);
+ mir_free(inopentag);
+ inopentag = new TCHAR [_tcslen(tmp)+1];
+ _tcscpy(inopentag, tmp);
+ GetDlgItemText(hwndDlg, IDC_IN_CLOSE_TAG, tmp, 128);
+ DBWriteContactSettingTString(NULL, szGPGModuleName, "szInCloseTag", tmp);
+ mir_free(inclosetag);
+ inclosetag = new TCHAR [_tcslen(tmp)+1];
+ _tcscpy(inclosetag, tmp);
+ GetDlgItemText(hwndDlg, IDC_OUT_OPEN_TAG, tmp, 128);
+ DBWriteContactSettingTString(NULL, szGPGModuleName, "szOutOpenTag", tmp);
+ mir_free(outopentag);
+ outopentag = new TCHAR [_tcslen(tmp)+1];
+ _tcscpy(outopentag, tmp);
+ GetDlgItemText(hwndDlg, IDC_OUT_CLOSE_TAG, tmp, 128);
+ DBWriteContactSettingTString(NULL, szGPGModuleName, "szOutCloseTag", tmp);
+ mir_free(outclosetag);
+ outclosetag = new TCHAR [_tcslen(tmp)+1];
+ _tcscpy(outclosetag, tmp);
+ }
+ return TRUE;
+ }
+ }
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static BOOL CALLBACK DlgProcGpgAdvOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ extern bool bJabberAPI;
+ TranslateDialogDefault(hwndDlg);
+ CheckStateLoadDB(hwndDlg, IDC_PRESCENSE_SUBSCRIPTION, "bPresenceSigning", 0);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_PRESCENSE_SUBSCRIPTION), bJabberAPI);
+
+ return TRUE;
+ }
+
+
+ case WM_COMMAND:
+ {
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+ switch (((LPNMHDR)lParam)->code)
+ {
+
+ case PSN_APPLY:
+ {
+ bPresenceSigning = CheckStateStoreDB(hwndDlg, IDC_PRESCENSE_SUBSCRIPTION, "bPresenceSigning");
+ return TRUE;
+ }
+ }
+ }
+ break;
+ }
+ return FALSE;
+}
+
+HWND hPubKeyEdit = NULL;
+
+LONG_PTR default_edit_proc = NULL;
+
+static BOOL CALLBACK editctrl_ctrl_a(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ LRESULT ret = 0;
+ switch(msg)
+ {
+ case WM_KEYDOWN:
+ if(wParam == 0x41 && GetKeyState(VK_CONTROL)< 0 )
+ SendMessage(hwndDlg, EM_SETSEL, 0, -1);
+ break;
+ default:
+ ret = CallWindowProc((WNDPROC)default_edit_proc, hwndDlg, msg, wParam, lParam);
+ break;
+ }
+ return ret;
+}
+
+static BOOL CALLBACK DlgProcLoadPublicKey(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ static HANDLE hContact = user_data[item_num+1];
+
+
+ TCHAR *tmp = NULL;
+
+ wstring key_buf;
+ wstring::size_type ws1 = 0, ws2 = 0;
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ default_edit_proc = GetWindowLong(GetDlgItem(hwndDlg, IDC_PUBLIC_KEY_EDIT), GWLP_WNDPROC);
+ SetWindowPos(hwndDlg, 0, load_key_rect.left, load_key_rect.top, 0, 0, SWP_NOSIZE|SWP_SHOWWINDOW);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_PUBLIC_KEY_EDIT), GWLP_WNDPROC, (LONG_PTR)editctrl_ctrl_a);
+ HANDLE hcnt = hContact;
+ if(metaIsProtoMetaContacts(hcnt))
+ hcnt = metaGetMostOnline(hcnt);
+ TranslateDialogDefault(hwndDlg);
+ {
+ string msg = Translate("Load Public GPG Key for ");
+ msg += (char*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hcnt, 0);
+ SetWindowTextA(hwndDlg, msg.c_str());
+ }
+ bool isContactSecured(HANDLE);
+ if(!hcnt)
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SELECT_EXISTING), 0);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLE_ENCRYPTION), 0);
+ }
+ if(isContactSecured(hcnt))
+ SetDlgItemText(hwndDlg, IDC_ENABLE_ENCRYPTION, TranslateW(_T("Turn off encryption")));
+ else
+ {
+ SetDlgItemText(hwndDlg, IDC_ENABLE_ENCRYPTION, TranslateW(_T("Turn on encryption")));
+ CheckDlgButton(hwndDlg, IDC_ENABLE_ENCRYPTION, 1);
+ }
+ if(hcnt)
+ {
+ tmp = UniGetContactSettingUtf(hcnt, szGPGModuleName, "GPGPubKey", _T(""));
+ wstring str = tmp;
+ mir_free(tmp); tmp = NULL;
+ wstring::size_type p = 0, stop = 0;
+ if(!str.empty())
+ {
+ for(;;)
+ {
+ if((p = str.find(_T("\n"), p+2)) != wstring::npos)
+ {
+ if(p > stop)
+ {
+ stop = p;
+ str.insert(p, _T("\r"));
+ }
+ else
+ break;
+ }
+ }
+ }
+// char *tmp = UniGetContactSettingUtf(hcnt, szGPGModuleName, "KeyID_Prescense", "");
+ if(!hcontact_data[hcnt].key_in_prescense.empty())
+ {
+ char *tmp2 = UniGetContactSettingUtf(hcnt, szGPGModuleName, "KeyID", "");
+ if(!tmp2[0])
+ {
+ string out;
+ DWORD code;
+ wstring cmd = _T(" --export -a ");
+// TCHAR *tmp3 = mir_a2t(tmp);
+ cmd += toUTF16(hcontact_data[hcnt].key_in_prescense);
+// mir_free(tmp3);
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::seconds(10)))
+ {
+ gpg_thread.~thread();
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ }
+ if((out.find("-----BEGIN PGP PUBLIC KEY BLOCK-----") != string::npos) && (out.find("-----END PGP PUBLIC KEY BLOCK-----") != string::npos))
+ {
+ string::size_type p = 0, stop = 0;
+ for(;;)
+ {
+ if((p = out.find("\n", p+2)) != string::npos)
+ {
+ if(p > stop)
+ {
+ stop = p;
+ out.insert(p, "\r");
+ }
+ else
+ break;
+ }
+ }
+ TCHAR *tmp3 = mir_a2t(out.c_str());
+ str.clear();
+ str.append(tmp3);
+ string msg = "Load Public GPG Key for ";
+ msg += (char*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hcnt, 0);
+ msg += " (Key ID: ";
+ msg += hcontact_data[hcnt].key_in_prescense;
+ msg += " found in prescense, and exists in keyring.)";
+ SetWindowTextA(hwndDlg, msg.c_str());
+ }
+ else
+ {
+ string msg = "Load Public GPG Key (Key ID: ";
+ msg += hcontact_data[hcnt].key_in_prescense;
+ msg += " found in prescense.)";
+ SetWindowTextA(hwndDlg, msg.c_str());
+ EnableWindow(GetDlgItem(hwndDlg, IDC_IMPORT), 1);
+ }
+ }
+ mir_free(tmp2);
+ }
+ if(tmp)
+ mir_free(tmp);
+ SetDlgItemText(hwndDlg, IDC_PUBLIC_KEY_EDIT, !str.empty()?str.c_str():_T(""));
+ }
+ hPubKeyEdit = GetDlgItem(hwndDlg, IDC_PUBLIC_KEY_EDIT);
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case ID_OK:
+ {
+ tmp = new TCHAR [40960];
+ TCHAR *begin, *end;
+ GetDlgItemText(hwndDlg, IDC_PUBLIC_KEY_EDIT, tmp, 40960);
+ key_buf.append(tmp);
+ key_buf.append(_T("\n")); //no new line at end of file )
+ delete [] tmp;
+ while((ws1 = key_buf.find(_T("\r"), ws1)) != wstring::npos)
+ {
+ key_buf.erase(ws1, 1); //remove windows specific trash
+ }
+ ws1 = 0;
+ if(((ws2 = key_buf.find(_T("-----END PGP PUBLIC KEY BLOCK-----"))) != wstring::npos) && ((ws1 = key_buf.find(_T("-----BEGIN PGP PUBLIC KEY BLOCK-----"))) != wstring::npos))
+ {
+ begin = (TCHAR*)mir_alloc(sizeof(TCHAR) * (_tcslen(_T("-----BEGIN PGP PUBLIC KEY BLOCK-----")) + 1));
+ _tcscpy(begin, _T("-----BEGIN PGP PUBLIC KEY BLOCK-----"));
+ end = (TCHAR*)mir_alloc(sizeof( TCHAR) * (_tcslen(_T("-----END PGP PUBLIC KEY BLOCK-----")) + 1));
+ _tcscpy(end, _T("-----END PGP PUBLIC KEY BLOCK-----"));
+ }
+ else if(((ws2 = key_buf.find(_T("-----END PGP PRIVATE KEY BLOCK-----"))) != wstring::npos) && ((ws1 = key_buf.find(_T("-----BEGIN PGP PRIVATE KEY BLOCK-----"))) != wstring::npos))
+ {
+ begin = (TCHAR*)mir_alloc(sizeof(TCHAR) * (_tcslen(_T("-----BEGIN PGP PRIVATE KEY BLOCK-----")) + 1));
+ _tcscpy(begin, _T("-----BEGIN PGP PRIVATE KEY BLOCK-----"));
+ end = (TCHAR*)mir_alloc(sizeof(TCHAR) * (_tcslen(_T("-----END PGP PRIVATE KEY BLOCK-----")) + 1));
+ _tcscpy(end, _T("-----END PGP PRIVATE KEY BLOCK-----"));
+ }
+ else
+ {
+ MessageBox(0, _T("This is not public or private key"), _T("INFO"), MB_OK);
+ break;
+ }
+ ws2 += _tcslen(end);
+ bool allsubcontacts = false;
+ {
+ if(metaIsProtoMetaContacts(hContact))
+ {
+ HANDLE hcnt = NULL;
+ if(MessageBox(0, _T("Do you want load key for all subcontacts ?"), _T("Metacontact detected"), MB_YESNO) == IDYES)
+ {
+ allsubcontacts = true;
+ int count = metaGetContactsNum(hContact);
+ for(int i = 0; i < count; i++)
+ {
+ hcnt = metaGetSubcontact(hContact, i);
+ if(hcnt)
+ DBWriteContactSettingTString(hcnt, szGPGModuleName, "GPGPubKey", key_buf.substr(ws1,ws2-ws1).c_str());
+ }
+ }
+ else
+ DBWriteContactSettingTString(metaGetMostOnline(hContact), szGPGModuleName, "GPGPubKey", key_buf.substr(ws1,ws2-ws1).c_str());
+ }
+ else
+ DBWriteContactSettingTString(hContact, szGPGModuleName, "GPGPubKey", key_buf.substr(ws1,ws2-ws1).c_str());
+ }
+ tmp = (TCHAR*)mir_alloc(sizeof( TCHAR) * (key_buf.length()+1));
+ _tcscpy(tmp, key_buf.substr(ws1,ws2-ws1).c_str());
+ { //gpg execute block
+ wstring cmd;
+ TCHAR tmp2[MAX_PATH] = {0};
+ TCHAR *ptmp;
+ string output;
+ DWORD exitcode;
+ {
+ HANDLE hcnt = hContact;
+ if(metaIsProtoMetaContacts(hcnt))
+ hcnt = metaGetMostOnline(hcnt);
+ ptmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T(""));
+ _tcscpy(tmp2, ptmp);
+ mir_free(ptmp);
+ _tcscat(tmp2, _T("\\"));
+ _tcscat(tmp2, _T("temporary_exported.asc"));
+ DeleteFile(tmp2);
+ wfstream f(tmp2, std::ios::out);
+ ptmp = UniGetContactSettingUtf(hcnt, szGPGModuleName, "GPGPubKey", _T(""));
+ wstring str = ptmp;
+ mir_free(ptmp);
+ wstring::size_type s = 0;
+ while((s = str.find(_T("\r"), s)) != wstring::npos)
+ {
+ str.erase(s, 1);
+ }
+ f<<str.c_str();
+ f.close();
+ cmd += _T(" --batch ");
+ cmd += _T(" --import \"");
+ cmd += tmp2;
+ cmd += _T("\"");
+ }
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &output;
+ params.code = &exitcode;
+ params.result = &result;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::seconds(10)))
+ {
+ gpg_thread.~thread();
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ break;
+ }
+ if(result == pxNotFound)
+ break;
+ mir_free(begin);
+ mir_free(end);
+ if(hContact)
+ {
+ if(metaIsProtoMetaContacts(hContact))
+ {
+ HANDLE hcnt = NULL;
+ if(allsubcontacts)
+ {
+ int count = metaGetContactsNum(hContact);
+ for(int i = 0; i < count; i++)
+ {
+ hcnt = metaGetSubcontact(hContact, i);
+ if(hcnt)
+ DBDeleteContactSetting(hcnt, szGPGModuleName, "bAlwatsTrust");
+ }
+ }
+ else
+ DBDeleteContactSetting(metaGetMostOnline(hContact), szGPGModuleName, "bAlwatsTrust");
+ }
+ else
+ DBDeleteContactSetting(hContact, szGPGModuleName, "bAlwatsTrust");
+ }
+ {
+ TCHAR *tmp;
+ if(output.find("already in secret keyring") != string::npos)
+ {
+ MessageBox(0, _T("Key already in scret key ring."), _T("Info"), MB_OK);
+ DeleteFile(tmp2);
+ break;
+ }
+ char *tmp2;
+ string::size_type s = output.find("gpg: key ") + strlen("gpg: key ");
+ string::size_type s2 = output.find(":", s);
+ tmp2 = (char*)mir_alloc(output.substr(s,s2-s).length()+1);
+ strcpy(tmp2, output.substr(s,s2-s).c_str());
+ mir_utf8decode(tmp2, 0);
+ {
+ if(metaIsProtoMetaContacts(hContact))
+ {
+ HANDLE hcnt = NULL;
+ if(allsubcontacts)
+ {
+ int count = metaGetContactsNum(hContact);
+ for(int i = 0; i < count; i++)
+ {
+ hcnt = metaGetSubcontact(hContact, i);
+ if(hcnt)
+ DBWriteContactSettingString(hcnt, szGPGModuleName, "KeyID", tmp2);
+ }
+ }
+ else
+ DBWriteContactSettingString(metaGetMostOnline(hContact), szGPGModuleName, "KeyID", tmp2);
+ }
+ else
+ DBWriteContactSettingString(hContact, szGPGModuleName, "KeyID", tmp2);
+ }
+ mir_free(tmp2);
+ tmp = mir_wstrdup(toUTF16(output.substr(s,s2-s)).c_str());
+ if(hContact && hwndList_p)
+ ListView_SetItemText(hwndList_p, item_num, 1, tmp);
+ mir_free(tmp);
+ s = output.find("“", s2);
+ if(s == string::npos)
+ {
+ s = output.find("\"", s2);
+ s += 1;
+ }
+ else
+ s += 3;
+ if((s2 = output.find("(", s)) == string::npos)
+ s2 = output.find("<", s);
+ else if(s2 > output.find("<", s))
+ s2 = output.find("<", s);
+ if(s2 != string::npos)
+ {
+ tmp2 = (char*)mir_alloc(output.substr(s,s2-s-1).length()+1);
+ strcpy(tmp2, output.substr(s,s2-s-1).c_str());
+ mir_utf8decode(tmp2, 0);
+ if(hContact)
+ {
+ if(metaIsProtoMetaContacts(hContact))
+ {
+ HANDLE hcnt = NULL;
+ if(allsubcontacts)
+ {
+ int count = metaGetContactsNum(hContact);
+ for(int i = 0; i < count; i++)
+ {
+ hcnt = metaGetSubcontact(hContact, i);
+ if(hcnt)
+ DBWriteContactSettingString(hcnt, szGPGModuleName, "KeyMainName", output.substr(s,s2-s-1).c_str());
+ }
+ }
+ else
+ DBWriteContactSettingString(metaGetMostOnline(hContact), szGPGModuleName, "KeyMainName", output.substr(s,s2-s-1).c_str());
+ }
+ else
+ DBWriteContactSettingString(hContact, szGPGModuleName, "KeyMainName", output.substr(s,s2-s-1).c_str());
+ }
+ mir_free(tmp2);
+ tmp = mir_wstrdup(toUTF16(output.substr(s,s2-s-1)).c_str());
+ if(hContact && hwndList_p)
+ ListView_SetItemText(hwndList_p, item_num, 2, tmp);
+ mir_free(tmp);
+ if((s = output.find(")", s2)) == string::npos)
+ s = output.find(">", s2);
+ else if(s > output.find(">", s2))
+ s = output.find(">", s2);
+ s2++;
+ if(output[s] == ')')
+ {
+ tmp2 = new char [output.substr(s2,s-s2).length()+1];
+ strcpy(tmp2, output.substr(s2,s-s2).c_str());
+ mir_utf8decode(tmp2, 0);
+ if(hContact)
+ {
+ if(metaIsProtoMetaContacts(hContact))
+ {
+ HANDLE hcnt = NULL;
+ if(allsubcontacts)
+ {
+ int count = metaGetContactsNum(hContact);
+ for(int i = 0; i < count; i++)
+ {
+ hcnt = metaGetSubcontact(hContact, i);
+ if(hcnt)
+ DBWriteContactSettingString(hcnt, szGPGModuleName, "KeyComment", output.substr(s2,s-s2).c_str());
+ }
+ }
+ else
+ DBWriteContactSettingString(metaGetMostOnline(hContact), szGPGModuleName, "KeyComment", output.substr(s2,s-s2).c_str());
+ }
+ else
+ DBWriteContactSettingString(hContact, szGPGModuleName, "KeyComment", output.substr(s2,s-s2).c_str());
+ }
+ mir_free(tmp2);
+ s+=3;
+ s2 = output.find(">", s);
+ tmp2 = new char [output.substr(s,s2-s).length()+1];
+ strcpy(tmp2, output.substr(s,s2-s).c_str());
+ mir_utf8decode(tmp2, 0);
+ if(hContact)
+ {
+ if(metaIsProtoMetaContacts(hContact))
+ {
+ HANDLE hcnt = NULL;
+ if(allsubcontacts)
+ {
+ int count = metaGetContactsNum(hContact);
+ for(int i = 0; i < count; i++)
+ {
+ hcnt = metaGetSubcontact(hContact, i);
+ if(hcnt)
+ DBWriteContactSettingString(hcnt, szGPGModuleName, "KeyMainEmail", output.substr(s,s2-s).c_str());
+ }
+ }
+ else
+ DBWriteContactSettingString(metaGetMostOnline(hContact), szGPGModuleName, "KeyMainEmail", output.substr(s,s2-s).c_str());
+ }
+ else
+ DBWriteContactSettingString(hContact, szGPGModuleName, "KeyMainEmail", output.substr(s,s2-s).c_str());
+ }
+ mir_free(tmp2);
+ tmp = mir_wstrdup(toUTF16(output.substr(s,s2-s)).c_str());
+ if(hContact && hwndList_p)
+ ListView_SetItemText(hwndList_p, item_num, 3, tmp);
+ mir_free(tmp);
+ }
+ else
+ {
+ tmp2 = (char*)mir_alloc(output.substr(s2,s-s2).length()+1);
+ strcpy(tmp2, output.substr(s2,s-s2).c_str());
+ mir_utf8decode(tmp2, 0);
+ if(hContact)
+ {
+ if(metaIsProtoMetaContacts(hContact))
+ {
+ HANDLE hcnt = NULL;
+ if(allsubcontacts)
+ {
+ int count = metaGetContactsNum(hContact);
+ for(int i = 0; i < count; i++)
+ {
+ hcnt = metaGetSubcontact(hContact, i);
+ if(hcnt)
+ DBWriteContactSettingString(hcnt, szGPGModuleName, "KeyMainEmail", output.substr(s2,s-s2).c_str());
+ }
+ }
+ else
+ DBWriteContactSettingString(metaGetMostOnline(hContact), szGPGModuleName, "KeyMainEmail", output.substr(s2,s-s2).c_str());
+ }
+ else
+ DBWriteContactSettingString(hContact, szGPGModuleName, "KeyMainEmail", output.substr(s2,s-s2).c_str());
+ }
+ mir_free(tmp2);
+ tmp = mir_wstrdup(toUTF16(output.substr(s2,s-s2)).c_str());
+ if(hContact && hwndList_p)
+ ListView_SetItemText(hwndList_p, item_num, 3, tmp);
+ mir_free(tmp);
+ }
+ }
+ if(hContact && hwndList_p)
+ {
+ ListView_SetColumnWidth(hwndList_p, 0, LVSCW_AUTOSIZE);
+ ListView_SetColumnWidth(hwndList_p, 1, LVSCW_AUTOSIZE);
+ ListView_SetColumnWidth(hwndList_p, 2, LVSCW_AUTOSIZE);
+ ListView_SetColumnWidth(hwndList_p, 3, LVSCW_AUTOSIZE);
+ }
+ }
+ if(!hContact)
+ {
+ TCHAR *fp = UniGetContactSettingUtf(hContact, szGPGModuleName, "KeyID", _T(""));
+ {
+ string out;
+ DWORD code;
+ wstring cmd = _T("--batch -a --export ");
+ cmd += fp;
+ mir_free(fp);
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::seconds(10)))
+ {
+ gpg_thread.~thread();
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ break;
+ }
+ if(result == pxNotFound)
+ break;
+ string::size_type s = 0;
+ while((s = out.find("\r", s)) != string::npos)
+ {
+ out.erase(s, 1);
+ }
+ DBWriteContactSettingString(hContact, szGPGModuleName, "GPGPubKey", out.c_str());
+ }
+ }
+ tmp = mir_wstrdup(toUTF16(output).c_str());
+ MessageBox(0, tmp, _T(""), MB_OK);
+ mir_free(tmp);
+ DeleteFile(tmp2);
+ }
+ key_buf.clear();
+ if(IsDlgButtonChecked(hwndDlg, IDC_ENABLE_ENCRYPTION))
+ {
+ void setSrmmIcon(HANDLE);
+ void setClistIcon(HANDLE);
+ if(hContact)
+ {
+ if(metaIsProtoMetaContacts(hContact))
+ {
+ HANDLE hcnt = NULL;
+ if(allsubcontacts)
+ {
+ int count = metaGetContactsNum(hContact);
+ for(int i = 0; i < count; i++)
+ {
+ hcnt = metaGetSubcontact(hContact, i);
+ if(hcnt)
+ {
+ if(!isContactSecured(hcnt))
+ DBWriteContactSettingByte(hcnt, szGPGModuleName, "GPGEncryption", 1);
+ else
+ DBWriteContactSettingByte(hcnt, szGPGModuleName, "GPGEncryption", 0);
+ setSrmmIcon(hContact);
+ setClistIcon(hContact);
+ }
+ }
+ }
+ else if(!isContactSecured(hContact))
+ DBWriteContactSettingByte(metaGetMostOnline(hContact), szGPGModuleName, "GPGEncryption", 1);
+ else
+ DBWriteContactSettingByte(metaGetMostOnline(hContact), szGPGModuleName, "GPGEncryption", 0);
+ }
+ else if(!isContactSecured(hContact))
+ DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 1);
+ else
+ DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 0);
+ }
+ }
+ DestroyWindow(hwndDlg);
+ }
+ break;
+ case ID_LOAD_FROM_FILE:
+ {
+ tmp = GetFilePath(_T("Set file containing GPG public key"), _T("*"), _T("GPG public key file"));
+ if(!tmp)
+ {
+ break;
+ }
+ wfstream f(tmp, std::ios::in | std::ios::ate | std::ios::binary);
+ delete [] tmp;
+ if(!f.is_open())
+ {
+ MessageBox(0, _T("Failed to open file"), _T("Error"), MB_OK);
+ break;
+ }
+ if(f.is_open())
+ {
+ std::wifstream::pos_type size = f.tellg();
+ TCHAR *tmp = new TCHAR [(std::ifstream::pos_type)size+(std::ifstream::pos_type)1];
+ f.seekg(0, std::ios::beg);
+ f.read(tmp, size);
+ tmp[size]= '\0';
+ key_buf.append(tmp);
+ delete [] tmp;
+ f.close();
+ }
+ if(key_buf.empty())
+ {
+ key_buf.clear();
+ debuglog<<time_str()<<": info: Failed to read key file\n";
+ break;
+ }
+ ws2 = key_buf.find(_T("-----END PGP PUBLIC KEY BLOCK-----"));
+ ws1 = key_buf.find(_T("-----BEGIN PGP PUBLIC KEY BLOCK-----"));
+ if(ws2 == wstring::npos || ws1 == wstring::npos)
+ {
+ ws2 = key_buf.find(_T("-----END PGP PRIVATE KEY BLOCK-----"));
+ ws1 = key_buf.find(_T("-----BEGIN PGP PRIVATE KEY BLOCK-----"));
+ }
+ if(ws2 == wstring::npos || ws1 == wstring::npos)
+ {
+ MessageBox(0, _T("Where is no public or private key."), _T("Info"), MB_OK);
+ break;
+ }
+ ws2 += _tcslen(_T("-----END PGP PUBLIC KEY BLOCK-----"));
+ SetDlgItemText(hwndDlg, IDC_PUBLIC_KEY_EDIT, key_buf.substr(ws1,ws2-ws1).c_str());
+ key_buf.clear();
+ }
+ break;
+ case IDC_IMPORT:
+ extern HANDLE new_key_hcnt;
+ extern boost::mutex new_key_hcnt_mutex;
+ new_key_hcnt_mutex.lock();
+ new_key_hcnt = hContact;
+ void ShowImportKeyDialog();
+ ShowImportKeyDialog();
+ break;
+ case IDC_SELECT_EXISTING:
+ void ShowSelectExistingKeyDialog();
+ ShowSelectExistingKeyDialog();
+ break;
+ }
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+ switch (((LPNMHDR)lParam)->code)
+ {
+
+ case PSN_APPLY:
+ {
+ return TRUE;
+ }
+ }
+ }
+ break;
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+ case WM_DESTROY:
+ {
+ GetWindowRect(hwndDlg, &load_key_rect);
+ DBWriteContactSettingDword(NULL, szGPGModuleName, "LoadKeyWindowX", load_key_rect.left);
+ DBWriteContactSettingDword(NULL, szGPGModuleName, "LoadKeyWindowY", load_key_rect.top);
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+
+
+void ShowLoadPublicKeyDialog()
+{
+ DialogBox(hInst, MAKEINTRESOURCE(IDD_LOAD_PUBLIC_KEY), NULL, (DLGPROC)DlgProcLoadPublicKey);
+}
diff --git a/plugins/New_GPG/src/resource.h b/plugins/New_GPG/src/resource.h
new file mode 100755
index 0000000000..027e27965c
--- /dev/null
+++ b/plugins/New_GPG/src/resource.h
@@ -0,0 +1,96 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by new_gpg.rc
+//
+#define IDD_LOAD_PUBLIC_KEY 102
+#define IDD_FIRST_RUN 103
+#define IDD_OPT_GPG 104
+#define IDD_OPT_GPG_BIN 105
+#define IDD_BIN_PATH 106
+#define IDD_OPT_GPG_MESSAGES 107
+#define IDD_NEW_KEY 108
+#define IDD_KEY_GEN 109
+#define IDD_LOAD_EXISTING_KEY 110
+#define IDD_KEY_PASSWD 111
+#define IDI_SECURED 112
+#define IDD_IMPORT_KEY 112
+#define IDI_UNSECURED 113
+#define IDD_OPT_GPG_ADVANCED 113
+#define IDC_SET_BIN_PATH 1016
+#define IDC_SET_HOME_DIR 1017
+#define IDC_BIN_PATH 1018
+#define IDC_HOME_DIR 1019
+#define IDC_USERLIST 1020
+#define IDC_LOAD_KEY_BUTTON 1022
+#define ID_OK 1023
+#define ID_LOD_FROM_FILE 1024
+#define ID_LOAD_FROM_FILE 1024
+#define IDC_EDIT1 1025
+#define IDC_PUBLIC_KEY_EDIT 1025
+#define IDC_KEY_PASSWORD 1025
+#define IDC_IN_OPEN_TAG 1025
+#define IDC_KEY_PASSWD 1025
+#define IDC_PASSWORD 1025
+#define IDC_LOG_FILE_EDIT 1025
+#define IDC_BUTTON1 1026
+#define IDC_SAVE_KEY_BUTTON 1026
+#define IDC_GENERATE_KEY 1026
+#define IDC_IGNORE_KEY 1026
+#define IDC_SELECT_EXISTING 1026
+#define IDC_KEY_EMAIL 1026
+#define IDC_DELETE_KEY_BUTTON 1027
+#define IDC_IN_CLOSE_TAG 1027
+#define IDC_KEY_REAL_NAME 1027
+#define IDC_KEY_LIST 1028
+#define IDC_KEY_COMMENT 1028
+#define IDC_OUT_OPEN_TAG 1029
+#define IDC_APPEND_TAGS 1030
+#define IDC_OUT_CLOSE_TAG 1031
+#define IDC_SELECT_KEY 1033
+#define IDC_MESSAGE 1034
+#define ID_IMPORT 1035
+#define IDC_IMPORT_AND_USE 1036
+#define IDC_KEY_TYPE 1039
+#define IDC_KEY_LENGTH 1040
+#define IDC_KEY_EXPIRE_DATE 1043
+#define IDC_EXISTING_KEY_LIST 1045
+#define IDC_BUTTON2 1046
+#define IDC_OTHER 1046
+#define IDC_LOG_FILE_SET 1046
+#define IDC_IMPORT 1046
+#define IDC_SAVE_PASSWORD 1047
+#define IDC_DEBUG_LOG 1048
+#define IDC_JABBER_API 1049
+#define IDC_ENABLE_ENCRYPTION 1050
+#define IDC_KEY_FROM 1051
+#define IDC_DELETE_KEY 1052
+#define IDC_KEYID 1053
+#define IDC_CURRENT_KEY 1054
+#define IDC_DEFAULT_PASSWORD 1055
+#define IDC_KEYSERVER 1058
+#define IDC_FILE_TRANSFERS 1061
+#define IDC_REMOVE_FILTERS 1062
+#define IDC_GENERATE_RANDOM 1063
+#define IDC_AUTO_EXCHANGE 1064
+#define IDC_AUT_EXCHANGE 1065
+#define IDC_BUTTON3 1066
+#define IDC_COPY_KEY 1066
+#define IDC_STRIP_TAGS 1067
+#define IDC_CHECK1 1068
+#define IDC_PRESCENSE_SUBSCRIPTION 1068
+#define IDC_GENERATING_KEY 1069
+#define IDC_GENERATING_TEXT 1070
+#define IDC_KEY_ID 1071
+#define IDC_COMBO1 1072
+#define IDC_ACCOUNT 1072
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 114
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1073
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/New_GPG/src/srmm.cpp b/plugins/New_GPG/src/srmm.cpp
new file mode 100755
index 0000000000..6fc204a9a9
--- /dev/null
+++ b/plugins/New_GPG/src/srmm.cpp
@@ -0,0 +1,88 @@
+// Copyright © 2010-2012 SecureIM developers (baloo and others), sss
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+
+#include "commonheaders.h"
+
+void ShowStatusIcon(HANDLE hContact);
+void setSrmmIcon(HANDLE hContact);
+
+int __cdecl onWindowEvent(WPARAM wParam, LPARAM lParam) {
+
+ MessageWindowEventData *mwd = (MessageWindowEventData *)lParam;
+ if(mwd->uType == MSG_WINDOW_EVT_OPEN || mwd->uType == MSG_WINDOW_EVT_OPENING)
+ {
+ setSrmmIcon(mwd->hContact);
+ }
+ return 0;
+}
+
+
+int __cdecl onIconPressed(WPARAM wParam, LPARAM lParam) {
+ HANDLE hContact = (HANDLE)wParam;
+ HANDLE hMeta = NULL;
+ if(metaIsProtoMetaContacts(hContact))
+ {
+ hMeta = hContact;
+ hContact = metaGetMostOnline(hContact); // âîçüìåì òîò, ÷åðåç êîòîðûé ïîéäåò ñîîáùåíèå
+ }
+ else if(metaIsSubcontact(hContact))
+ hMeta = metaGetContact(hContact);
+ StatusIconClickData *sicd = (StatusIconClickData *)lParam;
+ if(strcmp(sicd->szModule, szGPGModuleName))
+ return 0; // not our event
+
+ void setSrmmIcon(HANDLE);
+ void setClistIcon(HANDLE);
+ bool isContactHaveKey(HANDLE hContact);
+ BYTE enc = DBGetContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 0);
+ if(enc)
+ {
+ DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 0);
+ hMeta?DBWriteContactSettingByte(hMeta, szGPGModuleName, "GPGEncryption", 0):0;
+ setSrmmIcon(hContact);
+ setClistIcon(hContact);
+ }
+ else if(!enc)
+ {
+ if(!isContactHaveKey(hContact))
+ {
+ void ShowLoadPublicKeyDialog();
+ extern map<int, HANDLE> user_data;
+ extern int item_num;
+ item_num = 0; //black magic here
+ user_data[1] = hContact;
+ ShowLoadPublicKeyDialog();
+ }
+ else
+ {
+ DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 1);
+ hMeta?DBWriteContactSettingByte(hMeta, szGPGModuleName, "GPGEncryption", 1):0;
+ setSrmmIcon(hContact);
+ setClistIcon(hContact);
+ return 0;
+ }
+ if(isContactHaveKey(hContact))
+ {
+ DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 1);
+ hMeta?DBWriteContactSettingByte(hMeta, szGPGModuleName, "GPGEncryption", 1):0;
+ setSrmmIcon(hContact);
+ setClistIcon(hContact);
+ }
+ }
+ return 0;
+}
diff --git a/plugins/New_GPG/src/utilities.cpp b/plugins/New_GPG/src/utilities.cpp
new file mode 100755
index 0000000000..242ccc4b67
--- /dev/null
+++ b/plugins/New_GPG/src/utilities.cpp
@@ -0,0 +1,1824 @@
+// Copyright © 2010-2012 sss
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+#include "commonheaders.h"
+
+
+TCHAR* __stdcall UniGetContactSettingUtf(HANDLE hContact, const char *szModule,const char* szSetting, TCHAR* szDef)
+{
+ DBVARIANT dbv = {DBVT_DELETED};
+ TCHAR* szRes;
+ if (DBGetContactSettingTString(hContact, szModule, szSetting, &dbv))
+ return mir_tstrdup(szDef);
+ if(dbv.pszVal)
+ szRes = mir_tstrdup(dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ return szRes;
+}
+
+char* __stdcall UniGetContactSettingUtf(HANDLE hContact, const char *szModule,const char* szSetting, char* szDef)
+{
+ DBVARIANT dbv = {DBVT_DELETED};
+ char* szRes;
+ if (DBGetContactSettingString(hContact, szModule, szSetting, &dbv))
+ return mir_strdup(szDef);
+ if(dbv.pszVal)
+ szRes = mir_strdup(dbv.pszVal);
+ DBFreeVariant(&dbv);
+ return szRes;
+}
+
+
+char *date()
+{
+ setlocale( LC_ALL, "C" );
+ static char d[11];
+ char *tmp = __DATE__, m[4], mn[3] = "01";
+ m[0]=tmp[0];
+ m[1]=tmp[1];
+ m[2]=tmp[2];
+ if(strstr(m,"Jan"))
+ strcpy(mn,"01");
+ else if(strstr(m,"Feb"))
+ strcpy(mn,"02");
+ else if(strstr(m,"Mar"))
+ strcpy(mn,"03");
+ else if(strstr(m,"Apr"))
+ strcpy(mn,"04");
+ else if(strstr(m,"May"))
+ strcpy(mn,"05");
+ else if(strstr(m,"Jun"))
+ strcpy(mn,"06");
+ else if(strstr(m,"Jul"))
+ strcpy(mn,"07");
+ else if(strstr(m,"Aug"))
+ strcpy(mn,"08");
+ else if(strstr(m,"Sep"))
+ strcpy(mn,"09");
+ else if(strstr(m,"Oct"))
+ strcpy(mn,"10");
+ else if(strstr(m,"Nov"))
+ strcpy(mn,"11");
+ else if(strstr(m,"Dec"))
+ strcpy(mn,"12");
+ d[0]=tmp[7];
+ d[1]=tmp[8];
+ d[2]=tmp[9];
+ d[3]=tmp[10];
+ d[4]='.';
+ d[5]=mn[0];
+ d[6]=mn[1];
+ d[7]='.';
+ if (tmp[4] == ' ')
+ d[8] = '0';
+ else
+ d[8]=tmp[4];
+ d[9]=tmp[5];
+ return d;
+}
+
+void GetFilePath(TCHAR *WindowTittle, char *szSetting, TCHAR *szExt, TCHAR *szExtDesc)
+{
+ TCHAR str[MAX_PATH+2] = {0}, *tmp;
+ OPENFILENAME ofn={0};
+ TCHAR filter[512], *pfilter;
+ ofn.lStructSize=CDSIZEOF_STRUCT(OPENFILENAME,lpTemplateName);
+ ofn.Flags=OFN_EXPLORER;
+ ofn.lpstrTitle=TranslateW(WindowTittle);
+ _tcscpy(filter,TranslateW(szExtDesc));
+ pfilter=filter+_tcslen(filter)+1;
+ _tcscpy(pfilter, szExt);
+ pfilter[_tcslen(pfilter)+1] = '\0';
+ pfilter[_tcslen(pfilter)+2] = '\0';
+ ofn.lpstrFilter=filter;
+ tmp = UniGetContactSettingUtf(0, szGPGModuleName, szSetting, _T(""));
+ _tcscpy(str, tmp);
+ mir_free(tmp);
+ if(_tcslen(str)< 2)
+ str[0] = '\0';
+ ofn.lpstrFile=str;
+ ofn.nMaxFile=_MAX_PATH;
+ ofn.nMaxFileTitle=MAX_PATH;
+ if(!GetOpenFileName(&ofn))
+ return;
+ DBWriteContactSettingTString(0, szGPGModuleName, szSetting, str);
+}
+
+TCHAR *GetFilePath(TCHAR *WindowTittle, TCHAR *szExt, TCHAR *szExtDesc, bool save_file)
+{
+ TCHAR *str = new TCHAR [MAX_PATH+2];
+ OPENFILENAME ofn={0};
+ TCHAR filter[512], *pfilter;
+ ofn.lStructSize=CDSIZEOF_STRUCT(OPENFILENAME,lpTemplateName);
+ ofn.Flags=OFN_EXPLORER;
+ ofn.lpstrTitle=TranslateW(WindowTittle);
+ _tcscpy(filter,TranslateW(szExtDesc));
+ pfilter=filter+_tcslen(filter)+1;
+ _tcscpy(pfilter, szExt);
+ pfilter[_tcslen(pfilter)+1] = '\0';
+ pfilter[_tcslen(pfilter)+2] = '\0';
+ ofn.lpstrFilter=filter;
+ _tcscpy(str, _T(""));
+ if(_tcslen(str)< 2)
+ str[0] = '\0';
+ ofn.lpstrFile=str;
+ ofn.nMaxFile=_MAX_PATH;
+ ofn.nMaxFileTitle=MAX_PATH;
+ if(!save_file)
+ {
+ if(!GetOpenFileName(&ofn))
+ {
+ delete [] str;
+ return NULL;
+ }
+ }
+ else
+ {
+ if(!GetSaveFileName(&ofn))
+ {
+ delete [] str;
+ return NULL;
+ }
+ }
+ return str;
+}
+
+void GetFolderPath(TCHAR *WindowTittle, char *szSetting)
+{
+ BROWSEINFO pbi = {0};
+ pbi.lpszTitle = WindowTittle;
+ pbi.ulFlags = BIF_EDITBOX|BIF_NEWDIALOGSTYLE|BIF_SHAREABLE;
+ LPITEMIDLIST pidl = SHBrowseForFolder(&pbi);
+ if (pidl != 0)
+ {
+ TCHAR path[MAX_PATH];
+ if (SHGetPathFromIDList(pidl, path))
+ {
+ DBWriteContactSettingTString(NULL, szGPGModuleName, "szHomePath", path);
+ }
+ IMalloc * imalloc = 0;
+ if (SUCCEEDED(SHGetMalloc(&imalloc)))
+ {
+ imalloc->Free(pidl);
+ imalloc->Release();
+ }
+ }
+}
+
+int LoadKey(WPARAM w, LPARAM l)
+{
+ void ShowLoadPublicKeyDialog();
+ extern map<int, HANDLE> user_data;
+ extern int item_num;
+ item_num = 0; //black magic here
+ user_data[1] = (HANDLE)w;
+ ShowLoadPublicKeyDialog();
+ return 0;
+}
+
+int SendKey(WPARAM w, LPARAM l)
+{
+ HANDLE hContact = (HANDLE)w;
+ if(metaIsProtoMetaContacts(hContact))
+ hContact = metaGetMostOnline(hContact);
+ char *szMessage;
+ {
+ char *proto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ char setting[64];
+ if(proto)
+ {
+ strcpy(setting, proto);
+ strcat(setting, "_GPGPubKey");
+ szMessage = UniGetContactSettingUtf(NULL, szGPGModuleName, setting, "");
+ }
+ if(!szMessage[0])
+ {
+ mir_free(szMessage);
+ szMessage = UniGetContactSettingUtf(NULL, szGPGModuleName, "GPGPubKey", "");
+ }
+ }
+ if(szMessage[0])
+ {
+ BYTE enc = DBGetContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 0);
+ DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 0);
+ CallContactService(hContact, PSS_MESSAGE, (WPARAM)PREF_UTF, (LPARAM)szMessage);
+ HistoryLog(hContact, db_event("Public key sent", 0, 0, DBEF_SENT));
+ DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", enc);
+ }
+ mir_free(szMessage);
+ return 0;
+}
+
+extern HANDLE hLoadPublicKey, hToggleEncryption;
+
+int ToggleEncryption(WPARAM w, LPARAM l)
+{
+ HANDLE hContact = (HANDLE)w;
+ BYTE enc = 0;
+ if(metaIsProtoMetaContacts(hContact))
+ enc = DBGetContactSettingByte(metaGetMostOnline(hContact), szGPGModuleName, "GPGEncryption", 0);
+ else
+ enc = DBGetContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 0);
+ if(metaIsProtoMetaContacts(hContact))
+ {
+ HANDLE hcnt = NULL;
+ if(MessageBox(0, _T("Do you want to toggle encryption for all subcontacts ?"), _T("Metacontact detected"), MB_YESNO) == IDYES)
+ {
+ int count = metaGetContactsNum(hContact);
+ for(int i = 0; i < count; i++)
+ {
+ hcnt = metaGetSubcontact(hContact, i);
+ if(hcnt)
+ DBWriteContactSettingByte(hcnt, szGPGModuleName, "GPGEncryption", enc?0:1);
+ }
+ DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", enc?0:1);
+ }
+ }
+ else
+ DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", enc?0:1);
+ void setSrmmIcon(HANDLE hContact);
+ void setClistIcon(HANDLE hContact);
+ setSrmmIcon(hContact);
+ setClistIcon(hContact);
+ enc = enc?0:1;
+ CLISTMENUITEM mi = {0};
+ mi.cbSize=sizeof(mi);
+ mi.flags = CMIM_NAME;
+ enc?mi.pszName="Turn off GPG encryption":mi.pszName="Turn on GPG encryption";
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hToggleEncryption, (LPARAM)&mi);
+ return 0;
+}
+
+int OnPreBuildContactMenu(WPARAM w, LPARAM l)
+{
+ HANDLE hContact = (HANDLE)w;
+ if(metaIsProtoMetaContacts(hContact))
+ hContact = metaGetMostOnline(hContact);
+ CLISTMENUITEM mi = {0};
+ mi.cbSize=sizeof(mi);
+ mi.flags = CMIM_NAME;
+ TCHAR *tmp = UniGetContactSettingUtf(hContact, szGPGModuleName, "GPGPubKey", _T(""));
+ if(_tcslen(tmp) < 1)
+ {
+ DBDeleteContactSetting(hContact, szGPGModuleName, "GPGEncryption");
+ mi.flags += CMIM_FLAGS | CMIF_GRAYED;
+ }
+ else
+ mi.flags = CMIM_NAME | CMIM_FLAGS;
+ mi.pszName = DBGetContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 0)?"Turn off GPG encryption":"Turn on GPG encryption";
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hToggleEncryption, (LPARAM)&mi);
+ return 0;
+}
+
+
+list<wstring> transfers;
+extern bool bFileTransfers;
+
+int onProtoAck(WPARAM w, LPARAM l)
+{
+ ACKDATA *ack=(ACKDATA*)l;
+ CCSDATA *ccs=(CCSDATA*)ack->lParam;
+
+ if(ack->type == ACKTYPE_FILE && bFileTransfers)
+ {
+ switch(ack->result)
+ {
+ case ACKRESULT_DENIED: case ACKRESULT_FAILED:
+ break;
+ case ACKRESULT_SUCCESS:
+ {
+ PROTOFILETRANSFERSTATUS *f = (PROTOFILETRANSFERSTATUS*) ack->hProcess;
+ TCHAR *filename = NULL;
+ if(f->flags & PFTS_UNICODE)
+ {
+ if(f->tszCurrentFile && f->tszCurrentFile[0])
+ filename = mir_wstrdup(f->tszCurrentFile);
+ if(!filename)
+ return 0;
+ }
+ else
+ {
+ if(f->szCurrentFile && f->szCurrentFile[0])
+ filename = mir_utf8decodeT(f->szCurrentFile);
+ if(!filename)
+ return 0;
+ }
+ if(_tcsstr(filename, _T(".gpg"))) //decrypt it
+ { //process encrypted file
+ if(_waccess(f->tszCurrentFile, 0) == -1)
+ {
+ if(errno == ENOENT)
+ return 0;
+ }
+ string out;
+ DWORD code;
+ pxResult result;
+ wstring cmd = _T(" -o ");
+ wstring file = filename;
+ wstring::size_type p1 = file.rfind(_T(".gpg"));
+ file.erase(p1, _tcslen(_T(".gpg")));
+ if(_waccess(file.c_str(), 0) != -1)
+ {
+ if(MessageBox(0, _T("Target file exists, do you want to replace it ?"), _T("Warning"), MB_YESNO) == IDNO)
+ return 0;
+ }
+ DeleteFile(file.c_str());
+ file.insert(0, _T("\""));
+ file.insert(file.length(), _T("\" "));
+ cmd += file;
+ extern TCHAR *password;
+ { // password
+ TCHAR *pass = NULL;
+ char *keyid = UniGetContactSettingUtf(ack->hContact, szGPGModuleName, "KeyID", "");
+ if(strlen(keyid) > 0)
+ {
+ string dbsetting = "szKey_";
+ dbsetting += keyid;
+ dbsetting += "_Password";
+ pass = UniGetContactSettingUtf(NULL, szGPGModuleName, dbsetting.c_str(), _T(""));
+ if(_tcslen(pass) > 0)
+ debuglog<<time_str()<<": info: found password in database for key id: "<<keyid<<", trying to decrypt message from "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ack->hContact, GCDNF_TCHAR)<<" with password\n";
+ }
+ else
+ {
+ pass = UniGetContactSettingUtf(NULL, szGPGModuleName, "szKeyPassword", _T(""));
+ if(_tcslen(pass) > 0)
+ debuglog<<time_str()<<": info: found password for all keys in database, trying to decrypt message from "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ack->hContact, GCDNF_TCHAR)<<" with password\n";
+ }
+ if(_tcslen(pass) > 0)
+ {
+ cmd += _T("--passphrase \"");
+ cmd += pass;
+ cmd += _T("\" ");
+ }
+ else if(password)
+ {
+ debuglog<<time_str()<<": info: found password in memory, trying to decrypt message from "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ack->hContact, GCDNF_TCHAR)<<" with password\n";
+ cmd += _T("--passphrase \"");
+ cmd += password;
+ cmd += _T("\" ");
+ }
+ else
+ debuglog<<time_str()<<": info: passwords not found in database or memory, trying to decrypt message from "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ack->hContact, GCDNF_TCHAR)<<" with out password\n";
+ mir_free(pass);
+ mir_free(keyid);
+ }
+ cmd += _T(" -d \"");
+ cmd += filename;
+ cmd += _T("\"");
+ gpg_execution_params params;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ boost::thread *gpg_thread = new boost::thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread->timed_join(boost::posix_time::minutes(15)))
+ {
+ delete gpg_thread;
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ return 0;
+ }
+ while(out.find("public key decryption failed: bad passphrase") != string::npos)
+ {
+ extern bool _terminate;
+ extern HANDLE new_key_hcnt;
+ extern boost::mutex new_key_hcnt_mutex;
+ debuglog<<time_str()<<": info: failed to decrypt messaage from "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ack->hContact, GCDNF_TCHAR)<<" password needed, trying to get one\n";
+ if(_terminate)
+ break;
+ { //save inkey id
+ string::size_type s = out.find(" encrypted with ");
+ s = out.find(" ID ", s);
+ s += strlen(" ID ");
+ string::size_type s2 = out.find(",",s);
+ if(metaIsProtoMetaContacts(ack->hContact))
+ DBWriteContactSettingString(metaGetMostOnline(ack->hContact), szGPGModuleName, "InKeyID", out.substr(s, s2-s).c_str());
+ else
+ DBWriteContactSettingString(ack->hContact, szGPGModuleName, "InKeyID", out.substr(s, s2-s).c_str());
+ }
+ void ShowLoadKeyPasswordWindow();
+ new_key_hcnt_mutex.lock();
+ new_key_hcnt = ack->hContact;
+ ShowLoadKeyPasswordWindow();
+ wstring cmd2 = cmd;
+ if(password)
+ {
+ debuglog<<time_str()<<": info: found password in memory, trying to decrypt message from "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ack->hContact, GCDNF_TCHAR)<<"\n";
+ wstring tmp = _T("--passphrase \"");
+ tmp += password;
+ tmp += _T("\" ");
+ cmd2.insert(0, tmp);
+ }
+ out.clear();
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd2;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ gpg_thread = gpg_thread = new boost::thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread->timed_join(boost::posix_time::seconds(15)))
+ {
+ delete gpg_thread;
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ DeleteFile(filename);
+ return 0;
+ }
+ if(result == pxNotFound)
+ {
+ DeleteFile(filename);
+ return 0;
+ }
+ }
+ DeleteFile(filename);
+ mir_free(filename);
+ }
+ }
+ break;
+ }
+ }
+ else if(ack->type == ACKTYPE_MESSAGE)
+ {
+ extern std::list<HANDLE> sent_msgs;
+ if(!sent_msgs.empty())
+ {
+ if(ack->result == ACKRESULT_FAILED)
+ {
+ std::list<HANDLE>::iterator it = std::find(sent_msgs.begin(), sent_msgs.end(), ack->hProcess);
+ if(it != sent_msgs.end())
+ {
+ HistoryLog(ack->hContact, db_event("Failed to send encrypted message", 0,0, 0));
+
+ }
+ }
+ else if(ack->result == ACKRESULT_SUCCESS)
+ {
+ std::list<HANDLE>::iterator it = std::find(sent_msgs.begin(), sent_msgs.end(), ack->hProcess);
+ if(it != sent_msgs.end())
+ sent_msgs.erase(it);
+ }
+ }
+ }
+ return 0;
+}
+
+std::wstring encrypt_file(HANDLE hContact, TCHAR *filename)
+{
+ string out;
+ DWORD code;
+ pxResult result;
+ HANDLE hcnt = metaIsProtoMetaContacts(hContact)?metaGetMostOnline(hContact):hContact;
+ wstring cmd = _T("--batch --yes -r ");
+ char *keyid = UniGetContactSettingUtf(hcnt, szGPGModuleName, "KeyID", "");
+ TCHAR *szKeyid = mir_a2t(keyid);
+ TCHAR *name = _tcsrchr(filename,_T('\\'));
+ if( !name )
+ name = filename;
+ else
+ name++;
+ TCHAR *file_out = new TCHAR [_tcslen(filename)+4];
+ mir_sntprintf(file_out, _tcslen(name)+7, _T("%s.gpg"), name);
+ cmd += szKeyid;
+ if(DBGetContactSettingByte(hcnt, szGPGModuleName, "bAlwaysTrust", 0))
+ cmd += _T(" --trust-model always ");
+ mir_free(szKeyid);
+ mir_free(keyid);
+ cmd += _T(" -o \"");
+ TCHAR *temp = _tgetenv(_T("TEMP"));
+ cmd += temp;
+ cmd += _T("\\");
+ cmd += file_out;
+ wstring path_out = temp;
+ path_out += _T("\\");
+ path_out += file_out;
+ DeleteFile(path_out.c_str());
+ cmd += _T("\" ");
+ mir_free(temp);
+ cmd += _T(" -e \"");
+ cmd += filename;
+ cmd += _T("\" ");
+ gpg_execution_params params;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ mir_free(keyid);
+ delete [] file_out;
+ boost::thread *gpg_thread = new boost::thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread->timed_join(boost::posix_time::seconds(180)))
+ {
+ delete gpg_thread;
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ return 0;
+ }
+ if(out.find("There is no assurance this key belongs to the named user") != string::npos)
+ {
+ out.clear();
+ if(MessageBox(0, _T("We trying to encrypt with untrusted key, do you want to trust this key permanently ?"), _T("Warning"), MB_YESNO) == IDYES)
+ {
+ DBWriteContactSettingByte(hcnt, szGPGModuleName, "bAlwaysTrust", 1);
+ cmd.insert(0, _T("--trust-model always "));
+ gpg_thread = new boost::thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread->timed_join(boost::posix_time::seconds(180)))
+ {
+ delete gpg_thread;
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ return 0;
+ }
+ }
+ else
+ return 0;
+ }
+ return path_out;
+}
+
+//from secureim partially
+int onSendFile(WPARAM w, LPARAM l)
+{
+ if(!bFileTransfers)
+ return CallService(MS_PROTO_CHAINSEND, w, l);
+ CCSDATA *ccs=(CCSDATA*)l;
+ if(isContactSecured(ccs->hContact))
+ {
+
+ DWORD flags = (DWORD)ccs->wParam; //check for PFTS_UNICODE here
+ int i;
+// if(flags & PFTS_UNICODE) //this does not work ....
+ if(StriStr(ccs->szProtoService, "/sendfilew"))
+ {
+ TCHAR **file=(TCHAR **)ccs->lParam;
+ for(i = 0; file[i]; i++)
+ {
+ if(_waccess(file[i], 0) == -1)
+ if(errno == ENOENT)
+ return 0; //we do not want to send file unencrypted (sometimes ack have wrong info)
+ if (_tcsstr(file[i],_T(".gpg")))
+ continue;
+ std::wstring path_out = encrypt_file(ccs->hContact, file[i]);
+ mir_free(file[i]);
+ file[i] = mir_tstrdup(path_out.c_str());
+ transfers.push_back(path_out);
+ }
+ }
+ else
+ {
+ char **file = (char**) ccs->lParam;
+ for(i = 0; file[i]; i++)
+ {
+ if(_access(file[i], 0) == -1)
+ if(errno == ENOENT)
+ return 0; //we do not want to send file unencrypted (sometimes ack have wrong info)
+ if (strstr(file[i],".gpg"))
+ continue;
+ TCHAR *tmp = mir_utf8decodeT(file[i]);
+ std::wstring path_out = encrypt_file(ccs->hContact, tmp);
+ mir_free(tmp);
+ char* tmp2 = mir_utf8encodeW(path_out.c_str());
+ mir_free(file[i]);
+ file[i] = tmp2;
+ transfers.push_back(path_out);
+
+ }
+ }
+ }
+ return CallService(MS_PROTO_CHAINSEND, w, l);
+}
+
+void storeOutput(HANDLE ahandle, string *output)
+{
+ BOOL success;
+ char readbuffer[4096] = {0};
+ unsigned long transfered, available;
+
+ do {
+ PeekNamedPipe(ahandle,NULL,0,NULL,&available,NULL);
+ if (!available)
+ continue;
+ success=ReadFile(ahandle,readbuffer,sizeof(readbuffer),&transfered,NULL);
+ if (success && transfered)
+ output->append(readbuffer, 4096);
+ } while (available>0);
+}
+
+void HistoryLog(HANDLE hContact, db_event evt)
+{
+ DBEVENTINFO Event = {0};
+ Event.cbSize = sizeof(Event);
+ Event.szModule = szGPGModuleName;
+ Event.eventType = evt.eventType;
+ Event.flags = evt.flags;
+ if(!evt.timestamp)
+ Event.timestamp = (DWORD)time(NULL);
+ else
+ Event.timestamp = evt.timestamp;
+ Event.cbBlob = strlen((char*)evt.pBlob)+1;
+ Event.pBlob = (PBYTE)_strdup((char*)evt.pBlob);
+ CallService(MS_DB_EVENT_ADD, (WPARAM)(HANDLE)hContact,(LPARAM)&Event);
+}
+
+static int ControlAddStringUtf(HWND ctrl, DWORD msg, const TCHAR *szString)
+{
+ int item = -1;
+ item = SendMessage(ctrl, msg, 0, (LPARAM)szString);
+ return item;
+}
+
+int ComboBoxAddStringUtf(HWND hCombo, const TCHAR *szString, DWORD data)
+{
+ int item = ControlAddStringUtf(hCombo, CB_ADDSTRING, szString);
+ SendMessage(hCombo, CB_SETITEMDATA, item, data);
+
+ return item;
+}
+
+
+int GetJabberInterface(WPARAM w, LPARAM l) //get interface for all jabber accounts, options later
+{
+ extern list <JabberAccount*> Accounts;
+ void AddHandlers();
+ int count = 0;
+ PROTOACCOUNT **accounts;
+ ProtoEnumAccounts(&count, &accounts);
+ list <JabberAccount*>::iterator p;
+ Accounts.clear();
+ Accounts.push_back(new JabberAccount);
+ p = Accounts.begin();
+ (*p)->setAccountNumber(0);
+ for(int i = 0; i < count; i++) //get only jabber accounts from all accounts
+ {
+ IJabberInterface *JIftmp = getJabberApi(accounts[i]->szModuleName);
+ int a = 0;
+ if(JIftmp)
+ {
+ (*p)->setJabberInterface(JIftmp);
+ if(accounts[i]->tszAccountName)
+ {
+ TCHAR* tmp = mir_tstrdup(accounts[i]->tszAccountName);
+ (*p)->setAccountName(tmp);
+ }
+ else
+ {
+ TCHAR *tmp = mir_a2t(accounts[i]->szModuleName);
+ (*p)->setAccountName(tmp);
+ }
+ (*p)->setAccountNumber(a);
+ a++;
+ Accounts.push_back(new JabberAccount);
+ p++;
+ }
+ }
+ Accounts.pop_back();
+ AddHandlers();
+ return 0;
+}
+
+static JABBER_HANDLER_FUNC SendHandler(IJabberInterface *ji, HXML node, void *pUserData)
+{
+ HXML local_node = node;
+ for(int n = 0; n <= xi.getChildCount(node); n++)
+ {
+ LPCTSTR str = xi.getText(local_node);
+ LPCTSTR nodename = xi.getName(local_node);
+ if(str)
+ {
+ if(_tcsstr(str, _T("-----BEGIN PGP MESSAGE-----")) && _tcsstr(str, _T("-----END PGP MESSAGE-----")))
+ {
+ wstring data = str;
+ xi.setText(local_node, _T("This message is encrypted."));
+ wstring::size_type p1 = data.find(_T("-----BEGIN PGP MESSAGE-----")) + _tcslen(_T("-----BEGIN PGP MESSAGE-----"));
+ while(data.find(_T("Version: "), p1) != wstring::npos)
+ {
+ p1 = data.find(_T("Version: "), p1);
+ p1 = data.find(_T("\n"), p1);
+ }
+ while(data.find(_T("Comment: "), p1) != wstring::npos)
+ {
+ p1 = data.find(_T("Comment: "), p1);
+ p1 = data.find(_T("\n"), p1);
+ }
+ while(data.find(_T("Encoding: "), p1) != wstring::npos)
+ {
+ p1 = data.find(_T("Encoding: "), p1);
+ p1 = data.find(_T("\n"), p1);
+ }
+ p1+=2;
+ wstring::size_type p2 = data.find(_T("-----END PGP MESSAGE-----"));
+ HXML encrypted_data = xi.addChild(node, _T("x"), data.substr(p1, p2-p1).c_str());
+ xi.addAttr(encrypted_data, _T("xmlns"), _T("jabber:x:encrypted"));
+ return FALSE;
+ }
+ }
+ if(bPresenceSigning && nodename)
+ {
+ if(_tcsstr(nodename, _T("status")))
+ {
+ TCHAR *path_c = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T(""));
+ wstring path_out = path_c;
+ wstring file = toUTF16(get_random(10));
+ mir_free(path_c);
+ path_out += _T("\\tmp\\");
+ path_out += file;
+ DeleteFile(path_out.c_str());
+ wfstream f(path_out.c_str(), std::ios::out);
+ f<<toUTF8(str).c_str();
+ f.close();
+ if(_waccess(path_out.c_str(), 0) == -1)
+ {
+ if(errno == ENOENT)
+ {
+ debuglog<<time_str()<<": info: Failed to write prescense in file\n";
+ return FALSE;
+ }
+ }
+ {
+ extern TCHAR *password;
+ string out;
+ DWORD code;
+ wstring cmd;
+ {
+ char *inkeyid;
+ {
+ char *proto = ji->Sys()->GetModuleName();
+ char setting[64];
+ strcpy(setting, proto);
+ strcat(setting, "_KeyID");
+ inkeyid = UniGetContactSettingUtf(NULL, szGPGModuleName, setting, "");
+ if(!inkeyid[0])
+ {
+ mir_free(inkeyid);
+ inkeyid = UniGetContactSettingUtf(NULL, szGPGModuleName, "KeyID", "");
+ }
+ }
+ TCHAR *pass = NULL;
+ if(inkeyid[0])
+ {
+ string dbsetting = "szKey_";
+ dbsetting += inkeyid;
+ dbsetting += "_Password";
+ pass = UniGetContactSettingUtf(NULL, szGPGModuleName, dbsetting.c_str(), _T(""));
+ if(pass[0])
+ debuglog<<time_str()<<": info: found password in database for key id: "<<inkeyid<<", trying to encrypt message from self with password\n";
+ }
+ else
+ {
+ pass = UniGetContactSettingUtf(NULL, szGPGModuleName, "szKeyPassword", _T(""));
+ if(pass[0])
+ debuglog<<time_str()<<": info: found password for all keys in database, trying to encrypt message from self with password\n";
+ }
+ if(pass[0])
+ {
+ cmd += _T("--passphrase \"");
+ cmd += pass;
+ cmd += _T("\" ");
+ }
+ else if(password)
+ {
+ debuglog<<time_str()<<": info: found password in memory, trying to encrypt message from self with password\n";
+ cmd += _T("--passphrase \"");
+ cmd += password;
+ cmd += _T("\" ");
+ }
+ else
+ debuglog<<time_str()<<": info: passwords not found in database or memory, trying to encrypt message from self with out password\n";
+ mir_free(pass);
+ mir_free(inkeyid);
+ }
+ cmd += _T("--local-user ");
+ path_c = UniGetContactSettingUtf(NULL, szGPGModuleName, "KeyID", _T(""));
+ cmd += path_c;
+ cmd += _T(" --default-key ");
+ cmd += path_c;
+ mir_free(path_c);
+ cmd += _T(" --batch --yes -a -s \"");
+ cmd += path_out;
+ cmd += _T("\" ");
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::seconds(15)))
+ {
+ gpg_thread.~thread();
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<"GPG execution timed out, aborted\n";
+ }
+ DeleteFile(path_out.c_str());
+ path_out += _T(".asc");
+ f.open(path_out.c_str(), std::ios::in | std::ios::ate | std::ios::binary);
+ wstring data;
+ if(f.is_open())
+ {
+ std::wifstream::pos_type size = f.tellg();
+ TCHAR *tmp = new TCHAR [(std::ifstream::pos_type)size+(std::ifstream::pos_type)1];
+ f.seekg(0, std::ios::beg);
+ f.read(tmp, size);
+ tmp[size]= '\0';
+ data.append(tmp);
+ delete [] tmp;
+ f.close();
+ DeleteFile(path_out.c_str());
+ }
+ if(data.empty())
+ {
+ debuglog<<time_str()<<": info: Failed to read prescense sign from file\n";
+ return FALSE;
+ }
+ if(data.find(_T("-----BEGIN PGP MESSAGE-----")) != wstring::npos && data.find(_T("-----END PGP MESSAGE-----")) != wstring::npos)
+ {
+ wstring::size_type p1 = data.find(_T("-----BEGIN PGP MESSAGE-----")) + _tcslen(_T("-----BEGIN PGP MESSAGE-----"));
+ if(data.find(_T("Version: "), p1) != wstring::npos)
+ {
+ p1 = data.find(_T("Version: "), p1);
+ p1 = data.find(_T("\n"), p1);
+ if(data.find(_T("Version: "), p1) != wstring::npos)
+ {
+ p1 = data.find(_T("Version: "), p1);
+ p1 = data.find(_T("\n"), p1)+1;
+ }
+ else
+ p1 += 1;
+ }
+ if(data.find(_T("Comment: "), p1) != wstring::npos)
+ {
+ p1 = data.find(_T("Comment: "), p1);
+ p1 = data.find(_T("\n"), p1);
+ if(data.find(_T("Comment: "), p1) != wstring::npos)
+ {
+ p1 = data.find(_T("Comment: "), p1);
+ p1 = data.find(_T("\n"), p1)+1;
+ }
+ else
+ p1 += 1;
+ }
+ else
+ p1+=1;
+ wstring::size_type p2 = data.find(_T("-----END PGP MESSAGE-----"));
+ HXML encrypted_data = xi.addChild(node, _T("x"), data.substr(p1, p2-p1).c_str());
+ xi.addAttr(encrypted_data, _T("xmlns"), _T("jabber:x:signed"));
+ }
+ return FALSE;
+ }
+ }
+ }
+ local_node = xi.getChild(node, n);
+ }
+ return FALSE;
+}
+
+//boost::mutex sign_file_mutex;
+
+static JABBER_HANDLER_FUNC PrescenseHandler(IJabberInterface *ji, HXML node, void *pUserData)
+{
+ HXML local_node = node;
+ for(int n = 0; n <= xi.getChildCount(node); n++)
+ {
+ LPCTSTR str = xi.getText(local_node);
+ LPCTSTR nodename = xi.getName(local_node);
+ if(nodename)
+ {
+ if(_tcsstr(nodename, _T("x")))
+ {
+ for(int n = 0; n < xi.getAttrCount(local_node); n++)
+ {
+ LPCTSTR name = xi.getAttrName(local_node, n);
+ LPCTSTR value = xi.getAttrValue(local_node, name);
+ if(_tcsstr(value, _T("jabber:x:signed")))
+ {
+ LPCTSTR data = xi.getText(local_node);
+ wstring sign = _T("-----BEGIN PGP MESSAGE-----\n\n");
+ wstring file = toUTF16(get_random(10));
+ sign += data;
+ sign += _T("\n-----END PGP MESSAGE-----\n");
+ TCHAR *path_c = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T(""));
+ wstring path_out = path_c;
+ mir_free(path_c);
+ path_out += _T("\\tmp\\");
+ path_out += file;
+// sign_file_mutex.lock();
+ DeleteFile(path_out.c_str());
+ wfstream f(path_out.c_str(), std::ios::out);
+ while(!f.is_open())
+ f.open(path_out.c_str(), std::ios::out);
+ f<<toUTF8(sign).c_str();
+ f.close();
+ if(_waccess(path_out.c_str(), 0) == -1)
+ {
+ if(errno == ENOENT)
+ {
+// sign_file_mutex.unlock();
+ debuglog<<time_str()<<": info: Failed to write sign in file\n";
+ return FALSE;
+ }
+ }
+ { //gpg
+ string out;
+ DWORD code;
+ wstring cmd = _T(" --verify -a \"");
+ cmd += path_out;
+ cmd += _T("\"");
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::seconds(15)))
+ {
+ gpg_thread.~thread();
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ return FALSE;
+ }
+ if(result == pxNotFound)
+ {
+ return FALSE;
+ }
+ DeleteFile(path_out.c_str());
+ if(out.find("key ID ") != string::npos)
+ {
+ //need to get hcontact here, i can get jid from hxml, and get handle from jid, maybe exists better way ?
+ string::size_type p1 = out.find("key ID ") + strlen("key ID ");
+ string::size_type p2 = out.find("\n", p1);
+ if(p1 != string::npos && p2 != string::npos)
+ {
+ HANDLE hContact = NULL;
+ {
+ extern list <JabberAccount*> Accounts;
+ list <JabberAccount*>::iterator p = Accounts.begin();
+ for(unsigned int i = 0; i < Accounts.size(); i++, p++)
+ {
+ if(!(*p))
+ break;
+ hContact = (*p)->getJabberInterface()->Sys()->ContactFromJID(xi.getAttrValue(node, _T("from")));
+ if(hContact)
+ hcontact_data[hContact].key_in_prescense = out.substr(p1, p2-p1-1).c_str();
+ }
+ }
+ }
+ }
+ }
+ return FALSE;
+ }
+ }
+ }
+ }
+ local_node = xi.getChild(node, n);
+ }
+ return FALSE;
+}
+
+static JABBER_HANDLER_FUNC MessageHandler(IJabberInterface *ji, HXML node, void *pUserData)
+{
+ return FALSE;
+}
+
+
+
+
+void AddHandlers()
+{
+ extern list<JabberAccount*> Accounts;
+ list<JabberAccount*>::iterator end = Accounts.end();
+ for(list<JabberAccount*>::iterator p = Accounts.begin(); p != end; p++)
+ {
+ if(!(*p))
+ break;
+ if((*p)->getSendHandler() == INVALID_HANDLE_VALUE)
+ (*p)->setSendHandler((*p)->getJabberInterface()->Net()->AddSendHandler((JABBER_HANDLER_FUNC)SendHandler));
+ if((*p)->getPrescenseHandler() == INVALID_HANDLE_VALUE)
+ (*p)->setPrescenseHandler((*p)->getJabberInterface()->Net()->AddPresenceHandler((JABBER_HANDLER_FUNC)PrescenseHandler));
+// if((*p)->getMessageHandler() == INVALID_HANDLE_VALUE)
+// (*p)->setMessageHandler((*p)->getJabberInterface()->Net()->AddMessageHandler((JABBER_HANDLER_FUNC)MessageHandler, JABBER_MESSAGE_TYPE_ANY ,NULL,NULL));
+ if(bAutoExchange)
+ {
+ (*p)->getJabberInterface()->Net()->RegisterFeature(_T("GPG_Key_Auto_Exchange:0"), _T("Indicates that gpg installed and configured to public key auto exchange (currently implemented in new_gpg Miranda IM plugin)"));
+ (*p)->getJabberInterface()->Net()->AddFeatures(_T("GPG_Key_Auto_Exchange:0\0\0"));
+ }
+ }
+}
+
+bool isContactSecured(HANDLE hContact)
+{
+ BYTE gpg_enc = DBGetContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 0);
+ if(!gpg_enc)
+ {
+ debuglog<<time_str()<<": encryption is turned off for "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)<<"\n";
+ return false;
+ }
+ if(!metaIsProtoMetaContacts(hContact))
+ {
+ TCHAR *key = UniGetContactSettingUtf(hContact, szGPGModuleName, "GPGPubKey", _T(""));
+ if(!key[0])
+ {
+ mir_free(key);
+ debuglog<<time_str()<<": encryption is turned off for "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)<<"\n";
+ return false;
+ }
+ mir_free(key);
+ }
+ debuglog<<time_str()<<": encryption is turned on for "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)<<"\n";
+ return true;
+}
+
+bool isContactHaveKey(HANDLE hContact)
+{
+ TCHAR *key = UniGetContactSettingUtf(hContact, szGPGModuleName, "GPGPubKey", _T(""));
+ if(_tcslen(key) > 0)
+ {
+ mir_free(key);
+ return true;
+ }
+ mir_free(key);
+ return false;
+}
+
+bool isGPGKeyExist()
+{
+ TCHAR *id = UniGetContactSettingUtf(NULL, szGPGModuleName, "KeyID", _T(""));
+ char *key = UniGetContactSettingUtf(NULL, szGPGModuleName, "GPGPubKey", "");
+ if(id[0] && key[0])
+ {
+ mir_free(id);
+ mir_free(key);
+ return true;
+ }
+ mir_free(id);
+ mir_free(key);
+ return false;
+}
+bool isGPGValid()
+{
+ TCHAR *tmp;
+ bool gpg_exists = false, is_valid = true;
+ tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szGpgBinPath", _T(""));
+ if(_waccess(tmp, 0) != -1)
+ gpg_exists = true;
+ else
+ {
+ mir_free(tmp);
+ TCHAR *path = (TCHAR*)mir_alloc(sizeof(TCHAR)*MAX_PATH);
+ char *mir_path = (char*)mir_alloc(MAX_PATH);
+ CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)"\\", (LPARAM)mir_path);
+ SetCurrentDirectoryA(mir_path);
+ tmp = mir_a2t(mir_path);
+ mir_free(mir_path);
+ //mir_realloc(path, (_tcslen(path)+64)*sizeof(TCHAR));
+ TCHAR *gpg_path = (TCHAR*)mir_alloc(sizeof(TCHAR)*MAX_PATH);
+ _tcscpy(gpg_path, tmp);
+ _tcscat(gpg_path, _T("\\GnuPG\\gpg.exe"));
+ mir_free(tmp);
+ if(_waccess(gpg_path, 0) != -1)
+ {
+ gpg_exists = true;
+ _tcscpy(path, _T("GnuPG\\gpg.exe"));
+ }
+ mir_free(gpg_path);
+ tmp = mir_tstrdup(path);
+ mir_free(path);
+ }
+ DWORD len = MAX_PATH;
+ if(gpg_exists)
+ {
+ DBWriteContactSettingTString(NULL, szGPGModuleName, "szGpgBinPath", tmp);
+ string out;
+ DWORD code;
+ wstring cmd = _T("--version");
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ gpg_valid = true;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::seconds(10)))
+ {
+ gpg_thread.~thread();
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ }
+ gpg_valid = false;
+ string::size_type p1 = out.find("(GnuPG) ");
+ if(p1 == string::npos)
+ is_valid = false;
+ }
+ mir_free(tmp); tmp = NULL;
+ if(!gpg_exists)
+ {
+ wstring path_ = _wgetenv(_T("APPDATA"));
+ path_ += _T("\\GnuPG");
+ tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", (TCHAR*)path_.c_str());
+ }
+ if(tmp)
+ mir_free(tmp);
+ return is_valid;
+}
+
+#define NEWTSTR_MALLOC(A) (A==NULL)?NULL:strcpy((char*)mir_alloc(sizeof(char)*(strlen(A)+1)),A)
+
+const bool StriStr(const char *str, const char *substr)
+{
+ bool i = false;
+ char *str_up = NEWTSTR_MALLOC(str);
+ char *substr_up = NEWTSTR_MALLOC(substr);
+
+ CharUpperBuffA(str_up, strlen(str_up));
+ CharUpperBuffA(substr_up, strlen(substr_up));
+
+ if(strstr (str_up, substr_up))
+ i = true;
+
+ mir_free(str_up);
+ mir_free(substr_up);
+
+ return i;
+}
+
+bool IsOnline(HANDLE hContact)
+{
+ if(DBGetContactSettingByte(hContact, szGPGModuleName, "Status", 0) == ID_STATUS_OFFLINE)
+ return false;
+ return true;
+}
+
+//from secureim
+#include <process.h>
+
+struct TFakeAckParams {
+ inline TFakeAckParams( HANDLE p1, HANDLE p2, LONG p3, LPCSTR p4 ) :
+ hEvent( p1 ),
+ hContact( p2 ),
+ id( p3 ),
+ msg( p4 )
+ {}
+
+ HANDLE hEvent;
+ HANDLE hContact;
+ LONG id;
+ LPCSTR msg;
+};
+
+int SendBroadcast( HANDLE hContact, int type, int result, HANDLE hProcess, LPARAM lParam ) {
+ ACKDATA ack;
+ memset(&ack,0,sizeof(ack));
+ ack.cbSize = sizeof( ACKDATA );
+ ack.szModule = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ ack.hContact = hContact;
+ ack.type = type;
+ ack.result = result;
+ ack.hProcess = hProcess;
+ ack.lParam = lParam;
+ return CallService( MS_PROTO_BROADCASTACK, 0, ( LPARAM )&ack );
+}
+
+
+
+unsigned __stdcall sttFakeAck( LPVOID param ) {
+
+ TFakeAckParams* tParam = ( TFakeAckParams* )param;
+ WaitForSingleObject( tParam->hEvent, INFINITE );
+
+ Sleep( 100 );
+ if ( tParam->msg == NULL )
+ SendBroadcast( tParam->hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, ( HANDLE )tParam->id, 0 );
+ else
+ SendBroadcast( tParam->hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, ( HANDLE )tParam->id, LPARAM( tParam->msg ));
+
+ CloseHandle( tParam->hEvent );
+ delete tParam;
+
+ return 0;
+}
+
+
+int returnNoError(HANDLE hContact) {
+ HANDLE hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
+ unsigned int tID;
+ CloseHandle( (HANDLE) _beginthreadex(NULL, 0, sttFakeAck, new TFakeAckParams(hEvent,hContact,777,0), 0, &tID) );
+ SetEvent( hEvent );
+ return 777;
+}
+// end from secureim
+
+
+string toUTF8(wstring str)
+{
+ string ustr;
+ try{
+ utf8::utf16to8(str.begin(), str.end(), back_inserter(ustr));
+ }
+ catch(const utf8::exception& e)
+ {
+ debuglog<<std::string("utf8cpp encoding exception: ")+(char*)e.what();
+ //TODO
+ }
+ return ustr;
+}
+
+
+
+wstring toUTF16(string str) //convert as much as possible
+{
+ wstring ustr;
+ string tmpstr;
+ try{
+ utf8::replace_invalid(str.begin(), str.end(), back_inserter(tmpstr));
+ utf8::utf8to16(tmpstr.begin(), tmpstr.end(), back_inserter(ustr));
+ }
+ catch(const utf8::exception& e)
+ {
+ debuglog<<std::string("utf8cpp decoding exception: ")+(char*)e.what();
+ //TODO
+ }
+ return ustr;
+}
+
+string get_random(int length)
+{
+ string chars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890");
+ string data;
+ boost::random_device rng;
+ boost::variate_generator<boost::random_device&, boost::uniform_int<>> gen(rng, boost::uniform_int<>(0, chars.length()-1));
+ for(int i = 0; i < length; ++i)
+ data += chars[gen()];
+ return data;
+}
+
+void send_encrypted_msgs_thread(HANDLE hContact)
+{
+ while(true)
+ {
+ char *key = UniGetContactSettingUtf(hContact, szGPGModuleName, "GPGPubKey", "");
+ while(!isContactSecured(hContact))
+ boost::this_thread::sleep(boost::posix_time::seconds(1));
+ if(!hcontact_data[hContact].msgs_to_send.empty())
+ {
+ boost::this_thread::sleep(boost::posix_time::seconds(1));
+ list<string>::iterator end = hcontact_data[hContact].msgs_to_send.end();
+ extern std::list<HANDLE> sent_msgs;
+ for(list<string>::iterator p = hcontact_data[hContact].msgs_to_send.begin(); p != end; ++p)
+ {
+ sent_msgs.push_back((HANDLE)CallContactService(hContact, PSS_MESSAGE, (WPARAM)PREF_UTF, (LPARAM)p->c_str()));
+ HistoryLog(hContact, db_event((char*)p->c_str(),0,0, DBEF_SENT));
+ boost::this_thread::sleep(boost::posix_time::seconds(1));
+ }
+ hcontact_data[hContact].msgs_to_send.clear();
+ return;
+ }
+ else
+ return;
+ }
+}
+
+string time_str()
+{
+ boost::posix_time::ptime now = boost::posix_time::second_clock::local_time();
+ return (string)boost::posix_time::to_simple_string(now);
+}
+
+int handleEnum(const char *szSetting, LPARAM lParam)
+{
+ if(!*(bool*)lParam && szSetting[0] && StriStr(szSetting, "tabsrmm"))
+ {
+ bool f = false, *found = (bool*)lParam;
+ f = !DBGetContactSettingByte(NULL, "PluginDisable", szSetting, 0);
+ if(f)
+ *found = f;
+ }
+ return 0;
+}
+
+bool isTabsrmmUsed()
+{
+ DBCONTACTENUMSETTINGS enm = {0};
+ bool found = false;
+ enm.lParam = (LPARAM)&found;
+ enm.pfnEnumProc = (DBSETTINGENUMPROC)&handleEnum;
+ enm.szModule = "PluginDisable";
+ if(CallService(MS_DB_CONTACT_ENUMSETTINGS, (WPARAM)NULL, (LPARAM)&enm) == -1)
+ return false;
+
+ return found;
+}
+
+
+int ExportGpGKeys(WPARAM w, LPARAM l)
+{
+ TCHAR *p = GetFilePath(_T("Choose file to export public keys"), _T("*"), _T("Any file"), true);
+ if(!p || !p[0])
+ {
+ delete [] p;
+ //TODO: handle error
+ return 1;
+ }
+ char *path = mir_t2a(p);
+ delete [] p;
+ std::ofstream file;
+ file.open(path, std::ios::trunc | std::ios::out);
+ mir_free(path);
+ int exported_keys = 0;
+ if(!file.is_open())
+ return 1; //TODO: handle error
+ for(HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); hContact; hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0))
+ {
+ char *k = UniGetContactSettingUtf(hContact, szGPGModuleName, "GPGPubKey", "");
+ if(!k[0])
+ {
+ mir_free(k);
+ continue;
+ }
+ std::string key = k;
+ mir_free(k);
+
+ const char* proto = (const char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ std::string id = "Comment: login ";
+ const char * uid = (const char*)CallProtoService(proto, PS_GETCAPS, (WPARAM)PFLAG_UNIQUEIDSETTING, 0);
+ DBVARIANT dbv = {0};
+ DBCONTACTGETSETTING dbcgs = {0};
+ dbcgs.pValue = &dbv;
+ dbcgs.szModule = proto;
+ dbcgs.szSetting = uid;
+ CallService(MS_DB_CONTACT_GETSETTING, 0, (LPARAM)&dbcgs);
+ switch(dbcgs.pValue->type)
+ {
+ case DBVT_DELETED:
+ continue;
+ break;
+ case DBVT_BYTE:
+ {
+ char _id[64];
+ mir_snprintf(_id, 63, "%d", dbcgs.pValue->bVal);
+ id += _id;
+ }
+ break;
+ case DBVT_WORD:
+ {
+ char _id[64];
+ mir_snprintf(_id, 63, "%d", dbcgs.pValue->wVal);
+ id += _id;
+ }
+ break;
+ case DBVT_DWORD:
+ {
+ char _id[64];
+ mir_snprintf(_id, 63, "%d", dbcgs.pValue->dVal);
+ id += _id;
+ }
+ break;
+ case DBVT_ASCIIZ:
+ {
+ id += dbcgs.pValue->pszVal;
+ CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv);
+ }
+ break;
+ case DBVT_UTF8:
+ {
+ char *tmp = mir_utf8decodeA(dbcgs.pValue->pszVal);
+ if(tmp[0])
+ id += tmp;
+ mir_free(tmp);
+ CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv);
+ }
+ break;
+ case DBVT_BLOB:
+ //TODO
+ CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv);
+ break;
+ case DBVT_WCHAR:
+ //TODO
+ CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv);
+ break;
+ }
+ id += " contact_id ";
+ ZeroMemory(&dbv, sizeof(dbv));
+ ZeroMemory(&dbcgs, sizeof(dbcgs));
+ dbcgs.pValue = &dbv;
+ dbcgs.szModule = proto;
+ dbcgs.szSetting = uid;
+ CallService(MS_DB_CONTACT_GETSETTING, (WPARAM)hContact, (LPARAM)&dbcgs);
+ switch(dbcgs.pValue->type)
+ {
+ case DBVT_DELETED:
+ continue;
+ break;
+ case DBVT_BYTE:
+ {
+ char _id[64];
+ mir_snprintf(_id, 63, "%d", dbcgs.pValue->bVal);
+ id += _id;
+ }
+ break;
+ case DBVT_WORD:
+ {
+ char _id[64];
+ mir_snprintf(_id, 63, "%d", dbcgs.pValue->wVal);
+ id += _id;
+ }
+ break;
+ case DBVT_DWORD:
+ {
+ char _id[64];
+ mir_snprintf(_id, 63, "%d", dbcgs.pValue->dVal);
+ id += _id;
+ }
+ break;
+ case DBVT_ASCIIZ:
+ {
+ id += dbcgs.pValue->pszVal;
+ CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv);
+ }
+ break;
+ case DBVT_UTF8:
+ {
+ char *tmp = mir_utf8decodeA(dbcgs.pValue->pszVal);
+ if(tmp[0])
+ id += tmp;
+ mir_free(tmp);
+ CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv);
+ }
+ break;
+ case DBVT_BLOB:
+ //TODO
+ CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv);
+ break;
+ case DBVT_WCHAR:
+ //TODO
+ CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv);
+ break;
+ }
+ std::string::size_type p1 = key.find("-----BEGIN PGP PUBLIC KEY BLOCK-----");
+ if(p1 == std::string::npos)
+ continue;
+ p1 += strlen("-----BEGIN PGP PUBLIC KEY BLOCK-----");
+ p1 ++;
+ id += '\n';
+ key.insert(p1, id);
+ file<<key;
+ file<<std::endl;
+ exported_keys++;
+ }
+ if(file.is_open())
+ file.close();
+ char msg[512];
+ mir_snprintf(msg, 511, "we have succesfully exported %d keys", exported_keys);
+ MessageBoxA(NULL, msg, Translate("Keys export result"), MB_OK);
+ return 0;
+}
+
+int ImportGpGKeys(WPARAM w, LPARAM l)
+{
+ TCHAR *p = GetFilePath(_T("Choose file to import keys from"), _T("*"), _T("Any file"));
+ if(!p || !p[0])
+ {
+ delete [] p;
+ //TODO: handle error
+ return 1;
+ }
+ char *path = mir_t2a(p);
+ delete [] p;
+ std::ifstream file;
+ file.open(path, std::ios::in);
+ mir_free(path);
+ if(!file.is_open())
+ return 1; //TODO: handle error
+ PROTOACCOUNT **accs;
+ int acc_count = 0, processed_keys = 0;
+ ProtoEnumAccounts(&acc_count, &accs);
+ char line[256];
+ file.getline(line, 255);
+ if(!strstr(line, "-----BEGIN PGP PUBLIC KEY BLOCK-----"))
+ return 1; //TODO: handle error
+ std::string key, login, contact_id;
+ key += line;
+ key += '\n';
+ while(file.is_open() && !file.eof())
+ {
+ file.getline(line, 255);
+ key += line;
+ key += '\n';
+ if(strstr(line, "-----END PGP PUBLIC KEY BLOCK-----"))
+ { //TODO: parse key
+ std::string::size_type p1 = 0, p2 = 0;
+ p1 = key.find("Comment: login ");
+ p1 += strlen("Comment: login ");
+ p2 = key.find(" contact_id ");
+ login = key.substr(p1, p2-p1);
+ p2 += strlen(" contact_id ");
+ p1 = key.find("\n", p2);
+ contact_id = key.substr(p2, p1-p2);
+ p1 = key.find("Comment: login ");
+ p2 = key.find("\n", p1);
+ p2++;
+ key.erase(p1, p2-p1);
+ std::string acc;
+ for(int i = 0; i < acc_count; i++)
+ {
+ if(acc.length())
+ break;
+ const char * uid = (const char*)CallProtoService(accs[i]->szModuleName, PS_GETCAPS, (WPARAM)PFLAG_UNIQUEIDSETTING, 0);
+ DBVARIANT dbv = {0};
+ DBCONTACTGETSETTING dbcgs = {0};
+ dbcgs.pValue = &dbv;
+ dbcgs.szModule = accs[i]->szModuleName;
+ dbcgs.szSetting = uid;
+ CallService(MS_DB_CONTACT_GETSETTING, 0, (LPARAM)&dbcgs);
+ std::string id;
+ switch(dbcgs.pValue->type)
+ {
+ case DBVT_DELETED:
+ continue;
+ break;
+ case DBVT_BYTE:
+ {
+ char _id[64];
+ mir_snprintf(_id, 63, "%d", dbcgs.pValue->bVal);
+ id += _id;
+ if(id == login)
+ acc = accs[i]->szModuleName;
+ }
+ break;
+ case DBVT_WORD:
+ {
+ char _id[64];
+ mir_snprintf(_id, 63, "%d", dbcgs.pValue->wVal);
+ id += _id;
+ if(id == login)
+ acc = accs[i]->szModuleName;
+ }
+ break;
+ case DBVT_DWORD:
+ {
+ char _id[64];
+ mir_snprintf(_id, 63, "%d", dbcgs.pValue->dVal);
+ id += _id;
+ if(id == login)
+ acc = accs[i]->szModuleName;
+ }
+ break;
+ case DBVT_ASCIIZ:
+ {
+ id += dbcgs.pValue->pszVal;
+ CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv);
+ if(id == login)
+ acc = accs[i]->szModuleName;
+ }
+ break;
+ case DBVT_UTF8:
+ {
+ char *tmp = mir_utf8decodeA(dbcgs.pValue->pszVal);
+ if(tmp[0])
+ id += tmp;
+ mir_free(tmp);
+ CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv);
+ if(id == login)
+ acc = accs[i]->szModuleName;
+ }
+ break;
+ case DBVT_BLOB:
+ //TODO
+ CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv);
+ break;
+ case DBVT_WCHAR:
+ //TODO
+ CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv);
+ break;
+ }
+ }
+ if(acc.length())
+ {
+ const char * uid = (const char*)CallProtoService(acc.c_str(), PS_GETCAPS, (WPARAM)PFLAG_UNIQUEIDSETTING, 0);
+ for(HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, (LPARAM)acc.c_str()); hContact; hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, (LPARAM)acc.c_str()))
+ {
+ DBVARIANT dbv = {0};
+ DBCONTACTGETSETTING dbcgs = {0};
+ dbcgs.pValue = &dbv;
+ dbcgs.szModule = acc.c_str();
+ dbcgs.szSetting = uid;
+ CallService(MS_DB_CONTACT_GETSETTING, (WPARAM)hContact, (LPARAM)&dbcgs);
+ std::string id;
+ bool found = false;
+ switch(dbcgs.pValue->type)
+ {
+ case DBVT_DELETED:
+ continue;
+ break;
+ case DBVT_BYTE:
+ {
+ char _id[64];
+ mir_snprintf(_id, 63, "%d", dbcgs.pValue->bVal);
+ id += _id;
+ if(id == contact_id)
+ found = true;
+ }
+ break;
+ case DBVT_WORD:
+ {
+ char _id[64];
+ mir_snprintf(_id, 63, "%d", dbcgs.pValue->wVal);
+ id += _id;
+ if(id == contact_id)
+ found = true;
+ }
+ break;
+ case DBVT_DWORD:
+ {
+ char _id[64];
+ mir_snprintf(_id, 63, "%d", dbcgs.pValue->dVal);
+ id += _id;
+ if(id == contact_id)
+ found = true;
+ }
+ break;
+ case DBVT_ASCIIZ:
+ {
+ id += dbcgs.pValue->pszVal;
+ CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv);
+ if(id == contact_id)
+ found = true;
+ }
+ break;
+ case DBVT_UTF8:
+ {
+ char *tmp = mir_utf8decodeA(dbcgs.pValue->pszVal);
+ if(tmp[0])
+ id += tmp;
+ mir_free(tmp);
+ CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv);
+ if(id == contact_id)
+ found = true;
+ }
+ break;
+ case DBVT_BLOB:
+ //TODO
+ CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv);
+ break;
+ case DBVT_WCHAR:
+ //TODO
+ CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv);
+ break;
+ }
+ if(found)
+ {
+ wstring cmd;
+ TCHAR tmp2[MAX_PATH] = {0};
+ TCHAR *ptmp;
+ string output;
+ DWORD exitcode;
+ {
+ HANDLE hcnt = hContact;
+ ptmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T(""));
+ _tcscpy(tmp2, ptmp);
+ mir_free(ptmp);
+ _tcscat(tmp2, _T("\\"));
+ _tcscat(tmp2, _T("temporary_exported.asc"));
+ DeleteFile(tmp2);
+ wfstream f(tmp2, std::ios::out);
+ f<<toUTF16(key).c_str();
+ f.close();
+ cmd += _T(" --batch ");
+ cmd += _T(" --import \"");
+ cmd += tmp2;
+ cmd += _T("\"");
+ }
+ gpg_execution_params params;
+ pxResult result;
+ params.cmd = &cmd;
+ params.useless = "";
+ params.out = &output;
+ params.code = &exitcode;
+ params.result = &result;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::seconds(10)))
+ {
+ gpg_thread.~thread();
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ debuglog<<time_str()<<": GPG execution timed out, aborted\n";
+ break;
+ }
+ if(result == pxNotFound)
+ break;
+ if(result == pxSuccess)
+ processed_keys++;
+ {
+ if(output.find("already in secret keyring") != string::npos)
+ {
+ MessageBox(0, _T("Key already in scret key ring."), _T("Info"), MB_OK);
+ DeleteFile(tmp2);
+ break;
+ }
+ char *tmp2;
+ string::size_type s = output.find("gpg: key ") + strlen("gpg: key ");
+ string::size_type s2 = output.find(":", s);
+ tmp2 = new char [output.substr(s,s2-s).length()+1];
+ strcpy(tmp2, output.substr(s,s2-s).c_str());
+ mir_utf8decode(tmp2, 0);
+ DBWriteContactSettingString(hContact, szGPGModuleName, "KeyID", tmp2);
+ mir_free(tmp2);
+ s = output.find("“", s2);
+ if(s == string::npos)
+ {
+ s = output.find("\"", s2);
+ s += 1;
+ }
+ else
+ s += 3;
+ if((s2 = output.find("(", s)) == string::npos)
+ s2 = output.find("<", s);
+ else if(s2 > output.find("<", s))
+ s2 = output.find("<", s);
+ if(s2 != string::npos)
+ {
+ tmp2 = new char [output.substr(s,s2-s-1).length()+1];
+ strcpy(tmp2, output.substr(s,s2-s-1).c_str());
+ mir_utf8decode(tmp2, 0);
+ if(hContact)
+ {
+ DBWriteContactSettingString(hContact, szGPGModuleName, "KeyMainName", output.substr(s,s2-s-1).c_str());
+ }
+ mir_free(tmp2);
+ if((s = output.find(")", s2)) == string::npos)
+ s = output.find(">", s2);
+ else if(s > output.find(">", s2))
+ s = output.find(">", s2);
+ s2++;
+ if(output[s] == ')')
+ {
+ tmp2 = new char [output.substr(s2,s-s2).length()+1];
+ strcpy(tmp2, output.substr(s2,s-s2).c_str());
+ mir_utf8decode(tmp2, 0);
+ if(hContact)
+ DBWriteContactSettingString(hContact, szGPGModuleName, "KeyComment", output.substr(s2,s-s2).c_str());
+ mir_free(tmp2);
+ s+=3;
+ s2 = output.find(">", s);
+ tmp2 = new char [output.substr(s,s2-s).length()+1];
+ strcpy(tmp2, output.substr(s,s2-s).c_str());
+ mir_utf8decode(tmp2, 0);
+ if(hContact)
+ DBWriteContactSettingString(hContact, szGPGModuleName, "KeyMainEmail", output.substr(s,s2-s).c_str());
+ mir_free(tmp2);
+ }
+ else
+ {
+ tmp2 = new char [output.substr(s2,s-s2).length()+1];
+ strcpy(tmp2, output.substr(s2,s-s2).c_str());
+ mir_utf8decode(tmp2, 0);
+ if(hContact)
+ DBWriteContactSettingString(hContact, szGPGModuleName, "KeyMainEmail", output.substr(s2,s-s2).c_str());
+ mir_free(tmp2);
+ }
+ }
+ DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 1);
+ DBWriteContactSettingTString(hContact, szGPGModuleName, "GPGPubKey", toUTF16(key).c_str());
+ }
+ DeleteFile(tmp2);
+ break;
+ }
+ }
+ }
+ key.clear();
+ }
+ }
+ if(file.is_open())
+ file.close();
+ char msg[512];
+ mir_snprintf(msg, 511, "we have succesfully processed %d keys", processed_keys);
+ MessageBoxA(NULL, msg, Translate("Keys import result"), MB_OK);
+ return 0;
+} \ No newline at end of file
diff --git a/plugins/New_GPG/src/utilities.h b/plugins/New_GPG/src/utilities.h
new file mode 100755
index 0000000000..30e9f68bb2
--- /dev/null
+++ b/plugins/New_GPG/src/utilities.h
@@ -0,0 +1,104 @@
+// Copyright © 2010-2012 sss
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#ifndef UTILITIES_H
+#define UTILITIES_H
+TCHAR* __stdcall UniGetContactSettingUtf(HANDLE hContact, const char *szModule,const char* szSetting, TCHAR* szDef);
+char* __stdcall UniGetContactSettingUtf(HANDLE hContact, const char *szModule,const char* szSetting, char* szDef);
+void GetFilePath(TCHAR *WindowTittle, char *szSetting, TCHAR *szExt, TCHAR *szExtDesc);
+TCHAR *GetFilePath(TCHAR *WindowTittle, TCHAR *szExt, TCHAR *szExtDesc, bool save_file = false);
+void GetFolderPath(TCHAR *WindowTittle, char *szSetting);
+
+void storeOutput(HANDLE ahandle, string *output);
+
+int ComboBoxAddStringUtf(HWND hCombo, const TCHAR *szString, DWORD data);
+bool isContactSecured(HANDLE hContact);
+bool isContactHaveKey(HANDLE hContact);
+bool isTabsrmmUsed();
+bool isGPGKeyExist();
+bool isGPGValid();
+const bool StriStr(const char *str, const char *substr);
+string toUTF8(wstring str);
+wstring toUTF16(string str);
+string get_random(int length);
+string time_str();
+
+struct db_event : public DBEVENTINFO
+{
+public:
+ db_event(char* msg)
+ {
+ eventType = EVENTTYPE_MESSAGE;
+ flags = 0;
+ timestamp = 0;
+ szModule = 0;
+ cbSize = 0;
+ cbBlob = strlen(msg)+1;
+ pBlob = (PBYTE)msg;
+ }
+ db_event(char* msg, DWORD time)
+ {
+ cbBlob = strlen(msg)+1;
+ pBlob = (PBYTE)msg;
+ eventType = EVENTTYPE_MESSAGE;
+ flags = 0;
+ timestamp = time;
+ szModule = 0;
+ cbSize = 0;
+ }
+ db_event(char* msg, DWORD time, int type)
+ {
+ cbBlob = strlen(msg)+1;
+ pBlob = (PBYTE)msg;
+ if(type)
+ eventType = type;
+ else
+ eventType = EVENTTYPE_MESSAGE;
+ flags = 0;
+ timestamp = time;
+ szModule = 0;
+ cbSize = 0;
+ }
+ db_event(char* msg, int type)
+ {
+ cbBlob = strlen(msg)+1;
+ pBlob = (PBYTE)msg;
+ flags = 0;
+ if(type)
+ eventType = type;
+ else
+ eventType = EVENTTYPE_MESSAGE;
+ timestamp = 0;
+ szModule = 0;
+ cbSize = 0;
+ }
+ db_event(char* msg, DWORD time, int type, DWORD _flags)
+ {
+ cbBlob = strlen(msg)+1;
+ pBlob = (PBYTE)msg;
+ if(type)
+ eventType = type;
+ else
+ eventType = EVENTTYPE_MESSAGE;
+ flags = _flags;
+ timestamp = time;
+ szModule = 0;
+ cbSize = 0;
+ }
+};
+void HistoryLog(HANDLE, db_event);
+
+#endif