summaryrefslogtreecommitdiff
path: root/protocols/YAMN/src/proto
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/proto
parentdd743899a769120ba2321230afddd6e4f1271872 (diff)
Convert sources to CR+LF
Diffstat (limited to 'protocols/YAMN/src/proto')
-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
4 files changed, 3042 insertions, 3042 deletions
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;
+}