summaryrefslogtreecommitdiff
path: root/plugins/Import/src/miranda.cpp
diff options
context:
space:
mode:
authorGeorge Hazan <george.hazan@gmail.com>2012-07-24 17:57:46 +0000
committerGeorge Hazan <george.hazan@gmail.com>2012-07-24 17:57:46 +0000
commit9628bd0e796e0713377373863b962e3594204045 (patch)
tree92cc3afab82c75765cf038d00193a1679655d33a /plugins/Import/src/miranda.cpp
parentf4686842d390f8d5a2231f540c68b177111c7f87 (diff)
new import plugin for Miranda NG
git-svn-id: http://svn.miranda-ng.org/main/trunk@1166 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/Import/src/miranda.cpp')
-rw-r--r--plugins/Import/src/miranda.cpp1134
1 files changed, 34 insertions, 1100 deletions
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);
-} }