add support for POP3 CAPA command, patch by ch.ey@gmx.net, r/sr=bienvenu 219282
git-svn-id: svn://10.0.0.236/trunk@147003 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -944,8 +944,6 @@ nsPop3Protocol::WaitForResponse(nsIInputStream* inputStream, PRUint32 length)
|
||||
{
|
||||
if(!PL_strncasecmp(line, "+OK", 3))
|
||||
m_commandResponse = line + 4;
|
||||
// else if(PL_strncasecmp(m_commandResponse.get(), "Invalid login", 13))
|
||||
// m_commandResponse = "+";
|
||||
else // challenge answer to AUTH CRAM-MD5 and LOGIN username/password
|
||||
m_commandResponse = line + 2;
|
||||
}
|
||||
@@ -960,11 +958,19 @@ nsPop3Protocol::WaitForResponse(nsIInputStream* inputStream, PRUint32 length)
|
||||
else
|
||||
m_commandResponse = line;
|
||||
|
||||
// search for the response codes (RFC 2449, chapter 8)
|
||||
if(m_commandResponse.Find("[LOGIN-DELAY", PR_TRUE) >= 0 ||
|
||||
m_commandResponse.Find("[IN-USE", PR_TRUE) >= 0)
|
||||
// search for the response codes (RFC 2449, chapter 8 and RFC 3206)
|
||||
if(TestCapFlag(POP3_HAS_RESP_CODES | POP3_HAS_AUTH_RESP_CODE))
|
||||
{
|
||||
// code for authentication failure due to the user's credentials
|
||||
if(m_commandResponse.Find("[AUTH", PR_TRUE) >= 0)
|
||||
SetFlag(POP3_AUTH_FAILURE);
|
||||
|
||||
// codes for failures due to other reasons
|
||||
if(m_commandResponse.Find("[LOGIN-DELAY", PR_TRUE) >= 0 ||
|
||||
m_commandResponse.Find("[IN-USE", PR_TRUE) >= 0 ||
|
||||
m_commandResponse.Find("[SYS", PR_TRUE) >= 0)
|
||||
SetFlag(POP3_STOPLOGIN);
|
||||
|
||||
// remove the codes from the response string presented to the user
|
||||
PRInt32 i = m_commandResponse.FindChar(']');
|
||||
if(i >= 0)
|
||||
@@ -1088,7 +1094,7 @@ PRInt32 nsPop3Protocol::AuthResponse(nsIInputStream* inputStream,
|
||||
*/
|
||||
m_pop3ConData->command_succeeded = PR_TRUE;
|
||||
m_pop3Server->SetPop3CapabilityFlags(m_pop3ConData->capability_flags);
|
||||
m_pop3ConData->next_state = POP3_PROCESS_AUTH;
|
||||
m_pop3ConData->next_state = POP3_SEND_CAPA;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1107,7 +1113,7 @@ PRInt32 nsPop3Protocol::AuthResponse(nsIInputStream* inputStream,
|
||||
if (!PL_strcmp(line, "."))
|
||||
{
|
||||
// now that we've read all the AUTH responses, go for it
|
||||
m_pop3ConData->next_state = POP3_PROCESS_AUTH;
|
||||
m_pop3ConData->next_state = POP3_SEND_CAPA;
|
||||
m_pop3ConData->pause_for_read = PR_FALSE; /* don't pause */
|
||||
}
|
||||
else
|
||||
@@ -1116,9 +1122,11 @@ PRInt32 nsPop3Protocol::AuthResponse(nsIInputStream* inputStream,
|
||||
nsCOMPtr<nsISignatureVerifier> verifier = do_GetService(SIGNATURE_VERIFIER_CONTRACTID, &rv);
|
||||
// this checks if psm is installed...
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
SetCapFlag(POP3_HAS_AUTH_CRAM_MD5);
|
||||
m_pop3Server->SetPop3CapabilityFlags(m_pop3ConData->capability_flags);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (!PL_strcasecmp (line, "PLAIN"))
|
||||
{
|
||||
@@ -1136,6 +1144,73 @@ PRInt32 nsPop3Protocol::AuthResponse(nsIInputStream* inputStream,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* POP3 CAPA extention, see RFC 2449, chapter 5
|
||||
*/
|
||||
|
||||
PRInt32 nsPop3Protocol::SendCapa()
|
||||
{
|
||||
if(!m_pop3ConData->command_succeeded)
|
||||
return(Error(POP3_SERVER_ERROR));
|
||||
|
||||
nsCAutoString command("CAPA" CRLF);
|
||||
|
||||
m_pop3ConData->next_state_after_response = POP3_CAPA_RESPONSE;
|
||||
return SendData(m_url, command.get());
|
||||
}
|
||||
|
||||
PRInt32 nsPop3Protocol::CapaResponse(nsIInputStream* inputStream,
|
||||
PRUint32 length)
|
||||
{
|
||||
char * line;
|
||||
PRUint32 ln = 0;
|
||||
|
||||
if (!m_pop3ConData->command_succeeded)
|
||||
{
|
||||
/* CAPA command not implemented */
|
||||
m_pop3ConData->command_succeeded = PR_TRUE;
|
||||
m_pop3Server->SetPop3CapabilityFlags(m_pop3ConData->capability_flags);
|
||||
m_pop3ConData->next_state = POP3_PROCESS_AUTH;
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRBool pauseForMoreData = PR_FALSE;
|
||||
line = m_lineStreamBuffer->ReadNextLine(inputStream, ln, pauseForMoreData);
|
||||
|
||||
if(pauseForMoreData || !line)
|
||||
{
|
||||
m_pop3ConData->pause_for_read = PR_TRUE; /* pause */
|
||||
PR_Free(line);
|
||||
return(0);
|
||||
}
|
||||
|
||||
PR_LOG(POP3LOGMODULE, PR_LOG_ALWAYS,("RECV: %s", line));
|
||||
|
||||
if (!PL_strcmp(line, "."))
|
||||
{
|
||||
// now that we've read all the CAPA responses, go for it
|
||||
m_pop3ConData->next_state = POP3_PROCESS_AUTH;
|
||||
m_pop3ConData->pause_for_read = PR_FALSE; /* don't pause */
|
||||
}
|
||||
else
|
||||
// see RFC 2449, chapter 6.4
|
||||
if (!PL_strcasecmp(line, "RESP-CODES"))
|
||||
{
|
||||
SetCapFlag(POP3_HAS_RESP_CODES);
|
||||
m_pop3Server->SetPop3CapabilityFlags(m_pop3ConData->capability_flags);
|
||||
}
|
||||
else
|
||||
// see RFC 3206, chapter 6
|
||||
if (!PL_strcasecmp(line, "AUTH-RESP-CODE"))
|
||||
{
|
||||
SetCapFlag(POP3_HAS_AUTH_RESP_CODE);
|
||||
m_pop3Server->SetPop3CapabilityFlags(m_pop3ConData->capability_flags);
|
||||
}
|
||||
|
||||
PR_Free(line);
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRInt32 nsPop3Protocol::ProcessAuth()
|
||||
{
|
||||
if(m_useSecAuth)
|
||||
@@ -1173,9 +1248,10 @@ PRInt32 nsPop3Protocol::AuthFallback()
|
||||
m_pop3ConData->next_state = POP3_SEND_PASSWORD;
|
||||
else
|
||||
{
|
||||
// response code received, login failed
|
||||
// not because of wrong username
|
||||
if(TestFlag(POP3_STOPLOGIN))
|
||||
// response code received,
|
||||
// login failed not because of wrong password
|
||||
if(TestFlag(POP3_STOPLOGIN) ||
|
||||
TestCapFlag(POP3_HAS_AUTH_RESP_CODE) && !TestFlag(POP3_AUTH_FAILURE))
|
||||
return(Error(POP3_USERNAME_FAILURE));
|
||||
|
||||
// If one authentication failed, we're going to
|
||||
@@ -1418,9 +1494,10 @@ PRInt32 nsPop3Protocol::SendStatOrGurl(PRBool sendStat)
|
||||
/* check password response */
|
||||
if(!m_pop3ConData->command_succeeded)
|
||||
{
|
||||
// response code received, login failed
|
||||
// not because of wrong password
|
||||
if(TestFlag(POP3_STOPLOGIN))
|
||||
// response code received,
|
||||
// login failed not because of wrong password
|
||||
if(TestFlag(POP3_STOPLOGIN) ||
|
||||
TestCapFlag(POP3_HAS_AUTH_RESP_CODE) && !TestFlag(POP3_AUTH_FAILURE))
|
||||
return(Error(POP3_PASSWORD_FAILURE));
|
||||
|
||||
if(!TestCapFlag(POP3_HAS_AUTH_CRAM_MD5) &&
|
||||
@@ -3057,7 +3134,7 @@ nsresult nsPop3Protocol::ProcessProtocolState(nsIURI * url, nsIInputStream * aIn
|
||||
if (TestCapFlag(POP3_AUTH_MECH_UNDEFINED))
|
||||
m_pop3ConData->next_state = POP3_SEND_AUTH;
|
||||
else
|
||||
m_pop3ConData->next_state = POP3_PROCESS_AUTH;
|
||||
m_pop3ConData->next_state = POP3_SEND_CAPA;
|
||||
}
|
||||
else
|
||||
m_pop3ConData->next_state = POP3_SEND_USERNAME;;
|
||||
@@ -3098,7 +3175,7 @@ nsresult nsPop3Protocol::ProcessProtocolState(nsIURI * url, nsIInputStream * aIn
|
||||
if (TestCapFlag(POP3_AUTH_MECH_UNDEFINED))
|
||||
m_pop3ConData->next_state = POP3_SEND_AUTH;
|
||||
else
|
||||
m_pop3ConData->next_state = POP3_PROCESS_AUTH;
|
||||
m_pop3ConData->next_state = POP3_SEND_CAPA;
|
||||
}
|
||||
else
|
||||
m_pop3ConData->next_state = POP3_SEND_USERNAME;;
|
||||
@@ -3115,6 +3192,14 @@ nsresult nsPop3Protocol::ProcessProtocolState(nsIURI * url, nsIInputStream * aIn
|
||||
status = AuthResponse(aInputStream, aLength);
|
||||
break;
|
||||
|
||||
case POP3_SEND_CAPA:
|
||||
status = SendCapa();
|
||||
break;
|
||||
|
||||
case POP3_CAPA_RESPONSE:
|
||||
status = CapaResponse(aInputStream, aLength);
|
||||
break;
|
||||
|
||||
case POP3_PROCESS_AUTH:
|
||||
status = ProcessAuth();
|
||||
break;
|
||||
|
||||
@@ -103,7 +103,9 @@ enum Pop3CapabilityEnum {
|
||||
POP3_HAS_AUTH_USER = 0x00001000,
|
||||
POP3_HAS_AUTH_CRAM_MD5 = 0x00002000,
|
||||
POP3_HAS_AUTH_APOP = 0x00004000,
|
||||
POP3_HAS_AUTH_PLAIN = 0x00008000
|
||||
POP3_HAS_AUTH_PLAIN = 0x00008000,
|
||||
POP3_HAS_RESP_CODES = 0x00010000,
|
||||
POP3_HAS_AUTH_RESP_CODE = 0x00020000
|
||||
};
|
||||
|
||||
enum Pop3StatesEnum {
|
||||
@@ -145,19 +147,20 @@ enum Pop3StatesEnum {
|
||||
POP3_GET_FAKE_UIDL_TOP, // 28
|
||||
POP3_SEND_AUTH, // 29
|
||||
POP3_AUTH_RESPONSE, // 30
|
||||
POP3_PROCESS_AUTH, // 31
|
||||
POP3_AUTH_FALLBACK, // 32
|
||||
POP3_SEND_CAPA, // 31
|
||||
POP3_CAPA_RESPONSE, // 32
|
||||
POP3_PROCESS_AUTH, // 33
|
||||
POP3_AUTH_FALLBACK, // 34
|
||||
|
||||
POP3_AUTH_LOGIN, // 33
|
||||
POP3_AUTH_LOGIN_RESPONSE, // 34
|
||||
POP3_SEND_XSENDER, // 35
|
||||
POP3_XSENDER_RESPONSE, // 36
|
||||
POP3_SEND_GURL, // 37
|
||||
POP3_AUTH_LOGIN, // 35
|
||||
POP3_AUTH_LOGIN_RESPONSE, // 36
|
||||
POP3_SEND_XSENDER, // 37
|
||||
POP3_XSENDER_RESPONSE, // 38
|
||||
POP3_SEND_GURL, // 39
|
||||
|
||||
POP3_GURL_RESPONSE, // 38
|
||||
POP3_QUIT_RESPONSE,
|
||||
POP3_INTERRUPTED,
|
||||
POP3_STOPLOGIN
|
||||
POP3_GURL_RESPONSE, // 40
|
||||
POP3_QUIT_RESPONSE, // 41
|
||||
POP3_INTERRUPTED // 42
|
||||
};
|
||||
|
||||
|
||||
@@ -260,6 +263,8 @@ typedef struct _Pop3ConData {
|
||||
// commands, etc. I do not intend it to refer to protocol state)
|
||||
#define POP3_PAUSE_FOR_READ 0x00000001 /* should we pause for the next read */
|
||||
#define POP3_PASSWORD_FAILED 0x00000002
|
||||
#define POP3_STOPLOGIN 0x00000004 /* error loging in, so stop here */
|
||||
#define POP3_AUTH_FAILURE 0x00000008 /* extended code said authentication failed */
|
||||
|
||||
|
||||
class nsPop3Protocol : public nsMsgProtocol, public nsMsgLineBuffer
|
||||
@@ -332,6 +337,8 @@ private:
|
||||
PRInt32 Error(PRInt32 err_code);
|
||||
PRInt32 SendAuth();
|
||||
PRInt32 AuthResponse(nsIInputStream* inputStream, PRUint32 length);
|
||||
PRInt32 SendCapa();
|
||||
PRInt32 CapaResponse(nsIInputStream* inputStream, PRUint32 length);
|
||||
PRInt32 ProcessAuth();
|
||||
PRInt32 AuthFallback();
|
||||
PRInt32 AuthLogin();
|
||||
|
||||
Reference in New Issue
Block a user