266 lines
7.3 KiB
C++
266 lines
7.3 KiB
C++
#include <pop/popclnt.hpp>
|
|
#include <socket/hostent.hpp>
|
|
#include <socket/servent.hpp>
|
|
|
|
POPClient::POPClient(void)
|
|
: mSpace(" "), mIsLoggedIn(FALSE)
|
|
{
|
|
createCmds();
|
|
createStats();
|
|
}
|
|
|
|
POPClient::~POPClient()
|
|
{
|
|
}
|
|
|
|
BOOL POPClient::open(const String &hostName)
|
|
{
|
|
HostEnt hostEntry;
|
|
ServEnt serverEntry;
|
|
Block<String> responseLines;
|
|
INETSocketAddress internetSocketAddress;
|
|
|
|
if(hostName.isNull())return FALSE;
|
|
if(mPOPControl.isConnected())mPOPControl.destroy();
|
|
message(String("trying ")+hostName+String("..."));
|
|
if(!mWSASystem.isInitialized()){message("WINSOCK initialization failure.");return FALSE;}
|
|
InternetAddress internetAddress(hostName);
|
|
if(!internetAddress.isZero()){if(!hostEntry.hostByAddress(internetAddress)){return FALSE;}}
|
|
else if(!hostEntry.hostByName(hostName)){return FALSE;}
|
|
if(!internetAddress.isZero()){if(!hostEntry.hostByAddress(internetAddress)){message(String("no DNS entry for ")+hostName);return FALSE;}}
|
|
else if(!hostEntry.hostByName(hostName)){message(String("no DNS entry for ")+hostName);return FALSE;}
|
|
message(String("connect...")+String("'")+hostEntry.hostName()+String("' (")+(String)(hostEntry.addresses())[0]+String(")"));
|
|
internetSocketAddress.internetAddress((hostEntry.addresses())[0]);
|
|
if(serverEntry.serviceByName("pop3","tcp"))
|
|
{
|
|
if(!mPOPControl.create()){message("unable to create socket.");return FALSE;}
|
|
internetSocketAddress.family(PF_INET);
|
|
internetSocketAddress.port(serverEntry.port());
|
|
}
|
|
else
|
|
{
|
|
if(!mPOPControl.create()){message("unable to create socket.");return FALSE;}
|
|
internetSocketAddress.family(PF_INET);
|
|
internetSocketAddress.port(htons(POPPort));
|
|
}
|
|
if(!mPOPControl.connect(internetSocketAddress)){message("unable to connect to pop3 server");return FALSE;}
|
|
mPOPControl.getSocketName(internetSocketAddress);
|
|
if(!mPOPControl.isConnected())return FALSE;
|
|
if(!receive(responseLines)||!isInAckResponse(responseLines))
|
|
{
|
|
mPOPControl.destroy();
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL POPClient::quit(void)
|
|
{
|
|
Block<String> responseLines;
|
|
|
|
if(!isConnected())return FALSE;
|
|
isLoggedIn(FALSE);
|
|
if(!putControlData(mPOPCmds[Quit],FALSE))return FALSE;
|
|
receive(responseLines);
|
|
mPOPControl.destroy();
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL POPClient::authenticate(const String &user,const String &password)
|
|
{
|
|
Block<String> responseLines;
|
|
|
|
if(!isConnected())return FALSE;
|
|
if(!putControlData(mPOPCmds[User]+String(" ")+user,FALSE))return FALSE;
|
|
if(!receive(responseLines))return FALSE;
|
|
if(!isInAckResponse(responseLines))return FALSE;
|
|
if(!putControlData(mPOPCmds[Pass]+String(" ")+password,FALSE))return FALSE;
|
|
if(!receive(responseLines))return FALSE;
|
|
isLoggedIn(TRUE);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL POPClient::stat(WORD &messages,WORD &octets)
|
|
{
|
|
Block<String> responseLines;
|
|
String strItem;
|
|
|
|
messages=0;
|
|
octets=0;
|
|
if(!isConnected()||!isLoggedIn())return FALSE;
|
|
if(!putControlData(mPOPCmds[Stat],FALSE))return FALSE;
|
|
if(!receive(responseLines))return FALSE;
|
|
if(!isInAckResponse(responseLines))return FALSE;
|
|
strItem=responseLines[0].betweenString(' ',' ');
|
|
messages=::atoi((char*)strItem);
|
|
strItem=responseLines[0].betweenString(' ',0);
|
|
strItem=strItem.betweenString(' ',0);
|
|
octets=::atoi((char*)strItem);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL POPClient::retrieve(WORD msgNum,Block<String> &messageLines)
|
|
{
|
|
Block<String> responseLines;
|
|
String strMsg;
|
|
|
|
messageLines.remove();
|
|
if(!isConnected()||!isLoggedIn())return FALSE;
|
|
::sprintf(strMsg,"%d",msgNum);
|
|
if(!putControlData(mPOPCmds[Retr]+String(" ")+strMsg,FALSE))return FALSE;
|
|
if(!receive(responseLines))return FALSE;
|
|
if(!isInAckResponse(responseLines))return FALSE;
|
|
receiveLines(messageLines);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL POPClient::dele(WORD msgNum)
|
|
{
|
|
Block<String> responseLines;
|
|
String strMsg;
|
|
if(!isConnected()||!isLoggedIn())return FALSE;
|
|
::sprintf(strMsg,"%d",msgNum);
|
|
if(!putControlData(mPOPCmds[Dele]+String(" ")+strMsg,FALSE))return FALSE;
|
|
if(!receive(responseLines))return FALSE;
|
|
if(!isInAckResponse(responseLines))return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL POPClient::noop(void)
|
|
{
|
|
Block<String> responseLines;
|
|
|
|
if(!isConnected()||!isLoggedIn())return FALSE;
|
|
if(!putControlData(mPOPCmds[Noop],FALSE))return FALSE;
|
|
if(!receive(responseLines))return FALSE;
|
|
if(!isInAckResponse(responseLines))return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL POPClient::rset(void)
|
|
{
|
|
Block<String> responseLines;
|
|
|
|
if(!isConnected()||!isLoggedIn())return FALSE;
|
|
if(!putControlData(mPOPCmds[Rset],FALSE))return FALSE;
|
|
if(!receive(responseLines))return FALSE;
|
|
if(!isInAckResponse(responseLines))return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL POPClient::top(Block<String> &msgLines,WORD msgNum,WORD lineCount)
|
|
{
|
|
Block<String> responseLines;
|
|
String strMsg;
|
|
|
|
if(!isConnected()||!isLoggedIn())return FALSE;
|
|
::sprintf(strMsg,"%d %d",msgNum,lineCount);
|
|
if(!putControlData(mPOPCmds[Top]+String(" ")+strMsg,FALSE))return FALSE;
|
|
if(!receive(responseLines))return FALSE;
|
|
if(!isInAckResponse(responseLines))return FALSE;
|
|
if(!receiveLines(msgLines))return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
void POPClient::createStats(void)
|
|
{
|
|
mPOPStatus.insert(&String("+OK"));
|
|
mPOPStatus.insert(&String("-ERR"));
|
|
}
|
|
|
|
void POPClient::createCmds(void)
|
|
{
|
|
mPOPCmds.remove();
|
|
mPOPCmds.insert(&String("QUIT"));
|
|
mPOPCmds.insert(&String("USER"));
|
|
mPOPCmds.insert(&String("PASS"));
|
|
mPOPCmds.insert(&String("STAT"));
|
|
mPOPCmds.insert(&String("RETR"));
|
|
mPOPCmds.insert(&String("RSET"));
|
|
mPOPCmds.insert(&String("DELE"));
|
|
mPOPCmds.insert(&String("NOOP"));
|
|
mPOPCmds.insert(&String("TOP"));
|
|
}
|
|
|
|
WORD POPClient::putControlData(const String &stringData,WORD waitForResponse)
|
|
{
|
|
if(!mPOPControl.isConnected())return FALSE;
|
|
if(!mPOPControl.send(stringData))
|
|
{
|
|
mPOPControl.destroy();
|
|
String errorString(String("error sending '")+stringData+String("' to POP server."));
|
|
message(errorString);
|
|
errorString+="\n";
|
|
::OutputDebugString(errorString);
|
|
return FALSE;
|
|
}
|
|
if(waitForResponse&&!getControlData())
|
|
{
|
|
mPOPControl.destroy();
|
|
String errorString(String("error reading result of '")+stringData+String("' command from NNTP server."));
|
|
message(errorString);
|
|
errorString+="\n";
|
|
::OutputDebugString(errorString);
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
WORD POPClient::getControlData(void)
|
|
{
|
|
Block<String> responseStrings;
|
|
mPOPControl.receive(responseStrings);
|
|
return responseStrings.size();
|
|
}
|
|
|
|
BOOL POPClient::isInAckResponse(Block<String> &responseLines)
|
|
{
|
|
if(!responseLines.size())return FALSE;
|
|
if(responseLines[0].substr(0,2)==mPOPStatus[Ok])return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL POPClient::isInNakResponse(Block<String> &responseLines)
|
|
{
|
|
if(!responseLines.size())return FALSE;
|
|
if(responseLines[0].substr(0,3)==mPOPStatus[Error])return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL POPClient::receive(Block<String> &responseLines)
|
|
{
|
|
if(!mPOPControl.receive(responseLines))return FALSE;
|
|
// message(responseLines);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL POPClient::receiveLines(Block<String> &receiveStrings)
|
|
{
|
|
String stringData;
|
|
String seriesItem;
|
|
|
|
receiveStrings.remove();
|
|
while(TRUE)
|
|
{
|
|
if(!mPOPControl.receive(stringData))break;
|
|
if(stringData==String("."))break;
|
|
if(stringData==String(".."))stringData=".";
|
|
receiveStrings.insert(&stringData);
|
|
if(!isConnected())break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
// virtuals
|
|
|
|
void POPClient::message(const String &messageString)
|
|
{
|
|
::OutputDebugString(messageString+String("\n"));
|
|
}
|
|
|
|
void POPClient::message(Block<String> &messageStrings)
|
|
{
|
|
for(int itemIndex=0;itemIndex<messageStrings.size();itemIndex++)
|
|
::OutputDebugString(messageStrings[itemIndex]+String("\n"));
|
|
}
|