summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/newpluginapi.h1
-rw-r--r--plugins/PluginUpdater/src/DlgUpdate.cpp1
-rw-r--r--src/core/stdfile/CMakeLists.txt3
-rw-r--r--src/core/stdfile/res/resource.rc316
-rw-r--r--src/core/stdfile/res/version.rc9
-rw-r--r--src/core/stdfile/src/main.cpp79
-rw-r--r--src/core/stdfile/src/stdafx.cxx2
-rw-r--r--src/core/stdfile/src/stdafx.h85
-rw-r--r--src/core/stdfile/src/version.h11
-rw-r--r--src/core/stdfile/stdfile.vcxproj49
-rw-r--r--src/core/stdfile/stdfile.vcxproj.filters55
-rw-r--r--src/mir_app/mir_app.vcxproj8
-rw-r--r--src/mir_app/mir_app.vcxproj.filters27
-rw-r--r--src/mir_app/res/resource.rc166
-rw-r--r--src/mir_app/src/clisttray.cpp2
-rw-r--r--src/mir_app/src/file.cpp (renamed from src/core/stdfile/src/file.cpp)866
-rw-r--r--src/mir_app/src/file.h (renamed from src/core/stdfile/src/file.h)265
-rw-r--r--src/mir_app/src/fileexistsdlg.cpp (renamed from src/core/stdfile/src/fileexistsdlg.cpp)680
-rw-r--r--src/mir_app/src/fileopts.cpp (renamed from src/core/stdfile/src/fileopts.cpp)482
-rw-r--r--src/mir_app/src/filerecvdlg.cpp (renamed from src/core/stdfile/src/filerecvdlg.cpp)822
-rw-r--r--src/mir_app/src/filesenddlg.cpp (renamed from src/core/stdfile/src/filesenddlg.cpp)668
-rw-r--r--src/mir_app/src/filexferdlg.cpp (renamed from src/core/stdfile/src/filexferdlg.cpp)1504
-rw-r--r--src/mir_app/src/ftmanager.cpp (renamed from src/core/stdfile/src/ftmanager.cpp)1030
-rw-r--r--src/mir_app/src/modules.cpp2
-rw-r--r--src/mir_app/src/newplugins.cpp12
25 files changed, 3377 insertions, 3768 deletions
diff --git a/include/newpluginapi.h b/include/newpluginapi.h
index e836a93c9f..d964d7a52f 100644
--- a/include/newpluginapi.h
+++ b/include/newpluginapi.h
@@ -59,7 +59,6 @@ MIR_APP_DLL(void) SetPluginOnWhiteList(const char *szPluginName, bool bAllow);
#define MIID_UIUSERINFO {0x570b931c, 0x9af8, 0x48f1, {0xad, 0x9f, 0xc4, 0x49, 0x8c, 0x61, 0x8a, 0x77}}
#define MIID_SRAWAY {0x5ab54c76, 0x1b4c, 0x4a00, {0xb4, 0x04, 0x48, 0xcb, 0xea, 0x5f, 0xef, 0xe7}}
#define MIID_SREMAIL {0xd005b5a6, 0x1b66, 0x445a, {0xb6, 0x03, 0x74, 0xd4, 0xd4, 0x55, 0x2d, 0xe2}}
-#define MIID_SRFILE {0x989d104d, 0xacb7, 0x4ee0, {0xb9, 0x6d, 0x67, 0xce, 0x46, 0x53, 0xb6, 0x95}}
#define MIID_UIHISTORY {0x7f7e3d98, 0xce1f, 0x4962, {0x82, 0x84, 0x96, 0x85, 0x50, 0xf1, 0xd3, 0xd9}}
#define MIID_AUTOAWAY {0x9c87f7dc, 0x3bd7, 0x4983, {0xb7, 0xfb, 0xb8, 0x48, 0xfd, 0xbc, 0x91, 0xf0}}
#define MIID_USERONLINE {0x130829e0, 0x2463, 0x4ff8, {0xbb, 0xc8, 0xce, 0x73, 0xc0, 0x18, 0x84, 0x42}}
diff --git a/plugins/PluginUpdater/src/DlgUpdate.cpp b/plugins/PluginUpdater/src/DlgUpdate.cpp
index 09e0a19a3e..9a13d78737 100644
--- a/plugins/PluginUpdater/src/DlgUpdate.cpp
+++ b/plugins/PluginUpdater/src/DlgUpdate.cpp
@@ -527,6 +527,7 @@ static renameTable[] =
{ L"stdchat.dll", nullptr },
{ L"stdurl.dll", nullptr },
{ L"stdidle.dll", nullptr },
+ { L"stdfile.dll", nullptr },
{ L"stdhelp.dll", nullptr },
{ L"stdauth.dll", nullptr },
{ L"stdssl.dll", nullptr },
diff --git a/src/core/stdfile/CMakeLists.txt b/src/core/stdfile/CMakeLists.txt
deleted file mode 100644
index 3454bf4121..0000000000
--- a/src/core/stdfile/CMakeLists.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-set(TARGET StdFile)
-include(${CMAKE_SOURCE_DIR}/cmake/core.cmake)
-target_link_libraries(${TARGET} Shlwapi.lib) \ No newline at end of file
diff --git a/src/core/stdfile/res/resource.rc b/src/core/stdfile/res/resource.rc
deleted file mode 100644
index 4751451ce1..0000000000
--- a/src/core/stdfile/res/resource.rc
+++ /dev/null
@@ -1,316 +0,0 @@
-// Microsoft Visual C++ generated resource script.
-//
-#include "..\..\..\mir_app\src\resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include <windows.h>
-#include <winres.h>
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (United States) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Dialog
-//
-
-IDD_FILESEND DIALOGEX 0, 0, 256, 177
-STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU
-EXSTYLE WS_EX_CONTROLPARENT
-CAPTION "Send file(s)"
-FONT 8, "MS Shell Dlg", 0, 0, 0x1
-BEGIN
- EDITTEXT IDC_MSG,6,102,245,46,ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL
- DEFPUSHBUTTON "&Send",IDOK,67,157,50,15
- PUSHBUTTON "Cancel",IDCANCEL,140,157,50,15
- LTEXT "To:",IDC_STATIC,6,23,24,9,SS_CENTERIMAGE
- CONTROL "",IDC_TO,"Static",SS_SIMPLE | SS_NOPREFIX | WS_GROUP,43,24,159,9
- LTEXT "File(s):",IDC_STATIC,7,39,30,8
- EDITTEXT IDC_FILE,38,38,213,31,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY
- PUSHBUTTON "&Choose again...",IDC_CHOOSE,39,74,77,14
- RTEXT "Total size:",IDC_STATIC,119,76,68,8
- CONTROL "",IDC_TOTALSIZE,"Static",SS_SIMPLE | SS_NOPREFIX | WS_GROUP,191,76,58,8
- LTEXT "Description:",IDC_STATIC,6,93,96,8
- CONTROL "&User menu",IDC_USERMENU,"MButtonClass",WS_TABSTOP,195,5,16,14,WS_EX_NOACTIVATE | 0x10000000L
- CONTROL "User &details",IDC_DETAILS,"MButtonClass",WS_TABSTOP,213,5,16,14,WS_EX_NOACTIVATE | 0x10000000L
- CONTROL "&History",IDC_HISTORY,"MButtonClass",WS_TABSTOP,231,5,16,14,WS_EX_NOACTIVATE | 0x10000000L
- ICON "",IDC_PROTOCOL,5,7,20,20
- LTEXT "",IDC_NAME,19,7,151,9,SS_NOPREFIX | SS_CENTERIMAGE
-END
-
-IDD_FILERECV DIALOGEX 0, 0, 256, 174
-STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU
-EXSTYLE WS_EX_CONTROLPARENT
-CAPTION "Incoming file transfer"
-FONT 8, "MS Shell Dlg", 0, 0, 0x1
-BEGIN
- DEFPUSHBUTTON "A&ccept",IDOK,68,155,50,14
- PUSHBUTTON "&Decline",IDCANCEL,138,155,50,14
- LTEXT "From:",IDC_STATIC,6,20,24,9,SS_CENTERIMAGE
- CONTROL "",IDC_FROM,"Static",SS_SIMPLE | SS_NOPREFIX | WS_GROUP,39,21,159,9
- LTEXT "Date:",IDC_STATIC,6,35,28,9,SS_CENTERIMAGE
- CONTROL "",IDC_DATE,"Static",SS_SIMPLE | SS_NOPREFIX | WS_GROUP,39,34,159,9
- LTEXT "Files:",IDC_STATIC,6,50,28,8
- EDITTEXT IDC_FILENAMES,39,50,210,16,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | NOT WS_BORDER
- LTEXT "Description:",IDC_STATIC,6,69,64,8
- EDITTEXT IDC_MSG,6,79,243,45,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY
- LTEXT "Save to:",IDC_STATIC,6,131,34,8
- PUSHBUTTON "...",IDC_FILEDIRBROWSE,235,130,14,10
- COMBOBOX IDC_FILEDIR,45,129,187,108,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP
- CONTROL "&Add",IDC_ADD,"MButtonClass",WS_TABSTOP,177,5,16,14,WS_EX_NOACTIVATE | 0x10000000L
- CONTROL "&User menu",IDC_USERMENU,"MButtonClass",WS_TABSTOP,195,5,16,14,WS_EX_NOACTIVATE | 0x10000000L
- CONTROL "User &details",IDC_DETAILS,"MButtonClass",WS_TABSTOP,213,5,16,14,WS_EX_NOACTIVATE | 0x10000000L
- CONTROL "&History",IDC_HISTORY,"MButtonClass",WS_TABSTOP,231,5,16,14,WS_EX_NOACTIVATE | 0x10000000L
- ICON "",IDC_PROTOCOL,5,7,20,20
- LTEXT "",IDC_NAME,19,7,151,9,SS_NOPREFIX | SS_CENTERIMAGE
-END
-
-IDD_FILETRANSFERINFO DIALOGEX 0, 0, 256, 44
-STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | WS_CHILD
-EXSTYLE WS_EX_CONTROLPARENT
-FONT 8, "MS Shell Dlg", 0, 0, 0x1
-BEGIN
- CONTROL "&User menu",IDC_CONTACT,"MButtonClass",WS_TABSTOP,5,1,16,14,WS_EX_NOACTIVATE | 0x10000000L
- CONTROL "",IDC_CONTACTNAME,"Static",SS_LEFTNOWORDWRAP | SS_CENTERIMAGE | SS_WORDELLIPSIS | WS_GROUP,25,1,174,14
- CONTROL "&Open...",IDC_OPENFILE,"MButtonClass",WS_DISABLED | WS_TABSTOP,203,1,16,14,WS_EX_NOACTIVATE | 0x10000000L
- CONTROL "Open &folder",IDC_OPENFOLDER,"MButtonClass",WS_TABSTOP,219,1,16,14,WS_EX_NOACTIVATE | 0x10000000L
- CONTROL "&Cancel",IDCANCEL,"MButtonClass",WS_TABSTOP,235,1,16,14,WS_EX_NOACTIVATE | 0x10000000L
- CONTROL "",IDC_ALLFILESPROGRESS,"msctls_progress32",PBS_SMOOTH | NOT WS_VISIBLE | WS_DISABLED,25,16,190,12
- CONTROL "",IDC_STATUS,"Static",SS_LEFTNOWORDWRAP | SS_NOPREFIX | WS_GROUP,25,17,190,10
- ICON "",IDC_FILEICON,25,15,16,14,SS_CENTERIMAGE | SS_REALSIZEIMAGE
- CONTROL "Transfer completed, open file(s).",IDC_TRANSFERCOMPLETED,
- "Hyperlink",NOT WS_VISIBLE | WS_TABSTOP,42,17,173,10
- LTEXT "No data transferred",IDC_ALLTRANSFERRED,25,29,230,14,SS_NOPREFIX | SS_CENTERIMAGE
- RTEXT "",IDC_ALLSPEED,252,29,3,14,SS_NOPREFIX | SS_CENTERIMAGE
- LTEXT "",IDC_ALLPRECENTS,218,14,33,14,SS_CENTERIMAGE
- CONTROL "",IDC_FRAME,"Static",SS_ETCHEDHORZ,1,43,254,1
-END
-
-IDD_FILEEXISTS DIALOGEX 0, 0, 288, 181
-STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
-EXSTYLE WS_EX_CONTROLPARENT
-CAPTION "File already exists"
-FONT 8, "MS Shell Dlg", 0, 0, 0x1
-BEGIN
- PUSHBUTTON "Resume",IDC_RESUME,5,144,65,14
- PUSHBUTTON "Resume all",IDC_RESUMEALL,5,162,65,14
- PUSHBUTTON "Overwrite",IDC_OVERWRITE,76,144,65,14
- PUSHBUTTON "Overwrite all",IDC_OVERWRITEALL,76,162,65,14
- PUSHBUTTON "Save as...",IDC_SAVEAS,147,144,65,14
- PUSHBUTTON "Auto rename",IDC_AUTORENAME,147,162,65,14
- PUSHBUTTON "Skip",IDC_SKIP,218,144,65,14
- PUSHBUTTON "Cancel transfer",IDCANCEL,218,162,65,14
- LTEXT "You are about to receive the file",IDC_STATIC,5,5,278,8
- EDITTEXT IDC_FILENAME,15,16,268,8,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
- GROUPBOX "Existing file",IDC_STATIC,5,29,278,61
- ICON "",IDC_EXISTINGICON,14,45,20,20,SS_NOTIFY
- LTEXT "Size:",IDC_STATIC,40,42,27,8
- LTEXT "",IDC_EXISTINGSIZE,67,42,35,8
- RTEXT "Last modified:",IDC_STATIC,103,42,58,8
- LTEXT "",IDC_EXISTINGDATE,166,42,115,8
- LTEXT "Type:",IDC_STATIC,40,55,27,8
- LTEXT "",IDC_EXISTINGTYPE,67,55,214,8
- PUSHBUTTON "Open file",IDC_OPENFILE,12,70,62,13
- PUSHBUTTON "Open folder",IDC_OPENFOLDER,82,70,62,13
- PUSHBUTTON "File properties",IDC_PROPERTIES,201,70,74,13
- GROUPBOX "File being received",IDC_STATIC,5,95,278,42
- ICON "",IDC_NEWICON,14,110,20,20,SS_NOTIFY
- LTEXT "Size:",IDC_STATIC,40,108,27,8
- LTEXT "",IDC_NEWSIZE,67,108,35,8
- RTEXT "Last modified:",IDC_STATIC,103,108,58,8
- LTEXT "",IDC_NEWDATE,166,108,115,8
- LTEXT "Type:",IDC_STATIC,40,121,27,8
- LTEXT "",IDC_NEWTYPE,67,121,214,8
-END
-
-IDD_FTMGR DIALOGEX 0, 0, 276, 255
-STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
-CAPTION "File transfers"
-FONT 8, "MS Shell Dlg", 400, 0, 0x1
-BEGIN
- CONTROL "",IDC_TABS,"SysTabControl32",WS_TABSTOP,7,7,262,224
- PUSHBUTTON "Clear completed",IDC_CLEAR,7,234,100,14
- PUSHBUTTON "Close",IDCANCEL,219,234,50,14
-END
-
-IDD_FTPAGE DIALOGEX 0, 0, 320, 183
-STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VSCROLL | WS_SYSMENU
-EXSTYLE WS_EX_CONTROLPARENT | WS_EX_STATICEDGE
-FONT 8, "MS Shell Dlg", 400, 0, 0x1
-BEGIN
-END
-
-IDD_OPT_FILETRANSFER DIALOGEX 0, 0, 313, 243
-STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
-EXSTYLE WS_EX_CONTROLPARENT
-FONT 8, "MS Shell Dlg", 0, 0, 0x1
-BEGIN
- GROUPBOX "Receiving files",IDC_STATIC,0,0,313,99
- LTEXT "Received files folder:",IDC_STATIC,8,15,82,8
- EDITTEXT IDC_FILEDIR,92,13,190,12,ES_AUTOHSCROLL
- PUSHBUTTON "...",IDC_FILEDIRBROWSE,287,12,15,13
- LTEXT "Variables allowed: %userid%, %nick%, %proto%, %miranda_path%, %userprofile%",IDC_STATIC,8,26,294,11,WS_DISABLED
- CONTROL "Auto-accept incoming files from people on my contact list",IDC_AUTOACCEPT,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,36,294,10
- CONTROL "Minimize the file transfer window",IDC_AUTOMIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,17,48,285,10
- CONTROL "Close window when transfer completes",IDC_AUTOCLOSE,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,60,294,10
- CONTROL "Clear completed transfers on window closing",IDC_AUTOCLEAR,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,72,294,10
- CONTROL "Sort file transfers in the reverse order",IDC_REVERSE_ORDER,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,84,286,10
- GROUPBOX "Virus scanner",IDC_VIRUSSCANNERGROUP,0,100,313,93
- LTEXT "Scan files:",IDC_STATIC,8,112,43,9,SS_CENTERIMAGE
- CONTROL "Never, do not use virus scanning",IDC_NOSCANNER,"Button",BS_AUTORADIOBUTTON,52,112,250,10
- CONTROL "When all files have been downloaded",IDC_SCANAFTERDL,
- "Button",BS_AUTORADIOBUTTON,52,124,250,10
- CONTROL "As each file finishes downloading",IDC_SCANDURINGDL,
- "Button",BS_AUTORADIOBUTTON,52,136,250,10
- LTEXT "Command line:",IDC_ST_CMDLINE,7,152,62,8
- COMBOBOX IDC_SCANCMDLINE,70,151,213,71,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP
- PUSHBUTTON "...",IDC_SCANCMDLINEBROWSE,287,151,15,13
- LTEXT "%f will be replaced by the file or folder name to be scanned",IDC_ST_CMDLINEHELP,70,165,232,8
- CONTROL "Warn me before opening a file that has not been scanned",IDC_WARNBEFOREOPENING,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,178,294,10
- GROUPBOX "If incoming files already exist",IDC_STATIC,0,197,313,41
- CONTROL "Ask me",IDC_ASK,"Button",BS_AUTORADIOBUTTON,8,210,73,10
- CONTROL "Resume",IDC_RESUME,"Button",BS_AUTORADIOBUTTON,82,210,125,10
- CONTROL "Overwrite",IDC_OVERWRITE,"Button",BS_AUTORADIOBUTTON,8,222,73,10
- CONTROL "Rename (append "" (1)"", etc.)",IDC_RENAME,"Button",BS_AUTORADIOBUTTON,82,222,125,10
- LTEXT "You will always be asked about files from people not on your contact list",IDC_STATIC,212,208,90,24
-END
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// DESIGNINFO
-//
-
-#ifdef APSTUDIO_INVOKED
-GUIDELINES DESIGNINFO
-BEGIN
- IDD_FILESEND, DIALOG
- BEGIN
- LEFTMARGIN, 5
- RIGHTMARGIN, 251
- VERTGUIDE, 7
- VERTGUIDE, 249
- TOPMARGIN, 5
- BOTTOMMARGIN, 172
- END
-
- IDD_FILERECV, DIALOG
- BEGIN
- LEFTMARGIN, 5
- RIGHTMARGIN, 249
- VERTGUIDE, 7
- VERTGUIDE, 249
- TOPMARGIN, 5
- BOTTOMMARGIN, 169
- END
-
- IDD_FILETRANSFERINFO, DIALOG
- BEGIN
- VERTGUIDE, 5
- VERTGUIDE, 25
- VERTGUIDE, 36
- VERTGUIDE, 120
- VERTGUIDE, 180
- VERTGUIDE, 215
- VERTGUIDE, 218
- VERTGUIDE, 235
- VERTGUIDE, 251
- BOTTOMMARGIN, 43
- HORZGUIDE, 14
- HORZGUIDE, 28
- HORZGUIDE, 42
- END
-
- IDD_FILEEXISTS, DIALOG
- BEGIN
- LEFTMARGIN, 5
- RIGHTMARGIN, 283
- TOPMARGIN, 5
- BOTTOMMARGIN, 176
- END
-
- IDD_FTPAGE, DIALOG
- BEGIN
- LEFTMARGIN, 7
- RIGHTMARGIN, 303
- TOPMARGIN, 7
- BOTTOMMARGIN, 176
- END
-
- IDD_OPT_FILETRANSFER, DIALOG
- BEGIN
- VERTGUIDE, 8
- VERTGUIDE, 302
- END
-END
-#endif // APSTUDIO_INVOKED
-
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE
-BEGIN
- "..\\..\\..\\mir_app\\src\\resource.h\0"
-END
-
-2 TEXTINCLUDE
-BEGIN
- "#include <windows.h>\r\n"
- "#include <winres.h>\r\n"
- "\0"
-END
-
-3 TEXTINCLUDE
-BEGIN
- "\r\n"
- "\0"
-END
-
-#endif // APSTUDIO_INVOKED
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// AFX_DIALOG_LAYOUT
-//
-
-IDD_OPT_FILETRANSFER AFX_DIALOG_LAYOUT
-BEGIN
- 0
-END
-
-#endif // English (United States) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif // not APSTUDIO_INVOKED
-
diff --git a/src/core/stdfile/res/version.rc b/src/core/stdfile/res/version.rc
deleted file mode 100644
index 5a5ddd63ed..0000000000
--- a/src/core/stdfile/res/version.rc
+++ /dev/null
@@ -1,9 +0,0 @@
-// Microsoft Visual C++ generated resource script.
-//
-#ifdef APSTUDIO_INVOKED
-#error this file is not editable by Microsoft Visual C++
-#endif //APSTUDIO_INVOKED
-
-#include "..\src\version.h"
-
-#include "..\..\build\Version.rc"
diff --git a/src/core/stdfile/src/main.cpp b/src/core/stdfile/src/main.cpp
deleted file mode 100644
index 3797ea1e49..0000000000
--- a/src/core/stdfile/src/main.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
-
-Standard file transfers' plugin for Miranda NG
-
-Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org)
-
-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.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-#include "stdafx.h"
-
-int LoadSendRecvFileModule(void);
-
-CMPlugin g_plugin;
-
-ITaskbarList3 * pTaskbarInterface;
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-PLUGININFOEX pluginInfoEx = {
- sizeof(PLUGININFOEX),
- __PLUGIN_NAME,
- MIRANDA_VERSION_DWORD,
- __DESCRIPTION,
- __AUTHOR,
- __COPYRIGHT,
- __AUTHORWEB,
- UNICODE_AWARE,
- // 39698dce-7ed4-4334-ac4c-ba8b37a86f13
- { 0x39698dce, 0x7ed4, 0x4334, {0xac, 0x4c, 0xba, 0x8b, 0x37, 0xa8, 0x6f, 0x13}}
-};
-
-CMPlugin::CMPlugin() :
- PLUGIN<CMPlugin>(MODULENAME, pluginInfoEx),
- bAutoMin(MODULENAME, "AutoMin", false),
- bAutoClear(MODULENAME, "AutoClear", true),
- bAutoClose(MODULENAME, "AutoClose", false),
- bAutoAccept(MODULENAME, "AutoAccept", false),
- bReverseOrder(MODULENAME, "ReverseOrder", false)
-{
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = { MIID_SRFILE, MIID_LAST };
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-int CMPlugin::Load()
-{
- if (IsWinVer7Plus())
- if (FAILED(CoCreateInstance(CLSID_TaskbarList, nullptr, CLSCTX_ALL, IID_ITaskbarList3, (void**)&pTaskbarInterface)))
- pTaskbarInterface = nullptr;
-
- LoadSendRecvFileModule();
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-int CMPlugin::Unload()
-{
- if (pTaskbarInterface)
- pTaskbarInterface->Release();
-
- return 0;
-}
diff --git a/src/core/stdfile/src/stdafx.cxx b/src/core/stdfile/src/stdafx.cxx
deleted file mode 100644
index 716dda68f1..0000000000
--- a/src/core/stdfile/src/stdafx.cxx
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "stdafx.h"
-
diff --git a/src/core/stdfile/src/stdafx.h b/src/core/stdfile/src/stdafx.h
deleted file mode 100644
index 775d957d38..0000000000
--- a/src/core/stdfile/src/stdafx.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda 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.
-*/
-
-#pragma once
-
-#include <winsock2.h>
-#include <shlobj.h>
-#include <commctrl.h>
-#include <vssym32.h>
-#include <Shlwapi.h>
-
-#include <stdio.h>
-#include <time.h>
-#include <stddef.h>
-#include <process.h>
-#include <io.h>
-#include <limits.h>
-#include <string.h>
-#include <locale.h>
-#include <direct.h>
-#include <malloc.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <newpluginapi.h>
-#include <m_system.h>
-#include <m_database.h>
-#include <m_netlib.h>
-#include <m_crypto.h>
-#include <m_langpack.h>
-#include <m_clistint.h>
-#include <m_button.h>
-#include <m_protosvc.h>
-#include <m_protocols.h>
-#include <m_protoint.h>
-#include <m_options.h>
-#include <m_skin.h>
-#include <m_contacts.h>
-#include <m_message.h>
-#include <m_userinfo.h>
-#include <m_history.h>
-#include <m_findadd.h>
-#include <m_file.h>
-#include <m_icolib.h>
-#include <m_timezones.h>
-#include <m_metacontacts.h>
-
-#include "version.h"
-
-#include "../../mir_app/src/resource.h"
-
-#define MODULENAME "SRFile"
-
-struct CMPlugin : public PLUGIN<CMPlugin>
-{
- CMPlugin();
-
- CMOption<bool> bAutoMin, bAutoClear, bAutoClose, bAutoAccept, bReverseOrder;
-
- int Load() override;
- int Unload() override;
-};
-
-extern ITaskbarList3 * pTaskbarInterface;
diff --git a/src/core/stdfile/src/version.h b/src/core/stdfile/src/version.h
deleted file mode 100644
index 2099819477..0000000000
--- a/src/core/stdfile/src/version.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#include <m_version.h>
-
-#define __FILEVERSION_STRING MIRANDA_VERSION_FILEVERSION
-#define __VERSION_STRING_DOTS MIRANDA_VERSION_STRING
-
-#define __PLUGIN_NAME "Standard File Transfers"
-#define __FILENAME "stdfile.dll"
-#define __DESCRIPTION "Core module for sending/receiving files."
-#define __AUTHOR "Miranda NG team"
-#define __AUTHORWEB "https://miranda-ng.org/p/StdFile"
-#define __COPYRIGHT "© 2012-23 Miranda NG team"
diff --git a/src/core/stdfile/stdfile.vcxproj b/src/core/stdfile/stdfile.vcxproj
deleted file mode 100644
index 8913f39e63..0000000000
--- a/src/core/stdfile/stdfile.vcxproj
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup Label="ProjectConfigurations">
- <ProjectConfiguration Include="Debug|Win32">
- <Configuration>Debug</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Debug|x64">
- <Configuration>Debug</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|Win32">
- <Configuration>Release</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|x64">
- <Configuration>Release</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- </ItemGroup>
- <PropertyGroup Label="Globals">
- <ProjectName>StdFile</ProjectName>
- <ProjectGuid>{6022990D-3FD5-46A9-8AB5-E444C51646F3}</ProjectGuid>
- </PropertyGroup>
- <ImportGroup Label="PropertySheets">
- <Import Project="$(ProjectDir)..\..\..\build\vc.common\core.props" />
- </ImportGroup>
- <ItemGroup>
- <ClCompile Include="src\file.cpp" />
- <ClCompile Include="src\fileexistsdlg.cpp" />
- <ClCompile Include="src\fileopts.cpp" />
- <ClCompile Include="src\filerecvdlg.cpp" />
- <ClCompile Include="src\filesenddlg.cpp" />
- <ClCompile Include="src\filexferdlg.cpp" />
- <ClCompile Include="src\ftmanager.cpp" />
- <ClCompile Include="src\main.cpp" />
- <ClCompile Include="src\stdafx.cxx">
- <PrecompiledHeader>Create</PrecompiledHeader>
- </ClCompile>
- <ClInclude Include="..\..\mir_app\src\resource.h" />
- <ClInclude Include="src\file.h" />
- <ClInclude Include="src\stdafx.h" />
- <ClInclude Include="src\version.h" />
- </ItemGroup>
- <ItemGroup>
- <ResourceCompile Include="res\resource.rc" />
- <ResourceCompile Include="res\version.rc" />
- </ItemGroup>
-</Project> \ No newline at end of file
diff --git a/src/core/stdfile/stdfile.vcxproj.filters b/src/core/stdfile/stdfile.vcxproj.filters
deleted file mode 100644
index d80e8cd000..0000000000
--- a/src/core/stdfile/stdfile.vcxproj.filters
+++ /dev/null
@@ -1,55 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$(ProjectDir)..\..\..\build\vc.common\common.filters" />
- <ItemGroup>
- <ClCompile Include="src\file.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\fileexistsdlg.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\fileopts.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\filerecvdlg.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\filesenddlg.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\filexferdlg.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\ftmanager.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\main.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\stdafx.cxx">
- <Filter>Source Files</Filter>
- </ClCompile>
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="src\file.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\stdafx.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\version.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\..\mir_app\src\resource.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- </ItemGroup>
- <ItemGroup>
- <ResourceCompile Include="res\resource.rc">
- <Filter>Resource Files</Filter>
- </ResourceCompile>
- <ResourceCompile Include="res\version.rc">
- <Filter>Resource Files</Filter>
- </ResourceCompile>
- </ItemGroup>
-</Project> \ No newline at end of file
diff --git a/src/mir_app/mir_app.vcxproj b/src/mir_app/mir_app.vcxproj
index 5cb64ca6a3..2610d0ef02 100644
--- a/src/mir_app/mir_app.vcxproj
+++ b/src/mir_app/mir_app.vcxproj
@@ -77,10 +77,17 @@
<ClCompile Include="src\encrypt.cpp" />
<ClCompile Include="src\enterstring.cpp" />
<ClCompile Include="src\extracticon.cpp" />
+ <ClCompile Include="src\file.cpp" />
+ <ClCompile Include="src\fileexistsdlg.cpp" />
+ <ClCompile Include="src\fileopts.cpp" />
+ <ClCompile Include="src\filerecvdlg.cpp" />
+ <ClCompile Include="src\filesenddlg.cpp" />
+ <ClCompile Include="src\filexferdlg.cpp" />
<ClCompile Include="src\filter.cpp" />
<ClCompile Include="src\findadd.cpp" />
<ClCompile Include="src\FontOptions.cpp" />
<ClCompile Include="src\FontService.cpp" />
+ <ClCompile Include="src\ftmanager.cpp" />
<ClCompile Include="src\headerbar.cpp" />
<ClCompile Include="src\help.cpp" />
<ClCompile Include="src\hotkeys.cpp" />
@@ -167,6 +174,7 @@
<ClInclude Include="src\database.h" />
<ClInclude Include="src\encrypt.h" />
<ClInclude Include="src\extraicons.h" />
+ <ClInclude Include="src\file.h" />
<ClInclude Include="src\filter.h" />
<ClInclude Include="src\findadd.h" />
<ClInclude Include="src\FontService.h" />
diff --git a/src/mir_app/mir_app.vcxproj.filters b/src/mir_app/mir_app.vcxproj.filters
index 3a925e5b5a..a73e0dfbd4 100644
--- a/src/mir_app/mir_app.vcxproj.filters
+++ b/src/mir_app/mir_app.vcxproj.filters
@@ -404,6 +404,27 @@
<ClCompile Include="src\chat_loginfo.cpp">
<Filter>Source Files\Chats</Filter>
</ClCompile>
+ <ClCompile Include="src\file.cpp">
+ <Filter>Source Files\File</Filter>
+ </ClCompile>
+ <ClCompile Include="src\fileexistsdlg.cpp">
+ <Filter>Source Files\File</Filter>
+ </ClCompile>
+ <ClCompile Include="src\fileopts.cpp">
+ <Filter>Source Files\File</Filter>
+ </ClCompile>
+ <ClCompile Include="src\filerecvdlg.cpp">
+ <Filter>Source Files\File</Filter>
+ </ClCompile>
+ <ClCompile Include="src\filesenddlg.cpp">
+ <Filter>Source Files\File</Filter>
+ </ClCompile>
+ <ClCompile Include="src\filexferdlg.cpp">
+ <Filter>Source Files\File</Filter>
+ </ClCompile>
+ <ClCompile Include="src\ftmanager.cpp">
+ <Filter>Source Files\File</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\filter.h">
@@ -466,6 +487,9 @@
<ClInclude Include="src\profilemanager.h">
<Filter>Source Files\Database</Filter>
</ClInclude>
+ <ClInclude Include="src\file.h">
+ <Filter>Source Files\File</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="res\resource.rc">
@@ -510,5 +534,8 @@
<Filter Include="Source Files\Plugins">
<UniqueIdentifier>{2f5b2fe9-25c8-4029-8a52-f34a11f984a7}</UniqueIdentifier>
</Filter>
+ <Filter Include="Source Files\File">
+ <UniqueIdentifier>{bf5fc3bb-4d3d-4237-a43b-94cb18041b25}</UniqueIdentifier>
+ </Filter>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/src/mir_app/res/resource.rc b/src/mir_app/res/resource.rc
index d3f3bccf3c..301cd47f9f 100644
--- a/src/mir_app/res/resource.rc
+++ b/src/mir_app/res/resource.rc
@@ -999,6 +999,172 @@ BEGIN
LTEXT "(Setting timeout to 0 means default setting and -1 means indefinite time)",IDC_STATIC,33,151,207,17
END
+IDD_FILESEND DIALOGEX 0, 0, 256, 177
+STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+CAPTION "Send file(s)"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ EDITTEXT IDC_MSG,6,102,245,46,ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL
+ DEFPUSHBUTTON "&Send",IDOK,67,157,50,15
+ PUSHBUTTON "Cancel",IDCANCEL,140,157,50,15
+ LTEXT "To:",IDC_STATIC,6,23,24,9,SS_CENTERIMAGE
+ CONTROL "",IDC_TO,"Static",SS_SIMPLE | SS_NOPREFIX | WS_GROUP,43,24,159,9
+ LTEXT "File(s):",IDC_STATIC,7,39,30,8
+ EDITTEXT IDC_FILE,38,38,213,31,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY
+ PUSHBUTTON "&Choose again...",IDC_CHOOSE,39,74,77,14
+ RTEXT "Total size:",IDC_STATIC,119,76,68,8
+ CONTROL "",IDC_TOTALSIZE,"Static",SS_SIMPLE | SS_NOPREFIX | WS_GROUP,191,76,58,8
+ LTEXT "Description:",IDC_STATIC,6,93,96,8
+ CONTROL "&User menu",IDC_USERMENU,"MButtonClass",WS_TABSTOP,195,5,16,14,WS_EX_NOACTIVATE | 0x10000000L
+ CONTROL "User &details",IDC_DETAILS,"MButtonClass",WS_TABSTOP,213,5,16,14,WS_EX_NOACTIVATE | 0x10000000L
+ CONTROL "&History",IDC_HISTORY,"MButtonClass",WS_TABSTOP,231,5,16,14,WS_EX_NOACTIVATE | 0x10000000L
+ ICON "",IDC_PROTOCOL,5,7,20,20
+ LTEXT "",IDC_NAME,19,7,151,9,SS_NOPREFIX | SS_CENTERIMAGE
+END
+
+IDD_FILERECV DIALOGEX 0, 0, 256, 174
+STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+CAPTION "Incoming file transfer"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "A&ccept",IDOK,68,155,50,14
+ PUSHBUTTON "&Decline",IDCANCEL,138,155,50,14
+ LTEXT "From:",IDC_STATIC,6,20,24,9,SS_CENTERIMAGE
+ CONTROL "",IDC_FROM,"Static",SS_SIMPLE | SS_NOPREFIX | WS_GROUP,39,21,159,9
+ LTEXT "Date:",IDC_STATIC,6,35,28,9,SS_CENTERIMAGE
+ CONTROL "",IDC_DATE,"Static",SS_SIMPLE | SS_NOPREFIX | WS_GROUP,39,34,159,9
+ LTEXT "Files:",IDC_STATIC,6,50,28,8
+ EDITTEXT IDC_FILENAMES,39,50,210,16,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | NOT WS_BORDER
+ LTEXT "Description:",IDC_STATIC,6,69,64,8
+ EDITTEXT IDC_MSG,6,79,243,45,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY
+ LTEXT "Save to:",IDC_STATIC,6,131,34,8
+ PUSHBUTTON "...",IDC_FILEDIRBROWSE,235,130,14,10
+ COMBOBOX IDC_FILEDIR,45,129,187,108,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP
+ CONTROL "&Add",IDC_ADD,"MButtonClass",WS_TABSTOP,177,5,16,14,WS_EX_NOACTIVATE | 0x10000000L
+ CONTROL "&User menu",IDC_USERMENU,"MButtonClass",WS_TABSTOP,195,5,16,14,WS_EX_NOACTIVATE | 0x10000000L
+ CONTROL "User &details",IDC_DETAILS,"MButtonClass",WS_TABSTOP,213,5,16,14,WS_EX_NOACTIVATE | 0x10000000L
+ CONTROL "&History",IDC_HISTORY,"MButtonClass",WS_TABSTOP,231,5,16,14,WS_EX_NOACTIVATE | 0x10000000L
+ ICON "",IDC_PROTOCOL,5,7,20,20
+ LTEXT "",IDC_NAME,19,7,151,9,SS_NOPREFIX | SS_CENTERIMAGE
+END
+
+IDD_FILETRANSFERINFO DIALOGEX 0, 0, 256, 44
+STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "&User menu",IDC_CONTACT,"MButtonClass",WS_TABSTOP,5,1,16,14,WS_EX_NOACTIVATE | 0x10000000L
+ CONTROL "",IDC_CONTACTNAME,"Static",SS_LEFTNOWORDWRAP | SS_CENTERIMAGE | SS_WORDELLIPSIS | WS_GROUP,25,1,174,14
+ CONTROL "&Open...",IDC_OPENFILE,"MButtonClass",WS_DISABLED | WS_TABSTOP,203,1,16,14,WS_EX_NOACTIVATE | 0x10000000L
+ CONTROL "Open &folder",IDC_OPENFOLDER,"MButtonClass",WS_TABSTOP,219,1,16,14,WS_EX_NOACTIVATE | 0x10000000L
+ CONTROL "&Cancel",IDCANCEL,"MButtonClass",WS_TABSTOP,235,1,16,14,WS_EX_NOACTIVATE | 0x10000000L
+ CONTROL "",IDC_ALLFILESPROGRESS,"msctls_progress32",PBS_SMOOTH | NOT WS_VISIBLE | WS_DISABLED,25,16,190,12
+ CONTROL "",IDC_STATUS,"Static",SS_LEFTNOWORDWRAP | SS_NOPREFIX | WS_GROUP,25,17,190,10
+ ICON "",IDC_FILEICON,25,15,16,14,SS_CENTERIMAGE | SS_REALSIZEIMAGE
+ CONTROL "Transfer completed, open file(s).",IDC_TRANSFERCOMPLETED,
+ "Hyperlink",NOT WS_VISIBLE | WS_TABSTOP,42,17,173,10
+ LTEXT "No data transferred",IDC_ALLTRANSFERRED,25,29,230,14,SS_NOPREFIX | SS_CENTERIMAGE
+ RTEXT "",IDC_ALLSPEED,252,29,3,14,SS_NOPREFIX | SS_CENTERIMAGE
+ LTEXT "",IDC_ALLPRECENTS,218,14,33,14,SS_CENTERIMAGE
+ CONTROL "",IDC_FRAME,"Static",SS_ETCHEDHORZ,1,43,254,1
+END
+
+IDD_FILEEXISTS DIALOGEX 0, 0, 288, 181
+STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+CAPTION "File already exists"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ PUSHBUTTON "Resume",IDC_RESUME,5,144,65,14
+ PUSHBUTTON "Resume all",IDC_RESUMEALL,5,162,65,14
+ PUSHBUTTON "Overwrite",IDC_OVERWRITE,76,144,65,14
+ PUSHBUTTON "Overwrite all",IDC_OVERWRITEALL,76,162,65,14
+ PUSHBUTTON "Save as...",IDC_SAVEAS,147,144,65,14
+ PUSHBUTTON "Auto rename",IDC_AUTORENAME,147,162,65,14
+ PUSHBUTTON "Skip",IDC_SKIP,218,144,65,14
+ PUSHBUTTON "Cancel transfer",IDCANCEL,218,162,65,14
+ LTEXT "You are about to receive the file",IDC_STATIC,5,5,278,8
+ EDITTEXT IDC_FILENAME,15,16,268,8,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ GROUPBOX "Existing file",IDC_STATIC,5,29,278,61
+ ICON "",IDC_EXISTINGICON,14,45,20,20,SS_NOTIFY
+ LTEXT "Size:",IDC_STATIC,40,42,27,8
+ LTEXT "",IDC_EXISTINGSIZE,67,42,35,8
+ RTEXT "Last modified:",IDC_STATIC,103,42,58,8
+ LTEXT "",IDC_EXISTINGDATE,166,42,115,8
+ LTEXT "Type:",IDC_STATIC,40,55,27,8
+ LTEXT "",IDC_EXISTINGTYPE,67,55,214,8
+ PUSHBUTTON "Open file",IDC_OPENFILE,12,70,62,13
+ PUSHBUTTON "Open folder",IDC_OPENFOLDER,82,70,62,13
+ PUSHBUTTON "File properties",IDC_PROPERTIES,201,70,74,13
+ GROUPBOX "File being received",IDC_STATIC,5,95,278,42
+ ICON "",IDC_NEWICON,14,110,20,20,SS_NOTIFY
+ LTEXT "Size:",IDC_STATIC,40,108,27,8
+ LTEXT "",IDC_NEWSIZE,67,108,35,8
+ RTEXT "Last modified:",IDC_STATIC,103,108,58,8
+ LTEXT "",IDC_NEWDATE,166,108,115,8
+ LTEXT "Type:",IDC_STATIC,40,121,27,8
+ LTEXT "",IDC_NEWTYPE,67,121,214,8
+END
+
+IDD_FTMGR DIALOGEX 0, 0, 276, 255
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
+CAPTION "File transfers"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CONTROL "",IDC_TABS,"SysTabControl32",WS_TABSTOP,7,7,262,224
+ PUSHBUTTON "Clear completed",IDC_CLEAR,7,234,100,14
+ PUSHBUTTON "Close",IDCANCEL,219,234,50,14
+END
+
+IDD_FTPAGE DIALOGEX 0, 0, 320, 183
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VSCROLL | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT | WS_EX_STATICEDGE
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+END
+
+IDD_OPT_FILETRANSFER DIALOGEX 0, 0, 313, 243
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Receiving files",IDC_STATIC,0,0,313,99
+ LTEXT "Received files folder:",IDC_STATIC,8,15,82,8
+ EDITTEXT IDC_FILEDIR,92,13,190,12,ES_AUTOHSCROLL
+ PUSHBUTTON "...",IDC_FILEDIRBROWSE,287,12,15,13
+ LTEXT "Variables allowed: %userid%, %nick%, %proto%, %miranda_path%, %userprofile%",IDC_STATIC,8,26,294,11,WS_DISABLED
+ CONTROL "Auto-accept incoming files from people on my contact list",IDC_AUTOACCEPT,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,36,294,10
+ CONTROL "Minimize the file transfer window",IDC_AUTOMIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,17,48,285,10
+ CONTROL "Close window when transfer completes",IDC_AUTOCLOSE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,60,294,10
+ CONTROL "Clear completed transfers on window closing",IDC_AUTOCLEAR,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,72,294,10
+ CONTROL "Sort file transfers in the reverse order",IDC_REVERSE_ORDER,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,84,286,10
+ GROUPBOX "Virus scanner",IDC_VIRUSSCANNERGROUP,0,100,313,93
+ LTEXT "Scan files:",IDC_STATIC,8,112,43,9,SS_CENTERIMAGE
+ CONTROL "Never, do not use virus scanning",IDC_NOSCANNER,"Button",BS_AUTORADIOBUTTON,52,112,250,10
+ CONTROL "When all files have been downloaded",IDC_SCANAFTERDL,
+ "Button",BS_AUTORADIOBUTTON,52,124,250,10
+ CONTROL "As each file finishes downloading",IDC_SCANDURINGDL,
+ "Button",BS_AUTORADIOBUTTON,52,136,250,10
+ LTEXT "Command line:",IDC_ST_CMDLINE,7,152,62,8
+ COMBOBOX IDC_SCANCMDLINE,70,151,213,71,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "...",IDC_SCANCMDLINEBROWSE,287,151,15,13
+ LTEXT "%f will be replaced by the file or folder name to be scanned",IDC_ST_CMDLINEHELP,70,165,232,8
+ CONTROL "Warn me before opening a file that has not been scanned",IDC_WARNBEFOREOPENING,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,178,294,10
+ GROUPBOX "If incoming files already exist",IDC_STATIC,0,197,313,41
+ CONTROL "Ask me",IDC_ASK,"Button",BS_AUTORADIOBUTTON,8,210,73,10
+ CONTROL "Resume",IDC_RESUME,"Button",BS_AUTORADIOBUTTON,82,210,125,10
+ CONTROL "Overwrite",IDC_OVERWRITE,"Button",BS_AUTORADIOBUTTON,8,222,73,10
+ CONTROL "Rename (append "" (1)"", etc.)",IDC_RENAME,"Button",BS_AUTORADIOBUTTON,82,222,125,10
+ LTEXT "You will always be asked about files from people not on your contact list",IDC_STATIC,212,208,90,24
+END
+
/////////////////////////////////////////////////////////////////////////////
//
diff --git a/src/mir_app/src/clisttray.cpp b/src/mir_app/src/clisttray.cpp
index c10100a1b3..007074cffe 100644
--- a/src/mir_app/src/clisttray.cpp
+++ b/src/mir_app/src/clisttray.cpp
@@ -27,7 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define TOOLTIP_TOLERANCE 5
-static ITaskbarList3* pTaskbarInterface;
+ITaskbarList3* pTaskbarInterface;
static UINT WM_TASKBARCREATED;
static UINT WM_TASKBARBUTTONCREATED;
diff --git a/src/core/stdfile/src/file.cpp b/src/mir_app/src/file.cpp
index 5efa3f7027..c9cc489df4 100644
--- a/src/core/stdfile/src/file.cpp
+++ b/src/mir_app/src/file.cpp
@@ -1,430 +1,436 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda 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 "stdafx.h"
-#include "file.h"
-
-HANDLE hDlgSucceeded, hDlgCanceled;
-
-wchar_t* PFTS_StringToTchar(int flags, const wchar_t* s);
-int PFTS_CompareWithTchar(PROTOFILETRANSFERSTATUS* ft, const wchar_t* s, wchar_t *r);
-
-static HGENMENU hSRFileMenuItem;
-
-static INT_PTR SendFileCommand(WPARAM hContact, LPARAM)
-{
- FileSendData fsd;
- fsd.hContact = hContact;
- fsd.ppFiles = nullptr;
- return (INT_PTR)CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_FILESEND), NULL, DlgProcSendFile, (LPARAM)&fsd);
-}
-
-static INT_PTR SendSpecificFiles(WPARAM hContact, LPARAM lParam)
-{
- FileSendData fsd;
- fsd.hContact = hContact;
-
- char** ppFiles = (char**)lParam;
- int count = 0;
- while (ppFiles[count] != nullptr)
- count++;
-
- fsd.ppFiles = (const wchar_t**)alloca((count + 1) * sizeof(void*));
- for (int i = 0; i < count; i++)
- fsd.ppFiles[i] = mir_a2u(ppFiles[i]);
- fsd.ppFiles[count] = nullptr;
-
- HWND hWnd = CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_FILESEND), NULL, DlgProcSendFile, (LPARAM)&fsd);
- for (int j = 0; j < count; j++)
- mir_free((void*)fsd.ppFiles[j]);
- return (INT_PTR)hWnd;
-}
-
-static INT_PTR SendSpecificFilesT(WPARAM hContact, LPARAM lParam)
-{
- FileSendData fsd;
- fsd.hContact = hContact;
- fsd.ppFiles = (const wchar_t**)lParam;
- return (INT_PTR)CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_FILESEND), NULL, DlgProcSendFile, (LPARAM)&fsd);
-}
-
-static INT_PTR GetReceivedFilesFolder(WPARAM wParam, LPARAM lParam)
-{
- wchar_t buf[MAX_PATH];
- GetContactReceivedFilesDir(wParam, buf, MAX_PATH, TRUE);
- char *dir = mir_u2a(buf);
- mir_strncpy((char *)lParam, dir, MAX_PATH);
- mir_free(dir);
- return 0;
-}
-
-static INT_PTR GetReceivedFilesFolderW(WPARAM wParam, LPARAM lParam)
-{
- wchar_t buf[MAX_PATH];
- GetContactReceivedFilesDir(wParam, buf, MAX_PATH, TRUE);
- mir_wstrncpy((wchar_t *)lParam, buf, MAX_PATH);
- return 0;
-}
-
-static INT_PTR RecvFileCommand(WPARAM, LPARAM lParam)
-{
- LaunchRecvDialog((CLISTEVENT *)lParam);
- return 0;
-}
-
-int SRFile_GetRegValue(HKEY hKeyBase, const wchar_t *szSubKey, const wchar_t *szValue, wchar_t *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, nullptr, nullptr, (uint8_t*)szOutput, &cbOut) != ERROR_SUCCESS) {
- RegCloseKey(hKey);
- return 0;
- }
-
- RegCloseKey(hKey);
- return 1;
-}
-
-void GetSensiblyFormattedSize(__int64 size, wchar_t *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_snwprintf(szOut, cchOut, L"%u%s%s", (int)size, appendUnits ? L" " : L"", appendUnits ? TranslateT("bytes") : L""); break;
- case UNITS_KBPOINT1: mir_snwprintf(szOut, cchOut, L"%.1lf%s", size / 1024.0, appendUnits ? L" KB" : L""); break;
- case UNITS_KBPOINT0: mir_snwprintf(szOut, cchOut, L"%u%s", (int)(size / 1024), appendUnits ? L" KB" : L""); break;
- case UNITS_GBPOINT3: mir_snwprintf(szOut, cchOut, L"%.3f%s", (size >> 20) / 1024.0, appendUnits ? L" GB" : L""); break;
- default: mir_snwprintf(szOut, cchOut, L"%.2lf%s", size / 1048576.0, appendUnits ? L" MB" : L""); break;
- }
-}
-
-// Tripple redirection sucks but is needed to nullify the array pointer
-void FreeFilesMatrix(wchar_t ***files)
-{
- if (*files == nullptr)
- return;
-
- // Free each filename in the pointer array
- wchar_t **pFile = *files;
- while (*pFile != nullptr) {
- mir_free(*pFile);
- *pFile = nullptr;
- pFile++;
- }
-
- // Free the array itself
- mir_free(*files);
- *files = nullptr;
-}
-
-void FreeProtoFileTransferStatus(PROTOFILETRANSFERSTATUS *fts)
-{
- mir_free(fts->szCurrentFile.w);
- if (fts->pszFiles.w) {
- for (int i = 0; i < fts->totalFiles; i++) mir_free(fts->pszFiles.w[i]);
- mir_free(fts->pszFiles.w);
- }
- mir_free(fts->szWorkingDir.w);
-}
-
-void CopyProtoFileTransferStatus(PROTOFILETRANSFERSTATUS *dest, PROTOFILETRANSFERSTATUS *src)
-{
- *dest = *src;
- if (src->szCurrentFile.w) dest->szCurrentFile.w = PFTS_StringToTchar(src->flags, src->szCurrentFile.w);
- if (src->pszFiles.w) {
- dest->pszFiles.w = (wchar_t**)mir_alloc(sizeof(wchar_t*)*src->totalFiles);
- for (int i = 0; i < src->totalFiles; i++)
- dest->pszFiles.w[i] = PFTS_StringToTchar(src->flags, src->pszFiles.w[i]);
- }
- if (src->szWorkingDir.w) dest->szWorkingDir.w = PFTS_StringToTchar(src->flags, src->szWorkingDir.w);
- dest->flags &= ~PFTS_UTF;
- dest->flags |= PFTS_UNICODE;
-}
-
-void UpdateProtoFileTransferStatus(PROTOFILETRANSFERSTATUS *dest, PROTOFILETRANSFERSTATUS *src)
-{
- dest->hContact = src->hContact;
- dest->flags = src->flags;
- if (dest->totalFiles != src->totalFiles) {
- for (int i = 0; i < dest->totalFiles; i++) mir_free(dest->pszFiles.w[i]);
- mir_free(dest->pszFiles.w);
- dest->pszFiles.w = nullptr;
- dest->totalFiles = src->totalFiles;
- }
- if (src->pszFiles.w) {
- if (!dest->pszFiles.w)
- dest->pszFiles.w = (wchar_t**)mir_calloc(sizeof(wchar_t*)*src->totalFiles);
- for (int i = 0; i < src->totalFiles; i++)
- if (!dest->pszFiles.w[i] || !src->pszFiles.w[i] || PFTS_CompareWithTchar(src, src->pszFiles.w[i], dest->pszFiles.w[i])) {
- mir_free(dest->pszFiles.w[i]);
- if (src->pszFiles.w[i])
- dest->pszFiles.w[i] = PFTS_StringToTchar(src->flags, src->pszFiles.w[i]);
- else
- dest->pszFiles.w[i] = nullptr;
- }
- }
- else if (dest->pszFiles.w) {
- for (int i = 0; i < dest->totalFiles; i++)
- mir_free(dest->pszFiles.w[i]);
- mir_free(dest->pszFiles.w);
- dest->pszFiles.w = nullptr;
- }
-
- dest->currentFileNumber = src->currentFileNumber;
- dest->totalBytes = src->totalBytes;
- dest->totalProgress = src->totalProgress;
- if (src->szWorkingDir.w && (!dest->szWorkingDir.w || PFTS_CompareWithTchar(src, src->szWorkingDir.w, dest->szWorkingDir.w))) {
- mir_free(dest->szWorkingDir.w);
- if (src->szWorkingDir.w)
- dest->szWorkingDir.w = PFTS_StringToTchar(src->flags, src->szWorkingDir.w);
- else
- dest->szWorkingDir.w = nullptr;
- }
-
- if (!dest->szCurrentFile.w || !src->szCurrentFile.w || PFTS_CompareWithTchar(src, src->szCurrentFile.w, dest->szCurrentFile.w)) {
- mir_free(dest->szCurrentFile.w);
- if (src->szCurrentFile.w)
- dest->szCurrentFile.w = PFTS_StringToTchar(src->flags, src->szCurrentFile.w);
- else
- dest->szCurrentFile.w = nullptr;
- }
- dest->currentFileSize = src->currentFileSize;
- dest->currentFileProgress = src->currentFileProgress;
- dest->currentFileTime = src->currentFileTime;
- dest->flags &= ~PFTS_UTF;
- dest->flags |= PFTS_UNICODE;
-}
-
-static void RemoveUnreadFileEvents(void)
-{
- for (auto &hContact : Contacts()) {
- MEVENT hDbEvent = db_event_firstUnread(hContact);
- while (hDbEvent) {
- DBEVENTINFO dbei = {};
- db_event_get(hDbEvent, &dbei);
- if (!dbei.markedRead() && dbei.eventType == EVENTTYPE_FILE)
- db_event_markRead(hContact, hDbEvent);
- hDbEvent = db_event_next(hContact, hDbEvent);
- }
- }
-}
-
-static int SRFilePreBuildMenu(WPARAM wParam, LPARAM)
-{
- bool bEnabled = false;
- char *szProto = Proto_GetBaseAccountName(wParam);
- if (szProto != nullptr) {
- bool isChat = Contact::IsGroupChat(wParam, szProto);
- if (CallProtoService(szProto, PS_GETCAPS, isChat ? PFLAGNUM_4 : PFLAGNUM_1, 0) & (isChat ? PF4_GROUPCHATFILES : PF1_FILESEND)) {
- if (CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_4, 0) & PF4_OFFLINEFILES)
- bEnabled = true;
- else if (db_get_w(wParam, szProto, "Status", ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE)
- bEnabled = true;
- }
- }
-
- Menu_ShowItem(hSRFileMenuItem, bEnabled);
- return 0;
-}
-
-static int SRFileProtoAck(WPARAM, LPARAM lParam)
-{
- ACKDATA *ack = (ACKDATA*)lParam;
- if (ack->type == ACKTYPE_FILE) {
- int iEvent = 0;
- while (auto *cle = Clist_GetEvent(ack->hContact, iEvent++))
- if (cle->lParam == (LPARAM)ack->hProcess)
- Clist_RemoveEvent(ack->hContact, cle->hDbEvent);
- }
- return 0;
-}
-
-static int SRFileModulesLoaded(WPARAM, LPARAM)
-{
- CMenuItem mi(&g_plugin);
- SET_UID(mi, 0x7f8dcf77, 0xe448, 0x4505, 0xb0, 0x56, 0xb, 0xb1, 0xab, 0xac, 0x64, 0x9d);
- mi.position = -2000020000;
- mi.hIcolibItem = Skin_GetIconHandle(SKINICON_EVENT_FILE);
- mi.name.a = LPGEN("&File");
- mi.pszService = MS_FILE_SENDFILE;
- hSRFileMenuItem = Menu_AddContactMenuItem(&mi);
-
- RemoveUnreadFileEvents();
- return 0;
-}
-
-INT_PTR FtMgrShowCommand(WPARAM, LPARAM)
-{
- FtMgr_Show(true, true);
- return 0;
-}
-
-INT_PTR openContRecDir(WPARAM hContact, LPARAM)
-{
- wchar_t szContRecDir[MAX_PATH];
- GetContactReceivedFilesDir(hContact, szContRecDir, _countof(szContRecDir), TRUE);
- ShellExecute(nullptr, L"open", szContRecDir, nullptr, nullptr, SW_SHOW);
- return 0;
-}
-
-INT_PTR openRecDir(WPARAM, LPARAM)
-{
- wchar_t szContRecDir[MAX_PATH];
- GetReceivedFilesDir(szContRecDir, _countof(szContRecDir));
- ShellExecute(nullptr, L"open", szContRecDir, nullptr, nullptr, SW_SHOW);
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static INT_PTR Proto_RecvFileT(WPARAM, LPARAM lParam)
-{
- CCSDATA *ccs = (CCSDATA*)lParam;
- PROTORECVFILE* pre = (PROTORECVFILE*)ccs->lParam;
- if (pre->fileCount == 0)
- return 0;
-
- DB::EventInfo dbei;
- dbei.szModule = Proto_GetBaseAccountName(ccs->hContact);
- dbei.timestamp = pre->timestamp;
- dbei.szId = pre->szId;
- dbei.szUserId = pre->szUserId;
- dbei.eventType = EVENTTYPE_FILE;
- dbei.flags = DBEF_UTF;
- if (pre->dwFlags & PRFF_SENT)
- dbei.flags |= DBEF_SENT;
- if (pre->dwFlags & PRFF_READ)
- dbei.flags |= DBEF_READ;
-
- if ((pre->dwFlags & PRFF_UNICODE) == PRFF_UNICODE) {
- CMStringW wszFiles;
-
- for (int i = 0; i < pre->fileCount; i++) {
- if (i != 0)
- wszFiles.AppendChar(',');
- wszFiles.Append(pre->files.w[i]);
- }
-
- DB::FILE_BLOB blob(wszFiles, pre->descr.w);
- CallProtoService(dbei.szModule, PS_PRECREATE_OFFLINEFILE, WPARAM(&blob), pre->lParam);
- blob.write(dbei);
- }
- else {
- bool bUtf = (pre->dwFlags & PRFF_UTF) != 0;
- CMStringW wszFiles;
-
- for (int i = 0; i < pre->fileCount; i++) {
- if (i != 0)
- wszFiles.AppendChar(',');
-
- if (bUtf)
- wszFiles.Append(Utf2T(pre->files.a[i]));
- else
- wszFiles.Append(_A2T(pre->files.a[i]));
- }
-
- DB::FILE_BLOB blob(wszFiles, bUtf ? Utf2T(pre->descr.a).get() : _A2T(pre->descr.a));
- CallProtoService(dbei.szModule, PS_PRECREATE_OFFLINEFILE, WPARAM(&blob), pre->lParam);
- blob.write(dbei);
- }
-
- bool bShow = (pre->dwFlags & (PRFF_SILENT | PRFF_SENT)) == 0;
- MEVENT hdbe = db_event_add(ccs->hContact, &dbei);
-
- CLISTEVENT cle = {};
- cle.hContact = ccs->hContact;
- cle.hDbEvent = hdbe;
- cle.lParam = pre->lParam;
-
- if (bShow && g_plugin.bAutoAccept && Contact::OnList(ccs->hContact))
- LaunchRecvDialog(&cle);
- else {
- Skin_PlaySound("RecvFile");
-
- if (bShow) {
- wchar_t szTooltip[256];
- mir_snwprintf(szTooltip, TranslateT("File from %s"), Clist_GetContactDisplayName(ccs->hContact));
- cle.szTooltip.w = szTooltip;
-
- cle.flags |= CLEF_UNICODE;
- cle.hIcon = Skin_LoadIcon(SKINICON_EVENT_FILE);
- cle.pszService = "SRFile/RecvFile";
- g_clistApi.pfnAddEvent(&cle);
- }
- }
-
- return hdbe;
-}
-
-int LoadSendRecvFileModule(void)
-{
- CreateServiceFunction("FtMgr/Show", FtMgrShowCommand);
-
- CMenuItem mi(&g_plugin);
- SET_UID(mi, 0x75794ab5, 0x2573, 0x48f4, 0xb4, 0xa0, 0x93, 0xd6, 0xf5, 0xe0, 0xf3, 0x32);
- mi.hIcolibItem = Skin_GetIconHandle(SKINICON_EVENT_FILE);
- mi.position = 1900000000;
- mi.name.a = LPGEN("File &transfers...");
- mi.pszService = "FtMgr/Show"; //MS_PROTO_SHOWFTMGR;
- Menu_AddMainMenuItem(&mi);
-
- HookEvent(ME_SYSTEM_MODULESLOADED, SRFileModulesLoaded);
- HookEvent(ME_OPT_INITIALISE, FileOptInitialise);
- HookEvent(ME_CLIST_PREBUILDCONTACTMENU, SRFilePreBuildMenu);
- HookEvent(ME_PROTO_ACK, SRFileProtoAck);
-
- hDlgSucceeded = CreateHookableEvent(ME_FILEDLG_SUCCEEDED);
- hDlgCanceled = CreateHookableEvent(ME_FILEDLG_CANCELED);
-
- CreateServiceFunction(MS_PROTO_RECVFILET, Proto_RecvFileT);
-
- CreateServiceFunction(MS_FILE_SENDFILE, SendFileCommand);
- CreateServiceFunction(MS_FILE_SENDSPECIFICFILES, SendSpecificFiles);
- CreateServiceFunction(MS_FILE_SENDSPECIFICFILEST, SendSpecificFilesT);
- CreateServiceFunction(MS_FILE_GETRECEIVEDFILESFOLDER, GetReceivedFilesFolder);
- CreateServiceFunction(MS_FILE_GETRECEIVEDFILESFOLDERW, GetReceivedFilesFolderW);
- CreateServiceFunction("SRFile/RecvFile", RecvFileCommand);
-
- CreateServiceFunction("SRFile/OpenContRecDir", openContRecDir);
- CreateServiceFunction("SRFile/OpenRecDir", openRecDir);
-
- g_plugin.addSound("RecvFile", LPGENW("File"), LPGENW("Incoming"));
- g_plugin.addSound("FileDone", LPGENW("File"), LPGENW("Complete"));
- g_plugin.addSound("FileFailed", LPGENW("File"), LPGENW("Error"));
- g_plugin.addSound("FileDenied", LPGENW("File"), LPGENW("Denied"));
- return 0;
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda 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 "stdafx.h"
+#include "file.h"
+
+HANDLE hDlgSucceeded, hDlgCanceled;
+
+wchar_t* PFTS_StringToTchar(int flags, const wchar_t* s);
+int PFTS_CompareWithTchar(PROTOFILETRANSFERSTATUS* ft, const wchar_t* s, wchar_t *r);
+
+CMOption<bool> File::bAutoMin(SRFILEMODULE, "AutoMin", false);
+CMOption<bool> File::bAutoClear(SRFILEMODULE, "AutoClear", true);
+CMOption<bool> File::bAutoClose(SRFILEMODULE, "AutoClose", false);
+CMOption<bool> File::bAutoAccept(SRFILEMODULE, "AutoAccept", false);
+CMOption<bool> File::bReverseOrder(SRFILEMODULE, "ReverseOrder", false);
+
+static HGENMENU hSRFileMenuItem;
+
+static INT_PTR SendFileCommand(WPARAM hContact, LPARAM)
+{
+ FileSendData fsd;
+ fsd.hContact = hContact;
+ fsd.ppFiles = nullptr;
+ return (INT_PTR)CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_FILESEND), NULL, DlgProcSendFile, (LPARAM)&fsd);
+}
+
+static INT_PTR SendSpecificFiles(WPARAM hContact, LPARAM lParam)
+{
+ FileSendData fsd;
+ fsd.hContact = hContact;
+
+ char** ppFiles = (char**)lParam;
+ int count = 0;
+ while (ppFiles[count] != nullptr)
+ count++;
+
+ fsd.ppFiles = (const wchar_t**)alloca((count + 1) * sizeof(void*));
+ for (int i = 0; i < count; i++)
+ fsd.ppFiles[i] = mir_a2u(ppFiles[i]);
+ fsd.ppFiles[count] = nullptr;
+
+ HWND hWnd = CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_FILESEND), NULL, DlgProcSendFile, (LPARAM)&fsd);
+ for (int j = 0; j < count; j++)
+ mir_free((void*)fsd.ppFiles[j]);
+ return (INT_PTR)hWnd;
+}
+
+static INT_PTR SendSpecificFilesT(WPARAM hContact, LPARAM lParam)
+{
+ FileSendData fsd;
+ fsd.hContact = hContact;
+ fsd.ppFiles = (const wchar_t**)lParam;
+ return (INT_PTR)CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_FILESEND), NULL, DlgProcSendFile, (LPARAM)&fsd);
+}
+
+static INT_PTR GetReceivedFilesFolder(WPARAM wParam, LPARAM lParam)
+{
+ wchar_t buf[MAX_PATH];
+ GetContactReceivedFilesDir(wParam, buf, MAX_PATH, TRUE);
+ char *dir = mir_u2a(buf);
+ mir_strncpy((char *)lParam, dir, MAX_PATH);
+ mir_free(dir);
+ return 0;
+}
+
+static INT_PTR GetReceivedFilesFolderW(WPARAM wParam, LPARAM lParam)
+{
+ wchar_t buf[MAX_PATH];
+ GetContactReceivedFilesDir(wParam, buf, MAX_PATH, TRUE);
+ mir_wstrncpy((wchar_t *)lParam, buf, MAX_PATH);
+ return 0;
+}
+
+static INT_PTR RecvFileCommand(WPARAM, LPARAM lParam)
+{
+ LaunchRecvDialog((CLISTEVENT *)lParam);
+ return 0;
+}
+
+int SRFile_GetRegValue(HKEY hKeyBase, const wchar_t *szSubKey, const wchar_t *szValue, wchar_t *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, nullptr, nullptr, (uint8_t*)szOutput, &cbOut) != ERROR_SUCCESS) {
+ RegCloseKey(hKey);
+ return 0;
+ }
+
+ RegCloseKey(hKey);
+ return 1;
+}
+
+void GetSensiblyFormattedSize(__int64 size, wchar_t *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_snwprintf(szOut, cchOut, L"%u%s%s", (int)size, appendUnits ? L" " : L"", appendUnits ? TranslateT("bytes") : L""); break;
+ case UNITS_KBPOINT1: mir_snwprintf(szOut, cchOut, L"%.1lf%s", size / 1024.0, appendUnits ? L" KB" : L""); break;
+ case UNITS_KBPOINT0: mir_snwprintf(szOut, cchOut, L"%u%s", (int)(size / 1024), appendUnits ? L" KB" : L""); break;
+ case UNITS_GBPOINT3: mir_snwprintf(szOut, cchOut, L"%.3f%s", (size >> 20) / 1024.0, appendUnits ? L" GB" : L""); break;
+ default: mir_snwprintf(szOut, cchOut, L"%.2lf%s", size / 1048576.0, appendUnits ? L" MB" : L""); break;
+ }
+}
+
+// Tripple redirection sucks but is needed to nullify the array pointer
+void FreeFilesMatrix(wchar_t ***files)
+{
+ if (*files == nullptr)
+ return;
+
+ // Free each filename in the pointer array
+ wchar_t **pFile = *files;
+ while (*pFile != nullptr) {
+ mir_free(*pFile);
+ *pFile = nullptr;
+ pFile++;
+ }
+
+ // Free the array itself
+ mir_free(*files);
+ *files = nullptr;
+}
+
+void FreeProtoFileTransferStatus(PROTOFILETRANSFERSTATUS *fts)
+{
+ mir_free(fts->szCurrentFile.w);
+ if (fts->pszFiles.w) {
+ for (int i = 0; i < fts->totalFiles; i++) mir_free(fts->pszFiles.w[i]);
+ mir_free(fts->pszFiles.w);
+ }
+ mir_free(fts->szWorkingDir.w);
+}
+
+void CopyProtoFileTransferStatus(PROTOFILETRANSFERSTATUS *dest, PROTOFILETRANSFERSTATUS *src)
+{
+ *dest = *src;
+ if (src->szCurrentFile.w) dest->szCurrentFile.w = PFTS_StringToTchar(src->flags, src->szCurrentFile.w);
+ if (src->pszFiles.w) {
+ dest->pszFiles.w = (wchar_t**)mir_alloc(sizeof(wchar_t*)*src->totalFiles);
+ for (int i = 0; i < src->totalFiles; i++)
+ dest->pszFiles.w[i] = PFTS_StringToTchar(src->flags, src->pszFiles.w[i]);
+ }
+ if (src->szWorkingDir.w) dest->szWorkingDir.w = PFTS_StringToTchar(src->flags, src->szWorkingDir.w);
+ dest->flags &= ~PFTS_UTF;
+ dest->flags |= PFTS_UNICODE;
+}
+
+void UpdateProtoFileTransferStatus(PROTOFILETRANSFERSTATUS *dest, PROTOFILETRANSFERSTATUS *src)
+{
+ dest->hContact = src->hContact;
+ dest->flags = src->flags;
+ if (dest->totalFiles != src->totalFiles) {
+ for (int i = 0; i < dest->totalFiles; i++) mir_free(dest->pszFiles.w[i]);
+ mir_free(dest->pszFiles.w);
+ dest->pszFiles.w = nullptr;
+ dest->totalFiles = src->totalFiles;
+ }
+ if (src->pszFiles.w) {
+ if (!dest->pszFiles.w)
+ dest->pszFiles.w = (wchar_t**)mir_calloc(sizeof(wchar_t*)*src->totalFiles);
+ for (int i = 0; i < src->totalFiles; i++)
+ if (!dest->pszFiles.w[i] || !src->pszFiles.w[i] || PFTS_CompareWithTchar(src, src->pszFiles.w[i], dest->pszFiles.w[i])) {
+ mir_free(dest->pszFiles.w[i]);
+ if (src->pszFiles.w[i])
+ dest->pszFiles.w[i] = PFTS_StringToTchar(src->flags, src->pszFiles.w[i]);
+ else
+ dest->pszFiles.w[i] = nullptr;
+ }
+ }
+ else if (dest->pszFiles.w) {
+ for (int i = 0; i < dest->totalFiles; i++)
+ mir_free(dest->pszFiles.w[i]);
+ mir_free(dest->pszFiles.w);
+ dest->pszFiles.w = nullptr;
+ }
+
+ dest->currentFileNumber = src->currentFileNumber;
+ dest->totalBytes = src->totalBytes;
+ dest->totalProgress = src->totalProgress;
+ if (src->szWorkingDir.w && (!dest->szWorkingDir.w || PFTS_CompareWithTchar(src, src->szWorkingDir.w, dest->szWorkingDir.w))) {
+ mir_free(dest->szWorkingDir.w);
+ if (src->szWorkingDir.w)
+ dest->szWorkingDir.w = PFTS_StringToTchar(src->flags, src->szWorkingDir.w);
+ else
+ dest->szWorkingDir.w = nullptr;
+ }
+
+ if (!dest->szCurrentFile.w || !src->szCurrentFile.w || PFTS_CompareWithTchar(src, src->szCurrentFile.w, dest->szCurrentFile.w)) {
+ mir_free(dest->szCurrentFile.w);
+ if (src->szCurrentFile.w)
+ dest->szCurrentFile.w = PFTS_StringToTchar(src->flags, src->szCurrentFile.w);
+ else
+ dest->szCurrentFile.w = nullptr;
+ }
+ dest->currentFileSize = src->currentFileSize;
+ dest->currentFileProgress = src->currentFileProgress;
+ dest->currentFileTime = src->currentFileTime;
+ dest->flags &= ~PFTS_UTF;
+ dest->flags |= PFTS_UNICODE;
+}
+
+static void RemoveUnreadFileEvents(void)
+{
+ for (auto &hContact : Contacts()) {
+ MEVENT hDbEvent = db_event_firstUnread(hContact);
+ while (hDbEvent) {
+ DBEVENTINFO dbei = {};
+ db_event_get(hDbEvent, &dbei);
+ if (!dbei.markedRead() && dbei.eventType == EVENTTYPE_FILE)
+ db_event_markRead(hContact, hDbEvent);
+ hDbEvent = db_event_next(hContact, hDbEvent);
+ }
+ }
+}
+
+static int SRFilePreBuildMenu(WPARAM wParam, LPARAM)
+{
+ bool bEnabled = false;
+ char *szProto = Proto_GetBaseAccountName(wParam);
+ if (szProto != nullptr) {
+ bool isChat = Contact::IsGroupChat(wParam, szProto);
+ if (CallProtoService(szProto, PS_GETCAPS, isChat ? PFLAGNUM_4 : PFLAGNUM_1, 0) & (isChat ? PF4_GROUPCHATFILES : PF1_FILESEND)) {
+ if (CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_4, 0) & PF4_OFFLINEFILES)
+ bEnabled = true;
+ else if (db_get_w(wParam, szProto, "Status", ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE)
+ bEnabled = true;
+ }
+ }
+
+ Menu_ShowItem(hSRFileMenuItem, bEnabled);
+ return 0;
+}
+
+static int SRFileProtoAck(WPARAM, LPARAM lParam)
+{
+ ACKDATA *ack = (ACKDATA*)lParam;
+ if (ack->type == ACKTYPE_FILE) {
+ int iEvent = 0;
+ while (auto *cle = Clist_GetEvent(ack->hContact, iEvent++))
+ if (cle->lParam == (LPARAM)ack->hProcess)
+ Clist_RemoveEvent(ack->hContact, cle->hDbEvent);
+ }
+ return 0;
+}
+
+static int SRFileModulesLoaded(WPARAM, LPARAM)
+{
+ CMenuItem mi(&g_plugin);
+ SET_UID(mi, 0x7f8dcf77, 0xe448, 0x4505, 0xb0, 0x56, 0xb, 0xb1, 0xab, 0xac, 0x64, 0x9d);
+ mi.position = -2000020000;
+ mi.hIcolibItem = Skin_GetIconHandle(SKINICON_EVENT_FILE);
+ mi.name.a = LPGEN("&File");
+ mi.pszService = MS_FILE_SENDFILE;
+ hSRFileMenuItem = Menu_AddContactMenuItem(&mi);
+
+ RemoveUnreadFileEvents();
+ return 0;
+}
+
+INT_PTR FtMgrShowCommand(WPARAM, LPARAM)
+{
+ FtMgr_Show(true, true);
+ return 0;
+}
+
+INT_PTR openContRecDir(WPARAM hContact, LPARAM)
+{
+ wchar_t szContRecDir[MAX_PATH];
+ GetContactReceivedFilesDir(hContact, szContRecDir, _countof(szContRecDir), TRUE);
+ ShellExecute(nullptr, L"open", szContRecDir, nullptr, nullptr, SW_SHOW);
+ return 0;
+}
+
+INT_PTR openRecDir(WPARAM, LPARAM)
+{
+ wchar_t szContRecDir[MAX_PATH];
+ GetReceivedFilesDir(szContRecDir, _countof(szContRecDir));
+ ShellExecute(nullptr, L"open", szContRecDir, nullptr, nullptr, SW_SHOW);
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR Proto_RecvFileT(WPARAM, LPARAM lParam)
+{
+ CCSDATA *ccs = (CCSDATA*)lParam;
+ PROTORECVFILE* pre = (PROTORECVFILE*)ccs->lParam;
+ if (pre->fileCount == 0)
+ return 0;
+
+ DB::EventInfo dbei;
+ dbei.szModule = Proto_GetBaseAccountName(ccs->hContact);
+ dbei.timestamp = pre->timestamp;
+ dbei.szId = pre->szId;
+ dbei.szUserId = pre->szUserId;
+ dbei.eventType = EVENTTYPE_FILE;
+ dbei.flags = DBEF_UTF;
+ if (pre->dwFlags & PRFF_SENT)
+ dbei.flags |= DBEF_SENT;
+ if (pre->dwFlags & PRFF_READ)
+ dbei.flags |= DBEF_READ;
+
+ if ((pre->dwFlags & PRFF_UNICODE) == PRFF_UNICODE) {
+ CMStringW wszFiles;
+
+ for (int i = 0; i < pre->fileCount; i++) {
+ if (i != 0)
+ wszFiles.AppendChar(',');
+ wszFiles.Append(pre->files.w[i]);
+ }
+
+ DB::FILE_BLOB blob(wszFiles, pre->descr.w);
+ CallProtoService(dbei.szModule, PS_PRECREATE_OFFLINEFILE, WPARAM(&blob), pre->lParam);
+ blob.write(dbei);
+ }
+ else {
+ bool bUtf = (pre->dwFlags & PRFF_UTF) != 0;
+ CMStringW wszFiles;
+
+ for (int i = 0; i < pre->fileCount; i++) {
+ if (i != 0)
+ wszFiles.AppendChar(',');
+
+ if (bUtf)
+ wszFiles.Append(Utf2T(pre->files.a[i]));
+ else
+ wszFiles.Append(_A2T(pre->files.a[i]));
+ }
+
+ DB::FILE_BLOB blob(wszFiles, bUtf ? Utf2T(pre->descr.a).get() : _A2T(pre->descr.a));
+ CallProtoService(dbei.szModule, PS_PRECREATE_OFFLINEFILE, WPARAM(&blob), pre->lParam);
+ blob.write(dbei);
+ }
+
+ bool bShow = (pre->dwFlags & (PRFF_SILENT | PRFF_SENT)) == 0;
+ MEVENT hdbe = db_event_add(ccs->hContact, &dbei);
+
+ CLISTEVENT cle = {};
+ cle.hContact = ccs->hContact;
+ cle.hDbEvent = hdbe;
+ cle.lParam = pre->lParam;
+
+ if (bShow && File::bAutoAccept && Contact::OnList(ccs->hContact))
+ LaunchRecvDialog(&cle);
+ else {
+ Skin_PlaySound("RecvFile");
+
+ if (bShow) {
+ wchar_t szTooltip[256];
+ mir_snwprintf(szTooltip, TranslateT("File from %s"), Clist_GetContactDisplayName(ccs->hContact));
+ cle.szTooltip.w = szTooltip;
+
+ cle.flags |= CLEF_UNICODE;
+ cle.hIcon = Skin_LoadIcon(SKINICON_EVENT_FILE);
+ cle.pszService = "SRFile/RecvFile";
+ g_clistApi.pfnAddEvent(&cle);
+ }
+ }
+
+ return hdbe;
+}
+
+int LoadSendRecvFileModule(void)
+{
+ CreateServiceFunction("FtMgr/Show", FtMgrShowCommand);
+
+ CMenuItem mi(&g_plugin);
+ SET_UID(mi, 0x75794ab5, 0x2573, 0x48f4, 0xb4, 0xa0, 0x93, 0xd6, 0xf5, 0xe0, 0xf3, 0x32);
+ mi.hIcolibItem = Skin_GetIconHandle(SKINICON_EVENT_FILE);
+ mi.position = 1900000000;
+ mi.name.a = LPGEN("File &transfers...");
+ mi.pszService = "FtMgr/Show"; //MS_PROTO_SHOWFTMGR;
+ Menu_AddMainMenuItem(&mi);
+
+ HookEvent(ME_SYSTEM_MODULESLOADED, SRFileModulesLoaded);
+ HookEvent(ME_OPT_INITIALISE, FileOptInitialise);
+ HookEvent(ME_CLIST_PREBUILDCONTACTMENU, SRFilePreBuildMenu);
+ HookEvent(ME_PROTO_ACK, SRFileProtoAck);
+
+ hDlgSucceeded = CreateHookableEvent(ME_FILEDLG_SUCCEEDED);
+ hDlgCanceled = CreateHookableEvent(ME_FILEDLG_CANCELED);
+
+ CreateServiceFunction(MS_PROTO_RECVFILET, Proto_RecvFileT);
+
+ CreateServiceFunction(MS_FILE_SENDFILE, SendFileCommand);
+ CreateServiceFunction(MS_FILE_SENDSPECIFICFILES, SendSpecificFiles);
+ CreateServiceFunction(MS_FILE_SENDSPECIFICFILEST, SendSpecificFilesT);
+ CreateServiceFunction(MS_FILE_GETRECEIVEDFILESFOLDER, GetReceivedFilesFolder);
+ CreateServiceFunction(MS_FILE_GETRECEIVEDFILESFOLDERW, GetReceivedFilesFolderW);
+ CreateServiceFunction("SRFile/RecvFile", RecvFileCommand);
+
+ CreateServiceFunction("SRFile/OpenContRecDir", openContRecDir);
+ CreateServiceFunction("SRFile/OpenRecDir", openRecDir);
+
+ g_plugin.addSound("RecvFile", LPGENW("File"), LPGENW("Incoming"));
+ g_plugin.addSound("FileDone", LPGENW("File"), LPGENW("Complete"));
+ g_plugin.addSound("FileFailed", LPGENW("File"), LPGENW("Error"));
+ g_plugin.addSound("FileDenied", LPGENW("File"), LPGENW("Denied"));
+ return 0;
+}
diff --git a/src/core/stdfile/src/file.h b/src/mir_app/src/file.h
index e586ba645d..a394721b50 100644
--- a/src/core/stdfile/src/file.h
+++ b/src/mir_app/src/file.h
@@ -1,129 +1,136 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda 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.
-*/
-
-#pragma once
-
-#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
-{
- MCONTACT hContact;
- const wchar_t **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 : public MZeroedObject
-{
- ~FileDlgData();
-
- HWND hwndTransfer;
- HANDLE fs;
- MCONTACT hContact;
- MEVENT hDbEvent;
- HANDLE hNotifyEvent;
- HICON hIcon, hIconFolder;
- wchar_t **files;
- int send;
- int closeIfFileChooseCancelled;
- int resumeBehaviour;
- int bytesRecvedHistory[BYTESRECVEDHISTORYCOUNT];
- int bytesRecvedHistorySize;
- int waitingForAcceptance;
- PROTOFILETRANSFERSTATUS transferStatus;
- int *fileVirusScanned;
- HANDLE hPreshutdownEvent;
- uint32_t dwTicks;
-
- wchar_t szSavePath[MAX_PATH];
- wchar_t szMsg[450], szFilenames[1024];
-};
-
-//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, wchar_t *szOut, int cchOut, int unitsOverride, int appendUnits, int *unitsUsed);
-void FreeFilesMatrix(wchar_t ***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 wchar_t *szSubKey, const wchar_t *szValue, wchar_t *szOutput, int cbOutput);
-
-// filesenddlg.c
-INT_PTR CALLBACK DlgProcSendFile(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
-
-// filerecv.c
-void LaunchRecvDialog(CLISTEVENT *cle);
-void RemoveInvalidFilenameChars(wchar_t *tszString);
-void RemoveInvalidPathChars(wchar_t *tszString);
-void GetContactReceivedFilesDir(MCONTACT hContact, wchar_t *szDir, int cchDir, BOOL substVars);
-void GetReceivedFilesDir(wchar_t *szDir, int cchDir);
-int BrowseForFolder(HWND hwnd, wchar_t *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)
-
-#define HM_RECVEVENT (WM_USER+10)
-
-HWND FtMgr_Show(bool bForceActivate, bool bFromMenu);
-void FtMgr_Destroy();
-void FtMgr_AddTransfer(FileDlgData *dat);
-
-extern HANDLE hDlgSucceeded, hDlgCanceled;
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda 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.
+*/
+
+#pragma once
+
+#define SRFILEMODULE "SRFile"
+
+#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
+{
+ MCONTACT hContact;
+ const wchar_t **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 : public MZeroedObject
+{
+ ~FileDlgData();
+
+ HWND hwndTransfer;
+ HANDLE fs;
+ MCONTACT hContact;
+ MEVENT hDbEvent;
+ HANDLE hNotifyEvent;
+ HICON hIcon, hIconFolder;
+ wchar_t **files;
+ int send;
+ int closeIfFileChooseCancelled;
+ int resumeBehaviour;
+ int bytesRecvedHistory[BYTESRECVEDHISTORYCOUNT];
+ int bytesRecvedHistorySize;
+ int waitingForAcceptance;
+ PROTOFILETRANSFERSTATUS transferStatus;
+ int *fileVirusScanned;
+ HANDLE hPreshutdownEvent;
+ uint32_t dwTicks;
+
+ wchar_t szSavePath[MAX_PATH];
+ wchar_t szMsg[450], szFilenames[1024];
+};
+
+//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, wchar_t *szOut, int cchOut, int unitsOverride, int appendUnits, int *unitsUsed);
+void FreeFilesMatrix(wchar_t ***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 wchar_t *szSubKey, const wchar_t *szValue, wchar_t *szOutput, int cbOutput);
+
+// filesenddlg.c
+INT_PTR CALLBACK DlgProcSendFile(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+// filerecv.c
+void LaunchRecvDialog(CLISTEVENT *cle);
+void RemoveInvalidFilenameChars(wchar_t *tszString);
+void RemoveInvalidPathChars(wchar_t *tszString);
+void GetContactReceivedFilesDir(MCONTACT hContact, wchar_t *szDir, int cchDir, BOOL substVars);
+void GetReceivedFilesDir(wchar_t *szDir, int cchDir);
+int BrowseForFolder(HWND hwnd, wchar_t *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)
+
+#define HM_RECVEVENT (WM_USER+10)
+
+HWND FtMgr_Show(bool bForceActivate, bool bFromMenu);
+void FtMgr_Destroy();
+void FtMgr_AddTransfer(FileDlgData *dat);
+
+extern HANDLE hDlgSucceeded, hDlgCanceled;
+
+namespace File
+{
+ extern CMOption<bool> bAutoMin, bAutoClear, bAutoClose, bAutoAccept, bReverseOrder;
+};
diff --git a/src/core/stdfile/src/fileexistsdlg.cpp b/src/mir_app/src/fileexistsdlg.cpp
index c2e4f6dfa8..d75e2f6eae 100644
--- a/src/core/stdfile/src/fileexistsdlg.cpp
+++ b/src/mir_app/src/fileexistsdlg.cpp
@@ -1,340 +1,340 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda 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 "stdafx.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 = (11644473600ll + (__int64)unixTime) * 10000000;
- filetime.dwHighDateTime = liFiletime.HighPart;
- filetime.dwLowDateTime = liFiletime.LowPart;
- FileTimeToSystemTime(&filetime, &st);
- GetTimeFormatA(LOCALE_USER_DEFAULT, 0, &st, NULL, szTime, _countof(szTime));
- GetDateFormatA(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, szDate, _countof(szDate));
- mir_snprintf(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 wchar_t *szFilename, int cmd, POINT *ptCursor)
-{
- IShellFolder *pDesktopFolder;
- if (SHGetDesktopFolder(&pDesktopFolder) == NOERROR) {
- ITEMIDLIST *pCurrentIdl;
- wchar_t *wszFilename = (LPWSTR)szFilename;
-
- if (pDesktopFolder->ParseDisplayName(nullptr, nullptr, wszFilename, nullptr, &pCurrentIdl, nullptr) == NOERROR) {
- if (pCurrentIdl->mkid.cb) {
- ITEMIDLIST *pidl, *pidlNext, *pidlFilename;
- IShellFolder *pFileFolder;
-
- for (pidl = pCurrentIdl;;) {
- pidlNext = (ITEMIDLIST *)((uint8_t*)pidl + pidl->mkid.cb);
- if (pidlNext->mkid.cb == 0) {
- pidlFilename = (ITEMIDLIST *)CoTaskMemAlloc(pidl->mkid.cb + sizeof(pidl->mkid.cb));
- memcpy(pidlFilename, pidl, pidl->mkid.cb + sizeof(pidl->mkid.cb));
- pidl->mkid.cb = 0;
- break;
- }
- pidl = pidlNext;
- }
- if (pDesktopFolder->BindToObject(pCurrentIdl, nullptr, IID_IShellFolder, (void **)&pFileFolder) == NOERROR) {
- IContextMenu *pContextMenu;
- if (pFileFolder->GetUIObjectOf(nullptr, 1, (LPCITEMIDLIST *)&pidlFilename, IID_IContextMenu, nullptr, (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 = CreatePopupMenu();
- if (SUCCEEDED(pContextMenu->QueryContextMenu(hMenu, 0, 1000, 65535, (GetKeyState(VK_SHIFT) & 0x8000 ? CMF_EXTENDEDVERBS : 0) | CMF_NORMAL))) {
- int ret = TrackPopupMenu(hMenu, TPM_RETURNCMD, ptCursor->x, ptCursor->y, 0, hwnd, nullptr);
- if (ret) {
- CMINVOKECOMMANDINFO ici = { 0 };
- ici.cbSize = sizeof(ici);
- ici.hwnd = hwnd;
- ici.lpVerb = MAKEINTRESOURCEA(ret - 1000);
- ici.nShow = SW_SHOW;
- pContextMenu->InvokeCommand(&ici);
- }
- }
- DestroyMenu(hMenu);
- break;
- }
- pContextMenu->Release();
- }
- pFileFolder->Release();
- }
- CoTaskMemFree(pidlFilename);
- }
- CoTaskMemFree(pCurrentIdl);
- }
- pDesktopFolder->Release();
- }
-}
-
-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, nullptr, pft->szCurrentFile.w, nullptr, nullptr, SW_SHOW);
- break;
- case WM_RBUTTONUP:
- POINT pt;
- pt.x = (short)LOWORD(lParam); pt.y = (short)HIWORD(lParam);
- ClientToScreen(hwnd, &pt);
- DoAnnoyingShellCommand(hwnd, pft->szCurrentFile.w, C_CONTEXTMENU, &pt);
- return 0;
- }
- return mir_callNextSubclass(hwnd, IconCtrlSubclassProc, msg, wParam, lParam);
-}
-
-struct loadiconsstartinfo
-{
- HWND hwndDlg;
- wchar_t *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)) {
- wchar_t szExtension[64], szIconFile[MAX_PATH];
-
- wchar_t *pszFilename = wcsrchr(info->szFilename, '\\');
- if (pszFilename == nullptr)
- pszFilename = info->szFilename;
-
- wchar_t *pszExtension = wcsrchr(pszFilename, '.');
- if (pszExtension)
- mir_wstrncpy(szExtension, pszExtension + 1, _countof(szExtension));
- else {
- pszExtension = L".";
- szExtension[0] = '\0';
- }
- CharUpper(szExtension);
- if (fileInfo.szTypeName[0] == '\0')
- mir_snwprintf(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 (!mir_wstrcmp(szExtension, L"EXE"))
- SRFile_GetRegValue(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Icons", L"2", szIconFile, _countof(szIconFile));
- else {
- wchar_t szTypeName[MAX_PATH];
- if (SRFile_GetRegValue(HKEY_CLASSES_ROOT, pszExtension, NULL, szTypeName, _countof(szTypeName))) {
- mir_wstrcat(szTypeName, L"\\DefaultIcon");
- if (SRFile_GetRegValue(HKEY_CLASSES_ROOT, szTypeName, NULL, szIconFile, _countof(szIconFile))) {
- if (wcsstr(szIconFile, L"%1"))
- SRFile_GetRegValue(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Icons", L"0", szIconFile, _countof(szIconFile));
- else szIconFile[0] = '\0';
- }
- }
- }
-
- if (szIconFile[0]) {
- wchar_t *pszComma = wcsrchr(szIconFile, ',');
- int iconIndex;
- if (pszComma) {
- iconIndex = _wtoi(pszComma + 1);
- *pszComma = '\0';
- }
- else
- iconIndex = 0;
- HICON hIcon = ExtractIcon(g_plugin.getInst(), 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 = (PROTOFILETRANSFERSTATUS *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
- switch (msg) {
- case WM_INITDIALOG:
- TranslateDialogDefault(hwndDlg);
- {
- wchar_t szSize[64];
- struct _stati64 statbuf;
- auto *dat = (TDlgProcFileExistsParam *)lParam;
-
- SetPropA(hwndDlg, "Miranda.Preshutdown", HookEventMessage(ME_SYSTEM_PRESHUTDOWN, hwndDlg, M_PRESHUTDOWN));
- SetPropA(hwndDlg, "Miranda.ParentWnd", dat->hwndParent);
-
- fts = (PROTOFILETRANSFERSTATUS *)mir_alloc(sizeof(PROTOFILETRANSFERSTATUS));
- CopyProtoFileTransferStatus(fts, dat->fts);
- SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)fts);
- SetDlgItemText(hwndDlg, IDC_FILENAME, fts->szCurrentFile.w);
- SetControlToUnixTime(hwndDlg, IDC_NEWDATE, fts->currentFileTime);
- GetSensiblyFormattedSize(fts->currentFileSize, szSize, _countof(szSize), 0, 1, NULL);
- SetDlgItemText(hwndDlg, IDC_NEWSIZE, szSize);
-
- mir_subclassWindow(GetDlgItem(hwndDlg, IDC_EXISTINGICON), IconCtrlSubclassProc);
-
- HWND hwndFocus = GetDlgItem(hwndDlg, IDC_RESUME);
- if (_wstat64(fts->szCurrentFile.w, &statbuf) == 0) {
- SetControlToUnixTime(hwndDlg, IDC_EXISTINGDATE, statbuf.st_mtime);
- GetSensiblyFormattedSize(statbuf.st_size, szSize, _countof(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_wstrdup(fts->szCurrentFile.w);
- //can be a little slow, so why not?
- mir_forkthread(LoadIconsAndTypesThread, lisi);
- SetFocus(hwndFocus);
- SetWindowLongPtr(hwndFocus, GWL_STYLE, GetWindowLongPtr(hwndFocus, GWL_STYLE) | BS_DEFPUSHBUTTON);
- }
- return FALSE;
-
- case WM_COMMAND:
- {
- PROTOFILERESUME pfr = {};
- switch (LOWORD(wParam)) {
- case IDC_OPENFILE:
- ShellExecute(hwndDlg, NULL, fts->szCurrentFile.w, NULL, NULL, SW_SHOW);
- return FALSE;
-
- case IDC_OPENFOLDER:
- {
- wchar_t szFile[MAX_PATH];
- mir_wstrncpy(szFile, fts->szCurrentFile.w, _countof(szFile));
- wchar_t *pszLastBackslash = wcsrchr(szFile, '\\');
- if (pszLastBackslash)
- *pszLastBackslash = '\0';
- ShellExecute(hwndDlg, NULL, szFile, NULL, NULL, SW_SHOW);
- }
- return FALSE;
- case IDC_PROPERTIES:
- DoAnnoyingShellCommand(hwndDlg, fts->szCurrentFile.w, 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:
- wchar_t str[MAX_PATH];
- mir_wstrncpy(str, fts->szCurrentFile.w, _countof(str));
-
- wchar_t filter[512];
- mir_snwprintf(filter, L"%s (*)%c*%c", TranslateT("All files"), 0, 0);
- {
- OPENFILENAME ofn = {};
- ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
- ofn.hwndOwner = hwndDlg;
- ofn.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
- ofn.lpstrFilter = filter;
- ofn.lpstrFile = str;
- ofn.nMaxFile = _countof(str);
- ofn.nMaxFileTitle = MAX_PATH;
- if (!GetSaveFileName(&ofn))
- return FALSE;
-
- pfr.szFilename = mir_wstrdup(str);
- pfr.action = FILERESUME_RENAME;
- }
- break;
-
- case IDC_SKIP:
- pfr.action = FILERESUME_SKIP;
- break;
-
- case IDCANCEL:
- pfr.action = FILERESUME_CANCEL;
- break;
-
- default:
- return FALSE;
- }
-
- PostMessage((HWND)GetPropA(hwndDlg, "Miranda.ParentWnd"), M_FILEEXISTSDLGREPLY, (WPARAM)mir_wstrdup(fts->szCurrentFile.w), (LPARAM)new PROTOFILERESUME(pfr));
- 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;
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda 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 "stdafx.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 = (11644473600ll + (__int64)unixTime) * 10000000;
+ filetime.dwHighDateTime = liFiletime.HighPart;
+ filetime.dwLowDateTime = liFiletime.LowPart;
+ FileTimeToSystemTime(&filetime, &st);
+ GetTimeFormatA(LOCALE_USER_DEFAULT, 0, &st, NULL, szTime, _countof(szTime));
+ GetDateFormatA(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, szDate, _countof(szDate));
+ mir_snprintf(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 wchar_t *szFilename, int cmd, POINT *ptCursor)
+{
+ IShellFolder *pDesktopFolder;
+ if (SHGetDesktopFolder(&pDesktopFolder) == NOERROR) {
+ ITEMIDLIST *pCurrentIdl;
+ wchar_t *wszFilename = (LPWSTR)szFilename;
+
+ if (pDesktopFolder->ParseDisplayName(nullptr, nullptr, wszFilename, nullptr, &pCurrentIdl, nullptr) == NOERROR) {
+ if (pCurrentIdl->mkid.cb) {
+ ITEMIDLIST *pidl, *pidlNext, *pidlFilename;
+ IShellFolder *pFileFolder;
+
+ for (pidl = pCurrentIdl;;) {
+ pidlNext = (ITEMIDLIST *)((uint8_t*)pidl + pidl->mkid.cb);
+ if (pidlNext->mkid.cb == 0) {
+ pidlFilename = (ITEMIDLIST *)CoTaskMemAlloc(pidl->mkid.cb + sizeof(pidl->mkid.cb));
+ memcpy(pidlFilename, pidl, pidl->mkid.cb + sizeof(pidl->mkid.cb));
+ pidl->mkid.cb = 0;
+ break;
+ }
+ pidl = pidlNext;
+ }
+ if (pDesktopFolder->BindToObject(pCurrentIdl, nullptr, IID_IShellFolder, (void **)&pFileFolder) == NOERROR) {
+ IContextMenu *pContextMenu;
+ if (pFileFolder->GetUIObjectOf(nullptr, 1, (LPCITEMIDLIST *)&pidlFilename, IID_IContextMenu, nullptr, (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 = CreatePopupMenu();
+ if (SUCCEEDED(pContextMenu->QueryContextMenu(hMenu, 0, 1000, 65535, (GetKeyState(VK_SHIFT) & 0x8000 ? CMF_EXTENDEDVERBS : 0) | CMF_NORMAL))) {
+ int ret = TrackPopupMenu(hMenu, TPM_RETURNCMD, ptCursor->x, ptCursor->y, 0, hwnd, nullptr);
+ if (ret) {
+ CMINVOKECOMMANDINFO ici = { 0 };
+ ici.cbSize = sizeof(ici);
+ ici.hwnd = hwnd;
+ ici.lpVerb = MAKEINTRESOURCEA(ret - 1000);
+ ici.nShow = SW_SHOW;
+ pContextMenu->InvokeCommand(&ici);
+ }
+ }
+ DestroyMenu(hMenu);
+ break;
+ }
+ pContextMenu->Release();
+ }
+ pFileFolder->Release();
+ }
+ CoTaskMemFree(pidlFilename);
+ }
+ CoTaskMemFree(pCurrentIdl);
+ }
+ pDesktopFolder->Release();
+ }
+}
+
+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, nullptr, pft->szCurrentFile.w, nullptr, nullptr, SW_SHOW);
+ break;
+ case WM_RBUTTONUP:
+ POINT pt;
+ pt.x = (short)LOWORD(lParam); pt.y = (short)HIWORD(lParam);
+ ClientToScreen(hwnd, &pt);
+ DoAnnoyingShellCommand(hwnd, pft->szCurrentFile.w, C_CONTEXTMENU, &pt);
+ return 0;
+ }
+ return mir_callNextSubclass(hwnd, IconCtrlSubclassProc, msg, wParam, lParam);
+}
+
+struct loadiconsstartinfo
+{
+ HWND hwndDlg;
+ wchar_t *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)) {
+ wchar_t szExtension[64], szIconFile[MAX_PATH];
+
+ wchar_t *pszFilename = wcsrchr(info->szFilename, '\\');
+ if (pszFilename == nullptr)
+ pszFilename = info->szFilename;
+
+ wchar_t *pszExtension = wcsrchr(pszFilename, '.');
+ if (pszExtension)
+ mir_wstrncpy(szExtension, pszExtension + 1, _countof(szExtension));
+ else {
+ pszExtension = L".";
+ szExtension[0] = '\0';
+ }
+ CharUpper(szExtension);
+ if (fileInfo.szTypeName[0] == '\0')
+ mir_snwprintf(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 (!mir_wstrcmp(szExtension, L"EXE"))
+ SRFile_GetRegValue(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Icons", L"2", szIconFile, _countof(szIconFile));
+ else {
+ wchar_t szTypeName[MAX_PATH];
+ if (SRFile_GetRegValue(HKEY_CLASSES_ROOT, pszExtension, NULL, szTypeName, _countof(szTypeName))) {
+ mir_wstrcat(szTypeName, L"\\DefaultIcon");
+ if (SRFile_GetRegValue(HKEY_CLASSES_ROOT, szTypeName, NULL, szIconFile, _countof(szIconFile))) {
+ if (wcsstr(szIconFile, L"%1"))
+ SRFile_GetRegValue(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Icons", L"0", szIconFile, _countof(szIconFile));
+ else szIconFile[0] = '\0';
+ }
+ }
+ }
+
+ if (szIconFile[0]) {
+ wchar_t *pszComma = wcsrchr(szIconFile, ',');
+ int iconIndex;
+ if (pszComma) {
+ iconIndex = _wtoi(pszComma + 1);
+ *pszComma = '\0';
+ }
+ else
+ iconIndex = 0;
+ HICON hIcon = ExtractIcon(g_plugin.getInst(), 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 = (PROTOFILETRANSFERSTATUS *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ {
+ wchar_t szSize[64];
+ struct _stati64 statbuf;
+ auto *dat = (TDlgProcFileExistsParam *)lParam;
+
+ SetPropA(hwndDlg, "Miranda.Preshutdown", HookEventMessage(ME_SYSTEM_PRESHUTDOWN, hwndDlg, M_PRESHUTDOWN));
+ SetPropA(hwndDlg, "Miranda.ParentWnd", dat->hwndParent);
+
+ fts = (PROTOFILETRANSFERSTATUS *)mir_alloc(sizeof(PROTOFILETRANSFERSTATUS));
+ CopyProtoFileTransferStatus(fts, dat->fts);
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)fts);
+ SetDlgItemText(hwndDlg, IDC_FILENAME, fts->szCurrentFile.w);
+ SetControlToUnixTime(hwndDlg, IDC_NEWDATE, fts->currentFileTime);
+ GetSensiblyFormattedSize(fts->currentFileSize, szSize, _countof(szSize), 0, 1, NULL);
+ SetDlgItemText(hwndDlg, IDC_NEWSIZE, szSize);
+
+ mir_subclassWindow(GetDlgItem(hwndDlg, IDC_EXISTINGICON), IconCtrlSubclassProc);
+
+ HWND hwndFocus = GetDlgItem(hwndDlg, IDC_RESUME);
+ if (_wstat64(fts->szCurrentFile.w, &statbuf) == 0) {
+ SetControlToUnixTime(hwndDlg, IDC_EXISTINGDATE, statbuf.st_mtime);
+ GetSensiblyFormattedSize(statbuf.st_size, szSize, _countof(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_wstrdup(fts->szCurrentFile.w);
+ //can be a little slow, so why not?
+ mir_forkthread(LoadIconsAndTypesThread, lisi);
+ SetFocus(hwndFocus);
+ SetWindowLongPtr(hwndFocus, GWL_STYLE, GetWindowLongPtr(hwndFocus, GWL_STYLE) | BS_DEFPUSHBUTTON);
+ }
+ return FALSE;
+
+ case WM_COMMAND:
+ {
+ PROTOFILERESUME pfr = {};
+ switch (LOWORD(wParam)) {
+ case IDC_OPENFILE:
+ ShellExecute(hwndDlg, NULL, fts->szCurrentFile.w, NULL, NULL, SW_SHOW);
+ return FALSE;
+
+ case IDC_OPENFOLDER:
+ {
+ wchar_t szFile[MAX_PATH];
+ mir_wstrncpy(szFile, fts->szCurrentFile.w, _countof(szFile));
+ wchar_t *pszLastBackslash = wcsrchr(szFile, '\\');
+ if (pszLastBackslash)
+ *pszLastBackslash = '\0';
+ ShellExecute(hwndDlg, NULL, szFile, NULL, NULL, SW_SHOW);
+ }
+ return FALSE;
+ case IDC_PROPERTIES:
+ DoAnnoyingShellCommand(hwndDlg, fts->szCurrentFile.w, 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:
+ wchar_t str[MAX_PATH];
+ mir_wstrncpy(str, fts->szCurrentFile.w, _countof(str));
+
+ wchar_t filter[512];
+ mir_snwprintf(filter, L"%s (*)%c*%c", TranslateT("All files"), 0, 0);
+ {
+ OPENFILENAME ofn = {};
+ ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
+ ofn.hwndOwner = hwndDlg;
+ ofn.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
+ ofn.lpstrFilter = filter;
+ ofn.lpstrFile = str;
+ ofn.nMaxFile = _countof(str);
+ ofn.nMaxFileTitle = MAX_PATH;
+ if (!GetSaveFileName(&ofn))
+ return FALSE;
+
+ pfr.szFilename = mir_wstrdup(str);
+ pfr.action = FILERESUME_RENAME;
+ }
+ break;
+
+ case IDC_SKIP:
+ pfr.action = FILERESUME_SKIP;
+ break;
+
+ case IDCANCEL:
+ pfr.action = FILERESUME_CANCEL;
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ PostMessage((HWND)GetPropA(hwndDlg, "Miranda.ParentWnd"), M_FILEEXISTSDLGREPLY, (WPARAM)mir_wstrdup(fts->szCurrentFile.w), (LPARAM)new PROTOFILERESUME(pfr));
+ 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/core/stdfile/src/fileopts.cpp b/src/mir_app/src/fileopts.cpp
index f0d9e1bda2..d3a94c5b18 100644
--- a/src/core/stdfile/src/fileopts.cpp
+++ b/src/mir_app/src/fileopts.cpp
@@ -1,241 +1,241 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda 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 "stdafx.h"
-#include "file.h"
-
-#define VSCAN_MCAFEE 1
-#define VSCAN_DRSOLOMON 2
-#define VSCAN_NORTON 3
-#define VSCAN_CA 4
-
-struct {
- const wchar_t *szProductName;
- const wchar_t *szExeRegPath;
- const wchar_t *szExeRegValue;
- const wchar_t *szCommandLine;
-}
-static virusScanners[] =
-{
- {L"Network Associates/McAfee VirusScan", L"SOFTWARE\\McAfee\\VirusScan", L"Scan32EXE", L"\"%s\" %%f /nosplash /comp /autoscan /autoexit /noboot"},
- {L"Dr Solomon's VirusScan (Network Associates)", L"SOFTWARE\\Network Associates\\TVD\\VirusScan\\AVConsol\\General", L"szScannerExe", L"\"%s\" %%f /uinone /noboot /comp /prompt /autoexit"},
- {L"Norton AntiVirus", L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\Navw32.exe", nullptr, L"\"%s\" %%f /b- /m- /s+ /noresults"},
- {L"Computer Associates/Inoculate IT", L"Software\\Antivirus", L"ImageFilename", L"\"%s\" %%f /display = progress /exit"},
- {L"Computer Associates eTrust", L"SOFTWARE\\ComputerAssociates\\Anti-Virus\\Resident", L"VetPath", L"\"%s\" %%f /display = progress /exit"},
- {L"Kaspersky Anti-Virus", L"SOFTWARE\\KasperskyLab\\Components\\101", L"EXEName", L"\"%s\" /S /Q %%f"},
- {L"Kaspersky Anti-Virus", L"SOFTWARE\\KasperskyLab\\SetupFolders", L"KAV8", L"\"%savp.exe\" SCAN %%f"},
- {L"Kaspersky Anti-Virus", L"SOFTWARE\\KasperskyLab\\SetupFolders", L"KAV9", L"\"%savp.exe\" SCAN %%f"},
- {L"AntiVir PersonalEdition Classic", L"SOFTWARE\\Avira\\AntiVir PersonalEdition Classic", L"Path", L"\"%savscan.exe\" /GUIMODE = 2 /PATH = \"%%f\""},
- {L"ESET NOD32 Antivirus", L"SOFTWARE\\ESET\\ESET Security\\CurrentVersion\\Info", L"InstallDir", L"\"%secls.exe\" /log-all /aind /no-boots /adware /sfx /unsafe /unwanted /heur /adv-heur /action = clean \"%%f\""},
-};
-
-#ifndef SHACF_FILESYS_DIRS
- #define SHACF_FILESYS_DIRS 0x00000020
-#endif
-
-class CFileOptsDlg : public CDlgBase
-{
- CCtrlButton btnFileDir, btnScanCmdLine;
- CCtrlCheck chkAutoMin, chkAutoClear, chkAutoClose, chkAutoAccept, chkReverseOrder;
- CCtrlCheck chkNoScanner, chkScanDuringDl, chkScanAfterDl;
- CCtrlCombo cmbScanCmdLine;
-
-public:
- CFileOptsDlg() :
- CDlgBase(g_plugin, IDD_OPT_FILETRANSFER),
- btnFileDir(this, IDC_FILEDIRBROWSE),
- btnScanCmdLine(this, IDC_SCANCMDLINEBROWSE),
- chkAutoMin(this, IDC_AUTOMIN),
- chkAutoClear(this, IDC_AUTOCLEAR),
- chkAutoClose(this, IDC_AUTOCLOSE),
- chkAutoAccept(this, IDC_AUTOACCEPT),
- chkReverseOrder(this, IDC_REVERSE_ORDER),
-
- chkNoScanner(this, IDC_NOSCANNER),
- chkScanAfterDl(this, IDC_SCANAFTERDL),
- chkScanDuringDl(this, IDC_SCANDURINGDL),
-
- cmbScanCmdLine(this, IDC_SCANCMDLINE)
- {
- CreateLink(chkAutoMin, g_plugin.bAutoMin);
- CreateLink(chkAutoClear, g_plugin.bAutoClear);
- CreateLink(chkAutoClose, g_plugin.bAutoClose);
- CreateLink(chkAutoAccept, g_plugin.bAutoAccept);
- CreateLink(chkReverseOrder, g_plugin.bReverseOrder);
-
- btnFileDir.OnClick = Callback(this, &CFileOptsDlg::onClick_FileDir);
- btnScanCmdLine.OnClick = Callback(this, &CFileOptsDlg::onClick_ScanCmdLine);
-
- chkNoScanner.OnChange = Callback(this, &CFileOptsDlg::onChange_NoScanner);
- chkAutoAccept.OnChange = Callback(this, &CFileOptsDlg::onChange_AutoAccept);
- cmbScanCmdLine.OnSelChanged = Callback(this, &CFileOptsDlg::onSelChanged_Combo);
- }
-
- bool OnInitDialog() override
- {
- SHAutoComplete(GetDlgItem(m_hwnd, IDC_FILEDIR), SHACF_FILESYS_DIRS);
-
- wchar_t str[MAX_PATH];
- GetContactReceivedFilesDir(NULL, str, _countof(str), FALSE);
- SetDlgItemText(m_hwnd, IDC_FILEDIR, str);
-
- switch (g_plugin.getByte("UseScanner", VIRUSSCAN_DISABLE)) {
- case VIRUSSCAN_AFTERDL: chkScanAfterDl.SetState(true); break;
- case VIRUSSCAN_DURINGDL: chkScanDuringDl.SetState(true); break;
- default: chkNoScanner.SetState(true); break;
- }
- CheckDlgButton(m_hwnd, IDC_WARNBEFOREOPENING, g_plugin.getByte("WarnBeforeOpening", 1) ? BST_CHECKED : BST_UNCHECKED);
-
- for (int i = 0; i < _countof(virusScanners); i++) {
- wchar_t szScanExe[MAX_PATH];
- if (SRFile_GetRegValue(HKEY_LOCAL_MACHINE, virusScanners[i].szExeRegPath, virusScanners[i].szExeRegValue, szScanExe, _countof(szScanExe)))
- cmbScanCmdLine.AddString(virusScanners[i].szProductName, i);
- }
-
- if (!cmbScanCmdLine.GetCount())
- cmbScanCmdLine.AddString(L"", -1);
-
- DBVARIANT dbv;
- if (g_plugin.getWString("ScanCmdLine", &dbv) == 0) {
- cmbScanCmdLine.SetText(dbv.pwszVal);
- db_free(&dbv);
- }
- else if (cmbScanCmdLine.GetCount()) {
- cmbScanCmdLine.SetCurSel(0);
- onSelChanged_Combo(0);
- }
-
- switch (g_plugin.getByte("IfExists", FILERESUME_ASK)) {
- case FILERESUME_RESUMEALL: CheckDlgButton(m_hwnd, IDC_RESUME, BST_CHECKED); break;
- case FILERESUME_OVERWRITEALL: CheckDlgButton(m_hwnd, IDC_OVERWRITE, BST_CHECKED); break;
- case FILERESUME_RENAMEALL: CheckDlgButton(m_hwnd, IDC_RENAME, BST_CHECKED); break;
- default: CheckDlgButton(m_hwnd, IDC_ASK, BST_CHECKED); break;
- }
-
- return true;
- }
-
- bool OnApply() override
- {
- wchar_t str[512];
- GetDlgItemText(m_hwnd, IDC_FILEDIR, str, _countof(str));
- RemoveInvalidPathChars(str);
- g_plugin.setWString("RecvFilesDirAdv", str);
-
- cmbScanCmdLine.GetText(str, _countof(str));
- g_plugin.setWString("ScanCmdLine", str);
-
- g_plugin.setByte("UseScanner", chkScanAfterDl.GetState() ? VIRUSSCAN_AFTERDL : (chkScanDuringDl.GetState() ? VIRUSSCAN_DURINGDL : VIRUSSCAN_DISABLE));
- g_plugin.setByte("WarnBeforeOpening", (uint8_t)IsDlgButtonChecked(m_hwnd, IDC_WARNBEFOREOPENING));
- g_plugin.setByte("IfExists", (uint8_t)(IsDlgButtonChecked(m_hwnd, IDC_ASK) ? FILERESUME_ASK :
- (IsDlgButtonChecked(m_hwnd, IDC_RESUME) ? FILERESUME_RESUMEALL :
- (IsDlgButtonChecked(m_hwnd, IDC_OVERWRITE) ? FILERESUME_OVERWRITEALL : FILERESUME_RENAMEALL))));
- return TRUE;
- }
-
- void onChange_AutoAccept(CCtrlCheck *)
- {
- chkAutoMin.Enable(chkAutoAccept.GetState());
- }
-
- void onChange_NoScanner(CCtrlCheck *)
- {
- bool bEnabled = chkNoScanner.GetState();
- btnScanCmdLine.Enable(bEnabled);
- cmbScanCmdLine.Enable(bEnabled);
- EnableWindow(GetDlgItem(m_hwnd, IDC_ST_CMDLINE), bEnabled);
- EnableWindow(GetDlgItem(m_hwnd, IDC_ST_CMDLINEHELP), bEnabled);
- }
-
- void onSelChanged_Combo(CCtrlCombo*)
- {
- int iScanner = cmbScanCmdLine.GetCurData();
- if (iScanner >= _countof(virusScanners) || iScanner < 0)
- return;
-
- wchar_t szScanExe[MAX_PATH], str[512];
- if (SRFile_GetRegValue(HKEY_LOCAL_MACHINE, virusScanners[iScanner].szExeRegPath, virusScanners[iScanner].szExeRegValue, szScanExe, _countof(szScanExe)))
- mir_snwprintf(str, virusScanners[iScanner].szCommandLine, szScanExe);
- else
- str[0] = 0;
- cmbScanCmdLine.SetText(str);
- }
-
- void onClick_FileDir(CCtrlButton*)
- {
- wchar_t str[MAX_PATH];
- GetDlgItemText(m_hwnd, IDC_FILEDIR, str, _countof(str));
- if (BrowseForFolder(m_hwnd, str))
- SetDlgItemText(m_hwnd, IDC_FILEDIR, str);
- }
-
- void onClick_ScanCmdLine(CCtrlButton*)
- {
- wchar_t str[MAX_PATH + 2];
- cmbScanCmdLine.GetText(str, _countof(str));
-
- CMStringW tszFilter;
- tszFilter.AppendFormat(L"%s (*.exe)%c*.exe%c", TranslateT("Executable files"), 0, 0);
- tszFilter.AppendFormat(L"%s (*)%c*%c", TranslateT("All files"), 0, 0);
-
- OPENFILENAME ofn = { 0 };
- ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
- ofn.hwndOwner = m_hwnd;
- ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_DONTADDTORECENT;
- ofn.lpstrFilter = tszFilter;
- ofn.lpstrFile = str;
- ofn.nMaxFile = _countof(str) - 2;
- if (str[0] == '"') {
- wchar_t *pszQuote = wcschr(str + 1, '"');
- if (pszQuote)
- *pszQuote = 0;
- memmove(str, str + 1, (mir_wstrlen(str) * sizeof(wchar_t)));
- }
- else {
- wchar_t *pszSpace = wcschr(str, ' ');
- if (pszSpace) *pszSpace = 0;
- }
- ofn.nMaxFileTitle = MAX_PATH;
- if (!GetOpenFileName(&ofn))
- return;
-
- if (wcschr(str, ' ') != nullptr) {
- memmove(str + 1, str, ((_countof(str) - 2) * sizeof(wchar_t)));
- str[0] = '"';
- mir_wstrcat(str, L"\"");
- }
- cmbScanCmdLine.SetText(str);
- }
-};
-
-int FileOptInitialise(WPARAM wParam, LPARAM)
-{
- OPTIONSDIALOGPAGE odp = {};
- odp.position = 900000000;
- odp.szTitle.a = LPGEN("File transfers");
- odp.szGroup.a = LPGEN("Events");
- odp.pDialog = new CFileOptsDlg();
- odp.flags = ODPF_BOLDGROUPS;
- g_plugin.addOptions(wParam, &odp);
- return 0;
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda 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 "stdafx.h"
+#include "file.h"
+
+#define VSCAN_MCAFEE 1
+#define VSCAN_DRSOLOMON 2
+#define VSCAN_NORTON 3
+#define VSCAN_CA 4
+
+struct {
+ const wchar_t *szProductName;
+ const wchar_t *szExeRegPath;
+ const wchar_t *szExeRegValue;
+ const wchar_t *szCommandLine;
+}
+static virusScanners[] =
+{
+ {L"Network Associates/McAfee VirusScan", L"SOFTWARE\\McAfee\\VirusScan", L"Scan32EXE", L"\"%s\" %%f /nosplash /comp /autoscan /autoexit /noboot"},
+ {L"Dr Solomon's VirusScan (Network Associates)", L"SOFTWARE\\Network Associates\\TVD\\VirusScan\\AVConsol\\General", L"szScannerExe", L"\"%s\" %%f /uinone /noboot /comp /prompt /autoexit"},
+ {L"Norton AntiVirus", L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\Navw32.exe", nullptr, L"\"%s\" %%f /b- /m- /s+ /noresults"},
+ {L"Computer Associates/Inoculate IT", L"Software\\Antivirus", L"ImageFilename", L"\"%s\" %%f /display = progress /exit"},
+ {L"Computer Associates eTrust", L"SOFTWARE\\ComputerAssociates\\Anti-Virus\\Resident", L"VetPath", L"\"%s\" %%f /display = progress /exit"},
+ {L"Kaspersky Anti-Virus", L"SOFTWARE\\KasperskyLab\\Components\\101", L"EXEName", L"\"%s\" /S /Q %%f"},
+ {L"Kaspersky Anti-Virus", L"SOFTWARE\\KasperskyLab\\SetupFolders", L"KAV8", L"\"%savp.exe\" SCAN %%f"},
+ {L"Kaspersky Anti-Virus", L"SOFTWARE\\KasperskyLab\\SetupFolders", L"KAV9", L"\"%savp.exe\" SCAN %%f"},
+ {L"AntiVir PersonalEdition Classic", L"SOFTWARE\\Avira\\AntiVir PersonalEdition Classic", L"Path", L"\"%savscan.exe\" /GUIMODE = 2 /PATH = \"%%f\""},
+ {L"ESET NOD32 Antivirus", L"SOFTWARE\\ESET\\ESET Security\\CurrentVersion\\Info", L"InstallDir", L"\"%secls.exe\" /log-all /aind /no-boots /adware /sfx /unsafe /unwanted /heur /adv-heur /action = clean \"%%f\""},
+};
+
+#ifndef SHACF_FILESYS_DIRS
+ #define SHACF_FILESYS_DIRS 0x00000020
+#endif
+
+class CFileOptsDlg : public CDlgBase
+{
+ CCtrlButton btnFileDir, btnScanCmdLine;
+ CCtrlCheck chkAutoMin, chkAutoClear, chkAutoClose, chkAutoAccept, chkReverseOrder;
+ CCtrlCheck chkNoScanner, chkScanDuringDl, chkScanAfterDl;
+ CCtrlCombo cmbScanCmdLine;
+
+public:
+ CFileOptsDlg() :
+ CDlgBase(g_plugin, IDD_OPT_FILETRANSFER),
+ btnFileDir(this, IDC_FILEDIRBROWSE),
+ btnScanCmdLine(this, IDC_SCANCMDLINEBROWSE),
+ chkAutoMin(this, IDC_AUTOMIN),
+ chkAutoClear(this, IDC_AUTOCLEAR),
+ chkAutoClose(this, IDC_AUTOCLOSE),
+ chkAutoAccept(this, IDC_AUTOACCEPT),
+ chkReverseOrder(this, IDC_REVERSE_ORDER),
+
+ chkNoScanner(this, IDC_NOSCANNER),
+ chkScanAfterDl(this, IDC_SCANAFTERDL),
+ chkScanDuringDl(this, IDC_SCANDURINGDL),
+
+ cmbScanCmdLine(this, IDC_SCANCMDLINE)
+ {
+ CreateLink(chkAutoMin, File::bAutoMin);
+ CreateLink(chkAutoClear, File::bAutoClear);
+ CreateLink(chkAutoClose, File::bAutoClose);
+ CreateLink(chkAutoAccept, File::bAutoAccept);
+ CreateLink(chkReverseOrder, File::bReverseOrder);
+
+ btnFileDir.OnClick = Callback(this, &CFileOptsDlg::onClick_FileDir);
+ btnScanCmdLine.OnClick = Callback(this, &CFileOptsDlg::onClick_ScanCmdLine);
+
+ chkNoScanner.OnChange = Callback(this, &CFileOptsDlg::onChange_NoScanner);
+ chkAutoAccept.OnChange = Callback(this, &CFileOptsDlg::onChange_AutoAccept);
+ cmbScanCmdLine.OnSelChanged = Callback(this, &CFileOptsDlg::onSelChanged_Combo);
+ }
+
+ bool OnInitDialog() override
+ {
+ SHAutoComplete(GetDlgItem(m_hwnd, IDC_FILEDIR), SHACF_FILESYS_DIRS);
+
+ wchar_t str[MAX_PATH];
+ GetContactReceivedFilesDir(NULL, str, _countof(str), FALSE);
+ SetDlgItemText(m_hwnd, IDC_FILEDIR, str);
+
+ switch (g_plugin.getByte("UseScanner", VIRUSSCAN_DISABLE)) {
+ case VIRUSSCAN_AFTERDL: chkScanAfterDl.SetState(true); break;
+ case VIRUSSCAN_DURINGDL: chkScanDuringDl.SetState(true); break;
+ default: chkNoScanner.SetState(true); break;
+ }
+ CheckDlgButton(m_hwnd, IDC_WARNBEFOREOPENING, g_plugin.getByte("WarnBeforeOpening", 1) ? BST_CHECKED : BST_UNCHECKED);
+
+ for (int i = 0; i < _countof(virusScanners); i++) {
+ wchar_t szScanExe[MAX_PATH];
+ if (SRFile_GetRegValue(HKEY_LOCAL_MACHINE, virusScanners[i].szExeRegPath, virusScanners[i].szExeRegValue, szScanExe, _countof(szScanExe)))
+ cmbScanCmdLine.AddString(virusScanners[i].szProductName, i);
+ }
+
+ if (!cmbScanCmdLine.GetCount())
+ cmbScanCmdLine.AddString(L"", -1);
+
+ DBVARIANT dbv;
+ if (g_plugin.getWString("ScanCmdLine", &dbv) == 0) {
+ cmbScanCmdLine.SetText(dbv.pwszVal);
+ db_free(&dbv);
+ }
+ else if (cmbScanCmdLine.GetCount()) {
+ cmbScanCmdLine.SetCurSel(0);
+ onSelChanged_Combo(0);
+ }
+
+ switch (g_plugin.getByte("IfExists", FILERESUME_ASK)) {
+ case FILERESUME_RESUMEALL: CheckDlgButton(m_hwnd, IDC_RESUME, BST_CHECKED); break;
+ case FILERESUME_OVERWRITEALL: CheckDlgButton(m_hwnd, IDC_OVERWRITE, BST_CHECKED); break;
+ case FILERESUME_RENAMEALL: CheckDlgButton(m_hwnd, IDC_RENAME, BST_CHECKED); break;
+ default: CheckDlgButton(m_hwnd, IDC_ASK, BST_CHECKED); break;
+ }
+
+ return true;
+ }
+
+ bool OnApply() override
+ {
+ wchar_t str[512];
+ GetDlgItemText(m_hwnd, IDC_FILEDIR, str, _countof(str));
+ RemoveInvalidPathChars(str);
+ g_plugin.setWString("RecvFilesDirAdv", str);
+
+ cmbScanCmdLine.GetText(str, _countof(str));
+ g_plugin.setWString("ScanCmdLine", str);
+
+ g_plugin.setByte("UseScanner", chkScanAfterDl.GetState() ? VIRUSSCAN_AFTERDL : (chkScanDuringDl.GetState() ? VIRUSSCAN_DURINGDL : VIRUSSCAN_DISABLE));
+ g_plugin.setByte("WarnBeforeOpening", (uint8_t)IsDlgButtonChecked(m_hwnd, IDC_WARNBEFOREOPENING));
+ g_plugin.setByte("IfExists", (uint8_t)(IsDlgButtonChecked(m_hwnd, IDC_ASK) ? FILERESUME_ASK :
+ (IsDlgButtonChecked(m_hwnd, IDC_RESUME) ? FILERESUME_RESUMEALL :
+ (IsDlgButtonChecked(m_hwnd, IDC_OVERWRITE) ? FILERESUME_OVERWRITEALL : FILERESUME_RENAMEALL))));
+ return TRUE;
+ }
+
+ void onChange_AutoAccept(CCtrlCheck *)
+ {
+ chkAutoMin.Enable(chkAutoAccept.GetState());
+ }
+
+ void onChange_NoScanner(CCtrlCheck *)
+ {
+ bool bEnabled = chkNoScanner.GetState();
+ btnScanCmdLine.Enable(bEnabled);
+ cmbScanCmdLine.Enable(bEnabled);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_ST_CMDLINE), bEnabled);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_ST_CMDLINEHELP), bEnabled);
+ }
+
+ void onSelChanged_Combo(CCtrlCombo*)
+ {
+ int iScanner = cmbScanCmdLine.GetCurData();
+ if (iScanner >= _countof(virusScanners) || iScanner < 0)
+ return;
+
+ wchar_t szScanExe[MAX_PATH], str[512];
+ if (SRFile_GetRegValue(HKEY_LOCAL_MACHINE, virusScanners[iScanner].szExeRegPath, virusScanners[iScanner].szExeRegValue, szScanExe, _countof(szScanExe)))
+ mir_snwprintf(str, virusScanners[iScanner].szCommandLine, szScanExe);
+ else
+ str[0] = 0;
+ cmbScanCmdLine.SetText(str);
+ }
+
+ void onClick_FileDir(CCtrlButton*)
+ {
+ wchar_t str[MAX_PATH];
+ GetDlgItemText(m_hwnd, IDC_FILEDIR, str, _countof(str));
+ if (BrowseForFolder(m_hwnd, str))
+ SetDlgItemText(m_hwnd, IDC_FILEDIR, str);
+ }
+
+ void onClick_ScanCmdLine(CCtrlButton*)
+ {
+ wchar_t str[MAX_PATH + 2];
+ cmbScanCmdLine.GetText(str, _countof(str));
+
+ CMStringW tszFilter;
+ tszFilter.AppendFormat(L"%s (*.exe)%c*.exe%c", TranslateT("Executable files"), 0, 0);
+ tszFilter.AppendFormat(L"%s (*)%c*%c", TranslateT("All files"), 0, 0);
+
+ OPENFILENAME ofn = { 0 };
+ ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
+ ofn.hwndOwner = m_hwnd;
+ ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_DONTADDTORECENT;
+ ofn.lpstrFilter = tszFilter;
+ ofn.lpstrFile = str;
+ ofn.nMaxFile = _countof(str) - 2;
+ if (str[0] == '"') {
+ wchar_t *pszQuote = wcschr(str + 1, '"');
+ if (pszQuote)
+ *pszQuote = 0;
+ memmove(str, str + 1, (mir_wstrlen(str) * sizeof(wchar_t)));
+ }
+ else {
+ wchar_t *pszSpace = wcschr(str, ' ');
+ if (pszSpace) *pszSpace = 0;
+ }
+ ofn.nMaxFileTitle = MAX_PATH;
+ if (!GetOpenFileName(&ofn))
+ return;
+
+ if (wcschr(str, ' ') != nullptr) {
+ memmove(str + 1, str, ((_countof(str) - 2) * sizeof(wchar_t)));
+ str[0] = '"';
+ mir_wstrcat(str, L"\"");
+ }
+ cmbScanCmdLine.SetText(str);
+ }
+};
+
+int FileOptInitialise(WPARAM wParam, LPARAM)
+{
+ OPTIONSDIALOGPAGE odp = {};
+ odp.position = 900000000;
+ odp.szTitle.a = LPGEN("File transfers");
+ odp.szGroup.a = LPGEN("Events");
+ odp.pDialog = new CFileOptsDlg();
+ odp.flags = ODPF_BOLDGROUPS;
+ g_plugin.addOptions(wParam, &odp);
+ return 0;
+}
diff --git a/src/core/stdfile/src/filerecvdlg.cpp b/src/mir_app/src/filerecvdlg.cpp
index a605bdacec..f1b32d9e1e 100644
--- a/src/core/stdfile/src/filerecvdlg.cpp
+++ b/src/mir_app/src/filerecvdlg.cpp
@@ -1,411 +1,411 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda 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 "stdafx.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 wchar_t *szTestDir, wchar_t *szExistingDir, int cchExistingDir)
-{
- uint32_t dwAttributes;
- wchar_t *pszLastBackslash;
-
- mir_wstrncpy(szExistingDir, szTestDir, cchExistingDir);
- while ((dwAttributes = GetFileAttributes(szExistingDir)) != INVALID_FILE_ATTRIBUTES && !(dwAttributes&FILE_ATTRIBUTE_DIRECTORY)) {
- pszLastBackslash = wcsrchr(szExistingDir, '\\');
- if (pszLastBackslash == nullptr) { *szExistingDir = '\0'; break; }
- *pszLastBackslash = '\0';
- }
- if (szExistingDir[0] == '\0')
- GetCurrentDirectory(cchExistingDir, szExistingDir);
-}
-
-static const wchar_t InvalidFilenameChars[] = L"\\/:*?\"<>|";
-void RemoveInvalidFilenameChars(wchar_t *tszString)
-{
- size_t i;
- if (tszString) {
- for (i = wcscspn(tszString, InvalidFilenameChars); tszString[i]; i+=wcscspn(tszString+i+1, InvalidFilenameChars)+1)
- tszString[i] = '_';
- }
-}
-
-static const wchar_t InvalidPathChars[] = L"*?\"<>|"; // "\/:" are excluded as they are allowed in file path
-void RemoveInvalidPathChars(wchar_t *tszString)
-{
- if (tszString)
- for (size_t i = wcscspn(tszString, InvalidPathChars); tszString[i]; i += wcscspn(tszString + i + 1, InvalidPathChars) + 1)
- tszString[i] = '_';
-}
-
-static INT CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LPARAM pData)
-{
- wchar_t 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, wchar_t *szPath)
-{
- BROWSEINFO bi = {};
- 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;
-
- LPITEMIDLIST pidlResult = SHBrowseForFolder(&bi);
- if (pidlResult) {
- SHGetPathFromIDList(pidlResult, szPath);
- mir_wstrcat(szPath, L"\\");
- CoTaskMemFree(pidlResult);
- }
- return pidlResult != nullptr;
-}
-
-static REPLACEVARSARRAY sttVarsToReplace[] =
-{
- { "///", "//" },
- { "//", "/" },
- { "()", "" },
- { nullptr, nullptr }
-};
-
-static void patchDir(wchar_t *str, size_t strSize)
-{
- wchar_t *result = Utils_ReplaceVarsW(str, 0, sttVarsToReplace);
- if (result) {
- wcsncpy(str, result, strSize);
- mir_free(result);
- }
-
- size_t len = mir_wstrlen(str);
- if (len + 1 < strSize && str[len - 1] != '\\')
- mir_wstrcpy(str + len, L"\\");
-}
-
-void GetContactReceivedFilesDir(MCONTACT hContact, wchar_t *szDir, int cchDir, BOOL patchVars)
-{
- wchar_t tszTemp[MAX_PATH];
-
- ptrW tszRecvPath(g_plugin.getWStringA("RecvFilesDirAdv"));
- if (tszRecvPath)
- wcsncpy_s(tszTemp, tszRecvPath, _TRUNCATE);
- else
- mir_snwprintf(tszTemp, L"%%mydocuments%%\\%s\\%%userid%%", TranslateT("My received files"));
-
- if (hContact) {
- hContact = db_mc_tryMeta(hContact);
-
- REPLACEVARSARRAY rvaVarsToReplace[4];
- rvaVarsToReplace[0].key.w = L"nick";
- rvaVarsToReplace[0].value.w = mir_wstrdup(Clist_GetContactDisplayName(hContact));
- rvaVarsToReplace[1].key.w = L"userid";
- rvaVarsToReplace[1].value.w = Contact::GetInfo(CNF_UNIQUEID, hContact);
- rvaVarsToReplace[2].key.w = L"proto";
- rvaVarsToReplace[2].value.w = mir_a2u(Proto_GetBaseAccountName(hContact));
- rvaVarsToReplace[3].key.w = nullptr;
- rvaVarsToReplace[3].value.w = nullptr;
- for (int i = 0; i < (_countof(rvaVarsToReplace) - 1); i++)
- RemoveInvalidFilenameChars(rvaVarsToReplace[i].value.w);
-
- wchar_t *result = Utils_ReplaceVarsW(tszTemp, hContact, rvaVarsToReplace);
- if (result) {
- wcsncpy(tszTemp, result, _countof(tszTemp));
- mir_free(result);
- for (int i = 0; i < (_countof(rvaVarsToReplace) - 1); i++)
- mir_free(rvaVarsToReplace[i].value.w);
- }
- }
-
- if (patchVars)
- patchDir(tszTemp, _countof(tszTemp));
- RemoveInvalidPathChars(tszTemp);
- mir_wstrncpy(szDir, tszTemp, cchDir);
-}
-
-void GetReceivedFilesDir(wchar_t *szDir, int cchDir)
-{
- wchar_t tszTemp[MAX_PATH];
-
- ptrW tszRecvPath(g_plugin.getWStringA("RecvFilesDirAdv"));
- if (tszRecvPath)
- wcsncpy_s(tszTemp, tszRecvPath, _TRUNCATE);
- else
- mir_snwprintf(tszTemp, L"%%mydocuments%%\\%s\\%%userid%%", TranslateT("My received files"));
-
- patchDir(tszTemp, _countof(tszTemp));
- RemoveInvalidPathChars(tszTemp);
- mir_wstrncpy(szDir, tszTemp, cchDir);
-}
-
-class CRecvFileDlg : public CDlgBase
-{
- FileDlgData *dat;
- LPARAM m_lParam;
-
- CCtrlButton btnCancel, btnBrowse;
- CCtrlMButton btnAdd, btnUserMenu, btnDetails, btnHistory;
-
-public:
- CRecvFileDlg(CLISTEVENT *cle) :
- CDlgBase(g_plugin, IDD_FILERECV),
- btnAdd(this, IDC_ADD, SKINICON_OTHER_ADDCONTACT, LPGEN("Add contact permanently to list")),
- btnCancel(this, IDCANCEL),
- btnBrowse(this, IDC_FILEDIRBROWSE),
- btnDetails(this, IDC_DETAILS, SKINICON_OTHER_USERDETAILS, LPGEN("View user's details")),
- btnHistory(this, IDC_HISTORY, SKINICON_OTHER_HISTORY, LPGEN("View user's history")),
- btnUserMenu(this, IDC_USERMENU, SKINICON_OTHER_DOWNARROW, LPGEN("User menu"))
- {
- dat = new FileDlgData();
- dat->hContact = cle->hContact;
- dat->hDbEvent = cle->hDbEvent;
- dat->dwTicks = GetTickCount();
- m_lParam = cle->lParam;
-
- btnAdd.OnClick = Callback(this, &CRecvFileDlg::onClick_Add);
- btnCancel.OnClick = Callback(this, &CRecvFileDlg::onClick_Cancel);
- btnBrowse.OnClick = Callback(this, &CRecvFileDlg::onClick_Browse);
- btnDetails.OnClick = Callback(this, &CRecvFileDlg::onClick_Details);
- btnHistory.OnClick = Callback(this, &CRecvFileDlg::onClick_History);
- btnUserMenu.OnClick = Callback(this, &CRecvFileDlg::onClick_UserMenu);
- }
-
- bool OnInitDialog() override
- {
- char *szProto = Proto_GetBaseAccountName(dat->hContact);
-
- dat->hNotifyEvent = HookEventMessage(ME_PROTO_ACK, m_hwnd, HM_RECVEVENT);
- dat->hPreshutdownEvent = HookEventMessage(ME_SYSTEM_PRESHUTDOWN, m_hwnd, M_PRESHUTDOWN);
-
- SetWindowLongPtr(m_hwnd, GWLP_USERDATA, (LONG_PTR)dat);
-
- EnumChildWindows(m_hwnd, ClipSiblingsChildEnumProc, 0);
-
- Window_SetSkinIcon_IcoLib(m_hwnd, SKINICON_EVENT_FILE);
- SendDlgItemMessage(m_hwnd, IDC_PROTOCOL, STM_SETICON, LPARAM(Skin_LoadProtoIcon(szProto, ID_STATUS_ONLINE)), 0);
-
- wchar_t *contactName = Clist_GetContactDisplayName(dat->hContact);
- SetDlgItemText(m_hwnd, IDC_FROM, contactName);
-
- wchar_t szPath[450];
- GetContactReceivedFilesDir(dat->hContact, szPath, _countof(szPath), TRUE);
- SetDlgItemText(m_hwnd, IDC_FILEDIR, szPath);
- SHAutoComplete(GetWindow(GetDlgItem(m_hwnd, IDC_FILEDIR), GW_CHILD), 1);
-
- for (int i = 0; i < MAX_MRU_DIRS; i++) {
- char idstr[32];
- mir_snprintf(idstr, "MruDir%d", i);
-
- DBVARIANT dbv;
- if (g_plugin.getWString(idstr, &dbv))
- break;
- SendDlgItemMessage(m_hwnd, IDC_FILEDIR, CB_ADDSTRING, 0, (LPARAM)dbv.pwszVal);
- db_free(&dbv);
- }
-
- db_event_markRead(dat->hContact, dat->hDbEvent);
-
- DB::EventInfo dbei(dat->hDbEvent);
- if (!dbei)
- return false;
-
- dat->fs = (HANDLE)m_lParam;
-
- DB::FILE_BLOB blob(dbei);
- SetDlgItemText(m_hwnd, IDC_FILENAMES, blob.getName());
- if (mir_wstrlen(blob.getDescr()))
- SetDlgItemText(m_hwnd, IDC_MSG, blob.getDescr());
-
- wchar_t datetimestr[64];
- TimeZone_PrintTimeStamp(NULL, dbei.timestamp, L"t d", datetimestr, _countof(datetimestr), 0);
- SetDlgItemText(m_hwnd, IDC_DATE, datetimestr);
-
- ptrW info(Contact::GetInfo(CNF_UNIQUEID, dat->hContact));
- SetDlgItemText(m_hwnd, IDC_NAME, (info) ? info : contactName);
-
- if (!Contact::OnList(dat->hContact)) {
- RECT rcBtn1, rcBtn2, rcDateCtrl;
- GetWindowRect(GetDlgItem(m_hwnd, IDC_ADD), &rcBtn1);
- GetWindowRect(GetDlgItem(m_hwnd, IDC_USERMENU), &rcBtn2);
- GetWindowRect(GetDlgItem(m_hwnd, IDC_DATE), &rcDateCtrl);
- SetWindowPos(GetDlgItem(m_hwnd, IDC_DATE), 0, 0, 0, rcDateCtrl.right - rcDateCtrl.left - (rcBtn2.left - rcBtn1.left), rcDateCtrl.bottom - rcDateCtrl.top, SWP_NOZORDER | SWP_NOMOVE);
- }
- else if (g_plugin.bAutoAccept) {
- //don't check auto-min here to fix BUG#647620
- PostMessage(m_hwnd, WM_COMMAND, MAKEWPARAM(IDOK, BN_CLICKED), (LPARAM)GetDlgItem(m_hwnd, IDOK));
- }
- if (Contact::OnList(dat->hContact))
- btnAdd.Hide();
- return true;
- }
-
- bool OnApply() override
- {
- // most recently used directories
- wchar_t szRecvDir[MAX_PATH], szDefaultRecvDir[MAX_PATH];
- GetDlgItemText(m_hwnd, IDC_FILEDIR, szRecvDir, _countof(szRecvDir));
- RemoveInvalidPathChars(szRecvDir);
- GetContactReceivedFilesDir(NULL, szDefaultRecvDir, _countof(szDefaultRecvDir), TRUE);
- if (wcsnicmp(szRecvDir, szDefaultRecvDir, mir_wstrlen(szDefaultRecvDir))) {
- char idstr[32];
- int i;
- DBVARIANT dbv;
- for (i = MAX_MRU_DIRS - 2; i >= 0; i--) {
- mir_snprintf(idstr, "MruDir%d", i);
- if (g_plugin.getWString(idstr, &dbv)) continue;
- mir_snprintf(idstr, "MruDir%d", i + 1);
- g_plugin.setWString(idstr, dbv.pwszVal);
- db_free(&dbv);
- }
- g_plugin.setWString(idstr, szRecvDir);
- }
-
- EnableWindow(GetDlgItem(m_hwnd, IDC_FILENAMES), FALSE);
- EnableWindow(GetDlgItem(m_hwnd, IDC_MSG), FALSE);
- EnableWindow(GetDlgItem(m_hwnd, IDC_FILEDIR), FALSE);
- EnableWindow(GetDlgItem(m_hwnd, IDC_FILEDIRBROWSE), FALSE);
-
- GetDlgItemText(m_hwnd, IDC_FILEDIR, dat->szSavePath, _countof(dat->szSavePath));
- GetDlgItemText(m_hwnd, IDC_FILE, dat->szFilenames, _countof(dat->szFilenames));
- GetDlgItemText(m_hwnd, IDC_MSG, dat->szMsg, _countof(dat->szMsg));
- FtMgr_AddTransfer(dat);
- SetWindowLongPtr(m_hwnd, GWLP_USERDATA, 0);
- dat = nullptr;
-
- // check for auto-minimize here to fix BUG#647620
- if (g_plugin.bAutoAccept && g_plugin.bAutoMin) {
- ShowWindow(m_hwnd, SW_HIDE);
- ShowWindow(m_hwnd, SW_SHOWMINNOACTIVE);
- }
- return true;
- }
-
- void OnDestroy() override
- {
- Window_FreeIcon_IcoLib(m_hwnd);
-
- delete dat; dat = nullptr;
- SetWindowLongPtr(m_hwnd, GWLP_USERDATA, 0);
- }
-
- INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) override
- {
- switch (msg) {
- case WM_COMMAND:
- if (Clist_MenuProcessCommand(LOWORD(wParam), MPCF_CONTACTMENU, dat->hContact))
- return 1;
- break;
-
- case HM_RECVEVENT:
- ACKDATA *ack = (ACKDATA *)lParam;
- if (ack && dat) {
- if (ack->hProcess != dat->fs || ack->type != ACKTYPE_FILE || ack->hContact != dat->hContact)
- break;
-
- if (ack->result == ACKRESULT_DENIED || ack->result == ACKRESULT_FAILED) {
- EnableWindow(GetDlgItem(m_hwnd, IDOK), FALSE);
- EnableWindow(GetDlgItem(m_hwnd, IDC_FILEDIR), FALSE);
- EnableWindow(GetDlgItem(m_hwnd, IDC_FILEDIRBROWSE), FALSE);
- SetDlgItemText(m_hwnd, IDC_MSG, TranslateT("This file transfer has been canceled by the other side"));
- Skin_PlaySound("FileDenied");
- FlashWindow(m_hwnd, TRUE);
- }
- else if (ack->result != ACKRESULT_FILERESUME) {
- btnCancel.Click();
- }
- }
- break;
- }
-
- return CDlgBase::DlgProc(msg, wParam, lParam);
- }
-
- void onClick_Browse(CCtrlButton *)
- {
- wchar_t szDirName[MAX_PATH], szExistingDirName[MAX_PATH];
-
- GetDlgItemText(m_hwnd, IDC_FILEDIR, szDirName, _countof(szDirName));
- GetLowestExistingDirName(szDirName, szExistingDirName, _countof(szExistingDirName));
- if (BrowseForFolder(m_hwnd, szExistingDirName))
- SetDlgItemText(m_hwnd, IDC_FILEDIR, szExistingDirName);
- }
-
- void onClick_Cancel(CCtrlButton *)
- {
- if (dat->fs) {
- ProtoChainSend(dat->hContact, PSS_FILEDENY, (WPARAM)dat->fs, (LPARAM)TranslateT("Canceled"));
- dat->fs = nullptr; /* the protocol will free the handle */
- }
- }
-
- void onClick_Add(CCtrlButton *)
- {
- Contact::Add(dat->hContact, m_hwnd);
-
- if (Contact::OnList(dat->hContact))
- ShowWindow(GetDlgItem(m_hwnd, IDC_ADD), SW_HIDE);
- }
-
- void onClick_UserMenu(CCtrlButton *pButton)
- {
- RECT rc;
- GetWindowRect(pButton->GetHwnd(), &rc);
- HMENU hMenu = Menu_BuildContactMenu(dat->hContact);
- TrackPopupMenu(hMenu, 0, rc.left, rc.bottom, 0, m_hwnd, NULL);
- DestroyMenu(hMenu);
- }
-
- void onClick_Details(CCtrlButton *)
- {
- CallService(MS_USERINFO_SHOWDIALOG, dat->hContact, 0);
- }
-
- void onClick_History(CCtrlButton *)
- {
- CallService(MS_HISTORY_SHOWCONTACTHISTORY, dat->hContact, 0);
- }
-};
-
-void LaunchRecvDialog(CLISTEVENT *cle)
-{
- auto *pDlg = new CRecvFileDlg(cle);
- pDlg->Show();
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda 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 "stdafx.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 wchar_t *szTestDir, wchar_t *szExistingDir, int cchExistingDir)
+{
+ uint32_t dwAttributes;
+ wchar_t *pszLastBackslash;
+
+ mir_wstrncpy(szExistingDir, szTestDir, cchExistingDir);
+ while ((dwAttributes = GetFileAttributes(szExistingDir)) != INVALID_FILE_ATTRIBUTES && !(dwAttributes&FILE_ATTRIBUTE_DIRECTORY)) {
+ pszLastBackslash = wcsrchr(szExistingDir, '\\');
+ if (pszLastBackslash == nullptr) { *szExistingDir = '\0'; break; }
+ *pszLastBackslash = '\0';
+ }
+ if (szExistingDir[0] == '\0')
+ GetCurrentDirectory(cchExistingDir, szExistingDir);
+}
+
+static const wchar_t InvalidFilenameChars[] = L"\\/:*?\"<>|";
+void RemoveInvalidFilenameChars(wchar_t *tszString)
+{
+ size_t i;
+ if (tszString) {
+ for (i = wcscspn(tszString, InvalidFilenameChars); tszString[i]; i+=wcscspn(tszString+i+1, InvalidFilenameChars)+1)
+ tszString[i] = '_';
+ }
+}
+
+static const wchar_t InvalidPathChars[] = L"*?\"<>|"; // "\/:" are excluded as they are allowed in file path
+void RemoveInvalidPathChars(wchar_t *tszString)
+{
+ if (tszString)
+ for (size_t i = wcscspn(tszString, InvalidPathChars); tszString[i]; i += wcscspn(tszString + i + 1, InvalidPathChars) + 1)
+ tszString[i] = '_';
+}
+
+static INT CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LPARAM pData)
+{
+ wchar_t 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, wchar_t *szPath)
+{
+ BROWSEINFO bi = {};
+ 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;
+
+ LPITEMIDLIST pidlResult = SHBrowseForFolder(&bi);
+ if (pidlResult) {
+ SHGetPathFromIDList(pidlResult, szPath);
+ mir_wstrcat(szPath, L"\\");
+ CoTaskMemFree(pidlResult);
+ }
+ return pidlResult != nullptr;
+}
+
+static REPLACEVARSARRAY sttVarsToReplace[] =
+{
+ { "///", "//" },
+ { "//", "/" },
+ { "()", "" },
+ { nullptr, nullptr }
+};
+
+static void patchDir(wchar_t *str, size_t strSize)
+{
+ wchar_t *result = Utils_ReplaceVarsW(str, 0, sttVarsToReplace);
+ if (result) {
+ wcsncpy(str, result, strSize);
+ mir_free(result);
+ }
+
+ size_t len = mir_wstrlen(str);
+ if (len + 1 < strSize && str[len - 1] != '\\')
+ mir_wstrcpy(str + len, L"\\");
+}
+
+void GetContactReceivedFilesDir(MCONTACT hContact, wchar_t *szDir, int cchDir, BOOL patchVars)
+{
+ wchar_t tszTemp[MAX_PATH];
+
+ ptrW tszRecvPath(g_plugin.getWStringA("RecvFilesDirAdv"));
+ if (tszRecvPath)
+ wcsncpy_s(tszTemp, tszRecvPath, _TRUNCATE);
+ else
+ mir_snwprintf(tszTemp, L"%%mydocuments%%\\%s\\%%userid%%", TranslateT("My received files"));
+
+ if (hContact) {
+ hContact = db_mc_tryMeta(hContact);
+
+ REPLACEVARSARRAY rvaVarsToReplace[4];
+ rvaVarsToReplace[0].key.w = L"nick";
+ rvaVarsToReplace[0].value.w = mir_wstrdup(Clist_GetContactDisplayName(hContact));
+ rvaVarsToReplace[1].key.w = L"userid";
+ rvaVarsToReplace[1].value.w = Contact::GetInfo(CNF_UNIQUEID, hContact);
+ rvaVarsToReplace[2].key.w = L"proto";
+ rvaVarsToReplace[2].value.w = mir_a2u(Proto_GetBaseAccountName(hContact));
+ rvaVarsToReplace[3].key.w = nullptr;
+ rvaVarsToReplace[3].value.w = nullptr;
+ for (int i = 0; i < (_countof(rvaVarsToReplace) - 1); i++)
+ RemoveInvalidFilenameChars(rvaVarsToReplace[i].value.w);
+
+ wchar_t *result = Utils_ReplaceVarsW(tszTemp, hContact, rvaVarsToReplace);
+ if (result) {
+ wcsncpy(tszTemp, result, _countof(tszTemp));
+ mir_free(result);
+ for (int i = 0; i < (_countof(rvaVarsToReplace) - 1); i++)
+ mir_free(rvaVarsToReplace[i].value.w);
+ }
+ }
+
+ if (patchVars)
+ patchDir(tszTemp, _countof(tszTemp));
+ RemoveInvalidPathChars(tszTemp);
+ mir_wstrncpy(szDir, tszTemp, cchDir);
+}
+
+void GetReceivedFilesDir(wchar_t *szDir, int cchDir)
+{
+ wchar_t tszTemp[MAX_PATH];
+
+ ptrW tszRecvPath(g_plugin.getWStringA("RecvFilesDirAdv"));
+ if (tszRecvPath)
+ wcsncpy_s(tszTemp, tszRecvPath, _TRUNCATE);
+ else
+ mir_snwprintf(tszTemp, L"%%mydocuments%%\\%s\\%%userid%%", TranslateT("My received files"));
+
+ patchDir(tszTemp, _countof(tszTemp));
+ RemoveInvalidPathChars(tszTemp);
+ mir_wstrncpy(szDir, tszTemp, cchDir);
+}
+
+class CRecvFileDlg : public CDlgBase
+{
+ FileDlgData *dat;
+ LPARAM m_lParam;
+
+ CCtrlButton btnCancel, btnBrowse;
+ CCtrlMButton btnAdd, btnUserMenu, btnDetails, btnHistory;
+
+public:
+ CRecvFileDlg(CLISTEVENT *cle) :
+ CDlgBase(g_plugin, IDD_FILERECV),
+ btnAdd(this, IDC_ADD, SKINICON_OTHER_ADDCONTACT, LPGEN("Add contact permanently to list")),
+ btnCancel(this, IDCANCEL),
+ btnBrowse(this, IDC_FILEDIRBROWSE),
+ btnDetails(this, IDC_DETAILS, SKINICON_OTHER_USERDETAILS, LPGEN("View user's details")),
+ btnHistory(this, IDC_HISTORY, SKINICON_OTHER_HISTORY, LPGEN("View user's history")),
+ btnUserMenu(this, IDC_USERMENU, SKINICON_OTHER_DOWNARROW, LPGEN("User menu"))
+ {
+ dat = new FileDlgData();
+ dat->hContact = cle->hContact;
+ dat->hDbEvent = cle->hDbEvent;
+ dat->dwTicks = GetTickCount();
+ m_lParam = cle->lParam;
+
+ btnAdd.OnClick = Callback(this, &CRecvFileDlg::onClick_Add);
+ btnCancel.OnClick = Callback(this, &CRecvFileDlg::onClick_Cancel);
+ btnBrowse.OnClick = Callback(this, &CRecvFileDlg::onClick_Browse);
+ btnDetails.OnClick = Callback(this, &CRecvFileDlg::onClick_Details);
+ btnHistory.OnClick = Callback(this, &CRecvFileDlg::onClick_History);
+ btnUserMenu.OnClick = Callback(this, &CRecvFileDlg::onClick_UserMenu);
+ }
+
+ bool OnInitDialog() override
+ {
+ char *szProto = Proto_GetBaseAccountName(dat->hContact);
+
+ dat->hNotifyEvent = HookEventMessage(ME_PROTO_ACK, m_hwnd, HM_RECVEVENT);
+ dat->hPreshutdownEvent = HookEventMessage(ME_SYSTEM_PRESHUTDOWN, m_hwnd, M_PRESHUTDOWN);
+
+ SetWindowLongPtr(m_hwnd, GWLP_USERDATA, (LONG_PTR)dat);
+
+ EnumChildWindows(m_hwnd, ClipSiblingsChildEnumProc, 0);
+
+ Window_SetSkinIcon_IcoLib(m_hwnd, SKINICON_EVENT_FILE);
+ SendDlgItemMessage(m_hwnd, IDC_PROTOCOL, STM_SETICON, LPARAM(Skin_LoadProtoIcon(szProto, ID_STATUS_ONLINE)), 0);
+
+ wchar_t *contactName = Clist_GetContactDisplayName(dat->hContact);
+ SetDlgItemText(m_hwnd, IDC_FROM, contactName);
+
+ wchar_t szPath[450];
+ GetContactReceivedFilesDir(dat->hContact, szPath, _countof(szPath), TRUE);
+ SetDlgItemText(m_hwnd, IDC_FILEDIR, szPath);
+ SHAutoComplete(GetWindow(GetDlgItem(m_hwnd, IDC_FILEDIR), GW_CHILD), 1);
+
+ for (int i = 0; i < MAX_MRU_DIRS; i++) {
+ char idstr[32];
+ mir_snprintf(idstr, "MruDir%d", i);
+
+ DBVARIANT dbv;
+ if (g_plugin.getWString(idstr, &dbv))
+ break;
+ SendDlgItemMessage(m_hwnd, IDC_FILEDIR, CB_ADDSTRING, 0, (LPARAM)dbv.pwszVal);
+ db_free(&dbv);
+ }
+
+ db_event_markRead(dat->hContact, dat->hDbEvent);
+
+ DB::EventInfo dbei(dat->hDbEvent);
+ if (!dbei)
+ return false;
+
+ dat->fs = (HANDLE)m_lParam;
+
+ DB::FILE_BLOB blob(dbei);
+ SetDlgItemText(m_hwnd, IDC_FILENAMES, blob.getName());
+ if (mir_wstrlen(blob.getDescr()))
+ SetDlgItemText(m_hwnd, IDC_MSG, blob.getDescr());
+
+ wchar_t datetimestr[64];
+ TimeZone_PrintTimeStamp(NULL, dbei.timestamp, L"t d", datetimestr, _countof(datetimestr), 0);
+ SetDlgItemText(m_hwnd, IDC_DATE, datetimestr);
+
+ ptrW info(Contact::GetInfo(CNF_UNIQUEID, dat->hContact));
+ SetDlgItemText(m_hwnd, IDC_NAME, (info) ? info : contactName);
+
+ if (!Contact::OnList(dat->hContact)) {
+ RECT rcBtn1, rcBtn2, rcDateCtrl;
+ GetWindowRect(GetDlgItem(m_hwnd, IDC_ADD), &rcBtn1);
+ GetWindowRect(GetDlgItem(m_hwnd, IDC_USERMENU), &rcBtn2);
+ GetWindowRect(GetDlgItem(m_hwnd, IDC_DATE), &rcDateCtrl);
+ SetWindowPos(GetDlgItem(m_hwnd, IDC_DATE), 0, 0, 0, rcDateCtrl.right - rcDateCtrl.left - (rcBtn2.left - rcBtn1.left), rcDateCtrl.bottom - rcDateCtrl.top, SWP_NOZORDER | SWP_NOMOVE);
+ }
+ else if (File::bAutoAccept) {
+ //don't check auto-min here to fix BUG#647620
+ PostMessage(m_hwnd, WM_COMMAND, MAKEWPARAM(IDOK, BN_CLICKED), (LPARAM)GetDlgItem(m_hwnd, IDOK));
+ }
+ if (Contact::OnList(dat->hContact))
+ btnAdd.Hide();
+ return true;
+ }
+
+ bool OnApply() override
+ {
+ // most recently used directories
+ wchar_t szRecvDir[MAX_PATH], szDefaultRecvDir[MAX_PATH];
+ GetDlgItemText(m_hwnd, IDC_FILEDIR, szRecvDir, _countof(szRecvDir));
+ RemoveInvalidPathChars(szRecvDir);
+ GetContactReceivedFilesDir(NULL, szDefaultRecvDir, _countof(szDefaultRecvDir), TRUE);
+ if (wcsnicmp(szRecvDir, szDefaultRecvDir, mir_wstrlen(szDefaultRecvDir))) {
+ char idstr[32];
+ int i;
+ DBVARIANT dbv;
+ for (i = MAX_MRU_DIRS - 2; i >= 0; i--) {
+ mir_snprintf(idstr, "MruDir%d", i);
+ if (g_plugin.getWString(idstr, &dbv)) continue;
+ mir_snprintf(idstr, "MruDir%d", i + 1);
+ g_plugin.setWString(idstr, dbv.pwszVal);
+ db_free(&dbv);
+ }
+ g_plugin.setWString(idstr, szRecvDir);
+ }
+
+ EnableWindow(GetDlgItem(m_hwnd, IDC_FILENAMES), FALSE);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_MSG), FALSE);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_FILEDIR), FALSE);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_FILEDIRBROWSE), FALSE);
+
+ GetDlgItemText(m_hwnd, IDC_FILEDIR, dat->szSavePath, _countof(dat->szSavePath));
+ GetDlgItemText(m_hwnd, IDC_FILE, dat->szFilenames, _countof(dat->szFilenames));
+ GetDlgItemText(m_hwnd, IDC_MSG, dat->szMsg, _countof(dat->szMsg));
+ FtMgr_AddTransfer(dat);
+ SetWindowLongPtr(m_hwnd, GWLP_USERDATA, 0);
+ dat = nullptr;
+
+ // check for auto-minimize here to fix BUG#647620
+ if (File::bAutoAccept && File::bAutoMin) {
+ ShowWindow(m_hwnd, SW_HIDE);
+ ShowWindow(m_hwnd, SW_SHOWMINNOACTIVE);
+ }
+ return true;
+ }
+
+ void OnDestroy() override
+ {
+ Window_FreeIcon_IcoLib(m_hwnd);
+
+ delete dat; dat = nullptr;
+ SetWindowLongPtr(m_hwnd, GWLP_USERDATA, 0);
+ }
+
+ INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) override
+ {
+ switch (msg) {
+ case WM_COMMAND:
+ if (Clist_MenuProcessCommand(LOWORD(wParam), MPCF_CONTACTMENU, dat->hContact))
+ return 1;
+ break;
+
+ case HM_RECVEVENT:
+ ACKDATA *ack = (ACKDATA *)lParam;
+ if (ack && dat) {
+ if (ack->hProcess != dat->fs || ack->type != ACKTYPE_FILE || ack->hContact != dat->hContact)
+ break;
+
+ if (ack->result == ACKRESULT_DENIED || ack->result == ACKRESULT_FAILED) {
+ EnableWindow(GetDlgItem(m_hwnd, IDOK), FALSE);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_FILEDIR), FALSE);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_FILEDIRBROWSE), FALSE);
+ SetDlgItemText(m_hwnd, IDC_MSG, TranslateT("This file transfer has been canceled by the other side"));
+ Skin_PlaySound("FileDenied");
+ FlashWindow(m_hwnd, TRUE);
+ }
+ else if (ack->result != ACKRESULT_FILERESUME) {
+ btnCancel.Click();
+ }
+ }
+ break;
+ }
+
+ return CDlgBase::DlgProc(msg, wParam, lParam);
+ }
+
+ void onClick_Browse(CCtrlButton *)
+ {
+ wchar_t szDirName[MAX_PATH], szExistingDirName[MAX_PATH];
+
+ GetDlgItemText(m_hwnd, IDC_FILEDIR, szDirName, _countof(szDirName));
+ GetLowestExistingDirName(szDirName, szExistingDirName, _countof(szExistingDirName));
+ if (BrowseForFolder(m_hwnd, szExistingDirName))
+ SetDlgItemText(m_hwnd, IDC_FILEDIR, szExistingDirName);
+ }
+
+ void onClick_Cancel(CCtrlButton *)
+ {
+ if (dat->fs) {
+ ProtoChainSend(dat->hContact, PSS_FILEDENY, (WPARAM)dat->fs, (LPARAM)TranslateT("Canceled"));
+ dat->fs = nullptr; /* the protocol will free the handle */
+ }
+ }
+
+ void onClick_Add(CCtrlButton *)
+ {
+ Contact::Add(dat->hContact, m_hwnd);
+
+ if (Contact::OnList(dat->hContact))
+ ShowWindow(GetDlgItem(m_hwnd, IDC_ADD), SW_HIDE);
+ }
+
+ void onClick_UserMenu(CCtrlButton *pButton)
+ {
+ RECT rc;
+ GetWindowRect(pButton->GetHwnd(), &rc);
+ HMENU hMenu = Menu_BuildContactMenu(dat->hContact);
+ TrackPopupMenu(hMenu, 0, rc.left, rc.bottom, 0, m_hwnd, NULL);
+ DestroyMenu(hMenu);
+ }
+
+ void onClick_Details(CCtrlButton *)
+ {
+ CallService(MS_USERINFO_SHOWDIALOG, dat->hContact, 0);
+ }
+
+ void onClick_History(CCtrlButton *)
+ {
+ CallService(MS_HISTORY_SHOWCONTACTHISTORY, dat->hContact, 0);
+ }
+};
+
+void LaunchRecvDialog(CLISTEVENT *cle)
+{
+ auto *pDlg = new CRecvFileDlg(cle);
+ pDlg->Show();
+}
diff --git a/src/core/stdfile/src/filesenddlg.cpp b/src/mir_app/src/filesenddlg.cpp
index 4ecfd8bce6..1c1a1af606 100644
--- a/src/core/stdfile/src/filesenddlg.cpp
+++ b/src/mir_app/src/filesenddlg.cpp
@@ -1,334 +1,334 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda 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 "stdafx.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-#include "file.h"
-
-static void SetFileListAndSizeControls(HWND hwndDlg, FileDlgData *dat)
-{
- int fileCount = 0, dirCount = 0, i;
- __int64 totalSize = 0;
- struct _stati64 statbuf;
- wchar_t str[64];
-
- for (i = 0; dat->files[i]; i++) {
- if (_wstat64(dat->files[i], &statbuf) == 0) {
- if (statbuf.st_mode & _S_IFDIR)
- dirCount++;
- else
- fileCount++;
- totalSize += statbuf.st_size;
- }
- }
-
- GetSensiblyFormattedSize(totalSize, str, _countof(str), 0, 1, NULL);
- SetDlgItemText(hwndDlg, IDC_TOTALSIZE, str);
- if (i > 1) {
- wchar_t szFormat[32];
- if (fileCount && dirCount) {
- mir_snwprintf(szFormat, L"%s, %s", TranslateW(fileCount == 1 ? L"%d file" : L"%d files"), TranslateW(dirCount == 1 ? L"%d directory" : L"%d directories"));
- mir_snwprintf(str, szFormat, fileCount, dirCount);
- }
- else if (fileCount) {
- mir_wstrcpy(szFormat, TranslateT("%d files"));
- mir_snwprintf(str, szFormat, fileCount);
- }
- else {
- mir_wstrcpy(szFormat, TranslateT("%d directories"));
- mir_snwprintf(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, FileDlgData *dat, const wchar_t *buf)
-{
- // Make sure that the file matrix is empty (the user may select files several times)
- FreeFilesMatrix(&dat->files);
-
- // Get the file attributes of selection
- uint32_t 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 wchar_t *pBuf;
- int nNumberOfFiles = 0;
- int nTemp;
-
- // :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.
- size_t fileOffset = mir_wstrlen(buf) + 1;
-
- // Count number of files
- pBuf = buf + fileOffset;
- while (*pBuf) {
- pBuf += mir_wstrlen(pBuf) + 1;
- nNumberOfFiles++;
- }
-
- // Allocate memory for a pointer array
- if ((dat->files = (wchar_t**)mir_alloc((nNumberOfFiles + 1) * sizeof(wchar_t*))) == nullptr)
- return;
-
- // Fill the array
- pBuf = buf + fileOffset;
- nTemp = 0;
- while (*pBuf) {
- // Allocate space for path+filename
- size_t cbFileNameLen = mir_wstrlen(pBuf);
- dat->files[nTemp] = (wchar_t*)mir_alloc(sizeof(wchar_t)*(fileOffset + cbFileNameLen + 1));
-
- // Add path to filename and copy into array
- memcpy(dat->files[nTemp], buf, (fileOffset - 1) * sizeof(wchar_t));
- dat->files[nTemp][fileOffset - 1] = '\\';
- mir_wstrcpy(dat->files[nTemp] + fileOffset - (buf[fileOffset - 2] == '\\' ? 1 : 0), pBuf);
-
- // Move pointers to next file...
- pBuf += cbFileNameLen + 1;
- nTemp++;
- }
- // Terminate array
- dat->files[nNumberOfFiles] = nullptr;
- }
- // ...the selection is a single file
- else {
- if ((dat->files = (wchar_t **)mir_alloc(2 * sizeof(wchar_t*))) == nullptr) // Leaks when aborted
- return;
-
- dat->files[0] = mir_wstrdup(buf);
- dat->files[1] = nullptr;
- }
-
- // 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;
- FileDlgData *dat = (FileDlgData *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
-
- wchar_t *buf = (wchar_t *)mir_alloc(sizeof(wchar_t) * 32767);
- if (buf == nullptr) {
- PostMessage(hwndDlg, M_FILECHOOSEDONE, 0, NULL);
- return;
- }
-
- wchar_t filter[128];
- mir_wstrcpy(filter, TranslateT("All files"));
- mir_wstrcat(filter, L" (*)");
- wchar_t *pfilter = filter + mir_wstrlen(filter) + 1;
- mir_wstrcpy(pfilter, L"*");
- pfilter = filter + mir_wstrlen(filter) + 1;
- pfilter[0] = '\0';
-
- OPENFILENAME ofn = { 0 };
- ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
- ofn.hwndOwner = hwndDlg;
- ofn.lpstrFilter = filter;
- ofn.lpstrFile = buf; *buf = 0;
- ofn.nMaxFile = 32767;
- ofn.Flags = OFN_NOCHANGEDIR | OFN_FILEMUSTEXIST | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_DONTADDTORECENT;
-
- char *szProto = Proto_GetBaseAccountName(dat->hContact);
- if (!(CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_4, 0) & PF4_SINGLEFILEONLY))
- ofn.Flags |= OFN_ALLOWMULTISELECT;
-
- if (GetOpenFileName(&ofn))
- PostMessage(hwndDlg, M_FILECHOOSEDONE, 0, (LPARAM)buf);
- else {
- mir_free(buf);
- PostMessage(hwndDlg, M_FILECHOOSEDONE, 0, NULL);
- }
-}
-
-static BOOL CALLBACK ClipSiblingsChildEnumProc(HWND hwnd, LPARAM)
-{
- SetWindowLongPtr(hwnd, GWL_STYLE, GetWindowLongPtr(hwnd, GWL_STYLE) | WS_CLIPSIBLINGS);
- return TRUE;
-}
-
-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 mir_callNextSubclass(hwnd, SendEditSubclassProc, msg, wParam, lParam);
-}
-
-INT_PTR CALLBACK DlgProcSendFile(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- FileDlgData *dat = (FileDlgData *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
- switch (msg) {
- case WM_INITDIALOG:
- TranslateDialogDefault(hwndDlg);
- {
- FileSendData *fsd = (FileSendData *)lParam;
-
- dat = new 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 = nullptr;
- dat->dwTicks = GetTickCount();
-
- EnumChildWindows(hwndDlg, ClipSiblingsChildEnumProc, 0);
- mir_subclassWindow(GetDlgItem(hwndDlg, IDC_MSG), SendEditSubclassProc);
-
- Window_SetSkinIcon_IcoLib(hwndDlg, SKINICON_EVENT_FILE);
- Button_SetSkin_IcoLib(hwndDlg, IDC_DETAILS, SKINICON_OTHER_USERDETAILS, LPGEN("View user's details"));
- Button_SetSkin_IcoLib(hwndDlg, IDC_HISTORY, SKINICON_OTHER_HISTORY, LPGEN("View user's history"));
- Button_SetSkin_IcoLib(hwndDlg, IDC_USERMENU, SKINICON_OTHER_DOWNARROW, LPGEN("User menu"));
-
- char *szProto = Proto_GetBaseAccountName(dat->hContact);
- SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, STM_SETICON, LPARAM(Skin_LoadProtoIcon(szProto, ID_STATUS_ONLINE)), 0);
-
- EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
-
- if (fsd->ppFiles != nullptr && fsd->ppFiles[0] != nullptr) {
- int totalCount, i;
- for (totalCount = 0; fsd->ppFiles[totalCount]; totalCount++);
- dat->files = (wchar_t **)mir_alloc(sizeof(wchar_t *) * (totalCount + 1)); // Leaks
- for (i = 0; i < totalCount; i++)
- dat->files[i] = mir_wstrdup(fsd->ppFiles[i]);
- dat->files[totalCount] = nullptr;
- SetFileListAndSizeControls(hwndDlg, dat);
- }
-
- wchar_t *contactName = Clist_GetContactDisplayName(dat->hContact);
- SetDlgItemText(hwndDlg, IDC_TO, contactName);
-
- ptrW id(Contact::GetInfo(CNF_UNIQUEID, dat->hContact));
- SetDlgItemText(hwndDlg, IDC_NAME, (id) ? id : contactName);
-
- if (fsd->ppFiles == nullptr) {
- 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 Menu_MeasureItem(lParam);
-
- case WM_DRAWITEM:
- return Menu_DrawItem(lParam);
-
- case M_FILECHOOSEDONE:
- if (lParam != 0) {
- FilenameToFileList(hwndDlg, dat, (wchar_t *)lParam);
- mir_free((wchar_t *)lParam);
- dat->closeIfFileChooseCancelled = 0;
- }
- else if (dat->closeIfFileChooseCancelled)
- PostMessage(hwndDlg, WM_COMMAND, IDCANCEL, 0);
-
- EnableWindow(hwndDlg, TRUE);
- break;
-
- case WM_COMMAND:
- if (Clist_MenuProcessCommand(LOWORD(wParam), MPCF_CONTACTMENU, dat->hContact))
- break;
-
- switch (LOWORD(wParam)) {
- case IDC_CHOOSE:
- EnableWindow(hwndDlg, FALSE);
- mir_forkthread(ChooseFilesThread, hwndDlg);
- break;
-
- case IDOK:
- NotifyEventHooks(hDlgSucceeded, dat->hContact, (LPARAM)hwndDlg);
-
- EnableWindow(GetDlgItem(hwndDlg, IDC_FILENAME), FALSE);
- EnableWindow(GetDlgItem(hwndDlg, IDC_MSG), FALSE);
- EnableWindow(GetDlgItem(hwndDlg, IDC_CHOOSE), FALSE);
-
- GetDlgItemText(hwndDlg, IDC_FILEDIR, dat->szSavePath, _countof(dat->szSavePath));
- GetDlgItemText(hwndDlg, IDC_FILE, dat->szFilenames, _countof(dat->szFilenames));
- GetDlgItemText(hwndDlg, IDC_MSG, dat->szMsg, _countof(dat->szMsg));
- FtMgr_AddTransfer(dat);
- SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
- DestroyWindow(hwndDlg);
- return TRUE;
-
- case IDCANCEL:
- NotifyEventHooks(hDlgCanceled, dat->hContact, (LPARAM)hwndDlg);
- DestroyWindow(hwndDlg);
- return TRUE;
-
- case IDC_USERMENU:
- {
- RECT rc;
- GetWindowRect((HWND)lParam, &rc);
- HMENU hMenu = Menu_BuildContactMenu(dat->hContact);
- 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);
-
- delete dat;
- SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
- return TRUE;
- }
- return FALSE;
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda 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 "stdafx.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "file.h"
+
+static void SetFileListAndSizeControls(HWND hwndDlg, FileDlgData *dat)
+{
+ int fileCount = 0, dirCount = 0, i;
+ __int64 totalSize = 0;
+ struct _stati64 statbuf;
+ wchar_t str[64];
+
+ for (i = 0; dat->files[i]; i++) {
+ if (_wstat64(dat->files[i], &statbuf) == 0) {
+ if (statbuf.st_mode & _S_IFDIR)
+ dirCount++;
+ else
+ fileCount++;
+ totalSize += statbuf.st_size;
+ }
+ }
+
+ GetSensiblyFormattedSize(totalSize, str, _countof(str), 0, 1, NULL);
+ SetDlgItemText(hwndDlg, IDC_TOTALSIZE, str);
+ if (i > 1) {
+ wchar_t szFormat[32];
+ if (fileCount && dirCount) {
+ mir_snwprintf(szFormat, L"%s, %s", TranslateW(fileCount == 1 ? L"%d file" : L"%d files"), TranslateW(dirCount == 1 ? L"%d directory" : L"%d directories"));
+ mir_snwprintf(str, szFormat, fileCount, dirCount);
+ }
+ else if (fileCount) {
+ mir_wstrcpy(szFormat, TranslateT("%d files"));
+ mir_snwprintf(str, szFormat, fileCount);
+ }
+ else {
+ mir_wstrcpy(szFormat, TranslateT("%d directories"));
+ mir_snwprintf(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, FileDlgData *dat, const wchar_t *buf)
+{
+ // Make sure that the file matrix is empty (the user may select files several times)
+ FreeFilesMatrix(&dat->files);
+
+ // Get the file attributes of selection
+ uint32_t 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 wchar_t *pBuf;
+ int nNumberOfFiles = 0;
+ int nTemp;
+
+ // :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.
+ size_t fileOffset = mir_wstrlen(buf) + 1;
+
+ // Count number of files
+ pBuf = buf + fileOffset;
+ while (*pBuf) {
+ pBuf += mir_wstrlen(pBuf) + 1;
+ nNumberOfFiles++;
+ }
+
+ // Allocate memory for a pointer array
+ if ((dat->files = (wchar_t**)mir_alloc((nNumberOfFiles + 1) * sizeof(wchar_t*))) == nullptr)
+ return;
+
+ // Fill the array
+ pBuf = buf + fileOffset;
+ nTemp = 0;
+ while (*pBuf) {
+ // Allocate space for path+filename
+ size_t cbFileNameLen = mir_wstrlen(pBuf);
+ dat->files[nTemp] = (wchar_t*)mir_alloc(sizeof(wchar_t)*(fileOffset + cbFileNameLen + 1));
+
+ // Add path to filename and copy into array
+ memcpy(dat->files[nTemp], buf, (fileOffset - 1) * sizeof(wchar_t));
+ dat->files[nTemp][fileOffset - 1] = '\\';
+ mir_wstrcpy(dat->files[nTemp] + fileOffset - (buf[fileOffset - 2] == '\\' ? 1 : 0), pBuf);
+
+ // Move pointers to next file...
+ pBuf += cbFileNameLen + 1;
+ nTemp++;
+ }
+ // Terminate array
+ dat->files[nNumberOfFiles] = nullptr;
+ }
+ // ...the selection is a single file
+ else {
+ if ((dat->files = (wchar_t **)mir_alloc(2 * sizeof(wchar_t*))) == nullptr) // Leaks when aborted
+ return;
+
+ dat->files[0] = mir_wstrdup(buf);
+ dat->files[1] = nullptr;
+ }
+
+ // 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;
+ FileDlgData *dat = (FileDlgData *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+
+ wchar_t *buf = (wchar_t *)mir_alloc(sizeof(wchar_t) * 32767);
+ if (buf == nullptr) {
+ PostMessage(hwndDlg, M_FILECHOOSEDONE, 0, NULL);
+ return;
+ }
+
+ wchar_t filter[128];
+ mir_wstrcpy(filter, TranslateT("All files"));
+ mir_wstrcat(filter, L" (*)");
+ wchar_t *pfilter = filter + mir_wstrlen(filter) + 1;
+ mir_wstrcpy(pfilter, L"*");
+ pfilter = filter + mir_wstrlen(filter) + 1;
+ pfilter[0] = '\0';
+
+ OPENFILENAME ofn = { 0 };
+ ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
+ ofn.hwndOwner = hwndDlg;
+ ofn.lpstrFilter = filter;
+ ofn.lpstrFile = buf; *buf = 0;
+ ofn.nMaxFile = 32767;
+ ofn.Flags = OFN_NOCHANGEDIR | OFN_FILEMUSTEXIST | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_DONTADDTORECENT;
+
+ char *szProto = Proto_GetBaseAccountName(dat->hContact);
+ if (!(CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_4, 0) & PF4_SINGLEFILEONLY))
+ ofn.Flags |= OFN_ALLOWMULTISELECT;
+
+ if (GetOpenFileName(&ofn))
+ PostMessage(hwndDlg, M_FILECHOOSEDONE, 0, (LPARAM)buf);
+ else {
+ mir_free(buf);
+ PostMessage(hwndDlg, M_FILECHOOSEDONE, 0, NULL);
+ }
+}
+
+static BOOL CALLBACK ClipSiblingsChildEnumProc(HWND hwnd, LPARAM)
+{
+ SetWindowLongPtr(hwnd, GWL_STYLE, GetWindowLongPtr(hwnd, GWL_STYLE) | WS_CLIPSIBLINGS);
+ return TRUE;
+}
+
+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 mir_callNextSubclass(hwnd, SendEditSubclassProc, msg, wParam, lParam);
+}
+
+INT_PTR CALLBACK DlgProcSendFile(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ FileDlgData *dat = (FileDlgData *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ {
+ FileSendData *fsd = (FileSendData *)lParam;
+
+ dat = new 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 = nullptr;
+ dat->dwTicks = GetTickCount();
+
+ EnumChildWindows(hwndDlg, ClipSiblingsChildEnumProc, 0);
+ mir_subclassWindow(GetDlgItem(hwndDlg, IDC_MSG), SendEditSubclassProc);
+
+ Window_SetSkinIcon_IcoLib(hwndDlg, SKINICON_EVENT_FILE);
+ Button_SetSkin_IcoLib(hwndDlg, IDC_DETAILS, SKINICON_OTHER_USERDETAILS, LPGEN("View user's details"));
+ Button_SetSkin_IcoLib(hwndDlg, IDC_HISTORY, SKINICON_OTHER_HISTORY, LPGEN("View user's history"));
+ Button_SetSkin_IcoLib(hwndDlg, IDC_USERMENU, SKINICON_OTHER_DOWNARROW, LPGEN("User menu"));
+
+ char *szProto = Proto_GetBaseAccountName(dat->hContact);
+ SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, STM_SETICON, LPARAM(Skin_LoadProtoIcon(szProto, ID_STATUS_ONLINE)), 0);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
+
+ if (fsd->ppFiles != nullptr && fsd->ppFiles[0] != nullptr) {
+ int totalCount, i;
+ for (totalCount = 0; fsd->ppFiles[totalCount]; totalCount++);
+ dat->files = (wchar_t **)mir_alloc(sizeof(wchar_t *) * (totalCount + 1)); // Leaks
+ for (i = 0; i < totalCount; i++)
+ dat->files[i] = mir_wstrdup(fsd->ppFiles[i]);
+ dat->files[totalCount] = nullptr;
+ SetFileListAndSizeControls(hwndDlg, dat);
+ }
+
+ wchar_t *contactName = Clist_GetContactDisplayName(dat->hContact);
+ SetDlgItemText(hwndDlg, IDC_TO, contactName);
+
+ ptrW id(Contact::GetInfo(CNF_UNIQUEID, dat->hContact));
+ SetDlgItemText(hwndDlg, IDC_NAME, (id) ? id : contactName);
+
+ if (fsd->ppFiles == nullptr) {
+ 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 Menu_MeasureItem(lParam);
+
+ case WM_DRAWITEM:
+ return Menu_DrawItem(lParam);
+
+ case M_FILECHOOSEDONE:
+ if (lParam != 0) {
+ FilenameToFileList(hwndDlg, dat, (wchar_t *)lParam);
+ mir_free((wchar_t *)lParam);
+ dat->closeIfFileChooseCancelled = 0;
+ }
+ else if (dat->closeIfFileChooseCancelled)
+ PostMessage(hwndDlg, WM_COMMAND, IDCANCEL, 0);
+
+ EnableWindow(hwndDlg, TRUE);
+ break;
+
+ case WM_COMMAND:
+ if (Clist_MenuProcessCommand(LOWORD(wParam), MPCF_CONTACTMENU, dat->hContact))
+ break;
+
+ switch (LOWORD(wParam)) {
+ case IDC_CHOOSE:
+ EnableWindow(hwndDlg, FALSE);
+ mir_forkthread(ChooseFilesThread, hwndDlg);
+ break;
+
+ case IDOK:
+ NotifyEventHooks(hDlgSucceeded, dat->hContact, (LPARAM)hwndDlg);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FILENAME), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_MSG), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHOOSE), FALSE);
+
+ GetDlgItemText(hwndDlg, IDC_FILEDIR, dat->szSavePath, _countof(dat->szSavePath));
+ GetDlgItemText(hwndDlg, IDC_FILE, dat->szFilenames, _countof(dat->szFilenames));
+ GetDlgItemText(hwndDlg, IDC_MSG, dat->szMsg, _countof(dat->szMsg));
+ FtMgr_AddTransfer(dat);
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
+ DestroyWindow(hwndDlg);
+ return TRUE;
+
+ case IDCANCEL:
+ NotifyEventHooks(hDlgCanceled, dat->hContact, (LPARAM)hwndDlg);
+ DestroyWindow(hwndDlg);
+ return TRUE;
+
+ case IDC_USERMENU:
+ {
+ RECT rc;
+ GetWindowRect((HWND)lParam, &rc);
+ HMENU hMenu = Menu_BuildContactMenu(dat->hContact);
+ 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);
+
+ delete dat;
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/src/core/stdfile/src/filexferdlg.cpp b/src/mir_app/src/filexferdlg.cpp
index 5ab3a0679b..5743c9279e 100644
--- a/src/core/stdfile/src/filexferdlg.cpp
+++ b/src/mir_app/src/filexferdlg.cpp
@@ -1,752 +1,752 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda 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 "stdafx.h"
-#include <io.h>
-#include "file.h"
-
-static int CheckVirusScanned(HWND hwnd, FileDlgData *dat, int i)
-{
- if (dat->send) return 1;
- if (dat->fileVirusScanned == nullptr) return 0;
- if (dat->fileVirusScanned[i]) return 1;
- if (g_plugin.getByte("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
-{
- wchar_t *szFile;
- int returnCode;
- HWND hwndReply;
-};
-
-wchar_t* PFTS_StringToTchar(int flags, const wchar_t *s)
-{
- if (flags & PFTS_UTF)
- return mir_utf8decodeW((char*)s);
- if (flags & PFTS_UNICODE)
- return mir_wstrdup(s);
- return mir_a2u((char*)s);
-}
-
-int PFTS_CompareWithTchar(PROTOFILETRANSFERSTATUS *ft, const wchar_t *s, wchar_t *r)
-{
- if (ft->flags & PFTS_UTF) {
- wchar_t *ts = mir_utf8decodeW((char*)s);
- int res = mir_wstrcmp(ts, r);
- mir_free(ts);
- return res;
- }
- if (ft->flags & PFTS_UNICODE)
- return mir_wstrcmp(s, r);
-
- wchar_t *ts = mir_a2u((char*)s);
- int res = mir_wstrcmp(ts, r);
- mir_free(ts);
- return res;
-}
-
-static void SetOpenFileButtonStyle(HWND hwndButton, int enabled)
-{
- EnableWindow(hwndButton, enabled);
-}
-
-static void __cdecl RunVirusScannerThread(virusscanthreadstartinfo *info)
-{
- DBVARIANT dbv;
- if (!g_plugin.getWString("ScanCmdLine", &dbv)) {
- if (dbv.pwszVal[0]) {
- STARTUPINFO si = { 0 };
- si.cb = sizeof(si);
- wchar_t *pszReplace = wcsstr(dbv.pwszVal, L"%f");
- wchar_t szCmdLine[768];
- if (pszReplace) {
- if (info->szFile[mir_wstrlen(info->szFile) - 1] == '\\')
- info->szFile[mir_wstrlen(info->szFile) - 1] = '\0';
- *pszReplace = 0;
- mir_snwprintf(szCmdLine, L"%s\"%s\"%s", dbv.pwszVal, info->szFile, pszReplace + 2);
- }
- else
- wcsncpy_s(szCmdLine, dbv.pwszVal, _TRUNCATE);
-
- PROCESS_INFORMATION pi;
- if (CreateProcess(nullptr, szCmdLine, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &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);
- }
- }
- db_free(&dbv);
- }
- mir_free(info->szFile);
- mir_free(info);
-}
-
-static void SetFilenameControls(HWND hwndDlg, FileDlgData *dat, PROTOFILETRANSFERSTATUS *fts)
-{
- wchar_t msg[MAX_PATH];
- wchar_t *fnbuf = nullptr, *fn = nullptr;
- SHFILEINFO shfi = {};
-
- if (fts->szCurrentFile.w) {
- fnbuf = mir_wstrdup(fts->szCurrentFile.w);
- if ((fn = wcsrchr(fnbuf, '\\')) == nullptr)
- fn = fnbuf;
- else fn++;
- }
-
- if (dat->hIcon) DestroyIcon(dat->hIcon); dat->hIcon = nullptr;
-
- if (fn && (fts->totalFiles > 1)) {
- mir_snwprintf(msg, L"%s: %s (%d %s %d)", Clist_GetContactDisplayName(fts->hContact), 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_snwprintf(msg, L"%s: %s", Clist_GetContactDisplayName(fts->hContact), fn);
-
- SHGetFileInfo(fn, FILE_ATTRIBUTE_NORMAL, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_ICON | SHGFI_SMALLICON);
- dat->hIcon = shfi.hIcon;
- }
- else {
- mir_wstrncpy(msg, Clist_GetContactDisplayName(fts->hContact), _countof(msg));
- HICON hIcon = Skin_LoadIcon(SKINICON_OTHER_DOWNARROW);
- dat->hIcon = CopyIcon(hIcon);
- IcoLib_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, wchar_t *text, int mode)
-{
- SetDlgItemText(hwndDlg, IDC_STATUS, TranslateW(text));
- SetDlgItemText(hwndDlg, IDC_TRANSFERCOMPLETED, TranslateW(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(nullptr, hwndDlg, (LPPOINT)&rc, 2);
- SetWindowPos(hwndDlg, nullptr, 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 param, UTILRESIZECONTROL *urc)
-{
- auto *dat = (FileDlgData *)param;
-
- 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:
- if (dat->waitingForAcceptance)
- return RD_ANCHORX_WIDTH | RD_ANCHORY_TOP;
-
- 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_TOP;
-
- case IDC_ALLSPEED:
- if (dat->waitingForAcceptance)
- return RD_ANCHORX_RIGHT | RD_ANCHORY_TOP;
-
- 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_TOP;
- }
- 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) {
- if (db_mc_isMeta(dat->hContact))
- dat->hContact = db_mc_getMostOnline(dat->hContact);
- dat->fs = (HANDLE)ProtoChainSend(dat->hContact, PSS_FILE, (WPARAM)dat->szMsg, (LPARAM)dat->files);
- SetFtStatus(hwndDlg, LPGENW("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
- CreateDirectoryTreeW(dat->szSavePath);
- dat->fs = (HANDLE)ProtoChainSend(dat->hContact, PSS_FILEALLOW, (WPARAM)dat->fs, (LPARAM)dat->szSavePath);
- dat->transferStatus.szWorkingDir.w = mir_wstrdup(dat->szSavePath);
- if (!Contact::OnList(dat->hContact))
- dat->resumeBehaviour = FILERESUME_ASK;
- else
- dat->resumeBehaviour = g_plugin.getByte("IfExists", FILERESUME_ASK);
- SetFtStatus(hwndDlg, LPGENW("Waiting for connection..."), FTS_TEXT);
- }
-
- /* check we actually got an fs handle back from the protocol */
- if (!dat->fs) {
- SetFtStatus(hwndDlg, LPGENW("Unable to initiate transfer."), FTS_TEXT);
- dat->waitingForAcceptance = 0;
- }
- {
- LOGFONT lf;
- 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 = {};
- SHGetFileInfo(L"", FILE_ATTRIBUTE_DIRECTORY, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_ICON | SHGFI_SMALLICON);
- dat->hIconFolder = shfi.hIcon;
- }
- dat->hIcon = nullptr;
- {
- char *szProto = Proto_GetBaseAccountName(dat->hContact);
- uint16_t status = db_get_w(dat->hContact, szProto, "Status", ID_STATUS_ONLINE);
- SendDlgItemMessage(hwndDlg, IDC_CONTACT, BM_SETIMAGE, IMAGE_ICON, (LPARAM)Skin_LoadProtoIcon(szProto, status));
- }
-
- SendDlgItemMessage(hwndDlg, IDC_CONTACT, BUTTONADDTOOLTIP, (WPARAM)LPGEN("Contact menu"), 0);
- SendDlgItemMessage(hwndDlg, IDC_CONTACT, BUTTONSETASFLATBTN, TRUE, 0);
-
- Button_SetSkin_IcoLib(hwndDlg, IDC_OPENFILE, SKINICON_OTHER_DOWNARROW, LPGEN("Open..."));
- SendDlgItemMessage(hwndDlg, IDC_OPENFILE, BUTTONSETASPUSHBTN, TRUE, 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, TRUE, 0);
-
- Button_SetSkin_IcoLib(hwndDlg, IDCANCEL, SKINICON_OTHER_DELETE, LPGEN("Cancel"));
-
- SetDlgItemText(hwndDlg, IDC_CONTACTNAME, Clist_GetContactDisplayName(dat->hContact));
-
- if (!dat->waitingForAcceptance)
- SetTimer(hwndDlg, 1, 1000, nullptr);
- return TRUE;
-
- case WM_TIMER:
- memmove(dat->bytesRecvedHistory + 1, dat->bytesRecvedHistory, sizeof(dat->bytesRecvedHistory) - sizeof(dat->bytesRecvedHistory[0]));
- dat->bytesRecvedHistory[0] = dat->transferStatus.totalProgress;
- if (dat->bytesRecvedHistorySize < _countof(dat->bytesRecvedHistory))
- dat->bytesRecvedHistorySize++;
-
- wchar_t 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, _countof(szSpeed), 0, 1, NULL);
- if (dat->bytesRecvedHistory[0] == dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1])
- mir_wstrcpy(szTime, L"??:??:??");
- else {
- li.QuadPart = 10000000ll * (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, _countof(szTime));
- }
- if (dat->bytesRecvedHistory[0] != dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1]) {
- li.QuadPart = 10000000ll * (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, _countof(szTime));
- }
-
- mir_snwprintf(szDisplay, L"%s/%s (%s %s)", szSpeed, TranslateT("sec"), szTime, TranslateT("remaining"));
- SetDlgItemText(hwndDlg, IDC_ALLSPEED, szDisplay);
- break;
-
- case WM_MEASUREITEM:
- return Menu_MeasureItem(lParam);
-
- case WM_DRAWITEM:
- return Menu_DrawItem(lParam);
-
- case WM_FT_CLEANUP:
- if (!dat->fs) {
- PostMessage(GetParent(hwndDlg), WM_FT_REMOVE, 0, (LPARAM)hwndDlg);
- DestroyWindow(hwndDlg);
- }
- break;
-
- case WM_COMMAND:
- if (!dat)
- break;
-
- if (Clist_MenuProcessCommand(LOWORD(wParam), MPCF_CONTACTMENU, 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 = Menu_BuildContactMenu(dat->hContact);
- 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:
- {
- wchar_t *path = dat->transferStatus.szWorkingDir.w;
- if (!path || !path[0]) {
- path = NEWWSTR_ALLOCA(dat->transferStatus.szCurrentFile.w);
- wchar_t *p = wcsrchr(path, '\\'); if (p) *p = 0;
- }
-
- if (path) ShellExecute(NULL, L"open", path, NULL, NULL, SW_SHOW);
- }
- break;
-
- case IDC_OPENFILE:
- wchar_t **files;
- if (dat->send) {
- if (dat->files == nullptr)
- files = dat->transferStatus.pszFiles.w;
- else
- files = dat->files;
- }
- else files = dat->files;
-
- HMENU hMenu = CreatePopupMenu();
- AppendMenu(hMenu, MF_STRING, 1, TranslateT("Open folder"));
- AppendMenu(hMenu, MF_SEPARATOR, 0, nullptr);
-
- if (files && *files) {
- int limit;
- wchar_t *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 (int i = 0; i < limit; i++) {
- pszFilename = wcsrchr(files[i], '\\');
- if (pszFilename == nullptr)
- pszFilename = files[i];
- else
- pszFilename++;
-
- if (pszFilename) {
- size_t cbFileNameLen = mir_wstrlen(pszFilename);
-
- pszNewFileName = (wchar_t*)mir_alloc(cbFileNameLen * 2 * sizeof(wchar_t));
- wchar_t *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);
- }
- }
- }
-
- RECT rc;
- GetWindowRect((HWND)lParam, &rc);
- CheckDlgButton(hwndDlg, IDC_OPENFILE, BST_CHECKED);
- int ret = TrackPopupMenu(hMenu, TPM_RETURNCMD | TPM_RIGHTALIGN, rc.right, rc.bottom, 0, hwndDlg, nullptr);
- CheckDlgButton(hwndDlg, IDC_OPENFILE, BST_UNCHECKED);
- DestroyMenu(hMenu);
-
- if (ret == 1) {
- wchar_t *path = dat->transferStatus.szWorkingDir.w;
- if (!path || !path[0]) {
- path = NEWWSTR_ALLOCA(dat->transferStatus.szCurrentFile.w);
- wchar_t *p = wcsrchr(path, '\\');
- if (p)
- *p = 0;
- }
-
- if (path) ShellExecute(nullptr, L"open", path, nullptr, nullptr, SW_SHOW);
- }
- else if (ret && CheckVirusScanned(hwndDlg, dat, ret))
- ShellExecute(nullptr, nullptr, files[ret - 10], nullptr, nullptr, SW_SHOW);
- }
- break;
-
- case M_FILEEXISTSDLGREPLY:
- EnableWindow(hwndDlg, TRUE);
- {
- PROTOFILERESUME *pfr = (PROTOFILERESUME *)lParam;
- wchar_t *szOriginalFilename = (wchar_t *)wParam;
- char *szProto = Proto_GetBaseAccountName(dat->hContact);
-
- switch (pfr->action) {
- case FILERESUME_CANCEL:
- if (dat->fs) ProtoChainSend(dat->hContact, PSS_FILECANCEL, (WPARAM)dat->fs, 0);
- dat->fs = nullptr;
- 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;
- {
- wchar_t *pszExtension, *pszFilename;
- if ((pszFilename = wcsrchr(szOriginalFilename, '\\')) == nullptr) pszFilename = szOriginalFilename;
- if ((pszExtension = wcsrchr(pszFilename + 1, '.')) == nullptr) pszExtension = pszFilename + mir_wstrlen(pszFilename);
- if (pfr->szFilename) mir_free((wchar_t *)pfr->szFilename);
- size_t size = (pszExtension - szOriginalFilename) + 21 + mir_wstrlen(pszExtension);
- pfr->szFilename = (wchar_t *)mir_alloc(sizeof(wchar_t) * size);
- for (int i = 1;; i++) {
- mir_snwprintf((wchar_t *)pfr->szFilename, size, L"%.*s (%u)%s", pszExtension - szOriginalFilename, szOriginalFilename, i, pszExtension);
- if (_waccess(pfr->szFilename, 0) != 0)
- break;
- }
- }
- break;
- }
- mir_free(szOriginalFilename);
- CallProtoService(szProto, PS_FILERESUME, (WPARAM)dat->fs, (LPARAM)pfr);
- delete pfr;
- }
- break;
-
- case HM_RECVEVENT:
- {
- ACKDATA *ack = (ACKDATA *)lParam;
- if (ack->hProcess != dat->fs) break;
- if (ack->type != ACKTYPE_FILE) break;
- if (ack->hContact != dat->hContact) break;
-
- if (dat->waitingForAcceptance) {
- SetTimer(hwndDlg, 1, 1000, nullptr);
- dat->waitingForAcceptance = 0;
- }
-
- switch (ack->result) {
- case ACKRESULT_SENTREQUEST: SetFtStatus(hwndDlg, LPGENW("Decision sent"), FTS_TEXT); break;
- case ACKRESULT_CONNECTING: SetFtStatus(hwndDlg, LPGENW("Connecting..."), FTS_TEXT); break;
- case ACKRESULT_CONNECTPROXY: SetFtStatus(hwndDlg, LPGENW("Connecting to proxy..."), FTS_TEXT); break;
- case ACKRESULT_CONNECTED: SetFtStatus(hwndDlg, LPGENW("Connected"), FTS_TEXT); break;
- case ACKRESULT_LISTENING: SetFtStatus(hwndDlg, LPGENW("Waiting for connection..."), FTS_TEXT); break;
- case ACKRESULT_INITIALISING: SetFtStatus(hwndDlg, LPGENW("Initializing..."), FTS_TEXT); break;
- case ACKRESULT_NEXTFILE:
- SetFtStatus(hwndDlg, LPGENW("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 && g_plugin.getByte("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 = (virusscanthreadstartinfo *)mir_alloc(sizeof(virusscanthreadstartinfo));
- vstsi->hwndReply = hwndDlg;
- vstsi->szFile = mir_wstrdup(dat->files[dat->transferStatus.currentFileNumber]);
- vstsi->returnCode = dat->transferStatus.currentFileNumber;
- mir_forkThread<virusscanthreadstartinfo>(RunVirusScannerThread, vstsi);
- }
- }
- break;
-
- case ACKRESULT_FILERESUME:
- UpdateProtoFileTransferStatus(&dat->transferStatus, (PROTOFILETRANSFERSTATUS *)ack->lParam);
- {
- PROTOFILETRANSFERSTATUS *fts = &dat->transferStatus;
- SetFilenameControls(hwndDlg, dat, fts);
- if (_waccess(fts->szCurrentFile.w, 0))
- break;
-
- SetFtStatus(hwndDlg, LPGENW("File already exists"), FTS_TEXT);
- if (dat->resumeBehaviour == FILERESUME_ASK) {
- TDlgProcFileExistsParam param = { hwndDlg, fts };
- ShowWindow(hwndDlg, SW_SHOWNORMAL);
- CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_FILEEXISTS), hwndDlg, DlgProcFileExists, (LPARAM)&param);
- EnableWindow(hwndDlg, FALSE);
- }
- else {
- PROTOFILERESUME *pfr = new PROTOFILERESUME();
- pfr->action = dat->resumeBehaviour;
- pfr->szFilename = nullptr;
- PostMessage(hwndDlg, M_FILEEXISTSDLGREPLY, (WPARAM)mir_wstrdup(fts->szCurrentFile.w), (LPARAM)pfr);
- }
- }
- SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, 1);
- return TRUE;
-
- case ACKRESULT_DATA:
- {
- PROTOFILETRANSFERSTATUS *fts = (PROTOFILETRANSFERSTATUS *)ack->lParam;
- wchar_t str[64], str2[64], szSizeDone[32], szSizeTotal[32];//, *contactName;
-
- if (dat->fileVirusScanned == nullptr)
- 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 == nullptr)
- dat->files = (wchar_t **)mir_calloc((fts->totalFiles + 1) * sizeof(wchar_t *));
- if (fts->currentFileNumber < fts->totalFiles && dat->files[fts->currentFileNumber] == nullptr)
- dat->files[fts->currentFileNumber] = PFTS_StringToTchar(fts->flags, fts->szCurrentFile.w);
- }
-
- /* 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 ((GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_ALLFILESPROGRESS), GWL_STYLE) & WS_VISIBLE) == 0) {
- SetFtStatus(hwndDlg, (fts->flags & PFTS_SENDING) ? LPGENW("Sending...") : LPGENW("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 ? (100ll * fts->totalProgress / fts->totalBytes) : 0;
- if (lastPos != nextPos || firstTime) {
- SendDlgItemMessage(hwndDlg, IDC_ALLFILESPROGRESS, PBM_SETPOS, nextPos, 0);
- mir_snwprintf(str, L"%u%%", nextPos);
- SetDlgItemText(hwndDlg, IDC_ALLPRECENTS, str);
- }
-
- int units;
- GetSensiblyFormattedSize(fts->totalBytes, szSizeTotal, _countof(szSizeTotal), 0, 1, &units);
- GetSensiblyFormattedSize(fts->totalProgress, szSizeDone, _countof(szSizeDone), units, 0, NULL);
- mir_snwprintf(str, L"%s/%s", szSizeDone, szSizeTotal);
- str2[0] = 0;
- GetDlgItemText(hwndDlg, IDC_ALLTRANSFERRED, str2, _countof(str2));
- if (mir_wstrcmp(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 = nullptr;
-
- if (ack->result == ACKRESULT_DENIED) {
- dat->fs = nullptr; /* protocol will free structure */
- Skin_PlaySound("FileDenied");
- SetFtStatus(hwndDlg, LPGENW("File transfer denied"), FTS_TEXT);
- }
- else if (ack->result == ACKRESULT_FAILED) {
- dat->fs = nullptr; /* protocol will free structure */
- Skin_PlaySound("FileFailed");
- SetFtStatus(hwndDlg, LPGENW("File transfer failed"), FTS_TEXT);
- }
- else {
- Skin_PlaySound("FileDone");
- if (dat->send) {
- dat->fs = nullptr; /* protocol will free structure */
- SetFtStatus(hwndDlg, LPGENW("Transfer completed."), FTS_TEXT);
-
- DB::EventInfo dbei;
- dbei.szModule = Proto_GetBaseAccountName(dat->hContact);
- dbei.eventType = EVENTTYPE_FILE;
- dbei.flags = DBEF_SENT;
- dbei.timestamp = time(0);
- dbei.flags |= DBEF_UTF;
-
- DB::FILE_BLOB blob(dat->szFilenames, dat->szMsg);
- blob.write(dbei);
- db_event_add(dat->hContact, &dbei);
-
- dat->files = nullptr; //protocol library frees this
- }
- else {
- SetFtStatus(hwndDlg,
- (dat->transferStatus.totalFiles == 1) ?
- LPGENW("Transfer completed, open file.") :
- LPGENW("Transfer completed, open folder."),
- FTS_OPEN);
-
- int useScanner = g_plugin.getByte("UseScanner", VIRUSSCAN_DISABLE);
- if (useScanner != VIRUSSCAN_DISABLE) {
- auto *vstsi = (virusscanthreadstartinfo *)mir_alloc(sizeof(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 = nullptr;
- }
- else vstsi->szFile = mir_wstrdup(dat->files[dat->transferStatus.currentFileNumber]);
- }
- else {
- vstsi->szFile = mir_wstrdup(dat->transferStatus.szWorkingDir.w);
- vstsi->returnCode = -1;
- }
- SetFtStatus(hwndDlg, LPGENW("Scanning for viruses..."), FTS_TEXT);
- if (vstsi)
- mir_forkThread<virusscanthreadstartinfo>(RunVirusScannerThread, vstsi);
- }
- else dat->fs = nullptr; /* protocol will free structure */
-
- dat->transferStatus.currentFileNumber = dat->transferStatus.totalFiles;
- }
- }
-
- PostMessage(GetParent(hwndDlg), WM_FT_COMPLETED, ack->result, (LPARAM)hwndDlg);
- break;
- }
- }
- break;
-
- case M_VIRUSSCANDONE:
- {
- int done = 1;
- if ((int)wParam == -1) {
- for (int i = 0; i < dat->transferStatus.totalFiles; i++)
- dat->fileVirusScanned[i] = 1;
- }
- else {
- dat->fileVirusScanned[wParam] = 1;
- for (int i = 0; i < dat->transferStatus.totalFiles; i++)
- if (!dat->fileVirusScanned[i]) {
- done = 0;
- break;
- }
- }
- if (done) {
- dat->fs = nullptr; /* protocol will free structure */
- SetFtStatus(hwndDlg, LPGENW("Transfer and virus scan complete"), FTS_TEXT);
- }
- }
- break;
-
- case WM_SIZE:
- Utils_ResizeDialog(hwndDlg, g_plugin.getInst(), MAKEINTRESOURCEA(IDD_FILETRANSFERINFO), FileTransferDlgResizer, LPARAM(dat));
-
- 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);
-
- delete dat;
- SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
- break;
- }
- return FALSE;
-}
-
-FileDlgData::~FileDlgData()
-{
- if (fs)
- ProtoChainSend(hContact, PSS_FILECANCEL, (WPARAM)fs, 0);
-
- UnhookEvent(hPreshutdownEvent);
- UnhookEvent(hNotifyEvent);
-
- FreeProtoFileTransferStatus(&transferStatus);
- FreeFilesMatrix(&files);
-
- mir_free(fileVirusScanned);
- if (hIcon)
- DestroyIcon(hIcon);
- if (hIconFolder)
- DestroyIcon(hIconFolder);
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda 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 "stdafx.h"
+#include <io.h>
+#include "file.h"
+
+static int CheckVirusScanned(HWND hwnd, FileDlgData *dat, int i)
+{
+ if (dat->send) return 1;
+ if (dat->fileVirusScanned == nullptr) return 0;
+ if (dat->fileVirusScanned[i]) return 1;
+ if (g_plugin.getByte("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
+{
+ wchar_t *szFile;
+ int returnCode;
+ HWND hwndReply;
+};
+
+wchar_t* PFTS_StringToTchar(int flags, const wchar_t *s)
+{
+ if (flags & PFTS_UTF)
+ return mir_utf8decodeW((char*)s);
+ if (flags & PFTS_UNICODE)
+ return mir_wstrdup(s);
+ return mir_a2u((char*)s);
+}
+
+int PFTS_CompareWithTchar(PROTOFILETRANSFERSTATUS *ft, const wchar_t *s, wchar_t *r)
+{
+ if (ft->flags & PFTS_UTF) {
+ wchar_t *ts = mir_utf8decodeW((char*)s);
+ int res = mir_wstrcmp(ts, r);
+ mir_free(ts);
+ return res;
+ }
+ if (ft->flags & PFTS_UNICODE)
+ return mir_wstrcmp(s, r);
+
+ wchar_t *ts = mir_a2u((char*)s);
+ int res = mir_wstrcmp(ts, r);
+ mir_free(ts);
+ return res;
+}
+
+static void SetOpenFileButtonStyle(HWND hwndButton, int enabled)
+{
+ EnableWindow(hwndButton, enabled);
+}
+
+static void __cdecl RunVirusScannerThread(virusscanthreadstartinfo *info)
+{
+ DBVARIANT dbv;
+ if (!g_plugin.getWString("ScanCmdLine", &dbv)) {
+ if (dbv.pwszVal[0]) {
+ STARTUPINFO si = { 0 };
+ si.cb = sizeof(si);
+ wchar_t *pszReplace = wcsstr(dbv.pwszVal, L"%f");
+ wchar_t szCmdLine[768];
+ if (pszReplace) {
+ if (info->szFile[mir_wstrlen(info->szFile) - 1] == '\\')
+ info->szFile[mir_wstrlen(info->szFile) - 1] = '\0';
+ *pszReplace = 0;
+ mir_snwprintf(szCmdLine, L"%s\"%s\"%s", dbv.pwszVal, info->szFile, pszReplace + 2);
+ }
+ else
+ wcsncpy_s(szCmdLine, dbv.pwszVal, _TRUNCATE);
+
+ PROCESS_INFORMATION pi;
+ if (CreateProcess(nullptr, szCmdLine, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &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);
+ }
+ }
+ db_free(&dbv);
+ }
+ mir_free(info->szFile);
+ mir_free(info);
+}
+
+static void SetFilenameControls(HWND hwndDlg, FileDlgData *dat, PROTOFILETRANSFERSTATUS *fts)
+{
+ wchar_t msg[MAX_PATH];
+ wchar_t *fnbuf = nullptr, *fn = nullptr;
+ SHFILEINFO shfi = {};
+
+ if (fts->szCurrentFile.w) {
+ fnbuf = mir_wstrdup(fts->szCurrentFile.w);
+ if ((fn = wcsrchr(fnbuf, '\\')) == nullptr)
+ fn = fnbuf;
+ else fn++;
+ }
+
+ if (dat->hIcon) DestroyIcon(dat->hIcon); dat->hIcon = nullptr;
+
+ if (fn && (fts->totalFiles > 1)) {
+ mir_snwprintf(msg, L"%s: %s (%d %s %d)", Clist_GetContactDisplayName(fts->hContact), 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_snwprintf(msg, L"%s: %s", Clist_GetContactDisplayName(fts->hContact), fn);
+
+ SHGetFileInfo(fn, FILE_ATTRIBUTE_NORMAL, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_ICON | SHGFI_SMALLICON);
+ dat->hIcon = shfi.hIcon;
+ }
+ else {
+ mir_wstrncpy(msg, Clist_GetContactDisplayName(fts->hContact), _countof(msg));
+ HICON hIcon = Skin_LoadIcon(SKINICON_OTHER_DOWNARROW);
+ dat->hIcon = CopyIcon(hIcon);
+ IcoLib_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, wchar_t *text, int mode)
+{
+ SetDlgItemText(hwndDlg, IDC_STATUS, TranslateW(text));
+ SetDlgItemText(hwndDlg, IDC_TRANSFERCOMPLETED, TranslateW(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(nullptr, hwndDlg, (LPPOINT)&rc, 2);
+ SetWindowPos(hwndDlg, nullptr, 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 param, UTILRESIZECONTROL *urc)
+{
+ auto *dat = (FileDlgData *)param;
+
+ 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:
+ if (dat->waitingForAcceptance)
+ return RD_ANCHORX_WIDTH | RD_ANCHORY_TOP;
+
+ 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_TOP;
+
+ case IDC_ALLSPEED:
+ if (dat->waitingForAcceptance)
+ return RD_ANCHORX_RIGHT | RD_ANCHORY_TOP;
+
+ 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_TOP;
+ }
+ 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) {
+ if (db_mc_isMeta(dat->hContact))
+ dat->hContact = db_mc_getMostOnline(dat->hContact);
+ dat->fs = (HANDLE)ProtoChainSend(dat->hContact, PSS_FILE, (WPARAM)dat->szMsg, (LPARAM)dat->files);
+ SetFtStatus(hwndDlg, LPGENW("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
+ CreateDirectoryTreeW(dat->szSavePath);
+ dat->fs = (HANDLE)ProtoChainSend(dat->hContact, PSS_FILEALLOW, (WPARAM)dat->fs, (LPARAM)dat->szSavePath);
+ dat->transferStatus.szWorkingDir.w = mir_wstrdup(dat->szSavePath);
+ if (!Contact::OnList(dat->hContact))
+ dat->resumeBehaviour = FILERESUME_ASK;
+ else
+ dat->resumeBehaviour = g_plugin.getByte("IfExists", FILERESUME_ASK);
+ SetFtStatus(hwndDlg, LPGENW("Waiting for connection..."), FTS_TEXT);
+ }
+
+ /* check we actually got an fs handle back from the protocol */
+ if (!dat->fs) {
+ SetFtStatus(hwndDlg, LPGENW("Unable to initiate transfer."), FTS_TEXT);
+ dat->waitingForAcceptance = 0;
+ }
+ {
+ LOGFONT lf;
+ 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 = {};
+ SHGetFileInfo(L"", FILE_ATTRIBUTE_DIRECTORY, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_ICON | SHGFI_SMALLICON);
+ dat->hIconFolder = shfi.hIcon;
+ }
+ dat->hIcon = nullptr;
+ {
+ char *szProto = Proto_GetBaseAccountName(dat->hContact);
+ uint16_t status = db_get_w(dat->hContact, szProto, "Status", ID_STATUS_ONLINE);
+ SendDlgItemMessage(hwndDlg, IDC_CONTACT, BM_SETIMAGE, IMAGE_ICON, (LPARAM)Skin_LoadProtoIcon(szProto, status));
+ }
+
+ SendDlgItemMessage(hwndDlg, IDC_CONTACT, BUTTONADDTOOLTIP, (WPARAM)LPGEN("Contact menu"), 0);
+ SendDlgItemMessage(hwndDlg, IDC_CONTACT, BUTTONSETASFLATBTN, TRUE, 0);
+
+ Button_SetSkin_IcoLib(hwndDlg, IDC_OPENFILE, SKINICON_OTHER_DOWNARROW, LPGEN("Open..."));
+ SendDlgItemMessage(hwndDlg, IDC_OPENFILE, BUTTONSETASPUSHBTN, TRUE, 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, TRUE, 0);
+
+ Button_SetSkin_IcoLib(hwndDlg, IDCANCEL, SKINICON_OTHER_DELETE, LPGEN("Cancel"));
+
+ SetDlgItemText(hwndDlg, IDC_CONTACTNAME, Clist_GetContactDisplayName(dat->hContact));
+
+ if (!dat->waitingForAcceptance)
+ SetTimer(hwndDlg, 1, 1000, nullptr);
+ return TRUE;
+
+ case WM_TIMER:
+ memmove(dat->bytesRecvedHistory + 1, dat->bytesRecvedHistory, sizeof(dat->bytesRecvedHistory) - sizeof(dat->bytesRecvedHistory[0]));
+ dat->bytesRecvedHistory[0] = dat->transferStatus.totalProgress;
+ if (dat->bytesRecvedHistorySize < _countof(dat->bytesRecvedHistory))
+ dat->bytesRecvedHistorySize++;
+
+ wchar_t 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, _countof(szSpeed), 0, 1, NULL);
+ if (dat->bytesRecvedHistory[0] == dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1])
+ mir_wstrcpy(szTime, L"??:??:??");
+ else {
+ li.QuadPart = 10000000ll * (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, _countof(szTime));
+ }
+ if (dat->bytesRecvedHistory[0] != dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1]) {
+ li.QuadPart = 10000000ll * (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, _countof(szTime));
+ }
+
+ mir_snwprintf(szDisplay, L"%s/%s (%s %s)", szSpeed, TranslateT("sec"), szTime, TranslateT("remaining"));
+ SetDlgItemText(hwndDlg, IDC_ALLSPEED, szDisplay);
+ break;
+
+ case WM_MEASUREITEM:
+ return Menu_MeasureItem(lParam);
+
+ case WM_DRAWITEM:
+ return Menu_DrawItem(lParam);
+
+ case WM_FT_CLEANUP:
+ if (!dat->fs) {
+ PostMessage(GetParent(hwndDlg), WM_FT_REMOVE, 0, (LPARAM)hwndDlg);
+ DestroyWindow(hwndDlg);
+ }
+ break;
+
+ case WM_COMMAND:
+ if (!dat)
+ break;
+
+ if (Clist_MenuProcessCommand(LOWORD(wParam), MPCF_CONTACTMENU, 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 = Menu_BuildContactMenu(dat->hContact);
+ 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:
+ {
+ wchar_t *path = dat->transferStatus.szWorkingDir.w;
+ if (!path || !path[0]) {
+ path = NEWWSTR_ALLOCA(dat->transferStatus.szCurrentFile.w);
+ wchar_t *p = wcsrchr(path, '\\'); if (p) *p = 0;
+ }
+
+ if (path) ShellExecute(NULL, L"open", path, NULL, NULL, SW_SHOW);
+ }
+ break;
+
+ case IDC_OPENFILE:
+ wchar_t **files;
+ if (dat->send) {
+ if (dat->files == nullptr)
+ files = dat->transferStatus.pszFiles.w;
+ else
+ files = dat->files;
+ }
+ else files = dat->files;
+
+ HMENU hMenu = CreatePopupMenu();
+ AppendMenu(hMenu, MF_STRING, 1, TranslateT("Open folder"));
+ AppendMenu(hMenu, MF_SEPARATOR, 0, nullptr);
+
+ if (files && *files) {
+ int limit;
+ wchar_t *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 (int i = 0; i < limit; i++) {
+ pszFilename = wcsrchr(files[i], '\\');
+ if (pszFilename == nullptr)
+ pszFilename = files[i];
+ else
+ pszFilename++;
+
+ if (pszFilename) {
+ size_t cbFileNameLen = mir_wstrlen(pszFilename);
+
+ pszNewFileName = (wchar_t*)mir_alloc(cbFileNameLen * 2 * sizeof(wchar_t));
+ wchar_t *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);
+ }
+ }
+ }
+
+ RECT rc;
+ GetWindowRect((HWND)lParam, &rc);
+ CheckDlgButton(hwndDlg, IDC_OPENFILE, BST_CHECKED);
+ int ret = TrackPopupMenu(hMenu, TPM_RETURNCMD | TPM_RIGHTALIGN, rc.right, rc.bottom, 0, hwndDlg, nullptr);
+ CheckDlgButton(hwndDlg, IDC_OPENFILE, BST_UNCHECKED);
+ DestroyMenu(hMenu);
+
+ if (ret == 1) {
+ wchar_t *path = dat->transferStatus.szWorkingDir.w;
+ if (!path || !path[0]) {
+ path = NEWWSTR_ALLOCA(dat->transferStatus.szCurrentFile.w);
+ wchar_t *p = wcsrchr(path, '\\');
+ if (p)
+ *p = 0;
+ }
+
+ if (path) ShellExecute(nullptr, L"open", path, nullptr, nullptr, SW_SHOW);
+ }
+ else if (ret && CheckVirusScanned(hwndDlg, dat, ret))
+ ShellExecute(nullptr, nullptr, files[ret - 10], nullptr, nullptr, SW_SHOW);
+ }
+ break;
+
+ case M_FILEEXISTSDLGREPLY:
+ EnableWindow(hwndDlg, TRUE);
+ {
+ PROTOFILERESUME *pfr = (PROTOFILERESUME *)lParam;
+ wchar_t *szOriginalFilename = (wchar_t *)wParam;
+ char *szProto = Proto_GetBaseAccountName(dat->hContact);
+
+ switch (pfr->action) {
+ case FILERESUME_CANCEL:
+ if (dat->fs) ProtoChainSend(dat->hContact, PSS_FILECANCEL, (WPARAM)dat->fs, 0);
+ dat->fs = nullptr;
+ 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;
+ {
+ wchar_t *pszExtension, *pszFilename;
+ if ((pszFilename = wcsrchr(szOriginalFilename, '\\')) == nullptr) pszFilename = szOriginalFilename;
+ if ((pszExtension = wcsrchr(pszFilename + 1, '.')) == nullptr) pszExtension = pszFilename + mir_wstrlen(pszFilename);
+ if (pfr->szFilename) mir_free((wchar_t *)pfr->szFilename);
+ size_t size = (pszExtension - szOriginalFilename) + 21 + mir_wstrlen(pszExtension);
+ pfr->szFilename = (wchar_t *)mir_alloc(sizeof(wchar_t) * size);
+ for (int i = 1;; i++) {
+ mir_snwprintf((wchar_t *)pfr->szFilename, size, L"%.*s (%u)%s", pszExtension - szOriginalFilename, szOriginalFilename, i, pszExtension);
+ if (_waccess(pfr->szFilename, 0) != 0)
+ break;
+ }
+ }
+ break;
+ }
+ mir_free(szOriginalFilename);
+ CallProtoService(szProto, PS_FILERESUME, (WPARAM)dat->fs, (LPARAM)pfr);
+ delete pfr;
+ }
+ break;
+
+ case HM_RECVEVENT:
+ {
+ ACKDATA *ack = (ACKDATA *)lParam;
+ if (ack->hProcess != dat->fs) break;
+ if (ack->type != ACKTYPE_FILE) break;
+ if (ack->hContact != dat->hContact) break;
+
+ if (dat->waitingForAcceptance) {
+ SetTimer(hwndDlg, 1, 1000, nullptr);
+ dat->waitingForAcceptance = 0;
+ }
+
+ switch (ack->result) {
+ case ACKRESULT_SENTREQUEST: SetFtStatus(hwndDlg, LPGENW("Decision sent"), FTS_TEXT); break;
+ case ACKRESULT_CONNECTING: SetFtStatus(hwndDlg, LPGENW("Connecting..."), FTS_TEXT); break;
+ case ACKRESULT_CONNECTPROXY: SetFtStatus(hwndDlg, LPGENW("Connecting to proxy..."), FTS_TEXT); break;
+ case ACKRESULT_CONNECTED: SetFtStatus(hwndDlg, LPGENW("Connected"), FTS_TEXT); break;
+ case ACKRESULT_LISTENING: SetFtStatus(hwndDlg, LPGENW("Waiting for connection..."), FTS_TEXT); break;
+ case ACKRESULT_INITIALISING: SetFtStatus(hwndDlg, LPGENW("Initializing..."), FTS_TEXT); break;
+ case ACKRESULT_NEXTFILE:
+ SetFtStatus(hwndDlg, LPGENW("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 && g_plugin.getByte("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 = (virusscanthreadstartinfo *)mir_alloc(sizeof(virusscanthreadstartinfo));
+ vstsi->hwndReply = hwndDlg;
+ vstsi->szFile = mir_wstrdup(dat->files[dat->transferStatus.currentFileNumber]);
+ vstsi->returnCode = dat->transferStatus.currentFileNumber;
+ mir_forkThread<virusscanthreadstartinfo>(RunVirusScannerThread, vstsi);
+ }
+ }
+ break;
+
+ case ACKRESULT_FILERESUME:
+ UpdateProtoFileTransferStatus(&dat->transferStatus, (PROTOFILETRANSFERSTATUS *)ack->lParam);
+ {
+ PROTOFILETRANSFERSTATUS *fts = &dat->transferStatus;
+ SetFilenameControls(hwndDlg, dat, fts);
+ if (_waccess(fts->szCurrentFile.w, 0))
+ break;
+
+ SetFtStatus(hwndDlg, LPGENW("File already exists"), FTS_TEXT);
+ if (dat->resumeBehaviour == FILERESUME_ASK) {
+ TDlgProcFileExistsParam param = { hwndDlg, fts };
+ ShowWindow(hwndDlg, SW_SHOWNORMAL);
+ CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_FILEEXISTS), hwndDlg, DlgProcFileExists, (LPARAM)&param);
+ EnableWindow(hwndDlg, FALSE);
+ }
+ else {
+ PROTOFILERESUME *pfr = new PROTOFILERESUME();
+ pfr->action = dat->resumeBehaviour;
+ pfr->szFilename = nullptr;
+ PostMessage(hwndDlg, M_FILEEXISTSDLGREPLY, (WPARAM)mir_wstrdup(fts->szCurrentFile.w), (LPARAM)pfr);
+ }
+ }
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, 1);
+ return TRUE;
+
+ case ACKRESULT_DATA:
+ {
+ PROTOFILETRANSFERSTATUS *fts = (PROTOFILETRANSFERSTATUS *)ack->lParam;
+ wchar_t str[64], str2[64], szSizeDone[32], szSizeTotal[32];//, *contactName;
+
+ if (dat->fileVirusScanned == nullptr)
+ 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 == nullptr)
+ dat->files = (wchar_t **)mir_calloc((fts->totalFiles + 1) * sizeof(wchar_t *));
+ if (fts->currentFileNumber < fts->totalFiles && dat->files[fts->currentFileNumber] == nullptr)
+ dat->files[fts->currentFileNumber] = PFTS_StringToTchar(fts->flags, fts->szCurrentFile.w);
+ }
+
+ /* 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 ((GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_ALLFILESPROGRESS), GWL_STYLE) & WS_VISIBLE) == 0) {
+ SetFtStatus(hwndDlg, (fts->flags & PFTS_SENDING) ? LPGENW("Sending...") : LPGENW("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 ? (100ll * fts->totalProgress / fts->totalBytes) : 0;
+ if (lastPos != nextPos || firstTime) {
+ SendDlgItemMessage(hwndDlg, IDC_ALLFILESPROGRESS, PBM_SETPOS, nextPos, 0);
+ mir_snwprintf(str, L"%u%%", nextPos);
+ SetDlgItemText(hwndDlg, IDC_ALLPRECENTS, str);
+ }
+
+ int units;
+ GetSensiblyFormattedSize(fts->totalBytes, szSizeTotal, _countof(szSizeTotal), 0, 1, &units);
+ GetSensiblyFormattedSize(fts->totalProgress, szSizeDone, _countof(szSizeDone), units, 0, NULL);
+ mir_snwprintf(str, L"%s/%s", szSizeDone, szSizeTotal);
+ str2[0] = 0;
+ GetDlgItemText(hwndDlg, IDC_ALLTRANSFERRED, str2, _countof(str2));
+ if (mir_wstrcmp(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 = nullptr;
+
+ if (ack->result == ACKRESULT_DENIED) {
+ dat->fs = nullptr; /* protocol will free structure */
+ Skin_PlaySound("FileDenied");
+ SetFtStatus(hwndDlg, LPGENW("File transfer denied"), FTS_TEXT);
+ }
+ else if (ack->result == ACKRESULT_FAILED) {
+ dat->fs = nullptr; /* protocol will free structure */
+ Skin_PlaySound("FileFailed");
+ SetFtStatus(hwndDlg, LPGENW("File transfer failed"), FTS_TEXT);
+ }
+ else {
+ Skin_PlaySound("FileDone");
+ if (dat->send) {
+ dat->fs = nullptr; /* protocol will free structure */
+ SetFtStatus(hwndDlg, LPGENW("Transfer completed."), FTS_TEXT);
+
+ DB::EventInfo dbei;
+ dbei.szModule = Proto_GetBaseAccountName(dat->hContact);
+ dbei.eventType = EVENTTYPE_FILE;
+ dbei.flags = DBEF_SENT;
+ dbei.timestamp = time(0);
+ dbei.flags |= DBEF_UTF;
+
+ DB::FILE_BLOB blob(dat->szFilenames, dat->szMsg);
+ blob.write(dbei);
+ db_event_add(dat->hContact, &dbei);
+
+ dat->files = nullptr; //protocol library frees this
+ }
+ else {
+ SetFtStatus(hwndDlg,
+ (dat->transferStatus.totalFiles == 1) ?
+ LPGENW("Transfer completed, open file.") :
+ LPGENW("Transfer completed, open folder."),
+ FTS_OPEN);
+
+ int useScanner = g_plugin.getByte("UseScanner", VIRUSSCAN_DISABLE);
+ if (useScanner != VIRUSSCAN_DISABLE) {
+ auto *vstsi = (virusscanthreadstartinfo *)mir_alloc(sizeof(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 = nullptr;
+ }
+ else vstsi->szFile = mir_wstrdup(dat->files[dat->transferStatus.currentFileNumber]);
+ }
+ else {
+ vstsi->szFile = mir_wstrdup(dat->transferStatus.szWorkingDir.w);
+ vstsi->returnCode = -1;
+ }
+ SetFtStatus(hwndDlg, LPGENW("Scanning for viruses..."), FTS_TEXT);
+ if (vstsi)
+ mir_forkThread<virusscanthreadstartinfo>(RunVirusScannerThread, vstsi);
+ }
+ else dat->fs = nullptr; /* protocol will free structure */
+
+ dat->transferStatus.currentFileNumber = dat->transferStatus.totalFiles;
+ }
+ }
+
+ PostMessage(GetParent(hwndDlg), WM_FT_COMPLETED, ack->result, (LPARAM)hwndDlg);
+ break;
+ }
+ }
+ break;
+
+ case M_VIRUSSCANDONE:
+ {
+ int done = 1;
+ if ((int)wParam == -1) {
+ for (int i = 0; i < dat->transferStatus.totalFiles; i++)
+ dat->fileVirusScanned[i] = 1;
+ }
+ else {
+ dat->fileVirusScanned[wParam] = 1;
+ for (int i = 0; i < dat->transferStatus.totalFiles; i++)
+ if (!dat->fileVirusScanned[i]) {
+ done = 0;
+ break;
+ }
+ }
+ if (done) {
+ dat->fs = nullptr; /* protocol will free structure */
+ SetFtStatus(hwndDlg, LPGENW("Transfer and virus scan complete"), FTS_TEXT);
+ }
+ }
+ break;
+
+ case WM_SIZE:
+ Utils_ResizeDialog(hwndDlg, g_plugin.getInst(), MAKEINTRESOURCEA(IDD_FILETRANSFERINFO), FileTransferDlgResizer, LPARAM(dat));
+
+ 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);
+
+ delete dat;
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
+ break;
+ }
+ return FALSE;
+}
+
+FileDlgData::~FileDlgData()
+{
+ if (fs)
+ ProtoChainSend(hContact, PSS_FILECANCEL, (WPARAM)fs, 0);
+
+ UnhookEvent(hPreshutdownEvent);
+ UnhookEvent(hNotifyEvent);
+
+ FreeProtoFileTransferStatus(&transferStatus);
+ FreeFilesMatrix(&files);
+
+ mir_free(fileVirusScanned);
+ if (hIcon)
+ DestroyIcon(hIcon);
+ if (hIconFolder)
+ DestroyIcon(hIconFolder);
+}
diff --git a/src/core/stdfile/src/ftmanager.cpp b/src/mir_app/src/ftmanager.cpp
index 10f4215c63..04221b7956 100644
--- a/src/core/stdfile/src/ftmanager.cpp
+++ b/src/mir_app/src/ftmanager.cpp
@@ -1,514 +1,516 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda 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 "stdafx.h"
-#include "file.h"
-
-static HWND hwndFtMgr = nullptr;
-
-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
-{
- TLayoutWindowInfo(HWND _hwnd) :
- hwnd(_hwnd)
- {
- ::GetWindowRect(_hwnd, &rc);
- }
-
- HWND hwnd;
- RECT rc;
-};
-
-struct TFtPageData
-{
- TFtPageData() :
- arWindows(1)
- {}
-
- OBJLIST<TLayoutWindowInfo> arWindows;
- int runningCount = 0;
- int height = 0, dataHeight = 0, scrollPos = 0;
-};
-
-static void LayoutTransfers(HWND hwnd, TFtPageData *dat)
-{
- int top = 0;
- RECT rc;
- GetClientRect(hwnd, &rc);
-
- dat->scrollPos = GetScrollPos(hwnd, SB_VERT);
- dat->height = rc.bottom - rc.top;
-
- if (dat->arWindows.getCount()) {
- HDWP hdwp = BeginDeferWindowPos(dat->arWindows.getCount());
- top -= dat->scrollPos;
- for (auto &it : dat->arWindows) {
- int height = it->rc.bottom - it->rc.top;
- if (nullptr != it->hwnd) /* Wine fix. */
- hdwp = DeferWindowPos(hdwp, it->hwnd, nullptr, 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)
-{
- TFtPageData *dat = (TFtPageData *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
-
- switch (msg) {
- case WM_INITDIALOG:
- {
- // Force scrollbar visibility
- SCROLLINFO si = {};
- si.cbSize = sizeof(si);
- si.fMask = SIF_DISABLENOSCROLL;
- SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
-
- dat = new TFtPageData();
- SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)dat);
- }
- break;
-
- case WM_FT_ADD:
- {
- TLayoutWindowInfo *wnd = new TLayoutWindowInfo((HWND)lParam);
- if (g_plugin.bReverseOrder)
- dat->arWindows.insert(wnd, 0);
- else
- dat->arWindows.insert(wnd);
- LayoutTransfers(hwnd, dat);
- dat->runningCount++;
- PostMessage(GetParent(hwnd), WM_TIMER, 1, NULL);
- }
- break;
-
- case WM_FT_RESIZE:
- for (auto &it : dat->arWindows)
- if (it->hwnd == (HWND)lParam) {
- GetWindowRect(it->hwnd, &it->rc);
- break;
- }
- LayoutTransfers(hwnd, dat);
- break;
-
- case WM_FT_REMOVE:
- for (auto &it : dat->arWindows)
- if (it->hwnd == (HWND)lParam) {
- dat->arWindows.removeItem(&it);
- break;
- }
- LayoutTransfers(hwnd, dat);
- break;
-
- case WM_FT_COMPLETED:
- //wParam: { ACKRESULT_SUCCESS | ACKRESULT_FAILED | ACKRESULT_DENIED }
- dat->runningCount--;
- {
- bool bFound = false;
- for (auto &it : dat->arWindows)
- // no error when canceling (WM_FT_REMOVE is send first, check if hwnd is still registered)
- if (it->hwnd == (HWND)lParam) {
- bFound = true;
- SendMessage(GetParent(hwnd), WM_TIMER, 1, (LPARAM)wParam);
- break;
- }
-
- if (!bFound)
- PostMessage(GetParent(hwnd), WM_TIMER, 1, NULL);
- }
-
- if(dat->runningCount == 0 && wParam == ACKRESULT_SUCCESS && g_plugin.bAutoClose)
- ShowWindow(hwndFtMgr, SW_HIDE);
- break;
-
- case WM_FT_CLEANUP:
- for (auto &it : dat->arWindows)
- SendMessage(it->hwnd, WM_FT_CLEANUP, wParam, lParam);
- break;
-
- case WM_SIZE:
- LayoutTransfers(hwnd, dat);
- break;
-
- case WM_MOUSEWHEEL:
- if (int zDelta = GET_WHEEL_DELTA_WPARAM(wParam)) {
- int nScrollLines = 0;
- SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &nScrollLines, 0);
- for (int 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, nullptr, nullptr);
- SetScrollPos(hwnd, SB_VERT, pos, TRUE);
- dat->scrollPos = pos;
- }
- }
- break;
-
- case M_PRESHUTDOWN:
- for (auto &it : dat->arWindows)
- PostMessage(it->hwnd, WM_COMMAND, MAKEWPARAM(IDCANCEL, BN_CLICKED), 0);
- break;
-
- case M_CALCPROGRESS:
- {
- TFtProgressData *prg = (TFtProgressData *)wParam;
- for (auto &it : dat->arWindows) {
- FileDlgData *trdat = (FileDlgData *)GetWindowLongPtr(it->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++;
- }
- }
- break;
-
- case WM_DESTROY:
- delete dat;
- break;
- }
-
- return FALSE;
-}
-
-static INT_PTR CALLBACK FtMgrDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- auto *dat = (TFtMgrData *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
- HWND hwndTab = GetDlgItem(hwnd, IDC_TABS);
-
- switch (msg) {
- case WM_INITDIALOG:
- {
- TranslateDialogDefault(hwnd);
- Window_SetSkinIcon_IcoLib(hwnd, SKINICON_EVENT_FILE);
-
- dat = (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(g_plugin.getInst(), MAKEINTRESOURCE(IDD_FTPAGE), hwnd, FtMgrPageDlgProc);
- dat->hwndOutgoing = CreateDialog(g_plugin.getInst(), MAKEINTRESOURCE(IDD_FTPAGE), hwnd, FtMgrPageDlgProc);
- ShowWindow(dat->hwndIncoming, SW_SHOW);
-
- TCITEM tci = {};
- 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, MODULENAME, "FtMgrDlg_", RWPF_NOACTIVATE);
- // Fall through to setup initial placement
- __fallthrough;
- }
- case WM_SIZE:
- {
- RECT rc, rcButton;
- GetWindowRect(GetDlgItem(hwnd, IDCANCEL), &rcButton);
- OffsetRect(&rcButton, -rcButton.left, -rcButton.top);
-
- GetClientRect(hwnd, &rc);
- InflateRect(&rc, -6, -6);
-
- HDWP 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), nullptr, rc.right-rcButton.right, rc.bottom-rcButton.bottom, 0, 0, SWP_NOZORDER|SWP_NOSIZE);
-
- rc.bottom -= rcButton.bottom + 5;
-
- if (nullptr != hwndTab) /* Wine fix. */
- hdwp = DeferWindowPos(hdwp, hwndTab, nullptr, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, SWP_NOZORDER);
-
- EndDeferWindowPos(hdwp);
-
- GetWindowRect(hwndTab, &rc);
- MapWindowPoints(nullptr, hwnd, (LPPOINT)&rc, 2);
- TabCtrl_AdjustRect(hwndTab, FALSE, &rc);
- InflateRect(&rc, -5, -5);
-
- hdwp = BeginDeferWindowPos(2);
-
- if (nullptr != dat->hwndIncoming) /* Wine fix. */
- hdwp = DeferWindowPos(hdwp, dat->hwndIncoming, HWND_TOP, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, 0);
- if (nullptr != dat->hwndOutgoing) /* Wine fix. */
- 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:
- if (TabCtrl_GetCurSel(hwndTab) != (int)wParam) {
- TCITEM tci = {};
- 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:
- TCITEM tci = {};
- switch (((LPNMHDR)lParam)->code) {
- case TCN_SELCHANGING:
- tci.mask = TCIF_PARAM;
- TabCtrl_GetItem(hwndTab, TabCtrl_GetCurSel(hwndTab), &tci);
- ShowWindow((HWND)tci.lParam, SW_HIDE);
- break;
-
- case TCN_SELCHANGE:
- 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 (g_plugin.bAutoClear) {
- 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, MODULENAME, "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, nullptr);
- 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 bJustCreated = (hwndFtMgr == nullptr);
- if (bJustCreated)
- hwndFtMgr = CreateDialog(g_plugin.getInst(), MAKEINTRESOURCE(IDD_FTMGR), NULL, FtMgrDlgProc);
-
- if (bFromMenu) { /* lqbe */
- ShowWindow(hwndFtMgr, SW_RESTORE);
- ShowWindow(hwndFtMgr, SW_SHOW);
- SetForegroundWindow(hwndFtMgr);
- return hwndFtMgr;
- }
- if (g_plugin.bAutoMin && bJustCreated) { /* lqbe */
- ShowWindow(hwndFtMgr, SW_HIDE);
- ShowWindow(hwndFtMgr, SW_MINIMIZE);
- return hwndFtMgr;
- }
- if (bForceActivate) { /* lqbe */
- ShowWindow(hwndFtMgr, SW_RESTORE);
- ShowWindow(hwndFtMgr, SW_SHOWNOACTIVATE);
- SetForegroundWindow(hwndFtMgr);
- return hwndFtMgr;
- }
- if (!bJustCreated && IsWindowVisible(hwndFtMgr))
- return hwndFtMgr;
-
- ShowWindow(hwndFtMgr, g_plugin.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);
-}
-
-void FtMgr_AddTransfer(FileDlgData *fdd)
-{
- bool bForceActivate = fdd->send || !g_plugin.bAutoAccept;
- TFtMgrData *dat = (TFtMgrData *)GetWindowLongPtr(FtMgr_Show(bForceActivate, false), GWLP_USERDATA);
- if (dat == nullptr)
- return;
-
- HWND hwndBox = fdd->send ? dat->hwndOutgoing : dat->hwndIncoming;
- HWND hwndFt = CreateDialogParam(g_plugin.getInst(), 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);
- fdd->hwndTransfer = hwndFt;
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda 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 "stdafx.h"
+#include "file.h"
+
+extern ITaskbarList3 *pTaskbarInterface;
+
+static HWND hwndFtMgr = nullptr;
+
+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
+{
+ TLayoutWindowInfo(HWND _hwnd) :
+ hwnd(_hwnd)
+ {
+ ::GetWindowRect(_hwnd, &rc);
+ }
+
+ HWND hwnd;
+ RECT rc;
+};
+
+struct TFtPageData
+{
+ TFtPageData() :
+ arWindows(1)
+ {}
+
+ OBJLIST<TLayoutWindowInfo> arWindows;
+ int runningCount = 0;
+ int height = 0, dataHeight = 0, scrollPos = 0;
+};
+
+static void LayoutTransfers(HWND hwnd, TFtPageData *dat)
+{
+ int top = 0;
+ RECT rc;
+ GetClientRect(hwnd, &rc);
+
+ dat->scrollPos = GetScrollPos(hwnd, SB_VERT);
+ dat->height = rc.bottom - rc.top;
+
+ if (dat->arWindows.getCount()) {
+ HDWP hdwp = BeginDeferWindowPos(dat->arWindows.getCount());
+ top -= dat->scrollPos;
+ for (auto &it : dat->arWindows) {
+ int height = it->rc.bottom - it->rc.top;
+ if (nullptr != it->hwnd) /* Wine fix. */
+ hdwp = DeferWindowPos(hdwp, it->hwnd, nullptr, 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)
+{
+ TFtPageData *dat = (TFtPageData *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ // Force scrollbar visibility
+ SCROLLINFO si = {};
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_DISABLENOSCROLL;
+ SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
+
+ dat = new TFtPageData();
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)dat);
+ }
+ break;
+
+ case WM_FT_ADD:
+ {
+ TLayoutWindowInfo *wnd = new TLayoutWindowInfo((HWND)lParam);
+ if (File::bReverseOrder)
+ dat->arWindows.insert(wnd, 0);
+ else
+ dat->arWindows.insert(wnd);
+ LayoutTransfers(hwnd, dat);
+ dat->runningCount++;
+ PostMessage(GetParent(hwnd), WM_TIMER, 1, NULL);
+ }
+ break;
+
+ case WM_FT_RESIZE:
+ for (auto &it : dat->arWindows)
+ if (it->hwnd == (HWND)lParam) {
+ GetWindowRect(it->hwnd, &it->rc);
+ break;
+ }
+ LayoutTransfers(hwnd, dat);
+ break;
+
+ case WM_FT_REMOVE:
+ for (auto &it : dat->arWindows)
+ if (it->hwnd == (HWND)lParam) {
+ dat->arWindows.removeItem(&it);
+ break;
+ }
+ LayoutTransfers(hwnd, dat);
+ break;
+
+ case WM_FT_COMPLETED:
+ //wParam: { ACKRESULT_SUCCESS | ACKRESULT_FAILED | ACKRESULT_DENIED }
+ dat->runningCount--;
+ {
+ bool bFound = false;
+ for (auto &it : dat->arWindows)
+ // no error when canceling (WM_FT_REMOVE is send first, check if hwnd is still registered)
+ if (it->hwnd == (HWND)lParam) {
+ bFound = true;
+ SendMessage(GetParent(hwnd), WM_TIMER, 1, (LPARAM)wParam);
+ break;
+ }
+
+ if (!bFound)
+ PostMessage(GetParent(hwnd), WM_TIMER, 1, NULL);
+ }
+
+ if(dat->runningCount == 0 && wParam == ACKRESULT_SUCCESS && File::bAutoClose)
+ ShowWindow(hwndFtMgr, SW_HIDE);
+ break;
+
+ case WM_FT_CLEANUP:
+ for (auto &it : dat->arWindows)
+ SendMessage(it->hwnd, WM_FT_CLEANUP, wParam, lParam);
+ break;
+
+ case WM_SIZE:
+ LayoutTransfers(hwnd, dat);
+ break;
+
+ case WM_MOUSEWHEEL:
+ if (int zDelta = GET_WHEEL_DELTA_WPARAM(wParam)) {
+ int nScrollLines = 0;
+ SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &nScrollLines, 0);
+ for (int 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, nullptr, nullptr);
+ SetScrollPos(hwnd, SB_VERT, pos, TRUE);
+ dat->scrollPos = pos;
+ }
+ }
+ break;
+
+ case M_PRESHUTDOWN:
+ for (auto &it : dat->arWindows)
+ PostMessage(it->hwnd, WM_COMMAND, MAKEWPARAM(IDCANCEL, BN_CLICKED), 0);
+ break;
+
+ case M_CALCPROGRESS:
+ {
+ TFtProgressData *prg = (TFtProgressData *)wParam;
+ for (auto &it : dat->arWindows) {
+ FileDlgData *trdat = (FileDlgData *)GetWindowLongPtr(it->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++;
+ }
+ }
+ break;
+
+ case WM_DESTROY:
+ delete dat;
+ break;
+ }
+
+ return FALSE;
+}
+
+static INT_PTR CALLBACK FtMgrDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ auto *dat = (TFtMgrData *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ HWND hwndTab = GetDlgItem(hwnd, IDC_TABS);
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwnd);
+ Window_SetSkinIcon_IcoLib(hwnd, SKINICON_EVENT_FILE);
+
+ dat = (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(g_plugin.getInst(), MAKEINTRESOURCE(IDD_FTPAGE), hwnd, FtMgrPageDlgProc);
+ dat->hwndOutgoing = CreateDialog(g_plugin.getInst(), MAKEINTRESOURCE(IDD_FTPAGE), hwnd, FtMgrPageDlgProc);
+ ShowWindow(dat->hwndIncoming, SW_SHOW);
+
+ TCITEM tci = {};
+ 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, SRFILEMODULE, "FtMgrDlg_", RWPF_NOACTIVATE);
+ // Fall through to setup initial placement
+ __fallthrough;
+ }
+ case WM_SIZE:
+ {
+ RECT rc, rcButton;
+ GetWindowRect(GetDlgItem(hwnd, IDCANCEL), &rcButton);
+ OffsetRect(&rcButton, -rcButton.left, -rcButton.top);
+
+ GetClientRect(hwnd, &rc);
+ InflateRect(&rc, -6, -6);
+
+ HDWP 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), nullptr, rc.right-rcButton.right, rc.bottom-rcButton.bottom, 0, 0, SWP_NOZORDER|SWP_NOSIZE);
+
+ rc.bottom -= rcButton.bottom + 5;
+
+ if (nullptr != hwndTab) /* Wine fix. */
+ hdwp = DeferWindowPos(hdwp, hwndTab, nullptr, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, SWP_NOZORDER);
+
+ EndDeferWindowPos(hdwp);
+
+ GetWindowRect(hwndTab, &rc);
+ MapWindowPoints(nullptr, hwnd, (LPPOINT)&rc, 2);
+ TabCtrl_AdjustRect(hwndTab, FALSE, &rc);
+ InflateRect(&rc, -5, -5);
+
+ hdwp = BeginDeferWindowPos(2);
+
+ if (nullptr != dat->hwndIncoming) /* Wine fix. */
+ hdwp = DeferWindowPos(hdwp, dat->hwndIncoming, HWND_TOP, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, 0);
+ if (nullptr != dat->hwndOutgoing) /* Wine fix. */
+ 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:
+ if (TabCtrl_GetCurSel(hwndTab) != (int)wParam) {
+ TCITEM tci = {};
+ 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:
+ TCITEM tci = {};
+ switch (((LPNMHDR)lParam)->code) {
+ case TCN_SELCHANGING:
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(hwndTab, TabCtrl_GetCurSel(hwndTab), &tci);
+ ShowWindow((HWND)tci.lParam, SW_HIDE);
+ break;
+
+ case TCN_SELCHANGE:
+ 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 (File::bAutoClear) {
+ 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, SRFILEMODULE, "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, nullptr);
+ 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 bJustCreated = (hwndFtMgr == nullptr);
+ if (bJustCreated)
+ hwndFtMgr = CreateDialog(g_plugin.getInst(), MAKEINTRESOURCE(IDD_FTMGR), NULL, FtMgrDlgProc);
+
+ if (bFromMenu) { /* lqbe */
+ ShowWindow(hwndFtMgr, SW_RESTORE);
+ ShowWindow(hwndFtMgr, SW_SHOW);
+ SetForegroundWindow(hwndFtMgr);
+ return hwndFtMgr;
+ }
+ if (File::bAutoMin && bJustCreated) { /* lqbe */
+ ShowWindow(hwndFtMgr, SW_HIDE);
+ ShowWindow(hwndFtMgr, SW_MINIMIZE);
+ return hwndFtMgr;
+ }
+ if (bForceActivate) { /* lqbe */
+ ShowWindow(hwndFtMgr, SW_RESTORE);
+ ShowWindow(hwndFtMgr, SW_SHOWNOACTIVATE);
+ SetForegroundWindow(hwndFtMgr);
+ return hwndFtMgr;
+ }
+ if (!bJustCreated && IsWindowVisible(hwndFtMgr))
+ return hwndFtMgr;
+
+ ShowWindow(hwndFtMgr, File::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);
+}
+
+void FtMgr_AddTransfer(FileDlgData *fdd)
+{
+ bool bForceActivate = fdd->send || !File::bAutoAccept;
+ TFtMgrData *dat = (TFtMgrData *)GetWindowLongPtr(FtMgr_Show(bForceActivate, false), GWLP_USERDATA);
+ if (dat == nullptr)
+ return;
+
+ HWND hwndBox = fdd->send ? dat->hwndOutgoing : dat->hwndIncoming;
+ HWND hwndFt = CreateDialogParam(g_plugin.getInst(), 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);
+ fdd->hwndTransfer = hwndFt;
+}
diff --git a/src/mir_app/src/modules.cpp b/src/mir_app/src/modules.cpp
index 0db467d25f..d1bbdedf90 100644
--- a/src/mir_app/src/modules.cpp
+++ b/src/mir_app/src/modules.cpp
@@ -32,6 +32,7 @@ INT_PTR CheckRestart(); // core: IDD_WAITRESTART
int LoadSystemModule(void); // core: m_system.h services
int LoadNewPluginsModuleInfos(void); // core: preloading plugins
int LoadSendRecvAuthModule(void); // core: auth dialogs
+int LoadSendRecvFileModule(void); // code: file send/recv
int LoadNewPluginsModule(void); // core: N.O. plugins
int LoadNetlibModule(void); // core: network
int LoadProtocolsModule(void); // core: protocol manager
@@ -127,6 +128,7 @@ int LoadDefaultModules(void)
if (LoadChatModule()) return 1;
if (LoadSendRecvAuthModule()) return 1;
if (LoadDescButtonModule()) return 1;
+ if (LoadSendRecvFileModule()) return 1;
if (LoadOptionsModule()) return 1;
if (LoadProtocolsModule()) return 1;
diff --git a/src/mir_app/src/newplugins.cpp b/src/mir_app/src/newplugins.cpp
index 01b7de292c..372ea90d9b 100644
--- a/src/mir_app/src/newplugins.cpp
+++ b/src/mir_app/src/newplugins.cpp
@@ -114,6 +114,7 @@ static const MUUID pluginBannedList[] =
{ 0x8d0a046d, 0x8ea9, 0x4c55, { 0xb5, 0x68, 0x38, 0xda, 0x52, 0x05, 0x64, 0xfd } }, // stdauth
{ 0x9d6c3213, 0x02b4, 0x4fe1, { 0x92, 0xe6, 0x52, 0x6d, 0xe1, 0x4f, 0x8d, 0x65 } }, // stdchat
{ 0x1e64fd80, 0x299e, 0x48a0, { 0x94, 0x41, 0xde, 0x28, 0x68, 0x56, 0x3b, 0x6f } }, // stdhelp
+ { 0x39698dce, 0x7ed4, 0x4334, { 0xac, 0x4c, 0xba, 0x8b, 0x37, 0xa8, 0x6f, 0x13 } }, // stdfile
{ 0x53ac190b, 0xe223, 0x4341, { 0x82, 0x5f, 0x70, 0x9d, 0x85, 0x20, 0x21, 0x5b } }, // stdidle
{ 0x312C4F84, 0x75BE, 0x4404, { 0xBC, 0xB1, 0xC1, 0x03, 0xDB, 0xE5, 0xA3, 0xB8 } }, // stdssl
{ 0x621f886b, 0xa7f6, 0x457f, { 0x9d, 0x62, 0x8e, 0xe8, 0x4c, 0x27, 0x59, 0x93 } }, // modernopt
@@ -151,12 +152,11 @@ static MuuidReplacement pluginDefault[] =
{ MIID_SRMM, L"stdmsg", nullptr }, // 1
{ MIID_UIUSERINFO, L"stduserinfo", nullptr }, // 2
{ MIID_SREMAIL, L"stdemail", nullptr }, // 3
- { MIID_SRFILE, L"stdfile", nullptr }, // 4
- { MIID_UIHISTORY, L"stduihist", nullptr }, // 5
- { MIID_AUTOAWAY, L"stdautoaway", nullptr }, // 6
- { MIID_USERONLINE, L"stduseronline", nullptr }, // 7
- { MIID_SRAWAY, L"stdaway", nullptr }, // 8
- { MIID_POPUP, L"stdpopup", nullptr }, // 9
+ { MIID_UIHISTORY, L"stduihist", nullptr }, // 4
+ { MIID_AUTOAWAY, L"stdautoaway", nullptr }, // 5
+ { MIID_USERONLINE, L"stduseronline", nullptr }, // 6
+ { MIID_SRAWAY, L"stdaway", nullptr }, // 7
+ { MIID_POPUP, L"stdpopup", nullptr }, // 8
};
int getDefaultPluginIdx(const MUUID &muuid)