diff options
author | Gluzskiy Alexandr <sss123next@list.ru> | 2009-10-13 05:04:06 +0300 |
---|---|---|
committer | Gluzskiy Alexandr <sss123next@list.ru> | 2009-10-13 05:04:06 +0300 |
commit | 227022d9ed977c75196725502847e0b371e4e879 (patch) | |
tree | 6fe79f5ae836fe4a974db459553eb6b46a1bf8eb /spamfilter/path.c | |
parent | 23d6d3e482927c13294f204b34ce23c6f445e8ac (diff) |
Diffstat (limited to 'spamfilter/path.c')
-rw-r--r-- | spamfilter/path.c | 541 |
1 files changed, 541 insertions, 0 deletions
diff --git a/spamfilter/path.c b/spamfilter/path.c new file mode 100644 index 0000000..b829c68 --- /dev/null +++ b/spamfilter/path.c @@ -0,0 +1,541 @@ +/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+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 ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+// -- Includes
+#include "common.h"
+
+
+// -----------------------------------------
+
+
+BOOL PPreparePathForWrite(HWND hwndDlg, const WCHAR* pszPath, BOOL bAskDirCreate, BOOL bContainsFileName)
+{
+ // Using SHPathPrepareForWrite on Win2000+ (best, only if avail)
+ {
+ HRESULT (STDAPICALLTYPE *MySHPathPrepareForWrite)(HWND, IUnknown*, LPCTSTR, DWORD);
+
+ #if defined(UNICODE)
+ *(FARPROC*)&MySHPathPrepareForWrite = GetProcAddress(GetModuleHandle(_T("USER32")), "SHPathPrepareForWriteW");
+ #else
+ *(FARPROC*)&MySHPathPrepareForWrite = GetProcAddress(GetModuleHandle(_T("USER32")), "SHPathPrepareForWriteA");
+ #endif
+
+ if (MySHPathPrepareForWrite)
+ {
+ DWORD dwFlags = SHPPFW_NOWRITECHECK; // Not impl anyway
+
+ if (bContainsFileName)
+ dwFlags |= SHPPFW_IGNOREFILENAME;
+
+ dwFlags |= bAskDirCreate ? SHPPFW_ASKDIRCREATE : SHPPFW_DIRCREATE;
+
+ return SUCCEEDED(MySHPathPrepareForWrite(hwndDlg, NULL, (LPCTSTR)pszPath, dwFlags));
+ }
+ }
+
+ // Emulating SHPathPrepareForWrite:
+ // Using SHCreateDirectoryEx on WinME
+ // And: Using emulated version of SHCreateDirectoryEx on Win95/98
+ {
+ WCHAR* pszDir;
+ BOOL bReturn = FALSE;
+
+ pszDir = mir_wstrdup(pszPath);
+ if (!pszDir) return FALSE;
+
+ if (bContainsFileName)
+ PathRemoveFileSpec((LPWSTR)pszDir);
+
+ // No dialog is emulated, instead always behave as
+ // if "No" was clicked
+ if (bAskDirCreate)
+ return FALSE;
+
+ // Create all sub directories
+ {
+ int (STDAPICALLTYPE *MySHCreateDirectoryEx)(HWND, LPCTSTR, SECURITY_ATTRIBUTES*);
+
+ #if defined(UNICODE)
+ *(FARPROC*)&MySHCreateDirectoryEx = (FARPROC)GetProcAddress(GetModuleHandle(_T("SHELL32")), "SHCreateDirectoryExW");
+ #else
+ *(FARPROC*)&MySHCreateDirectoryEx = (FARPROC)GetProcAddress(GetModuleHandle(_T("SHELL32")), "SHCreateDirectoryExA");
+ #endif
+
+ if (MySHCreateDirectoryEx)
+ {
+ int iRet = (SHCreateDirectoryEx(hwndDlg, pszDir, NULL) == ERROR_SUCCESS);
+ bReturn = ((iRet == ERROR_SUCCESS) || (iRet == ERROR_ALREADY_EXISTS));
+
+ } else {
+
+ int iSlashOcc;
+ int iAbsSlashOcc;
+ WCHAR* pszSlash;
+ WCHAR szDirTemp[MAX_PATH];
+ WCHAR szDirOutput[MAX_PATH];
+
+ ZeroMemory(&szDirTemp, sizeof(szDirTemp));
+ ZeroMemory(&szDirOutput, sizeof(szDirOutput));
+
+ // Skip drive letter
+ pszSlash = StrChr(pszDir, _T('\\')); // Search for the first :'\\'
+
+ if (pszSlash != NULL) // does not contain any slashs
+ {
+ iSlashOcc = (int)(pszSlash-pszDir+1); // Pointer arithmetic
+ StrCpyN(szDirTemp, pszDir+iSlashOcc, lstrlen(pszDir)-iSlashOcc); // Pointer arithmetic
+ iAbsSlashOcc = iSlashOcc;
+
+ bReturn = TRUE;
+ pszSlash = szDirTemp;
+ while (pszSlash)
+ {
+ pszSlash = StrChr(szDirTemp, _T('\\'));
+
+ iSlashOcc = (int)(pszSlash-szDirTemp+1); // Pointer arithmetic
+ iAbsSlashOcc = iAbsSlashOcc + iSlashOcc;
+
+ StrCpyN(szDirOutput, pszPath, iAbsSlashOcc); // Pointer arithmetic
+
+ StrCpyN(szDirTemp, szDirTemp+iSlashOcc, lstrlen(szDirTemp)-iSlashOcc); // Pointer arithmetic
+ ZeroMemory((PBYTE)szDirTemp+((lstrlen(szDirTemp)-iSlashOcc)*sizeof(WCHAR)), iSlashOcc*sizeof(WCHAR));
+
+ bReturn = (CreateDirectory(szDirOutput, NULL) && bReturn);
+ }
+ }
+ }
+ }
+
+ mir_free(pszDir);
+ return bReturn;
+ }
+}
+
+
+BOOL PIsValidFile(const WCHAR* pszFileName, const WCHAR* aszFileExtensions[], int nFileExtensions, const WCHAR* aszContentTypes[], int nContentTypes)
+{
+ BOOL bIsOk = FALSE;
+ int i;
+
+ if (!pszFileName) return FALSE;
+
+ // Check file extensions
+ for (i=0; i<nFileExtensions; i++)
+ {
+ bIsOk = (StrCmpI(PathFindExtension(pszFileName), aszFileExtensions[i]) == 0);
+ if (bIsOk) break;
+ }
+
+ if (!bIsOk)
+ {
+ // Check content types
+ for (i=0; i<nContentTypes; i++)
+ {
+ bIsOk = PathIsContentType(pszFileName, aszContentTypes[i]);
+ if (bIsOk) break;
+ }
+
+ if (!bIsOk)
+ return FALSE;
+ }
+
+ // Check if the file name is actually a directory
+ if (PathIsDirectory(pszFileName))
+ return FALSE;
+
+ // Finally check if file is present
+ return PathFileExists(pszFileName);
+}
+
+
+void PMakePathPretty(WCHAR* pszPath, DWORD dwFlags)
+{
+ WCHAR szBuf[MAX_PATH];
+ WCHAR szRelativeTo[MAX_PATH];
+
+ if (!pszPath)
+ return;
+
+ if (!PConstructLocalPath(szRelativeTo, CSIDL_EXT_EXECUTABLE, NULL, NULL, NULL))
+ szRelativeTo[0] = _T('\0');
+
+ // Create absolute path if path is relative
+ if (PathIsRelative(pszPath))
+ {
+ if (PathCombine(szBuf, szRelativeTo, pszPath))
+ {
+ mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
+ dwFlags |= PC_ABSOLUTERELATIVE; // Convert back after making pretty
+ }
+ }
+
+ // Make pretty
+ {
+ if (PathCanonicalize(szBuf, pszPath))
+ mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
+
+ // Convert slightly wrong chars
+ ReplaceSubStringWithStringBuf(pszPath, 0, _T("/"), _T("\\"), TRUE, FALSE);
+ ReplaceSubStringWithStringBuf(pszPath, 0, _T("\\\\"), _T("\\"), TRUE, FALSE);
+ ReplaceSubStringWithStringBuf(pszPath, 0, _T("\""), NULL, TRUE, FALSE);
+
+ /*
+ {
+ int i;
+
+ // Remove wildcard characters
+ if (dwFlags&PC_ALLOW_WILDCARDS)
+ for (i=lstrlen(pszPath); i>=0; i--)
+ if (PathGetCharType(pszPath[i])&GCT_WILD)
+ RemoveSubStr(pszPath, i, 1);
+
+ // Remove disallowed TCHARs
+ for (i=lstrlen(pszPath); i>=0; i--)
+ if (PathGetCharType(pszPath[i])&GCT_INVALID)
+ RemoveSubStr(pszPath, i, 1);
+ }
+ */
+
+ PathRemoveBlanks(pszPath);
+ PathUnquoteSpaces(pszPath);
+
+ // Upper case drive TCHAR
+ if (PathGetDriveNumber(pszPath) != -1)
+ CharUpperBuff(pszPath, 1);
+
+ // Make it use the long path name (Win98+/Win2000+)
+ {
+ DWORD (WINAPI *MyGetLongPathName)(LPCTSTR, LPCTSTR, DWORD);
+
+ #if defined(UNICODE)
+ *(FARPROC*)&MyGetLongPathName = GetProcAddress(GetModuleHandle(_T("KERNEL32")), "GetLongPathNameW");
+ #else
+ *(FARPROC*)&MyGetLongPathName = GetProcAddress(GetModuleHandle(_T("KERNEL32")), "GetLongPathNameA");
+ #endif
+
+ if (MyGetLongPathName)
+ {
+ if (MyGetLongPathName(pszPath, pszPath, MAX_PATH) == 0)
+ {
+ // Try to remove file name and see if it works then
+ mir_sntprintf(szBuf, ARRAYSIZE(szBuf), _T("%s"), pszPath);
+
+ if (PathRemoveFileSpec(szBuf) && (MyGetLongPathName(szBuf, szBuf, ARRAYSIZE(szBuf)) != 0))
+ {
+ PathAppend(szBuf, PathFindFileName(pszPath));
+ mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
+ }
+ }
+ }
+ }
+
+ // Lower case path if all upper case (only if user activated this feature for Windows-Explorer)
+ {
+ SHELLFLAGSTATE sfs;
+ SHGetSettings(&sfs, SSF_DONTPRETTYPATH);
+
+ if (!sfs.fDontPrettyPath)
+ PathMakePretty(pszPath);
+ }
+ }
+
+ // Make relative
+ if (dwFlags&PC_ABSOLUTERELATIVE)
+ {
+ if (PathRelativePathTo(szBuf, szRelativeTo, FILE_ATTRIBUTE_DIRECTORY, pszPath, FILE_ATTRIBUTE_NORMAL))
+ {
+ mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
+
+ // Remove backslash in front -> does not belong there (causes by PathRelativePathTo)
+ if ((pszPath[0] == _T('\\')) || (pszPath[0] == _T('/')))
+ MoveMemory(pszPath, CharNext(pszPath), (lstrlen(CharNext(pszPath))+1)*sizeof(WCHAR));
+ }
+
+ // Miranda Utils contains a quite less featured implementation of relative paths
+ // (not all cases are captured, does not support Unicode, too)
+ //if (CallService(MS_UTILS_PATHTORELATIVE, (WPARAM)pszPath, (LPARAM)szBuf) == 0)
+ // mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
+ }
+
+ // Environment strings
+ if (dwFlags&PC_ENVIRONMENTSTRINGS)
+ {
+ BOOL (STDAPICALLTYPE *MyPathUnExpandEnvStrings)(LPCTSTR, LPTSTR, UINT);
+
+ // PathUnExpandEnvStrings is Win98/2000+
+ #if defined(UNICODE)
+ *(FARPROC*)&MyPathUnExpandEnvStrings = (FARPROC)GetProcAddress(GetModuleHandle(_T("SHLWAPI")), "PathUnExpandEnvStringsW");
+ #else
+ *(FARPROC*)&MyPathUnExpandEnvStrings = (FARPROC)GetProcAddress(GetModuleHandle(_T("SHLWAPI")), "PathUnExpandEnvStringsA");
+ #endif
+
+ if (MyPathUnExpandEnvStrings)
+ if (MyPathUnExpandEnvStrings(pszPath, szBuf, MAX_PATH))
+ mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
+ }
+}
+
+
+DWORD PMakePathUsable(WCHAR* pszPath)
+{
+ WCHAR szBuf[MAX_PATH];
+ DWORD dwFlags = 0;
+
+ if (!pszPath)
+ return dwFlags;
+
+ PathUnquoteSpaces(pszPath);
+
+ // Environment strings
+ {
+ if (ExpandEnvironmentStrings(pszPath, szBuf, ARRAYSIZE(szBuf)) != 0)
+ {
+ // Success?
+ if (StrCmp(pszPath, szBuf) != 0)
+ dwFlags |= PC_ENVIRONMENTSTRINGS;
+
+ mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
+ }
+ }
+
+ // Absolute/relative path
+ {
+ WCHAR szRelativeTo[MAX_PATH];
+ PConstructLocalPath(szRelativeTo, CSIDL_EXT_EXECUTABLE, NULL, NULL, NULL);
+
+ // Miranda Utils contains not a very good implementation of relative paths
+ // (not all cases are captured)
+ //(CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)szBuf, (LPARAM)pszPath) != lstrlenA(szBuf))
+
+ // Create absolute path if path is relative
+ if (PathIsRelative(pszPath))
+ {
+ if (PathCombine(szBuf, szRelativeTo, pszPath))
+ {
+ dwFlags |= PC_ABSOLUTERELATIVE;
+ mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
+ }
+ }
+ }
+
+ return dwFlags;
+}
+
+
+
+BOOL PConstructLocalPath(WCHAR* pszReturn, int nMainFolder, const WCHAR* pszSubFolders, const WCHAR* pszFileName, const WCHAR* pszOptFileExtension)
+{
+ // pszReturn muss MAX_PATH groß sein
+ if (!pszReturn) return FALSE;
+
+ pszReturn[0] = _T('\0');
+
+ switch (nMainFolder)
+ {
+ case CSIDL_EXT_MIRANDAPROFILE:
+ {
+ // Profile directory of Miranda's database
+ WCHAR szBuf[MAX_PATH];
+
+ if (CallService(MS_DB_GETPROFILEPATH, (WPARAM)ARRAYSIZE(szBuf), (LPARAM)szBuf) != 0)
+ return FALSE;
+
+ #if defined(UNICODE)
+ {
+ WCHAR* pszBuf = (WCHAR*)mir_utf8encodeW(szBuf);
+ if (!pszBuf) return FALSE;
+
+ mir_sntprintf(pszReturn, MAX_PATH, _T("%s"), pszBuf);
+ mir_free(pszBuf);
+ }
+ #else
+ mir_sntprintf(pszReturn, MAX_PATH, _T("%s"), szBuf);
+ #endif
+
+ break;
+ }
+
+ case CSIDL_EXT_MODULE:
+ {
+ // Current DLL's directory
+ if (GetModuleFileName(hInstance, pszReturn, MAX_PATH) == 0)
+ return FALSE;
+
+ PathRemoveFileSpec(pszReturn);
+ break;
+ }
+
+ case CSIDL_EXT_EXECUTABLE:
+ {
+ // Current executable path
+ if (GetModuleFileName(NULL, pszReturn, MAX_PATH) == 0)
+ return FALSE;
+
+ PathRemoveFileSpec(pszReturn);
+ break;
+ }
+
+ case CSIDL_EXT_TEMP:
+ {
+ // Temp directory
+ if (GetTempPath(MAX_PATH, pszReturn) == 0)
+ return FALSE;
+ break;
+ }
+
+ case CSIDL_EXT_CURRENT:
+ {
+ // Current directory
+ if (GetCurrentDirectory(MAX_PATH, pszReturn) == 0)
+ return FALSE;
+ break;
+ }
+
+ default:
+ {
+ // CSIDL directory
+ if (!SHGetSpecialFolderPath(NULL, pszReturn, nMainFolder, FALSE))
+ return FALSE;
+
+ break;
+ }
+ }
+
+ if (!PathAddBackslash(pszReturn))
+ return FALSE;
+
+ if (pszSubFolders)
+ {
+ if (!PathAppend(pszReturn, pszSubFolders))
+ return FALSE;
+
+ if (!PathAddBackslash(pszReturn))
+ return FALSE;
+ }
+
+ if (pszFileName)
+ if (!PathAppend(pszReturn, pszFileName))
+ return FALSE;
+
+ if (pszFileName && pszOptFileExtension)
+ if (!PathAddExtension(pszReturn, pszOptFileExtension))
+ return FALSE;
+
+ return TRUE;
+}
+
+// Move files or whole folder from module to destination directory
+BOOL PInstallFile(const WCHAR* pszFileName, const WCHAR* pszDestDir)
+{
+ BOOL bReturn;
+ WCHAR szFileFrom[MAX_PATH+1];
+ WCHAR szFileTo[MAX_PATH+1];
+
+ if (!pszFileName) return FALSE;
+ PConstructLocalPath(szFileFrom, CSIDL_EXT_MODULE, NULL, pszFileName, NULL);
+ if (!PathFileExists(szFileFrom)) return FALSE;
+ mir_sntprintf(szFileTo, ARRAYSIZE(szFileTo), _T("%s"), pszDestDir);
+
+ if (PathIsDirectory(szFileFrom))
+ {
+ SHFILEOPSTRUCT sfo;
+
+ ZeroMemory(&sfo, sizeof(sfo));
+ sfo.fFlags = FOF_MULTIDESTFILES|FOF_NOERRORUI|FOF_NOCONFIRMATION|FOF_NOCONFIRMMKDIR|FOF_SILENT;
+ sfo.wFunc = FO_MOVE;
+ szFileFrom[lstrlen(szFileFrom)+1] = _T('\0');
+ sfo.pFrom = szFileFrom;
+ szFileTo[lstrlen(szFileTo)+1] = _T('\0');
+ sfo.pTo = szFileTo;
+ bReturn = (SHFileOperation(&sfo) == 0);
+
+ } else {
+ PathAppend(szFileTo, pszFileName);
+
+ DeleteFile(szFileTo);
+ bReturn = MoveFile(szFileFrom, szFileTo); // MoveFile does only support directories limitedly
+ }
+
+ return bReturn;
+}
+
+BOOL PInstallDLLFile(const WCHAR* pszFileName, BOOL bIgnoreLanguage, BOOL bIgnoreOpSystem)
+{
+ DWORD dwErr;
+ WCHAR szSrcDir[MAX_PATH];
+ WCHAR szDestDir[MAX_PATH];
+ WCHAR szTmpFile[MAX_PATH];
+ UINT uTmpFileSize = ARRAYSIZE(szTmpFile);
+
+ if (!pszFileName) return FALSE;
+
+ // Test if file-to-be-installed exists
+ PConstructLocalPath(szSrcDir, CSIDL_EXT_MODULE, NULL, pszFileName, NULL);
+ if (!PathFileExists(szSrcDir)) return FALSE;
+
+ // Source: module dir (Plugins directory)
+ PConstructLocalPath(szSrcDir, CSIDL_EXT_MODULE, NULL, NULL, NULL);
+
+ // Destination: app dir
+ PConstructLocalPath(szDestDir, CSIDL_EXT_EXECUTABLE, NULL, NULL, NULL);
+
+ // Install DLL using version verfication
+ szTmpFile[0] = _T('\0'); // needs to be empty (docs)
+ dwErr = VerInstallFile(0, (WCHAR*)pszFileName, (WCHAR*)pszFileName, szSrcDir, szDestDir, szDestDir, szTmpFile, &uTmpFileSize);
+ if (!(dwErr&VIF_WRITEPROT) && !(dwErr&VIF_SRCOLD))
+ {
+ // Ignore language/codepage of the DLL (install anyway) -> useful for DLLs without user interface
+ if (bIgnoreLanguage)
+ if ((dwErr&VIF_DIFFLANG) && (dwErr&VIF_DIFFCODEPG))
+ dwErr = VerInstallFile(VIFF_FORCEINSTALL, (WCHAR*)pszFileName, (WCHAR*)pszFileName, szSrcDir, szDestDir, szDestDir, szTmpFile, &uTmpFileSize);
+
+ // Ignore operating system of the DLL (install anyway) -> useful for DLLs that work anyway
+ if (bIgnoreOpSystem)
+ if (dwErr&VIF_DIFFTYPE)
+ dwErr = VerInstallFile(VIFF_FORCEINSTALL, (WCHAR*)pszFileName, (WCHAR*)pszFileName, szSrcDir, szDestDir, szDestDir, szTmpFile, &uTmpFileSize);
+ }
+
+ // Delete temp file
+ if ((dwErr&VIF_TEMPFILE) && !(dwErr&VIF_BUFFTOOSMALL)) // buffer too small for temp file
+ DeleteFile(szTmpFile);
+
+ // Test for success
+ PConstructLocalPath(szDestDir, CSIDL_EXT_EXECUTABLE, NULL, pszFileName, NULL);
+ if (PathFileExists(szDestDir))
+ {
+ PConstructLocalPath(szSrcDir, CSIDL_EXT_MODULE, NULL, pszFileName, NULL);
+ DeleteFile(szSrcDir);
+ return TRUE;
+ }
+
+ // Debug output
+ OutputDebugString(_T("Spam Filter: VersionInfo DLL (VERSION.DLL) could not be used to install DLL file.\r\n"));
+
+ // Source: module dir (Plugins directory)
+ PConstructLocalPath(szSrcDir, CSIDL_EXT_MODULE, NULL, pszFileName, NULL);
+ // Destination: app dir
+ PConstructLocalPath(szDestDir, CSIDL_EXT_EXECUTABLE, NULL, pszFileName, NULL);
+
+ // Copy without version checking [danger!]
+ DeleteFile(szDestDir);
+ return MoveFile(szSrcDir, szDestDir);
+}
\ No newline at end of file |