#include "pop3.h"
string m_sErrorTable[10]=
{
"Connect error",
"USER error",
"PASS error",
"STAT error",
"TOP error",
"LIST error",
"UIDL error",
"RETR error",
"DELE error",
"QUIT error"
};
bool CPOP3::DisConnect()
{
if (m_bConnected == false)
{
return true;
}
if(Dialog("QUIT\r\n", "OK", QUIT) == false)
{
return false;
}
close(tcpsock);
m_bConnected = true;
return true;
}
const char *CPOP3::Strstr(const char *strsrc, const char *strtofind, int len)
{
int n=0;
if (strsrc == NULL || strtofind == NULL)
{
return NULL;
}
const char *ptr1 = NULL;
const char *ptr2 = NULL;
while ( *strsrc != 0 && n< len)
{
if (abs(*strsrc - *strtofind) == 32 || (*strsrc - *strtofind)==0)
{
ptr1 = strsrc+1;
ptr2 = strtofind+1;
while ((abs(*ptr1 - *ptr2)==32|| (*ptr1 - *ptr2)==0) && *ptr1 != 0 && *ptr2 != 0)
{
ptr1++;
ptr2++;
}
if (*ptr2 == 0)
{
return strsrc;
}
}
strsrc++;
n++;
}
return NULL;
}
void CPOP3::Trim(char *str)
{
int srclen = strlen(str);
char *ptr1 = str;
char *ptr2 = str + srclen -1;
char *temp = new char[srclen+1];
memset(temp, 0, srclen+1);
while(*ptr1 == ' ')
ptr1++;
while(*ptr2 == ' ')
ptr2--;
int len = int(ptr2-ptr1+1);
memcpy(temp, ptr1, len);
memset(str,0,srclen);
strncpy(str, temp, len);
delete []temp;
}
void CPOP3::TranslateDate(char *str)
{
//Thu, 29 May 2008 10:54:27 +0800
char month[4]="";
//char week[4]="";
int nmonth = 0;
int week = 0;
char day[3]="";
char year[5]="";
char time[9]="";
char timezone[6]="";
//strncpy(week,str,3);
strncpy(day, str+5, 2);
strncpy(month, str+8, 3);
strncpy(year, str+12, 4);
strncpy(time, str+17, 8);
strncpy(timezone, str+26, 5);
int len = strlen(str);
char temp[50]="";
//memset(temp, 0, len);
char monthtable[37]= "JanFebMarAprMayJunJulAugSepOctNovDec";
switch(*str)
{
case 'S':
case 's':
{
if (*(str+1) == 'u' || *(str+1) == 'U')
{
week = 0;
break;
}
if (*(str+1) == 'a' || *(str+1) == 'A')
{
week = 6;
break;
}
}
case 'M':
case 'm':
week =1;
break;
case 'T':
case 't':
{
if (*(str+1) == 'u' || *(str+1) == 'U')
{
week = 2;
break;
}
if (*(str+1) == 'h' || *(str+1) == 'H')
{
week = 4;
break;
}
}
case 'W':
case 'w':
week = 3;
break;
case 'F':
case 'f':
week = 5;
break;
default:
break;
}
const char *ptr = Strstr(monthtable, month, sizeof(monthtable));
int pos = int(ptr-monthtable);
nmonth = pos/3 + 1;
sprintf(temp, "%s-%2d-%s %s %s", year, nmonth, day, time, timezone);
strcpy(str, temp);
}
string CPOP3::GetLastError()
{
return m_sError;
}
CPOP3::CPOP3()
{
m_bConnected = false;
memset(m_recvbuff, 0, RESPBUFF_SIZE);
tcpsock = socket(AF_INET, SOCK_STREAM, 0);
if (tcpsock == INVALID_SOCKET)
{
m_sError = "socket create error";
}
}
CPOP3::~CPOP3()
{
if (tcpsock != INVALID_SOCKET && m_bConnected)
{
close(tcpsock);
}
}
int CPOP3::FindCharInStr(const char *str, char tofind)
{
const char *ptr = str;
if (tofind == '=')return -1;
while (ptr!= NULL && tofind != *ptr)
{
ptr++;
}
if (ptr==NULL)return -1;
int ret = int(ptr-str);
return ret;
}
void CPOP3::Base64Decode(const char *src, char *dst, int srclen, int *dstlen)
{
char *table="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
//int len = strlen(src);
if (srclen%4 != 0)
return;
char buff[4]="";
for(int i=0;i<srclen;i+=4)
{
//memcpy(buff, src+i, 4);
buff[0] = FindCharInStr(table, *(src+i));
if (buff[0]<0)buff[0]=0;
buff[1] = FindCharInStr(table, *(src+i+1));
if (buff[1]<0)buff[1]=0;
buff[2] = FindCharInStr(table, *(src+i+2));
if (buff[2]<0)buff[2]=0;
buff[3] = FindCharInStr(table, *(src+i+3));
if (buff[3]<0)buff[3]=0;
dst[i/4*3+0] = buff[0]<<2 | buff[1]>>4;
dst[i/4*3+1] = buff[1]<<4 | buff[2]>>2;
dst[i/4*3+2] = buff[2]<<6 | buff[3];
}
*dstlen = srclen/4*3;
return;
}
void CPOP3::SetPOP3Server(string servernameorip, unsigned short nport )
{
m_sServerNameorIP = servernameorip;
m_nPort = nport;
}
void CPOP3::SetUserProperty(string user, string passwd)
{
m_sUser = user;
m_sPasswd = passwd;
}
bool CPOP3::Dialog(const char *cmd, const char *resp, int cmdtype)
{
int len = 0;
fd_set rset;
FD_ZERO(&rset);
FD_SET(tcpsock, &rset);
struct timeval tv;
tv.tv_sec = 10;
tv.tv_usec = 0;
int maxfd = tcpsock;
if (cmd != NULL)
{
if ((len = send(tcpsock, cmd, strlen(cmd), 0)) != strlen(cmd))
{
m_sError = "send error";
return false;
}
/* if (strstr(cmd,"LIST"))//
{
Sleep(300);
}*/
}
usleep(100);
if (resp != NULL)
{
if (select(maxfd+1,&rset, NULL, NULL, &tv)==0)
{
m_sError = "recv timeout";
return false;
}
memset(m_recvbuff, 0, RESPBUFF_SIZE);
//len = recv(tcpsock, m_recvbuff, RESPBUFF_SIZE, 0);
if (ReadLine(m_recvbuff, RESPBUFF_SIZE)==false)//ʹ��ReadLine����ճ������
{
m_sError = m_sErrorTable[cmdtype];
return false;
}
if (Strstr(m_recvbuff, resp, RESPBUFF_SIZE))
{
return true;
}
else
{
m_sError = m_sErrorTable[cmdtype];
return false;
}
}
return true;
}
int CPOP3::GetMessageCount()
{
char cmd[10] = "STAT\r\n";
if ((Dialog(cmd, "OK", STAT) == false))
{
return -1;
}
const char *ptr1 = Strstr(m_recvbuff, " ", RESPBUFF_SIZE);
while(*(++ptr1) == ' '); // in case there are more than one space
const char *ptr2 = Strstr(ptr1+1, " ", RESPBUFF_SIZE);
int numlen = int(ptr2 - ptr1);
char numchar[20] = "";
strncpy(numchar, ptr1, numlen);
return atoi(numchar);
}
bool CPOP3::ReadLine(char *line, int size)//receive a line that ended with "\r\n" from the pop3 server
{
int len;
char temp=0;
char pretemp=0;
char *ptr = line;
int count = 0;
while(count<size)
{
len = recv(tcpsock, &temp, 1, 0);
if (len != 1)
{
return false;
}
if (temp=='\n')
{
if (pretemp == '\r')
{
*ptr++ = temp;
*ptr = '\0';
break;
}
}
*ptr++ = temp;
pretemp = temp;
count++;
}
return true;
}
int CPOP3::Recvn(char *recvbuff, unsigned int len)
{
int nleft = len;
int nread = 0;
fd_set rset;
FD_ZERO(&rset);
FD_SET(tcpsock, &rset);
struct timeval tv;
tv.tv_sec = 5;
tv.tv_usec = 0;
int maxfd = tcpsock;
while (nleft > 0)
{
if (select(maxfd+1, &rset, NULL, NULL,&tv) == 0)
{
m_sError = "recv timeout";
return len-nleft;
}
//nread = recv(tcpsock, recvbuff, nleft, MSG_WAITALL);
nread = recv(tcpsock, recvbuff, nleft, 0);
if (nread == 0)
{
return (len-nleft);
}
nleft -= nread;
recvbuff += nread;
}
return len;
}
bool CPOP3::GetMessageSubject(unsigned int nMsg, string &sSubject)
{
char cmd[20] ="";
const char *ptr1 = NULL;
const char *ptr2 = NULL;
int fieldlen = 0;
int head_len = 0;
int len = 0;
sprintf(cmd, "TOP %d 10 \r\n", nMsg);// receive 20 lines
if (Dialog(cmd, "OK", TOP) == false)
{
return false;
}
len = strlen(m_recvbuff);
ptr1 = Strstr(m_recvbuff, " ", len);
if (ptr1==NULL)
{
return false;
}
ptr2= Strstr(ptr1+1, " ", len);
if (ptr2==NULL)
{
return false;
}
int numlen = int(ptr2 - ptr1)-1;
char numchar[20] = "";
strncpy(numchar, ptr1+1, numlen);
head_len = atoi(numchar);
char *msghead = new char[head_len+3];
memset(msghead, 0, head_len+3);
len = Recvn(msghead, head_len+3);//note:the pop3 server will add a three bytes ".\r\n" data to the bytecout's data
//len = recv(tcpsock, msghead, head_len, 0);
ptr1 = Strstr(msghead, "Subject:",len);
if (ptr1==NULL)
{
return false;
}
ptr2 = Strstr(ptr1, "\r\n", len);
if (ptr2==NULL)
{
return false;
}
fieldlen = int(ptr2-ptr1);
char subject[1