summaryrefslogtreecommitdiff
path: root/spamfilter/logfile.c
diff options
context:
space:
mode:
Diffstat (limited to 'spamfilter/logfile.c')
-rw-r--r--spamfilter/logfile.c478
1 files changed, 478 insertions, 0 deletions
diff --git a/spamfilter/logfile.c b/spamfilter/logfile.c
new file mode 100644
index 0000000..7712119
--- /dev/null
+++ b/spamfilter/logfile.c
@@ -0,0 +1,478 @@
+/*
+
+"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 WriteToLogFile(const char* pszMsgTypeSection, const char* pszMsgTypeName, const WCHAR* pszUserName, const WCHAR* pszMsgContent, STRINGLIST* pslRecognition, DWORD dwResult)
+{
+ BOOL bReturn;
+
+ HANDLE hFile;
+ DWORD dwWritten; // For Windows 95/98/ME compatibility for WriteFile (parameter needed)
+
+ STRINGLIST* pslVariablesFromTo;
+ WCHAR szLogFile[MAX_PATH];
+
+ int iBuf;
+ WCHAR* pszBuf;
+
+ // Get file to log to
+ {
+ DBVARIANT dbv;
+ if (DBGetContactSettingTString(NULL, DB_MODULE_NAME, DB_SETTING_LOGFILE, &dbv) == 0)
+ {
+ mir_sntprintf(szLogFile, ARRAYSIZE(szLogFile), _T("%s"), dbv.pszVal);
+ DBFreeVariant(&dbv);
+ PMakePathUsable(szLogFile);
+ } else {
+ szLogFile[0] = _T('\0');
+ }
+ }
+
+ // Make sure the directory exists: SILENT!
+ PPreparePathForWrite(NULL, szLogFile, FALSE, TRUE);
+
+ // Open file
+ hFile = CreateFile(szLogFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ bReturn = (hFile != INVALID_HANDLE_VALUE);
+ if (!bReturn)
+ {
+ WCHAR* pszLastError = GetLastErrorDescription(GetLastError());
+
+ ShowInfoMessage(NIIF_ERROR, TranslateT("Spam Filter Error"), TranslateT("The log file \"%s\"\r\ncan not be written.\r\n\r\nProblem:\r\n%s\r\nPlease check the settings."), lstrlen(szLogFile)+lstrlen(pszLastError), (lstrlen(PathFindFileName(szLogFile))>0)?PathFindFileName(szLogFile):szLogFile, pszLastError?pszLastError:_T(""));
+ if (pszLastError) mir_free(pszLastError);
+
+ return FALSE;
+ }
+
+ // Variables list (From-To)
+ pslVariablesFromTo = SLNewList();
+
+ // %log_time%
+ iBuf = GetTimeFormat(GetThreadLocale(), 0, NULL, NULL, NULL, 0); // or: LOCALE_USER_DEFAULT
+ pszBuf = (WCHAR*)mir_alloc((iBuf+1)*sizeof(WCHAR));
+ GetTimeFormat(GetThreadLocale(), 0, NULL, NULL, pszBuf, iBuf); // or: LOCALE_USER_DEFAULT
+ SLAddItemPair(pslVariablesFromTo, _T("%log_time%"), pszBuf);
+ if (pszBuf) mir_free(pszBuf);
+
+ // %log_date%
+ iBuf = GetDateFormat(GetThreadLocale(), DATE_SHORTDATE, NULL, NULL, NULL, 0); // or: LOCALE_USER_DEFAULT
+ pszBuf = (WCHAR*)mir_alloc((iBuf+1)*sizeof(WCHAR));
+ GetDateFormat(GetThreadLocale(), DATE_SHORTDATE, NULL, NULL, pszBuf, iBuf); // or: LOCALE_USER_DEFAULT
+ SLAddItemPair(pslVariablesFromTo, _T("%log_date%"), pszBuf);
+ if (pszBuf) mir_free(pszBuf);
+
+ // %log_user%
+ SLAddItemPair(pslVariablesFromTo, _T("%log_user%"), pszUserName);
+
+ // %log_type%
+ EnterCriticalSection(&csMsgTypes); // thread safety
+ iBuf = GetMsgTypeID(pszMsgTypeSection, pszMsgTypeName);
+ pszBuf = (iBuf >= 0) ? pamtdMsgTypes[iBuf].ptszDescription : NULL;
+ SLAddItemPair(pslVariablesFromTo, _T("%log_type%"), pszBuf);
+ LeaveCriticalSection(&csMsgTypes); // thread safety
+
+ // %log_recognition%
+ pszBuf = SLConvertToString(pslRecognition, TranslateT(", "), FALSE, FALSE, NULL);
+ SLAddItemPair(pslVariablesFromTo, _T("%log_recognition%"), pszBuf);
+ if (pszBuf) SLFreeReturn(pszBuf);
+
+ // %log_result%
+ if (dwResult&SFF_MARKREAD)
+ pszBuf = TranslateT("Message marked read");
+ else if (dwResult&SFF_IGNORE)
+ pszBuf = TranslateT("Message deleted");
+ else
+ pszBuf = TranslateT("User ignored");
+ SLAddItemPair(pslVariablesFromTo, _T("%log_result%"), pszBuf);
+
+ // %log_message%
+ SLAddItemPair(pslVariablesFromTo, _T("%log_message%"), pszMsgContent);
+
+ // ##### XML format #####
+ if (PathMatchSpec(szLogFile, _T("*.xml")))
+ {
+ HANDLE hXSLFile;
+ WCHAR szXSLFile[MAX_PATH];
+
+ STRINGLIST* pslSpecialCharsFromTo;
+ char* pszUtf8;
+ WCHAR* pszBuf2;
+
+ // Create XSL file name
+ mir_sntprintf(szXSLFile, ARRAYSIZE(szXSLFile), _T("%s"), szLogFile);
+ PathRenameExtension(szXSLFile, _T(".xsl"));
+
+ // Construct XML special char replace filter
+ pslSpecialCharsFromTo = SLNewList();
+ SLAddItemPair(pslSpecialCharsFromTo, _T("&"), _T("&"));
+ SLAddItemPair(pslSpecialCharsFromTo, _T("<"), _T("&lt;"));
+ SLAddItemPair(pslSpecialCharsFromTo, _T(">"), _T("&gt;"));
+ SLAddItemPair(pslSpecialCharsFromTo, _T("'"), _T("&apos;"));
+ SLAddItemPair(pslSpecialCharsFromTo, _T("\""), _T("&quot;"));
+ SLAddItemPair(pslSpecialCharsFromTo, _T(" "), _T("&nbsp;&nbsp;"));// Only one single space is allowed (multiple must be replaced)
+
+ // Replace special chars in replacement variables
+ for (iBuf=SL_MIN_POS; iBuf<=SLGetMaxPos(pslVariablesFromTo); iBuf+=2)
+ {
+ pszBuf = ReplaceSubStringWithStringMultiple(SLGetItem(pslVariablesFromTo, iBuf), pslSpecialCharsFromTo, TRUE, FALSE, NULL);
+ SLChangeItem(pslVariablesFromTo, iBuf, pszBuf, FALSE);
+ if (pszBuf) mir_free(pszBuf);
+ }
+
+ // Write XSL stylesheet for XML (XSL-File)
+ hXSLFile = CreateFile(szXSLFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hXSLFile != INVALID_HANDLE_VALUE) // If file does not already exist
+ {
+ STRINGLIST* pslXSLFromTo = SLNewList();
+
+ // Translate file contents
+ // ", "
+ pszBuf = ReplaceSubStringWithStringMultiple(TranslateT(", "), pslSpecialCharsFromTo, TRUE, FALSE, NULL);
+ SLAddItemPair(pslXSLFromTo, _T(", "), pszBuf);
+ if (pszBuf) mir_free(pszBuf);
+
+ // "Received Spam"
+ pszBuf = ReplaceSubStringWithStringMultiple(TranslateT("Received Spam"), pslSpecialCharsFromTo, TRUE, FALSE, NULL);
+ SLAddItemPair(pslXSLFromTo, _T("Received Spam"), pszBuf);
+ if (pszBuf) mir_free(pszBuf);
+
+ // "Logged since"
+ pszBuf = ReplaceSubStringWithStringMultiple(TranslateT("Logged since"), pslSpecialCharsFromTo, TRUE, FALSE, NULL);
+ SLAddItemPair(pslXSLFromTo, _T("Logged since"), pszBuf);
+ if (pszBuf) mir_free(pszBuf);
+
+ // "Date/Time:"
+ pszBuf = ReplaceSubStringWithStringMultiple(TranslateT("Date/Time:"), pslSpecialCharsFromTo, TRUE, FALSE, NULL);
+ SLAddItemPair(pslXSLFromTo, _T("Date/Time:"), pszBuf);
+ if (pszBuf) mir_free(pszBuf);
+
+ // "User:"
+ pszBuf = ReplaceSubStringWithStringMultiple(TranslateT("User:"), pslSpecialCharsFromTo, TRUE, FALSE, NULL);
+ SLAddItemPair(pslXSLFromTo, _T("User:"), pszBuf);
+ if (pszBuf) mir_free(pszBuf);
+
+ // Type:
+ pszBuf = ReplaceSubStringWithStringMultiple(TranslateT("Type:"), pslSpecialCharsFromTo, TRUE, FALSE, NULL);
+ SLAddItemPair(pslXSLFromTo, _T("Type:"), pszBuf);
+ if (pszBuf) mir_free(pszBuf);
+
+ // "Recognition:"
+ pszBuf = ReplaceSubStringWithStringMultiple(TranslateT("Recognition:"), pslSpecialCharsFromTo, TRUE, FALSE, NULL);
+ SLAddItemPair(pslXSLFromTo, _T("Recognition:"), pszBuf);
+ if (pszBuf) mir_free(pszBuf);
+
+ // "Result:"
+ pszBuf = ReplaceSubStringWithStringMultiple(TranslateT("Result:"), pslSpecialCharsFromTo, TRUE, FALSE, NULL);
+ SLAddItemPair(pslXSLFromTo, _T("Result:"), pszBuf);
+ if (pszBuf) mir_free(pszBuf);
+
+ mir_utf8decode(LockResource(LoadResource(hInstance, FindResource(hInstance, MAKEINTRESOURCE(IDR_XSLLAYOUTFILETEMPLATE), _T("TEXT")))),&pszBuf2);
+ if (pszBuf2)
+ {
+ pszBuf = ReplaceSubStringWithStringMultiple(pszBuf2, pslXSLFromTo, TRUE, FALSE, NULL);
+ mir_free(pszBuf2);
+ if (pszBuf)
+ {
+ pszUtf8 = mir_utf8encodeW(pszBuf);
+ mir_free(pszBuf);
+ if (pszUtf8)
+ {
+ WriteFile(hXSLFile, (PBYTE)pszUtf8, lstrlenA(pszUtf8)*sizeof(char), &dwWritten, NULL);
+ //SetEndOfFile(hXSLFile);
+ mir_free(pszUtf8);
+ }
+ }
+ }
+
+ SLFreeList(pslXSLFromTo);
+ CloseHandle(hXSLFile);
+ }
+
+ // Write XML header/footer (XML-File)
+ if (GetFileSize(hFile, NULL) == 0) // If file is empty
+ {
+ // Replace spacial variables in header
+ // %log_xslfile%
+ SLAddItemPair(pslVariablesFromTo, _T("%log_xslfile%"), PathFindFileName(szXSLFile));
+
+ mir_utf8decode(LockResource(LoadResource(hInstance, FindResource(hInstance, MAKEINTRESOURCE(IDR_XMLFILETEMPLATE), _T("TEXT")))),&pszBuf2);
+ if (pszBuf2)
+ {
+ pszBuf = ReplaceSubStringWithStringMultiple(pszBuf2, pslVariablesFromTo, TRUE, FALSE, NULL);
+ mir_free(pszBuf2);
+ if (pszBuf)
+ {
+ pszUtf8 = mir_utf8encodeW(pszBuf);
+ mir_free(pszBuf);
+ if (pszUtf8)
+ {
+ WriteFile(hFile, (PBYTE)pszUtf8, lstrlenA(pszUtf8)*sizeof(char), &dwWritten, NULL);
+ //SetEndOfFile(hFile);
+ mir_free(pszUtf8);
+ }
+ }
+ }
+ }
+
+ // Inject new XML item (XML-File)
+ mir_utf8decode(LockResource(LoadResource(hInstance, FindResource(hInstance, MAKEINTRESOURCE(IDR_XMLITEMTEMPLATE), _T("TEXT")))),&pszBuf2);
+ if (pszBuf2)
+ {
+ pszBuf = ReplaceSubStringWithStringMultiple(pszBuf2, pslVariablesFromTo, TRUE, FALSE, NULL);
+ mir_free(pszBuf2);
+ if (pszBuf)
+ {
+ pszUtf8 = mir_utf8encodeW(pszBuf);
+ mir_free(pszBuf);
+ if (pszUtf8)
+ {
+ SetFilePointer(hFile, -12, NULL, FILE_END);
+ bReturn = WriteFile(hFile, (PBYTE)pszUtf8, lstrlenA(pszUtf8)*sizeof(char), &dwWritten, NULL);
+ //SetEndOfFile(hFile);
+ mir_free(pszUtf8);
+ }
+ }
+ }
+
+ SLFreeList(pslSpecialCharsFromTo);
+
+
+ // ##### Character Separated Values (CSV) format #####
+ } else if (PathMatchSpec(szLogFile, _T("*.csv"))) {
+
+ BOOL bIsUnicodeFile;
+
+ // Replace special chars in replacement variables
+ for (iBuf=SL_MIN_POS; iBuf<=SLGetMaxPos(pslVariablesFromTo); iBuf+=2)
+ {
+ pszBuf = ReplaceSubStringWithString(SLGetItem(pslVariablesFromTo, iBuf), _T("\""), _T("\"\""), TRUE, FALSE, NULL);
+ SLChangeItem(pslVariablesFromTo, iBuf, pszBuf, FALSE);
+ if (pszBuf) mir_free(pszBuf);
+ }
+
+ // Unicode and CSV header (Byte-order Mark)
+ if (GetFileSize(hFile, NULL) == 0) // If file is empty
+ {
+ #if defined(UNICODE)
+ // Write Unicode BOM UTF-16LE (Notepad)
+ // FF FE = UTF-16, little-endian
+ // -> indicating Unicode text file
+ if (IsWinVer2000Plus()) { // Notepad doesn't support Unicode on Win9x/ME -> no viewer available
+ WCHAR chBOM = 0xFFFE;
+ bIsUnicodeFile = WriteFile(hFile, (PBYTE)&chBOM, sizeof(WCHAR), &dwWritten, NULL);
+ } else {
+ bIsUnicodeFile = FALSE;
+ }
+ #else
+ bIsUnicodeFile = FALSE;
+ #endif
+
+ pszBuf = TranslateT("\"Date\";\"Time\";\"User\";\"Type\";\"Recognition\";\"Result\";\"Message\"\r\n");
+ if (pszBuf)
+ {
+ #if defined(UNICODE)
+
+ if (!bIsUnicodeFile)
+ {
+ WCHAR* pszAnsi;
+ mir_utf8decode((char*)pszBuf,&pszAnsi);
+ if (pszAnsi)
+ {
+ bReturn = WriteFile(hFile, (PBYTE)pszAnsi, lstrlenW(pszAnsi)*sizeof(char), &dwWritten, NULL);
+ mir_free(pszAnsi);
+ }
+
+ } else {
+ bReturn = WriteFile(hFile, (PBYTE)pszBuf, lstrlenW(pszBuf)*sizeof(WCHAR), &dwWritten, NULL);
+ }
+
+ #else
+
+ if (bIsUnicodeFile)
+ {
+ WCHAR* pszUnicode = mir_utf8encodeW(pszBuf);
+ if (pszUnicode)
+ {
+ bReturn = WriteFile(hFile, (PBYTE)pszUnicode, lstrlenW(pszUnicode)*sizeof(WCHAR), &dwWritten, NULL);
+ mir_free(pszUnicode);
+ }
+
+ } else {
+ bReturn = WriteFile(hFile, (PBYTE)pszBuf, lstrlenA(pszBuf)*sizeof(char), &dwWritten, NULL);
+ }
+
+ #endif
+ }
+
+ } else {
+
+ WCHAR chBOM;
+
+ // Read BOM header (Is file UTF-16LE?)
+ if (ReadFile(hFile, (PBYTE)&chBOM, sizeof(WCHAR), &dwWritten, NULL))
+ bIsUnicodeFile = (chBOM == 0xFFFE);
+ else
+ bIsUnicodeFile = FALSE;
+ }
+
+ pszBuf = TranslateT("\"%log_date%\";\"%log_time%\";\"%log_user%\";\"%log_type%\";\"%log_recognition%\";\"%log_result%\";\"%log_message%\"\r\n");
+ pszBuf = ReplaceSubStringWithStringMultiple(pszBuf, pslVariablesFromTo, TRUE, FALSE, NULL);
+ if (pszBuf)
+ {
+ SetFilePointer(hFile, 0, NULL, FILE_END);
+
+ // Append Unicode/ANSI CSV item
+ #if defined(UNICODE)
+
+ if (!bIsUnicodeFile)
+ {
+ WCHAR* pszAnsi;
+ mir_utf8decode((char*)pszBuf,&pszAnsi);
+ if (pszAnsi)
+ {
+ bReturn = WriteFile(hFile, (PBYTE)pszAnsi, lstrlenW(pszAnsi)*sizeof(char), &dwWritten, NULL);
+ mir_free(pszAnsi);
+ }
+
+ } else {
+ bReturn = WriteFile(hFile, (PBYTE)pszBuf, lstrlen(pszBuf)*sizeof(WCHAR), &dwWritten, NULL);
+ }
+
+ #else
+
+ if (bIsUnicodeFile)
+ {
+ WCHAR* pszUnicode = mir_utf8encodeW(pszBuf);
+ if (pszUnicode)
+ {
+ bReturn = WriteFile(hFile, (PBYTE)pszUnicode, lstrlenW(pszUnicode)*sizeof(WCHAR), &dwWritten, NULL);
+ mir_free(pszUnicode);
+ }
+
+ } else {
+ bReturn = WriteFile(hFile, (PBYTE)pszBuf, lstrlen(pszBuf)*sizeof(WCHAR), &dwWritten, NULL);
+ }
+
+ #endif
+
+ //SetEndOfFile(hFile);
+ mir_free(pszBuf);
+ }
+
+
+ // ##### Plain-Text format (TXT/LOG) #####
+ } else {
+
+ BOOL bIsUnicodeFile;
+
+ // Unicode header (Byte-order Mark)
+ if (GetFileSize(hFile, NULL) == 0) // If file is empty
+ {
+ #if defined(UNICODE)
+ // Write Unicode BOM UTF-16LE (Notepad)
+ // FF FE = UTF-16, little-endian
+ // -> indicating Unicode text file
+ if (IsWinVer2000Plus()) {// Notepad doesn't support Unicode on Win9x/ME -> no viewer available
+ WCHAR chBOM = 0xFFFE;
+ bIsUnicodeFile = WriteFile(hFile, (PBYTE)&chBOM, sizeof(WCHAR), &dwWritten, NULL);
+ } else {
+ bIsUnicodeFile = FALSE;
+ }
+ #else
+ bIsUnicodeFile = FALSE;
+ #endif
+
+ } else {
+
+ WCHAR chBOM;
+ bIsUnicodeFile = FALSE;
+
+ // Read BOM header (Is file UTF-16LE?)
+ if (ReadFile(hFile, (PBYTE)&chBOM, sizeof(WCHAR), &dwWritten, NULL)) {
+ bIsUnicodeFile = (chBOM == 0xFFFE);
+ } else {
+ bIsUnicodeFile = FALSE;
+ }
+ }
+
+ pszBuf = TranslateT("[%log_date% %log_time%, User: %log_user%, Type: %log_type%]\r\nRecognition: %log_recognition%\t\r\nResult: %log_result%\r\n%log_message%\r\n\r\n");
+ pszBuf = ReplaceSubStringWithStringMultiple(pszBuf, pslVariablesFromTo, TRUE, FALSE, NULL);
+ if (pszBuf)
+ {
+ SetFilePointer(hFile, 0, NULL, FILE_END);
+
+ // Append Unicode/ANSI log item
+ #if defined(UNICODE)
+
+ if (!bIsUnicodeFile)
+ {
+ WCHAR* pszAnsi;
+ mir_utf8decode((char*)pszBuf,&pszAnsi);
+ if (pszAnsi)
+ {
+ bReturn = WriteFile(hFile, (PBYTE)pszAnsi, lstrlenW(pszAnsi)*sizeof(char), &dwWritten, NULL);
+ mir_free(pszAnsi);
+ }
+
+ } else {
+ bReturn = WriteFile(hFile, (PBYTE)pszBuf, lstrlen(pszBuf)*sizeof(WCHAR), &dwWritten, NULL);
+ }
+
+ #else
+
+ if (bIsUnicodeFile)
+ {
+ WCHAR* pszUnicode = mir_utf8encodeW(pszBuf);
+ if (pszUnicode)
+ {
+ bReturn = WriteFile(hFile, (PBYTE)pszUnicode, lstrlenW(pszUnicode)*sizeof(WCHAR), &dwWritten, NULL);
+ mir_free(pszUnicode);
+ }
+
+ } else {
+ bReturn = WriteFile(hFile, (PBYTE)pszBuf, lstrlen(pszBuf)*sizeof(TCHAR), &dwWritten, NULL);
+ }
+
+ #endif
+
+ //SetEndOfFile(hFile);
+ mir_free(pszBuf);
+ }
+
+
+ } // ##### format end #####
+
+ CloseHandle(hFile);
+ SLFreeList(pslVariablesFromTo);
+
+ // Enable "show log" button if log was created while window open
+ if (IsWindow(hwndSpamFilterOpt))
+ PostMessage(hwndSpamFilterOpt, SFM_VALIDATE_LOGFILENAME, 0, 0);
+
+ return bReturn;
+} \ No newline at end of file