From 1ed1296853c671fc557599c6daf5fba88d52a21f Mon Sep 17 00:00:00 2001 From: George Hazan Date: Fri, 6 Jul 2012 14:44:59 +0000 Subject: + stdauth + stdfile; NEWSTR_ALLOCA / NEWTSTR_ALLOCA / NEWWSTR_ALLOCA moved to m_system.h git-svn-id: http://svn.miranda-ng.org/main/trunk@792 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- src/core/stdfile/filerecvdlg.cpp | 442 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 442 insertions(+) create mode 100644 src/core/stdfile/filerecvdlg.cpp (limited to 'src/core/stdfile/filerecvdlg.cpp') diff --git a/src/core/stdfile/filerecvdlg.cpp b/src/core/stdfile/filerecvdlg.cpp new file mode 100644 index 0000000000..33a27d80ff --- /dev/null +++ b/src/core/stdfile/filerecvdlg.cpp @@ -0,0 +1,442 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2009 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include "commonheaders.h" +#include "file.h" + +#define MAX_MRU_DIRS 5 + +static BOOL CALLBACK ClipSiblingsChildEnumProc(HWND hwnd, LPARAM) +{ + SetWindowLongPtr(hwnd, GWL_STYLE, GetWindowLongPtr(hwnd, GWL_STYLE)|WS_CLIPSIBLINGS); + return TRUE; +} + +static void GetLowestExistingDirName(const TCHAR *szTestDir, TCHAR *szExistingDir, int cchExistingDir) +{ + DWORD dwAttributes; + TCHAR *pszLastBackslash; + + lstrcpyn(szExistingDir, szTestDir, cchExistingDir); + while ((dwAttributes = GetFileAttributes(szExistingDir)) != INVALID_FILE_ATTRIBUTES && !(dwAttributes&FILE_ATTRIBUTE_DIRECTORY)) { + pszLastBackslash = _tcsrchr(szExistingDir, '\\'); + if (pszLastBackslash == NULL) {*szExistingDir = '\0'; break;} + *pszLastBackslash = '\0'; + } + if (szExistingDir[0] == '\0') GetCurrentDirectory(cchExistingDir, szExistingDir); +} + +static const TCHAR InvalidFilenameChars[] = _T("\\/:*?\"<>|"); +void RemoveInvalidFilenameChars(TCHAR *tszString) +{ + size_t i; + if (tszString) { + for (i = _tcscspn(tszString, InvalidFilenameChars); tszString[i]; i+=_tcscspn(tszString+i+1, InvalidFilenameChars)+1) + if (tszString[i] >= 0) + tszString[i] = _T('_'); + } +} + +static const TCHAR InvalidPathChars[] = _T("*?\"<>|"); // "\/:" are excluded as they are allowed in file path +void RemoveInvalidPathChars(TCHAR *tszString) +{ + size_t i; + if (tszString) { + for (i = _tcscspn(tszString, InvalidPathChars); tszString[i]; i+=_tcscspn(tszString+i+1, InvalidPathChars)+1) + if (tszString[i] >= 0) + tszString[i] = _T('_'); + } +} + +static INT CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LPARAM pData) +{ + TCHAR szDir[MAX_PATH]; + switch(uMsg) { + case BFFM_INITIALIZED: + SendMessage(hwnd, BFFM_SETSELECTION, TRUE, pData); + break; + case BFFM_SELCHANGED: + if (SHGetPathFromIDList((LPITEMIDLIST) lp , szDir)) + SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)szDir); + break; + } + return 0; +} + +int BrowseForFolder(HWND hwnd, TCHAR *szPath) +{ + BROWSEINFO bi = {0}; + LPITEMIDLIST pidlResult; + + bi.hwndOwner = hwnd; + bi.pszDisplayName = szPath; + bi.lpszTitle = TranslateT("Select Folder"); + bi.ulFlags = BIF_NEWDIALOGSTYLE|BIF_EDITBOX|BIF_RETURNONLYFSDIRS; // Use this combo instead of BIF_USENEWUI + bi.lpfn = BrowseCallbackProc; + bi.lParam = (LPARAM)szPath; + + pidlResult = SHBrowseForFolder(&bi); + if (pidlResult) { + SHGetPathFromIDList(pidlResult, szPath); + lstrcat(szPath, _T("\\")); + CoTaskMemFree(pidlResult); + } + return pidlResult != NULL; +} + +static REPLACEVARSARRAY sttVarsToReplace[] = +{ + { (TCHAR*)"///", (TCHAR*)"//" }, + { (TCHAR*)"//", (TCHAR*)"/" }, + { (TCHAR*)"()", (TCHAR*)"" }, + { NULL, NULL } +}; + +static void patchDir(TCHAR* str, size_t strSize) +{ + REPLACEVARSDATA dat = { 0 }; + dat.cbSize = sizeof(dat); + dat.dwFlags = RVF_TCHAR; + dat.variables = sttVarsToReplace; + + TCHAR* result = (TCHAR*)CallService(MS_UTILS_REPLACEVARS, (WPARAM)str, (LPARAM)&dat); + if (result) { + _tcsncpy(str, result, strSize); + mir_free(result); + } + + size_t len = lstrlen(str); + if (len+1 < strSize && str[len-1] != '\\') + lstrcpy(str+len, _T("\\")); +} + +void GetContactReceivedFilesDir(HANDLE hContact, TCHAR *szDir, int cchDir, BOOL patchVars) +{ + DBVARIANT dbv; + TCHAR szTemp[MAX_PATH]; + szTemp[0] = 0; + + if ( !DBGetContactSettingTString(NULL, "SRFile", "RecvFilesDirAdv", &dbv)) { + if (lstrlen(dbv.ptszVal) > 0) + lstrcpyn(szTemp, dbv.ptszVal, SIZEOF(szTemp)); + DBFreeVariant(&dbv); + } + + if ( !szTemp[0]) + + mir_sntprintf(szTemp, SIZEOF(szTemp), _T("%%mydocuments%%\\%s\\%%userid%%"), TranslateT("My Received Files")); + + + if (hContact) { + REPLACEVARSDATA dat = { 0 }; + REPLACEVARSARRAY rvaVarsToReplace[4]; + rvaVarsToReplace[0].lptzKey = _T("nick"); + rvaVarsToReplace[0].lptzValue = mir_tstrdup((TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)); + rvaVarsToReplace[1].lptzKey = _T("userid"); + rvaVarsToReplace[1].lptzValue = GetContactID(hContact); + rvaVarsToReplace[2].lptzKey = _T("proto"); + rvaVarsToReplace[2].lptzValue = mir_a2t((char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0)); + rvaVarsToReplace[3].lptzKey = NULL; + rvaVarsToReplace[3].lptzValue = NULL; + for (int i=0; i < (SIZEOF(rvaVarsToReplace)-1);i++) + RemoveInvalidFilenameChars(rvaVarsToReplace[i].lptzValue); + + dat.cbSize = sizeof(dat); + dat.dwFlags = RVF_TCHAR; + dat.variables = rvaVarsToReplace; + dat.hContact = hContact; + TCHAR* result = (TCHAR*)CallService(MS_UTILS_REPLACEVARS, (WPARAM)szTemp, (LPARAM)&dat); + if (result) { + _tcsncpy(szTemp, result, SIZEOF(szTemp)); + mir_free(result); + for (int i=0; i < (SIZEOF(rvaVarsToReplace)-1);i++) + mir_free(rvaVarsToReplace[i].lptzValue); + } } + + if (patchVars) + patchDir(szTemp, SIZEOF(szTemp)); + RemoveInvalidPathChars(szTemp); + lstrcpyn(szDir, szTemp, cchDir); +} + +void GetReceivedFilesDir(TCHAR *szDir, int cchDir) +{ + DBVARIANT dbv; + TCHAR szTemp[MAX_PATH]; + szTemp[0] = 0; + + if ( !DBGetContactSettingTString(NULL, "SRFile", "RecvFilesDirAdv", &dbv)) { + if (lstrlen(dbv.ptszVal) > 0) + lstrcpyn(szTemp, dbv.ptszVal, SIZEOF(szTemp)); + DBFreeVariant(&dbv); + } + + if ( !szTemp[0]) + + mir_sntprintf(szTemp, SIZEOF(szTemp), _T("%%mydocuments%%\\%s"), TranslateT("My Received Files")); + + + patchDir(szTemp, SIZEOF(szTemp)); + RemoveInvalidPathChars(szTemp); + lstrcpyn(szDir, szTemp, cchDir); +} + +INT_PTR CALLBACK DlgProcRecvFile(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + struct FileDlgData *dat; + + dat = (struct FileDlgData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + switch (msg) { + case WM_INITDIALOG: { + TCHAR *contactName; + TCHAR szPath[450]; + CLISTEVENT* cle = (CLISTEVENT*)lParam; + + TranslateDialogDefault(hwndDlg); + + dat = (struct FileDlgData*)mir_calloc(sizeof(struct FileDlgData)); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat); + dat->hContact = cle->hContact; + dat->hDbEvent = cle->hDbEvent; + dat->hPreshutdownEvent = HookEventMessage(ME_SYSTEM_PRESHUTDOWN, hwndDlg, M_PRESHUTDOWN); + dat->dwTicks = GetTickCount(); + + EnumChildWindows(hwndDlg, ClipSiblingsChildEnumProc, 0); + + Window_SetIcon_IcoLib(hwndDlg, SKINICON_EVENT_FILE); + Button_SetIcon_IcoLib(hwndDlg, IDC_ADD, SKINICON_OTHER_ADDCONTACT, LPGEN("Add Contact Permanently to List")); + Button_SetIcon_IcoLib(hwndDlg, IDC_DETAILS, SKINICON_OTHER_USERDETAILS, LPGEN("View User's Details")); + Button_SetIcon_IcoLib(hwndDlg, IDC_HISTORY, SKINICON_OTHER_HISTORY, LPGEN("View User's History")); + Button_SetIcon_IcoLib(hwndDlg, IDC_USERMENU, SKINICON_OTHER_DOWNARROW, LPGEN("User Menu")); + + contactName = pcli->pfnGetContactDisplayName(dat->hContact, 0); + SetDlgItemText(hwndDlg, IDC_FROM, contactName); + GetContactReceivedFilesDir(dat->hContact, szPath, SIZEOF(szPath), TRUE); + SetDlgItemText(hwndDlg, IDC_FILEDIR, szPath); + { + int i; + char idstr[32]; + DBVARIANT dbv; + + if (shAutoComplete) + shAutoComplete(GetWindow(GetDlgItem(hwndDlg, IDC_FILEDIR), GW_CHILD), 1); + + for (i=0;ihContact, (LPARAM)dat->hDbEvent); + { + DBEVENTINFO dbei = {0}; + TCHAR datetimestr[64]; + char buf[540]; + + dbei.cbSize = sizeof(dbei); + dbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)dat->hDbEvent, 0); + dbei.pBlob = (PBYTE)mir_alloc(dbei.cbBlob); + CallService(MS_DB_EVENT_GET, (WPARAM)dat->hDbEvent, (LPARAM)&dbei); + dat->fs = cle->lParam ? (HANDLE)cle->lParam : (HANDLE)*(PDWORD)dbei.pBlob; + lstrcpynA(buf, (char*)dbei.pBlob+4, min(dbei.cbBlob+1, SIZEOF(buf))); + TCHAR* ptszFileName = DbGetEventStringT(&dbei, buf); + SetDlgItemText(hwndDlg, IDC_FILENAMES, ptszFileName); + mir_free(ptszFileName); + lstrcpynA(buf, (char*)dbei.pBlob+4+strlen((char*)dbei.pBlob+4)+1, min((int)(dbei.cbBlob-4-strlen((char*)dbei.pBlob+4)), SIZEOF(buf))); + TCHAR* ptszDescription = DbGetEventStringT(&dbei, buf); + SetDlgItemText(hwndDlg, IDC_MSG, ptszDescription); + mir_free(ptszDescription); + mir_free(dbei.pBlob); + + tmi.printTimeStamp(NULL, dbei.timestamp, _T("t d"), datetimestr, SIZEOF(datetimestr), 0); + SetDlgItemText(hwndDlg, IDC_DATE, datetimestr); + } + { + char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)dat->hContact, 0); + if (szProto) { + CONTACTINFO ci; + int hasName = 0; + char buf[128]; + ZeroMemory(&ci, sizeof(ci)); + + ci.cbSize = sizeof(ci); + ci.hContact = dat->hContact; + ci.szProto = szProto; + ci.dwFlag = CNF_UNIQUEID; + if ( !CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci)) { + switch(ci.type) { + case CNFT_ASCIIZ: + hasName = 1; + mir_snprintf(buf, SIZEOF(buf), "%s", ci.pszVal); + mir_free(ci.pszVal); + break; + case CNFT_DWORD: + hasName = 1; + mir_snprintf(buf, SIZEOF(buf), "%u", ci.dVal); + break; + } } + if (hasName) + SetDlgItemTextA(hwndDlg, IDC_NAME, buf); + else + SetDlgItemText(hwndDlg, IDC_NAME, contactName); + } } + + if (DBGetContactSettingByte(dat->hContact, "CList", "NotOnList", 0)) { + RECT rcBtn1, rcBtn2, rcDateCtrl; + GetWindowRect(GetDlgItem(hwndDlg, IDC_ADD), &rcBtn1); + GetWindowRect(GetDlgItem(hwndDlg, IDC_USERMENU), &rcBtn2); + GetWindowRect(GetDlgItem(hwndDlg, IDC_DATE), &rcDateCtrl); + SetWindowPos(GetDlgItem(hwndDlg, IDC_DATE), 0, 0, 0, rcDateCtrl.right-rcDateCtrl.left-(rcBtn2.left-rcBtn1.left), rcDateCtrl.bottom-rcDateCtrl.top, SWP_NOZORDER|SWP_NOMOVE); + } + else if (DBGetContactSettingByte(NULL, "SRFile", "AutoAccept", 0)) { + //don't check auto-min here to fix BUG#647620 + PostMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDOK, BN_CLICKED), (LPARAM)GetDlgItem(hwndDlg, IDOK)); + } + if ( !DBGetContactSettingByte(dat->hContact, "CList", "NotOnList", 0)) + ShowWindow(GetDlgItem(hwndDlg, IDC_ADD), SW_HIDE); + return TRUE; + } + + case WM_MEASUREITEM: + return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam); + + case WM_DRAWITEM: + { LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lParam; + if (dis->hwndItem == GetDlgItem(hwndDlg, IDC_PROTOCOL)) { + char *szProto; + + szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)dat->hContact, 0); + if (szProto) { + HICON hIcon; + + hIcon = (HICON)CallProtoService(szProto, PS_LOADICON, PLI_PROTOCOL|PLIF_SMALL, 0); + if (hIcon) { + DrawIconEx(dis->hDC, dis->rcItem.left, dis->rcItem.top, hIcon, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0, NULL, DI_NORMAL); + DestroyIcon(hIcon); + } } } } + return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam); + + case WM_COMMAND: + if (CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), MPCF_CONTACTMENU), (LPARAM)dat->hContact)) + break; + + switch (LOWORD(wParam)) { + case IDC_FILEDIRBROWSE: + { + TCHAR szDirName[MAX_PATH], szExistingDirName[MAX_PATH]; + + GetDlgItemText(hwndDlg, IDC_FILEDIR, szDirName, SIZEOF(szDirName)); + GetLowestExistingDirName(szDirName, szExistingDirName, SIZEOF(szExistingDirName)); + if (BrowseForFolder(hwndDlg, szExistingDirName)) + SetDlgItemText(hwndDlg, IDC_FILEDIR, szExistingDirName); + } + break; + + case IDOK: + { //most recently used directories + TCHAR szRecvDir[MAX_PATH], szDefaultRecvDir[MAX_PATH]; + GetDlgItemText(hwndDlg, IDC_FILEDIR, szRecvDir, SIZEOF(szRecvDir)); + RemoveInvalidPathChars(szRecvDir); + GetContactReceivedFilesDir(NULL, szDefaultRecvDir, SIZEOF(szDefaultRecvDir), TRUE); + if (_tcsnicmp(szRecvDir, szDefaultRecvDir, lstrlen(szDefaultRecvDir))) { + char idstr[32]; + int i; + DBVARIANT dbv; + for (i = MAX_MRU_DIRS-2;i>=0;i--) { + mir_snprintf(idstr, SIZEOF(idstr), "MruDir%d", i); + if (DBGetContactSettingTString(NULL, "SRFile", idstr, &dbv)) continue; + mir_snprintf(idstr, SIZEOF(idstr), "MruDir%d", i+1); + DBWriteContactSettingTString(NULL, "SRFile", idstr, dbv.ptszVal); + DBFreeVariant(&dbv); + } + DBWriteContactSettingTString(NULL, "SRFile", idstr, szRecvDir); + } + } + EnableWindow(GetDlgItem(hwndDlg, IDC_FILENAMES), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_MSG), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_FILEDIR), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_FILEDIRBROWSE), FALSE); + + GetDlgItemText(hwndDlg, IDC_FILEDIR, dat->szSavePath, SIZEOF(dat->szSavePath)); + GetDlgItemText(hwndDlg, IDC_FILE, dat->szFilenames, SIZEOF(dat->szFilenames)); + GetDlgItemText(hwndDlg, IDC_MSG, dat->szMsg, SIZEOF(dat->szMsg)); + dat->hwndTransfer = FtMgr_AddTransfer(dat); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0); + //check for auto-minimize here to fix BUG#647620 + if (DBGetContactSettingByte(NULL, "SRFile", "AutoAccept", 0) && DBGetContactSettingByte(NULL, "SRFile", "AutoMin", 0)) { + ShowWindow(hwndDlg, SW_HIDE); + ShowWindow(hwndDlg, SW_SHOWMINNOACTIVE); + } + DestroyWindow(hwndDlg); + break; + + case IDCANCEL: + if (dat->fs) CallContactService(dat->hContact, PSS_FILEDENYT, (WPARAM)dat->fs, (LPARAM)TranslateT("Cancelled")); + dat->fs = NULL; /* the protocol will free the handle */ + DestroyWindow(hwndDlg); + break; + + case IDC_ADD: + { ADDCONTACTSTRUCT acs = {0}; + + acs.handle = dat->hContact; + acs.handleType = HANDLE_CONTACT; + acs.szProto = ""; + CallService(MS_ADDCONTACT_SHOW, (WPARAM)hwndDlg, (LPARAM)&acs); + if ( !DBGetContactSettingByte(dat->hContact, "CList", "NotOnList", 0)) + ShowWindow(GetDlgItem(hwndDlg, IDC_ADD), SW_HIDE); + } + break; + + case IDC_USERMENU: + { RECT rc; + HMENU hMenu = (HMENU)CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM)dat->hContact, 0); + GetWindowRect((HWND)lParam, &rc); + TrackPopupMenu(hMenu, 0, rc.left, rc.bottom, 0, hwndDlg, NULL); + DestroyMenu(hMenu); + } + break; + + case IDC_DETAILS: + CallService(MS_USERINFO_SHOWDIALOG, (WPARAM)dat->hContact, 0); + break; + + case IDC_HISTORY: + CallService(MS_HISTORY_SHOWCONTACTHISTORY, (WPARAM)dat->hContact, 0); + break; + } + break; + + case WM_DESTROY: + Window_FreeIcon_IcoLib(hwndDlg); + Button_FreeIcon_IcoLib(hwndDlg, IDC_ADD); + Button_FreeIcon_IcoLib(hwndDlg, IDC_DETAILS); + Button_FreeIcon_IcoLib(hwndDlg, IDC_HISTORY); + Button_FreeIcon_IcoLib(hwndDlg, IDC_USERMENU); + + if (dat) FreeFileDlgData(dat); + break; + } + return FALSE; +} -- cgit v1.2.3