diff options
Diffstat (limited to 'plugins/Import/src/mirabilis.cpp')
-rw-r--r-- | plugins/Import/src/mirabilis.cpp | 1493 |
1 files changed, 0 insertions, 1493 deletions
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(id<entry->entryIdLow) 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<dwProperties;n++) dwOffset+=*(PWORD)(pDat+dwOffset)+2;
- break;
- case 0x6E:
- for(n=0;n<dwProperties;n++) {
- if (!(dwOffset = ReadPropertyBlock(dwOffset, NULL, NULL))) return 0;
- }
- break;
- default:
- // Unknown sub list type
- AddMessage( LPGEN("Error: Unknown sub list type (%u) at offset %u."), dwSubType, dwOffset);
- return 0;
- }
-
- return dwOffset;
-}
-
-DWORD ReadPropertyBlock(DWORD dwOffset, char* SearchWord, int* nSearchResult)
-{
- DWORD n, dwProperties, nameOfs;
- WORD nameLen;
-
- #ifdef _LOGGING
- AddMessage( LPGEN("Attempting to parse property block at offset %u."), dwOffset );
- #endif
-
- // Reset search result
- if (SearchWord) *nSearchResult = 0;
-
- // Check number of properties in block
- dwOffset+=2;
- dwProperties = *(PDWORD)(pDat+dwOffset);
-
- // Scan all properties and search for
- // 'SearchWord' (if it has been specified).
- dwOffset+=4;
- for(n=0;n<dwProperties;n++) {
- nameLen=*(PWORD)(pDat+dwOffset); // Length of current property name
- dwOffset+=2;
- nameOfs=dwOffset; // Save pointer to start of name
- dwOffset+=nameLen; // dwOffset now points to property value type
-
- if ( SearchWord ) {
- // Is this the property we are searching for?
- if (!lstrcmpA((char*)(pDat+nameOfs),SearchWord)) {
- *nSearchResult = 1;
- return dwOffset;
- } }
-
- // Increase 'dwOffset' to point to length of next property
- switch(*(pDat+dwOffset)) {
- case 0x64:
- case 0x65: dwOffset+=2; break;
- case 0x66:
- case 0x67: dwOffset+=3; break;
- case 0x68:
- case 0x69: dwOffset+=5; break;
- case 0x6b: dwOffset+=*(PWORD)(pDat+dwOffset+1)+3; break;
- case 0x6d:
- dwOffset = ReadSubList(dwOffset+1);
- if (!dwOffset) return 0;
- break;
- case 0x6f: dwOffset+=*(PDWORD)(pDat+dwOffset+1)+5; break;
- default:
- // Unknown property value type
- AddMessage( LPGEN("Error: Unknown datatype (%u) at offset %u."), *(pDat+dwOffset), dwOffset);
- return 0;
- } }
-
- // We have reached the end without finding
- // the property we searched for
- if (SearchWord) *nSearchResult = 0;
-
- // Return offset to the byte right after the
- // property list
- return dwOffset;
-}
-
-DWORD ReadPropertyBlockList(DWORD dwOffset, char* SearchWord, int* nSearchResult)
-{
- DWORD dwBlocks, n;
-
- #ifdef _LOGGING
- AddMessage( LPGEN("Attempting to parse property block list at offset %u."), dwOffset );
- #endif
-
- // Check number of blocks in list
- dwBlocks = *(PDWORD)(pDat+dwOffset);
-
- // Scan all blocks and search for 'SearchWord' (if
- // it has been specified).
- dwOffset += 4;
- for(n = 0;n<dwBlocks;n++) {
- if (!(dwOffset = ReadPropertyBlock(dwOffset, SearchWord, nSearchResult))) {
- AddMessage( LPGEN("Failed to read Property block."));
- return 0;
- }
- if (SearchWord)
- // Was the property found in the block?
- if (*nSearchResult) return dwOffset;
- }
-
- // We have reached the end without finding
- // the property we searched for
- if (SearchWord) *nSearchResult = 0;
-
- // Return offset to the byte right after the
- // property list
- return dwOffset;
-}
-
-DWORD ReadWavList(DWORD dwOffset)
-{
- DWORD dwWavEntries, n;
- WORD wNameLen;
-
- #ifdef _LOGGING
- AddMessage( LPGEN("Attempting to parse wav file list at offset %u."), dwOffset);
- #endif
-
- // Check number of wav entries
- dwWavEntries = *(PDWORD)(pDat+dwOffset);
-
- // Read entire list
- dwOffset+=4;
- for(n = 0;n<dwWavEntries;n++) {
- wNameLen = *(PWORD)(pDat+dwOffset+0x0A);
- dwOffset += wNameLen + 0x0C;
- }
-
- // Return the offset to the byte right
- // after the list
- return dwOffset;
-}
-
-DWORD FindMyDetails(void)
-{
- DWORD dwOffset = GetIdDatOfs(1005);
-
- if (!dwOffset) return 0;
- if (*(PDWORD)(pDat+dwOffset+0x08) != 1005) return 0;
- if (*(PBYTE)(pDat+dwOffset+0x0C) != 0xE4) return 0;
- if (*(int*)(pDat+dwOffset+0x1e) != 'USER') return 0;
- if (*(PDWORD)(pDat+dwOffset+0x22) != 6) return 0;
-
- return dwOffset;
-}
-
-// dwOffset must point to MyDetails
-DWORD FindGroupList(DWORD dwOffset)
-{
- DWORD n, dwPhoneEntries;
- WORD wSeparatorValue;
- int nFormat;
-
- wSeparatorValue = *(PWORD)(pDat+dwOffset+0x1c);
- nFormat = GetEntryVersion(wSeparatorValue);
-
- #ifdef _LOGGING
- AddMessage( LPGEN("Attempting to parse group list, type %d."), nFormat );
- #endif
-
- switch (nFormat) {
- case ENTRYV99A:
- if (!(dwOffset = ReadWavList(dwOffset+0x54))) return 0;
- if (!(dwOffset = ReadPropertyBlock(dwOffset+38, NULL, NULL))) return 0;
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // User 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; // Primary e-mail
- dwOffset += 0x13; // Various fixed length data
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Home city
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Home state
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Additional details
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // User homepage
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Home phone number
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Notes
- dwOffset += 0x08; // Various fixed length data
- dwOffset += 0x04; // ++ UNKNOWN ++
- dwPhoneEntries = *(PDWORD)(pDat+dwOffset); // Phonebook starts here
- dwOffset += 0x04;
- for(n = 0;n<dwPhoneEntries;n++) {
- dwOffset += *(PWORD)(pDat+dwOffset)+2;
- dwOffset += *(PWORD)(pDat+dwOffset)+2;
- dwOffset += *(PWORD)(pDat+dwOffset)+2;
- dwOffset += *(PWORD)(pDat+dwOffset)+2;
- dwOffset += 2;
- dwOffset += *(PWORD)(pDat+dwOffset)+2;
- }
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Picture file name
- dwOffset += 0x06; // ++ UNKNOWN ++ (8 enligt spec)
- dwOffset += 0x06; // Various fixed length data
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Secondary e-mail
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Old e-mail
- dwOffset += 0x04; // ++ UNKNOWN ++
- dwOffset += 0x03; // Various fixed length data
- dwOffset += 0x08; // ++ UNKNOWN ++
- dwOffset += 0x03; // Various fixed length data
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Home street address
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Home fax number
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Home cell phone number
- dwOffset += 0x04; // ++ UNKNOWN ++
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Company Div/Dept
- dwOffset += 0x01; // Occupation
- dwOffset += 0x04; // ++ UNKNOWN ++
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Company position
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Company name
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Work street address
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Work state
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Work city
- dwOffset += 0x08; // Various fixed length data
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Work phone number
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Work fax number
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Work homepage
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Past background #1
- dwOffset += 0x02; // Past background #1 category
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Past background #2
- dwOffset += 0x02; // Past background #2 category
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Past background #3
- dwOffset += 0x02; // Past background #3 category
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Affiliation #1
- dwOffset += 0x02; // Affiliation #1 category
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Affiliation #2
- dwOffset += 0x02; // Affiliation #2 category
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Affiliation #3
- dwOffset += 0x02; // Affiliation #3 category
- dwOffset += 0x14; // ++ UNKNOWN ++
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Interest #1
- dwOffset += 0x02; // Interest #1 category
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Interest #2
- dwOffset += 0x02; // Interest #2 category
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Interest #3
- dwOffset += 0x02; // Interest #3 category
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Interest #4
- dwOffset += 0x02; // Interest #4 category
- dwOffset += 0x28; // ++ UNKNOWN ++
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // Password
- dwOffset += 0x04; // ++ UNKNOWN ++
- dwOffset += 0x0E; // ++ UNKNOWN ++
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // POP3 account name
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // POP3 account password
- dwOffset += *(PWORD)(pDat+dwOffset)+2; // POP server name
- dwOffset += 0x15; // ++ UNKNOWN ++
- return dwOffset;
-
- case ENTRYV99B:
- if (!(dwOffset = ReadWavList(dwOffset+0x2C))) return 0;
- if (!(dwOffset = ReadPropertyBlockList(dwOffset+0x02, NULL, NULL))) return 0;
- dwOffset += 0x08;
- dwPhoneEntries = *(PDWORD)(pDat+dwOffset); // Phonebook
- dwOffset += 0x04;
- for(n = 0;n<dwPhoneEntries;n++) {
- dwOffset += *(PWORD)(pDat+dwOffset)+2;
- dwOffset += *(PWORD)(pDat+dwOffset)+2;
- dwOffset += *(PWORD)(pDat+dwOffset)+2;
- dwOffset += *(PWORD)(pDat+dwOffset)+2;
- dwOffset += 2;
- dwOffset += *(PWORD)(pDat+dwOffset)+2;
- }
- return dwOffset + 0x06;
-
- case ENTRYV2000A:
- case ENTRYV2000B:
- case ENTRYV2002A:
- if (!(dwOffset = ReadWavList(dwOffset+0x2C))) return 0;
- if (!(dwOffset = ReadPropertyBlockList(dwOffset+0x02, NULL, NULL))) return 0;
- return dwOffset + 0x06;
-
- case ENTRYV2001A:
- case ENTRYV2001B:
- if (!(dwOffset = ReadPropertyBlockList(dwOffset+0x2C, NULL, NULL))) return 0;
- return dwOffset + 0x06;
-
- default:
- AddMessage( LPGEN("default"));
- return 0;
- }
-}
-
-// ------------------------------------------------
-// Finds the name of a group with a specific GroupID.
-// ------------------------------------------------
-// dwGroupID is the GroupID of the group.
-// Returns a pointer to the name string or NULL if
-// it was not found.
-char* GetGroupName(DWORD dwGroupID)
-{
- DWORD dwGroups, n, tmpOfs, dwOffset;
- char* strGroupName = 0;
- int nSearchResult;
-
- // Check for the existence of any group
- if (!dwGroupListOfs) return 0;
- dwOffset = dwGroupListOfs;
- dwGroups = *(PDWORD)(pDat + dwOffset);
- if (dwGroups == 0) return 0;
-
- dwOffset += 4;
-
- // Examine all groups
- switch (dwDBVersion) {
- case DBV99A:
- case DBV99B:
- for (n = 0; n < dwGroups; n++) {
- if (dwGroupID == *(PDWORD)(pDat + dwOffset)) {
- if (*(PWORD)(pDat + dwOffset + 4) > 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);
-}
|