From f3088d36fec8c063462d9dc16734ec0c11813668 Mon Sep 17 00:00:00 2001 From: Kirill Volinsky Date: Sat, 23 Jun 2012 13:52:34 +0000 Subject: Import_SA: renamed to .cpp git-svn-id: http://svn.miranda-ng.org/main/trunk@553 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Dbx_mmap_SA/Import_SA/ICQserver.c | 73 -- plugins/Dbx_mmap_SA/Import_SA/ICQserver.cpp | 73 ++ plugins/Dbx_mmap_SA/Import_SA/encryption.c | 310 ----- plugins/Dbx_mmap_SA/Import_SA/encryption.cpp | 310 +++++ plugins/Dbx_mmap_SA/Import_SA/main.c | 550 -------- plugins/Dbx_mmap_SA/Import_SA/main.cpp | 550 ++++++++ plugins/Dbx_mmap_SA/Import_SA/mirabilis.c | 1492 --------------------- plugins/Dbx_mmap_SA/Import_SA/mirabilis.cpp | 1492 +++++++++++++++++++++ plugins/Dbx_mmap_SA/Import_SA/miranda.c | 1502 ---------------------- plugins/Dbx_mmap_SA/Import_SA/miranda.cpp | 1502 ++++++++++++++++++++++ plugins/Dbx_mmap_SA/Import_SA/mirandahistory.c | 208 --- plugins/Dbx_mmap_SA/Import_SA/mirandahistory.cpp | 208 +++ plugins/Dbx_mmap_SA/Import_SA/progress.c | 100 -- plugins/Dbx_mmap_SA/Import_SA/progress.cpp | 100 ++ plugins/Dbx_mmap_SA/Import_SA/wizard.c | 215 ---- plugins/Dbx_mmap_SA/Import_SA/wizard.cpp | 215 ++++ 16 files changed, 4450 insertions(+), 4450 deletions(-) delete mode 100644 plugins/Dbx_mmap_SA/Import_SA/ICQserver.c create mode 100644 plugins/Dbx_mmap_SA/Import_SA/ICQserver.cpp delete mode 100644 plugins/Dbx_mmap_SA/Import_SA/encryption.c create mode 100644 plugins/Dbx_mmap_SA/Import_SA/encryption.cpp delete mode 100644 plugins/Dbx_mmap_SA/Import_SA/main.c create mode 100644 plugins/Dbx_mmap_SA/Import_SA/main.cpp delete mode 100644 plugins/Dbx_mmap_SA/Import_SA/mirabilis.c create mode 100644 plugins/Dbx_mmap_SA/Import_SA/mirabilis.cpp delete mode 100644 plugins/Dbx_mmap_SA/Import_SA/miranda.c create mode 100644 plugins/Dbx_mmap_SA/Import_SA/miranda.cpp delete mode 100644 plugins/Dbx_mmap_SA/Import_SA/mirandahistory.c create mode 100644 plugins/Dbx_mmap_SA/Import_SA/mirandahistory.cpp delete mode 100644 plugins/Dbx_mmap_SA/Import_SA/progress.c create mode 100644 plugins/Dbx_mmap_SA/Import_SA/progress.cpp delete mode 100644 plugins/Dbx_mmap_SA/Import_SA/wizard.c create mode 100644 plugins/Dbx_mmap_SA/Import_SA/wizard.cpp (limited to 'plugins') diff --git a/plugins/Dbx_mmap_SA/Import_SA/ICQserver.c b/plugins/Dbx_mmap_SA/Import_SA/ICQserver.c deleted file mode 100644 index 62666c7531..0000000000 --- a/plugins/Dbx_mmap_SA/Import_SA/ICQserver.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - -Import plugin for Miranda IM - -Copyright (C) 2001-2005 Martin Öberg, Richard Hughes, Roland Rabien & Tristan Van de Vreede - -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. - -*/ - -// ============== -// == INCLUDES == -// ============== - -#include "import.h" - -#include "ICQserver.h" - -// ==================== -// ==================== -// == IMPLEMENTATION == -// ==================== -// ==================== - -BOOL CALLBACK ICQserverPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam) -{ - switch(message) { - case WM_INITDIALOG: - SendMessage(GetParent(hdlg),WIZM_DISABLEBUTTON,0,0); - SendMessage(GetParent(hdlg),WIZM_ENABLEBUTTON,1,0); - SendMessage(GetParent(hdlg),WIZM_DISABLEBUTTON,2,0); - TranslateDialogDefault(hdlg); - ICQserverImport(); - return TRUE; - - case WM_COMMAND: - switch(LOWORD(wParam)) { - case IDOK: - PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_FINISHED,(LPARAM)FinishedPageProc); - break; - case IDCANCEL: - PostMessage(GetParent(hdlg),WM_CLOSE,0,0); - break; - } - break; - } - return FALSE; -} - -static void ICQserverImport() -{ - // Clear last update stamp - DBDeleteContactSetting(NULL, szICQModuleName[ iICQAccount ], "SrvLastUpdate"); - DBDeleteContactSetting(NULL, szICQModuleName[ iICQAccount ], "SrvRecordCount"); - - // Enable contacts downloading - DBWriteContactSettingByte(NULL, szICQModuleName[ iICQAccount ], "UseServerCList", 1); - DBWriteContactSettingByte(NULL, szICQModuleName[ iICQAccount ], "AddServerNew", 1); - DBWriteContactSettingByte(NULL, szICQModuleName[ iICQAccount ], "UseServerNicks", 1); - DBWriteContactSettingByte(NULL, szICQModuleName[ iICQAccount ], "ServerAddRemove", 1); -} diff --git a/plugins/Dbx_mmap_SA/Import_SA/ICQserver.cpp b/plugins/Dbx_mmap_SA/Import_SA/ICQserver.cpp new file mode 100644 index 0000000000..62666c7531 --- /dev/null +++ b/plugins/Dbx_mmap_SA/Import_SA/ICQserver.cpp @@ -0,0 +1,73 @@ +/* + +Import plugin for Miranda IM + +Copyright (C) 2001-2005 Martin Öberg, Richard Hughes, Roland Rabien & Tristan Van de Vreede + +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. + +*/ + +// ============== +// == INCLUDES == +// ============== + +#include "import.h" + +#include "ICQserver.h" + +// ==================== +// ==================== +// == IMPLEMENTATION == +// ==================== +// ==================== + +BOOL CALLBACK ICQserverPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam) +{ + switch(message) { + case WM_INITDIALOG: + SendMessage(GetParent(hdlg),WIZM_DISABLEBUTTON,0,0); + SendMessage(GetParent(hdlg),WIZM_ENABLEBUTTON,1,0); + SendMessage(GetParent(hdlg),WIZM_DISABLEBUTTON,2,0); + TranslateDialogDefault(hdlg); + ICQserverImport(); + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDOK: + PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_FINISHED,(LPARAM)FinishedPageProc); + break; + case IDCANCEL: + PostMessage(GetParent(hdlg),WM_CLOSE,0,0); + break; + } + break; + } + return FALSE; +} + +static void ICQserverImport() +{ + // Clear last update stamp + DBDeleteContactSetting(NULL, szICQModuleName[ iICQAccount ], "SrvLastUpdate"); + DBDeleteContactSetting(NULL, szICQModuleName[ iICQAccount ], "SrvRecordCount"); + + // Enable contacts downloading + DBWriteContactSettingByte(NULL, szICQModuleName[ iICQAccount ], "UseServerCList", 1); + DBWriteContactSettingByte(NULL, szICQModuleName[ iICQAccount ], "AddServerNew", 1); + DBWriteContactSettingByte(NULL, szICQModuleName[ iICQAccount ], "UseServerNicks", 1); + DBWriteContactSettingByte(NULL, szICQModuleName[ iICQAccount ], "ServerAddRemove", 1); +} diff --git a/plugins/Dbx_mmap_SA/Import_SA/encryption.c b/plugins/Dbx_mmap_SA/Import_SA/encryption.c deleted file mode 100644 index ede73c006a..0000000000 --- a/plugins/Dbx_mmap_SA/Import_SA/encryption.c +++ /dev/null @@ -1,310 +0,0 @@ -// (C) Artem Shpynov aka FYR and Igonin Vitaliy aka chaos.persei, 2007 - 2008 - -#include "import.h" - -typedef struct{ - void* (__stdcall *GenerateKey)(char* pwd); - void (__stdcall *FreeKey)(void* key); - void (__stdcall *EncryptMem)(BYTE* data, int size, void* key); - void (__stdcall *DecryptMem)(BYTE* data, int size, void* key); - - char* Name; - char* Info; - char* Author; - char* Site; - char* Email; - - DWORD Version; - - WORD uid; -} Cryptor; - -typedef struct{ - char dllname[255]; - HMODULE hLib; - Cryptor* cryptor; -} CryptoModule; - -BOOL CALLBACK DlgStdInProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); - -char encryptKey[255]; -size_t encryptKeyLength; - -int wrongPass = 0; -void* key; - -Cryptor* CryptoEngine = NULL; - -int ModulesCount = 0; -CryptoModule* Modules[100]; - - -void zero_fill(BYTE * pBuf, size_t bufSize) -{ - size_t i; - for(i = 0; i < bufSize; i++) - pBuf[i] = 0; -} - -void InitSecurity() -{ - HMODULE hLib; - WIN32_FIND_DATAA fd; - HANDLE hFile; - - Cryptor* (__stdcall *GetCryptor)(); - - { - TCHAR szMirandaDir[MAX_PATH]; - TCHAR *str2; - - szMirandaDir[ 0 ] = 0; - - GetModuleFileName(NULL,szMirandaDir,SIZEOF(szMirandaDir)); - str2 = _tcsrchr(szMirandaDir,'\\'); - if ( str2 != NULL ) - *str2=0; - _tchdir(szMirandaDir); - } - - hFile = FindFirstFileA(".\\plugins\\cryptors\\*.dll", &fd); - - AddMessage(LPGEN("Scanning cryptors directory")); - - ModulesCount = 0; - while (hFile != INVALID_HANDLE_VALUE) - { - char tmp[MAX_PATH], buf[255]; - strcpy(tmp, ".\\plugins\\cryptors\\"); - strcat(tmp, fd.cFileName); - - hLib = LoadLibraryA(tmp); - if(hLib){ - GetCryptor = (Cryptor* (__stdcall *)()) GetProcAddress(hLib, "GetCryptor"); - if(GetCryptor){ - //TCHAR Name[100], Version[100], DllName[100]; - - - Modules[ModulesCount] = (CryptoModule*) malloc(sizeof(CryptoModule)); - Modules[ModulesCount]->cryptor = GetCryptor(); - strcpy(Modules[ModulesCount]->dllname, fd.cFileName); - Modules[ModulesCount]->hLib = hLib; - - _snprintf(buf,SIZEOF(buf),"%d.%d.%d.%d", HIBYTE(HIWORD(Modules[ModulesCount]->cryptor->Version)), LOBYTE(HIWORD(Modules[ModulesCount]->cryptor->Version)), HIBYTE(LOWORD(Modules[ModulesCount]->cryptor->Version)), LOBYTE(LOWORD(Modules[ModulesCount]->cryptor->Version))); - // Unsane: none -/* - - mbstowcs(Name, Modules[ModulesCount]->cryptor->Name, 100); - mbstowcs(Version, buf, 100); - mbstowcs(DllName, Modules[ModulesCount]->dllname, 100); - -*/ - AddMessage(LPGEN("Cryptor loaded: %s [%s] (%s)"), Modules[ModulesCount]->cryptor->Name, buf, Modules[ModulesCount]->dllname); - - ModulesCount++; - }else{ - FreeLibrary(hLib); - } - } - if(ModulesCount >= 100) break; - if (!FindNextFileA(hFile, &fd)) break; - } - - AddMessage(LPGEN("%d crypto modules loaded"), ModulesCount); -} - -void UnloadSecurity() -{ - int i; - - if(CryptoEngine) CryptoEngine->FreeKey(key); - - for(i = 0; i < ModulesCount; i++) - { - FreeLibrary(Modules[i]->hLib); - free(Modules[i]); - } -} - -void EncoderInit() -{ - encryptKey[encryptKeyLength] = 0; - key = CryptoEngine->GenerateKey(encryptKey); -} - -void EncodeCopyMemory(BYTE * dst, void * src, size_t size ) -{ - memcpy(dst, src, size); - CryptoEngine->EncryptMem(dst, (int)size, key); -} - -void DecodeCopyMemory(BYTE * dst, void * src, size_t size ) -{ - memcpy(dst, src, size); - CryptoEngine->DecryptMem(dst, (int)size, key); -} - - -void EncodeMemory(BYTE * mem, size_t size) -{ - CryptoEngine->EncryptMem(mem, (int)size, key); -} - -void DecodeMemory(BYTE * mem, size_t size) -{ - CryptoEngine->DecryptMem(mem, (int)size, key); -} - -int bCheckingPass = 0; - -int CheckPassword(WORD checkWord, WORD cryptorUID, TCHAR * szDBName) -{ - WORD ver; - int res; - - if(bCheckingPass) return 0; - bCheckingPass = 1; - - { - int i; - int Found = 0; - for(i = 0; i < ModulesCount; i++) { - if(cryptorUID == Modules[i]->cryptor->uid){ - CryptoEngine = Modules[i]->cryptor; - Found = 1; - break; - } - } - if (!Found){ - AddMessage(LPGEN("Sorry, but your database encrypted with unknown module"), MB_OK); - bCheckingPass = 0; - return 0; - } - } - - { - //wchar_t Name[100], Author[100]; - - // Unsane: none - AddMessage(LPGEN("Database encrypted with %s by %s"), CryptoEngine->Name, CryptoEngine->Author); - } - - while(1){ - res = DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_LOGIN), NULL, (DLGPROC)DlgStdInProc, (LPARAM)szDBName); - if(res == IDCANCEL) - { - wrongPass = 0; - bCheckingPass = 0; - return 0; - } - if(encryptKeyLength < 1) continue; - EncoderInit(); - DecodeCopyMemory((BYTE*)&ver, &checkWord, sizeof(checkWord)); - if(ver == 0x5195) - { - wrongPass = 0; - bCheckingPass = 0; - return 1; - } - wrongPass++; - } - - bCheckingPass = 0; -} - - -UINT oldLangID = 0; -void LanguageChanged(HWND hDlg) -{ - UINT LangID = (UINT)GetKeyboardLayout(0); - char Lang[3] = {0}; - if (LangID != oldLangID) - { - oldLangID = LangID; - GetLocaleInfoA(MAKELCID((LangID & 0xffffffff), SORT_DEFAULT), LOCALE_SABBREVLANGNAME, Lang, 2); - SetDlgItemTextA(hDlg, IDC_LANG, Lang); - } -} - -BOOL CALLBACK DlgStdInProc(HWND hDlg, UINT uMsg,WPARAM wParam,LPARAM lParam) -{ - HICON hIcon = 0; - TCHAR tszHeaderTxt[256]; - switch(uMsg) - { - case WM_INITDIALOG: - { - HWND hwndCtrl; - TranslateDialogDefault(hDlg); - - hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_PASS)); - SendMessage(GetDlgItem(hDlg, IDC_HEADERBAR), WM_SETICON, 0, (LPARAM)hIcon); - - if (!wrongPass) - { - mir_sntprintf(tszHeaderTxt, SIZEOF(tszHeaderTxt), _T("%s\n%s"), TranslateT("Please type in your password for"), lParam); - SetWindowText(GetDlgItem(hDlg, IDC_HEADERBAR), tszHeaderTxt); - } - else - { - if (wrongPass > 2) - { - hwndCtrl = GetDlgItem(hDlg, IDC_USERPASS); - EnableWindow(hwndCtrl, FALSE); - hwndCtrl = GetDlgItem(hDlg, IDOK); - EnableWindow(hwndCtrl, FALSE); - - SetWindowText(GetDlgItem(hDlg, IDC_HEADERBAR), TranslateT("Too many errors!")); - } - else - SetWindowText(GetDlgItem(hDlg, IDC_HEADERBAR), TranslateT("Password is not correct!")); - } - oldLangID = 0; - SetTimer(hDlg,1,200,NULL); - LanguageChanged(hDlg); - return TRUE; - } - - case WM_CTLCOLORSTATIC: - { - if ((HWND)lParam == GetDlgItem(hDlg, IDC_LANG)) - { - SetTextColor((HDC)wParam, GetSysColor(COLOR_HIGHLIGHTTEXT)); - SetBkMode((HDC)wParam, TRANSPARENT); - return (BOOL)GetSysColorBrush(COLOR_HIGHLIGHT); - } - - return FALSE; - } - - case WM_COMMAND: - { - UINT uid = LOWORD(wParam); - - if(uid == IDOK){ - if (!GetWindowLongPtr(hDlg,GWLP_USERDATA)) - { - encryptKeyLength = GetDlgItemTextA(hDlg, IDC_USERPASS, encryptKey, 254); - EndDialog(hDlg,IDOK); - }else{ - - } - }else if(uid == IDCANCEL){ - EndDialog(hDlg,IDCANCEL); - } - } - case WM_TIMER: - { - LanguageChanged(hDlg); - return FALSE; - } - case WM_DESTROY: - { - KillTimer(hDlg, 1); - DestroyIcon(hIcon); - return FALSE; - } - } - - return FALSE; -} diff --git a/plugins/Dbx_mmap_SA/Import_SA/encryption.cpp b/plugins/Dbx_mmap_SA/Import_SA/encryption.cpp new file mode 100644 index 0000000000..ede73c006a --- /dev/null +++ b/plugins/Dbx_mmap_SA/Import_SA/encryption.cpp @@ -0,0 +1,310 @@ +// (C) Artem Shpynov aka FYR and Igonin Vitaliy aka chaos.persei, 2007 - 2008 + +#include "import.h" + +typedef struct{ + void* (__stdcall *GenerateKey)(char* pwd); + void (__stdcall *FreeKey)(void* key); + void (__stdcall *EncryptMem)(BYTE* data, int size, void* key); + void (__stdcall *DecryptMem)(BYTE* data, int size, void* key); + + char* Name; + char* Info; + char* Author; + char* Site; + char* Email; + + DWORD Version; + + WORD uid; +} Cryptor; + +typedef struct{ + char dllname[255]; + HMODULE hLib; + Cryptor* cryptor; +} CryptoModule; + +BOOL CALLBACK DlgStdInProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); + +char encryptKey[255]; +size_t encryptKeyLength; + +int wrongPass = 0; +void* key; + +Cryptor* CryptoEngine = NULL; + +int ModulesCount = 0; +CryptoModule* Modules[100]; + + +void zero_fill(BYTE * pBuf, size_t bufSize) +{ + size_t i; + for(i = 0; i < bufSize; i++) + pBuf[i] = 0; +} + +void InitSecurity() +{ + HMODULE hLib; + WIN32_FIND_DATAA fd; + HANDLE hFile; + + Cryptor* (__stdcall *GetCryptor)(); + + { + TCHAR szMirandaDir[MAX_PATH]; + TCHAR *str2; + + szMirandaDir[ 0 ] = 0; + + GetModuleFileName(NULL,szMirandaDir,SIZEOF(szMirandaDir)); + str2 = _tcsrchr(szMirandaDir,'\\'); + if ( str2 != NULL ) + *str2=0; + _tchdir(szMirandaDir); + } + + hFile = FindFirstFileA(".\\plugins\\cryptors\\*.dll", &fd); + + AddMessage(LPGEN("Scanning cryptors directory")); + + ModulesCount = 0; + while (hFile != INVALID_HANDLE_VALUE) + { + char tmp[MAX_PATH], buf[255]; + strcpy(tmp, ".\\plugins\\cryptors\\"); + strcat(tmp, fd.cFileName); + + hLib = LoadLibraryA(tmp); + if(hLib){ + GetCryptor = (Cryptor* (__stdcall *)()) GetProcAddress(hLib, "GetCryptor"); + if(GetCryptor){ + //TCHAR Name[100], Version[100], DllName[100]; + + + Modules[ModulesCount] = (CryptoModule*) malloc(sizeof(CryptoModule)); + Modules[ModulesCount]->cryptor = GetCryptor(); + strcpy(Modules[ModulesCount]->dllname, fd.cFileName); + Modules[ModulesCount]->hLib = hLib; + + _snprintf(buf,SIZEOF(buf),"%d.%d.%d.%d", HIBYTE(HIWORD(Modules[ModulesCount]->cryptor->Version)), LOBYTE(HIWORD(Modules[ModulesCount]->cryptor->Version)), HIBYTE(LOWORD(Modules[ModulesCount]->cryptor->Version)), LOBYTE(LOWORD(Modules[ModulesCount]->cryptor->Version))); + // Unsane: none +/* + + mbstowcs(Name, Modules[ModulesCount]->cryptor->Name, 100); + mbstowcs(Version, buf, 100); + mbstowcs(DllName, Modules[ModulesCount]->dllname, 100); + +*/ + AddMessage(LPGEN("Cryptor loaded: %s [%s] (%s)"), Modules[ModulesCount]->cryptor->Name, buf, Modules[ModulesCount]->dllname); + + ModulesCount++; + }else{ + FreeLibrary(hLib); + } + } + if(ModulesCount >= 100) break; + if (!FindNextFileA(hFile, &fd)) break; + } + + AddMessage(LPGEN("%d crypto modules loaded"), ModulesCount); +} + +void UnloadSecurity() +{ + int i; + + if(CryptoEngine) CryptoEngine->FreeKey(key); + + for(i = 0; i < ModulesCount; i++) + { + FreeLibrary(Modules[i]->hLib); + free(Modules[i]); + } +} + +void EncoderInit() +{ + encryptKey[encryptKeyLength] = 0; + key = CryptoEngine->GenerateKey(encryptKey); +} + +void EncodeCopyMemory(BYTE * dst, void * src, size_t size ) +{ + memcpy(dst, src, size); + CryptoEngine->EncryptMem(dst, (int)size, key); +} + +void DecodeCopyMemory(BYTE * dst, void * src, size_t size ) +{ + memcpy(dst, src, size); + CryptoEngine->DecryptMem(dst, (int)size, key); +} + + +void EncodeMemory(BYTE * mem, size_t size) +{ + CryptoEngine->EncryptMem(mem, (int)size, key); +} + +void DecodeMemory(BYTE * mem, size_t size) +{ + CryptoEngine->DecryptMem(mem, (int)size, key); +} + +int bCheckingPass = 0; + +int CheckPassword(WORD checkWord, WORD cryptorUID, TCHAR * szDBName) +{ + WORD ver; + int res; + + if(bCheckingPass) return 0; + bCheckingPass = 1; + + { + int i; + int Found = 0; + for(i = 0; i < ModulesCount; i++) { + if(cryptorUID == Modules[i]->cryptor->uid){ + CryptoEngine = Modules[i]->cryptor; + Found = 1; + break; + } + } + if (!Found){ + AddMessage(LPGEN("Sorry, but your database encrypted with unknown module"), MB_OK); + bCheckingPass = 0; + return 0; + } + } + + { + //wchar_t Name[100], Author[100]; + + // Unsane: none + AddMessage(LPGEN("Database encrypted with %s by %s"), CryptoEngine->Name, CryptoEngine->Author); + } + + while(1){ + res = DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_LOGIN), NULL, (DLGPROC)DlgStdInProc, (LPARAM)szDBName); + if(res == IDCANCEL) + { + wrongPass = 0; + bCheckingPass = 0; + return 0; + } + if(encryptKeyLength < 1) continue; + EncoderInit(); + DecodeCopyMemory((BYTE*)&ver, &checkWord, sizeof(checkWord)); + if(ver == 0x5195) + { + wrongPass = 0; + bCheckingPass = 0; + return 1; + } + wrongPass++; + } + + bCheckingPass = 0; +} + + +UINT oldLangID = 0; +void LanguageChanged(HWND hDlg) +{ + UINT LangID = (UINT)GetKeyboardLayout(0); + char Lang[3] = {0}; + if (LangID != oldLangID) + { + oldLangID = LangID; + GetLocaleInfoA(MAKELCID((LangID & 0xffffffff), SORT_DEFAULT), LOCALE_SABBREVLANGNAME, Lang, 2); + SetDlgItemTextA(hDlg, IDC_LANG, Lang); + } +} + +BOOL CALLBACK DlgStdInProc(HWND hDlg, UINT uMsg,WPARAM wParam,LPARAM lParam) +{ + HICON hIcon = 0; + TCHAR tszHeaderTxt[256]; + switch(uMsg) + { + case WM_INITDIALOG: + { + HWND hwndCtrl; + TranslateDialogDefault(hDlg); + + hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_PASS)); + SendMessage(GetDlgItem(hDlg, IDC_HEADERBAR), WM_SETICON, 0, (LPARAM)hIcon); + + if (!wrongPass) + { + mir_sntprintf(tszHeaderTxt, SIZEOF(tszHeaderTxt), _T("%s\n%s"), TranslateT("Please type in your password for"), lParam); + SetWindowText(GetDlgItem(hDlg, IDC_HEADERBAR), tszHeaderTxt); + } + else + { + if (wrongPass > 2) + { + hwndCtrl = GetDlgItem(hDlg, IDC_USERPASS); + EnableWindow(hwndCtrl, FALSE); + hwndCtrl = GetDlgItem(hDlg, IDOK); + EnableWindow(hwndCtrl, FALSE); + + SetWindowText(GetDlgItem(hDlg, IDC_HEADERBAR), TranslateT("Too many errors!")); + } + else + SetWindowText(GetDlgItem(hDlg, IDC_HEADERBAR), TranslateT("Password is not correct!")); + } + oldLangID = 0; + SetTimer(hDlg,1,200,NULL); + LanguageChanged(hDlg); + return TRUE; + } + + case WM_CTLCOLORSTATIC: + { + if ((HWND)lParam == GetDlgItem(hDlg, IDC_LANG)) + { + SetTextColor((HDC)wParam, GetSysColor(COLOR_HIGHLIGHTTEXT)); + SetBkMode((HDC)wParam, TRANSPARENT); + return (BOOL)GetSysColorBrush(COLOR_HIGHLIGHT); + } + + return FALSE; + } + + case WM_COMMAND: + { + UINT uid = LOWORD(wParam); + + if(uid == IDOK){ + if (!GetWindowLongPtr(hDlg,GWLP_USERDATA)) + { + encryptKeyLength = GetDlgItemTextA(hDlg, IDC_USERPASS, encryptKey, 254); + EndDialog(hDlg,IDOK); + }else{ + + } + }else if(uid == IDCANCEL){ + EndDialog(hDlg,IDCANCEL); + } + } + case WM_TIMER: + { + LanguageChanged(hDlg); + return FALSE; + } + case WM_DESTROY: + { + KillTimer(hDlg, 1); + DestroyIcon(hIcon); + return FALSE; + } + } + + return FALSE; +} diff --git a/plugins/Dbx_mmap_SA/Import_SA/main.c b/plugins/Dbx_mmap_SA/Import_SA/main.c deleted file mode 100644 index f6fd4bc67a..0000000000 --- a/plugins/Dbx_mmap_SA/Import_SA/main.c +++ /dev/null @@ -1,550 +0,0 @@ -/* - -Import plugin for Miranda IM - -Copyright (C) 2001-2005 Martin Öberg, Richard Hughes, Roland Rabien & Tristan Van de Vreede - -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 "import.h" -#include "version.h" - -void FreeVariant( DBVARIANT* dbv ); -void WriteVariant( HANDLE hContact, const char* module, const char* var, DBVARIANT* dbv ); - -BOOL IsDuplicateEvent(HANDLE hContact, DBEVENTINFO dbei); - - -int nImportOption; -int nCustomOptions; -int hLangpack; - -int cICQAccounts = 0; -char ** szICQModuleName = NULL; -TCHAR ** tszICQAccountName = NULL; -int iICQAccount = 0; - -static HANDLE hHookModulesLoaded = NULL; -static HANDLE hHookOnExit = NULL; -static HANDLE hImportService = NULL; - -INT_PTR CALLBACK WizardDlgProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam); - -HINSTANCE hInst; -PLUGINLINK *pluginLink; -static HWND hwndWizard = NULL; - -PLUGININFOEX pluginInfo = { - sizeof(PLUGININFOEX), - __PLUGIN_NAME, - __VERSION_DWORD, - __DESCRIPTION, - __AUTHOR, - __AUTHOREMAIL, - __COPYRIGHT, - __AUTHORWEB, - UNICODE_AWARE, - 0, //{2D77A746-00A6-4343-BFC5-F808CDD772EA} - {0x2d77a746, 0xa6, 0x4343, { 0xbf, 0xc5, 0xf8, 0x8, 0xcd, 0xd7, 0x72, 0xea }} -}; - -BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) -{ - hInst = hinstDLL; - return TRUE; -} - -static INT_PTR ImportCommand(WPARAM wParam,LPARAM lParam) -{ - if (IsWindow(hwndWizard)) { - SetForegroundWindow(hwndWizard); - SetFocus(hwndWizard); - } - else hwndWizard = CreateDialog(hInst, MAKEINTRESOURCE(IDD_WIZARD), NULL, WizardDlgProc); - - return 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// MirandaPluginInfoEx - returns an information about a plugin - -__declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) -{ - return &pluginInfo; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// MirandaPluginInterfaces - returns the protocol interface to the core - -static const MUUID interfaces[] = {MIID_IMPORT, MIID_LAST}; - -__declspec(dllexport) const MUUID* MirandaPluginInterfaces(void) -{ - return interfaces; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Performs a primary set of actions upon plugin loading - -static int ModulesLoaded(WPARAM wParam, LPARAM lParam) -{ - int nProtocols = 0; - int n; - PROTOCOLDESCRIPTOR **ppProtos = NULL; - - if (DBGetContactSettingByte(NULL, IMPORT_MODULE, IMP_KEY_FR, 1)) - return 0; - - // Only autorun import wizard if at least one protocol is installed - CallService(MS_PROTO_ENUMPROTOCOLS, (WPARAM)&nProtocols, (LPARAM)&ppProtos); - for (n=0; n < nProtocols; n++) { - if (ppProtos[n]->type == PROTOTYPE_PROTOCOL) { - CallService(IMPORT_SERVICE, 0, 0); - DBWriteContactSettingByte(NULL, IMPORT_MODULE, IMP_KEY_FR, 1); - break; - } } - return 0; -} - -static int OnExit(WPARAM wParam, LPARAM lParam) -{ - if ( hwndWizard ) - SendMessage(hwndWizard, WM_CLOSE, 0, 0); - return 0; -} - -int __declspec(dllexport) Load(PLUGINLINK *link) -{ - pluginLink = link; - mir_getMMI( &mmi ); - mir_getUTFI( &utfi ); - mir_getLP( &pluginInfo ); - - hImportService = CreateServiceFunction(IMPORT_SERVICE, ImportCommand); - { - CLISTMENUITEM mi; - ZeroMemory(&mi, sizeof(mi)); - mi.cbSize = sizeof(mi); - mi.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_IMPORT)); - mi.pszName = LPGEN("&Import..."); - mi.position = 500050000; - mi.pszService = IMPORT_SERVICE; - Menu_AddMainMenuItem(&mi); - } - hHookModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded); - hHookOnExit = HookEvent(ME_SYSTEM_OKTOEXIT, OnExit); - { - INITCOMMONCONTROLSEX icex; - icex.dwSize = sizeof(icex); - icex.dwICC = ICC_DATE_CLASSES; - InitCommonControlsEx(&icex); - } - - return 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Unload a plugin - -int __declspec(dllexport) Unload(void) -{ - if (hHookModulesLoaded) - UnhookEvent(hHookModulesLoaded); - if (hHookOnExit) - UnhookEvent(hHookOnExit); - if (hImportService) - DestroyServiceFunction(hImportService); - - return 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -BOOL IsProtocolLoaded(char* pszProtocolName) -{ - return CallService(MS_PROTO_ISPROTOCOLLOADED, 0, (LPARAM)pszProtocolName) ? TRUE : FALSE; -} - -BOOL EnumICQAccounts() -{ - int count, i = 0; - PROTOACCOUNT ** accs; - - while (cICQAccounts) - { - cICQAccounts--; - free(szICQModuleName[cICQAccounts]); - free(tszICQAccountName[cICQAccounts]); - } - - ProtoEnumAccounts(&count, &accs); - szICQModuleName = (char**)realloc(szICQModuleName, count * sizeof(char**)); - tszICQAccountName = (TCHAR**)realloc(tszICQAccountName, count * sizeof(TCHAR**)); - while (i < count) - { - if ((0 == strcmp(ICQOSCPROTONAME, accs[i]->szProtoName)) && accs[i]->bIsEnabled) - { - szICQModuleName[cICQAccounts] = strdup(accs[i]->szModuleName); - tszICQAccountName[cICQAccounts] = _tcsdup(accs[i]->tszAccountName); - cICQAccounts++; - } - i++; - } - return cICQAccounts != 0; -} - -void FreeICQAccountsList() -{ - while (cICQAccounts) - { - cICQAccounts--; - free(szICQModuleName[cICQAccounts]); - free(tszICQAccountName[cICQAccounts]); - } - - if (szICQModuleName) - free(szICQModuleName); - if (tszICQAccountName) - free(tszICQAccountName); - - szICQModuleName = NULL; - tszICQAccountName = NULL; -} - -HANDLE HContactFromNumericID(char* pszProtoName, char* pszSetting, DWORD dwID) -{ - char* szProto; - HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); - while (hContact != NULL) - { - if (DBGetContactSettingDword(hContact, pszProtoName, pszSetting, 0) == dwID) - { - szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); - if (szProto != NULL && !strcmp(szProto, pszProtoName)) - return hContact; - } - hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); - } - return INVALID_HANDLE_VALUE; -} - -HANDLE HContactFromID(char* pszProtoName, char* pszSetting, char* pszID) -{ - DBVARIANT dbv; - HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); - while (hContact != NULL) { - char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); - if ( !lstrcmpA(szProto, pszProtoName)) { - if (DBGetContactSettingString(hContact, pszProtoName, pszSetting, &dbv) == 0) { - if (strcmp(pszID, dbv.pszVal) == 0) { - DBFreeVariant(&dbv); - return hContact; - } - DBFreeVariant(&dbv); - } - } - - hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); - } - return INVALID_HANDLE_VALUE; -} - -HANDLE HistoryImportFindContact(HWND hdlgProgress, char* szModuleName, DWORD uin, int addUnknown) -{ - HANDLE hContact = HContactFromNumericID(szModuleName, "UIN", uin); - if (hContact == NULL) { - AddMessage( LPGEN("Ignored event from/to self")); - return INVALID_HANDLE_VALUE; - } - - if (hContact != INVALID_HANDLE_VALUE) - return hContact; - - if (!addUnknown) - return INVALID_HANDLE_VALUE; - - hContact = (HANDLE)CallService(MS_DB_CONTACT_ADD, 0, 0); - CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)szModuleName); - DBWriteContactSettingDword(hContact, szModuleName, "UIN", uin); - AddMessage( LPGEN("Added contact %u (found in history)"), uin ); - return hContact; -} - -HANDLE AddContact(HWND hdlgProgress, char* pszProtoName, char* pszUniqueSetting, - DBVARIANT* id, DBVARIANT* nick, DBVARIANT* group) -{ - HANDLE hContact; - char szid[ 40 ]; - char* pszUserID = ( id->type == DBVT_DWORD ) ? _ltoa( id->dVal, szid, 10 ) : id->pszVal; - - hContact = (HANDLE)CallService(MS_DB_CONTACT_ADD, 0, 0); - if ( CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)pszProtoName) != 0) { - CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0); - AddMessage( LPGEN("Failed to add %s contact %s"), pszProtoName, pszUserID ); - FreeVariant( id ); - FreeVariant( nick ); - FreeVariant( group ); - return INVALID_HANDLE_VALUE; - } - - WriteVariant( hContact, pszProtoName, pszUniqueSetting, id ); - - if ( group->type ) - CreateGroup( group->type, group->pszVal, hContact ); - - if ( nick->type && nick->pszVal[0] ) { - WriteVariant( hContact, "CList", "MyHandle", nick ); - if (nick->type == DBVT_UTF8) { - char *tmp = mir_utf8decodeA(nick->pszVal); - AddMessage( LPGEN("Added %s contact %s, '%s'"), pszProtoName, pszUserID, tmp ); - mir_free(tmp); - } - else AddMessage( LPGEN("Added %s contact %s, '%s'"), pszProtoName, pszUserID, nick->pszVal ); - } - else AddMessage( LPGEN("Added %s contact %s"), pszProtoName, pszUserID ); - - FreeVariant( id ); - FreeVariant( nick ); - FreeVariant( group ); - return hContact; -} - -// ------------------------------------------------ -// Creates a group with a specified name in the -// Miranda contact list. -// If contact is specified adds it to group -// ------------------------------------------------ -// Returns 1 if successful and 0 when it fails. -int CreateGroup(BYTE type, const char* name, HANDLE hContact) -{ - int groupId; - TCHAR *tmp, *tszGrpName; - char groupIdStr[11]; - size_t cbName; - - if (type == DBVT_UTF8) - tmp = mir_utf8decodeT( name ); - else if (type == DBVT_WCHAR) - tmp = mir_u2t(( wchar_t* )name ); - else - tmp = mir_a2t( name ); - - if ( tmp == NULL ) - return 0; - - cbName = _tcslen(tmp); - tszGrpName = _alloca(( cbName+2 )*sizeof( TCHAR )); - tszGrpName[0] = 1 | GROUPF_EXPANDED; - _tcscpy( tszGrpName+1, tmp ); - mir_free( tmp ); - - // Check for duplicate & find unused id - for (groupId = 0; ; groupId++) { - DBVARIANT dbv; - itoa(groupId, groupIdStr,10); - if (DBGetContactSettingTString(NULL, "CListGroups", groupIdStr, &dbv)) - break; - - if ( !lstrcmp(dbv.ptszVal + 1, tszGrpName + 1 )) { - if (hContact) - DBWriteContactSettingTString( hContact, "CList", "Group", tszGrpName+1 ); - else { - char *str = mir_t2a(tszGrpName + 1); - AddMessage( LPGEN("Skipping duplicate group %s."), str); - mir_free(str); - } - - DBFreeVariant(&dbv); - return 0; - } - - DBFreeVariant(&dbv); - } - - DBWriteContactSettingTString( NULL, "CListGroups", groupIdStr, tszGrpName ); - - if (hContact) - DBWriteContactSettingTString( hContact, "CList", "Group", tszGrpName+1 ); - - return 1; -} - -// Returns TRUE if the event already exist in the database -BOOL IsDuplicateEvent(HANDLE hContact, DBEVENTINFO dbei) -{ - static DWORD dwPreviousTimeStamp = -1; - static HANDLE hPreviousContact = INVALID_HANDLE_VALUE; - static HANDLE hPreviousDbEvent = NULL; - - HANDLE hExistingDbEvent; - DWORD dwEventTimeStamp; - DBEVENTINFO dbeiExisting; - - // get last event - if (!(hExistingDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDLAST, (WPARAM)hContact, 0))) - return FALSE; - - ZeroMemory(&dbeiExisting, sizeof(dbeiExisting)); - dbeiExisting.cbSize = sizeof(dbeiExisting); - CallService(MS_DB_EVENT_GET, (WPARAM)hExistingDbEvent, (LPARAM)&dbeiExisting); - dwEventTimeStamp = dbeiExisting.timestamp; - - // compare with last timestamp - if (dbei.timestamp > dwEventTimeStamp) - { - // remember event - hPreviousDbEvent = hExistingDbEvent; - dwPreviousTimeStamp = dwEventTimeStamp; - return FALSE; - } - - if (hContact != hPreviousContact) - { - hPreviousContact = hContact; - // remember event - hPreviousDbEvent = hExistingDbEvent; - dwPreviousTimeStamp = dwEventTimeStamp; - - // get first event - if (!(hExistingDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDFIRST, (WPARAM)hContact, 0))) - return FALSE; - - ZeroMemory(&dbeiExisting, sizeof(dbeiExisting)); - dbeiExisting.cbSize = sizeof(dbeiExisting); - CallService(MS_DB_EVENT_GET, (WPARAM)hExistingDbEvent, (LPARAM)&dbeiExisting); - dwEventTimeStamp = dbeiExisting.timestamp; - - // compare with first timestamp - if (dbei.timestamp <= dwEventTimeStamp) - { - // remember event - dwPreviousTimeStamp = dwEventTimeStamp; - hPreviousDbEvent = hExistingDbEvent; - - if ( dbei.timestamp != dwEventTimeStamp ) - return FALSE; - } - - } - // check for equal timestamps - if (dbei.timestamp == dwPreviousTimeStamp) - { - ZeroMemory(&dbeiExisting, sizeof(dbeiExisting)); - dbeiExisting.cbSize = sizeof(dbeiExisting); - CallService(MS_DB_EVENT_GET, (WPARAM)hPreviousDbEvent, (LPARAM)&dbeiExisting); - - if ((dbei.timestamp == dbeiExisting.timestamp) && - (dbei.eventType == dbeiExisting.eventType) && - (dbei.cbBlob == dbeiExisting.cbBlob) && - ((dbei.flags&DBEF_SENT) == (dbeiExisting.flags&DBEF_SENT))) - return TRUE; - - // find event with another timestamp - hExistingDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDNEXT, (WPARAM)hPreviousDbEvent, 0); - while (hExistingDbEvent != NULL) - { - ZeroMemory(&dbeiExisting, sizeof(dbeiExisting)); - dbeiExisting.cbSize = sizeof(dbeiExisting); - CallService(MS_DB_EVENT_GET, (WPARAM)hExistingDbEvent, (LPARAM)&dbeiExisting); - - if (dbeiExisting.timestamp != dwPreviousTimeStamp) - { - // use found event - hPreviousDbEvent = hExistingDbEvent; - dwPreviousTimeStamp = dbeiExisting.timestamp; - break; - } - - hPreviousDbEvent = hExistingDbEvent; - hExistingDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDNEXT, (WPARAM)hExistingDbEvent, 0); - } - } - - hExistingDbEvent = hPreviousDbEvent; - - if (dbei.timestamp <= dwPreviousTimeStamp) - { - // look back - while (hExistingDbEvent != NULL) - { - ZeroMemory(&dbeiExisting, sizeof(dbeiExisting)); - dbeiExisting.cbSize = sizeof(dbeiExisting); - CallService(MS_DB_EVENT_GET, (WPARAM)hExistingDbEvent, (LPARAM)&dbeiExisting); - - if (dbei.timestamp > dbeiExisting.timestamp) - { - // remember event - hPreviousDbEvent = hExistingDbEvent; - dwPreviousTimeStamp = dbeiExisting.timestamp; - return FALSE; - } - - // Compare event with import candidate - if ((dbei.timestamp == dbeiExisting.timestamp) && - (dbei.eventType == dbeiExisting.eventType) && - (dbei.cbBlob == dbeiExisting.cbBlob) && - ((dbei.flags&DBEF_SENT) == (dbeiExisting.flags&DBEF_SENT))) - { - // remember event - hPreviousDbEvent = hExistingDbEvent; - dwPreviousTimeStamp = dbeiExisting.timestamp; - return TRUE; - } - - // Get previous event in chain - hExistingDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDPREV, (WPARAM)hExistingDbEvent, 0); - } - - } - else - { - // look forward - while (hExistingDbEvent != NULL) - { - ZeroMemory(&dbeiExisting, sizeof(dbeiExisting)); - dbeiExisting.cbSize = sizeof(dbeiExisting); - CallService(MS_DB_EVENT_GET, (WPARAM)hExistingDbEvent, (LPARAM)&dbeiExisting); - - if (dbei.timestamp < dbeiExisting.timestamp) - { - // remember event - hPreviousDbEvent = hExistingDbEvent; - dwPreviousTimeStamp = dbeiExisting.timestamp; - return FALSE; - } - - // Compare event with import candidate - if ((dbei.timestamp == dbeiExisting.timestamp) && - (dbei.eventType == dbeiExisting.eventType) && - (dbei.cbBlob == dbeiExisting.cbBlob) && - ((dbei.flags&DBEF_SENT) == (dbeiExisting.flags&DBEF_SENT))) - { - // remember event - hPreviousDbEvent = hExistingDbEvent; - dwPreviousTimeStamp = dbeiExisting.timestamp; - return TRUE; - } - - // Get next event in chain - hExistingDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDNEXT, (WPARAM)hExistingDbEvent, 0); - } - - } - // reset last event - hPreviousContact = INVALID_HANDLE_VALUE; - return FALSE; -} diff --git a/plugins/Dbx_mmap_SA/Import_SA/main.cpp b/plugins/Dbx_mmap_SA/Import_SA/main.cpp new file mode 100644 index 0000000000..f6fd4bc67a --- /dev/null +++ b/plugins/Dbx_mmap_SA/Import_SA/main.cpp @@ -0,0 +1,550 @@ +/* + +Import plugin for Miranda IM + +Copyright (C) 2001-2005 Martin Öberg, Richard Hughes, Roland Rabien & Tristan Van de Vreede + +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 "import.h" +#include "version.h" + +void FreeVariant( DBVARIANT* dbv ); +void WriteVariant( HANDLE hContact, const char* module, const char* var, DBVARIANT* dbv ); + +BOOL IsDuplicateEvent(HANDLE hContact, DBEVENTINFO dbei); + + +int nImportOption; +int nCustomOptions; +int hLangpack; + +int cICQAccounts = 0; +char ** szICQModuleName = NULL; +TCHAR ** tszICQAccountName = NULL; +int iICQAccount = 0; + +static HANDLE hHookModulesLoaded = NULL; +static HANDLE hHookOnExit = NULL; +static HANDLE hImportService = NULL; + +INT_PTR CALLBACK WizardDlgProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam); + +HINSTANCE hInst; +PLUGINLINK *pluginLink; +static HWND hwndWizard = NULL; + +PLUGININFOEX pluginInfo = { + sizeof(PLUGININFOEX), + __PLUGIN_NAME, + __VERSION_DWORD, + __DESCRIPTION, + __AUTHOR, + __AUTHOREMAIL, + __COPYRIGHT, + __AUTHORWEB, + UNICODE_AWARE, + 0, //{2D77A746-00A6-4343-BFC5-F808CDD772EA} + {0x2d77a746, 0xa6, 0x4343, { 0xbf, 0xc5, 0xf8, 0x8, 0xcd, 0xd7, 0x72, 0xea }} +}; + +BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) +{ + hInst = hinstDLL; + return TRUE; +} + +static INT_PTR ImportCommand(WPARAM wParam,LPARAM lParam) +{ + if (IsWindow(hwndWizard)) { + SetForegroundWindow(hwndWizard); + SetFocus(hwndWizard); + } + else hwndWizard = CreateDialog(hInst, MAKEINTRESOURCE(IDD_WIZARD), NULL, WizardDlgProc); + + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MirandaPluginInfoEx - returns an information about a plugin + +__declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) +{ + return &pluginInfo; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MirandaPluginInterfaces - returns the protocol interface to the core + +static const MUUID interfaces[] = {MIID_IMPORT, MIID_LAST}; + +__declspec(dllexport) const MUUID* MirandaPluginInterfaces(void) +{ + return interfaces; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Performs a primary set of actions upon plugin loading + +static int ModulesLoaded(WPARAM wParam, LPARAM lParam) +{ + int nProtocols = 0; + int n; + PROTOCOLDESCRIPTOR **ppProtos = NULL; + + if (DBGetContactSettingByte(NULL, IMPORT_MODULE, IMP_KEY_FR, 1)) + return 0; + + // Only autorun import wizard if at least one protocol is installed + CallService(MS_PROTO_ENUMPROTOCOLS, (WPARAM)&nProtocols, (LPARAM)&ppProtos); + for (n=0; n < nProtocols; n++) { + if (ppProtos[n]->type == PROTOTYPE_PROTOCOL) { + CallService(IMPORT_SERVICE, 0, 0); + DBWriteContactSettingByte(NULL, IMPORT_MODULE, IMP_KEY_FR, 1); + break; + } } + return 0; +} + +static int OnExit(WPARAM wParam, LPARAM lParam) +{ + if ( hwndWizard ) + SendMessage(hwndWizard, WM_CLOSE, 0, 0); + return 0; +} + +int __declspec(dllexport) Load(PLUGINLINK *link) +{ + pluginLink = link; + mir_getMMI( &mmi ); + mir_getUTFI( &utfi ); + mir_getLP( &pluginInfo ); + + hImportService = CreateServiceFunction(IMPORT_SERVICE, ImportCommand); + { + CLISTMENUITEM mi; + ZeroMemory(&mi, sizeof(mi)); + mi.cbSize = sizeof(mi); + mi.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_IMPORT)); + mi.pszName = LPGEN("&Import..."); + mi.position = 500050000; + mi.pszService = IMPORT_SERVICE; + Menu_AddMainMenuItem(&mi); + } + hHookModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded); + hHookOnExit = HookEvent(ME_SYSTEM_OKTOEXIT, OnExit); + { + INITCOMMONCONTROLSEX icex; + icex.dwSize = sizeof(icex); + icex.dwICC = ICC_DATE_CLASSES; + InitCommonControlsEx(&icex); + } + + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Unload a plugin + +int __declspec(dllexport) Unload(void) +{ + if (hHookModulesLoaded) + UnhookEvent(hHookModulesLoaded); + if (hHookOnExit) + UnhookEvent(hHookOnExit); + if (hImportService) + DestroyServiceFunction(hImportService); + + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +BOOL IsProtocolLoaded(char* pszProtocolName) +{ + return CallService(MS_PROTO_ISPROTOCOLLOADED, 0, (LPARAM)pszProtocolName) ? TRUE : FALSE; +} + +BOOL EnumICQAccounts() +{ + int count, i = 0; + PROTOACCOUNT ** accs; + + while (cICQAccounts) + { + cICQAccounts--; + free(szICQModuleName[cICQAccounts]); + free(tszICQAccountName[cICQAccounts]); + } + + ProtoEnumAccounts(&count, &accs); + szICQModuleName = (char**)realloc(szICQModuleName, count * sizeof(char**)); + tszICQAccountName = (TCHAR**)realloc(tszICQAccountName, count * sizeof(TCHAR**)); + while (i < count) + { + if ((0 == strcmp(ICQOSCPROTONAME, accs[i]->szProtoName)) && accs[i]->bIsEnabled) + { + szICQModuleName[cICQAccounts] = strdup(accs[i]->szModuleName); + tszICQAccountName[cICQAccounts] = _tcsdup(accs[i]->tszAccountName); + cICQAccounts++; + } + i++; + } + return cICQAccounts != 0; +} + +void FreeICQAccountsList() +{ + while (cICQAccounts) + { + cICQAccounts--; + free(szICQModuleName[cICQAccounts]); + free(tszICQAccountName[cICQAccounts]); + } + + if (szICQModuleName) + free(szICQModuleName); + if (tszICQAccountName) + free(tszICQAccountName); + + szICQModuleName = NULL; + tszICQAccountName = NULL; +} + +HANDLE HContactFromNumericID(char* pszProtoName, char* pszSetting, DWORD dwID) +{ + char* szProto; + HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while (hContact != NULL) + { + if (DBGetContactSettingDword(hContact, pszProtoName, pszSetting, 0) == dwID) + { + szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + if (szProto != NULL && !strcmp(szProto, pszProtoName)) + return hContact; + } + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); + } + return INVALID_HANDLE_VALUE; +} + +HANDLE HContactFromID(char* pszProtoName, char* pszSetting, char* pszID) +{ + DBVARIANT dbv; + HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while (hContact != NULL) { + char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + if ( !lstrcmpA(szProto, pszProtoName)) { + if (DBGetContactSettingString(hContact, pszProtoName, pszSetting, &dbv) == 0) { + if (strcmp(pszID, dbv.pszVal) == 0) { + DBFreeVariant(&dbv); + return hContact; + } + DBFreeVariant(&dbv); + } + } + + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); + } + return INVALID_HANDLE_VALUE; +} + +HANDLE HistoryImportFindContact(HWND hdlgProgress, char* szModuleName, DWORD uin, int addUnknown) +{ + HANDLE hContact = HContactFromNumericID(szModuleName, "UIN", uin); + if (hContact == NULL) { + AddMessage( LPGEN("Ignored event from/to self")); + return INVALID_HANDLE_VALUE; + } + + if (hContact != INVALID_HANDLE_VALUE) + return hContact; + + if (!addUnknown) + return INVALID_HANDLE_VALUE; + + hContact = (HANDLE)CallService(MS_DB_CONTACT_ADD, 0, 0); + CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)szModuleName); + DBWriteContactSettingDword(hContact, szModuleName, "UIN", uin); + AddMessage( LPGEN("Added contact %u (found in history)"), uin ); + return hContact; +} + +HANDLE AddContact(HWND hdlgProgress, char* pszProtoName, char* pszUniqueSetting, + DBVARIANT* id, DBVARIANT* nick, DBVARIANT* group) +{ + HANDLE hContact; + char szid[ 40 ]; + char* pszUserID = ( id->type == DBVT_DWORD ) ? _ltoa( id->dVal, szid, 10 ) : id->pszVal; + + hContact = (HANDLE)CallService(MS_DB_CONTACT_ADD, 0, 0); + if ( CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)pszProtoName) != 0) { + CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0); + AddMessage( LPGEN("Failed to add %s contact %s"), pszProtoName, pszUserID ); + FreeVariant( id ); + FreeVariant( nick ); + FreeVariant( group ); + return INVALID_HANDLE_VALUE; + } + + WriteVariant( hContact, pszProtoName, pszUniqueSetting, id ); + + if ( group->type ) + CreateGroup( group->type, group->pszVal, hContact ); + + if ( nick->type && nick->pszVal[0] ) { + WriteVariant( hContact, "CList", "MyHandle", nick ); + if (nick->type == DBVT_UTF8) { + char *tmp = mir_utf8decodeA(nick->pszVal); + AddMessage( LPGEN("Added %s contact %s, '%s'"), pszProtoName, pszUserID, tmp ); + mir_free(tmp); + } + else AddMessage( LPGEN("Added %s contact %s, '%s'"), pszProtoName, pszUserID, nick->pszVal ); + } + else AddMessage( LPGEN("Added %s contact %s"), pszProtoName, pszUserID ); + + FreeVariant( id ); + FreeVariant( nick ); + FreeVariant( group ); + return hContact; +} + +// ------------------------------------------------ +// Creates a group with a specified name in the +// Miranda contact list. +// If contact is specified adds it to group +// ------------------------------------------------ +// Returns 1 if successful and 0 when it fails. +int CreateGroup(BYTE type, const char* name, HANDLE hContact) +{ + int groupId; + TCHAR *tmp, *tszGrpName; + char groupIdStr[11]; + size_t cbName; + + if (type == DBVT_UTF8) + tmp = mir_utf8decodeT( name ); + else if (type == DBVT_WCHAR) + tmp = mir_u2t(( wchar_t* )name ); + else + tmp = mir_a2t( name ); + + if ( tmp == NULL ) + return 0; + + cbName = _tcslen(tmp); + tszGrpName = _alloca(( cbName+2 )*sizeof( TCHAR )); + tszGrpName[0] = 1 | GROUPF_EXPANDED; + _tcscpy( tszGrpName+1, tmp ); + mir_free( tmp ); + + // Check for duplicate & find unused id + for (groupId = 0; ; groupId++) { + DBVARIANT dbv; + itoa(groupId, groupIdStr,10); + if (DBGetContactSettingTString(NULL, "CListGroups", groupIdStr, &dbv)) + break; + + if ( !lstrcmp(dbv.ptszVal + 1, tszGrpName + 1 )) { + if (hContact) + DBWriteContactSettingTString( hContact, "CList", "Group", tszGrpName+1 ); + else { + char *str = mir_t2a(tszGrpName + 1); + AddMessage( LPGEN("Skipping duplicate group %s."), str); + mir_free(str); + } + + DBFreeVariant(&dbv); + return 0; + } + + DBFreeVariant(&dbv); + } + + DBWriteContactSettingTString( NULL, "CListGroups", groupIdStr, tszGrpName ); + + if (hContact) + DBWriteContactSettingTString( hContact, "CList", "Group", tszGrpName+1 ); + + return 1; +} + +// Returns TRUE if the event already exist in the database +BOOL IsDuplicateEvent(HANDLE hContact, DBEVENTINFO dbei) +{ + static DWORD dwPreviousTimeStamp = -1; + static HANDLE hPreviousContact = INVALID_HANDLE_VALUE; + static HANDLE hPreviousDbEvent = NULL; + + HANDLE hExistingDbEvent; + DWORD dwEventTimeStamp; + DBEVENTINFO dbeiExisting; + + // get last event + if (!(hExistingDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDLAST, (WPARAM)hContact, 0))) + return FALSE; + + ZeroMemory(&dbeiExisting, sizeof(dbeiExisting)); + dbeiExisting.cbSize = sizeof(dbeiExisting); + CallService(MS_DB_EVENT_GET, (WPARAM)hExistingDbEvent, (LPARAM)&dbeiExisting); + dwEventTimeStamp = dbeiExisting.timestamp; + + // compare with last timestamp + if (dbei.timestamp > dwEventTimeStamp) + { + // remember event + hPreviousDbEvent = hExistingDbEvent; + dwPreviousTimeStamp = dwEventTimeStamp; + return FALSE; + } + + if (hContact != hPreviousContact) + { + hPreviousContact = hContact; + // remember event + hPreviousDbEvent = hExistingDbEvent; + dwPreviousTimeStamp = dwEventTimeStamp; + + // get first event + if (!(hExistingDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDFIRST, (WPARAM)hContact, 0))) + return FALSE; + + ZeroMemory(&dbeiExisting, sizeof(dbeiExisting)); + dbeiExisting.cbSize = sizeof(dbeiExisting); + CallService(MS_DB_EVENT_GET, (WPARAM)hExistingDbEvent, (LPARAM)&dbeiExisting); + dwEventTimeStamp = dbeiExisting.timestamp; + + // compare with first timestamp + if (dbei.timestamp <= dwEventTimeStamp) + { + // remember event + dwPreviousTimeStamp = dwEventTimeStamp; + hPreviousDbEvent = hExistingDbEvent; + + if ( dbei.timestamp != dwEventTimeStamp ) + return FALSE; + } + + } + // check for equal timestamps + if (dbei.timestamp == dwPreviousTimeStamp) + { + ZeroMemory(&dbeiExisting, sizeof(dbeiExisting)); + dbeiExisting.cbSize = sizeof(dbeiExisting); + CallService(MS_DB_EVENT_GET, (WPARAM)hPreviousDbEvent, (LPARAM)&dbeiExisting); + + if ((dbei.timestamp == dbeiExisting.timestamp) && + (dbei.eventType == dbeiExisting.eventType) && + (dbei.cbBlob == dbeiExisting.cbBlob) && + ((dbei.flags&DBEF_SENT) == (dbeiExisting.flags&DBEF_SENT))) + return TRUE; + + // find event with another timestamp + hExistingDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDNEXT, (WPARAM)hPreviousDbEvent, 0); + while (hExistingDbEvent != NULL) + { + ZeroMemory(&dbeiExisting, sizeof(dbeiExisting)); + dbeiExisting.cbSize = sizeof(dbeiExisting); + CallService(MS_DB_EVENT_GET, (WPARAM)hExistingDbEvent, (LPARAM)&dbeiExisting); + + if (dbeiExisting.timestamp != dwPreviousTimeStamp) + { + // use found event + hPreviousDbEvent = hExistingDbEvent; + dwPreviousTimeStamp = dbeiExisting.timestamp; + break; + } + + hPreviousDbEvent = hExistingDbEvent; + hExistingDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDNEXT, (WPARAM)hExistingDbEvent, 0); + } + } + + hExistingDbEvent = hPreviousDbEvent; + + if (dbei.timestamp <= dwPreviousTimeStamp) + { + // look back + while (hExistingDbEvent != NULL) + { + ZeroMemory(&dbeiExisting, sizeof(dbeiExisting)); + dbeiExisting.cbSize = sizeof(dbeiExisting); + CallService(MS_DB_EVENT_GET, (WPARAM)hExistingDbEvent, (LPARAM)&dbeiExisting); + + if (dbei.timestamp > dbeiExisting.timestamp) + { + // remember event + hPreviousDbEvent = hExistingDbEvent; + dwPreviousTimeStamp = dbeiExisting.timestamp; + return FALSE; + } + + // Compare event with import candidate + if ((dbei.timestamp == dbeiExisting.timestamp) && + (dbei.eventType == dbeiExisting.eventType) && + (dbei.cbBlob == dbeiExisting.cbBlob) && + ((dbei.flags&DBEF_SENT) == (dbeiExisting.flags&DBEF_SENT))) + { + // remember event + hPreviousDbEvent = hExistingDbEvent; + dwPreviousTimeStamp = dbeiExisting.timestamp; + return TRUE; + } + + // Get previous event in chain + hExistingDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDPREV, (WPARAM)hExistingDbEvent, 0); + } + + } + else + { + // look forward + while (hExistingDbEvent != NULL) + { + ZeroMemory(&dbeiExisting, sizeof(dbeiExisting)); + dbeiExisting.cbSize = sizeof(dbeiExisting); + CallService(MS_DB_EVENT_GET, (WPARAM)hExistingDbEvent, (LPARAM)&dbeiExisting); + + if (dbei.timestamp < dbeiExisting.timestamp) + { + // remember event + hPreviousDbEvent = hExistingDbEvent; + dwPreviousTimeStamp = dbeiExisting.timestamp; + return FALSE; + } + + // Compare event with import candidate + if ((dbei.timestamp == dbeiExisting.timestamp) && + (dbei.eventType == dbeiExisting.eventType) && + (dbei.cbBlob == dbeiExisting.cbBlob) && + ((dbei.flags&DBEF_SENT) == (dbeiExisting.flags&DBEF_SENT))) + { + // remember event + hPreviousDbEvent = hExistingDbEvent; + dwPreviousTimeStamp = dbeiExisting.timestamp; + return TRUE; + } + + // Get next event in chain + hExistingDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDNEXT, (WPARAM)hExistingDbEvent, 0); + } + + } + // reset last event + hPreviousContact = INVALID_HANDLE_VALUE; + return FALSE; +} diff --git a/plugins/Dbx_mmap_SA/Import_SA/mirabilis.c b/plugins/Dbx_mmap_SA/Import_SA/mirabilis.c deleted file mode 100644 index 130843205e..0000000000 --- a/plugins/Dbx_mmap_SA/Import_SA/mirabilis.c +++ /dev/null @@ -1,1492 +0,0 @@ -/* - -Import plugin for Miranda IM - -Copyright (C) 2001-2005 Martin Öberg, Richard Hughes, Roland Rabien & Tristan Van de Vreede - -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. - -*/ - -// ============== -// == INCLUDES == -// ============== - -#include "import.h" -#include "mirabilis.h" - -BOOL IsDuplicateEvent(HANDLE hContact, DBEVENTINFO dbei); -BOOL IsProtocolLoaded(char* pszProtocolName); -HANDLE HContactFromNumericID(char* pszProtoName, char* pszSetting, DWORD dwID); -HANDLE AddContact(HWND hdlgProgress, char* pszProtoName, char* pszUniqueSetting, DBVARIANT* id, DBVARIANT* nick, DBVARIANT* group); - -// ==================== -// ==================== -// == IMPLEMENTATION == -// ==================== -// ==================== - -static void SearchForDatabases(HWND hdlg, const TCHAR *dbPath, const TCHAR *type) -{ - HANDLE hFind; - WIN32_FIND_DATA fd; - TCHAR szSearchPath[MAX_PATH]; - TCHAR szRootName[MAX_PATH],*str2; - - int i; - - wsprintf(szSearchPath, _T("%s\\*.idx"), dbPath); - hFind=FindFirstFile(szSearchPath,&fd); - if(hFind!=INVALID_HANDLE_VALUE) { - do { - lstrcpy(szRootName,fd.cFileName); - str2=_tcsrchr(szRootName,'.'); - if(str2!=NULL) *str2=0; - if(lstrlen(szRootName)>3 && !lstrcmpi(szRootName+lstrlen(szRootName)-3,_T("tmp"))) - continue; - lstrcat(szRootName,type); - i=SendDlgItemMessage(hdlg,IDC_LIST,LB_ADDSTRING,0,(LPARAM)szRootName); - str2 = (TCHAR*)mir_alloc((lstrlen(dbPath) + 2+lstrlen(fd.cFileName))*sizeof(TCHAR)); - wsprintf(str2, _T("%s\\%s"), dbPath, fd.cFileName); - SendDlgItemMessage(hdlg,IDC_LIST,LB_SETITEMDATA,i,(LPARAM)str2); - } - while( FindNextFile( hFind, &fd )); - - FindClose(hFind); - } -} - -INT_PTR CALLBACK MirabilisPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam) -{ - switch(message) { - case WM_INITDIALOG: - { - HKEY hKey; - LONG lResult; - int i; - TranslateDialogDefault(hdlg); - if (ERROR_SUCCESS != (lResult = RegOpenKeyEx(HKEY_CURRENT_USER, _T("Software\\Mirabilis\\ICQ\\DefaultPrefs"), 0, KEY_QUERY_VALUE, &hKey))) - lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\Mirabilis\\ICQ\\DefaultPrefs"), 0, KEY_QUERY_VALUE, &hKey); - - if (lResult == ERROR_SUCCESS) { - TCHAR dbPath[MAX_PATH]; - DWORD cch; - cch=sizeof(dbPath); - if(ERROR_SUCCESS==RegQueryValueEx(hKey,_T("New Database"),NULL,NULL,(LPBYTE)dbPath,&cch)) - SearchForDatabases(hdlg,dbPath,_T(" (99a)")); - cch=sizeof(dbPath); - if(ERROR_SUCCESS==RegQueryValueEx(hKey,_T("99b Database"),NULL,NULL,(LPBYTE)dbPath,&cch)) - SearchForDatabases(hdlg,dbPath,_T(" (99b)")); - cch=sizeof(dbPath); - if(ERROR_SUCCESS==RegQueryValueEx(hKey,_T("2000a Database"),NULL,NULL,(LPBYTE)dbPath,&cch)) - SearchForDatabases(hdlg,dbPath,_T(" (2000a)")); - cch=sizeof(dbPath); - if(ERROR_SUCCESS==RegQueryValueEx(hKey,_T("2000b Database"),NULL,NULL,(LPBYTE)dbPath,&cch)) - SearchForDatabases(hdlg,dbPath,_T(" (2000b)")); - cch=sizeof(dbPath); - if(ERROR_SUCCESS==RegQueryValueEx(hKey,_T("2001a Database"),NULL,NULL,(LPBYTE)dbPath,&cch)) - SearchForDatabases(hdlg,dbPath,_T(" (2001a)")); - cch=sizeof(dbPath); - if(ERROR_SUCCESS==RegQueryValueEx(hKey,_T("2001b Database"),NULL,NULL,(LPBYTE)dbPath,&cch)) - SearchForDatabases(hdlg,dbPath,_T(" (2001b)")); - cch=sizeof(dbPath); - if(ERROR_SUCCESS==RegQueryValueEx(hKey,_T("2002a Database"),NULL,NULL,(LPBYTE)dbPath,&cch)) - SearchForDatabases(hdlg,dbPath,_T(" (2002a)")); - cch=sizeof(dbPath); - if(ERROR_SUCCESS==RegQueryValueEx(hKey,_T("2003a Database"),NULL,NULL,(LPBYTE)dbPath,&cch)) - SearchForDatabases(hdlg,dbPath,_T(" (2003a)")); - } - - for (i = 0; i < cICQAccounts; i++) - { - SendDlgItemMessage(hdlg, IDC_MIRABILISACCOUNT, CB_ADDSTRING, 0, (LPARAM)tszICQAccountName[i]); - } - SendDlgItemMessage(hdlg, IDC_MIRABILISACCOUNT, CB_SETCURSEL, 0, 0); - - SetTimer(hdlg,1,2000,NULL); - SendMessage(hdlg,WM_TIMER,0,0); - return TRUE; - } - case WM_TIMER: - { HANDLE hMirabilisMutex; - hMirabilisMutex=OpenMutexA(MUTEX_ALL_ACCESS,FALSE,"Mirabilis ICQ Mutex"); - if(hMirabilisMutex!=NULL) { - CloseHandle(hMirabilisMutex); - ShowWindow(GetDlgItem(hdlg,IDC_MIRABILISRUNNING),SW_SHOW); - } - else ShowWindow(GetDlgItem(hdlg,IDC_MIRABILISRUNNING),SW_HIDE); - } - break; - case WM_COMMAND: - switch(LOWORD(wParam)) { - case IDC_BACK: - PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_IMPORTTYPE,(LPARAM)ImportTypePageProc); - break; - case IDOK: - { TCHAR filename[MAX_PATH]; - GetDlgItemText(hdlg,IDC_FILENAME,filename,SIZEOF(filename)); - if(_taccess(filename,4)) { - MessageBox(hdlg,TranslateT("The given file does not exist. Please check that you have entered the name correctly."),TranslateT("Mirabilis Import"),MB_OK); - break; - } - lstrcpy(importFile,filename); - iICQAccount = SendDlgItemMessage(hdlg, IDC_MIRABILISACCOUNT, CB_GETCURSEL, 0, 0); - PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_OPTIONS,(LPARAM)MirabilisOptionsPageProc); - break; - } - case IDCANCEL: - PostMessage(GetParent(hdlg),WM_CLOSE,0,0); - break; - case IDC_LIST: - if(HIWORD(wParam)==LBN_SELCHANGE) { - int sel=SendDlgItemMessage(hdlg,IDC_LIST,LB_GETCURSEL,0,0); - if(sel==LB_ERR) break; - SetDlgItemText(hdlg,IDC_FILENAME,(TCHAR*)SendDlgItemMessage(hdlg,IDC_LIST,LB_GETITEMDATA,sel,0)); - } - break; - case IDC_OTHER: - { OPENFILENAME ofn; - TCHAR str[MAX_PATH], text[256]; - int index; - - // TranslateTS doesnt translate \0 separated strings - index = mir_sntprintf(text, 64, _T("%s (*.idx)"), TranslateT("Mirabilis ICQ database indexes")) + 1; - _tcscpy(text + index, _T("*.idx")); index += 6; - index += mir_sntprintf(text + index, 64, _T("%s (*.*)"), TranslateT("All Files")) + 1; - _tcscpy(text + index, _T("*.*")); index += 4; - text[index] = 0; - - GetDlgItemText(hdlg,IDC_FILENAME,str,SIZEOF(str)); - ZeroMemory(&ofn, sizeof(ofn)); - ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; - ofn.hwndOwner = hdlg; - ofn.lpstrFilter = text; - ofn.lpstrFile = str; - ofn.Flags = OFN_FILEMUSTEXIST | OFN_EXPLORER | OFN_NOCHANGEDIR | OFN_DONTADDTORECENT; - ofn.nMaxFile = SIZEOF(str); - ofn.lpstrDefExt = _T("idx"); - if(GetOpenFileName(&ofn)) - SetDlgItemText(hdlg,IDC_FILENAME,str); - break; - } - } - break; - - case WM_DESTROY: - { int i; - for(i=SendDlgItemMessage(hdlg,IDC_LIST,LB_GETCOUNT,0,0)-1;i>=0;i--) - mir_free((char*)SendDlgItemMessage(hdlg,IDC_LIST,LB_GETITEMDATA,i,0)); - break; - } - } - return FALSE; -} - - -INT_PTR CALLBACK MirabilisOptionsPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam) -{ - switch(message) { - case WM_INITDIALOG: - TranslateDialogDefault(hdlg); - EnableWindow(GetDlgItem(hdlg, IDC_RADIO_ALL), TRUE); - EnableWindow(GetDlgItem(hdlg, IDC_STATIC_ALL), TRUE); - EnableWindow(GetDlgItem(hdlg, IDC_RADIO_CONTACTS), TRUE); - EnableWindow(GetDlgItem(hdlg, IDC_STATIC_CONTACTS), TRUE); - CheckDlgButton(hdlg, IDC_RADIO_ALL, BST_CHECKED); - return TRUE; - - case WM_COMMAND: - switch(LOWORD(wParam)) { - case IDC_BACK: - PostMessage(GetParent(hdlg), WIZM_GOTOPAGE, IDD_MIRABILISDB, (LPARAM)MirabilisPageProc); - break; - case IDOK: - if (IsDlgButtonChecked(hdlg, IDC_RADIO_ALL)) { - DoImport = MirabilisImport; - nImportOption = IMPORT_ALL; - nCustomOptions = IOPT_MSGSENT|IOPT_MSGRECV|IOPT_URLSENT|IOPT_URLRECV; - PostMessage(GetParent(hdlg), WIZM_GOTOPAGE, IDD_PROGRESS, (LPARAM)ProgressPageProc); - break; - } - if (IsDlgButtonChecked(hdlg, IDC_RADIO_CONTACTS)) { - DoImport = MirabilisImport; - nImportOption = IMPORT_CONTACTS; - nCustomOptions = 0; - PostMessage(GetParent(hdlg), WIZM_GOTOPAGE, IDD_PROGRESS, (LPARAM)ProgressPageProc); - break; - } - break; - case IDCANCEL: - PostMessage(GetParent(hdlg), WM_CLOSE, 0, 0); - break; - } - break; - } - - return FALSE; -} - -static int GetHighestIndexEntry(void) -{ - struct TIdxIndexEntry *entry; - DWORD ofs; - - ofs=*(PDWORD)(pIdx+12); - for (;;) { - entry=(struct TIdxIndexEntry*)(pIdx+ofs); - if(entry->entryIdLow==(DWORD)-2) return ((struct TIdxDatEntry*)entry)->entryId; - if(entry->ofsHigher>=0xF0000000) ofs=entry->ofsInHere; - else ofs=entry->ofsHigher; - } -} - -static int GetIdDatOfs(DWORD id) -{ - struct TIdxIndexEntry *entry; - DWORD ofs = *(PDWORD)(pIdx+12); - for (;;) { - entry=(struct TIdxIndexEntry*)(pIdx+ofs); - if(entry->entryIdLow==(DWORD)-2) { - if(entry->entryIdHigh==id) return ((struct TIdxDatEntry*)entry)->datOfs; - return 0; - } - if(identryIdLow) ofs=entry->ofsLower; - else if(entry->ofsHigher<0xF0000000 && id>=entry->entryIdHigh) ofs=entry->ofsHigher; - else ofs=entry->ofsInHere; - } - return 0; -} - -static int GetDatEntryType(DWORD ofs) -{ - return *(int*)(pDat+ofs+4); -} - -DWORD GetDBVersion() -{ - dwDBVersion = *(PDWORD)(pIdx+16); - - switch (dwDBVersion) { - case DBV99A: - AddMessage( LPGEN("This looks like a ICQ 99a database.")); - break; - case DBV99B: - AddMessage( LPGEN("This looks like a ICQ 99b database.")); - break; - case DBV2000A: - AddMessage( LPGEN("This looks like a ICQ 2000a database.")); - break; - case DBV2000B: - AddMessage( LPGEN("This looks like a ICQ 2000b database.")); - break; - case DBV2001A: - AddMessage( LPGEN("This looks like a ICQ 2001, 2002 or 2003a database.")); - break; - default: - AddMessage( LPGEN("This database is an unknown version.")); - return 0; - } - - return dwDBVersion; -} - -int GetEntryVersion(WORD wSeparatorValue) -{ - int nVersion; - - if (wSeparatorValue < ENTRYV99A) - nVersion = 0; // Cannot handle ICQ98 contacts - else if ((wSeparatorValue >= ENTRYV99A) && (wSeparatorValue < ENTRYV99B)) - nVersion = ENTRYV99A; - else if ((wSeparatorValue >= ENTRYV99B) && (wSeparatorValue < ENTRYV2000A)) - nVersion = ENTRYV99B; - else if ((wSeparatorValue >= ENTRYV2000A) && (wSeparatorValue < ENTRYV2000B)) - nVersion = ENTRYV2000A; - else if ((wSeparatorValue >= ENTRYV2000B) && (wSeparatorValue < ENTRYV2001A)) - nVersion = ENTRYV2000B; - else if ((wSeparatorValue >= ENTRYV2001A) && (wSeparatorValue < ENTRYV2001B)) - nVersion = ENTRYV2001A; - else if ((wSeparatorValue >= ENTRYV2001B) && (wSeparatorValue < ENTRYV2002A)) - nVersion = ENTRYV2001B; - else if (wSeparatorValue >= ENTRYV2002A) - nVersion = ENTRYV2002A; - else - nVersion = ENTRYVUNKNOWN; // Just in case... Skip undocumented contact versions - - return nVersion; -} - -DWORD ReadSubList(DWORD dwOffset) -{ - DWORD dwSubType, dwProperties, n; - - #ifdef _LOGGING - AddMessage( LPGEN("Attempting to parse sub list at offset %u."), dwOffset); - #endif - - // Check number of properties in sub list - dwProperties = *(PDWORD)(pDat+dwOffset); - dwOffset+=4; - - // Check sub list type - dwSubType = *(PBYTE)(pDat+dwOffset); - dwOffset+=1; - - switch (dwSubType){ - case 0x6B: - for(n=0;n 1) - return 6 + (char*)(pDat + dwOffset); - - break; - } - else - // Skip to next group - dwOffset += *(PWORD)(pDat + dwOffset + 4) + 12; - } - break; - - case DBV2000A: - case DBV2000B: - case DBV2001A: - for (n = 0; n < dwGroups; n++) { - if (tmpOfs = ReadPropertyBlock(dwOffset, "GroupID", &nSearchResult)) { - if (nSearchResult) { - if (dwGroupID == *(PDWORD)(pDat + tmpOfs + 1)) { - strGroupName = 3 + (char*)(pDat + ReadPropertyBlock(dwOffset, "GroupName", &nSearchResult)); - if (nSearchResult) { - if ((DWORD)*(strGroupName - 2) > 1) - return strGroupName; - break; - } } } } - - // Skip to next group - if ( dwOffset != ReadPropertyBlock(dwOffset, NULL, NULL)) - break; - } - break; - } - - // The GroupID was not found, or it was found - // but the group did not have a name, or there - // was an error during parsing. - return 0; -} - -// ------------------------------------------------ -// Scans a group list and adds all found groups to -// the Miranda contact list -// ------------------------------------------------ -// dwOffset must point to the number of entries in -// the following group list. -// Returns the number of added groups, or -1 if an error -// occurred - -int ImportGroups() -{ - DWORD dwGroups, n, tmpOfs, dwOffset; - int nImported = 0; - int nSearchResult, nFormat; - WORD wSeparatorValue; - - if (!(dwOffset = FindMyDetails())) { - AddMessage( LPGEN("ERROR: Failed to find owner information.")); - return -1; - } - - wSeparatorValue = *(PWORD)(pDat + dwOffset + 0x1c); - nFormat = GetEntryVersion(wSeparatorValue); - - dwGroupListOfs = dwOffset = FindGroupList(dwOffset); - if (!dwOffset) { - AddMessage( LPGEN("ERROR: Failed to find contact list groups.")); - #ifdef _LOGGING - { // If this is a debug build, dump MyDetails block to disk - FILE *stream; - DWORD dwSize; - dwOffset = FindMyDetails(); - dwSize = *(PDWORD)(pDat + dwOffset); - stream = fopen("import_grouplist_dump.bin", "w"); - fwrite(pDat + dwOffset, 1, dwSize, stream); - fclose(stream); - } - #endif - return -1; - } - - // Check number of groups - dwGroups = *(PDWORD)(pDat + dwOffset); - if (dwGroups > 0) - AddMessage( LPGEN("Importing groups.")); - else { - AddMessage( LPGEN("This database does not contain any contact groups.")); - return 0; - } - - dwOffset += 4; - - // Import all groups with a name - switch (nFormat) { - case ENTRYV99A: - case ENTRYV99B: - for (n = 0; n < dwGroups; n++) { - if (*(PWORD)(pDat+dwOffset+4) > 1) { - if ( CreateGroup(DBVT_ASCIIZ, (char*)(pDat + dwOffset) + 6, NULL )) - nImported++; - dwOffset += *(PWORD)(pDat + dwOffset + 4) + 12; - } } - break; - - case ENTRYV2000A: - case ENTRYV2000B: - case ENTRYV2001A: - case ENTRYV2001B: - case ENTRYV2002A: - for (n = 0; n < dwGroups; n++) { - if (tmpOfs = ReadPropertyBlock(dwOffset, "GroupName", &nSearchResult)) { - if (nSearchResult) { - if (CreateGroup( DBVT_ASCIIZ, (char*)(pDat + tmpOfs + 3), NULL )) - nImported++; - } } - - dwOffset = ReadPropertyBlock(dwOffset, NULL, NULL); - if (!dwOffset) { - AddMessage( LPGEN("ERROR: An error occurred while importing groups.")); - AddMessage( LPGEN("All groups may not have not been imported.")); - #ifdef _LOGGING - { // If this is a debug build, dump MyDetails block to disk - FILE *stream; - DWORD dwSize; - dwOffset = FindMyDetails(); - dwSize = *(PDWORD)(pDat + dwOffset); - stream = fopen("import_grouplist_dump.bin", "w"); - fwrite(pDat + dwOffset, 1, dwSize, stream); - fclose(stream); - } - #endif - return -1; - } } - break; - - default: - return -1; - } - - return nImported; -} - -// Imports the contact at offset dwOffset -// Returns the HANDLE of the Miranda contact -// or INVALID_HANDLE_VALUE on failure - -HANDLE ImportContact(DWORD dwOffset) -{ - int nContactVersion, nSearchResult; - BYTE Status; - WORD wSeparatorValue; - DWORD dwGroup, dwUIN = 0, tmpOfs = 0; - char *strNickname = 0, *strGroupName = 0; - - if (*(int*)(pDat + dwOffset + 4) != DATENTRY_CONTACT) - return INVALID_HANDLE_VALUE; - - if (*(int*)(pDat + dwOffset + 0x1e) != 'USER') - return INVALID_HANDLE_VALUE; - - #ifdef _LOGGING - { // If this is a debug build, dump contact to disk - FILE *stream; - DWORD dwSize; - dwSize = *(PDWORD)(pDat + dwOffset); - stream = fopen("import_last_contact.bin", "w"); - fwrite(pDat + dwOffset, 1, dwSize, stream); - fclose(stream); - } - #endif - - Status = *(pDat + dwOffset + 0x22); - wSeparatorValue = *(PWORD)(pDat + dwOffset + 0x1c); - nContactVersion = GetEntryVersion(wSeparatorValue); - - dwGroup = *(PDWORD)(pDat + dwOffset + 0x26); - if (dwGroup >= 1000) - strGroupName = GetGroupName(dwGroup); - - if (Status == 5) - return INVALID_HANDLE_VALUE; // Skip deleted contacts - - if ((Status != 2) && (Status != 3)) { - AddMessage( LPGEN("Skipping inactive contact.")); - return INVALID_HANDLE_VALUE; - } - - if ((nContactVersion < ENTRYV99A) || (nContactVersion == 0)) { - AddMessage( LPGEN("Skipping contact with unsupported version.")); - return INVALID_HANDLE_VALUE; - } - - switch(nContactVersion){ - case ENTRYV99A: - if (!(dwOffset = ReadWavList(dwOffset + 0x54))) return INVALID_HANDLE_VALUE; - if (!(dwOffset = ReadPropertyBlock(dwOffset + 0x26, NULL, NULL))) return INVALID_HANDLE_VALUE; - // Check for custom nickname - if (*(PWORD)(pDat + dwOffset) > 1) strNickname = (char*)(dwOffset + pDat + 2); - // Find UIN - dwOffset += *(PWORD)(pDat + dwOffset) + 2; // Custom nick name - dwOffset += *(PWORD)(pDat + dwOffset) + 2; // Nick name - dwOffset += *(PWORD)(pDat + dwOffset) + 2; // First name - dwOffset += *(PWORD)(pDat + dwOffset) + 2; // Last name - dwOffset += *(PWORD)(pDat + dwOffset) + 2; // E-mail - dwUIN = *(PDWORD)(pDat + dwOffset); // UIN - break; - - case ENTRYV99B: - case ENTRYV2000A: - case ENTRYV2000B: - if (!(dwOffset = ReadWavList(dwOffset + 0x2C))) return INVALID_HANDLE_VALUE; - tmpOfs = ReadPropertyBlockList(dwOffset + 0x02, "UIN", &nSearchResult); - if (nSearchResult) dwUIN = *(PDWORD)(pDat + tmpOfs + 1); - tmpOfs = ReadPropertyBlockList(dwOffset + 0x02, "MyDefinedHandle", &nSearchResult); - if (nSearchResult) strNickname = (char*)(tmpOfs + pDat + 3); - break; - - case ENTRYV2001A: - case ENTRYV2001B: - tmpOfs = ReadPropertyBlockList(dwOffset + 0x2C, "MyDefinedHandle", &nSearchResult); - if (nSearchResult) strNickname = (char*)(tmpOfs + pDat + 3); - tmpOfs = ReadPropertyBlockList(dwOffset + 0x2C, "UIN", &nSearchResult); - if (nSearchResult) dwUIN = *(PDWORD)(pDat + tmpOfs + 1); - break; - - case ENTRYV2002A: - tmpOfs = ReadPropertyBlockList(dwOffset + 0x32, "MyDefinedHandle", &nSearchResult); - if (nSearchResult) strNickname = (char*)(tmpOfs + pDat + 3); - tmpOfs = ReadPropertyBlockList(dwOffset + 0x32, "UIN", &nSearchResult); - if (nSearchResult) dwUIN = *(PDWORD)(pDat + tmpOfs + 1); - break; - } - - if (!dwUIN) { - AddMessage( LPGEN("Skipping unrecognizable contact.")); - return INVALID_HANDLE_VALUE; - } - - if (dwUIN < 10000) { - AddMessage( LPGEN("Skipping non-ICQ contact %u."), dwUIN ); - return INVALID_HANDLE_VALUE; - } - - if (HContactFromNumericID( szICQModuleName[ iICQAccount ], "UIN", dwUIN) == INVALID_HANDLE_VALUE) { - DBVARIANT id, nick, group; - id.type = DBVT_DWORD; id.dVal = dwUIN; - if ( strNickname != NULL && strlen(strNickname) > 0 ) - nick.type = DBVT_ASCIIZ, nick.pszVal = strNickname; - else - nick.type = DBVT_DELETED; - group.type = DBVT_ASCIIZ, group.pszVal = strGroupName; - return AddContact(hdlgProgress, szICQModuleName[ iICQAccount ], "UIN", &id, &nick, &group); - } - else { - if ((strNickname != NULL) && (strlen(strNickname) > 0)) - AddMessage( LPGEN("Skipping duplicate ICQ contact %u, %s"), dwUIN, strNickname); - else - AddMessage( LPGEN("Skipping duplicate ICQ contact %u"), dwUIN); - } - - // Failure - return INVALID_HANDLE_VALUE; -} - -BOOL ImportMessage(DWORD dwOffset) -{ - struct TDatMessage *msg = (struct TDatMessage*)(pDat + dwOffset); - struct TDatEntryFooter *footer; - DBEVENTINFO dbei; - HANDLE hContact; - int nUCTOffset; - TIME_ZONE_INFORMATION TimeZoneInformation; - int nHistoryCount = 0; - - // Get timestamp offset. In ICQ, event timestamps are stored - // as UTC + (0-TZ offset). YES! That's the negation of the - // timezone offset, only God and Mirabilis knows why. - GetTimeZoneInformation(&TimeZoneInformation); - nUCTOffset = -TimeZoneInformation.Bias * 60; - - // Ignore messages in 'Deleted' folder - if (msg->filingStatus&FILING_DELETED) - return FALSE; - - // Skip messages from non-icq contacts - if (msg->uin < 10000) { - AddMessage( LPGEN("Ignoring msg from user %d at ofs %d."), msg->uin, dwOffset ); - return FALSE; - } - - // Ignore received messages? - if (( msg->filingStatus & FILING_RECEIVED ) && !( nCustomOptions & IOPT_MSGRECV )) - return FALSE; - - // Ignores sent messages? - if ( !(msg->filingStatus & FILING_RECEIVED) && !( nCustomOptions & IOPT_MSGSENT )) - return FALSE; - - // Check if contact exists in Miranda database - hContact = HistoryImportFindContact(hdlgProgress, szICQModuleName[ iICQAccount ], msg->uin, nCustomOptions&IOPT_ADDUNKNOWN); - if (hContact == INVALID_HANDLE_VALUE) - return FALSE; // Contact couldn't be found/added - - // Convert the event to a Miranda dbevent - footer = (struct TDatEntryFooter*)(pDat + dwOffset + msg->textLen + offsetof(struct TDatMessage, text)); - ZeroMemory(&dbei, sizeof(dbei)); - dbei.cbSize = sizeof(dbei); - dbei.eventType = EVENTTYPE_MESSAGE; - dbei.flags = footer->sent == 1 ? DBEF_SENT : DBEF_READ; - dbei.szModule = szICQModuleName[ iICQAccount ]; - // Convert timestamp - dbei.timestamp = footer->timestamp + nUCTOffset; - dbei.cbBlob = msg->textLen; - dbei.pBlob = (PBYTE)alloca(msg->textLen); - CopyMemory(dbei.pBlob, msg->text, dbei.cbBlob); - dbei.pBlob[dbei.cbBlob - 1] = 0; - - // Check for duplicate entries - if (IsDuplicateEvent(hContact, dbei)) { - nDupes++; - } - else { - if (CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei)) - nMessagesCount++; - } - - return TRUE; -} - -BOOL ImportExtendedMessage(DWORD dwOffset) -{ - struct TDatMessage *msg = (struct TDatMessage*)(pDat + dwOffset); - struct TDatEntryFooter *footer; - DBEVENTINFO dbei; - HANDLE hContact; - int nUCTOffset; - TIME_ZONE_INFORMATION TimeZoneInformation; - int nHistoryCount = 0; - char* pszText = 0; - DWORD dwRichTextOffset = 0; - DWORD wRichTextLength = 0; - DWORD wLength = 0; - BOOL bFreeMe = FALSE; - - // Get timestamp offset. In ICQ, event timestamps are stored - // as UTC + (0-TZ offset). YES! That's the negation of the - // timezone offset, only God and Mirabilis knows why. - GetTimeZoneInformation(&TimeZoneInformation); - nUCTOffset = -TimeZoneInformation.Bias * 60; - - // Ignore messages in 'Deleted' folder - if (msg->filingStatus&FILING_DELETED) - return FALSE; - - // Skip messages from non-icq contacts - if (msg->uin < 10000) { - AddMessage( LPGEN("Ignoring msg from user %d at ofs %d."), msg->uin, dwOffset ); - return FALSE; - } - - // Ignore received messages? - if (( msg->filingStatus & FILING_RECEIVED) && !( nCustomOptions & IOPT_MSGRECV )) - return FALSE; - - // Ignore sent messages? - if ( !( msg->filingStatus & FILING_RECEIVED ) && !( nCustomOptions & IOPT_MSGSENT )) - return FALSE; - - // Check if contact exists in Miranda database - hContact = HistoryImportFindContact(hdlgProgress, szICQModuleName[ iICQAccount ], msg->uin, nCustomOptions&IOPT_ADDUNKNOWN); - if (hContact == INVALID_HANDLE_VALUE) - return FALSE; // Contact couldn't be found/added - - // Find a piece of usable text content - if (msg->textLen <= 1) { - // Skip past the RTF segment - wRichTextLength = *(PWORD)(pDat + dwOffset + 0x2A + msg->textLen + 0x21); - dwRichTextOffset = dwOffset + 0x2A + msg->textLen + 0x23; - - // Use the UTF-8 text segment - wLength = *(PWORD)(pDat + dwRichTextOffset + wRichTextLength); - if (wLength <= 1) { - AddMessage( LPGEN("Ignoring msg with no text from %d ofs %d."), msg->uin, dwOffset ); - return FALSE; - } - pszText = _strdup(pDat + dwRichTextOffset + wRichTextLength + 2); - bFreeMe = TRUE; - mir_utf8decode(pszText, NULL); - wLength = (DWORD)strlen(pszText)+1; - } - else { - // Use the ANSI text segment - wLength = msg->textLen; - pszText = pDat + dwOffset + 0x2A; - } - - // Convert the event to a Miranda dbevent - footer = (struct TDatEntryFooter*)(pDat + dwOffset + msg->textLen + offsetof(struct TDatMessage, text)); - ZeroMemory(&dbei, sizeof(dbei)); - dbei.cbSize = sizeof(dbei); - dbei.eventType = EVENTTYPE_MESSAGE; - dbei.flags = footer->sent == 1 ? DBEF_SENT : DBEF_READ; - dbei.szModule = szICQModuleName[ iICQAccount ]; - // Convert timestamp - dbei.timestamp = footer->timestamp + nUCTOffset; - dbei.cbBlob = wLength; - dbei.pBlob = (PBYTE)calloc(wLength,1); - CopyMemory(dbei.pBlob, pszText, dbei.cbBlob); - dbei.pBlob[dbei.cbBlob - 1] = 0; - - // Check for duplicate entries - if (IsDuplicateEvent(hContact, dbei)) { - nDupes++; - } - else { - if (CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei)) - nMessagesCount++; - } - - free(dbei.pBlob); - if (bFreeMe) - free(pszText); - - return TRUE; -} - -BOOL ImportURLMessage(DWORD dwOffset) -{ - struct TDatMessage *msg = (struct TDatMessage*)(pDat + dwOffset); - struct TDatEntryFooter *footer; - DBEVENTINFO dbei; - HANDLE hContact; - int nUCTOffset; - TIME_ZONE_INFORMATION TimeZoneInformation; - int nHistoryCount = 0; - char *pSeparator; - - // Get timestamp offset. In ICQ, event timestamps are stored - // as UTC + (0-TZ offset). YES! That's the negation of the - // timezone offset, only God and Mirabilis knows why. - GetTimeZoneInformation(&TimeZoneInformation); - nUCTOffset = -TimeZoneInformation.Bias * 60; - - // Ignore URLs in 'Deleted' folder - if (msg->filingStatus&FILING_DELETED) - return FALSE; - - // Skip URLs from non-icq contacts - if (msg->uin < 10000) { - AddMessage( LPGEN("Ignoring msg from user %d at ofs %d."), msg->uin, dwOffset ); - return FALSE; - } - - // Ignore received URLs? - if (( msg->filingStatus & FILING_RECEIVED ) && !( nCustomOptions & IOPT_URLRECV )) - return FALSE; - - // Ignores sent URLs? - if ( !( msg->filingStatus & FILING_RECEIVED ) && !( nCustomOptions & IOPT_URLSENT )) - return FALSE; - - // Check if contact exists in Miranda database - hContact = HistoryImportFindContact(hdlgProgress, szICQModuleName[ iICQAccount ], msg->uin, nCustomOptions&IOPT_ADDUNKNOWN); - if (hContact == INVALID_HANDLE_VALUE) - return FALSE; // Contact couldn't be found/added - - // Convert the event to a Miranda dbevent - footer = (struct TDatEntryFooter*)(pDat + dwOffset + msg->textLen + offsetof(struct TDatMessage, text)); - ZeroMemory(&dbei, sizeof(dbei)); - dbei.cbSize = sizeof(dbei); - dbei.eventType = EVENTTYPE_URL; - dbei.flags = footer->sent == 1 ? DBEF_SENT : DBEF_READ; - dbei.szModule = szICQModuleName[ iICQAccount ]; - // Convert timestamp - dbei.timestamp = footer->timestamp + nUCTOffset; - dbei.cbBlob = msg->textLen; - dbei.pBlob = (PBYTE)alloca(msg->textLen); - CopyMemory(dbei.pBlob, msg->text, dbei.cbBlob); - dbei.pBlob[dbei.cbBlob - 1] = 0; - // Separate URL and description - pSeparator = strchr((char*)dbei.pBlob, 0xFE); - if (pSeparator != NULL) - *pSeparator = 0; - - // Check for duplicate entries - if (IsDuplicateEvent(hContact, dbei)) - nDupes++; - else if (CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei)) - nMessagesCount++; - - return TRUE; -} - -BOOL ImportEvent(DWORD dwOffset) -{ - struct TDatMessage *msg = (struct TDatMessage*)(pDat + dwOffset); - - // Events have IDs > 2000 - if (msg->hdr.entryId < 2001) { - AddMessage( LPGEN("Skipping event with ID < 2001.")); - return FALSE; - } - - // Separate code paths based on the event signature - switch (msg->hdr.subType) { - - case SUBTYPE_MESSAGE: // All kinds of messages - switch (msg->type) { - case 1: // Normal message - if ((nCustomOptions&IOPT_MSGRECV) || (nCustomOptions&IOPT_MSGSENT)) { - return ImportMessage(dwOffset); - } - break; - - case 4: // URL - if ((nCustomOptions&IOPT_URLSENT) || (nCustomOptions&IOPT_URLRECV)) { - return ImportURLMessage(dwOffset); - } - break; - - case 6: // Request for authorization - #ifdef _LOGGING - AddMessage( LPGEN("Skipping 'Request for auth.' msg, ofs %d."), dwOffset ); - #endif - break; - - case 7: // Authorization request denied - #ifdef _LOGGING - AddMessage( LPGEN("Skipping 'Auth. denied' msg, ofs %d."), dwOffset ); - #endif - break; - - case 8: // Authorization request accepted - #ifdef _LOGGING - AddMessage( LPGEN("Skipping 'Auth. accepted' msg, ofs %d."), dwOffset ); - #endif - break; - - case 9: // System message - #ifdef _LOGGING - AddMessage( LPGEN("Skipping 'System message', ofs %d."), dwOffset ); - #endif - break; - - case 12: // You were added - #ifdef _LOGGING - AddMessage( LPGEN("Skipping 'You were added' msg, ofs %d."), dwOffset ); - #endif - break; - - case 13: // WWWPager ? - #ifdef _LOGGING - AddMessage( LPGEN("Skipping 'WWW Pager' msg, ofs %d."), dwOffset ); - #endif - break; - - case 14: // Email Express ? - #ifdef _LOGGING - AddMessage( LPGEN("Skipping 'Email Express' msg, ofs %d."), dwOffset ); - #endif - break; - - case 19: // Contact list - #ifdef _LOGGING - AddMessage( LPGEN("Skipping 'Contact' msg, ofs %d."), dwOffset ); - #endif - break; - - case 21: // Phonecall request? - #ifdef _LOGGING - AddMessage( LPGEN("Skipping 'Phonecall' msg (?), ofs %d."), dwOffset ); - #endif - break; - - case 26: // SMS request? - #ifdef _LOGGING - AddMessage( LPGEN("Skipping 'SMS' msg (?), ofs %d."), dwOffset ); - #endif - break; - - case 29: // Active list invitation ?? - #ifdef _LOGGING - AddMessage( LPGEN("Skipping 29 msg, ofs %d."), dwOffset ); - #endif - break; - - case 30: // Birthday reminder - #ifdef _LOGGING - AddMessage( LPGEN("Skipping 'Birthday' msg (?), ofs %d."), dwOffset ); - #endif - break; - - case 32: // Unknown (Tomer) - #ifdef _LOGGING - AddMessage( LPGEN("Skipping 32 msg, ofs %d."), dwOffset ); - #endif - break; - - default: - AddMessage( LPGEN("Skipping unknown 0xE0 subtype (%d), ofs %d."), msg->type, dwOffset ); - - #ifdef _LOGGING - { // If this is a debug build, dump entry to disk - FILE *stream; - DWORD dwSize = *(PDWORD)(pDat + dwOffset); - wsprintfA(str, "import_unknown_E0subtype_%u-%u.bin", msg->type, dwOffset); - stream = fopen(str, "w"); - fwrite(pDat + dwOffset, 1, dwSize, stream); - fclose(stream); - } - #endif - - return FALSE; - } - break; - - case SUBTYPE_CHATREQUEST: // 0xE1 - #ifdef _LOGGING - if (nImportOption != IMPORT_CONTACTS) - AddMessage( LPGEN("Skipping 'Chat request' msg, ofs %d."), dwOffset ); - #endif - break; - - case SUBTYPE_FILEREQUEST: // 0xE2 - #ifdef _LOGGING - if (nImportOption != IMPORT_CONTACTS) - AddMessage( LPGEN("Skipping file message offset %d."), dwOffset ); - #endif - break; - - case 0xE3: // External (IPhone, Battlecom) Maybe general voice calls? - #ifdef _LOGGING - if (nImportOption != IMPORT_CONTACTS) - AddMessage( LPGEN("Skipping message type 0xE3 at offset %d."), dwOffset ); - #endif - break; - - case 0xE4: // My details - break; - case 0xE5: // Contact - break; - case 0xE6: // Reminder - break; - case 0xE7: // Addressbook - break; - case 0xEC: // Voice message - break; - case 0xED: // Unknown, something to do with chatting and .CHT files - // if (importHistory) { - // wsprintf(str, "Skipping message type 0xED at offset %d.", dwOffset); - // AddMessage( LPGEN(str); - // } - break; - case 0xEE: // Note - break; - case 0xEF: // Event folder - break; - // case 0xF0: // Unknown - // if (importHistory) { - // wsprintf(str, "Skipping message type 0xF0 at offset %d.", dwOffset); - // AddMessage( LPGEN(str); - // } - // break; - case 0xF1: // Server list - break; - // case 0xF6: // Unknown - // if (importHistory) { - // wsprintf(str, "Skipping message type 0xF6 at offset %d.", dwOffset); - // AddMessage( LPGEN(str); - // } - // break; - case 0x50: // Extended message, ICQ 2000a+? - if (nImportOption != IMPORT_CONTACTS) { - return ImportExtendedMessage(dwOffset); - } - break; - - case 0xA0: // URL message type 2 - if (nImportOption != IMPORT_CONTACTS) { - if ((msg->filingStatus&FILING_RECEIVED) || (nCustomOptions&IOPT_URLRECV)) { - return ImportURLMessage(dwOffset); - } - } - break; - - default: - if (nImportOption != IMPORT_CONTACTS) { - AddMessage( LPGEN("Skipping unknown event type %d at offset %d."), msg->hdr.subType, dwOffset ); - -#ifdef _LOGGING - { // If this is a debug build, dump entry to disk - FILE *stream; - DWORD dwSize; - dwSize = *(PDWORD)(pDat + dwOffset); - wsprintfA(str, "import_unknown_eventtype_%u-%u.bin", msg->hdr.subType, dwOffset); - stream = fopen(str, "w"); - fwrite(pDat + dwOffset, 1, dwSize, stream); - fclose(stream); - } -#endif - - } - break; - } - - return FALSE; -} - - -static void MirabilisImport(HWND hdlgProgressWnd) -{ - HANDLE hIdx, hDat, hIdxMapping, hDatMapping; - DWORD i, ofs, highestIndexEntry; - TCHAR datFilename[MAX_PATH]; - MSG msg; - DWORD dwTimer; - - - int status = 0; - hdlgProgress = hdlgProgressWnd; - nDupes = nContactsCount = nMessagesCount = 0; - - SetProgress(0); - lstrcpy(datFilename, importFile); - { - TCHAR* str2; - str2 = _tcsrchr(datFilename,'.'); - if ( str2 != NULL ) - lstrcpy(str2, _T(".dat")); - } - - hIdx = CreateFile(importFile, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - if (hIdx == INVALID_HANDLE_VALUE) { - AddMessage( LPGEN("Failed to open index file")); - AddMessage( LPGEN("Import aborted")); - SetProgress(100); - return; - } - - hDat = CreateFile(datFilename, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - if (hDat == INVALID_HANDLE_VALUE) { - AddMessage( LPGEN("Failed to open database file")); - AddMessage( LPGEN("Import aborted")); - SetProgress(100); - return; - } - - // Creating file mappings - hIdxMapping = CreateFileMapping(hIdx, NULL, PAGE_READONLY, 0, 0, NULL); - hDatMapping = CreateFileMapping(hDat, NULL, PAGE_READONLY, 0, 0, NULL); - - // Mapping views of files - pIdx = (PBYTE)MapViewOfFile(hIdxMapping, FILE_MAP_READ, 0, 0, 0); - pDat = (PBYTE)MapViewOfFile(hDatMapping, FILE_MAP_READ, 0, 0, 0); - - // Is this a supported format? - if (GetDBVersion()) { - AddMessage( "" ); - - highestIndexEntry = GetHighestIndexEntry(); - - // Import groups - nGroupsCount = ImportGroups(); - if (nGroupsCount < 0) { - AddMessage( LPGEN("Group import was not completed.")); - nGroupsCount = 0; - } - AddMessage( "" ); - - // Start benchmark timer - dwTimer = time(NULL); - - if ( !IsProtocolLoaded( szICQModuleName[iICQAccount] )) { - AddMessage( LPGEN("ICQ account is not installed.")); - AddMessage( LPGEN("No ICQ contacts or history will be imported.")); - AddMessage( "" ); - } - else { - // Configure database for fast writing - CallService(MS_DB_SETSAFETYMODE, FALSE, 0); - - // Import contacts - AddMessage( LPGEN("Importing contacts")); - for (i = 2001; i <= highestIndexEntry; i++) { //event ids start at 2001 - if (!(i%10)) { - if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - if (!(i%100)) - SetProgress(100 * (i - 2001) / (highestIndexEntry - 2001)); - - ofs = GetIdDatOfs(i); - if (ofs != 0) { - if (ImportContact(ofs) != INVALID_HANDLE_VALUE) - nContactsCount++; - } - } - AddMessage( "" ); - - // Import history - if (nImportOption != IMPORT_CONTACTS) { - AddMessage( LPGEN("Importing history (this may take a while)")); - for (i = 2001; i <= highestIndexEntry; i++) { //event ids start at 2001 - if (!(i%10)) { - if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - - if (!(i%100)) - SetProgress(100 * (i - 2001) / (highestIndexEntry - 2001)); - - ofs = GetIdDatOfs(i); - if (ofs != 0) ImportEvent(ofs); - } - AddMessage( "" ); - } - - // Restore database writing mode - CallService(MS_DB_SETSAFETYMODE, TRUE, 0); - } - - dwTimer = time(NULL) - dwTimer; - - AddMessage( LPGEN("Import completed in %d seconds."), dwTimer ); - SetProgress(100); - AddMessage( LPGEN("Added %d contacts and %d groups."), nContactsCount, nGroupsCount ); - if ( nImportOption != IMPORT_CONTACTS ) - AddMessage( LPGEN("Added %d events and skipped %d duplicates."), nMessagesCount, nDupes ); - } - - UnmapViewOfFile(pDat); - UnmapViewOfFile(pIdx); - CloseHandle(hDatMapping); - CloseHandle(hIdxMapping); - CloseHandle(hDat); - CloseHandle(hIdx); -} diff --git a/plugins/Dbx_mmap_SA/Import_SA/mirabilis.cpp b/plugins/Dbx_mmap_SA/Import_SA/mirabilis.cpp new file mode 100644 index 0000000000..130843205e --- /dev/null +++ b/plugins/Dbx_mmap_SA/Import_SA/mirabilis.cpp @@ -0,0 +1,1492 @@ +/* + +Import plugin for Miranda IM + +Copyright (C) 2001-2005 Martin Öberg, Richard Hughes, Roland Rabien & Tristan Van de Vreede + +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. + +*/ + +// ============== +// == INCLUDES == +// ============== + +#include "import.h" +#include "mirabilis.h" + +BOOL IsDuplicateEvent(HANDLE hContact, DBEVENTINFO dbei); +BOOL IsProtocolLoaded(char* pszProtocolName); +HANDLE HContactFromNumericID(char* pszProtoName, char* pszSetting, DWORD dwID); +HANDLE AddContact(HWND hdlgProgress, char* pszProtoName, char* pszUniqueSetting, DBVARIANT* id, DBVARIANT* nick, DBVARIANT* group); + +// ==================== +// ==================== +// == IMPLEMENTATION == +// ==================== +// ==================== + +static void SearchForDatabases(HWND hdlg, const TCHAR *dbPath, const TCHAR *type) +{ + HANDLE hFind; + WIN32_FIND_DATA fd; + TCHAR szSearchPath[MAX_PATH]; + TCHAR szRootName[MAX_PATH],*str2; + + int i; + + wsprintf(szSearchPath, _T("%s\\*.idx"), dbPath); + hFind=FindFirstFile(szSearchPath,&fd); + if(hFind!=INVALID_HANDLE_VALUE) { + do { + lstrcpy(szRootName,fd.cFileName); + str2=_tcsrchr(szRootName,'.'); + if(str2!=NULL) *str2=0; + if(lstrlen(szRootName)>3 && !lstrcmpi(szRootName+lstrlen(szRootName)-3,_T("tmp"))) + continue; + lstrcat(szRootName,type); + i=SendDlgItemMessage(hdlg,IDC_LIST,LB_ADDSTRING,0,(LPARAM)szRootName); + str2 = (TCHAR*)mir_alloc((lstrlen(dbPath) + 2+lstrlen(fd.cFileName))*sizeof(TCHAR)); + wsprintf(str2, _T("%s\\%s"), dbPath, fd.cFileName); + SendDlgItemMessage(hdlg,IDC_LIST,LB_SETITEMDATA,i,(LPARAM)str2); + } + while( FindNextFile( hFind, &fd )); + + FindClose(hFind); + } +} + +INT_PTR CALLBACK MirabilisPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam) +{ + switch(message) { + case WM_INITDIALOG: + { + HKEY hKey; + LONG lResult; + int i; + TranslateDialogDefault(hdlg); + if (ERROR_SUCCESS != (lResult = RegOpenKeyEx(HKEY_CURRENT_USER, _T("Software\\Mirabilis\\ICQ\\DefaultPrefs"), 0, KEY_QUERY_VALUE, &hKey))) + lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\Mirabilis\\ICQ\\DefaultPrefs"), 0, KEY_QUERY_VALUE, &hKey); + + if (lResult == ERROR_SUCCESS) { + TCHAR dbPath[MAX_PATH]; + DWORD cch; + cch=sizeof(dbPath); + if(ERROR_SUCCESS==RegQueryValueEx(hKey,_T("New Database"),NULL,NULL,(LPBYTE)dbPath,&cch)) + SearchForDatabases(hdlg,dbPath,_T(" (99a)")); + cch=sizeof(dbPath); + if(ERROR_SUCCESS==RegQueryValueEx(hKey,_T("99b Database"),NULL,NULL,(LPBYTE)dbPath,&cch)) + SearchForDatabases(hdlg,dbPath,_T(" (99b)")); + cch=sizeof(dbPath); + if(ERROR_SUCCESS==RegQueryValueEx(hKey,_T("2000a Database"),NULL,NULL,(LPBYTE)dbPath,&cch)) + SearchForDatabases(hdlg,dbPath,_T(" (2000a)")); + cch=sizeof(dbPath); + if(ERROR_SUCCESS==RegQueryValueEx(hKey,_T("2000b Database"),NULL,NULL,(LPBYTE)dbPath,&cch)) + SearchForDatabases(hdlg,dbPath,_T(" (2000b)")); + cch=sizeof(dbPath); + if(ERROR_SUCCESS==RegQueryValueEx(hKey,_T("2001a Database"),NULL,NULL,(LPBYTE)dbPath,&cch)) + SearchForDatabases(hdlg,dbPath,_T(" (2001a)")); + cch=sizeof(dbPath); + if(ERROR_SUCCESS==RegQueryValueEx(hKey,_T("2001b Database"),NULL,NULL,(LPBYTE)dbPath,&cch)) + SearchForDatabases(hdlg,dbPath,_T(" (2001b)")); + cch=sizeof(dbPath); + if(ERROR_SUCCESS==RegQueryValueEx(hKey,_T("2002a Database"),NULL,NULL,(LPBYTE)dbPath,&cch)) + SearchForDatabases(hdlg,dbPath,_T(" (2002a)")); + cch=sizeof(dbPath); + if(ERROR_SUCCESS==RegQueryValueEx(hKey,_T("2003a Database"),NULL,NULL,(LPBYTE)dbPath,&cch)) + SearchForDatabases(hdlg,dbPath,_T(" (2003a)")); + } + + for (i = 0; i < cICQAccounts; i++) + { + SendDlgItemMessage(hdlg, IDC_MIRABILISACCOUNT, CB_ADDSTRING, 0, (LPARAM)tszICQAccountName[i]); + } + SendDlgItemMessage(hdlg, IDC_MIRABILISACCOUNT, CB_SETCURSEL, 0, 0); + + SetTimer(hdlg,1,2000,NULL); + SendMessage(hdlg,WM_TIMER,0,0); + return TRUE; + } + case WM_TIMER: + { HANDLE hMirabilisMutex; + hMirabilisMutex=OpenMutexA(MUTEX_ALL_ACCESS,FALSE,"Mirabilis ICQ Mutex"); + if(hMirabilisMutex!=NULL) { + CloseHandle(hMirabilisMutex); + ShowWindow(GetDlgItem(hdlg,IDC_MIRABILISRUNNING),SW_SHOW); + } + else ShowWindow(GetDlgItem(hdlg,IDC_MIRABILISRUNNING),SW_HIDE); + } + break; + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDC_BACK: + PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_IMPORTTYPE,(LPARAM)ImportTypePageProc); + break; + case IDOK: + { TCHAR filename[MAX_PATH]; + GetDlgItemText(hdlg,IDC_FILENAME,filename,SIZEOF(filename)); + if(_taccess(filename,4)) { + MessageBox(hdlg,TranslateT("The given file does not exist. Please check that you have entered the name correctly."),TranslateT("Mirabilis Import"),MB_OK); + break; + } + lstrcpy(importFile,filename); + iICQAccount = SendDlgItemMessage(hdlg, IDC_MIRABILISACCOUNT, CB_GETCURSEL, 0, 0); + PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_OPTIONS,(LPARAM)MirabilisOptionsPageProc); + break; + } + case IDCANCEL: + PostMessage(GetParent(hdlg),WM_CLOSE,0,0); + break; + case IDC_LIST: + if(HIWORD(wParam)==LBN_SELCHANGE) { + int sel=SendDlgItemMessage(hdlg,IDC_LIST,LB_GETCURSEL,0,0); + if(sel==LB_ERR) break; + SetDlgItemText(hdlg,IDC_FILENAME,(TCHAR*)SendDlgItemMessage(hdlg,IDC_LIST,LB_GETITEMDATA,sel,0)); + } + break; + case IDC_OTHER: + { OPENFILENAME ofn; + TCHAR str[MAX_PATH], text[256]; + int index; + + // TranslateTS doesnt translate \0 separated strings + index = mir_sntprintf(text, 64, _T("%s (*.idx)"), TranslateT("Mirabilis ICQ database indexes")) + 1; + _tcscpy(text + index, _T("*.idx")); index += 6; + index += mir_sntprintf(text + index, 64, _T("%s (*.*)"), TranslateT("All Files")) + 1; + _tcscpy(text + index, _T("*.*")); index += 4; + text[index] = 0; + + GetDlgItemText(hdlg,IDC_FILENAME,str,SIZEOF(str)); + ZeroMemory(&ofn, sizeof(ofn)); + ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; + ofn.hwndOwner = hdlg; + ofn.lpstrFilter = text; + ofn.lpstrFile = str; + ofn.Flags = OFN_FILEMUSTEXIST | OFN_EXPLORER | OFN_NOCHANGEDIR | OFN_DONTADDTORECENT; + ofn.nMaxFile = SIZEOF(str); + ofn.lpstrDefExt = _T("idx"); + if(GetOpenFileName(&ofn)) + SetDlgItemText(hdlg,IDC_FILENAME,str); + break; + } + } + break; + + case WM_DESTROY: + { int i; + for(i=SendDlgItemMessage(hdlg,IDC_LIST,LB_GETCOUNT,0,0)-1;i>=0;i--) + mir_free((char*)SendDlgItemMessage(hdlg,IDC_LIST,LB_GETITEMDATA,i,0)); + break; + } + } + return FALSE; +} + + +INT_PTR CALLBACK MirabilisOptionsPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam) +{ + switch(message) { + case WM_INITDIALOG: + TranslateDialogDefault(hdlg); + EnableWindow(GetDlgItem(hdlg, IDC_RADIO_ALL), TRUE); + EnableWindow(GetDlgItem(hdlg, IDC_STATIC_ALL), TRUE); + EnableWindow(GetDlgItem(hdlg, IDC_RADIO_CONTACTS), TRUE); + EnableWindow(GetDlgItem(hdlg, IDC_STATIC_CONTACTS), TRUE); + CheckDlgButton(hdlg, IDC_RADIO_ALL, BST_CHECKED); + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDC_BACK: + PostMessage(GetParent(hdlg), WIZM_GOTOPAGE, IDD_MIRABILISDB, (LPARAM)MirabilisPageProc); + break; + case IDOK: + if (IsDlgButtonChecked(hdlg, IDC_RADIO_ALL)) { + DoImport = MirabilisImport; + nImportOption = IMPORT_ALL; + nCustomOptions = IOPT_MSGSENT|IOPT_MSGRECV|IOPT_URLSENT|IOPT_URLRECV; + PostMessage(GetParent(hdlg), WIZM_GOTOPAGE, IDD_PROGRESS, (LPARAM)ProgressPageProc); + break; + } + if (IsDlgButtonChecked(hdlg, IDC_RADIO_CONTACTS)) { + DoImport = MirabilisImport; + nImportOption = IMPORT_CONTACTS; + nCustomOptions = 0; + PostMessage(GetParent(hdlg), WIZM_GOTOPAGE, IDD_PROGRESS, (LPARAM)ProgressPageProc); + break; + } + break; + case IDCANCEL: + PostMessage(GetParent(hdlg), WM_CLOSE, 0, 0); + break; + } + break; + } + + return FALSE; +} + +static int GetHighestIndexEntry(void) +{ + struct TIdxIndexEntry *entry; + DWORD ofs; + + ofs=*(PDWORD)(pIdx+12); + for (;;) { + entry=(struct TIdxIndexEntry*)(pIdx+ofs); + if(entry->entryIdLow==(DWORD)-2) return ((struct TIdxDatEntry*)entry)->entryId; + if(entry->ofsHigher>=0xF0000000) ofs=entry->ofsInHere; + else ofs=entry->ofsHigher; + } +} + +static int GetIdDatOfs(DWORD id) +{ + struct TIdxIndexEntry *entry; + DWORD ofs = *(PDWORD)(pIdx+12); + for (;;) { + entry=(struct TIdxIndexEntry*)(pIdx+ofs); + if(entry->entryIdLow==(DWORD)-2) { + if(entry->entryIdHigh==id) return ((struct TIdxDatEntry*)entry)->datOfs; + return 0; + } + if(identryIdLow) ofs=entry->ofsLower; + else if(entry->ofsHigher<0xF0000000 && id>=entry->entryIdHigh) ofs=entry->ofsHigher; + else ofs=entry->ofsInHere; + } + return 0; +} + +static int GetDatEntryType(DWORD ofs) +{ + return *(int*)(pDat+ofs+4); +} + +DWORD GetDBVersion() +{ + dwDBVersion = *(PDWORD)(pIdx+16); + + switch (dwDBVersion) { + case DBV99A: + AddMessage( LPGEN("This looks like a ICQ 99a database.")); + break; + case DBV99B: + AddMessage( LPGEN("This looks like a ICQ 99b database.")); + break; + case DBV2000A: + AddMessage( LPGEN("This looks like a ICQ 2000a database.")); + break; + case DBV2000B: + AddMessage( LPGEN("This looks like a ICQ 2000b database.")); + break; + case DBV2001A: + AddMessage( LPGEN("This looks like a ICQ 2001, 2002 or 2003a database.")); + break; + default: + AddMessage( LPGEN("This database is an unknown version.")); + return 0; + } + + return dwDBVersion; +} + +int GetEntryVersion(WORD wSeparatorValue) +{ + int nVersion; + + if (wSeparatorValue < ENTRYV99A) + nVersion = 0; // Cannot handle ICQ98 contacts + else if ((wSeparatorValue >= ENTRYV99A) && (wSeparatorValue < ENTRYV99B)) + nVersion = ENTRYV99A; + else if ((wSeparatorValue >= ENTRYV99B) && (wSeparatorValue < ENTRYV2000A)) + nVersion = ENTRYV99B; + else if ((wSeparatorValue >= ENTRYV2000A) && (wSeparatorValue < ENTRYV2000B)) + nVersion = ENTRYV2000A; + else if ((wSeparatorValue >= ENTRYV2000B) && (wSeparatorValue < ENTRYV2001A)) + nVersion = ENTRYV2000B; + else if ((wSeparatorValue >= ENTRYV2001A) && (wSeparatorValue < ENTRYV2001B)) + nVersion = ENTRYV2001A; + else if ((wSeparatorValue >= ENTRYV2001B) && (wSeparatorValue < ENTRYV2002A)) + nVersion = ENTRYV2001B; + else if (wSeparatorValue >= ENTRYV2002A) + nVersion = ENTRYV2002A; + else + nVersion = ENTRYVUNKNOWN; // Just in case... Skip undocumented contact versions + + return nVersion; +} + +DWORD ReadSubList(DWORD dwOffset) +{ + DWORD dwSubType, dwProperties, n; + + #ifdef _LOGGING + AddMessage( LPGEN("Attempting to parse sub list at offset %u."), dwOffset); + #endif + + // Check number of properties in sub list + dwProperties = *(PDWORD)(pDat+dwOffset); + dwOffset+=4; + + // Check sub list type + dwSubType = *(PBYTE)(pDat+dwOffset); + dwOffset+=1; + + switch (dwSubType){ + case 0x6B: + for(n=0;n 1) + return 6 + (char*)(pDat + dwOffset); + + break; + } + else + // Skip to next group + dwOffset += *(PWORD)(pDat + dwOffset + 4) + 12; + } + break; + + case DBV2000A: + case DBV2000B: + case DBV2001A: + for (n = 0; n < dwGroups; n++) { + if (tmpOfs = ReadPropertyBlock(dwOffset, "GroupID", &nSearchResult)) { + if (nSearchResult) { + if (dwGroupID == *(PDWORD)(pDat + tmpOfs + 1)) { + strGroupName = 3 + (char*)(pDat + ReadPropertyBlock(dwOffset, "GroupName", &nSearchResult)); + if (nSearchResult) { + if ((DWORD)*(strGroupName - 2) > 1) + return strGroupName; + break; + } } } } + + // Skip to next group + if ( dwOffset != ReadPropertyBlock(dwOffset, NULL, NULL)) + break; + } + break; + } + + // The GroupID was not found, or it was found + // but the group did not have a name, or there + // was an error during parsing. + return 0; +} + +// ------------------------------------------------ +// Scans a group list and adds all found groups to +// the Miranda contact list +// ------------------------------------------------ +// dwOffset must point to the number of entries in +// the following group list. +// Returns the number of added groups, or -1 if an error +// occurred + +int ImportGroups() +{ + DWORD dwGroups, n, tmpOfs, dwOffset; + int nImported = 0; + int nSearchResult, nFormat; + WORD wSeparatorValue; + + if (!(dwOffset = FindMyDetails())) { + AddMessage( LPGEN("ERROR: Failed to find owner information.")); + return -1; + } + + wSeparatorValue = *(PWORD)(pDat + dwOffset + 0x1c); + nFormat = GetEntryVersion(wSeparatorValue); + + dwGroupListOfs = dwOffset = FindGroupList(dwOffset); + if (!dwOffset) { + AddMessage( LPGEN("ERROR: Failed to find contact list groups.")); + #ifdef _LOGGING + { // If this is a debug build, dump MyDetails block to disk + FILE *stream; + DWORD dwSize; + dwOffset = FindMyDetails(); + dwSize = *(PDWORD)(pDat + dwOffset); + stream = fopen("import_grouplist_dump.bin", "w"); + fwrite(pDat + dwOffset, 1, dwSize, stream); + fclose(stream); + } + #endif + return -1; + } + + // Check number of groups + dwGroups = *(PDWORD)(pDat + dwOffset); + if (dwGroups > 0) + AddMessage( LPGEN("Importing groups.")); + else { + AddMessage( LPGEN("This database does not contain any contact groups.")); + return 0; + } + + dwOffset += 4; + + // Import all groups with a name + switch (nFormat) { + case ENTRYV99A: + case ENTRYV99B: + for (n = 0; n < dwGroups; n++) { + if (*(PWORD)(pDat+dwOffset+4) > 1) { + if ( CreateGroup(DBVT_ASCIIZ, (char*)(pDat + dwOffset) + 6, NULL )) + nImported++; + dwOffset += *(PWORD)(pDat + dwOffset + 4) + 12; + } } + break; + + case ENTRYV2000A: + case ENTRYV2000B: + case ENTRYV2001A: + case ENTRYV2001B: + case ENTRYV2002A: + for (n = 0; n < dwGroups; n++) { + if (tmpOfs = ReadPropertyBlock(dwOffset, "GroupName", &nSearchResult)) { + if (nSearchResult) { + if (CreateGroup( DBVT_ASCIIZ, (char*)(pDat + tmpOfs + 3), NULL )) + nImported++; + } } + + dwOffset = ReadPropertyBlock(dwOffset, NULL, NULL); + if (!dwOffset) { + AddMessage( LPGEN("ERROR: An error occurred while importing groups.")); + AddMessage( LPGEN("All groups may not have not been imported.")); + #ifdef _LOGGING + { // If this is a debug build, dump MyDetails block to disk + FILE *stream; + DWORD dwSize; + dwOffset = FindMyDetails(); + dwSize = *(PDWORD)(pDat + dwOffset); + stream = fopen("import_grouplist_dump.bin", "w"); + fwrite(pDat + dwOffset, 1, dwSize, stream); + fclose(stream); + } + #endif + return -1; + } } + break; + + default: + return -1; + } + + return nImported; +} + +// Imports the contact at offset dwOffset +// Returns the HANDLE of the Miranda contact +// or INVALID_HANDLE_VALUE on failure + +HANDLE ImportContact(DWORD dwOffset) +{ + int nContactVersion, nSearchResult; + BYTE Status; + WORD wSeparatorValue; + DWORD dwGroup, dwUIN = 0, tmpOfs = 0; + char *strNickname = 0, *strGroupName = 0; + + if (*(int*)(pDat + dwOffset + 4) != DATENTRY_CONTACT) + return INVALID_HANDLE_VALUE; + + if (*(int*)(pDat + dwOffset + 0x1e) != 'USER') + return INVALID_HANDLE_VALUE; + + #ifdef _LOGGING + { // If this is a debug build, dump contact to disk + FILE *stream; + DWORD dwSize; + dwSize = *(PDWORD)(pDat + dwOffset); + stream = fopen("import_last_contact.bin", "w"); + fwrite(pDat + dwOffset, 1, dwSize, stream); + fclose(stream); + } + #endif + + Status = *(pDat + dwOffset + 0x22); + wSeparatorValue = *(PWORD)(pDat + dwOffset + 0x1c); + nContactVersion = GetEntryVersion(wSeparatorValue); + + dwGroup = *(PDWORD)(pDat + dwOffset + 0x26); + if (dwGroup >= 1000) + strGroupName = GetGroupName(dwGroup); + + if (Status == 5) + return INVALID_HANDLE_VALUE; // Skip deleted contacts + + if ((Status != 2) && (Status != 3)) { + AddMessage( LPGEN("Skipping inactive contact.")); + return INVALID_HANDLE_VALUE; + } + + if ((nContactVersion < ENTRYV99A) || (nContactVersion == 0)) { + AddMessage( LPGEN("Skipping contact with unsupported version.")); + return INVALID_HANDLE_VALUE; + } + + switch(nContactVersion){ + case ENTRYV99A: + if (!(dwOffset = ReadWavList(dwOffset + 0x54))) return INVALID_HANDLE_VALUE; + if (!(dwOffset = ReadPropertyBlock(dwOffset + 0x26, NULL, NULL))) return INVALID_HANDLE_VALUE; + // Check for custom nickname + if (*(PWORD)(pDat + dwOffset) > 1) strNickname = (char*)(dwOffset + pDat + 2); + // Find UIN + dwOffset += *(PWORD)(pDat + dwOffset) + 2; // Custom nick name + dwOffset += *(PWORD)(pDat + dwOffset) + 2; // Nick name + dwOffset += *(PWORD)(pDat + dwOffset) + 2; // First name + dwOffset += *(PWORD)(pDat + dwOffset) + 2; // Last name + dwOffset += *(PWORD)(pDat + dwOffset) + 2; // E-mail + dwUIN = *(PDWORD)(pDat + dwOffset); // UIN + break; + + case ENTRYV99B: + case ENTRYV2000A: + case ENTRYV2000B: + if (!(dwOffset = ReadWavList(dwOffset + 0x2C))) return INVALID_HANDLE_VALUE; + tmpOfs = ReadPropertyBlockList(dwOffset + 0x02, "UIN", &nSearchResult); + if (nSearchResult) dwUIN = *(PDWORD)(pDat + tmpOfs + 1); + tmpOfs = ReadPropertyBlockList(dwOffset + 0x02, "MyDefinedHandle", &nSearchResult); + if (nSearchResult) strNickname = (char*)(tmpOfs + pDat + 3); + break; + + case ENTRYV2001A: + case ENTRYV2001B: + tmpOfs = ReadPropertyBlockList(dwOffset + 0x2C, "MyDefinedHandle", &nSearchResult); + if (nSearchResult) strNickname = (char*)(tmpOfs + pDat + 3); + tmpOfs = ReadPropertyBlockList(dwOffset + 0x2C, "UIN", &nSearchResult); + if (nSearchResult) dwUIN = *(PDWORD)(pDat + tmpOfs + 1); + break; + + case ENTRYV2002A: + tmpOfs = ReadPropertyBlockList(dwOffset + 0x32, "MyDefinedHandle", &nSearchResult); + if (nSearchResult) strNickname = (char*)(tmpOfs + pDat + 3); + tmpOfs = ReadPropertyBlockList(dwOffset + 0x32, "UIN", &nSearchResult); + if (nSearchResult) dwUIN = *(PDWORD)(pDat + tmpOfs + 1); + break; + } + + if (!dwUIN) { + AddMessage( LPGEN("Skipping unrecognizable contact.")); + return INVALID_HANDLE_VALUE; + } + + if (dwUIN < 10000) { + AddMessage( LPGEN("Skipping non-ICQ contact %u."), dwUIN ); + return INVALID_HANDLE_VALUE; + } + + if (HContactFromNumericID( szICQModuleName[ iICQAccount ], "UIN", dwUIN) == INVALID_HANDLE_VALUE) { + DBVARIANT id, nick, group; + id.type = DBVT_DWORD; id.dVal = dwUIN; + if ( strNickname != NULL && strlen(strNickname) > 0 ) + nick.type = DBVT_ASCIIZ, nick.pszVal = strNickname; + else + nick.type = DBVT_DELETED; + group.type = DBVT_ASCIIZ, group.pszVal = strGroupName; + return AddContact(hdlgProgress, szICQModuleName[ iICQAccount ], "UIN", &id, &nick, &group); + } + else { + if ((strNickname != NULL) && (strlen(strNickname) > 0)) + AddMessage( LPGEN("Skipping duplicate ICQ contact %u, %s"), dwUIN, strNickname); + else + AddMessage( LPGEN("Skipping duplicate ICQ contact %u"), dwUIN); + } + + // Failure + return INVALID_HANDLE_VALUE; +} + +BOOL ImportMessage(DWORD dwOffset) +{ + struct TDatMessage *msg = (struct TDatMessage*)(pDat + dwOffset); + struct TDatEntryFooter *footer; + DBEVENTINFO dbei; + HANDLE hContact; + int nUCTOffset; + TIME_ZONE_INFORMATION TimeZoneInformation; + int nHistoryCount = 0; + + // Get timestamp offset. In ICQ, event timestamps are stored + // as UTC + (0-TZ offset). YES! That's the negation of the + // timezone offset, only God and Mirabilis knows why. + GetTimeZoneInformation(&TimeZoneInformation); + nUCTOffset = -TimeZoneInformation.Bias * 60; + + // Ignore messages in 'Deleted' folder + if (msg->filingStatus&FILING_DELETED) + return FALSE; + + // Skip messages from non-icq contacts + if (msg->uin < 10000) { + AddMessage( LPGEN("Ignoring msg from user %d at ofs %d."), msg->uin, dwOffset ); + return FALSE; + } + + // Ignore received messages? + if (( msg->filingStatus & FILING_RECEIVED ) && !( nCustomOptions & IOPT_MSGRECV )) + return FALSE; + + // Ignores sent messages? + if ( !(msg->filingStatus & FILING_RECEIVED) && !( nCustomOptions & IOPT_MSGSENT )) + return FALSE; + + // Check if contact exists in Miranda database + hContact = HistoryImportFindContact(hdlgProgress, szICQModuleName[ iICQAccount ], msg->uin, nCustomOptions&IOPT_ADDUNKNOWN); + if (hContact == INVALID_HANDLE_VALUE) + return FALSE; // Contact couldn't be found/added + + // Convert the event to a Miranda dbevent + footer = (struct TDatEntryFooter*)(pDat + dwOffset + msg->textLen + offsetof(struct TDatMessage, text)); + ZeroMemory(&dbei, sizeof(dbei)); + dbei.cbSize = sizeof(dbei); + dbei.eventType = EVENTTYPE_MESSAGE; + dbei.flags = footer->sent == 1 ? DBEF_SENT : DBEF_READ; + dbei.szModule = szICQModuleName[ iICQAccount ]; + // Convert timestamp + dbei.timestamp = footer->timestamp + nUCTOffset; + dbei.cbBlob = msg->textLen; + dbei.pBlob = (PBYTE)alloca(msg->textLen); + CopyMemory(dbei.pBlob, msg->text, dbei.cbBlob); + dbei.pBlob[dbei.cbBlob - 1] = 0; + + // Check for duplicate entries + if (IsDuplicateEvent(hContact, dbei)) { + nDupes++; + } + else { + if (CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei)) + nMessagesCount++; + } + + return TRUE; +} + +BOOL ImportExtendedMessage(DWORD dwOffset) +{ + struct TDatMessage *msg = (struct TDatMessage*)(pDat + dwOffset); + struct TDatEntryFooter *footer; + DBEVENTINFO dbei; + HANDLE hContact; + int nUCTOffset; + TIME_ZONE_INFORMATION TimeZoneInformation; + int nHistoryCount = 0; + char* pszText = 0; + DWORD dwRichTextOffset = 0; + DWORD wRichTextLength = 0; + DWORD wLength = 0; + BOOL bFreeMe = FALSE; + + // Get timestamp offset. In ICQ, event timestamps are stored + // as UTC + (0-TZ offset). YES! That's the negation of the + // timezone offset, only God and Mirabilis knows why. + GetTimeZoneInformation(&TimeZoneInformation); + nUCTOffset = -TimeZoneInformation.Bias * 60; + + // Ignore messages in 'Deleted' folder + if (msg->filingStatus&FILING_DELETED) + return FALSE; + + // Skip messages from non-icq contacts + if (msg->uin < 10000) { + AddMessage( LPGEN("Ignoring msg from user %d at ofs %d."), msg->uin, dwOffset ); + return FALSE; + } + + // Ignore received messages? + if (( msg->filingStatus & FILING_RECEIVED) && !( nCustomOptions & IOPT_MSGRECV )) + return FALSE; + + // Ignore sent messages? + if ( !( msg->filingStatus & FILING_RECEIVED ) && !( nCustomOptions & IOPT_MSGSENT )) + return FALSE; + + // Check if contact exists in Miranda database + hContact = HistoryImportFindContact(hdlgProgress, szICQModuleName[ iICQAccount ], msg->uin, nCustomOptions&IOPT_ADDUNKNOWN); + if (hContact == INVALID_HANDLE_VALUE) + return FALSE; // Contact couldn't be found/added + + // Find a piece of usable text content + if (msg->textLen <= 1) { + // Skip past the RTF segment + wRichTextLength = *(PWORD)(pDat + dwOffset + 0x2A + msg->textLen + 0x21); + dwRichTextOffset = dwOffset + 0x2A + msg->textLen + 0x23; + + // Use the UTF-8 text segment + wLength = *(PWORD)(pDat + dwRichTextOffset + wRichTextLength); + if (wLength <= 1) { + AddMessage( LPGEN("Ignoring msg with no text from %d ofs %d."), msg->uin, dwOffset ); + return FALSE; + } + pszText = _strdup(pDat + dwRichTextOffset + wRichTextLength + 2); + bFreeMe = TRUE; + mir_utf8decode(pszText, NULL); + wLength = (DWORD)strlen(pszText)+1; + } + else { + // Use the ANSI text segment + wLength = msg->textLen; + pszText = pDat + dwOffset + 0x2A; + } + + // Convert the event to a Miranda dbevent + footer = (struct TDatEntryFooter*)(pDat + dwOffset + msg->textLen + offsetof(struct TDatMessage, text)); + ZeroMemory(&dbei, sizeof(dbei)); + dbei.cbSize = sizeof(dbei); + dbei.eventType = EVENTTYPE_MESSAGE; + dbei.flags = footer->sent == 1 ? DBEF_SENT : DBEF_READ; + dbei.szModule = szICQModuleName[ iICQAccount ]; + // Convert timestamp + dbei.timestamp = footer->timestamp + nUCTOffset; + dbei.cbBlob = wLength; + dbei.pBlob = (PBYTE)calloc(wLength,1); + CopyMemory(dbei.pBlob, pszText, dbei.cbBlob); + dbei.pBlob[dbei.cbBlob - 1] = 0; + + // Check for duplicate entries + if (IsDuplicateEvent(hContact, dbei)) { + nDupes++; + } + else { + if (CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei)) + nMessagesCount++; + } + + free(dbei.pBlob); + if (bFreeMe) + free(pszText); + + return TRUE; +} + +BOOL ImportURLMessage(DWORD dwOffset) +{ + struct TDatMessage *msg = (struct TDatMessage*)(pDat + dwOffset); + struct TDatEntryFooter *footer; + DBEVENTINFO dbei; + HANDLE hContact; + int nUCTOffset; + TIME_ZONE_INFORMATION TimeZoneInformation; + int nHistoryCount = 0; + char *pSeparator; + + // Get timestamp offset. In ICQ, event timestamps are stored + // as UTC + (0-TZ offset). YES! That's the negation of the + // timezone offset, only God and Mirabilis knows why. + GetTimeZoneInformation(&TimeZoneInformation); + nUCTOffset = -TimeZoneInformation.Bias * 60; + + // Ignore URLs in 'Deleted' folder + if (msg->filingStatus&FILING_DELETED) + return FALSE; + + // Skip URLs from non-icq contacts + if (msg->uin < 10000) { + AddMessage( LPGEN("Ignoring msg from user %d at ofs %d."), msg->uin, dwOffset ); + return FALSE; + } + + // Ignore received URLs? + if (( msg->filingStatus & FILING_RECEIVED ) && !( nCustomOptions & IOPT_URLRECV )) + return FALSE; + + // Ignores sent URLs? + if ( !( msg->filingStatus & FILING_RECEIVED ) && !( nCustomOptions & IOPT_URLSENT )) + return FALSE; + + // Check if contact exists in Miranda database + hContact = HistoryImportFindContact(hdlgProgress, szICQModuleName[ iICQAccount ], msg->uin, nCustomOptions&IOPT_ADDUNKNOWN); + if (hContact == INVALID_HANDLE_VALUE) + return FALSE; // Contact couldn't be found/added + + // Convert the event to a Miranda dbevent + footer = (struct TDatEntryFooter*)(pDat + dwOffset + msg->textLen + offsetof(struct TDatMessage, text)); + ZeroMemory(&dbei, sizeof(dbei)); + dbei.cbSize = sizeof(dbei); + dbei.eventType = EVENTTYPE_URL; + dbei.flags = footer->sent == 1 ? DBEF_SENT : DBEF_READ; + dbei.szModule = szICQModuleName[ iICQAccount ]; + // Convert timestamp + dbei.timestamp = footer->timestamp + nUCTOffset; + dbei.cbBlob = msg->textLen; + dbei.pBlob = (PBYTE)alloca(msg->textLen); + CopyMemory(dbei.pBlob, msg->text, dbei.cbBlob); + dbei.pBlob[dbei.cbBlob - 1] = 0; + // Separate URL and description + pSeparator = strchr((char*)dbei.pBlob, 0xFE); + if (pSeparator != NULL) + *pSeparator = 0; + + // Check for duplicate entries + if (IsDuplicateEvent(hContact, dbei)) + nDupes++; + else if (CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei)) + nMessagesCount++; + + return TRUE; +} + +BOOL ImportEvent(DWORD dwOffset) +{ + struct TDatMessage *msg = (struct TDatMessage*)(pDat + dwOffset); + + // Events have IDs > 2000 + if (msg->hdr.entryId < 2001) { + AddMessage( LPGEN("Skipping event with ID < 2001.")); + return FALSE; + } + + // Separate code paths based on the event signature + switch (msg->hdr.subType) { + + case SUBTYPE_MESSAGE: // All kinds of messages + switch (msg->type) { + case 1: // Normal message + if ((nCustomOptions&IOPT_MSGRECV) || (nCustomOptions&IOPT_MSGSENT)) { + return ImportMessage(dwOffset); + } + break; + + case 4: // URL + if ((nCustomOptions&IOPT_URLSENT) || (nCustomOptions&IOPT_URLRECV)) { + return ImportURLMessage(dwOffset); + } + break; + + case 6: // Request for authorization + #ifdef _LOGGING + AddMessage( LPGEN("Skipping 'Request for auth.' msg, ofs %d."), dwOffset ); + #endif + break; + + case 7: // Authorization request denied + #ifdef _LOGGING + AddMessage( LPGEN("Skipping 'Auth. denied' msg, ofs %d."), dwOffset ); + #endif + break; + + case 8: // Authorization request accepted + #ifdef _LOGGING + AddMessage( LPGEN("Skipping 'Auth. accepted' msg, ofs %d."), dwOffset ); + #endif + break; + + case 9: // System message + #ifdef _LOGGING + AddMessage( LPGEN("Skipping 'System message', ofs %d."), dwOffset ); + #endif + break; + + case 12: // You were added + #ifdef _LOGGING + AddMessage( LPGEN("Skipping 'You were added' msg, ofs %d."), dwOffset ); + #endif + break; + + case 13: // WWWPager ? + #ifdef _LOGGING + AddMessage( LPGEN("Skipping 'WWW Pager' msg, ofs %d."), dwOffset ); + #endif + break; + + case 14: // Email Express ? + #ifdef _LOGGING + AddMessage( LPGEN("Skipping 'Email Express' msg, ofs %d."), dwOffset ); + #endif + break; + + case 19: // Contact list + #ifdef _LOGGING + AddMessage( LPGEN("Skipping 'Contact' msg, ofs %d."), dwOffset ); + #endif + break; + + case 21: // Phonecall request? + #ifdef _LOGGING + AddMessage( LPGEN("Skipping 'Phonecall' msg (?), ofs %d."), dwOffset ); + #endif + break; + + case 26: // SMS request? + #ifdef _LOGGING + AddMessage( LPGEN("Skipping 'SMS' msg (?), ofs %d."), dwOffset ); + #endif + break; + + case 29: // Active list invitation ?? + #ifdef _LOGGING + AddMessage( LPGEN("Skipping 29 msg, ofs %d."), dwOffset ); + #endif + break; + + case 30: // Birthday reminder + #ifdef _LOGGING + AddMessage( LPGEN("Skipping 'Birthday' msg (?), ofs %d."), dwOffset ); + #endif + break; + + case 32: // Unknown (Tomer) + #ifdef _LOGGING + AddMessage( LPGEN("Skipping 32 msg, ofs %d."), dwOffset ); + #endif + break; + + default: + AddMessage( LPGEN("Skipping unknown 0xE0 subtype (%d), ofs %d."), msg->type, dwOffset ); + + #ifdef _LOGGING + { // If this is a debug build, dump entry to disk + FILE *stream; + DWORD dwSize = *(PDWORD)(pDat + dwOffset); + wsprintfA(str, "import_unknown_E0subtype_%u-%u.bin", msg->type, dwOffset); + stream = fopen(str, "w"); + fwrite(pDat + dwOffset, 1, dwSize, stream); + fclose(stream); + } + #endif + + return FALSE; + } + break; + + case SUBTYPE_CHATREQUEST: // 0xE1 + #ifdef _LOGGING + if (nImportOption != IMPORT_CONTACTS) + AddMessage( LPGEN("Skipping 'Chat request' msg, ofs %d."), dwOffset ); + #endif + break; + + case SUBTYPE_FILEREQUEST: // 0xE2 + #ifdef _LOGGING + if (nImportOption != IMPORT_CONTACTS) + AddMessage( LPGEN("Skipping file message offset %d."), dwOffset ); + #endif + break; + + case 0xE3: // External (IPhone, Battlecom) Maybe general voice calls? + #ifdef _LOGGING + if (nImportOption != IMPORT_CONTACTS) + AddMessage( LPGEN("Skipping message type 0xE3 at offset %d."), dwOffset ); + #endif + break; + + case 0xE4: // My details + break; + case 0xE5: // Contact + break; + case 0xE6: // Reminder + break; + case 0xE7: // Addressbook + break; + case 0xEC: // Voice message + break; + case 0xED: // Unknown, something to do with chatting and .CHT files + // if (importHistory) { + // wsprintf(str, "Skipping message type 0xED at offset %d.", dwOffset); + // AddMessage( LPGEN(str); + // } + break; + case 0xEE: // Note + break; + case 0xEF: // Event folder + break; + // case 0xF0: // Unknown + // if (importHistory) { + // wsprintf(str, "Skipping message type 0xF0 at offset %d.", dwOffset); + // AddMessage( LPGEN(str); + // } + // break; + case 0xF1: // Server list + break; + // case 0xF6: // Unknown + // if (importHistory) { + // wsprintf(str, "Skipping message type 0xF6 at offset %d.", dwOffset); + // AddMessage( LPGEN(str); + // } + // break; + case 0x50: // Extended message, ICQ 2000a+? + if (nImportOption != IMPORT_CONTACTS) { + return ImportExtendedMessage(dwOffset); + } + break; + + case 0xA0: // URL message type 2 + if (nImportOption != IMPORT_CONTACTS) { + if ((msg->filingStatus&FILING_RECEIVED) || (nCustomOptions&IOPT_URLRECV)) { + return ImportURLMessage(dwOffset); + } + } + break; + + default: + if (nImportOption != IMPORT_CONTACTS) { + AddMessage( LPGEN("Skipping unknown event type %d at offset %d."), msg->hdr.subType, dwOffset ); + +#ifdef _LOGGING + { // If this is a debug build, dump entry to disk + FILE *stream; + DWORD dwSize; + dwSize = *(PDWORD)(pDat + dwOffset); + wsprintfA(str, "import_unknown_eventtype_%u-%u.bin", msg->hdr.subType, dwOffset); + stream = fopen(str, "w"); + fwrite(pDat + dwOffset, 1, dwSize, stream); + fclose(stream); + } +#endif + + } + break; + } + + return FALSE; +} + + +static void MirabilisImport(HWND hdlgProgressWnd) +{ + HANDLE hIdx, hDat, hIdxMapping, hDatMapping; + DWORD i, ofs, highestIndexEntry; + TCHAR datFilename[MAX_PATH]; + MSG msg; + DWORD dwTimer; + + + int status = 0; + hdlgProgress = hdlgProgressWnd; + nDupes = nContactsCount = nMessagesCount = 0; + + SetProgress(0); + lstrcpy(datFilename, importFile); + { + TCHAR* str2; + str2 = _tcsrchr(datFilename,'.'); + if ( str2 != NULL ) + lstrcpy(str2, _T(".dat")); + } + + hIdx = CreateFile(importFile, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if (hIdx == INVALID_HANDLE_VALUE) { + AddMessage( LPGEN("Failed to open index file")); + AddMessage( LPGEN("Import aborted")); + SetProgress(100); + return; + } + + hDat = CreateFile(datFilename, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if (hDat == INVALID_HANDLE_VALUE) { + AddMessage( LPGEN("Failed to open database file")); + AddMessage( LPGEN("Import aborted")); + SetProgress(100); + return; + } + + // Creating file mappings + hIdxMapping = CreateFileMapping(hIdx, NULL, PAGE_READONLY, 0, 0, NULL); + hDatMapping = CreateFileMapping(hDat, NULL, PAGE_READONLY, 0, 0, NULL); + + // Mapping views of files + pIdx = (PBYTE)MapViewOfFile(hIdxMapping, FILE_MAP_READ, 0, 0, 0); + pDat = (PBYTE)MapViewOfFile(hDatMapping, FILE_MAP_READ, 0, 0, 0); + + // Is this a supported format? + if (GetDBVersion()) { + AddMessage( "" ); + + highestIndexEntry = GetHighestIndexEntry(); + + // Import groups + nGroupsCount = ImportGroups(); + if (nGroupsCount < 0) { + AddMessage( LPGEN("Group import was not completed.")); + nGroupsCount = 0; + } + AddMessage( "" ); + + // Start benchmark timer + dwTimer = time(NULL); + + if ( !IsProtocolLoaded( szICQModuleName[iICQAccount] )) { + AddMessage( LPGEN("ICQ account is not installed.")); + AddMessage( LPGEN("No ICQ contacts or history will be imported.")); + AddMessage( "" ); + } + else { + // Configure database for fast writing + CallService(MS_DB_SETSAFETYMODE, FALSE, 0); + + // Import contacts + AddMessage( LPGEN("Importing contacts")); + for (i = 2001; i <= highestIndexEntry; i++) { //event ids start at 2001 + if (!(i%10)) { + if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + if (!(i%100)) + SetProgress(100 * (i - 2001) / (highestIndexEntry - 2001)); + + ofs = GetIdDatOfs(i); + if (ofs != 0) { + if (ImportContact(ofs) != INVALID_HANDLE_VALUE) + nContactsCount++; + } + } + AddMessage( "" ); + + // Import history + if (nImportOption != IMPORT_CONTACTS) { + AddMessage( LPGEN("Importing history (this may take a while)")); + for (i = 2001; i <= highestIndexEntry; i++) { //event ids start at 2001 + if (!(i%10)) { + if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + if (!(i%100)) + SetProgress(100 * (i - 2001) / (highestIndexEntry - 2001)); + + ofs = GetIdDatOfs(i); + if (ofs != 0) ImportEvent(ofs); + } + AddMessage( "" ); + } + + // Restore database writing mode + CallService(MS_DB_SETSAFETYMODE, TRUE, 0); + } + + dwTimer = time(NULL) - dwTimer; + + AddMessage( LPGEN("Import completed in %d seconds."), dwTimer ); + SetProgress(100); + AddMessage( LPGEN("Added %d contacts and %d groups."), nContactsCount, nGroupsCount ); + if ( nImportOption != IMPORT_CONTACTS ) + AddMessage( LPGEN("Added %d events and skipped %d duplicates."), nMessagesCount, nDupes ); + } + + UnmapViewOfFile(pDat); + UnmapViewOfFile(pIdx); + CloseHandle(hDatMapping); + CloseHandle(hIdxMapping); + CloseHandle(hDat); + CloseHandle(hIdx); +} diff --git a/plugins/Dbx_mmap_SA/Import_SA/miranda.c b/plugins/Dbx_mmap_SA/Import_SA/miranda.c deleted file mode 100644 index 69b348d192..0000000000 --- a/plugins/Dbx_mmap_SA/Import_SA/miranda.c +++ /dev/null @@ -1,1502 +0,0 @@ -/* - -Import plugin for Miranda IM - -Copyright (C) 2001-2005 Martin Öberg, Richard Hughes, Roland Rabien & Tristan Van de Vreede - -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. - -*/ - -// ============== -// == INCLUDES == -// ============== - -#include "import.h" - -#include "mirandadb0700.h" - -// ====================== -// == GLOBAL FUNCTIONS == -// ====================== - -HANDLE HContactFromNumericID(char* pszProtoName, char* pszSetting, DWORD dwID); -HANDLE HContactFromID(char* pszProtoName, char* pszSetting, char* pszID); - -HANDLE AddContact(HWND hdlgProgress, char* pszProtoName, char* pszUniqueSetting, DBVARIANT* id, DBVARIANT* nick, DBVARIANT* group); - -BOOL IsProtocolLoaded(char* pszProtocolName); -BOOL IsDuplicateEvent(HANDLE hContact, DBEVENTINFO dbei); - -INT_PTR CALLBACK ImportTypePageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam); -INT_PTR CALLBACK FinishedPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam); -INT_PTR CALLBACK ProgressPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam); -INT_PTR CALLBACK MirandaOptionsPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam); -INT_PTR CALLBACK MirandaAdvOptionsPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam); - -// ===================== -// == LOCAL FUNCTIONS == -// ===================== - -void MirandaImport(HWND hdlgProgress); -int CheckFileFormat(HANDLE hFile); -static HANDLE ImportContact(HANDLE hDbFile, struct DBContact Contact); -static void ImportHistory(HANDLE hDbFile, struct DBContact Contact, PROTOCOLDESCRIPTOR **protocol, int protoCount); -static int ImportGroups(HANDLE hDbFile, struct DBHeader *pdbHeader); - -#define NEWSTR_ALLOCA(A) (A==NULL)?NULL:strcpy((char*)alloca(strlen(A)+1),A) - -// Comment: The Find* functions only return a file offset. -// The Get* functions actually reads the requested -// data from the file and gives you a pointer to a structure -// containing the data. - -DWORD FindFirstContact(struct DBHeader* pDbHeader); -DWORD FindNextContact(struct DBContact* pDbContact); -DWORD FindNextEvent(HANDLE hDbFile, DWORD dwOffset); -DWORD FindOwnerContact(struct DBHeader* pDbHeader); - -int GetContactCount(struct DBHeader* pDbHeader); -BOOL GetContact(HANDLE hDbFile, DWORD dwOffset, struct DBContact* pDbContact); -BOOL GetSetting(HANDLE hDbFile, struct DBContact* pDbContact, char* pszModuleName, char* pszSettingName, DBVARIANT* pValue); -char* GetNextSetting(char* pDbSetting); -BOOL GetSettings(HANDLE hDbFile, DWORD dwOffset, struct DBContactSettings** pDbSettings); -struct DBContactSettings* GetSettingsGroupByModuleName(HANDLE hdbFile, struct DBContact* pDbContact, char* pszName); -DWORD GetBlobSize(struct DBContactSettings* pDbSettings); -int GetSettingByName(struct DBContactSettings* pDbSettings, char* pszSettingName, DBVARIANT* pValue); -int GetSettingValue(char* pBlob,DBVARIANT* pValue); - -BOOL GetEvent(HANDLE hDbFile, DWORD dwOffset, DBEVENTINFO* pDBEI); -char* GetName(HANDLE hDbFile, DWORD dwOffset); - - -// ====================== -// == GLOBAL VARIABLES == -// ====================== - -extern void (*DoImport)(HWND); -extern int nImportOption; -extern int nCustomOptions; - - -// ===================== -// == LOCAL VARIABLES == -// ===================== - -TCHAR importFile[MAX_PATH]; -HWND hdlgProgress; -DWORD dwFileSize; - -DWORD nDupes; -DWORD nContactsCount; -DWORD nMessagesCount; -DWORD nGroupsCount; -DWORD nSkippedEvents; -DWORD nSkippedContacts; - -time_t dwSinceDate = 0; - -// ============= -// == DEFINES == -// ============= - -#define EVENTTYPE_MESSAGE 0 -#define EVENTTYPE_URL 1 -#define EVENTTYPE_FILE 1002 - - -// Supported database versions -#define DB_INVALID 0x00000000 // Unknown or corrupted DAT -#define DB_000700 0x00000700 // Miranda 0.1.0.0 - 0.1.2.2+ - -// DAT file signature -struct DBSignature { - char name[15]; - BYTE eof; -}; - -static struct DBSignature dbSignature={"Miranda ICQ DB",0x1A}; - -// Unsane: Secured signature -static struct DBSignature dbSignatureEncrypted={"Miranda ICQ SD",0x1A}; - -// ==================== -// ==================== -// == IMPLEMENTATION == -// ==================== -// ==================== - -static void SearchForLists(HWND hdlg, const TCHAR *mirandaPath, const TCHAR *mirandaProf, const TCHAR *pattern, const TCHAR *type) -{ - HANDLE hFind; - WIN32_FIND_DATA fd; - TCHAR szSearchPath[MAX_PATH]; - TCHAR szRootName[MAX_PATH]; - TCHAR* str2; - int i; - - mir_sntprintf(szSearchPath, SIZEOF(szSearchPath), _T("%s\\%s"), mirandaPath, pattern); - hFind = FindFirstFile(szSearchPath, &fd); - if (hFind != INVALID_HANDLE_VALUE) - { - do - { - _tcscpy(szRootName, fd.cFileName); - str2 = _tcsrchr(szRootName, '.'); - if (str2 != NULL) *str2 = 0; - if (mirandaProf == NULL || _tcsicmp(mirandaProf, szRootName)) - { - _tcscat(szRootName, type); - i = SendDlgItemMessage(hdlg, IDC_LIST, LB_ADDSTRING, 0, (LPARAM)szRootName); - str2 = (TCHAR*)mir_alloc((_tcslen(mirandaPath) + 2 + _tcslen(fd.cFileName)) * sizeof(TCHAR)); - wsprintf(str2, _T("%s\\%s"), mirandaPath, fd.cFileName); - SendDlgItemMessage(hdlg, IDC_LIST, LB_SETITEMDATA, i, (LPARAM)str2); - } - } - while( FindNextFile( hFind, &fd )); - - FindClose( hFind ); - } -} - -INT_PTR CALLBACK MirandaPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam) -{ - switch(message) { - case WM_INITDIALOG: - TranslateDialogDefault(hdlg); - { - TCHAR *pfd, *pfd1, *pfd2, *pfn; - - REPLACEVARSDATA dat = {0}; - dat.cbSize = sizeof(dat); - dat.dwFlags = RVF_TCHAR; - - pfd = (TCHAR*)CallService(MS_UTILS_REPLACEVARS, (WPARAM)_T("%miranda_path%\\Profiles"), (LPARAM)&dat); - pfd1 = (TCHAR*)CallService(MS_UTILS_REPLACEVARS, (WPARAM)_T("%miranda_path%"), (LPARAM)&dat); - pfd2 = (TCHAR*)CallService(MS_UTILS_REPLACEVARS, (WPARAM)_T("%miranda_profile%"), (LPARAM)&dat); - pfn = (TCHAR*)CallService(MS_UTILS_REPLACEVARS, (WPARAM)_T("%miranda_profilename%"), (LPARAM)&dat); - - SearchForLists(hdlg, pfd2, pfn, _T("*.dat"), _T(" (Miranda IM v0.x)")); - // Unsane: check for exclude equal or used profiles - if (lstrcmpi(pfd1, pfd2)) - SearchForLists(hdlg, pfd1, NULL, _T("*.dat"), _T(" (Miranda IM v0.x)")); - if (lstrcmpi(pfd, pfd2)) - SearchForLists(hdlg, pfd, NULL, _T("*.dat"), _T(" (Miranda IM v0.x)")); - - mir_free(pfn); - mir_free(pfd2); - mir_free(pfd1); - mir_free(pfd); - return TRUE; - } - - case WM_COMMAND: - switch(LOWORD(wParam)) { - case IDC_BACK: - PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_IMPORTTYPE,(LPARAM)ImportTypePageProc); - break; - - case IDOK: - { - TCHAR filename[MAX_PATH]; - - GetDlgItemText(hdlg, IDC_FILENAME, filename, SIZEOF(filename)); - if (_taccess(filename, 4)) { - MessageBox(hdlg, TranslateT("The given file does not exist. Please check that you have entered the name correctly."), TranslateT("Miranda Import"), MB_OK); - break; - } - lstrcpy(importFile, filename); - PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_OPTIONS,(LPARAM)MirandaOptionsPageProc); - } - break; - - case IDCANCEL: - PostMessage(GetParent(hdlg),WM_CLOSE,0,0); - break; - - case IDC_LIST: - if(HIWORD(wParam)==LBN_SELCHANGE) { - int sel = SendDlgItemMessage(hdlg, IDC_LIST, LB_GETCURSEL, 0, 0); - if (sel == LB_ERR) break; - SetDlgItemText(hdlg, IDC_FILENAME, (TCHAR*)SendDlgItemMessage(hdlg, IDC_LIST, LB_GETITEMDATA, sel, 0)); - } - break; - - case IDC_OTHER: - { - OPENFILENAME ofn; - TCHAR str[MAX_PATH], text[256]; - TCHAR *pfd; - int index; - - pfd = Utils_ReplaceVarsT(_T("%miranda_profile%")); - - // TranslateTS doesnt translate \0 separated strings - index = mir_sntprintf(text, 64, _T("%s (*.dat)"), TranslateT("Miranda IM database")) + 1; - _tcscpy(text + index, _T("*.dat")); index += 6; - index += mir_sntprintf(text + index, 64, _T("%s (*.*)"), TranslateT("All Files")) + 1; - _tcscpy(text + index, _T("*.*")); index += 4; - text[index] = 0; - - GetDlgItemText(hdlg, IDC_FILENAME, str, SIZEOF(str)); - ZeroMemory(&ofn, sizeof(ofn)); - ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; - ofn.hwndOwner = hdlg; - ofn.lpstrFilter = text; - ofn.lpstrDefExt = _T("dat"); - ofn.lpstrFile = str; - ofn.Flags = OFN_FILEMUSTEXIST | OFN_EXPLORER | OFN_NOCHANGEDIR | OFN_DONTADDTORECENT; - ofn.nMaxFile = SIZEOF(str); - ofn.lpstrInitialDir = pfd; - if (GetOpenFileName(&ofn)) - SetDlgItemText(hdlg,IDC_FILENAME,str); - - mir_free(pfd); - break; - } - } - break; - case WM_DESTROY: - { - int i; - - for(i=SendDlgItemMessage(hdlg,IDC_LIST,LB_GETCOUNT,0,0)-1;i>=0;i--) - mir_free((char*)SendDlgItemMessage(hdlg,IDC_LIST,LB_GETITEMDATA,i,0)); - break; - } } - - return FALSE; -} - - -INT_PTR CALLBACK MirandaOptionsPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam) -{ - switch(message) { - case WM_INITDIALOG: - TranslateDialogDefault(hdlg); - EnableWindow(GetDlgItem(hdlg,IDC_RADIO_ALL), TRUE); - EnableWindow(GetDlgItem(hdlg,IDC_STATIC_ALL), TRUE); - EnableWindow(GetDlgItem(hdlg,IDC_RADIO_CONTACTS), TRUE); - EnableWindow(GetDlgItem(hdlg,IDC_STATIC_CONTACTS), TRUE); - EnableWindow(GetDlgItem(hdlg,IDC_RADIO_CUSTOM), TRUE); - EnableWindow(GetDlgItem(hdlg,IDC_STATIC_CUSTOM), TRUE); - CheckDlgButton(hdlg,IDC_RADIO_ALL,BST_UNCHECKED); - return TRUE; - - case WM_COMMAND: - switch(LOWORD(wParam)) { - case IDC_BACK: - PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_MIRANDADB,(LPARAM)MirandaPageProc); - break; - - case IDOK: - if(IsDlgButtonChecked(hdlg,IDC_RADIO_ALL)) { - nImportOption = IMPORT_ALL; - nCustomOptions = 0;//IOPT_MSGSENT|IOPT_MSGRECV|IOPT_URLSENT|IOPT_URLRECV; - DoImport = MirandaImport; - PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_PROGRESS,(LPARAM)ProgressPageProc); - break; - } - - if(IsDlgButtonChecked(hdlg,IDC_RADIO_CONTACTS)) { - nImportOption = IMPORT_CONTACTS; - nCustomOptions = 0; - DoImport = MirandaImport; - PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_PROGRESS,(LPARAM)ProgressPageProc); - break; - } - - if(IsDlgButtonChecked(hdlg,IDC_RADIO_CUSTOM)) { - PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_ADVOPTIONS,(LPARAM)MirandaAdvOptionsPageProc); - break; - } - break; - - case IDCANCEL: - PostMessage(GetParent(hdlg), WM_CLOSE, 0, 0); - break; - } - break; - } - return FALSE; -} - -static const UINT InControls[]={IDC_IN_MSG,IDC_IN_URL,IDC_IN_FT,IDC_IN_OTHER}; -static const UINT OutControls[]={IDC_OUT_MSG,IDC_OUT_URL,IDC_OUT_FT,IDC_OUT_OTHER}; -static const UINT SysControls[]={IDC_CONTACTS, IDC_SYSTEM}; - -INT_PTR CALLBACK MirandaAdvOptionsPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam) -{ - switch(message) { - case WM_INITDIALOG: - TranslateDialogDefault(hdlg); - { - struct tm *TM = NULL; - struct _SYSTEMTIME ST = {0}; - - dwSinceDate = DBGetContactSettingDword(NULL,IMPORT_MODULE,"ImportSinceTS",time(NULL)); - - TM = localtime(&dwSinceDate); - - ST.wYear = TM->tm_year + 1900; - ST.wMonth = TM->tm_mon + 1; - ST.wDay = TM->tm_mday; - - DateTime_SetSystemtime(GetDlgItem(hdlg,IDC_DATETIMEPICKER),GDT_VALID,&ST); - } - return TRUE; - - case WM_COMMAND: - switch(LOWORD(wParam)) { - case IDC_BACK: - PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_OPTIONS,(LPARAM)MirandaOptionsPageProc); - break; - - case IDOK: - DoImport = MirandaImport; - nImportOption = IMPORT_CUSTOM; - nCustomOptions = 0; - - if (IsDlgButtonChecked(hdlg,IDC_CONTACTS)) - nCustomOptions |= IOPT_CONTACTS | IOPT_GROUPS; - if (IsDlgButtonChecked(hdlg,IDC_SYSTEM)) - nCustomOptions |= IOPT_SYSTEM; - - // incoming - if (IsDlgButtonChecked(hdlg,IDC_IN_MSG)) - nCustomOptions |= IOPT_MSGRECV; - if (IsDlgButtonChecked(hdlg,IDC_IN_URL)) - nCustomOptions |= IOPT_URLRECV; - if (IsDlgButtonChecked(hdlg,IDC_IN_FT)) - nCustomOptions |= IOPT_FILERECV; - if (IsDlgButtonChecked(hdlg,IDC_IN_OTHER)) - nCustomOptions |= IOPT_OTHERRECV; - - // outgoing - if (IsDlgButtonChecked(hdlg,IDC_OUT_MSG)) - nCustomOptions |= IOPT_MSGSENT; - if (IsDlgButtonChecked(hdlg,IDC_OUT_URL)) - nCustomOptions |= IOPT_URLSENT; - if (IsDlgButtonChecked(hdlg,IDC_OUT_FT)) - nCustomOptions |= IOPT_FILESENT; - if (IsDlgButtonChecked(hdlg,IDC_OUT_OTHER)) - nCustomOptions |= IOPT_OTHERSENT; - - // since date - dwSinceDate = 0; - - if ( IsDlgButtonChecked( hdlg, IDC_SINCE )) { - struct _SYSTEMTIME ST = {0}; - - if (DateTime_GetSystemtime(GetDlgItem(hdlg,IDC_DATETIMEPICKER), &ST) == GDT_VALID) { - struct tm TM = {0}; - - TM.tm_mday = ST.wDay; - TM.tm_mon = ST.wMonth - 1; - TM.tm_year = ST.wYear - 1900; - - dwSinceDate = mktime(&TM); - - DBWriteContactSettingDword(NULL,IMPORT_MODULE,"ImportSinceTS",dwSinceDate); - } } - - if (nCustomOptions) - PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_PROGRESS,(LPARAM)ProgressPageProc); - break; - - case IDCANCEL: - PostMessage(GetParent(hdlg), WM_CLOSE, 0, 0); - break; - - case IDC_SINCE: - EnableWindow(GetDlgItem(hdlg, IDC_DATETIMEPICKER), IsDlgButtonChecked(hdlg, IDC_SINCE)); - break; - - if (HIWORD(wParam) != STN_CLICKED) - break; - - case IDC_ALL: - case IDC_INCOMING: - case IDC_OUTGOING: - { - int i; - - if (LOWORD(wParam) == IDC_ALL) - for (i = 0; i < sizeof(SysControls)/sizeof(SysControls[0]); i++) - CheckDlgButton(hdlg,SysControls[i], !IsDlgButtonChecked(hdlg,SysControls[i])); - - if (LOWORD(wParam) != IDC_OUTGOING) - for (i = 0; i < sizeof(InControls)/sizeof(InControls[0]); i++) - CheckDlgButton(hdlg,InControls[i], !IsDlgButtonChecked(hdlg,InControls[i])); - - if (LOWORD(wParam) != IDC_INCOMING) - for (i = 0; i < sizeof(OutControls)/sizeof(OutControls[0]); i++) - CheckDlgButton(hdlg,OutControls[i], !IsDlgButtonChecked(hdlg,OutControls[i])); - } - break; - - case IDC_MSG: - CheckDlgButton(hdlg,IDC_IN_MSG, !IsDlgButtonChecked(hdlg,IDC_IN_MSG)); - CheckDlgButton(hdlg,IDC_OUT_MSG, !IsDlgButtonChecked(hdlg,IDC_OUT_MSG)); - break; - - case IDC_URL: - CheckDlgButton(hdlg,IDC_IN_URL, !IsDlgButtonChecked(hdlg,IDC_IN_URL)); - CheckDlgButton(hdlg,IDC_OUT_URL, !IsDlgButtonChecked(hdlg,IDC_OUT_URL)); - break; - - case IDC_FT: - CheckDlgButton(hdlg,IDC_IN_FT, !IsDlgButtonChecked(hdlg,IDC_IN_FT)); - CheckDlgButton(hdlg,IDC_OUT_FT, !IsDlgButtonChecked(hdlg,IDC_OUT_FT)); - break; - - case IDC_OTHER: - CheckDlgButton(hdlg,IDC_IN_OTHER, !IsDlgButtonChecked(hdlg,IDC_IN_OTHER)); - CheckDlgButton(hdlg,IDC_OUT_OTHER, !IsDlgButtonChecked(hdlg,IDC_OUT_OTHER)); - break; - } - break; - } - return FALSE; -} - -#ifndef INVALID_SET_FILE_POINTER -#define INVALID_SET_FILE_POINTER ((DWORD)-1) -#endif - -// Read header from file, returns null on failure -struct DBHeader* GetHeader(HANDLE hDbFile) -{ - struct DBHeader* pdbHeader; - DWORD dwBytesRead; - - if (( pdbHeader = calloc(1, sizeof(struct DBHeader))) == NULL ) - return NULL; - - // Goto start of file - if (SetFilePointer(hDbFile, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) - return FALSE; - - // Read header - if ( !ReadFile(hDbFile, pdbHeader, sizeof(struct DBHeader), &dwBytesRead, NULL ) || - dwBytesRead != sizeof(struct DBHeader)) - return NULL; - - // Return pointer to header - return pdbHeader; -} - -// Unsane: database crypted status -BOOL bEncrypted; -// Unsane: crypted database work fuction -int CheckPassword(WORD version, WORD cryptorUID, TCHAR * szDBName); -void InitSecurity(); - -int CheckFileFormat(HANDLE hDbFile) -{ - struct DBHeader* pdbHeader; - TCHAR* tszDbName; - - // Read header - if (( pdbHeader = GetHeader(hDbFile)) == NULL ) - return DB_INVALID; - - // Check header signature - bEncrypted = FALSE; - if (memcmp(pdbHeader->signature, &dbSignature, sizeof(pdbHeader->signature))) { - // Unsane: if not encrypted signature - if (memcmp(pdbHeader->signature, &dbSignatureEncrypted, sizeof(pdbHeader->signature))) { - AddMessage( LPGEN("Signature mismatch" )); - return DB_INVALID; - } - AddMessage(LPGEN("Database is Secured MMAP database")); - // Unsane: check password - InitSecurity(); - tszDbName = _tcsrchr(importFile, _T('\\')) + 1; - if (CheckPassword(pdbHeader->checkWord, pdbHeader->cryptorUID, tszDbName)) { - AddMessage(LPGEN("Secured MMAP: authorization successful")); - bEncrypted = TRUE; - } - else - { - AddMessage(LPGEN("You are not authorized for access to Database")); - return DB_INVALID; - } - } - - // Determine Miranda version - switch (pdbHeader->checkWord) { - case DB_000700: - AddMessage( LPGEN("This looks like a Miranda database, version 0.1.0.0 or above." )); - free(pdbHeader); - return DB_000700; - - default: - if (!bEncrypted){ - AddMessage( LPGEN("Version mismatch" )); - free(pdbHeader); - return DB_INVALID; - } - break; -} } - -// High level Miranda DB access functions -// Returns true if pValue points to the requested value - -BOOL GetSetting(HANDLE hDbFile, struct DBContact* pDbContact, char* pszModuleName, char* pszSettingName, DBVARIANT* pValue) -{ - struct DBContactSettings* pDbSettings; - if ( pDbSettings = GetSettingsGroupByModuleName(hDbFile, pDbContact, pszModuleName)) { - if ( GetSettingByName( pDbSettings, pszSettingName, pValue )) { - free(pDbSettings); - return TRUE; - } - #ifdef _LOGGING - AddMessage( LPGEN("Failed to find setting %s" ), pszSettingName ); - #endif - free(pDbSettings); - } -#ifdef _LOGGING - else AddMessage( LPGEN("Failed to find module %s" ), pszModuleName ); -#endif - - // Search failed - pValue->type = 0; - return FALSE; -} - -// ** -// ** CONTACT CHAIN -// ** - -// Return offset to first contact -DWORD FindFirstContact(struct DBHeader* pDbHeader) -{ - if (!pDbHeader) - return 0; - - return pDbHeader->ofsFirstContact; -} - -DWORD FindOwnerContact(struct DBHeader* pDbHeader) -{ - if (!pDbHeader) - return 0; - - return pDbHeader->ofsUser; -} - -// Return offset to next contact -DWORD FindNextContact(struct DBContact* pDbContact) -{ - if (!pDbContact) - return 0; - - if (pDbContact->signature != DBCONTACT_SIGNATURE) - return 0; - - return pDbContact->ofsNext; -} - - -// Read the contact at offset 'dwOffset' -// Returns true if successful and pDbContact points to the contact struct -// pDbContact must point to allocated struct -BOOL GetContact(HANDLE hDbFile, DWORD dwOffset, struct DBContact* pDbContact) -{ - DWORD dwBytesRead; - - // Early reject - if (dwOffset == 0 || dwOffset >= dwFileSize) - return FALSE; - - // ** Read and verify the struct - - if (SetFilePointer(hDbFile, (LONG)dwOffset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) - return FALSE; - - if ((!ReadFile(hDbFile, pDbContact, sizeof(struct DBContact), &dwBytesRead, NULL)) || - (dwBytesRead != sizeof(struct DBContact))) - return FALSE; - - if ((pDbContact->signature != DBCONTACT_SIGNATURE) || - (pDbContact->ofsNext >= dwFileSize)) - return FALSE; // Contact corrupted - - return TRUE; -} - -// Return ptr to next setting in settings struct -char* GetNextSetting(char* pDbSetting) -{ - // Get next setting - pDbSetting = pDbSetting + *pDbSetting+1; // Skip name - switch( *(BYTE*)pDbSetting ) { - case DBVT_BYTE: - pDbSetting = pDbSetting+1+1; - break; - - case DBVT_WORD: - pDbSetting = pDbSetting+1+2; - break; - - case DBVT_DWORD: - pDbSetting = pDbSetting+1+4; - break; - - case DBVT_ASCIIZ: - case DBVT_UTF8: - case DBVT_BLOB: - case DBVTF_VARIABLELENGTH: - pDbSetting = pDbSetting + 3 + *(WORD*)(pDbSetting+1); - break; - - case DBVT_DELETED: - AddMessage( LPGEN("DEBUG: Deleted setting treated as 0-length setting")); - pDbSetting = pDbSetting+1; - break; - - default: - // Unknown datatype assert - AddMessage( LPGEN("ERROR: Faulty settings chain")); - return NULL; - } - - return pDbSetting; -} - - -// ** -// ** SETTINGS CHAIN -// ** - -// Return the settings at offset 'dwOffset' -BOOL GetSettingsGroup(HANDLE hDbFile, DWORD dwOffset, struct DBContactSettings** pDbSettings) -{ - DWORD dwBytesRead, dwBlobSize, dwHead; - struct DBContactSettings pSettings; - - // Early reject - if (dwOffset == 0 || dwOffset >= dwFileSize) - return FALSE; - - // ** Read and verify the struct - if (SetFilePointer(hDbFile, dwOffset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) - return FALSE; - - dwHead = offsetof(struct DBContactSettings, blob); - if ((!ReadFile(hDbFile, &pSettings, dwHead, &dwBytesRead, NULL)) || - (dwBytesRead != dwHead)) - return FALSE; - - if (pSettings.signature != DBCONTACTSETTINGS_SIGNATURE) - return FALSE; // Setttings corrupted - - // ** Read the struct and the following blob - dwBlobSize = pSettings.cbBlob; - if (!(*pDbSettings = calloc(1, sizeof(struct DBContactSettings) + dwBlobSize))) - return FALSE; - - memcpy(*pDbSettings, &pSettings, dwHead ); - - if ((!ReadFile(hDbFile, (*pDbSettings)->blob, sizeof(struct DBContactSettings) - dwHead + dwBlobSize, &dwBytesRead, NULL)) || - (dwBytesRead != sizeof(struct DBContactSettings) - dwHead + dwBlobSize)) - { - free(*pDbSettings); - return FALSE; - } - - return TRUE; -} - -// pDbContact is a ptr to a struct DBContact -// Returns pointer to a struct DBContactSettings or NULL -struct DBContactSettings* GetSettingsGroupByModuleName(HANDLE hDbFile, struct DBContact* pDbContact, char* pszName) -{ - char* pszGroupName; - struct DBContactSettings* pSettingsGroup; - DWORD dwGroupOfs; - - // Get ptr to first settings group - if (!(dwGroupOfs = pDbContact->ofsFirstSettings)) - return NULL; // No settings exists in this contact - - // Loop over all settings groups - while (dwGroupOfs && dwGroupOfs < dwFileSize) { - pSettingsGroup = NULL; - - // Read and verify the struct - if (!GetSettingsGroup(hDbFile, dwGroupOfs, &pSettingsGroup)) - return NULL; // Bad struct - - // Struct OK, now get the name - if ((pszGroupName = GetName(hDbFile, pSettingsGroup->ofsModuleName))) { - - // Is it the right one? - if (strcmp(pszGroupName, pszName) == 0) { - #ifdef _LOGGING - AddMessage( LPGEN("Found module: %s"), pszGroupName ); - #endif - return pSettingsGroup; - } - #ifdef _LOGGING - else AddMessage( LPGEN("Ignoring module: %s"), pszGroupName ); - #endif - } - else AddMessage( LPGEN("Warning: Found module with no name")); - - dwGroupOfs = pSettingsGroup->ofsNext; - - if (pSettingsGroup) - free(pSettingsGroup); - } - - // Search failed - return NULL; -} - -// pDbSettings must point to a complete DBContactSettings struct in memory -int GetSettingByName(struct DBContactSettings* pDbSettings, char* pszSettingName, DBVARIANT* dbv) -{ - char pszName[256]; - // We need at least one setting to start with - char* pDbSetting = pDbSettings->blob; - if ( !pDbSetting ) - return FALSE; - - // ** pDbSettings now points to the first setting in this module - - // Loop over all settings - while (pDbSetting && *pDbSetting) { - memcpy(pszName, pDbSetting+1, *pDbSetting); - pszName[*pDbSetting] = 0; - - // Is this the right one? - if (strcmp(pszSettingName, pszName) == 0) { - return GetSettingValue(pDbSetting, dbv); - } - - #ifdef _LOGGING - AddMessage( LPGEN("Ignoring setting: %s"), pszName ); - #endif - pDbSetting = GetNextSetting(pDbSetting); - } - - // Search failed - return FALSE; -} - -// dwSettingpointer points to a valid DBSettings struct -int GetSettingValue(char* pBlob, DBVARIANT* dbv) -{ - #ifdef _LOGGING - { - char* pszName = calloc((*pBlob)+1, 1); - memcpy(pszName, pBlob+1, *pBlob); - AddMessage( LPGEN("Getting type %u value for setting: %s"), (BYTE)*(pBlob+(*pBlob)+1), pszName ); - free(pszName); - } - #endif - - // Skip name - pBlob = pBlob + (*pBlob)+1; - dbv->type = ( BYTE )*pBlob++; - - // Check what type it is - switch( dbv->type ) { - case DBVT_BYTE: - dbv->bVal = *pBlob; - return TRUE; - - case DBVT_WORD: - // Unsane: encrypt WORDs - if (bEncrypted) - DecodeMemory(pBlob, sizeof(pBlob)); - dbv->wVal = *(WORD*)pBlob; - return TRUE; - - case DBVT_DWORD: - // Unsane: encrypt DWORDs - if (bEncrypted) - DecodeMemory(pBlob, sizeof(pBlob)); - dbv->dVal = *(DWORD*)pBlob; - return TRUE; - - case DBVT_ASCIIZ: - case DBVT_UTF8: - // Unsane: encrypt STRINGs - dbv->cchVal = *(WORD*)pBlob; - dbv->pszVal = calloc( dbv->cchVal+1, sizeof( char )); - if (bEncrypted) - DecodeCopyMemory(dbv->pszVal, pBlob+2, dbv->cchVal); - else - memcpy( dbv->pszVal, pBlob+2, dbv->cchVal ); - dbv->pszVal[ dbv->cchVal ] = 0; - - return TRUE; - - case DBVTF_VARIABLELENGTH: - case DBVT_BLOB: - dbv->cpbVal = *(WORD*)pBlob; - dbv->pbVal = calloc( dbv->cpbVal+1, sizeof( char )); - // Unsane: encrypt other - if (bEncrypted) - DecodeCopyMemory(dbv->pszVal, pBlob+2, dbv->cchVal); - else - memcpy( dbv->pbVal, pBlob+2, dbv->cpbVal ); - dbv->pbVal[ dbv->cpbVal ] = 0; - return TRUE; - - case DBVT_DELETED: - AddMessage( LPGEN("DEBUG: Deleted setting treated as 0-length setting")); - - default: - dbv->type = DBVT_DELETED; - } - - return FALSE; -} - -void FreeVariant( DBVARIANT* dbv ) -{ - switch( dbv->type ) { - case DBVT_ASCIIZ: - case DBVT_UTF8: - if ( dbv->pszVal ) - free( dbv->pszVal ); - break; - - case DBVTF_VARIABLELENGTH: - case DBVT_BLOB: - if ( dbv->pbVal ) - free( dbv->pbVal ); - break; - } - - dbv->type = 0; -} - -void WriteVariant( HANDLE hContact, const char* module, const char* var, DBVARIANT* dbv ) -{ - DBCONTACTWRITESETTING dbw; - dbw.szModule = module; - dbw.szSetting = var; - dbw.value = *dbv; - CallService( MS_DB_CONTACT_WRITESETTING, (WPARAM)hContact, (LPARAM)&dbw ); -} - -// Returns true if pDBEI has been filled in with nice values -// Don't forget to free those pointers! -BOOL GetEvent(HANDLE hDbFile, DWORD dwOffset, DBEVENTINFO* pDBEI) -{ - DWORD dwBytesRead; - struct DBEvent pEvent; - static char pBlob[65536]; - - // Early reject - if (dwOffset == 0 || dwOffset >= dwFileSize) - return FALSE; - - // ** Read and verify the struct - if (SetFilePointer(hDbFile, dwOffset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) - return FALSE; - - if (!ReadFile(hDbFile, &pEvent, offsetof(struct DBEvent, blob), &dwBytesRead, NULL) || - (dwBytesRead != offsetof(struct DBEvent, blob))) - return FALSE; - - if (pEvent.signature != DBEVENT_SIGNATURE) - return FALSE; // Event corrupted - - // ** Read the blob - if ((!ReadFile(hDbFile, pBlob, pEvent.cbBlob, &dwBytesRead, NULL)) || - (dwBytesRead != pEvent.cbBlob)) - { - return FALSE; - } - - // ** Copy the static part to the event info struct - pDBEI->timestamp = pEvent.timestamp; - pDBEI->eventType = pEvent.eventType; - pDBEI->cbSize = sizeof(DBEVENTINFO); - pDBEI->cbBlob = pEvent.cbBlob; - pDBEI->pBlob = pBlob; - pDBEI->flags = (pEvent.flags & ~(DBEF_SENT+DBEF_READ)) + - ((pEvent.flags & DBEF_SENT) ? DBEF_SENT : DBEF_READ ); // Imported events are always marked READ - - if (!(pDBEI->szModule = GetName(hDbFile, pEvent.ofsModuleName))) { - return FALSE; - } - - // Unsane: encrypt dbevent - if (bEncrypted) - DecodeMemory(pDBEI->pBlob, pDBEI->cbBlob); - - return TRUE; -} - -// Returns a pointer to a string with the name -// from a DBModuleName struct if given a file offset -// Returns NULL on failure -char* GetName(HANDLE hDbFile, DWORD dwOffset) -{ - static DWORD dwLastOffset = 0; - static HANDLE hLastDbFile = NULL; - static char szName[256] = {0}; - - DWORD dwBytesRead; - struct DBModuleName pModule; - - // Early reject - if (dwOffset == 0 || dwOffset >= dwFileSize) - return FALSE; - - // Quick lookup - if (dwOffset == dwLastOffset && hDbFile == hLastDbFile) - return szName; - - // ** Read and verify the name struct - if (SetFilePointer(hDbFile, dwOffset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) - return NULL; - - if ((!ReadFile(hDbFile, &pModule, offsetof(struct DBModuleName, name), &dwBytesRead, NULL)) || - (dwBytesRead != offsetof(struct DBModuleName, name))) - return NULL; - - if (pModule.signature != DBMODULENAME_SIGNATURE) { - AddMessage( LPGEN("Modulename corrupted")); - return NULL; // ModuleName corrupted - } - - // ** Name struct OK, now read name into string buffer - if ((!ReadFile(hDbFile, szName, pModule.cbName, &dwBytesRead, NULL)) || (dwBytesRead != pModule.cbName)) { - return NULL; - } - - // terminate string - szName[pModule.cbName] = 0; - - // update last offset - dwLastOffset = dwOffset; - hLastDbFile = hDbFile; - - return szName; -} - -DWORD FindNextEvent(HANDLE hDbFile, DWORD dwOffset) -{ - DWORD dwBytesRead; - struct DBEvent pEvent; - - // Early reject - if (dwOffset == 0 || dwOffset >= dwFileSize) - return FALSE; - - // ** Read and verify the struct - if (SetFilePointer(hDbFile, dwOffset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) - return FALSE; - - if ((!ReadFile(hDbFile, &pEvent, sizeof(struct DBEvent), &dwBytesRead, NULL)) || - (dwBytesRead != sizeof(struct DBEvent))) - return FALSE; - - if ( pEvent.signature != DBEVENT_SIGNATURE || pEvent.ofsNext > dwFileSize ) - return FALSE; // Event corrupted - - return pEvent.ofsNext; -} - -int ImportGroups(HANDLE hDbFile, struct DBHeader* pdbHeader) -{ - struct DBContactSettings* pDbSettings; - struct DBContact DbContact; - char* pSetting; - DWORD dwOffset; - int nGroups = 0; - - // Find owner data - dwOffset = pdbHeader->ofsUser; - if (!GetContact(hDbFile, dwOffset, &DbContact)) { - AddMessage( LPGEN("No owner found.")); - return -1; - } - - // Find the module with the groups, and import them all - if ( pDbSettings = GetSettingsGroupByModuleName( hDbFile, &DbContact, "CListGroups" )) { - /*if (bEncrypted) - DecodeMemory(pDbSettings->blob, pDbSettings->cbBlob);*/ - pSetting = pDbSettings->blob; - while ( pSetting && *pSetting ) { - DBVARIANT dbv; - if ( GetSettingValue( pSetting, &dbv )) { - if ( CreateGroup( dbv.type, dbv.pszVal+1, NULL )) - nGroups++; - FreeVariant( &dbv ); - } - pSetting = GetNextSetting(pSetting); - } - free(pDbSettings); - - /*if (bEncrypted) - EncodeMemory(pDbSettings->blob, pDbSettings->cbBlob);*/ - } - - return nGroups; -} - -HANDLE ImportContact(HANDLE hDbFile, struct DBContact Contact) -{ - HANDLE hContact; - DBVARIANT group, nick, dbv; - char* pszProtoName; - char* pszUniqueSetting; - char* pszUserName; - char id[ 40 ]; - - // Check what protocol this contact belongs to - if ( !GetSetting( hDbFile, &Contact, "Protocol", "p", &dbv )) { - AddMessage( LPGEN("Skipping contact with no protocol")); - return INVALID_HANDLE_VALUE; - } - - pszProtoName = NEWSTR_ALLOCA( dbv.pszVal ); - FreeVariant( &dbv ); - - if ( !IsProtocolLoaded( pszProtoName )) { - AddMessage( LPGEN("Skipping contact, %s not installed."), pszProtoName ); - return INVALID_HANDLE_VALUE; - } - - // Skip protocols with no unique id setting (some non IM protocols return NULL) - pszUniqueSetting = (char*)CallProtoService(pszProtoName, PS_GETCAPS, PFLAG_UNIQUEIDSETTING, 0); - if ( !pszUniqueSetting || (INT_PTR)pszUniqueSetting == CALLSERVICE_NOTFOUND ) { - AddMessage( LPGEN("Skipping non-IM contact (%s)"), pszProtoName ); - return INVALID_HANDLE_VALUE; - } - - if ( !GetSetting(hDbFile, &Contact, pszProtoName, pszUniqueSetting, &dbv )) { - AddMessage( LPGEN("Skipping %s contact, ID not found"), pszProtoName ); - return INVALID_HANDLE_VALUE; - } - - // Does the contact already exist? - if ( dbv.type == DBVT_DWORD ) { - pszUserName = _ltoa( dbv.dVal, id, 10 ); - hContact = HContactFromNumericID( pszProtoName, pszUniqueSetting, dbv.dVal ); - } - else { - pszUserName = NEWSTR_ALLOCA( dbv.pszVal ); - hContact = HContactFromID( pszProtoName, pszUniqueSetting, dbv.pszVal ); - } - - if ( hContact != INVALID_HANDLE_VALUE ) { - AddMessage( LPGEN("Skipping duplicate %s contact %s"), pszProtoName, pszUserName ); - FreeVariant( &dbv ); - return INVALID_HANDLE_VALUE; - } - // No, add contact and copy some important settings - GetSetting(hDbFile, &Contact, "CList", "Group", &group); - - if ( !GetSetting( hDbFile, &Contact, "CList", "MyHandle", &nick )) - GetSetting(hDbFile, &Contact, pszProtoName, "Nick", &nick ); - - hContact = AddContact( hdlgProgress, pszProtoName, pszUniqueSetting, &dbv, &nick, &group ); - - if ( hContact != INVALID_HANDLE_VALUE) { - - // Hidden? - if ( GetSetting( hDbFile, &Contact, "CList", "Hidden", &dbv )) { - WriteVariant( hContact, "CList", "Hidden", &dbv ); - FreeVariant( &dbv ); - } - // Ignore settings - if ( GetSetting( hDbFile, &Contact, "Ignore", "Mask1", &dbv )) { - WriteVariant( hContact, "Ignore", "Mask1", &dbv ); - FreeVariant( &dbv ); - } - - // Apparent mode - if ( GetSetting( hDbFile, &Contact, pszProtoName, "ApparentMode", &dbv )) { - WriteVariant( hContact, pszProtoName, "ApparentMode", &dbv ); - FreeVariant( &dbv ); - } - - // Nick - if ( GetSetting( hDbFile, &Contact, pszProtoName, "Nick", &dbv )) { - WriteVariant( hContact, pszProtoName, "Nick", &dbv ); - FreeVariant( &dbv ); - } - - // Myhandle - if ( GetSetting( hDbFile, &Contact, pszProtoName, "MyHandle", &dbv )) { - WriteVariant( hContact, pszProtoName, "MyHandle", &dbv ); - FreeVariant( &dbv ); - } - - // First name - if ( GetSetting( hDbFile, &Contact, pszProtoName, "FirstName", &dbv )) { - WriteVariant( hContact, pszProtoName, "FirstName", &dbv ); - FreeVariant( &dbv ); - } - - // Last name - if ( GetSetting( hDbFile, &Contact, pszProtoName, "LastName", &dbv )) { - WriteVariant( hContact, pszProtoName, "LastName", &dbv ); - FreeVariant( &dbv ); - } - - // About - if ( GetSetting( hDbFile, &Contact, pszProtoName, "About", &dbv )) { - WriteVariant( hContact, pszProtoName, "About", &dbv ); - FreeVariant( &dbv ); - } - } - else AddMessage( LPGEN("Unknown error while adding %s contact %s"), pszProtoName, pszUserName ); - - return hContact; -} - -// This function should always be called after contact import. That is -// why there are no messages for errors related to contacts. Those -// would only be a repetition of the messages printed during contact -// import. - -static void ImportHistory(HANDLE hDbFile, struct DBContact Contact, PROTOCOLDESCRIPTOR **protocol, int protoCount) -{ - HANDLE hContact = INVALID_HANDLE_VALUE; - DWORD dwOffset; - MSG msg; - DBVARIANT proto; - int i, skipAll, bIsVoidContact; - - // Is it contats history import? - if ( protoCount == 0 ) { - - // Check what protocol this contact belongs to - if ( GetSetting( hDbFile, &Contact, "Protocol", "p", &proto )) { - - // Protocol installed? - if ( IsProtocolLoaded( proto.pszVal )) { - // Is contact in database? - char* pszUniqueSetting = (char*)CallProtoService( proto.pszVal, PS_GETCAPS, PFLAG_UNIQUEIDSETTING, 0); - - // Skip protocols with no unique id setting (some non IM protocols return NULL) - if ( pszUniqueSetting && ( INT_PTR )pszUniqueSetting != CALLSERVICE_NOTFOUND ) { - DBVARIANT dbv; - if ( GetSetting( hDbFile, &Contact, proto.pszVal, pszUniqueSetting, &dbv )) { - if ( dbv.type == DBVT_DWORD ) - hContact = HContactFromNumericID( proto.pszVal, pszUniqueSetting, dbv.dVal ); - else - hContact = HContactFromID( proto.pszVal, pszUniqueSetting, dbv.pszVal ); - FreeVariant( &dbv ); - } } } - FreeVariant( &proto ); - } - } - else hContact = NULL; //system history import - - // OK to import this chain? - if (hContact == INVALID_HANDLE_VALUE) { - nSkippedContacts++; - return; - } - - i = skipAll = 0; - bIsVoidContact = CallService( MS_DB_EVENT_GETCOUNT, ( WPARAM )hContact, 0 ) == 0; - - // Get the start of the event chain - dwOffset = Contact.ofsFirstEvent; - while (dwOffset) { - int skip = 0; - - // Copy the event and import it - DBEVENTINFO dbei = { 0 }; - if (GetEvent(hDbFile, dwOffset, &dbei)) { - // check protocols during system history import - if (hContact == NULL) { - int i; - skipAll = 1; - - for(i = 0; i < protoCount; i++) - if (!strcmp(dbei.szModule, protocol[i]->szName)) { //&& protocol[i]->type == PROTOTYPE_PROTOCOL) - skipAll = 0; - break; - } - - skip = skipAll; - } - - // custom filtering - if (!skip && nImportOption == IMPORT_CUSTOM) { - BOOL sent = (dbei.flags&DBEF_SENT); - - if (dbei.timestamp < (DWORD)dwSinceDate) - skip = 1; - - if (!skip) { - if (hContact) { - skip = 1; - switch(dbei.eventType) { - case EVENTTYPE_MESSAGE: - if ((sent?IOPT_MSGSENT:IOPT_MSGRECV)&nCustomOptions) - skip = 0; - break; - case EVENTTYPE_FILE: - if ((sent?IOPT_FILESENT:IOPT_FILERECV)&nCustomOptions) - skip = 0; - break; - case EVENTTYPE_URL: - if ((sent?IOPT_URLSENT:IOPT_URLRECV)&nCustomOptions) - skip = 0; - break; - default: - if ((sent?IOPT_OTHERSENT:IOPT_OTHERRECV)&nCustomOptions) - skip = 0; - break; - } - } - else if ( !( nCustomOptions & IOPT_SYSTEM )) - skip = 1; - } - - if (skip) - nSkippedEvents++; - } - - if (!skip) { - // Check for duplicate entries - if ( !IsDuplicateEvent( hContact, dbei )) { - // Add dbevent - if (!bIsVoidContact) - dbei.flags &= ~DBEF_FIRST; - if (CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei)) - nMessagesCount++; - else - AddMessage( LPGEN("Failed to add message")); - } - else - nDupes++; - } - } - - if ( !( i%10 )) { - if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } } - - // skip this chain if needed - if ( skipAll ) - break; - - // Get next event - dwOffset = FindNextEvent(hDbFile, dwOffset); - i++; - } -} - -static void MirandaImport(HWND hdlg) -{ - int nDBVersion; - int i; - int nNumberOfContacts = 0; - MSG msg; - DWORD dwTimer; - DWORD dwOffset; - HANDLE hFile; - char* pszModuleName = NULL; - struct DBHeader* pdbHeader = NULL; - struct DBContact Contact; - - // Just to keep the macros happy - hdlgProgress = hdlg; - - // Reset statistics - nSkippedEvents = 0; - nDupes = 0; - nContactsCount = 0; - nMessagesCount = 0; - nGroupsCount = 0; - nSkippedContacts = 0; - SetProgress(0); - - // Open database - hFile = CreateFile(importFile, - GENERIC_READ, // open for reading - 0, // do not share - NULL, // no security - OPEN_EXISTING, // existing file only - FILE_ATTRIBUTE_NORMAL, // normal file - NULL); // no attr. template - - // Read error - if (hFile == INVALID_HANDLE_VALUE) { - AddMessage( LPGEN("Could not open file.")); - SetProgress(100); - return; - } - - // Check filesize - dwFileSize = GetFileSize(hFile, NULL) ; - if ((dwFileSize == INVALID_FILE_SIZE) || (dwFileSize < sizeof(struct DBHeader))) { - AddMessage( LPGEN("This is not a valid Miranda IM database.")); - SetProgress(100); - CloseHandle(hFile); - return; - } - - // Check header and database version - nDBVersion = CheckFileFormat(hFile); - if (nDBVersion == DB_INVALID) { - AddMessage( LPGEN("This is not a valid Miranda IM database.")); - SetProgress(100); - CloseHandle(hFile); - return; - } - - // Load database header - if (!(pdbHeader = GetHeader(hFile))) { - AddMessage( LPGEN("Read failure.")); - SetProgress(100); - CloseHandle(hFile); - return; - } - - // Get number of contacts - nNumberOfContacts = pdbHeader->contactCount; - AddMessage( LPGEN("Number of contacts in database: %d"), nNumberOfContacts ); - AddMessage( "" ); - - // Configure database for fast writing - CallService(MS_DB_SETSAFETYMODE, FALSE, 0); - - // Start benchmark timer - dwTimer = time(NULL); - - // Import Groups - if (nImportOption == IMPORT_ALL || (nCustomOptions & IOPT_GROUPS)) { - AddMessage( LPGEN("Importing groups.")); - nGroupsCount = ImportGroups(hFile, pdbHeader); - if (nGroupsCount == -1) - AddMessage( LPGEN("Group import failed.")); - - AddMessage( "" ); - } - // End of Import Groups - - // Import Contacts - if (nImportOption != IMPORT_CUSTOM || (nCustomOptions & IOPT_CONTACTS)) { - AddMessage( LPGEN("Importing contacts.")); - i = 1; - dwOffset = FindFirstContact(pdbHeader); - while (dwOffset && (dwOffset < dwFileSize)) { - if (!GetContact(hFile, dwOffset, &Contact)) { - AddMessage( LPGEN("ERROR: Chain broken, no valid contact at %d"), dwOffset ); - SetProgress(100); - break; - } - - if (ImportContact(hFile, Contact) != INVALID_HANDLE_VALUE) - nContactsCount++; - - // Update progress bar - SetProgress(100 * i / nNumberOfContacts); - i++; - - // Process queued messages - if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - // Get next contact in chain - dwOffset = FindNextContact(&Contact); - } - } - else AddMessage( LPGEN("Skipping new contacts import.")); - AddMessage( "" ); - // End of Import Contacts - - // Import history - if (nImportOption != IMPORT_CONTACTS) { - // Import NULL contact message chain - if (nImportOption == IMPORT_ALL || (nCustomOptions & IOPT_SYSTEM)) { - AddMessage( LPGEN("Importing system history.")); - dwOffset = FindOwnerContact(pdbHeader); - if (!GetContact(hFile, dwOffset, &Contact)) { - AddMessage( LPGEN("ERROR: Chain broken, no valid contact at %d"), dwOffset ); - SetProgress(100); - } - else { - PROTOCOLDESCRIPTOR **protocol; - int protoCount; - - CallService(MS_PROTO_ENUMPROTOCOLS, (WPARAM)&protoCount, (LPARAM)&protocol); - - if (protoCount > 0) - ImportHistory(hFile, Contact, protocol, protoCount); - } - } - else AddMessage( LPGEN("Skipping system history import.")); - - AddMessage( "" ); - - // Import other contact messages - if (nImportOption == IMPORT_ALL || (nCustomOptions & 2046)) { // 2 - 1024 types - AddMessage( LPGEN("Importing history.")); - dwOffset = FindFirstContact(pdbHeader); - for(i=1; i <= nNumberOfContacts; i++) { - if (!GetContact(hFile, dwOffset, &Contact)) { - AddMessage( LPGEN("ERROR: Chain broken, no valid contact at %d"), dwOffset ); - SetProgress(100); - break; - } - - ImportHistory(hFile, Contact, NULL, 0); - - SetProgress(100 * i / nNumberOfContacts); - dwOffset = FindNextContact(&Contact); - } - } - else AddMessage( LPGEN("Skipping history import.")); - - AddMessage( "" ); - } - // End of Import History - - // Restore database writing mode - CallService(MS_DB_SETSAFETYMODE, TRUE, 0); - - // Clean up before exit - CloseHandle(hFile); - free(pdbHeader); - - // Stop timer - dwTimer = time(NULL) - dwTimer; - - // Print statistics - AddMessage( LPGEN("Import completed in %d seconds."), dwTimer ); - SetProgress(100); - AddMessage((nImportOption == IMPORT_CONTACTS) ? - LPGEN("Added %d contacts and %d groups.") : LPGEN("Added %d contacts, %d groups and %d events."), - nContactsCount, nGroupsCount, nMessagesCount); - - if ( nImportOption != IMPORT_CONTACTS ) { - if (nSkippedContacts) - AddMessage( LPGEN("Skipped %d contacts."), nSkippedContacts ); - - AddMessage((nImportOption == IMPORT_CUSTOM) ? - LPGEN("Skipped %d duplicates and %d filtered events.") : LPGEN("Skipped %d duplicates."), - nDupes, nSkippedEvents); -} } diff --git a/plugins/Dbx_mmap_SA/Import_SA/miranda.cpp b/plugins/Dbx_mmap_SA/Import_SA/miranda.cpp new file mode 100644 index 0000000000..69b348d192 --- /dev/null +++ b/plugins/Dbx_mmap_SA/Import_SA/miranda.cpp @@ -0,0 +1,1502 @@ +/* + +Import plugin for Miranda IM + +Copyright (C) 2001-2005 Martin Öberg, Richard Hughes, Roland Rabien & Tristan Van de Vreede + +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. + +*/ + +// ============== +// == INCLUDES == +// ============== + +#include "import.h" + +#include "mirandadb0700.h" + +// ====================== +// == GLOBAL FUNCTIONS == +// ====================== + +HANDLE HContactFromNumericID(char* pszProtoName, char* pszSetting, DWORD dwID); +HANDLE HContactFromID(char* pszProtoName, char* pszSetting, char* pszID); + +HANDLE AddContact(HWND hdlgProgress, char* pszProtoName, char* pszUniqueSetting, DBVARIANT* id, DBVARIANT* nick, DBVARIANT* group); + +BOOL IsProtocolLoaded(char* pszProtocolName); +BOOL IsDuplicateEvent(HANDLE hContact, DBEVENTINFO dbei); + +INT_PTR CALLBACK ImportTypePageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam); +INT_PTR CALLBACK FinishedPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam); +INT_PTR CALLBACK ProgressPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam); +INT_PTR CALLBACK MirandaOptionsPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam); +INT_PTR CALLBACK MirandaAdvOptionsPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam); + +// ===================== +// == LOCAL FUNCTIONS == +// ===================== + +void MirandaImport(HWND hdlgProgress); +int CheckFileFormat(HANDLE hFile); +static HANDLE ImportContact(HANDLE hDbFile, struct DBContact Contact); +static void ImportHistory(HANDLE hDbFile, struct DBContact Contact, PROTOCOLDESCRIPTOR **protocol, int protoCount); +static int ImportGroups(HANDLE hDbFile, struct DBHeader *pdbHeader); + +#define NEWSTR_ALLOCA(A) (A==NULL)?NULL:strcpy((char*)alloca(strlen(A)+1),A) + +// Comment: The Find* functions only return a file offset. +// The Get* functions actually reads the requested +// data from the file and gives you a pointer to a structure +// containing the data. + +DWORD FindFirstContact(struct DBHeader* pDbHeader); +DWORD FindNextContact(struct DBContact* pDbContact); +DWORD FindNextEvent(HANDLE hDbFile, DWORD dwOffset); +DWORD FindOwnerContact(struct DBHeader* pDbHeader); + +int GetContactCount(struct DBHeader* pDbHeader); +BOOL GetContact(HANDLE hDbFile, DWORD dwOffset, struct DBContact* pDbContact); +BOOL GetSetting(HANDLE hDbFile, struct DBContact* pDbContact, char* pszModuleName, char* pszSettingName, DBVARIANT* pValue); +char* GetNextSetting(char* pDbSetting); +BOOL GetSettings(HANDLE hDbFile, DWORD dwOffset, struct DBContactSettings** pDbSettings); +struct DBContactSettings* GetSettingsGroupByModuleName(HANDLE hdbFile, struct DBContact* pDbContact, char* pszName); +DWORD GetBlobSize(struct DBContactSettings* pDbSettings); +int GetSettingByName(struct DBContactSettings* pDbSettings, char* pszSettingName, DBVARIANT* pValue); +int GetSettingValue(char* pBlob,DBVARIANT* pValue); + +BOOL GetEvent(HANDLE hDbFile, DWORD dwOffset, DBEVENTINFO* pDBEI); +char* GetName(HANDLE hDbFile, DWORD dwOffset); + + +// ====================== +// == GLOBAL VARIABLES == +// ====================== + +extern void (*DoImport)(HWND); +extern int nImportOption; +extern int nCustomOptions; + + +// ===================== +// == LOCAL VARIABLES == +// ===================== + +TCHAR importFile[MAX_PATH]; +HWND hdlgProgress; +DWORD dwFileSize; + +DWORD nDupes; +DWORD nContactsCount; +DWORD nMessagesCount; +DWORD nGroupsCount; +DWORD nSkippedEvents; +DWORD nSkippedContacts; + +time_t dwSinceDate = 0; + +// ============= +// == DEFINES == +// ============= + +#define EVENTTYPE_MESSAGE 0 +#define EVENTTYPE_URL 1 +#define EVENTTYPE_FILE 1002 + + +// Supported database versions +#define DB_INVALID 0x00000000 // Unknown or corrupted DAT +#define DB_000700 0x00000700 // Miranda 0.1.0.0 - 0.1.2.2+ + +// DAT file signature +struct DBSignature { + char name[15]; + BYTE eof; +}; + +static struct DBSignature dbSignature={"Miranda ICQ DB",0x1A}; + +// Unsane: Secured signature +static struct DBSignature dbSignatureEncrypted={"Miranda ICQ SD",0x1A}; + +// ==================== +// ==================== +// == IMPLEMENTATION == +// ==================== +// ==================== + +static void SearchForLists(HWND hdlg, const TCHAR *mirandaPath, const TCHAR *mirandaProf, const TCHAR *pattern, const TCHAR *type) +{ + HANDLE hFind; + WIN32_FIND_DATA fd; + TCHAR szSearchPath[MAX_PATH]; + TCHAR szRootName[MAX_PATH]; + TCHAR* str2; + int i; + + mir_sntprintf(szSearchPath, SIZEOF(szSearchPath), _T("%s\\%s"), mirandaPath, pattern); + hFind = FindFirstFile(szSearchPath, &fd); + if (hFind != INVALID_HANDLE_VALUE) + { + do + { + _tcscpy(szRootName, fd.cFileName); + str2 = _tcsrchr(szRootName, '.'); + if (str2 != NULL) *str2 = 0; + if (mirandaProf == NULL || _tcsicmp(mirandaProf, szRootName)) + { + _tcscat(szRootName, type); + i = SendDlgItemMessage(hdlg, IDC_LIST, LB_ADDSTRING, 0, (LPARAM)szRootName); + str2 = (TCHAR*)mir_alloc((_tcslen(mirandaPath) + 2 + _tcslen(fd.cFileName)) * sizeof(TCHAR)); + wsprintf(str2, _T("%s\\%s"), mirandaPath, fd.cFileName); + SendDlgItemMessage(hdlg, IDC_LIST, LB_SETITEMDATA, i, (LPARAM)str2); + } + } + while( FindNextFile( hFind, &fd )); + + FindClose( hFind ); + } +} + +INT_PTR CALLBACK MirandaPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam) +{ + switch(message) { + case WM_INITDIALOG: + TranslateDialogDefault(hdlg); + { + TCHAR *pfd, *pfd1, *pfd2, *pfn; + + REPLACEVARSDATA dat = {0}; + dat.cbSize = sizeof(dat); + dat.dwFlags = RVF_TCHAR; + + pfd = (TCHAR*)CallService(MS_UTILS_REPLACEVARS, (WPARAM)_T("%miranda_path%\\Profiles"), (LPARAM)&dat); + pfd1 = (TCHAR*)CallService(MS_UTILS_REPLACEVARS, (WPARAM)_T("%miranda_path%"), (LPARAM)&dat); + pfd2 = (TCHAR*)CallService(MS_UTILS_REPLACEVARS, (WPARAM)_T("%miranda_profile%"), (LPARAM)&dat); + pfn = (TCHAR*)CallService(MS_UTILS_REPLACEVARS, (WPARAM)_T("%miranda_profilename%"), (LPARAM)&dat); + + SearchForLists(hdlg, pfd2, pfn, _T("*.dat"), _T(" (Miranda IM v0.x)")); + // Unsane: check for exclude equal or used profiles + if (lstrcmpi(pfd1, pfd2)) + SearchForLists(hdlg, pfd1, NULL, _T("*.dat"), _T(" (Miranda IM v0.x)")); + if (lstrcmpi(pfd, pfd2)) + SearchForLists(hdlg, pfd, NULL, _T("*.dat"), _T(" (Miranda IM v0.x)")); + + mir_free(pfn); + mir_free(pfd2); + mir_free(pfd1); + mir_free(pfd); + return TRUE; + } + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDC_BACK: + PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_IMPORTTYPE,(LPARAM)ImportTypePageProc); + break; + + case IDOK: + { + TCHAR filename[MAX_PATH]; + + GetDlgItemText(hdlg, IDC_FILENAME, filename, SIZEOF(filename)); + if (_taccess(filename, 4)) { + MessageBox(hdlg, TranslateT("The given file does not exist. Please check that you have entered the name correctly."), TranslateT("Miranda Import"), MB_OK); + break; + } + lstrcpy(importFile, filename); + PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_OPTIONS,(LPARAM)MirandaOptionsPageProc); + } + break; + + case IDCANCEL: + PostMessage(GetParent(hdlg),WM_CLOSE,0,0); + break; + + case IDC_LIST: + if(HIWORD(wParam)==LBN_SELCHANGE) { + int sel = SendDlgItemMessage(hdlg, IDC_LIST, LB_GETCURSEL, 0, 0); + if (sel == LB_ERR) break; + SetDlgItemText(hdlg, IDC_FILENAME, (TCHAR*)SendDlgItemMessage(hdlg, IDC_LIST, LB_GETITEMDATA, sel, 0)); + } + break; + + case IDC_OTHER: + { + OPENFILENAME ofn; + TCHAR str[MAX_PATH], text[256]; + TCHAR *pfd; + int index; + + pfd = Utils_ReplaceVarsT(_T("%miranda_profile%")); + + // TranslateTS doesnt translate \0 separated strings + index = mir_sntprintf(text, 64, _T("%s (*.dat)"), TranslateT("Miranda IM database")) + 1; + _tcscpy(text + index, _T("*.dat")); index += 6; + index += mir_sntprintf(text + index, 64, _T("%s (*.*)"), TranslateT("All Files")) + 1; + _tcscpy(text + index, _T("*.*")); index += 4; + text[index] = 0; + + GetDlgItemText(hdlg, IDC_FILENAME, str, SIZEOF(str)); + ZeroMemory(&ofn, sizeof(ofn)); + ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; + ofn.hwndOwner = hdlg; + ofn.lpstrFilter = text; + ofn.lpstrDefExt = _T("dat"); + ofn.lpstrFile = str; + ofn.Flags = OFN_FILEMUSTEXIST | OFN_EXPLORER | OFN_NOCHANGEDIR | OFN_DONTADDTORECENT; + ofn.nMaxFile = SIZEOF(str); + ofn.lpstrInitialDir = pfd; + if (GetOpenFileName(&ofn)) + SetDlgItemText(hdlg,IDC_FILENAME,str); + + mir_free(pfd); + break; + } + } + break; + case WM_DESTROY: + { + int i; + + for(i=SendDlgItemMessage(hdlg,IDC_LIST,LB_GETCOUNT,0,0)-1;i>=0;i--) + mir_free((char*)SendDlgItemMessage(hdlg,IDC_LIST,LB_GETITEMDATA,i,0)); + break; + } } + + return FALSE; +} + + +INT_PTR CALLBACK MirandaOptionsPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam) +{ + switch(message) { + case WM_INITDIALOG: + TranslateDialogDefault(hdlg); + EnableWindow(GetDlgItem(hdlg,IDC_RADIO_ALL), TRUE); + EnableWindow(GetDlgItem(hdlg,IDC_STATIC_ALL), TRUE); + EnableWindow(GetDlgItem(hdlg,IDC_RADIO_CONTACTS), TRUE); + EnableWindow(GetDlgItem(hdlg,IDC_STATIC_CONTACTS), TRUE); + EnableWindow(GetDlgItem(hdlg,IDC_RADIO_CUSTOM), TRUE); + EnableWindow(GetDlgItem(hdlg,IDC_STATIC_CUSTOM), TRUE); + CheckDlgButton(hdlg,IDC_RADIO_ALL,BST_UNCHECKED); + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDC_BACK: + PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_MIRANDADB,(LPARAM)MirandaPageProc); + break; + + case IDOK: + if(IsDlgButtonChecked(hdlg,IDC_RADIO_ALL)) { + nImportOption = IMPORT_ALL; + nCustomOptions = 0;//IOPT_MSGSENT|IOPT_MSGRECV|IOPT_URLSENT|IOPT_URLRECV; + DoImport = MirandaImport; + PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_PROGRESS,(LPARAM)ProgressPageProc); + break; + } + + if(IsDlgButtonChecked(hdlg,IDC_RADIO_CONTACTS)) { + nImportOption = IMPORT_CONTACTS; + nCustomOptions = 0; + DoImport = MirandaImport; + PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_PROGRESS,(LPARAM)ProgressPageProc); + break; + } + + if(IsDlgButtonChecked(hdlg,IDC_RADIO_CUSTOM)) { + PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_ADVOPTIONS,(LPARAM)MirandaAdvOptionsPageProc); + break; + } + break; + + case IDCANCEL: + PostMessage(GetParent(hdlg), WM_CLOSE, 0, 0); + break; + } + break; + } + return FALSE; +} + +static const UINT InControls[]={IDC_IN_MSG,IDC_IN_URL,IDC_IN_FT,IDC_IN_OTHER}; +static const UINT OutControls[]={IDC_OUT_MSG,IDC_OUT_URL,IDC_OUT_FT,IDC_OUT_OTHER}; +static const UINT SysControls[]={IDC_CONTACTS, IDC_SYSTEM}; + +INT_PTR CALLBACK MirandaAdvOptionsPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam) +{ + switch(message) { + case WM_INITDIALOG: + TranslateDialogDefault(hdlg); + { + struct tm *TM = NULL; + struct _SYSTEMTIME ST = {0}; + + dwSinceDate = DBGetContactSettingDword(NULL,IMPORT_MODULE,"ImportSinceTS",time(NULL)); + + TM = localtime(&dwSinceDate); + + ST.wYear = TM->tm_year + 1900; + ST.wMonth = TM->tm_mon + 1; + ST.wDay = TM->tm_mday; + + DateTime_SetSystemtime(GetDlgItem(hdlg,IDC_DATETIMEPICKER),GDT_VALID,&ST); + } + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDC_BACK: + PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_OPTIONS,(LPARAM)MirandaOptionsPageProc); + break; + + case IDOK: + DoImport = MirandaImport; + nImportOption = IMPORT_CUSTOM; + nCustomOptions = 0; + + if (IsDlgButtonChecked(hdlg,IDC_CONTACTS)) + nCustomOptions |= IOPT_CONTACTS | IOPT_GROUPS; + if (IsDlgButtonChecked(hdlg,IDC_SYSTEM)) + nCustomOptions |= IOPT_SYSTEM; + + // incoming + if (IsDlgButtonChecked(hdlg,IDC_IN_MSG)) + nCustomOptions |= IOPT_MSGRECV; + if (IsDlgButtonChecked(hdlg,IDC_IN_URL)) + nCustomOptions |= IOPT_URLRECV; + if (IsDlgButtonChecked(hdlg,IDC_IN_FT)) + nCustomOptions |= IOPT_FILERECV; + if (IsDlgButtonChecked(hdlg,IDC_IN_OTHER)) + nCustomOptions |= IOPT_OTHERRECV; + + // outgoing + if (IsDlgButtonChecked(hdlg,IDC_OUT_MSG)) + nCustomOptions |= IOPT_MSGSENT; + if (IsDlgButtonChecked(hdlg,IDC_OUT_URL)) + nCustomOptions |= IOPT_URLSENT; + if (IsDlgButtonChecked(hdlg,IDC_OUT_FT)) + nCustomOptions |= IOPT_FILESENT; + if (IsDlgButtonChecked(hdlg,IDC_OUT_OTHER)) + nCustomOptions |= IOPT_OTHERSENT; + + // since date + dwSinceDate = 0; + + if ( IsDlgButtonChecked( hdlg, IDC_SINCE )) { + struct _SYSTEMTIME ST = {0}; + + if (DateTime_GetSystemtime(GetDlgItem(hdlg,IDC_DATETIMEPICKER), &ST) == GDT_VALID) { + struct tm TM = {0}; + + TM.tm_mday = ST.wDay; + TM.tm_mon = ST.wMonth - 1; + TM.tm_year = ST.wYear - 1900; + + dwSinceDate = mktime(&TM); + + DBWriteContactSettingDword(NULL,IMPORT_MODULE,"ImportSinceTS",dwSinceDate); + } } + + if (nCustomOptions) + PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_PROGRESS,(LPARAM)ProgressPageProc); + break; + + case IDCANCEL: + PostMessage(GetParent(hdlg), WM_CLOSE, 0, 0); + break; + + case IDC_SINCE: + EnableWindow(GetDlgItem(hdlg, IDC_DATETIMEPICKER), IsDlgButtonChecked(hdlg, IDC_SINCE)); + break; + + if (HIWORD(wParam) != STN_CLICKED) + break; + + case IDC_ALL: + case IDC_INCOMING: + case IDC_OUTGOING: + { + int i; + + if (LOWORD(wParam) == IDC_ALL) + for (i = 0; i < sizeof(SysControls)/sizeof(SysControls[0]); i++) + CheckDlgButton(hdlg,SysControls[i], !IsDlgButtonChecked(hdlg,SysControls[i])); + + if (LOWORD(wParam) != IDC_OUTGOING) + for (i = 0; i < sizeof(InControls)/sizeof(InControls[0]); i++) + CheckDlgButton(hdlg,InControls[i], !IsDlgButtonChecked(hdlg,InControls[i])); + + if (LOWORD(wParam) != IDC_INCOMING) + for (i = 0; i < sizeof(OutControls)/sizeof(OutControls[0]); i++) + CheckDlgButton(hdlg,OutControls[i], !IsDlgButtonChecked(hdlg,OutControls[i])); + } + break; + + case IDC_MSG: + CheckDlgButton(hdlg,IDC_IN_MSG, !IsDlgButtonChecked(hdlg,IDC_IN_MSG)); + CheckDlgButton(hdlg,IDC_OUT_MSG, !IsDlgButtonChecked(hdlg,IDC_OUT_MSG)); + break; + + case IDC_URL: + CheckDlgButton(hdlg,IDC_IN_URL, !IsDlgButtonChecked(hdlg,IDC_IN_URL)); + CheckDlgButton(hdlg,IDC_OUT_URL, !IsDlgButtonChecked(hdlg,IDC_OUT_URL)); + break; + + case IDC_FT: + CheckDlgButton(hdlg,IDC_IN_FT, !IsDlgButtonChecked(hdlg,IDC_IN_FT)); + CheckDlgButton(hdlg,IDC_OUT_FT, !IsDlgButtonChecked(hdlg,IDC_OUT_FT)); + break; + + case IDC_OTHER: + CheckDlgButton(hdlg,IDC_IN_OTHER, !IsDlgButtonChecked(hdlg,IDC_IN_OTHER)); + CheckDlgButton(hdlg,IDC_OUT_OTHER, !IsDlgButtonChecked(hdlg,IDC_OUT_OTHER)); + break; + } + break; + } + return FALSE; +} + +#ifndef INVALID_SET_FILE_POINTER +#define INVALID_SET_FILE_POINTER ((DWORD)-1) +#endif + +// Read header from file, returns null on failure +struct DBHeader* GetHeader(HANDLE hDbFile) +{ + struct DBHeader* pdbHeader; + DWORD dwBytesRead; + + if (( pdbHeader = calloc(1, sizeof(struct DBHeader))) == NULL ) + return NULL; + + // Goto start of file + if (SetFilePointer(hDbFile, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) + return FALSE; + + // Read header + if ( !ReadFile(hDbFile, pdbHeader, sizeof(struct DBHeader), &dwBytesRead, NULL ) || + dwBytesRead != sizeof(struct DBHeader)) + return NULL; + + // Return pointer to header + return pdbHeader; +} + +// Unsane: database crypted status +BOOL bEncrypted; +// Unsane: crypted database work fuction +int CheckPassword(WORD version, WORD cryptorUID, TCHAR * szDBName); +void InitSecurity(); + +int CheckFileFormat(HANDLE hDbFile) +{ + struct DBHeader* pdbHeader; + TCHAR* tszDbName; + + // Read header + if (( pdbHeader = GetHeader(hDbFile)) == NULL ) + return DB_INVALID; + + // Check header signature + bEncrypted = FALSE; + if (memcmp(pdbHeader->signature, &dbSignature, sizeof(pdbHeader->signature))) { + // Unsane: if not encrypted signature + if (memcmp(pdbHeader->signature, &dbSignatureEncrypted, sizeof(pdbHeader->signature))) { + AddMessage( LPGEN("Signature mismatch" )); + return DB_INVALID; + } + AddMessage(LPGEN("Database is Secured MMAP database")); + // Unsane: check password + InitSecurity(); + tszDbName = _tcsrchr(importFile, _T('\\')) + 1; + if (CheckPassword(pdbHeader->checkWord, pdbHeader->cryptorUID, tszDbName)) { + AddMessage(LPGEN("Secured MMAP: authorization successful")); + bEncrypted = TRUE; + } + else + { + AddMessage(LPGEN("You are not authorized for access to Database")); + return DB_INVALID; + } + } + + // Determine Miranda version + switch (pdbHeader->checkWord) { + case DB_000700: + AddMessage( LPGEN("This looks like a Miranda database, version 0.1.0.0 or above." )); + free(pdbHeader); + return DB_000700; + + default: + if (!bEncrypted){ + AddMessage( LPGEN("Version mismatch" )); + free(pdbHeader); + return DB_INVALID; + } + break; +} } + +// High level Miranda DB access functions +// Returns true if pValue points to the requested value + +BOOL GetSetting(HANDLE hDbFile, struct DBContact* pDbContact, char* pszModuleName, char* pszSettingName, DBVARIANT* pValue) +{ + struct DBContactSettings* pDbSettings; + if ( pDbSettings = GetSettingsGroupByModuleName(hDbFile, pDbContact, pszModuleName)) { + if ( GetSettingByName( pDbSettings, pszSettingName, pValue )) { + free(pDbSettings); + return TRUE; + } + #ifdef _LOGGING + AddMessage( LPGEN("Failed to find setting %s" ), pszSettingName ); + #endif + free(pDbSettings); + } +#ifdef _LOGGING + else AddMessage( LPGEN("Failed to find module %s" ), pszModuleName ); +#endif + + // Search failed + pValue->type = 0; + return FALSE; +} + +// ** +// ** CONTACT CHAIN +// ** + +// Return offset to first contact +DWORD FindFirstContact(struct DBHeader* pDbHeader) +{ + if (!pDbHeader) + return 0; + + return pDbHeader->ofsFirstContact; +} + +DWORD FindOwnerContact(struct DBHeader* pDbHeader) +{ + if (!pDbHeader) + return 0; + + return pDbHeader->ofsUser; +} + +// Return offset to next contact +DWORD FindNextContact(struct DBContact* pDbContact) +{ + if (!pDbContact) + return 0; + + if (pDbContact->signature != DBCONTACT_SIGNATURE) + return 0; + + return pDbContact->ofsNext; +} + + +// Read the contact at offset 'dwOffset' +// Returns true if successful and pDbContact points to the contact struct +// pDbContact must point to allocated struct +BOOL GetContact(HANDLE hDbFile, DWORD dwOffset, struct DBContact* pDbContact) +{ + DWORD dwBytesRead; + + // Early reject + if (dwOffset == 0 || dwOffset >= dwFileSize) + return FALSE; + + // ** Read and verify the struct + + if (SetFilePointer(hDbFile, (LONG)dwOffset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) + return FALSE; + + if ((!ReadFile(hDbFile, pDbContact, sizeof(struct DBContact), &dwBytesRead, NULL)) || + (dwBytesRead != sizeof(struct DBContact))) + return FALSE; + + if ((pDbContact->signature != DBCONTACT_SIGNATURE) || + (pDbContact->ofsNext >= dwFileSize)) + return FALSE; // Contact corrupted + + return TRUE; +} + +// Return ptr to next setting in settings struct +char* GetNextSetting(char* pDbSetting) +{ + // Get next setting + pDbSetting = pDbSetting + *pDbSetting+1; // Skip name + switch( *(BYTE*)pDbSetting ) { + case DBVT_BYTE: + pDbSetting = pDbSetting+1+1; + break; + + case DBVT_WORD: + pDbSetting = pDbSetting+1+2; + break; + + case DBVT_DWORD: + pDbSetting = pDbSetting+1+4; + break; + + case DBVT_ASCIIZ: + case DBVT_UTF8: + case DBVT_BLOB: + case DBVTF_VARIABLELENGTH: + pDbSetting = pDbSetting + 3 + *(WORD*)(pDbSetting+1); + break; + + case DBVT_DELETED: + AddMessage( LPGEN("DEBUG: Deleted setting treated as 0-length setting")); + pDbSetting = pDbSetting+1; + break; + + default: + // Unknown datatype assert + AddMessage( LPGEN("ERROR: Faulty settings chain")); + return NULL; + } + + return pDbSetting; +} + + +// ** +// ** SETTINGS CHAIN +// ** + +// Return the settings at offset 'dwOffset' +BOOL GetSettingsGroup(HANDLE hDbFile, DWORD dwOffset, struct DBContactSettings** pDbSettings) +{ + DWORD dwBytesRead, dwBlobSize, dwHead; + struct DBContactSettings pSettings; + + // Early reject + if (dwOffset == 0 || dwOffset >= dwFileSize) + return FALSE; + + // ** Read and verify the struct + if (SetFilePointer(hDbFile, dwOffset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) + return FALSE; + + dwHead = offsetof(struct DBContactSettings, blob); + if ((!ReadFile(hDbFile, &pSettings, dwHead, &dwBytesRead, NULL)) || + (dwBytesRead != dwHead)) + return FALSE; + + if (pSettings.signature != DBCONTACTSETTINGS_SIGNATURE) + return FALSE; // Setttings corrupted + + // ** Read the struct and the following blob + dwBlobSize = pSettings.cbBlob; + if (!(*pDbSettings = calloc(1, sizeof(struct DBContactSettings) + dwBlobSize))) + return FALSE; + + memcpy(*pDbSettings, &pSettings, dwHead ); + + if ((!ReadFile(hDbFile, (*pDbSettings)->blob, sizeof(struct DBContactSettings) - dwHead + dwBlobSize, &dwBytesRead, NULL)) || + (dwBytesRead != sizeof(struct DBContactSettings) - dwHead + dwBlobSize)) + { + free(*pDbSettings); + return FALSE; + } + + return TRUE; +} + +// pDbContact is a ptr to a struct DBContact +// Returns pointer to a struct DBContactSettings or NULL +struct DBContactSettings* GetSettingsGroupByModuleName(HANDLE hDbFile, struct DBContact* pDbContact, char* pszName) +{ + char* pszGroupName; + struct DBContactSettings* pSettingsGroup; + DWORD dwGroupOfs; + + // Get ptr to first settings group + if (!(dwGroupOfs = pDbContact->ofsFirstSettings)) + return NULL; // No settings exists in this contact + + // Loop over all settings groups + while (dwGroupOfs && dwGroupOfs < dwFileSize) { + pSettingsGroup = NULL; + + // Read and verify the struct + if (!GetSettingsGroup(hDbFile, dwGroupOfs, &pSettingsGroup)) + return NULL; // Bad struct + + // Struct OK, now get the name + if ((pszGroupName = GetName(hDbFile, pSettingsGroup->ofsModuleName))) { + + // Is it the right one? + if (strcmp(pszGroupName, pszName) == 0) { + #ifdef _LOGGING + AddMessage( LPGEN("Found module: %s"), pszGroupName ); + #endif + return pSettingsGroup; + } + #ifdef _LOGGING + else AddMessage( LPGEN("Ignoring module: %s"), pszGroupName ); + #endif + } + else AddMessage( LPGEN("Warning: Found module with no name")); + + dwGroupOfs = pSettingsGroup->ofsNext; + + if (pSettingsGroup) + free(pSettingsGroup); + } + + // Search failed + return NULL; +} + +// pDbSettings must point to a complete DBContactSettings struct in memory +int GetSettingByName(struct DBContactSettings* pDbSettings, char* pszSettingName, DBVARIANT* dbv) +{ + char pszName[256]; + // We need at least one setting to start with + char* pDbSetting = pDbSettings->blob; + if ( !pDbSetting ) + return FALSE; + + // ** pDbSettings now points to the first setting in this module + + // Loop over all settings + while (pDbSetting && *pDbSetting) { + memcpy(pszName, pDbSetting+1, *pDbSetting); + pszName[*pDbSetting] = 0; + + // Is this the right one? + if (strcmp(pszSettingName, pszName) == 0) { + return GetSettingValue(pDbSetting, dbv); + } + + #ifdef _LOGGING + AddMessage( LPGEN("Ignoring setting: %s"), pszName ); + #endif + pDbSetting = GetNextSetting(pDbSetting); + } + + // Search failed + return FALSE; +} + +// dwSettingpointer points to a valid DBSettings struct +int GetSettingValue(char* pBlob, DBVARIANT* dbv) +{ + #ifdef _LOGGING + { + char* pszName = calloc((*pBlob)+1, 1); + memcpy(pszName, pBlob+1, *pBlob); + AddMessage( LPGEN("Getting type %u value for setting: %s"), (BYTE)*(pBlob+(*pBlob)+1), pszName ); + free(pszName); + } + #endif + + // Skip name + pBlob = pBlob + (*pBlob)+1; + dbv->type = ( BYTE )*pBlob++; + + // Check what type it is + switch( dbv->type ) { + case DBVT_BYTE: + dbv->bVal = *pBlob; + return TRUE; + + case DBVT_WORD: + // Unsane: encrypt WORDs + if (bEncrypted) + DecodeMemory(pBlob, sizeof(pBlob)); + dbv->wVal = *(WORD*)pBlob; + return TRUE; + + case DBVT_DWORD: + // Unsane: encrypt DWORDs + if (bEncrypted) + DecodeMemory(pBlob, sizeof(pBlob)); + dbv->dVal = *(DWORD*)pBlob; + return TRUE; + + case DBVT_ASCIIZ: + case DBVT_UTF8: + // Unsane: encrypt STRINGs + dbv->cchVal = *(WORD*)pBlob; + dbv->pszVal = calloc( dbv->cchVal+1, sizeof( char )); + if (bEncrypted) + DecodeCopyMemory(dbv->pszVal, pBlob+2, dbv->cchVal); + else + memcpy( dbv->pszVal, pBlob+2, dbv->cchVal ); + dbv->pszVal[ dbv->cchVal ] = 0; + + return TRUE; + + case DBVTF_VARIABLELENGTH: + case DBVT_BLOB: + dbv->cpbVal = *(WORD*)pBlob; + dbv->pbVal = calloc( dbv->cpbVal+1, sizeof( char )); + // Unsane: encrypt other + if (bEncrypted) + DecodeCopyMemory(dbv->pszVal, pBlob+2, dbv->cchVal); + else + memcpy( dbv->pbVal, pBlob+2, dbv->cpbVal ); + dbv->pbVal[ dbv->cpbVal ] = 0; + return TRUE; + + case DBVT_DELETED: + AddMessage( LPGEN("DEBUG: Deleted setting treated as 0-length setting")); + + default: + dbv->type = DBVT_DELETED; + } + + return FALSE; +} + +void FreeVariant( DBVARIANT* dbv ) +{ + switch( dbv->type ) { + case DBVT_ASCIIZ: + case DBVT_UTF8: + if ( dbv->pszVal ) + free( dbv->pszVal ); + break; + + case DBVTF_VARIABLELENGTH: + case DBVT_BLOB: + if ( dbv->pbVal ) + free( dbv->pbVal ); + break; + } + + dbv->type = 0; +} + +void WriteVariant( HANDLE hContact, const char* module, const char* var, DBVARIANT* dbv ) +{ + DBCONTACTWRITESETTING dbw; + dbw.szModule = module; + dbw.szSetting = var; + dbw.value = *dbv; + CallService( MS_DB_CONTACT_WRITESETTING, (WPARAM)hContact, (LPARAM)&dbw ); +} + +// Returns true if pDBEI has been filled in with nice values +// Don't forget to free those pointers! +BOOL GetEvent(HANDLE hDbFile, DWORD dwOffset, DBEVENTINFO* pDBEI) +{ + DWORD dwBytesRead; + struct DBEvent pEvent; + static char pBlob[65536]; + + // Early reject + if (dwOffset == 0 || dwOffset >= dwFileSize) + return FALSE; + + // ** Read and verify the struct + if (SetFilePointer(hDbFile, dwOffset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) + return FALSE; + + if (!ReadFile(hDbFile, &pEvent, offsetof(struct DBEvent, blob), &dwBytesRead, NULL) || + (dwBytesRead != offsetof(struct DBEvent, blob))) + return FALSE; + + if (pEvent.signature != DBEVENT_SIGNATURE) + return FALSE; // Event corrupted + + // ** Read the blob + if ((!ReadFile(hDbFile, pBlob, pEvent.cbBlob, &dwBytesRead, NULL)) || + (dwBytesRead != pEvent.cbBlob)) + { + return FALSE; + } + + // ** Copy the static part to the event info struct + pDBEI->timestamp = pEvent.timestamp; + pDBEI->eventType = pEvent.eventType; + pDBEI->cbSize = sizeof(DBEVENTINFO); + pDBEI->cbBlob = pEvent.cbBlob; + pDBEI->pBlob = pBlob; + pDBEI->flags = (pEvent.flags & ~(DBEF_SENT+DBEF_READ)) + + ((pEvent.flags & DBEF_SENT) ? DBEF_SENT : DBEF_READ ); // Imported events are always marked READ + + if (!(pDBEI->szModule = GetName(hDbFile, pEvent.ofsModuleName))) { + return FALSE; + } + + // Unsane: encrypt dbevent + if (bEncrypted) + DecodeMemory(pDBEI->pBlob, pDBEI->cbBlob); + + return TRUE; +} + +// Returns a pointer to a string with the name +// from a DBModuleName struct if given a file offset +// Returns NULL on failure +char* GetName(HANDLE hDbFile, DWORD dwOffset) +{ + static DWORD dwLastOffset = 0; + static HANDLE hLastDbFile = NULL; + static char szName[256] = {0}; + + DWORD dwBytesRead; + struct DBModuleName pModule; + + // Early reject + if (dwOffset == 0 || dwOffset >= dwFileSize) + return FALSE; + + // Quick lookup + if (dwOffset == dwLastOffset && hDbFile == hLastDbFile) + return szName; + + // ** Read and verify the name struct + if (SetFilePointer(hDbFile, dwOffset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) + return NULL; + + if ((!ReadFile(hDbFile, &pModule, offsetof(struct DBModuleName, name), &dwBytesRead, NULL)) || + (dwBytesRead != offsetof(struct DBModuleName, name))) + return NULL; + + if (pModule.signature != DBMODULENAME_SIGNATURE) { + AddMessage( LPGEN("Modulename corrupted")); + return NULL; // ModuleName corrupted + } + + // ** Name struct OK, now read name into string buffer + if ((!ReadFile(hDbFile, szName, pModule.cbName, &dwBytesRead, NULL)) || (dwBytesRead != pModule.cbName)) { + return NULL; + } + + // terminate string + szName[pModule.cbName] = 0; + + // update last offset + dwLastOffset = dwOffset; + hLastDbFile = hDbFile; + + return szName; +} + +DWORD FindNextEvent(HANDLE hDbFile, DWORD dwOffset) +{ + DWORD dwBytesRead; + struct DBEvent pEvent; + + // Early reject + if (dwOffset == 0 || dwOffset >= dwFileSize) + return FALSE; + + // ** Read and verify the struct + if (SetFilePointer(hDbFile, dwOffset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) + return FALSE; + + if ((!ReadFile(hDbFile, &pEvent, sizeof(struct DBEvent), &dwBytesRead, NULL)) || + (dwBytesRead != sizeof(struct DBEvent))) + return FALSE; + + if ( pEvent.signature != DBEVENT_SIGNATURE || pEvent.ofsNext > dwFileSize ) + return FALSE; // Event corrupted + + return pEvent.ofsNext; +} + +int ImportGroups(HANDLE hDbFile, struct DBHeader* pdbHeader) +{ + struct DBContactSettings* pDbSettings; + struct DBContact DbContact; + char* pSetting; + DWORD dwOffset; + int nGroups = 0; + + // Find owner data + dwOffset = pdbHeader->ofsUser; + if (!GetContact(hDbFile, dwOffset, &DbContact)) { + AddMessage( LPGEN("No owner found.")); + return -1; + } + + // Find the module with the groups, and import them all + if ( pDbSettings = GetSettingsGroupByModuleName( hDbFile, &DbContact, "CListGroups" )) { + /*if (bEncrypted) + DecodeMemory(pDbSettings->blob, pDbSettings->cbBlob);*/ + pSetting = pDbSettings->blob; + while ( pSetting && *pSetting ) { + DBVARIANT dbv; + if ( GetSettingValue( pSetting, &dbv )) { + if ( CreateGroup( dbv.type, dbv.pszVal+1, NULL )) + nGroups++; + FreeVariant( &dbv ); + } + pSetting = GetNextSetting(pSetting); + } + free(pDbSettings); + + /*if (bEncrypted) + EncodeMemory(pDbSettings->blob, pDbSettings->cbBlob);*/ + } + + return nGroups; +} + +HANDLE ImportContact(HANDLE hDbFile, struct DBContact Contact) +{ + HANDLE hContact; + DBVARIANT group, nick, dbv; + char* pszProtoName; + char* pszUniqueSetting; + char* pszUserName; + char id[ 40 ]; + + // Check what protocol this contact belongs to + if ( !GetSetting( hDbFile, &Contact, "Protocol", "p", &dbv )) { + AddMessage( LPGEN("Skipping contact with no protocol")); + return INVALID_HANDLE_VALUE; + } + + pszProtoName = NEWSTR_ALLOCA( dbv.pszVal ); + FreeVariant( &dbv ); + + if ( !IsProtocolLoaded( pszProtoName )) { + AddMessage( LPGEN("Skipping contact, %s not installed."), pszProtoName ); + return INVALID_HANDLE_VALUE; + } + + // Skip protocols with no unique id setting (some non IM protocols return NULL) + pszUniqueSetting = (char*)CallProtoService(pszProtoName, PS_GETCAPS, PFLAG_UNIQUEIDSETTING, 0); + if ( !pszUniqueSetting || (INT_PTR)pszUniqueSetting == CALLSERVICE_NOTFOUND ) { + AddMessage( LPGEN("Skipping non-IM contact (%s)"), pszProtoName ); + return INVALID_HANDLE_VALUE; + } + + if ( !GetSetting(hDbFile, &Contact, pszProtoName, pszUniqueSetting, &dbv )) { + AddMessage( LPGEN("Skipping %s contact, ID not found"), pszProtoName ); + return INVALID_HANDLE_VALUE; + } + + // Does the contact already exist? + if ( dbv.type == DBVT_DWORD ) { + pszUserName = _ltoa( dbv.dVal, id, 10 ); + hContact = HContactFromNumericID( pszProtoName, pszUniqueSetting, dbv.dVal ); + } + else { + pszUserName = NEWSTR_ALLOCA( dbv.pszVal ); + hContact = HContactFromID( pszProtoName, pszUniqueSetting, dbv.pszVal ); + } + + if ( hContact != INVALID_HANDLE_VALUE ) { + AddMessage( LPGEN("Skipping duplicate %s contact %s"), pszProtoName, pszUserName ); + FreeVariant( &dbv ); + return INVALID_HANDLE_VALUE; + } + // No, add contact and copy some important settings + GetSetting(hDbFile, &Contact, "CList", "Group", &group); + + if ( !GetSetting( hDbFile, &Contact, "CList", "MyHandle", &nick )) + GetSetting(hDbFile, &Contact, pszProtoName, "Nick", &nick ); + + hContact = AddContact( hdlgProgress, pszProtoName, pszUniqueSetting, &dbv, &nick, &group ); + + if ( hContact != INVALID_HANDLE_VALUE) { + + // Hidden? + if ( GetSetting( hDbFile, &Contact, "CList", "Hidden", &dbv )) { + WriteVariant( hContact, "CList", "Hidden", &dbv ); + FreeVariant( &dbv ); + } + // Ignore settings + if ( GetSetting( hDbFile, &Contact, "Ignore", "Mask1", &dbv )) { + WriteVariant( hContact, "Ignore", "Mask1", &dbv ); + FreeVariant( &dbv ); + } + + // Apparent mode + if ( GetSetting( hDbFile, &Contact, pszProtoName, "ApparentMode", &dbv )) { + WriteVariant( hContact, pszProtoName, "ApparentMode", &dbv ); + FreeVariant( &dbv ); + } + + // Nick + if ( GetSetting( hDbFile, &Contact, pszProtoName, "Nick", &dbv )) { + WriteVariant( hContact, pszProtoName, "Nick", &dbv ); + FreeVariant( &dbv ); + } + + // Myhandle + if ( GetSetting( hDbFile, &Contact, pszProtoName, "MyHandle", &dbv )) { + WriteVariant( hContact, pszProtoName, "MyHandle", &dbv ); + FreeVariant( &dbv ); + } + + // First name + if ( GetSetting( hDbFile, &Contact, pszProtoName, "FirstName", &dbv )) { + WriteVariant( hContact, pszProtoName, "FirstName", &dbv ); + FreeVariant( &dbv ); + } + + // Last name + if ( GetSetting( hDbFile, &Contact, pszProtoName, "LastName", &dbv )) { + WriteVariant( hContact, pszProtoName, "LastName", &dbv ); + FreeVariant( &dbv ); + } + + // About + if ( GetSetting( hDbFile, &Contact, pszProtoName, "About", &dbv )) { + WriteVariant( hContact, pszProtoName, "About", &dbv ); + FreeVariant( &dbv ); + } + } + else AddMessage( LPGEN("Unknown error while adding %s contact %s"), pszProtoName, pszUserName ); + + return hContact; +} + +// This function should always be called after contact import. That is +// why there are no messages for errors related to contacts. Those +// would only be a repetition of the messages printed during contact +// import. + +static void ImportHistory(HANDLE hDbFile, struct DBContact Contact, PROTOCOLDESCRIPTOR **protocol, int protoCount) +{ + HANDLE hContact = INVALID_HANDLE_VALUE; + DWORD dwOffset; + MSG msg; + DBVARIANT proto; + int i, skipAll, bIsVoidContact; + + // Is it contats history import? + if ( protoCount == 0 ) { + + // Check what protocol this contact belongs to + if ( GetSetting( hDbFile, &Contact, "Protocol", "p", &proto )) { + + // Protocol installed? + if ( IsProtocolLoaded( proto.pszVal )) { + // Is contact in database? + char* pszUniqueSetting = (char*)CallProtoService( proto.pszVal, PS_GETCAPS, PFLAG_UNIQUEIDSETTING, 0); + + // Skip protocols with no unique id setting (some non IM protocols return NULL) + if ( pszUniqueSetting && ( INT_PTR )pszUniqueSetting != CALLSERVICE_NOTFOUND ) { + DBVARIANT dbv; + if ( GetSetting( hDbFile, &Contact, proto.pszVal, pszUniqueSetting, &dbv )) { + if ( dbv.type == DBVT_DWORD ) + hContact = HContactFromNumericID( proto.pszVal, pszUniqueSetting, dbv.dVal ); + else + hContact = HContactFromID( proto.pszVal, pszUniqueSetting, dbv.pszVal ); + FreeVariant( &dbv ); + } } } + FreeVariant( &proto ); + } + } + else hContact = NULL; //system history import + + // OK to import this chain? + if (hContact == INVALID_HANDLE_VALUE) { + nSkippedContacts++; + return; + } + + i = skipAll = 0; + bIsVoidContact = CallService( MS_DB_EVENT_GETCOUNT, ( WPARAM )hContact, 0 ) == 0; + + // Get the start of the event chain + dwOffset = Contact.ofsFirstEvent; + while (dwOffset) { + int skip = 0; + + // Copy the event and import it + DBEVENTINFO dbei = { 0 }; + if (GetEvent(hDbFile, dwOffset, &dbei)) { + // check protocols during system history import + if (hContact == NULL) { + int i; + skipAll = 1; + + for(i = 0; i < protoCount; i++) + if (!strcmp(dbei.szModule, protocol[i]->szName)) { //&& protocol[i]->type == PROTOTYPE_PROTOCOL) + skipAll = 0; + break; + } + + skip = skipAll; + } + + // custom filtering + if (!skip && nImportOption == IMPORT_CUSTOM) { + BOOL sent = (dbei.flags&DBEF_SENT); + + if (dbei.timestamp < (DWORD)dwSinceDate) + skip = 1; + + if (!skip) { + if (hContact) { + skip = 1; + switch(dbei.eventType) { + case EVENTTYPE_MESSAGE: + if ((sent?IOPT_MSGSENT:IOPT_MSGRECV)&nCustomOptions) + skip = 0; + break; + case EVENTTYPE_FILE: + if ((sent?IOPT_FILESENT:IOPT_FILERECV)&nCustomOptions) + skip = 0; + break; + case EVENTTYPE_URL: + if ((sent?IOPT_URLSENT:IOPT_URLRECV)&nCustomOptions) + skip = 0; + break; + default: + if ((sent?IOPT_OTHERSENT:IOPT_OTHERRECV)&nCustomOptions) + skip = 0; + break; + } + } + else if ( !( nCustomOptions & IOPT_SYSTEM )) + skip = 1; + } + + if (skip) + nSkippedEvents++; + } + + if (!skip) { + // Check for duplicate entries + if ( !IsDuplicateEvent( hContact, dbei )) { + // Add dbevent + if (!bIsVoidContact) + dbei.flags &= ~DBEF_FIRST; + if (CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei)) + nMessagesCount++; + else + AddMessage( LPGEN("Failed to add message")); + } + else + nDupes++; + } + } + + if ( !( i%10 )) { + if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } } + + // skip this chain if needed + if ( skipAll ) + break; + + // Get next event + dwOffset = FindNextEvent(hDbFile, dwOffset); + i++; + } +} + +static void MirandaImport(HWND hdlg) +{ + int nDBVersion; + int i; + int nNumberOfContacts = 0; + MSG msg; + DWORD dwTimer; + DWORD dwOffset; + HANDLE hFile; + char* pszModuleName = NULL; + struct DBHeader* pdbHeader = NULL; + struct DBContact Contact; + + // Just to keep the macros happy + hdlgProgress = hdlg; + + // Reset statistics + nSkippedEvents = 0; + nDupes = 0; + nContactsCount = 0; + nMessagesCount = 0; + nGroupsCount = 0; + nSkippedContacts = 0; + SetProgress(0); + + // Open database + hFile = CreateFile(importFile, + GENERIC_READ, // open for reading + 0, // do not share + NULL, // no security + OPEN_EXISTING, // existing file only + FILE_ATTRIBUTE_NORMAL, // normal file + NULL); // no attr. template + + // Read error + if (hFile == INVALID_HANDLE_VALUE) { + AddMessage( LPGEN("Could not open file.")); + SetProgress(100); + return; + } + + // Check filesize + dwFileSize = GetFileSize(hFile, NULL) ; + if ((dwFileSize == INVALID_FILE_SIZE) || (dwFileSize < sizeof(struct DBHeader))) { + AddMessage( LPGEN("This is not a valid Miranda IM database.")); + SetProgress(100); + CloseHandle(hFile); + return; + } + + // Check header and database version + nDBVersion = CheckFileFormat(hFile); + if (nDBVersion == DB_INVALID) { + AddMessage( LPGEN("This is not a valid Miranda IM database.")); + SetProgress(100); + CloseHandle(hFile); + return; + } + + // Load database header + if (!(pdbHeader = GetHeader(hFile))) { + AddMessage( LPGEN("Read failure.")); + SetProgress(100); + CloseHandle(hFile); + return; + } + + // Get number of contacts + nNumberOfContacts = pdbHeader->contactCount; + AddMessage( LPGEN("Number of contacts in database: %d"), nNumberOfContacts ); + AddMessage( "" ); + + // Configure database for fast writing + CallService(MS_DB_SETSAFETYMODE, FALSE, 0); + + // Start benchmark timer + dwTimer = time(NULL); + + // Import Groups + if (nImportOption == IMPORT_ALL || (nCustomOptions & IOPT_GROUPS)) { + AddMessage( LPGEN("Importing groups.")); + nGroupsCount = ImportGroups(hFile, pdbHeader); + if (nGroupsCount == -1) + AddMessage( LPGEN("Group import failed.")); + + AddMessage( "" ); + } + // End of Import Groups + + // Import Contacts + if (nImportOption != IMPORT_CUSTOM || (nCustomOptions & IOPT_CONTACTS)) { + AddMessage( LPGEN("Importing contacts.")); + i = 1; + dwOffset = FindFirstContact(pdbHeader); + while (dwOffset && (dwOffset < dwFileSize)) { + if (!GetContact(hFile, dwOffset, &Contact)) { + AddMessage( LPGEN("ERROR: Chain broken, no valid contact at %d"), dwOffset ); + SetProgress(100); + break; + } + + if (ImportContact(hFile, Contact) != INVALID_HANDLE_VALUE) + nContactsCount++; + + // Update progress bar + SetProgress(100 * i / nNumberOfContacts); + i++; + + // Process queued messages + if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + // Get next contact in chain + dwOffset = FindNextContact(&Contact); + } + } + else AddMessage( LPGEN("Skipping new contacts import.")); + AddMessage( "" ); + // End of Import Contacts + + // Import history + if (nImportOption != IMPORT_CONTACTS) { + // Import NULL contact message chain + if (nImportOption == IMPORT_ALL || (nCustomOptions & IOPT_SYSTEM)) { + AddMessage( LPGEN("Importing system history.")); + dwOffset = FindOwnerContact(pdbHeader); + if (!GetContact(hFile, dwOffset, &Contact)) { + AddMessage( LPGEN("ERROR: Chain broken, no valid contact at %d"), dwOffset ); + SetProgress(100); + } + else { + PROTOCOLDESCRIPTOR **protocol; + int protoCount; + + CallService(MS_PROTO_ENUMPROTOCOLS, (WPARAM)&protoCount, (LPARAM)&protocol); + + if (protoCount > 0) + ImportHistory(hFile, Contact, protocol, protoCount); + } + } + else AddMessage( LPGEN("Skipping system history import.")); + + AddMessage( "" ); + + // Import other contact messages + if (nImportOption == IMPORT_ALL || (nCustomOptions & 2046)) { // 2 - 1024 types + AddMessage( LPGEN("Importing history.")); + dwOffset = FindFirstContact(pdbHeader); + for(i=1; i <= nNumberOfContacts; i++) { + if (!GetContact(hFile, dwOffset, &Contact)) { + AddMessage( LPGEN("ERROR: Chain broken, no valid contact at %d"), dwOffset ); + SetProgress(100); + break; + } + + ImportHistory(hFile, Contact, NULL, 0); + + SetProgress(100 * i / nNumberOfContacts); + dwOffset = FindNextContact(&Contact); + } + } + else AddMessage( LPGEN("Skipping history import.")); + + AddMessage( "" ); + } + // End of Import History + + // Restore database writing mode + CallService(MS_DB_SETSAFETYMODE, TRUE, 0); + + // Clean up before exit + CloseHandle(hFile); + free(pdbHeader); + + // Stop timer + dwTimer = time(NULL) - dwTimer; + + // Print statistics + AddMessage( LPGEN("Import completed in %d seconds."), dwTimer ); + SetProgress(100); + AddMessage((nImportOption == IMPORT_CONTACTS) ? + LPGEN("Added %d contacts and %d groups.") : LPGEN("Added %d contacts, %d groups and %d events."), + nContactsCount, nGroupsCount, nMessagesCount); + + if ( nImportOption != IMPORT_CONTACTS ) { + if (nSkippedContacts) + AddMessage( LPGEN("Skipped %d contacts."), nSkippedContacts ); + + AddMessage((nImportOption == IMPORT_CUSTOM) ? + LPGEN("Skipped %d duplicates and %d filtered events.") : LPGEN("Skipped %d duplicates."), + nDupes, nSkippedEvents); +} } diff --git a/plugins/Dbx_mmap_SA/Import_SA/mirandahistory.c b/plugins/Dbx_mmap_SA/Import_SA/mirandahistory.c deleted file mode 100644 index ba7a923df7..0000000000 --- a/plugins/Dbx_mmap_SA/Import_SA/mirandahistory.c +++ /dev/null @@ -1,208 +0,0 @@ -/* -Miranda ICQ: the free icq client for MS Windows -Copyright (C) 2000-2 Richard Hughes, Roland Rabien & Tristan Van de Vreede - -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 -#include -#include -#include "resource.h" -#include "import.h" - -BOOL CALLBACK MirandaPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam); -BOOL CALLBACK FinishedPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam); -BOOL CALLBACK ProgressPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam); -extern char importFile[MAX_PATH]; -extern void (*DoImport)(HWND); -static void OldMirandaHistoryImport(HWND hdlgProgress); -HANDLE HContactFromUIN(DWORD uin); -HANDLE HistoryImportFindContact(HWND hdlgProgress,DWORD uin,int addUnknown); -static DWORD importOptions; - -BOOL CALLBACK MirandaHistoryPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam) -{ - switch(message) { - case WM_INITDIALOG: - CheckDlgButton(hdlg,IDC_ADDUNKNOWN,BST_CHECKED); - CheckDlgButton(hdlg,IDC_MSGRECV,BST_CHECKED); - CheckDlgButton(hdlg,IDC_MSGSENT,BST_CHECKED); - CheckDlgButton(hdlg,IDC_URLRECV,BST_CHECKED); - CheckDlgButton(hdlg,IDC_URLSENT,BST_CHECKED); - CheckDlgButton(hdlg,IDC_AUTHREQ,BST_CHECKED); - CheckDlgButton(hdlg,IDC_ADDED,BST_CHECKED); - return TRUE; - case WM_COMMAND: - switch(LOWORD(wParam)) { - case IDC_BACK: - PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_MIRANDADB,(LPARAM)MirandaPageProc); - break; - case IDOK: - importOptions=0; - if(IsDlgButtonChecked(hdlg,IDC_ADDUNKNOWN)) importOptions|=IOPT_ADDUNKNOWN; - if(IsDlgButtonChecked(hdlg,IDC_MSGSENT)) importOptions|=IOPT_MSGSENT; - if(IsDlgButtonChecked(hdlg,IDC_MSGRECV)) importOptions|=IOPT_MSGRECV; - if(IsDlgButtonChecked(hdlg,IDC_URLSENT)) importOptions|=IOPT_URLSENT; - if(IsDlgButtonChecked(hdlg,IDC_URLRECV)) importOptions|=IOPT_URLRECV; - if(IsDlgButtonChecked(hdlg,IDC_AUTHREQ)) importOptions|=IOPT_AUTHREQ; - if(IsDlgButtonChecked(hdlg,IDC_ADDED)) importOptions|=IOPT_ADDED; - DoImport=OldMirandaHistoryImport; - PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_PROGRESS,(LPARAM)ProgressPageProc); - break; - case IDCANCEL: - PostMessage(GetParent(hdlg),WM_CLOSE,0,0); - break; - } - break; - } - return FALSE; -} - -#define HISTORY_MSGRECV 1 -#define HISTORY_MSGSEND 2 -#define HISTORY_URLRECV 3 -#define HISTORY_URLSEND 4 -#define HISTORY_AUTHREQ 5 -#define HISTORY_ADDED 6 -#define issent(t) ((t)==HISTORY_MSGSEND || (t)==HISTORY_URLSEND) -static int historyTypeToOption[]={0,IOPT_MSGRECV,IOPT_MSGSENT,IOPT_URLRECV,IOPT_URLSENT,IOPT_AUTHREQ,IOPT_ADDED}; - -static PBYTE ReadHistoryLines(FILE *fp,int *cbBlob) -{ - char str[2048]; - char *blob; - int ofs; - *cbBlob=0; - blob=NULL; - while(fgets(str,sizeof(str),fp) && lstrcmp(str,"\xEE\xEE\xEE\xEE\r\n")) { - ofs=*cbBlob; - *cbBlob+=lstrlen(str); - blob=(char*)realloc(blob,*cbBlob+1); - lstrcpy(blob+ofs,str); - } - if (*cbBlob) { - (*cbBlob)--; - blob[*cbBlob-1]=0; - } - else { - *cbBlob=1; - blob=(char*)malloc(1); - blob[0]=0; - } - return (PBYTE)blob; -} - -static void OldMirandaHistoryImport(HWND hdlgProgress) -{ - int fileSize; - FILE *fp; - char str[2048],*eol,*timeofs; - HANDLE hContact; - int type; - DWORD uin; - struct tm tmEventTime; - DBEVENTINFO dbei; - - AddMessage("Old Miranda history import routines initialised"); - fp=fopen(importFile,"rb"); - AddMessage("Calibrating status support functions"); - fseek(fp,0,SEEK_END); - fileSize=ftell(fp); - fseek(fp,0,SEEK_SET); - SetProgress(0); - - ZeroMemory(&dbei,sizeof(dbei)); - dbei.cbSize=sizeof(dbei); - dbei.szModule=ICQOSCPROTONAME; - - while(!feof(fp)) { - SetProgress(100*ftell(fp)/fileSize); - if(fgets(str,sizeof(str),fp)==NULL) break; - eol=str+lstrlen(str)-1; - - while(*eol=='\r' || *eol=='\n' && eol!=str-1) - *(eol--)=0; - - if(lstrlen(str)<20) continue; - type=*eol; - uin=strtoul(str,NULL,10); - if(uin==0) continue; //skip MSN - timeofs=str+lstrlen(str)-20; - tmEventTime.tm_hour=atoi(timeofs); - timeofs=strchr(timeofs,':'); - if(timeofs==NULL) continue; - tmEventTime.tm_min=atoi(timeofs+1); - tmEventTime.tm_sec=0; - tmEventTime.tm_isdst=-1; - tmEventTime.tm_mday=atoi(timeofs+7); - tmEventTime.tm_mon=atoi(timeofs+10)-1; - tmEventTime.tm_year=atoi(timeofs+13)-1900; - dbei.timestamp=mktime(&tmEventTime)+_timezone; - if (!(importOptions&historyTypeToOption[type])) continue; - hContact=HistoryImportFindContact(hdlgProgress,uin,importOptions&IOPT_ADDUNKNOWN); - if(hContact==INVALID_HANDLE_VALUE) break; - dbei.flags=issent(type)?DBEF_SENT:DBEF_READ; - switch(type) { - case HISTORY_MSGRECV: - case HISTORY_MSGSEND: - dbei.eventType=EVENTTYPE_MESSAGE; - dbei.pBlob=ReadHistoryLines(fp,&dbei.cbBlob); - CallService(MS_DB_EVENT_ADD,(WPARAM)hContact,(LPARAM)&dbei); - break; - case HISTORY_URLRECV: - case HISTORY_URLSEND: - dbei.eventType=EVENTTYPE_URL; - dbei.pBlob=ReadHistoryLines(fp,&dbei.cbBlob); - { char *endOfUrl; - endOfUrl=strchr(dbei.pBlob,'\r'); - if(endOfUrl!=NULL) { - *endOfUrl=0; - dbei.cbBlob--; - MoveMemory(endOfUrl+1,endOfUrl+2,dbei.cbBlob-(endOfUrl-dbei.pBlob)); - } - } - CallService(MS_DB_EVENT_ADD,(WPARAM)hContact,(LPARAM)&dbei); - break; - case HISTORY_AUTHREQ: - dbei.eventType=EVENTTYPE_AUTHREQUEST; - dbei.pBlob=ReadHistoryLines(fp,&dbei.cbBlob); - dbei.pBlob=(PBYTE)realloc(dbei.pBlob,dbei.cbBlob+8); - MoveMemory(dbei.pBlob+8,dbei.pBlob,dbei.cbBlob); - *(PDWORD)dbei.pBlob=uin; - *(char*)(dbei.pBlob+4)=0; //leave nick, first, last, email blank - *(char*)(dbei.pBlob+5)=0; - *(char*)(dbei.pBlob+6)=0; - *(char*)(dbei.pBlob+7)=0; - dbei.cbBlob+=8; - CallService(MS_DB_EVENT_ADD,(WPARAM)(HANDLE)NULL,(LPARAM)&dbei); - break; - case HISTORY_ADDED: - dbei.eventType=EVENTTYPE_ADDED; - dbei.pBlob=(PBYTE)malloc(8); - dbei.cbBlob=8; - *(PDWORD)dbei.pBlob=uin; - *(char*)(dbei.pBlob+4)=0; //leave nick, first, last, email blank - *(char*)(dbei.pBlob+5)=0; - *(char*)(dbei.pBlob+6)=0; - *(char*)(dbei.pBlob+7)=0; - CallService(MS_DB_EVENT_ADD,(WPARAM)(HANDLE)NULL,(LPARAM)&dbei); - break; - } - } - AddMessage("Terminating cached I/O access"); - fclose(fp); - AddMessage("Import completed successfully"); - SetProgress(100); -} \ No newline at end of file diff --git a/plugins/Dbx_mmap_SA/Import_SA/mirandahistory.cpp b/plugins/Dbx_mmap_SA/Import_SA/mirandahistory.cpp new file mode 100644 index 0000000000..ba7a923df7 --- /dev/null +++ b/plugins/Dbx_mmap_SA/Import_SA/mirandahistory.cpp @@ -0,0 +1,208 @@ +/* +Miranda ICQ: the free icq client for MS Windows +Copyright (C) 2000-2 Richard Hughes, Roland Rabien & Tristan Van de Vreede + +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 +#include +#include +#include "resource.h" +#include "import.h" + +BOOL CALLBACK MirandaPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam); +BOOL CALLBACK FinishedPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam); +BOOL CALLBACK ProgressPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam); +extern char importFile[MAX_PATH]; +extern void (*DoImport)(HWND); +static void OldMirandaHistoryImport(HWND hdlgProgress); +HANDLE HContactFromUIN(DWORD uin); +HANDLE HistoryImportFindContact(HWND hdlgProgress,DWORD uin,int addUnknown); +static DWORD importOptions; + +BOOL CALLBACK MirandaHistoryPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam) +{ + switch(message) { + case WM_INITDIALOG: + CheckDlgButton(hdlg,IDC_ADDUNKNOWN,BST_CHECKED); + CheckDlgButton(hdlg,IDC_MSGRECV,BST_CHECKED); + CheckDlgButton(hdlg,IDC_MSGSENT,BST_CHECKED); + CheckDlgButton(hdlg,IDC_URLRECV,BST_CHECKED); + CheckDlgButton(hdlg,IDC_URLSENT,BST_CHECKED); + CheckDlgButton(hdlg,IDC_AUTHREQ,BST_CHECKED); + CheckDlgButton(hdlg,IDC_ADDED,BST_CHECKED); + return TRUE; + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDC_BACK: + PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_MIRANDADB,(LPARAM)MirandaPageProc); + break; + case IDOK: + importOptions=0; + if(IsDlgButtonChecked(hdlg,IDC_ADDUNKNOWN)) importOptions|=IOPT_ADDUNKNOWN; + if(IsDlgButtonChecked(hdlg,IDC_MSGSENT)) importOptions|=IOPT_MSGSENT; + if(IsDlgButtonChecked(hdlg,IDC_MSGRECV)) importOptions|=IOPT_MSGRECV; + if(IsDlgButtonChecked(hdlg,IDC_URLSENT)) importOptions|=IOPT_URLSENT; + if(IsDlgButtonChecked(hdlg,IDC_URLRECV)) importOptions|=IOPT_URLRECV; + if(IsDlgButtonChecked(hdlg,IDC_AUTHREQ)) importOptions|=IOPT_AUTHREQ; + if(IsDlgButtonChecked(hdlg,IDC_ADDED)) importOptions|=IOPT_ADDED; + DoImport=OldMirandaHistoryImport; + PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_PROGRESS,(LPARAM)ProgressPageProc); + break; + case IDCANCEL: + PostMessage(GetParent(hdlg),WM_CLOSE,0,0); + break; + } + break; + } + return FALSE; +} + +#define HISTORY_MSGRECV 1 +#define HISTORY_MSGSEND 2 +#define HISTORY_URLRECV 3 +#define HISTORY_URLSEND 4 +#define HISTORY_AUTHREQ 5 +#define HISTORY_ADDED 6 +#define issent(t) ((t)==HISTORY_MSGSEND || (t)==HISTORY_URLSEND) +static int historyTypeToOption[]={0,IOPT_MSGRECV,IOPT_MSGSENT,IOPT_URLRECV,IOPT_URLSENT,IOPT_AUTHREQ,IOPT_ADDED}; + +static PBYTE ReadHistoryLines(FILE *fp,int *cbBlob) +{ + char str[2048]; + char *blob; + int ofs; + *cbBlob=0; + blob=NULL; + while(fgets(str,sizeof(str),fp) && lstrcmp(str,"\xEE\xEE\xEE\xEE\r\n")) { + ofs=*cbBlob; + *cbBlob+=lstrlen(str); + blob=(char*)realloc(blob,*cbBlob+1); + lstrcpy(blob+ofs,str); + } + if (*cbBlob) { + (*cbBlob)--; + blob[*cbBlob-1]=0; + } + else { + *cbBlob=1; + blob=(char*)malloc(1); + blob[0]=0; + } + return (PBYTE)blob; +} + +static void OldMirandaHistoryImport(HWND hdlgProgress) +{ + int fileSize; + FILE *fp; + char str[2048],*eol,*timeofs; + HANDLE hContact; + int type; + DWORD uin; + struct tm tmEventTime; + DBEVENTINFO dbei; + + AddMessage("Old Miranda history import routines initialised"); + fp=fopen(importFile,"rb"); + AddMessage("Calibrating status support functions"); + fseek(fp,0,SEEK_END); + fileSize=ftell(fp); + fseek(fp,0,SEEK_SET); + SetProgress(0); + + ZeroMemory(&dbei,sizeof(dbei)); + dbei.cbSize=sizeof(dbei); + dbei.szModule=ICQOSCPROTONAME; + + while(!feof(fp)) { + SetProgress(100*ftell(fp)/fileSize); + if(fgets(str,sizeof(str),fp)==NULL) break; + eol=str+lstrlen(str)-1; + + while(*eol=='\r' || *eol=='\n' && eol!=str-1) + *(eol--)=0; + + if(lstrlen(str)<20) continue; + type=*eol; + uin=strtoul(str,NULL,10); + if(uin==0) continue; //skip MSN + timeofs=str+lstrlen(str)-20; + tmEventTime.tm_hour=atoi(timeofs); + timeofs=strchr(timeofs,':'); + if(timeofs==NULL) continue; + tmEventTime.tm_min=atoi(timeofs+1); + tmEventTime.tm_sec=0; + tmEventTime.tm_isdst=-1; + tmEventTime.tm_mday=atoi(timeofs+7); + tmEventTime.tm_mon=atoi(timeofs+10)-1; + tmEventTime.tm_year=atoi(timeofs+13)-1900; + dbei.timestamp=mktime(&tmEventTime)+_timezone; + if (!(importOptions&historyTypeToOption[type])) continue; + hContact=HistoryImportFindContact(hdlgProgress,uin,importOptions&IOPT_ADDUNKNOWN); + if(hContact==INVALID_HANDLE_VALUE) break; + dbei.flags=issent(type)?DBEF_SENT:DBEF_READ; + switch(type) { + case HISTORY_MSGRECV: + case HISTORY_MSGSEND: + dbei.eventType=EVENTTYPE_MESSAGE; + dbei.pBlob=ReadHistoryLines(fp,&dbei.cbBlob); + CallService(MS_DB_EVENT_ADD,(WPARAM)hContact,(LPARAM)&dbei); + break; + case HISTORY_URLRECV: + case HISTORY_URLSEND: + dbei.eventType=EVENTTYPE_URL; + dbei.pBlob=ReadHistoryLines(fp,&dbei.cbBlob); + { char *endOfUrl; + endOfUrl=strchr(dbei.pBlob,'\r'); + if(endOfUrl!=NULL) { + *endOfUrl=0; + dbei.cbBlob--; + MoveMemory(endOfUrl+1,endOfUrl+2,dbei.cbBlob-(endOfUrl-dbei.pBlob)); + } + } + CallService(MS_DB_EVENT_ADD,(WPARAM)hContact,(LPARAM)&dbei); + break; + case HISTORY_AUTHREQ: + dbei.eventType=EVENTTYPE_AUTHREQUEST; + dbei.pBlob=ReadHistoryLines(fp,&dbei.cbBlob); + dbei.pBlob=(PBYTE)realloc(dbei.pBlob,dbei.cbBlob+8); + MoveMemory(dbei.pBlob+8,dbei.pBlob,dbei.cbBlob); + *(PDWORD)dbei.pBlob=uin; + *(char*)(dbei.pBlob+4)=0; //leave nick, first, last, email blank + *(char*)(dbei.pBlob+5)=0; + *(char*)(dbei.pBlob+6)=0; + *(char*)(dbei.pBlob+7)=0; + dbei.cbBlob+=8; + CallService(MS_DB_EVENT_ADD,(WPARAM)(HANDLE)NULL,(LPARAM)&dbei); + break; + case HISTORY_ADDED: + dbei.eventType=EVENTTYPE_ADDED; + dbei.pBlob=(PBYTE)malloc(8); + dbei.cbBlob=8; + *(PDWORD)dbei.pBlob=uin; + *(char*)(dbei.pBlob+4)=0; //leave nick, first, last, email blank + *(char*)(dbei.pBlob+5)=0; + *(char*)(dbei.pBlob+6)=0; + *(char*)(dbei.pBlob+7)=0; + CallService(MS_DB_EVENT_ADD,(WPARAM)(HANDLE)NULL,(LPARAM)&dbei); + break; + } + } + AddMessage("Terminating cached I/O access"); + fclose(fp); + AddMessage("Import completed successfully"); + SetProgress(100); +} \ No newline at end of file diff --git a/plugins/Dbx_mmap_SA/Import_SA/progress.c b/plugins/Dbx_mmap_SA/Import_SA/progress.c deleted file mode 100644 index f3f4e9f08a..0000000000 --- a/plugins/Dbx_mmap_SA/Import_SA/progress.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - -Import plugin for Miranda IM - -Copyright (C) 2001-2005 Martin Öberg, Richard Hughes, Roland Rabien & Tristan Van de Vreede - -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 -#include -#include - -#include "import.h" - -#define PROGM_START (WM_USER+100) - -INT_PTR CALLBACK FinishedPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam); - -void (*DoImport)(HWND); - -INT_PTR CALLBACK ProgressPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam) -{ - switch(message) { - case WM_INITDIALOG: - TranslateDialogDefault(hdlg); - SendMessage(GetParent(hdlg),WIZM_DISABLEBUTTON,0,0); - SendMessage(GetParent(hdlg),WIZM_DISABLEBUTTON,1,0); - SendMessage(GetParent(hdlg),WIZM_DISABLEBUTTON,2,0); - SendDlgItemMessage(hdlg,IDC_PROGRESS,PBM_SETRANGE,0,MAKELPARAM(0,100)); - PostMessage(hdlg,PROGM_START,0,0); - return TRUE; - - case PROGM_SETPROGRESS: - SendDlgItemMessage(hdlg,IDC_PROGRESS,PBM_SETPOS,wParam,0); - break; - - case PROGM_ADDMESSAGE: - { - int i=SendDlgItemMessage(hdlg,IDC_STATUS,LB_ADDSTRING,0,lParam); - SendDlgItemMessage(hdlg,IDC_STATUS,LB_SETTOPINDEX,i,0); - } - break; - - case PROGM_START: - DoImport(hdlg); - SendMessage(GetParent(hdlg),WIZM_ENABLEBUTTON,1,0); - SendMessage(GetParent(hdlg),WIZM_ENABLEBUTTON,2,0); - break; - - case WM_COMMAND: - switch(LOWORD(wParam)) { - case IDOK: - PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_FINISHED,(LPARAM)FinishedPageProc); - break; - case IDCANCEL: - PostMessage(GetParent(hdlg),WM_CLOSE,0,0); - break; - } - break; - } - return FALSE; -} - -void AddMessage( const char* fmt, ... ) -{ - va_list args; - char msgBuf[ 4096 ]; - va_start( args, fmt ); - - mir_vsnprintf( msgBuf, sizeof(msgBuf), Translate(fmt), args ); - - #ifdef _LOGGING - { - FILE *stream; - stream = fopen("Import Debug.log", "a"); - fprintf(stream, "%s\n", msgBuf); - fclose(stream); - } - #endif - - - { TCHAR* str = mir_a2t( msgBuf ); - SendMessage( hdlgProgress, PROGM_ADDMESSAGE, 0, ( LPARAM )str ); - mir_free( str ); - } -} diff --git a/plugins/Dbx_mmap_SA/Import_SA/progress.cpp b/plugins/Dbx_mmap_SA/Import_SA/progress.cpp new file mode 100644 index 0000000000..f3f4e9f08a --- /dev/null +++ b/plugins/Dbx_mmap_SA/Import_SA/progress.cpp @@ -0,0 +1,100 @@ +/* + +Import plugin for Miranda IM + +Copyright (C) 2001-2005 Martin Öberg, Richard Hughes, Roland Rabien & Tristan Van de Vreede + +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 +#include +#include + +#include "import.h" + +#define PROGM_START (WM_USER+100) + +INT_PTR CALLBACK FinishedPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam); + +void (*DoImport)(HWND); + +INT_PTR CALLBACK ProgressPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam) +{ + switch(message) { + case WM_INITDIALOG: + TranslateDialogDefault(hdlg); + SendMessage(GetParent(hdlg),WIZM_DISABLEBUTTON,0,0); + SendMessage(GetParent(hdlg),WIZM_DISABLEBUTTON,1,0); + SendMessage(GetParent(hdlg),WIZM_DISABLEBUTTON,2,0); + SendDlgItemMessage(hdlg,IDC_PROGRESS,PBM_SETRANGE,0,MAKELPARAM(0,100)); + PostMessage(hdlg,PROGM_START,0,0); + return TRUE; + + case PROGM_SETPROGRESS: + SendDlgItemMessage(hdlg,IDC_PROGRESS,PBM_SETPOS,wParam,0); + break; + + case PROGM_ADDMESSAGE: + { + int i=SendDlgItemMessage(hdlg,IDC_STATUS,LB_ADDSTRING,0,lParam); + SendDlgItemMessage(hdlg,IDC_STATUS,LB_SETTOPINDEX,i,0); + } + break; + + case PROGM_START: + DoImport(hdlg); + SendMessage(GetParent(hdlg),WIZM_ENABLEBUTTON,1,0); + SendMessage(GetParent(hdlg),WIZM_ENABLEBUTTON,2,0); + break; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDOK: + PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_FINISHED,(LPARAM)FinishedPageProc); + break; + case IDCANCEL: + PostMessage(GetParent(hdlg),WM_CLOSE,0,0); + break; + } + break; + } + return FALSE; +} + +void AddMessage( const char* fmt, ... ) +{ + va_list args; + char msgBuf[ 4096 ]; + va_start( args, fmt ); + + mir_vsnprintf( msgBuf, sizeof(msgBuf), Translate(fmt), args ); + + #ifdef _LOGGING + { + FILE *stream; + stream = fopen("Import Debug.log", "a"); + fprintf(stream, "%s\n", msgBuf); + fclose(stream); + } + #endif + + + { TCHAR* str = mir_a2t( msgBuf ); + SendMessage( hdlgProgress, PROGM_ADDMESSAGE, 0, ( LPARAM )str ); + mir_free( str ); + } +} diff --git a/plugins/Dbx_mmap_SA/Import_SA/wizard.c b/plugins/Dbx_mmap_SA/Import_SA/wizard.c deleted file mode 100644 index 0584cba073..0000000000 --- a/plugins/Dbx_mmap_SA/Import_SA/wizard.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - -Import plugin for Miranda IM - -Copyright (C) 2001-2005 Martin Öberg, Richard Hughes, Roland Rabien & Tristan Van de Vreede - -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 "import.h" - -INT_PTR CALLBACK WizardIntroPageProc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK FinishedPageProc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK MirabilisPageProc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK MirandaPageProc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK ICQserverPageProc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam); - -extern HINSTANCE hInst; -BOOL IsProtocolLoaded(char* pszProtocolName); -BOOL EnumICQAccounts(); -void FreeICQAccountsList(); - -INT_PTR CALLBACK ImportTypePageProc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch( message ) { - case WM_INITDIALOG: - TranslateDialogDefault(hdlg); - CheckDlgButton(hdlg, IDC_MIRANDA, BST_CHECKED); - - // Disable Mirabilis import if ICQ isn't loaded. - if (!EnumICQAccounts()) - EnableWindow(GetDlgItem(hdlg, IDC_MIRABILIS), FALSE); - - return TRUE; - - case WM_COMMAND: - switch( LOWORD( wParam )) { - case IDC_BACK: - PostMessage(GetParent(hdlg), WIZM_GOTOPAGE, IDD_WIZARDINTRO, (LPARAM)WizardIntroPageProc); - break; - - case IDOK: - if (IsDlgButtonChecked(hdlg, IDC_MIRANDA)) - PostMessage(GetParent(hdlg), WIZM_GOTOPAGE, IDD_MIRANDADB, (LPARAM)MirandaPageProc); - else if (IsDlgButtonChecked(hdlg, IDC_MIRABILIS)) - PostMessage(GetParent(hdlg), WIZM_GOTOPAGE, IDD_MIRABILISDB, (LPARAM)MirabilisPageProc); - else if (IsDlgButtonChecked(hdlg, IDC_USEFINDADD)) { - CallService(MS_FINDADD_FINDADD, 0, 0); - PostMessage(GetParent(hdlg), WIZM_GOTOPAGE, IDD_FINISHED, (LPARAM)FinishedPageProc); - } - break; - - case IDCANCEL: - PostMessage(GetParent(hdlg), WM_CLOSE, 0, 0); - break; - } } - - return FALSE; -} - -INT_PTR CALLBACK WizardIntroPageProc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch( message ) { - case WM_INITDIALOG: - TranslateDialogDefault(hdlg); - SendMessage(GetParent(hdlg), WIZM_DISABLEBUTTON, 0, 0); - return TRUE; - - case WM_COMMAND: - switch( LOWORD( wParam )) { - case IDOK: - PostMessage(GetParent(hdlg), WIZM_GOTOPAGE, IDD_IMPORTTYPE, (LPARAM)ImportTypePageProc); - break; - - case IDCANCEL: - PostMessage(GetParent(hdlg), WM_CLOSE, 0, 0); - break; - } } - - return FALSE; -} - -INT_PTR CALLBACK FinishedPageProc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch( message ) { - case WM_INITDIALOG: - TranslateDialogDefault(hdlg); - SendMessage(GetParent(hdlg), WIZM_DISABLEBUTTON, 0, 0); - SendMessage(GetParent(hdlg), WIZM_SETCANCELTEXT, 0, (LPARAM)TranslateT("Finish")); - CheckDlgButton(hdlg, IDC_DONTLOADPLUGIN, BST_UNCHECKED); - return TRUE; - - case WM_COMMAND: - switch( LOWORD( wParam )) { - case IDOK: - PostMessage(GetParent(hdlg), WIZM_GOTOPAGE, IDD_IMPORTTYPE, (LPARAM)ImportTypePageProc); - break; - - case IDCANCEL: - if ( IsDlgButtonChecked( hdlg, IDC_DONTLOADPLUGIN )) { - char sModuleFileName[MAX_PATH]; - char *pszFileName; - - GetModuleFileNameA(hInst, sModuleFileName, sizeof(sModuleFileName)); - pszFileName = strrchr(sModuleFileName, '\\' ); - if (pszFileName == NULL) - pszFileName = sModuleFileName; - else - pszFileName++; - - // We must lower case here because if a DLL is loaded in two - // processes, its file name from GetModuleFileName in one process may - // differ in case from its file name in the other process. This will - // prevent the plugin from disabling/enabling correctly (this fix relies - // on the plugin loader to ignore case) - CharLowerA(pszFileName); - DBWriteContactSettingByte(NULL, "PluginDisable", pszFileName, 1); - } - PostMessage(GetParent(hdlg), WM_CLOSE, 0, 0); - break; - } - break; - } - - return FALSE; -} - -INT_PTR CALLBACK WizardDlgProc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - static HWND hwndPage; - - switch ( message ) { - case WM_INITDIALOG: - TranslateDialogDefault(hdlg); - hwndPage = CreateDialog(hInst, MAKEINTRESOURCE(IDD_WIZARDINTRO), hdlg, WizardIntroPageProc); - SetWindowPos(hwndPage, 0, 0, 0, 0, 0, SWP_NOZORDER|SWP_NOSIZE); - ShowWindow(hwndPage, SW_SHOW); - ShowWindow(hdlg, SW_SHOW); - SendMessage(hdlg, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon(hInst,MAKEINTRESOURCE(IDI_IMPORT))); - return TRUE; - - case WIZM_GOTOPAGE: - DestroyWindow(hwndPage); - EnableWindow(GetDlgItem(hdlg, IDC_BACK), TRUE); - EnableWindow(GetDlgItem(hdlg, IDOK), TRUE); - EnableWindow(GetDlgItem(hdlg, IDCANCEL), TRUE); - SetDlgItemText(hdlg, IDCANCEL, TranslateT("Cancel")); - hwndPage = CreateDialog(hInst, MAKEINTRESOURCE(wParam), hdlg, (DLGPROC)lParam); - SetWindowPos(hwndPage, 0, 0, 0, 0, 0, SWP_NOZORDER|SWP_NOSIZE); - ShowWindow(hwndPage, SW_SHOW); - break; - - case WIZM_DISABLEBUTTON: - switch ( wParam ) { - case 0: - EnableWindow(GetDlgItem(hdlg, IDC_BACK), FALSE); - break; - - case 1: - EnableWindow(GetDlgItem(hdlg, IDOK), FALSE); - break; - - case 2: - EnableWindow(GetDlgItem(hdlg, IDCANCEL), FALSE); - break; - } - break; - - case WIZM_ENABLEBUTTON: - switch ( wParam ) { - case 0: - EnableWindow(GetDlgItem(hdlg, IDC_BACK), TRUE); - break; - - case 1: - EnableWindow(GetDlgItem(hdlg, IDOK), TRUE); - break; - - case 2: - EnableWindow(GetDlgItem(hdlg, IDCANCEL), TRUE); - break; - } - break; - - case WIZM_SETCANCELTEXT: - SetDlgItemText(hdlg, IDCANCEL, (TCHAR*)lParam); - break; - - case WM_COMMAND: - SendMessage(hwndPage, WM_COMMAND, wParam, lParam); - break; - - case WM_CLOSE: - DestroyWindow(hwndPage); - DestroyWindow(hdlg); - - FreeICQAccountsList(); - break; - } - - return FALSE; -} diff --git a/plugins/Dbx_mmap_SA/Import_SA/wizard.cpp b/plugins/Dbx_mmap_SA/Import_SA/wizard.cpp new file mode 100644 index 0000000000..0584cba073 --- /dev/null +++ b/plugins/Dbx_mmap_SA/Import_SA/wizard.cpp @@ -0,0 +1,215 @@ +/* + +Import plugin for Miranda IM + +Copyright (C) 2001-2005 Martin Öberg, Richard Hughes, Roland Rabien & Tristan Van de Vreede + +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 "import.h" + +INT_PTR CALLBACK WizardIntroPageProc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK FinishedPageProc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK MirabilisPageProc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK MirandaPageProc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK ICQserverPageProc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam); + +extern HINSTANCE hInst; +BOOL IsProtocolLoaded(char* pszProtocolName); +BOOL EnumICQAccounts(); +void FreeICQAccountsList(); + +INT_PTR CALLBACK ImportTypePageProc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch( message ) { + case WM_INITDIALOG: + TranslateDialogDefault(hdlg); + CheckDlgButton(hdlg, IDC_MIRANDA, BST_CHECKED); + + // Disable Mirabilis import if ICQ isn't loaded. + if (!EnumICQAccounts()) + EnableWindow(GetDlgItem(hdlg, IDC_MIRABILIS), FALSE); + + return TRUE; + + case WM_COMMAND: + switch( LOWORD( wParam )) { + case IDC_BACK: + PostMessage(GetParent(hdlg), WIZM_GOTOPAGE, IDD_WIZARDINTRO, (LPARAM)WizardIntroPageProc); + break; + + case IDOK: + if (IsDlgButtonChecked(hdlg, IDC_MIRANDA)) + PostMessage(GetParent(hdlg), WIZM_GOTOPAGE, IDD_MIRANDADB, (LPARAM)MirandaPageProc); + else if (IsDlgButtonChecked(hdlg, IDC_MIRABILIS)) + PostMessage(GetParent(hdlg), WIZM_GOTOPAGE, IDD_MIRABILISDB, (LPARAM)MirabilisPageProc); + else if (IsDlgButtonChecked(hdlg, IDC_USEFINDADD)) { + CallService(MS_FINDADD_FINDADD, 0, 0); + PostMessage(GetParent(hdlg), WIZM_GOTOPAGE, IDD_FINISHED, (LPARAM)FinishedPageProc); + } + break; + + case IDCANCEL: + PostMessage(GetParent(hdlg), WM_CLOSE, 0, 0); + break; + } } + + return FALSE; +} + +INT_PTR CALLBACK WizardIntroPageProc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch( message ) { + case WM_INITDIALOG: + TranslateDialogDefault(hdlg); + SendMessage(GetParent(hdlg), WIZM_DISABLEBUTTON, 0, 0); + return TRUE; + + case WM_COMMAND: + switch( LOWORD( wParam )) { + case IDOK: + PostMessage(GetParent(hdlg), WIZM_GOTOPAGE, IDD_IMPORTTYPE, (LPARAM)ImportTypePageProc); + break; + + case IDCANCEL: + PostMessage(GetParent(hdlg), WM_CLOSE, 0, 0); + break; + } } + + return FALSE; +} + +INT_PTR CALLBACK FinishedPageProc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch( message ) { + case WM_INITDIALOG: + TranslateDialogDefault(hdlg); + SendMessage(GetParent(hdlg), WIZM_DISABLEBUTTON, 0, 0); + SendMessage(GetParent(hdlg), WIZM_SETCANCELTEXT, 0, (LPARAM)TranslateT("Finish")); + CheckDlgButton(hdlg, IDC_DONTLOADPLUGIN, BST_UNCHECKED); + return TRUE; + + case WM_COMMAND: + switch( LOWORD( wParam )) { + case IDOK: + PostMessage(GetParent(hdlg), WIZM_GOTOPAGE, IDD_IMPORTTYPE, (LPARAM)ImportTypePageProc); + break; + + case IDCANCEL: + if ( IsDlgButtonChecked( hdlg, IDC_DONTLOADPLUGIN )) { + char sModuleFileName[MAX_PATH]; + char *pszFileName; + + GetModuleFileNameA(hInst, sModuleFileName, sizeof(sModuleFileName)); + pszFileName = strrchr(sModuleFileName, '\\' ); + if (pszFileName == NULL) + pszFileName = sModuleFileName; + else + pszFileName++; + + // We must lower case here because if a DLL is loaded in two + // processes, its file name from GetModuleFileName in one process may + // differ in case from its file name in the other process. This will + // prevent the plugin from disabling/enabling correctly (this fix relies + // on the plugin loader to ignore case) + CharLowerA(pszFileName); + DBWriteContactSettingByte(NULL, "PluginDisable", pszFileName, 1); + } + PostMessage(GetParent(hdlg), WM_CLOSE, 0, 0); + break; + } + break; + } + + return FALSE; +} + +INT_PTR CALLBACK WizardDlgProc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + static HWND hwndPage; + + switch ( message ) { + case WM_INITDIALOG: + TranslateDialogDefault(hdlg); + hwndPage = CreateDialog(hInst, MAKEINTRESOURCE(IDD_WIZARDINTRO), hdlg, WizardIntroPageProc); + SetWindowPos(hwndPage, 0, 0, 0, 0, 0, SWP_NOZORDER|SWP_NOSIZE); + ShowWindow(hwndPage, SW_SHOW); + ShowWindow(hdlg, SW_SHOW); + SendMessage(hdlg, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon(hInst,MAKEINTRESOURCE(IDI_IMPORT))); + return TRUE; + + case WIZM_GOTOPAGE: + DestroyWindow(hwndPage); + EnableWindow(GetDlgItem(hdlg, IDC_BACK), TRUE); + EnableWindow(GetDlgItem(hdlg, IDOK), TRUE); + EnableWindow(GetDlgItem(hdlg, IDCANCEL), TRUE); + SetDlgItemText(hdlg, IDCANCEL, TranslateT("Cancel")); + hwndPage = CreateDialog(hInst, MAKEINTRESOURCE(wParam), hdlg, (DLGPROC)lParam); + SetWindowPos(hwndPage, 0, 0, 0, 0, 0, SWP_NOZORDER|SWP_NOSIZE); + ShowWindow(hwndPage, SW_SHOW); + break; + + case WIZM_DISABLEBUTTON: + switch ( wParam ) { + case 0: + EnableWindow(GetDlgItem(hdlg, IDC_BACK), FALSE); + break; + + case 1: + EnableWindow(GetDlgItem(hdlg, IDOK), FALSE); + break; + + case 2: + EnableWindow(GetDlgItem(hdlg, IDCANCEL), FALSE); + break; + } + break; + + case WIZM_ENABLEBUTTON: + switch ( wParam ) { + case 0: + EnableWindow(GetDlgItem(hdlg, IDC_BACK), TRUE); + break; + + case 1: + EnableWindow(GetDlgItem(hdlg, IDOK), TRUE); + break; + + case 2: + EnableWindow(GetDlgItem(hdlg, IDCANCEL), TRUE); + break; + } + break; + + case WIZM_SETCANCELTEXT: + SetDlgItemText(hdlg, IDCANCEL, (TCHAR*)lParam); + break; + + case WM_COMMAND: + SendMessage(hwndPage, WM_COMMAND, wParam, lParam); + break; + + case WM_CLOSE: + DestroyWindow(hwndPage); + DestroyWindow(hdlg); + + FreeICQAccountsList(); + break; + } + + return FALSE; +} -- cgit v1.2.3