1
0
mirror of https://github.com/moparisthebest/k-9 synced 2024-11-23 18:02:15 -05:00

Break ImapConnection#open into smaller methods

This commit is contained in:
Jan Berkel 2014-12-19 10:04:53 +01:00
parent 6ed52ac551
commit 2eecb2d2c5
3 changed files with 338 additions and 313 deletions

View File

@ -4,6 +4,7 @@ import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;
import com.fsck.k9.mail.AuthType;
import com.fsck.k9.mail.Authentication;
import com.fsck.k9.mail.AuthenticationFailedException;
import com.fsck.k9.mail.CertificateValidationException;
@ -13,7 +14,6 @@ import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.filter.Base64;
import com.fsck.k9.mail.filter.PeekableInputStream;
import com.fsck.k9.mail.ssl.TrustedSocketFactory;
import com.fsck.k9.mail.store.RemoteStore;
import com.fsck.k9.mail.transport.imap.ImapSettings;
import com.jcraft.jzlib.JZlib;
import com.jcraft.jzlib.ZOutputStream;
@ -44,13 +44,26 @@ import java.util.zip.InflaterInputStream;
import javax.net.ssl.SSLException;
import static com.fsck.k9.mail.ConnectionSecurity.STARTTLS_REQUIRED;
import static com.fsck.k9.mail.K9MailLib.DEBUG_PROTOCOL_IMAP;
import static com.fsck.k9.mail.K9MailLib.LOG_TAG;
import static com.fsck.k9.mail.store.RemoteStore.SOCKET_CONNECT_TIMEOUT;
import static com.fsck.k9.mail.store.RemoteStore.SOCKET_READ_TIMEOUT;
import static com.fsck.k9.mail.store.imap.ImapCommands.CAPABILITY_AUTH_CRAM_MD5;
import static com.fsck.k9.mail.store.imap.ImapCommands.CAPABILITY_AUTH_EXTERNAL;
import static com.fsck.k9.mail.store.imap.ImapCommands.CAPABILITY_AUTH_PLAIN;
import static com.fsck.k9.mail.store.imap.ImapCommands.CAPABILITY_CAPABILITY;
import static com.fsck.k9.mail.store.imap.ImapCommands.CAPABILITY_COMPRESS_DEFLATE;
import static com.fsck.k9.mail.store.imap.ImapCommands.CAPABILITY_LOGINDISABLED;
import static com.fsck.k9.mail.store.imap.ImapCommands.COMMAND_CAPABILITY;
import static com.fsck.k9.mail.store.imap.ImapResponseParser.equalsIgnoreCase;
/**
* A cacheable class that stores the details for a single IMAP connection.
*/
class ImapConnection {
private static final int BUFFER_SIZE = 1024;
private Socket mSocket;
private PeekableInputStream mIn;
@ -82,73 +95,22 @@ class ImapConnection {
return "conn" + hashCode();
}
public void open() throws IOException, MessagingException {
if (isOpen()) {
return;
}
boolean authSuccess = false;
mNextCommandTag = 1;
try {
Security.setProperty("networkaddress.cache.ttl", "0");
} catch (Exception e) {
Log.w(LOG_TAG, "Could not set DNS ttl to 0 for " + getLogId(), e);
}
adjustDNSCacheTTL();
try {
Security.setProperty("networkaddress.cache.negative.ttl", "0");
} catch (Exception e) {
Log.w(LOG_TAG, "Could not set DNS negative ttl to 0 for " + getLogId(), e);
}
mSocket = connect(mSettings, mSocketFactory);
setReadTimeout(SOCKET_READ_TIMEOUT);
try {
ConnectionSecurity connectionSecurity = mSettings.getConnectionSecurity();
// Try all IPv4 and IPv6 addresses of the host
InetAddress[] addresses = InetAddress.getAllByName(mSettings.getHost());
for (int i = 0; i < addresses.length; i++) {
try {
if (K9MailLib.isDebug() && DEBUG_PROTOCOL_IMAP) {
Log.d(LOG_TAG, "Connecting to " + mSettings.getHost() + " as " +
addresses[i]);
}
SocketAddress socketAddress = new InetSocketAddress(addresses[i],
mSettings.getPort());
if (connectionSecurity == ConnectionSecurity.SSL_TLS_REQUIRED) {
mSocket = mSocketFactory.createSocket(
null,
mSettings.getHost(),
mSettings.getPort(),
mSettings.getClientCertificateAlias());
} else {
mSocket = new Socket();
}
mSocket.connect(socketAddress, RemoteStore.SOCKET_CONNECT_TIMEOUT);
// Successfully connected to the server; don't try any other addresses
break;
} catch (SocketException e) {
if (i < (addresses.length - 1)) {
// There are still other addresses for that host to try
continue;
}
throw new MessagingException("Cannot connect to host", e);
}
}
setReadTimeout(RemoteStore.SOCKET_READ_TIMEOUT);
mIn = new PeekableInputStream(new BufferedInputStream(mSocket.getInputStream(),
1024));
mIn = new PeekableInputStream(new BufferedInputStream(mSocket.getInputStream(), BUFFER_SIZE));
mParser = new ImapResponseParser(mIn);
mOut = new BufferedOutputStream(mSocket.getOutputStream(), 1024);
mOut = new BufferedOutputStream(mSocket.getOutputStream(), BUFFER_SIZE);
capabilities.clear();
ImapResponse nullResponse = mParser.readResponse();
if (K9MailLib.isDebug() && DEBUG_PROTOCOL_IMAP)
@ -158,39 +120,18 @@ class ImapConnection {
nullResponses.add(nullResponse);
receiveCapabilities(nullResponses);
if (!hasCapability(ImapCommands.CAPABILITY_CAPABILITY)) {
if (!hasCapability(CAPABILITY_CAPABILITY)) {
if (K9MailLib.isDebug())
Log.i(LOG_TAG, "Did not get capabilities in banner, requesting CAPABILITY for " + getLogId());
List<ImapResponse> responses = receiveCapabilities(executeSimpleCommand(ImapCommands.COMMAND_CAPABILITY));
List<ImapResponse> responses = receiveCapabilities(executeSimpleCommand(COMMAND_CAPABILITY));
if (responses.size() != 2) {
throw new MessagingException("Invalid CAPABILITY response received");
}
}
if (mSettings.getConnectionSecurity() == ConnectionSecurity.STARTTLS_REQUIRED) {
if (mSettings.getConnectionSecurity() == STARTTLS_REQUIRED) {
if (hasCapability("STARTTLS")) {
// STARTTLS
executeSimpleCommand("STARTTLS");
mSocket = mSocketFactory.createSocket(
mSocket,
mSettings.getHost(),
mSettings.getPort(),
mSettings.getClientCertificateAlias());
mSocket.setSoTimeout(RemoteStore.SOCKET_READ_TIMEOUT);
mIn = new PeekableInputStream(new BufferedInputStream(mSocket
.getInputStream(), 1024));
mParser = new ImapResponseParser(mIn);
mOut = new BufferedOutputStream(mSocket.getOutputStream(), 1024);
// Per RFC 2595 (3.1): Once TLS has been started, reissue CAPABILITY command
if (K9MailLib.isDebug())
Log.i(LOG_TAG, "Updating capabilities after STARTTLS for " + getLogId());
capabilities.clear();
List<ImapResponse> responses = receiveCapabilities(executeSimpleCommand(ImapCommands.COMMAND_CAPABILITY));
if (responses.size() != 2) {
throw new MessagingException("Invalid CAPABILITY response received");
}
startTLS();
} else {
/*
* This exception triggers a "Certificate error"
@ -199,137 +140,40 @@ class ImapConnection {
* the account was configured with an obsolete
* "STARTTLS (if available)" setting.
*/
throw new CertificateValidationException(
"STARTTLS connection security not available");
throw new CertificateValidationException("STARTTLS connection security not available");
}
}
switch (mSettings.getAuthType()) {
case CRAM_MD5:
if (hasCapability(ImapCommands.CAPABILITY_AUTH_CRAM_MD5)) {
authCramMD5();
} else {
throw new MessagingException(
"Server doesn't support encrypted passwords using CRAM-MD5.");
}
break;
case PLAIN:
if (hasCapability(ImapCommands.CAPABILITY_AUTH_PLAIN)) {
saslAuthPlain();
} else if (!hasCapability(ImapCommands.CAPABILITY_LOGINDISABLED)) {
login();
} else {
throw new MessagingException(
"Server doesn't support unencrypted passwords using AUTH=PLAIN and LOGIN is disabled.");
}
break;
case EXTERNAL:
if (hasCapability(ImapCommands.CAPABILITY_AUTH_EXTERNAL)) {
saslAuthExternal();
} else {
// Provide notification to user of a problem authenticating using client certificates
throw new CertificateValidationException(CertificateValidationException.Reason.MissingCapability);
}
break;
default:
throw new MessagingException(
"Unhandled authentication method found in the server settings (bug).");
}
authenticate(mSettings.getAuthType());
authSuccess = true;
if (K9MailLib.isDebug()) {
Log.d(LOG_TAG, ImapCommands.CAPABILITY_COMPRESS_DEFLATE + " = " + hasCapability(ImapCommands.CAPABILITY_COMPRESS_DEFLATE));
Log.d(LOG_TAG, CAPABILITY_COMPRESS_DEFLATE + " = " + hasCapability(CAPABILITY_COMPRESS_DEFLATE));
}
if (hasCapability(ImapCommands.CAPABILITY_COMPRESS_DEFLATE)) {
boolean useCompression = true;
NetworkInfo netInfo = mConnectivityManager.getActiveNetworkInfo();
if (netInfo != null) {
int type = netInfo.getType();
if (K9MailLib.isDebug())
Log.d(LOG_TAG, "On network type " + type);
useCompression = mSettings.useCompression(type);
}
if (K9MailLib.isDebug())
Log.d(LOG_TAG, "useCompression " + useCompression);
if (useCompression) {
try {
executeSimpleCommand(ImapCommands.COMMAND_COMPRESS_DEFLATE);
Inflater inf = new Inflater(true);
InflaterInputStream zInputStream = new InflaterInputStream(mSocket.getInputStream(), inf);
mIn = new PeekableInputStream(new BufferedInputStream(zInputStream, 1024));
mParser = new ImapResponseParser(mIn);
ZOutputStream zOutputStream = new ZOutputStream(mSocket.getOutputStream(), JZlib.Z_BEST_SPEED, true);
mOut = new BufferedOutputStream(zOutputStream, 1024);
zOutputStream.setFlushMode(JZlib.Z_PARTIAL_FLUSH);
if (K9MailLib.isDebug()) {
Log.i(LOG_TAG, "Compression enabled for " + getLogId());
}
} catch (Exception e) {
Log.e(LOG_TAG, "Unable to negotiate compression", e);
}
}
if (hasCapability(CAPABILITY_COMPRESS_DEFLATE) && shouldEnableCompression()) {
enableCompression();
}
if (K9MailLib.isDebug())
if (K9MailLib.isDebug()) {
Log.d(LOG_TAG, "NAMESPACE = " + hasCapability(ImapCommands.CAPABILITY_NAMESPACE)
+ ", mPathPrefix = " + mSettings.getPathPrefix());
+ ", mPathPrefix = " + mSettings.getPathPrefix());
}
if (mSettings.getPathPrefix() == null) {
if (hasCapability(ImapCommands.CAPABILITY_NAMESPACE)) {
if (K9MailLib.isDebug())
Log.i(LOG_TAG, "mPathPrefix is unset and server has NAMESPACE capability");
List<ImapResponse> namespaceResponses =
executeSimpleCommand(ImapCommands.COMMAND_NAMESPACE);
for (ImapResponse response : namespaceResponses) {
if (ImapResponseParser.equalsIgnoreCase(response.get(0), ImapCommands.COMMAND_NAMESPACE)) {
if (K9MailLib.isDebug())
Log.d(LOG_TAG, "Got NAMESPACE response " + response + " on " + getLogId());
Object personalNamespaces = response.get(1);
if (personalNamespaces != null && personalNamespaces instanceof ImapList) {
if (K9MailLib.isDebug())
Log.d(LOG_TAG, "Got personal namespaces: " + personalNamespaces);
ImapList bracketed = (ImapList)personalNamespaces;
Object firstNamespace = bracketed.get(0);
if (firstNamespace != null && firstNamespace instanceof ImapList) {
if (K9MailLib.isDebug())
Log.d(LOG_TAG, "Got first personal namespaces: " + firstNamespace);
bracketed = (ImapList)firstNamespace;
mSettings.setPathPrefix(bracketed.getString(0));
mSettings.setPathDelimeter(bracketed.getString(1));
mSettings.setCombinedPrefix(null);
if (K9MailLib.isDebug())
Log.d(LOG_TAG, "Got path '" + mSettings.getPathPrefix() + "' and separator '" + mSettings.getPathDelimeter() + "'");
}
}
}
if (K9MailLib.isDebug()) {
Log.i(LOG_TAG, "pathPrefix is unset and server has NAMESPACE capability");
}
handleNamespace();
} else {
if (K9MailLib.isDebug())
Log.i(LOG_TAG, "mPathPrefix is unset but server does not have NAMESPACE capability");
if (K9MailLib.isDebug()) {
Log.i(LOG_TAG, "pathPrefix is unset but server does not have NAMESPACE capability");
}
mSettings.setPathPrefix("");
}
}
if (mSettings.getPathDelimeter() == null) {
try {
List<ImapResponse> nameResponses =
executeSimpleCommand("LIST \"\" \"\"");
for (ImapResponse response : nameResponses) {
if (ImapResponseParser.equalsIgnoreCase(response.get(0), "LIST")) {
mSettings.setPathDelimeter(response.getString(2));
mSettings.setCombinedPrefix(null);
if (K9MailLib.isDebug())
Log.d(LOG_TAG, "Got path delimeter '" + mSettings.getPathDelimeter() + "' for " + getLogId());
}
}
} catch (Exception e) {
Log.e(LOG_TAG, "Unable to get path delimeter using LIST", e);
}
if (mSettings.getPathDelimiter() == null) {
getPathDelimiter();
}
} catch (SSLException e) {
@ -358,12 +202,106 @@ class ImapConnection {
}
}
private List<ImapResponse> receiveCapabilities(List<ImapResponse> responses) {
capabilities = ImapResponseParser.parseCapabilities(responses);
if (K9MailLib.isDebug()) {
Log.d(LOG_TAG, "Saving " + capabilities + " capabilities for " + getLogId());
public boolean isOpen() {
return (mIn != null && mOut != null && mSocket != null && mSocket.isConnected() && !mSocket.isClosed());
}
public void close() {
// if (isOpen()) {
// try {
// executeSimpleCommand("LOGOUT");
// } catch (Exception e) {
//
// }
// }
IOUtils.closeQuietly(mIn);
IOUtils.closeQuietly(mOut);
IOUtils.closeQuietly(mSocket);
mIn = null;
mOut = null;
mSocket = null;
}
public ImapResponse readResponse() throws IOException, MessagingException {
return readResponse(null);
}
public ImapResponse readResponse(ImapResponseCallback callback) throws IOException {
try {
ImapResponse response = mParser.readResponse(callback);
if (K9MailLib.isDebug() && DEBUG_PROTOCOL_IMAP)
Log.v(LOG_TAG, getLogId() + "<<<" + response);
return response;
} catch (IOException ioe) {
close();
throw ioe;
}
return responses;
}
public void sendContinuation(String continuation) throws IOException {
mOut.write(continuation.getBytes());
mOut.write('\r');
mOut.write('\n');
mOut.flush();
if (K9MailLib.isDebug() && DEBUG_PROTOCOL_IMAP)
Log.v(LOG_TAG, getLogId() + ">>> " + continuation);
}
public String sendCommand(String command, boolean sensitive) throws MessagingException, IOException {
try {
open();
String tag = Integer.toString(mNextCommandTag++);
String commandToSend = tag + " " + command + "\r\n";
mOut.write(commandToSend.getBytes());
mOut.flush();
if (K9MailLib.isDebug() && DEBUG_PROTOCOL_IMAP) {
if (sensitive && !K9MailLib.isDebugSensitive()) {
Log.v(LOG_TAG, getLogId() + ">>> "
+ "[Command Hidden, Enable Sensitive Debug Logging To Show]");
} else {
Log.v(LOG_TAG, getLogId() + ">>> " + commandToSend);
}
}
return tag;
} catch (IOException ioe) {
close();
throw ioe;
} catch (ImapException ie) {
close();
throw ie;
} catch (MessagingException me) {
close();
throw me;
}
}
public List<ImapResponse> executeSimpleCommand(String command) throws IOException,
MessagingException {
return executeSimpleCommand(command, false, null);
}
public List<ImapResponse> executeSimpleCommand(String command, boolean sensitive) throws IOException,
MessagingException {
return executeSimpleCommand(command, sensitive, null);
}
public List<ImapResponse> executeSimpleCommand(String command, boolean sensitive, UntaggedHandler untaggedHandler)
throws IOException, MessagingException {
String commandToLog = command;
if (sensitive && !K9MailLib.isDebugSensitive()) {
commandToLog = "*sensitive*";
}
//if (K9MailLib.isDebug())
// Log.v(LOG_TAG, "Sending IMAP command " + commandToLog + " on connection " + getLogId());
String tag = sendCommand(command, sensitive);
//if (K9MailLib.isDebug())
// Log.v(LOG_TAG, "Sent IMAP command " + commandToLog + " with tag " + tag + " for " + getLogId());
return mParser.readStatusResponse(tag, commandToLog, getLogId(), untaggedHandler);
}
protected void login() throws IOException, MessagingException {
@ -426,23 +364,6 @@ class ImapConnection {
}
}
private void saslAuthExternal() throws IOException, MessagingException {
try {
receiveCapabilities(executeSimpleCommand(
String.format("AUTHENTICATE EXTERNAL %s",
Base64.encode(mSettings.getUsername())), false));
} catch (ImapException e) {
/*
* Provide notification to the user of a problem authenticating
* using client certificates. We don't use an
* AuthenticationFailedException because that would trigger a
* "Username or password incorrect" notification in
* AccountSetupCheckSettings.
*/
throw new CertificateValidationException(e.getMessage());
}
}
protected ImapResponse readContinuationResponse(String tag)
throws IOException, MessagingException {
ImapResponse response;
@ -462,7 +383,6 @@ class ImapConnection {
return response;
}
protected void setReadTimeout(int millis) throws SocketException {
Socket sock = mSocket;
if (sock != null) {
@ -481,106 +401,211 @@ class ImapConnection {
return capabilities.contains(capability.toUpperCase(Locale.US));
}
public boolean isOpen() {
return (mIn != null && mOut != null && mSocket != null && mSocket.isConnected() && !mSocket.isClosed());
}
public void close() {
// if (isOpen()) {
// try {
// executeSimpleCommand("LOGOUT");
// } catch (Exception e) {
//
// }
// }
IOUtils.closeQuietly(mIn);
IOUtils.closeQuietly(mOut);
IOUtils.closeQuietly(mSocket);
mIn = null;
mOut = null;
mSocket = null;
}
public ImapResponse readResponse() throws IOException, MessagingException {
return readResponse(null);
}
public ImapResponse readResponse(ImapResponseCallback callback) throws IOException {
private void saslAuthExternal() throws IOException, MessagingException {
try {
ImapResponse response = mParser.readResponse(callback);
if (K9MailLib.isDebug() && DEBUG_PROTOCOL_IMAP)
Log.v(LOG_TAG, getLogId() + "<<<" + response);
return response;
} catch (IOException ioe) {
close();
throw ioe;
receiveCapabilities(executeSimpleCommand(
String.format("AUTHENTICATE EXTERNAL %s",
Base64.encode(mSettings.getUsername())), false));
} catch (ImapException e) {
/*
* Provide notification to the user of a problem authenticating
* using client certificates. We don't use an
* AuthenticationFailedException because that would trigger a
* "Username or password incorrect" notification in
* AccountSetupCheckSettings.
*/
throw new CertificateValidationException(e.getMessage());
}
}
public void sendContinuation(String continuation) throws IOException {
mOut.write(continuation.getBytes());
mOut.write('\r');
mOut.write('\n');
mOut.flush();
if (K9MailLib.isDebug() && DEBUG_PROTOCOL_IMAP)
Log.v(LOG_TAG, getLogId() + ">>> " + continuation);
}
public String sendCommand(String command, boolean sensitive) throws MessagingException, IOException {
private void getPathDelimiter() {
try {
open();
String tag = Integer.toString(mNextCommandTag++);
String commandToSend = tag + " " + command + "\r\n";
mOut.write(commandToSend.getBytes());
mOut.flush();
if (K9MailLib.isDebug() && DEBUG_PROTOCOL_IMAP) {
if (sensitive && !K9MailLib.isDebugSensitive()) {
Log.v(LOG_TAG, getLogId() + ">>> "
+ "[Command Hidden, Enable Sensitive Debug Logging To Show]");
} else {
Log.v(LOG_TAG, getLogId() + ">>> " + commandToSend);
List<ImapResponse> nameResponses = executeSimpleCommand("LIST \"\" \"\"");
for (ImapResponse response : nameResponses) {
if (equalsIgnoreCase(response.get(0), "LIST")) {
mSettings.setPathDelimiter(response.getString(2));
mSettings.setCombinedPrefix(null);
if (K9MailLib.isDebug()) {
Log.d(LOG_TAG, "Got path delimiter '" + mSettings.getPathDelimiter() + "' for " + getLogId());
}
}
}
return tag;
} catch (IOException ioe) {
close();
throw ioe;
} catch (ImapException ie) {
close();
throw ie;
} catch (MessagingException me) {
close();
throw me;
} catch (Exception e) {
Log.e(LOG_TAG, "Unable to get path delimiter using LIST", e);
}
}
public List<ImapResponse> executeSimpleCommand(String command) throws IOException,
MessagingException {
return executeSimpleCommand(command, false, null);
}
private void handleNamespace() throws IOException, MessagingException {
List<ImapResponse> responses = executeSimpleCommand(ImapCommands.COMMAND_NAMESPACE);
for (ImapResponse response : responses) {
if (equalsIgnoreCase(response.get(0), ImapCommands.COMMAND_NAMESPACE)) {
if (K9MailLib.isDebug()) {
Log.d(LOG_TAG, "Got NAMESPACE response " + response + " on " + getLogId());
}
public List<ImapResponse> executeSimpleCommand(String command, boolean sensitive) throws IOException,
MessagingException {
return executeSimpleCommand(command, sensitive, null);
}
public List<ImapResponse> executeSimpleCommand(String command, boolean sensitive, UntaggedHandler untaggedHandler)
throws IOException, MessagingException {
String commandToLog = command;
if (sensitive && !K9MailLib.isDebugSensitive()) {
commandToLog = "*sensitive*";
Object personalNamespaces = response.get(1);
if (personalNamespaces instanceof ImapList) {
if (K9MailLib.isDebug())
Log.d(LOG_TAG, "Got personal namespaces: " + personalNamespaces);
ImapList bracketed = (ImapList)personalNamespaces;
Object firstNamespace = bracketed.get(0);
if (firstNamespace != null && firstNamespace instanceof ImapList) {
if (K9MailLib.isDebug())
Log.d(LOG_TAG, "Got first personal namespaces: " + firstNamespace);
bracketed = (ImapList)firstNamespace;
mSettings.setPathPrefix(bracketed.getString(0));
mSettings.setPathDelimiter(bracketed.getString(1));
mSettings.setCombinedPrefix(null);
if (K9MailLib.isDebug())
Log.d(LOG_TAG, "Got path '" + mSettings.getPathPrefix() + "' and separator '" + mSettings.getPathDelimiter() + "'");
}
}
}
}
//if (K9MailLib.isDebug())
// Log.v(LOG_TAG, "Sending IMAP command " + commandToLog + " on connection " + getLogId());
String tag = sendCommand(command, sensitive);
//if (K9MailLib.isDebug())
// Log.v(LOG_TAG, "Sent IMAP command " + commandToLog + " with tag " + tag + " for " + getLogId());
}
return mParser.readStatusResponse(tag, commandToLog, getLogId(), untaggedHandler);
private boolean shouldEnableCompression() {
boolean useCompression = true;
NetworkInfo netInfo = mConnectivityManager.getActiveNetworkInfo();
if (netInfo != null) {
int type = netInfo.getType();
if (K9MailLib.isDebug()) {
Log.d(LOG_TAG, "On network type " + type);
}
useCompression = mSettings.useCompression(type);
}
if (K9MailLib.isDebug()) {
Log.d(LOG_TAG, "useCompression " + useCompression);
}
return useCompression;
}
private void enableCompression() {
try {
executeSimpleCommand(ImapCommands.COMMAND_COMPRESS_DEFLATE);
InflaterInputStream zInputStream = new InflaterInputStream(mSocket.getInputStream(), new Inflater(true));
mIn = new PeekableInputStream(new BufferedInputStream(zInputStream, BUFFER_SIZE));
mParser = new ImapResponseParser(mIn);
ZOutputStream zOutputStream = new ZOutputStream(mSocket.getOutputStream(), JZlib.Z_BEST_SPEED, true);
mOut = new BufferedOutputStream(zOutputStream, BUFFER_SIZE);
zOutputStream.setFlushMode(JZlib.Z_PARTIAL_FLUSH);
if (K9MailLib.isDebug()) {
Log.i(LOG_TAG, "Compression enabled for " + getLogId());
}
} catch (Exception e) {
Log.e(LOG_TAG, "Unable to negotiate compression", e);
}
}
private void authenticate(AuthType authType) throws MessagingException, IOException {
switch (authType) {
case CRAM_MD5:
if (hasCapability(CAPABILITY_AUTH_CRAM_MD5)) {
authCramMD5();
} else {
throw new MessagingException("Server doesn't support encrypted passwords using CRAM-MD5.");
}
break;
case PLAIN:
if (hasCapability(CAPABILITY_AUTH_PLAIN)) {
saslAuthPlain();
} else if (!hasCapability(CAPABILITY_LOGINDISABLED)) {
login();
} else {
throw new MessagingException( "Server doesn't support unencrypted passwords using AUTH=PLAIN and LOGIN is disabled.");
}
break;
case EXTERNAL:
if (hasCapability(CAPABILITY_AUTH_EXTERNAL)) {
saslAuthExternal();
} else {
// Provide notification to user of a problem authenticating using client certificates
throw new CertificateValidationException(CertificateValidationException.Reason.MissingCapability);
}
break;
default:
throw new MessagingException("Unhandled authentication method found in the server settings (bug).");
}
}
private void startTLS() throws IOException, MessagingException, GeneralSecurityException {
executeSimpleCommand("STARTTLS");
mSocket = mSocketFactory.createSocket(
mSocket,
mSettings.getHost(),
mSettings.getPort(),
mSettings.getClientCertificateAlias());
mSocket.setSoTimeout(SOCKET_READ_TIMEOUT);
mIn = new PeekableInputStream(new BufferedInputStream(mSocket.getInputStream(), BUFFER_SIZE));
mParser = new ImapResponseParser(mIn);
mOut = new BufferedOutputStream(mSocket.getOutputStream(), BUFFER_SIZE);
// Per RFC 2595 (3.1): Once TLS has been started, reissue CAPABILITY command
if (K9MailLib.isDebug()) {
Log.i(LOG_TAG, "Updating capabilities after STARTTLS for " + getLogId());
}
capabilities.clear();
List<ImapResponse> responses = receiveCapabilities(executeSimpleCommand(COMMAND_CAPABILITY));
if (responses.size() != 2) {
throw new MessagingException("Invalid CAPABILITY response received");
}
}
private static Socket connect(ImapSettings settings, TrustedSocketFactory socketFactory)
throws GeneralSecurityException, MessagingException, IOException {
// Try all IPv4 and IPv6 addresses of the host
InetAddress[] addresses = InetAddress.getAllByName(settings.getHost());
for (int i = 0; i < addresses.length; i++) {
try {
if (K9MailLib.isDebug() && DEBUG_PROTOCOL_IMAP) {
Log.d(LOG_TAG, "Connecting to " + settings.getHost() + " as " + addresses[i]);
}
SocketAddress socketAddress = new InetSocketAddress(addresses[i], settings.getPort());
Socket socket;
if (settings.getConnectionSecurity() == ConnectionSecurity.SSL_TLS_REQUIRED) {
socket = socketFactory.createSocket(
null,
settings.getHost(),
settings.getPort(),
settings.getClientCertificateAlias());
} else {
socket = new Socket();
}
socket.connect(socketAddress, SOCKET_CONNECT_TIMEOUT);
// Successfully connected to the server; don't try any other addresses
return socket;
} catch (SocketException e) {
if (i < (addresses.length - 1)) {
// There are still other addresses for that host to try
continue;
}
throw new MessagingException("Cannot connect to host", e);
}
}
throw new MessagingException("Cannot connect to host");
}
private void adjustDNSCacheTTL() {
try {
Security.setProperty("networkaddress.cache.ttl", "0");
} catch (Exception e) {
Log.w(LOG_TAG, "Could not set DNS ttl to 0 for " + getLogId(), e);
}
try {
Security.setProperty("networkaddress.cache.negative.ttl", "0");
} catch (Exception e) {
Log.w(LOG_TAG, "Could not set DNS negative ttl to 0 for " + getLogId(), e);
}
}
private List<ImapResponse> receiveCapabilities(List<ImapResponse> responses) {
capabilities = ImapResponseParser.parseCapabilities(responses);
if (K9MailLib.isDebug()) {
Log.d(LOG_TAG, "Saving " + capabilities + " capabilities for " + getLogId());
}
return responses;
}
}

View File

@ -2945,13 +2945,13 @@ public class ImapStore extends RemoteStore {
}
@Override
public String getPathDelimeter() {
public String getPathDelimiter() {
return mPathDelimiter;
}
@Override
public void setPathDelimeter(String delimeter) {
mPathDelimiter = delimeter;
public void setPathDelimiter(String delimiter) {
mPathDelimiter = delimiter;
}
@Override

View File

@ -28,9 +28,9 @@ public interface ImapSettings {
void setPathPrefix(String prefix);
String getPathDelimeter();
String getPathDelimiter();
void setPathDelimeter(String delimeter);
void setPathDelimiter(String delimiter);
String getCombinedPrefix();