// Copyright © 2010-2012 sss // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "commonheaders.h" TCHAR* __stdcall UniGetContactSettingUtf(HANDLE hContact, const char *szModule,const char* szSetting, TCHAR* szDef) { DBVARIANT dbv = {DBVT_DELETED}; TCHAR* szRes; if (DBGetContactSettingTString(hContact, szModule, szSetting, &dbv)) return mir_tstrdup(szDef); if(dbv.pszVal) szRes = mir_tstrdup(dbv.ptszVal); DBFreeVariant(&dbv); return szRes; } char* __stdcall UniGetContactSettingUtf(HANDLE hContact, const char *szModule,const char* szSetting, char* szDef) { DBVARIANT dbv = {DBVT_DELETED}; char* szRes; if (DBGetContactSettingString(hContact, szModule, szSetting, &dbv)) return mir_strdup(szDef); if(dbv.pszVal) szRes = mir_strdup(dbv.pszVal); DBFreeVariant(&dbv); return szRes; } void GetFilePath(TCHAR *WindowTittle, char *szSetting, TCHAR *szExt, TCHAR *szExtDesc) { TCHAR str[MAX_PATH+2] = {0}, *tmp; OPENFILENAME ofn={0}; TCHAR filter[512], *pfilter; ofn.lStructSize=CDSIZEOF_STRUCT(OPENFILENAME,lpTemplateName); ofn.Flags=OFN_EXPLORER; ofn.lpstrTitle=TranslateW(WindowTittle); _tcscpy(filter,TranslateW(szExtDesc)); pfilter=filter+_tcslen(filter)+1; _tcscpy(pfilter, szExt); pfilter[_tcslen(pfilter)+1] = '\0'; pfilter[_tcslen(pfilter)+2] = '\0'; ofn.lpstrFilter=filter; tmp = UniGetContactSettingUtf(0, szGPGModuleName, szSetting, _T("")); _tcscpy(str, tmp); mir_free(tmp); if(_tcslen(str)< 2) str[0] = '\0'; ofn.lpstrFile=str; ofn.nMaxFile=_MAX_PATH; ofn.nMaxFileTitle=MAX_PATH; if(!GetOpenFileName(&ofn)) return; DBWriteContactSettingTString(0, szGPGModuleName, szSetting, str); } TCHAR *GetFilePath(TCHAR *WindowTittle, TCHAR *szExt, TCHAR *szExtDesc, bool save_file) { TCHAR *str = new TCHAR [MAX_PATH+2]; OPENFILENAME ofn={0}; TCHAR filter[512], *pfilter; ofn.lStructSize=CDSIZEOF_STRUCT(OPENFILENAME,lpTemplateName); ofn.Flags=OFN_EXPLORER; ofn.lpstrTitle=TranslateW(WindowTittle); _tcscpy(filter,TranslateW(szExtDesc)); pfilter=filter+_tcslen(filter)+1; _tcscpy(pfilter, szExt); pfilter[_tcslen(pfilter)+1] = '\0'; pfilter[_tcslen(pfilter)+2] = '\0'; ofn.lpstrFilter=filter; _tcscpy(str, _T("")); if(_tcslen(str)< 2) str[0] = '\0'; ofn.lpstrFile=str; ofn.nMaxFile=_MAX_PATH; ofn.nMaxFileTitle=MAX_PATH; if(!save_file) { if(!GetOpenFileName(&ofn)) { delete [] str; return NULL; } } else { if(!GetSaveFileName(&ofn)) { delete [] str; return NULL; } } return str; } void GetFolderPath(TCHAR *WindowTittle, char *szSetting) { BROWSEINFO pbi = {0}; pbi.lpszTitle = WindowTittle; pbi.ulFlags = BIF_EDITBOX|BIF_NEWDIALOGSTYLE|BIF_SHAREABLE; LPITEMIDLIST pidl = SHBrowseForFolder(&pbi); if (pidl != 0) { TCHAR path[MAX_PATH]; if (SHGetPathFromIDList(pidl, path)) { DBWriteContactSettingTString(NULL, szGPGModuleName, "szHomePath", path); } IMalloc * imalloc = 0; if (SUCCEEDED(SHGetMalloc(&imalloc))) { imalloc->Free(pidl); imalloc->Release(); } } } INT_PTR LoadKey(WPARAM w, LPARAM l) { void ShowLoadPublicKeyDialog(); extern map user_data; extern int item_num; item_num = 0; //black magic here user_data[1] = (HANDLE)w; ShowLoadPublicKeyDialog(); return 0; } INT_PTR SendKey(WPARAM w, LPARAM l) { HANDLE hContact = (HANDLE)w; if(metaIsProtoMetaContacts(hContact)) hContact = metaGetMostOnline(hContact); char *szMessage; { LPSTR proto = (LPSTR)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); PROTOACCOUNT *acc = (PROTOACCOUNT*)CallService(MS_PROTO_GETCONTACTBASEPROTO, 0, (LPARAM)proto); std::string acc_str; if(acc) { acc_str = toUTF8(acc->tszAccountName); acc_str += "("; acc_str += acc->szModuleName; acc_str += ")" ; acc_str += "_GPGPubKey"; } szMessage = UniGetContactSettingUtf(hContact, szGPGModuleName, acc_str.empty()?"GPGPubKey":acc_str.c_str(), ""); } if(szMessage[0]) { BYTE enc = DBGetContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 0); DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 0); CallContactService(hContact, PSS_MESSAGE, (WPARAM)PREF_UTF, (LPARAM)szMessage); HistoryLog(hContact, db_event("Public key sent", 0, 0, DBEF_SENT)); DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", enc); } mir_free(szMessage); return 0; } extern HANDLE hLoadPublicKey, hToggleEncryption; INT_PTR ToggleEncryption(WPARAM w, LPARAM l) { HANDLE hContact = (HANDLE)w; BYTE enc = 0; if(metaIsProtoMetaContacts(hContact)) enc = DBGetContactSettingByte(metaGetMostOnline(hContact), szGPGModuleName, "GPGEncryption", 0); else enc = DBGetContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 0); if(metaIsProtoMetaContacts(hContact)) { HANDLE hcnt = NULL; if(MessageBox(0, _T("Do you want to toggle encryption for all subcontacts ?"), _T("Metacontact detected"), MB_YESNO) == IDYES) { int count = metaGetContactsNum(hContact); for(int i = 0; i < count; i++) { hcnt = metaGetSubcontact(hContact, i); if(hcnt) DBWriteContactSettingByte(hcnt, szGPGModuleName, "GPGEncryption", enc?0:1); } DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", enc?0:1); } } else DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", enc?0:1); void setSrmmIcon(HANDLE hContact); void setClistIcon(HANDLE hContact); setSrmmIcon(hContact); setClistIcon(hContact); enc = enc?0:1; CLISTMENUITEM mi = {0}; mi.cbSize=sizeof(mi); mi.flags = CMIM_NAME; enc?mi.pszName="Turn off GPG encryption":mi.pszName="Turn on GPG encryption"; CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hToggleEncryption, (LPARAM)&mi); return 0; } int OnPreBuildContactMenu(WPARAM w, LPARAM l) { HANDLE hContact = (HANDLE)w; if(metaIsProtoMetaContacts(hContact)) hContact = metaGetMostOnline(hContact); CLISTMENUITEM mi = {0}; mi.cbSize=sizeof(mi); mi.flags = CMIM_NAME; TCHAR *tmp = UniGetContactSettingUtf(hContact, szGPGModuleName, "GPGPubKey", _T("")); if(_tcslen(tmp) < 1) { DBDeleteContactSetting(hContact, szGPGModuleName, "GPGEncryption"); mi.flags += CMIM_FLAGS | CMIF_GRAYED; } else mi.flags = CMIM_NAME | CMIM_FLAGS; mi.pszName = DBGetContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 0)?"Turn off GPG encryption":"Turn on GPG encryption"; CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hToggleEncryption, (LPARAM)&mi); return 0; } list transfers; extern bool bFileTransfers; int onProtoAck(WPARAM w, LPARAM l) { ACKDATA *ack=(ACKDATA*)l; CCSDATA *ccs=(CCSDATA*)ack->lParam; if(ack->type == ACKTYPE_FILE && bFileTransfers) { switch(ack->result) { case ACKRESULT_DENIED: case ACKRESULT_FAILED: break; case ACKRESULT_SUCCESS: { PROTOFILETRANSFERSTATUS *f = (PROTOFILETRANSFERSTATUS*) ack->hProcess; TCHAR *filename = NULL; if(f->flags & PFTS_UNICODE) { if(f->tszCurrentFile && f->tszCurrentFile[0]) filename = mir_wstrdup(f->tszCurrentFile); if(!filename) return 0; } else { if(f->szCurrentFile && f->szCurrentFile[0]) filename = mir_utf8decodeT(f->szCurrentFile); if(!filename) return 0; } if(_tcsstr(filename, _T(".gpg"))) //decrypt it { //process encrypted file if(_waccess(f->tszCurrentFile, 0) == -1) { if(errno == ENOENT) return 0; } string out; DWORD code; pxResult result; wstring cmd = _T(" -o "); wstring file = filename; wstring::size_type p1 = file.rfind(_T(".gpg")); file.erase(p1, _tcslen(_T(".gpg"))); if(_waccess(file.c_str(), 0) != -1) { if(MessageBox(0, _T("Target file exists, do you want to replace it ?"), _T("Warning"), MB_YESNO) == IDNO) return 0; } DeleteFile(file.c_str()); file.insert(0, _T("\"")); file.insert(file.length(), _T("\" ")); cmd += file; extern TCHAR *password; { // password TCHAR *pass = NULL; char *keyid = UniGetContactSettingUtf(ack->hContact, szGPGModuleName, "KeyID", ""); if(strlen(keyid) > 0) { string dbsetting = "szKey_"; dbsetting += keyid; dbsetting += "_Password"; pass = UniGetContactSettingUtf(NULL, szGPGModuleName, dbsetting.c_str(), _T("")); if(_tcslen(pass) > 0) debuglog<hContact, GCDNF_TCHAR)<<" with password\n"; } else { pass = UniGetContactSettingUtf(NULL, szGPGModuleName, "szKeyPassword", _T("")); if(_tcslen(pass) > 0) debuglog<hContact, GCDNF_TCHAR)<<" with password\n"; } if(_tcslen(pass) > 0) { cmd += _T("--passphrase \""); cmd += pass; cmd += _T("\" "); } else if(password) { debuglog<hContact, GCDNF_TCHAR)<<" with password\n"; cmd += _T("--passphrase \""); cmd += password; cmd += _T("\" "); } else debuglog<hContact, GCDNF_TCHAR)<<" with out password\n"; mir_free(pass); mir_free(keyid); } cmd += _T(" -d \""); cmd += filename; cmd += _T("\""); gpg_execution_params params; params.cmd = &cmd; params.useless = ""; params.out = &out; params.code = &code; params.result = &result; boost::thread *gpg_thread = new boost::thread(boost::bind(&pxEexcute_thread, ¶ms)); if(!gpg_thread->timed_join(boost::posix_time::minutes(15))) { delete gpg_thread; TerminateProcess(params.hProcess, 1); params.hProcess = NULL; debuglog<hContact, GCDNF_TCHAR)<<" password needed, trying to get one\n"; if(_terminate) break; { //save inkey id string::size_type s = out.find(" encrypted with "); s = out.find(" ID ", s); s += strlen(" ID "); string::size_type s2 = out.find(",",s); if(metaIsProtoMetaContacts(ack->hContact)) DBWriteContactSettingString(metaGetMostOnline(ack->hContact), szGPGModuleName, "InKeyID", out.substr(s, s2-s).c_str()); else DBWriteContactSettingString(ack->hContact, szGPGModuleName, "InKeyID", out.substr(s, s2-s).c_str()); } void ShowLoadKeyPasswordWindow(); new_key_hcnt_mutex.lock(); new_key_hcnt = ack->hContact; ShowLoadKeyPasswordWindow(); wstring cmd2 = cmd; if(password) { debuglog<hContact, GCDNF_TCHAR)<<"\n"; wstring tmp = _T("--passphrase \""); tmp += password; tmp += _T("\" "); cmd2.insert(0, tmp); } out.clear(); gpg_execution_params params; pxResult result; params.cmd = &cmd2; params.useless = ""; params.out = &out; params.code = &code; params.result = &result; gpg_thread = gpg_thread = new boost::thread(boost::bind(&pxEexcute_thread, ¶ms)); if(!gpg_thread->timed_join(boost::posix_time::seconds(15))) { delete gpg_thread; TerminateProcess(params.hProcess, 1); params.hProcess = NULL; debuglog<type == ACKTYPE_MESSAGE) { extern std::list sent_msgs; if(!sent_msgs.empty()) { if(ack->result == ACKRESULT_FAILED) { std::list::iterator it = std::find(sent_msgs.begin(), sent_msgs.end(), ack->hProcess); if(it != sent_msgs.end()) { HistoryLog(ack->hContact, db_event("Failed to send encrypted message", 0,0, 0)); } } else if(ack->result == ACKRESULT_SUCCESS) { std::list::iterator it = std::find(sent_msgs.begin(), sent_msgs.end(), ack->hProcess); if(it != sent_msgs.end()) sent_msgs.erase(it); } } } return 0; } std::wstring encrypt_file(HANDLE hContact, TCHAR *filename) { string out; DWORD code; pxResult result; HANDLE hcnt = metaIsProtoMetaContacts(hContact)?metaGetMostOnline(hContact):hContact; wstring cmd = _T("--batch --yes -r "); char *keyid = UniGetContactSettingUtf(hcnt, szGPGModuleName, "KeyID", ""); TCHAR *szKeyid = mir_a2t(keyid); TCHAR *name = _tcsrchr(filename,_T('\\')); if( !name ) name = filename; else name++; TCHAR *file_out = new TCHAR [_tcslen(filename)+4]; mir_sntprintf(file_out, _tcslen(name)+7, _T("%s.gpg"), name); cmd += szKeyid; if(DBGetContactSettingByte(hcnt, szGPGModuleName, "bAlwaysTrust", 0)) cmd += _T(" --trust-model always "); mir_free(szKeyid); mir_free(keyid); cmd += _T(" -o \""); TCHAR *temp = _tgetenv(_T("TEMP")); cmd += temp; cmd += _T("\\"); cmd += file_out; wstring path_out = temp; path_out += _T("\\"); path_out += file_out; DeleteFile(path_out.c_str()); cmd += _T("\" "); mir_free(temp); cmd += _T(" -e \""); cmd += filename; cmd += _T("\" "); gpg_execution_params params; params.cmd = &cmd; params.useless = ""; params.out = &out; params.code = &code; params.result = &result; mir_free(keyid); delete [] file_out; boost::thread *gpg_thread = new boost::thread(boost::bind(&pxEexcute_thread, ¶ms)); if(!gpg_thread->timed_join(boost::posix_time::seconds(180))) { delete gpg_thread; TerminateProcess(params.hProcess, 1); params.hProcess = NULL; debuglog<timed_join(boost::posix_time::seconds(180))) { delete gpg_thread; TerminateProcess(params.hProcess, 1); params.hProcess = NULL; debuglog<hContact)) { DWORD flags = (DWORD)ccs->wParam; //check for PFTS_UNICODE here int i; // if(flags & PFTS_UNICODE) //this does not work .... if(StriStr(ccs->szProtoService, "/sendfilew")) { TCHAR **file=(TCHAR **)ccs->lParam; for(i = 0; file[i]; i++) { if(_waccess(file[i], 0) == -1) if(errno == ENOENT) return 0; //we do not want to send file unencrypted (sometimes ack have wrong info) if (_tcsstr(file[i],_T(".gpg"))) continue; std::wstring path_out = encrypt_file(ccs->hContact, file[i]); mir_free(file[i]); file[i] = mir_tstrdup(path_out.c_str()); transfers.push_back(path_out); } } else { char **file = (char**) ccs->lParam; for(i = 0; file[i]; i++) { if(_access(file[i], 0) == -1) if(errno == ENOENT) return 0; //we do not want to send file unencrypted (sometimes ack have wrong info) if (strstr(file[i],".gpg")) continue; TCHAR *tmp = mir_utf8decodeT(file[i]); std::wstring path_out = encrypt_file(ccs->hContact, tmp); mir_free(tmp); char* tmp2 = mir_utf8encodeW(path_out.c_str()); mir_free(file[i]); file[i] = tmp2; transfers.push_back(path_out); } } } return CallService(MS_PROTO_CHAINSEND, w, l); } void storeOutput(HANDLE ahandle, string *output) { BOOL success; char *readbuffer = NULL; unsigned long transfered, available; do { PeekNamedPipe(ahandle,NULL,0,NULL,&available,NULL); if (!available) continue; readbuffer = (char*)mir_alloc(available); success=ReadFile(ahandle,readbuffer,available,&transfered,NULL); if (success && transfered) output->append(readbuffer, available); mir_free(readbuffer); } while (available>0); } void HistoryLog(HANDLE hContact, db_event evt) { DBEVENTINFO Event = {0}; Event.cbSize = sizeof(Event); Event.szModule = szGPGModuleName; Event.eventType = evt.eventType; Event.flags = evt.flags; if(!evt.timestamp) Event.timestamp = (DWORD)time(NULL); else Event.timestamp = evt.timestamp; Event.cbBlob = strlen((char*)evt.pBlob)+1; Event.pBlob = (PBYTE)_strdup((char*)evt.pBlob); CallService(MS_DB_EVENT_ADD, (WPARAM)(HANDLE)hContact,(LPARAM)&Event); } static int ControlAddStringUtf(HWND ctrl, DWORD msg, const TCHAR *szString) { int item = -1; item = SendMessage(ctrl, msg, 0, (LPARAM)szString); return item; } int ComboBoxAddStringUtf(HWND hCombo, const TCHAR *szString, DWORD data) { int item = ControlAddStringUtf(hCombo, CB_ADDSTRING, szString); SendMessage(hCombo, CB_SETITEMDATA, item, data); return item; } int GetJabberInterface(WPARAM w, LPARAM l) //get interface for all jabber accounts, options later { extern list Accounts; void AddHandlers(); int count = 0; PROTOACCOUNT **accounts; ProtoEnumAccounts(&count, &accounts); list ::iterator p; Accounts.clear(); Accounts.push_back(new JabberAccount); p = Accounts.begin(); (*p)->setAccountNumber(0); for(int i = 0; i < count; i++) //get only jabber accounts from all accounts { IJabberInterface *JIftmp = getJabberApi(accounts[i]->szModuleName); int a = 0; if(JIftmp) { (*p)->setJabberInterface(JIftmp); if(accounts[i]->tszAccountName) { TCHAR* tmp = mir_tstrdup(accounts[i]->tszAccountName); (*p)->setAccountName(tmp); } else { TCHAR *tmp = mir_a2t(accounts[i]->szModuleName); (*p)->setAccountName(tmp); } (*p)->setAccountNumber(a); a++; Accounts.push_back(new JabberAccount); p++; } } Accounts.pop_back(); AddHandlers(); return 0; } static JABBER_HANDLER_FUNC SendHandler(IJabberInterface *ji, HXML node, void *pUserData) { HXML local_node = node; for(int n = 0; n <= xi.getChildCount(node); n++) { LPCTSTR str = xi.getText(local_node); LPCTSTR nodename = xi.getName(local_node); if(str) { if(_tcsstr(str, _T("-----BEGIN PGP MESSAGE-----")) && _tcsstr(str, _T("-----END PGP MESSAGE-----"))) { wstring data = str; xi.setText(local_node, _T("This message is encrypted.")); wstring::size_type p1 = data.find(_T("-----BEGIN PGP MESSAGE-----")) + _tcslen(_T("-----BEGIN PGP MESSAGE-----")); while(data.find(_T("Version: "), p1) != wstring::npos) { p1 = data.find(_T("Version: "), p1); p1 = data.find(_T("\n"), p1); } while(data.find(_T("Comment: "), p1) != wstring::npos) { p1 = data.find(_T("Comment: "), p1); p1 = data.find(_T("\n"), p1); } while(data.find(_T("Encoding: "), p1) != wstring::npos) { p1 = data.find(_T("Encoding: "), p1); p1 = data.find(_T("\n"), p1); } p1+=2; wstring::size_type p2 = data.find(_T("-----END PGP MESSAGE-----")); HXML encrypted_data = xi.addChild(node, _T("x"), data.substr(p1, p2-p1).c_str()); xi.addAttr(encrypted_data, _T("xmlns"), _T("jabber:x:encrypted")); return FALSE; } } if(bPresenceSigning && nodename) { if(_tcsstr(nodename, _T("status"))) { TCHAR *path_c = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T("")); wstring path_out = path_c; wstring file = toUTF16(get_random(10)); mir_free(path_c); path_out += _T("\\tmp\\"); path_out += file; DeleteFile(path_out.c_str()); wfstream f(path_out.c_str(), std::ios::out); f<Sys()->GetModuleName(); char setting[64]; strcpy(setting, proto); strcat(setting, "_KeyID"); inkeyid = UniGetContactSettingUtf(NULL, szGPGModuleName, setting, ""); if(!inkeyid[0]) { mir_free(inkeyid); inkeyid = UniGetContactSettingUtf(NULL, szGPGModuleName, "KeyID", ""); } } TCHAR *pass = NULL; if(inkeyid[0]) { string dbsetting = "szKey_"; dbsetting += inkeyid; dbsetting += "_Password"; pass = UniGetContactSettingUtf(NULL, szGPGModuleName, dbsetting.c_str(), _T("")); if(pass[0]) debuglog< Accounts; list ::iterator p = Accounts.begin(); for(unsigned int i = 0; i < Accounts.size(); i++, p++) { if(!(*p)) break; hContact = (*p)->getJabberInterface()->Sys()->ContactFromJID(xi.getAttrValue(node, _T("from"))); if(hContact) hcontact_data[hContact].key_in_prescense = out.substr(p1, p2-p1-1).c_str(); } } } } } return FALSE; } } } } local_node = xi.getChild(node, n); } return FALSE; } static JABBER_HANDLER_FUNC MessageHandler(IJabberInterface *ji, HXML node, void *pUserData) { return FALSE; } void AddHandlers() { extern list Accounts; list::iterator end = Accounts.end(); for(list::iterator p = Accounts.begin(); p != end; p++) { if(!(*p)) break; if((*p)->getSendHandler() == INVALID_HANDLE_VALUE) (*p)->setSendHandler((*p)->getJabberInterface()->Net()->AddSendHandler((JABBER_HANDLER_FUNC)SendHandler)); if((*p)->getPrescenseHandler() == INVALID_HANDLE_VALUE) (*p)->setPrescenseHandler((*p)->getJabberInterface()->Net()->AddPresenceHandler((JABBER_HANDLER_FUNC)PrescenseHandler)); // if((*p)->getMessageHandler() == INVALID_HANDLE_VALUE) // (*p)->setMessageHandler((*p)->getJabberInterface()->Net()->AddMessageHandler((JABBER_HANDLER_FUNC)MessageHandler, JABBER_MESSAGE_TYPE_ANY ,NULL,NULL)); if(bAutoExchange) { (*p)->getJabberInterface()->Net()->RegisterFeature(_T("GPG_Key_Auto_Exchange:0"), _T("Indicates that gpg installed and configured to public key auto exchange (currently implemented in new_gpg Miranda IM plugin)")); (*p)->getJabberInterface()->Net()->AddFeatures(_T("GPG_Key_Auto_Exchange:0\0\0")); } } } bool isContactSecured(HANDLE hContact) { BYTE gpg_enc = DBGetContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 0); if(!gpg_enc) { debuglog< 0) { mir_free(key); return true; } mir_free(key); return false; } bool isGPGKeyExist() { TCHAR *id = UniGetContactSettingUtf(NULL, szGPGModuleName, "KeyID", _T("")); char *key = UniGetContactSettingUtf(NULL, szGPGModuleName, "GPGPubKey", ""); if(id[0] && key[0]) { mir_free(id); mir_free(key); return true; } mir_free(id); mir_free(key); return false; } bool isGPGValid() { TCHAR *tmp; bool gpg_exists = false, is_valid = true; tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szGpgBinPath", _T("")); if(_waccess(tmp, 0) != -1) gpg_exists = true; else { mir_free(tmp); TCHAR *path = (TCHAR*)mir_alloc(sizeof(TCHAR)*MAX_PATH); char *mir_path = (char*)mir_alloc(MAX_PATH); CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)"\\", (LPARAM)mir_path); SetCurrentDirectoryA(mir_path); tmp = mir_a2t(mir_path); mir_free(mir_path); //mir_realloc(path, (_tcslen(path)+64)*sizeof(TCHAR)); TCHAR *gpg_path = (TCHAR*)mir_alloc(sizeof(TCHAR)*MAX_PATH); _tcscpy(gpg_path, tmp); _tcscat(gpg_path, _T("\\GnuPG\\gpg.exe")); mir_free(tmp); if(_waccess(gpg_path, 0) != -1) { gpg_exists = true; _tcscpy(path, _T("GnuPG\\gpg.exe")); } mir_free(gpg_path); tmp = mir_tstrdup(path); mir_free(path); } DWORD len = MAX_PATH; if(gpg_exists) { DBWriteContactSettingTString(NULL, szGPGModuleName, "szGpgBinPath", tmp); string out; DWORD code; wstring cmd = _T("--version"); gpg_execution_params params; pxResult result; params.cmd = &cmd; params.useless = ""; params.out = &out; params.code = &code; params.result = &result; gpg_valid = true; boost::thread gpg_thread(boost::bind(&pxEexcute_thread, ¶ms)); if(!gpg_thread.timed_join(boost::posix_time::seconds(10))) { gpg_thread.~thread(); TerminateProcess(params.hProcess, 1); params.hProcess = NULL; debuglog< struct TFakeAckParams { inline TFakeAckParams( HANDLE p1, HANDLE p2, LONG p3, LPCSTR p4 ) : hEvent( p1 ), hContact( p2 ), id( p3 ), msg( p4 ) {} HANDLE hEvent; HANDLE hContact; LONG id; LPCSTR msg; }; int SendBroadcast( HANDLE hContact, int type, int result, HANDLE hProcess, LPARAM lParam ) { ACKDATA ack; memset(&ack,0,sizeof(ack)); ack.cbSize = sizeof( ACKDATA ); ack.szModule = szGPGModuleName;// (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); ack.hContact = hContact; ack.type = type; ack.result = result; ack.hProcess = hProcess; ack.lParam = lParam; return CallService( MS_PROTO_BROADCASTACK, 0, ( LPARAM )&ack ); } unsigned __stdcall sttFakeAck( LPVOID param ) { TFakeAckParams* tParam = ( TFakeAckParams* )param; WaitForSingleObject( tParam->hEvent, INFINITE ); Sleep( 100 ); if ( tParam->msg == NULL ) SendBroadcast( tParam->hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, ( HANDLE )tParam->id, 0 ); else SendBroadcast( tParam->hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, ( HANDLE )tParam->id, LPARAM( tParam->msg )); CloseHandle( tParam->hEvent ); delete tParam; return 0; } int returnNoError(HANDLE hContact) { HANDLE hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); unsigned int tID; CloseHandle( (HANDLE) _beginthreadex(NULL, 0, sttFakeAck, new TFakeAckParams(hEvent,hContact,777,0), 0, &tID) ); SetEvent( hEvent ); return 777; } // end from secureim string toUTF8(wstring str) { string ustr; try{ utf8::utf16to8(str.begin(), str.end(), back_inserter(ustr)); } catch(const utf8::exception& e) { debuglog<> gen(rng, boost::uniform_int<>(0, chars.length()-1)); for(int i = 0; i < length; ++i) data += chars[gen()]; return data; } void send_encrypted_msgs_thread(HANDLE hContact) { while(true) { char *key = UniGetContactSettingUtf(hContact, szGPGModuleName, "GPGPubKey", ""); while(!isContactSecured(hContact)) boost::this_thread::sleep(boost::posix_time::seconds(1)); if(!hcontact_data[hContact].msgs_to_send.empty()) { boost::this_thread::sleep(boost::posix_time::seconds(1)); list::iterator end = hcontact_data[hContact].msgs_to_send.end(); extern std::list sent_msgs; for(list::iterator p = hcontact_data[hContact].msgs_to_send.begin(); p != end; ++p) { sent_msgs.push_back((HANDLE)CallContactService(hContact, PSS_MESSAGE, (WPARAM)PREF_UTF, (LPARAM)p->c_str())); HistoryLog(hContact, db_event((char*)p->c_str(),0,0, DBEF_SENT)); boost::this_thread::sleep(boost::posix_time::seconds(1)); } hcontact_data[hContact].msgs_to_send.clear(); return; } else return; } } string time_str() { boost::posix_time::ptime now = boost::posix_time::second_clock::local_time(); return (string)boost::posix_time::to_simple_string(now); } int handleEnum(const char *szSetting, LPARAM lParam) { if(!*(bool*)lParam && szSetting[0] && StriStr(szSetting, "tabsrmm")) { bool f = false, *found = (bool*)lParam; f = !DBGetContactSettingByte(NULL, "PluginDisable", szSetting, 0); if(f) *found = f; } return 0; } bool isTabsrmmUsed() { DBCONTACTENUMSETTINGS enm = {0}; bool found = false; enm.lParam = (LPARAM)&found; enm.pfnEnumProc = (DBSETTINGENUMPROC)&handleEnum; enm.szModule = "PluginDisable"; if(CallService(MS_DB_CONTACT_ENUMSETTINGS, (WPARAM)NULL, (LPARAM)&enm) == -1) return false; return found; } INT_PTR ExportGpGKeys(WPARAM w, LPARAM l) { TCHAR *p = GetFilePath(_T("Choose file to export public keys"), _T("*"), _T("Any file"), true); if(!p || !p[0]) { delete [] p; //TODO: handle error return 1; } char *path = mir_t2a(p); delete [] p; std::ofstream file; file.open(path, std::ios::trunc | std::ios::out); mir_free(path); int exported_keys = 0; if(!file.is_open()) return 1; //TODO: handle error for(HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); hContact; hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0)) { char *k = UniGetContactSettingUtf(hContact, szGPGModuleName, "GPGPubKey", ""); if(!k[0]) { mir_free(k); continue; } std::string key = k; mir_free(k); const char* proto = (const char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); std::string id = "Comment: login "; const char * uid = (const char*)CallProtoService(proto, PS_GETCAPS, (WPARAM)PFLAG_UNIQUEIDSETTING, 0); DBVARIANT dbv = {0}; DBCONTACTGETSETTING dbcgs = {0}; dbcgs.pValue = &dbv; dbcgs.szModule = proto; dbcgs.szSetting = uid; CallService(MS_DB_CONTACT_GETSETTING, 0, (LPARAM)&dbcgs); switch(dbcgs.pValue->type) { case DBVT_DELETED: continue; break; case DBVT_BYTE: { char _id[64]; mir_snprintf(_id, 63, "%d", dbcgs.pValue->bVal); id += _id; } break; case DBVT_WORD: { char _id[64]; mir_snprintf(_id, 63, "%d", dbcgs.pValue->wVal); id += _id; } break; case DBVT_DWORD: { char _id[64]; mir_snprintf(_id, 63, "%d", dbcgs.pValue->dVal); id += _id; } break; case DBVT_ASCIIZ: { id += dbcgs.pValue->pszVal; CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); } break; case DBVT_UTF8: { char *tmp = mir_utf8decodeA(dbcgs.pValue->pszVal); if(tmp[0]) id += tmp; mir_free(tmp); CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); } break; case DBVT_BLOB: //TODO CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); break; case DBVT_WCHAR: //TODO CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); break; } id += " contact_id "; ZeroMemory(&dbv, sizeof(dbv)); ZeroMemory(&dbcgs, sizeof(dbcgs)); dbcgs.pValue = &dbv; dbcgs.szModule = proto; dbcgs.szSetting = uid; CallService(MS_DB_CONTACT_GETSETTING, (WPARAM)hContact, (LPARAM)&dbcgs); switch(dbcgs.pValue->type) { case DBVT_DELETED: continue; break; case DBVT_BYTE: { char _id[64]; mir_snprintf(_id, 63, "%d", dbcgs.pValue->bVal); id += _id; } break; case DBVT_WORD: { char _id[64]; mir_snprintf(_id, 63, "%d", dbcgs.pValue->wVal); id += _id; } break; case DBVT_DWORD: { char _id[64]; mir_snprintf(_id, 63, "%d", dbcgs.pValue->dVal); id += _id; } break; case DBVT_ASCIIZ: { id += dbcgs.pValue->pszVal; CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); } break; case DBVT_UTF8: { char *tmp = mir_utf8decodeA(dbcgs.pValue->pszVal); if(tmp[0]) id += tmp; mir_free(tmp); CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); } break; case DBVT_BLOB: //TODO CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); break; case DBVT_WCHAR: //TODO CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); break; } std::string::size_type p1 = key.find("-----BEGIN PGP PUBLIC KEY BLOCK-----"); if(p1 == std::string::npos) continue; p1 += strlen("-----BEGIN PGP PUBLIC KEY BLOCK-----"); p1 ++; id += '\n'; key.insert(p1, id); file<szModuleName, PS_GETCAPS, (WPARAM)PFLAG_UNIQUEIDSETTING, 0); DBVARIANT dbv = {0}; DBCONTACTGETSETTING dbcgs = {0}; dbcgs.pValue = &dbv; dbcgs.szModule = accs[i]->szModuleName; dbcgs.szSetting = uid; CallService(MS_DB_CONTACT_GETSETTING, 0, (LPARAM)&dbcgs); std::string id; switch(dbcgs.pValue->type) { case DBVT_DELETED: continue; break; case DBVT_BYTE: { char _id[64]; mir_snprintf(_id, 63, "%d", dbcgs.pValue->bVal); id += _id; if(id == login) acc = accs[i]->szModuleName; } break; case DBVT_WORD: { char _id[64]; mir_snprintf(_id, 63, "%d", dbcgs.pValue->wVal); id += _id; if(id == login) acc = accs[i]->szModuleName; } break; case DBVT_DWORD: { char _id[64]; mir_snprintf(_id, 63, "%d", dbcgs.pValue->dVal); id += _id; if(id == login) acc = accs[i]->szModuleName; } break; case DBVT_ASCIIZ: { id += dbcgs.pValue->pszVal; CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); if(id == login) acc = accs[i]->szModuleName; } break; case DBVT_UTF8: { char *tmp = mir_utf8decodeA(dbcgs.pValue->pszVal); if(tmp[0]) id += tmp; mir_free(tmp); CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); if(id == login) acc = accs[i]->szModuleName; } break; case DBVT_BLOB: //TODO CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); break; case DBVT_WCHAR: //TODO CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); break; } } if(acc.length()) { const char * uid = (const char*)CallProtoService(acc.c_str(), PS_GETCAPS, (WPARAM)PFLAG_UNIQUEIDSETTING, 0); for(HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, (LPARAM)acc.c_str()); hContact; hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, (LPARAM)acc.c_str())) { DBVARIANT dbv = {0}; DBCONTACTGETSETTING dbcgs = {0}; dbcgs.pValue = &dbv; dbcgs.szModule = acc.c_str(); dbcgs.szSetting = uid; CallService(MS_DB_CONTACT_GETSETTING, (WPARAM)hContact, (LPARAM)&dbcgs); std::string id; bool found = false; switch(dbcgs.pValue->type) { case DBVT_DELETED: continue; break; case DBVT_BYTE: { char _id[64]; mir_snprintf(_id, 63, "%d", dbcgs.pValue->bVal); id += _id; if(id == contact_id) found = true; } break; case DBVT_WORD: { char _id[64]; mir_snprintf(_id, 63, "%d", dbcgs.pValue->wVal); id += _id; if(id == contact_id) found = true; } break; case DBVT_DWORD: { char _id[64]; mir_snprintf(_id, 63, "%d", dbcgs.pValue->dVal); id += _id; if(id == contact_id) found = true; } break; case DBVT_ASCIIZ: { id += dbcgs.pValue->pszVal; CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); if(id == contact_id) found = true; } break; case DBVT_UTF8: { char *tmp = mir_utf8decodeA(dbcgs.pValue->pszVal); if(tmp[0]) id += tmp; mir_free(tmp); CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); if(id == contact_id) found = true; } break; case DBVT_BLOB: //TODO CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); break; case DBVT_WCHAR: //TODO CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); break; } if(found) { wstring cmd; TCHAR tmp2[MAX_PATH] = {0}; TCHAR *ptmp; string output; DWORD exitcode; { HANDLE hcnt = hContact; ptmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T("")); _tcscpy(tmp2, ptmp); mir_free(ptmp); _tcscat(tmp2, _T("\\")); _tcscat(tmp2, _T("temporary_exported.asc")); DeleteFile(tmp2); wfstream f(tmp2, std::ios::out); f< output.find("<", s)) s2 = output.find("<", s); if(s2 != string::npos) { tmp2 = new char [output.substr(s,s2-s-1).length()+1]; strcpy(tmp2, output.substr(s,s2-s-1).c_str()); mir_utf8decode(tmp2, 0); if(hContact) { DBWriteContactSettingString(hContact, szGPGModuleName, "KeyMainName", output.substr(s,s2-s-1).c_str()); } mir_free(tmp2); if((s = output.find(")", s2)) == string::npos) s = output.find(">", s2); else if(s > output.find(">", s2)) s = output.find(">", s2); s2++; if(output[s] == ')') { tmp2 = new char [output.substr(s2,s-s2).length()+1]; strcpy(tmp2, output.substr(s2,s-s2).c_str()); mir_utf8decode(tmp2, 0); if(hContact) DBWriteContactSettingString(hContact, szGPGModuleName, "KeyComment", output.substr(s2,s-s2).c_str()); mir_free(tmp2); s+=3; s2 = output.find(">", s); tmp2 = new char [output.substr(s,s2-s).length()+1]; strcpy(tmp2, output.substr(s,s2-s).c_str()); mir_utf8decode(tmp2, 0); if(hContact) DBWriteContactSettingString(hContact, szGPGModuleName, "KeyMainEmail", output.substr(s,s2-s).c_str()); mir_free(tmp2); } else { tmp2 = new char [output.substr(s2,s-s2).length()+1]; strcpy(tmp2, output.substr(s2,s-s2).c_str()); mir_utf8decode(tmp2, 0); if(hContact) DBWriteContactSettingString(hContact, szGPGModuleName, "KeyMainEmail", output.substr(s2,s-s2).c_str()); mir_free(tmp2); } } DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 1); DBWriteContactSettingTString(hContact, szGPGModuleName, "GPGPubKey", toUTF16(key).c_str()); } DeleteFile(tmp2); break; } } } key.clear(); } } if(file.is_open()) file.close(); char msg[512]; mir_snprintf(msg, 511, "we have succesfully processed %d keys", processed_keys); MessageBoxA(NULL, msg, Translate("Keys import result"), MB_OK); return 0; }