From b61ba851da0157ace3bdfc1ebbf87156b0b76413 Mon Sep 17 00:00:00 2001 From: Kirill Volinsky Date: Wed, 6 Jun 2012 08:58:27 +0000 Subject: protocols plugins moved to protocols git-svn-id: http://svn.miranda-ng.org/main/trunk@327 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/YAMN/proto/md5.c | 260 ++++++ protocols/YAMN/proto/md5.h | 27 + protocols/YAMN/proto/netclient.h | 22 + protocols/YAMN/proto/netlib.cpp | 271 ++++++ protocols/YAMN/proto/netlib.h | 55 ++ protocols/YAMN/proto/pop3/pop3.cpp | 370 ++++++++ protocols/YAMN/proto/pop3/pop3.h | 66 ++ protocols/YAMN/proto/pop3/pop3comm.cpp | 1563 ++++++++++++++++++++++++++++++++ protocols/YAMN/proto/pop3/pop3comm.h | 97 ++ protocols/YAMN/proto/pop3/pop3opt.cpp | 1556 +++++++++++++++++++++++++++++++ protocols/YAMN/proto/pop3/pop3opt.h | 42 + 11 files changed, 4329 insertions(+) create mode 100644 protocols/YAMN/proto/md5.c create mode 100644 protocols/YAMN/proto/md5.h create mode 100644 protocols/YAMN/proto/netclient.h create mode 100644 protocols/YAMN/proto/netlib.cpp create mode 100644 protocols/YAMN/proto/netlib.h create mode 100644 protocols/YAMN/proto/pop3/pop3.cpp create mode 100644 protocols/YAMN/proto/pop3/pop3.h create mode 100644 protocols/YAMN/proto/pop3/pop3comm.cpp create mode 100644 protocols/YAMN/proto/pop3/pop3comm.h create mode 100644 protocols/YAMN/proto/pop3/pop3opt.cpp create mode 100644 protocols/YAMN/proto/pop3/pop3opt.h (limited to 'protocols/YAMN/proto') diff --git a/protocols/YAMN/proto/md5.c b/protocols/YAMN/proto/md5.c new file mode 100644 index 0000000000..25546d2a65 --- /dev/null +++ b/protocols/YAMN/proto/md5.c @@ -0,0 +1,260 @@ +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ +//#include /* for memcpy() */ +#if defined(_WIN64) + typedef unsigned __int64 size_t; +#else + typedef unsigned int size_t; + #include "../filter/simple/AggressiveOptimize.h" +#endif +void * __cdecl memcpy(void *, const void *, size_t); +void * __cdecl memset(void *, int, size_t); +#include "md5.h" + +#ifndef HIGHFIRST +#define byteReverse(buf, len) /* Nothing */ +#else +void byteReverse(unsigned char *buf, unsigned longs); + +#ifndef ASM_MD5 +/* + * Note: this code is harmless on little-endian machines. + */ +void byteReverse(unsigned char *buf, unsigned longs) +{ + uint32 t; + do { + t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + *(uint32 *) buf = t; + buf += 4; + } while (--longs); +} +#endif +#endif + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void MD5Init(struct MD5Context *ctx) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) +{ + uint32 t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *) ctx->in); + buf += t; + len -= t; + } + /* Process data in 64-byte chunks */ + + while (len >= 64) { + memcpy(ctx->in, buf, 64); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *) ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + memcpy(ctx->in, buf, len); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +void MD5Final(unsigned char digest[16], struct MD5Context *ctx) +{ + unsigned count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset(p, 0, count); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *) ctx->in); + + /* Now fill the next block with 56 bytes */ + memset(ctx->in, 0, 56); + } else { + /* Pad block to 56 bytes */ + memset(p, 0, count - 8); + } + byteReverse(ctx->in, 14); + + /* Append length in bits and transform */ + ((uint32 *) ctx->in)[14] = ctx->bits[0]; + ((uint32 *) ctx->in)[15] = ctx->bits[1]; + + MD5Transform(ctx->buf, (uint32 *) ctx->in); + byteReverse((unsigned char *) ctx->buf, 4); + memcpy(digest, ctx->buf, 16); + memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ +} + +#ifndef ASM_MD5 + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +void MD5Transform(uint32 buf[4], uint32 const in[16]) +{ + register uint32 a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +#endif diff --git a/protocols/YAMN/proto/md5.h b/protocols/YAMN/proto/md5.h new file mode 100644 index 0000000000..e264f686db --- /dev/null +++ b/protocols/YAMN/proto/md5.h @@ -0,0 +1,27 @@ +#ifndef MD5_H +#define MD5_H + +#ifdef __alpha +typedef unsigned int uint32; +#else +typedef unsigned long uint32; +#endif + +struct MD5Context { + uint32 buf[4]; + uint32 bits[2]; + unsigned char in[64]; +}; + +void MD5Init(struct MD5Context *context); +void MD5Update(struct MD5Context *context, unsigned char const *buf, + unsigned len); +void MD5Final(unsigned char digest[16], struct MD5Context *context); +void MD5Transform(uint32 buf[4], uint32 const in[16]); + +/* + * This is needed to make RSAREF happy on some MS-DOS compilers. + */ +typedef struct MD5Context MD5_CTX; + +#endif /* !MD5_H */ diff --git a/protocols/YAMN/proto/netclient.h b/protocols/YAMN/proto/netclient.h new file mode 100644 index 0000000000..2414dbdef1 --- /dev/null +++ b/protocols/YAMN/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=NULL,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/proto/netlib.cpp b/protocols/YAMN/proto/netlib.cpp new file mode 100644 index 0000000000..b7c1864ffa --- /dev/null +++ b/protocols/YAMN/proto/netlib.cpp @@ -0,0 +1,271 @@ +/* + * This code implements communication based on Miranda netlib library + * + * (c) majvan 2002-2004 + */ + +#include "..\yamn.h" +#include "m_netlib.h" +#include "netlib.h" + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +BOOL SSLLoaded=FALSE; +HANDLE hNetlibUser=NULL; + +extern PVOID TLSCtx; +extern PVOID SSLCtx; + +void __stdcall SSL_DebugLog(const char *fmt, ...) +{ + char str[ 4096 ]; + va_list vararg; + + va_start( vararg, fmt ); + int tBytes = _vsnprintf( str, sizeof(str)-1, fmt, vararg ); + if ( tBytes == 0 ) + return; + + if ( tBytes > 0 ) + str[ tBytes ] = 0; + else + str[ sizeof(str)-1 ] = 0; + + CallService(MS_NETLIB_LOG, (WPARAM)hNetlibUser, (LPARAM)str); + va_end( vararg ); +} + +HANDLE RegisterNLClient(const char *name) +{ + static NETLIBUSER nlu={0}; + char desc[128]; + + sprintf(desc, Translate("%s connection"),name); + +#ifdef DEBUG_COMM + DebugLog(CommFile,""); +#endif + nlu.cbSize = sizeof(nlu); + nlu.flags = NUF_OUTGOING | NUF_HTTPCONNS; + nlu.szDescriptiveName=desc; + nlu.szSettingsModule=(char *)name; + hNetlibUser=(HANDLE)CallService(MS_NETLIB_REGISTERUSER,0,(LPARAM)&nlu); + +#ifdef DEBUG_COMM + if (NULL==hNetlibUser) + DebugLog(CommFile,"\n"); + else + DebugLog(CommFile,"\n"); +#endif + return hNetlibUser; +} + +//Move connection to SSL +void CNLClient::SSLify() throw(DWORD){ +#ifdef DEBUG_COMM + SSL_DebugLog("Staring SSL..."); +#endif + int socket = CallService(MS_NETLIB_GETSOCKET, (WPARAM)hConnection, 0); + if (socket != INVALID_SOCKET) + { +#ifdef DEBUG_COMM + SSL_DebugLog("Staring netlib core SSL"); +#endif + if (CallService(MS_NETLIB_STARTSSL, (WPARAM)hConnection, 0)) + { +#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) +{ + NETLIBOPENCONNECTION nloc; + + NetworkError=SystemError=0; + isTLSed = false; + +#ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); +#endif + try + { + nloc.cbSize=sizeof(NETLIBOPENCONNECTION); + nloc.szHost=servername; + nloc.wPort=port; + nloc.flags=0; + if (NULL==(hConnection=(HANDLE)CallService(MS_NETLIB_OPENCONNECTION,(WPARAM)hNetlibUser,(LPARAM)&nloc))) + { + SystemError=WSAGetLastError(); + throw NetworkError=(DWORD)ENL_CONNECT; + } +#ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); +#endif + return; + } + catch(...) + { +#ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); +#endif + throw; + } +} + +//Performs a simple query +// query- command to send +int CNLClient::LocalNetlib_Send(HANDLE hConn,const char *buf,int len,int flags) { + if (isTLSed) + { +#ifdef DEBUG_COMM + SSL_DebugLog("SSL send: %s", buf); +#endif + } + + NETLIBBUFFER nlb={(char*)buf,len,flags}; + return CallService(MS_NETLIB_SEND,(WPARAM)hConn,(LPARAM)&nlb); +} + +void CNLClient::Send(const char *query) throw(DWORD) +{ + unsigned int Sent; + + if (NULL==query) + return; + if (hConnection==NULL) + return; +#ifdef DEBUG_COMM + DebugLog(CommFile,"%s",query); +#endif + try + { + if ((SOCKET_ERROR==(Sent=LocalNetlib_Send(hConnection,query,(int)strlen(query),MSG_DUMPASTEXT))) || Sent!=(unsigned int)strlen(query)) + { + SystemError=WSAGetLastError(); + throw NetworkError=(DWORD)ENL_SEND; + } +#ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); +#endif + } + catch(...) + { +#ifdef DEBUG_COMM + DebugLog(CommFile,"\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(HANDLE hConn,char *buf,int len,int flags) { + NETLIBBUFFER nlb={buf,len,flags}; + int iReturn = CallService(MS_NETLIB_RECV,(WPARAM)hConn,(LPARAM)&nlb); + 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,""); +#endif + try + { + if (buf==NULL) + buf=(char *)malloc(sizeof(char)*(buflen+1)); + if (buf==NULL) + throw NetworkError=(DWORD)ENL_RECVALLOC; + + if (!isTLSed) + { + NETLIBSELECT nls; + memset(&nls, 0, sizeof(NETLIBSELECT)); + nls.cbSize = sizeof(NETLIBSELECT); + nls.dwTimeout = 60000; + nls.hReadConns[0] = hConnection; + switch (CallService(MS_NETLIB_SELECT, 0, (LPARAM) &nls)) + { + case SOCKET_ERROR: + free(buf); + SystemError=WSAGetLastError(); + throw NetworkError = (DWORD) ENL_RECV; + case 0: // time out! + free(buf); + throw NetworkError = (DWORD) ENL_TIMEOUT; + } + } + + ZeroMemory(buf,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,"\n"); +#endif + return(buf); + } + catch(...) + { +#ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); +#endif + throw; + } +} + +//Closes netlib connection +void CNLClient::Disconnect() +{ + Netlib_CloseHandle(hConnection); + hConnection=(HANDLE)NULL; +} + +//Uninitializes netlib library +void UnregisterNLClient() +{ +#ifdef DEBUG_COMM + DebugLog(CommFile,""); +#endif + + Netlib_CloseHandle(hNetlibUser); + hNetlibUser=(HANDLE)NULL; +#ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); +#endif +} diff --git a/protocols/YAMN/proto/netlib.h b/protocols/YAMN/proto/netlib.h new file mode 100644 index 0000000000..90ad3613a5 --- /dev/null +++ b/protocols/YAMN/proto/netlib.h @@ -0,0 +1,55 @@ +#ifndef __NETLIB_H +#define __NETLIB_H + +#include "netclient.h" + +#pragma warning( disable : 4290 ) + +class CNLClient: public CNetClient +{ +public: + CNLClient(): hConnection(NULL) {} + void Connect(const char* servername,const int port) throw(DWORD); + void Send(const char *query) throw(DWORD); + char* Recv(char *buf=NULL,int buflen=65536) throw(DWORD); + void Disconnect(); + void SSLify()throw(DWORD); + + inline BOOL Connected() {return hConnection!=NULL;} + +protected: + HANDLE hConnection; + BOOL isTLSed; + int LocalNetlib_Send(HANDLE hConn,const char *buf,int len,int flags); + int LocalNetlib_Recv(HANDLE 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/proto/pop3/pop3.cpp b/protocols/YAMN/proto/pop3/pop3.cpp new file mode 100644 index 0000000000..05e85d7156 --- /dev/null +++ b/protocols/YAMN/proto/pop3/pop3.cpp @@ -0,0 +1,370 @@ +/* + * This code implements basics of POP3 protocol + * + * (c) majvan 2002-2004 + */ +/* This was made from the libspopc project + * copyright c 2002 Benoit Rouits + * 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 + * 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 + * + */ + +#pragma warning( disable : 4290 ) + +#include "..\..\yamn.h" +#include "pop3.h" + +extern "C" { +#include "../md5.h" +} + +extern void __stdcall SSL_DebugLog( const char *fmt, ... ); + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +//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 = 0; + if (Stopped) //check if we can work with this POP3 client session + throw POP3Error=(DWORD)EPOP3_STOPPED; + + if (NetClient!=NULL) + 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 NULL; + } + } + + 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 NULL; + } +// 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!=NULL) + free(PrevString); + throw POP3Error=(DWORD)EPOP3_STOPPED; + } + if (SizeLeft==0) //if block is full + { + SizeRead+=size; + SizeLeft=size; + LastString=NetClient->Recv(NULL,SizeLeft); + PrevString=(char *)realloc(PrevString,sizeof(char)*(SizeRead+size)); + if (PrevString==NULL) + 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; +// printf("[Read: %s]\n",PrevString); + } + 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; + + sprintf(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; + + sprintf(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]; + char hexdigest[40]; + + if (timestamp==NULL) + throw POP3Error=(DWORD)EPOP3_APOP; + MD5Context ctx; + MD5Init(&ctx); + MD5Update(&ctx,(const unsigned char *)timestamp,(unsigned int)strlen(timestamp)); + MD5Update(&ctx,(const unsigned char *)pw,(unsigned int)strlen(pw)); + MD5Final(digest,&ctx); + hexdigest[0]='\0'; + for (int i=0; i<16; i++) { + char tmp[4]; + sprintf(tmp, "%02x", digest[i]); + strcat(hexdigest, tmp); + } + sprintf(query,"APOP %s %s\r\n",name, 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]; + + sprintf(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) + { + sprintf(query,"UIDL %d\r\n",nr); + NetClient->Send(query); + return RecvRest(NetClient->Recv(),POP3_SEARCHACK); + } + sprintf(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]; + + sprintf(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]; + + sprintf(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/proto/pop3/pop3.h b/protocols/YAMN/proto/pop3/pop3.h new file mode 100644 index 0000000000..1f7f2ea737 --- /dev/null +++ b/protocols/YAMN/proto/pop3/pop3.h @@ -0,0 +1,66 @@ +#ifndef __POP3_H +#define __POP3_H + +#include "../../debug.h" +#include "../netlib.h" //NetLib client + +#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(NULL), Stopped(FALSE) {} + ~CPop3Client() {if (NetClient!=NULL) 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/proto/pop3/pop3comm.cpp b/protocols/YAMN/proto/pop3/pop3comm.cpp new file mode 100644 index 0000000000..dcd38ee2c8 --- /dev/null +++ b/protocols/YAMN/proto/pop3/pop3comm.cpp @@ -0,0 +1,1563 @@ +/* + * 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 +*/ + + +#pragma warning( disable : 4290 ) +#include "../../yamn.h" +#include "../../main.h" +#include "pop3.h" +#include "pop3comm.h" //all we need for POP3 account (POP3 account= YAMN account + some more POP3 specified members) +#include //socket thorugh proxy functions + +#define ERRORSTR_MAXLEN 1024 //in wide-chars + +//-------------------------------------------------------------------------------------------------- + +HANDLE hNetLib = NULL; +PSCOUNTER CPOP3Account::AccountWriterSO = NULL; + +//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 +DWORD WINAPI DeleteMailsPOP3(struct DeleteParam *WhichTemp); + +//Function makes readable message about error. It sends it back to YAMN, so YAMN then +//can show it to the message window +TCHAR* 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 len,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 = NULL; +MailExportedFcns *pYAMNMailFcn = NULL; + +YAMN_PROTOIMPORTFCN POP3ProtocolFunctions = +{ + CreatePOP3Account, + DeletePOP3Account, + StopPOP3Account, + WritePOP3Options, + ReadPOP3Options, + SynchroPOP3, + SynchroPOP3, + SynchroPOP3, + DeleteMailsPOP3, + GetErrorString, + NULL, + DeleteErrorString, + WritePOP3Accounts, + NULL, + UnLoadPOP3, +}; + +YAMN_MAILIMPORTFCN POP3MailFunctions = +{ + CreatePOP3Mail, + NULL, + NULL, + NULL, +}; + +PYAMN_VARIABLES pYAMNVar = NULL; +HYAMNPROTOPLUGIN POP3Plugin = NULL; + +YAMN_PROTOREGISTRATION POP3ProtocolRegistration = +{ + "POP3 protocol (internal)", + YAMN_VERSION_C, + "© 2002-2004 majvan | 2005-2007 tweety, yb", + "Mail notifier and browser for Miranda IM. Included POP3 protocol.", + "francois.mean@skynet.be", + "http://forums.miranda-im.org/showthread.php?t=3035", +}; + +static TCHAR *FileName = NULL; + +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(NULL,FALSE,TRUE,NULL); + InternetQueries=new SCOUNTER; + AbilityFlags=YAMN_ACC_BROWSE | YAMN_ACC_POPUP; + + SetAccountStatus((HACCOUNT)this,TranslateT("Disconnected")); +} + +CPOP3Account::~CPOP3Account() +{ + CloseHandle(UseInternetFree); + if (InternetQueries!=NULL) + delete InternetQueries; +} + +HACCOUNT WINAPI CreatePOP3Account(HYAMNPROTOPLUGIN Plugin,DWORD CAccountVersion) +{ +//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!=NULL) //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 (NULL==(pYAMNVar=(PYAMN_VARIABLES)CallService(MS_YAMN_GETVARIABLES,(WPARAM)YAMN_VARIABLESVERSION,(LPARAM)0))) + return 0; + + //We have to get pointers to YAMN exported functions: allocate structure and fill it + if (NULL==(pYAMNFcn=new struct YAMNExportedFcns)) + {UnLoadPOP3(0); return 0;} + + //Register new pop3 user in netlib + if (NULL==(hNetLib=RegisterNLClient("YAMN-POP3"))) + {UnLoadPOP3(0); return 0;} + + pYAMNFcn->SetProtocolPluginFcnImportFcn=(YAMN_SETPROTOCOLPLUGINFCNIMPORTFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_SETPROTOCOLPLUGINFCNIMPORTID,(LPARAM)0); + pYAMNFcn->WaitToWriteFcn=(YAMN_WAITTOWRITEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_WAITTOWRITEID,(LPARAM)0); + pYAMNFcn->WriteDoneFcn=(YAMN_WRITEDONEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_WRITEDONEID,(LPARAM)0); + pYAMNFcn->WaitToReadFcn=(YAMN_WAITTOREADFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_WAITTOREADID,(LPARAM)0); + pYAMNFcn->ReadDoneFcn=(YAMN_READDONEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_READDONEID,(LPARAM)0); + pYAMNFcn->SCGetNumberFcn=(YAMN_SCMANAGEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_SCGETNUMBERID,(LPARAM)0); + pYAMNFcn->SCIncFcn=(YAMN_SCMANAGEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_SCINCID,(LPARAM)0); + pYAMNFcn->SCDecFcn=(YAMN_SCMANAGEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_SCDECID,(LPARAM)0); + pYAMNFcn->SetStatusFcn=(YAMN_SETSTATUSFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_SETSTATUSID,(LPARAM)0); + pYAMNFcn->GetStatusFcn=(YAMN_GETSTATUSFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_GETSTATUSID,(LPARAM)0); + + if (NULL==(pYAMNMailFcn=new struct MailExportedFcns)) + {UnLoadPOP3(0); return 0;} + + pYAMNMailFcn->SynchroMessagesFcn=(YAMN_SYNCHROMIMEMSGSFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_SYNCHROMIMEMSGSID,(LPARAM)0); + pYAMNMailFcn->TranslateHeaderFcn=(YAMN_TRANSLATEHEADERFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_TRANSLATEHEADERID,(LPARAM)0); + pYAMNMailFcn->AppendQueueFcn=(YAMN_APPENDQUEUEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_APPENDQUEUEID,(LPARAM)0); + pYAMNMailFcn->DeleteMessagesToEndFcn=(YAMN_DELETEMIMEQUEUEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_DELETEMIMEQUEUEID,(LPARAM)0); + pYAMNMailFcn->DeleteMessageFromQueueFcn=(YAMN_DELETEMIMEMESSAGEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_DELETEMIMEMESSAGEID,(LPARAM)0); + pYAMNMailFcn->FindMessageByIDFcn=(YAMN_FINDMIMEMESSAGEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_FINDMIMEMESSAGEID,(LPARAM)0); + pYAMNMailFcn->CreateNewDeleteQueueFcn=(YAMN_CREATENEWDELETEQUEUEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_CREATENEWDELETEQUEUEID,(LPARAM)0); + + //set static variable + if (CPOP3Account::AccountWriterSO==NULL) { + if (NULL==(CPOP3Account::AccountWriterSO=new SCOUNTER)) + {UnLoadPOP3(0); 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("Mail notifier and browser for Miranda IM. Included POP3 protocol."); + if (NULL==(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 = (TCHAR *)CallService(MS_YAMN_GETFILENAME,(WPARAM)_T("pop3"), 0); + + switch(CallService(MS_YAMN_READACCOUNTS,(WPARAM)POP3Plugin,(LPARAM)FileName)) { + case EACC_FILEVERSION: + MessageBox(NULL,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,(LPARAM)0); + FileName = NULL; + return 0; + case EACC_FILECOMPATIBILITY: + MessageBox(NULL,TranslateT("Error reading account file. Account file corrupted."),TranslateT("YAMN (internal POP3) read error"),MB_OK); + CallService(MS_YAMN_DELETEFILENAME,(WPARAM)FileName,(LPARAM)0); + FileName = NULL; + return 0; + case EACC_ALLOC: + MessageBox(NULL,TranslateT("Memory allocation error while data reading"),TranslateT("YAMN (internal POP3) read error"),MB_OK); + CallService(MS_YAMN_DELETEFILENAME,(WPARAM)FileName,(LPARAM)0); + FileName = NULL; + return 0; + case EACC_SYSTEM: + if (ERROR_FILE_NOT_FOUND!=GetLastError()) + { + TCHAR temp[1024] = {0}; + mir_sntprintf(temp, SIZEOF(temp), _T("%s\n%s"),TranslateT("Reading file error. File already in use?"),FileName); + MessageBox(NULL,temp,TranslateT("YAMN (internal POP3) read error"),MB_OK); + CallService(MS_YAMN_DELETEFILENAME,(WPARAM)FileName,(LPARAM)0); + FileName = NULL; + return 0; + } + break; + } + //HookEvent(ME_OPT_INITIALISE,POP3OptInit); + + HACCOUNT Finder; + HANDLE hContact; + DBVARIANT dbv; + char *szProto; + + for (Finder=POP3Plugin->FirstAccount;Finder!=NULL;Finder=Finder->Next) + { + Finder->hContact = NULL; + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while(hContact) + { + szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + if (szProto != NULL && strcmp(szProto, YAMN_DBMODULE)==0) + { + if (!DBGetContactSettingString(hContact,YAMN_DBMODULE,"Id",&dbv)) { + if ( strcmp( dbv.pszVal, Finder->Name) == 0) { + Finder->hContact = hContact; + DBWriteContactSettingWord(Finder->hContact, YAMN_DBMODULE, "Status", ID_STATUS_ONLINE); + DBWriteContactSettingString(Finder->hContact, "CList", "StatusMsg", Translate("No new mail message")); + if ((Finder->Flags & YAMN_ACC_ENA) && (Finder->NewMailN.Flags & YAMN_ACC_CONT)) + DBDeleteContactSetting(Finder->hContact, "CList", "Hidden"); + + if (!(Finder->Flags & YAMN_ACC_ENA) || !(Finder->NewMailN.Flags & YAMN_ACC_CONT)) + DBWriteContactSettingByte(Finder->hContact, "CList", "Hidden", 1); + } + DBFreeVariant(&dbv); + } + } + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); + } + + if (Finder->hContact == NULL && (Finder->Flags & YAMN_ACC_ENA) && (Finder->NewMailN.Flags & YAMN_ACC_CONT)) { + //No account contact found, have to create one + Finder->hContact =(HANDLE) CallService(MS_DB_CONTACT_ADD, 0, 0); + CallService(MS_PROTO_ADDTOCONTACT,(WPARAM)Finder->hContact,(LPARAM)YAMN_DBMODULE); + DBWriteContactSettingString(Finder->hContact,YAMN_DBMODULE,"Id",Finder->Name); + DBWriteContactSettingString(Finder->hContact,YAMN_DBMODULE,"Nick",Finder->Name); + DBWriteContactSettingString(Finder->hContact,"Protocol","p",YAMN_DBMODULE); + DBWriteContactSettingWord(Finder->hContact, YAMN_DBMODULE, "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 = NULL;} + if (CPOP3Account::AccountWriterSO) { + delete CPOP3Account::AccountWriterSO; CPOP3Account::AccountWriterSO = NULL;} + if (pYAMNMailFcn) { + delete pYAMNMailFcn; pYAMNMailFcn = NULL;} + if (pYAMNFcn) { + delete pYAMNFcn; pYAMNFcn = NULL;} + if (FileName) { + CallService(MS_YAMN_DELETEFILENAME,(WPARAM)FileName,(LPARAM)0); FileName = NULL;} + + #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) { + TCHAR temp[1024] = {0}; + mir_sntprintf(temp, SIZEOF(temp), _T("%s\n%s"), TranslateT("Error while copying data to disk occured. File in use?"), FileName ); + MessageBox(NULL, 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,NULL)) || + (!WriteFile(File,(char *)&((HPOP3ACCOUNT)Which)->CP,sizeof(WORD),&WrittenBytes,NULL))) + return EACC_SYSTEM; + return 0; +} + +DWORD WINAPI ReadPOP3Options(HACCOUNT Which,char **Parser,char *End) +{ + DWORD Ver; +#ifdef DEBUG_FILEREAD + TCHAR 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 + _stprintf(Debug,_T("CodePage: %d, remaining %d chars"),((HPOP3ACCOUNT)Which)->CP,End-*Parser); + MessageBox(NULL,Debug,_T("debug"),MB_OK); +#endif + return 0; +} + +HYAMNMAIL WINAPI CreatePOP3Mail(HACCOUNT Account,DWORD MailDataVersion) +{ + 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 (NULL==(NewMail=new YAMNMAIL)) + return NULL; + + if (NULL==(NewMail->MailData=new MAILDATA)) + { + delete NewMail; + return NULL; + } + 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)) { + DBWriteContactSettingWord(account->hContact, YAMN_DBMODULE, "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 (NULL!=(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!=NULL) + 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==NULL) + { + 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==NULL) + return; + + if ((ActualAccount->BadConnectN.Flags & YAMN_ACC_MSG) || (ActualAccount->BadConnectN.Flags & YAMN_ACC_ICO) || (ActualAccount->BadConnectN.Flags & YAMN_ACC_POP)) + { + YAMN_BADCONNECTIONPARAM cp={(HANDLE)0,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=NULL,MsgQueuePtr=NULL; + char* DataRX=NULL,*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==NULL) || !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=NULL; + + if (DataRX!=NULL) + { + 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=NULL; + } + + SetAccountStatus(ActualAccount,TranslateT("Entering POP3 account")); + + if (ActualCopied.Flags & YAMN_ACC_APOP) + { + DataRX=MyClient->APOP(ActualCopied.ServerLogin,ActualCopied.ServerPasswd,timestamp); + if (DataRX!=NULL) + free(DataRX); + DataRX=NULL; + delete[] timestamp; + } else { + DataRX=MyClient->User(ActualCopied.ServerLogin); + if (DataRX!=NULL) + free(DataRX); + DataRX=NULL; + DataRX=MyClient->Pass(ActualCopied.ServerPasswd); + if (DataRX!=NULL) + free(DataRX); + DataRX=NULL; + } + } + SetAccountStatus(ActualAccount,TranslateT("Searching for new mail message")); + + DataRX=MyClient->Stat(); + + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"<--------Account checking-------->\n"); + DebugLog(DecodeFile,"\n"); + #endif + ExtractStat(DataRX,MyClient->NetClient->Rcv,&mboxsize,&msgs); + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"%d\n",mboxsize); + DebugLog(DecodeFile,"%d\n",msgs); + DebugLog(DecodeFile,"\n"); + #endif + if (DataRX!=NULL) + free(DataRX); + DataRX=NULL; + for (i=0;iNext=(HYAMNMAIL)CallService(MS_YAMN_CREATEACCOUNTMAIL,(WPARAM)ActualAccount,(LPARAM)YAMN_MAILVERSION); + MsgQueuePtr=MsgQueuePtr->Next; + } + if (MsgQueuePtr==NULL) + { + ActualAccount->SystemError=EPOP3_QUEUEALLOC; + throw (DWORD)ActualAccount->SystemError; + } + } + + if (msgs) + { + DataRX=MyClient->List(); + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + #endif + ExtractList(DataRX,MyClient->NetClient->Rcv,NewMails); + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + #endif + if (DataRX!=NULL) + free(DataRX); + DataRX=NULL; + + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + #endif + DataRX=MyClient->Uidl(); + ExtractUIDL(DataRX,MyClient->NetClient->Rcv,NewMails); + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + #endif + if (DataRX!=NULL) + free(DataRX); + DataRX=NULL; + } + #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!=NULL;MsgQueuePtr=MsgQueuePtr->Next){ + if (MsgQueuePtr->Flags&YAMN_MSG_BODYREQUESTED){ + HYAMNMAIL NewMsgsPtr=NULL; + for (NewMsgsPtr=(HYAMNMAIL)NewMails;NewMsgsPtr!=NULL;NewMsgsPtr=NewMsgsPtr->Next){ + if (!strcmp(MsgQueuePtr->ID,NewMsgsPtr->ID)) { + TCHAR accstatus[512]; + wsprintf(accstatus,TranslateT("Reading body %s"),NewMsgsPtr->ID); + SetAccountStatus(ActualAccount,accstatus); + DataRX=MyClient->Top(MsgQueuePtr->Number,100); + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + DebugLog(DecodeFile,"
%s
\n",DataRX); + #endif + if (DataRX!=NULL) + { + Temp=DataRX; + while((TempNetClient->Rcv) && (WS(Temp) || ENDLINE(Temp))) Temp++; + + if (OKLINE(DataRX)) + for (Temp=DataRX;(TempNetClient->Rcv) && (!ENDLINE(Temp));Temp++); + while((TempNetClient->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!=NULL;) + { + TH=TH->Next; + if (MsgQueuePtr->MailData->TranslatedHeader->name!=NULL) + delete[] MsgQueuePtr->MailData->TranslatedHeader->name; + if (MsgQueuePtr->MailData->TranslatedHeader->value!=NULL) + 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,"
\n"); + #endif + MsgQueuePtr->Flags|=YAMN_MSG_BODYRECEIVED; + + if (DataRX!=NULL) + free(DataRX); + DataRX=NULL; + break; + } + } + } + } + + SynchroMessages(ActualAccount,(HYAMNMAIL *)&ActualAccount->Mails,NULL,(HYAMNMAIL *)&NewMails,NULL); //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!=NULL;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!=NULL;MsgQueuePtr=MsgQueuePtr->Next,msgs++); //get number of new mails + + try + { + TCHAR accstatus[512]; + + for (i=0,MsgQueuePtr=NewMails;MsgQueuePtr!=NULL;i++) + { + BOOL autoretr = (ActualAccount->Flags & YAMN_ACC_BODY)!=0; + DataRX=MyClient->Top(MsgQueuePtr->Number,autoretr?100:0); + wsprintf(accstatus,TranslateT("Reading new mail messages (%d%% done)"),100*i/msgs); + SetAccountStatus(ActualAccount,accstatus); + + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + DebugLog(DecodeFile,"
%s
\n",DataRX); + #endif + if (DataRX!=NULL) + { + Temp=DataRX; + while((TempNetClient->Rcv) && (WS(Temp) || ENDLINE(Temp))) Temp++; + + if (OKLINE(DataRX)) + for (Temp=DataRX;(TempNetClient->Rcv) && (!ENDLINE(Temp));Temp++); + while((TempNetClient->Rcv) && ENDLINE(Temp)) Temp++; + } + else + continue; + + TranslateHeader(Temp,MyClient->NetClient->Rcv-(Temp-DataRX),&MsgQueuePtr->MailData->TranslatedHeader); + + + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"
\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!=NULL) + free(DataRX); + DataRX=NULL; + + //MsgQueuePtr->MailData->Body=MyClient->Retr(MsgQueuePtr->Number); + + MsgQueuePtr=MsgQueuePtr->Next; + + } + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\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==NULL) + 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!=NULL) + free(DataRX); + DataRX=NULL; + 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)0,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!=NULL) + free(DataRX); + DataRX=NULL; + 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,"\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; +} + +DWORD WINAPI DeleteMailsPOP3(struct DeleteParam *WhichTemp) +{ + HPOP3ACCOUNT ActualAccount; + LPVOID YAMNParam; + UINT_PTR POP3PluginParam; + CPop3Client *MyClient; + HYAMNMAIL DeleteMails,NewMails=NULL,MsgQueuePtr; + char* DataRX=NULL; + int mboxsize,msgs,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". + // } + + ActualAccount=(HPOP3ACCOUNT)((struct DeleteParam *)WhichTemp)->AccountParam; //copy address of structure from calling thread to stack of this thread + YAMNParam=((struct DeleteParam *)WhichTemp)->BrowserParam; + 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 0; + } +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:ActualAccountSO-read enter\n"); +#endif + if (NULL==(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)0,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 NO_MAIL_FOR_DELETE; + } + 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==NULL) || !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=NULL; + if (DataRX!=NULL) { + 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=NULL; + } + SetAccountStatus(ActualAccount,TranslateT("Entering POP3 account")); + + if (ActualAccount->Flags & YAMN_ACC_APOP) + { + DataRX=MyClient->APOP(ActualCopied.ServerLogin,ActualCopied.ServerPasswd,timestamp); + if (DataRX!=NULL) + free(DataRX); + DataRX=NULL; + delete[] timestamp; + } else { + DataRX=MyClient->User(ActualCopied.ServerLogin); + if (DataRX!=NULL) + free(DataRX); + DataRX=NULL; + DataRX=MyClient->Pass(ActualCopied.ServerPasswd); + if (DataRX!=NULL) + free(DataRX); + DataRX=NULL; + } + } + +#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,"\n"); +#endif + ExtractStat(DataRX,MyClient->NetClient->Rcv,&mboxsize,&msgs); +#ifdef DEBUG_DECODE + DebugLog(DecodeFile,"%d\n",mboxsize); + DebugLog(DecodeFile,"%d\n",msgs); + DebugLog(DecodeFile,"\n"); +#endif + if (DataRX!=NULL) + free(DataRX); + DataRX=NULL; + for (i=0;iNext=(HYAMNMAIL)CallService(MS_YAMN_CREATEACCOUNTMAIL,(WPARAM)ActualAccount,(LPARAM)YAMN_MAILVERSION); + MsgQueuePtr=MsgQueuePtr->Next; + } + if (MsgQueuePtr==NULL) + { + ActualAccount->SystemError=EPOP3_QUEUEALLOC; + throw (DWORD)ActualAccount->SystemError; + } + } + + if (msgs) + { +#ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); +#endif + DataRX=MyClient->Uidl(); + ExtractUIDL(DataRX,MyClient->NetClient->Rcv,NewMails); +#ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); +#endif + if (DataRX!=NULL) + free(DataRX); + DataRX=NULL; +// 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,NULL,(HYAMNMAIL *)&NewMails,NULL); + } + } + 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!=NULL;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!=NULL) + free(DataRX); + DataRX=NULL; + } + 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!=NULL) +// 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,NULL,(HYAMNMAIL *)&NewMails,NULL); +// 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=NULL; + } + } + else + { + DeleteMIMEQueue(ActualAccount,(HYAMNMAIL)ActualAccount->Mails); + ActualAccount->Mails=NULL; + } +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:ActualAccountMsgsSO-write done\n"); +#endif + MsgsWriteDone(ActualAccount); +#ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\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)0,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!=NULL) + free(DataRX); + DataRX=NULL; + 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!=NULL) + 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,"\n"); +#endif +// WriteAccounts(); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:Decrementing \"using threads\" %x (account %x)\n",ActualAccount->UsingThreads,ActualAccount); +#endif + SCDec(ActualAccount->UsingThreads); + return 0; +} + +void ExtractStat(char *stream,int len,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,"\n"); + #endif + while(WS(finder)) finder++; //jump whitespace + if (1!=sscanf(finder,"%d",&msgnr)) + throw (DWORD)EPOP3_UIDL; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"%d\n",msgnr); + #endif +// for (i=1,queueptr=queue;(queueptr->Next!=NULL) && (iNext,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,"%s\n",queueptr->MailData->Body); + DebugLog(DecodeFile,"\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,"\n"); + #endif + while(WS(finder)) finder++; //jump whitespace + if (1!=sscanf(finder,"%d",&msgnr)) + throw (DWORD)EPOP3_UIDL; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"%d\n",msgnr); + #endif +// for (i=1,queueptr=queue;(queueptr->Next!=NULL) && (iNext,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,"%s\n",queueptr->ID); + DebugLog(DecodeFile,"\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,"\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,"%d\n",msgnr); + #endif + + for (i=1,queueptr=queue;(queueptr->Next!=NULL) && (iNext,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,"%d\n",queueptr->MailData->Size); + #endif + while(!ENDLINE(finder)) finder++; + } +} + +TCHAR* WINAPI GetErrorString(DWORD Code) +{ + static TCHAR *POP3Errors[]= + { + LPGENT("Memory allocation error."), //memory allocation + LPGENT("Account is about to be stopped."), //stop account + LPGENT("Cannot connect to POP3 server."), + LPGENT("Cannot allocate memory for received data."), + LPGENT("Cannot login to POP3 server."), + LPGENT("Bad user or password."), + LPGENT("Server does not support APOP authorization."), + LPGENT("Error while executing POP3 command."), + LPGENT("Error while executing POP3 command."), + LPGENT("Error while executing POP3 command."), + }; + + static TCHAR *NetlibErrors[]= + { + LPGENT("Cannot connect to server with NetLib."), + LPGENT("Cannot send data."), + LPGENT("Cannot receive data."), + LPGENT("Cannot allocate memory for received data."), + }; + + static TCHAR *SSLErrors[]= + { + LPGENT("OpenSSL not loaded."), + LPGENT("Windows socket 2.0 init failed."), + LPGENT("DNS lookup error."), + LPGENT("Error while creating base socket."), + LPGENT("Error connecting to server with socket."), + LPGENT("Error while creating SSL structure."), + LPGENT("Error connecting socket with SSL."), + LPGENT("Server rejected connection with SSL."), + LPGENT("Cannot write SSL data."), + LPGENT("Cannot read SSL data."), + LPGENT("Cannot allocate memory for received data."), + }; + + TCHAR *ErrorString = new TCHAR[ERRORSTR_MAXLEN]; + POP3_ERRORCODE *ErrorCode=(POP3_ERRORCODE *)(UINT_PTR)Code; + + mir_sntprintf(ErrorString, ERRORSTR_MAXLEN, TranslateT("Error %d-%d-%d-%d:"),ErrorCode->AppError,ErrorCode->POP3Error,ErrorCode->NetError,ErrorCode->SystemError); + if (ErrorCode->POP3Error) + mir_sntprintf(ErrorString, ERRORSTR_MAXLEN, _T("%s\n%s"),ErrorString,TranslateTS(POP3Errors[ErrorCode->POP3Error-1])); + if (ErrorCode->NetError) { + if (ErrorCode->SSL) + mir_sntprintf(ErrorString, ERRORSTR_MAXLEN, _T("%s\n%s"),ErrorString, TranslateTS(SSLErrors[ErrorCode->NetError-1])); + else + mir_sntprintf(ErrorString, ERRORSTR_MAXLEN, _T("%s\n%s"),ErrorString, TranslateTS(NetlibErrors[ErrorCode->NetError-4])); + } + + return ErrorString; +} + +void WINAPI DeleteErrorString(LPVOID String) +{ + delete (char *)String; +} diff --git a/protocols/YAMN/proto/pop3/pop3comm.h b/protocols/YAMN/proto/pop3/pop3comm.h new file mode 100644 index 0000000000..c7eb01b5a1 --- /dev/null +++ b/protocols/YAMN/proto/pop3/pop3comm.h @@ -0,0 +1,97 @@ +#ifndef __POP3COMM_H +#define __POP3COMM_H + +#include +#include "pop3.h" + +#include "m_protoplugin.h" +//We can use synchro.h because this is internal plugin. If you use external plugin, +//and you want to use SO for your plugin, you can use YAMN's SO. +//All you need is to include synchro.h and use YAMN's exported synchronization functions. +#include "m_synchro.h" + +//For mail exported functions defintions +#include "m_mails.h" + +#include "../../debug.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/proto/pop3/pop3opt.cpp b/protocols/YAMN/proto/pop3/pop3opt.cpp new file mode 100644 index 0000000000..bcbf78e380 --- /dev/null +++ b/protocols/YAMN/proto/pop3/pop3opt.cpp @@ -0,0 +1,1556 @@ +/* + * This code implements POP3 options window handling + * + * (c) majvan 2002-2003 +*/ + +#include "../../yamn.h" +#include "../../main.h" +#include "pop3comm.h" +#include "pop3opt.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,DBGetContactSettingByte(NULL,YAMN_DBMODULE,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,DBGetContactSettingByte(NULL, YAMN_DBMODULE, YAMN_SHOWMAINMENU, 1)); + CheckDlgButton(hDlg,IDC_YAMNASPROTO,DBGetContactSettingByte(NULL, YAMN_DBMODULE, YAMN_SHOWASPROTO, 1)); + CheckDlgButton(hDlg,IDC_CLOSEONDELETE,DBGetContactSettingByte(NULL, YAMN_DBMODULE, YAMN_CLOSEDELETE, 0)); + 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: + DBWriteContactSettingByte(NULL, YAMN_DBMODULE, YAMN_SHOWASPROTO, IsDlgButtonChecked(hDlg,IDC_YAMNASPROTO)); + DBWriteContactSettingByte(NULL, YAMN_DBMODULE, YAMN_SHOWMAINMENU, IsDlgButtonChecked(hDlg,IDC_MAINMENU)); + DBWriteContactSettingByte(NULL, YAMN_DBMODULE, YAMN_CLOSEDELETE, IsDlgButtonChecked(hDlg,IDC_CLOSEONDELETE)); + DBWriteContactSettingByte(NULL, YAMN_DBMODULE, 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; + DBWriteContactSettingByte(NULL,YAMN_DBMODULE,YAMN_DBTIMEOPTIONS,optDateTime); + } + } + break; + } + + return FALSE; +} + +INT_PTR CALLBACK DlgProcPluginOpt(HWND hDlg,UINT msg,WPARAM wParam,LPARAM 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,(LPARAM)0); + EnterCriticalSection(&PluginRegCS); + for (PParser=FirstProtoPlugin;PParser!=NULL;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 == NULL ? "" : PParser->Plugin->PluginInfo->Description); + SetDlgItemTextA(hDlg,IDC_STCOPY,PParser->Plugin->PluginInfo->Copyright == NULL ? "" : PParser->Plugin->PluginInfo->Copyright); + SetDlgItemTextA(hDlg,IDC_STMAIL,PParser->Plugin->PluginInfo->Email == NULL ? "" : PParser->Plugin->PluginInfo->Email); + SetDlgItemTextA(hDlg,IDC_STWWW,PParser->Plugin->PluginInfo->WWW == NULL ? "" : PParser->Plugin->PluginInfo->WWW); + break; + } + for (FParser=FirstFilterPlugin;FParser!=NULL;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 == NULL ? "" : FParser->Plugin->PluginInfo->Description); + SetDlgItemTextA(hDlg,IDC_STCOPY,FParser->Plugin->PluginInfo->Copyright == NULL ? "" : FParser->Plugin->PluginInfo->Copyright); + SetDlgItemTextA(hDlg,IDC_STMAIL,FParser->Plugin->PluginInfo->Email == NULL ? "" : FParser->Plugin->PluginInfo->Email); + SetDlgItemTextA(hDlg,IDC_STWWW,FParser->Plugin->PluginInfo->WWW == NULL ? "" : FParser->Plugin->PluginInfo->WWW); + break; + } + LeaveCriticalSection(&PluginRegCS); + } + break; + case IDC_STWWW: + { + char str[1024]; + GetDlgItemTextA(hDlg,IDC_STWWW,str,SIZEOF(str)); + CallService(MS_UTILS_OPENURL,1,(LPARAM)str); + break; + } + + } + break; + } + case WM_SHOWWINDOW: + if (TRUE==(BOOL)wParam) { + PYAMN_PROTOPLUGINQUEUE PParser; + PYAMN_FILTERPLUGINQUEUE FParser; + int index; + + EnterCriticalSection(&PluginRegCS); + for (PParser = FirstProtoPlugin; PParser != NULL; PParser = PParser->Next) { + index = SendDlgItemMessageA(hDlg,IDC_COMBOPLUGINS,CB_ADDSTRING,0,(LPARAM)PParser->Plugin->PluginInfo->Name); + index = SendDlgItemMessage(hDlg,IDC_COMBOPLUGINS,CB_SETITEMDATA,(WPARAM)index,(LPARAM)PParser->Plugin); + } + for (FParser = FirstFilterPlugin; FParser != NULL; FParser = FParser->Next) { + index = SendDlgItemMessageA(hDlg,IDC_COMBOPLUGINS,CB_ADDSTRING,0,(LPARAM)FParser->Plugin->PluginInfo->Name); + index = SendDlgItemMessage(hDlg,IDC_COMBOPLUGINS,CB_SETITEMDATA,(WPARAM)index,(LPARAM)FParser->Plugin); + } + + LeaveCriticalSection(&PluginRegCS); + SendDlgItemMessage(hDlg,IDC_COMBOPLUGINS,CB_SETCURSEL,(WPARAM)0,(LPARAM)0); + SendMessage(hDlg,WM_COMMAND,MAKELONG(IDC_COMBOPLUGINS,CBN_SELCHANGE),(LPARAM)NULL); + break; + } + else { //delete all items in combobox + int cbn=SendDlgItemMessage(hDlg,IDC_COMBOPLUGINS,CB_GETCOUNT,(WPARAM)0,(LPARAM)0); + for (int i=0;iStatusFlags & 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) + { + TCHAR 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 ((iCP)) + { + SendMessage(GetDlgItem(hDlg,IDC_COMBOCP),CB_SETCURSEL,(WPARAM)i,(LPARAM)0); + break; + } + if (i==CPLENSUPP) + SendMessage(GetDlgItem(hDlg,IDC_COMBOCP),CB_SETCURSEL,(WPARAM)CPDEFINDEX,(LPARAM)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,(LPARAM)NULL); + DlgSetItemText(hDlg,(WPARAM)IDC_EDITNAME,(LPARAM)NULL); + DlgSetItemText(hDlg,(WPARAM)IDC_EDITLOGIN,(LPARAM)NULL); + DlgSetItemText(hDlg,(WPARAM)IDC_EDITPASS,(LPARAM)NULL); + DlgSetItemText(hDlg,(WPARAM)IDC_EDITAPP,(LPARAM)NULL); + DlgSetItemText(hDlg,(WPARAM)IDC_EDITAPPPARAM,(LPARAM)NULL); + DlgSetItemText(hDlg,(WPARAM)IDC_STTIMELEFT,(LPARAM)NULL); + 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); + SendMessage(GetDlgItem(hDlg,IDC_COMBOCP),CB_SETCURSEL,(WPARAM)CPDEFINDEX,(LPARAM)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 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 == NULL) + SetDlgItemTextA(hDlg, wParam, ""); + else + SetDlgItemTextA(hDlg, wParam, str); + return TRUE; +} + +BOOL DlgSetItemTextW(HWND hDlg,WPARAM wParam,const WCHAR* str) +{ + if (str == NULL) + SetDlgItemTextW(hDlg, wParam, L""); + else + SetDlgItemTextW(hDlg, wParam, str); + return TRUE; +} + +BOOL CALLBACK DlgProcPOP3AccStatusOpt(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam) +{ + static HPOP3ACCOUNT ActualAccount; + switch(msg) + { + case WM_INITDIALOG: + { + ActualAccount=(HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME,(WPARAM)POP3Plugin,(LPARAM)DlgInput); + if (ActualAccount != NULL) + { + DlgShowAccountStatus(hDlg,(WPARAM)M_SHOWACTUAL,(LPARAM)ActualAccount); + DlgEnableAccountStatus(hDlg,(WPARAM)TRUE,(LPARAM)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; + break; + } + case WM_COMMAND: + { + + WORD wNotifyCode = HIWORD(wParam); + 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,(WPARAM)0,(LPARAM)0); + EndDialog(hDlg,0); + DestroyWindow(hDlg); + break; + + case IDCANCEL: + EndDialog(hDlg,0); + DestroyWindow(hDlg); + break; + + default: + break; + } + } + default: + 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,(WPARAM)FALSE,(LPARAM)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!=NULL;ActualAccount=(HPOP3ACCOUNT)ActualAccount->Next) + if (ActualAccount->Name != NULL) + 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 = lstrlen(info.CodePageName+7); + info.CodePageName[len+6]=0; + SendDlgItemMessage(hDlg,IDC_COMBOCP,CB_ADDSTRING,0,(LPARAM)(info.CodePageName+7)); + } + + SendMessage(GetDlgItem(hDlg,IDC_COMBOCP),CB_SETCURSEL,(WPARAM)CPDEFINDEX,(LPARAM)0); + ActualAccount=NULL; + 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,(LPARAM)0); + } + else WindowList_Add(pYAMNVar->MessageWnds,hDlg,NULL); + return TRUE; + + case WM_YAMN_CHANGESTATUS: + if ((HPOP3ACCOUNT)wParam == ActualAccount) { + TCHAR 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) { + TCHAR Text[256]; + mir_sntprintf(Text,SIZEOF(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=NULL; + DlgSetItemText(hDlg,(WPARAM)IDC_STTIMELEFT,(LPARAM)NULL); + + if (GetDlgItemTextA(hDlg,IDC_COMBOACCOUNT,DlgInput,sizeof(DlgInput))) + DlgEnableAccount(hDlg,(WPARAM)TRUE,(LPARAM)FALSE); + else + DlgEnableAccount(hDlg,(WPARAM)FALSE,(LPARAM)FALSE); + break; + + case CBN_KILLFOCUS: + GetDlgItemTextA(hDlg,IDC_COMBOACCOUNT,DlgInput,sizeof(DlgInput)); + if (NULL==(ActualAccount=(HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME,(WPARAM)POP3Plugin,(LPARAM)DlgInput))) { + DlgSetItemText(hDlg,(WPARAM)IDC_STTIMELEFT,(LPARAM)NULL); + EnableWindow(GetDlgItem(hDlg,IDC_BTNDEL),FALSE); + if (lstrlenA(DlgInput)) + DlgEnableAccount(hDlg,(WPARAM)TRUE,(LPARAM)TRUE); + else + DlgEnableAccount(hDlg,(WPARAM)FALSE,(LPARAM)FALSE); + } + else { + DlgShowAccount(hDlg,(WPARAM)M_SHOWACTUAL,(LPARAM)ActualAccount); + DlgEnableAccount(hDlg,(WPARAM)TRUE,(LPARAM)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) || (NULL==(ActualAccount=(HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME,(WPARAM)POP3Plugin,(LPARAM)DlgInput)))) { + DlgSetItemText(hDlg,(WPARAM)IDC_STTIMELEFT,(LPARAM)NULL); + EnableWindow(GetDlgItem(hDlg,IDC_BTNDEL),FALSE); + } + else { + DlgShowAccount(hDlg,(WPARAM)M_SHOWACTUAL,(LPARAM)ActualAccount); + DlgEnableAccount(hDlg,(WPARAM)TRUE,(LPARAM)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(pYAMNVar->hInst,MAKEINTRESOURCEW(IDD_CHOOSESTATUSMODES),hDlg,(DLGPROC)DlgProcPOP3AccStatusOpt,(LPARAM)NULL); + break; + + case IDC_BTNADD: + DlgSetItemText(hDlg,(WPARAM)IDC_STTIMELEFT,(LPARAM)NULL); + DlgShowAccount(hDlg,(WPARAM)M_SHOWDEFAULT,0); + DlgEnableAccount(hDlg,(WPARAM)TRUE,(LPARAM)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: + { + TCHAR filter[MAX_PATH]; + mir_sntprintf(filter, SIZEOF(filter), _T("%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 TCHAR[MAX_PATH]; + OFNStruct.lpstrFile[0]=(TCHAR)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,_T("Dialog box error"),_T("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,sizeof(DlgInput)); + EnableWindow(GetDlgItem(hDlg,IDC_BTNDEL),FALSE); + if ((CB_ERR==(Result=SendDlgItemMessage(hDlg,IDC_COMBOACCOUNT,CB_GETCURSEL,0,0))) + || (NULL==(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) + CallService(MS_DB_CONTACT_DELETE,(WPARAM)(HANDLE) ActualAccount->hContact, 0); + + 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,(LPARAM)NULL); + DlgEnableAccount(hDlg,(WPARAM)FALSE,0); + DlgShowAccount(hDlg,(WPARAM)M_SHOWDEFAULT,0); + break; + + case IDC_BTNRESET: + if (ActualAccount != NULL) + 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, sizeof(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, sizeof(Text)); + if (CheckApp && !(Length = strlen(Text))) { + MessageBox(hDlg,TranslateT("Please select application to run"),TranslateT("Input error"),MB_OK); + break; + } + + GetDlgItemTextA(hDlg, IDC_COMBOACCOUNT, Text, sizeof(Text)); + if ( !( Length = strlen(Text))) { + GetDlgItemTextA(hDlg,IDC_EDITNAME, Text, sizeof(Text)); + if ( !(Length = strlen( Text ))) + break; + } + + DlgSetItemTextT(hDlg, IDC_STTIMELEFT, TranslateT("Please wait while no account is in use.")); + + if (NULL==(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 (NULL==(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, sizeof(Text)); + if ( !(Length = strlen( Text ))) + break; + if (NULL != ActualAccount->Name) + delete[] ActualAccount->Name; + ActualAccount->Name = new char[ strlen(Text)+1]; + strcpy(ActualAccount->Name,Text); + + GetDlgItemTextA(hDlg,IDC_EDITSERVER,Text,sizeof(Text)); + if (NULL!=ActualAccount->Server->Name) + delete[] ActualAccount->Server->Name; + ActualAccount->Server->Name=new char[ strlen(Text)+1]; + strcpy(ActualAccount->Server->Name,Text); + + GetDlgItemTextA(hDlg,IDC_EDITLOGIN,Text,sizeof(Text)); + if (NULL!=ActualAccount->Server->Login) + delete[] ActualAccount->Server->Login; + ActualAccount->Server->Login=new char[ strlen(Text)+1]; + strcpy(ActualAccount->Server->Login,Text); + + GetDlgItemTextA(hDlg,IDC_EDITPASS,Text,sizeof(Text)); + if (NULL!=ActualAccount->Server->Passwd) + delete[] ActualAccount->Server->Passwd; + ActualAccount->Server->Passwd=new char[ strlen(Text)+1]; + strcpy(ActualAccount->Server->Passwd,Text); + + GetDlgItemTextW(hDlg,IDC_EDITAPP,TextW,SIZEOF(TextW)); + if (NULL!=ActualAccount->NewMailN.App) + delete[] ActualAccount->NewMailN.App; + ActualAccount->NewMailN.App=new WCHAR[wcslen(TextW)+1]; + wcscpy(ActualAccount->NewMailN.App,TextW); + + GetDlgItemTextW(hDlg,IDC_EDITAPPPARAM,TextW,SIZEOF(TextW)); + if (NULL!=ActualAccount->NewMailN.AppParam) + delete[] ActualAccount->NewMailN.AppParam; + ActualAccount->NewMailN.AppParam=new WCHAR[wcslen(TextW)+1]; + wcscpy(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,(LPARAM)NULL); + + index = SendDlgItemMessage(hDlg,IDC_COMBOACCOUNT,CB_GETCURSEL,(WPARAM)0,(LPARAM)0); + + HPOP3ACCOUNT temp = ActualAccount; + + SendDlgItemMessage(hDlg,IDC_COMBOACCOUNT,CB_RESETCONTENT,0,(LPARAM)0); + if (POP3Plugin->FirstAccount!=NULL) + for (ActualAccount=(HPOP3ACCOUNT)POP3Plugin->FirstAccount;ActualAccount!=NULL;ActualAccount=(HPOP3ACCOUNT)ActualAccount->Next) + if (ActualAccount->Name!=NULL) + 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,(WPARAM)FALSE,(LPARAM)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!=NULL) + for (ActualAccount=(HPOP3ACCOUNT)POP3Plugin->FirstAccount;ActualAccount!=NULL;ActualAccount=(HPOP3ACCOUNT)ActualAccount->Next) + if (ActualAccount->Name!=NULL) + 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=NULL; + + + 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,(LPARAM)0); + } + else + { + WindowList_Add(pYAMNVar->MessageWnds,hDlg,NULL); + + int index = SendDlgItemMessage(hDlg,IDC_COMBOACCOUNT,CB_GETCURSEL,(WPARAM)0,(LPARAM)0); + HPOP3ACCOUNT temp = ActualAccount; + SendDlgItemMessage(hDlg,IDC_COMBOACCOUNT,CB_RESETCONTENT,0,(LPARAM)0); + + if (POP3Plugin->FirstAccount!=NULL) + for (ActualAccount=(HPOP3ACCOUNT)POP3Plugin->FirstAccount;ActualAccount!=NULL;ActualAccount=(HPOP3ACCOUNT)ActualAccount->Next) + if (ActualAccount->Name!=NULL) + SendDlgItemMessageA(hDlg,IDC_COMBOACCOUNT,CB_ADDSTRING,0,(LPARAM)ActualAccount->Name); + + ActualAccount = temp; + + if (ActualAccount != NULL) + { + 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,(WPARAM)TRUE,(LPARAM)FALSE); + } + else + { + DlgShowAccountPopup(hDlg,(WPARAM)M_SHOWDEFAULT,0); + DlgEnableAccountPopup(hDlg,(WPARAM)FALSE,(LPARAM)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,sizeof(DlgInput)); + if (NULL==(ActualAccount=(HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME,(WPARAM)POP3Plugin,(LPARAM)DlgInput))) + { + DlgSetItemText(hDlg,(WPARAM)IDC_STTIMELEFT,(LPARAM)NULL); + if (lstrlenA(DlgInput)) + DlgEnableAccountPopup(hDlg,(WPARAM)TRUE,(LPARAM)TRUE); + else + DlgEnableAccountPopup(hDlg,(WPARAM)FALSE,(LPARAM)FALSE); + } + else + { + DlgShowAccount(hDlg,(WPARAM)M_SHOWACTUAL,(LPARAM)ActualAccount); + DlgShowAccountColors(hDlg,0,(LPARAM)ActualAccount); + DlgEnableAccountPopup(hDlg,(WPARAM)TRUE,(LPARAM)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) || (NULL==(ActualAccount=(HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME,(WPARAM)POP3Plugin,(LPARAM)DlgInput)))) + { + DlgSetItemText(hDlg,(WPARAM)IDC_STTIMELEFT,(LPARAM)NULL); + } + else + { + DlgShowAccount(hDlg,(WPARAM)M_SHOWACTUAL,(LPARAM)ActualAccount); + DlgShowAccountColors(hDlg,0,(LPARAM)ActualAccount); + DlgEnableAccountPopup(hDlg,(WPARAM)TRUE,(LPARAM)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: + { + POPUPDATAT Tester; + POPUPDATAT TesterF; + POPUPDATAT 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); + + ZeroMemory(&Tester,sizeof(Tester)); + ZeroMemory(&TesterF,sizeof(TesterF)); + ZeroMemory(&TesterF,sizeof(TesterN)); + Tester.lchContact=NULL; + TesterF.lchContact=NULL; + TesterN.lchContact=NULL; + Tester.lchIcon=g_LoadIconEx(2); + TesterF.lchIcon=g_LoadIconEx(3); + TesterN.lchIcon=g_LoadIconEx(1); + + lstrcpy(Tester.lptzContactName,TranslateT("Account Test")); + lstrcpy(TesterF.lptzContactName,TranslateT("Account Test (failed)")); + lstrcpy(TesterN.lptzContactName,TranslateT("Account Test")); + lstrcpy(Tester.lptzText,TranslateT("You have N new mail messages")); + lstrcpy(TesterF.lptzText,TranslateT("Connection failed message")); + lstrcpy(TesterN.lptzText,TranslateT("No new mail message")); + 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=(WNDPROC)NULL; + TesterF.PluginWindowProc=(WNDPROC)NULL; + TesterN.PluginWindowProc=(WNDPROC)NULL; + Tester.PluginData=NULL; + TesterF.PluginData=NULL; + TesterN.PluginData=NULL; + + if (IsDlgButtonChecked(hDlg,IDC_CHECKPOP)==BST_CHECKED) + CallService(MS_POPUP_ADDPOPUP,(WPARAM)&Tester,0); + if (IsDlgButtonChecked(hDlg,IDC_CHECKFPOP)==BST_CHECKED) + CallService(MS_POPUP_ADDPOPUP,(WPARAM)&TesterF,0); + if (IsDlgButtonChecked(hDlg,IDC_CHECKNPOP)==BST_CHECKED) + CallService(MS_POPUP_ADDPOPUP,(WPARAM)&TesterN,0); + 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: + { + TCHAR Text[MAX_PATH]; + BOOL Translated,NewAcc=FALSE,CheckPopup,CheckPopupW; + BOOL CheckNPopup,CheckNPopupW,CheckFPopup,CheckFPopupW; + BOOL CheckPopN; + UINT Time,TimeN,TimeF; + + if (GetDlgItemText(hDlg,IDC_COMBOACCOUNT,Text,sizeof(Text)/sizeof(TCHAR))) + { + 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); + +// if (0==WritePOP3Accounts()) +// Beep(500,100); + WritePOP3Accounts(); + RefreshContact(); + return TRUE; + } + } + break; + } + break; + } + break; + } + if (Changed) + SendMessage(GetParent(hDlg),PSM_CHANGED,0,0); + return FALSE; +} + diff --git a/protocols/YAMN/proto/pop3/pop3opt.h b/protocols/YAMN/proto/pop3/pop3opt.h new file mode 100644 index 0000000000..c828c221e0 --- /dev/null +++ b/protocols/YAMN/proto/pop3/pop3opt.h @@ -0,0 +1,42 @@ +#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 +BOOL 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*); + +#if defined( _UNICODE ) + #define DlgSetItemTextT DlgSetItemTextW +#else + #define DlgSetItemTextT DlgSetItemText +#endif + +#endif -- cgit v1.2.3