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/file.cpp | 487 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 487 insertions(+) create mode 100644 src/core/stdfile/file.cpp (limited to 'src/core/stdfile/file.cpp') diff --git a/src/core/stdfile/file.cpp b/src/core/stdfile/file.cpp new file mode 100644 index 0000000000..45a84aaeaf --- /dev/null +++ b/src/core/stdfile/file.cpp @@ -0,0 +1,487 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2009 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "commonheaders.h" +#include "file.h" + +TCHAR* PFTS_StringToTchar(int flags, const PROTOCHAR* s); +int PFTS_CompareWithTchar(PROTOFILETRANSFERSTATUS* ft, const PROTOCHAR* s, TCHAR* r); + +static HANDLE hSRFileMenuItem; + +TCHAR *GetContactID(HANDLE hContact) +{ + TCHAR *theValue = {0}; + char *szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + if (DBGetContactSettingByte(hContact, szProto, "ChatRoom", 0) == 1) { + DBVARIANT dbv; + if ( !DBGetContactSettingTString(hContact, szProto, "ChatRoomID", &dbv)) { + theValue = (TCHAR *)mir_tstrdup(dbv.ptszVal); + DBFreeVariant(&dbv); + return theValue; + } } + else { + CONTACTINFO ci = {0}; + ci.cbSize = sizeof(ci); + ci.hContact = hContact; + ci.szProto = szProto; + ci.dwFlag = CNF_UNIQUEID | CNF_TCHAR; + if ( !CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci)) { + switch (ci.type) { + case CNFT_ASCIIZ: + return (TCHAR *)ci.pszVal; + break; + case CNFT_DWORD: + return _itot(ci.dVal, (TCHAR *)mir_alloc(sizeof(TCHAR)*32), 10); + break; + } } } + return NULL; +} + +static INT_PTR SendFileCommand(WPARAM wParam, LPARAM) +{ + struct FileSendData fsd; + fsd.hContact = (HANDLE)wParam; + fsd.ppFiles = NULL; + CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_FILESEND), NULL, DlgProcSendFile, (LPARAM)&fsd); + return 0; +} + +static INT_PTR SendSpecificFiles(WPARAM wParam, LPARAM lParam) +{ + FileSendData fsd; + fsd.hContact = (HANDLE)wParam; + + char** ppFiles = (char**)lParam; + int count = 0; + while (ppFiles[count] != NULL) + count++; + + fsd.ppFiles = (const TCHAR**)alloca((count+1) * sizeof(void*)); + for (int i=0; i < count; i++) + fsd.ppFiles[i] = (const TCHAR*)mir_a2t(ppFiles[i]); + fsd.ppFiles[ count ] = NULL; + + CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_FILESEND), NULL, DlgProcSendFile, (LPARAM)&fsd); + for (int j = 0; j < count; j++) + mir_free((void*)fsd.ppFiles[j]); + return 0; +} + +static INT_PTR SendSpecificFilesT(WPARAM wParam, LPARAM lParam) +{ + FileSendData fsd; + fsd.hContact = (HANDLE)wParam; + fsd.ppFiles = (const TCHAR**)lParam; + CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_FILESEND), NULL, DlgProcSendFile, (LPARAM)&fsd); + return 0; +} + +static INT_PTR GetReceivedFilesFolder(WPARAM wParam, LPARAM lParam) +{ + TCHAR buf[MAX_PATH]; + GetContactReceivedFilesDir((HANDLE)wParam, buf, MAX_PATH, TRUE); + char* dir = mir_t2a(buf); + lstrcpynA((char*)lParam, dir, MAX_PATH); + mir_free(dir); + return 0; +} + +static INT_PTR RecvFileCommand(WPARAM, LPARAM lParam) +{ + CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_FILERECV), NULL, DlgProcRecvFile, lParam); + return 0; +} + +void PushFileEvent(HANDLE hContact, HANDLE hdbe, LPARAM lParam) +{ + CLISTEVENT cle = {0}; + cle.cbSize = sizeof(cle); + cle.hContact = hContact; + cle.hDbEvent = hdbe; + cle.lParam = lParam; + if (DBGetContactSettingByte(NULL, "SRFile", "AutoAccept", 0) && !DBGetContactSettingByte(hContact, "CList", "NotOnList", 0)) { + CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_FILERECV), NULL, DlgProcRecvFile, (LPARAM)&cle); + } + else { + SkinPlaySound("RecvFile"); + + TCHAR szTooltip[256]; + mir_sntprintf(szTooltip, SIZEOF(szTooltip), TranslateT("File from %s"), pcli->pfnGetContactDisplayName(hContact, 0)); + cle.ptszTooltip = szTooltip; + + cle.flags |= CLEF_TCHAR; + cle.hIcon = LoadSkinIcon(SKINICON_EVENT_FILE); + cle.pszService = "SRFile/RecvFile"; + CallService(MS_CLIST_ADDEVENT, 0, (LPARAM)&cle); +} } + +static int FileEventAdded(WPARAM wParam, LPARAM lParam) +{ + DWORD dwSignature; + + DBEVENTINFO dbei = {0}; + dbei.cbSize = sizeof(dbei); + dbei.cbBlob = sizeof(DWORD); + dbei.pBlob = (PBYTE)&dwSignature; + CallService(MS_DB_EVENT_GET, lParam, (LPARAM)&dbei); + if (dbei.flags&(DBEF_SENT|DBEF_READ) || dbei.eventType != EVENTTYPE_FILE || dwSignature == 0) + return 0; + + PushFileEvent((HANDLE)wParam, (HANDLE)lParam, 0); + return 0; +} + +int SRFile_GetRegValue(HKEY hKeyBase, const TCHAR *szSubKey, const TCHAR *szValue, TCHAR *szOutput, int cbOutput) +{ + HKEY hKey; + DWORD cbOut = cbOutput; + + if (RegOpenKeyEx(hKeyBase, szSubKey, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS) + return 0; + + if (RegQueryValueEx(hKey, szValue, NULL, NULL, (PBYTE)szOutput, &cbOut) != ERROR_SUCCESS) { + RegCloseKey(hKey); + return 0; + } + + RegCloseKey(hKey); + return 1; +} + +void GetSensiblyFormattedSize(__int64 size, TCHAR *szOut, int cchOut, int unitsOverride, int appendUnits, int *unitsUsed) +{ + if ( !unitsOverride) { + if (size<1000) unitsOverride = UNITS_BYTES; + else if (size<100*1024) unitsOverride = UNITS_KBPOINT1; + else if (size<1024*1024) unitsOverride = UNITS_KBPOINT0; + else if (size<1024*1024*1024) unitsOverride = UNITS_MBPOINT2; + else unitsOverride = UNITS_GBPOINT3; + } + if (unitsUsed) *unitsUsed = unitsOverride; + switch(unitsOverride) { + case UNITS_BYTES: mir_sntprintf(szOut, cchOut, _T("%u%s%s"), (int)size, appendUnits?_T(" "):_T(""), appendUnits?TranslateT("bytes"):_T("")); break; + case UNITS_KBPOINT1: mir_sntprintf(szOut, cchOut, _T("%.1lf%s"), size/1024.0, appendUnits?_T(" KB"):_T("")); break; + case UNITS_KBPOINT0: mir_sntprintf(szOut, cchOut, _T("%u%s"), (int)(size/1024), appendUnits?_T(" KB"):_T("")); break; + case UNITS_GBPOINT3: mir_sntprintf(szOut, cchOut, _T("%.3f%s"), (size >> 20)/1024.0, appendUnits?_T(" GB"):_T("")); break; + default: mir_sntprintf(szOut, cchOut, _T("%.2lf%s"), size/1048576.0, appendUnits?_T(" MB"):_T("")); break; + } +} + +// Tripple redirection sucks but is needed to nullify the array pointer +void FreeFilesMatrix(TCHAR ***files) +{ + if (*files == NULL) + return; + + // Free each filename in the pointer array + TCHAR **pFile = *files; + while (*pFile != NULL) + { + mir_free(*pFile); + *pFile = NULL; + pFile++; + } + + // Free the array itself + mir_free(*files); + *files = NULL; +} + +void FreeProtoFileTransferStatus(PROTOFILETRANSFERSTATUS *fts) +{ + mir_free(fts->tszCurrentFile); + if (fts->ptszFiles) { + for (int i=0;itotalFiles;i++) mir_free(fts->ptszFiles[i]); + mir_free(fts->ptszFiles); + } + mir_free(fts->tszWorkingDir); +} + +void CopyProtoFileTransferStatus(PROTOFILETRANSFERSTATUS *dest, PROTOFILETRANSFERSTATUS *src) +{ + *dest = *src; + if (src->tszCurrentFile) dest->tszCurrentFile = PFTS_StringToTchar(src->flags, src->tszCurrentFile); + if (src->ptszFiles) { + dest->ptszFiles = (TCHAR**)mir_alloc(sizeof(TCHAR*)*src->totalFiles); + for (int i=0; i < src->totalFiles; i++) + dest->ptszFiles[i] = PFTS_StringToTchar(src->flags, src->ptszFiles[i]); + } + if (src->tszWorkingDir) dest->tszWorkingDir = PFTS_StringToTchar(src->flags, src->tszWorkingDir); + dest->flags &= ~PFTS_UTF; + dest->flags |= PFTS_TCHAR; +} + +void UpdateProtoFileTransferStatus(PROTOFILETRANSFERSTATUS *dest, PROTOFILETRANSFERSTATUS *src) +{ + dest->hContact = src->hContact; + dest->flags = src->flags; + if (dest->totalFiles != src->totalFiles) { + for (int i=0;itotalFiles;i++) mir_free(dest->ptszFiles[i]); + mir_free(dest->ptszFiles); + dest->ptszFiles = NULL; + dest->totalFiles = src->totalFiles; + } + if (src->ptszFiles) { + if ( !dest->ptszFiles) + dest->ptszFiles = (TCHAR**)mir_calloc(sizeof(TCHAR*)*src->totalFiles); + for (int i=0; i < src->totalFiles; i++) + if ( !dest->ptszFiles[i] || !src->ptszFiles[i] || PFTS_CompareWithTchar(src, src->ptszFiles[i], dest->ptszFiles[i])) { + mir_free(dest->ptszFiles[i]); + if (src->ptszFiles[i]) + dest->ptszFiles[i] = PFTS_StringToTchar(src->flags, src->ptszFiles[i]); + else + dest->ptszFiles[i] = NULL; + } + } + else if (dest->ptszFiles) { + for (int i=0; i < dest->totalFiles; i++) + mir_free(dest->ptszFiles[i]); + mir_free(dest->ptszFiles); + dest->ptszFiles = NULL; + } + + dest->currentFileNumber = src->currentFileNumber; + dest->totalBytes = src->totalBytes; + dest->totalProgress = src->totalProgress; + if (src->tszWorkingDir && ( !dest->tszWorkingDir || PFTS_CompareWithTchar(src, src->tszWorkingDir, dest->tszWorkingDir))) { + mir_free(dest->tszWorkingDir); + if (src->tszWorkingDir) + dest->tszWorkingDir = PFTS_StringToTchar(src->flags, src->tszWorkingDir); + else + dest->tszWorkingDir = NULL; + } + + if ( !dest->tszCurrentFile || !src->tszCurrentFile || PFTS_CompareWithTchar(src, src->tszCurrentFile, dest->tszCurrentFile)) { + mir_free(dest->tszCurrentFile); + if (src->tszCurrentFile) + dest->tszCurrentFile = PFTS_StringToTchar(src->flags, src->tszCurrentFile); + else + dest->tszCurrentFile = NULL; + } + dest->currentFileSize = src->currentFileSize; + dest->currentFileProgress = src->currentFileProgress; + dest->currentFileTime = src->currentFileTime; + dest->flags &= ~PFTS_UTF; + dest->flags |= PFTS_TCHAR; +} + +static void RemoveUnreadFileEvents(void) +{ + DBEVENTINFO dbei = {0}; + HANDLE hDbEvent, hContact; + + dbei.cbSize = sizeof(dbei); + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while (hContact) { + hDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDFIRSTUNREAD, (WPARAM)hContact, 0); + while (hDbEvent) { + dbei.cbBlob = 0; + CallService(MS_DB_EVENT_GET, (WPARAM)hDbEvent, (LPARAM)&dbei); + if ( !(dbei.flags&(DBEF_SENT|DBEF_READ)) && dbei.eventType == EVENTTYPE_FILE) + CallService(MS_DB_EVENT_MARKREAD, (WPARAM)hContact, (LPARAM)hDbEvent); + hDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDNEXT, (WPARAM)hDbEvent, 0); + } + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); + } +} + +static int SRFilePreBuildMenu(WPARAM wParam, LPARAM) +{ + CLISTMENUITEM mi = { 0 }; + mi.cbSize = sizeof(mi); + mi.flags = CMIM_FLAGS | CMIF_HIDDEN; + + char *szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0); + if (szProto != NULL) { + if ( CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_FILESEND) { + if ( CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_4, 0) & PF4_OFFLINEFILES) + mi.flags = CMIM_FLAGS; + else if (DBGetContactSettingWord((HANDLE)wParam, szProto, "Status", ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE) + mi.flags = CMIM_FLAGS; + } } + + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hSRFileMenuItem, (LPARAM)&mi); + return 0; +} + +static int SRFileModulesLoaded(WPARAM, LPARAM) +{ + CLISTMENUITEM mi = { 0 }; + mi.cbSize = sizeof(mi); + mi.position = -2000020000; + mi.icolibItem = GetSkinIconHandle(SKINICON_EVENT_FILE); + mi.pszName = LPGEN("&File"); + mi.pszService = MS_FILE_SENDFILE; + mi.flags = CMIF_ICONFROMICOLIB; + hSRFileMenuItem = Menu_AddContactMenuItem(&mi); + + RemoveUnreadFileEvents(); + return 0; +} + +INT_PTR FtMgrShowCommand(WPARAM, LPARAM) +{ + FtMgr_Show(true, true); + return 0; +} + +INT_PTR openContRecDir(WPARAM wparam, LPARAM) +{ + TCHAR szContRecDir[MAX_PATH]; + HANDLE hContact = (HANDLE)wparam; + GetContactReceivedFilesDir(hContact, szContRecDir, SIZEOF(szContRecDir), TRUE); + ShellExecute(0, _T("open"), szContRecDir, 0, 0, SW_SHOW); + return 0; +} + +INT_PTR openRecDir(WPARAM, LPARAM) +{ + TCHAR szContRecDir[MAX_PATH]; + GetReceivedFilesDir(szContRecDir, SIZEOF(szContRecDir)); + ShellExecute(0, _T("open"), szContRecDir, 0, 0, SW_SHOW); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +static void sttRecvCreateBlob(DBEVENTINFO& dbei, int fileCount, char** pszFiles, char* szDescr) +{ + dbei.cbBlob = sizeof(DWORD); + { + for (int i=0; i < fileCount; i++) + dbei.cbBlob += lstrlenA(pszFiles[i]) + 1; + } + + dbei.cbBlob += lstrlenA(szDescr) + 1; + + if ((dbei.pBlob = (BYTE*)mir_alloc(dbei.cbBlob)) == 0) + return; + + *(DWORD*)dbei.pBlob = 0; + BYTE* p = dbei.pBlob + sizeof(DWORD); + for (int i=0; i < fileCount; i++) { + strcpy((char*)p, pszFiles[i]); + p += lstrlenA(pszFiles[i]) + 1; + } + strcpy((char*)p, (szDescr == NULL) ? "" : szDescr); +} + +static INT_PTR Proto_RecvFile(WPARAM, LPARAM lParam) +{ + CCSDATA* ccs = (CCSDATA*)lParam; + PROTORECVEVENT* pre = (PROTORECVEVENT*)ccs->lParam; + char* szFile = pre->szMessage + sizeof(DWORD); + char* szDescr = szFile + strlen(szFile) + 1; + + // Suppress the standard event filter + if (pre->lParam != NULL) + *(DWORD*)pre->szMessage = 0; + + DBEVENTINFO dbei = { 0 }; + dbei.cbSize = sizeof(dbei); + dbei.szModule = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)ccs->hContact, 0); + dbei.timestamp = pre->timestamp; + dbei.flags = (pre->flags & PREF_CREATEREAD) ? DBEF_READ : 0; + dbei.flags |= (pre->flags & PREF_UTF) ? DBEF_UTF : 0; + dbei.eventType = EVENTTYPE_FILE; + dbei.cbBlob = (DWORD)(sizeof(DWORD) + strlen(szFile) + strlen(szDescr) + 2); + dbei.pBlob = (PBYTE)pre->szMessage; + HANDLE hdbe = (HANDLE)CallService(MS_DB_EVENT_ADD, (WPARAM)ccs->hContact, (LPARAM)&dbei); + + if (pre->lParam != NULL) + PushFileEvent(ccs->hContact, hdbe, pre->lParam); + return 0; +} + +static INT_PTR Proto_RecvFileT(WPARAM, LPARAM lParam) +{ + CCSDATA* ccs = (CCSDATA*)lParam; + PROTORECVFILET* pre = (PROTORECVFILET*)ccs->lParam; + if (pre->fileCount == 0) + return 0; + + DBEVENTINFO dbei = { 0 }; + dbei.cbSize = sizeof(dbei); + dbei.szModule = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)ccs->hContact, 0); + dbei.timestamp = pre->timestamp; + dbei.flags = (pre->flags & PREF_CREATEREAD) ? DBEF_READ : 0; + dbei.eventType = EVENTTYPE_FILE; + + char** pszFiles = (char**)alloca(pre->fileCount * sizeof(char*)); + { + for (int i=0; i < pre->fileCount; i++) + pszFiles[i] = Utf8EncodeT(pre->ptszFiles[i]); + } + char* szDescr = Utf8EncodeT(pre->tszDescription); + dbei.flags |= DBEF_UTF; + sttRecvCreateBlob(dbei, pre->fileCount, pszFiles, szDescr); + { + for (int i=0; i < pre->fileCount; i++) + mir_free(pszFiles[i]); + } + mir_free(szDescr); + + HANDLE hdbe = (HANDLE)CallService(MS_DB_EVENT_ADD, (WPARAM)ccs->hContact, (LPARAM)&dbei); + + PushFileEvent(ccs->hContact, hdbe, pre->lParam); + mir_free(dbei.pBlob); + return 0; +} + +int LoadSendRecvFileModule(void) +{ + CreateServiceFunction("FtMgr/Show", FtMgrShowCommand); + + CLISTMENUITEM mi = { 0 }; + mi.cbSize = sizeof(mi); + mi.flags = CMIF_ICONFROMICOLIB; + mi.icolibItem = GetSkinIconHandle(SKINICON_EVENT_FILE); + mi.position = 1900000000; + mi.pszName = LPGEN("File &Transfers..."); + mi.pszService = "FtMgr/Show"; //MS_PROTO_SHOWFTMGR; + Menu_AddMainMenuItem(&mi); + + HookEvent(ME_SYSTEM_MODULESLOADED, SRFileModulesLoaded); + HookEvent(ME_DB_EVENT_ADDED, FileEventAdded); + HookEvent(ME_OPT_INITIALISE, FileOptInitialise); + HookEvent(ME_CLIST_PREBUILDCONTACTMENU, SRFilePreBuildMenu); + + CreateServiceFunction(MS_PROTO_RECVFILE, Proto_RecvFile); + 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("SRFile/RecvFile", RecvFileCommand); + + CreateServiceFunction("SRFile/OpenContRecDir", openContRecDir); + CreateServiceFunction("SRFile/OpenRecDir", openRecDir); + + SkinAddNewSoundEx("RecvFile", LPGEN("File"), LPGEN("Incoming")); + SkinAddNewSoundEx("FileDone", LPGEN("File"), LPGEN("Complete")); + SkinAddNewSoundEx("FileFailed", LPGEN("File"), LPGEN("Error")); + SkinAddNewSoundEx("FileDenied", LPGEN("File"), LPGEN("Denied")); + return 0; +} -- cgit v1.2.3