#include "stdafx.h" HANDLE CToxProto::hProfileFolderPath; TCHAR* CToxProto::GetToxProfilePath() { return GetToxProfilePath(m_tszUserName); } TCHAR* CToxProto::GetToxProfilePath(const TCHAR *accountName) { TCHAR *profilePath = (TCHAR*)mir_calloc(MAX_PATH * sizeof(TCHAR) + 1); TCHAR profileRootPath[MAX_PATH]; FoldersGetCustomPathT(hProfileFolderPath, profileRootPath, _countof(profileRootPath), VARST(_T("%miranda_userdata%"))); mir_sntprintf(profilePath, MAX_PATH, _T("%s\\%s.tox"), profileRootPath, accountName); return profilePath; } bool CToxProto::LoadToxProfile(Tox_Options *options) { logger->Log(__FUNCTION__": loading tox profile"); mir_cslock locker(profileLock); ptrT profilePath(GetToxProfilePath()); if (!IsFileExists(profilePath)) return false; FILE *profile = _tfopen(profilePath, _T("rb")); if (profile == NULL) { ShowNotification(TranslateT("Unable to open Tox profile"), MB_ICONERROR); logger->Log(__FUNCTION__": failed to open tox profile"); return false; } fseek(profile, 0, SEEK_END); long size = ftell(profile); rewind(profile); if (size < 0) { fclose(profile); return false; } if (size == 0) { fclose(profile); return true; } uint8_t *data = (uint8_t*)mir_calloc(size); if (fread((char*)data, sizeof(char), size, profile) != (size_t)size) { fclose(profile); ShowNotification(TranslateT("Unable to read Tox profile"), MB_ICONERROR); logger->Log(__FUNCTION__": failed to read tox profile"); mir_free(data); return false; } fclose(profile); if (tox_is_data_encrypted(data)) { pass_ptrA password(mir_utf8encodeW(pass_ptrT(getTStringA("Password")))); if (password == NULL || mir_strlen(password) == 0) { CToxPasswordEditor passwordEditor(this); if (!passwordEditor.DoModal()) { mir_free(data); return false; } } uint8_t *encryptedData = (uint8_t*)mir_calloc(size - TOX_PASS_ENCRYPTION_EXTRA_LENGTH); TOX_ERR_DECRYPTION coreDecryptError; if (!tox_pass_decrypt(data, size, (uint8_t*)(char*)password, mir_strlen(password), encryptedData, &coreDecryptError)) { ShowNotification(TranslateT("Unable to decrypt Tox profile"), MB_ICONERROR); logger->Log(__FUNCTION__": failed to decrypt tox profile (%d)", coreDecryptError); mir_free(data); return false; } mir_free(data); data = encryptedData; size -= TOX_PASS_ENCRYPTION_EXTRA_LENGTH; } if (data) { options->savedata_data = data; options->savedata_length = size; options->savedata_type = TOX_SAVEDATA_TYPE_TOX_SAVE; return true; } return false; } void CToxProto::SaveToxProfile(CToxThread *toxThread) { mir_cslock locker(profileLock); if (!toxThread) return; size_t size = tox_get_savedata_size(toxThread->Tox()); uint8_t *data = (uint8_t*)mir_calloc(size + TOX_PASS_ENCRYPTION_EXTRA_LENGTH); tox_get_savedata(toxThread->Tox(), data); pass_ptrA password(mir_utf8encodeW(pass_ptrT(getTStringA("Password")))); if (password && mir_strlen(password)) { TOX_ERR_ENCRYPTION coreEncryptError; if (!tox_pass_encrypt(data, size, (uint8_t*)(char*)password, mir_strlen(password), data, &coreEncryptError)) { logger->Log(__FUNCTION__": failed to encrypt tox profile"); mir_free(data); return; } size += TOX_PASS_ENCRYPTION_EXTRA_LENGTH; } ptrT profilePath(GetToxProfilePath()); FILE *profile = _tfopen(profilePath, _T("wb")); if (profile == NULL) { logger->Log(__FUNCTION__": failed to open tox profile"); mir_free(data); return; } size_t written = fwrite(data, sizeof(char), size, profile); if (size != written) { logger->Log(__FUNCTION__": failed to write tox profile"); } fclose(profile); mir_free(data); } INT_PTR CToxProto::OnCopyToxID(WPARAM, LPARAM) { ptrA address(getStringA(TOX_SETTINGS_ID)); size_t length = mir_strlen(address) + 1; if (OpenClipboard(NULL)) { EmptyClipboard(); HGLOBAL hMemory = GlobalAlloc(GMEM_FIXED, length); memcpy(GlobalLock(hMemory), address, length); GlobalUnlock(hMemory); SetClipboardData(CF_TEXT, hMemory); CloseClipboard(); } return 0; } CToxPasswordEditor::CToxPasswordEditor(CToxProto *proto) : CToxDlgBase(proto, IDD_PASSWORD, false), ok(this, IDOK), password(this, IDC_PASSWORD), savePermanently(this, IDC_SAVEPERMANENTLY) { ok.OnClick = Callback(this, &CToxPasswordEditor::OnOk); } void CToxPasswordEditor::OnOk(CCtrlButton*) { pass_ptrT tszPassword(password.GetText()); if (savePermanently.Enabled()) m_proto->setTString("Password", tszPassword); EndDialog(m_hwnd, 1); }