/* importTrillian: History & Contacts import plugin for Miranda-IM. Copyright (C) 2005 Daniel 'Spin' Hofer This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include "resource.h" #include "newpluginapi.h" #include "m_langpack.h" #include "m_system.h" #include "m_database.h" #include "m_clist.h" #include "m_protomod.h" #pragma warning( disable: 4311 ) #pragma warning( disable: 4312 ) #define IMPORT_MODULE "MIMImportTrillian" #define IMPORT_SERVICE "MIMImportTrillian/ImportTrillian" #define DLG_UPDATE 0x2000 #define SESS_START1 "Session Start (" #define SESS_START2 "Start (ICQ - " #define SESS_START3 "Start (MSN - " #define SESS_START4 "Start (AIM - " #define SESS_START5 "Start (Yahoo! - " #define SESS_START6 "Start (IRC - " #define SESS_STOP "Session Close (" void Utf8ToAnsi(const char *szIn, char *szOut, int cchOut); static int ImportCommand( WPARAM wParam,LPARAM lParam ); static int ImportMessages( ); static char line[2048]; static char file[MAX_PATH]; static char delBeforeDate[MAX_PATH]; static char icqUin[32]; time_t delBeforeTS; static HANDLE hHookModulesLoaded; HINSTANCE hInst; PLUGINLINK *pluginLink; char status[256]; BOOL importProt[5] = { 1, 1, 1, 1, 1 }; BOOL importNic = TRUE; BOOL importCha = TRUE; BOOL importMsg = TRUE; BOOL importStat = TRUE; BOOL importAdd = FALSE; BOOL importEx = TRUE; BOOL skipDup = FALSE; BOOL repDup = TRUE; BOOL delBefore = FALSE; BOOL speedMode = TRUE; BOOL utf8AutoDetect = FALSE; BOOL utf8DoAlways = FALSE; int aborting = 0; int finished = 0; int getNick = 0; char lastNick[256]; PLUGININFO pluginInfo = { sizeof(PLUGININFO), "Import Trillian history/contacts", PLUGIN_MAKE_VERSION(0,2,0,0), "Miranda IM history/contact import plugin.", "Daniel \'Zpin\' Hofer", "dhofer@freesurf.ch", "©2006 by Daniel \'Zpin\' Hofer", "http://www.zpin.ch", 0, 0 }; BOOL WINAPI DllMain( HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved ) { hInst = hinstDLL; return TRUE; } static int readLine( FILE *f ) { int i = 0; char chr; chr = fgetc( f ); while( chr != '\n' && !feof( f ) && i < 2047 ) { line[i++] = chr; chr = fgetc( f ); } line[i] = '\0'; return !feof( f ); } struct tm string2Tm( char *string ) { char mon[4]; int mt = 0, day, hr, min, sec, yr; struct tm starttime; sscanf( string, "%3s %d %d:%d:%d %d", &mon, &day, &hr, &min, &sec, &yr ); if( !strcmp( mon, "Jan" ) ) mt = 0; else if( !strcmp( mon, "Feb" ) ) mt = 1; else if( !strcmp( mon, "Mar" ) ) mt = 2; else if( !strcmp( mon, "Apr" ) ) mt = 3; else if( !strcmp( mon, "May" ) ) mt = 4; else if( !strcmp( mon, "Jun" ) ) mt = 5; else if( !strcmp( mon, "Jul" ) ) mt = 6; else if( !strcmp( mon, "Aug" ) ) mt = 7; else if( !strcmp( mon, "Sep" ) ) mt = 8; else if( !strcmp( mon, "Oct" ) ) mt = 9; else if( !strcmp( mon, "Nov" ) ) mt = 10; else if( !strcmp( mon, "Dec" ) ) mt = 11; starttime.tm_mon = mt; starttime.tm_mday = day; starttime.tm_hour = hr; starttime.tm_min = min; starttime.tm_sec = sec; starttime.tm_year = yr - 1900; return starttime; } BOOL CALLBACK StartupDialogProc( HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam ) { FILE *fl; switch( message ) { case WM_INITDIALOG: SetWindowText( hdlg, Translate( "Import settings" ) ); SetDlgItemText( hdlg, IDC_INFO1, Translate( "Trillian logs directory" ) ); SetDlgItemText( hdlg, IDC_INFO2, Translate( "Protocols" ) ); SetDlgItemText( hdlg, IDC_INFO3, Translate( "Contacts" ) ); SetDlgItemText( hdlg, IDC_INFO4, Translate( "Import" ) ); SetDlgItemText( hdlg, IDC_BROWSE, Translate( "Browse" ) ); SetDlgItemText( hdlg, IDC_UTF8, Translate( "UTF8" ) ); SetDlgItemText( hdlg, IDOK, Translate( "Start" ) ); SetDlgItemText( hdlg, IDCANCEL, Translate( "Cancel" ) ); SetDlgItemText( hdlg, IDC_IMPICQ, Translate( "Import ICQ history" ) ); SetDlgItemText( hdlg, IDC_IMPMSN, Translate( "Import MSN history" ) ); SetDlgItemText( hdlg, IDC_IMPAIM, Translate( "Import AIM history" ) ); SetDlgItemText( hdlg, IDC_IMPICQ, Translate( "Import ICQ history" ) ); SetDlgItemText( hdlg, IDC_IMPYAHOO, Translate( "Import Yahoo! history" ) ); SetDlgItemText( hdlg, IDC_IMPIRC, Translate( "Import IRC history" ) ); SetDlgItemText( hdlg, IDC_IMPCHA, Translate( "Import IRC channel history" ) ); SetDlgItemText( hdlg, IDC_IMPEX, Translate( "Import history of existing contacts" ) ); SetDlgItemText( hdlg, IDC_IMPADD, Translate( "Add new contacts if a contact from the history is not on the list" ) ); SetDlgItemText( hdlg, IDC_IMPMSG, Translate( "Import messages" ) ); SetDlgItemText( hdlg, IDC_SKIPDUP, Translate( "Skip duplicate messages" ) ); SetDlgItemText( hdlg, IDC_REPDUP, Translate( "Replace duplicate messages" ) ); SetDlgItemText( hdlg, IDC_DELBEF, Translate( "Delete entries before" ) ); SetDlgItemText( hdlg, IDC_DELBEFINFO, Translate( "(Must match this format exactly: MMM DD HH:mm:ss YYYY)" ) ); SetDlgItemText( hdlg, IDC_IMPSTAT, Translate( "Import status reports (filetransfers, away msg, etc.)" ) ); SetDlgItemText( hdlg, IDC_SPEEDMODE, Translate( "Fast mode (backup your db!)" ) ); SetDlgItemText( hdlg, IDC_UTF8AUTO, Translate( "Try to auto-detect UTF8 strings (is slow, detects öäüßéàèç)" ) ); SetDlgItemText( hdlg, IDC_UTF8ALWAYS, Translate( "Interpret logs as UTF8 files" ) ); ShowWindow( hdlg, SW_SHOW ); SendMessage( hdlg, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon(hInst,MAKEINTRESOURCE(IDI_IMPORT))); fl = fopen( "importTrillian.ini", "r" ); if( fl ) { int i = -1; do { i++; file[i] = fgetc( fl ); } while( file[i] != EOF && file[i] != '\n' && i < MAX_PATH ); file[i] = '\0'; fclose( fl ); } SendDlgItemMessage( hdlg, IDC_LOGDIR, WM_SETTEXT, 0, (DWORD)file ); SendDlgItemMessage( hdlg, IDC_DELBEFDATE, WM_SETTEXT, 0, (DWORD)"Mar 16 20:31:29 2005" ); CheckDlgButton( hdlg, IDC_IMPICQ, TRUE ); CheckDlgButton( hdlg, IDC_IMPMSN, TRUE ); CheckDlgButton( hdlg, IDC_IMPAIM, TRUE ); CheckDlgButton( hdlg, IDC_IMPYAHOO, TRUE ); CheckDlgButton( hdlg, IDC_IMPIRC, TRUE ); CheckDlgButton( hdlg, IDC_IMPCHA, TRUE ); CheckDlgButton( hdlg, IDC_IMPMSG, TRUE ); CheckDlgButton( hdlg, IDC_IMPSTAT, TRUE ); CheckDlgButton( hdlg, IDC_IMPEX, TRUE ); CheckDlgButton( hdlg, IDC_REPDUP, TRUE ); CheckDlgButton( hdlg, IDC_SPEEDMODE, TRUE ); return TRUE; case WM_COMMAND: switch( LOWORD( wParam ) ) { case IDC_BROWSE: { BROWSEINFO bi = { 0 }; LPITEMIDLIST pidl = SHBrowseForFolder( &bi ); bi.lpszTitle = Translate( "Please select the \'logs\' folder in your Trillian directory" ); if( pidl != 0 ) SHGetPathFromIDList ( pidl, file ); SendDlgItemMessage( hdlg, IDC_LOGDIR, WM_SETTEXT, 0, (DWORD)file ); } break; case IDOK: { struct tm time; importProt[0] = IsDlgButtonChecked( hdlg, IDC_IMPICQ ); importProt[1] = IsDlgButtonChecked( hdlg, IDC_IMPMSN ); importProt[2] = IsDlgButtonChecked( hdlg, IDC_IMPAIM ); importProt[3] = IsDlgButtonChecked( hdlg, IDC_IMPYAHOO ); importNic = IsDlgButtonChecked( hdlg, IDC_IMPIRC ); importCha = IsDlgButtonChecked( hdlg, IDC_IMPCHA ); importProt[4] = importNic || importCha; importMsg = IsDlgButtonChecked( hdlg, IDC_IMPMSG ); importStat = IsDlgButtonChecked( hdlg, IDC_IMPSTAT ); importAdd = IsDlgButtonChecked( hdlg, IDC_IMPADD ); importEx = IsDlgButtonChecked( hdlg, IDC_IMPEX ); skipDup = IsDlgButtonChecked( hdlg, IDC_SKIPDUP ); repDup = IsDlgButtonChecked( hdlg, IDC_REPDUP ); delBefore = IsDlgButtonChecked( hdlg, IDC_DELBEF ); speedMode = IsDlgButtonChecked( hdlg, IDC_SPEEDMODE ); utf8AutoDetect = IsDlgButtonChecked( hdlg, IDC_UTF8AUTO ); utf8DoAlways = IsDlgButtonChecked( hdlg, IDC_UTF8ALWAYS ); GetDlgItemText( hdlg, IDC_LOGDIR, file, MAX_PATH-1 ); GetDlgItemText( hdlg, IDC_DELBEFDATE, delBeforeDate, MAX_PATH-1 ); time = string2Tm( delBeforeDate ); delBeforeTS = mktime( &time ); fl = fopen( "importTrillian.ini", "w" ); if( fl ) { fprintf( fl, "%s", file ); fclose( fl ); } if( ( importProt[0] || importProt[1] || importProt[2] || importProt[3] || importProt[4] ) && ( importMsg || importStat ) ) { PostMessage( hdlg, WM_CLOSE, 0, 0 ); DestroyWindow(hdlg); ImportMessages( ); } else MessageBox( hdlg, Translate( "There's nothing to import, please\nselect a protocol." ), Translate( "Invalid settings" ), 0 ); } break; case IDCANCEL: PostMessage( hdlg, WM_CLOSE, 0, 0 ); break; } break; case WM_CLOSE: DestroyWindow(hdlg); aborting = 1; break; } return FALSE; } BOOL CALLBACK ProgressDialogProc( HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam ) { switch( message ) { case WM_INITDIALOG: SetWindowText( hdlg, Translate( "Importing History" ) ); SetDlgItemText( hdlg, IDC_INFO5, Translate( "Import in progress..." ) ); SetDlgItemText( hdlg, IDC_INFO6, Translate( "Overall (current protocol)" ) ); SetDlgItemText( hdlg, IDC_INFO7, Translate( "File" ) ); SetDlgItemText( hdlg, IDOK, Translate( "OK" ) ); SetDlgItemText( hdlg, IDCANCEL, Translate( "Cancel" ) ); ShowWindow( hdlg, SW_SHOW ); SendMessage( hdlg, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon( hInst,MAKEINTRESOURCE(IDI_IMPORT) ) ); return TRUE; case WM_COMMAND: switch( LOWORD( wParam ) ) { case IDOK: if( finished ) PostMessage( hdlg, WM_CLOSE, 0, 0 ); break; case IDCANCEL: { int ret; ret = MessageBox( hdlg, Translate( "WARNING: If you cancel now and continue later you might\nget duplicate entries. Cancel anyways?" ), Translate( "Warning" ), MB_YESNO ); if( ret == IDYES ) PostMessage( hdlg, WM_CLOSE, 0, 0 ); break; } } break; case DLG_UPDATE: SendDlgItemMessage( hdlg, IDC_STATUS, WM_SETTEXT, 0, (DWORD)status ); SendDlgItemMessage( hdlg, IDC_FILEP, PBM_SETPOS, wParam, 0 ); SendDlgItemMessage( hdlg, IDC_OVERP, PBM_SETPOS, lParam, 0 ); break; case WM_CLOSE: DestroyWindow( hdlg ); aborting = 1; break; } return FALSE; } HANDLE GetContactByID( char* proto, char *idname, char* id ) { HANDLE contact; char *otherproto; DBVARIANT dbv; DWORD idnum = atol(id); contact = (HANDLE)CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 ); while( contact != NULL) { otherproto = (char*)CallService( MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)contact, 0 ); if( ( otherproto != NULL ) && !strcmp( otherproto, proto ) ) { if( !DBGetContactSetting( contact, proto, idname, &dbv ) ) { switch( dbv.type ) { case DBVT_BYTE: if( dbv.bVal == idnum ) return contact; break; case DBVT_WORD: if( dbv.wVal == idnum ) return contact; break; case DBVT_DWORD: if( dbv.dVal == idnum ) return contact; break; default: case DBVT_ASCIIZ: if( !strcmp( id, dbv.pszVal ) ) { DBFreeVariant( &dbv ); return contact; } break; } } } contact = (HANDLE)CallService( MS_DB_CONTACT_FINDNEXT, (WPARAM)contact, 0 ); } return INVALID_HANDLE_VALUE; } HANDLE DeleteContactEventsBefore( HANDLE hContact, time_t ts ) { HANDLE hDbEvent, hPrev; DBEVENTINFO dbei; if( !( hDbEvent = (HANDLE)CallService( MS_DB_EVENT_FINDFIRST, (WPARAM)hContact, 0 ) ) ) return INVALID_HANDLE_VALUE; while( hDbEvent != NULL ) { ZeroMemory( &dbei, sizeof(dbei) ); dbei.cbSize = sizeof(dbei); dbei.cbBlob = 0; CallService( MS_DB_EVENT_GET, (WPARAM)hDbEvent, (LPARAM)&dbei ); hPrev = hDbEvent; hDbEvent = (HANDLE)CallService( MS_DB_EVENT_FINDNEXT, (WPARAM)hDbEvent, 0 ); if( (time_t)dbei.timestamp < ts ) CallService( MS_DB_EVENT_DELETE, (WPARAM)hContact, (LPARAM)hPrev ); } return INVALID_HANDLE_VALUE; } //***************************************** // MODIFIED CODE FROM THE IMPORT.DLL PLUGIN! //***************************************** HANDLE IsDuplicateEvent(HANDLE hContact, DBEVENTINFO dbei ) { HANDLE hExistingDbEvent; DBEVENTINFO dbeiExisting; if( !( hExistingDbEvent = (HANDLE)CallService( MS_DB_EVENT_FINDLAST, (WPARAM)hContact, 0 ) ) ) return INVALID_HANDLE_VALUE; ZeroMemory( &dbeiExisting, sizeof(dbeiExisting) ); dbeiExisting.cbSize = sizeof(dbeiExisting); dbeiExisting.cbBlob = 0; CallService( MS_DB_EVENT_GET, (WPARAM)hExistingDbEvent, (LPARAM)&dbeiExisting ); if( dbei.timestamp > dbeiExisting.timestamp ) return INVALID_HANDLE_VALUE; if( !( hExistingDbEvent = (HANDLE)CallService( MS_DB_EVENT_FINDFIRST, (WPARAM)hContact, 0 ) ) ) return INVALID_HANDLE_VALUE; ZeroMemory( &dbeiExisting, sizeof(dbeiExisting) ); dbeiExisting.cbSize = sizeof(dbeiExisting); dbeiExisting.cbBlob = 0; CallService( MS_DB_EVENT_GET, (WPARAM)hExistingDbEvent, (LPARAM)&dbeiExisting ); if( dbei.timestamp < dbeiExisting.timestamp ) return INVALID_HANDLE_VALUE; while( hExistingDbEvent != NULL ) { char *blob; ZeroMemory( &dbeiExisting, sizeof(dbeiExisting) ); dbeiExisting.cbSize = sizeof(dbeiExisting); dbeiExisting.cbBlob = CallService( MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hExistingDbEvent, (LPARAM)0 ); blob = malloc( dbeiExisting.cbBlob ); dbeiExisting.pBlob = blob; CallService( MS_DB_EVENT_GET, (WPARAM)hExistingDbEvent, (LPARAM)&dbeiExisting ); if( dbei.timestamp < dbeiExisting.timestamp ) { free( blob ); return INVALID_HANDLE_VALUE; } // Compare event with import candidate if( ( dbei.timestamp == dbeiExisting.timestamp ) && ( dbei.eventType == dbeiExisting.eventType ) && ( dbei.cbBlob == dbeiExisting.cbBlob ) ) { if( !strcmp( dbei.pBlob, dbeiExisting.pBlob ) ) { free( blob ); return hExistingDbEvent; } } free( blob ); // Get next event in chain hExistingDbEvent = (HANDLE)CallService( MS_DB_EVENT_FINDNEXT, (WPARAM)hExistingDbEvent, 0 ); } return INVALID_HANDLE_VALUE; } HANDLE AddNumericContact( char* pszProtoName, char* pszUniqueSetting, DWORD dwID, char* pzsNick ) { HANDLE hContact = INVALID_HANDLE_VALUE; 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 ); return INVALID_HANDLE_VALUE; } DBWriteContactSettingDword( hContact, pszProtoName, pszUniqueSetting, dwID ); if( pzsNick && pzsNick[0] ) DBWriteContactSettingString( hContact, "CList", "MyHandle", pzsNick ); return hContact; } HANDLE AddContact( char* pszProtoName, char* pszUniqueSetting, char* pszID, char* pzsNick ) { HANDLE hContact = INVALID_HANDLE_VALUE; 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 ); return INVALID_HANDLE_VALUE; } DBWriteContactSettingString( hContact, pszProtoName, pszUniqueSetting, pszID ); if( pzsNick && pzsNick[0] ) DBWriteContactSettingString( hContact, "CList", "MyHandle", pzsNick ); return hContact; } // szIn, pointer to source string // szOut, pointer to destination buffer // cchOut, size of destination buffer void Utf8ToAnsi( const char *szIn, char *szOut, int cchOut ) { if( GetVersion( ) != 4 || !( GetVersion( ) & 0x80000000 ) ) { WCHAR *wszTemp; int inlen; inlen = (int)strlen(szIn); wszTemp = (WCHAR *)malloc( sizeof(WCHAR) * (inlen + 1) ); MultiByteToWideChar( CP_UTF8, 0, szIn, -1, wszTemp, inlen + 1 ); WideCharToMultiByte( CP_ACP, 0, wszTemp, -1, szOut, cchOut, NULL, NULL ); free(wszTemp); } else { for( ; *szIn && cchOut > 1; szIn++ ) { if( *szIn >= 0 ) { *szOut++ = *szIn; cchOut--; } else { unsigned short wideChar; if( (unsigned char)*szIn >= 0xe0 ) { wideChar = ((szIn[0]&0x0f) << 12) | ((szIn[1]&0x3f) << 6) | (szIn[2]&0x3f); szIn += 2; } else { wideChar = ( (szIn[0]&0x1f) << 6 ) | ( szIn[1]&0x3f ); szIn++; } if( wideChar >= 0x100 ) *szOut++ = '?'; else *szOut++ = (char)wideChar; cchOut--; } } *szOut = '\0'; } } //***************************************** // END CODE FROM THE IMPORT.DLL PLUGIN! //***************************************** BOOL importSingleHistory( char *logpath, HANDLE *hContact, char *prot, HWND *dlg, float overal ) { int i = 0, lineNr, lineTotal = 0, lastflag = 0, imp = 0; char *time; char *message; DBEVENTINFO dbev; HANDLE dup; FILE *msg; char other[256]; time_t startts, prev = 0; struct tm starttime; int hasTime = -1, timeType = 0; int nameoffset[2][2] = { { 0, 8 }, { 0, 11 } }; BOOL doConversion = FALSE; MSG pm; msg = fopen( logpath, "r" ); lineTotal = 0; startts = 0; if( msg ) { while( !feof( msg ) ) { if( fgetc( msg ) == '\n' ) lineTotal++; } fseek( msg, 0, SEEK_SET ); lineNr = 0; imp = FALSE; } lineTotal = max( 1, lineTotal ); while( msg && readLine( msg ) ) { if( aborting ) return FALSE; lineNr++; ZeroMemory( &dbev, sizeof( dbev ) ); dbev.cbSize = sizeof(dbev); dbev.eventType = EVENTTYPE_MESSAGE; dbev.szModule = prot; if( !( lineNr % 10 ) ) { SendMessage( *dlg, DLG_UPDATE, 100 * lineNr / lineTotal, (LPARAM)overal ); wsprintf( status, "%s: %s %d/~%d", logpath, Translate( "line" ), lineNr, lineTotal ); } if( !strlen( line ) ) { } // Inefficient but quite save. else if( strstr( line, SESS_START1 ) || strstr( line, SESS_START2 ) || strstr( line, SESS_START3 ) || strstr( line, SESS_START4 ) || strstr( line, SESS_START5 ) ) { if( !strrchr( line, ')' ) ) continue; time = strrchr( line, ')' ) + 7; starttime = string2Tm( time ); startts = mktime( &starttime ); hasTime = -1; strncpy( other, strchr( line, ':' ) + 1, 255 ); if( strrchr( other, ')' ) ) *strrchr( other, ')' ) = '\0'; strcpy( lastNick, other ); } else if( strstr( line, SESS_STOP ) ) { } else if( startts ) { //FILE *f; if( hasTime == -1 ) { hasTime = 0; if( line[0] == '[' && strncmp( line, other, strlen(other) ) ) { int timelen = ( (int)strchr( line, ']' ) - (int)line ); if( timelen == 9 ) { hasTime = 1; timeType = 1; } else if( timelen == 6 ) { hasTime = 1; timeType = 0; } } } /*f = fopen( "test.log", "w" ); fprintf( f, "%s\n%s", &line[nameoffset[timeType][hasTime]], other ); fclose( f );*/ if( hasTime && line[0] != '[' ) { if( !importMsg ) continue; message = line; dbev.flags = lastflag; } else if( !strncmp( &line[nameoffset[timeType][hasTime]], other, strlen(other) ) ) { if( !importMsg ) continue; dbev.flags = DBEF_READ; message = line + nameoffset[timeType][hasTime] + strlen( other ) + 2; } else if( !strncmp( &line[nameoffset[timeType][hasTime]], "*** ", 4 ) ) { if( !importStat ) continue; dbev.flags = DBEF_READ; message = line + nameoffset[timeType][hasTime]; } else { if( !importMsg ) continue; message = strchr( line + nameoffset[timeType][hasTime], ':' ) + 2; if( (int)message == 2 ) message = line + nameoffset[timeType][hasTime] + 1; dbev.flags = DBEF_SENT | DBEF_READ; } if( hasTime && line[0] == '[' && line[3] == ':') { int hr, min, sec; if( timeType == 1 ) { sscanf( line, "[%d:%d:%d", &hr, &min, &sec ); starttime.tm_sec = sec; } else { sscanf( line, "[%d:%d", &hr, &min ); starttime.tm_sec = 0; } starttime.tm_hour = hr; starttime.tm_min = min; startts = mktime( &starttime ); } //if( startts == prev ) // startts += 4; doConversion = FALSE; if( utf8AutoDetect ) { //Whatever :) if( strstr( message, "ä" ) || strstr( message, "ö" ) || strstr( message, "ü" ) || strstr( message, "Ä" ) || strstr( message, "Ö" ) || strstr( message, "Ü" ) || strstr( message, "ß" ) || strstr( message, "é" ) || strstr( message, "à" ) || strstr( message, "è" ) || strstr( message, "É" ) || strstr( message, "À" ) || strstr( message, "È" ) || strstr( message, "ç" ) ) doConversion = TRUE; } else if( utf8DoAlways ) doConversion = TRUE; if( doConversion ) Utf8ToAnsi( message, message, (int)strlen(message) ); imp = TRUE; lastflag = dbev.flags; dbev.timestamp = (DWORD)startts; dbev.cbBlob = (DWORD)strlen( message ) + 1; dbev.pBlob = (PBYTE)malloc( dbev.cbBlob ); CopyMemory( dbev.pBlob, message, dbev.cbBlob ); dbev.pBlob[dbev.cbBlob - 1] = 0; if( ( dup = IsDuplicateEvent( *hContact, dbev ) ) == INVALID_HANDLE_VALUE ) CallService( MS_DB_EVENT_ADD, (WPARAM)*hContact, (LPARAM)&dbev ); else if( repDup ) { CallService( MS_DB_EVENT_DELETE, (WPARAM)*hContact, (LPARAM)dup ); CallService( MS_DB_EVENT_ADD, (WPARAM)*hContact, (LPARAM)&dbev ); } else wsprintf( status, "Skipping dublicate entries..." ); prev = startts; free( dbev.pBlob ); } if( PeekMessage( &pm, NULL, 0, 0, PM_REMOVE ) ) { TranslateMessage( &pm ); DispatchMessage( &pm ); } } if( msg ) fclose( msg ); return imp; } struct import { char prot[8]; char id[8]; int num; }; int numFiles( char *path ) { struct _finddata_t fl; long curFl; int num = 0; if( ( curFl = (long)_findfirst( path, &fl ) ) == -1L ) return num; while( _findnext( curFl, &fl ) == 0 ) { num++; } _findclose( curFl ); return num; } struct import importList[6] = { { "ICQ", "UIN", 1 }, { "MSN", "e-mail", 0 }, { "AIM", "SN", 0 }, { "YAHOO", "yahoo_id", 0 }, { "IRC", "Nick", 0 }, { "", "", 0 } }; static int ImportMessages( ) { int i = 0, numImp = 0, contTotal = 0, contNr = 0, o; HANDLE hContact; char msgpath[128]; char id[64]; HWND dlg; MSG pm; struct _finddata_t fl; long curFl; int len, first = 1; aborting = 0; finished = 0; dlg = CreateDialog( hInst, MAKEINTRESOURCE(IDD_TRILLIAN), NULL, (DLGPROC)ProgressDialogProc ); //contTotal = (int)CallService( MS_DB_CONTACT_GETCOUNT, 0, 0 ); if( speedMode ) CallService( MS_DB_SETSAFETYMODE, (WPARAM)FALSE, 0 ); while( !aborting && strlen( importList[i].prot ) ) { if( !importProt[i] ) { i++; continue; } for( o = 0; o < 2; o++ ) { first = 1; contNr = -1; sprintf( msgpath, "%s\\%s%s\\*.log", file, importList[i].prot, o == 0 ? "" : "\\Query" ); contTotal = numFiles( msgpath ); curFl = (long)_findfirst( msgpath, &fl ); //if( ( curFl = (long)_findfirst( msgpath, &fl ) ) == -1L ) // MessageBox( dlg, Translate( "No logs found for this protocol." ), importList[i].prot, 0 ); while( !aborting && ( ( first && curFl != -1 ) || ( _findnext( curFl, &fl ) == 0 ) ) ) { first = 0; contNr++; if( !strncmp( fl.name, importList[i].prot, strlen( importList[i].prot ) ) ) continue; if( !strcmp( importList[i].prot, "IRC" ) ) { if( strchr( fl.name, '#' ) ) { if( !importCha ) continue; } else if( !importNic ) continue; } len = (long)strrchr( fl.name, '.' ) - (long)fl.name; strncpy( id, fl.name, len ); id[len] = '\0'; getNick = FALSE; hContact = GetContactByID( importList[i].prot, importList[i].id, id ); sprintf( msgpath, "%s\\%s%s\\%s.log", file, importList[i].prot, o == 0 ? "" : "\\Query", id ); if( ( hContact == INVALID_HANDLE_VALUE ) && importAdd ) { if( importList[i].num ) hContact = AddNumericContact( importList[i].prot, importList[i].id, atol(id), 0 ); else hContact = AddContact( importList[i].prot, importList[i].id, id, 0 ); getNick = TRUE; } else if( !importEx ) continue; if( delBefore ) DeleteContactEventsBefore( hContact, delBeforeTS ); if( ( hContact != INVALID_HANDLE_VALUE ) && importSingleHistory( msgpath, &hContact, importList[i].prot, &dlg, 100.0f * contNr / contTotal ) ) numImp++; if( getNick ) DBWriteContactSettingString( hContact, "CList", "MyHandle", lastNick ); } _findclose( curFl ); } i++; } if( speedMode ) CallService( MS_DB_SETSAFETYMODE, (WPARAM)TRUE, 0 ); finished = 1; wsprintf( status, Translate( "Done importing %d contact history files!" ), numImp ); if( numImp == 0 ) strcat( status, Translate( "\nCheck your UIN and path settings. Path musst end with \\logs" ) ); SendMessage( dlg, DLG_UPDATE, 100, 100 ); while( PeekMessage( &pm, NULL, 0, 0, PM_REMOVE ) ) { TranslateMessage( &pm ); DispatchMessage( &pm ); } return 0; } static int ImportCommand( WPARAM wParam,LPARAM lParam ) { HWND dlg; strcpy( file, "C:\\Program Files\\Trillian\\users\\default\\logs" ); dlg = CreateDialog( hInst, MAKEINTRESOURCE(IDD_STARTUP), NULL, (DLGPROC)StartupDialogProc ); return 0; } __declspec(dllexport) PLUGININFO* MirandaPluginInfo( DWORD mirandaVersion ) { if (mirandaVersion < PLUGIN_MAKE_VERSION(0, 1, 1, 0)) return NULL; return &pluginInfo; } int __declspec(dllexport) Load( PLUGINLINK *link ) { CLISTMENUITEM mi; pluginLink = link; CreateServiceFunction( IMPORT_SERVICE, ImportCommand ); ZeroMemory( &mi, sizeof( mi ) ); mi.cbSize = sizeof( mi ); mi.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_IMPORT)); mi.pszName = Translate( Translate( "Import Trillian history/contacts..." ) ); mi.position = 500050000; mi.pszService = IMPORT_SERVICE; CallService( MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM)&mi ); return 0; } int __declspec(dllexport) Unload( void ) { return 0; }