diff options
Diffstat (limited to 'src/com/android/phone/common/mail/store/ImapConnection.java')
-rw-r--r-- | src/com/android/phone/common/mail/store/ImapConnection.java | 248 |
1 files changed, 0 insertions, 248 deletions
diff --git a/src/com/android/phone/common/mail/store/ImapConnection.java b/src/com/android/phone/common/mail/store/ImapConnection.java deleted file mode 100644 index 3cae5f8..0000000 --- a/src/com/android/phone/common/mail/store/ImapConnection.java +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.phone.common.mail.store; - -import android.text.TextUtils; -import android.util.Log; - -import com.android.phone.common.mail.AuthenticationFailedException; -import com.android.phone.common.mail.CertificateValidationException; -import com.android.phone.common.mail.MailTransport; -import com.android.phone.common.mail.MessagingException; -import com.android.phone.common.mail.store.imap.ImapConstants; -import com.android.phone.common.mail.store.imap.ImapResponse; -import com.android.phone.common.mail.store.imap.ImapResponseParser; -import com.android.phone.common.mail.store.imap.ImapUtility; -import com.android.phone.common.mail.store.ImapStore.ImapException; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; - -import javax.net.ssl.SSLException; - -/** - * A cacheable class that stores the details for a single IMAP connection. - */ -public class ImapConnection { - private final String TAG = "ImapConnection"; - - private String mLoginPhrase; - private ImapStore mImapStore; - private MailTransport mTransport; - private ImapResponseParser mParser; - - static final String IMAP_REDACTED_LOG = "[IMAP command redacted]"; - - /** - * Next tag to use. All connections associated to the same ImapStore instance share the same - * counter to make tests simpler. - * (Some of the tests involve multiple connections but only have a single counter to track the - * tag.) - */ - private final AtomicInteger mNextCommandTag = new AtomicInteger(0); - - ImapConnection(ImapStore store) { - setStore(store); - } - - void setStore(ImapStore store) { - // TODO: maybe we should throw an exception if the connection is not closed here, - // if it's not currently closed, then we won't reopen it, so if the credentials have - // changed, the connection will not be reestablished. - mImapStore = store; - mLoginPhrase = null; - } - - /** - * Generates and returns the phrase to be used for authentication. This will be a LOGIN with - * username and password. - * - * @return the login command string to sent to the IMAP server - */ - String getLoginPhrase() { - if (mLoginPhrase == null) { - if (mImapStore.getUsername() != null && mImapStore.getPassword() != null) { - // build the LOGIN string once (instead of over-and-over again.) - // apply the quoting here around the built-up password - mLoginPhrase = ImapConstants.LOGIN + " " + mImapStore.getUsername() + " " - + ImapUtility.imapQuoted(mImapStore.getPassword()); - } - } - return mLoginPhrase; - } - - void open() throws IOException, MessagingException { - if (mTransport != null && mTransport.isOpen()) { - return; - } - - try { - // copy configuration into a clean transport, if necessary - if (mTransport == null) { - mTransport = mImapStore.cloneTransport(); - } - - mTransport.open(); - - createParser(); - - // LOGIN - doLogin(); - } catch (SSLException e) { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "SSLException ", e); - } - throw new CertificateValidationException(e.getMessage(), e); - } catch (IOException ioe) { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "IOException", ioe); - } - throw ioe; - } finally { - destroyResponses(); - } - } - - /** - * Closes the connection and releases all resources. This connection can not be used again - * until {@link #setStore(ImapStore)} is called. - */ - void close() { - if (mTransport != null) { - mTransport.close(); - mTransport = null; - } - destroyResponses(); - mParser = null; - mImapStore = null; - } - - /** - * Logs into the IMAP server - */ - private void doLogin() throws IOException, MessagingException, AuthenticationFailedException { - try { - executeSimpleCommand(getLoginPhrase(), true); - } catch (ImapException ie) { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "ImapException", ie); - } - final String status = ie.getStatus(); - final String code = ie.getResponseCode(); - final String alertText = ie.getAlertText(); - - // if the response code indicates expired or bad credentials, throw a special exception - if (ImapConstants.AUTHENTICATIONFAILED.equals(code) || - ImapConstants.EXPIRED.equals(code) || - (ImapConstants.NO.equals(status) && TextUtils.isEmpty(code))) { - throw new AuthenticationFailedException(alertText, ie); - } - - throw new MessagingException(alertText, ie); - } - } - - /** - * Create an {@link ImapResponseParser} from {@code mTransport.getInputStream()} and - * set it to {@link #mParser}. - * - * If we already have an {@link ImapResponseParser}, we - * {@link #destroyResponses()} and throw it away. - */ - private void createParser() { - destroyResponses(); - mParser = new ImapResponseParser(mTransport.getInputStream()); - } - - - void destroyResponses() { - if (mParser != null) { - mParser.destroyResponses(); - } - } - - List<ImapResponse> executeSimpleCommand(String command) - throws IOException, MessagingException{ - return executeSimpleCommand(command, false); - } - - /** - * Send a single command to the server. The command will be preceded by an IMAP command - * tag and followed by \r\n (caller need not supply them). - * Execute a simple command at the server, a simple command being one that is sent in a single - * line of text - * - * @param command the command to send to the server - * @param sensitive whether the command should be redacted in logs (used for login) - * @return a list of ImapResponses - * @throws IOException - * @throws MessagingException - */ - List<ImapResponse> executeSimpleCommand(String command, boolean sensitive) - throws IOException, MessagingException { - // TODO: It may be nice to catch IOExceptions and close the connection here. - // Currently, we expect callers to do that, but if they fail to we'll be in a broken state. - sendCommand(command, sensitive); - return getCommandResponses(); - } - - String sendCommand(String command, boolean sensitive) throws IOException, MessagingException { - open(); - - if (mTransport == null) { - throw new IOException("Null transport"); - } - String tag = Integer.toString(mNextCommandTag.incrementAndGet()); - String commandToSend = tag + " " + command; - mTransport.writeLine(commandToSend, (sensitive ? IMAP_REDACTED_LOG : command)); - - return tag; - } - - /** - * Read and return all of the responses from the most recent command sent to the server - * - * @return a list of ImapResponses - * @throws IOException - * @throws MessagingException - */ - List<ImapResponse> getCommandResponses() throws IOException, MessagingException { - final List<ImapResponse> responses = new ArrayList<ImapResponse>(); - ImapResponse response; - do { - response = mParser.readResponse(); - responses.add(response); - } while (!response.isTagged()); - - if (!response.isOk()) { - final String toString = response.toString(); - final String status = response.getStatusOrEmpty().getString(); - final String alert = response.getAlertTextOrEmpty().getString(); - final String responseCode = response.getResponseCodeOrEmpty().getString(); - destroyResponses(); - - // if the response code indicates an error occurred within the server, indicate that - if (ImapConstants.UNAVAILABLE.equals(responseCode)) { - throw new MessagingException(MessagingException.SERVER_ERROR, alert); - } - - throw new ImapException(toString, status, alert, responseCode); - } - return responses; - } -} |