// Copyright © 2010 sss // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "commonheaders.h" #include extern HINSTANCE hInst; static BOOL CALLBACK DlgProcGpgOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); static BOOL CALLBACK DlgProcGpgBinOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); int GpgOptInit(WPARAM wParam,LPARAM lParam) { OPTIONSDIALOGPAGE odp = { 0 }; odp.cbSize = sizeof(odp); odp.hInstance = hInst; odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_GPG); odp.pszTitle = szModuleName; odp.pszGroup = "Services"; odp.pszTab = "Main"; odp.flags=ODPF_BOLDGROUPS; odp.pfnDlgProc = DlgProcGpgOpts; CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp); ZeroMemory(&odp, sizeof(odp)); odp.cbSize = sizeof(odp); odp.hInstance = hInst; odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_GPG_BIN); odp.pszTitle = szModuleName; odp.pszGroup = "Services"; odp.pszTab = "GnuPG Variables"; odp.flags=ODPF_BOLDGROUPS; odp.pfnDlgProc = DlgProcGpgBinOpts; CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp); return 0; } static HWND hwndLoadPublicKey = NULL; map user_data; int item_num = 0; HWND hwndList_p; void ShowLoadPublicKeyDialog(); static BOOL CALLBACK DlgProcGpgOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { HWND hwndList=GetDlgItem(hwndDlg, IDC_USERLIST); hwndList_p = hwndList; LVCOLUMN col; LVITEM item; TCHAR *tmp; NMLISTVIEW * hdr = (NMLISTVIEW *) lParam; switch (msg) { case WM_INITDIALOG: { TranslateDialogDefault(hwndDlg); col.pszText = _T("Contact"); col.mask = LVCF_TEXT | LVCF_WIDTH; col.fmt = LVCFMT_LEFT; col.cx = 100; ListView_InsertColumn(hwndList, 0, &col); ZeroMemory(&col,sizeof(col)); col.pszText = _T("Protocol"); col.mask = LVCF_TEXT | LVCF_WIDTH; col.fmt = LVCFMT_LEFT; col.cx = 30; ListView_InsertColumn(hwndList, 1, &col); ZeroMemory(&col,sizeof(col)); col.pszText = _T("PubKey"); col.mask = LVCF_TEXT | LVCF_WIDTH; col.fmt = LVCFMT_LEFT; col.cx = 250; ListView_InsertColumn(hwndList, 2, &col); ListView_SetExtendedListViewStyleEx(hwndList, 0, LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT); int i = 1, iRow = 0; for(HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); hContact != NULL; hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0)) { TCHAR *name = (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR); item.mask = LVIF_TEXT; item.iItem = i; item.iSubItem = 0; item.pszText = name; iRow = ListView_InsertItem(hwndList, &item); ListView_SetItemText(hwndList, iRow, 0, name); TCHAR *tmp = mir_a2t((char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0)); ListView_SetItemText(hwndList, iRow, 1, tmp); mir_free(tmp); tmp = UniGetContactSettingUtf(hContact, szModuleName, "GPGPubKey", _T("not set")); ListView_SetItemText(hwndList, iRow, 2, (_tcslen(tmp) > 1)?tmp:_T("not set")); if(DBGetContactSettingByte(hContact, szModuleName, "GPGEncryption", 0)) ListView_SetItemState(hwndList, iRow, 0x2000, 0xF000); user_data[i] = hContact; ZeroMemory(&item,sizeof(item)); i++; } ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE);// not sure about this ListView_SetColumnWidth(hwndList, 1, LVSCW_AUTOSIZE); ListView_SetColumnWidth(hwndList, 2, LVSCW_AUTOSIZE); return TRUE; } case WM_COMMAND: { switch (LOWORD(wParam)) { case IDC_LOAD_KEY_BUTTON: ShowLoadPublicKeyDialog(); return TRUE; case IDC_DELETE_KEY_BUTTON: DBDeleteContactSetting(user_data[item_num+1], szModuleName, "GPGPubKey"); DBDeleteContactSetting(user_data[item_num+1], szModuleName, "KeyFingerprint"); DBDeleteContactSetting(user_data[item_num+1], szModuleName, "KeyMainName"); DBDeleteContactSetting(user_data[item_num+1], szModuleName, "KeyType"); DBDeleteContactSetting(user_data[item_num+1], szModuleName, "KeyMainEmail"); DBDeleteContactSetting(user_data[item_num+1], szModuleName, "KeyComment"); ListView_SetItemText(hwndList, item_num, 2, _T("not set")); { //gpg execute block TCHAR cmd[40960] = {0}; TCHAR tmp2[MAX_PATH] = {0}; TCHAR *ptmp; char *tmp; bool keep = false; tmp = GetContactSettingStringA(user_data[item_num+1], szModuleName, "KeyFingerprint", ""); for(HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); hContact != NULL; hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0)) { if(hContact != user_data[item_num+1]) { char *tmp2 = GetContactSettingStringA(hContact, szModuleName, "KeyFingerprint", ""); if(!strcmp(tmp, tmp2)) { mir_free(tmp2); keep = true; break; } mir_free(tmp2); } } if(keep) { mir_free(tmp); break; } string output; DWORD exitcode; _tcscat(cmd, _T(" --batch")); _tcscat(cmd, _T(" --yes")); _tcscat(cmd, _T(" --delete-key ")); ptmp = mir_a2t(tmp); _tcscat(cmd, ptmp); mir_free(ptmp); pxResult pxresult=pxExecute(cmd,"",&output,&exitcode); mir_free(tmp); } break; default: break; case IDC_SAVE_KEY_BUTTON: tmp = GetFilePath(_T("Export public key"), _T("*"), _T(".asc pubkey file"), true); if(!tmp) { break; } wfstream f(tmp, std::ios::out); delete [] tmp; wstring str; { TCHAR *tmp = UniGetContactSettingUtf(user_data[item_num+1], szModuleName, "GPGPubKey", _T("")); str.append(tmp); mir_free(tmp); } wstring::size_type s = 0; while((s = str.find(_T("\r"), s)) != wstring::npos) { str.erase(s, 1); } f<hdr.hwndFrom) && hdr->iItem != (-1)) { if(hdr->hdr.code == LVN_ITEMCHANGED) { int i = hdr->iItem; if(ListView_GetItemState(hwndList, i, 0xF000) == 0x2000) DBWriteContactSettingByte(user_data[i+1], szModuleName, "GPGEncryption", 1); else DBWriteContactSettingByte(user_data[i+1], szModuleName, "GPGEncryption", 0); item_num = hdr->iItem; } } switch (((LPNMHDR)lParam)->code) { case PSN_APPLY: { return TRUE; } } } break; } return FALSE; } static BOOL CALLBACK DlgProcGpgBinOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { TCHAR *tmp = NULL; switch (msg) { case WM_INITDIALOG: { TranslateDialogDefault(hwndDlg); tmp = UniGetContactSettingUtf(NULL, szModuleName, "szGpgBinPath", _T("gpg2.exe")); SetDlgItemText(hwndDlg, IDC_BIN_PATH, tmp); mir_free(tmp); tmp = UniGetContactSettingUtf(NULL, szModuleName, "szHomePath", _T("gpg")); SetDlgItemText(hwndDlg, IDC_HOME_DIR, tmp); mir_free(tmp); return TRUE; } case WM_COMMAND: { switch (LOWORD(wParam)) { case IDC_SET_BIN_PATH: GetFilePath(_T("Choose gpg2.exe"), "szGpgBinPath", _T("*.exe"), _T("EXE Executables")); tmp = UniGetContactSettingUtf(NULL, szModuleName, "szGpgBinPath", _T("gpg2.exe")); SetDlgItemText(hwndDlg, IDC_BIN_PATH, tmp); mir_free(tmp); break; case IDC_SET_HOME_DIR: GetFolderPath(_T("Set home diractory"), "szHomePath"); tmp = UniGetContactSettingUtf(NULL, szModuleName, "szHomePath", _T("")); SetDlgItemText(hwndDlg, IDC_HOME_DIR, tmp); mir_free(tmp); break; default: break; } SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); break; } case WM_NOTIFY: { switch (((LPNMHDR)lParam)->code) { case PSN_APPLY: { TCHAR tmp[512]; GetDlgItemText(hwndDlg, IDC_BIN_PATH, tmp, 512); DBWriteContactSettingTString(NULL, szModuleName, "szGpgBinPath", tmp); GetDlgItemText(hwndDlg, IDC_HOME_DIR, tmp, 512); DBWriteContactSettingTString(NULL, szModuleName, "szHomePath", tmp); return TRUE; } } } break; } return FALSE; } static BOOL CALLBACK DlgProcLoadPublicKey(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam) { HANDLE hContact = user_data[item_num+1]; TCHAR *tmp = NULL; wstring key_buf; wstring::size_type ws1 = 0, ws2 = 0; switch (msg) { case WM_INITDIALOG: { TranslateDialogDefault(hwndDlg); tmp = UniGetContactSettingUtf(hContact, szModuleName, "GPGPubKey", _T("")); SetDlgItemText(hwndDlg, IDC_PUBLIC_KEY_EDIT, (_tcslen(tmp) > 1)?tmp:_T("")); return TRUE; } case WM_COMMAND: { switch (LOWORD(wParam)) { case ID_OK: tmp = new TCHAR [40960]; GetDlgItemText(hwndDlg, IDC_PUBLIC_KEY_EDIT, tmp, 40960); key_buf.append(tmp); key_buf.append(_T("\n")); //no new line at end of file ) delete [] tmp; while((ws1 = key_buf.find(_T("\r"), ws1)) != wstring::npos) { key_buf.erase(ws1, 1); //remove windows specific trash } ws1 = 0; if(((ws2 = key_buf.find(_T("-----END PGP PUBLIC KEY BLOCK-----"))) == wstring::npos) || ((ws1 = key_buf.find(_T("-----BEGIN PGP PUBLIC KEY BLOCK-----"))) == wstring::npos)) { MessageBox(0, _T("This is not public key"), _T("INFO"), MB_OK); break; } ws2 += _tcslen(_T("-----END PGP PUBLIC KEY BLOCK-----")); DBWriteContactSettingTString(hContact, szModuleName, "GPGPubKey", key_buf.substr(ws1,ws2-ws1).c_str()); tmp = new TCHAR [key_buf.length()+1]; _tcscpy(tmp, key_buf.substr(ws1,ws2-ws1).c_str()); ListView_SetItemText(hwndList_p, item_num, 2, tmp); { //gpg execute block TCHAR cmd[40960] = {0}; TCHAR tmp2[MAX_PATH] = {0}; TCHAR *ptmp; string output; DWORD exitcode; _tcscat(cmd, _T(" --import ")); { ptmp = UniGetContactSettingUtf(NULL, szModuleName, "szHomePath", _T("")); _tcscpy(tmp2, ptmp); mir_free(ptmp); _tcscat(tmp2, _T("\\")); _tcscat(tmp2, _T("temporary_exported.asc")); wfstream f(tmp2, std::ios::out); ptmp = UniGetContactSettingUtf(user_data[item_num+1], szModuleName, "GPGPubKey", _T("")); wstring str = ptmp; mir_free(ptmp); wstring::size_type s = 0; while((s = str.find(_T("\r"), s)) != wstring::npos) { str.erase(s, 1); } f<", s2); s2++; if(output[s] == ')') { DBWriteContactSettingString(user_data[item_num+1], szModuleName, "KeyComment", output.substr(s2,s-s2).c_str()); s+=3; s2 = output.find(">", s); DBWriteContactSettingString(user_data[item_num+1], szModuleName, "KeyMainEmail", output.substr(s,s2-s).c_str()); } else DBWriteContactSettingString(user_data[item_num+1], szModuleName, "KeyMainEmail", output.substr(s2,s-s2).c_str()); } MessageBoxA(0, output.c_str(), "", MB_OK); DeleteFile(tmp2); } delete [] tmp; key_buf.clear(); DestroyWindow(hwndDlg); break; case ID_LOAD_FROM_FILE: tmp = GetFilePath(_T("Set file containing GPG public key"), _T("*"), _T("GPG public key file")); if(!tmp) { break; } wfstream f(tmp, std::ios::in); delete [] tmp; if(!f.is_open()) { MessageBox(0, _T("Failed to open file"), _T("Error"), MB_OK); break; } while(!f.eof()) { tmp = new TCHAR [1024]; f.getline(tmp, 1024, '\n'); key_buf.append(tmp); key_buf.append(_T("\n")); delete [] tmp; } f.close(); if(((ws2 = key_buf.find(_T("-----END PGP PUBLIC KEY BLOCK-----"))) == wstring::npos) || ((ws1 = key_buf.find(_T("-----BEGIN PGP PUBLIC KEY BLOCK-----"))) == wstring::npos)) { MessageBox(0, _T("This is not public key"), _T("INFO"), MB_OK); break; } ws2 += _tcslen(_T("-----END PGP PUBLIC KEY BLOCK-----")); SetDlgItemText(hwndDlg, IDC_PUBLIC_KEY_EDIT, key_buf.substr(ws1,ws2-ws1).c_str()); key_buf.clear(); break; } SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); break; } case WM_NOTIFY: { switch (((LPNMHDR)lParam)->code) { case PSN_APPLY: { return TRUE; } } } break; case WM_CLOSE: DestroyWindow(hwndDlg); break; case WM_DESTROY: hwndLoadPublicKey = NULL; break; } return FALSE; } void ShowLoadPublicKeyDialog() { if (hwndLoadPublicKey == NULL) { hwndLoadPublicKey = CreateDialog(hInst, MAKEINTRESOURCE(IDD_LOAD_PUBLIC_KEY), NULL, DlgProcLoadPublicKey); } SetForegroundWindow(hwndLoadPublicKey); }