From 9628bd0e796e0713377373863b962e3594204045 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Tue, 24 Jul 2012 17:57:46 +0000 Subject: new import plugin for Miranda NG git-svn-id: http://svn.miranda-ng.org/main/trunk@1166 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Import/src/ICQserver.cpp | 74 -- plugins/Import/src/ICQserver.h | 62 -- plugins/Import/src/import.cpp | 497 ++++++++++++ plugins/Import/src/import.h | 33 +- plugins/Import/src/main.cpp | 6 +- plugins/Import/src/mirabilis.cpp | 1493 ------------------------------------ plugins/Import/src/mirabilis.h | 200 ----- plugins/Import/src/miranda.cpp | 1134 +-------------------------- plugins/Import/src/mirandadb0700.h | 142 ---- plugins/Import/src/progress.cpp | 4 +- plugins/Import/src/resource.h | 7 +- plugins/Import/src/utils.cpp | 115 +-- plugins/Import/src/wizard.cpp | 59 +- 13 files changed, 576 insertions(+), 3250 deletions(-) delete mode 100644 plugins/Import/src/ICQserver.cpp delete mode 100644 plugins/Import/src/ICQserver.h create mode 100644 plugins/Import/src/import.cpp delete mode 100644 plugins/Import/src/mirabilis.cpp delete mode 100644 plugins/Import/src/mirabilis.h delete mode 100644 plugins/Import/src/mirandadb0700.h (limited to 'plugins/Import/src') diff --git a/plugins/Import/src/ICQserver.cpp b/plugins/Import/src/ICQserver.cpp deleted file mode 100644 index 372c0cb92c..0000000000 --- a/plugins/Import/src/ICQserver.cpp +++ /dev/null @@ -1,74 +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" -#include "resource.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/Import/src/ICQserver.h b/plugins/Import/src/ICQserver.h deleted file mode 100644 index 864890a978..0000000000 --- a/plugins/Import/src/ICQserver.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - -Import plugin for Miranda IM - -Copyright (C) 2001,2002,2003,2004 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. - -*/ - - - -#ifndef ICQSERVER_H -#define ICQSERVER_H - -#include - -// ====================== -// == GLOBAL FUNCTIONS == -// ====================== - -// ===================== -// == LOCAL FUNCTIONS == -// ===================== - -// Main function -static void ICQserverImport(); - -// GUI callbacks -INT_PTR CALLBACK FinishedPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam); - - -// ====================== -// == GLOBAL VARIABLES == -// ====================== - -extern int cICQAccounts; -extern char ** szICQModuleName; -extern TCHAR ** tszICQAccountName; -extern int iICQAccount; - -// ===================== -// == LOCAL VARIABLES == -// ===================== - -// ============= -// == DEFINES == -// ============= - -#endif \ No newline at end of file diff --git a/plugins/Import/src/import.cpp b/plugins/Import/src/import.cpp new file mode 100644 index 0000000000..fe2c4916bf --- /dev/null +++ b/plugins/Import/src/import.cpp @@ -0,0 +1,497 @@ +/* + +Import plugin for Miranda NG + +Copyright (C) 2012 George Hazan + +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 + +time_t dwSinceDate = 0; + +HWND hdlgProgress; + +static DWORD nDupes, nContactsCount, nMessagesCount, nGroupsCount, nSkippedEvents, nSkippedContacts; +static MIDatabase *srcDb, *dstDb; + +static int myGet(HANDLE hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv) +{ + dbv->type = 0; + DBCONTACTGETSETTING dgs = { szModule, szSetting, dbv }; + return srcDb->GetContactSetting(hContact, &dgs); +} + +static TCHAR* myGetWs(HANDLE hContact, const char *szModule, const char *szSetting) +{ + DBVARIANT dbv = { DBVT_TCHAR }; + DBCONTACTGETSETTING dgs = { szModule, szSetting, &dbv }; + return ( srcDb->GetContactSettingStr(hContact, &dgs)) ? NULL : dbv.ptszVal; +} + +static char* myGetS(HANDLE hContact, const char *szModule, const char *szSetting) +{ + DBVARIANT dbv = { DBVT_ASCIIZ }; + DBCONTACTGETSETTING dgs = { szModule, szSetting, &dbv }; + return ( srcDb->GetContactSettingStr(hContact, &dgs)) ? NULL : dbv.pszVal; +} + +void mySet(HANDLE hContact, const char *module, const char *var, DBVARIANT *dbv) +{ + DBCONTACTWRITESETTING dbw; + dbw.szModule = module; + dbw.szSetting = var; + dbw.value = *dbv; + dstDb->WriteContactSetting(hContact, &dbw); +} + +static int ImportGroup(const char* szSettingName, LPARAM lParam) +{ + int* pnGroups = (int*)lParam; + + TCHAR* tszGroup = myGetWs(NULL, "CListGroups", szSettingName); + if (tszGroup != NULL) { + if ( CreateGroup( tszGroup, NULL )) + pnGroups[0]++; + mir_free(tszGroup); + } + return 0; +} + +static int ImportGroups() +{ + int nGroups = 0; + + DBCONTACTENUMSETTINGS param = { 0 }; + param.szModule = "CListGroups"; + param.pfnEnumProc = ImportGroup; + param.lParam = (LPARAM)&nGroups; + srcDb->EnumContactSettings(NULL, ¶m); + return nGroups; +} + +HANDLE AddContact(HWND hdlgProgress, char* pszProtoName, char* pszUniqueSetting, DBVARIANT* id, TCHAR *nick, TCHAR *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 ); + srcDb->FreeVariant( id ); + return INVALID_HANDLE_VALUE; + } + + mySet( hContact, pszProtoName, pszUniqueSetting, id ); + + CreateGroup(group, hContact); + + if (nick && *nick) { + db_set_ws(hContact, "CList", "MyHandle", nick ); + AddMessage( LPGEN("Added %s contact %s, '%S'"), pszProtoName, pszUserID, nick); + } + else AddMessage( LPGEN("Added %s contact %s"), pszProtoName, pszUserID); + + srcDb->FreeVariant( id ); + return hContact; +} + +static HANDLE ImportContact(HANDLE hSrc) +{ + HANDLE hDst; + char* pszUserName; + char id[ 40 ]; + + // Check what protocol this contact belongs to + mir_ptr pszProtoName( myGetS(hSrc, "Protocol", "p")); + if ( !pszProtoName) { + AddMessage( LPGEN("Skipping contact with no protocol")); + return NULL; + } + + if ( !IsProtocolLoaded(pszProtoName)) { + AddMessage( LPGEN("Skipping contact, %s not installed."), pszProtoName); + return NULL; + } + + // Skip protocols with no unique id setting (some non IM protocols return NULL) + char* 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 NULL; + } + + DBVARIANT dbv; + if ( myGet(hSrc, pszProtoName, pszUniqueSetting, &dbv)) { + AddMessage( LPGEN("Skipping %s contact, ID not found"), pszProtoName); + return NULL; + } + + // Does the contact already exist? + if ( dbv.type == DBVT_DWORD ) { + pszUserName = _ltoa(dbv.dVal, id, 10); + hDst = HContactFromNumericID( pszProtoName, pszUniqueSetting, dbv.dVal ); + } + else { + pszUserName = NEWSTR_ALLOCA(dbv.pszVal); + hDst = HContactFromID( pszProtoName, pszUniqueSetting, dbv.pszVal ); + } + + if (hDst != INVALID_HANDLE_VALUE) { + AddMessage( LPGEN("Skipping duplicate %s contact %s"), pszProtoName, pszUserName ); + srcDb->FreeVariant( &dbv ); + return NULL; + } + + TCHAR *tszGroup = myGetWs(hSrc, "CList", "Group"), *tszNick = myGetWs(hSrc, "CList", "MyHandle"); + if (tszNick == NULL) + tszNick = myGetWs(hSrc, pszProtoName, "Nick"); + + hDst = AddContact(hdlgProgress, pszProtoName, pszUniqueSetting, &dbv, tszNick, tszGroup); + mir_free(tszGroup), mir_free(tszNick); + + if ( hDst != INVALID_HANDLE_VALUE) { + // Hidden? + if ( myGet(hSrc, "CList", "Hidden", &dbv )) { + mySet(hDst, "CList", "Hidden", &dbv); + srcDb->FreeVariant(&dbv); + } + + // Ignore settings + if ( myGet(hSrc, "Ignore", "Mask1", &dbv )) { + mySet( hDst, "Ignore", "Mask1", &dbv ); + srcDb->FreeVariant(&dbv); + } + + // Apparent mode + if ( myGet(hSrc, pszProtoName, "ApparentMode", &dbv )) { + mySet( hDst, pszProtoName, "ApparentMode", &dbv ); + srcDb->FreeVariant(&dbv); + } + + // Nick + if ( myGet(hSrc, pszProtoName, "Nick", &dbv )) { + mySet( hDst, pszProtoName, "Nick", &dbv ); + srcDb->FreeVariant(&dbv); + } + + // Myhandle + if ( myGet(hSrc, pszProtoName, "MyHandle", &dbv )) { + mySet( hDst, pszProtoName, "MyHandle", &dbv ); + srcDb->FreeVariant(&dbv); + } + + // First name + if ( myGet(hSrc, pszProtoName, "FirstName", &dbv )) { + mySet( hDst, pszProtoName, "FirstName", &dbv ); + srcDb->FreeVariant(&dbv); + } + + // Last name + if ( myGet(hSrc, pszProtoName, "LastName", &dbv )) { + mySet( hDst, pszProtoName, "LastName", &dbv ); + srcDb->FreeVariant(&dbv); + } + + // About + if ( myGet(hSrc, pszProtoName, "About", &dbv )) { + mySet( hDst, pszProtoName, "About", &dbv ); + srcDb->FreeVariant(&dbv); + } + } + else AddMessage( LPGEN("Unknown error while adding %s contact %s"), pszProtoName, pszUserName ); + + return hDst; +} + +// 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 hContact, PROTOACCOUNT **protocol, int protoCount) +{ + HANDLE hDst = INVALID_HANDLE_VALUE; + + // Is it contats history import? + if (protoCount == 0) { + // Check what protocol this contact belongs to + char* szProto = myGetS(hContact, "Protocol", "p"); + if (szProto != NULL) { + // Protocol installed? + if ( IsProtocolLoaded(szProto)) { + // Is contact in database? + char* pszUniqueSetting = (char*)CallProtoService(szProto, 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 ( myGet(hContact, szProto, pszUniqueSetting, &dbv)) { + if ( dbv.type == DBVT_DWORD ) + hDst = HContactFromNumericID(szProto, pszUniqueSetting, dbv.dVal); + else + hDst = HContactFromID(szProto, pszUniqueSetting, dbv.pszVal); + srcDb->FreeVariant( &dbv ); + } } } + + mir_free(szProto); + } + } + else hDst = NULL; //system history import + + // OK to import this chain? + if (hDst == INVALID_HANDLE_VALUE) { + nSkippedContacts++; + return; + } + + int i = 0, skipAll = 0; + bool bIsVoidContact = dstDb->GetEventCount(hDst) == 0; + + // Get the start of the event chain + HANDLE hEvent = srcDb->FindFirstEvent(hContact); + while (hEvent) { + int skip = 0; + + // Copy the event and import it + DBEVENTINFO dbei = { 0 }; + if ( !srcDb->GetEvent(hEvent, &dbei)) { + // check protocols during system history import + if (hDst == NULL) { + skipAll = 1; + for (int i = 0; i < protoCount; i++) + if ( !strcmp(dbei.szModule, protocol[i]->szModuleName)) { + 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 (hDst) { + 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( hDst, dbei )) { + // Add dbevent + if (!bIsVoidContact) + dbei.flags &= ~DBEF_FIRST; + if (dstDb->AddEvent(hDst, &dbei) != NULL) + nMessagesCount++; + else + AddMessage( LPGEN("Failed to add message")); + } + else + nDupes++; + } + } + + if ( !( i%10 )) { + MSG msg; + if ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } } + + // skip this chain if needed + if ( skipAll ) + break; + + // Get next event + hEvent = srcDb->FindNextEvent(hEvent); + i++; + } +} + +void MirandaImport(HWND hdlg) +{ + DWORD dwTimer; + char* pszModuleName = NULL; + + // Just to keep the macros happy + hdlgProgress = hdlg; + if ((dstDb = GetCurrentDatabase()) == NULL) { + AddMessage( LPGEN("Error retrieving current profile, exiting.")); + return; + } + + DATABASELINK* dblink = FindDatabasePlugin(importFile); + if (dblink == NULL) { + AddMessage( LPGEN("There's no database driver to open the input file, exiting.")); + return; + } + + if ((srcDb = dblink->Load(importFile)) == NULL) { + AddMessage( LPGEN("Error loading source file, exiting.")); + return; + } + + // Reset statistics + nSkippedEvents = 0; + nDupes = 0; + nContactsCount = 0; + nMessagesCount = 0; + nGroupsCount = 0; + nSkippedContacts = 0; + SetProgress(0); + + // Get number of contacts + int nNumberOfContacts = srcDb->GetContactCount(); + AddMessage( LPGEN("Number of contacts in database: %d"), nNumberOfContacts ); + AddMessage( "" ); + + // Configure database for fast writing + dstDb->SetCacheSafetyMode(FALSE); + + // Start benchmark timer + dwTimer = time(NULL); + + // Import Groups + if (nImportOption == IMPORT_ALL || (nCustomOptions & IOPT_GROUPS)) { + AddMessage( LPGEN("Importing groups.")); + nGroupsCount = ImportGroups(); + 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.")); + int i = 1; + HANDLE hContact = srcDb->FindFirstContact(); + while (hContact != NULL) { + if ( ImportContact(hContact)) + nContactsCount++; + + // Update progress bar + SetProgress(100 * i / nNumberOfContacts); + i++; + + // Process queued messages + MSG msg; + if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + // Get next contact in chain + hContact = srcDb->FindNextContact(hContact); + } + } + 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.")); + + int protoCount; + PROTOACCOUNT **accs; + CallService(MS_PROTO_ENUMACCOUNTS, (WPARAM)&protoCount, (LPARAM)&accs); + + if (protoCount > 0) + ImportHistory(NULL, accs, 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.")); + HANDLE hContact = srcDb->FindFirstContact(); + for(int i=1; hContact != NULL; i++) { + ImportHistory(hContact, NULL, NULL); + + SetProgress(100 * i / nNumberOfContacts); + hContact = srcDb->FindNextContact(hContact); + } + } + else AddMessage( LPGEN("Skipping history import.")); + + AddMessage( "" ); + } + // End of Import History + + // Restore database writing mode + dstDb->SetCacheSafetyMode(TRUE); + + // Clean up before exit + dblink->Unload(srcDb); + + // 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/Import/src/import.h b/plugins/Import/src/import.h index f0d9b022bd..43effb7a0f 100644 --- a/plugins/Import/src/import.h +++ b/plugins/Import/src/import.h @@ -1,8 +1,8 @@ /* -Import plugin for Miranda IM +Import plugin for Miranda NG -Copyright (C) 2001,2002,2003,2004 Martin Öberg, Richard Hughes, Roland Rabien & Tristan Van de Vreede +Copyright (C) 2012 George Hazan This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -45,6 +45,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include #include +#include #include #include #include @@ -101,11 +102,29 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. void AddMessage( const char* fmt, ... ); -void FreeVariant( DBVARIANT* dbv ); -void WriteVariant( HANDLE hContact, const char* module, const char* var, DBVARIANT* dbv ); +void mySet( HANDLE hContact, const char* module, const char* var, DBVARIANT* dbv ); -int CreateGroup(BYTE type, const char* name, HANDLE hContact); +INT_PTR CALLBACK WizardIntroPageProc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK ProgressPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam); +INT_PTR CALLBACK MirandaPageProc(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); +INT_PTR CALLBACK FinishedPageProc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam); -extern HWND hdlgProgress; +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, TCHAR *nick, TCHAR *group); + +BOOL IsProtocolLoaded(char* pszProtocolName); +BOOL IsDuplicateEvent(HANDLE hContact, DBEVENTINFO dbei); -extern DWORD nDupes, nContactsCount, nMessagesCount, nGroupsCount, nSkippedEvents, nSkippedContacts; +int CreateGroup(const TCHAR* name, HANDLE hContact); + +extern HINSTANCE hInst; +extern HWND hdlgProgress; +extern void (*DoImport)(HWND); +extern int nImportOption; +extern int nCustomOptions; +extern TCHAR importFile[]; +extern time_t dwSinceDate; diff --git a/plugins/Import/src/main.cpp b/plugins/Import/src/main.cpp index 89d3320d32..13f4f8f315 100644 --- a/plugins/Import/src/main.cpp +++ b/plugins/Import/src/main.cpp @@ -1,8 +1,8 @@ /* -Import plugin for Miranda IM +Import plugin for Miranda NG -Copyright (C) 2001-2005 Martin Öberg, Richard Hughes, Roland Rabien & Tristan Van de Vreede +Copyright (C) 2012 George Hazan This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -32,7 +32,7 @@ int nCustomOptions; static HANDLE hImportService = NULL; HINSTANCE hInst; -DLGPROC WizardDlgProc; +INT_PTR CALLBACK WizardDlgProc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam); static HWND hwndWizard = NULL; int hLangpack; diff --git a/plugins/Import/src/mirabilis.cpp b/plugins/Import/src/mirabilis.cpp deleted file mode 100644 index 1f032827af..0000000000 --- a/plugins/Import/src/mirabilis.cpp +++ /dev/null @@ -1,1493 +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" -#include "resource.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((char*)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 = (char*)(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/Import/src/mirabilis.h b/plugins/Import/src/mirabilis.h deleted file mode 100644 index 47f10141e1..0000000000 --- a/plugins/Import/src/mirabilis.h +++ /dev/null @@ -1,200 +0,0 @@ -/* - -Import plugin for Miranda IM - -Copyright (C) 2001,2002,2003,2004 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. - -*/ - - - -#ifndef MIRABILIS_H -#define MIRABILIS_H - -#include -#include -#include - -// ====================== -// == GLOBAL FUNCTIONS == -// ====================== - -HANDLE HistoryImportFindContact(HWND hdlgProgress, char* szModuleName, DWORD uin,int addUnknown); - -// ===================== -// == LOCAL FUNCTIONS == -// ===================== - - -// Main function -static void MirabilisImport(HWND hdlgProgressWnd); - -// GUI callbacks -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 MirabilisPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam); -INT_PTR CALLBACK MirabilisOptionsPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam); - -// Helper functions for entries -static int GetHighestIndexEntry(void); -static int GetIdDatOfs(DWORD id); -static int GetDatEntryType(DWORD ofs); -DWORD FindMyDetails(void); - -// Parsing functions -DWORD GetDBVersion(); -int GetEntryVersion(WORD wSeparatorValue); -DWORD ReadPropertyBlock(DWORD dwOffset, char* SearchWord, int* nSearchResult); -DWORD ReadSubList(DWORD dwOffset); -DWORD ReadPropertyBlock(DWORD dwOffset, char* SearchWord, int* nSearchResult); -DWORD ReadPropertyBlockList(DWORD dwOffset, char* SearchWord, int* nSearchResult); -DWORD ReadWavList(DWORD ofs); -DWORD FindGroupList(DWORD dwOffset); -char* GetGroupName(DWORD dwGroupID); -int ImportGroups(); -static HANDLE ImportContact(DWORD dwOffset); - -BOOL ImportEvent(DWORD dwOffset); -BOOL ImportMessage(DWORD dwOffset); -BOOL ImportExtendedMessage(DWORD dwOffset); -BOOL ImportURLMessage(DWORD dwOffset); - - - - -// ====================== -// == GLOBAL VARIABLES == -// ====================== - -extern TCHAR importFile[MAX_PATH]; -extern void (*DoImport)(HWND); -extern int nImportOption; -extern int nCustomOptions; - - -extern int cICQAccounts; -extern char ** szICQModuleName; -extern TCHAR ** tszICQAccountName; -extern int iICQAccount; - -// ===================== -// == LOCAL VARIABLES == -// ===================== - -static DWORD dwDBVersion; -static DWORD dwGroupListOfs; -static PBYTE pIdx,pDat; - -// ============= -// == DEFINES == -// ============= - -// Contact versions -// These numbers are not 100% accurate -#define ENTRYVUNKNOWN -1 -#define ENTRYV99A 200 -#define ENTRYV99B 300 -#define ENTRYV2000A 400 -#define ENTRYV2000B 455 -#define ENTRYV2001A 500 -#define ENTRYV2001B 515 -#define ENTRYV2002A 533 - -// Database versions -#define DBV99A 10 -#define DBV99B 14 -#define DBV2000A 17 -#define DBV2000B 18 -#define DBV2001A 19 // This is used by ICQ 2001a, 2001b & 2002a - -#define DATENTRY_UNFILED (DWORD)(-1) -#define DATENTRY_MESSAGE 0 -#define DATENTRY_CONTACT 1 -#define DATENTRY_IGNORED 2 -#define DATENTRY_SYSTEM 9 - -#define MAX_NON_ICQ_CONTACTS 100 - -#define SUBTYPE_NEWMESSAGE 0x50 -#define SUBTYPE_NEWURL 0xA0 - -#define SUBTYPE_MESSAGE 0xE0 //Message / URL Message / Request For Authorization / "Authorization" / System Request / "You Were Added" / Contacts List -#define SUBTYPE_CHATREQUEST 0xE1 -#define SUBTYPE_FILEREQUEST 0xE2 -#define SUBTYPE_MYDETAILS 0xE4 -#define SUBTYPE_CONTACTINFO 0xE5 -#define SUBTYPE_REMINDER 0xE6 -#define SUBTYPE_ADDRESSBOOK 0xE7 -#define SUBTYPE_VOICEMSG 0xEC //??? -#define SUBTYPE_NOTE 0xEE -#define SUBTYPE_EVENTFOLDER 0xEF -#define SUBTYPE_SERVERLIST 0xF1 //and objectionable word list -#define SUBTYPE_X1 0xF6 //(new to ICQ 99b???) - -#define FILING_RECEIVED 0x01 -#define FILING_DELETED 0x02 -#define FILING_MESSAGE 0x04 -#define MSGTYPE_MESSAGE 1 -#define MSGTYPE_URL 4 -#define MSGTYPE_CLIST 19 -#include - -struct TIdxDatEntry { - DWORD status; //-2=valid, else is an index entry - DWORD entryId; - DWORD ofsNext,ofsPrev; - DWORD datOfs; -}; - -struct TIdxIndexEntry { - DWORD entryIdLow; - DWORD entryIdHigh; - DWORD ofsLower; - DWORD ofsInHere; - DWORD ofsHigher; -}; - -struct TDatEntryHeader { - DWORD entrySize; //in bytes - DWORD entryType; //DATENTRY_* constant - DWORD entryId; //same as in index - BYTE subType; //SUBTYPE_* constant - BYTE signature[15]; -}; - -struct TDatEntryFooter { - DWORD unknown; - DWORD sent; //1 if sent, 0 if received - WORD separator; - DWORD timestamp; //unix time -}; - -struct TDatMessage { - struct TDatEntryHeader hdr; //hdr.entryType==DATENTRY_MESSAGE && hdr.subType==MSGTYPE_MESSAGE - WORD separator; - DWORD filingStatus; //FILING_* flags - WORD type; //MSGTYPE_* constant - DWORD uin; - WORD textLen; - char text[1]; //0xFE separates description & URL in URLs - //a struct TDatEntryFooter comes here -}; - -#include - -#endif diff --git a/plugins/Import/src/miranda.cpp b/plugins/Import/src/miranda.cpp index 068f53acf0..0c20b61d7a 100644 --- a/plugins/Import/src/miranda.cpp +++ b/plugins/Import/src/miranda.cpp @@ -1,8 +1,8 @@ /* -Import plugin for Miranda IM +Import plugin for Miranda NG -Copyright (C) 2001-2005 Martin Öberg, Richard Hughes, Roland Rabien & Tristan Van de Vreede +Copyright (C) 2012 George Hazan This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -20,92 +20,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -// ============== -// == INCLUDES == -// ============== - #include "import.h" - #include "resource.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); - -// 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 == @@ -115,56 +39,44 @@ time_t dwSinceDate = 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}; - // ==================== // ==================== // == IMPLEMENTATION == // ==================== // ==================== -static void SearchForLists(HWND hdlg, const TCHAR *mirandaPath, const TCHAR *mirandaProf, const TCHAR *pattern, const TCHAR *type) +static void SearchForLists(HWND hdlg, const TCHAR *mirandaPath, const TCHAR *mirandaProf) { - HANDLE hFind; + // find in Miranda profile subfolders + TCHAR searchspec[MAX_PATH]; + mir_sntprintf(searchspec, SIZEOF(searchspec), _T("%s\\*.*"), mirandaPath); + 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 )); + HANDLE hFind = FindFirstFile(searchspec, &fd); + if (hFind == INVALID_HANDLE_VALUE) + return; - FindClose( hFind ); + do { + // find all subfolders except "." and ".." + if ( !(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) || !_tcscmp(fd.cFileName, _T(".")) || !_tcscmp(fd.cFileName, _T(".."))) + continue; + + // skip the current profile too + if (mirandaProf != NULL && !_tcsicmp(mirandaProf, fd.cFileName)) + continue; + + TCHAR buf[MAX_PATH], profile[MAX_PATH]; + mir_sntprintf(buf, SIZEOF(buf), _T("%s\\%s\\%s.dat"), mirandaPath, fd.cFileName, fd.cFileName); + if ( _taccess(buf, 0) == 0) { + mir_sntprintf(profile, SIZEOF(profile), _T("%s.dat"), fd.cFileName); + + int i = SendDlgItemMessage(hdlg, IDC_LIST, LB_ADDSTRING, 0, (LPARAM)profile); + SendDlgItemMessage(hdlg, IDC_LIST, LB_SETITEMDATA, i, (LPARAM)mir_tstrdup(buf)); + } } + while (FindNextFile(hFind, &fd)); + + FindClose(hFind); } INT_PTR CALLBACK MirandaPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam) @@ -184,10 +96,10 @@ INT_PTR CALLBACK MirandaPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lPa 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)")); - SearchForLists(hdlg, pfd1, NULL, _T("*.dat"), _T(" (Miranda IM v0.x)")); + SearchForLists(hdlg, pfd2, pfn); + SearchForLists(hdlg, pfd1, NULL); if (lstrcmpi(pfd, pfd2)) - SearchForLists(hdlg, pfd, NULL, _T("*.dat"), _T(" (Miranda IM v0.x)")); + SearchForLists(hdlg, pfd, NULL); mir_free(pfn); mir_free(pfd2); @@ -199,7 +111,7 @@ INT_PTR CALLBACK MirandaPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lPa case WM_COMMAND: switch(LOWORD(wParam)) { case IDC_BACK: - PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_IMPORTTYPE,(LPARAM)ImportTypePageProc); + PostMessage(GetParent(hdlg),WIZM_GOTOPAGE,IDD_WIZARDINTRO,(LPARAM)WizardIntroPageProc); break; case IDOK: @@ -267,7 +179,6 @@ INT_PTR CALLBACK MirandaPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lPa return FALSE; } - INT_PTR CALLBACK MirandaOptionsPageProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam) { switch(message) { @@ -459,980 +370,3 @@ INT_PTR CALLBACK MirandaAdvOptionsPageProc(HWND hdlg,UINT message,WPARAM wParam, 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 = (DBHeader*)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; -} - -int CheckFileFormat(HANDLE hDbFile) -{ - struct DBHeader* pdbHeader; - - // Read header - if (( pdbHeader = GetHeader(hDbFile)) == NULL ) - return DB_INVALID; - - // Check header signature - if (memcmp(pdbHeader->signature, &dbSignature, sizeof(pdbHeader->signature))) { - AddMessage( LPGEN("Signature mismatch" )); - return DB_INVALID; - } - - // Determine Miranda version - switch (pdbHeader->version) { - case DB_000700: - AddMessage( LPGEN("This looks like a Miranda database, version 0.1.0.0 or above." )); - free(pdbHeader); - return DB_000700; - - default: - AddMessage( LPGEN("Version mismatch" )); - free(pdbHeader); - return DB_INVALID; -} } - -// 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 = (DBContactSettings *)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 = (char*)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: - dbv->wVal = *(WORD*)pBlob; - return TRUE; - - case DBVT_DWORD: - dbv->dVal = *(DWORD*)pBlob; - return TRUE; - - case DBVT_ASCIIZ: - case DBVT_UTF8: - dbv->cchVal = *(WORD*)pBlob; - dbv->pszVal = (char *)calloc( dbv->cchVal+1, sizeof( char )); - 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 = (BYTE *)calloc( dbv->cpbVal+1, sizeof( char )); - 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 = (PBYTE)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; - } - - 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" )) { - pSetting = (char *)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); - } - - 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/Import/src/mirandadb0700.h b/plugins/Import/src/mirandadb0700.h deleted file mode 100644 index 2c77588951..0000000000 --- a/plugins/Import/src/mirandadb0700.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - -Import plugin for Miranda IM - -Copyright (C) 2001,2002,2003,2004 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. - -*/ - - - -//all offsets are relative to the start of the file -//offsets are 0 if there is nothing in the chain or this is the last in the -//chain - - - - -/* tree diagram - -DBHeader - |-->end of file (plain offset) - |-->first contact (DBContact) - | |-->next contact (DBContact) - | | \--> ... - | |-->first settings (DBContactSettings) - | | |-->next settings (DBContactSettings) - | | | \--> ... - | | \-->module name (DBModuleName) - | \-->first/last/firstunread event - |-->user contact (DBContact) - | |-->next contact=NULL - | |-->first settings as above - | \-->first/last/firstunread event as above - \-->first module name (DBModuleName) - \-->next module name (DBModuleName) - \--> ... -*/ - -#define DB_THIS_VERSION 0x00000700u - -#include -struct DBHeader { - BYTE signature[16]; // 'Miranda ICQ DB',0,26 - DWORD version; //as 4 bytes, ie 1.2.3.10=0x0102030a - //this version is 0x00000700 - DWORD ofsFileEnd; //offset of the end of the database - place to write - //new structures - DWORD slackSpace; //a counter of the number of bytes that have been - //wasted so far due to deleting structures and/or - //re-making them at the end. We should compact when - //this gets above a threshold - DWORD contactCount; //number of contacts in the chain,excluding the user - DWORD ofsFirstContact; //offset to first struct DBContact in the chain - DWORD ofsUser; //offset to struct DBContact representing the user - DWORD ofsFirstModuleName; //offset to first struct DBModuleName in the chain -}; - -#define DBCONTACT_SIGNATURE 0x43DECADEu -struct DBContact { - DWORD signature; - DWORD ofsNext; //offset to the next contact in the chain. zero if - //this is the 'user' contact or the last contact - //in the chain - DWORD ofsFirstSettings; //offset to the first DBContactSettings in the - //chain for this contact. - DWORD eventCount; //number of events in the chain for this contact - DWORD ofsFirstEvent,ofsLastEvent; //offsets to the first and last DBEvent in - //the chain for this contact - DWORD ofsFirstUnreadEvent; //offset to the first (chronological) unread event - //in the chain, 0 if all are read - DWORD timestampFirstUnread; //timestamp of the event at ofsFirstUnreadEvent -}; - -#define DBMODULENAME_SIGNATURE 0x4DDECADEu -struct DBModuleName { - DWORD signature; - DWORD ofsNext; //offset to the next module name in the chain - BYTE cbName; //number of characters in this module name - char name[1]; //name, no nul terminator -}; - -#define DBCONTACTSETTINGS_SIGNATURE 0x53DECADEu -struct DBContactSettings { - DWORD signature; - DWORD ofsNext; //offset to the next contactsettings in the chain - DWORD ofsModuleName; //offset to the DBModuleName of the owner of these - //settings - DWORD cbBlob; //size of the blob in bytes. May be larger than the - //actual size for reducing the number of moves - //required using granularity in resizing - BYTE blob[1]; //the blob. a back-to-back sequence of DBSetting - //structs, the last has cbName=0 -}; - -/* not a valid structure, content is figured out on the fly -struct DBSetting { - BYTE cbName; //number of bytes in the name of this setting - //this =0 marks the end - char szName[...]; //setting name, excluding nul - BYTE dataType; //type of data. see m_database.h, db/contact/getsetting - union { //a load of types of data, length is defined by dataType - BYTE bVal; WORD wVal; DWORD dVal; - struct { - WORD cbString; - char szVal[...]; //excludes nul terminator - }; - struct { - WORD cbBlob; - BYTE blobVal[...]; - }; - }; -}; -*/ - -#define DBEVENT_SIGNATURE 0x45DECADEu -struct DBEvent { - DWORD signature; - DWORD ofsPrev,ofsNext; //offset to the previous and next events in the - //chain. Chain is sorted chronologically - DWORD ofsModuleName; //offset to a DBModuleName struct of the name of - //the owner of this event - DWORD timestamp; //seconds since 00:00:00 01/01/1970 - DWORD flags; //see m_database.h, db/event/add - WORD eventType; //module-defined event type - DWORD cbBlob; //number of bytes in the blob - BYTE blob[1]; //the blob. module-defined formatting -}; -#include diff --git a/plugins/Import/src/progress.cpp b/plugins/Import/src/progress.cpp index 99412f647a..2328ce1222 100644 --- a/plugins/Import/src/progress.cpp +++ b/plugins/Import/src/progress.cpp @@ -1,8 +1,8 @@ /* -Import plugin for Miranda IM +Import plugin for Miranda NG -Copyright (C) 2001-2005 Martin Öberg, Richard Hughes, Roland Rabien & Tristan Van de Vreede +Copyright (C) 2012 George Hazan This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/plugins/Import/src/resource.h b/plugins/Import/src/resource.h index 7bf769f14d..469bfb0259 100644 --- a/plugins/Import/src/resource.h +++ b/plugins/Import/src/resource.h @@ -5,7 +5,6 @@ #define IDC_BACK 3 #define IDD_WIZARD 101 #define IDD_OPTIONS 102 -#define IDD_ICQSERVER 104 #define IDD_IMPORTTYPE 106 #define IDD_WIZARDINTRO 107 #define IDD_FINISHED 108 @@ -14,17 +13,13 @@ #define IDD_PROGRESS 111 #define IDD_ADVOPTIONS 112 #define IDI_IMPORT 177 -#define IDC_MIRABILIS 1000 #define IDC_DONTLOADPLUGIN 1001 -#define IDC_MIRANDA 1001 -#define IDC_USEFINDADD 1004 +#define IDC_MIRANDA 1002 #define IDC_OTHER 1005 #define IDC_LIST 1006 #define IDC_FILENAME 1007 #define IDC_PROGRESS 1008 #define IDC_STATUS 1009 -#define IDC_MIRABILISRUNNING 1010 -#define IDC_MIRABILISACCOUNT 1011 #define IDC_RADIO_ALL 1016 #define IDC_RADIO_CONTACTS 1017 #define IDC_RADIO_CUSTOM 1018 diff --git a/plugins/Import/src/utils.cpp b/plugins/Import/src/utils.cpp index 0e57e2479f..69489ca087 100644 --- a/plugins/Import/src/utils.cpp +++ b/plugins/Import/src/utils.cpp @@ -1,8 +1,8 @@ /* -Import plugin for Miranda IM +Import plugin for Miranda NG -Copyright (C) 2001-2005 Martin Öberg, Richard Hughes, Roland Rabien & Tristan Van de Vreede +Copyright (C) 2012 George Hazan This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -36,52 +36,6 @@ 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; @@ -141,76 +95,25 @@ HANDLE HistoryImportFindContact(HWND hdlgProgress, char* szModuleName, DWORD 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 CreateGroup(const TCHAR* group, 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 ) + if (group == NULL) return 0; - cbName = _tcslen(tmp); - tszGrpName = (TCHAR*)_alloca(( cbName+2 )*sizeof( TCHAR )); + size_t cbName = _tcslen(group); + TCHAR *tszGrpName = (TCHAR*)_alloca(( cbName+2 )*sizeof( TCHAR )); tszGrpName[0] = 1 | GROUPF_EXPANDED; - _tcscpy( tszGrpName+1, tmp ); - mir_free( tmp ); + _tcscpy(tszGrpName+1, group); // Check for duplicate & find unused id - for (groupId = 0; ; groupId++) { + char groupIdStr[11]; + for (int groupId = 0; ; groupId++) { DBVARIANT dbv; itoa(groupId, groupIdStr,10); if (DBGetContactSettingTString(NULL, "CListGroups", groupIdStr, &dbv)) diff --git a/plugins/Import/src/wizard.cpp b/plugins/Import/src/wizard.cpp index 029f251943..bd92adeb6b 100644 --- a/plugins/Import/src/wizard.cpp +++ b/plugins/Import/src/wizard.cpp @@ -1,8 +1,8 @@ /* -Import plugin for Miranda IM +Import plugin for Miranda NG -Copyright (C) 2001-2005 Martin Öberg, Richard Hughes, Roland Rabien & Tristan Van de Vreede +Copyright (C) 2012 George Hazan This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -23,55 +23,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "import.h" #include "resource.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 ) { @@ -83,7 +34,7 @@ INT_PTR CALLBACK WizardIntroPageProc(HWND hdlg, UINT message, WPARAM wParam, LPA case WM_COMMAND: switch( LOWORD( wParam )) { case IDOK: - PostMessage(GetParent(hdlg), WIZM_GOTOPAGE, IDD_IMPORTTYPE, (LPARAM)ImportTypePageProc); + PostMessage(GetParent(hdlg), WIZM_GOTOPAGE, IDD_MIRANDADB, (LPARAM)MirandaPageProc); break; case IDCANCEL: @@ -107,7 +58,7 @@ INT_PTR CALLBACK FinishedPageProc(HWND hdlg, UINT message, WPARAM wParam, LPARAM case WM_COMMAND: switch( LOWORD( wParam )) { case IDOK: - PostMessage(GetParent(hdlg), WIZM_GOTOPAGE, IDD_IMPORTTYPE, (LPARAM)ImportTypePageProc); + PostMessage(GetParent(hdlg), WIZM_GOTOPAGE, IDD_MIRANDADB, (LPARAM)MirandaPageProc); break; case IDCANCEL: @@ -207,8 +158,6 @@ INT_PTR CALLBACK WizardDlgProc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lP case WM_CLOSE: DestroyWindow(hwndPage); DestroyWindow(hdlg); - - FreeICQAccountsList(); break; } -- cgit v1.2.3