Files
Work/pop/HOLD/POPCLNT.CPP
2024-08-07 09:16:27 -04:00

264 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.closeSocket();
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.openSocket()){message("unable to create socket.");return FALSE;}
internetSocketAddress.family(PF_INET);
internetSocketAddress.port(serverEntry.port());
}
else
{
if(!mPOPControl.openSocket()){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.closeSocket();
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.closeSocket();
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;
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.closeSocket();
String errorString(String("error sending '")+stringData+String("' to POP server."));
message(errorString);
errorString+="\n";
::OutputDebugString(errorString);
return FALSE;
}
if(waitForResponse&&!getControlData())
{
mPOPControl.closeSocket();
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"));
}