diff options
author | Gluzskiy Alexandr <sss@sss.chaoslab.ru> | 2012-07-29 01:01:18 +0300 |
---|---|---|
committer | Gluzskiy Alexandr <sss@sss.chaoslab.ru> | 2012-07-29 01:01:18 +0300 |
commit | 8ef18318d8f81a533c0e3bc5c10c76fec0be3b5f (patch) | |
tree | 88eb30555006e99e5cc446eee4520f3f955eae99 /utilities.cpp | |
parent | 191c2e330ab91f4b35860e08c5424667ed1893c5 (diff) | |
parent | 64c6452c697a05ab0b0d4bbbda167ddc35215397 (diff) |
Merge branch 'new_gpg' into new_gpg_autoexchangenew_gpg_autoexchange
Conflicts:
main.cpp
messages.cpp
Diffstat (limited to 'utilities.cpp')
-rwxr-xr-x[-rw-r--r--] | utilities.cpp | 942 |
1 files changed, 795 insertions, 147 deletions
diff --git a/utilities.cpp b/utilities.cpp index dbf8786..2207213 100644..100755 --- a/utilities.cpp +++ b/utilities.cpp @@ -1,4 +1,4 @@ -// Copyright © 2010 sss +// 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 @@ -195,8 +195,23 @@ int SendKey(WPARAM w, LPARAM l) HANDLE hContact = (HANDLE)w; if(metaIsProtoMetaContacts(hContact)) hContact = metaGetMostOnline(hContact); - char *szMessage = UniGetContactSettingUtf(NULL, szGPGModuleName, "GPGPubKey", ""); - if(strlen(szMessage) > 1) + char *szMessage; + { + char *proto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + char setting[64]; + if(proto) + { + strcpy(setting, proto); + strcat(setting, "_GPGPubKey"); + szMessage = UniGetContactSettingUtf(NULL, szGPGModuleName, setting, ""); + } + if(!szMessage[0]) + { + mir_free(szMessage); + szMessage = UniGetContactSettingUtf(NULL, szGPGModuleName, "GPGPubKey", ""); + } + } + if(szMessage[0]) { BYTE enc = DBGetContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 0); DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 0); @@ -234,7 +249,7 @@ int ToggleEncryption(WPARAM w, LPARAM l) } } else - DBWriteContactSettingByte(metaGetMostOnline(hContact), szGPGModuleName, "GPGEncryption", enc?0:1); + DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", enc?0:1); void setSrmmIcon(HANDLE hContact); void setClistIcon(HANDLE hContact); setSrmmIcon(hContact); @@ -275,171 +290,195 @@ extern bool bFileTransfers; int onProtoAck(WPARAM w, LPARAM l) { - if(!bFileTransfers) - return 0; ACKDATA *ack=(ACKDATA*)l; CCSDATA *ccs=(CCSDATA*)ack->lParam; - if (ack->type!=ACKTYPE_FILE) - return 0; - - switch(ack->result) + + if(ack->type == ACKTYPE_FILE && bFileTransfers) { - case ACKRESULT_DENIED: case ACKRESULT_FAILED: - break; - case ACKRESULT_SUCCESS: + switch(ack->result) { - 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 + case ACKRESULT_DENIED: case ACKRESULT_FAILED: + break; + case ACKRESULT_SUCCESS: { - 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) + PROTOFILETRANSFERSTATUS *f = (PROTOFILETRANSFERSTATUS*) ack->hProcess; + TCHAR *filename = NULL; + if(f->flags & PFTS_UNICODE) { - if(errno == ENOENT) + if(f->tszCurrentFile && f->tszCurrentFile[0]) + filename = mir_wstrdup(f->tszCurrentFile); + if(!filename) 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) + else { - if(MessageBox(0, _T("Target file exists, do you want to replace it ?"), _T("Warning"), MB_YESNO) == IDNO) + if(f->szCurrentFile && f->szCurrentFile[0]) + filename = mir_utf8decodeT(f->szCurrentFile); + if(!filename) return 0; } - DeleteFile(file.c_str()); - file.insert(0, _T("\"")); - file.insert(file.length(), _T("\" ")); - cmd += file; - cmd += _T(" -d \""); - cmd += filename; - cmd += _T("\""); - extern TCHAR *password; - { // password - TCHAR *pass = NULL; - char *keyid = UniGetContactSettingUtf(ccs->hContact, szGPGModuleName, "KeyID", ""); - if(strlen(keyid) > 0) - { - string dbsetting = "szKey_"; - dbsetting += keyid; - dbsetting += "_Password"; - pass = UniGetContactSettingUtf(NULL, szGPGModuleName, dbsetting.c_str(), _T("")); - if(_tcslen(pass) > 0) - debuglog<<time_str()<<": info: found password in database for key id: "<<keyid<<", trying to decrypt message from "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ccs->hContact, GCDNF_TCHAR)<<" with password\n"; - } - else - { - pass = UniGetContactSettingUtf(NULL, szGPGModuleName, "szKeyPassword", _T("")); - if(_tcslen(pass) > 0) - debuglog<<time_str()<<": info: found password for all keys in database, trying to decrypt message from "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ccs->hContact, GCDNF_TCHAR)<<" with password\n"; - } - if(_tcslen(pass) > 0) + if(_tcsstr(filename, _T(".gpg"))) //decrypt it + { //process encrypted file + if(_waccess(f->tszCurrentFile, 0) == -1) { - cmd += _T("--passphrase \""); - cmd += pass; - cmd += _T("\" "); + if(errno == ENOENT) + return 0; } - else if(password) + 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) { - debuglog<<time_str()<<": info: found password in memory, trying to decrypt message from "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ccs->hContact, GCDNF_TCHAR)<<" with password\n"; - cmd += _T("--passphrase \""); - cmd += password; - cmd += _T("\" "); - } - else - debuglog<<time_str()<<": info: passwords not found in database or memory, trying to decrypt message from "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ccs->hContact, GCDNF_TCHAR)<<" with out password\n"; - mir_free(pass); - mir_free(keyid); - } - 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<<time_str()<<": GPG execution timed out, aborted\n"; - return 0; - } - while(out.find("public key decryption failed: bad passphrase") != string::npos) - { - extern bool _terminate; - extern HANDLE new_key_hcnt; - extern boost::mutex new_key_hcnt_mutex; - debuglog<<time_str()<<": info: failed to decrypt messaage from "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ccs->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); - DBWriteContactSettingString(metaGetMostOnline(ccs->hContact), szGPGModuleName, "InKeyID", out.substr(s, s2-s).c_str()); + if(MessageBox(0, _T("Target file exists, do you want to replace it ?"), _T("Warning"), MB_YESNO) == IDNO) + return 0; } - void ShowLoadKeyPasswordWindow(); - new_key_hcnt_mutex.lock(); - new_key_hcnt = ccs->hContact; - ShowLoadKeyPasswordWindow(); - wstring cmd2 = cmd; - if(password) - { - debuglog<<time_str()<<": info: found password in memory, trying to decrypt message from "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ccs->hContact, GCDNF_TCHAR)<<"\n"; - wstring tmp = _T("--passphrase \""); - tmp += password; - tmp += _T("\" "); - cmd2.insert(0, tmp); + DeleteFile(file.c_str()); + file.insert(0, _T("\"")); + file.insert(file.length(), _T("\" ")); + cmd += file; + extern TCHAR *password; + { // password + TCHAR *pass = NULL; + char *keyid = UniGetContactSettingUtf(ack->hContact, szGPGModuleName, "KeyID", ""); + if(strlen(keyid) > 0) + { + string dbsetting = "szKey_"; + dbsetting += keyid; + dbsetting += "_Password"; + pass = UniGetContactSettingUtf(NULL, szGPGModuleName, dbsetting.c_str(), _T("")); + if(_tcslen(pass) > 0) + debuglog<<time_str()<<": info: found password in database for key id: "<<keyid<<", trying to decrypt message from "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ack->hContact, GCDNF_TCHAR)<<" with password\n"; + } + else + { + pass = UniGetContactSettingUtf(NULL, szGPGModuleName, "szKeyPassword", _T("")); + if(_tcslen(pass) > 0) + debuglog<<time_str()<<": info: found password for all keys in database, trying to decrypt message from "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ack->hContact, GCDNF_TCHAR)<<" with password\n"; + } + if(_tcslen(pass) > 0) + { + cmd += _T("--passphrase \""); + cmd += pass; + cmd += _T("\" "); + } + else if(password) + { + debuglog<<time_str()<<": info: found password in memory, trying to decrypt message from "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ack->hContact, GCDNF_TCHAR)<<" with password\n"; + cmd += _T("--passphrase \""); + cmd += password; + cmd += _T("\" "); + } + else + debuglog<<time_str()<<": info: passwords not found in database or memory, trying to decrypt message from "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ack->hContact, GCDNF_TCHAR)<<" with out password\n"; + mir_free(pass); + mir_free(keyid); } - out.clear(); + cmd += _T(" -d \""); + cmd += filename; + cmd += _T("\""); gpg_execution_params params; - pxResult result; - params.cmd = &cmd2; + params.cmd = &cmd; 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))) + 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<<time_str()<<": GPG execution timed out, aborted\n"; - DeleteFile(filename); return 0; } - if(result == pxNotFound) + while(out.find("public key decryption failed: bad passphrase") != string::npos) { - DeleteFile(filename); - return 0; + extern bool _terminate; + extern HANDLE new_key_hcnt; + extern boost::mutex new_key_hcnt_mutex; + debuglog<<time_str()<<": info: failed to decrypt messaage from "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ack->hContact, GCDNF_TCHAR)<<" password needed, trying to get one\n"; + if(_terminate) + break; + { //save inkey id + string::size_type s = out.find(" encrypted with "); + s = out.find(" ID ", s); + s += strlen(" ID "); + string::size_type s2 = out.find(",",s); + if(metaIsProtoMetaContacts(ack->hContact)) + DBWriteContactSettingString(metaGetMostOnline(ack->hContact), szGPGModuleName, "InKeyID", out.substr(s, s2-s).c_str()); + else + DBWriteContactSettingString(ack->hContact, szGPGModuleName, "InKeyID", out.substr(s, s2-s).c_str()); + } + void ShowLoadKeyPasswordWindow(); + new_key_hcnt_mutex.lock(); + new_key_hcnt = ack->hContact; + ShowLoadKeyPasswordWindow(); + wstring cmd2 = cmd; + if(password) + { + debuglog<<time_str()<<": info: found password in memory, trying to decrypt message from "<<(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ack->hContact, GCDNF_TCHAR)<<"\n"; + wstring tmp = _T("--passphrase \""); + tmp += password; + tmp += _T("\" "); + cmd2.insert(0, tmp); + } + out.clear(); + gpg_execution_params params; + pxResult result; + params.cmd = &cmd2; + params.useless = ""; + params.out = &out; + params.code = &code; + params.result = &result; + gpg_thread = gpg_thread = new boost::thread(boost::bind(&pxEexcute_thread, ¶ms)); + if(!gpg_thread->timed_join(boost::posix_time::seconds(15))) + { + delete gpg_thread; + TerminateProcess(params.hProcess, 1); + params.hProcess = NULL; + debuglog<<time_str()<<": GPG execution timed out, aborted\n"; + DeleteFile(filename); + return 0; + } + if(result == pxNotFound) + { + DeleteFile(filename); + return 0; + } } - } - DeleteFile(filename); - mir_free(filename); + DeleteFile(filename); + mir_free(filename); } } break; } + } + else if(ack->type == ACKTYPE_MESSAGE) + { + extern std::list<HANDLE> sent_msgs; + if(!sent_msgs.empty()) + { + if(ack->result == ACKRESULT_FAILED) + { + std::list<HANDLE>::iterator it = std::find(sent_msgs.begin(), sent_msgs.end(), ack->hProcess); + if(it != sent_msgs.end()) + { + HistoryLog(ack->hContact, db_event("Failed to send encrypted message", 0,0, 0)); + + } + } + else if(ack->result == ACKRESULT_SUCCESS) + { + std::list<HANDLE>::iterator it = std::find(sent_msgs.begin(), sent_msgs.end(), ack->hProcess); + if(it != sent_msgs.end()) + sent_msgs.erase(it); + } + } + } return 0; } @@ -448,10 +487,9 @@ 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(hContact, szGPGModuleName, "KeyID", ""); - if(DBGetContactSettingByte(hContact, szGPGModuleName, "bAlwaysTrust", 0)) - cmd += _T("--trust-model always "); + char *keyid = UniGetContactSettingUtf(hcnt, szGPGModuleName, "KeyID", ""); TCHAR *szKeyid = mir_a2t(keyid); TCHAR *name = _tcsrchr(filename,_T('\\')); if( !name ) @@ -461,6 +499,8 @@ std::wstring encrypt_file(HANDLE hContact, TCHAR *filename) 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 \""); @@ -499,7 +539,7 @@ std::wstring encrypt_file(HANDLE hContact, TCHAR *filename) out.clear(); if(MessageBox(0, _T("We trying to encrypt with untrusted key, do you want to trust this key permanently ?"), _T("Warning"), MB_YESNO) == IDYES) { - DBWriteContactSettingByte(hContact, szGPGModuleName, "bAlwaysTrust", 1); + DBWriteContactSettingByte(hcnt, szGPGModuleName, "bAlwaysTrust", 1); cmd.insert(0, _T("--trust-model always ")); gpg_thread = new boost::thread(boost::bind(&pxEexcute_thread, ¶ms)); if(!gpg_thread->timed_join(boost::posix_time::seconds(180))) @@ -528,7 +568,8 @@ int onSendFile(WPARAM w, LPARAM l) DWORD flags = (DWORD)ccs->wParam; //check for PFTS_UNICODE here int i; - if(flags & PFTS_UNICODE) +// if(flags & PFTS_UNICODE) //this does not work .... + if(StriStr(ccs->szProtoService, "/sendfilew")) { TCHAR **file=(TCHAR **)ccs->lParam; for(i = 0; file[i]; i++) @@ -692,7 +733,7 @@ static JABBER_HANDLER_FUNC SendHandler(IJabberInterface *ji, HXML node, void *pU return FALSE; } } - if(nodename) + if(bPresenceSigning && nodename) { if(_tcsstr(nodename, _T("status"))) { @@ -720,7 +761,19 @@ static JABBER_HANDLER_FUNC SendHandler(IJabberInterface *ji, HXML node, void *pU DWORD code; wstring cmd; { - char *inkeyid = UniGetContactSettingUtf(NULL, szGPGModuleName, "KeyID", ""); + char *inkeyid; + { + char *proto = ji->Sys()->GetModuleName(); + char setting[64]; + strcpy(setting, proto); + strcat(setting, "_KeyID"); + inkeyid = UniGetContactSettingUtf(NULL, szGPGModuleName, setting, ""); + if(!inkeyid[0]) + { + mir_free(inkeyid); + inkeyid = UniGetContactSettingUtf(NULL, szGPGModuleName, "KeyID", ""); + } + } TCHAR *pass = NULL; if(inkeyid[0]) { @@ -967,8 +1020,8 @@ void AddHandlers() (*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_ERROR,0 ,0)); +// 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)")); @@ -1012,7 +1065,7 @@ bool isContactHaveKey(HANDLE hContact) return false; } -bool isGPGConfigured() +bool isGPGKeyExist() { TCHAR *id = UniGetContactSettingUtf(NULL, szGPGModuleName, "KeyID", _T("")); char *key = UniGetContactSettingUtf(NULL, szGPGModuleName, "GPGPubKey", ""); @@ -1026,6 +1079,74 @@ bool isGPGConfigured() 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 = new TCHAR [MAX_PATH]; + char *mir_path = new char [MAX_PATH]; + CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)"\\", (LPARAM)mir_path); + SetCurrentDirectoryA(mir_path); + tmp = mir_a2t(mir_path); + mir_free(mir_path); + mir_realloc(path, (_tcslen(path)+128)*sizeof(TCHAR)); + TCHAR *gpg_path = new TCHAR [MAX_PATH]; + _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_wstrdup(path); + delete [] 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<<time_str()<<": GPG execution timed out, aborted\n"; + } + gpg_valid = false; + string::size_type p1 = out.find("(GnuPG) "); + if(p1 == string::npos) + is_valid = false; + } + mir_free(tmp); + if(!gpg_exists) + { + wstring path_ = _wgetenv(_T("APPDATA")); + path_ += _T("\\GnuPG"); + tmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", (TCHAR*)path_.c_str()); + } + mir_free(tmp); + return is_valid; +} #define NEWTSTR_MALLOC(A) (A==NULL)?NULL:strcpy((char*)mir_alloc(sizeof(char)*(strlen(A)+1)),A) @@ -1117,7 +1238,14 @@ int returnNoError(HANDLE hContact) { string toUTF8(wstring str) { string ustr; + try{ utf8::utf16to8(str.begin(), str.end(), back_inserter(ustr)); + } + catch(const utf8::exception& e) + { + debuglog<<std::string("utf8cpp encoding exception: ")+(char*)e.what(); + //TODO + } return ustr; } @@ -1127,8 +1255,15 @@ wstring toUTF16(string str) //convert as much as possible { wstring ustr; string tmpstr; + try{ utf8::replace_invalid(str.begin(), str.end(), back_inserter(tmpstr)); utf8::utf8to16(tmpstr.begin(), tmpstr.end(), back_inserter(ustr)); + } + catch(const utf8::exception& e) + { + debuglog<<std::string("utf8cpp decoding exception: ")+(char*)e.what(); + //TODO + } return ustr; } @@ -1154,13 +1289,14 @@ void send_encrypted_msgs_thread(HANDLE hContact) { boost::this_thread::sleep(boost::posix_time::seconds(1)); list<string>::iterator end = hcontact_data[hContact].msgs_to_send.end(); + extern std::list<HANDLE> sent_msgs; for(list<string>::iterator p = hcontact_data[hContact].msgs_to_send.begin(); p != end; ++p) { - CallContactService(hContact, PSS_MESSAGE, (WPARAM)PREF_UTF, (LPARAM)p->c_str()); - + 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 @@ -1173,3 +1309,515 @@ string time_str() boost::posix_time::ptime now = boost::posix_time::second_clock::local_time(); return (string)boost::posix_time::to_simple_string(now); } + +int handleEnum(const char *szSetting, LPARAM lParam) +{ + if(!*(bool*)lParam && szSetting[0] && StriStr(szSetting, "tabsrmm")) + { + bool f = false, *found = (bool*)lParam; + f = !DBGetContactSettingByte(NULL, "PluginDisable", szSetting, 0); + if(f) + *found = f; + } + return 0; +} + +bool isTabsrmmUsed() +{ + DBCONTACTENUMSETTINGS enm = {0}; + bool found = false; + enm.lParam = (LPARAM)&found; + enm.pfnEnumProc = (DBSETTINGENUMPROC)&handleEnum; + enm.szModule = "PluginDisable"; + if(CallService(MS_DB_CONTACT_ENUMSETTINGS, (WPARAM)NULL, (LPARAM)&enm) == -1) + return false; + + return found; +} + + +int ExportGpGKeys(WPARAM w, LPARAM l) +{ + TCHAR *p = GetFilePath(_T("Choose file to export public keys"), _T("*"), _T("Any file"), true); + if(!p || !p[0]) + { + delete [] p; + //TODO: handle error + return 1; + } + char *path = mir_t2a(p); + delete [] p; + std::ofstream file; + file.open(path, std::ios::trunc | std::ios::out); + mir_free(path); + int exported_keys = 0; + if(!file.is_open()) + return 1; //TODO: handle error + for(HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); hContact; hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0)) + { + char *k = UniGetContactSettingUtf(hContact, szGPGModuleName, "GPGPubKey", ""); + if(!k[0]) + { + mir_free(k); + continue; + } + std::string key = k; + mir_free(k); + + const char* proto = (const char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + std::string id = "Comment: login "; + const char * uid = (const char*)CallProtoService(proto, PS_GETCAPS, (WPARAM)PFLAG_UNIQUEIDSETTING, 0); + DBVARIANT dbv = {0}; + DBCONTACTGETSETTING dbcgs = {0}; + dbcgs.pValue = &dbv; + dbcgs.szModule = proto; + dbcgs.szSetting = uid; + CallService(MS_DB_CONTACT_GETSETTING, 0, (LPARAM)&dbcgs); + switch(dbcgs.pValue->type) + { + case DBVT_DELETED: + continue; + break; + case DBVT_BYTE: + { + char _id[64]; + mir_snprintf(_id, 63, "%d", dbcgs.pValue->bVal); + id += _id; + } + break; + case DBVT_WORD: + { + char _id[64]; + mir_snprintf(_id, 63, "%d", dbcgs.pValue->wVal); + id += _id; + } + break; + case DBVT_DWORD: + { + char _id[64]; + mir_snprintf(_id, 63, "%d", dbcgs.pValue->dVal); + id += _id; + } + break; + case DBVT_ASCIIZ: + { + id += dbcgs.pValue->pszVal; + CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); + } + break; + case DBVT_UTF8: + { + char *tmp = mir_utf8decodeA(dbcgs.pValue->pszVal); + if(tmp[0]) + id += tmp; + mir_free(tmp); + CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); + } + break; + case DBVT_BLOB: + //TODO + CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); + break; + case DBVT_WCHAR: + //TODO + CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); + break; + } + id += " contact_id "; + ZeroMemory(&dbv, sizeof(dbv)); + ZeroMemory(&dbcgs, sizeof(dbcgs)); + dbcgs.pValue = &dbv; + dbcgs.szModule = proto; + dbcgs.szSetting = uid; + CallService(MS_DB_CONTACT_GETSETTING, (WPARAM)hContact, (LPARAM)&dbcgs); + switch(dbcgs.pValue->type) + { + case DBVT_DELETED: + continue; + break; + case DBVT_BYTE: + { + char _id[64]; + mir_snprintf(_id, 63, "%d", dbcgs.pValue->bVal); + id += _id; + } + break; + case DBVT_WORD: + { + char _id[64]; + mir_snprintf(_id, 63, "%d", dbcgs.pValue->wVal); + id += _id; + } + break; + case DBVT_DWORD: + { + char _id[64]; + mir_snprintf(_id, 63, "%d", dbcgs.pValue->dVal); + id += _id; + } + break; + case DBVT_ASCIIZ: + { + id += dbcgs.pValue->pszVal; + CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); + } + break; + case DBVT_UTF8: + { + char *tmp = mir_utf8decodeA(dbcgs.pValue->pszVal); + if(tmp[0]) + id += tmp; + mir_free(tmp); + CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); + } + break; + case DBVT_BLOB: + //TODO + CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); + break; + case DBVT_WCHAR: + //TODO + CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); + break; + } + std::string::size_type p1 = key.find("-----BEGIN PGP PUBLIC KEY BLOCK-----"); + if(p1 == std::string::npos) + continue; + p1 += strlen("-----BEGIN PGP PUBLIC KEY BLOCK-----"); + p1 ++; + id += '\n'; + key.insert(p1, id); + file<<key; + file<<std::endl; + exported_keys++; + } + if(file.is_open()) + file.close(); + char msg[512]; + mir_snprintf(msg, 511, "we have succesfully exported %d keys", exported_keys); + MessageBoxA(NULL, msg, Translate("Keys export result"), MB_OK); + return 0; +} + +int ImportGpGKeys(WPARAM w, LPARAM l) +{ + TCHAR *p = GetFilePath(_T("Choose file to import keys from"), _T("*"), _T("Any file")); + if(!p || !p[0]) + { + delete [] p; + //TODO: handle error + return 1; + } + char *path = mir_t2a(p); + delete [] p; + std::ifstream file; + file.open(path, std::ios::in); + mir_free(path); + if(!file.is_open()) + return 1; //TODO: handle error + PROTOACCOUNT **accs; + int acc_count = 0, processed_keys = 0; + ProtoEnumAccounts(&acc_count, &accs); + char line[256]; + file.getline(line, 255); + if(!strstr(line, "-----BEGIN PGP PUBLIC KEY BLOCK-----")) + return 1; //TODO: handle error + std::string key, login, contact_id; + key += line; + key += '\n'; + while(file.is_open() && !file.eof()) + { + file.getline(line, 255); + key += line; + key += '\n'; + if(strstr(line, "-----END PGP PUBLIC KEY BLOCK-----")) + { //TODO: parse key + std::string::size_type p1 = 0, p2 = 0; + p1 = key.find("Comment: login "); + p1 += strlen("Comment: login "); + p2 = key.find(" contact_id "); + login = key.substr(p1, p2-p1); + p2 += strlen(" contact_id "); + p1 = key.find("\n", p2); + contact_id = key.substr(p2, p1-p2); + p1 = key.find("Comment: login "); + p2 = key.find("\n", p1); + p2++; + key.erase(p1, p2-p1); + std::string acc; + for(int i = 0; i < acc_count; i++) + { + if(acc.length()) + break; + const char * uid = (const char*)CallProtoService(accs[i]->szModuleName, PS_GETCAPS, (WPARAM)PFLAG_UNIQUEIDSETTING, 0); + DBVARIANT dbv = {0}; + DBCONTACTGETSETTING dbcgs = {0}; + dbcgs.pValue = &dbv; + dbcgs.szModule = accs[i]->szModuleName; + dbcgs.szSetting = uid; + CallService(MS_DB_CONTACT_GETSETTING, 0, (LPARAM)&dbcgs); + std::string id; + switch(dbcgs.pValue->type) + { + case DBVT_DELETED: + continue; + break; + case DBVT_BYTE: + { + char _id[64]; + mir_snprintf(_id, 63, "%d", dbcgs.pValue->bVal); + id += _id; + if(id == login) + acc = accs[i]->szModuleName; + } + break; + case DBVT_WORD: + { + char _id[64]; + mir_snprintf(_id, 63, "%d", dbcgs.pValue->wVal); + id += _id; + if(id == login) + acc = accs[i]->szModuleName; + } + break; + case DBVT_DWORD: + { + char _id[64]; + mir_snprintf(_id, 63, "%d", dbcgs.pValue->dVal); + id += _id; + if(id == login) + acc = accs[i]->szModuleName; + } + break; + case DBVT_ASCIIZ: + { + id += dbcgs.pValue->pszVal; + CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); + if(id == login) + acc = accs[i]->szModuleName; + } + break; + case DBVT_UTF8: + { + char *tmp = mir_utf8decodeA(dbcgs.pValue->pszVal); + if(tmp[0]) + id += tmp; + mir_free(tmp); + CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); + if(id == login) + acc = accs[i]->szModuleName; + } + break; + case DBVT_BLOB: + //TODO + CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); + break; + case DBVT_WCHAR: + //TODO + CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); + break; + } + } + if(acc.length()) + { + const char * uid = (const char*)CallProtoService(acc.c_str(), PS_GETCAPS, (WPARAM)PFLAG_UNIQUEIDSETTING, 0); + for(HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, (LPARAM)acc.c_str()); hContact; hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, (LPARAM)acc.c_str())) + { + DBVARIANT dbv = {0}; + DBCONTACTGETSETTING dbcgs = {0}; + dbcgs.pValue = &dbv; + dbcgs.szModule = acc.c_str(); + dbcgs.szSetting = uid; + CallService(MS_DB_CONTACT_GETSETTING, (WPARAM)hContact, (LPARAM)&dbcgs); + std::string id; + bool found = false; + switch(dbcgs.pValue->type) + { + case DBVT_DELETED: + continue; + break; + case DBVT_BYTE: + { + char _id[64]; + mir_snprintf(_id, 63, "%d", dbcgs.pValue->bVal); + id += _id; + if(id == contact_id) + found = true; + } + break; + case DBVT_WORD: + { + char _id[64]; + mir_snprintf(_id, 63, "%d", dbcgs.pValue->wVal); + id += _id; + if(id == contact_id) + found = true; + } + break; + case DBVT_DWORD: + { + char _id[64]; + mir_snprintf(_id, 63, "%d", dbcgs.pValue->dVal); + id += _id; + if(id == contact_id) + found = true; + } + break; + case DBVT_ASCIIZ: + { + id += dbcgs.pValue->pszVal; + CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); + if(id == contact_id) + found = true; + } + break; + case DBVT_UTF8: + { + char *tmp = mir_utf8decodeA(dbcgs.pValue->pszVal); + if(tmp[0]) + id += tmp; + mir_free(tmp); + CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); + if(id == contact_id) + found = true; + } + break; + case DBVT_BLOB: + //TODO + CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); + break; + case DBVT_WCHAR: + //TODO + CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); + break; + } + if(found) + { + wstring cmd; + TCHAR tmp2[MAX_PATH] = {0}; + TCHAR *ptmp; + string output; + DWORD exitcode; + { + HANDLE hcnt = hContact; + ptmp = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T("")); + _tcscpy(tmp2, ptmp); + mir_free(ptmp); + _tcscat(tmp2, _T("\\")); + _tcscat(tmp2, _T("temporary_exported.asc")); + DeleteFile(tmp2); + wfstream f(tmp2, std::ios::out); + f<<toUTF16(key).c_str(); + f.close(); + cmd += _T(" --batch "); + cmd += _T(" --import \""); + cmd += tmp2; + cmd += _T("\""); + } + gpg_execution_params params; + pxResult result; + params.cmd = &cmd; + params.useless = ""; + params.out = &output; + params.code = &exitcode; + params.result = &result; + boost::thread gpg_thread(boost::bind(&pxEexcute_thread, ¶ms)); + if(!gpg_thread.timed_join(boost::posix_time::seconds(10))) + { + gpg_thread.~thread(); + TerminateProcess(params.hProcess, 1); + params.hProcess = NULL; + debuglog<<time_str()<<": GPG execution timed out, aborted\n"; + break; + } + if(result == pxNotFound) + break; + if(result == pxSuccess) + processed_keys++; + { + if(output.find("already in secret keyring") != string::npos) + { + MessageBox(0, _T("Key already in scret key ring."), _T("Info"), MB_OK); + DeleteFile(tmp2); + break; + } + char *tmp2; + string::size_type s = output.find("gpg: key ") + strlen("gpg: key "); + string::size_type s2 = output.find(":", s); + tmp2 = new char [output.substr(s,s2-s).length()+1]; + strcpy(tmp2, output.substr(s,s2-s).c_str()); + mir_utf8decode(tmp2, 0); + DBWriteContactSettingString(hContact, szGPGModuleName, "KeyID", tmp2); + mir_free(tmp2); + s = output.find("“", s2); + if(s == string::npos) + { + s = output.find("\"", s2); + s += 1; + } + else + s += 3; + if((s2 = output.find("(", s)) == string::npos) + s2 = output.find("<", s); + else if(s2 > output.find("<", s)) + s2 = output.find("<", s); + if(s2 != string::npos) + { + tmp2 = new char [output.substr(s,s2-s-1).length()+1]; + strcpy(tmp2, output.substr(s,s2-s-1).c_str()); + mir_utf8decode(tmp2, 0); + if(hContact) + { + DBWriteContactSettingString(hContact, szGPGModuleName, "KeyMainName", output.substr(s,s2-s-1).c_str()); + } + mir_free(tmp2); + if((s = output.find(")", s2)) == string::npos) + s = output.find(">", s2); + else if(s > output.find(">", s2)) + s = output.find(">", s2); + s2++; + if(output[s] == ')') + { + tmp2 = new char [output.substr(s2,s-s2).length()+1]; + strcpy(tmp2, output.substr(s2,s-s2).c_str()); + mir_utf8decode(tmp2, 0); + if(hContact) + DBWriteContactSettingString(hContact, szGPGModuleName, "KeyComment", output.substr(s2,s-s2).c_str()); + mir_free(tmp2); + s+=3; + s2 = output.find(">", s); + tmp2 = new char [output.substr(s,s2-s).length()+1]; + strcpy(tmp2, output.substr(s,s2-s).c_str()); + mir_utf8decode(tmp2, 0); + if(hContact) + DBWriteContactSettingString(hContact, szGPGModuleName, "KeyMainEmail", output.substr(s,s2-s).c_str()); + mir_free(tmp2); + } + else + { + tmp2 = new char [output.substr(s2,s-s2).length()+1]; + strcpy(tmp2, output.substr(s2,s-s2).c_str()); + mir_utf8decode(tmp2, 0); + if(hContact) + DBWriteContactSettingString(hContact, szGPGModuleName, "KeyMainEmail", output.substr(s2,s-s2).c_str()); + mir_free(tmp2); + } + } + DBWriteContactSettingByte(hContact, szGPGModuleName, "GPGEncryption", 1); + DBWriteContactSettingTString(hContact, szGPGModuleName, "GPGPubKey", toUTF16(key).c_str()); + } + DeleteFile(tmp2); + break; + } + } + } + key.clear(); + } + } + if(file.is_open()) + file.close(); + char msg[512]; + mir_snprintf(msg, 511, "we have succesfully processed %d keys", processed_keys); + MessageBoxA(NULL, msg, Translate("Keys import result"), MB_OK); + return 0; +}
\ No newline at end of file |