summaryrefslogtreecommitdiff
path: root/plugins/New_GPG/src
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/New_GPG/src')
-rw-r--r--plugins/New_GPG/src/Version.h14
-rw-r--r--plugins/New_GPG/src/clist.cpp32
-rw-r--r--plugins/New_GPG/src/commonheaders.h86
-rw-r--r--plugins/New_GPG/src/constants.h5
-rw-r--r--plugins/New_GPG/src/globals.h22
-rw-r--r--plugins/New_GPG/src/gpg_wrapper.cpp340
-rw-r--r--plugins/New_GPG/src/gpg_wrapper.h75
-rw-r--r--plugins/New_GPG/src/icons.cpp98
-rw-r--r--plugins/New_GPG/src/include/boost/process.hpp22
-rw-r--r--plugins/New_GPG/src/include/boost/process/all.hpp30
-rw-r--r--plugins/New_GPG/src/include/boost/process/child.hpp74
-rw-r--r--plugins/New_GPG/src/include/boost/process/config.hpp82
-rw-r--r--plugins/New_GPG/src/include/boost/process/create_pipe.hpp48
-rw-r--r--plugins/New_GPG/src/include/boost/process/execute.hpp38
-rw-r--r--plugins/New_GPG/src/include/boost/process/executor.hpp176
-rw-r--r--plugins/New_GPG/src/include/boost/process/initializers.hpp497
-rw-r--r--plugins/New_GPG/src/include/boost/process/mitigate.hpp104
-rw-r--r--plugins/New_GPG/src/include/boost/process/pipe.hpp64
-rw-r--r--plugins/New_GPG/src/include/boost/process/search_path.hpp51
-rw-r--r--plugins/New_GPG/src/include/boost/process/shell_path.hpp46
-rw-r--r--plugins/New_GPG/src/include/boost/process/terminate.hpp52
-rw-r--r--plugins/New_GPG/src/include/boost/process/wait_for_exit.hpp58
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/child.hpp55
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/create_pipe.hpp40
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/execute.hpp82
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/executor.hpp130
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/initializers.hpp33
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/initializers/bind_stderr.hpp39
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/initializers/bind_stdin.hpp39
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/initializers/bind_stdout.hpp39
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/initializers/close_stderr.hpp31
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/initializers/close_stdin.hpp31
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/initializers/close_stdout.hpp31
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/initializers/hide_console.hpp31
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/initializers/inherit_env.hpp24
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/initializers/initializer_base.hpp29
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/initializers/on_CreateProcess_error.hpp42
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/initializers/on_CreateProcess_setup.hpp42
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/initializers/on_CreateProcess_success.hpp42
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/initializers/run_exe.hpp69
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/initializers/set_args.hpp87
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/initializers/set_cmd_line.hpp68
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/initializers/set_env.hpp88
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/initializers/set_on_error.hpp36
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/initializers/show_window.hpp36
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/initializers/start_in_dir.hpp69
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/initializers/throw_on_error.hpp30
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/pipe.hpp32
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/search_path.hpp104
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/shell_path.hpp50
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/terminate.hpp38
-rw-r--r--plugins/New_GPG/src/include/boost/process/windows/wait_for_exit.hpp49
-rw-r--r--plugins/New_GPG/src/include/utf8.h34
-rw-r--r--plugins/New_GPG/src/include/utf8/checked.h327
-rw-r--r--plugins/New_GPG/src/include/utf8/core.h329
-rw-r--r--plugins/New_GPG/src/include/utf8/unchecked.h228
-rw-r--r--plugins/New_GPG/src/init.cpp251
-rw-r--r--plugins/New_GPG/src/jabber_account.cpp85
-rw-r--r--plugins/New_GPG/src/jabber_account.h43
-rw-r--r--plugins/New_GPG/src/log.cpp87
-rw-r--r--plugins/New_GPG/src/log.h36
-rw-r--r--plugins/New_GPG/src/main.cpp2611
-rw-r--r--plugins/New_GPG/src/main.h31
-rw-r--r--plugins/New_GPG/src/messages.cpp1198
-rw-r--r--plugins/New_GPG/src/metacontacts.cpp88
-rw-r--r--plugins/New_GPG/src/metacontacts.h24
-rw-r--r--plugins/New_GPG/src/options.cpp1360
-rw-r--r--plugins/New_GPG/src/resource.h116
-rw-r--r--plugins/New_GPG/src/srmm.cpp88
-rw-r--r--plugins/New_GPG/src/stdafx.cpp18
-rw-r--r--plugins/New_GPG/src/utilities.cpp2238
-rw-r--r--plugins/New_GPG/src/utilities.h110
72 files changed, 12832 insertions, 0 deletions
diff --git a/plugins/New_GPG/src/Version.h b/plugins/New_GPG/src/Version.h
new file mode 100644
index 0000000000..86774f7ace
--- /dev/null
+++ b/plugins/New_GPG/src/Version.h
@@ -0,0 +1,14 @@
+#define __MAJOR_VERSION 0
+#define __MINOR_VERSION 0
+#define __RELEASE_NUM 0
+#define __BUILD_NUM 11
+
+#define __FILEVERSION_STRING __MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM
+
+#define __PLUGIN_NAME "GPG"
+#define __FILENAME "New_GPG.dll"
+#define __DESCRIPTION "New GPG encryption support plugin, based on code from old GPG plugin and SecureIM."
+#define __AUTHOR "sss"
+#define __AUTHOREMAIL "sss123next@list.ru"
+#define __AUTHORWEB "http://miranda-ng.org/"
+#define __COPYRIGHT "© 2010-2012 sss"
diff --git a/plugins/New_GPG/src/clist.cpp b/plugins/New_GPG/src/clist.cpp
new file mode 100644
index 0000000000..4533a464c2
--- /dev/null
+++ b/plugins/New_GPG/src/clist.cpp
@@ -0,0 +1,32 @@
+// 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 RefreshContactListIcons(void);
+void setClistIcon(HANDLE);
+
+int onExtraImageListRebuilding(WPARAM, LPARAM)
+{
+ RefreshContactListIcons();
+ return 0;
+}
+
+int onExtraImageApplying(WPARAM wParam, LPARAM)
+{
+ setClistIcon((HANDLE)wParam);
+ return 0;
+}
diff --git a/plugins/New_GPG/src/commonheaders.h b/plugins/New_GPG/src/commonheaders.h
new file mode 100644
index 0000000000..01a1d59ff5
--- /dev/null
+++ b/plugins/New_GPG/src/commonheaders.h
@@ -0,0 +1,86 @@
+// 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 _CRT_SECURE_NO_WARNINGS
+#define _SCL_SECURE_NO_WARNINGS
+
+//windows
+#include <windows.h>
+#include <shlobj.h>
+#include <io.h>
+#include <shlwapi.h>
+
+//c++
+#include <map>
+using std::map;
+#include <list>
+using std::list;
+#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>
+#include <boost/iostreams/stream.hpp>
+
+//boost process
+#include <boost/process.hpp>
+
+//utf8cpp
+#include <utf8.h>
+
+//miranda
+#include <newpluginapi.h>
+#include <m_database.h>
+#include <m_options.h>
+#include <m_langpack.h>
+#include <m_clui.h>
+#include <m_skin.h>
+#include <m_protomod.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 <win2k.h>
+
+#include <m_metacontacts.h>
+
+//internal
+#include "resource.h"
+#include "Version.h"
+#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 100644
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 100644
index 0000000000..9942e16e96
--- /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, bSameAction, bFileTransfers, bDebugLog;
+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 100644
index 0000000000..112d86080f
--- /dev/null
+++ b/plugins/New_GPG/src/gpg_wrapper.cpp
@@ -0,0 +1,340 @@
+// 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
+
+
+pxResult pxExecute(std::vector<std::wstring> &aargv, string *aoutput, LPDWORD aexitcode, pxResult *result, boost::process::child *_child)
+{
+ if(!gpg_valid)
+ return pxNotConfigured;
+ extern logtofile debuglog;
+
+
+ TCHAR *bin_path = UniGetContactSettingUtf(NULL, szGPGModuleName, "szGpgBinPath", _T(""));
+ {
+ if(!boost::filesystem::exists(bin_path))
+ {
+ mir_free(bin_path);
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": GPG executable not found");
+ *result = pxNotFound;
+ return pxNotFound;
+ }
+ }
+
+ using namespace boost::process;
+ using namespace boost::process::initializers;
+ using namespace boost::iostreams;
+
+
+ std::vector<std::wstring> argv;
+ std::vector<std::wstring> env;
+ env.push_back(L"LANGUAGE=en@quot");
+ env.push_back(L"LC_ALL=English");
+ argv.push_back(bin_path);
+ argv.push_back(L"--homedir");
+ TCHAR *home_dir = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T(""));
+ argv.push_back(home_dir);
+ mir_free(home_dir);
+ argv.push_back(L"--display-charset");
+ argv.push_back(L"utf-8");
+ argv.push_back(L"-z9");
+ argv.insert(argv.end(), aargv.begin(), aargv.end());
+
+ if(bDebugLog)
+ {
+ std::wstring args;
+ for(int i = 0; i < argv.size(); ++i)
+ {
+ args += argv[i];
+ args += L" ";
+ }
+ args.erase(args.size()-1, 1);
+ debuglog<<std::string(time_str()+": gpg in: "+toUTF8(args));
+ }
+
+
+ pipe pout = create_pipe();
+ pipe perr = create_pipe();
+ child *c = nullptr;
+ {
+ file_descriptor_sink sout(pout.sink, close_handle);
+ file_descriptor_sink serr(perr.sink, close_handle);
+
+ char *mir_path = new char [MAX_PATH];
+ PathToAbsolute("\\", mir_path);
+
+ c = new child(execute(set_args(argv), bind_stdout(sout), bind_stderr(serr), close_stdin(),/*bind_stdin(sin),*/ show_window(SW_HIDE), hide_console(), inherit_env(), set_env(env), start_in_dir(toUTF16(mir_path))));
+ _child = c;
+
+ delete [] mir_path;
+ }
+
+
+ file_descriptor_source source(pout.source, close_handle);
+
+ stream<file_descriptor_source> is(source);
+
+ try{
+ std::string s;
+ while(std::getline(is, s))
+ {
+ aoutput->append(s);
+ aoutput->append("\n");
+ }
+ }
+ catch(const std::exception &e)
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": failed to read from stream with error: " + e.what() + "\n\tSuccesfully read : " + *aoutput);
+ }
+
+ file_descriptor_source source2(perr.source, close_handle);
+
+ stream<file_descriptor_source> is2(source2);
+
+ try{
+ std::string s;
+ while(std::getline(is2, s))
+ {
+ aoutput->append(s);
+ aoutput->append("\n");
+ }
+ }
+ catch(const std::exception &e)
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": failed to read from stream with error: " + e.what() + "\n\tSuccesfully read : " + *aoutput);
+ }
+
+ fix_line_term(*aoutput);
+
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": gpg out: "+*aoutput);
+
+ auto ec = wait_for_exit(*c);
+ delete c;
+ *aexitcode = ec;
+ _child = nullptr;
+
+
+ if(*aexitcode)
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": warning: wrong gpg exit status, gpg output: "+*aoutput);
+ return pxSuccessExitCodeInvalid;
+ }
+
+
+ return pxSuccess;
+}
+
+void pxEexcute_thread(gpg_execution_params &params)
+{
+ pxExecute(params.aargv, params.out, params.code, params.result, params.child);
+}
+
+bool gpg_launcher(gpg_execution_params &params, boost::posix_time::time_duration t)
+{
+ bool ret = true;
+ boost::thread *gpg_thread = new boost::thread(boost::bind(&pxEexcute_thread, params));
+ if(!gpg_thread->timed_join(t))
+ {
+ ret = false;
+ delete gpg_thread;
+ if(params.child)
+ boost::process::terminate(*(params.child));
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": GPG execution timed out, aborted");
+ }
+ return ret;
+}
+
+
+
+pxResult pxExecute_passwd_change(std::vector<std::wstring> &aargv, string *aoutput, LPDWORD aexitcode, pxResult *result, boost::process::child *_child, string &old_pass, string &new_pass)
+{
+ if(!gpg_valid)
+ return pxNotConfigured;
+ extern logtofile debuglog;
+
+ TCHAR *bin_path = UniGetContactSettingUtf(NULL, szGPGModuleName, "szGpgBinPath", _T(""));
+ {
+ if(!boost::filesystem::exists(bin_path))
+ {
+ mir_free(bin_path);
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": GPG executable not found");
+ *result = pxNotFound;
+ return pxNotFound;
+ }
+ }
+
+ using namespace boost::process;
+ using namespace boost::process::initializers;
+ using namespace boost::iostreams;
+
+
+ std::vector<std::wstring> argv;
+ std::vector<std::wstring> env;
+ env.push_back(L"LANGUAGE=en@quot");
+ env.push_back(L"LC_ALL=English");
+ argv.push_back(bin_path);
+ argv.push_back(L"--homedir");
+ TCHAR *home_dir = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T(""));
+ argv.push_back(home_dir);
+ mir_free(home_dir);
+ argv.push_back(L"--display-charset");
+ argv.push_back(L"utf-8");
+ argv.push_back(L"-z9");
+ argv.insert(argv.end(), aargv.begin(), aargv.end());
+
+// pipe pout = create_pipe();
+// pipe pin = create_pipe();
+// file_descriptor_sink sout(pout.sink, close_handle);
+// file_descriptor_source sin(pin.source, close_handle);
+
+ char *mir_path = new char [MAX_PATH];
+ PathToAbsolute("\\", mir_path);
+
+ //execute(set_args(argv), bind_stdout(sout), bind_stdin(sin), show_window(SW_HIDE), hide_console(), inherit_env(), set_env(env), start_in_dir(toUTF16(mir_path)));
+ child c = execute(set_args(argv), /*bind_stdin(sin), */inherit_env(), set_env(env), start_in_dir(toUTF16(mir_path)));
+ _child = &c;
+
+ delete [] mir_path;
+
+// file_descriptor_source source(pout.source, close_handle);
+/* file_descriptor_sink _sin(pin.sink, close_handle);
+
+ stream<file_descriptor_sink> out(_sin);
+
+
+ std::wstring cmd;
+ for(int i = 0; i < argv.size(); i++)
+ {
+ cmd += argv[i];
+ cmd += L" ";
+ }
+ */
+// out<<toUTF8(cmd)<<std::endl;
+
+ //fucked gpg does not want to give us stdin/stdout
+ wait_for_exit(*_child);
+ _child = nullptr;
+
+/* out<<old_pass<<std::endl;
+ out<<new_pass<<std::endl;
+ out<<new_pass<<std::endl;
+ out<<"save"<<std::endl; */
+
+// stream<file_descriptor_source> is(source);
+/* std::string s;
+
+ is>>s;
+
+ MessageBoxA(NULL, s.c_str(), "", MB_OK); */
+
+
+/* ctx.environment = boost::process::self::get_environment();
+ ctx.environment.insert(boost::process::environment::value_type("LANGUAGE", "en@quot"));
+ ctx.environment["LC_ALL"] = "English";
+
+ char *mir_path = new char [MAX_PATH];
+ PathToAbsolute("\\", mir_path);
+ ctx.work_directory = mir_path;
+ delete [] mir_path;
+
+ boost::process::win32_child proc = boost::process::win32_launch(toUTF8(bin_path), argv, ctx);
+
+ mir_free(bin_path);
+
+// boost::process::pistream &_stdout = proc.get_stdout();
+ boost::process::postream &_stdin = proc.get_stdin();
+
+ boost::this_thread::sleep(boost::posix_time::milliseconds(50));
+
+ std::string buf; */
+
+
+/* std::getline(_stdout, buf);
+ while(_stdout.good())
+ {
+ *aoutput += buf;
+ if(aoutput->find("Enter passphrase") != std::string::npos)
+ break;
+ boost::this_thread::sleep(boost::posix_time::milliseconds(50));
+ std::getline(_stdout, buf);
+ }
+ *aoutput += buf; */
+
+ //_stdin<<old_pass<<std::endl;
+
+/* std::getline(_stdout, buf);
+ while(_stdout.good())
+ {
+ *aoutput += buf;
+ if(aoutput->find("Enter the new passphrase for this secret key.") != std::string::npos)
+ break;
+ boost::this_thread::sleep(boost::posix_time::milliseconds(50));
+ std::getline(_stdout, buf);
+ }
+
+ *aoutput += buf;
+
+ if(aoutput->find("Enter passphrase") != std::string::npos)*/
+ //_stdin<<new_pass<<std::endl;
+
+/* std::getline(_stdout, buf);
+ while(_stdout.good())
+ {
+ *aoutput += buf;
+ if(aoutput->find("Repeat passphrase") != std::string::npos)
+ break;
+ boost::this_thread::sleep(boost::posix_time::milliseconds(50));
+ std::getline(_stdout, buf);
+ }
+ *aoutput += buf; */
+
+ //_stdin<<new_pass<<std::endl;
+
+/* std::getline(_stdout, buf);
+ while(_stdout.good())
+ {
+ *aoutput += buf;
+ if(aoutput->find("Command") != std::string::npos)
+ break;
+ boost::this_thread::sleep(boost::posix_time::milliseconds(50));
+ std::getline(_stdout, buf);
+ }
+ *aoutput += buf; */
+
+ //_stdin<<"save"<<std::endl;
+
+ //proc.wait();
+
+ //MessageBoxA(NULL, aoutput->c_str(), "info", MB_OK);
+
+ return pxSuccess;
+}
+
+
+void pxEexcute_passwd_change_thread(void *param)
+{
+ gpg_execution_params_pass *params = (gpg_execution_params_pass*)param;
+ pxResult result = pxExecute_passwd_change(params->args, params->out, params->code, params->result, params->child, params->old_pass, params->new_pass);
+}
diff --git a/plugins/New_GPG/src/gpg_wrapper.h b/plugins/New_GPG/src/gpg_wrapper.h
new file mode 100644
index 0000000000..9ff09578b5
--- /dev/null
+++ b/plugins/New_GPG/src/gpg_wrapper.h
@@ -0,0 +1,75 @@
+// 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(std::vector<std::string> &aargv, string *aoutput, LPDWORD aexitcode, pxResult *result);
+pxResult pxExecute_passwd_change(std::vector<std::string> &aargv, string *aoutput, LPDWORD aexitcode, pxResult *result, string &old_pass, string &new_pass);
+
+struct gpg_execution_params
+{
+ std::vector<std::wstring> &aargv;
+// char *useless;
+ string *out;
+ LPDWORD code;
+ pxResult *result;
+ boost::process::child *child;
+// HANDLE hProcess;
+// PROCESS_INFORMATION *proc;
+ gpg_execution_params(std::vector<std::wstring> &a): aargv(a)
+ {
+ child = nullptr;
+ }
+};
+
+struct gpg_execution_params_pass
+{
+ std::vector<std::wstring> &args;
+ string &old_pass, &new_pass;
+ string *out;
+ LPDWORD code;
+ pxResult *result;
+ boost::process::child *child;
+// HANDLE hProcess;
+// PROCESS_INFORMATION *proc;
+ gpg_execution_params_pass(std::vector<std::wstring> &a, std::string &o, std::string &n): args(a), old_pass(o), new_pass(n)
+ {
+ child = nullptr;
+ }
+};
+
+
+void pxEexcute_thread(gpg_execution_params &params);
+bool gpg_launcher(gpg_execution_params &params, boost::posix_time::time_duration t = boost::posix_time::seconds(10));
+void pxEexcute_passwd_change_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 100644
index 0000000000..4c7b100023
--- /dev/null
+++ b/plugins/New_GPG/src/icons.cpp
@@ -0,0 +1,98 @@
+// 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 HINSTANCE hInst;
+
+static IconItem iconList[] =
+{
+ { "Secured", "secured", IDI_SECURED },
+ { "Unsecured", "unsecured", IDI_UNSECURED }
+};
+
+void InitIconLib()
+{
+ Icon_Register(hInst, szGPGModuleName, iconList, SIZEOF(iconList));
+}
+
+HICON IconLibGetIcon(const char* ident)
+{
+ return Skin_GetIcon(ident);
+}
+
+void IconLibReleaseIcon(const char* ident)
+{
+ Skin_ReleaseIcon(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);
+ const char *szIconId = (enabled) ? "secured" : NULL;
+ ExtraIcon_SetIcon(g_hCLIcon, hContact, szIconId);
+ if(hMC)
+ ExtraIcon_SetIcon(g_hCLIcon, hMC, szIconId);
+}
+
+void setSrmmIcon(HANDLE h)
+{
+ HANDLE hContact = metaIsProtoMetaContacts(h)?metaGetMostOnline(h):h;
+ bool enabled = isContactSecured(hContact);
+ HANDLE hMC = NULL;
+ if(metaIsSubcontact(hContact))
+ hMC = metaGetContact(hContact);
+ else if(metaIsProtoMetaContacts(hContact))
+ hMC = metaGetContact(hContact);
+
+ StatusIconData sid = { sizeof(sid) };
+ sid.szModule = szGPGModuleName;
+ sid.hIcon = IconLibGetIcon("secured");
+ sid.dwId = 1;
+ sid.flags = enabled ? 0 : MBF_HIDDEN;
+ Srmm_ModifyIcon(hContact, &sid);
+ if(hMC)
+ Srmm_ModifyIcon(hMC, &sid);
+
+ sid.hIcon = IconLibGetIcon("unsecured");
+ sid.dwId = 2;
+ sid.flags = enabled ? MBF_HIDDEN : 0;
+ Srmm_ModifyIcon(hContact, &sid);
+ if(hMC)
+ Srmm_ModifyIcon(hMC, &sid);
+}
+
+
+void RefreshContactListIcons()
+{
+ CallService(MS_CLUI_LISTBEGINREBUILD,0,0);
+
+ for (HANDLE hContact = db_find_first(); hContact; hContact = db_find_next(hContact))
+ setClistIcon(hContact);
+
+ CallService(MS_CLUI_LISTENDREBUILD,0,0);
+}
diff --git a/plugins/New_GPG/src/include/boost/process.hpp b/plugins/New_GPG/src/include/boost/process.hpp
new file mode 100644
index 0000000000..2271e9b49e
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process.hpp
@@ -0,0 +1,22 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011 Jeff Flinn, Boris Schaeling
+// Copyright (c) 2012 Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+/**
+ * \file boost/process.hpp
+ *
+ * Convenience header which includes all public Boost.Process header files.
+ */
+
+#ifndef BOOST_PROCESS_HPP
+#define BOOST_PROCESS_HPP
+
+#include <boost/process/all.hpp>
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/all.hpp b/plugins/New_GPG/src/include/boost/process/all.hpp
new file mode 100644
index 0000000000..234dd05d4c
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/all.hpp
@@ -0,0 +1,30 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+/**
+ * \file boost/process/all.hpp
+ *
+ * Convenience header which includes all public Boost.Process header files.
+ */
+
+#ifndef BOOST_PROCESS_ALL_HPP
+#define BOOST_PROCESS_ALL_HPP
+
+#include <boost/process/child.hpp>
+#include <boost/process/create_pipe.hpp>
+#include <boost/process/execute.hpp>
+#include <boost/process/executor.hpp>
+#include <boost/process/initializers.hpp>
+#include <boost/process/pipe.hpp>
+#include <boost/process/search_path.hpp>
+#include <boost/process/shell_path.hpp>
+#include <boost/process/terminate.hpp>
+#include <boost/process/wait_for_exit.hpp>
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/child.hpp b/plugins/New_GPG/src/include/boost/process/child.hpp
new file mode 100644
index 0000000000..ec129fc936
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/child.hpp
@@ -0,0 +1,74 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+/**
+ * \file boost/process/child.hpp
+ *
+ * Defines a child process class.
+ */
+
+#ifndef BOOST_PROCESS_CHILD_HPP
+#define BOOST_PROCESS_CHILD_HPP
+
+#include <boost/process/config.hpp>
+
+#include BOOST_PROCESS_PLATFORM_PROMOTE_PATH(child)
+BOOST_PROCESS_PLATFORM_PROMOTE_NAMESPACE(child)
+
+#if defined(BOOST_PROCESS_DOXYGEN)
+namespace boost { namespace process {
+
+/**
+ * Represents a child process.
+ *
+ * On Windows child is movable but non-copyable. The destructor
+ * automatically closes handles to the child process.
+ */
+struct child
+{
+ /**
+ * Process information.
+ *
+ * \remark <em>Windows only.</em>
+ */
+ PROCESS_INFORMATION proc_info;
+
+ /**
+ * Constructor.
+ *
+ * \remark <em>Windows only.<em/>
+ */
+ explicit child(const PROCESS_INFORMATION &pi) : proc_info(pi) {}
+
+ /**
+ * Returns the process handle.
+ *
+ * \remark <em>Windows only.</em>
+ */
+ HANDLE process_handle() const { return proc_info.hProcess; }
+
+ /**
+ * Process identifier.
+ *
+ * \remark <em>POSIX only.</em>
+ */
+ pid_t pid;
+
+ /**
+ * Constructor.
+ *
+ * \remark <em>POSIX only.</em>
+ */
+ explicit child(pid_t p) : pid(p) {}
+};
+
+}}
+#endif
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/config.hpp b/plugins/New_GPG/src/include/boost/process/config.hpp
new file mode 100644
index 0000000000..7aae4d3ca4
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/config.hpp
@@ -0,0 +1,82 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+/**
+ * \file boost/process/config.hpp
+ *
+ * Defines various macros.
+ */
+
+#ifndef BOOST_PROCESS_CONFIG_HPP
+#define BOOST_PROCESS_CONFIG_HPP
+
+#include <boost/config.hpp>
+#include <boost/system/config.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/system/system_error.hpp>
+
+#if defined(BOOST_POSIX_API)
+# include <errno.h>
+# define BOOST_PROCESS_LAST_ERROR errno
+# define BOOST_PROCESS_PLATFORM posix
+#elif defined(BOOST_WINDOWS_API)
+# include <Windows.h>
+# define BOOST_PROCESS_LAST_ERROR GetLastError()
+# define BOOST_PROCESS_PLATFORM windows
+#endif
+
+/** \cond */
+#define BOOST_PROCESS_PLATFORM_PROMOTE_PATH(COMPONENT) \
+ <boost/process/BOOST_PROCESS_PLATFORM/COMPONENT.hpp>
+#define BOOST_PROCESS_PLATFORM_PROMOTE_NAMESPACE(COMPONENT) \
+ namespace boost { namespace process { using BOOST_PROCESS_PLATFORM::COMPONENT; }}
+#define BOOST_PROCESS_PLATFORM_PROMOTE_INITIALIZERS_NAMESPACE \
+ namespace boost { namespace process { namespace initializers { \
+ using namespace boost::process::BOOST_PROCESS_PLATFORM::initializers; }}}
+/** \endcond */
+
+#if defined(BOOST_PROCESS_DOXYGEN)
+/**
+ * \def BOOST_POSIX_API
+ *
+ * This macro is defined on POSIX.
+ */
+#define BOOST_POSIX_API
+/**
+ * \def BOOST_WINDOWS_API
+ *
+ * This macro is defined on Windows.
+ */
+#define BOOST_WINDOWS_API
+#endif
+
+/**
+ * \def BOOST_PROCESS_THROW(EX)
+ *
+ * Defines how exceptions are thrown. Set this macro for example
+ * to \c BOOST_THROW_EXCEPTION if you like to use Boost.Exception.
+ */
+#define BOOST_PROCESS_THROW(EX) throw EX
+
+/** \cond */
+#define BOOST_PROCESS_SOURCE_LOCATION \
+ "in file '" __FILE__ "', line " BOOST_STRINGIZE(__LINE__) ": "
+
+#define BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(what) \
+ BOOST_PROCESS_THROW(boost::system::system_error( \
+ boost::system::error_code(BOOST_PROCESS_LAST_ERROR, \
+ boost::system::system_category()), \
+ BOOST_PROCESS_SOURCE_LOCATION what))
+
+#define BOOST_PROCESS_RETURN_LAST_SYSTEM_ERROR(ec) \
+ ec = boost::system::error_code(BOOST_PROCESS_LAST_ERROR, \
+ boost::system::system_category())
+/** \endcond */
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/create_pipe.hpp b/plugins/New_GPG/src/include/boost/process/create_pipe.hpp
new file mode 100644
index 0000000000..6c34ecf44b
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/create_pipe.hpp
@@ -0,0 +1,48 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+/**
+ * \file boost/process/create_pipe.hpp
+ *
+ * Defines a function to create a pipe.
+ */
+
+#ifndef BOOST_PROCESS_CREATE_PIPE_HPP
+#define BOOST_PROCESS_CREATE_PIPE_HPP
+
+#include <boost/process/config.hpp>
+
+#include BOOST_PROCESS_PLATFORM_PROMOTE_PATH(create_pipe)
+BOOST_PROCESS_PLATFORM_PROMOTE_NAMESPACE(create_pipe)
+
+#if defined(BOOST_PROCESS_DOXYGEN)
+namespace boost { namespace process {
+
+/**
+ * Creates an anonymous pipe.
+ *
+ * \note On Windows anonymous pipes don't support
+ * asynchronous I/O.
+ *
+ * \throws boost::system::system_error in case of an error
+ */
+pipe create_pipe();
+
+/**
+ * Creates an anonymous pipe.
+ *
+ * \note On Windows anonymous pipes don't support
+ * asynchronous I/O.
+ */
+pipe create_pipe(boost::system::error_code &ec);
+
+}}
+#endif
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/execute.hpp b/plugins/New_GPG/src/include/boost/process/execute.hpp
new file mode 100644
index 0000000000..608831171e
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/execute.hpp
@@ -0,0 +1,38 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+/**
+ * \file boost/process/execute.hpp
+ *
+ * Defines a function to execute a program.
+ */
+
+#ifndef BOOST_PROCESS_EXECUTE_HPP
+#define BOOST_PROCESS_EXECUTE_HPP
+
+#include <boost/process/config.hpp>
+
+#include BOOST_PROCESS_PLATFORM_PROMOTE_PATH(execute)
+BOOST_PROCESS_PLATFORM_PROMOTE_NAMESPACE(execute)
+
+#if defined(BOOST_PROCESS_DOXYGEN)
+namespace boost { namespace process {
+
+/**
+ * Starts a program.
+ *
+ * \tparam initializers define what and how the program is started
+ */
+template <class Initializer, class... Initializers>
+child execute(const Initializer &initializer, const Initializers... &initializers);
+
+}}
+#endif
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/executor.hpp b/plugins/New_GPG/src/include/boost/process/executor.hpp
new file mode 100644
index 0000000000..905d7f84cc
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/executor.hpp
@@ -0,0 +1,176 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+/**
+ * \file boost/process/executor.hpp
+ *
+ * Defines an executor which can create child processes.
+ */
+
+#ifndef BOOST_PROCESS_EXECUTOR_HPP
+#define BOOST_PROCESS_EXECUTOR_HPP
+
+#include <boost/process/config.hpp>
+
+#include BOOST_PROCESS_PLATFORM_PROMOTE_PATH(executor)
+BOOST_PROCESS_PLATFORM_PROMOTE_NAMESPACE(executor)
+
+#if defined(BOOST_PROCESS_DOXYGEN)
+namespace boost { namespace process {
+
+/**
+ * Starts a program.
+ *
+ * boost::process::executor is a functor which calls the system functions
+ * to start a program. Before system functions are called it iterates
+ * over initializers and calls a member function passing a reference
+ * to itself as a parameter. Initializers get then a chance to setup
+ * the executor. If system functions fail boost::process::executor again
+ * iterates over initializers and calls another member function passing a
+ * reference to itself as a parameter. This gives initializers a
+ * chance to handle the error.
+ *
+ * \note Library users shouldn't need to use boost::process::executor.
+ * It is recommended to call boost::process::execute which uses
+ * boost::pocess::executor internally.
+ */
+struct executor
+{
+ /**
+ * Default constructor.
+ */
+ executor();
+
+ /**
+ * Starts a program.
+ *
+ * \tparam initializers define what and how the program is started
+ */
+ template <class Initializer, class... Initializers>
+ child operator()(const Initializer &initializer, const Initializers... &initializers);
+
+ ///\defgroup WindowsOnly Windows only.
+ ///@{
+
+ /**
+ * Program name.
+ *
+ * \remark <em>Windows only.</em>
+ */
+ LPCTSTR exe;
+
+ /**
+ * Command line.
+ *
+ * \remark <em>Windows only.</em>
+ */
+ LPTSTR cmd_line;
+
+ /**
+ * Process attributes.
+ *
+ * \remark <em>Windows only.</em>
+ */
+ LPSECURITY_ATTRIBUTES proc_attrs;
+
+ /**
+ * Thread attributes.
+ *
+ * \remark <em>Windows only.</em>
+ */
+ LPSECURITY_ATTRIBUTES thread_attrs;
+
+ /**
+ * Flag to inherit handles.
+ *
+ * \remark <em>Windows only.</em>
+ */
+ BOOL inherit_handles;
+
+ /**
+ * Creation flags.
+ *
+ * \remark <em>Windows only.</em>
+ */
+ DWORD creation_flags;
+
+ /**
+ * Environment variables.
+ *
+ * \remark <em>Windows only.</em>
+ */
+ LPVOID env;
+
+ /**
+ * Work directory.
+ *
+ * \remark <em>Windows only.</em>
+ */
+ LPCTSTR work_dir;
+
+ /**
+ * Startupinfo structure.
+ *
+ * \remark <em>Windows only.</em>
+ */
+ STARTUPINFO startup_info;
+
+ /**
+ * Startupinfoex structure.
+ *
+ * If this member variable is available, \c startup_info is a reference
+ * to \c StartupInfo in STARTUPINFOEX.
+ *
+ * \remark <em>Windows Vista, Windows Server 2008 or better.</em>
+ */
+ STARTUPINFOEX startup_info_ex;
+
+ /**
+ * Process information.
+ *
+ * \c proc_info contains the result after a child process
+ * could be started successfully.
+ *
+ * \remark <em>Windows only.</em>
+ */
+ PROCESS_INFORMATION proc_info;
+
+ ///@}
+
+ ///\defgroup POSIXOnly POSIX only.
+ ///@{
+
+ /**
+ * Program name.
+ *
+ * \remark <em>POSIX only.</em>
+ */
+ const char *exe;
+
+ /**
+ * Command line arguments.
+ *
+ * \remark <em>POSIX only.</em>
+ */
+ char **cmd_line;
+
+ /**
+ * Environment variables.
+ *
+ * \remark <em>POSIX only.</em>
+ */
+ char **env;
+
+ ///@}
+};
+
+}}
+#endif
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/initializers.hpp b/plugins/New_GPG/src/include/boost/process/initializers.hpp
new file mode 100644
index 0000000000..c7175d1425
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/initializers.hpp
@@ -0,0 +1,497 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+/**
+ * \file boost/process/initializers.hpp
+ *
+ * Defines initializers.
+ */
+
+#ifndef BOOST_PROCESS_INITIALIZERS_HPP
+#define BOOST_PROCESS_INITIALIZERS_HPP
+
+#include <boost/process/config.hpp>
+
+#include BOOST_PROCESS_PLATFORM_PROMOTE_PATH(initializers)
+BOOST_PROCESS_PLATFORM_PROMOTE_INITIALIZERS_NAMESPACE
+
+#if defined(BOOST_PROCESS_DOXYGEN)
+namespace boost { namespace process { namespace initializers {
+
+/**
+ * Binds the standard error stream.
+ */
+class bind_stderr : public initializer_base
+{
+public:
+ /**
+ * Constructor.
+ */
+ explicit bind_stderr(const boost::iostreams::file_descriptor_sink &sink);
+};
+
+/**
+ * Binds the standard input stream.
+ */
+class bind_stdin : public initializer_base
+{
+public:
+ /**
+ * Constructor.
+ */
+ explicit bind_stdin(const boost::iostreams::file_descriptor_source &source);
+};
+
+/**
+ * Binds the standard output stream.
+ */
+class bind_stdout : public initializer_base
+{
+public:
+ /**
+ * Constructor.
+ */
+ explicit bind_stdout(const boost::iostreams::file_descriptor_sink &sink);
+};
+
+/**
+ * Binds a file descriptor.
+ *
+ * \remark <em>POSIX only.</em>
+ */
+class bind_fd : public initializer_base
+{
+public:
+ /**
+ * Constructor.
+ */
+ bind_fd(int id, const boost::iostreams::file_descriptor &fd);
+};
+
+/**
+ * Closes a file descriptor.
+ *
+ * \remark <em>POSIX only.</em>
+ */
+class close_fd : public initializer_base
+{
+ /**
+ * Constructor.
+ */
+ explicit close_fd(int fd);
+};
+
+/**
+ * Closes file descriptors.
+ *
+ * \remark <em>POSIX only.</em>
+ */
+class close_fds : public initializer_base
+{
+public:
+ /**
+ * Constructor.
+ *
+ * \c range_type must be an <tt>int</tt>-range.
+ */
+ explicit close_fds(const range_type &fds);
+};
+
+/**
+ * Closes all file descriptors a predicate returns
+ * true for.
+ *
+ * This initializer doesn't close file descriptors
+ * immediately. Instead it sets the \c FD_CLOEXEC
+ * flag. File descriptors are closed when \c execve
+ * is called and the call succeeds.
+ *
+ * \remark <em>POSIX only.</em>
+ */
+class close_fds_if : public initializer_base
+{
+public:
+ /**
+ * Constructor.
+ *
+ * \c predicate_type must be a function or functor with
+ * this signature: <tt>bool(int)</tt>
+ */
+ explicit close_fds_if(const predicate_type &pred);
+};
+
+/**
+ * Closes the standard error stream.
+ */
+class close_stderr : public initializer_base
+{
+ /**
+ * Constructor.
+ */
+ close_stderr();
+};
+
+/**
+ * Closes the standard input stream.
+ */
+class close_stdin : public initializer_base
+{
+ /**
+ * Constructor.
+ */
+ close_stdin();
+};
+
+/**
+ * Closes the standard output stream.
+ */
+class close_stdout : public initializer_base
+{
+ /**
+ * Constructor.
+ */
+ close_stdout();
+};
+
+/**
+ * Hides the console.
+ */
+class hide_console : public initializer_base
+{
+public:
+ /**
+ * Constructor.
+ */
+ hide_console();
+};
+
+/**
+ * Inherits environment variables.
+ */
+class inherit_env : public initializer_base
+{
+public:
+ /**
+ * Constructor.
+ */
+ inherit_env();
+};
+
+/**
+ * Notifies an I/O service object of fork-related events.
+ *
+ * \see boost::asio::io_service::notify_fork
+ *
+ * \remark <em>POSIX only.</em>
+ */
+class notify_io_service : public initializer_base
+{
+public:
+ /**
+ * Constructor.
+ */
+ explicit notify_io_service(boost::asio::io_service &io_service);
+};
+
+/**
+ * Generic initializer to execute any code if \c execve
+ * failed.
+ *
+ * \remark <em>POSIX only.</em>
+ */
+class on_exec_error : public initializer_base
+{
+public:
+ /**
+ * Constructor.
+ *
+ * \c handler_type must be a function or functor with
+ * this signature: <tt>void(executor&)</tt>
+ */
+ explicit on_exec_error(handler_type handler);
+};
+
+/**
+ * Generic initializer to execute any code before \c execve
+ * is called.
+ *
+ * \remark <em>POSIX only.</em>
+ */
+class on_exec_setup : public initializer_base
+{
+public:
+ /**
+ * Constructor.
+ *
+ * \c handler_type must be a function or functor with
+ * this signature: <tt>void(executor&)</tt>
+ */
+ explicit on_exec_setup(handler_type handler);
+};
+
+/**
+ * Generic initializer to execute any code if \c fork
+ * failed.
+ *
+ * \remark <em>POSIX only.</em>
+ */
+class on_fork_error : public initializer_base
+{
+public:
+ /**
+ * Constructor.
+ *
+ * \c handler_type must be a function or functor with
+ * this signature: <tt>void(executor&)</tt>
+ */
+ explicit on_fork_error(handler_type handler);
+};
+
+/**
+ * Generic initializer to execute any code before \c fork
+ * is called.
+ *
+ * \remark <em>POSIX only.</em>
+ */
+class on_fork_setup : public initializer_base
+{
+public:
+ /**
+ * Constructor.
+ *
+ * \c handler_type must be a function or functor with
+ * this signature: <tt>void(executor&)</tt>
+ */
+ explicit on_fork_setup(handler_type handler);
+};
+
+/**
+ * Generic initializer to execute any code in the parent
+ * process after \c fork has been called successfully.
+ *
+ * \remark <em>POSIX only.</em>
+ */
+class on_fork_success : public initializer_base
+{
+public:
+ /**
+ * Constructor.
+ *
+ * \c handler_type must be a function or functor with
+ * this signature: <tt>void(executor&)</tt>
+ */
+ explicit on_fork_success(handler_type handler);
+};
+
+/**
+ * Generic initializer to execute any code if \c CreateProcess
+ * failed.
+ *
+ * \remark <em>Windows only.</em>
+ */
+class on_CreateProcess_error : public initializer_base
+{
+public:
+ /**
+ * Constructor.
+ *
+ * \c handler_type must be a function or functor with
+ * this signature: <tt>void(executor&)</tt>
+ */
+ explicit on_CreateProcess_error(handler_type handler);
+};
+
+/**
+ * Generic initializer to execute any code before \c CreateProcess
+ * is called.
+ *
+ * \remark <em>Windows only.</em>
+ */
+class on_CreateProcess_setup : public initializer_base
+{
+public:
+ /**
+ * Constructor.
+ *
+ * \c handler_type must be a function or functor with
+ * this signature: <tt>void(executor&)</tt>
+ */
+ explicit on_CreateProcess_setup(handler_type handler);
+};
+
+/**
+ * Generic initializer to execute any code after \c CreateProcess
+ * has been called successfully.
+ *
+ * \remark <em>Windows only.</em>
+ */
+class on_CreateProcess_success : public initializer_base
+{
+public:
+ /**
+ * Constructor.
+ *
+ * \c handler_type must be a function or functor with
+ * this signature: <tt>void(executor&)</tt>
+ */
+ explicit on_CreateProcess_success(handler_type handler);
+};
+
+/**
+ * Specifies the executable to start.
+ *
+ * This initializer must always be used. The only exception is
+ * if you use \c set_args or a generic initializer which
+ * specifies the executable.
+ */
+class run_exe : public initializer_base
+{
+public:
+ /**
+ * Constructor.
+ *
+ * On Windows \c string_type must be <tt>const char*</tt>,
+ * <tt>std::string</tt> or <tt>boost::filesystem::path</tt>.
+ * If Unicode is used, \c string_type must be
+ * <tt>const wchar_t*</tt>, <tt>std::wstring</tt> or
+ * <tt>boost::filesystem::path</tt>.
+ *
+ * On POSIX \c string_type must be <tt>const char*</tt>,
+ * <tt>std::string</tt> or <tt>boost::filesystem::path</tt>.
+ */
+ explicit run_exe(const string_type &s);
+};
+
+/**
+ * Sets the command line arguments.
+ *
+ * The first argument specifies the executable to start unless
+ * \c run_exe is used.
+ *
+ * Use \c set_cmd_line if you don't want to pass a collection of
+ * command line arguments but set the command line as one string.
+ */
+class set_args : public initializer_base
+{
+public:
+ /**
+ * Constructor.
+ *
+ * On Windows \c range_type must be a <tt>std::string</tt>-range.
+ * If Unicode is used, \c range_type must be a
+ * <tt>std::wstring</tt>-range.
+ *
+ * On POSIX \c range_type must be a <tt>std::string</tt>-range.
+ */
+ explicit set_args(const range_type &r);
+};
+
+/**
+ * Sets the command line.
+ *
+ * Use \c set_args if you don't want to set the command line as
+ * one string but pass a collection of command line arguments.
+ */
+class set_cmd_line : public initializer_base
+{
+public:
+ /**
+ * Constructor.
+ *
+ * On Windows \c string_type must be <tt>const char*</tt>,
+ * <tt>std::string</tt> or <tt>boost::filesystem::path</tt>.
+ * If Unicode is used, \c string_type must be
+ * <tt>const wchar_t*</tt>, <tt>std::wstring</tt> or
+ * <tt>boost::filesystem::path</tt>.
+ *
+ * On POSIX \c string_type must be <tt>const char*</tt>,
+ * <tt>std::string</tt> or <tt>boost::filesystem::path</tt>.
+ */
+ explicit set_cmd_line(const string_type &s);
+};
+
+/**
+ * Sets the environment.
+ */
+class set_env : public initializer_base
+{
+public:
+ /**
+ * Constructor.
+ *
+ * On Windows \c range_type must be a <tt>std::string</tt>-range.
+ * If Unicode is used, \c range_type must be a
+ * <tt>std::wstring</tt>-range.
+ *
+ * On POSIX \c range_type must be a <tt>std::string</tt>-range.
+ */
+ explicit set_env(const range_type &r);
+};
+
+/**
+ * Sets an error if a child process can't be created.
+ */
+class set_on_error : public initializer_base
+{
+public:
+ /**
+ * Constructor.
+ */
+ explicit set_on_error(boost::system::error_code &ec);
+};
+
+/**
+ * Sets the flag \c wShowWindow in \c STARTUPINFO.
+ *
+ * \remark <em>Windows only.</em>
+ */
+class show_window : public initializer_base
+{
+public:
+ /**
+ * Constructor.
+ */
+ explicit show_window(WORD flags);
+};
+
+/**
+ * Sets the work directory.
+ */
+class start_in_dir : public initializer_base
+{
+public:
+ /**
+ * Constructor.
+ *
+ * On Windows \c string_type must be <tt>const char*</tt>,
+ * <tt>std::string</tt> or <tt>boost::filesystem::path</tt>.
+ * If Unicode is used, \c string_type must be
+ * <tt>const wchar_t*</tt>, <tt>std::wstring</tt> or
+ * <tt>boost::filesystem::path</tt>.
+ *
+ * On POSIX \c string_type must be <tt>const char*</tt>,
+ * <tt>std::string</tt> or <tt>boost::filesystem::path</tt>.
+ */
+ explicit start_in_dir(const string_type &s);
+};
+
+/**
+ * Throws an error if a child process can't be created.
+ *
+ * The type of the error thrown is \c boost::system::system_error.
+ */
+class throw_on_error : public initializer_base
+{
+public:
+};
+
+}}}
+#endif
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/mitigate.hpp b/plugins/New_GPG/src/include/boost/process/mitigate.hpp
new file mode 100644
index 0000000000..6838984aa1
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/mitigate.hpp
@@ -0,0 +1,104 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+/**
+ * \file boost/process/mitigate.hpp
+ *
+ * Helpers to mitigate platform differences.
+ */
+
+#ifndef BOOST_PROCESS_MITIGATE_HPP
+#define BOOST_PROCESS_MITIGATE_HPP
+
+#include <boost/asio.hpp>
+#if defined(BOOST_POSIX_API)
+# include <sys/wait.h>
+#endif
+
+namespace boost { namespace process {
+
+#if defined(BOOST_WINDOWS_API)
+typedef boost::asio::windows::stream_handle pipe_end;
+#elif defined(BOOST_POSIX_API)
+typedef boost::asio::posix::stream_descriptor pipe_end;
+#endif
+
+inline const char *zero_device()
+{
+#if defined(BOOST_WINDOWS_API)
+ return "NUL";
+#elif defined(BOOST_POSIX_API)
+ return "/dev/zero";
+#endif
+}
+
+inline const char *null_device()
+{
+#if defined(BOOST_WINDOWS_API)
+ return "NUL";
+#elif defined(BOOST_POSIX_API)
+ return "/dev/null";
+#endif
+}
+
+#if defined(BOOST_WINDOWS_API)
+# define BOOST_PROCESS_EXITSTATUS(a) static_cast<int>(a)
+#elif defined(BOOST_POSIX_API)
+# define BOOST_PROCESS_EXITSTATUS WEXITSTATUS
+#endif
+
+#if defined(BOOST_PROCESS_DOXYGEN)
+/**
+ * Type definition for the end of a pipe.
+ *
+ * On Windows the type is based on boost::asio::windows::stream_handle. On
+ * POSIX it is based on boost::asio::posix::stream_descriptor.
+ *
+ * You can use this type definition for asynchronous I/O with streams of
+ * child processes.
+ */
+typedef boost_asio_type pipe_end;
+
+/**
+ * Gets the name of the zero device.
+ *
+ * You can use zero_device to initialize a
+ * boost::iostreams::file_descriptor_source to read
+ * null characters from.
+ *
+ * \returns NUL on Windows and /dev/zero on POSIX.
+ */
+const char *zero_device();
+
+/**
+ * Gets the name of the null device.
+ *
+ * You can use null_device to initialize a
+ * boost::iostreams::file_descriptor_sink which discards
+ * data written to it.
+ *
+ * \returns NUL on Windows and /dev/null on POSIX.
+ */
+const char *null_device();
+
+/**
+ * \def BOOST_PROCESS_EXITSTATUS
+ *
+ * On Windows \c BOOST_PROCESS_EXITSTATUS is a static cast to \c int.
+ * On POSIX it is set to \c WEXITSTATUS.
+ *
+ * You can use \c BOOST_PROCESS_EXITSTATUS for the return value of
+ * boost::process::wait_for_exit to get the exit status of a process.
+ */
+#define BOOST_PROCESS_EXITSTATUS
+#endif
+
+}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/pipe.hpp b/plugins/New_GPG/src/include/boost/process/pipe.hpp
new file mode 100644
index 0000000000..35f2a4470d
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/pipe.hpp
@@ -0,0 +1,64 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+/**
+ * \file boost/process/pipe.hpp
+ *
+ * Defines a pipe.
+ */
+
+#ifndef BOOST_PROCESS_PIPE_HPP
+#define BOOST_PROCESS_PIPE_HPP
+
+#include <boost/process/config.hpp>
+
+#include BOOST_PROCESS_PLATFORM_PROMOTE_PATH(pipe)
+BOOST_PROCESS_PLATFORM_PROMOTE_NAMESPACE(pipe)
+BOOST_PROCESS_PLATFORM_PROMOTE_NAMESPACE(make_pipe)
+
+#if defined(BOOST_PROCESS_DOXYGEN)
+namespace boost { namespace process {
+
+/**
+ * Represents a pipe.
+ */
+struct pipe
+{
+ /**
+ * Read-end.
+ */
+ pipe_end_type source;
+
+ /**
+ * Write-end.
+ */
+ pipe_end_type sink;
+
+ /**
+ * Constructor.
+ */
+ pipe(pipe_end_type source, pipe_end_type sink);
+};
+
+/**
+ * Returns a pipe instance.
+ *
+ * This is a helper function to instantiate boost::process::pipe.
+ *
+ * \note boost::process::make_pipe does not create a pipe.
+ * You must pass existing pipe ends to this function.
+ * If you want to create an anonymous pipe, call
+ * boost::process::create_pipe.
+ */
+pipe make_pipe(pipe_end_type source, pipe_end_type sink);
+
+}}
+#endif
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/search_path.hpp b/plugins/New_GPG/src/include/boost/process/search_path.hpp
new file mode 100644
index 0000000000..20bff060b6
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/search_path.hpp
@@ -0,0 +1,51 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+/**
+ * \file boost/process/search_path.hpp
+ *
+ * Defines a function to search for an executable in path.
+ */
+
+#ifndef BOOST_PROCESS_SEARCH_PATH_HPP
+#define BOOST_PROCESS_SEARCH_PATH_HPP
+
+#include <boost/process/config.hpp>
+
+#include BOOST_PROCESS_PLATFORM_PROMOTE_PATH(search_path)
+BOOST_PROCESS_PLATFORM_PROMOTE_NAMESPACE(search_path)
+
+#if defined(BOOST_PROCESS_DOXYGEN)
+namespace boost { namespace process {
+
+/**
+ * Searches for an executable in path.
+ *
+ * filename must be a basename including the file extension.
+ * It must not include any directory separators (like a slash).
+ * On Windows the file extension may be omitted. The function
+ * will then try the various file extensions for executables on
+ * Windows to find filename.
+ *
+ * path must be a set of directories. Directories must be
+ * separated by colons on POSIX and by semicolons on Windows.
+ * If path is empty, the environment variable PATH is used.
+ *
+ * \returns the absolute path to the executable filename or an
+ * empty string if filename isn't found
+ *
+ * \throws std::runtime_error if path is empty and no environment
+ * variable PATH exists
+ */
+string_type search_path(const string_type &filename, string_type path = "");
+
+}}
+#endif
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/shell_path.hpp b/plugins/New_GPG/src/include/boost/process/shell_path.hpp
new file mode 100644
index 0000000000..92e9f0814b
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/shell_path.hpp
@@ -0,0 +1,46 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+/**
+ * \file boost/process/shell_path.hpp
+ *
+ * Defines a function to return the absolute path to a shell executable.
+ */
+
+#ifndef BOOST_PROCESS_SHELL_PATH_HPP
+#define BOOST_PROCESS_SHELL_PATH_HPP
+
+#include <boost/process/config.hpp>
+
+#include BOOST_PROCESS_PLATFORM_PROMOTE_PATH(shell_path)
+BOOST_PROCESS_PLATFORM_PROMOTE_NAMESPACE(shell_path)
+
+#if defined(BOOST_PROCESS_DOXYGEN)
+namespace boost { namespace process {
+
+/**
+ * Returns the absolute path to a shell executable.
+ *
+ * \returns the path to cmd.exe on Windows and /bin/sh on POSIX.
+ *
+ * \throws boost::system::system_error in case of an error
+ */
+boost::filesystem::path shell_path();
+
+/**
+ * Returns the absolute path to a shell executable.
+ *
+ * \returns the path to cmd.exe on Windows and /bin/sh on POSIX.
+ */
+boost::filesystem::path shell_path(boost::system::error_code &ec);
+
+}}
+#endif
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/terminate.hpp b/plugins/New_GPG/src/include/boost/process/terminate.hpp
new file mode 100644
index 0000000000..140eba7e8d
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/terminate.hpp
@@ -0,0 +1,52 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+/**
+ * \file boost/process/terminate.hpp
+ *
+ * Defines a function to terminate a process.
+ */
+
+#ifndef BOOST_PROCESS_TERMINATE_HPP
+#define BOOST_PROCESS_TERMINATE_HPP
+
+#include <boost/process/config.hpp>
+
+#include BOOST_PROCESS_PLATFORM_PROMOTE_PATH(terminate)
+BOOST_PROCESS_PLATFORM_PROMOTE_NAMESPACE(terminate)
+
+#if defined(BOOST_PROCESS_DOXYGEN)
+namespace boost { namespace process {
+
+/**
+ * Terminates a process.
+ *
+ * \warning Call this function only as a last resort. The process
+ * is terminated immediately and forcefully and has no
+ * chance to close or clean up resources properly.
+ *
+ * \throws boost::system::system_error in case of an error
+ */
+template <class Process>
+void terminate(const Process &p);
+
+/**
+ * Terminates a process.
+ *
+ * \warning Call this function only as a last resort. The process
+ * is terminated immediately and forcefully and has no
+ * chance to close or clean up resources properly.
+ */
+template <class Process>
+void terminate(const Process &p, boost::system::error_code &ec);
+
+}}
+#endif
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/wait_for_exit.hpp b/plugins/New_GPG/src/include/boost/process/wait_for_exit.hpp
new file mode 100644
index 0000000000..d9b118695d
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/wait_for_exit.hpp
@@ -0,0 +1,58 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+/**
+ * \file boost/process/wait_for_exit.hpp
+ *
+ * Defines a function to wait for a process to exit.
+ */
+
+#ifndef BOOST_PROCESS_WAIT_FOR_EXIT_HPP
+#define BOOST_PROCESS_WAIT_FOR_EXIT_HPP
+
+#include <boost/process/config.hpp>
+
+#include BOOST_PROCESS_PLATFORM_PROMOTE_PATH(wait_for_exit)
+BOOST_PROCESS_PLATFORM_PROMOTE_NAMESPACE(wait_for_exit)
+
+#if defined(BOOST_PROCESS_DOXYGEN)
+namespace boost { namespace process {
+
+/**
+ * Waits for a process to exit.
+ *
+ * On Window boost::process::wait_for_exit returns the exit code
+ * of the process. On POSIX the exit status is returned. You must
+ * use the macro \c WEXITSTATUS (defined in sys/wait.h) to fetch
+ * the exit code from the exit status.
+ *
+ * \note This is a blocking function.
+ *
+ * \throws boost::system::system_error in case of an error
+ */
+template <class Process>
+int_type wait_for_exit(const Process &p);
+
+/**
+ * Waits for a process to exit.
+ *
+ * On Window boost::process::wait_for_exit returns the exit code
+ * of the process. On POSIX the exit status is returned. You must
+ * use the macro \c WEXITSTATUS (defined in sys/wait.h) to fetch
+ * the exit code from the exit status.
+ *
+ * \note This is a blocking function.
+ */
+template <class Process>
+int_type wait_for_exit(const Process &p, boost::system::error_code &ec);
+
+}}
+#endif
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/child.hpp b/plugins/New_GPG/src/include/boost/process/windows/child.hpp
new file mode 100644
index 0000000000..083cd29da0
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/child.hpp
@@ -0,0 +1,55 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_CHILD_HPP
+#define BOOST_PROCESS_WINDOWS_CHILD_HPP
+
+#include <boost/move/move.hpp>
+#include <Windows.h>
+
+namespace boost { namespace process { namespace windows {
+
+class child
+{
+public:
+ PROCESS_INFORMATION proc_info;
+
+ explicit child(const PROCESS_INFORMATION &pi) : proc_info(pi) {}
+
+ ~child()
+ {
+ ::CloseHandle(proc_info.hProcess);
+ ::CloseHandle(proc_info.hThread);
+ }
+
+ child(BOOST_RV_REF(child) c) : proc_info(c.proc_info)
+ {
+ c.proc_info.hProcess = INVALID_HANDLE_VALUE;
+ c.proc_info.hThread = INVALID_HANDLE_VALUE;
+ }
+
+ child &operator=(BOOST_RV_REF(child) c)
+ {
+ ::CloseHandle(proc_info.hProcess);
+ ::CloseHandle(proc_info.hThread);
+ proc_info = c.proc_info;
+ c.proc_info.hProcess = INVALID_HANDLE_VALUE;
+ c.proc_info.hThread = INVALID_HANDLE_VALUE;
+ return *this;
+ }
+
+ HANDLE process_handle() const { return proc_info.hProcess; }
+
+private:
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(child);
+};
+
+}}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/create_pipe.hpp b/plugins/New_GPG/src/include/boost/process/windows/create_pipe.hpp
new file mode 100644
index 0000000000..fe1e49751d
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/create_pipe.hpp
@@ -0,0 +1,40 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_CREATE_PIPE_HPP
+#define BOOST_PROCESS_WINDOWS_CREATE_PIPE_HPP
+
+#include <boost/process/config.hpp>
+#include <boost/process/windows/pipe.hpp>
+#include <boost/system/error_code.hpp>
+#include <Windows.h>
+
+namespace boost { namespace process { namespace windows {
+
+inline pipe create_pipe()
+{
+ HANDLE handles[2];
+ if (!::CreatePipe(&handles[0], &handles[1], NULL, 0))
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreatePipe() failed");
+ return make_pipe(handles[0], handles[1]);
+}
+
+inline pipe create_pipe(boost::system::error_code &ec)
+{
+ HANDLE handles[2];
+ if (!::CreatePipe(&handles[0], &handles[1], NULL, 0))
+ BOOST_PROCESS_RETURN_LAST_SYSTEM_ERROR(ec);
+ else
+ ec.clear();
+ return make_pipe(handles[0], handles[1]);
+}
+
+}}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/execute.hpp b/plugins/New_GPG/src/include/boost/process/windows/execute.hpp
new file mode 100644
index 0000000000..43067521ea
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/execute.hpp
@@ -0,0 +1,82 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_EXECUTE_HPP
+#define BOOST_PROCESS_WINDOWS_EXECUTE_HPP
+
+#include <boost/process/windows/executor.hpp>
+#include <boost/process/windows/child.hpp>
+#include <boost/fusion/tuple/make_tuple.hpp>
+#include <boost/ref.hpp>
+
+namespace boost { namespace process { namespace windows {
+
+template <class I0>
+child execute(const I0 &i0)
+{
+ return executor()(boost::fusion::make_tuple(boost::cref(i0)));
+}
+
+template <class I0, class I1>
+child execute(const I0 &i0, const I1 &i1)
+{
+ return executor()(boost::fusion::make_tuple(boost::cref(i0), boost::cref(i1)));
+}
+
+template <class I0, class I1, class I2>
+child execute(const I0 &i0, const I1 &i1, const I2 &i2)
+{
+ return executor()(boost::fusion::make_tuple(boost::cref(i0), boost::cref(i1), boost::cref(i2)));
+}
+
+template <class I0, class I1, class I2, class I3>
+child execute(const I0 &i0, const I1 &i1, const I2 &i2, const I3 &i3)
+{
+ return executor()(boost::fusion::make_tuple(boost::cref(i0), boost::cref(i1), boost::cref(i2), boost::cref(i3)));
+}
+
+template <class I0, class I1, class I2, class I3, class I4>
+child execute(const I0 &i0, const I1 &i1, const I2 &i2, const I3 &i3, const I4 &i4)
+{
+ return executor()(boost::fusion::make_tuple(boost::cref(i0), boost::cref(i1), boost::cref(i2), boost::cref(i3), boost::cref(i4)));
+}
+
+template <class I0, class I1, class I2, class I3, class I4, class I5>
+child execute(const I0 &i0, const I1 &i1, const I2 &i2, const I3 &i3, const I4 &i4, const I5 &i5)
+{
+ return executor()(boost::fusion::make_tuple(boost::cref(i0), boost::cref(i1), boost::cref(i2), boost::cref(i3), boost::cref(i4), boost::cref(i5)));
+}
+
+template <class I0, class I1, class I2, class I3, class I4, class I5, class I6>
+child execute(const I0 &i0, const I1 &i1, const I2 &i2, const I3 &i3, const I4 &i4, const I5 &i5, const I6 &i6)
+{
+ return executor()(boost::fusion::make_tuple(boost::cref(i0), boost::cref(i1), boost::cref(i2), boost::cref(i3), boost::cref(i4), boost::cref(i5), boost::cref(i6)));
+}
+
+template <class I0, class I1, class I2, class I3, class I4, class I5, class I6, class I7>
+child execute(const I0 &i0, const I1 &i1, const I2 &i2, const I3 &i3, const I4 &i4, const I5 &i5, const I6 &i6, const I7 &i7)
+{
+ return executor()(boost::fusion::make_tuple(boost::cref(i0), boost::cref(i1), boost::cref(i2), boost::cref(i3), boost::cref(i4), boost::cref(i5), boost::cref(i6), boost::cref(i7)));
+}
+
+template <class I0, class I1, class I2, class I3, class I4, class I5, class I6, class I7, class I8>
+child execute(const I0 &i0, const I1 &i1, const I2 &i2, const I3 &i3, const I4 &i4, const I5 &i5, const I6 &i6, const I7 &i7, const I8 &i8)
+{
+ return executor()(boost::fusion::make_tuple(boost::cref(i0), boost::cref(i1), boost::cref(i2), boost::cref(i3), boost::cref(i4), boost::cref(i5), boost::cref(i6), boost::cref(i7), boost::cref(i8)));
+}
+
+template <class I0, class I1, class I2, class I3, class I4, class I5, class I6, class I7, class I8, class I9>
+child execute(const I0 &i0, const I1 &i1, const I2 &i2, const I3 &i3, const I4 &i4, const I5 &i5, const I6 &i6, const I7 &i7, const I8 &i8, const I9 &i9)
+{
+ return executor()(boost::fusion::make_tuple(boost::cref(i0), boost::cref(i1), boost::cref(i2), boost::cref(i3), boost::cref(i4), boost::cref(i5), boost::cref(i6), boost::cref(i7), boost::cref(i8), boost::cref(i9)));
+}
+
+}}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/executor.hpp b/plugins/New_GPG/src/include/boost/process/windows/executor.hpp
new file mode 100644
index 0000000000..1560f30793
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/executor.hpp
@@ -0,0 +1,130 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_EXECUTOR_HPP
+#define BOOST_PROCESS_WINDOWS_EXECUTOR_HPP
+
+#include <boost/process/windows/child.hpp>
+#include <boost/fusion/algorithm/iteration/for_each.hpp>
+#include <Windows.h>
+
+namespace boost { namespace process { namespace windows {
+
+struct executor
+{
+ executor() : exe(0), cmd_line(0), proc_attrs(0), thread_attrs(0),
+ inherit_handles(FALSE),
+#if (_WIN32_WINNT >= 0x0600)
+ creation_flags(EXTENDED_STARTUPINFO_PRESENT),
+#else
+ creation_flags(0),
+#endif
+ env(0), work_dir(0)
+#if (_WIN32_WINNT >= 0x0600)
+ ,startup_info(startup_info_ex.StartupInfo)
+#endif
+ {
+#if (_WIN32_WINNT >= 0x0600)
+ ZeroMemory(&startup_info_ex, sizeof(STARTUPINFOEX));
+ startup_info.cb = sizeof(STARTUPINFOEX);
+#else
+ ZeroMemory(&startup_info, sizeof(STARTUPINFO));
+ startup_info.cb = sizeof(STARTUPINFO);
+#endif
+ startup_info.hStdInput = INVALID_HANDLE_VALUE;
+ startup_info.hStdOutput = INVALID_HANDLE_VALUE;
+ startup_info.hStdError = INVALID_HANDLE_VALUE;
+ }
+
+ struct call_on_CreateProcess_setup
+ {
+ executor &e_;
+
+ call_on_CreateProcess_setup(executor &e) : e_(e) {}
+
+ template <class Arg>
+ void operator()(Arg &arg) const
+ {
+ arg.on_CreateProcess_setup(e_);
+ }
+ };
+
+ struct call_on_CreateProcess_error
+ {
+ executor &e_;
+
+ call_on_CreateProcess_error(executor &e) : e_(e) {}
+
+ template <class Arg>
+ void operator()(Arg &arg) const
+ {
+ arg.on_CreateProcess_error(e_);
+ }
+ };
+
+ struct call_on_CreateProcess_success
+ {
+ executor &e_;
+
+ call_on_CreateProcess_success(executor &e) : e_(e) {}
+
+ template <class Arg>
+ void operator()(Arg &arg) const
+ {
+ arg.on_CreateProcess_success(e_);
+ }
+ };
+
+ template <class InitializerSequence>
+ child operator()(const InitializerSequence &seq)
+ {
+ boost::fusion::for_each(seq, call_on_CreateProcess_setup(*this));
+
+ if (!::CreateProcess(
+ exe,
+ cmd_line,
+ proc_attrs,
+ thread_attrs,
+ inherit_handles,
+ creation_flags,
+ env,
+ work_dir,
+ &startup_info,
+ &proc_info))
+ {
+ boost::fusion::for_each(seq, call_on_CreateProcess_error(*this));
+ }
+ else
+ {
+ boost::fusion::for_each(seq, call_on_CreateProcess_success(*this));
+ }
+
+ return child(proc_info);
+ }
+
+ LPCTSTR exe;
+ LPTSTR cmd_line;
+ LPSECURITY_ATTRIBUTES proc_attrs;
+ LPSECURITY_ATTRIBUTES thread_attrs;
+ BOOL inherit_handles;
+ DWORD creation_flags;
+ LPVOID env;
+ LPCTSTR work_dir;
+#if (_WIN32_WINNT >= 0x0600)
+ STARTUPINFOEX startup_info_ex;
+ STARTUPINFO &startup_info;
+#else
+ STARTUPINFO startup_info;
+#endif
+ PROCESS_INFORMATION proc_info;
+};
+
+}}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers.hpp
new file mode 100644
index 0000000000..2d7098c034
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/initializers.hpp
@@ -0,0 +1,33 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_HPP
+#define BOOST_PROCESS_WINDOWS_INITIALIZERS_HPP
+
+#include <boost/process/windows/initializers/bind_stderr.hpp>
+#include <boost/process/windows/initializers/bind_stdin.hpp>
+#include <boost/process/windows/initializers/bind_stdout.hpp>
+#include <boost/process/windows/initializers/close_stderr.hpp>
+#include <boost/process/windows/initializers/close_stdin.hpp>
+#include <boost/process/windows/initializers/close_stdout.hpp>
+#include <boost/process/windows/initializers/hide_console.hpp>
+#include <boost/process/windows/initializers/inherit_env.hpp>
+#include <boost/process/windows/initializers/on_CreateProcess_error.hpp>
+#include <boost/process/windows/initializers/on_CreateProcess_setup.hpp>
+#include <boost/process/windows/initializers/on_CreateProcess_success.hpp>
+#include <boost/process/windows/initializers/run_exe.hpp>
+#include <boost/process/windows/initializers/set_args.hpp>
+#include <boost/process/windows/initializers/set_cmd_line.hpp>
+#include <boost/process/windows/initializers/set_env.hpp>
+#include <boost/process/windows/initializers/set_on_error.hpp>
+#include <boost/process/windows/initializers/show_window.hpp>
+#include <boost/process/windows/initializers/start_in_dir.hpp>
+#include <boost/process/windows/initializers/throw_on_error.hpp>
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/bind_stderr.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/bind_stderr.hpp
new file mode 100644
index 0000000000..de3ee30dc5
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/bind_stderr.hpp
@@ -0,0 +1,39 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_BIND_STDERR_HPP
+#define BOOST_PROCESS_WINDOWS_INITIALIZERS_BIND_STDERR_HPP
+
+#include <boost/process/windows/initializers/initializer_base.hpp>
+#include <boost/iostreams/device/file_descriptor.hpp>
+#include <Windows.h>
+
+namespace boost { namespace process { namespace windows { namespace initializers {
+
+class bind_stderr : public initializer_base
+{
+public:
+ explicit bind_stderr(const boost::iostreams::file_descriptor_sink &sink) : sink_(sink) {}
+
+ template <class WindowsExecutor>
+ void on_CreateProcess_setup(WindowsExecutor &e) const
+ {
+ ::SetHandleInformation(sink_.handle(), HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
+ e.startup_info.hStdError = sink_.handle();
+ e.startup_info.dwFlags |= STARTF_USESTDHANDLES;
+ e.inherit_handles = true;
+ }
+
+private:
+ boost::iostreams::file_descriptor_sink sink_;
+};
+
+}}}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/bind_stdin.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/bind_stdin.hpp
new file mode 100644
index 0000000000..54c942ab63
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/bind_stdin.hpp
@@ -0,0 +1,39 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_BIND_STDIN_HPP
+#define BOOST_PROCESS_WINDOWS_INITIALIZERS_BIND_STDIN_HPP
+
+#include <boost/process/windows/initializers/initializer_base.hpp>
+#include <boost/iostreams/device/file_descriptor.hpp>
+#include <Windows.h>
+
+namespace boost { namespace process { namespace windows { namespace initializers {
+
+class bind_stdin : public initializer_base
+{
+public:
+ explicit bind_stdin(const boost::iostreams::file_descriptor_source &source) : source_(source) {}
+
+ template <class WindowsExecutor>
+ void on_CreateProcess_setup(WindowsExecutor &e) const
+ {
+ ::SetHandleInformation(source_.handle(), HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
+ e.startup_info.hStdInput = source_.handle();
+ e.startup_info.dwFlags |= STARTF_USESTDHANDLES;
+ e.inherit_handles = true;
+ }
+
+private:
+ boost::iostreams::file_descriptor_source source_;
+};
+
+}}}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/bind_stdout.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/bind_stdout.hpp
new file mode 100644
index 0000000000..c72c05f1bf
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/bind_stdout.hpp
@@ -0,0 +1,39 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_BIND_STDOUT_HPP
+#define BOOST_PROCESS_WINDOWS_INITIALIZERS_BIND_STDOUT_HPP
+
+#include <boost/process/windows/initializers/initializer_base.hpp>
+#include <boost/iostreams/device/file_descriptor.hpp>
+#include <Windows.h>
+
+namespace boost { namespace process { namespace windows { namespace initializers {
+
+class bind_stdout : public initializer_base
+{
+public:
+ explicit bind_stdout(const boost::iostreams::file_descriptor_sink &sink) : sink_(sink) {}
+
+ template <class WindowsExecutor>
+ void on_CreateProcess_setup(WindowsExecutor &e) const
+ {
+ ::SetHandleInformation(sink_.handle(), HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
+ e.startup_info.hStdOutput = sink_.handle();
+ e.startup_info.dwFlags |= STARTF_USESTDHANDLES;
+ e.inherit_handles = true;
+ }
+
+private:
+ boost::iostreams::file_descriptor_sink sink_;
+};
+
+}}}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/close_stderr.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/close_stderr.hpp
new file mode 100644
index 0000000000..373c097f3a
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/close_stderr.hpp
@@ -0,0 +1,31 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_CLOSE_STDERR_HPP
+#define BOOST_PROCESS_WINDOWS_INITIALIZERS_CLOSE_STDERR_HPP
+
+#include <boost/process/windows/initializers/initializer_base.hpp>
+#include <Windows.h>
+
+namespace boost { namespace process { namespace windows { namespace initializers {
+
+class close_stderr : public initializer_base
+{
+public:
+ template <class WindowsExecutor>
+ void on_CreateProcess_setup(WindowsExecutor &e) const
+ {
+ e.startup_info.hStdError = INVALID_HANDLE_VALUE;
+ e.startup_info.dwFlags |= STARTF_USESTDHANDLES;
+ }
+};
+
+}}}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/close_stdin.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/close_stdin.hpp
new file mode 100644
index 0000000000..036b0bb4ce
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/close_stdin.hpp
@@ -0,0 +1,31 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_CLOSE_STDIN_HPP
+#define BOOST_PROCESS_WINDOWS_INITIALIZERS_CLOSE_STDIN_HPP
+
+#include <boost/process/windows/initializers/initializer_base.hpp>
+#include <Windows.h>
+
+namespace boost { namespace process { namespace windows { namespace initializers {
+
+class close_stdin : public initializer_base
+{
+public:
+ template <class WindowsExecutor>
+ void on_CreateProcess_setup(WindowsExecutor &e) const
+ {
+ e.startup_info.hStdInput = INVALID_HANDLE_VALUE;
+ e.startup_info.dwFlags |= STARTF_USESTDHANDLES;
+ }
+};
+
+}}}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/close_stdout.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/close_stdout.hpp
new file mode 100644
index 0000000000..b58a6000f9
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/close_stdout.hpp
@@ -0,0 +1,31 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_CLOSE_STDOUT_HPP
+#define BOOST_PROCESS_WINDOWS_INITIALIZERS_CLOSE_STDOUT_HPP
+
+#include <boost/process/windows/initializers/initializer_base.hpp>
+#include <Windows.h>
+
+namespace boost { namespace process { namespace windows { namespace initializers {
+
+class close_stdout : public initializer_base
+{
+public:
+ template <class WindowsExecutor>
+ void on_CreateProcess_setup(WindowsExecutor &e) const
+ {
+ e.startup_info.hStdOutput = INVALID_HANDLE_VALUE;
+ e.startup_info.dwFlags |= STARTF_USESTDHANDLES;
+ }
+};
+
+}}}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/hide_console.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/hide_console.hpp
new file mode 100644
index 0000000000..b01aa026f0
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/hide_console.hpp
@@ -0,0 +1,31 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_HIDE_CONSOLE_HPP
+#define BOOST_PROCESS_WINDOWS_INITIALIZERS_HIDE_CONSOLE_HPP
+
+#include <boost/process/windows/initializers/initializer_base.hpp>
+#include <Windows.h>
+
+namespace boost { namespace process { namespace windows { namespace initializers {
+
+class hide_console : public initializer_base
+{
+public:
+ template <class WindowsExecutor>
+ void on_CreateProcess_setup(WindowsExecutor &e) const
+ {
+ e.startup_info.dwFlags |= STARTF_USESHOWWINDOW;
+ e.startup_info.wShowWindow |= SW_HIDE;
+ }
+};
+
+}}}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/inherit_env.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/inherit_env.hpp
new file mode 100644
index 0000000000..a2b2eda00a
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/inherit_env.hpp
@@ -0,0 +1,24 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_INHERIT_ENV_HPP
+#define BOOST_PROCESS_WINDOWS_INITIALIZERS_INHERIT_ENV_HPP
+
+#include <boost/process/windows/initializers/initializer_base.hpp>
+
+namespace boost { namespace process { namespace windows { namespace initializers {
+
+class inherit_env : public initializer_base
+{
+public:
+};
+
+}}}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/initializer_base.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/initializer_base.hpp
new file mode 100644
index 0000000000..b98da7b21b
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/initializer_base.hpp
@@ -0,0 +1,29 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_INITIALIZER_BASE_HPP
+#define BOOST_PROCESS_WINDOWS_INITIALIZERS_INITIALIZER_BASE_HPP
+
+namespace boost { namespace process { namespace windows { namespace initializers {
+
+struct initializer_base
+{
+ template <class WindowsExecutor>
+ void on_CreateProcess_setup(WindowsExecutor&) const {}
+
+ template <class WindowsExecutor>
+ void on_CreateProcess_error(WindowsExecutor&) const {}
+
+ template <class WindowsExecutor>
+ void on_CreateProcess_success(WindowsExecutor&) const {}
+};
+
+}}}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/on_CreateProcess_error.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/on_CreateProcess_error.hpp
new file mode 100644
index 0000000000..71eeada072
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/on_CreateProcess_error.hpp
@@ -0,0 +1,42 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_ON_CREATEPROCESS_ERROR_HPP
+#define BOOST_PROCESS_WINDOWS_INITIALIZERS_ON_CREATEPROCESS_ERROR_HPP
+
+#include <boost/process/config.hpp>
+#include <boost/process/windows/initializers/initializer_base.hpp>
+
+namespace boost { namespace process { namespace windows { namespace initializers {
+
+template <class Handler>
+class on_CreateProcess_error_ : public initializer_base
+{
+public:
+ explicit on_CreateProcess_error_(Handler handler) : handler_(handler) {}
+
+ template <class WindowsExecutor>
+ void on_CreateProcess_error(WindowsExecutor &e) const
+ {
+ handler_(e);
+ }
+
+private:
+ Handler handler_;
+};
+
+template <class Handler>
+on_CreateProcess_error_<Handler> on_CreateProcess_error(Handler handler)
+{
+ return on_CreateProcess_error_<Handler>(handler);
+}
+
+}}}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/on_CreateProcess_setup.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/on_CreateProcess_setup.hpp
new file mode 100644
index 0000000000..671fc9ac5c
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/on_CreateProcess_setup.hpp
@@ -0,0 +1,42 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_ON_CREATEPROCESS_SETUP_HPP
+#define BOOST_PROCESS_WINDOWS_INITIALIZERS_ON_CREATEPROCESS_SETUP_HPP
+
+#include <boost/process/config.hpp>
+#include <boost/process/windows/initializers/initializer_base.hpp>
+
+namespace boost { namespace process { namespace windows { namespace initializers {
+
+template <class Handler>
+class on_CreateProcess_setup_ : public initializer_base
+{
+public:
+ explicit on_CreateProcess_setup_(Handler handler) : handler_(handler) {}
+
+ template <class WindowsExecutor>
+ void on_CreateProcess_setup(WindowsExecutor &e) const
+ {
+ handler_(e);
+ }
+
+private:
+ Handler handler_;
+};
+
+template <class Handler>
+on_CreateProcess_setup_<Handler> on_CreateProcess_setup(Handler handler)
+{
+ return on_CreateProcess_setup_<Handler>(handler);
+}
+
+}}}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/on_CreateProcess_success.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/on_CreateProcess_success.hpp
new file mode 100644
index 0000000000..67b3b2bdcf
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/on_CreateProcess_success.hpp
@@ -0,0 +1,42 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_ON_CREATEPROCESS_SUCCESS_HPP
+#define BOOST_PROCESS_WINDOWS_INITIALIZERS_ON_CREATEPROCESS_SUCCESS_HPP
+
+#include <boost/process/config.hpp>
+#include <boost/process/windows/initializers/initializer_base.hpp>
+
+namespace boost { namespace process { namespace windows { namespace initializers {
+
+template <class Handler>
+class on_CreateProcess_success_ : public initializer_base
+{
+public:
+ explicit on_CreateProcess_success_(Handler handler) : handler_(handler) {}
+
+ template <class WindowsExecutor>
+ void on_CreateProcess_sucess(WindowsExecutor &e) const
+ {
+ handler_(e);
+ }
+
+private:
+ Handler handler_;
+};
+
+template <class Handler>
+on_CreateProcess_success_<Handler> on_CreateProcess_success(Handler handler)
+{
+ return on_CreateProcess_success_<Handler>(handler);
+}
+
+}}}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/run_exe.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/run_exe.hpp
new file mode 100644
index 0000000000..bfa2b790b1
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/run_exe.hpp
@@ -0,0 +1,69 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_RUN_EXE_HPP
+#define BOOST_PROCESS_WINDOWS_INITIALIZERS_RUN_EXE_HPP
+
+#include <boost/process/windows/initializers/initializer_base.hpp>
+#include <boost/filesystem.hpp>
+#include <string>
+
+namespace boost { namespace process { namespace windows { namespace initializers {
+
+template <class String>
+class run_exe_ : public initializer_base
+{
+public:
+ explicit run_exe_(const String &s) : s_(s) {}
+
+ template <class WindowsExecutor>
+ void on_CreateProcess_setup(WindowsExecutor &e) const
+ {
+ e.exe = s_.c_str();
+ }
+
+private:
+ String s_;
+};
+
+#if defined(_UNICODE) || defined(UNICODE)
+inline run_exe_<std::wstring> run_exe(const wchar_t *ws)
+{
+ return run_exe_<std::wstring>(ws);
+}
+
+inline run_exe_<std::wstring> run_exe(const std::wstring &ws)
+{
+ return run_exe_<std::wstring>(ws);
+}
+
+inline run_exe_<std::wstring> run_exe(const boost::filesystem::path &p)
+{
+ return run_exe_<std::wstring>(p.wstring());
+}
+#else
+inline run_exe_<std::string> run_exe(const char *s)
+{
+ return run_exe_<std::string>(s);
+}
+
+inline run_exe_<std::string> run_exe(const std::string &s)
+{
+ return run_exe_<std::string>(s);
+}
+
+inline run_exe_<std::string> run_exe(const boost::filesystem::path &p)
+{
+ return run_exe_<std::string>(p.string());
+}
+#endif
+
+}}}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/set_args.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/set_args.hpp
new file mode 100644
index 0000000000..4b3c5b6249
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/set_args.hpp
@@ -0,0 +1,87 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_SET_ARGS_HPP
+#define BOOST_PROCESS_WINDOWS_INITIALIZERS_SET_ARGS_HPP
+
+#include <boost/process/windows/initializers/initializer_base.hpp>
+#include <boost/range/begin.hpp>
+#include <boost/range/end.hpp>
+#include <boost/range/algorithm/copy.hpp>
+#include <boost/algorithm/string/predicate.hpp>
+#include <boost/shared_array.hpp>
+#include <sstream>
+
+namespace boost { namespace process { namespace windows { namespace initializers {
+
+template <class Range>
+class set_args_ : public initializer_base
+{
+private:
+ typedef typename Range::const_iterator ConstIterator;
+ typedef typename Range::value_type String;
+ typedef typename String::value_type Char;
+ typedef std::basic_ostringstream<Char> OStringStream;
+
+public:
+ explicit set_args_(const Range &args)
+ {
+ ConstIterator it = boost::const_begin(args);
+ ConstIterator end = boost::const_end(args);
+ if (it != end)
+ {
+ exe_ = *it;
+ OStringStream os;
+ for (; it != end; ++it)
+ {
+ if (boost::algorithm::contains(*it,
+ String(1, static_cast<Char>(' '))))
+ {
+ os << static_cast<Char>('"') << *it <<
+ static_cast<Char>('"');
+ }
+ else
+ {
+ os << *it;
+ }
+ os << static_cast<Char>(' ');
+ }
+ String s = os.str();
+ cmd_line_.reset(new Char[s.size() + 1]);
+ boost::copy(s, cmd_line_.get());
+ cmd_line_[s.size()] = 0;
+ }
+ else
+ {
+ cmd_line_.reset(new Char[1]());
+ }
+ }
+
+ template <class WindowsExecutor>
+ void on_CreateProcess_setup(WindowsExecutor &e) const
+ {
+ e.cmd_line = cmd_line_.get();
+ if (!e.exe && !exe_.empty())
+ e.exe = exe_.c_str();
+ }
+
+private:
+ boost::shared_array<Char> cmd_line_;
+ String exe_;
+};
+
+template <class Range>
+set_args_<Range> set_args(const Range &range)
+{
+ return set_args_<Range>(range);
+}
+
+}}}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/set_cmd_line.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/set_cmd_line.hpp
new file mode 100644
index 0000000000..a3d9f6f761
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/set_cmd_line.hpp
@@ -0,0 +1,68 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_SET_CMD_LINE_HPP
+#define BOOST_PROCESS_WINDOWS_INITIALIZERS_SET_CMD_LINE_HPP
+
+#include <boost/process/windows/initializers/initializer_base.hpp>
+#include <boost/range/algorithm/copy.hpp>
+#include <boost/shared_array.hpp>
+#include <memory>
+
+namespace boost { namespace process { namespace windows { namespace initializers {
+
+template <class String>
+class set_cmd_line_ : public initializer_base
+{
+private:
+ typedef typename String::value_type Char;
+
+public:
+ explicit set_cmd_line_(const String &s)
+ : cmd_line_(new Char[s.size() + 1])
+ {
+ boost::copy(s, cmd_line_.get());
+ cmd_line_[s.size()] = 0;
+ }
+
+ template <class WindowsExecutor>
+ void on_CreateProcess_setup(WindowsExecutor &e) const
+ {
+ e.cmd_line = cmd_line_.get();
+ }
+
+private:
+ boost::shared_array<Char> cmd_line_;
+};
+
+#if defined(_UNICODE) || defined(UNICODE)
+inline set_cmd_line_<std::wstring> set_cmd_line(const wchar_t *ws)
+{
+ return set_cmd_line_<std::wstring>(ws);
+}
+
+inline set_cmd_line_<std::wstring> set_cmd_line(const std::wstring &ws)
+{
+ return set_cmd_line_<std::wstring>(ws);
+}
+#else
+inline set_cmd_line_<std::string> set_cmd_line(const char *s)
+{
+ return set_cmd_line_<std::string>(s);
+}
+
+inline set_cmd_line_<std::string> set_cmd_line(const std::string &s)
+{
+ return set_cmd_line_<std::string>(s);
+}
+#endif
+
+}}}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/set_env.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/set_env.hpp
new file mode 100644
index 0000000000..6dfdfc58a4
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/set_env.hpp
@@ -0,0 +1,88 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_SET_ENV_HPP
+#define BOOST_PROCESS_WINDOWS_INITIALIZERS_SET_ENV_HPP
+
+#include <Windows.h>
+#include <boost/process/windows/initializers/initializer_base.hpp>
+#include <boost/range/numeric.hpp>
+#include <boost/range/algorithm/copy.hpp>
+#include <boost/range/algorithm/for_each.hpp>
+#include <boost/shared_array.hpp>
+#include <iterator>
+#include <cstddef>
+
+namespace boost { namespace process { namespace windows { namespace initializers {
+
+template <class Range, bool Unicode>
+class set_env_ : public initializer_base
+{
+private:
+ typedef typename Range::value_type String;
+ typedef typename String::value_type Char;
+
+ static std::size_t add_size(std::size_t size, const String &s)
+ {
+ return size + s.size() + 1u;
+ }
+
+ struct copy
+ {
+ Char *it_;
+
+ copy(Char *it) : it_(it) {}
+
+ void operator()(const String &s)
+ {
+ it_ = boost::copy(s, it_);
+ *it_ = 0;
+ ++it_;
+ }
+ };
+
+public:
+ set_env_(const Range &envs)
+ : size_(boost::accumulate(envs, 0, add_size) + 1),
+ env_(new Char[size_])
+ {
+ boost::for_each(envs, copy(env_.get()));
+ env_[size_ - 1] = 0;
+ }
+
+ template <class WindowsExecutor>
+ void on_CreateProcess_setup(WindowsExecutor &e) const
+ {
+ e.env = env_.get();
+ if (Unicode)
+ e.creation_flags |= CREATE_UNICODE_ENVIRONMENT;
+ }
+
+private:
+ std::size_t size_;
+ boost::shared_array<Char> env_;
+};
+
+#if defined(_UNICODE) || defined(UNICODE)
+template <class Range>
+set_env_<Range, true> set_env(const Range &envs)
+{
+ return set_env_<Range, true>(envs);
+}
+#else
+template <class Range>
+set_env_<Range, false> set_env(const Range &envs)
+{
+ return set_env_<Range, false>(envs);
+}
+#endif
+
+}}}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/set_on_error.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/set_on_error.hpp
new file mode 100644
index 0000000000..695ea5904d
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/set_on_error.hpp
@@ -0,0 +1,36 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_SET_ON_ERROR_HPP
+#define BOOST_PROCESS_WINDOWS_INITIALIZERS_SET_ON_ERROR_HPP
+
+#include <boost/process/config.hpp>
+#include <boost/process/windows/initializers/initializer_base.hpp>
+#include <boost/system/error_code.hpp>
+
+namespace boost { namespace process { namespace windows { namespace initializers {
+
+class set_on_error : public initializer_base
+{
+public:
+ explicit set_on_error(boost::system::error_code &ec) : ec_(ec) {}
+
+ template <class WindowsExecutor>
+ void on_CreateProcess_error(WindowsExecutor&) const
+ {
+ BOOST_PROCESS_RETURN_LAST_SYSTEM_ERROR(ec_);
+ }
+
+private:
+ boost::system::error_code &ec_;
+};
+
+}}}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/show_window.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/show_window.hpp
new file mode 100644
index 0000000000..3046179205
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/show_window.hpp
@@ -0,0 +1,36 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_SHOW_WINDOW_HPP
+#define BOOST_PROCESS_WINDOWS_INITIALIZERS_SHOW_WINDOW_HPP
+
+#include <boost/process/windows/initializers/initializer_base.hpp>
+#include <Windows.h>
+
+namespace boost { namespace process { namespace windows { namespace initializers {
+
+class show_window : public initializer_base
+{
+public:
+ explicit show_window(WORD flags) : flags_(flags) {}
+
+ template <class WindowsExecutor>
+ void on_CreateProcess_setup(WindowsExecutor &e) const
+ {
+ e.startup_info.dwFlags |= STARTF_USESHOWWINDOW;
+ e.startup_info.wShowWindow |= flags_;
+ }
+
+private:
+ WORD flags_;
+};
+
+}}}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/start_in_dir.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/start_in_dir.hpp
new file mode 100644
index 0000000000..8dc952abcc
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/start_in_dir.hpp
@@ -0,0 +1,69 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_START_IN_DIR_HPP
+#define BOOST_PROCESS_WINDOWS_INITIALIZERS_START_IN_DIR_HPP
+
+#include <boost/process/windows/initializers/initializer_base.hpp>
+#include <boost/filesystem/path.hpp>
+#include <string>
+
+namespace boost { namespace process { namespace windows { namespace initializers {
+
+template <class String>
+class start_in_dir_ : public initializer_base
+{
+public:
+ explicit start_in_dir_(const String &s) : s_(s) {}
+
+ template <class WindowsExecutor>
+ void on_CreateProcess_setup(WindowsExecutor &e) const
+ {
+ e.work_dir = s_.c_str();
+ }
+
+private:
+ String s_;
+};
+
+#if defined(_UNICODE) || defined(UNICODE)
+inline start_in_dir_<std::wstring> start_in_dir(const wchar_t *ws)
+{
+ return start_in_dir_<std::wstring>(ws);
+}
+
+inline start_in_dir_<std::wstring> start_in_dir(const std::wstring &ws)
+{
+ return start_in_dir_<std::wstring>(ws);
+}
+
+inline start_in_dir_<std::wstring> start_in_dir(const boost::filesystem::path &p)
+{
+ return start_in_dir_<std::wstring>(p.wstring());
+}
+#else
+inline start_in_dir_<std::string> start_in_dir(const char *s)
+{
+ return start_in_dir_<std::string>(s);
+}
+
+inline start_in_dir_<std::string> start_in_dir(const std::string &s)
+{
+ return start_in_dir_<std::string>(s);
+}
+
+inline start_in_dir_<std::string> start_in_dir(const boost::filesystem::path &p)
+{
+ return start_in_dir_<std::string>(p.string());
+}
+#endif
+
+}}}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/throw_on_error.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/throw_on_error.hpp
new file mode 100644
index 0000000000..044fa00417
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/throw_on_error.hpp
@@ -0,0 +1,30 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_THROW_ON_ERROR_HPP
+#define BOOST_PROCESS_WINDOWS_INITIALIZERS_THROW_ON_ERROR_HPP
+
+#include <boost/process/config.hpp>
+#include <boost/process/windows/initializers/initializer_base.hpp>
+
+namespace boost { namespace process { namespace windows { namespace initializers {
+
+class throw_on_error : public initializer_base
+{
+public:
+ template <class WindowsExecutor>
+ void on_CreateProcess_error(WindowsExecutor&) const
+ {
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateProcess() failed");
+ }
+};
+
+}}}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/pipe.hpp b/plugins/New_GPG/src/include/boost/process/windows/pipe.hpp
new file mode 100644
index 0000000000..fd912afcc9
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/pipe.hpp
@@ -0,0 +1,32 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_PIPE_HPP
+#define BOOST_PROCESS_WINDOWS_PIPE_HPP
+
+#include <Windows.h>
+
+namespace boost { namespace process { namespace windows {
+
+struct pipe
+{
+ HANDLE source;
+ HANDLE sink;
+
+ pipe(HANDLE source, HANDLE sink) : source(source), sink(sink) {}
+};
+
+inline pipe make_pipe(HANDLE source, HANDLE sink)
+{
+ return pipe(source, sink);
+}
+
+}}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/search_path.hpp b/plugins/New_GPG/src/include/boost/process/windows/search_path.hpp
new file mode 100644
index 0000000000..ceb9c6f7c2
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/search_path.hpp
@@ -0,0 +1,104 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_SEARCH_PATH_HPP
+#define BOOST_PROCESS_WINDOWS_SEARCH_PATH_HPP
+
+#include <boost/process/config.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/tokenizer.hpp>
+#include <boost/array.hpp>
+#include <boost/system/error_code.hpp>
+#include <string>
+#include <stdexcept>
+#include <stdlib.h>
+#include <Shellapi.h>
+
+namespace boost { namespace process { namespace windows {
+
+#if defined(_UNICODE) || defined(UNICODE)
+inline std::wstring search_path(const std::wstring &filename,
+ std::wstring path = L"")
+{
+ if (path.empty())
+ {
+ path = ::_wgetenv(L"PATH");
+ if (path.empty())
+ BOOST_PROCESS_THROW(std::runtime_error(
+ "Environment variable PATH not found"));
+ }
+
+ typedef boost::tokenizer<boost::char_separator<wchar_t>,
+ std::wstring::const_iterator, std::wstring> tokenizer;
+ boost::char_separator<wchar_t> sep(L";");
+ tokenizer tok(path, sep);
+ for (tokenizer::iterator it = tok.begin(); it != tok.end(); ++it)
+ {
+ boost::filesystem::path p = *it;
+ p /= filename;
+ boost::array<std::string, 4> extensions =
+ { "", ".exe", ".com", ".bat" };
+ for (boost::array<std::string, 4>::iterator it2 = extensions.begin();
+ it2 != extensions.end(); ++it2)
+ {
+ boost::filesystem::path p2 = p;
+ p2 /= (std::string)*it2;
+ boost::system::error_code ec;
+ bool file = boost::filesystem::is_regular_file(p2, ec);
+ if (!ec && file &&
+ SHGetFileInfoW(p2.c_str(), 0, 0, 0, SHGFI_EXETYPE))
+ {
+ return p2.wstring();
+ }
+ }
+ }
+ return L"";
+}
+#else
+inline std::string search_path(const std::string &filename,
+ std::string path = "")
+{
+ if (path.empty())
+ {
+ path = ::getenv("PATH");
+ if (path.empty())
+ BOOST_PROCESS_THROW(std::runtime_error(
+ "Environment variable PATH not found"));
+ }
+
+ typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+ boost::char_separator<char> sep(";");
+ tokenizer tok(path, sep);
+ for (tokenizer::iterator it = tok.begin(); it != tok.end(); ++it)
+ {
+ boost::filesystem::path p = *it;
+ p /= filename;
+ boost::array<std::string, 4> extensions =
+ { "", ".exe", ".com", ".bat" };
+ for (boost::array<std::string, 4>::iterator it2 = extensions.begin();
+ it2 != extensions.end(); ++it2)
+ {
+ boost::filesystem::path p2 = p;
+ p2 += *it2;
+ boost::system::error_code ec;
+ bool file = boost::filesystem::is_regular_file(p2, ec);
+ if (!ec && file &&
+ SHGetFileInfoA(p2.string().c_str(), 0, 0, 0, SHGFI_EXETYPE))
+ {
+ return p2.string();
+ }
+ }
+ }
+ return "";
+}
+#endif
+
+}}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/shell_path.hpp b/plugins/New_GPG/src/include/boost/process/windows/shell_path.hpp
new file mode 100644
index 0000000000..ace15b96e1
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/shell_path.hpp
@@ -0,0 +1,50 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_SHELL_PATH_HPP
+#define BOOST_PROCESS_WINDOWS_SHELL_PATH_HPP
+
+#include <boost/process/config.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/filesystem/path.hpp>
+#include <Windows.h>
+
+namespace boost { namespace process { namespace windows {
+
+inline boost::filesystem::path shell_path()
+{
+ TCHAR sysdir[MAX_PATH];
+ UINT size = ::GetSystemDirectory(sysdir, sizeof(sysdir));
+ if (!size)
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("GetSystemDirectory() failed");
+ boost::filesystem::path p = sysdir;
+ return p / "cmd.exe";
+}
+
+inline boost::filesystem::path shell_path(boost::system::error_code &ec)
+{
+ TCHAR sysdir[MAX_PATH];
+ UINT size = ::GetSystemDirectory(sysdir, sizeof(sysdir));
+ boost::filesystem::path p;
+ if (!size)
+ {
+ BOOST_PROCESS_RETURN_LAST_SYSTEM_ERROR(ec);
+ }
+ else
+ {
+ ec.clear();
+ p = sysdir;
+ p /= "cmd.exe";
+ }
+ return p;
+}
+
+}}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/terminate.hpp b/plugins/New_GPG/src/include/boost/process/windows/terminate.hpp
new file mode 100644
index 0000000000..43afe250a6
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/terminate.hpp
@@ -0,0 +1,38 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_TERMINATE_HPP
+#define BOOST_PROCESS_WINDOWS_TERMINATE_HPP
+
+#include <boost/process/config.hpp>
+#include <boost/system/error_code.hpp>
+#include <cstdlib>
+#include <Windows.h>
+
+namespace boost { namespace process { namespace windows {
+
+template <class Process>
+void terminate(const Process &p)
+{
+ if (!::TerminateProcess(p.process_handle(), EXIT_FAILURE))
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("TerminateProcess() failed");
+}
+
+template <class Process>
+void terminate(const Process &p, boost::system::error_code &ec)
+{
+ if (!::TerminateProcess(p.process_handle(), EXIT_FAILURE))
+ BOOST_PROCESS_RETURN_LAST_SYSTEM_ERROR(ec);
+ else
+ ec.clear();
+}
+
+}}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/boost/process/windows/wait_for_exit.hpp b/plugins/New_GPG/src/include/boost/process/windows/wait_for_exit.hpp
new file mode 100644
index 0000000000..23a8b9a9f1
--- /dev/null
+++ b/plugins/New_GPG/src/include/boost/process/windows/wait_for_exit.hpp
@@ -0,0 +1,49 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_WAIT_FOR_EXIT_HPP
+#define BOOST_PROCESS_WINDOWS_WAIT_FOR_EXIT_HPP
+
+#include <boost/process/config.hpp>
+#include <boost/system/error_code.hpp>
+#include <Windows.h>
+
+namespace boost { namespace process { namespace windows {
+
+template <class Process>
+inline DWORD wait_for_exit(const Process &p)
+{
+ if (::WaitForSingleObject(p.process_handle(), INFINITE) == WAIT_FAILED)
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("WaitForSingleObject() failed");
+
+ DWORD exit_code;
+ if (!::GetExitCodeProcess(p.process_handle(), &exit_code))
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("GetExitCodeProcess() failed");
+
+ return exit_code;
+}
+
+template <class Process>
+inline DWORD wait_for_exit(const Process &p, boost::system::error_code &ec)
+{
+ DWORD exit_code = 1;
+
+ if (::WaitForSingleObject(p.process_handle(), INFINITE) == WAIT_FAILED)
+ BOOST_PROCESS_RETURN_LAST_SYSTEM_ERROR(ec);
+ else if (!::GetExitCodeProcess(p.process_handle(), &exit_code))
+ BOOST_PROCESS_RETURN_LAST_SYSTEM_ERROR(ec);
+ else
+ ec.clear();
+
+ return exit_code;
+}
+
+}}}
+
+#endif
diff --git a/plugins/New_GPG/src/include/utf8.h b/plugins/New_GPG/src/include/utf8.h
new file mode 100644
index 0000000000..4e4451403f
--- /dev/null
+++ b/plugins/New_GPG/src/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/src/include/utf8/checked.h b/plugins/New_GPG/src/include/utf8/checked.h
new file mode 100644
index 0000000000..3b00644444
--- /dev/null
+++ b/plugins/New_GPG/src/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/src/include/utf8/core.h b/plugins/New_GPG/src/include/utf8/core.h
new file mode 100644
index 0000000000..693d388c07
--- /dev/null
+++ b/plugins/New_GPG/src/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/src/include/utf8/unchecked.h b/plugins/New_GPG/src/include/utf8/unchecked.h
new file mode 100644
index 0000000000..b4547fad94
--- /dev/null
+++ b/plugins/New_GPG/src/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/src/init.cpp b/plugins/New_GPG/src/init.cpp
new file mode 100644
index 0000000000..b0a2232cce
--- /dev/null
+++ b/plugins/New_GPG/src/init.cpp
@@ -0,0 +1,251 @@
+// 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, bSameAction = false, bAutoExchange = false, bStripTags = false, tabsrmm_used = false;
+TCHAR *inopentag = NULL, *inclosetag = NULL, *outopentag = NULL, *outclosetag = NULL, *password = NULL;
+
+list <JabberAccount*> Accounts;
+
+HINSTANCE hInst;
+HFONT bold_font = NULL;
+HANDLE hLoadPubKey = NULL, g_hCLIcon = NULL, hExportGpgKeys = NULL, hImportGpgKeys = NULL;
+HGENMENU hSendKey = NULL, hToggleEncryption = NULL;
+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;
+
+PLUGININFOEX pluginInfo={
+ sizeof(PLUGININFOEX),
+ __PLUGIN_NAME,
+ PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
+ __DESCRIPTION,
+ __AUTHOR,
+ __AUTHOREMAIL,
+ __COPYRIGHT,
+ __AUTHORWEB,
+ UNICODE_AWARE,
+ // {4227c050-8d97-48d2-91ec-6a952b3dab94}
+ { 0x4227c050, 0x8d97, 0x48d2, { 0x91, 0xec, 0x6a, 0x95, 0x2b, 0x3d, 0xab, 0x94 } }
+};
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ hInst = hinstDLL;
+ return TRUE;
+}
+
+
+extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ return &pluginInfo;
+}
+
+
+INT_PTR LoadKey(WPARAM w, LPARAM l);
+INT_PTR ToggleEncryption(WPARAM w, LPARAM l);
+INT_PTR SendKey(WPARAM w, LPARAM l);
+INT_PTR ExportGpGKeys(WPARAM w, LPARAM l);
+INT_PTR ImportGpGKeys(WPARAM w, LPARAM l);
+
+void init_vars()
+{
+ bAppendTags = db_get_b(NULL, szGPGModuleName, "bAppendTags", 0) != 0;
+ bStripTags = db_get_b(NULL, szGPGModuleName, "bStripTags", 0) != 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 = db_get_b(NULL, szGPGModuleName, "bDebugLog", 0) != 0;
+ bAutoExchange = db_get_b(NULL, szGPGModuleName, "bAutoExchange", 0) != 0;
+ bSameAction = db_get_b(NULL, szGPGModuleName, "bSameAction", 0) != 0;
+ password = UniGetContactSettingUtf(NULL, szGPGModuleName, "szKeyPassword", _T(""));
+ debuglog.init();
+ bIsMiranda09 = (DWORD)CallService(MS_SYSTEM_GETVERSION, 0, 0) >= 0x00090001;
+ bJabberAPI = db_get_b(NULL, szGPGModuleName, "bJabberAPI", bIsMiranda09) != 0;
+ bPresenceSigning = db_get_b(NULL, szGPGModuleName, "bPresenceSigning", 0) != 0;
+ bFileTransfers = db_get_b(NULL, szGPGModuleName, "bFileTransfers", 0) != 0;
+ firstrun_rect.left = db_get_dw(NULL, szGPGModuleName, "FirstrunWindowX", 0);
+ firstrun_rect.top = db_get_dw(NULL, szGPGModuleName, "FirstrunWindowY", 0);
+ key_password_rect.left = db_get_dw(NULL, szGPGModuleName, "PasswordWindowX", 0);
+ key_password_rect.top = db_get_dw(NULL, szGPGModuleName, "PasswordWindowY", 0);
+ key_gen_rect.left = db_get_dw(NULL, szGPGModuleName, "KeyGenWindowX", 0);
+ key_gen_rect.top = db_get_dw(NULL, szGPGModuleName, "KeyGenWindowY", 0);
+ load_key_rect.left = db_get_dw(NULL, szGPGModuleName, "LoadKeyWindowX", 0);
+ load_key_rect.top = db_get_dw(NULL, szGPGModuleName, "LoadKeyWindowY", 0);
+ import_key_rect.left = db_get_dw(NULL, szGPGModuleName, "ImportKeyWindowX", 0);
+ import_key_rect.top = db_get_dw(NULL, szGPGModuleName, "ImportKeyWindowY", 0);
+ new_key_rect.left = db_get_dw(NULL, szGPGModuleName, "NewKeyWindowX", 0);
+ new_key_rect.top = db_get_dw(NULL, szGPGModuleName, "NewKeyWindowY", 0);
+ load_existing_key_rect.left = db_get_dw(NULL, szGPGModuleName, "LoadExistingKeyWindowX", 0);
+ load_existing_key_rect.top = db_get_dw(NULL, szGPGModuleName, "LoadExistingKeyWindowY", 0);
+ tabsrmm_used = isTabsrmmUsed();
+ bold_font = CreateFont(14, 0, 0, 0, 600, 0, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, _T("Arial"));
+}
+
+static int OnModulesLoaded(WPARAM wParam,LPARAM lParam)
+{
+ int GpgOptInit(WPARAM wParam,LPARAM lParam);
+ int OnPreBuildContactMenu(WPARAM w, LPARAM l);
+ INT_PTR RecvMsgSvc(WPARAM w, LPARAM l);
+ INT_PTR 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_PTR onSendFile(WPARAM, LPARAM);
+ void InitIconLib();
+
+ void InitCheck();
+ void FirstRun();
+ FirstRun();
+ if(!db_get_b(NULL, szGPGModuleName, "FirstRun", 1))
+ InitCheck();
+ InitIconLib();
+
+ HICON IconLibGetIcon(const char* ident);
+
+ StatusIconData sid = { sizeof(sid) };
+ sid.szModule = szGPGModuleName;
+ sid.flags = MBF_HIDDEN;
+ sid.dwId = 0x00000001;
+ sid.hIcon = IconLibGetIcon("secured");
+ sid.szTooltip = LPGEN("GPG Turn off encryption");
+ Srmm_AddIcon(&sid);
+
+ sid.dwId = 0x00000002;
+ sid.hIcon = IconLibGetIcon("unsecured");
+ sid.szTooltip = LPGEN("GPG Turn on encryption");
+ Srmm_AddIcon(&sid);
+
+ bMetaContacts = ServiceExists(MS_MC_GETMETACONTACT) != 0;
+
+ 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);
+
+ HookEvent(ME_CLIST_PREBUILDCONTACTMENU, OnPreBuildContactMenu);
+
+ HookEvent(ME_MSG_WINDOWEVENT, onWindowEvent);
+ HookEvent(ME_MSG_ICONPRESSED, onIconPressed);
+
+ g_hCLIcon = ExtraIcon_Register(szGPGModuleName, Translate("GPG encryption status"), "secured", (MIRANDAHOOK)onExtraImageListRebuilding, (MIRANDAHOOK)onExtraImageApplying);
+
+ PROTOCOLDESCRIPTOR pd = { sizeof(pd) };
+ pd.szName = szGPGModuleName;
+ pd.type = PROTOTYPE_ENCRYPTION;
+ CallService(MS_PROTO_REGISTERMODULE,0,(LPARAM)&pd);
+
+ CreateProtoServiceFunction(szGPGModuleName, PSR_MESSAGE, RecvMsgSvc);
+ CreateProtoServiceFunction(szGPGModuleName, PSS_MESSAGE, SendMsgSvc);
+ CreateProtoServiceFunction(szGPGModuleName, PSS_FILE, onSendFile);
+ clean_temp_dir();
+ return 0;
+}
+
+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",LoadKey);
+ CreateServiceFunction("/ToggleEncryption",ToggleEncryption);
+ CreateServiceFunction("/SendKey",SendKey);
+ CreateServiceFunction("/ExportGPGKeys",ExportGpGKeys);
+ CreateServiceFunction("/ImportGPGKeys",ImportGpGKeys);
+
+ // !!!!!!!! check it later
+ CLISTMENUITEM mi = { sizeof(mi) };
+ mi.position=-0x7FFFFFFF;
+ mi.flags=CMIF_TCHAR;
+ mi.hIcon=LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);
+ mi.ptszName=LPGENT("Load GPG public key");
+ mi.pszService="/LoadPubKey";
+ hLoadPubKey = Menu_AddContactMenuItem(&mi);
+
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize=sizeof(mi);
+ mi.position=-0x7FFFFFFe;
+ mi.flags=CMIF_TCHAR;
+ mi.hIcon=LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);
+ mi.ptszName=LPGENT("Toggle GPG encryption");
+ mi.pszService="/ToggleEncryption";
+ hToggleEncryption = Menu_AddContactMenuItem(&mi);
+
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize=sizeof(mi);
+ mi.position=-0x7FFFFFFd;
+ mi.flags=CMIF_TCHAR;
+ mi.hIcon=LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);
+ mi.ptszName=LPGENT("Send public key");
+ mi.pszService="/SendKey";
+ hSendKey = Menu_AddContactMenuItem(&mi);
+
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize=sizeof(mi);
+ mi.position=-0x7FFFFFFe;
+ mi.flags=CMIF_TCHAR;
+ mi.hIcon=LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);
+ mi.ptszName=LPGENT("Export GPG Public keys");
+ mi.pszService="/ExportGPGKeys";
+ hExportGpgKeys = Menu_AddMainMenuItem(&mi);
+
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize=sizeof(mi);
+ mi.position=-0x7FFFFFFF;
+ mi.flags=CMIF_TCHAR;
+ mi.hIcon=LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);
+ mi.ptszName=LPGENT("Import GPG Public keys");
+ mi.pszService="/ImportGPGKeys";
+ hImportGpgKeys = Menu_AddMainMenuItem(&mi);
+
+ return 0;
+}
+
+extern list<wstring> transfers;
+extern "C" int __declspec(dllexport) Unload(void)
+{
+ if(!transfers.empty())
+ {
+ for(list<wstring>::iterator p = transfers.begin(); p != transfers.end(); p++)
+ if(!(*p).empty())
+ boost::filesystem::remove((*p));
+ }
+ mir_free(inopentag);
+ mir_free(inclosetag);
+ mir_free(outopentag);
+ mir_free(outclosetag);
+ if(password)
+ mir_free(password);
+ clean_temp_dir();
+ return 0;
+}
diff --git a/plugins/New_GPG/src/jabber_account.cpp b/plugins/New_GPG/src/jabber_account.cpp
new file mode 100644
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 100644
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 100644
index 0000000000..29f80a1d5e
--- /dev/null
+++ b/plugins/New_GPG/src/log.cpp
@@ -0,0 +1,87 @@
+// 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)
+{
+ if(_bDebugLog != bDebugLog)
+ init();
+ log_mutex.lock();
+ log.open(toUTF8(path).c_str(), std::ios::app |std::ios::ate);
+ log<<toUTF8(buf);
+ log<<"\n";
+ log.close();
+ log_mutex.unlock();
+ return *this;
+}
+logtofile& logtofile::operator<<(char *buf)
+{
+ if(_bDebugLog != bDebugLog)
+ init();
+ log_mutex.lock();
+ log.open(toUTF8(path).c_str(), std::ios::app |std::ios::ate);
+ log<<buf;
+ log<<"\n";
+ log.close();
+ log_mutex.unlock();
+ return *this;
+}
+logtofile& logtofile::operator<<(string buf)
+{
+ if(_bDebugLog != bDebugLog)
+ init();
+ 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<<"\n";
+ log.close();
+ log_mutex.unlock();
+ mir_free(tmp);
+ return *this;
+}
+logtofile& logtofile::operator<<(wstring buf)
+{
+ if(_bDebugLog != bDebugLog)
+ init();
+ log_mutex.lock();
+ log.open(toUTF8(path).c_str(), std::ios::app |std::ios::ate);
+ log<<toUTF8(buf);
+ log<<"\n";
+ log.close();
+ log_mutex.unlock();
+ return *this;
+}
+void logtofile::init()
+{
+ if(bDebugLog)
+ {
+ if(path)
+ mir_free(path);
+ path = UniGetContactSettingUtf(NULL, szGPGModuleName, "szLogFilePath", _T("C:\\GPGdebug.log"));
+ }
+ _bDebugLog = bDebugLog;
+}
+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 100644
index 0000000000..9d1dcb39e6
--- /dev/null
+++ b/plugins/New_GPG/src/log.h
@@ -0,0 +1,36 @@
+// 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;
+ bool _bDebugLog;
+};
+
+#endif
diff --git a/plugins/New_GPG/src/main.cpp b/plugins/New_GPG/src/main.cpp
new file mode 100644
index 0000000000..072b64a26e
--- /dev/null
+++ b/plugins/New_GPG/src/main.cpp
@@ -0,0 +1,2611 @@
+// 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);
+
+TCHAR key_id_global[17] = {0};
+
+static INT_PTR 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, TranslateT("Set own key"));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_COPY_PUBKEY), 0);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_EXPORT_PRIVATE), 0);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHANGE_PASSWD), 0);
+ 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 = TranslateT("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 = TranslateT("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 = TranslateT("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 = TranslateT("Expire 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 = TranslateT("Key length");
+ col.mask = LVCF_TEXT | LVCF_WIDTH;
+ col.fmt = LVCFMT_LEFT;
+ col.cx = 30;
+ ListView_InsertColumn(hwndList, 5, &col);
+ ZeroMemory(&col,sizeof(col));
+ col.pszText = TranslateT("Accounts");
+ col.mask = LVCF_TEXT | LVCF_WIDTH;
+ col.fmt = LVCFMT_LEFT;
+ col.cx = 30;
+ ListView_InsertColumn(hwndList, 6, &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;
+ {
+ std::vector<wstring> cmd;
+ cmd.push_back(L"--batch");
+ cmd.push_back(L"--list-secret-keys");
+ gpg_execution_params params(cmd);
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ if(!gpg_launcher(params))
+ {
+ 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 *key_len = mir_wstrdup(toUTF16(out.substr(p,p2-p)).c_str()), *creation_date = NULL, *expire_date = NULL;
+ p2+=2;
+ p = out.find(" ", p2);
+ std::wstring key_id = toUTF16(out.substr(p2,p-p2));
+ p += 1;
+ p2 = out.find(" ", p);
+ std::string::size_type p3 = out.find("\n", p);
+ if((p2 != std::string::npos) && (p3 < p2))
+ {
+ p2 = p3;
+ creation_date = mir_wstrdup(toUTF16(out.substr(p,p2-p-1)).c_str());
+ }
+ else
+ {
+ creation_date = mir_wstrdup(toUTF16(out.substr(p,p2-p)).c_str());
+ p2 = out.find("[", p2);
+ p2 = out.find("expires:", p2);
+ p2 += strlen("expires:");
+ if(p2 != std::string::npos)
+ {
+ p2++;
+ p = p2;
+ p2 = out.find("]", p);
+ expire_date = mir_wstrdup(toUTF16(out.substr(p,p2-p)).c_str());
+ //check expiration
+ bool expired = false;
+ {
+ boost::posix_time::ptime now = boost::posix_time::second_clock::local_time();
+ TCHAR buf[5];
+ mir_sntprintf(buf, 5, _T("%s"), expire_date);
+ int year = _ttoi(buf);
+ if(year < now.date().year())
+ expired = true;
+ else if(year == now.date().year())
+ {
+ mir_sntprintf(buf, 3, _T("%s"), expire_date+5);
+ int month = _ttoi(buf);
+ if(month < now.date().month())
+ expired = true;
+ else if(month == now.date().month())
+ {
+ mir_sntprintf(buf, 3, _T("%s"), expire_date+8);
+ unsigned day = _ttoi(buf);
+ if(day <= now.date().day_number())
+ expired = true;
+ }
+ }
+ }
+ if(expired)
+ {
+ mir_free(key_len);
+ mir_free(creation_date);
+ mir_free(expire_date);
+ //mimic normal behaviour
+ p = out.find("uid ", p);
+ p2 = out.find_first_not_of(" ", p+5);
+ p = out.find("<", p2);
+ p++;
+ p2 = out.find(">", p);
+ //
+ continue; //does not add to key list
+ }
+ }
+ }
+ iRow = ListView_InsertItem(hwndList, &item);
+ ListView_SetItemText(hwndList, iRow, 3, creation_date);
+ mir_free(creation_date);
+ if(expire_date)
+ {
+ ListView_SetItemText(hwndList, iRow, 4, expire_date);
+ mir_free(expire_date);
+ }
+ ListView_SetItemText(hwndList, iRow, 5, key_len);
+ mir_free(key_len);
+ ListView_SetItemText(hwndList, iRow, 0, (TCHAR*)key_id.c_str());
+ p = out.find("uid ", p);
+ p2 = out.find_first_not_of(" ", p+5);
+ p = out.find("<", p2);
+ TCHAR *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);
+ { //get accounts
+ int count = 0;
+ PROTOACCOUNT **accounts;
+ ProtoEnumAccounts(&count, &accounts);
+ std::wstring accs;
+ for(int i = 0; i < count; i++)
+ {
+ std::string setting = toUTF8(accounts[i]->tszAccountName);
+ setting += "(";
+ setting += accounts[i]->szModuleName;
+ setting += ")" ;
+ setting += "_KeyID";
+ TCHAR *str = UniGetContactSettingUtf(NULL, szGPGModuleName, setting.c_str(), _T(""));
+ if(key_id == str)
+ {
+ if(accs.empty())
+ accs += accounts[i]->tszAccountName;
+ else
+ {
+ accs += _T(",");
+ accs += accounts[i]->tszAccountName;
+ }
+ }
+ }
+ ListView_SetItemText(hwndList, iRow, 6, (TCHAR*)accs.c_str());
+ }
+ i++;
+ }
+ ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE);
+ 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);
+ ListView_SetColumnWidth(hwndList, 6, LVSCW_AUTOSIZE);
+ }
+ }
+ {
+ 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;
+ std::string acc = toUTF8(accounts[i]->tszAccountName);
+ acc += "(";
+ acc += accounts[i]->szModuleName;
+ acc += ")";
+ //acc += "_KeyID";
+ SendMessageA(GetDlgItem(hwndDlg, IDC_ACCOUNT), CB_ADDSTRING, 0, (LPARAM)acc.c_str());
+ }
+ 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;
+ std::vector<wstring> cmd;
+ cmd.push_back(L"--batch");
+ cmd.push_back(L"-a");
+ cmd.push_back(L"--export");
+ cmd.push_back(fp);
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ if(!gpg_launcher(params))
+ {
+ break;
+ }
+ if(result == pxNotFound)
+ break;
+ string::size_type s = 0;
+ boost::algorithm::erase_all(out, "\r");
+ {
+ char buf[64];
+ GetDlgItemTextA(hwndDlg, IDC_ACCOUNT, buf, 63);
+ if(!strcmp(buf, Translate("Default")))
+ {
+ db_set_s(NULL, szGPGModuleName, "GPGPubKey", out.c_str());
+ db_set_ts(NULL, szGPGModuleName, "KeyMainName", name);
+ db_set_ts(NULL, szGPGModuleName, "KeyID", fp);
+ }
+ else
+ {
+ std::string acc_str = buf;
+ acc_str += "_GPGPubKey";
+ db_set_s(NULL, szGPGModuleName, acc_str.c_str(), out.c_str());
+ acc_str = buf;
+ acc_str += "_KeyMainName";
+ db_set_ts(NULL, szGPGModuleName, acc_str.c_str(), name);
+ acc_str = buf;
+ acc_str += "_KeyID";
+ db_set_ts(NULL, szGPGModuleName, acc_str.c_str(), fp);
+ }
+ if(!strcmp(buf, Translate("Default")))
+ {
+ 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());
+ }
+ }
+ 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";
+ db_set_ts(NULL, szGPGModuleName, dbsetting.c_str(), passwd);
+ }
+ 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;
+ {
+ std::vector<wstring> cmd;
+ cmd.push_back(L"--batch");
+ cmd.push_back(L"--list-secret-keys");
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ if(!gpg_launcher(params))
+ {
+ 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;
+ std::vector<wstring> cmd;
+ cmd.push_back(L"--batch");
+ cmd.push_back(L"--fingerprint");
+ cmd.push_back(fp);
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ if(!gpg_launcher(params))
+ {
+ 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.push_back(L"--batch");
+ cmd.push_back(L"--delete-secret-and-public-key");
+ cmd.push_back(L"--fingerprint");
+ cmd.push_back(fp);
+ mir_free(fp);
+ if(!gpg_launcher(params))
+ {
+ break;
+ }
+ if(result == pxNotFound)
+ break;
+ }
+ {
+ char buf[64];
+ GetDlgItemTextA(hwndDlg, IDC_ACCOUNT, buf, 63);
+ if(!strcmp(buf, Translate("Default")))
+ {
+ db_unset(NULL, szGPGModuleName, "GPGPubKey");
+ db_unset(NULL, szGPGModuleName, "KeyID");
+ db_unset(NULL, szGPGModuleName, "KeyComment");
+ db_unset(NULL, szGPGModuleName, "KeyMainName");
+ db_unset(NULL, szGPGModuleName, "KeyMainEmail");
+ db_unset(NULL, szGPGModuleName, "KeyType");
+ }
+ else
+ {
+ std::string acc_str = buf;
+ acc_str += "_GPGPubKey";
+ db_unset(NULL, szGPGModuleName, acc_str.c_str());
+ acc_str = buf;
+ acc_str += "_KeyMainName";
+ db_unset(NULL, szGPGModuleName, acc_str.c_str());
+ acc_str = buf;
+ acc_str += "_KeyID";
+ db_unset(NULL, szGPGModuleName, acc_str.c_str());
+ acc_str = buf;
+ acc_str += "_KeyComment";
+ db_unset(NULL, szGPGModuleName, acc_str.c_str());
+ acc_str = buf;
+ acc_str += "_KeyMainEmail";
+ db_unset(NULL, szGPGModuleName, acc_str.c_str());
+ acc_str = buf;
+ acc_str += "_KeyType";
+ db_unset(NULL, szGPGModuleName, acc_str.c_str());
+ }
+ }
+ 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;
+ std::vector<wstring> cmd;
+ cmd.push_back(L"--batch");
+ cmd.push_back(L"--yes");
+ cmd.push_back(L"--gen-key");
+ cmd.push_back(path);
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ extern HFONT bold_font;
+ SendMessage(GetDlgItem(hwndDlg, IDC_GENERATING_KEY), WM_SETFONT, (WPARAM)bold_font, true);
+ 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);
+ if(!gpg_launcher(params, boost::posix_time::minutes(10)))
+ {
+ break;
+ }
+ if(result == pxNotFound)
+ break;
+
+ boost::filesystem::remove(path);
+ 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;
+ std::vector<wstring> cmd;
+ cmd.push_back(L"--batch");
+ cmd.push_back(L"-a");
+ cmd.push_back(L"--export");
+ cmd.push_back(path);
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ if(!gpg_launcher(params))
+ {
+ 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")))
+ {
+ db_set_s(NULL, szGPGModuleName, "GPGPubKey", out.c_str());
+ db_set_ts(NULL, szGPGModuleName, "KeyID", fp);
+ }
+ else
+ {
+ std::string acc_str = buf;
+ acc_str += "_GPGPubKey";
+ db_set_s(NULL, szGPGModuleName, acc_str.c_str(), out.c_str());
+ acc_str = buf;
+ acc_str += "_KeyID";
+ db_set_ts(NULL, szGPGModuleName, acc_str.c_str(), 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 += ": ";
+ std::string acc_str= buf;
+ acc_str += "_KeyID";
+ char *keyid = UniGetContactSettingUtf(NULL, szGPGModuleName, acc_str.c_str(), "");
+ keyinfo += (strlen(keyid) > 0)?keyid:Translate("not set");
+ mir_free(keyid);
+ SetDlgItemTextA(hwndDlg, IDC_KEY_ID, keyinfo.c_str());
+ }
+ }
+ break;
+ case IDC_COPY_PUBKEY:
+ {
+ if(OpenClipboard(hwndDlg))
+ {
+ ListView_GetItemText(hwndList, itemnum, 0, fp, 16);
+ string out;
+ DWORD code;
+ std::vector<wstring> cmd;
+ cmd.push_back(L"--batch");
+ cmd.push_back(L"-a");
+ cmd.push_back(L"--export");
+ cmd.push_back(fp);
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ if(!gpg_launcher(params))
+ {
+ break;
+ }
+ if(result == pxNotFound)
+ break;
+ boost::algorithm::erase_all(out, "\r");
+ HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, out.size() +1);
+ if(!hMem)
+ {
+ MessageBox(0, TranslateT("Failed to alocate memory"), TranslateT("Error"), MB_OK);
+ break;
+ }
+ char *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, out.c_str(), out.size());
+ szKey[out.size()] = '\0';
+ 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();
+ }
+ }
+ break;
+ case IDC_EXPORT_PRIVATE:
+ {
+ TCHAR *p = GetFilePath(_T("Choose file to export key"), _T("*"), _T("Any file"), true);
+ if(!p || !p[0])
+ {
+ delete [] p;
+ //TODO: handle error
+ break;
+ }
+ char *path = mir_t2a(p);
+ delete [] p;
+ std::ofstream file;
+ file.open(path, std::ios::trunc | std::ios::out);
+ mir_free(path);
+ if(!file.is_open())
+ break; //TODO: handle error
+ ListView_GetItemText(hwndList, itemnum, 0, fp, 16);
+ string out;
+ DWORD code;
+ std::vector<wstring> cmd;
+ cmd.push_back(L"--batch");
+ cmd.push_back(L"-a");
+ cmd.push_back(L"--export-secret-keys");
+ cmd.push_back(fp);
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ if(!gpg_launcher(params))
+ {
+ break;
+ }
+ if(result == pxNotFound)
+ break;
+ boost::algorithm::erase_all(out, "\r");
+ file<<out;
+ if(file.is_open())
+ file.close();
+ }
+ break;
+ case IDC_CHANGE_PASSWD:
+ ListView_GetItemText(hwndList, itemnum, 0, key_id_global, 16);
+// extern void ShowChangePasswdDlg();
+// ShowChangePasswdDlg();
+ //temporary code follows
+ std::vector<std::wstring> cmd;
+ std::string old_pass, new_pass;
+ TCHAR tmp2[MAX_PATH] = {0};
+ string output;
+ DWORD exitcode;
+ cmd.push_back(L"--edit-key");
+ cmd.push_back(key_id_global);
+ cmd.push_back(L"passwd");
+ gpg_execution_params_pass params(cmd, old_pass, new_pass);
+ pxResult result;
+ params.out = &output;
+ params.code = &exitcode;
+ params.result = &result;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_passwd_change_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::minutes(10)))
+ {
+ gpg_thread.~thread();
+ if(params.child)
+ boost::process::terminate(*(params.child));
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": GPG execution timed out, aborted");
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ if(result == pxNotFound)
+ break;
+ //
+ 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);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_COPY_PUBKEY), 1);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_EXPORT_PRIVATE), 1);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHANGE_PASSWD), 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);
+ db_set_dw(NULL, szGPGModuleName, "FirstrunWindowX", firstrun_rect.left);
+ db_set_dw(NULL, szGPGModuleName, "FirstrunWindowY", firstrun_rect.top);
+ }
+ hwndFirstRun = NULL;
+ break;
+
+ }
+
+ return FALSE;
+}
+
+void ShowFirstRunDialog();
+
+static INT_PTR CALLBACK DlgProcGpgBinOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ TCHAR *tmp = NULL;
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ TCHAR *path = (TCHAR*)mir_alloc(sizeof(TCHAR) * MAX_PATH);
+ bool gpg_exists = false, lang_exists = false;
+ {
+ char *mir_path = (char*)mir_alloc(sizeof(char) * MAX_PATH);
+ PathToAbsolute("\\", 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 = (TCHAR*)mir_alloc(sizeof(TCHAR) * MAX_PATH), *gpg_lang_path = (TCHAR*)mir_alloc(sizeof(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(boost::filesystem::exists(gpg_path))
+ {
+ gpg_exists = true;
+ _tcscpy(path, _T("GnuPG\\gpg.exe"));
+ }
+ if(boost::filesystem::exists(gpg_lang_path))
+ lang_exists = true;
+ if(gpg_exists && !lang_exists)
+ 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])
+ if(!boost::filesystem::exists(tmp))
+ MessageBox(0, TranslateT("wrong gpg binary location found in system.\nplease choose another location"), TranslateT("Warning"), MB_OK);
+ }
+ else tmp = mir_wstrdup(path);
+ mir_free(path);
+
+ SetDlgItemText(hwndDlg, IDC_BIN_PATH, tmp);
+ bool bad_version = false;
+ if(gpg_exists/* && lang_exists*/)
+ {
+ db_set_ts(NULL, szGPGModuleName, "szGpgBinPath", tmp);
+ string out;
+ DWORD code;
+ std::vector<wstring> cmd;
+ cmd.push_back(L"--version");
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ gpg_valid = true;
+ gpg_launcher(params);
+ gpg_valid = false;
+ db_unset(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("Error"), 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);
+ {
+ tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T(""));
+ if(!tmp[0])
+ {
+ mir_free(tmp);
+ char *mir_path = (char*)mir_alloc(sizeof(char) * MAX_PATH);
+ PathToAbsolute("\\", mir_path);
+ strcat(mir_path, "\\gpg");
+ if(_access(mir_path, 0) != -1)
+ {
+ tmp = mir_wstrdup(toUTF16(mir_path).c_str());
+ MessageBox(0, TranslateT("found \"gpg\" directory in MIranda root.\nassuming it's gpg home directory.\ngpg home directory set."), TranslateT("Info"), MB_OK);
+ }
+ else
+ {
+ wstring path_ = _wgetenv(_T("APPDATA"));
+ path_ += _T("\\GnuPG");
+ tmp = mir_wstrdup(path_.c_str());
+ }
+ }
+ SetDlgItemText(hwndDlg, IDC_HOME_DIR, !gpg_exists?tmp:_T("gpg"));
+ mir_free(tmp);
+ }
+ //TODO: additional check for write access
+ 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);
+ PathToAbsolute("\\", 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);
+ PathToAbsolute("\\", 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];
+ PathToAbsolute("\\", mir_path);
+ SetCurrentDirectoryA(mir_path);
+ delete [] mir_path;
+ if(!boost::filesystem::exists(tmp))
+ {
+ 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;
+ db_set_ts(NULL, szGPGModuleName, "szGpgBinPath", tmp);
+ string out;
+ DWORD code;
+ std::vector<wstring> cmd;
+ cmd.push_back(L"--version");
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ gpg_valid = true;
+ gpg_launcher(params);
+ gpg_valid = false;
+ db_unset(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);
+ }
+ db_set_ts(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;
+ }
+ db_set_ts(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;
+ db_set_b(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];
+ PathToAbsolute("\\", mir_path);
+ SetCurrentDirectoryA(mir_path);
+ delete [] mir_path;
+ if(!boost::filesystem::exists(tmp))
+ {
+ 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;
+ db_set_ts(NULL, szGPGModuleName, "szGpgBinPath", tmp);
+ string out;
+ DWORD code;
+ std::vector<wstring> cmd;
+ cmd.push_back(L"--version");
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ gpg_valid = true;
+ gpg_launcher(params);
+ gpg_valid = false;
+ db_unset(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);
+ }
+ db_set_ts(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;
+ }
+ db_set_ts(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;
+ std::vector<wstring> cmd;
+ cmd.push_back(L"--batch");
+ cmd.push_back(L"--yes");
+ cmd.push_back(L"--gen-key");
+ cmd.push_back(path);
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ gpg_valid = true;
+ if(!gpg_launcher(params, boost::posix_time::minutes(10)))
+ {
+ gpg_valid = false;
+ break;
+ }
+ gpg_valid = false;
+ if(result == pxNotFound)
+ break;
+ boost::filesystem::remove(path);
+ 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;
+ std::vector<wstring> cmd;
+ cmd.push_back(L"--batch");
+ cmd.push_back(L"-a");
+ cmd.push_back(L"--export");
+ cmd.push_back(path);
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ gpg_valid = true;
+ if(!gpg_launcher(params))
+ {
+ 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);
+ }
+ db_set_s(NULL, szGPGModuleName, "GPGPubKey", out.c_str());
+ db_set_ts(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;
+ db_set_b(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;
+ void InitCheck();
+ InitCheck();
+ break;
+
+ }
+ return FALSE;
+}
+
+static INT_PTR 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), db_get_b(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();
+ db_set_b(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);
+ db_set_dw(NULL, szGPGModuleName, "NewKeyWindowX", new_key_rect.left);
+ db_set_dw(NULL, szGPGModuleName, "NewKeyWindowY", new_key_rect.top);
+ }
+ hwndNewKey = NULL;
+ break;
+
+ }
+ return FALSE;
+}
+static INT_PTR 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;
+ std::vector<wstring> cmd;
+ cmd.push_back(L"--batch");
+ cmd.push_back(L"--yes");
+ cmd.push_back(L"--gen-key");
+ cmd.push_back(path);
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ extern HFONT bold_font;
+ SendMessage(GetDlgItem(hwndDlg, IDC_GENERATING_TEXT), WM_SETFONT, (WPARAM)bold_font, true);
+ 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);
+ if(!gpg_launcher(params, boost::posix_time::minutes(10)))
+ break;
+ if(result == pxNotFound)
+ break;
+ }
+ boost::filesystem::remove(path);
+ 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;
+ {
+ std::vector<wstring> cmd;
+ cmd.push_back(L"--list-secret-keys");
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ if(!gpg_launcher(params))
+ 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);
+ db_set_dw(NULL, szGPGModuleName, "KeyGenWindowX", key_gen_rect.left);
+ db_set_dw(NULL, szGPGModuleName, "KeyGenWindowY", key_gen_rect.top);
+ }
+ hwndKeyGen = NULL;
+ break;
+
+ }
+ return FALSE;
+}
+
+int itemnum2 = 0;
+
+static INT_PTR 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;
+ {
+ std::vector<wstring> cmd;
+ cmd.push_back(L"--batch");
+ cmd.push_back(L"--list-keys");
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ if(!gpg_launcher(params))
+ 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;
+ std::vector<wstring> cmd;
+ cmd.push_back(L"--batch");
+ cmd.push_back(L"-a");
+ cmd.push_back(L"--export");
+ cmd.push_back(id);
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ if(!gpg_launcher(params))
+ 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);
+ db_set_dw(NULL, szGPGModuleName, "LoadExistingKeyWindowX", load_existing_key_rect.left);
+ db_set_dw(NULL, szGPGModuleName, "LoadExistingKeyWindowY", load_existing_key_rect.top);
+ }
+ hwndSelectExistingKey = NULL;
+ break;
+
+ }
+
+ return FALSE;
+}
+static INT_PTR 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;
+ std::vector<wstring> cmd;
+ cmd.push_back(L"--keyserver");
+ TCHAR *server= new TCHAR [128];
+ GetDlgItemText(hwndDlg, IDC_KEYSERVER, server, 128);
+ cmd.push_back(server);
+ delete [] server;
+ cmd.push_back(L"--recv-keys");
+// char *tmp = UniGetContactSettingUtf(hContact, szGPGModuleName, "KeyID_Prescense", "");
+// TCHAR *tmp2 = mir_a2t(tmp);
+// mir_free(tmp);
+ cmd.push_back(toUTF16(hcontact_data[hContact].key_in_prescense));
+// mir_free(tmp2);
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ gpg_launcher(params);
+ 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);
+ db_set_dw(NULL, szGPGModuleName, "ImportKeyWindowX", import_key_rect.left);
+ db_set_dw(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, DlgProcFirstRun);
+ }
+ SetForegroundWindow(hwndFirstRun);
+}
+
+
+void ShowSetDirsDialog()
+{
+ if (hwndSetDirs == NULL)
+ {
+ hwndSetDirs = CreateDialog(hInst, MAKEINTRESOURCE(IDD_BIN_PATH), NULL, DlgProcGpgBinOpts);
+ }
+ SetForegroundWindow(hwndSetDirs);
+}
+
+void ShowNewKeyDialog()
+{
+ hwndNewKey = CreateDialog(hInst, MAKEINTRESOURCE(IDD_NEW_KEY), NULL, DlgProcNewKeyDialog);
+ SetForegroundWindow(hwndNewKey);
+}
+
+void ShowKeyGenDialog()
+{
+ if (hwndKeyGen == NULL)
+ {
+ hwndKeyGen = CreateDialog(hInst, MAKEINTRESOURCE(IDD_KEY_GEN), NULL, DlgProcKeyGenDialog);
+ }
+ SetForegroundWindow(hwndKeyGen);
+}
+
+void ShowSelectExistingKeyDialog()
+{
+ if (hwndSelectExistingKey == NULL)
+ {
+ hwndSelectExistingKey = CreateDialog(hInst, MAKEINTRESOURCE(IDD_LOAD_EXISTING_KEY), NULL, DlgProcLoadExistingKey);
+ }
+ SetForegroundWindow(hwndSelectExistingKey);
+}
+
+void ShowImportKeyDialog()
+{
+ CreateDialog(hInst, MAKEINTRESOURCE(IDD_IMPORT_KEY), NULL, DlgProcImportKeyDialog);
+}
+
+
+
+
+void FirstRun()
+{
+ DWORD pid = 0;
+ if(!db_get_b(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();
+ boost::filesystem::remove(test_path);
+ }
+ 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();
+ boost::filesystem::remove(test_path);
+ }
+ 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;
+ {
+ std::vector<wstring> cmd;
+ cmd.push_back(L"--batch");
+ cmd.push_back(L"--list-secret-keys");
+ gpg_execution_params params(cmd);
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ if(!gpg_launcher(params))
+ 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());
+ int count = 0;
+ PROTOACCOUNT **accounts;
+ ProtoEnumAccounts(&count, &accounts);
+ string question;
+ char *keyid, *key;
+ for(int i = 0; i < count; i++)
+ {
+ if(StriStr(accounts[i]->szModuleName, "metacontacts"))
+ continue;
+ if(StriStr(accounts[i]->szModuleName, "weather"))
+ continue;
+ std::string acc = toUTF8(accounts[i]->tszAccountName);
+ acc += "(";
+ acc += accounts[i]->szModuleName;
+ acc += ")";
+ acc += "_KeyID";
+ keyid = UniGetContactSettingUtf(NULL, szGPGModuleName, acc.c_str(), "");
+ if(keyid[0])
+ {
+ question = Translate("Your secret key whith id: ");
+ keyid = UniGetContactSettingUtf(NULL, szGPGModuleName, "KeyID", "");
+ key = UniGetContactSettingUtf(NULL, szGPGModuleName, "GPGPubKey", "");
+ void ShowFirstRunDialog();
+ if((p = out.find(keyid)) == string::npos)
+ {
+ question += keyid;
+ question += Translate(" for account ");
+ question += toUTF8(accounts[i]->tszAccountName);
+ 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();
+ }
+ p2 = p;
+ p = out.find("[", p);
+ p2 = out.find("\n", p2);
+ if((p != std::string::npos) && (p < p2))
+ {
+ p = out.find("expires:", p);
+ p += strlen("expires:");
+ p++;
+ p2 = out.find("]", p);
+ TCHAR *expire_date = mir_wstrdup(toUTF16(out.substr(p,p2-p)).c_str());
+ bool expired = false;
+ {
+ boost::posix_time::ptime now = boost::posix_time::second_clock::local_time();
+ TCHAR buf[5];
+ mir_sntprintf(buf, 5, _T("%s"), expire_date);
+ int year = _ttoi(buf);
+ if(year < now.date().year())
+ expired = true;
+ else if(year == now.date().year())
+ {
+ mir_sntprintf(buf, 3, _T("%s"), expire_date+5);
+ int month = _ttoi(buf);
+ if(month < now.date().month())
+ expired = true;
+ else if(month == now.date().month())
+ {
+ mir_sntprintf(buf, 3, _T("%s"), expire_date+8);
+ unsigned day = _ttoi(buf);
+ if(day <= now.date().day_number())
+ expired = true;
+ }
+ }
+ }
+ if(expired)
+ {
+ question += keyid;
+ question += Translate(" for account ");
+ question += toUTF8(accounts[i]->tszAccountName);
+ question += Translate(" expired and will not work\nDo you want to set another key ?");
+ if(MessageBoxA(0, question.c_str(), Translate("Own secret key warning"), MB_YESNO) == IDYES)
+ ShowFirstRunDialog();
+ }
+ mir_free(expire_date);
+ }
+ }
+ mir_free(keyid);
+ }
+ question = Translate("Your secret key whith id: ");
+ keyid = UniGetContactSettingUtf(NULL, szGPGModuleName, "KeyID", "");
+ key = UniGetContactSettingUtf(NULL, szGPGModuleName, "GPGPubKey", "");
+ void ShowFirstRunDialog();
+ if(!db_get_b(NULL, szGPGModuleName, "FirstRun", 1) && (!keyid[0] || !key[0]))
+ {
+ question = Translate("You didn't set a private key.\nWould you like to set it now?");
+ if(MessageBoxA(0, question.c_str(), Translate("Own private key warning"), MB_YESNO) == IDYES)
+ ShowFirstRunDialog();
+ }
+ if((p = 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();
+ }
+ p2 = p;
+ p = out.find("[", p);
+ p2 = out.find("\n", p2);
+ if((p != std::string::npos) && (p < p2))
+ {
+ p = out.find("expires:", p);
+ p += strlen("expires:");
+ p++;
+ p2 = out.find("]", p);
+ TCHAR *expire_date = mir_wstrdup(toUTF16(out.substr(p,p2-p)).c_str());
+ bool expired = false;
+ {
+ boost::posix_time::ptime now = boost::posix_time::second_clock::local_time();
+ TCHAR buf[5];
+ mir_sntprintf(buf, 5, _T("%s"), expire_date);
+ int year = _ttoi(buf);
+ if(year < now.date().year())
+ expired = true;
+ else if(year == now.date().year())
+ {
+ mir_sntprintf(buf, 3, _T("%s"), expire_date+5);
+ int month = _ttoi(buf);
+ if(month < now.date().month())
+ expired = true;
+ else if(month == now.date().month())
+ {
+ mir_sntprintf(buf, 3, _T("%s"), expire_date+8);
+ unsigned day = _ttoi(buf);
+ if(day <= now.date().day_number())
+ expired = true;
+ }
+ }
+ }
+ if(expired)
+ {
+ question += keyid;
+ question += Translate(" expired and will not work\nDo you want to set another key ?");
+ if(MessageBoxA(0, question.c_str(), Translate("Own secret key warning"), MB_YESNO) == IDYES)
+ ShowFirstRunDialog();
+ }
+ mir_free(expire_date);
+ }
+ //TODO: check for expired key
+ 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);
+ }
+ }
+ if(bFileTransfers)
+ {
+ int count = 0;
+ PROTOACCOUNT **accounts;
+ ProtoEnumAccounts(&count, &accounts);
+ ICQ_CUSTOMCAP cap;
+ cap.cbSize = sizeof(ICQ_CUSTOMCAP);
+ cap.hIcon = 0;
+ strcpy(cap.name, "GPG Encrypted FileTransfers");
+ strcpy(cap.caps, "GPG FileTransfer");
+
+ 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)
+ db_set_ts(hcnt, szGPGModuleName, "GPGPubKey", new_key.c_str());
+ }
+ }
+ else
+ db_set_ts(metaGetMostOnline(hContact), szGPGModuleName, "GPGPubKey", new_key.c_str());
+ }
+ else
+ db_set_ts(hContact, szGPGModuleName, "GPGPubKey", new_key.c_str());
+ new_key.clear();
+ { //gpg execute block
+ std::vector<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"));
+ boost::filesystem::remove(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.push_back(L"--batch");
+ cmd.push_back(L"--import");
+ cmd.push_back(tmp2);
+ }
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &output;
+ params.code = &exitcode;
+ params.result = &result;
+ if(!gpg_launcher(params))
+ 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);
+ db_set_s(hcnt, szGPGModuleName, "KeyID", output.substr(s,s2-s).c_str());
+ s = output.find("“", s2);
+ if(s == string::npos)
+ {
+ s = output.find("\"", s2);
+ s += 1;
+ }
+ else
+ s += 3;
+ bool uncommon = false;
+ if((s2 = output.find("(", s)) == string::npos)
+ {
+ if((s2 = output.find("<", s)) == string::npos)
+ {
+ s2 = output.find("â€", s);
+ uncommon = true;
+ }
+ }
+ else if(s2 > output.find("<", s))
+ s2 = output.find("<", s);
+ if(s != string::npos && s2 != string::npos)
+ {
+ tmp = (char*)mir_alloc(sizeof(char)*(output.substr(s,s2-s-(uncommon?1:0)).length()+1));
+ strcpy(tmp, output.substr(s,s2-s-(uncommon?1:0)).c_str());
+ mir_utf8decode(tmp, 0);
+ db_set_s(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(s != string::npos && s2 != string::npos)
+ {
+ if(output[s] == ')')
+ {
+ tmp = (char*)mir_alloc(sizeof(char)* (output.substr(s2,s-s2).length()+1));
+ strcpy(tmp, output.substr(s2,s-s2).c_str());
+ mir_utf8decode(tmp, 0);
+ db_set_s(hcnt, szGPGModuleName, "KeyComment", tmp);
+ mir_free(tmp);
+ s+=3;
+ s2 = output.find(">", s);
+ if(s != string::npos && s2 != string::npos)
+ {
+ tmp = (char*) mir_alloc(sizeof(char)*(output.substr(s,s2-s).length()+1));
+ strcpy(tmp, output.substr(s,s2-s).c_str());
+ mir_utf8decode(tmp, 0);
+ db_set_s(hcnt, szGPGModuleName, "KeyMainEmail", tmp);
+ mir_free(tmp);
+ }
+ }
+ else
+ {
+ tmp = (char*)mir_alloc(sizeof(char)* (output.substr(s2,s-s2).length()+1));
+ strcpy(tmp, output.substr(s2,s-s2).c_str());
+ mir_utf8decode(tmp, 0);
+ db_set_s(hcnt, szGPGModuleName, "KeyMainEmail", output.substr(s2,s-s2).c_str());
+ mir_free(tmp);
+ }
+ }
+ db_unset(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);
+ db_set_s(metaGetMostOnline(hContact), szGPGModuleName, "KeyID", output.substr(s,s2-s).c_str());
+ s = output.find("“", s2);
+ if(s == string::npos)
+ {
+ s = output.find("\"", s2);
+ s += 1;
+ }
+ else
+ s += 3;
+ bool uncommon = false;
+ if((s2 = output.find("(", s)) == string::npos)
+ {
+ if((s2 = output.find("<", s)) == string::npos)
+ {
+ s2 = output.find("â€", s);
+ uncommon = true;
+ }
+ }
+ else if(s2 > output.find("<", s))
+ s2 = output.find("<", s);
+ if(s != string::npos && s2 != string::npos)
+ {
+ tmp = (char*)mir_alloc(sizeof(char)*(output.substr(s,s2-s-(uncommon?1:0)).length()+1));
+ strcpy(tmp, output.substr(s,s2-s-(uncommon?1:0)).c_str());
+ mir_utf8decode(tmp, 0);
+ db_set_s(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(s != string::npos && s2 != string::npos)
+ {
+ if(output[s] == ')')
+ {
+ tmp = (char*)mir_alloc(sizeof(char)* (output.substr(s2,s-s2).length()+1));
+ strcpy(tmp, output.substr(s2,s-s2).c_str());
+ mir_utf8decode(tmp, 0);
+ db_set_s(metaGetMostOnline(hContact), szGPGModuleName, "KeyComment", tmp);
+ mir_free(tmp);
+ s+=3;
+ s2 = output.find(">", s);
+ if(s != string::npos && s2 != string::npos)
+ {
+ tmp = (char*) mir_alloc(sizeof(char)*(output.substr(s,s2-s).length()+1));
+ strcpy(tmp, output.substr(s,s2-s).c_str());
+ mir_utf8decode(tmp, 0);
+ db_set_s(metaGetMostOnline(hContact), szGPGModuleName, "KeyMainEmail", tmp);
+ mir_free(tmp);
+ }
+ }
+ else
+ {
+ tmp = (char*)mir_alloc(sizeof(char)* (output.substr(s2,s-s2).length()+1));
+ strcpy(tmp, output.substr(s2,s-s2).c_str());
+ mir_utf8decode(tmp, 0);
+ db_set_s(metaGetMostOnline(hContact), szGPGModuleName, "KeyMainEmail", output.substr(s2,s-s2).c_str());
+ mir_free(tmp);
+ }
+ }
+ db_unset(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);
+ db_set_s(hContact, szGPGModuleName, "KeyID", output.substr(s,s2-s).c_str());
+ s = output.find("“", s2);
+ if(s == string::npos)
+ {
+ s = output.find("\"", s2);
+ s += 1;
+ }
+ else
+ s += 3;
+ bool uncommon = false;
+ if((s2 = output.find("(", s)) == string::npos)
+ {
+ if((s2 = output.find("<", s)) == string::npos)
+ {
+ s2 = output.find("â€", s);
+ uncommon = true;
+ }
+ }
+ else if(s2 > output.find("<", s))
+ s2 = output.find("<", s);
+ if(s != string::npos && s2 != string::npos)
+ {
+ tmp = (char*)mir_alloc(sizeof(char)*(output.substr(s,s2-s-(uncommon?1:0)).length()+1));
+ strcpy(tmp, output.substr(s,s2-s-(uncommon?1:0)).c_str());
+ mir_utf8decode(tmp, 0);
+ db_set_s(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(s != string::npos && s2 != string::npos)
+ {
+ if(output[s] == ')')
+ {
+ tmp = (char*)mir_alloc(sizeof(char)* (output.substr(s2,s-s2).length()+1));
+ strcpy(tmp, output.substr(s2,s-s2).c_str());
+ mir_utf8decode(tmp, 0);
+ db_set_s(hContact, szGPGModuleName, "KeyComment", tmp);
+ mir_free(tmp);
+ s+=3;
+ s2 = output.find(">", s);
+ if(s != string::npos && s2 != string::npos)
+ {
+ tmp = (char*) mir_alloc(sizeof(char)*(output.substr(s,s2-s).length()+1));
+ strcpy(tmp, output.substr(s,s2-s).c_str());
+ mir_utf8decode(tmp, 0);
+ db_set_s(hContact, szGPGModuleName, "KeyMainEmail", tmp);
+ mir_free(tmp);
+ }
+ }
+ else
+ {
+ tmp = (char*)mir_alloc(sizeof(char)* (output.substr(s2,s-s2).length()+1));
+ strcpy(tmp, output.substr(s2,s-s2).c_str());
+ mir_utf8decode(tmp, 0);
+ db_set_s(hContact, szGPGModuleName, "KeyMainEmail", output.substr(s2,s-s2).c_str());
+ mir_free(tmp);
+ }
+ }
+ db_unset(hContact, szGPGModuleName, "bAlwatsTrust");
+ }
+ }
+ ptmp = mir_wstrdup(toUTF16(output).c_str());
+ MessageBox(0, ptmp, _T(""), MB_OK);
+ mir_free(ptmp);
+ boost::filesystem::remove(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 100644
index 0000000000..353dee0aae
--- /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 100644
index 0000000000..645d6a5435
--- /dev/null
+++ b/plugins/New_GPG/src/messages.cpp
@@ -0,0 +1,1198 @@
+// 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;
+
+void 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))
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info: received encrypted message from: "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR))+" with turned off encryption");
+ if(MessageBox(0, TranslateT("We received encrypted message from contact with encryption turned off.\nDo you want turn on encryption for this contact ?"), TranslateT("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
+ {
+ db_set_b(metaIsProtoMetaContacts(hContact)?metaGetMostOnline(hContact):hContact, szGPGModuleName, "GPGEncryption", 1);
+ setSrmmIcon(hContact);
+ setClistIcon(hContact);
+ }
+ if(isContactHaveKey(hContact))
+ {
+ db_set_b(metaIsProtoMetaContacts(hContact)?metaGetMostOnline(hContact):hContact, szGPGModuleName, "GPGEncryption", 1);
+ setSrmmIcon(hContact);
+ setClistIcon(hContact);
+ }
+ }
+ else if(MessageBox(0, TranslateT("Do you want try to decrypt encrypted message ?"), TranslateT("Warning"), MB_YESNO) == IDNO)
+ {
+
+ HistoryLog(hContact, db_event(msg, timestamp, 0, dbflags));
+ return;
+ }
+ }
+ else if(bDebugLog)
+ {
+ debuglog<<std::string(time_str()+": info: received encrypted message from: "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)));
+ }
+ boost::algorithm::erase_all(str, "\r");
+ 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);
+ boost::filesystem::remove(path);
+ 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;
+ std::vector<wstring> cmd;
+ cmd.push_back(L"--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] && bDebugLog)
+ debuglog<<std::string(time_str()+": info: found password in database for key id: "+inkeyid+", trying to decrypt message from "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR))+" with password");
+ }
+ else
+ {
+ pass = UniGetContactSettingUtf(NULL, szGPGModuleName, "szKeyPassword", _T(""));
+ if(pass[0] && bDebugLog)
+ debuglog<<std::string(time_str()+": info: found password for all keys in database, trying to decrypt message from "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR))+" with password");
+ }
+ if(pass && pass[0])
+ {
+ cmd.push_back(L"--passphrase");
+ cmd.push_back(pass);
+ }
+ else if(password && password[0])
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info: found password in memory, trying to decrypt message from "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR))+" with password");
+ cmd.push_back(L"--passphrase");
+ cmd.push_back(password);
+ }
+ else if (bDebugLog)
+ debuglog<<std::string(time_str()+": info: passwords not found in database or memory, trying to decrypt message from "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR))+" with out password");
+ mir_free(pass);
+ mir_free(inkeyid);
+ }
+ {
+ wstring path = tmp2;
+ path += _T("\\tmp\\");
+ path += decfile;
+ boost::filesystem::remove(path);
+ }
+ cmd.push_back(L"--output");
+ cmd.push_back(std::wstring(tmp2) + L"\\tmp\\" + decfile);
+ cmd.push_back(L"-d");
+ cmd.push_back(L"-a");
+ cmd.push_back(path);
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ if(!gpg_launcher(params))
+ {
+ boost::filesystem::remove(path);
+ HistoryLog(hContact, db_event(msg, timestamp, 0, dbflags));
+ BYTE enc = db_get_b(hContact, szGPGModuleName, "GPGEncryption", 0);
+ db_set_b(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));
+ db_set_b(hContact, szGPGModuleName, "GPGEncryption", enc);
+ return;
+ }
+ if(result == pxNotFound)
+ {
+ boost::filesystem::remove(path);
+ HistoryLog(hContact, db_event(msg, timestamp, 0, dbflags));
+ return;
+ }
+ if(result == pxSuccessExitCodeInvalid)
+ {
+ boost::filesystem::remove(path);
+ HistoryLog(hContact, db_event(msg, timestamp, 0, dbflags));
+ HistoryLog(hContact, db_event(Translate("failed to decrypt message, GPG returned error, turn on debug log for more details"), timestamp, 0, 0));
+ return;
+ }
+
+ //TODO: check gpg output for errors
+ _terminate = false;
+ while(out.find("public key decryption failed: bad passphrase") != string::npos)
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info: failed to decrypt messaage from "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR))+" password needed, trying to get one");
+ if(_terminate)
+ {
+ BYTE enc = db_get_b(hContact, szGPGModuleName, "GPGEncryption", 0);
+ db_set_b(hContact, szGPGModuleName, "GPGEncryption", 0);
+ CallContactService(hContact, PSS_MESSAGE, PREF_UTF, (LPARAM)"Unable to decrypt PGP encrypted message");
+ HistoryLog(hContact, db_event("Error message sent", 0, 0, DBEF_SENT));
+ db_set_b(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);
+ db_set_s(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();
+ std::vector<wstring> cmd2 = cmd;
+ if(password)
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info: found password in memory, trying to decrypt message from "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)));
+ std::vector<wstring> tmp;
+ tmp.push_back(L"--passphrase");
+ tmp.push_back(password);
+ cmd2.insert(cmd2.begin(), tmp.begin(), tmp.end());
+ }
+ out.clear();
+ gpg_execution_params params(cmd2);
+ pxResult result;
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ if(!gpg_launcher(params))
+ {
+ boost::filesystem::remove(path);
+ HistoryLog(hContact, db_event(msg, timestamp, 0, dbflags));
+ BYTE enc = db_get_b(hContact, szGPGModuleName, "GPGEncryption", 0);
+ db_set_b(hContact, szGPGModuleName, "GPGEncryption", 0);
+ CallContactService(hContact, PSS_MESSAGE, PREF_UTF, (LPARAM)"Unable to decrypt PGP encrypted message");
+ HistoryLog(hContact, db_event("Error message sent", 0, 0, DBEF_SENT));
+ db_set_b(hContact, szGPGModuleName, "GPGEncryption", enc);
+ return;
+ }
+ if(result == pxNotFound)
+ {
+ boost::filesystem::remove(path);
+ HistoryLog(hContact, db_event(msg, timestamp, 0, dbflags));
+ return;
+ }
+ }
+ out.clear();
+ if(!gpg_launcher(params))
+ {
+ boost::filesystem::remove(path);
+ HistoryLog(hContact, db_event(msg, timestamp, 0, dbflags));
+ BYTE enc = db_get_b(hContact, szGPGModuleName, "GPGEncryption", 0);
+ db_set_b(hContact, szGPGModuleName, "GPGEncryption", 0);
+ CallContactService(hContact, PSS_MESSAGE, PREF_UTF, (LPARAM)"Unable to decrypt PGP encrypted message");
+ HistoryLog(hContact, db_event("Error message sent", 0, 0, DBEF_SENT));
+ db_set_b(hContact, szGPGModuleName, "GPGEncryption", enc);
+ return;
+ }
+ if(result == pxNotFound)
+ {
+ boost::filesystem::remove(path);
+ HistoryLog(hContact, db_event(msg, timestamp, 0, dbflags));
+ }
+ {
+ wstring tmp = tmp2;
+ tmp += _T("\\tmp\\");
+ tmp += encfile;
+ boost::filesystem::remove(tmp);
+ }
+ {
+ wstring tmp = tmp2;
+ tmp += _T("\\tmp\\");
+ tmp += decfile;
+ if(!boost::filesystem::exists(tmp))
+ {
+ string str = msg;
+ str.insert(0, "Received unencrypted message:\n");
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info: Failed to decrypt GPG encrypted message.");
+ char *tmp = (char*)mir_alloc(sizeof(char)*(str.length()+1));
+ strcpy(tmp, str.c_str());
+ HistoryLog(hContact, db_event(msg, timestamp, 0, dbflags));
+ BYTE enc = db_get_b(hContact, szGPGModuleName, "GPGEncryption", 0);
+ db_set_b(hContact, szGPGModuleName, "GPGEncryption", 0);
+ CallContactService(hContact, PSS_MESSAGE, PREF_UTF, (LPARAM)"Unable to decrypt PGP encrypted message");
+ HistoryLog(hContact, db_event("Error message sent", 0, 0, DBEF_SENT));
+ db_set_b(hContact, szGPGModuleName, "GPGEncryption", enc);
+ mir_free(tmp);
+ return;
+ }
+ }
+ 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();
+ boost::filesystem::remove(path);
+ }
+ if(str.empty())
+ {
+ string str = msg;
+ str.insert(0, "Failed to decrypt GPG encrypted message.\nMessage body for manual decryption:\n");
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info: Failed to decrypt GPG encrypted message.");
+ char *tmp = mir_strdup(str.c_str());
+ HistoryLog(hContact, db_event(msg, timestamp, 0, dbflags));
+ BYTE enc = db_get_b(hContact, szGPGModuleName, "GPGEncryption", 0);
+ db_set_b(hContact, szGPGModuleName, "GPGEncryption", 0);
+ CallContactService(hContact, PSS_MESSAGE, PREF_UTF, (LPARAM)"Unable to decrypt PGP encrypted message");
+ HistoryLog(hContact, db_event("Error message sent", 0, 0, DBEF_SENT));
+ db_set_b(hContact, szGPGModuleName, "GPGEncryption", enc);
+ mir_free(tmp);
+ return;
+ }
+ else
+ {
+ fix_line_term(str);
+ 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;
+ }
+ char *tmp = mir_strdup(toUTF8(str).c_str());
+ HistoryLog(hContact, db_event(tmp, timestamp, 0, dbflags));
+ mir_free(tmp);
+ return;
+ }
+ }
+ }
+ }
+ }
+ if(db_get_b(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;
+ }
+ HistoryLog(hContact, db_event(msg, timestamp, 0, dbflags|DBEF_READ));
+ return;
+ }
+ HistoryLog(hContact, db_event(msg, timestamp, 0, dbflags));
+ return;
+}
+
+INT_PTR 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);
+ DWORD dbflags = DBEF_UTF;
+ if(metaIsProtoMetaContacts(ccs->hContact))
+ {
+ if(!strstr(msg, "-----BEGIN PGP MESSAGE-----"))
+ return CallService(MS_PROTO_CHAINRECV, w, l);
+ else
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info: blocked pgp message to metacontact:"+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ccs->hContact, GCDNF_TCHAR)));
+ return 0;
+ }
+ }
+ wstring str = toUTF16(msg);
+ wstring::size_type s1 = wstring::npos, s2 = wstring::npos;
+ if(bAutoExchange && (str.find(_T("-----PGP KEY RESPONSE-----")) != wstring::npos))
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info(autoexchange): parsing key response:"+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ccs->hContact, GCDNF_TCHAR)));
+ 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)
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info(autoexchange): found pubkey block:"+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ccs->hContact, GCDNF_TCHAR)));
+ s2 += _tcslen(_T("-----END PGP PUBLIC KEY BLOCK-----"));
+ db_set_ts(ccs->hContact, szGPGModuleName, "GPGPubKey", str.substr(s1,s2-s1).c_str());
+ { //gpg execute block
+ std::vector<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("\\"));
+ TCHAR *tmp3 = mir_a2t(get_random(5).c_str());
+ _tcscat(tmp2, tmp3);
+ _tcscat(tmp2, _T(".asc"));
+ mir_free(tmp3);
+ //_tcscat(tmp2, _T("temporary_exported.asc"));
+ boost::filesystem::remove(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.push_back(L"--batch");
+ cmd.push_back(L"--import");
+ cmd.push_back(tmp2);
+ }
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &output;
+ params.code = &exitcode;
+ params.result = &result;
+ if(!gpg_launcher(params))
+ return 1;
+ boost::filesystem::remove(tmp2);
+ if(result == pxNotFound)
+ return 1;
+ if(result == pxSuccessExitCodeInvalid)
+ {
+ HistoryLog(ccs->hContact, db_event(Translate("failed to decrypt message, GPG returned error, turn on debug log for more details")));
+ return 1;
+ }
+ {
+ char *tmp = NULL;
+ string::size_type s = output.find("gpg: key ") + strlen("gpg: key ");
+ string::size_type s2 = output.find(":", s);
+ db_set_s(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);
+ db_set_s(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);
+ db_set_s(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);
+ db_set_s(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);
+ db_set_s(ccs->hContact, szGPGModuleName, "KeyMainEmail", output.substr(s2,s-s2).c_str());
+ mir_free(tmp);
+ }
+ db_set_b(ccs->hContact, szGPGModuleName, "GPGEncryption", 1);
+ db_set_b(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(((s2 = str.find(_T("-----END PGP PUBLIC KEY BLOCK-----"))) == wstring::npos) || ((s1 = str.find(_T("-----BEGIN PGP PUBLIC 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(bDebugLog)
+ debuglog<<std::string(time_str()+": info: received key from: "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ccs->hContact, GCDNF_TCHAR)));
+ s1 = 0;
+ while((s1 = str.find(_T("\r"), s1)) != wstring::npos)
+ str.erase(s1, 1);
+ void ShowNewKeyDialog();
+ if(((s2 = str.find(_T("-----END PGP PUBLIC KEY BLOCK-----"))) != wstring::npos) && ((s1 = str.find(_T("-----BEGIN PGP PUBLIC KEY BLOCK-----"))) != wstring::npos))
+ {
+ s2 += _tcslen(_T("-----END PGP PUBLIC KEY BLOCK-----"));
+ }
+ else if(((s2 = str.find(_T("-----BEGIN PGP PRIVATE KEY BLOCK-----"))) != wstring::npos) && ((s1 = str.find(_T("-----END PGP PRIVATE KEY BLOCK-----"))) != wstring::npos))
+ {
+ 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)
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info(autoexchange): received key request from: "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ccs->hContact, GCDNF_TCHAR)));
+ char *tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "GPGPubKey", "");
+ if(tmp[0])
+ {
+ int enc_state = db_get_b(ccs->hContact, szGPGModuleName, "GPGEncryption", 0);
+ if(enc_state)
+ db_set_b(ccs->hContact, szGPGModuleName, "GPGEncryption", 0);
+ string str = "-----PGP KEY RESPONSE-----";
+ str.append(tmp);
+ CallContactService(ccs->hContact, PSS_MESSAGE, PREF_UTF, (LPARAM)str.c_str());
+ if(enc_state)
+ db_set_b(ccs->hContact, szGPGModuleName, "GPGEncryption", 1);
+ }
+ mir_free(tmp);
+ return 0;
+ }
+ else if(!isContactHaveKey(ccs->hContact) && bAutoExchange && gpg_valid && gpg_keyexist)
+ {
+ char *proto = GetContactProto(ccs->hContact);
+ DWORD uin = db_get_dw(ccs->hContact, proto, "UIN", 0);
+ if(uin) {
+ 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, PREF_UTF, (LPARAM)"-----PGP KEY REQUEST-----");
+ return 0;
+ }
+ }
+ }
+ 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, 0, (LPARAM)"-----PGP KEY REQUEST-----");
+ return 0;
+ }
+ }
+ }
+ }
+ }
+ }
+ if(!strstr(msg, "-----BEGIN 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 0;
+}
+
+void SendMsgSvc_func(HANDLE hContact, char *msg, DWORD flags)
+{
+ bool isansi = false;
+ DWORD dbflags = 0;
+ if((flags & PREF_UTF) == PREF_UTF)
+ dbflags |= DBEF_UTF;
+ wstring str = toUTF16(msg);
+ if(bStripTags && bAppendTags)
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info: stripping tags in outgoing message, name: "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)));
+ strip_tags(str);
+ }
+/* 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 file = toUTF16(get_random(10)), path;
+ std::vector<std::wstring> cmd;
+ 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 (not found key for encryption in db)", 0,0, DBEF_SENT));
+// hcontact_data[hContact].msgs_to_pass.push_back("Failed to encrypt message with GPG (not found key for encryption in db)");
+ //mir_free(msg);
+ CallContactService(hContact, PSS_MESSAGE, flags, (LPARAM)msg);
+ return;
+ }
+ if(!bJabberAPI || !bIsMiranda09) //force jabber to handle encrypted message by itself
+ {
+ cmd.push_back(L"--comment");
+ cmd.push_back(L"\"\"");
+ cmd.push_back(L"--no-version");
+ }
+ if(db_get_b(hContact, szGPGModuleName, "bAlwaysTrust", 0))
+ {
+ cmd.push_back(L"--trust-model");
+ cmd.push_back(L"always");
+ }
+ cmd.push_back(L"--batch");
+ cmd.push_back(L"--yes");
+ cmd.push_back(L"-eatr");
+ TCHAR *tmp2 = mir_a2t(tmp);
+ mir_free(tmp);
+ cmd.push_back(tmp2);
+ mir_free(tmp2);
+ tmp2 = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T(""));
+ path = tmp2;
+ cmd.push_back(std::wstring(tmp2) + L"\\tmp\\" + file);
+ mir_free(tmp2);
+ path += L"\\tmp\\";
+ path += file;
+ {
+ fstream f(path.c_str(), std::ios::out);
+ while(!f.is_open())
+ {
+ boost::this_thread::sleep(boost::posix_time::milliseconds(50));
+ f.open(path.c_str(), std::ios::out);
+ }
+ std::string tmp = toUTF8(str);
+ f.write(tmp.c_str(), tmp.size());
+ f.close();
+ }
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ if(!gpg_launcher(params))
+ {
+ //mir_free(msg);
+ CallContactService(hContact, PSS_MESSAGE, flags, (LPARAM)msg);
+ return;
+ }
+ if(result == pxNotFound)
+ {
+ //mir_free(msg);
+ CallContactService(hContact, PSS_MESSAGE, flags, (LPARAM)msg);
+ return;
+ }
+ if(out.find("There is no assurance this key belongs to the named user") != string::npos)
+ {
+ out.clear();
+ if(MessageBox(0, TranslateT("We trying to encrypt with untrusted key, do you want to trust this key permanently ?"), TranslateT("Warning"), MB_YESNO) == IDYES)
+ {
+ db_set_b(hContact, szGPGModuleName, "bAlwaysTrust", 1);
+ std::vector<std::wstring> tmp;
+ tmp.push_back(L"--trust-model");
+ tmp.push_back(L"always");
+ cmd.insert(cmd.begin(), tmp.begin(), tmp.end());
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ if(!gpg_launcher(params))
+ {
+ //mir_free(msg);
+ CallContactService(hContact, PSS_MESSAGE, flags, (LPARAM)msg);
+ return;
+ }
+ if(result == pxNotFound)
+ {
+ //mir_free(msg);
+ CallContactService(hContact, PSS_MESSAGE, flags, (LPARAM)msg);
+ return;
+ }
+ //TODO: check gpg output for errors
+ }
+ else
+ {
+ //mir_free(msg);
+ return;
+ }
+ }
+ if(result == pxSuccessExitCodeInvalid)
+ {
+ //mir_free(msg);
+ HistoryLog(hContact, db_event(Translate("failed o encrypt message, GPG returned error, turn on debug log for more details"), 0,0, DBEF_SENT));
+ boost::filesystem::remove(path);
+ return;
+ }
+ if(out.find("usage: ") != string::npos)
+ {
+ MessageBox(0, TranslateT("Something wrong, gpg does not understand us, aborting encryption."), TranslateT("Warning"), MB_OK);
+ //mir_free(msg);
+ CallContactService(hContact, PSS_MESSAGE, flags, (LPARAM)msg);
+ boost::filesystem::remove(path);
+ return;
+ }
+ boost::filesystem::remove(path);
+ path.append(_T(".asc"));
+ wfstream f(path.c_str(), std::ios::in | std::ios::ate | std::ios::binary);
+ while(!f.is_open())
+ {
+ boost::this_thread::sleep(boost::posix_time::milliseconds(100));
+ 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();
+ boost::filesystem::remove(path);
+ }
+ 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");
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info: Failed to encrypt message with GPG");
+ //mir_free(msg);
+ CallContactService(hContact, PSS_MESSAGE, flags, (LPARAM)msg);
+ return;
+ }
+ 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);
+ if(bDebugLog)
+ {
+ debuglog<<std::string(time_str() + toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)) +"is subcontact of" + toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)metaGetContact(hContact), GCDNF_TCHAR)));
+ debuglog<<std::string(time_str()+": adding event to metacontact: "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)metaGetContact(hContact), GCDNF_TCHAR))+" on send message.");
+ }
+ HistoryLog(metaGetContact(hContact), db_event((char*)str_event.c_str(), 0,0, DBEF_SENT|dbflags));
+ }*/ //unneeded ?
+// hcontact_data[hContact].msgs_to_pass.push_back(str_event);
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": adding event to contact: "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR))+" on send message.");
+ //HistoryLog(hContact, db_event((char*)str_event.c_str(), 0,0, dbflags|DBEF_SENT));
+ if(!(flags & PREF_UTF))
+ flags |= PREF_UTF;
+ fix_line_term(str);
+ sent_msgs.push_back((HANDLE)CallContactService(hContact, PSS_MESSAGE, flags, (LPARAM)toUTF8(str).c_str()));
+ //mir_free(msg);
+ return;
+}
+
+INT_PTR SendMsgSvc(WPARAM w, LPARAM l)
+{
+ CCSDATA *ccs = (CCSDATA*)l;
+ if (!ccs)
+ return CallService(MS_PROTO_CHAINSEND, w, l);
+ char *msg = nullptr;
+ if((ccs->wParam & PREF_UTF) == PREF_UTF)
+ msg = mir_strdup((char*)(ccs->lParam));
+ else
+ msg = mir_utf8encode((char*)(ccs->lParam));
+ if (!msg)
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info: failed to get message data, name: "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ccs->hContact, GCDNF_TCHAR)));
+ mir_free(msg);
+ return CallService(MS_PROTO_CHAINSEND, w, l);
+ }
+ if(strstr(msg,"-----BEGIN PGP MESSAGE-----"))
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info: encrypted messge, let it go, name: "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ccs->hContact, GCDNF_TCHAR)));
+ return CallService(MS_PROTO_CHAINSEND, w, l);
+ }
+ /*if(!isContactHaveKey(ccs->hContact))
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info: contact have not key, name: "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ccs->hContact, GCDNF_TCHAR)));
+ if(bAutoExchange && !strstr(msg, "-----PGP KEY REQUEST-----") && !strstr(msg, "-----BEGIN PGP PUBLIC KEY BLOCK-----") && gpg_valid)
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info: checking for autoexchange possibility, name: "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ccs->hContact, GCDNF_TCHAR)));
+ void send_encrypted_msgs_thread(HANDLE hContact);
+ LPSTR proto = GetContactProto(ccs->hContact);
+ DWORD uin = db_get_dw(ccs->hContact, proto, "UIN", 0);
+ if(uin)
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info(autoexchange): protocol looks like icq, name: "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ccs->hContact, GCDNF_TCHAR)));
+ char *proto = GetContactProto(ccs->hContact);
+ char svc[64];
+ strcpy(svc, proto);
+ strcat(svc, PS_ICQ_CHECKCAPABILITY);
+
+ if(ServiceExists(svc))
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info(autoexchange, icq): checking for autoexchange icq capability, name: "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ccs->hContact, GCDNF_TCHAR)));
+ ICQ_CUSTOMCAP cap = {0};
+ strcpy(cap.caps, "GPG AutoExchange");
+ if(CallService(svc, (WPARAM)ccs->hContact, (LPARAM)&cap))
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info(autoexchange, icq): sending key requiest, name: "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ccs->hContact, GCDNF_TCHAR)));
+ 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])
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info(autoexchange): protocol looks like jabber, name: "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ccs->hContact, GCDNF_TCHAR)));
+ 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)
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info(autoexchange, jabber): autoexchange capability found, sending key request, name: "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ccs->hContact, GCDNF_TCHAR)));
+ 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);
+ }
+ } */
+ else if(bDebugLog)
+ debuglog<<std::string(time_str()+": info: contact have key, name: "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ccs->hContact, GCDNF_TCHAR)));
+ if(bDebugLog && metaIsProtoMetaContacts(ccs->hContact))
+ debuglog<<std::string(time_str()+": info: protocol is metacontacts, name: "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ccs->hContact, GCDNF_TCHAR)));
+ if(!isContactSecured(ccs->hContact) || metaIsProtoMetaContacts(ccs->hContact))
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info: contact not secured, name: "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ccs->hContact, GCDNF_TCHAR)));
+ mir_free(msg);
+ return CallService(MS_PROTO_CHAINSEND, w, l);
+ }
+ mir_free(msg);
+ //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;
+ HANDLE hContact = (HANDLE)w;
+ if(dbei->flags & DBEF_SENT)
+ {
+ if(isContactSecured(hContact) && strstr((char*)dbei->pBlob, "-----BEGIN PGP MESSAGE-----")) //our service data, can be double added by metacontacts e.t.c.
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info(send handler): block pgp message event, name: "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)));
+ return 1;
+ }
+ if(bAutoExchange && (strstr((char*)dbei->pBlob, "-----PGP KEY RESPONSE-----") || strstr((char*)dbei->pBlob, "-----PGP KEY REQUEST-----"))) ///do not show service data in history
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info(send handler): block pgp key request/response event, name: "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)));
+ return 1;
+ }
+ }
+ if(metaIsProtoMetaContacts(hContact))
+ return 0;
+
+ if(!isContactHaveKey(hContact))
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info: contact have not key, name: "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)));
+ if(bAutoExchange && !strstr((char*)dbei->pBlob, "-----PGP KEY REQUEST-----") && !strstr((char*)dbei->pBlob, "-----BEGIN PGP PUBLIC KEY BLOCK-----") && gpg_valid)
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info: checking for autoexchange possibility, name: "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)));
+ void send_encrypted_msgs_thread(HANDLE hContact);
+ LPSTR proto = GetContactProto(hContact);
+ DWORD uin = db_get_dw(hContact, proto, "UIN", 0);
+ if(uin)
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info(autoexchange): protocol looks like icq, name: "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)));
+ char *proto = GetContactProto(hContact);
+ char svc[64];
+ strcpy(svc, proto);
+ strcat(svc, PS_ICQ_CHECKCAPABILITY);
+
+ if(ServiceExists(svc))
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info(autoexchange, icq): checking for autoexchange icq capability, name: "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)));
+ ICQ_CUSTOMCAP cap = {0};
+ strcpy(cap.caps, "GPG AutoExchange");
+ if(CallService(svc, (WPARAM)hContact, (LPARAM)&cap))
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info(autoexchange, icq): sending key requiest, name: "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)));
+ CallContactService(hContact, PSS_MESSAGE, (dbei->flags & DBEF_UTF) ? PREF_UTF : 0, (LPARAM)"-----PGP KEY REQUEST-----");
+ hcontact_data[hContact].msgs_to_send.push_back((char*)dbei->pBlob);
+ boost::thread *thr = new boost::thread(boost::bind(send_encrypted_msgs_thread, hContact));
+ //TODO: wait for message
+ return 0;
+ }
+ }
+ }
+ else
+ {
+ TCHAR *jid = UniGetContactSettingUtf(hContact, proto, "jid", _T(""));
+ if(jid[0])
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info(autoexchange): protocol looks like jabber, name: "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)));
+ 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)
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info(autoexchange, jabber): autoexchange capability found, sending key request, name: "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)));
+ CallContactService(hContact, PSS_MESSAGE, (dbei->flags & DBEF_UTF) ? PREF_UTF : 0, (LPARAM)"-----PGP KEY REQUEST-----");
+ hcontact_data[hContact].msgs_to_send.push_back((char*)dbei->pBlob);
+ boost::thread *thr = new boost::thread(boost::bind(send_encrypted_msgs_thread, hContact));
+ //mir_free((char*)dbei->pBlob);
+ //TODO: wait for message
+ return 0;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ if(isContactSecured(hContact) && (dbei->flags & DBEF_SENT)) //aggressive outgoing events filtering
+ {
+ DWORD flags;
+ if((dbei->flags & DBEF_UTF) == DBEF_UTF)
+ flags |= PREF_UTF;
+ SendMsgSvc_func(hContact, (char*)dbei->pBlob, flags);
+ //TODO: handle errors somehow ...
+ if(bAppendTags)
+ {
+ string str_event = (char*)dbei->pBlob;
+ //mir_free(dbei->pBlob);
+ str_event.insert(0, toUTF8(outopentag));
+ str_event.append(toUTF8(outclosetag));
+ dbei->pBlob = (PBYTE)mir_strdup(str_event.c_str());
+ dbei->cbBlob = str_event.length() + 1;
+ }
+
+ return 0;
+/* bool stop = false;
+ int count = 0; */
+/* while(!stop)
+ {
+ if(count >= 300)
+ stop = true;
+ 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);
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": event message: \""+(char*)dbei->pBlob+"\" passed event filter, contact "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR))+", message is in allowed list");
+ event_processing_mutex.unlock();
+ return 0;
+ }
+ }
+ event_processing_mutex.unlock();
+ }
+ boost::this_thread::sleep(boost::posix_time::milliseconds(100));
+ count++;
+ } */
+ //return 1;
+ }
+ if(!isContactSecured(hContact))
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": event message: \""+(char*)dbei->pBlob+"\" passed event filter, contact "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR))+" is unsecured");
+ 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-----"))
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info(send handler): block pgp message event, name: "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)));
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+static INT_PTR 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";
+ db_set_ts(NULL, szGPGModuleName, dbsetting.c_str(), tmp);
+ }
+ else
+ db_set_ts(NULL, szGPGModuleName, "szKeyPassword", tmp);
+ }
+ if(password)
+ mir_free(password);
+ password = (TCHAR*)mir_alloc(sizeof(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);
+ db_set_dw(NULL, szGPGModuleName, "PasswordWindowX", key_password_rect.left);
+ db_set_dw(NULL, szGPGModuleName, "PasswordWindowY", key_password_rect.top);
+ }
+ break;
+
+ }
+ return FALSE;
+}
+
+void ShowLoadKeyPasswordWindow()
+{
+ extern HINSTANCE hInst;
+ DialogBox(hInst, MAKEINTRESOURCE(IDD_KEY_PASSWD), NULL, DlgProcKeyPassword);
+}
diff --git a/plugins/New_GPG/src/metacontacts.cpp b/plugins/New_GPG/src/metacontacts.cpp
new file mode 100644
index 0000000000..ab3c60bce5
--- /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 = GetContactProto(hContact);
+ 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 100644
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 100644
index 0000000000..eb65fc8184
--- /dev/null
+++ b/plugins/New_GPG/src/options.cpp
@@ -0,0 +1,1360 @@
+// 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 INT_PTR CALLBACK DlgProcGpgOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static INT_PTR CALLBACK DlgProcGpgBinOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static INT_PTR CALLBACK DlgProcGpgMsgOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static INT_PTR CALLBACK DlgProcGpgAdvOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+BOOL CheckStateLoadDB(HWND hwndDlg, int idCtrl, const char* szSetting, BYTE bDef)
+{
+ BOOL state = db_get_b(NULL, szGPGModuleName, szSetting, bDef);
+ CheckDlgButton(hwndDlg, idCtrl, state);
+ return state;
+}
+
+BOOL CheckStateStoreDB(HWND hwndDlg, int idCtrl, const char* szSetting)
+{
+ BOOL state = IsDlgButtonChecked(hwndDlg, idCtrl);
+ db_set_b(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.ptszTitle = _T(szGPGModuleName);
+ odp.ptszGroup = LPGENT("Services");
+ odp.ptszTab = LPGENT("Main");
+ odp.flags=ODPF_BOLDGROUPS | ODPF_TCHAR;
+ odp.pfnDlgProc = DlgProcGpgOpts;
+ Options_AddPage(wParam, &odp);
+
+ ZeroMemory(&odp, sizeof(odp));
+
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = hInst;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_GPG_BIN);
+ odp.ptszTitle = _T(szGPGModuleName);
+ odp.ptszGroup = LPGENT("Services");
+ odp.ptszTab = LPGENT("GnuPG Variables");
+ odp.flags=ODPF_BOLDGROUPS | ODPF_TCHAR;
+ odp.pfnDlgProc = DlgProcGpgBinOpts;
+ Options_AddPage(wParam, &odp);
+
+ ZeroMemory(&odp, sizeof(odp));
+
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = hInst;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_GPG_MESSAGES);
+ odp.ptszTitle = _T(szGPGModuleName);
+ odp.ptszGroup = LPGENT("Services");
+ odp.ptszTab = LPGENT("Messages");
+ odp.flags=ODPF_BOLDGROUPS | ODPF_TCHAR;
+ odp.pfnDlgProc = DlgProcGpgMsgOpts;
+ Options_AddPage(wParam, &odp);
+
+ ZeroMemory(&odp, sizeof(odp));
+
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = hInst;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_GPG_ADVANCED);
+ odp.ptszTitle = _T(szGPGModuleName);
+ odp.ptszGroup = LPGENT("Services");
+ odp.ptszTab = LPGENT("Advanced");
+ odp.flags=ODPF_BOLDGROUPS | ODPF_TCHAR;
+ odp.pfnDlgProc = 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 INT_PTR 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 = TranslateT("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 = TranslateT("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 = TranslateT("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 = TranslateT("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 = TranslateT("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 = db_find_first(); hContact != NULL; hContact = db_find_next(hContact)) {
+ 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(GetContactProto(hContact));
+ 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(db_get_b(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 = db_find_first(); hcnttmp != NULL; hcnttmp = db_find_next(hcnttmp)) {
+ 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, TranslateT("This key not used by any contact, do you want to remove it from public keyring ?"), TranslateT("Key info"), MB_YESNO) == IDYES)
+ {
+ std::vector<wstring> cmd;
+ string output;
+ DWORD exitcode;
+ cmd.push_back(L"--batch");
+ cmd.push_back(L"--yes");
+ cmd.push_back(L"--delete-key");
+ ptmp = mir_a2t(tmp);
+ cmd.push_back(ptmp);
+ mir_free(ptmp);
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &output;
+ params.code = &exitcode;
+ params.result = &result;
+ if(!gpg_launcher(params))
+ {
+ mir_free(tmp);
+ break;
+ }
+ if(result == pxNotFound)
+ {
+ mir_free(tmp);
+ break;
+ }
+ if(output.find("--delete-secret-keys") != string::npos)
+ MessageBox(0, TranslateT("we have secret key for this public key, do not removing from GPG keyring"), TranslateT("info"), MB_OK);
+ else
+ MessageBox(0, TranslateT("Key removed from GPG keyring"), TranslateT("info"), MB_OK);
+ }
+ mir_free(tmp);
+ if(ismetacontact)
+ {
+ if(MessageBox(0, TranslateT("Do you want to remove key from entire metacontact (all subcontacts) ?"), TranslateT("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)
+ {
+ db_unset(hcnt, szGPGModuleName, "KeyID");
+ db_unset(hcnt, szGPGModuleName, "GPGPubKey");
+ db_unset(hcnt, szGPGModuleName, "KeyMainName");
+ db_unset(hcnt, szGPGModuleName, "KeyType");
+ db_unset(hcnt, szGPGModuleName, "KeyMainEmail");
+ db_unset(hcnt, szGPGModuleName, "KeyComment");
+ setClistIcon(hcnt);
+ setSrmmIcon(hcnt);
+ }
+ }
+ }
+ else
+ {
+ db_unset(hContact, szGPGModuleName, "KeyID");
+ db_unset(hContact, szGPGModuleName, "GPGPubKey");
+ db_unset(hContact, szGPGModuleName, "KeyMainName");
+ db_unset(hContact, szGPGModuleName, "KeyType");
+ db_unset(hContact, szGPGModuleName, "KeyMainEmail");
+ db_unset(hContact, szGPGModuleName, "KeyComment");
+ setClistIcon(hContact);
+ setSrmmIcon(hContact);
+ }
+ }
+ else
+ {
+ db_unset(user_data[item_num+1], szGPGModuleName, "KeyID");
+ db_unset(user_data[item_num+1], szGPGModuleName, "GPGPubKey");
+ db_unset(user_data[item_num+1], szGPGModuleName, "KeyMainName");
+ db_unset(user_data[item_num+1], szGPGModuleName, "KeyType");
+ db_unset(user_data[item_num+1], szGPGModuleName, "KeyMainEmail");
+ db_unset(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, TranslateT("not set"));
+ ListView_SetItemText(hwndList, item_num, 2, TranslateT("not set"));
+ ListView_SetItemText(hwndList, item_num, 1, TranslateT("not set"));
+ break;
+ case IDC_SELECT_KEY:
+ {
+ void ShowFirstRunDialog();
+ ShowFirstRunDialog();
+ }
+ break;
+ case IDC_SAVE_KEY_BUTTON:
+ {
+ tmp = GetFilePath(TranslateT("Export public key"), _T("*"), TranslateT(".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);
+ boost::algorithm::replace_all(str, "\n", "\r\n");
+ HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, str.size() +1);
+ if(!hMem)
+ {
+ MessageBox(0, TranslateT("Failed to alocate memory"), TranslateT("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(TranslateT("Set log file"), _T("*"), TranslateT("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))
+ db_set_b(user_data[item_num+1], szGPGModuleName, "GPGEncryption", 1);
+ else
+ db_set_b(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 bJabberAPI, bFileTransfers;
+ bDebugLog = CheckStateStoreDB(hwndDlg, IDC_DEBUG_LOG, "bDebugLog");
+ if(bDebugLog)
+ debuglog.init();
+ bJabberAPI = CheckStateStoreDB(hwndDlg, IDC_JABBER_API, "bJabberAPI");
+ bool old_bFileTransfers = db_get_b(NULL, szGPGModuleName, "bFileTransfers", 0);
+ bFileTransfers = CheckStateStoreDB(hwndDlg, IDC_FILE_TRANSFERS, "bFileTransfers");
+ if(bFileTransfers != old_bFileTransfers)
+ {
+ db_set_b(NULL, szGPGModuleName, "bSameAction", 0);
+ bSameAction = false;
+ }
+ bAutoExchange = CheckStateStoreDB(hwndDlg, IDC_AUTO_EXCHANGE, "bAutoExchange");
+ {
+ TCHAR tmp[512];
+ GetDlgItemText(hwndDlg, IDC_LOG_FILE_EDIT, tmp, 512);
+ db_set_ts(NULL, szGPGModuleName, "szLogFilePath", tmp);
+ }
+ return TRUE;
+ }
+ }
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+
+static INT_PTR 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(TranslateT("Choose gpg.exe"), "szGpgBinPath", _T("*.exe"), TranslateT("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(""));
+ db_set_ts(NULL, szGPGModuleName, "szGpgBinPath", tmp);
+ string out;
+ DWORD code;
+ std::vector<wstring> cmd;
+ cmd.push_back(L"--version");
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ gpg_launcher(params);
+ db_set_ts(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."), TranslateT("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);
+ PathToAbsolute("\\", 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(TranslateT("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);
+ PathToAbsolute("\\", 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);
+ db_set_ts(NULL, szGPGModuleName, "szGpgBinPath", tmp);
+ GetDlgItemText(hwndDlg, IDC_HOME_DIR, tmp, 512);
+ while(tmp[_tcslen(tmp)-1] == '\\')
+ tmp[_tcslen(tmp)-1] = '\0';
+ db_set_ts(NULL, szGPGModuleName, "szHomePath", tmp);
+ return TRUE;
+ }
+ }
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static INT_PTR 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);
+ db_set_ts(NULL, szGPGModuleName, "szInOpenTag", tmp);
+ mir_free(inopentag);
+ inopentag = (TCHAR*)mir_alloc(sizeof(TCHAR)* (_tcslen(tmp)+1));
+ _tcscpy(inopentag, tmp);
+ GetDlgItemText(hwndDlg, IDC_IN_CLOSE_TAG, tmp, 128);
+ db_set_ts(NULL, szGPGModuleName, "szInCloseTag", tmp);
+ mir_free(inclosetag);
+ inclosetag = (TCHAR*)mir_alloc(sizeof(TCHAR)* (_tcslen(tmp)+1));
+ _tcscpy(inclosetag, tmp);
+ GetDlgItemText(hwndDlg, IDC_OUT_OPEN_TAG, tmp, 128);
+ db_set_ts(NULL, szGPGModuleName, "szOutOpenTag", tmp);
+ mir_free(outopentag);
+ outopentag = (TCHAR*)mir_alloc(sizeof(TCHAR)* (_tcslen(tmp)+1));
+ _tcscpy(outopentag, tmp);
+ GetDlgItemText(hwndDlg, IDC_OUT_CLOSE_TAG, tmp, 128);
+ db_set_ts(NULL, szGPGModuleName, "szOutCloseTag", tmp);
+ mir_free(outclosetag);
+ outclosetag = (TCHAR*)mir_alloc(sizeof(TCHAR)*(_tcslen(tmp)+1));
+ _tcscpy(outclosetag, tmp);
+ }
+ return TRUE;
+ }
+ }
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static INT_PTR 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:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_EXPORT:
+ {
+ INT_PTR ExportGpGKeys(WPARAM w, LPARAM l);
+ ExportGpGKeys(NULL, NULL);
+ }
+ break;
+ case IDC_IMPORT:
+ {
+ INT_PTR ImportGpGKeys(WPARAM w, LPARAM l);
+ ImportGpGKeys(NULL, NULL);
+ }
+ break;
+ default:
+ break;
+ }
+
+ 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;
+
+static LRESULT CALLBACK editctrl_ctrl_a(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ switch(msg) {
+ case WM_KEYDOWN:
+ if(wParam == 0x41 && GetKeyState(VK_CONTROL)< 0 )
+ SendMessage(hwndDlg, EM_SETSEL, 0, -1);
+ return 0;
+ }
+ return mir_callNextSubclass(hwndDlg, editctrl_ctrl_a, msg, wParam, lParam);
+}
+
+static INT_PTR CALLBACK DlgProcLoadPublicKey(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ static HANDLE hContact;
+ TCHAR *tmp = NULL;
+ wstring key_buf;
+ wstring::size_type ws1 = 0, ws2 = 0;
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ hContact = user_data[1];
+ SetWindowPos(hwndDlg, 0, load_key_rect.left, load_key_rect.top, 0, 0, SWP_NOSIZE|SWP_SHOWWINDOW);
+ mir_subclassWindow(GetDlgItem(hwndDlg, IDC_PUBLIC_KEY_EDIT), 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, TranslateT("Turn off encryption"));
+ else
+ {
+ SetDlgItemText(hwndDlg, IDC_ENABLE_ENCRYPTION, TranslateT("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;
+ std::vector<wstring> cmd;
+ cmd.push_back(L"--export");
+ cmd.push_back(L"-a");
+ cmd.push_back(toUTF16(hcontact_data[hcnt].key_in_prescense));
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ gpg_launcher(params); //TODO: handle errors
+ 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 = Translate("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 += Translate(" found in prescense, and exists in keyring.)");
+ SetWindowTextA(hwndDlg, msg.c_str());
+ }
+ else
+ {
+ string msg = Translate("Load Public GPG Key (Key ID: ");
+ msg += hcontact_data[hcnt].key_in_prescense;
+ msg += Translate(" 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, TranslateT("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, TranslateT("Do you want load key for all subcontacts ?"), TranslateT("Metacontact detected"), MB_YESNO) == IDYES)
+ {
+ allsubcontacts = true;
+ int count = metaGetContactsNum(hContact);
+ for(int i = 0; i < count; i++)
+ {
+ hcnt = metaGetSubcontact(hContact, i);
+ if(hcnt)
+ db_set_ts(hcnt, szGPGModuleName, "GPGPubKey", key_buf.substr(ws1,ws2-ws1).c_str());
+ }
+ }
+ else
+ db_set_ts(metaGetMostOnline(hContact), szGPGModuleName, "GPGPubKey", key_buf.substr(ws1,ws2-ws1).c_str());
+ }
+ else
+ db_set_ts(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
+ std::vector<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"));
+ boost::filesystem::remove(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.push_back(L"--batch");
+ cmd.push_back(L"--import");
+ cmd.push_back(tmp2);
+ }
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &output;
+ params.code = &exitcode;
+ params.result = &result;
+ if(!gpg_launcher(params))
+ 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)
+ db_unset(hcnt, szGPGModuleName, "bAlwatsTrust");
+ }
+ }
+ else
+ db_unset(metaGetMostOnline(hContact), szGPGModuleName, "bAlwatsTrust");
+ }
+ else
+ db_unset(hContact, szGPGModuleName, "bAlwatsTrust");
+ }
+ {
+ TCHAR *tmp;
+ if(output.find("already in secret keyring") != string::npos)
+ {
+ MessageBox(0, TranslateT("Key already in scret key ring."), TranslateT("Info"), MB_OK);
+ boost::filesystem::remove(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)*sizeof(char));
+ 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)
+ db_set_s(hcnt, szGPGModuleName, "KeyID", tmp2);
+ }
+ }
+ else
+ db_set_s(metaGetMostOnline(hContact), szGPGModuleName, "KeyID", tmp2);
+ }
+ else
+ db_set_s(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;
+ bool uncommon = false;
+ if((s2 = output.find("(", s)) == string::npos)
+ {
+ if((s2 = output.find("<", s)) == string::npos)
+ {
+ s2 = output.find("â€", s);
+ uncommon = true;
+ }
+ }
+ else if(s2 > output.find("<", s))
+ s2 = output.find("<", s);
+ if(s2 != string::npos && s != string::npos)
+ {
+ tmp2 = (char*)mir_alloc(sizeof(char)*(output.substr(s,s2-s-(uncommon?1:0)).length()+1));
+ strcpy(tmp2, output.substr(s,s2-s-(uncommon?1:0)).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)
+ db_set_s(hcnt, szGPGModuleName, "KeyMainName", output.substr(s,s2-s-1).c_str());
+ }
+ }
+ else
+ db_set_s(metaGetMostOnline(hContact), szGPGModuleName, "KeyMainName", output.substr(s,s2-s-1).c_str());
+ }
+ else
+ db_set_s(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(s != string::npos && s2 != string::npos)
+ {
+ if(output[s] == ')')
+ {
+ tmp2 = (char*)mir_alloc((output.substr(s2,s-s2).length()+1)*sizeof(char));
+ 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)
+ db_set_s(hcnt, szGPGModuleName, "KeyComment", output.substr(s2,s-s2).c_str());
+ }
+ }
+ else
+ db_set_s(metaGetMostOnline(hContact), szGPGModuleName, "KeyComment", output.substr(s2,s-s2).c_str());
+ }
+ else
+ db_set_s(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)
+ db_set_s(hcnt, szGPGModuleName, "KeyMainEmail", output.substr(s,s2-s).c_str());
+ }
+ }
+ else
+ db_set_s(metaGetMostOnline(hContact), szGPGModuleName, "KeyMainEmail", output.substr(s,s2-s).c_str());
+ }
+ else
+ db_set_s(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)
+ db_set_s(hcnt, szGPGModuleName, "KeyMainEmail", output.substr(s2,s-s2).c_str());
+ }
+ }
+ else
+ db_set_s(metaGetMostOnline(hContact), szGPGModuleName, "KeyMainEmail", output.substr(s2,s-s2).c_str());
+ }
+ else
+ db_set_s(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;
+ std::vector<wstring> cmd;
+ cmd.push_back(L"--batch");
+ cmd.push_back(L"-a");
+ cmd.push_back(L"--export");
+ cmd.push_back(fp);
+ mir_free(fp);
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ if(!gpg_launcher(params))
+ break;
+ if(result == pxNotFound)
+ break;
+ string::size_type s = 0;
+ while((s = out.find("\r", s)) != string::npos)
+ {
+ out.erase(s, 1);
+ }
+ db_set_s(hContact, szGPGModuleName, "GPGPubKey", out.c_str());
+ }
+ }
+ tmp = mir_wstrdup(toUTF16(output).c_str());
+ MessageBox(0, tmp, _T(""), MB_OK);
+ mir_free(tmp);
+ boost::filesystem::remove(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))
+ db_set_b(hcnt, szGPGModuleName, "GPGEncryption", 1);
+ else
+ db_set_b(hcnt, szGPGModuleName, "GPGEncryption", 0);
+ setSrmmIcon(hContact);
+ setClistIcon(hContact);
+ }
+ }
+ }
+ else if(!isContactSecured(hContact))
+ db_set_b(metaGetMostOnline(hContact), szGPGModuleName, "GPGEncryption", 1);
+ else
+ db_set_b(metaGetMostOnline(hContact), szGPGModuleName, "GPGEncryption", 0);
+ }
+ else if(!isContactSecured(hContact))
+ db_set_b(hContact, szGPGModuleName, "GPGEncryption", 1);
+ else
+ db_set_b(hContact, szGPGModuleName, "GPGEncryption", 0);
+ }
+ }
+ DestroyWindow(hwndDlg);
+ }
+ break;
+ case ID_LOAD_FROM_FILE:
+ {
+ tmp = GetFilePath(TranslateT("Set file containing GPG public key"), _T("*"), TranslateT("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, TranslateT("Failed to open file"), TranslateT("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();
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info: Failed to read key file");
+ 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, TranslateT("Where is no public or private key."), TranslateT("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);
+ db_set_dw(NULL, szGPGModuleName, "LoadKeyWindowX", load_key_rect.left);
+ db_set_dw(NULL, szGPGModuleName, "LoadKeyWindowY", load_key_rect.top);
+ break;
+ }
+
+ return FALSE;
+}
+
+void ShowLoadPublicKeyDialog()
+{
+ DialogBox(hInst, MAKEINTRESOURCE(IDD_LOAD_PUBLIC_KEY), NULL, DlgProcLoadPublicKey);
+}
diff --git a/plugins/New_GPG/src/resource.h b/plugins/New_GPG/src/resource.h
new file mode 100644
index 0000000000..cd607fb27a
--- /dev/null
+++ b/plugins/New_GPG/src/resource.h
@@ -0,0 +1,116 @@
+//{{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 IDD_ENCRYPTED_FILE_MSG_BOX 114
+#define IDD_EXPORT_TYPE 115
+#define IDD_CHANGE_PASSWD 116
+#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_IGNORE 1026
+#define IDC_OK 1026
+#define IDC_EXPORT 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_DECRYPT 1046
+#define IDC_CANCEL 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_COPY_PUBKEY 1066
+#define IDC_STRIP_TAGS 1067
+#define IDC_CHECK1 1068
+#define IDC_PRESCENSE_SUBSCRIPTION 1068
+#define IDC_REMEMBRE 1068
+#define IDC_REMEMBER 1068
+#define IDC_GENERATING_KEY 1069
+#define IDC_GENERATING_TEXT 1070
+#define IDC_KEY_ID 1071
+#define IDC_COMBO1 1072
+#define IDC_ACCOUNT 1072
+#define IDC_PUBLIC 1073
+#define IDC_PRIVATE 1074
+#define IDC_ALL 1075
+#define IDC_EXPORT_PRIVATE 1076
+#define IDC_CHANGE_PASSWD 1077
+#define IDC_OLD_PASSWD 1078
+#define IDC_NEW_PASSWD1 1079
+#define IDC_NEW_PASSWD2 1080
+
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 117
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1081
+#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 100644
index 0000000000..85e149214e
--- /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 = db_get_b(hContact, szGPGModuleName, "GPGEncryption", 0);
+ if(enc)
+ {
+ db_set_b(hContact, szGPGModuleName, "GPGEncryption", 0);
+ hMeta?db_set_b(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
+ {
+ db_set_b(hContact, szGPGModuleName, "GPGEncryption", 1);
+ hMeta?db_set_b(hMeta, szGPGModuleName, "GPGEncryption", 1):0;
+ setSrmmIcon(hContact);
+ setClistIcon(hContact);
+ return 0;
+ }
+ if(isContactHaveKey(hContact))
+ {
+ db_set_b(hContact, szGPGModuleName, "GPGEncryption", 1);
+ hMeta?db_set_b(hMeta, szGPGModuleName, "GPGEncryption", 1):0;
+ setSrmmIcon(hContact);
+ setClistIcon(hContact);
+ }
+ }
+ return 0;
+}
diff --git a/plugins/New_GPG/src/stdafx.cpp b/plugins/New_GPG/src/stdafx.cpp
new file mode 100644
index 0000000000..e7e41dae3c
--- /dev/null
+++ b/plugins/New_GPG/src/stdafx.cpp
@@ -0,0 +1,18 @@
+/*
+Copyright (C) 2012-13 Miranda NG Project (http://miranda-ng.org)
+
+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 version 2
+of the License.
+
+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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "commonheaders.h" \ No newline at end of file
diff --git a/plugins/New_GPG/src/utilities.cpp b/plugins/New_GPG/src/utilities.cpp
new file mode 100644
index 0000000000..ce78023bdf
--- /dev/null
+++ b/plugins/New_GPG/src/utilities.cpp
@@ -0,0 +1,2238 @@
+// 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 (db_get_ts(hContact, szModule, szSetting, &dbv))
+ return mir_tstrdup(szDef);
+ if(dbv.pszVal)
+ szRes = mir_tstrdup(dbv.ptszVal);
+ db_free(&dbv);
+ return szRes;
+}
+
+char* __stdcall UniGetContactSettingUtf(HANDLE hContact, const char *szModule,const char* szSetting, char* szDef)
+{
+ DBVARIANT dbv = {DBVT_DELETED};
+ char* szRes;
+ if (db_get_s(hContact, szModule, szSetting, &dbv))
+ return mir_strdup(szDef);
+ if(dbv.pszVal)
+ szRes = mir_strdup(dbv.pszVal);
+ db_free(&dbv);
+ return szRes;
+}
+
+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;
+ db_set_ts(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))
+ {
+ db_set_ts(NULL, szGPGModuleName, "szHomePath", path);
+ }
+ IMalloc * imalloc = 0;
+ if (SUCCEEDED(SHGetMalloc(&imalloc)))
+ {
+ imalloc->Free(pidl);
+ imalloc->Release();
+ }
+ }
+}
+
+INT_PTR LoadKey(WPARAM w, LPARAM l)
+{
+ void ShowLoadPublicKeyDialog();
+ extern map<int, HANDLE> user_data;
+ user_data[1] = (HANDLE)w;
+ ShowLoadPublicKeyDialog();
+ return 0;
+}
+
+INT_PTR SendKey(WPARAM w, LPARAM l)
+{
+ HANDLE hContact = (HANDLE)w;
+ if(metaIsProtoMetaContacts(hContact))
+ hContact = metaGetMostOnline(hContact);
+ char *szMessage;
+ std::string key_id_str;
+ {
+ LPSTR proto = GetContactProto(hContact);
+ PROTOACCOUNT *acc = (PROTOACCOUNT*)CallService(MS_PROTO_GETACCOUNT, 0, (LPARAM)proto);
+ std::string acc_str;
+ if(acc)
+ {
+ acc_str = toUTF8(acc->tszAccountName);
+ acc_str += "(";
+ acc_str += acc->szModuleName;
+ acc_str += ")" ;
+ key_id_str = acc_str;
+ key_id_str += "_KeyID";
+ acc_str += "_GPGPubKey";
+ }
+ szMessage = UniGetContactSettingUtf(NULL, szGPGModuleName, acc_str.empty()?"GPGPubKey":acc_str.c_str(), "");
+ if(!szMessage[0])
+ {
+ mir_free(szMessage);
+ szMessage = UniGetContactSettingUtf(NULL, szGPGModuleName, "GPGPubKey", ""); //try to get default key as fallback in any way
+ }
+ }
+ if(szMessage[0])
+ {
+ BYTE enc = db_get_b(hContact, szGPGModuleName, "GPGEncryption", 0);
+ db_set_b(hContact, szGPGModuleName, "GPGEncryption", 0);
+ CallContactService(hContact, PSS_MESSAGE, PREF_UTF, (LPARAM)szMessage);
+ std::string msg = "Public key ";
+ char *keyid = UniGetContactSettingUtf(NULL, szGPGModuleName, key_id_str.c_str(), "");
+ if(!keyid[0])
+ {
+ mir_free(keyid);
+ keyid = UniGetContactSettingUtf(NULL, szGPGModuleName, "KeyID", "");
+ }
+ msg += keyid;
+ mir_free(keyid);
+ msg += " sent";
+ mir_free(szMessage);
+ szMessage = mir_strdup(msg.c_str());
+ HistoryLog(hContact, db_event(szMessage, 0, 0, DBEF_SENT));
+ db_set_b(hContact, szGPGModuleName, "GPGEncryption", enc);
+ }
+ else
+ mir_free(szMessage);
+ return 0;
+}
+
+extern HANDLE hLoadPublicKey;
+extern HGENMENU hToggleEncryption, hSendKey;
+
+INT_PTR ToggleEncryption(WPARAM w, LPARAM l)
+{
+ HANDLE hContact = (HANDLE)w;
+ BYTE enc = 0;
+ if(metaIsProtoMetaContacts(hContact))
+ enc = db_get_b(metaGetMostOnline(hContact), szGPGModuleName, "GPGEncryption", 0);
+ else
+ enc = db_get_b(hContact, szGPGModuleName, "GPGEncryption", 0);
+ if(metaIsProtoMetaContacts(hContact))
+ {
+ HANDLE hcnt = NULL;
+ if(MessageBox(0, TranslateT("Do you want to toggle encryption for all subcontacts ?"), TranslateT("Metacontact detected"), MB_YESNO) == IDYES)
+ {
+ int count = metaGetContactsNum(hContact);
+ for(int i = 0; i < count; i++)
+ {
+ hcnt = metaGetSubcontact(hContact, i);
+ if(hcnt)
+ db_set_b(hcnt, szGPGModuleName, "GPGEncryption", enc?0:1);
+ }
+ db_set_b(hContact, szGPGModuleName, "GPGEncryption", enc?0:1);
+ }
+ }
+ else
+ db_set_b(hContact, szGPGModuleName, "GPGEncryption", enc?0:1);
+ void setSrmmIcon(HANDLE hContact);
+ void setClistIcon(HANDLE hContact);
+ setSrmmIcon(hContact);
+ setClistIcon(hContact);
+ enc = enc?0:1;
+ CLISTMENUITEM mi = { sizeof(mi) };
+ mi.flags = CMIM_NAME;
+ enc?mi.pszName="Turn off GPG encryption":mi.pszName="Turn on GPG encryption";
+ Menu_ModifyItem(hToggleEncryption, &mi);
+ return 0;
+}
+
+int OnPreBuildContactMenu(WPARAM w, LPARAM l)
+{
+ HANDLE hContact = (HANDLE)w;
+ if(metaIsProtoMetaContacts(hContact))
+ hContact = metaGetMostOnline(hContact);
+
+ {
+ CLISTMENUITEM mi2 = { sizeof(mi2) };
+ LPSTR proto = GetContactProto(hContact);
+ PROTOACCOUNT *acc = (PROTOACCOUNT*)CallService(MS_PROTO_GETACCOUNT, 0, (LPARAM)proto);
+ std::string setting;
+ if(acc)
+ {
+ setting = toUTF8(acc->tszAccountName);
+ setting += "(";
+ setting += acc->szModuleName;
+ setting += ")" ;
+ setting += "_KeyID";
+ }
+ char *keyid = keyid = UniGetContactSettingUtf(NULL, szGPGModuleName, setting.c_str(), "");
+ if(!keyid[0])
+ {
+ mir_free(keyid);
+ keyid = UniGetContactSettingUtf(NULL, szGPGModuleName, "KeyID", "");
+ }
+ TCHAR buf[128] = {0};
+ mir_sntprintf(buf, 127 * sizeof(TCHAR), _T("%s: %s"), TranslateT("Send publick key"), toUTF16(keyid).c_str());
+ mi2.ptszName = buf;
+ mi2.flags = CMIM_NAME | CMIF_TCHAR;
+ Menu_ModifyItem(hSendKey, &mi2);
+ }
+ CLISTMENUITEM mi = { sizeof(mi) };
+ mi.flags = CMIM_NAME;
+ TCHAR *tmp = UniGetContactSettingUtf(hContact, szGPGModuleName, "GPGPubKey", _T(""));
+ if(_tcslen(tmp) < 1)
+ {
+ db_unset(hContact, szGPGModuleName, "GPGEncryption");
+ mi.flags += CMIM_FLAGS | CMIF_GRAYED;
+ }
+ else
+ mi.flags = CMIM_NAME | CMIM_FLAGS;
+ mi.pszName = db_get_b(hContact, szGPGModuleName, "GPGEncryption", 0)?"Turn off GPG encryption":"Turn on GPG encryption";
+ Menu_ModifyItem(hToggleEncryption, &mi);
+ return 0;
+}
+
+
+list<wstring> transfers;
+
+DWORD file_msg_state = -1;
+
+int onProtoAck(WPARAM w, LPARAM l)
+{
+ ACKDATA *ack=(ACKDATA*)l;
+ CCSDATA *ccs=(CCSDATA*)ack->lParam;
+
+ if(ack->type == ACKTYPE_FILE)
+ {
+ switch(ack->result)
+ {
+ case ACKRESULT_DENIED: case ACKRESULT_FAILED:
+ break;
+ case ACKRESULT_SUCCESS:
+ {
+ PROTOFILETRANSFERSTATUS *f = (PROTOFILETRANSFERSTATUS*) ack->hProcess;
+ if((f->flags & PFTS_SENDING) != PFTS_SENDING)
+ {
+ 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(!bFileTransfers && !bSameAction)
+ {
+ void ShowEncryptedFileMsgBox();
+ ShowEncryptedFileMsgBox();
+ }
+ if(!bFileTransfers && bSameAction)
+ return 0;
+ if(file_msg_state < 1)
+ return 0;
+ HistoryLog(ack->hContact, db_event("Recieved encrypted file, trying to decrypt", 0,0, 0));
+ if(!boost::filesystem::exists(f->tszCurrentFile))
+ return 0;
+ string out;
+ DWORD code;
+ pxResult result;
+ std::vector<wstring> cmd;
+ cmd.push_back(L"-o");
+ wstring file = filename;
+ wstring::size_type p1 = file.rfind(_T(".gpg"));
+ file.erase(p1, _tcslen(_T(".gpg")));
+ if(boost::filesystem::exists(file))
+ {
+ if(MessageBox(0, TranslateT("Target file exists, do you want to replace it ?"), TranslateT("Warning"), MB_YESNO) == IDNO)
+ return 0;
+ }
+ cmd.push_back(file);
+ boost::filesystem::remove(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 && bDebugLog)
+ debuglog<<std::string(time_str()+": info: found password in database for key id: "+keyid+", trying to decrypt message from "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ack->hContact, GCDNF_TCHAR))+" with password");
+ }
+ else
+ {
+ pass = UniGetContactSettingUtf(NULL, szGPGModuleName, "szKeyPassword", _T(""));
+ if(_tcslen(pass) > 0 && bDebugLog)
+ debuglog<<std::string(time_str()+": info: found password for all keys in database, trying to decrypt message from "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ack->hContact, GCDNF_TCHAR))+" with password");
+ }
+ if(_tcslen(pass) > 0)
+ {
+ cmd.push_back(L"--passphrase");
+ cmd.push_back(pass);
+ }
+ else if(password)
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info: found password in memory, trying to decrypt message from "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ack->hContact, GCDNF_TCHAR))+" with password");
+ cmd.push_back(L"--passphrase");
+ cmd.push_back(password);
+ }
+ else if (bDebugLog)
+ debuglog<<std::string(time_str()+": info: passwords not found in database or memory, trying to decrypt message from "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ack->hContact, GCDNF_TCHAR))+" with out password");
+ mir_free(pass);
+ mir_free(keyid);
+ }
+ cmd.push_back(L"-d");
+ cmd.push_back(filename);
+ gpg_execution_params params(cmd);
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ if(!gpg_launcher(params, boost::posix_time::minutes(15)))
+ 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;
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info: failed to decrypt messaage from "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ack->hContact, GCDNF_TCHAR))+" password needed, trying to get one");
+ 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))
+ db_set_s(metaGetMostOnline(ack->hContact), szGPGModuleName, "InKeyID", out.substr(s, s2-s).c_str());
+ else
+ db_set_s(ack->hContact, szGPGModuleName, "InKeyID", out.substr(s, s2-s).c_str());
+ }
+ void ShowLoadKeyPasswordWindow();
+ new_key_hcnt_mutex.lock();
+ new_key_hcnt = ack->hContact;
+ ShowLoadKeyPasswordWindow();
+ std::vector<wstring> cmd2 = cmd;
+ if(password)
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info: found password in memory, trying to decrypt message from "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ack->hContact, GCDNF_TCHAR)));
+ std::vector<wstring> tmp;
+ tmp.push_back(L"--passphrase");
+ tmp.push_back(password);
+ cmd2.insert(cmd2.begin(), tmp.begin(), tmp.end());
+ }
+ out.clear();
+ gpg_execution_params params(cmd2);
+ //pxResult result;
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ if(!gpg_launcher(params, boost::posix_time::seconds(15)))
+ {
+ //boost::filesystem::remove(filename);
+ return 0;
+ }
+ if(result == pxNotFound)
+ {
+ //boost::filesystem::remove(filename);
+ return 0;
+ }
+ }
+ if(result == pxSuccess)
+ boost::filesystem::remove(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;
+ std::vector<wstring> cmd;
+ cmd.push_back(L"--batch");
+ cmd.push_back(L"--tes");
+ cmd.push_back(L"-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.push_back(szKeyid);
+ if(db_get_b(hcnt, szGPGModuleName, "bAlwaysTrust", 0))
+ {
+ cmd.push_back(L"--trust-model");
+ cmd.push_back(L"always");
+ }
+ mir_free(szKeyid);
+ mir_free(keyid);
+ cmd.push_back(L"-o");
+ TCHAR *temp = _tgetenv(_T("TEMP"));
+ cmd.push_back(wstring(temp) + L"\\" + file_out);
+ wstring path_out = temp;
+ path_out += _T("\\");
+ path_out += file_out;
+ boost::filesystem::remove(path_out);
+ cmd.push_back(L"-e");
+ cmd.push_back(filename);
+ gpg_execution_params params(cmd);
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ delete [] file_out;
+ if(!gpg_launcher(params, boost::posix_time::minutes(3)))
+ return 0;
+ if(out.find("There is no assurance this key belongs to the named user") != string::npos)
+ {
+ out.clear();
+ if(MessageBox(0, TranslateT("We trying to encrypt with untrusted key, do you want to trust this key permanently ?"), TranslateT("Warning"), MB_YESNO) == IDYES)
+ {
+ db_set_b(hcnt, szGPGModuleName, "bAlwaysTrust", 1);
+ std::vector<std::wstring> tmp;
+ tmp.push_back(L"--trust-model");
+ tmp.push_back(L"always");
+ cmd.insert(cmd.begin(), tmp.begin(), tmp.end());
+ if(!gpg_launcher(params, boost::posix_time::minutes(3)))
+ return 0;
+ }
+ else
+ return 0;
+ }
+ return path_out;
+}
+
+//from secureim partially
+INT_PTR onSendFile(WPARAM w, LPARAM l)
+{
+ if(!bFileTransfers)
+ return CallService(MS_PROTO_CHAINSEND, w, l);
+ CCSDATA *ccs=(CCSDATA*)l;
+ if(isContactSecured(ccs->hContact))
+ {
+ char *proto = GetContactProto(ccs->hContact);
+ DWORD uin = db_get_dw(ccs->hContact, proto, "UIN", 0);
+ bool cap_found = false, supported_proto = false;
+ if(uin)
+ {
+ char svc[64];
+ strcpy(svc, proto);
+ strcat(svc, PS_ICQ_CHECKCAPABILITY);
+ if(ServiceExists(svc))
+ {
+ supported_proto = true;
+ ICQ_CUSTOMCAP cap = {0};
+ strcpy(cap.caps, "GPG FileTransfer");
+ if(CallService(svc, (WPARAM)ccs->hContact, (LPARAM)&cap))
+ cap_found = true;
+ }
+ }
+ 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)
+ {
+ supported_proto = true;
+ 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_Encrypted_FileTransfers:0")) != string::npos)
+ cap_found = true;
+ }
+ }
+ }
+ }
+ if(supported_proto && !cap_found)
+ {
+ if(MessageBox(0, TranslateT("Capability to decrypt file not found on other side\nRecipient may be unable to decrypt file(s)\nDo you want to encrypt file(s) anyway?"), TranslateT("Filetransfer warning"), MB_YESNO) == IDNO)
+ return CallService(MS_PROTO_CHAINSEND, w, l);
+ }
+ if(!supported_proto)
+ {
+ if(MessageBox(0, TranslateT("Unable to check encryption support on other side\nRecipient may be unable to decrypt file(s)\nCurrently capability check supported only for ICQ and Jabber protocols.\nIt will work for any other proto if Miranda with new_gpg used on other side.\nDo you want to encrypt file(s) anyway?"), TranslateT("Filetransfer warning"), MB_YESNO) == IDNO)
+ return CallService(MS_PROTO_CHAINSEND, w, l);
+ }
+ HistoryLog(ccs->hContact, db_event(Translate("encrypting file for transfer"), 0, 0, DBEF_SENT));
+ 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(!boost::filesystem::exists(file[i]))
+ 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(!boost::filesystem::exists(file[i]))
+ 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 HistoryLog(HANDLE hContact, db_event evt)
+{
+ DBEVENTINFO Event = { 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);
+ db_event_add(hContact, &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);
+ LPCTSTR attr = xi.getAttrValue(local_node, _T("to"));
+ if(attr)
+ {
+ HANDLE hContact = ji->Sys()->ContactFromJID(attr);
+ if(hContact)
+ if(!isContactSecured(hContact))
+ return FALSE;
+ }
+ 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+=3;
+ wstring::size_type p2 = data.find(_T("-----END PGP MESSAGE-----"));
+ wstring data2 = data.substr(p1, p2-p1-2);
+ strip_line_term(data2);
+ HXML encrypted_data = xi.addChild(node, _T("x"), data2.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;
+ boost::filesystem::remove(path_out);
+ wfstream f(path_out.c_str(), std::ios::out);
+ f<<toUTF8(str).c_str();
+ f.close();
+ if(!boost::filesystem::exists(path_out))
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info: Failed to write prescense in file");
+ return FALSE;
+ }
+ {
+ extern TCHAR *password;
+ string out;
+ DWORD code;
+ std::vector<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] && bDebugLog)
+ debuglog<<std::string(time_str()+": info: found password in database for key id: "+inkeyid+", trying to encrypt message from self with password");
+ }
+ else
+ {
+ pass = UniGetContactSettingUtf(NULL, szGPGModuleName, "szKeyPassword", _T(""));
+ if(pass[0] && bDebugLog)
+ debuglog<<std::string(time_str()+": info: found password for all keys in database, trying to encrypt message from self with password");
+ }
+ if(pass[0])
+ {
+ cmd.push_back(L"--passphrase");
+ cmd.push_back(pass);
+ }
+ else if(password)
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info: found password in memory, trying to encrypt message from self with password");
+ cmd.push_back(L"--passphrase");
+ cmd.push_back(password);
+ }
+ else if (bDebugLog)
+ debuglog<<std::string(time_str()+": info: passwords not found in database or memory, trying to encrypt message from self with out password");
+ mir_free(pass);
+ mir_free(inkeyid);
+ }
+ cmd.push_back(L"--local-user");
+ path_c = UniGetContactSettingUtf(NULL, szGPGModuleName, "KeyID", _T(""));
+ cmd.push_back(path_c);
+ cmd.push_back(L"--default-key");
+ cmd.push_back(path_c);
+ mir_free(path_c);
+ cmd.push_back(L"--batch");
+ cmd.push_back(L"--yes");
+ cmd.push_back(L"-abs");
+ cmd.push_back(path_out);
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ gpg_launcher(params, boost::posix_time::seconds(15)); // TODO: handle errors
+ boost::filesystem::remove(path_out);
+ 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();
+ boost::filesystem::remove(path_out);
+ }
+ if(data.empty())
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info: Failed to read prescense sign from file");
+ return FALSE;
+ }
+ if(data.find(_T("-----BEGIN PGP SIGNATURE-----")) != wstring::npos && data.find(_T("-----END PGP SIGNATURE-----")) != wstring::npos)
+ {
+ wstring::size_type p1 = data.find(_T("-----BEGIN PGP SIGNATURE-----")) + _tcslen(_T("-----BEGIN PGP SIGNATURE-----"));
+ 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;
+ p1++;
+ wstring::size_type p2 = data.find(_T("-----END PGP SIGNATURE-----"));
+ {
+ std::wstring tmp = data.substr(p1, p2-p1);
+ strip_line_term(tmp);
+ HXML encrypted_data = xi.addChild(node, _T("x"), tmp.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")))
+ {
+ std::wstring status_str;
+ HXML local_node2 = node;
+ for(int n = 0; n <= xi.getChildCount(node); n++)
+ {
+ LPCTSTR nodename2 = xi.getName(local_node2);
+ if(_tcsstr(nodename2, _T("status")))
+ {
+ LPCTSTR status = xi.getText(local_node2);
+ if(status)
+ status_str = status;
+ break;
+ }
+ local_node2 = xi.getChild(node, n);
+ }
+ LPCTSTR data = xi.getText(local_node);
+ wstring sign = _T("-----BEGIN PGP SIGNATURE-----\n\n");
+ wstring file = toUTF16(get_random(10)), status_file = toUTF16(get_random(10));
+ sign += data;
+ sign += _T("\n-----END PGP SIGNATURE-----\n");
+ TCHAR *path_c = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T(""));
+ wstring path_out = path_c, status_file_out = path_c;
+ mir_free(path_c);
+ path_out += L"\\tmp\\";
+ path_out += file;
+ path_out += L".sig";
+ status_file_out += L"\\tmp\\";
+ status_file_out += status_file;
+ status_file_out += L".status";
+// sign_file_mutex.lock();
+ boost::filesystem::remove(path_out);
+ boost::filesystem::remove(status_file_out);
+ 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();
+ f.open(status_file_out.c_str(), std::ios::out);
+ while(!f.is_open())
+ f.open(status_file_out.c_str(), std::ios::out);
+ f<<toUTF8(status_str).c_str();
+ f.close();
+ if(!boost::filesystem::exists(path_out))
+ {
+// sign_file_mutex.unlock();
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": info: Failed to write sign in file");
+ return FALSE;
+ }
+ { //gpg
+ string out;
+ DWORD code;
+ std::vector<wstring> cmd;
+ cmd.push_back(L"--verify");
+ cmd.push_back(L"-a");
+ cmd.push_back(path_out);
+ cmd.push_back(status_file_out);
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ if(!gpg_launcher(params, boost::posix_time::seconds(15)))
+ {
+ return FALSE;
+ }
+ if(result == pxNotFound)
+ {
+ return FALSE;
+ }
+ boost::filesystem::remove(path_out);
+ boost::filesystem::remove(status_file_out);
+ 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 plugin for Miranda IM and Miranda NG)"));
+ (*p)->getJabberInterface()->Net()->AddFeatures(_T("GPG_Key_Auto_Exchange:0\0\0"));
+ }
+ if(bFileTransfers)
+ {
+ (*p)->getJabberInterface()->Net()->RegisterFeature(_T("GPG_Encrypted_FileTransfers:0"), _T("Indicates that gpg installed and configured to encrypt files (currently implemented in new_gpg plugin for Miranda IM and Miranda NG)"));
+ (*p)->getJabberInterface()->Net()->AddFeatures(_T("GPG_Encrypted_FileTransfers:0\0\0"));
+ }
+ }
+}
+
+bool isContactSecured(HANDLE hContact)
+{
+ BYTE gpg_enc = db_get_b(hContact, szGPGModuleName, "GPGEncryption", 0);
+ if(!gpg_enc)
+ {
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": encryption is turned off for "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)));
+ return false;
+ }
+ if(!metaIsProtoMetaContacts(hContact))
+ {
+ TCHAR *key = UniGetContactSettingUtf(hContact, szGPGModuleName, "GPGPubKey", _T(""));
+ if(!key[0])
+ {
+ mir_free(key);
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": encryption is turned off for "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)));
+ return false;
+ }
+ mir_free(key);
+ }
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": encryption is turned on for "+toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)));
+ 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);
+ PathToAbsolute("\\", 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)
+ {
+ db_set_ts(NULL, szGPGModuleName, "szGpgBinPath", tmp);
+ string out;
+ DWORD code;
+ std::vector<wstring> cmd;
+ cmd.push_back(L"--version");
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ gpg_valid = true;
+ gpg_launcher(params);
+ 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(db_get_b(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 = GetContactProto(hContact);//szGPGModuleName;
+ ack.hContact = hContact;
+ ack.type = type;
+ ack.result = result;
+ ack.hProcess = (HANDLE)777;//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)
+ {
+ if(bDebugLog)
+ 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)
+ {
+ if(bDebugLog)
+ 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, 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 = !db_get_b(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, 0, (LPARAM)&enm) == -1)
+ return false;
+
+ return found;
+}
+
+void ExportGpGKeysFunc(int type)
+{
+ TCHAR *p = GetFilePath(_T("Choose file to export keys"), _T("*"), _T("Any file"), true);
+ if(!p || !p[0])
+ {
+ delete [] p;
+ //TODO: handle error
+ return;
+ }
+ 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; //TODO: handle error
+ if(!type || type == 2) {
+ for(HANDLE hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) {
+ 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*)GetContactProto(hContact);
+ 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(type == 1 || type == 2)
+ {
+ string out;
+ DWORD code;
+ pxResult result;
+ std::vector<wstring> cmd;
+ cmd.push_back(L"--batch");
+ cmd.push_back(L"-export-secret-keys");
+ cmd.push_back(L"-a");
+ gpg_execution_params params(cmd);
+ params.out = &out;
+ params.code = &code;
+ params.result = &result;
+ gpg_launcher(params); //TODO: handle errors
+ {
+ file<<out;
+ file<<std::endl;
+ }
+ }
+ if(file.is_open())
+ file.close();
+ char msg[512];
+ if(type == 2)
+ mir_snprintf(msg, 511, "%s %d %s %s %s", Translate("we have succesfully exported"), exported_keys, Translate("public keys"), Translate("and"), Translate("all private keys"));
+ else if(type == 1)
+ mir_snprintf(msg, 511, "%s %s", Translate("we have succesfully exported"), Translate("all private keys"));
+ else if(!type)
+ mir_snprintf(msg, 511, "%s %d %s",Translate("we have succesfully exported"), exported_keys, Translate("public keys"));
+ MessageBoxA(NULL, msg, Translate("Keys export result"), MB_OK);
+}
+
+INT_PTR ExportGpGKeys(WPARAM w, LPARAM l)
+{
+ void ShowExportKeysDlg();
+ ShowExportKeysDlg();
+ return 0;
+}
+
+INT_PTR 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, processed_private_keys = 0;
+ ProtoEnumAccounts(&acc_count, &accs);
+ char line[256];
+ file.getline(line, 255);
+ if(!strstr(line, "-----BEGIN PGP PUBLIC KEY BLOCK-----") && !strstr(line, "-----BEGIN PGP PRIVATE 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-----"))
+ {
+ 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 = db_find_first(acc.c_str()); hContact; hContact = db_find_next(hContact, 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 path;
+ std::vector<std::wstring> cmd;
+ TCHAR *ptmp;
+ string output;
+ DWORD exitcode;
+ {
+ HANDLE hcnt = hContact;
+ ptmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T(""));
+ path = ptmp;
+ mir_free(ptmp);
+ mir_free(ptmp);
+ wstring rand = toUTF16(get_random(10));
+ path += L"\\";
+ path += rand;
+ boost::filesystem::remove(path);
+ wfstream f(path, std::ios::out);
+ f<<toUTF16(key).c_str();
+ f.close();
+ cmd.push_back(L"--batch");
+ cmd.push_back(L"--import");
+ cmd.push_back(path);
+ }
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &output;
+ params.code = &exitcode;
+ params.result = &result;
+ if(!gpg_launcher(params))
+ break;
+ if(result == pxNotFound)
+ break;
+ if(result == pxSuccess)
+ processed_keys++;
+ {
+ if(output.find("already in secret keyring") != string::npos)
+ {
+ MessageBox(0, TranslateT("Key already in scret key ring."), TranslateT("Info"), MB_OK);
+ boost::filesystem::remove(path);
+ 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) * sizeof(char));
+ strcpy(tmp2, output.substr(s,s2-s).c_str());
+ mir_utf8decode(tmp2, 0);
+ db_set_s(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 = (char*)mir_alloc((output.substr(s,s2-s-1).length()+1) * sizeof(char));
+ strcpy(tmp2, output.substr(s,s2-s-1).c_str());
+ mir_utf8decode(tmp2, 0);
+ if(hContact)
+ {
+ db_set_s(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 = (char*)mir_alloc((output.substr(s2,s-s2).length()+1) * sizeof(char));
+ strcpy(tmp2, output.substr(s2,s-s2).c_str());
+ mir_utf8decode(tmp2, 0);
+ if(hContact)
+ db_set_s(hContact, szGPGModuleName, "KeyComment", output.substr(s2,s-s2).c_str());
+ mir_free(tmp2);
+ s+=3;
+ s2 = output.find(">", s);
+ tmp2 = (char*)mir_alloc((output.substr(s,s2-s).length()+1) * sizeof(char));
+ strcpy(tmp2, output.substr(s,s2-s).c_str());
+ mir_utf8decode(tmp2, 0);
+ if(hContact)
+ db_set_s(hContact, szGPGModuleName, "KeyMainEmail", output.substr(s,s2-s).c_str());
+ mir_free(tmp2);
+ }
+ else
+ {
+ tmp2 = (char*)mir_alloc((output.substr(s2,s-s2).length()+1) * sizeof(char));
+ strcpy(tmp2, output.substr(s2,s-s2).c_str());
+ mir_utf8decode(tmp2, 0);
+ if(hContact)
+ db_set_s(hContact, szGPGModuleName, "KeyMainEmail", output.substr(s2,s-s2).c_str());
+ mir_free(tmp2);
+ }
+ }
+ db_set_b(hContact, szGPGModuleName, "GPGEncryption", 1);
+ db_set_ts(hContact, szGPGModuleName, "GPGPubKey", toUTF16(key).c_str());
+ }
+ boost::filesystem::remove(path);
+ break;
+ }
+ }
+ }
+ key.clear();
+ }
+ if(strstr(line, "-----END PGP PRIVATE KEY BLOCK-----"))
+ {
+ std::vector<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"));
+ boost::filesystem::remove(tmp2);
+ wfstream f(tmp2, std::ios::out);
+ f<<toUTF16(key).c_str();
+ f.close();
+ cmd.push_back(L"--batch");
+ cmd.push_back(L"--import");
+ cmd.push_back(tmp2);
+ }
+ gpg_execution_params params(cmd);
+ pxResult result;
+ params.out = &output;
+ params.code = &exitcode;
+ params.result = &result;
+ if(!gpg_launcher(params))
+ break;
+ if(result == pxNotFound)
+ break;
+ if(result == pxSuccess)
+ processed_private_keys++;
+ key.clear();
+ }
+ }
+ if(file.is_open())
+ file.close();
+ char msg[512];
+ if(processed_private_keys)
+ mir_snprintf(msg, 511, "we have succesfully processed %d public keys and some private keys", processed_keys);
+ else
+ mir_snprintf(msg, 511, "we have succesfully processed %d public keys", processed_keys);
+ MessageBoxA(NULL, msg, Translate("Keys import result"), MB_OK);
+ return 0;
+}
+
+void fix_line_term(std::string &s)
+{
+ if(s.empty())
+ return;
+ boost::algorithm::erase_all(s, "\r\r");
+}
+
+void fix_line_term(std::wstring &s)
+{
+ if(s.empty())
+ return;
+ boost::algorithm::erase_all(s, _T("\r\r"));
+}
+
+void strip_line_term(std::wstring &s)
+{
+ if(s.empty())
+ return;
+ boost::algorithm::erase_all(s, _T("\r"));
+ boost::algorithm::erase_all(s, _T("\n"));
+}
+
+void strip_line_term(std::string &s)
+{
+ if(s.empty())
+ return;
+ boost::algorithm::erase_all(s, "\r");
+ boost::algorithm::erase_all(s, "\n");
+}
+
+void strip_tags(std::wstring &str)
+{
+ if(str.empty())
+ return;
+ boost::algorithm::erase_all(str, inopentag);
+ boost::algorithm::erase_all(str, inclosetag);
+ boost::algorithm::erase_all(str, outopentag);
+ boost::algorithm::erase_all(str, outclosetag);
+}
+
+
+static INT_PTR CALLBACK DlgProcEncryptedFileMsgBox(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ char *inkeyid = NULL;
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ file_msg_state = -1;
+ return TRUE;
+ }
+
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_IGNORE:
+ if(IsDlgButtonChecked(hwndDlg, IDC_REMEMBER))
+ {
+ db_set_b(NULL, szGPGModuleName, "bSameAction", 1);
+ bSameAction = true;
+ }
+ DestroyWindow(hwndDlg);
+ break;
+
+ case IDC_DECRYPT:
+ file_msg_state = 1;
+ if(IsDlgButtonChecked(hwndDlg, IDC_REMEMBER))
+ {
+ db_set_b(NULL, szGPGModuleName, "bFileTransfers", 1);
+ bFileTransfers = true;
+ db_set_b(NULL, szGPGModuleName, "bSameAction", 0);
+ bSameAction = false;
+ }
+
+ DestroyWindow(hwndDlg);
+ break;
+
+ default:
+ break;
+ }
+
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+ }
+ break;
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+ case WM_DESTROY:
+ {
+ }
+ break;
+ }
+ return FALSE;
+}
+
+
+void ShowEncryptedFileMsgBox()
+{
+ extern HINSTANCE hInst;
+ DialogBox(hInst, MAKEINTRESOURCE(IDD_ENCRYPTED_FILE_MSG_BOX), NULL, DlgProcEncryptedFileMsgBox);
+}
+
+
+static INT_PTR CALLBACK DlgProcExportKeys(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ return TRUE;
+ }
+
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_OK:
+ if(IsDlgButtonChecked(hwndDlg, IDC_PUBLIC))
+ ExportGpGKeysFunc(0);
+ else if(IsDlgButtonChecked(hwndDlg, IDC_PRIVATE))
+ ExportGpGKeysFunc(1);
+ else if(IsDlgButtonChecked(hwndDlg, IDC_ALL))
+ ExportGpGKeysFunc(2);
+ DestroyWindow(hwndDlg);
+ break;
+
+ case IDC_CANCEL:
+ DestroyWindow(hwndDlg);
+ break;
+
+ default:
+ break;
+ }
+
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+ }
+ break;
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+ case WM_DESTROY:
+ {
+ }
+ break;
+ }
+ return FALSE;
+}
+
+void ShowExportKeysDlg()
+{
+ extern HINSTANCE hInst;
+ DialogBox(hInst, MAKEINTRESOURCE(IDD_EXPORT_TYPE), NULL, DlgProcExportKeys);
+}
+
+static INT_PTR CALLBACK DlgProcChangePasswd(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ return TRUE;
+ }
+
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_OK:
+ //TODO: show some prgress
+ {
+ std::string old_pass, new_pass;
+ extern TCHAR key_id_global[17];
+ TCHAR buf[256] = {0};
+ GetDlgItemText(hwndDlg, IDC_NEW_PASSWD1, buf, 255);
+ new_pass = toUTF8(buf);
+ GetDlgItemText(hwndDlg, IDC_NEW_PASSWD2, buf, 255);
+ if(new_pass != toUTF8(buf))
+ {
+ MessageBox(hwndDlg, TranslateT("New passwords not match"), TranslateT("Error"), MB_OK);
+ //key_id_global[0] = 0;
+ break;
+ }
+ GetDlgItemText(hwndDlg, IDC_OLD_PASSWD, buf, 255);
+ old_pass = toUTF8(buf);
+ bool old_pass_match = false;
+ TCHAR *pass = UniGetContactSettingUtf(NULL, szGPGModuleName, "szKeyPassword", _T(""));
+ if(!_tcscmp(pass,buf))
+ old_pass_match = true;
+ mir_free(pass);
+ if(!old_pass_match)
+ {
+ if(key_id_global[0])
+ {
+ string dbsetting = "szKey_";
+ dbsetting += toUTF8(key_id_global);
+ dbsetting += "_Password";
+ pass = UniGetContactSettingUtf(NULL, szGPGModuleName, dbsetting.c_str(), _T(""));
+ if(!_tcscmp(pass,buf))
+ old_pass_match = true;
+ mir_free(pass);
+ }
+ }
+ if(!old_pass_match)
+ {
+ if(MessageBox(hwndDlg, TranslateT("Old password not match, you can continue, but gpg will reject wrong password.\nDo you want to continue?"), TranslateT("Error"), MB_YESNO) == IDNO)
+ {
+ //key_id_global[0] = 0;
+ break;
+ }
+ }
+ std::vector<std::wstring> cmd;
+ TCHAR tmp2[MAX_PATH] = {0};
+ string output;
+ DWORD exitcode;
+ cmd.push_back(L"--edit-key");
+ cmd.push_back(key_id_global);
+ cmd.push_back(L"passwd");
+ gpg_execution_params_pass params(cmd, old_pass, new_pass);
+ pxResult result;
+ params.out = &output;
+ params.code = &exitcode;
+ params.result = &result;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_passwd_change_thread, &params));
+ if(!gpg_thread.timed_join(boost::posix_time::minutes(10)))
+ {
+ gpg_thread.~thread();
+ if(params.child)
+ boost::process::terminate(*(params.child));
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": GPG execution timed out, aborted");
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ if(result == pxNotFound)
+ break;
+ //if(result == pxSuccess)
+ //TODO: save to db
+
+
+ }
+ DestroyWindow(hwndDlg);
+ break;
+ default:
+ break;
+ }
+
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+ }
+ break;
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+ case WM_DESTROY:
+ {
+ extern TCHAR key_id_global[17];
+ key_id_global[0] = 0;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+void ShowChangePasswdDlg()
+{
+ extern HINSTANCE hInst;
+ HWND hwndPaaswdDlg = NULL;
+ hwndPaaswdDlg = CreateDialog(hInst, MAKEINTRESOURCE(IDD_CHANGE_PASSWD), NULL, DlgProcChangePasswd);
+ SetForegroundWindow(hwndPaaswdDlg);
+}
+
+
+void clean_temp_dir()
+{
+ using namespace boost::filesystem;
+ char *mir_path = new char [MAX_PATH];
+ PathToAbsolute("\\", mir_path);
+ wstring path = toUTF16(mir_path);
+ SetCurrentDirectoryA(mir_path);
+ delete [] mir_path;
+ TCHAR *tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T(""));
+ path += tmp;
+ mir_free(tmp);
+ path += L"\\tmp";
+ if(exists(path) && is_directory(path))
+ {
+ boost::filesystem::path p(path);
+ for(directory_iterator i = directory_iterator(p), end = directory_iterator(); i != end; ++i)
+ {
+ if(boost::filesystem::is_regular_file(i->path()))
+ {
+ if((i->path().filename().generic_string().length() == 10 && (i->path().filename().generic_string().find(".") == std::string::npos)) ||
+ i->path().extension() == ".sig" || i->path().extension() == ".asc" || i->path().extension() == ".status")
+ boost::filesystem::remove(i->path());
+ }
+ }
+ }
+} \ 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 100644
index 0000000000..eaa7ef71b5
--- /dev/null
+++ b/plugins/New_GPG/src/utilities.h
@@ -0,0 +1,110 @@
+// 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 = time(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 = time(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);
+void fix_line_term(std::string &s);
+void fix_line_term(std::wstring &s);
+void strip_line_term(std::wstring &s);
+void strip_line_term(std::string &s);
+void strip_tags(std::wstring &s);
+void clean_temp_dir();
+
+#endif