1
0
mirror of https://github.com/moparisthebest/k-9 synced 2024-11-24 10:22:15 -05:00

Improved fallback authentication methods + ran source formatter.

This commit is contained in:
Kris Wong 2010-12-17 14:40:19 +00:00
parent 0778c8ea17
commit 623217f6d0

View File

@ -25,7 +25,6 @@ import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair; import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.ExecutionContext;
import org.apache.http.protocol.HttpContext; import org.apache.http.protocol.HttpContext;
import org.xml.sax.Attributes; import org.xml.sax.Attributes;
import org.xml.sax.InputSource; import org.xml.sax.InputSource;
@ -92,12 +91,11 @@ public class WebDavStore extends Store
private String mAuthPath; /* Stores the path off of the server to post data to for form based authentication */ private String mAuthPath; /* Stores the path off of the server to post data to for form based authentication */
private String mMailboxPath; /* Stores the user specified path to the mailbox */ private String mMailboxPath; /* Stores the user specified path to the mailbox */
private URI mUri; /* Stores the Uniform Resource Indicator with all connection info */ private URI mUri; /* Stores the Uniform Resource Indicator with all connection info */
private String mRedirectUrl;
private String mAuthString;
private boolean mSecure; private boolean mSecure;
private WebDavHttpClient mHttpClient = null; private WebDavHttpClient mHttpClient = null;
private HttpContext mContext = null; private HttpContext mContext = null;
private String mAuthString;
private CookieStore mAuthCookies = null; private CookieStore mAuthCookies = null;
private short mAuthentication = AUTH_TYPE_NONE; private short mAuthentication = AUTH_TYPE_NONE;
private String mCachedLoginUrl; private String mCachedLoginUrl;
@ -392,7 +390,8 @@ public class WebDavStore extends Store
buffer.append("<a:searchrequest xmlns:a='DAV:'><a:sql>\r\n"); buffer.append("<a:searchrequest xmlns:a='DAV:'><a:sql>\r\n");
buffer.append("SELECT \"DAV:visiblecount\"\r\n"); buffer.append("SELECT \"DAV:visiblecount\"\r\n");
buffer.append(" FROM \"\"\r\n"); buffer.append(" FROM \"\"\r\n");
buffer.append(" WHERE \"DAV:ishidden\"=False AND \"DAV:isfolder\"=False AND \"urn:schemas:httpmail:read\"=").append(messageState).append("\r\n"); buffer.append(" WHERE \"DAV:ishidden\"=False AND \"DAV:isfolder\"=False AND \"urn:schemas:httpmail:read\"=")
.append(messageState).append("\r\n");
buffer.append(" GROUP BY \"DAV:ishidden\"\r\n"); buffer.append(" GROUP BY \"DAV:ishidden\"\r\n");
buffer.append("</a:sql></a:searchrequest>\r\n"); buffer.append("</a:sql></a:searchrequest>\r\n");
return buffer.toString(); return buffer.toString();
@ -540,11 +539,12 @@ public class WebDavStore extends Store
*/ */
/** /**
* Determines which type of authentication Exchange is using and * Determines which type of authentication Exchange is using and authenticates appropriately.
* authenticates appropriately. *
* @throws MessagingException * @throws MessagingException
*/ */
public boolean authenticate() throws MessagingException public boolean authenticate()
throws MessagingException
{ {
try try
{ {
@ -602,11 +602,13 @@ public class WebDavStore extends Store
} }
/** /**
* Makes the initial connection to Exchange for authentication. * Makes the initial connection to Exchange for authentication. Determines the type of authentication necessary for
* Determines the type of authentication necessary for the server. * the server.
*
* @throws MessagingException * @throws MessagingException
*/ */
private ConnectionInfo doInitialConnection() throws MessagingException private ConnectionInfo doInitialConnection()
throws MessagingException
{ {
// For our initial connection we are sending an empty GET request to // For our initial connection we are sending an empty GET request to
// the configured URL, which should be in the following form: // the configured URL, which should be in the following form:
@ -683,9 +685,11 @@ public class WebDavStore extends Store
/** /**
* Performs form-based authentication. * Performs form-based authentication.
*
* @throws MessagingException * @throws MessagingException
*/ */
public void doFBA(ConnectionInfo info) throws IOException, MessagingException public void doFBA(ConnectionInfo info)
throws IOException, MessagingException
{ {
// Clear out cookies from any previous authentication. // Clear out cookies from any previous authentication.
mAuthCookies.clear(); mAuthCookies.clear();
@ -725,85 +729,78 @@ public class WebDavStore extends Store
HttpResponse response = httpClient.executeOverride(request, mContext); HttpResponse response = httpClient.executeOverride(request, mContext);
int statusCode = response.getStatusLine().getStatusCode(); int statusCode = response.getStatusLine().getStatusCode();
if (statusCode >= 200 && statusCode < 300) if (statusCode >= 200 && statusCode < 300 &&
mAuthCookies != null && !mAuthCookies.getCookies().isEmpty())
{ {
// Success, we're logged on and an authentication cookie should // Success, we're authenticated and cookies have been added to mAuthCookies for us.
// have already been added to mAuthCookies for us.
} }
else if (statusCode == 404) else
{ {
// The resource was not found, which means we need to get tricky // Check our response from the authentication URL above for a form action.
// about finding the correct login path. String formAction = findFormAction(WebDavHttpClient.getUngzippedContent(response.getEntity()));
// Send a request to our original redirect URL, and scrape the if (formAction == null)
// login path from the returned page.
httpClient.addRequestInterceptor(new HttpRequestInterceptor()
{ {
public void process(HttpRequest request, HttpContext context) // If there is no form action, try using our redirect URL from the initial connection.
throws HttpException, IOException if (info.redirectUrl != null && !info.redirectUrl.equals(""))
{
mRedirectUrl = ((HttpHost) context.getAttribute(ExecutionContext.HTTP_TARGET_HOST)).toURI() +
request.getRequestLine().getUri();
}
});
if (info != null)
{ {
loginUrl = info.redirectUrl; loginUrl = info.redirectUrl;
}
else if (mRedirectUrl != null && !mRedirectUrl.equals(""))
{
loginUrl = mRedirectUrl;
}
else
{
throw new MessagingException("No valid login URL available for form-based authentication.");
}
request = new HttpGeneric(loginUrl);
request.setMethod("GET");
response = httpClient.executeOverride(request, mContext);
formAction = findFormAction(WebDavHttpClient.getUngzippedContent(response.getEntity()));
}
}
if (formAction != null)
{
try try
{ {
InputStream istream = sendRequest(loginUrl, "GET", null, null, false); URI formActionUri = new URI(formAction);
if (istream != null) URI loginUri = new URI(loginUrl);
{
BufferedReader reader = new BufferedReader(new InputStreamReader(istream), 4096);
String tempText = "";
boolean matched = false;
while ((tempText = reader.readLine()) != null && if (formActionUri.isAbsolute())
!matched)
{ {
if (tempText.indexOf(" action") >= 0) // The form action is an absolute URL, just use it.
{ loginUrl = formAction;
String[] tagParts = tempText.split("\"");
if (tagParts[1].lastIndexOf('/') < 0 &&
mRedirectUrl != null &&
!mRedirectUrl.equals(""))
{
/* We have to do a multi-stage substring here because of potential GET parameters */
mRedirectUrl = mRedirectUrl.substring(0, mRedirectUrl.lastIndexOf('?'));
mRedirectUrl = mRedirectUrl.substring(0, mRedirectUrl.lastIndexOf('/'));
loginUrl = mRedirectUrl + "/" + tagParts[1];
this.mAuthPath = new URI(loginUrl).getPath();
} }
else else
{ {
loginUrl = getRoot() + tagParts[1]; // Append the form action to our current URL, minus the file name.
this.mAuthPath = new URI(loginUrl).getPath(); String urlPath = loginUri.getPath();
int lastPathPos = urlPath.lastIndexOf('/');
if (lastPathPos > -1)
{
urlPath = urlPath.substring(0, lastPathPos + 1);
urlPath = urlPath.concat(formAction);
} }
}
}
istream.close();
// Now retry the login using our scraped login URL. // Reconstruct the login URL based on the original login URL and the form action.
URI finalUri = new URI(loginUri.getScheme(),
loginUri.getUserInfo(),
loginUri.getHost(),
loginUri.getPort(),
urlPath,
null,
null);
loginUrl = finalUri.toString();
}
// Retry the login using our new URL.
request = new HttpGeneric(loginUrl); request = new HttpGeneric(loginUrl);
request.setMethod("POST"); request.setMethod("POST");
request.setEntity(formEntity); request.setEntity(formEntity);
httpClient.executeOverride(request, mContext); httpClient.executeOverride(request, mContext);
} }
} catch (URISyntaxException e)
catch(URISyntaxException use)
{ {
throw new MessagingException("An invalid login URL was detected: " + loginUrl); Log.e(K9.LOG_TAG, "URISyntaxException caught " + e + "\nTrace: " + processException(e));
throw new MessagingException("URISyntaxException caught", e);
}
}
else
{
throw new MessagingException("A valid URL for Exchange authentication could not be found.");
} }
} }
@ -814,6 +811,47 @@ public class WebDavStore extends Store
} }
} }
/**
* Searches the specified stream for an HTML form and returns the form's action target.
*
* @throws IOException
*/
private String findFormAction(InputStream istream)
throws IOException
{
String formAction = null;
BufferedReader reader = new BufferedReader(new InputStreamReader(istream), 4096);
String tempText;
// Read line by line until we find something like: <form action="owaauth.dll"...>.
while ((tempText = reader.readLine()) != null &&
formAction == null)
{
if (tempText.indexOf(" action=") > -1)
{
String[] actionParts = tempText.split(" action=");
if (actionParts.length > 1 && actionParts[1].length() > 1)
{
char openQuote = actionParts[1].charAt(0);
int closePos = actionParts[1].indexOf(openQuote, 1);
if (closePos > 1)
{
formAction = actionParts[1].substring(1, closePos);
// Remove any GET parameters.
int quesPos = formAction.indexOf('?');
if (quesPos != -1)
{
formAction = formAction.substring(0, quesPos);
}
}
}
}
}
return formAction;
}
public CookieStore getAuthCookies() public CookieStore getAuthCookies()
{ {
return mAuthCookies; return mAuthCookies;
@ -834,6 +872,8 @@ public class WebDavStore extends Store
if (mHttpClient == null) if (mHttpClient == null)
{ {
mHttpClient = new WebDavHttpClient(); mHttpClient = new WebDavHttpClient();
// Disable automatic redirects on the http client.
mHttpClient.getParams().setBooleanParameter("http.protocol.handle-redirects", false);
// Setup a cookie store for forms-based authentication. // Setup a cookie store for forms-based authentication.
mContext = new BasicHttpContext(); mContext = new BasicHttpContext();
@ -860,13 +900,13 @@ public class WebDavStore extends Store
return mHttpClient; return mHttpClient;
} }
private InputStream sendRequest(String url, String method, StringEntity messageBody, HashMap<String, String> headers, boolean tryAuth) private InputStream sendRequest(String url, String method, StringEntity messageBody,
HashMap<String, String> headers, boolean tryAuth)
throws MessagingException throws MessagingException
{ {
InputStream istream = null; InputStream istream = null;
if (url == null || if (url == null || method == null)
method == null)
{ {
return istream; return istream;
} }
@ -885,10 +925,13 @@ public class WebDavStore extends Store
httpmethod.setEntity(messageBody); httpmethod.setEntity(messageBody);
} }
if (headers != null)
{
for (String headerName : headers.keySet()) for (String headerName : headers.keySet())
{ {
httpmethod.setHeader(headerName, headers.get(headerName)); httpmethod.setHeader(headerName, headers.get(headerName));
} }
}
if (mAuthentication == AUTH_TYPE_NONE) if (mAuthentication == AUTH_TYPE_NONE)
{ {
@ -956,9 +999,9 @@ public class WebDavStore extends Store
} }
/** /**
* Performs an httprequest to the supplied url using the supplied method. * Performs an httprequest to the supplied url using the supplied method. messageBody and headers are optional as
* messageBody and headers are optional as not all requests will need them. * not all requests will need them. There are two signatures to support calls that don't require parsing of the
* There are two signatures to support calls that don't require parsing of the response. * response.
*/ */
private DataSet processRequest(String url, String method, String messageBody, HashMap<String, String> headers) private DataSet processRequest(String url, String method, String messageBody, HashMap<String, String> headers)
throws MessagingException throws MessagingException
@ -966,13 +1009,15 @@ public class WebDavStore extends Store
return processRequest(url, method, messageBody, headers, true); return processRequest(url, method, messageBody, headers, true);
} }
private DataSet processRequest(String url, String method, String messageBody, HashMap<String, String> headers, boolean needsParsing) private DataSet processRequest(String url, String method, String messageBody, HashMap<String, String> headers,
boolean needsParsing)
throws MessagingException throws MessagingException
{ {
DataSet dataset = new DataSet(); DataSet dataset = new DataSet();
if (K9.DEBUG && K9.DEBUG_PROTOCOL_WEBDAV) if (K9.DEBUG && K9.DEBUG_PROTOCOL_WEBDAV)
{ {
Log.v(K9.LOG_TAG, "processRequest url = '" + url + "', method = '" + method + "', messageBody = '" + messageBody + "'"); Log.v(K9.LOG_TAG, "processRequest url = '" + url + "', method = '" + method + "', messageBody = '"
+ messageBody + "'");
} }
if (url == null || if (url == null ||
@ -1015,7 +1060,8 @@ public class WebDavStore extends Store
} }
catch (ParserConfigurationException pce) catch (ParserConfigurationException pce)
{ {
Log.e(K9.LOG_TAG, "ParserConfigurationException in processRequest() " + pce + "\nTrace: " + processException(pce)); Log.e(K9.LOG_TAG, "ParserConfigurationException in processRequest() " + pce + "\nTrace: "
+ processException(pce));
throw new MessagingException("ParserConfigurationException in processRequest() ", pce); throw new MessagingException("ParserConfigurationException in processRequest() ", pce);
} }
@ -1136,9 +1182,9 @@ public class WebDavStore extends Store
encodedName = encodedName.replaceAll("\\+", "%20"); encodedName = encodedName.replaceAll("\\+", "%20");
/** /**
* In some instances, it is possible that our folder objects have been collected, * In some instances, it is possible that our folder objects have been collected, but
* but getPersonalNamespaces() isn't called again (ex. Android destroys the email client). * getPersonalNamespaces() isn't called again (ex. Android destroys the email client). Perform an
* Perform an authentication to get the appropriate URLs in place again * authentication to get the appropriate URLs in place again
*/ */
// TODO: danapple0 - huh? // TODO: danapple0 - huh?
// getHttpClient(); // getHttpClient();
@ -1189,7 +1235,9 @@ public class WebDavStore extends Store
{ {
moveOrCopyMessages(msgs, trashFolderName, true); moveOrCopyMessages(msgs, trashFolderName, true);
} }
private void moveOrCopyMessages(Message[] messages, String folderName, boolean isMove) throws MessagingException
private void moveOrCopyMessages(Message[] messages, String folderName, boolean isMove)
throws MessagingException
{ {
String[] uids = new String[messages.length]; String[] uids = new String[messages.length];
@ -1460,7 +1508,6 @@ public class WebDavStore extends Store
fetchFlags(messages, listener); fetchFlags(messages, listener);
} }
if (fp.contains(FetchProfile.Item.BODY_SANE)) if (fp.contains(FetchProfile.Item.BODY_SANE))
{ {
fetchMessages(messages, listener, (mAccount.getMaximumAutoDownloadMessageSize() / 76)); fetchMessages(messages, listener, (mAccount.getMaximumAutoDownloadMessageSize() / 76));
@ -1474,7 +1521,8 @@ public class WebDavStore extends Store
/** /**
* Fetches the full messages or up to lines lines and passes them to the message parser. * Fetches the full messages or up to lines lines and passes them to the message parser.
*/ */
private void fetchMessages(Message[] messages, MessageRetrievalListener listener, int lines) throws MessagingException private void fetchMessages(Message[] messages, MessageRetrievalListener listener, int lines)
throws MessagingException
{ {
WebDavHttpClient httpclient; WebDavHttpClient httpclient;
httpclient = getHttpClient(); httpclient = getHttpClient();
@ -1500,13 +1548,14 @@ public class WebDavStore extends Store
} }
/** /**
* If fetch is called outside of the initial list (ie, a locally stored * If fetch is called outside of the initial list (ie, a locally stored message), it may not have a URL
* message), it may not have a URL associated. Verify and fix that * associated. Verify and fix that
*/ */
if (wdMessage.getUrl().equals("")) if (wdMessage.getUrl().equals(""))
{ {
wdMessage.setUrl(getMessageUrls(new String[] { wdMessage.getUid() }).get(wdMessage.getUid())); wdMessage.setUrl(getMessageUrls(new String[] { wdMessage.getUid() }).get(wdMessage.getUid()));
Log.i(K9.LOG_TAG, "Fetching messages with UID = '" + wdMessage.getUid() + "', URL = '" + wdMessage.getUrl() + "'"); Log.i(K9.LOG_TAG, "Fetching messages with UID = '" + wdMessage.getUid() + "', URL = '"
+ wdMessage.getUrl() + "'");
if (wdMessage.getUrl().equals("")) if (wdMessage.getUrl().equals(""))
{ {
throw new MessagingException("Unable to get URL for message"); throw new MessagingException("Unable to get URL for message");
@ -1515,7 +1564,8 @@ public class WebDavStore extends Store
try try
{ {
Log.i(K9.LOG_TAG, "Fetching message with UID = '" + wdMessage.getUid() + "', URL = '" + wdMessage.getUrl() + "'"); Log.i(K9.LOG_TAG, "Fetching message with UID = '" + wdMessage.getUid() + "', URL = '"
+ wdMessage.getUrl() + "'");
HttpGet httpget = new HttpGet(new URI(wdMessage.getUrl())); HttpGet httpget = new HttpGet(new URI(wdMessage.getUrl()));
HttpResponse response; HttpResponse response;
HttpEntity entity; HttpEntity entity;
@ -1581,7 +1631,9 @@ public class WebDavStore extends Store
} }
catch (IOException ioe) catch (IOException ioe)
{ {
Log.e(K9.LOG_TAG, "Non-success response code loading message, response code was " + statusCode + "\nURL: " + wdMessage.getUrl() + "\nError: " + ioe.getMessage() + "\nTrace: " + processException(ioe)); Log.e(K9.LOG_TAG, "Non-success response code loading message, response code was " + statusCode
+ "\nURL: " + wdMessage.getUrl() + "\nError: " + ioe.getMessage() + "\nTrace: "
+ processException(ioe));
throw new MessagingException("Failure code " + statusCode, ioe); throw new MessagingException("Failure code " + statusCode, ioe);
} }
@ -1593,9 +1645,8 @@ public class WebDavStore extends Store
} }
/** /**
* Fetches and sets the message flags for the supplied messages. * Fetches and sets the message flags for the supplied messages. The idea is to have this be recursive so that
* The idea is to have this be recursive so that we do a series of medium calls * we do a series of medium calls instead of one large massive call or a large number of smaller calls.
* instead of one large massive call or a large number of smaller calls.
*/ */
private void fetchFlags(Message[] startMessages, MessageRetrievalListener listener) throws MessagingException private void fetchFlags(Message[] startMessages, MessageRetrievalListener listener) throws MessagingException
{ {
@ -1675,12 +1726,12 @@ public class WebDavStore extends Store
} }
/** /**
* Fetches and parses the message envelopes for the supplied messages. * Fetches and parses the message envelopes for the supplied messages. The idea is to have this be recursive so
* The idea is to have this be recursive so that we do a series of medium calls * that we do a series of medium calls instead of one large massive call or a large number of smaller calls.
* instead of one large massive call or a large number of smaller calls.
* Call it a happy balance * Call it a happy balance
*/ */
private void fetchEnvelope(Message[] startMessages, MessageRetrievalListener listener) throws MessagingException private void fetchEnvelope(Message[] startMessages, MessageRetrievalListener listener)
throws MessagingException
{ {
HashMap<String, ParsedMessageEnvelope> envelopes = new HashMap<String, ParsedMessageEnvelope>(); HashMap<String, ParsedMessageEnvelope> envelopes = new HashMap<String, ParsedMessageEnvelope>();
HashMap<String, String> headers = new HashMap<String, String>(); HashMap<String, String> headers = new HashMap<String, String>();
@ -1932,7 +1983,8 @@ public class WebDavStore extends Store
@Override @Override
public String getUidFromMessageId(Message message) throws MessagingException public String getUidFromMessageId(Message message) throws MessagingException
{ {
Log.e(K9.LOG_TAG, "Unimplemented method getUidFromMessageId in WebDavStore.WebDavFolder could lead to duplicate messages " Log.e(K9.LOG_TAG,
"Unimplemented method getUidFromMessageId in WebDavStore.WebDavFolder could lead to duplicate messages "
+ " being uploaded to the Sent folder"); + " being uploaded to the Sent folder");
return null; return null;
} }
@ -1940,7 +1992,8 @@ public class WebDavStore extends Store
@Override @Override
public void setFlags(Flag[] flags, boolean value) throws MessagingException public void setFlags(Flag[] flags, boolean value) throws MessagingException
{ {
Log.e(K9.LOG_TAG, "Unimplemented method setFlags(Flag[], boolean) breaks markAllMessagesAsRead and EmptyTrash"); Log.e(K9.LOG_TAG,
"Unimplemented method setFlags(Flag[], boolean) breaks markAllMessagesAsRead and EmptyTrash");
// Try to make this efficient by not retrieving all of the messages // Try to make this efficient by not retrieving all of the messages
} }
} }
@ -1952,7 +2005,6 @@ public class WebDavStore extends Store
{ {
private String mUrl = ""; private String mUrl = "";
WebDavMessage(String uid, Folder folder) WebDavMessage(String uid, Folder folder)
{ {
this.mUid = uid; this.mUid = uid;
@ -1980,8 +2032,7 @@ public class WebDavStore extends Store
url = ""; url = "";
/** /**
* We have to decode, then encode the URL because Exchange likes to * We have to decode, then encode the URL because Exchange likes to not properly encode all characters
* not properly encode all characters
*/ */
try try
{ {
@ -1991,11 +2042,13 @@ public class WebDavStore extends Store
} }
catch (UnsupportedEncodingException uee) catch (UnsupportedEncodingException uee)
{ {
Log.e(K9.LOG_TAG, "UnsupportedEncodingException caught in setUrl: " + uee + "\nTrace: " + processException(uee)); Log.e(K9.LOG_TAG, "UnsupportedEncodingException caught in setUrl: " + uee + "\nTrace: "
+ processException(uee));
} }
catch (IllegalArgumentException iae) catch (IllegalArgumentException iae)
{ {
Log.e(K9.LOG_TAG, "IllegalArgumentException caught in setUrl: " + iae + "\nTrace: " + processException(iae)); Log.e(K9.LOG_TAG, "IllegalArgumentException caught in setUrl: " + iae + "\nTrace: "
+ processException(iae));
} }
for (int i = 0; i < length - 1; i++) for (int i = 0; i < length - 1; i++)
@ -2075,8 +2128,7 @@ public class WebDavStore extends Store
} }
/** /**
* XML Parsing Handler * XML Parsing Handler Can handle all XML handling needs
* Can handle all XML handling needs
*/ */
public class WebDavHandler extends DefaultHandler public class WebDavHandler extends DefaultHandler
{ {
@ -2128,9 +2180,8 @@ public class WebDavStore extends Store
} }
/** /**
* Data set for a single E-Mail message's required headers (the envelope) * Data set for a single E-Mail message's required headers (the envelope) Only provides accessor methods to the
* Only provides accessor methods to the stored data. All processing should be * stored data. All processing should be done elsewhere. This is done rather than having multiple hashmaps
* done elsewhere. This is done rather than having multiple hashmaps
* associating UIDs to values * associating UIDs to values
*/ */
public static class ParsedMessageEnvelope public static class ParsedMessageEnvelope
@ -2206,8 +2257,8 @@ public class WebDavStore extends Store
} }
/** /**
* Dataset for all XML parses. * Dataset for all XML parses. Data is stored in a single format inside the class and is formatted appropriately
* Data is stored in a single format inside the class and is formatted appropriately depending on the accessor calls made. * depending on the accessor calls made.
*/ */
public class DataSet public class DataSet
{ {
@ -2242,8 +2293,9 @@ public class WebDavStore extends Store
} }
else if (mTempData != null) else if (mTempData != null)
{ {
/* Lost Data are for requests that don't include a message UID. /*
* These requests should only have a depth of one for the response so it will never get stomped over. * Lost Data are for requests that don't include a message UID. These requests should only have a depth
* of one for the response so it will never get stomped over.
*/ */
} }
@ -2376,7 +2428,8 @@ public class WebDavStore extends Store
{ {
/** /**
* Exchange doesn't give us rfc822 dates like it claims. The date is in the format: * Exchange doesn't give us rfc822 dates like it claims. The date is in the format:
* yyyy-MM-dd'T'HH:mm:ss.SSS<Single digit representation of timezone, so far, all instances are Z> * yyyy-MM-dd'T'HH:mm:ss.SSS<Single digit representation of timezone, so far, all instances
* are Z>
*/ */
String date = data.get(header); String date = data.get(header);
date = date.substring(0, date.length() - 1); date = date.substring(0, date.length() - 1);
@ -2414,8 +2467,8 @@ public class WebDavStore extends Store
} }
/** /**
* New HTTP Method that allows changing of the method and generic handling * New HTTP Method that allows changing of the method and generic handling Needed for WebDAV custom methods such as
* Needed for WebDAV custom methods such as SEARCH and PROPFIND * SEARCH and PROPFIND
*/ */
public class HttpGeneric extends HttpEntityEnclosingRequestBase public class HttpGeneric extends HttpEntityEnclosingRequestBase
{ {
@ -2433,7 +2486,8 @@ public class WebDavStore extends Store
} }
/** /**
* @throws IllegalArgumentException if the uri is invalid. * @throws IllegalArgumentException
* if the uri is invalid.
*/ */
public HttpGeneric(final String uri) public HttpGeneric(final String uri)
{ {
@ -2450,8 +2504,7 @@ public class WebDavStore extends Store
String url = ""; String url = "";
/** /**
* We have to decode, then encode the URL because Exchange likes to * We have to decode, then encode the URL because Exchange likes to not properly encode all characters
* not properly encode all characters
*/ */
try try
{ {
@ -2464,11 +2517,13 @@ public class WebDavStore extends Store
} }
catch (UnsupportedEncodingException uee) catch (UnsupportedEncodingException uee)
{ {
Log.e(K9.LOG_TAG, "UnsupportedEncodingException caught in HttpGeneric(String uri): " + uee + "\nTrace: " + processException(uee)); Log.e(K9.LOG_TAG, "UnsupportedEncodingException caught in HttpGeneric(String uri): " + uee
+ "\nTrace: " + processException(uee));
} }
catch (IllegalArgumentException iae) catch (IllegalArgumentException iae)
{ {
Log.e(K9.LOG_TAG, "IllegalArgumentException caught in HttpGeneric(String uri): " + iae + "\nTrace: " + processException(iae)); Log.e(K9.LOG_TAG, "IllegalArgumentException caught in HttpGeneric(String uri): " + iae + "\nTrace: "
+ processException(iae));
} }
for (int i = 0; i < length - 1; i++) for (int i = 0; i < length - 1; i++)
@ -2513,17 +2568,14 @@ public class WebDavStore extends Store
/* /*
* Copyright (C) 2007 The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
* you may not use this file except in compliance with the License. * compliance with the License. You may obtain a copy of the License at
* You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed under the License is distributed on an "AS IS" BASIS, * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * the License for the specific language governing permissions and limitations under the License.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
public static void modifyRequestToAcceptGzipResponse(HttpRequest request) public static void modifyRequestToAcceptGzipResponse(HttpRequest request)
{ {
@ -2535,11 +2587,14 @@ public class WebDavStore extends Store
throws IOException throws IOException
{ {
InputStream responseStream = entity.getContent(); InputStream responseStream = entity.getContent();
if (responseStream == null) return responseStream; if (responseStream == null)
return responseStream;
Header header = entity.getContentEncoding(); Header header = entity.getContentEncoding();
if (header == null) return responseStream; if (header == null)
return responseStream;
String contentEncoding = header.getValue(); String contentEncoding = header.getValue();
if (contentEncoding == null) return responseStream; if (contentEncoding == null)
return responseStream;
if (contentEncoding.contains("gzip")) if (contentEncoding.contains("gzip"))
{ {
Log.i(K9.LOG_TAG, "Response is gzipped"); Log.i(K9.LOG_TAG, "Response is gzipped");