diff options
author | George Hazan <ghazan@miranda.im> | 2019-03-02 12:32:44 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2019-03-02 12:32:55 +0300 |
commit | 931a7dc1ac0dbc7e6c1083583ced915e572f5b47 (patch) | |
tree | 9fe9a6448d44030e26aa7107ce16044ed413e0d0 /protocols/YAMN/src/proto | |
parent | dd7d9954042254e66e3bbbec7195c6be8b1a0663 (diff) |
all protocols (even virtual ones) moved to the Protocols folder
Diffstat (limited to 'protocols/YAMN/src/proto')
-rw-r--r-- | protocols/YAMN/src/proto/netclient.h | 22 | ||||
-rw-r--r-- | protocols/YAMN/src/proto/netlib.cpp | 242 | ||||
-rw-r--r-- | protocols/YAMN/src/proto/netlib.h | 51 | ||||
-rw-r--r-- | protocols/YAMN/src/proto/pop3/pop3.cpp | 356 | ||||
-rw-r--r-- | protocols/YAMN/src/proto/pop3/pop3.h | 63 | ||||
-rw-r--r-- | protocols/YAMN/src/proto/pop3/pop3comm.cpp | 1558 | ||||
-rw-r--r-- | protocols/YAMN/src/proto/pop3/pop3comm.h | 83 | ||||
-rw-r--r-- | protocols/YAMN/src/proto/pop3/pop3opt.cpp | 1481 | ||||
-rw-r--r-- | protocols/YAMN/src/proto/pop3/pop3opt.h | 40 |
9 files changed, 3896 insertions, 0 deletions
diff --git a/protocols/YAMN/src/proto/netclient.h b/protocols/YAMN/src/proto/netclient.h new file mode 100644 index 0000000000..99ec0888f1 --- /dev/null +++ b/protocols/YAMN/src/proto/netclient.h @@ -0,0 +1,22 @@ +#ifndef __CLIENT_H +#define __CLIENT_H + +class CNetClient +{ +public: + CNetClient(): Stopped(FALSE) {} + virtual void Connect(const char* servername, const int port)=0; + virtual void Send(const char *query)=0; + virtual char* Recv(char *buf= nullptr, int buflen=65536)=0; + virtual void Disconnect()=0; + virtual BOOL Connected()=0; + virtual void SSLify()=0; + + BOOL Stopped; + int Rcv; + DWORD NetworkError; + DWORD SystemError; + BOOL ifTLSed; +}; + +#endif diff --git a/protocols/YAMN/src/proto/netlib.cpp b/protocols/YAMN/src/proto/netlib.cpp new file mode 100644 index 0000000000..02fb6d3cdc --- /dev/null +++ b/protocols/YAMN/src/proto/netlib.cpp @@ -0,0 +1,242 @@ +/* + * 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(const char *name) +{ + char desc[128]; + + mir_snprintf(desc, Translate("%s connection"), name); + + #ifdef DEBUG_COMM + DebugLog(CommFile, "<Register PROXY support>"); + #endif + + NETLIBUSER nlu = {}; + nlu.flags = NUF_OUTGOING | NUF_HTTPCONNS; + nlu.szDescriptiveName.a = desc; + 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 = (DWORD)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 { + NETLIBOPENCONNECTION nloc; + nloc.cbSize = sizeof(NETLIBOPENCONNECTION); + nloc.szHost = servername; + nloc.wPort = port; + nloc.flags = 0; + if (nullptr == (hConnection = Netlib_OpenConnection(hNetlibUser, &nloc))) { + SystemError = WSAGetLastError(); + throw NetworkError = (DWORD)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 = (DWORD)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 = (DWORD)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 = (DWORD)ENL_RECV; + case 0: // time out! + free(buf); + throw NetworkError = (DWORD)ENL_TIMEOUT; + } + } + + memset(buf, 0, buflen); + if (SOCKET_ERROR == (Rcv = LocalNetlib_Recv(hConnection, buf, buflen, MSG_DUMPASTEXT))) { + free(buf); + SystemError = WSAGetLastError(); + throw NetworkError = (DWORD)ENL_RECV; + } + if (!Rcv) { + free(buf); + SystemError = WSAGetLastError(); + throw NetworkError = (DWORD)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/netlib.h b/protocols/YAMN/src/proto/netlib.h new file mode 100644 index 0000000000..778d6497ed --- /dev/null +++ b/protocols/YAMN/src/proto/netlib.h @@ -0,0 +1,51 @@ +#ifndef __NETLIB_H +#define __NETLIB_H + +class CNLClient: public CNetClient +{ +public: + CNLClient(): hConnection(nullptr) {} + void Connect(const char* servername, const int port) throw(DWORD); + void Send(const char *query) throw(DWORD); + char* Recv(char *buf= nullptr, int buflen = 65536) throw(DWORD); + void Disconnect(); + void SSLify()throw(DWORD); + + inline BOOL Connected() {return hConnection != nullptr;} + +protected: + HNETLIBCONN hConnection; + BOOL isTLSed; + int LocalNetlib_Send(HNETLIBCONN hConn, const char *buf, int len, int flags); + int LocalNetlib_Recv(HNETLIBCONN hConn, char *buf, int len, int flags); +}; + +void SSL_DebugLog(const char *fmt, ...); + +enum +{ + ENL_WINSOCKINIT=1, //error initializing socket //only wsock + ENL_GETHOSTBYNAME, //DNS error //only wsock + ENL_CREATESOCKET, //error creating socket //only wsock + ENL_CONNECT, //cannot connect to server + ENL_SEND, //cannot send data + ENL_RECV, //cannot receive data + ENL_RECVALLOC, //cannot allocate memory for received data + ENL_TIMEOUT, //timed out during recv +}; + +enum +{ + ESSL_NOTLOADED=1, //OpenSSL is not loaded + ESSL_WINSOCKINIT, //WinSock 2.0 init failed + ESSL_GETHOSTBYNAME, //DNS error + ESSL_CREATESOCKET, //error creating socket + ESSL_SOCKETCONNECT, //error connecting with socket + ESSL_CREATESSL, //error creating SSL session structure + ESSL_SETSOCKET, //error connect socket with SSL session for bidirect I/O space + ESSL_CONNECT, //cannot connect to server + ESSL_SEND, //cannot send data + ESSL_RECV, //cannot receive data + ESSL_RECVALLOC, //cannot allocate memory for received data +}; +#endif diff --git a/protocols/YAMN/src/proto/pop3/pop3.cpp b/protocols/YAMN/src/proto/pop3/pop3.cpp new file mode 100644 index 0000000000..d47fac4836 --- /dev/null +++ b/protocols/YAMN/src/proto/pop3/pop3.cpp @@ -0,0 +1,356 @@ +/* + * 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) +{ + char *temp = nullptr; + if (Stopped) //check if we can work with this POP3 client session + throw POP3Error=(DWORD)EPOP3_STOPPED; + + if (NetClient != nullptr) + 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; + } + } + + 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=(DWORD)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; + } +// temp = RecvRest(NetClient->Recv(),POP3_SEARCHACK); + } + } +// SSL_DebugLog("Received: %s",temp); + 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=(DWORD)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=(DWORD)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=(DWORD)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=(DWORD)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=(DWORD)EPOP3_STOPPED; + + char query[128]; + char *Result; + + mir_snprintf(query, "PASS %s\r\n", pw); + NetClient->Send(query); + Result=RecvRest(NetClient->Recv(),POP3_SEARCHACK); + if (AckFlag==POP3_FERR) + throw POP3Error=(DWORD)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=(DWORD)EPOP3_STOPPED; + + char query[512]; + char *Result; + unsigned char digest[16]; + + if (timestamp==nullptr) + throw POP3Error=(DWORD)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=(DWORD)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=(DWORD)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=(DWORD)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=(DWORD)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=(DWORD)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=(DWORD)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=(DWORD)EPOP3_STOPPED; + + char query[128]; + + mir_snprintf(query, "RETR %d\r\n", nr); + NetClient->Send(query); + RecvRest(NetClient->Recv(),POP3_SEARCHACK); + return NetClient->Recv(); +}
\ No newline at end of file diff --git a/protocols/YAMN/src/proto/pop3/pop3.h b/protocols/YAMN/src/proto/pop3/pop3.h new file mode 100644 index 0000000000..1fd7994bed --- /dev/null +++ b/protocols/YAMN/src/proto/pop3/pop3.h @@ -0,0 +1,63 @@ +#ifndef __POP3_H +#define __POP3_H + +#define DOTLINE(s) ((((s)[-2]=='\r') || ((s)[-2]=='\n')) && ((s)[-1]=='.') && (((s)[0]=='\r') || ((s)[0]=='\n') || ((s)[0]=='\0'))) // be careful, it's different to ESR's pop3.c ;-) +#define ENDLINE(s) (((s)[0]=='\r') || ((s)[0]=='\n')) //endline +#define OKLINE(s) (((s)[0]=='+') && (((s)[1]=='o') || ((s)[1]=='O')) && (((s)[2]=='k') || ((s)[2]=='K'))) // +OK +#define ERRLINE(s) (((s)[0]=='-') && (((s)[1]=='e') || ((s)[1]=='E')) && (((s)[2]=='r') || ((s)[2]=='R')) && (((s)[3]=='r') || ((s)[3]=='R'))) // -ERR +#define ACKLINE(s) (OKLINE(s) || ERRLINE(s)) + +#define POP3_SEARCHDOT 1 +#define POP3_SEARCHACK 2 +#define POP3_SEARCHOK 3 +#define POP3_SEARCHERR 4 +#define POP3_SEARCHNL 5 + +#define POP3_FOK 1 +#define POP3_FERR 2 + +class CPop3Client +{ +public: + CPop3Client(): NetClient(nullptr), Stopped(FALSE) {} + ~CPop3Client() {if (NetClient != nullptr) delete NetClient;} + + char* Connect(const char* servername,const int port=110,BOOL UseSSL=FALSE, BOOL NoTLS=FALSE); + char* RecvRest(char* prev,int mode,int size=65536); + char* User(char* name); + char* Pass(char* pw); + char* APOP(char* name, char* pw, char* timestamp); + char* Quit(); + char* Stat(); + char* List(); + char* Top(int nr, int lines=0); + char* Uidl(int nr=0); + char* Dele(int nr); + char* Retr(int nr); + + unsigned char AckFlag; + BOOL SSL; + BOOL Stopped; + + DWORD POP3Error; + class CNetClient *NetClient; //here the network layout is defined (TCP or SSL+TCP etc.) +private: + BOOL SearchFromEnd(char *end,int bs,int mode); + BOOL SearchFromStart(char *end,int bs,int mode); +}; + +enum +{ + EPOP3_QUEUEALLOC=1, //memory allocation + EPOP3_STOPPED, //stop account + EPOP3_CONNECT, //cannot connect to server + EPOP3_RESTALLOC, //cannot allocate memory for received data + EPOP3_BADUSER, //cannot login because USER command failed + EPOP3_BADPASS, //cannot login because PASS command failed + EPOP3_APOP, //server does not send timestamp for APOP auth + EPOP3_STAT, + EPOP3_LIST, + EPOP3_UIDL, +}; + +#endif diff --git a/protocols/YAMN/src/proto/pop3/pop3comm.cpp b/protocols/YAMN/src/proto/pop3/pop3comm.cpp new file mode 100644 index 0000000000..dad9ee1e28 --- /dev/null +++ b/protocols/YAMN/src/proto/pop3/pop3comm.cpp @@ -0,0 +1,1558 @@ +/* + * 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 +HACCOUNT WINAPI CreatePOP3Account(HYAMNPROTOPLUGIN Plugin, DWORD CAccountVersion); + +//Deletes CPOP3Account structure +void WINAPI DeletePOP3Account(HACCOUNT Which); + +//Sets stop flag to account +void WINAPI StopPOP3Account(HACCOUNT 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, HACCOUNT); + +//Function reads plugin's data for account from file +DWORD WINAPI ReadPOP3Options(HACCOUNT, char **, char *); + +//Creates new mail for an account +HYAMNMAIL WINAPI CreatePOP3Mail(HACCOUNT 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, DWORD 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(const 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((HACCOUNT)this, TranslateT("Disconnected")); +} + +CPOP3Account::~CPOP3Account() +{ + CloseHandle(UseInternetFree); + if (InternetQueries != nullptr) + delete InternetQueries; +} + +HACCOUNT 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 (HACCOUNT)new struct CPOP3Account(); +} + +void WINAPI DeletePOP3Account(HACCOUNT Which) +{ + delete (HPOP3ACCOUNT)Which; +} + +void WINAPI StopPOP3Account(HACCOUNT 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, (WPARAM)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)) + { + UnLoadPOP3(nullptr); return 0; + } + + //Register new pop3 user in netlib + if (nullptr == (hNetLib = RegisterNLClient("YAMN-POP3"))) + { + UnLoadPOP3(nullptr); return 0; + } + + 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)) + { + UnLoadPOP3(nullptr); return 0; + } + + 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)) + { + UnLoadPOP3(nullptr); return 0; + } + } + + //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 HACCOUNT + 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; + } + + HACCOUNT Finder; + DBVARIANT dbv; + + for (Finder = POP3Plugin->FirstAccount; Finder != nullptr; Finder = Finder->Next) { + Finder->hContact = NULL; + for (auto &hContact : Contacts(YAMN_DBMODULE)) { + 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)) + db_unset(Finder->hContact, "CList", "Hidden"); + + if (!(Finder->Flags & YAMN_ACC_ENA) || !(Finder->NewMailN.Flags & YAMN_ACC_CONT)) + db_set_b(Finder->hContact, "CList", "Hidden", 1); + } + 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", YAMN_STATUS); + } + } + + 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; + } + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"UnLoadPOP3:done\n"); +#endif + return 1; +} + +DWORD WINAPI WritePOP3Accounts() +{ + DWORD 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, HACCOUNT Which) +{ + DWORD WrittenBytes; + DWORD Ver = POP3_FILEVERSION; + + if ((!WriteFile(File, (char *)&Ver, sizeof(DWORD), &WrittenBytes, nullptr)) || + (!WriteFile(File, (char *)&((HPOP3ACCOUNT)Which)->CP, sizeof(WORD), &WrittenBytes, nullptr))) + return EACC_SYSTEM; + return 0; +} + +DWORD WINAPI ReadPOP3Options(HACCOUNT Which, char **Parser, char *End) +{ + DWORD Ver; +#ifdef DEBUG_FILEREAD + wchar_t Debug[256]; +#endif + Ver = *(DWORD *)(*Parser); + (*Parser) += sizeof(DWORD); + if (*Parser >= End) + return EACC_FILECOMPATIBILITY; + if (Ver != POP3_FILEVERSION) + return EACC_FILECOMPATIBILITY; + + ((HPOP3ACCOUNT)Which)->CP = *(WORD *)(*Parser); + (*Parser) += sizeof(WORD); + 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(HACCOUNT 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 MAILDATA)) + { + delete NewMail; + return nullptr; + } + NewMail->MailData->CP = ((HPOP3ACCOUNT)Account)->CP; + return (HYAMNMAIL)NewMail; +} + +static void SetContactStatus(HACCOUNT 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, DWORD 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 == (DWORD)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)) + { + YAMN_BADCONNECTIONPARAM cp = { (HANDLE)nullptr, ActualAccount, (UINT_PTR)ErrorCode, ParamToBadConnection }; + + CallService(MS_YAMN_BADCONNECTION, (WPARAM)&cp, (LPARAM)YAMN_BADCONNECTIONVERSION); + } + if (POP3PluginParam == (DWORD)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; + DWORD CheckFlags; + BOOL UsingInternet = FALSE; + struct { + char *ServerName; + DWORD ServerPort; + char *ServerLogin; + char *ServerPasswd; + DWORD Flags; + DWORD NFlags; + DWORD 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 (DWORD)-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; +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:Incrementing \"using threads\" %x (account %x)\n",ActualAccount->UsingThreads,ActualAccount); +#endif + 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); + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountSO-read wait\n"); +#endif + if (WAIT_OBJECT_0 != WaitToRead(ActualAccount)) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountSO-read wait failed\n"); +#endif +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:Decrementing \"using threads\" %x (account %x)\n",ActualAccount->UsingThreads,ActualAccount); +#endif + SCDec(ActualAccount->UsingThreads); + return 0; + } +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountSO-read enter\n"); +#endif + 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; + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountSO-read done\n"); +#endif + ReadDone(ActualAccount); + + SCInc(ActualAccount->InternetQueries); //increment counter, that there is one more thread waiting for connection +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:InternetFreeEV-wait\n"); +#endif + WaitForSingleObject(ActualAccount->UseInternetFree, INFINITE); //wait until we can use connection +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:InternetFreeEV-enter\n"); +#endif + 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) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:stop signal-InternetFreeEV-done\n"); +#endif + SetEvent(ActualAccount->UseInternetFree); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:stop signal-Decrementing \"using threads\" %x (account %x)\n",ActualAccount->UsingThreads,ActualAccount); +#endif + 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); +#ifdef DEBUG_COMM + DebugLog(CommFile,"<--------Communication-------->\n"); +#endif + // 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(); + +#ifdef DEBUG_DECODE + DebugLog(DecodeFile,"<--------Account checking-------->\n"); + 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 (DWORD)ActualAccount->SystemError; + } + } + + if (msgs) + { + DataRX = MyClient->List(); +#ifdef DEBUG_DECODE + DebugLog(DecodeFile,"<Extracting list>\n"); +#endif + ExtractList(DataRX, MyClient->NetClient->Rcv, NewMails); +#ifdef DEBUG_DECODE + DebugLog(DecodeFile,"</Extracting list>\n"); +#endif + if (DataRX != nullptr) + free(DataRX); + DataRX = nullptr; + +#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; + } +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountMsgsSO-write wait\n"); +#endif + if (WAIT_OBJECT_0 != MsgsWaitToWrite(ActualAccount)) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountMsgsSO-write wait failed\n"); +#endif + throw (DWORD)(ActualAccount->SystemError = EACC_STOPPED); + } +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountMsgsSO-write enter\n"); +#endif + 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); +#ifdef DEBUG_DECODE + DebugLog(DecodeFile,"<Reading body>\n"); + DebugLog(DecodeFile,"<Header>%s</Header>\n",DataRX); +#endif + 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); + + +#ifdef DEBUG_DECODE + DebugLog(DecodeFile,"</Reading body>\n"); +#endif + 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! + // NewMails=NULL; + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountMsgsSO-write done\n"); +#endif + 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); + +#ifdef DEBUG_DECODE + DebugLog(DecodeFile,"<New mail>\n"); + DebugLog(DecodeFile,"<Header>%s</Header>\n",DataRX); +#endif + 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; + + } +#ifdef DEBUG_DECODE + DebugLog(DecodeFile,"</--------Account checking-------->\n"); +#endif + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountMsgsSO-write wait\n"); +#endif + if (WAIT_OBJECT_0 != MsgsWaitToWrite(ActualAccount)) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountMsgsSO-write wait failed\n"); +#endif + throw (DWORD)ActualAccount->SystemError == EACC_STOPPED; + } +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountMsgsSO-write enter\n"); +#endif + if (ActualAccount->Mails == nullptr) + ActualAccount->Mails = NewMails; + else + { + ActualAccount->LastMail = ActualAccount->LastChecked; + AppendQueue((HYAMNMAIL)ActualAccount->Mails, NewMails); + } +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountMsgsSO-write done\n"); +#endif + 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; +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:InternetFreeEV-done\n"); +#endif + 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(DWORD ErrorCode) +#else + catch (DWORD) +#endif + { + if (ActualAccount->Client.POP3Error == EPOP3_STOPPED) + ActualAccount->SystemError = EACC_STOPPED; +#ifdef DEBUG_COMM + DebugLog(CommFile,"ERROR: %x\n",ErrorCode); +#endif +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountMsgsSO-write wait\n"); +#endif + if (WAIT_OBJECT_0 == MsgsWaitToWrite(ActualAccount)) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountMsgsSO-write enter\n"); +#endif + ActualAccount->LastChecked = now; +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountMsgsSO-write done\n"); +#endif + MsgsWriteDone(ActualAccount); + } +#ifdef DEBUG_SYNCHRO + else + DebugLog(SynchroFile,"CheckPOP3:ActualAccountMsgsSO-write wait failed\n"); +#endif + + 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, (DWORD)NULL, MyClient->SSL); //it closes internet connection too + } + + if (UsingInternet) //if our thread still uses internet + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:InternetFreeEV-done\n"); +#endif + 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(); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:Decrementing \"using threads\" %x (account %x)\n",ActualAccount->UsingThreads,ActualAccount); +#endif + 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; + DWORD ServerPort; + char *ServerLogin; + char *ServerPasswd; + DWORD Flags; + DWORD NFlags; + DWORD 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 (DWORD)-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; +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:Incrementing \"using threads\" %x (account %x)\n",ActualAccount->UsingThreads,ActualAccount); +#endif + SCInc(ActualAccount->UsingThreads); + if (INVALID_HANDLE_VALUE != WhichTemp->ThreadRunningEV) + SetEvent(WhichTemp->ThreadRunningEV); + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:ActualAccountSO-read wait\n"); +#endif + if (WAIT_OBJECT_0 != WaitToRead(ActualAccount)) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:ActualAccountSO-read wait failed\n"); +#endif +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:Decrementing \"using threads\" %x (account %x)\n",ActualAccount->UsingThreads,ActualAccount); +#endif + SCDec(ActualAccount->UsingThreads); + return; + } +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:ActualAccountSO-read enter\n"); +#endif + 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); + } +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:ActualAccountSO-read done\n"); +#endif + ReadDone(ActualAccount); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:Decrementing \"using threads\" %x (account %x)\n",ActualAccount->UsingThreads,ActualAccount); +#endif + 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; + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:ActualAccountSO-read done\n"); +#endif + 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 + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:InternetFreeEV-wait\n"); +#endif + WaitForSingleObject(ActualAccount->UseInternetFree, INFINITE); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:InternetFreeEV-enter\n"); +#endif + } + 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 (DWORD)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")); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:ActualAccountMsgsSO-write wait\n"); +#endif + if (WAIT_OBJECT_0 != MsgsWaitToWrite(ActualAccount)) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:ActualAccountMsgsSO-write wait failed\n"); +#endif + throw (DWORD)EACC_STOPPED; + } +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:ActualAccountMsgsSO-write enter\n"); +#endif + 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 + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:ActualAccountMsgsSO-write done\n"); +#endif + 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; + } +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:ActualAccountMsgsSO-write done\n"); +#endif + 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; +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:InternetFreeEV-done\n"); +#endif + SetEvent(ActualAccount->UseInternetFree); + } + SetContactStatus(ActualAccount, ActualAccount->isCounting ? ID_STATUS_ONLINE : ID_STATUS_OFFLINE); + } +#ifdef DEBUG_COMM + catch(DWORD ErrorCode) +#else + catch (DWORD) +#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 + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:InternetFreeEV-done\n"); +#endif + 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(); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:Decrementing \"using threads\" %x (account %x)\n",ActualAccount->UsingThreads,ActualAccount); +#endif + 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 (DWORD)EPOP3_STAT; + while (!WS(finder)) finder++; + while (WS(finder)) finder++; + if (1 != sscanf(finder, "%d", mboxsize)) + throw (DWORD)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 (DWORD)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 (DWORD)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 (DWORD)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 (DWORD)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 (DWORD)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 (DWORD)EPOP3_LIST; + while (!WS(finder)) finder++; //jump characters + while (WS(finder)) finder++; //jump whitespace + finderend = finder + 1; + if (1 != sscanf(finder, "%d", &queueptr->MailData->Size)) + throw (DWORD)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/pop3comm.h b/protocols/YAMN/src/proto/pop3/pop3comm.h new file mode 100644 index 0000000000..3d98675d3c --- /dev/null +++ b/protocols/YAMN/src/proto/pop3/pop3comm.h @@ -0,0 +1,83 @@ +#ifndef __POP3COMM_H +#define __POP3COMM_H + +#define POP3_FILEVERSION 1 //Version of aditional information stored in book file + +typedef struct CPOP3Account: public CAccount +{ +// We can use SCOUNTER structure, because this is internal plugin. +// This SO is used to determine if any POP3 account is in "write access" mode + static PSCOUNTER AccountWriterSO; + +// It is usefull to have client structure in account. With this structure we have access to account's socket. +// This is related to InternetQueries and UseInternetFree +// This member should be synchronized with UseInternetFree + class CPop3Client Client; + +// This member is usefull for MIME headers. It is default codepage, if no other codepage found + WORD CP; //access only through AccountAccessSO + +// In this memeber last error code is stored + DWORD SystemError; //access through UseInternetFree + +// We use only counter from this object and it is # of threads waiting to work on internet. +// We use event UseInternet to access critical sections. +// It is usefull in 2 ways: we have mutual exclusion that only one thread works with account on internet. +// Thread, which has done its work with account on internet can close socket, but it is not needed, when any other +// thread wants to work (e.g. we have deleted mails, but when deleting, another thread wants to check new mail, so +// we delete all needed mails and check if there's thread that wants to work. If yes, we do not need to quit session, +// we leave socket open, and leave internet. Another thread then start checking and does not connect, does not send +// user and password... because socket is open- it continues) + PSCOUNTER InternetQueries; + HANDLE UseInternetFree; + + CPOP3Account(); + ~CPOP3Account(); + +} POP3ACCOUNT,*HPOP3ACCOUNT; + +typedef struct POP3LayeredError +{ + BOOL SSL; + DWORD AppError; + DWORD POP3Error; + DWORD NetError; + DWORD SystemError; +} POP3_ERRORCODE,*PPOP3_ERRORCODE; + +struct YAMNExportedFcns +{ + YAMN_SETPROTOCOLPLUGINFCNIMPORTFCN SetProtocolPluginFcnImportFcn; + YAMN_WAITTOWRITEFCN WaitToWriteFcn; + YAMN_WRITEDONEFCN WriteDoneFcn; + YAMN_WAITTOREADFCN WaitToReadFcn; + YAMN_READDONEFCN ReadDoneFcn; + YAMN_SCMANAGEFCN SCGetNumberFcn; + YAMN_SCMANAGEFCN SCIncFcn; + YAMN_SCMANAGEFCN SCDecFcn; + YAMN_SETSTATUSFCN SetStatusFcn; + YAMN_GETSTATUSFCN GetStatusFcn; +}; + +struct MailExportedFcns +{ + YAMN_SYNCHROMIMEMSGSFCN SynchroMessagesFcn; + YAMN_TRANSLATEHEADERFCN TranslateHeaderFcn; + YAMN_APPENDQUEUEFCN AppendQueueFcn; + YAMN_DELETEMIMEQUEUEFCN DeleteMessagesToEndFcn; + YAMN_DELETEMIMEMESSAGEFCN DeleteMessageFromQueueFcn; + YAMN_FINDMIMEMESSAGEFCN FindMessageByIDFcn; + YAMN_CREATENEWDELETEQUEUEFCN CreateNewDeleteQueueFcn; +}; + +enum +{ + EACC_QUEUEALLOC=1, //memory allocation + EACC_STOPPED, //stop account +}; + +#define NO_MAIL_FOR_DELETE 1 + +#define POP3_DELETEFROMCHECK 1 + +#endif diff --git a/protocols/YAMN/src/proto/pop3/pop3opt.cpp b/protocols/YAMN/src/proto/pop3/pop3opt.cpp new file mode 100644 index 0000000000..b22b237e47 --- /dev/null +++ b/protocols/YAMN/src/proto/pop3/pop3opt.cpp @@ -0,0 +1,1481 @@ +/* + * This code implements POP3 options window handling + * + * (c) majvan 2002-2003 +*/ + +#include "../../stdafx.h" + +//-------------------------------------------------------------------------------------------------- + +static BOOL Check0, Check1, Check2, Check3, Check4, Check5, Check6, Check7, Check8, Check9; +static char DlgInput[MAX_PATH]; + +void CheckMenuItems(); + +//-------------------------------------------------------------------------------------------------- + +INT_PTR CALLBACK DlgProcYAMNOpt(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hDlg); + CheckDlgButton(hDlg, IDC_CHECKTTB, g_plugin.getByte(YAMN_TTBFCHECK, 1) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_LONGDATE, (optDateTime&SHOWDATELONG) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_SMARTDATE, (optDateTime&SHOWDATENOTODAY) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_NOSECONDS, (optDateTime&SHOWDATENOSECONDS) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_MAINMENU, g_plugin.getByte(YAMN_SHOWMAINMENU, 1) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_YAMNASPROTO, g_plugin.getByte(YAMN_SHOWASPROTO, 1) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CLOSEONDELETE, g_plugin.getByte(YAMN_CLOSEDELETE, 0) ? BST_CHECKED : BST_UNCHECKED); + break; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_YAMNASPROTO: + case IDC_MAINMENU: + case IDC_CHECKTTB: + case IDC_CLOSEONDELETE: + case IDC_LONGDATE: + case IDC_SMARTDATE: + case IDC_NOSECONDS: + SendMessage(GetParent(hDlg), PSM_CHANGED, 0, 0); + break; + } + break; + + case WM_NOTIFY: + switch (((LPNMHDR)lParam)->idFrom) { + case 0: + switch (((LPNMHDR)lParam)->code) { + case PSN_APPLY: + g_plugin.setByte(YAMN_SHOWASPROTO, IsDlgButtonChecked(hDlg, IDC_YAMNASPROTO)); + g_plugin.setByte(YAMN_SHOWMAINMENU, IsDlgButtonChecked(hDlg, IDC_MAINMENU)); + g_plugin.setByte(YAMN_CLOSEDELETE, IsDlgButtonChecked(hDlg, IDC_CLOSEONDELETE)); + g_plugin.setByte(YAMN_TTBFCHECK, IsDlgButtonChecked(hDlg, IDC_CHECKTTB)); + + AddTopToolbarIcon(0, 0); + CheckMenuItems(); + + optDateTime = 0; + if (IsDlgButtonChecked(hDlg, IDC_LONGDATE))optDateTime |= SHOWDATELONG; + if (IsDlgButtonChecked(hDlg, IDC_SMARTDATE))optDateTime |= SHOWDATENOTODAY; + if (IsDlgButtonChecked(hDlg, IDC_NOSECONDS))optDateTime |= SHOWDATENOSECONDS; + g_plugin.setByte(YAMN_DBTIMEOPTIONS, optDateTime); + } + } + break; + } + + return FALSE; +} + +INT_PTR CALLBACK DlgProcPluginOpt(HWND hDlg, UINT msg, WPARAM wParam, LPARAM) +{ + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hDlg); + break; + + case WM_COMMAND: + { + WORD wNotifyCode = HIWORD(wParam); + switch (LOWORD(wParam)) { + case IDC_COMBOPLUGINS: + if (wNotifyCode == CBN_SELCHANGE) { + HWND hCombo = GetDlgItem(hDlg, IDC_COMBOPLUGINS); + PYAMN_PROTOPLUGINQUEUE PParser; + PYAMN_FILTERPLUGINQUEUE FParser; + int index, id; + + if (CB_ERR == (index = SendMessage(hCombo, CB_GETCURSEL, 0, 0))) + break; + id = SendMessage(hCombo, CB_GETITEMDATA, (WPARAM)index, 0); + + mir_cslock lck(PluginRegCS); + for (PParser = FirstProtoPlugin; PParser != nullptr; PParser = PParser->Next) + if (id == (INT_PTR)PParser->Plugin) { + SetDlgItemTextA(hDlg, IDC_STVER, PParser->Plugin->PluginInfo->Ver); + SetDlgItemTextA(hDlg, IDC_STDESC, PParser->Plugin->PluginInfo->Description == nullptr ? "" : PParser->Plugin->PluginInfo->Description); + SetDlgItemTextA(hDlg, IDC_STCOPY, PParser->Plugin->PluginInfo->Copyright == nullptr ? "" : PParser->Plugin->PluginInfo->Copyright); + SetDlgItemTextA(hDlg, IDC_STWWW, PParser->Plugin->PluginInfo->WWW == nullptr ? "" : PParser->Plugin->PluginInfo->WWW); + break; + } + for (FParser = FirstFilterPlugin; FParser != nullptr; FParser = FParser->Next) + if (id == (INT_PTR)FParser->Plugin) { + SetDlgItemTextA(hDlg, IDC_STVER, FParser->Plugin->PluginInfo->Ver); + SetDlgItemTextA(hDlg, IDC_STDESC, FParser->Plugin->PluginInfo->Description == nullptr ? "" : FParser->Plugin->PluginInfo->Description); + SetDlgItemTextA(hDlg, IDC_STCOPY, FParser->Plugin->PluginInfo->Copyright == nullptr ? "" : FParser->Plugin->PluginInfo->Copyright); + SetDlgItemTextA(hDlg, IDC_STWWW, FParser->Plugin->PluginInfo->WWW == nullptr ? "" : FParser->Plugin->PluginInfo->WWW); + break; + } + } + break; + case IDC_STWWW: + { + char str[1024]; + GetDlgItemTextA(hDlg, IDC_STWWW, str, _countof(str)); + Utils_OpenUrl(str); + break; + } + + } + break; + } + case WM_SHOWWINDOW: + if (TRUE == (BOOL)wParam) { + { + mir_cslock lck(PluginRegCS); + for (PYAMN_PROTOPLUGINQUEUE PParser = FirstProtoPlugin; PParser != nullptr; PParser = PParser->Next) { + int index = SendDlgItemMessageA(hDlg, IDC_COMBOPLUGINS, CB_ADDSTRING, 0, (LPARAM)PParser->Plugin->PluginInfo->Name); + SendDlgItemMessage(hDlg, IDC_COMBOPLUGINS, CB_SETITEMDATA, (WPARAM)index, (LPARAM)PParser->Plugin); + } + for (PYAMN_FILTERPLUGINQUEUE FParser = FirstFilterPlugin; FParser != nullptr; FParser = FParser->Next) { + int index = SendDlgItemMessageA(hDlg, IDC_COMBOPLUGINS, CB_ADDSTRING, 0, (LPARAM)FParser->Plugin->PluginInfo->Name); + SendDlgItemMessage(hDlg, IDC_COMBOPLUGINS, CB_SETITEMDATA, (WPARAM)index, (LPARAM)FParser->Plugin); + } + } + + SendDlgItemMessage(hDlg, IDC_COMBOPLUGINS, CB_SETCURSEL, 0, 0); + SendMessage(hDlg, WM_COMMAND, MAKELONG(IDC_COMBOPLUGINS, CBN_SELCHANGE), 0); + break; + } + else { //delete all items in combobox + int cbn = SendDlgItemMessage(hDlg, IDC_COMBOPLUGINS, CB_GETCOUNT, 0, 0); + for (int i = 0; i < cbn; i++) + SendDlgItemMessage(hDlg, IDC_COMBOPLUGINS, CB_DELETESTRING, 0, 0); + break; + } + } + + return FALSE; +} + + +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.pszTemplate = MAKEINTRESOURCEA(IDD_POP3ACCOUNTOPT); + odp.pfnDlgProc = DlgProcPOP3AccOpt; + g_plugin.addOptions(wParam, &odp); + + odp.szTab.a = LPGEN("General"); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_YAMNOPT); + odp.pfnDlgProc = DlgProcYAMNOpt; + g_plugin.addOptions(wParam, &odp); + + odp.szTab.a = LPGEN("Plugins"); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_PLUGINOPT); + odp.pfnDlgProc = DlgProcPluginOpt; + g_plugin.addOptions(wParam, &odp); + + if (ServiceExists(MS_POPUP_ADDPOPUPW)) { + odp.szGroup.a = LPGEN("Popups"); + odp.szTab.a = LPGEN("YAMN"); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_POP3ACCOUNTPOPUP); + odp.pfnDlgProc = DlgProcPOP3AccPopup; + g_plugin.addOptions(wParam, &odp); + } + return 0; +} + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- +BOOL DlgEnableAccountStatus(HWND hDlg, WPARAM wParam, LPARAM) +{ + EnableWindow(GetDlgItem(hDlg, IDC_CHECKST0), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKST1), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKST2), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKST3), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKST4), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKST5), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKST6), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKST7), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKST8), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKST9), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKST9), (BOOL)wParam); + return TRUE; +} + +BOOL DlgEnableAccountPopup(HWND hDlg, WPARAM wParam, LPARAM) +{ + EnableWindow(GetDlgItem(hDlg, IDC_CHECKPOP), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_EDITPOPS), (IsDlgButtonChecked(hDlg, IDC_CHECKPOP) == BST_CHECKED) && wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKCOL), (IsDlgButtonChecked(hDlg, IDC_CHECKPOP) == BST_CHECKED) && wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CPB), (IsDlgButtonChecked(hDlg, IDC_CHECKCOL) == BST_CHECKED) && (IsDlgButtonChecked(hDlg, IDC_CHECKPOP) == BST_CHECKED) && wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CPT), (IsDlgButtonChecked(hDlg, IDC_CHECKCOL) == BST_CHECKED) && (IsDlgButtonChecked(hDlg, IDC_CHECKPOP) == BST_CHECKED) && wParam); + EnableWindow(GetDlgItem(hDlg, IDC_RADIOPOPN), (IsDlgButtonChecked(hDlg, IDC_CHECKPOP) == BST_CHECKED) && wParam); + EnableWindow(GetDlgItem(hDlg, IDC_RADIOPOP1), (IsDlgButtonChecked(hDlg, IDC_CHECKPOP) == BST_CHECKED) && wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKNPOP), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_EDITNPOPS), (IsDlgButtonChecked(hDlg, IDC_CHECKNPOP) == BST_CHECKED) && wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKNCOL), (IsDlgButtonChecked(hDlg, IDC_CHECKNPOP) == BST_CHECKED) && wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CPNB), (IsDlgButtonChecked(hDlg, IDC_CHECKNCOL) == BST_CHECKED) && (IsDlgButtonChecked(hDlg, IDC_CHECKNPOP) == BST_CHECKED) && wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CPNT), (IsDlgButtonChecked(hDlg, IDC_CHECKNCOL) == BST_CHECKED) && (IsDlgButtonChecked(hDlg, IDC_CHECKNPOP) == BST_CHECKED) && wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKFPOP), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_EDITFPOPS), (IsDlgButtonChecked(hDlg, IDC_CHECKFPOP) == BST_CHECKED) && wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKFCOL), (IsDlgButtonChecked(hDlg, IDC_CHECKFPOP) == BST_CHECKED) && wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CPFB), (IsDlgButtonChecked(hDlg, IDC_CHECKFCOL) == BST_CHECKED) && (IsDlgButtonChecked(hDlg, IDC_CHECKFPOP) == BST_CHECKED) && wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CPFT), (IsDlgButtonChecked(hDlg, IDC_CHECKFCOL) == BST_CHECKED) && (IsDlgButtonChecked(hDlg, IDC_CHECKFPOP) == BST_CHECKED) && wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKAPOP), (BOOL)wParam); + return TRUE; +} + +BOOL DlgEnableAccount(HWND hDlg, WPARAM wParam, LPARAM) +{ + EnableWindow(GetDlgItem(hDlg, IDC_CHECK), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_EDITSERVER), wParam); + EnableWindow(GetDlgItem(hDlg, IDC_EDITNAME), wParam); + EnableWindow(GetDlgItem(hDlg, IDC_EDITPORT), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_EDITLOGIN), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_EDITPASS), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_EDITINTERVAL), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKSND), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKMSG), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKICO), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKAPP), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKKBN), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_BTNAPP), (IsDlgButtonChecked(hDlg, IDC_CHECKAPP) == BST_CHECKED) && wParam); + EnableWindow(GetDlgItem(hDlg, IDC_EDITAPP), (IsDlgButtonChecked(hDlg, IDC_CHECKAPP) == BST_CHECKED) && wParam); + EnableWindow(GetDlgItem(hDlg, IDC_EDITAPPPARAM), (IsDlgButtonChecked(hDlg, IDC_CHECKAPP) == BST_CHECKED) && wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKNMSGP), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKFSND), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKFMSG), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKFICO), (BOOL)wParam); + /*EnableWindow(GetDlgItem(hDlg,IDC_CHECKST0),(BOOL)wParam); + EnableWindow(GetDlgItem(hDlg,IDC_CHECKST1),(BOOL)wParam); + EnableWindow(GetDlgItem(hDlg,IDC_CHECKST2),(BOOL)wParam); + EnableWindow(GetDlgItem(hDlg,IDC_CHECKST3),(BOOL)wParam); + EnableWindow(GetDlgItem(hDlg,IDC_CHECKST4),(BOOL)wParam); + EnableWindow(GetDlgItem(hDlg,IDC_CHECKST5),(BOOL)wParam); + EnableWindow(GetDlgItem(hDlg,IDC_CHECKST6),(BOOL)wParam); + EnableWindow(GetDlgItem(hDlg,IDC_CHECKST7),(BOOL)wParam); + EnableWindow(GetDlgItem(hDlg,IDC_CHECKST8),(BOOL)wParam); + EnableWindow(GetDlgItem(hDlg,IDC_CHECKST9),(BOOL)wParam); + EnableWindow(GetDlgItem(hDlg,IDC_CHECKST9),(BOOL)wParam);*/ + EnableWindow(GetDlgItem(hDlg, IDC_CHECKSTART), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKFORCE), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_COMBOCP), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_STTIMELEFT), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_BTNRESET), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_BTNDEFAULT), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_BTNSTATUS), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKSSL), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKNOTLS), (IsDlgButtonChecked(hDlg, IDC_CHECKSSL) == BST_UNCHECKED) && wParam); + EnableWindow(GetDlgItem(hDlg, IDC_AUTOBODY), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKCONTACT), (BOOL)wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKCONTACTNICK), (IsDlgButtonChecked(hDlg, IDC_CHECKCONTACT) == BST_CHECKED) && wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKCONTACTNOEVENT), (IsDlgButtonChecked(hDlg, IDC_CHECKCONTACT) == BST_CHECKED) && wParam); + return TRUE; +} +BOOL DlgShowAccountStatus(HWND hDlg, WPARAM wParam, LPARAM lParam) +{ + HPOP3ACCOUNT ActualAccount = (HPOP3ACCOUNT)lParam; + + if ((DWORD)wParam == M_SHOWACTUAL) { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:SHOWACCOUNT:ActualAccountSO-read wait\n"); + #endif + 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 + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:SHOWACCOUNT:ActualAccountSO-read enter\n"); + #endif + 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); + CheckDlgButton(hDlg, IDC_CHECKST8, ActualAccount->StatusFlags & YAMN_ACC_ST8 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKST9, ActualAccount->StatusFlags & YAMN_ACC_ST9 ? 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); + CheckDlgButton(hDlg, IDC_CHECKST8, BST_CHECKED); + CheckDlgButton(hDlg, IDC_CHECKST9, BST_CHECKED); + } + return TRUE; +} +BOOL DlgShowAccountPopup(HWND hDlg, WPARAM wParam, LPARAM lParam) +{ + HPOP3ACCOUNT ActualAccount = (HPOP3ACCOUNT)lParam; + + if ((DWORD)wParam == M_SHOWACTUAL) { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:SHOWACCOUNT:ActualAccountSO-read wait\n"); + #endif + 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 + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:SHOWACCOUNT:ActualAccountSO-read enter\n"); + #endif + SetDlgItemInt(hDlg, IDC_EDITPOPS, ActualAccount->NewMailN.PopupTime, FALSE); + SetDlgItemInt(hDlg, IDC_EDITNPOPS, ActualAccount->NoNewMailN.PopupTime, FALSE); + SetDlgItemInt(hDlg, IDC_EDITFPOPS, ActualAccount->BadConnectN.PopupTime, FALSE); + + + CheckDlgButton(hDlg, IDC_CHECKPOP, ActualAccount->NewMailN.Flags & YAMN_ACC_POP ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKCOL, ActualAccount->NewMailN.Flags & YAMN_ACC_POPC ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKNPOP, ActualAccount->NoNewMailN.Flags & YAMN_ACC_POP ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKNCOL, ActualAccount->NoNewMailN.Flags & YAMN_ACC_POPC ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKFPOP, ActualAccount->BadConnectN.Flags & YAMN_ACC_POP ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKFCOL, ActualAccount->BadConnectN.Flags & YAMN_ACC_POPC ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_RADIOPOPN, ActualAccount->Flags & YAMN_ACC_POPN ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_RADIOPOP1, ActualAccount->Flags & YAMN_ACC_POPN ? BST_UNCHECKED : BST_CHECKED); + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:SHOWACCOUNT:ActualAccountSO-read done\n"); + #endif + ReadDone(ActualAccount); + } + else //default + { + + SetDlgItemInt(hDlg, IDC_EDITPOPS, 0, FALSE); + SetDlgItemInt(hDlg, IDC_EDITNPOPS, 0, FALSE); + SetDlgItemInt(hDlg, IDC_EDITFPOPS, 0, FALSE); + CheckDlgButton(hDlg, IDC_CHECKPOP, BST_CHECKED); + CheckDlgButton(hDlg, IDC_CHECKCOL, BST_CHECKED); + CheckDlgButton(hDlg, IDC_CHECKNPOP, BST_CHECKED); + CheckDlgButton(hDlg, IDC_CHECKNCOL, BST_CHECKED); + CheckDlgButton(hDlg, IDC_CHECKFPOP, BST_CHECKED); + CheckDlgButton(hDlg, IDC_CHECKFCOL, BST_CHECKED); + CheckDlgButton(hDlg, IDC_RADIOPOPN, BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_RADIOPOP1, BST_CHECKED); + } + return TRUE; +} +BOOL DlgShowAccount(HWND hDlg, WPARAM wParam, LPARAM lParam) +{ + HPOP3ACCOUNT ActualAccount = (HPOP3ACCOUNT)lParam; + int i; + + if ((DWORD)wParam == M_SHOWACTUAL) { + wchar_t accstatus[256]; + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:SHOWACCOUNT:ActualAccountSO-read wait\n"); + #endif + 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 + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:SHOWACCOUNT:ActualAccountSO-read enter\n"); + #endif + DlgSetItemText(hDlg, IDC_EDITSERVER, ActualAccount->Server->Name); + DlgSetItemText(hDlg, IDC_EDITNAME, ActualAccount->Name); + DlgSetItemText(hDlg, IDC_EDITLOGIN, ActualAccount->Server->Login); + DlgSetItemText(hDlg, IDC_EDITPASS, ActualAccount->Server->Passwd); + DlgSetItemTextW(hDlg, IDC_EDITAPP, ActualAccount->NewMailN.App); + DlgSetItemTextW(hDlg, IDC_EDITAPPPARAM, ActualAccount->NewMailN.AppParam); + SetDlgItemInt(hDlg, IDC_EDITPORT, ActualAccount->Server->Port, FALSE); + SetDlgItemInt(hDlg, IDC_EDITINTERVAL, ActualAccount->Interval / 60, FALSE); + SetDlgItemInt(hDlg, IDC_EDITPOPS, ActualAccount->NewMailN.PopupTime, FALSE); + SetDlgItemInt(hDlg, IDC_EDITNPOPS, ActualAccount->NoNewMailN.PopupTime, FALSE); + SetDlgItemInt(hDlg, IDC_EDITFPOPS, ActualAccount->BadConnectN.PopupTime, FALSE); + for (i = 0; i <= CPLENSUPP; i++) + if ((i < CPLENSUPP) && (CodePageNamesSupp[i].CP == ActualAccount->CP)) { + SendDlgItemMessage(hDlg, IDC_COMBOCP, CB_SETCURSEL, (WPARAM)i, 0); + break; + } + if (i == CPLENSUPP) + SendDlgItemMessage(hDlg, IDC_COMBOCP, CB_SETCURSEL, (WPARAM)CPDEFINDEX, 0); + + CheckDlgButton(hDlg, IDC_CHECK, ActualAccount->Flags & YAMN_ACC_ENA ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKSND, ActualAccount->NewMailN.Flags & YAMN_ACC_SND ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKMSG, ActualAccount->NewMailN.Flags & YAMN_ACC_MSG ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKICO, ActualAccount->NewMailN.Flags & YAMN_ACC_ICO ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKPOP, ActualAccount->NewMailN.Flags & YAMN_ACC_POP ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKCOL, ActualAccount->NewMailN.Flags & YAMN_ACC_POPC ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKAPP, ActualAccount->NewMailN.Flags & YAMN_ACC_APP ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKKBN, ActualAccount->NewMailN.Flags & YAMN_ACC_KBN ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKNPOP, ActualAccount->NoNewMailN.Flags & YAMN_ACC_POP ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKNCOL, ActualAccount->NoNewMailN.Flags & YAMN_ACC_POPC ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKNMSGP, ActualAccount->NoNewMailN.Flags & YAMN_ACC_MSGP ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKFSND, ActualAccount->BadConnectN.Flags & YAMN_ACC_SND ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKFMSG, ActualAccount->BadConnectN.Flags & YAMN_ACC_MSG ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKFICO, ActualAccount->BadConnectN.Flags & YAMN_ACC_ICO ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKFPOP, ActualAccount->BadConnectN.Flags & YAMN_ACC_POP ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKFCOL, ActualAccount->BadConnectN.Flags & YAMN_ACC_POPC ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_RADIOPOPN, ActualAccount->Flags & YAMN_ACC_POPN ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_RADIOPOP1, ActualAccount->Flags & YAMN_ACC_POPN ? BST_UNCHECKED : BST_CHECKED); + CheckDlgButton(hDlg, IDC_CHECKSSL, ActualAccount->Flags & YAMN_ACC_SSL23 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKNOTLS, ActualAccount->Flags & YAMN_ACC_NOTLS ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKAPOP, ActualAccount->Flags & YAMN_ACC_APOP ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_AUTOBODY, ActualAccount->Flags & YAMN_ACC_BODY ? BST_CHECKED : BST_UNCHECKED); + /*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); + CheckDlgButton(hDlg,IDC_CHECKST8,ActualAccount->StatusFlags & YAMN_ACC_ST8 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST9,ActualAccount->StatusFlags & YAMN_ACC_ST9 ? BST_CHECKED : BST_UNCHECKED);*/ + Check0 = ActualAccount->StatusFlags & YAMN_ACC_ST0; + Check1 = ActualAccount->StatusFlags & YAMN_ACC_ST1; + Check2 = ActualAccount->StatusFlags & YAMN_ACC_ST2; + Check3 = ActualAccount->StatusFlags & YAMN_ACC_ST3; + Check4 = ActualAccount->StatusFlags & YAMN_ACC_ST4; + Check5 = ActualAccount->StatusFlags & YAMN_ACC_ST5; + Check6 = ActualAccount->StatusFlags & YAMN_ACC_ST6; + Check7 = ActualAccount->StatusFlags & YAMN_ACC_ST7; + Check8 = ActualAccount->StatusFlags & YAMN_ACC_ST8; + Check9 = ActualAccount->StatusFlags & YAMN_ACC_ST9; + CheckDlgButton(hDlg, IDC_CHECKSTART, ActualAccount->StatusFlags & YAMN_ACC_STARTS ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKFORCE, ActualAccount->StatusFlags & YAMN_ACC_FORCE ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKCONTACT, ActualAccount->NewMailN.Flags & YAMN_ACC_CONT ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKCONTACTNICK, ActualAccount->NewMailN.Flags & YAMN_ACC_CONTNICK ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKCONTACTNOEVENT, ActualAccount->NewMailN.Flags & YAMN_ACC_CONTNOEVENT ? BST_CHECKED : BST_UNCHECKED); + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:SHOWACCOUNT:ActualAccountSO-read done\n"); + #endif + GetAccountStatus(ActualAccount, accstatus); + SetDlgItemText(hDlg, IDC_STSTATUS, accstatus); + ReadDone(ActualAccount); + } + else //default + { + DlgSetItemText(hDlg, (WPARAM)IDC_EDITSERVER, nullptr); + DlgSetItemText(hDlg, (WPARAM)IDC_EDITNAME, nullptr); + DlgSetItemText(hDlg, (WPARAM)IDC_EDITLOGIN, nullptr); + DlgSetItemText(hDlg, (WPARAM)IDC_EDITPASS, nullptr); + DlgSetItemText(hDlg, (WPARAM)IDC_EDITAPP, nullptr); + DlgSetItemText(hDlg, (WPARAM)IDC_EDITAPPPARAM, nullptr); + DlgSetItemText(hDlg, (WPARAM)IDC_STTIMELEFT, nullptr); + SetDlgItemInt(hDlg, IDC_EDITPORT, 110, FALSE); + SetDlgItemInt(hDlg, IDC_EDITINTERVAL, 30, FALSE); + SetDlgItemInt(hDlg, IDC_EDITPOPS, 0, FALSE); + SetDlgItemInt(hDlg, IDC_EDITNPOPS, 0, FALSE); + SetDlgItemInt(hDlg, IDC_EDITFPOPS, 0, FALSE); + SendDlgItemMessage(hDlg, IDC_COMBOCP, CB_SETCURSEL, (WPARAM)CPDEFINDEX, 0); + CheckDlgButton(hDlg, IDC_CHECK, BST_CHECKED); + CheckDlgButton(hDlg, IDC_CHECKSND, BST_CHECKED); + CheckDlgButton(hDlg, IDC_CHECKMSG, BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKICO, BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKPOP, BST_CHECKED); + CheckDlgButton(hDlg, IDC_CHECKCOL, BST_CHECKED); + CheckDlgButton(hDlg, IDC_CHECKAPP, BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKPOP, BST_CHECKED); + CheckDlgButton(hDlg, IDC_CHECKCOL, BST_CHECKED); + CheckDlgButton(hDlg, IDC_CHECKFSND, BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKFMSG, BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKFICO, BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKFPOP, BST_CHECKED); + CheckDlgButton(hDlg, IDC_CHECKFCOL, BST_CHECKED); + /*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); + CheckDlgButton(hDlg,IDC_CHECKST8,BST_CHECKED); + CheckDlgButton(hDlg,IDC_CHECKST9,BST_CHECKED);*/ + CheckDlgButton(hDlg, IDC_CHECKSTART, BST_CHECKED); + CheckDlgButton(hDlg, IDC_CHECKFORCE, BST_CHECKED); + CheckDlgButton(hDlg, IDC_RADIOPOPN, BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_RADIOPOP1, BST_CHECKED); + CheckDlgButton(hDlg, IDC_CHECKSSL, BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKNOTLS, BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKAPOP, BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_AUTOBODY, BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_CHECKCONTACT, BST_CHECKED); + + SetDlgItemText(hDlg, IDC_STSTATUS, TranslateT("No account selected")); + } + return TRUE; +} + +BOOL DlgShowAccountColors(HWND hDlg, WPARAM, LPARAM lParam) +{ + HPOP3ACCOUNT ActualAccount = (HPOP3ACCOUNT)lParam; + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:SHOWACCOUNTCOLORS:ActualAccountSO-read wait\n"); + #endif + 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 + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:SHOWACCOUNTCOLORS:ActualAccountSO-read enter\n"); + #endif + if (ActualAccount->NewMailN.Flags & YAMN_ACC_POPC) { + SendDlgItemMessage(hDlg, IDC_CPB, CPM_SETCOLOUR, 0, (LPARAM)ActualAccount->NewMailN.PopupB); + SendDlgItemMessage(hDlg, IDC_CPT, CPM_SETCOLOUR, 0, (LPARAM)ActualAccount->NewMailN.PopupT); + } + else { + SendDlgItemMessage(hDlg, IDC_CPB, CPM_SETCOLOUR, 0, (LPARAM)GetSysColor(COLOR_BTNFACE)); + SendDlgItemMessage(hDlg, IDC_CPT, CPM_SETCOLOUR, 0, (LPARAM)GetSysColor(COLOR_WINDOWTEXT)); + } + if (ActualAccount->BadConnectN.Flags & YAMN_ACC_POPC) { + SendDlgItemMessage(hDlg, IDC_CPFB, CPM_SETCOLOUR, 0, (LPARAM)ActualAccount->BadConnectN.PopupB); + SendDlgItemMessage(hDlg, IDC_CPFT, CPM_SETCOLOUR, 0, (LPARAM)ActualAccount->BadConnectN.PopupT); + } + else { + SendDlgItemMessage(hDlg, IDC_CPFB, CPM_SETCOLOUR, 0, (LPARAM)GetSysColor(COLOR_BTNFACE)); + SendDlgItemMessage(hDlg, IDC_CPFT, CPM_SETCOLOUR, 0, (LPARAM)GetSysColor(COLOR_WINDOWTEXT)); + } + if (ActualAccount->NoNewMailN.Flags & YAMN_ACC_POPC) { + SendDlgItemMessage(hDlg, IDC_CPNB, CPM_SETCOLOUR, 0, (LPARAM)ActualAccount->NoNewMailN.PopupB); + SendDlgItemMessage(hDlg, IDC_CPNT, CPM_SETCOLOUR, 0, (LPARAM)ActualAccount->NoNewMailN.PopupT); + } + else { + SendDlgItemMessage(hDlg, IDC_CPNB, CPM_SETCOLOUR, 0, (LPARAM)GetSysColor(COLOR_BTNFACE)); + SendDlgItemMessage(hDlg, IDC_CPNT, CPM_SETCOLOUR, 0, (LPARAM)GetSysColor(COLOR_WINDOWTEXT)); + } + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:SHOWACCOUNTCOLORS:ActualAccountSO-read done\n"); + #endif + 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 + return TRUE; +} + +BOOL DlgSetItemText(HWND hDlg, WPARAM wParam, const char* str) +{ + if (str == nullptr) + SetDlgItemTextA(hDlg, wParam, ""); + else + SetDlgItemTextA(hDlg, wParam, str); + return TRUE; +} + +BOOL DlgSetItemTextW(HWND hDlg, WPARAM wParam, const WCHAR* str) +{ + if (str == nullptr) + SetDlgItemTextW(hDlg, wParam, L""); + else + SetDlgItemTextW(hDlg, wParam, str); + return TRUE; +} + +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, (WPARAM)M_SHOWACTUAL, (LPARAM)ActualAccount); + DlgEnableAccountStatus(hDlg, TRUE, TRUE); + } + else { + CheckDlgButton(hDlg, IDC_CHECKST0, BST_CHECKED); + CheckDlgButton(hDlg, IDC_CHECKST1, BST_CHECKED); + CheckDlgButton(hDlg, IDC_CHECKST2, BST_CHECKED); + CheckDlgButton(hDlg, IDC_CHECKST3, BST_CHECKED); + CheckDlgButton(hDlg, IDC_CHECKST4, BST_CHECKED); + CheckDlgButton(hDlg, IDC_CHECKST5, BST_CHECKED); + CheckDlgButton(hDlg, IDC_CHECKST6, BST_CHECKED); + CheckDlgButton(hDlg, IDC_CHECKST7, BST_CHECKED); + CheckDlgButton(hDlg, IDC_CHECKST8, BST_CHECKED); + CheckDlgButton(hDlg, IDC_CHECKST9, BST_CHECKED); + } + TranslateDialogDefault(hDlg); + SendMessage(GetParent(hDlg), PSM_UNCHANGED, (WPARAM)hDlg, 0); + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + Check0 = (IsDlgButtonChecked(hDlg, IDC_CHECKST0) == BST_CHECKED); + Check1 = (IsDlgButtonChecked(hDlg, IDC_CHECKST1) == BST_CHECKED); + Check2 = (IsDlgButtonChecked(hDlg, IDC_CHECKST2) == BST_CHECKED); + Check3 = (IsDlgButtonChecked(hDlg, IDC_CHECKST3) == BST_CHECKED); + Check4 = (IsDlgButtonChecked(hDlg, IDC_CHECKST4) == BST_CHECKED); + Check5 = (IsDlgButtonChecked(hDlg, IDC_CHECKST5) == BST_CHECKED); + Check6 = (IsDlgButtonChecked(hDlg, IDC_CHECKST6) == BST_CHECKED); + Check7 = (IsDlgButtonChecked(hDlg, IDC_CHECKST7) == BST_CHECKED); + Check8 = (IsDlgButtonChecked(hDlg, IDC_CHECKST8) == BST_CHECKED); + Check9 = (IsDlgButtonChecked(hDlg, IDC_CHECKST9) == BST_CHECKED); + WindowList_BroadcastAsync(YAMNVar.MessageWnds, WM_YAMN_CHANGESTATUSOPTION, 0, 0); + EndDialog(hDlg, 0); + DestroyWindow(hDlg); + break; + + case IDCANCEL: + EndDialog(hDlg, 0); + DestroyWindow(hDlg); + break; + } + } + return FALSE; +} + +INT_PTR CALLBACK DlgProcPOP3AccOpt(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + BOOL Changed = FALSE; + INT_PTR Result; + static BOOL InList = FALSE; + static HPOP3ACCOUNT ActualAccount; + static UCHAR ActualStatus; + // static struct CPOP3Options POP3Options; + + switch (msg) { + case WM_INITDIALOG: + { + int i; + + EnableWindow(GetDlgItem(hDlg, IDC_BTNDEL), FALSE); + + DlgEnableAccount(hDlg, FALSE, FALSE); + DlgShowAccount(hDlg, (WPARAM)M_SHOWDEFAULT, 0); + + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:INITDIALOG:AccountBrowserSO-read wait\n"); + #endif + WaitToReadSO(POP3Plugin->AccountBrowserSO); + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:INITDIALOG:AccountBrowserSO-read enter\n"); + #endif + + for (ActualAccount = (HPOP3ACCOUNT)POP3Plugin->FirstAccount; ActualAccount != nullptr; ActualAccount = (HPOP3ACCOUNT)ActualAccount->Next) + if (ActualAccount->Name != nullptr) + SendDlgItemMessageA(hDlg, IDC_COMBOACCOUNT, CB_ADDSTRING, 0, (LPARAM)ActualAccount->Name); + + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:INITDIALOG:AccountBrowserSO-read done\n"); + #endif + ReadDoneSO(POP3Plugin->AccountBrowserSO); + SendDlgItemMessage(hDlg, IDC_COMBOCP, CB_ADDSTRING, 0, (LPARAM)TranslateT("Default")); + for (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; + SendDlgItemMessage(hDlg, IDC_COMBOCP, CB_ADDSTRING, 0, (LPARAM)(info.CodePageName + 7)); + } + + SendDlgItemMessage(hDlg, IDC_COMBOCP, CB_SETCURSEL, (WPARAM)CPDEFINDEX, 0); + ActualAccount = nullptr; + TranslateDialogDefault(hDlg); + SendMessage(GetParent(hDlg), PSM_UNCHANGED, (WPARAM)hDlg, 0); + return TRUE; + } + + case WM_SHOWWINDOW: + if (wParam == FALSE) { + WindowList_Remove(pYAMNVar->MessageWnds, hDlg); + SendMessage(GetParent(hDlg), PSM_UNCHANGED, (WPARAM)hDlg, 0); + } + else WindowList_Add(pYAMNVar->MessageWnds, hDlg); + return TRUE; + + case WM_YAMN_CHANGESTATUS: + if ((HPOP3ACCOUNT)wParam == ActualAccount) { + wchar_t accstatus[256]; + GetAccountStatus(ActualAccount, accstatus); + SetDlgItemText(hDlg, IDC_STSTATUS, accstatus); + return TRUE; + } + break; + + case WM_YAMN_CHANGESTATUSOPTION: + Changed = TRUE; + SendMessage(GetParent(hDlg), PSM_CHANGED, 0, 0); + 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"), (DWORD)lParam); + SetDlgItemText(hDlg, IDC_STTIMELEFT, Text); + } + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_COMBOACCOUNT: + switch (HIWORD(wParam)) { + case CBN_EDITCHANGE: + ActualAccount = nullptr; + DlgSetItemText(hDlg, (WPARAM)IDC_STTIMELEFT, nullptr); + + if (GetDlgItemTextA(hDlg, IDC_COMBOACCOUNT, DlgInput, _countof(DlgInput))) + DlgEnableAccount(hDlg, TRUE, FALSE); + else + DlgEnableAccount(hDlg, FALSE, FALSE); + break; + + case CBN_KILLFOCUS: + GetDlgItemTextA(hDlg, IDC_COMBOACCOUNT, DlgInput, _countof(DlgInput)); + if (nullptr == (ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)DlgInput))) { + DlgSetItemText(hDlg, (WPARAM)IDC_STTIMELEFT, nullptr); + EnableWindow(GetDlgItem(hDlg, IDC_BTNDEL), FALSE); + if (mir_strlen(DlgInput)) + DlgEnableAccount(hDlg, TRUE, TRUE); + else + DlgEnableAccount(hDlg, FALSE, FALSE); + } + else { + DlgShowAccount(hDlg, (WPARAM)M_SHOWACTUAL, (LPARAM)ActualAccount); + DlgEnableAccount(hDlg, TRUE, TRUE); + EnableWindow(GetDlgItem(hDlg, IDC_BTNDEL), TRUE); + } + break; + + case CBN_SELCHANGE: + if (CB_ERR != (Result = SendDlgItemMessage(hDlg, IDC_COMBOACCOUNT, CB_GETCURSEL, 0, 0))) + SendDlgItemMessageA(hDlg, IDC_COMBOACCOUNT, CB_GETLBTEXT, (WPARAM)Result, (LPARAM)DlgInput); + + if ((Result == CB_ERR) || (nullptr == (ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)DlgInput)))) { + DlgSetItemText(hDlg, (WPARAM)IDC_STTIMELEFT, nullptr); + EnableWindow(GetDlgItem(hDlg, IDC_BTNDEL), FALSE); + } + else { + DlgShowAccount(hDlg, (WPARAM)M_SHOWACTUAL, (LPARAM)ActualAccount); + DlgEnableAccount(hDlg, TRUE, FALSE); + EnableWindow(GetDlgItem(hDlg, IDC_BTNDEL), TRUE); + } + break; + } + break; + + case IDC_COMBOCP: + { + int sel = SendDlgItemMessage(hDlg, IDC_COMBOCP, CB_GETCURSEL, 0, 0); + CPINFOEX info; GetCPInfoEx(CodePageNamesSupp[sel].CP, 0, &info); + DlgSetItemTextT(hDlg, IDC_STSTATUS, info.CodePageName); + } + case IDC_CHECK: + case IDC_CHECKSND: + case IDC_CHECKMSG: + case IDC_CHECKICO: + case IDC_CHECKFSND: + case IDC_CHECKFMSG: + case IDC_CHECKFICO: + case IDC_CHECKST0: + case IDC_CHECKST1: + case IDC_CHECKST2: + case IDC_CHECKST3: + case IDC_CHECKST4: + case IDC_CHECKST5: + case IDC_CHECKST6: + case IDC_CHECKST7: + case IDC_CHECKST8: + case IDC_CHECKST9: + case IDC_CHECKSTART: + case IDC_CHECKFORCE: + case IDC_EDITAPPPARAM: + case IDC_CHECKAPOP: + case IDC_AUTOBODY: + case IDC_CHECKCONTACTNICK: + case IDC_CHECKCONTACTNOEVENT: + case IDC_CHECKNOTLS: + Changed = TRUE; + break; + + case IDC_CHECKCONTACT: + Changed = IsDlgButtonChecked(hDlg, IDC_CHECKCONTACT) == BST_CHECKED; + EnableWindow(GetDlgItem(hDlg, IDC_CHECKCONTACTNICK), Changed); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKCONTACTNOEVENT), Changed); + Changed = TRUE; + break; + + case IDC_CHECKSSL: + { + BOOL SSLC = (IsDlgButtonChecked(hDlg, IDC_CHECKSSL) == BST_CHECKED); + SetDlgItemInt(hDlg, IDC_EDITPORT, SSLC ? 995 : 110, FALSE); + EnableWindow(GetDlgItem(hDlg, IDC_CHECKNOTLS), SSLC ? 0 : 1); + } + Changed = TRUE; + break; + + case IDC_CPB: + case IDC_CPT: + case IDC_CPFB: + case IDC_CPFT: + case IDC_CPNB: + case IDC_CPNT: + if (HIWORD(wParam) != CPN_COLOURCHANGED) + break; + + case IDC_CHECKKBN: + Changed = TRUE; + break; + + case IDC_CHECKAPP: + Changed = TRUE; + EnableWindow(GetDlgItem(hDlg, IDC_BTNAPP), IsDlgButtonChecked(hDlg, IDC_CHECKAPP) == BST_CHECKED); + EnableWindow(GetDlgItem(hDlg, IDC_EDITAPP), IsDlgButtonChecked(hDlg, IDC_CHECKAPP) == BST_CHECKED); + EnableWindow(GetDlgItem(hDlg, IDC_EDITAPPPARAM), IsDlgButtonChecked(hDlg, IDC_CHECKAPP) == BST_CHECKED); + break; + + case IDC_BTNSTATUS: + DialogBoxParamW(g_plugin.getInst(), MAKEINTRESOURCEW(IDD_CHOOSESTATUSMODES), hDlg, DlgProcPOP3AccStatusOpt, NULL); + break; + + case IDC_BTNADD: + DlgSetItemText(hDlg, (WPARAM)IDC_STTIMELEFT, nullptr); + DlgShowAccount(hDlg, (WPARAM)M_SHOWDEFAULT, 0); + DlgEnableAccount(hDlg, TRUE, TRUE); + EnableWindow(GetDlgItem(hDlg, IDC_BTNDEL), FALSE); + DlgSetItemTextT(hDlg, IDC_EDITNAME, TranslateT("New Account")); + { + int index = SendDlgItemMessage(hDlg, IDC_COMBOACCOUNT, CB_ADDSTRING, 0, (LPARAM)TranslateT("New Account")); + if (index != CB_ERR && index != CB_ERRSPACE) + SendDlgItemMessage(hDlg, IDC_COMBOACCOUNT, CB_SETCURSEL, index, (LPARAM)TranslateT("New Account")); + } + break; + + case IDC_BTNAPP: + { + 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 = hDlg; + 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(hDlg, TranslateT("Dialog box error"), TranslateT("Failed"), MB_OK); + } + else DlgSetItemTextT(hDlg, IDC_EDITAPP, OFNStruct.lpstrFile); + delete[] OFNStruct.lpstrFile; + } + break; + + case IDC_BTNDEFAULT: + DlgShowAccount(hDlg, (WPARAM)M_SHOWDEFAULT, 0); + break; + + case IDC_BTNDEL: + GetDlgItemTextA(hDlg, IDC_COMBOACCOUNT, DlgInput, _countof(DlgInput)); + EnableWindow(GetDlgItem(hDlg, IDC_BTNDEL), FALSE); + if ((CB_ERR == (Result = SendDlgItemMessage(hDlg, IDC_COMBOACCOUNT, CB_GETCURSEL, 0, 0))) + || (nullptr == (ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)DlgInput)))) + return TRUE; + + if (IDOK != MessageBox(hDlg, TranslateT("Do you really want to delete this account?"), TranslateT("Delete account confirmation"), MB_OKCANCEL | MB_ICONWARNING)) + return TRUE; + + DlgSetItemTextT(hDlg, 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(hDlg, IDC_COMBOACCOUNT, CB_DELETESTRING, (WPARAM)Result, 0); + DlgSetItemText(hDlg, (WPARAM)IDC_COMBOACCOUNT, nullptr); + DlgEnableAccount(hDlg, FALSE, 0); + DlgShowAccount(hDlg, (WPARAM)M_SHOWDEFAULT, 0); + break; + + case IDC_BTNRESET: + if (ActualAccount != nullptr) + ActualAccount->TimeLeft = ActualAccount->Interval; + return 1; + } + + if (HIWORD(wParam) == EN_CHANGE) + Changed = TRUE; + break; + + case WM_NOTIFY: + if (((LPNMHDR)lParam)->idFrom == 0 && ((LPNMHDR)lParam)->code == PSN_APPLY) { + char Text[MAX_PATH]; + WCHAR TextW[MAX_PATH]; + BOOL Translated, NewAcc = FALSE, Check, CheckMsg, CheckSnd, CheckIco, CheckApp, CheckAPOP; + BOOL CheckNMsgP, CheckFMsg, CheckFSnd, CheckFIco; + BOOL CheckKBN, CheckContact, CheckContactNick, CheckContactNoEvent; + BOOL CheckSSL, CheckABody, CheckNoTLS; + //BOOL Check0,Check1,Check2,Check3,Check4,Check5,Check6,Check7,Check8,Check9, + BOOL CheckStart, CheckForce; + size_t Length, index; + UINT Port, Interval; + + if (GetDlgItemTextA(hDlg, IDC_COMBOACCOUNT, Text, _countof(Text))) { + Check = (IsDlgButtonChecked(hDlg, IDC_CHECK) == BST_CHECKED); + CheckSSL = (IsDlgButtonChecked(hDlg, IDC_CHECKSSL) == BST_CHECKED); + CheckNoTLS = (IsDlgButtonChecked(hDlg, IDC_CHECKNOTLS) == BST_CHECKED); + CheckAPOP = (IsDlgButtonChecked(hDlg, IDC_CHECKAPOP) == BST_CHECKED); + + CheckABody = (IsDlgButtonChecked(hDlg, IDC_AUTOBODY) == BST_CHECKED); + CheckMsg = (IsDlgButtonChecked(hDlg, IDC_CHECKMSG) == BST_CHECKED); + CheckSnd = (IsDlgButtonChecked(hDlg, IDC_CHECKSND) == BST_CHECKED); + CheckIco = (IsDlgButtonChecked(hDlg, IDC_CHECKICO) == BST_CHECKED); + + CheckApp = (IsDlgButtonChecked(hDlg, IDC_CHECKAPP) == BST_CHECKED); + CheckKBN = (IsDlgButtonChecked(hDlg, IDC_CHECKKBN) == BST_CHECKED); + CheckContact = (IsDlgButtonChecked(hDlg, IDC_CHECKCONTACT) == BST_CHECKED); + CheckContactNick = (IsDlgButtonChecked(hDlg, IDC_CHECKCONTACTNICK) == BST_CHECKED); + CheckContactNoEvent = (IsDlgButtonChecked(hDlg, IDC_CHECKCONTACTNOEVENT) == BST_CHECKED); + + CheckFSnd = (IsDlgButtonChecked(hDlg, IDC_CHECKFSND) == BST_CHECKED); + CheckFMsg = (IsDlgButtonChecked(hDlg, IDC_CHECKFMSG) == BST_CHECKED); + CheckFIco = (IsDlgButtonChecked(hDlg, IDC_CHECKFICO) == BST_CHECKED); + + CheckNMsgP = (IsDlgButtonChecked(hDlg, IDC_CHECKNMSGP) == BST_CHECKED); + + Port = GetDlgItemInt(hDlg, IDC_EDITPORT, &Translated, FALSE); + if (!Translated) { + MessageBox(hDlg, TranslateT("This is not a valid number value"), TranslateT("Input error"), MB_OK); + SetFocus(GetDlgItem(hDlg, IDC_EDITPORT)); + break; + } + Interval = GetDlgItemInt(hDlg, IDC_EDITINTERVAL, &Translated, FALSE); + if (!Translated) { + MessageBox(hDlg, TranslateT("This is not a valid number value"), TranslateT("Input error"), MB_OK); + SetFocus(GetDlgItem(hDlg, IDC_EDITINTERVAL)); + break; + } + + GetDlgItemTextA(hDlg, IDC_EDITAPP, Text, _countof(Text)); + if (CheckApp && !(Length = mir_strlen(Text))) { + MessageBox(hDlg, TranslateT("Please select application to run"), TranslateT("Input error"), MB_OK); + break; + } + + GetDlgItemTextA(hDlg, IDC_COMBOACCOUNT, Text, _countof(Text)); + if (!(Length = mir_strlen(Text))) { + GetDlgItemTextA(hDlg, IDC_EDITNAME, Text, _countof(Text)); + if (!(Length = mir_strlen(Text))) + break; + } + + DlgSetItemTextT(hDlg, 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; + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:APPLY:AccountBrowserSO-write wait\n"); + #endif + WaitToWriteSO(POP3Plugin->AccountBrowserSO); + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:APPLY:AccountBrowserSO-write enter\n"); + #endif + if (nullptr == (ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_GETNEXTFREEACCOUNT, (WPARAM)POP3Plugin, (LPARAM)YAMN_ACCOUNTVERSION))) { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:APPLY:AccountBrowserSO-write done\n"); + #endif + WriteDoneSO(POP3Plugin->AccountBrowserSO); + MessageBox(hDlg, TranslateT("Cannot allocate memory space for new account"), TranslateT("Memory error"), MB_OK); + break; + } + } + else { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:APPLY:AccountBrowserSO-write wait\n"); + #endif + //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); + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:APPLY:AccountBrowserSO-write enter\n"); + #endif + } + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:APPLY:ActualAccountSO-write wait\n"); + #endif + if (WAIT_OBJECT_0 != WaitToWrite(ActualAccount)) { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:APPLY:ActualAccountSO-write wait failed\n"); + #endif + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:APPLY:ActualBrowserSO-write done\n"); + #endif + WriteDoneSO(POP3Plugin->AccountBrowserSO); + + } + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:APPLY:ActualAccountSO-write enter\n"); + #endif + + GetDlgItemTextA(hDlg, IDC_EDITNAME, Text, _countof(Text)); + if (!(Length = mir_strlen(Text))) + break; + if (nullptr != ActualAccount->Name) + delete[] ActualAccount->Name; + ActualAccount->Name = new char[mir_strlen(Text) + 1]; + mir_strcpy(ActualAccount->Name, Text); + + GetDlgItemTextA(hDlg, 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(hDlg, 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(hDlg, 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(hDlg, IDC_EDITAPP, TextW, _countof(TextW)); + if (nullptr != ActualAccount->NewMailN.App) + delete[] ActualAccount->NewMailN.App; + ActualAccount->NewMailN.App = new WCHAR[mir_wstrlen(TextW) + 1]; + mir_wstrcpy(ActualAccount->NewMailN.App, TextW); + + GetDlgItemTextW(hDlg, IDC_EDITAPPPARAM, TextW, _countof(TextW)); + if (nullptr != ActualAccount->NewMailN.AppParam) + delete[] ActualAccount->NewMailN.AppParam; + ActualAccount->NewMailN.AppParam = new WCHAR[mir_wstrlen(TextW) + 1]; + mir_wstrcpy(ActualAccount->NewMailN.AppParam, TextW); + + ActualAccount->Server->Port = Port; + ActualAccount->Interval = Interval * 60; + + if (CB_ERR == (index = SendDlgItemMessage(hDlg, IDC_COMBOCP, CB_GETCURSEL, 0, 0))) + index = CPDEFINDEX; + ActualAccount->CP = CodePageNamesSupp[index].CP; + + if (NewAcc) + ActualAccount->TimeLeft = Interval * 60; + + CheckStart = (IsDlgButtonChecked(hDlg, IDC_CHECKSTART) == BST_CHECKED); + CheckForce = (IsDlgButtonChecked(hDlg, 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 = + (Check0 ? YAMN_ACC_ST0 : 0) | + (Check1 ? YAMN_ACC_ST1 : 0) | + (Check2 ? YAMN_ACC_ST2 : 0) | + (Check3 ? YAMN_ACC_ST3 : 0) | + (Check4 ? YAMN_ACC_ST4 : 0) | + (Check5 ? YAMN_ACC_ST5 : 0) | + (Check6 ? YAMN_ACC_ST6 : 0) | + (Check7 ? YAMN_ACC_ST7 : 0) | + (Check8 ? YAMN_ACC_ST8 : 0) | + (Check9 ? YAMN_ACC_ST9 : 0) | + (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); + + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:APPLY:ActualAccountSO-write done\n"); + #endif + WriteDone(ActualAccount); + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:APPLY:AccountBrowserSO-write done\n"); + #endif + WriteDoneSO(POP3Plugin->AccountBrowserSO); + + EnableWindow(GetDlgItem(hDlg, IDC_BTNDEL), TRUE); + + DlgSetItemText(hDlg, (WPARAM)IDC_STTIMELEFT, nullptr); + + index = SendDlgItemMessage(hDlg, IDC_COMBOACCOUNT, CB_GETCURSEL, 0, 0); + + HPOP3ACCOUNT temp = ActualAccount; + + SendDlgItemMessage(hDlg, 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(hDlg, IDC_COMBOACCOUNT, CB_ADDSTRING, 0, (LPARAM)ActualAccount->Name); + + ActualAccount = temp; + SendDlgItemMessage(hDlg, IDC_COMBOACCOUNT, CB_SETCURSEL, (WPARAM)index, (LPARAM)ActualAccount->Name); + + WritePOP3Accounts(); + RefreshContact(); + return TRUE; + } + } + break; + } + if (Changed) + SendMessage(GetParent(hDlg), PSM_CHANGED, 0, 0); + return FALSE; +} + +INT_PTR CALLBACK DlgProcPOP3AccPopup(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + BOOL Changed = FALSE; + static BOOL InList = FALSE; + static HPOP3ACCOUNT ActualAccount; + static UCHAR ActualStatus; + // static struct CPOP3Options POP3Options; + + switch (msg) { + case WM_INITDIALOG: + { + DlgEnableAccountPopup(hDlg, FALSE, FALSE); + DlgShowAccountPopup(hDlg, (WPARAM)M_SHOWDEFAULT, 0); + //DlgShowAccountColors(hDlg,0,(LPARAM)ActualAccount); + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:INITDIALOG:AccountBrowserSO-read wait\n"); + #endif + WaitToReadSO(POP3Plugin->AccountBrowserSO); + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:INITDIALOG:AccountBrowserSO-read enter\n"); + #endif + if (POP3Plugin->FirstAccount != nullptr) + for (ActualAccount = (HPOP3ACCOUNT)POP3Plugin->FirstAccount; ActualAccount != nullptr; ActualAccount = (HPOP3ACCOUNT)ActualAccount->Next) + if (ActualAccount->Name != nullptr) + SendDlgItemMessageA(hDlg, IDC_COMBOACCOUNT, CB_ADDSTRING, 0, (LPARAM)ActualAccount->Name); + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:INITDIALOG:AccountBrowserSO-read done\n"); + #endif + ReadDoneSO(POP3Plugin->AccountBrowserSO); + ActualAccount = nullptr; + + + TranslateDialogDefault(hDlg); + SendMessage(GetParent(hDlg), PSM_UNCHANGED, (WPARAM)hDlg, 0); + return TRUE; + } + + case WM_SHOWWINDOW: + if ((BOOL)wParam == FALSE) { + WindowList_Remove(pYAMNVar->MessageWnds, hDlg); + SendMessage(GetParent(hDlg), PSM_UNCHANGED, (WPARAM)hDlg, 0); + } + else { + WindowList_Add(pYAMNVar->MessageWnds, hDlg); + + int index = SendDlgItemMessage(hDlg, IDC_COMBOACCOUNT, CB_GETCURSEL, 0, 0); + HPOP3ACCOUNT temp = ActualAccount; + SendDlgItemMessage(hDlg, 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(hDlg, IDC_COMBOACCOUNT, CB_ADDSTRING, 0, (LPARAM)ActualAccount->Name); + + ActualAccount = temp; + + if (ActualAccount != nullptr) { + SendDlgItemMessage(hDlg, IDC_COMBOACCOUNT, CB_SETCURSEL, (WPARAM)index, (LPARAM)ActualAccount->Name); + DlgShowAccount(hDlg, (WPARAM)M_SHOWACTUAL, (LPARAM)ActualAccount); + DlgShowAccountColors(hDlg, 0, (LPARAM)ActualAccount); + DlgEnableAccountPopup(hDlg, TRUE, FALSE); + } + else { + DlgShowAccountPopup(hDlg, (WPARAM)M_SHOWDEFAULT, 0); + DlgEnableAccountPopup(hDlg, FALSE, FALSE); + } + + } + return TRUE; + + case WM_COMMAND: + { + WORD wNotifyCode = HIWORD(wParam); + switch (LOWORD(wParam)) { + LONG Result; + case IDC_COMBOACCOUNT: + switch (wNotifyCode) { + + case CBN_KILLFOCUS: + GetDlgItemTextA(hDlg, IDC_COMBOACCOUNT, DlgInput, _countof(DlgInput)); + if (nullptr == (ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)DlgInput))) { + DlgSetItemText(hDlg, (WPARAM)IDC_STTIMELEFT, nullptr); + if (mir_strlen(DlgInput)) + DlgEnableAccountPopup(hDlg, TRUE, TRUE); + else + DlgEnableAccountPopup(hDlg, FALSE, FALSE); + } + else { + DlgShowAccount(hDlg, (WPARAM)M_SHOWACTUAL, (LPARAM)ActualAccount); + DlgShowAccountColors(hDlg, 0, (LPARAM)ActualAccount); + DlgEnableAccountPopup(hDlg, TRUE, TRUE); + } + break; + case CBN_SELCHANGE: + if (CB_ERR != (Result = SendDlgItemMessage(hDlg, IDC_COMBOACCOUNT, CB_GETCURSEL, 0, 0))) + SendDlgItemMessageA(hDlg, IDC_COMBOACCOUNT, CB_GETLBTEXT, (WPARAM)Result, (LPARAM)DlgInput); + if ((Result == CB_ERR) || (nullptr == (ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)DlgInput)))) { + DlgSetItemText(hDlg, (WPARAM)IDC_STTIMELEFT, nullptr); + } + else { + DlgShowAccount(hDlg, (WPARAM)M_SHOWACTUAL, (LPARAM)ActualAccount); + DlgShowAccountColors(hDlg, 0, (LPARAM)ActualAccount); + DlgEnableAccountPopup(hDlg, TRUE, FALSE); + } + break; + } + break; + case IDC_COMBOCP: + { + int sel = SendDlgItemMessage(hDlg, IDC_COMBOCP, CB_GETCURSEL, 0, 0); + CPINFOEX info; GetCPInfoEx(CodePageNamesSupp[sel].CP, 0, &info); + DlgSetItemTextT(hDlg, IDC_STSTATUS, info.CodePageName); + } + case IDC_RADIOPOPN: + case IDC_RADIOPOP1: + Changed = TRUE; + break; + case IDC_CPB: + case IDC_CPT: + case IDC_CPFB: + case IDC_CPFT: + case IDC_CPNB: + case IDC_CPNT: + if (HIWORD(wParam) != CPN_COLOURCHANGED) + break; + case IDC_CHECKCOL: + case IDC_CHECKFCOL: + case IDC_CHECKNCOL: + EnableWindow(GetDlgItem(hDlg, IDC_CPB), (IsDlgButtonChecked(hDlg, IDC_CHECKCOL) == BST_CHECKED) && (IsDlgButtonChecked(hDlg, IDC_CHECKPOP) == BST_CHECKED) && wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CPT), (IsDlgButtonChecked(hDlg, IDC_CHECKCOL) == BST_CHECKED) && (IsDlgButtonChecked(hDlg, IDC_CHECKPOP) == BST_CHECKED) && wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CPNB), (IsDlgButtonChecked(hDlg, IDC_CHECKNCOL) == BST_CHECKED) && (IsDlgButtonChecked(hDlg, IDC_CHECKNPOP) == BST_CHECKED) && wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CPNT), (IsDlgButtonChecked(hDlg, IDC_CHECKNCOL) == BST_CHECKED) && (IsDlgButtonChecked(hDlg, IDC_CHECKNPOP) == BST_CHECKED) && wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CPFB), (IsDlgButtonChecked(hDlg, IDC_CHECKFCOL) == BST_CHECKED) && (IsDlgButtonChecked(hDlg, IDC_CHECKFPOP) == BST_CHECKED) && wParam); + EnableWindow(GetDlgItem(hDlg, IDC_CPFT), (IsDlgButtonChecked(hDlg, IDC_CHECKFCOL) == BST_CHECKED) && (IsDlgButtonChecked(hDlg, IDC_CHECKFPOP) == BST_CHECKED) && wParam); + Changed = TRUE; + break; + + case IDC_PREVIEW: + { + POPUPDATAW Tester; + POPUPDATAW TesterF; + POPUPDATAW TesterN; + BOOL TesterC = (IsDlgButtonChecked(hDlg, IDC_CHECKCOL) == BST_CHECKED); + BOOL TesterFC = (IsDlgButtonChecked(hDlg, IDC_CHECKFCOL) == BST_CHECKED); + BOOL TesterNC = (IsDlgButtonChecked(hDlg, IDC_CHECKNCOL) == BST_CHECKED); + + memset(&Tester, 0, sizeof(Tester)); + memset(&TesterF, 0, sizeof(TesterF)); + memset(&TesterN, 0, sizeof(TesterN)); + Tester.lchIcon = g_LoadIconEx(2); + TesterF.lchIcon = g_LoadIconEx(3); + TesterN.lchIcon = g_LoadIconEx(1); + + mir_wstrncpy(Tester.lpwzContactName, TranslateT("Account Test"), MAX_CONTACTNAME); + mir_wstrncpy(TesterF.lpwzContactName, TranslateT("Account Test (failed)"), MAX_CONTACTNAME); + mir_wstrncpy(TesterN.lpwzContactName, TranslateT("Account Test"), MAX_CONTACTNAME); + mir_wstrncpy(Tester.lpwzText, TranslateT("You have N new mail messages"), MAX_SECONDLINE); + mir_wstrncpy(TesterF.lpwzText, TranslateT("Connection failed message"), MAX_SECONDLINE); + mir_wstrncpy(TesterN.lpwzText, TranslateT("No new mail message"), MAX_SECONDLINE); + if (TesterC) { + Tester.colorBack = SendDlgItemMessage(hDlg, IDC_CPB, CPM_GETCOLOUR, 0, 0); + Tester.colorText = SendDlgItemMessage(hDlg, IDC_CPT, CPM_GETCOLOUR, 0, 0); + } + else { + Tester.colorBack = GetSysColor(COLOR_BTNFACE); + Tester.colorText = GetSysColor(COLOR_WINDOWTEXT); + } + if (TesterFC) { + TesterF.colorBack = SendDlgItemMessage(hDlg, IDC_CPFB, CPM_GETCOLOUR, 0, 0); + TesterF.colorText = SendDlgItemMessage(hDlg, IDC_CPFT, CPM_GETCOLOUR, 0, 0); + } + else { + TesterF.colorBack = GetSysColor(COLOR_BTNFACE); + TesterF.colorText = GetSysColor(COLOR_WINDOWTEXT); + } + if (TesterNC) { + TesterN.colorBack = SendDlgItemMessage(hDlg, IDC_CPNB, CPM_GETCOLOUR, 0, 0); + TesterN.colorText = SendDlgItemMessage(hDlg, IDC_CPNT, CPM_GETCOLOUR, 0, 0); + } + else { + TesterN.colorBack = GetSysColor(COLOR_BTNFACE); + TesterN.colorText = GetSysColor(COLOR_WINDOWTEXT); + } + Tester.PluginWindowProc = nullptr; + TesterF.PluginWindowProc = nullptr; + TesterN.PluginWindowProc = nullptr; + Tester.PluginData = nullptr; + TesterF.PluginData = nullptr; + TesterN.PluginData = nullptr; + + if (IsDlgButtonChecked(hDlg, IDC_CHECKPOP) == BST_CHECKED) + PUAddPopupW(&Tester); + if (IsDlgButtonChecked(hDlg, IDC_CHECKFPOP) == BST_CHECKED) + PUAddPopupW(&TesterF); + if (IsDlgButtonChecked(hDlg, IDC_CHECKNPOP) == BST_CHECKED) + PUAddPopupW(&TesterN); + Changed = TRUE; + } + break; + case IDC_CHECKKBN: + Changed = TRUE; + break; + case IDC_CHECKPOP: + Changed = TRUE; + EnableWindow(GetDlgItem(hDlg, IDC_CHECKCOL), IsDlgButtonChecked(hDlg, IDC_CHECKPOP) == BST_CHECKED); + EnableWindow(GetDlgItem(hDlg, IDC_CPB), (IsDlgButtonChecked(hDlg, IDC_CHECKCOL) == BST_CHECKED) && IsDlgButtonChecked(hDlg, IDC_CHECKPOP) == BST_CHECKED); + EnableWindow(GetDlgItem(hDlg, IDC_CPT), (IsDlgButtonChecked(hDlg, IDC_CHECKCOL) == BST_CHECKED) && IsDlgButtonChecked(hDlg, IDC_CHECKPOP) == BST_CHECKED); + EnableWindow(GetDlgItem(hDlg, IDC_RADIOPOPN), (IsDlgButtonChecked(hDlg, IDC_CHECKPOP) == BST_CHECKED)); + EnableWindow(GetDlgItem(hDlg, IDC_RADIOPOP1), (IsDlgButtonChecked(hDlg, IDC_CHECKPOP) == BST_CHECKED)); + EnableWindow(GetDlgItem(hDlg, IDC_EDITPOPS), (IsDlgButtonChecked(hDlg, IDC_CHECKPOP) == BST_CHECKED)); + break; + case IDC_CHECKFPOP: + Changed = TRUE; + EnableWindow(GetDlgItem(hDlg, IDC_CHECKFCOL), IsDlgButtonChecked(hDlg, IDC_CHECKFPOP) == BST_CHECKED); + EnableWindow(GetDlgItem(hDlg, IDC_CPFB), (IsDlgButtonChecked(hDlg, IDC_CHECKFCOL) == BST_CHECKED) && IsDlgButtonChecked(hDlg, IDC_CHECKFPOP) == BST_CHECKED); + EnableWindow(GetDlgItem(hDlg, IDC_CPFT), (IsDlgButtonChecked(hDlg, IDC_CHECKFCOL) == BST_CHECKED) && IsDlgButtonChecked(hDlg, IDC_CHECKFPOP) == BST_CHECKED); + EnableWindow(GetDlgItem(hDlg, IDC_EDITFPOPS), (IsDlgButtonChecked(hDlg, IDC_CHECKFPOP) == BST_CHECKED)); + break; + case IDC_CHECKNPOP: + Changed = TRUE; + EnableWindow(GetDlgItem(hDlg, IDC_CHECKNCOL), IsDlgButtonChecked(hDlg, IDC_CHECKNPOP) == BST_CHECKED); + EnableWindow(GetDlgItem(hDlg, IDC_CPNB), (IsDlgButtonChecked(hDlg, IDC_CHECKNCOL) == BST_CHECKED) && IsDlgButtonChecked(hDlg, IDC_CHECKNPOP) == BST_CHECKED); + EnableWindow(GetDlgItem(hDlg, IDC_CPNT), (IsDlgButtonChecked(hDlg, IDC_CHECKNCOL) == BST_CHECKED) && IsDlgButtonChecked(hDlg, IDC_CHECKNPOP) == BST_CHECKED); + EnableWindow(GetDlgItem(hDlg, IDC_EDITNPOPS), (IsDlgButtonChecked(hDlg, IDC_CHECKNPOP) == BST_CHECKED)); + break; + + } + if (HIWORD(wParam) == EN_CHANGE) + Changed = TRUE; + break; + } + case WM_NOTIFY: + switch (((LPNMHDR)lParam)->idFrom) { + case 0: + switch (((LPNMHDR)lParam)->code) { + case PSN_APPLY: + { + wchar_t Text[MAX_PATH]; + BOOL Translated, CheckPopup, CheckPopupW; + BOOL CheckNPopup, CheckNPopupW, CheckFPopup, CheckFPopupW; + BOOL CheckPopN; + UINT Time, TimeN, TimeF; + + if (GetDlgItemText(hDlg, IDC_COMBOACCOUNT, Text, _countof(Text))) { + CheckPopup = (IsDlgButtonChecked(hDlg, IDC_CHECKPOP) == BST_CHECKED); + CheckPopupW = (IsDlgButtonChecked(hDlg, IDC_CHECKCOL) == BST_CHECKED); + + CheckFPopup = (IsDlgButtonChecked(hDlg, IDC_CHECKFPOP) == BST_CHECKED); + CheckFPopupW = (IsDlgButtonChecked(hDlg, IDC_CHECKFCOL) == BST_CHECKED); + + CheckNPopup = (IsDlgButtonChecked(hDlg, IDC_CHECKNPOP) == BST_CHECKED); + CheckNPopupW = (IsDlgButtonChecked(hDlg, IDC_CHECKNCOL) == BST_CHECKED); + + CheckPopN = (IsDlgButtonChecked(hDlg, IDC_RADIOPOPN) == BST_CHECKED); + + + Time = GetDlgItemInt(hDlg, IDC_EDITPOPS, &Translated, FALSE); + if (!Translated) { + MessageBox(hDlg, TranslateT("This is not a valid number value"), TranslateT("Input error"), MB_OK); + SetFocus(GetDlgItem(hDlg, IDC_EDITPOPS)); + break; + } + TimeN = GetDlgItemInt(hDlg, IDC_EDITNPOPS, &Translated, FALSE); + if (!Translated) { + MessageBox(hDlg, TranslateT("This is not a valid number value"), TranslateT("Input error"), MB_OK); + SetFocus(GetDlgItem(hDlg, IDC_EDITNPOPS)); + break; + } + TimeF = GetDlgItemInt(hDlg, IDC_EDITFPOPS, &Translated, FALSE); + if (!Translated) { + MessageBox(hDlg, TranslateT("This is not a valid number value"), TranslateT("Input error"), MB_OK); + SetFocus(GetDlgItem(hDlg, IDC_EDITFPOPS)); + break; + } + + DlgSetItemTextT(hDlg, 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(hDlg, IDC_CPB, CPM_GETCOLOUR, 0, 0); + ActualAccount->NewMailN.PopupT = SendDlgItemMessage(hDlg, IDC_CPT, CPM_GETCOLOUR, 0, 0); + ActualAccount->NewMailN.PopupTime = Time; + + ActualAccount->NoNewMailN.PopupB = SendDlgItemMessage(hDlg, IDC_CPNB, CPM_GETCOLOUR, 0, 0); + ActualAccount->NoNewMailN.PopupT = SendDlgItemMessage(hDlg, IDC_CPNT, CPM_GETCOLOUR, 0, 0); + ActualAccount->NoNewMailN.PopupTime = TimeN; + + ActualAccount->BadConnectN.PopupB = SendDlgItemMessage(hDlg, IDC_CPFB, CPM_GETCOLOUR, 0, 0); + ActualAccount->BadConnectN.PopupT = SendDlgItemMessage(hDlg, IDC_CPFT, CPM_GETCOLOUR, 0, 0); + ActualAccount->BadConnectN.PopupTime = TimeF; + + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:APPLY:ActualAccountSO-write done\n"); + #endif + WriteDone(ActualAccount); + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile, "Options:APPLY:AccountBrowserSO-write done\n"); + #endif + WriteDoneSO(POP3Plugin->AccountBrowserSO); + + WritePOP3Accounts(); + RefreshContact(); + return TRUE; + } + } + break; + } + break; + } + break; + } + if (Changed) + SendMessage(GetParent(hDlg), PSM_CHANGED, 0, 0); + return FALSE; +} diff --git a/protocols/YAMN/src/proto/pop3/pop3opt.h b/protocols/YAMN/src/proto/pop3/pop3opt.h new file mode 100644 index 0000000000..245f7679a4 --- /dev/null +++ b/protocols/YAMN/src/proto/pop3/pop3opt.h @@ -0,0 +1,40 @@ +#ifndef __OPTIONS_H +#define __OPTIONS_H + +#define M_SHOWACTUAL 0 +#define M_SHOWDEFAULT 1 + + +//Enables account in options +BOOL DlgEnableAccount(HWND hDlg,WPARAM wParam,LPARAM lParam); + +//Sets dialog controls to match current account +BOOL DlgShowAccount(HWND hDlg,WPARAM wParam,LPARAM lParam); + +//Sets colors to match colors of actual account +BOOL DlgShowAccountColors(HWND hDlg,WPARAM wParam,LPARAM lParam); + +//Options dialog procedure +INT_PTR CALLBACK DlgProcPOP3AccOpt(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +//Options dialog procedure +INT_PTR CALLBACK DlgProcPOP3AccStatusOpt(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +//Options dialog procedure +INT_PTR CALLBACK DlgProcYAMNOpt(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +//Options dialog procedure +INT_PTR CALLBACK DlgProcPOP3AccPopup(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +//Initializes POP3 options for Miranda +int POP3OptInit(WPARAM wParam,LPARAM lParam); + +//Sets dialog item text +BOOL DlgSetItemText(HWND hDlg,WPARAM wParam,const char*); +BOOL DlgSetItemTextW(HWND hDlg,WPARAM wParam,const WCHAR*); + + +#define DlgSetItemTextT DlgSetItemTextW + + +#endif |