From f5c584f3073bbe65bbf4794e555aabd651476612 Mon Sep 17 00:00:00 2001 From: Rozhuk Ivan Date: Thu, 27 Nov 2014 01:26:26 +0000 Subject: StdFile: code cleanup git-svn-id: http://svn.miranda-ng.org/main/trunk@11116 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- src/core/stdfile/filerecvdlg.cpp | 3 +- src/core/stdfile/filesenddlg.cpp | 5 +- src/core/stdfile/filexferdlg.cpp | 1527 +++++++++++++++++++------------------- 3 files changed, 770 insertions(+), 765 deletions(-) (limited to 'src/core') diff --git a/src/core/stdfile/filerecvdlg.cpp b/src/core/stdfile/filerecvdlg.cpp index 5bed7dbd7b..68e84dcf73 100644 --- a/src/core/stdfile/filerecvdlg.cpp +++ b/src/core/stdfile/filerecvdlg.cpp @@ -418,7 +418,8 @@ INT_PTR CALLBACK DlgProcRecvFile(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM l Button_FreeIcon_IcoLib(hwndDlg, IDC_HISTORY); Button_FreeIcon_IcoLib(hwndDlg, IDC_USERMENU); - if (dat) FreeFileDlgData(dat); + FreeFileDlgData(dat); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0); break; } return FALSE; diff --git a/src/core/stdfile/filesenddlg.cpp b/src/core/stdfile/filesenddlg.cpp index 2772e9503c..b6fdfe2ec4 100644 --- a/src/core/stdfile/filesenddlg.cpp +++ b/src/core/stdfile/filesenddlg.cpp @@ -363,9 +363,8 @@ INT_PTR CALLBACK DlgProcSendFile(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM l Button_FreeIcon_IcoLib(hwndDlg, IDC_HISTORY); Button_FreeIcon_IcoLib(hwndDlg, IDC_USERMENU); - if (dat) - FreeFileDlgData(dat); - + FreeFileDlgData(dat); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0); return TRUE; } return FALSE; diff --git a/src/core/stdfile/filexferdlg.cpp b/src/core/stdfile/filexferdlg.cpp index c3efcc6e54..18c8e3b5a4 100644 --- a/src/core/stdfile/filexferdlg.cpp +++ b/src/core/stdfile/filexferdlg.cpp @@ -1,761 +1,766 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (c) 2012-14 Miranda NG project (http://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 "commonheaders.h" -#include -#include "file.h" - -#define HM_RECVEVENT (WM_USER+10) - -static int CheckVirusScanned(HWND hwnd, FileDlgData *dat, int i) -{ - if (dat->send) return 1; - if (dat->fileVirusScanned == NULL) return 0; - if (dat->fileVirusScanned[i]) return 1; - if (db_get_b(NULL, "SRFile", "WarnBeforeOpening", 1) == 0) return 1; - return IDYES == MessageBox(hwnd, TranslateT("This file has not yet been scanned for viruses. Are you certain you want to open it?"), TranslateT("File received"), MB_YESNO|MB_DEFBUTTON2); -} - -#define M_VIRUSSCANDONE (WM_USER+100) -struct virusscanthreadstartinfo { - TCHAR *szFile; - int returnCode; - HWND hwndReply; -}; - -TCHAR* PFTS_StringToTchar(int flags, const PROTOCHAR* s) -{ - if (flags & PFTS_UTF) - return Utf8DecodeW((char*)s); - if (flags & PFTS_UNICODE) - return mir_tstrdup(s); - return mir_a2t((char*)s); -} - -int PFTS_CompareWithTchar(PROTOFILETRANSFERSTATUS *ft, const PROTOCHAR *s, TCHAR *r) -{ - if (ft->flags & PFTS_UTF) { - TCHAR *ts = Utf8DecodeW((char*)s); - int res = _tcscmp(ts, r); - mir_free(ts); - return res; - } - if (ft->flags & PFTS_UNICODE) - return _tcscmp(s, r); - - TCHAR *ts = mir_a2t((char*)s); - int res = _tcscmp(ts, r); - mir_free(ts); - return res; -} - -static void SetOpenFileButtonStyle(HWND hwndButton, int enabled) -{ - EnableWindow(hwndButton, enabled); -} - -void FillSendData(FileDlgData *dat, DBEVENTINFO& dbei) -{ - dbei.cbSize = sizeof(dbei); - dbei.szModule = GetContactProto(dat->hContact); - dbei.eventType = EVENTTYPE_FILE; - dbei.flags = DBEF_SENT; - dbei.timestamp = time(NULL); - char *szFileNames = Utf8EncodeT(dat->szFilenames), *szMsg = Utf8EncodeT(dat->szMsg); - dbei.flags |= DBEF_UTF; - - dbei.cbBlob = sizeof(DWORD) + lstrlenA(szFileNames) + lstrlenA(szMsg) + 2; - dbei.pBlob = (PBYTE)mir_alloc(dbei.cbBlob); - *(PDWORD)dbei.pBlob = 0; - lstrcpyA((char*)dbei.pBlob + sizeof(DWORD), szFileNames); - lstrcpyA((char*)dbei.pBlob + sizeof(DWORD) + lstrlenA(szFileNames) + 1, szMsg); - - mir_free(szFileNames), mir_free(szMsg); -} - -static void __cdecl RunVirusScannerThread(struct virusscanthreadstartinfo *info) -{ - DBVARIANT dbv; - if (!db_get_ts(NULL, "SRFile", "ScanCmdLine", &dbv)) { - if (dbv.ptszVal[0]) { - STARTUPINFO si = { 0 }; - si.cb = sizeof(si); - TCHAR *pszReplace = _tcsstr(dbv.ptszVal, _T("%f")); - TCHAR szCmdLine[768]; - if (pszReplace) { - if (info->szFile[_tcslen(info->szFile) - 1] == '\\') - info->szFile[_tcslen(info->szFile) - 1] = '\0'; - *pszReplace = 0; - mir_sntprintf(szCmdLine, SIZEOF(szCmdLine), _T("%s\"%s\"%s"), dbv.ptszVal, info->szFile, pszReplace + 2); - } - else lstrcpyn(szCmdLine, dbv.ptszVal, SIZEOF(szCmdLine)); - - PROCESS_INFORMATION pi; - if (CreateProcess(NULL, szCmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { - if (WaitForSingleObject(pi.hProcess, 3600 * 1000) == WAIT_OBJECT_0) - PostMessage(info->hwndReply, M_VIRUSSCANDONE, info->returnCode, 0); - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - } - } - db_free(&dbv); - } - mir_free(info->szFile); - mir_free(info); -} - -static void SetFilenameControls(HWND hwndDlg, FileDlgData *dat, PROTOFILETRANSFERSTATUS *fts) -{ - TCHAR msg[MAX_PATH]; - TCHAR *fnbuf = NULL, *fn = NULL; - SHFILEINFO shfi = { 0 }; - - if (fts->tszCurrentFile) { - fnbuf = mir_tstrdup(fts->tszCurrentFile); - if ((fn = _tcsrchr(fnbuf, '\\')) == NULL) - fn = fnbuf; - else fn++; - } - - if (dat->hIcon) DestroyIcon(dat->hIcon); dat->hIcon = NULL; - - if (fn && (fts->totalFiles > 1)) { - mir_sntprintf(msg, SIZEOF(msg), _T("%s: %s (%d %s %d)"), - pcli->pfnGetContactDisplayName(fts->hContact, 0), - fn, fts->currentFileNumber + 1, TranslateT("of"), fts->totalFiles); - - SHGetFileInfo(fn, FILE_ATTRIBUTE_DIRECTORY, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_ICON | SHGFI_SMALLICON); - dat->hIcon = shfi.hIcon; - } - else if (fn) { - mir_sntprintf(msg, SIZEOF(msg), _T("%s: %s"), pcli->pfnGetContactDisplayName(fts->hContact, 0), fn); - - SHGetFileInfo(fn, FILE_ATTRIBUTE_NORMAL, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_ICON | SHGFI_SMALLICON); - dat->hIcon = shfi.hIcon; - } - else { - lstrcpyn(msg, pcli->pfnGetContactDisplayName(fts->hContact, 0), SIZEOF(msg)); - HICON hIcon = LoadSkinIcon(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, TCHAR *text, int mode) -{ - SetDlgItemText(hwndDlg, IDC_STATUS, TranslateTS(text)); - SetDlgItemText(hwndDlg, IDC_TRANSFERCOMPLETED, TranslateTS(text)); - - ShowWindow(GetDlgItem(hwndDlg, IDC_STATUS), (mode == FTS_TEXT) ? SW_SHOW : SW_HIDE); - ShowWindow(GetDlgItem(hwndDlg, IDC_ALLFILESPROGRESS), (mode == FTS_PROGRESS) ? SW_SHOW : SW_HIDE); - ShowWindow(GetDlgItem(hwndDlg, IDC_TRANSFERCOMPLETED), (mode == FTS_OPEN) ? SW_SHOW : SW_HIDE); - ShowWindow(GetDlgItem(hwndDlg, IDC_FILEICON), (mode == FTS_OPEN) ? SW_SHOW : SW_HIDE); -} - -static void HideProgressControls(HWND hwndDlg) -{ - RECT rc; - char buf[64]; - - GetWindowRect(GetDlgItem(hwndDlg, IDC_ALLPRECENTS), &rc); - MapWindowPoints(NULL, hwndDlg, (LPPOINT)&rc, 2); - SetWindowPos(hwndDlg, NULL, 0, 0, 100, rc.bottom + 3, SWP_NOMOVE | SWP_NOZORDER); - ShowWindow(GetDlgItem(hwndDlg, IDC_ALLTRANSFERRED), SW_HIDE); - ShowWindow(GetDlgItem(hwndDlg, IDC_ALLSPEED), SW_HIDE); - - _strtime(buf); - SetDlgItemTextA(hwndDlg, IDC_ALLPRECENTS, buf); - - PostMessage(GetParent(hwndDlg), WM_FT_RESIZE, 0, (LPARAM)hwndDlg); -} - -static int FileTransferDlgResizer(HWND, LPARAM, UTILRESIZECONTROL *urc) -{ - switch (urc->wId) { - case IDC_CONTACTNAME: - case IDC_STATUS: - case IDC_ALLFILESPROGRESS: - case IDC_TRANSFERCOMPLETED: - return RD_ANCHORX_WIDTH | RD_ANCHORY_TOP; - case IDC_FRAME: - return RD_ANCHORX_WIDTH | RD_ANCHORY_BOTTOM; - case IDC_ALLPRECENTS: - case IDCANCEL: - case IDC_OPENFILE: - case IDC_OPENFOLDER: - return RD_ANCHORX_RIGHT | RD_ANCHORY_TOP; - - case IDC_ALLTRANSFERRED: - urc->rcItem.right = urc->rcItem.left + (urc->rcItem.right - urc->rcItem.left - urc->dlgOriginalSize.cx + urc->dlgNewSize.cx) / 3; - return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM; - - case IDC_ALLSPEED: - urc->rcItem.right = urc->rcItem.right - urc->dlgOriginalSize.cx + urc->dlgNewSize.cx; - urc->rcItem.left = urc->rcItem.left + (urc->rcItem.right - urc->rcItem.left) / 3; - return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM; - } - return RD_ANCHORX_LEFT | RD_ANCHORY_TOP; -} - -INT_PTR CALLBACK DlgProcFileTransfer(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - FileDlgData *dat = (FileDlgData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - - switch (msg) { - case WM_INITDIALOG: - TranslateDialogDefault(hwndDlg); - dat = (FileDlgData*)lParam; - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat); - dat->hNotifyEvent = HookEventMessage(ME_PROTO_ACK, hwndDlg, HM_RECVEVENT); - dat->transferStatus.currentFileNumber = -1; - if (dat->send) { - if (db_mc_isMeta(dat->hContact)) - dat->hContact = db_mc_getMostOnline(dat->hContact); - dat->fs = (HANDLE)CallContactService(dat->hContact, PSS_FILET, (WPARAM)dat->szMsg, (LPARAM)dat->files); - SetFtStatus(hwndDlg, LPGENT("Request sent, waiting for acceptance..."), FTS_TEXT); - SetOpenFileButtonStyle(GetDlgItem(hwndDlg, IDC_OPENFILE), 1); - dat->waitingForAcceptance = 1; - // hide "open" button since it may cause potential access violations... - ShowWindow(GetDlgItem(hwndDlg, IDC_OPENFILE), SW_HIDE); - ShowWindow(GetDlgItem(hwndDlg, IDC_OPENFOLDER), SW_HIDE); - } - else { //recv - CreateDirectoryTreeT(dat->szSavePath); - dat->fs = (HANDLE)CallContactService(dat->hContact, PSS_FILEALLOWT, (WPARAM)dat->fs, (LPARAM)dat->szSavePath); - dat->transferStatus.tszWorkingDir = mir_tstrdup(dat->szSavePath); - if (db_get_b(dat->hContact, "CList", "NotOnList", 0)) dat->resumeBehaviour = FILERESUME_ASK; - else dat->resumeBehaviour = db_get_b(NULL, "SRFile", "IfExists", FILERESUME_ASK); - SetFtStatus(hwndDlg, LPGENT("Waiting for connection..."), FTS_TEXT); - } - - /* check we actually got an fs handle back from the protocol */ - if (!dat->fs) { - SetFtStatus(hwndDlg, LPGENT("Unable to initiate transfer."), FTS_TEXT); - dat->waitingForAcceptance = 0; - } - { - LOGFONT lf; - HFONT hFont = (HFONT)SendDlgItemMessage(hwndDlg, IDC_CONTACTNAME, WM_GETFONT, 0, 0); - GetObject(hFont, sizeof(lf), &lf); - lf.lfWeight = FW_BOLD; - hFont = CreateFontIndirect(&lf); - SendDlgItemMessage(hwndDlg, IDC_CONTACTNAME, WM_SETFONT, (WPARAM)hFont, 0); - - SHFILEINFO shfi = { 0 }; - SHGetFileInfo(_T(""), FILE_ATTRIBUTE_DIRECTORY, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_ICON | SHGFI_SMALLICON); - dat->hIconFolder = shfi.hIcon; - } - dat->hIcon = NULL; - { - char *szProto = GetContactProto(dat->hContact); - WORD status = db_get_w(dat->hContact, szProto, "Status", ID_STATUS_ONLINE); - SendDlgItemMessage(hwndDlg, IDC_CONTACT, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadSkinnedProtoIcon(szProto, status)); - } - - SendDlgItemMessage(hwndDlg, IDC_CONTACT, BUTTONADDTOOLTIP, (WPARAM)LPGEN("Contact menu"), 0); - SendDlgItemMessage(hwndDlg, IDC_CONTACT, BUTTONSETASFLATBTN, TRUE, 0); - - Button_SetIcon_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_SetIcon_IcoLib(hwndDlg, IDCANCEL, SKINICON_OTHER_DELETE, LPGEN("Cancel")); - - SetDlgItemText(hwndDlg, IDC_CONTACTNAME, pcli->pfnGetContactDisplayName(dat->hContact, 0)); - - if (!dat->waitingForAcceptance) SetTimer(hwndDlg, 1, 1000, NULL); - return TRUE; - - case WM_TIMER: - MoveMemory(dat->bytesRecvedHistory + 1, dat->bytesRecvedHistory, sizeof(dat->bytesRecvedHistory) - sizeof(dat->bytesRecvedHistory[0])); - dat->bytesRecvedHistory[0] = dat->transferStatus.totalProgress; - if (dat->bytesRecvedHistorySize < SIZEOF(dat->bytesRecvedHistory)) - dat->bytesRecvedHistorySize++; - - { - TCHAR szSpeed[32], szTime[32], szDisplay[96]; - SYSTEMTIME st; - ULARGE_INTEGER li; - FILETIME ft; - - GetSensiblyFormattedSize((dat->bytesRecvedHistory[0] - dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1]) / dat->bytesRecvedHistorySize, szSpeed, SIZEOF(szSpeed), 0, 1, NULL); - if (dat->bytesRecvedHistory[0] == dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1]) - lstrcpy(szTime, _T("??:??:??")); - else { - li.QuadPart = BIGI(10000000)*(dat->transferStatus.currentFileSize - dat->transferStatus.currentFileProgress)*dat->bytesRecvedHistorySize / (dat->bytesRecvedHistory[0] - dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1]); - ft.dwHighDateTime = li.HighPart; ft.dwLowDateTime = li.LowPart; - FileTimeToSystemTime(&ft, &st); - GetTimeFormat(LOCALE_USER_DEFAULT, TIME_FORCE24HOURFORMAT | TIME_NOTIMEMARKER, &st, NULL, szTime, SIZEOF(szTime)); - } - if (dat->bytesRecvedHistory[0] != dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1]) { - li.QuadPart = BIGI(10000000)*(dat->transferStatus.totalBytes - dat->transferStatus.totalProgress)*dat->bytesRecvedHistorySize / (dat->bytesRecvedHistory[0] - dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1]); - ft.dwHighDateTime = li.HighPart; ft.dwLowDateTime = li.LowPart; - FileTimeToSystemTime(&ft, &st); - GetTimeFormat(LOCALE_USER_DEFAULT, TIME_FORCE24HOURFORMAT | TIME_NOTIMEMARKER, &st, NULL, szTime, SIZEOF(szTime)); - } - - mir_sntprintf(szDisplay, SIZEOF(szDisplay), _T("%s/%s (%s %s)"), szSpeed, TranslateT("sec"), szTime, TranslateT("remaining")); - SetDlgItemText(hwndDlg, IDC_ALLSPEED, szDisplay); - } - break; - - case WM_MEASUREITEM: - return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam); - - case WM_DRAWITEM: - return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam); - - case WM_FT_CLEANUP: - if (!dat->fs) { - PostMessage(GetParent(hwndDlg), WM_FT_REMOVE, 0, (LPARAM)hwndDlg); - DestroyWindow(hwndDlg); - } - break; - - case WM_COMMAND: - if (CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), MPCF_CONTACTMENU), (LPARAM)dat->hContact)) - break; - - switch (LOWORD(wParam)) { - case IDOK: - case IDCANCEL: - PostMessage(GetParent(hwndDlg), WM_FT_REMOVE, 0, (LPARAM)hwndDlg); - DestroyWindow(hwndDlg); - break; - - case IDC_CONTACT: - { - RECT rc; - HMENU hMenu = (HMENU)CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM)dat->hContact, 0); - GetWindowRect((HWND)lParam, &rc); - TrackPopupMenu(hMenu, 0, rc.left, rc.bottom, 0, hwndDlg, NULL); - DestroyMenu(hMenu); - } - break; - - case IDC_TRANSFERCOMPLETED: - if (dat->transferStatus.currentFileNumber <= 1 && CheckVirusScanned(hwndDlg, dat, 0)) { - ShellExecute(NULL, NULL, dat->files[0], NULL, NULL, SW_SHOW); - break; - } - - case IDC_OPENFOLDER: - if (dat) { - TCHAR *path = dat->transferStatus.tszWorkingDir; - if (!path || !path[0]) { - path = NEWTSTR_ALLOCA(dat->transferStatus.tszCurrentFile); - TCHAR *p = _tcsrchr(path, '\\'); if (p) *p = 0; - } - - if (path) ShellExecute(NULL, _T("open"), path, NULL, NULL, SW_SHOW); - } - break; - - case IDC_OPENFILE: - TCHAR **files; - if (dat->send) { - if (dat->files == NULL) - files = dat->transferStatus.ptszFiles; - else - files = dat->files; - } - else files = dat->files; - - HMENU hMenu = CreatePopupMenu(); - AppendMenu(hMenu, MF_STRING, 1, TranslateT("Open folder")); - AppendMenu(hMenu, MF_SEPARATOR, 0, 0); - - if (files && *files) { - int limit; - TCHAR *pszFilename, *pszNewFileName; - - if (dat->send) - limit = dat->transferStatus.totalFiles; - else - limit = dat->transferStatus.currentFileNumber; - - // Loop over all transfered files and add them to the menu - for (int i = 0; i < limit; i++) { - pszFilename = _tcsrchr(files[i], '\\'); - if (pszFilename == NULL) - pszFilename = files[i]; - else - pszFilename++; - - if (pszFilename) { - size_t cbFileNameLen = _tcslen(pszFilename); - - pszNewFileName = (TCHAR*)mir_alloc(cbFileNameLen * 2 * sizeof(TCHAR)); - TCHAR *p = pszNewFileName; - for (size_t pszlen = 0; pszlen < cbFileNameLen; pszlen++) { - *p++ = pszFilename[pszlen]; - if (pszFilename[pszlen] == '&') - *p++ = '&'; - } - *p = '\0'; - AppendMenu(hMenu, MF_STRING, i + 10, pszNewFileName); - mir_free(pszNewFileName); - } - } - } - - 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, NULL); - CheckDlgButton(hwndDlg, IDC_OPENFILE, BST_UNCHECKED); - DestroyMenu(hMenu); - - if (ret == 1) { - TCHAR *path = dat->transferStatus.tszWorkingDir; - if (!path || !path[0]) { - path = NEWTSTR_ALLOCA(dat->transferStatus.tszCurrentFile); - TCHAR *p = _tcsrchr(path, '\\'); - if (p) - *p = 0; - } - - if (path) ShellExecute(NULL, _T("open"), path, NULL, NULL, SW_SHOW); - } - else if (ret && CheckVirusScanned(hwndDlg, dat, ret)) - ShellExecute(NULL, NULL, files[ret - 10], NULL, NULL, SW_SHOW); - } - break; - - case M_FILEEXISTSDLGREPLY: - EnableWindow(hwndDlg, TRUE); - { - PROTOFILERESUME *pfr = (PROTOFILERESUME*)lParam; - TCHAR *szOriginalFilename = (TCHAR*)wParam; - char *szProto = GetContactProto(dat->hContact); - - switch (pfr->action) { - case FILERESUME_CANCEL: - if (dat->fs) CallContactService(dat->hContact, PSS_FILECANCEL, (WPARAM)dat->fs, 0); - dat->fs = NULL; - mir_free(szOriginalFilename); - if (pfr->szFilename) mir_free((char*)pfr->szFilename); - mir_free(pfr); - return 0; - case FILERESUME_RESUMEALL: - case FILERESUME_OVERWRITEALL: - dat->resumeBehaviour = pfr->action; - pfr->action &= ~FILERESUMEF_ALL; - break; - case FILERESUME_RENAMEALL: - pfr->action = FILERESUME_RENAME; - { - TCHAR *pszExtension, *pszFilename; - if ((pszFilename = _tcsrchr(szOriginalFilename, '\\')) == NULL) pszFilename = szOriginalFilename; - if ((pszExtension = _tcsrchr(pszFilename + 1, '.')) == NULL) pszExtension = pszFilename + lstrlen(pszFilename); - if (pfr->szFilename) mir_free((TCHAR*)pfr->szFilename); - size_t size = (pszExtension - szOriginalFilename) + 21 + lstrlen(pszExtension); - pfr->szFilename = (TCHAR*)mir_alloc(sizeof(TCHAR)*size); - for (int i = 1;; i++) { - mir_sntprintf((TCHAR*)pfr->szFilename, size, _T("%.*s (%u)%s"), pszExtension - szOriginalFilename, szOriginalFilename, i, pszExtension); - if (_taccess(pfr->szFilename, 0) != 0) - break; - } - } - break; - } - mir_free(szOriginalFilename); - CallProtoService(szProto, PS_FILERESUMET, (WPARAM)dat->fs, (LPARAM)pfr); - if (pfr->szFilename) mir_free((char*)pfr->szFilename); - mir_free(pfr); - } - break; - - case HM_RECVEVENT: - { - ACKDATA *ack = (ACKDATA*)lParam; - if (ack->hProcess != dat->fs) break; - if (ack->type != ACKTYPE_FILE) break; - if (ack->hContact != dat->hContact) break; - - if (dat->waitingForAcceptance) { - SetTimer(hwndDlg, 1, 1000, NULL); - dat->waitingForAcceptance = 0; - } - - switch (ack->result) { - case ACKRESULT_SENTREQUEST: SetFtStatus(hwndDlg, LPGENT("Decision sent"), FTS_TEXT); break; - case ACKRESULT_CONNECTING: SetFtStatus(hwndDlg, LPGENT("Connecting..."), FTS_TEXT); break; - case ACKRESULT_CONNECTPROXY: SetFtStatus(hwndDlg, LPGENT("Connecting to proxy..."), FTS_TEXT); break; - case ACKRESULT_CONNECTED: SetFtStatus(hwndDlg, LPGENT("Connected"), FTS_TEXT); break; - case ACKRESULT_LISTENING: SetFtStatus(hwndDlg, LPGENT("Waiting for connection..."), FTS_TEXT); break; - case ACKRESULT_INITIALISING: SetFtStatus(hwndDlg, LPGENT("Initializing..."), FTS_TEXT); break; - case ACKRESULT_NEXTFILE: - SetFtStatus(hwndDlg, LPGENT("Moving to next file..."), FTS_TEXT); - SetDlgItemTextA(hwndDlg, IDC_FILENAME, ""); - if (dat->transferStatus.currentFileNumber == 1 && dat->transferStatus.totalFiles > 1 && !dat->send) - SetOpenFileButtonStyle(GetDlgItem(hwndDlg, IDC_OPENFILE), 1); - if (dat->transferStatus.currentFileNumber != -1 && dat->files && !dat->send && db_get_b(NULL, "SRFile", "UseScanner", VIRUSSCAN_DISABLE) == VIRUSSCAN_DURINGDL) { - if (GetFileAttributes(dat->files[dat->transferStatus.currentFileNumber])&FILE_ATTRIBUTE_DIRECTORY) - PostMessage(hwndDlg, M_VIRUSSCANDONE, dat->transferStatus.currentFileNumber, 0); - else { - virusscanthreadstartinfo *vstsi; - vstsi = (struct virusscanthreadstartinfo*)mir_alloc(sizeof(struct virusscanthreadstartinfo)); - vstsi->hwndReply = hwndDlg; - vstsi->szFile = mir_tstrdup(dat->files[dat->transferStatus.currentFileNumber]); - vstsi->returnCode = dat->transferStatus.currentFileNumber; - forkthread((void(*)(void*))RunVirusScannerThread, 0, vstsi); - } - } - break; - - case ACKRESULT_FILERESUME: - UpdateProtoFileTransferStatus(&dat->transferStatus, (PROTOFILETRANSFERSTATUS*)ack->lParam); - { - PROTOFILETRANSFERSTATUS *fts = &dat->transferStatus; - SetFilenameControls(hwndDlg, dat, fts); - if (_taccess(fts->tszCurrentFile, 0)) - break; - - SetFtStatus(hwndDlg, LPGENT("File already exists"), FTS_TEXT); - if (dat->resumeBehaviour == FILERESUME_ASK) { - TDlgProcFileExistsParam param = { hwndDlg, fts }; - ShowWindow(hwndDlg, SW_SHOWNORMAL); - CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_FILEEXISTS), hwndDlg, DlgProcFileExists, (LPARAM)¶m); - EnableWindow(hwndDlg, FALSE); - } - else { - PROTOFILERESUME *pfr = (PROTOFILERESUME*)mir_alloc(sizeof(PROTOFILERESUME)); - pfr->action = dat->resumeBehaviour; - pfr->szFilename = NULL; - PostMessage(hwndDlg, M_FILEEXISTSDLGREPLY, (WPARAM)mir_tstrdup(fts->tszCurrentFile), (LPARAM)pfr); - } - } - SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, 1); - return TRUE; - - case ACKRESULT_DATA: - { - PROTOFILETRANSFERSTATUS *fts = (PROTOFILETRANSFERSTATUS*)ack->lParam; - TCHAR str[64], str2[64], szSizeDone[32], szSizeTotal[32];//, *contactName; - - if (dat->fileVirusScanned == NULL) - dat->fileVirusScanned = (int*)mir_calloc(sizeof(int) * fts->totalFiles); - - // This needs to be here - otherwise we get holes in the files array - if (!dat->send) { - if (dat->files == NULL) - dat->files = (TCHAR**)mir_calloc((fts->totalFiles + 1) * sizeof(TCHAR*)); - if (fts->currentFileNumber < fts->totalFiles && dat->files[fts->currentFileNumber] == NULL) - dat->files[fts->currentFileNumber] = PFTS_StringToTchar(fts->flags, fts->tszCurrentFile); - } - - /* HACK: for 0.3.3, limit updates to around 1.1 ack per second */ - if (fts->totalProgress != fts->totalBytes && GetTickCount() < (dat->dwTicks + 650)) - break; // the last update was less than a second ago! - dat->dwTicks = GetTickCount(); - - // Update local transfer status with data from protocol - UpdateProtoFileTransferStatus(&dat->transferStatus, fts); - fts = &dat->transferStatus; - - bool firstTime = false; - if ((GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_ALLFILESPROGRESS), GWL_STYLE) & WS_VISIBLE) == 0) { - SetFtStatus(hwndDlg, (fts->flags & PFTS_SENDING) ? LPGENT("Sending...") : LPGENT("Receiving..."), FTS_PROGRESS); - SetFilenameControls(hwndDlg, dat, fts); - firstTime = true; - } - - const unsigned long lastPos = SendDlgItemMessage(hwndDlg, IDC_ALLFILESPROGRESS, PBM_GETPOS, 0, 0); - const unsigned long nextPos = fts->totalBytes ? (BIGI(100) * fts->totalProgress / fts->totalBytes) : 0; - if (lastPos != nextPos || firstTime) { - SendDlgItemMessage(hwndDlg, IDC_ALLFILESPROGRESS, PBM_SETPOS, nextPos, 0); - mir_sntprintf(str, SIZEOF(str), _T("%u%%"), nextPos); - SetDlgItemText(hwndDlg, IDC_ALLPRECENTS, str); - } - - int units; - GetSensiblyFormattedSize(fts->totalBytes, szSizeTotal, SIZEOF(szSizeTotal), 0, 1, &units); - GetSensiblyFormattedSize(fts->totalProgress, szSizeDone, SIZEOF(szSizeDone), units, 0, NULL); - mir_sntprintf(str, SIZEOF(str), _T("%s/%s"), szSizeDone, szSizeTotal); - str2[0] = 0; - GetDlgItemText(hwndDlg, IDC_ALLTRANSFERRED, str2, SIZEOF(str2)); - if (_tcscmp(str, str2)) - SetDlgItemText(hwndDlg, IDC_ALLTRANSFERRED, str); - } - break; - - case ACKRESULT_SUCCESS: - case ACKRESULT_FAILED: - case ACKRESULT_DENIED: - HideProgressControls(hwndDlg); - KillTimer(hwndDlg, 1); - if (!dat->send) - SetOpenFileButtonStyle(GetDlgItem(hwndDlg, IDC_OPENFILE), 1); - SetDlgItemText(hwndDlg, IDCANCEL, TranslateT("Close")); - if (dat->hNotifyEvent) - UnhookEvent(dat->hNotifyEvent); - dat->hNotifyEvent = NULL; - - if (ack->result == ACKRESULT_DENIED) { - dat->fs = NULL; /* protocol will free structure */ - SkinPlaySound("FileDenied"); - SetFtStatus(hwndDlg, LPGENT("File transfer denied"), FTS_TEXT); - } - else if (ack->result == ACKRESULT_FAILED) { - dat->fs = NULL; /* protocol will free structure */ - SkinPlaySound("FileFailed"); - SetFtStatus(hwndDlg, LPGENT("File transfer failed"), FTS_TEXT); - } - else { - SkinPlaySound("FileDone"); - if (dat->send) { - dat->fs = NULL; /* protocol will free structure */ - SetFtStatus(hwndDlg, LPGENT("Transfer completed."), FTS_TEXT); - - DBEVENTINFO dbei = { 0 }; - FillSendData(dat, dbei); - db_event_add(dat->hContact, &dbei); - if (dbei.pBlob) - mir_free(dbei.pBlob); - dat->files = NULL; //protocol library frees this - } - else { - SetFtStatus(hwndDlg, - (dat->transferStatus.totalFiles == 1) ? - LPGENT("Transfer completed, open file.") : - LPGENT("Transfer completed, open folder."), - FTS_OPEN); - - int useScanner = db_get_b(NULL, "SRFile", "UseScanner", VIRUSSCAN_DISABLE); - if (useScanner != VIRUSSCAN_DISABLE) { - struct virusscanthreadstartinfo *vstsi; - vstsi = (struct virusscanthreadstartinfo*)mir_alloc(sizeof(struct virusscanthreadstartinfo)); - vstsi->hwndReply = hwndDlg; - if (useScanner == VIRUSSCAN_DURINGDL) { - vstsi->returnCode = dat->transferStatus.currentFileNumber; - if (GetFileAttributes(dat->files[dat->transferStatus.currentFileNumber])&FILE_ATTRIBUTE_DIRECTORY) { - PostMessage(hwndDlg, M_VIRUSSCANDONE, vstsi->returnCode, 0); - mir_free(vstsi); - vstsi = NULL; - } - else vstsi->szFile = mir_tstrdup(dat->files[dat->transferStatus.currentFileNumber]); - } - else { - vstsi->szFile = mir_tstrdup(dat->transferStatus.tszWorkingDir); - vstsi->returnCode = -1; - } - SetFtStatus(hwndDlg, LPGENT("Scanning for viruses..."), FTS_TEXT); - if (vstsi) - forkthread((void(*)(void*))RunVirusScannerThread, 0, vstsi); - } - else dat->fs = NULL; /* protocol will free structure */ - - dat->transferStatus.currentFileNumber = dat->transferStatus.totalFiles; - } // else dat->send - - } // else ack->result - - PostMessage(GetParent(hwndDlg), WM_FT_COMPLETED, ack->result, (LPARAM)hwndDlg); - break; - } // switch ack->result - } // case HM_RECVEVENT - 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 = NULL; /* protocol will free structure */ - SetFtStatus(hwndDlg, LPGENT("Transfer and virus scan complete"), FTS_TEXT); - } - } - break; - - case WM_SIZE: - { - UTILRESIZEDIALOG urd = { 0 }; - urd.cbSize = sizeof(urd); - urd.hwndDlg = hwndDlg; - urd.hInstance = hInst; - urd.lpTemplate = MAKEINTRESOURCEA(IDD_FILETRANSFERINFO); - urd.pfnResizer = FileTransferDlgResizer; - CallService(MS_UTILS_RESIZEDIALOG, 0, (LPARAM)&urd); - } - RedrawWindow(GetDlgItem(hwndDlg, IDC_ALLTRANSFERRED), NULL, NULL, RDW_INVALIDATE | RDW_NOERASE); - RedrawWindow(GetDlgItem(hwndDlg, IDC_ALLSPEED), NULL, NULL, RDW_INVALIDATE | RDW_NOERASE); - RedrawWindow(GetDlgItem(hwndDlg, IDC_CONTACTNAME), NULL, NULL, RDW_INVALIDATE | RDW_NOERASE); - RedrawWindow(GetDlgItem(hwndDlg, IDC_STATUS), NULL, NULL, RDW_INVALIDATE | RDW_NOERASE); - break; - - case WM_DESTROY: - KillTimer(hwndDlg, 1); - - HFONT hFont = (HFONT)SendDlgItemMessage(hwndDlg, IDC_CONTACTNAME, WM_GETFONT, 0, 0); - DeleteObject(hFont); - - Button_FreeIcon_IcoLib(hwndDlg, IDC_CONTACT); - Button_FreeIcon_IcoLib(hwndDlg, IDC_OPENFILE); - Button_FreeIcon_IcoLib(hwndDlg, IDCANCEL); - - FreeFileDlgData(dat); - break; - } - return FALSE; -} - -void FreeFileDlgData(FileDlgData* dat) -{ - if (dat->fs) - CallContactService(dat->hContact, PSS_FILECANCEL, (WPARAM)dat->fs, 0); - dat->fs = NULL; - - if (dat->hPreshutdownEvent) UnhookEvent(dat->hPreshutdownEvent); - if (dat->hNotifyEvent) UnhookEvent(dat->hNotifyEvent); - dat->hNotifyEvent = NULL; - - FreeProtoFileTransferStatus(&dat->transferStatus); - FreeFilesMatrix(&dat->files); - - mir_free(dat->fileVirusScanned); - if (dat->hIcon) DestroyIcon(dat->hIcon); - if (dat->hIconFolder) DestroyIcon(dat->hIconFolder); - mir_free(dat); -} +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (c) 2012-14 Miranda NG project (http://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 "commonheaders.h" +#include +#include "file.h" + +#define HM_RECVEVENT (WM_USER+10) + +static int CheckVirusScanned(HWND hwnd, FileDlgData *dat, int i) +{ + if (dat->send) return 1; + if (dat->fileVirusScanned == NULL) return 0; + if (dat->fileVirusScanned[i]) return 1; + if (db_get_b(NULL, "SRFile", "WarnBeforeOpening", 1) == 0) return 1; + return IDYES == MessageBox(hwnd, TranslateT("This file has not yet been scanned for viruses. Are you certain you want to open it?"), TranslateT("File received"), MB_YESNO|MB_DEFBUTTON2); +} + +#define M_VIRUSSCANDONE (WM_USER+100) +struct virusscanthreadstartinfo { + TCHAR *szFile; + int returnCode; + HWND hwndReply; +}; + +TCHAR* PFTS_StringToTchar(int flags, const PROTOCHAR* s) +{ + if (flags & PFTS_UTF) + return Utf8DecodeW((char*)s); + if (flags & PFTS_UNICODE) + return mir_tstrdup(s); + return mir_a2t((char*)s); +} + +int PFTS_CompareWithTchar(PROTOFILETRANSFERSTATUS *ft, const PROTOCHAR *s, TCHAR *r) +{ + if (ft->flags & PFTS_UTF) { + TCHAR *ts = Utf8DecodeW((char*)s); + int res = _tcscmp(ts, r); + mir_free(ts); + return res; + } + if (ft->flags & PFTS_UNICODE) + return _tcscmp(s, r); + + TCHAR *ts = mir_a2t((char*)s); + int res = _tcscmp(ts, r); + mir_free(ts); + return res; +} + +static void SetOpenFileButtonStyle(HWND hwndButton, int enabled) +{ + EnableWindow(hwndButton, enabled); +} + +void FillSendData(FileDlgData *dat, DBEVENTINFO& dbei) +{ + dbei.cbSize = sizeof(dbei); + dbei.szModule = GetContactProto(dat->hContact); + dbei.eventType = EVENTTYPE_FILE; + dbei.flags = DBEF_SENT; + dbei.timestamp = time(NULL); + char *szFileNames = Utf8EncodeT(dat->szFilenames), *szMsg = Utf8EncodeT(dat->szMsg); + dbei.flags |= DBEF_UTF; + + dbei.cbBlob = sizeof(DWORD) + lstrlenA(szFileNames) + lstrlenA(szMsg) + 2; + dbei.pBlob = (PBYTE)mir_alloc(dbei.cbBlob); + *(PDWORD)dbei.pBlob = 0; + lstrcpyA((char*)dbei.pBlob + sizeof(DWORD), szFileNames); + lstrcpyA((char*)dbei.pBlob + sizeof(DWORD) + lstrlenA(szFileNames) + 1, szMsg); + + mir_free(szFileNames), mir_free(szMsg); +} + +static void __cdecl RunVirusScannerThread(struct virusscanthreadstartinfo *info) +{ + DBVARIANT dbv; + if (!db_get_ts(NULL, "SRFile", "ScanCmdLine", &dbv)) { + if (dbv.ptszVal[0]) { + STARTUPINFO si = { 0 }; + si.cb = sizeof(si); + TCHAR *pszReplace = _tcsstr(dbv.ptszVal, _T("%f")); + TCHAR szCmdLine[768]; + if (pszReplace) { + if (info->szFile[_tcslen(info->szFile) - 1] == '\\') + info->szFile[_tcslen(info->szFile) - 1] = '\0'; + *pszReplace = 0; + mir_sntprintf(szCmdLine, SIZEOF(szCmdLine), _T("%s\"%s\"%s"), dbv.ptszVal, info->szFile, pszReplace + 2); + } + else lstrcpyn(szCmdLine, dbv.ptszVal, SIZEOF(szCmdLine)); + + PROCESS_INFORMATION pi; + if (CreateProcess(NULL, szCmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { + if (WaitForSingleObject(pi.hProcess, 3600 * 1000) == WAIT_OBJECT_0) + PostMessage(info->hwndReply, M_VIRUSSCANDONE, info->returnCode, 0); + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + } + } + db_free(&dbv); + } + mir_free(info->szFile); + mir_free(info); +} + +static void SetFilenameControls(HWND hwndDlg, FileDlgData *dat, PROTOFILETRANSFERSTATUS *fts) +{ + TCHAR msg[MAX_PATH]; + TCHAR *fnbuf = NULL, *fn = NULL; + SHFILEINFO shfi = { 0 }; + + if (fts->tszCurrentFile) { + fnbuf = mir_tstrdup(fts->tszCurrentFile); + if ((fn = _tcsrchr(fnbuf, '\\')) == NULL) + fn = fnbuf; + else fn++; + } + + if (dat->hIcon) DestroyIcon(dat->hIcon); dat->hIcon = NULL; + + if (fn && (fts->totalFiles > 1)) { + mir_sntprintf(msg, SIZEOF(msg), _T("%s: %s (%d %s %d)"), + pcli->pfnGetContactDisplayName(fts->hContact, 0), + fn, fts->currentFileNumber + 1, TranslateT("of"), fts->totalFiles); + + SHGetFileInfo(fn, FILE_ATTRIBUTE_DIRECTORY, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_ICON | SHGFI_SMALLICON); + dat->hIcon = shfi.hIcon; + } + else if (fn) { + mir_sntprintf(msg, SIZEOF(msg), _T("%s: %s"), pcli->pfnGetContactDisplayName(fts->hContact, 0), fn); + + SHGetFileInfo(fn, FILE_ATTRIBUTE_NORMAL, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_ICON | SHGFI_SMALLICON); + dat->hIcon = shfi.hIcon; + } + else { + lstrcpyn(msg, pcli->pfnGetContactDisplayName(fts->hContact, 0), SIZEOF(msg)); + HICON hIcon = LoadSkinIcon(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, TCHAR *text, int mode) +{ + SetDlgItemText(hwndDlg, IDC_STATUS, TranslateTS(text)); + SetDlgItemText(hwndDlg, IDC_TRANSFERCOMPLETED, TranslateTS(text)); + + ShowWindow(GetDlgItem(hwndDlg, IDC_STATUS), (mode == FTS_TEXT) ? SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_ALLFILESPROGRESS), (mode == FTS_PROGRESS) ? SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_TRANSFERCOMPLETED), (mode == FTS_OPEN) ? SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_FILEICON), (mode == FTS_OPEN) ? SW_SHOW : SW_HIDE); +} + +static void HideProgressControls(HWND hwndDlg) +{ + RECT rc; + char buf[64]; + + GetWindowRect(GetDlgItem(hwndDlg, IDC_ALLPRECENTS), &rc); + MapWindowPoints(NULL, hwndDlg, (LPPOINT)&rc, 2); + SetWindowPos(hwndDlg, NULL, 0, 0, 100, rc.bottom + 3, SWP_NOMOVE | SWP_NOZORDER); + ShowWindow(GetDlgItem(hwndDlg, IDC_ALLTRANSFERRED), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_ALLSPEED), SW_HIDE); + + _strtime(buf); + SetDlgItemTextA(hwndDlg, IDC_ALLPRECENTS, buf); + + PostMessage(GetParent(hwndDlg), WM_FT_RESIZE, 0, (LPARAM)hwndDlg); +} + +static int FileTransferDlgResizer(HWND, LPARAM, UTILRESIZECONTROL *urc) +{ + switch (urc->wId) { + case IDC_CONTACTNAME: + case IDC_STATUS: + case IDC_ALLFILESPROGRESS: + case IDC_TRANSFERCOMPLETED: + return RD_ANCHORX_WIDTH | RD_ANCHORY_TOP; + case IDC_FRAME: + return RD_ANCHORX_WIDTH | RD_ANCHORY_BOTTOM; + case IDC_ALLPRECENTS: + case IDCANCEL: + case IDC_OPENFILE: + case IDC_OPENFOLDER: + return RD_ANCHORX_RIGHT | RD_ANCHORY_TOP; + + case IDC_ALLTRANSFERRED: + urc->rcItem.right = urc->rcItem.left + (urc->rcItem.right - urc->rcItem.left - urc->dlgOriginalSize.cx + urc->dlgNewSize.cx) / 3; + return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM; + + case IDC_ALLSPEED: + urc->rcItem.right = urc->rcItem.right - urc->dlgOriginalSize.cx + urc->dlgNewSize.cx; + urc->rcItem.left = urc->rcItem.left + (urc->rcItem.right - urc->rcItem.left) / 3; + return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM; + } + return RD_ANCHORX_LEFT | RD_ANCHORY_TOP; +} + +INT_PTR CALLBACK DlgProcFileTransfer(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + FileDlgData *dat = (FileDlgData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + dat = (FileDlgData*)lParam; + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat); + dat->hNotifyEvent = HookEventMessage(ME_PROTO_ACK, hwndDlg, HM_RECVEVENT); + dat->transferStatus.currentFileNumber = -1; + if (dat->send) { + if (db_mc_isMeta(dat->hContact)) + dat->hContact = db_mc_getMostOnline(dat->hContact); + dat->fs = (HANDLE)CallContactService(dat->hContact, PSS_FILET, (WPARAM)dat->szMsg, (LPARAM)dat->files); + SetFtStatus(hwndDlg, LPGENT("Request sent, waiting for acceptance..."), FTS_TEXT); + SetOpenFileButtonStyle(GetDlgItem(hwndDlg, IDC_OPENFILE), 1); + dat->waitingForAcceptance = 1; + // hide "open" button since it may cause potential access violations... + ShowWindow(GetDlgItem(hwndDlg, IDC_OPENFILE), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_OPENFOLDER), SW_HIDE); + } + else { //recv + CreateDirectoryTreeT(dat->szSavePath); + dat->fs = (HANDLE)CallContactService(dat->hContact, PSS_FILEALLOWT, (WPARAM)dat->fs, (LPARAM)dat->szSavePath); + dat->transferStatus.tszWorkingDir = mir_tstrdup(dat->szSavePath); + if (db_get_b(dat->hContact, "CList", "NotOnList", 0)) dat->resumeBehaviour = FILERESUME_ASK; + else dat->resumeBehaviour = db_get_b(NULL, "SRFile", "IfExists", FILERESUME_ASK); + SetFtStatus(hwndDlg, LPGENT("Waiting for connection..."), FTS_TEXT); + } + + /* check we actually got an fs handle back from the protocol */ + if (!dat->fs) { + SetFtStatus(hwndDlg, LPGENT("Unable to initiate transfer."), FTS_TEXT); + dat->waitingForAcceptance = 0; + } + { + LOGFONT lf; + HFONT hFont = (HFONT)SendDlgItemMessage(hwndDlg, IDC_CONTACTNAME, WM_GETFONT, 0, 0); + GetObject(hFont, sizeof(lf), &lf); + lf.lfWeight = FW_BOLD; + hFont = CreateFontIndirect(&lf); + SendDlgItemMessage(hwndDlg, IDC_CONTACTNAME, WM_SETFONT, (WPARAM)hFont, 0); + + SHFILEINFO shfi = { 0 }; + SHGetFileInfo(_T(""), FILE_ATTRIBUTE_DIRECTORY, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_ICON | SHGFI_SMALLICON); + dat->hIconFolder = shfi.hIcon; + } + dat->hIcon = NULL; + { + char *szProto = GetContactProto(dat->hContact); + WORD status = db_get_w(dat->hContact, szProto, "Status", ID_STATUS_ONLINE); + SendDlgItemMessage(hwndDlg, IDC_CONTACT, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadSkinnedProtoIcon(szProto, status)); + } + + SendDlgItemMessage(hwndDlg, IDC_CONTACT, BUTTONADDTOOLTIP, (WPARAM)LPGEN("Contact menu"), 0); + SendDlgItemMessage(hwndDlg, IDC_CONTACT, BUTTONSETASFLATBTN, TRUE, 0); + + Button_SetIcon_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_SetIcon_IcoLib(hwndDlg, IDCANCEL, SKINICON_OTHER_DELETE, LPGEN("Cancel")); + + SetDlgItemText(hwndDlg, IDC_CONTACTNAME, pcli->pfnGetContactDisplayName(dat->hContact, 0)); + + if (!dat->waitingForAcceptance) SetTimer(hwndDlg, 1, 1000, NULL); + return TRUE; + + case WM_TIMER: + MoveMemory(dat->bytesRecvedHistory + 1, dat->bytesRecvedHistory, sizeof(dat->bytesRecvedHistory) - sizeof(dat->bytesRecvedHistory[0])); + dat->bytesRecvedHistory[0] = dat->transferStatus.totalProgress; + if (dat->bytesRecvedHistorySize < SIZEOF(dat->bytesRecvedHistory)) + dat->bytesRecvedHistorySize++; + + { + TCHAR szSpeed[32], szTime[32], szDisplay[96]; + SYSTEMTIME st; + ULARGE_INTEGER li; + FILETIME ft; + + GetSensiblyFormattedSize((dat->bytesRecvedHistory[0] - dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1]) / dat->bytesRecvedHistorySize, szSpeed, SIZEOF(szSpeed), 0, 1, NULL); + if (dat->bytesRecvedHistory[0] == dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1]) + lstrcpy(szTime, _T("??:??:??")); + else { + li.QuadPart = BIGI(10000000)*(dat->transferStatus.currentFileSize - dat->transferStatus.currentFileProgress)*dat->bytesRecvedHistorySize / (dat->bytesRecvedHistory[0] - dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1]); + ft.dwHighDateTime = li.HighPart; ft.dwLowDateTime = li.LowPart; + FileTimeToSystemTime(&ft, &st); + GetTimeFormat(LOCALE_USER_DEFAULT, TIME_FORCE24HOURFORMAT | TIME_NOTIMEMARKER, &st, NULL, szTime, SIZEOF(szTime)); + } + if (dat->bytesRecvedHistory[0] != dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1]) { + li.QuadPart = BIGI(10000000)*(dat->transferStatus.totalBytes - dat->transferStatus.totalProgress)*dat->bytesRecvedHistorySize / (dat->bytesRecvedHistory[0] - dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1]); + ft.dwHighDateTime = li.HighPart; ft.dwLowDateTime = li.LowPart; + FileTimeToSystemTime(&ft, &st); + GetTimeFormat(LOCALE_USER_DEFAULT, TIME_FORCE24HOURFORMAT | TIME_NOTIMEMARKER, &st, NULL, szTime, SIZEOF(szTime)); + } + + mir_sntprintf(szDisplay, SIZEOF(szDisplay), _T("%s/%s (%s %s)"), szSpeed, TranslateT("sec"), szTime, TranslateT("remaining")); + SetDlgItemText(hwndDlg, IDC_ALLSPEED, szDisplay); + } + break; + + case WM_MEASUREITEM: + return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam); + + case WM_DRAWITEM: + return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam); + + case WM_FT_CLEANUP: + if (!dat->fs) { + PostMessage(GetParent(hwndDlg), WM_FT_REMOVE, 0, (LPARAM)hwndDlg); + DestroyWindow(hwndDlg); + } + break; + + case WM_COMMAND: + if (CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), MPCF_CONTACTMENU), (LPARAM)dat->hContact)) + break; + + switch (LOWORD(wParam)) { + case IDOK: + case IDCANCEL: + PostMessage(GetParent(hwndDlg), WM_FT_REMOVE, 0, (LPARAM)hwndDlg); + DestroyWindow(hwndDlg); + break; + + case IDC_CONTACT: + { + RECT rc; + HMENU hMenu = (HMENU)CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM)dat->hContact, 0); + GetWindowRect((HWND)lParam, &rc); + TrackPopupMenu(hMenu, 0, rc.left, rc.bottom, 0, hwndDlg, NULL); + DestroyMenu(hMenu); + } + break; + + case IDC_TRANSFERCOMPLETED: + if (dat->transferStatus.currentFileNumber <= 1 && CheckVirusScanned(hwndDlg, dat, 0)) { + ShellExecute(NULL, NULL, dat->files[0], NULL, NULL, SW_SHOW); + break; + } + + case IDC_OPENFOLDER: + if (dat) { + TCHAR *path = dat->transferStatus.tszWorkingDir; + if (!path || !path[0]) { + path = NEWTSTR_ALLOCA(dat->transferStatus.tszCurrentFile); + TCHAR *p = _tcsrchr(path, '\\'); if (p) *p = 0; + } + + if (path) ShellExecute(NULL, _T("open"), path, NULL, NULL, SW_SHOW); + } + break; + + case IDC_OPENFILE: + TCHAR **files; + if (dat->send) { + if (dat->files == NULL) + files = dat->transferStatus.ptszFiles; + else + files = dat->files; + } + else files = dat->files; + + HMENU hMenu = CreatePopupMenu(); + AppendMenu(hMenu, MF_STRING, 1, TranslateT("Open folder")); + AppendMenu(hMenu, MF_SEPARATOR, 0, 0); + + if (files && *files) { + int limit; + TCHAR *pszFilename, *pszNewFileName; + + if (dat->send) + limit = dat->transferStatus.totalFiles; + else + limit = dat->transferStatus.currentFileNumber; + + // Loop over all transfered files and add them to the menu + for (int i = 0; i < limit; i++) { + pszFilename = _tcsrchr(files[i], '\\'); + if (pszFilename == NULL) + pszFilename = files[i]; + else + pszFilename++; + + if (pszFilename) { + size_t cbFileNameLen = _tcslen(pszFilename); + + pszNewFileName = (TCHAR*)mir_alloc(cbFileNameLen * 2 * sizeof(TCHAR)); + TCHAR *p = pszNewFileName; + for (size_t pszlen = 0; pszlen < cbFileNameLen; pszlen++) { + *p++ = pszFilename[pszlen]; + if (pszFilename[pszlen] == '&') + *p++ = '&'; + } + *p = '\0'; + AppendMenu(hMenu, MF_STRING, i + 10, pszNewFileName); + mir_free(pszNewFileName); + } + } + } + + 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, NULL); + CheckDlgButton(hwndDlg, IDC_OPENFILE, BST_UNCHECKED); + DestroyMenu(hMenu); + + if (ret == 1) { + TCHAR *path = dat->transferStatus.tszWorkingDir; + if (!path || !path[0]) { + path = NEWTSTR_ALLOCA(dat->transferStatus.tszCurrentFile); + TCHAR *p = _tcsrchr(path, '\\'); + if (p) + *p = 0; + } + + if (path) ShellExecute(NULL, _T("open"), path, NULL, NULL, SW_SHOW); + } + else if (ret && CheckVirusScanned(hwndDlg, dat, ret)) + ShellExecute(NULL, NULL, files[ret - 10], NULL, NULL, SW_SHOW); + } + break; + + case M_FILEEXISTSDLGREPLY: + EnableWindow(hwndDlg, TRUE); + { + PROTOFILERESUME *pfr = (PROTOFILERESUME*)lParam; + TCHAR *szOriginalFilename = (TCHAR*)wParam; + char *szProto = GetContactProto(dat->hContact); + + switch (pfr->action) { + case FILERESUME_CANCEL: + if (dat->fs) CallContactService(dat->hContact, PSS_FILECANCEL, (WPARAM)dat->fs, 0); + dat->fs = NULL; + mir_free(szOriginalFilename); + if (pfr->szFilename) mir_free((char*)pfr->szFilename); + mir_free(pfr); + return 0; + case FILERESUME_RESUMEALL: + case FILERESUME_OVERWRITEALL: + dat->resumeBehaviour = pfr->action; + pfr->action &= ~FILERESUMEF_ALL; + break; + case FILERESUME_RENAMEALL: + pfr->action = FILERESUME_RENAME; + { + TCHAR *pszExtension, *pszFilename; + if ((pszFilename = _tcsrchr(szOriginalFilename, '\\')) == NULL) pszFilename = szOriginalFilename; + if ((pszExtension = _tcsrchr(pszFilename + 1, '.')) == NULL) pszExtension = pszFilename + lstrlen(pszFilename); + if (pfr->szFilename) mir_free((TCHAR*)pfr->szFilename); + size_t size = (pszExtension - szOriginalFilename) + 21 + lstrlen(pszExtension); + pfr->szFilename = (TCHAR*)mir_alloc(sizeof(TCHAR)*size); + for (int i = 1;; i++) { + mir_sntprintf((TCHAR*)pfr->szFilename, size, _T("%.*s (%u)%s"), pszExtension - szOriginalFilename, szOriginalFilename, i, pszExtension); + if (_taccess(pfr->szFilename, 0) != 0) + break; + } + } + break; + } + mir_free(szOriginalFilename); + CallProtoService(szProto, PS_FILERESUMET, (WPARAM)dat->fs, (LPARAM)pfr); + if (pfr->szFilename) mir_free((char*)pfr->szFilename); + mir_free(pfr); + } + break; + + case HM_RECVEVENT: + { + ACKDATA *ack = (ACKDATA*)lParam; + if (ack->hProcess != dat->fs) break; + if (ack->type != ACKTYPE_FILE) break; + if (ack->hContact != dat->hContact) break; + + if (dat->waitingForAcceptance) { + SetTimer(hwndDlg, 1, 1000, NULL); + dat->waitingForAcceptance = 0; + } + + switch (ack->result) { + case ACKRESULT_SENTREQUEST: SetFtStatus(hwndDlg, LPGENT("Decision sent"), FTS_TEXT); break; + case ACKRESULT_CONNECTING: SetFtStatus(hwndDlg, LPGENT("Connecting..."), FTS_TEXT); break; + case ACKRESULT_CONNECTPROXY: SetFtStatus(hwndDlg, LPGENT("Connecting to proxy..."), FTS_TEXT); break; + case ACKRESULT_CONNECTED: SetFtStatus(hwndDlg, LPGENT("Connected"), FTS_TEXT); break; + case ACKRESULT_LISTENING: SetFtStatus(hwndDlg, LPGENT("Waiting for connection..."), FTS_TEXT); break; + case ACKRESULT_INITIALISING: SetFtStatus(hwndDlg, LPGENT("Initializing..."), FTS_TEXT); break; + case ACKRESULT_NEXTFILE: + SetFtStatus(hwndDlg, LPGENT("Moving to next file..."), FTS_TEXT); + SetDlgItemTextA(hwndDlg, IDC_FILENAME, ""); + if (dat->transferStatus.currentFileNumber == 1 && dat->transferStatus.totalFiles > 1 && !dat->send) + SetOpenFileButtonStyle(GetDlgItem(hwndDlg, IDC_OPENFILE), 1); + if (dat->transferStatus.currentFileNumber != -1 && dat->files && !dat->send && db_get_b(NULL, "SRFile", "UseScanner", VIRUSSCAN_DISABLE) == VIRUSSCAN_DURINGDL) { + if (GetFileAttributes(dat->files[dat->transferStatus.currentFileNumber])&FILE_ATTRIBUTE_DIRECTORY) + PostMessage(hwndDlg, M_VIRUSSCANDONE, dat->transferStatus.currentFileNumber, 0); + else { + virusscanthreadstartinfo *vstsi; + vstsi = (struct virusscanthreadstartinfo*)mir_alloc(sizeof(struct virusscanthreadstartinfo)); + vstsi->hwndReply = hwndDlg; + vstsi->szFile = mir_tstrdup(dat->files[dat->transferStatus.currentFileNumber]); + vstsi->returnCode = dat->transferStatus.currentFileNumber; + forkthread((void(*)(void*))RunVirusScannerThread, 0, vstsi); + } + } + break; + + case ACKRESULT_FILERESUME: + UpdateProtoFileTransferStatus(&dat->transferStatus, (PROTOFILETRANSFERSTATUS*)ack->lParam); + { + PROTOFILETRANSFERSTATUS *fts = &dat->transferStatus; + SetFilenameControls(hwndDlg, dat, fts); + if (_taccess(fts->tszCurrentFile, 0)) + break; + + SetFtStatus(hwndDlg, LPGENT("File already exists"), FTS_TEXT); + if (dat->resumeBehaviour == FILERESUME_ASK) { + TDlgProcFileExistsParam param = { hwndDlg, fts }; + ShowWindow(hwndDlg, SW_SHOWNORMAL); + CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_FILEEXISTS), hwndDlg, DlgProcFileExists, (LPARAM)¶m); + EnableWindow(hwndDlg, FALSE); + } + else { + PROTOFILERESUME *pfr = (PROTOFILERESUME*)mir_alloc(sizeof(PROTOFILERESUME)); + pfr->action = dat->resumeBehaviour; + pfr->szFilename = NULL; + PostMessage(hwndDlg, M_FILEEXISTSDLGREPLY, (WPARAM)mir_tstrdup(fts->tszCurrentFile), (LPARAM)pfr); + } + } + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, 1); + return TRUE; + + case ACKRESULT_DATA: + { + PROTOFILETRANSFERSTATUS *fts = (PROTOFILETRANSFERSTATUS*)ack->lParam; + TCHAR str[64], str2[64], szSizeDone[32], szSizeTotal[32];//, *contactName; + + if (dat->fileVirusScanned == NULL) + dat->fileVirusScanned = (int*)mir_calloc(sizeof(int) * fts->totalFiles); + + // This needs to be here - otherwise we get holes in the files array + if (!dat->send) { + if (dat->files == NULL) + dat->files = (TCHAR**)mir_calloc((fts->totalFiles + 1) * sizeof(TCHAR*)); + if (fts->currentFileNumber < fts->totalFiles && dat->files[fts->currentFileNumber] == NULL) + dat->files[fts->currentFileNumber] = PFTS_StringToTchar(fts->flags, fts->tszCurrentFile); + } + + /* HACK: for 0.3.3, limit updates to around 1.1 ack per second */ + if (fts->totalProgress != fts->totalBytes && GetTickCount() < (dat->dwTicks + 650)) + break; // the last update was less than a second ago! + dat->dwTicks = GetTickCount(); + + // Update local transfer status with data from protocol + UpdateProtoFileTransferStatus(&dat->transferStatus, fts); + fts = &dat->transferStatus; + + bool firstTime = false; + if ((GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_ALLFILESPROGRESS), GWL_STYLE) & WS_VISIBLE) == 0) { + SetFtStatus(hwndDlg, (fts->flags & PFTS_SENDING) ? LPGENT("Sending...") : LPGENT("Receiving..."), FTS_PROGRESS); + SetFilenameControls(hwndDlg, dat, fts); + firstTime = true; + } + + const unsigned long lastPos = SendDlgItemMessage(hwndDlg, IDC_ALLFILESPROGRESS, PBM_GETPOS, 0, 0); + const unsigned long nextPos = fts->totalBytes ? (BIGI(100) * fts->totalProgress / fts->totalBytes) : 0; + if (lastPos != nextPos || firstTime) { + SendDlgItemMessage(hwndDlg, IDC_ALLFILESPROGRESS, PBM_SETPOS, nextPos, 0); + mir_sntprintf(str, SIZEOF(str), _T("%u%%"), nextPos); + SetDlgItemText(hwndDlg, IDC_ALLPRECENTS, str); + } + + int units; + GetSensiblyFormattedSize(fts->totalBytes, szSizeTotal, SIZEOF(szSizeTotal), 0, 1, &units); + GetSensiblyFormattedSize(fts->totalProgress, szSizeDone, SIZEOF(szSizeDone), units, 0, NULL); + mir_sntprintf(str, SIZEOF(str), _T("%s/%s"), szSizeDone, szSizeTotal); + str2[0] = 0; + GetDlgItemText(hwndDlg, IDC_ALLTRANSFERRED, str2, SIZEOF(str2)); + if (_tcscmp(str, str2)) + SetDlgItemText(hwndDlg, IDC_ALLTRANSFERRED, str); + } + break; + + case ACKRESULT_SUCCESS: + case ACKRESULT_FAILED: + case ACKRESULT_DENIED: + HideProgressControls(hwndDlg); + KillTimer(hwndDlg, 1); + if (!dat->send) + SetOpenFileButtonStyle(GetDlgItem(hwndDlg, IDC_OPENFILE), 1); + SetDlgItemText(hwndDlg, IDCANCEL, TranslateT("Close")); + if (dat->hNotifyEvent) + UnhookEvent(dat->hNotifyEvent); + dat->hNotifyEvent = NULL; + + if (ack->result == ACKRESULT_DENIED) { + dat->fs = NULL; /* protocol will free structure */ + SkinPlaySound("FileDenied"); + SetFtStatus(hwndDlg, LPGENT("File transfer denied"), FTS_TEXT); + } + else if (ack->result == ACKRESULT_FAILED) { + dat->fs = NULL; /* protocol will free structure */ + SkinPlaySound("FileFailed"); + SetFtStatus(hwndDlg, LPGENT("File transfer failed"), FTS_TEXT); + } + else { + SkinPlaySound("FileDone"); + if (dat->send) { + dat->fs = NULL; /* protocol will free structure */ + SetFtStatus(hwndDlg, LPGENT("Transfer completed."), FTS_TEXT); + + DBEVENTINFO dbei = { 0 }; + FillSendData(dat, dbei); + db_event_add(dat->hContact, &dbei); + if (dbei.pBlob) + mir_free(dbei.pBlob); + dat->files = NULL; //protocol library frees this + } + else { + SetFtStatus(hwndDlg, + (dat->transferStatus.totalFiles == 1) ? + LPGENT("Transfer completed, open file.") : + LPGENT("Transfer completed, open folder."), + FTS_OPEN); + + int useScanner = db_get_b(NULL, "SRFile", "UseScanner", VIRUSSCAN_DISABLE); + if (useScanner != VIRUSSCAN_DISABLE) { + struct virusscanthreadstartinfo *vstsi; + vstsi = (struct virusscanthreadstartinfo*)mir_alloc(sizeof(struct virusscanthreadstartinfo)); + vstsi->hwndReply = hwndDlg; + if (useScanner == VIRUSSCAN_DURINGDL) { + vstsi->returnCode = dat->transferStatus.currentFileNumber; + if (GetFileAttributes(dat->files[dat->transferStatus.currentFileNumber])&FILE_ATTRIBUTE_DIRECTORY) { + PostMessage(hwndDlg, M_VIRUSSCANDONE, vstsi->returnCode, 0); + mir_free(vstsi); + vstsi = NULL; + } + else vstsi->szFile = mir_tstrdup(dat->files[dat->transferStatus.currentFileNumber]); + } + else { + vstsi->szFile = mir_tstrdup(dat->transferStatus.tszWorkingDir); + vstsi->returnCode = -1; + } + SetFtStatus(hwndDlg, LPGENT("Scanning for viruses..."), FTS_TEXT); + if (vstsi) + forkthread((void(*)(void*))RunVirusScannerThread, 0, vstsi); + } + else dat->fs = NULL; /* protocol will free structure */ + + dat->transferStatus.currentFileNumber = dat->transferStatus.totalFiles; + } // else dat->send + + } // else ack->result + + PostMessage(GetParent(hwndDlg), WM_FT_COMPLETED, ack->result, (LPARAM)hwndDlg); + break; + } // switch ack->result + } // case HM_RECVEVENT + 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 = NULL; /* protocol will free structure */ + SetFtStatus(hwndDlg, LPGENT("Transfer and virus scan complete"), FTS_TEXT); + } + } + break; + + case WM_SIZE: + { + UTILRESIZEDIALOG urd = { 0 }; + urd.cbSize = sizeof(urd); + urd.hwndDlg = hwndDlg; + urd.hInstance = hInst; + urd.lpTemplate = MAKEINTRESOURCEA(IDD_FILETRANSFERINFO); + urd.pfnResizer = FileTransferDlgResizer; + CallService(MS_UTILS_RESIZEDIALOG, 0, (LPARAM)&urd); + } + RedrawWindow(GetDlgItem(hwndDlg, IDC_ALLTRANSFERRED), NULL, NULL, RDW_INVALIDATE | RDW_NOERASE); + RedrawWindow(GetDlgItem(hwndDlg, IDC_ALLSPEED), NULL, NULL, RDW_INVALIDATE | RDW_NOERASE); + RedrawWindow(GetDlgItem(hwndDlg, IDC_CONTACTNAME), NULL, NULL, RDW_INVALIDATE | RDW_NOERASE); + RedrawWindow(GetDlgItem(hwndDlg, IDC_STATUS), NULL, NULL, RDW_INVALIDATE | RDW_NOERASE); + break; + + case WM_DESTROY: + KillTimer(hwndDlg, 1); + + HFONT hFont = (HFONT)SendDlgItemMessage(hwndDlg, IDC_CONTACTNAME, WM_GETFONT, 0, 0); + DeleteObject(hFont); + + Button_FreeIcon_IcoLib(hwndDlg, IDC_CONTACT); + Button_FreeIcon_IcoLib(hwndDlg, IDC_OPENFILE); + Button_FreeIcon_IcoLib(hwndDlg, IDCANCEL); + + FreeFileDlgData(dat); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0); + break; + } + return FALSE; +} + +void FreeFileDlgData(FileDlgData* dat) +{ + if (dat == NULL) + return; + + if (dat->fs) + CallContactService(dat->hContact, PSS_FILECANCEL, (WPARAM)dat->fs, 0); + if (dat->hPreshutdownEvent) + UnhookEvent(dat->hPreshutdownEvent); + if (dat->hNotifyEvent) + UnhookEvent(dat->hNotifyEvent); + + FreeProtoFileTransferStatus(&dat->transferStatus); + FreeFilesMatrix(&dat->files); + + mir_free(dat->fileVirusScanned); + if (dat->hIcon) + DestroyIcon(dat->hIcon); + if (dat->hIconFolder) + DestroyIcon(dat->hIconFolder); + mir_free(dat); +} -- cgit v1.2.3