summaryrefslogtreecommitdiff
path: root/protocols/YAMN/src
diff options
context:
space:
mode:
authordartraiden <wowemuh@gmail.com>2023-01-14 01:30:59 +0300
committerdartraiden <wowemuh@gmail.com>2023-01-14 01:30:59 +0300
commitde40f3be3f08487937525c2ef096dad665dda61d (patch)
treeeb1205f8dca7c30b561a2776f9527072bd92eaf1 /protocols/YAMN/src
parentdd743899a769120ba2321230afddd6e4f1271872 (diff)
Convert sources to CR+LF
Diffstat (limited to 'protocols/YAMN/src')
-rw-r--r--protocols/YAMN/src/account.cpp2102
-rw-r--r--protocols/YAMN/src/browser/badconnect.cpp502
-rw-r--r--protocols/YAMN/src/browser/browser.h76
-rw-r--r--protocols/YAMN/src/browser/mailbrowser.cpp4494
-rw-r--r--protocols/YAMN/src/debug.cpp220
-rw-r--r--protocols/YAMN/src/debug.h100
-rw-r--r--protocols/YAMN/src/filterplugin.cpp338
-rw-r--r--protocols/YAMN/src/mails/decode.cpp1068
-rw-r--r--protocols/YAMN/src/mails/mails.cpp946
-rw-r--r--protocols/YAMN/src/mails/mime.cpp1390
-rw-r--r--protocols/YAMN/src/main.cpp648
-rw-r--r--protocols/YAMN/src/main.h74
-rw-r--r--protocols/YAMN/src/proto/netlib.cpp464
-rw-r--r--protocols/YAMN/src/proto/pop3/pop3.cpp688
-rw-r--r--protocols/YAMN/src/proto/pop3/pop3comm.cpp2658
-rw-r--r--protocols/YAMN/src/proto/pop3/pop3opt.cpp2274
-rw-r--r--protocols/YAMN/src/protoplugin.cpp344
-rw-r--r--protocols/YAMN/src/resource.h222
-rw-r--r--protocols/YAMN/src/services.cpp756
-rw-r--r--protocols/YAMN/src/stdafx.h506
-rw-r--r--protocols/YAMN/src/synchro.cpp630
-rw-r--r--protocols/YAMN/src/yamn.cpp460
22 files changed, 10480 insertions, 10480 deletions
diff --git a/protocols/YAMN/src/account.cpp b/protocols/YAMN/src/account.cpp
index 91b57ad544..46b7782ab0 100644
--- a/protocols/YAMN/src/account.cpp
+++ b/protocols/YAMN/src/account.cpp
@@ -1,1051 +1,1051 @@
-/*
- * This code implements manipulation with accounts
- * such as reading accounts from file, writing them to file,
- * finding account by name etc.
- *
- * (c) majvan 2002-2004
- */
-
-#include "stdafx.h"
-
- // Account status CS
- // When we check some account, thread should change status of account to idle, connecting etc.
- // So if we want to read status, we have to successfully write and then read.
-static mir_cs csAccountStatusCS;
-
-// File Writing CS
-// When 2 threads want to write to file...
-static mir_cs csFileWritingCS;
-
-struct CExportedFunctions AccountExportedFcn[] =
-{
- {YAMN_GETSTATUSID, (void *)GetStatusFcn},
- {YAMN_SETSTATUSID, (void *)SetStatusFcn},
-};
-
-struct CExportedServices AccountExportedSvc[] =
-{
- {MS_YAMN_CREATEPLUGINACCOUNT, CreatePluginAccountSvc},
- {MS_YAMN_DELETEPLUGINACCOUNT, DeletePluginAccountSvc},
- {MS_YAMN_FINDACCOUNTBYNAME, FindAccountByNameSvc},
- {MS_YAMN_GETNEXTFREEACCOUNT, GetNextFreeAccountSvc},
- {MS_YAMN_DELETEACCOUNT, DeletePluginAccountSvc},
- {MS_YAMN_READACCOUNTS, AddAccountsFromFileSvc},
- {MS_YAMN_WRITEACCOUNTS, WriteAccountsToFileSvc},
-};
-
-//--------------------------------------------------------------------------------------------------
-//--------------------------------------------------------------------------------------------------
-
-INT_PTR CreatePluginAccountSvc(WPARAM wParam, LPARAM lParam)
-{
- HYAMNPROTOPLUGIN Plugin = (HYAMNPROTOPLUGIN)wParam;
- uint32_t AccountVersion = (uint32_t)lParam;
-
- //test if we are going to initialize members of suitable structure (structures of plugin and YAMN must match)
- if (AccountVersion != YAMN_ACCOUNTVERSION)
- return NULL;
-
- if (Plugin != nullptr) {
- CAccount *NewAccount;
- if (Plugin->Fcn->NewAccountFcnPtr != nullptr)
- //Let plugin create its own structure, which can be derived from CAccount structure
- NewAccount = Plugin->Fcn->NewAccountFcnPtr(Plugin, YAMN_ACCOUNTVERSION);
- else
- //We suggest plugin uses standard CAccount structure, so we create it
- NewAccount = new struct CAccount;
-
- //If not created successfully
- if (NewAccount == nullptr)
- return NULL;
-
- NewAccount->Plugin = Plugin;
- //Init every members of structure, used by YAMN
- InitAccount(NewAccount);
-
- return (INT_PTR)NewAccount;
- }
- return NULL;
-}
-
-INT_PTR DeletePluginAccountSvc(WPARAM wParam, LPARAM)
-{
- CAccount *OldAccount = (CAccount *)wParam;
-
- if (OldAccount->Plugin->Fcn != nullptr) {
- // Deinit every members and allocated fields of structure used by YAMN
- DeInitAccount(OldAccount);
- if (OldAccount->Plugin->Fcn->DeleteAccountFcnPtr != nullptr) {
- // Let plugin delete its own CAccount derived structure
- OldAccount->Plugin->Fcn->DeleteAccountFcnPtr(OldAccount);
- }
- else {
- delete OldAccount; //consider account as standard YAMN CAccount *and use its own destructor
- }
- return 1;
- }
- delete OldAccount; //consider account as standard YAMN CAccount *, not initialized before and use its own destructor
- return 1;
-}
-
-int InitAccount(CAccount *Which)
-{
- //initialize synchronizing objects
- Which->AccountAccessSO = new SWMRG;
- SWMRGInitialize(Which->AccountAccessSO, nullptr);
- Which->MessagesAccessSO = new SWMRG;
- SWMRGInitialize(Which->MessagesAccessSO, nullptr);
- Which->UsingThreads = new SCOUNTER;
- SWMRGInitialize(Which->MessagesAccessSO, nullptr);
-
- //zero memory, where timestamps are stored
- memset(&Which->LastChecked, 0, sizeof(Which->LastChecked));
- memset(&Which->LastSChecked, 0, sizeof(Which->LastSChecked));
- memset(&Which->LastSynchronised, 0, sizeof(Which->LastSynchronised));
- memset(&Which->LastMail, 0, sizeof(Which->LastMail));
-
- Which->Name = nullptr;
- Which->Mails = nullptr;
- Which->Interval = 0;
- Which->Flags = 0;
- Which->StatusFlags = YAMN_ACC_ST1 + YAMN_ACC_ST7;
- Which->Next = nullptr;
-
- Which->Server = new struct CServer;
- Which->AbleToWork = TRUE;
-
- return 1;
-}
-
-void DeInitAccount(CAccount *Which)
-{
- //delete YAMN allocated fields
- if (Which->Name != nullptr)
- delete[] Which->Name;
- if (Which->Server != nullptr) {
- if (Which->Server->Name != nullptr)
- delete[] Which->Server->Name;
- if (Which->Server->Login != nullptr)
- delete[] Which->Server->Login;
- if (Which->Server->Passwd != nullptr)
- delete[] Which->Server->Passwd;
- delete[] Which->Server;
- }
-
- SWMRGDelete(Which->AccountAccessSO);
- delete Which->AccountAccessSO;
- SWMRGDelete(Which->MessagesAccessSO);
- delete Which->MessagesAccessSO;
- delete Which->UsingThreads;
- DeleteMessagesToEndFcn(Which, (HYAMNMAIL)Which->Mails);
-}
-
-void StopSignalFcn(CAccount *Which)
-//set event that we are going to delete account
-{
- Which->AbleToWork = FALSE;
- //do not use synchronizing objects anymore
- //any access to these objects then ends with WAIT_FAILED
- SetEvent(Which->AccountAccessSO->hFinishEV);
- SetEvent(Which->MessagesAccessSO->hFinishEV);
-}
-
-void CodeDecodeString(char *Dest, BOOL Encrypt)
-{
- wchar_t Code = STARTCODEPSW;
-
- if (Dest == nullptr)
- return;
-
- for (; *Dest != (wchar_t)0; Dest++) {
- if (Encrypt)
- *Dest = *Dest + Code;
- else
- *Dest = *Dest - Code;
- Code += (wchar_t)ADDCODEPSW;
- }
-}
-
-static uint32_t PostFileToMemory(HANDLE File, char **MemFile, char **End)
-{
- DWORD FileSize, ReadBytes;
- if (!(FileSize = GetFileSize(File, nullptr))) {
- CloseHandle(File);
- return EACC_FILESIZE;
- }
-
- //allocate space in memory, where we copy the whole file
- if (nullptr == (*MemFile = new char[FileSize])) {
- CloseHandle(File);
- return EACC_ALLOC;
- }
-
- //copy file to memory
- if (!ReadFile(File, (LPVOID)*MemFile, FileSize, &ReadBytes, nullptr)) {
- CloseHandle(File);
- delete[] * MemFile;
- return EACC_SYSTEM;
- }
- CloseHandle(File);
- *End = *MemFile + FileSize;
- return 0;
-}
-
-uint32_t FileToMemory(wchar_t *FileName, char **MemFile, char **End)
-{
- HANDLE hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
- if (hFile == INVALID_HANDLE_VALUE)
- return EACC_SYSTEM;
-
- return PostFileToMemory(hFile, MemFile, End);
-}
-
-#if defined(DEBUG_FILEREAD) || defined(DEBUG_FILEREADMESSAGES)
-uint32_t ReadStringFromMemory(char **Parser, wchar_t *End, char **StoreTo, wchar_t *DebugString)
-{
- //This is the debug version of ReadStringFromMemory function. This version shows MessageBox where
- //read string is displayed
- wchar_t *Dest, *Finder;
- uint32_t Size;
- wchar_t Debug[65536];
-
- Finder = *Parser;
- while ((*Finder != (wchar_t)0) && (Finder <= End)) Finder++;
- mir_snwprintf(Debug, L"%s: %s,length is %d, remaining %d chars", DebugString, *Parser, Finder - *Parser, End - Finder);
- MessageBox(NULL, Debug, L"debug", MB_OK);
- if (Finder >= End)
- return EACC_FILECOMPATIBILITY;
- if (Size = Finder - *Parser) {
- if (NULL == (Dest = *StoreTo = new wchar_t[Size + 1]))
- return EACC_ALLOC;
- for (; *Parser <= Finder; (*Parser)++, Dest++)
- *Dest = **Parser;
- }
- else {
- *StoreTo = NULL;
- (*Parser)++;
- }
- return 0;
-}
-#endif
-
-uint32_t ReadStringFromMemory(char **Parser, char *End, char **StoreTo)
-{
- char *Dest, *Finder;
- uint32_t Size;
-
- Finder = *Parser;
- while ((*Finder != (wchar_t)0) && (Finder <= End)) Finder++;
- if (Finder >= End)
- return EACC_FILECOMPATIBILITY;
- if (Size = Finder - *Parser) {
- if (nullptr == (Dest = *StoreTo = new char[Size + 1]))
- return EACC_ALLOC;
- for (; *Parser <= Finder; (*Parser)++, Dest++)
- *Dest = **Parser;
- }
- else {
- *StoreTo = nullptr;
- (*Parser)++;
- }
- return 0;
-}
-
-#if defined(DEBUG_FILEREAD) || defined(DEBUG_FILEREADMESSAGES)
-uint32_t ReadStringFromMemoryW(wchar_t **Parser, wchar_t *End, wchar_t **StoreTo, wchar_t *DebugString)
-{
- //This is the debug version of ReadStringFromMemoryW function. This version shows MessageBox where
- //read string is displayed
- wchar_t *Dest, *Finder;
- uint32_t Size;
- wchar_t Debug[65536];
-
- Finder = *Parser;
- while ((*Finder != (wchar_t)0) && (Finder <= (wchar_t *)End)) Finder++;
- mir_snwprintf(Debug, L"%s: %s,length is %d, remaining %d chars", DebugString, *Parser, Finder - *Parser, (wchar_t *)End - Finder);
- MessageBoxW(NULL, Debug, L"debug", MB_OK);
- if (Finder >= (wchar_t *)End)
- return EACC_FILECOMPATIBILITY;
- if (Size = Finder - *Parser) {
- if (NULL == (Dest = *StoreTo = new wchar_t[Size + 1]))
- return EACC_ALLOC;
- for (; *Parser <= Finder; (*Parser)++, Dest++)
- *Dest = **Parser;
- }
- else {
- *StoreTo = NULL;
- (*Parser)++;
- }
- return 0;
-}
-#endif //if defined(DEBUG...)
-
-uint32_t ReadStringFromMemoryW(wchar_t **Parser, wchar_t *End, wchar_t **StoreTo)
-{
- wchar_t *Dest, *Finder;
- uint32_t Size;
-
- Finder = *Parser;
- while ((*Finder != (wchar_t)0) && (Finder <= (wchar_t *)End)) Finder++;
- if (Finder >= (wchar_t *)End)
- return EACC_FILECOMPATIBILITY;
- if (Size = Finder - *Parser) {
- if (nullptr == (Dest = *StoreTo = new wchar_t[Size + 1]))
- return EACC_ALLOC;
- for (; *Parser <= Finder; (*Parser)++, Dest++)
- *Dest = **Parser;
- }
- else {
- *StoreTo = nullptr;
- (*Parser)++;
- }
- return 0;
-}
-
-static uint32_t ReadNotificationFromMemory(char **Parser, char *End, YAMN_NOTIFICATION *Which)
-{
- uint32_t Stat;
- #ifdef DEBUG_FILEREAD
- wchar_t Debug[65536];
- #endif
-
- Which->Flags = *(uint32_t *)(*Parser);
- (*Parser) += sizeof(uint32_t);
- if (*Parser >= End)
- return EACC_FILECOMPATIBILITY;
- #ifdef DEBUG_FILEREAD
- mir_snwprintf(Debug, L"NFlags: %04x, remaining %d chars", Which->Flags, End - *Parser);
- MessageBox(NULL, Debug, L"debug", MB_OK);
- #endif
-
- Which->PopupB = *(COLORREF *)(*Parser);
- (*Parser) += sizeof(COLORREF);
- if (*Parser >= End)
- return EACC_FILECOMPATIBILITY;
- #ifdef DEBUG_FILEREAD
- mir_snwprintf(Debug, L"PopupB: %04x, remaining %d chars", Which->PopupB, End - *Parser);
- MessageBox(NULL, Debug, L"debug", MB_OK);
- #endif
- Which->PopupT = *(COLORREF *)(*Parser);
- (*Parser) += sizeof(COLORREF);
- if (*Parser >= End)
- return EACC_FILECOMPATIBILITY;
- #ifdef DEBUG_FILEREAD
- mir_snwprintf(Debug, L"PopupT: %04x, remaining %d chars", Which->PopupT, End - *Parser);
- MessageBox(NULL, Debug, L"debug", MB_OK);
- #endif
- Which->PopupTime = *(uint32_t *)(*Parser);
- (*Parser) += sizeof(uint32_t);
- if (*Parser >= End)
- return EACC_FILECOMPATIBILITY;
- #ifdef DEBUG_FILEREAD
- mir_snwprintf(Debug, L"PopupTime: %04x, remaining %d chars", Which->PopupTime, End - *Parser);
- MessageBox(NULL, Debug, L"debug", MB_OK);
- #endif
-
- #ifdef DEBUG_FILEREAD
- if (Stat = ReadStringFromMemoryW((wchar_t **)Parser, (wchar_t *)End, &Which->App, L"App"))
- #else
- if (Stat = ReadStringFromMemoryW((wchar_t **)Parser, (wchar_t *)End, &Which->App))
- #endif
- return Stat;
- #ifdef DEBUG_FILEREAD
- if (Stat = ReadStringFromMemoryW((wchar_t **)Parser, (wchar_t *)End, &Which->AppParam, L"AppParam"))
- #else
- if (Stat = ReadStringFromMemoryW((wchar_t **)Parser, (wchar_t *)End, &Which->AppParam))
- #endif
- return Stat;
- return 0;
-}
-
-uint32_t ReadMessagesFromMemory(CAccount *Which, char **Parser, char *End)
-{
- char *Finder;
- uint32_t Size, Stat;
- HYAMNMAIL ActualMail = nullptr;
- struct CMimeItem *items;
- char *ReadString;
-
- #ifdef DEBUG_FILEREAD
- MessageBox(NULL, L"going to read messages, if any...", L"debug", MB_OK);
- #endif
- do {
- Finder = *Parser;
- while ((*Finder != (wchar_t)0) && (Finder <= End)) Finder++;
- if (Finder >= End)
- return EACC_FILECOMPATIBILITY;
- if (Size = Finder - *Parser) {
- if (Which->Mails == nullptr) //First message in queue
- {
- if (nullptr == (Which->Mails = ActualMail = CreateAccountMail(Which)))
- return EACC_ALLOC;
- }
- else {
- if (nullptr == (ActualMail->Next = CreateAccountMail(Which))) {
- return EACC_ALLOC;
- }
- ActualMail = ActualMail->Next;
- }
- items = nullptr;
- #ifdef DEBUG_FILEREADMESSAGES
- if (Stat = ReadStringFromMemory(Parser, End, &ActualMail->ID, L"ID"))
- #else
- if (Stat = ReadStringFromMemory(Parser, End, &ActualMail->ID))
- #endif
- return Stat;
- // ActualMail->MailData=new MAILDATA; !!! mem leake !!! this is alloc by CreateAccountMail, no need for doubble alloc !!!!
-
- ActualMail->MailData->Size = *(uint32_t *)(*Parser);
- (*Parser) += sizeof(uint32_t);
- if (*Parser >= End)
- return EACC_FILECOMPATIBILITY;
- ActualMail->Flags = *(uint32_t *)(*Parser);
- (*Parser) += sizeof(uint32_t);
- if (*Parser >= End)
- return EACC_FILECOMPATIBILITY;
- ActualMail->Number = *(uint32_t *)(*Parser);
- (*Parser) += sizeof(uint32_t);
- if (*Parser >= End)
- return EACC_FILECOMPATIBILITY;
-
- if ((nullptr != Which->Plugin->MailFcn) && (nullptr != Which->Plugin->MailFcn->ReadMailOptsFcnPtr))
- Which->Plugin->MailFcn->ReadMailOptsFcnPtr(ActualMail, Parser, End); //read plugin mail settings from file
-
- do {
- #if defined(DEBUG_FILEREADMESSAGES) || defined(DEBUG_FILEREAD)
- if (Stat = ReadStringFromMemory(Parser, End, &ReadString, L"Name"))
- #else
- if (Stat = ReadStringFromMemory(Parser, End, &ReadString))
- #endif
- return Stat;
- if (ReadString == nullptr)
- break;
-
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "<read name>%s</read name>", ReadString);
- #endif
-
- if (items == nullptr)
- items = ActualMail->MailData->TranslatedHeader = new struct CMimeItem;
- else {
- items->Next = new struct CMimeItem;
- items = items->Next;
- }
- if (items == nullptr)
- return EACC_ALLOC;
- items->name = ReadString;
-
- #ifdef DEBUG_FILEREADMESSAGES
- if (Stat = ReadStringFromMemory(Parser, End, &ReadString, L"Value"))
- #else
- if (Stat = ReadStringFromMemory(Parser, End, &ReadString))
- #endif
- return Stat;
- items->value = ReadString;
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "<read value>%s</read value>\n", ReadString);
- #endif
- } while (1);
- }
- else
- break; //no next messages, new account!
-
- } while (1);
- (*Parser)++;
- return 0;
-}
-
-uint32_t ReadAccountFromMemory(CAccount *Which, char **Parser, char *End)
-{
- uint32_t Stat;
- #ifdef DEBUG_FILEREAD
- wchar_t Debug[65536];
- #endif
- //Read name of account
-
- #ifdef DEBUG_FILEREAD
- if (Stat = ReadStringFromMemory(Parser, End, &Which->Name, L"Name"))
- #else
- if (Stat = ReadStringFromMemory(Parser, End, &Which->Name))
- #endif
- return Stat;
- if (Which->Name == nullptr)
- return EACC_FILECOMPATIBILITY;
-
- //Read server parameters
- #ifdef DEBUG_FILEREAD
- if (Stat = ReadStringFromMemory(Parser, End, &Which->Server->Name, L"Server"))
- #else
- if (Stat = ReadStringFromMemory(Parser, End, &Which->Server->Name))
- #endif
- return Stat;
- Which->Server->Port = *(uint16_t *)(*Parser);
- (*Parser) += sizeof(uint16_t);
- if (*Parser >= End)
- return EACC_FILECOMPATIBILITY;
- #ifdef DEBUG_FILEREAD
- mir_snwprintf(Debug, L"Port: %d, remaining %d chars", Which->Server->Port, End - *Parser);
- MessageBox(NULL, Debug, L"debug", MB_OK);
- #endif
- #ifdef DEBUG_FILEREAD
- if (Stat = ReadStringFromMemory(Parser, End, &Which->Server->Login, L"Login"))
- #else
- if (Stat = ReadStringFromMemory(Parser, End, &Which->Server->Login))
- #endif
- return Stat;
- #ifdef DEBUG_FILEREAD
- if (Stat = ReadStringFromMemory(Parser, End, &Which->Server->Passwd, L"Password"))
- #else
- if (Stat = ReadStringFromMemory(Parser, End, &Which->Server->Passwd))
- #endif
- return Stat;
- CodeDecodeString(Which->Server->Passwd, FALSE);
-
- //Read account flags
- Which->Flags = *(uint32_t *)(*Parser);
- (*Parser) += sizeof(uint32_t);
- if (*Parser >= End)
- return EACC_FILECOMPATIBILITY;
- #ifdef DEBUG_FILEREAD
- mir_snwprintf(Debug, L"Flags: %04x, remaining %d chars", Which->Flags, End - *Parser);
- MessageBox(NULL, Debug, L"debug", MB_OK);
- #endif
- Which->StatusFlags = *(uint32_t *)(*Parser);
- (*Parser) += sizeof(uint32_t);
- #ifdef DEBUG_FILEREAD
- mir_snwprintf(Debug, L"STFlags: %04x, remaining %d chars", Which->StatusFlags, End - *Parser);
- MessageBox(NULL, Debug, L"debug", MB_OK);
- #endif
- Which->PluginFlags = *(uint32_t *)(*Parser);
- (*Parser) += sizeof(uint32_t);
- #ifdef DEBUG_FILEREAD
- mir_snwprintf(Debug, L"PFlags: %04x, remaining %d chars", Which->PluginFlags, End - *Parser);
- MessageBox(NULL, Debug, L"debug", MB_OK);
- #endif
-
- //Read account miscellaneous parameters
- Which->Interval = *(uint16_t *)(*Parser);
- Which->TimeLeft = Which->Interval; //check on loading
- (*Parser) += sizeof(uint16_t);
- if (*Parser >= End)
- return EACC_FILECOMPATIBILITY;
- #ifdef DEBUG_FILEREAD
- mir_snwprintf(Debug, L"Interval: %d, remaining %d chars", Which->Interval, End - *Parser);
- MessageBox(NULL, Debug, L"debug", MB_OK);
- #endif
-
- //Read notification parameters
- if (Stat = ReadNotificationFromMemory(Parser, End, &Which->NewMailN))
- return Stat;
- if (Stat = ReadNotificationFromMemory(Parser, End, &Which->NoNewMailN))
- return Stat;
- if (Stat = ReadNotificationFromMemory(Parser, End, &Which->BadConnectN))
- return Stat;
-
- //Let plugin read its own data stored in file
- if (Which->Plugin->Fcn != nullptr && Which->Plugin->Fcn->ReadPluginOptsFcnPtr != nullptr)
- if (Stat = Which->Plugin->Fcn->ReadPluginOptsFcnPtr(Which, Parser, End))
- return Stat;
-
- // Read mails
- WaitToWriteFcn(Which->MessagesAccessSO);
-
- if (Stat = ReadMessagesFromMemory(Which, Parser, End)) {
- WriteDoneFcn(Which->MessagesAccessSO);
- return Stat;
- }
-
- WriteDoneFcn(Which->MessagesAccessSO);
-
- // Read timestamps
- Which->LastChecked = *(SYSTEMTIME *)(*Parser);
- (*Parser) += sizeof(SYSTEMTIME);
- if (*Parser >= End)
- return EACC_FILECOMPATIBILITY;
-
- Which->LastSChecked = *(SYSTEMTIME *)(*Parser);
- (*Parser) += sizeof(SYSTEMTIME);
- if (*Parser >= End)
- return EACC_FILECOMPATIBILITY;
-
- Which->LastSynchronised = *(SYSTEMTIME *)(*Parser);
- (*Parser) += sizeof(SYSTEMTIME);
- if (*Parser >= End)
- return EACC_FILECOMPATIBILITY;
-
- Which->LastMail = *(SYSTEMTIME *)(*Parser);
- (*Parser) += sizeof(SYSTEMTIME);
- if (*Parser > End) //WARNING! There's only > at the end of testing
- return EACC_FILECOMPATIBILITY;
-
- if (*Parser == End)
- return EACC_ENDOFFILE;
- return 0;
-}
-
-static INT_PTR PerformAccountReading(HYAMNPROTOPLUGIN Plugin, char *MemFile, char *End)
-{
- // Retrieve info for account from memory
- char *Parser;
- uint32_t Ver, Stat;
-
- CAccount *ActualAccount, *FirstAllocatedAccount;
-
- Ver = *(uint32_t *)MemFile;
- if (Ver > YAMN_ACCOUNTFILEVERSION) {
- delete[] MemFile;
- return EACC_FILEVERSION;
- }
- Parser = MemFile + sizeof(Ver);
-
- SWMRGWaitToWrite(Plugin->AccountBrowserSO, INFINITE);
-
- if (nullptr == (ActualAccount = (CAccount *)CallService(MS_YAMN_GETNEXTFREEACCOUNT, (WPARAM)Plugin, (LPARAM)YAMN_ACCOUNTVERSION))) {
- SWMRGDoneWriting(Plugin->AccountBrowserSO);
- delete[] MemFile;
- return EACC_ALLOC;
- }
-
- FirstAllocatedAccount = ActualAccount;
-
- do {
- CAccount *Temp;
-
- WaitToWriteFcn(ActualAccount->AccountAccessSO);
- Stat = ReadAccountFromMemory(ActualAccount, &Parser, End);
-
- if (ActualAccount->StatusFlags & (YAMN_ACC_STARTA | YAMN_ACC_STARTS))
- ActualAccount->TimeLeft = 1; //check on loading
-
- if (Stat && (Stat != EACC_ENDOFFILE)) {
- for (ActualAccount = FirstAllocatedAccount; ActualAccount != nullptr; ActualAccount = Temp) {
- Temp = ActualAccount->Next;
- delete ActualAccount;
- }
- delete[] MemFile;
- if (Plugin->FirstAccount == FirstAllocatedAccount)
- Plugin->FirstAccount = nullptr;
-
- SWMRGDoneWriting(Plugin->AccountBrowserSO);
- return (INT_PTR)Stat;
- }
-
- WriteDoneFcn(ActualAccount->AccountAccessSO);
-
- if ((Stat != EACC_ENDOFFILE) && (nullptr == (ActualAccount = (CAccount *)CallService(MS_YAMN_GETNEXTFREEACCOUNT, (WPARAM)Plugin, (LPARAM)YAMN_ACCOUNTVERSION)))) {
- for (ActualAccount = FirstAllocatedAccount; ActualAccount != nullptr; ActualAccount = Temp) {
- Temp = ActualAccount->Next;
- delete ActualAccount;
- }
- delete[] MemFile;
- if (Plugin->FirstAccount == FirstAllocatedAccount)
- Plugin->FirstAccount = nullptr;
-
- SWMRGDoneWriting(Plugin->AccountBrowserSO);
- return EACC_ALLOC;
- }
- } while (Stat != EACC_ENDOFFILE);
-
- SWMRGDoneWriting(Plugin->AccountBrowserSO);
- delete[] MemFile;
- return 0;
-}
-
-// Add accounts from file to memory
-INT_PTR AddAccountsFromFileSvc(WPARAM wParam, LPARAM lParam)
-{
- char *MemFile, *End;
- uint32_t Stat = FileToMemory((wchar_t *)lParam, &MemFile, &End);
- if (Stat != NO_ERROR)
- return (INT_PTR)Stat;
-
- return PerformAccountReading((HYAMNPROTOPLUGIN)wParam, MemFile, End);
-}
-
-uint32_t WriteStringToFile(HANDLE File, char *Source)
-{
- DWORD Length, WrittenBytes;
- char null = 0;
-
- if ((Source == nullptr) || !(Length = (uint32_t)mir_strlen(Source))) {
- if (!WriteFile(File, &null, 1, &WrittenBytes, nullptr)) {
- CloseHandle(File);
- return EACC_SYSTEM;
- }
- }
- else if (!WriteFile(File, Source, (Length + 1), &WrittenBytes, nullptr)) {
- CloseHandle(File);
- return EACC_SYSTEM;
- }
- return 0;
-}
-
-uint32_t WriteStringToFileW(HANDLE File, wchar_t *Source)
-{
- DWORD Length, WrittenBytes;
- wchar_t null = (wchar_t)0;
-
- if ((Source == nullptr) || !(Length = (uint32_t)mir_wstrlen(Source))) {
- if (!WriteFile(File, &null, sizeof(wchar_t), &WrittenBytes, nullptr)) {
- CloseHandle(File);
- return EACC_SYSTEM;
- }
- }
- else if (!WriteFile(File, Source, (Length + 1) * sizeof(wchar_t), &WrittenBytes, nullptr))
- return EACC_SYSTEM;
- return 0;
-}
-
-DWORD WriteMessagesToFile(HANDLE File, CAccount *Which)
-{
- DWORD WrittenBytes, Stat;
- HYAMNMAIL ActualMail = (HYAMNMAIL)Which->Mails;
- struct CMimeItem *items;
-
- while (ActualMail != nullptr) {
- if (Stat = WriteStringToFile(File, ActualMail->ID))
- return Stat;
-
- if (!WriteFile(File, (char *)&ActualMail->MailData->Size, sizeof(ActualMail->MailData->Size), &WrittenBytes, nullptr) ||
- !WriteFile(File, (char *)&ActualMail->Flags, sizeof(ActualMail->Flags), &WrittenBytes, nullptr) ||
- !WriteFile(File, (char *)&ActualMail->Number, sizeof(ActualMail->Number), &WrittenBytes, nullptr))
- return EACC_SYSTEM;
- if ((nullptr != Which->Plugin->MailFcn) && (nullptr != Which->Plugin->MailFcn->WriteMailOptsFcnPtr))
- Which->Plugin->MailFcn->WriteMailOptsFcnPtr(File, ActualMail); //write plugin mail options to file
- for (items = ActualMail->MailData->TranslatedHeader; items != nullptr; items = items->Next) {
- if (Stat = WriteStringToFile(File, items->name))
- return Stat;
- if (Stat = WriteStringToFile(File, items->value))
- return Stat;
- }
- if (Stat = WriteStringToFile(File, ""))
- return Stat;
- ActualMail = ActualMail->Next;
- }
- if (Stat = WriteStringToFile(File, ""))
- return Stat;
- return 0;
-}
-
-static INT_PTR PerformAccountWriting(HYAMNPROTOPLUGIN Plugin, HANDLE File)
-{
- DWORD WrittenBytes, Stat;
- CAccount *ActualAccount;
- uint32_t Ver = YAMN_ACCOUNTFILEVERSION;
- BOOL Writed = FALSE;
- uint32_t ReturnValue = 0, EnterCode;
-
- SWMRGWaitToRead(Plugin->AccountBrowserSO, INFINITE);
-
- try {
- for (ActualAccount = Plugin->FirstAccount; ActualAccount != nullptr; ActualAccount = ActualAccount->Next) {
- EnterCode = WaitToReadFcn(ActualAccount->AccountAccessSO);
- if (EnterCode == WAIT_FINISH) //account is about to delete
- {
- ActualAccount = ActualAccount->Next;
- continue;
- }
- if (EnterCode == WAIT_FAILED) //account is deleted
- break;
-
- if ((ActualAccount->Name == nullptr) || (*ActualAccount->Name == (wchar_t)0)) {
- ReadDoneFcn(ActualAccount->AccountAccessSO);
- continue;
- }
-
- if (!Writed && !WriteFile(File, &Ver, sizeof(Ver), &WrittenBytes, nullptr))
- throw (uint32_t)EACC_SYSTEM;
-
- Writed = TRUE;
-
- if (Stat = WriteStringToFile(File, ActualAccount->Name))
- throw (uint32_t)Stat;
-
- if (Stat = WriteStringToFile(File, ActualAccount->Server->Name))
- throw (uint32_t)Stat;
-
- if (!WriteFile(File, (char *)&ActualAccount->Server->Port, 2, &WrittenBytes, nullptr))
- throw (uint32_t)EACC_SYSTEM;
-
- if ((Stat = WriteStringToFile(File, ActualAccount->Server->Login)))
- throw (uint32_t)Stat;
-
- CodeDecodeString(ActualAccount->Server->Passwd, TRUE);
-
- if (Stat = WriteStringToFile(File, ActualAccount->Server->Passwd)) {
- CodeDecodeString(ActualAccount->Server->Passwd, FALSE);
- throw (uint32_t)Stat;
- }
- CodeDecodeString(ActualAccount->Server->Passwd, FALSE);
-
- if ((!WriteFile(File, (char *)&ActualAccount->Flags, sizeof(uint32_t), &WrittenBytes, nullptr) ||
- (!WriteFile(File, (char *)&ActualAccount->StatusFlags, sizeof(uint32_t), &WrittenBytes, nullptr)) ||
- (!WriteFile(File, (char *)&ActualAccount->PluginFlags, sizeof(uint32_t), &WrittenBytes, nullptr))))
- throw (uint32_t)EACC_SYSTEM;
-
- if (!WriteFile(File, (char *)&ActualAccount->Interval, sizeof(uint16_t), &WrittenBytes, nullptr))
- throw (uint32_t)EACC_SYSTEM;
-
- if ((!WriteFile(File, (char *)&ActualAccount->NewMailN.Flags, sizeof(uint32_t), &WrittenBytes, nullptr)) ||
- (!WriteFile(File, (char *)&ActualAccount->NewMailN.PopupB, sizeof(COLORREF), &WrittenBytes, nullptr)) ||
- (!WriteFile(File, (char *)&ActualAccount->NewMailN.PopupT, sizeof(COLORREF), &WrittenBytes, nullptr)) ||
- (!WriteFile(File, (char *)&ActualAccount->NewMailN.PopupTime, sizeof(uint32_t), &WrittenBytes, nullptr)))
- throw (uint32_t)EACC_SYSTEM;
-
- if ((Stat = WriteStringToFileW(File, ActualAccount->NewMailN.App)) ||
- (Stat = WriteStringToFileW(File, ActualAccount->NewMailN.AppParam)))
- throw (uint32_t)Stat;
-
- if ((!WriteFile(File, (char *)&ActualAccount->NoNewMailN.Flags, sizeof(uint32_t), &WrittenBytes, nullptr)) ||
- (!WriteFile(File, (char *)&ActualAccount->NoNewMailN.PopupB, sizeof(COLORREF), &WrittenBytes, nullptr)) ||
- (!WriteFile(File, (char *)&ActualAccount->NoNewMailN.PopupT, sizeof(COLORREF), &WrittenBytes, nullptr)) ||
- (!WriteFile(File, (char *)&ActualAccount->NoNewMailN.PopupTime, sizeof(uint32_t), &WrittenBytes, nullptr)))
- throw (uint32_t)EACC_SYSTEM;
-
- if ((Stat = WriteStringToFileW(File, ActualAccount->NoNewMailN.App)) ||
- (Stat = WriteStringToFileW(File, ActualAccount->NoNewMailN.AppParam)))
- throw (uint32_t)Stat;
-
- if ((!WriteFile(File, (char *)&ActualAccount->BadConnectN.Flags, sizeof(uint32_t), &WrittenBytes, nullptr)) ||
- (!WriteFile(File, (char *)&ActualAccount->BadConnectN.PopupB, sizeof(COLORREF), &WrittenBytes, nullptr)) ||
- (!WriteFile(File, (char *)&ActualAccount->BadConnectN.PopupT, sizeof(COLORREF), &WrittenBytes, nullptr)) ||
- (!WriteFile(File, (char *)&ActualAccount->BadConnectN.PopupTime, sizeof(uint32_t), &WrittenBytes, nullptr)))
- throw (uint32_t)EACC_SYSTEM;
-
- if ((Stat = WriteStringToFileW(File, ActualAccount->BadConnectN.App)) ||
- (Stat = WriteStringToFileW(File, ActualAccount->BadConnectN.AppParam)))
- throw (uint32_t)Stat;
-
- //Let plugin write its own values into file
- if (ActualAccount->Plugin->Fcn != nullptr && ActualAccount->Plugin->Fcn->WritePluginOptsFcnPtr != nullptr)
- if (Stat = ActualAccount->Plugin->Fcn->WritePluginOptsFcnPtr(File, ActualAccount))
- throw (uint32_t)Stat;
-
- WaitToReadFcn(ActualAccount->MessagesAccessSO);
-
- if (Stat = WriteMessagesToFile(File, ActualAccount)) {
-
- ReadDoneFcn(ActualAccount->MessagesAccessSO);
- throw (uint32_t)Stat;
- }
-
- ReadDoneFcn(ActualAccount->MessagesAccessSO);
-
- if ((!WriteFile(File, (char *)&ActualAccount->LastChecked, sizeof(SYSTEMTIME), &WrittenBytes, nullptr)) ||
- (!WriteFile(File, (char *)&ActualAccount->LastSChecked, sizeof(SYSTEMTIME), &WrittenBytes, nullptr)) ||
- (!WriteFile(File, (char *)&ActualAccount->LastSynchronised, sizeof(SYSTEMTIME), &WrittenBytes, nullptr)) ||
- (!WriteFile(File, (char *)&ActualAccount->LastMail, sizeof(SYSTEMTIME), &WrittenBytes, nullptr)))
- throw (uint32_t)Stat;
-
- ReadDoneFcn(ActualAccount->AccountAccessSO);
- }
- }
- catch (uint32_t ErrorCode) {
- ReadDoneFcn(ActualAccount->AccountAccessSO);
- ReturnValue = ErrorCode;
- }
-
- SWMRGDoneReading(Plugin->AccountBrowserSO);
- CloseHandle(File);
- return 0;
-}
-
-// Writes accounts to file
-INT_PTR WriteAccountsToFileSvc(WPARAM wParam, LPARAM lParam)
-{
- HYAMNPROTOPLUGIN Plugin = (HYAMNPROTOPLUGIN)wParam;
-
- mir_cslock lck(csFileWritingCS);
- HANDLE hFile = CreateFile((wchar_t *)lParam, GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
- if (hFile == INVALID_HANDLE_VALUE)
- return EACC_SYSTEM;
-
- return PerformAccountWriting(Plugin, hFile);
-}
-
-INT_PTR FindAccountByNameSvc(WPARAM wParam, LPARAM lParam)
-{
- HYAMNPROTOPLUGIN Plugin = (HYAMNPROTOPLUGIN)wParam;
- char *SearchedAccount = (char *)lParam;
- CAccount *Finder;
-
- SWMRGWaitToRead(Plugin->AccountBrowserSO, INFINITE);
-
- for (Finder = Plugin->FirstAccount; Finder != nullptr; Finder = Finder->Next)
- if ((Finder->Name != nullptr) && (0 == mir_strcmp(SearchedAccount, Finder->Name)))
- break;
-
- SWMRGDoneReading(Plugin->AccountBrowserSO);
- return (INT_PTR)Finder;
-}
-
-INT_PTR GetNextFreeAccountSvc(WPARAM wParam, LPARAM lParam)
-{
- HYAMNPROTOPLUGIN Plugin = (HYAMNPROTOPLUGIN)wParam;
- CAccount *Finder;
-
- if (Plugin->FirstAccount == nullptr) {
- Plugin->FirstAccount = (CAccount *)CallService(MS_YAMN_CREATEPLUGINACCOUNT, wParam, lParam);
- return (INT_PTR)Plugin->FirstAccount;
- }
- for (Finder = Plugin->FirstAccount; Finder->Next != nullptr; Finder = Finder->Next);
- Finder->Next = (CAccount *)CallService(MS_YAMN_CREATEPLUGINACCOUNT, wParam, lParam);
- return (INT_PTR)Finder->Next;
-}
-
-INT_PTR DeleteAccountSvc(WPARAM wParam, LPARAM lParam)
-{
- //Deleting account works on these steps:
- //1. set signal that account should stop activity (set event)
- // setting this event we achieve, that any access to account is failed,
- // so threads do not start any work with accounts (better saying threads of plugins should not start)
- //2. wait to get write access to chained list of accounts
- //3. we can write to chained list, so we change chain not to show to actual account
- // now, any thread browsing list of accounts does not browse through actual account
- // actual account seems to be hidden (it exists, but it is not in accounts chained list (chained list=queue))
- //Now, we should delete account from memory, BUT!!!
- // Any thread can still be waked up and start asking account synchronizing object
- // If account is deleted, asking about access to read account can throw memory exception (reading for
- // a synchronizing object from memory, that was deleted)
- //So, we cannot now delete account. We have to wait until we are sure no thread will be using account anymore
- // (or to the end of Miranda, but problem is in allocated memory- it is allocated and Miranda is SMALLER, faster, easier, isn't it?)
- // This deleting is achieved in 2 ways:
- // We have event in UsingThreads synchronization objects. This event signals that no thread will use actual account
- // 1. Any thread using account first increment UsingThread, so we know that account is used
- // 2. If thread is about to close, it should decrement UsingThread
- // 3. If thread creates another thread, that will use account, caller has to wait until the new thread does not
- // increment UsingThreads (imagine that caller ends before the new thread set it: if no other thread is using
- // account, account is automaticaly (decreasing UsingThreads) signaled as "not used" and we delete it. But then
- // new thread is going to read account...).
- //4. wait until UsingThread Event is signaled
- //5. delete account from memory
-
- HYAMNPROTOPLUGIN Plugin = (HYAMNPROTOPLUGIN)wParam;
- CAccount *Which = (CAccount *)lParam;
- CAccount *Finder;
-
- //1. set stop signal
- StopSignalFcn(Which);
- WindowList_BroadcastAsync(YAMNVar.MessageWnds, WM_YAMN_STOPACCOUNT, (WPARAM)Which, 0);
- if (Plugin->Fcn->StopAccountFcnPtr != nullptr)
- Plugin->Fcn->StopAccountFcnPtr(Which);
-
- //2. wait to get write access
- SWMRGWaitToWrite(Plugin->AccountBrowserSO, INFINITE);
-
- //3. remove from queue (chained list)
- if (Plugin->FirstAccount == nullptr) {
- SWMRGDoneWriting(Plugin->AccountBrowserSO);
- return 0;
- }
- if (Plugin->FirstAccount == Which) {
- Finder = Plugin->FirstAccount->Next;
- Plugin->FirstAccount = Finder;
- }
- else {
- for (Finder = Plugin->FirstAccount; Which != Finder->Next; Finder = Finder->Next);
- Finder->Next = Finder->Next->Next;
- }
-
- //leave write access
- SWMRGDoneWriting(Plugin->AccountBrowserSO);
-
- //4. wait while event "UsingThread" is not signaled
- // And what to do, if this event will be signaled in 1 hour? (Although it's paranoia, because we have sent "delete signal", so
- // other threads do not start any new work with actual account) We will wait in blocked state?
- // No, of course not. We will create new thread, that will wait and additionally remove our thread in background.
- //5. So, the last point (deleting from memory) is performed in new DeleteAccountInBackground thread
-
- if ((Plugin->Fcn != nullptr) && (Plugin->Fcn->WriteAccountsFcnPtr != nullptr))
- Plugin->Fcn->WriteAccountsFcnPtr();
- CloseHandle(mir_forkthread(DeleteAccountInBackground, (void *)Which));
-
- //Now, plugin can consider account as deleted, but plugin really can achieve deleting this account from memory when using
- //event UsingThreads.
- return 1;
-}
-
-void __cdecl DeleteAccountInBackground(void *Value)
-{
- CAccount *Which = (CAccount *)Value;
- WaitForSingleObject(Which->UsingThreads->Event, INFINITE);
- CallService(MS_YAMN_DELETEPLUGINACCOUNT, (WPARAM)Which, 0);
-}
-
-int StopAccounts(HYAMNPROTOPLUGIN Plugin)
-{
- CAccount *Finder;
-
- //1. wait to get write access
- SWMRGWaitToWrite(Plugin->AccountBrowserSO, INFINITE);
-
- for (Finder = Plugin->FirstAccount; Finder != nullptr; Finder = Finder->Next) {
- //2. set stop signal
- StopSignalFcn(Finder);
- WindowList_BroadcastAsync(YAMNVar.MessageWnds, WM_YAMN_STOPACCOUNT, (WPARAM)Finder, 0);
- if (Plugin->Fcn->StopAccountFcnPtr != nullptr)
- Plugin->Fcn->StopAccountFcnPtr(Finder);
- }
-
- //leave write access
- SWMRGDoneWriting(Plugin->AccountBrowserSO);
-
- //Now, account is stopped. It can be removed from memory...
- return 1;
-}
-
-int WaitForAllAccounts(HYAMNPROTOPLUGIN Plugin, BOOL GetAccountBrowserAccess)
-{
- if (GetAccountBrowserAccess) {
- //1. wait to get write access
- SWMRGWaitToWrite(Plugin->AccountBrowserSO, INFINITE);
- }
- for (CAccount *Finder = Plugin->FirstAccount; Finder != nullptr; Finder = Finder->Next) {
- //2. wait for signal that account is not in use
- WaitForSingleObject(Finder->UsingThreads->Event, INFINITE);
- SetEvent(Finder->UsingThreads->Event);
- }
- if (GetAccountBrowserAccess) {
- //leave write access
- SWMRGDoneWriting(Plugin->AccountBrowserSO);
- }
-
- return 1;
-}
-
-int DeleteAccounts(HYAMNPROTOPLUGIN Plugin)
-{
- //1. wait to get write access
- SWMRGWaitToWrite(Plugin->AccountBrowserSO, INFINITE);
-
- WaitForAllAccounts(Plugin, FALSE);
-
- for (CAccount *Finder = Plugin->FirstAccount; Finder != nullptr;) {
- CAccount *Next = Finder->Next;
- DeletePluginAccountSvc((WPARAM)Finder, 0);
- Finder = Next;
- }
-
- //leave write access
- SWMRGDoneWriting(Plugin->AccountBrowserSO);
- return 1;
-}
-
-void WINAPI GetStatusFcn(CAccount *Which, wchar_t *Value)
-{
- if (Which == nullptr)
- return;
-
- mir_cslock lck(csAccountStatusCS);
- mir_wstrcpy(Value, Which->Status);
-}
-
-void WINAPI SetStatusFcn(CAccount *Which, wchar_t *Value)
-{
- if (Which != nullptr) {
- mir_cslock lck(csAccountStatusCS);
- mir_wstrcpy(Which->Status, Value);
- }
-
- WindowList_BroadcastAsync(YAMNVar.MessageWnds, WM_YAMN_CHANGESTATUS, (WPARAM)Which, 0);
-}
+/*
+ * This code implements manipulation with accounts
+ * such as reading accounts from file, writing them to file,
+ * finding account by name etc.
+ *
+ * (c) majvan 2002-2004
+ */
+
+#include "stdafx.h"
+
+ // Account status CS
+ // When we check some account, thread should change status of account to idle, connecting etc.
+ // So if we want to read status, we have to successfully write and then read.
+static mir_cs csAccountStatusCS;
+
+// File Writing CS
+// When 2 threads want to write to file...
+static mir_cs csFileWritingCS;
+
+struct CExportedFunctions AccountExportedFcn[] =
+{
+ {YAMN_GETSTATUSID, (void *)GetStatusFcn},
+ {YAMN_SETSTATUSID, (void *)SetStatusFcn},
+};
+
+struct CExportedServices AccountExportedSvc[] =
+{
+ {MS_YAMN_CREATEPLUGINACCOUNT, CreatePluginAccountSvc},
+ {MS_YAMN_DELETEPLUGINACCOUNT, DeletePluginAccountSvc},
+ {MS_YAMN_FINDACCOUNTBYNAME, FindAccountByNameSvc},
+ {MS_YAMN_GETNEXTFREEACCOUNT, GetNextFreeAccountSvc},
+ {MS_YAMN_DELETEACCOUNT, DeletePluginAccountSvc},
+ {MS_YAMN_READACCOUNTS, AddAccountsFromFileSvc},
+ {MS_YAMN_WRITEACCOUNTS, WriteAccountsToFileSvc},
+};
+
+//--------------------------------------------------------------------------------------------------
+//--------------------------------------------------------------------------------------------------
+
+INT_PTR CreatePluginAccountSvc(WPARAM wParam, LPARAM lParam)
+{
+ HYAMNPROTOPLUGIN Plugin = (HYAMNPROTOPLUGIN)wParam;
+ uint32_t AccountVersion = (uint32_t)lParam;
+
+ //test if we are going to initialize members of suitable structure (structures of plugin and YAMN must match)
+ if (AccountVersion != YAMN_ACCOUNTVERSION)
+ return NULL;
+
+ if (Plugin != nullptr) {
+ CAccount *NewAccount;
+ if (Plugin->Fcn->NewAccountFcnPtr != nullptr)
+ //Let plugin create its own structure, which can be derived from CAccount structure
+ NewAccount = Plugin->Fcn->NewAccountFcnPtr(Plugin, YAMN_ACCOUNTVERSION);
+ else
+ //We suggest plugin uses standard CAccount structure, so we create it
+ NewAccount = new struct CAccount;
+
+ //If not created successfully
+ if (NewAccount == nullptr)
+ return NULL;
+
+ NewAccount->Plugin = Plugin;
+ //Init every members of structure, used by YAMN
+ InitAccount(NewAccount);
+
+ return (INT_PTR)NewAccount;
+ }
+ return NULL;
+}
+
+INT_PTR DeletePluginAccountSvc(WPARAM wParam, LPARAM)
+{
+ CAccount *OldAccount = (CAccount *)wParam;
+
+ if (OldAccount->Plugin->Fcn != nullptr) {
+ // Deinit every members and allocated fields of structure used by YAMN
+ DeInitAccount(OldAccount);
+ if (OldAccount->Plugin->Fcn->DeleteAccountFcnPtr != nullptr) {
+ // Let plugin delete its own CAccount derived structure
+ OldAccount->Plugin->Fcn->DeleteAccountFcnPtr(OldAccount);
+ }
+ else {
+ delete OldAccount; //consider account as standard YAMN CAccount *and use its own destructor
+ }
+ return 1;
+ }
+ delete OldAccount; //consider account as standard YAMN CAccount *, not initialized before and use its own destructor
+ return 1;
+}
+
+int InitAccount(CAccount *Which)
+{
+ //initialize synchronizing objects
+ Which->AccountAccessSO = new SWMRG;
+ SWMRGInitialize(Which->AccountAccessSO, nullptr);
+ Which->MessagesAccessSO = new SWMRG;
+ SWMRGInitialize(Which->MessagesAccessSO, nullptr);
+ Which->UsingThreads = new SCOUNTER;
+ SWMRGInitialize(Which->MessagesAccessSO, nullptr);
+
+ //zero memory, where timestamps are stored
+ memset(&Which->LastChecked, 0, sizeof(Which->LastChecked));
+ memset(&Which->LastSChecked, 0, sizeof(Which->LastSChecked));
+ memset(&Which->LastSynchronised, 0, sizeof(Which->LastSynchronised));
+ memset(&Which->LastMail, 0, sizeof(Which->LastMail));
+
+ Which->Name = nullptr;
+ Which->Mails = nullptr;
+ Which->Interval = 0;
+ Which->Flags = 0;
+ Which->StatusFlags = YAMN_ACC_ST1 + YAMN_ACC_ST7;
+ Which->Next = nullptr;
+
+ Which->Server = new struct CServer;
+ Which->AbleToWork = TRUE;
+
+ return 1;
+}
+
+void DeInitAccount(CAccount *Which)
+{
+ //delete YAMN allocated fields
+ if (Which->Name != nullptr)
+ delete[] Which->Name;
+ if (Which->Server != nullptr) {
+ if (Which->Server->Name != nullptr)
+ delete[] Which->Server->Name;
+ if (Which->Server->Login != nullptr)
+ delete[] Which->Server->Login;
+ if (Which->Server->Passwd != nullptr)
+ delete[] Which->Server->Passwd;
+ delete[] Which->Server;
+ }
+
+ SWMRGDelete(Which->AccountAccessSO);
+ delete Which->AccountAccessSO;
+ SWMRGDelete(Which->MessagesAccessSO);
+ delete Which->MessagesAccessSO;
+ delete Which->UsingThreads;
+ DeleteMessagesToEndFcn(Which, (HYAMNMAIL)Which->Mails);
+}
+
+void StopSignalFcn(CAccount *Which)
+//set event that we are going to delete account
+{
+ Which->AbleToWork = FALSE;
+ //do not use synchronizing objects anymore
+ //any access to these objects then ends with WAIT_FAILED
+ SetEvent(Which->AccountAccessSO->hFinishEV);
+ SetEvent(Which->MessagesAccessSO->hFinishEV);
+}
+
+void CodeDecodeString(char *Dest, BOOL Encrypt)
+{
+ wchar_t Code = STARTCODEPSW;
+
+ if (Dest == nullptr)
+ return;
+
+ for (; *Dest != (wchar_t)0; Dest++) {
+ if (Encrypt)
+ *Dest = *Dest + Code;
+ else
+ *Dest = *Dest - Code;
+ Code += (wchar_t)ADDCODEPSW;
+ }
+}
+
+static uint32_t PostFileToMemory(HANDLE File, char **MemFile, char **End)
+{
+ DWORD FileSize, ReadBytes;
+ if (!(FileSize = GetFileSize(File, nullptr))) {
+ CloseHandle(File);
+ return EACC_FILESIZE;
+ }
+
+ //allocate space in memory, where we copy the whole file
+ if (nullptr == (*MemFile = new char[FileSize])) {
+ CloseHandle(File);
+ return EACC_ALLOC;
+ }
+
+ //copy file to memory
+ if (!ReadFile(File, (LPVOID)*MemFile, FileSize, &ReadBytes, nullptr)) {
+ CloseHandle(File);
+ delete[] * MemFile;
+ return EACC_SYSTEM;
+ }
+ CloseHandle(File);
+ *End = *MemFile + FileSize;
+ return 0;
+}
+
+uint32_t FileToMemory(wchar_t *FileName, char **MemFile, char **End)
+{
+ HANDLE hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
+ if (hFile == INVALID_HANDLE_VALUE)
+ return EACC_SYSTEM;
+
+ return PostFileToMemory(hFile, MemFile, End);
+}
+
+#if defined(DEBUG_FILEREAD) || defined(DEBUG_FILEREADMESSAGES)
+uint32_t ReadStringFromMemory(char **Parser, wchar_t *End, char **StoreTo, wchar_t *DebugString)
+{
+ //This is the debug version of ReadStringFromMemory function. This version shows MessageBox where
+ //read string is displayed
+ wchar_t *Dest, *Finder;
+ uint32_t Size;
+ wchar_t Debug[65536];
+
+ Finder = *Parser;
+ while ((*Finder != (wchar_t)0) && (Finder <= End)) Finder++;
+ mir_snwprintf(Debug, L"%s: %s,length is %d, remaining %d chars", DebugString, *Parser, Finder - *Parser, End - Finder);
+ MessageBox(NULL, Debug, L"debug", MB_OK);
+ if (Finder >= End)
+ return EACC_FILECOMPATIBILITY;
+ if (Size = Finder - *Parser) {
+ if (NULL == (Dest = *StoreTo = new wchar_t[Size + 1]))
+ return EACC_ALLOC;
+ for (; *Parser <= Finder; (*Parser)++, Dest++)
+ *Dest = **Parser;
+ }
+ else {
+ *StoreTo = NULL;
+ (*Parser)++;
+ }
+ return 0;
+}
+#endif
+
+uint32_t ReadStringFromMemory(char **Parser, char *End, char **StoreTo)
+{
+ char *Dest, *Finder;
+ uint32_t Size;
+
+ Finder = *Parser;
+ while ((*Finder != (wchar_t)0) && (Finder <= End)) Finder++;
+ if (Finder >= End)
+ return EACC_FILECOMPATIBILITY;
+ if (Size = Finder - *Parser) {
+ if (nullptr == (Dest = *StoreTo = new char[Size + 1]))
+ return EACC_ALLOC;
+ for (; *Parser <= Finder; (*Parser)++, Dest++)
+ *Dest = **Parser;
+ }
+ else {
+ *StoreTo = nullptr;
+ (*Parser)++;
+ }
+ return 0;
+}
+
+#if defined(DEBUG_FILEREAD) || defined(DEBUG_FILEREADMESSAGES)
+uint32_t ReadStringFromMemoryW(wchar_t **Parser, wchar_t *End, wchar_t **StoreTo, wchar_t *DebugString)
+{
+ //This is the debug version of ReadStringFromMemoryW function. This version shows MessageBox where
+ //read string is displayed
+ wchar_t *Dest, *Finder;
+ uint32_t Size;
+ wchar_t Debug[65536];
+
+ Finder = *Parser;
+ while ((*Finder != (wchar_t)0) && (Finder <= (wchar_t *)End)) Finder++;
+ mir_snwprintf(Debug, L"%s: %s,length is %d, remaining %d chars", DebugString, *Parser, Finder - *Parser, (wchar_t *)End - Finder);
+ MessageBoxW(NULL, Debug, L"debug", MB_OK);
+ if (Finder >= (wchar_t *)End)
+ return EACC_FILECOMPATIBILITY;
+ if (Size = Finder - *Parser) {
+ if (NULL == (Dest = *StoreTo = new wchar_t[Size + 1]))
+ return EACC_ALLOC;
+ for (; *Parser <= Finder; (*Parser)++, Dest++)
+ *Dest = **Parser;
+ }
+ else {
+ *StoreTo = NULL;
+ (*Parser)++;
+ }
+ return 0;
+}
+#endif //if defined(DEBUG...)
+
+uint32_t ReadStringFromMemoryW(wchar_t **Parser, wchar_t *End, wchar_t **StoreTo)
+{
+ wchar_t *Dest, *Finder;
+ uint32_t Size;
+
+ Finder = *Parser;
+ while ((*Finder != (wchar_t)0) && (Finder <= (wchar_t *)End)) Finder++;
+ if (Finder >= (wchar_t *)End)
+ return EACC_FILECOMPATIBILITY;
+ if (Size = Finder - *Parser) {
+ if (nullptr == (Dest = *StoreTo = new wchar_t[Size + 1]))
+ return EACC_ALLOC;
+ for (; *Parser <= Finder; (*Parser)++, Dest++)
+ *Dest = **Parser;
+ }
+ else {
+ *StoreTo = nullptr;
+ (*Parser)++;
+ }
+ return 0;
+}
+
+static uint32_t ReadNotificationFromMemory(char **Parser, char *End, YAMN_NOTIFICATION *Which)
+{
+ uint32_t Stat;
+ #ifdef DEBUG_FILEREAD
+ wchar_t Debug[65536];
+ #endif
+
+ Which->Flags = *(uint32_t *)(*Parser);
+ (*Parser) += sizeof(uint32_t);
+ if (*Parser >= End)
+ return EACC_FILECOMPATIBILITY;
+ #ifdef DEBUG_FILEREAD
+ mir_snwprintf(Debug, L"NFlags: %04x, remaining %d chars", Which->Flags, End - *Parser);
+ MessageBox(NULL, Debug, L"debug", MB_OK);
+ #endif
+
+ Which->PopupB = *(COLORREF *)(*Parser);
+ (*Parser) += sizeof(COLORREF);
+ if (*Parser >= End)
+ return EACC_FILECOMPATIBILITY;
+ #ifdef DEBUG_FILEREAD
+ mir_snwprintf(Debug, L"PopupB: %04x, remaining %d chars", Which->PopupB, End - *Parser);
+ MessageBox(NULL, Debug, L"debug", MB_OK);
+ #endif
+ Which->PopupT = *(COLORREF *)(*Parser);
+ (*Parser) += sizeof(COLORREF);
+ if (*Parser >= End)
+ return EACC_FILECOMPATIBILITY;
+ #ifdef DEBUG_FILEREAD
+ mir_snwprintf(Debug, L"PopupT: %04x, remaining %d chars", Which->PopupT, End - *Parser);
+ MessageBox(NULL, Debug, L"debug", MB_OK);
+ #endif
+ Which->PopupTime = *(uint32_t *)(*Parser);
+ (*Parser) += sizeof(uint32_t);
+ if (*Parser >= End)
+ return EACC_FILECOMPATIBILITY;
+ #ifdef DEBUG_FILEREAD
+ mir_snwprintf(Debug, L"PopupTime: %04x, remaining %d chars", Which->PopupTime, End - *Parser);
+ MessageBox(NULL, Debug, L"debug", MB_OK);
+ #endif
+
+ #ifdef DEBUG_FILEREAD
+ if (Stat = ReadStringFromMemoryW((wchar_t **)Parser, (wchar_t *)End, &Which->App, L"App"))
+ #else
+ if (Stat = ReadStringFromMemoryW((wchar_t **)Parser, (wchar_t *)End, &Which->App))
+ #endif
+ return Stat;
+ #ifdef DEBUG_FILEREAD
+ if (Stat = ReadStringFromMemoryW((wchar_t **)Parser, (wchar_t *)End, &Which->AppParam, L"AppParam"))
+ #else
+ if (Stat = ReadStringFromMemoryW((wchar_t **)Parser, (wchar_t *)End, &Which->AppParam))
+ #endif
+ return Stat;
+ return 0;
+}
+
+uint32_t ReadMessagesFromMemory(CAccount *Which, char **Parser, char *End)
+{
+ char *Finder;
+ uint32_t Size, Stat;
+ HYAMNMAIL ActualMail = nullptr;
+ struct CMimeItem *items;
+ char *ReadString;
+
+ #ifdef DEBUG_FILEREAD
+ MessageBox(NULL, L"going to read messages, if any...", L"debug", MB_OK);
+ #endif
+ do {
+ Finder = *Parser;
+ while ((*Finder != (wchar_t)0) && (Finder <= End)) Finder++;
+ if (Finder >= End)
+ return EACC_FILECOMPATIBILITY;
+ if (Size = Finder - *Parser) {
+ if (Which->Mails == nullptr) //First message in queue
+ {
+ if (nullptr == (Which->Mails = ActualMail = CreateAccountMail(Which)))
+ return EACC_ALLOC;
+ }
+ else {
+ if (nullptr == (ActualMail->Next = CreateAccountMail(Which))) {
+ return EACC_ALLOC;
+ }
+ ActualMail = ActualMail->Next;
+ }
+ items = nullptr;
+ #ifdef DEBUG_FILEREADMESSAGES
+ if (Stat = ReadStringFromMemory(Parser, End, &ActualMail->ID, L"ID"))
+ #else
+ if (Stat = ReadStringFromMemory(Parser, End, &ActualMail->ID))
+ #endif
+ return Stat;
+ // ActualMail->MailData=new MAILDATA; !!! mem leake !!! this is alloc by CreateAccountMail, no need for doubble alloc !!!!
+
+ ActualMail->MailData->Size = *(uint32_t *)(*Parser);
+ (*Parser) += sizeof(uint32_t);
+ if (*Parser >= End)
+ return EACC_FILECOMPATIBILITY;
+ ActualMail->Flags = *(uint32_t *)(*Parser);
+ (*Parser) += sizeof(uint32_t);
+ if (*Parser >= End)
+ return EACC_FILECOMPATIBILITY;
+ ActualMail->Number = *(uint32_t *)(*Parser);
+ (*Parser) += sizeof(uint32_t);
+ if (*Parser >= End)
+ return EACC_FILECOMPATIBILITY;
+
+ if ((nullptr != Which->Plugin->MailFcn) && (nullptr != Which->Plugin->MailFcn->ReadMailOptsFcnPtr))
+ Which->Plugin->MailFcn->ReadMailOptsFcnPtr(ActualMail, Parser, End); //read plugin mail settings from file
+
+ do {
+ #if defined(DEBUG_FILEREADMESSAGES) || defined(DEBUG_FILEREAD)
+ if (Stat = ReadStringFromMemory(Parser, End, &ReadString, L"Name"))
+ #else
+ if (Stat = ReadStringFromMemory(Parser, End, &ReadString))
+ #endif
+ return Stat;
+ if (ReadString == nullptr)
+ break;
+
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<read name>%s</read name>", ReadString);
+ #endif
+
+ if (items == nullptr)
+ items = ActualMail->MailData->TranslatedHeader = new struct CMimeItem;
+ else {
+ items->Next = new struct CMimeItem;
+ items = items->Next;
+ }
+ if (items == nullptr)
+ return EACC_ALLOC;
+ items->name = ReadString;
+
+ #ifdef DEBUG_FILEREADMESSAGES
+ if (Stat = ReadStringFromMemory(Parser, End, &ReadString, L"Value"))
+ #else
+ if (Stat = ReadStringFromMemory(Parser, End, &ReadString))
+ #endif
+ return Stat;
+ items->value = ReadString;
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<read value>%s</read value>\n", ReadString);
+ #endif
+ } while (1);
+ }
+ else
+ break; //no next messages, new account!
+
+ } while (1);
+ (*Parser)++;
+ return 0;
+}
+
+uint32_t ReadAccountFromMemory(CAccount *Which, char **Parser, char *End)
+{
+ uint32_t Stat;
+ #ifdef DEBUG_FILEREAD
+ wchar_t Debug[65536];
+ #endif
+ //Read name of account
+
+ #ifdef DEBUG_FILEREAD
+ if (Stat = ReadStringFromMemory(Parser, End, &Which->Name, L"Name"))
+ #else
+ if (Stat = ReadStringFromMemory(Parser, End, &Which->Name))
+ #endif
+ return Stat;
+ if (Which->Name == nullptr)
+ return EACC_FILECOMPATIBILITY;
+
+ //Read server parameters
+ #ifdef DEBUG_FILEREAD
+ if (Stat = ReadStringFromMemory(Parser, End, &Which->Server->Name, L"Server"))
+ #else
+ if (Stat = ReadStringFromMemory(Parser, End, &Which->Server->Name))
+ #endif
+ return Stat;
+ Which->Server->Port = *(uint16_t *)(*Parser);
+ (*Parser) += sizeof(uint16_t);
+ if (*Parser >= End)
+ return EACC_FILECOMPATIBILITY;
+ #ifdef DEBUG_FILEREAD
+ mir_snwprintf(Debug, L"Port: %d, remaining %d chars", Which->Server->Port, End - *Parser);
+ MessageBox(NULL, Debug, L"debug", MB_OK);
+ #endif
+ #ifdef DEBUG_FILEREAD
+ if (Stat = ReadStringFromMemory(Parser, End, &Which->Server->Login, L"Login"))
+ #else
+ if (Stat = ReadStringFromMemory(Parser, End, &Which->Server->Login))
+ #endif
+ return Stat;
+ #ifdef DEBUG_FILEREAD
+ if (Stat = ReadStringFromMemory(Parser, End, &Which->Server->Passwd, L"Password"))
+ #else
+ if (Stat = ReadStringFromMemory(Parser, End, &Which->Server->Passwd))
+ #endif
+ return Stat;
+ CodeDecodeString(Which->Server->Passwd, FALSE);
+
+ //Read account flags
+ Which->Flags = *(uint32_t *)(*Parser);
+ (*Parser) += sizeof(uint32_t);
+ if (*Parser >= End)
+ return EACC_FILECOMPATIBILITY;
+ #ifdef DEBUG_FILEREAD
+ mir_snwprintf(Debug, L"Flags: %04x, remaining %d chars", Which->Flags, End - *Parser);
+ MessageBox(NULL, Debug, L"debug", MB_OK);
+ #endif
+ Which->StatusFlags = *(uint32_t *)(*Parser);
+ (*Parser) += sizeof(uint32_t);
+ #ifdef DEBUG_FILEREAD
+ mir_snwprintf(Debug, L"STFlags: %04x, remaining %d chars", Which->StatusFlags, End - *Parser);
+ MessageBox(NULL, Debug, L"debug", MB_OK);
+ #endif
+ Which->PluginFlags = *(uint32_t *)(*Parser);
+ (*Parser) += sizeof(uint32_t);
+ #ifdef DEBUG_FILEREAD
+ mir_snwprintf(Debug, L"PFlags: %04x, remaining %d chars", Which->PluginFlags, End - *Parser);
+ MessageBox(NULL, Debug, L"debug", MB_OK);
+ #endif
+
+ //Read account miscellaneous parameters
+ Which->Interval = *(uint16_t *)(*Parser);
+ Which->TimeLeft = Which->Interval; //check on loading
+ (*Parser) += sizeof(uint16_t);
+ if (*Parser >= End)
+ return EACC_FILECOMPATIBILITY;
+ #ifdef DEBUG_FILEREAD
+ mir_snwprintf(Debug, L"Interval: %d, remaining %d chars", Which->Interval, End - *Parser);
+ MessageBox(NULL, Debug, L"debug", MB_OK);
+ #endif
+
+ //Read notification parameters
+ if (Stat = ReadNotificationFromMemory(Parser, End, &Which->NewMailN))
+ return Stat;
+ if (Stat = ReadNotificationFromMemory(Parser, End, &Which->NoNewMailN))
+ return Stat;
+ if (Stat = ReadNotificationFromMemory(Parser, End, &Which->BadConnectN))
+ return Stat;
+
+ //Let plugin read its own data stored in file
+ if (Which->Plugin->Fcn != nullptr && Which->Plugin->Fcn->ReadPluginOptsFcnPtr != nullptr)
+ if (Stat = Which->Plugin->Fcn->ReadPluginOptsFcnPtr(Which, Parser, End))
+ return Stat;
+
+ // Read mails
+ WaitToWriteFcn(Which->MessagesAccessSO);
+
+ if (Stat = ReadMessagesFromMemory(Which, Parser, End)) {
+ WriteDoneFcn(Which->MessagesAccessSO);
+ return Stat;
+ }
+
+ WriteDoneFcn(Which->MessagesAccessSO);
+
+ // Read timestamps
+ Which->LastChecked = *(SYSTEMTIME *)(*Parser);
+ (*Parser) += sizeof(SYSTEMTIME);
+ if (*Parser >= End)
+ return EACC_FILECOMPATIBILITY;
+
+ Which->LastSChecked = *(SYSTEMTIME *)(*Parser);
+ (*Parser) += sizeof(SYSTEMTIME);
+ if (*Parser >= End)
+ return EACC_FILECOMPATIBILITY;
+
+ Which->LastSynchronised = *(SYSTEMTIME *)(*Parser);
+ (*Parser) += sizeof(SYSTEMTIME);
+ if (*Parser >= End)
+ return EACC_FILECOMPATIBILITY;
+
+ Which->LastMail = *(SYSTEMTIME *)(*Parser);
+ (*Parser) += sizeof(SYSTEMTIME);
+ if (*Parser > End) //WARNING! There's only > at the end of testing
+ return EACC_FILECOMPATIBILITY;
+
+ if (*Parser == End)
+ return EACC_ENDOFFILE;
+ return 0;
+}
+
+static INT_PTR PerformAccountReading(HYAMNPROTOPLUGIN Plugin, char *MemFile, char *End)
+{
+ // Retrieve info for account from memory
+ char *Parser;
+ uint32_t Ver, Stat;
+
+ CAccount *ActualAccount, *FirstAllocatedAccount;
+
+ Ver = *(uint32_t *)MemFile;
+ if (Ver > YAMN_ACCOUNTFILEVERSION) {
+ delete[] MemFile;
+ return EACC_FILEVERSION;
+ }
+ Parser = MemFile + sizeof(Ver);
+
+ SWMRGWaitToWrite(Plugin->AccountBrowserSO, INFINITE);
+
+ if (nullptr == (ActualAccount = (CAccount *)CallService(MS_YAMN_GETNEXTFREEACCOUNT, (WPARAM)Plugin, (LPARAM)YAMN_ACCOUNTVERSION))) {
+ SWMRGDoneWriting(Plugin->AccountBrowserSO);
+ delete[] MemFile;
+ return EACC_ALLOC;
+ }
+
+ FirstAllocatedAccount = ActualAccount;
+
+ do {
+ CAccount *Temp;
+
+ WaitToWriteFcn(ActualAccount->AccountAccessSO);
+ Stat = ReadAccountFromMemory(ActualAccount, &Parser, End);
+
+ if (ActualAccount->StatusFlags & (YAMN_ACC_STARTA | YAMN_ACC_STARTS))
+ ActualAccount->TimeLeft = 1; //check on loading
+
+ if (Stat && (Stat != EACC_ENDOFFILE)) {
+ for (ActualAccount = FirstAllocatedAccount; ActualAccount != nullptr; ActualAccount = Temp) {
+ Temp = ActualAccount->Next;
+ delete ActualAccount;
+ }
+ delete[] MemFile;
+ if (Plugin->FirstAccount == FirstAllocatedAccount)
+ Plugin->FirstAccount = nullptr;
+
+ SWMRGDoneWriting(Plugin->AccountBrowserSO);
+ return (INT_PTR)Stat;
+ }
+
+ WriteDoneFcn(ActualAccount->AccountAccessSO);
+
+ if ((Stat != EACC_ENDOFFILE) && (nullptr == (ActualAccount = (CAccount *)CallService(MS_YAMN_GETNEXTFREEACCOUNT, (WPARAM)Plugin, (LPARAM)YAMN_ACCOUNTVERSION)))) {
+ for (ActualAccount = FirstAllocatedAccount; ActualAccount != nullptr; ActualAccount = Temp) {
+ Temp = ActualAccount->Next;
+ delete ActualAccount;
+ }
+ delete[] MemFile;
+ if (Plugin->FirstAccount == FirstAllocatedAccount)
+ Plugin->FirstAccount = nullptr;
+
+ SWMRGDoneWriting(Plugin->AccountBrowserSO);
+ return EACC_ALLOC;
+ }
+ } while (Stat != EACC_ENDOFFILE);
+
+ SWMRGDoneWriting(Plugin->AccountBrowserSO);
+ delete[] MemFile;
+ return 0;
+}
+
+// Add accounts from file to memory
+INT_PTR AddAccountsFromFileSvc(WPARAM wParam, LPARAM lParam)
+{
+ char *MemFile, *End;
+ uint32_t Stat = FileToMemory((wchar_t *)lParam, &MemFile, &End);
+ if (Stat != NO_ERROR)
+ return (INT_PTR)Stat;
+
+ return PerformAccountReading((HYAMNPROTOPLUGIN)wParam, MemFile, End);
+}
+
+uint32_t WriteStringToFile(HANDLE File, char *Source)
+{
+ DWORD Length, WrittenBytes;
+ char null = 0;
+
+ if ((Source == nullptr) || !(Length = (uint32_t)mir_strlen(Source))) {
+ if (!WriteFile(File, &null, 1, &WrittenBytes, nullptr)) {
+ CloseHandle(File);
+ return EACC_SYSTEM;
+ }
+ }
+ else if (!WriteFile(File, Source, (Length + 1), &WrittenBytes, nullptr)) {
+ CloseHandle(File);
+ return EACC_SYSTEM;
+ }
+ return 0;
+}
+
+uint32_t WriteStringToFileW(HANDLE File, wchar_t *Source)
+{
+ DWORD Length, WrittenBytes;
+ wchar_t null = (wchar_t)0;
+
+ if ((Source == nullptr) || !(Length = (uint32_t)mir_wstrlen(Source))) {
+ if (!WriteFile(File, &null, sizeof(wchar_t), &WrittenBytes, nullptr)) {
+ CloseHandle(File);
+ return EACC_SYSTEM;
+ }
+ }
+ else if (!WriteFile(File, Source, (Length + 1) * sizeof(wchar_t), &WrittenBytes, nullptr))
+ return EACC_SYSTEM;
+ return 0;
+}
+
+DWORD WriteMessagesToFile(HANDLE File, CAccount *Which)
+{
+ DWORD WrittenBytes, Stat;
+ HYAMNMAIL ActualMail = (HYAMNMAIL)Which->Mails;
+ struct CMimeItem *items;
+
+ while (ActualMail != nullptr) {
+ if (Stat = WriteStringToFile(File, ActualMail->ID))
+ return Stat;
+
+ if (!WriteFile(File, (char *)&ActualMail->MailData->Size, sizeof(ActualMail->MailData->Size), &WrittenBytes, nullptr) ||
+ !WriteFile(File, (char *)&ActualMail->Flags, sizeof(ActualMail->Flags), &WrittenBytes, nullptr) ||
+ !WriteFile(File, (char *)&ActualMail->Number, sizeof(ActualMail->Number), &WrittenBytes, nullptr))
+ return EACC_SYSTEM;
+ if ((nullptr != Which->Plugin->MailFcn) && (nullptr != Which->Plugin->MailFcn->WriteMailOptsFcnPtr))
+ Which->Plugin->MailFcn->WriteMailOptsFcnPtr(File, ActualMail); //write plugin mail options to file
+ for (items = ActualMail->MailData->TranslatedHeader; items != nullptr; items = items->Next) {
+ if (Stat = WriteStringToFile(File, items->name))
+ return Stat;
+ if (Stat = WriteStringToFile(File, items->value))
+ return Stat;
+ }
+ if (Stat = WriteStringToFile(File, ""))
+ return Stat;
+ ActualMail = ActualMail->Next;
+ }
+ if (Stat = WriteStringToFile(File, ""))
+ return Stat;
+ return 0;
+}
+
+static INT_PTR PerformAccountWriting(HYAMNPROTOPLUGIN Plugin, HANDLE File)
+{
+ DWORD WrittenBytes, Stat;
+ CAccount *ActualAccount;
+ uint32_t Ver = YAMN_ACCOUNTFILEVERSION;
+ BOOL Writed = FALSE;
+ uint32_t ReturnValue = 0, EnterCode;
+
+ SWMRGWaitToRead(Plugin->AccountBrowserSO, INFINITE);
+
+ try {
+ for (ActualAccount = Plugin->FirstAccount; ActualAccount != nullptr; ActualAccount = ActualAccount->Next) {
+ EnterCode = WaitToReadFcn(ActualAccount->AccountAccessSO);
+ if (EnterCode == WAIT_FINISH) //account is about to delete
+ {
+ ActualAccount = ActualAccount->Next;
+ continue;
+ }
+ if (EnterCode == WAIT_FAILED) //account is deleted
+ break;
+
+ if ((ActualAccount->Name == nullptr) || (*ActualAccount->Name == (wchar_t)0)) {
+ ReadDoneFcn(ActualAccount->AccountAccessSO);
+ continue;
+ }
+
+ if (!Writed && !WriteFile(File, &Ver, sizeof(Ver), &WrittenBytes, nullptr))
+ throw (uint32_t)EACC_SYSTEM;
+
+ Writed = TRUE;
+
+ if (Stat = WriteStringToFile(File, ActualAccount->Name))
+ throw (uint32_t)Stat;
+
+ if (Stat = WriteStringToFile(File, ActualAccount->Server->Name))
+ throw (uint32_t)Stat;
+
+ if (!WriteFile(File, (char *)&ActualAccount->Server->Port, 2, &WrittenBytes, nullptr))
+ throw (uint32_t)EACC_SYSTEM;
+
+ if ((Stat = WriteStringToFile(File, ActualAccount->Server->Login)))
+ throw (uint32_t)Stat;
+
+ CodeDecodeString(ActualAccount->Server->Passwd, TRUE);
+
+ if (Stat = WriteStringToFile(File, ActualAccount->Server->Passwd)) {
+ CodeDecodeString(ActualAccount->Server->Passwd, FALSE);
+ throw (uint32_t)Stat;
+ }
+ CodeDecodeString(ActualAccount->Server->Passwd, FALSE);
+
+ if ((!WriteFile(File, (char *)&ActualAccount->Flags, sizeof(uint32_t), &WrittenBytes, nullptr) ||
+ (!WriteFile(File, (char *)&ActualAccount->StatusFlags, sizeof(uint32_t), &WrittenBytes, nullptr)) ||
+ (!WriteFile(File, (char *)&ActualAccount->PluginFlags, sizeof(uint32_t), &WrittenBytes, nullptr))))
+ throw (uint32_t)EACC_SYSTEM;
+
+ if (!WriteFile(File, (char *)&ActualAccount->Interval, sizeof(uint16_t), &WrittenBytes, nullptr))
+ throw (uint32_t)EACC_SYSTEM;
+
+ if ((!WriteFile(File, (char *)&ActualAccount->NewMailN.Flags, sizeof(uint32_t), &WrittenBytes, nullptr)) ||
+ (!WriteFile(File, (char *)&ActualAccount->NewMailN.PopupB, sizeof(COLORREF), &WrittenBytes, nullptr)) ||
+ (!WriteFile(File, (char *)&ActualAccount->NewMailN.PopupT, sizeof(COLORREF), &WrittenBytes, nullptr)) ||
+ (!WriteFile(File, (char *)&ActualAccount->NewMailN.PopupTime, sizeof(uint32_t), &WrittenBytes, nullptr)))
+ throw (uint32_t)EACC_SYSTEM;
+
+ if ((Stat = WriteStringToFileW(File, ActualAccount->NewMailN.App)) ||
+ (Stat = WriteStringToFileW(File, ActualAccount->NewMailN.AppParam)))
+ throw (uint32_t)Stat;
+
+ if ((!WriteFile(File, (char *)&ActualAccount->NoNewMailN.Flags, sizeof(uint32_t), &WrittenBytes, nullptr)) ||
+ (!WriteFile(File, (char *)&ActualAccount->NoNewMailN.PopupB, sizeof(COLORREF), &WrittenBytes, nullptr)) ||
+ (!WriteFile(File, (char *)&ActualAccount->NoNewMailN.PopupT, sizeof(COLORREF), &WrittenBytes, nullptr)) ||
+ (!WriteFile(File, (char *)&ActualAccount->NoNewMailN.PopupTime, sizeof(uint32_t), &WrittenBytes, nullptr)))
+ throw (uint32_t)EACC_SYSTEM;
+
+ if ((Stat = WriteStringToFileW(File, ActualAccount->NoNewMailN.App)) ||
+ (Stat = WriteStringToFileW(File, ActualAccount->NoNewMailN.AppParam)))
+ throw (uint32_t)Stat;
+
+ if ((!WriteFile(File, (char *)&ActualAccount->BadConnectN.Flags, sizeof(uint32_t), &WrittenBytes, nullptr)) ||
+ (!WriteFile(File, (char *)&ActualAccount->BadConnectN.PopupB, sizeof(COLORREF), &WrittenBytes, nullptr)) ||
+ (!WriteFile(File, (char *)&ActualAccount->BadConnectN.PopupT, sizeof(COLORREF), &WrittenBytes, nullptr)) ||
+ (!WriteFile(File, (char *)&ActualAccount->BadConnectN.PopupTime, sizeof(uint32_t), &WrittenBytes, nullptr)))
+ throw (uint32_t)EACC_SYSTEM;
+
+ if ((Stat = WriteStringToFileW(File, ActualAccount->BadConnectN.App)) ||
+ (Stat = WriteStringToFileW(File, ActualAccount->BadConnectN.AppParam)))
+ throw (uint32_t)Stat;
+
+ //Let plugin write its own values into file
+ if (ActualAccount->Plugin->Fcn != nullptr && ActualAccount->Plugin->Fcn->WritePluginOptsFcnPtr != nullptr)
+ if (Stat = ActualAccount->Plugin->Fcn->WritePluginOptsFcnPtr(File, ActualAccount))
+ throw (uint32_t)Stat;
+
+ WaitToReadFcn(ActualAccount->MessagesAccessSO);
+
+ if (Stat = WriteMessagesToFile(File, ActualAccount)) {
+
+ ReadDoneFcn(ActualAccount->MessagesAccessSO);
+ throw (uint32_t)Stat;
+ }
+
+ ReadDoneFcn(ActualAccount->MessagesAccessSO);
+
+ if ((!WriteFile(File, (char *)&ActualAccount->LastChecked, sizeof(SYSTEMTIME), &WrittenBytes, nullptr)) ||
+ (!WriteFile(File, (char *)&ActualAccount->LastSChecked, sizeof(SYSTEMTIME), &WrittenBytes, nullptr)) ||
+ (!WriteFile(File, (char *)&ActualAccount->LastSynchronised, sizeof(SYSTEMTIME), &WrittenBytes, nullptr)) ||
+ (!WriteFile(File, (char *)&ActualAccount->LastMail, sizeof(SYSTEMTIME), &WrittenBytes, nullptr)))
+ throw (uint32_t)Stat;
+
+ ReadDoneFcn(ActualAccount->AccountAccessSO);
+ }
+ }
+ catch (uint32_t ErrorCode) {
+ ReadDoneFcn(ActualAccount->AccountAccessSO);
+ ReturnValue = ErrorCode;
+ }
+
+ SWMRGDoneReading(Plugin->AccountBrowserSO);
+ CloseHandle(File);
+ return 0;
+}
+
+// Writes accounts to file
+INT_PTR WriteAccountsToFileSvc(WPARAM wParam, LPARAM lParam)
+{
+ HYAMNPROTOPLUGIN Plugin = (HYAMNPROTOPLUGIN)wParam;
+
+ mir_cslock lck(csFileWritingCS);
+ HANDLE hFile = CreateFile((wchar_t *)lParam, GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
+ if (hFile == INVALID_HANDLE_VALUE)
+ return EACC_SYSTEM;
+
+ return PerformAccountWriting(Plugin, hFile);
+}
+
+INT_PTR FindAccountByNameSvc(WPARAM wParam, LPARAM lParam)
+{
+ HYAMNPROTOPLUGIN Plugin = (HYAMNPROTOPLUGIN)wParam;
+ char *SearchedAccount = (char *)lParam;
+ CAccount *Finder;
+
+ SWMRGWaitToRead(Plugin->AccountBrowserSO, INFINITE);
+
+ for (Finder = Plugin->FirstAccount; Finder != nullptr; Finder = Finder->Next)
+ if ((Finder->Name != nullptr) && (0 == mir_strcmp(SearchedAccount, Finder->Name)))
+ break;
+
+ SWMRGDoneReading(Plugin->AccountBrowserSO);
+ return (INT_PTR)Finder;
+}
+
+INT_PTR GetNextFreeAccountSvc(WPARAM wParam, LPARAM lParam)
+{
+ HYAMNPROTOPLUGIN Plugin = (HYAMNPROTOPLUGIN)wParam;
+ CAccount *Finder;
+
+ if (Plugin->FirstAccount == nullptr) {
+ Plugin->FirstAccount = (CAccount *)CallService(MS_YAMN_CREATEPLUGINACCOUNT, wParam, lParam);
+ return (INT_PTR)Plugin->FirstAccount;
+ }
+ for (Finder = Plugin->FirstAccount; Finder->Next != nullptr; Finder = Finder->Next);
+ Finder->Next = (CAccount *)CallService(MS_YAMN_CREATEPLUGINACCOUNT, wParam, lParam);
+ return (INT_PTR)Finder->Next;
+}
+
+INT_PTR DeleteAccountSvc(WPARAM wParam, LPARAM lParam)
+{
+ //Deleting account works on these steps:
+ //1. set signal that account should stop activity (set event)
+ // setting this event we achieve, that any access to account is failed,
+ // so threads do not start any work with accounts (better saying threads of plugins should not start)
+ //2. wait to get write access to chained list of accounts
+ //3. we can write to chained list, so we change chain not to show to actual account
+ // now, any thread browsing list of accounts does not browse through actual account
+ // actual account seems to be hidden (it exists, but it is not in accounts chained list (chained list=queue))
+ //Now, we should delete account from memory, BUT!!!
+ // Any thread can still be waked up and start asking account synchronizing object
+ // If account is deleted, asking about access to read account can throw memory exception (reading for
+ // a synchronizing object from memory, that was deleted)
+ //So, we cannot now delete account. We have to wait until we are sure no thread will be using account anymore
+ // (or to the end of Miranda, but problem is in allocated memory- it is allocated and Miranda is SMALLER, faster, easier, isn't it?)
+ // This deleting is achieved in 2 ways:
+ // We have event in UsingThreads synchronization objects. This event signals that no thread will use actual account
+ // 1. Any thread using account first increment UsingThread, so we know that account is used
+ // 2. If thread is about to close, it should decrement UsingThread
+ // 3. If thread creates another thread, that will use account, caller has to wait until the new thread does not
+ // increment UsingThreads (imagine that caller ends before the new thread set it: if no other thread is using
+ // account, account is automaticaly (decreasing UsingThreads) signaled as "not used" and we delete it. But then
+ // new thread is going to read account...).
+ //4. wait until UsingThread Event is signaled
+ //5. delete account from memory
+
+ HYAMNPROTOPLUGIN Plugin = (HYAMNPROTOPLUGIN)wParam;
+ CAccount *Which = (CAccount *)lParam;
+ CAccount *Finder;
+
+ //1. set stop signal
+ StopSignalFcn(Which);
+ WindowList_BroadcastAsync(YAMNVar.MessageWnds, WM_YAMN_STOPACCOUNT, (WPARAM)Which, 0);
+ if (Plugin->Fcn->StopAccountFcnPtr != nullptr)
+ Plugin->Fcn->StopAccountFcnPtr(Which);
+
+ //2. wait to get write access
+ SWMRGWaitToWrite(Plugin->AccountBrowserSO, INFINITE);
+
+ //3. remove from queue (chained list)
+ if (Plugin->FirstAccount == nullptr) {
+ SWMRGDoneWriting(Plugin->AccountBrowserSO);
+ return 0;
+ }
+ if (Plugin->FirstAccount == Which) {
+ Finder = Plugin->FirstAccount->Next;
+ Plugin->FirstAccount = Finder;
+ }
+ else {
+ for (Finder = Plugin->FirstAccount; Which != Finder->Next; Finder = Finder->Next);
+ Finder->Next = Finder->Next->Next;
+ }
+
+ //leave write access
+ SWMRGDoneWriting(Plugin->AccountBrowserSO);
+
+ //4. wait while event "UsingThread" is not signaled
+ // And what to do, if this event will be signaled in 1 hour? (Although it's paranoia, because we have sent "delete signal", so
+ // other threads do not start any new work with actual account) We will wait in blocked state?
+ // No, of course not. We will create new thread, that will wait and additionally remove our thread in background.
+ //5. So, the last point (deleting from memory) is performed in new DeleteAccountInBackground thread
+
+ if ((Plugin->Fcn != nullptr) && (Plugin->Fcn->WriteAccountsFcnPtr != nullptr))
+ Plugin->Fcn->WriteAccountsFcnPtr();
+ CloseHandle(mir_forkthread(DeleteAccountInBackground, (void *)Which));
+
+ //Now, plugin can consider account as deleted, but plugin really can achieve deleting this account from memory when using
+ //event UsingThreads.
+ return 1;
+}
+
+void __cdecl DeleteAccountInBackground(void *Value)
+{
+ CAccount *Which = (CAccount *)Value;
+ WaitForSingleObject(Which->UsingThreads->Event, INFINITE);
+ CallService(MS_YAMN_DELETEPLUGINACCOUNT, (WPARAM)Which, 0);
+}
+
+int StopAccounts(HYAMNPROTOPLUGIN Plugin)
+{
+ CAccount *Finder;
+
+ //1. wait to get write access
+ SWMRGWaitToWrite(Plugin->AccountBrowserSO, INFINITE);
+
+ for (Finder = Plugin->FirstAccount; Finder != nullptr; Finder = Finder->Next) {
+ //2. set stop signal
+ StopSignalFcn(Finder);
+ WindowList_BroadcastAsync(YAMNVar.MessageWnds, WM_YAMN_STOPACCOUNT, (WPARAM)Finder, 0);
+ if (Plugin->Fcn->StopAccountFcnPtr != nullptr)
+ Plugin->Fcn->StopAccountFcnPtr(Finder);
+ }
+
+ //leave write access
+ SWMRGDoneWriting(Plugin->AccountBrowserSO);
+
+ //Now, account is stopped. It can be removed from memory...
+ return 1;
+}
+
+int WaitForAllAccounts(HYAMNPROTOPLUGIN Plugin, BOOL GetAccountBrowserAccess)
+{
+ if (GetAccountBrowserAccess) {
+ //1. wait to get write access
+ SWMRGWaitToWrite(Plugin->AccountBrowserSO, INFINITE);
+ }
+ for (CAccount *Finder = Plugin->FirstAccount; Finder != nullptr; Finder = Finder->Next) {
+ //2. wait for signal that account is not in use
+ WaitForSingleObject(Finder->UsingThreads->Event, INFINITE);
+ SetEvent(Finder->UsingThreads->Event);
+ }
+ if (GetAccountBrowserAccess) {
+ //leave write access
+ SWMRGDoneWriting(Plugin->AccountBrowserSO);
+ }
+
+ return 1;
+}
+
+int DeleteAccounts(HYAMNPROTOPLUGIN Plugin)
+{
+ //1. wait to get write access
+ SWMRGWaitToWrite(Plugin->AccountBrowserSO, INFINITE);
+
+ WaitForAllAccounts(Plugin, FALSE);
+
+ for (CAccount *Finder = Plugin->FirstAccount; Finder != nullptr;) {
+ CAccount *Next = Finder->Next;
+ DeletePluginAccountSvc((WPARAM)Finder, 0);
+ Finder = Next;
+ }
+
+ //leave write access
+ SWMRGDoneWriting(Plugin->AccountBrowserSO);
+ return 1;
+}
+
+void WINAPI GetStatusFcn(CAccount *Which, wchar_t *Value)
+{
+ if (Which == nullptr)
+ return;
+
+ mir_cslock lck(csAccountStatusCS);
+ mir_wstrcpy(Value, Which->Status);
+}
+
+void WINAPI SetStatusFcn(CAccount *Which, wchar_t *Value)
+{
+ if (Which != nullptr) {
+ mir_cslock lck(csAccountStatusCS);
+ mir_wstrcpy(Which->Status, Value);
+ }
+
+ WindowList_BroadcastAsync(YAMNVar.MessageWnds, WM_YAMN_CHANGESTATUS, (WPARAM)Which, 0);
+}
diff --git a/protocols/YAMN/src/browser/badconnect.cpp b/protocols/YAMN/src/browser/badconnect.cpp
index 5f9118eb18..d871fa2eea 100644
--- a/protocols/YAMN/src/browser/badconnect.cpp
+++ b/protocols/YAMN/src/browser/badconnect.cpp
@@ -1,251 +1,251 @@
-/*
- * This code implements window handling (connection error)
- *
- * (c) majvan 2002,2004
- */
-
-#include "../stdafx.h"
-
-#define BADCONNECTTITLE LPGEN("%s - connection error")
-#define BADCONNECTMSG LPGEN("An error occurred. Error code: %d")//is in use?
-
-//--------------------------------------------------------------------------------------------------
-
-LRESULT CALLBACK BadConnectPopupProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- switch (msg) {
- case WM_COMMAND:
- // if clicked and it's new mail popup window
- if ((HIWORD(wParam) == STN_CLICKED) && (PUGetPluginData(hWnd))) {
- PROCESS_INFORMATION pi;
- STARTUPINFOW si;
- memset(&si, 0, sizeof(si));
- si.cb = sizeof(si);
- CAccount *ActualAccount = (CAccount *)PUGetPluginData(hWnd);
-
- if (WAIT_OBJECT_0 == WaitToReadFcn(ActualAccount->AccountAccessSO)) {
- if (ActualAccount->BadConnectN.App != nullptr) {
- wchar_t *Command;
- if (ActualAccount->BadConnectN.AppParam != nullptr)
- Command = new wchar_t[mir_wstrlen(ActualAccount->BadConnectN.App) + mir_wstrlen(ActualAccount->BadConnectN.AppParam) + 6];
- else
- Command = new wchar_t[mir_wstrlen(ActualAccount->BadConnectN.App) + 6];
-
- if (Command != nullptr) {
- mir_wstrcpy(Command, L"\"");
- mir_wstrcat(Command, ActualAccount->BadConnectN.App);
- mir_wstrcat(Command, L"\" ");
- if (ActualAccount->BadConnectN.AppParam != nullptr)
- mir_wstrcat(Command, ActualAccount->BadConnectN.AppParam);
- CreateProcessW(nullptr, Command, nullptr, nullptr, FALSE, NORMAL_PRIORITY_CLASS, nullptr, nullptr, &si, &pi);
- delete[] Command;
- }
- }
-
- ReadDoneFcn(ActualAccount->AccountAccessSO);
- }
-
- PUDeletePopup(hWnd);
- }
- break;
-
- case UM_FREEPLUGINDATA:
- //Here we'd free our own data, if we had it.
- return FALSE;
-
- case UM_INITPOPUP:
- //This is the equivalent to WM_INITDIALOG you'd get if you were the maker of dialog popups.
- break;
- case WM_CONTEXTMENU:
- PUDeletePopup(hWnd);
- break;
- }
- return DefWindowProc(hWnd, msg, wParam, lParam);
-}
-
-INT_PTR CALLBACK DlgProcYAMNBadConnection(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- switch (msg) {
- case WM_INITDIALOG:
- {
- BOOL ShowPopup, ShowMsg, ShowIco;
- CAccount *ActualAccount;
- uint32_t ErrorCode;
- char *TitleStrA;
- char *Message1A = nullptr;
- wchar_t *Message1W = nullptr;
- POPUPDATAW BadConnectPopup = {};
-
- ActualAccount = ((struct BadConnectionParam *)lParam)->account;
- ErrorCode = ((struct BadConnectionParam *)lParam)->errcode;
-
- if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO))
- return FALSE;
-
- int size = (int)(mir_strlen(ActualAccount->Name) + mir_strlen(Translate(BADCONNECTTITLE)));
- TitleStrA = new char[size];
- mir_snprintf(TitleStrA, size, Translate(BADCONNECTTITLE), ActualAccount->Name);
-
- ShowPopup = ActualAccount->BadConnectN.Flags & YAMN_ACC_POP;
- ShowMsg = ActualAccount->BadConnectN.Flags & YAMN_ACC_MSG;
- ShowIco = ActualAccount->BadConnectN.Flags & YAMN_ACC_ICO;
-
- if (ShowPopup) {
- BadConnectPopup.lchIcon = g_plugin.getIcon(IDI_BADCONNECT);
- BadConnectPopup.colorBack = ActualAccount->BadConnectN.Flags & YAMN_ACC_POPC ? ActualAccount->BadConnectN.PopupB : GetSysColor(COLOR_BTNFACE);
- BadConnectPopup.colorText = ActualAccount->BadConnectN.Flags & YAMN_ACC_POPC ? ActualAccount->BadConnectN.PopupT : GetSysColor(COLOR_WINDOWTEXT);
- BadConnectPopup.iSeconds = ActualAccount->BadConnectN.PopupTime;
-
- BadConnectPopup.PluginWindowProc = BadConnectPopupProc;
- BadConnectPopup.PluginData = ActualAccount;
- mir_wstrncpy(BadConnectPopup.lpwzContactName, _A2T(ActualAccount->Name), _countof(BadConnectPopup.lpwzContactName));
- }
-
- if (ActualAccount->Plugin->Fcn != nullptr && ActualAccount->Plugin->Fcn->GetErrorStringWFcnPtr != nullptr) {
- Message1W = ActualAccount->Plugin->Fcn->GetErrorStringWFcnPtr(ErrorCode);
- SetDlgItemText(hDlg, IDC_STATICMSG, Message1W);
- wcsncpy_s(BadConnectPopup.lpwzText, Message1W, _TRUNCATE);
- if (ShowPopup)
- PUAddPopupW(&BadConnectPopup);
- }
- else if (ActualAccount->Plugin->Fcn != nullptr && ActualAccount->Plugin->Fcn->GetErrorStringAFcnPtr != nullptr) {
- Message1W = ActualAccount->Plugin->Fcn->GetErrorStringWFcnPtr(ErrorCode);
- SetDlgItemText(hDlg, IDC_STATICMSG, Message1W);
- wcsncpy_s(BadConnectPopup.lpwzText, Message1W, _TRUNCATE);
- if (ShowPopup)
- PUAddPopupW(&BadConnectPopup);
- }
- else {
- Message1W = TranslateT("Unknown error");
- SetDlgItemText(hDlg, IDC_STATICMSG, Message1W);
- wcsncpy_s(BadConnectPopup.lpwzText, Message1W, _TRUNCATE);
- if (ShowPopup)
- PUAddPopupW(&BadConnectPopup);
- }
-
- if (!ShowMsg && !ShowIco)
- DestroyWindow(hDlg);
-
- ReadDoneFcn(ActualAccount->AccountAccessSO);
-
- SetWindowTextA(hDlg, TitleStrA);
- delete[] TitleStrA;
- if (Message1A != nullptr)
- delete[] Message1A;
- if (ActualAccount->Plugin->Fcn != nullptr && ActualAccount->Plugin->Fcn->DeleteErrorStringFcnPtr != nullptr && Message1A != nullptr)
- ActualAccount->Plugin->Fcn->DeleteErrorStringFcnPtr(Message1A);
- if (ActualAccount->Plugin->Fcn != nullptr && ActualAccount->Plugin->Fcn->DeleteErrorStringFcnPtr != nullptr && Message1W != nullptr)
- ActualAccount->Plugin->Fcn->DeleteErrorStringFcnPtr(Message1W);
- return 0;
- }
- case WM_DESTROY:
- {
- NOTIFYICONDATA nid;
-
- memset(&nid, 0, sizeof(NOTIFYICONDATA));
- nid.cbSize = sizeof(NOTIFYICONDATA);
- nid.hWnd = hDlg;
- nid.uID = 0;
- Shell_NotifyIcon(NIM_DELETE, &nid);
- PostQuitMessage(0);
- break;
- }
- case WM_YAMN_NOTIFYICON:
- switch (lParam) {
- case WM_LBUTTONDBLCLK:
- ShowWindow(hDlg, SW_SHOWNORMAL);
- SetForegroundWindow(hDlg);
- break;
- }
- return 0;
- case WM_CHAR:
- switch ((wchar_t)wParam) {
- case 27:
- case 13:
- DestroyWindow(hDlg);
- break;
- }
- break;
- case WM_SYSCOMMAND:
- switch (wParam) {
- case SC_CLOSE:
- DestroyWindow(hDlg);
- }
- break;
- case WM_COMMAND:
- switch (LOWORD(wParam)) {
- case IDC_BTNOK:
- DestroyWindow(hDlg);
- }
- break;
- }
- return 0;
-}
-
-void __cdecl BadConnection(void *Param)
-{
- MSG msg;
- HWND hBadConnect;
- CAccount *ActualAccount;
-
- struct BadConnectionParam MyParam = *(struct BadConnectionParam *)Param;
- ActualAccount = MyParam.account;
-
- SCIncFcn(ActualAccount->UsingThreads);
-
- // we will not use params in stack anymore
- SetEvent(MyParam.ThreadRunningEV);
-
- __try {
- hBadConnect = CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_DLGBADCONNECT), nullptr, DlgProcYAMNBadConnection, (LPARAM)&MyParam);
- Window_SetIcon_IcoLib(hBadConnect, g_plugin.getIconHandle(IDI_BADCONNECT));
-
- if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO))
- __leave;
-
- if (ActualAccount->BadConnectN.Flags & YAMN_ACC_SND)
- Skin_PlaySound(YAMN_CONNECTFAILSOUND);
-
- if (ActualAccount->BadConnectN.Flags & YAMN_ACC_MSG)
- ShowWindow(hBadConnect, SW_SHOWNORMAL);
-
- if (ActualAccount->BadConnectN.Flags & YAMN_ACC_ICO) {
- NOTIFYICONDATA nid = {};
- nid.cbSize = sizeof(nid);
- nid.hWnd = hBadConnect;
- nid.hIcon = g_plugin.getIcon(IDI_BADCONNECT);
- nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
- nid.uCallbackMessage = WM_YAMN_NOTIFYICON;
- mir_snwprintf(nid.szTip, L"%S%s", ActualAccount->Name, TranslateT(" - connection error"));
- Shell_NotifyIcon(NIM_ADD, &nid);
- }
-
- ReadDoneFcn(ActualAccount->AccountAccessSO);
-
- UpdateWindow(hBadConnect);
- while (GetMessage(&msg, nullptr, 0, 0)) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
-
- // now, write to file. Why? Because we want to write when was new mail last checked
- if ((ActualAccount->Plugin->Fcn != nullptr) && (ActualAccount->Plugin->Fcn->WriteAccountsFcnPtr != nullptr) && ActualAccount->AbleToWork)
- ActualAccount->Plugin->Fcn->WriteAccountsFcnPtr();
- }
- __finally {
- SCDecFcn(ActualAccount->UsingThreads);
- }
-}
-
-int RunBadConnection(CAccount *acc, UINT_PTR iErrorCode, void *pUserInfo)
-{
- BadConnectionParam param = {CreateEvent(nullptr, FALSE, FALSE, nullptr), acc, iErrorCode, pUserInfo};
-
- HANDLE NewThread = mir_forkthread(BadConnection, &param);
- if (nullptr == NewThread)
- return 0;
-
- WaitForSingleObject(param.ThreadRunningEV, INFINITE);
- CloseHandle(param.ThreadRunningEV);
- return 1;
-}
+/*
+ * This code implements window handling (connection error)
+ *
+ * (c) majvan 2002,2004
+ */
+
+#include "../stdafx.h"
+
+#define BADCONNECTTITLE LPGEN("%s - connection error")
+#define BADCONNECTMSG LPGEN("An error occurred. Error code: %d")//is in use?
+
+//--------------------------------------------------------------------------------------------------
+
+LRESULT CALLBACK BadConnectPopupProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_COMMAND:
+ // if clicked and it's new mail popup window
+ if ((HIWORD(wParam) == STN_CLICKED) && (PUGetPluginData(hWnd))) {
+ PROCESS_INFORMATION pi;
+ STARTUPINFOW si;
+ memset(&si, 0, sizeof(si));
+ si.cb = sizeof(si);
+ CAccount *ActualAccount = (CAccount *)PUGetPluginData(hWnd);
+
+ if (WAIT_OBJECT_0 == WaitToReadFcn(ActualAccount->AccountAccessSO)) {
+ if (ActualAccount->BadConnectN.App != nullptr) {
+ wchar_t *Command;
+ if (ActualAccount->BadConnectN.AppParam != nullptr)
+ Command = new wchar_t[mir_wstrlen(ActualAccount->BadConnectN.App) + mir_wstrlen(ActualAccount->BadConnectN.AppParam) + 6];
+ else
+ Command = new wchar_t[mir_wstrlen(ActualAccount->BadConnectN.App) + 6];
+
+ if (Command != nullptr) {
+ mir_wstrcpy(Command, L"\"");
+ mir_wstrcat(Command, ActualAccount->BadConnectN.App);
+ mir_wstrcat(Command, L"\" ");
+ if (ActualAccount->BadConnectN.AppParam != nullptr)
+ mir_wstrcat(Command, ActualAccount->BadConnectN.AppParam);
+ CreateProcessW(nullptr, Command, nullptr, nullptr, FALSE, NORMAL_PRIORITY_CLASS, nullptr, nullptr, &si, &pi);
+ delete[] Command;
+ }
+ }
+
+ ReadDoneFcn(ActualAccount->AccountAccessSO);
+ }
+
+ PUDeletePopup(hWnd);
+ }
+ break;
+
+ case UM_FREEPLUGINDATA:
+ //Here we'd free our own data, if we had it.
+ return FALSE;
+
+ case UM_INITPOPUP:
+ //This is the equivalent to WM_INITDIALOG you'd get if you were the maker of dialog popups.
+ break;
+ case WM_CONTEXTMENU:
+ PUDeletePopup(hWnd);
+ break;
+ }
+ return DefWindowProc(hWnd, msg, wParam, lParam);
+}
+
+INT_PTR CALLBACK DlgProcYAMNBadConnection(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ BOOL ShowPopup, ShowMsg, ShowIco;
+ CAccount *ActualAccount;
+ uint32_t ErrorCode;
+ char *TitleStrA;
+ char *Message1A = nullptr;
+ wchar_t *Message1W = nullptr;
+ POPUPDATAW BadConnectPopup = {};
+
+ ActualAccount = ((struct BadConnectionParam *)lParam)->account;
+ ErrorCode = ((struct BadConnectionParam *)lParam)->errcode;
+
+ if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO))
+ return FALSE;
+
+ int size = (int)(mir_strlen(ActualAccount->Name) + mir_strlen(Translate(BADCONNECTTITLE)));
+ TitleStrA = new char[size];
+ mir_snprintf(TitleStrA, size, Translate(BADCONNECTTITLE), ActualAccount->Name);
+
+ ShowPopup = ActualAccount->BadConnectN.Flags & YAMN_ACC_POP;
+ ShowMsg = ActualAccount->BadConnectN.Flags & YAMN_ACC_MSG;
+ ShowIco = ActualAccount->BadConnectN.Flags & YAMN_ACC_ICO;
+
+ if (ShowPopup) {
+ BadConnectPopup.lchIcon = g_plugin.getIcon(IDI_BADCONNECT);
+ BadConnectPopup.colorBack = ActualAccount->BadConnectN.Flags & YAMN_ACC_POPC ? ActualAccount->BadConnectN.PopupB : GetSysColor(COLOR_BTNFACE);
+ BadConnectPopup.colorText = ActualAccount->BadConnectN.Flags & YAMN_ACC_POPC ? ActualAccount->BadConnectN.PopupT : GetSysColor(COLOR_WINDOWTEXT);
+ BadConnectPopup.iSeconds = ActualAccount->BadConnectN.PopupTime;
+
+ BadConnectPopup.PluginWindowProc = BadConnectPopupProc;
+ BadConnectPopup.PluginData = ActualAccount;
+ mir_wstrncpy(BadConnectPopup.lpwzContactName, _A2T(ActualAccount->Name), _countof(BadConnectPopup.lpwzContactName));
+ }
+
+ if (ActualAccount->Plugin->Fcn != nullptr && ActualAccount->Plugin->Fcn->GetErrorStringWFcnPtr != nullptr) {
+ Message1W = ActualAccount->Plugin->Fcn->GetErrorStringWFcnPtr(ErrorCode);
+ SetDlgItemText(hDlg, IDC_STATICMSG, Message1W);
+ wcsncpy_s(BadConnectPopup.lpwzText, Message1W, _TRUNCATE);
+ if (ShowPopup)
+ PUAddPopupW(&BadConnectPopup);
+ }
+ else if (ActualAccount->Plugin->Fcn != nullptr && ActualAccount->Plugin->Fcn->GetErrorStringAFcnPtr != nullptr) {
+ Message1W = ActualAccount->Plugin->Fcn->GetErrorStringWFcnPtr(ErrorCode);
+ SetDlgItemText(hDlg, IDC_STATICMSG, Message1W);
+ wcsncpy_s(BadConnectPopup.lpwzText, Message1W, _TRUNCATE);
+ if (ShowPopup)
+ PUAddPopupW(&BadConnectPopup);
+ }
+ else {
+ Message1W = TranslateT("Unknown error");
+ SetDlgItemText(hDlg, IDC_STATICMSG, Message1W);
+ wcsncpy_s(BadConnectPopup.lpwzText, Message1W, _TRUNCATE);
+ if (ShowPopup)
+ PUAddPopupW(&BadConnectPopup);
+ }
+
+ if (!ShowMsg && !ShowIco)
+ DestroyWindow(hDlg);
+
+ ReadDoneFcn(ActualAccount->AccountAccessSO);
+
+ SetWindowTextA(hDlg, TitleStrA);
+ delete[] TitleStrA;
+ if (Message1A != nullptr)
+ delete[] Message1A;
+ if (ActualAccount->Plugin->Fcn != nullptr && ActualAccount->Plugin->Fcn->DeleteErrorStringFcnPtr != nullptr && Message1A != nullptr)
+ ActualAccount->Plugin->Fcn->DeleteErrorStringFcnPtr(Message1A);
+ if (ActualAccount->Plugin->Fcn != nullptr && ActualAccount->Plugin->Fcn->DeleteErrorStringFcnPtr != nullptr && Message1W != nullptr)
+ ActualAccount->Plugin->Fcn->DeleteErrorStringFcnPtr(Message1W);
+ return 0;
+ }
+ case WM_DESTROY:
+ {
+ NOTIFYICONDATA nid;
+
+ memset(&nid, 0, sizeof(NOTIFYICONDATA));
+ nid.cbSize = sizeof(NOTIFYICONDATA);
+ nid.hWnd = hDlg;
+ nid.uID = 0;
+ Shell_NotifyIcon(NIM_DELETE, &nid);
+ PostQuitMessage(0);
+ break;
+ }
+ case WM_YAMN_NOTIFYICON:
+ switch (lParam) {
+ case WM_LBUTTONDBLCLK:
+ ShowWindow(hDlg, SW_SHOWNORMAL);
+ SetForegroundWindow(hDlg);
+ break;
+ }
+ return 0;
+ case WM_CHAR:
+ switch ((wchar_t)wParam) {
+ case 27:
+ case 13:
+ DestroyWindow(hDlg);
+ break;
+ }
+ break;
+ case WM_SYSCOMMAND:
+ switch (wParam) {
+ case SC_CLOSE:
+ DestroyWindow(hDlg);
+ }
+ break;
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDC_BTNOK:
+ DestroyWindow(hDlg);
+ }
+ break;
+ }
+ return 0;
+}
+
+void __cdecl BadConnection(void *Param)
+{
+ MSG msg;
+ HWND hBadConnect;
+ CAccount *ActualAccount;
+
+ struct BadConnectionParam MyParam = *(struct BadConnectionParam *)Param;
+ ActualAccount = MyParam.account;
+
+ SCIncFcn(ActualAccount->UsingThreads);
+
+ // we will not use params in stack anymore
+ SetEvent(MyParam.ThreadRunningEV);
+
+ __try {
+ hBadConnect = CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_DLGBADCONNECT), nullptr, DlgProcYAMNBadConnection, (LPARAM)&MyParam);
+ Window_SetIcon_IcoLib(hBadConnect, g_plugin.getIconHandle(IDI_BADCONNECT));
+
+ if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO))
+ __leave;
+
+ if (ActualAccount->BadConnectN.Flags & YAMN_ACC_SND)
+ Skin_PlaySound(YAMN_CONNECTFAILSOUND);
+
+ if (ActualAccount->BadConnectN.Flags & YAMN_ACC_MSG)
+ ShowWindow(hBadConnect, SW_SHOWNORMAL);
+
+ if (ActualAccount->BadConnectN.Flags & YAMN_ACC_ICO) {
+ NOTIFYICONDATA nid = {};
+ nid.cbSize = sizeof(nid);
+ nid.hWnd = hBadConnect;
+ nid.hIcon = g_plugin.getIcon(IDI_BADCONNECT);
+ nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
+ nid.uCallbackMessage = WM_YAMN_NOTIFYICON;
+ mir_snwprintf(nid.szTip, L"%S%s", ActualAccount->Name, TranslateT(" - connection error"));
+ Shell_NotifyIcon(NIM_ADD, &nid);
+ }
+
+ ReadDoneFcn(ActualAccount->AccountAccessSO);
+
+ UpdateWindow(hBadConnect);
+ while (GetMessage(&msg, nullptr, 0, 0)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+ // now, write to file. Why? Because we want to write when was new mail last checked
+ if ((ActualAccount->Plugin->Fcn != nullptr) && (ActualAccount->Plugin->Fcn->WriteAccountsFcnPtr != nullptr) && ActualAccount->AbleToWork)
+ ActualAccount->Plugin->Fcn->WriteAccountsFcnPtr();
+ }
+ __finally {
+ SCDecFcn(ActualAccount->UsingThreads);
+ }
+}
+
+int RunBadConnection(CAccount *acc, UINT_PTR iErrorCode, void *pUserInfo)
+{
+ BadConnectionParam param = {CreateEvent(nullptr, FALSE, FALSE, nullptr), acc, iErrorCode, pUserInfo};
+
+ HANDLE NewThread = mir_forkthread(BadConnection, &param);
+ if (nullptr == NewThread)
+ return 0;
+
+ WaitForSingleObject(param.ThreadRunningEV, INFINITE);
+ CloseHandle(param.ThreadRunningEV);
+ return 1;
+}
diff --git a/protocols/YAMN/src/browser/browser.h b/protocols/YAMN/src/browser/browser.h
index 6707d50621..0cb3f1a248 100644
--- a/protocols/YAMN/src/browser/browser.h
+++ b/protocols/YAMN/src/browser/browser.h
@@ -1,38 +1,38 @@
-#ifndef __MAILBROWSER_H
-#define __MAILBROWSER_H
-
-typedef struct MailBrowserWinParam
-{
-#define YAMN_MAILBROWSERVERSION 1
- HANDLE ThreadRunningEV;
- CAccount *account;
- uint32_t nflags; //flags YAMN_ACC_??? when new mails
- uint32_t nnflags; //flags YAMN_ACC_??? when no new mails
- void *Param;
-} YAMN_MAILBROWSERPARAM,*PYAMN_MAILBROWSERPARAM;
-
-typedef struct MailShowMsgWinParam
-{
- HANDLE ThreadRunningEV;
- CAccount *account;
- HYAMNMAIL mail;
-} YAMN_MAILSHOWPARAM, *PYAMN_MAILSHOWPARAM;
-
-typedef struct NoNewMailParam
-{
-#define YAMN_NONEWMAILVERSION 1
- HANDLE ThreadRunningEV;
- CAccount *account;
- uint32_t flags;
- void *Param;
-} YAMN_NONEWMAILPARAM,*PYAMN_NONEWMAILPARAM;
-
-struct BadConnectionParam
-{
- HANDLE ThreadRunningEV;
- CAccount *account;
- UINT_PTR errcode;
- void *Param;
-};
-
-#endif
+#ifndef __MAILBROWSER_H
+#define __MAILBROWSER_H
+
+typedef struct MailBrowserWinParam
+{
+#define YAMN_MAILBROWSERVERSION 1
+ HANDLE ThreadRunningEV;
+ CAccount *account;
+ uint32_t nflags; //flags YAMN_ACC_??? when new mails
+ uint32_t nnflags; //flags YAMN_ACC_??? when no new mails
+ void *Param;
+} YAMN_MAILBROWSERPARAM,*PYAMN_MAILBROWSERPARAM;
+
+typedef struct MailShowMsgWinParam
+{
+ HANDLE ThreadRunningEV;
+ CAccount *account;
+ HYAMNMAIL mail;
+} YAMN_MAILSHOWPARAM, *PYAMN_MAILSHOWPARAM;
+
+typedef struct NoNewMailParam
+{
+#define YAMN_NONEWMAILVERSION 1
+ HANDLE ThreadRunningEV;
+ CAccount *account;
+ uint32_t flags;
+ void *Param;
+} YAMN_NONEWMAILPARAM,*PYAMN_NONEWMAILPARAM;
+
+struct BadConnectionParam
+{
+ HANDLE ThreadRunningEV;
+ CAccount *account;
+ UINT_PTR errcode;
+ void *Param;
+};
+
+#endif
diff --git a/protocols/YAMN/src/browser/mailbrowser.cpp b/protocols/YAMN/src/browser/mailbrowser.cpp
index 1d62ad00dc..7b1b68e35a 100644
--- a/protocols/YAMN/src/browser/mailbrowser.cpp
+++ b/protocols/YAMN/src/browser/mailbrowser.cpp
@@ -1,2247 +1,2247 @@
-/*
- * This code implements window handling (new mail)
- *
- * (c) majvan 2002-2004
- */
- /* There can be problems when compiling this file, because in this file
- * we are using both unicode and no-unicode functions and compiler does not
- * like it in one file
- * When you got errors, try to comment the #define <stdio.h> and compile, then
- * put it back to uncommented and compile again :)
- */
-
-#include "../stdafx.h"
-
-#define TIMER_FLASHING 0x09061979
-#define MAILBROWSER_MINXSIZE 200 //min size of mail browser window
-#define MAILBROWSER_MINYSIZE 130
-
-#define MAILBROWSERTITLE LPGEN("%s - %d new mail messages, %d total")
-
-void __cdecl ShowEmailThread(void *Param);
-
-//--------------------------------------------------------------------------------------------------
-char *s_MonthNames[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
-bool bDate = false, bSub = false, bSize = false, bFrom = false;
-int PosX = 0, PosY = 0, SizeX = 460, SizeY = 100;
-int HeadSizeX = 0x2b2, HeadSizeY = 0x0b5, HeadPosX = 100, HeadPosY = 100;
-int HeadSplitPos = 250; // per-mils of the size
-static int FromWidth = 250, SubjectWidth = 280, SizeWidth = 50, SizeDate = 205;
-unsigned char optDateTime = (SHOWDATELONG | SHOWDATENOTODAY);
-
-struct CMailNumbersSub
-{
- int Total; //any mail
- int New; //uses YAMN_MSG_NEW flag
- int UnSeen; //uses YAMN_MSG_UNSEEN flag
- // int Browser; //uses YAMN_MSG_BROWSER flag
- int BrowserUC; //uses YAMN_MSG_BROWSER flag and YAMN_MSG_UNSEEN flag
- int Display; //uses YAMN_MSG_DISPLAY flag
- int DisplayTC; //uses YAMN_MSG_DISPLAY flag and YAMN_MSG_DISPLAYC flag
- int DisplayUC; //uses YAMN_MSG_DISPLAY flag and YAMN_MSG_DISPLAYC flag and YAMN_MSG_UNSEEN flag
- int Popup; //uses YAMN_MSG_POPUP flag
- int PopupTC; //uses YAMN_MSG_POPUPC flag
- int PopupNC; //uses YAMN_MSG_POPUPC flag and YAMN_MSG_NEW flag
- int PopupRun; //uses YAMN_MSG_POPUP flag and YAMN_MSG_NEW flag
- int PopupSL2NC; //uses YAMN_MSG_SPAML2 flag and YAMN_MSG_NEW flag
- int PopupSL3NC; //uses YAMN_MSG_SPAML3 flag and YAMN_MSG_NEW flag
- // int SysTray; //uses YAMN_MSG_SYSTRAY flag
- int SysTrayUC; //uses YAMN_MSG_SYSTRAY flag and YAMN_MSG_UNSEEN flag
- // int Sound; //uses YAMN_MSG_SOUND flag
- int SoundNC; //uses YAMN_MSG_SOUND flag and YAMN_MSG_NEW flag
- // int App; //uses YAMN_MSG_APP flag
- int AppNC; //uses YAMN_MSG_APP flag and YAMN_MSG_NEW flag
- int EventNC; //uses YAMN_MSG_NEVENT flag and YAMN_MSG_NEW flag
-};
-
-struct CMailNumbers
-{
- struct CMailNumbersSub Real;
- struct CMailNumbersSub Virtual;
-};
-
-struct CMailWinUserInfo
-{
- CAccount *Account;
- int TrayIconState;
- BOOL UpdateMailsMessagesAccess;
- BOOL Seen;
- BOOL RunFirstTime;
-};
-
-struct CChangeContent
-{
- uint32_t nflags;
- uint32_t nnflags;
-};
-
-struct CUpdateMails
-{
- struct CChangeContent *Flags;
- BOOL Waiting;
- HANDLE Copied;
-};
-
-struct CSortList
-{
- HWND hDlg;
- int iSubItem;
-};
-
-// Retrieves CAccount *, whose mails are displayed in ListMails
-// hLM- handle of dialog window
-// returns handle of account
-inline CAccount *GetWindowAccount(HWND hDialog);
-
-// Looks to mail flags and increment mail counter (e.g. if mail is new, increments the new mail counter
-// msgq- mail, which increments the counters
-// MN- counnters structure
-void IncrementMailCounters(HYAMNMAIL msgq, struct CMailNumbers *MN);
-
-enum
-{
- UPDATE_FAIL = 0, //function failed
- UPDATE_NONE, //none update has been performed
- UPDATE_OK, //some changes occured, update performed
-};
-
-// Just looks for mail changes in account and update the mail browser window
-// hDlg- dialog handle
-// ActualAccount- account handle
-// nflags- flags what to do when new mail arrives
-// nnflags- flags what to do when no new mail arrives
-// returns one of UPDATE_XXX value(not implemented yet)
-int UpdateMails(HWND hDlg, CAccount *ActualAccount, uint32_t nflags, uint32_t nnflags);
-
-// When new mail occurs, shows window, plays sound, runs application...
-// hDlg- dialog handle. Dialog of mailbrowser is already created and actions are performed over this window
-// ActualAccount- handle of account, whose mails are to be notified
-// MN- statistics of mails in account
-// nflags- what to do or not to do (e.g. to show mailbrowser window or prohibit to show)
-// nflags- flags what to do when new mail arrives
-// nnflags- flags what to do when no new mail arrives
-void DoMailActions(HWND hDlg, CAccount *ActualAccount, struct CMailNumbers *MN, uint32_t nflags, uint32_t nnflags);
-
-// Looks for items in mailbrowser and if they were deleted, delete them from browser window
-// hListView- handle of listview window
-// ActualAccount- handle of account, whose mails are show
-// MailNumbers- pointer to structure, in which function stores numbers of mails with some property
-// returns one of UPDATE_XXX value (not implemented yet)
-int ChangeExistingMailStatus(HWND hListView, CAccount *ActualAccount);
-
-// Adds new mails to ListView and if any new, shows multi popup (every new message is new popup window created by popup plugin)
-// hListView- handle of listview window
-// ActualAccount- handle of account, whose mails are show
-// NewMailPopup- pointer to prepared structure for popup plugin, can be NULL if no popup show
-// MailNumbers- pointer to structure, in which function stores numbers of mails with some property
-// nflags- flags what to do when new mail arrives
-// returns one of UPDATE_XXX value (not implemented yet)
-int AddNewMailsToListView(HWND hListView, CAccount *ActualAccount, uint32_t nflags);
-
-// Window callback procedure for popup window (created by popup plugin)
-LRESULT CALLBACK NewMailPopupProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
-
-// Window callback procedure for popup window (created by popup plugin)
-LRESULT CALLBACK NoNewMailPopupProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
-
-// Dialog callback procedure for mail browser
-INT_PTR CALLBACK DlgProcYAMNMailBrowser(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
-
-// MailBrowser thread function creates window if needed, tray icon and plays sound
-void __cdecl MailBrowser(void *Param);
-
-LRESULT CALLBACK ListViewSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
-
-// Runs mail browser in new thread
-INT_PTR RunMailBrowserSvc(WPARAM, LPARAM);
-
-#define YAMN_BROWSER_SHOWPOPUP 0x01
-
-// list view items' order criteria
-#define LVORDER_NOORDER -1
-#define LVORDER_STRING 0
-#define LVORDER_NUMERIC 1
-#define LVORDER_DATETIME 2
-
-// list view order direction
-#define LVORDER_ASCENDING 1
-#define LVORDER_NONE 0
-#define LVORDER_DESCENDING -1
-
-// list view sort type
-#define LVSORTPRIORITY_NONE -1
-
-// List view column info.
-typedef struct _SAMPLELISTVIEWCOLUMN
-{
- UINT uCXCol; // index
- int nSortType; // sorting type (STRING = 0, NUMERIC, DATE, DATETIME)
- int nSortOrder; // sorting order (ASCENDING = -1, NONE, DESCENDING)
- int nPriority; // sort priority (-1 for none, 0, 1, ..., nColumns - 1 maximum)
- wchar_t lpszName[128]; // column name
-} SAMPLELISTVIEWCOLUMN;
-
-// Compare priority
-typedef struct _LVCOMPAREINFO
-{
- int iIdx; // Index
- int iPriority; // Priority
-} LVCOMPAREINFO, *LPLVCOMPAREINFO;
-
-//--------------------------------------------------------------------------------------------------
-
-LPARAM readItemLParam(HWND hwnd, uint32_t iItem)
-{
- LVITEM item;
- item.mask = LVIF_PARAM;
- item.iItem = iItem;
- item.iSubItem = 0;
- SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
- return item.lParam;
-}
-
-inline CAccount *GetWindowAccount(HWND hDlg)
-{
- struct CMailWinUserInfo *mwui = (struct CMailWinUserInfo *)GetWindowLongPtr(hDlg, DWLP_USER);
-
- return (mwui == nullptr) ? nullptr : mwui->Account;
-}
-
-void IncrementMailCounters(HYAMNMAIL msgq, struct CMailNumbers *MN)
-{
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.Total++;
- else
- MN->Real.Total++;
-
- if (msgq->Flags & YAMN_MSG_NEW)
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.New++;
- else
- MN->Real.New++;
- if (msgq->Flags & YAMN_MSG_UNSEEN)
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.UnSeen++;
- else
- MN->Real.UnSeen++;
- if ((msgq->Flags & (YAMN_MSG_UNSEEN | YAMN_MSG_BROWSER)) == (YAMN_MSG_UNSEEN | YAMN_MSG_BROWSER))
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.BrowserUC++;
- else
- MN->Real.BrowserUC++;
- if (msgq->Flags & YAMN_MSG_DISPLAY)
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.Display++;
- else
- MN->Real.Display++;
- if ((msgq->Flags & (YAMN_MSG_DISPLAYC | YAMN_MSG_DISPLAY)) == (YAMN_MSG_DISPLAYC | YAMN_MSG_DISPLAY))
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.DisplayTC++;
- else
- MN->Real.DisplayTC++;
- if ((msgq->Flags & (YAMN_MSG_UNSEEN | YAMN_MSG_DISPLAYC | YAMN_MSG_DISPLAY)) == (YAMN_MSG_UNSEEN | YAMN_MSG_DISPLAYC | YAMN_MSG_DISPLAY))
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.DisplayUC++;
- else
- MN->Real.DisplayUC++;
- if (msgq->Flags & YAMN_MSG_POPUP)
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.Popup++;
- else
- MN->Real.Popup++;
- if ((msgq->Flags & YAMN_MSG_POPUPC) == YAMN_MSG_POPUPC)
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.PopupTC++;
- else
- MN->Real.PopupTC++;
- if ((msgq->Flags & (YAMN_MSG_NEW | YAMN_MSG_POPUPC)) == (YAMN_MSG_NEW | YAMN_MSG_POPUPC))
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.PopupNC++;
- else
- MN->Real.PopupNC++;
- if ((msgq->Flags & (YAMN_MSG_NEW | YAMN_MSG_POPUP)) == (YAMN_MSG_NEW | YAMN_MSG_POPUP))
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.PopupRun++;
- else
- MN->Real.PopupRun++;
- if ((msgq->Flags & YAMN_MSG_NEW) && YAMN_MSG_SPAML(msgq->Flags, YAMN_MSG_SPAML2))
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.PopupSL2NC++;
- else
- MN->Real.PopupSL2NC++;
- if ((msgq->Flags & YAMN_MSG_NEW) && YAMN_MSG_SPAML(msgq->Flags, YAMN_MSG_SPAML3))
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.PopupSL3NC++;
- else
- MN->Real.PopupSL3NC++;
- /* if (msgq->MailData->Flags & YAMN_MSG_SYSTRAY)
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.SysTray++;
- else
- MN->Real.SysTray++;
- */ if ((msgq->Flags & (YAMN_MSG_UNSEEN | YAMN_MSG_SYSTRAY)) == (YAMN_MSG_UNSEEN | YAMN_MSG_SYSTRAY))
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.SysTrayUC++;
- else
- MN->Real.SysTrayUC++;
- /* if (msgq->MailData->Flags & YAMN_MSG_SOUND)
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.Sound++;
- else
- MN->Real.Sound++;
- */ if ((msgq->Flags & (YAMN_MSG_NEW | YAMN_MSG_SOUND)) == (YAMN_MSG_NEW | YAMN_MSG_SOUND))
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.SoundNC++;
- else
- MN->Real.SoundNC++;
- /* if (msgq->MailData->Flags & YAMN_MSG_APP)
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.App++;
- else
- MN->Real.App++;
- */ if ((msgq->Flags & (YAMN_MSG_NEW | YAMN_MSG_APP)) == (YAMN_MSG_NEW | YAMN_MSG_APP))
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.AppNC++;
- else
- MN->Real.AppNC++;
- if ((msgq->Flags & (YAMN_MSG_NEW | YAMN_MSG_NEVENT)) == (YAMN_MSG_NEW | YAMN_MSG_NEVENT))
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.EventNC++;
- else
- MN->Real.EventNC++;
-}
-
-int UpdateMails(HWND hDlg, CAccount *ActualAccount, uint32_t nflags, uint32_t nnflags)
-{
- struct CMailNumbers MN;
-
- BOOL Loaded;
- BOOL RunMailBrowser, RunPopups;
-
- struct CMailWinUserInfo *mwui = (struct CMailWinUserInfo *)GetWindowLongPtr(hDlg, DWLP_USER);
- //now we ensure read access for account and write access for its mails
- if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO)) {
- PostMessage(hDlg, WM_DESTROY, 0, 0);
- return UPDATE_FAIL;
- }
-
- if (WAIT_OBJECT_0 != WaitToWriteFcn(ActualAccount->MessagesAccessSO)) {
- ReadDoneFcn(ActualAccount->AccountAccessSO);
- PostMessage(hDlg, WM_DESTROY, 0, 0);
- return UPDATE_FAIL;
- }
-
- memset(&MN, 0, sizeof(MN));
-
- for (HYAMNMAIL msgq = (HYAMNMAIL)ActualAccount->Mails; msgq != nullptr; msgq = msgq->Next) {
- if (!LoadedMailData(msgq)) //check if mail is already in memory
- {
- Loaded = false;
- if (nullptr == LoadMailData(msgq)) //if we could not load mail to memory, consider this mail deleted and do not display it
- continue;
- }
- else
- Loaded = true;
-
- IncrementMailCounters(msgq, &MN);
-
- if (!Loaded)
- UnloadMailData(msgq); //do not keep data for mail in memory
- }
-
- if (mwui != nullptr)
- mwui->UpdateMailsMessagesAccess = TRUE;
-
- //Now we are going to check if extracting data from mail headers are needed.
- //If popups will be displayed or mailbrowser window
- if ((((mwui != nullptr) && !(mwui->RunFirstTime)) &&
- (
- ((nnflags & YAMN_ACC_MSGP) && !(MN.Real.BrowserUC + MN.Virtual.BrowserUC)) ||
- ((nflags & YAMN_ACC_MSGP) && (MN.Real.BrowserUC + MN.Virtual.BrowserUC))
- )
- ) || //if mail window was displayed before and flag YAMN_ACC_MSGP is set
- ((nnflags & YAMN_ACC_MSG) && !(MN.Real.BrowserUC + MN.Virtual.BrowserUC)) || //if needed to run mailbrowser when no unseen and no unseen mail found
- ((nflags & YAMN_ACC_MSG) && (MN.Real.BrowserUC + MN.Virtual.BrowserUC)) || //if unseen mails found, we sure run mailbrowser
- ((nflags & YAMN_ACC_ICO) && (MN.Real.SysTrayUC + MN.Virtual.SysTrayUC))
- ) //if needed to run systray
- RunMailBrowser = TRUE;
- else
- RunMailBrowser = FALSE;
-
- // if some popups with mails are needed to show
- if ((nflags & YAMN_ACC_POP) && (ActualAccount->Flags & YAMN_ACC_POPN) && (MN.Real.PopupNC + MN.Virtual.PopupNC))
- RunPopups = TRUE;
- else RunPopups = FALSE;
-
- if (RunMailBrowser)
- ChangeExistingMailStatus(GetDlgItem(hDlg, IDC_LISTMAILS), ActualAccount);
- if (RunMailBrowser || RunPopups)
- AddNewMailsToListView(hDlg == nullptr ? nullptr : GetDlgItem(hDlg, IDC_LISTMAILS), ActualAccount, nflags);
-
- if (RunMailBrowser) {
- size_t len = mir_strlen(ActualAccount->Name) + mir_strlen(Translate(MAILBROWSERTITLE)) + 10; //+10 chars for numbers
- char *TitleStrA = new char[len];
- wchar_t *TitleStrW = new wchar_t[len];
-
- mir_snprintf(TitleStrA, len, Translate(MAILBROWSERTITLE), ActualAccount->Name, MN.Real.DisplayUC + MN.Virtual.DisplayUC, MN.Real.Display + MN.Virtual.Display);
- MultiByteToWideChar(CP_ACP, MB_USEGLYPHCHARS, TitleStrA, -1, TitleStrW, (int)mir_strlen(TitleStrA) + 1);
- SetWindowTextW(hDlg, TitleStrW);
- delete[] TitleStrA;
- delete[] TitleStrW;
- }
-
- DoMailActions(hDlg, ActualAccount, &MN, nflags, nnflags);
-
- SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails, YAMN_MSG_NEW, 0, YAMN_MSG_NEW, YAMN_FLAG_REMOVE); //rempve the new flag
- if (!RunMailBrowser)
- SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails, YAMN_MSG_UNSEEN, YAMN_MSG_STAYUNSEEN, YAMN_MSG_UNSEEN, YAMN_FLAG_REMOVE); //remove the unseen flag when it was not displayed and it has not "stay unseen" flag set
-
- if (mwui != nullptr) {
- mwui->UpdateMailsMessagesAccess = FALSE;
- mwui->RunFirstTime = FALSE;
- }
-
- WriteDoneFcn(ActualAccount->MessagesAccessSO);
- ReadDoneFcn(ActualAccount->AccountAccessSO);
-
- if (RunMailBrowser)
- UpdateWindow(GetDlgItem(hDlg, IDC_LISTMAILS));
- else if (hDlg != nullptr)
- DestroyWindow(hDlg);
-
- return 1;
-}
-
-int ChangeExistingMailStatus(HWND hListView, CAccount *ActualAccount)
-{
- LVITEM item;
- HYAMNMAIL mail, msgq;
-
- int in = ListView_GetItemCount(hListView);
- item.mask = LVIF_PARAM;
-
- for (int i = 0; i < in; i++) {
- item.iItem = i;
- item.iSubItem = 0;
- if (TRUE == ListView_GetItem(hListView, &item))
- mail = (HYAMNMAIL)item.lParam;
- else
- continue;
- for (msgq = (HYAMNMAIL)ActualAccount->Mails; (msgq != nullptr) && (msgq != mail); msgq = msgq->Next); //found the same mail in account queue
- if (msgq == nullptr) //if mail was not found
- if (TRUE == ListView_DeleteItem(hListView, i)) {
- in--; i--;
- continue;
- }
- }
-
- return TRUE;
-}
-
-void MimeDateToLocalizedDateTime(char *datein, wchar_t *dateout, int lendateout);
-int AddNewMailsToListView(HWND hListView, CAccount *ActualAccount, uint32_t nflags)
-{
- wchar_t *FromStr;
- wchar_t SizeStr[20];
- wchar_t LocalDateStr[128];
-
- LVITEMW item;
- LVFINDINFO fi;
-
- int foundi = 0, lfoundi = 0;
- struct CHeader UnicodeHeader;
- BOOL Loaded, Extracted, FromStrNew = FALSE;
-
- memset(&item, 0, sizeof(item));
- memset(&UnicodeHeader, 0, sizeof(UnicodeHeader));
-
- if (hListView != nullptr) {
- item.mask = LVIF_TEXT | LVIF_PARAM;
- item.iItem = 0;
- memset(&fi, 0, sizeof(fi));
- fi.flags = LVFI_PARAM; //let's go search item by lParam number
- lfoundi = 0;
- }
-
- POPUPDATAW NewMailPopup = {};
- NewMailPopup.lchContact = (ActualAccount->hContact != NULL) ? ActualAccount->hContact : (UINT_PTR)ActualAccount;
- NewMailPopup.lchIcon = g_plugin.getIcon(IDI_NEWMAIL);
- if (nflags & YAMN_ACC_POPC) {
- NewMailPopup.colorBack = ActualAccount->NewMailN.PopupB;
- NewMailPopup.colorText = ActualAccount->NewMailN.PopupT;
- }
- else {
- NewMailPopup.colorBack = GetSysColor(COLOR_BTNFACE);
- NewMailPopup.colorText = GetSysColor(COLOR_WINDOWTEXT);
- }
- NewMailPopup.iSeconds = ActualAccount->NewMailN.PopupTime;
-
- NewMailPopup.PluginWindowProc = NewMailPopupProc;
- NewMailPopup.PluginData = nullptr; //it's new mail popup
-
- for (HYAMNMAIL msgq = (HYAMNMAIL)ActualAccount->Mails; msgq != nullptr; msgq = msgq->Next, lfoundi++) {
- // now we hide mail pointer to item's lParam member. We can later use it to retrieve mail datas
-
- Extracted = FALSE; FromStr = nullptr; FromStrNew = FALSE;
-
- if (hListView != nullptr) {
- fi.lParam = (LPARAM)msgq;
- if (-1 != (foundi = ListView_FindItem(hListView, -1, &fi))) { // if mail is already in window
- lfoundi = foundi;
- continue; // do not insert any item
- }
-
- item.iItem = lfoundi; // insert after last found item
- item.lParam = (LPARAM)msgq;
- }
-
- if (!LoadedMailData(msgq)) { // check if mail is already in memory
- Loaded = false;
- if (nullptr == LoadMailData(msgq)) //if we could not load mail to memory, consider this mail deleted and do not display it
- continue;
- }
- else Loaded = true;
-
- if (((hListView != nullptr) && (msgq->Flags & YAMN_MSG_DISPLAY)) ||
- ((nflags & YAMN_ACC_POP) && (ActualAccount->Flags & YAMN_ACC_POPN) && (msgq->Flags & YAMN_MSG_POPUP) && (msgq->Flags & YAMN_MSG_NEW))) {
-
- if (!Extracted) ExtractHeader(msgq->MailData->TranslatedHeader, msgq->MailData->CP, &UnicodeHeader);
- Extracted = TRUE;
-
- if ((UnicodeHeader.From != nullptr) && (UnicodeHeader.FromNick != nullptr)) {
- size_t size = mir_wstrlen(UnicodeHeader.From) + mir_wstrlen(UnicodeHeader.FromNick) + 4;
- FromStr = new wchar_t[size];
- mir_snwprintf(FromStr, size, L"%s <%s>", UnicodeHeader.FromNick, UnicodeHeader.From);
- FromStrNew = TRUE;
- }
- else if (UnicodeHeader.From != nullptr)
- FromStr = UnicodeHeader.From;
- else if (UnicodeHeader.FromNick != nullptr)
- FromStr = UnicodeHeader.FromNick;
- else if (UnicodeHeader.ReturnPath != nullptr)
- FromStr = UnicodeHeader.ReturnPath;
-
- if (nullptr == FromStr) {
- FromStr = L"";
- FromStrNew = FALSE;
- }
- }
-
- if ((hListView != nullptr) && (msgq->Flags & YAMN_MSG_DISPLAY)) {
- item.iSubItem = 0;
- item.pszText = FromStr;
- item.iItem = SendMessage(hListView, LVM_INSERTITEM, 0, (LPARAM)&item);
-
- item.iSubItem = 1;
- item.pszText = (nullptr != UnicodeHeader.Subject ? UnicodeHeader.Subject : (wchar_t *)L"");
- SendMessage(hListView, LVM_SETITEMTEXT, (WPARAM)item.iItem, (LPARAM)&item);
-
- item.iSubItem = 2;
- mir_snwprintf(SizeStr, L"%d kB", msgq->MailData->Size / 1024);
- item.pszText = SizeStr;
- SendMessage(hListView, LVM_SETITEMTEXT, (WPARAM)item.iItem, (LPARAM)&item);
-
- item.iSubItem = 3;
- item.pszText = L"";
-
- for (CMimeItem *heads = msgq->MailData->TranslatedHeader; heads != nullptr; heads = heads->Next) {
- if (!_stricmp(heads->name, "Date")) {
- MimeDateToLocalizedDateTime(heads->value, LocalDateStr, 128);
- item.pszText = LocalDateStr;
- break;
- }
- }
- SendMessage(hListView, LVM_SETITEMTEXT, (WPARAM)item.iItem, (LPARAM)&item);
- }
-
- if ((nflags & YAMN_ACC_POP) && (ActualAccount->Flags & YAMN_ACC_POPN) && (msgq->Flags & YAMN_MSG_POPUP) && (msgq->Flags & YAMN_MSG_NEW)) {
- mir_wstrncpy(NewMailPopup.lpwzContactName, FromStr, _countof(NewMailPopup.lpwzContactName));
- mir_wstrncpy(NewMailPopup.lpwzText, UnicodeHeader.Subject, _countof(NewMailPopup.lpwzText));
-
- PYAMN_MAILSHOWPARAM MailParam = (PYAMN_MAILSHOWPARAM)malloc(sizeof(YAMN_MAILSHOWPARAM));
- if (MailParam) {
- MailParam->account = ActualAccount;
- MailParam->mail = msgq;
- MailParam->ThreadRunningEV = nullptr;
- NewMailPopup.PluginData = MailParam;
- PUAddPopupW(&NewMailPopup);
- }
- }
-
- if ((msgq->Flags & YAMN_MSG_UNSEEN) && (ActualAccount->NewMailN.Flags & YAMN_ACC_KBN))
- CallService(MS_KBDNOTIFY_EVENTSOPENED, 1, NULL);
-
- if (FromStrNew)
- delete[] FromStr;
-
- if (Extracted) {
- DeleteHeaderContent(&UnicodeHeader);
- memset(&UnicodeHeader, 0, sizeof(UnicodeHeader));
- }
-
- if (!Loaded) {
- SaveMailData(msgq);
- UnloadMailData(msgq); //do not keep data for mail in memory
- }
- }
-
- return TRUE;
-}
-
-void DoMailActions(HWND hDlg, CAccount *ActualAccount, struct CMailNumbers *MN, uint32_t nflags, uint32_t nnflags)
-{
- NOTIFYICONDATA nid = {};
- nid.cbSize = sizeof(nid);
- nid.hWnd = hDlg;
-
- if (MN->Real.EventNC + MN->Virtual.EventNC)
- NotifyEventHooks(hNewMailHook, 0, 0);
-
- if ((nflags & YAMN_ACC_KBN) && (MN->Real.PopupRun + MN->Virtual.PopupRun))
- CallService(MS_KBDNOTIFY_STARTBLINK, (WPARAM)MN->Real.PopupNC + MN->Virtual.PopupNC, NULL);
-
- if ((nflags & YAMN_ACC_CONT) && (MN->Real.PopupRun + MN->Virtual.PopupRun)) {
- wchar_t tszMsg[250];
- mir_snwprintf(tszMsg, TranslateT("%s : %d new mail message(s), %d total"), _A2T(ActualAccount->Name).get(), MN->Real.PopupNC + MN->Virtual.PopupNC, MN->Real.PopupTC + MN->Virtual.PopupTC);
-
- if (!(nflags & YAMN_ACC_CONTNOEVENT)) {
- CLISTEVENT evt = {};
- evt.flags = CLEF_UNICODE;
- evt.hContact = ActualAccount->hContact;
- evt.hIcon = g_plugin.getIcon(IDI_NEWMAIL);
- evt.hDbEvent = ActualAccount->hContact;
- evt.lParam = ActualAccount->hContact;
- evt.pszService = MS_YAMN_CLISTDBLCLICK;
- evt.szTooltip.w = tszMsg;
- g_clistApi.pfnAddEvent(&evt);
- }
- db_set_ws(ActualAccount->hContact, "CList", "StatusMsg", tszMsg);
-
- if (nflags & YAMN_ACC_CONTNICK)
- g_plugin.setWString(ActualAccount->hContact, "Nick", tszMsg);
- }
-
- if ((nflags & YAMN_ACC_POP) &&
- !(ActualAccount->Flags & YAMN_ACC_POPN) &&
- (MN->Real.PopupRun + MN->Virtual.PopupRun)) {
- POPUPDATAW NewMailPopup;
-
- NewMailPopup.lchContact = (ActualAccount->hContact != NULL) ? ActualAccount->hContact : (UINT_PTR)ActualAccount;
- NewMailPopup.lchIcon = g_plugin.getIcon(IDI_NEWMAIL);
- if (nflags & YAMN_ACC_POPC) {
- NewMailPopup.colorBack = ActualAccount->NewMailN.PopupB;
- NewMailPopup.colorText = ActualAccount->NewMailN.PopupT;
- }
- else {
- NewMailPopup.colorBack = GetSysColor(COLOR_BTNFACE);
- NewMailPopup.colorText = GetSysColor(COLOR_WINDOWTEXT);
- }
- NewMailPopup.iSeconds = ActualAccount->NewMailN.PopupTime;
-
- NewMailPopup.PluginWindowProc = NewMailPopupProc;
- NewMailPopup.PluginData = (void *)nullptr; //multiple popups
-
- mir_wstrncpy(NewMailPopup.lpwzContactName, _A2T(ActualAccount->Name), _countof(NewMailPopup.lpwzContactName));
- mir_snwprintf(NewMailPopup.lpwzText, TranslateT("%d new mail message(s), %d total"), MN->Real.PopupNC + MN->Virtual.PopupNC, MN->Real.PopupTC + MN->Virtual.PopupTC);
- PUAddPopupW(&NewMailPopup);
- }
-
- // destroy tray icon if no new mail
- if ((MN->Real.SysTrayUC + MN->Virtual.SysTrayUC == 0) && (hDlg != nullptr))
- Shell_NotifyIcon(NIM_DELETE, &nid);
-
- // and remove the event
- if ((nflags & YAMN_ACC_CONT) && (!(nflags & YAMN_ACC_CONTNOEVENT)) && (MN->Real.UnSeen + MN->Virtual.UnSeen == 0))
- g_clistApi.pfnRemoveEvent(ActualAccount->hContact, ActualAccount->hContact);
-
- if ((MN->Real.BrowserUC + MN->Virtual.BrowserUC == 0) && (hDlg != nullptr)) {
- if (!IsWindowVisible(hDlg) && !(nflags & YAMN_ACC_MSG))
- PostMessage(hDlg, WM_DESTROY, 0, 0); //destroy window if no new mail and window is not visible
- if (nnflags & YAMN_ACC_MSG) //if no new mail and msg should be executed
- {
- SetForegroundWindow(hDlg);
- ShowWindow(hDlg, SW_SHOWNORMAL);
- }
- }
- else
- if (hDlg != nullptr) //else insert icon and set window if new mails
- {
- SendDlgItemMessageW(hDlg, IDC_LISTMAILS, LVM_SCROLL, 0, (LPARAM)0x7ffffff);
-
- if ((nflags & YAMN_ACC_ICO) && (MN->Real.SysTrayUC + MN->Virtual.SysTrayUC)) {
- nid.hIcon = g_plugin.getIcon(IDI_NEWMAIL);
- nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
- nid.uCallbackMessage = WM_YAMN_NOTIFYICON;
- mir_snwprintf(nid.szTip, L"%S %s", ActualAccount->Name, TranslateT("- new mail message(s)"));
- Shell_NotifyIcon(NIM_ADD, &nid);
- SetTimer(hDlg, TIMER_FLASHING, 500, nullptr);
- }
- if (nflags & YAMN_ACC_MSG) //if no new mail and msg should be executed
- ShowWindow(hDlg, SW_SHOWNORMAL);
- }
-
- if (MN->Real.AppNC + MN->Virtual.AppNC != 0) {
- if (nflags & YAMN_ACC_APP) {
- PROCESS_INFORMATION pi;
- STARTUPINFOW si;
- memset(&si, 0, sizeof(si));
- si.cb = sizeof(si);
-
- if (ActualAccount->NewMailN.App != nullptr) {
- wchar_t *Command;
- if (ActualAccount->NewMailN.AppParam != nullptr)
- Command = new wchar_t[mir_wstrlen(ActualAccount->NewMailN.App) + mir_wstrlen(ActualAccount->NewMailN.AppParam) + 6];
- else
- Command = new wchar_t[mir_wstrlen(ActualAccount->NewMailN.App) + 6];
-
- if (Command != nullptr) {
- mir_wstrcpy(Command, L"\"");
- mir_wstrcat(Command, ActualAccount->NewMailN.App);
- mir_wstrcat(Command, L"\" ");
- if (ActualAccount->NewMailN.AppParam != nullptr)
- mir_wstrcat(Command, ActualAccount->NewMailN.AppParam);
- CreateProcessW(nullptr, Command, nullptr, nullptr, FALSE, NORMAL_PRIORITY_CLASS, nullptr, nullptr, &si, &pi);
- delete[] Command;
- }
- }
- }
- }
-
- if (MN->Real.SoundNC + MN->Virtual.SoundNC != 0)
- if (nflags & YAMN_ACC_SND)
- Skin_PlaySound(YAMN_NEWMAILSOUND);
-
- if ((nnflags & YAMN_ACC_POP) && (MN->Real.PopupRun + MN->Virtual.PopupRun == 0)) {
- POPUPDATAW NoNewMailPopup = {};
-
- NoNewMailPopup.lchContact = (ActualAccount->hContact != NULL) ? ActualAccount->hContact : (UINT_PTR)ActualAccount;
- NoNewMailPopup.lchIcon = g_plugin.getIcon(IDI_LAUNCHAPP);
- if (nflags & YAMN_ACC_POPC) {
- NoNewMailPopup.colorBack = ActualAccount->NoNewMailN.PopupB;
- NoNewMailPopup.colorText = ActualAccount->NoNewMailN.PopupT;
- }
- else {
- NoNewMailPopup.colorBack = GetSysColor(COLOR_BTNFACE);
- NoNewMailPopup.colorText = GetSysColor(COLOR_WINDOWTEXT);
- }
- NoNewMailPopup.iSeconds = ActualAccount->NoNewMailN.PopupTime;
-
- NoNewMailPopup.PluginWindowProc = NoNewMailPopupProc;
- NoNewMailPopup.PluginData = nullptr; //it's not new mail popup
-
- mir_wstrncpy(NoNewMailPopup.lpwzContactName, _A2T(ActualAccount->Name), _countof(NoNewMailPopup.lpwzContactName));
- if (MN->Real.PopupSL2NC + MN->Virtual.PopupSL2NC)
- mir_snwprintf(NoNewMailPopup.lpwzText, TranslateT("No new mail message, %d spam(s)"), MN->Real.PopupSL2NC + MN->Virtual.PopupSL2NC);
- else
- mir_wstrncpy(NoNewMailPopup.lpwzText, TranslateT("No new mail message"), _countof(NoNewMailPopup.lpwzText));
- PUAddPopupW(&NoNewMailPopup);
- }
-
- if ((nflags & YAMN_ACC_CONT) && (MN->Real.PopupRun + MN->Virtual.PopupRun == 0)) {
- if (ActualAccount->hContact != NULL) {
- if (MN->Real.PopupTC + MN->Virtual.PopupTC) {
- char tmp[255];
- mir_snprintf(tmp, Translate("%d new mail message(s), %d total"), MN->Real.PopupNC + MN->Virtual.PopupNC, MN->Real.PopupTC + MN->Virtual.PopupTC);
- db_set_s(ActualAccount->hContact, "CList", "StatusMsg", tmp);
- }
- else db_set_s(ActualAccount->hContact, "CList", "StatusMsg", Translate("No new mail message"));
-
- if (nflags & YAMN_ACC_CONTNICK)
- g_plugin.setString(ActualAccount->hContact, "Nick", ActualAccount->Name);
- }
- }
- return;
-}
-
-LRESULT CALLBACK NewMailPopupProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- INT_PTR PluginParam = 0;
- switch (msg) {
- case WM_COMMAND:
- // if clicked and it's new mail popup window
- if ((HIWORD(wParam) == STN_CLICKED) && (-1 != (PluginParam = (INT_PTR)PUGetPluginData(hWnd)))) {
- MCONTACT hContact = 0;
- CAccount *Account;
- if (PluginParam) {
- PYAMN_MAILSHOWPARAM MailParam = new YAMN_MAILSHOWPARAM;
- memcpy(MailParam, (PINT_PTR)PluginParam, sizeof(YAMN_MAILSHOWPARAM));
- hContact = MailParam->account->hContact;
- Account = MailParam->account;
- mir_forkthread(ShowEmailThread, MailParam);
- }
- else {
- DBVARIANT dbv;
-
- hContact = PUGetContact(hWnd);
-
- if (!g_plugin.getString(hContact, "Id", &dbv)) {
- Account = (CAccount *)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)dbv.pszVal);
- db_free(&dbv);
- }
- else Account = (CAccount *)hContact; //????
-
- if (WAIT_OBJECT_0 == WaitToReadFcn(Account->AccountAccessSO)) {
- switch (msg) {
- case WM_COMMAND:
- {
- YAMN_MAILBROWSERPARAM Param = {(HANDLE)nullptr, Account,
- (Account->NewMailN.Flags & ~YAMN_ACC_POP) | YAMN_ACC_MSGP | YAMN_ACC_MSG,
- (Account->NoNewMailN.Flags & ~YAMN_ACC_POP) | YAMN_ACC_MSGP | YAMN_ACC_MSG};
-
- RunMailBrowserSvc((WPARAM)&Param, (LPARAM)YAMN_MAILBROWSERVERSION);
- }
- break;
- }
- ReadDoneFcn(Account->AccountAccessSO);
- }
- }
- if ((Account->NewMailN.Flags & YAMN_ACC_CONT) && !(Account->NewMailN.Flags & YAMN_ACC_CONTNOEVENT))
- g_clistApi.pfnRemoveEvent(hContact, hContact);
- }
- __fallthrough;
-
- case WM_CONTEXTMENU:
- PUDeletePopup(hWnd);
- break;
- case UM_FREEPLUGINDATA:
- {
- PYAMN_MAILSHOWPARAM mpd = (PYAMN_MAILSHOWPARAM)PUGetPluginData(hWnd);
- if ((mpd) && (INT_PTR)mpd != -1)free(mpd);
- return FALSE;
- }
- case UM_INITPOPUP:
- //This is the equivalent to WM_INITDIALOG you'd get if you were the maker of dialog popups.
- WindowList_Add(YAMNVar.MessageWnds, hWnd);
- break;
- case UM_DESTROYPOPUP:
- WindowList_Remove(YAMNVar.MessageWnds, hWnd);
- break;
- case WM_YAMN_STOPACCOUNT:
- {
- CAccount *ActualAccount;
- DBVARIANT dbv;
-
- MCONTACT hContact = PUGetContact(hWnd);
-
- if (!g_plugin.getString(hContact, "Id", &dbv)) {
- ActualAccount = (CAccount *)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)dbv.pszVal);
- db_free(&dbv);
- }
- else
- ActualAccount = (CAccount *)hContact;
-
- if ((CAccount *)wParam != ActualAccount)
- break;
- DestroyWindow(hWnd);
- return 0;
- }
- case WM_NOTIFY:
- default:
- break;
- }
- return DefWindowProc(hWnd, msg, wParam, lParam);
-}
-
-LRESULT CALLBACK NoNewMailPopupProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- switch (msg) {
- case WM_COMMAND:
- if ((HIWORD(wParam) == STN_CLICKED) && (msg == WM_COMMAND)) {
- CAccount *ActualAccount;
- DBVARIANT dbv;
-
- MCONTACT hContact = PUGetContact(hWnd);
-
- if (!g_plugin.getString(hContact, "Id", &dbv)) {
- ActualAccount = (CAccount *)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)dbv.pszVal);
- db_free(&dbv);
- }
- else
- ActualAccount = (CAccount *)hContact;
-
- if (WAIT_OBJECT_0 == WaitToReadFcn(ActualAccount->AccountAccessSO)) {
- switch (msg) {
- case WM_COMMAND:
- {
- YAMN_MAILBROWSERPARAM Param = {(HANDLE)nullptr, ActualAccount, ActualAccount->NewMailN.Flags, ActualAccount->NoNewMailN.Flags, nullptr};
-
- Param.nnflags = Param.nnflags | YAMN_ACC_MSG; //show mails in account even no new mail in account
- Param.nnflags = Param.nnflags & ~YAMN_ACC_POP;
-
- Param.nflags = Param.nflags | YAMN_ACC_MSG; //show mails in account even no new mail in account
- Param.nflags = Param.nflags & ~YAMN_ACC_POP;
-
- RunMailBrowserSvc((WPARAM)&Param, (LPARAM)YAMN_MAILBROWSERVERSION);
- }
- break;
- }
- ReadDoneFcn(ActualAccount->AccountAccessSO);
- }
- PUDeletePopup(hWnd);
- }
- break;
-
- case WM_CONTEXTMENU:
- PUDeletePopup(hWnd);
- break;
-
- case UM_FREEPLUGINDATA:
- //Here we'd free our own data, if we had it.
- return FALSE;
- case UM_INITPOPUP:
- //This is the equivalent to WM_INITDIALOG you'd get if you were the maker of dialog popups.
- WindowList_Add(YAMNVar.MessageWnds, hWnd);
- break;
- case UM_DESTROYPOPUP:
- WindowList_Remove(YAMNVar.MessageWnds, hWnd);
- break;
- case WM_YAMN_STOPACCOUNT:
- {
- CAccount *ActualAccount;
- DBVARIANT dbv;
-
- MCONTACT hContact = PUGetContact(hWnd);
-
- if (!g_plugin.getString(hContact, "Id", &dbv)) {
- ActualAccount = (CAccount *)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)dbv.pszVal);
- db_free(&dbv);
- }
- else
- ActualAccount = (CAccount *)hContact;
-
- if ((CAccount *)wParam != ActualAccount)
- break;
-
- DestroyWindow(hWnd);
- return 0;
- }
- }
- return DefWindowProc(hWnd, msg, wParam, lParam);
-}
-
-#ifdef __GNUC__
-//number of 100 ns periods between FILETIME 0 (1601/01/01 00:00:00.0000000) and TIMESTAMP 0 (1970/01/01 00:00:00)
-#define NUM100NANOSEC 116444736000000000ULL
-//The biggest time Get[Date|Time]Format can handle (Fri, 31 Dec 30827 23:59:59.9999999)
-#define MAXFILETIME 0x7FFF35F4F06C7FFFULL
-#else
-#define NUM100NANOSEC 116444736000000000
-#define MAXFILETIME 0x7FFF35F4F06C7FFF
-#endif
-
-ULONGLONG MimeDateToFileTime(char *datein)
-{
- char *day = nullptr, *month = nullptr, *year = nullptr, *time = nullptr, *shift = nullptr;
- SYSTEMTIME st;
- ULONGLONG res = 0;
- int wShiftSeconds = TimeZone_ToLocal(0);
- GetLocalTime(&st);
- //datein = "Xxx, 1 Jan 2060 5:29:1 +0530 XXX";
- //datein = "Xxx, 1 Jan 2060 05:29:10 ";
- //datein = " ManySpaces 1.5 Jan 2060 05::";
- //datein = "Xxx, 35 February 20 :29:10 ";
- //datein = "01.12.2007 (22:38:17)"; //
- if (datein) {
- char tmp[64];
- while (datein[0] == ' ') datein++; // eat leading spaces
- strncpy(tmp, datein, 63); tmp[63] = 0;
- if (atoi(tmp)) { // Parseable integer on DayOfWeek field? Buggy mime date.
- day = tmp;
- }
- else {
- int i = 0;
- while (tmp[i] == ' ')i++; if (day = strchr(&tmp[i], ' ')) { day[0] = 0; day++; }
- }
- if (day) { while (day[0] == ' ') day++; if (month = strchr(day, ' ')) { month[0] = 0; month++; } }
- if (month) { while (month[0] == ' ')month++; if (year = strchr(month, ' ')) { year[0] = 0; year++; } }
- if (year) { while (year[0] == ' ') year++; if (time = strchr(year, ' ')) { time[0] = 0; time++; } }
- if (time) { while (time[0] == ' ') time++; if (shift = strchr(time, ' ')) { shift[0] = 0; shift++; shift[5] = 0; } }
-
- if (year) {
- st.wYear = atoi(year);
- if (mir_strlen(year) < 4) if (st.wYear < 70)st.wYear += 2000; else st.wYear += 1900;
- };
- if (month) for (int i = 0; i < 12; i++) if (strncmp(month, s_MonthNames[i], 3) == 0) { st.wMonth = i + 1; break; }
- if (day) st.wDay = atoi(day);
- if (time) {
- char *h, *m, *s;
- h = time;
- if (m = strchr(h, ':')) {
- m[0] = 0; m++;
- if (s = strchr(m, ':')) { s[0] = 0; s++; }
- }
- else s = nullptr;
- st.wHour = atoi(h);
- st.wMinute = m ? atoi(m) : 0;
- st.wSecond = s ? atoi(s) : 0;
- }
- else { st.wHour = st.wMinute = st.wSecond = 0; }
-
- if (shift) {
- if (mir_strlen(shift) < 4) {
- //has only hour
- wShiftSeconds = (atoi(shift)) * 3600;
- }
- else {
- char *smin = shift + mir_strlen(shift) - 2;
- int ismin = atoi(smin);
- smin[0] = 0;
- int ishour = atoi(shift);
- wShiftSeconds = (ishour * 60 + (ishour < 0 ? -1 : 1) * ismin) * 60;
- }
- }
- } // if (datein)
- FILETIME ft;
- if (SystemTimeToFileTime(&st, &ft)) {
- res = ((ULONGLONG)ft.dwHighDateTime << 32) | ((ULONGLONG)ft.dwLowDateTime);
- LONGLONG w100nano = Int32x32To64((uint32_t)wShiftSeconds, 10000000);
- res -= w100nano;
- }
- else {
- res = 0;
- }
- return res;
-}
-
-void FileTimeToLocalizedDateTime(LONGLONG filetime, wchar_t *dateout, int lendateout)
-{
- int localeID = Langpack_GetDefaultLocale();
- //int localeID = MAKELCID(LANG_URDU, SORT_DEFAULT);
- if (localeID == CALLSERVICE_NOTFOUND) localeID = LOCALE_USER_DEFAULT;
- if (filetime > MAXFILETIME) filetime = MAXFILETIME;
- else if (filetime <= 0) {
- wcsncpy(dateout, TranslateT("Invalid"), lendateout);
- return;
- }
- SYSTEMTIME st;
- uint16_t wTodayYear = 0, wTodayMonth = 0, wTodayDay = 0;
- FILETIME ft;
- BOOL willShowDate = !(optDateTime & SHOWDATENOTODAY);
- if (!willShowDate) {
- GetLocalTime(&st);
- wTodayYear = st.wYear;
- wTodayMonth = st.wMonth;
- wTodayDay = st.wDay;
- }
- ft.dwLowDateTime = (uint32_t)filetime;
- ft.dwHighDateTime = (uint32_t)(filetime >> 32);
- FILETIME localft;
- if (!FileTimeToLocalFileTime(&ft, &localft)) {
- // this should never happen
- wcsncpy(dateout, L"Incorrect FileTime", lendateout);
- }
- else {
- if (!FileTimeToSystemTime(&localft, &st)) {
- // this should never happen
- wcsncpy(dateout, L"Incorrect LocalFileTime", lendateout);
- }
- else {
- dateout[lendateout - 1] = 0;
- int templen = 0;
- if (!willShowDate) willShowDate = (wTodayYear != st.wYear) || (wTodayMonth != st.wMonth) || (wTodayDay != st.wDay);
- if (willShowDate) {
- templen = GetDateFormatW(localeID, (optDateTime & SHOWDATELONG) ? DATE_LONGDATE : DATE_SHORTDATE, &st, nullptr, dateout, lendateout - 2);
- dateout[templen - 1] = ' ';
- }
- if (templen < (lendateout - 1)) {
- GetTimeFormatW(localeID, (optDateTime & SHOWDATENOSECONDS) ? TIME_NOSECONDS : 0, &st, nullptr, &dateout[templen], lendateout - templen - 1);
- }
- }
- }
-}
-
-void MimeDateToLocalizedDateTime(char *datein, wchar_t *dateout, int lendateout)
-{
- ULONGLONG ft = MimeDateToFileTime(datein);
- FileTimeToLocalizedDateTime(ft, dateout, lendateout);
-}
-
-int CALLBACK ListViewCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
-{
- if (lParam1 == NULL || lParam2 == NULL)
- return 0;
-
- int nResult = 0;
- char *str1;
- char *str2;
- HYAMNMAIL email1 = (HYAMNMAIL)lParam1;
- HYAMNMAIL email2 = (HYAMNMAIL)lParam2;
- struct CShortHeader Header1;
- struct CShortHeader Header2;
- memset(&Header1, 0, sizeof(Header1));
- memset(&Header2, 0, sizeof(Header2));
-
- try {
- ExtractShortHeader(email1->MailData->TranslatedHeader, &Header1);
- ExtractShortHeader(email2->MailData->TranslatedHeader, &Header2);
-
- switch ((int)lParamSort) {
- case 0: //From
- if (Header1.FromNick == nullptr)
- str1 = Header1.From;
- else str1 = Header1.FromNick;
-
- if (Header2.FromNick == nullptr)
- str2 = Header2.From;
- else str2 = Header2.FromNick;
-
- nResult = mir_strcmp(str1, str2);
-
- if (bFrom) nResult = -nResult;
- break;
- case 1: //Subject
- if (Header1.Subject == nullptr)
- str1 = " ";
- else str1 = Header1.Subject;
-
- if (Header2.Subject == nullptr)
- str2 = " ";
- else str2 = Header2.Subject;
-
- nResult = mir_strcmp(str1, str2);
-
- if (bSub) nResult = -nResult;
- break;
- case 2: //Size
- if (email1->MailData->Size == email2->MailData->Size) nResult = 0;
- if (email1->MailData->Size > email2->MailData->Size) nResult = 1;
- if (email1->MailData->Size < email2->MailData->Size) nResult = -1;
-
- if (bSize) nResult = -nResult;
- break;
-
- case 3: //Date
- {
- ULONGLONG ts1 = 0, ts2 = 0;
- ts1 = MimeDateToFileTime(Header1.Date);
- ts2 = MimeDateToFileTime(Header2.Date);
- if (ts1 > ts2) nResult = 1;
- else if (ts1 < ts2) nResult = -1;
- else nResult = 0;
- }
- if (bDate) nResult = -nResult;
- break;
-
- default:
- if (Header1.Subject == nullptr) str1 = " ";
- else str1 = Header1.Subject;
-
- if (Header2.Subject == nullptr) str2 = " ";
- else str2 = Header2.Subject;
-
- nResult = mir_strcmp(str1, str2);
- break;
- }
- //MessageBox(NULL,str1,str2,0);
- }
- catch (...) {
- }
-
- //free mem
- DeleteShortHeaderContent(&Header1);
- DeleteShortHeaderContent(&Header2);
- return nResult;
-
-}
-
-HCURSOR hCurSplitNS, hCurSplitWE;
-#define DM_SPLITTERMOVED (WM_USER+15)
-
-static LRESULT CALLBACK SplitterSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- switch (msg) {
- case WM_NCHITTEST:
- return HTCLIENT;
-
- case WM_SETCURSOR:
- SetCursor(hCurSplitNS);
- return TRUE;
-
- case WM_LBUTTONDOWN:
- SetCapture(hwnd);
- return 0;
-
- case WM_MOUSEMOVE:
- if (GetCapture() == hwnd) {
- RECT rc;
- GetClientRect(hwnd, &rc);
- SendMessage(GetParent(hwnd), DM_SPLITTERMOVED, (short)HIWORD(GetMessagePos()) + rc.bottom / 2, (LPARAM)hwnd);
- }
- return 0;
-
- case WM_LBUTTONUP:
- ReleaseCapture();
- return 0;
- }
- return mir_callNextSubclass(hwnd, SplitterSubclassProc, msg, wParam, lParam);
-}
-
-void ConvertCodedStringToUnicode(char *stream, wchar_t **storeto, uint32_t cp, int mode);
-int ConvertStringToUnicode(char *stream, unsigned int cp, wchar_t **out);
-
-INT_PTR CALLBACK DlgProcYAMNShowMessage(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- switch (msg) {
- case WM_INITDIALOG:
- {
- PYAMN_MAILSHOWPARAM MailParam = (PYAMN_MAILSHOWPARAM)lParam;
- wchar_t *iHeaderW = nullptr;
- wchar_t *iValueW = nullptr;
- int StrLen;
- HWND hListView = GetDlgItem(hDlg, IDC_LISTHEADERS);
- mir_subclassWindow(GetDlgItem(hDlg, IDC_SPLITTER), SplitterSubclassProc);
- SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)MailParam);
- Window_SetIcon_IcoLib(hDlg, g_plugin.getIconHandle(IDI_NEWMAIL));
-
- ListView_SetUnicodeFormat(hListView, TRUE);
- ListView_SetExtendedListViewStyle(hListView, LVS_EX_FULLROWSELECT);
-
- StrLen = MultiByteToWideChar(CP_ACP, MB_USEGLYPHCHARS, Translate("Header"), -1, nullptr, 0);
- iHeaderW = new wchar_t[StrLen + 1];
- MultiByteToWideChar(CP_ACP, MB_USEGLYPHCHARS, Translate("Header"), -1, iHeaderW, StrLen);
-
- StrLen = MultiByteToWideChar(CP_ACP, MB_USEGLYPHCHARS, Translate("Value"), -1, nullptr, 0);
- iValueW = new wchar_t[StrLen + 1];
- MultiByteToWideChar(CP_ACP, MB_USEGLYPHCHARS, Translate("Value"), -1, iValueW, StrLen);
-
- LVCOLUMN lvc0 = {LVCF_FMT | LVCF_TEXT | LVCF_WIDTH, LVCFMT_LEFT, 130, iHeaderW, 0, 0};
- LVCOLUMN lvc1 = {LVCF_FMT | LVCF_TEXT | LVCF_WIDTH, LVCFMT_LEFT, 400, iValueW, 0, 0};
- SendMessage(hListView, LVM_INSERTCOLUMN, 0, (LPARAM)&lvc0);
- SendMessage(hListView, LVM_INSERTCOLUMN, 1, (LPARAM)&lvc1);
- if (nullptr != iHeaderW)
- delete[] iHeaderW;
- if (nullptr != iValueW)
- delete[] iValueW;
-
- SendMessage(hDlg, WM_YAMN_CHANGECONTENT, 0, (LPARAM)MailParam);
- MoveWindow(hDlg, HeadPosX, HeadPosY, HeadSizeX, HeadSizeY, 0);
- ShowWindow(hDlg, SW_SHOWNORMAL);
- }
- break;
-
- case WM_YAMN_CHANGECONTENT:
- {
- PYAMN_MAILSHOWPARAM MailParam = (PYAMN_MAILSHOWPARAM)
- (lParam ? lParam : GetWindowLongPtr(hDlg, DWLP_USER));
- HWND hListView = GetDlgItem(hDlg, IDC_LISTHEADERS);
- HWND hEdit = GetDlgItem(hDlg, IDC_EDITBODY);
- //do not redraw
- SendMessage(hListView, WM_SETREDRAW, 0, 0);
- ListView_DeleteAllItems(hListView);
- struct CMimeItem *Header;
- LVITEMW item;
- item.mask = LVIF_TEXT | LVIF_PARAM;
- wchar_t *From = nullptr, *Subj = nullptr;
- char *contentType = nullptr, *transEncoding = nullptr, *body = nullptr; //should not be delete[]-ed
- for (Header = MailParam->mail->MailData->TranslatedHeader; Header != nullptr; Header = Header->Next) {
- wchar_t *str1 = nullptr;
- wchar_t *str2 = nullptr;
- wchar_t str_nul[2] = {0};
- if (!body) if (!_stricmp(Header->name, "Body")) { body = Header->value; continue; }
- if (!contentType) if (!_stricmp(Header->name, "Content-Type")) contentType = Header->value;
- if (!transEncoding) if (!_stricmp(Header->name, "Content-Transfer-Encoding")) transEncoding = Header->value;
- //ConvertCodedStringToUnicode(Header->name,&str1,MailParam->mail->MailData->CP,1);
- {
- int streamsize = MultiByteToWideChar(20127, 0, Header->name, -1, nullptr, 0);
- str1 = (wchar_t *)malloc(sizeof(wchar_t) * (streamsize + 1));
- MultiByteToWideChar(20127, 0, Header->name, -1, str1, streamsize);//US-ASCII
- }
- ConvertCodedStringToUnicode(Header->value, &str2, MailParam->mail->MailData->CP, 1);
- if (!str2) { str2 = (wchar_t *)str_nul; }// the header value may be NULL
- if (!From) if (!_stricmp(Header->name, "From")) {
- From = new wchar_t[mir_wstrlen(str2) + 1];
- mir_wstrcpy(From, str2);
- }
- if (!Subj) if (!_stricmp(Header->name, "Subject")) {
- Subj = new wchar_t[mir_wstrlen(str2) + 1];
- mir_wstrcpy(Subj, str2);
- }
- //if (!hasBody) if (!mir_strcmp(Header->name,"Body")) hasBody = true;
- int count = 0; wchar_t **split = nullptr;
- int ofs = 0;
- while (str2[ofs]) {
- if ((str2[ofs] == 0x266A) || (str2[ofs] == 0x25D9) || (str2[ofs] == 0x25CB) ||
- (str2[ofs] == 0x09) || (str2[ofs] == 0x0A) || (str2[ofs] == 0x0D))count++;
- ofs++;
- }
- split = new wchar_t *[count + 1];
- count = 0; ofs = 0;
- split[0] = str2;
- while (str2[ofs]) {
- if ((str2[ofs] == 0x266A) || (str2[ofs] == 0x25D9) || (str2[ofs] == 0x25CB) ||
- (str2[ofs] == 0x09) || (str2[ofs] == 0x0A) || (str2[ofs] == 0x0D)) {
- if (str2[ofs - 1]) {
- count++;
- }
- split[count] = (wchar_t *)(str2 + ofs + 1);
- str2[ofs] = 0;
- }
- ofs++;
- };
-
- if (!_stricmp(Header->name, "From") || !_stricmp(Header->name, "To") || !_stricmp(Header->name, "Date") || !_stricmp(Header->name, "Subject"))
- item.iItem = 0;
- else
- item.iItem = 999;
- for (int i = 0; i <= count; i++) {
- item.iSubItem = 0;
- if (i == 0)
- item.pszText = str1;
- else {
- item.iItem++;
- item.pszText = nullptr;
- }
- item.iItem = SendMessage(hListView, LVM_INSERTITEM, 0, (LPARAM)&item);
- item.iSubItem = 1;
- item.pszText = str2 ? split[i] : nullptr;
- SendMessage(hListView, LVM_SETITEMTEXT, (WPARAM)item.iItem, (LPARAM)&item);
- }
- delete[] split;
-
- if (str1)
- free(str1);
- if (str2 != (wchar_t *)str_nul)
- free(str2);
- }
- if (body) {
- wchar_t *bodyDecoded = nullptr;
- char *localBody = nullptr;
- if (contentType) {
- if (!_strnicmp(contentType, "text", 4)) {
- if (transEncoding) {
- if (!_stricmp(transEncoding, "base64")) {
- int size = (int)mir_strlen(body) * 3 / 4 + 5;
- localBody = new char[size + 1];
- DecodeBase64(body, localBody, size);
- }
- else if (!_stricmp(transEncoding, "quoted-printable")) {
- int size = (int)mir_strlen(body) + 2;
- localBody = new char[size + 1];
- DecodeQuotedPrintable(body, localBody, size, FALSE);
- }
- }
- }
- else if (!_strnicmp(contentType, "multipart/", 10)) {
- char *bondary = nullptr;
- if (nullptr != (bondary = ExtractFromContentType(contentType, "boundary="))) {
- bodyDecoded = ParseMultipartBody(body, bondary);
- delete[] bondary;
- }
- }
- }
- if (!bodyDecoded)ConvertStringToUnicode(localBody ? localBody : body, MailParam->mail->MailData->CP, &bodyDecoded);
- SetWindowTextW(hEdit, bodyDecoded);
- delete[] bodyDecoded;
- if (localBody) delete[] localBody;
- SetFocus(hEdit);
- }
- if (!(MailParam->mail->Flags & YAMN_MSG_BODYRECEIVED)) {
- MailParam->mail->Flags |= YAMN_MSG_BODYREQUESTED;
- CallService(MS_YAMN_ACCOUNTCHECK, (WPARAM)MailParam->account, 0);
- }
- else {
- if (MailParam->mail->Flags & YAMN_MSG_UNSEEN) {
- MailParam->mail->Flags &= ~YAMN_MSG_UNSEEN; //mark the message as seen
- HWND hMailBrowser = WindowList_Find(YAMNVar.NewMailAccountWnd, (UINT_PTR)MailParam->account);
- if (hMailBrowser) {
- struct CChangeContent Params = {MailParam->account->NewMailN.Flags | YAMN_ACC_MSGP, MailParam->account->NoNewMailN.Flags | YAMN_ACC_MSGP};
- SendMessage(hMailBrowser, WM_YAMN_CHANGECONTENT, (WPARAM)MailParam->account, (LPARAM)&Params);
- }
- else UpdateMails(nullptr, MailParam->account, MailParam->account->NewMailN.Flags, MailParam->account->NoNewMailN.Flags);
- }
- }
- ShowWindow(GetDlgItem(hDlg, IDC_SPLITTER), (MailParam->mail->Flags & YAMN_MSG_BODYRECEIVED) ? SW_SHOW : SW_HIDE);
- ShowWindow(hEdit, (MailParam->mail->Flags & YAMN_MSG_BODYRECEIVED) ? SW_SHOW : SW_HIDE);
- wchar_t *title = nullptr;
- size_t size = (From ? mir_wstrlen(From) : 0) + (Subj ? mir_wstrlen(Subj) : 0) + 4;
- title = new wchar_t[size];
- if (From && Subj)
- mir_snwprintf(title, size, L"%s (%s)", Subj, From);
- else if (From)
- wcsncpy_s(title, size, From, _TRUNCATE);
- else if (Subj)
- wcsncpy_s(title, size, Subj, _TRUNCATE);
- else
- wcsncpy_s(title, size, L"none", _TRUNCATE);
- if (Subj) delete[] Subj;
- if (From) delete[] From;
- SetWindowTextW(hDlg, title);
- delete[] title;
- // turn on redrawing
- SendMessage(hListView, WM_SETREDRAW, 1, 0);
- SendMessage(hDlg, WM_SIZE, 0, HeadSizeY << 16 | HeadSizeX);
- } break;
-
- case WM_YAMN_STOPACCOUNT:
- {
- PYAMN_MAILSHOWPARAM MailParam = (PYAMN_MAILSHOWPARAM)
- (lParam ? lParam : GetWindowLongPtr(hDlg, DWLP_USER));
-
- if (nullptr == MailParam)
- break;
- if ((CAccount *)wParam != MailParam->account)
- break;
-
- DestroyWindow(hDlg);
- }
- return 1;
-
- case WM_CTLCOLORSTATIC:
- // here should be check if this is our edittext control.
- // but we have only one static control (for now);
- SetBkColor((HDC)wParam, GetSysColor(COLOR_WINDOW));
- SetTextColor((HDC)wParam, GetSysColor(COLOR_WINDOWTEXT));
- return (INT_PTR)GetSysColorBrush(COLOR_WINDOW);
-
- case WM_DESTROY:
- Window_FreeIcon_IcoLib(hDlg);
- {
- RECT coord;
- if (GetWindowRect(hDlg, &coord)) {
- HeadPosX = coord.left;
- HeadSizeX = coord.right - coord.left;
- HeadPosY = coord.top;
- HeadSizeY = coord.bottom - coord.top;
- }
-
- PostQuitMessage(1);
- }
- break;
-
- case WM_SYSCOMMAND:
- switch (wParam) {
- case SC_CLOSE:
- DestroyWindow(hDlg);
- break;
- }
- break;
-
- case WM_MOVE:
- HeadPosX = LOWORD(lParam); //((LPRECT)lParam)->right-((LPRECT)lParam)->left;
- HeadPosY = HIWORD(lParam); //((LPRECT)lParam)->bottom-((LPRECT)lParam)->top;
- return 0;
-
- case DM_SPLITTERMOVED:
- if ((HWND)lParam == GetDlgItem(hDlg, IDC_SPLITTER)) {
- POINT pt;
- pt.x = 0;
- pt.y = wParam;
- ScreenToClient(hDlg, &pt);
- HeadSplitPos = (pt.y * 1000) / HeadSizeY;//+rc.bottom-rc.top;
- if (HeadSplitPos >= 1000) HeadSplitPos = 999;
- else if (HeadSplitPos <= 0) HeadSplitPos = 1;
- else SendMessage(hDlg, WM_SIZE, 0, HeadSizeY << 16 | HeadSizeX);
- }
- return 0;
-
- case WM_SIZE:
- if (wParam == SIZE_RESTORED) {
- HWND hList = GetDlgItem(hDlg, IDC_LISTHEADERS);
- HWND hEdit = GetDlgItem(hDlg, IDC_EDITBODY);
- BOOL isBodyShown = ((PYAMN_MAILSHOWPARAM)(GetWindowLongPtr(hDlg, DWLP_USER)))->mail->Flags & YAMN_MSG_BODYRECEIVED;
- HeadSizeX = LOWORD(lParam); //((LPRECT)lParam)->right-((LPRECT)lParam)->left;
- HeadSizeY = HIWORD(lParam); //((LPRECT)lParam)->bottom-((LPRECT)lParam)->top;
- int localSplitPos = (HeadSplitPos * HeadSizeY) / 1000;
- int localSizeX;
- RECT coord;
- MoveWindow(GetDlgItem(hDlg, IDC_SPLITTER), 5, localSplitPos, HeadSizeX - 10, 2, TRUE);
- MoveWindow(hEdit, 5, localSplitPos + 6, HeadSizeX - 10, HeadSizeY - localSplitPos - 11, TRUE); //where to put text window while resizing
- MoveWindow(hList, 5, 5, HeadSizeX - 10, (isBodyShown ? localSplitPos : HeadSizeY) - 10, TRUE); //where to put headers list window while resizing
- //if (changeX) {
- if (GetClientRect(hList, &coord)) {
- localSizeX = coord.right - coord.left;
- }
- else localSizeX = HeadSizeX;
- LONG iNameWidth = ListView_GetColumnWidth(hList, 0);
- ListView_SetColumnWidth(hList, 1, (localSizeX <= iNameWidth) ? 0 : (localSizeX - iNameWidth));
- //}
- }
- return 0;
-
- case WM_CONTEXTMENU:
- if (GetWindowLongPtr((HWND)wParam, GWLP_ID) == IDC_LISTHEADERS) {
- //MessageBox(0,"LISTHEADERS","Debug",0);
- HWND hList = GetDlgItem(hDlg, IDC_LISTHEADERS);
- POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
- if (pt.x == -1) pt.x = 0;
- if (pt.y == -1) pt.y = 0;
- if (int numRows = ListView_GetItemCount(hList)) {
- HMENU hMenu = CreatePopupMenu();
- AppendMenu(hMenu, MF_STRING, (UINT_PTR)1, TranslateT("Copy Selected"));
- AppendMenu(hMenu, MF_STRING, (UINT_PTR)2, TranslateT("Copy All"));
- AppendMenu(hMenu, MF_SEPARATOR, 0, nullptr);
- AppendMenu(hMenu, MF_STRING, (UINT_PTR)0, TranslateT("Cancel"));
- int nReturnCmd = TrackPopupMenu(hMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hDlg, nullptr);
- DestroyMenu(hMenu);
- if (nReturnCmd > 0) {
- int courRow = 0;
- size_t sizeNeeded = 0;
- wchar_t headname[64] = {0}, headvalue[256] = {0};
- for (courRow = 0; courRow < numRows; courRow++) {
- if ((nReturnCmd == 1) && (ListView_GetItemState(hList, courRow, LVIS_SELECTED) == 0)) continue;
- ListView_GetItemText(hList, courRow, 0, headname, _countof(headname));
- ListView_GetItemText(hList, courRow, 1, headvalue, _countof(headvalue));
- size_t headnamelen = mir_wstrlen(headname);
- if (headnamelen) sizeNeeded += 1 + headnamelen;
- sizeNeeded += 3 + mir_wstrlen(headvalue);
- }
- if (sizeNeeded && OpenClipboard(hDlg)) {
- EmptyClipboard();
- HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE, (sizeNeeded + 1) * sizeof(wchar_t));
- wchar_t *buff = (wchar_t *)GlobalLock(hData);
- int courPos = 0;
- for (courRow = 0; courRow < numRows; courRow++) {
- if ((nReturnCmd == 1) && (ListView_GetItemState(hList, courRow, LVIS_SELECTED) == 0)) continue;
- ListView_GetItemText(hList, courRow, 0, headname, _countof(headname));
- ListView_GetItemText(hList, courRow, 1, headvalue, _countof(headvalue));
- if (mir_wstrlen(headname)) courPos += mir_snwprintf(&buff[courPos], sizeNeeded + 1, L"%s:\t%s\r\n", headname, headvalue);
- else courPos += mir_snwprintf(&buff[courPos], sizeNeeded + 1, L"\t%s\r\n", headvalue);
- }
- GlobalUnlock(hData);
-
- SetClipboardData(CF_UNICODETEXT, hData);
-
- CloseClipboard();
- }
- }
- }
- }
- break; // just in case
- }
- return 0;
-}
-
-void __cdecl ShowEmailThread(void *Param)
-{
- struct MailShowMsgWinParam MyParam = *(struct MailShowMsgWinParam *)Param;
-
- SCIncFcn(MyParam.account->UsingThreads);
-
- if (MyParam.mail->MsgWindow) {
- //if (!BringWindowToTop(MyParam.mail->MsgWindow)) {
- if (!SetForegroundWindow(MyParam.mail->MsgWindow)) {
- SendMessage(MyParam.mail->MsgWindow, WM_DESTROY, 0, 0);
- MyParam.mail->MsgWindow = nullptr;
- goto CREADTEVIEWMESSAGEWINDOW;
- }
-
- if (IsIconic(MyParam.mail->MsgWindow))
- OpenIcon(MyParam.mail->MsgWindow);
- }
- else {
-CREADTEVIEWMESSAGEWINDOW:
- MyParam.mail->MsgWindow = CreateDialogParamW(g_plugin.getInst(), MAKEINTRESOURCEW(IDD_DLGSHOWMESSAGE), nullptr, DlgProcYAMNShowMessage, (LPARAM)&MyParam);
- WindowList_Add(YAMNVar.MessageWnds, MyParam.mail->MsgWindow);
- MSG msg;
- while (GetMessage(&msg, nullptr, 0, 0)) {
- if (MyParam.mail->MsgWindow == nullptr || !IsDialogMessage(MyParam.mail->MsgWindow, &msg)) { /* Wine fix. */
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
- WindowList_Remove(YAMNVar.MessageWnds, MyParam.mail->MsgWindow);
- MyParam.mail->MsgWindow = nullptr;
- }
-
- SCDecFcn(MyParam.account->UsingThreads);
- delete (struct MailShowMsgWinParam *)Param;
-}
-
-INT_PTR CALLBACK DlgProcYAMNMailBrowser(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- CAccount *ActualAccount;
- int Items;
-
- switch (msg) {
- case WM_INITDIALOG:
- {
- struct MailBrowserWinParam *MyParam = (struct MailBrowserWinParam *)lParam;
-
- ListView_SetUnicodeFormat(GetDlgItem(hDlg, IDC_LISTMAILS), TRUE);
- ListView_SetExtendedListViewStyle(GetDlgItem(hDlg, IDC_LISTMAILS), LVS_EX_FULLROWSELECT);
-
- ActualAccount = MyParam->account;
- struct CMailWinUserInfo *mwui = new struct CMailWinUserInfo;
- mwui->Account = ActualAccount;
- mwui->TrayIconState = 0;
- mwui->UpdateMailsMessagesAccess = FALSE;
- mwui->Seen = FALSE;
- mwui->RunFirstTime = TRUE;
-
- SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)mwui);
- if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO)) {
- DestroyWindow(hDlg);
- return FALSE;
- }
-
- SetDlgItemText(hDlg, IDC_BTNAPP, TranslateT("Run application"));
- SetDlgItemText(hDlg, IDC_BTNDEL, TranslateT("Delete selected"));
- SetDlgItemText(hDlg, IDC_BTNCHECKALL, TranslateT("Select All"));
- SetDlgItemText(hDlg, IDC_BTNOK, TranslateT("OK"));
-
- LVCOLUMN lvc0 = {LVCF_FMT | LVCF_TEXT | LVCF_WIDTH, LVCFMT_LEFT, FromWidth, TranslateT("From"), 0, 0};
- LVCOLUMN lvc1 = {LVCF_FMT | LVCF_TEXT | LVCF_WIDTH, LVCFMT_LEFT, SubjectWidth, TranslateT("Subject"), 0, 0};
- LVCOLUMN lvc2 = {LVCF_FMT | LVCF_TEXT | LVCF_WIDTH, LVCFMT_LEFT, SizeWidth, TranslateT("Size"), 0, 0};
- LVCOLUMN lvc3 = {LVCF_FMT | LVCF_TEXT | LVCF_WIDTH, LVCFMT_LEFT, SizeDate, TranslateT("Date"), 0, 0};
- SendDlgItemMessage(hDlg, IDC_LISTMAILS, LVM_INSERTCOLUMN, 0, (LPARAM)&lvc0);
- SendDlgItemMessage(hDlg, IDC_LISTMAILS, LVM_INSERTCOLUMN, 1, (LPARAM)&lvc1);
- SendDlgItemMessage(hDlg, IDC_LISTMAILS, LVM_INSERTCOLUMN, (WPARAM)2, (LPARAM)&lvc2);
- SendDlgItemMessage(hDlg, IDC_LISTMAILS, LVM_INSERTCOLUMN, (WPARAM)3, (LPARAM)&lvc3);
-
- if ((ActualAccount->NewMailN.App != nullptr) && (mir_wstrlen(ActualAccount->NewMailN.App)))
- EnableWindow(GetDlgItem(hDlg, IDC_BTNAPP), TRUE);
- else
- EnableWindow(GetDlgItem(hDlg, IDC_BTNAPP), FALSE);
-
- ReadDoneFcn(ActualAccount->AccountAccessSO);
-
- WindowList_Add(YAMNVar.MessageWnds, hDlg);
- WindowList_Add(YAMNVar.NewMailAccountWnd, hDlg, (UINT_PTR)ActualAccount);
-
- {
- wchar_t accstatus[512];
- GetStatusFcn(ActualAccount, accstatus);
- SetDlgItemText(hDlg, IDC_STSTATUS, accstatus);
- }
- SetTimer(hDlg, TIMER_FLASHING, 500, nullptr);
-
- if (ActualAccount->hContact != NULL)
- g_clistApi.pfnRemoveEvent(ActualAccount->hContact, (LPARAM)"yamn new mail message");
-
- mir_subclassWindow(GetDlgItem(hDlg, IDC_LISTMAILS), ListViewSubclassProc);
- }
- break;
-
- case WM_DESTROY:
- {
- RECT coord;
- LVCOLUMN ColInfo;
- HYAMNMAIL Parser;
-
- Window_FreeIcon_IcoLib(hDlg);
-
- struct CMailWinUserInfo *mwui = (struct CMailWinUserInfo *)GetWindowLongPtr(hDlg, DWLP_USER);
- if (nullptr == (ActualAccount = GetWindowAccount(hDlg)))
- break;
- ColInfo.mask = LVCF_WIDTH;
- if (ListView_GetColumn(GetDlgItem(hDlg, IDC_LISTMAILS), 0, &ColInfo))
- FromWidth = ColInfo.cx;
- if (ListView_GetColumn(GetDlgItem(hDlg, IDC_LISTMAILS), 1, &ColInfo))
- SubjectWidth = ColInfo.cx;
- if (ListView_GetColumn(GetDlgItem(hDlg, IDC_LISTMAILS), 2, &ColInfo))
- SizeWidth = ColInfo.cx;
- if (ListView_GetColumn(GetDlgItem(hDlg, IDC_LISTMAILS), 3, &ColInfo))
- SizeDate = ColInfo.cx;
-
- if (!YAMNVar.Shutdown && GetWindowRect(hDlg, &coord)) //the YAMNVar.Shutdown testing is because M<iranda strange functionality at shutdown phase, when call to DBWriteContactSetting freezes calling thread
- {
- PosX = coord.left;
- SizeX = coord.right - coord.left;
- PosY = coord.top;
- SizeY = coord.bottom - coord.top;
- g_plugin.setDword(YAMN_DBPOSX, PosX);
- g_plugin.setDword(YAMN_DBPOSY, PosY);
- g_plugin.setDword(YAMN_DBSIZEX, SizeX);
- g_plugin.setDword(YAMN_DBSIZEY, SizeY);
- }
- KillTimer(hDlg, TIMER_FLASHING);
-
- WindowList_Remove(YAMNVar.NewMailAccountWnd, hDlg);
- WindowList_Remove(YAMNVar.MessageWnds, hDlg);
-
- if (WAIT_OBJECT_0 != WaitToWriteFcn(ActualAccount->MessagesAccessSO))
- break;
-
- //delete mails from queue, which are deleted from server (spam level 3 mails e.g.)
- for (Parser = (HYAMNMAIL)ActualAccount->Mails; Parser != nullptr; Parser = Parser->Next) {
- if ((Parser->Flags & YAMN_MSG_DELETED) && YAMN_MSG_SPAML(Parser->Flags, YAMN_MSG_SPAML3) && mwui->Seen) //if spaml3 was already deleted and user knows about it
- {
- DeleteMessageFromQueueFcn((HYAMNMAIL *)&ActualAccount->Mails, Parser, 1);
- CallService(MS_YAMN_DELETEACCOUNTMAIL, (WPARAM)ActualAccount->Plugin, (LPARAM)Parser);
- }
- }
-
- //mark mails as read (remove "new" and "unseen" flags)
- if (mwui->Seen)
- SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails, YAMN_MSG_DISPLAY, 0, YAMN_MSG_NEW | YAMN_MSG_UNSEEN, 0);
-
- WriteDoneFcn(ActualAccount->MessagesAccessSO);
-
- NOTIFYICONDATA nid;
- memset(&nid, 0, sizeof(NOTIFYICONDATA));
-
- delete mwui;
- SetWindowLongPtr(hDlg, DWLP_USER, NULL);
-
- nid.cbSize = sizeof(NOTIFYICONDATA);
- nid.hWnd = hDlg;
- nid.uID = 0;
- Shell_NotifyIcon(NIM_DELETE, &nid);
- PostQuitMessage(0);
- }
- break;
-
- case WM_SHOWWINDOW:
- {
- struct CMailWinUserInfo *mwui = (struct CMailWinUserInfo *)GetWindowLongPtr(hDlg, DWLP_USER);
-
- if (mwui == nullptr)
- return 0;
- mwui->Seen = TRUE;
- }
-
- case WM_YAMN_CHANGESTATUS:
- if (nullptr == (ActualAccount = GetWindowAccount(hDlg)))
- break;
-
- if ((CAccount *)wParam != ActualAccount)
- break;
-
- wchar_t accstatus[512];
- GetStatusFcn(ActualAccount, accstatus);
- SetDlgItemText(hDlg, IDC_STSTATUS, accstatus);
- return 1;
-
- case WM_YAMN_CHANGECONTENT:
- {
- struct CUpdateMails UpdateParams;
- BOOL ThisThreadWindow = (GetCurrentThreadId() == GetWindowThreadProcessId(hDlg, nullptr));
-
- if (nullptr == (UpdateParams.Copied = CreateEvent(nullptr, FALSE, FALSE, nullptr))) {
- DestroyWindow(hDlg);
- return 0;
- }
- UpdateParams.Flags = (struct CChangeContent *)lParam;
- UpdateParams.Waiting = !ThisThreadWindow;
-
- if (ThisThreadWindow) {
- if (!UpdateMails(hDlg, (CAccount *)wParam, UpdateParams.Flags->nflags, UpdateParams.Flags->nnflags))
- DestroyWindow(hDlg);
- }
- else if (PostMessage(hDlg, WM_YAMN_UPDATEMAILS, wParam, (LPARAM)&UpdateParams)) //this ensures UpdateMails will execute the thread who created the browser window
- {
- if (!ThisThreadWindow)
- WaitForSingleObject(UpdateParams.Copied, INFINITE);
- }
-
- CloseHandle(UpdateParams.Copied);
- }
- return 1;
- case WM_YAMN_UPDATEMAILS:
- {
- struct CUpdateMails *um = (struct CUpdateMails *)lParam;
- uint32_t nflags, nnflags;
-
- if (nullptr == (ActualAccount = GetWindowAccount(hDlg)))
- return 0;
- if ((CAccount *)wParam != ActualAccount)
- return 0;
-
- nflags = um->Flags->nflags;
- nnflags = um->Flags->nnflags;
-
- if (um->Waiting)
- SetEvent(um->Copied);
-
- if (!UpdateMails(hDlg, ActualAccount, nflags, nnflags))
- DestroyWindow(hDlg);
- }
- return 1;
- case WM_YAMN_STOPACCOUNT:
- if (nullptr == (ActualAccount = GetWindowAccount(hDlg)))
- break;
- if ((CAccount *)wParam != ActualAccount)
- break;
- PostQuitMessage(0);
- return 1;
-
- case WM_YAMN_NOTIFYICON:
- if (nullptr == (ActualAccount = GetWindowAccount(hDlg)))
- break;
-
- switch (lParam) {
- case WM_LBUTTONDBLCLK:
- if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO)) {
- return 0;
- }
-
- if (ActualAccount->AbilityFlags & YAMN_ACC_BROWSE) {
- ShowWindow(hDlg, SW_SHOWNORMAL);
- SetForegroundWindow(hDlg);
- }
- else DestroyWindow(hDlg);
-
- ReadDoneFcn(ActualAccount->AccountAccessSO);
- break;
- }
- break;
-
- case WM_YAMN_SHOWSELECTED:
- {
- int iSelect = SendDlgItemMessage(hDlg, IDC_LISTMAILS, LVM_GETNEXTITEM, -1, MAKELPARAM((UINT)LVNI_FOCUSED, 0)); // return item selected
- if (iSelect != -1) {
- LV_ITEMW item;
-
- item.iItem = iSelect;
- item.iSubItem = 0;
- item.mask = LVIF_PARAM | LVIF_STATE;
- item.stateMask = 0xFFFFFFFF;
- ListView_GetItem(GetDlgItem(hDlg, IDC_LISTMAILS), &item);
- HYAMNMAIL ActualMail = (HYAMNMAIL)item.lParam;
- if (nullptr != ActualMail) {
- PYAMN_MAILSHOWPARAM MailParam = new YAMN_MAILSHOWPARAM;
- MailParam->account = GetWindowAccount(hDlg);
- MailParam->mail = ActualMail;
- mir_forkthread(ShowEmailThread, MailParam);
- }
- }
- }
- break;
-
- case WM_SYSCOMMAND:
- if (nullptr == (ActualAccount = GetWindowAccount(hDlg)))
- break;
- switch (wParam) {
- case SC_CLOSE:
- DestroyWindow(hDlg);
- break;
- }
- break;
-
- case WM_COMMAND:
- if (nullptr == (ActualAccount = GetWindowAccount(hDlg)))
- break;
-
- switch (LOWORD(wParam)) {
- case IDC_BTNCHECKALL:
- ListView_SetItemState(GetDlgItem(hDlg, IDC_LISTMAILS), -1, 0, LVIS_SELECTED); // deselect all items
- ListView_SetItemState(GetDlgItem(hDlg, IDC_LISTMAILS), -1, LVIS_SELECTED, LVIS_SELECTED);
- Items = ListView_GetItemCount(GetDlgItem(hDlg, IDC_LISTMAILS));
- ListView_RedrawItems(GetDlgItem(hDlg, IDC_LISTMAILS), 0, Items);
- UpdateWindow(GetDlgItem(hDlg, IDC_LISTMAILS));
- SetFocus(GetDlgItem(hDlg, IDC_LISTMAILS));
- break;
-
- case IDC_BTNOK:
- DestroyWindow(hDlg);
- break;
-
- case IDC_BTNAPP:
- {
- PROCESS_INFORMATION pi;
- STARTUPINFOW si;
-
- memset(&si, 0, sizeof(si));
- si.cb = sizeof(si);
-
- if (WAIT_OBJECT_0 == WaitToReadFcn(ActualAccount->AccountAccessSO)) {
- if (ActualAccount->NewMailN.App != nullptr) {
- wchar_t *Command;
- if (ActualAccount->NewMailN.AppParam != nullptr)
- Command = new wchar_t[mir_wstrlen(ActualAccount->NewMailN.App) + mir_wstrlen(ActualAccount->NewMailN.AppParam) + 6];
- else
- Command = new wchar_t[mir_wstrlen(ActualAccount->NewMailN.App) + 6];
-
- if (Command != nullptr) {
- mir_wstrcpy(Command, L"\"");
- mir_wstrcat(Command, ActualAccount->NewMailN.App);
- mir_wstrcat(Command, L"\" ");
- if (ActualAccount->NewMailN.AppParam != nullptr)
- mir_wstrcat(Command, ActualAccount->NewMailN.AppParam);
- CreateProcessW(nullptr, Command, nullptr, nullptr, FALSE, NORMAL_PRIORITY_CLASS, nullptr, nullptr, &si, &pi);
- delete[] Command;
- }
- }
-
- ReadDoneFcn(ActualAccount->AccountAccessSO);
- }
-
- if (!(GetKeyState(VK_SHIFT) & 0x8000) && !(GetKeyState(VK_CONTROL) & 0x8000))
- DestroyWindow(hDlg);
- }
- break;
-
- case IDC_BTNDEL:
- {
- HYAMNMAIL ActualMail;
- uint32_t Total = 0;
-
- // we use event to signal, that running thread has all needed stack parameters copied
- HANDLE ThreadRunningEV = CreateEvent(nullptr, FALSE, FALSE, nullptr);
- if (ThreadRunningEV == nullptr)
- break;
-
- Items = ListView_GetItemCount(GetDlgItem(hDlg, IDC_LISTMAILS));
-
- LVITEM item;
- item.stateMask = 0xFFFFFFFF;
-
- if (WAIT_OBJECT_0 == WaitToWriteFcn(ActualAccount->MessagesAccessSO)) {
- for (int i = 0; i < Items; i++) {
- item.iItem = i;
- item.iSubItem = 0;
- item.mask = LVIF_PARAM | LVIF_STATE;
- item.stateMask = 0xFFFFFFFF;
- ListView_GetItem(GetDlgItem(hDlg, IDC_LISTMAILS), &item);
- ActualMail = (HYAMNMAIL)item.lParam;
- if (nullptr == ActualMail)
- break;
- if (item.state & LVIS_SELECTED) {
- ActualMail->Flags |= YAMN_MSG_USERDELETE; //set to mail we are going to delete it
- Total++;
- }
- }
-
- // Enable write-access to mails
- WriteDoneFcn(ActualAccount->MessagesAccessSO);
-
- if (Total) {
- wchar_t DeleteMsg[1024];
-
- mir_snwprintf(DeleteMsg, TranslateT("Do you really want to delete %d selected mails?"), Total);
- if (IDOK == MessageBox(hDlg, DeleteMsg, TranslateT("Delete confirmation"), MB_OKCANCEL | MB_ICONWARNING)) {
- struct DeleteParam ParamToDeleteMails = {YAMN_DELETEVERSION, ThreadRunningEV, ActualAccount, nullptr};
-
- // Find if there's mail marked to delete, which was deleted before
- if (WAIT_OBJECT_0 == WaitToWriteFcn(ActualAccount->MessagesAccessSO)) {
- for (ActualMail = (HYAMNMAIL)ActualAccount->Mails; ActualMail != nullptr; ActualMail = ActualMail->Next) {
- if ((ActualMail->Flags & YAMN_MSG_DELETED) && ((ActualMail->Flags & YAMN_MSG_USERDELETE))) //if selected mail was already deleted
- {
- DeleteMessageFromQueueFcn((HYAMNMAIL *)&ActualAccount->Mails, ActualMail, 1);
- CallService(MS_YAMN_DELETEACCOUNTMAIL, (WPARAM)ActualAccount->Plugin, (LPARAM)ActualMail); //delete it from memory
- continue;
- }
- }
- // Set flag to marked mails that they can be deleted
- SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails, YAMN_MSG_DISPLAY | YAMN_MSG_USERDELETE, 0, YAMN_MSG_DELETEOK, 1);
- // Create new thread which deletes marked mails.
- HANDLE NewThread = mir_forkthread(ActualAccount->Plugin->Fcn->DeleteMailsFcnPtr, &ParamToDeleteMails);
- if (NewThread != nullptr)
- WaitForSingleObject(ThreadRunningEV, INFINITE);
-
- // Enable write-access to mails
- WriteDoneFcn(ActualAccount->MessagesAccessSO);
- }
- }
- else //else mark messages that they are not to be deleted
- SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails, YAMN_MSG_DISPLAY | YAMN_MSG_USERDELETE, 0, YAMN_MSG_USERDELETE, 0);
- }
- }
- CloseHandle(ThreadRunningEV);
- if (g_plugin.getByte(YAMN_CLOSEDELETE, 0))
- DestroyWindow(hDlg);
- }
- break;
- }
- break;
-
- case WM_SIZE:
- if (wParam == SIZE_RESTORED) {
- LONG x = LOWORD(lParam); //((LPRECT)lParam)->right-((LPRECT)lParam)->left;
- LONG y = HIWORD(lParam); //((LPRECT)lParam)->bottom-((LPRECT)lParam)->top;
- MoveWindow(GetDlgItem(hDlg, IDC_BTNDEL), 5, y - 5 - 25, (x - 20) / 3, 25, TRUE); //where to put DELETE button while resizing
- MoveWindow(GetDlgItem(hDlg, IDC_BTNCHECKALL), 10 + (x - 20) / 3, y - 5 - 25, (x - 20) / 6, 25, TRUE); //where to put CHECK ALL button while resizing
- MoveWindow(GetDlgItem(hDlg, IDC_BTNAPP), 15 + (x - 20) / 3 + (x - 20) / 6, y - 5 - 25, (x - 20) / 3, 25, TRUE); //where to put RUN APP button while resizing
- MoveWindow(GetDlgItem(hDlg, IDC_BTNOK), 20 + 2 * (x - 20) / 3 + (x - 20) / 6, y - 5 - 25, (x - 20) / 6, 25, TRUE); //where to put OK button while resizing
- MoveWindow(GetDlgItem(hDlg, IDC_LISTMAILS), 5, 5, x - 10, y - 55, TRUE); //where to put list mail window while resizing
- MoveWindow(GetDlgItem(hDlg, IDC_STSTATUS), 5, y - 5 - 45, x - 10, 15, TRUE); //where to put account status text while resizing
- }
- return 0;
-
- case WM_GETMINMAXINFO:
- ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = MAILBROWSER_MINXSIZE;
- ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = MAILBROWSER_MINYSIZE;
- return 0;
-
- case WM_TIMER:
- {
- NOTIFYICONDATA nid;
- struct CMailWinUserInfo *mwui = (struct CMailWinUserInfo *)GetWindowLongPtr(hDlg, DWLP_USER);
-
- memset(&nid, 0, sizeof(nid));
- nid.cbSize = sizeof(NOTIFYICONDATA);
- nid.hWnd = hDlg;
- nid.uID = 0;
- nid.uFlags = NIF_ICON;
- if (mwui->TrayIconState == 0)
- nid.hIcon = g_plugin.getIcon(IDI_CHECKMAIL);
- else
- nid.hIcon = g_plugin.getIcon(IDI_NEWMAIL);
- Shell_NotifyIcon(NIM_MODIFY, &nid);
- mwui->TrayIconState = !mwui->TrayIconState;
- // UpdateWindow(hDlg);
- }
- break;
-
- case WM_NOTIFY:
- switch (((LPNMHDR)lParam)->idFrom) {
- case IDC_LISTMAILS:
- switch (((LPNMHDR)lParam)->code) {
- case NM_DBLCLK:
- SendMessage(hDlg, WM_YAMN_SHOWSELECTED, 0, 0);
- break;
-
- case LVN_COLUMNCLICK:
- if (nullptr != (ActualAccount = GetWindowAccount(hDlg))) {
- NM_LISTVIEW *pNMListView = (NM_LISTVIEW *)lParam;
- if (WAIT_OBJECT_0 == WaitToReadFcn(ActualAccount->AccountAccessSO)) {
- switch ((int)pNMListView->iSubItem) {
- case 0:
- bFrom = !bFrom;
- break;
- case 1:
- bSub = !bSub;
- break;
- case 2:
- bSize = !bSize;
- break;
- case 3:
- bDate = !bDate;
- break;
- default:
- break;
- }
- ListView_SortItems(pNMListView->hdr.hwndFrom, ListViewCompareProc, pNMListView->iSubItem);
- ReadDoneFcn(ActualAccount->AccountAccessSO);
- }
- }
- break;
-
- case NM_CUSTOMDRAW:
- {
- LPNMLVCUSTOMDRAW cd = (LPNMLVCUSTOMDRAW)lParam;
- LONG_PTR PaintCode;
-
- if (nullptr == (ActualAccount = GetWindowAccount(hDlg)))
- break;
-
- switch (cd->nmcd.dwDrawStage) {
- case CDDS_PREPAINT:
- PaintCode = CDRF_NOTIFYITEMDRAW;
- break;
- case CDDS_ITEMPREPAINT:
- PaintCode = CDRF_NOTIFYSUBITEMDRAW;
- break;
- case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
- {
- BOOL umma;
- {
- struct CMailWinUserInfo *mwui = (struct CMailWinUserInfo *)GetWindowLongPtr(hDlg, DWLP_USER);
- umma = mwui->UpdateMailsMessagesAccess;
- }
- HYAMNMAIL ActualMail = (HYAMNMAIL)cd->nmcd.lItemlParam;
- if (!ActualMail)
- ActualMail = (HYAMNMAIL)readItemLParam(cd->nmcd.hdr.hwndFrom, cd->nmcd.dwItemSpec);
-
- if (!umma)
- if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->MessagesAccessSO))
- return 0;
-
- switch (ActualMail->Flags & YAMN_MSG_SPAMMASK) {
- case YAMN_MSG_SPAML1:
- case YAMN_MSG_SPAML2:
- cd->clrText = RGB(150, 150, 150);
- break;
- case YAMN_MSG_SPAML3:
- cd->clrText = RGB(200, 200, 200);
- cd->clrTextBk = RGB(160, 160, 160);
- break;
- case 0:
- if (cd->nmcd.dwItemSpec & 1)
- cd->clrTextBk = RGB(230, 230, 230);
- break;
- default:
- break;
- }
- if (ActualMail->Flags & YAMN_MSG_UNSEEN)
- cd->clrTextBk = RGB(220, 235, 250);
- PaintCode = CDRF_DODEFAULT;
-
- if (!umma)
- ReadDoneFcn(ActualAccount->MessagesAccessSO);
- break;
- }
- default:
- PaintCode = 0;
- }
- SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PaintCode);
- return 1;
- }
- }
- }
- break;
-
- case WM_CONTEXTMENU:
- if (GetWindowLongPtr((HWND)wParam, GWLP_ID) == IDC_LISTMAILS) {
- //MessageBox(0,"LISTHEADERS","Debug",0);
- HWND hList = GetDlgItem(hDlg, IDC_LISTMAILS);
- POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
- if (pt.x == -1) pt.x = 0;
- if (pt.y == -1) pt.y = 0;
- if (int numRows = ListView_GetItemCount(hList)) {
- HMENU hMenu = CreatePopupMenu();
- AppendMenu(hMenu, MF_STRING, (UINT_PTR)1, TranslateT("Copy Selected"));
- AppendMenu(hMenu, MF_STRING, (UINT_PTR)2, TranslateT("Copy All"));
- AppendMenu(hMenu, MF_SEPARATOR, 0, nullptr);
- AppendMenu(hMenu, MF_STRING, (UINT_PTR)0, TranslateT("Cancel"));
- int nReturnCmd = TrackPopupMenu(hMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hDlg, nullptr);
- DestroyMenu(hMenu);
- if (nReturnCmd > 0) {
- int courRow = 0;
- size_t sizeNeeded = 0;
- wchar_t from[128] = {0}, subject[256] = {0}, size[16] = {0}, date[64] = {0};
- for (courRow = 0; courRow < numRows; courRow++) {
- if ((nReturnCmd == 1) && (ListView_GetItemState(hList, courRow, LVIS_SELECTED) == 0)) continue;
- ListView_GetItemText(hList, courRow, 0, from, _countof(from));
- ListView_GetItemText(hList, courRow, 1, subject, _countof(subject));
- ListView_GetItemText(hList, courRow, 2, size, _countof(size));
- ListView_GetItemText(hList, courRow, 3, date, _countof(date));
- sizeNeeded += 5 + mir_wstrlen(from) + mir_wstrlen(subject) + mir_wstrlen(size) + mir_wstrlen(date);
- }
- if (sizeNeeded && OpenClipboard(hDlg)) {
- EmptyClipboard();
- HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE, (sizeNeeded + 1) * sizeof(wchar_t));
- wchar_t *buff = (wchar_t *)GlobalLock(hData);
- int courPos = 0;
- for (courRow = 0; courRow < numRows; courRow++) {
- if ((nReturnCmd == 1) && (ListView_GetItemState(hList, courRow, LVIS_SELECTED) == 0)) continue;
- ListView_GetItemText(hList, courRow, 0, from, _countof(from));
- ListView_GetItemText(hList, courRow, 1, subject, _countof(subject));
- ListView_GetItemText(hList, courRow, 2, size, _countof(size));
- ListView_GetItemText(hList, courRow, 3, date, _countof(date));
- courPos += mir_snwprintf(&buff[courPos], sizeNeeded + 1, L"%s\t%s\t%s\t%s\r\n", from, subject, size, date);
- }
- GlobalUnlock(hData);
-
- SetClipboardData(CF_UNICODETEXT, hData);
-
- CloseClipboard();
- }
- }
- }
- }
- break; // just in case
- }
- return 0;
-}
-
-LRESULT CALLBACK ListViewSubclassProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- HWND hwndParent = GetParent(hDlg);
-
- switch (msg) {
- case WM_GETDLGCODE:
- {
- LPMSG lpmsg = (LPMSG)lParam;
- if (lpmsg != nullptr) {
- if (lpmsg->message == WM_KEYDOWN
- && lpmsg->wParam == VK_RETURN)
- return DLGC_WANTALLKEYS;
- }
- }
- break;
-
- case WM_KEYDOWN:
- {
- BOOL isCtrl = GetKeyState(VK_CONTROL) & 0x8000;
- BOOL isShift = GetKeyState(VK_SHIFT) & 0x8000;
- BOOL isAlt = GetKeyState(VK_MENU) & 0x8000;
-
- switch (wParam) {
- case 'A': // ctrl-a
- if (!isAlt && !isShift && isCtrl) SendMessage(hwndParent, WM_COMMAND, IDC_BTNCHECKALL, 0);
- break;
- case VK_RETURN:
- case VK_SPACE:
- if (!isAlt && !isShift && !isCtrl) SendMessage(hwndParent, WM_YAMN_SHOWSELECTED, 0, 0);
- break;
- case VK_DELETE:
- SendMessage(hwndParent, WM_COMMAND, IDC_BTNDEL, 0);
- break;
- }
- }
- break;
- }
- return mir_callNextSubclass(hDlg, ListViewSubclassProc, msg, wParam, lParam);
-}
-
-void __cdecl MailBrowser(void *Param)
-{
- MSG msg;
-
- HWND hMailBrowser;
- BOOL WndFound = FALSE;
-
- struct MailBrowserWinParam MyParam = *(struct MailBrowserWinParam *)Param;
- CAccount *ActualAccount = MyParam.account;
- SCIncFcn(ActualAccount->UsingThreads);
-
- // we will not use params in stack anymore
- SetEvent(MyParam.ThreadRunningEV);
-
- __try {
- if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO))
- return;
-
- if (!(ActualAccount->AbilityFlags & YAMN_ACC_BROWSE)) {
- MyParam.nflags = MyParam.nflags & ~YAMN_ACC_MSG;
- MyParam.nnflags = MyParam.nnflags & ~YAMN_ACC_MSG;
- }
-
- if (!(ActualAccount->AbilityFlags & YAMN_ACC_POPUP))
- MyParam.nflags = MyParam.nflags & ~YAMN_ACC_POP;
-
- ReadDoneFcn(ActualAccount->AccountAccessSO);
-
- if (nullptr != (hMailBrowser = WindowList_Find(YAMNVar.NewMailAccountWnd, (UINT_PTR)ActualAccount)))
- WndFound = TRUE;
-
- if ((hMailBrowser == nullptr) && ((MyParam.nflags & YAMN_ACC_MSG) || (MyParam.nflags & YAMN_ACC_ICO) || (MyParam.nnflags & YAMN_ACC_MSG))) {
- hMailBrowser = CreateDialogParamW(g_plugin.getInst(), MAKEINTRESOURCEW(IDD_DLGVIEWMESSAGES), nullptr, DlgProcYAMNMailBrowser, (LPARAM)&MyParam);
- Window_SetIcon_IcoLib(hMailBrowser, g_plugin.getIconHandle(IDI_NEWMAIL));
- MoveWindow(hMailBrowser, PosX, PosY, SizeX, SizeY, TRUE);
- }
-
- if (hMailBrowser != nullptr) {
- struct CChangeContent Params = {MyParam.nflags, MyParam.nnflags}; //if this thread created window, just post message to update mails
-
- SendMessage(hMailBrowser, WM_YAMN_CHANGECONTENT, (WPARAM)ActualAccount, (LPARAM)&Params); //we ensure this will do the thread who created the browser window
- }
- else
- UpdateMails(nullptr, ActualAccount, MyParam.nflags, MyParam.nnflags); //update mails without displaying or refreshing any window
-
- if ((hMailBrowser != nullptr) && !WndFound) { //we process message loop only for thread that created window
- while (GetMessage(&msg, nullptr, 0, 0)) {
- if (hMailBrowser == nullptr || !IsDialogMessage(hMailBrowser, &msg)) { /* Wine fix. */
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
- }
-
- if ((!WndFound) && (ActualAccount->Plugin->Fcn != nullptr) && (ActualAccount->Plugin->Fcn->WriteAccountsFcnPtr != nullptr) && ActualAccount->AbleToWork)
- ActualAccount->Plugin->Fcn->WriteAccountsFcnPtr();
- }
- __finally {
- SCDecFcn(ActualAccount->UsingThreads);
- }
-}
-
-INT_PTR RunMailBrowserSvc(WPARAM wParam, LPARAM lParam)
-{
- PYAMN_MAILBROWSERPARAM Param = (PYAMN_MAILBROWSERPARAM)wParam;
-
- if ((uint32_t)lParam != YAMN_MAILBROWSERVERSION)
- return 0;
-
- //an event for successfull copy parameters to which point a pointer in stack for new thread
- HANDLE ThreadRunningEV = CreateEvent(nullptr, FALSE, FALSE, nullptr);
- Param->ThreadRunningEV = ThreadRunningEV;
-
- HANDLE NewThread = mir_forkthread(MailBrowser, Param);
- if (NewThread != nullptr)
- WaitForSingleObject(ThreadRunningEV, INFINITE);
-
- CloseHandle(ThreadRunningEV);
- return 1;
-}
+/*
+ * This code implements window handling (new mail)
+ *
+ * (c) majvan 2002-2004
+ */
+ /* There can be problems when compiling this file, because in this file
+ * we are using both unicode and no-unicode functions and compiler does not
+ * like it in one file
+ * When you got errors, try to comment the #define <stdio.h> and compile, then
+ * put it back to uncommented and compile again :)
+ */
+
+#include "../stdafx.h"
+
+#define TIMER_FLASHING 0x09061979
+#define MAILBROWSER_MINXSIZE 200 //min size of mail browser window
+#define MAILBROWSER_MINYSIZE 130
+
+#define MAILBROWSERTITLE LPGEN("%s - %d new mail messages, %d total")
+
+void __cdecl ShowEmailThread(void *Param);
+
+//--------------------------------------------------------------------------------------------------
+char *s_MonthNames[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+bool bDate = false, bSub = false, bSize = false, bFrom = false;
+int PosX = 0, PosY = 0, SizeX = 460, SizeY = 100;
+int HeadSizeX = 0x2b2, HeadSizeY = 0x0b5, HeadPosX = 100, HeadPosY = 100;
+int HeadSplitPos = 250; // per-mils of the size
+static int FromWidth = 250, SubjectWidth = 280, SizeWidth = 50, SizeDate = 205;
+unsigned char optDateTime = (SHOWDATELONG | SHOWDATENOTODAY);
+
+struct CMailNumbersSub
+{
+ int Total; //any mail
+ int New; //uses YAMN_MSG_NEW flag
+ int UnSeen; //uses YAMN_MSG_UNSEEN flag
+ // int Browser; //uses YAMN_MSG_BROWSER flag
+ int BrowserUC; //uses YAMN_MSG_BROWSER flag and YAMN_MSG_UNSEEN flag
+ int Display; //uses YAMN_MSG_DISPLAY flag
+ int DisplayTC; //uses YAMN_MSG_DISPLAY flag and YAMN_MSG_DISPLAYC flag
+ int DisplayUC; //uses YAMN_MSG_DISPLAY flag and YAMN_MSG_DISPLAYC flag and YAMN_MSG_UNSEEN flag
+ int Popup; //uses YAMN_MSG_POPUP flag
+ int PopupTC; //uses YAMN_MSG_POPUPC flag
+ int PopupNC; //uses YAMN_MSG_POPUPC flag and YAMN_MSG_NEW flag
+ int PopupRun; //uses YAMN_MSG_POPUP flag and YAMN_MSG_NEW flag
+ int PopupSL2NC; //uses YAMN_MSG_SPAML2 flag and YAMN_MSG_NEW flag
+ int PopupSL3NC; //uses YAMN_MSG_SPAML3 flag and YAMN_MSG_NEW flag
+ // int SysTray; //uses YAMN_MSG_SYSTRAY flag
+ int SysTrayUC; //uses YAMN_MSG_SYSTRAY flag and YAMN_MSG_UNSEEN flag
+ // int Sound; //uses YAMN_MSG_SOUND flag
+ int SoundNC; //uses YAMN_MSG_SOUND flag and YAMN_MSG_NEW flag
+ // int App; //uses YAMN_MSG_APP flag
+ int AppNC; //uses YAMN_MSG_APP flag and YAMN_MSG_NEW flag
+ int EventNC; //uses YAMN_MSG_NEVENT flag and YAMN_MSG_NEW flag
+};
+
+struct CMailNumbers
+{
+ struct CMailNumbersSub Real;
+ struct CMailNumbersSub Virtual;
+};
+
+struct CMailWinUserInfo
+{
+ CAccount *Account;
+ int TrayIconState;
+ BOOL UpdateMailsMessagesAccess;
+ BOOL Seen;
+ BOOL RunFirstTime;
+};
+
+struct CChangeContent
+{
+ uint32_t nflags;
+ uint32_t nnflags;
+};
+
+struct CUpdateMails
+{
+ struct CChangeContent *Flags;
+ BOOL Waiting;
+ HANDLE Copied;
+};
+
+struct CSortList
+{
+ HWND hDlg;
+ int iSubItem;
+};
+
+// Retrieves CAccount *, whose mails are displayed in ListMails
+// hLM- handle of dialog window
+// returns handle of account
+inline CAccount *GetWindowAccount(HWND hDialog);
+
+// Looks to mail flags and increment mail counter (e.g. if mail is new, increments the new mail counter
+// msgq- mail, which increments the counters
+// MN- counnters structure
+void IncrementMailCounters(HYAMNMAIL msgq, struct CMailNumbers *MN);
+
+enum
+{
+ UPDATE_FAIL = 0, //function failed
+ UPDATE_NONE, //none update has been performed
+ UPDATE_OK, //some changes occured, update performed
+};
+
+// Just looks for mail changes in account and update the mail browser window
+// hDlg- dialog handle
+// ActualAccount- account handle
+// nflags- flags what to do when new mail arrives
+// nnflags- flags what to do when no new mail arrives
+// returns one of UPDATE_XXX value(not implemented yet)
+int UpdateMails(HWND hDlg, CAccount *ActualAccount, uint32_t nflags, uint32_t nnflags);
+
+// When new mail occurs, shows window, plays sound, runs application...
+// hDlg- dialog handle. Dialog of mailbrowser is already created and actions are performed over this window
+// ActualAccount- handle of account, whose mails are to be notified
+// MN- statistics of mails in account
+// nflags- what to do or not to do (e.g. to show mailbrowser window or prohibit to show)
+// nflags- flags what to do when new mail arrives
+// nnflags- flags what to do when no new mail arrives
+void DoMailActions(HWND hDlg, CAccount *ActualAccount, struct CMailNumbers *MN, uint32_t nflags, uint32_t nnflags);
+
+// Looks for items in mailbrowser and if they were deleted, delete them from browser window
+// hListView- handle of listview window
+// ActualAccount- handle of account, whose mails are show
+// MailNumbers- pointer to structure, in which function stores numbers of mails with some property
+// returns one of UPDATE_XXX value (not implemented yet)
+int ChangeExistingMailStatus(HWND hListView, CAccount *ActualAccount);
+
+// Adds new mails to ListView and if any new, shows multi popup (every new message is new popup window created by popup plugin)
+// hListView- handle of listview window
+// ActualAccount- handle of account, whose mails are show
+// NewMailPopup- pointer to prepared structure for popup plugin, can be NULL if no popup show
+// MailNumbers- pointer to structure, in which function stores numbers of mails with some property
+// nflags- flags what to do when new mail arrives
+// returns one of UPDATE_XXX value (not implemented yet)
+int AddNewMailsToListView(HWND hListView, CAccount *ActualAccount, uint32_t nflags);
+
+// Window callback procedure for popup window (created by popup plugin)
+LRESULT CALLBACK NewMailPopupProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+// Window callback procedure for popup window (created by popup plugin)
+LRESULT CALLBACK NoNewMailPopupProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+// Dialog callback procedure for mail browser
+INT_PTR CALLBACK DlgProcYAMNMailBrowser(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+// MailBrowser thread function creates window if needed, tray icon and plays sound
+void __cdecl MailBrowser(void *Param);
+
+LRESULT CALLBACK ListViewSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+// Runs mail browser in new thread
+INT_PTR RunMailBrowserSvc(WPARAM, LPARAM);
+
+#define YAMN_BROWSER_SHOWPOPUP 0x01
+
+// list view items' order criteria
+#define LVORDER_NOORDER -1
+#define LVORDER_STRING 0
+#define LVORDER_NUMERIC 1
+#define LVORDER_DATETIME 2
+
+// list view order direction
+#define LVORDER_ASCENDING 1
+#define LVORDER_NONE 0
+#define LVORDER_DESCENDING -1
+
+// list view sort type
+#define LVSORTPRIORITY_NONE -1
+
+// List view column info.
+typedef struct _SAMPLELISTVIEWCOLUMN
+{
+ UINT uCXCol; // index
+ int nSortType; // sorting type (STRING = 0, NUMERIC, DATE, DATETIME)
+ int nSortOrder; // sorting order (ASCENDING = -1, NONE, DESCENDING)
+ int nPriority; // sort priority (-1 for none, 0, 1, ..., nColumns - 1 maximum)
+ wchar_t lpszName[128]; // column name
+} SAMPLELISTVIEWCOLUMN;
+
+// Compare priority
+typedef struct _LVCOMPAREINFO
+{
+ int iIdx; // Index
+ int iPriority; // Priority
+} LVCOMPAREINFO, *LPLVCOMPAREINFO;
+
+//--------------------------------------------------------------------------------------------------
+
+LPARAM readItemLParam(HWND hwnd, uint32_t iItem)
+{
+ LVITEM item;
+ item.mask = LVIF_PARAM;
+ item.iItem = iItem;
+ item.iSubItem = 0;
+ SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
+ return item.lParam;
+}
+
+inline CAccount *GetWindowAccount(HWND hDlg)
+{
+ struct CMailWinUserInfo *mwui = (struct CMailWinUserInfo *)GetWindowLongPtr(hDlg, DWLP_USER);
+
+ return (mwui == nullptr) ? nullptr : mwui->Account;
+}
+
+void IncrementMailCounters(HYAMNMAIL msgq, struct CMailNumbers *MN)
+{
+ if (msgq->Flags & YAMN_MSG_VIRTUAL)
+ MN->Virtual.Total++;
+ else
+ MN->Real.Total++;
+
+ if (msgq->Flags & YAMN_MSG_NEW)
+ if (msgq->Flags & YAMN_MSG_VIRTUAL)
+ MN->Virtual.New++;
+ else
+ MN->Real.New++;
+ if (msgq->Flags & YAMN_MSG_UNSEEN)
+ if (msgq->Flags & YAMN_MSG_VIRTUAL)
+ MN->Virtual.UnSeen++;
+ else
+ MN->Real.UnSeen++;
+ if ((msgq->Flags & (YAMN_MSG_UNSEEN | YAMN_MSG_BROWSER)) == (YAMN_MSG_UNSEEN | YAMN_MSG_BROWSER))
+ if (msgq->Flags & YAMN_MSG_VIRTUAL)
+ MN->Virtual.BrowserUC++;
+ else
+ MN->Real.BrowserUC++;
+ if (msgq->Flags & YAMN_MSG_DISPLAY)
+ if (msgq->Flags & YAMN_MSG_VIRTUAL)
+ MN->Virtual.Display++;
+ else
+ MN->Real.Display++;
+ if ((msgq->Flags & (YAMN_MSG_DISPLAYC | YAMN_MSG_DISPLAY)) == (YAMN_MSG_DISPLAYC | YAMN_MSG_DISPLAY))
+ if (msgq->Flags & YAMN_MSG_VIRTUAL)
+ MN->Virtual.DisplayTC++;
+ else
+ MN->Real.DisplayTC++;
+ if ((msgq->Flags & (YAMN_MSG_UNSEEN | YAMN_MSG_DISPLAYC | YAMN_MSG_DISPLAY)) == (YAMN_MSG_UNSEEN | YAMN_MSG_DISPLAYC | YAMN_MSG_DISPLAY))
+ if (msgq->Flags & YAMN_MSG_VIRTUAL)
+ MN->Virtual.DisplayUC++;
+ else
+ MN->Real.DisplayUC++;
+ if (msgq->Flags & YAMN_MSG_POPUP)
+ if (msgq->Flags & YAMN_MSG_VIRTUAL)
+ MN->Virtual.Popup++;
+ else
+ MN->Real.Popup++;
+ if ((msgq->Flags & YAMN_MSG_POPUPC) == YAMN_MSG_POPUPC)
+ if (msgq->Flags & YAMN_MSG_VIRTUAL)
+ MN->Virtual.PopupTC++;
+ else
+ MN->Real.PopupTC++;
+ if ((msgq->Flags & (YAMN_MSG_NEW | YAMN_MSG_POPUPC)) == (YAMN_MSG_NEW | YAMN_MSG_POPUPC))
+ if (msgq->Flags & YAMN_MSG_VIRTUAL)
+ MN->Virtual.PopupNC++;
+ else
+ MN->Real.PopupNC++;
+ if ((msgq->Flags & (YAMN_MSG_NEW | YAMN_MSG_POPUP)) == (YAMN_MSG_NEW | YAMN_MSG_POPUP))
+ if (msgq->Flags & YAMN_MSG_VIRTUAL)
+ MN->Virtual.PopupRun++;
+ else
+ MN->Real.PopupRun++;
+ if ((msgq->Flags & YAMN_MSG_NEW) && YAMN_MSG_SPAML(msgq->Flags, YAMN_MSG_SPAML2))
+ if (msgq->Flags & YAMN_MSG_VIRTUAL)
+ MN->Virtual.PopupSL2NC++;
+ else
+ MN->Real.PopupSL2NC++;
+ if ((msgq->Flags & YAMN_MSG_NEW) && YAMN_MSG_SPAML(msgq->Flags, YAMN_MSG_SPAML3))
+ if (msgq->Flags & YAMN_MSG_VIRTUAL)
+ MN->Virtual.PopupSL3NC++;
+ else
+ MN->Real.PopupSL3NC++;
+ /* if (msgq->MailData->Flags & YAMN_MSG_SYSTRAY)
+ if (msgq->Flags & YAMN_MSG_VIRTUAL)
+ MN->Virtual.SysTray++;
+ else
+ MN->Real.SysTray++;
+ */ if ((msgq->Flags & (YAMN_MSG_UNSEEN | YAMN_MSG_SYSTRAY)) == (YAMN_MSG_UNSEEN | YAMN_MSG_SYSTRAY))
+ if (msgq->Flags & YAMN_MSG_VIRTUAL)
+ MN->Virtual.SysTrayUC++;
+ else
+ MN->Real.SysTrayUC++;
+ /* if (msgq->MailData->Flags & YAMN_MSG_SOUND)
+ if (msgq->Flags & YAMN_MSG_VIRTUAL)
+ MN->Virtual.Sound++;
+ else
+ MN->Real.Sound++;
+ */ if ((msgq->Flags & (YAMN_MSG_NEW | YAMN_MSG_SOUND)) == (YAMN_MSG_NEW | YAMN_MSG_SOUND))
+ if (msgq->Flags & YAMN_MSG_VIRTUAL)
+ MN->Virtual.SoundNC++;
+ else
+ MN->Real.SoundNC++;
+ /* if (msgq->MailData->Flags & YAMN_MSG_APP)
+ if (msgq->Flags & YAMN_MSG_VIRTUAL)
+ MN->Virtual.App++;
+ else
+ MN->Real.App++;
+ */ if ((msgq->Flags & (YAMN_MSG_NEW | YAMN_MSG_APP)) == (YAMN_MSG_NEW | YAMN_MSG_APP))
+ if (msgq->Flags & YAMN_MSG_VIRTUAL)
+ MN->Virtual.AppNC++;
+ else
+ MN->Real.AppNC++;
+ if ((msgq->Flags & (YAMN_MSG_NEW | YAMN_MSG_NEVENT)) == (YAMN_MSG_NEW | YAMN_MSG_NEVENT))
+ if (msgq->Flags & YAMN_MSG_VIRTUAL)
+ MN->Virtual.EventNC++;
+ else
+ MN->Real.EventNC++;
+}
+
+int UpdateMails(HWND hDlg, CAccount *ActualAccount, uint32_t nflags, uint32_t nnflags)
+{
+ struct CMailNumbers MN;
+
+ BOOL Loaded;
+ BOOL RunMailBrowser, RunPopups;
+
+ struct CMailWinUserInfo *mwui = (struct CMailWinUserInfo *)GetWindowLongPtr(hDlg, DWLP_USER);
+ //now we ensure read access for account and write access for its mails
+ if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO)) {
+ PostMessage(hDlg, WM_DESTROY, 0, 0);
+ return UPDATE_FAIL;
+ }
+
+ if (WAIT_OBJECT_0 != WaitToWriteFcn(ActualAccount->MessagesAccessSO)) {
+ ReadDoneFcn(ActualAccount->AccountAccessSO);
+ PostMessage(hDlg, WM_DESTROY, 0, 0);
+ return UPDATE_FAIL;
+ }
+
+ memset(&MN, 0, sizeof(MN));
+
+ for (HYAMNMAIL msgq = (HYAMNMAIL)ActualAccount->Mails; msgq != nullptr; msgq = msgq->Next) {
+ if (!LoadedMailData(msgq)) //check if mail is already in memory
+ {
+ Loaded = false;
+ if (nullptr == LoadMailData(msgq)) //if we could not load mail to memory, consider this mail deleted and do not display it
+ continue;
+ }
+ else
+ Loaded = true;
+
+ IncrementMailCounters(msgq, &MN);
+
+ if (!Loaded)
+ UnloadMailData(msgq); //do not keep data for mail in memory
+ }
+
+ if (mwui != nullptr)
+ mwui->UpdateMailsMessagesAccess = TRUE;
+
+ //Now we are going to check if extracting data from mail headers are needed.
+ //If popups will be displayed or mailbrowser window
+ if ((((mwui != nullptr) && !(mwui->RunFirstTime)) &&
+ (
+ ((nnflags & YAMN_ACC_MSGP) && !(MN.Real.BrowserUC + MN.Virtual.BrowserUC)) ||
+ ((nflags & YAMN_ACC_MSGP) && (MN.Real.BrowserUC + MN.Virtual.BrowserUC))
+ )
+ ) || //if mail window was displayed before and flag YAMN_ACC_MSGP is set
+ ((nnflags & YAMN_ACC_MSG) && !(MN.Real.BrowserUC + MN.Virtual.BrowserUC)) || //if needed to run mailbrowser when no unseen and no unseen mail found
+ ((nflags & YAMN_ACC_MSG) && (MN.Real.BrowserUC + MN.Virtual.BrowserUC)) || //if unseen mails found, we sure run mailbrowser
+ ((nflags & YAMN_ACC_ICO) && (MN.Real.SysTrayUC + MN.Virtual.SysTrayUC))
+ ) //if needed to run systray
+ RunMailBrowser = TRUE;
+ else
+ RunMailBrowser = FALSE;
+
+ // if some popups with mails are needed to show
+ if ((nflags & YAMN_ACC_POP) && (ActualAccount->Flags & YAMN_ACC_POPN) && (MN.Real.PopupNC + MN.Virtual.PopupNC))
+ RunPopups = TRUE;
+ else RunPopups = FALSE;
+
+ if (RunMailBrowser)
+ ChangeExistingMailStatus(GetDlgItem(hDlg, IDC_LISTMAILS), ActualAccount);
+ if (RunMailBrowser || RunPopups)
+ AddNewMailsToListView(hDlg == nullptr ? nullptr : GetDlgItem(hDlg, IDC_LISTMAILS), ActualAccount, nflags);
+
+ if (RunMailBrowser) {
+ size_t len = mir_strlen(ActualAccount->Name) + mir_strlen(Translate(MAILBROWSERTITLE)) + 10; //+10 chars for numbers
+ char *TitleStrA = new char[len];
+ wchar_t *TitleStrW = new wchar_t[len];
+
+ mir_snprintf(TitleStrA, len, Translate(MAILBROWSERTITLE), ActualAccount->Name, MN.Real.DisplayUC + MN.Virtual.DisplayUC, MN.Real.Display + MN.Virtual.Display);
+ MultiByteToWideChar(CP_ACP, MB_USEGLYPHCHARS, TitleStrA, -1, TitleStrW, (int)mir_strlen(TitleStrA) + 1);
+ SetWindowTextW(hDlg, TitleStrW);
+ delete[] TitleStrA;
+ delete[] TitleStrW;
+ }
+
+ DoMailActions(hDlg, ActualAccount, &MN, nflags, nnflags);
+
+ SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails, YAMN_MSG_NEW, 0, YAMN_MSG_NEW, YAMN_FLAG_REMOVE); //rempve the new flag
+ if (!RunMailBrowser)
+ SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails, YAMN_MSG_UNSEEN, YAMN_MSG_STAYUNSEEN, YAMN_MSG_UNSEEN, YAMN_FLAG_REMOVE); //remove the unseen flag when it was not displayed and it has not "stay unseen" flag set
+
+ if (mwui != nullptr) {
+ mwui->UpdateMailsMessagesAccess = FALSE;
+ mwui->RunFirstTime = FALSE;
+ }
+
+ WriteDoneFcn(ActualAccount->MessagesAccessSO);
+ ReadDoneFcn(ActualAccount->AccountAccessSO);
+
+ if (RunMailBrowser)
+ UpdateWindow(GetDlgItem(hDlg, IDC_LISTMAILS));
+ else if (hDlg != nullptr)
+ DestroyWindow(hDlg);
+
+ return 1;
+}
+
+int ChangeExistingMailStatus(HWND hListView, CAccount *ActualAccount)
+{
+ LVITEM item;
+ HYAMNMAIL mail, msgq;
+
+ int in = ListView_GetItemCount(hListView);
+ item.mask = LVIF_PARAM;
+
+ for (int i = 0; i < in; i++) {
+ item.iItem = i;
+ item.iSubItem = 0;
+ if (TRUE == ListView_GetItem(hListView, &item))
+ mail = (HYAMNMAIL)item.lParam;
+ else
+ continue;
+ for (msgq = (HYAMNMAIL)ActualAccount->Mails; (msgq != nullptr) && (msgq != mail); msgq = msgq->Next); //found the same mail in account queue
+ if (msgq == nullptr) //if mail was not found
+ if (TRUE == ListView_DeleteItem(hListView, i)) {
+ in--; i--;
+ continue;
+ }
+ }
+
+ return TRUE;
+}
+
+void MimeDateToLocalizedDateTime(char *datein, wchar_t *dateout, int lendateout);
+int AddNewMailsToListView(HWND hListView, CAccount *ActualAccount, uint32_t nflags)
+{
+ wchar_t *FromStr;
+ wchar_t SizeStr[20];
+ wchar_t LocalDateStr[128];
+
+ LVITEMW item;
+ LVFINDINFO fi;
+
+ int foundi = 0, lfoundi = 0;
+ struct CHeader UnicodeHeader;
+ BOOL Loaded, Extracted, FromStrNew = FALSE;
+
+ memset(&item, 0, sizeof(item));
+ memset(&UnicodeHeader, 0, sizeof(UnicodeHeader));
+
+ if (hListView != nullptr) {
+ item.mask = LVIF_TEXT | LVIF_PARAM;
+ item.iItem = 0;
+ memset(&fi, 0, sizeof(fi));
+ fi.flags = LVFI_PARAM; //let's go search item by lParam number
+ lfoundi = 0;
+ }
+
+ POPUPDATAW NewMailPopup = {};
+ NewMailPopup.lchContact = (ActualAccount->hContact != NULL) ? ActualAccount->hContact : (UINT_PTR)ActualAccount;
+ NewMailPopup.lchIcon = g_plugin.getIcon(IDI_NEWMAIL);
+ if (nflags & YAMN_ACC_POPC) {
+ NewMailPopup.colorBack = ActualAccount->NewMailN.PopupB;
+ NewMailPopup.colorText = ActualAccount->NewMailN.PopupT;
+ }
+ else {
+ NewMailPopup.colorBack = GetSysColor(COLOR_BTNFACE);
+ NewMailPopup.colorText = GetSysColor(COLOR_WINDOWTEXT);
+ }
+ NewMailPopup.iSeconds = ActualAccount->NewMailN.PopupTime;
+
+ NewMailPopup.PluginWindowProc = NewMailPopupProc;
+ NewMailPopup.PluginData = nullptr; //it's new mail popup
+
+ for (HYAMNMAIL msgq = (HYAMNMAIL)ActualAccount->Mails; msgq != nullptr; msgq = msgq->Next, lfoundi++) {
+ // now we hide mail pointer to item's lParam member. We can later use it to retrieve mail datas
+
+ Extracted = FALSE; FromStr = nullptr; FromStrNew = FALSE;
+
+ if (hListView != nullptr) {
+ fi.lParam = (LPARAM)msgq;
+ if (-1 != (foundi = ListView_FindItem(hListView, -1, &fi))) { // if mail is already in window
+ lfoundi = foundi;
+ continue; // do not insert any item
+ }
+
+ item.iItem = lfoundi; // insert after last found item
+ item.lParam = (LPARAM)msgq;
+ }
+
+ if (!LoadedMailData(msgq)) { // check if mail is already in memory
+ Loaded = false;
+ if (nullptr == LoadMailData(msgq)) //if we could not load mail to memory, consider this mail deleted and do not display it
+ continue;
+ }
+ else Loaded = true;
+
+ if (((hListView != nullptr) && (msgq->Flags & YAMN_MSG_DISPLAY)) ||
+ ((nflags & YAMN_ACC_POP) && (ActualAccount->Flags & YAMN_ACC_POPN) && (msgq->Flags & YAMN_MSG_POPUP) && (msgq->Flags & YAMN_MSG_NEW))) {
+
+ if (!Extracted) ExtractHeader(msgq->MailData->TranslatedHeader, msgq->MailData->CP, &UnicodeHeader);
+ Extracted = TRUE;
+
+ if ((UnicodeHeader.From != nullptr) && (UnicodeHeader.FromNick != nullptr)) {
+ size_t size = mir_wstrlen(UnicodeHeader.From) + mir_wstrlen(UnicodeHeader.FromNick) + 4;
+ FromStr = new wchar_t[size];
+ mir_snwprintf(FromStr, size, L"%s <%s>", UnicodeHeader.FromNick, UnicodeHeader.From);
+ FromStrNew = TRUE;
+ }
+ else if (UnicodeHeader.From != nullptr)
+ FromStr = UnicodeHeader.From;
+ else if (UnicodeHeader.FromNick != nullptr)
+ FromStr = UnicodeHeader.FromNick;
+ else if (UnicodeHeader.ReturnPath != nullptr)
+ FromStr = UnicodeHeader.ReturnPath;
+
+ if (nullptr == FromStr) {
+ FromStr = L"";
+ FromStrNew = FALSE;
+ }
+ }
+
+ if ((hListView != nullptr) && (msgq->Flags & YAMN_MSG_DISPLAY)) {
+ item.iSubItem = 0;
+ item.pszText = FromStr;
+ item.iItem = SendMessage(hListView, LVM_INSERTITEM, 0, (LPARAM)&item);
+
+ item.iSubItem = 1;
+ item.pszText = (nullptr != UnicodeHeader.Subject ? UnicodeHeader.Subject : (wchar_t *)L"");
+ SendMessage(hListView, LVM_SETITEMTEXT, (WPARAM)item.iItem, (LPARAM)&item);
+
+ item.iSubItem = 2;
+ mir_snwprintf(SizeStr, L"%d kB", msgq->MailData->Size / 1024);
+ item.pszText = SizeStr;
+ SendMessage(hListView, LVM_SETITEMTEXT, (WPARAM)item.iItem, (LPARAM)&item);
+
+ item.iSubItem = 3;
+ item.pszText = L"";
+
+ for (CMimeItem *heads = msgq->MailData->TranslatedHeader; heads != nullptr; heads = heads->Next) {
+ if (!_stricmp(heads->name, "Date")) {
+ MimeDateToLocalizedDateTime(heads->value, LocalDateStr, 128);
+ item.pszText = LocalDateStr;
+ break;
+ }
+ }
+ SendMessage(hListView, LVM_SETITEMTEXT, (WPARAM)item.iItem, (LPARAM)&item);
+ }
+
+ if ((nflags & YAMN_ACC_POP) && (ActualAccount->Flags & YAMN_ACC_POPN) && (msgq->Flags & YAMN_MSG_POPUP) && (msgq->Flags & YAMN_MSG_NEW)) {
+ mir_wstrncpy(NewMailPopup.lpwzContactName, FromStr, _countof(NewMailPopup.lpwzContactName));
+ mir_wstrncpy(NewMailPopup.lpwzText, UnicodeHeader.Subject, _countof(NewMailPopup.lpwzText));
+
+ PYAMN_MAILSHOWPARAM MailParam = (PYAMN_MAILSHOWPARAM)malloc(sizeof(YAMN_MAILSHOWPARAM));
+ if (MailParam) {
+ MailParam->account = ActualAccount;
+ MailParam->mail = msgq;
+ MailParam->ThreadRunningEV = nullptr;
+ NewMailPopup.PluginData = MailParam;
+ PUAddPopupW(&NewMailPopup);
+ }
+ }
+
+ if ((msgq->Flags & YAMN_MSG_UNSEEN) && (ActualAccount->NewMailN.Flags & YAMN_ACC_KBN))
+ CallService(MS_KBDNOTIFY_EVENTSOPENED, 1, NULL);
+
+ if (FromStrNew)
+ delete[] FromStr;
+
+ if (Extracted) {
+ DeleteHeaderContent(&UnicodeHeader);
+ memset(&UnicodeHeader, 0, sizeof(UnicodeHeader));
+ }
+
+ if (!Loaded) {
+ SaveMailData(msgq);
+ UnloadMailData(msgq); //do not keep data for mail in memory
+ }
+ }
+
+ return TRUE;
+}
+
+void DoMailActions(HWND hDlg, CAccount *ActualAccount, struct CMailNumbers *MN, uint32_t nflags, uint32_t nnflags)
+{
+ NOTIFYICONDATA nid = {};
+ nid.cbSize = sizeof(nid);
+ nid.hWnd = hDlg;
+
+ if (MN->Real.EventNC + MN->Virtual.EventNC)
+ NotifyEventHooks(hNewMailHook, 0, 0);
+
+ if ((nflags & YAMN_ACC_KBN) && (MN->Real.PopupRun + MN->Virtual.PopupRun))
+ CallService(MS_KBDNOTIFY_STARTBLINK, (WPARAM)MN->Real.PopupNC + MN->Virtual.PopupNC, NULL);
+
+ if ((nflags & YAMN_ACC_CONT) && (MN->Real.PopupRun + MN->Virtual.PopupRun)) {
+ wchar_t tszMsg[250];
+ mir_snwprintf(tszMsg, TranslateT("%s : %d new mail message(s), %d total"), _A2T(ActualAccount->Name).get(), MN->Real.PopupNC + MN->Virtual.PopupNC, MN->Real.PopupTC + MN->Virtual.PopupTC);
+
+ if (!(nflags & YAMN_ACC_CONTNOEVENT)) {
+ CLISTEVENT evt = {};
+ evt.flags = CLEF_UNICODE;
+ evt.hContact = ActualAccount->hContact;
+ evt.hIcon = g_plugin.getIcon(IDI_NEWMAIL);
+ evt.hDbEvent = ActualAccount->hContact;
+ evt.lParam = ActualAccount->hContact;
+ evt.pszService = MS_YAMN_CLISTDBLCLICK;
+ evt.szTooltip.w = tszMsg;
+ g_clistApi.pfnAddEvent(&evt);
+ }
+ db_set_ws(ActualAccount->hContact, "CList", "StatusMsg", tszMsg);
+
+ if (nflags & YAMN_ACC_CONTNICK)
+ g_plugin.setWString(ActualAccount->hContact, "Nick", tszMsg);
+ }
+
+ if ((nflags & YAMN_ACC_POP) &&
+ !(ActualAccount->Flags & YAMN_ACC_POPN) &&
+ (MN->Real.PopupRun + MN->Virtual.PopupRun)) {
+ POPUPDATAW NewMailPopup;
+
+ NewMailPopup.lchContact = (ActualAccount->hContact != NULL) ? ActualAccount->hContact : (UINT_PTR)ActualAccount;
+ NewMailPopup.lchIcon = g_plugin.getIcon(IDI_NEWMAIL);
+ if (nflags & YAMN_ACC_POPC) {
+ NewMailPopup.colorBack = ActualAccount->NewMailN.PopupB;
+ NewMailPopup.colorText = ActualAccount->NewMailN.PopupT;
+ }
+ else {
+ NewMailPopup.colorBack = GetSysColor(COLOR_BTNFACE);
+ NewMailPopup.colorText = GetSysColor(COLOR_WINDOWTEXT);
+ }
+ NewMailPopup.iSeconds = ActualAccount->NewMailN.PopupTime;
+
+ NewMailPopup.PluginWindowProc = NewMailPopupProc;
+ NewMailPopup.PluginData = (void *)nullptr; //multiple popups
+
+ mir_wstrncpy(NewMailPopup.lpwzContactName, _A2T(ActualAccount->Name), _countof(NewMailPopup.lpwzContactName));
+ mir_snwprintf(NewMailPopup.lpwzText, TranslateT("%d new mail message(s), %d total"), MN->Real.PopupNC + MN->Virtual.PopupNC, MN->Real.PopupTC + MN->Virtual.PopupTC);
+ PUAddPopupW(&NewMailPopup);
+ }
+
+ // destroy tray icon if no new mail
+ if ((MN->Real.SysTrayUC + MN->Virtual.SysTrayUC == 0) && (hDlg != nullptr))
+ Shell_NotifyIcon(NIM_DELETE, &nid);
+
+ // and remove the event
+ if ((nflags & YAMN_ACC_CONT) && (!(nflags & YAMN_ACC_CONTNOEVENT)) && (MN->Real.UnSeen + MN->Virtual.UnSeen == 0))
+ g_clistApi.pfnRemoveEvent(ActualAccount->hContact, ActualAccount->hContact);
+
+ if ((MN->Real.BrowserUC + MN->Virtual.BrowserUC == 0) && (hDlg != nullptr)) {
+ if (!IsWindowVisible(hDlg) && !(nflags & YAMN_ACC_MSG))
+ PostMessage(hDlg, WM_DESTROY, 0, 0); //destroy window if no new mail and window is not visible
+ if (nnflags & YAMN_ACC_MSG) //if no new mail and msg should be executed
+ {
+ SetForegroundWindow(hDlg);
+ ShowWindow(hDlg, SW_SHOWNORMAL);
+ }
+ }
+ else
+ if (hDlg != nullptr) //else insert icon and set window if new mails
+ {
+ SendDlgItemMessageW(hDlg, IDC_LISTMAILS, LVM_SCROLL, 0, (LPARAM)0x7ffffff);
+
+ if ((nflags & YAMN_ACC_ICO) && (MN->Real.SysTrayUC + MN->Virtual.SysTrayUC)) {
+ nid.hIcon = g_plugin.getIcon(IDI_NEWMAIL);
+ nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
+ nid.uCallbackMessage = WM_YAMN_NOTIFYICON;
+ mir_snwprintf(nid.szTip, L"%S %s", ActualAccount->Name, TranslateT("- new mail message(s)"));
+ Shell_NotifyIcon(NIM_ADD, &nid);
+ SetTimer(hDlg, TIMER_FLASHING, 500, nullptr);
+ }
+ if (nflags & YAMN_ACC_MSG) //if no new mail and msg should be executed
+ ShowWindow(hDlg, SW_SHOWNORMAL);
+ }
+
+ if (MN->Real.AppNC + MN->Virtual.AppNC != 0) {
+ if (nflags & YAMN_ACC_APP) {
+ PROCESS_INFORMATION pi;
+ STARTUPINFOW si;
+ memset(&si, 0, sizeof(si));
+ si.cb = sizeof(si);
+
+ if (ActualAccount->NewMailN.App != nullptr) {
+ wchar_t *Command;
+ if (ActualAccount->NewMailN.AppParam != nullptr)
+ Command = new wchar_t[mir_wstrlen(ActualAccount->NewMailN.App) + mir_wstrlen(ActualAccount->NewMailN.AppParam) + 6];
+ else
+ Command = new wchar_t[mir_wstrlen(ActualAccount->NewMailN.App) + 6];
+
+ if (Command != nullptr) {
+ mir_wstrcpy(Command, L"\"");
+ mir_wstrcat(Command, ActualAccount->NewMailN.App);
+ mir_wstrcat(Command, L"\" ");
+ if (ActualAccount->NewMailN.AppParam != nullptr)
+ mir_wstrcat(Command, ActualAccount->NewMailN.AppParam);
+ CreateProcessW(nullptr, Command, nullptr, nullptr, FALSE, NORMAL_PRIORITY_CLASS, nullptr, nullptr, &si, &pi);
+ delete[] Command;
+ }
+ }
+ }
+ }
+
+ if (MN->Real.SoundNC + MN->Virtual.SoundNC != 0)
+ if (nflags & YAMN_ACC_SND)
+ Skin_PlaySound(YAMN_NEWMAILSOUND);
+
+ if ((nnflags & YAMN_ACC_POP) && (MN->Real.PopupRun + MN->Virtual.PopupRun == 0)) {
+ POPUPDATAW NoNewMailPopup = {};
+
+ NoNewMailPopup.lchContact = (ActualAccount->hContact != NULL) ? ActualAccount->hContact : (UINT_PTR)ActualAccount;
+ NoNewMailPopup.lchIcon = g_plugin.getIcon(IDI_LAUNCHAPP);
+ if (nflags & YAMN_ACC_POPC) {
+ NoNewMailPopup.colorBack = ActualAccount->NoNewMailN.PopupB;
+ NoNewMailPopup.colorText = ActualAccount->NoNewMailN.PopupT;
+ }
+ else {
+ NoNewMailPopup.colorBack = GetSysColor(COLOR_BTNFACE);
+ NoNewMailPopup.colorText = GetSysColor(COLOR_WINDOWTEXT);
+ }
+ NoNewMailPopup.iSeconds = ActualAccount->NoNewMailN.PopupTime;
+
+ NoNewMailPopup.PluginWindowProc = NoNewMailPopupProc;
+ NoNewMailPopup.PluginData = nullptr; //it's not new mail popup
+
+ mir_wstrncpy(NoNewMailPopup.lpwzContactName, _A2T(ActualAccount->Name), _countof(NoNewMailPopup.lpwzContactName));
+ if (MN->Real.PopupSL2NC + MN->Virtual.PopupSL2NC)
+ mir_snwprintf(NoNewMailPopup.lpwzText, TranslateT("No new mail message, %d spam(s)"), MN->Real.PopupSL2NC + MN->Virtual.PopupSL2NC);
+ else
+ mir_wstrncpy(NoNewMailPopup.lpwzText, TranslateT("No new mail message"), _countof(NoNewMailPopup.lpwzText));
+ PUAddPopupW(&NoNewMailPopup);
+ }
+
+ if ((nflags & YAMN_ACC_CONT) && (MN->Real.PopupRun + MN->Virtual.PopupRun == 0)) {
+ if (ActualAccount->hContact != NULL) {
+ if (MN->Real.PopupTC + MN->Virtual.PopupTC) {
+ char tmp[255];
+ mir_snprintf(tmp, Translate("%d new mail message(s), %d total"), MN->Real.PopupNC + MN->Virtual.PopupNC, MN->Real.PopupTC + MN->Virtual.PopupTC);
+ db_set_s(ActualAccount->hContact, "CList", "StatusMsg", tmp);
+ }
+ else db_set_s(ActualAccount->hContact, "CList", "StatusMsg", Translate("No new mail message"));
+
+ if (nflags & YAMN_ACC_CONTNICK)
+ g_plugin.setString(ActualAccount->hContact, "Nick", ActualAccount->Name);
+ }
+ }
+ return;
+}
+
+LRESULT CALLBACK NewMailPopupProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ INT_PTR PluginParam = 0;
+ switch (msg) {
+ case WM_COMMAND:
+ // if clicked and it's new mail popup window
+ if ((HIWORD(wParam) == STN_CLICKED) && (-1 != (PluginParam = (INT_PTR)PUGetPluginData(hWnd)))) {
+ MCONTACT hContact = 0;
+ CAccount *Account;
+ if (PluginParam) {
+ PYAMN_MAILSHOWPARAM MailParam = new YAMN_MAILSHOWPARAM;
+ memcpy(MailParam, (PINT_PTR)PluginParam, sizeof(YAMN_MAILSHOWPARAM));
+ hContact = MailParam->account->hContact;
+ Account = MailParam->account;
+ mir_forkthread(ShowEmailThread, MailParam);
+ }
+ else {
+ DBVARIANT dbv;
+
+ hContact = PUGetContact(hWnd);
+
+ if (!g_plugin.getString(hContact, "Id", &dbv)) {
+ Account = (CAccount *)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)dbv.pszVal);
+ db_free(&dbv);
+ }
+ else Account = (CAccount *)hContact; //????
+
+ if (WAIT_OBJECT_0 == WaitToReadFcn(Account->AccountAccessSO)) {
+ switch (msg) {
+ case WM_COMMAND:
+ {
+ YAMN_MAILBROWSERPARAM Param = {(HANDLE)nullptr, Account,
+ (Account->NewMailN.Flags & ~YAMN_ACC_POP) | YAMN_ACC_MSGP | YAMN_ACC_MSG,
+ (Account->NoNewMailN.Flags & ~YAMN_ACC_POP) | YAMN_ACC_MSGP | YAMN_ACC_MSG};
+
+ RunMailBrowserSvc((WPARAM)&Param, (LPARAM)YAMN_MAILBROWSERVERSION);
+ }
+ break;
+ }
+ ReadDoneFcn(Account->AccountAccessSO);
+ }
+ }
+ if ((Account->NewMailN.Flags & YAMN_ACC_CONT) && !(Account->NewMailN.Flags & YAMN_ACC_CONTNOEVENT))
+ g_clistApi.pfnRemoveEvent(hContact, hContact);
+ }
+ __fallthrough;
+
+ case WM_CONTEXTMENU:
+ PUDeletePopup(hWnd);
+ break;
+ case UM_FREEPLUGINDATA:
+ {
+ PYAMN_MAILSHOWPARAM mpd = (PYAMN_MAILSHOWPARAM)PUGetPluginData(hWnd);
+ if ((mpd) && (INT_PTR)mpd != -1)free(mpd);
+ return FALSE;
+ }
+ case UM_INITPOPUP:
+ //This is the equivalent to WM_INITDIALOG you'd get if you were the maker of dialog popups.
+ WindowList_Add(YAMNVar.MessageWnds, hWnd);
+ break;
+ case UM_DESTROYPOPUP:
+ WindowList_Remove(YAMNVar.MessageWnds, hWnd);
+ break;
+ case WM_YAMN_STOPACCOUNT:
+ {
+ CAccount *ActualAccount;
+ DBVARIANT dbv;
+
+ MCONTACT hContact = PUGetContact(hWnd);
+
+ if (!g_plugin.getString(hContact, "Id", &dbv)) {
+ ActualAccount = (CAccount *)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)dbv.pszVal);
+ db_free(&dbv);
+ }
+ else
+ ActualAccount = (CAccount *)hContact;
+
+ if ((CAccount *)wParam != ActualAccount)
+ break;
+ DestroyWindow(hWnd);
+ return 0;
+ }
+ case WM_NOTIFY:
+ default:
+ break;
+ }
+ return DefWindowProc(hWnd, msg, wParam, lParam);
+}
+
+LRESULT CALLBACK NoNewMailPopupProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_COMMAND:
+ if ((HIWORD(wParam) == STN_CLICKED) && (msg == WM_COMMAND)) {
+ CAccount *ActualAccount;
+ DBVARIANT dbv;
+
+ MCONTACT hContact = PUGetContact(hWnd);
+
+ if (!g_plugin.getString(hContact, "Id", &dbv)) {
+ ActualAccount = (CAccount *)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)dbv.pszVal);
+ db_free(&dbv);
+ }
+ else
+ ActualAccount = (CAccount *)hContact;
+
+ if (WAIT_OBJECT_0 == WaitToReadFcn(ActualAccount->AccountAccessSO)) {
+ switch (msg) {
+ case WM_COMMAND:
+ {
+ YAMN_MAILBROWSERPARAM Param = {(HANDLE)nullptr, ActualAccount, ActualAccount->NewMailN.Flags, ActualAccount->NoNewMailN.Flags, nullptr};
+
+ Param.nnflags = Param.nnflags | YAMN_ACC_MSG; //show mails in account even no new mail in account
+ Param.nnflags = Param.nnflags & ~YAMN_ACC_POP;
+
+ Param.nflags = Param.nflags | YAMN_ACC_MSG; //show mails in account even no new mail in account
+ Param.nflags = Param.nflags & ~YAMN_ACC_POP;
+
+ RunMailBrowserSvc((WPARAM)&Param, (LPARAM)YAMN_MAILBROWSERVERSION);
+ }
+ break;
+ }
+ ReadDoneFcn(ActualAccount->AccountAccessSO);
+ }
+ PUDeletePopup(hWnd);
+ }
+ break;
+
+ case WM_CONTEXTMENU:
+ PUDeletePopup(hWnd);
+ break;
+
+ case UM_FREEPLUGINDATA:
+ //Here we'd free our own data, if we had it.
+ return FALSE;
+ case UM_INITPOPUP:
+ //This is the equivalent to WM_INITDIALOG you'd get if you were the maker of dialog popups.
+ WindowList_Add(YAMNVar.MessageWnds, hWnd);
+ break;
+ case UM_DESTROYPOPUP:
+ WindowList_Remove(YAMNVar.MessageWnds, hWnd);
+ break;
+ case WM_YAMN_STOPACCOUNT:
+ {
+ CAccount *ActualAccount;
+ DBVARIANT dbv;
+
+ MCONTACT hContact = PUGetContact(hWnd);
+
+ if (!g_plugin.getString(hContact, "Id", &dbv)) {
+ ActualAccount = (CAccount *)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)dbv.pszVal);
+ db_free(&dbv);
+ }
+ else
+ ActualAccount = (CAccount *)hContact;
+
+ if ((CAccount *)wParam != ActualAccount)
+ break;
+
+ DestroyWindow(hWnd);
+ return 0;
+ }
+ }
+ return DefWindowProc(hWnd, msg, wParam, lParam);
+}
+
+#ifdef __GNUC__
+//number of 100 ns periods between FILETIME 0 (1601/01/01 00:00:00.0000000) and TIMESTAMP 0 (1970/01/01 00:00:00)
+#define NUM100NANOSEC 116444736000000000ULL
+//The biggest time Get[Date|Time]Format can handle (Fri, 31 Dec 30827 23:59:59.9999999)
+#define MAXFILETIME 0x7FFF35F4F06C7FFFULL
+#else
+#define NUM100NANOSEC 116444736000000000
+#define MAXFILETIME 0x7FFF35F4F06C7FFF
+#endif
+
+ULONGLONG MimeDateToFileTime(char *datein)
+{
+ char *day = nullptr, *month = nullptr, *year = nullptr, *time = nullptr, *shift = nullptr;
+ SYSTEMTIME st;
+ ULONGLONG res = 0;
+ int wShiftSeconds = TimeZone_ToLocal(0);
+ GetLocalTime(&st);
+ //datein = "Xxx, 1 Jan 2060 5:29:1 +0530 XXX";
+ //datein = "Xxx, 1 Jan 2060 05:29:10 ";
+ //datein = " ManySpaces 1.5 Jan 2060 05::";
+ //datein = "Xxx, 35 February 20 :29:10 ";
+ //datein = "01.12.2007 (22:38:17)"; //
+ if (datein) {
+ char tmp[64];
+ while (datein[0] == ' ') datein++; // eat leading spaces
+ strncpy(tmp, datein, 63); tmp[63] = 0;
+ if (atoi(tmp)) { // Parseable integer on DayOfWeek field? Buggy mime date.
+ day = tmp;
+ }
+ else {
+ int i = 0;
+ while (tmp[i] == ' ')i++; if (day = strchr(&tmp[i], ' ')) { day[0] = 0; day++; }
+ }
+ if (day) { while (day[0] == ' ') day++; if (month = strchr(day, ' ')) { month[0] = 0; month++; } }
+ if (month) { while (month[0] == ' ')month++; if (year = strchr(month, ' ')) { year[0] = 0; year++; } }
+ if (year) { while (year[0] == ' ') year++; if (time = strchr(year, ' ')) { time[0] = 0; time++; } }
+ if (time) { while (time[0] == ' ') time++; if (shift = strchr(time, ' ')) { shift[0] = 0; shift++; shift[5] = 0; } }
+
+ if (year) {
+ st.wYear = atoi(year);
+ if (mir_strlen(year) < 4) if (st.wYear < 70)st.wYear += 2000; else st.wYear += 1900;
+ };
+ if (month) for (int i = 0; i < 12; i++) if (strncmp(month, s_MonthNames[i], 3) == 0) { st.wMonth = i + 1; break; }
+ if (day) st.wDay = atoi(day);
+ if (time) {
+ char *h, *m, *s;
+ h = time;
+ if (m = strchr(h, ':')) {
+ m[0] = 0; m++;
+ if (s = strchr(m, ':')) { s[0] = 0; s++; }
+ }
+ else s = nullptr;
+ st.wHour = atoi(h);
+ st.wMinute = m ? atoi(m) : 0;
+ st.wSecond = s ? atoi(s) : 0;
+ }
+ else { st.wHour = st.wMinute = st.wSecond = 0; }
+
+ if (shift) {
+ if (mir_strlen(shift) < 4) {
+ //has only hour
+ wShiftSeconds = (atoi(shift)) * 3600;
+ }
+ else {
+ char *smin = shift + mir_strlen(shift) - 2;
+ int ismin = atoi(smin);
+ smin[0] = 0;
+ int ishour = atoi(shift);
+ wShiftSeconds = (ishour * 60 + (ishour < 0 ? -1 : 1) * ismin) * 60;
+ }
+ }
+ } // if (datein)
+ FILETIME ft;
+ if (SystemTimeToFileTime(&st, &ft)) {
+ res = ((ULONGLONG)ft.dwHighDateTime << 32) | ((ULONGLONG)ft.dwLowDateTime);
+ LONGLONG w100nano = Int32x32To64((uint32_t)wShiftSeconds, 10000000);
+ res -= w100nano;
+ }
+ else {
+ res = 0;
+ }
+ return res;
+}
+
+void FileTimeToLocalizedDateTime(LONGLONG filetime, wchar_t *dateout, int lendateout)
+{
+ int localeID = Langpack_GetDefaultLocale();
+ //int localeID = MAKELCID(LANG_URDU, SORT_DEFAULT);
+ if (localeID == CALLSERVICE_NOTFOUND) localeID = LOCALE_USER_DEFAULT;
+ if (filetime > MAXFILETIME) filetime = MAXFILETIME;
+ else if (filetime <= 0) {
+ wcsncpy(dateout, TranslateT("Invalid"), lendateout);
+ return;
+ }
+ SYSTEMTIME st;
+ uint16_t wTodayYear = 0, wTodayMonth = 0, wTodayDay = 0;
+ FILETIME ft;
+ BOOL willShowDate = !(optDateTime & SHOWDATENOTODAY);
+ if (!willShowDate) {
+ GetLocalTime(&st);
+ wTodayYear = st.wYear;
+ wTodayMonth = st.wMonth;
+ wTodayDay = st.wDay;
+ }
+ ft.dwLowDateTime = (uint32_t)filetime;
+ ft.dwHighDateTime = (uint32_t)(filetime >> 32);
+ FILETIME localft;
+ if (!FileTimeToLocalFileTime(&ft, &localft)) {
+ // this should never happen
+ wcsncpy(dateout, L"Incorrect FileTime", lendateout);
+ }
+ else {
+ if (!FileTimeToSystemTime(&localft, &st)) {
+ // this should never happen
+ wcsncpy(dateout, L"Incorrect LocalFileTime", lendateout);
+ }
+ else {
+ dateout[lendateout - 1] = 0;
+ int templen = 0;
+ if (!willShowDate) willShowDate = (wTodayYear != st.wYear) || (wTodayMonth != st.wMonth) || (wTodayDay != st.wDay);
+ if (willShowDate) {
+ templen = GetDateFormatW(localeID, (optDateTime & SHOWDATELONG) ? DATE_LONGDATE : DATE_SHORTDATE, &st, nullptr, dateout, lendateout - 2);
+ dateout[templen - 1] = ' ';
+ }
+ if (templen < (lendateout - 1)) {
+ GetTimeFormatW(localeID, (optDateTime & SHOWDATENOSECONDS) ? TIME_NOSECONDS : 0, &st, nullptr, &dateout[templen], lendateout - templen - 1);
+ }
+ }
+ }
+}
+
+void MimeDateToLocalizedDateTime(char *datein, wchar_t *dateout, int lendateout)
+{
+ ULONGLONG ft = MimeDateToFileTime(datein);
+ FileTimeToLocalizedDateTime(ft, dateout, lendateout);
+}
+
+int CALLBACK ListViewCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
+{
+ if (lParam1 == NULL || lParam2 == NULL)
+ return 0;
+
+ int nResult = 0;
+ char *str1;
+ char *str2;
+ HYAMNMAIL email1 = (HYAMNMAIL)lParam1;
+ HYAMNMAIL email2 = (HYAMNMAIL)lParam2;
+ struct CShortHeader Header1;
+ struct CShortHeader Header2;
+ memset(&Header1, 0, sizeof(Header1));
+ memset(&Header2, 0, sizeof(Header2));
+
+ try {
+ ExtractShortHeader(email1->MailData->TranslatedHeader, &Header1);
+ ExtractShortHeader(email2->MailData->TranslatedHeader, &Header2);
+
+ switch ((int)lParamSort) {
+ case 0: //From
+ if (Header1.FromNick == nullptr)
+ str1 = Header1.From;
+ else str1 = Header1.FromNick;
+
+ if (Header2.FromNick == nullptr)
+ str2 = Header2.From;
+ else str2 = Header2.FromNick;
+
+ nResult = mir_strcmp(str1, str2);
+
+ if (bFrom) nResult = -nResult;
+ break;
+ case 1: //Subject
+ if (Header1.Subject == nullptr)
+ str1 = " ";
+ else str1 = Header1.Subject;
+
+ if (Header2.Subject == nullptr)
+ str2 = " ";
+ else str2 = Header2.Subject;
+
+ nResult = mir_strcmp(str1, str2);
+
+ if (bSub) nResult = -nResult;
+ break;
+ case 2: //Size
+ if (email1->MailData->Size == email2->MailData->Size) nResult = 0;
+ if (email1->MailData->Size > email2->MailData->Size) nResult = 1;
+ if (email1->MailData->Size < email2->MailData->Size) nResult = -1;
+
+ if (bSize) nResult = -nResult;
+ break;
+
+ case 3: //Date
+ {
+ ULONGLONG ts1 = 0, ts2 = 0;
+ ts1 = MimeDateToFileTime(Header1.Date);
+ ts2 = MimeDateToFileTime(Header2.Date);
+ if (ts1 > ts2) nResult = 1;
+ else if (ts1 < ts2) nResult = -1;
+ else nResult = 0;
+ }
+ if (bDate) nResult = -nResult;
+ break;
+
+ default:
+ if (Header1.Subject == nullptr) str1 = " ";
+ else str1 = Header1.Subject;
+
+ if (Header2.Subject == nullptr) str2 = " ";
+ else str2 = Header2.Subject;
+
+ nResult = mir_strcmp(str1, str2);
+ break;
+ }
+ //MessageBox(NULL,str1,str2,0);
+ }
+ catch (...) {
+ }
+
+ //free mem
+ DeleteShortHeaderContent(&Header1);
+ DeleteShortHeaderContent(&Header2);
+ return nResult;
+
+}
+
+HCURSOR hCurSplitNS, hCurSplitWE;
+#define DM_SPLITTERMOVED (WM_USER+15)
+
+static LRESULT CALLBACK SplitterSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_NCHITTEST:
+ return HTCLIENT;
+
+ case WM_SETCURSOR:
+ SetCursor(hCurSplitNS);
+ return TRUE;
+
+ case WM_LBUTTONDOWN:
+ SetCapture(hwnd);
+ return 0;
+
+ case WM_MOUSEMOVE:
+ if (GetCapture() == hwnd) {
+ RECT rc;
+ GetClientRect(hwnd, &rc);
+ SendMessage(GetParent(hwnd), DM_SPLITTERMOVED, (short)HIWORD(GetMessagePos()) + rc.bottom / 2, (LPARAM)hwnd);
+ }
+ return 0;
+
+ case WM_LBUTTONUP:
+ ReleaseCapture();
+ return 0;
+ }
+ return mir_callNextSubclass(hwnd, SplitterSubclassProc, msg, wParam, lParam);
+}
+
+void ConvertCodedStringToUnicode(char *stream, wchar_t **storeto, uint32_t cp, int mode);
+int ConvertStringToUnicode(char *stream, unsigned int cp, wchar_t **out);
+
+INT_PTR CALLBACK DlgProcYAMNShowMessage(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ PYAMN_MAILSHOWPARAM MailParam = (PYAMN_MAILSHOWPARAM)lParam;
+ wchar_t *iHeaderW = nullptr;
+ wchar_t *iValueW = nullptr;
+ int StrLen;
+ HWND hListView = GetDlgItem(hDlg, IDC_LISTHEADERS);
+ mir_subclassWindow(GetDlgItem(hDlg, IDC_SPLITTER), SplitterSubclassProc);
+ SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)MailParam);
+ Window_SetIcon_IcoLib(hDlg, g_plugin.getIconHandle(IDI_NEWMAIL));
+
+ ListView_SetUnicodeFormat(hListView, TRUE);
+ ListView_SetExtendedListViewStyle(hListView, LVS_EX_FULLROWSELECT);
+
+ StrLen = MultiByteToWideChar(CP_ACP, MB_USEGLYPHCHARS, Translate("Header"), -1, nullptr, 0);
+ iHeaderW = new wchar_t[StrLen + 1];
+ MultiByteToWideChar(CP_ACP, MB_USEGLYPHCHARS, Translate("Header"), -1, iHeaderW, StrLen);
+
+ StrLen = MultiByteToWideChar(CP_ACP, MB_USEGLYPHCHARS, Translate("Value"), -1, nullptr, 0);
+ iValueW = new wchar_t[StrLen + 1];
+ MultiByteToWideChar(CP_ACP, MB_USEGLYPHCHARS, Translate("Value"), -1, iValueW, StrLen);
+
+ LVCOLUMN lvc0 = {LVCF_FMT | LVCF_TEXT | LVCF_WIDTH, LVCFMT_LEFT, 130, iHeaderW, 0, 0};
+ LVCOLUMN lvc1 = {LVCF_FMT | LVCF_TEXT | LVCF_WIDTH, LVCFMT_LEFT, 400, iValueW, 0, 0};
+ SendMessage(hListView, LVM_INSERTCOLUMN, 0, (LPARAM)&lvc0);
+ SendMessage(hListView, LVM_INSERTCOLUMN, 1, (LPARAM)&lvc1);
+ if (nullptr != iHeaderW)
+ delete[] iHeaderW;
+ if (nullptr != iValueW)
+ delete[] iValueW;
+
+ SendMessage(hDlg, WM_YAMN_CHANGECONTENT, 0, (LPARAM)MailParam);
+ MoveWindow(hDlg, HeadPosX, HeadPosY, HeadSizeX, HeadSizeY, 0);
+ ShowWindow(hDlg, SW_SHOWNORMAL);
+ }
+ break;
+
+ case WM_YAMN_CHANGECONTENT:
+ {
+ PYAMN_MAILSHOWPARAM MailParam = (PYAMN_MAILSHOWPARAM)
+ (lParam ? lParam : GetWindowLongPtr(hDlg, DWLP_USER));
+ HWND hListView = GetDlgItem(hDlg, IDC_LISTHEADERS);
+ HWND hEdit = GetDlgItem(hDlg, IDC_EDITBODY);
+ //do not redraw
+ SendMessage(hListView, WM_SETREDRAW, 0, 0);
+ ListView_DeleteAllItems(hListView);
+ struct CMimeItem *Header;
+ LVITEMW item;
+ item.mask = LVIF_TEXT | LVIF_PARAM;
+ wchar_t *From = nullptr, *Subj = nullptr;
+ char *contentType = nullptr, *transEncoding = nullptr, *body = nullptr; //should not be delete[]-ed
+ for (Header = MailParam->mail->MailData->TranslatedHeader; Header != nullptr; Header = Header->Next) {
+ wchar_t *str1 = nullptr;
+ wchar_t *str2 = nullptr;
+ wchar_t str_nul[2] = {0};
+ if (!body) if (!_stricmp(Header->name, "Body")) { body = Header->value; continue; }
+ if (!contentType) if (!_stricmp(Header->name, "Content-Type")) contentType = Header->value;
+ if (!transEncoding) if (!_stricmp(Header->name, "Content-Transfer-Encoding")) transEncoding = Header->value;
+ //ConvertCodedStringToUnicode(Header->name,&str1,MailParam->mail->MailData->CP,1);
+ {
+ int streamsize = MultiByteToWideChar(20127, 0, Header->name, -1, nullptr, 0);
+ str1 = (wchar_t *)malloc(sizeof(wchar_t) * (streamsize + 1));
+ MultiByteToWideChar(20127, 0, Header->name, -1, str1, streamsize);//US-ASCII
+ }
+ ConvertCodedStringToUnicode(Header->value, &str2, MailParam->mail->MailData->CP, 1);
+ if (!str2) { str2 = (wchar_t *)str_nul; }// the header value may be NULL
+ if (!From) if (!_stricmp(Header->name, "From")) {
+ From = new wchar_t[mir_wstrlen(str2) + 1];
+ mir_wstrcpy(From, str2);
+ }
+ if (!Subj) if (!_stricmp(Header->name, "Subject")) {
+ Subj = new wchar_t[mir_wstrlen(str2) + 1];
+ mir_wstrcpy(Subj, str2);
+ }
+ //if (!hasBody) if (!mir_strcmp(Header->name,"Body")) hasBody = true;
+ int count = 0; wchar_t **split = nullptr;
+ int ofs = 0;
+ while (str2[ofs]) {
+ if ((str2[ofs] == 0x266A) || (str2[ofs] == 0x25D9) || (str2[ofs] == 0x25CB) ||
+ (str2[ofs] == 0x09) || (str2[ofs] == 0x0A) || (str2[ofs] == 0x0D))count++;
+ ofs++;
+ }
+ split = new wchar_t *[count + 1];
+ count = 0; ofs = 0;
+ split[0] = str2;
+ while (str2[ofs]) {
+ if ((str2[ofs] == 0x266A) || (str2[ofs] == 0x25D9) || (str2[ofs] == 0x25CB) ||
+ (str2[ofs] == 0x09) || (str2[ofs] == 0x0A) || (str2[ofs] == 0x0D)) {
+ if (str2[ofs - 1]) {
+ count++;
+ }
+ split[count] = (wchar_t *)(str2 + ofs + 1);
+ str2[ofs] = 0;
+ }
+ ofs++;
+ };
+
+ if (!_stricmp(Header->name, "From") || !_stricmp(Header->name, "To") || !_stricmp(Header->name, "Date") || !_stricmp(Header->name, "Subject"))
+ item.iItem = 0;
+ else
+ item.iItem = 999;
+ for (int i = 0; i <= count; i++) {
+ item.iSubItem = 0;
+ if (i == 0)
+ item.pszText = str1;
+ else {
+ item.iItem++;
+ item.pszText = nullptr;
+ }
+ item.iItem = SendMessage(hListView, LVM_INSERTITEM, 0, (LPARAM)&item);
+ item.iSubItem = 1;
+ item.pszText = str2 ? split[i] : nullptr;
+ SendMessage(hListView, LVM_SETITEMTEXT, (WPARAM)item.iItem, (LPARAM)&item);
+ }
+ delete[] split;
+
+ if (str1)
+ free(str1);
+ if (str2 != (wchar_t *)str_nul)
+ free(str2);
+ }
+ if (body) {
+ wchar_t *bodyDecoded = nullptr;
+ char *localBody = nullptr;
+ if (contentType) {
+ if (!_strnicmp(contentType, "text", 4)) {
+ if (transEncoding) {
+ if (!_stricmp(transEncoding, "base64")) {
+ int size = (int)mir_strlen(body) * 3 / 4 + 5;
+ localBody = new char[size + 1];
+ DecodeBase64(body, localBody, size);
+ }
+ else if (!_stricmp(transEncoding, "quoted-printable")) {
+ int size = (int)mir_strlen(body) + 2;
+ localBody = new char[size + 1];
+ DecodeQuotedPrintable(body, localBody, size, FALSE);
+ }
+ }
+ }
+ else if (!_strnicmp(contentType, "multipart/", 10)) {
+ char *bondary = nullptr;
+ if (nullptr != (bondary = ExtractFromContentType(contentType, "boundary="))) {
+ bodyDecoded = ParseMultipartBody(body, bondary);
+ delete[] bondary;
+ }
+ }
+ }
+ if (!bodyDecoded)ConvertStringToUnicode(localBody ? localBody : body, MailParam->mail->MailData->CP, &bodyDecoded);
+ SetWindowTextW(hEdit, bodyDecoded);
+ delete[] bodyDecoded;
+ if (localBody) delete[] localBody;
+ SetFocus(hEdit);
+ }
+ if (!(MailParam->mail->Flags & YAMN_MSG_BODYRECEIVED)) {
+ MailParam->mail->Flags |= YAMN_MSG_BODYREQUESTED;
+ CallService(MS_YAMN_ACCOUNTCHECK, (WPARAM)MailParam->account, 0);
+ }
+ else {
+ if (MailParam->mail->Flags & YAMN_MSG_UNSEEN) {
+ MailParam->mail->Flags &= ~YAMN_MSG_UNSEEN; //mark the message as seen
+ HWND hMailBrowser = WindowList_Find(YAMNVar.NewMailAccountWnd, (UINT_PTR)MailParam->account);
+ if (hMailBrowser) {
+ struct CChangeContent Params = {MailParam->account->NewMailN.Flags | YAMN_ACC_MSGP, MailParam->account->NoNewMailN.Flags | YAMN_ACC_MSGP};
+ SendMessage(hMailBrowser, WM_YAMN_CHANGECONTENT, (WPARAM)MailParam->account, (LPARAM)&Params);
+ }
+ else UpdateMails(nullptr, MailParam->account, MailParam->account->NewMailN.Flags, MailParam->account->NoNewMailN.Flags);
+ }
+ }
+ ShowWindow(GetDlgItem(hDlg, IDC_SPLITTER), (MailParam->mail->Flags & YAMN_MSG_BODYRECEIVED) ? SW_SHOW : SW_HIDE);
+ ShowWindow(hEdit, (MailParam->mail->Flags & YAMN_MSG_BODYRECEIVED) ? SW_SHOW : SW_HIDE);
+ wchar_t *title = nullptr;
+ size_t size = (From ? mir_wstrlen(From) : 0) + (Subj ? mir_wstrlen(Subj) : 0) + 4;
+ title = new wchar_t[size];
+ if (From && Subj)
+ mir_snwprintf(title, size, L"%s (%s)", Subj, From);
+ else if (From)
+ wcsncpy_s(title, size, From, _TRUNCATE);
+ else if (Subj)
+ wcsncpy_s(title, size, Subj, _TRUNCATE);
+ else
+ wcsncpy_s(title, size, L"none", _TRUNCATE);
+ if (Subj) delete[] Subj;
+ if (From) delete[] From;
+ SetWindowTextW(hDlg, title);
+ delete[] title;
+ // turn on redrawing
+ SendMessage(hListView, WM_SETREDRAW, 1, 0);
+ SendMessage(hDlg, WM_SIZE, 0, HeadSizeY << 16 | HeadSizeX);
+ } break;
+
+ case WM_YAMN_STOPACCOUNT:
+ {
+ PYAMN_MAILSHOWPARAM MailParam = (PYAMN_MAILSHOWPARAM)
+ (lParam ? lParam : GetWindowLongPtr(hDlg, DWLP_USER));
+
+ if (nullptr == MailParam)
+ break;
+ if ((CAccount *)wParam != MailParam->account)
+ break;
+
+ DestroyWindow(hDlg);
+ }
+ return 1;
+
+ case WM_CTLCOLORSTATIC:
+ // here should be check if this is our edittext control.
+ // but we have only one static control (for now);
+ SetBkColor((HDC)wParam, GetSysColor(COLOR_WINDOW));
+ SetTextColor((HDC)wParam, GetSysColor(COLOR_WINDOWTEXT));
+ return (INT_PTR)GetSysColorBrush(COLOR_WINDOW);
+
+ case WM_DESTROY:
+ Window_FreeIcon_IcoLib(hDlg);
+ {
+ RECT coord;
+ if (GetWindowRect(hDlg, &coord)) {
+ HeadPosX = coord.left;
+ HeadSizeX = coord.right - coord.left;
+ HeadPosY = coord.top;
+ HeadSizeY = coord.bottom - coord.top;
+ }
+
+ PostQuitMessage(1);
+ }
+ break;
+
+ case WM_SYSCOMMAND:
+ switch (wParam) {
+ case SC_CLOSE:
+ DestroyWindow(hDlg);
+ break;
+ }
+ break;
+
+ case WM_MOVE:
+ HeadPosX = LOWORD(lParam); //((LPRECT)lParam)->right-((LPRECT)lParam)->left;
+ HeadPosY = HIWORD(lParam); //((LPRECT)lParam)->bottom-((LPRECT)lParam)->top;
+ return 0;
+
+ case DM_SPLITTERMOVED:
+ if ((HWND)lParam == GetDlgItem(hDlg, IDC_SPLITTER)) {
+ POINT pt;
+ pt.x = 0;
+ pt.y = wParam;
+ ScreenToClient(hDlg, &pt);
+ HeadSplitPos = (pt.y * 1000) / HeadSizeY;//+rc.bottom-rc.top;
+ if (HeadSplitPos >= 1000) HeadSplitPos = 999;
+ else if (HeadSplitPos <= 0) HeadSplitPos = 1;
+ else SendMessage(hDlg, WM_SIZE, 0, HeadSizeY << 16 | HeadSizeX);
+ }
+ return 0;
+
+ case WM_SIZE:
+ if (wParam == SIZE_RESTORED) {
+ HWND hList = GetDlgItem(hDlg, IDC_LISTHEADERS);
+ HWND hEdit = GetDlgItem(hDlg, IDC_EDITBODY);
+ BOOL isBodyShown = ((PYAMN_MAILSHOWPARAM)(GetWindowLongPtr(hDlg, DWLP_USER)))->mail->Flags & YAMN_MSG_BODYRECEIVED;
+ HeadSizeX = LOWORD(lParam); //((LPRECT)lParam)->right-((LPRECT)lParam)->left;
+ HeadSizeY = HIWORD(lParam); //((LPRECT)lParam)->bottom-((LPRECT)lParam)->top;
+ int localSplitPos = (HeadSplitPos * HeadSizeY) / 1000;
+ int localSizeX;
+ RECT coord;
+ MoveWindow(GetDlgItem(hDlg, IDC_SPLITTER), 5, localSplitPos, HeadSizeX - 10, 2, TRUE);
+ MoveWindow(hEdit, 5, localSplitPos + 6, HeadSizeX - 10, HeadSizeY - localSplitPos - 11, TRUE); //where to put text window while resizing
+ MoveWindow(hList, 5, 5, HeadSizeX - 10, (isBodyShown ? localSplitPos : HeadSizeY) - 10, TRUE); //where to put headers list window while resizing
+ //if (changeX) {
+ if (GetClientRect(hList, &coord)) {
+ localSizeX = coord.right - coord.left;
+ }
+ else localSizeX = HeadSizeX;
+ LONG iNameWidth = ListView_GetColumnWidth(hList, 0);
+ ListView_SetColumnWidth(hList, 1, (localSizeX <= iNameWidth) ? 0 : (localSizeX - iNameWidth));
+ //}
+ }
+ return 0;
+
+ case WM_CONTEXTMENU:
+ if (GetWindowLongPtr((HWND)wParam, GWLP_ID) == IDC_LISTHEADERS) {
+ //MessageBox(0,"LISTHEADERS","Debug",0);
+ HWND hList = GetDlgItem(hDlg, IDC_LISTHEADERS);
+ POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
+ if (pt.x == -1) pt.x = 0;
+ if (pt.y == -1) pt.y = 0;
+ if (int numRows = ListView_GetItemCount(hList)) {
+ HMENU hMenu = CreatePopupMenu();
+ AppendMenu(hMenu, MF_STRING, (UINT_PTR)1, TranslateT("Copy Selected"));
+ AppendMenu(hMenu, MF_STRING, (UINT_PTR)2, TranslateT("Copy All"));
+ AppendMenu(hMenu, MF_SEPARATOR, 0, nullptr);
+ AppendMenu(hMenu, MF_STRING, (UINT_PTR)0, TranslateT("Cancel"));
+ int nReturnCmd = TrackPopupMenu(hMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hDlg, nullptr);
+ DestroyMenu(hMenu);
+ if (nReturnCmd > 0) {
+ int courRow = 0;
+ size_t sizeNeeded = 0;
+ wchar_t headname[64] = {0}, headvalue[256] = {0};
+ for (courRow = 0; courRow < numRows; courRow++) {
+ if ((nReturnCmd == 1) && (ListView_GetItemState(hList, courRow, LVIS_SELECTED) == 0)) continue;
+ ListView_GetItemText(hList, courRow, 0, headname, _countof(headname));
+ ListView_GetItemText(hList, courRow, 1, headvalue, _countof(headvalue));
+ size_t headnamelen = mir_wstrlen(headname);
+ if (headnamelen) sizeNeeded += 1 + headnamelen;
+ sizeNeeded += 3 + mir_wstrlen(headvalue);
+ }
+ if (sizeNeeded && OpenClipboard(hDlg)) {
+ EmptyClipboard();
+ HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE, (sizeNeeded + 1) * sizeof(wchar_t));
+ wchar_t *buff = (wchar_t *)GlobalLock(hData);
+ int courPos = 0;
+ for (courRow = 0; courRow < numRows; courRow++) {
+ if ((nReturnCmd == 1) && (ListView_GetItemState(hList, courRow, LVIS_SELECTED) == 0)) continue;
+ ListView_GetItemText(hList, courRow, 0, headname, _countof(headname));
+ ListView_GetItemText(hList, courRow, 1, headvalue, _countof(headvalue));
+ if (mir_wstrlen(headname)) courPos += mir_snwprintf(&buff[courPos], sizeNeeded + 1, L"%s:\t%s\r\n", headname, headvalue);
+ else courPos += mir_snwprintf(&buff[courPos], sizeNeeded + 1, L"\t%s\r\n", headvalue);
+ }
+ GlobalUnlock(hData);
+
+ SetClipboardData(CF_UNICODETEXT, hData);
+
+ CloseClipboard();
+ }
+ }
+ }
+ }
+ break; // just in case
+ }
+ return 0;
+}
+
+void __cdecl ShowEmailThread(void *Param)
+{
+ struct MailShowMsgWinParam MyParam = *(struct MailShowMsgWinParam *)Param;
+
+ SCIncFcn(MyParam.account->UsingThreads);
+
+ if (MyParam.mail->MsgWindow) {
+ //if (!BringWindowToTop(MyParam.mail->MsgWindow)) {
+ if (!SetForegroundWindow(MyParam.mail->MsgWindow)) {
+ SendMessage(MyParam.mail->MsgWindow, WM_DESTROY, 0, 0);
+ MyParam.mail->MsgWindow = nullptr;
+ goto CREADTEVIEWMESSAGEWINDOW;
+ }
+
+ if (IsIconic(MyParam.mail->MsgWindow))
+ OpenIcon(MyParam.mail->MsgWindow);
+ }
+ else {
+CREADTEVIEWMESSAGEWINDOW:
+ MyParam.mail->MsgWindow = CreateDialogParamW(g_plugin.getInst(), MAKEINTRESOURCEW(IDD_DLGSHOWMESSAGE), nullptr, DlgProcYAMNShowMessage, (LPARAM)&MyParam);
+ WindowList_Add(YAMNVar.MessageWnds, MyParam.mail->MsgWindow);
+ MSG msg;
+ while (GetMessage(&msg, nullptr, 0, 0)) {
+ if (MyParam.mail->MsgWindow == nullptr || !IsDialogMessage(MyParam.mail->MsgWindow, &msg)) { /* Wine fix. */
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+ WindowList_Remove(YAMNVar.MessageWnds, MyParam.mail->MsgWindow);
+ MyParam.mail->MsgWindow = nullptr;
+ }
+
+ SCDecFcn(MyParam.account->UsingThreads);
+ delete (struct MailShowMsgWinParam *)Param;
+}
+
+INT_PTR CALLBACK DlgProcYAMNMailBrowser(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ CAccount *ActualAccount;
+ int Items;
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ struct MailBrowserWinParam *MyParam = (struct MailBrowserWinParam *)lParam;
+
+ ListView_SetUnicodeFormat(GetDlgItem(hDlg, IDC_LISTMAILS), TRUE);
+ ListView_SetExtendedListViewStyle(GetDlgItem(hDlg, IDC_LISTMAILS), LVS_EX_FULLROWSELECT);
+
+ ActualAccount = MyParam->account;
+ struct CMailWinUserInfo *mwui = new struct CMailWinUserInfo;
+ mwui->Account = ActualAccount;
+ mwui->TrayIconState = 0;
+ mwui->UpdateMailsMessagesAccess = FALSE;
+ mwui->Seen = FALSE;
+ mwui->RunFirstTime = TRUE;
+
+ SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)mwui);
+ if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO)) {
+ DestroyWindow(hDlg);
+ return FALSE;
+ }
+
+ SetDlgItemText(hDlg, IDC_BTNAPP, TranslateT("Run application"));
+ SetDlgItemText(hDlg, IDC_BTNDEL, TranslateT("Delete selected"));
+ SetDlgItemText(hDlg, IDC_BTNCHECKALL, TranslateT("Select All"));
+ SetDlgItemText(hDlg, IDC_BTNOK, TranslateT("OK"));
+
+ LVCOLUMN lvc0 = {LVCF_FMT | LVCF_TEXT | LVCF_WIDTH, LVCFMT_LEFT, FromWidth, TranslateT("From"), 0, 0};
+ LVCOLUMN lvc1 = {LVCF_FMT | LVCF_TEXT | LVCF_WIDTH, LVCFMT_LEFT, SubjectWidth, TranslateT("Subject"), 0, 0};
+ LVCOLUMN lvc2 = {LVCF_FMT | LVCF_TEXT | LVCF_WIDTH, LVCFMT_LEFT, SizeWidth, TranslateT("Size"), 0, 0};
+ LVCOLUMN lvc3 = {LVCF_FMT | LVCF_TEXT | LVCF_WIDTH, LVCFMT_LEFT, SizeDate, TranslateT("Date"), 0, 0};
+ SendDlgItemMessage(hDlg, IDC_LISTMAILS, LVM_INSERTCOLUMN, 0, (LPARAM)&lvc0);
+ SendDlgItemMessage(hDlg, IDC_LISTMAILS, LVM_INSERTCOLUMN, 1, (LPARAM)&lvc1);
+ SendDlgItemMessage(hDlg, IDC_LISTMAILS, LVM_INSERTCOLUMN, (WPARAM)2, (LPARAM)&lvc2);
+ SendDlgItemMessage(hDlg, IDC_LISTMAILS, LVM_INSERTCOLUMN, (WPARAM)3, (LPARAM)&lvc3);
+
+ if ((ActualAccount->NewMailN.App != nullptr) && (mir_wstrlen(ActualAccount->NewMailN.App)))
+ EnableWindow(GetDlgItem(hDlg, IDC_BTNAPP), TRUE);
+ else
+ EnableWindow(GetDlgItem(hDlg, IDC_BTNAPP), FALSE);
+
+ ReadDoneFcn(ActualAccount->AccountAccessSO);
+
+ WindowList_Add(YAMNVar.MessageWnds, hDlg);
+ WindowList_Add(YAMNVar.NewMailAccountWnd, hDlg, (UINT_PTR)ActualAccount);
+
+ {
+ wchar_t accstatus[512];
+ GetStatusFcn(ActualAccount, accstatus);
+ SetDlgItemText(hDlg, IDC_STSTATUS, accstatus);
+ }
+ SetTimer(hDlg, TIMER_FLASHING, 500, nullptr);
+
+ if (ActualAccount->hContact != NULL)
+ g_clistApi.pfnRemoveEvent(ActualAccount->hContact, (LPARAM)"yamn new mail message");
+
+ mir_subclassWindow(GetDlgItem(hDlg, IDC_LISTMAILS), ListViewSubclassProc);
+ }
+ break;
+
+ case WM_DESTROY:
+ {
+ RECT coord;
+ LVCOLUMN ColInfo;
+ HYAMNMAIL Parser;
+
+ Window_FreeIcon_IcoLib(hDlg);
+
+ struct CMailWinUserInfo *mwui = (struct CMailWinUserInfo *)GetWindowLongPtr(hDlg, DWLP_USER);
+ if (nullptr == (ActualAccount = GetWindowAccount(hDlg)))
+ break;
+ ColInfo.mask = LVCF_WIDTH;
+ if (ListView_GetColumn(GetDlgItem(hDlg, IDC_LISTMAILS), 0, &ColInfo))
+ FromWidth = ColInfo.cx;
+ if (ListView_GetColumn(GetDlgItem(hDlg, IDC_LISTMAILS), 1, &ColInfo))
+ SubjectWidth = ColInfo.cx;
+ if (ListView_GetColumn(GetDlgItem(hDlg, IDC_LISTMAILS), 2, &ColInfo))
+ SizeWidth = ColInfo.cx;
+ if (ListView_GetColumn(GetDlgItem(hDlg, IDC_LISTMAILS), 3, &ColInfo))
+ SizeDate = ColInfo.cx;
+
+ if (!YAMNVar.Shutdown && GetWindowRect(hDlg, &coord)) //the YAMNVar.Shutdown testing is because M<iranda strange functionality at shutdown phase, when call to DBWriteContactSetting freezes calling thread
+ {
+ PosX = coord.left;
+ SizeX = coord.right - coord.left;
+ PosY = coord.top;
+ SizeY = coord.bottom - coord.top;
+ g_plugin.setDword(YAMN_DBPOSX, PosX);
+ g_plugin.setDword(YAMN_DBPOSY, PosY);
+ g_plugin.setDword(YAMN_DBSIZEX, SizeX);
+ g_plugin.setDword(YAMN_DBSIZEY, SizeY);
+ }
+ KillTimer(hDlg, TIMER_FLASHING);
+
+ WindowList_Remove(YAMNVar.NewMailAccountWnd, hDlg);
+ WindowList_Remove(YAMNVar.MessageWnds, hDlg);
+
+ if (WAIT_OBJECT_0 != WaitToWriteFcn(ActualAccount->MessagesAccessSO))
+ break;
+
+ //delete mails from queue, which are deleted from server (spam level 3 mails e.g.)
+ for (Parser = (HYAMNMAIL)ActualAccount->Mails; Parser != nullptr; Parser = Parser->Next) {
+ if ((Parser->Flags & YAMN_MSG_DELETED) && YAMN_MSG_SPAML(Parser->Flags, YAMN_MSG_SPAML3) && mwui->Seen) //if spaml3 was already deleted and user knows about it
+ {
+ DeleteMessageFromQueueFcn((HYAMNMAIL *)&ActualAccount->Mails, Parser, 1);
+ CallService(MS_YAMN_DELETEACCOUNTMAIL, (WPARAM)ActualAccount->Plugin, (LPARAM)Parser);
+ }
+ }
+
+ //mark mails as read (remove "new" and "unseen" flags)
+ if (mwui->Seen)
+ SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails, YAMN_MSG_DISPLAY, 0, YAMN_MSG_NEW | YAMN_MSG_UNSEEN, 0);
+
+ WriteDoneFcn(ActualAccount->MessagesAccessSO);
+
+ NOTIFYICONDATA nid;
+ memset(&nid, 0, sizeof(NOTIFYICONDATA));
+
+ delete mwui;
+ SetWindowLongPtr(hDlg, DWLP_USER, NULL);
+
+ nid.cbSize = sizeof(NOTIFYICONDATA);
+ nid.hWnd = hDlg;
+ nid.uID = 0;
+ Shell_NotifyIcon(NIM_DELETE, &nid);
+ PostQuitMessage(0);
+ }
+ break;
+
+ case WM_SHOWWINDOW:
+ {
+ struct CMailWinUserInfo *mwui = (struct CMailWinUserInfo *)GetWindowLongPtr(hDlg, DWLP_USER);
+
+ if (mwui == nullptr)
+ return 0;
+ mwui->Seen = TRUE;
+ }
+
+ case WM_YAMN_CHANGESTATUS:
+ if (nullptr == (ActualAccount = GetWindowAccount(hDlg)))
+ break;
+
+ if ((CAccount *)wParam != ActualAccount)
+ break;
+
+ wchar_t accstatus[512];
+ GetStatusFcn(ActualAccount, accstatus);
+ SetDlgItemText(hDlg, IDC_STSTATUS, accstatus);
+ return 1;
+
+ case WM_YAMN_CHANGECONTENT:
+ {
+ struct CUpdateMails UpdateParams;
+ BOOL ThisThreadWindow = (GetCurrentThreadId() == GetWindowThreadProcessId(hDlg, nullptr));
+
+ if (nullptr == (UpdateParams.Copied = CreateEvent(nullptr, FALSE, FALSE, nullptr))) {
+ DestroyWindow(hDlg);
+ return 0;
+ }
+ UpdateParams.Flags = (struct CChangeContent *)lParam;
+ UpdateParams.Waiting = !ThisThreadWindow;
+
+ if (ThisThreadWindow) {
+ if (!UpdateMails(hDlg, (CAccount *)wParam, UpdateParams.Flags->nflags, UpdateParams.Flags->nnflags))
+ DestroyWindow(hDlg);
+ }
+ else if (PostMessage(hDlg, WM_YAMN_UPDATEMAILS, wParam, (LPARAM)&UpdateParams)) //this ensures UpdateMails will execute the thread who created the browser window
+ {
+ if (!ThisThreadWindow)
+ WaitForSingleObject(UpdateParams.Copied, INFINITE);
+ }
+
+ CloseHandle(UpdateParams.Copied);
+ }
+ return 1;
+ case WM_YAMN_UPDATEMAILS:
+ {
+ struct CUpdateMails *um = (struct CUpdateMails *)lParam;
+ uint32_t nflags, nnflags;
+
+ if (nullptr == (ActualAccount = GetWindowAccount(hDlg)))
+ return 0;
+ if ((CAccount *)wParam != ActualAccount)
+ return 0;
+
+ nflags = um->Flags->nflags;
+ nnflags = um->Flags->nnflags;
+
+ if (um->Waiting)
+ SetEvent(um->Copied);
+
+ if (!UpdateMails(hDlg, ActualAccount, nflags, nnflags))
+ DestroyWindow(hDlg);
+ }
+ return 1;
+ case WM_YAMN_STOPACCOUNT:
+ if (nullptr == (ActualAccount = GetWindowAccount(hDlg)))
+ break;
+ if ((CAccount *)wParam != ActualAccount)
+ break;
+ PostQuitMessage(0);
+ return 1;
+
+ case WM_YAMN_NOTIFYICON:
+ if (nullptr == (ActualAccount = GetWindowAccount(hDlg)))
+ break;
+
+ switch (lParam) {
+ case WM_LBUTTONDBLCLK:
+ if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO)) {
+ return 0;
+ }
+
+ if (ActualAccount->AbilityFlags & YAMN_ACC_BROWSE) {
+ ShowWindow(hDlg, SW_SHOWNORMAL);
+ SetForegroundWindow(hDlg);
+ }
+ else DestroyWindow(hDlg);
+
+ ReadDoneFcn(ActualAccount->AccountAccessSO);
+ break;
+ }
+ break;
+
+ case WM_YAMN_SHOWSELECTED:
+ {
+ int iSelect = SendDlgItemMessage(hDlg, IDC_LISTMAILS, LVM_GETNEXTITEM, -1, MAKELPARAM((UINT)LVNI_FOCUSED, 0)); // return item selected
+ if (iSelect != -1) {
+ LV_ITEMW item;
+
+ item.iItem = iSelect;
+ item.iSubItem = 0;
+ item.mask = LVIF_PARAM | LVIF_STATE;
+ item.stateMask = 0xFFFFFFFF;
+ ListView_GetItem(GetDlgItem(hDlg, IDC_LISTMAILS), &item);
+ HYAMNMAIL ActualMail = (HYAMNMAIL)item.lParam;
+ if (nullptr != ActualMail) {
+ PYAMN_MAILSHOWPARAM MailParam = new YAMN_MAILSHOWPARAM;
+ MailParam->account = GetWindowAccount(hDlg);
+ MailParam->mail = ActualMail;
+ mir_forkthread(ShowEmailThread, MailParam);
+ }
+ }
+ }
+ break;
+
+ case WM_SYSCOMMAND:
+ if (nullptr == (ActualAccount = GetWindowAccount(hDlg)))
+ break;
+ switch (wParam) {
+ case SC_CLOSE:
+ DestroyWindow(hDlg);
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ if (nullptr == (ActualAccount = GetWindowAccount(hDlg)))
+ break;
+
+ switch (LOWORD(wParam)) {
+ case IDC_BTNCHECKALL:
+ ListView_SetItemState(GetDlgItem(hDlg, IDC_LISTMAILS), -1, 0, LVIS_SELECTED); // deselect all items
+ ListView_SetItemState(GetDlgItem(hDlg, IDC_LISTMAILS), -1, LVIS_SELECTED, LVIS_SELECTED);
+ Items = ListView_GetItemCount(GetDlgItem(hDlg, IDC_LISTMAILS));
+ ListView_RedrawItems(GetDlgItem(hDlg, IDC_LISTMAILS), 0, Items);
+ UpdateWindow(GetDlgItem(hDlg, IDC_LISTMAILS));
+ SetFocus(GetDlgItem(hDlg, IDC_LISTMAILS));
+ break;
+
+ case IDC_BTNOK:
+ DestroyWindow(hDlg);
+ break;
+
+ case IDC_BTNAPP:
+ {
+ PROCESS_INFORMATION pi;
+ STARTUPINFOW si;
+
+ memset(&si, 0, sizeof(si));
+ si.cb = sizeof(si);
+
+ if (WAIT_OBJECT_0 == WaitToReadFcn(ActualAccount->AccountAccessSO)) {
+ if (ActualAccount->NewMailN.App != nullptr) {
+ wchar_t *Command;
+ if (ActualAccount->NewMailN.AppParam != nullptr)
+ Command = new wchar_t[mir_wstrlen(ActualAccount->NewMailN.App) + mir_wstrlen(ActualAccount->NewMailN.AppParam) + 6];
+ else
+ Command = new wchar_t[mir_wstrlen(ActualAccount->NewMailN.App) + 6];
+
+ if (Command != nullptr) {
+ mir_wstrcpy(Command, L"\"");
+ mir_wstrcat(Command, ActualAccount->NewMailN.App);
+ mir_wstrcat(Command, L"\" ");
+ if (ActualAccount->NewMailN.AppParam != nullptr)
+ mir_wstrcat(Command, ActualAccount->NewMailN.AppParam);
+ CreateProcessW(nullptr, Command, nullptr, nullptr, FALSE, NORMAL_PRIORITY_CLASS, nullptr, nullptr, &si, &pi);
+ delete[] Command;
+ }
+ }
+
+ ReadDoneFcn(ActualAccount->AccountAccessSO);
+ }
+
+ if (!(GetKeyState(VK_SHIFT) & 0x8000) && !(GetKeyState(VK_CONTROL) & 0x8000))
+ DestroyWindow(hDlg);
+ }
+ break;
+
+ case IDC_BTNDEL:
+ {
+ HYAMNMAIL ActualMail;
+ uint32_t Total = 0;
+
+ // we use event to signal, that running thread has all needed stack parameters copied
+ HANDLE ThreadRunningEV = CreateEvent(nullptr, FALSE, FALSE, nullptr);
+ if (ThreadRunningEV == nullptr)
+ break;
+
+ Items = ListView_GetItemCount(GetDlgItem(hDlg, IDC_LISTMAILS));
+
+ LVITEM item;
+ item.stateMask = 0xFFFFFFFF;
+
+ if (WAIT_OBJECT_0 == WaitToWriteFcn(ActualAccount->MessagesAccessSO)) {
+ for (int i = 0; i < Items; i++) {
+ item.iItem = i;
+ item.iSubItem = 0;
+ item.mask = LVIF_PARAM | LVIF_STATE;
+ item.stateMask = 0xFFFFFFFF;
+ ListView_GetItem(GetDlgItem(hDlg, IDC_LISTMAILS), &item);
+ ActualMail = (HYAMNMAIL)item.lParam;
+ if (nullptr == ActualMail)
+ break;
+ if (item.state & LVIS_SELECTED) {
+ ActualMail->Flags |= YAMN_MSG_USERDELETE; //set to mail we are going to delete it
+ Total++;
+ }
+ }
+
+ // Enable write-access to mails
+ WriteDoneFcn(ActualAccount->MessagesAccessSO);
+
+ if (Total) {
+ wchar_t DeleteMsg[1024];
+
+ mir_snwprintf(DeleteMsg, TranslateT("Do you really want to delete %d selected mails?"), Total);
+ if (IDOK == MessageBox(hDlg, DeleteMsg, TranslateT("Delete confirmation"), MB_OKCANCEL | MB_ICONWARNING)) {
+ struct DeleteParam ParamToDeleteMails = {YAMN_DELETEVERSION, ThreadRunningEV, ActualAccount, nullptr};
+
+ // Find if there's mail marked to delete, which was deleted before
+ if (WAIT_OBJECT_0 == WaitToWriteFcn(ActualAccount->MessagesAccessSO)) {
+ for (ActualMail = (HYAMNMAIL)ActualAccount->Mails; ActualMail != nullptr; ActualMail = ActualMail->Next) {
+ if ((ActualMail->Flags & YAMN_MSG_DELETED) && ((ActualMail->Flags & YAMN_MSG_USERDELETE))) //if selected mail was already deleted
+ {
+ DeleteMessageFromQueueFcn((HYAMNMAIL *)&ActualAccount->Mails, ActualMail, 1);
+ CallService(MS_YAMN_DELETEACCOUNTMAIL, (WPARAM)ActualAccount->Plugin, (LPARAM)ActualMail); //delete it from memory
+ continue;
+ }
+ }
+ // Set flag to marked mails that they can be deleted
+ SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails, YAMN_MSG_DISPLAY | YAMN_MSG_USERDELETE, 0, YAMN_MSG_DELETEOK, 1);
+ // Create new thread which deletes marked mails.
+ HANDLE NewThread = mir_forkthread(ActualAccount->Plugin->Fcn->DeleteMailsFcnPtr, &ParamToDeleteMails);
+ if (NewThread != nullptr)
+ WaitForSingleObject(ThreadRunningEV, INFINITE);
+
+ // Enable write-access to mails
+ WriteDoneFcn(ActualAccount->MessagesAccessSO);
+ }
+ }
+ else //else mark messages that they are not to be deleted
+ SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails, YAMN_MSG_DISPLAY | YAMN_MSG_USERDELETE, 0, YAMN_MSG_USERDELETE, 0);
+ }
+ }
+ CloseHandle(ThreadRunningEV);
+ if (g_plugin.getByte(YAMN_CLOSEDELETE, 0))
+ DestroyWindow(hDlg);
+ }
+ break;
+ }
+ break;
+
+ case WM_SIZE:
+ if (wParam == SIZE_RESTORED) {
+ LONG x = LOWORD(lParam); //((LPRECT)lParam)->right-((LPRECT)lParam)->left;
+ LONG y = HIWORD(lParam); //((LPRECT)lParam)->bottom-((LPRECT)lParam)->top;
+ MoveWindow(GetDlgItem(hDlg, IDC_BTNDEL), 5, y - 5 - 25, (x - 20) / 3, 25, TRUE); //where to put DELETE button while resizing
+ MoveWindow(GetDlgItem(hDlg, IDC_BTNCHECKALL), 10 + (x - 20) / 3, y - 5 - 25, (x - 20) / 6, 25, TRUE); //where to put CHECK ALL button while resizing
+ MoveWindow(GetDlgItem(hDlg, IDC_BTNAPP), 15 + (x - 20) / 3 + (x - 20) / 6, y - 5 - 25, (x - 20) / 3, 25, TRUE); //where to put RUN APP button while resizing
+ MoveWindow(GetDlgItem(hDlg, IDC_BTNOK), 20 + 2 * (x - 20) / 3 + (x - 20) / 6, y - 5 - 25, (x - 20) / 6, 25, TRUE); //where to put OK button while resizing
+ MoveWindow(GetDlgItem(hDlg, IDC_LISTMAILS), 5, 5, x - 10, y - 55, TRUE); //where to put list mail window while resizing
+ MoveWindow(GetDlgItem(hDlg, IDC_STSTATUS), 5, y - 5 - 45, x - 10, 15, TRUE); //where to put account status text while resizing
+ }
+ return 0;
+
+ case WM_GETMINMAXINFO:
+ ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = MAILBROWSER_MINXSIZE;
+ ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = MAILBROWSER_MINYSIZE;
+ return 0;
+
+ case WM_TIMER:
+ {
+ NOTIFYICONDATA nid;
+ struct CMailWinUserInfo *mwui = (struct CMailWinUserInfo *)GetWindowLongPtr(hDlg, DWLP_USER);
+
+ memset(&nid, 0, sizeof(nid));
+ nid.cbSize = sizeof(NOTIFYICONDATA);
+ nid.hWnd = hDlg;
+ nid.uID = 0;
+ nid.uFlags = NIF_ICON;
+ if (mwui->TrayIconState == 0)
+ nid.hIcon = g_plugin.getIcon(IDI_CHECKMAIL);
+ else
+ nid.hIcon = g_plugin.getIcon(IDI_NEWMAIL);
+ Shell_NotifyIcon(NIM_MODIFY, &nid);
+ mwui->TrayIconState = !mwui->TrayIconState;
+ // UpdateWindow(hDlg);
+ }
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->idFrom) {
+ case IDC_LISTMAILS:
+ switch (((LPNMHDR)lParam)->code) {
+ case NM_DBLCLK:
+ SendMessage(hDlg, WM_YAMN_SHOWSELECTED, 0, 0);
+ break;
+
+ case LVN_COLUMNCLICK:
+ if (nullptr != (ActualAccount = GetWindowAccount(hDlg))) {
+ NM_LISTVIEW *pNMListView = (NM_LISTVIEW *)lParam;
+ if (WAIT_OBJECT_0 == WaitToReadFcn(ActualAccount->AccountAccessSO)) {
+ switch ((int)pNMListView->iSubItem) {
+ case 0:
+ bFrom = !bFrom;
+ break;
+ case 1:
+ bSub = !bSub;
+ break;
+ case 2:
+ bSize = !bSize;
+ break;
+ case 3:
+ bDate = !bDate;
+ break;
+ default:
+ break;
+ }
+ ListView_SortItems(pNMListView->hdr.hwndFrom, ListViewCompareProc, pNMListView->iSubItem);
+ ReadDoneFcn(ActualAccount->AccountAccessSO);
+ }
+ }
+ break;
+
+ case NM_CUSTOMDRAW:
+ {
+ LPNMLVCUSTOMDRAW cd = (LPNMLVCUSTOMDRAW)lParam;
+ LONG_PTR PaintCode;
+
+ if (nullptr == (ActualAccount = GetWindowAccount(hDlg)))
+ break;
+
+ switch (cd->nmcd.dwDrawStage) {
+ case CDDS_PREPAINT:
+ PaintCode = CDRF_NOTIFYITEMDRAW;
+ break;
+ case CDDS_ITEMPREPAINT:
+ PaintCode = CDRF_NOTIFYSUBITEMDRAW;
+ break;
+ case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
+ {
+ BOOL umma;
+ {
+ struct CMailWinUserInfo *mwui = (struct CMailWinUserInfo *)GetWindowLongPtr(hDlg, DWLP_USER);
+ umma = mwui->UpdateMailsMessagesAccess;
+ }
+ HYAMNMAIL ActualMail = (HYAMNMAIL)cd->nmcd.lItemlParam;
+ if (!ActualMail)
+ ActualMail = (HYAMNMAIL)readItemLParam(cd->nmcd.hdr.hwndFrom, cd->nmcd.dwItemSpec);
+
+ if (!umma)
+ if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->MessagesAccessSO))
+ return 0;
+
+ switch (ActualMail->Flags & YAMN_MSG_SPAMMASK) {
+ case YAMN_MSG_SPAML1:
+ case YAMN_MSG_SPAML2:
+ cd->clrText = RGB(150, 150, 150);
+ break;
+ case YAMN_MSG_SPAML3:
+ cd->clrText = RGB(200, 200, 200);
+ cd->clrTextBk = RGB(160, 160, 160);
+ break;
+ case 0:
+ if (cd->nmcd.dwItemSpec & 1)
+ cd->clrTextBk = RGB(230, 230, 230);
+ break;
+ default:
+ break;
+ }
+ if (ActualMail->Flags & YAMN_MSG_UNSEEN)
+ cd->clrTextBk = RGB(220, 235, 250);
+ PaintCode = CDRF_DODEFAULT;
+
+ if (!umma)
+ ReadDoneFcn(ActualAccount->MessagesAccessSO);
+ break;
+ }
+ default:
+ PaintCode = 0;
+ }
+ SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PaintCode);
+ return 1;
+ }
+ }
+ }
+ break;
+
+ case WM_CONTEXTMENU:
+ if (GetWindowLongPtr((HWND)wParam, GWLP_ID) == IDC_LISTMAILS) {
+ //MessageBox(0,"LISTHEADERS","Debug",0);
+ HWND hList = GetDlgItem(hDlg, IDC_LISTMAILS);
+ POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
+ if (pt.x == -1) pt.x = 0;
+ if (pt.y == -1) pt.y = 0;
+ if (int numRows = ListView_GetItemCount(hList)) {
+ HMENU hMenu = CreatePopupMenu();
+ AppendMenu(hMenu, MF_STRING, (UINT_PTR)1, TranslateT("Copy Selected"));
+ AppendMenu(hMenu, MF_STRING, (UINT_PTR)2, TranslateT("Copy All"));
+ AppendMenu(hMenu, MF_SEPARATOR, 0, nullptr);
+ AppendMenu(hMenu, MF_STRING, (UINT_PTR)0, TranslateT("Cancel"));
+ int nReturnCmd = TrackPopupMenu(hMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hDlg, nullptr);
+ DestroyMenu(hMenu);
+ if (nReturnCmd > 0) {
+ int courRow = 0;
+ size_t sizeNeeded = 0;
+ wchar_t from[128] = {0}, subject[256] = {0}, size[16] = {0}, date[64] = {0};
+ for (courRow = 0; courRow < numRows; courRow++) {
+ if ((nReturnCmd == 1) && (ListView_GetItemState(hList, courRow, LVIS_SELECTED) == 0)) continue;
+ ListView_GetItemText(hList, courRow, 0, from, _countof(from));
+ ListView_GetItemText(hList, courRow, 1, subject, _countof(subject));
+ ListView_GetItemText(hList, courRow, 2, size, _countof(size));
+ ListView_GetItemText(hList, courRow, 3, date, _countof(date));
+ sizeNeeded += 5 + mir_wstrlen(from) + mir_wstrlen(subject) + mir_wstrlen(size) + mir_wstrlen(date);
+ }
+ if (sizeNeeded && OpenClipboard(hDlg)) {
+ EmptyClipboard();
+ HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE, (sizeNeeded + 1) * sizeof(wchar_t));
+ wchar_t *buff = (wchar_t *)GlobalLock(hData);
+ int courPos = 0;
+ for (courRow = 0; courRow < numRows; courRow++) {
+ if ((nReturnCmd == 1) && (ListView_GetItemState(hList, courRow, LVIS_SELECTED) == 0)) continue;
+ ListView_GetItemText(hList, courRow, 0, from, _countof(from));
+ ListView_GetItemText(hList, courRow, 1, subject, _countof(subject));
+ ListView_GetItemText(hList, courRow, 2, size, _countof(size));
+ ListView_GetItemText(hList, courRow, 3, date, _countof(date));
+ courPos += mir_snwprintf(&buff[courPos], sizeNeeded + 1, L"%s\t%s\t%s\t%s\r\n", from, subject, size, date);
+ }
+ GlobalUnlock(hData);
+
+ SetClipboardData(CF_UNICODETEXT, hData);
+
+ CloseClipboard();
+ }
+ }
+ }
+ }
+ break; // just in case
+ }
+ return 0;
+}
+
+LRESULT CALLBACK ListViewSubclassProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HWND hwndParent = GetParent(hDlg);
+
+ switch (msg) {
+ case WM_GETDLGCODE:
+ {
+ LPMSG lpmsg = (LPMSG)lParam;
+ if (lpmsg != nullptr) {
+ if (lpmsg->message == WM_KEYDOWN
+ && lpmsg->wParam == VK_RETURN)
+ return DLGC_WANTALLKEYS;
+ }
+ }
+ break;
+
+ case WM_KEYDOWN:
+ {
+ BOOL isCtrl = GetKeyState(VK_CONTROL) & 0x8000;
+ BOOL isShift = GetKeyState(VK_SHIFT) & 0x8000;
+ BOOL isAlt = GetKeyState(VK_MENU) & 0x8000;
+
+ switch (wParam) {
+ case 'A': // ctrl-a
+ if (!isAlt && !isShift && isCtrl) SendMessage(hwndParent, WM_COMMAND, IDC_BTNCHECKALL, 0);
+ break;
+ case VK_RETURN:
+ case VK_SPACE:
+ if (!isAlt && !isShift && !isCtrl) SendMessage(hwndParent, WM_YAMN_SHOWSELECTED, 0, 0);
+ break;
+ case VK_DELETE:
+ SendMessage(hwndParent, WM_COMMAND, IDC_BTNDEL, 0);
+ break;
+ }
+ }
+ break;
+ }
+ return mir_callNextSubclass(hDlg, ListViewSubclassProc, msg, wParam, lParam);
+}
+
+void __cdecl MailBrowser(void *Param)
+{
+ MSG msg;
+
+ HWND hMailBrowser;
+ BOOL WndFound = FALSE;
+
+ struct MailBrowserWinParam MyParam = *(struct MailBrowserWinParam *)Param;
+ CAccount *ActualAccount = MyParam.account;
+ SCIncFcn(ActualAccount->UsingThreads);
+
+ // we will not use params in stack anymore
+ SetEvent(MyParam.ThreadRunningEV);
+
+ __try {
+ if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO))
+ return;
+
+ if (!(ActualAccount->AbilityFlags & YAMN_ACC_BROWSE)) {
+ MyParam.nflags = MyParam.nflags & ~YAMN_ACC_MSG;
+ MyParam.nnflags = MyParam.nnflags & ~YAMN_ACC_MSG;
+ }
+
+ if (!(ActualAccount->AbilityFlags & YAMN_ACC_POPUP))
+ MyParam.nflags = MyParam.nflags & ~YAMN_ACC_POP;
+
+ ReadDoneFcn(ActualAccount->AccountAccessSO);
+
+ if (nullptr != (hMailBrowser = WindowList_Find(YAMNVar.NewMailAccountWnd, (UINT_PTR)ActualAccount)))
+ WndFound = TRUE;
+
+ if ((hMailBrowser == nullptr) && ((MyParam.nflags & YAMN_ACC_MSG) || (MyParam.nflags & YAMN_ACC_ICO) || (MyParam.nnflags & YAMN_ACC_MSG))) {
+ hMailBrowser = CreateDialogParamW(g_plugin.getInst(), MAKEINTRESOURCEW(IDD_DLGVIEWMESSAGES), nullptr, DlgProcYAMNMailBrowser, (LPARAM)&MyParam);
+ Window_SetIcon_IcoLib(hMailBrowser, g_plugin.getIconHandle(IDI_NEWMAIL));
+ MoveWindow(hMailBrowser, PosX, PosY, SizeX, SizeY, TRUE);
+ }
+
+ if (hMailBrowser != nullptr) {
+ struct CChangeContent Params = {MyParam.nflags, MyParam.nnflags}; //if this thread created window, just post message to update mails
+
+ SendMessage(hMailBrowser, WM_YAMN_CHANGECONTENT, (WPARAM)ActualAccount, (LPARAM)&Params); //we ensure this will do the thread who created the browser window
+ }
+ else
+ UpdateMails(nullptr, ActualAccount, MyParam.nflags, MyParam.nnflags); //update mails without displaying or refreshing any window
+
+ if ((hMailBrowser != nullptr) && !WndFound) { //we process message loop only for thread that created window
+ while (GetMessage(&msg, nullptr, 0, 0)) {
+ if (hMailBrowser == nullptr || !IsDialogMessage(hMailBrowser, &msg)) { /* Wine fix. */
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+ }
+
+ if ((!WndFound) && (ActualAccount->Plugin->Fcn != nullptr) && (ActualAccount->Plugin->Fcn->WriteAccountsFcnPtr != nullptr) && ActualAccount->AbleToWork)
+ ActualAccount->Plugin->Fcn->WriteAccountsFcnPtr();
+ }
+ __finally {
+ SCDecFcn(ActualAccount->UsingThreads);
+ }
+}
+
+INT_PTR RunMailBrowserSvc(WPARAM wParam, LPARAM lParam)
+{
+ PYAMN_MAILBROWSERPARAM Param = (PYAMN_MAILBROWSERPARAM)wParam;
+
+ if ((uint32_t)lParam != YAMN_MAILBROWSERVERSION)
+ return 0;
+
+ //an event for successfull copy parameters to which point a pointer in stack for new thread
+ HANDLE ThreadRunningEV = CreateEvent(nullptr, FALSE, FALSE, nullptr);
+ Param->ThreadRunningEV = ThreadRunningEV;
+
+ HANDLE NewThread = mir_forkthread(MailBrowser, Param);
+ if (NewThread != nullptr)
+ WaitForSingleObject(ThreadRunningEV, INFINITE);
+
+ CloseHandle(ThreadRunningEV);
+ return 1;
+}
diff --git a/protocols/YAMN/src/debug.cpp b/protocols/YAMN/src/debug.cpp
index 1fc41adc19..65322366ab 100644
--- a/protocols/YAMN/src/debug.cpp
+++ b/protocols/YAMN/src/debug.cpp
@@ -1,111 +1,111 @@
-/*
- * YAMN plugin main file
- * Miranda homepage: http://miranda-icq.sourceforge.net/
- *
- * Debug functions used in DEBUG release (you need to global #define DEBUG to get debug version)
- *
- * (c) majvan 2002-2004
- */
-
-#include "stdafx.h"
-
-#ifdef _DEBUG
-
-//--------------------------------------------------------------------------------------------------
-//--------------------------------------------------------------------------------------------------
-
-wchar_t DebugUserDirectory[MAX_PATH] = L".";
-CRITICAL_SECTION FileAccessCS;
-
-#ifdef DEBUG_COMM
-wchar_t DebugCommFileName2[]=L"%s\\yamn-debug.comm.log";
-HANDLE CommFile;
-#endif
-
-#ifdef DEBUG_DECODE
-wchar_t DebugDecodeFileName2[]=L"%s\\yamn-debug.decode.log";
-HANDLE DecodeFile;
-#endif
-
-//--------------------------------------------------------------------------------------------------
-//--------------------------------------------------------------------------------------------------
-
-void InitDebug()
-{
-#if defined (DEBUG_COMM) || defined (DEBUG_DECODE)
- wchar_t DebugFileName[MAX_PATH];
-#endif
- InitializeCriticalSection(&FileAccessCS);
-
-#ifdef DEBUG_COMM
- mir_snwprintf(DebugFileName, DebugCommFileName2, DebugUserDirectory);
-
- CommFile=CreateFile(DebugFileName,GENERIC_WRITE,FILE_SHARE_WRITE|FILE_SHARE_READ,NULL,CREATE_ALWAYS,0,NULL);
- DebugLog(CommFile,"Communication debug file created by %s\n",YAMN_VER);
-#endif
-
-#ifdef DEBUG_DECODE
- mir_snwprintf(DebugFileName, DebugDecodeFileName2, DebugUserDirectory);
-
- DecodeFile=CreateFile(DebugFileName,GENERIC_WRITE,FILE_SHARE_WRITE|FILE_SHARE_READ,NULL,CREATE_ALWAYS,0,NULL);
- DebugLog(DecodeFile,"Decoding kernel debug file created by %s\n",YAMN_VER);
-#endif
-}
-
-void UnInitDebug()
-{
- DeleteCriticalSection(&FileAccessCS);
-#ifdef DEBUG_COMM
- DebugLog(CommFile,"File is being closed normally.");
- CloseHandle(CommFile);
-#endif
-#ifdef DEBUG_DECODE
- DebugLog(DecodeFile,"File is being closed normally.");
- CloseHandle(DecodeFile);
-#endif
-}
-
-
-void DebugLog(HANDLE File,const char *fmt,...)
-{
- char *str;
- char tids[32];
- va_list vararg;
- int strsize;
- DWORD Written;
-
- va_start(vararg,fmt);
- str=(char *)malloc(strsize=65536);
- mir_snprintf(tids, "[%x]",GetCurrentThreadId());
- while(mir_vsnprintf(str, strsize, fmt, vararg)==-1)
- str=(char *)realloc(str,strsize+=65536);
- va_end(vararg);
- EnterCriticalSection(&FileAccessCS);
- WriteFile(File,tids,(uint32_t)mir_strlen(tids),&Written,nullptr);
- WriteFile(File,str,(uint32_t)mir_strlen(str),&Written,nullptr);
- LeaveCriticalSection(&FileAccessCS);
- free(str);
-}
-
-void DebugLogW(HANDLE File,const wchar_t *fmt,...)
-{
- wchar_t *str;
- char tids[32];
- va_list vararg;
- int strsize;
- DWORD Written;
-
- va_start(vararg,fmt);
- str=(wchar_t *)malloc((strsize=65536)*sizeof(wchar_t));
- mir_snprintf(tids, "[%x]",GetCurrentThreadId());
- while(mir_vsnwprintf(str, strsize, fmt, vararg)==-1)
- str=(wchar_t *)realloc(str,(strsize+=65536)*sizeof(wchar_t));
- va_end(vararg);
- EnterCriticalSection(&FileAccessCS);
- WriteFile(File,tids,(uint32_t)mir_strlen(tids),&Written,nullptr);
- WriteFile(File,str,(uint32_t)mir_wstrlen(str)*sizeof(wchar_t),&Written,nullptr);
- LeaveCriticalSection(&FileAccessCS);
- free(str);
-}
-
+/*
+ * YAMN plugin main file
+ * Miranda homepage: http://miranda-icq.sourceforge.net/
+ *
+ * Debug functions used in DEBUG release (you need to global #define DEBUG to get debug version)
+ *
+ * (c) majvan 2002-2004
+ */
+
+#include "stdafx.h"
+
+#ifdef _DEBUG
+
+//--------------------------------------------------------------------------------------------------
+//--------------------------------------------------------------------------------------------------
+
+wchar_t DebugUserDirectory[MAX_PATH] = L".";
+CRITICAL_SECTION FileAccessCS;
+
+#ifdef DEBUG_COMM
+wchar_t DebugCommFileName2[]=L"%s\\yamn-debug.comm.log";
+HANDLE CommFile;
+#endif
+
+#ifdef DEBUG_DECODE
+wchar_t DebugDecodeFileName2[]=L"%s\\yamn-debug.decode.log";
+HANDLE DecodeFile;
+#endif
+
+//--------------------------------------------------------------------------------------------------
+//--------------------------------------------------------------------------------------------------
+
+void InitDebug()
+{
+#if defined (DEBUG_COMM) || defined (DEBUG_DECODE)
+ wchar_t DebugFileName[MAX_PATH];
+#endif
+ InitializeCriticalSection(&FileAccessCS);
+
+#ifdef DEBUG_COMM
+ mir_snwprintf(DebugFileName, DebugCommFileName2, DebugUserDirectory);
+
+ CommFile=CreateFile(DebugFileName,GENERIC_WRITE,FILE_SHARE_WRITE|FILE_SHARE_READ,NULL,CREATE_ALWAYS,0,NULL);
+ DebugLog(CommFile,"Communication debug file created by %s\n",YAMN_VER);
+#endif
+
+#ifdef DEBUG_DECODE
+ mir_snwprintf(DebugFileName, DebugDecodeFileName2, DebugUserDirectory);
+
+ DecodeFile=CreateFile(DebugFileName,GENERIC_WRITE,FILE_SHARE_WRITE|FILE_SHARE_READ,NULL,CREATE_ALWAYS,0,NULL);
+ DebugLog(DecodeFile,"Decoding kernel debug file created by %s\n",YAMN_VER);
+#endif
+}
+
+void UnInitDebug()
+{
+ DeleteCriticalSection(&FileAccessCS);
+#ifdef DEBUG_COMM
+ DebugLog(CommFile,"File is being closed normally.");
+ CloseHandle(CommFile);
+#endif
+#ifdef DEBUG_DECODE
+ DebugLog(DecodeFile,"File is being closed normally.");
+ CloseHandle(DecodeFile);
+#endif
+}
+
+
+void DebugLog(HANDLE File,const char *fmt,...)
+{
+ char *str;
+ char tids[32];
+ va_list vararg;
+ int strsize;
+ DWORD Written;
+
+ va_start(vararg,fmt);
+ str=(char *)malloc(strsize=65536);
+ mir_snprintf(tids, "[%x]",GetCurrentThreadId());
+ while(mir_vsnprintf(str, strsize, fmt, vararg)==-1)
+ str=(char *)realloc(str,strsize+=65536);
+ va_end(vararg);
+ EnterCriticalSection(&FileAccessCS);
+ WriteFile(File,tids,(uint32_t)mir_strlen(tids),&Written,nullptr);
+ WriteFile(File,str,(uint32_t)mir_strlen(str),&Written,nullptr);
+ LeaveCriticalSection(&FileAccessCS);
+ free(str);
+}
+
+void DebugLogW(HANDLE File,const wchar_t *fmt,...)
+{
+ wchar_t *str;
+ char tids[32];
+ va_list vararg;
+ int strsize;
+ DWORD Written;
+
+ va_start(vararg,fmt);
+ str=(wchar_t *)malloc((strsize=65536)*sizeof(wchar_t));
+ mir_snprintf(tids, "[%x]",GetCurrentThreadId());
+ while(mir_vsnwprintf(str, strsize, fmt, vararg)==-1)
+ str=(wchar_t *)realloc(str,(strsize+=65536)*sizeof(wchar_t));
+ va_end(vararg);
+ EnterCriticalSection(&FileAccessCS);
+ WriteFile(File,tids,(uint32_t)mir_strlen(tids),&Written,nullptr);
+ WriteFile(File,str,(uint32_t)mir_wstrlen(str)*sizeof(wchar_t),&Written,nullptr);
+ LeaveCriticalSection(&FileAccessCS);
+ free(str);
+}
+
#endif //ifdef DEBUG \ No newline at end of file
diff --git a/protocols/YAMN/src/debug.h b/protocols/YAMN/src/debug.h
index a13ac952b0..e2e8e3e506 100644
--- a/protocols/YAMN/src/debug.h
+++ b/protocols/YAMN/src/debug.h
@@ -1,50 +1,50 @@
-#ifndef __DEBUG_H
-#define __DEBUG_H
-
-#ifdef _DEBUG
-
-//#define DEBUG_COMM //debug communiation to a file
-//#define DEBUG_DECODE //debug header decoding to a file
-//#define DEBUG_DECODECODEPAGE //add info about codepage used in conversion
-//#define DEBUG_DECODEBASE64 //add info about base64 result
-//#define DEBUG_DECODEQUOTED //add info about quoted printable result
-//#define DEBUG_FILEREAD //debug file reading to message boxes
-//#define DEBUG_FILEREADMESSAGES //debug file reading messages to message boxes
-
-void DebugLog(HANDLE,const char *fmt,...);
-void DebugLogW(HANDLE File,const wchar_t *fmt,...);
-
-#ifdef DEBUG_SYNCHRO
-// Used for synchronization debug
-extern HANDLE SynchroFile;
-#endif
-
-#ifdef DEBUG_COMM
-// Used for communication debug
-extern HANDLE CommFile;
-#endif
-
-#ifdef DEBUG_DECODE
-// Used for decoding debug
-extern HANDLE DecodeFile;
-#endif
-
-#if defined(DEBUG_FILEREAD) || defined(DEBUG_FILEREADMESSAGES)
-uint32_t ReadStringFromMemory(char **Parser,char *End,char **StoreTo,char *DebugString);
-
-uint32_t ReadStringFromMemoryW(char **Parser,wchar_t *End,char **StoreTo,wchar_t *DebugString);
-
-#else
-uint32_t ReadStringFromMemory(char **Parser,char *End,char **StoreTo);
-
-uint32_t ReadStringFromMemoryW(wchar_t **Parser,wchar_t *End,wchar_t **StoreTo);
-
-#endif
-
-//#ifdef DEBUG_ACCOUNTS
-//int GetAccounts();
-//void WriteAccounts();
-//#endif
-
-#endif //YAMN_DEBUG
-#endif //_DEBUG_H
+#ifndef __DEBUG_H
+#define __DEBUG_H
+
+#ifdef _DEBUG
+
+//#define DEBUG_COMM //debug communiation to a file
+//#define DEBUG_DECODE //debug header decoding to a file
+//#define DEBUG_DECODECODEPAGE //add info about codepage used in conversion
+//#define DEBUG_DECODEBASE64 //add info about base64 result
+//#define DEBUG_DECODEQUOTED //add info about quoted printable result
+//#define DEBUG_FILEREAD //debug file reading to message boxes
+//#define DEBUG_FILEREADMESSAGES //debug file reading messages to message boxes
+
+void DebugLog(HANDLE,const char *fmt,...);
+void DebugLogW(HANDLE File,const wchar_t *fmt,...);
+
+#ifdef DEBUG_SYNCHRO
+// Used for synchronization debug
+extern HANDLE SynchroFile;
+#endif
+
+#ifdef DEBUG_COMM
+// Used for communication debug
+extern HANDLE CommFile;
+#endif
+
+#ifdef DEBUG_DECODE
+// Used for decoding debug
+extern HANDLE DecodeFile;
+#endif
+
+#if defined(DEBUG_FILEREAD) || defined(DEBUG_FILEREADMESSAGES)
+uint32_t ReadStringFromMemory(char **Parser,char *End,char **StoreTo,char *DebugString);
+
+uint32_t ReadStringFromMemoryW(char **Parser,wchar_t *End,char **StoreTo,wchar_t *DebugString);
+
+#else
+uint32_t ReadStringFromMemory(char **Parser,char *End,char **StoreTo);
+
+uint32_t ReadStringFromMemoryW(wchar_t **Parser,wchar_t *End,wchar_t **StoreTo);
+
+#endif
+
+//#ifdef DEBUG_ACCOUNTS
+//int GetAccounts();
+//void WriteAccounts();
+//#endif
+
+#endif //YAMN_DEBUG
+#endif //_DEBUG_H
diff --git a/protocols/YAMN/src/filterplugin.cpp b/protocols/YAMN/src/filterplugin.cpp
index 1d55f3a9c1..451ea155aa 100644
--- a/protocols/YAMN/src/filterplugin.cpp
+++ b/protocols/YAMN/src/filterplugin.cpp
@@ -1,169 +1,169 @@
-/*
- * YAMN plugin export functions for filtering
- *
- * (c) majvan 2002-2004
- */
-
-#include "stdafx.h"
-
- //--------------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------------
-
-PYAMN_FILTERPLUGINQUEUE FirstFilterPlugin = nullptr;
-
-INT_PTR RegisterFilterPluginSvc(WPARAM, LPARAM);
-
-//Removes plugin from queue and deletes its structures
-INT_PTR UnregisterFilterPlugin(HYAMNFILTERPLUGIN Plugin);
-
-INT_PTR UnregisterFilterPluginSvc(WPARAM wParam, LPARAM lParam);
-
-//Removes all filter plugins
-INT_PTR UnregisterFilterPlugins();
-
-INT_PTR FilterMailSvc(WPARAM, LPARAM);
-
-//Sets imported functions for an plugin and therefore it starts plugin to be registered and running
-// Plugin- plugin, which wants to set its functions
-// Importance- importance of plugin (see m_filterplugin.h)
-// YAMNFilterFcn- pointer to imported functions
-// YAMNfilterFcnVer- version of YAMN_FILTERIMPORTFCN, use YAMN_FILTERIMPORTFCNVERSION
-// returns nonzero if success
-int WINAPI SetFilterPluginFcnImportFcn(HYAMNFILTERPLUGIN Plugin, uint32_t Importance, PYAMN_FILTERIMPORTFCN YAMNFilterFcn, uint32_t YAMNFilterFcnVer);
-
-struct CExportedFunctions FilterPluginExportedFcn[] =
-{
- {YAMN_SETFILTERPLUGINFCNIMPORTID, (void *)SetFilterPluginFcnImportFcn},
-};
-
-struct CExportedServices FilterPluginExportedSvc[] =
-{
- {MS_YAMN_REGISTERFILTERPLUGIN, RegisterFilterPluginSvc},
- {MS_YAMN_UNREGISTERFILTERPLUGIN, UnregisterFilterPluginSvc},
-};
-
-//--------------------------------------------------------------------------------------------------
-//--------------------------------------------------------------------------------------------------
-
-INT_PTR RegisterFilterPluginSvc(WPARAM wParam, LPARAM lParam)
-{
- PYAMN_FILTERREGISTRATION Registration = (PYAMN_FILTERREGISTRATION)wParam;
- HYAMNFILTERPLUGIN Plugin;
-
- if (lParam != YAMN_FILTERREGISTRATIONVERSION)
- return 0;
- if ((Registration->Name == nullptr) || (Registration->Ver == nullptr))
- return NULL;
- if (nullptr == (Plugin = new YAMN_FILTERPLUGIN))
- return NULL;
-
- Plugin->PluginInfo = Registration;
- Plugin->FilterFcn = nullptr;
- return (INT_PTR)Plugin;
-}
-
-INT_PTR UnregisterFilterPlugin(HYAMNFILTERPLUGIN Plugin)
-{
- PYAMN_FILTERPLUGINQUEUE Parser, Found;
-
- if (FirstFilterPlugin->Plugin == Plugin) {
- Found = FirstFilterPlugin;
- FirstFilterPlugin = FirstFilterPlugin->Next;
- }
- else {
- for (Parser = FirstFilterPlugin; (Parser->Next != nullptr) && (Plugin != Parser->Next->Plugin); Parser = Parser->Next);
- if (Parser->Next != nullptr) {
- Found = Parser->Next;
- Parser->Next = Parser->Next->Next;
- }
- else
- Found = nullptr;
- }
- if (Found != nullptr) {
- if (Plugin->FilterFcn->UnLoadFcn != nullptr)
- Plugin->FilterFcn->UnLoadFcn((void *)nullptr);
-
- delete Found->Plugin;
- delete Found;
- return 1;
- }
-
- return 0;
-}
-
-INT_PTR UnregisterFilterPluginSvc(WPARAM wParam, LPARAM)
-{
- HYAMNFILTERPLUGIN Plugin = (HYAMNFILTERPLUGIN)wParam;
-
- mir_cslock lck(PluginRegCS);
- UnregisterFilterPlugin(Plugin);
- return 1;
-}
-
-INT_PTR UnregisterFilterPlugins()
-{
- mir_cslock lck(PluginRegCS);
-
- // We remove protocols from the protocol list
- while (FirstFilterPlugin != nullptr)
- UnregisterFilterPlugin(FirstFilterPlugin->Plugin);
- return 1;
-}
-
-int WINAPI SetFilterPluginFcnImportFcn(HYAMNFILTERPLUGIN Plugin, uint32_t Importance, PYAMN_FILTERIMPORTFCN YAMNFilterFcn, uint32_t YAMNFilterFcnVer)
-{
- PYAMN_FILTERPLUGINQUEUE Parser, Previous;
-
- if (YAMNFilterFcnVer != YAMN_FILTERIMPORTFCNVERSION)
- return 0;
- if (YAMNFilterFcn == nullptr)
- return 0;
-
- Plugin->Importance = Importance;
- Plugin->FilterFcn = YAMNFilterFcn;
-
- mir_cslock lck(PluginRegCS);
-
- // We add protocol to the protocol list
- for (Previous = nullptr, Parser = FirstFilterPlugin; Parser != nullptr && Parser->Next != nullptr && Parser->Plugin->Importance <= Importance; Previous = Parser, Parser = Parser->Next);
-
- if (Previous == nullptr) { //insert to the beginnig of queue
- FirstFilterPlugin = new YAMN_FILTERPLUGINQUEUE;
- FirstFilterPlugin->Plugin = Plugin;
- FirstFilterPlugin->Next = Parser;
- }
- else {
- Previous->Next = new YAMN_FILTERPLUGINQUEUE;
- Previous = Previous->Next; //leave previous, go to actual plugin
- Previous->Plugin = Plugin;
- Previous->Next = Parser; //and in actual plugin set, that next plugin is the one we insert in front of
- }
- return 1;
-}
-
-INT_PTR FilterMailSvc(WPARAM wParam, LPARAM lParam)
-{
- CAccount *Account = (CAccount *)wParam;
- HYAMNMAIL Mail = (HYAMNMAIL)lParam;
- PYAMN_FILTERPLUGINQUEUE ActualPlugin;
-
- mir_cslock lck(PluginRegCS);
- WaitToWriteFcn(Account->MessagesAccessSO);
-
- for (ActualPlugin = FirstFilterPlugin; ActualPlugin != nullptr; ActualPlugin = ActualPlugin->Next)
- if (ActualPlugin->Plugin->FilterFcn->FilterMailFcnPtr != nullptr)
- ActualPlugin->Plugin->FilterFcn->FilterMailFcnPtr(Account, YAMN_ACCOUNTVERSION, Mail, YAMN_MAILVERSION);
-
- Mail->Flags |= YAMN_MSG_FILTERED;
-
- //Set mail flags according to spamlevel settings
- if ((Mail->Flags & YAMN_MSG_SPAMMASK) > YAMN_MSG_SPAML1)
- Mail->Flags = Mail->Flags & ~(YAMN_MSG_BROWSER | YAMN_MSG_POPUP | YAMN_MSG_SYSTRAY | YAMN_MSG_SOUND | YAMN_MSG_APP | YAMN_MSG_NEVENT);
- if (YAMN_MSG_SPAML(Mail->Flags, YAMN_MSG_SPAML3) || YAMN_MSG_SPAML(Mail->Flags, YAMN_MSG_SPAML4))
- Mail->Flags = Mail->Flags | (YAMN_MSG_AUTODELETE | YAMN_MSG_DELETEOK); //set message to delete
- if (YAMN_MSG_SPAML(Mail->Flags, YAMN_MSG_SPAML3))
- Mail->Flags = Mail->Flags & ~(YAMN_MSG_MEMDELETE); //set message not to delete it immidiatelly from memory
-
- WriteDoneFcn(Account->MessagesAccessSO);
- return 1;
-}
+/*
+ * YAMN plugin export functions for filtering
+ *
+ * (c) majvan 2002-2004
+ */
+
+#include "stdafx.h"
+
+ //--------------------------------------------------------------------------------------------------
+ //--------------------------------------------------------------------------------------------------
+
+PYAMN_FILTERPLUGINQUEUE FirstFilterPlugin = nullptr;
+
+INT_PTR RegisterFilterPluginSvc(WPARAM, LPARAM);
+
+//Removes plugin from queue and deletes its structures
+INT_PTR UnregisterFilterPlugin(HYAMNFILTERPLUGIN Plugin);
+
+INT_PTR UnregisterFilterPluginSvc(WPARAM wParam, LPARAM lParam);
+
+//Removes all filter plugins
+INT_PTR UnregisterFilterPlugins();
+
+INT_PTR FilterMailSvc(WPARAM, LPARAM);
+
+//Sets imported functions for an plugin and therefore it starts plugin to be registered and running
+// Plugin- plugin, which wants to set its functions
+// Importance- importance of plugin (see m_filterplugin.h)
+// YAMNFilterFcn- pointer to imported functions
+// YAMNfilterFcnVer- version of YAMN_FILTERIMPORTFCN, use YAMN_FILTERIMPORTFCNVERSION
+// returns nonzero if success
+int WINAPI SetFilterPluginFcnImportFcn(HYAMNFILTERPLUGIN Plugin, uint32_t Importance, PYAMN_FILTERIMPORTFCN YAMNFilterFcn, uint32_t YAMNFilterFcnVer);
+
+struct CExportedFunctions FilterPluginExportedFcn[] =
+{
+ {YAMN_SETFILTERPLUGINFCNIMPORTID, (void *)SetFilterPluginFcnImportFcn},
+};
+
+struct CExportedServices FilterPluginExportedSvc[] =
+{
+ {MS_YAMN_REGISTERFILTERPLUGIN, RegisterFilterPluginSvc},
+ {MS_YAMN_UNREGISTERFILTERPLUGIN, UnregisterFilterPluginSvc},
+};
+
+//--------------------------------------------------------------------------------------------------
+//--------------------------------------------------------------------------------------------------
+
+INT_PTR RegisterFilterPluginSvc(WPARAM wParam, LPARAM lParam)
+{
+ PYAMN_FILTERREGISTRATION Registration = (PYAMN_FILTERREGISTRATION)wParam;
+ HYAMNFILTERPLUGIN Plugin;
+
+ if (lParam != YAMN_FILTERREGISTRATIONVERSION)
+ return 0;
+ if ((Registration->Name == nullptr) || (Registration->Ver == nullptr))
+ return NULL;
+ if (nullptr == (Plugin = new YAMN_FILTERPLUGIN))
+ return NULL;
+
+ Plugin->PluginInfo = Registration;
+ Plugin->FilterFcn = nullptr;
+ return (INT_PTR)Plugin;
+}
+
+INT_PTR UnregisterFilterPlugin(HYAMNFILTERPLUGIN Plugin)
+{
+ PYAMN_FILTERPLUGINQUEUE Parser, Found;
+
+ if (FirstFilterPlugin->Plugin == Plugin) {
+ Found = FirstFilterPlugin;
+ FirstFilterPlugin = FirstFilterPlugin->Next;
+ }
+ else {
+ for (Parser = FirstFilterPlugin; (Parser->Next != nullptr) && (Plugin != Parser->Next->Plugin); Parser = Parser->Next);
+ if (Parser->Next != nullptr) {
+ Found = Parser->Next;
+ Parser->Next = Parser->Next->Next;
+ }
+ else
+ Found = nullptr;
+ }
+ if (Found != nullptr) {
+ if (Plugin->FilterFcn->UnLoadFcn != nullptr)
+ Plugin->FilterFcn->UnLoadFcn((void *)nullptr);
+
+ delete Found->Plugin;
+ delete Found;
+ return 1;
+ }
+
+ return 0;
+}
+
+INT_PTR UnregisterFilterPluginSvc(WPARAM wParam, LPARAM)
+{
+ HYAMNFILTERPLUGIN Plugin = (HYAMNFILTERPLUGIN)wParam;
+
+ mir_cslock lck(PluginRegCS);
+ UnregisterFilterPlugin(Plugin);
+ return 1;
+}
+
+INT_PTR UnregisterFilterPlugins()
+{
+ mir_cslock lck(PluginRegCS);
+
+ // We remove protocols from the protocol list
+ while (FirstFilterPlugin != nullptr)
+ UnregisterFilterPlugin(FirstFilterPlugin->Plugin);
+ return 1;
+}
+
+int WINAPI SetFilterPluginFcnImportFcn(HYAMNFILTERPLUGIN Plugin, uint32_t Importance, PYAMN_FILTERIMPORTFCN YAMNFilterFcn, uint32_t YAMNFilterFcnVer)
+{
+ PYAMN_FILTERPLUGINQUEUE Parser, Previous;
+
+ if (YAMNFilterFcnVer != YAMN_FILTERIMPORTFCNVERSION)
+ return 0;
+ if (YAMNFilterFcn == nullptr)
+ return 0;
+
+ Plugin->Importance = Importance;
+ Plugin->FilterFcn = YAMNFilterFcn;
+
+ mir_cslock lck(PluginRegCS);
+
+ // We add protocol to the protocol list
+ for (Previous = nullptr, Parser = FirstFilterPlugin; Parser != nullptr && Parser->Next != nullptr && Parser->Plugin->Importance <= Importance; Previous = Parser, Parser = Parser->Next);
+
+ if (Previous == nullptr) { //insert to the beginnig of queue
+ FirstFilterPlugin = new YAMN_FILTERPLUGINQUEUE;
+ FirstFilterPlugin->Plugin = Plugin;
+ FirstFilterPlugin->Next = Parser;
+ }
+ else {
+ Previous->Next = new YAMN_FILTERPLUGINQUEUE;
+ Previous = Previous->Next; //leave previous, go to actual plugin
+ Previous->Plugin = Plugin;
+ Previous->Next = Parser; //and in actual plugin set, that next plugin is the one we insert in front of
+ }
+ return 1;
+}
+
+INT_PTR FilterMailSvc(WPARAM wParam, LPARAM lParam)
+{
+ CAccount *Account = (CAccount *)wParam;
+ HYAMNMAIL Mail = (HYAMNMAIL)lParam;
+ PYAMN_FILTERPLUGINQUEUE ActualPlugin;
+
+ mir_cslock lck(PluginRegCS);
+ WaitToWriteFcn(Account->MessagesAccessSO);
+
+ for (ActualPlugin = FirstFilterPlugin; ActualPlugin != nullptr; ActualPlugin = ActualPlugin->Next)
+ if (ActualPlugin->Plugin->FilterFcn->FilterMailFcnPtr != nullptr)
+ ActualPlugin->Plugin->FilterFcn->FilterMailFcnPtr(Account, YAMN_ACCOUNTVERSION, Mail, YAMN_MAILVERSION);
+
+ Mail->Flags |= YAMN_MSG_FILTERED;
+
+ //Set mail flags according to spamlevel settings
+ if ((Mail->Flags & YAMN_MSG_SPAMMASK) > YAMN_MSG_SPAML1)
+ Mail->Flags = Mail->Flags & ~(YAMN_MSG_BROWSER | YAMN_MSG_POPUP | YAMN_MSG_SYSTRAY | YAMN_MSG_SOUND | YAMN_MSG_APP | YAMN_MSG_NEVENT);
+ if (YAMN_MSG_SPAML(Mail->Flags, YAMN_MSG_SPAML3) || YAMN_MSG_SPAML(Mail->Flags, YAMN_MSG_SPAML4))
+ Mail->Flags = Mail->Flags | (YAMN_MSG_AUTODELETE | YAMN_MSG_DELETEOK); //set message to delete
+ if (YAMN_MSG_SPAML(Mail->Flags, YAMN_MSG_SPAML3))
+ Mail->Flags = Mail->Flags & ~(YAMN_MSG_MEMDELETE); //set message not to delete it immidiatelly from memory
+
+ WriteDoneFcn(Account->MessagesAccessSO);
+ return 1;
+}
diff --git a/protocols/YAMN/src/mails/decode.cpp b/protocols/YAMN/src/mails/decode.cpp
index 414edfce60..7306376c2e 100644
--- a/protocols/YAMN/src/mails/decode.cpp
+++ b/protocols/YAMN/src/mails/decode.cpp
@@ -1,534 +1,534 @@
-/*
- * This code implements decoding encoded MIME header in style
- * =?iso-8859-2?Q? "User using email in central Europe characters such as =E9" ?=
- *
- * (c) majvan 2002-2004
- */
-#include "../stdafx.h"
-//--------------------------------------------------------------------------------------------------
-//--------------------------------------------------------------------------------------------------
-
-struct _tcptable CodePageNamesAll[]=
-{
- { "ANSI", "",TRUE,CP_ACP},
- { "WINDOWS-1", "250",0,1250},
- { "WINDOWS-1", "251",0,1251},
- { "WINDOWS-1", "252",0,1252},
- { "WINDOWS-1", "253",0,1253},
- { "WINDOWS-1", "254",0,1254},
- { "WINDOWS-1", "255",0,1255},
- { "WINDOWS-1", "256",0,1256},
- { "WINDOWS-1", "257",0,1257},
- { "WINDOWS-1", "258",0,1258},
- { "CP1", "250",0,1250},
- { "CP1", "251",0,1251},
- { "CP1", "252",0,1252},
- { "CP1", "253",0,1253},
- { "CP1", "254",0,1254},
- { "CP1", "255",0,1255},
- { "CP1", "256",0,1256},
- { "CP1", "257",0,1257},
- { "CP1", "258",0,1258},
- { "ANSI-1", "250",0,1250},
- { "ANSI-1", "251",0,1251},
- { "ANSI-1", "252",0,1252},
- { "ANSI-1", "253",0,1253},
- { "ANSI-1", "254",0,1254},
- { "ANSI-1", "255",0,1255},
- { "ANSI-1", "256",0,1256},
- { "ANSI-1", "257",0,1257},
- { "ANSI-1", "258",0,1258},
- { "KOI8", "-R",0,20866},
- { "KOI8", "",0,20866},
- { "KOI8", "-U",0,21866},
- { "KOI8", "-RU",0,21866},
- { "US-", "ASCII",0,20127},
- { "CP", "367",0,20127},
- { "ASCII", "",0,20127},
- { "ASCII", "7",0,20127},
- { "ISO-8859", "-1",0,28591},
- { "ISO-8859", "-2",0,28592},
- { "ISO-8859", "-3",0,28593},
- { "ISO-8859", "-4",0,28594},
- { "ISO-8859", "-5",0,28595},
- { "ISO-8859", "-6",0,28596},
- { "ISO-8859", "-7",0,28597},
- { "ISO-8859", "-8",0,28598},
- { "ISO-8859", "-9",0,28599},
- { "ISO-8859", "-15",0,28605},
- { "ISO_8859", "-1",0,28591},
- { "ISO_8859", "-2",0,28592},
- { "ISO_8859", "-3",0,28593},
- { "ISO_8859", "-4",0,28594},
- { "ISO_8859", "-5",0,28595},
- { "ISO_8859", "-6",0,28596},
- { "ISO_8859", "-7",0,28597},
- { "ISO_8859", "-8",0,28598},
- { "ISO_8859", "-9",0,28599},
- { "ISO_8859", "-15",0,28605},
- { "ISO-", "10646-USC2",0,1200},
- { "ISO-2022", "/2-JP",0,50220},
- { "ISO-2022", "-JP",0,50221},
- { "ISO-2022", "/JIS-JP",0,50222},
- { "ISO-2022", "-KR",0,50225},
- { "ISO-2022", "-CH(SP)",0,50227},
- { "ISO-2022", "-CH(TR)",0,50229},
- { "UTF-", "7",0,65000},
- { "UTF-", "8",0,65001},
- { "ARAB-", "TRANSPARENT",0,710},
- { "ASMO-", "TRANSPARENT",0,720},
- { "ASMO-", "449",0,709},
- { "ASMO-", "708",0,708},
- { "BIG5", "",0,950},
- { "EUC-", "CH(SP)",0,51936},
- { "EUC-", "CH(TR)",0,51950},
- { "EUC-", "JP",0,51932},
- { "EUC-", "KR",0,51949},
- { "GB-", "2312",0,20936},
- { "GB", "2312",0,20936},
- { "HZGB-", "2312",0,52936},
- { "IBM-", "037",0,37},
- { "IBM-", "290",0,290},
- { "IBM-", "437",0,437},
- { "IBM-", "500",0,500},
- { "IBM-", "775",0,775},
- { "IBM-", "850",0,850},
- { "IBM-", "852",0,852},
- { "IBM-", "855",0,855},
- { "IBM-", "857",0,857},
- { "IBM-", "860",0,860},
- { "IBM-", "861",0,861},
- { "IBM-", "862",0,862},
- { "IBM-", "863",0,863},
- { "IBM-", "864",0,864},
- { "IBM-", "865",0,865},
- { "IBM-", "866",0,866},
- { "IBM-", "869",0,869},
- { "IBM-", "870",0,870},
- { "IBM-", "875",0,875},
- { "IBM-", "1026",0,1026},
- { "IBM-", "273",0,20273},
- { "IBM-", "277",0,20277},
- { "IBM-", "278",0,20278},
- { "IBM-", "280",0,20280},
- { "IBM-", "284",0,20284},
- { "IBM-", "285",0,20285},
- { "IBM-", "290",0,20290},
- { "IBM-", "297",0,20297},
- { "IBM-", "420",0,20420},
- { "IBM-", "423",0,20423},
- { "IBM-", "871",0,20871},
- { "IBM-", "880",0,20880},
- { "IBM-", "905",0,20905},
- { "IBM-", "THAI",0,20838},
- { "ISCII-", "DEVANAGARI",0,57002},
- { "ISCII-", "BENGALI",0,57003},
- { "ISCII-", "TAMIL",0,57004},
- { "ISCII-", "TELUGU",0,57005},
- { "ISCII-", "ASSAMESE",0,57006},
- { "ISCII-", "ORIYA",0,57007},
- { "ISCII-", "KANNADA",0,57008},
- { "ISCII-", "MALAYALAM",0,57009},
- { "ISCII-", "GUJARATI",0,57010},
- { "ISCII-", "PUNJABI",0,57011},
- { "KOR-", "JOHAB",0,1361},
- { "KSC-", "5601",0,1361},
- { "MAC-", "ROMAN",0,10000},
- { "MAC-", "JP",0,10001},
- { "MAC-", "CH(SP)(BIG5)",0,10002},
- { "MAC-", "KR",0,10003},
- { "MAC-", "AR",0,10004},
- { "MAC-", "HW",0,10005},
- { "MAC-", "GR",0,10006},
- { "MAC-", "CY",0,10007},
- { "MAC-", "CH(SP)(GB2312)",0,10008},
- { "MAC-", "ROMANIA",0,10010},
- { "MAC-", "UA",0,10017},
- { "MAC-", "TH",0,10021},
- { "MAC-", "LAT2",0,10029},
- { "MAC-", "ICE",0,10079},
- { "MAC-", "TR",0,10081},
- { "MAC-", "CR",0,10082}
-};
-
-int CPLENALL = _countof(CodePageNamesAll);
-struct _tcptable *CodePageNamesSupp;
-int CPLENSUPP = 1;
-
-//Gets codepage ID from string representing charset such as "iso-8859-1"
-// input- the string
-// size- max length of input string
-int GetCharsetFromString(char *input, size_t size);
-
-//HexValue to DecValue ('a' to 10)
-// HexValue- hexa value ('a')
-// DecValue- poiner where to store dec value
-// returns 0 if not success
-int FromHexa(char HexValue, char *DecValue);
-
-//Decodes a char from Base64
-// Base64Value- input char in Base64
-// DecValue- pointer where to store the result
-// returns 0 if not success
-int FromBase64(char Base64Value, char *DecValue);
-
-//Decodes string in quoted printable
-// Src- input string
-// Dst- where to store output string
-// DstLen- how max long should be output string
-// isQ- if is "Q-encoding" modification. should be TRUE in headers
-// always returns 1
-int DecodeQuotedPrintable(char *Src, char *Dst, int DstLen, BOOL isQ);
-
-//Decodes string in base64
-// Src- input string
-// Dst- where to store output string
-// DstLen- how max long should be output string
-// returns 0 if string was not properly decoded
-int DecodeBase64(char *Src, char *Dst, int DstLen);
-
-//Converts string to unicode from string with specified codepage
-// stream- input string
-// cp- codepage of input string
-// out- pointer to new allocated memory that contains unicode string
-int ConvertStringToUnicode(char *stream, unsigned int cp, wchar_t **out);
-
-//Converts string from MIME header to unicode
-// stream- input string
-// cp- codepage of input string
-// storeto- pointer to memory that contains unicode string
-// mode- MIME_PLAIN or MIME_MAIL (MIME_MAIL deletes '"' from start and end of string)
-void ConvertCodedStringToUnicode(char *stream, wchar_t **storeto, uint32_t cp, int mode);
-
-//--------------------------------------------------------------------------------------------------
-//--------------------------------------------------------------------------------------------------
-
-int GetCharsetFromString(char *input, size_t size)
-//"ISO-8859-1" to ID from table
-{
- char *pin = input;
- char *pout, *parser;
-
- if ((size < 1) || (parser = pout = new char[size + 1]) == nullptr)
- return -1;
- while ((*pin != 0) && (pin - input < (INT_PTR)size)) {
- if ((*pin >= 'a') && (*pin <= 'z'))
- *parser++ = *(pin++) - ('a' - 'A'); // make it capital
- //else if (*pin=='\"') // this is already done in ExtractFromContentType
- // *pin++; //skip the quotes if any
- else
- *parser++ = *pin++;
- }
-
- *parser = 0;
-
- #ifdef DEBUG_DECODECODEPAGE
- DebugLog(DecodeFile, "<CodePage>%s</CodePage>", pout);
- #endif
- for (int i = 0; i < CPLENALL; i++) {
- size_t len = mir_strlen(CodePageNamesAll[i].NameBase);
- if (0 == strncmp(pout, CodePageNamesAll[i].NameBase, len)) {
- if (0 == mir_strcmp(pout + len, CodePageNamesAll[i].NameSub)) {
- delete[] pout;
- return CodePageNamesAll[i].CP;
- }
- }
- }
- delete[] pout;
- return -1; //not found
-}
-
-int FromHexa(char HexValue, char *DecValue)
-{
- if (HexValue >= '0' && HexValue <= '9') {
- *DecValue = HexValue - '0';
- return 1;
- }
- if (HexValue >= 'A' && HexValue <= 'F') {
- *DecValue = HexValue - 'A' + 10;
- return 1;
- }
- if (HexValue >= 'a' && HexValue <= 'f') {
- *DecValue = HexValue - 'a' + 10;
- return 1;
- }
- return 0;
-}
-
-int FromBase64(char Base64Value, char *DecValue)
-{
- if (Base64Value >= 'A' && Base64Value <= 'Z') {
- *DecValue = Base64Value - 'A';
- return 1;
- }
- if (Base64Value >= 'a' && Base64Value <= 'z') {
- *DecValue = Base64Value - 'a' + 26;
- return 1;
- }
- if (Base64Value >= '0' && Base64Value <= '9') {
- *DecValue = Base64Value - '0' + 52;
- return 1;
- }
- if (Base64Value == '+') {
- *DecValue = Base64Value - '+' + 62;
- return 1;
- }
- if (Base64Value == '/') {
- *DecValue = Base64Value - '/' + 63;
- return 1;
- }
- if (Base64Value == '=') {
- *DecValue = 0;
- return 1;
- }
- return 0;
-}
-
-int DecodeQuotedPrintable(char *Src, char *Dst, int DstLen, BOOL isQ)
-{
- #ifdef DEBUG_DECODEQUOTED
- char *DstTemp = Dst;
- DebugLog(DecodeFile, "<Decode Quoted><Input>%s</Input>", Src);
- #endif
- for (int Counter = 0; (*Src != 0) && DstLen && (Counter++ < DstLen); Src++, Dst++)
- if (*Src == '=') {
- if (!isQ) {
- if (Src[1] == 0x0D) {
- Src++; Src++;
- if (Src[0] == 0x0A) Src++;
- goto CopyCharQuotedPrintable;
- }
- if (Src[1] == 0x0A) {
- Src++; Src++;
- goto CopyCharQuotedPrintable;
- }
- }
- char First, Second;
- if (!FromHexa(*(++Src), &First)) {
- *Dst++ = '='; Src--;
- continue;
- }
- if (!FromHexa(*(++Src), &Second)) {
- *Dst++ = '='; Src--; Src--;
- continue;
- }
- *Dst = (char)(First) << 4;
- *Dst += Second;
- }
- else if (isQ && *Src == '_')
- *Dst = ' ';
- else
- CopyCharQuotedPrintable: // Yeah. Bad programming stile.
- *Dst = *Src;
- *Dst = 0;
- #ifdef DEBUG_DECODEQUOTED
- DebugLog(DecodeFile, "<Output>%s</Output></Decode Quoted>", DstTemp);
- #endif
- return 1;
-}
-
-int DecodeBase64(char *Src, char *Dst, int DstLen)
-{
- int Result = 0;
- char Locator = 0, MiniResult[4];
- char *End = Dst + DstLen;
-
- MiniResult[0] = MiniResult[1] = MiniResult[2] = MiniResult[3] = 0;
-
- #ifdef DEBUG_DECODEBASE64
- char *DstTemp = Dst;
- DebugLog(DecodeFile, "<Decode Base64><Input>\n%s\n</Input>\n", Src);
- #endif
- while (*Src != 0 && DstLen && Dst != End) {
- if ((*Src == 0x0D) || (*Src == 0x0A)) {
- Src++;
- continue;
- }
- if ((!(Result = FromBase64(*Src, MiniResult + Locator)) && (*Src == 0)) || Locator++ == 3) //end_of_str || end_of_4_bytes
- {
- Locator = 0; //next write to the first byte
- *Dst++ = (char)((MiniResult[0] << 2) | (MiniResult[1] >> 4));
- if (Dst == End) goto end; //DstLen exceeded?
- *Dst++ = (char)((MiniResult[1] << 4) | (MiniResult[2] >> 2));
- if (Dst == End) goto end; //someones don't like goto, but not me
- *Dst++ = (char)((MiniResult[2] << 6) | MiniResult[3]);
- if (!Result && (*Src == 0)) goto end; //end of string?
- MiniResult[0] = MiniResult[1] = MiniResult[2] = MiniResult[3] = 0; //zero 4byte buffer for next loop
- }
- if (!Result) return 0; //unrecognised character occured
- Src++;
- }
-end:
- *Dst = 0;
- #ifdef DEBUG_DECODEBASE64
- DebugLog(DecodeFile, "<Output>\n%s\n</Output></Decode Base64>", DstTemp);
- #endif
- return 1;
-}
-
-
-
-int ConvertStringToUnicode(char *stream, unsigned int cp, wchar_t **out)
-{
- CPINFO CPInfo;
- wchar_t *temp, *src = *out, *dest;
- size_t outlen;
- int streamlen, Index;
-
- //codepages, which require to have set 0 in dwFlags parameter when calling MultiByteToWideChar
- uint32_t CodePagesZeroFlags[] = {50220, 50221, 50222, 50225, 50227, 50229, 52936, 54936, 57002, 57003, 57004, 57005, 57006, 57007, 57008, 57009, 57010, 57011, 65000, 65001};
-
- if ((cp != CP_ACP) && (cp != CP_OEMCP) && (cp != CP_MACCP) && (cp != CP_THREAD_ACP) && (cp != CP_SYMBOL) && (cp != CP_UTF7) && (cp != CP_UTF8) && !GetCPInfo(cp, &CPInfo))
- cp = CP_ACP;
- #ifdef DEBUG_DECODECODEPAGE
- DebugLog(DecodeFile, "<CodePage #>%d</CodePage #>", cp);
- #endif
-
- for (Index = 0; Index < sizeof(CodePagesZeroFlags) / sizeof(CodePagesZeroFlags[0]); Index++)
- if (CodePagesZeroFlags[Index] == cp) {
- Index = -1;
- break;
- }
- if (Index == -1)
- streamlen = MultiByteToWideChar(cp, 0, stream, -1, nullptr, 0);
- else
- streamlen = MultiByteToWideChar(cp, MB_USEGLYPHCHARS, stream, -1, nullptr, 0);
-
- if (*out != nullptr)
- outlen = mir_wstrlen(*out);
- else
- outlen = 0;
- temp = new wchar_t[streamlen + outlen + 1];
-
- if (*out != nullptr) {
- for (dest = temp; *src != (wchar_t)0; src++, dest++) //copy old string from *out to temp
- *dest = *src;
- // *dest++=L' '; //add space?
- delete[] * out;
- }
- else
- dest = temp;
- *out = temp;
-
- if (Index == -1) {
- if (!MultiByteToWideChar(cp, 0, stream, -1, dest, streamlen))
- return 0;
- }
- else {
- if (!MultiByteToWideChar(cp, MB_USEGLYPHCHARS, stream, -1, dest, streamlen))
- return 0;
- }
- return 1;
-}
-
-void ConvertCodedStringToUnicode(char *stream, wchar_t **storeto, uint32_t cp, int mode)
-{
- char *start = stream, *finder, *finderend;
- char Encoding = 0;
-
- if (stream == nullptr)
- return;
-
- while (WS(start)) start++;
- wchar_t *tempstore = nullptr;
- if (!ConvertStringToUnicode(stream, cp, &tempstore))return;
-
- size_t tempstoreLength = mir_wstrlen(tempstore);
-
- size_t outind = 0;
- while (*start != 0) {
- if (CODES(start)) {
- finder = start + 2; finderend = finder;
- while (!CODED(finderend) && !EOS(finderend)) finderend++;
- start = finderend;
- if (CODED(finderend)) {
- Encoding = *(finderend + 1);
- switch (Encoding) {
- case 'b':
- case 'B':
- case 'q':
- case 'Q':
- break;
- default:
- goto NotEncoded;
- }
- if (-1 == (cp = (uint32_t)GetCharsetFromString(finder, finderend - finder)))
- cp = CP_ACP;
- if (Encoding != 0) {
- int size = 0, codeend;
- char *pcodeend = nullptr;
-
- finder = finderend + 2;
- if (CODED(finder))
- finder++;
- while (WS(finder)) finder++;
- finderend = finder;
- while (!CODEE(finderend) && !EOS(finderend)) finderend++;
- if (codeend = CODEE(finderend))
- pcodeend = finderend;
- while (WS(finderend - 1)) finderend--;
- if ((mode == MIME_MAIL) && (((*finder == '"') && (*(finderend - 1) == '"')))) {
- finder++;
- finderend--;
- }
- char *oneWordEncoded = new char[finderend - finder + 1];
- strncpy(oneWordEncoded, finder, finderend - finder);
- oneWordEncoded[finderend - finder] = 0;
- switch (Encoding) {
- case 'b':
- case 'B':
- size = (finderend - finder) * 3 / 4 + 3 + 1 + 1;
- break;
- case 'q':
- case 'Q':
- size = finderend - finder + 1 + 1;
- break;
- }
-
- char *DecodedResult = new char[size + 1];
- switch (Encoding) {
- case 'q':
- case 'Q':
- DecodeQuotedPrintable(oneWordEncoded, DecodedResult, size, TRUE);
- break;
- case 'b':
- case 'B':
- DecodeBase64(oneWordEncoded, DecodedResult, size);
- break;
- }
- delete[] oneWordEncoded;
- if (codeend)
- finderend = pcodeend + 2;
- if (WS(finderend)) //if string continues and there's some whitespace, add space to string that is to be converted
- {
- size_t len = mir_strlen(DecodedResult);
- DecodedResult[len] = ' ';
- DecodedResult[len + 1] = 0;
- finderend++;
- }
- wchar_t *oneWord = nullptr;
- if (ConvertStringToUnicode(DecodedResult, cp, &oneWord)) {
- size_t len = mir_wstrlen(oneWord);
- memcpy(&tempstore[outind], oneWord, len * sizeof(wchar_t));
- outind += len;
- }
- delete oneWord;
- oneWord = nullptr;
- delete[] DecodedResult;
- start = finderend;
- }
- else if (!EOS(start)) start++;
- }
- else if (!EOS(start)) start++;
- }
- else {
-NotEncoded:
- tempstore[outind] = tempstore[start - stream];
- outind++;
- if (outind > tempstoreLength) break;
- start++;
- }
- }
- tempstore[outind] = 0;
- *storeto = tempstore;
-}
+/*
+ * This code implements decoding encoded MIME header in style
+ * =?iso-8859-2?Q? "User using email in central Europe characters such as =E9" ?=
+ *
+ * (c) majvan 2002-2004
+ */
+#include "../stdafx.h"
+//--------------------------------------------------------------------------------------------------
+//--------------------------------------------------------------------------------------------------
+
+struct _tcptable CodePageNamesAll[]=
+{
+ { "ANSI", "",TRUE,CP_ACP},
+ { "WINDOWS-1", "250",0,1250},
+ { "WINDOWS-1", "251",0,1251},
+ { "WINDOWS-1", "252",0,1252},
+ { "WINDOWS-1", "253",0,1253},
+ { "WINDOWS-1", "254",0,1254},
+ { "WINDOWS-1", "255",0,1255},
+ { "WINDOWS-1", "256",0,1256},
+ { "WINDOWS-1", "257",0,1257},
+ { "WINDOWS-1", "258",0,1258},
+ { "CP1", "250",0,1250},
+ { "CP1", "251",0,1251},
+ { "CP1", "252",0,1252},
+ { "CP1", "253",0,1253},
+ { "CP1", "254",0,1254},
+ { "CP1", "255",0,1255},
+ { "CP1", "256",0,1256},
+ { "CP1", "257",0,1257},
+ { "CP1", "258",0,1258},
+ { "ANSI-1", "250",0,1250},
+ { "ANSI-1", "251",0,1251},
+ { "ANSI-1", "252",0,1252},
+ { "ANSI-1", "253",0,1253},
+ { "ANSI-1", "254",0,1254},
+ { "ANSI-1", "255",0,1255},
+ { "ANSI-1", "256",0,1256},
+ { "ANSI-1", "257",0,1257},
+ { "ANSI-1", "258",0,1258},
+ { "KOI8", "-R",0,20866},
+ { "KOI8", "",0,20866},
+ { "KOI8", "-U",0,21866},
+ { "KOI8", "-RU",0,21866},
+ { "US-", "ASCII",0,20127},
+ { "CP", "367",0,20127},
+ { "ASCII", "",0,20127},
+ { "ASCII", "7",0,20127},
+ { "ISO-8859", "-1",0,28591},
+ { "ISO-8859", "-2",0,28592},
+ { "ISO-8859", "-3",0,28593},
+ { "ISO-8859", "-4",0,28594},
+ { "ISO-8859", "-5",0,28595},
+ { "ISO-8859", "-6",0,28596},
+ { "ISO-8859", "-7",0,28597},
+ { "ISO-8859", "-8",0,28598},
+ { "ISO-8859", "-9",0,28599},
+ { "ISO-8859", "-15",0,28605},
+ { "ISO_8859", "-1",0,28591},
+ { "ISO_8859", "-2",0,28592},
+ { "ISO_8859", "-3",0,28593},
+ { "ISO_8859", "-4",0,28594},
+ { "ISO_8859", "-5",0,28595},
+ { "ISO_8859", "-6",0,28596},
+ { "ISO_8859", "-7",0,28597},
+ { "ISO_8859", "-8",0,28598},
+ { "ISO_8859", "-9",0,28599},
+ { "ISO_8859", "-15",0,28605},
+ { "ISO-", "10646-USC2",0,1200},
+ { "ISO-2022", "/2-JP",0,50220},
+ { "ISO-2022", "-JP",0,50221},
+ { "ISO-2022", "/JIS-JP",0,50222},
+ { "ISO-2022", "-KR",0,50225},
+ { "ISO-2022", "-CH(SP)",0,50227},
+ { "ISO-2022", "-CH(TR)",0,50229},
+ { "UTF-", "7",0,65000},
+ { "UTF-", "8",0,65001},
+ { "ARAB-", "TRANSPARENT",0,710},
+ { "ASMO-", "TRANSPARENT",0,720},
+ { "ASMO-", "449",0,709},
+ { "ASMO-", "708",0,708},
+ { "BIG5", "",0,950},
+ { "EUC-", "CH(SP)",0,51936},
+ { "EUC-", "CH(TR)",0,51950},
+ { "EUC-", "JP",0,51932},
+ { "EUC-", "KR",0,51949},
+ { "GB-", "2312",0,20936},
+ { "GB", "2312",0,20936},
+ { "HZGB-", "2312",0,52936},
+ { "IBM-", "037",0,37},
+ { "IBM-", "290",0,290},
+ { "IBM-", "437",0,437},
+ { "IBM-", "500",0,500},
+ { "IBM-", "775",0,775},
+ { "IBM-", "850",0,850},
+ { "IBM-", "852",0,852},
+ { "IBM-", "855",0,855},
+ { "IBM-", "857",0,857},
+ { "IBM-", "860",0,860},
+ { "IBM-", "861",0,861},
+ { "IBM-", "862",0,862},
+ { "IBM-", "863",0,863},
+ { "IBM-", "864",0,864},
+ { "IBM-", "865",0,865},
+ { "IBM-", "866",0,866},
+ { "IBM-", "869",0,869},
+ { "IBM-", "870",0,870},
+ { "IBM-", "875",0,875},
+ { "IBM-", "1026",0,1026},
+ { "IBM-", "273",0,20273},
+ { "IBM-", "277",0,20277},
+ { "IBM-", "278",0,20278},
+ { "IBM-", "280",0,20280},
+ { "IBM-", "284",0,20284},
+ { "IBM-", "285",0,20285},
+ { "IBM-", "290",0,20290},
+ { "IBM-", "297",0,20297},
+ { "IBM-", "420",0,20420},
+ { "IBM-", "423",0,20423},
+ { "IBM-", "871",0,20871},
+ { "IBM-", "880",0,20880},
+ { "IBM-", "905",0,20905},
+ { "IBM-", "THAI",0,20838},
+ { "ISCII-", "DEVANAGARI",0,57002},
+ { "ISCII-", "BENGALI",0,57003},
+ { "ISCII-", "TAMIL",0,57004},
+ { "ISCII-", "TELUGU",0,57005},
+ { "ISCII-", "ASSAMESE",0,57006},
+ { "ISCII-", "ORIYA",0,57007},
+ { "ISCII-", "KANNADA",0,57008},
+ { "ISCII-", "MALAYALAM",0,57009},
+ { "ISCII-", "GUJARATI",0,57010},
+ { "ISCII-", "PUNJABI",0,57011},
+ { "KOR-", "JOHAB",0,1361},
+ { "KSC-", "5601",0,1361},
+ { "MAC-", "ROMAN",0,10000},
+ { "MAC-", "JP",0,10001},
+ { "MAC-", "CH(SP)(BIG5)",0,10002},
+ { "MAC-", "KR",0,10003},
+ { "MAC-", "AR",0,10004},
+ { "MAC-", "HW",0,10005},
+ { "MAC-", "GR",0,10006},
+ { "MAC-", "CY",0,10007},
+ { "MAC-", "CH(SP)(GB2312)",0,10008},
+ { "MAC-", "ROMANIA",0,10010},
+ { "MAC-", "UA",0,10017},
+ { "MAC-", "TH",0,10021},
+ { "MAC-", "LAT2",0,10029},
+ { "MAC-", "ICE",0,10079},
+ { "MAC-", "TR",0,10081},
+ { "MAC-", "CR",0,10082}
+};
+
+int CPLENALL = _countof(CodePageNamesAll);
+struct _tcptable *CodePageNamesSupp;
+int CPLENSUPP = 1;
+
+//Gets codepage ID from string representing charset such as "iso-8859-1"
+// input- the string
+// size- max length of input string
+int GetCharsetFromString(char *input, size_t size);
+
+//HexValue to DecValue ('a' to 10)
+// HexValue- hexa value ('a')
+// DecValue- poiner where to store dec value
+// returns 0 if not success
+int FromHexa(char HexValue, char *DecValue);
+
+//Decodes a char from Base64
+// Base64Value- input char in Base64
+// DecValue- pointer where to store the result
+// returns 0 if not success
+int FromBase64(char Base64Value, char *DecValue);
+
+//Decodes string in quoted printable
+// Src- input string
+// Dst- where to store output string
+// DstLen- how max long should be output string
+// isQ- if is "Q-encoding" modification. should be TRUE in headers
+// always returns 1
+int DecodeQuotedPrintable(char *Src, char *Dst, int DstLen, BOOL isQ);
+
+//Decodes string in base64
+// Src- input string
+// Dst- where to store output string
+// DstLen- how max long should be output string
+// returns 0 if string was not properly decoded
+int DecodeBase64(char *Src, char *Dst, int DstLen);
+
+//Converts string to unicode from string with specified codepage
+// stream- input string
+// cp- codepage of input string
+// out- pointer to new allocated memory that contains unicode string
+int ConvertStringToUnicode(char *stream, unsigned int cp, wchar_t **out);
+
+//Converts string from MIME header to unicode
+// stream- input string
+// cp- codepage of input string
+// storeto- pointer to memory that contains unicode string
+// mode- MIME_PLAIN or MIME_MAIL (MIME_MAIL deletes '"' from start and end of string)
+void ConvertCodedStringToUnicode(char *stream, wchar_t **storeto, uint32_t cp, int mode);
+
+//--------------------------------------------------------------------------------------------------
+//--------------------------------------------------------------------------------------------------
+
+int GetCharsetFromString(char *input, size_t size)
+//"ISO-8859-1" to ID from table
+{
+ char *pin = input;
+ char *pout, *parser;
+
+ if ((size < 1) || (parser = pout = new char[size + 1]) == nullptr)
+ return -1;
+ while ((*pin != 0) && (pin - input < (INT_PTR)size)) {
+ if ((*pin >= 'a') && (*pin <= 'z'))
+ *parser++ = *(pin++) - ('a' - 'A'); // make it capital
+ //else if (*pin=='\"') // this is already done in ExtractFromContentType
+ // *pin++; //skip the quotes if any
+ else
+ *parser++ = *pin++;
+ }
+
+ *parser = 0;
+
+ #ifdef DEBUG_DECODECODEPAGE
+ DebugLog(DecodeFile, "<CodePage>%s</CodePage>", pout);
+ #endif
+ for (int i = 0; i < CPLENALL; i++) {
+ size_t len = mir_strlen(CodePageNamesAll[i].NameBase);
+ if (0 == strncmp(pout, CodePageNamesAll[i].NameBase, len)) {
+ if (0 == mir_strcmp(pout + len, CodePageNamesAll[i].NameSub)) {
+ delete[] pout;
+ return CodePageNamesAll[i].CP;
+ }
+ }
+ }
+ delete[] pout;
+ return -1; //not found
+}
+
+int FromHexa(char HexValue, char *DecValue)
+{
+ if (HexValue >= '0' && HexValue <= '9') {
+ *DecValue = HexValue - '0';
+ return 1;
+ }
+ if (HexValue >= 'A' && HexValue <= 'F') {
+ *DecValue = HexValue - 'A' + 10;
+ return 1;
+ }
+ if (HexValue >= 'a' && HexValue <= 'f') {
+ *DecValue = HexValue - 'a' + 10;
+ return 1;
+ }
+ return 0;
+}
+
+int FromBase64(char Base64Value, char *DecValue)
+{
+ if (Base64Value >= 'A' && Base64Value <= 'Z') {
+ *DecValue = Base64Value - 'A';
+ return 1;
+ }
+ if (Base64Value >= 'a' && Base64Value <= 'z') {
+ *DecValue = Base64Value - 'a' + 26;
+ return 1;
+ }
+ if (Base64Value >= '0' && Base64Value <= '9') {
+ *DecValue = Base64Value - '0' + 52;
+ return 1;
+ }
+ if (Base64Value == '+') {
+ *DecValue = Base64Value - '+' + 62;
+ return 1;
+ }
+ if (Base64Value == '/') {
+ *DecValue = Base64Value - '/' + 63;
+ return 1;
+ }
+ if (Base64Value == '=') {
+ *DecValue = 0;
+ return 1;
+ }
+ return 0;
+}
+
+int DecodeQuotedPrintable(char *Src, char *Dst, int DstLen, BOOL isQ)
+{
+ #ifdef DEBUG_DECODEQUOTED
+ char *DstTemp = Dst;
+ DebugLog(DecodeFile, "<Decode Quoted><Input>%s</Input>", Src);
+ #endif
+ for (int Counter = 0; (*Src != 0) && DstLen && (Counter++ < DstLen); Src++, Dst++)
+ if (*Src == '=') {
+ if (!isQ) {
+ if (Src[1] == 0x0D) {
+ Src++; Src++;
+ if (Src[0] == 0x0A) Src++;
+ goto CopyCharQuotedPrintable;
+ }
+ if (Src[1] == 0x0A) {
+ Src++; Src++;
+ goto CopyCharQuotedPrintable;
+ }
+ }
+ char First, Second;
+ if (!FromHexa(*(++Src), &First)) {
+ *Dst++ = '='; Src--;
+ continue;
+ }
+ if (!FromHexa(*(++Src), &Second)) {
+ *Dst++ = '='; Src--; Src--;
+ continue;
+ }
+ *Dst = (char)(First) << 4;
+ *Dst += Second;
+ }
+ else if (isQ && *Src == '_')
+ *Dst = ' ';
+ else
+ CopyCharQuotedPrintable: // Yeah. Bad programming stile.
+ *Dst = *Src;
+ *Dst = 0;
+ #ifdef DEBUG_DECODEQUOTED
+ DebugLog(DecodeFile, "<Output>%s</Output></Decode Quoted>", DstTemp);
+ #endif
+ return 1;
+}
+
+int DecodeBase64(char *Src, char *Dst, int DstLen)
+{
+ int Result = 0;
+ char Locator = 0, MiniResult[4];
+ char *End = Dst + DstLen;
+
+ MiniResult[0] = MiniResult[1] = MiniResult[2] = MiniResult[3] = 0;
+
+ #ifdef DEBUG_DECODEBASE64
+ char *DstTemp = Dst;
+ DebugLog(DecodeFile, "<Decode Base64><Input>\n%s\n</Input>\n", Src);
+ #endif
+ while (*Src != 0 && DstLen && Dst != End) {
+ if ((*Src == 0x0D) || (*Src == 0x0A)) {
+ Src++;
+ continue;
+ }
+ if ((!(Result = FromBase64(*Src, MiniResult + Locator)) && (*Src == 0)) || Locator++ == 3) //end_of_str || end_of_4_bytes
+ {
+ Locator = 0; //next write to the first byte
+ *Dst++ = (char)((MiniResult[0] << 2) | (MiniResult[1] >> 4));
+ if (Dst == End) goto end; //DstLen exceeded?
+ *Dst++ = (char)((MiniResult[1] << 4) | (MiniResult[2] >> 2));
+ if (Dst == End) goto end; //someones don't like goto, but not me
+ *Dst++ = (char)((MiniResult[2] << 6) | MiniResult[3]);
+ if (!Result && (*Src == 0)) goto end; //end of string?
+ MiniResult[0] = MiniResult[1] = MiniResult[2] = MiniResult[3] = 0; //zero 4byte buffer for next loop
+ }
+ if (!Result) return 0; //unrecognised character occured
+ Src++;
+ }
+end:
+ *Dst = 0;
+ #ifdef DEBUG_DECODEBASE64
+ DebugLog(DecodeFile, "<Output>\n%s\n</Output></Decode Base64>", DstTemp);
+ #endif
+ return 1;
+}
+
+
+
+int ConvertStringToUnicode(char *stream, unsigned int cp, wchar_t **out)
+{
+ CPINFO CPInfo;
+ wchar_t *temp, *src = *out, *dest;
+ size_t outlen;
+ int streamlen, Index;
+
+ //codepages, which require to have set 0 in dwFlags parameter when calling MultiByteToWideChar
+ uint32_t CodePagesZeroFlags[] = {50220, 50221, 50222, 50225, 50227, 50229, 52936, 54936, 57002, 57003, 57004, 57005, 57006, 57007, 57008, 57009, 57010, 57011, 65000, 65001};
+
+ if ((cp != CP_ACP) && (cp != CP_OEMCP) && (cp != CP_MACCP) && (cp != CP_THREAD_ACP) && (cp != CP_SYMBOL) && (cp != CP_UTF7) && (cp != CP_UTF8) && !GetCPInfo(cp, &CPInfo))
+ cp = CP_ACP;
+ #ifdef DEBUG_DECODECODEPAGE
+ DebugLog(DecodeFile, "<CodePage #>%d</CodePage #>", cp);
+ #endif
+
+ for (Index = 0; Index < sizeof(CodePagesZeroFlags) / sizeof(CodePagesZeroFlags[0]); Index++)
+ if (CodePagesZeroFlags[Index] == cp) {
+ Index = -1;
+ break;
+ }
+ if (Index == -1)
+ streamlen = MultiByteToWideChar(cp, 0, stream, -1, nullptr, 0);
+ else
+ streamlen = MultiByteToWideChar(cp, MB_USEGLYPHCHARS, stream, -1, nullptr, 0);
+
+ if (*out != nullptr)
+ outlen = mir_wstrlen(*out);
+ else
+ outlen = 0;
+ temp = new wchar_t[streamlen + outlen + 1];
+
+ if (*out != nullptr) {
+ for (dest = temp; *src != (wchar_t)0; src++, dest++) //copy old string from *out to temp
+ *dest = *src;
+ // *dest++=L' '; //add space?
+ delete[] * out;
+ }
+ else
+ dest = temp;
+ *out = temp;
+
+ if (Index == -1) {
+ if (!MultiByteToWideChar(cp, 0, stream, -1, dest, streamlen))
+ return 0;
+ }
+ else {
+ if (!MultiByteToWideChar(cp, MB_USEGLYPHCHARS, stream, -1, dest, streamlen))
+ return 0;
+ }
+ return 1;
+}
+
+void ConvertCodedStringToUnicode(char *stream, wchar_t **storeto, uint32_t cp, int mode)
+{
+ char *start = stream, *finder, *finderend;
+ char Encoding = 0;
+
+ if (stream == nullptr)
+ return;
+
+ while (WS(start)) start++;
+ wchar_t *tempstore = nullptr;
+ if (!ConvertStringToUnicode(stream, cp, &tempstore))return;
+
+ size_t tempstoreLength = mir_wstrlen(tempstore);
+
+ size_t outind = 0;
+ while (*start != 0) {
+ if (CODES(start)) {
+ finder = start + 2; finderend = finder;
+ while (!CODED(finderend) && !EOS(finderend)) finderend++;
+ start = finderend;
+ if (CODED(finderend)) {
+ Encoding = *(finderend + 1);
+ switch (Encoding) {
+ case 'b':
+ case 'B':
+ case 'q':
+ case 'Q':
+ break;
+ default:
+ goto NotEncoded;
+ }
+ if (-1 == (cp = (uint32_t)GetCharsetFromString(finder, finderend - finder)))
+ cp = CP_ACP;
+ if (Encoding != 0) {
+ int size = 0, codeend;
+ char *pcodeend = nullptr;
+
+ finder = finderend + 2;
+ if (CODED(finder))
+ finder++;
+ while (WS(finder)) finder++;
+ finderend = finder;
+ while (!CODEE(finderend) && !EOS(finderend)) finderend++;
+ if (codeend = CODEE(finderend))
+ pcodeend = finderend;
+ while (WS(finderend - 1)) finderend--;
+ if ((mode == MIME_MAIL) && (((*finder == '"') && (*(finderend - 1) == '"')))) {
+ finder++;
+ finderend--;
+ }
+ char *oneWordEncoded = new char[finderend - finder + 1];
+ strncpy(oneWordEncoded, finder, finderend - finder);
+ oneWordEncoded[finderend - finder] = 0;
+ switch (Encoding) {
+ case 'b':
+ case 'B':
+ size = (finderend - finder) * 3 / 4 + 3 + 1 + 1;
+ break;
+ case 'q':
+ case 'Q':
+ size = finderend - finder + 1 + 1;
+ break;
+ }
+
+ char *DecodedResult = new char[size + 1];
+ switch (Encoding) {
+ case 'q':
+ case 'Q':
+ DecodeQuotedPrintable(oneWordEncoded, DecodedResult, size, TRUE);
+ break;
+ case 'b':
+ case 'B':
+ DecodeBase64(oneWordEncoded, DecodedResult, size);
+ break;
+ }
+ delete[] oneWordEncoded;
+ if (codeend)
+ finderend = pcodeend + 2;
+ if (WS(finderend)) //if string continues and there's some whitespace, add space to string that is to be converted
+ {
+ size_t len = mir_strlen(DecodedResult);
+ DecodedResult[len] = ' ';
+ DecodedResult[len + 1] = 0;
+ finderend++;
+ }
+ wchar_t *oneWord = nullptr;
+ if (ConvertStringToUnicode(DecodedResult, cp, &oneWord)) {
+ size_t len = mir_wstrlen(oneWord);
+ memcpy(&tempstore[outind], oneWord, len * sizeof(wchar_t));
+ outind += len;
+ }
+ delete oneWord;
+ oneWord = nullptr;
+ delete[] DecodedResult;
+ start = finderend;
+ }
+ else if (!EOS(start)) start++;
+ }
+ else if (!EOS(start)) start++;
+ }
+ else {
+NotEncoded:
+ tempstore[outind] = tempstore[start - stream];
+ outind++;
+ if (outind > tempstoreLength) break;
+ start++;
+ }
+ }
+ tempstore[outind] = 0;
+ *storeto = tempstore;
+}
diff --git a/protocols/YAMN/src/mails/mails.cpp b/protocols/YAMN/src/mails/mails.cpp
index 168c6c9397..1385cb649d 100644
--- a/protocols/YAMN/src/mails/mails.cpp
+++ b/protocols/YAMN/src/mails/mails.cpp
@@ -1,473 +1,473 @@
-/*
- * This code implements retrieving info from MIME header
- *
- * (c) majvan 2002-2004
- */
-
-#include "../stdafx.h"
-
- //--------------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------------
-
- // SMALL INTRO
- // Mails are queued in a queue (chained list). Pointer to first mail is pointed from Account structure
- // member called Mails.
- // Mail queue is ended with NULL- pointered mail (NULL handle)
-
- //Creates new mail for plugin (calling plugin's constructor, when plugin imported to YAMN)
-INT_PTR CreateAccountMailSvc(WPARAM wParam, LPARAM lParam);
-
-//Deletes mail for plugin (calling plugin's destructor, when plugin imported to YAMN)
-INT_PTR DeleteAccountMailSvc(WPARAM wParam, LPARAM lParam);
-
-//Loads mail data from standard storage to memory
-INT_PTR LoadMailDataSvc(WPARAM wParam, LPARAM lParam);
-
-//Deletes mail data from memory
-INT_PTR UnloadMailDataSvc(WPARAM wParam, LPARAM);
-
-//Saves mail data from memory to standard storage
-INT_PTR SaveMailDataSvc(WPARAM wParam, LPARAM lParam);
-
-//Appends second MIME mail queue to the first one
-//Only finds the end of first queue and its Next memember repoints to second one
-void WINAPI AppendQueueFcn(HYAMNMAIL first, HYAMNMAIL second);
-
-//Synchronizes two accounts
-//Function finds, if there were some mails deleted from mailbox and deletes (depends on RemovedOld param) them from OldQueue
-//Next finds, if there are new mails. Mails that are still on mailbox are deleted (depends on RemovedNew param) from NewQueue
-//After this, OldQueue is pointer to mails that are on mailbox, but not new mails
-//and NewQueue contains new mails in account
-//New accounts can be then appended to account mails queue, but they have set the New flag
-//
-//Two mails equals if they have the same ID
-//
-// hPlugin- handle of plugin going to delete mails
-// OldQueue- queue of mails that we found on mailbox last time, after function finishes queue contains all mails except new ones
-// RemovedOld- queue of mails where to store removed mails from OldQueue, if NULL deletes mails from OldQueue
-// NewQueue- queue of mails that we found on mailbox (all mails), after function finishes queue contains only new mails
-// RemovedNew- queue of mails where to store removed mails from NewQueue, if NULL deletes mails from NewQueue
-//So function works like:
-//1. delete (or move to RemovedOld queue if RemovedOld is not NULL) all mails from OldQueue not found in NewQueue
-//2. delete (or move to RemovedNew queue if RemovedNew is not NULL) all mails from NewQueue found in OldQueue
-void WINAPI SynchroMessagesFcn(CAccount *Account, HYAMNMAIL *OldQueue, HYAMNMAIL *RemovedOld, HYAMNMAIL *NewQueue, HYAMNMAIL *RemovedNew);
-
-//Deletes messages from mail From to the end
-// Account- account who owns mails
-// From- first mail in queue, which is going to delete
-void WINAPI DeleteMessagesToEndFcn(CAccount *Account, HYAMNMAIL From);
-
-//Removes message from queue, does not delete from memory
-// From- queue pointer
-// Which- mail to delete
-// mode- nonzero if you want to decrement numbers in messages that are bigger than the one in Which mail, 0 if not
-void WINAPI DeleteMessageFromQueueFcn(HYAMNMAIL *From, HYAMNMAIL Which, int mode);
-
-//Finds message in queue that has the same ID number
-// From- message queue
-// ID- pointer to ID
-// returns pointer to found message, NULL if not found
-HYAMNMAIL WINAPI FindMessageByIDFcn(HYAMNMAIL From, char *ID);
-
-//Translate header from text to queue of CMimeItem structures
-//This means that new queue will contain all info about headers
-// stream- pointer to text containing header (can be ended with zero)
-// len- length of stream
-// head- function fills this pointer to first header item in queue
-void WINAPI TranslateHeaderFcn(char *stream, int len, struct CMimeItem **head);
-
-//Creates new mail queue, copying only these mails, that have set flag for deleting
-// From- message queue, whose mail with given flag are duplicated
-// returns new mail queue (or NULL when no mail with flag is in From queue)
-//Function does not copy the whole mails, it copies only ID string. And ID is copied as string, so
-//you can use this fcn only if you have your ID as pointer to char string ended with zero character
-HYAMNMAIL WINAPI CreateNewDeleteQueueFcn(HYAMNMAIL From);
-
-//Sets/removes flags from specific mails
-// From- pointer to first message
-// FlagsSet- mail must have set these flags...
-// FlagsNotSet- ...and must not have set these flags...
-// FlagsToSetRemove- ...to set/remove these flags (see mode)
-// mode- nonzero to set, else remove
-void WINAPI SetRemoveFlagsInQueueFcn(HYAMNMAIL From, uint32_t FlagsSet, uint32_t FlagsNotSet, uint32_t FlagsToSetRemove, int mode);
-
-struct CExportedFunctions MailExportedFcn[] =
-{
- {YAMN_SYNCHROMIMEMSGSID, (void *)SynchroMessagesFcn},
- {YAMN_TRANSLATEHEADERID, (void *)TranslateHeaderFcn},
- {YAMN_APPENDQUEUEID, (void *)AppendQueueFcn},
- {YAMN_DELETEMIMEQUEUEID, (void *)DeleteMessagesToEndFcn},
- {YAMN_DELETEMIMEMESSAGEID, (void *)DeleteMessageFromQueueFcn},
- {YAMN_FINDMIMEMESSAGEID, (void *)FindMessageByIDFcn},
- {YAMN_CREATENEWDELETEQUEUEID, (void *)CreateNewDeleteQueueFcn},
- {YAMN_SETREMOVEQUEUEFLAGSID, (void *)SetRemoveFlagsInQueueFcn},
-};
-
-struct CExportedServices MailExportedSvc[] =
-{
- {MS_YAMN_CREATEACCOUNTMAIL, CreateAccountMailSvc},
- {MS_YAMN_DELETEACCOUNTMAIL, DeleteAccountMailSvc},
- {MS_YAMN_LOADMAILDATA, LoadMailDataSvc},
- {MS_YAMN_UNLOADMAILDATA, UnloadMailDataSvc},
- {MS_YAMN_SAVEMAILDATA, SaveMailDataSvc},
-};
-
-
-//--------------------------------------------------------------------------------------------------
-//--------------------------------------------------------------------------------------------------
-
-INT_PTR CreateAccountMailSvc(WPARAM wParam, LPARAM lParam)
-{
- CAccount *Account = (CAccount *)wParam;
- uint32_t MailVersion = (uint32_t)lParam;
- HYAMNMAIL NewMail;
-
- //test if we are going to initialize members of suitable structure (structures of plugin and YAMN must match)
- if (MailVersion != YAMN_MAILVERSION)
- return NULL;
-
- if (Account->Plugin != nullptr) {
- if (Account->Plugin->MailFcn->NewMailFcnPtr != nullptr) {
- //Let plugin create its own structure, which can be derived from CAccount structure
- if (nullptr == (NewMail = Account->Plugin->MailFcn->NewMailFcnPtr(Account, YAMN_MAILVERSION)))
- return NULL;
- }
- else {
- //We suggest plugin uses standard CAccount structure, so we create it
- if (nullptr == (NewMail = new YAMNMAIL))
- //If not created successfully
- return NULL;
- NewMail->MailData = nullptr;
- }
- //Init every members of structure, used by YAMN
- return (INT_PTR)NewMail;
- }
- return NULL;
-}
-
-INT_PTR DeleteAccountMailSvc(WPARAM wParam, LPARAM lParam)
-{
- HYAMNPROTOPLUGIN Plugin = (HYAMNPROTOPLUGIN)wParam;
- HYAMNMAIL OldMail = (HYAMNMAIL)lParam;
- struct CMimeItem *TH;
-
- if (Plugin->MailFcn != nullptr) {
- if (Plugin->MailFcn->DeleteMailFcnPtr != nullptr) {
- //Let plugin delete its own CMimeMsgQueue derived structure
- Plugin->MailFcn->DeleteMailFcnPtr(OldMail);
- return 1;
- }
- }
- if (OldMail->MailData != nullptr) {
- if (OldMail->MailData->Body != nullptr)
- delete[] OldMail->MailData->Body;
- if ((TH = OldMail->MailData->TranslatedHeader) != nullptr)
- for (; OldMail->MailData->TranslatedHeader != nullptr;) {
- TH = TH->Next;
- if (OldMail->MailData->TranslatedHeader->name != nullptr)
- delete[] OldMail->MailData->TranslatedHeader->name;
- if (OldMail->MailData->TranslatedHeader->value != nullptr)
- delete[] OldMail->MailData->TranslatedHeader->value;
- delete OldMail->MailData->TranslatedHeader;
- OldMail->MailData->TranslatedHeader = TH;
- }
- delete OldMail->MailData;
- }
- if (OldMail->ID != nullptr)
- delete[] OldMail->ID;
-
- delete OldMail; //consider mail as standard HYAMNMAIL, not initialized before and use its own destructor
- return 1;
-}
-
-
-void WINAPI AppendQueueFcn(HYAMNMAIL first, HYAMNMAIL second)
-{
- HYAMNMAIL Finder = first;
- while (Finder->Next != nullptr) Finder = Finder->Next;
- Finder->Next = second;
-}
-
-INT_PTR LoadMailDataSvc(WPARAM wParam, LPARAM lParam)
-{
- HYAMNMAIL Mail = (HYAMNMAIL)wParam;
- uint32_t MailVersion = (uint32_t)lParam;
-
- if (MailVersion != YAMN_MAILDATAVERSION)
- return NULL;
-
- // now we have all data to memory persisting, so no loading is needed
- return (INT_PTR)Mail->MailData;
-}
-
-INT_PTR UnloadMailDataSvc(WPARAM, LPARAM)
-{
- return 1;
-}
-
-INT_PTR SaveMailDataSvc(WPARAM, LPARAM lParam)
-{
- uint32_t MailVersion = (uint32_t)lParam;
-
- if (MailVersion != YAMN_MAILDATAVERSION)
- return (INT_PTR)-1;
-
- // now we have all data to memory persisting, so no saving is needed
- return (INT_PTR)0;
-}
-
-void WINAPI SynchroMessagesFcn(CAccount *Account, HYAMNMAIL *OldQueue, HYAMNMAIL *RemovedOld, HYAMNMAIL *NewQueue, HYAMNMAIL *RemovedNew)
-//deletes messages from new queue, if they are old
-//it also deletes messages from old queue, if they are not in mailbox anymore
-//"YAMN_MSG_DELETED" messages in old queue remain in old queue (are never removed, although they are not in new queue)
-//"YAMN_MSG_DELETED" messages in new queue remain in new queue (are never removed, although they can be in old queue)
-{
- HYAMNMAIL Finder, FinderPrev;
- HYAMNMAIL Parser, ParserPrev;
- HYAMNMAIL RemovedOldParser = nullptr;
- HYAMNMAIL RemovedNewParser = nullptr;
- if (RemovedOld != nullptr) *RemovedOld = nullptr;
- if (RemovedNew != nullptr) *RemovedNew = nullptr;
-
- for (FinderPrev = nullptr, Finder = *OldQueue; Finder != nullptr;) {
- if (Finder->Flags & YAMN_MSG_DELETED) //if old queue contains deleted mail
- {
- FinderPrev = Finder;
- Finder = Finder->Next; //get next message in old queue for testing
- continue;
- }
- for (ParserPrev = nullptr, Parser = *NewQueue; Parser != nullptr; ParserPrev = Parser, Parser = Parser->Next) {
- if (Parser->Flags & YAMN_MSG_DELETED)
- continue;
-
- if (Parser->ID == nullptr) //simply ignore the message, that has not filled its ID
- continue;
-
- if (0 == mir_strcmp(Parser->ID, Finder->ID)) //search for equal message in new queue
- break;
- }
- if (Parser != nullptr) //found equal message in new queue
- {
- if (Parser == *NewQueue)
- *NewQueue = (*NewQueue)->Next;
- else
- ParserPrev->Next = Parser->Next;
- Finder->Number = Parser->Number; //rewrite the number of current message in old queue
-
- if (RemovedNew == nullptr) //delete from new queue
- DeleteAccountMailSvc((WPARAM)Account->Plugin, (LPARAM)Parser);
- else //or move to RemovedNew
- {
- if (RemovedNewParser == nullptr) //if it is first mail removed from NewQueue
- *RemovedNew = Parser; //set RemovedNew queue to point to first message in removed queue
- else
- RemovedNewParser->Next = Parser; //else don't forget to show to next message in RemovedNew queue
- RemovedNewParser = Parser; //follow RemovedNew queue
- RemovedNewParser->Next = nullptr;
- }
- FinderPrev = Finder;
- Finder = Finder->Next; //get next message in old queue for testing
- }
- else //a message was already deleted from mailbox
- {
- if (Finder == *OldQueue) //if we are at the first item in OldQueue
- {
- *OldQueue = (*OldQueue)->Next; //set OldQueue to next item
- if (RemovedOld == nullptr) //delete from old queue
- DeleteAccountMailSvc((WPARAM)Account->Plugin, (LPARAM)Finder);
- else //or move to RemovedOld
- {
- if (RemovedOldParser == nullptr) //if it is first mail removed from OldQueue
- *RemovedOld = Finder; //set RemovedOld queue to point to first message in removed queue
- else
- RemovedOldParser->Next = Finder; //else don't forget to show to next message in RemovedNew queue
- RemovedOldParser = Finder; //follow RemovedOld queue
- RemovedOldParser->Next = nullptr;
- }
- Finder = *OldQueue;
- }
- else {
- FinderPrev->Next = Finder->Next;
- if (RemovedOld == nullptr) //delete from old queue
- DeleteAccountMailSvc((WPARAM)Account->Plugin, (LPARAM)Finder);
- else //or move to RemovedOld
- {
- if (RemovedOldParser == nullptr) //if it is first mail removed from OldQueue
- *RemovedOld = Finder; //set RemovedOld queue to point to first message in removed queue
- else
- RemovedOldParser->Next = Finder; //else don't forget to show to next message in RemovedNew queue
- RemovedOldParser = Finder; //follow RemovedOld queue
- RemovedOldParser->Next = nullptr;
- }
- Finder = FinderPrev->Next;
- }
- }
- }
-}
-
-void WINAPI DeleteMessagesToEndFcn(CAccount *Account, HYAMNMAIL From)
-{
- HYAMNMAIL Temp;
- while (From != nullptr) {
- Temp = From;
- From = From->Next;
- DeleteAccountMailSvc((WPARAM)Account->Plugin, (LPARAM)Temp);
- }
-}
-
-void WINAPI DeleteMessageFromQueueFcn(HYAMNMAIL *From, HYAMNMAIL Which, int mode = 0)
-{
- uint32_t Number = Which->Number;
- HYAMNMAIL Parser;
-
- if (*From == Which) {
- Parser = Which->Next;
- *From = Parser;
- }
- else {
- for (Parser = *From; Which != Parser->Next; Parser = Parser->Next)
- if (mode && (Parser->Number > Number)) Parser->Number--;
- if (mode && (Parser->Number > Number)) Parser->Number--;
- Parser->Next = Parser->Next->Next;
- Parser = Which->Next;
- }
- if (mode)
- for (; Parser != nullptr; Parser = Parser->Next)
- if (Parser->Number > Number) Parser->Number--;
-}
-
-void DeleteMessagesFromQueue(HYAMNMAIL *From, HYAMNMAIL Which, int mode = 0)
-{
- HYAMNMAIL Parser;
-
- for (Parser = Which; Parser != nullptr; Parser = Parser->Next)
- DeleteMessageFromQueueFcn(From, Parser, mode);
-}
-
-HYAMNMAIL WINAPI FindMessageByIDFcn(HYAMNMAIL From, char *ID)
-{
- HYAMNMAIL Browser;
-
- for (Browser = From; Browser != nullptr; Browser = Browser->Next)
- if (0 == mir_strcmp(Browser->ID, ID))
- break;
- return Browser;
-}
-
-void WINAPI TranslateHeaderFcn(char *stream, int len, struct CMimeItem **head)
-{
- try {
- char *finder = stream;
- char *prev1, *prev2, *prev3;
- struct CMimeItem *Item = nullptr;
-
- while (finder <= (stream + len)) {
- while (ENDLINEWS(finder)) finder++;
-
- //at the start of line
- if (DOTLINE(finder + 1)) //at the end of stream
- break;
-
- prev1 = finder;
-
- while (*finder != ':' && !EOS(finder)) finder++;
- if (!EOS(finder))
- prev2 = finder++;
- else
- break;
-
- while (WS(finder) && !EOS(finder)) finder++;
- if (!EOS(finder))
- prev3 = finder;
- else
- break;
-
- do {
- if (ENDLINEWS(finder)) finder += 2; //after endline information continues
- while (!ENDLINE(finder) && !EOS(finder)) finder++;
- } while (ENDLINEWS(finder));
-
- if (Item != nullptr) {
- if (nullptr == (Item->Next = new struct CMimeItem))
- break;
- Item = Item->Next;
- }
- else {
- Item = new CMimeItem;
- *head = Item;
- }
-
- Item->Next = nullptr;
- Item->name = new char[prev2 - prev1 + 1];
- mir_strncpy(Item->name, prev1, prev2 - prev1 + 1);
- Item->value = new char[finder - prev3 + 1];
- mir_strncpy(Item->value, prev3, finder - prev3 + 1);
-
- if (EOS(finder))
- break;
- finder++;
- if (ENDLINE(finder)) {
- finder++;
- if (ENDLINE(finder)) {
- // end of headers. message body begins
- finder++;
- if (ENDLINE(finder))finder++;
- prev1 = finder;
- while (!DOTLINE(finder + 1))finder++;
- if (ENDLINE(finder))finder--;
- prev2 = finder;
- if (prev2 > prev1) { // yes, we have body
- if (nullptr == (Item->Next = new struct CMimeItem)) break; // Cant create new item?!
- Item = Item->Next;
- Item->Next = nullptr;//just in case;
- Item->name = new char[5]; strncpy(Item->name, "Body", 5);
- Item->value = new char[prev2 - prev1];
- mir_strncpy(Item->value, prev1, prev2 - prev1 - 1);
- }
- break; // there is nothing else
- }
- }
- }
- }
- catch (...) {
- MessageBoxA(nullptr, "Translate header error", "", 0);
- }
-}
-
-HYAMNMAIL WINAPI CreateNewDeleteQueueFcn(HYAMNMAIL From)
-{
- HYAMNMAIL FirstMail, Browser = nullptr;
-
- for (FirstMail = nullptr; From != nullptr; From = From->Next) {
- if ((From->Flags & (YAMN_MSG_USERDELETE | YAMN_MSG_AUTODELETE)) && !(From->Flags & YAMN_MSG_DELETED)) {
- if (FirstMail == nullptr) {
- FirstMail = Browser = new YAMNMAIL;
- if (FirstMail == nullptr)
- break;
- }
- else {
- Browser->Next = new YAMNMAIL;
- Browser = Browser->Next;
- }
- Browser->ID = new char[mir_strlen(From->ID) + 1];
- mir_strcpy(Browser->ID, From->ID);
- Browser->Number = From->Number;
- Browser->Flags = From->Flags;
- }
- }
- return FirstMail;
-}
-
-void WINAPI SetRemoveFlagsInQueueFcn(HYAMNMAIL From, uint32_t FlagsSet, uint32_t FlagsNotSet, uint32_t FlagsToSetRemove, int mode)
-{
- HYAMNMAIL msgq;
-
- for (msgq = (HYAMNMAIL)From; msgq != nullptr; msgq = msgq->Next) {
- if ((FlagsSet == (msgq->Flags & FlagsSet)) && (0 == (msgq->Flags & FlagsNotSet))) {
- if (mode)
- msgq->Flags = msgq->Flags | FlagsToSetRemove;
- else
- msgq->Flags = msgq->Flags & ~FlagsToSetRemove;
- }
- }
-}
+/*
+ * This code implements retrieving info from MIME header
+ *
+ * (c) majvan 2002-2004
+ */
+
+#include "../stdafx.h"
+
+ //--------------------------------------------------------------------------------------------------
+ //--------------------------------------------------------------------------------------------------
+
+ // SMALL INTRO
+ // Mails are queued in a queue (chained list). Pointer to first mail is pointed from Account structure
+ // member called Mails.
+ // Mail queue is ended with NULL- pointered mail (NULL handle)
+
+ //Creates new mail for plugin (calling plugin's constructor, when plugin imported to YAMN)
+INT_PTR CreateAccountMailSvc(WPARAM wParam, LPARAM lParam);
+
+//Deletes mail for plugin (calling plugin's destructor, when plugin imported to YAMN)
+INT_PTR DeleteAccountMailSvc(WPARAM wParam, LPARAM lParam);
+
+//Loads mail data from standard storage to memory
+INT_PTR LoadMailDataSvc(WPARAM wParam, LPARAM lParam);
+
+//Deletes mail data from memory
+INT_PTR UnloadMailDataSvc(WPARAM wParam, LPARAM);
+
+//Saves mail data from memory to standard storage
+INT_PTR SaveMailDataSvc(WPARAM wParam, LPARAM lParam);
+
+//Appends second MIME mail queue to the first one
+//Only finds the end of first queue and its Next memember repoints to second one
+void WINAPI AppendQueueFcn(HYAMNMAIL first, HYAMNMAIL second);
+
+//Synchronizes two accounts
+//Function finds, if there were some mails deleted from mailbox and deletes (depends on RemovedOld param) them from OldQueue
+//Next finds, if there are new mails. Mails that are still on mailbox are deleted (depends on RemovedNew param) from NewQueue
+//After this, OldQueue is pointer to mails that are on mailbox, but not new mails
+//and NewQueue contains new mails in account
+//New accounts can be then appended to account mails queue, but they have set the New flag
+//
+//Two mails equals if they have the same ID
+//
+// hPlugin- handle of plugin going to delete mails
+// OldQueue- queue of mails that we found on mailbox last time, after function finishes queue contains all mails except new ones
+// RemovedOld- queue of mails where to store removed mails from OldQueue, if NULL deletes mails from OldQueue
+// NewQueue- queue of mails that we found on mailbox (all mails), after function finishes queue contains only new mails
+// RemovedNew- queue of mails where to store removed mails from NewQueue, if NULL deletes mails from NewQueue
+//So function works like:
+//1. delete (or move to RemovedOld queue if RemovedOld is not NULL) all mails from OldQueue not found in NewQueue
+//2. delete (or move to RemovedNew queue if RemovedNew is not NULL) all mails from NewQueue found in OldQueue
+void WINAPI SynchroMessagesFcn(CAccount *Account, HYAMNMAIL *OldQueue, HYAMNMAIL *RemovedOld, HYAMNMAIL *NewQueue, HYAMNMAIL *RemovedNew);
+
+//Deletes messages from mail From to the end
+// Account- account who owns mails
+// From- first mail in queue, which is going to delete
+void WINAPI DeleteMessagesToEndFcn(CAccount *Account, HYAMNMAIL From);
+
+//Removes message from queue, does not delete from memory
+// From- queue pointer
+// Which- mail to delete
+// mode- nonzero if you want to decrement numbers in messages that are bigger than the one in Which mail, 0 if not
+void WINAPI DeleteMessageFromQueueFcn(HYAMNMAIL *From, HYAMNMAIL Which, int mode);
+
+//Finds message in queue that has the same ID number
+// From- message queue
+// ID- pointer to ID
+// returns pointer to found message, NULL if not found
+HYAMNMAIL WINAPI FindMessageByIDFcn(HYAMNMAIL From, char *ID);
+
+//Translate header from text to queue of CMimeItem structures
+//This means that new queue will contain all info about headers
+// stream- pointer to text containing header (can be ended with zero)
+// len- length of stream
+// head- function fills this pointer to first header item in queue
+void WINAPI TranslateHeaderFcn(char *stream, int len, struct CMimeItem **head);
+
+//Creates new mail queue, copying only these mails, that have set flag for deleting
+// From- message queue, whose mail with given flag are duplicated
+// returns new mail queue (or NULL when no mail with flag is in From queue)
+//Function does not copy the whole mails, it copies only ID string. And ID is copied as string, so
+//you can use this fcn only if you have your ID as pointer to char string ended with zero character
+HYAMNMAIL WINAPI CreateNewDeleteQueueFcn(HYAMNMAIL From);
+
+//Sets/removes flags from specific mails
+// From- pointer to first message
+// FlagsSet- mail must have set these flags...
+// FlagsNotSet- ...and must not have set these flags...
+// FlagsToSetRemove- ...to set/remove these flags (see mode)
+// mode- nonzero to set, else remove
+void WINAPI SetRemoveFlagsInQueueFcn(HYAMNMAIL From, uint32_t FlagsSet, uint32_t FlagsNotSet, uint32_t FlagsToSetRemove, int mode);
+
+struct CExportedFunctions MailExportedFcn[] =
+{
+ {YAMN_SYNCHROMIMEMSGSID, (void *)SynchroMessagesFcn},
+ {YAMN_TRANSLATEHEADERID, (void *)TranslateHeaderFcn},
+ {YAMN_APPENDQUEUEID, (void *)AppendQueueFcn},
+ {YAMN_DELETEMIMEQUEUEID, (void *)DeleteMessagesToEndFcn},
+ {YAMN_DELETEMIMEMESSAGEID, (void *)DeleteMessageFromQueueFcn},
+ {YAMN_FINDMIMEMESSAGEID, (void *)FindMessageByIDFcn},
+ {YAMN_CREATENEWDELETEQUEUEID, (void *)CreateNewDeleteQueueFcn},
+ {YAMN_SETREMOVEQUEUEFLAGSID, (void *)SetRemoveFlagsInQueueFcn},
+};
+
+struct CExportedServices MailExportedSvc[] =
+{
+ {MS_YAMN_CREATEACCOUNTMAIL, CreateAccountMailSvc},
+ {MS_YAMN_DELETEACCOUNTMAIL, DeleteAccountMailSvc},
+ {MS_YAMN_LOADMAILDATA, LoadMailDataSvc},
+ {MS_YAMN_UNLOADMAILDATA, UnloadMailDataSvc},
+ {MS_YAMN_SAVEMAILDATA, SaveMailDataSvc},
+};
+
+
+//--------------------------------------------------------------------------------------------------
+//--------------------------------------------------------------------------------------------------
+
+INT_PTR CreateAccountMailSvc(WPARAM wParam, LPARAM lParam)
+{
+ CAccount *Account = (CAccount *)wParam;
+ uint32_t MailVersion = (uint32_t)lParam;
+ HYAMNMAIL NewMail;
+
+ //test if we are going to initialize members of suitable structure (structures of plugin and YAMN must match)
+ if (MailVersion != YAMN_MAILVERSION)
+ return NULL;
+
+ if (Account->Plugin != nullptr) {
+ if (Account->Plugin->MailFcn->NewMailFcnPtr != nullptr) {
+ //Let plugin create its own structure, which can be derived from CAccount structure
+ if (nullptr == (NewMail = Account->Plugin->MailFcn->NewMailFcnPtr(Account, YAMN_MAILVERSION)))
+ return NULL;
+ }
+ else {
+ //We suggest plugin uses standard CAccount structure, so we create it
+ if (nullptr == (NewMail = new YAMNMAIL))
+ //If not created successfully
+ return NULL;
+ NewMail->MailData = nullptr;
+ }
+ //Init every members of structure, used by YAMN
+ return (INT_PTR)NewMail;
+ }
+ return NULL;
+}
+
+INT_PTR DeleteAccountMailSvc(WPARAM wParam, LPARAM lParam)
+{
+ HYAMNPROTOPLUGIN Plugin = (HYAMNPROTOPLUGIN)wParam;
+ HYAMNMAIL OldMail = (HYAMNMAIL)lParam;
+ struct CMimeItem *TH;
+
+ if (Plugin->MailFcn != nullptr) {
+ if (Plugin->MailFcn->DeleteMailFcnPtr != nullptr) {
+ //Let plugin delete its own CMimeMsgQueue derived structure
+ Plugin->MailFcn->DeleteMailFcnPtr(OldMail);
+ return 1;
+ }
+ }
+ if (OldMail->MailData != nullptr) {
+ if (OldMail->MailData->Body != nullptr)
+ delete[] OldMail->MailData->Body;
+ if ((TH = OldMail->MailData->TranslatedHeader) != nullptr)
+ for (; OldMail->MailData->TranslatedHeader != nullptr;) {
+ TH = TH->Next;
+ if (OldMail->MailData->TranslatedHeader->name != nullptr)
+ delete[] OldMail->MailData->TranslatedHeader->name;
+ if (OldMail->MailData->TranslatedHeader->value != nullptr)
+ delete[] OldMail->MailData->TranslatedHeader->value;
+ delete OldMail->MailData->TranslatedHeader;
+ OldMail->MailData->TranslatedHeader = TH;
+ }
+ delete OldMail->MailData;
+ }
+ if (OldMail->ID != nullptr)
+ delete[] OldMail->ID;
+
+ delete OldMail; //consider mail as standard HYAMNMAIL, not initialized before and use its own destructor
+ return 1;
+}
+
+
+void WINAPI AppendQueueFcn(HYAMNMAIL first, HYAMNMAIL second)
+{
+ HYAMNMAIL Finder = first;
+ while (Finder->Next != nullptr) Finder = Finder->Next;
+ Finder->Next = second;
+}
+
+INT_PTR LoadMailDataSvc(WPARAM wParam, LPARAM lParam)
+{
+ HYAMNMAIL Mail = (HYAMNMAIL)wParam;
+ uint32_t MailVersion = (uint32_t)lParam;
+
+ if (MailVersion != YAMN_MAILDATAVERSION)
+ return NULL;
+
+ // now we have all data to memory persisting, so no loading is needed
+ return (INT_PTR)Mail->MailData;
+}
+
+INT_PTR UnloadMailDataSvc(WPARAM, LPARAM)
+{
+ return 1;
+}
+
+INT_PTR SaveMailDataSvc(WPARAM, LPARAM lParam)
+{
+ uint32_t MailVersion = (uint32_t)lParam;
+
+ if (MailVersion != YAMN_MAILDATAVERSION)
+ return (INT_PTR)-1;
+
+ // now we have all data to memory persisting, so no saving is needed
+ return (INT_PTR)0;
+}
+
+void WINAPI SynchroMessagesFcn(CAccount *Account, HYAMNMAIL *OldQueue, HYAMNMAIL *RemovedOld, HYAMNMAIL *NewQueue, HYAMNMAIL *RemovedNew)
+//deletes messages from new queue, if they are old
+//it also deletes messages from old queue, if they are not in mailbox anymore
+//"YAMN_MSG_DELETED" messages in old queue remain in old queue (are never removed, although they are not in new queue)
+//"YAMN_MSG_DELETED" messages in new queue remain in new queue (are never removed, although they can be in old queue)
+{
+ HYAMNMAIL Finder, FinderPrev;
+ HYAMNMAIL Parser, ParserPrev;
+ HYAMNMAIL RemovedOldParser = nullptr;
+ HYAMNMAIL RemovedNewParser = nullptr;
+ if (RemovedOld != nullptr) *RemovedOld = nullptr;
+ if (RemovedNew != nullptr) *RemovedNew = nullptr;
+
+ for (FinderPrev = nullptr, Finder = *OldQueue; Finder != nullptr;) {
+ if (Finder->Flags & YAMN_MSG_DELETED) //if old queue contains deleted mail
+ {
+ FinderPrev = Finder;
+ Finder = Finder->Next; //get next message in old queue for testing
+ continue;
+ }
+ for (ParserPrev = nullptr, Parser = *NewQueue; Parser != nullptr; ParserPrev = Parser, Parser = Parser->Next) {
+ if (Parser->Flags & YAMN_MSG_DELETED)
+ continue;
+
+ if (Parser->ID == nullptr) //simply ignore the message, that has not filled its ID
+ continue;
+
+ if (0 == mir_strcmp(Parser->ID, Finder->ID)) //search for equal message in new queue
+ break;
+ }
+ if (Parser != nullptr) //found equal message in new queue
+ {
+ if (Parser == *NewQueue)
+ *NewQueue = (*NewQueue)->Next;
+ else
+ ParserPrev->Next = Parser->Next;
+ Finder->Number = Parser->Number; //rewrite the number of current message in old queue
+
+ if (RemovedNew == nullptr) //delete from new queue
+ DeleteAccountMailSvc((WPARAM)Account->Plugin, (LPARAM)Parser);
+ else //or move to RemovedNew
+ {
+ if (RemovedNewParser == nullptr) //if it is first mail removed from NewQueue
+ *RemovedNew = Parser; //set RemovedNew queue to point to first message in removed queue
+ else
+ RemovedNewParser->Next = Parser; //else don't forget to show to next message in RemovedNew queue
+ RemovedNewParser = Parser; //follow RemovedNew queue
+ RemovedNewParser->Next = nullptr;
+ }
+ FinderPrev = Finder;
+ Finder = Finder->Next; //get next message in old queue for testing
+ }
+ else //a message was already deleted from mailbox
+ {
+ if (Finder == *OldQueue) //if we are at the first item in OldQueue
+ {
+ *OldQueue = (*OldQueue)->Next; //set OldQueue to next item
+ if (RemovedOld == nullptr) //delete from old queue
+ DeleteAccountMailSvc((WPARAM)Account->Plugin, (LPARAM)Finder);
+ else //or move to RemovedOld
+ {
+ if (RemovedOldParser == nullptr) //if it is first mail removed from OldQueue
+ *RemovedOld = Finder; //set RemovedOld queue to point to first message in removed queue
+ else
+ RemovedOldParser->Next = Finder; //else don't forget to show to next message in RemovedNew queue
+ RemovedOldParser = Finder; //follow RemovedOld queue
+ RemovedOldParser->Next = nullptr;
+ }
+ Finder = *OldQueue;
+ }
+ else {
+ FinderPrev->Next = Finder->Next;
+ if (RemovedOld == nullptr) //delete from old queue
+ DeleteAccountMailSvc((WPARAM)Account->Plugin, (LPARAM)Finder);
+ else //or move to RemovedOld
+ {
+ if (RemovedOldParser == nullptr) //if it is first mail removed from OldQueue
+ *RemovedOld = Finder; //set RemovedOld queue to point to first message in removed queue
+ else
+ RemovedOldParser->Next = Finder; //else don't forget to show to next message in RemovedNew queue
+ RemovedOldParser = Finder; //follow RemovedOld queue
+ RemovedOldParser->Next = nullptr;
+ }
+ Finder = FinderPrev->Next;
+ }
+ }
+ }
+}
+
+void WINAPI DeleteMessagesToEndFcn(CAccount *Account, HYAMNMAIL From)
+{
+ HYAMNMAIL Temp;
+ while (From != nullptr) {
+ Temp = From;
+ From = From->Next;
+ DeleteAccountMailSvc((WPARAM)Account->Plugin, (LPARAM)Temp);
+ }
+}
+
+void WINAPI DeleteMessageFromQueueFcn(HYAMNMAIL *From, HYAMNMAIL Which, int mode = 0)
+{
+ uint32_t Number = Which->Number;
+ HYAMNMAIL Parser;
+
+ if (*From == Which) {
+ Parser = Which->Next;
+ *From = Parser;
+ }
+ else {
+ for (Parser = *From; Which != Parser->Next; Parser = Parser->Next)
+ if (mode && (Parser->Number > Number)) Parser->Number--;
+ if (mode && (Parser->Number > Number)) Parser->Number--;
+ Parser->Next = Parser->Next->Next;
+ Parser = Which->Next;
+ }
+ if (mode)
+ for (; Parser != nullptr; Parser = Parser->Next)
+ if (Parser->Number > Number) Parser->Number--;
+}
+
+void DeleteMessagesFromQueue(HYAMNMAIL *From, HYAMNMAIL Which, int mode = 0)
+{
+ HYAMNMAIL Parser;
+
+ for (Parser = Which; Parser != nullptr; Parser = Parser->Next)
+ DeleteMessageFromQueueFcn(From, Parser, mode);
+}
+
+HYAMNMAIL WINAPI FindMessageByIDFcn(HYAMNMAIL From, char *ID)
+{
+ HYAMNMAIL Browser;
+
+ for (Browser = From; Browser != nullptr; Browser = Browser->Next)
+ if (0 == mir_strcmp(Browser->ID, ID))
+ break;
+ return Browser;
+}
+
+void WINAPI TranslateHeaderFcn(char *stream, int len, struct CMimeItem **head)
+{
+ try {
+ char *finder = stream;
+ char *prev1, *prev2, *prev3;
+ struct CMimeItem *Item = nullptr;
+
+ while (finder <= (stream + len)) {
+ while (ENDLINEWS(finder)) finder++;
+
+ //at the start of line
+ if (DOTLINE(finder + 1)) //at the end of stream
+ break;
+
+ prev1 = finder;
+
+ while (*finder != ':' && !EOS(finder)) finder++;
+ if (!EOS(finder))
+ prev2 = finder++;
+ else
+ break;
+
+ while (WS(finder) && !EOS(finder)) finder++;
+ if (!EOS(finder))
+ prev3 = finder;
+ else
+ break;
+
+ do {
+ if (ENDLINEWS(finder)) finder += 2; //after endline information continues
+ while (!ENDLINE(finder) && !EOS(finder)) finder++;
+ } while (ENDLINEWS(finder));
+
+ if (Item != nullptr) {
+ if (nullptr == (Item->Next = new struct CMimeItem))
+ break;
+ Item = Item->Next;
+ }
+ else {
+ Item = new CMimeItem;
+ *head = Item;
+ }
+
+ Item->Next = nullptr;
+ Item->name = new char[prev2 - prev1 + 1];
+ mir_strncpy(Item->name, prev1, prev2 - prev1 + 1);
+ Item->value = new char[finder - prev3 + 1];
+ mir_strncpy(Item->value, prev3, finder - prev3 + 1);
+
+ if (EOS(finder))
+ break;
+ finder++;
+ if (ENDLINE(finder)) {
+ finder++;
+ if (ENDLINE(finder)) {
+ // end of headers. message body begins
+ finder++;
+ if (ENDLINE(finder))finder++;
+ prev1 = finder;
+ while (!DOTLINE(finder + 1))finder++;
+ if (ENDLINE(finder))finder--;
+ prev2 = finder;
+ if (prev2 > prev1) { // yes, we have body
+ if (nullptr == (Item->Next = new struct CMimeItem)) break; // Cant create new item?!
+ Item = Item->Next;
+ Item->Next = nullptr;//just in case;
+ Item->name = new char[5]; strncpy(Item->name, "Body", 5);
+ Item->value = new char[prev2 - prev1];
+ mir_strncpy(Item->value, prev1, prev2 - prev1 - 1);
+ }
+ break; // there is nothing else
+ }
+ }
+ }
+ }
+ catch (...) {
+ MessageBoxA(nullptr, "Translate header error", "", 0);
+ }
+}
+
+HYAMNMAIL WINAPI CreateNewDeleteQueueFcn(HYAMNMAIL From)
+{
+ HYAMNMAIL FirstMail, Browser = nullptr;
+
+ for (FirstMail = nullptr; From != nullptr; From = From->Next) {
+ if ((From->Flags & (YAMN_MSG_USERDELETE | YAMN_MSG_AUTODELETE)) && !(From->Flags & YAMN_MSG_DELETED)) {
+ if (FirstMail == nullptr) {
+ FirstMail = Browser = new YAMNMAIL;
+ if (FirstMail == nullptr)
+ break;
+ }
+ else {
+ Browser->Next = new YAMNMAIL;
+ Browser = Browser->Next;
+ }
+ Browser->ID = new char[mir_strlen(From->ID) + 1];
+ mir_strcpy(Browser->ID, From->ID);
+ Browser->Number = From->Number;
+ Browser->Flags = From->Flags;
+ }
+ }
+ return FirstMail;
+}
+
+void WINAPI SetRemoveFlagsInQueueFcn(HYAMNMAIL From, uint32_t FlagsSet, uint32_t FlagsNotSet, uint32_t FlagsToSetRemove, int mode)
+{
+ HYAMNMAIL msgq;
+
+ for (msgq = (HYAMNMAIL)From; msgq != nullptr; msgq = msgq->Next) {
+ if ((FlagsSet == (msgq->Flags & FlagsSet)) && (0 == (msgq->Flags & FlagsNotSet))) {
+ if (mode)
+ msgq->Flags = msgq->Flags | FlagsToSetRemove;
+ else
+ msgq->Flags = msgq->Flags & ~FlagsToSetRemove;
+ }
+ }
+}
diff --git a/protocols/YAMN/src/mails/mime.cpp b/protocols/YAMN/src/mails/mime.cpp
index 69099af808..2a2e7b4665 100644
--- a/protocols/YAMN/src/mails/mime.cpp
+++ b/protocols/YAMN/src/mails/mime.cpp
@@ -1,695 +1,695 @@
-/*
- * This code implements retrieving info from MIME header
- *
- * (c) majvan 2002-2004
- */
-
-#include "../stdafx.h"
-
- //--------------------------------------------------------------------------------------------------
-
- //Copies one string to another
- // srcstart- source string
- // srcend- address to the end of source string
- // dest- pointer that stores new allocated string that contains copy of source string
- // mode- MIME_PLAIN or MIME_MAIL (MIME_MAIL deletes '"' characters (or '<' and '>') if they are at start and end of source string
-void CopyToHeader(char *srcstart, char *srcend, char **dest, int mode);
-
-//Extracts email address (finds nick name and mail and then stores them to strings)
-// finder- source string
-// storeto- pointer that receives address of mail string
-// storetonick- pointer that receives address of nickname
-void ExtractAddressFromLine(char *finder, char **storeto, char **storetonick);
-
-//Extracts simple text from string
-// finder- source string
-// storeto- pointer that receives address of string
-void ExtractStringFromLine(char *finder, char **storeto);
-
-//Extracts some item from content-type string
-//Example: ContentType string: "TEXT/PLAIN; charset=US-ASCII", item:"charset=", returns: "US-ASCII"
-// ContetType- content-type string
-// value- string item
-// returns extracted string (or NULL when not found)
-char *ExtractFromContentType(char *ContentType, char *value);
-
-//Extracts info from header text into header members
-//Note that this function as well as struct CShortHeadwer can be always changed, because there are many items to extract
-//(e.g. the X-Priority and Importance and so on)
-// items- translated header (see TranslateHeaderFcn)
-// head- header to be filled with values extracted from items
-void ExtractShortHeader(struct CMimeItem *items, struct CShortHeader *head);
-
-//Extracts header to mail using ExtractShortHeader fcn.
-// items- translated header (see TranslateHeaderFcn)
-// CP- codepage used when no default found
-// head- header to be filled with values extracted from items, in unicode (wide char)
-void ExtractHeader(struct CMimeItem *items, int &CP, struct CHeader *head);
-
-//Deletes items in CShortHeader structure
-// head- structure whose items are deleted
-void DeleteShortHeaderContent(struct CShortHeader *head);
-
-//Deletes list of YAMN_MIMENAMES structures
-// Names- pointer to first item of list
-void DeleteNames(CMimeNames *Names);
-
-//Deletes list of YAMN_MIMESHORTNAMES structures
-// Names- pointer to first item of list
-void DeleteShortNames(CShortNames *Names);
-
-//Makes a string lowercase
-// string- string to be lowercased
-void inline ToLower(char *string);
-
-//--------------------------------------------------------------------------------------------------
-//--------------------------------------------------------------------------------------------------
-
-void CopyToHeader(char *srcstart, char *srcend, char **dest, int mode)
-{
- char *dst;
-
- if (dest == nullptr)
- return;
- if (srcstart >= srcend)
- return;
-
- if ((mode == MIME_MAIL) && (((*srcstart == '"') && (*(srcend - 1) == '"')) || ((*srcstart == '<') && (*(srcend - 1) == '>')))) {
- srcstart++;
- srcend--;
- }
-
- if (srcstart >= srcend)
- return;
-
- if (nullptr != *dest)
- delete[] * dest;
- if (nullptr == (*dest = new char[srcend - srcstart + 1]))
- return;
-
- dst = *dest;
-
- for (; srcstart < srcend; dst++, srcstart++) {
- if (ENDLINE(srcstart)) {
- while (ENDLINE(srcstart) || WS(srcstart)) srcstart++;
- *dst = ' ';
- srcstart--; //because at the end of "for loop" we increment srcstart
- }
- else
- *dst = *srcstart;
- }
- *dst = 0;
-}
-
-void ExtractAddressFromLine(char *finder, char **storeto, char **storetonick)
-{
- if (finder == nullptr) {
- *storeto = *storetonick = nullptr;
- return;
- }
- while (WS(finder)) finder++;
- if ((*finder) != '<') {
- char *finderend = finder + 1;
- do {
- if (ENDLINEWS(finderend)) //after endline information continues
- finderend += 2;
- while (!ENDLINE(finderend) && !EOS(finderend)) finderend++; //seek to the end of line or to the end of string
- } while (ENDLINEWS(finderend));
- finderend--;
- while (WS(finderend) || ENDLINE(finderend)) finderend--; //find the end of text, no whitespace
- if (*finderend != '>') //not '>' at the end of line
- CopyToHeader(finder, finderend + 1, storeto, MIME_MAIL);
- else //at the end of line, there's '>'
- {
- char *finder2 = finderend;
- while ((*finder2 != '<') && (finder2 > finder)) finder2--; //go to matching '<' or to the start
- CopyToHeader(finder2, finderend + 1, storeto, MIME_MAIL);
- if (*finder2 == '<') //if we found '<', the rest copy as from nick
- {
- finder2--;
- while (WS(finder2) || ENDLINE(finder2)) finder2--; //parse whitespace
- CopyToHeader(finder, finder2 + 1, storetonick, MIME_MAIL); //and store nickname
- }
- }
- }
- else {
- char *finderend = finder + 1;
- do {
- if (ENDLINEWS(finderend)) //after endline information continues
- finderend += 2;
- while (!ENDLINE(finderend) && (*finderend != '>') && !EOS(finderend)) finderend++; //seek to the matching < or to the end of line or to the end of string
- } while (ENDLINEWS(finderend));
- CopyToHeader(finder, finderend + 1, storeto, MIME_MAIL); //go to first '>' or to the end and copy
- finder = finderend + 1;
- while (WS(finder)) finder++; //parse whitespace
- if (!ENDLINE(finder) && !EOS(finder)) //if there are chars yet, it's nick
- {
- finderend = finder + 1;
- while (!ENDLINE(finderend) && !EOS(finderend)) finderend++; //seek to the end of line or to the end of string
- finderend--;
- while (WS(finderend)) finderend--; //find the end of line, no whitespace
- CopyToHeader(finder, finderend + 1, storetonick, MIME_MAIL);
- }
- }
-}
-
-void ExtractStringFromLine(char *finder, char **storeto)
-{
- if (finder == nullptr) {
- *storeto = nullptr;
- return;
- }
- while (WS(finder)) finder++;
- char *finderend = finder;
-
- do {
- if (ENDLINEWS(finderend)) finderend++; //after endline information continues
- while (!ENDLINE(finderend) && !EOS(finderend)) finderend++;
- } while (ENDLINEWS(finderend));
- finderend--;
- while (WS(finderend)) finderend--; //find the end of line, no whitespace
- CopyToHeader(finder, finderend + 1, storeto, MIME_PLAIN);
-}
-
-char *ExtractFromContentType(char *ContentType, char *value)
-{
- char *lowered = _strdup(ContentType);
- ToLower(lowered);
- char *finder = strstr(lowered, value);
- if (finder == nullptr) {
- free(lowered);
- return nullptr;
- }
- finder = finder - lowered + ContentType;
- free(lowered);
-
- char *temp, *copier;
- char *CopiedString;
-
- temp = finder - 1;
- while ((temp > ContentType) && WS(temp)) temp--; //now we have to find, if the word "Charset=" is located after ';' like "; Charset="
- if (*temp != ';' && !ENDLINE(temp) && temp != ContentType)
- return nullptr;
- finder = finder + mir_strlen(value); //jump over value string
-
- while (WS(finder)) finder++; //jump over whitespaces
- temp = finder;
- while (*temp != 0 && *temp != ';') temp++; //jump to the end of setting (to the next ;)
- temp--;
- while (WS(temp)) temp--; //remove whitespaces from the end
- if (*finder == '\"') { //remove heading and tailing quotes
- finder++;
- if (*temp == '\"') temp--;
- }
- if (nullptr == (CopiedString = new char[++temp - finder + 1]))
- return nullptr;
- for (copier = CopiedString; finder != temp; *copier++ = *finder++); //copy string
- *copier = 0; //and end it with zero character
-
- return CopiedString;
-}
-
-void ExtractShortHeader(struct CMimeItem *items, struct CShortHeader *head)
-{
- for (; items != nullptr; items = items->Next) {
- //at the start of line
- //MessageBox(NULL,items->value,items->name,0);
- if (0 == _strnicmp(items->name, "From", 4)) {
- if (items->value == nullptr)
- continue;
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "<Extracting from>");
- #endif
- ExtractAddressFromLine(items->value, &head->From, &head->FromNick);
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "</Extracting>\n");
- #endif
- }
- else if (0 == _strnicmp(items->name, "Return-Path", 11)) {
- if (items->value == nullptr)
- continue;
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "<Extracting return-path>");
- #endif
- ExtractAddressFromLine(items->value, &head->ReturnPath, &head->ReturnPathNick);
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "</Extracting>\n");
- #endif
- }
- else if (0 == _strnicmp(items->name, "Subject", 7)) {
- if (items->value == nullptr)
- continue;
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "<Extracting subject>");
- #endif
- ExtractStringFromLine(items->value, &head->Subject);
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "</Extracting>\n");
- #endif
- }
- else if (0 == _strnicmp(items->name, "Body", 4)) {
- if (items->value == nullptr)
- continue;
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "<Extracting body>");
- #endif
- ExtractStringFromLine(items->value, &head->Body);
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "</Extracting>\n");
- #endif
- }
- else if (0 == _strnicmp(items->name, "Date", 4)) {
- if (items->value == nullptr)
- continue;
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "<Extracting date>");
- #endif
- ExtractStringFromLine(items->value, &head->Date);
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "</Extracting>\n");
- #endif
- }
- else if (0 == _strnicmp(items->name, "Content-Type", 12)) {
- if (items->value == nullptr)
- continue;
-
- char *ContentType = nullptr, *CharSetStr;
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "<Extracting Content-Type>");
- #endif
- ExtractStringFromLine(items->value, &ContentType);
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "</Extracting>\n");
- #endif
- ToLower(ContentType);
- if (nullptr != (CharSetStr = ExtractFromContentType(ContentType, "charset="))) {
- head->CP = GetCharsetFromString(CharSetStr, mir_strlen(CharSetStr));
- delete[] CharSetStr;
- }
- delete[] ContentType;
- }
- else if (0 == _strnicmp(items->name, "Importance", 10)) {
- if (items->value == nullptr)
- continue;
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "<Extracting importance>");
- #endif
- if (head->Priority != -1) {
- if (0 == strncmp(items->value, "low", 3))
- head->Priority = 5;
- else if (0 == strncmp(items->value, "normal", 6))
- head->Priority = 3;
- else if (0 == strncmp(items->value, "high", 4))
- head->Priority = 1;
- }
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "</Extracting>\n");
- #endif
- }
- else if (0 == _strnicmp(items->name, "X-Priority", 10)) {
- if (items->value == nullptr)
- continue;
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "<X-Priority>");
- #endif
- if ((*items->value >= '1') && (*items->value <= '5'))
- head->Priority = *items->value - '0';
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "</Extracting>\n");
- #endif
- }
-
- }
-}
-
-void ExtractHeader(struct CMimeItem *items, int &CP, struct CHeader *head)
-{
- struct CShortHeader ShortHeader;
-
- memset(&ShortHeader, 0, sizeof(struct CShortHeader));
- ShortHeader.Priority = ShortHeader.CP = -1;
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "<Extracting header>\n");
- #endif
- ExtractShortHeader(items, &ShortHeader);
-
- head->Priority = ShortHeader.Priority == -1 ? 3 : ShortHeader.Priority;
- CP = ShortHeader.CP == -1 ? CP : ShortHeader.CP;
- #ifdef DEBUG_DECODE
- if (NULL != ShortHeader.From)
- DebugLog(DecodeFile, "<Decoded from>%s</Decoded)\n", ShortHeader.From);
- if (NULL != ShortHeader.FromNick)
- DebugLog(DecodeFile, "<Decoded from-nick>%s</Decoded)\n", ShortHeader.FromNick);
- if (NULL != ShortHeader.ReturnPath)
- DebugLog(DecodeFile, "<Decoded return-path>%s</Decoded)\n", ShortHeader.ReturnPath);
- if (NULL != ShortHeader.ReturnPathNick)
- DebugLog(DecodeFile, "<Decoded return-path nick>%s</Decoded)\n", ShortHeader.ReturnPathNick);
- if (NULL != ShortHeader.Subject)
- DebugLog(DecodeFile, "<Decoded subject>%s</Decoded)\n", ShortHeader.Subject);
- if (NULL != ShortHeader.Date)
- DebugLog(DecodeFile, "<Decoded date>%s</Decoded)\n", ShortHeader.Date);
- DebugLog(DecodeFile, "</Extracting header>\n");
- DebugLog(DecodeFile, "<Convert>\n");
- #endif
-
- ConvertCodedStringToUnicode(ShortHeader.From, &head->From, CP, MIME_PLAIN);
-
- #ifdef DEBUG_DECODE
- if (NULL != head->From)
- DebugLogW(DecodeFile, L"<Converted from>%s</Converted>\n", head->From);
- #endif
- ConvertCodedStringToUnicode(ShortHeader.FromNick, &head->FromNick, CP, MIME_MAIL);
- #ifdef DEBUG_DECODE
- if (NULL != head->FromNick)
- DebugLogW(DecodeFile, L"<Converted from-nick>%s</Converted>\n", head->FromNick);
- #endif
- ConvertCodedStringToUnicode(ShortHeader.ReturnPath, &head->ReturnPath, CP, MIME_PLAIN);
- #ifdef DEBUG_DECODE
- if (NULL != head->ReturnPath)
- DebugLogW(DecodeFile, L"<Converted return-path>%s</Converted>\n", head->ReturnPath);
- #endif
- ConvertCodedStringToUnicode(ShortHeader.ReturnPathNick, &head->ReturnPathNick, CP, MIME_MAIL);
- #ifdef DEBUG_DECODE
- if (NULL != head->ReturnPathNick)
- DebugLogW(DecodeFile, L"<Converted return-path nick>%s</Converted>\n", head->ReturnPathNick);
- #endif
- ConvertCodedStringToUnicode(ShortHeader.Subject, &head->Subject, CP, MIME_PLAIN);
- #ifdef DEBUG_DECODE
- if (NULL != head->Subject)
- DebugLogW(DecodeFile, L"<Converted subject>%s</Converted>\n", head->Subject);
- #endif
- ConvertCodedStringToUnicode(ShortHeader.Date, &head->Date, CP, MIME_PLAIN);
- #ifdef DEBUG_DECODE
- if (NULL != head->Date)
- DebugLogW(DecodeFile, L"<Converted date>%s</Converted>\n", head->Date);
- #endif
-
- ConvertCodedStringToUnicode(ShortHeader.Body, &head->Body, CP, MIME_PLAIN);
- #ifdef DEBUG_DECODE
- if (NULL != head->Body)
- DebugLogW(DecodeFile, L"<Converted Body>%s</Converted>\n", head->Body);
- #endif
-
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "</Convert>\n");
- #endif
-
- DeleteShortHeaderContent(&ShortHeader);
-
- // head->From=L"Frommmm";
- // head->Subject=L"Subject";
- return;
-}
-
-void DeleteShortHeaderContent(struct CShortHeader *head)
-{
- if (head->From != nullptr) delete[] head->From;
- if (head->FromNick != nullptr) delete[] head->FromNick;
- if (head->ReturnPath != nullptr) delete[] head->ReturnPath;
- if (head->ReturnPathNick != nullptr) delete[] head->ReturnPathNick;
- if (head->Subject != nullptr) delete[] head->Subject;
- if (head->Date != nullptr) delete[] head->Date;
- if (head->To != nullptr) DeleteShortNames(head->To);
- if (head->Cc != nullptr) DeleteShortNames(head->Cc);
- if (head->Bcc != nullptr) DeleteShortNames(head->Bcc);
- if (head->Body != nullptr) delete[] head->Body;
-}
-
-void DeleteHeaderContent(struct CHeader *head)
-{
- if (head->From != nullptr) delete[] head->From;
- if (head->FromNick != nullptr) delete[] head->FromNick;
- if (head->ReturnPath != nullptr) delete[] head->ReturnPath;
- if (head->ReturnPathNick != nullptr) delete[] head->ReturnPathNick;
- if (head->Subject != nullptr) delete[] head->Subject;
- if (head->Date != nullptr) delete[] head->Date;
- if (head->Body != nullptr) delete[] head->Body;
- if (head->To != nullptr) DeleteNames(head->To);
- if (head->Cc != nullptr) DeleteNames(head->Cc);
- if (head->Bcc != nullptr) DeleteNames(head->Bcc);
-}
-
-void DeleteNames(CMimeNames *Names)
-{
- CMimeNames *Parser = Names;
- for (; Parser != nullptr; Parser = Parser->Next) {
- if (Parser->Value != nullptr)
- delete[] Parser->Value;
- if (Parser->ValueNick != nullptr)
- delete[] Parser->ValueNick;
-
- CMimeNames *Old = Parser;
- Parser = Parser->Next;
- delete Old;
- }
-}
-
-void DeleteShortNames(CShortNames *Names)
-{
- CShortNames *Parser = Names;
- for (; Parser != nullptr; Parser = Parser->Next) {
- if (Parser->Value != nullptr)
- delete[] Parser->Value;
- if (Parser->ValueNick != nullptr)
- delete[] Parser->ValueNick;
-
- CShortNames *Old = Parser;
- Parser = Parser->Next;
- delete Old;
- }
-}
-
-
-void inline ToLower(char *string)
-{
- for (; *string != 0; string++)
- if (*string >= 'A' && *string <= 'Z') *string = *string - 'A' + 'a';
-}
-
-#define TE_UNKNOWN
-#define TE_QUOTEDPRINTABLE 1
-#define TE_BASE64 2
-struct APartDataType
-{
- char *Src;//Input
- char *ContType;
- int CodePage;
- char *TransEnc;
- uint8_t TransEncType; //TE_something
- char *body;
- int bodyLen;
- wchar_t *wBody;
-};
-
-
-void ParseAPart(APartDataType *data)
-{
- size_t len = mir_strlen(data->Src);
- try {
- char *finder = data->Src;
- char *prev1, *prev2, *prev3;
-
- while (finder <= (data->Src + len)) {
- while (ENDLINEWS(finder)) finder++;
-
- //at the start of line
- if (finder > data->Src) {
- if (*(finder - 2) == '\r' || *(finder - 2) == '\n')
- *(finder - 2) = 0;
- if (*(finder - 1) == '\r' || *(finder - 1) == '\n')
- *(finder - 1) = 0;
- }
- prev1 = finder;
-
- while (*finder != ':' && !EOS(finder) && !ENDLINE(finder)) finder++;
- if (ENDLINE(finder) || EOS(finder)) {
- // no ":" in the line? here the body begins;
- data->body = prev1;
- break;
- }
- prev2 = finder++;
-
- while (WS(finder) && !EOS(finder)) finder++;
- if (!EOS(finder))
- prev3 = finder;
- else
- break;
-
- do {
- if (ENDLINEWS(finder)) finder += 2; //after endline information continues
- while (!ENDLINE(finder) && !EOS(finder)) finder++;
- } while (ENDLINEWS(finder));
-
- if (!_strnicmp(prev1, "Content-type", prev2 - prev1)) {
- data->ContType = prev3;
- }
- else if (!_strnicmp(prev1, "Content-Transfer-Encoding", prev2 - prev1)) {
- data->TransEnc = prev3;
- }
-
- if (EOS(finder))
- break;
- finder++;
- if (ENDLINE(finder)) {
- finder++;
- if (ENDLINE(finder)) {
- // end of headers. message body begins
- if (finder > data->Src) {
- if (*(finder - 2) == '\r' || *(finder - 2) == '\n')
- *(finder - 2) = 0;
- if (*(finder - 1) == '\r' || *(finder - 1) == '\n')
- *(finder - 1) = 0;
- }
- finder++;
- if (ENDLINE(finder))finder++;
- prev1 = finder;
- while (!EOS(finder + 1))finder++;
- if (ENDLINE(finder))finder--;
- prev2 = finder;
- if (prev2 > prev1) { // yes, we have body
- data->body = prev1;
- }
- break; // there is nothing else
- }
- }
- }
- }
- catch (...) {
- MessageBox(nullptr, TranslateT("Translate header error"), L"", 0);
- }
- if (data->body) data->bodyLen = (int)mir_strlen(data->body);
-}
-
-//from decode.cpp
-int DecodeQuotedPrintable(char *Src, char *Dst, int DstLen, BOOL isQ);
-int DecodeBase64(char *Src, char *Dst, int DstLen);
-int ConvertStringToUnicode(char *stream, unsigned int cp, wchar_t **out);
-
-wchar_t *ParseMultipartBody(char *src, char *bond)
-{
- char *srcback = _strdup(src);
- size_t sizebond = mir_strlen(bond);
- int numparts = 1;
- int i;
- char *courbond = srcback;
- wchar_t *dest;
- for (; (courbond = strstr(courbond, bond)); numparts++, courbond += sizebond);
- APartDataType *partData = new APartDataType[numparts];
- memset(partData, 0, sizeof(APartDataType) * numparts);
- partData[0].Src = courbond = srcback;
- for (i = 1; (courbond = strstr(courbond, bond)); i++, courbond += sizebond) {
- *(courbond - 2) = 0;
- partData[i].Src = courbond + sizebond;
- while (ENDLINE(partData[i].Src)) partData[i].Src++;
- }
- size_t resultSize = 0;
- for (i = 0; i < numparts; i++) {
- ParseAPart(&partData[i]);
- if (partData[i].body) {
- if (partData[i].TransEnc) {
- if (!_stricmp(partData[i].TransEnc, "base64")) partData[i].TransEncType = TE_BASE64;
- else if (!_stricmp(partData[i].TransEnc, "quoted-printable"))partData[i].TransEncType = TE_QUOTEDPRINTABLE;
- }
- if (partData[i].ContType) {
- char *CharSetStr;
- if (nullptr != (CharSetStr = ExtractFromContentType(partData[i].ContType, "charset="))) {
- partData[i].CodePage = GetCharsetFromString(CharSetStr, mir_strlen(CharSetStr));
- delete[] CharSetStr;
- }
- }
- if (partData[i].ContType && !_strnicmp(partData[i].ContType, "text", 4)) {
- char *localBody = nullptr;
- switch (partData[i].TransEncType) {
- case TE_BASE64:
- {
- int size = partData[i].bodyLen * 3 / 4 + 5;
- localBody = new char[size + 1];
- DecodeBase64(partData[i].body, localBody, size);
- }break;
- case TE_QUOTEDPRINTABLE:
- {
- int size = partData[i].bodyLen + 2;
- localBody = new char[size + 1];
- DecodeQuotedPrintable(partData[i].body, localBody, size, FALSE);
- }break;
- }
- ConvertStringToUnicode(localBody ? localBody : partData[i].body, partData[i].CodePage, &partData[i].wBody);
- if (localBody) delete[] localBody;
- }
- else if (partData[i].ContType && !_strnicmp(partData[i].ContType, "multipart/", 10)) {
- //Multipart in mulitipart recursive? should be SPAM. Ah well
- char *bondary = nullptr;
- if (nullptr != (bondary = ExtractFromContentType(partData[i].ContType, "boundary="))) {
- partData[i].wBody = ParseMultipartBody(partData[i].body, bondary);
- delete[] bondary;
- }
- else goto FailBackRaw; //multipart with no boundary? badly formatted messages.
- }
- else {
-FailBackRaw:
- ConvertStringToUnicode(partData[i].body, partData[i].CodePage, &partData[i].wBody);
- }
- resultSize += mir_wstrlen(partData[i].wBody);
- }// if (partData[i].body)
- resultSize += 100 + 4 + 3; //cr+nl+100+ 3*bullet
- }
- dest = new wchar_t[resultSize + 1];
- size_t destpos = 0;
- for (i = 0; i < numparts; i++) {
- if (i) { // part before first boudary should not have headers
- char infoline[1024]; size_t linesize = 0;
- mir_snprintf(infoline, "%s %d", Translate("Part"), i);
- linesize = mir_strlen(infoline);
- if (partData[i].TransEnc) {
- mir_snprintf(infoline + linesize, _countof(infoline) - linesize, "; %s", partData[i].TransEnc);
- linesize = mir_strlen(infoline);
- }
- if (partData[i].ContType) {
- char *CharSetStr = strchr(partData[i].ContType, ';');
- if (CharSetStr) {
- CharSetStr[0] = 0;
- mir_snprintf(infoline + linesize, _countof(infoline) - linesize, "; %s", partData[i].ContType);
- linesize = mir_strlen(infoline);
- partData[i].ContType = CharSetStr + 1;
- if (nullptr != (CharSetStr = ExtractFromContentType(partData[i].ContType, "charset="))) {
- mir_snprintf(infoline + linesize, _countof(infoline) - linesize, "; %s", CharSetStr);
- linesize = mir_strlen(infoline);
- delete[] CharSetStr;
- }
- if (nullptr != (CharSetStr = ExtractFromContentType(partData[i].ContType, "name="))) {
- mir_snprintf(infoline + linesize, _countof(infoline) - linesize, "; \"%s\"", CharSetStr);
- linesize = mir_strlen(infoline);
- delete[] CharSetStr;
- }
- }
- else {
- mir_snprintf(infoline + linesize, _countof(infoline) - linesize, "; %s", partData[i].ContType);
- linesize = mir_strlen(infoline);
- }
- }
- mir_snprintf(infoline + linesize, _countof(infoline) - linesize, ".\r\n");
- {
- wchar_t *temp = nullptr;
- dest[destpos] = dest[destpos + 1] = dest[destpos + 2] = 0x2022; // bullet;
- destpos += 3;
- ConvertStringToUnicode(infoline, CP_ACP, &temp);
- size_t wsize = mir_wstrlen(temp);
- mir_wstrcpy(&dest[destpos], temp);
- destpos += wsize;
- delete[] temp;
- }
- } // if (i)
-
- if (partData[i].wBody) {
- size_t wsize = mir_wstrlen(partData[i].wBody);
- mir_wstrcpy(&dest[destpos], partData[i].wBody);
- destpos += wsize;
- delete[] partData[i].wBody;
- }
- }
-
- free(srcback);
- delete[] partData;
- dest[resultSize] = 0;//just in case
- return dest;
-}
+/*
+ * This code implements retrieving info from MIME header
+ *
+ * (c) majvan 2002-2004
+ */
+
+#include "../stdafx.h"
+
+ //--------------------------------------------------------------------------------------------------
+
+ //Copies one string to another
+ // srcstart- source string
+ // srcend- address to the end of source string
+ // dest- pointer that stores new allocated string that contains copy of source string
+ // mode- MIME_PLAIN or MIME_MAIL (MIME_MAIL deletes '"' characters (or '<' and '>') if they are at start and end of source string
+void CopyToHeader(char *srcstart, char *srcend, char **dest, int mode);
+
+//Extracts email address (finds nick name and mail and then stores them to strings)
+// finder- source string
+// storeto- pointer that receives address of mail string
+// storetonick- pointer that receives address of nickname
+void ExtractAddressFromLine(char *finder, char **storeto, char **storetonick);
+
+//Extracts simple text from string
+// finder- source string
+// storeto- pointer that receives address of string
+void ExtractStringFromLine(char *finder, char **storeto);
+
+//Extracts some item from content-type string
+//Example: ContentType string: "TEXT/PLAIN; charset=US-ASCII", item:"charset=", returns: "US-ASCII"
+// ContetType- content-type string
+// value- string item
+// returns extracted string (or NULL when not found)
+char *ExtractFromContentType(char *ContentType, char *value);
+
+//Extracts info from header text into header members
+//Note that this function as well as struct CShortHeadwer can be always changed, because there are many items to extract
+//(e.g. the X-Priority and Importance and so on)
+// items- translated header (see TranslateHeaderFcn)
+// head- header to be filled with values extracted from items
+void ExtractShortHeader(struct CMimeItem *items, struct CShortHeader *head);
+
+//Extracts header to mail using ExtractShortHeader fcn.
+// items- translated header (see TranslateHeaderFcn)
+// CP- codepage used when no default found
+// head- header to be filled with values extracted from items, in unicode (wide char)
+void ExtractHeader(struct CMimeItem *items, int &CP, struct CHeader *head);
+
+//Deletes items in CShortHeader structure
+// head- structure whose items are deleted
+void DeleteShortHeaderContent(struct CShortHeader *head);
+
+//Deletes list of YAMN_MIMENAMES structures
+// Names- pointer to first item of list
+void DeleteNames(CMimeNames *Names);
+
+//Deletes list of YAMN_MIMESHORTNAMES structures
+// Names- pointer to first item of list
+void DeleteShortNames(CShortNames *Names);
+
+//Makes a string lowercase
+// string- string to be lowercased
+void inline ToLower(char *string);
+
+//--------------------------------------------------------------------------------------------------
+//--------------------------------------------------------------------------------------------------
+
+void CopyToHeader(char *srcstart, char *srcend, char **dest, int mode)
+{
+ char *dst;
+
+ if (dest == nullptr)
+ return;
+ if (srcstart >= srcend)
+ return;
+
+ if ((mode == MIME_MAIL) && (((*srcstart == '"') && (*(srcend - 1) == '"')) || ((*srcstart == '<') && (*(srcend - 1) == '>')))) {
+ srcstart++;
+ srcend--;
+ }
+
+ if (srcstart >= srcend)
+ return;
+
+ if (nullptr != *dest)
+ delete[] * dest;
+ if (nullptr == (*dest = new char[srcend - srcstart + 1]))
+ return;
+
+ dst = *dest;
+
+ for (; srcstart < srcend; dst++, srcstart++) {
+ if (ENDLINE(srcstart)) {
+ while (ENDLINE(srcstart) || WS(srcstart)) srcstart++;
+ *dst = ' ';
+ srcstart--; //because at the end of "for loop" we increment srcstart
+ }
+ else
+ *dst = *srcstart;
+ }
+ *dst = 0;
+}
+
+void ExtractAddressFromLine(char *finder, char **storeto, char **storetonick)
+{
+ if (finder == nullptr) {
+ *storeto = *storetonick = nullptr;
+ return;
+ }
+ while (WS(finder)) finder++;
+ if ((*finder) != '<') {
+ char *finderend = finder + 1;
+ do {
+ if (ENDLINEWS(finderend)) //after endline information continues
+ finderend += 2;
+ while (!ENDLINE(finderend) && !EOS(finderend)) finderend++; //seek to the end of line or to the end of string
+ } while (ENDLINEWS(finderend));
+ finderend--;
+ while (WS(finderend) || ENDLINE(finderend)) finderend--; //find the end of text, no whitespace
+ if (*finderend != '>') //not '>' at the end of line
+ CopyToHeader(finder, finderend + 1, storeto, MIME_MAIL);
+ else //at the end of line, there's '>'
+ {
+ char *finder2 = finderend;
+ while ((*finder2 != '<') && (finder2 > finder)) finder2--; //go to matching '<' or to the start
+ CopyToHeader(finder2, finderend + 1, storeto, MIME_MAIL);
+ if (*finder2 == '<') //if we found '<', the rest copy as from nick
+ {
+ finder2--;
+ while (WS(finder2) || ENDLINE(finder2)) finder2--; //parse whitespace
+ CopyToHeader(finder, finder2 + 1, storetonick, MIME_MAIL); //and store nickname
+ }
+ }
+ }
+ else {
+ char *finderend = finder + 1;
+ do {
+ if (ENDLINEWS(finderend)) //after endline information continues
+ finderend += 2;
+ while (!ENDLINE(finderend) && (*finderend != '>') && !EOS(finderend)) finderend++; //seek to the matching < or to the end of line or to the end of string
+ } while (ENDLINEWS(finderend));
+ CopyToHeader(finder, finderend + 1, storeto, MIME_MAIL); //go to first '>' or to the end and copy
+ finder = finderend + 1;
+ while (WS(finder)) finder++; //parse whitespace
+ if (!ENDLINE(finder) && !EOS(finder)) //if there are chars yet, it's nick
+ {
+ finderend = finder + 1;
+ while (!ENDLINE(finderend) && !EOS(finderend)) finderend++; //seek to the end of line or to the end of string
+ finderend--;
+ while (WS(finderend)) finderend--; //find the end of line, no whitespace
+ CopyToHeader(finder, finderend + 1, storetonick, MIME_MAIL);
+ }
+ }
+}
+
+void ExtractStringFromLine(char *finder, char **storeto)
+{
+ if (finder == nullptr) {
+ *storeto = nullptr;
+ return;
+ }
+ while (WS(finder)) finder++;
+ char *finderend = finder;
+
+ do {
+ if (ENDLINEWS(finderend)) finderend++; //after endline information continues
+ while (!ENDLINE(finderend) && !EOS(finderend)) finderend++;
+ } while (ENDLINEWS(finderend));
+ finderend--;
+ while (WS(finderend)) finderend--; //find the end of line, no whitespace
+ CopyToHeader(finder, finderend + 1, storeto, MIME_PLAIN);
+}
+
+char *ExtractFromContentType(char *ContentType, char *value)
+{
+ char *lowered = _strdup(ContentType);
+ ToLower(lowered);
+ char *finder = strstr(lowered, value);
+ if (finder == nullptr) {
+ free(lowered);
+ return nullptr;
+ }
+ finder = finder - lowered + ContentType;
+ free(lowered);
+
+ char *temp, *copier;
+ char *CopiedString;
+
+ temp = finder - 1;
+ while ((temp > ContentType) && WS(temp)) temp--; //now we have to find, if the word "Charset=" is located after ';' like "; Charset="
+ if (*temp != ';' && !ENDLINE(temp) && temp != ContentType)
+ return nullptr;
+ finder = finder + mir_strlen(value); //jump over value string
+
+ while (WS(finder)) finder++; //jump over whitespaces
+ temp = finder;
+ while (*temp != 0 && *temp != ';') temp++; //jump to the end of setting (to the next ;)
+ temp--;
+ while (WS(temp)) temp--; //remove whitespaces from the end
+ if (*finder == '\"') { //remove heading and tailing quotes
+ finder++;
+ if (*temp == '\"') temp--;
+ }
+ if (nullptr == (CopiedString = new char[++temp - finder + 1]))
+ return nullptr;
+ for (copier = CopiedString; finder != temp; *copier++ = *finder++); //copy string
+ *copier = 0; //and end it with zero character
+
+ return CopiedString;
+}
+
+void ExtractShortHeader(struct CMimeItem *items, struct CShortHeader *head)
+{
+ for (; items != nullptr; items = items->Next) {
+ //at the start of line
+ //MessageBox(NULL,items->value,items->name,0);
+ if (0 == _strnicmp(items->name, "From", 4)) {
+ if (items->value == nullptr)
+ continue;
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<Extracting from>");
+ #endif
+ ExtractAddressFromLine(items->value, &head->From, &head->FromNick);
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "</Extracting>\n");
+ #endif
+ }
+ else if (0 == _strnicmp(items->name, "Return-Path", 11)) {
+ if (items->value == nullptr)
+ continue;
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<Extracting return-path>");
+ #endif
+ ExtractAddressFromLine(items->value, &head->ReturnPath, &head->ReturnPathNick);
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "</Extracting>\n");
+ #endif
+ }
+ else if (0 == _strnicmp(items->name, "Subject", 7)) {
+ if (items->value == nullptr)
+ continue;
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<Extracting subject>");
+ #endif
+ ExtractStringFromLine(items->value, &head->Subject);
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "</Extracting>\n");
+ #endif
+ }
+ else if (0 == _strnicmp(items->name, "Body", 4)) {
+ if (items->value == nullptr)
+ continue;
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<Extracting body>");
+ #endif
+ ExtractStringFromLine(items->value, &head->Body);
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "</Extracting>\n");
+ #endif
+ }
+ else if (0 == _strnicmp(items->name, "Date", 4)) {
+ if (items->value == nullptr)
+ continue;
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<Extracting date>");
+ #endif
+ ExtractStringFromLine(items->value, &head->Date);
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "</Extracting>\n");
+ #endif
+ }
+ else if (0 == _strnicmp(items->name, "Content-Type", 12)) {
+ if (items->value == nullptr)
+ continue;
+
+ char *ContentType = nullptr, *CharSetStr;
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<Extracting Content-Type>");
+ #endif
+ ExtractStringFromLine(items->value, &ContentType);
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "</Extracting>\n");
+ #endif
+ ToLower(ContentType);
+ if (nullptr != (CharSetStr = ExtractFromContentType(ContentType, "charset="))) {
+ head->CP = GetCharsetFromString(CharSetStr, mir_strlen(CharSetStr));
+ delete[] CharSetStr;
+ }
+ delete[] ContentType;
+ }
+ else if (0 == _strnicmp(items->name, "Importance", 10)) {
+ if (items->value == nullptr)
+ continue;
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<Extracting importance>");
+ #endif
+ if (head->Priority != -1) {
+ if (0 == strncmp(items->value, "low", 3))
+ head->Priority = 5;
+ else if (0 == strncmp(items->value, "normal", 6))
+ head->Priority = 3;
+ else if (0 == strncmp(items->value, "high", 4))
+ head->Priority = 1;
+ }
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "</Extracting>\n");
+ #endif
+ }
+ else if (0 == _strnicmp(items->name, "X-Priority", 10)) {
+ if (items->value == nullptr)
+ continue;
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<X-Priority>");
+ #endif
+ if ((*items->value >= '1') && (*items->value <= '5'))
+ head->Priority = *items->value - '0';
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "</Extracting>\n");
+ #endif
+ }
+
+ }
+}
+
+void ExtractHeader(struct CMimeItem *items, int &CP, struct CHeader *head)
+{
+ struct CShortHeader ShortHeader;
+
+ memset(&ShortHeader, 0, sizeof(struct CShortHeader));
+ ShortHeader.Priority = ShortHeader.CP = -1;
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<Extracting header>\n");
+ #endif
+ ExtractShortHeader(items, &ShortHeader);
+
+ head->Priority = ShortHeader.Priority == -1 ? 3 : ShortHeader.Priority;
+ CP = ShortHeader.CP == -1 ? CP : ShortHeader.CP;
+ #ifdef DEBUG_DECODE
+ if (NULL != ShortHeader.From)
+ DebugLog(DecodeFile, "<Decoded from>%s</Decoded)\n", ShortHeader.From);
+ if (NULL != ShortHeader.FromNick)
+ DebugLog(DecodeFile, "<Decoded from-nick>%s</Decoded)\n", ShortHeader.FromNick);
+ if (NULL != ShortHeader.ReturnPath)
+ DebugLog(DecodeFile, "<Decoded return-path>%s</Decoded)\n", ShortHeader.ReturnPath);
+ if (NULL != ShortHeader.ReturnPathNick)
+ DebugLog(DecodeFile, "<Decoded return-path nick>%s</Decoded)\n", ShortHeader.ReturnPathNick);
+ if (NULL != ShortHeader.Subject)
+ DebugLog(DecodeFile, "<Decoded subject>%s</Decoded)\n", ShortHeader.Subject);
+ if (NULL != ShortHeader.Date)
+ DebugLog(DecodeFile, "<Decoded date>%s</Decoded)\n", ShortHeader.Date);
+ DebugLog(DecodeFile, "</Extracting header>\n");
+ DebugLog(DecodeFile, "<Convert>\n");
+ #endif
+
+ ConvertCodedStringToUnicode(ShortHeader.From, &head->From, CP, MIME_PLAIN);
+
+ #ifdef DEBUG_DECODE
+ if (NULL != head->From)
+ DebugLogW(DecodeFile, L"<Converted from>%s</Converted>\n", head->From);
+ #endif
+ ConvertCodedStringToUnicode(ShortHeader.FromNick, &head->FromNick, CP, MIME_MAIL);
+ #ifdef DEBUG_DECODE
+ if (NULL != head->FromNick)
+ DebugLogW(DecodeFile, L"<Converted from-nick>%s</Converted>\n", head->FromNick);
+ #endif
+ ConvertCodedStringToUnicode(ShortHeader.ReturnPath, &head->ReturnPath, CP, MIME_PLAIN);
+ #ifdef DEBUG_DECODE
+ if (NULL != head->ReturnPath)
+ DebugLogW(DecodeFile, L"<Converted return-path>%s</Converted>\n", head->ReturnPath);
+ #endif
+ ConvertCodedStringToUnicode(ShortHeader.ReturnPathNick, &head->ReturnPathNick, CP, MIME_MAIL);
+ #ifdef DEBUG_DECODE
+ if (NULL != head->ReturnPathNick)
+ DebugLogW(DecodeFile, L"<Converted return-path nick>%s</Converted>\n", head->ReturnPathNick);
+ #endif
+ ConvertCodedStringToUnicode(ShortHeader.Subject, &head->Subject, CP, MIME_PLAIN);
+ #ifdef DEBUG_DECODE
+ if (NULL != head->Subject)
+ DebugLogW(DecodeFile, L"<Converted subject>%s</Converted>\n", head->Subject);
+ #endif
+ ConvertCodedStringToUnicode(ShortHeader.Date, &head->Date, CP, MIME_PLAIN);
+ #ifdef DEBUG_DECODE
+ if (NULL != head->Date)
+ DebugLogW(DecodeFile, L"<Converted date>%s</Converted>\n", head->Date);
+ #endif
+
+ ConvertCodedStringToUnicode(ShortHeader.Body, &head->Body, CP, MIME_PLAIN);
+ #ifdef DEBUG_DECODE
+ if (NULL != head->Body)
+ DebugLogW(DecodeFile, L"<Converted Body>%s</Converted>\n", head->Body);
+ #endif
+
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "</Convert>\n");
+ #endif
+
+ DeleteShortHeaderContent(&ShortHeader);
+
+ // head->From=L"Frommmm";
+ // head->Subject=L"Subject";
+ return;
+}
+
+void DeleteShortHeaderContent(struct CShortHeader *head)
+{
+ if (head->From != nullptr) delete[] head->From;
+ if (head->FromNick != nullptr) delete[] head->FromNick;
+ if (head->ReturnPath != nullptr) delete[] head->ReturnPath;
+ if (head->ReturnPathNick != nullptr) delete[] head->ReturnPathNick;
+ if (head->Subject != nullptr) delete[] head->Subject;
+ if (head->Date != nullptr) delete[] head->Date;
+ if (head->To != nullptr) DeleteShortNames(head->To);
+ if (head->Cc != nullptr) DeleteShortNames(head->Cc);
+ if (head->Bcc != nullptr) DeleteShortNames(head->Bcc);
+ if (head->Body != nullptr) delete[] head->Body;
+}
+
+void DeleteHeaderContent(struct CHeader *head)
+{
+ if (head->From != nullptr) delete[] head->From;
+ if (head->FromNick != nullptr) delete[] head->FromNick;
+ if (head->ReturnPath != nullptr) delete[] head->ReturnPath;
+ if (head->ReturnPathNick != nullptr) delete[] head->ReturnPathNick;
+ if (head->Subject != nullptr) delete[] head->Subject;
+ if (head->Date != nullptr) delete[] head->Date;
+ if (head->Body != nullptr) delete[] head->Body;
+ if (head->To != nullptr) DeleteNames(head->To);
+ if (head->Cc != nullptr) DeleteNames(head->Cc);
+ if (head->Bcc != nullptr) DeleteNames(head->Bcc);
+}
+
+void DeleteNames(CMimeNames *Names)
+{
+ CMimeNames *Parser = Names;
+ for (; Parser != nullptr; Parser = Parser->Next) {
+ if (Parser->Value != nullptr)
+ delete[] Parser->Value;
+ if (Parser->ValueNick != nullptr)
+ delete[] Parser->ValueNick;
+
+ CMimeNames *Old = Parser;
+ Parser = Parser->Next;
+ delete Old;
+ }
+}
+
+void DeleteShortNames(CShortNames *Names)
+{
+ CShortNames *Parser = Names;
+ for (; Parser != nullptr; Parser = Parser->Next) {
+ if (Parser->Value != nullptr)
+ delete[] Parser->Value;
+ if (Parser->ValueNick != nullptr)
+ delete[] Parser->ValueNick;
+
+ CShortNames *Old = Parser;
+ Parser = Parser->Next;
+ delete Old;
+ }
+}
+
+
+void inline ToLower(char *string)
+{
+ for (; *string != 0; string++)
+ if (*string >= 'A' && *string <= 'Z') *string = *string - 'A' + 'a';
+}
+
+#define TE_UNKNOWN
+#define TE_QUOTEDPRINTABLE 1
+#define TE_BASE64 2
+struct APartDataType
+{
+ char *Src;//Input
+ char *ContType;
+ int CodePage;
+ char *TransEnc;
+ uint8_t TransEncType; //TE_something
+ char *body;
+ int bodyLen;
+ wchar_t *wBody;
+};
+
+
+void ParseAPart(APartDataType *data)
+{
+ size_t len = mir_strlen(data->Src);
+ try {
+ char *finder = data->Src;
+ char *prev1, *prev2, *prev3;
+
+ while (finder <= (data->Src + len)) {
+ while (ENDLINEWS(finder)) finder++;
+
+ //at the start of line
+ if (finder > data->Src) {
+ if (*(finder - 2) == '\r' || *(finder - 2) == '\n')
+ *(finder - 2) = 0;
+ if (*(finder - 1) == '\r' || *(finder - 1) == '\n')
+ *(finder - 1) = 0;
+ }
+ prev1 = finder;
+
+ while (*finder != ':' && !EOS(finder) && !ENDLINE(finder)) finder++;
+ if (ENDLINE(finder) || EOS(finder)) {
+ // no ":" in the line? here the body begins;
+ data->body = prev1;
+ break;
+ }
+ prev2 = finder++;
+
+ while (WS(finder) && !EOS(finder)) finder++;
+ if (!EOS(finder))
+ prev3 = finder;
+ else
+ break;
+
+ do {
+ if (ENDLINEWS(finder)) finder += 2; //after endline information continues
+ while (!ENDLINE(finder) && !EOS(finder)) finder++;
+ } while (ENDLINEWS(finder));
+
+ if (!_strnicmp(prev1, "Content-type", prev2 - prev1)) {
+ data->ContType = prev3;
+ }
+ else if (!_strnicmp(prev1, "Content-Transfer-Encoding", prev2 - prev1)) {
+ data->TransEnc = prev3;
+ }
+
+ if (EOS(finder))
+ break;
+ finder++;
+ if (ENDLINE(finder)) {
+ finder++;
+ if (ENDLINE(finder)) {
+ // end of headers. message body begins
+ if (finder > data->Src) {
+ if (*(finder - 2) == '\r' || *(finder - 2) == '\n')
+ *(finder - 2) = 0;
+ if (*(finder - 1) == '\r' || *(finder - 1) == '\n')
+ *(finder - 1) = 0;
+ }
+ finder++;
+ if (ENDLINE(finder))finder++;
+ prev1 = finder;
+ while (!EOS(finder + 1))finder++;
+ if (ENDLINE(finder))finder--;
+ prev2 = finder;
+ if (prev2 > prev1) { // yes, we have body
+ data->body = prev1;
+ }
+ break; // there is nothing else
+ }
+ }
+ }
+ }
+ catch (...) {
+ MessageBox(nullptr, TranslateT("Translate header error"), L"", 0);
+ }
+ if (data->body) data->bodyLen = (int)mir_strlen(data->body);
+}
+
+//from decode.cpp
+int DecodeQuotedPrintable(char *Src, char *Dst, int DstLen, BOOL isQ);
+int DecodeBase64(char *Src, char *Dst, int DstLen);
+int ConvertStringToUnicode(char *stream, unsigned int cp, wchar_t **out);
+
+wchar_t *ParseMultipartBody(char *src, char *bond)
+{
+ char *srcback = _strdup(src);
+ size_t sizebond = mir_strlen(bond);
+ int numparts = 1;
+ int i;
+ char *courbond = srcback;
+ wchar_t *dest;
+ for (; (courbond = strstr(courbond, bond)); numparts++, courbond += sizebond);
+ APartDataType *partData = new APartDataType[numparts];
+ memset(partData, 0, sizeof(APartDataType) * numparts);
+ partData[0].Src = courbond = srcback;
+ for (i = 1; (courbond = strstr(courbond, bond)); i++, courbond += sizebond) {
+ *(courbond - 2) = 0;
+ partData[i].Src = courbond + sizebond;
+ while (ENDLINE(partData[i].Src)) partData[i].Src++;
+ }
+ size_t resultSize = 0;
+ for (i = 0; i < numparts; i++) {
+ ParseAPart(&partData[i]);
+ if (partData[i].body) {
+ if (partData[i].TransEnc) {
+ if (!_stricmp(partData[i].TransEnc, "base64")) partData[i].TransEncType = TE_BASE64;
+ else if (!_stricmp(partData[i].TransEnc, "quoted-printable"))partData[i].TransEncType = TE_QUOTEDPRINTABLE;
+ }
+ if (partData[i].ContType) {
+ char *CharSetStr;
+ if (nullptr != (CharSetStr = ExtractFromContentType(partData[i].ContType, "charset="))) {
+ partData[i].CodePage = GetCharsetFromString(CharSetStr, mir_strlen(CharSetStr));
+ delete[] CharSetStr;
+ }
+ }
+ if (partData[i].ContType && !_strnicmp(partData[i].ContType, "text", 4)) {
+ char *localBody = nullptr;
+ switch (partData[i].TransEncType) {
+ case TE_BASE64:
+ {
+ int size = partData[i].bodyLen * 3 / 4 + 5;
+ localBody = new char[size + 1];
+ DecodeBase64(partData[i].body, localBody, size);
+ }break;
+ case TE_QUOTEDPRINTABLE:
+ {
+ int size = partData[i].bodyLen + 2;
+ localBody = new char[size + 1];
+ DecodeQuotedPrintable(partData[i].body, localBody, size, FALSE);
+ }break;
+ }
+ ConvertStringToUnicode(localBody ? localBody : partData[i].body, partData[i].CodePage, &partData[i].wBody);
+ if (localBody) delete[] localBody;
+ }
+ else if (partData[i].ContType && !_strnicmp(partData[i].ContType, "multipart/", 10)) {
+ //Multipart in mulitipart recursive? should be SPAM. Ah well
+ char *bondary = nullptr;
+ if (nullptr != (bondary = ExtractFromContentType(partData[i].ContType, "boundary="))) {
+ partData[i].wBody = ParseMultipartBody(partData[i].body, bondary);
+ delete[] bondary;
+ }
+ else goto FailBackRaw; //multipart with no boundary? badly formatted messages.
+ }
+ else {
+FailBackRaw:
+ ConvertStringToUnicode(partData[i].body, partData[i].CodePage, &partData[i].wBody);
+ }
+ resultSize += mir_wstrlen(partData[i].wBody);
+ }// if (partData[i].body)
+ resultSize += 100 + 4 + 3; //cr+nl+100+ 3*bullet
+ }
+ dest = new wchar_t[resultSize + 1];
+ size_t destpos = 0;
+ for (i = 0; i < numparts; i++) {
+ if (i) { // part before first boudary should not have headers
+ char infoline[1024]; size_t linesize = 0;
+ mir_snprintf(infoline, "%s %d", Translate("Part"), i);
+ linesize = mir_strlen(infoline);
+ if (partData[i].TransEnc) {
+ mir_snprintf(infoline + linesize, _countof(infoline) - linesize, "; %s", partData[i].TransEnc);
+ linesize = mir_strlen(infoline);
+ }
+ if (partData[i].ContType) {
+ char *CharSetStr = strchr(partData[i].ContType, ';');
+ if (CharSetStr) {
+ CharSetStr[0] = 0;
+ mir_snprintf(infoline + linesize, _countof(infoline) - linesize, "; %s", partData[i].ContType);
+ linesize = mir_strlen(infoline);
+ partData[i].ContType = CharSetStr + 1;
+ if (nullptr != (CharSetStr = ExtractFromContentType(partData[i].ContType, "charset="))) {
+ mir_snprintf(infoline + linesize, _countof(infoline) - linesize, "; %s", CharSetStr);
+ linesize = mir_strlen(infoline);
+ delete[] CharSetStr;
+ }
+ if (nullptr != (CharSetStr = ExtractFromContentType(partData[i].ContType, "name="))) {
+ mir_snprintf(infoline + linesize, _countof(infoline) - linesize, "; \"%s\"", CharSetStr);
+ linesize = mir_strlen(infoline);
+ delete[] CharSetStr;
+ }
+ }
+ else {
+ mir_snprintf(infoline + linesize, _countof(infoline) - linesize, "; %s", partData[i].ContType);
+ linesize = mir_strlen(infoline);
+ }
+ }
+ mir_snprintf(infoline + linesize, _countof(infoline) - linesize, ".\r\n");
+ {
+ wchar_t *temp = nullptr;
+ dest[destpos] = dest[destpos + 1] = dest[destpos + 2] = 0x2022; // bullet;
+ destpos += 3;
+ ConvertStringToUnicode(infoline, CP_ACP, &temp);
+ size_t wsize = mir_wstrlen(temp);
+ mir_wstrcpy(&dest[destpos], temp);
+ destpos += wsize;
+ delete[] temp;
+ }
+ } // if (i)
+
+ if (partData[i].wBody) {
+ size_t wsize = mir_wstrlen(partData[i].wBody);
+ mir_wstrcpy(&dest[destpos], partData[i].wBody);
+ destpos += wsize;
+ delete[] partData[i].wBody;
+ }
+ }
+
+ free(srcback);
+ delete[] partData;
+ dest[resultSize] = 0;//just in case
+ return dest;
+}
diff --git a/protocols/YAMN/src/main.cpp b/protocols/YAMN/src/main.cpp
index 72b831f765..c4979af1fb 100644
--- a/protocols/YAMN/src/main.cpp
+++ b/protocols/YAMN/src/main.cpp
@@ -1,324 +1,324 @@
-/*
- * YAMN plugin main file
- * Miranda homepage: http://miranda-icq.sourceforge.net/
- * YAMN homepage: http://www.majvan.host.sk/Projekty/YAMN
- *
- * initializes all variables for further work
- *
- * (c) majvan 2002-2004
- */
-
-#include "stdafx.h"
-
- //--------------------------------------------------------------------------------------------------
-
-wchar_t ProfileName[MAX_PATH];
-wchar_t UserDirectory[MAX_PATH];
-
-wchar_t szMirandaDir[MAX_PATH];
-wchar_t szProfileDir[MAX_PATH];
-
-BOOL UninstallPlugins;
-
-HANDLE hAccountFolder;
-
-HINSTANCE *hDllPlugins;
-static int iDllPlugins = 0;
-
-YAMN_VARIABLES YAMNVar;
-
-CMPlugin g_plugin;
-
-HANDLE hNewMailHook;
-HANDLE NoWriterEV;
-HANDLE hTTButton;
-
-UINT SecTimer;
-
-#define FIXED_TAB_SIZE 100 // default value for fixed width tabs
-
-static void GetProfileDirectory(wchar_t *szPath, int cbPath)
-//This is copied from Miranda's sources. In 0.2.1.0 it is needed, in newer vesions of Miranda use MS_DB_GETPROFILEPATH service
-{
- wchar_t tszOldPath[MAX_PATH];
- Profile_GetPathW(_countof(tszOldPath), tszOldPath);
- mir_wstrcat(tszOldPath, L"\\*.book");
-
- VARSW ptszNewPath(L"%miranda_userdata%");
-
- SHFILEOPSTRUCT file_op = {
- nullptr,
- FO_MOVE,
- tszOldPath,
- ptszNewPath,
- FOF_NOERRORUI | FOF_NOCONFIRMATION | FOF_SILENT,
- false,
- nullptr,
- L""};
- SHFileOperation(&file_op);
-
- wcsncpy(szPath, ptszNewPath, cbPath);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_PROTOCOL, MIID_LAST};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-PLUGININFOEX pluginInfoEx = {
- sizeof(PLUGININFOEX),
- __PLUGIN_NAME,
- PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
- __DESCRIPTION,
- __AUTHOR,
- __COPYRIGHT,
- __AUTHORWEB,
- UNICODE_AWARE,
- // {B047A7E5-027A-4CFC-8B18-EDA8345D2790}
- {0xb047a7e5, 0x27a, 0x4cfc, {0x8b, 0x18, 0xed, 0xa8, 0x34, 0x5d, 0x27, 0x90}}
-};
-
-CMPlugin::CMPlugin() :
- PLUGIN<CMPlugin>(YAMN_DBMODULE, pluginInfoEx)
-{
- RegisterProtocol(PROTOTYPE_VIRTUAL);
- SetUniqueId("Id");
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// The callback function
-
-BOOL CALLBACK EnumSystemCodePagesProc(LPTSTR cpStr)
-{
- // Convert code page string to number
- UINT cp = _wtoi(cpStr);
- if (!IsValidCodePage(cp))
- return TRUE;
-
- // Get Code Page name
- CPINFOEX info;
- if (GetCPInfoEx(cp, 0, &info)) {
- for (int i = 1; i < CPLENALL; i++) if (CodePageNamesAll[i].CP == cp) {
- CodePageNamesAll[i].isValid = TRUE;
- CPLENSUPP++;
- break;
- }
- }
- return TRUE;
-}
-
-int SystemModulesLoaded(WPARAM, LPARAM)
-{
- //Insert "Check mail (YAMN)" item to Miranda's menu
- CMenuItem mi(&g_plugin);
-
- SET_UID(mi, 0xa01ff3d9, 0x53cb, 0x4406, 0x85, 0xd9, 0xf1, 0x90, 0x3a, 0x94, 0xed, 0xf4);
- mi.position = 0xb0000000;
- mi.hIcolibItem = g_plugin.getIconHandle(IDI_CHECKMAIL);
- mi.name.a = LPGEN("Check &mail (All Account)");
- mi.pszService = MS_YAMN_FORCECHECK;
- Menu_AddMainMenuItem(&mi);
-
- SET_UID(mi, 0xfe22191f, 0x40c8, 0x479f, 0x93, 0x5d, 0xa5, 0x17, 0x1f, 0x57, 0x2f, 0xcb);
- mi.name.a = LPGEN("Check &mail (This Account)");
- mi.pszService = MS_YAMN_CLISTCONTEXT;
- Menu_AddContactMenuItem(&mi, YAMN_DBMODULE);
-
- SET_UID(mi, 0x147c7800, 0x12d0, 0x4209, 0xab, 0xcc, 0xfa, 0x64, 0xc6, 0xb0, 0xa6, 0xeb);
- mi.hIcolibItem = g_plugin.getIconHandle(IDI_LAUNCHAPP);
- mi.name.a = LPGEN("Launch application");
- mi.pszService = MS_YAMN_CLISTCONTEXTAPP;
- Menu_AddContactMenuItem(&mi, YAMN_DBMODULE);
-
- if (hAccountFolder = FoldersRegisterCustomPathW(LPGEN("YAMN"), LPGEN("YAMN Account Folder"), UserDirectory))
- FoldersGetCustomPathW(hAccountFolder, UserDirectory, MAX_PATH, UserDirectory);
-
- RegisterPOP3Plugin(0, 0);
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static IconItem iconList[] =
-{
- {LPGEN("Check mail"), "YAMN_Check", IDI_CHECKMAIL},
- {LPGEN("Launch application"), "YAMN_Launch", IDI_LAUNCHAPP},
- {LPGEN("New Mail"), "YAMN_NewMail", IDI_NEWMAIL},
- {LPGEN("Connect Fail"), "YAMN_ConnectFail", IDI_BADCONNECT},
-};
-
-void LoadIcons()
-{
- g_plugin.registerIcon("YAMN", iconList);
-}
-
-static void LoadPlugins()
-{
- wchar_t szSearchPath[MAX_PATH];
- mir_snwprintf(szSearchPath, L"%s\\Plugins\\YAMN\\*.dll", szMirandaDir);
-
- hDllPlugins = nullptr;
-
- WIN32_FIND_DATA fd;
- HANDLE hFind = FindFirstFile(szSearchPath, &fd);
- if (hFind != INVALID_HANDLE_VALUE) {
- do {
- //rewritten from Miranda sources... Needed because Win32 API has a bug in FindFirstFile, search is done for *.dlllllll... too
- wchar_t *dot = wcsrchr(fd.cFileName, '.');
- if (dot == nullptr)
- continue;
-
- // we have a dot
- int len = (int)mir_wstrlen(fd.cFileName); // find the length of the string
- wchar_t *end = fd.cFileName + len; // get a pointer to the NULL
- int safe = (end - dot) - 1; // figure out how many chars after the dot are "safe", not including NULL
-
- if ((safe != 3) || (mir_wstrcmpi(dot + 1, L"dll") != 0)) //not bound, however the "dll" string should mean only 3 chars are compared
- continue;
-
- wchar_t szPluginPath[MAX_PATH];
- mir_snwprintf(szPluginPath, L"%s\\Plugins\\YAMN\\%s", szMirandaDir, fd.cFileName);
- HINSTANCE hDll = LoadLibrary(szPluginPath);
- if (hDll == nullptr)
- continue;
-
- LOADFILTERFCN LoadFilter = (LOADFILTERFCN)GetProcAddress(hDll, "LoadFilter");
- if (nullptr == LoadFilter) {
- FreeLibrary(hDll);
- hDll = nullptr;
- continue;
- }
-
- if (!LoadFilter(GetFcnPtrSvc)) {
- FreeLibrary(hDll);
- hDll = nullptr;
- }
-
- if (hDll != nullptr) {
- hDllPlugins = (HINSTANCE *)realloc(hDllPlugins, (iDllPlugins + 1) * sizeof(HINSTANCE));
- hDllPlugins[iDllPlugins++] = hDll;
- }
- } while (FindNextFile(hFind, &fd));
-
- FindClose(hFind);
- }
-}
-
-int CMPlugin::Load()
-{
- // we get the Miranda Root Path
- PathToAbsoluteW(L".", szMirandaDir);
-
- // retrieve the current profile name
- Profile_GetNameW(_countof(ProfileName), ProfileName);
- wchar_t *fc = wcsrchr(ProfileName, '.');
- if (fc != nullptr) *fc = 0;
-
- // we get the user path where our yamn-account.book.ini is stored from mirandaboot.ini file
- GetProfileDirectory(UserDirectory, _countof(UserDirectory));
-
- // Enumerate all the code pages available for the System Locale
- EnumSystemCodePages(EnumSystemCodePagesProc, CP_INSTALLED);
- CodePageNamesSupp = new _tcptable[CPLENSUPP];
- for (int i = 0, k = 0; i < CPLENALL; i++)
- if (CodePageNamesAll[i].isValid) {
- CodePageNamesSupp[k] = CodePageNamesAll[i];
- k++;
- }
-
- if (nullptr == (NoWriterEV = CreateEvent(nullptr, TRUE, TRUE, nullptr)))
- return 1;
- if (nullptr == (WriteToFileEV = CreateEvent(nullptr, FALSE, FALSE, nullptr)))
- return 1;
- if (nullptr == (ExitEV = CreateEvent(nullptr, TRUE, FALSE, nullptr)))
- return 1;
-
- PosX = g_plugin.getDword(YAMN_DBPOSX, 0);
- PosY = g_plugin.getDword(YAMN_DBPOSY, 0);
- SizeX = g_plugin.getDword(YAMN_DBSIZEX, 800);
- SizeY = g_plugin.getDword(YAMN_DBSIZEY, 200);
-
- HeadPosX = g_plugin.getDword(YAMN_DBMSGPOSX, 0);
- HeadPosY = g_plugin.getDword(YAMN_DBMSGPOSY, 0);
- HeadSizeX = g_plugin.getDword(YAMN_DBMSGSIZEX, 690);
- HeadSizeY = g_plugin.getDword(YAMN_DBMSGSIZEY, 300);
- HeadSplitPos = g_plugin.getWord(YAMN_DBMSGPOSSPLIT, 250);
-
- optDateTime = g_plugin.getByte(YAMN_DBTIMEOPTIONS, optDateTime);
-
- // Create new window queues for broadcast messages
- YAMNVar.MessageWnds = WindowList_Create();
- YAMNVar.NewMailAccountWnd = WindowList_Create();
- YAMNVar.Shutdown = FALSE;
-
- hCurSplitNS = LoadCursor(nullptr, IDC_SIZENS);
- hCurSplitWE = LoadCursor(nullptr, IDC_SIZEWE);
-
- #ifdef _DEBUG
- InitDebug();
- #endif
-
- CreateServiceFunctions();
-
- g_plugin.addSound(YAMN_NEWMAILSOUND, L"YAMN", YAMN_NEWMAILSNDDESC);
- g_plugin.addSound(YAMN_CONNECTFAILSOUND, L"YAMN", YAMN_CONNECTFAILSNDDESC);
-
- HookEvents();
-
- LoadIcons();
- LoadPlugins();
-
- HOTKEYDESC hkd = {};
- hkd.pszName = "YAMN_hotkey";
- hkd.pszService = MS_YAMN_FORCECHECK;
- hkd.szSection.a = YAMN_DBMODULE;
- hkd.szDescription.a = LPGEN("Check mail");
- hkd.DefHotKey = HOTKEYCODE(HOTKEYF_CONTROL, VK_F11);
- g_plugin.addHotkey(&hkd);
-
- //Create thread that will be executed every second
- if (!(SecTimer = SetTimer(nullptr, 0, 1000, TimerProc)))
- return 1;
-
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static void UnloadPlugins()
-{
- if (hDllPlugins == nullptr)
- return;
-
- for (int i = iDllPlugins - 1; i >= 0; i--) {
- if (FreeLibrary(hDllPlugins[i])) {
- hDllPlugins[i] = nullptr; //for safety
- iDllPlugins--;
- }
- }
- free((void *)hDllPlugins);
- hDllPlugins = nullptr;
-}
-
-int CMPlugin::Unload()
-{
- #ifdef _DEBUG
- UnInitDebug();
- #endif
-
- WindowList_Destroy(YAMNVar.MessageWnds);
- WindowList_Destroy(YAMNVar.NewMailAccountWnd);
-
- DestroyCursor(hCurSplitNS);
- DestroyCursor(hCurSplitWE);
-
- CloseHandle(NoWriterEV);
- CloseHandle(WriteToFileEV);
- CloseHandle(ExitEV);
-
- UnloadPlugins();
-
- delete[] CodePageNamesSupp;
- return 0;
-}
+/*
+ * YAMN plugin main file
+ * Miranda homepage: http://miranda-icq.sourceforge.net/
+ * YAMN homepage: http://www.majvan.host.sk/Projekty/YAMN
+ *
+ * initializes all variables for further work
+ *
+ * (c) majvan 2002-2004
+ */
+
+#include "stdafx.h"
+
+ //--------------------------------------------------------------------------------------------------
+
+wchar_t ProfileName[MAX_PATH];
+wchar_t UserDirectory[MAX_PATH];
+
+wchar_t szMirandaDir[MAX_PATH];
+wchar_t szProfileDir[MAX_PATH];
+
+BOOL UninstallPlugins;
+
+HANDLE hAccountFolder;
+
+HINSTANCE *hDllPlugins;
+static int iDllPlugins = 0;
+
+YAMN_VARIABLES YAMNVar;
+
+CMPlugin g_plugin;
+
+HANDLE hNewMailHook;
+HANDLE NoWriterEV;
+HANDLE hTTButton;
+
+UINT SecTimer;
+
+#define FIXED_TAB_SIZE 100 // default value for fixed width tabs
+
+static void GetProfileDirectory(wchar_t *szPath, int cbPath)
+//This is copied from Miranda's sources. In 0.2.1.0 it is needed, in newer vesions of Miranda use MS_DB_GETPROFILEPATH service
+{
+ wchar_t tszOldPath[MAX_PATH];
+ Profile_GetPathW(_countof(tszOldPath), tszOldPath);
+ mir_wstrcat(tszOldPath, L"\\*.book");
+
+ VARSW ptszNewPath(L"%miranda_userdata%");
+
+ SHFILEOPSTRUCT file_op = {
+ nullptr,
+ FO_MOVE,
+ tszOldPath,
+ ptszNewPath,
+ FOF_NOERRORUI | FOF_NOCONFIRMATION | FOF_SILENT,
+ false,
+ nullptr,
+ L""};
+ SHFileOperation(&file_op);
+
+ wcsncpy(szPath, ptszNewPath, cbPath);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_PROTOCOL, MIID_LAST};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+PLUGININFOEX pluginInfoEx = {
+ sizeof(PLUGININFOEX),
+ __PLUGIN_NAME,
+ PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
+ __DESCRIPTION,
+ __AUTHOR,
+ __COPYRIGHT,
+ __AUTHORWEB,
+ UNICODE_AWARE,
+ // {B047A7E5-027A-4CFC-8B18-EDA8345D2790}
+ {0xb047a7e5, 0x27a, 0x4cfc, {0x8b, 0x18, 0xed, 0xa8, 0x34, 0x5d, 0x27, 0x90}}
+};
+
+CMPlugin::CMPlugin() :
+ PLUGIN<CMPlugin>(YAMN_DBMODULE, pluginInfoEx)
+{
+ RegisterProtocol(PROTOTYPE_VIRTUAL);
+ SetUniqueId("Id");
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// The callback function
+
+BOOL CALLBACK EnumSystemCodePagesProc(LPTSTR cpStr)
+{
+ // Convert code page string to number
+ UINT cp = _wtoi(cpStr);
+ if (!IsValidCodePage(cp))
+ return TRUE;
+
+ // Get Code Page name
+ CPINFOEX info;
+ if (GetCPInfoEx(cp, 0, &info)) {
+ for (int i = 1; i < CPLENALL; i++) if (CodePageNamesAll[i].CP == cp) {
+ CodePageNamesAll[i].isValid = TRUE;
+ CPLENSUPP++;
+ break;
+ }
+ }
+ return TRUE;
+}
+
+int SystemModulesLoaded(WPARAM, LPARAM)
+{
+ //Insert "Check mail (YAMN)" item to Miranda's menu
+ CMenuItem mi(&g_plugin);
+
+ SET_UID(mi, 0xa01ff3d9, 0x53cb, 0x4406, 0x85, 0xd9, 0xf1, 0x90, 0x3a, 0x94, 0xed, 0xf4);
+ mi.position = 0xb0000000;
+ mi.hIcolibItem = g_plugin.getIconHandle(IDI_CHECKMAIL);
+ mi.name.a = LPGEN("Check &mail (All Account)");
+ mi.pszService = MS_YAMN_FORCECHECK;
+ Menu_AddMainMenuItem(&mi);
+
+ SET_UID(mi, 0xfe22191f, 0x40c8, 0x479f, 0x93, 0x5d, 0xa5, 0x17, 0x1f, 0x57, 0x2f, 0xcb);
+ mi.name.a = LPGEN("Check &mail (This Account)");
+ mi.pszService = MS_YAMN_CLISTCONTEXT;
+ Menu_AddContactMenuItem(&mi, YAMN_DBMODULE);
+
+ SET_UID(mi, 0x147c7800, 0x12d0, 0x4209, 0xab, 0xcc, 0xfa, 0x64, 0xc6, 0xb0, 0xa6, 0xeb);
+ mi.hIcolibItem = g_plugin.getIconHandle(IDI_LAUNCHAPP);
+ mi.name.a = LPGEN("Launch application");
+ mi.pszService = MS_YAMN_CLISTCONTEXTAPP;
+ Menu_AddContactMenuItem(&mi, YAMN_DBMODULE);
+
+ if (hAccountFolder = FoldersRegisterCustomPathW(LPGEN("YAMN"), LPGEN("YAMN Account Folder"), UserDirectory))
+ FoldersGetCustomPathW(hAccountFolder, UserDirectory, MAX_PATH, UserDirectory);
+
+ RegisterPOP3Plugin(0, 0);
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static IconItem iconList[] =
+{
+ {LPGEN("Check mail"), "YAMN_Check", IDI_CHECKMAIL},
+ {LPGEN("Launch application"), "YAMN_Launch", IDI_LAUNCHAPP},
+ {LPGEN("New Mail"), "YAMN_NewMail", IDI_NEWMAIL},
+ {LPGEN("Connect Fail"), "YAMN_ConnectFail", IDI_BADCONNECT},
+};
+
+void LoadIcons()
+{
+ g_plugin.registerIcon("YAMN", iconList);
+}
+
+static void LoadPlugins()
+{
+ wchar_t szSearchPath[MAX_PATH];
+ mir_snwprintf(szSearchPath, L"%s\\Plugins\\YAMN\\*.dll", szMirandaDir);
+
+ hDllPlugins = nullptr;
+
+ WIN32_FIND_DATA fd;
+ HANDLE hFind = FindFirstFile(szSearchPath, &fd);
+ if (hFind != INVALID_HANDLE_VALUE) {
+ do {
+ //rewritten from Miranda sources... Needed because Win32 API has a bug in FindFirstFile, search is done for *.dlllllll... too
+ wchar_t *dot = wcsrchr(fd.cFileName, '.');
+ if (dot == nullptr)
+ continue;
+
+ // we have a dot
+ int len = (int)mir_wstrlen(fd.cFileName); // find the length of the string
+ wchar_t *end = fd.cFileName + len; // get a pointer to the NULL
+ int safe = (end - dot) - 1; // figure out how many chars after the dot are "safe", not including NULL
+
+ if ((safe != 3) || (mir_wstrcmpi(dot + 1, L"dll") != 0)) //not bound, however the "dll" string should mean only 3 chars are compared
+ continue;
+
+ wchar_t szPluginPath[MAX_PATH];
+ mir_snwprintf(szPluginPath, L"%s\\Plugins\\YAMN\\%s", szMirandaDir, fd.cFileName);
+ HINSTANCE hDll = LoadLibrary(szPluginPath);
+ if (hDll == nullptr)
+ continue;
+
+ LOADFILTERFCN LoadFilter = (LOADFILTERFCN)GetProcAddress(hDll, "LoadFilter");
+ if (nullptr == LoadFilter) {
+ FreeLibrary(hDll);
+ hDll = nullptr;
+ continue;
+ }
+
+ if (!LoadFilter(GetFcnPtrSvc)) {
+ FreeLibrary(hDll);
+ hDll = nullptr;
+ }
+
+ if (hDll != nullptr) {
+ hDllPlugins = (HINSTANCE *)realloc(hDllPlugins, (iDllPlugins + 1) * sizeof(HINSTANCE));
+ hDllPlugins[iDllPlugins++] = hDll;
+ }
+ } while (FindNextFile(hFind, &fd));
+
+ FindClose(hFind);
+ }
+}
+
+int CMPlugin::Load()
+{
+ // we get the Miranda Root Path
+ PathToAbsoluteW(L".", szMirandaDir);
+
+ // retrieve the current profile name
+ Profile_GetNameW(_countof(ProfileName), ProfileName);
+ wchar_t *fc = wcsrchr(ProfileName, '.');
+ if (fc != nullptr) *fc = 0;
+
+ // we get the user path where our yamn-account.book.ini is stored from mirandaboot.ini file
+ GetProfileDirectory(UserDirectory, _countof(UserDirectory));
+
+ // Enumerate all the code pages available for the System Locale
+ EnumSystemCodePages(EnumSystemCodePagesProc, CP_INSTALLED);
+ CodePageNamesSupp = new _tcptable[CPLENSUPP];
+ for (int i = 0, k = 0; i < CPLENALL; i++)
+ if (CodePageNamesAll[i].isValid) {
+ CodePageNamesSupp[k] = CodePageNamesAll[i];
+ k++;
+ }
+
+ if (nullptr == (NoWriterEV = CreateEvent(nullptr, TRUE, TRUE, nullptr)))
+ return 1;
+ if (nullptr == (WriteToFileEV = CreateEvent(nullptr, FALSE, FALSE, nullptr)))
+ return 1;
+ if (nullptr == (ExitEV = CreateEvent(nullptr, TRUE, FALSE, nullptr)))
+ return 1;
+
+ PosX = g_plugin.getDword(YAMN_DBPOSX, 0);
+ PosY = g_plugin.getDword(YAMN_DBPOSY, 0);
+ SizeX = g_plugin.getDword(YAMN_DBSIZEX, 800);
+ SizeY = g_plugin.getDword(YAMN_DBSIZEY, 200);
+
+ HeadPosX = g_plugin.getDword(YAMN_DBMSGPOSX, 0);
+ HeadPosY = g_plugin.getDword(YAMN_DBMSGPOSY, 0);
+ HeadSizeX = g_plugin.getDword(YAMN_DBMSGSIZEX, 690);
+ HeadSizeY = g_plugin.getDword(YAMN_DBMSGSIZEY, 300);
+ HeadSplitPos = g_plugin.getWord(YAMN_DBMSGPOSSPLIT, 250);
+
+ optDateTime = g_plugin.getByte(YAMN_DBTIMEOPTIONS, optDateTime);
+
+ // Create new window queues for broadcast messages
+ YAMNVar.MessageWnds = WindowList_Create();
+ YAMNVar.NewMailAccountWnd = WindowList_Create();
+ YAMNVar.Shutdown = FALSE;
+
+ hCurSplitNS = LoadCursor(nullptr, IDC_SIZENS);
+ hCurSplitWE = LoadCursor(nullptr, IDC_SIZEWE);
+
+ #ifdef _DEBUG
+ InitDebug();
+ #endif
+
+ CreateServiceFunctions();
+
+ g_plugin.addSound(YAMN_NEWMAILSOUND, L"YAMN", YAMN_NEWMAILSNDDESC);
+ g_plugin.addSound(YAMN_CONNECTFAILSOUND, L"YAMN", YAMN_CONNECTFAILSNDDESC);
+
+ HookEvents();
+
+ LoadIcons();
+ LoadPlugins();
+
+ HOTKEYDESC hkd = {};
+ hkd.pszName = "YAMN_hotkey";
+ hkd.pszService = MS_YAMN_FORCECHECK;
+ hkd.szSection.a = YAMN_DBMODULE;
+ hkd.szDescription.a = LPGEN("Check mail");
+ hkd.DefHotKey = HOTKEYCODE(HOTKEYF_CONTROL, VK_F11);
+ g_plugin.addHotkey(&hkd);
+
+ //Create thread that will be executed every second
+ if (!(SecTimer = SetTimer(nullptr, 0, 1000, TimerProc)))
+ return 1;
+
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static void UnloadPlugins()
+{
+ if (hDllPlugins == nullptr)
+ return;
+
+ for (int i = iDllPlugins - 1; i >= 0; i--) {
+ if (FreeLibrary(hDllPlugins[i])) {
+ hDllPlugins[i] = nullptr; //for safety
+ iDllPlugins--;
+ }
+ }
+ free((void *)hDllPlugins);
+ hDllPlugins = nullptr;
+}
+
+int CMPlugin::Unload()
+{
+ #ifdef _DEBUG
+ UnInitDebug();
+ #endif
+
+ WindowList_Destroy(YAMNVar.MessageWnds);
+ WindowList_Destroy(YAMNVar.NewMailAccountWnd);
+
+ DestroyCursor(hCurSplitNS);
+ DestroyCursor(hCurSplitWE);
+
+ CloseHandle(NoWriterEV);
+ CloseHandle(WriteToFileEV);
+ CloseHandle(ExitEV);
+
+ UnloadPlugins();
+
+ delete[] CodePageNamesSupp;
+ return 0;
+}
diff --git a/protocols/YAMN/src/main.h b/protocols/YAMN/src/main.h
index cdcf5c285c..971ba43c9f 100644
--- a/protocols/YAMN/src/main.h
+++ b/protocols/YAMN/src/main.h
@@ -1,37 +1,37 @@
-#ifndef __MAIN_H
-#define __MAIN_H
-
-#define YAMN_NEWMAILSNDDESC LPGENW("New mail message")
-#define YAMN_CONNECTFAILSNDDESC LPGENW("Connect failed")
-#define YAMN_CONNECTFAILSOUND "YAMN/Sound/ConnectFail"
-#define YAMN_NEWMAILSOUND "YAMN/Sound/NewMail"
-
-#define YAMN_DBMODULE "YAMN"
-#define YAMN_DBPOSX "MailBrowserWinX"
-#define YAMN_DBPOSY "MailBrowserWinY"
-#define YAMN_DBSIZEX "MailBrowserWinW"
-#define YAMN_DBSIZEY "MailBrowserWinH"
-#define YAMN_DBMSGPOSX "MailMessageWinX"
-#define YAMN_DBMSGPOSY "MailMessageWinY"
-#define YAMN_DBMSGSIZEX "MailMessageWinW"
-#define YAMN_DBMSGSIZEY "MailMessageWinH"
-#define YAMN_DBMSGPOSSPLIT "MailMessageSplitY"
-#define YAMN_TTBFCHECK "ForceCheckTTB"
-#define YAMN_CLOSEDELETE "CloseOnDelete"
-#define YAMN_DBTIMEOPTIONS "MailBrowserTimeOpts"
-
-#define YAMN_DEFAULTHK MAKEWORD(VK_F11,MOD_CONTROL)
-
-#define SHOWDATELONG 0x01
-#define SHOWDATENOTODAY 0x02
-#define SHOWDATENOSECONDS 0x04
-
-extern unsigned char optDateTime;
-
-// Loading Icon and checking for icolib
-void LoadIcons();
-
-typedef INT_PTR (*LOADFILTERFCN)(MIRANDASERVICE GetYAMNFcn);
-
-#endif
-
+#ifndef __MAIN_H
+#define __MAIN_H
+
+#define YAMN_NEWMAILSNDDESC LPGENW("New mail message")
+#define YAMN_CONNECTFAILSNDDESC LPGENW("Connect failed")
+#define YAMN_CONNECTFAILSOUND "YAMN/Sound/ConnectFail"
+#define YAMN_NEWMAILSOUND "YAMN/Sound/NewMail"
+
+#define YAMN_DBMODULE "YAMN"
+#define YAMN_DBPOSX "MailBrowserWinX"
+#define YAMN_DBPOSY "MailBrowserWinY"
+#define YAMN_DBSIZEX "MailBrowserWinW"
+#define YAMN_DBSIZEY "MailBrowserWinH"
+#define YAMN_DBMSGPOSX "MailMessageWinX"
+#define YAMN_DBMSGPOSY "MailMessageWinY"
+#define YAMN_DBMSGSIZEX "MailMessageWinW"
+#define YAMN_DBMSGSIZEY "MailMessageWinH"
+#define YAMN_DBMSGPOSSPLIT "MailMessageSplitY"
+#define YAMN_TTBFCHECK "ForceCheckTTB"
+#define YAMN_CLOSEDELETE "CloseOnDelete"
+#define YAMN_DBTIMEOPTIONS "MailBrowserTimeOpts"
+
+#define YAMN_DEFAULTHK MAKEWORD(VK_F11,MOD_CONTROL)
+
+#define SHOWDATELONG 0x01
+#define SHOWDATENOTODAY 0x02
+#define SHOWDATENOSECONDS 0x04
+
+extern unsigned char optDateTime;
+
+// Loading Icon and checking for icolib
+void LoadIcons();
+
+typedef INT_PTR (*LOADFILTERFCN)(MIRANDASERVICE GetYAMNFcn);
+
+#endif
+
diff --git a/protocols/YAMN/src/proto/netlib.cpp b/protocols/YAMN/src/proto/netlib.cpp
index cf477e8219..726860e459 100644
--- a/protocols/YAMN/src/proto/netlib.cpp
+++ b/protocols/YAMN/src/proto/netlib.cpp
@@ -1,232 +1,232 @@
-/*
- * This code implements communication based on Miranda netlib library
- *
- * (c) majvan 2002-2004
- */
-
-#include "../stdafx.h"
-
- //--------------------------------------------------------------------------------------------------
-
-BOOL SSLLoaded = FALSE;
-HNETLIBUSER hNetlibUser = nullptr;
-
-void __stdcall SSL_DebugLog(const char *fmt, ...)
-{
- char str[4096];
- va_list vararg;
-
- va_start(vararg, fmt);
- int tBytes = mir_vsnprintf(str, _countof(str), fmt, vararg);
- if (tBytes == 0)
- return;
-
- if (tBytes > 0)
- str[tBytes] = 0;
- else
- str[sizeof(str) - 1] = 0;
-
- Netlib_Log(hNetlibUser, str);
- va_end(vararg);
-}
-
-HANDLE RegisterNLClient(char *name)
-{
- #ifdef DEBUG_COMM
- DebugLog(CommFile, "<Register PROXY support>");
- #endif
-
- NETLIBUSER nlu = {};
- nlu.flags = NUF_OUTGOING | NUF_HTTPCONNS;
- nlu.szDescriptiveName.a = name;
- nlu.szSettingsModule = (char *)name;
- hNetlibUser = Netlib_RegisterUser(&nlu);
-
- #ifdef DEBUG_COMM
- if (NULL == hNetlibUser)
- DebugLog(CommFile, "<error></Register PROXY support>\n");
- else
- DebugLog(CommFile, "</Register PROXY support>\n");
- #endif
- return hNetlibUser;
-}
-
-//Move connection to SSL
-void CNLClient::SSLify() throw(DWORD)
-{
- #ifdef DEBUG_COMM
- SSL_DebugLog("Staring SSL...");
- #endif
- int socket = Netlib_GetSocket(hConnection);
- if (socket != INVALID_SOCKET) {
- #ifdef DEBUG_COMM
- SSL_DebugLog("Staring netlib core SSL");
- #endif
- if (Netlib_StartSsl(hConnection, nullptr)) {
- #ifdef DEBUG_COMM
- SSL_DebugLog("Netlib core SSL started");
- #endif
- isTLSed = true;
- SSLLoaded = TRUE;
- return;
- }
- }
-
- //ssl could not be created
- throw NetworkError = (uint32_t)ESSL_CREATESSL;
-}
-
-//Connects to the server through the sock
-//if not success, exception is throwed
-void CNLClient::Connect(const char *servername, const int port) throw(DWORD)
-{
- NetworkError = SystemError = 0;
- isTLSed = false;
-
- #ifdef DEBUG_COMM
- DebugLog(CommFile, "<connect>\n");
- #endif
- try {
- if (nullptr == (hConnection = Netlib_OpenConnection(hNetlibUser, servername, port))) {
- SystemError = WSAGetLastError();
- throw NetworkError = (uint32_t)ENL_CONNECT;
- }
- #ifdef DEBUG_COMM
- DebugLog(CommFile, "</connect>\n");
- #endif
- return;
- }
- catch (...) {
- #ifdef DEBUG_COMM
- DebugLog(CommFile, "<error></connect>\n");
- #endif
- throw;
- }
-}
-
-//Performs a simple query
-// query- command to send
-int CNLClient::LocalNetlib_Send(HNETLIBCONN hConn, const char *buf, int len, int flags)
-{
- return Netlib_Send(hConn, buf, len, flags);
-}
-
-void CNLClient::Send(const char *query) throw(DWORD)
-{
- unsigned int Sent;
-
- if (nullptr == query)
- return;
- if (hConnection == nullptr)
- return;
- #ifdef DEBUG_COMM
- DebugLog(CommFile, "<send>%s", query);
- #endif
- try {
- if ((SOCKET_ERROR == (Sent = LocalNetlib_Send(hConnection, query, (int)mir_strlen(query), MSG_DUMPASTEXT))) || Sent != (unsigned int)mir_strlen(query)) {
- SystemError = WSAGetLastError();
- throw NetworkError = (uint32_t)ENL_SEND;
- }
- #ifdef DEBUG_COMM
- DebugLog(CommFile, "</send>\n");
- #endif
- }
- catch (...) {
- #ifdef DEBUG_COMM
- DebugLog(CommFile, "<error></send>\n");
- #endif
- throw;
- }
-}
-
-//Reads data from socket
-// buf- buffer where to store max. buflen of received characters
-// if buf is NULL, creates buffer of buflen size
-// buf is NULL by default
-//You need free() returned buffer, which can be allocated in this function
-//if not success, exception is throwed
-
-int CNLClient::LocalNetlib_Recv(HNETLIBCONN hConn, char *buf, int len, int flags)
-{
- int iReturn = Netlib_Recv(hConn, buf, len, flags);
- if (isTLSed) {
- #ifdef DEBUG_COMM
- SSL_DebugLog("SSL recv: %s", buf);
- #endif
- }
-
- return iReturn;
-}
-
-char *CNLClient::Recv(char *buf, int buflen) throw(DWORD)
-{
- #ifdef DEBUG_COMM
- DebugLog(CommFile, "<reading>");
- #endif
- try {
- if (buf == nullptr)
- buf = (char *)malloc(sizeof(char) * (buflen + 1));
- if (buf == nullptr)
- throw NetworkError = (uint32_t)ENL_RECVALLOC;
-
- if (!isTLSed) {
- NETLIBSELECT nls = {};
- nls.dwTimeout = 60000;
- nls.hReadConns[0] = hConnection;
- switch (Netlib_Select(&nls)) {
- case SOCKET_ERROR:
- free(buf);
- SystemError = WSAGetLastError();
- throw NetworkError = (uint32_t)ENL_RECV;
- case 0: // time out!
- free(buf);
- throw NetworkError = (uint32_t)ENL_TIMEOUT;
- }
- }
-
- memset(buf, 0, buflen);
- if (SOCKET_ERROR == (Rcv = LocalNetlib_Recv(hConnection, buf, buflen, MSG_DUMPASTEXT))) {
- free(buf);
- SystemError = WSAGetLastError();
- throw NetworkError = (uint32_t)ENL_RECV;
- }
- if (!Rcv) {
- free(buf);
- SystemError = WSAGetLastError();
- throw NetworkError = (uint32_t)ENL_RECV;
- }
- #ifdef DEBUG_COMM
- *(buf + Rcv) = 0; //end the buffer to write it to file
- DebugLog(CommFile, "%s", buf);
- DebugLog(CommFile, "</reading>\n");
- #endif
- return(buf);
- }
- catch (...) {
- #ifdef DEBUG_COMM
- DebugLog(CommFile, "<error></reading>\n");
- #endif
- throw;
- }
-}
-
-//Closes netlib connection
-void CNLClient::Disconnect()
-{
- Netlib_CloseHandle(hConnection);
- hConnection = nullptr;
-}
-
-//Uninitializes netlib library
-void UnregisterNLClient()
-{
- #ifdef DEBUG_COMM
- DebugLog(CommFile, "<Unregister PROXY support>");
- #endif
-
- Netlib_CloseHandle(hNetlibUser);
- hNetlibUser = nullptr;
- #ifdef DEBUG_COMM
- DebugLog(CommFile, "</Unregister PROXY support>\n");
- #endif
-}
+/*
+ * This code implements communication based on Miranda netlib library
+ *
+ * (c) majvan 2002-2004
+ */
+
+#include "../stdafx.h"
+
+ //--------------------------------------------------------------------------------------------------
+
+BOOL SSLLoaded = FALSE;
+HNETLIBUSER hNetlibUser = nullptr;
+
+void __stdcall SSL_DebugLog(const char *fmt, ...)
+{
+ char str[4096];
+ va_list vararg;
+
+ va_start(vararg, fmt);
+ int tBytes = mir_vsnprintf(str, _countof(str), fmt, vararg);
+ if (tBytes == 0)
+ return;
+
+ if (tBytes > 0)
+ str[tBytes] = 0;
+ else
+ str[sizeof(str) - 1] = 0;
+
+ Netlib_Log(hNetlibUser, str);
+ va_end(vararg);
+}
+
+HANDLE RegisterNLClient(char *name)
+{
+ #ifdef DEBUG_COMM
+ DebugLog(CommFile, "<Register PROXY support>");
+ #endif
+
+ NETLIBUSER nlu = {};
+ nlu.flags = NUF_OUTGOING | NUF_HTTPCONNS;
+ nlu.szDescriptiveName.a = name;
+ nlu.szSettingsModule = (char *)name;
+ hNetlibUser = Netlib_RegisterUser(&nlu);
+
+ #ifdef DEBUG_COMM
+ if (NULL == hNetlibUser)
+ DebugLog(CommFile, "<error></Register PROXY support>\n");
+ else
+ DebugLog(CommFile, "</Register PROXY support>\n");
+ #endif
+ return hNetlibUser;
+}
+
+//Move connection to SSL
+void CNLClient::SSLify() throw(DWORD)
+{
+ #ifdef DEBUG_COMM
+ SSL_DebugLog("Staring SSL...");
+ #endif
+ int socket = Netlib_GetSocket(hConnection);
+ if (socket != INVALID_SOCKET) {
+ #ifdef DEBUG_COMM
+ SSL_DebugLog("Staring netlib core SSL");
+ #endif
+ if (Netlib_StartSsl(hConnection, nullptr)) {
+ #ifdef DEBUG_COMM
+ SSL_DebugLog("Netlib core SSL started");
+ #endif
+ isTLSed = true;
+ SSLLoaded = TRUE;
+ return;
+ }
+ }
+
+ //ssl could not be created
+ throw NetworkError = (uint32_t)ESSL_CREATESSL;
+}
+
+//Connects to the server through the sock
+//if not success, exception is throwed
+void CNLClient::Connect(const char *servername, const int port) throw(DWORD)
+{
+ NetworkError = SystemError = 0;
+ isTLSed = false;
+
+ #ifdef DEBUG_COMM
+ DebugLog(CommFile, "<connect>\n");
+ #endif
+ try {
+ if (nullptr == (hConnection = Netlib_OpenConnection(hNetlibUser, servername, port))) {
+ SystemError = WSAGetLastError();
+ throw NetworkError = (uint32_t)ENL_CONNECT;
+ }
+ #ifdef DEBUG_COMM
+ DebugLog(CommFile, "</connect>\n");
+ #endif
+ return;
+ }
+ catch (...) {
+ #ifdef DEBUG_COMM
+ DebugLog(CommFile, "<error></connect>\n");
+ #endif
+ throw;
+ }
+}
+
+//Performs a simple query
+// query- command to send
+int CNLClient::LocalNetlib_Send(HNETLIBCONN hConn, const char *buf, int len, int flags)
+{
+ return Netlib_Send(hConn, buf, len, flags);
+}
+
+void CNLClient::Send(const char *query) throw(DWORD)
+{
+ unsigned int Sent;
+
+ if (nullptr == query)
+ return;
+ if (hConnection == nullptr)
+ return;
+ #ifdef DEBUG_COMM
+ DebugLog(CommFile, "<send>%s", query);
+ #endif
+ try {
+ if ((SOCKET_ERROR == (Sent = LocalNetlib_Send(hConnection, query, (int)mir_strlen(query), MSG_DUMPASTEXT))) || Sent != (unsigned int)mir_strlen(query)) {
+ SystemError = WSAGetLastError();
+ throw NetworkError = (uint32_t)ENL_SEND;
+ }
+ #ifdef DEBUG_COMM
+ DebugLog(CommFile, "</send>\n");
+ #endif
+ }
+ catch (...) {
+ #ifdef DEBUG_COMM
+ DebugLog(CommFile, "<error></send>\n");
+ #endif
+ throw;
+ }
+}
+
+//Reads data from socket
+// buf- buffer where to store max. buflen of received characters
+// if buf is NULL, creates buffer of buflen size
+// buf is NULL by default
+//You need free() returned buffer, which can be allocated in this function
+//if not success, exception is throwed
+
+int CNLClient::LocalNetlib_Recv(HNETLIBCONN hConn, char *buf, int len, int flags)
+{
+ int iReturn = Netlib_Recv(hConn, buf, len, flags);
+ if (isTLSed) {
+ #ifdef DEBUG_COMM
+ SSL_DebugLog("SSL recv: %s", buf);
+ #endif
+ }
+
+ return iReturn;
+}
+
+char *CNLClient::Recv(char *buf, int buflen) throw(DWORD)
+{
+ #ifdef DEBUG_COMM
+ DebugLog(CommFile, "<reading>");
+ #endif
+ try {
+ if (buf == nullptr)
+ buf = (char *)malloc(sizeof(char) * (buflen + 1));
+ if (buf == nullptr)
+ throw NetworkError = (uint32_t)ENL_RECVALLOC;
+
+ if (!isTLSed) {
+ NETLIBSELECT nls = {};
+ nls.dwTimeout = 60000;
+ nls.hReadConns[0] = hConnection;
+ switch (Netlib_Select(&nls)) {
+ case SOCKET_ERROR:
+ free(buf);
+ SystemError = WSAGetLastError();
+ throw NetworkError = (uint32_t)ENL_RECV;
+ case 0: // time out!
+ free(buf);
+ throw NetworkError = (uint32_t)ENL_TIMEOUT;
+ }
+ }
+
+ memset(buf, 0, buflen);
+ if (SOCKET_ERROR == (Rcv = LocalNetlib_Recv(hConnection, buf, buflen, MSG_DUMPASTEXT))) {
+ free(buf);
+ SystemError = WSAGetLastError();
+ throw NetworkError = (uint32_t)ENL_RECV;
+ }
+ if (!Rcv) {
+ free(buf);
+ SystemError = WSAGetLastError();
+ throw NetworkError = (uint32_t)ENL_RECV;
+ }
+ #ifdef DEBUG_COMM
+ *(buf + Rcv) = 0; //end the buffer to write it to file
+ DebugLog(CommFile, "%s", buf);
+ DebugLog(CommFile, "</reading>\n");
+ #endif
+ return(buf);
+ }
+ catch (...) {
+ #ifdef DEBUG_COMM
+ DebugLog(CommFile, "<error></reading>\n");
+ #endif
+ throw;
+ }
+}
+
+//Closes netlib connection
+void CNLClient::Disconnect()
+{
+ Netlib_CloseHandle(hConnection);
+ hConnection = nullptr;
+}
+
+//Uninitializes netlib library
+void UnregisterNLClient()
+{
+ #ifdef DEBUG_COMM
+ DebugLog(CommFile, "<Unregister PROXY support>");
+ #endif
+
+ Netlib_CloseHandle(hNetlibUser);
+ hNetlibUser = nullptr;
+ #ifdef DEBUG_COMM
+ DebugLog(CommFile, "</Unregister PROXY support>\n");
+ #endif
+}
diff --git a/protocols/YAMN/src/proto/pop3/pop3.cpp b/protocols/YAMN/src/proto/pop3/pop3.cpp
index d8f704dbd6..8d24a5218c 100644
--- a/protocols/YAMN/src/proto/pop3/pop3.cpp
+++ b/protocols/YAMN/src/proto/pop3/pop3.cpp
@@ -1,344 +1,344 @@
-/*
- * This code implements basics of POP3 protocol
- *
- * (c) majvan 2002-2004
- */
-/* This was made from the libspopc project
- * copyright c 2002 Benoit Rouits <brouits@free.fr>
- * released under the terms of GNU LGPL
- * (GNU Lesser General Public Licence).
- * libspopc offers simple API for a pop3 client (MTA).
- * See RFC 1725 for pop3 specifications.
- * more information on http://brouits.free.fr/libspopc/
- */
-/*
- * This file is not original and is changed by majvan <om3tn@psg.sk>
- * for mail checker purpose. Please see original web page to
- * obtain the original. I rewrote it in C++, but good ideas were,
- * I think, unchanged.
- *
- * Note that this file was not designed to work under Unix. It's
- * needed to add Unix-specific features. I was interested only in
- * Windows for my project. majvan
- *
- */
-
-#include "../../stdafx.h"
-
- //--------------------------------------------------------------------------------------------------
-
- //Connects to the server through the netlib
- //if not success, exception is throwed
- //returns welcome string returned by server
- //sets AckFlag
-char *CPop3Client::Connect(const char *servername, const int port, BOOL UseSSL, BOOL NoTLS)
-{
- if (Stopped) // check if we can work with this POP3 client session
- throw POP3Error = (uint32_t)EPOP3_STOPPED;
-
- delete NetClient;
- SSL = UseSSL;
- NetClient = new CNLClient;
-
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "Connect:servername: %s port:%d\n", servername, port);
- #endif
- POP3Error = EPOP3_CONNECT;
- NetClient->Connect(servername, port);
- POP3Error = 0;
-
- if (SSL) {
- try {
- NetClient->SSLify();
- }
- catch (...) {
- NetClient->Disconnect();
- return nullptr;
- }
- }
-
- char *temp = RecvRest(NetClient->Recv(), POP3_SEARCHACK);
- extern BOOL SSLLoaded;
- if (!NoTLS & !(SSL)) {
- if (NetClient->Stopped) //check if we can work with this POP3 client session
- throw POP3Error = (uint32_t)EPOP3_STOPPED;
- NetClient->Send("STLS\r\n");
- free(temp);
- temp = RecvRest(NetClient->Recv(), POP3_SEARCHACK);
- if (AckFlag == POP3_FOK) { // Ok, we are going to tls
- try {
- NetClient->SSLify();
- }
- catch (...) {
- NetClient->Disconnect();
- return nullptr;
- }
- }
- }
- return temp;
-}
-
-//Receives data to the end of packet
-// prev- previous data read (appends to this string next received data)
-// mode- mode of packet.
-// Packet can end with ack state (+OK or -ERR): set mode to POP3_SEARCHACK
-// If packet ends with '.' (end of string), set mode to POP3_SEARCHDOT
-// size- received data are stored to memory, but if length of data is more than allocated memory, function allocates
-// new memory. New allocated memory has allocated size more bytes
-// This value can be selectable: if you think it is better to reallocate by 1kB size, select size to 1024,
-// default is 128. You do not need to use this parameter
-
-char *CPop3Client::RecvRest(char *prev, int mode, int size)
-{
- int SizeRead = 0;
- int SizeLeft = size - NetClient->Rcv;
- int RcvAll = NetClient->Rcv;
- char *LastString, *PrevString = prev;
-
- AckFlag = 0;
-
- while (((mode == POP3_SEARCHDOT) && !SearchFromEnd(PrevString + RcvAll - 1, RcvAll - 3, POP3_SEARCHDOT) && !SearchFromStart(PrevString, 2, POP3_SEARCHERR)) || //we are looking for dot or -err phrase
- ((mode == POP3_SEARCHACK) && (!SearchFromStart(PrevString, RcvAll - 3, mode) || !((RcvAll > 3) && SearchFromEnd(PrevString + RcvAll - 1, 1, POP3_SEARCHNL))))) //we are looking for +ok or -err phrase ended with newline
- { //if not found
- if (NetClient->Stopped) //check if we can work with this POP3 client session
- {
- if (PrevString != nullptr)
- free(PrevString);
- throw POP3Error = (uint32_t)EPOP3_STOPPED;
- }
- if (SizeLeft == 0) //if block is full
- {
- SizeRead += size;
- SizeLeft = size;
- LastString = NetClient->Recv(nullptr, SizeLeft);
- PrevString = (char *)realloc(PrevString, sizeof(char) * (SizeRead + size));
- if (PrevString == nullptr)
- throw POP3Error = (uint32_t)EPOP3_RESTALLOC;
- memcpy(PrevString + SizeRead, LastString, size);
- free(LastString);
- }
- else
- NetClient->Recv(PrevString + RcvAll, SizeLeft); //to Rcv stores received bytes
- SizeLeft = SizeLeft - NetClient->Rcv;
- RcvAll += NetClient->Rcv;
- }
- NetClient->Rcv = RcvAll; //at the end, store the number of all bytes, no the number of last received bytes
- return PrevString;
-}
-
-// CPop3Client::SearchFromEnd
-// returns 1 if substring DOTLINE or ENDLINE found from end in bs bytes
-// if you need to add condition for mode, insert it into switch statement
-BOOL CPop3Client::SearchFromEnd(char *end, int bs, int mode)
-{
- while (bs >= 0) {
- switch (mode) {
- case POP3_SEARCHDOT:
- if (DOTLINE(end))
- return 1;
- break;
-
- case POP3_SEARCHNL:
- if (ENDLINE(end))
- return 1;
- break;
- }
- end--;
- bs--;
- }
- return 0;
-}
-
-//Finds for a occurence of some pattern in string
-// returns 1 if substring OKLINE, ERRLINE or any of them found from start in bs bytes
-//call only this function to retrieve ack status (+OK or -ERR), because it sets flag AckFlag
-//if you need to add condition for mode, insert it into switch statement
-BOOL CPop3Client::SearchFromStart(char *start, int bs, int mode)
-{
- while (bs >= 0) {
- switch (mode) {
- case POP3_SEARCHOK:
- if (OKLINE(start)) {
- AckFlag = POP3_FOK;
- return 1;
- }
- break;
- case POP3_SEARCHERR:
- if (ERRLINE(start)) {
- AckFlag = POP3_FERR;
- return 1;
- }
- break;
- case POP3_SEARCHACK:
- if (ACKLINE(start)) {
- OKLINE(start) ? AckFlag = POP3_FOK : AckFlag = POP3_FERR;
- return 1;
- }
- break;
- }
- start++;
- bs--;
- }
- return 0;
-}
-
-//Performs "USER" pop query and returns server response
-//sets AckFlag
-char *CPop3Client::User(char *name)
-{
- if (NetClient->Stopped) // check if we can work with this POP3 client session
- throw POP3Error = (uint32_t)EPOP3_STOPPED;
-
- char query[128];
- char *Result;
-
- mir_snprintf(query, "USER %s\r\n", name);
- NetClient->Send(query);
- Result = RecvRest(NetClient->Recv(), POP3_SEARCHACK);
- if (AckFlag == POP3_FERR)
- throw POP3Error = (uint32_t)EPOP3_BADUSER;
- POP3Error = 0;
- return Result;
-}
-
-//Performs "PASS" pop query and returns server response
-//sets AckFlag
-char *CPop3Client::Pass(char *pw)
-{
- if (NetClient->Stopped) //check if we can work with this POP3 client session
- throw POP3Error = (uint32_t)EPOP3_STOPPED;
-
- char query[128];
- mir_snprintf(query, "PASS %s\r\n", pw);
- NetClient->Send(query);
-
- char *Result = RecvRest(NetClient->Recv(), POP3_SEARCHACK);
- if (AckFlag == POP3_FERR)
- throw POP3Error = (uint32_t)EPOP3_BADPASS;
- return Result;
-}
-
-//Performs "APOP" pop query and returns server response
-//sets AckFlag
-char *CPop3Client::APOP(char *name, char *pw, char *timestamp)
-{
- if (NetClient->Stopped) // check if we can work with this POP3 client session
- throw POP3Error = (uint32_t)EPOP3_STOPPED;
-
- char query[512];
- char *Result;
- unsigned char digest[16];
-
- if (timestamp == nullptr)
- throw POP3Error = (uint32_t)EPOP3_APOP;
- mir_md5_state_s ctx;
- mir_md5_init(&ctx);
- mir_md5_append(&ctx, (const unsigned char *)timestamp, (unsigned int)mir_strlen(timestamp));
- mir_md5_append(&ctx, (const unsigned char *)pw, (unsigned int)mir_strlen(pw));
- mir_md5_finish(&ctx, digest);
-
- char hexdigest[40];
- mir_snprintf(query, "APOP %s %s\r\n", name, bin2hex(digest, sizeof(digest), hexdigest));
-
- NetClient->Send(query);
- Result = RecvRest(NetClient->Recv(), POP3_SEARCHACK);
- if (AckFlag == POP3_FERR)
- throw POP3Error = (uint32_t)EPOP3_BADUSER;
- return Result;
-}
-
-//Performs "QUIT" pop query and returns server response
-//sets AckFlag
-char *CPop3Client::Quit()
-{
- char query[] = "QUIT\r\n";
-
- NetClient->Send(query);
- return RecvRest(NetClient->Recv(), POP3_SEARCHACK);
-}
-
-//Performs "STAT" pop query and returns server response
-//sets AckFlag
-char *CPop3Client::Stat()
-{
- if (NetClient->Stopped) //check if we can work with this POP3 client session
- throw POP3Error = (uint32_t)EPOP3_STOPPED;
-
- char query[] = "STAT\r\n";
- NetClient->Send(query);
- return RecvRest(NetClient->Recv(), POP3_SEARCHACK);
-}
-
-//Performs "LIST" pop query and returns server response
-//sets AckFlag
-char *CPop3Client::List()
-{
- if (NetClient->Stopped) // check if we can work with this POP3 client session
- throw POP3Error = (uint32_t)EPOP3_STOPPED;
-
- char query[] = "LIST\r\n";
-
- NetClient->Send(query);
- return RecvRest(NetClient->Recv(), POP3_SEARCHDOT);
-}
-
-//Performs "TOP" pop query and returns server response
-//sets AckFlag
-char *CPop3Client::Top(int nr, int lines)
-{
- if (NetClient->Stopped) // check if we can work with this POP3 client session
- throw POP3Error = (uint32_t)EPOP3_STOPPED;
-
- char query[128];
-
- mir_snprintf(query, "TOP %d %d\r\n", nr, lines);
- NetClient->Send(query);
- return RecvRest(NetClient->Recv(), POP3_SEARCHDOT);
-}
-
-//Performs "UIDL" pop query and returns server response
-//sets AckFlag
-char *CPop3Client::Uidl(int nr)
-{
- if (NetClient->Stopped) // check if we can work with this POP3 client session
- throw POP3Error = (uint32_t)EPOP3_STOPPED;
-
- char query[128];
- if (nr) {
- mir_snprintf(query, "UIDL %d\r\n", nr);
- NetClient->Send(query);
- return RecvRest(NetClient->Recv(), POP3_SEARCHACK);
- }
- mir_snprintf(query, "UIDL\r\n");
- NetClient->Send(query);
- return RecvRest(NetClient->Recv(), POP3_SEARCHDOT);
-}
-
-//Performs "DELE" pop query and returns server response
-//sets AckFlag
-char *CPop3Client::Dele(int nr)
-{
- if (NetClient->Stopped) // check if we can work with this POP3 client session
- throw POP3Error = (uint32_t)EPOP3_STOPPED;
-
- char query[128];
-
- mir_snprintf(query, "DELE %d\r\n", nr);
- NetClient->Send(query);
- return RecvRest(NetClient->Recv(), POP3_SEARCHACK);
-}
-
-//Performs "RETR" pop query and returns server response
-//sets AckFlag
-char *CPop3Client::Retr(int nr)
-{
- if (NetClient->Stopped) // check if we can work with this POP3 client session
- throw POP3Error = (uint32_t)EPOP3_STOPPED;
-
- char query[128];
- mir_snprintf(query, "RETR %d\r\n", nr);
- NetClient->Send(query);
-
- RecvRest(NetClient->Recv(), POP3_SEARCHACK);
- return NetClient->Recv();
-}
+/*
+ * This code implements basics of POP3 protocol
+ *
+ * (c) majvan 2002-2004
+ */
+/* This was made from the libspopc project
+ * copyright c 2002 Benoit Rouits <brouits@free.fr>
+ * released under the terms of GNU LGPL
+ * (GNU Lesser General Public Licence).
+ * libspopc offers simple API for a pop3 client (MTA).
+ * See RFC 1725 for pop3 specifications.
+ * more information on http://brouits.free.fr/libspopc/
+ */
+/*
+ * This file is not original and is changed by majvan <om3tn@psg.sk>
+ * for mail checker purpose. Please see original web page to
+ * obtain the original. I rewrote it in C++, but good ideas were,
+ * I think, unchanged.
+ *
+ * Note that this file was not designed to work under Unix. It's
+ * needed to add Unix-specific features. I was interested only in
+ * Windows for my project. majvan
+ *
+ */
+
+#include "../../stdafx.h"
+
+ //--------------------------------------------------------------------------------------------------
+
+ //Connects to the server through the netlib
+ //if not success, exception is throwed
+ //returns welcome string returned by server
+ //sets AckFlag
+char *CPop3Client::Connect(const char *servername, const int port, BOOL UseSSL, BOOL NoTLS)
+{
+ if (Stopped) // check if we can work with this POP3 client session
+ throw POP3Error = (uint32_t)EPOP3_STOPPED;
+
+ delete NetClient;
+ SSL = UseSSL;
+ NetClient = new CNLClient;
+
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "Connect:servername: %s port:%d\n", servername, port);
+ #endif
+ POP3Error = EPOP3_CONNECT;
+ NetClient->Connect(servername, port);
+ POP3Error = 0;
+
+ if (SSL) {
+ try {
+ NetClient->SSLify();
+ }
+ catch (...) {
+ NetClient->Disconnect();
+ return nullptr;
+ }
+ }
+
+ char *temp = RecvRest(NetClient->Recv(), POP3_SEARCHACK);
+ extern BOOL SSLLoaded;
+ if (!NoTLS & !(SSL)) {
+ if (NetClient->Stopped) //check if we can work with this POP3 client session
+ throw POP3Error = (uint32_t)EPOP3_STOPPED;
+ NetClient->Send("STLS\r\n");
+ free(temp);
+ temp = RecvRest(NetClient->Recv(), POP3_SEARCHACK);
+ if (AckFlag == POP3_FOK) { // Ok, we are going to tls
+ try {
+ NetClient->SSLify();
+ }
+ catch (...) {
+ NetClient->Disconnect();
+ return nullptr;
+ }
+ }
+ }
+ return temp;
+}
+
+//Receives data to the end of packet
+// prev- previous data read (appends to this string next received data)
+// mode- mode of packet.
+// Packet can end with ack state (+OK or -ERR): set mode to POP3_SEARCHACK
+// If packet ends with '.' (end of string), set mode to POP3_SEARCHDOT
+// size- received data are stored to memory, but if length of data is more than allocated memory, function allocates
+// new memory. New allocated memory has allocated size more bytes
+// This value can be selectable: if you think it is better to reallocate by 1kB size, select size to 1024,
+// default is 128. You do not need to use this parameter
+
+char *CPop3Client::RecvRest(char *prev, int mode, int size)
+{
+ int SizeRead = 0;
+ int SizeLeft = size - NetClient->Rcv;
+ int RcvAll = NetClient->Rcv;
+ char *LastString, *PrevString = prev;
+
+ AckFlag = 0;
+
+ while (((mode == POP3_SEARCHDOT) && !SearchFromEnd(PrevString + RcvAll - 1, RcvAll - 3, POP3_SEARCHDOT) && !SearchFromStart(PrevString, 2, POP3_SEARCHERR)) || //we are looking for dot or -err phrase
+ ((mode == POP3_SEARCHACK) && (!SearchFromStart(PrevString, RcvAll - 3, mode) || !((RcvAll > 3) && SearchFromEnd(PrevString + RcvAll - 1, 1, POP3_SEARCHNL))))) //we are looking for +ok or -err phrase ended with newline
+ { //if not found
+ if (NetClient->Stopped) //check if we can work with this POP3 client session
+ {
+ if (PrevString != nullptr)
+ free(PrevString);
+ throw POP3Error = (uint32_t)EPOP3_STOPPED;
+ }
+ if (SizeLeft == 0) //if block is full
+ {
+ SizeRead += size;
+ SizeLeft = size;
+ LastString = NetClient->Recv(nullptr, SizeLeft);
+ PrevString = (char *)realloc(PrevString, sizeof(char) * (SizeRead + size));
+ if (PrevString == nullptr)
+ throw POP3Error = (uint32_t)EPOP3_RESTALLOC;
+ memcpy(PrevString + SizeRead, LastString, size);
+ free(LastString);
+ }
+ else
+ NetClient->Recv(PrevString + RcvAll, SizeLeft); //to Rcv stores received bytes
+ SizeLeft = SizeLeft - NetClient->Rcv;
+ RcvAll += NetClient->Rcv;
+ }
+ NetClient->Rcv = RcvAll; //at the end, store the number of all bytes, no the number of last received bytes
+ return PrevString;
+}
+
+// CPop3Client::SearchFromEnd
+// returns 1 if substring DOTLINE or ENDLINE found from end in bs bytes
+// if you need to add condition for mode, insert it into switch statement
+BOOL CPop3Client::SearchFromEnd(char *end, int bs, int mode)
+{
+ while (bs >= 0) {
+ switch (mode) {
+ case POP3_SEARCHDOT:
+ if (DOTLINE(end))
+ return 1;
+ break;
+
+ case POP3_SEARCHNL:
+ if (ENDLINE(end))
+ return 1;
+ break;
+ }
+ end--;
+ bs--;
+ }
+ return 0;
+}
+
+//Finds for a occurence of some pattern in string
+// returns 1 if substring OKLINE, ERRLINE or any of them found from start in bs bytes
+//call only this function to retrieve ack status (+OK or -ERR), because it sets flag AckFlag
+//if you need to add condition for mode, insert it into switch statement
+BOOL CPop3Client::SearchFromStart(char *start, int bs, int mode)
+{
+ while (bs >= 0) {
+ switch (mode) {
+ case POP3_SEARCHOK:
+ if (OKLINE(start)) {
+ AckFlag = POP3_FOK;
+ return 1;
+ }
+ break;
+ case POP3_SEARCHERR:
+ if (ERRLINE(start)) {
+ AckFlag = POP3_FERR;
+ return 1;
+ }
+ break;
+ case POP3_SEARCHACK:
+ if (ACKLINE(start)) {
+ OKLINE(start) ? AckFlag = POP3_FOK : AckFlag = POP3_FERR;
+ return 1;
+ }
+ break;
+ }
+ start++;
+ bs--;
+ }
+ return 0;
+}
+
+//Performs "USER" pop query and returns server response
+//sets AckFlag
+char *CPop3Client::User(char *name)
+{
+ if (NetClient->Stopped) // check if we can work with this POP3 client session
+ throw POP3Error = (uint32_t)EPOP3_STOPPED;
+
+ char query[128];
+ char *Result;
+
+ mir_snprintf(query, "USER %s\r\n", name);
+ NetClient->Send(query);
+ Result = RecvRest(NetClient->Recv(), POP3_SEARCHACK);
+ if (AckFlag == POP3_FERR)
+ throw POP3Error = (uint32_t)EPOP3_BADUSER;
+ POP3Error = 0;
+ return Result;
+}
+
+//Performs "PASS" pop query and returns server response
+//sets AckFlag
+char *CPop3Client::Pass(char *pw)
+{
+ if (NetClient->Stopped) //check if we can work with this POP3 client session
+ throw POP3Error = (uint32_t)EPOP3_STOPPED;
+
+ char query[128];
+ mir_snprintf(query, "PASS %s\r\n", pw);
+ NetClient->Send(query);
+
+ char *Result = RecvRest(NetClient->Recv(), POP3_SEARCHACK);
+ if (AckFlag == POP3_FERR)
+ throw POP3Error = (uint32_t)EPOP3_BADPASS;
+ return Result;
+}
+
+//Performs "APOP" pop query and returns server response
+//sets AckFlag
+char *CPop3Client::APOP(char *name, char *pw, char *timestamp)
+{
+ if (NetClient->Stopped) // check if we can work with this POP3 client session
+ throw POP3Error = (uint32_t)EPOP3_STOPPED;
+
+ char query[512];
+ char *Result;
+ unsigned char digest[16];
+
+ if (timestamp == nullptr)
+ throw POP3Error = (uint32_t)EPOP3_APOP;
+ mir_md5_state_s ctx;
+ mir_md5_init(&ctx);
+ mir_md5_append(&ctx, (const unsigned char *)timestamp, (unsigned int)mir_strlen(timestamp));
+ mir_md5_append(&ctx, (const unsigned char *)pw, (unsigned int)mir_strlen(pw));
+ mir_md5_finish(&ctx, digest);
+
+ char hexdigest[40];
+ mir_snprintf(query, "APOP %s %s\r\n", name, bin2hex(digest, sizeof(digest), hexdigest));
+
+ NetClient->Send(query);
+ Result = RecvRest(NetClient->Recv(), POP3_SEARCHACK);
+ if (AckFlag == POP3_FERR)
+ throw POP3Error = (uint32_t)EPOP3_BADUSER;
+ return Result;
+}
+
+//Performs "QUIT" pop query and returns server response
+//sets AckFlag
+char *CPop3Client::Quit()
+{
+ char query[] = "QUIT\r\n";
+
+ NetClient->Send(query);
+ return RecvRest(NetClient->Recv(), POP3_SEARCHACK);
+}
+
+//Performs "STAT" pop query and returns server response
+//sets AckFlag
+char *CPop3Client::Stat()
+{
+ if (NetClient->Stopped) //check if we can work with this POP3 client session
+ throw POP3Error = (uint32_t)EPOP3_STOPPED;
+
+ char query[] = "STAT\r\n";
+ NetClient->Send(query);
+ return RecvRest(NetClient->Recv(), POP3_SEARCHACK);
+}
+
+//Performs "LIST" pop query and returns server response
+//sets AckFlag
+char *CPop3Client::List()
+{
+ if (NetClient->Stopped) // check if we can work with this POP3 client session
+ throw POP3Error = (uint32_t)EPOP3_STOPPED;
+
+ char query[] = "LIST\r\n";
+
+ NetClient->Send(query);
+ return RecvRest(NetClient->Recv(), POP3_SEARCHDOT);
+}
+
+//Performs "TOP" pop query and returns server response
+//sets AckFlag
+char *CPop3Client::Top(int nr, int lines)
+{
+ if (NetClient->Stopped) // check if we can work with this POP3 client session
+ throw POP3Error = (uint32_t)EPOP3_STOPPED;
+
+ char query[128];
+
+ mir_snprintf(query, "TOP %d %d\r\n", nr, lines);
+ NetClient->Send(query);
+ return RecvRest(NetClient->Recv(), POP3_SEARCHDOT);
+}
+
+//Performs "UIDL" pop query and returns server response
+//sets AckFlag
+char *CPop3Client::Uidl(int nr)
+{
+ if (NetClient->Stopped) // check if we can work with this POP3 client session
+ throw POP3Error = (uint32_t)EPOP3_STOPPED;
+
+ char query[128];
+ if (nr) {
+ mir_snprintf(query, "UIDL %d\r\n", nr);
+ NetClient->Send(query);
+ return RecvRest(NetClient->Recv(), POP3_SEARCHACK);
+ }
+ mir_snprintf(query, "UIDL\r\n");
+ NetClient->Send(query);
+ return RecvRest(NetClient->Recv(), POP3_SEARCHDOT);
+}
+
+//Performs "DELE" pop query and returns server response
+//sets AckFlag
+char *CPop3Client::Dele(int nr)
+{
+ if (NetClient->Stopped) // check if we can work with this POP3 client session
+ throw POP3Error = (uint32_t)EPOP3_STOPPED;
+
+ char query[128];
+
+ mir_snprintf(query, "DELE %d\r\n", nr);
+ NetClient->Send(query);
+ return RecvRest(NetClient->Recv(), POP3_SEARCHACK);
+}
+
+//Performs "RETR" pop query and returns server response
+//sets AckFlag
+char *CPop3Client::Retr(int nr)
+{
+ if (NetClient->Stopped) // check if we can work with this POP3 client session
+ throw POP3Error = (uint32_t)EPOP3_STOPPED;
+
+ char query[128];
+ mir_snprintf(query, "RETR %d\r\n", nr);
+ NetClient->Send(query);
+
+ RecvRest(NetClient->Recv(), POP3_SEARCHACK);
+ return NetClient->Recv();
+}
diff --git a/protocols/YAMN/src/proto/pop3/pop3comm.cpp b/protocols/YAMN/src/proto/pop3/pop3comm.cpp
index 946b93ea54..fc0f5819bb 100644
--- a/protocols/YAMN/src/proto/pop3/pop3comm.cpp
+++ b/protocols/YAMN/src/proto/pop3/pop3comm.cpp
@@ -1,1329 +1,1329 @@
-/*
- * This code implements POP3 server checking for new mail and so on.
- * There's function SynchroPOP3 in this file- for checking and synchronising POP3 account
- * and DeleteMailsPOP3- for deleting mails from POP3 server
- *
- * Note this file acts as main file for internal plugin.
- *
- * (c) majvan 2002-2004
- * 18/08
- */
-
-
-#include "../../stdafx.h"
-
-#define ERRORSTR_MAXLEN 1024 //in wide-chars
-
- //--------------------------------------------------------------------------------------------------
-
-HANDLE hNetLib = nullptr;
-PSCOUNTER CPOP3Account::AccountWriterSO = nullptr;
-
-//Creates new CPOP3Account structure
-CAccount *WINAPI CreatePOP3Account(HYAMNPROTOPLUGIN Plugin, DWORD CAccountVersion);
-
-//Deletes CPOP3Account structure
-void WINAPI DeletePOP3Account(CAccount *Which);
-
-//Sets stop flag to account
-void WINAPI StopPOP3Account(CAccount *Which);
-
-//Function registers standard functions for YAMN
-int RegisterPOP3Plugin(WPARAM, LPARAM);
-
-//Unloads all variables created on heap (delete[])
-DWORD WINAPI UnLoadPOP3(void *);
-
-//Function writes POP3 accounts using YAMN exported functions
-DWORD WINAPI WritePOP3Accounts();
-
-//Function stores plugin's data for account to file
-DWORD WINAPI WritePOP3Options(HANDLE, CAccount *);
-
-//Function reads plugin's data for account from file
-DWORD WINAPI ReadPOP3Options(CAccount *, char **, char *);
-
-//Creates new mail for an account
-HYAMNMAIL WINAPI CreatePOP3Mail(CAccount *Account, DWORD CMimeMailVersion);
-
-//Function does all needed work when connection failed or any error occured
-//Creates structure containing error code, closes internet session, runs "bad connect" function
-static void PostErrorProc(HPOP3ACCOUNT ActualAccount, void *ParamToBadConnect, uint32_t POP3PluginParam, BOOL UseSSL);
-
-//Checks POP3 account and stores all info to account. It deletes old mails=> synchro
-// WhichTemp- pointer to strucure containing needed information
-DWORD WINAPI SynchroPOP3(struct CheckParam *WhichTemp);
-
-//Deletes mails from POP3 server
-// WhichTemp- structure containing needed information (queued messages to delete)
-//Function deletes from memory queue in WhichTemp structure
-void __cdecl DeleteMailsPOP3(void *param);
-
-//Function makes readable message about error. It sends it back to YAMN, so YAMN then
-//can show it to the message window
-wchar_t *WINAPI GetErrorString(DWORD Code);
-
-//Function deletes string allocated in GetErrorString
-void WINAPI DeleteErrorString(LPVOID String);
-
-//Extracts info from result of POP3's STAT command
-// stream- source string
-// len- length of source string
-// mboxsize- adreess to integer, that receives size of mailbox
-// mails- adreess to integer, that receives number of mails
-void ExtractStat(char *stream, int *mboxsize, int *mails);
-
-//Extracts mail ID on mailbox
-// stream- source string
-// len- length of source string
-// queue- address of first message, where first ID will be stored
-void ExtractUIDL(char *stream, int len, HYAMNMAIL queue);
-
-//Extracts mail size on mailbox
-// stream- source string
-// len- length of source string
-// queue- address of first message, where size of message #1 will be stored
-void ExtractList(char *stream, int len, HYAMNMAIL queue);
-
-void ExtractMail(char *stream, int len, HYAMNMAIL queue);
-
-YAMNExportedFcns *pYAMNFcn = nullptr;
-MailExportedFcns *pYAMNMailFcn = nullptr;
-
-YAMN_PROTOIMPORTFCN POP3ProtocolFunctions =
-{
- CreatePOP3Account,
- DeletePOP3Account,
- StopPOP3Account,
- WritePOP3Options,
- ReadPOP3Options,
- SynchroPOP3,
- SynchroPOP3,
- SynchroPOP3,
- DeleteMailsPOP3,
- GetErrorString,
- nullptr,
- DeleteErrorString,
- WritePOP3Accounts,
- nullptr,
- UnLoadPOP3,
-};
-
-YAMN_MAILIMPORTFCN POP3MailFunctions =
-{
- CreatePOP3Mail,
- nullptr,
- nullptr,
- nullptr,
-};
-
-PYAMN_VARIABLES pYAMNVar = nullptr;
-HYAMNPROTOPLUGIN POP3Plugin = nullptr;
-
-YAMN_PROTOREGISTRATION POP3ProtocolRegistration =
-{
- "POP3 protocol (internal)",
- __VERSION_STRING_DOTS,
- __COPYRIGHT,
- __DESCRIPTION,
- __AUTHORWEB,
-};
-
-static wchar_t *FileName = nullptr;
-
-HANDLE RegisterNLClient(char *name);
-
-//--------------------------------------------------------------------------------------------------
-//--------------------------------------------------------------------------------------------------
-
-CPOP3Account::CPOP3Account()
-{
- //NOTE! This constructor constructs CAccount structure. If your plugin is not internal,
- //you will need these constructors. All you need is in Account.cpp. Just copy to your source code
- //constructor and destructor of CAccount.
- UseInternetFree = CreateEvent(nullptr, FALSE, TRUE, nullptr);
- InternetQueries = new SCOUNTER;
- AbilityFlags = YAMN_ACC_BROWSE | YAMN_ACC_POPUP;
-
- SetAccountStatus((CAccount *)this, TranslateT("Disconnected"));
-}
-
-CPOP3Account::~CPOP3Account()
-{
- CloseHandle(UseInternetFree);
- if (InternetQueries != nullptr)
- delete InternetQueries;
-}
-
-CAccount *WINAPI CreatePOP3Account(HYAMNPROTOPLUGIN, DWORD)
-{
- //First, we should check whether CAccountVersion matches.
- //But this is internal plugin, so YAMN's CAccount structure and our CAccount structure are
- //the same, so we do not need to test version. Otherwise, if CAccount version does not match
- //in your plugin, you should return NULL, like this:
- // if (CAccountVersion != YAMN_ACCOUNTVERSION) return NULL;
-
- //Now it is needed to construct our POP3 account and return its handle
- return (CAccount *)new struct CPOP3Account();
-}
-
-void WINAPI DeletePOP3Account(CAccount *Which)
-{
- delete (HPOP3ACCOUNT)Which;
-}
-
-void WINAPI StopPOP3Account(CAccount *Which)
-{
- ((HPOP3ACCOUNT)Which)->Client.Stopped = TRUE;
- if (((HPOP3ACCOUNT)Which)->Client.NetClient != nullptr) //we should inform also network client. Usefull only when network client implements this feature
- ((HPOP3ACCOUNT)Which)->Client.NetClient->Stopped = TRUE;
-}
-
-//This function is like main function for POP3 internal protocol
-int RegisterPOP3Plugin(WPARAM, LPARAM)
-{
- // Get YAMN variables we can use
- if (nullptr == (pYAMNVar = (PYAMN_VARIABLES)CallService(MS_YAMN_GETVARIABLES, YAMN_VARIABLESVERSION, 0)))
- return 0;
-
- // We have to get pointers to YAMN exported functions: allocate structure and fill it
- if (nullptr == (pYAMNFcn = new struct YAMNExportedFcns)) {
-LBL_Error:
- UnLoadPOP3(nullptr);
- return 0;
- }
-
- // Register new pop3 user in netlib
- if (nullptr == (hNetLib = RegisterNLClient("YAMN (POP3)")))
- goto LBL_Error;
-
- pYAMNFcn->SetProtocolPluginFcnImportFcn = (YAMN_SETPROTOCOLPLUGINFCNIMPORTFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_SETPROTOCOLPLUGINFCNIMPORTID, 0);
- pYAMNFcn->WaitToWriteFcn = (YAMN_WAITTOWRITEFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_WAITTOWRITEID, 0);
- pYAMNFcn->WriteDoneFcn = (YAMN_WRITEDONEFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_WRITEDONEID, 0);
- pYAMNFcn->WaitToReadFcn = (YAMN_WAITTOREADFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_WAITTOREADID, 0);
- pYAMNFcn->ReadDoneFcn = (YAMN_READDONEFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_READDONEID, 0);
- pYAMNFcn->SCGetNumberFcn = (YAMN_SCMANAGEFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_SCGETNUMBERID, 0);
- pYAMNFcn->SCIncFcn = (YAMN_SCMANAGEFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_SCINCID, 0);
- pYAMNFcn->SCDecFcn = (YAMN_SCMANAGEFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_SCDECID, 0);
- pYAMNFcn->SetStatusFcn = (YAMN_SETSTATUSFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_SETSTATUSID, 0);
- pYAMNFcn->GetStatusFcn = (YAMN_GETSTATUSFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_GETSTATUSID, 0);
-
- if (nullptr == (pYAMNMailFcn = new struct MailExportedFcns))
- goto LBL_Error;
-
- pYAMNMailFcn->SynchroMessagesFcn = (YAMN_SYNCHROMIMEMSGSFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_SYNCHROMIMEMSGSID, 0);
- pYAMNMailFcn->TranslateHeaderFcn = (YAMN_TRANSLATEHEADERFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_TRANSLATEHEADERID, 0);
- pYAMNMailFcn->AppendQueueFcn = (YAMN_APPENDQUEUEFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_APPENDQUEUEID, 0);
- pYAMNMailFcn->DeleteMessagesToEndFcn = (YAMN_DELETEMIMEQUEUEFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_DELETEMIMEQUEUEID, 0);
- pYAMNMailFcn->DeleteMessageFromQueueFcn = (YAMN_DELETEMIMEMESSAGEFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_DELETEMIMEMESSAGEID, 0);
- pYAMNMailFcn->FindMessageByIDFcn = (YAMN_FINDMIMEMESSAGEFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_FINDMIMEMESSAGEID, 0);
- pYAMNMailFcn->CreateNewDeleteQueueFcn = (YAMN_CREATENEWDELETEQUEUEFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_CREATENEWDELETEQUEUEID, 0);
-
- //set static variable
- if (CPOP3Account::AccountWriterSO == nullptr)
- if (nullptr == (CPOP3Account::AccountWriterSO = new SCOUNTER))
- goto LBL_Error;
-
- //First, we register this plugin
- //it is quite impossible this function returns zero (failure) as YAMN and internal plugin structre versions are the same
- POP3ProtocolRegistration.Name = Translate("POP3 protocol (internal)");
- POP3ProtocolRegistration.Description = Translate(__DESCRIPTION);
- if (nullptr == (POP3Plugin = (HYAMNPROTOPLUGIN)CallService(MS_YAMN_REGISTERPROTOPLUGIN, (WPARAM)&POP3ProtocolRegistration, (LPARAM)YAMN_PROTOREGISTRATIONVERSION)))
- return 0;
-
- //Next we set our imported functions for YAMN
- if (!SetProtocolPluginFcnImport(POP3Plugin, &POP3ProtocolFunctions, YAMN_PROTOIMPORTFCNVERSION, &POP3MailFunctions, YAMN_MAILIMPORTFCNVERSION))
- return 0;
-
- //Then, we read all mails for accounts.
- //You must first register account, before using this function as YAMN must use CreatePOP3Account function to add new accounts
- //But if CreatePOP3Account is not implemented (equals to NULL), YAMN creates account as YAMN's standard CAccount *
- if (FileName) CallService(MS_YAMN_DELETEFILENAME, (WPARAM)FileName, 0); //shoud not happen (only for secure)
- FileName = (wchar_t *)CallService(MS_YAMN_GETFILENAME, (WPARAM)L"pop3", 0);
-
- switch (CallService(MS_YAMN_READACCOUNTS, (WPARAM)POP3Plugin, (LPARAM)FileName)) {
- case EACC_FILEVERSION:
- MessageBox(nullptr, TranslateT("Found new version of account book, not compatible with this version of YAMN."), TranslateT("YAMN (internal POP3) read error"), MB_OK);
- CallService(MS_YAMN_DELETEFILENAME, (WPARAM)FileName, 0);
- FileName = nullptr;
- return 0;
- case EACC_FILECOMPATIBILITY:
- MessageBox(nullptr, TranslateT("Error reading account file. Account file corrupted."), TranslateT("YAMN (internal POP3) read error"), MB_OK);
- CallService(MS_YAMN_DELETEFILENAME, (WPARAM)FileName, 0);
- FileName = nullptr;
- return 0;
- case EACC_ALLOC:
- MessageBox(nullptr, TranslateT("Memory allocation error while data reading"), TranslateT("YAMN (internal POP3) read error"), MB_OK);
- CallService(MS_YAMN_DELETEFILENAME, (WPARAM)FileName, 0);
- FileName = nullptr;
- return 0;
- case EACC_SYSTEM:
- if (ERROR_FILE_NOT_FOUND != GetLastError()) {
- wchar_t temp[1024] = {0};
- mir_snwprintf(temp, L"%s\n%s", TranslateT("Reading file error. File already in use?"), FileName);
- MessageBox(nullptr, temp, TranslateT("YAMN (internal POP3) read error"), MB_OK);
- CallService(MS_YAMN_DELETEFILENAME, (WPARAM)FileName, 0);
- FileName = nullptr;
- return 0;
- }
- break;
- }
-
- for (CAccount *Finder = POP3Plugin->FirstAccount; Finder != nullptr; Finder = Finder->Next) {
- Finder->hContact = NULL;
- for (auto &hContact : Contacts(YAMN_DBMODULE)) {
- DBVARIANT dbv;
- if (!g_plugin.getString(hContact, "Id", &dbv)) {
- if (mir_strcmp(dbv.pszVal, Finder->Name) == 0) {
- Finder->hContact = hContact;
- g_plugin.setWord(Finder->hContact, "Status", ID_STATUS_ONLINE);
- db_set_s(Finder->hContact, "CList", "StatusMsg", Translate("No new mail message"));
- if ((Finder->Flags & YAMN_ACC_ENA) && (Finder->NewMailN.Flags & YAMN_ACC_CONT))
- Contact::Hide(Finder->hContact, false);
-
- if (!(Finder->Flags & YAMN_ACC_ENA) || !(Finder->NewMailN.Flags & YAMN_ACC_CONT))
- Contact::Hide(Finder->hContact);
- }
- db_free(&dbv);
- }
- }
-
- if (!Finder->hContact && (Finder->Flags & YAMN_ACC_ENA) && (Finder->NewMailN.Flags & YAMN_ACC_CONT)) {
- // No account contact found, have to create one
- Finder->hContact = db_add_contact();
- Proto_AddToContact(Finder->hContact, YAMN_DBMODULE);
- g_plugin.setString(Finder->hContact, "Id", Finder->Name);
- g_plugin.setString(Finder->hContact, "Nick", Finder->Name);
- g_plugin.setWord(Finder->hContact, "Status", ID_STATUS_OFFLINE);
- }
- }
-
- return 0;
-}
-
-DWORD WINAPI UnLoadPOP3(void *)
-{
- //pYAMNVar is only a pointr, no need delete or free
- if (hNetLib) {
- Netlib_CloseHandle(hNetLib); hNetLib = nullptr;
- }
- if (CPOP3Account::AccountWriterSO) {
- delete CPOP3Account::AccountWriterSO; CPOP3Account::AccountWriterSO = nullptr;
- }
- if (pYAMNMailFcn) {
- delete pYAMNMailFcn; pYAMNMailFcn = nullptr;
- }
- if (pYAMNFcn) {
- delete pYAMNFcn; pYAMNFcn = nullptr;
- }
- if (FileName) {
- CallService(MS_YAMN_DELETEFILENAME, (WPARAM)FileName, 0); FileName = nullptr;
- }
-
- return 1;
-}
-
-DWORD WINAPI WritePOP3Accounts()
-{
- uint32_t ReturnValue = CallService(MS_YAMN_WRITEACCOUNTS, (WPARAM)POP3Plugin, (LPARAM)FileName);
- if (ReturnValue == EACC_SYSTEM) {
- wchar_t temp[1024] = {0};
- mir_snwprintf(temp, L"%s\n%s", TranslateT("Error while copying data to disk occurred. Is file in use?"), FileName);
- MessageBox(nullptr, temp, TranslateT("POP3 plugin - write file error"), MB_OK);
- }
-
- return ReturnValue;
-}
-
-DWORD WINAPI WritePOP3Options(HANDLE File, CAccount *Which)
-{
- DWORD WrittenBytes;
- uint32_t Ver = POP3_FILEVERSION;
-
- if ((!WriteFile(File, (char *)&Ver, sizeof(uint32_t), &WrittenBytes, nullptr)) ||
- (!WriteFile(File, (char *)&((HPOP3ACCOUNT)Which)->CP, sizeof(uint16_t), &WrittenBytes, nullptr)))
- return EACC_SYSTEM;
- return 0;
-}
-
-DWORD WINAPI ReadPOP3Options(CAccount *Which, char **Parser, char *End)
-{
- uint32_t Ver;
- #ifdef DEBUG_FILEREAD
- wchar_t Debug[256];
- #endif
- Ver = *(uint32_t *)(*Parser);
- (*Parser) += sizeof(uint32_t);
- if (*Parser >= End)
- return EACC_FILECOMPATIBILITY;
- if (Ver != POP3_FILEVERSION)
- return EACC_FILECOMPATIBILITY;
-
- ((HPOP3ACCOUNT)Which)->CP = *(uint16_t *)(*Parser);
- (*Parser) += sizeof(uint16_t);
- if (*Parser >= End)
- return EACC_FILECOMPATIBILITY;
- #ifdef DEBUG_FILEREAD
- mir_snwprintf(Debug, L"CodePage: %d, remaining %d chars", ((HPOP3ACCOUNT)Which)->CP, End - *Parser);
- MessageBox(NULL, Debug, L"debug", MB_OK);
- #endif
- return 0;
-}
-
-HYAMNMAIL WINAPI CreatePOP3Mail(CAccount *Account, DWORD)
-{
- HYAMNMAIL NewMail;
- //First, we should check whether MAILDATA matches.
- //But this is internal plugin, so YAMN's MAILDATA structure and our MAILDATA structure are
- //the same, so we do not need to test version. Otherwise, if MAILDATA version does not match
- //in your plugin, you should return NULL, like this:
- // if (MailDataVersion != YAMN_MAILDATAVERSION) return NULL;
-
- //Now it is needed to construct our POP3 account and return its handle
- if (nullptr == (NewMail = new YAMNMAIL))
- return nullptr;
-
- if (nullptr == (NewMail->MailData = new CMailData())) {
- delete NewMail;
- return nullptr;
- }
- NewMail->MailData->CP = ((HPOP3ACCOUNT)Account)->CP;
- return (HYAMNMAIL)NewMail;
-}
-
-static void SetContactStatus(CAccount *account, int status)
-{
- if ((account->hContact) && (account->NewMailN.Flags & YAMN_ACC_CONT))
- g_plugin.setWord(account->hContact, "Status", status);
-}
-
-static void PostErrorProc(HPOP3ACCOUNT ActualAccount, void *ParamToBadConnection, uint32_t POP3PluginParam, BOOL UseSSL)
-{
- char *DataRX;
-
- //We create new structure, that we pass to bad connection dialog procedure. This procedure next calls YAMN imported fuction
- //from POP3 protocol to determine the description of error. We can describe error from our error code structure, because later,
- //when YAMN calls our function, it passes us our error code. This is pointer to structure for POP3 protocol in fact.
- PPOP3_ERRORCODE ErrorCode;
-
- //We store status before we do Quit(), because quit can destroy our errorcode status
- if (nullptr != (ErrorCode = new POP3_ERRORCODE)) {
- ErrorCode->SSL = UseSSL;
- ErrorCode->AppError = ActualAccount->SystemError;
- ErrorCode->POP3Error = ActualAccount->Client.POP3Error;
- ErrorCode->NetError = ActualAccount->Client.NetClient->NetworkError;
- ErrorCode->SystemError = ActualAccount->Client.NetClient->SystemError;
- }
-
- if (POP3PluginParam == (uint32_t)NULL) //if it was normal YAMN call (force check or so on)
- {
- try {
- DataRX = ActualAccount->Client.Quit();
- if (DataRX != nullptr)
- free(DataRX);
- }
- catch (...) {
- }
- //We always close connection if error occured
- try {
- ActualAccount->Client.NetClient->Disconnect();
- }
- catch (...) {
- }
-
- SetAccountStatus(ActualAccount, TranslateT("Disconnected"));
-
- //If we cannot allocate memory, do nothing
- if (ErrorCode == nullptr) {
- SetEvent(ActualAccount->UseInternetFree);
- return;
- }
- }
- else // else it was called from POP3 plugin, probably error when deleting old mail (POP3 synchro calls POP3 delete)
- if (ErrorCode == nullptr)
- return;
-
- if ((ActualAccount->BadConnectN.Flags & YAMN_ACC_MSG) || (ActualAccount->BadConnectN.Flags & YAMN_ACC_ICO) || (ActualAccount->BadConnectN.Flags & YAMN_ACC_POP))
- RunBadConnection(ActualAccount, (UINT_PTR)ErrorCode, ParamToBadConnection);
-
- if (POP3PluginParam == (uint32_t)NULL) //if it was normal YAMN call
- SetEvent(ActualAccount->UseInternetFree);
-}
-
-//Checks POP3 account and synchronizes it
-DWORD WINAPI SynchroPOP3(struct CheckParam *WhichTemp)
-{
- HPOP3ACCOUNT ActualAccount;
- CPop3Client *MyClient;
- HYAMNMAIL NewMails = nullptr, MsgQueuePtr = nullptr;
- char *DataRX = nullptr, *Temp;
- int mboxsize, msgs, i;
- SYSTEMTIME now;
- LPVOID YAMNParam;
- uint32_t CheckFlags;
- BOOL UsingInternet = FALSE;
- struct
- {
- char *ServerName;
- uint32_t ServerPort;
- char *ServerLogin;
- char *ServerPasswd;
- uint32_t Flags;
- uint32_t NFlags;
- uint32_t NNFlags;
- } ActualCopied;
-
- //First, we should compare our version of CheckParam structure, but here it is not needed, because YAMN and internal plugin
- //have the same version. But your plugin should do that in this way:
- // if (((struct CheckParam *)WhichTemp)->Ver != YAMN_CHECKVERSION)
- // {
- // SetEvent(((struct CheckParam *)WhichTemp)->ThreadRunningEV); //don't forget to unblock YAMN
- // return (uint32_t)-1; //ok, but we should return value.
- // //When our plugin returns e.g. 0xFFFFFFFF (=-1, this is only our plugin value, YAMN does nothing with return value,
- // //but only tests if it is nonzero. If yes, it calls GetErrorStringFcn. We know problem occured in YAMN incompatibility
- // //and then we can in our GetErrorStringFcn e.g. return string "Uncompatible version of YAMN".
- // }
-
- ActualAccount = (HPOP3ACCOUNT)WhichTemp->AccountParam; //copy address of structure from calling thread to stack of this thread
- YAMNParam = WhichTemp->BrowserParam;
- CheckFlags = WhichTemp->Flags;
-
- SCInc(ActualAccount->UsingThreads);
- //Unblock YAMN, signal that we have copied all parameters from YAMN thread stack
- if (INVALID_HANDLE_VALUE != WhichTemp->ThreadRunningEV)
- SetEvent(WhichTemp->ThreadRunningEV);
-
- if (WAIT_OBJECT_0 != WaitToRead(ActualAccount)) {
- SCDec(ActualAccount->UsingThreads);
- return 0;
- }
-
- MyClient = &ActualAccount->Client;
- //Now, copy all needed information about account to local variables, so ActualAccount is not blocked in read mode during all connection process, which can last for several minutes.
- ActualCopied.ServerName = _strdup(ActualAccount->Server->Name);
- ActualCopied.ServerPort = ActualAccount->Server->Port;
- ActualCopied.Flags = ActualAccount->Flags;
- ActualCopied.ServerLogin = _strdup(ActualAccount->Server->Login);
- ActualCopied.ServerPasswd = _strdup(ActualAccount->Server->Passwd);
- ActualCopied.NFlags = ActualAccount->NewMailN.Flags;
- ActualCopied.NNFlags = ActualAccount->NoNewMailN.Flags;
-
- ReadDone(ActualAccount);
- SCInc(ActualAccount->InternetQueries); //increment counter, that there is one more thread waiting for connection
-
- WaitForSingleObject(ActualAccount->UseInternetFree, INFINITE); //wait until we can use connection
- SCDec(ActualAccount->InternetQueries);
-
- //OK, we enter the "use internet" section. But after we start communication, we can test if we did not enter the "use internet" section only for the reason,
- //that previous thread release the internet section because this account has stop signal (we stop account and there are 2 threads: one communicating,
- //the second one waiting for network access- the first one ends because we want to stop account, this one is released, but should be stopped as well).
- if (!ActualAccount->AbleToWork) {
- SetEvent(ActualAccount->UseInternetFree);
- SCDec(ActualAccount->UsingThreads);
- return 0;
- }
- UsingInternet = TRUE;
-
- GetLocalTime(&now);
- ActualAccount->SystemError = 0; //now we can use internet for this socket. First, clear errorcode.
- try {
- SetContactStatus(ActualAccount, ID_STATUS_OCCUPIED);
-
- // if we are already connected, we have open session (another thread left us open session), so we don't need to login
- // note that connected state without logging cannot occur, because if we close session, we always close socket too (we must close socket is the right word :))
- if ((MyClient->NetClient == nullptr) || !MyClient->NetClient->Connected()) {
- SetAccountStatus(ActualAccount, TranslateT("Connecting to server"));
-
- DataRX = MyClient->Connect(ActualCopied.ServerName, ActualCopied.ServerPort, ActualCopied.Flags & YAMN_ACC_SSL23, ActualCopied.Flags & YAMN_ACC_NOTLS);
- char *timestamp = nullptr;
-
- if (DataRX != nullptr) {
- if (ActualCopied.Flags & YAMN_ACC_APOP) {
- char *lpos = strchr(DataRX, '<');
- char *rpos = strchr(DataRX, '>');
- if (lpos && rpos && rpos > lpos) {
- int sz = (int)(rpos - lpos + 2);
- timestamp = new char[sz];
- memcpy(timestamp, lpos, sz - 1);
- timestamp[sz - 1] = '\0';
- }
- }
- free(DataRX);
- DataRX = nullptr;
- }
-
- SetAccountStatus(ActualAccount, TranslateT("Entering POP3 account"));
-
- if (ActualCopied.Flags & YAMN_ACC_APOP) {
- DataRX = MyClient->APOP(ActualCopied.ServerLogin, ActualCopied.ServerPasswd, timestamp);
- if (DataRX != nullptr)
- free(DataRX);
- DataRX = nullptr;
- delete[] timestamp;
- }
- else {
- DataRX = MyClient->User(ActualCopied.ServerLogin);
- if (DataRX != nullptr)
- free(DataRX);
- DataRX = nullptr;
- DataRX = MyClient->Pass(ActualCopied.ServerPasswd);
- if (DataRX != nullptr)
- free(DataRX);
- DataRX = nullptr;
- }
- }
- SetAccountStatus(ActualAccount, TranslateT("Searching for new mail message"));
-
- DataRX = MyClient->Stat();
-
- ExtractStat(DataRX, &mboxsize, &msgs);
-
- if (DataRX != nullptr)
- free(DataRX);
- DataRX = nullptr;
- for (i = 0; i < msgs; i++) {
- if (!i)
- MsgQueuePtr = NewMails = (HYAMNMAIL)CallService(MS_YAMN_CREATEACCOUNTMAIL, (WPARAM)ActualAccount, (LPARAM)YAMN_MAILVERSION);
- else {
- MsgQueuePtr->Next = (HYAMNMAIL)CallService(MS_YAMN_CREATEACCOUNTMAIL, (WPARAM)ActualAccount, (LPARAM)YAMN_MAILVERSION);
- MsgQueuePtr = MsgQueuePtr->Next;
- }
- if (MsgQueuePtr == nullptr) {
- ActualAccount->SystemError = EPOP3_QUEUEALLOC;
- throw (uint32_t)ActualAccount->SystemError;
- }
- }
-
- if (msgs) {
- DataRX = MyClient->List();
- ExtractList(DataRX, MyClient->NetClient->Rcv, NewMails);
- if (DataRX != nullptr)
- free(DataRX);
-
- DataRX = MyClient->Uidl();
- ExtractUIDL(DataRX, MyClient->NetClient->Rcv, NewMails);
-
- if (DataRX != nullptr)
- free(DataRX);
- DataRX = nullptr;
- }
-
- if (WAIT_OBJECT_0 != MsgsWaitToWrite(ActualAccount))
- throw (uint32_t)(ActualAccount->SystemError = EACC_STOPPED);
-
- ActualAccount->LastChecked = now;
- for (MsgQueuePtr = (HYAMNMAIL)ActualAccount->Mails; MsgQueuePtr != nullptr; MsgQueuePtr = MsgQueuePtr->Next) {
- if (MsgQueuePtr->Flags & YAMN_MSG_BODYREQUESTED) {
- HYAMNMAIL NewMsgsPtr = nullptr;
- for (NewMsgsPtr = (HYAMNMAIL)NewMails; NewMsgsPtr != nullptr; NewMsgsPtr = NewMsgsPtr->Next) {
- if (!mir_strcmp(MsgQueuePtr->ID, NewMsgsPtr->ID)) {
- wchar_t accstatus[512];
- mir_snwprintf(accstatus, TranslateT("Reading body %s"), NewMsgsPtr->ID);
- SetAccountStatus(ActualAccount, accstatus);
- DataRX = MyClient->Top(MsgQueuePtr->Number, 100);
- if (DataRX != nullptr) {
- Temp = DataRX;
- while ((Temp < DataRX + MyClient->NetClient->Rcv) && (WS(Temp) || ENDLINE(Temp))) Temp++;
-
- if (OKLINE(DataRX))
- for (Temp = DataRX; (Temp < DataRX + MyClient->NetClient->Rcv) && (!ENDLINE(Temp)); Temp++);
- while ((Temp < DataRX + MyClient->NetClient->Rcv) && ENDLINE(Temp)) Temp++;
- }
- else
- continue;
- //delete all the headers of the old mail MsgQueuePtr->MailData->TranslatedHeader
- struct CMimeItem *TH = MsgQueuePtr->MailData->TranslatedHeader;
- if (TH) for (; MsgQueuePtr->MailData->TranslatedHeader != nullptr;) {
- TH = TH->Next;
- if (MsgQueuePtr->MailData->TranslatedHeader->name != nullptr)
- delete[] MsgQueuePtr->MailData->TranslatedHeader->name;
- if (MsgQueuePtr->MailData->TranslatedHeader->value != nullptr)
- delete[] MsgQueuePtr->MailData->TranslatedHeader->value;
- delete MsgQueuePtr->MailData->TranslatedHeader;
- MsgQueuePtr->MailData->TranslatedHeader = TH;
- }
-
- TranslateHeader(Temp, MyClient->NetClient->Rcv - (Temp - DataRX), &MsgQueuePtr->MailData->TranslatedHeader);
-
- MsgQueuePtr->Flags |= YAMN_MSG_BODYRECEIVED;
-
- if (DataRX != nullptr)
- free(DataRX);
- DataRX = nullptr;
- break;
- }
- }
- }
- }
-
- SynchroMessages(ActualAccount, (HYAMNMAIL *)&ActualAccount->Mails, nullptr, (HYAMNMAIL *)&NewMails, nullptr); //we get only new mails on server!
-
- MsgsWriteDone(ActualAccount);
- for (MsgQueuePtr = (HYAMNMAIL)ActualAccount->Mails; MsgQueuePtr != nullptr; MsgQueuePtr = MsgQueuePtr->Next) {
- if ((MsgQueuePtr->Flags & YAMN_MSG_BODYREQUESTED) && (MsgQueuePtr->Flags & YAMN_MSG_BODYRECEIVED)) {
- MsgQueuePtr->Flags &= ~YAMN_MSG_BODYREQUESTED;
- if (MsgQueuePtr->MsgWindow)
- SendMessage(MsgQueuePtr->MsgWindow, WM_YAMN_CHANGECONTENT, 0, 0);
- }
- }
-
- for (msgs = 0, MsgQueuePtr = NewMails; MsgQueuePtr != nullptr; MsgQueuePtr = MsgQueuePtr->Next, msgs++); //get number of new mails
-
- try {
- wchar_t accstatus[512];
-
- for (i = 0, MsgQueuePtr = NewMails; MsgQueuePtr != nullptr; i++) {
- BOOL autoretr = (ActualAccount->Flags & YAMN_ACC_BODY) != 0;
- DataRX = MyClient->Top(MsgQueuePtr->Number, autoretr ? 100 : 0);
- mir_snwprintf(accstatus, TranslateT("Reading new mail messages (%d%% done)"), 100 * i / msgs);
- SetAccountStatus(ActualAccount, accstatus);
-
- if (DataRX != nullptr) {
- Temp = DataRX;
- while ((Temp < DataRX + MyClient->NetClient->Rcv) && (WS(Temp) || ENDLINE(Temp))) Temp++;
-
- if (OKLINE(DataRX))
- for (Temp = DataRX; (Temp < DataRX + MyClient->NetClient->Rcv) && (!ENDLINE(Temp)); Temp++);
- while ((Temp < DataRX + MyClient->NetClient->Rcv) && ENDLINE(Temp)) Temp++;
- }
- else
- continue;
-
- TranslateHeader(Temp, MyClient->NetClient->Rcv - (Temp - DataRX), &MsgQueuePtr->MailData->TranslatedHeader);
-
-
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "</New mail>\n");
- #endif
- MsgQueuePtr->Flags |= YAMN_MSG_NORMALNEW;
- if (autoretr) MsgQueuePtr->Flags |= YAMN_MSG_BODYRECEIVED;
-
- //We are going to filter mail. Warning!- we must not be in read access neither write access to mails when calling this service
- //This is done, because the "NewMails" queue is not synchronised. It is because it is new queue. Only this thread uses new queue yet, it is not
- //connected to account mail queue.
- // CallService(MS_YAMN_FILTERMAIL,(WPARAM)ActualAccount,(LPARAM)MsgQueuePtr);
- FilterMailSvc((WPARAM)ActualAccount, (LPARAM)MsgQueuePtr);
-
- if (DataRX != nullptr)
- free(DataRX);
- DataRX = nullptr;
-
- //MsgQueuePtr->MailData->Body=MyClient->Retr(MsgQueuePtr->Number);
-
- MsgQueuePtr = MsgQueuePtr->Next;
-
- }
-
- if (WAIT_OBJECT_0 != MsgsWaitToWrite(ActualAccount))
- throw (uint32_t)ActualAccount->SystemError == EACC_STOPPED;
-
- if (ActualAccount->Mails == nullptr)
- ActualAccount->Mails = NewMails;
- else {
- ActualAccount->LastMail = ActualAccount->LastChecked;
- AppendQueue((HYAMNMAIL)ActualAccount->Mails, NewMails);
- }
-
- MsgsWriteDone(ActualAccount);
-
- // we are going to delete mails having SPAM flag level3 and 4 (see m_mails.h) set
- {
- struct DeleteParam ParamToDeleteMails = {YAMN_DELETEVERSION, INVALID_HANDLE_VALUE, ActualAccount, YAMNParam, (void *)POP3_DELETEFROMCHECK};
-
- // Delete mails from server. Here we should not be in write access for account's mails
- DeleteMailsPOP3(&ParamToDeleteMails);
- }
-
- // if there is no waiting thread for internet connection close it
- // else leave connection open
- if (0 == SCGetNumber(ActualAccount->InternetQueries)) {
- DataRX = MyClient->Quit();
- if (DataRX != nullptr)
- free(DataRX);
- DataRX = nullptr;
- MyClient->NetClient->Disconnect();
-
- SetAccountStatus(ActualAccount, TranslateT("Disconnected"));
- }
-
- UsingInternet = FALSE;
- SetEvent(ActualAccount->UseInternetFree);
-
- ActualAccount->LastSChecked = ActualAccount->LastChecked;
- ActualAccount->LastSynchronised = ActualAccount->LastChecked;
- }
- catch (...) {
- throw; //go to the main exception handling
- }
-
- {
- YAMN_MAILBROWSERPARAM Param = {(HANDLE)nullptr, ActualAccount, ActualCopied.NFlags, ActualCopied.NNFlags, YAMNParam};
-
- if (CheckFlags & YAMN_FORCECHECK)
- Param.nnflags |= YAMN_ACC_POP; //if force check, show popup anyway and if mailbrowser was opened, do not close
- Param.nnflags |= YAMN_ACC_MSGP; //do not close browser if already open
- CallService(MS_YAMN_MAILBROWSER, (WPARAM)&Param, (LPARAM)YAMN_MAILBROWSERVERSION);
- }
- SetContactStatus(ActualAccount, ActualAccount->isCounting ? ID_STATUS_ONLINE : ID_STATUS_OFFLINE);
- }
- #ifdef DEBUG_COMM
- catch (uint32_t ErrorCode)
- #else
- catch (uint32_t)
- #endif
- {
- if (ActualAccount->Client.POP3Error == EPOP3_STOPPED)
- ActualAccount->SystemError = EACC_STOPPED;
- #ifdef DEBUG_COMM
- DebugLog(CommFile, "ERROR: %x\n", ErrorCode);
- #endif
- if (WAIT_OBJECT_0 == MsgsWaitToWrite(ActualAccount)) {
- ActualAccount->LastChecked = now;
- MsgsWriteDone(ActualAccount);
- }
-
- DeleteMIMEQueue(ActualAccount, NewMails);
-
- if (DataRX != nullptr)
- free(DataRX);
- DataRX = nullptr;
- switch (ActualAccount->SystemError) {
- case EACC_QUEUEALLOC:
- case EACC_STOPPED:
- ActualAccount->Client.NetClient->Disconnect();
- break;
- default:
- PostErrorProc(ActualAccount, YAMNParam, (uint32_t)NULL, MyClient->SSL); //it closes internet connection too
- }
-
- if (UsingInternet) //if our thread still uses internet
- SetEvent(ActualAccount->UseInternetFree);
-
- SetContactStatus(ActualAccount, ID_STATUS_NA);
- }
- free(ActualCopied.ServerName);
- free(ActualCopied.ServerLogin);
- free(ActualCopied.ServerPasswd);
- #ifdef DEBUG_COMM
- DebugLog(CommFile, "</--------Communication-------->\n");
- #endif
-
- // WriteAccounts();
- SCDec(ActualAccount->UsingThreads);
- return 0;
-}
-
-void __cdecl DeleteMailsPOP3(void *param)
-{
- DeleteParam *WhichTemp = (DeleteParam *)param;
-
- CPop3Client *MyClient;
- HYAMNMAIL DeleteMails, NewMails = nullptr, MsgQueuePtr = nullptr;
- char *DataRX = nullptr;
- int mboxsize = 0, msgs = 0, i;
- BOOL UsingInternet = FALSE;
- struct
- {
- char *ServerName;
- uint32_t ServerPort;
- char *ServerLogin;
- char *ServerPasswd;
- uint32_t Flags;
- uint32_t NFlags;
- uint32_t NNFlags;
- } ActualCopied;
-
- //First, we should compare our version of DeleteParam structure, but here it is not needed, because YAMN and internal plugin
- //have the same version. But your plugin should do that in this way:
- // if (((struct DeleteParam *)WhichTemp)->Ver != YAMN_DELETEVERSION)
- // {
- // SetEvent(((struct DeleteParam *)WhichTemp)->ThreadRunningEV); //don't forget to unblock YAMN
- // return (uint32_t)-1; //ok, but we should return value.
- // //When our plugin returns e.g. 0xFFFFFFFF (this is only our plugin value, YAMN does nothing with return value,
- // //but only tests if it is nonzero. If yes, it calls GetErrorStringFcn), we know problem occured in YAMN incompatibility
- // //and then we can in our GetErrorStringFcn e.g. return string "Uncompatible version of YAMN".
- // }
-
- HPOP3ACCOUNT ActualAccount = (HPOP3ACCOUNT)WhichTemp->AccountParam; //copy address of structure from calling thread to stack of this thread
- LPVOID YAMNParam = WhichTemp->BrowserParam;
- UINT_PTR POP3PluginParam = (UINT_PTR)((struct DeleteParam *)WhichTemp)->CustomParam;
-
- SCInc(ActualAccount->UsingThreads);
- if (INVALID_HANDLE_VALUE != WhichTemp->ThreadRunningEV)
- SetEvent(WhichTemp->ThreadRunningEV);
-
- if (WAIT_OBJECT_0 != WaitToRead(ActualAccount)) {
- SCDec(ActualAccount->UsingThreads);
- return;
- }
-
- if (nullptr == (DeleteMails = (HYAMNMAIL)CreateNewDeleteQueue((HYAMNMAIL)ActualAccount->Mails))) //if there's no mail for deleting, return
- {
- if (POP3_DELETEFROMCHECK != POP3PluginParam) //We do not wait for free internet when calling from SynchroPOP3. It is because UseInternetFree is blocked
- {
- YAMN_MAILBROWSERPARAM Param = {(HANDLE)nullptr, ActualAccount, YAMN_ACC_MSGP, YAMN_ACC_MSGP, YAMNParam}; //Just update the window
- CallService(MS_YAMN_MAILBROWSER, (WPARAM)&Param, (LPARAM)YAMN_MAILBROWSERVERSION);
- }
-
- SCDec(ActualAccount->UsingThreads);
- return;
- }
-
- MyClient = &(ActualAccount->Client);
-
- //Now, copy all needed information about account to local variables, so ActualAccount is not blocked in read mode during all connection process, which can last for several minutes.
- ActualCopied.ServerName = _strdup(ActualAccount->Server->Name);
- ActualCopied.ServerPort = ActualAccount->Server->Port;
- ActualCopied.Flags = ActualAccount->Flags;
- ActualCopied.ServerLogin = _strdup(ActualAccount->Server->Login);
- ActualCopied.ServerPasswd = _strdup(ActualAccount->Server->Passwd);
- ActualCopied.NFlags = ActualAccount->NewMailN.Flags;
- ActualCopied.NNFlags = ActualAccount->NoNewMailN.Flags;
-
- ReadDone(ActualAccount);
-
- SCInc(ActualAccount->InternetQueries); //This is POP3-internal SCOUNTER, we set another thread wait for this account to be connected to inet
- if (POP3_DELETEFROMCHECK != POP3PluginParam) //We do not wait for free internet when calling from SynchroPOP3. It is because UseInternetFree is blocked
- WaitForSingleObject(ActualAccount->UseInternetFree, INFINITE);
-
- SCDec(ActualAccount->InternetQueries);
- UsingInternet = TRUE;
-
- try {
- SetContactStatus(ActualAccount, ID_STATUS_OCCUPIED);
- #ifdef DEBUG_COMM
- DebugLog(CommFile, "<--------Communication-------->\n");
- #endif
- if ((MyClient->NetClient == nullptr) || !MyClient->NetClient->Connected()) {
- SetAccountStatus(ActualAccount, TranslateT("Connecting to server"));
-
- DataRX = MyClient->Connect(ActualCopied.ServerName, ActualCopied.ServerPort, ActualCopied.Flags & YAMN_ACC_SSL23, ActualCopied.Flags & YAMN_ACC_NOTLS);
-
- char *timestamp = nullptr;
- if (DataRX != nullptr) {
- if (ActualAccount->Flags & YAMN_ACC_APOP) {
- char *lpos = strchr(DataRX, '<');
- char *rpos = strchr(DataRX, '>');
- if (lpos && rpos && rpos > lpos) {
- int sz = (int)(rpos - lpos + 2);
- timestamp = new char[sz];
- memcpy(timestamp, lpos, sz - 1);
- timestamp[sz - 1] = '\0';
- }
- }
- free(DataRX);
- DataRX = nullptr;
- }
- SetAccountStatus(ActualAccount, TranslateT("Entering POP3 account"));
-
- if (ActualAccount->Flags & YAMN_ACC_APOP) {
- DataRX = MyClient->APOP(ActualCopied.ServerLogin, ActualCopied.ServerPasswd, timestamp);
- if (DataRX != nullptr)
- free(DataRX);
- DataRX = nullptr;
- delete[] timestamp;
- }
- else {
- DataRX = MyClient->User(ActualCopied.ServerLogin);
- if (DataRX != nullptr)
- free(DataRX);
- DataRX = nullptr;
- DataRX = MyClient->Pass(ActualCopied.ServerPasswd);
- if (DataRX != nullptr)
- free(DataRX);
- DataRX = nullptr;
- }
- }
-
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "<--------Deleting requested mails-------->\n");
- #endif
- if (POP3_DELETEFROMCHECK != POP3PluginParam) //We do not need to get mails on server as we have already it from check function
- {
- SetAccountStatus(ActualAccount, TranslateT("Deleting requested mails"));
-
- DataRX = MyClient->Stat();
-
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "<Extracting stat>\n");
- #endif
- ExtractStat(DataRX, &mboxsize, &msgs);
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "<MailBoxSize>%d</MailBoxSize>\n", mboxsize);
- DebugLog(DecodeFile, "<Msgs>%d</Msgs>\n", msgs);
- DebugLog(DecodeFile, "</Extracting stat>\n");
- #endif
- if (DataRX != nullptr)
- free(DataRX);
- DataRX = nullptr;
- for (i = 0; i < msgs; i++) {
- if (!i)
- MsgQueuePtr = NewMails = (HYAMNMAIL)CallService(MS_YAMN_CREATEACCOUNTMAIL, (WPARAM)ActualAccount, (LPARAM)YAMN_MAILVERSION);
- else {
- MsgQueuePtr->Next = (HYAMNMAIL)CallService(MS_YAMN_CREATEACCOUNTMAIL, (WPARAM)ActualAccount, (LPARAM)YAMN_MAILVERSION);
- MsgQueuePtr = MsgQueuePtr->Next;
- }
- if (MsgQueuePtr == nullptr) {
- ActualAccount->SystemError = EPOP3_QUEUEALLOC;
- throw (uint32_t)ActualAccount->SystemError;
- }
- }
-
- if (msgs) {
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "<Extracting UIDL>\n");
- #endif
- DataRX = MyClient->Uidl();
- ExtractUIDL(DataRX, MyClient->NetClient->Rcv, NewMails);
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "</Extracting UIDL>\n");
- #endif
- if (DataRX != nullptr)
- free(DataRX);
- DataRX = nullptr;
- // we get "new mails" on server (NewMails will contain all mails on server not found in DeleteMails)
- // but also in DeleteMails we get only those, which are still on server with their responsable numbers
- SynchroMessages(ActualAccount, (HYAMNMAIL *)&DeleteMails, nullptr, (HYAMNMAIL *)&NewMails, nullptr);
- }
- }
- else SetAccountStatus(ActualAccount, TranslateT("Deleting spam"));
-
- if (WAIT_OBJECT_0 != MsgsWaitToWrite(ActualAccount))
- throw (uint32_t)EACC_STOPPED;
-
- if (msgs || POP3_DELETEFROMCHECK == POP3PluginParam) {
- try {
- HYAMNMAIL Temp;
-
- for (i = 0, MsgQueuePtr = DeleteMails; MsgQueuePtr != nullptr; i++) {
- if (!(MsgQueuePtr->Flags & YAMN_MSG_VIRTUAL)) //of course we can only delete real mails, not virtual
- {
- DataRX = MyClient->Dele(MsgQueuePtr->Number);
- Temp = MsgQueuePtr->Next;
- if (POP3_FOK == MyClient->AckFlag) //if server answers that mail was deleted
- {
- DeleteMIMEMessage((HYAMNMAIL *)&DeleteMails, MsgQueuePtr);
- HYAMNMAIL DeletedMail = FindMIMEMessageByID((HYAMNMAIL)ActualAccount->Mails, MsgQueuePtr->ID);
- if ((MsgQueuePtr->Flags & YAMN_MSG_MEMDELETE)) //if mail should be deleted from memory (or disk)
- {
- DeleteMIMEMessage((HYAMNMAIL *)&ActualAccount->Mails, DeletedMail); //remove from queue
- CallService(MS_YAMN_DELETEACCOUNTMAIL, (WPARAM)POP3Plugin, (LPARAM)DeletedMail);
- }
- else //else mark it only as "deleted mail"
- {
- DeletedMail->Flags |= (YAMN_MSG_VIRTUAL | YAMN_MSG_DELETED);
- DeletedMail->Flags &= ~(YAMN_MSG_NEW | YAMN_MSG_USERDELETE | YAMN_MSG_AUTODELETE); //clear "new mail"
- }
- delete MsgQueuePtr->MailData;
- delete[] MsgQueuePtr->ID;
- delete MsgQueuePtr;
- }
- MsgQueuePtr = Temp;
-
- if (DataRX != nullptr)
- free(DataRX);
- DataRX = nullptr;
- }
- else
- MsgQueuePtr = MsgQueuePtr->Next;
- }
- }
- catch (...) //if any exception in the code where we have write-access to account occured, don't forget to leave write-access
- {
- MsgsWriteDone(ActualAccount);
- throw; //and go to the main exception handling
- }
-
- if (NewMails != nullptr)
- // in ActualAccount->Mails we have all mails stored before calling this function
- // in NewMails we have all mails not found in DeleteMails (in other words: we performed new ID checking and we
- // stored all mails found on server, then we deleted the ones we wanted to delete in this function
- // and NewMails queue now contains actual state of mails on server). But we will not use NewMails as actual state, because NewMails does not contain header data (subject, from...)
- // We perform deleting from ActualAccount->Mails: we remove from original queue (ActualAccount->Mails) all deleted mails
- SynchroMessages(ActualAccount, (HYAMNMAIL *)&ActualAccount->Mails, nullptr, (HYAMNMAIL *)&NewMails, nullptr);
- // Now ActualAccount->Mails contains all mails when calling this function except the ones, we wanted to delete (these are in DeleteMails)
- // And in NewMails we have new mails (if any)
- else if (POP3_DELETEFROMCHECK != POP3PluginParam) {
- DeleteMIMEQueue(ActualAccount, (HYAMNMAIL)ActualAccount->Mails);
- ActualAccount->Mails = nullptr;
- }
- }
- else {
- DeleteMIMEQueue(ActualAccount, (HYAMNMAIL)ActualAccount->Mails);
- ActualAccount->Mails = nullptr;
- }
-
- MsgsWriteDone(ActualAccount);
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "</--------Deleting requested mails-------->\n");
- #endif
-
- // TODO: now, we have in NewMails new mails. If NewMails is not NULL, we found some new mails, so Checking for new mail should be performed
- // now, we do not call CheckPOP3
-
- // if there is no waiting thread for internet connection close it
- // else leave connection open
- // if this functin was called from SynchroPOP3, then do not try to disconnect
- if (POP3_DELETEFROMCHECK != POP3PluginParam) {
- YAMN_MAILBROWSERPARAM Param = {(HANDLE)nullptr, ActualAccount, ActualCopied.NFlags, YAMN_ACC_MSGP, YAMNParam};
-
- CallService(MS_YAMN_MAILBROWSER, (WPARAM)&Param, (LPARAM)YAMN_MAILBROWSERVERSION);
-
- if (0 == SCGetNumber(ActualAccount->InternetQueries)) {
- DataRX = MyClient->Quit();
- if (DataRX != nullptr)
- free(DataRX);
- DataRX = nullptr;
- MyClient->NetClient->Disconnect();
-
- SetAccountStatus(ActualAccount, TranslateT("Disconnected"));
- }
-
- UsingInternet = FALSE;
- SetEvent(ActualAccount->UseInternetFree);
- }
- SetContactStatus(ActualAccount, ActualAccount->isCounting ? ID_STATUS_ONLINE : ID_STATUS_OFFLINE);
- }
- #ifdef DEBUG_COMM
- catch (uint32_t ErrorCode)
- #else
- catch (uint32_t)
- #endif
- {
- if (ActualAccount->Client.POP3Error == EPOP3_STOPPED)
- ActualAccount->SystemError = EACC_STOPPED;
- #ifdef DEBUG_COMM
- DebugLog(CommFile, "ERROR %x\n", ErrorCode);
- #endif
- if (DataRX != nullptr)
- free(DataRX);
- switch (ActualAccount->SystemError) {
- case EACC_QUEUEALLOC:
- case EACC_STOPPED:
- ActualAccount->Client.NetClient->Disconnect();
- break;
- default:
- PostErrorProc(ActualAccount, YAMNParam, POP3PluginParam, MyClient->SSL); //it closes internet connection too
- }
-
- if (UsingInternet && (POP3_DELETEFROMCHECK != POP3PluginParam)) //if our thread still uses internet and it is needed to release internet
- SetEvent(ActualAccount->UseInternetFree);
- }
-
- free(ActualCopied.ServerName);
- free(ActualCopied.ServerLogin);
- free(ActualCopied.ServerPasswd);
-
- DeleteMIMEQueue(ActualAccount, NewMails);
- DeleteMIMEQueue(ActualAccount, DeleteMails);
-
- #ifdef DEBUG_COMM
- DebugLog(CommFile, "</--------Communication-------->\n");
- #endif
-
- // WriteAccounts();
- SCDec(ActualAccount->UsingThreads);
- return;
-}
-
-void ExtractStat(char *stream, int *mboxsize, int *mails)
-{
- char *finder = stream;
- while (WS(finder) || ENDLINE(finder)) finder++;
- if (ACKLINE(finder)) {
- while (!WS(finder)) finder++;
- while (WS(finder)) finder++;
- }
- if (1 != sscanf(finder, "%d", mails))
- throw (uint32_t)EPOP3_STAT;
- while (!WS(finder)) finder++;
- while (WS(finder)) finder++;
- if (1 != sscanf(finder, "%d", mboxsize))
- throw (uint32_t)EPOP3_STAT;
-}
-void ExtractMail(char *stream, int len, HYAMNMAIL queue)
-{
- char *finder = stream;
- char *finderend;
- int msgnr, i;
- HYAMNMAIL queueptr = queue;
-
- while (WS(finder) || ENDLINE(finder)) finder++;
- while (!ACKLINE(finder)) finder++;
- while (!ENDLINE(finder)) finder++; //now we at the end of first ack line
- while (finder <= (stream + len)) {
- while (ENDLINE(finder)) finder++; //go to the new line
- if (DOTLINE(finder + 1)) //at the end of stream
- break;
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "<Message>\n");
- #endif
- while (WS(finder)) finder++; //jump whitespace
- if (1 != sscanf(finder, "%d", &msgnr))
- throw (uint32_t)EPOP3_UIDL;
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "<Nr>%d</Nr>\n", msgnr);
- #endif
- // for (i=1,queueptr=queue;(queueptr->Next != NULL) && (i<msgnr);queueptr=queueptr->Next,i++);
- // if (i != msgnr)
- // throw (uint32_t)EPOP3_UIDL;
- while (!WS(finder)) finder++; //jump characters
- while (WS(finder)) finder++; //jump whitespace
- finderend = finder + 1;
- while (!WS(finderend) && !ENDLINE(finderend)) finderend++;
- queueptr->ID = new char[finderend - finder + 1];
- for (i = 0; finder != finderend; finder++, i++)
- queueptr->MailData->Body[i] = *finder;
- queueptr->MailData->Body[i] = 0; //ends string
- queueptr->Number = msgnr;
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "<ID>%s</ID>\n", queueptr->MailData->Body);
- DebugLog(DecodeFile, "</Message>\n");
- #endif
- queueptr = queueptr->Next;
- while (!ENDLINE(finder)) finder++;
- }
-}
-
-void ExtractUIDL(char *stream, int len, HYAMNMAIL queue)
-{
- char *finder = stream;
- char *finderend;
- int msgnr, i;
- HYAMNMAIL queueptr = queue;
-
- while (WS(finder) || ENDLINE(finder)) finder++;
- while (!ACKLINE(finder)) finder++;
- while (!ENDLINE(finder)) finder++; //now we at the end of first ack line
- while (finder <= (stream + len)) {
- while (ENDLINE(finder)) finder++; //go to the new line
- if (DOTLINE(finder + 1)) //at the end of stream
- break;
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "<Message>\n");
- #endif
- while (WS(finder)) finder++; //jump whitespace
- if (1 != sscanf(finder, "%d", &msgnr))
- throw (uint32_t)EPOP3_UIDL;
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "<Nr>%d</Nr>\n", msgnr);
- #endif
- // for (i=1,queueptr=queue;(queueptr->Next != NULL) && (i<msgnr);queueptr=queueptr->Next,i++);
- // if (i != msgnr)
- // throw (uint32_t)EPOP3_UIDL;
- while (!WS(finder)) finder++; //jump characters
- while (WS(finder)) finder++; //jump whitespace
- finderend = finder + 1;
- while (!WS(finderend) && !ENDLINE(finderend)) finderend++;
- queueptr->ID = new char[finderend - finder + 1];
- for (i = 0; finder != finderend; finder++, i++)
- queueptr->ID[i] = *finder;
- queueptr->ID[i] = 0; //ends string
- queueptr->Number = msgnr;
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "<ID>%s</ID>\n", queueptr->ID);
- DebugLog(DecodeFile, "</Message>\n");
- #endif
- queueptr = queueptr->Next;
- while (!ENDLINE(finder)) finder++;
- }
-}
-
-void ExtractList(char *stream, int len, HYAMNMAIL queue)
-{
- char *finder = stream;
- char *finderend;
- int msgnr, i;
- HYAMNMAIL queueptr;
-
- while (WS(finder) || ENDLINE(finder)) finder++;
- while (!ACKLINE(finder)) finder++;
- while (!ENDLINE(finder)) finder++; //now we at the end of first ack line
- while (finder <= (stream + len)) {
- while (ENDLINE(finder)) finder++; //go to the new line
- if (DOTLINE(finder + 1)) //at the end of stream
- break;
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "<Message>\n", NULL, 0);
- #endif
- while (WS(finder)) finder++; //jump whitespace
- if (1 != sscanf(finder, "%d", &msgnr)) //message nr.
- throw (uint32_t)EPOP3_LIST;
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "<Nr>%d</Nr>\n", msgnr);
- #endif
-
- for (i = 1, queueptr = queue; (queueptr->Next != nullptr) && (i < msgnr); queueptr = queueptr->Next, i++);
- if (i != msgnr)
- throw (uint32_t)EPOP3_LIST;
- while (!WS(finder)) finder++; //jump characters
- while (WS(finder)) finder++; //jump whitespace
- finderend = finder + 1;
- if (1 != sscanf(finder, "%u", &queueptr->MailData->Size))
- throw (uint32_t)EPOP3_LIST;
- #ifdef DEBUG_DECODE
- DebugLog(DecodeFile, "<Nr>%d</Nr>\n", queueptr->MailData->Size);
- #endif
- while (!ENDLINE(finder)) finder++;
- }
-}
-
-wchar_t *WINAPI GetErrorString(DWORD Code)
-{
- static wchar_t *POP3Errors[] =
- {
- LPGENW("Memory allocation error."), //memory allocation
- LPGENW("Account is about to be stopped."), //stop account
- LPGENW("Cannot connect to POP3 server."),
- LPGENW("Cannot allocate memory for received data."),
- LPGENW("Cannot login to POP3 server."),
- LPGENW("Bad user or password."),
- LPGENW("Server does not support APOP authorization."),
- LPGENW("Error while executing POP3 command."),
- LPGENW("Error while executing POP3 command."),
- LPGENW("Error while executing POP3 command."),
- };
-
- static wchar_t *NetlibErrors[] =
- {
- LPGENW("Cannot connect to server with NetLib."),
- LPGENW("Cannot send data."),
- LPGENW("Cannot receive data."),
- LPGENW("Cannot allocate memory for received data."),
- };
-
- static wchar_t *SSLErrors[] =
- {
- LPGENW("OpenSSL not loaded."),
- LPGENW("Windows socket 2.0 init failed."),
- LPGENW("DNS lookup error."),
- LPGENW("Error while creating base socket."),
- LPGENW("Error connecting to server with socket."),
- LPGENW("Error while creating SSL structure."),
- LPGENW("Error connecting socket with SSL."),
- LPGENW("Server rejected connection with SSL."),
- LPGENW("Cannot write SSL data."),
- LPGENW("Cannot read SSL data."),
- LPGENW("Cannot allocate memory for received data."),
- };
-
- wchar_t *ErrorString = new wchar_t[ERRORSTR_MAXLEN];
- POP3_ERRORCODE *ErrorCode = (POP3_ERRORCODE *)(UINT_PTR)Code;
-
- mir_snwprintf(ErrorString, ERRORSTR_MAXLEN, TranslateT("Error %d-%d-%d-%d:"), ErrorCode->AppError, ErrorCode->POP3Error, ErrorCode->NetError, ErrorCode->SystemError);
- if (ErrorCode->POP3Error)
- mir_snwprintf(ErrorString, ERRORSTR_MAXLEN, L"%s\n%s", ErrorString, TranslateW(POP3Errors[ErrorCode->POP3Error - 1]));
- if (ErrorCode->NetError) {
- if (ErrorCode->SSL)
- mir_snwprintf(ErrorString, ERRORSTR_MAXLEN, L"%s\n%s", ErrorString, TranslateW(SSLErrors[ErrorCode->NetError - 1]));
- else
- mir_snwprintf(ErrorString, ERRORSTR_MAXLEN, L"%s\n%s", ErrorString, TranslateW(NetlibErrors[ErrorCode->NetError - 4]));
- }
-
- return ErrorString;
-}
-
-void WINAPI DeleteErrorString(LPVOID String)
-{
- delete (char *)String;
-}
+/*
+ * This code implements POP3 server checking for new mail and so on.
+ * There's function SynchroPOP3 in this file- for checking and synchronising POP3 account
+ * and DeleteMailsPOP3- for deleting mails from POP3 server
+ *
+ * Note this file acts as main file for internal plugin.
+ *
+ * (c) majvan 2002-2004
+ * 18/08
+ */
+
+
+#include "../../stdafx.h"
+
+#define ERRORSTR_MAXLEN 1024 //in wide-chars
+
+ //--------------------------------------------------------------------------------------------------
+
+HANDLE hNetLib = nullptr;
+PSCOUNTER CPOP3Account::AccountWriterSO = nullptr;
+
+//Creates new CPOP3Account structure
+CAccount *WINAPI CreatePOP3Account(HYAMNPROTOPLUGIN Plugin, DWORD CAccountVersion);
+
+//Deletes CPOP3Account structure
+void WINAPI DeletePOP3Account(CAccount *Which);
+
+//Sets stop flag to account
+void WINAPI StopPOP3Account(CAccount *Which);
+
+//Function registers standard functions for YAMN
+int RegisterPOP3Plugin(WPARAM, LPARAM);
+
+//Unloads all variables created on heap (delete[])
+DWORD WINAPI UnLoadPOP3(void *);
+
+//Function writes POP3 accounts using YAMN exported functions
+DWORD WINAPI WritePOP3Accounts();
+
+//Function stores plugin's data for account to file
+DWORD WINAPI WritePOP3Options(HANDLE, CAccount *);
+
+//Function reads plugin's data for account from file
+DWORD WINAPI ReadPOP3Options(CAccount *, char **, char *);
+
+//Creates new mail for an account
+HYAMNMAIL WINAPI CreatePOP3Mail(CAccount *Account, DWORD CMimeMailVersion);
+
+//Function does all needed work when connection failed or any error occured
+//Creates structure containing error code, closes internet session, runs "bad connect" function
+static void PostErrorProc(HPOP3ACCOUNT ActualAccount, void *ParamToBadConnect, uint32_t POP3PluginParam, BOOL UseSSL);
+
+//Checks POP3 account and stores all info to account. It deletes old mails=> synchro
+// WhichTemp- pointer to strucure containing needed information
+DWORD WINAPI SynchroPOP3(struct CheckParam *WhichTemp);
+
+//Deletes mails from POP3 server
+// WhichTemp- structure containing needed information (queued messages to delete)
+//Function deletes from memory queue in WhichTemp structure
+void __cdecl DeleteMailsPOP3(void *param);
+
+//Function makes readable message about error. It sends it back to YAMN, so YAMN then
+//can show it to the message window
+wchar_t *WINAPI GetErrorString(DWORD Code);
+
+//Function deletes string allocated in GetErrorString
+void WINAPI DeleteErrorString(LPVOID String);
+
+//Extracts info from result of POP3's STAT command
+// stream- source string
+// len- length of source string
+// mboxsize- adreess to integer, that receives size of mailbox
+// mails- adreess to integer, that receives number of mails
+void ExtractStat(char *stream, int *mboxsize, int *mails);
+
+//Extracts mail ID on mailbox
+// stream- source string
+// len- length of source string
+// queue- address of first message, where first ID will be stored
+void ExtractUIDL(char *stream, int len, HYAMNMAIL queue);
+
+//Extracts mail size on mailbox
+// stream- source string
+// len- length of source string
+// queue- address of first message, where size of message #1 will be stored
+void ExtractList(char *stream, int len, HYAMNMAIL queue);
+
+void ExtractMail(char *stream, int len, HYAMNMAIL queue);
+
+YAMNExportedFcns *pYAMNFcn = nullptr;
+MailExportedFcns *pYAMNMailFcn = nullptr;
+
+YAMN_PROTOIMPORTFCN POP3ProtocolFunctions =
+{
+ CreatePOP3Account,
+ DeletePOP3Account,
+ StopPOP3Account,
+ WritePOP3Options,
+ ReadPOP3Options,
+ SynchroPOP3,
+ SynchroPOP3,
+ SynchroPOP3,
+ DeleteMailsPOP3,
+ GetErrorString,
+ nullptr,
+ DeleteErrorString,
+ WritePOP3Accounts,
+ nullptr,
+ UnLoadPOP3,
+};
+
+YAMN_MAILIMPORTFCN POP3MailFunctions =
+{
+ CreatePOP3Mail,
+ nullptr,
+ nullptr,
+ nullptr,
+};
+
+PYAMN_VARIABLES pYAMNVar = nullptr;
+HYAMNPROTOPLUGIN POP3Plugin = nullptr;
+
+YAMN_PROTOREGISTRATION POP3ProtocolRegistration =
+{
+ "POP3 protocol (internal)",
+ __VERSION_STRING_DOTS,
+ __COPYRIGHT,
+ __DESCRIPTION,
+ __AUTHORWEB,
+};
+
+static wchar_t *FileName = nullptr;
+
+HANDLE RegisterNLClient(char *name);
+
+//--------------------------------------------------------------------------------------------------
+//--------------------------------------------------------------------------------------------------
+
+CPOP3Account::CPOP3Account()
+{
+ //NOTE! This constructor constructs CAccount structure. If your plugin is not internal,
+ //you will need these constructors. All you need is in Account.cpp. Just copy to your source code
+ //constructor and destructor of CAccount.
+ UseInternetFree = CreateEvent(nullptr, FALSE, TRUE, nullptr);
+ InternetQueries = new SCOUNTER;
+ AbilityFlags = YAMN_ACC_BROWSE | YAMN_ACC_POPUP;
+
+ SetAccountStatus((CAccount *)this, TranslateT("Disconnected"));
+}
+
+CPOP3Account::~CPOP3Account()
+{
+ CloseHandle(UseInternetFree);
+ if (InternetQueries != nullptr)
+ delete InternetQueries;
+}
+
+CAccount *WINAPI CreatePOP3Account(HYAMNPROTOPLUGIN, DWORD)
+{
+ //First, we should check whether CAccountVersion matches.
+ //But this is internal plugin, so YAMN's CAccount structure and our CAccount structure are
+ //the same, so we do not need to test version. Otherwise, if CAccount version does not match
+ //in your plugin, you should return NULL, like this:
+ // if (CAccountVersion != YAMN_ACCOUNTVERSION) return NULL;
+
+ //Now it is needed to construct our POP3 account and return its handle
+ return (CAccount *)new struct CPOP3Account();
+}
+
+void WINAPI DeletePOP3Account(CAccount *Which)
+{
+ delete (HPOP3ACCOUNT)Which;
+}
+
+void WINAPI StopPOP3Account(CAccount *Which)
+{
+ ((HPOP3ACCOUNT)Which)->Client.Stopped = TRUE;
+ if (((HPOP3ACCOUNT)Which)->Client.NetClient != nullptr) //we should inform also network client. Usefull only when network client implements this feature
+ ((HPOP3ACCOUNT)Which)->Client.NetClient->Stopped = TRUE;
+}
+
+//This function is like main function for POP3 internal protocol
+int RegisterPOP3Plugin(WPARAM, LPARAM)
+{
+ // Get YAMN variables we can use
+ if (nullptr == (pYAMNVar = (PYAMN_VARIABLES)CallService(MS_YAMN_GETVARIABLES, YAMN_VARIABLESVERSION, 0)))
+ return 0;
+
+ // We have to get pointers to YAMN exported functions: allocate structure and fill it
+ if (nullptr == (pYAMNFcn = new struct YAMNExportedFcns)) {
+LBL_Error:
+ UnLoadPOP3(nullptr);
+ return 0;
+ }
+
+ // Register new pop3 user in netlib
+ if (nullptr == (hNetLib = RegisterNLClient("YAMN (POP3)")))
+ goto LBL_Error;
+
+ pYAMNFcn->SetProtocolPluginFcnImportFcn = (YAMN_SETPROTOCOLPLUGINFCNIMPORTFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_SETPROTOCOLPLUGINFCNIMPORTID, 0);
+ pYAMNFcn->WaitToWriteFcn = (YAMN_WAITTOWRITEFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_WAITTOWRITEID, 0);
+ pYAMNFcn->WriteDoneFcn = (YAMN_WRITEDONEFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_WRITEDONEID, 0);
+ pYAMNFcn->WaitToReadFcn = (YAMN_WAITTOREADFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_WAITTOREADID, 0);
+ pYAMNFcn->ReadDoneFcn = (YAMN_READDONEFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_READDONEID, 0);
+ pYAMNFcn->SCGetNumberFcn = (YAMN_SCMANAGEFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_SCGETNUMBERID, 0);
+ pYAMNFcn->SCIncFcn = (YAMN_SCMANAGEFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_SCINCID, 0);
+ pYAMNFcn->SCDecFcn = (YAMN_SCMANAGEFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_SCDECID, 0);
+ pYAMNFcn->SetStatusFcn = (YAMN_SETSTATUSFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_SETSTATUSID, 0);
+ pYAMNFcn->GetStatusFcn = (YAMN_GETSTATUSFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_GETSTATUSID, 0);
+
+ if (nullptr == (pYAMNMailFcn = new struct MailExportedFcns))
+ goto LBL_Error;
+
+ pYAMNMailFcn->SynchroMessagesFcn = (YAMN_SYNCHROMIMEMSGSFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_SYNCHROMIMEMSGSID, 0);
+ pYAMNMailFcn->TranslateHeaderFcn = (YAMN_TRANSLATEHEADERFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_TRANSLATEHEADERID, 0);
+ pYAMNMailFcn->AppendQueueFcn = (YAMN_APPENDQUEUEFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_APPENDQUEUEID, 0);
+ pYAMNMailFcn->DeleteMessagesToEndFcn = (YAMN_DELETEMIMEQUEUEFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_DELETEMIMEQUEUEID, 0);
+ pYAMNMailFcn->DeleteMessageFromQueueFcn = (YAMN_DELETEMIMEMESSAGEFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_DELETEMIMEMESSAGEID, 0);
+ pYAMNMailFcn->FindMessageByIDFcn = (YAMN_FINDMIMEMESSAGEFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_FINDMIMEMESSAGEID, 0);
+ pYAMNMailFcn->CreateNewDeleteQueueFcn = (YAMN_CREATENEWDELETEQUEUEFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_CREATENEWDELETEQUEUEID, 0);
+
+ //set static variable
+ if (CPOP3Account::AccountWriterSO == nullptr)
+ if (nullptr == (CPOP3Account::AccountWriterSO = new SCOUNTER))
+ goto LBL_Error;
+
+ //First, we register this plugin
+ //it is quite impossible this function returns zero (failure) as YAMN and internal plugin structre versions are the same
+ POP3ProtocolRegistration.Name = Translate("POP3 protocol (internal)");
+ POP3ProtocolRegistration.Description = Translate(__DESCRIPTION);
+ if (nullptr == (POP3Plugin = (HYAMNPROTOPLUGIN)CallService(MS_YAMN_REGISTERPROTOPLUGIN, (WPARAM)&POP3ProtocolRegistration, (LPARAM)YAMN_PROTOREGISTRATIONVERSION)))
+ return 0;
+
+ //Next we set our imported functions for YAMN
+ if (!SetProtocolPluginFcnImport(POP3Plugin, &POP3ProtocolFunctions, YAMN_PROTOIMPORTFCNVERSION, &POP3MailFunctions, YAMN_MAILIMPORTFCNVERSION))
+ return 0;
+
+ //Then, we read all mails for accounts.
+ //You must first register account, before using this function as YAMN must use CreatePOP3Account function to add new accounts
+ //But if CreatePOP3Account is not implemented (equals to NULL), YAMN creates account as YAMN's standard CAccount *
+ if (FileName) CallService(MS_YAMN_DELETEFILENAME, (WPARAM)FileName, 0); //shoud not happen (only for secure)
+ FileName = (wchar_t *)CallService(MS_YAMN_GETFILENAME, (WPARAM)L"pop3", 0);
+
+ switch (CallService(MS_YAMN_READACCOUNTS, (WPARAM)POP3Plugin, (LPARAM)FileName)) {
+ case EACC_FILEVERSION:
+ MessageBox(nullptr, TranslateT("Found new version of account book, not compatible with this version of YAMN."), TranslateT("YAMN (internal POP3) read error"), MB_OK);
+ CallService(MS_YAMN_DELETEFILENAME, (WPARAM)FileName, 0);
+ FileName = nullptr;
+ return 0;
+ case EACC_FILECOMPATIBILITY:
+ MessageBox(nullptr, TranslateT("Error reading account file. Account file corrupted."), TranslateT("YAMN (internal POP3) read error"), MB_OK);
+ CallService(MS_YAMN_DELETEFILENAME, (WPARAM)FileName, 0);
+ FileName = nullptr;
+ return 0;
+ case EACC_ALLOC:
+ MessageBox(nullptr, TranslateT("Memory allocation error while data reading"), TranslateT("YAMN (internal POP3) read error"), MB_OK);
+ CallService(MS_YAMN_DELETEFILENAME, (WPARAM)FileName, 0);
+ FileName = nullptr;
+ return 0;
+ case EACC_SYSTEM:
+ if (ERROR_FILE_NOT_FOUND != GetLastError()) {
+ wchar_t temp[1024] = {0};
+ mir_snwprintf(temp, L"%s\n%s", TranslateT("Reading file error. File already in use?"), FileName);
+ MessageBox(nullptr, temp, TranslateT("YAMN (internal POP3) read error"), MB_OK);
+ CallService(MS_YAMN_DELETEFILENAME, (WPARAM)FileName, 0);
+ FileName = nullptr;
+ return 0;
+ }
+ break;
+ }
+
+ for (CAccount *Finder = POP3Plugin->FirstAccount; Finder != nullptr; Finder = Finder->Next) {
+ Finder->hContact = NULL;
+ for (auto &hContact : Contacts(YAMN_DBMODULE)) {
+ DBVARIANT dbv;
+ if (!g_plugin.getString(hContact, "Id", &dbv)) {
+ if (mir_strcmp(dbv.pszVal, Finder->Name) == 0) {
+ Finder->hContact = hContact;
+ g_plugin.setWord(Finder->hContact, "Status", ID_STATUS_ONLINE);
+ db_set_s(Finder->hContact, "CList", "StatusMsg", Translate("No new mail message"));
+ if ((Finder->Flags & YAMN_ACC_ENA) && (Finder->NewMailN.Flags & YAMN_ACC_CONT))
+ Contact::Hide(Finder->hContact, false);
+
+ if (!(Finder->Flags & YAMN_ACC_ENA) || !(Finder->NewMailN.Flags & YAMN_ACC_CONT))
+ Contact::Hide(Finder->hContact);
+ }
+ db_free(&dbv);
+ }
+ }
+
+ if (!Finder->hContact && (Finder->Flags & YAMN_ACC_ENA) && (Finder->NewMailN.Flags & YAMN_ACC_CONT)) {
+ // No account contact found, have to create one
+ Finder->hContact = db_add_contact();
+ Proto_AddToContact(Finder->hContact, YAMN_DBMODULE);
+ g_plugin.setString(Finder->hContact, "Id", Finder->Name);
+ g_plugin.setString(Finder->hContact, "Nick", Finder->Name);
+ g_plugin.setWord(Finder->hContact, "Status", ID_STATUS_OFFLINE);
+ }
+ }
+
+ return 0;
+}
+
+DWORD WINAPI UnLoadPOP3(void *)
+{
+ //pYAMNVar is only a pointr, no need delete or free
+ if (hNetLib) {
+ Netlib_CloseHandle(hNetLib); hNetLib = nullptr;
+ }
+ if (CPOP3Account::AccountWriterSO) {
+ delete CPOP3Account::AccountWriterSO; CPOP3Account::AccountWriterSO = nullptr;
+ }
+ if (pYAMNMailFcn) {
+ delete pYAMNMailFcn; pYAMNMailFcn = nullptr;
+ }
+ if (pYAMNFcn) {
+ delete pYAMNFcn; pYAMNFcn = nullptr;
+ }
+ if (FileName) {
+ CallService(MS_YAMN_DELETEFILENAME, (WPARAM)FileName, 0); FileName = nullptr;
+ }
+
+ return 1;
+}
+
+DWORD WINAPI WritePOP3Accounts()
+{
+ uint32_t ReturnValue = CallService(MS_YAMN_WRITEACCOUNTS, (WPARAM)POP3Plugin, (LPARAM)FileName);
+ if (ReturnValue == EACC_SYSTEM) {
+ wchar_t temp[1024] = {0};
+ mir_snwprintf(temp, L"%s\n%s", TranslateT("Error while copying data to disk occurred. Is file in use?"), FileName);
+ MessageBox(nullptr, temp, TranslateT("POP3 plugin - write file error"), MB_OK);
+ }
+
+ return ReturnValue;
+}
+
+DWORD WINAPI WritePOP3Options(HANDLE File, CAccount *Which)
+{
+ DWORD WrittenBytes;
+ uint32_t Ver = POP3_FILEVERSION;
+
+ if ((!WriteFile(File, (char *)&Ver, sizeof(uint32_t), &WrittenBytes, nullptr)) ||
+ (!WriteFile(File, (char *)&((HPOP3ACCOUNT)Which)->CP, sizeof(uint16_t), &WrittenBytes, nullptr)))
+ return EACC_SYSTEM;
+ return 0;
+}
+
+DWORD WINAPI ReadPOP3Options(CAccount *Which, char **Parser, char *End)
+{
+ uint32_t Ver;
+ #ifdef DEBUG_FILEREAD
+ wchar_t Debug[256];
+ #endif
+ Ver = *(uint32_t *)(*Parser);
+ (*Parser) += sizeof(uint32_t);
+ if (*Parser >= End)
+ return EACC_FILECOMPATIBILITY;
+ if (Ver != POP3_FILEVERSION)
+ return EACC_FILECOMPATIBILITY;
+
+ ((HPOP3ACCOUNT)Which)->CP = *(uint16_t *)(*Parser);
+ (*Parser) += sizeof(uint16_t);
+ if (*Parser >= End)
+ return EACC_FILECOMPATIBILITY;
+ #ifdef DEBUG_FILEREAD
+ mir_snwprintf(Debug, L"CodePage: %d, remaining %d chars", ((HPOP3ACCOUNT)Which)->CP, End - *Parser);
+ MessageBox(NULL, Debug, L"debug", MB_OK);
+ #endif
+ return 0;
+}
+
+HYAMNMAIL WINAPI CreatePOP3Mail(CAccount *Account, DWORD)
+{
+ HYAMNMAIL NewMail;
+ //First, we should check whether MAILDATA matches.
+ //But this is internal plugin, so YAMN's MAILDATA structure and our MAILDATA structure are
+ //the same, so we do not need to test version. Otherwise, if MAILDATA version does not match
+ //in your plugin, you should return NULL, like this:
+ // if (MailDataVersion != YAMN_MAILDATAVERSION) return NULL;
+
+ //Now it is needed to construct our POP3 account and return its handle
+ if (nullptr == (NewMail = new YAMNMAIL))
+ return nullptr;
+
+ if (nullptr == (NewMail->MailData = new CMailData())) {
+ delete NewMail;
+ return nullptr;
+ }
+ NewMail->MailData->CP = ((HPOP3ACCOUNT)Account)->CP;
+ return (HYAMNMAIL)NewMail;
+}
+
+static void SetContactStatus(CAccount *account, int status)
+{
+ if ((account->hContact) && (account->NewMailN.Flags & YAMN_ACC_CONT))
+ g_plugin.setWord(account->hContact, "Status", status);
+}
+
+static void PostErrorProc(HPOP3ACCOUNT ActualAccount, void *ParamToBadConnection, uint32_t POP3PluginParam, BOOL UseSSL)
+{
+ char *DataRX;
+
+ //We create new structure, that we pass to bad connection dialog procedure. This procedure next calls YAMN imported fuction
+ //from POP3 protocol to determine the description of error. We can describe error from our error code structure, because later,
+ //when YAMN calls our function, it passes us our error code. This is pointer to structure for POP3 protocol in fact.
+ PPOP3_ERRORCODE ErrorCode;
+
+ //We store status before we do Quit(), because quit can destroy our errorcode status
+ if (nullptr != (ErrorCode = new POP3_ERRORCODE)) {
+ ErrorCode->SSL = UseSSL;
+ ErrorCode->AppError = ActualAccount->SystemError;
+ ErrorCode->POP3Error = ActualAccount->Client.POP3Error;
+ ErrorCode->NetError = ActualAccount->Client.NetClient->NetworkError;
+ ErrorCode->SystemError = ActualAccount->Client.NetClient->SystemError;
+ }
+
+ if (POP3PluginParam == (uint32_t)NULL) //if it was normal YAMN call (force check or so on)
+ {
+ try {
+ DataRX = ActualAccount->Client.Quit();
+ if (DataRX != nullptr)
+ free(DataRX);
+ }
+ catch (...) {
+ }
+ //We always close connection if error occured
+ try {
+ ActualAccount->Client.NetClient->Disconnect();
+ }
+ catch (...) {
+ }
+
+ SetAccountStatus(ActualAccount, TranslateT("Disconnected"));
+
+ //If we cannot allocate memory, do nothing
+ if (ErrorCode == nullptr) {
+ SetEvent(ActualAccount->UseInternetFree);
+ return;
+ }
+ }
+ else // else it was called from POP3 plugin, probably error when deleting old mail (POP3 synchro calls POP3 delete)
+ if (ErrorCode == nullptr)
+ return;
+
+ if ((ActualAccount->BadConnectN.Flags & YAMN_ACC_MSG) || (ActualAccount->BadConnectN.Flags & YAMN_ACC_ICO) || (ActualAccount->BadConnectN.Flags & YAMN_ACC_POP))
+ RunBadConnection(ActualAccount, (UINT_PTR)ErrorCode, ParamToBadConnection);
+
+ if (POP3PluginParam == (uint32_t)NULL) //if it was normal YAMN call
+ SetEvent(ActualAccount->UseInternetFree);
+}
+
+//Checks POP3 account and synchronizes it
+DWORD WINAPI SynchroPOP3(struct CheckParam *WhichTemp)
+{
+ HPOP3ACCOUNT ActualAccount;
+ CPop3Client *MyClient;
+ HYAMNMAIL NewMails = nullptr, MsgQueuePtr = nullptr;
+ char *DataRX = nullptr, *Temp;
+ int mboxsize, msgs, i;
+ SYSTEMTIME now;
+ LPVOID YAMNParam;
+ uint32_t CheckFlags;
+ BOOL UsingInternet = FALSE;
+ struct
+ {
+ char *ServerName;
+ uint32_t ServerPort;
+ char *ServerLogin;
+ char *ServerPasswd;
+ uint32_t Flags;
+ uint32_t NFlags;
+ uint32_t NNFlags;
+ } ActualCopied;
+
+ //First, we should compare our version of CheckParam structure, but here it is not needed, because YAMN and internal plugin
+ //have the same version. But your plugin should do that in this way:
+ // if (((struct CheckParam *)WhichTemp)->Ver != YAMN_CHECKVERSION)
+ // {
+ // SetEvent(((struct CheckParam *)WhichTemp)->ThreadRunningEV); //don't forget to unblock YAMN
+ // return (uint32_t)-1; //ok, but we should return value.
+ // //When our plugin returns e.g. 0xFFFFFFFF (=-1, this is only our plugin value, YAMN does nothing with return value,
+ // //but only tests if it is nonzero. If yes, it calls GetErrorStringFcn. We know problem occured in YAMN incompatibility
+ // //and then we can in our GetErrorStringFcn e.g. return string "Uncompatible version of YAMN".
+ // }
+
+ ActualAccount = (HPOP3ACCOUNT)WhichTemp->AccountParam; //copy address of structure from calling thread to stack of this thread
+ YAMNParam = WhichTemp->BrowserParam;
+ CheckFlags = WhichTemp->Flags;
+
+ SCInc(ActualAccount->UsingThreads);
+ //Unblock YAMN, signal that we have copied all parameters from YAMN thread stack
+ if (INVALID_HANDLE_VALUE != WhichTemp->ThreadRunningEV)
+ SetEvent(WhichTemp->ThreadRunningEV);
+
+ if (WAIT_OBJECT_0 != WaitToRead(ActualAccount)) {
+ SCDec(ActualAccount->UsingThreads);
+ return 0;
+ }
+
+ MyClient = &ActualAccount->Client;
+ //Now, copy all needed information about account to local variables, so ActualAccount is not blocked in read mode during all connection process, which can last for several minutes.
+ ActualCopied.ServerName = _strdup(ActualAccount->Server->Name);
+ ActualCopied.ServerPort = ActualAccount->Server->Port;
+ ActualCopied.Flags = ActualAccount->Flags;
+ ActualCopied.ServerLogin = _strdup(ActualAccount->Server->Login);
+ ActualCopied.ServerPasswd = _strdup(ActualAccount->Server->Passwd);
+ ActualCopied.NFlags = ActualAccount->NewMailN.Flags;
+ ActualCopied.NNFlags = ActualAccount->NoNewMailN.Flags;
+
+ ReadDone(ActualAccount);
+ SCInc(ActualAccount->InternetQueries); //increment counter, that there is one more thread waiting for connection
+
+ WaitForSingleObject(ActualAccount->UseInternetFree, INFINITE); //wait until we can use connection
+ SCDec(ActualAccount->InternetQueries);
+
+ //OK, we enter the "use internet" section. But after we start communication, we can test if we did not enter the "use internet" section only for the reason,
+ //that previous thread release the internet section because this account has stop signal (we stop account and there are 2 threads: one communicating,
+ //the second one waiting for network access- the first one ends because we want to stop account, this one is released, but should be stopped as well).
+ if (!ActualAccount->AbleToWork) {
+ SetEvent(ActualAccount->UseInternetFree);
+ SCDec(ActualAccount->UsingThreads);
+ return 0;
+ }
+ UsingInternet = TRUE;
+
+ GetLocalTime(&now);
+ ActualAccount->SystemError = 0; //now we can use internet for this socket. First, clear errorcode.
+ try {
+ SetContactStatus(ActualAccount, ID_STATUS_OCCUPIED);
+
+ // if we are already connected, we have open session (another thread left us open session), so we don't need to login
+ // note that connected state without logging cannot occur, because if we close session, we always close socket too (we must close socket is the right word :))
+ if ((MyClient->NetClient == nullptr) || !MyClient->NetClient->Connected()) {
+ SetAccountStatus(ActualAccount, TranslateT("Connecting to server"));
+
+ DataRX = MyClient->Connect(ActualCopied.ServerName, ActualCopied.ServerPort, ActualCopied.Flags & YAMN_ACC_SSL23, ActualCopied.Flags & YAMN_ACC_NOTLS);
+ char *timestamp = nullptr;
+
+ if (DataRX != nullptr) {
+ if (ActualCopied.Flags & YAMN_ACC_APOP) {
+ char *lpos = strchr(DataRX, '<');
+ char *rpos = strchr(DataRX, '>');
+ if (lpos && rpos && rpos > lpos) {
+ int sz = (int)(rpos - lpos + 2);
+ timestamp = new char[sz];
+ memcpy(timestamp, lpos, sz - 1);
+ timestamp[sz - 1] = '\0';
+ }
+ }
+ free(DataRX);
+ DataRX = nullptr;
+ }
+
+ SetAccountStatus(ActualAccount, TranslateT("Entering POP3 account"));
+
+ if (ActualCopied.Flags & YAMN_ACC_APOP) {
+ DataRX = MyClient->APOP(ActualCopied.ServerLogin, ActualCopied.ServerPasswd, timestamp);
+ if (DataRX != nullptr)
+ free(DataRX);
+ DataRX = nullptr;
+ delete[] timestamp;
+ }
+ else {
+ DataRX = MyClient->User(ActualCopied.ServerLogin);
+ if (DataRX != nullptr)
+ free(DataRX);
+ DataRX = nullptr;
+ DataRX = MyClient->Pass(ActualCopied.ServerPasswd);
+ if (DataRX != nullptr)
+ free(DataRX);
+ DataRX = nullptr;
+ }
+ }
+ SetAccountStatus(ActualAccount, TranslateT("Searching for new mail message"));
+
+ DataRX = MyClient->Stat();
+
+ ExtractStat(DataRX, &mboxsize, &msgs);
+
+ if (DataRX != nullptr)
+ free(DataRX);
+ DataRX = nullptr;
+ for (i = 0; i < msgs; i++) {
+ if (!i)
+ MsgQueuePtr = NewMails = (HYAMNMAIL)CallService(MS_YAMN_CREATEACCOUNTMAIL, (WPARAM)ActualAccount, (LPARAM)YAMN_MAILVERSION);
+ else {
+ MsgQueuePtr->Next = (HYAMNMAIL)CallService(MS_YAMN_CREATEACCOUNTMAIL, (WPARAM)ActualAccount, (LPARAM)YAMN_MAILVERSION);
+ MsgQueuePtr = MsgQueuePtr->Next;
+ }
+ if (MsgQueuePtr == nullptr) {
+ ActualAccount->SystemError = EPOP3_QUEUEALLOC;
+ throw (uint32_t)ActualAccount->SystemError;
+ }
+ }
+
+ if (msgs) {
+ DataRX = MyClient->List();
+ ExtractList(DataRX, MyClient->NetClient->Rcv, NewMails);
+ if (DataRX != nullptr)
+ free(DataRX);
+
+ DataRX = MyClient->Uidl();
+ ExtractUIDL(DataRX, MyClient->NetClient->Rcv, NewMails);
+
+ if (DataRX != nullptr)
+ free(DataRX);
+ DataRX = nullptr;
+ }
+
+ if (WAIT_OBJECT_0 != MsgsWaitToWrite(ActualAccount))
+ throw (uint32_t)(ActualAccount->SystemError = EACC_STOPPED);
+
+ ActualAccount->LastChecked = now;
+ for (MsgQueuePtr = (HYAMNMAIL)ActualAccount->Mails; MsgQueuePtr != nullptr; MsgQueuePtr = MsgQueuePtr->Next) {
+ if (MsgQueuePtr->Flags & YAMN_MSG_BODYREQUESTED) {
+ HYAMNMAIL NewMsgsPtr = nullptr;
+ for (NewMsgsPtr = (HYAMNMAIL)NewMails; NewMsgsPtr != nullptr; NewMsgsPtr = NewMsgsPtr->Next) {
+ if (!mir_strcmp(MsgQueuePtr->ID, NewMsgsPtr->ID)) {
+ wchar_t accstatus[512];
+ mir_snwprintf(accstatus, TranslateT("Reading body %s"), NewMsgsPtr->ID);
+ SetAccountStatus(ActualAccount, accstatus);
+ DataRX = MyClient->Top(MsgQueuePtr->Number, 100);
+ if (DataRX != nullptr) {
+ Temp = DataRX;
+ while ((Temp < DataRX + MyClient->NetClient->Rcv) && (WS(Temp) || ENDLINE(Temp))) Temp++;
+
+ if (OKLINE(DataRX))
+ for (Temp = DataRX; (Temp < DataRX + MyClient->NetClient->Rcv) && (!ENDLINE(Temp)); Temp++);
+ while ((Temp < DataRX + MyClient->NetClient->Rcv) && ENDLINE(Temp)) Temp++;
+ }
+ else
+ continue;
+ //delete all the headers of the old mail MsgQueuePtr->MailData->TranslatedHeader
+ struct CMimeItem *TH = MsgQueuePtr->MailData->TranslatedHeader;
+ if (TH) for (; MsgQueuePtr->MailData->TranslatedHeader != nullptr;) {
+ TH = TH->Next;
+ if (MsgQueuePtr->MailData->TranslatedHeader->name != nullptr)
+ delete[] MsgQueuePtr->MailData->TranslatedHeader->name;
+ if (MsgQueuePtr->MailData->TranslatedHeader->value != nullptr)
+ delete[] MsgQueuePtr->MailData->TranslatedHeader->value;
+ delete MsgQueuePtr->MailData->TranslatedHeader;
+ MsgQueuePtr->MailData->TranslatedHeader = TH;
+ }
+
+ TranslateHeader(Temp, MyClient->NetClient->Rcv - (Temp - DataRX), &MsgQueuePtr->MailData->TranslatedHeader);
+
+ MsgQueuePtr->Flags |= YAMN_MSG_BODYRECEIVED;
+
+ if (DataRX != nullptr)
+ free(DataRX);
+ DataRX = nullptr;
+ break;
+ }
+ }
+ }
+ }
+
+ SynchroMessages(ActualAccount, (HYAMNMAIL *)&ActualAccount->Mails, nullptr, (HYAMNMAIL *)&NewMails, nullptr); //we get only new mails on server!
+
+ MsgsWriteDone(ActualAccount);
+ for (MsgQueuePtr = (HYAMNMAIL)ActualAccount->Mails; MsgQueuePtr != nullptr; MsgQueuePtr = MsgQueuePtr->Next) {
+ if ((MsgQueuePtr->Flags & YAMN_MSG_BODYREQUESTED) && (MsgQueuePtr->Flags & YAMN_MSG_BODYRECEIVED)) {
+ MsgQueuePtr->Flags &= ~YAMN_MSG_BODYREQUESTED;
+ if (MsgQueuePtr->MsgWindow)
+ SendMessage(MsgQueuePtr->MsgWindow, WM_YAMN_CHANGECONTENT, 0, 0);
+ }
+ }
+
+ for (msgs = 0, MsgQueuePtr = NewMails; MsgQueuePtr != nullptr; MsgQueuePtr = MsgQueuePtr->Next, msgs++); //get number of new mails
+
+ try {
+ wchar_t accstatus[512];
+
+ for (i = 0, MsgQueuePtr = NewMails; MsgQueuePtr != nullptr; i++) {
+ BOOL autoretr = (ActualAccount->Flags & YAMN_ACC_BODY) != 0;
+ DataRX = MyClient->Top(MsgQueuePtr->Number, autoretr ? 100 : 0);
+ mir_snwprintf(accstatus, TranslateT("Reading new mail messages (%d%% done)"), 100 * i / msgs);
+ SetAccountStatus(ActualAccount, accstatus);
+
+ if (DataRX != nullptr) {
+ Temp = DataRX;
+ while ((Temp < DataRX + MyClient->NetClient->Rcv) && (WS(Temp) || ENDLINE(Temp))) Temp++;
+
+ if (OKLINE(DataRX))
+ for (Temp = DataRX; (Temp < DataRX + MyClient->NetClient->Rcv) && (!ENDLINE(Temp)); Temp++);
+ while ((Temp < DataRX + MyClient->NetClient->Rcv) && ENDLINE(Temp)) Temp++;
+ }
+ else
+ continue;
+
+ TranslateHeader(Temp, MyClient->NetClient->Rcv - (Temp - DataRX), &MsgQueuePtr->MailData->TranslatedHeader);
+
+
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "</New mail>\n");
+ #endif
+ MsgQueuePtr->Flags |= YAMN_MSG_NORMALNEW;
+ if (autoretr) MsgQueuePtr->Flags |= YAMN_MSG_BODYRECEIVED;
+
+ //We are going to filter mail. Warning!- we must not be in read access neither write access to mails when calling this service
+ //This is done, because the "NewMails" queue is not synchronised. It is because it is new queue. Only this thread uses new queue yet, it is not
+ //connected to account mail queue.
+ // CallService(MS_YAMN_FILTERMAIL,(WPARAM)ActualAccount,(LPARAM)MsgQueuePtr);
+ FilterMailSvc((WPARAM)ActualAccount, (LPARAM)MsgQueuePtr);
+
+ if (DataRX != nullptr)
+ free(DataRX);
+ DataRX = nullptr;
+
+ //MsgQueuePtr->MailData->Body=MyClient->Retr(MsgQueuePtr->Number);
+
+ MsgQueuePtr = MsgQueuePtr->Next;
+
+ }
+
+ if (WAIT_OBJECT_0 != MsgsWaitToWrite(ActualAccount))
+ throw (uint32_t)ActualAccount->SystemError == EACC_STOPPED;
+
+ if (ActualAccount->Mails == nullptr)
+ ActualAccount->Mails = NewMails;
+ else {
+ ActualAccount->LastMail = ActualAccount->LastChecked;
+ AppendQueue((HYAMNMAIL)ActualAccount->Mails, NewMails);
+ }
+
+ MsgsWriteDone(ActualAccount);
+
+ // we are going to delete mails having SPAM flag level3 and 4 (see m_mails.h) set
+ {
+ struct DeleteParam ParamToDeleteMails = {YAMN_DELETEVERSION, INVALID_HANDLE_VALUE, ActualAccount, YAMNParam, (void *)POP3_DELETEFROMCHECK};
+
+ // Delete mails from server. Here we should not be in write access for account's mails
+ DeleteMailsPOP3(&ParamToDeleteMails);
+ }
+
+ // if there is no waiting thread for internet connection close it
+ // else leave connection open
+ if (0 == SCGetNumber(ActualAccount->InternetQueries)) {
+ DataRX = MyClient->Quit();
+ if (DataRX != nullptr)
+ free(DataRX);
+ DataRX = nullptr;
+ MyClient->NetClient->Disconnect();
+
+ SetAccountStatus(ActualAccount, TranslateT("Disconnected"));
+ }
+
+ UsingInternet = FALSE;
+ SetEvent(ActualAccount->UseInternetFree);
+
+ ActualAccount->LastSChecked = ActualAccount->LastChecked;
+ ActualAccount->LastSynchronised = ActualAccount->LastChecked;
+ }
+ catch (...) {
+ throw; //go to the main exception handling
+ }
+
+ {
+ YAMN_MAILBROWSERPARAM Param = {(HANDLE)nullptr, ActualAccount, ActualCopied.NFlags, ActualCopied.NNFlags, YAMNParam};
+
+ if (CheckFlags & YAMN_FORCECHECK)
+ Param.nnflags |= YAMN_ACC_POP; //if force check, show popup anyway and if mailbrowser was opened, do not close
+ Param.nnflags |= YAMN_ACC_MSGP; //do not close browser if already open
+ CallService(MS_YAMN_MAILBROWSER, (WPARAM)&Param, (LPARAM)YAMN_MAILBROWSERVERSION);
+ }
+ SetContactStatus(ActualAccount, ActualAccount->isCounting ? ID_STATUS_ONLINE : ID_STATUS_OFFLINE);
+ }
+ #ifdef DEBUG_COMM
+ catch (uint32_t ErrorCode)
+ #else
+ catch (uint32_t)
+ #endif
+ {
+ if (ActualAccount->Client.POP3Error == EPOP3_STOPPED)
+ ActualAccount->SystemError = EACC_STOPPED;
+ #ifdef DEBUG_COMM
+ DebugLog(CommFile, "ERROR: %x\n", ErrorCode);
+ #endif
+ if (WAIT_OBJECT_0 == MsgsWaitToWrite(ActualAccount)) {
+ ActualAccount->LastChecked = now;
+ MsgsWriteDone(ActualAccount);
+ }
+
+ DeleteMIMEQueue(ActualAccount, NewMails);
+
+ if (DataRX != nullptr)
+ free(DataRX);
+ DataRX = nullptr;
+ switch (ActualAccount->SystemError) {
+ case EACC_QUEUEALLOC:
+ case EACC_STOPPED:
+ ActualAccount->Client.NetClient->Disconnect();
+ break;
+ default:
+ PostErrorProc(ActualAccount, YAMNParam, (uint32_t)NULL, MyClient->SSL); //it closes internet connection too
+ }
+
+ if (UsingInternet) //if our thread still uses internet
+ SetEvent(ActualAccount->UseInternetFree);
+
+ SetContactStatus(ActualAccount, ID_STATUS_NA);
+ }
+ free(ActualCopied.ServerName);
+ free(ActualCopied.ServerLogin);
+ free(ActualCopied.ServerPasswd);
+ #ifdef DEBUG_COMM
+ DebugLog(CommFile, "</--------Communication-------->\n");
+ #endif
+
+ // WriteAccounts();
+ SCDec(ActualAccount->UsingThreads);
+ return 0;
+}
+
+void __cdecl DeleteMailsPOP3(void *param)
+{
+ DeleteParam *WhichTemp = (DeleteParam *)param;
+
+ CPop3Client *MyClient;
+ HYAMNMAIL DeleteMails, NewMails = nullptr, MsgQueuePtr = nullptr;
+ char *DataRX = nullptr;
+ int mboxsize = 0, msgs = 0, i;
+ BOOL UsingInternet = FALSE;
+ struct
+ {
+ char *ServerName;
+ uint32_t ServerPort;
+ char *ServerLogin;
+ char *ServerPasswd;
+ uint32_t Flags;
+ uint32_t NFlags;
+ uint32_t NNFlags;
+ } ActualCopied;
+
+ //First, we should compare our version of DeleteParam structure, but here it is not needed, because YAMN and internal plugin
+ //have the same version. But your plugin should do that in this way:
+ // if (((struct DeleteParam *)WhichTemp)->Ver != YAMN_DELETEVERSION)
+ // {
+ // SetEvent(((struct DeleteParam *)WhichTemp)->ThreadRunningEV); //don't forget to unblock YAMN
+ // return (uint32_t)-1; //ok, but we should return value.
+ // //When our plugin returns e.g. 0xFFFFFFFF (this is only our plugin value, YAMN does nothing with return value,
+ // //but only tests if it is nonzero. If yes, it calls GetErrorStringFcn), we know problem occured in YAMN incompatibility
+ // //and then we can in our GetErrorStringFcn e.g. return string "Uncompatible version of YAMN".
+ // }
+
+ HPOP3ACCOUNT ActualAccount = (HPOP3ACCOUNT)WhichTemp->AccountParam; //copy address of structure from calling thread to stack of this thread
+ LPVOID YAMNParam = WhichTemp->BrowserParam;
+ UINT_PTR POP3PluginParam = (UINT_PTR)((struct DeleteParam *)WhichTemp)->CustomParam;
+
+ SCInc(ActualAccount->UsingThreads);
+ if (INVALID_HANDLE_VALUE != WhichTemp->ThreadRunningEV)
+ SetEvent(WhichTemp->ThreadRunningEV);
+
+ if (WAIT_OBJECT_0 != WaitToRead(ActualAccount)) {
+ SCDec(ActualAccount->UsingThreads);
+ return;
+ }
+
+ if (nullptr == (DeleteMails = (HYAMNMAIL)CreateNewDeleteQueue((HYAMNMAIL)ActualAccount->Mails))) //if there's no mail for deleting, return
+ {
+ if (POP3_DELETEFROMCHECK != POP3PluginParam) //We do not wait for free internet when calling from SynchroPOP3. It is because UseInternetFree is blocked
+ {
+ YAMN_MAILBROWSERPARAM Param = {(HANDLE)nullptr, ActualAccount, YAMN_ACC_MSGP, YAMN_ACC_MSGP, YAMNParam}; //Just update the window
+ CallService(MS_YAMN_MAILBROWSER, (WPARAM)&Param, (LPARAM)YAMN_MAILBROWSERVERSION);
+ }
+
+ SCDec(ActualAccount->UsingThreads);
+ return;
+ }
+
+ MyClient = &(ActualAccount->Client);
+
+ //Now, copy all needed information about account to local variables, so ActualAccount is not blocked in read mode during all connection process, which can last for several minutes.
+ ActualCopied.ServerName = _strdup(ActualAccount->Server->Name);
+ ActualCopied.ServerPort = ActualAccount->Server->Port;
+ ActualCopied.Flags = ActualAccount->Flags;
+ ActualCopied.ServerLogin = _strdup(ActualAccount->Server->Login);
+ ActualCopied.ServerPasswd = _strdup(ActualAccount->Server->Passwd);
+ ActualCopied.NFlags = ActualAccount->NewMailN.Flags;
+ ActualCopied.NNFlags = ActualAccount->NoNewMailN.Flags;
+
+ ReadDone(ActualAccount);
+
+ SCInc(ActualAccount->InternetQueries); //This is POP3-internal SCOUNTER, we set another thread wait for this account to be connected to inet
+ if (POP3_DELETEFROMCHECK != POP3PluginParam) //We do not wait for free internet when calling from SynchroPOP3. It is because UseInternetFree is blocked
+ WaitForSingleObject(ActualAccount->UseInternetFree, INFINITE);
+
+ SCDec(ActualAccount->InternetQueries);
+ UsingInternet = TRUE;
+
+ try {
+ SetContactStatus(ActualAccount, ID_STATUS_OCCUPIED);
+ #ifdef DEBUG_COMM
+ DebugLog(CommFile, "<--------Communication-------->\n");
+ #endif
+ if ((MyClient->NetClient == nullptr) || !MyClient->NetClient->Connected()) {
+ SetAccountStatus(ActualAccount, TranslateT("Connecting to server"));
+
+ DataRX = MyClient->Connect(ActualCopied.ServerName, ActualCopied.ServerPort, ActualCopied.Flags & YAMN_ACC_SSL23, ActualCopied.Flags & YAMN_ACC_NOTLS);
+
+ char *timestamp = nullptr;
+ if (DataRX != nullptr) {
+ if (ActualAccount->Flags & YAMN_ACC_APOP) {
+ char *lpos = strchr(DataRX, '<');
+ char *rpos = strchr(DataRX, '>');
+ if (lpos && rpos && rpos > lpos) {
+ int sz = (int)(rpos - lpos + 2);
+ timestamp = new char[sz];
+ memcpy(timestamp, lpos, sz - 1);
+ timestamp[sz - 1] = '\0';
+ }
+ }
+ free(DataRX);
+ DataRX = nullptr;
+ }
+ SetAccountStatus(ActualAccount, TranslateT("Entering POP3 account"));
+
+ if (ActualAccount->Flags & YAMN_ACC_APOP) {
+ DataRX = MyClient->APOP(ActualCopied.ServerLogin, ActualCopied.ServerPasswd, timestamp);
+ if (DataRX != nullptr)
+ free(DataRX);
+ DataRX = nullptr;
+ delete[] timestamp;
+ }
+ else {
+ DataRX = MyClient->User(ActualCopied.ServerLogin);
+ if (DataRX != nullptr)
+ free(DataRX);
+ DataRX = nullptr;
+ DataRX = MyClient->Pass(ActualCopied.ServerPasswd);
+ if (DataRX != nullptr)
+ free(DataRX);
+ DataRX = nullptr;
+ }
+ }
+
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<--------Deleting requested mails-------->\n");
+ #endif
+ if (POP3_DELETEFROMCHECK != POP3PluginParam) //We do not need to get mails on server as we have already it from check function
+ {
+ SetAccountStatus(ActualAccount, TranslateT("Deleting requested mails"));
+
+ DataRX = MyClient->Stat();
+
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<Extracting stat>\n");
+ #endif
+ ExtractStat(DataRX, &mboxsize, &msgs);
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<MailBoxSize>%d</MailBoxSize>\n", mboxsize);
+ DebugLog(DecodeFile, "<Msgs>%d</Msgs>\n", msgs);
+ DebugLog(DecodeFile, "</Extracting stat>\n");
+ #endif
+ if (DataRX != nullptr)
+ free(DataRX);
+ DataRX = nullptr;
+ for (i = 0; i < msgs; i++) {
+ if (!i)
+ MsgQueuePtr = NewMails = (HYAMNMAIL)CallService(MS_YAMN_CREATEACCOUNTMAIL, (WPARAM)ActualAccount, (LPARAM)YAMN_MAILVERSION);
+ else {
+ MsgQueuePtr->Next = (HYAMNMAIL)CallService(MS_YAMN_CREATEACCOUNTMAIL, (WPARAM)ActualAccount, (LPARAM)YAMN_MAILVERSION);
+ MsgQueuePtr = MsgQueuePtr->Next;
+ }
+ if (MsgQueuePtr == nullptr) {
+ ActualAccount->SystemError = EPOP3_QUEUEALLOC;
+ throw (uint32_t)ActualAccount->SystemError;
+ }
+ }
+
+ if (msgs) {
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<Extracting UIDL>\n");
+ #endif
+ DataRX = MyClient->Uidl();
+ ExtractUIDL(DataRX, MyClient->NetClient->Rcv, NewMails);
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "</Extracting UIDL>\n");
+ #endif
+ if (DataRX != nullptr)
+ free(DataRX);
+ DataRX = nullptr;
+ // we get "new mails" on server (NewMails will contain all mails on server not found in DeleteMails)
+ // but also in DeleteMails we get only those, which are still on server with their responsable numbers
+ SynchroMessages(ActualAccount, (HYAMNMAIL *)&DeleteMails, nullptr, (HYAMNMAIL *)&NewMails, nullptr);
+ }
+ }
+ else SetAccountStatus(ActualAccount, TranslateT("Deleting spam"));
+
+ if (WAIT_OBJECT_0 != MsgsWaitToWrite(ActualAccount))
+ throw (uint32_t)EACC_STOPPED;
+
+ if (msgs || POP3_DELETEFROMCHECK == POP3PluginParam) {
+ try {
+ HYAMNMAIL Temp;
+
+ for (i = 0, MsgQueuePtr = DeleteMails; MsgQueuePtr != nullptr; i++) {
+ if (!(MsgQueuePtr->Flags & YAMN_MSG_VIRTUAL)) //of course we can only delete real mails, not virtual
+ {
+ DataRX = MyClient->Dele(MsgQueuePtr->Number);
+ Temp = MsgQueuePtr->Next;
+ if (POP3_FOK == MyClient->AckFlag) //if server answers that mail was deleted
+ {
+ DeleteMIMEMessage((HYAMNMAIL *)&DeleteMails, MsgQueuePtr);
+ HYAMNMAIL DeletedMail = FindMIMEMessageByID((HYAMNMAIL)ActualAccount->Mails, MsgQueuePtr->ID);
+ if ((MsgQueuePtr->Flags & YAMN_MSG_MEMDELETE)) //if mail should be deleted from memory (or disk)
+ {
+ DeleteMIMEMessage((HYAMNMAIL *)&ActualAccount->Mails, DeletedMail); //remove from queue
+ CallService(MS_YAMN_DELETEACCOUNTMAIL, (WPARAM)POP3Plugin, (LPARAM)DeletedMail);
+ }
+ else //else mark it only as "deleted mail"
+ {
+ DeletedMail->Flags |= (YAMN_MSG_VIRTUAL | YAMN_MSG_DELETED);
+ DeletedMail->Flags &= ~(YAMN_MSG_NEW | YAMN_MSG_USERDELETE | YAMN_MSG_AUTODELETE); //clear "new mail"
+ }
+ delete MsgQueuePtr->MailData;
+ delete[] MsgQueuePtr->ID;
+ delete MsgQueuePtr;
+ }
+ MsgQueuePtr = Temp;
+
+ if (DataRX != nullptr)
+ free(DataRX);
+ DataRX = nullptr;
+ }
+ else
+ MsgQueuePtr = MsgQueuePtr->Next;
+ }
+ }
+ catch (...) //if any exception in the code where we have write-access to account occured, don't forget to leave write-access
+ {
+ MsgsWriteDone(ActualAccount);
+ throw; //and go to the main exception handling
+ }
+
+ if (NewMails != nullptr)
+ // in ActualAccount->Mails we have all mails stored before calling this function
+ // in NewMails we have all mails not found in DeleteMails (in other words: we performed new ID checking and we
+ // stored all mails found on server, then we deleted the ones we wanted to delete in this function
+ // and NewMails queue now contains actual state of mails on server). But we will not use NewMails as actual state, because NewMails does not contain header data (subject, from...)
+ // We perform deleting from ActualAccount->Mails: we remove from original queue (ActualAccount->Mails) all deleted mails
+ SynchroMessages(ActualAccount, (HYAMNMAIL *)&ActualAccount->Mails, nullptr, (HYAMNMAIL *)&NewMails, nullptr);
+ // Now ActualAccount->Mails contains all mails when calling this function except the ones, we wanted to delete (these are in DeleteMails)
+ // And in NewMails we have new mails (if any)
+ else if (POP3_DELETEFROMCHECK != POP3PluginParam) {
+ DeleteMIMEQueue(ActualAccount, (HYAMNMAIL)ActualAccount->Mails);
+ ActualAccount->Mails = nullptr;
+ }
+ }
+ else {
+ DeleteMIMEQueue(ActualAccount, (HYAMNMAIL)ActualAccount->Mails);
+ ActualAccount->Mails = nullptr;
+ }
+
+ MsgsWriteDone(ActualAccount);
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "</--------Deleting requested mails-------->\n");
+ #endif
+
+ // TODO: now, we have in NewMails new mails. If NewMails is not NULL, we found some new mails, so Checking for new mail should be performed
+ // now, we do not call CheckPOP3
+
+ // if there is no waiting thread for internet connection close it
+ // else leave connection open
+ // if this functin was called from SynchroPOP3, then do not try to disconnect
+ if (POP3_DELETEFROMCHECK != POP3PluginParam) {
+ YAMN_MAILBROWSERPARAM Param = {(HANDLE)nullptr, ActualAccount, ActualCopied.NFlags, YAMN_ACC_MSGP, YAMNParam};
+
+ CallService(MS_YAMN_MAILBROWSER, (WPARAM)&Param, (LPARAM)YAMN_MAILBROWSERVERSION);
+
+ if (0 == SCGetNumber(ActualAccount->InternetQueries)) {
+ DataRX = MyClient->Quit();
+ if (DataRX != nullptr)
+ free(DataRX);
+ DataRX = nullptr;
+ MyClient->NetClient->Disconnect();
+
+ SetAccountStatus(ActualAccount, TranslateT("Disconnected"));
+ }
+
+ UsingInternet = FALSE;
+ SetEvent(ActualAccount->UseInternetFree);
+ }
+ SetContactStatus(ActualAccount, ActualAccount->isCounting ? ID_STATUS_ONLINE : ID_STATUS_OFFLINE);
+ }
+ #ifdef DEBUG_COMM
+ catch (uint32_t ErrorCode)
+ #else
+ catch (uint32_t)
+ #endif
+ {
+ if (ActualAccount->Client.POP3Error == EPOP3_STOPPED)
+ ActualAccount->SystemError = EACC_STOPPED;
+ #ifdef DEBUG_COMM
+ DebugLog(CommFile, "ERROR %x\n", ErrorCode);
+ #endif
+ if (DataRX != nullptr)
+ free(DataRX);
+ switch (ActualAccount->SystemError) {
+ case EACC_QUEUEALLOC:
+ case EACC_STOPPED:
+ ActualAccount->Client.NetClient->Disconnect();
+ break;
+ default:
+ PostErrorProc(ActualAccount, YAMNParam, POP3PluginParam, MyClient->SSL); //it closes internet connection too
+ }
+
+ if (UsingInternet && (POP3_DELETEFROMCHECK != POP3PluginParam)) //if our thread still uses internet and it is needed to release internet
+ SetEvent(ActualAccount->UseInternetFree);
+ }
+
+ free(ActualCopied.ServerName);
+ free(ActualCopied.ServerLogin);
+ free(ActualCopied.ServerPasswd);
+
+ DeleteMIMEQueue(ActualAccount, NewMails);
+ DeleteMIMEQueue(ActualAccount, DeleteMails);
+
+ #ifdef DEBUG_COMM
+ DebugLog(CommFile, "</--------Communication-------->\n");
+ #endif
+
+ // WriteAccounts();
+ SCDec(ActualAccount->UsingThreads);
+ return;
+}
+
+void ExtractStat(char *stream, int *mboxsize, int *mails)
+{
+ char *finder = stream;
+ while (WS(finder) || ENDLINE(finder)) finder++;
+ if (ACKLINE(finder)) {
+ while (!WS(finder)) finder++;
+ while (WS(finder)) finder++;
+ }
+ if (1 != sscanf(finder, "%d", mails))
+ throw (uint32_t)EPOP3_STAT;
+ while (!WS(finder)) finder++;
+ while (WS(finder)) finder++;
+ if (1 != sscanf(finder, "%d", mboxsize))
+ throw (uint32_t)EPOP3_STAT;
+}
+void ExtractMail(char *stream, int len, HYAMNMAIL queue)
+{
+ char *finder = stream;
+ char *finderend;
+ int msgnr, i;
+ HYAMNMAIL queueptr = queue;
+
+ while (WS(finder) || ENDLINE(finder)) finder++;
+ while (!ACKLINE(finder)) finder++;
+ while (!ENDLINE(finder)) finder++; //now we at the end of first ack line
+ while (finder <= (stream + len)) {
+ while (ENDLINE(finder)) finder++; //go to the new line
+ if (DOTLINE(finder + 1)) //at the end of stream
+ break;
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<Message>\n");
+ #endif
+ while (WS(finder)) finder++; //jump whitespace
+ if (1 != sscanf(finder, "%d", &msgnr))
+ throw (uint32_t)EPOP3_UIDL;
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<Nr>%d</Nr>\n", msgnr);
+ #endif
+ // for (i=1,queueptr=queue;(queueptr->Next != NULL) && (i<msgnr);queueptr=queueptr->Next,i++);
+ // if (i != msgnr)
+ // throw (uint32_t)EPOP3_UIDL;
+ while (!WS(finder)) finder++; //jump characters
+ while (WS(finder)) finder++; //jump whitespace
+ finderend = finder + 1;
+ while (!WS(finderend) && !ENDLINE(finderend)) finderend++;
+ queueptr->ID = new char[finderend - finder + 1];
+ for (i = 0; finder != finderend; finder++, i++)
+ queueptr->MailData->Body[i] = *finder;
+ queueptr->MailData->Body[i] = 0; //ends string
+ queueptr->Number = msgnr;
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<ID>%s</ID>\n", queueptr->MailData->Body);
+ DebugLog(DecodeFile, "</Message>\n");
+ #endif
+ queueptr = queueptr->Next;
+ while (!ENDLINE(finder)) finder++;
+ }
+}
+
+void ExtractUIDL(char *stream, int len, HYAMNMAIL queue)
+{
+ char *finder = stream;
+ char *finderend;
+ int msgnr, i;
+ HYAMNMAIL queueptr = queue;
+
+ while (WS(finder) || ENDLINE(finder)) finder++;
+ while (!ACKLINE(finder)) finder++;
+ while (!ENDLINE(finder)) finder++; //now we at the end of first ack line
+ while (finder <= (stream + len)) {
+ while (ENDLINE(finder)) finder++; //go to the new line
+ if (DOTLINE(finder + 1)) //at the end of stream
+ break;
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<Message>\n");
+ #endif
+ while (WS(finder)) finder++; //jump whitespace
+ if (1 != sscanf(finder, "%d", &msgnr))
+ throw (uint32_t)EPOP3_UIDL;
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<Nr>%d</Nr>\n", msgnr);
+ #endif
+ // for (i=1,queueptr=queue;(queueptr->Next != NULL) && (i<msgnr);queueptr=queueptr->Next,i++);
+ // if (i != msgnr)
+ // throw (uint32_t)EPOP3_UIDL;
+ while (!WS(finder)) finder++; //jump characters
+ while (WS(finder)) finder++; //jump whitespace
+ finderend = finder + 1;
+ while (!WS(finderend) && !ENDLINE(finderend)) finderend++;
+ queueptr->ID = new char[finderend - finder + 1];
+ for (i = 0; finder != finderend; finder++, i++)
+ queueptr->ID[i] = *finder;
+ queueptr->ID[i] = 0; //ends string
+ queueptr->Number = msgnr;
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<ID>%s</ID>\n", queueptr->ID);
+ DebugLog(DecodeFile, "</Message>\n");
+ #endif
+ queueptr = queueptr->Next;
+ while (!ENDLINE(finder)) finder++;
+ }
+}
+
+void ExtractList(char *stream, int len, HYAMNMAIL queue)
+{
+ char *finder = stream;
+ char *finderend;
+ int msgnr, i;
+ HYAMNMAIL queueptr;
+
+ while (WS(finder) || ENDLINE(finder)) finder++;
+ while (!ACKLINE(finder)) finder++;
+ while (!ENDLINE(finder)) finder++; //now we at the end of first ack line
+ while (finder <= (stream + len)) {
+ while (ENDLINE(finder)) finder++; //go to the new line
+ if (DOTLINE(finder + 1)) //at the end of stream
+ break;
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<Message>\n", NULL, 0);
+ #endif
+ while (WS(finder)) finder++; //jump whitespace
+ if (1 != sscanf(finder, "%d", &msgnr)) //message nr.
+ throw (uint32_t)EPOP3_LIST;
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<Nr>%d</Nr>\n", msgnr);
+ #endif
+
+ for (i = 1, queueptr = queue; (queueptr->Next != nullptr) && (i < msgnr); queueptr = queueptr->Next, i++);
+ if (i != msgnr)
+ throw (uint32_t)EPOP3_LIST;
+ while (!WS(finder)) finder++; //jump characters
+ while (WS(finder)) finder++; //jump whitespace
+ finderend = finder + 1;
+ if (1 != sscanf(finder, "%u", &queueptr->MailData->Size))
+ throw (uint32_t)EPOP3_LIST;
+ #ifdef DEBUG_DECODE
+ DebugLog(DecodeFile, "<Nr>%d</Nr>\n", queueptr->MailData->Size);
+ #endif
+ while (!ENDLINE(finder)) finder++;
+ }
+}
+
+wchar_t *WINAPI GetErrorString(DWORD Code)
+{
+ static wchar_t *POP3Errors[] =
+ {
+ LPGENW("Memory allocation error."), //memory allocation
+ LPGENW("Account is about to be stopped."), //stop account
+ LPGENW("Cannot connect to POP3 server."),
+ LPGENW("Cannot allocate memory for received data."),
+ LPGENW("Cannot login to POP3 server."),
+ LPGENW("Bad user or password."),
+ LPGENW("Server does not support APOP authorization."),
+ LPGENW("Error while executing POP3 command."),
+ LPGENW("Error while executing POP3 command."),
+ LPGENW("Error while executing POP3 command."),
+ };
+
+ static wchar_t *NetlibErrors[] =
+ {
+ LPGENW("Cannot connect to server with NetLib."),
+ LPGENW("Cannot send data."),
+ LPGENW("Cannot receive data."),
+ LPGENW("Cannot allocate memory for received data."),
+ };
+
+ static wchar_t *SSLErrors[] =
+ {
+ LPGENW("OpenSSL not loaded."),
+ LPGENW("Windows socket 2.0 init failed."),
+ LPGENW("DNS lookup error."),
+ LPGENW("Error while creating base socket."),
+ LPGENW("Error connecting to server with socket."),
+ LPGENW("Error while creating SSL structure."),
+ LPGENW("Error connecting socket with SSL."),
+ LPGENW("Server rejected connection with SSL."),
+ LPGENW("Cannot write SSL data."),
+ LPGENW("Cannot read SSL data."),
+ LPGENW("Cannot allocate memory for received data."),
+ };
+
+ wchar_t *ErrorString = new wchar_t[ERRORSTR_MAXLEN];
+ POP3_ERRORCODE *ErrorCode = (POP3_ERRORCODE *)(UINT_PTR)Code;
+
+ mir_snwprintf(ErrorString, ERRORSTR_MAXLEN, TranslateT("Error %d-%d-%d-%d:"), ErrorCode->AppError, ErrorCode->POP3Error, ErrorCode->NetError, ErrorCode->SystemError);
+ if (ErrorCode->POP3Error)
+ mir_snwprintf(ErrorString, ERRORSTR_MAXLEN, L"%s\n%s", ErrorString, TranslateW(POP3Errors[ErrorCode->POP3Error - 1]));
+ if (ErrorCode->NetError) {
+ if (ErrorCode->SSL)
+ mir_snwprintf(ErrorString, ERRORSTR_MAXLEN, L"%s\n%s", ErrorString, TranslateW(SSLErrors[ErrorCode->NetError - 1]));
+ else
+ mir_snwprintf(ErrorString, ERRORSTR_MAXLEN, L"%s\n%s", ErrorString, TranslateW(NetlibErrors[ErrorCode->NetError - 4]));
+ }
+
+ return ErrorString;
+}
+
+void WINAPI DeleteErrorString(LPVOID String)
+{
+ delete (char *)String;
+}
diff --git a/protocols/YAMN/src/proto/pop3/pop3opt.cpp b/protocols/YAMN/src/proto/pop3/pop3opt.cpp
index 80764d85bb..a1dfa14199 100644
--- a/protocols/YAMN/src/proto/pop3/pop3opt.cpp
+++ b/protocols/YAMN/src/proto/pop3/pop3opt.cpp
@@ -1,1137 +1,1137 @@
-/*
- * This code implements POP3 options window handling
- *
- * (c) majvan 2002-2003
-*/
-
-#include "../../stdafx.h"
-
-//--------------------------------------------------------------------------------------------------
-
-static char DlgInput[MAX_PATH];
-
-static BOOL DlgSetItemText(HWND hDlg, WPARAM wParam, const char *str)
-{
- if (str == nullptr)
- SetDlgItemTextA(hDlg, wParam, "");
- else
- SetDlgItemTextA(hDlg, wParam, str);
- return TRUE;
-}
-
-static BOOL DlgSetItemTextW(HWND hDlg, WPARAM wParam, const wchar_t *str)
-{
- if (str == nullptr)
- SetDlgItemTextW(hDlg, wParam, L"");
- else
- SetDlgItemTextW(hDlg, wParam, str);
- return TRUE;
-}
-
-struct CBaseOptionsDlg : public CDlgBase
-{
- CBaseOptionsDlg(int iDlgId) :
- CDlgBase(g_plugin, iDlgId)
- {}
-
- void DlgShowAccount(HPOP3ACCOUNT pAccount)
- {
- int i;
-
- if (pAccount) {
- // we do not need to check if account is deleted. It is not deleted, because only thread that can delete account is this thread
- WaitToRead(pAccount);
-
- DlgSetItemText(m_hwnd, IDC_EDITSERVER, pAccount->Server->Name);
- DlgSetItemText(m_hwnd, IDC_EDITNAME, pAccount->Name);
- DlgSetItemText(m_hwnd, IDC_EDITLOGIN, pAccount->Server->Login);
- DlgSetItemText(m_hwnd, IDC_EDITPASS, pAccount->Server->Passwd);
- DlgSetItemTextW(m_hwnd, IDC_EDITAPP, pAccount->NewMailN.App);
- DlgSetItemTextW(m_hwnd, IDC_EDITAPPPARAM, pAccount->NewMailN.AppParam);
- SetDlgItemInt(m_hwnd, IDC_EDITPORT, pAccount->Server->Port, FALSE);
- SetDlgItemInt(m_hwnd, IDC_EDITINTERVAL, pAccount->Interval / 60, FALSE);
- SetDlgItemInt(m_hwnd, IDC_EDITPOPS, pAccount->NewMailN.PopupTime, FALSE);
- SetDlgItemInt(m_hwnd, IDC_EDITNPOPS, pAccount->NoNewMailN.PopupTime, FALSE);
- SetDlgItemInt(m_hwnd, IDC_EDITFPOPS, pAccount->BadConnectN.PopupTime, FALSE);
- for (i = 0; i <= CPLENSUPP; i++)
- if ((i < CPLENSUPP) && (CodePageNamesSupp[i].CP == pAccount->CP)) {
- SendDlgItemMessage(m_hwnd, IDC_COMBOCP, CB_SETCURSEL, (WPARAM)i, 0);
- break;
- }
-
- if (i == CPLENSUPP)
- SendDlgItemMessage(m_hwnd, IDC_COMBOCP, CB_SETCURSEL, (WPARAM)CPDEFINDEX, 0);
-
- CheckDlgButton(m_hwnd, IDC_CHECK, pAccount->Flags & YAMN_ACC_ENA ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKSND, pAccount->NewMailN.Flags & YAMN_ACC_SND ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKMSG, pAccount->NewMailN.Flags & YAMN_ACC_MSG ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKICO, pAccount->NewMailN.Flags & YAMN_ACC_ICO ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKPOP, pAccount->NewMailN.Flags & YAMN_ACC_POP ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKCOL, pAccount->NewMailN.Flags & YAMN_ACC_POPC ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKAPP, pAccount->NewMailN.Flags & YAMN_ACC_APP ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKKBN, pAccount->NewMailN.Flags & YAMN_ACC_KBN ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKNPOP, pAccount->NoNewMailN.Flags & YAMN_ACC_POP ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKNCOL, pAccount->NoNewMailN.Flags & YAMN_ACC_POPC ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKNMSGP, pAccount->NoNewMailN.Flags & YAMN_ACC_MSGP ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKFSND, pAccount->BadConnectN.Flags & YAMN_ACC_SND ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKFMSG, pAccount->BadConnectN.Flags & YAMN_ACC_MSG ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKFICO, pAccount->BadConnectN.Flags & YAMN_ACC_ICO ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKFPOP, pAccount->BadConnectN.Flags & YAMN_ACC_POP ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKFCOL, pAccount->BadConnectN.Flags & YAMN_ACC_POPC ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_RADIOPOPN, pAccount->Flags & YAMN_ACC_POPN ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_RADIOPOP1, pAccount->Flags & YAMN_ACC_POPN ? BST_UNCHECKED : BST_CHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKSSL, pAccount->Flags & YAMN_ACC_SSL23 ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKNOTLS, pAccount->Flags & YAMN_ACC_NOTLS ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKAPOP, pAccount->Flags & YAMN_ACC_APOP ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_AUTOBODY, pAccount->Flags & YAMN_ACC_BODY ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKSTART, pAccount->StatusFlags & YAMN_ACC_STARTS ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKFORCE, pAccount->StatusFlags & YAMN_ACC_FORCE ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKCONTACT, pAccount->NewMailN.Flags & YAMN_ACC_CONT ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKCONTACTNICK, pAccount->NewMailN.Flags & YAMN_ACC_CONTNICK ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKCONTACTNOEVENT, pAccount->NewMailN.Flags & YAMN_ACC_CONTNOEVENT ? BST_CHECKED : BST_UNCHECKED);
-
- wchar_t accstatus[256];
- GetAccountStatus(pAccount, accstatus);
- SetDlgItemText(m_hwnd, IDC_STSTATUS, accstatus);
- ReadDone(pAccount);
- }
- else {
- DlgSetItemText(m_hwnd, IDC_EDITSERVER, nullptr);
- DlgSetItemText(m_hwnd, IDC_EDITNAME, nullptr);
- DlgSetItemText(m_hwnd, IDC_EDITLOGIN, nullptr);
- DlgSetItemText(m_hwnd, IDC_EDITPASS, nullptr);
- DlgSetItemText(m_hwnd, IDC_EDITAPP, nullptr);
- DlgSetItemText(m_hwnd, IDC_EDITAPPPARAM, nullptr);
- DlgSetItemText(m_hwnd, IDC_STTIMELEFT, nullptr);
- SetDlgItemInt(m_hwnd, IDC_EDITPORT, 110, FALSE);
- SetDlgItemInt(m_hwnd, IDC_EDITINTERVAL, 30, FALSE);
- SetDlgItemInt(m_hwnd, IDC_EDITPOPS, 0, FALSE);
- SetDlgItemInt(m_hwnd, IDC_EDITNPOPS, 0, FALSE);
- SetDlgItemInt(m_hwnd, IDC_EDITFPOPS, 0, FALSE);
- SendDlgItemMessage(m_hwnd, IDC_COMBOCP, CB_SETCURSEL, (WPARAM)CPDEFINDEX, 0);
- CheckDlgButton(m_hwnd, IDC_CHECK, BST_CHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKSND, BST_CHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKMSG, BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKICO, BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKPOP, BST_CHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKCOL, BST_CHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKAPP, BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKFSND, BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKFMSG, BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKFICO, BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKFPOP, BST_CHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKFCOL, BST_CHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKSTART, BST_CHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKFORCE, BST_CHECKED);
- CheckDlgButton(m_hwnd, IDC_RADIOPOPN, BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_RADIOPOP1, BST_CHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKSSL, BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKNOTLS, BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKAPOP, BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_AUTOBODY, BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CHECKCONTACT, BST_CHECKED);
-
- SetDlgItemText(m_hwnd, IDC_STSTATUS, TranslateT("No account selected"));
- }
- }
-};
-
-//=======================================================================================
-// General options dialog
-
-struct CGeneralOptDlg : public CBaseOptionsDlg
-{
- CGeneralOptDlg() :
- CBaseOptionsDlg(IDD_YAMNOPT)
- {}
-
- bool OnInitDialog() override
- {
- CheckDlgButton(m_hwnd, IDC_CHECKTTB, g_plugin.getByte(YAMN_TTBFCHECK, 1) ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_LONGDATE, (optDateTime & SHOWDATELONG) ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_SMARTDATE, (optDateTime & SHOWDATENOTODAY) ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_NOSECONDS, (optDateTime & SHOWDATENOSECONDS) ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_CLOSEONDELETE, g_plugin.getByte(YAMN_CLOSEDELETE, 0) ? BST_CHECKED : BST_UNCHECKED);
- return true;
- }
-
- bool OnApply() override
- {
- g_plugin.setByte(YAMN_CLOSEDELETE, IsDlgButtonChecked(m_hwnd, IDC_CLOSEONDELETE));
- g_plugin.setByte(YAMN_TTBFCHECK, IsDlgButtonChecked(m_hwnd, IDC_CHECKTTB));
-
- AddTopToolbarIcon(0, 0);
-
- optDateTime = 0;
- if (IsDlgButtonChecked(m_hwnd, IDC_LONGDATE)) optDateTime |= SHOWDATELONG;
- if (IsDlgButtonChecked(m_hwnd, IDC_SMARTDATE)) optDateTime |= SHOWDATENOTODAY;
- if (IsDlgButtonChecked(m_hwnd, IDC_NOSECONDS)) optDateTime |= SHOWDATENOSECONDS;
- g_plugin.setByte(YAMN_DBTIMEOPTIONS, optDateTime);
- return true;
- }
-};
-
-//--------------------------------------------------------------------------------------------------
-
-static int g_iStatusControls[] = {IDC_CHECKST0, IDC_CHECKST1, IDC_CHECKST2, IDC_CHECKST3, IDC_CHECKST4, IDC_CHECKST5, IDC_CHECKST6, IDC_CHECKST7};
-
-static BOOL DlgShowAccountStatus(HWND hDlg, HPOP3ACCOUNT ActualAccount)
-{
- if (ActualAccount) {
- WaitToRead(ActualAccount); //we do not need to check if account is deleted. It is not deleted, because only thread that can delete account is this thread
-
- CheckDlgButton(hDlg, IDC_CHECKST0, ActualAccount->StatusFlags & YAMN_ACC_ST0 ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hDlg, IDC_CHECKST1, ActualAccount->StatusFlags & YAMN_ACC_ST1 ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hDlg, IDC_CHECKST2, ActualAccount->StatusFlags & YAMN_ACC_ST2 ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hDlg, IDC_CHECKST3, ActualAccount->StatusFlags & YAMN_ACC_ST3 ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hDlg, IDC_CHECKST4, ActualAccount->StatusFlags & YAMN_ACC_ST4 ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hDlg, IDC_CHECKST5, ActualAccount->StatusFlags & YAMN_ACC_ST5 ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hDlg, IDC_CHECKST6, ActualAccount->StatusFlags & YAMN_ACC_ST6 ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hDlg, IDC_CHECKST7, ActualAccount->StatusFlags & YAMN_ACC_ST7 ? BST_CHECKED : BST_UNCHECKED);
-
- ReadDone(ActualAccount);
- }
- else {
- CheckDlgButton(hDlg, IDC_CHECKST0, BST_UNCHECKED);
- CheckDlgButton(hDlg, IDC_CHECKST1, BST_CHECKED);
- CheckDlgButton(hDlg, IDC_CHECKST2, BST_UNCHECKED);
- CheckDlgButton(hDlg, IDC_CHECKST3, BST_UNCHECKED);
- CheckDlgButton(hDlg, IDC_CHECKST4, BST_UNCHECKED);
- CheckDlgButton(hDlg, IDC_CHECKST5, BST_UNCHECKED);
- CheckDlgButton(hDlg, IDC_CHECKST6, BST_UNCHECKED);
- CheckDlgButton(hDlg, IDC_CHECKST7, BST_CHECKED);
- }
- return TRUE;
-}
-
-static INT_PTR CALLBACK DlgProcPOP3AccStatusOpt(HWND hDlg, UINT msg, WPARAM wParam, LPARAM)
-{
- static HPOP3ACCOUNT ActualAccount;
- switch (msg) {
- case WM_INITDIALOG:
- ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)DlgInput);
- if (ActualAccount != nullptr) {
- DlgShowAccountStatus(hDlg, ActualAccount);
- for (auto &it : g_iStatusControls)
- EnableWindow(GetDlgItem(hDlg, it), true);
- }
- else {
- for (auto &it : g_iStatusControls)
- CheckDlgButton(hDlg, it, BST_CHECKED);
- }
- TranslateDialogDefault(hDlg);
- SendMessage(GetParent(hDlg), PSM_UNCHANGED, (WPARAM)hDlg, 0);
- return TRUE;
-
- case WM_COMMAND:
- switch (LOWORD(wParam)) {
- case IDCANCEL:
- EndDialog(hDlg, 0);
- DestroyWindow(hDlg);
- break;
-
- case IDOK:
- int iShift = 1;
- ActualAccount->StatusFlags = 0;
- for (auto &it : g_iStatusControls) {
- if (IsDlgButtonChecked(hDlg, it))
- ActualAccount->StatusFlags |= iShift;
- iShift <<= 1;
- }
-
- WindowList_BroadcastAsync(YAMNVar.MessageWnds, WM_YAMN_CHANGESTATUSOPTION, 0, 0);
- EndDialog(hDlg, 0);
- DestroyWindow(hDlg);
- break;
- }
- }
- return FALSE;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Account options
-
-class CAccOptDlg : public CBaseOptionsDlg
-{
- INT_PTR Result;
- UCHAR ActualStatus;
- HPOP3ACCOUNT ActualAccount = nullptr;
-
- CCtrlCheck chkContact, chkSsl, chkApp;
- CCtrlCombo cmbAccount, cmbCP;
- CCtrlButton btnStatus, btnAdd, btnDel, btnApp, btnDefault, btnReset;
-
- void DlgEnableAccount(bool bEnable)
- {
- cmbAccount.Enable(POP3Plugin->FirstAccount != nullptr);
-
- EnableWindow(GetDlgItem(m_hwnd, IDC_CHECK), bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_EDITSERVER), bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_EDITNAME), bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_EDITPORT), bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_EDITLOGIN), bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_EDITPASS), bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_EDITINTERVAL), bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKSND), bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKMSG), bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKICO), bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKAPP), bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKKBN), bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_BTNAPP), chkApp.IsChecked() && bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_EDITAPP), chkApp.IsChecked() && bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_EDITAPPPARAM), chkApp.IsChecked() && bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKNMSGP), bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKFSND), bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKFMSG), bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKFICO), bEnable);
-
- EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKSTART), bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKFORCE), bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_COMBOCP), bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_STTIMELEFT), bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_BTNRESET), bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_BTNDEFAULT), bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_BTNSTATUS), bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKSSL), bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKAPOP), bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKNOTLS), chkSsl.IsChecked() && bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_AUTOBODY), bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKCONTACT), bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKCONTACTNICK), chkContact.IsChecked() && bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKCONTACTNOEVENT), chkContact.IsChecked() && bEnable);
- }
-
-public:
- CAccOptDlg() :
- CBaseOptionsDlg(IDD_POP3ACCOUNTOPT),
- cmbCP(this, IDC_COMBOCP),
- btnAdd(this, IDC_BTNADD),
- btnApp(this, IDC_BTNAPP),
- btnDel(this, IDC_BTNDEL),
- chkApp(this, IDC_CHECKAPP),
- chkSsl(this, IDC_CHECKSSL),
- btnReset(this, IDC_BTNRESET),
- btnStatus(this, IDC_BTNSTATUS),
- btnDefault(this, IDC_BTNDEFAULT),
- cmbAccount(this, IDC_COMBOACCOUNT),
- chkContact(this, IDC_CHECKCONTACT)
- {
- cmbCP.OnSelChanged = Callback(this, &CAccOptDlg::onSelChange_CP);
-
- cmbAccount.OnChange = Callback(this, &CAccOptDlg::onChange_Account);
- cmbAccount.OnKillFocus = Callback(this, &CAccOptDlg::onKillFocus_Account);
- cmbAccount.OnSelChanged = Callback(this, &CAccOptDlg::onSelChange_Account);
-
- chkApp.OnChange = Callback(this, &CAccOptDlg::onChangeApp);
- chkSsl.OnChange = Callback(this, &CAccOptDlg::onChangeSsl);
- chkContact.OnChange = Callback(this, &CAccOptDlg::onChangeContact);
-
- btnAdd.OnClick = Callback(this, &CAccOptDlg::onClick_Add);
- btnDel.OnClick = Callback(this, &CAccOptDlg::onClick_Del);
- btnApp.OnClick = Callback(this, &CAccOptDlg::onClick_App);
- btnReset.OnClick = Callback(this, &CAccOptDlg::onClick_Reset);
- btnStatus.OnClick = Callback(this, &CAccOptDlg::onClick_Status);
- btnDefault.OnClick = Callback(this, &CAccOptDlg::onClick_Default);
- }
-
- bool OnInitDialog() override
- {
- EnableWindow(GetDlgItem(m_hwnd, IDC_BTNDEL), FALSE);
-
- DlgEnableAccount(false);
- DlgShowAccount(0);
-
- // Fill accounts
- WaitToReadSO(POP3Plugin->AccountBrowserSO);
-
- for (ActualAccount = (HPOP3ACCOUNT)POP3Plugin->FirstAccount; ActualAccount != nullptr; ActualAccount = (HPOP3ACCOUNT)ActualAccount->Next)
- if (ActualAccount->Name != nullptr)
- cmbAccount.AddStringA(ActualAccount->Name);
- cmbAccount.SetCurSel(0);
-
- ReadDoneSO(POP3Plugin->AccountBrowserSO);
-
- // Fill code pages
- cmbCP.AddString(TranslateT("Default"));
- for (int i = 1; i < CPLENSUPP; i++) {
- CPINFOEX info; GetCPInfoEx(CodePageNamesSupp[i].CP, 0, &info);
- size_t len = mir_wstrlen(info.CodePageName + 7);
- info.CodePageName[len + 6] = 0;
- cmbCP.AddString(info.CodePageName + 7);
- }
- cmbCP.SetCurSel(0);
-
- ActualAccount = nullptr;
- SendMessage(GetParent(m_hwnd), PSM_UNCHANGED, (WPARAM)m_hwnd, 0);
-
- WindowList_Add(pYAMNVar->MessageWnds, m_hwnd);
- return true;
- }
-
- void OnDestroy() override
- {
- WindowList_Remove(pYAMNVar->MessageWnds, m_hwnd);
- }
-
- INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) override
- {
- switch (msg) {
- case WM_YAMN_CHANGESTATUS:
- if ((HPOP3ACCOUNT)wParam == ActualAccount) {
- wchar_t accstatus[256];
- GetAccountStatus(ActualAccount, accstatus);
- SetDlgItemText(m_hwnd, IDC_STSTATUS, accstatus);
- return TRUE;
- }
- break;
-
- case WM_YAMN_CHANGESTATUSOPTION:
- NotifyChange();
- return TRUE;
-
- case WM_YAMN_CHANGETIME:
- if ((HPOP3ACCOUNT)wParam == ActualAccount) {
- wchar_t Text[256];
- mir_snwprintf(Text, TranslateT("Time left to next check [s]: %d"), (uint32_t)lParam);
- SetDlgItemText(m_hwnd, IDC_STTIMELEFT, Text);
- }
- return TRUE;
- }
- return CDlgBase::DlgProc(msg, wParam, lParam);
- }
-
- void onChange_Account(CCtrlCombo *)
- {
- ActualAccount = nullptr;
- DlgSetItemText(m_hwnd, (WPARAM)IDC_STTIMELEFT, nullptr);
- DlgEnableAccount(0 != GetDlgItemTextA(m_hwnd, IDC_COMBOACCOUNT, DlgInput, _countof(DlgInput)));
- }
-
- void onKillFocus_Account(CCtrlCombo *)
- {
- GetDlgItemTextA(m_hwnd, IDC_COMBOACCOUNT, DlgInput, _countof(DlgInput));
- if (nullptr == (ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)DlgInput))) {
- DlgSetItemText(m_hwnd, (WPARAM)IDC_STTIMELEFT, nullptr);
- EnableWindow(GetDlgItem(m_hwnd, IDC_BTNDEL), FALSE);
- DlgEnableAccount(mir_strlen(DlgInput) > 0);
- }
- else {
- DlgShowAccount(ActualAccount);
- DlgEnableAccount(true);
- EnableWindow(GetDlgItem(m_hwnd, IDC_BTNDEL), TRUE);
- }
- }
-
- void onSelChange_Account(CCtrlCombo *)
- {
- if (CB_ERR != (Result = cmbAccount.GetCurSel()))
- SendDlgItemMessageA(m_hwnd, IDC_COMBOACCOUNT, CB_GETLBTEXT, (WPARAM)Result, (LPARAM)DlgInput);
-
- if ((Result == CB_ERR) || (nullptr == (ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)DlgInput)))) {
- DlgSetItemText(m_hwnd, (WPARAM)IDC_STTIMELEFT, nullptr);
- EnableWindow(GetDlgItem(m_hwnd, IDC_BTNDEL), FALSE);
- }
- else {
- DlgShowAccount(ActualAccount);
- DlgEnableAccount(true);
- EnableWindow(GetDlgItem(m_hwnd, IDC_BTNDEL), TRUE);
- }
- }
-
- void onSelChange_CP(CCtrlCombo *)
- {
- int sel = cmbCP.GetCurSel();
- CPINFOEX info; GetCPInfoEx(CodePageNamesSupp[sel].CP, 0, &info);
- DlgSetItemTextW(m_hwnd, IDC_STSTATUS, info.CodePageName);
- }
-
- void onChangeContact(CCtrlCheck *)
- {
- bool bEnabled = chkContact.IsChecked();
- EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKCONTACTNICK), bEnabled);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKCONTACTNOEVENT), bEnabled);
- }
-
- void onChangeSsl(CCtrlCheck *)
- {
- bool bEnabled = chkSsl.IsChecked();
- SetDlgItemInt(m_hwnd, IDC_EDITPORT, bEnabled ? 995 : 110, FALSE);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKNOTLS), !bEnabled);
- }
-
- void onChangeApp(CCtrlCheck *)
- {
- bool bEnabled = chkApp.IsChecked();
- EnableWindow(GetDlgItem(m_hwnd, IDC_BTNAPP), bEnabled);
- EnableWindow(GetDlgItem(m_hwnd, IDC_EDITAPP), bEnabled);
- EnableWindow(GetDlgItem(m_hwnd, IDC_EDITAPPPARAM), bEnabled);
- }
-
- void onClick_Status(CCtrlButton *)
- {
- DialogBoxParamW(g_plugin.getInst(), MAKEINTRESOURCEW(IDD_CHOOSESTATUSMODES), m_hwnd, DlgProcPOP3AccStatusOpt, NULL);
- }
-
- void onClick_Add(CCtrlButton *)
- {
- DlgSetItemText(m_hwnd, (WPARAM)IDC_STTIMELEFT, nullptr);
- DlgShowAccount(0);
- DlgEnableAccount(true);
- EnableWindow(GetDlgItem(m_hwnd, IDC_BTNDEL), FALSE);
- DlgSetItemTextW(m_hwnd, IDC_EDITNAME, TranslateT("New Account"));
-
- int index = SendDlgItemMessage(m_hwnd, IDC_COMBOACCOUNT, CB_ADDSTRING, 0, (LPARAM)TranslateT("New Account"));
- if (index != CB_ERR && index != CB_ERRSPACE)
- SendDlgItemMessage(m_hwnd, IDC_COMBOACCOUNT, CB_SETCURSEL, index, (LPARAM)TranslateT("New Account"));
- }
-
- void onClick_App(CCtrlButton *)
- {
- wchar_t filter[MAX_PATH];
- mir_snwprintf(filter, L"%s (*.exe;*.bat;*.cmd;*.com)%c*.exe;*.bat;*.cmd;*.com%c%s (*.*)%c*.*%c",
- TranslateT("Executables"), 0, 0, TranslateT("All Files"), 0, 0);
-
- OPENFILENAME OFNStruct = {0};
- OFNStruct.lStructSize = sizeof(OPENFILENAME);
- OFNStruct.hwndOwner = m_hwnd;
- OFNStruct.lpstrFilter = filter;
- OFNStruct.nFilterIndex = 1;
- OFNStruct.nMaxFile = MAX_PATH;
- OFNStruct.lpstrFile = new wchar_t[MAX_PATH];
- OFNStruct.lpstrFile[0] = (wchar_t)0;
- OFNStruct.lpstrTitle = TranslateT("Select executable used for notification");
- OFNStruct.Flags = OFN_FILEMUSTEXIST | OFN_NONETWORKBUTTON | OFN_PATHMUSTEXIST | OFN_NOCHANGEDIR;
- if (!GetOpenFileName(&OFNStruct)) {
- if (CommDlgExtendedError())
- MessageBox(m_hwnd, TranslateT("Dialog box error"), TranslateT("Failed"), MB_OK);
- }
- else DlgSetItemTextW(m_hwnd, IDC_EDITAPP, OFNStruct.lpstrFile);
- delete[] OFNStruct.lpstrFile;
- }
-
- void onClick_Default(CCtrlButton *)
- {
- DlgShowAccount(0);
- }
-
- void onClick_Del(CCtrlButton *)
- {
- GetDlgItemTextA(m_hwnd, IDC_COMBOACCOUNT, DlgInput, _countof(DlgInput));
- EnableWindow(GetDlgItem(m_hwnd, IDC_BTNDEL), FALSE);
- if ((CB_ERR == (Result = SendDlgItemMessage(m_hwnd, IDC_COMBOACCOUNT, CB_GETCURSEL, 0, 0)))
- || (nullptr == (ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)DlgInput))))
- return;
-
- if (IDOK != MessageBox(m_hwnd, TranslateT("Do you really want to delete this account?"), TranslateT("Delete account confirmation"), MB_OKCANCEL | MB_ICONWARNING))
- return;
-
- DlgSetItemTextW(m_hwnd, IDC_STTIMELEFT, TranslateT("Please wait while no account is in use."));
-
- if (ActualAccount->hContact != NULL)
- db_delete_contact(ActualAccount->hContact);
-
- CallService(MS_YAMN_DELETEACCOUNT, (WPARAM)POP3Plugin, (LPARAM)ActualAccount);
-
- // We can consider our account as deleted.
- SendDlgItemMessage(m_hwnd, IDC_COMBOACCOUNT, CB_DELETESTRING, Result, 0);
- DlgSetItemText(m_hwnd, IDC_COMBOACCOUNT, nullptr);
- DlgEnableAccount(false);
- DlgShowAccount(0);
- }
-
- void onClick_Reset(CCtrlButton *)
- {
- if (ActualAccount != nullptr)
- ActualAccount->TimeLeft = ActualAccount->Interval;
- }
-
- bool OnApply() override
- {
- char Text[MAX_PATH];
- wchar_t TextW[MAX_PATH];
- BOOL Translated, NewAcc = FALSE;
- size_t Length, index;
-
- if (!GetDlgItemTextA(m_hwnd, IDC_COMBOACCOUNT, Text, _countof(Text)))
- return false;
-
- BOOL Check = (IsDlgButtonChecked(m_hwnd, IDC_CHECK) == BST_CHECKED);
- BOOL CheckSSL = (IsDlgButtonChecked(m_hwnd, IDC_CHECKSSL) == BST_CHECKED);
- BOOL CheckNoTLS = (IsDlgButtonChecked(m_hwnd, IDC_CHECKNOTLS) == BST_CHECKED);
- BOOL CheckAPOP = (IsDlgButtonChecked(m_hwnd, IDC_CHECKAPOP) == BST_CHECKED);
-
- BOOL CheckABody = (IsDlgButtonChecked(m_hwnd, IDC_AUTOBODY) == BST_CHECKED);
- BOOL CheckMsg = (IsDlgButtonChecked(m_hwnd, IDC_CHECKMSG) == BST_CHECKED);
- BOOL CheckSnd = (IsDlgButtonChecked(m_hwnd, IDC_CHECKSND) == BST_CHECKED);
- BOOL CheckIco = (IsDlgButtonChecked(m_hwnd, IDC_CHECKICO) == BST_CHECKED);
-
- BOOL CheckApp = (IsDlgButtonChecked(m_hwnd, IDC_CHECKAPP) == BST_CHECKED);
- BOOL CheckKBN = (IsDlgButtonChecked(m_hwnd, IDC_CHECKKBN) == BST_CHECKED);
- BOOL CheckContact = (IsDlgButtonChecked(m_hwnd, IDC_CHECKCONTACT) == BST_CHECKED);
- BOOL CheckContactNick = (IsDlgButtonChecked(m_hwnd, IDC_CHECKCONTACTNICK) == BST_CHECKED);
- BOOL CheckContactNoEvent = (IsDlgButtonChecked(m_hwnd, IDC_CHECKCONTACTNOEVENT) == BST_CHECKED);
-
- BOOL CheckFSnd = (IsDlgButtonChecked(m_hwnd, IDC_CHECKFSND) == BST_CHECKED);
- BOOL CheckFMsg = (IsDlgButtonChecked(m_hwnd, IDC_CHECKFMSG) == BST_CHECKED);
- BOOL CheckFIco = (IsDlgButtonChecked(m_hwnd, IDC_CHECKFICO) == BST_CHECKED);
-
- BOOL CheckNMsgP = (IsDlgButtonChecked(m_hwnd, IDC_CHECKNMSGP) == BST_CHECKED);
-
- UINT Port = GetDlgItemInt(m_hwnd, IDC_EDITPORT, &Translated, FALSE);
- if (!Translated) {
- MessageBox(m_hwnd, TranslateT("This is not a valid number value"), TranslateT("Input error"), MB_OK);
- SetFocus(GetDlgItem(m_hwnd, IDC_EDITPORT));
- return false;
- }
-
- UINT Interval = GetDlgItemInt(m_hwnd, IDC_EDITINTERVAL, &Translated, FALSE);
- if (!Translated) {
- MessageBox(m_hwnd, TranslateT("This is not a valid number value"), TranslateT("Input error"), MB_OK);
- SetFocus(GetDlgItem(m_hwnd, IDC_EDITINTERVAL));
- return false;
- }
-
- GetDlgItemTextA(m_hwnd, IDC_EDITAPP, Text, _countof(Text));
- if (CheckApp && !(Length = mir_strlen(Text))) {
- MessageBox(m_hwnd, TranslateT("Please select application to run"), TranslateT("Input error"), MB_OK);
- return false;
- }
-
- GetDlgItemTextA(m_hwnd, IDC_COMBOACCOUNT, Text, _countof(Text));
- if (!(Length = mir_strlen(Text))) {
- GetDlgItemTextA(m_hwnd, IDC_EDITNAME, Text, _countof(Text));
- if (!(Length = mir_strlen(Text)))
- return false;
- }
-
- DlgSetItemTextW(m_hwnd, IDC_STTIMELEFT, TranslateT("Please wait while no account is in use."));
-
- if (nullptr == (ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)Text))) {
- NewAcc = TRUE;
- WaitToWriteSO(POP3Plugin->AccountBrowserSO);
- if (nullptr == (ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_GETNEXTFREEACCOUNT, (WPARAM)POP3Plugin, (LPARAM)YAMN_ACCOUNTVERSION))) {
- WriteDoneSO(POP3Plugin->AccountBrowserSO);
- MessageBox(m_hwnd, TranslateT("Cannot allocate memory space for new account"), TranslateT("Memory error"), MB_OK);
- return false;
- }
- DlgEnableAccount(true);
- }
- else { // We have to get full access to AccountBrowser, so other iterating thrads cannot get new account until new account is right set
- WaitToWriteSO(POP3Plugin->AccountBrowserSO);
- }
-
- if (WAIT_OBJECT_0 != WaitToWrite(ActualAccount))
- WriteDoneSO(POP3Plugin->AccountBrowserSO);
-
- GetDlgItemTextA(m_hwnd, IDC_EDITNAME, Text, _countof(Text));
- if (!(Length = mir_strlen(Text)))
- return false;
- if (nullptr != ActualAccount->Name)
- delete[] ActualAccount->Name;
- ActualAccount->Name = new char[mir_strlen(Text) + 1];
- mir_strcpy(ActualAccount->Name, Text);
-
- GetDlgItemTextA(m_hwnd, IDC_EDITSERVER, Text, _countof(Text));
- if (nullptr != ActualAccount->Server->Name)
- delete[] ActualAccount->Server->Name;
- ActualAccount->Server->Name = new char[mir_strlen(Text) + 1];
- mir_strcpy(ActualAccount->Server->Name, Text);
-
- GetDlgItemTextA(m_hwnd, IDC_EDITLOGIN, Text, _countof(Text));
- if (nullptr != ActualAccount->Server->Login)
- delete[] ActualAccount->Server->Login;
- ActualAccount->Server->Login = new char[mir_strlen(Text) + 1];
- mir_strcpy(ActualAccount->Server->Login, Text);
-
- GetDlgItemTextA(m_hwnd, IDC_EDITPASS, Text, _countof(Text));
- if (nullptr != ActualAccount->Server->Passwd)
- delete[] ActualAccount->Server->Passwd;
- ActualAccount->Server->Passwd = new char[mir_strlen(Text) + 1];
- mir_strcpy(ActualAccount->Server->Passwd, Text);
-
- GetDlgItemTextW(m_hwnd, IDC_EDITAPP, TextW, _countof(TextW));
- if (nullptr != ActualAccount->NewMailN.App)
- delete[] ActualAccount->NewMailN.App;
- ActualAccount->NewMailN.App = new wchar_t[mir_wstrlen(TextW) + 1];
- mir_wstrcpy(ActualAccount->NewMailN.App, TextW);
-
- GetDlgItemTextW(m_hwnd, IDC_EDITAPPPARAM, TextW, _countof(TextW));
- if (nullptr != ActualAccount->NewMailN.AppParam)
- delete[] ActualAccount->NewMailN.AppParam;
- ActualAccount->NewMailN.AppParam = new wchar_t[mir_wstrlen(TextW) + 1];
- mir_wstrcpy(ActualAccount->NewMailN.AppParam, TextW);
-
- ActualAccount->Server->Port = Port;
- ActualAccount->Interval = Interval * 60;
-
- if (CB_ERR == (index = SendDlgItemMessage(m_hwnd, IDC_COMBOCP, CB_GETCURSEL, 0, 0)))
- index = CPDEFINDEX;
- ActualAccount->CP = CodePageNamesSupp[index].CP;
-
- if (NewAcc)
- ActualAccount->TimeLeft = Interval * 60;
-
- BOOL CheckStart = (IsDlgButtonChecked(m_hwnd, IDC_CHECKSTART) == BST_CHECKED);
- BOOL CheckForce = (IsDlgButtonChecked(m_hwnd, IDC_CHECKFORCE) == BST_CHECKED);
-
- ActualAccount->Flags =
- (Check ? YAMN_ACC_ENA : 0) |
- (CheckSSL ? YAMN_ACC_SSL23 : 0) |
- (CheckNoTLS ? YAMN_ACC_NOTLS : 0) |
- (CheckAPOP ? YAMN_ACC_APOP : 0) |
- (CheckABody ? YAMN_ACC_BODY : 0) |
- (ActualAccount->Flags & YAMN_ACC_POPN);
-
- ActualAccount->StatusFlags &= 0xFFFF;
- ActualAccount->StatusFlags |=
- (CheckStart ? YAMN_ACC_STARTS : 0) |
- (CheckForce ? YAMN_ACC_FORCE : 0);
-
- ActualAccount->NewMailN.Flags =
- (CheckSnd ? YAMN_ACC_SND : 0) |
- (CheckMsg ? YAMN_ACC_MSG : 0) |
- (CheckIco ? YAMN_ACC_ICO : 0) |
- (ActualAccount->NewMailN.Flags & YAMN_ACC_POP) |
- (ActualAccount->NewMailN.Flags & YAMN_ACC_POPC) |
- (CheckApp ? YAMN_ACC_APP : 0) |
- (CheckKBN ? YAMN_ACC_KBN : 0) |
- (CheckContact ? YAMN_ACC_CONT : 0) |
- (CheckContactNick ? YAMN_ACC_CONTNICK : 0) |
- (CheckContactNoEvent ? YAMN_ACC_CONTNOEVENT : 0) |
- YAMN_ACC_MSGP; //this is default: when new mail arrives and window was displayed, leave it displayed.
-
- ActualAccount->NoNewMailN.Flags =
- (ActualAccount->NoNewMailN.Flags & YAMN_ACC_POP) |
- (ActualAccount->NoNewMailN.Flags & YAMN_ACC_POPC) |
- (CheckNMsgP ? YAMN_ACC_MSGP : 0);
-
- ActualAccount->BadConnectN.Flags =
- (CheckFSnd ? YAMN_ACC_SND : 0) |
- (CheckFMsg ? YAMN_ACC_MSG : 0) |
- (CheckFIco ? YAMN_ACC_ICO : 0) |
- (ActualAccount->BadConnectN.Flags & YAMN_ACC_POP) |
- (ActualAccount->BadConnectN.Flags & YAMN_ACC_POPC);
-
- WriteDone(ActualAccount);
- WriteDoneSO(POP3Plugin->AccountBrowserSO);
-
- EnableWindow(GetDlgItem(m_hwnd, IDC_BTNDEL), TRUE);
-
- DlgSetItemText(m_hwnd, (WPARAM)IDC_STTIMELEFT, nullptr);
-
- index = SendDlgItemMessage(m_hwnd, IDC_COMBOACCOUNT, CB_GETCURSEL, 0, 0);
-
- HPOP3ACCOUNT temp = ActualAccount;
-
- SendDlgItemMessage(m_hwnd, IDC_COMBOACCOUNT, CB_RESETCONTENT, 0, 0);
- if (POP3Plugin->FirstAccount != nullptr)
- for (ActualAccount = (HPOP3ACCOUNT)POP3Plugin->FirstAccount; ActualAccount != nullptr; ActualAccount = (HPOP3ACCOUNT)ActualAccount->Next)
- if (ActualAccount->Name != nullptr)
- SendDlgItemMessageA(m_hwnd, IDC_COMBOACCOUNT, CB_ADDSTRING, 0, (LPARAM)ActualAccount->Name);
-
- ActualAccount = temp;
- SendDlgItemMessage(m_hwnd, IDC_COMBOACCOUNT, CB_SETCURSEL, (WPARAM)index, (LPARAM)ActualAccount->Name);
-
- WritePOP3Accounts();
- RefreshContact();
- return TRUE;
- }
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Popup options
-
-class CPopupOptsDlg : public CBaseOptionsDlg
-{
- HPOP3ACCOUNT ActualAccount = nullptr;
- UCHAR ActualStatus;
-
- CCtrlCombo cmbAccount, cmbCP;
- CCtrlCheck chkCol, chkFcol, chkNcol, chkPop, chkFpop, chkNpop;
- CCtrlButton btnPreview;
-
- void DlgShowAccountPopup()
- {
- if (ActualAccount) {
- WaitToRead(ActualAccount); //we do not need to check if account is deleted. It is not deleted, because only thread that can delete account is this thread
- SetDlgItemInt(m_hwnd, IDC_EDITPOPS, ActualAccount->NewMailN.PopupTime, FALSE);
- SetDlgItemInt(m_hwnd, IDC_EDITNPOPS, ActualAccount->NoNewMailN.PopupTime, FALSE);
- SetDlgItemInt(m_hwnd, IDC_EDITFPOPS, ActualAccount->BadConnectN.PopupTime, FALSE);
-
- chkPop.SetState(ActualAccount->NewMailN.Flags & YAMN_ACC_POP);
- chkCol.SetState(ActualAccount->NewMailN.Flags & YAMN_ACC_POPC);
- chkNpop.SetState(ActualAccount->NoNewMailN.Flags & YAMN_ACC_POP);
- chkNcol.SetState(ActualAccount->NoNewMailN.Flags & YAMN_ACC_POPC);
- chkFpop.SetState(ActualAccount->BadConnectN.Flags & YAMN_ACC_POP ? BST_CHECKED : BST_UNCHECKED);
- chkFcol.SetState(ActualAccount->BadConnectN.Flags & YAMN_ACC_POPC);
- CheckDlgButton(m_hwnd, IDC_RADIOPOPN, ActualAccount->Flags & YAMN_ACC_POPN ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_RADIOPOP1, ActualAccount->Flags & YAMN_ACC_POPN ? BST_UNCHECKED : BST_CHECKED);
- ReadDone(ActualAccount);
- }
- else { // default
- SetDlgItemInt(m_hwnd, IDC_EDITPOPS, 0, FALSE);
- SetDlgItemInt(m_hwnd, IDC_EDITNPOPS, 0, FALSE);
- SetDlgItemInt(m_hwnd, IDC_EDITFPOPS, 0, FALSE);
- chkPop.SetState(true);
- chkCol.SetState(true);
- chkNpop.SetState(true);
- chkNcol.SetState(true);
- chkFpop.SetState(true);
- chkFcol.SetState(true);
- CheckDlgButton(m_hwnd, IDC_RADIOPOPN, BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_RADIOPOP1, BST_CHECKED);
- }
- }
-
- void DlgEnableAccountPopup(bool bEnable)
- {
- chkPop.Enable(bEnable);
- chkCol.Enable(chkPop.IsChecked() && bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_EDITPOPS), chkPop.IsChecked() && bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CPB), chkCol.IsChecked() && chkPop.IsChecked() && bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CPT), chkCol.IsChecked() && chkPop.IsChecked() && bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_RADIOPOPN), chkPop.IsChecked() && bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_RADIOPOP1), chkPop.IsChecked() && bEnable);
-
- chkNpop.Enable(bEnable);
- chkNcol.Enable(chkNpop.IsChecked() && bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_EDITNPOPS), chkNpop.IsChecked() && bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CPNB), chkNcol.IsChecked() && chkNpop.IsChecked() && bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CPNT), chkNcol.IsChecked() && chkNpop.IsChecked() && bEnable);
-
- chkFpop.Enable(bEnable);
- chkFcol.Enable(chkFpop.IsChecked() && bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_EDITFPOPS), chkFpop.IsChecked() && bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CPFB), chkFcol.IsChecked() && chkFpop.IsChecked() && bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CPFT), chkFcol.IsChecked() && chkFpop.IsChecked() && bEnable);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKAPOP), bEnable);
- }
-
- void DlgShowAccountColors()
- {
- WaitToRead(ActualAccount); //we do not need to check if account is deleted. It is not deleted, because only thread that can delete account is this thread
-
- if (ActualAccount->NewMailN.Flags & YAMN_ACC_POPC) {
- SendDlgItemMessage(m_hwnd, IDC_CPB, CPM_SETCOLOUR, 0, (LPARAM)ActualAccount->NewMailN.PopupB);
- SendDlgItemMessage(m_hwnd, IDC_CPT, CPM_SETCOLOUR, 0, (LPARAM)ActualAccount->NewMailN.PopupT);
- }
- else {
- SendDlgItemMessage(m_hwnd, IDC_CPB, CPM_SETCOLOUR, 0, (LPARAM)GetSysColor(COLOR_BTNFACE));
- SendDlgItemMessage(m_hwnd, IDC_CPT, CPM_SETCOLOUR, 0, (LPARAM)GetSysColor(COLOR_WINDOWTEXT));
- }
- if (ActualAccount->BadConnectN.Flags & YAMN_ACC_POPC) {
- SendDlgItemMessage(m_hwnd, IDC_CPFB, CPM_SETCOLOUR, 0, (LPARAM)ActualAccount->BadConnectN.PopupB);
- SendDlgItemMessage(m_hwnd, IDC_CPFT, CPM_SETCOLOUR, 0, (LPARAM)ActualAccount->BadConnectN.PopupT);
- }
- else {
- SendDlgItemMessage(m_hwnd, IDC_CPFB, CPM_SETCOLOUR, 0, (LPARAM)GetSysColor(COLOR_BTNFACE));
- SendDlgItemMessage(m_hwnd, IDC_CPFT, CPM_SETCOLOUR, 0, (LPARAM)GetSysColor(COLOR_WINDOWTEXT));
- }
- if (ActualAccount->NoNewMailN.Flags & YAMN_ACC_POPC) {
- SendDlgItemMessage(m_hwnd, IDC_CPNB, CPM_SETCOLOUR, 0, (LPARAM)ActualAccount->NoNewMailN.PopupB);
- SendDlgItemMessage(m_hwnd, IDC_CPNT, CPM_SETCOLOUR, 0, (LPARAM)ActualAccount->NoNewMailN.PopupT);
- }
- else {
- SendDlgItemMessage(m_hwnd, IDC_CPNB, CPM_SETCOLOUR, 0, (LPARAM)GetSysColor(COLOR_BTNFACE));
- SendDlgItemMessage(m_hwnd, IDC_CPNT, CPM_SETCOLOUR, 0, (LPARAM)GetSysColor(COLOR_WINDOWTEXT));
- }
-
- ReadDone(ActualAccount); //we do not need to check if account is deleted. It is not deleted, because only thread that can delete account is this thread
- }
-
-public:
- CPopupOptsDlg() :
- CBaseOptionsDlg(IDD_POP3ACCOUNTPOPUP),
- cmbCP(this, IDC_COMBOCP),
- chkCol(this, IDC_CHECKCOL),
- chkPop(this, IDC_CHECKPOP),
- chkFcol(this, IDC_CHECKFCOL),
- chkFpop(this, IDC_CHECKFPOP),
- chkNcol(this, IDC_CHECKNCOL),
- chkNpop(this, IDC_CHECKNPOP),
- btnPreview(this, IDC_PREVIEW),
- cmbAccount(this, IDC_COMBOACCOUNT)
- {
- chkPop.OnChange = Callback(this, &CPopupOptsDlg::onChange_Pop);
- chkFpop.OnChange = Callback(this, &CPopupOptsDlg::onChange_Fpop);
- chkNpop.OnChange = Callback(this, &CPopupOptsDlg::onChange_Npop);
- chkCol.OnChange = chkFcol.OnChange = chkNcol.OnChange = Callback(this, &CPopupOptsDlg::onChange_Col);
-
- cmbCP.OnSelChanged = Callback(this, &CPopupOptsDlg::onSelChange_CP);
-
- btnPreview.OnClick = Callback(this, &CPopupOptsDlg::onClick_Preview);
-
- cmbAccount.OnKillFocus = Callback(this, &CPopupOptsDlg::onKillFocus_Account);
- cmbAccount.OnSelChanged = Callback(this, &CPopupOptsDlg::onSelChange_Account);
- }
-
- bool OnInitDialog() override
- {
- WindowList_Add(pYAMNVar->MessageWnds, m_hwnd);
-
- DlgEnableAccountPopup(false);
- DlgShowAccountPopup();
-
- WaitToReadSO(POP3Plugin->AccountBrowserSO);
-
- if (POP3Plugin->FirstAccount != nullptr)
- for (ActualAccount = (HPOP3ACCOUNT)POP3Plugin->FirstAccount; ActualAccount != nullptr; ActualAccount = (HPOP3ACCOUNT)ActualAccount->Next)
- if (ActualAccount->Name != nullptr)
- cmbAccount.AddStringA(ActualAccount->Name);
-
- ReadDoneSO(POP3Plugin->AccountBrowserSO);
- ActualAccount = nullptr;
- cmbAccount.SetCurSel(0);
- return true;
- }
-
- void OnDestroy() override
- {
- WindowList_Remove(pYAMNVar->MessageWnds, m_hwnd);
- }
-
- void onKillFocus_Account(CCtrlCombo *)
- {
- GetDlgItemTextA(m_hwnd, IDC_COMBOACCOUNT, DlgInput, _countof(DlgInput));
- if (nullptr == (ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)DlgInput))) {
- DlgSetItemText(m_hwnd, (WPARAM)IDC_STTIMELEFT, nullptr);
- if (mir_strlen(DlgInput))
- DlgEnableAccountPopup(true);
- else
- DlgEnableAccountPopup(false);
- }
- else {
- DlgShowAccount(ActualAccount);
- DlgShowAccountColors();
- DlgEnableAccountPopup(true);
- }
- }
-
- void onSelChange_Account(CCtrlCombo *)
- {
- int Result = SendDlgItemMessage(m_hwnd, IDC_COMBOACCOUNT, CB_GETCURSEL, 0, 0);
- if (CB_ERR != Result)
- SendDlgItemMessageA(m_hwnd, IDC_COMBOACCOUNT, CB_GETLBTEXT, (WPARAM)Result, (LPARAM)DlgInput);
- if ((Result == CB_ERR) || (nullptr == (ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)DlgInput)))) {
- DlgSetItemText(m_hwnd, (WPARAM)IDC_STTIMELEFT, nullptr);
- }
- else {
- DlgShowAccount(ActualAccount);
- DlgShowAccountColors();
- DlgEnableAccountPopup(true);
- }
- }
-
- void onSelChange_CP(CCtrlCombo *)
- {
- int sel = SendDlgItemMessage(m_hwnd, IDC_COMBOCP, CB_GETCURSEL, 0, 0);
- CPINFOEX info; GetCPInfoEx(CodePageNamesSupp[sel].CP, 0, &info);
- DlgSetItemTextW(m_hwnd, IDC_STSTATUS, info.CodePageName);
- }
-
- void onChange_Col(CCtrlCheck *)
- {
- EnableWindow(GetDlgItem(m_hwnd, IDC_CPB), chkCol.IsChecked() && chkPop.IsChecked());
- EnableWindow(GetDlgItem(m_hwnd, IDC_CPT), chkCol.IsChecked() && chkPop.IsChecked());
- EnableWindow(GetDlgItem(m_hwnd, IDC_CPNB), chkNcol.IsChecked() && chkNpop.IsChecked());
- EnableWindow(GetDlgItem(m_hwnd, IDC_CPNT), chkNcol.IsChecked() && chkNpop.IsChecked());
- EnableWindow(GetDlgItem(m_hwnd, IDC_CPFB), chkFcol.IsChecked() && chkFpop.IsChecked());
- EnableWindow(GetDlgItem(m_hwnd, IDC_CPFT), chkFcol.IsChecked() && chkFpop.IsChecked());
- }
-
- void onClick_Preview(CCtrlButton *)
- {
- if (chkPop.IsChecked()) {
- POPUPDATAW Tester = {};
- Tester.lchIcon = g_plugin.getIcon(IDI_NEWMAIL);
- mir_wstrncpy(Tester.lpwzContactName, TranslateT("Account Test"), MAX_CONTACTNAME);
- mir_wstrncpy(Tester.lpwzText, TranslateT("You have N new mail messages"), MAX_SECONDLINE);
- if (chkCol.IsChecked()) {
- Tester.colorBack = SendDlgItemMessage(m_hwnd, IDC_CPB, CPM_GETCOLOUR, 0, 0);
- Tester.colorText = SendDlgItemMessage(m_hwnd, IDC_CPT, CPM_GETCOLOUR, 0, 0);
- }
- else {
- Tester.colorBack = GetSysColor(COLOR_BTNFACE);
- Tester.colorText = GetSysColor(COLOR_WINDOWTEXT);
- }
- PUAddPopupW(&Tester);
- }
-
- if (chkFpop.IsChecked()) {
- POPUPDATAW TesterF = {};
- TesterF.lchIcon = g_plugin.getIcon(IDI_BADCONNECT);
- mir_wstrncpy(TesterF.lpwzContactName, TranslateT("Account Test (failed)"), MAX_CONTACTNAME);
- mir_wstrncpy(TesterF.lpwzText, TranslateT("Connection failed message"), MAX_SECONDLINE);
- if (chkFcol.IsChecked()) {
- TesterF.colorBack = SendDlgItemMessage(m_hwnd, IDC_CPFB, CPM_GETCOLOUR, 0, 0);
- TesterF.colorText = SendDlgItemMessage(m_hwnd, IDC_CPFT, CPM_GETCOLOUR, 0, 0);
- }
- else {
- TesterF.colorBack = GetSysColor(COLOR_BTNFACE);
- TesterF.colorText = GetSysColor(COLOR_WINDOWTEXT);
- }
- PUAddPopupW(&TesterF);
- }
-
- if (chkNpop.IsChecked()) {
- POPUPDATAW TesterN = {};
- TesterN.lchIcon = g_plugin.getIcon(IDI_LAUNCHAPP);
- mir_wstrncpy(TesterN.lpwzContactName, TranslateT("Account Test"), MAX_CONTACTNAME);
- mir_wstrncpy(TesterN.lpwzText, TranslateT("No new mail message"), MAX_SECONDLINE);
- if (chkNcol.IsChecked()) {
- TesterN.colorBack = SendDlgItemMessage(m_hwnd, IDC_CPNB, CPM_GETCOLOUR, 0, 0);
- TesterN.colorText = SendDlgItemMessage(m_hwnd, IDC_CPNT, CPM_GETCOLOUR, 0, 0);
- }
- else {
- TesterN.colorBack = GetSysColor(COLOR_BTNFACE);
- TesterN.colorText = GetSysColor(COLOR_WINDOWTEXT);
- }
- PUAddPopupW(&TesterN);
- }
- }
-
- void onChange_Pop(CCtrlCheck *)
- {
- bool bEnabled = chkPop.IsChecked();
- chkCol.Enable(bEnabled);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CPB), chkCol.IsChecked() && bEnabled);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CPT), chkCol.IsChecked() && bEnabled);
- EnableWindow(GetDlgItem(m_hwnd, IDC_RADIOPOPN), bEnabled);
- EnableWindow(GetDlgItem(m_hwnd, IDC_RADIOPOP1), bEnabled);
- EnableWindow(GetDlgItem(m_hwnd, IDC_EDITPOPS), bEnabled);
- }
-
- void onChange_Fpop(CCtrlCheck *)
- {
- bool bEnabled = chkFpop.IsChecked();
- chkFcol.Enable(bEnabled);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CPFB), chkFcol.IsChecked() && bEnabled);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CPFT), chkFcol.IsChecked() && bEnabled);
- EnableWindow(GetDlgItem(m_hwnd, IDC_EDITFPOPS), bEnabled);
- }
-
- void onChange_Npop(CCtrlCheck *)
- {
- bool bEnabled = chkNpop.IsChecked();
- chkNcol.Enable(bEnabled);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CPNB), chkNcol.IsChecked() && bEnabled);
- EnableWindow(GetDlgItem(m_hwnd, IDC_CPNT), chkNcol.IsChecked() && bEnabled);
- EnableWindow(GetDlgItem(m_hwnd, IDC_EDITNPOPS), bEnabled);
- }
-
- bool OnApply() override
- {
- wchar_t Text[MAX_PATH];
- if (!GetDlgItemText(m_hwnd, IDC_COMBOACCOUNT, Text, _countof(Text)))
- return false;
-
- BOOL CheckPopup = chkPop.IsChecked();
- BOOL CheckPopupW = chkCol.IsChecked();
-
- BOOL CheckFPopup = chkFpop.IsChecked();
- BOOL CheckFPopupW = chkFcol.IsChecked();
-
- BOOL CheckNPopup = chkNpop.IsChecked();
- BOOL CheckNPopupW = chkNcol.IsChecked();
-
- BOOL CheckPopN = (IsDlgButtonChecked(m_hwnd, IDC_RADIOPOPN) == BST_CHECKED);
-
- BOOL Translated;
- UINT Time = GetDlgItemInt(m_hwnd, IDC_EDITPOPS, &Translated, FALSE);
- if (!Translated) {
- MessageBox(m_hwnd, TranslateT("This is not a valid number value"), TranslateT("Input error"), MB_OK);
- SetFocus(GetDlgItem(m_hwnd, IDC_EDITPOPS));
- return false;
- }
- UINT TimeN = GetDlgItemInt(m_hwnd, IDC_EDITNPOPS, &Translated, FALSE);
- if (!Translated) {
- MessageBox(m_hwnd, TranslateT("This is not a valid number value"), TranslateT("Input error"), MB_OK);
- SetFocus(GetDlgItem(m_hwnd, IDC_EDITNPOPS));
- return false;
- }
- UINT TimeF = GetDlgItemInt(m_hwnd, IDC_EDITFPOPS, &Translated, FALSE);
- if (!Translated) {
- MessageBox(m_hwnd, TranslateT("This is not a valid number value"), TranslateT("Input error"), MB_OK);
- SetFocus(GetDlgItem(m_hwnd, IDC_EDITFPOPS));
- return false;
- }
-
- DlgSetItemTextW(m_hwnd, IDC_STTIMELEFT, TranslateT("Please wait while no account is in use."));
-
- ActualAccount->Flags =
- (ActualAccount->Flags & YAMN_ACC_ENA) |
- (ActualAccount->Flags & YAMN_ACC_SSL23) |
- (ActualAccount->Flags & YAMN_ACC_NOTLS) |
- (ActualAccount->Flags & YAMN_ACC_APOP) |
- (ActualAccount->Flags & YAMN_ACC_BODY) |
- (CheckPopN ? YAMN_ACC_POPN : 0);
-
- ActualAccount->NewMailN.Flags =
- (ActualAccount->NewMailN.Flags & YAMN_ACC_SND) |
- (ActualAccount->NewMailN.Flags & YAMN_ACC_MSG) |
- (ActualAccount->NewMailN.Flags & YAMN_ACC_ICO) |
- (CheckPopup ? YAMN_ACC_POP : 0) |
- (CheckPopupW ? YAMN_ACC_POPC : 0) |
- (ActualAccount->NewMailN.Flags & YAMN_ACC_APP) |
- (ActualAccount->NewMailN.Flags & YAMN_ACC_KBN) |
- (ActualAccount->NewMailN.Flags & YAMN_ACC_CONT) |
- (ActualAccount->NewMailN.Flags & YAMN_ACC_CONTNICK) |
- (ActualAccount->NewMailN.Flags & YAMN_ACC_CONTNOEVENT) |
- YAMN_ACC_MSGP;
-
- ActualAccount->NoNewMailN.Flags =
- (CheckNPopup ? YAMN_ACC_POP : 0) |
- (CheckNPopupW ? YAMN_ACC_POPC : 0) |
- (ActualAccount->NoNewMailN.Flags & YAMN_ACC_MSGP);
-
- ActualAccount->BadConnectN.Flags =
- (ActualAccount->BadConnectN.Flags & YAMN_ACC_SND) |
- (ActualAccount->BadConnectN.Flags & YAMN_ACC_MSG) |
- (ActualAccount->BadConnectN.Flags & YAMN_ACC_ICO) |
- (CheckFPopup ? YAMN_ACC_POP : 0) |
- (CheckFPopupW ? YAMN_ACC_POPC : 0);
-
- ActualAccount->NewMailN.PopupB = SendDlgItemMessage(m_hwnd, IDC_CPB, CPM_GETCOLOUR, 0, 0);
- ActualAccount->NewMailN.PopupT = SendDlgItemMessage(m_hwnd, IDC_CPT, CPM_GETCOLOUR, 0, 0);
- ActualAccount->NewMailN.PopupTime = Time;
-
- ActualAccount->NoNewMailN.PopupB = SendDlgItemMessage(m_hwnd, IDC_CPNB, CPM_GETCOLOUR, 0, 0);
- ActualAccount->NoNewMailN.PopupT = SendDlgItemMessage(m_hwnd, IDC_CPNT, CPM_GETCOLOUR, 0, 0);
- ActualAccount->NoNewMailN.PopupTime = TimeN;
-
- ActualAccount->BadConnectN.PopupB = SendDlgItemMessage(m_hwnd, IDC_CPFB, CPM_GETCOLOUR, 0, 0);
- ActualAccount->BadConnectN.PopupT = SendDlgItemMessage(m_hwnd, IDC_CPFT, CPM_GETCOLOUR, 0, 0);
- ActualAccount->BadConnectN.PopupTime = TimeF;
-
- WriteDone(ActualAccount);
- WriteDoneSO(POP3Plugin->AccountBrowserSO);
-
- WritePOP3Accounts();
- RefreshContact();
- return TRUE;
- }
-};
-
-//--------------------------------------------------------------------------------------------------
-
-int YAMNOptInitSvc(WPARAM wParam, LPARAM)
-{
- OPTIONSDIALOGPAGE odp = {};
- odp.szGroup.a = LPGEN("Network");
- odp.szTitle.a = LPGEN("YAMN");
- odp.flags = ODPF_BOLDGROUPS;
-
- odp.szTab.a = LPGEN("Accounts");
- odp.pDialog = new CAccOptDlg();
- g_plugin.addOptions(wParam, &odp);
-
- odp.szTab.a = LPGEN("General");
- odp.pDialog = new CGeneralOptDlg();
- g_plugin.addOptions(wParam, &odp);
-
- odp.szGroup.a = LPGEN("Popups");
- odp.szTab.a = LPGEN("YAMN");
- odp.pDialog = new CPopupOptsDlg();
- g_plugin.addOptions(wParam, &odp);
- return 0;
-}
+/*
+ * This code implements POP3 options window handling
+ *
+ * (c) majvan 2002-2003
+*/
+
+#include "../../stdafx.h"
+
+//--------------------------------------------------------------------------------------------------
+
+static char DlgInput[MAX_PATH];
+
+static BOOL DlgSetItemText(HWND hDlg, WPARAM wParam, const char *str)
+{
+ if (str == nullptr)
+ SetDlgItemTextA(hDlg, wParam, "");
+ else
+ SetDlgItemTextA(hDlg, wParam, str);
+ return TRUE;
+}
+
+static BOOL DlgSetItemTextW(HWND hDlg, WPARAM wParam, const wchar_t *str)
+{
+ if (str == nullptr)
+ SetDlgItemTextW(hDlg, wParam, L"");
+ else
+ SetDlgItemTextW(hDlg, wParam, str);
+ return TRUE;
+}
+
+struct CBaseOptionsDlg : public CDlgBase
+{
+ CBaseOptionsDlg(int iDlgId) :
+ CDlgBase(g_plugin, iDlgId)
+ {}
+
+ void DlgShowAccount(HPOP3ACCOUNT pAccount)
+ {
+ int i;
+
+ if (pAccount) {
+ // we do not need to check if account is deleted. It is not deleted, because only thread that can delete account is this thread
+ WaitToRead(pAccount);
+
+ DlgSetItemText(m_hwnd, IDC_EDITSERVER, pAccount->Server->Name);
+ DlgSetItemText(m_hwnd, IDC_EDITNAME, pAccount->Name);
+ DlgSetItemText(m_hwnd, IDC_EDITLOGIN, pAccount->Server->Login);
+ DlgSetItemText(m_hwnd, IDC_EDITPASS, pAccount->Server->Passwd);
+ DlgSetItemTextW(m_hwnd, IDC_EDITAPP, pAccount->NewMailN.App);
+ DlgSetItemTextW(m_hwnd, IDC_EDITAPPPARAM, pAccount->NewMailN.AppParam);
+ SetDlgItemInt(m_hwnd, IDC_EDITPORT, pAccount->Server->Port, FALSE);
+ SetDlgItemInt(m_hwnd, IDC_EDITINTERVAL, pAccount->Interval / 60, FALSE);
+ SetDlgItemInt(m_hwnd, IDC_EDITPOPS, pAccount->NewMailN.PopupTime, FALSE);
+ SetDlgItemInt(m_hwnd, IDC_EDITNPOPS, pAccount->NoNewMailN.PopupTime, FALSE);
+ SetDlgItemInt(m_hwnd, IDC_EDITFPOPS, pAccount->BadConnectN.PopupTime, FALSE);
+ for (i = 0; i <= CPLENSUPP; i++)
+ if ((i < CPLENSUPP) && (CodePageNamesSupp[i].CP == pAccount->CP)) {
+ SendDlgItemMessage(m_hwnd, IDC_COMBOCP, CB_SETCURSEL, (WPARAM)i, 0);
+ break;
+ }
+
+ if (i == CPLENSUPP)
+ SendDlgItemMessage(m_hwnd, IDC_COMBOCP, CB_SETCURSEL, (WPARAM)CPDEFINDEX, 0);
+
+ CheckDlgButton(m_hwnd, IDC_CHECK, pAccount->Flags & YAMN_ACC_ENA ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKSND, pAccount->NewMailN.Flags & YAMN_ACC_SND ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKMSG, pAccount->NewMailN.Flags & YAMN_ACC_MSG ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKICO, pAccount->NewMailN.Flags & YAMN_ACC_ICO ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKPOP, pAccount->NewMailN.Flags & YAMN_ACC_POP ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKCOL, pAccount->NewMailN.Flags & YAMN_ACC_POPC ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKAPP, pAccount->NewMailN.Flags & YAMN_ACC_APP ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKKBN, pAccount->NewMailN.Flags & YAMN_ACC_KBN ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKNPOP, pAccount->NoNewMailN.Flags & YAMN_ACC_POP ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKNCOL, pAccount->NoNewMailN.Flags & YAMN_ACC_POPC ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKNMSGP, pAccount->NoNewMailN.Flags & YAMN_ACC_MSGP ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKFSND, pAccount->BadConnectN.Flags & YAMN_ACC_SND ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKFMSG, pAccount->BadConnectN.Flags & YAMN_ACC_MSG ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKFICO, pAccount->BadConnectN.Flags & YAMN_ACC_ICO ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKFPOP, pAccount->BadConnectN.Flags & YAMN_ACC_POP ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKFCOL, pAccount->BadConnectN.Flags & YAMN_ACC_POPC ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_RADIOPOPN, pAccount->Flags & YAMN_ACC_POPN ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_RADIOPOP1, pAccount->Flags & YAMN_ACC_POPN ? BST_UNCHECKED : BST_CHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKSSL, pAccount->Flags & YAMN_ACC_SSL23 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKNOTLS, pAccount->Flags & YAMN_ACC_NOTLS ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKAPOP, pAccount->Flags & YAMN_ACC_APOP ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_AUTOBODY, pAccount->Flags & YAMN_ACC_BODY ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKSTART, pAccount->StatusFlags & YAMN_ACC_STARTS ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKFORCE, pAccount->StatusFlags & YAMN_ACC_FORCE ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKCONTACT, pAccount->NewMailN.Flags & YAMN_ACC_CONT ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKCONTACTNICK, pAccount->NewMailN.Flags & YAMN_ACC_CONTNICK ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKCONTACTNOEVENT, pAccount->NewMailN.Flags & YAMN_ACC_CONTNOEVENT ? BST_CHECKED : BST_UNCHECKED);
+
+ wchar_t accstatus[256];
+ GetAccountStatus(pAccount, accstatus);
+ SetDlgItemText(m_hwnd, IDC_STSTATUS, accstatus);
+ ReadDone(pAccount);
+ }
+ else {
+ DlgSetItemText(m_hwnd, IDC_EDITSERVER, nullptr);
+ DlgSetItemText(m_hwnd, IDC_EDITNAME, nullptr);
+ DlgSetItemText(m_hwnd, IDC_EDITLOGIN, nullptr);
+ DlgSetItemText(m_hwnd, IDC_EDITPASS, nullptr);
+ DlgSetItemText(m_hwnd, IDC_EDITAPP, nullptr);
+ DlgSetItemText(m_hwnd, IDC_EDITAPPPARAM, nullptr);
+ DlgSetItemText(m_hwnd, IDC_STTIMELEFT, nullptr);
+ SetDlgItemInt(m_hwnd, IDC_EDITPORT, 110, FALSE);
+ SetDlgItemInt(m_hwnd, IDC_EDITINTERVAL, 30, FALSE);
+ SetDlgItemInt(m_hwnd, IDC_EDITPOPS, 0, FALSE);
+ SetDlgItemInt(m_hwnd, IDC_EDITNPOPS, 0, FALSE);
+ SetDlgItemInt(m_hwnd, IDC_EDITFPOPS, 0, FALSE);
+ SendDlgItemMessage(m_hwnd, IDC_COMBOCP, CB_SETCURSEL, (WPARAM)CPDEFINDEX, 0);
+ CheckDlgButton(m_hwnd, IDC_CHECK, BST_CHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKSND, BST_CHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKMSG, BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKICO, BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKPOP, BST_CHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKCOL, BST_CHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKAPP, BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKFSND, BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKFMSG, BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKFICO, BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKFPOP, BST_CHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKFCOL, BST_CHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKSTART, BST_CHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKFORCE, BST_CHECKED);
+ CheckDlgButton(m_hwnd, IDC_RADIOPOPN, BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_RADIOPOP1, BST_CHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKSSL, BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKNOTLS, BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKAPOP, BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_AUTOBODY, BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CHECKCONTACT, BST_CHECKED);
+
+ SetDlgItemText(m_hwnd, IDC_STSTATUS, TranslateT("No account selected"));
+ }
+ }
+};
+
+//=======================================================================================
+// General options dialog
+
+struct CGeneralOptDlg : public CBaseOptionsDlg
+{
+ CGeneralOptDlg() :
+ CBaseOptionsDlg(IDD_YAMNOPT)
+ {}
+
+ bool OnInitDialog() override
+ {
+ CheckDlgButton(m_hwnd, IDC_CHECKTTB, g_plugin.getByte(YAMN_TTBFCHECK, 1) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_LONGDATE, (optDateTime & SHOWDATELONG) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_SMARTDATE, (optDateTime & SHOWDATENOTODAY) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_NOSECONDS, (optDateTime & SHOWDATENOSECONDS) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_CLOSEONDELETE, g_plugin.getByte(YAMN_CLOSEDELETE, 0) ? BST_CHECKED : BST_UNCHECKED);
+ return true;
+ }
+
+ bool OnApply() override
+ {
+ g_plugin.setByte(YAMN_CLOSEDELETE, IsDlgButtonChecked(m_hwnd, IDC_CLOSEONDELETE));
+ g_plugin.setByte(YAMN_TTBFCHECK, IsDlgButtonChecked(m_hwnd, IDC_CHECKTTB));
+
+ AddTopToolbarIcon(0, 0);
+
+ optDateTime = 0;
+ if (IsDlgButtonChecked(m_hwnd, IDC_LONGDATE)) optDateTime |= SHOWDATELONG;
+ if (IsDlgButtonChecked(m_hwnd, IDC_SMARTDATE)) optDateTime |= SHOWDATENOTODAY;
+ if (IsDlgButtonChecked(m_hwnd, IDC_NOSECONDS)) optDateTime |= SHOWDATENOSECONDS;
+ g_plugin.setByte(YAMN_DBTIMEOPTIONS, optDateTime);
+ return true;
+ }
+};
+
+//--------------------------------------------------------------------------------------------------
+
+static int g_iStatusControls[] = {IDC_CHECKST0, IDC_CHECKST1, IDC_CHECKST2, IDC_CHECKST3, IDC_CHECKST4, IDC_CHECKST5, IDC_CHECKST6, IDC_CHECKST7};
+
+static BOOL DlgShowAccountStatus(HWND hDlg, HPOP3ACCOUNT ActualAccount)
+{
+ if (ActualAccount) {
+ WaitToRead(ActualAccount); //we do not need to check if account is deleted. It is not deleted, because only thread that can delete account is this thread
+
+ CheckDlgButton(hDlg, IDC_CHECKST0, ActualAccount->StatusFlags & YAMN_ACC_ST0 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_CHECKST1, ActualAccount->StatusFlags & YAMN_ACC_ST1 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_CHECKST2, ActualAccount->StatusFlags & YAMN_ACC_ST2 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_CHECKST3, ActualAccount->StatusFlags & YAMN_ACC_ST3 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_CHECKST4, ActualAccount->StatusFlags & YAMN_ACC_ST4 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_CHECKST5, ActualAccount->StatusFlags & YAMN_ACC_ST5 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_CHECKST6, ActualAccount->StatusFlags & YAMN_ACC_ST6 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_CHECKST7, ActualAccount->StatusFlags & YAMN_ACC_ST7 ? BST_CHECKED : BST_UNCHECKED);
+
+ ReadDone(ActualAccount);
+ }
+ else {
+ CheckDlgButton(hDlg, IDC_CHECKST0, BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_CHECKST1, BST_CHECKED);
+ CheckDlgButton(hDlg, IDC_CHECKST2, BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_CHECKST3, BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_CHECKST4, BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_CHECKST5, BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_CHECKST6, BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_CHECKST7, BST_CHECKED);
+ }
+ return TRUE;
+}
+
+static INT_PTR CALLBACK DlgProcPOP3AccStatusOpt(HWND hDlg, UINT msg, WPARAM wParam, LPARAM)
+{
+ static HPOP3ACCOUNT ActualAccount;
+ switch (msg) {
+ case WM_INITDIALOG:
+ ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)DlgInput);
+ if (ActualAccount != nullptr) {
+ DlgShowAccountStatus(hDlg, ActualAccount);
+ for (auto &it : g_iStatusControls)
+ EnableWindow(GetDlgItem(hDlg, it), true);
+ }
+ else {
+ for (auto &it : g_iStatusControls)
+ CheckDlgButton(hDlg, it, BST_CHECKED);
+ }
+ TranslateDialogDefault(hDlg);
+ SendMessage(GetParent(hDlg), PSM_UNCHANGED, (WPARAM)hDlg, 0);
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDCANCEL:
+ EndDialog(hDlg, 0);
+ DestroyWindow(hDlg);
+ break;
+
+ case IDOK:
+ int iShift = 1;
+ ActualAccount->StatusFlags = 0;
+ for (auto &it : g_iStatusControls) {
+ if (IsDlgButtonChecked(hDlg, it))
+ ActualAccount->StatusFlags |= iShift;
+ iShift <<= 1;
+ }
+
+ WindowList_BroadcastAsync(YAMNVar.MessageWnds, WM_YAMN_CHANGESTATUSOPTION, 0, 0);
+ EndDialog(hDlg, 0);
+ DestroyWindow(hDlg);
+ break;
+ }
+ }
+ return FALSE;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Account options
+
+class CAccOptDlg : public CBaseOptionsDlg
+{
+ INT_PTR Result;
+ UCHAR ActualStatus;
+ HPOP3ACCOUNT ActualAccount = nullptr;
+
+ CCtrlCheck chkContact, chkSsl, chkApp;
+ CCtrlCombo cmbAccount, cmbCP;
+ CCtrlButton btnStatus, btnAdd, btnDel, btnApp, btnDefault, btnReset;
+
+ void DlgEnableAccount(bool bEnable)
+ {
+ cmbAccount.Enable(POP3Plugin->FirstAccount != nullptr);
+
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CHECK), bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_EDITSERVER), bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_EDITNAME), bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_EDITPORT), bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_EDITLOGIN), bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_EDITPASS), bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_EDITINTERVAL), bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKSND), bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKMSG), bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKICO), bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKAPP), bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKKBN), bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_BTNAPP), chkApp.IsChecked() && bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_EDITAPP), chkApp.IsChecked() && bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_EDITAPPPARAM), chkApp.IsChecked() && bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKNMSGP), bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKFSND), bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKFMSG), bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKFICO), bEnable);
+
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKSTART), bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKFORCE), bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_COMBOCP), bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_STTIMELEFT), bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_BTNRESET), bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_BTNDEFAULT), bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_BTNSTATUS), bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKSSL), bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKAPOP), bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKNOTLS), chkSsl.IsChecked() && bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_AUTOBODY), bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKCONTACT), bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKCONTACTNICK), chkContact.IsChecked() && bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKCONTACTNOEVENT), chkContact.IsChecked() && bEnable);
+ }
+
+public:
+ CAccOptDlg() :
+ CBaseOptionsDlg(IDD_POP3ACCOUNTOPT),
+ cmbCP(this, IDC_COMBOCP),
+ btnAdd(this, IDC_BTNADD),
+ btnApp(this, IDC_BTNAPP),
+ btnDel(this, IDC_BTNDEL),
+ chkApp(this, IDC_CHECKAPP),
+ chkSsl(this, IDC_CHECKSSL),
+ btnReset(this, IDC_BTNRESET),
+ btnStatus(this, IDC_BTNSTATUS),
+ btnDefault(this, IDC_BTNDEFAULT),
+ cmbAccount(this, IDC_COMBOACCOUNT),
+ chkContact(this, IDC_CHECKCONTACT)
+ {
+ cmbCP.OnSelChanged = Callback(this, &CAccOptDlg::onSelChange_CP);
+
+ cmbAccount.OnChange = Callback(this, &CAccOptDlg::onChange_Account);
+ cmbAccount.OnKillFocus = Callback(this, &CAccOptDlg::onKillFocus_Account);
+ cmbAccount.OnSelChanged = Callback(this, &CAccOptDlg::onSelChange_Account);
+
+ chkApp.OnChange = Callback(this, &CAccOptDlg::onChangeApp);
+ chkSsl.OnChange = Callback(this, &CAccOptDlg::onChangeSsl);
+ chkContact.OnChange = Callback(this, &CAccOptDlg::onChangeContact);
+
+ btnAdd.OnClick = Callback(this, &CAccOptDlg::onClick_Add);
+ btnDel.OnClick = Callback(this, &CAccOptDlg::onClick_Del);
+ btnApp.OnClick = Callback(this, &CAccOptDlg::onClick_App);
+ btnReset.OnClick = Callback(this, &CAccOptDlg::onClick_Reset);
+ btnStatus.OnClick = Callback(this, &CAccOptDlg::onClick_Status);
+ btnDefault.OnClick = Callback(this, &CAccOptDlg::onClick_Default);
+ }
+
+ bool OnInitDialog() override
+ {
+ EnableWindow(GetDlgItem(m_hwnd, IDC_BTNDEL), FALSE);
+
+ DlgEnableAccount(false);
+ DlgShowAccount(0);
+
+ // Fill accounts
+ WaitToReadSO(POP3Plugin->AccountBrowserSO);
+
+ for (ActualAccount = (HPOP3ACCOUNT)POP3Plugin->FirstAccount; ActualAccount != nullptr; ActualAccount = (HPOP3ACCOUNT)ActualAccount->Next)
+ if (ActualAccount->Name != nullptr)
+ cmbAccount.AddStringA(ActualAccount->Name);
+ cmbAccount.SetCurSel(0);
+
+ ReadDoneSO(POP3Plugin->AccountBrowserSO);
+
+ // Fill code pages
+ cmbCP.AddString(TranslateT("Default"));
+ for (int i = 1; i < CPLENSUPP; i++) {
+ CPINFOEX info; GetCPInfoEx(CodePageNamesSupp[i].CP, 0, &info);
+ size_t len = mir_wstrlen(info.CodePageName + 7);
+ info.CodePageName[len + 6] = 0;
+ cmbCP.AddString(info.CodePageName + 7);
+ }
+ cmbCP.SetCurSel(0);
+
+ ActualAccount = nullptr;
+ SendMessage(GetParent(m_hwnd), PSM_UNCHANGED, (WPARAM)m_hwnd, 0);
+
+ WindowList_Add(pYAMNVar->MessageWnds, m_hwnd);
+ return true;
+ }
+
+ void OnDestroy() override
+ {
+ WindowList_Remove(pYAMNVar->MessageWnds, m_hwnd);
+ }
+
+ INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) override
+ {
+ switch (msg) {
+ case WM_YAMN_CHANGESTATUS:
+ if ((HPOP3ACCOUNT)wParam == ActualAccount) {
+ wchar_t accstatus[256];
+ GetAccountStatus(ActualAccount, accstatus);
+ SetDlgItemText(m_hwnd, IDC_STSTATUS, accstatus);
+ return TRUE;
+ }
+ break;
+
+ case WM_YAMN_CHANGESTATUSOPTION:
+ NotifyChange();
+ return TRUE;
+
+ case WM_YAMN_CHANGETIME:
+ if ((HPOP3ACCOUNT)wParam == ActualAccount) {
+ wchar_t Text[256];
+ mir_snwprintf(Text, TranslateT("Time left to next check [s]: %d"), (uint32_t)lParam);
+ SetDlgItemText(m_hwnd, IDC_STTIMELEFT, Text);
+ }
+ return TRUE;
+ }
+ return CDlgBase::DlgProc(msg, wParam, lParam);
+ }
+
+ void onChange_Account(CCtrlCombo *)
+ {
+ ActualAccount = nullptr;
+ DlgSetItemText(m_hwnd, (WPARAM)IDC_STTIMELEFT, nullptr);
+ DlgEnableAccount(0 != GetDlgItemTextA(m_hwnd, IDC_COMBOACCOUNT, DlgInput, _countof(DlgInput)));
+ }
+
+ void onKillFocus_Account(CCtrlCombo *)
+ {
+ GetDlgItemTextA(m_hwnd, IDC_COMBOACCOUNT, DlgInput, _countof(DlgInput));
+ if (nullptr == (ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)DlgInput))) {
+ DlgSetItemText(m_hwnd, (WPARAM)IDC_STTIMELEFT, nullptr);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_BTNDEL), FALSE);
+ DlgEnableAccount(mir_strlen(DlgInput) > 0);
+ }
+ else {
+ DlgShowAccount(ActualAccount);
+ DlgEnableAccount(true);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_BTNDEL), TRUE);
+ }
+ }
+
+ void onSelChange_Account(CCtrlCombo *)
+ {
+ if (CB_ERR != (Result = cmbAccount.GetCurSel()))
+ SendDlgItemMessageA(m_hwnd, IDC_COMBOACCOUNT, CB_GETLBTEXT, (WPARAM)Result, (LPARAM)DlgInput);
+
+ if ((Result == CB_ERR) || (nullptr == (ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)DlgInput)))) {
+ DlgSetItemText(m_hwnd, (WPARAM)IDC_STTIMELEFT, nullptr);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_BTNDEL), FALSE);
+ }
+ else {
+ DlgShowAccount(ActualAccount);
+ DlgEnableAccount(true);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_BTNDEL), TRUE);
+ }
+ }
+
+ void onSelChange_CP(CCtrlCombo *)
+ {
+ int sel = cmbCP.GetCurSel();
+ CPINFOEX info; GetCPInfoEx(CodePageNamesSupp[sel].CP, 0, &info);
+ DlgSetItemTextW(m_hwnd, IDC_STSTATUS, info.CodePageName);
+ }
+
+ void onChangeContact(CCtrlCheck *)
+ {
+ bool bEnabled = chkContact.IsChecked();
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKCONTACTNICK), bEnabled);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKCONTACTNOEVENT), bEnabled);
+ }
+
+ void onChangeSsl(CCtrlCheck *)
+ {
+ bool bEnabled = chkSsl.IsChecked();
+ SetDlgItemInt(m_hwnd, IDC_EDITPORT, bEnabled ? 995 : 110, FALSE);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKNOTLS), !bEnabled);
+ }
+
+ void onChangeApp(CCtrlCheck *)
+ {
+ bool bEnabled = chkApp.IsChecked();
+ EnableWindow(GetDlgItem(m_hwnd, IDC_BTNAPP), bEnabled);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_EDITAPP), bEnabled);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_EDITAPPPARAM), bEnabled);
+ }
+
+ void onClick_Status(CCtrlButton *)
+ {
+ DialogBoxParamW(g_plugin.getInst(), MAKEINTRESOURCEW(IDD_CHOOSESTATUSMODES), m_hwnd, DlgProcPOP3AccStatusOpt, NULL);
+ }
+
+ void onClick_Add(CCtrlButton *)
+ {
+ DlgSetItemText(m_hwnd, (WPARAM)IDC_STTIMELEFT, nullptr);
+ DlgShowAccount(0);
+ DlgEnableAccount(true);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_BTNDEL), FALSE);
+ DlgSetItemTextW(m_hwnd, IDC_EDITNAME, TranslateT("New Account"));
+
+ int index = SendDlgItemMessage(m_hwnd, IDC_COMBOACCOUNT, CB_ADDSTRING, 0, (LPARAM)TranslateT("New Account"));
+ if (index != CB_ERR && index != CB_ERRSPACE)
+ SendDlgItemMessage(m_hwnd, IDC_COMBOACCOUNT, CB_SETCURSEL, index, (LPARAM)TranslateT("New Account"));
+ }
+
+ void onClick_App(CCtrlButton *)
+ {
+ wchar_t filter[MAX_PATH];
+ mir_snwprintf(filter, L"%s (*.exe;*.bat;*.cmd;*.com)%c*.exe;*.bat;*.cmd;*.com%c%s (*.*)%c*.*%c",
+ TranslateT("Executables"), 0, 0, TranslateT("All Files"), 0, 0);
+
+ OPENFILENAME OFNStruct = {0};
+ OFNStruct.lStructSize = sizeof(OPENFILENAME);
+ OFNStruct.hwndOwner = m_hwnd;
+ OFNStruct.lpstrFilter = filter;
+ OFNStruct.nFilterIndex = 1;
+ OFNStruct.nMaxFile = MAX_PATH;
+ OFNStruct.lpstrFile = new wchar_t[MAX_PATH];
+ OFNStruct.lpstrFile[0] = (wchar_t)0;
+ OFNStruct.lpstrTitle = TranslateT("Select executable used for notification");
+ OFNStruct.Flags = OFN_FILEMUSTEXIST | OFN_NONETWORKBUTTON | OFN_PATHMUSTEXIST | OFN_NOCHANGEDIR;
+ if (!GetOpenFileName(&OFNStruct)) {
+ if (CommDlgExtendedError())
+ MessageBox(m_hwnd, TranslateT("Dialog box error"), TranslateT("Failed"), MB_OK);
+ }
+ else DlgSetItemTextW(m_hwnd, IDC_EDITAPP, OFNStruct.lpstrFile);
+ delete[] OFNStruct.lpstrFile;
+ }
+
+ void onClick_Default(CCtrlButton *)
+ {
+ DlgShowAccount(0);
+ }
+
+ void onClick_Del(CCtrlButton *)
+ {
+ GetDlgItemTextA(m_hwnd, IDC_COMBOACCOUNT, DlgInput, _countof(DlgInput));
+ EnableWindow(GetDlgItem(m_hwnd, IDC_BTNDEL), FALSE);
+ if ((CB_ERR == (Result = SendDlgItemMessage(m_hwnd, IDC_COMBOACCOUNT, CB_GETCURSEL, 0, 0)))
+ || (nullptr == (ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)DlgInput))))
+ return;
+
+ if (IDOK != MessageBox(m_hwnd, TranslateT("Do you really want to delete this account?"), TranslateT("Delete account confirmation"), MB_OKCANCEL | MB_ICONWARNING))
+ return;
+
+ DlgSetItemTextW(m_hwnd, IDC_STTIMELEFT, TranslateT("Please wait while no account is in use."));
+
+ if (ActualAccount->hContact != NULL)
+ db_delete_contact(ActualAccount->hContact);
+
+ CallService(MS_YAMN_DELETEACCOUNT, (WPARAM)POP3Plugin, (LPARAM)ActualAccount);
+
+ // We can consider our account as deleted.
+ SendDlgItemMessage(m_hwnd, IDC_COMBOACCOUNT, CB_DELETESTRING, Result, 0);
+ DlgSetItemText(m_hwnd, IDC_COMBOACCOUNT, nullptr);
+ DlgEnableAccount(false);
+ DlgShowAccount(0);
+ }
+
+ void onClick_Reset(CCtrlButton *)
+ {
+ if (ActualAccount != nullptr)
+ ActualAccount->TimeLeft = ActualAccount->Interval;
+ }
+
+ bool OnApply() override
+ {
+ char Text[MAX_PATH];
+ wchar_t TextW[MAX_PATH];
+ BOOL Translated, NewAcc = FALSE;
+ size_t Length, index;
+
+ if (!GetDlgItemTextA(m_hwnd, IDC_COMBOACCOUNT, Text, _countof(Text)))
+ return false;
+
+ BOOL Check = (IsDlgButtonChecked(m_hwnd, IDC_CHECK) == BST_CHECKED);
+ BOOL CheckSSL = (IsDlgButtonChecked(m_hwnd, IDC_CHECKSSL) == BST_CHECKED);
+ BOOL CheckNoTLS = (IsDlgButtonChecked(m_hwnd, IDC_CHECKNOTLS) == BST_CHECKED);
+ BOOL CheckAPOP = (IsDlgButtonChecked(m_hwnd, IDC_CHECKAPOP) == BST_CHECKED);
+
+ BOOL CheckABody = (IsDlgButtonChecked(m_hwnd, IDC_AUTOBODY) == BST_CHECKED);
+ BOOL CheckMsg = (IsDlgButtonChecked(m_hwnd, IDC_CHECKMSG) == BST_CHECKED);
+ BOOL CheckSnd = (IsDlgButtonChecked(m_hwnd, IDC_CHECKSND) == BST_CHECKED);
+ BOOL CheckIco = (IsDlgButtonChecked(m_hwnd, IDC_CHECKICO) == BST_CHECKED);
+
+ BOOL CheckApp = (IsDlgButtonChecked(m_hwnd, IDC_CHECKAPP) == BST_CHECKED);
+ BOOL CheckKBN = (IsDlgButtonChecked(m_hwnd, IDC_CHECKKBN) == BST_CHECKED);
+ BOOL CheckContact = (IsDlgButtonChecked(m_hwnd, IDC_CHECKCONTACT) == BST_CHECKED);
+ BOOL CheckContactNick = (IsDlgButtonChecked(m_hwnd, IDC_CHECKCONTACTNICK) == BST_CHECKED);
+ BOOL CheckContactNoEvent = (IsDlgButtonChecked(m_hwnd, IDC_CHECKCONTACTNOEVENT) == BST_CHECKED);
+
+ BOOL CheckFSnd = (IsDlgButtonChecked(m_hwnd, IDC_CHECKFSND) == BST_CHECKED);
+ BOOL CheckFMsg = (IsDlgButtonChecked(m_hwnd, IDC_CHECKFMSG) == BST_CHECKED);
+ BOOL CheckFIco = (IsDlgButtonChecked(m_hwnd, IDC_CHECKFICO) == BST_CHECKED);
+
+ BOOL CheckNMsgP = (IsDlgButtonChecked(m_hwnd, IDC_CHECKNMSGP) == BST_CHECKED);
+
+ UINT Port = GetDlgItemInt(m_hwnd, IDC_EDITPORT, &Translated, FALSE);
+ if (!Translated) {
+ MessageBox(m_hwnd, TranslateT("This is not a valid number value"), TranslateT("Input error"), MB_OK);
+ SetFocus(GetDlgItem(m_hwnd, IDC_EDITPORT));
+ return false;
+ }
+
+ UINT Interval = GetDlgItemInt(m_hwnd, IDC_EDITINTERVAL, &Translated, FALSE);
+ if (!Translated) {
+ MessageBox(m_hwnd, TranslateT("This is not a valid number value"), TranslateT("Input error"), MB_OK);
+ SetFocus(GetDlgItem(m_hwnd, IDC_EDITINTERVAL));
+ return false;
+ }
+
+ GetDlgItemTextA(m_hwnd, IDC_EDITAPP, Text, _countof(Text));
+ if (CheckApp && !(Length = mir_strlen(Text))) {
+ MessageBox(m_hwnd, TranslateT("Please select application to run"), TranslateT("Input error"), MB_OK);
+ return false;
+ }
+
+ GetDlgItemTextA(m_hwnd, IDC_COMBOACCOUNT, Text, _countof(Text));
+ if (!(Length = mir_strlen(Text))) {
+ GetDlgItemTextA(m_hwnd, IDC_EDITNAME, Text, _countof(Text));
+ if (!(Length = mir_strlen(Text)))
+ return false;
+ }
+
+ DlgSetItemTextW(m_hwnd, IDC_STTIMELEFT, TranslateT("Please wait while no account is in use."));
+
+ if (nullptr == (ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)Text))) {
+ NewAcc = TRUE;
+ WaitToWriteSO(POP3Plugin->AccountBrowserSO);
+ if (nullptr == (ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_GETNEXTFREEACCOUNT, (WPARAM)POP3Plugin, (LPARAM)YAMN_ACCOUNTVERSION))) {
+ WriteDoneSO(POP3Plugin->AccountBrowserSO);
+ MessageBox(m_hwnd, TranslateT("Cannot allocate memory space for new account"), TranslateT("Memory error"), MB_OK);
+ return false;
+ }
+ DlgEnableAccount(true);
+ }
+ else { // We have to get full access to AccountBrowser, so other iterating thrads cannot get new account until new account is right set
+ WaitToWriteSO(POP3Plugin->AccountBrowserSO);
+ }
+
+ if (WAIT_OBJECT_0 != WaitToWrite(ActualAccount))
+ WriteDoneSO(POP3Plugin->AccountBrowserSO);
+
+ GetDlgItemTextA(m_hwnd, IDC_EDITNAME, Text, _countof(Text));
+ if (!(Length = mir_strlen(Text)))
+ return false;
+ if (nullptr != ActualAccount->Name)
+ delete[] ActualAccount->Name;
+ ActualAccount->Name = new char[mir_strlen(Text) + 1];
+ mir_strcpy(ActualAccount->Name, Text);
+
+ GetDlgItemTextA(m_hwnd, IDC_EDITSERVER, Text, _countof(Text));
+ if (nullptr != ActualAccount->Server->Name)
+ delete[] ActualAccount->Server->Name;
+ ActualAccount->Server->Name = new char[mir_strlen(Text) + 1];
+ mir_strcpy(ActualAccount->Server->Name, Text);
+
+ GetDlgItemTextA(m_hwnd, IDC_EDITLOGIN, Text, _countof(Text));
+ if (nullptr != ActualAccount->Server->Login)
+ delete[] ActualAccount->Server->Login;
+ ActualAccount->Server->Login = new char[mir_strlen(Text) + 1];
+ mir_strcpy(ActualAccount->Server->Login, Text);
+
+ GetDlgItemTextA(m_hwnd, IDC_EDITPASS, Text, _countof(Text));
+ if (nullptr != ActualAccount->Server->Passwd)
+ delete[] ActualAccount->Server->Passwd;
+ ActualAccount->Server->Passwd = new char[mir_strlen(Text) + 1];
+ mir_strcpy(ActualAccount->Server->Passwd, Text);
+
+ GetDlgItemTextW(m_hwnd, IDC_EDITAPP, TextW, _countof(TextW));
+ if (nullptr != ActualAccount->NewMailN.App)
+ delete[] ActualAccount->NewMailN.App;
+ ActualAccount->NewMailN.App = new wchar_t[mir_wstrlen(TextW) + 1];
+ mir_wstrcpy(ActualAccount->NewMailN.App, TextW);
+
+ GetDlgItemTextW(m_hwnd, IDC_EDITAPPPARAM, TextW, _countof(TextW));
+ if (nullptr != ActualAccount->NewMailN.AppParam)
+ delete[] ActualAccount->NewMailN.AppParam;
+ ActualAccount->NewMailN.AppParam = new wchar_t[mir_wstrlen(TextW) + 1];
+ mir_wstrcpy(ActualAccount->NewMailN.AppParam, TextW);
+
+ ActualAccount->Server->Port = Port;
+ ActualAccount->Interval = Interval * 60;
+
+ if (CB_ERR == (index = SendDlgItemMessage(m_hwnd, IDC_COMBOCP, CB_GETCURSEL, 0, 0)))
+ index = CPDEFINDEX;
+ ActualAccount->CP = CodePageNamesSupp[index].CP;
+
+ if (NewAcc)
+ ActualAccount->TimeLeft = Interval * 60;
+
+ BOOL CheckStart = (IsDlgButtonChecked(m_hwnd, IDC_CHECKSTART) == BST_CHECKED);
+ BOOL CheckForce = (IsDlgButtonChecked(m_hwnd, IDC_CHECKFORCE) == BST_CHECKED);
+
+ ActualAccount->Flags =
+ (Check ? YAMN_ACC_ENA : 0) |
+ (CheckSSL ? YAMN_ACC_SSL23 : 0) |
+ (CheckNoTLS ? YAMN_ACC_NOTLS : 0) |
+ (CheckAPOP ? YAMN_ACC_APOP : 0) |
+ (CheckABody ? YAMN_ACC_BODY : 0) |
+ (ActualAccount->Flags & YAMN_ACC_POPN);
+
+ ActualAccount->StatusFlags &= 0xFFFF;
+ ActualAccount->StatusFlags |=
+ (CheckStart ? YAMN_ACC_STARTS : 0) |
+ (CheckForce ? YAMN_ACC_FORCE : 0);
+
+ ActualAccount->NewMailN.Flags =
+ (CheckSnd ? YAMN_ACC_SND : 0) |
+ (CheckMsg ? YAMN_ACC_MSG : 0) |
+ (CheckIco ? YAMN_ACC_ICO : 0) |
+ (ActualAccount->NewMailN.Flags & YAMN_ACC_POP) |
+ (ActualAccount->NewMailN.Flags & YAMN_ACC_POPC) |
+ (CheckApp ? YAMN_ACC_APP : 0) |
+ (CheckKBN ? YAMN_ACC_KBN : 0) |
+ (CheckContact ? YAMN_ACC_CONT : 0) |
+ (CheckContactNick ? YAMN_ACC_CONTNICK : 0) |
+ (CheckContactNoEvent ? YAMN_ACC_CONTNOEVENT : 0) |
+ YAMN_ACC_MSGP; //this is default: when new mail arrives and window was displayed, leave it displayed.
+
+ ActualAccount->NoNewMailN.Flags =
+ (ActualAccount->NoNewMailN.Flags & YAMN_ACC_POP) |
+ (ActualAccount->NoNewMailN.Flags & YAMN_ACC_POPC) |
+ (CheckNMsgP ? YAMN_ACC_MSGP : 0);
+
+ ActualAccount->BadConnectN.Flags =
+ (CheckFSnd ? YAMN_ACC_SND : 0) |
+ (CheckFMsg ? YAMN_ACC_MSG : 0) |
+ (CheckFIco ? YAMN_ACC_ICO : 0) |
+ (ActualAccount->BadConnectN.Flags & YAMN_ACC_POP) |
+ (ActualAccount->BadConnectN.Flags & YAMN_ACC_POPC);
+
+ WriteDone(ActualAccount);
+ WriteDoneSO(POP3Plugin->AccountBrowserSO);
+
+ EnableWindow(GetDlgItem(m_hwnd, IDC_BTNDEL), TRUE);
+
+ DlgSetItemText(m_hwnd, (WPARAM)IDC_STTIMELEFT, nullptr);
+
+ index = SendDlgItemMessage(m_hwnd, IDC_COMBOACCOUNT, CB_GETCURSEL, 0, 0);
+
+ HPOP3ACCOUNT temp = ActualAccount;
+
+ SendDlgItemMessage(m_hwnd, IDC_COMBOACCOUNT, CB_RESETCONTENT, 0, 0);
+ if (POP3Plugin->FirstAccount != nullptr)
+ for (ActualAccount = (HPOP3ACCOUNT)POP3Plugin->FirstAccount; ActualAccount != nullptr; ActualAccount = (HPOP3ACCOUNT)ActualAccount->Next)
+ if (ActualAccount->Name != nullptr)
+ SendDlgItemMessageA(m_hwnd, IDC_COMBOACCOUNT, CB_ADDSTRING, 0, (LPARAM)ActualAccount->Name);
+
+ ActualAccount = temp;
+ SendDlgItemMessage(m_hwnd, IDC_COMBOACCOUNT, CB_SETCURSEL, (WPARAM)index, (LPARAM)ActualAccount->Name);
+
+ WritePOP3Accounts();
+ RefreshContact();
+ return TRUE;
+ }
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Popup options
+
+class CPopupOptsDlg : public CBaseOptionsDlg
+{
+ HPOP3ACCOUNT ActualAccount = nullptr;
+ UCHAR ActualStatus;
+
+ CCtrlCombo cmbAccount, cmbCP;
+ CCtrlCheck chkCol, chkFcol, chkNcol, chkPop, chkFpop, chkNpop;
+ CCtrlButton btnPreview;
+
+ void DlgShowAccountPopup()
+ {
+ if (ActualAccount) {
+ WaitToRead(ActualAccount); //we do not need to check if account is deleted. It is not deleted, because only thread that can delete account is this thread
+ SetDlgItemInt(m_hwnd, IDC_EDITPOPS, ActualAccount->NewMailN.PopupTime, FALSE);
+ SetDlgItemInt(m_hwnd, IDC_EDITNPOPS, ActualAccount->NoNewMailN.PopupTime, FALSE);
+ SetDlgItemInt(m_hwnd, IDC_EDITFPOPS, ActualAccount->BadConnectN.PopupTime, FALSE);
+
+ chkPop.SetState(ActualAccount->NewMailN.Flags & YAMN_ACC_POP);
+ chkCol.SetState(ActualAccount->NewMailN.Flags & YAMN_ACC_POPC);
+ chkNpop.SetState(ActualAccount->NoNewMailN.Flags & YAMN_ACC_POP);
+ chkNcol.SetState(ActualAccount->NoNewMailN.Flags & YAMN_ACC_POPC);
+ chkFpop.SetState(ActualAccount->BadConnectN.Flags & YAMN_ACC_POP ? BST_CHECKED : BST_UNCHECKED);
+ chkFcol.SetState(ActualAccount->BadConnectN.Flags & YAMN_ACC_POPC);
+ CheckDlgButton(m_hwnd, IDC_RADIOPOPN, ActualAccount->Flags & YAMN_ACC_POPN ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_RADIOPOP1, ActualAccount->Flags & YAMN_ACC_POPN ? BST_UNCHECKED : BST_CHECKED);
+ ReadDone(ActualAccount);
+ }
+ else { // default
+ SetDlgItemInt(m_hwnd, IDC_EDITPOPS, 0, FALSE);
+ SetDlgItemInt(m_hwnd, IDC_EDITNPOPS, 0, FALSE);
+ SetDlgItemInt(m_hwnd, IDC_EDITFPOPS, 0, FALSE);
+ chkPop.SetState(true);
+ chkCol.SetState(true);
+ chkNpop.SetState(true);
+ chkNcol.SetState(true);
+ chkFpop.SetState(true);
+ chkFcol.SetState(true);
+ CheckDlgButton(m_hwnd, IDC_RADIOPOPN, BST_UNCHECKED);
+ CheckDlgButton(m_hwnd, IDC_RADIOPOP1, BST_CHECKED);
+ }
+ }
+
+ void DlgEnableAccountPopup(bool bEnable)
+ {
+ chkPop.Enable(bEnable);
+ chkCol.Enable(chkPop.IsChecked() && bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_EDITPOPS), chkPop.IsChecked() && bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CPB), chkCol.IsChecked() && chkPop.IsChecked() && bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CPT), chkCol.IsChecked() && chkPop.IsChecked() && bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_RADIOPOPN), chkPop.IsChecked() && bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_RADIOPOP1), chkPop.IsChecked() && bEnable);
+
+ chkNpop.Enable(bEnable);
+ chkNcol.Enable(chkNpop.IsChecked() && bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_EDITNPOPS), chkNpop.IsChecked() && bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CPNB), chkNcol.IsChecked() && chkNpop.IsChecked() && bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CPNT), chkNcol.IsChecked() && chkNpop.IsChecked() && bEnable);
+
+ chkFpop.Enable(bEnable);
+ chkFcol.Enable(chkFpop.IsChecked() && bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_EDITFPOPS), chkFpop.IsChecked() && bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CPFB), chkFcol.IsChecked() && chkFpop.IsChecked() && bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CPFT), chkFcol.IsChecked() && chkFpop.IsChecked() && bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CHECKAPOP), bEnable);
+ }
+
+ void DlgShowAccountColors()
+ {
+ WaitToRead(ActualAccount); //we do not need to check if account is deleted. It is not deleted, because only thread that can delete account is this thread
+
+ if (ActualAccount->NewMailN.Flags & YAMN_ACC_POPC) {
+ SendDlgItemMessage(m_hwnd, IDC_CPB, CPM_SETCOLOUR, 0, (LPARAM)ActualAccount->NewMailN.PopupB);
+ SendDlgItemMessage(m_hwnd, IDC_CPT, CPM_SETCOLOUR, 0, (LPARAM)ActualAccount->NewMailN.PopupT);
+ }
+ else {
+ SendDlgItemMessage(m_hwnd, IDC_CPB, CPM_SETCOLOUR, 0, (LPARAM)GetSysColor(COLOR_BTNFACE));
+ SendDlgItemMessage(m_hwnd, IDC_CPT, CPM_SETCOLOUR, 0, (LPARAM)GetSysColor(COLOR_WINDOWTEXT));
+ }
+ if (ActualAccount->BadConnectN.Flags & YAMN_ACC_POPC) {
+ SendDlgItemMessage(m_hwnd, IDC_CPFB, CPM_SETCOLOUR, 0, (LPARAM)ActualAccount->BadConnectN.PopupB);
+ SendDlgItemMessage(m_hwnd, IDC_CPFT, CPM_SETCOLOUR, 0, (LPARAM)ActualAccount->BadConnectN.PopupT);
+ }
+ else {
+ SendDlgItemMessage(m_hwnd, IDC_CPFB, CPM_SETCOLOUR, 0, (LPARAM)GetSysColor(COLOR_BTNFACE));
+ SendDlgItemMessage(m_hwnd, IDC_CPFT, CPM_SETCOLOUR, 0, (LPARAM)GetSysColor(COLOR_WINDOWTEXT));
+ }
+ if (ActualAccount->NoNewMailN.Flags & YAMN_ACC_POPC) {
+ SendDlgItemMessage(m_hwnd, IDC_CPNB, CPM_SETCOLOUR, 0, (LPARAM)ActualAccount->NoNewMailN.PopupB);
+ SendDlgItemMessage(m_hwnd, IDC_CPNT, CPM_SETCOLOUR, 0, (LPARAM)ActualAccount->NoNewMailN.PopupT);
+ }
+ else {
+ SendDlgItemMessage(m_hwnd, IDC_CPNB, CPM_SETCOLOUR, 0, (LPARAM)GetSysColor(COLOR_BTNFACE));
+ SendDlgItemMessage(m_hwnd, IDC_CPNT, CPM_SETCOLOUR, 0, (LPARAM)GetSysColor(COLOR_WINDOWTEXT));
+ }
+
+ ReadDone(ActualAccount); //we do not need to check if account is deleted. It is not deleted, because only thread that can delete account is this thread
+ }
+
+public:
+ CPopupOptsDlg() :
+ CBaseOptionsDlg(IDD_POP3ACCOUNTPOPUP),
+ cmbCP(this, IDC_COMBOCP),
+ chkCol(this, IDC_CHECKCOL),
+ chkPop(this, IDC_CHECKPOP),
+ chkFcol(this, IDC_CHECKFCOL),
+ chkFpop(this, IDC_CHECKFPOP),
+ chkNcol(this, IDC_CHECKNCOL),
+ chkNpop(this, IDC_CHECKNPOP),
+ btnPreview(this, IDC_PREVIEW),
+ cmbAccount(this, IDC_COMBOACCOUNT)
+ {
+ chkPop.OnChange = Callback(this, &CPopupOptsDlg::onChange_Pop);
+ chkFpop.OnChange = Callback(this, &CPopupOptsDlg::onChange_Fpop);
+ chkNpop.OnChange = Callback(this, &CPopupOptsDlg::onChange_Npop);
+ chkCol.OnChange = chkFcol.OnChange = chkNcol.OnChange = Callback(this, &CPopupOptsDlg::onChange_Col);
+
+ cmbCP.OnSelChanged = Callback(this, &CPopupOptsDlg::onSelChange_CP);
+
+ btnPreview.OnClick = Callback(this, &CPopupOptsDlg::onClick_Preview);
+
+ cmbAccount.OnKillFocus = Callback(this, &CPopupOptsDlg::onKillFocus_Account);
+ cmbAccount.OnSelChanged = Callback(this, &CPopupOptsDlg::onSelChange_Account);
+ }
+
+ bool OnInitDialog() override
+ {
+ WindowList_Add(pYAMNVar->MessageWnds, m_hwnd);
+
+ DlgEnableAccountPopup(false);
+ DlgShowAccountPopup();
+
+ WaitToReadSO(POP3Plugin->AccountBrowserSO);
+
+ if (POP3Plugin->FirstAccount != nullptr)
+ for (ActualAccount = (HPOP3ACCOUNT)POP3Plugin->FirstAccount; ActualAccount != nullptr; ActualAccount = (HPOP3ACCOUNT)ActualAccount->Next)
+ if (ActualAccount->Name != nullptr)
+ cmbAccount.AddStringA(ActualAccount->Name);
+
+ ReadDoneSO(POP3Plugin->AccountBrowserSO);
+ ActualAccount = nullptr;
+ cmbAccount.SetCurSel(0);
+ return true;
+ }
+
+ void OnDestroy() override
+ {
+ WindowList_Remove(pYAMNVar->MessageWnds, m_hwnd);
+ }
+
+ void onKillFocus_Account(CCtrlCombo *)
+ {
+ GetDlgItemTextA(m_hwnd, IDC_COMBOACCOUNT, DlgInput, _countof(DlgInput));
+ if (nullptr == (ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)DlgInput))) {
+ DlgSetItemText(m_hwnd, (WPARAM)IDC_STTIMELEFT, nullptr);
+ if (mir_strlen(DlgInput))
+ DlgEnableAccountPopup(true);
+ else
+ DlgEnableAccountPopup(false);
+ }
+ else {
+ DlgShowAccount(ActualAccount);
+ DlgShowAccountColors();
+ DlgEnableAccountPopup(true);
+ }
+ }
+
+ void onSelChange_Account(CCtrlCombo *)
+ {
+ int Result = SendDlgItemMessage(m_hwnd, IDC_COMBOACCOUNT, CB_GETCURSEL, 0, 0);
+ if (CB_ERR != Result)
+ SendDlgItemMessageA(m_hwnd, IDC_COMBOACCOUNT, CB_GETLBTEXT, (WPARAM)Result, (LPARAM)DlgInput);
+ if ((Result == CB_ERR) || (nullptr == (ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)DlgInput)))) {
+ DlgSetItemText(m_hwnd, (WPARAM)IDC_STTIMELEFT, nullptr);
+ }
+ else {
+ DlgShowAccount(ActualAccount);
+ DlgShowAccountColors();
+ DlgEnableAccountPopup(true);
+ }
+ }
+
+ void onSelChange_CP(CCtrlCombo *)
+ {
+ int sel = SendDlgItemMessage(m_hwnd, IDC_COMBOCP, CB_GETCURSEL, 0, 0);
+ CPINFOEX info; GetCPInfoEx(CodePageNamesSupp[sel].CP, 0, &info);
+ DlgSetItemTextW(m_hwnd, IDC_STSTATUS, info.CodePageName);
+ }
+
+ void onChange_Col(CCtrlCheck *)
+ {
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CPB), chkCol.IsChecked() && chkPop.IsChecked());
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CPT), chkCol.IsChecked() && chkPop.IsChecked());
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CPNB), chkNcol.IsChecked() && chkNpop.IsChecked());
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CPNT), chkNcol.IsChecked() && chkNpop.IsChecked());
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CPFB), chkFcol.IsChecked() && chkFpop.IsChecked());
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CPFT), chkFcol.IsChecked() && chkFpop.IsChecked());
+ }
+
+ void onClick_Preview(CCtrlButton *)
+ {
+ if (chkPop.IsChecked()) {
+ POPUPDATAW Tester = {};
+ Tester.lchIcon = g_plugin.getIcon(IDI_NEWMAIL);
+ mir_wstrncpy(Tester.lpwzContactName, TranslateT("Account Test"), MAX_CONTACTNAME);
+ mir_wstrncpy(Tester.lpwzText, TranslateT("You have N new mail messages"), MAX_SECONDLINE);
+ if (chkCol.IsChecked()) {
+ Tester.colorBack = SendDlgItemMessage(m_hwnd, IDC_CPB, CPM_GETCOLOUR, 0, 0);
+ Tester.colorText = SendDlgItemMessage(m_hwnd, IDC_CPT, CPM_GETCOLOUR, 0, 0);
+ }
+ else {
+ Tester.colorBack = GetSysColor(COLOR_BTNFACE);
+ Tester.colorText = GetSysColor(COLOR_WINDOWTEXT);
+ }
+ PUAddPopupW(&Tester);
+ }
+
+ if (chkFpop.IsChecked()) {
+ POPUPDATAW TesterF = {};
+ TesterF.lchIcon = g_plugin.getIcon(IDI_BADCONNECT);
+ mir_wstrncpy(TesterF.lpwzContactName, TranslateT("Account Test (failed)"), MAX_CONTACTNAME);
+ mir_wstrncpy(TesterF.lpwzText, TranslateT("Connection failed message"), MAX_SECONDLINE);
+ if (chkFcol.IsChecked()) {
+ TesterF.colorBack = SendDlgItemMessage(m_hwnd, IDC_CPFB, CPM_GETCOLOUR, 0, 0);
+ TesterF.colorText = SendDlgItemMessage(m_hwnd, IDC_CPFT, CPM_GETCOLOUR, 0, 0);
+ }
+ else {
+ TesterF.colorBack = GetSysColor(COLOR_BTNFACE);
+ TesterF.colorText = GetSysColor(COLOR_WINDOWTEXT);
+ }
+ PUAddPopupW(&TesterF);
+ }
+
+ if (chkNpop.IsChecked()) {
+ POPUPDATAW TesterN = {};
+ TesterN.lchIcon = g_plugin.getIcon(IDI_LAUNCHAPP);
+ mir_wstrncpy(TesterN.lpwzContactName, TranslateT("Account Test"), MAX_CONTACTNAME);
+ mir_wstrncpy(TesterN.lpwzText, TranslateT("No new mail message"), MAX_SECONDLINE);
+ if (chkNcol.IsChecked()) {
+ TesterN.colorBack = SendDlgItemMessage(m_hwnd, IDC_CPNB, CPM_GETCOLOUR, 0, 0);
+ TesterN.colorText = SendDlgItemMessage(m_hwnd, IDC_CPNT, CPM_GETCOLOUR, 0, 0);
+ }
+ else {
+ TesterN.colorBack = GetSysColor(COLOR_BTNFACE);
+ TesterN.colorText = GetSysColor(COLOR_WINDOWTEXT);
+ }
+ PUAddPopupW(&TesterN);
+ }
+ }
+
+ void onChange_Pop(CCtrlCheck *)
+ {
+ bool bEnabled = chkPop.IsChecked();
+ chkCol.Enable(bEnabled);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CPB), chkCol.IsChecked() && bEnabled);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CPT), chkCol.IsChecked() && bEnabled);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_RADIOPOPN), bEnabled);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_RADIOPOP1), bEnabled);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_EDITPOPS), bEnabled);
+ }
+
+ void onChange_Fpop(CCtrlCheck *)
+ {
+ bool bEnabled = chkFpop.IsChecked();
+ chkFcol.Enable(bEnabled);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CPFB), chkFcol.IsChecked() && bEnabled);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CPFT), chkFcol.IsChecked() && bEnabled);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_EDITFPOPS), bEnabled);
+ }
+
+ void onChange_Npop(CCtrlCheck *)
+ {
+ bool bEnabled = chkNpop.IsChecked();
+ chkNcol.Enable(bEnabled);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CPNB), chkNcol.IsChecked() && bEnabled);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_CPNT), chkNcol.IsChecked() && bEnabled);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_EDITNPOPS), bEnabled);
+ }
+
+ bool OnApply() override
+ {
+ wchar_t Text[MAX_PATH];
+ if (!GetDlgItemText(m_hwnd, IDC_COMBOACCOUNT, Text, _countof(Text)))
+ return false;
+
+ BOOL CheckPopup = chkPop.IsChecked();
+ BOOL CheckPopupW = chkCol.IsChecked();
+
+ BOOL CheckFPopup = chkFpop.IsChecked();
+ BOOL CheckFPopupW = chkFcol.IsChecked();
+
+ BOOL CheckNPopup = chkNpop.IsChecked();
+ BOOL CheckNPopupW = chkNcol.IsChecked();
+
+ BOOL CheckPopN = (IsDlgButtonChecked(m_hwnd, IDC_RADIOPOPN) == BST_CHECKED);
+
+ BOOL Translated;
+ UINT Time = GetDlgItemInt(m_hwnd, IDC_EDITPOPS, &Translated, FALSE);
+ if (!Translated) {
+ MessageBox(m_hwnd, TranslateT("This is not a valid number value"), TranslateT("Input error"), MB_OK);
+ SetFocus(GetDlgItem(m_hwnd, IDC_EDITPOPS));
+ return false;
+ }
+ UINT TimeN = GetDlgItemInt(m_hwnd, IDC_EDITNPOPS, &Translated, FALSE);
+ if (!Translated) {
+ MessageBox(m_hwnd, TranslateT("This is not a valid number value"), TranslateT("Input error"), MB_OK);
+ SetFocus(GetDlgItem(m_hwnd, IDC_EDITNPOPS));
+ return false;
+ }
+ UINT TimeF = GetDlgItemInt(m_hwnd, IDC_EDITFPOPS, &Translated, FALSE);
+ if (!Translated) {
+ MessageBox(m_hwnd, TranslateT("This is not a valid number value"), TranslateT("Input error"), MB_OK);
+ SetFocus(GetDlgItem(m_hwnd, IDC_EDITFPOPS));
+ return false;
+ }
+
+ DlgSetItemTextW(m_hwnd, IDC_STTIMELEFT, TranslateT("Please wait while no account is in use."));
+
+ ActualAccount->Flags =
+ (ActualAccount->Flags & YAMN_ACC_ENA) |
+ (ActualAccount->Flags & YAMN_ACC_SSL23) |
+ (ActualAccount->Flags & YAMN_ACC_NOTLS) |
+ (ActualAccount->Flags & YAMN_ACC_APOP) |
+ (ActualAccount->Flags & YAMN_ACC_BODY) |
+ (CheckPopN ? YAMN_ACC_POPN : 0);
+
+ ActualAccount->NewMailN.Flags =
+ (ActualAccount->NewMailN.Flags & YAMN_ACC_SND) |
+ (ActualAccount->NewMailN.Flags & YAMN_ACC_MSG) |
+ (ActualAccount->NewMailN.Flags & YAMN_ACC_ICO) |
+ (CheckPopup ? YAMN_ACC_POP : 0) |
+ (CheckPopupW ? YAMN_ACC_POPC : 0) |
+ (ActualAccount->NewMailN.Flags & YAMN_ACC_APP) |
+ (ActualAccount->NewMailN.Flags & YAMN_ACC_KBN) |
+ (ActualAccount->NewMailN.Flags & YAMN_ACC_CONT) |
+ (ActualAccount->NewMailN.Flags & YAMN_ACC_CONTNICK) |
+ (ActualAccount->NewMailN.Flags & YAMN_ACC_CONTNOEVENT) |
+ YAMN_ACC_MSGP;
+
+ ActualAccount->NoNewMailN.Flags =
+ (CheckNPopup ? YAMN_ACC_POP : 0) |
+ (CheckNPopupW ? YAMN_ACC_POPC : 0) |
+ (ActualAccount->NoNewMailN.Flags & YAMN_ACC_MSGP);
+
+ ActualAccount->BadConnectN.Flags =
+ (ActualAccount->BadConnectN.Flags & YAMN_ACC_SND) |
+ (ActualAccount->BadConnectN.Flags & YAMN_ACC_MSG) |
+ (ActualAccount->BadConnectN.Flags & YAMN_ACC_ICO) |
+ (CheckFPopup ? YAMN_ACC_POP : 0) |
+ (CheckFPopupW ? YAMN_ACC_POPC : 0);
+
+ ActualAccount->NewMailN.PopupB = SendDlgItemMessage(m_hwnd, IDC_CPB, CPM_GETCOLOUR, 0, 0);
+ ActualAccount->NewMailN.PopupT = SendDlgItemMessage(m_hwnd, IDC_CPT, CPM_GETCOLOUR, 0, 0);
+ ActualAccount->NewMailN.PopupTime = Time;
+
+ ActualAccount->NoNewMailN.PopupB = SendDlgItemMessage(m_hwnd, IDC_CPNB, CPM_GETCOLOUR, 0, 0);
+ ActualAccount->NoNewMailN.PopupT = SendDlgItemMessage(m_hwnd, IDC_CPNT, CPM_GETCOLOUR, 0, 0);
+ ActualAccount->NoNewMailN.PopupTime = TimeN;
+
+ ActualAccount->BadConnectN.PopupB = SendDlgItemMessage(m_hwnd, IDC_CPFB, CPM_GETCOLOUR, 0, 0);
+ ActualAccount->BadConnectN.PopupT = SendDlgItemMessage(m_hwnd, IDC_CPFT, CPM_GETCOLOUR, 0, 0);
+ ActualAccount->BadConnectN.PopupTime = TimeF;
+
+ WriteDone(ActualAccount);
+ WriteDoneSO(POP3Plugin->AccountBrowserSO);
+
+ WritePOP3Accounts();
+ RefreshContact();
+ return TRUE;
+ }
+};
+
+//--------------------------------------------------------------------------------------------------
+
+int YAMNOptInitSvc(WPARAM wParam, LPARAM)
+{
+ OPTIONSDIALOGPAGE odp = {};
+ odp.szGroup.a = LPGEN("Network");
+ odp.szTitle.a = LPGEN("YAMN");
+ odp.flags = ODPF_BOLDGROUPS;
+
+ odp.szTab.a = LPGEN("Accounts");
+ odp.pDialog = new CAccOptDlg();
+ g_plugin.addOptions(wParam, &odp);
+
+ odp.szTab.a = LPGEN("General");
+ odp.pDialog = new CGeneralOptDlg();
+ g_plugin.addOptions(wParam, &odp);
+
+ odp.szGroup.a = LPGEN("Popups");
+ odp.szTab.a = LPGEN("YAMN");
+ odp.pDialog = new CPopupOptsDlg();
+ g_plugin.addOptions(wParam, &odp);
+ return 0;
+}
diff --git a/protocols/YAMN/src/protoplugin.cpp b/protocols/YAMN/src/protoplugin.cpp
index c6e6a6aecc..b192ac1f5f 100644
--- a/protocols/YAMN/src/protoplugin.cpp
+++ b/protocols/YAMN/src/protoplugin.cpp
@@ -1,172 +1,172 @@
-/*
- * YAMN plugin export functions for protocols
- *
- * (c) majvan 2002-2004
- */
-
-#include "stdafx.h"
-
- //--------------------------------------------------------------------------------------------------
-
-PYAMN_PROTOPLUGINQUEUE FirstProtoPlugin = nullptr;
-
-INT_PTR RegisterProtocolPluginSvc(WPARAM, LPARAM);
-
-//Removes plugin from queue and deletes registration structures
-INT_PTR UnregisterProtocolPlugin(HYAMNPROTOPLUGIN Plugin);
-
-INT_PTR UnregisterProtocolPluginSvc(WPARAM, LPARAM);
-
-//Removes plugins from queue and deletes registration structures
-INT_PTR UnregisterProtoPlugins();
-
-//Sets imported functions for an plugin and therefore it starts plugin to be registered and running
-// Plugin- plugin, which wants to set its functions
-// YAMNFcn- pointer to imported functions with accounts
-// YAMNFcnVer- version of YAMN_PROTOIMPORTFCN, use YAMN_PROTOIMPORTFCNVERSION
-// YAMNMailFcn- pointer to imported functions with mails
-// YAMNMailFcnVer- version of YAMN_MAILIMPORTFCN, use YAMN_MAILIMPORTFCNVERSION
-// returns nonzero if success
-int WINAPI SetProtocolPluginFcnImportFcn(HYAMNPROTOPLUGIN Plugin, PYAMN_PROTOIMPORTFCN YAMNFcn, uint32_t YAMNFcnVer, PYAMN_MAILIMPORTFCN YAMNMailFcn, uint32_t YAMNMailFcnVer);
-
-struct CExportedFunctions ProtoPluginExportedFcn[] =
-{
- {YAMN_SETPROTOCOLPLUGINFCNIMPORTID, (void *)SetProtocolPluginFcnImportFcn},
-};
-
-struct CExportedServices ProtoPluginExportedSvc[] =
-{
- {MS_YAMN_REGISTERPROTOPLUGIN, RegisterProtocolPluginSvc},
- {MS_YAMN_UNREGISTERPROTOPLUGIN, UnregisterProtocolPluginSvc},
- {MS_YAMN_GETFILENAME, GetFileNameSvc},
- {MS_YAMN_DELETEFILENAME, DeleteFileNameSvc},
-};
-
-//--------------------------------------------------------------------------------------------------
-//--------------------------------------------------------------------------------------------------
-
-INT_PTR RegisterProtocolPluginSvc(WPARAM wParam, LPARAM lParam)
-{
- PYAMN_PROTOREGISTRATION Registration = (PYAMN_PROTOREGISTRATION)wParam;
- HYAMNPROTOPLUGIN Plugin;
-
- if (lParam != YAMN_PROTOREGISTRATIONVERSION)
- return 0;
- if ((Registration->Name == nullptr) || (Registration->Ver == nullptr))
- return (INT_PTR)NULL;
- if (nullptr == (Plugin = new YAMN_PROTOPLUGIN))
- return (INT_PTR)NULL;
-
- Plugin->PluginInfo = Registration;
-
- Plugin->FirstAccount = nullptr;
-
- Plugin->AccountBrowserSO = new SWMRG;
- SWMRGInitialize(Plugin->AccountBrowserSO, nullptr);
-
- Plugin->Fcn = nullptr;
- Plugin->MailFcn = nullptr;
-
- return (INT_PTR)Plugin;
-}
-
-int WINAPI SetProtocolPluginFcnImportFcn(HYAMNPROTOPLUGIN Plugin, PYAMN_PROTOIMPORTFCN YAMNFcn, uint32_t YAMNFcnVer, PYAMN_MAILIMPORTFCN YAMNMailFcn, uint32_t YAMNMailFcnVer)
-{
- PYAMN_PROTOPLUGINQUEUE Parser;
-
- if (YAMNFcnVer != YAMN_PROTOIMPORTFCNVERSION)
- return 0;
- if (YAMNMailFcnVer != YAMN_MAILIMPORTFCNVERSION)
- return 0;
- if (YAMNFcn == nullptr)
- return 0;
- if (YAMNMailFcn == nullptr)
- return 0;
-
- Plugin->Fcn = YAMNFcn;
- Plugin->MailFcn = YAMNMailFcn;
-
- mir_cslock lck(PluginRegCS);
- // We add protocol to the protocol list
- for (Parser = FirstProtoPlugin; Parser != nullptr && Parser->Next != nullptr; Parser = Parser->Next);
- if (Parser == nullptr) {
- FirstProtoPlugin = new YAMN_PROTOPLUGINQUEUE;
- Parser = FirstProtoPlugin;
- }
- else {
- Parser->Next = new YAMN_PROTOPLUGINQUEUE;
- Parser = Parser->Next;
- }
-
- Parser->Plugin = Plugin;
- Parser->Next = nullptr;
- return 1;
-}
-
-INT_PTR UnregisterProtocolPlugin(HYAMNPROTOPLUGIN Plugin)
-{
- PYAMN_PROTOPLUGINQUEUE Parser, Found;
-
- if (FirstProtoPlugin->Plugin == Plugin) {
- Found = FirstProtoPlugin;
- FirstProtoPlugin = FirstProtoPlugin->Next;
- }
- else {
- for (Parser = FirstProtoPlugin; (Parser->Next != nullptr) && (Plugin != Parser->Next->Plugin); Parser = Parser->Next);
- if (Parser->Next != nullptr) {
- Found = Parser->Next;
- Parser->Next = Parser->Next->Next;
- }
- else
- Found = nullptr;
- }
- if (Found != nullptr) {
- StopAccounts(Plugin);
- DeleteAccounts(Plugin);
- if (Plugin->Fcn->UnLoadFcn != nullptr)
- Plugin->Fcn->UnLoadFcn((void *)nullptr);
-
- delete Found->Plugin->AccountBrowserSO;
- delete Found->Plugin;
- delete Found;
- }
- else
- return 0;
- return 1;
-}
-
-INT_PTR UnregisterProtocolPluginSvc(WPARAM wParam, LPARAM)
-{
- HYAMNPROTOPLUGIN Plugin = (HYAMNPROTOPLUGIN)wParam;
-
- mir_cslock lck(PluginRegCS);
- UnregisterProtocolPlugin(Plugin);
- return 1;
-}
-
-INT_PTR UnregisterProtoPlugins()
-{
- mir_cslock lck(PluginRegCS);
- // We remove protocols from the protocol list
- while (FirstProtoPlugin != nullptr)
- UnregisterProtocolPlugin(FirstProtoPlugin->Plugin);
- return 1;
-}
-
-INT_PTR GetFileNameSvc(WPARAM wParam, LPARAM)
-{
- wchar_t *FileName = new wchar_t[MAX_PATH];
- if (FileName == nullptr)
- return NULL;
-
- mir_snwprintf(FileName, MAX_PATH, L"%s\\yamn-accounts.%s.%s.book", UserDirectory, (wchar_t *)wParam, ProfileName);
- return (INT_PTR)FileName;
-}
-
-INT_PTR DeleteFileNameSvc(WPARAM wParam, LPARAM)
-{
- if ((wchar_t *)wParam != nullptr)
- delete[](wchar_t *) wParam;
-
- return 0;
-}
+/*
+ * YAMN plugin export functions for protocols
+ *
+ * (c) majvan 2002-2004
+ */
+
+#include "stdafx.h"
+
+ //--------------------------------------------------------------------------------------------------
+
+PYAMN_PROTOPLUGINQUEUE FirstProtoPlugin = nullptr;
+
+INT_PTR RegisterProtocolPluginSvc(WPARAM, LPARAM);
+
+//Removes plugin from queue and deletes registration structures
+INT_PTR UnregisterProtocolPlugin(HYAMNPROTOPLUGIN Plugin);
+
+INT_PTR UnregisterProtocolPluginSvc(WPARAM, LPARAM);
+
+//Removes plugins from queue and deletes registration structures
+INT_PTR UnregisterProtoPlugins();
+
+//Sets imported functions for an plugin and therefore it starts plugin to be registered and running
+// Plugin- plugin, which wants to set its functions
+// YAMNFcn- pointer to imported functions with accounts
+// YAMNFcnVer- version of YAMN_PROTOIMPORTFCN, use YAMN_PROTOIMPORTFCNVERSION
+// YAMNMailFcn- pointer to imported functions with mails
+// YAMNMailFcnVer- version of YAMN_MAILIMPORTFCN, use YAMN_MAILIMPORTFCNVERSION
+// returns nonzero if success
+int WINAPI SetProtocolPluginFcnImportFcn(HYAMNPROTOPLUGIN Plugin, PYAMN_PROTOIMPORTFCN YAMNFcn, uint32_t YAMNFcnVer, PYAMN_MAILIMPORTFCN YAMNMailFcn, uint32_t YAMNMailFcnVer);
+
+struct CExportedFunctions ProtoPluginExportedFcn[] =
+{
+ {YAMN_SETPROTOCOLPLUGINFCNIMPORTID, (void *)SetProtocolPluginFcnImportFcn},
+};
+
+struct CExportedServices ProtoPluginExportedSvc[] =
+{
+ {MS_YAMN_REGISTERPROTOPLUGIN, RegisterProtocolPluginSvc},
+ {MS_YAMN_UNREGISTERPROTOPLUGIN, UnregisterProtocolPluginSvc},
+ {MS_YAMN_GETFILENAME, GetFileNameSvc},
+ {MS_YAMN_DELETEFILENAME, DeleteFileNameSvc},
+};
+
+//--------------------------------------------------------------------------------------------------
+//--------------------------------------------------------------------------------------------------
+
+INT_PTR RegisterProtocolPluginSvc(WPARAM wParam, LPARAM lParam)
+{
+ PYAMN_PROTOREGISTRATION Registration = (PYAMN_PROTOREGISTRATION)wParam;
+ HYAMNPROTOPLUGIN Plugin;
+
+ if (lParam != YAMN_PROTOREGISTRATIONVERSION)
+ return 0;
+ if ((Registration->Name == nullptr) || (Registration->Ver == nullptr))
+ return (INT_PTR)NULL;
+ if (nullptr == (Plugin = new YAMN_PROTOPLUGIN))
+ return (INT_PTR)NULL;
+
+ Plugin->PluginInfo = Registration;
+
+ Plugin->FirstAccount = nullptr;
+
+ Plugin->AccountBrowserSO = new SWMRG;
+ SWMRGInitialize(Plugin->AccountBrowserSO, nullptr);
+
+ Plugin->Fcn = nullptr;
+ Plugin->MailFcn = nullptr;
+
+ return (INT_PTR)Plugin;
+}
+
+int WINAPI SetProtocolPluginFcnImportFcn(HYAMNPROTOPLUGIN Plugin, PYAMN_PROTOIMPORTFCN YAMNFcn, uint32_t YAMNFcnVer, PYAMN_MAILIMPORTFCN YAMNMailFcn, uint32_t YAMNMailFcnVer)
+{
+ PYAMN_PROTOPLUGINQUEUE Parser;
+
+ if (YAMNFcnVer != YAMN_PROTOIMPORTFCNVERSION)
+ return 0;
+ if (YAMNMailFcnVer != YAMN_MAILIMPORTFCNVERSION)
+ return 0;
+ if (YAMNFcn == nullptr)
+ return 0;
+ if (YAMNMailFcn == nullptr)
+ return 0;
+
+ Plugin->Fcn = YAMNFcn;
+ Plugin->MailFcn = YAMNMailFcn;
+
+ mir_cslock lck(PluginRegCS);
+ // We add protocol to the protocol list
+ for (Parser = FirstProtoPlugin; Parser != nullptr && Parser->Next != nullptr; Parser = Parser->Next);
+ if (Parser == nullptr) {
+ FirstProtoPlugin = new YAMN_PROTOPLUGINQUEUE;
+ Parser = FirstProtoPlugin;
+ }
+ else {
+ Parser->Next = new YAMN_PROTOPLUGINQUEUE;
+ Parser = Parser->Next;
+ }
+
+ Parser->Plugin = Plugin;
+ Parser->Next = nullptr;
+ return 1;
+}
+
+INT_PTR UnregisterProtocolPlugin(HYAMNPROTOPLUGIN Plugin)
+{
+ PYAMN_PROTOPLUGINQUEUE Parser, Found;
+
+ if (FirstProtoPlugin->Plugin == Plugin) {
+ Found = FirstProtoPlugin;
+ FirstProtoPlugin = FirstProtoPlugin->Next;
+ }
+ else {
+ for (Parser = FirstProtoPlugin; (Parser->Next != nullptr) && (Plugin != Parser->Next->Plugin); Parser = Parser->Next);
+ if (Parser->Next != nullptr) {
+ Found = Parser->Next;
+ Parser->Next = Parser->Next->Next;
+ }
+ else
+ Found = nullptr;
+ }
+ if (Found != nullptr) {
+ StopAccounts(Plugin);
+ DeleteAccounts(Plugin);
+ if (Plugin->Fcn->UnLoadFcn != nullptr)
+ Plugin->Fcn->UnLoadFcn((void *)nullptr);
+
+ delete Found->Plugin->AccountBrowserSO;
+ delete Found->Plugin;
+ delete Found;
+ }
+ else
+ return 0;
+ return 1;
+}
+
+INT_PTR UnregisterProtocolPluginSvc(WPARAM wParam, LPARAM)
+{
+ HYAMNPROTOPLUGIN Plugin = (HYAMNPROTOPLUGIN)wParam;
+
+ mir_cslock lck(PluginRegCS);
+ UnregisterProtocolPlugin(Plugin);
+ return 1;
+}
+
+INT_PTR UnregisterProtoPlugins()
+{
+ mir_cslock lck(PluginRegCS);
+ // We remove protocols from the protocol list
+ while (FirstProtoPlugin != nullptr)
+ UnregisterProtocolPlugin(FirstProtoPlugin->Plugin);
+ return 1;
+}
+
+INT_PTR GetFileNameSvc(WPARAM wParam, LPARAM)
+{
+ wchar_t *FileName = new wchar_t[MAX_PATH];
+ if (FileName == nullptr)
+ return NULL;
+
+ mir_snwprintf(FileName, MAX_PATH, L"%s\\yamn-accounts.%s.%s.book", UserDirectory, (wchar_t *)wParam, ProfileName);
+ return (INT_PTR)FileName;
+}
+
+INT_PTR DeleteFileNameSvc(WPARAM wParam, LPARAM)
+{
+ if ((wchar_t *)wParam != nullptr)
+ delete[](wchar_t *) wParam;
+
+ return 0;
+}
diff --git a/protocols/YAMN/src/resource.h b/protocols/YAMN/src/resource.h
index 3f6a52fa55..70cb2647c8 100644
--- a/protocols/YAMN/src/resource.h
+++ b/protocols/YAMN/src/resource.h
@@ -1,111 +1,111 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by W:\miranda-ng\protocols\YAMN\res\YAMN.rc
-//
-#define IDI_CHECKMAIL 104
-#define IDI_LAUNCHAPP 105
-#define IDD_DLGVIEWMESSAGES 107
-#define IDD_DLGSHOWMESSAGE 108
-#define IDI_ICOYAMN2 112
-#define IDI_ICOYAMN1 113
-#define IDD_DLGBADCONNECT 115
-#define IDD_POP3ACCOUNTOPT 121
-#define IDD_YAMNOPT 126
-#define IDI_BADCONNECT 131
-#define IDI_ICOTTBUP 138
-#define IDI_NEWMAIL 159
-#define IDD_CHOOSESTATUSMODES 310
-#define IDD_OPTIONS 311
-#define IDD_POP3ACCOUNTPOPUP 312
-#define IDC_EDITSERVER 1000
-#define IDC_EDITPORT 1001
-#define IDC_EDITLOGIN 1002
-#define IDC_EDITPASS 1003
-#define IDC_COMBOACCOUNT 1005
-#define IDC_BTNDEFAULT 1006
-#define IDC_EDITINTERVAL 1007
-#define IDC_CHECKSND 1008
-#define IDC_CHECKMSG 1009
-#define IDC_CHECKAPP 1010
-#define IDC_BTNAPP 1011
-#define IDC_CHECKICO 1012
-#define IDC_CHECK 1013
-#define IDC_BTNDEL 1014
-#define IDC_CHECKFSND 1016
-#define IDC_CHECKFMSG 1017
-#define IDC_CHECKFICO 1018
-#define IDC_CHECKST0 1019
-#define IDC_CHECKST1 1020
-#define IDC_CHECKST2 1021
-#define IDC_CHECKST3 1022
-#define IDC_CHECKST4 1023
-#define IDC_CHECKST5 1024
-#define IDC_CHECKST6 1025
-#define IDC_CHECKST7 1026
-#define IDC_EDITAPP 1027
-#define IDC_CHECKCONTACT 1030
-#define IDC_CHECKCONTACTNICK 1031
-#define IDC_CHECKCONTACTNOEVENT 1032
-#define IDC_STTIMELEFT 1033
-#define IDC_LISTMAILS 1038
-#define IDC_LISTHEADERS 1039
-#define IDC_EDITAPPPARAM 1044
-#define IDC_BTNOK 1047
-#define IDC_COMBOCP 1050
-#define IDC_STATICMSG 1055
-#define IDC_AUTOBODY 1062
-#define IDC_BTNRESET 1063
-#define IDC_CHECKSTART 1064
-#define IDC_STWCHECK 1065
-#define IDC_CHECKFORCE 1066
-#define IDC_RADIOPOP1 1068
-#define IDC_RADIOPOPN 1069
-#define IDC_CPB 1070
-#define IDC_CPNB 1071
-#define IDC_CHECKCOL 1073
-#define IDC_CPT 1074
-#define IDC_CPFB 1075
-#define IDC_CPFT 1076
-#define IDC_CHECKFCOL 1077
-#define IDC_CHECKNCOL 1078
-#define IDC_CPNT 1079
-#define IDC_CHECKPOP 1087
-#define IDC_CHECKNPOP 1088
-#define IDC_CHECKFPOP 1089
-#define IDC_EDITPOPS 1090
-#define IDC_EDITNPOPS 1091
-#define IDC_EDITFPOPS 1092
-#define IDC_GBNEWMAIL 1094
-#define IDC_GBNONEWMAIL 1095
-#define IDC_GBBADCONNECT 1096
-#define IDC_STSTATUS 1102
-#define IDC_CHECKTTB 1117
-#define IDC_CHECKSSL 1117
-#define IDC_CHECKNMSGP 1118
-#define IDC_CHECKNOTLS 1120
-#define IDC_CHECKKBN 1121
-#define IDC_BTNSTATUS 1123
-#define IDC_OPTIONSTAB 1124
-#define IDC_BTNCHECKALL 1125
-#define IDC_CLOSEONDELETE 1127
-#define IDC_LONGDATE 1128
-#define IDC_SMARTDATE 1129
-#define IDC_NOSECONDS 1130
-#define IDC_CHECKAPOP 1200
-#define IDC_STATUSGROUP 1338
-#define IDC_SPLITTER 1400
-#define IDC_EDITBODY 1401
-#define IDC_PREVIEW 1402
-#define IDC_BTNADD 1403
-#define IDC_EDITNAME 1404
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 144
-#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1407
-#define _APS_NEXT_SYMED_VALUE 101
-#endif
-#endif
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by W:\miranda-ng\protocols\YAMN\res\YAMN.rc
+//
+#define IDI_CHECKMAIL 104
+#define IDI_LAUNCHAPP 105
+#define IDD_DLGVIEWMESSAGES 107
+#define IDD_DLGSHOWMESSAGE 108
+#define IDI_ICOYAMN2 112
+#define IDI_ICOYAMN1 113
+#define IDD_DLGBADCONNECT 115
+#define IDD_POP3ACCOUNTOPT 121
+#define IDD_YAMNOPT 126
+#define IDI_BADCONNECT 131
+#define IDI_ICOTTBUP 138
+#define IDI_NEWMAIL 159
+#define IDD_CHOOSESTATUSMODES 310
+#define IDD_OPTIONS 311
+#define IDD_POP3ACCOUNTPOPUP 312
+#define IDC_EDITSERVER 1000
+#define IDC_EDITPORT 1001
+#define IDC_EDITLOGIN 1002
+#define IDC_EDITPASS 1003
+#define IDC_COMBOACCOUNT 1005
+#define IDC_BTNDEFAULT 1006
+#define IDC_EDITINTERVAL 1007
+#define IDC_CHECKSND 1008
+#define IDC_CHECKMSG 1009
+#define IDC_CHECKAPP 1010
+#define IDC_BTNAPP 1011
+#define IDC_CHECKICO 1012
+#define IDC_CHECK 1013
+#define IDC_BTNDEL 1014
+#define IDC_CHECKFSND 1016
+#define IDC_CHECKFMSG 1017
+#define IDC_CHECKFICO 1018
+#define IDC_CHECKST0 1019
+#define IDC_CHECKST1 1020
+#define IDC_CHECKST2 1021
+#define IDC_CHECKST3 1022
+#define IDC_CHECKST4 1023
+#define IDC_CHECKST5 1024
+#define IDC_CHECKST6 1025
+#define IDC_CHECKST7 1026
+#define IDC_EDITAPP 1027
+#define IDC_CHECKCONTACT 1030
+#define IDC_CHECKCONTACTNICK 1031
+#define IDC_CHECKCONTACTNOEVENT 1032
+#define IDC_STTIMELEFT 1033
+#define IDC_LISTMAILS 1038
+#define IDC_LISTHEADERS 1039
+#define IDC_EDITAPPPARAM 1044
+#define IDC_BTNOK 1047
+#define IDC_COMBOCP 1050
+#define IDC_STATICMSG 1055
+#define IDC_AUTOBODY 1062
+#define IDC_BTNRESET 1063
+#define IDC_CHECKSTART 1064
+#define IDC_STWCHECK 1065
+#define IDC_CHECKFORCE 1066
+#define IDC_RADIOPOP1 1068
+#define IDC_RADIOPOPN 1069
+#define IDC_CPB 1070
+#define IDC_CPNB 1071
+#define IDC_CHECKCOL 1073
+#define IDC_CPT 1074
+#define IDC_CPFB 1075
+#define IDC_CPFT 1076
+#define IDC_CHECKFCOL 1077
+#define IDC_CHECKNCOL 1078
+#define IDC_CPNT 1079
+#define IDC_CHECKPOP 1087
+#define IDC_CHECKNPOP 1088
+#define IDC_CHECKFPOP 1089
+#define IDC_EDITPOPS 1090
+#define IDC_EDITNPOPS 1091
+#define IDC_EDITFPOPS 1092
+#define IDC_GBNEWMAIL 1094
+#define IDC_GBNONEWMAIL 1095
+#define IDC_GBBADCONNECT 1096
+#define IDC_STSTATUS 1102
+#define IDC_CHECKTTB 1117
+#define IDC_CHECKSSL 1117
+#define IDC_CHECKNMSGP 1118
+#define IDC_CHECKNOTLS 1120
+#define IDC_CHECKKBN 1121
+#define IDC_BTNSTATUS 1123
+#define IDC_OPTIONSTAB 1124
+#define IDC_BTNCHECKALL 1125
+#define IDC_CLOSEONDELETE 1127
+#define IDC_LONGDATE 1128
+#define IDC_SMARTDATE 1129
+#define IDC_NOSECONDS 1130
+#define IDC_CHECKAPOP 1200
+#define IDC_STATUSGROUP 1338
+#define IDC_SPLITTER 1400
+#define IDC_EDITBODY 1401
+#define IDC_PREVIEW 1402
+#define IDC_BTNADD 1403
+#define IDC_EDITNAME 1404
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 144
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1407
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/protocols/YAMN/src/services.cpp b/protocols/YAMN/src/services.cpp
index 822f5d9f31..361fb01636 100644
--- a/protocols/YAMN/src/services.cpp
+++ b/protocols/YAMN/src/services.cpp
@@ -1,378 +1,378 @@
-#include "stdafx.h"
-
-static INT_PTR Service_GetCaps(WPARAM wParam, LPARAM)
-{
- switch (wParam) {
- case PFLAGNUM_4:
- return PF4_NOCUSTOMAUTH;
- case PFLAG_UNIQUEIDTEXT:
- return (INT_PTR)TranslateT("Nick");
- case PFLAG_MAXLENOFMESSAGE:
- return 400;
- case PFLAGNUM_2:
- case PFLAGNUM_5:
- return PF2_ONLINE | PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND;
- }
-
- return 0;
-}
-
-static INT_PTR Service_GetName(WPARAM wParam, LPARAM lParam)
-{
- mir_strncpy((char *)lParam, YAMN_DBMODULE, wParam);
- return 0;
-}
-
-static INT_PTR Service_LoadIcon(WPARAM wParam, LPARAM)
-{
- if (LOWORD(wParam) == PLI_PROTOCOL)
- return (INT_PTR)CopyIcon(g_plugin.getIcon(IDI_CHECKMAIL)); // noone cares about other than PLI_PROTOCOL
-
- return (INT_PTR)(HICON)NULL;
-}
-
-INT_PTR ClistContactDoubleclicked(WPARAM, LPARAM lParam)
-{
- ContactDoubleclicked(((CLISTEVENT *)lParam)->lParam, lParam);
- return 0;
-}
-
-static int Service_ContactDoubleclicked(WPARAM wParam, LPARAM lParam)
-{
- ContactDoubleclicked(wParam, lParam);
- return 0;
-}
-
-static INT_PTR ContactApplication(WPARAM wParam, LPARAM)
-{
- char *szProto = Proto_GetBaseAccountName(wParam);
- if (mir_strcmp(szProto, YAMN_DBMODULE))
- return 0;
-
- DBVARIANT dbv;
- if (g_plugin.getString(wParam, "Id", &dbv))
- return 0;
-
- CAccount *ActualAccount = (CAccount *)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)dbv.pszVal);
- if (ActualAccount != nullptr) {
- STARTUPINFOW si = {0};
- si.cb = sizeof(si);
-
- if (WAIT_OBJECT_0 == WaitToReadFcn(ActualAccount->AccountAccessSO)) {
- if (ActualAccount->NewMailN.App != nullptr) {
- wchar_t *Command;
- if (ActualAccount->NewMailN.AppParam != nullptr)
- Command = new wchar_t[mir_wstrlen(ActualAccount->NewMailN.App) + mir_wstrlen(ActualAccount->NewMailN.AppParam) + 6];
- else
- Command = new wchar_t[mir_wstrlen(ActualAccount->NewMailN.App) + 6];
-
- if (Command != nullptr) {
- mir_wstrcpy(Command, L"\"");
- mir_wstrcat(Command, ActualAccount->NewMailN.App);
- mir_wstrcat(Command, L"\" ");
- if (ActualAccount->NewMailN.AppParam != nullptr)
- mir_wstrcat(Command, ActualAccount->NewMailN.AppParam);
-
- PROCESS_INFORMATION pi;
- CreateProcessW(nullptr, Command, nullptr, nullptr, FALSE, NORMAL_PRIORITY_CLASS, nullptr, nullptr, &si, &pi);
- delete[] Command;
- }
- }
-
- ReadDoneFcn(ActualAccount->AccountAccessSO);
- }
- }
- db_free(&dbv);
- return 0;
-}
-
-uint32_t WINAPI SWMRGWaitToRead(PSWMRG pSWMRG, uint32_t dwTimeout);
-static INT_PTR AccountMailCheck(WPARAM wParam, LPARAM lParam)
-{
- //This service will check/sincronize the account pointed by wParam
- CAccount *ActualAccount = (CAccount *)wParam;
- // copy/paste make mistakes
- if (ActualAccount != nullptr) {
- //we use event to signal, that running thread has all needed stack parameters copied
- HANDLE ThreadRunningEV = CreateEvent(nullptr, FALSE, FALSE, nullptr);
- if (ThreadRunningEV == nullptr)
- return 0;
- //if we want to close miranda, we get event and do not run pop3 checking anymore
- if (WAIT_OBJECT_0 == WaitForSingleObject(ExitEV, 0))
- return 0;
-
- mir_cslock lck(PluginRegCS);
- if (WAIT_OBJECT_0 != SWMRGWaitToRead(ActualAccount->AccountAccessSO, 0)) {
- }
- else {
- if ((ActualAccount->Flags & YAMN_ACC_ENA) && ActualAccount->Plugin->Fcn->SynchroFcnPtr) {
- CheckParam ParamToPlugin = {YAMN_CHECKVERSION, ThreadRunningEV, ActualAccount, lParam != 0 ? YAMN_FORCECHECK : YAMN_NORMALCHECK, nullptr, nullptr};
-
- ActualAccount->TimeLeft = ActualAccount->Interval;
- DWORD tid;
- HANDLE NewThread = CreateThread(nullptr, 0, (YAMN_STANDARDFCN)ActualAccount->Plugin->Fcn->SynchroFcnPtr, &ParamToPlugin, 0, &tid);
- if (NewThread) {
- WaitForSingleObject(ThreadRunningEV, INFINITE);
- CloseHandle(NewThread);
- }
- }
- ReadDoneFcn(ActualAccount->AccountAccessSO);
- }
- CloseHandle(ThreadRunningEV);
- }
- return 0;
-}
-
-static INT_PTR ContactMailCheck(WPARAM hContact, LPARAM)
-{
- char *szProto = Proto_GetBaseAccountName(hContact);
- if (mir_strcmp(szProto, YAMN_DBMODULE))
- return 0;
-
- DBVARIANT dbv;
- if (g_plugin.getString(hContact, "Id", &dbv))
- return 0;
-
- CAccount *ActualAccount = (CAccount *)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)dbv.pszVal);
- if (ActualAccount != nullptr) {
- //we use event to signal, that running thread has all needed stack parameters copied
- HANDLE ThreadRunningEV;
- if (nullptr == (ThreadRunningEV = CreateEvent(nullptr, FALSE, FALSE, nullptr)))
- return 0;
- //if we want to close miranda, we get event and do not run pop3 checking anymore
- if (WAIT_OBJECT_0 == WaitForSingleObject(ExitEV, 0))
- return 0;
- mir_cslock lck(PluginRegCS);
- if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO)) {
- }
- else {
- if ((ActualAccount->Flags & YAMN_ACC_ENA) && (ActualAccount->StatusFlags & YAMN_ACC_FORCE)) //account cannot be forced to check
- {
- if (ActualAccount->Plugin->Fcn->ForceCheckFcnPtr == nullptr)
- ReadDoneFcn(ActualAccount->AccountAccessSO);
-
- DWORD tid;
- struct CheckParam ParamToPlugin = {YAMN_CHECKVERSION, ThreadRunningEV, ActualAccount, YAMN_FORCECHECK, (void *)nullptr, nullptr};
- if (nullptr == CreateThread(nullptr, 0, (YAMN_STANDARDFCN)ActualAccount->Plugin->Fcn->ForceCheckFcnPtr, &ParamToPlugin, 0, &tid))
- ReadDoneFcn(ActualAccount->AccountAccessSO);
- else
- WaitForSingleObject(ThreadRunningEV, INFINITE);
- }
- ReadDoneFcn(ActualAccount->AccountAccessSO);
- }
- CloseHandle(ThreadRunningEV);
- }
- db_free(&dbv);
- return 0;
-}
-
-/*static*/ void ContactDoubleclicked(WPARAM wParam, LPARAM)
-{
- char *szProto = Proto_GetBaseAccountName(wParam);
- if (mir_strcmp(szProto, YAMN_DBMODULE))
- return;
-
- DBVARIANT dbv;
- if (g_plugin.getString(wParam, "Id", &dbv))
- return;
-
- CAccount *ActualAccount = (CAccount *)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)dbv.pszVal);
- if (ActualAccount != nullptr) {
- if (WAIT_OBJECT_0 == WaitToReadFcn(ActualAccount->AccountAccessSO)) {
- YAMN_MAILBROWSERPARAM Param = {nullptr, ActualAccount, ActualAccount->NewMailN.Flags, ActualAccount->NoNewMailN.Flags, nullptr};
-
- Param.nnflags = Param.nnflags | YAMN_ACC_MSG; //show mails in account even no new mail in account
- Param.nnflags = Param.nnflags & ~YAMN_ACC_POP;
-
- Param.nflags = Param.nflags | YAMN_ACC_MSG; //show mails in account even no new mail in account
- Param.nflags = Param.nflags & ~YAMN_ACC_POP;
-
- RunMailBrowserSvc((WPARAM)&Param, YAMN_MAILBROWSERVERSION);
- ReadDoneFcn(ActualAccount->AccountAccessSO);
- }
- }
- db_free(&dbv);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-HBITMAP LoadBmpFromIcon(HICON hIcon)
-{
- int IconSizeX = 16;
- int IconSizeY = 16;
-
- HBRUSH hBkgBrush = CreateSolidBrush(GetSysColor(COLOR_3DFACE));
-
- BITMAPINFOHEADER bih = {0};
- bih.biSize = sizeof(bih);
- bih.biBitCount = 24;
- bih.biPlanes = 1;
- bih.biCompression = BI_RGB;
- bih.biHeight = IconSizeY;
- bih.biWidth = IconSizeX;
-
- RECT rc;
- rc.top = rc.left = 0;
- rc.right = bih.biWidth;
- rc.bottom = bih.biHeight;
-
- HDC hdc = GetDC(nullptr);
- HBITMAP hBmp = CreateCompatibleBitmap(hdc, bih.biWidth, bih.biHeight);
- HDC hdcMem = CreateCompatibleDC(hdc);
- HBITMAP hoBmp = (HBITMAP)SelectObject(hdcMem, hBmp);
- FillRect(hdcMem, &rc, hBkgBrush);
- DrawIconEx(hdcMem, 0, 0, hIcon, bih.biWidth, bih.biHeight, 0, nullptr, DI_NORMAL);
- SelectObject(hdcMem, hoBmp);
- return hBmp;
-}
-
-int AddTopToolbarIcon(WPARAM, LPARAM)
-{
- if (g_plugin.getByte(YAMN_TTBFCHECK, 1)) {
- if (ServiceExists(MS_TTB_REMOVEBUTTON) && hTTButton == nullptr) {
- TTBButton btn = {};
- btn.pszService = MS_YAMN_FORCECHECK;
- btn.dwFlags = TTBBF_VISIBLE | TTBBF_SHOWTOOLTIP;
- btn.hIconHandleUp = btn.hIconHandleDn = g_plugin.getIconHandle(IDI_CHECKMAIL);
- btn.name = btn.pszTooltipUp = LPGEN("Check mail");
- hTTButton = g_plugin.addTTB(&btn);
- }
- }
- else {
- if (hTTButton != nullptr) {
- CallService(MS_TTB_REMOVEBUTTON, (WPARAM)hTTButton, 0);
- hTTButton = nullptr;
- }
- }
-
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-int Shutdown(WPARAM, LPARAM)
-{
- CallService(MS_TTB_REMOVEBUTTON, (WPARAM)hTTButton, 0);
-
- g_plugin.setDword(YAMN_DBMSGPOSX, HeadPosX);
- g_plugin.setDword(YAMN_DBMSGPOSY, HeadPosY);
- g_plugin.setDword(YAMN_DBMSGSIZEX, HeadSizeX);
- g_plugin.setDword(YAMN_DBMSGSIZEY, HeadSizeY);
- g_plugin.setWord(YAMN_DBMSGPOSSPLIT, HeadSplitPos);
- YAMNVar.Shutdown = TRUE;
- KillTimer(nullptr, SecTimer);
-
- UnregisterProtoPlugins();
- UnregisterFilterPlugins();
- return 0;
-}
-
-int SystemModulesLoaded(WPARAM, LPARAM); //in main.cpp
-
-void HookEvents(void)
-{
- HookEvent(ME_SYSTEM_MODULESLOADED, SystemModulesLoaded);
- HookEvent(ME_TTB_MODULELOADED, AddTopToolbarIcon);
- HookEvent(ME_OPT_INITIALISE, YAMNOptInitSvc);
- HookEvent(ME_SYSTEM_PRESHUTDOWN, Shutdown);
- HookEvent(ME_CLIST_DOUBLECLICKED, Service_ContactDoubleclicked);
-}
-
-void CreateServiceFunctions(void)
-{
- // Standard 'protocol' services
- CreateServiceFunction(YAMN_DBMODULE PS_GETCAPS, Service_GetCaps);
- CreateServiceFunction(YAMN_DBMODULE PS_GETNAME, Service_GetName);
- CreateServiceFunction(YAMN_DBMODULE PS_LOADICON, Service_LoadIcon);
-
- // Function with which protocol plugin can register
- CreateServiceFunction(MS_YAMN_GETFCNPTR, GetFcnPtrSvc);
-
- // Function returns pointer to YAMN variables
- CreateServiceFunction(MS_YAMN_GETVARIABLES, GetVariablesSvc);
-
- // Function with which protocol plugin can register
- CreateServiceFunction(MS_YAMN_REGISTERPROTOPLUGIN, RegisterProtocolPluginSvc);
-
- // Function with which protocol plugin can unregister
- CreateServiceFunction(MS_YAMN_UNREGISTERPROTOPLUGIN, UnregisterProtocolPluginSvc);
-
- // Function creates an account for plugin
- CreateServiceFunction(MS_YAMN_CREATEPLUGINACCOUNT, CreatePluginAccountSvc);
-
- // Function deletes plugin account
- CreateServiceFunction(MS_YAMN_DELETEPLUGINACCOUNT, DeletePluginAccountSvc);
-
- // Finds account for plugin by name
- CreateServiceFunction(MS_YAMN_FINDACCOUNTBYNAME, FindAccountByNameSvc);
-
- // Creates next account for plugin
- CreateServiceFunction(MS_YAMN_GETNEXTFREEACCOUNT, GetNextFreeAccountSvc);
-
- // Function removes account from YAMN queue. Does not delete it from memory
- CreateServiceFunction(MS_YAMN_DELETEACCOUNT, DeleteAccountSvc);
-
- // Function finds accounts for specified plugin
- CreateServiceFunction(MS_YAMN_READACCOUNTS, AddAccountsFromFileSvc);
-
- // Function that stores all plugin mails to one file
- CreateServiceFunction(MS_YAMN_WRITEACCOUNTS, WriteAccountsToFileSvc);
-
- // Function that returns user's filename
- CreateServiceFunction(MS_YAMN_GETFILENAME, GetFileNameSvc);
-
- // Releases unicode string from memory
- CreateServiceFunction(MS_YAMN_DELETEFILENAME, DeleteFileNameSvc);
-
- // Checks mail
- CreateServiceFunction(MS_YAMN_FORCECHECK, ForceCheckSvc);
-
- // Runs YAMN's mail browser
- CreateServiceFunction(MS_YAMN_MAILBROWSER, RunMailBrowserSvc);
-
- // Function creates new mail for plugin
- CreateServiceFunction(MS_YAMN_CREATEACCOUNTMAIL, CreateAccountMailSvc);
-
- // Function deletes plugin account
- CreateServiceFunction(MS_YAMN_DELETEACCOUNTMAIL, DeleteAccountMailSvc);
-
- // Function with which filter plugin can register
- CreateServiceFunction(MS_YAMN_REGISTERFILTERPLUGIN, RegisterFilterPluginSvc);
-
- // Function with which filter plugin can unregister
- CreateServiceFunction(MS_YAMN_UNREGISTERFILTERPLUGIN, UnregisterFilterPluginSvc);
-
- // Function filters mail
- CreateServiceFunction(MS_YAMN_FILTERMAIL, FilterMailSvc);
-
- // Function contact list double click
- CreateServiceFunction(MS_YAMN_CLISTDBLCLICK, ClistContactDoubleclicked);
-
- // Function to check individual account
- CreateServiceFunction(MS_YAMN_ACCOUNTCHECK, AccountMailCheck);
-
- // Function contact list context menu click
- CreateServiceFunction(MS_YAMN_CLISTCONTEXT, ContactMailCheck);
-
- // Function contact list context menu click
- CreateServiceFunction(MS_YAMN_CLISTCONTEXTAPP, ContactApplication);
-}
-
-// Function to put all enabled contact to the Online status
-void RefreshContact(void)
-{
- CAccount *Finder;
- for (Finder = POP3Plugin->FirstAccount; Finder != nullptr; Finder = Finder->Next) {
- if (Finder->hContact != NULL) {
- Contact::Hide(Finder->hContact, !(Finder->Flags & YAMN_ACC_ENA) && (Finder->NewMailN.Flags & YAMN_ACC_CONT));
- }
- else if ((Finder->Flags & YAMN_ACC_ENA) && (Finder->NewMailN.Flags & YAMN_ACC_CONT)) {
- Finder->hContact = db_add_contact();
- Proto_AddToContact(Finder->hContact, YAMN_DBMODULE);
- g_plugin.setString(Finder->hContact, "Id", Finder->Name);
- g_plugin.setString(Finder->hContact, "Nick", Finder->Name);
- g_plugin.setWord(Finder->hContact, "Status", ID_STATUS_ONLINE);
- db_set_s(Finder->hContact, "CList", "StatusMsg", Translate("No new mail message"));
- }
- }
-}
+#include "stdafx.h"
+
+static INT_PTR Service_GetCaps(WPARAM wParam, LPARAM)
+{
+ switch (wParam) {
+ case PFLAGNUM_4:
+ return PF4_NOCUSTOMAUTH;
+ case PFLAG_UNIQUEIDTEXT:
+ return (INT_PTR)TranslateT("Nick");
+ case PFLAG_MAXLENOFMESSAGE:
+ return 400;
+ case PFLAGNUM_2:
+ case PFLAGNUM_5:
+ return PF2_ONLINE | PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND;
+ }
+
+ return 0;
+}
+
+static INT_PTR Service_GetName(WPARAM wParam, LPARAM lParam)
+{
+ mir_strncpy((char *)lParam, YAMN_DBMODULE, wParam);
+ return 0;
+}
+
+static INT_PTR Service_LoadIcon(WPARAM wParam, LPARAM)
+{
+ if (LOWORD(wParam) == PLI_PROTOCOL)
+ return (INT_PTR)CopyIcon(g_plugin.getIcon(IDI_CHECKMAIL)); // noone cares about other than PLI_PROTOCOL
+
+ return (INT_PTR)(HICON)NULL;
+}
+
+INT_PTR ClistContactDoubleclicked(WPARAM, LPARAM lParam)
+{
+ ContactDoubleclicked(((CLISTEVENT *)lParam)->lParam, lParam);
+ return 0;
+}
+
+static int Service_ContactDoubleclicked(WPARAM wParam, LPARAM lParam)
+{
+ ContactDoubleclicked(wParam, lParam);
+ return 0;
+}
+
+static INT_PTR ContactApplication(WPARAM wParam, LPARAM)
+{
+ char *szProto = Proto_GetBaseAccountName(wParam);
+ if (mir_strcmp(szProto, YAMN_DBMODULE))
+ return 0;
+
+ DBVARIANT dbv;
+ if (g_plugin.getString(wParam, "Id", &dbv))
+ return 0;
+
+ CAccount *ActualAccount = (CAccount *)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)dbv.pszVal);
+ if (ActualAccount != nullptr) {
+ STARTUPINFOW si = {0};
+ si.cb = sizeof(si);
+
+ if (WAIT_OBJECT_0 == WaitToReadFcn(ActualAccount->AccountAccessSO)) {
+ if (ActualAccount->NewMailN.App != nullptr) {
+ wchar_t *Command;
+ if (ActualAccount->NewMailN.AppParam != nullptr)
+ Command = new wchar_t[mir_wstrlen(ActualAccount->NewMailN.App) + mir_wstrlen(ActualAccount->NewMailN.AppParam) + 6];
+ else
+ Command = new wchar_t[mir_wstrlen(ActualAccount->NewMailN.App) + 6];
+
+ if (Command != nullptr) {
+ mir_wstrcpy(Command, L"\"");
+ mir_wstrcat(Command, ActualAccount->NewMailN.App);
+ mir_wstrcat(Command, L"\" ");
+ if (ActualAccount->NewMailN.AppParam != nullptr)
+ mir_wstrcat(Command, ActualAccount->NewMailN.AppParam);
+
+ PROCESS_INFORMATION pi;
+ CreateProcessW(nullptr, Command, nullptr, nullptr, FALSE, NORMAL_PRIORITY_CLASS, nullptr, nullptr, &si, &pi);
+ delete[] Command;
+ }
+ }
+
+ ReadDoneFcn(ActualAccount->AccountAccessSO);
+ }
+ }
+ db_free(&dbv);
+ return 0;
+}
+
+uint32_t WINAPI SWMRGWaitToRead(PSWMRG pSWMRG, uint32_t dwTimeout);
+static INT_PTR AccountMailCheck(WPARAM wParam, LPARAM lParam)
+{
+ //This service will check/sincronize the account pointed by wParam
+ CAccount *ActualAccount = (CAccount *)wParam;
+ // copy/paste make mistakes
+ if (ActualAccount != nullptr) {
+ //we use event to signal, that running thread has all needed stack parameters copied
+ HANDLE ThreadRunningEV = CreateEvent(nullptr, FALSE, FALSE, nullptr);
+ if (ThreadRunningEV == nullptr)
+ return 0;
+ //if we want to close miranda, we get event and do not run pop3 checking anymore
+ if (WAIT_OBJECT_0 == WaitForSingleObject(ExitEV, 0))
+ return 0;
+
+ mir_cslock lck(PluginRegCS);
+ if (WAIT_OBJECT_0 != SWMRGWaitToRead(ActualAccount->AccountAccessSO, 0)) {
+ }
+ else {
+ if ((ActualAccount->Flags & YAMN_ACC_ENA) && ActualAccount->Plugin->Fcn->SynchroFcnPtr) {
+ CheckParam ParamToPlugin = {YAMN_CHECKVERSION, ThreadRunningEV, ActualAccount, lParam != 0 ? YAMN_FORCECHECK : YAMN_NORMALCHECK, nullptr, nullptr};
+
+ ActualAccount->TimeLeft = ActualAccount->Interval;
+ DWORD tid;
+ HANDLE NewThread = CreateThread(nullptr, 0, (YAMN_STANDARDFCN)ActualAccount->Plugin->Fcn->SynchroFcnPtr, &ParamToPlugin, 0, &tid);
+ if (NewThread) {
+ WaitForSingleObject(ThreadRunningEV, INFINITE);
+ CloseHandle(NewThread);
+ }
+ }
+ ReadDoneFcn(ActualAccount->AccountAccessSO);
+ }
+ CloseHandle(ThreadRunningEV);
+ }
+ return 0;
+}
+
+static INT_PTR ContactMailCheck(WPARAM hContact, LPARAM)
+{
+ char *szProto = Proto_GetBaseAccountName(hContact);
+ if (mir_strcmp(szProto, YAMN_DBMODULE))
+ return 0;
+
+ DBVARIANT dbv;
+ if (g_plugin.getString(hContact, "Id", &dbv))
+ return 0;
+
+ CAccount *ActualAccount = (CAccount *)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)dbv.pszVal);
+ if (ActualAccount != nullptr) {
+ //we use event to signal, that running thread has all needed stack parameters copied
+ HANDLE ThreadRunningEV;
+ if (nullptr == (ThreadRunningEV = CreateEvent(nullptr, FALSE, FALSE, nullptr)))
+ return 0;
+ //if we want to close miranda, we get event and do not run pop3 checking anymore
+ if (WAIT_OBJECT_0 == WaitForSingleObject(ExitEV, 0))
+ return 0;
+ mir_cslock lck(PluginRegCS);
+ if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO)) {
+ }
+ else {
+ if ((ActualAccount->Flags & YAMN_ACC_ENA) && (ActualAccount->StatusFlags & YAMN_ACC_FORCE)) //account cannot be forced to check
+ {
+ if (ActualAccount->Plugin->Fcn->ForceCheckFcnPtr == nullptr)
+ ReadDoneFcn(ActualAccount->AccountAccessSO);
+
+ DWORD tid;
+ struct CheckParam ParamToPlugin = {YAMN_CHECKVERSION, ThreadRunningEV, ActualAccount, YAMN_FORCECHECK, (void *)nullptr, nullptr};
+ if (nullptr == CreateThread(nullptr, 0, (YAMN_STANDARDFCN)ActualAccount->Plugin->Fcn->ForceCheckFcnPtr, &ParamToPlugin, 0, &tid))
+ ReadDoneFcn(ActualAccount->AccountAccessSO);
+ else
+ WaitForSingleObject(ThreadRunningEV, INFINITE);
+ }
+ ReadDoneFcn(ActualAccount->AccountAccessSO);
+ }
+ CloseHandle(ThreadRunningEV);
+ }
+ db_free(&dbv);
+ return 0;
+}
+
+/*static*/ void ContactDoubleclicked(WPARAM wParam, LPARAM)
+{
+ char *szProto = Proto_GetBaseAccountName(wParam);
+ if (mir_strcmp(szProto, YAMN_DBMODULE))
+ return;
+
+ DBVARIANT dbv;
+ if (g_plugin.getString(wParam, "Id", &dbv))
+ return;
+
+ CAccount *ActualAccount = (CAccount *)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)dbv.pszVal);
+ if (ActualAccount != nullptr) {
+ if (WAIT_OBJECT_0 == WaitToReadFcn(ActualAccount->AccountAccessSO)) {
+ YAMN_MAILBROWSERPARAM Param = {nullptr, ActualAccount, ActualAccount->NewMailN.Flags, ActualAccount->NoNewMailN.Flags, nullptr};
+
+ Param.nnflags = Param.nnflags | YAMN_ACC_MSG; //show mails in account even no new mail in account
+ Param.nnflags = Param.nnflags & ~YAMN_ACC_POP;
+
+ Param.nflags = Param.nflags | YAMN_ACC_MSG; //show mails in account even no new mail in account
+ Param.nflags = Param.nflags & ~YAMN_ACC_POP;
+
+ RunMailBrowserSvc((WPARAM)&Param, YAMN_MAILBROWSERVERSION);
+ ReadDoneFcn(ActualAccount->AccountAccessSO);
+ }
+ }
+ db_free(&dbv);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+HBITMAP LoadBmpFromIcon(HICON hIcon)
+{
+ int IconSizeX = 16;
+ int IconSizeY = 16;
+
+ HBRUSH hBkgBrush = CreateSolidBrush(GetSysColor(COLOR_3DFACE));
+
+ BITMAPINFOHEADER bih = {0};
+ bih.biSize = sizeof(bih);
+ bih.biBitCount = 24;
+ bih.biPlanes = 1;
+ bih.biCompression = BI_RGB;
+ bih.biHeight = IconSizeY;
+ bih.biWidth = IconSizeX;
+
+ RECT rc;
+ rc.top = rc.left = 0;
+ rc.right = bih.biWidth;
+ rc.bottom = bih.biHeight;
+
+ HDC hdc = GetDC(nullptr);
+ HBITMAP hBmp = CreateCompatibleBitmap(hdc, bih.biWidth, bih.biHeight);
+ HDC hdcMem = CreateCompatibleDC(hdc);
+ HBITMAP hoBmp = (HBITMAP)SelectObject(hdcMem, hBmp);
+ FillRect(hdcMem, &rc, hBkgBrush);
+ DrawIconEx(hdcMem, 0, 0, hIcon, bih.biWidth, bih.biHeight, 0, nullptr, DI_NORMAL);
+ SelectObject(hdcMem, hoBmp);
+ return hBmp;
+}
+
+int AddTopToolbarIcon(WPARAM, LPARAM)
+{
+ if (g_plugin.getByte(YAMN_TTBFCHECK, 1)) {
+ if (ServiceExists(MS_TTB_REMOVEBUTTON) && hTTButton == nullptr) {
+ TTBButton btn = {};
+ btn.pszService = MS_YAMN_FORCECHECK;
+ btn.dwFlags = TTBBF_VISIBLE | TTBBF_SHOWTOOLTIP;
+ btn.hIconHandleUp = btn.hIconHandleDn = g_plugin.getIconHandle(IDI_CHECKMAIL);
+ btn.name = btn.pszTooltipUp = LPGEN("Check mail");
+ hTTButton = g_plugin.addTTB(&btn);
+ }
+ }
+ else {
+ if (hTTButton != nullptr) {
+ CallService(MS_TTB_REMOVEBUTTON, (WPARAM)hTTButton, 0);
+ hTTButton = nullptr;
+ }
+ }
+
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+int Shutdown(WPARAM, LPARAM)
+{
+ CallService(MS_TTB_REMOVEBUTTON, (WPARAM)hTTButton, 0);
+
+ g_plugin.setDword(YAMN_DBMSGPOSX, HeadPosX);
+ g_plugin.setDword(YAMN_DBMSGPOSY, HeadPosY);
+ g_plugin.setDword(YAMN_DBMSGSIZEX, HeadSizeX);
+ g_plugin.setDword(YAMN_DBMSGSIZEY, HeadSizeY);
+ g_plugin.setWord(YAMN_DBMSGPOSSPLIT, HeadSplitPos);
+ YAMNVar.Shutdown = TRUE;
+ KillTimer(nullptr, SecTimer);
+
+ UnregisterProtoPlugins();
+ UnregisterFilterPlugins();
+ return 0;
+}
+
+int SystemModulesLoaded(WPARAM, LPARAM); //in main.cpp
+
+void HookEvents(void)
+{
+ HookEvent(ME_SYSTEM_MODULESLOADED, SystemModulesLoaded);
+ HookEvent(ME_TTB_MODULELOADED, AddTopToolbarIcon);
+ HookEvent(ME_OPT_INITIALISE, YAMNOptInitSvc);
+ HookEvent(ME_SYSTEM_PRESHUTDOWN, Shutdown);
+ HookEvent(ME_CLIST_DOUBLECLICKED, Service_ContactDoubleclicked);
+}
+
+void CreateServiceFunctions(void)
+{
+ // Standard 'protocol' services
+ CreateServiceFunction(YAMN_DBMODULE PS_GETCAPS, Service_GetCaps);
+ CreateServiceFunction(YAMN_DBMODULE PS_GETNAME, Service_GetName);
+ CreateServiceFunction(YAMN_DBMODULE PS_LOADICON, Service_LoadIcon);
+
+ // Function with which protocol plugin can register
+ CreateServiceFunction(MS_YAMN_GETFCNPTR, GetFcnPtrSvc);
+
+ // Function returns pointer to YAMN variables
+ CreateServiceFunction(MS_YAMN_GETVARIABLES, GetVariablesSvc);
+
+ // Function with which protocol plugin can register
+ CreateServiceFunction(MS_YAMN_REGISTERPROTOPLUGIN, RegisterProtocolPluginSvc);
+
+ // Function with which protocol plugin can unregister
+ CreateServiceFunction(MS_YAMN_UNREGISTERPROTOPLUGIN, UnregisterProtocolPluginSvc);
+
+ // Function creates an account for plugin
+ CreateServiceFunction(MS_YAMN_CREATEPLUGINACCOUNT, CreatePluginAccountSvc);
+
+ // Function deletes plugin account
+ CreateServiceFunction(MS_YAMN_DELETEPLUGINACCOUNT, DeletePluginAccountSvc);
+
+ // Finds account for plugin by name
+ CreateServiceFunction(MS_YAMN_FINDACCOUNTBYNAME, FindAccountByNameSvc);
+
+ // Creates next account for plugin
+ CreateServiceFunction(MS_YAMN_GETNEXTFREEACCOUNT, GetNextFreeAccountSvc);
+
+ // Function removes account from YAMN queue. Does not delete it from memory
+ CreateServiceFunction(MS_YAMN_DELETEACCOUNT, DeleteAccountSvc);
+
+ // Function finds accounts for specified plugin
+ CreateServiceFunction(MS_YAMN_READACCOUNTS, AddAccountsFromFileSvc);
+
+ // Function that stores all plugin mails to one file
+ CreateServiceFunction(MS_YAMN_WRITEACCOUNTS, WriteAccountsToFileSvc);
+
+ // Function that returns user's filename
+ CreateServiceFunction(MS_YAMN_GETFILENAME, GetFileNameSvc);
+
+ // Releases unicode string from memory
+ CreateServiceFunction(MS_YAMN_DELETEFILENAME, DeleteFileNameSvc);
+
+ // Checks mail
+ CreateServiceFunction(MS_YAMN_FORCECHECK, ForceCheckSvc);
+
+ // Runs YAMN's mail browser
+ CreateServiceFunction(MS_YAMN_MAILBROWSER, RunMailBrowserSvc);
+
+ // Function creates new mail for plugin
+ CreateServiceFunction(MS_YAMN_CREATEACCOUNTMAIL, CreateAccountMailSvc);
+
+ // Function deletes plugin account
+ CreateServiceFunction(MS_YAMN_DELETEACCOUNTMAIL, DeleteAccountMailSvc);
+
+ // Function with which filter plugin can register
+ CreateServiceFunction(MS_YAMN_REGISTERFILTERPLUGIN, RegisterFilterPluginSvc);
+
+ // Function with which filter plugin can unregister
+ CreateServiceFunction(MS_YAMN_UNREGISTERFILTERPLUGIN, UnregisterFilterPluginSvc);
+
+ // Function filters mail
+ CreateServiceFunction(MS_YAMN_FILTERMAIL, FilterMailSvc);
+
+ // Function contact list double click
+ CreateServiceFunction(MS_YAMN_CLISTDBLCLICK, ClistContactDoubleclicked);
+
+ // Function to check individual account
+ CreateServiceFunction(MS_YAMN_ACCOUNTCHECK, AccountMailCheck);
+
+ // Function contact list context menu click
+ CreateServiceFunction(MS_YAMN_CLISTCONTEXT, ContactMailCheck);
+
+ // Function contact list context menu click
+ CreateServiceFunction(MS_YAMN_CLISTCONTEXTAPP, ContactApplication);
+}
+
+// Function to put all enabled contact to the Online status
+void RefreshContact(void)
+{
+ CAccount *Finder;
+ for (Finder = POP3Plugin->FirstAccount; Finder != nullptr; Finder = Finder->Next) {
+ if (Finder->hContact != NULL) {
+ Contact::Hide(Finder->hContact, !(Finder->Flags & YAMN_ACC_ENA) && (Finder->NewMailN.Flags & YAMN_ACC_CONT));
+ }
+ else if ((Finder->Flags & YAMN_ACC_ENA) && (Finder->NewMailN.Flags & YAMN_ACC_CONT)) {
+ Finder->hContact = db_add_contact();
+ Proto_AddToContact(Finder->hContact, YAMN_DBMODULE);
+ g_plugin.setString(Finder->hContact, "Id", Finder->Name);
+ g_plugin.setString(Finder->hContact, "Nick", Finder->Name);
+ g_plugin.setWord(Finder->hContact, "Status", ID_STATUS_ONLINE);
+ db_set_s(Finder->hContact, "CList", "StatusMsg", Translate("No new mail message"));
+ }
+ }
+}
diff --git a/protocols/YAMN/src/stdafx.h b/protocols/YAMN/src/stdafx.h
index 05681d467b..38f1c1b5fe 100644
--- a/protocols/YAMN/src/stdafx.h
+++ b/protocols/YAMN/src/stdafx.h
@@ -1,253 +1,253 @@
-
-#ifndef __YAMN_H
-#define __YAMN_H
-
-#define VC_EXTRALEAN
-
-#include <windows.h>
-#include <windowsx.h>
-#include <commctrl.h>
-
-#include <newpluginapi.h>
-#include <m_clistint.h>
-#include <m_contacts.h>
-#include <m_database.h>
-#include <m_hotkeys.h>
-#include <m_icolib.h>
-#include <m_langpack.h>
-#include <m_messages.h>
-#include <m_netlib.h>
-#include <m_options.h>
-#include <m_popup.h>
-#include <m_protosvc.h>
-#include <m_skin.h>
-#include <m_timezones.h>
-
-#include <m_toptoolbar.h>
-#include <m_kbdnotify.h>
-#include <m_filterplugin.h>
-#include <m_yamn.h>
-#include <m_protoplugin.h>
-#include <m_folders.h>
-
-#include "main.h"
-#include "mails/decode.h"
-#include "browser/browser.h"
-#include "resource.h"
-#include "debug.h"
-#include "version.h"
-#include "proto/netclient.h"
-#include "proto/netlib.h"
-#include "proto/pop3/pop3.h"
-#include "proto/pop3/pop3comm.h"
-
-struct CMPlugin : public PLUGIN<CMPlugin>
-{
- CMPlugin();
-
- int Load() override;
- int Unload() override;
-};
-
-// From services.cpp
-void CreateServiceFunctions(void);
-void HookEvents(void);
-void RefreshContact(void);
-void ContactDoubleclicked(WPARAM wParam, LPARAM lParam);
-INT_PTR ClistContactDoubleclicked(WPARAM wParam, LPARAM lParam);
-
-extern mir_cs PluginRegCS;
-extern SCOUNTER *AccountWriterSO;
-extern HANDLE ExitEV;
-extern HANDLE WriteToFileEV;
-
-// From debug.cpp
-#ifdef _DEBUG
-void InitDebug();
-void UnInitDebug();
-#endif
-
-// From yamn.cpp
-INT_PTR GetFcnPtrSvc(WPARAM wParam, LPARAM lParam);
-INT_PTR GetVariablesSvc(WPARAM, LPARAM);
-void CALLBACK TimerProc(HWND, UINT, UINT_PTR, DWORD);
-INT_PTR ForceCheckSvc(WPARAM, LPARAM);
-
-extern struct YAMNExportedFcns *pYAMNFcn;
-
-// From account.cpp
-INT_PTR CreatePluginAccountSvc(WPARAM wParam, LPARAM lParam);
-INT_PTR DeletePluginAccountSvc(WPARAM wParam, LPARAM);
-int InitAccount(CAccount *Which);
-void DeInitAccount(CAccount *Which);
-void StopSignalFcn(CAccount *Which);
-void CodeDecodeString(char *Dest, BOOL Encrypt);
-uint32_t FileToMemory(wchar_t *FileName, char **MemFile, char **End);
-
-#if defined(DEBUG_FILEREAD) || defined(DEBUG_FILEREADMESSAGES)
-uint32_t ReadStringFromMemory(char **Parser,char *End,char **StoreTo,char *DebugString);
-#endif
-uint32_t ReadStringFromMemory(char **Parser, char *End, char **StoreTo);
-uint32_t ReadMessagesFromMemory(CAccount *Which, char **Parser, char *End);
-uint32_t ReadAccountFromMemory(CAccount *Which, char **Parser, wchar_t *End);
-INT_PTR AddAccountsFromFileSvc(WPARAM wParam, LPARAM lParam);
-
-uint32_t WriteStringToFile(HANDLE File, char *Source);
-uint32_t WriteStringToFileW(HANDLE File, wchar_t *Source);
-
-
-DWORD WriteMessagesToFile(HANDLE File, CAccount *Which);
-DWORD WINAPI WritePOP3Accounts();
-INT_PTR WriteAccountsToFileSvc(WPARAM wParam, LPARAM lParam);
-INT_PTR FindAccountByNameSvc(WPARAM wParam, LPARAM lParam);
-INT_PTR GetNextFreeAccountSvc(WPARAM wParam, LPARAM lParam);
-
-INT_PTR DeleteAccountSvc(WPARAM wParam, LPARAM);
-void __cdecl DeleteAccountInBackground(void *Which);
-int StopAccounts(HYAMNPROTOPLUGIN Plugin);
-int WaitForAllAccounts(HYAMNPROTOPLUGIN Plugin, BOOL GetAccountBrowserAccess = FALSE);
-int DeleteAccounts(HYAMNPROTOPLUGIN Plugin);
-
-void WINAPI GetStatusFcn(CAccount *Which, wchar_t *Value);
-void WINAPI SetStatusFcn(CAccount *Which, wchar_t *Value);
-
-INT_PTR UnregisterProtoPlugins();
-INT_PTR RegisterProtocolPluginSvc(WPARAM, LPARAM);
-INT_PTR UnregisterProtocolPluginSvc(WPARAM, LPARAM);
-INT_PTR GetFileNameSvc(WPARAM, LPARAM);
-INT_PTR DeleteFileNameSvc(WPARAM, LPARAM);
-
-//From filterplugin.cpp
-//struct CExportedFunctions FilterPluginExported[];
-INT_PTR UnregisterFilterPlugins();
-INT_PTR RegisterFilterPluginSvc(WPARAM, LPARAM);
-INT_PTR UnregisterFilterPluginSvc(WPARAM, LPARAM);
-INT_PTR FilterMailSvc(WPARAM, LPARAM);
-
-//From mails.cpp (MIME)
-//struct CExportedFunctions MailExported[];
-INT_PTR CreateAccountMailSvc(WPARAM wParam, LPARAM lParam);
-INT_PTR DeleteAccountMailSvc(WPARAM wParam, LPARAM lParam);
-INT_PTR LoadMailDataSvc(WPARAM wParam, LPARAM lParam);
-INT_PTR UnloadMailDataSvc(WPARAM wParam, LPARAM);
-INT_PTR SaveMailDataSvc(WPARAM wParam, LPARAM lParam);
-
-//From mime.cpp
-//void WINAPI ExtractHeaderFcn(char *,int,uint16_t,HYAMNMAIL); //already in MailExported
-struct _tcptable
-{
- char *NameBase, *NameSub;
- BOOLEAN isValid;
- unsigned short int CP;
-};
-extern struct _tcptable CodePageNamesAll[]; // in mime/decode.cpp
-extern int CPLENALL;
-extern struct _tcptable *CodePageNamesSupp; // in mime/decode.cpp
-extern int CPLENSUPP;
-
-extern int PosX, PosY, SizeX, SizeY;
-extern int HeadPosX, HeadPosY, HeadSizeX, HeadSizeY, HeadSplitPos;
-
-//#define CPDEFINDEX 63 //ISO-8859-1
-#define CPDEFINDEX 0 //ACP
-
-//From pop3comm.cpp
-int RegisterPOP3Plugin(WPARAM, LPARAM);
-
-//From mailbrowser.cpp
-INT_PTR RunMailBrowserSvc(WPARAM, LPARAM);
-
-//From badconnect.cpp
-int RunBadConnection(CAccount *acc, UINT_PTR iErrorCode, void *pUserInfo);
-
-//From YAMNopts.cpp
-int YAMNOptInitSvc(WPARAM, LPARAM);
-
-//From main.cpp
-int PostLoad(WPARAM, LPARAM); //Executed after all plugins loaded YAMN reads mails from file and notify every protocol it should set its functions
-int Shutdown(WPARAM, LPARAM); //Executed before Miranda is going to shutdown
-int AddTopToolbarIcon(WPARAM, LPARAM); //Executed when TopToolBar plugin loaded Adds bitmap to toolbar
-
-extern wchar_t UserDirectory[]; //e.g. "F:\WINNT\Profiles\UserXYZ"
-extern wchar_t ProfileName[]; //e.g. "majvan"
-extern SWMRG *AccountBrowserSO;
-extern YAMN_VARIABLES YAMNVar;
-extern HANDLE hNewMailHook;
-extern HANDLE hTTButton;
-extern HCURSOR hCurSplitNS, hCurSplitWE;
-extern UINT SecTimer;
-
-//From synchro.cpp
-void WINAPI DeleteMessagesToEndFcn(CAccount *Account, HYAMNMAIL From);
-uint32_t WINAPI WaitToWriteFcn(PSWMRG SObject, PSCOUNTER SCounter = nullptr);
-void WINAPI WriteDoneFcn(PSWMRG SObject, PSCOUNTER SCounter = nullptr);
-uint32_t WINAPI WaitToReadFcn(PSWMRG SObject);
-void WINAPI ReadDoneFcn(PSWMRG SObject);
-uint32_t WINAPI SCIncFcn(PSCOUNTER SCounter);
-uint32_t WINAPI SCDecFcn(PSCOUNTER SCounter);
-BOOL WINAPI SWMRGInitialize(PSWMRG, wchar_t *);
-void WINAPI SWMRGDelete(PSWMRG);
-uint32_t WINAPI SWMRGWaitToWrite(PSWMRG pSWMRG, uint32_t dwTimeout);
-void WINAPI SWMRGDoneWriting(PSWMRG pSWMRG);
-uint32_t WINAPI SWMRGWaitToRead(PSWMRG pSWMRG, uint32_t dwTimeout);
-void WINAPI SWMRGDoneReading(PSWMRG pSWMRG);
-
-//From mails.cpp
-void WINAPI DeleteMessageFromQueueFcn(HYAMNMAIL *From, HYAMNMAIL Which, int mode);
-void WINAPI SetRemoveFlagsInQueueFcn(HYAMNMAIL From, uint32_t FlagsSet, uint32_t FlagsNotSet, uint32_t FlagsToSet, int mode);
-
-//From mime.cpp
-void ExtractHeader(struct CMimeItem *items, int &CP, struct CHeader *head);
-void ExtractShortHeader(struct CMimeItem *items, struct CShortHeader *head);
-void DeleteHeaderContent(struct CHeader *head);
-void DeleteShortHeaderContent(struct CShortHeader *head);
-char *ExtractFromContentType(char *ContentType, char *value);
-wchar_t *ParseMultipartBody(char *src, char *bond);
-
-//From account.cpp
-void WINAPI GetStatusFcn(CAccount *Which, wchar_t *Value);
-
-extern HYAMNPROTOPLUGIN POP3Plugin;
-
-//from decode.cpp
-int DecodeQuotedPrintable(char *Src, char *Dst, int DstLen, BOOL isQ);
-int DecodeBase64(char *Src, char *Dst, int DstLen);
-
-//From filterplugin.cpp
-extern PYAMN_FILTERPLUGINQUEUE FirstFilterPlugin;
-
-//From protoplugin.cpp
-extern PYAMN_PROTOPLUGINQUEUE FirstProtoPlugin;
-
-extern struct CExportedFunctions ProtoPluginExportedFcn[1];
-extern struct CExportedServices ProtoPluginExportedSvc[5];
-//From filterplugin.cpp
-extern struct CExportedFunctions FilterPluginExportedFcn[1];
-extern struct CExportedServices FilterPluginExportedSvc[2];
-//From synchro.cpp
-extern struct CExportedFunctions SynchroExportedFcn[7];
-//From account.cpp
-extern struct CExportedFunctions AccountExportedFcn[2];
-extern struct CExportedServices AccountExportedSvc[9];
-//From mails.cpp (MIME)
-extern struct CExportedFunctions MailExportedFcn[8];
-extern struct CExportedServices MailExportedSvc[5];
-
-extern char *iconDescs[];
-extern char *iconNames[];
-extern HIMAGELIST CSImages;
-
-extern void __stdcall SSL_DebugLog(const char *fmt, ...);
-
-extern struct WndHandles *MessageWnd;
-
-extern int GetCharsetFromString(char *input, size_t size);
-extern void ConvertCodedStringToUnicode(char *stream, wchar_t **storeto, uint32_t cp, int mode);
-extern void __cdecl MailBrowser(void *Param);
-extern void __cdecl BadConnection(void *Param);
-extern PVOID TLSCtx;
-extern PVOID SSLCtx;
-
-extern PYAMN_VARIABLES pYAMNVar;
-
-#endif
+
+#ifndef __YAMN_H
+#define __YAMN_H
+
+#define VC_EXTRALEAN
+
+#include <windows.h>
+#include <windowsx.h>
+#include <commctrl.h>
+
+#include <newpluginapi.h>
+#include <m_clistint.h>
+#include <m_contacts.h>
+#include <m_database.h>
+#include <m_hotkeys.h>
+#include <m_icolib.h>
+#include <m_langpack.h>
+#include <m_messages.h>
+#include <m_netlib.h>
+#include <m_options.h>
+#include <m_popup.h>
+#include <m_protosvc.h>
+#include <m_skin.h>
+#include <m_timezones.h>
+
+#include <m_toptoolbar.h>
+#include <m_kbdnotify.h>
+#include <m_filterplugin.h>
+#include <m_yamn.h>
+#include <m_protoplugin.h>
+#include <m_folders.h>
+
+#include "main.h"
+#include "mails/decode.h"
+#include "browser/browser.h"
+#include "resource.h"
+#include "debug.h"
+#include "version.h"
+#include "proto/netclient.h"
+#include "proto/netlib.h"
+#include "proto/pop3/pop3.h"
+#include "proto/pop3/pop3comm.h"
+
+struct CMPlugin : public PLUGIN<CMPlugin>
+{
+ CMPlugin();
+
+ int Load() override;
+ int Unload() override;
+};
+
+// From services.cpp
+void CreateServiceFunctions(void);
+void HookEvents(void);
+void RefreshContact(void);
+void ContactDoubleclicked(WPARAM wParam, LPARAM lParam);
+INT_PTR ClistContactDoubleclicked(WPARAM wParam, LPARAM lParam);
+
+extern mir_cs PluginRegCS;
+extern SCOUNTER *AccountWriterSO;
+extern HANDLE ExitEV;
+extern HANDLE WriteToFileEV;
+
+// From debug.cpp
+#ifdef _DEBUG
+void InitDebug();
+void UnInitDebug();
+#endif
+
+// From yamn.cpp
+INT_PTR GetFcnPtrSvc(WPARAM wParam, LPARAM lParam);
+INT_PTR GetVariablesSvc(WPARAM, LPARAM);
+void CALLBACK TimerProc(HWND, UINT, UINT_PTR, DWORD);
+INT_PTR ForceCheckSvc(WPARAM, LPARAM);
+
+extern struct YAMNExportedFcns *pYAMNFcn;
+
+// From account.cpp
+INT_PTR CreatePluginAccountSvc(WPARAM wParam, LPARAM lParam);
+INT_PTR DeletePluginAccountSvc(WPARAM wParam, LPARAM);
+int InitAccount(CAccount *Which);
+void DeInitAccount(CAccount *Which);
+void StopSignalFcn(CAccount *Which);
+void CodeDecodeString(char *Dest, BOOL Encrypt);
+uint32_t FileToMemory(wchar_t *FileName, char **MemFile, char **End);
+
+#if defined(DEBUG_FILEREAD) || defined(DEBUG_FILEREADMESSAGES)
+uint32_t ReadStringFromMemory(char **Parser,char *End,char **StoreTo,char *DebugString);
+#endif
+uint32_t ReadStringFromMemory(char **Parser, char *End, char **StoreTo);
+uint32_t ReadMessagesFromMemory(CAccount *Which, char **Parser, char *End);
+uint32_t ReadAccountFromMemory(CAccount *Which, char **Parser, wchar_t *End);
+INT_PTR AddAccountsFromFileSvc(WPARAM wParam, LPARAM lParam);
+
+uint32_t WriteStringToFile(HANDLE File, char *Source);
+uint32_t WriteStringToFileW(HANDLE File, wchar_t *Source);
+
+
+DWORD WriteMessagesToFile(HANDLE File, CAccount *Which);
+DWORD WINAPI WritePOP3Accounts();
+INT_PTR WriteAccountsToFileSvc(WPARAM wParam, LPARAM lParam);
+INT_PTR FindAccountByNameSvc(WPARAM wParam, LPARAM lParam);
+INT_PTR GetNextFreeAccountSvc(WPARAM wParam, LPARAM lParam);
+
+INT_PTR DeleteAccountSvc(WPARAM wParam, LPARAM);
+void __cdecl DeleteAccountInBackground(void *Which);
+int StopAccounts(HYAMNPROTOPLUGIN Plugin);
+int WaitForAllAccounts(HYAMNPROTOPLUGIN Plugin, BOOL GetAccountBrowserAccess = FALSE);
+int DeleteAccounts(HYAMNPROTOPLUGIN Plugin);
+
+void WINAPI GetStatusFcn(CAccount *Which, wchar_t *Value);
+void WINAPI SetStatusFcn(CAccount *Which, wchar_t *Value);
+
+INT_PTR UnregisterProtoPlugins();
+INT_PTR RegisterProtocolPluginSvc(WPARAM, LPARAM);
+INT_PTR UnregisterProtocolPluginSvc(WPARAM, LPARAM);
+INT_PTR GetFileNameSvc(WPARAM, LPARAM);
+INT_PTR DeleteFileNameSvc(WPARAM, LPARAM);
+
+//From filterplugin.cpp
+//struct CExportedFunctions FilterPluginExported[];
+INT_PTR UnregisterFilterPlugins();
+INT_PTR RegisterFilterPluginSvc(WPARAM, LPARAM);
+INT_PTR UnregisterFilterPluginSvc(WPARAM, LPARAM);
+INT_PTR FilterMailSvc(WPARAM, LPARAM);
+
+//From mails.cpp (MIME)
+//struct CExportedFunctions MailExported[];
+INT_PTR CreateAccountMailSvc(WPARAM wParam, LPARAM lParam);
+INT_PTR DeleteAccountMailSvc(WPARAM wParam, LPARAM lParam);
+INT_PTR LoadMailDataSvc(WPARAM wParam, LPARAM lParam);
+INT_PTR UnloadMailDataSvc(WPARAM wParam, LPARAM);
+INT_PTR SaveMailDataSvc(WPARAM wParam, LPARAM lParam);
+
+//From mime.cpp
+//void WINAPI ExtractHeaderFcn(char *,int,uint16_t,HYAMNMAIL); //already in MailExported
+struct _tcptable
+{
+ char *NameBase, *NameSub;
+ BOOLEAN isValid;
+ unsigned short int CP;
+};
+extern struct _tcptable CodePageNamesAll[]; // in mime/decode.cpp
+extern int CPLENALL;
+extern struct _tcptable *CodePageNamesSupp; // in mime/decode.cpp
+extern int CPLENSUPP;
+
+extern int PosX, PosY, SizeX, SizeY;
+extern int HeadPosX, HeadPosY, HeadSizeX, HeadSizeY, HeadSplitPos;
+
+//#define CPDEFINDEX 63 //ISO-8859-1
+#define CPDEFINDEX 0 //ACP
+
+//From pop3comm.cpp
+int RegisterPOP3Plugin(WPARAM, LPARAM);
+
+//From mailbrowser.cpp
+INT_PTR RunMailBrowserSvc(WPARAM, LPARAM);
+
+//From badconnect.cpp
+int RunBadConnection(CAccount *acc, UINT_PTR iErrorCode, void *pUserInfo);
+
+//From YAMNopts.cpp
+int YAMNOptInitSvc(WPARAM, LPARAM);
+
+//From main.cpp
+int PostLoad(WPARAM, LPARAM); //Executed after all plugins loaded YAMN reads mails from file and notify every protocol it should set its functions
+int Shutdown(WPARAM, LPARAM); //Executed before Miranda is going to shutdown
+int AddTopToolbarIcon(WPARAM, LPARAM); //Executed when TopToolBar plugin loaded Adds bitmap to toolbar
+
+extern wchar_t UserDirectory[]; //e.g. "F:\WINNT\Profiles\UserXYZ"
+extern wchar_t ProfileName[]; //e.g. "majvan"
+extern SWMRG *AccountBrowserSO;
+extern YAMN_VARIABLES YAMNVar;
+extern HANDLE hNewMailHook;
+extern HANDLE hTTButton;
+extern HCURSOR hCurSplitNS, hCurSplitWE;
+extern UINT SecTimer;
+
+//From synchro.cpp
+void WINAPI DeleteMessagesToEndFcn(CAccount *Account, HYAMNMAIL From);
+uint32_t WINAPI WaitToWriteFcn(PSWMRG SObject, PSCOUNTER SCounter = nullptr);
+void WINAPI WriteDoneFcn(PSWMRG SObject, PSCOUNTER SCounter = nullptr);
+uint32_t WINAPI WaitToReadFcn(PSWMRG SObject);
+void WINAPI ReadDoneFcn(PSWMRG SObject);
+uint32_t WINAPI SCIncFcn(PSCOUNTER SCounter);
+uint32_t WINAPI SCDecFcn(PSCOUNTER SCounter);
+BOOL WINAPI SWMRGInitialize(PSWMRG, wchar_t *);
+void WINAPI SWMRGDelete(PSWMRG);
+uint32_t WINAPI SWMRGWaitToWrite(PSWMRG pSWMRG, uint32_t dwTimeout);
+void WINAPI SWMRGDoneWriting(PSWMRG pSWMRG);
+uint32_t WINAPI SWMRGWaitToRead(PSWMRG pSWMRG, uint32_t dwTimeout);
+void WINAPI SWMRGDoneReading(PSWMRG pSWMRG);
+
+//From mails.cpp
+void WINAPI DeleteMessageFromQueueFcn(HYAMNMAIL *From, HYAMNMAIL Which, int mode);
+void WINAPI SetRemoveFlagsInQueueFcn(HYAMNMAIL From, uint32_t FlagsSet, uint32_t FlagsNotSet, uint32_t FlagsToSet, int mode);
+
+//From mime.cpp
+void ExtractHeader(struct CMimeItem *items, int &CP, struct CHeader *head);
+void ExtractShortHeader(struct CMimeItem *items, struct CShortHeader *head);
+void DeleteHeaderContent(struct CHeader *head);
+void DeleteShortHeaderContent(struct CShortHeader *head);
+char *ExtractFromContentType(char *ContentType, char *value);
+wchar_t *ParseMultipartBody(char *src, char *bond);
+
+//From account.cpp
+void WINAPI GetStatusFcn(CAccount *Which, wchar_t *Value);
+
+extern HYAMNPROTOPLUGIN POP3Plugin;
+
+//from decode.cpp
+int DecodeQuotedPrintable(char *Src, char *Dst, int DstLen, BOOL isQ);
+int DecodeBase64(char *Src, char *Dst, int DstLen);
+
+//From filterplugin.cpp
+extern PYAMN_FILTERPLUGINQUEUE FirstFilterPlugin;
+
+//From protoplugin.cpp
+extern PYAMN_PROTOPLUGINQUEUE FirstProtoPlugin;
+
+extern struct CExportedFunctions ProtoPluginExportedFcn[1];
+extern struct CExportedServices ProtoPluginExportedSvc[5];
+//From filterplugin.cpp
+extern struct CExportedFunctions FilterPluginExportedFcn[1];
+extern struct CExportedServices FilterPluginExportedSvc[2];
+//From synchro.cpp
+extern struct CExportedFunctions SynchroExportedFcn[7];
+//From account.cpp
+extern struct CExportedFunctions AccountExportedFcn[2];
+extern struct CExportedServices AccountExportedSvc[9];
+//From mails.cpp (MIME)
+extern struct CExportedFunctions MailExportedFcn[8];
+extern struct CExportedServices MailExportedSvc[5];
+
+extern char *iconDescs[];
+extern char *iconNames[];
+extern HIMAGELIST CSImages;
+
+extern void __stdcall SSL_DebugLog(const char *fmt, ...);
+
+extern struct WndHandles *MessageWnd;
+
+extern int GetCharsetFromString(char *input, size_t size);
+extern void ConvertCodedStringToUnicode(char *stream, wchar_t **storeto, uint32_t cp, int mode);
+extern void __cdecl MailBrowser(void *Param);
+extern void __cdecl BadConnection(void *Param);
+extern PVOID TLSCtx;
+extern PVOID SSLCtx;
+
+extern PYAMN_VARIABLES pYAMNVar;
+
+#endif
diff --git a/protocols/YAMN/src/synchro.cpp b/protocols/YAMN/src/synchro.cpp
index c4bb58e6de..184156787d 100644
--- a/protocols/YAMN/src/synchro.cpp
+++ b/protocols/YAMN/src/synchro.cpp
@@ -1,315 +1,315 @@
-/*
- * This code implements synchronization objects code between threads. If you want, you can include it to your
- * code. This file is not dependent on any other external code (functions)
- *
- * (c) majvan 2002-2004
- */
-
-#include "stdafx.h"
-
- // Initializes a SWMRG structure. This structure must be
- // initialized before any writer or reader threads attempt
- // to wait on it.
- // The structure must be allocated by the application and
- // the structure's address is passed as the first parameter.
- // The lpszName parameter is the name of the object. Pass
- // NULL if you do not want to share the object.
-BOOL WINAPI SWMRGInitialize(PSWMRG pSWMRG, wchar_t *Name);
-
-// Deletes the system resources associated with a SWMRG
-// structure. The structure must be deleted only when
-// no writer or reader threads in the calling process
-// will wait on it.
-void WINAPI SWMRGDelete(PSWMRG pSWMRG);
-
-// A writer thread calls this function to know when
-// it can successfully write to the shared data.
-// returns WAIT_FINISH when we are in write-access or WAIT_FAILED
-// when event about quick finishing is set (or when system returns fail when waiting for synchro object)
-uint32_t WINAPI SWMRGWaitToWrite(PSWMRG pSWMRG, uint32_t dwTimeout);
-
-// A writer thread calls this function to let other threads
-// know that it no longer needs to write to the shared data.
-void WINAPI SWMRGDoneWriting(PSWMRG pSWMRG);
-
-// A reader thread calls this function to know when
-// it can successfully read the shared data.
-// returns WAIT_FINISH when we are in read-access or WAIT_FAILED
-// when event about quick finishing is set (or when system returns fail when waiting for synchro object)
-uint32_t WINAPI SWMRGWaitToRead(PSWMRG pSWMRG, uint32_t dwTimeout);
-
-// A reader thread calls this function to let other threads
-// know when it no longer needs to read the shared data.
-void WINAPI SWMRGDoneReading(PSWMRG pSWMRG);
-
-// WaitToReadFcn
-// is used to wait for read access with SWMRG SO, but it also increments counter if successfull
-// returns WAIT_FAILED or WAIT_FINISH
-// when WAIT_FAILED, we should not begin to access datas, we are not in read-access mode
-uint32_t WINAPI WaitToReadFcn(PSWMRG SObject);
-
-// WriteDoneFcn
-// is used to release read access with SWMRG SO, but it also decrements counter if successfull
-void WINAPI ReadDoneFcn(PSWMRG SObject);
-
-// This functions is for export purposes
-// Plugin can call this function to manage SCOUNTER synchronization object
-
-// Gets number value stored in SCOUNTER SO
-// Note you must not read the number from memory directly, because
-// CPU can stop reading thread when it has read HI-Word, then another thread
-// can change the value and then OS starts the previous thread, that reads the
-// LO-uint16_t of uint32_t. And the return value HI+LO-uint16_t is corrupted
-uint32_t WINAPI SCGetNumberFcn(PSCOUNTER SCounter);
-
-// Increments SCOUNTER and unsets event
-// Returns Number after incrementing
-uint32_t WINAPI SCIncFcn(PSCOUNTER SCounter);
-
-// Decrements SCOUNTER and sets event if zero
-// Returns Number after decrementing
-uint32_t WINAPI SCDecFcn(PSCOUNTER SCounter);
-
-struct CExportedFunctions SynchroExportedFcn[] =
-{
- {YAMN_WAITTOWRITEID, (void *)WaitToWriteFcn},
- {YAMN_WRITEDONEID, (void *)WriteDoneFcn},
- {YAMN_WAITTOREADID, (void *)WaitToReadFcn},
- {YAMN_READDONEID, (void *)ReadDoneFcn},
- {YAMN_SCGETNUMBERID, (void *)SCGetNumberFcn},
- {YAMN_SCINCID, (void *)SCIncFcn},
- {YAMN_SCDECID, (void *)SCDecFcn},
-};
-
-//--------------------------------------------------------------------------------------------------
-//--------------------------------------------------------------------------------------------------
-
-void WINAPI SWMRGDelete(PSWMRG pSWMRG)
-{
- // Destroys any synchronization objects that were
- // successfully created.
- if (nullptr != pSWMRG->hEventNoWriter)
- CloseHandle(pSWMRG->hEventNoWriter);
- if (nullptr != pSWMRG->hEventNoReaders)
- CloseHandle(pSWMRG->hEventNoReaders);
- if (nullptr != pSWMRG->hSemNumReaders)
- CloseHandle(pSWMRG->hSemNumReaders);
- if (nullptr != pSWMRG->hFinishEV)
- CloseHandle(pSWMRG->hFinishEV);
-}
-
-BOOL WINAPI SWMRGInitialize(PSWMRG pSWMRG, wchar_t *Name)
-{
- pSWMRG->hEventNoWriter = nullptr;
- pSWMRG->hEventNoReaders = nullptr;
- pSWMRG->hSemNumReaders = nullptr;
- pSWMRG->hFinishEV = nullptr;
-
- // Creates the automatic-reset event that is signalled when
- // no writer threads are writing.
- // Initially no reader threads are reading.
- if (Name != nullptr)
- Name[0] = (wchar_t)'W';
- pSWMRG->hEventNoWriter = CreateEvent(nullptr, FALSE, TRUE, Name);
-
- // Creates the manual-reset event that is signalled when
- // no reader threads are reading.
- // Initially no reader threads are reading.
- if (Name != nullptr)
- Name[0] = (wchar_t)'R';
- pSWMRG->hEventNoReaders = CreateEvent(nullptr, TRUE, TRUE, Name);
-
- // Initializes the variable that indicates the number of
- // reader threads that are reading.
- // Initially no reader threads are reading.
- if (Name != nullptr)
- Name[0] = (wchar_t)'C';
- pSWMRG->hSemNumReaders = CreateSemaphore(nullptr, 0, 0x7FFFFFFF, Name);
-
- if (Name != nullptr)
- Name[0] = (wchar_t)'F';
- pSWMRG->hFinishEV = CreateEvent(nullptr, TRUE, FALSE, Name);
-
- // If a synchronization object could not be created,
- // destroys any created objects and return failure.
- if ((nullptr == pSWMRG->hEventNoWriter) || (nullptr == pSWMRG->hEventNoReaders) || (nullptr == pSWMRG->hSemNumReaders) || (nullptr == pSWMRG->hFinishEV)) {
- SWMRGDelete(pSWMRG);
- return FALSE;
- }
- return TRUE;
-}
-
-uint32_t WINAPI SWMRGWaitToWrite(PSWMRG pSWMRG, uint32_t dwTimeout)
-{
- uint32_t dw;
- HANDLE aHandles[2];
-
- // We can write if the following are true:
- // 1. No other threads are writing.
- // 2. No threads are reading.
- // But first we have to know if SWMRG structure is not about to delete
- aHandles[0] = pSWMRG->hEventNoWriter;
- aHandles[1] = pSWMRG->hEventNoReaders;
- if (WAIT_OBJECT_0 == (dw = WaitForSingleObject(pSWMRG->hFinishEV, 0)))
- return WAIT_FINISH;
- if (WAIT_FAILED == dw)
- return dw;
- dw = WaitForMultipleObjects(2, aHandles, TRUE, dwTimeout);
- // if a request to delete became later, we should not catch it. Try once more to ask if account is not about to delete
- if ((dw != WAIT_FAILED) && (WAIT_OBJECT_0 == (WaitForSingleObject(pSWMRG->hFinishEV, 0)))) {
- SetEvent(pSWMRG->hEventNoWriter);
- return WAIT_FINISH;
- }
-
- // This thread can write to the shared data.
- // Automatic event for NoWriter sets hEventNoWriter to nonsignaled after WaitForMultipleObject
-
- // Because a writer thread is writing, the Event
- // should not be reset. This stops other
- // writers and readers.
- return dw;
-}
-
-void WINAPI SWMRGDoneWriting(PSWMRG pSWMRG)
-// Presumably, a writer thread calling this function has
-// successfully called WaitToWrite. This means that we
-// do not have to wait on any synchronization objects
-// here because the writer already owns the Event.
-{
- // Allow other writer/reader threads to use
- // the SWMRG synchronization object.
- SetEvent(pSWMRG->hEventNoWriter);
-}
-
-uint32_t WINAPI SWMRGWaitToRead(PSWMRG pSWMRG, uint32_t dwTimeout)
-{
- uint32_t dw;
- LONG lPreviousCount;
-
- // We can read if no threads are writing.
- // And there's not request to delete structure
- if (WAIT_OBJECT_0 == (dw = WaitForSingleObject(pSWMRG->hFinishEV, 0)))
- return WAIT_FINISH;
- if (WAIT_FAILED == dw)
- return dw;
- dw = WaitForSingleObject(pSWMRG->hEventNoWriter, dwTimeout);
- // if a request to delete became later, we should not catch it. Try once more to ask if account is not about to delete
- if ((dw != WAIT_FAILED) && (WAIT_OBJECT_0 == (WaitForSingleObject(pSWMRG->hFinishEV, 0)))) {
- SetEvent(pSWMRG->hEventNoWriter);
- return WAIT_FINISH;
- }
-
- if (dw == WAIT_OBJECT_0) {
- // This thread can read from the shared data.
- // Increment the number of reader threads.
- // But there can't be more than one thread incrementing readers,
- // so this is why we use semaphore.
- ReleaseSemaphore(pSWMRG->hSemNumReaders, 1, &lPreviousCount);
- if (lPreviousCount == 0)
- // If this is the first reader thread,
- // set event to reflect this. Other reader threads can read, no writer thread can write.
- ResetEvent(pSWMRG->hEventNoReaders);
-
- // Allow other writer/reader threads to use
- // the SWMRG synchronization object. hEventNoWrite is still non-signaled
- // (it looks like writer is processing thread, but it is not true)
- SetEvent(pSWMRG->hEventNoWriter);
- }
-
- return(dw);
-}
-
-void WINAPI SWMRGDoneReading(PSWMRG pSWMRG)
-{
- HANDLE aHandles[2];
- LONG lNumReaders;
-
- // We can stop reading if the events are available,
- // but when we stop reading we must also decrement the
- // number of reader threads.
- aHandles[0] = pSWMRG->hEventNoWriter;
- aHandles[1] = pSWMRG->hSemNumReaders;
- WaitForMultipleObjects(2, aHandles, TRUE, INFINITE);
-
- // Get the remaining number of readers by releasing the
- // semaphore and then restoring the count by immediately
- // performing a wait.
- ReleaseSemaphore(pSWMRG->hSemNumReaders, 1, &lNumReaders);
- WaitForSingleObject(pSWMRG->hSemNumReaders, INFINITE);
-
- // If there are no remaining readers,
- // set the event to relect this.
- if (lNumReaders == 0)
- // If there are no reader threads,
- // set our event to reflect this.
- SetEvent(pSWMRG->hEventNoReaders);
-
- // Allow other writer/reader threads to use
- // the SWMRG synchronization object.
- // (it looks like writer is processing thread, but it is not true)
- SetEvent(pSWMRG->hEventNoWriter);
-}
-
-uint32_t WINAPI WaitToWriteFcn(PSWMRG SObject, PSCOUNTER SCounter)
-{
- uint32_t EnterCode;
-
- if (WAIT_OBJECT_0 == (EnterCode = SWMRGWaitToWrite(SObject, INFINITE)))
- if (SCounter != nullptr)
- SCIncFcn(SCounter);
-
- return EnterCode;
-}
-
-void WINAPI WriteDoneFcn(PSWMRG SObject, PSCOUNTER SCounter)
-{
- SWMRGDoneWriting(SObject);
- if (SCounter != nullptr)
- SCDecFcn(SCounter);
-}
-
-uint32_t WINAPI WaitToReadFcn(PSWMRG SObject)
-{
- uint32_t EnterCode = SWMRGWaitToRead(SObject, INFINITE);
- return EnterCode;
-}
-
-void WINAPI ReadDoneFcn(PSWMRG SObject)
-{
- SWMRGDoneReading(SObject);
-}
-
-uint32_t WINAPI SCGetNumberFcn(PSCOUNTER SCounter)
-{
-
- EnterCriticalSection(&SCounter->CounterCS);
-
- uint32_t Temp = SCounter->Number;
-
- LeaveCriticalSection(&SCounter->CounterCS);
- return Temp;
-}
-
-uint32_t WINAPI SCIncFcn(PSCOUNTER SCounter)
-{
- EnterCriticalSection(&SCounter->CounterCS);
-
- uint32_t Temp = ++SCounter->Number;
- ResetEvent(SCounter->Event);
-
- LeaveCriticalSection(&SCounter->CounterCS);
- return Temp;
-}
-
-uint32_t WINAPI SCDecFcn(PSCOUNTER SCounter)
-{
- uint32_t Temp;
- EnterCriticalSection(&SCounter->CounterCS);
-
- if (!(Temp = --SCounter->Number)) {
- SetEvent(SCounter->Event);
- }
-
- LeaveCriticalSection(&SCounter->CounterCS);
- return Temp;
-}
+/*
+ * This code implements synchronization objects code between threads. If you want, you can include it to your
+ * code. This file is not dependent on any other external code (functions)
+ *
+ * (c) majvan 2002-2004
+ */
+
+#include "stdafx.h"
+
+ // Initializes a SWMRG structure. This structure must be
+ // initialized before any writer or reader threads attempt
+ // to wait on it.
+ // The structure must be allocated by the application and
+ // the structure's address is passed as the first parameter.
+ // The lpszName parameter is the name of the object. Pass
+ // NULL if you do not want to share the object.
+BOOL WINAPI SWMRGInitialize(PSWMRG pSWMRG, wchar_t *Name);
+
+// Deletes the system resources associated with a SWMRG
+// structure. The structure must be deleted only when
+// no writer or reader threads in the calling process
+// will wait on it.
+void WINAPI SWMRGDelete(PSWMRG pSWMRG);
+
+// A writer thread calls this function to know when
+// it can successfully write to the shared data.
+// returns WAIT_FINISH when we are in write-access or WAIT_FAILED
+// when event about quick finishing is set (or when system returns fail when waiting for synchro object)
+uint32_t WINAPI SWMRGWaitToWrite(PSWMRG pSWMRG, uint32_t dwTimeout);
+
+// A writer thread calls this function to let other threads
+// know that it no longer needs to write to the shared data.
+void WINAPI SWMRGDoneWriting(PSWMRG pSWMRG);
+
+// A reader thread calls this function to know when
+// it can successfully read the shared data.
+// returns WAIT_FINISH when we are in read-access or WAIT_FAILED
+// when event about quick finishing is set (or when system returns fail when waiting for synchro object)
+uint32_t WINAPI SWMRGWaitToRead(PSWMRG pSWMRG, uint32_t dwTimeout);
+
+// A reader thread calls this function to let other threads
+// know when it no longer needs to read the shared data.
+void WINAPI SWMRGDoneReading(PSWMRG pSWMRG);
+
+// WaitToReadFcn
+// is used to wait for read access with SWMRG SO, but it also increments counter if successfull
+// returns WAIT_FAILED or WAIT_FINISH
+// when WAIT_FAILED, we should not begin to access datas, we are not in read-access mode
+uint32_t WINAPI WaitToReadFcn(PSWMRG SObject);
+
+// WriteDoneFcn
+// is used to release read access with SWMRG SO, but it also decrements counter if successfull
+void WINAPI ReadDoneFcn(PSWMRG SObject);
+
+// This functions is for export purposes
+// Plugin can call this function to manage SCOUNTER synchronization object
+
+// Gets number value stored in SCOUNTER SO
+// Note you must not read the number from memory directly, because
+// CPU can stop reading thread when it has read HI-Word, then another thread
+// can change the value and then OS starts the previous thread, that reads the
+// LO-uint16_t of uint32_t. And the return value HI+LO-uint16_t is corrupted
+uint32_t WINAPI SCGetNumberFcn(PSCOUNTER SCounter);
+
+// Increments SCOUNTER and unsets event
+// Returns Number after incrementing
+uint32_t WINAPI SCIncFcn(PSCOUNTER SCounter);
+
+// Decrements SCOUNTER and sets event if zero
+// Returns Number after decrementing
+uint32_t WINAPI SCDecFcn(PSCOUNTER SCounter);
+
+struct CExportedFunctions SynchroExportedFcn[] =
+{
+ {YAMN_WAITTOWRITEID, (void *)WaitToWriteFcn},
+ {YAMN_WRITEDONEID, (void *)WriteDoneFcn},
+ {YAMN_WAITTOREADID, (void *)WaitToReadFcn},
+ {YAMN_READDONEID, (void *)ReadDoneFcn},
+ {YAMN_SCGETNUMBERID, (void *)SCGetNumberFcn},
+ {YAMN_SCINCID, (void *)SCIncFcn},
+ {YAMN_SCDECID, (void *)SCDecFcn},
+};
+
+//--------------------------------------------------------------------------------------------------
+//--------------------------------------------------------------------------------------------------
+
+void WINAPI SWMRGDelete(PSWMRG pSWMRG)
+{
+ // Destroys any synchronization objects that were
+ // successfully created.
+ if (nullptr != pSWMRG->hEventNoWriter)
+ CloseHandle(pSWMRG->hEventNoWriter);
+ if (nullptr != pSWMRG->hEventNoReaders)
+ CloseHandle(pSWMRG->hEventNoReaders);
+ if (nullptr != pSWMRG->hSemNumReaders)
+ CloseHandle(pSWMRG->hSemNumReaders);
+ if (nullptr != pSWMRG->hFinishEV)
+ CloseHandle(pSWMRG->hFinishEV);
+}
+
+BOOL WINAPI SWMRGInitialize(PSWMRG pSWMRG, wchar_t *Name)
+{
+ pSWMRG->hEventNoWriter = nullptr;
+ pSWMRG->hEventNoReaders = nullptr;
+ pSWMRG->hSemNumReaders = nullptr;
+ pSWMRG->hFinishEV = nullptr;
+
+ // Creates the automatic-reset event that is signalled when
+ // no writer threads are writing.
+ // Initially no reader threads are reading.
+ if (Name != nullptr)
+ Name[0] = (wchar_t)'W';
+ pSWMRG->hEventNoWriter = CreateEvent(nullptr, FALSE, TRUE, Name);
+
+ // Creates the manual-reset event that is signalled when
+ // no reader threads are reading.
+ // Initially no reader threads are reading.
+ if (Name != nullptr)
+ Name[0] = (wchar_t)'R';
+ pSWMRG->hEventNoReaders = CreateEvent(nullptr, TRUE, TRUE, Name);
+
+ // Initializes the variable that indicates the number of
+ // reader threads that are reading.
+ // Initially no reader threads are reading.
+ if (Name != nullptr)
+ Name[0] = (wchar_t)'C';
+ pSWMRG->hSemNumReaders = CreateSemaphore(nullptr, 0, 0x7FFFFFFF, Name);
+
+ if (Name != nullptr)
+ Name[0] = (wchar_t)'F';
+ pSWMRG->hFinishEV = CreateEvent(nullptr, TRUE, FALSE, Name);
+
+ // If a synchronization object could not be created,
+ // destroys any created objects and return failure.
+ if ((nullptr == pSWMRG->hEventNoWriter) || (nullptr == pSWMRG->hEventNoReaders) || (nullptr == pSWMRG->hSemNumReaders) || (nullptr == pSWMRG->hFinishEV)) {
+ SWMRGDelete(pSWMRG);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+uint32_t WINAPI SWMRGWaitToWrite(PSWMRG pSWMRG, uint32_t dwTimeout)
+{
+ uint32_t dw;
+ HANDLE aHandles[2];
+
+ // We can write if the following are true:
+ // 1. No other threads are writing.
+ // 2. No threads are reading.
+ // But first we have to know if SWMRG structure is not about to delete
+ aHandles[0] = pSWMRG->hEventNoWriter;
+ aHandles[1] = pSWMRG->hEventNoReaders;
+ if (WAIT_OBJECT_0 == (dw = WaitForSingleObject(pSWMRG->hFinishEV, 0)))
+ return WAIT_FINISH;
+ if (WAIT_FAILED == dw)
+ return dw;
+ dw = WaitForMultipleObjects(2, aHandles, TRUE, dwTimeout);
+ // if a request to delete became later, we should not catch it. Try once more to ask if account is not about to delete
+ if ((dw != WAIT_FAILED) && (WAIT_OBJECT_0 == (WaitForSingleObject(pSWMRG->hFinishEV, 0)))) {
+ SetEvent(pSWMRG->hEventNoWriter);
+ return WAIT_FINISH;
+ }
+
+ // This thread can write to the shared data.
+ // Automatic event for NoWriter sets hEventNoWriter to nonsignaled after WaitForMultipleObject
+
+ // Because a writer thread is writing, the Event
+ // should not be reset. This stops other
+ // writers and readers.
+ return dw;
+}
+
+void WINAPI SWMRGDoneWriting(PSWMRG pSWMRG)
+// Presumably, a writer thread calling this function has
+// successfully called WaitToWrite. This means that we
+// do not have to wait on any synchronization objects
+// here because the writer already owns the Event.
+{
+ // Allow other writer/reader threads to use
+ // the SWMRG synchronization object.
+ SetEvent(pSWMRG->hEventNoWriter);
+}
+
+uint32_t WINAPI SWMRGWaitToRead(PSWMRG pSWMRG, uint32_t dwTimeout)
+{
+ uint32_t dw;
+ LONG lPreviousCount;
+
+ // We can read if no threads are writing.
+ // And there's not request to delete structure
+ if (WAIT_OBJECT_0 == (dw = WaitForSingleObject(pSWMRG->hFinishEV, 0)))
+ return WAIT_FINISH;
+ if (WAIT_FAILED == dw)
+ return dw;
+ dw = WaitForSingleObject(pSWMRG->hEventNoWriter, dwTimeout);
+ // if a request to delete became later, we should not catch it. Try once more to ask if account is not about to delete
+ if ((dw != WAIT_FAILED) && (WAIT_OBJECT_0 == (WaitForSingleObject(pSWMRG->hFinishEV, 0)))) {
+ SetEvent(pSWMRG->hEventNoWriter);
+ return WAIT_FINISH;
+ }
+
+ if (dw == WAIT_OBJECT_0) {
+ // This thread can read from the shared data.
+ // Increment the number of reader threads.
+ // But there can't be more than one thread incrementing readers,
+ // so this is why we use semaphore.
+ ReleaseSemaphore(pSWMRG->hSemNumReaders, 1, &lPreviousCount);
+ if (lPreviousCount == 0)
+ // If this is the first reader thread,
+ // set event to reflect this. Other reader threads can read, no writer thread can write.
+ ResetEvent(pSWMRG->hEventNoReaders);
+
+ // Allow other writer/reader threads to use
+ // the SWMRG synchronization object. hEventNoWrite is still non-signaled
+ // (it looks like writer is processing thread, but it is not true)
+ SetEvent(pSWMRG->hEventNoWriter);
+ }
+
+ return(dw);
+}
+
+void WINAPI SWMRGDoneReading(PSWMRG pSWMRG)
+{
+ HANDLE aHandles[2];
+ LONG lNumReaders;
+
+ // We can stop reading if the events are available,
+ // but when we stop reading we must also decrement the
+ // number of reader threads.
+ aHandles[0] = pSWMRG->hEventNoWriter;
+ aHandles[1] = pSWMRG->hSemNumReaders;
+ WaitForMultipleObjects(2, aHandles, TRUE, INFINITE);
+
+ // Get the remaining number of readers by releasing the
+ // semaphore and then restoring the count by immediately
+ // performing a wait.
+ ReleaseSemaphore(pSWMRG->hSemNumReaders, 1, &lNumReaders);
+ WaitForSingleObject(pSWMRG->hSemNumReaders, INFINITE);
+
+ // If there are no remaining readers,
+ // set the event to relect this.
+ if (lNumReaders == 0)
+ // If there are no reader threads,
+ // set our event to reflect this.
+ SetEvent(pSWMRG->hEventNoReaders);
+
+ // Allow other writer/reader threads to use
+ // the SWMRG synchronization object.
+ // (it looks like writer is processing thread, but it is not true)
+ SetEvent(pSWMRG->hEventNoWriter);
+}
+
+uint32_t WINAPI WaitToWriteFcn(PSWMRG SObject, PSCOUNTER SCounter)
+{
+ uint32_t EnterCode;
+
+ if (WAIT_OBJECT_0 == (EnterCode = SWMRGWaitToWrite(SObject, INFINITE)))
+ if (SCounter != nullptr)
+ SCIncFcn(SCounter);
+
+ return EnterCode;
+}
+
+void WINAPI WriteDoneFcn(PSWMRG SObject, PSCOUNTER SCounter)
+{
+ SWMRGDoneWriting(SObject);
+ if (SCounter != nullptr)
+ SCDecFcn(SCounter);
+}
+
+uint32_t WINAPI WaitToReadFcn(PSWMRG SObject)
+{
+ uint32_t EnterCode = SWMRGWaitToRead(SObject, INFINITE);
+ return EnterCode;
+}
+
+void WINAPI ReadDoneFcn(PSWMRG SObject)
+{
+ SWMRGDoneReading(SObject);
+}
+
+uint32_t WINAPI SCGetNumberFcn(PSCOUNTER SCounter)
+{
+
+ EnterCriticalSection(&SCounter->CounterCS);
+
+ uint32_t Temp = SCounter->Number;
+
+ LeaveCriticalSection(&SCounter->CounterCS);
+ return Temp;
+}
+
+uint32_t WINAPI SCIncFcn(PSCOUNTER SCounter)
+{
+ EnterCriticalSection(&SCounter->CounterCS);
+
+ uint32_t Temp = ++SCounter->Number;
+ ResetEvent(SCounter->Event);
+
+ LeaveCriticalSection(&SCounter->CounterCS);
+ return Temp;
+}
+
+uint32_t WINAPI SCDecFcn(PSCOUNTER SCounter)
+{
+ uint32_t Temp;
+ EnterCriticalSection(&SCounter->CounterCS);
+
+ if (!(Temp = --SCounter->Number)) {
+ SetEvent(SCounter->Event);
+ }
+
+ LeaveCriticalSection(&SCounter->CounterCS);
+ return Temp;
+}
diff --git a/protocols/YAMN/src/yamn.cpp b/protocols/YAMN/src/yamn.cpp
index d0d80021f8..2af7efd74f 100644
--- a/protocols/YAMN/src/yamn.cpp
+++ b/protocols/YAMN/src/yamn.cpp
@@ -1,230 +1,230 @@
-/*
- * This code implements miscellaneous usefull functions
- *
- * (c) majvan 2002-2004
- */
-
-#include "stdafx.h"
-
-//--------------------------------------------------------------------------------------------------
-//--------------------------------------------------------------------------------------------------
-
-//Plugin registration CS
-//Used if we add (register) plugin to YAMN plugins and when we browse through registered plugins
-mir_cs PluginRegCS;
-
-//AccountWriterCS
-//We want to store number of writers of Accounts (number of Accounts used for writing)
-//If we want to read all accounts (for saving to file) immidiatelly, we have to wait until no account is changing (no thread writing to account)
-SCOUNTER *AccountWriterSO;
-
-//NoExitEV
-//Event that is signaled when there's a request to exit, so no new pop3 check should be performed
-HANDLE ExitEV;
-
-//WriteToFileEV
-//If this is signaled, write accounts to file is performed. Set this event if you want to actualize your accounts and messages
-HANDLE WriteToFileEV;
-
-//Returns pointer to YAMN exported function
-INT_PTR GetFcnPtrSvc(WPARAM wParam, LPARAM lParam);
-
-//Returns pointer to YAMN variables
-INT_PTR GetVariablesSvc(WPARAM wParam, LPARAM);
-
-// Function every seconds decrements account counter of seconds and checks if they are 0
-// If yes, creates a POP3 thread to check account
-void CALLBACK TimerProc(HWND, UINT, UINT, uint32_t);
-
-// Function called to check all accounts immidialtelly
-// no params
-INT_PTR ForceCheckSvc(WPARAM, LPARAM);
-
-//thread is running all the time
-//waits for WriteToFileEV and then writes all accounts to file
-//uint32_t WINAPI FileWritingThread(PVOID);
-
-// Function is called when Miranda notifies plugin that it is about to exit
-// Ensures succesfull end of POP3 checking, sets event that no next checking should be performed
-// If there's no writer to account (POP3 thread), saves the results to the file
-//not used now, perhaps in the future
-
-
-//int ExitProc(WPARAM wParam, LPARAM lParam);
-
-//--------------------------------------------------------------------------------------------------
-//--------------------------------------------------------------------------------------------------
-
-INT_PTR GetFcnPtrSvc(WPARAM wParam, LPARAM)
-{
- int i;
-
- for (i=0;i<sizeof(ProtoPluginExportedFcn)/sizeof(ProtoPluginExportedFcn[0]);i++)
- if (0==mir_strcmp((char *)wParam, ProtoPluginExportedFcn[i].ID))
- return (INT_PTR)ProtoPluginExportedFcn[i].Ptr;
- for (i=0;i<sizeof(ProtoPluginExportedSvc)/sizeof(ProtoPluginExportedSvc[0]);i++)
- if (0==mir_strcmp((char *)wParam, ProtoPluginExportedSvc[i].ID))
- return (INT_PTR)ProtoPluginExportedSvc[i].Ptr;
- for (i=0;i<sizeof(SynchroExportedFcn)/sizeof(SynchroExportedFcn[0]);i++)
- if (0==mir_strcmp((char *)wParam, SynchroExportedFcn[i].ID))
- return (INT_PTR)SynchroExportedFcn[i].Ptr;
- for (i=0;i<sizeof(AccountExportedFcn)/sizeof(AccountExportedFcn[0]);i++)
- if (0==mir_strcmp((char *)wParam, AccountExportedFcn[i].ID))
- return (INT_PTR)AccountExportedFcn[i].Ptr;
- for (i=0;i<sizeof(AccountExportedSvc)/sizeof(AccountExportedSvc[0]);i++)
- if (0==mir_strcmp((char *)wParam, AccountExportedSvc[i].ID))
- return (INT_PTR)AccountExportedSvc[i].Ptr;
- for (i=0;i<sizeof(MailExportedFcn)/sizeof(MailExportedFcn[0]);i++)
- if (0==mir_strcmp((char *)wParam, MailExportedFcn[i].ID))
- return (INT_PTR)MailExportedFcn[i].Ptr;
- for (i=0;i<sizeof(MailExportedSvc)/sizeof(MailExportedSvc[0]);i++)
- if (0==mir_strcmp((char *)wParam, MailExportedSvc[i].ID))
- return (INT_PTR)MailExportedSvc[i].Ptr;
- for (i=0;i<sizeof(FilterPluginExportedFcn)/sizeof(FilterPluginExportedFcn[0]);i++)
- if (0==mir_strcmp((char *)wParam, FilterPluginExportedFcn[i].ID))
- return (INT_PTR)FilterPluginExportedFcn[i].Ptr;
- for (i=0;i<sizeof(FilterPluginExportedSvc)/sizeof(FilterPluginExportedSvc[0]);i++)
- if (0==mir_strcmp((char *)wParam, FilterPluginExportedSvc[i].ID))
- return (INT_PTR)FilterPluginExportedSvc[i].Ptr;
- return (INT_PTR)NULL;
-}
-
-INT_PTR GetVariablesSvc(WPARAM wParam, LPARAM)
-{
- return wParam==YAMN_VARIABLESVERSION ? (INT_PTR)&YAMNVar : (INT_PTR)NULL;
-}
-
-void CALLBACK TimerProc(HWND, UINT, UINT_PTR, DWORD)
-{
- CAccount *ActualAccount;
- DWORD Status, tid;
-
- // we use event to signal, that running thread has all needed stack parameters copied
- HANDLE ThreadRunningEV = CreateEvent(nullptr, FALSE, FALSE, nullptr);
- if (ThreadRunningEV == nullptr)
- return;
-
- // if we want to close miranda, we get event and do not run checking anymore
- if (WAIT_OBJECT_0 == WaitForSingleObject(ExitEV, 0))
- return;
-
- // Get actual status of current user in Miranda
- Status = CallService(MS_CLIST_GETSTATUSMODE, 0, 0);
-
- mir_cslock lck(PluginRegCS);
- for (PYAMN_PROTOPLUGINQUEUE ActualPlugin = FirstProtoPlugin; ActualPlugin != nullptr; ActualPlugin = ActualPlugin->Next) {
- if (WAIT_OBJECT_0 != SWMRGWaitToRead(ActualPlugin->Plugin->AccountBrowserSO, 0)) // we want to access accounts immiadtelly
- return;
-
- for (ActualAccount = ActualPlugin->Plugin->FirstAccount; ActualAccount != nullptr; ActualAccount = ActualAccount->Next) {
- if (ActualAccount->Plugin == nullptr || ActualAccount->Plugin->Fcn == nullptr) //account not inited
- continue;
-
- if (WAIT_OBJECT_0 != SWMRGWaitToRead(ActualAccount->AccountAccessSO, 0))
- continue;
-
- BOOL isAccountCounting = 0;
- if ((ActualAccount->Flags & YAMN_ACC_ENA) &&
- (((ActualAccount->StatusFlags & YAMN_ACC_ST0) && (Status <= ID_STATUS_OFFLINE)) ||
- ((ActualAccount->StatusFlags & YAMN_ACC_ST1) && (Status == ID_STATUS_ONLINE)) ||
- ((ActualAccount->StatusFlags & YAMN_ACC_ST2) && (Status == ID_STATUS_AWAY)) ||
- ((ActualAccount->StatusFlags & YAMN_ACC_ST3) && (Status == ID_STATUS_DND)) ||
- ((ActualAccount->StatusFlags & YAMN_ACC_ST4) && (Status == ID_STATUS_NA)) ||
- ((ActualAccount->StatusFlags & YAMN_ACC_ST5) && (Status == ID_STATUS_OCCUPIED)) ||
- ((ActualAccount->StatusFlags & YAMN_ACC_ST6) && (Status == ID_STATUS_FREECHAT)) ||
- ((ActualAccount->StatusFlags & YAMN_ACC_ST7) && (Status == ID_STATUS_INVISIBLE))))
- {
- if ((!ActualAccount->Interval && !ActualAccount->TimeLeft) || ActualAccount->Plugin->Fcn->TimeoutFcnPtr == nullptr)
- goto ChangeIsCountingStatusLabel;
-
- if (ActualAccount->TimeLeft) {
- ActualAccount->TimeLeft--;
- isAccountCounting = TRUE;
- }
-
- WindowList_BroadcastAsync(YAMNVar.MessageWnds, WM_YAMN_CHANGETIME, (WPARAM)ActualAccount, (LPARAM)ActualAccount->TimeLeft);
- if (!ActualAccount->TimeLeft) {
- struct CheckParam ParamToPlugin = {YAMN_CHECKVERSION, ThreadRunningEV, ActualAccount, YAMN_NORMALCHECK, (void *)nullptr, nullptr};
-
- ActualAccount->TimeLeft = ActualAccount->Interval;
- HANDLE NewThread = CreateThread(nullptr, 0, (YAMN_STANDARDFCN)ActualAccount->Plugin->Fcn->TimeoutFcnPtr, &ParamToPlugin, 0, &tid);
- if (NewThread == nullptr) {
- ReadDoneFcn(ActualAccount->AccountAccessSO);
- continue;
- }
- else {
- WaitForSingleObject(ThreadRunningEV, INFINITE);
- CloseHandle(NewThread);
- }
- }
- }
-
-ChangeIsCountingStatusLabel:
- if (((ActualAccount->isCounting) != 0) != isAccountCounting) {
- ActualAccount->isCounting = isAccountCounting;
- uint16_t cStatus = g_plugin.getWord(ActualAccount->hContact, "Status");
- switch (cStatus) {
- case ID_STATUS_ONLINE:
- case ID_STATUS_OFFLINE:
- g_plugin.setWord(ActualAccount->hContact, "Status", isAccountCounting ? ID_STATUS_ONLINE : ID_STATUS_OFFLINE);
- default:
- break;
- }
- }
- ReadDoneFcn(ActualAccount->AccountAccessSO);
- }
- SWMRGDoneReading(ActualPlugin->Plugin->AccountBrowserSO);
- }
- CloseHandle(ThreadRunningEV);
-}
-
-INT_PTR ForceCheckSvc(WPARAM, LPARAM)
-{
- CAccount *ActualAccount;
- DWORD tid;
-
- //we use event to signal, that running thread has all needed stack parameters copied
- HANDLE ThreadRunningEV = CreateEvent(nullptr, FALSE, FALSE, nullptr);
- if (ThreadRunningEV == nullptr)
- return 0;
- //if we want to close miranda, we get event and do not run pop3 checking anymore
- if (WAIT_OBJECT_0 == WaitForSingleObject(ExitEV, 0))
- return 0;
-
- {
- mir_cslock lck(PluginRegCS);
- for (PYAMN_PROTOPLUGINQUEUE ActualPlugin = FirstProtoPlugin; ActualPlugin != nullptr; ActualPlugin = ActualPlugin->Next) {
- SWMRGWaitToRead(ActualPlugin->Plugin->AccountBrowserSO, INFINITE);
- for (ActualAccount = ActualPlugin->Plugin->FirstAccount; ActualAccount != nullptr; ActualAccount = ActualAccount->Next) {
- if (ActualAccount->Plugin->Fcn == nullptr) //account not inited
- continue;
-
- if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO))
- continue;
-
- if ((ActualAccount->Flags & YAMN_ACC_ENA) && (ActualAccount->StatusFlags & YAMN_ACC_FORCE)) { //account cannot be forced to check
- if (ActualAccount->Plugin->Fcn->ForceCheckFcnPtr == nullptr) {
- ReadDoneFcn(ActualAccount->AccountAccessSO);
- continue;
- }
- struct CheckParam ParamToPlugin = { YAMN_CHECKVERSION, ThreadRunningEV, ActualAccount, YAMN_FORCECHECK, (void *)nullptr, nullptr };
-
- if (nullptr == CreateThread(nullptr, 0, (YAMN_STANDARDFCN)ActualAccount->Plugin->Fcn->ForceCheckFcnPtr, &ParamToPlugin, 0, &tid)) {
- ReadDoneFcn(ActualAccount->AccountAccessSO);
- continue;
- }
- else
- WaitForSingleObject(ThreadRunningEV, INFINITE);
- }
- ReadDoneFcn(ActualAccount->AccountAccessSO);
- }
- SWMRGDoneReading(ActualPlugin->Plugin->AccountBrowserSO);
- }
- }
-
- CloseHandle(ThreadRunningEV);
-
- if (hTTButton)
- CallService(MS_TTB_SETBUTTONSTATE, (WPARAM)hTTButton, 0);
- return 1;
-}
+/*
+ * This code implements miscellaneous usefull functions
+ *
+ * (c) majvan 2002-2004
+ */
+
+#include "stdafx.h"
+
+//--------------------------------------------------------------------------------------------------
+//--------------------------------------------------------------------------------------------------
+
+//Plugin registration CS
+//Used if we add (register) plugin to YAMN plugins and when we browse through registered plugins
+mir_cs PluginRegCS;
+
+//AccountWriterCS
+//We want to store number of writers of Accounts (number of Accounts used for writing)
+//If we want to read all accounts (for saving to file) immidiatelly, we have to wait until no account is changing (no thread writing to account)
+SCOUNTER *AccountWriterSO;
+
+//NoExitEV
+//Event that is signaled when there's a request to exit, so no new pop3 check should be performed
+HANDLE ExitEV;
+
+//WriteToFileEV
+//If this is signaled, write accounts to file is performed. Set this event if you want to actualize your accounts and messages
+HANDLE WriteToFileEV;
+
+//Returns pointer to YAMN exported function
+INT_PTR GetFcnPtrSvc(WPARAM wParam, LPARAM lParam);
+
+//Returns pointer to YAMN variables
+INT_PTR GetVariablesSvc(WPARAM wParam, LPARAM);
+
+// Function every seconds decrements account counter of seconds and checks if they are 0
+// If yes, creates a POP3 thread to check account
+void CALLBACK TimerProc(HWND, UINT, UINT, uint32_t);
+
+// Function called to check all accounts immidialtelly
+// no params
+INT_PTR ForceCheckSvc(WPARAM, LPARAM);
+
+//thread is running all the time
+//waits for WriteToFileEV and then writes all accounts to file
+//uint32_t WINAPI FileWritingThread(PVOID);
+
+// Function is called when Miranda notifies plugin that it is about to exit
+// Ensures succesfull end of POP3 checking, sets event that no next checking should be performed
+// If there's no writer to account (POP3 thread), saves the results to the file
+//not used now, perhaps in the future
+
+
+//int ExitProc(WPARAM wParam, LPARAM lParam);
+
+//--------------------------------------------------------------------------------------------------
+//--------------------------------------------------------------------------------------------------
+
+INT_PTR GetFcnPtrSvc(WPARAM wParam, LPARAM)
+{
+ int i;
+
+ for (i=0;i<sizeof(ProtoPluginExportedFcn)/sizeof(ProtoPluginExportedFcn[0]);i++)
+ if (0==mir_strcmp((char *)wParam, ProtoPluginExportedFcn[i].ID))
+ return (INT_PTR)ProtoPluginExportedFcn[i].Ptr;
+ for (i=0;i<sizeof(ProtoPluginExportedSvc)/sizeof(ProtoPluginExportedSvc[0]);i++)
+ if (0==mir_strcmp((char *)wParam, ProtoPluginExportedSvc[i].ID))
+ return (INT_PTR)ProtoPluginExportedSvc[i].Ptr;
+ for (i=0;i<sizeof(SynchroExportedFcn)/sizeof(SynchroExportedFcn[0]);i++)
+ if (0==mir_strcmp((char *)wParam, SynchroExportedFcn[i].ID))
+ return (INT_PTR)SynchroExportedFcn[i].Ptr;
+ for (i=0;i<sizeof(AccountExportedFcn)/sizeof(AccountExportedFcn[0]);i++)
+ if (0==mir_strcmp((char *)wParam, AccountExportedFcn[i].ID))
+ return (INT_PTR)AccountExportedFcn[i].Ptr;
+ for (i=0;i<sizeof(AccountExportedSvc)/sizeof(AccountExportedSvc[0]);i++)
+ if (0==mir_strcmp((char *)wParam, AccountExportedSvc[i].ID))
+ return (INT_PTR)AccountExportedSvc[i].Ptr;
+ for (i=0;i<sizeof(MailExportedFcn)/sizeof(MailExportedFcn[0]);i++)
+ if (0==mir_strcmp((char *)wParam, MailExportedFcn[i].ID))
+ return (INT_PTR)MailExportedFcn[i].Ptr;
+ for (i=0;i<sizeof(MailExportedSvc)/sizeof(MailExportedSvc[0]);i++)
+ if (0==mir_strcmp((char *)wParam, MailExportedSvc[i].ID))
+ return (INT_PTR)MailExportedSvc[i].Ptr;
+ for (i=0;i<sizeof(FilterPluginExportedFcn)/sizeof(FilterPluginExportedFcn[0]);i++)
+ if (0==mir_strcmp((char *)wParam, FilterPluginExportedFcn[i].ID))
+ return (INT_PTR)FilterPluginExportedFcn[i].Ptr;
+ for (i=0;i<sizeof(FilterPluginExportedSvc)/sizeof(FilterPluginExportedSvc[0]);i++)
+ if (0==mir_strcmp((char *)wParam, FilterPluginExportedSvc[i].ID))
+ return (INT_PTR)FilterPluginExportedSvc[i].Ptr;
+ return (INT_PTR)NULL;
+}
+
+INT_PTR GetVariablesSvc(WPARAM wParam, LPARAM)
+{
+ return wParam==YAMN_VARIABLESVERSION ? (INT_PTR)&YAMNVar : (INT_PTR)NULL;
+}
+
+void CALLBACK TimerProc(HWND, UINT, UINT_PTR, DWORD)
+{
+ CAccount *ActualAccount;
+ DWORD Status, tid;
+
+ // we use event to signal, that running thread has all needed stack parameters copied
+ HANDLE ThreadRunningEV = CreateEvent(nullptr, FALSE, FALSE, nullptr);
+ if (ThreadRunningEV == nullptr)
+ return;
+
+ // if we want to close miranda, we get event and do not run checking anymore
+ if (WAIT_OBJECT_0 == WaitForSingleObject(ExitEV, 0))
+ return;
+
+ // Get actual status of current user in Miranda
+ Status = CallService(MS_CLIST_GETSTATUSMODE, 0, 0);
+
+ mir_cslock lck(PluginRegCS);
+ for (PYAMN_PROTOPLUGINQUEUE ActualPlugin = FirstProtoPlugin; ActualPlugin != nullptr; ActualPlugin = ActualPlugin->Next) {
+ if (WAIT_OBJECT_0 != SWMRGWaitToRead(ActualPlugin->Plugin->AccountBrowserSO, 0)) // we want to access accounts immiadtelly
+ return;
+
+ for (ActualAccount = ActualPlugin->Plugin->FirstAccount; ActualAccount != nullptr; ActualAccount = ActualAccount->Next) {
+ if (ActualAccount->Plugin == nullptr || ActualAccount->Plugin->Fcn == nullptr) //account not inited
+ continue;
+
+ if (WAIT_OBJECT_0 != SWMRGWaitToRead(ActualAccount->AccountAccessSO, 0))
+ continue;
+
+ BOOL isAccountCounting = 0;
+ if ((ActualAccount->Flags & YAMN_ACC_ENA) &&
+ (((ActualAccount->StatusFlags & YAMN_ACC_ST0) && (Status <= ID_STATUS_OFFLINE)) ||
+ ((ActualAccount->StatusFlags & YAMN_ACC_ST1) && (Status == ID_STATUS_ONLINE)) ||
+ ((ActualAccount->StatusFlags & YAMN_ACC_ST2) && (Status == ID_STATUS_AWAY)) ||
+ ((ActualAccount->StatusFlags & YAMN_ACC_ST3) && (Status == ID_STATUS_DND)) ||
+ ((ActualAccount->StatusFlags & YAMN_ACC_ST4) && (Status == ID_STATUS_NA)) ||
+ ((ActualAccount->StatusFlags & YAMN_ACC_ST5) && (Status == ID_STATUS_OCCUPIED)) ||
+ ((ActualAccount->StatusFlags & YAMN_ACC_ST6) && (Status == ID_STATUS_FREECHAT)) ||
+ ((ActualAccount->StatusFlags & YAMN_ACC_ST7) && (Status == ID_STATUS_INVISIBLE))))
+ {
+ if ((!ActualAccount->Interval && !ActualAccount->TimeLeft) || ActualAccount->Plugin->Fcn->TimeoutFcnPtr == nullptr)
+ goto ChangeIsCountingStatusLabel;
+
+ if (ActualAccount->TimeLeft) {
+ ActualAccount->TimeLeft--;
+ isAccountCounting = TRUE;
+ }
+
+ WindowList_BroadcastAsync(YAMNVar.MessageWnds, WM_YAMN_CHANGETIME, (WPARAM)ActualAccount, (LPARAM)ActualAccount->TimeLeft);
+ if (!ActualAccount->TimeLeft) {
+ struct CheckParam ParamToPlugin = {YAMN_CHECKVERSION, ThreadRunningEV, ActualAccount, YAMN_NORMALCHECK, (void *)nullptr, nullptr};
+
+ ActualAccount->TimeLeft = ActualAccount->Interval;
+ HANDLE NewThread = CreateThread(nullptr, 0, (YAMN_STANDARDFCN)ActualAccount->Plugin->Fcn->TimeoutFcnPtr, &ParamToPlugin, 0, &tid);
+ if (NewThread == nullptr) {
+ ReadDoneFcn(ActualAccount->AccountAccessSO);
+ continue;
+ }
+ else {
+ WaitForSingleObject(ThreadRunningEV, INFINITE);
+ CloseHandle(NewThread);
+ }
+ }
+ }
+
+ChangeIsCountingStatusLabel:
+ if (((ActualAccount->isCounting) != 0) != isAccountCounting) {
+ ActualAccount->isCounting = isAccountCounting;
+ uint16_t cStatus = g_plugin.getWord(ActualAccount->hContact, "Status");
+ switch (cStatus) {
+ case ID_STATUS_ONLINE:
+ case ID_STATUS_OFFLINE:
+ g_plugin.setWord(ActualAccount->hContact, "Status", isAccountCounting ? ID_STATUS_ONLINE : ID_STATUS_OFFLINE);
+ default:
+ break;
+ }
+ }
+ ReadDoneFcn(ActualAccount->AccountAccessSO);
+ }
+ SWMRGDoneReading(ActualPlugin->Plugin->AccountBrowserSO);
+ }
+ CloseHandle(ThreadRunningEV);
+}
+
+INT_PTR ForceCheckSvc(WPARAM, LPARAM)
+{
+ CAccount *ActualAccount;
+ DWORD tid;
+
+ //we use event to signal, that running thread has all needed stack parameters copied
+ HANDLE ThreadRunningEV = CreateEvent(nullptr, FALSE, FALSE, nullptr);
+ if (ThreadRunningEV == nullptr)
+ return 0;
+ //if we want to close miranda, we get event and do not run pop3 checking anymore
+ if (WAIT_OBJECT_0 == WaitForSingleObject(ExitEV, 0))
+ return 0;
+
+ {
+ mir_cslock lck(PluginRegCS);
+ for (PYAMN_PROTOPLUGINQUEUE ActualPlugin = FirstProtoPlugin; ActualPlugin != nullptr; ActualPlugin = ActualPlugin->Next) {
+ SWMRGWaitToRead(ActualPlugin->Plugin->AccountBrowserSO, INFINITE);
+ for (ActualAccount = ActualPlugin->Plugin->FirstAccount; ActualAccount != nullptr; ActualAccount = ActualAccount->Next) {
+ if (ActualAccount->Plugin->Fcn == nullptr) //account not inited
+ continue;
+
+ if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO))
+ continue;
+
+ if ((ActualAccount->Flags & YAMN_ACC_ENA) && (ActualAccount->StatusFlags & YAMN_ACC_FORCE)) { //account cannot be forced to check
+ if (ActualAccount->Plugin->Fcn->ForceCheckFcnPtr == nullptr) {
+ ReadDoneFcn(ActualAccount->AccountAccessSO);
+ continue;
+ }
+ struct CheckParam ParamToPlugin = { YAMN_CHECKVERSION, ThreadRunningEV, ActualAccount, YAMN_FORCECHECK, (void *)nullptr, nullptr };
+
+ if (nullptr == CreateThread(nullptr, 0, (YAMN_STANDARDFCN)ActualAccount->Plugin->Fcn->ForceCheckFcnPtr, &ParamToPlugin, 0, &tid)) {
+ ReadDoneFcn(ActualAccount->AccountAccessSO);
+ continue;
+ }
+ else
+ WaitForSingleObject(ThreadRunningEV, INFINITE);
+ }
+ ReadDoneFcn(ActualAccount->AccountAccessSO);
+ }
+ SWMRGDoneReading(ActualPlugin->Plugin->AccountBrowserSO);
+ }
+ }
+
+ CloseHandle(ThreadRunningEV);
+
+ if (hTTButton)
+ CallService(MS_TTB_SETBUTTONSTATE, (WPARAM)hTTButton, 0);
+ return 1;
+}