diff options
author | Gluzskiy Alexandr <sss@sss.chaoslab.ru> | 2017-12-08 07:42:32 +0300 |
---|---|---|
committer | Gluzskiy Alexandr <sss@sss.chaoslab.ru> | 2017-12-08 07:42:32 +0300 |
commit | caff89011ee731657192dc076b6a1ea54fcee520 (patch) | |
tree | 2390a84cb56fbd7a472533efda7b24ea409f389e /plugins/New_GPG | |
parent | b3d3b95a16be5b1785681f0f6fdc3bcdb967a42e (diff) |
new_gpg: a bit of refactoring
- eliminated few confusing globals (including unnecessary mutex)
- implemeted proper way to avoid collisions in some places
Diffstat (limited to 'plugins/New_GPG')
-rwxr-xr-x | plugins/New_GPG/src/globals.h | 3 | ||||
-rwxr-xr-x | plugins/New_GPG/src/init.cpp | 6 | ||||
-rwxr-xr-x | plugins/New_GPG/src/main.cpp | 1541 | ||||
-rwxr-xr-x | plugins/New_GPG/src/main.h | 2 | ||||
-rwxr-xr-x | plugins/New_GPG/src/messages.cpp | 95 | ||||
-rwxr-xr-x | plugins/New_GPG/src/options.cpp | 14 | ||||
-rwxr-xr-x | plugins/New_GPG/src/ui.cpp | 1279 | ||||
-rwxr-xr-x | plugins/New_GPG/src/ui.h | 120 | ||||
-rwxr-xr-x | plugins/New_GPG/src/utilities.cpp | 186 | ||||
-rwxr-xr-x | plugins/New_GPG/src/utilities.h | 3 |
10 files changed, 1626 insertions, 1623 deletions
diff --git a/plugins/New_GPG/src/globals.h b/plugins/New_GPG/src/globals.h index 0434802bea..9b63ae4358 100755 --- a/plugins/New_GPG/src/globals.h +++ b/plugins/New_GPG/src/globals.h @@ -33,9 +33,6 @@ struct globals_s std::map<MCONTACT, contact_data> hcontact_data; map<int, MCONTACT> user_data; bool _terminate; - wstring new_key; - MCONTACT new_key_hcnt; - boost::mutex new_key_hcnt_mutex; int item_num; //TODO: get rid of this diff --git a/plugins/New_GPG/src/init.cpp b/plugins/New_GPG/src/init.cpp index fc83d06c14..1736462b5e 100755 --- a/plugins/New_GPG/src/init.cpp +++ b/plugins/New_GPG/src/init.cpp @@ -215,9 +215,9 @@ 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)); + for(auto p : transfers) + if(!p.empty()) + boost::filesystem::remove(p); } mir_free(globals.inopentag); mir_free(globals.inclosetag); diff --git a/plugins/New_GPG/src/main.cpp b/plugins/New_GPG/src/main.cpp index a8404fec3e..fe5db8a1e5 100755 --- a/plugins/New_GPG/src/main.cpp +++ b/plugins/New_GPG/src/main.cpp @@ -18,1513 +18,13 @@ #pragma comment(lib, "shlwapi.lib") -void ShowFirstRunDialog(); - -HWND hwndFirstRun = nullptr, hwndSetDirs = nullptr, hwndNewKey = nullptr, hwndKeyGen = nullptr, hwndSelectExistingKey = nullptr; - -//int itemnum = 0; - -HWND hwndList_g = nullptr; -BOOL CheckStateStoreDB(HWND hwndDlg, int idCtrl, const char* szSetting) -{ - BOOL state = IsDlgButtonChecked(hwndDlg, idCtrl); - db_set_b(NULL, szGPGModuleName, szSetting, (BYTE)state); - return state; -} - -bool gpg_validate_paths(wchar_t *gpg_bin_path, wchar_t *gpg_home_path) -{ - wstring tmp = gpg_bin_path; - if (!tmp.empty()) { - wchar_t mir_path[MAX_PATH]; - PathToAbsoluteW(L"\\", mir_path); - SetCurrentDirectoryW(mir_path); - if (!boost::filesystem::exists(tmp)) { - MessageBox(nullptr, TranslateT("GPG binary does not exist.\nPlease choose another location"), TranslateT("Warning"), MB_OK); - return false; - } - } - else { - MessageBox(nullptr, TranslateT("Please choose GPG binary location"), TranslateT("Warning"), MB_OK); - return false; - } - { - bool bad_version = false; - db_set_ws(NULL, szGPGModuleName, "szGpgBinPath", tmp.c_str()); - 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; - bool _gpg_valid = globals.gpg_valid; - globals.gpg_valid = true; - gpg_launcher(params); - globals.gpg_valid = _gpg_valid; //TODO: check this - db_unset(NULL, szGPGModuleName, "szGpgBinPath"); - string::size_type p1 = out.find("(GnuPG) "); - if (p1 != string::npos) { - p1 += mir_strlen("(GnuPG) "); - if (out[p1] != '1') - bad_version = true; - } - else { - bad_version = false; - MessageBox(nullptr, TranslateT("This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin."), TranslateT("Warning"), MB_OK); - return false; - } - if (bad_version) - MessageBox(nullptr, TranslateT("Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin."), TranslateT("Warning"), MB_OK); - } - tmp = gpg_home_path; - if (tmp[tmp.length()] == '\\') - tmp.erase(tmp.length()); - if (tmp.empty()) { - MessageBox(nullptr, TranslateT("Please set keyring's home directory"), TranslateT("Warning"), MB_OK); - return false; - } - { - wchar_t *path = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", L""); - DWORD dwFileAttr = GetFileAttributes(path); - if (dwFileAttr != INVALID_FILE_ATTRIBUTES) { - dwFileAttr &= ~FILE_ATTRIBUTE_READONLY; - SetFileAttributes(path, dwFileAttr); - } - mir_free(path); - } - return true; -} - -void gpg_save_paths(wchar_t *gpg_bin_path, wchar_t *gpg_home_path) -{ - db_set_ws(NULL, szGPGModuleName, "szGpgBinPath", gpg_bin_path); - db_set_ws(NULL, szGPGModuleName, "szHomePath", gpg_home_path); -} - -bool gpg_use_new_random_key(char *account_name = Translate("Default"), wchar_t *gpg_bin_path = nullptr, wchar_t *gpg_home_dir = nullptr) -{ - if (gpg_bin_path && gpg_home_dir) - gpg_save_paths(gpg_bin_path, gpg_home_dir); - { - wstring path; - { - // generating key file - wchar_t *tmp = nullptr; - if (gpg_home_dir) - tmp = gpg_home_dir; - else - tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", L""); - path = tmp; - if(!gpg_home_dir) - mir_free(tmp); - path.append(L"\\new_key"); - wfstream f(path.c_str(), std::ios::out); - if (!f.is_open()) { - MessageBox(nullptr, TranslateT("Failed to open file"), TranslateT("Error"), MB_OK); - return false; - } - 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; - if (!gpg_launcher(params, boost::posix_time::minutes(10))) - return false; - if (result == pxNotFound) - return false; - - 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)) { - return false; - } - if (result == pxNotFound) - return false; - string::size_type s = 0; - while ((s = out.find("\r", s)) != string::npos) { - out.erase(s, 1); - } - { - if (!mir_strcmp(account_name, Translate("Default"))) - { - db_set_s(NULL, szGPGModuleName, "GPGPubKey", out.c_str()); - db_set_ws(NULL, szGPGModuleName, "KeyID", path.c_str()); - } - else - { - std::string acc_str = account_name; - acc_str += "_GPGPubKey"; - db_set_s(NULL, szGPGModuleName, acc_str.c_str(), out.c_str()); - acc_str = account_name; - acc_str += "_KeyID"; - db_set_ws(NULL, szGPGModuleName, acc_str.c_str(), path.c_str()); - } - } - } - } - return true; -} - -class CDlgFirstRun : public CDlgBase -{ -public: - CDlgFirstRun() : CDlgBase(globals.hInst, IDD_FIRST_RUN), - list_KEY_LIST(this, IDC_KEY_LIST), - btn_COPY_PUBKEY(this, IDC_COPY_PUBKEY), btn_EXPORT_PRIVATE(this, IDC_EXPORT_PRIVATE), btn_CHANGE_PASSWD(this, IDC_CHANGE_PASSWD), btn_GENERATE_RANDOM(this, IDC_GENERATE_RANDOM), - btn_GENERATE_KEY(this, IDC_GENERATE_KEY), btn_OTHER(this, IDC_OTHER), btn_DELETE_KEY(this, IDC_DELETE_KEY), btn_OK(this, ID_OK), - edit_KEY_PASSWORD(this, IDC_KEY_PASSWORD), - combo_ACCOUNT(this, IDC_ACCOUNT), - lbl_KEY_ID(this, IDC_KEY_ID), lbl_GENERATING_KEY(this, IDC_GENERATING_KEY) - { - fp[0] = 0; - hwndList_g = list_KEY_LIST.GetHwnd(); - - btn_COPY_PUBKEY.OnClick = Callback(this, &CDlgFirstRun::onClick_COPY_PUBKEY); - btn_EXPORT_PRIVATE.OnClick = Callback(this, &CDlgFirstRun::onClick_EXPORT_PRIVATE); - btn_CHANGE_PASSWD.OnClick = Callback(this, &CDlgFirstRun::onClick_CHANGE_PASSWD); - btn_GENERATE_RANDOM.OnClick = Callback(this, &CDlgFirstRun::onClick_GENERATE_RANDOM); - btn_GENERATE_KEY.OnClick = Callback(this, &CDlgFirstRun::onClick_GENERATE_KEY); - btn_OTHER.OnClick = Callback(this, &CDlgFirstRun::onClick_OTHER); - btn_DELETE_KEY.OnClick = Callback(this, &CDlgFirstRun::onClick_DELETE_KEY); - btn_OK.OnClick = Callback(this, &CDlgFirstRun::onClick_OK); - - } - virtual void OnInitDialog() override - { - SetWindowPos(m_hwnd, nullptr, globals.firstrun_rect.left, globals.firstrun_rect.top, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW); - SetCaption(TranslateT("Set own key")); - btn_COPY_PUBKEY.Disable(); - btn_EXPORT_PRIVATE.Disable(); - btn_CHANGE_PASSWD.Disable(); - - list_KEY_LIST.AddColumn(0, TranslateT("Key ID"), 50); - list_KEY_LIST.AddColumn(1, TranslateT("Email"), 30); - list_KEY_LIST.AddColumn(2, TranslateT("Name"), 250); - list_KEY_LIST.AddColumn(3, TranslateT("Creation date"), 30); - list_KEY_LIST.AddColumn(4, TranslateT("Expire date"), 30); - list_KEY_LIST.AddColumn(5, TranslateT("Key length"), 30); - list_KEY_LIST.AddColumn(6, TranslateT("Accounts"), 30); - list_KEY_LIST.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_SINGLEROW); - - refresh_key_list(); - - { - combo_ACCOUNT.AddString(TranslateT("Default")); - int count = 0; - PROTOACCOUNT **accounts; - Proto_EnumAccounts(&count, &accounts); - for (int n = 0; n < count; n++) { - if (StriStr(accounts[n]->szModuleName, "metacontacts")) - continue; - if (StriStr(accounts[n]->szModuleName, "weather")) - continue; - std::string acc = toUTF8(accounts[n]->tszAccountName); - acc += "("; - acc += accounts[n]->szModuleName; - acc += ")"; - //acc += "_KeyID"; - combo_ACCOUNT.AddStringA(acc.c_str()); - } - combo_ACCOUNT.SelectString(TranslateT("Default")); - string keyinfo = Translate("key ID"); - keyinfo += ": "; - char *keyid = UniGetContactSettingUtf(NULL, szGPGModuleName, "KeyID", ""); - keyinfo += (mir_strlen(keyid) > 0) ? keyid : Translate("not set"); - mir_free(keyid); - lbl_KEY_ID.SetTextA(keyinfo.c_str()); - } - combo_ACCOUNT.OnChange = Callback(this, &CDlgFirstRun::onChange_ACCOUNT); - list_KEY_LIST.OnItemChanged = Callback(this, &CDlgFirstRun::onChange_KEY_LIST); - } - void onClick_COPY_PUBKEY(CCtrlButton*) - { - int i = list_KEY_LIST.GetSelectionMark(); - if (i == -1) - return; - if (OpenClipboard(m_hwnd)) - { - list_KEY_LIST.GetItemText(i, 0, fp, _countof(fp)); - 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)) - return; - if (result == pxNotFound) - return; - boost::algorithm::erase_all(out, "\r"); - HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, out.size() + 1); - if (!hMem) { - MessageBox(nullptr, TranslateT("Failed to allocate memory"), TranslateT("Error"), MB_OK); - return; - } - char *szKey = (char*)GlobalLock(hMem); - if (!szKey) { - wchar_t msg[64]; - mir_snwprintf(msg, TranslateT("Failed to lock memory with error %d"), GetLastError()); - MessageBox(nullptr, msg, TranslateT("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); - wchar_t msg[64]; - mir_snwprintf(msg, TranslateT("Failed write to clipboard with error %d"), GetLastError()); - MessageBox(nullptr, msg, TranslateT("Error"), MB_OK); - } - CloseClipboard(); - } - } - void onClick_EXPORT_PRIVATE(CCtrlButton*) - { - { - int i = list_KEY_LIST.GetSelectionMark(); - if (i == -1) - return; - wchar_t *p = GetFilePath(L"Choose file to export key", L"*", L"Any file", true); - if (!p || !p[0]) { - delete[] p; - //TODO: handle error - return; - } - char *path = mir_u2a(p); - delete[] p; - std::ofstream file; - file.open(path, std::ios::trunc | std::ios::out); - mir_free(path); - if (!file.is_open()) - return; //TODO: handle error - list_KEY_LIST.GetItemText(i, 0, fp, _countof(fp)); - 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)) { - return; - } - if (result == pxNotFound) - return; - boost::algorithm::erase_all(out, "\r"); - file << out; - if (file.is_open()) - file.close(); - } - } - void onClick_CHANGE_PASSWD(CCtrlButton*) - { - int i = list_KEY_LIST.GetSelectionMark(); - if (i == -1) - return; - list_KEY_LIST.GetItemText(i, 0, globals.key_id_global, _countof(globals.key_id_global)); - - //temporary code follows - std::vector<std::wstring> cmd; - std::string old_pass, new_pass; - string output; - DWORD exitcode; - cmd.push_back(L"--edit-key"); - cmd.push_back(globals.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, ¶ms)); - if (!gpg_thread.timed_join(boost::posix_time::minutes(10))) { - gpg_thread.~thread(); - if (params.child) - boost::process::terminate(*(params.child)); - if (globals.bDebugLog) - globals.debuglog << std::string(time_str() + ": GPG execution timed out, aborted"); - this->Close(); - } - - } - void onClick_GENERATE_RANDOM(CCtrlButton*) - { - lbl_GENERATING_KEY.SendMsg(WM_SETFONT, (WPARAM)globals.bold_font, TRUE); - lbl_GENERATING_KEY.SetText(TranslateT("Generating new random key, please wait")); - btn_GENERATE_KEY.Disable(); - btn_OTHER.Disable(); - btn_DELETE_KEY.Disable(); - list_KEY_LIST.Disable(); - btn_GENERATE_RANDOM.Disable(); - gpg_use_new_random_key(combo_ACCOUNT.GetTextA()); - this->Close(); - } - void onClick_GENERATE_KEY(CCtrlButton*) - { - void ShowKeyGenDialog(); - ShowKeyGenDialog(); - refresh_key_list(); - } - void onClick_OTHER(CCtrlButton*) - { - void ShowLoadPublicKeyDialog(bool = false); - globals.item_num = 0; //black magic here - globals.user_data[1] = 0; - ShowLoadPublicKeyDialog(true); - refresh_key_list(); - } - void onClick_DELETE_KEY(CCtrlButton*) - { - int i = list_KEY_LIST.GetSelectionMark(); - if (i == -1) - return; - list_KEY_LIST.GetItemText(i, 0, fp, _countof(fp)); - { - 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)) - return; - if (result == pxNotFound) - return; - string::size_type s = out.find("Key fingerprint = "); - s += mir_strlen("Key fingerprint = "); - string::size_type s2 = out.find("\n", s); - wchar_t *str = nullptr; - { - 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); - - str = mir_a2u(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(str); - mir_free(str); - if (!gpg_launcher(params)) - return; - if (result == pxNotFound) - return; - } - { - char *buf = mir_strdup(combo_ACCOUNT.GetTextA()); - if (!mir_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()); - } - if (buf) - mir_free(buf); - } - list_KEY_LIST.DeleteItem(i); - } - void onClick_OK(CCtrlButton*) - { - { - int i = list_KEY_LIST.GetSelectionMark(); - if (i == -1) - return; - - list_KEY_LIST.GetItemText(i, 0, fp, _countof(fp)); - wchar_t *name = new wchar_t[65]; - list_KEY_LIST.GetItemText(i, 2, name, 64); - { - if (wcschr(name, '(')) { - wstring str = name; - wstring::size_type p = str.find(L"(") - 1; - mir_wstrcpy(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)) - { - delete [] name; - return; - } - if (result == pxNotFound) - { - delete[] name; - return; - } - - boost::algorithm::erase_all(out, "\r"); - { - char *buf = mir_strdup(combo_ACCOUNT.GetTextA()); - if (!mir_strcmp(buf, Translate("Default"))) { - db_set_s(NULL, szGPGModuleName, "GPGPubKey", out.c_str()); - db_set_ws(NULL, szGPGModuleName, "KeyMainName", name); - db_set_ws(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_ws(NULL, szGPGModuleName, acc_str.c_str(), name); - acc_str = buf; - acc_str += "_KeyID"; - db_set_ws(NULL, szGPGModuleName, acc_str.c_str(), fp); - } - if (!mir_strcmp(buf, Translate("Default"))) { - wstring keyinfo = TranslateT("Default private key ID"); - keyinfo += L": "; - keyinfo += (fp[0]) ? fp : L"not set"; - extern HWND hwndCurKey_p; - SetWindowText(hwndCurKey_p, keyinfo.c_str()); - } - if (buf) - mir_free(buf); - } - wchar_t *passwd = mir_wstrdup(edit_KEY_PASSWORD.GetText()); - if (passwd && passwd[0]) - { - string dbsetting = "szKey_"; - char *keyid = mir_u2a(fp); - dbsetting += keyid; - mir_free(keyid); - dbsetting += "_Password"; - db_set_ws(NULL, szGPGModuleName, dbsetting.c_str(), passwd); - } - mir_free(passwd); - delete[] name; - } - //bAutoExchange = CheckStateStoreDB(hwndDlg, IDC_AUTO_EXCHANGE, "bAutoExchange") != 0; //TODO: check is it just typo, or doing something - globals.gpg_valid = isGPGValid(); - globals.gpg_keyexist = isGPGKeyExist(); - DestroyWindow(m_hwnd); - } - void onChange_ACCOUNT(CCtrlCombo*) - { - char *buf = mir_strdup(combo_ACCOUNT.GetTextA()); - if (!mir_strcmp(buf, Translate("Default"))) { - string keyinfo = Translate("key ID"); - keyinfo += ": "; - char *keyid = UniGetContactSettingUtf(NULL, szGPGModuleName, "KeyID", ""); - keyinfo += (mir_strlen(keyid) > 0) ? keyid : Translate("not set"); - mir_free(keyid); - lbl_KEY_ID.SetTextA(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 += (mir_strlen(keyid) > 0) ? keyid : Translate("not set"); - mir_free(keyid); - lbl_KEY_ID.SetTextA(keyinfo.c_str()); - } - if (buf) - mir_free(buf); - } - void onChange_KEY_LIST(CCtrlListView::TEventInfo *ev) //TODO: check if this work - { - if (ev->nmlv) - { - NMLISTVIEW *hdr = ev->nmlv; - - if (hdr->hdr.code == NM_CLICK) { - btn_OK.Enable(); - btn_COPY_PUBKEY.Enable(); - btn_EXPORT_PRIVATE.Enable(); - btn_CHANGE_PASSWD.Enable(); - } - } - } - virtual void OnDestroy() override - { - GetWindowRect(m_hwnd, &globals.firstrun_rect); - db_set_dw(NULL, szGPGModuleName, "FirstrunWindowX", globals.firstrun_rect.left); - db_set_dw(NULL, szGPGModuleName, "FirstrunWindowY", globals.firstrun_rect.top); - hwndFirstRun = nullptr; - delete this; - } - -private: - void refresh_key_list() - { - list_KEY_LIST.DeleteAllItems(); - int i = 1; - { - { - //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)) - return; - if (result == pxNotFound) - return; - } - 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; - wchar_t *key_len = mir_wstrdup(toUTF16(out.substr(p, p2 - p)).c_str()), *creation_date = nullptr, *expire_date = nullptr; - 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 += mir_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(); - wchar_t buf[5]; - wcsncpy_s(buf, expire_date, _TRUNCATE); - int year = _wtoi(buf); - if (year < now.date().year()) - expired = true; - else if (year == now.date().year()) { - wcsncpy_s(buf, (expire_date + 5), _TRUNCATE); - int month = _wtoi(buf); - if (month < now.date().month()) - expired = true; - else if (month == now.date().month()) { - wcsncpy_s(buf, (expire_date + 8), _TRUNCATE); - unsigned day = _wtoi(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 - } - } - } - int row = list_KEY_LIST.AddItem(L"", 0); - list_KEY_LIST.SetItemText(row, 3, creation_date); - mir_free(creation_date); - if (expire_date) { - list_KEY_LIST.SetItemText(row, 4, expire_date); - mir_free(expire_date); - } - list_KEY_LIST.SetItemText(row, 5, key_len); - mir_free(key_len); - list_KEY_LIST.SetItemText(row, 0, (wchar_t*)key_id.c_str()); - p = out.find("uid ", p); - p2 = out.find_first_not_of(" ", p + 5); - p = out.find("<", p2); - - wstring tmp = toUTF16(out.substr(p2, p - p2)); - list_KEY_LIST.SetItemText(row, 2, (wchar_t*)tmp.c_str()); - - p++; - p2 = out.find(">", p); - - tmp = toUTF16(out.substr(p, p2 - p)); - list_KEY_LIST.SetItemText(row, 1, (wchar_t*)tmp.c_str()); - - // get accounts - int count = 0; - PROTOACCOUNT **accounts; - Proto_EnumAccounts(&count, &accounts); - std::wstring accs; - for (int n = 0; n < count; n++) { - std::string setting = toUTF8(accounts[n]->tszAccountName); - setting += "("; - setting += accounts[n]->szModuleName; - setting += ")"; - setting += "_KeyID"; - wchar_t *str = UniGetContactSettingUtf(NULL, szGPGModuleName, setting.c_str(), L""); - if (key_id == str) { - if (!accs.empty()) - accs += L","; - accs += accounts[n]->tszAccountName; - } - mir_free(str); - } - list_KEY_LIST.SetItemText(row, 6, (wchar_t*)accs.c_str()); - } - i++; - list_KEY_LIST.SetColumnWidth(0, LVSCW_AUTOSIZE); - list_KEY_LIST.SetColumnWidth(1, LVSCW_AUTOSIZE); - list_KEY_LIST.SetColumnWidth(2, LVSCW_AUTOSIZE); - list_KEY_LIST.SetColumnWidth(3, LVSCW_AUTOSIZE); - list_KEY_LIST.SetColumnWidth(4, LVSCW_AUTOSIZE); - list_KEY_LIST.SetColumnWidth(5, LVSCW_AUTOSIZE); - list_KEY_LIST.SetColumnWidth(6, LVSCW_AUTOSIZE); - } - } - } - CCtrlListView list_KEY_LIST; - CCtrlButton btn_COPY_PUBKEY, btn_EXPORT_PRIVATE, btn_CHANGE_PASSWD, btn_GENERATE_RANDOM, btn_GENERATE_KEY, btn_OTHER, btn_DELETE_KEY, btn_OK; - CCtrlEdit edit_KEY_PASSWORD; - CCtrlCombo combo_ACCOUNT; - CCtrlData lbl_KEY_ID, lbl_GENERATING_KEY; - wchar_t fp[16]; -}; - - -class CDlgGpgBinOpts : public CDlgBase -{ -public: - CDlgGpgBinOpts() : CDlgBase(globals.hInst, IDD_BIN_PATH), - btn_SET_BIN_PATH(this, IDC_SET_BIN_PATH), btn_SET_HOME_DIR(this, IDC_SET_HOME_DIR), btn_OK(this, ID_OK), btn_GENERATE_RANDOM(this, IDC_GENERATE_RANDOM), - edit_BIN_PATH(this, IDC_BIN_PATH), edit_HOME_DIR(this, IDC_HOME_DIR), - chk_AUTO_EXCHANGE(this, IDC_AUTO_EXCHANGE) - { - btn_SET_BIN_PATH.OnClick = Callback(this, &CDlgGpgBinOpts::onClick_SET_BIN_PATH); - btn_SET_HOME_DIR.OnClick = Callback(this, &CDlgGpgBinOpts::onClick_SET_HOME_DIR); - btn_OK.OnClick = Callback(this, &CDlgGpgBinOpts::onClick_OK); - btn_GENERATE_RANDOM.OnClick = Callback(this, &CDlgGpgBinOpts::onClick_GENERATE_RANDOM); - } - virtual void OnInitDialog() override - { - CMStringW path; - bool gpg_exists = false, lang_exists = false; - { - wchar_t mir_path[MAX_PATH]; - PathToAbsoluteW(L"\\", mir_path); - SetCurrentDirectoryW(mir_path); - - CMStringW gpg_path(mir_path); gpg_path.Append(L"\\GnuPG\\gpg.exe"); - CMStringW gpg_lang_path(mir_path); gpg_lang_path.Append(L"\\GnuPG\\gnupg.nls\\en@quot.mo"); - - if (boost::filesystem::exists(gpg_path.c_str())) { - gpg_exists = true; - path = L"GnuPG\\gpg.exe"; - } - else path = gpg_path; - - if (boost::filesystem::exists(gpg_lang_path.c_str())) - lang_exists = true; - if (gpg_exists && !lang_exists) - MessageBox(nullptr, TranslateT("GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned."), TranslateT("Warning"), MB_OK); - } - DWORD len = MAX_PATH; - bool bad_version = false; - { - ptrW tmp; - if (!gpg_exists) { - tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szGpgBinPath", (SHGetValueW(HKEY_CURRENT_USER, L"Software\\GNU\\GnuPG", L"gpgProgram", 0, (void*)path.c_str(), &len) == ERROR_SUCCESS) ? path.c_str() : L""); - if (tmp[0]) - if (!boost::filesystem::exists((wchar_t*)tmp)) - MessageBox(nullptr, TranslateT("Wrong GPG binary location found in system.\nPlease choose another location"), TranslateT("Warning"), MB_OK); - } - else tmp = mir_wstrdup(path.c_str()); - - edit_BIN_PATH.SetText(tmp); - if (gpg_exists/* && lang_exists*/) { - db_set_ws(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; - bool _gpg_valid = globals.gpg_valid; - globals.gpg_valid = true; - gpg_launcher(params); - globals.gpg_valid = _gpg_valid; //TODO: check this - db_unset(NULL, szGPGModuleName, "szGpgBinPath"); - string::size_type p1 = out.find("(GnuPG) "); - if (p1 != string::npos) { - p1 += mir_strlen("(GnuPG) "); - if (out[p1] != '1') - bad_version = true; - } - else { - bad_version = false; - MessageBox(nullptr, TranslateT("This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin."), TranslateT("Error"), MB_OK); - } - if (bad_version) - MessageBox(nullptr, TranslateT("Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin."), TranslateT("Warning"), MB_OK); - } - } - { - ptrW tmp(UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", L"")); - if (!tmp[0]) { - wchar_t mir_path[MAX_PATH]; - PathToAbsoluteW(L"\\", mir_path); - mir_wstrcat(mir_path, L"\\gpg"); - if (_waccess(mir_path, 0) != -1) { - tmp = mir_wstrdup(mir_path); - MessageBox(nullptr, TranslateT("\"GPG\" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set."), TranslateT("Info"), MB_OK); - } - else { - wstring path_ = _wgetenv(L"APPDATA"); - path_ += L"\\GnuPG"; - tmp = mir_wstrdup(path_.c_str()); - } - } - edit_HOME_DIR.SetText(!gpg_exists ? tmp : L"gpg"); - } - //TODO: additional check for write access - if (gpg_exists && lang_exists && !bad_version) - MessageBox(nullptr, TranslateT("Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue."), TranslateT("Info"), MB_OK); - chk_AUTO_EXCHANGE.Enable(); - } - void onClick_SET_BIN_PATH(CCtrlButton*) - { - GetFilePath(L"Choose gpg.exe", "szGpgBinPath", L"*.exe", L"EXE Executables"); - CMStringW tmp(ptrW(UniGetContactSettingUtf(NULL, szGPGModuleName, "szGpgBinPath", L"gpg.exe"))); - edit_BIN_PATH.SetText(tmp); - wchar_t mir_path[MAX_PATH]; - PathToAbsoluteW(L"\\", mir_path); - if (tmp.Find(mir_path, 0) == 0) - { - CMStringW path = tmp.Mid(mir_wstrlen(mir_path)); - edit_BIN_PATH.SetText(path); - } - - } - void onClick_SET_HOME_DIR(CCtrlButton*) - { - GetFolderPath(L"Set home directory", "szHomePath"); - CMStringW tmp(ptrW(UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", L""))); - edit_HOME_DIR.SetText(tmp); - wchar_t mir_path[MAX_PATH]; - PathToAbsoluteW(L"\\", mir_path); - PathToAbsoluteW(L"\\", mir_path); - if (tmp.Find(mir_path, 0) == 0) { - CMStringW path = tmp.Mid(mir_wstrlen(mir_path)); - edit_HOME_DIR.SetText(path); - } - - } - void onClick_OK(CCtrlButton*) - { - if (gpg_validate_paths(edit_BIN_PATH.GetText(), edit_HOME_DIR.GetText())) - { - gpg_save_paths(edit_BIN_PATH.GetText(), edit_HOME_DIR.GetText()); - globals.gpg_valid = true; - db_set_b(NULL, szGPGModuleName, "FirstRun", 0); - this->Hide(); - ShowFirstRunDialog(); - this->Close(); - } - } - void onClick_GENERATE_RANDOM(CCtrlButton*) - { - if (gpg_validate_paths(edit_BIN_PATH.GetText(), edit_HOME_DIR.GetText())) - { - gpg_save_paths(edit_BIN_PATH.GetText(), edit_HOME_DIR.GetText()); - globals.gpg_valid = true; - if (gpg_use_new_random_key()) - { - db_set_b(NULL, szGPGModuleName, "bAutoExchange", globals.bAutoExchange = chk_AUTO_EXCHANGE.GetState()); - globals.gpg_valid = true; - db_set_b(NULL, szGPGModuleName, "FirstRun", 0); - this->Close(); - } - } - } - virtual void OnDestroy() override - { - hwndSetDirs = nullptr; - void InitCheck(); - InitCheck(); - delete this; - } -private: - CCtrlButton btn_SET_BIN_PATH, btn_SET_HOME_DIR, btn_OK, btn_GENERATE_RANDOM; - CCtrlEdit edit_BIN_PATH, edit_HOME_DIR; - CCtrlCheck chk_AUTO_EXCHANGE; -}; - -class CDlgNewKey : public CDlgBase -{ -public: - CDlgNewKey() : CDlgBase(globals.hInst, IDD_NEW_KEY), - lbl_KEY_FROM(this, IDC_KEY_FROM), lbl_MESSAGE(this, IDC_MESSAGE), - btn_IMPORT(this, ID_IMPORT), btn_IMPORT_AND_USE(this, IDC_IMPORT_AND_USE), btn_IGNORE_KEY(this, IDC_IGNORE_KEY) - { - hContact = INVALID_CONTACT_ID; - btn_IMPORT.OnClick = Callback(this, &CDlgNewKey::onClick_IMPORT); - btn_IMPORT_AND_USE.OnClick = Callback(this, &CDlgNewKey::onClick_IMPORT_AND_USE); - btn_IGNORE_KEY.OnClick = Callback(this, &CDlgNewKey::onClick_IGNORE_KEY); - - } - virtual void OnInitDialog() override - { - hContact = globals.new_key_hcnt; - //new_key_hcnt_mutex.unlock(); - SetWindowPos(m_hwnd, nullptr, globals.new_key_rect.left, globals.new_key_rect.top, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW); - wchar_t *tmp = UniGetContactSettingUtf(hContact, szGPGModuleName, "GPGPubKey", L""); - lbl_MESSAGE.SetText(tmp[0] ? TranslateT("There is existing key for contact, would you like to replace it with new key?") : TranslateT("New public key was received, do you want to import it?")); - btn_IMPORT_AND_USE.Enable(db_get_b(hContact, szGPGModuleName, "GPGEncryption", 0)); - btn_IMPORT.SetText(tmp[0] ? TranslateT("Replace") : TranslateT("Accept")); - mir_free(tmp); - tmp = new wchar_t[256]; - mir_snwprintf(tmp, 255 * sizeof(wchar_t), TranslateT("Received key from %s"), pcli->pfnGetContactDisplayName(hContact, 0)); - lbl_KEY_FROM.SetText(tmp); - mir_free(tmp); - } - virtual void OnDestroy() override - { - GetWindowRect(m_hwnd, &globals.new_key_rect); - db_set_dw(NULL, szGPGModuleName, "NewKeyWindowX", globals.new_key_rect.left); - db_set_dw(NULL, szGPGModuleName, "NewKeyWindowY", globals.new_key_rect.top); - delete this; - } - void onClick_IMPORT(CCtrlButton*) - { - void ImportKey(); - ImportKey(); - this->Close(); - } - void onClick_IMPORT_AND_USE(CCtrlButton*) - { - void ImportKey(); - ImportKey(); - db_set_b(hContact, szGPGModuleName, "GPGEncryption", 1); - void setSrmmIcon(MCONTACT hContact); - void setClistIcon(MCONTACT hContact); - setSrmmIcon(hContact); - setClistIcon(hContact); - this->Close(); - } - void onClick_IGNORE_KEY(CCtrlButton*) - { - this->Close(); - } -private: - MCONTACT hContact; - CCtrlData lbl_KEY_FROM, lbl_MESSAGE; - CCtrlButton btn_IMPORT, btn_IMPORT_AND_USE, btn_IGNORE_KEY; -}; - -class CDlgKeyGen : public CDlgBase //TODO: in modal mode window destroying on any button press even without direct "Close" call -{ -public: - CDlgKeyGen() : CDlgBase(globals.hInst, IDD_KEY_GEN), - combo_KEY_TYPE(this, IDC_KEY_TYPE), - edit_KEY_LENGTH(this, IDC_KEY_LENGTH), edit_KEY_PASSWD(this, IDC_KEY_PASSWD), edit_KEY_REAL_NAME(this, IDC_KEY_REAL_NAME), edit_KEY_EMAIL(this, IDC_KEY_EMAIL), edit_KEY_COMMENT(this, IDC_KEY_COMMENT), - edit_KEY_EXPIRE_DATE(this, IDC_KEY_EXPIRE_DATE), - lbl_GENERATING_TEXT(this, IDC_GENERATING_TEXT), - btn_OK(this, IDOK), btn_CANCEL(this, IDCANCEL) - { - btn_OK.OnClick = Callback(this, &CDlgKeyGen::onClick_OK); - btn_CANCEL.OnClick = Callback(this, &CDlgKeyGen::onClick_CANCEL); - } - virtual void OnInitDialog() override - { - SetWindowPos(m_hwnd, nullptr, globals.key_gen_rect.left, globals.key_gen_rect.top, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW); - SetCaption(TranslateT("Key Generation dialog")); - combo_KEY_TYPE.AddString(L"RSA"); - combo_KEY_TYPE.AddString(L"DSA"); - combo_KEY_TYPE.SelectString(L"RSA"); - edit_KEY_EXPIRE_DATE.SetText(L"0"); - edit_KEY_LENGTH.SetText(L"4096"); - } - - void onClick_OK(CCtrlButton*) - { - { - wstring path; - { //data sanity checks - wchar_t *tmp = mir_wstrdup(combo_KEY_TYPE.GetText()); - if (!tmp) - { - MessageBox(nullptr, TranslateT("You must set encryption algorithm first"), TranslateT("Error"), MB_OK); - return; - } - if (mir_wstrlen(tmp) < 3) - { - mir_free(tmp); - tmp = nullptr; - MessageBox(nullptr, TranslateT("You must set encryption algorithm first"), TranslateT("Error"), MB_OK); - return; - } - mir_free(tmp); - tmp = mir_wstrdup(edit_KEY_LENGTH.GetText()); - if (!tmp) - { - MessageBox(nullptr, TranslateT("Key length must be of length from 1024 to 4096 bits"), TranslateT("Error"), MB_OK); - return; - } - int length = _wtoi(tmp); - mir_free(tmp); - if (length < 1024 || length > 4096) { - MessageBox(nullptr, TranslateT("Key length must be of length from 1024 to 4096 bits"), TranslateT("Error"), MB_OK); - return; - } - tmp = mir_wstrdup(edit_KEY_EXPIRE_DATE.GetText()); - if (!tmp) - { - MessageBox(nullptr, TranslateT("Invalid date"), TranslateT("Error"), MB_OK); - return; - } - if (mir_wstrlen(tmp) != 10 && tmp[0] != '0') { - MessageBox(nullptr, TranslateT("Invalid date"), TranslateT("Error"), MB_OK); - mir_free(tmp); - return; - } - mir_free(tmp); - tmp = mir_wstrdup(edit_KEY_REAL_NAME.GetText()); - if (!tmp) - { - MessageBox(nullptr, TranslateT("Name must contain at least 5 characters"), TranslateT("Error"), MB_OK); - return; - } - if (mir_wstrlen(tmp) < 5) { - MessageBox(nullptr, TranslateT("Name must contain at least 5 characters"), TranslateT("Error"), MB_OK); - mir_free(tmp); - return; - } - else if (wcschr(tmp, '(') || wcschr(tmp, ')')) - { - MessageBox(nullptr, TranslateT("Name cannot contain '(' or ')'"), TranslateT("Error"), MB_OK); - mir_free(tmp); - return; - } - mir_free(tmp); - tmp = mir_wstrdup(edit_KEY_EMAIL.GetText()); - if (!tmp) - { - MessageBox(nullptr, TranslateT("Invalid Email"), TranslateT("Error"), MB_OK); - return; - } - if ((mir_wstrlen(tmp)) < 5 || (!wcschr(tmp, '@')) || (!wcschr(tmp, '.'))) { - MessageBox(nullptr, TranslateT("Invalid Email"), TranslateT("Error"), MB_OK); - mir_free(tmp); - return; - } - mir_free(tmp); - } - { //generating key file - wchar_t *tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", L""); - char *tmp2;// = mir_u2a(tmp); - path = tmp; - mir_free(tmp); - // mir_free(tmp2); - path.append(L"\\new_key"); - wfstream f(path.c_str(), std::ios::out); - if (!f.is_open()) { - MessageBox(nullptr, TranslateT("Failed to open file"), TranslateT("Error"), MB_OK); - return; - } - f << "Key-Type: "; - tmp2 = mir_u2a(combo_KEY_TYPE.GetText()); - char *subkeytype = (char*)mir_alloc(6); - if (strstr(tmp2, "RSA")) - mir_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 - mir_strcpy(subkeytype, "ELG-E"); - f << tmp2; - mir_free(tmp2); - f << "\n"; - f << "Key-Length: "; - f << _wtoi(edit_KEY_LENGTH.GetText()); - f << "\n"; - f << "Subkey-Length: "; - f << _wtoi(edit_KEY_LENGTH.GetText()); - f << "\n"; - f << "Subkey-Type: "; - f << subkeytype; - mir_free(subkeytype); - f << "\n"; - if (edit_KEY_PASSWD.GetText()[0]) - { - f << "Passphrase: "; - f << toUTF8(edit_KEY_PASSWD.GetText()).c_str(); - f << "\n"; - } - f << "Name-Real: "; - f << toUTF8(edit_KEY_REAL_NAME.GetText()).c_str(); - f << "\n"; - if (edit_KEY_COMMENT.GetText()[0]) - { - f << "Name-Comment: "; - f << toUTF8(edit_KEY_COMMENT.GetText()).c_str(); - f << "\n"; - } - f << "Name-Email: "; - f << toUTF8(edit_KEY_EMAIL.GetText()).c_str(); - f << "\n"; - f << "Expire-Date: "; - f << toUTF8(edit_KEY_EXPIRE_DATE.GetText()).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; - lbl_GENERATING_TEXT.SendMsg(WM_SETFONT, (WPARAM)globals.bold_font, TRUE); - lbl_GENERATING_TEXT.SetText(TranslateT("Generating new key, please wait...")); - btn_CANCEL.Disable(); - btn_OK.Disable(); - combo_KEY_TYPE.Disable(); - edit_KEY_LENGTH.Disable(); - edit_KEY_PASSWD.Disable(); - edit_KEY_REAL_NAME.Disable(); - edit_KEY_EMAIL.Disable(); - edit_KEY_COMMENT.Disable(); - edit_KEY_EXPIRE_DATE.Disable(); - if (!gpg_launcher(params, boost::posix_time::minutes(10))) - return; - if (result == pxNotFound) - return; - } - boost::filesystem::remove(path); - } - this->Close(); - } - void onClick_CANCEL(CCtrlButton*) - { - this->Close(); - } - virtual void OnDestroy() override - { - GetWindowRect(m_hwnd, &globals.key_gen_rect); - db_set_dw(NULL, szGPGModuleName, "KeyGenWindowX", globals.key_gen_rect.left); - db_set_dw(NULL, szGPGModuleName, "KeyGenWindowY", globals.key_gen_rect.top); - delete this; - } - -private: - CCtrlCombo combo_KEY_TYPE; - CCtrlEdit edit_KEY_LENGTH, edit_KEY_PASSWD, edit_KEY_REAL_NAME, edit_KEY_EMAIL, edit_KEY_COMMENT, edit_KEY_EXPIRE_DATE; - CCtrlData lbl_GENERATING_TEXT; - CCtrlButton btn_OK, btn_CANCEL; - -}; - -int itemnum2 = 0; - -class CDlgLoadExistingKey : public CDlgBase -{ -public: - CDlgLoadExistingKey() : CDlgBase(globals.hInst, IDD_LOAD_EXISTING_KEY), - btn_OK(this, IDOK), btn_CANCEL(this, IDCANCEL), - list_EXISTING_KEY_LIST(this, IDC_EXISTING_KEY_LIST) - { - id[0] = 0; - btn_OK.OnClick = Callback(this, &CDlgLoadExistingKey::onClick_OK); - btn_CANCEL.OnClick = Callback(this, &CDlgLoadExistingKey::onClick_CANCEL); - - } - virtual void OnInitDialog() override - { - SetWindowPos(m_hwnd, nullptr, globals.load_existing_key_rect.left, globals.load_existing_key_rect.top, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW); - - - list_EXISTING_KEY_LIST.AddColumn(0, TranslateT("Key ID"), 50); - list_EXISTING_KEY_LIST.AddColumn(1, TranslateT("Email"), 30); - list_EXISTING_KEY_LIST.AddColumn(2, TranslateT("Name"), 250); - list_EXISTING_KEY_LIST.AddColumn(3, TranslateT("Creation date"), 30); - list_EXISTING_KEY_LIST.AddColumn(4, TranslateT("Expiration date"), 30); - list_EXISTING_KEY_LIST.AddColumn(5, TranslateT("Key length"), 30); - list_EXISTING_KEY_LIST.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_SINGLEROW); - int i = 1; - { - {//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)) - return; - if (result == pxNotFound) - return; - } - 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; - wchar_t *tmp = mir_wstrdup(toUTF16(out.substr(p, p2 - p)).c_str()); - int row = list_EXISTING_KEY_LIST.AddItem(L"", 0); - list_EXISTING_KEY_LIST.SetItemText(row, 5, tmp); - mir_free(tmp); - p2 += 2; - p = out.find(" ", p2); - tmp = mir_wstrdup(toUTF16(out.substr(p2, p - p2)).c_str()); - list_EXISTING_KEY_LIST.SetItemText(row, 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 += mir_strlen("expires: "); - string::size_type p4 = out.find("]", p3); - tmp = mir_wstrdup(toUTF16(out.substr(p3, p4 - p3)).c_str()); - list_EXISTING_KEY_LIST.SetItemText(row, 4, tmp); - mir_free(tmp); - } - else - p2--; - tmp = mir_wstrdup(toUTF16(out.substr(p, p2 - p)).c_str()); - list_EXISTING_KEY_LIST.SetItemText(row, 3, tmp); - mir_free(tmp); - p = out.find("uid ", p); - p += mir_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()); - list_EXISTING_KEY_LIST.SetItemText(row, 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()); - list_EXISTING_KEY_LIST.SetItemText(row, 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); - list_EXISTING_KEY_LIST.SetColumnWidth(0, LVSCW_AUTOSIZE);// not sure about this - list_EXISTING_KEY_LIST.SetColumnWidth(1, LVSCW_AUTOSIZE); - list_EXISTING_KEY_LIST.SetColumnWidth(2, LVSCW_AUTOSIZE); - list_EXISTING_KEY_LIST.SetColumnWidth(3, LVSCW_AUTOSIZE); - list_EXISTING_KEY_LIST.SetColumnWidth(4, LVSCW_AUTOSIZE); - list_EXISTING_KEY_LIST.SetColumnWidth(5, LVSCW_AUTOSIZE); - i++; - } - } - } - list_EXISTING_KEY_LIST.OnItemChanged = Callback(this, &CDlgLoadExistingKey::onChange_EXISTING_KEY_LIST); - } - virtual void OnDestroy() override - { - GetWindowRect(m_hwnd, &globals.load_existing_key_rect); - db_set_dw(NULL, szGPGModuleName, "LoadExistingKeyWindowX", globals.load_existing_key_rect.left); - db_set_dw(NULL, szGPGModuleName, "LoadExistingKeyWindowY", globals.load_existing_key_rect.top); - delete this; - } - void onClick_OK(CCtrlButton*) - { - int i = list_EXISTING_KEY_LIST.GetSelectionMark(); - if (i == -1) - return; //TODO: error message - - list_EXISTING_KEY_LIST.GetItemText(i, 0, id, _countof(id)); - extern CCtrlEdit *edit_p_PubKeyEdit; - 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)) - return; - if (result == pxNotFound) - return; - 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 += mir_strlen("-----END PGP PUBLIC KEY BLOCK-----"); - out = out.substr(p1, p2 - p1); - wchar_t *tmp = mir_a2u(out.c_str()); - if (edit_p_PubKeyEdit) - edit_p_PubKeyEdit->SetText(tmp); - mir_free(tmp); - } - else - MessageBox(nullptr, TranslateT("Failed to export public key."), TranslateT("Error"), MB_OK); - } - else - MessageBox(nullptr, TranslateT("Failed to export public key."), TranslateT("Error"), MB_OK); - // SetDlgItemText(hPubKeyEdit, IDC_PUBLIC_KEY_EDIT, tmp); - this->Close(); - } - void onClick_CANCEL(CCtrlButton*) - { - this->Close(); - } - void onChange_EXISTING_KEY_LIST(CCtrlListView::TEventInfo * /*ev*/) //TODO: check if this work - { - if (list_EXISTING_KEY_LIST.GetSelectionMark() != -1) - btn_OK.Enable(); - } -private: - wchar_t id[16]; - CCtrlButton btn_OK, btn_CANCEL; - CCtrlListView list_EXISTING_KEY_LIST; -}; - -class CDlgImportKey : public CDlgBase -{ -public: - CDlgImportKey() : CDlgBase(globals.hInst, IDD_IMPORT_KEY), - combo_KEYSERVER(this, IDC_KEYSERVER), - btn_IMPORT(this, IDC_IMPORT) - { - hContact = INVALID_CONTACT_ID; - btn_IMPORT.OnClick = Callback(this, &CDlgImportKey::onClick_IMPORT); - } - virtual void OnInitDialog() override - { - hContact = globals.new_key_hcnt; - globals.new_key_hcnt_mutex.unlock(); - SetWindowPos(m_hwnd, nullptr, globals.import_key_rect.left, globals.import_key_rect.top, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW); - combo_KEYSERVER.AddString(L"subkeys.pgp.net"); - combo_KEYSERVER.AddString(L"keys.gnupg.net"); - } - virtual void OnDestroy() override - { - GetWindowRect(m_hwnd, &globals.import_key_rect); - db_set_dw(NULL, szGPGModuleName, "ImportKeyWindowX", globals.import_key_rect.left); - db_set_dw(NULL, szGPGModuleName, "ImportKeyWindowY", globals.import_key_rect.top); - delete this; - } - void onClick_IMPORT(CCtrlButton*) - { - string out; - DWORD code; - std::vector<wstring> cmd; - cmd.push_back(L"--keyserver"); - cmd.push_back(combo_KEYSERVER.GetText()); - cmd.push_back(L"--recv-keys"); - cmd.push_back(toUTF16(globals.hcontact_data[hContact].key_in_prescense)); - gpg_execution_params params(cmd); - pxResult result; - params.out = &out; - params.code = &code; - params.result = &result; - gpg_launcher(params); - MessageBoxA(nullptr, out.c_str(), "GPG output", MB_OK); - } -private: - MCONTACT hContact; - CCtrlCombo combo_KEYSERVER; - CCtrlButton btn_IMPORT; -}; - - -void ShowFirstRunDialog() -{ - CDlgFirstRun *d = new CDlgFirstRun; - d->Show(); -} - - -void ShowSetDirsDialog() -{ - CDlgGpgBinOpts *d = new CDlgGpgBinOpts; - d->Show(); -} - -void ShowNewKeyDialog() -{ - CDlgNewKey *d = new CDlgNewKey; - d->Show(); -} - -void ShowKeyGenDialog() -{ - CDlgKeyGen *d = new CDlgKeyGen; - d->DoModal(); -} - -void ShowSelectExistingKeyDialog() -{ - CDlgLoadExistingKey *d = new CDlgLoadExistingKey; - d->DoModal(); -} - -void ShowImportKeyDialog() -{ - CDlgImportKey *d = new CDlgImportKey; //TODO: shoud it be modal ? - d->Show(); -} void FirstRun() { if (!db_get_b(NULL, szGPGModuleName, "FirstRun", 1)) return; - ShowSetDirsDialog(); + CDlgGpgBinOpts *d = new CDlgGpgBinOpts; + d->Show(); } void InitCheck() @@ -1623,7 +123,10 @@ void InitCheck() question += toUTF8(accounts[i]->tszAccountName); question += Translate(" deleted from GPG secret keyring.\nDo you want to set another key?"); if (MessageBoxA(nullptr, question.c_str(), Translate("Own secret key warning"), MB_YESNO) == IDYES) - ShowFirstRunDialog(); + { + CDlgFirstRun *d = new CDlgFirstRun; + d->DoModal(); + } } p2 = p; p = out.find("[", p); @@ -1661,7 +164,10 @@ void InitCheck() question += toUTF8(accounts[i]->tszAccountName); question += Translate(" expired and will not work.\nDo you want to set another key?"); if (MessageBoxA(nullptr, question.c_str(), Translate("Own secret key warning"), MB_YESNO) == IDYES) - ShowFirstRunDialog(); + { + CDlgFirstRun *d = new CDlgFirstRun; + d->DoModal(); + } } mir_free(expire_date); } @@ -1677,13 +183,19 @@ void InitCheck() 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(nullptr, question.c_str(), Translate("Own private key warning"), MB_YESNO) == IDYES) - ShowFirstRunDialog(); + { + CDlgFirstRun *d = new CDlgFirstRun; + d->DoModal(); + } } 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(nullptr, question.c_str(), Translate("Own secret key warning"), MB_YESNO) == IDYES) - ShowFirstRunDialog(); + { + CDlgFirstRun *d = new CDlgFirstRun; + d->DoModal(); + } } p2 = p; p = out.find("[", p); @@ -1719,7 +231,10 @@ void InitCheck() question += keyid; question += Translate(" expired and will not work.\nDo you want to set another key?"); if (MessageBoxA(nullptr, question.c_str(), Translate("Own secret key warning"), MB_YESNO) == IDYES) - ShowFirstRunDialog(); + { + CDlgFirstRun *d = new CDlgFirstRun; + d->DoModal(); + } } mir_free(expire_date); } @@ -1766,10 +281,8 @@ void InitCheck() } } -void ImportKey() +void ImportKey(MCONTACT hContact, std::wstring new_key) { - MCONTACT hContact = globals.new_key_hcnt; - globals.new_key_hcnt_mutex.unlock(); bool for_all_sub = false; if (db_mc_isMeta(hContact)) { if (MessageBox(nullptr, TranslateT("Do you want to load key for all subcontacts?"), TranslateT("Metacontact detected"), MB_YESNO) == IDYES) @@ -1780,14 +293,12 @@ void ImportKey() for (int i = 0; i < count; i++) { MCONTACT hcnt = db_mc_getSub(hContact, i); if (hcnt) - db_set_ws(hcnt, szGPGModuleName, "GPGPubKey", globals.new_key.c_str()); + db_set_ws(hcnt, szGPGModuleName, "GPGPubKey", new_key.c_str()); } } - else db_set_ws(metaGetMostOnline(hContact), szGPGModuleName, "GPGPubKey", globals.new_key.c_str()); + else db_set_ws(metaGetMostOnline(hContact), szGPGModuleName, "GPGPubKey", new_key.c_str()); } - else db_set_ws(hContact, szGPGModuleName, "GPGPubKey", globals.new_key.c_str()); - - globals.new_key.clear(); + else db_set_ws(hContact, szGPGModuleName, "GPGPubKey", new_key.c_str()); // gpg execute block std::vector<wstring> cmd; diff --git a/plugins/New_GPG/src/main.h b/plugins/New_GPG/src/main.h index fd0d688c6b..096eca802a 100755 --- a/plugins/New_GPG/src/main.h +++ b/plugins/New_GPG/src/main.h @@ -22,6 +22,8 @@ struct contact_data string key_in_prescense; }; +void ImportKey(MCONTACT hContact, std::wstring new_key); + #endif diff --git a/plugins/New_GPG/src/messages.cpp b/plugins/New_GPG/src/messages.cpp index fc240c5574..1741708642 100755 --- a/plugins/New_GPG/src/messages.cpp +++ b/plugins/New_GPG/src/messages.cpp @@ -214,10 +214,9 @@ void RecvMsgSvc_func(MCONTACT hContact, std::wstring str, char *msg, DWORD, DWOR s += mir_strlen(" ID "); db_set_s(db_mc_isMeta(hContact) ? metaGetMostOnline(hContact) : hContact, szGPGModuleName, "InKeyID", out.substr(s, out.find(",", s) - s).c_str()); } - void ShowLoadKeyPasswordWindow(); - globals.new_key_hcnt_mutex.lock(); - globals.new_key_hcnt = hContact; - ShowLoadKeyPasswordWindow(); + + CDlgKeyPasswordMsgBox *d = new CDlgKeyPasswordMsgBox(hContact); + d->DoModal(); std::vector<wstring> cmd2 = cmd; if (globals.password) { @@ -558,15 +557,12 @@ INT_PTR RecvMsgSvc(WPARAM w, LPARAM l) s1 = 0; while ((s1 = str.find(L"\r", s1)) != wstring::npos) str.erase(s1, 1); - void ShowNewKeyDialog(); if (((s2 = str.find(L"-----END PGP PUBLIC KEY BLOCK-----")) != wstring::npos) && ((s1 = str.find(L"-----BEGIN PGP PUBLIC KEY BLOCK-----")) != wstring::npos)) s2 += mir_wstrlen(L"-----END PGP PUBLIC KEY BLOCK-----"); else if (((s2 = str.find(L"-----BEGIN PGP PRIVATE KEY BLOCK-----")) != wstring::npos) && ((s1 = str.find(L"-----END PGP PRIVATE KEY BLOCK-----")) != wstring::npos)) s2 += mir_wstrlen(L"-----END PGP PRIVATE KEY BLOCK-----"); - globals.new_key.append(str.substr(s1, s2 - s1)); - //new_key_hcnt_mutex.lock(); - globals.new_key_hcnt = ccs->hContact; - ShowNewKeyDialog(); + CDlgNewKey *d = new CDlgNewKey(ccs->hContact, str.substr(s1, s2 - s1));
+ d->Show();
HistoryLog(ccs->hContact, db_event(msg, 0, 0, dbflags)); return 0; } @@ -992,84 +988,3 @@ int HookSendMsg(WPARAM w, LPARAM l) return 0; } -class CDlgKeyPasswordMsgBox : public CDlgBase //always modal -{ -public: - CDlgKeyPasswordMsgBox() : CDlgBase(globals.hInst, IDD_KEY_PASSWD), - lbl_KEYID(this, IDC_KEYID), - edit_KEY_PASSWORD(this, IDC_KEY_PASSWORD), - chk_DEFAULT_PASSWORD(this, IDC_DEFAULT_PASSWORD), chk_SAVE_PASSWORD(this, IDC_SAVE_PASSWORD), - btn_OK(this, IDOK), btn_CANCEL(this, IDCANCEL) - { - btn_OK.OnClick = Callback(this, &CDlgKeyPasswordMsgBox::onClick_OK); - btn_CANCEL.OnClick = Callback(this, &CDlgKeyPasswordMsgBox::onClick_CANCEL); - } - virtual void OnInitDialog() override - { - inkeyid = UniGetContactSettingUtf(globals.new_key_hcnt, szGPGModuleName, "InKeyID", ""); - globals.new_key_hcnt_mutex.unlock(); - - SetWindowPos(m_hwnd, nullptr, globals.key_password_rect.left, globals.key_password_rect.top, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW); - { - string questionstr = "Please enter password for key with ID: "; - questionstr += inkeyid; - mir_free(inkeyid); - lbl_KEYID.SetTextA(questionstr.c_str()); - chk_DEFAULT_PASSWORD.Disable(); - } - } - virtual void OnClose() override - { - DestroyWindow(m_hwnd); - } - virtual void OnDestroy() override - { - mir_free(inkeyid); - GetWindowRect(m_hwnd, &globals.key_password_rect); - db_set_dw(NULL, szGPGModuleName, "PasswordWindowX", globals.key_password_rect.left); - db_set_dw(NULL, szGPGModuleName, "PasswordWindowY", globals.key_password_rect.top); - delete this; - } - void onClick_OK(CCtrlButton*) - { - wchar_t *tmp = mir_wstrdup(edit_KEY_PASSWORD.GetText()); - if (tmp && tmp[0]) { - if (chk_SAVE_PASSWORD.GetState()) { - inkeyid = UniGetContactSettingUtf(globals.new_key_hcnt, szGPGModuleName, "InKeyID", ""); - if (inkeyid && inkeyid[0] && !chk_DEFAULT_PASSWORD.GetState()) { - string dbsetting = "szKey_"; - dbsetting += inkeyid; - dbsetting += "_Password"; - db_set_ws(NULL, szGPGModuleName, dbsetting.c_str(), tmp); - } - else - db_set_ws(NULL, szGPGModuleName, "szKeyPassword", tmp); - } - if (globals.password) - mir_free(globals.password); - globals.password = (wchar_t*)mir_alloc(sizeof(wchar_t)*(mir_wstrlen(tmp) + 1)); - mir_wstrcpy(globals.password, tmp); - } - mir_free(inkeyid); - DestroyWindow(m_hwnd); - } - void onClick_CANCEL(CCtrlButton*) - { - globals._terminate = true; - DestroyWindow(m_hwnd); - } -private: - char *inkeyid = nullptr; - CCtrlData lbl_KEYID; - CCtrlEdit edit_KEY_PASSWORD; - CCtrlCheck chk_DEFAULT_PASSWORD, chk_SAVE_PASSWORD; - CCtrlButton btn_OK, btn_CANCEL; -}; - - - -void ShowLoadKeyPasswordWindow() -{ - CDlgKeyPasswordMsgBox *d = new CDlgKeyPasswordMsgBox; - d->DoModal(); -} diff --git a/plugins/New_GPG/src/options.cpp b/plugins/New_GPG/src/options.cpp index 4d6b3a5bc6..8ff4c114c1 100755 --- a/plugins/New_GPG/src/options.cpp +++ b/plugins/New_GPG/src/options.cpp @@ -261,8 +261,8 @@ public: void onClick_SELECT_KEY(CCtrlButton*) { - void ShowFirstRunDialog(); - ShowFirstRunDialog(); + CDlgFirstRun *d = new CDlgFirstRun;
+ d->Show();
} void onClick_SAVE_KEY_BUTTON(CCtrlButton*) @@ -678,8 +678,8 @@ public: void onClick_SELECT_EXISTING(CCtrlButton*) { - void ShowSelectExistingKeyDialog(); - ShowSelectExistingKeyDialog(); + CDlgLoadExistingKey *d = new CDlgLoadExistingKey; + d->Show(); } void onClick_OK(CCtrlButton*) @@ -1048,10 +1048,8 @@ public: } void onClick_IMPORT(CCtrlButton*) { - globals.new_key_hcnt_mutex.lock(); - globals.new_key_hcnt = hContact; - void ShowImportKeyDialog(); - ShowImportKeyDialog(); + CDlgImportKey *d = new CDlgImportKey(hContact); + d->Show(); } }; diff --git a/plugins/New_GPG/src/ui.cpp b/plugins/New_GPG/src/ui.cpp index 4271e8d442..c6d34470d4 100755 --- a/plugins/New_GPG/src/ui.cpp +++ b/plugins/New_GPG/src/ui.cpp @@ -17,6 +17,9 @@ #include "stdafx.h" +//HWND hwndFirstRun = nullptr, hwndSetDirs = nullptr, hwndNewKey = nullptr, hwndKeyGen = nullptr, hwndSelectExistingKey = nullptr; + +CCtrlListView *list_hwndList_g = nullptr; void CDlgEncryptedFileMsgBox::OnInitDialog() @@ -165,3 +168,1279 @@ void CDlgChangePasswdMsgBox::onClick_OK(CCtrlButton*) } this->Close(); } + + + +CDlgFirstRun::CDlgFirstRun() : CDlgBase(globals.hInst, IDD_FIRST_RUN), +list_KEY_LIST(this, IDC_KEY_LIST), +btn_COPY_PUBKEY(this, IDC_COPY_PUBKEY), btn_EXPORT_PRIVATE(this, IDC_EXPORT_PRIVATE), btn_CHANGE_PASSWD(this, IDC_CHANGE_PASSWD), btn_GENERATE_RANDOM(this, IDC_GENERATE_RANDOM), +btn_GENERATE_KEY(this, IDC_GENERATE_KEY), btn_OTHER(this, IDC_OTHER), btn_DELETE_KEY(this, IDC_DELETE_KEY), btn_OK(this, ID_OK), +edit_KEY_PASSWORD(this, IDC_KEY_PASSWORD), +combo_ACCOUNT(this, IDC_ACCOUNT), +lbl_KEY_ID(this, IDC_KEY_ID), lbl_GENERATING_KEY(this, IDC_GENERATING_KEY) +{ + fp[0] = 0; + list_hwndList_g = &list_KEY_LIST; + + btn_COPY_PUBKEY.OnClick = Callback(this, &CDlgFirstRun::onClick_COPY_PUBKEY); + btn_EXPORT_PRIVATE.OnClick = Callback(this, &CDlgFirstRun::onClick_EXPORT_PRIVATE); + btn_CHANGE_PASSWD.OnClick = Callback(this, &CDlgFirstRun::onClick_CHANGE_PASSWD); + btn_GENERATE_RANDOM.OnClick = Callback(this, &CDlgFirstRun::onClick_GENERATE_RANDOM); + btn_GENERATE_KEY.OnClick = Callback(this, &CDlgFirstRun::onClick_GENERATE_KEY); + btn_OTHER.OnClick = Callback(this, &CDlgFirstRun::onClick_OTHER); + btn_DELETE_KEY.OnClick = Callback(this, &CDlgFirstRun::onClick_DELETE_KEY); + btn_OK.OnClick = Callback(this, &CDlgFirstRun::onClick_OK); + +} +void CDlgFirstRun::OnInitDialog() +{ + SetWindowPos(m_hwnd, nullptr, globals.firstrun_rect.left, globals.firstrun_rect.top, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW); + SetCaption(TranslateT("Set own key")); + btn_COPY_PUBKEY.Disable(); + btn_EXPORT_PRIVATE.Disable(); + btn_CHANGE_PASSWD.Disable(); + + list_KEY_LIST.AddColumn(0, TranslateT("Key ID"), 50); + list_KEY_LIST.AddColumn(1, TranslateT("Email"), 30); + list_KEY_LIST.AddColumn(2, TranslateT("Name"), 250); + list_KEY_LIST.AddColumn(3, TranslateT("Creation date"), 30); + list_KEY_LIST.AddColumn(4, TranslateT("Expire date"), 30); + list_KEY_LIST.AddColumn(5, TranslateT("Key length"), 30); + list_KEY_LIST.AddColumn(6, TranslateT("Accounts"), 30); + list_KEY_LIST.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_SINGLEROW); + + refresh_key_list(); + + { + combo_ACCOUNT.AddString(TranslateT("Default")); + int count = 0; + PROTOACCOUNT **accounts; + Proto_EnumAccounts(&count, &accounts); + for (int n = 0; n < count; n++) { + if (StriStr(accounts[n]->szModuleName, "metacontacts")) + continue; + if (StriStr(accounts[n]->szModuleName, "weather")) + continue; + std::string acc = toUTF8(accounts[n]->tszAccountName); + acc += "("; + acc += accounts[n]->szModuleName; + acc += ")"; + //acc += "_KeyID"; + combo_ACCOUNT.AddStringA(acc.c_str()); + } + combo_ACCOUNT.SelectString(TranslateT("Default")); + string keyinfo = Translate("key ID"); + keyinfo += ": "; + char *keyid = UniGetContactSettingUtf(NULL, szGPGModuleName, "KeyID", ""); + keyinfo += (mir_strlen(keyid) > 0) ? keyid : Translate("not set"); + mir_free(keyid); + lbl_KEY_ID.SetTextA(keyinfo.c_str()); + } + combo_ACCOUNT.OnChange = Callback(this, &CDlgFirstRun::onChange_ACCOUNT); + list_KEY_LIST.OnItemChanged = Callback(this, &CDlgFirstRun::onChange_KEY_LIST); +} +void CDlgFirstRun::onClick_COPY_PUBKEY(CCtrlButton*) +{ + int i = list_KEY_LIST.GetSelectionMark(); + if (i == -1) + return; + if (OpenClipboard(m_hwnd)) + { + list_KEY_LIST.GetItemText(i, 0, fp, _countof(fp)); + 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)) + return; + if (result == pxNotFound) + return; + boost::algorithm::erase_all(out, "\r"); + HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, out.size() + 1); + if (!hMem) { + MessageBox(nullptr, TranslateT("Failed to allocate memory"), TranslateT("Error"), MB_OK); + return; + } + char *szKey = (char*)GlobalLock(hMem); + if (!szKey) { + wchar_t msg[64]; + mir_snwprintf(msg, TranslateT("Failed to lock memory with error %d"), GetLastError()); + MessageBox(nullptr, msg, TranslateT("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); + wchar_t msg[64]; + mir_snwprintf(msg, TranslateT("Failed write to clipboard with error %d"), GetLastError()); + MessageBox(nullptr, msg, TranslateT("Error"), MB_OK); + } + CloseClipboard(); + } +} +void CDlgFirstRun::onClick_EXPORT_PRIVATE(CCtrlButton*) +{ + { + int i = list_KEY_LIST.GetSelectionMark(); + if (i == -1) + return; + wchar_t *p = GetFilePath(L"Choose file to export key", L"*", L"Any file", true); + if (!p || !p[0]) { + delete[] p; + //TODO: handle error + return; + } + char *path = mir_u2a(p); + delete[] p; + std::ofstream file; + file.open(path, std::ios::trunc | std::ios::out); + mir_free(path); + if (!file.is_open()) + return; //TODO: handle error + list_KEY_LIST.GetItemText(i, 0, fp, _countof(fp)); + 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)) { + return; + } + if (result == pxNotFound) + return; + boost::algorithm::erase_all(out, "\r"); + file << out; + if (file.is_open()) + file.close(); + } +} +void CDlgFirstRun::onClick_CHANGE_PASSWD(CCtrlButton*) +{ + int i = list_KEY_LIST.GetSelectionMark(); + if (i == -1) + return; + list_KEY_LIST.GetItemText(i, 0, globals.key_id_global, _countof(globals.key_id_global)); + + //temporary code follows + std::vector<std::wstring> cmd; + std::string old_pass, new_pass; + string output; + DWORD exitcode; + cmd.push_back(L"--edit-key"); + cmd.push_back(globals.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, ¶ms)); + if (!gpg_thread.timed_join(boost::posix_time::minutes(10))) { + gpg_thread.~thread(); + if (params.child) + boost::process::terminate(*(params.child)); + if (globals.bDebugLog) + globals.debuglog << std::string(time_str() + ": GPG execution timed out, aborted"); + this->Close(); + } + +} +void CDlgFirstRun::onClick_GENERATE_RANDOM(CCtrlButton*) +{ + lbl_GENERATING_KEY.SendMsg(WM_SETFONT, (WPARAM)globals.bold_font, TRUE); + lbl_GENERATING_KEY.SetText(TranslateT("Generating new random key, please wait")); + btn_GENERATE_KEY.Disable(); + btn_OTHER.Disable(); + btn_DELETE_KEY.Disable(); + list_KEY_LIST.Disable(); + btn_GENERATE_RANDOM.Disable(); + gpg_use_new_random_key(combo_ACCOUNT.GetTextA()); + this->Close(); +} +void CDlgFirstRun::onClick_GENERATE_KEY(CCtrlButton*) +{ + CDlgKeyGen *d = new CDlgKeyGen; + d->DoModal(); + refresh_key_list(); +} +void CDlgFirstRun::onClick_OTHER(CCtrlButton*) +{ + void ShowLoadPublicKeyDialog(bool = false); + globals.item_num = 0; //black magic here + globals.user_data[1] = 0; + ShowLoadPublicKeyDialog(true); + refresh_key_list(); +} +void CDlgFirstRun::onClick_DELETE_KEY(CCtrlButton*) +{ + int i = list_KEY_LIST.GetSelectionMark(); + if (i == -1) + return; + list_KEY_LIST.GetItemText(i, 0, fp, _countof(fp)); + { + 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)) + return; + if (result == pxNotFound) + return; + string::size_type s = out.find("Key fingerprint = "); + s += mir_strlen("Key fingerprint = "); + string::size_type s2 = out.find("\n", s); + wchar_t *str = nullptr; + { + 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); + + str = mir_a2u(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(str); + mir_free(str); + if (!gpg_launcher(params)) + return; + if (result == pxNotFound) + return; + } + { + char *buf = mir_strdup(combo_ACCOUNT.GetTextA()); + if (!mir_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()); + } + if (buf) + mir_free(buf); + } + list_KEY_LIST.DeleteItem(i); +} +void CDlgFirstRun::onClick_OK(CCtrlButton*) +{ + { + int i = list_KEY_LIST.GetSelectionMark(); + if (i == -1) + return; + + list_KEY_LIST.GetItemText(i, 0, fp, _countof(fp)); + wchar_t *name = new wchar_t[65]; + list_KEY_LIST.GetItemText(i, 2, name, 64); + { + if (wcschr(name, '(')) { + wstring str = name; + wstring::size_type p = str.find(L"(") - 1; + mir_wstrcpy(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)) + { + delete[] name; + return; + } + if (result == pxNotFound) + { + delete[] name; + return; + } + + boost::algorithm::erase_all(out, "\r"); + { + char *buf = mir_strdup(combo_ACCOUNT.GetTextA()); + if (!mir_strcmp(buf, Translate("Default"))) { + db_set_s(NULL, szGPGModuleName, "GPGPubKey", out.c_str()); + db_set_ws(NULL, szGPGModuleName, "KeyMainName", name); + db_set_ws(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_ws(NULL, szGPGModuleName, acc_str.c_str(), name); + acc_str = buf; + acc_str += "_KeyID"; + db_set_ws(NULL, szGPGModuleName, acc_str.c_str(), fp); + } + if (!mir_strcmp(buf, Translate("Default"))) { + wstring keyinfo = TranslateT("Default private key ID"); + keyinfo += L": "; + keyinfo += (fp[0]) ? fp : L"not set"; + extern HWND hwndCurKey_p; + SetWindowText(hwndCurKey_p, keyinfo.c_str()); + } + if (buf) + mir_free(buf); + } + wchar_t *passwd = mir_wstrdup(edit_KEY_PASSWORD.GetText()); + if (passwd && passwd[0]) + { + string dbsetting = "szKey_"; + char *keyid = mir_u2a(fp); + dbsetting += keyid; + mir_free(keyid); + dbsetting += "_Password"; + db_set_ws(NULL, szGPGModuleName, dbsetting.c_str(), passwd); + } + mir_free(passwd); + delete[] name; + } + //bAutoExchange = CheckStateStoreDB(hwndDlg, IDC_AUTO_EXCHANGE, "bAutoExchange") != 0; //TODO: check is it just typo, or doing something + globals.gpg_valid = isGPGValid(); + globals.gpg_keyexist = isGPGKeyExist(); + DestroyWindow(m_hwnd); +} +void CDlgFirstRun::onChange_ACCOUNT(CCtrlCombo*) +{ + char *buf = mir_strdup(combo_ACCOUNT.GetTextA()); + if (!mir_strcmp(buf, Translate("Default"))) { + string keyinfo = Translate("key ID"); + keyinfo += ": "; + char *keyid = UniGetContactSettingUtf(NULL, szGPGModuleName, "KeyID", ""); + keyinfo += (mir_strlen(keyid) > 0) ? keyid : Translate("not set"); + mir_free(keyid); + lbl_KEY_ID.SetTextA(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 += (mir_strlen(keyid) > 0) ? keyid : Translate("not set"); + mir_free(keyid); + lbl_KEY_ID.SetTextA(keyinfo.c_str()); + } + if (buf) + mir_free(buf); +} +void CDlgFirstRun::onChange_KEY_LIST(CCtrlListView::TEventInfo *ev) //TODO: check if this work +{ + if (ev->nmlv) + { + NMLISTVIEW *hdr = ev->nmlv; + + if (hdr->hdr.code == NM_CLICK) { + btn_OK.Enable(); + btn_COPY_PUBKEY.Enable(); + btn_EXPORT_PRIVATE.Enable(); + btn_CHANGE_PASSWD.Enable(); + } + } +} +void CDlgFirstRun::OnDestroy() +{ + GetWindowRect(m_hwnd, &globals.firstrun_rect); + db_set_dw(NULL, szGPGModuleName, "FirstrunWindowX", globals.firstrun_rect.left); + db_set_dw(NULL, szGPGModuleName, "FirstrunWindowY", globals.firstrun_rect.top); + delete this; +} + + +void CDlgFirstRun::refresh_key_list() +{ + list_KEY_LIST.DeleteAllItems(); + int i = 1; + { + { + //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)) + return; + if (result == pxNotFound) + return; + } + 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; + wchar_t *key_len = mir_wstrdup(toUTF16(out.substr(p, p2 - p)).c_str()), *creation_date = nullptr, *expire_date = nullptr; + 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 += mir_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(); + wchar_t buf[5]; + wcsncpy_s(buf, expire_date, _TRUNCATE); + int year = _wtoi(buf); + if (year < now.date().year()) + expired = true; + else if (year == now.date().year()) { + wcsncpy_s(buf, (expire_date + 5), _TRUNCATE); + int month = _wtoi(buf); + if (month < now.date().month()) + expired = true; + else if (month == now.date().month()) { + wcsncpy_s(buf, (expire_date + 8), _TRUNCATE); + unsigned day = _wtoi(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 + } + } + } + int row = list_KEY_LIST.AddItem(L"", 0); + list_KEY_LIST.SetItemText(row, 3, creation_date); + mir_free(creation_date); + if (expire_date) { + list_KEY_LIST.SetItemText(row, 4, expire_date); + mir_free(expire_date); + } + list_KEY_LIST.SetItemText(row, 5, key_len); + mir_free(key_len); + list_KEY_LIST.SetItemText(row, 0, (wchar_t*)key_id.c_str()); + p = out.find("uid ", p); + p2 = out.find_first_not_of(" ", p + 5); + p = out.find("<", p2); + + wstring tmp = toUTF16(out.substr(p2, p - p2)); + list_KEY_LIST.SetItemText(row, 2, (wchar_t*)tmp.c_str()); + + p++; + p2 = out.find(">", p); + + tmp = toUTF16(out.substr(p, p2 - p)); + list_KEY_LIST.SetItemText(row, 1, (wchar_t*)tmp.c_str()); + + // get accounts + int count = 0; + PROTOACCOUNT **accounts; + Proto_EnumAccounts(&count, &accounts); + std::wstring accs; + for (int n = 0; n < count; n++) { + std::string setting = toUTF8(accounts[n]->tszAccountName); + setting += "("; + setting += accounts[n]->szModuleName; + setting += ")"; + setting += "_KeyID"; + wchar_t *str = UniGetContactSettingUtf(NULL, szGPGModuleName, setting.c_str(), L""); + if (key_id == str) { + if (!accs.empty()) + accs += L","; + accs += accounts[n]->tszAccountName; + } + mir_free(str); + } + list_KEY_LIST.SetItemText(row, 6, (wchar_t*)accs.c_str()); + } + i++; + list_KEY_LIST.SetColumnWidth(0, LVSCW_AUTOSIZE); + list_KEY_LIST.SetColumnWidth(1, LVSCW_AUTOSIZE); + list_KEY_LIST.SetColumnWidth(2, LVSCW_AUTOSIZE); + list_KEY_LIST.SetColumnWidth(3, LVSCW_AUTOSIZE); + list_KEY_LIST.SetColumnWidth(4, LVSCW_AUTOSIZE); + list_KEY_LIST.SetColumnWidth(5, LVSCW_AUTOSIZE); + list_KEY_LIST.SetColumnWidth(6, LVSCW_AUTOSIZE); + } + } +} + + + +CDlgGpgBinOpts::CDlgGpgBinOpts() : CDlgBase(globals.hInst, IDD_BIN_PATH), +btn_SET_BIN_PATH(this, IDC_SET_BIN_PATH), btn_SET_HOME_DIR(this, IDC_SET_HOME_DIR), btn_OK(this, ID_OK), btn_GENERATE_RANDOM(this, IDC_GENERATE_RANDOM), +edit_BIN_PATH(this, IDC_BIN_PATH), edit_HOME_DIR(this, IDC_HOME_DIR), +chk_AUTO_EXCHANGE(this, IDC_AUTO_EXCHANGE) +{ + btn_SET_BIN_PATH.OnClick = Callback(this, &CDlgGpgBinOpts::onClick_SET_BIN_PATH); + btn_SET_HOME_DIR.OnClick = Callback(this, &CDlgGpgBinOpts::onClick_SET_HOME_DIR); + btn_OK.OnClick = Callback(this, &CDlgGpgBinOpts::onClick_OK); + btn_GENERATE_RANDOM.OnClick = Callback(this, &CDlgGpgBinOpts::onClick_GENERATE_RANDOM); +} +void CDlgGpgBinOpts::OnInitDialog() +{ + CMStringW path; + bool gpg_exists = false, lang_exists = false; + { + wchar_t mir_path[MAX_PATH]; + PathToAbsoluteW(L"\\", mir_path); + SetCurrentDirectoryW(mir_path); + + CMStringW gpg_path(mir_path); gpg_path.Append(L"\\GnuPG\\gpg.exe"); + CMStringW gpg_lang_path(mir_path); gpg_lang_path.Append(L"\\GnuPG\\gnupg.nls\\en@quot.mo"); + + if (boost::filesystem::exists(gpg_path.c_str())) { + gpg_exists = true; + path = L"GnuPG\\gpg.exe"; + } + else path = gpg_path; + + if (boost::filesystem::exists(gpg_lang_path.c_str())) + lang_exists = true; + if (gpg_exists && !lang_exists) + MessageBox(nullptr, TranslateT("GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned."), TranslateT("Warning"), MB_OK); + } + DWORD len = MAX_PATH; + bool bad_version = false; + { + ptrW tmp; + if (!gpg_exists) { + tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szGpgBinPath", (SHGetValueW(HKEY_CURRENT_USER, L"Software\\GNU\\GnuPG", L"gpgProgram", 0, (void*)path.c_str(), &len) == ERROR_SUCCESS) ? path.c_str() : L""); + if (tmp[0]) + if (!boost::filesystem::exists((wchar_t*)tmp)) + MessageBox(nullptr, TranslateT("Wrong GPG binary location found in system.\nPlease choose another location"), TranslateT("Warning"), MB_OK); + } + else tmp = mir_wstrdup(path.c_str()); + + edit_BIN_PATH.SetText(tmp); + if (gpg_exists/* && lang_exists*/) { + db_set_ws(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; + bool _gpg_valid = globals.gpg_valid; + globals.gpg_valid = true; + gpg_launcher(params); + globals.gpg_valid = _gpg_valid; //TODO: check this + db_unset(NULL, szGPGModuleName, "szGpgBinPath"); + string::size_type p1 = out.find("(GnuPG) "); + if (p1 != string::npos) { + p1 += mir_strlen("(GnuPG) "); + if (out[p1] != '1') + bad_version = true; + } + else { + bad_version = false; + MessageBox(nullptr, TranslateT("This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin."), TranslateT("Error"), MB_OK); + } + if (bad_version) + MessageBox(nullptr, TranslateT("Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin."), TranslateT("Warning"), MB_OK); + } + } + { + ptrW tmp(UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", L"")); + if (!tmp[0]) { + wchar_t mir_path[MAX_PATH]; + PathToAbsoluteW(L"\\", mir_path); + mir_wstrcat(mir_path, L"\\gpg"); + if (_waccess(mir_path, 0) != -1) { + tmp = mir_wstrdup(mir_path); + MessageBox(nullptr, TranslateT("\"GPG\" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set."), TranslateT("Info"), MB_OK); + } + else { + wstring path_ = _wgetenv(L"APPDATA"); + path_ += L"\\GnuPG"; + tmp = mir_wstrdup(path_.c_str()); + } + } + edit_HOME_DIR.SetText(!gpg_exists ? tmp : L"gpg"); + } + //TODO: additional check for write access + if (gpg_exists && lang_exists && !bad_version) + MessageBox(nullptr, TranslateT("Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue."), TranslateT("Info"), MB_OK); + chk_AUTO_EXCHANGE.Enable(); +} +void CDlgGpgBinOpts::onClick_SET_BIN_PATH(CCtrlButton*) +{ + GetFilePath(L"Choose gpg.exe", "szGpgBinPath", L"*.exe", L"EXE Executables"); + CMStringW tmp(ptrW(UniGetContactSettingUtf(NULL, szGPGModuleName, "szGpgBinPath", L"gpg.exe"))); + edit_BIN_PATH.SetText(tmp); + wchar_t mir_path[MAX_PATH]; + PathToAbsoluteW(L"\\", mir_path); + if (tmp.Find(mir_path, 0) == 0) + { + CMStringW path = tmp.Mid(mir_wstrlen(mir_path)); + edit_BIN_PATH.SetText(path); + } + +} +void CDlgGpgBinOpts::onClick_SET_HOME_DIR(CCtrlButton*) +{ + GetFolderPath(L"Set home directory", "szHomePath"); + CMStringW tmp(ptrW(UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", L""))); + edit_HOME_DIR.SetText(tmp); + wchar_t mir_path[MAX_PATH]; + PathToAbsoluteW(L"\\", mir_path); + PathToAbsoluteW(L"\\", mir_path); + if (tmp.Find(mir_path, 0) == 0) { + CMStringW path = tmp.Mid(mir_wstrlen(mir_path)); + edit_HOME_DIR.SetText(path); + } + +} +void CDlgGpgBinOpts::onClick_OK(CCtrlButton*) +{ + if (gpg_validate_paths(edit_BIN_PATH.GetText(), edit_HOME_DIR.GetText())) + { + gpg_save_paths(edit_BIN_PATH.GetText(), edit_HOME_DIR.GetText()); + globals.gpg_valid = true; + db_set_b(NULL, szGPGModuleName, "FirstRun", 0); + this->Hide(); + CDlgFirstRun *d = new CDlgFirstRun; + d->Show(); + this->Close(); + } +} +void CDlgGpgBinOpts::onClick_GENERATE_RANDOM(CCtrlButton*) +{ + if (gpg_validate_paths(edit_BIN_PATH.GetText(), edit_HOME_DIR.GetText())) + { + gpg_save_paths(edit_BIN_PATH.GetText(), edit_HOME_DIR.GetText()); + globals.gpg_valid = true; + if (gpg_use_new_random_key()) + { + db_set_b(NULL, szGPGModuleName, "bAutoExchange", globals.bAutoExchange = chk_AUTO_EXCHANGE.GetState()); + globals.gpg_valid = true; + db_set_b(NULL, szGPGModuleName, "FirstRun", 0); + this->Close(); + } + } +} +void CDlgGpgBinOpts::OnDestroy() +{ + void InitCheck(); + InitCheck(); + delete this; +} + +CDlgNewKey::CDlgNewKey(MCONTACT _hContact, wstring _new_key) : CDlgBase(globals.hInst, IDD_NEW_KEY), +lbl_KEY_FROM(this, IDC_KEY_FROM), lbl_MESSAGE(this, IDC_MESSAGE), +btn_IMPORT(this, ID_IMPORT), btn_IMPORT_AND_USE(this, IDC_IMPORT_AND_USE), btn_IGNORE_KEY(this, IDC_IGNORE_KEY) +{ + hContact = _hContact; + new_key = _new_key; + btn_IMPORT.OnClick = Callback(this, &CDlgNewKey::onClick_IMPORT); + btn_IMPORT_AND_USE.OnClick = Callback(this, &CDlgNewKey::onClick_IMPORT_AND_USE); + btn_IGNORE_KEY.OnClick = Callback(this, &CDlgNewKey::onClick_IGNORE_KEY); + +} +void CDlgNewKey::OnInitDialog() +{ + //new_key_hcnt_mutex.unlock(); + SetWindowPos(m_hwnd, nullptr, globals.new_key_rect.left, globals.new_key_rect.top, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW); + wchar_t *tmp = UniGetContactSettingUtf(hContact, szGPGModuleName, "GPGPubKey", L""); + lbl_MESSAGE.SetText(tmp[0] ? TranslateT("There is existing key for contact, would you like to replace it with new key?") : TranslateT("New public key was received, do you want to import it?")); + btn_IMPORT_AND_USE.Enable(db_get_b(hContact, szGPGModuleName, "GPGEncryption", 0)); + btn_IMPORT.SetText(tmp[0] ? TranslateT("Replace") : TranslateT("Accept")); + mir_free(tmp); + tmp = new wchar_t[256]; + mir_snwprintf(tmp, 255 * sizeof(wchar_t), TranslateT("Received key from %s"), pcli->pfnGetContactDisplayName(hContact, 0)); + lbl_KEY_FROM.SetText(tmp); + mir_free(tmp); +} +void CDlgNewKey::OnDestroy() +{ + GetWindowRect(m_hwnd, &globals.new_key_rect); + db_set_dw(NULL, szGPGModuleName, "NewKeyWindowX", globals.new_key_rect.left); + db_set_dw(NULL, szGPGModuleName, "NewKeyWindowY", globals.new_key_rect.top); + delete this; +} +void CDlgNewKey::onClick_IMPORT(CCtrlButton*) +{ + ImportKey(hContact, new_key); + this->Close(); +} +void CDlgNewKey::onClick_IMPORT_AND_USE(CCtrlButton*) +{ + ImportKey(hContact, new_key); + db_set_b(hContact, szGPGModuleName, "GPGEncryption", 1); + void setSrmmIcon(MCONTACT hContact); + void setClistIcon(MCONTACT hContact); + setSrmmIcon(hContact); + setClistIcon(hContact); + this->Close(); +} +void CDlgNewKey::onClick_IGNORE_KEY(CCtrlButton*) +{ + this->Close(); +} + +CDlgKeyGen::CDlgKeyGen() : CDlgBase(globals.hInst, IDD_KEY_GEN), +combo_KEY_TYPE(this, IDC_KEY_TYPE), +edit_KEY_LENGTH(this, IDC_KEY_LENGTH), edit_KEY_PASSWD(this, IDC_KEY_PASSWD), edit_KEY_REAL_NAME(this, IDC_KEY_REAL_NAME), edit_KEY_EMAIL(this, IDC_KEY_EMAIL), edit_KEY_COMMENT(this, IDC_KEY_COMMENT), +edit_KEY_EXPIRE_DATE(this, IDC_KEY_EXPIRE_DATE), +lbl_GENERATING_TEXT(this, IDC_GENERATING_TEXT), +btn_OK(this, IDOK), btn_CANCEL(this, IDCANCEL) +{ + btn_OK.OnClick = Callback(this, &CDlgKeyGen::onClick_OK); + btn_CANCEL.OnClick = Callback(this, &CDlgKeyGen::onClick_CANCEL); +} +void CDlgKeyGen::OnInitDialog() +{ + SetWindowPos(m_hwnd, nullptr, globals.key_gen_rect.left, globals.key_gen_rect.top, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW); + SetCaption(TranslateT("Key Generation dialog")); + combo_KEY_TYPE.AddString(L"RSA"); + combo_KEY_TYPE.AddString(L"DSA"); + combo_KEY_TYPE.SelectString(L"RSA"); + edit_KEY_EXPIRE_DATE.SetText(L"0"); + edit_KEY_LENGTH.SetText(L"4096"); +} + +void CDlgKeyGen::onClick_OK(CCtrlButton*) +{ + { + wstring path; + { //data sanity checks + wchar_t *tmp = mir_wstrdup(combo_KEY_TYPE.GetText()); + if (!tmp) + { + MessageBox(nullptr, TranslateT("You must set encryption algorithm first"), TranslateT("Error"), MB_OK); + return; + } + if (mir_wstrlen(tmp) < 3) + { + mir_free(tmp); + tmp = nullptr; + MessageBox(nullptr, TranslateT("You must set encryption algorithm first"), TranslateT("Error"), MB_OK); + return; + } + mir_free(tmp); + tmp = mir_wstrdup(edit_KEY_LENGTH.GetText()); + if (!tmp) + { + MessageBox(nullptr, TranslateT("Key length must be of length from 1024 to 4096 bits"), TranslateT("Error"), MB_OK); + return; + } + int length = _wtoi(tmp); + mir_free(tmp); + if (length < 1024 || length > 4096) { + MessageBox(nullptr, TranslateT("Key length must be of length from 1024 to 4096 bits"), TranslateT("Error"), MB_OK); + return; + } + tmp = mir_wstrdup(edit_KEY_EXPIRE_DATE.GetText()); + if (!tmp) + { + MessageBox(nullptr, TranslateT("Invalid date"), TranslateT("Error"), MB_OK); + return; + } + if (mir_wstrlen(tmp) != 10 && tmp[0] != '0') { + MessageBox(nullptr, TranslateT("Invalid date"), TranslateT("Error"), MB_OK); + mir_free(tmp); + return; + } + mir_free(tmp); + tmp = mir_wstrdup(edit_KEY_REAL_NAME.GetText()); + if (!tmp) + { + MessageBox(nullptr, TranslateT("Name must contain at least 5 characters"), TranslateT("Error"), MB_OK); + return; + } + if (mir_wstrlen(tmp) < 5) { + MessageBox(nullptr, TranslateT("Name must contain at least 5 characters"), TranslateT("Error"), MB_OK); + mir_free(tmp); + return; + } + else if (wcschr(tmp, '(') || wcschr(tmp, ')')) + { + MessageBox(nullptr, TranslateT("Name cannot contain '(' or ')'"), TranslateT("Error"), MB_OK); + mir_free(tmp); + return; + } + mir_free(tmp); + tmp = mir_wstrdup(edit_KEY_EMAIL.GetText()); + if (!tmp) + { + MessageBox(nullptr, TranslateT("Invalid Email"), TranslateT("Error"), MB_OK); + return; + } + if ((mir_wstrlen(tmp)) < 5 || (!wcschr(tmp, '@')) || (!wcschr(tmp, '.'))) { + MessageBox(nullptr, TranslateT("Invalid Email"), TranslateT("Error"), MB_OK); + mir_free(tmp); + return; + } + mir_free(tmp); + } + { //generating key file + wchar_t *tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", L""); + char *tmp2;// = mir_u2a(tmp); + path = tmp; + mir_free(tmp); + // mir_free(tmp2); + path.append(L"\\new_key"); + wfstream f(path.c_str(), std::ios::out); + if (!f.is_open()) { + MessageBox(nullptr, TranslateT("Failed to open file"), TranslateT("Error"), MB_OK); + return; + } + f << "Key-Type: "; + tmp2 = mir_u2a(combo_KEY_TYPE.GetText()); + char *subkeytype = (char*)mir_alloc(6); + if (strstr(tmp2, "RSA")) + mir_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 + mir_strcpy(subkeytype, "ELG-E"); + f << tmp2; + mir_free(tmp2); + f << "\n"; + f << "Key-Length: "; + f << _wtoi(edit_KEY_LENGTH.GetText()); + f << "\n"; + f << "Subkey-Length: "; + f << _wtoi(edit_KEY_LENGTH.GetText()); + f << "\n"; + f << "Subkey-Type: "; + f << subkeytype; + mir_free(subkeytype); + f << "\n"; + if (edit_KEY_PASSWD.GetText()[0]) + { + f << "Passphrase: "; + f << toUTF8(edit_KEY_PASSWD.GetText()).c_str(); + f << "\n"; + } + f << "Name-Real: "; + f << toUTF8(edit_KEY_REAL_NAME.GetText()).c_str(); + f << "\n"; + if (edit_KEY_COMMENT.GetText()[0]) + { + f << "Name-Comment: "; + f << toUTF8(edit_KEY_COMMENT.GetText()).c_str(); + f << "\n"; + } + f << "Name-Email: "; + f << toUTF8(edit_KEY_EMAIL.GetText()).c_str(); + f << "\n"; + f << "Expire-Date: "; + f << toUTF8(edit_KEY_EXPIRE_DATE.GetText()).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; + lbl_GENERATING_TEXT.SendMsg(WM_SETFONT, (WPARAM)globals.bold_font, TRUE); + lbl_GENERATING_TEXT.SetText(TranslateT("Generating new key, please wait...")); + btn_CANCEL.Disable(); + btn_OK.Disable(); + combo_KEY_TYPE.Disable(); + edit_KEY_LENGTH.Disable(); + edit_KEY_PASSWD.Disable(); + edit_KEY_REAL_NAME.Disable(); + edit_KEY_EMAIL.Disable(); + edit_KEY_COMMENT.Disable(); + edit_KEY_EXPIRE_DATE.Disable(); + if (!gpg_launcher(params, boost::posix_time::minutes(10))) + return; + if (result == pxNotFound) + return; + } + boost::filesystem::remove(path); + } + this->Close(); +} +void CDlgKeyGen::onClick_CANCEL(CCtrlButton*) +{ + this->Close(); +} +void CDlgKeyGen::OnDestroy() +{ + GetWindowRect(m_hwnd, &globals.key_gen_rect); + db_set_dw(NULL, szGPGModuleName, "KeyGenWindowX", globals.key_gen_rect.left); + db_set_dw(NULL, szGPGModuleName, "KeyGenWindowY", globals.key_gen_rect.top); + delete this; +} + +CDlgLoadExistingKey::CDlgLoadExistingKey() : CDlgBase(globals.hInst, IDD_LOAD_EXISTING_KEY), +btn_OK(this, IDOK), btn_CANCEL(this, IDCANCEL), +list_EXISTING_KEY_LIST(this, IDC_EXISTING_KEY_LIST) +{ + id[0] = 0; + btn_OK.OnClick = Callback(this, &CDlgLoadExistingKey::onClick_OK); + btn_CANCEL.OnClick = Callback(this, &CDlgLoadExistingKey::onClick_CANCEL); + +} +void CDlgLoadExistingKey::OnInitDialog() +{ + SetWindowPos(m_hwnd, nullptr, globals.load_existing_key_rect.left, globals.load_existing_key_rect.top, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW); + + + list_EXISTING_KEY_LIST.AddColumn(0, TranslateT("Key ID"), 50); + list_EXISTING_KEY_LIST.AddColumn(1, TranslateT("Email"), 30); + list_EXISTING_KEY_LIST.AddColumn(2, TranslateT("Name"), 250); + list_EXISTING_KEY_LIST.AddColumn(3, TranslateT("Creation date"), 30); + list_EXISTING_KEY_LIST.AddColumn(4, TranslateT("Expiration date"), 30); + list_EXISTING_KEY_LIST.AddColumn(5, TranslateT("Key length"), 30); + list_EXISTING_KEY_LIST.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_SINGLEROW); + int i = 1; + { + {//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)) + return; + if (result == pxNotFound) + return; + } + 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; + wchar_t *tmp = mir_wstrdup(toUTF16(out.substr(p, p2 - p)).c_str()); + int row = list_EXISTING_KEY_LIST.AddItem(L"", 0); + list_EXISTING_KEY_LIST.SetItemText(row, 5, tmp); + mir_free(tmp); + p2 += 2; + p = out.find(" ", p2); + tmp = mir_wstrdup(toUTF16(out.substr(p2, p - p2)).c_str()); + list_EXISTING_KEY_LIST.SetItemText(row, 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 += mir_strlen("expires: "); + string::size_type p4 = out.find("]", p3); + tmp = mir_wstrdup(toUTF16(out.substr(p3, p4 - p3)).c_str()); + list_EXISTING_KEY_LIST.SetItemText(row, 4, tmp); + mir_free(tmp); + } + else + p2--; + tmp = mir_wstrdup(toUTF16(out.substr(p, p2 - p)).c_str()); + list_EXISTING_KEY_LIST.SetItemText(row, 3, tmp); + mir_free(tmp); + p = out.find("uid ", p); + p += mir_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()); + list_EXISTING_KEY_LIST.SetItemText(row, 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()); + list_EXISTING_KEY_LIST.SetItemText(row, 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); + list_EXISTING_KEY_LIST.SetColumnWidth(0, LVSCW_AUTOSIZE);// not sure about this + list_EXISTING_KEY_LIST.SetColumnWidth(1, LVSCW_AUTOSIZE); + list_EXISTING_KEY_LIST.SetColumnWidth(2, LVSCW_AUTOSIZE); + list_EXISTING_KEY_LIST.SetColumnWidth(3, LVSCW_AUTOSIZE); + list_EXISTING_KEY_LIST.SetColumnWidth(4, LVSCW_AUTOSIZE); + list_EXISTING_KEY_LIST.SetColumnWidth(5, LVSCW_AUTOSIZE); + i++; + } + } + } + list_EXISTING_KEY_LIST.OnItemChanged = Callback(this, &CDlgLoadExistingKey::onChange_EXISTING_KEY_LIST); +} +void CDlgLoadExistingKey::OnDestroy() +{ + GetWindowRect(m_hwnd, &globals.load_existing_key_rect); + db_set_dw(NULL, szGPGModuleName, "LoadExistingKeyWindowX", globals.load_existing_key_rect.left); + db_set_dw(NULL, szGPGModuleName, "LoadExistingKeyWindowY", globals.load_existing_key_rect.top); + delete this; +} +void CDlgLoadExistingKey::onClick_OK(CCtrlButton*) +{ + int i = list_EXISTING_KEY_LIST.GetSelectionMark(); + if (i == -1) + return; //TODO: error message + + list_EXISTING_KEY_LIST.GetItemText(i, 0, id, _countof(id)); + extern CCtrlEdit *edit_p_PubKeyEdit; + 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)) + return; + if (result == pxNotFound) + return; + 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 += mir_strlen("-----END PGP PUBLIC KEY BLOCK-----"); + out = out.substr(p1, p2 - p1); + wchar_t *tmp = mir_a2u(out.c_str()); + if (edit_p_PubKeyEdit) + edit_p_PubKeyEdit->SetText(tmp); + mir_free(tmp); + } + else + MessageBox(nullptr, TranslateT("Failed to export public key."), TranslateT("Error"), MB_OK); + } + else + MessageBox(nullptr, TranslateT("Failed to export public key."), TranslateT("Error"), MB_OK); + // SetDlgItemText(hPubKeyEdit, IDC_PUBLIC_KEY_EDIT, tmp); + this->Close(); +} +void CDlgLoadExistingKey::onClick_CANCEL(CCtrlButton*) +{ + this->Close(); +} +void CDlgLoadExistingKey::onChange_EXISTING_KEY_LIST(CCtrlListView::TEventInfo * /*ev*/) //TODO: check if this work +{ + if (list_EXISTING_KEY_LIST.GetSelectionMark() != -1) + btn_OK.Enable(); +} + +CDlgImportKey::CDlgImportKey(MCONTACT _hContact) : CDlgBase(globals.hInst, IDD_IMPORT_KEY), +combo_KEYSERVER(this, IDC_KEYSERVER), +btn_IMPORT(this, IDC_IMPORT) +{ + hContact = _hContact; + btn_IMPORT.OnClick = Callback(this, &CDlgImportKey::onClick_IMPORT); +} +void CDlgImportKey::OnInitDialog() +{ + SetWindowPos(m_hwnd, nullptr, globals.import_key_rect.left, globals.import_key_rect.top, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW); + combo_KEYSERVER.AddString(L"subkeys.pgp.net"); + combo_KEYSERVER.AddString(L"keys.gnupg.net"); +} +void CDlgImportKey::OnDestroy() +{ + GetWindowRect(m_hwnd, &globals.import_key_rect); + db_set_dw(NULL, szGPGModuleName, "ImportKeyWindowX", globals.import_key_rect.left); + db_set_dw(NULL, szGPGModuleName, "ImportKeyWindowY", globals.import_key_rect.top); + delete this; +} +void CDlgImportKey::onClick_IMPORT(CCtrlButton*) +{ + string out; + DWORD code; + std::vector<wstring> cmd; + cmd.push_back(L"--keyserver"); + cmd.push_back(combo_KEYSERVER.GetText()); + cmd.push_back(L"--recv-keys"); + cmd.push_back(toUTF16(globals.hcontact_data[hContact].key_in_prescense)); + gpg_execution_params params(cmd); + pxResult result; + params.out = &out; + params.code = &code; + params.result = &result; + gpg_launcher(params); + MessageBoxA(nullptr, out.c_str(), "GPG output", MB_OK); +} + + + +CDlgKeyPasswordMsgBox::CDlgKeyPasswordMsgBox(MCONTACT _hContact) : CDlgBase(globals.hInst, IDD_KEY_PASSWD), +lbl_KEYID(this, IDC_KEYID), +edit_KEY_PASSWORD(this, IDC_KEY_PASSWORD), +chk_DEFAULT_PASSWORD(this, IDC_DEFAULT_PASSWORD), chk_SAVE_PASSWORD(this, IDC_SAVE_PASSWORD), +btn_OK(this, IDOK), btn_CANCEL(this, IDCANCEL) +{ + hContact = _hContact; + btn_OK.OnClick = Callback(this, &CDlgKeyPasswordMsgBox::onClick_OK); + btn_CANCEL.OnClick = Callback(this, &CDlgKeyPasswordMsgBox::onClick_CANCEL); +} +void CDlgKeyPasswordMsgBox::OnInitDialog() +{ + inkeyid = UniGetContactSettingUtf(hContact, szGPGModuleName, "InKeyID", ""); + + SetWindowPos(m_hwnd, nullptr, globals.key_password_rect.left, globals.key_password_rect.top, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW); + { + string questionstr = "Please enter password for key with ID: "; + questionstr += inkeyid; + mir_free(inkeyid); + lbl_KEYID.SetTextA(questionstr.c_str()); + chk_DEFAULT_PASSWORD.Disable(); + } +} +void CDlgKeyPasswordMsgBox::OnDestroy() +{ + mir_free(inkeyid); + GetWindowRect(m_hwnd, &globals.key_password_rect); + db_set_dw(NULL, szGPGModuleName, "PasswordWindowX", globals.key_password_rect.left); + db_set_dw(NULL, szGPGModuleName, "PasswordWindowY", globals.key_password_rect.top); + delete this; +} +void CDlgKeyPasswordMsgBox::onClick_OK(CCtrlButton*) +{ + wchar_t *tmp = mir_wstrdup(edit_KEY_PASSWORD.GetText()); + if (tmp && tmp[0]) { + if (chk_SAVE_PASSWORD.GetState()) { + inkeyid = UniGetContactSettingUtf(hContact, szGPGModuleName, "InKeyID", ""); + if (inkeyid && inkeyid[0] && !chk_DEFAULT_PASSWORD.GetState()) { + string dbsetting = "szKey_"; + dbsetting += inkeyid; + dbsetting += "_Password"; + db_set_ws(NULL, szGPGModuleName, dbsetting.c_str(), tmp); + } + else + db_set_ws(NULL, szGPGModuleName, "szKeyPassword", tmp); + } + if (globals.password) + mir_free(globals.password); + globals.password = (wchar_t*)mir_alloc(sizeof(wchar_t)*(mir_wstrlen(tmp) + 1)); + mir_wstrcpy(globals.password, tmp); + } + mir_free(inkeyid); + DestroyWindow(m_hwnd); +} +void CDlgKeyPasswordMsgBox::onClick_CANCEL(CCtrlButton*) +{ + globals._terminate = true; + DestroyWindow(m_hwnd); +} + diff --git a/plugins/New_GPG/src/ui.h b/plugins/New_GPG/src/ui.h index 5c017b7e1f..1825175bd7 100755 --- a/plugins/New_GPG/src/ui.h +++ b/plugins/New_GPG/src/ui.h @@ -57,7 +57,127 @@ private: CCtrlEdit edit_NEW_PASSWD1, edit_NEW_PASSWD2, edit_OLD_PASSWD; }; +class CDlgFirstRun : public CDlgBase +{ +public: + CDlgFirstRun(); + + virtual void OnInitDialog() override; + void onClick_COPY_PUBKEY(CCtrlButton*); + void onClick_EXPORT_PRIVATE(CCtrlButton*); + void onClick_CHANGE_PASSWD(CCtrlButton*); + void onClick_GENERATE_RANDOM(CCtrlButton*); + void onClick_GENERATE_KEY(CCtrlButton*); + void onClick_OTHER(CCtrlButton*); + void onClick_DELETE_KEY(CCtrlButton*); + void onClick_OK(CCtrlButton*); + void onChange_ACCOUNT(CCtrlCombo*); + void onChange_KEY_LIST(CCtrlListView::TEventInfo *ev); + virtual void OnDestroy() override; + +private: + void refresh_key_list(); + CCtrlListView list_KEY_LIST; + CCtrlButton btn_COPY_PUBKEY, btn_EXPORT_PRIVATE, btn_CHANGE_PASSWD, btn_GENERATE_RANDOM, btn_GENERATE_KEY, btn_OTHER, btn_DELETE_KEY, btn_OK; + CCtrlEdit edit_KEY_PASSWORD; + CCtrlCombo combo_ACCOUNT; + CCtrlData lbl_KEY_ID, lbl_GENERATING_KEY; + wchar_t fp[16]; +}; + +class CDlgGpgBinOpts : public CDlgBase +{ +public: + CDlgGpgBinOpts(); + virtual void OnInitDialog() override; + void onClick_SET_BIN_PATH(CCtrlButton*); + void onClick_SET_HOME_DIR(CCtrlButton*); + void onClick_OK(CCtrlButton*); + void onClick_GENERATE_RANDOM(CCtrlButton*); + virtual void OnDestroy() override; +private: + CCtrlButton btn_SET_BIN_PATH, btn_SET_HOME_DIR, btn_OK, btn_GENERATE_RANDOM; + CCtrlEdit edit_BIN_PATH, edit_HOME_DIR; + CCtrlCheck chk_AUTO_EXCHANGE; +}; + +class CDlgNewKey : public CDlgBase +{ +public: + CDlgNewKey(MCONTACT hContact, wstring new_key); + virtual void OnInitDialog() override; + virtual void OnDestroy() override; + void onClick_IMPORT(CCtrlButton*); + void onClick_IMPORT_AND_USE(CCtrlButton*); + void onClick_IGNORE_KEY(CCtrlButton*); +private: + wstring new_key; + MCONTACT hContact; + CCtrlData lbl_KEY_FROM, lbl_MESSAGE; + CCtrlButton btn_IMPORT, btn_IMPORT_AND_USE, btn_IGNORE_KEY; +}; + +class CDlgKeyGen : public CDlgBase //TODO: in modal mode window destroying on any button press even without direct "Close" call +{ +public: + CDlgKeyGen(); + virtual void OnInitDialog() override; + + void onClick_OK(CCtrlButton*); + void onClick_CANCEL(CCtrlButton*); + virtual void OnDestroy() override; + +private: + CCtrlCombo combo_KEY_TYPE; + CCtrlEdit edit_KEY_LENGTH, edit_KEY_PASSWD, edit_KEY_REAL_NAME, edit_KEY_EMAIL, edit_KEY_COMMENT, edit_KEY_EXPIRE_DATE; + CCtrlData lbl_GENERATING_TEXT; + CCtrlButton btn_OK, btn_CANCEL; +}; + +class CDlgLoadExistingKey : public CDlgBase +{ +public: + CDlgLoadExistingKey(); + virtual void OnInitDialog() override; + virtual void OnDestroy() override; + void onClick_OK(CCtrlButton*); + void onClick_CANCEL(CCtrlButton*); + void onChange_EXISTING_KEY_LIST(CCtrlListView::TEventInfo * /*ev*/); +private: + wchar_t id[16]; + CCtrlButton btn_OK, btn_CANCEL; + CCtrlListView list_EXISTING_KEY_LIST; +}; +class CDlgImportKey : public CDlgBase +{ +public: + CDlgImportKey(MCONTACT hContact); + virtual void OnInitDialog() override; + virtual void OnDestroy() override; + void onClick_IMPORT(CCtrlButton*); +private: + MCONTACT hContact; + CCtrlCombo combo_KEYSERVER; + CCtrlButton btn_IMPORT; +}; + +class CDlgKeyPasswordMsgBox : public CDlgBase //always modal +{ +public: + CDlgKeyPasswordMsgBox(MCONTACT _hContact); + virtual void OnInitDialog() override; + virtual void OnDestroy() override; + void onClick_OK(CCtrlButton*); + void onClick_CANCEL(CCtrlButton*); +private: + char *inkeyid = nullptr; + MCONTACT hContact; + CCtrlData lbl_KEYID; + CCtrlEdit edit_KEY_PASSWORD; + CCtrlCheck chk_DEFAULT_PASSWORD, chk_SAVE_PASSWORD; + CCtrlButton btn_OK, btn_CANCEL; +}; #endif // UI_H
\ No newline at end of file diff --git a/plugins/New_GPG/src/utilities.cpp b/plugins/New_GPG/src/utilities.cpp index a7802c3558..1c0d383eac 100755 --- a/plugins/New_GPG/src/utilities.cpp +++ b/plugins/New_GPG/src/utilities.cpp @@ -365,10 +365,8 @@ int onProtoAck(WPARAM, LPARAM l) else db_set_s(ack->hContact, szGPGModuleName, "InKeyID", out.substr(s, s2 - s).c_str()); } - void ShowLoadKeyPasswordWindow(); - globals.new_key_hcnt_mutex.lock(); - globals.new_key_hcnt = ack->hContact; - ShowLoadKeyPasswordWindow(); + CDlgKeyPasswordMsgBox *d = new CDlgKeyPasswordMsgBox(ack->hContact); + d->DoModal(); std::vector<wstring> cmd2 = cmd; if (globals.password) { if (globals.bDebugLog) @@ -1837,3 +1835,183 @@ void clean_temp_dir() } } } + +bool gpg_validate_paths(wchar_t *gpg_bin_path, wchar_t *gpg_home_path) +{ + wstring tmp = gpg_bin_path; + if (!tmp.empty()) { + wchar_t mir_path[MAX_PATH]; + PathToAbsoluteW(L"\\", mir_path); + SetCurrentDirectoryW(mir_path); + if (!boost::filesystem::exists(tmp)) { + MessageBox(nullptr, TranslateT("GPG binary does not exist.\nPlease choose another location"), TranslateT("Warning"), MB_OK); + return false; + } + } + else { + MessageBox(nullptr, TranslateT("Please choose GPG binary location"), TranslateT("Warning"), MB_OK); + return false; + } + { + bool bad_version = false; + db_set_ws(NULL, szGPGModuleName, "szGpgBinPath", tmp.c_str()); + 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; + bool _gpg_valid = globals.gpg_valid; + globals.gpg_valid = true; + gpg_launcher(params); + globals.gpg_valid = _gpg_valid; //TODO: check this + db_unset(NULL, szGPGModuleName, "szGpgBinPath"); + string::size_type p1 = out.find("(GnuPG) "); + if (p1 != string::npos) { + p1 += mir_strlen("(GnuPG) "); + if (out[p1] != '1') + bad_version = true; + } + else { + bad_version = false; + MessageBox(nullptr, TranslateT("This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin."), TranslateT("Warning"), MB_OK); + return false; + } + if (bad_version) + MessageBox(nullptr, TranslateT("Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin."), TranslateT("Warning"), MB_OK); + } + tmp = gpg_home_path; + if (tmp[tmp.length()] == '\\') + tmp.erase(tmp.length()); + if (tmp.empty()) { + MessageBox(nullptr, TranslateT("Please set keyring's home directory"), TranslateT("Warning"), MB_OK); + return false; + } + { + wchar_t *path = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", L""); + DWORD dwFileAttr = GetFileAttributes(path); + if (dwFileAttr != INVALID_FILE_ATTRIBUTES) { + dwFileAttr &= ~FILE_ATTRIBUTE_READONLY; + SetFileAttributes(path, dwFileAttr); + } + mir_free(path); + } + return true; +} + +void gpg_save_paths(wchar_t *gpg_bin_path, wchar_t *gpg_home_path) +{ + db_set_ws(NULL, szGPGModuleName, "szGpgBinPath", gpg_bin_path); + db_set_ws(NULL, szGPGModuleName, "szHomePath", gpg_home_path); +} + +bool gpg_use_new_random_key(char *account_name, wchar_t *gpg_bin_path, wchar_t *gpg_home_dir) +{ + if (gpg_bin_path && gpg_home_dir) + gpg_save_paths(gpg_bin_path, gpg_home_dir); + { + wstring path; + { + // generating key file + wchar_t *tmp = nullptr; + if (gpg_home_dir) + tmp = gpg_home_dir; + else + tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", L""); + path = tmp; + if (!gpg_home_dir) + mir_free(tmp); + path.append(L"\\new_key"); + wfstream f(path.c_str(), std::ios::out); + if (!f.is_open()) { + MessageBox(nullptr, TranslateT("Failed to open file"), TranslateT("Error"), MB_OK); + return false; + } + 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; + if (!gpg_launcher(params, boost::posix_time::minutes(10))) + return false; + if (result == pxNotFound) + return false; + + 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)) { + return false; + } + if (result == pxNotFound) + return false; + string::size_type s = 0; + while ((s = out.find("\r", s)) != string::npos) { + out.erase(s, 1); + } + { + if (!mir_strcmp(account_name, Translate("Default"))) + { + db_set_s(NULL, szGPGModuleName, "GPGPubKey", out.c_str()); + db_set_ws(NULL, szGPGModuleName, "KeyID", path.c_str()); + } + else + { + std::string acc_str = account_name; + acc_str += "_GPGPubKey"; + db_set_s(NULL, szGPGModuleName, acc_str.c_str(), out.c_str()); + acc_str = account_name; + acc_str += "_KeyID"; + db_set_ws(NULL, szGPGModuleName, acc_str.c_str(), path.c_str()); + } + } + } + } + return true; +} diff --git a/plugins/New_GPG/src/utilities.h b/plugins/New_GPG/src/utilities.h index b14f50dd69..1d2d6c7de7 100755 --- a/plugins/New_GPG/src/utilities.h +++ b/plugins/New_GPG/src/utilities.h @@ -109,5 +109,8 @@ void strip_line_term(std::wstring &s); void strip_line_term(std::string &s); void strip_tags(std::wstring &s); void clean_temp_dir(); +bool gpg_validate_paths(wchar_t *gpg_bin_path, wchar_t *gpg_home_path); +void gpg_save_paths(wchar_t *gpg_bin_path, wchar_t *gpg_home_path); +bool gpg_use_new_random_key(char *account_name = Translate("Default"), wchar_t *gpg_bin_path = nullptr, wchar_t *gpg_home_dir = nullptr); #endif |