diff --git a/mozilla/mailnews/local/src/nsPop3Protocol.cpp b/mozilla/mailnews/local/src/nsPop3Protocol.cpp index 6ccd2c23f09..d9eeed43c9b 100644 --- a/mozilla/mailnews/local/src/nsPop3Protocol.cpp +++ b/mozilla/mailnews/local/src/nsPop3Protocol.cpp @@ -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 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; diff --git a/mozilla/mailnews/local/src/nsPop3Protocol.h b/mozilla/mailnews/local/src/nsPop3Protocol.h index dadc7e5f1f7..4ecfb438721 100644 --- a/mozilla/mailnews/local/src/nsPop3Protocol.h +++ b/mozilla/mailnews/local/src/nsPop3Protocol.h @@ -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();