diff options
Diffstat (limited to 'src/modules/srfile')
-rw-r--r-- | src/modules/srfile/file.cpp | 392 | ||||
-rw-r--r-- | src/modules/srfile/file.h | 115 | ||||
-rw-r--r-- | src/modules/srfile/fileexistsdlg.cpp | 354 | ||||
-rw-r--r-- | src/modules/srfile/fileopts.cpp | 247 | ||||
-rw-r--r-- | src/modules/srfile/filerecvdlg.cpp | 446 | ||||
-rw-r--r-- | src/modules/srfile/filesenddlg.cpp | 363 | ||||
-rw-r--r-- | src/modules/srfile/filexferdlg.cpp | 799 | ||||
-rw-r--r-- | src/modules/srfile/ftmanager.cpp | 592 |
8 files changed, 3308 insertions, 0 deletions
diff --git a/src/modules/srfile/file.cpp b/src/modules/srfile/file.cpp new file mode 100644 index 0000000000..85eb99a7bc --- /dev/null +++ b/src/modules/srfile/file.cpp @@ -0,0 +1,392 @@ +/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2009 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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 "commonheaders.h"
+#include "file.h"
+
+TCHAR* PFTS_StringToTchar( int flags, const PROTOCHAR* s );
+int PFTS_CompareWithTchar( PROTOFILETRANSFERSTATUS* ft, const PROTOCHAR* s, TCHAR* r );
+
+static HANDLE hSRFileMenuItem;
+
+static INT_PTR SendFileCommand(WPARAM wParam, LPARAM)
+{
+ struct FileSendData fsd;
+ fsd.hContact=(HANDLE)wParam;
+ fsd.ppFiles=NULL;
+ CreateDialogParam(hMirandaInst,MAKEINTRESOURCE(IDD_FILESEND),NULL,DlgProcSendFile,(LPARAM)&fsd);
+ return 0;
+}
+
+static INT_PTR SendSpecificFiles(WPARAM wParam,LPARAM lParam)
+{
+ FileSendData fsd;
+ fsd.hContact=(HANDLE)wParam;
+ #if defined( _UNICODE )
+ char** ppFiles = ( char** )lParam;
+ int count = 0;
+ while ( ppFiles[count] != NULL )
+ count++;
+
+ fsd.ppFiles = (const TCHAR**)alloca(( count+1 ) * sizeof( void* ));
+ for ( int i=0; i < count; i++ )
+ fsd.ppFiles[i] = ( const TCHAR* )mir_a2t( ppFiles[i] );
+ fsd.ppFiles[ count ] = NULL;
+ #else
+ fsd.ppFiles=(const char**)lParam;
+ #endif
+ CreateDialogParam(hMirandaInst,MAKEINTRESOURCE(IDD_FILESEND),NULL,DlgProcSendFile,(LPARAM)&fsd);
+ #if defined( _UNICODE )
+ for ( int j=0; j < count; j++ )
+ mir_free(( void* )fsd.ppFiles[j] );
+ #endif
+ return 0;
+}
+
+static INT_PTR SendSpecificFilesT(WPARAM wParam,LPARAM lParam)
+{
+ FileSendData fsd;
+ fsd.hContact=(HANDLE)wParam;
+ fsd.ppFiles=(const TCHAR**)lParam;
+ CreateDialogParam(hMirandaInst,MAKEINTRESOURCE(IDD_FILESEND),NULL,DlgProcSendFile,(LPARAM)&fsd);
+ return 0;
+}
+
+static INT_PTR GetReceivedFilesFolder(WPARAM wParam,LPARAM lParam)
+{
+ TCHAR buf[MAX_PATH];
+ GetContactReceivedFilesDir((HANDLE)wParam,buf,MAX_PATH,TRUE);
+ char* dir = mir_t2a(buf);
+ lstrcpynA((char*)lParam,dir,MAX_PATH);
+ mir_free(dir);
+ return 0;
+}
+
+static INT_PTR RecvFileCommand(WPARAM, LPARAM lParam)
+{
+ CreateDialogParam(hMirandaInst,MAKEINTRESOURCE(IDD_FILERECV),NULL,DlgProcRecvFile,lParam);
+ return 0;
+}
+
+void PushFileEvent( HANDLE hContact, HANDLE hdbe, LPARAM lParam )
+{
+ CLISTEVENT cle={0};
+ cle.cbSize = sizeof(cle);
+ cle.hContact = hContact;
+ cle.hDbEvent = hdbe;
+ cle.lParam = lParam;
+ if ( DBGetContactSettingByte(NULL,"SRFile","AutoAccept",0) && !DBGetContactSettingByte(hContact,"CList","NotOnList",0)) {
+ CreateDialogParam(hMirandaInst,MAKEINTRESOURCE(IDD_FILERECV),NULL,DlgProcRecvFile,(LPARAM)&cle);
+ }
+ else {
+ SkinPlaySound("RecvFile");
+
+ TCHAR szTooltip[256];
+ mir_sntprintf(szTooltip,SIZEOF(szTooltip),TranslateT("File from %s"), cli.pfnGetContactDisplayName( hContact, 0 ));
+ cle.ptszTooltip = szTooltip;
+
+ cle.flags |= CLEF_TCHAR;
+ cle.hIcon = LoadSkinIcon( SKINICON_EVENT_FILE );
+ cle.pszService = "SRFile/RecvFile";
+ CallService(MS_CLIST_ADDEVENT,0,(LPARAM)&cle);
+} }
+
+static int FileEventAdded(WPARAM wParam,LPARAM lParam)
+{
+ DWORD dwSignature;
+
+ DBEVENTINFO dbei={0};
+ dbei.cbSize = sizeof(dbei);
+ dbei.cbBlob = sizeof( DWORD );
+ dbei.pBlob = ( PBYTE )&dwSignature;
+ CallService( MS_DB_EVENT_GET, lParam, ( LPARAM )&dbei );
+ if ( dbei.flags&(DBEF_SENT|DBEF_READ) || dbei.eventType != EVENTTYPE_FILE || dwSignature == 0 )
+ return 0;
+
+ PushFileEvent(( HANDLE )wParam, ( HANDLE )lParam, 0 );
+ return 0;
+}
+
+int SRFile_GetRegValue(HKEY hKeyBase,const TCHAR *szSubKey,const TCHAR *szValue,TCHAR *szOutput,int cbOutput)
+{
+ HKEY hKey;
+ DWORD cbOut=cbOutput;
+
+ if ( RegOpenKeyEx( hKeyBase,szSubKey,0,KEY_QUERY_VALUE,&hKey ) != ERROR_SUCCESS)
+ return 0;
+
+ if ( RegQueryValueEx( hKey,szValue,NULL,NULL,(PBYTE)szOutput, &cbOut ) != ERROR_SUCCESS ) {
+ RegCloseKey(hKey);
+ return 0;
+ }
+
+ RegCloseKey(hKey);
+ return 1;
+}
+
+void GetSensiblyFormattedSize(__int64 size,TCHAR *szOut,int cchOut,int unitsOverride,int appendUnits,int *unitsUsed)
+{
+ if(!unitsOverride) {
+ if(size<1000) unitsOverride=UNITS_BYTES;
+ else if(size<100*1024) unitsOverride=UNITS_KBPOINT1;
+ else if(size<1024*1024) unitsOverride=UNITS_KBPOINT0;
+ else if(size<1024*1024*1024) unitsOverride=UNITS_MBPOINT2;
+ else unitsOverride=UNITS_GBPOINT3;
+ }
+ if(unitsUsed) *unitsUsed=unitsOverride;
+ switch(unitsOverride) {
+ case UNITS_BYTES: mir_sntprintf(szOut,cchOut,_T("%u%s%s"),(int)size,appendUnits?_T(" "):_T(""),appendUnits?TranslateT("bytes"):_T("")); break;
+ case UNITS_KBPOINT1: mir_sntprintf(szOut,cchOut,_T("%.1lf%s"),size/1024.0,appendUnits?_T(" KB"):_T("")); break;
+ case UNITS_KBPOINT0: mir_sntprintf(szOut,cchOut,_T("%u%s"),(int)(size/1024),appendUnits?_T(" KB"):_T("")); break;
+ case UNITS_GBPOINT3: mir_sntprintf(szOut,cchOut,_T("%.3f%s"),(size >> 20)/1024.0,appendUnits?_T(" GB"):_T("")); break;
+ default: mir_sntprintf(szOut,cchOut,_T("%.2lf%s"),size/1048576.0,appendUnits?_T(" MB"):_T("")); break;
+ }
+}
+
+// Tripple redirection sucks but is needed to nullify the array pointer
+void FreeFilesMatrix(TCHAR ***files)
+{
+ if (*files == NULL)
+ return;
+
+ // Free each filename in the pointer array
+ TCHAR **pFile = *files;
+ while (*pFile != NULL)
+ {
+ mir_free(*pFile);
+ *pFile = NULL;
+ pFile++;
+ }
+
+ // Free the array itself
+ mir_free(*files);
+ *files = NULL;
+}
+
+void FreeProtoFileTransferStatus(PROTOFILETRANSFERSTATUS *fts)
+{
+ mir_free(fts->tszCurrentFile);
+ if(fts->ptszFiles) {
+ for( int i=0;i<fts->totalFiles;i++) mir_free(fts->ptszFiles[i]);
+ mir_free(fts->ptszFiles);
+ }
+ mir_free(fts->tszWorkingDir);
+}
+
+void CopyProtoFileTransferStatus(PROTOFILETRANSFERSTATUS *dest, PROTOFILETRANSFERSTATUS *src)
+{
+ *dest=*src;
+ if ( src->tszCurrentFile ) dest->tszCurrentFile = PFTS_StringToTchar(src->flags, src->tszCurrentFile);
+ if ( src->ptszFiles ) {
+ dest->ptszFiles = (TCHAR**)mir_alloc(sizeof(TCHAR*)*src->totalFiles);
+ for( int i=0; i < src->totalFiles; i++ )
+ dest->ptszFiles[i] = PFTS_StringToTchar(src->flags, src->ptszFiles[i] );
+ }
+ if ( src->tszWorkingDir ) dest->tszWorkingDir = PFTS_StringToTchar(src->flags, src->tszWorkingDir );
+ dest->flags &= ~PFTS_UTF;
+ dest->flags |= PFTS_TCHAR;
+}
+
+void UpdateProtoFileTransferStatus(PROTOFILETRANSFERSTATUS *dest, PROTOFILETRANSFERSTATUS *src)
+{
+ if (src->cbSize == sizeof(PROTOFILETRANSFERSTATUS_V1))
+ {
+ PROTOFILETRANSFERSTATUS_V1 *src1 = (PROTOFILETRANSFERSTATUS_V1*)src;
+ src = (PROTOFILETRANSFERSTATUS*)alloca(sizeof(PROTOFILETRANSFERSTATUS));
+
+ src->cbSize = sizeof(PROTOFILETRANSFERSTATUS);
+ src->hContact = src1->hContact;
+ src->flags = src1->sending ? PFTS_SENDING : 0;
+ src->pszFiles = src1->files;
+ src->totalFiles = src1->totalFiles;
+ src->currentFileNumber = src1->currentFileNumber;
+ src->totalBytes = src1->totalBytes;
+ src->totalProgress = src1->totalProgress;
+ src->szWorkingDir = src1->workingDir;
+ src->szCurrentFile = src1->currentFile;
+ src->currentFileSize = src1->currentFileSize;
+ src->currentFileProgress = src1->currentFileProgress;
+ src->currentFileTime = src1->currentFileTime;
+ }
+
+ dest->hContact = src->hContact;
+ dest->flags = src->flags;
+ if ( dest->totalFiles != src->totalFiles ) {
+ for( int i=0;i<dest->totalFiles;i++) mir_free(dest->ptszFiles[i]);
+ mir_free(dest->ptszFiles);
+ dest->ptszFiles = NULL;
+ dest->totalFiles = src->totalFiles;
+ }
+ if ( src->ptszFiles ) {
+ if ( !dest->ptszFiles )
+ dest->ptszFiles = ( TCHAR** )mir_calloc( sizeof(TCHAR*)*src->totalFiles);
+ for ( int i=0; i < src->totalFiles; i++ )
+ if ( !dest->ptszFiles[i] || !src->ptszFiles[i] || PFTS_CompareWithTchar( src, src->ptszFiles[i], dest->ptszFiles[i] )) {
+ mir_free( dest->ptszFiles[i] );
+ if ( src->ptszFiles[i] )
+ dest->ptszFiles[i] = PFTS_StringToTchar( src->flags, src->ptszFiles[i] );
+ else
+ dest->ptszFiles[i] = NULL;
+ }
+ }
+ else if (dest->ptszFiles) {
+ for( int i=0; i < dest->totalFiles; i++ )
+ mir_free(dest->ptszFiles[i]);
+ mir_free( dest->ptszFiles );
+ dest->ptszFiles = NULL;
+ }
+
+ dest->currentFileNumber = src->currentFileNumber;
+ dest->totalBytes = src->totalBytes;
+ dest->totalProgress = src->totalProgress;
+ if (src->tszWorkingDir && (!dest->tszWorkingDir || PFTS_CompareWithTchar( src, src->tszWorkingDir, dest->tszWorkingDir))) {
+ mir_free( dest->tszWorkingDir );
+ if ( src->tszWorkingDir )
+ dest->tszWorkingDir = PFTS_StringToTchar( src->flags, src->tszWorkingDir );
+ else
+ dest->tszWorkingDir = NULL;
+ }
+
+ if ( !dest->tszCurrentFile || !src->tszCurrentFile || PFTS_CompareWithTchar( src, src->tszCurrentFile, dest->tszCurrentFile )) {
+ mir_free( dest->tszCurrentFile );
+ if ( src->tszCurrentFile )
+ dest->tszCurrentFile = PFTS_StringToTchar( src->flags, src->tszCurrentFile );
+ else
+ dest->tszCurrentFile = NULL;
+ }
+ dest->currentFileSize = src->currentFileSize;
+ dest->currentFileProgress = src->currentFileProgress;
+ dest->currentFileTime = src->currentFileTime;
+ dest->flags &= ~PFTS_UTF;
+ dest->flags |= PFTS_TCHAR;
+}
+
+static void RemoveUnreadFileEvents(void)
+{
+ DBEVENTINFO dbei={0};
+ HANDLE hDbEvent,hContact;
+
+ dbei.cbSize=sizeof(dbei);
+ hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0);
+ while(hContact) {
+ hDbEvent=(HANDLE)CallService(MS_DB_EVENT_FINDFIRSTUNREAD,(WPARAM)hContact,0);
+ while(hDbEvent) {
+ dbei.cbBlob=0;
+ CallService(MS_DB_EVENT_GET,(WPARAM)hDbEvent,(LPARAM)&dbei);
+ if(!(dbei.flags&(DBEF_SENT|DBEF_READ)) && dbei.eventType==EVENTTYPE_FILE)
+ CallService(MS_DB_EVENT_MARKREAD,(WPARAM)hContact,(LPARAM)hDbEvent);
+ hDbEvent=(HANDLE)CallService(MS_DB_EVENT_FINDNEXT,(WPARAM)hDbEvent,0);
+ }
+ hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0);
+ }
+}
+
+static int SRFilePreBuildMenu(WPARAM wParam, LPARAM)
+{
+ CLISTMENUITEM mi = { 0 };
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_FLAGS | CMIF_HIDDEN;
+
+ char *szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0);
+ if (szProto != NULL) {
+ if ( CallProtoService(szProto, PS_GETCAPS,PFLAGNUM_1, 0 ) & PF1_FILESEND) {
+ if ( CallProtoService(szProto, PS_GETCAPS,PFLAGNUM_4, 0 ) & PF4_OFFLINEFILES )
+ mi.flags = CMIM_FLAGS;
+ else if ( DBGetContactSettingWord(( HANDLE )wParam, szProto, "Status", ID_STATUS_OFFLINE ) != ID_STATUS_OFFLINE )
+ mi.flags = CMIM_FLAGS;
+ } }
+
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hSRFileMenuItem, (LPARAM)&mi);
+ return 0;
+}
+
+static int SRFileModulesLoaded(WPARAM, LPARAM)
+{
+ CLISTMENUITEM mi = { 0 };
+ mi.cbSize = sizeof(mi);
+ mi.position = -2000020000;
+ mi.icolibItem = GetSkinIconHandle( SKINICON_EVENT_FILE );
+ mi.pszName = LPGEN("&File");
+ mi.pszService = MS_FILE_SENDFILE;
+ mi.flags = CMIF_ICONFROMICOLIB;
+ hSRFileMenuItem = ( HANDLE )CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi);
+
+ RemoveUnreadFileEvents();
+ return 0;
+}
+
+INT_PTR FtMgrShowCommand(WPARAM, LPARAM)
+{
+ FtMgr_Show(true, true);
+ return 0;
+}
+
+INT_PTR openContRecDir(WPARAM wparam, LPARAM)
+{
+ TCHAR szContRecDir[MAX_PATH];
+ HANDLE hContact = (HANDLE)wparam;
+ GetContactReceivedFilesDir(hContact, szContRecDir, SIZEOF(szContRecDir),TRUE);
+ ShellExecute(0, _T("open"), szContRecDir, 0, 0, SW_SHOW);
+ return 0;
+}
+
+INT_PTR openRecDir(WPARAM, LPARAM)
+{
+ TCHAR szContRecDir[MAX_PATH];
+ GetReceivedFilesDir(szContRecDir, SIZEOF(szContRecDir));
+ ShellExecute(0, _T("open"), szContRecDir, 0, 0, SW_SHOW);
+ return 0;
+}
+
+int LoadSendRecvFileModule(void)
+{
+ CreateServiceFunction("FtMgr/Show", FtMgrShowCommand);
+
+ CLISTMENUITEM mi = { 0 };
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIF_ICONFROMICOLIB;
+ mi.icolibItem = GetSkinIconHandle( SKINICON_EVENT_FILE );
+ mi.position = 1900000000;
+ mi.pszName = LPGEN("File &Transfers...");
+ mi.pszService = "FtMgr/Show"; //MS_PROTO_SHOWFTMGR;
+ CallService( MS_CLIST_ADDMAINMENUITEM, 0, ( LPARAM )&mi );
+
+ HookEvent(ME_SYSTEM_MODULESLOADED,SRFileModulesLoaded);
+ HookEvent(ME_DB_EVENT_ADDED,FileEventAdded);
+ HookEvent(ME_OPT_INITIALISE,FileOptInitialise);
+ HookEvent(ME_CLIST_PREBUILDCONTACTMENU, SRFilePreBuildMenu);
+
+ CreateServiceFunction(MS_FILE_SENDFILE,SendFileCommand);
+ CreateServiceFunction(MS_FILE_SENDSPECIFICFILES,SendSpecificFiles);
+ CreateServiceFunction(MS_FILE_SENDSPECIFICFILEST,SendSpecificFilesT);
+ CreateServiceFunction(MS_FILE_GETRECEIVEDFILESFOLDER,GetReceivedFilesFolder);
+ CreateServiceFunction("SRFile/RecvFile",RecvFileCommand);
+
+ CreateServiceFunction("SRFile/OpenContRecDir",openContRecDir);
+ CreateServiceFunction("SRFile/OpenRecDir",openRecDir);
+
+ SkinAddNewSoundEx("RecvFile", "File", "Incoming");
+ SkinAddNewSoundEx("FileDone", "File", "Complete");
+ SkinAddNewSoundEx("FileFailed", "File", "Error");
+ SkinAddNewSoundEx("FileDenied", "File", "Denied");
+ return 0;
+}
diff --git a/src/modules/srfile/file.h b/src/modules/srfile/file.h new file mode 100644 index 0000000000..8ee9048eb9 --- /dev/null +++ b/src/modules/srfile/file.h @@ -0,0 +1,115 @@ +/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2009 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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.
+*/
+
+#define VIRUSSCAN_DISABLE 0
+#define VIRUSSCAN_AFTERDL 1
+#define VIRUSSCAN_DURINGDL 2
+
+#define FILERESUME_ASK 0
+//1,2,3,4: resume, overwrite, rename, skip: from proto library
+#define FILERESUMEF_ALL 0x80
+#define FILERESUME_RESUMEALL (FILERESUME_RESUME|FILERESUMEF_ALL)
+#define FILERESUME_OVERWRITEALL (FILERESUME_OVERWRITE|FILERESUMEF_ALL)
+#define FILERESUME_RENAMEALL (FILERESUME_RENAME|FILERESUMEF_ALL)
+#define FILERESUME_CANCEL 0xFFFFFFFF
+
+#define M_FILEEXISTSDLGREPLY (WM_USER+200)
+#define M_PRESHUTDOWN (WM_USER+201)
+
+struct FileSendData {
+ HANDLE hContact;
+ const TCHAR **ppFiles;
+};
+
+#define BYTESRECVEDHISTORYCOUNT 10 //the number of bytes recved is sampled once a second and the last 10 are used to get the transfer speed
+struct FileDlgData {
+ HWND hwndTransfer;
+ HANDLE fs;
+ HANDLE hContact;
+ HANDLE hDbEvent;
+ HANDLE hNotifyEvent;
+ TCHAR **files;
+ int send;
+ int closeIfFileChooseCancelled;
+ int resumeBehaviour;
+ int bytesRecvedHistory[BYTESRECVEDHISTORYCOUNT];
+ int bytesRecvedHistorySize;
+ int waitingForAcceptance;
+ PROTOFILETRANSFERSTATUS transferStatus;
+ int *fileVirusScanned;
+ HANDLE hPreshutdownEvent;
+ DWORD dwTicks;
+
+ TCHAR szSavePath[MAX_PATH];
+ TCHAR szMsg[450], szFilenames[1024];
+ HICON hIcon, hIconFolder;
+};
+
+//file.c
+#define UNITS_BYTES 1 // 0<=size<1000: "%d bytes"
+#define UNITS_KBPOINT1 2 // 1000<=size<100*1024: "%.1f KB"
+#define UNITS_KBPOINT0 3 // 100*1024<=size<1024*1024: "%d KB"
+#define UNITS_MBPOINT2 4 // 1024*1024<=size: "%.2f MB"
+#define UNITS_GBPOINT3 5 // 1024*1024*1024<=size: "%.3f GB"
+
+void GetSensiblyFormattedSize(__int64 size,TCHAR *szOut,int cchOut,int unitsOverride,int appendUnits,int *unitsUsed);
+void FreeFilesMatrix(TCHAR ***files); //loving that triple indirection
+void FreeProtoFileTransferStatus(PROTOFILETRANSFERSTATUS *fts);
+void CopyProtoFileTransferStatus(PROTOFILETRANSFERSTATUS *dest,PROTOFILETRANSFERSTATUS *src);
+void UpdateProtoFileTransferStatus(PROTOFILETRANSFERSTATUS *dest,PROTOFILETRANSFERSTATUS *src);
+int SRFile_GetRegValue(HKEY hKeyBase,const TCHAR *szSubKey,const TCHAR *szValue,TCHAR *szOutput,int cbOutput);
+//filesenddlg.c
+INT_PTR CALLBACK DlgProcSendFile(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+//filerecv.c
+INT_PTR CALLBACK DlgProcRecvFile(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+void RemoveInvalidFilenameChars(TCHAR *tszString);
+void RemoveInvalidPathChars(TCHAR *tszString);
+void GetContactReceivedFilesDir(HANDLE hContact,TCHAR *szDir,int cchDir,BOOL substVars);
+void GetReceivedFilesDir(TCHAR *szDir,int cchDir);
+int BrowseForFolder(HWND hwnd,TCHAR *szPath);
+//fileexistsdlg.c
+struct TDlgProcFileExistsParam
+{
+ HWND hwndParent;
+ PROTOFILETRANSFERSTATUS *fts;
+};
+INT_PTR CALLBACK DlgProcFileExists(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+//filexferdlg.c
+INT_PTR CALLBACK DlgProcFileTransfer(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+//fileopts.c
+int FileOptInitialise(WPARAM wParam,LPARAM lParam);
+//ftmanager.c
+#define WM_FT_ADD (WM_USER+701)
+#define WM_FT_RESIZE (WM_USER+702)
+#define WM_FT_REMOVE (WM_USER+703)
+#define WM_FT_SELECTPAGE (WM_USER+704)
+#define WM_FT_CLEANUP (WM_USER+705)
+#define WM_FT_COMPLETED (WM_USER+706)
+
+HWND FtMgr_Show(bool bForceActivate, bool bFromMenu);
+void FtMgr_Destroy();
+HWND FtMgr_AddTransfer(struct FileDlgData *dat);
+
+void FreeFileDlgData( FileDlgData* dat );
+
+TCHAR *GetContactID(HANDLE hContact);
diff --git a/src/modules/srfile/fileexistsdlg.cpp b/src/modules/srfile/fileexistsdlg.cpp new file mode 100644 index 0000000000..d97d6d8da2 --- /dev/null +++ b/src/modules/srfile/fileexistsdlg.cpp @@ -0,0 +1,354 @@ +/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2009 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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 "commonheaders.h"
+#include <shlobj.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "file.h"
+
+static void SetControlToUnixTime(HWND hwndDlg, UINT idCtrl, time_t unixTime)
+{
+ LARGE_INTEGER liFiletime;
+ FILETIME filetime;
+ SYSTEMTIME st;
+ char szTime[64],szDate[64],szOutput[128];
+
+ liFiletime.QuadPart=(BIGI(11644473600)+(__int64)unixTime)*10000000;
+ filetime.dwHighDateTime=liFiletime.HighPart;
+ filetime.dwLowDateTime=liFiletime.LowPart;
+ FileTimeToSystemTime(&filetime,&st);
+ GetTimeFormatA(LOCALE_USER_DEFAULT,0,&st,NULL,szTime,SIZEOF(szTime));
+ GetDateFormatA(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&st,NULL,szDate,SIZEOF(szDate));
+ mir_snprintf(szOutput, SIZEOF(szOutput), "%s %s",szDate,szTime);
+ SetDlgItemTextA(hwndDlg,idCtrl,szOutput);
+}
+
+#define C_CONTEXTMENU 0
+#define C_PROPERTIES 1
+// not defined in VC++ 6.0 SE
+#ifndef CMF_EXTENDEDVERBS
+#define CMF_EXTENDEDVERBS 0x00000100
+#endif
+static void DoAnnoyingShellCommand(HWND hwnd,const TCHAR *szFilename,int cmd,POINT *ptCursor)
+{
+ IShellFolder *pDesktopFolder;
+ if(SHGetDesktopFolder(&pDesktopFolder)==NOERROR) {
+ ITEMIDLIST *pCurrentIdl;
+ #if defined( _UNICODE )
+ WCHAR* wszFilename = ( LPWSTR )szFilename;
+ #else
+ WCHAR wszFilename[MAX_PATH];
+ MultiByteToWideChar(CP_ACP,0,szFilename,-1,wszFilename,SIZEOF(wszFilename));
+ #endif
+ if(pDesktopFolder->ParseDisplayName(NULL,NULL,wszFilename,NULL,&pCurrentIdl,NULL)==NOERROR) {
+ if(pCurrentIdl->mkid.cb) {
+ ITEMIDLIST *pidl,*pidlNext,*pidlFilename;
+ IShellFolder *pFileFolder;
+
+ for(pidl=pCurrentIdl;;) {
+ pidlNext=(ITEMIDLIST*)((PBYTE)pidl+pidl->mkid.cb);
+ if(pidlNext->mkid.cb==0) {
+ pidlFilename = (ITEMIDLIST*)CoTaskMemAlloc(pidl->mkid.cb+sizeof(pidl->mkid.cb));
+ CopyMemory(pidlFilename,pidl,pidl->mkid.cb+sizeof(pidl->mkid.cb));
+ pidl->mkid.cb=0;
+ break;
+ }
+ pidl=pidlNext;
+ }
+ if(pDesktopFolder->BindToObject(pCurrentIdl,NULL,IID_IShellFolder,(void**)&pFileFolder)==NOERROR) {
+ IContextMenu *pContextMenu;
+ if(pFileFolder->GetUIObjectOf(NULL,1,(LPCITEMIDLIST*)&pidlFilename,IID_IContextMenu,NULL,(void**)&pContextMenu)==NOERROR) {
+ switch(cmd) {
+ case C_PROPERTIES:
+ { CMINVOKECOMMANDINFO ici={0};
+ ici.cbSize=sizeof(ici);
+ ici.hwnd=hwnd;
+ ici.lpVerb="properties";
+ ici.nShow=SW_SHOW;
+ pContextMenu->InvokeCommand(&ici);
+ break;
+ }
+ case C_CONTEXTMENU:
+ { HMENU hMenu;
+ hMenu=CreatePopupMenu();
+ if(SUCCEEDED(pContextMenu->QueryContextMenu(hMenu,0,1000,65535,(GetKeyState(VK_SHIFT)&0x8000?CMF_EXTENDEDVERBS:0)|CMF_NORMAL))) {
+ int cmd;
+ cmd=TrackPopupMenu(hMenu,TPM_RETURNCMD,ptCursor->x,ptCursor->y,0,hwnd,NULL);
+ if(cmd) {
+ CMINVOKECOMMANDINFO ici={0};
+ ici.cbSize=sizeof(ici);
+ ici.hwnd=hwnd;
+ ici.lpVerb=MAKEINTRESOURCEA(cmd-1000);
+ ici.nShow=SW_SHOW;
+ pContextMenu->InvokeCommand(&ici);
+ }
+ }
+ DestroyMenu(hMenu);
+ break;
+ }
+ }
+ pContextMenu->Release();
+ }
+ pFileFolder->Release();
+ }
+ CoTaskMemFree(pidlFilename);
+ }
+ CoTaskMemFree(pCurrentIdl);
+ }
+ pDesktopFolder->Release();
+ }
+}
+
+static WNDPROC pfnIconWindowProc;
+static LRESULT CALLBACK IconCtrlSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ PROTOFILETRANSFERSTATUS* pft = (PROTOFILETRANSFERSTATUS*)GetWindowLongPtr(GetParent(hwnd),GWLP_USERDATA);
+
+ switch(msg) {
+ case WM_LBUTTONDBLCLK:
+ ShellExecute(hwnd,NULL,pft->tszCurrentFile,NULL,NULL,SW_SHOW);
+ break;
+ case WM_RBUTTONUP:
+ { POINT pt;
+ pt.x=(short)LOWORD(lParam); pt.y=(short)HIWORD(lParam);
+ ClientToScreen( hwnd, &pt );
+ DoAnnoyingShellCommand( hwnd, pft->tszCurrentFile, C_CONTEXTMENU, &pt );
+ return 0;
+ }
+ }
+ return CallWindowProc(pfnIconWindowProc,hwnd,msg,wParam,lParam);
+}
+
+struct loadiconsstartinfo {
+ HWND hwndDlg;
+ TCHAR *szFilename;
+};
+void __cdecl LoadIconsAndTypesThread(void* param)
+{
+ loadiconsstartinfo *info = ( loadiconsstartinfo* )param;
+ SHFILEINFO fileInfo;
+
+ if ( SHGetFileInfo( info->szFilename, 0, &fileInfo, sizeof(fileInfo),SHGFI_TYPENAME|SHGFI_ICON|SHGFI_LARGEICON)) {
+ TCHAR *pszExtension,*pszFilename;
+ TCHAR szExtension[64];
+ TCHAR szIconFile[MAX_PATH];
+
+ pszFilename = _tcsrchr(info->szFilename,'\\');
+ if ( pszFilename == NULL )
+ pszFilename = info->szFilename;
+
+ pszExtension = _tcsrchr( pszFilename, '.' );
+ if ( pszExtension )
+ lstrcpyn( szExtension, pszExtension+1, SIZEOF( szExtension ));
+ else {
+ pszExtension = _T(".");
+ szExtension[0]='\0';
+ }
+ CharUpper(szExtension);
+ if ( fileInfo.szTypeName[0]=='\0' )
+ mir_sntprintf( fileInfo.szTypeName, SIZEOF(fileInfo.szTypeName), TranslateT("%s File"),szExtension);
+ SetDlgItemText(info->hwndDlg,IDC_EXISTINGTYPE,fileInfo.szTypeName);
+ SetDlgItemText(info->hwndDlg,IDC_NEWTYPE,fileInfo.szTypeName);
+ SendDlgItemMessage(info->hwndDlg,IDC_EXISTINGICON,STM_SETICON,(WPARAM)fileInfo.hIcon,0);
+ szIconFile[0]='\0';
+ if ( !lstrcmp( szExtension, _T("EXE"))) {
+ SRFile_GetRegValue(HKEY_LOCAL_MACHINE,_T("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Icons"),_T("2"),szIconFile,SIZEOF(szIconFile));
+ }
+ else {
+ TCHAR szTypeName[MAX_PATH];
+ if(SRFile_GetRegValue(HKEY_CLASSES_ROOT,pszExtension,NULL,szTypeName,SIZEOF(szTypeName))) {
+ lstrcat(szTypeName,_T("\\DefaultIcon"));
+ if(SRFile_GetRegValue(HKEY_CLASSES_ROOT,szTypeName,NULL,szIconFile,SIZEOF(szIconFile))) {
+ if ( _tcsstr( szIconFile, _T("%1")))
+ SRFile_GetRegValue(HKEY_LOCAL_MACHINE,_T("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Icons"),_T("0"),szIconFile,SIZEOF(szIconFile));
+ else szIconFile[0]='\0';
+ } } }
+
+ if ( szIconFile[0]) {
+ int iconIndex;
+ HICON hIcon;
+ TCHAR *pszComma = _tcsrchr(szIconFile,',');
+ if ( pszComma == NULL )
+ iconIndex=0;
+ else {
+ iconIndex = _ttoi(pszComma+1); *pszComma='\0';
+ }
+ hIcon = ExtractIcon( hMirandaInst, szIconFile, iconIndex );
+ if ( hIcon )
+ fileInfo.hIcon = hIcon;
+ }
+ SendDlgItemMessage(info->hwndDlg,IDC_NEWICON,STM_SETICON,(WPARAM)fileInfo.hIcon,0);
+ }
+ mir_free(info->szFilename);
+ mir_free(info);
+}
+
+INT_PTR CALLBACK DlgProcFileExists(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ PROTOFILETRANSFERSTATUS *fts;
+
+ fts=(PROTOFILETRANSFERSTATUS*)GetWindowLongPtr(hwndDlg,GWLP_USERDATA);
+ switch(msg) {
+ case WM_INITDIALOG:
+ {
+ TCHAR szSize[64];
+ struct _stati64 statbuf;
+ HWND hwndFocus;
+ struct TDlgProcFileExistsParam *dat = (struct TDlgProcFileExistsParam *)lParam;
+
+ SetPropA(hwndDlg,"Miranda.Preshutdown",HookEventMessage(ME_SYSTEM_PRESHUTDOWN,hwndDlg,M_PRESHUTDOWN));
+ SetPropA(hwndDlg,"Miranda.ParentWnd",dat->hwndParent);
+
+ TranslateDialogDefault(hwndDlg);
+ fts=(PROTOFILETRANSFERSTATUS*)mir_alloc(sizeof(PROTOFILETRANSFERSTATUS));
+ CopyProtoFileTransferStatus(fts,dat->fts);
+ SetWindowLongPtr(hwndDlg,GWLP_USERDATA,(LONG_PTR)fts);
+ SetDlgItemText(hwndDlg,IDC_FILENAME,fts->tszCurrentFile);
+ SetControlToUnixTime(hwndDlg,IDC_NEWDATE,fts->currentFileTime);
+ GetSensiblyFormattedSize(fts->currentFileSize,szSize,SIZEOF(szSize),0,1,NULL);
+ SetDlgItemText(hwndDlg,IDC_NEWSIZE,szSize);
+
+ pfnIconWindowProc=(WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_EXISTINGICON),GWLP_WNDPROC,(LONG_PTR)IconCtrlSubclassProc);
+
+ hwndFocus=GetDlgItem(hwndDlg,IDC_RESUME);
+ if ( _tstati64(fts->tszCurrentFile,&statbuf)==0) {
+ SetControlToUnixTime(hwndDlg,IDC_EXISTINGDATE,statbuf.st_mtime);
+ GetSensiblyFormattedSize(statbuf.st_size,szSize,SIZEOF(szSize),0,1,NULL);
+ SetDlgItemText(hwndDlg,IDC_EXISTINGSIZE,szSize);
+ if(statbuf.st_size>(int)fts->currentFileSize) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_RESUME),FALSE);
+ hwndFocus=GetDlgItem(hwndDlg,IDC_OVERWRITE);
+ } }
+
+ loadiconsstartinfo *lisi = ( loadiconsstartinfo* )mir_alloc(sizeof(loadiconsstartinfo));
+ lisi->hwndDlg=hwndDlg;
+ lisi->szFilename = mir_tstrdup(fts->tszCurrentFile);
+ //can be a little slow, so why not?
+ forkthread(LoadIconsAndTypesThread,0,lisi);
+ SetFocus(hwndFocus);
+ SetWindowLongPtr(hwndFocus,GWL_STYLE,GetWindowLongPtr(hwndFocus,GWL_STYLE)|BS_DEFPUSHBUTTON);
+ return FALSE;
+ }
+ case WM_COMMAND:
+ {
+ PROTOFILERESUME pfr={0};
+ switch(LOWORD(wParam)) {
+ case IDC_OPENFILE:
+ ShellExecute( hwndDlg, NULL, fts->tszCurrentFile, NULL, NULL, SW_SHOW );
+ return FALSE;
+
+ case IDC_OPENFOLDER:
+ {
+ TCHAR szFile[MAX_PATH];
+ lstrcpyn( szFile, fts->tszCurrentFile, SIZEOF(szFile));
+ TCHAR* pszLastBackslash = _tcsrchr( szFile, '\\' );
+ if ( pszLastBackslash )
+ *pszLastBackslash = '\0';
+ ShellExecute(hwndDlg,NULL,szFile,NULL,NULL,SW_SHOW);
+ return FALSE;
+ }
+ case IDC_PROPERTIES:
+ DoAnnoyingShellCommand(hwndDlg,fts->tszCurrentFile,C_PROPERTIES,NULL);
+ return FALSE;
+ case IDC_RESUME:
+ pfr.action=FILERESUME_RESUME;
+ break;
+ case IDC_RESUMEALL:
+ pfr.action=FILERESUME_RESUMEALL;
+ break;
+ case IDC_OVERWRITE:
+ pfr.action=FILERESUME_OVERWRITE;
+ break;
+ case IDC_OVERWRITEALL:
+ pfr.action=FILERESUME_OVERWRITEALL;
+ break;
+
+ case IDC_AUTORENAME:
+ pfr.action = FILERESUME_RENAMEALL;
+ break;
+
+ case IDC_SAVEAS:
+ {
+ OPENFILENAME ofn={0};
+ TCHAR filter[512],*pfilter;
+ TCHAR str[MAX_PATH];
+
+ lstrcpyn( str, fts->tszCurrentFile, SIZEOF(str));
+ ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
+ ofn.hwndOwner = hwndDlg;
+ ofn.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
+ _tcscpy( filter, TranslateT("All Files"));
+ _tcscat( filter, _T(" (*)"));
+ pfilter = filter + _tcslen(filter) + 1;
+ _tcscpy( pfilter, _T("*"));
+ pfilter = pfilter + _tcslen(pfilter) + 1;
+ *pfilter='\0';
+ ofn.lpstrFilter = filter;
+ ofn.lpstrFile = str;
+ ofn.nMaxFile = SIZEOF(str);
+ ofn.nMaxFileTitle = MAX_PATH;
+ if(!GetSaveFileName(&ofn))
+ return FALSE;
+
+ pfr.szFilename = mir_tstrdup(str);
+ pfr.action = FILERESUME_RENAME;
+ break;
+ }
+ case IDC_SKIP:
+ pfr.action=FILERESUME_SKIP;
+ break;
+ case IDCANCEL:
+ pfr.action=FILERESUME_CANCEL;
+ break;
+ default:
+ return FALSE;
+ }
+ { PROTOFILERESUME *pfrCopy;
+ pfrCopy=(PROTOFILERESUME*)mir_alloc(sizeof(pfr));
+ CopyMemory(pfrCopy,&pfr,sizeof(pfr));
+ PostMessage((HWND)GetPropA(hwndDlg,"Miranda.ParentWnd"),M_FILEEXISTSDLGREPLY,(WPARAM)mir_tstrdup(fts->tszCurrentFile),(LPARAM)pfrCopy);
+ DestroyWindow(hwndDlg);
+ }
+ break;
+ }
+
+ case WM_CLOSE:
+ PostMessage(hwndDlg,WM_COMMAND,MAKEWPARAM(IDCANCEL,BN_CLICKED),(LPARAM)GetDlgItem(hwndDlg,IDCANCEL));
+ break;
+
+ case M_PRESHUTDOWN:
+ PostMessage(hwndDlg,WM_CLOSE,0,0);
+ break;
+
+ case WM_DESTROY:
+ UnhookEvent(GetPropA(hwndDlg,"Miranda.Preshutdown")); // GetProp() will return NULL if it couldnt find anything
+ RemovePropA(hwndDlg,"Miranda.Preshutdown");
+ RemovePropA(hwndDlg,"Miranda.ParentWnd");
+ DestroyIcon((HICON)SendDlgItemMessage(hwndDlg,IDC_EXISTINGICON,STM_GETICON,0,0));
+ DestroyIcon((HICON)SendDlgItemMessage(hwndDlg,IDC_NEWICON,STM_GETICON,0,0));
+ FreeProtoFileTransferStatus(fts);
+ mir_free(fts);
+ break;
+ }
+ return FALSE;
+}
diff --git a/src/modules/srfile/fileopts.cpp b/src/modules/srfile/fileopts.cpp new file mode 100644 index 0000000000..3107f109a3 --- /dev/null +++ b/src/modules/srfile/fileopts.cpp @@ -0,0 +1,247 @@ +/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2009 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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 "commonheaders.h"
+#include "file.h"
+
+#define VSCAN_MCAFEE 1
+#define VSCAN_DRSOLOMON 2
+#define VSCAN_NORTON 3
+#define VSCAN_CA 4
+
+struct virusscannerinfo {
+ const TCHAR *szProductName;
+ const TCHAR *szExeRegPath;
+ const TCHAR *szExeRegValue;
+ const TCHAR *szCommandLine;
+};
+
+static const struct virusscannerinfo virusScanners[]={
+ {_T("Network Associates/McAfee VirusScan"),_T("SOFTWARE\\McAfee\\VirusScan"),_T("Scan32EXE"),_T("\"%s\" %%f /nosplash /comp /autoscan /autoexit /noboot")},
+ {_T("Dr Solomon's VirusScan (Network Associates)"),_T("SOFTWARE\\Network Associates\\TVD\\VirusScan\\AVConsol\\General"),_T("szScannerExe"),_T("\"%s\" %%f /uinone /noboot /comp /prompt /autoexit")},
+ {_T("Norton AntiVirus"),_T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\Navw32.exe"),NULL,_T("\"%s\" %%f /b- /m- /s+ /noresults")},
+ {_T("Computer Associates/Inoculate IT"),_T("Software\\Antivirus"),_T("ImageFilename"),_T("\"%s\" %%f /display=progress /exit")},
+ {_T("Computer Associates eTrust"),_T("SOFTWARE\\ComputerAssociates\\Anti-Virus\\Resident"),_T("VetPath"),_T("\"%s\" %%f /display=progress /exit")},
+ {_T("Kaspersky Anti-Virus"),_T("SOFTWARE\\KasperskyLab\\Components\\101"),_T("EXEName"),_T("\"%s\" /S /Q %%f")},
+ {_T("Kaspersky Anti-Virus"),_T("SOFTWARE\\KasperskyLab\\SetupFolders"),_T("KAV8"),_T("\"%savp.exe\" SCAN %%f")},
+ {_T("Kaspersky Anti-Virus"),_T("SOFTWARE\\KasperskyLab\\SetupFolders"),_T("KAV9"),_T("\"%savp.exe\" SCAN %%f")},
+ {_T("AntiVir PersonalEdition Classic"),_T("SOFTWARE\\Avira\\AntiVir PersonalEdition Classic"),_T("Path"),_T("\"%savscan.exe\" /GUIMODE=2 /PATH=\"%%f\"")},
+ {_T("ESET NOD32 Antivirus"),_T("SOFTWARE\\ESET\\ESET Security\\CurrentVersion\\Info"),_T("InstallDir"),_T("\"%secls.exe\" /log-all /aind /no-boots /adware /sfx /unsafe /unwanted /heur /adv-heur /action=clean \"%%f\"")},
+};
+
+#define M_UPDATEENABLING (WM_USER+100)
+#define M_SCANCMDLINESELCHANGE (WM_USER+101)
+
+#ifndef SHACF_FILESYS_DIRS
+ #define SHACF_FILESYS_DIRS 0x00000020
+#endif
+
+static INT_PTR CALLBACK DlgProcFileOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg) {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+
+ if (shAutoComplete)
+ shAutoComplete(GetDlgItem(hwndDlg, IDC_FILEDIR), SHACF_FILESYS_DIRS);
+
+ {
+ TCHAR str[MAX_PATH];
+ GetContactReceivedFilesDir(NULL,str,SIZEOF(str),FALSE);
+ SetDlgItemText(hwndDlg,IDC_FILEDIR,str);
+ }
+
+ CheckDlgButton(hwndDlg, IDC_AUTOACCEPT, DBGetContactSettingByte(NULL,"SRFile","AutoAccept",0) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_AUTOMIN, DBGetContactSettingByte(NULL,"SRFile","AutoMin",0) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_AUTOCLOSE, DBGetContactSettingByte(NULL,"SRFile","AutoClose",0) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_AUTOCLEAR, DBGetContactSettingByte(NULL,"SRFile","AutoClear",1) ? BST_CHECKED : BST_UNCHECKED);
+ switch(DBGetContactSettingByte(NULL,"SRFile","UseScanner",VIRUSSCAN_DISABLE)) {
+ case VIRUSSCAN_AFTERDL: CheckDlgButton(hwndDlg, IDC_SCANAFTERDL, BST_CHECKED); break;
+ case VIRUSSCAN_DURINGDL: CheckDlgButton(hwndDlg, IDC_SCANDURINGDL, BST_CHECKED); break;
+ default: CheckDlgButton(hwndDlg, IDC_NOSCANNER, BST_CHECKED); break;
+ }
+ CheckDlgButton(hwndDlg, IDC_WARNBEFOREOPENING, DBGetContactSettingByte(NULL,"SRFile","WarnBeforeOpening",1) ? BST_CHECKED : BST_UNCHECKED);
+
+ { TCHAR szScanExe[MAX_PATH];
+ int i,iItem;
+ for( i=0; i < SIZEOF(virusScanners); i++ ) {
+ if(SRFile_GetRegValue(HKEY_LOCAL_MACHINE,virusScanners[i].szExeRegPath,virusScanners[i].szExeRegValue,szScanExe,SIZEOF(szScanExe))) {
+ iItem=SendDlgItemMessage(hwndDlg,IDC_SCANCMDLINE,CB_ADDSTRING,0,(LPARAM)virusScanners[i].szProductName);
+ SendDlgItemMessage(hwndDlg,IDC_SCANCMDLINE,CB_SETITEMDATA,iItem,i);
+ }
+ }
+ if ( SendDlgItemMessageA(hwndDlg,IDC_SCANCMDLINE,CB_GETCOUNT,0,0) == 0 )
+ {
+ iItem = SendDlgItemMessage(hwndDlg,IDC_SCANCMDLINE,CB_ADDSTRING,0,(LPARAM)_T("") );
+ SendDlgItemMessage(hwndDlg,IDC_SCANCMDLINE,CB_SETITEMDATA,iItem, (LPARAM)-1);
+ }
+ }
+
+ DBVARIANT dbv;
+ if(DBGetContactSettingTString(NULL,"SRFile","ScanCmdLine",&dbv)==0) {
+ SetDlgItemText(hwndDlg,IDC_SCANCMDLINE,dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ }
+ else {
+ if(SendDlgItemMessage(hwndDlg,IDC_SCANCMDLINE,CB_GETCOUNT,0,0)) {
+ SendDlgItemMessage(hwndDlg,IDC_SCANCMDLINE,CB_SETCURSEL,0,0);
+ PostMessage(hwndDlg,M_SCANCMDLINESELCHANGE,0,0);
+ }
+ }
+ switch(DBGetContactSettingByte(NULL,"SRFile","IfExists",FILERESUME_ASK)) {
+ case FILERESUME_RESUMEALL: CheckDlgButton(hwndDlg, IDC_RESUME, BST_CHECKED); break;
+ case FILERESUME_OVERWRITEALL: CheckDlgButton(hwndDlg, IDC_OVERWRITE, BST_CHECKED); break;
+ case FILERESUME_RENAMEALL: CheckDlgButton(hwndDlg, IDC_RENAME, BST_CHECKED); break;
+ default: CheckDlgButton(hwndDlg, IDC_ASK, BST_CHECKED); break;
+ }
+ SendMessage(hwndDlg,M_UPDATEENABLING,0,0);
+ return TRUE;
+ }
+ case M_UPDATEENABLING:
+ { int on=!IsDlgButtonChecked(hwndDlg,IDC_NOSCANNER);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_ST_CMDLINE),on);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SCANCMDLINE),on);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SCANCMDLINEBROWSE),on);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_ST_CMDLINEHELP),on);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AUTOMIN),IsDlgButtonChecked(hwndDlg,IDC_AUTOACCEPT));
+ break;
+ }
+ case M_SCANCMDLINESELCHANGE:
+ { TCHAR str[512];
+ TCHAR szScanExe[MAX_PATH];
+ int iScanner=SendDlgItemMessage(hwndDlg,IDC_SCANCMDLINE,CB_GETITEMDATA,SendDlgItemMessage(hwndDlg,IDC_SCANCMDLINE,CB_GETCURSEL,0,0),0);
+ if(iScanner >= SIZEOF(virusScanners) || iScanner<0) break;
+ str[0]='\0';
+ if(SRFile_GetRegValue(HKEY_LOCAL_MACHINE,virusScanners[iScanner].szExeRegPath,virusScanners[iScanner].szExeRegValue,szScanExe,SIZEOF(szScanExe)))
+ mir_sntprintf(str, SIZEOF(str), virusScanners[iScanner].szCommandLine,szScanExe);
+ SetDlgItemText(hwndDlg,IDC_SCANCMDLINE,str);
+ break;
+ }
+ case WM_COMMAND:
+ switch(LOWORD(wParam)) {
+ case IDC_FILEDIR:
+ if((HIWORD(wParam)!=EN_CHANGE || (HWND)lParam!=GetFocus())) return 0;
+ break;
+ case IDC_FILEDIRBROWSE:
+ { TCHAR str[MAX_PATH];
+ GetDlgItemText(hwndDlg,IDC_FILEDIR,str,SIZEOF(str));
+ if(BrowseForFolder(hwndDlg,str))
+ SetDlgItemText(hwndDlg,IDC_FILEDIR,str);
+ break;
+ }
+ case IDC_AUTOACCEPT:
+ case IDC_NOSCANNER:
+ case IDC_SCANAFTERDL:
+ case IDC_SCANDURINGDL:
+ SendMessage(hwndDlg,M_UPDATEENABLING,0,0);
+ break;
+ case IDC_SCANCMDLINE:
+ if(HIWORD(wParam)==CBN_SELCHANGE) PostMessage(hwndDlg,M_SCANCMDLINESELCHANGE,0,0);
+ else if(HIWORD(wParam)!=CBN_EDITCHANGE) return 0;
+ break;
+ case IDC_SCANCMDLINEBROWSE:
+ { TCHAR str[MAX_PATH+2];
+ OPENFILENAME ofn = {0};
+ TCHAR filter[512], *pfilter;
+
+ GetDlgItemText(hwndDlg, IDC_SCANCMDLINE, str, SIZEOF(str));
+ ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
+ ofn.hwndOwner = hwndDlg;
+ ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_DONTADDTORECENT;
+ _tcscpy(filter,TranslateT("Executable Files"));
+ _tcscat(filter, _T(" (*.exe)"));
+ pfilter = filter + _tcslen(filter) + 1;
+ _tcscpy(pfilter, _T("*.exe"));
+ pfilter = pfilter + _tcslen(pfilter)+1;
+ _tcscpy(pfilter, TranslateT("All Files"));
+ _tcscat(pfilter, _T(" (*)"));
+ pfilter = pfilter + _tcslen(pfilter) + 1;
+ _tcscpy(pfilter, _T("*"));
+ pfilter = pfilter + _tcslen(pfilter) + 1;
+ *pfilter = 0;
+ ofn.lpstrFilter = filter;
+ ofn.lpstrFile = str;
+ ofn.nMaxFile = SIZEOF(str)-2;
+ if(str[0]=='"') {
+ TCHAR *pszQuote = _tcschr(str + 1, '"');
+ if (pszQuote) *pszQuote = 0;
+ MoveMemory(str, str + 1, _tcslen(str) * sizeof(TCHAR));
+ }
+ else {
+ TCHAR *pszSpace = _tcschr(str, ' ');
+ if (pszSpace) *pszSpace = 0;
+ }
+ ofn.nMaxFileTitle = MAX_PATH;
+ if (!GetOpenFileName(&ofn)) break;
+ if (_tcschr(str, ' ') != NULL) {
+ MoveMemory(str+1, str, SIZEOF(str) - 2 * sizeof(TCHAR));
+ str[0] = '"';
+ _tcscat(str, _T("\""));
+ }
+ SetDlgItemText(hwndDlg, IDC_SCANCMDLINE, str);
+ break;
+ }
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ { TCHAR str[512];
+ GetDlgItemText(hwndDlg, IDC_FILEDIR, str, SIZEOF(str));
+ RemoveInvalidPathChars(str);
+ DBWriteContactSettingTString(NULL,"SRFile","RecvFilesDirAdv",str);
+ DBWriteContactSettingByte(NULL,"SRFile","AutoAccept",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_AUTOACCEPT));
+ DBWriteContactSettingByte(NULL,"SRFile","AutoMin",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_AUTOMIN));
+ DBWriteContactSettingByte(NULL,"SRFile","AutoClose",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_AUTOCLOSE));
+ DBWriteContactSettingByte(NULL,"SRFile","AutoClear",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_AUTOCLEAR));
+ DBWriteContactSettingByte(NULL,"SRFile","UseScanner",(BYTE)(IsDlgButtonChecked(hwndDlg,IDC_SCANAFTERDL)?VIRUSSCAN_AFTERDL:(IsDlgButtonChecked(hwndDlg,IDC_SCANDURINGDL)?VIRUSSCAN_DURINGDL:VIRUSSCAN_DISABLE)));
+ GetDlgItemText(hwndDlg, IDC_SCANCMDLINE, str, SIZEOF(str));
+ DBWriteContactSettingTString(NULL,"SRFile","ScanCmdLine",str);
+ DBWriteContactSettingByte(NULL,"SRFile","WarnBeforeOpening",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_WARNBEFOREOPENING));
+ DBWriteContactSettingByte(NULL,"SRFile","IfExists",(BYTE)(IsDlgButtonChecked(hwndDlg,IDC_ASK)?FILERESUME_ASK:(IsDlgButtonChecked(hwndDlg,IDC_RESUME)?FILERESUME_RESUMEALL:(IsDlgButtonChecked(hwndDlg,IDC_OVERWRITE)?FILERESUME_OVERWRITEALL:FILERESUME_RENAMEALL))));
+ return TRUE;
+ }
+ }
+ break;
+ }
+ return FALSE;
+}
+
+int FileOptInitialise(WPARAM wParam, LPARAM)
+{
+ OPTIONSDIALOGPAGE odp={0};
+ odp.cbSize = sizeof(odp);
+ odp.position = 900000000;
+ odp.hInstance = hMirandaInst;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_FILETRANSFER);
+ odp.pszTitle = LPGEN("File Transfers");
+ odp.pszGroup = LPGEN("Events");
+ odp.pfnDlgProc = DlgProcFileOpts;
+ odp.flags = ODPF_BOLDGROUPS;
+ odp.nIDBottomSimpleControl = IDC_VIRUSSCANNERGROUP;
+ CallService( MS_OPT_ADDPAGE, wParam, ( LPARAM )&odp );
+ return 0;
+}
+
diff --git a/src/modules/srfile/filerecvdlg.cpp b/src/modules/srfile/filerecvdlg.cpp new file mode 100644 index 0000000000..451a27e8bc --- /dev/null +++ b/src/modules/srfile/filerecvdlg.cpp @@ -0,0 +1,446 @@ +/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2009 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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 "commonheaders.h"
+#include "file.h"
+
+#define MAX_MRU_DIRS 5
+
+static BOOL CALLBACK ClipSiblingsChildEnumProc(HWND hwnd, LPARAM)
+{
+ SetWindowLongPtr(hwnd,GWL_STYLE,GetWindowLongPtr(hwnd,GWL_STYLE)|WS_CLIPSIBLINGS);
+ return TRUE;
+}
+
+static void GetLowestExistingDirName(const TCHAR *szTestDir,TCHAR *szExistingDir,int cchExistingDir)
+{
+ DWORD dwAttributes;
+ TCHAR *pszLastBackslash;
+
+ lstrcpyn(szExistingDir,szTestDir,cchExistingDir);
+ while((dwAttributes=GetFileAttributes(szExistingDir))!=INVALID_FILE_ATTRIBUTES && !(dwAttributes&FILE_ATTRIBUTE_DIRECTORY)) {
+ pszLastBackslash=_tcsrchr(szExistingDir,'\\');
+ if(pszLastBackslash==NULL) {*szExistingDir='\0'; break;}
+ *pszLastBackslash='\0';
+ }
+ if(szExistingDir[0]=='\0') GetCurrentDirectory(cchExistingDir,szExistingDir);
+}
+
+static const TCHAR InvalidFilenameChars[] = _T("\\/:*?\"<>|");
+void RemoveInvalidFilenameChars(TCHAR *tszString)
+{
+ size_t i;
+ if (tszString) {
+ for(i=_tcscspn(tszString,InvalidFilenameChars); tszString[i]; i+=_tcscspn(tszString+i+1,InvalidFilenameChars)+1)
+ if(tszString[i] >= 0)
+ tszString[i] = _T('_');
+ }
+}
+
+static const TCHAR InvalidPathChars[] = _T("*?\"<>|"); // "\/:" are excluded as they are allowed in file path
+void RemoveInvalidPathChars(TCHAR *tszString)
+{
+ size_t i;
+ if (tszString) {
+ for(i=_tcscspn(tszString,InvalidPathChars); tszString[i]; i+=_tcscspn(tszString+i+1,InvalidPathChars)+1)
+ if(tszString[i] >= 0)
+ tszString[i] = _T('_');
+ }
+}
+
+static INT CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LPARAM pData)
+{
+ TCHAR szDir[MAX_PATH];
+ switch(uMsg) {
+ case BFFM_INITIALIZED:
+ SendMessage(hwnd, BFFM_SETSELECTION, TRUE, pData);
+ break;
+ case BFFM_SELCHANGED:
+ if (SHGetPathFromIDList((LPITEMIDLIST) lp ,szDir))
+ SendMessage(hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)szDir);
+ break;
+ }
+ return 0;
+}
+
+int BrowseForFolder(HWND hwnd,TCHAR *szPath)
+{
+ BROWSEINFO bi={0};
+ LPITEMIDLIST pidlResult;
+
+ bi.hwndOwner=hwnd;
+ bi.pszDisplayName=szPath;
+ bi.lpszTitle=TranslateT("Select Folder");
+ bi.ulFlags=BIF_NEWDIALOGSTYLE|BIF_EDITBOX|BIF_RETURNONLYFSDIRS; // Use this combo instead of BIF_USENEWUI
+ bi.lpfn=BrowseCallbackProc;
+ bi.lParam=(LPARAM)szPath;
+
+ pidlResult=SHBrowseForFolder(&bi);
+ if(pidlResult) {
+ SHGetPathFromIDList(pidlResult,szPath);
+ lstrcat(szPath,_T("\\"));
+ CoTaskMemFree(pidlResult);
+ }
+ return pidlResult != NULL;
+}
+
+static REPLACEVARSARRAY sttVarsToReplace[] =
+{
+ { ( TCHAR* )"///", ( TCHAR* )"//" },
+ { ( TCHAR* )"//", ( TCHAR* )"/" },
+ { ( TCHAR* )"()", ( TCHAR* )"" },
+ { NULL, NULL }
+};
+
+static void patchDir( TCHAR* str, size_t strSize )
+{
+ REPLACEVARSDATA dat = { 0 };
+ dat.cbSize = sizeof( dat );
+ dat.dwFlags = RVF_TCHAR;
+ dat.variables = sttVarsToReplace;
+
+ TCHAR* result = ( TCHAR* )CallService( MS_UTILS_REPLACEVARS, (WPARAM)str, (LPARAM)&dat );
+ if ( result ) {
+ _tcsncpy( str, result, strSize );
+ mir_free( result );
+ }
+
+ size_t len = lstrlen( str );
+ if ( len+1 < strSize && str[len-1] != '\\' )
+ lstrcpy( str+len, _T("\\") );
+}
+
+void GetContactReceivedFilesDir(HANDLE hContact, TCHAR *szDir, int cchDir, BOOL patchVars)
+{
+ DBVARIANT dbv;
+ TCHAR szTemp[MAX_PATH];
+ szTemp[0] = 0;
+
+ if ( !DBGetContactSettingTString( NULL, "SRFile", "RecvFilesDirAdv", &dbv)) {
+ if ( lstrlen( dbv.ptszVal ) > 0 )
+ lstrcpyn( szTemp, dbv.ptszVal, SIZEOF( szTemp ));
+ DBFreeVariant( &dbv );
+ }
+
+ if ( !szTemp[0] )
+#ifdef _UNICODE
+ mir_sntprintf( szTemp, SIZEOF(szTemp), _T("%%mydocuments%%\\%s\\%%userid%%"), TranslateT("My Received Files"));
+#else
+ mir_sntprintf( szTemp, SIZEOF(szTemp), _T("%%mydocuments%%\\%s\\%%userid%%"), "My Received Files");
+#endif
+
+ if ( hContact ) {
+ REPLACEVARSDATA dat = { 0 };
+ REPLACEVARSARRAY rvaVarsToReplace[4];
+ rvaVarsToReplace[0].lptzKey = _T("nick");
+ rvaVarsToReplace[0].lptzValue = mir_tstrdup((TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR));
+ rvaVarsToReplace[1].lptzKey = _T("userid");
+ rvaVarsToReplace[1].lptzValue = GetContactID(hContact);
+ rvaVarsToReplace[2].lptzKey = _T("proto");
+ rvaVarsToReplace[2].lptzValue = mir_a2t((char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact,0));
+ rvaVarsToReplace[3].lptzKey = NULL;
+ rvaVarsToReplace[3].lptzValue = NULL;
+ for (int i=0; i < (SIZEOF(rvaVarsToReplace)-1);i++)
+ RemoveInvalidFilenameChars(rvaVarsToReplace[i].lptzValue);
+
+ dat.cbSize = sizeof( dat );
+ dat.dwFlags = RVF_TCHAR;
+ dat.variables = rvaVarsToReplace;
+ dat.hContact = hContact;
+ TCHAR* result = ( TCHAR* )CallService( MS_UTILS_REPLACEVARS, (WPARAM)szTemp, (LPARAM)&dat );
+ if ( result ) {
+ _tcsncpy( szTemp, result, SIZEOF(szTemp));
+ mir_free( result );
+ for (int i=0; i < (SIZEOF(rvaVarsToReplace)-1);i++)
+ mir_free(rvaVarsToReplace[i].lptzValue);
+ } }
+
+ if (patchVars)
+ patchDir( szTemp, SIZEOF(szTemp));
+ RemoveInvalidPathChars(szTemp);
+ lstrcpyn( szDir, szTemp, cchDir );
+}
+
+void GetReceivedFilesDir(TCHAR *szDir, int cchDir)
+{
+ DBVARIANT dbv;
+ TCHAR szTemp[MAX_PATH];
+ szTemp[0] = 0;
+
+ if ( !DBGetContactSettingTString( NULL, "SRFile", "RecvFilesDirAdv", &dbv )) {
+ if ( lstrlen( dbv.ptszVal ) > 0 )
+ lstrcpyn( szTemp, dbv.ptszVal, SIZEOF( szTemp ));
+ DBFreeVariant(&dbv);
+ }
+
+ if ( !szTemp[0] )
+#ifdef _UNICODE
+ mir_sntprintf( szTemp, SIZEOF(szTemp), _T("%%mydocuments%%\\%s"), TranslateT("My Received Files"));
+#else
+ mir_sntprintf( szTemp, SIZEOF(szTemp), _T("%%mydocuments%%\\%s"), "My Received Files");
+#endif
+
+ patchDir( szTemp, SIZEOF(szTemp));
+ RemoveInvalidPathChars(szTemp);
+ lstrcpyn( szDir, szTemp, cchDir );
+}
+
+INT_PTR CALLBACK DlgProcRecvFile(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct FileDlgData *dat;
+
+ dat=(struct FileDlgData*)GetWindowLongPtr(hwndDlg,GWLP_USERDATA);
+ switch (msg) {
+ case WM_INITDIALOG: {
+ TCHAR *contactName;
+ TCHAR szPath[450];
+ CLISTEVENT* cle = (CLISTEVENT*)lParam;
+
+ TranslateDialogDefault(hwndDlg);
+
+ dat=(struct FileDlgData*)mir_calloc(sizeof(struct FileDlgData));
+ SetWindowLongPtr(hwndDlg,GWLP_USERDATA,(LONG_PTR)dat);
+ dat->hContact = cle->hContact;
+ dat->hDbEvent = cle->hDbEvent;
+ dat->hPreshutdownEvent = HookEventMessage(ME_SYSTEM_PRESHUTDOWN,hwndDlg,M_PRESHUTDOWN);
+ dat->dwTicks = GetTickCount();
+
+ EnumChildWindows(hwndDlg,ClipSiblingsChildEnumProc,0);
+
+ Window_SetIcon_IcoLib(hwndDlg, SKINICON_EVENT_FILE);
+ Button_SetIcon_IcoLib(hwndDlg, IDC_ADD, SKINICON_OTHER_ADDCONTACT, LPGEN("Add Contact Permanently to List"));
+ Button_SetIcon_IcoLib(hwndDlg, IDC_DETAILS, SKINICON_OTHER_USERDETAILS, LPGEN("View User's Details"));
+ Button_SetIcon_IcoLib(hwndDlg, IDC_HISTORY, SKINICON_OTHER_HISTORY, LPGEN("View User's History"));
+ Button_SetIcon_IcoLib(hwndDlg, IDC_USERMENU, SKINICON_OTHER_DOWNARROW, LPGEN("User Menu"));
+
+ contactName = cli.pfnGetContactDisplayName( dat->hContact, 0 );
+ SetDlgItemText(hwndDlg,IDC_FROM,contactName);
+ GetContactReceivedFilesDir(dat->hContact,szPath,SIZEOF(szPath),TRUE);
+ SetDlgItemText(hwndDlg,IDC_FILEDIR,szPath);
+ {
+ int i;
+ char idstr[32];
+ DBVARIANT dbv;
+
+ if (shAutoComplete)
+ shAutoComplete(GetWindow(GetDlgItem(hwndDlg,IDC_FILEDIR),GW_CHILD),1);
+
+ for(i=0;i<MAX_MRU_DIRS;i++) {
+ mir_snprintf(idstr, SIZEOF(idstr), "MruDir%d",i);
+ if(DBGetContactSettingTString(NULL,"SRFile",idstr,&dbv)) break;
+ SendDlgItemMessage(hwndDlg,IDC_FILEDIR,CB_ADDSTRING,0,(LPARAM)dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ }
+ }
+
+ CallService(MS_DB_EVENT_MARKREAD,(WPARAM)dat->hContact,(LPARAM)dat->hDbEvent);
+ {
+ DBEVENTINFO dbei={0};
+ TCHAR datetimestr[64];
+ char buf[540];
+
+ dbei.cbSize=sizeof(dbei);
+ dbei.cbBlob=CallService(MS_DB_EVENT_GETBLOBSIZE,(WPARAM)dat->hDbEvent,0);
+ dbei.pBlob=(PBYTE)mir_alloc(dbei.cbBlob);
+ CallService(MS_DB_EVENT_GET,(WPARAM)dat->hDbEvent,(LPARAM)&dbei);
+ dat->fs = cle->lParam ? (HANDLE)cle->lParam : (HANDLE)*(PDWORD)dbei.pBlob;
+ lstrcpynA(buf, (char*)dbei.pBlob+4, min(dbei.cbBlob+1,SIZEOF(buf)));
+ TCHAR* ptszFileName = DbGetEventStringT( &dbei, buf );
+ SetDlgItemText(hwndDlg,IDC_FILENAMES,ptszFileName);
+ mir_free(ptszFileName);
+ lstrcpynA(buf, (char*)dbei.pBlob+4+strlen((char*)dbei.pBlob+4)+1, min((int)(dbei.cbBlob-4-strlen((char*)dbei.pBlob+4)),SIZEOF(buf)));
+ TCHAR* ptszDescription = DbGetEventStringT( &dbei, buf );
+ SetDlgItemText(hwndDlg,IDC_MSG,ptszDescription);
+ mir_free(ptszDescription);
+ mir_free(dbei.pBlob);
+
+ tmi.printTimeStamp(NULL, dbei.timestamp, _T("t d"), datetimestr, SIZEOF(datetimestr), 0);
+ SetDlgItemText(hwndDlg, IDC_DATE, datetimestr);
+ }
+ {
+ char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)dat->hContact, 0);
+ if (szProto) {
+ CONTACTINFO ci;
+ int hasName = 0;
+ char buf[128];
+ ZeroMemory(&ci,sizeof(ci));
+
+ ci.cbSize = sizeof(ci);
+ ci.hContact = dat->hContact;
+ ci.szProto = szProto;
+ ci.dwFlag = CNF_UNIQUEID;
+ if (!CallService(MS_CONTACT_GETCONTACTINFO,0,(LPARAM)&ci)) {
+ switch(ci.type) {
+ case CNFT_ASCIIZ:
+ hasName = 1;
+ mir_snprintf(buf, SIZEOF(buf), "%s", ci.pszVal);
+ mir_free(ci.pszVal);
+ break;
+ case CNFT_DWORD:
+ hasName = 1;
+ mir_snprintf(buf, SIZEOF(buf),"%u",ci.dVal);
+ break;
+ } }
+ if (hasName)
+ SetDlgItemTextA(hwndDlg, IDC_NAME, buf );
+ else
+ SetDlgItemText(hwndDlg, IDC_NAME, contactName);
+ } }
+
+ if(DBGetContactSettingByte(dat->hContact,"CList","NotOnList",0)) {
+ RECT rcBtn1,rcBtn2,rcDateCtrl;
+ GetWindowRect(GetDlgItem(hwndDlg,IDC_ADD),&rcBtn1);
+ GetWindowRect(GetDlgItem(hwndDlg,IDC_USERMENU),&rcBtn2);
+ GetWindowRect(GetDlgItem(hwndDlg,IDC_DATE),&rcDateCtrl);
+ SetWindowPos(GetDlgItem(hwndDlg,IDC_DATE),0,0,0,rcDateCtrl.right-rcDateCtrl.left-(rcBtn2.left-rcBtn1.left),rcDateCtrl.bottom-rcDateCtrl.top,SWP_NOZORDER|SWP_NOMOVE);
+ }
+ else if(DBGetContactSettingByte(NULL,"SRFile","AutoAccept",0)) {
+ //don't check auto-min here to fix BUG#647620
+ PostMessage(hwndDlg,WM_COMMAND,MAKEWPARAM(IDOK,BN_CLICKED),(LPARAM)GetDlgItem(hwndDlg,IDOK));
+ }
+ if(!DBGetContactSettingByte(dat->hContact,"CList","NotOnList",0))
+ ShowWindow(GetDlgItem(hwndDlg, IDC_ADD),SW_HIDE);
+ return TRUE;
+ }
+
+ case WM_MEASUREITEM:
+ return CallService(MS_CLIST_MENUMEASUREITEM,wParam,lParam);
+
+ case WM_DRAWITEM:
+ { LPDRAWITEMSTRUCT dis=(LPDRAWITEMSTRUCT)lParam;
+ if(dis->hwndItem==GetDlgItem(hwndDlg, IDC_PROTOCOL)) {
+ char *szProto;
+
+ szProto=(char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)dat->hContact,0);
+ if (szProto) {
+ HICON hIcon;
+
+ hIcon=(HICON)CallProtoService(szProto,PS_LOADICON,PLI_PROTOCOL|PLIF_SMALL,0);
+ if (hIcon) {
+ DrawIconEx(dis->hDC,dis->rcItem.left,dis->rcItem.top,hIcon,GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0,NULL,DI_NORMAL);
+ DestroyIcon(hIcon);
+ } } } }
+ return CallService(MS_CLIST_MENUDRAWITEM,wParam,lParam);
+
+ case WM_COMMAND:
+ if ( CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam),MPCF_CONTACTMENU), (LPARAM)dat->hContact ))
+ break;
+
+ switch ( LOWORD( wParam )) {
+ case IDC_FILEDIRBROWSE:
+ {
+ TCHAR szDirName[MAX_PATH],szExistingDirName[MAX_PATH];
+
+ GetDlgItemText(hwndDlg,IDC_FILEDIR,szDirName,SIZEOF(szDirName));
+ GetLowestExistingDirName(szDirName,szExistingDirName,SIZEOF(szExistingDirName));
+ if(BrowseForFolder(hwndDlg,szExistingDirName))
+ SetDlgItemText(hwndDlg,IDC_FILEDIR,szExistingDirName);
+ }
+ break;
+
+ case IDOK:
+ { //most recently used directories
+ TCHAR szRecvDir[MAX_PATH],szDefaultRecvDir[MAX_PATH];
+ GetDlgItemText(hwndDlg,IDC_FILEDIR,szRecvDir,SIZEOF(szRecvDir));
+ RemoveInvalidPathChars(szRecvDir);
+ GetContactReceivedFilesDir(NULL,szDefaultRecvDir,SIZEOF(szDefaultRecvDir),TRUE);
+ if(_tcsnicmp(szRecvDir,szDefaultRecvDir,lstrlen(szDefaultRecvDir))) {
+ char idstr[32];
+ int i;
+ DBVARIANT dbv;
+ for(i=MAX_MRU_DIRS-2;i>=0;i--) {
+ mir_snprintf(idstr, SIZEOF(idstr), "MruDir%d",i);
+ if(DBGetContactSettingTString(NULL,"SRFile",idstr,&dbv)) continue;
+ mir_snprintf(idstr, SIZEOF(idstr), "MruDir%d",i+1);
+ DBWriteContactSettingTString(NULL,"SRFile",idstr,dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ }
+ DBWriteContactSettingTString(NULL,"SRFile",idstr,szRecvDir);
+ }
+ }
+ EnableWindow(GetDlgItem(hwndDlg,IDC_FILENAMES),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MSG),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_FILEDIR),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_FILEDIRBROWSE),FALSE);
+
+ GetDlgItemText(hwndDlg,IDC_FILEDIR,dat->szSavePath,SIZEOF(dat->szSavePath));
+ GetDlgItemText(hwndDlg,IDC_FILE,dat->szFilenames,SIZEOF(dat->szFilenames));
+ GetDlgItemText(hwndDlg,IDC_MSG,dat->szMsg,SIZEOF(dat->szMsg));
+ dat->hwndTransfer = FtMgr_AddTransfer(dat);
+ SetWindowLongPtr( hwndDlg, GWLP_USERDATA, 0);
+ //check for auto-minimize here to fix BUG#647620
+ if(DBGetContactSettingByte(NULL,"SRFile","AutoAccept",0) && DBGetContactSettingByte(NULL,"SRFile","AutoMin",0)) {
+ ShowWindow(hwndDlg,SW_HIDE);
+ ShowWindow(hwndDlg,SW_SHOWMINNOACTIVE);
+ }
+ DestroyWindow(hwndDlg);
+ break;
+
+ case IDCANCEL:
+ if (dat->fs) CallContactService(dat->hContact,PSS_FILEDENYT,(WPARAM)dat->fs,(LPARAM)TranslateT("Cancelled"));
+ dat->fs=NULL; /* the protocol will free the handle */
+ DestroyWindow(hwndDlg);
+ break;
+
+ case IDC_ADD:
+ { ADDCONTACTSTRUCT acs={0};
+
+ acs.handle=dat->hContact;
+ acs.handleType=HANDLE_CONTACT;
+ acs.szProto="";
+ CallService(MS_ADDCONTACT_SHOW,(WPARAM)hwndDlg,(LPARAM)&acs);
+ if(!DBGetContactSettingByte(dat->hContact,"CList","NotOnList",0))
+ ShowWindow(GetDlgItem(hwndDlg,IDC_ADD), SW_HIDE);
+ }
+ break;
+
+ case IDC_USERMENU:
+ { RECT rc;
+ HMENU hMenu=(HMENU)CallService(MS_CLIST_MENUBUILDCONTACT,(WPARAM)dat->hContact,0);
+ GetWindowRect((HWND)lParam,&rc);
+ TrackPopupMenu(hMenu,0,rc.left,rc.bottom,0,hwndDlg,NULL);
+ DestroyMenu(hMenu);
+ }
+ break;
+
+ case IDC_DETAILS:
+ CallService(MS_USERINFO_SHOWDIALOG,(WPARAM)dat->hContact,0);
+ break;
+
+ case IDC_HISTORY:
+ CallService(MS_HISTORY_SHOWCONTACTHISTORY,(WPARAM)dat->hContact,0);
+ break;
+ }
+ break;
+
+ case WM_DESTROY:
+ Window_FreeIcon_IcoLib(hwndDlg);
+ Button_FreeIcon_IcoLib(hwndDlg,IDC_ADD);
+ Button_FreeIcon_IcoLib(hwndDlg,IDC_DETAILS);
+ Button_FreeIcon_IcoLib(hwndDlg,IDC_HISTORY);
+ Button_FreeIcon_IcoLib(hwndDlg,IDC_USERMENU);
+
+ if ( dat ) FreeFileDlgData( dat );
+ break;
+ }
+ return FALSE;
+}
diff --git a/src/modules/srfile/filesenddlg.cpp b/src/modules/srfile/filesenddlg.cpp new file mode 100644 index 0000000000..94c24a2479 --- /dev/null +++ b/src/modules/srfile/filesenddlg.cpp @@ -0,0 +1,363 @@ +/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2009 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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 "commonheaders.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "file.h"
+
+static void SetFileListAndSizeControls(HWND hwndDlg,struct FileDlgData *dat)
+{
+ int fileCount=0,dirCount=0,totalSize=0,i;
+ struct _stat statbuf;
+ TCHAR str[64];
+
+ for ( i=0; dat->files[i]; i++ ) {
+ if ( _tstat( dat->files[i], &statbuf ) == 0 ) {
+ if ( statbuf.st_mode & _S_IFDIR)
+ dirCount++;
+ else
+ fileCount++;
+ totalSize += statbuf.st_size;
+ } }
+
+ GetSensiblyFormattedSize(totalSize,str,SIZEOF(str),0,1,NULL);
+ SetDlgItemText(hwndDlg,IDC_TOTALSIZE,str);
+ if(i>1) {
+ TCHAR szFormat[32];
+ if(fileCount && dirCount) {
+ mir_sntprintf(szFormat,SIZEOF(szFormat),_T("%s, %s"),TranslateTS(fileCount==1?_T("%d file"):_T("%d files")),TranslateTS(dirCount==1?_T("%d directory"):_T("%d directories")));
+ mir_sntprintf(str,SIZEOF(str),szFormat,fileCount,dirCount);
+ }
+ else if(fileCount) {
+ lstrcpy(szFormat,TranslateT("%d files"));
+ mir_sntprintf(str,SIZEOF(str),szFormat,fileCount);
+ }
+ else {
+ lstrcpy(szFormat,TranslateT("%d directories"));
+ mir_sntprintf(str,SIZEOF(str),szFormat,dirCount);
+ }
+ SetDlgItemText(hwndDlg,IDC_FILE,str);
+ }
+ else SetDlgItemText(hwndDlg,IDC_FILE,dat->files[0]);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDOK), fileCount || dirCount);
+}
+
+static void FilenameToFileList(HWND hwndDlg, struct FileDlgData* dat, const TCHAR* buf)
+{
+ DWORD dwFileAttributes;
+
+ // Make sure that the file matrix is empty (the user may select files several times)
+ FreeFilesMatrix(&dat->files);
+
+ // Get the file attributes of selection
+ dwFileAttributes = GetFileAttributes( buf );
+ if (dwFileAttributes == INVALID_FILE_ATTRIBUTES)
+ return;
+
+ // Check if the selection is a directory or a file
+ if ( GetFileAttributes( buf ) & FILE_ATTRIBUTE_DIRECTORY ) {
+ const TCHAR* pBuf;
+ int nNumberOfFiles = 0;
+ int nTemp;
+ int fileOffset;
+
+ // :NOTE: The first string in the buffer is the directory, followed by a
+ // NULL separated list of all files
+
+ // fileOffset is the offset to the first file.
+ fileOffset = lstrlen(buf) + 1;
+
+ // Count number of files
+ pBuf = buf + fileOffset;
+ while ( *pBuf ) {
+ pBuf += lstrlen(pBuf) + 1;
+ nNumberOfFiles++;
+ }
+
+ // Allocate memory for a pointer array
+ if (( dat->files = ( TCHAR* *)mir_alloc((nNumberOfFiles + 1) * sizeof(TCHAR*))) == NULL )
+ return;
+
+ // Fill the array
+ pBuf = buf + fileOffset;
+ nTemp = 0;
+ while(*pBuf)
+ {
+ // Allocate space for path+filename
+ int cbFileNameLen = lstrlen( pBuf );
+ dat->files[nTemp] = ( TCHAR* )mir_alloc( sizeof(TCHAR)*(fileOffset + cbFileNameLen + 1));
+
+ // Add path to filename and copy into array
+ #if defined( _UNICODE )
+ CopyMemory(dat->files[nTemp], buf, (fileOffset-1)*sizeof( TCHAR ));
+ dat->files[nTemp][fileOffset-1] = '\\';
+ _tcscpy(dat->files[nTemp] + fileOffset - (buf[fileOffset-2]=='\\'?1:0), pBuf);
+ #else
+ CopyMemory(dat->files[nTemp], buf, fileOffset-1 );
+ dat->files[nTemp][fileOffset-1] = '\\';
+ strcpy(dat->files[nTemp] + fileOffset - (buf[fileOffset-2]=='\\'?1:0), pBuf);
+ #endif
+ // Move pointers to next file...
+ pBuf += cbFileNameLen + 1;
+ nTemp++;
+ }
+ // Terminate array
+ dat->files[nNumberOfFiles] = NULL;
+ }
+ // ...the selection is a single file
+ else
+ {
+ if (( dat->files = ( TCHAR **)mir_alloc(2 * sizeof( TCHAR*))) == NULL ) // Leaks when aborted
+ return;
+
+ dat->files[0] = mir_tstrdup(buf);
+ dat->files[1] = NULL;
+ }
+
+ // Update dialog text with new file selection
+ SetFileListAndSizeControls(hwndDlg, dat);
+}
+
+#define M_FILECHOOSEDONE (WM_USER+100)
+void __cdecl ChooseFilesThread(void* param)
+{
+ HWND hwndDlg = ( HWND )param;
+ TCHAR filter[128], *pfilter;
+ TCHAR* buf = ( TCHAR* )mir_alloc( sizeof(TCHAR)*32767 );
+ if ( buf == NULL )
+ PostMessage( hwndDlg, M_FILECHOOSEDONE, 0, ( LPARAM )( TCHAR* )NULL );
+ else {
+ OPENFILENAME ofn = {0};
+ ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
+ ofn.hwndOwner = hwndDlg;
+ lstrcpy( filter, TranslateT( "All Files" ));
+ lstrcat( filter, _T(" (*)" ));
+ pfilter = filter + lstrlen( filter )+1;
+ lstrcpy( pfilter, _T( "*" ));
+ pfilter = filter + lstrlen( filter )+1;
+ pfilter[ 0 ] = '\0';
+ ofn.lpstrFilter = filter;
+ ofn.lpstrFile = buf; *buf = 0;
+ ofn.nMaxFile = 32767;
+ ofn.Flags = OFN_NOCHANGEDIR | OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_DONTADDTORECENT;
+ if ( GetOpenFileName( &ofn ))
+ PostMessage( hwndDlg, M_FILECHOOSEDONE, 0, ( LPARAM )buf );
+ else {
+ mir_free( buf );
+ PostMessage( hwndDlg, M_FILECHOOSEDONE, 0, ( LPARAM )( TCHAR* )NULL );
+} } }
+
+static BOOL CALLBACK ClipSiblingsChildEnumProc(HWND hwnd,LPARAM)
+{
+ SetWindowLongPtr(hwnd,GWL_STYLE,GetWindowLongPtr(hwnd,GWL_STYLE)|WS_CLIPSIBLINGS);
+ return TRUE;
+}
+
+static WNDPROC OldSendEditProc;
+static LRESULT CALLBACK SendEditSubclassProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ switch(msg) {
+ case WM_CHAR:
+ if(wParam=='\n' && GetKeyState(VK_CONTROL)&0x8000) {
+ PostMessage(GetParent(hwnd),WM_COMMAND,IDOK,0);
+ return 0;
+ }
+ break;
+ case WM_SYSCHAR:
+ if((wParam=='s' || wParam=='S') && GetKeyState(VK_MENU)&0x8000) {
+ PostMessage(GetParent(hwnd),WM_COMMAND,IDOK,0);
+ return 0;
+ }
+ break;
+ }
+ return CallWindowProc(OldSendEditProc,hwnd,msg,wParam,lParam);
+}
+
+INT_PTR CALLBACK DlgProcSendFile(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct FileDlgData *dat;
+
+ dat=(struct FileDlgData*)GetWindowLongPtr(hwndDlg,GWLP_USERDATA);
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ struct FileSendData *fsd=(struct FileSendData*)lParam;
+
+ dat=(struct FileDlgData*)mir_calloc(sizeof(struct FileDlgData));
+ SetWindowLongPtr(hwndDlg,GWLP_USERDATA,(LONG_PTR)dat);
+ dat->hContact=fsd->hContact;
+ dat->send=1;
+ dat->hPreshutdownEvent=HookEventMessage(ME_SYSTEM_PRESHUTDOWN,hwndDlg,M_PRESHUTDOWN);
+ dat->fs=NULL;
+ dat->dwTicks=GetTickCount();
+
+ TranslateDialogDefault(hwndDlg);
+ EnumChildWindows(hwndDlg,ClipSiblingsChildEnumProc,0);
+ OldSendEditProc=(WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_MSG),GWLP_WNDPROC,(LONG_PTR)SendEditSubclassProc);
+
+ Window_SetIcon_IcoLib(hwndDlg, SKINICON_EVENT_FILE);
+ Button_SetIcon_IcoLib(hwndDlg, IDC_DETAILS, SKINICON_OTHER_USERDETAILS, LPGEN("View User's Details"));
+ Button_SetIcon_IcoLib(hwndDlg, IDC_HISTORY, SKINICON_OTHER_HISTORY, LPGEN("View User's History"));
+ Button_SetIcon_IcoLib(hwndDlg, IDC_USERMENU, SKINICON_OTHER_DOWNARROW, LPGEN("User Menu"));
+
+ EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
+
+ if(fsd->ppFiles!=NULL && fsd->ppFiles[0]!=NULL) {
+ int totalCount,i;
+ for(totalCount=0;fsd->ppFiles[totalCount];totalCount++);
+ dat->files = ( TCHAR** )mir_alloc( sizeof(TCHAR*)*(totalCount+1)); // Leaks
+ for(i=0;i<totalCount;i++)
+ dat->files[i] = mir_tstrdup( fsd->ppFiles[i] );
+ dat->files[totalCount]=NULL;
+ SetFileListAndSizeControls(hwndDlg,dat);
+ }
+ {
+ char *szProto;
+ TCHAR* contactName = cli.pfnGetContactDisplayName( dat->hContact, 0 );
+ SetDlgItemText(hwndDlg,IDC_TO,contactName);
+
+ szProto=(char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)dat->hContact,0);
+ if (szProto) {
+ CONTACTINFO ci;
+ int hasName = 0;
+ char buf[128];
+ ZeroMemory(&ci,sizeof(ci));
+
+ ci.cbSize = sizeof(ci);
+ ci.hContact = dat->hContact;
+ ci.szProto = szProto;
+ ci.dwFlag = CNF_UNIQUEID;
+ if (!CallService(MS_CONTACT_GETCONTACTINFO,0,(LPARAM)&ci)) {
+ switch(ci.type) {
+ case CNFT_ASCIIZ:
+ hasName = 1;
+ mir_snprintf(buf, SIZEOF(buf), "%s", ci.pszVal);
+ mir_free(ci.pszVal);
+ break;
+ case CNFT_DWORD:
+ hasName = 1;
+ mir_snprintf(buf, SIZEOF(buf),"%u",ci.dVal);
+ break;
+ } }
+
+ if ( hasName )
+ SetDlgItemTextA(hwndDlg,IDC_NAME,buf);
+ else
+ SetDlgItemText(hwndDlg,IDC_NAME,contactName);
+ } }
+
+ if ( fsd->ppFiles == NULL ) {
+ EnableWindow(hwndDlg, FALSE);
+ dat->closeIfFileChooseCancelled=1;
+ PostMessage(hwndDlg,WM_COMMAND,MAKEWPARAM(IDC_CHOOSE,BN_CLICKED),(LPARAM)GetDlgItem(hwndDlg,IDC_CHOOSE));
+ }
+ return TRUE;
+ }
+
+ case WM_MEASUREITEM:
+ return CallService(MS_CLIST_MENUMEASUREITEM,wParam,lParam);
+
+ case WM_DRAWITEM:
+ {
+ LPDRAWITEMSTRUCT dis=(LPDRAWITEMSTRUCT)lParam;
+ if(dis->hwndItem==GetDlgItem(hwndDlg, IDC_PROTOCOL)) {
+ char *szProto;
+
+ szProto=(char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)dat->hContact,0);
+ if (szProto) {
+ HICON hIcon = (HICON)CallProtoService(szProto,PS_LOADICON,PLI_PROTOCOL|PLIF_SMALL,0);
+ if (hIcon) {
+ DrawIconEx(dis->hDC,dis->rcItem.left,dis->rcItem.top,hIcon,GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0,NULL,DI_NORMAL);
+ DestroyIcon(hIcon);
+ } } } }
+ return CallService(MS_CLIST_MENUDRAWITEM,wParam,lParam);
+
+ case M_FILECHOOSEDONE:
+ if( lParam != 0 ) {
+ FilenameToFileList( hwndDlg, dat, ( TCHAR* )lParam );
+ mir_free(( TCHAR* )lParam );
+ dat->closeIfFileChooseCancelled = 0;
+ }
+ else if(dat->closeIfFileChooseCancelled) DestroyWindow(hwndDlg);
+ EnableWindow(hwndDlg,TRUE);
+ break;
+
+ case WM_COMMAND:
+ if(CallService(MS_CLIST_MENUPROCESSCOMMAND,MAKEWPARAM(LOWORD(wParam),MPCF_CONTACTMENU),(LPARAM)dat->hContact))
+ break;
+ switch (LOWORD(wParam))
+ {
+ case IDC_CHOOSE:
+ EnableWindow(hwndDlg,FALSE);
+ //GetOpenFileName() creates its own message queue which prevents any incoming events being processed
+ forkthread(ChooseFilesThread,0,hwndDlg);
+ break;
+ case IDOK:
+ EnableWindow(GetDlgItem(hwndDlg,IDC_FILENAME),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MSG),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHOOSE),FALSE);
+
+ GetDlgItemText(hwndDlg,IDC_FILEDIR,dat->szSavePath,SIZEOF(dat->szSavePath));
+ GetDlgItemText(hwndDlg,IDC_FILE,dat->szFilenames,SIZEOF(dat->szFilenames));
+ GetDlgItemText(hwndDlg,IDC_MSG,dat->szMsg,SIZEOF(dat->szMsg));
+ dat->hwndTransfer = FtMgr_AddTransfer(dat);
+ SetWindowLongPtr( hwndDlg, GWLP_USERDATA, 0);
+ DestroyWindow(hwndDlg);
+ return TRUE;
+
+ case IDCANCEL:
+ DestroyWindow(hwndDlg);
+ return TRUE;
+
+ case IDC_USERMENU:
+ { RECT rc;
+ HMENU hMenu=(HMENU)CallService(MS_CLIST_MENUBUILDCONTACT,(WPARAM)dat->hContact,0);
+ GetWindowRect((HWND)lParam,&rc);
+ TrackPopupMenu(hMenu,0,rc.left,rc.bottom,0,hwndDlg,NULL);
+ DestroyMenu(hMenu);
+ break;
+ }
+ case IDC_DETAILS:
+ CallService(MS_USERINFO_SHOWDIALOG,(WPARAM)dat->hContact,0);
+ return TRUE;
+ case IDC_HISTORY:
+ CallService(MS_HISTORY_SHOWCONTACTHISTORY,(WPARAM)dat->hContact,0);
+ return TRUE;
+ }
+ break;
+
+ case WM_DESTROY:
+ Window_FreeIcon_IcoLib(hwndDlg);
+ Button_FreeIcon_IcoLib(hwndDlg,IDC_DETAILS);
+ Button_FreeIcon_IcoLib(hwndDlg,IDC_HISTORY);
+ Button_FreeIcon_IcoLib(hwndDlg,IDC_USERMENU);
+
+ if ( dat )
+ FreeFileDlgData( dat );
+
+ SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_MSG),GWLP_WNDPROC,(LONG_PTR)OldSendEditProc);
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/src/modules/srfile/filexferdlg.cpp b/src/modules/srfile/filexferdlg.cpp new file mode 100644 index 0000000000..0a6246dea0 --- /dev/null +++ b/src/modules/srfile/filexferdlg.cpp @@ -0,0 +1,799 @@ +/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2010 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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 "commonheaders.h"
+#include <io.h>
+#include "file.h"
+
+#define HM_RECVEVENT (WM_USER+10)
+
+static int CheckVirusScanned(HWND hwnd,struct FileDlgData *dat,int i)
+{
+ if(dat->send) return 1;
+ if(dat->fileVirusScanned == NULL) return 0;
+ if(dat->fileVirusScanned[i]) return 1;
+ if(DBGetContactSettingByte(NULL,"SRFile","WarnBeforeOpening",1)==0) return 1;
+ return IDYES==MessageBox(hwnd,TranslateT("This file has not yet been scanned for viruses. Are you certain you want to open it?"),TranslateT("File Received"),MB_YESNO|MB_DEFBUTTON2);
+}
+
+#define M_VIRUSSCANDONE (WM_USER+100)
+struct virusscanthreadstartinfo {
+ TCHAR *szFile;
+ int returnCode;
+ HWND hwndReply;
+};
+
+TCHAR* PFTS_StringToTchar( int flags, const PROTOCHAR* s )
+{
+#ifdef _UNICODE
+ if ( flags & PFTS_UTF )
+ return Utf8DecodeUcs2(( char* )s );
+ else if ( flags & PFTS_UNICODE )
+ return mir_tstrdup( s );
+ else
+ return mir_a2t(( char* )s );
+#else
+ if ( flags & PFTS_UTF ) {
+ char *szAnsi = mir_strdup(( char* )s );
+ return Utf8Decode(szAnsi, NULL);
+ }
+ else
+ return mir_strdup( s );
+#endif
+}
+
+int PFTS_CompareWithTchar( PROTOFILETRANSFERSTATUS* ft, const PROTOCHAR* s, TCHAR* r )
+{
+#ifdef _UNICODE
+ if ( ft->flags & PFTS_UTF ) {
+ TCHAR* ts = Utf8DecodeUcs2(( char* )s );
+ int res = _tcscmp( ts, r );
+ mir_free( ts );
+ return res;
+ }
+ else if ( ft->flags & PFTS_UNICODE )
+ return _tcscmp( s, r );
+ else {
+ TCHAR* ts = mir_a2t(( char* )s );
+ int res = _tcscmp( ts, r );
+ mir_free( ts );
+ return res;
+ }
+#else
+ if ( ft->flags & PFTS_UTF ) {
+ char *ts = NEWSTR_ALLOCA(( char* )s );
+ return _tcscmp( Utf8Decode(( char* )ts, NULL), r );
+ }
+ else
+ return _tcscmp( s, r );
+#endif
+}
+
+static void SetOpenFileButtonStyle(HWND hwndButton,int enabled)
+{
+ EnableWindow(hwndButton,enabled);
+}
+
+void FillSendData( FileDlgData* dat, DBEVENTINFO& dbei )
+{
+ dbei.cbSize = sizeof(dbei);
+ dbei.szModule = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)dat->hContact,0);
+ dbei.eventType = EVENTTYPE_FILE;
+ dbei.flags = DBEF_SENT;
+ dbei.timestamp = time(NULL);
+ #if defined( _UNICODE )
+ char *szFileNames = Utf8EncodeT(dat->szFilenames), *szMsg = Utf8EncodeT(dat->szMsg);
+ dbei.flags |= DBEF_UTF;
+ #else
+ char *szFileNames = dat->szFilenames, *szMsg = dat->szMsg;
+ #endif
+
+ dbei.cbBlob = sizeof(DWORD) + lstrlenA(szFileNames)+lstrlenA(szMsg)+2;
+ dbei.pBlob=(PBYTE)mir_alloc(dbei.cbBlob);
+ *(PDWORD)dbei.pBlob=0;
+ lstrcpyA((char*)dbei.pBlob+sizeof(DWORD),szFileNames);
+ lstrcpyA((char*)dbei.pBlob+sizeof(DWORD)+lstrlenA(szFileNames)+1,szMsg);
+
+ #if defined( _UNICODE )
+ mir_free( szFileNames ), mir_free( szMsg );
+ #endif
+}
+
+static void __cdecl RunVirusScannerThread(struct virusscanthreadstartinfo *info)
+{
+ PROCESS_INFORMATION pi;
+ STARTUPINFO si={0};
+ DBVARIANT dbv;
+ TCHAR szCmdLine[768];
+
+ if (!DBGetContactSettingTString(NULL,"SRFile", "ScanCmdLine", &dbv))
+ {
+ if(dbv.ptszVal[0])
+ {
+ TCHAR *pszReplace;
+ si.cb=sizeof(si);
+ pszReplace = _tcsstr(dbv.ptszVal, _T("%f"));
+ if (pszReplace)
+ {
+ if ( info->szFile[_tcslen(info->szFile) - 1] == '\\')
+ info->szFile[_tcslen(info->szFile) - 1] = '\0';
+ *pszReplace = 0;
+ mir_sntprintf(szCmdLine, SIZEOF(szCmdLine), _T("%s\"%s\"%s"), dbv.ptszVal, info->szFile, pszReplace+2);
+ }
+ else lstrcpyn(szCmdLine, dbv.ptszVal, SIZEOF(szCmdLine));
+ if(CreateProcess(NULL,szCmdLine,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi)) {
+ if(WaitForSingleObject(pi.hProcess,3600*1000)==WAIT_OBJECT_0)
+ PostMessage(info->hwndReply,M_VIRUSSCANDONE,info->returnCode,0);
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ }
+ }
+ DBFreeVariant(&dbv);
+ }
+ mir_free(info->szFile);
+ mir_free(info);
+}
+
+static void SetFilenameControls(HWND hwndDlg, struct FileDlgData *dat, PROTOFILETRANSFERSTATUS *fts)
+{
+ TCHAR msg[MAX_PATH];
+ TCHAR *fnbuf = NULL, *fn = NULL;
+ SHFILEINFO shfi = {0};
+
+ if ( fts->tszCurrentFile ) {
+ fnbuf = mir_tstrdup( fts->tszCurrentFile );
+ if (( fn = _tcsrchr( fnbuf, '\\' )) == NULL )
+ fn = fnbuf;
+ else fn++;
+ }
+
+ if (dat->hIcon) DestroyIcon(dat->hIcon); dat->hIcon = NULL;
+
+ if (fn && (fts->totalFiles > 1)) {
+ mir_sntprintf(msg, SIZEOF(msg), _T("%s: %s (%d %s %d)"),
+ cli.pfnGetContactDisplayName( fts->hContact, 0 ),
+ fn, fts->currentFileNumber+1, TranslateT("of"), fts->totalFiles);
+
+ SHGetFileInfo(fn, FILE_ATTRIBUTE_DIRECTORY, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES|SHGFI_ICON|SHGFI_SMALLICON);
+ dat->hIcon = shfi.hIcon;
+ }
+ else if (fn) {
+ mir_sntprintf(msg, SIZEOF(msg), _T("%s: %s"), cli.pfnGetContactDisplayName( fts->hContact, 0 ), fn);
+
+ SHGetFileInfo(fn, FILE_ATTRIBUTE_NORMAL, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES|SHGFI_ICON|SHGFI_SMALLICON);
+ dat->hIcon = shfi.hIcon;
+ }
+ else {
+ lstrcpyn(msg, cli.pfnGetContactDisplayName( fts->hContact, 0 ), SIZEOF(msg));
+ HICON hIcon = LoadSkinIcon(SKINICON_OTHER_DOWNARROW);
+ dat->hIcon = CopyIcon(hIcon);
+ IconLib_ReleaseIcon(hIcon, NULL);
+ }
+
+ mir_free( fnbuf );
+
+ SendDlgItemMessage(hwndDlg, IDC_FILEICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM)dat->hIcon);
+ SetDlgItemText(hwndDlg, IDC_CONTACTNAME, msg);
+}
+
+enum { FTS_TEXT, FTS_PROGRESS, FTS_OPEN };
+static void SetFtStatus(HWND hwndDlg, TCHAR *text, int mode)
+{
+ SetDlgItemText(hwndDlg,IDC_STATUS,TranslateTS(text));
+ SetDlgItemText(hwndDlg,IDC_TRANSFERCOMPLETED,TranslateTS(text));
+
+ ShowWindow(GetDlgItem(hwndDlg,IDC_STATUS), (mode == FTS_TEXT)?SW_SHOW:SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_ALLFILESPROGRESS), (mode == FTS_PROGRESS)?SW_SHOW:SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_TRANSFERCOMPLETED), (mode == FTS_OPEN)?SW_SHOW:SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_FILEICON), (mode == FTS_OPEN)?SW_SHOW:SW_HIDE);
+}
+
+static void HideProgressControls(HWND hwndDlg)
+{
+ RECT rc;
+ char buf[64];
+
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_ALLPRECENTS), &rc);
+ MapWindowPoints(NULL, hwndDlg, (LPPOINT)&rc, 2);
+ SetWindowPos(hwndDlg, NULL, 0, 0, 100, rc.bottom+3, SWP_NOMOVE|SWP_NOZORDER);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_ALLTRANSFERRED), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_ALLSPEED), SW_HIDE);
+
+ _strtime(buf);
+ SetDlgItemTextA(hwndDlg, IDC_ALLPRECENTS, buf);
+
+ PostMessage(GetParent(hwndDlg), WM_FT_RESIZE, 0, (LPARAM)hwndDlg);
+}
+
+static int FileTransferDlgResizer(HWND, LPARAM, UTILRESIZECONTROL *urc)
+{
+ switch(urc->wId) {
+ case IDC_CONTACTNAME:
+ case IDC_STATUS:
+ case IDC_ALLFILESPROGRESS:
+ case IDC_TRANSFERCOMPLETED:
+ return RD_ANCHORX_WIDTH|RD_ANCHORY_TOP;
+ case IDC_FRAME:
+ return RD_ANCHORX_WIDTH|RD_ANCHORY_BOTTOM;
+ case IDC_ALLPRECENTS:
+ case IDCANCEL:
+ case IDC_OPENFILE:
+ case IDC_OPENFOLDER:
+ return RD_ANCHORX_RIGHT|RD_ANCHORY_TOP;
+
+ case IDC_ALLTRANSFERRED:
+ urc->rcItem.right = urc->rcItem.left + (urc->rcItem.right - urc->rcItem.left - urc->dlgOriginalSize.cx + urc->dlgNewSize.cx) / 3;
+ return RD_ANCHORX_CUSTOM|RD_ANCHORY_CUSTOM;
+
+ case IDC_ALLSPEED:
+ urc->rcItem.right = urc->rcItem.right - urc->dlgOriginalSize.cx + urc->dlgNewSize.cx;
+ urc->rcItem.left = urc->rcItem.left + (urc->rcItem.right - urc->rcItem.left) / 3;
+ return RD_ANCHORX_CUSTOM|RD_ANCHORY_CUSTOM;
+ }
+ return RD_ANCHORX_LEFT|RD_ANCHORY_TOP;
+}
+
+INT_PTR CALLBACK DlgProcFileTransfer(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ FileDlgData *dat = (FileDlgData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ dat = (FileDlgData*)lParam;
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat);
+ dat->hNotifyEvent=HookEventMessage(ME_PROTO_ACK,hwndDlg,HM_RECVEVENT);
+ dat->transferStatus.currentFileNumber = -1;
+ if(dat->send) {
+ dat->fs=(HANDLE)CallContactService(dat->hContact,PSS_FILET,(WPARAM)dat->szMsg,(LPARAM)dat->files);
+ SetFtStatus(hwndDlg, LPGENT("Request sent, waiting for acceptance..."), FTS_TEXT);
+ SetOpenFileButtonStyle(GetDlgItem(hwndDlg,IDC_OPENFILE),1);
+ dat->waitingForAcceptance=1;
+ // hide "open" button since it may cause potential access violations...
+ ShowWindow(GetDlgItem(hwndDlg, IDC_OPENFILE), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_OPENFOLDER), SW_HIDE);
+ }
+ else { //recv
+ CreateDirectoryTreeT(dat->szSavePath);
+ dat->fs=(HANDLE)CallContactService(dat->hContact,PSS_FILEALLOWT,(WPARAM)dat->fs,(LPARAM)dat->szSavePath);
+ dat->transferStatus.tszWorkingDir = mir_tstrdup(dat->szSavePath);
+ if(DBGetContactSettingByte(dat->hContact,"CList","NotOnList",0)) dat->resumeBehaviour=FILERESUME_ASK;
+ else dat->resumeBehaviour=DBGetContactSettingByte(NULL,"SRFile","IfExists",FILERESUME_ASK);
+ SetFtStatus(hwndDlg, LPGENT("Waiting for connection..."), FTS_TEXT);
+ }
+ {
+ /* check we actually got an fs handle back from the protocol */
+ if (!dat->fs) {
+ SetFtStatus(hwndDlg, LPGENT("Unable to initiate transfer."), FTS_TEXT);
+ dat->waitingForAcceptance=0;
+ }
+ }
+ { LOGFONT lf;
+ HFONT hFont;
+ hFont=(HFONT)SendDlgItemMessage(hwndDlg,IDC_CONTACTNAME,WM_GETFONT,0,0);
+ GetObject(hFont,sizeof(lf),&lf);
+ lf.lfWeight=FW_BOLD;
+ hFont=CreateFontIndirect(&lf);
+ SendDlgItemMessage(hwndDlg,IDC_CONTACTNAME,WM_SETFONT,(WPARAM)hFont,0);
+ }
+
+ { SHFILEINFO shfi = {0};
+ SHGetFileInfo(_T(""), FILE_ATTRIBUTE_DIRECTORY, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES|SHGFI_ICON|SHGFI_SMALLICON);
+ dat->hIconFolder = shfi.hIcon;
+ }
+
+ dat->hIcon = NULL;
+
+ SendDlgItemMessage(hwndDlg, IDC_CONTACT, BM_SETIMAGE, IMAGE_ICON,
+ (LPARAM)LoadSkinnedProtoIcon((char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)dat->hContact, 0), ID_STATUS_ONLINE));
+ SendDlgItemMessage(hwndDlg, IDC_CONTACT, BUTTONADDTOOLTIP, (WPARAM)LPGEN("Contact menu"), 0);
+ SendDlgItemMessage(hwndDlg, IDC_CONTACT, BUTTONSETASFLATBTN, 0, 0);
+
+ Button_SetIcon_IcoLib(hwndDlg, IDC_OPENFILE, SKINICON_OTHER_DOWNARROW, LPGEN("Open..."));
+ SendDlgItemMessage(hwndDlg, IDC_OPENFILE, BUTTONSETASPUSHBTN, 0, 0);
+
+ SendDlgItemMessage(hwndDlg, IDC_OPENFOLDER, BM_SETIMAGE, IMAGE_ICON, (LPARAM)dat->hIconFolder);
+ SendDlgItemMessage(hwndDlg, IDC_OPENFOLDER, BUTTONADDTOOLTIP, (WPARAM)LPGEN("Open folder"), 0);
+ SendDlgItemMessage(hwndDlg, IDC_OPENFOLDER, BUTTONSETASFLATBTN, 0, 0);
+
+ Button_SetIcon_IcoLib(hwndDlg, IDCANCEL, SKINICON_OTHER_DELETE, LPGEN("Cancel"));
+
+ SetDlgItemText(hwndDlg, IDC_CONTACTNAME, cli.pfnGetContactDisplayName( dat->hContact, 0 ));
+
+ if(!dat->waitingForAcceptance) SetTimer(hwndDlg,1,1000,NULL);
+ return TRUE;
+ case WM_TIMER:
+ MoveMemory(dat->bytesRecvedHistory+1,dat->bytesRecvedHistory,sizeof(dat->bytesRecvedHistory)-sizeof(dat->bytesRecvedHistory[0]));
+ dat->bytesRecvedHistory[0]=dat->transferStatus.totalProgress;
+ if ( dat->bytesRecvedHistorySize < SIZEOF(dat->bytesRecvedHistory))
+ dat->bytesRecvedHistorySize++;
+
+ { TCHAR szSpeed[32], szTime[32], szDisplay[96];
+ SYSTEMTIME st;
+ ULARGE_INTEGER li;
+ FILETIME ft;
+
+ GetSensiblyFormattedSize((dat->bytesRecvedHistory[0]-dat->bytesRecvedHistory[dat->bytesRecvedHistorySize-1])/dat->bytesRecvedHistorySize,szSpeed,SIZEOF(szSpeed),0,1,NULL);
+ if(dat->bytesRecvedHistory[0]==dat->bytesRecvedHistory[dat->bytesRecvedHistorySize-1])
+ lstrcpy(szTime,_T("??:??:??"));
+ else {
+ li.QuadPart=BIGI(10000000)*(dat->transferStatus.currentFileSize-dat->transferStatus.currentFileProgress)*dat->bytesRecvedHistorySize/(dat->bytesRecvedHistory[0]-dat->bytesRecvedHistory[dat->bytesRecvedHistorySize-1]);
+ ft.dwHighDateTime=li.HighPart; ft.dwLowDateTime=li.LowPart;
+ FileTimeToSystemTime(&ft,&st);
+ GetTimeFormat(LOCALE_USER_DEFAULT,TIME_FORCE24HOURFORMAT|TIME_NOTIMEMARKER,&st,NULL,szTime,SIZEOF(szTime));
+ }
+ if(dat->bytesRecvedHistory[0]!=dat->bytesRecvedHistory[dat->bytesRecvedHistorySize-1]) {
+ li.QuadPart=BIGI(10000000)*(dat->transferStatus.totalBytes-dat->transferStatus.totalProgress)*dat->bytesRecvedHistorySize/(dat->bytesRecvedHistory[0]-dat->bytesRecvedHistory[dat->bytesRecvedHistorySize-1]);
+ ft.dwHighDateTime=li.HighPart; ft.dwLowDateTime=li.LowPart;
+ FileTimeToSystemTime(&ft,&st);
+ GetTimeFormat(LOCALE_USER_DEFAULT,TIME_FORCE24HOURFORMAT|TIME_NOTIMEMARKER,&st,NULL,szTime,SIZEOF(szTime));
+ }
+
+ mir_sntprintf(szDisplay,SIZEOF(szDisplay),_T("%s/%s (%s %s)"),szSpeed,TranslateT("sec"),szTime,TranslateT("remaining"));
+ SetDlgItemText(hwndDlg,IDC_ALLSPEED,szDisplay);
+ }
+ break;
+
+ case WM_MEASUREITEM:
+ return CallService(MS_CLIST_MENUMEASUREITEM,wParam,lParam);
+
+ case WM_DRAWITEM:
+ return CallService(MS_CLIST_MENUDRAWITEM,wParam,lParam);
+
+ case WM_FT_CLEANUP:
+ if (!dat->fs)
+ {
+ PostMessage(GetParent(hwndDlg), WM_FT_REMOVE, 0, (LPARAM)hwndDlg);
+ DestroyWindow(hwndDlg);
+ }
+ break;
+
+ case WM_COMMAND:
+ if ( CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam),MPCF_CONTACTMENU), (LPARAM)dat->hContact ))
+ break;
+
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+ case IDCANCEL:
+ PostMessage(GetParent(hwndDlg), WM_FT_REMOVE, 0, (LPARAM)hwndDlg);
+ DestroyWindow(hwndDlg);
+ break;
+
+ case IDC_CONTACT:
+ { RECT rc;
+ HMENU hMenu=(HMENU)CallService(MS_CLIST_MENUBUILDCONTACT,(WPARAM)dat->hContact,0);
+ GetWindowRect((HWND)lParam,&rc);
+ TrackPopupMenu(hMenu,0,rc.left,rc.bottom,0,hwndDlg,NULL);
+ DestroyMenu(hMenu);
+ break;
+ }
+
+ case IDC_TRANSFERCOMPLETED:
+ if (dat->transferStatus.currentFileNumber <= 1 && CheckVirusScanned(hwndDlg, dat, 0))
+ {
+ ShellExecute(NULL, NULL, dat->files[0], NULL, NULL, SW_SHOW);
+ break;
+ }
+
+ case IDC_OPENFOLDER:
+ if ( dat )
+ {
+ TCHAR* path = dat->transferStatus.tszWorkingDir;
+ if (!path || !path[0])
+ {
+ path = NEWTSTR_ALLOCA(dat->transferStatus.tszCurrentFile);
+ TCHAR* p = _tcsrchr(path, '\\'); if (p) *p = 0;
+ }
+
+ if (path) ShellExecute(NULL, _T("open"), path, NULL, NULL, SW_SHOW);
+ }
+ break;
+
+ case IDC_OPENFILE:
+ {
+ TCHAR **files;
+ HMENU hMenu;
+ RECT rc;
+ int ret;
+
+ if (dat->send)
+ if (dat->files == NULL)
+ files = dat->transferStatus.ptszFiles;
+ else
+ files = dat->files;
+ else
+ files=dat->files;
+
+ hMenu = CreatePopupMenu();
+ AppendMenu(hMenu, MF_STRING, 1, TranslateT("Open folder"));
+ AppendMenu(hMenu, MF_SEPARATOR, 0, 0);
+
+ if (files && *files)
+ {
+ int i, limit;
+ TCHAR *pszFilename,*pszNewFileName;
+
+ if (dat->send)
+ limit = dat->transferStatus.totalFiles;
+ else
+ limit = dat->transferStatus.currentFileNumber;
+
+ // Loop over all transfered files and add them to the menu
+ for (i = 0; i < limit; i++) {
+ pszFilename = _tcsrchr(files[i], '\\');
+ if (pszFilename == NULL)
+ pszFilename = files[i];
+ else
+ pszFilename++;
+ {
+ if (pszFilename) {
+ size_t cbFileNameLen = _tcslen(pszFilename);
+
+ pszNewFileName = (TCHAR*)mir_alloc( cbFileNameLen*2*sizeof( TCHAR ));
+ TCHAR *p = pszNewFileName;
+ for (size_t pszlen=0; pszlen < cbFileNameLen; pszlen++) {
+ *p++ = pszFilename[pszlen];
+ if (pszFilename[pszlen]=='&')
+ *p++ = '&';
+ }
+ *p = '\0';
+ AppendMenu(hMenu, MF_STRING, i+10, pszNewFileName);
+ mir_free(pszNewFileName);
+ }
+ }
+ }
+ }
+
+ GetWindowRect((HWND)lParam, &rc);
+ CheckDlgButton(hwndDlg, IDC_OPENFILE, BST_CHECKED);
+ ret = TrackPopupMenu(hMenu, TPM_RETURNCMD|TPM_RIGHTALIGN, rc.right, rc.bottom, 0, hwndDlg, NULL);
+ CheckDlgButton(hwndDlg, IDC_OPENFILE, BST_UNCHECKED);
+ DestroyMenu(hMenu);
+
+ if (ret == 1)
+ {
+ TCHAR* path = dat->transferStatus.tszWorkingDir;
+ if (!path || !path[0])
+ {
+ path = NEWTSTR_ALLOCA(dat->transferStatus.tszCurrentFile);
+ TCHAR* p = _tcsrchr(path, '\\'); if (p) *p = 0;
+ }
+
+ if (path) ShellExecute(NULL, _T("open"), path, NULL, NULL, SW_SHOW);
+ }
+ else if (ret && CheckVirusScanned(hwndDlg, dat, ret))
+ ShellExecute(NULL, NULL, files[ret-10], NULL, NULL, SW_SHOW);
+
+ break;
+ }
+ }
+ break;
+ case M_FILEEXISTSDLGREPLY:
+ { PROTOFILERESUME *pfr=(PROTOFILERESUME*)lParam;
+ TCHAR *szOriginalFilename=(TCHAR*)wParam;
+ char *szProto=(char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)dat->hContact,0);
+
+ EnableWindow(hwndDlg,TRUE);
+ switch(pfr->action) {
+ case FILERESUME_CANCEL:
+ if (dat->fs) CallContactService(dat->hContact,PSS_FILECANCEL,(WPARAM)dat->fs,0);
+ dat->fs=NULL;
+ mir_free(szOriginalFilename);
+ if(pfr->szFilename) mir_free((char*)pfr->szFilename);
+ mir_free(pfr);
+ return 0;
+ case FILERESUME_RESUMEALL:
+ case FILERESUME_OVERWRITEALL:
+ dat->resumeBehaviour=pfr->action;
+ pfr->action&=~FILERESUMEF_ALL;
+ break;
+ case FILERESUME_RENAMEALL:
+ pfr->action=FILERESUME_RENAME;
+ { TCHAR *pszExtension,*pszFilename;
+ int i;
+ if((pszFilename = _tcsrchr(szOriginalFilename,'\\'))==NULL) pszFilename=szOriginalFilename;
+ if((pszExtension = _tcsrchr(pszFilename+1,'.'))==NULL) pszExtension=pszFilename+lstrlen(pszFilename);
+ if(pfr->szFilename) mir_free((TCHAR*)pfr->szFilename);
+ pfr->szFilename = (TCHAR*)mir_alloc(sizeof(TCHAR)*((pszExtension-szOriginalFilename)+21+lstrlen(pszExtension)));
+ for(i=1;;i++) {
+ _stprintf((TCHAR*)pfr->szFilename,_T("%.*s (%u)%s"),pszExtension-szOriginalFilename,szOriginalFilename,i,pszExtension);
+ if(_taccess(pfr->szFilename,0)!=0)
+ break;
+ }
+ }
+ break;
+ }
+ mir_free(szOriginalFilename);
+ CallProtoService(szProto,PS_FILERESUMET,(WPARAM)dat->fs,(LPARAM)pfr);
+ if(pfr->szFilename) mir_free((char*)pfr->szFilename);
+ mir_free(pfr);
+ break;
+ }
+ case HM_RECVEVENT:
+ { ACKDATA *ack=(ACKDATA*)lParam;
+ if (ack->hProcess!=dat->fs) break; /* icq abuses this sometimes */
+ if(ack->hContact!=dat->hContact) break;
+ if(ack->type!=ACKTYPE_FILE) break;
+
+ if(dat->waitingForAcceptance) {
+ SetTimer(hwndDlg,1,1000,NULL);
+ dat->waitingForAcceptance=0;
+ }
+ switch(ack->result) {
+ case ACKRESULT_SENTREQUEST: SetFtStatus(hwndDlg, LPGENT("Decision sent"), FTS_TEXT); break;
+ case ACKRESULT_CONNECTING: SetFtStatus(hwndDlg, LPGENT("Connecting..."), FTS_TEXT); break;
+ case ACKRESULT_CONNECTPROXY: SetFtStatus(hwndDlg, LPGENT("Connecting to proxy..."), FTS_TEXT); break;
+ case ACKRESULT_CONNECTED: SetFtStatus(hwndDlg, LPGENT("Connected"), FTS_TEXT); break;
+ case ACKRESULT_LISTENING: SetFtStatus(hwndDlg, LPGENT("Waiting for connection..."), FTS_TEXT); break;
+ case ACKRESULT_INITIALISING: SetFtStatus(hwndDlg, LPGENT("Initialising..."), FTS_TEXT); break;
+ case ACKRESULT_NEXTFILE:
+ SetFtStatus(hwndDlg, LPGENT("Moving to next file..."), FTS_TEXT);
+ SetDlgItemTextA(hwndDlg,IDC_FILENAME,"");
+ if(dat->transferStatus.currentFileNumber==1 && dat->transferStatus.totalFiles>1 && !dat->send)
+ SetOpenFileButtonStyle(GetDlgItem(hwndDlg,IDC_OPENFILE),1);
+ if(dat->transferStatus.currentFileNumber!=-1 && dat->files && !dat->send && DBGetContactSettingByte(NULL,"SRFile","UseScanner",VIRUSSCAN_DISABLE)==VIRUSSCAN_DURINGDL) {
+ if(GetFileAttributes(dat->files[dat->transferStatus.currentFileNumber])&FILE_ATTRIBUTE_DIRECTORY)
+ PostMessage(hwndDlg,M_VIRUSSCANDONE,dat->transferStatus.currentFileNumber,0);
+ else {
+ virusscanthreadstartinfo *vstsi;
+ vstsi=(struct virusscanthreadstartinfo*)mir_alloc(sizeof(struct virusscanthreadstartinfo));
+ vstsi->hwndReply = hwndDlg;
+ vstsi->szFile = mir_tstrdup(dat->files[dat->transferStatus.currentFileNumber]);
+ vstsi->returnCode = dat->transferStatus.currentFileNumber;
+ forkthread((void (*)(void*))RunVirusScannerThread,0,vstsi);
+ }
+ }
+ break;
+ case ACKRESULT_FILERESUME:
+ {
+ UpdateProtoFileTransferStatus(&dat->transferStatus, (PROTOFILETRANSFERSTATUS*)ack->lParam);
+ PROTOFILETRANSFERSTATUS *fts = &dat->transferStatus;
+
+ SetFilenameControls( hwndDlg, dat, fts );
+ int res = _taccess( fts->tszCurrentFile, 0 );
+ if ( res )
+ break;
+
+ SetFtStatus(hwndDlg, LPGENT("File already exists"), FTS_TEXT);
+ if(dat->resumeBehaviour==FILERESUME_ASK) {
+ TDlgProcFileExistsParam param = { hwndDlg, fts };
+ ShowWindow(hwndDlg,SW_SHOWNORMAL);
+ CreateDialogParam(hMirandaInst,MAKEINTRESOURCE(IDD_FILEEXISTS),hwndDlg,DlgProcFileExists,(LPARAM)¶m);
+ EnableWindow(hwndDlg,FALSE);
+ }
+ else {
+ PROTOFILERESUME *pfr;
+ pfr=(PROTOFILERESUME*)mir_alloc(sizeof(PROTOFILERESUME));
+ pfr->action = dat->resumeBehaviour;
+ pfr->szFilename = NULL;
+ PostMessage(hwndDlg,M_FILEEXISTSDLGREPLY,(WPARAM)mir_tstrdup(fts->tszCurrentFile),(LPARAM)pfr);
+ }
+ SetWindowLongPtr(hwndDlg,DWLP_MSGRESULT,1);
+ return TRUE;
+ }
+ case ACKRESULT_DATA:
+ {
+ PROTOFILETRANSFERSTATUS *fts=(PROTOFILETRANSFERSTATUS*)ack->lParam;
+ TCHAR str[64], str2[64], szSizeDone[32], szSizeTotal[32];//,*contactName;
+ int units;
+
+ if ( dat->fileVirusScanned==NULL )
+ dat->fileVirusScanned=(int*)mir_calloc(sizeof(int) * fts->totalFiles);
+
+ // This needs to be here - otherwise we get holes in the files array
+ if (!dat->send)
+ {
+ if (dat->files == NULL)
+ dat->files = (TCHAR**)mir_calloc((fts->totalFiles + 1) * sizeof(TCHAR*));
+ if (fts->currentFileNumber < fts->totalFiles && dat->files[fts->currentFileNumber] == NULL)
+ {
+ if (fts->cbSize == sizeof(PROTOFILETRANSFERSTATUS_V1))
+ {
+ PROTOFILETRANSFERSTATUS_V1 *fts1 = (PROTOFILETRANSFERSTATUS_V1*)fts;
+ dat->files[fts->currentFileNumber] = PFTS_StringToTchar(0, (PROTOCHAR*)fts1->currentFile);
+ }
+ else
+ dat->files[fts->currentFileNumber] = PFTS_StringToTchar(fts->flags, fts->tszCurrentFile);
+ }
+ }
+
+ /* HACK: for 0.3.3, limit updates to around 1.1 ack per second */
+ if (fts->totalProgress != fts->totalBytes && GetTickCount() < (dat->dwTicks + 650)) break; // the last update was less than a second ago!
+ dat->dwTicks = GetTickCount();
+
+ // Update local transfer status with data from protocol
+ UpdateProtoFileTransferStatus(&dat->transferStatus, fts);
+ fts = &dat->transferStatus;
+
+ bool firstTime = false;
+ if ((GetWindowLong(GetDlgItem(hwndDlg, IDC_ALLFILESPROGRESS), GWL_STYLE) & WS_VISIBLE) == 0)
+ {
+ SetFtStatus(hwndDlg, ( fts->flags & PFTS_SENDING ) ? LPGENT("Sending...") : LPGENT("Receiving..."), FTS_PROGRESS);
+ SetFilenameControls(hwndDlg, dat, fts);
+ firstTime = true;
+ }
+
+ const unsigned long lastPos = SendDlgItemMessage(hwndDlg, IDC_ALLFILESPROGRESS, PBM_GETPOS, 0, 0);
+ const unsigned long nextPos = fts->totalBytes ? (BIGI(100) * fts->totalProgress / fts->totalBytes) : 0;
+ if (lastPos != nextPos || firstTime)
+ {
+ SendDlgItemMessage(hwndDlg, IDC_ALLFILESPROGRESS, PBM_SETPOS, nextPos, 0);
+ mir_sntprintf(str, SIZEOF(str), _T("%u%%"), nextPos);
+ SetDlgItemText(hwndDlg, IDC_ALLPRECENTS, str);
+ }
+
+ GetSensiblyFormattedSize(fts->totalBytes, szSizeTotal, SIZEOF(szSizeTotal), 0, 1, &units);
+ GetSensiblyFormattedSize(fts->totalProgress, szSizeDone, SIZEOF(szSizeDone), units, 0, NULL);
+ mir_sntprintf(str, SIZEOF(str), _T("%s/%s"), szSizeDone, szSizeTotal);
+ str2[0] = 0;
+ GetDlgItemText(hwndDlg, IDC_ALLTRANSFERRED, str2, SIZEOF(str2));
+ if (_tcscmp(str, str2)) SetDlgItemText(hwndDlg, IDC_ALLTRANSFERRED, str);
+ break;
+ }
+
+ case ACKRESULT_SUCCESS:
+ case ACKRESULT_FAILED:
+ case ACKRESULT_DENIED:
+ {
+
+ HideProgressControls(hwndDlg);
+ KillTimer(hwndDlg,1);
+ if (!dat->send)
+ SetOpenFileButtonStyle(GetDlgItem(hwndDlg,IDC_OPENFILE),1);
+ SetDlgItemText(hwndDlg,IDCANCEL,TranslateT("Close"));
+ if (dat->hNotifyEvent)
+ UnhookEvent(dat->hNotifyEvent);
+ dat->hNotifyEvent=NULL;
+
+ if (ack->result == ACKRESULT_DENIED)
+ {
+ dat->fs=NULL; /* protocol will free structure */
+ SkinPlaySound("FileDenied");
+ SetFtStatus(hwndDlg, LPGENT("File transfer denied"), FTS_TEXT);
+ } else if (ack->result == ACKRESULT_FAILED)
+ {
+ dat->fs=NULL; /* protocol will free structure */
+ SkinPlaySound("FileFailed");
+ SetFtStatus(hwndDlg, LPGENT("File transfer failed"), FTS_TEXT);
+ } else {
+ SkinPlaySound("FileDone");
+ if (dat->send)
+ {
+ dat->fs=NULL; /* protocol will free structure */
+ SetFtStatus(hwndDlg, LPGENT("Transfer completed."), FTS_TEXT);
+
+ DBEVENTINFO dbei={0};
+ FillSendData( dat, dbei );
+ CallService(MS_DB_EVENT_ADD,(WPARAM)dat->hContact,(LPARAM)&dbei);
+ if (dbei.pBlob)
+ mir_free(dbei.pBlob);
+ dat->files=NULL; //protocol library frees this
+
+ } else {
+ SetFtStatus(hwndDlg,
+ (dat->transferStatus.totalFiles == 1) ?
+ LPGENT("Transfer completed, open file.") :
+ LPGENT("Transfer completed, open folder."),
+ FTS_OPEN);
+
+ int useScanner=DBGetContactSettingByte(NULL,"SRFile","UseScanner",VIRUSSCAN_DISABLE);
+ if (useScanner!=VIRUSSCAN_DISABLE) {
+ struct virusscanthreadstartinfo *vstsi;
+ vstsi=(struct virusscanthreadstartinfo*)mir_alloc(sizeof(struct virusscanthreadstartinfo));
+ vstsi->hwndReply=hwndDlg;
+ if(useScanner==VIRUSSCAN_DURINGDL) {
+ vstsi->returnCode=dat->transferStatus.currentFileNumber;
+ if ( GetFileAttributes(dat->files[dat->transferStatus.currentFileNumber])&FILE_ATTRIBUTE_DIRECTORY) {
+ PostMessage(hwndDlg,M_VIRUSSCANDONE,vstsi->returnCode,0);
+ mir_free(vstsi);
+ vstsi=NULL;
+ }
+ else vstsi->szFile = mir_tstrdup(dat->files[dat->transferStatus.currentFileNumber]);
+ }
+ else {
+ vstsi->szFile = mir_tstrdup(dat->transferStatus.tszWorkingDir);
+ vstsi->returnCode = -1;
+ }
+ SetFtStatus(hwndDlg, LPGENT("Scanning for viruses..."), FTS_TEXT);
+ if(vstsi) forkthread((void (*)(void*))RunVirusScannerThread,0,vstsi);
+ } else {
+ dat->fs=NULL; /* protocol will free structure */
+ }
+ dat->transferStatus.currentFileNumber=dat->transferStatus.totalFiles;
+ } // else dat->send
+
+ } // else ack->result
+
+ PostMessage(GetParent(hwndDlg), WM_FT_COMPLETED, ack->result, (LPARAM)hwndDlg);
+ break;
+ }
+ break;
+ } // switch ack->result
+ } break; // case HM_RECVEVENT
+ case M_VIRUSSCANDONE:
+ { int done=1,i;
+ if((int)wParam==-1) {
+ for(i=0;i<dat->transferStatus.totalFiles;i++) dat->fileVirusScanned[i]=1;
+ }
+ else {
+ dat->fileVirusScanned[wParam]=1;
+ for(i=0;i<dat->transferStatus.totalFiles;i++) if(!dat->fileVirusScanned[i]) {done=0; break;}
+ }
+ if (done)
+ {
+ dat->fs=NULL; /* protocol will free structure */
+ SetFtStatus(hwndDlg, LPGENT("Transfer and virus scan complete"), FTS_TEXT);
+ }
+ break;
+ }
+ case WM_SIZE:
+ {
+ UTILRESIZEDIALOG urd={0};
+ urd.cbSize=sizeof(urd);
+ urd.hwndDlg=hwndDlg;
+ urd.hInstance=hMirandaInst;
+ urd.lpTemplate=MAKEINTRESOURCEA(IDD_FILETRANSFERINFO);
+ urd.pfnResizer=FileTransferDlgResizer;
+ CallService(MS_UTILS_RESIZEDIALOG,0,(LPARAM)&urd);
+
+ RedrawWindow(GetDlgItem(hwndDlg, IDC_ALLTRANSFERRED), NULL, NULL, RDW_INVALIDATE|RDW_NOERASE);
+ RedrawWindow(GetDlgItem(hwndDlg, IDC_ALLSPEED), NULL, NULL, RDW_INVALIDATE|RDW_NOERASE);
+ RedrawWindow(GetDlgItem(hwndDlg, IDC_CONTACTNAME), NULL, NULL, RDW_INVALIDATE|RDW_NOERASE);
+ RedrawWindow(GetDlgItem(hwndDlg, IDC_STATUS), NULL, NULL, RDW_INVALIDATE|RDW_NOERASE);
+ break;
+ }
+ case WM_DESTROY:
+ KillTimer(hwndDlg, 1);
+
+ HFONT hFont = (HFONT)SendDlgItemMessage(hwndDlg,IDC_CONTACTNAME,WM_GETFONT,0,0);
+ DeleteObject(hFont);
+
+ Button_FreeIcon_IcoLib(hwndDlg, IDC_CONTACT);
+ Button_FreeIcon_IcoLib(hwndDlg, IDC_OPENFILE);
+ Button_FreeIcon_IcoLib(hwndDlg, IDCANCEL);
+
+ FreeFileDlgData(dat);
+ break;
+ }
+ return FALSE;
+}
+
+void FreeFileDlgData( FileDlgData* dat )
+{
+ if(dat->fs)
+ CallContactService(dat->hContact,PSS_FILECANCEL,(WPARAM)dat->fs,0);
+ dat->fs = NULL;
+
+ if (dat->hPreshutdownEvent) UnhookEvent(dat->hPreshutdownEvent);
+ if (dat->hNotifyEvent) UnhookEvent(dat->hNotifyEvent);
+ dat->hNotifyEvent = NULL;
+
+ FreeProtoFileTransferStatus(&dat->transferStatus);
+ FreeFilesMatrix(&dat->files);
+
+ mir_free(dat->fileVirusScanned);
+ Safe_DestroyIcon(dat->hIcon);
+ Safe_DestroyIcon(dat->hIconFolder);
+ mir_free(dat);
+}
diff --git a/src/modules/srfile/ftmanager.cpp b/src/modules/srfile/ftmanager.cpp new file mode 100644 index 0000000000..a219d2188a --- /dev/null +++ b/src/modules/srfile/ftmanager.cpp @@ -0,0 +1,592 @@ +/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2009 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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 "commonheaders.h"
+#include "file.h"
+
+static HWND hwndFtMgr = NULL;
+
+struct TFtMgrData
+{
+ HWND hwndIncoming;
+ HWND hwndOutgoing;
+
+ HANDLE hhkPreshutdown;
+ TBPFLAG errorState;
+};
+
+
+#define M_CALCPROGRESS (WM_USER + 200)
+struct TFtProgressData
+{
+ unsigned int init, run, scan;
+ unsigned __int64 totalBytes, totalProgress;
+};
+
+struct TLayoutWindowInfo
+{
+ HWND hwnd;
+ RECT rc;
+};
+
+struct TLayoutWindowList
+{
+ struct TLayoutWindowInfo **items;
+ int realCount, limit, increment;
+ FSortFunc sortFunc;
+};
+
+struct TFtPageData
+{
+ struct TLayoutWindowList *wnds;
+ int runningCount;
+ int height, dataHeight, scrollPos;
+};
+
+static void LayoutTransfers(HWND hwnd, struct TFtPageData *dat)
+{
+ int top = 0;
+ RECT rc;
+ GetClientRect(hwnd, &rc);
+
+ dat->scrollPos = GetScrollPos(hwnd, SB_VERT);
+ dat->height = rc.bottom - rc.top;
+
+ if (dat->wnds->realCount)
+ {
+ int i;
+ HDWP hdwp;
+
+ hdwp = BeginDeferWindowPos(dat->wnds->realCount);
+ top -= dat->scrollPos;
+ for (i = 0; i < dat->wnds->realCount; ++i)
+ {
+ int height = dat->wnds->items[i]->rc.bottom - dat->wnds->items[i]->rc.top;
+ hdwp = DeferWindowPos(hdwp, dat->wnds->items[i]->hwnd, NULL, 0, top, rc.right, height, SWP_NOZORDER);
+ top += height;
+ }
+ top += dat->scrollPos;
+ EndDeferWindowPos(hdwp);
+ }
+
+ dat->dataHeight = top;
+
+ {
+ SCROLLINFO si = {0};
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_DISABLENOSCROLL|SIF_PAGE|SIF_RANGE;
+ si.nPage = dat->height;
+ si.nMin = 0;
+ si.nMax = dat->dataHeight;
+ SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
+ }
+}
+
+static INT_PTR CALLBACK FtMgrPageDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct TFtPageData *dat = (struct TFtPageData *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ // Force scrollbar visibility
+ SCROLLINFO si = {0};
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_DISABLENOSCROLL;
+ SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
+
+ dat = (struct TFtPageData *)mir_alloc(sizeof(struct TFtPageData));
+ dat->wnds = (struct TLayoutWindowList *)List_Create(0, 1);
+ dat->scrollPos = 0;
+ dat->runningCount = 0;
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)dat);
+ break;
+ }
+
+ case WM_FT_ADD:
+ {
+ struct TLayoutWindowInfo *wnd = (struct TLayoutWindowInfo *)mir_alloc(sizeof(struct TLayoutWindowInfo));
+ wnd->hwnd = (HWND)lParam;
+ GetWindowRect(wnd->hwnd, &wnd->rc);
+ List_Insert((SortedList *)dat->wnds, wnd, dat->wnds->realCount);
+ LayoutTransfers(hwnd, dat);
+ dat->runningCount++;
+ PostMessage(GetParent(hwnd), WM_TIMER, 1, NULL);
+ break;
+ }
+
+ case WM_FT_RESIZE:
+ {
+ int i;
+ for (i = 0; i < dat->wnds->realCount; ++i)
+ if (dat->wnds->items[i]->hwnd == (HWND)lParam)
+ {
+ GetWindowRect(dat->wnds->items[i]->hwnd, &dat->wnds->items[i]->rc);
+ break;
+ }
+ LayoutTransfers(hwnd, dat);
+ break;
+ }
+
+ case WM_FT_REMOVE:
+ {
+ int i;
+ for (i = 0; i < dat->wnds->realCount; ++i)
+ if (dat->wnds->items[i]->hwnd == (HWND)lParam)
+ {
+ mir_free(dat->wnds->items[i]);
+ List_Remove((SortedList *)dat->wnds, i);
+ break;
+ }
+ LayoutTransfers(hwnd, dat);
+ break;
+ }
+
+ case WM_FT_COMPLETED:
+ { //wParam: { ACKRESULT_SUCCESS | ACKRESULT_FAILED | ACKRESULT_DENIED }
+ dat->runningCount--;
+ int i = 0;
+ while (i < dat->wnds->realCount)
+ {
+ // no error when canceling (WM_FT_REMOVE is send first, check if hwnd is still registered)
+ if (dat->wnds->items[i]->hwnd == (HWND)lParam)
+ {
+ SendMessage(GetParent(hwnd), WM_TIMER, 1, (LPARAM)wParam);
+ break;
+ }
+ ++i;
+ }
+ if (i == dat->wnds->realCount)
+ PostMessage(GetParent(hwnd), WM_TIMER, 1, NULL);
+
+ if(dat->runningCount == 0 && (int)wParam == ACKRESULT_SUCCESS && DBGetContactSettingByte(NULL,"SRFile","AutoClose",0))
+ ShowWindow(hwndFtMgr, SW_HIDE);
+ break;
+ }
+
+ case WM_FT_CLEANUP:
+ {
+ int i;
+ for (i = 0; i < dat->wnds->realCount; ++i)
+ SendMessage(dat->wnds->items[i]->hwnd, WM_FT_CLEANUP, wParam, lParam);
+ break;
+ }
+
+ case WM_SIZE:
+ {
+ LayoutTransfers(hwnd, dat);
+ break;
+ }
+
+ case WM_MOUSEWHEEL:
+ {
+ int zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
+ if (zDelta)
+ {
+ int i, nScrollLines = 0;
+ SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, (void*)&nScrollLines, 0);
+ for (i = 0; i < (nScrollLines + 1) / 2; i++ )
+ SendMessage(hwnd, WM_VSCROLL, (zDelta < 0) ? SB_LINEDOWN : SB_LINEUP, 0);
+ }
+
+ SetWindowLongPtr(hwnd, DWLP_MSGRESULT, 0);
+ return TRUE;
+ }
+
+ case WM_VSCROLL:
+ {
+ int pos = dat->scrollPos;
+ switch (LOWORD(wParam))
+ {
+ case SB_LINEDOWN:
+ pos += 15;
+ break;
+ case SB_LINEUP:
+ pos -= 15;
+ break;
+ case SB_PAGEDOWN:
+ pos += dat->height - 10;
+ break;
+ case SB_PAGEUP:
+ pos -= dat->height - 10;
+ break;
+ case SB_THUMBTRACK:
+ pos = HIWORD(wParam);
+ break;
+ }
+
+ if (pos > dat->dataHeight - dat->height) pos = dat->dataHeight - dat->height;
+ if (pos < 0) pos = 0;
+
+ if (dat->scrollPos != pos)
+ {
+ ScrollWindow(hwnd, 0, dat->scrollPos - pos, NULL, NULL);
+ SetScrollPos(hwnd, SB_VERT, pos, TRUE);
+ dat->scrollPos = pos;
+ }
+ break;
+ }
+
+ case M_PRESHUTDOWN:
+ {
+ int i;
+ for (i = 0; i < dat->wnds->realCount; ++i)
+ PostMessage(dat->wnds->items[i]->hwnd, WM_COMMAND, MAKEWPARAM(IDCANCEL, BN_CLICKED), 0);
+ break;
+ }
+
+ case WM_DESTROY:
+ {
+ int i;
+ for (i = 0; i < dat->wnds->realCount; ++i)
+ mir_free(dat->wnds->items[i]);
+ List_Destroy((SortedList *)dat->wnds);
+ mir_free(dat->wnds);
+ mir_free(dat);
+ break;
+ }
+
+ case M_CALCPROGRESS:
+ {
+ int i;
+ TFtProgressData * prg = (TFtProgressData *)wParam;
+ for (i = 0; i < dat->wnds->realCount; ++i)
+ {
+ struct FileDlgData *trdat = (struct FileDlgData *)GetWindowLongPtr(dat->wnds->items[i]->hwnd, GWLP_USERDATA);
+ if (trdat->transferStatus.totalBytes && trdat->fs && !trdat->send && (trdat->transferStatus.totalBytes == trdat->transferStatus.totalProgress))
+ {
+ prg->scan++;
+ } else if (trdat->transferStatus.totalBytes && trdat->fs)
+ { // in progress
+ prg->run++;
+ prg->totalBytes += trdat->transferStatus.totalBytes;
+ prg->totalProgress += trdat->transferStatus.totalProgress;
+ } else if (trdat->fs)
+ { // starting
+ prg->init++;
+ }
+
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+static INT_PTR CALLBACK FtMgrDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct TFtMgrData *dat = (struct TFtMgrData *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TCITEM tci = {0};
+ HWND hwndTab = GetDlgItem(hwnd, IDC_TABS);
+
+ TranslateDialogDefault(hwnd);
+ Window_SetIcon_IcoLib(hwnd, SKINICON_EVENT_FILE);
+
+ dat = (struct TFtMgrData *)mir_calloc(sizeof(struct TFtMgrData));
+
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)dat);
+
+ dat->hhkPreshutdown = HookEventMessage(ME_SYSTEM_PRESHUTDOWN, hwnd, M_PRESHUTDOWN);
+
+ dat->hwndIncoming = CreateDialog(hMirandaInst, MAKEINTRESOURCE(IDD_FTPAGE), hwnd, FtMgrPageDlgProc);
+ dat->hwndOutgoing = CreateDialog(hMirandaInst, MAKEINTRESOURCE(IDD_FTPAGE), hwnd, FtMgrPageDlgProc);
+ ShowWindow(dat->hwndIncoming, SW_SHOW);
+
+ tci.mask = TCIF_PARAM|TCIF_TEXT;
+ tci.pszText = TranslateT("Incoming");
+ tci.lParam = (LPARAM)dat->hwndIncoming;
+ TabCtrl_InsertItem(hwndTab, 0, &tci);
+ tci.pszText = TranslateT("Outgoing");
+ tci.lParam = (LPARAM)dat->hwndOutgoing;
+ TabCtrl_InsertItem(hwndTab, 1, &tci);
+
+ // Utils_RestoreWindowPosition(hwnd, NULL, "SRFile", "FtMgrDlg_");
+ SAVEWINDOWPOS swp;
+ swp.hwnd=hwnd; swp.hContact=NULL; swp.szModule="SRFile"; swp.szNamePrefix="FtMgrDlg_";
+ CallService(MS_UTILS_RESTOREWINDOWPOSITION, RWPF_NOACTIVATE, (LPARAM)&swp);
+
+ // Fall through to setup initial placement
+ }
+ case WM_SIZE:
+ {
+ RECT rc, rcButton;
+ HDWP hdwp;
+ HWND hwndTab = GetDlgItem(hwnd, IDC_TABS);
+
+ GetWindowRect(GetDlgItem(hwnd, IDCANCEL), &rcButton);
+ OffsetRect(&rcButton, -rcButton.left, -rcButton.top);
+
+ GetClientRect(hwnd, &rc);
+ InflateRect(&rc, -6, -6);
+
+ hdwp = BeginDeferWindowPos(3);
+
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwnd, IDC_CLEAR), NULL, rc.left, rc.bottom-rcButton.bottom, 0, 0, SWP_NOZORDER|SWP_NOSIZE);
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwnd, IDCANCEL), NULL, rc.right-rcButton.right, rc.bottom-rcButton.bottom, 0, 0, SWP_NOZORDER|SWP_NOSIZE);
+
+ rc.bottom -= rcButton.bottom + 5;
+
+ hdwp = DeferWindowPos(hdwp, hwndTab, NULL, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, SWP_NOZORDER);
+
+ EndDeferWindowPos(hdwp);
+
+ GetWindowRect(hwndTab, &rc);
+ MapWindowPoints(NULL, hwnd, (LPPOINT)&rc, 2);
+ TabCtrl_AdjustRect(hwndTab, FALSE, &rc);
+ InflateRect(&rc, -5, -5);
+
+ hdwp = BeginDeferWindowPos(2);
+
+ hdwp = DeferWindowPos(hdwp, dat->hwndIncoming, HWND_TOP, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, 0);
+ hdwp = DeferWindowPos(hdwp, dat->hwndOutgoing, HWND_TOP, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, 0);
+
+ EndDeferWindowPos(hdwp);
+
+ break;
+ }
+
+ case WM_MOUSEWHEEL:
+ {
+ if (IsWindowVisible(dat->hwndIncoming)) SendMessage(dat->hwndIncoming, msg, wParam, lParam);
+ if (IsWindowVisible(dat->hwndOutgoing)) SendMessage(dat->hwndOutgoing, msg, wParam, lParam);
+ break;
+ }
+
+ case WM_FT_SELECTPAGE:
+ {
+ TCITEM tci = {0};
+ HWND hwndTab = GetDlgItem(hwnd, IDC_TABS);
+
+ if (TabCtrl_GetCurSel(hwndTab) == (int)wParam) break;
+
+ tci.mask = TCIF_PARAM;
+
+ TabCtrl_GetItem(hwndTab, TabCtrl_GetCurSel(hwndTab), &tci);
+ ShowWindow((HWND)tci.lParam, SW_HIDE);
+
+ TabCtrl_SetCurSel(hwndTab, wParam);
+
+ TabCtrl_GetItem(hwndTab, TabCtrl_GetCurSel(hwndTab), &tci);
+ ShowWindow((HWND)tci.lParam, SW_SHOW);
+
+ break;
+ }
+
+ case WM_GETMINMAXINFO:
+ {
+ LPMINMAXINFO lpmmi = (LPMINMAXINFO)lParam;
+ lpmmi->ptMinTrackSize.x = 300;
+ lpmmi->ptMinTrackSize.y = 400;
+ return 0;
+ }
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case IDCANCEL:
+ PostMessage(hwnd, WM_CLOSE , 0, 0);
+ break;
+
+ case IDC_CLEAR:
+ PostMessage(dat->hwndIncoming, WM_FT_CLEANUP, 0, 0);
+ PostMessage(dat->hwndOutgoing, WM_FT_CLEANUP, 0, 0);
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ {
+ switch (((LPNMHDR)lParam)->idFrom)
+ {
+ case IDC_TABS:
+ {
+ HWND hwndTab = GetDlgItem(hwnd, IDC_TABS);
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case TCN_SELCHANGING:
+ {
+ TCITEM tci = {0};
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(hwndTab, TabCtrl_GetCurSel(hwndTab), &tci);
+ ShowWindow((HWND)tci.lParam, SW_HIDE);
+ break;
+ }
+
+ case TCN_SELCHANGE:
+ {
+ TCITEM tci = {0};
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(hwndTab, TabCtrl_GetCurSel(hwndTab), &tci);
+ ShowWindow((HWND)tci.lParam, SW_SHOW);
+ break;
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+
+ case M_PRESHUTDOWN:
+ SendMessage(dat->hwndIncoming, M_PRESHUTDOWN, 0, 0);
+ SendMessage(dat->hwndOutgoing, M_PRESHUTDOWN, 0, 0);
+ DestroyWindow(hwnd);
+ break;
+
+ case WM_CLOSE:
+ ShowWindow(hwnd, SW_HIDE);
+ if (DBGetContactSettingByte(NULL, "SRFile", "AutoClear", 1)) {
+ PostMessage(dat->hwndIncoming, WM_FT_CLEANUP, 0, 0);
+ PostMessage(dat->hwndOutgoing, WM_FT_CLEANUP, 0, 0);
+ }
+ return TRUE; /* Disable default IDCANCEL notification */
+
+ case WM_DESTROY:
+ UnhookEvent(dat->hhkPreshutdown);
+ Window_FreeIcon_IcoLib(hwnd);
+ DestroyWindow(dat->hwndIncoming);
+ DestroyWindow(dat->hwndOutgoing);
+ mir_free(dat);
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, 0);
+ Utils_SaveWindowPosition(hwnd, NULL, "SRFile", "FtMgrDlg_");
+ break;
+
+ case WM_ACTIVATE:
+ {
+ dat->errorState = TBPF_NOPROGRESS;
+ wParam = 1;
+ } break;
+ case WM_SHOWWINDOW:
+ {
+ if (!wParam) // hiding
+ {
+ KillTimer(hwnd, 1);
+ break;
+ }
+ lParam = 0;
+ }
+ case WM_TIMER:
+ {
+ if (pTaskbarInterface)
+ {
+ SetTimer(hwnd, 1, 400, NULL);
+ if ((lParam == ACKRESULT_FAILED) || (lParam == ACKRESULT_DENIED))
+ dat->errorState = TBPF_ERROR;
+
+ TFtProgressData prg = {0};
+ SendMessage(dat->hwndIncoming, M_CALCPROGRESS, (WPARAM)&prg, 0);
+ SendMessage(dat->hwndOutgoing, M_CALCPROGRESS, (WPARAM)&prg, 0);
+ if (dat->errorState)
+ {
+ pTaskbarInterface->SetProgressState(hwnd, dat->errorState);
+ if (!prg.run)
+ pTaskbarInterface->SetProgressValue(hwnd, 1, 1);
+ } else if (prg.run)
+ {
+ pTaskbarInterface->SetProgressState(hwnd, TBPF_NORMAL);
+ } else if (prg.init || prg.scan)
+ {
+ pTaskbarInterface->SetProgressState(hwnd, TBPF_INDETERMINATE);
+ } else {
+ pTaskbarInterface->SetProgressState(hwnd, TBPF_NOPROGRESS);
+ KillTimer(hwnd, 1);
+ }
+
+ if (prg.run)
+ {
+ pTaskbarInterface->SetProgressValue(hwnd, prg.totalProgress, prg.totalBytes);
+ }
+
+ }
+ } break;
+
+ }
+
+ return FALSE;
+}
+
+HWND FtMgr_Show(bool bForceActivate, bool bFromMenu)
+{
+ bool bAutoMin = DBGetContactSettingByte(NULL,"SRFile","AutoMin",0) != 0; /* lqbe */
+
+ bool bJustCreated = (hwndFtMgr == NULL);
+ if (bJustCreated)
+ {
+ hwndFtMgr = CreateDialog(hMirandaInst, MAKEINTRESOURCE(IDD_FTMGR), NULL, FtMgrDlgProc);
+ }
+ if (bFromMenu) /* lqbe */
+ {
+ ShowWindow(hwndFtMgr, SW_RESTORE);
+ ShowWindow(hwndFtMgr, SW_SHOW);
+ SetForegroundWindow(hwndFtMgr);
+ return hwndFtMgr;
+ }
+ else if (bAutoMin && bJustCreated) /* lqbe */
+ {
+ ShowWindow(hwndFtMgr, SW_HIDE);
+ ShowWindow(hwndFtMgr, SW_MINIMIZE);
+ return hwndFtMgr;
+ }
+ else if (bForceActivate) /* lqbe */
+ {
+ ShowWindow(hwndFtMgr, SW_RESTORE);
+ ShowWindow(hwndFtMgr, SW_SHOWNOACTIVATE);
+ SetForegroundWindow(hwndFtMgr);
+ return hwndFtMgr;
+ }
+ if (!bJustCreated && IsWindowVisible(hwndFtMgr))
+ return hwndFtMgr;
+
+ ShowWindow(hwndFtMgr, bAutoMin ? SW_SHOWMINNOACTIVE : SW_SHOWNOACTIVATE);
+ return hwndFtMgr;
+ }
+
+void FtMgr_Destroy()
+{
+ if (hwndFtMgr)
+ DestroyWindow(hwndFtMgr);
+}
+
+void FtMgr_ShowPage(int page)
+{
+ if (hwndFtMgr)
+ SendMessage(hwndFtMgr, WM_FT_SELECTPAGE, page, 0);
+}
+
+HWND FtMgr_AddTransfer(FileDlgData *fdd)
+{
+ bool bForceActivate = fdd->send || !DBGetContactSettingByte(NULL, "SRFile", "AutoAccept", 0);
+ TFtMgrData *dat = (TFtMgrData*)GetWindowLongPtr(FtMgr_Show(bForceActivate, false), GWLP_USERDATA);
+ if (dat == NULL) return NULL;
+ HWND hwndBox = fdd->send ? dat->hwndOutgoing : dat->hwndIncoming;
+ HWND hwndFt = CreateDialogParam(hMirandaInst, MAKEINTRESOURCE(IDD_FILETRANSFERINFO), hwndBox, DlgProcFileTransfer, (LPARAM)fdd);
+ ShowWindow(hwndFt, SW_SHOWNA);
+ SendMessage(hwndBox, WM_FT_ADD, 0, (LPARAM)hwndFt);
+ FtMgr_ShowPage(fdd->send ? 1 : 0);
+ return hwndFt;
+}
\ No newline at end of file |