diff options
author | George Hazan <george.hazan@gmail.com> | 2012-07-24 17:57:46 +0000 |
---|---|---|
committer | George Hazan <george.hazan@gmail.com> | 2012-07-24 17:57:46 +0000 |
commit | 9628bd0e796e0713377373863b962e3594204045 (patch) | |
tree | 92cc3afab82c75765cf038d00193a1679655d33a /plugins | |
parent | f4686842d390f8d5a2231f540c68b177111c7f87 (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')
-rw-r--r-- | plugins/Import/docs/import-readme.txt | 4 | ||||
-rw-r--r-- | plugins/Import/import_10.vcxproj | 6 | ||||
-rw-r--r-- | plugins/Import/import_10.vcxproj.filters | 18 | ||||
-rw-r--r-- | plugins/Import/res/resource.rc | 54 | ||||
-rw-r--r-- | plugins/Import/src/ICQserver.cpp | 74 | ||||
-rw-r--r-- | plugins/Import/src/ICQserver.h | 62 | ||||
-rw-r--r-- | plugins/Import/src/import.cpp | 497 | ||||
-rw-r--r-- | plugins/Import/src/import.h | 33 | ||||
-rw-r--r-- | plugins/Import/src/main.cpp | 6 | ||||
-rw-r--r-- | plugins/Import/src/mirabilis.cpp | 1493 | ||||
-rw-r--r-- | plugins/Import/src/mirabilis.h | 200 | ||||
-rw-r--r-- | plugins/Import/src/miranda.cpp | 1134 | ||||
-rw-r--r-- | plugins/Import/src/mirandadb0700.h | 142 | ||||
-rw-r--r-- | plugins/Import/src/progress.cpp | 4 | ||||
-rw-r--r-- | plugins/Import/src/resource.h | 7 | ||||
-rw-r--r-- | plugins/Import/src/utils.cpp | 115 | ||||
-rw-r--r-- | plugins/Import/src/wizard.cpp | 59 |
17 files changed, 585 insertions, 3323 deletions
diff --git a/plugins/Import/docs/import-readme.txt b/plugins/Import/docs/import-readme.txt index 0ad0b7b1d2..af0f681fc5 100644 --- a/plugins/Import/docs/import-readme.txt +++ b/plugins/Import/docs/import-readme.txt @@ -1,5 +1,5 @@ - Import Plugin for Miranda IM
+ Import plugin for Miranda NG
____________________________
@@ -111,7 +111,7 @@ E-mail: strickz at miranda-im.org License and Copyright
_____________________
-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/import_10.vcxproj b/plugins/Import/import_10.vcxproj index 348b48c382..e5cde04716 100644 --- a/plugins/Import/import_10.vcxproj +++ b/plugins/Import/import_10.vcxproj @@ -207,21 +207,17 @@ <ClCompile Include="..\Utils\mir_icons.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
- <ClCompile Include="src\ICQserver.cpp" />
+ <ClCompile Include="src\import.cpp" />
<ClCompile Include="src\main.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
- <ClCompile Include="src\mirabilis.cpp" />
<ClCompile Include="src\miranda.cpp" />
<ClCompile Include="src\progress.cpp" />
<ClCompile Include="src\utils.cpp" />
<ClCompile Include="src\wizard.cpp" />
</ItemGroup>
<ItemGroup>
- <ClInclude Include="src\ICQserver.h" />
<ClInclude Include="src\import.h" />
- <ClInclude Include="src\mirabilis.h" />
- <ClInclude Include="src\mirandadb0700.h" />
<ClInclude Include="src\resource.h" />
</ItemGroup>
<ItemGroup>
diff --git a/plugins/Import/import_10.vcxproj.filters b/plugins/Import/import_10.vcxproj.filters index 0c89a67229..f7ed0a68e6 100644 --- a/plugins/Import/import_10.vcxproj.filters +++ b/plugins/Import/import_10.vcxproj.filters @@ -18,15 +18,9 @@ </Filter>
</ItemGroup>
<ItemGroup>
- <ClCompile Include="src\ICQserver.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
<ClCompile Include="src\main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\mirabilis.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
<ClCompile Include="src\miranda.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -42,20 +36,14 @@ <ClCompile Include="..\Utils\mir_icons.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="src\import.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
- <ClInclude Include="src\ICQserver.h">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="src\import.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="src\mirabilis.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\mirandadb0700.h">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="src\resource.h">
<Filter>Header Files</Filter>
</ClInclude>
diff --git a/plugins/Import/res/resource.rc b/plugins/Import/res/resource.rc index 103ad9c908..3ad1b1111a 100644 --- a/plugins/Import/res/resource.rc +++ b/plugins/Import/res/resource.rc @@ -60,23 +60,19 @@ BEGIN 210,8
CONTROL "From a Miranda IM database.",IDC_MIRANDA,"Button",
BS_AUTORADIOBUTTON,11,31,204,10
- CONTROL "From a Mirabilis ICQ (99a - 2003a) database.",
- IDC_MIRABILIS,"Button",BS_AUTORADIOBUTTON,11,46,204,10
- CONTROL "Use the Find/Add contacts tool to populate my contact list.",
- IDC_USEFINDADD,"Button",BS_AUTORADIOBUTTON,11,61,204,10
END
IDD_WIZARDINTRO DIALOGEX 0, 0, 220, 114
STYLE DS_SETFONT | DS_FIXEDSYS | DS_3DLOOK | DS_CONTROL | WS_CHILD
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
- LTEXT "This wizard will help you import contacts and message history from Mirabilis ICQ, as well as letting you import from other Miranda IM profiles.",
+ LTEXT "This wizard will help you import contacts and message history from another Miranda profile or from an external program.",
IDC_STATIC,33,12,182,32
ICON IDI_IMPORT,IDC_STATIC,5,12,20,20
LTEXT "Click ""Next"" to choose the information you wish to import, or click ""Cancel"" to exit the wizard and continue using Miranda.",
IDC_STATIC,33,49,182,25
- CTEXT "It is recommended that you create a backup of your current Miranda profile before importing.",
- IDC_STATIC,30,81,182,21
+ LTEXT "It is recommended that you create a backup of your current Miranda profile before importing.",
+ IDC_STATIC,33,81,182,21
END
IDD_FINISHED DIALOGEX 0, 0, 220, 114
@@ -95,24 +91,6 @@ BEGIN IDC_STATIC,5,69,210,24
END
-IDD_MIRABILISDB DIALOGEX 0, 0, 220, 114
-STYLE DS_SETFONT | DS_FIXEDSYS | DS_3DLOOK | DS_CONTROL | WS_CHILD
-FONT 8, "MS Shell Dlg", 0, 0, 0x1
-BEGIN
- LTEXT "Miranda has found Mirabilis ICQ databases corresponding to the following ICQ numbers. Please select the one you wish to import, or click ""Other Database"" if your database is not listed.",
- IDC_STATIC,5,5,210,24
- LISTBOX IDC_LIST,5,31,210,36,LBS_SORT | LBS_NOINTEGRALHEIGHT |
- WS_VSCROLL | WS_TABSTOP
- PUSHBUTTON "&Other Database...",IDC_OTHER,149,69,66,14
- RTEXT "&Filename:",IDC_STATIC,5,88,34,8
- EDITTEXT IDC_FILENAME,42,86,173,12,ES_AUTOHSCROLL
- CTEXT "Warning: Mirabilis ICQ running. Import may not be reliable.",
- IDC_MIRABILISRUNNING,5,101,210,8
- RTEXT "&Account:",IDC_STATIC,6,74,34,8
- COMBOBOX IDC_MIRABILISACCOUNT,42,71,102,30,CBS_DROPDOWNLIST |
- WS_VSCROLL | WS_TABSTOP
-END
-
IDD_MIRANDADB DIALOGEX 0, 0, 220, 114
STYLE DS_SETFONT | DS_FIXEDSYS | DS_3DLOOK | DS_CONTROL | WS_CHILD
FONT 8, "MS Shell Dlg", 0, 0, 0x1
@@ -168,16 +146,6 @@ BEGIN IDC_STATIC_CUSTOM,26,84,187,16,WS_DISABLED
END
-IDD_ICQSERVER DIALOGEX 0, 0, 220, 114
-STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
-FONT 8, "MS Shell Dlg", 0, 0, 0x1
-BEGIN
- LTEXT "Miranda has now been configured to automatically download the contacts in your server-side contact list the next time you connect to ICQ.",
- IDC_STATIC,7,9,206,31
- LTEXT "If you want to change the way Miranda handles server-side contacts at a later time, you can do this in the ""ICQ Contacts"" page in the Miranda options.",
- IDC_STATIC,7,44,206,37
-END
-
IDD_ADVOPTIONS DIALOGEX 0, 0, 220, 114
STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
FONT 8, "MS Shell Dlg", 0, 0, 0x0
@@ -250,14 +218,6 @@ BEGIN BOTTOMMARGIN, 109
END
- IDD_MIRABILISDB, DIALOG
- BEGIN
- LEFTMARGIN, 5
- RIGHTMARGIN, 215
- TOPMARGIN, 5
- BOTTOMMARGIN, 109
- END
-
IDD_MIRANDADB, DIALOG
BEGIN
LEFTMARGIN, 3
@@ -290,14 +250,6 @@ BEGIN BOTTOMMARGIN, 111
END
- IDD_ICQSERVER, DIALOG
- BEGIN
- LEFTMARGIN, 7
- RIGHTMARGIN, 213
- TOPMARGIN, 7
- BOTTOMMARGIN, 107
- END
-
IDD_ADVOPTIONS, DIALOG
BEGIN
VERTGUIDE, 10
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 <windows.h>
-
-// ======================
-// == 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 <m_db_int.h>
+
+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<char> 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 <newpluginapi.h>
#include <m_langpack.h>
#include <m_system.h>
+#include <m_system_cpp.h>
#include <m_database.h>
#include <m_protocols.h>
#include <m_protosvc.h>
@@ -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(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);
-}
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 <windows.h>
-#include <newpluginapi.h>
-#include <m_database.h>
-
-// ======================
-// == 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 <pshpack1.h>
-
-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 <poppack.h>
-
-#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 <pshpack1.h>
-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 <poppack.h>
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;
}
|