/* Miranda IM: the free IM client for Microsoft* Windows* Copyright 2000-2009 Miranda ICQ/IM project, all portions of this codebase are copyrighted to the people listed in contributors.txt. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "commonheaders.h" #include "file.h" TCHAR* PFTS_StringToTchar( int flags, const PROTOCHAR* s ); int PFTS_CompareWithTchar( PROTOFILETRANSFERSTATUS* ft, const PROTOCHAR* s, TCHAR* r ); static HANDLE hSRFileMenuItem; static INT_PTR SendFileCommand(WPARAM wParam, LPARAM) { struct FileSendData fsd; fsd.hContact=(HANDLE)wParam; fsd.ppFiles=NULL; CreateDialogParam(hMirandaInst,MAKEINTRESOURCE(IDD_FILESEND),NULL,DlgProcSendFile,(LPARAM)&fsd); return 0; } static INT_PTR SendSpecificFiles(WPARAM wParam,LPARAM lParam) { FileSendData fsd; fsd.hContact=(HANDLE)wParam; #if defined( _UNICODE ) char** ppFiles = ( char** )lParam; int count = 0; while ( ppFiles[count] != NULL ) count++; fsd.ppFiles = (const TCHAR**)alloca(( count+1 ) * sizeof( void* )); for ( int i=0; i < count; i++ ) fsd.ppFiles[i] = ( const TCHAR* )mir_a2t( ppFiles[i] ); fsd.ppFiles[ count ] = NULL; #else fsd.ppFiles=(const char**)lParam; #endif CreateDialogParam(hMirandaInst,MAKEINTRESOURCE(IDD_FILESEND),NULL,DlgProcSendFile,(LPARAM)&fsd); #if defined( _UNICODE ) for ( int j=0; j < count; j++ ) mir_free(( void* )fsd.ppFiles[j] ); #endif return 0; } static INT_PTR SendSpecificFilesT(WPARAM wParam,LPARAM lParam) { FileSendData fsd; fsd.hContact=(HANDLE)wParam; fsd.ppFiles=(const TCHAR**)lParam; CreateDialogParam(hMirandaInst,MAKEINTRESOURCE(IDD_FILESEND),NULL,DlgProcSendFile,(LPARAM)&fsd); return 0; } static INT_PTR GetReceivedFilesFolder(WPARAM wParam,LPARAM lParam) { TCHAR buf[MAX_PATH]; GetContactReceivedFilesDir((HANDLE)wParam,buf,MAX_PATH,TRUE); char* dir = mir_t2a(buf); lstrcpynA((char*)lParam,dir,MAX_PATH); mir_free(dir); return 0; } static INT_PTR RecvFileCommand(WPARAM, LPARAM lParam) { CreateDialogParam(hMirandaInst,MAKEINTRESOURCE(IDD_FILERECV),NULL,DlgProcRecvFile,lParam); return 0; } void PushFileEvent( HANDLE hContact, HANDLE hdbe, LPARAM lParam ) { CLISTEVENT cle={0}; cle.cbSize = sizeof(cle); cle.hContact = hContact; cle.hDbEvent = hdbe; cle.lParam = lParam; if ( DBGetContactSettingByte(NULL,"SRFile","AutoAccept",0) && !DBGetContactSettingByte(hContact,"CList","NotOnList",0)) { CreateDialogParam(hMirandaInst,MAKEINTRESOURCE(IDD_FILERECV),NULL,DlgProcRecvFile,(LPARAM)&cle); } else { SkinPlaySound("RecvFile"); TCHAR szTooltip[256]; mir_sntprintf(szTooltip,SIZEOF(szTooltip),TranslateT("File from %s"), cli.pfnGetContactDisplayName( hContact, 0 )); cle.ptszTooltip = szTooltip; cle.flags |= CLEF_TCHAR; cle.hIcon = LoadSkinIcon( SKINICON_EVENT_FILE ); cle.pszService = "SRFile/RecvFile"; CallService(MS_CLIST_ADDEVENT,0,(LPARAM)&cle); } } static int FileEventAdded(WPARAM wParam,LPARAM lParam) { DWORD dwSignature; DBEVENTINFO dbei={0}; dbei.cbSize = sizeof(dbei); dbei.cbBlob = sizeof( DWORD ); dbei.pBlob = ( PBYTE )&dwSignature; CallService( MS_DB_EVENT_GET, lParam, ( LPARAM )&dbei ); if ( dbei.flags&(DBEF_SENT|DBEF_READ) || dbei.eventType != EVENTTYPE_FILE || dwSignature == 0 ) return 0; PushFileEvent(( HANDLE )wParam, ( HANDLE )lParam, 0 ); return 0; } int SRFile_GetRegValue(HKEY hKeyBase,const TCHAR *szSubKey,const TCHAR *szValue,TCHAR *szOutput,int cbOutput) { HKEY hKey; DWORD cbOut=cbOutput; if ( RegOpenKeyEx( hKeyBase,szSubKey,0,KEY_QUERY_VALUE,&hKey ) != ERROR_SUCCESS) return 0; if ( RegQueryValueEx( hKey,szValue,NULL,NULL,(PBYTE)szOutput, &cbOut ) != ERROR_SUCCESS ) { RegCloseKey(hKey); return 0; } RegCloseKey(hKey); return 1; } void GetSensiblyFormattedSize(__int64 size,TCHAR *szOut,int cchOut,int unitsOverride,int appendUnits,int *unitsUsed) { if(!unitsOverride) { if(size<1000) unitsOverride=UNITS_BYTES; else if(size<100*1024) unitsOverride=UNITS_KBPOINT1; else if(size<1024*1024) unitsOverride=UNITS_KBPOINT0; else if(size<1024*1024*1024) unitsOverride=UNITS_MBPOINT2; else unitsOverride=UNITS_GBPOINT3; } if(unitsUsed) *unitsUsed=unitsOverride; switch(unitsOverride) { case UNITS_BYTES: mir_sntprintf(szOut,cchOut,_T("%u%s%s"),(int)size,appendUnits?_T(" "):_T(""),appendUnits?TranslateT("bytes"):_T("")); break; case UNITS_KBPOINT1: mir_sntprintf(szOut,cchOut,_T("%.1lf%s"),size/1024.0,appendUnits?_T(" KB"):_T("")); break; case UNITS_KBPOINT0: mir_sntprintf(szOut,cchOut,_T("%u%s"),(int)(size/1024),appendUnits?_T(" KB"):_T("")); break; case UNITS_GBPOINT3: mir_sntprintf(szOut,cchOut,_T("%.3f%s"),(size >> 20)/1024.0,appendUnits?_T(" GB"):_T("")); break; default: mir_sntprintf(szOut,cchOut,_T("%.2lf%s"),size/1048576.0,appendUnits?_T(" MB"):_T("")); break; } } // Tripple redirection sucks but is needed to nullify the array pointer void FreeFilesMatrix(TCHAR ***files) { if (*files == NULL) return; // Free each filename in the pointer array TCHAR **pFile = *files; while (*pFile != NULL) { mir_free(*pFile); *pFile = NULL; pFile++; } // Free the array itself mir_free(*files); *files = NULL; } void FreeProtoFileTransferStatus(PROTOFILETRANSFERSTATUS *fts) { mir_free(fts->tszCurrentFile); if(fts->ptszFiles) { for( int i=0;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 = ( HANDLE )CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi); RemoveUnreadFileEvents(); return 0; } INT_PTR FtMgrShowCommand(WPARAM, LPARAM) { FtMgr_Show(true, true); return 0; } INT_PTR openContRecDir(WPARAM wparam, LPARAM) { TCHAR szContRecDir[MAX_PATH]; HANDLE hContact = (HANDLE)wparam; GetContactReceivedFilesDir(hContact, szContRecDir, SIZEOF(szContRecDir),TRUE); ShellExecute(0, _T("open"), szContRecDir, 0, 0, SW_SHOW); return 0; } INT_PTR openRecDir(WPARAM, LPARAM) { TCHAR szContRecDir[MAX_PATH]; GetReceivedFilesDir(szContRecDir, SIZEOF(szContRecDir)); ShellExecute(0, _T("open"), szContRecDir, 0, 0, SW_SHOW); return 0; } int LoadSendRecvFileModule(void) { CreateServiceFunction("FtMgr/Show", FtMgrShowCommand); CLISTMENUITEM mi = { 0 }; mi.cbSize = sizeof(mi); mi.flags = CMIF_ICONFROMICOLIB; mi.icolibItem = GetSkinIconHandle( SKINICON_EVENT_FILE ); mi.position = 1900000000; mi.pszName = LPGEN("File &Transfers..."); mi.pszService = "FtMgr/Show"; //MS_PROTO_SHOWFTMGR; CallService( MS_CLIST_ADDMAINMENUITEM, 0, ( LPARAM )&mi ); HookEvent(ME_SYSTEM_MODULESLOADED,SRFileModulesLoaded); HookEvent(ME_DB_EVENT_ADDED,FileEventAdded); HookEvent(ME_OPT_INITIALISE,FileOptInitialise); HookEvent(ME_CLIST_PREBUILDCONTACTMENU, SRFilePreBuildMenu); CreateServiceFunction(MS_FILE_SENDFILE,SendFileCommand); CreateServiceFunction(MS_FILE_SENDSPECIFICFILES,SendSpecificFiles); CreateServiceFunction(MS_FILE_SENDSPECIFICFILEST,SendSpecificFilesT); CreateServiceFunction(MS_FILE_GETRECEIVEDFILESFOLDER,GetReceivedFilesFolder); CreateServiceFunction("SRFile/RecvFile",RecvFileCommand); CreateServiceFunction("SRFile/OpenContRecDir",openContRecDir); CreateServiceFunction("SRFile/OpenRecDir",openRecDir); SkinAddNewSoundEx("RecvFile", "File", "Incoming"); SkinAddNewSoundEx("FileDone", "File", "Complete"); SkinAddNewSoundEx("FileFailed", "File", "Error"); SkinAddNewSoundEx("FileDenied", "File", "Denied"); return 0; }