mirror of
https://github.com/moparisthebest/k-9
synced 2024-11-24 02:12:15 -05:00
Improved fallback authentication methods + ran source formatter.
This commit is contained in:
parent
0778c8ea17
commit
623217f6d0
@ -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;
|
||||||
@ -84,24 +83,23 @@ public class WebDavStore extends Store
|
|||||||
|
|
||||||
private short mConnectionSecurity;
|
private short mConnectionSecurity;
|
||||||
private String mUsername; /* Stores the username for authentications */
|
private String mUsername; /* Stores the username for authentications */
|
||||||
private String mAlias; /* Stores the alias for the user's mailbox */
|
private String mAlias; /* Stores the alias for the user's mailbox */
|
||||||
private String mPassword; /* Stores the password for authentications */
|
private String mPassword; /* Stores the password for authentications */
|
||||||
private String mUrl; /* Stores the base URL for the server */
|
private String mUrl; /* Stores the base URL for the server */
|
||||||
private String mHost; /* Stores the host name for the server */
|
private String mHost; /* Stores the host name for the server */
|
||||||
private String mPath; /* Stores the path for the server */
|
private String mPath; /* Stores the path for the server */
|
||||||
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;
|
||||||
|
|
||||||
private HashMap<String, WebDavFolder> mFolderList = new HashMap<String, WebDavFolder>();
|
private HashMap<String, WebDavFolder> mFolderList = new HashMap<String, WebDavFolder>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -220,7 +218,7 @@ public class WebDavStore extends Store
|
|||||||
|
|
||||||
if (mPath == null || mPath.equals(""))
|
if (mPath == null || mPath.equals(""))
|
||||||
{
|
{
|
||||||
mPath = "/Exchange";
|
mPath = "/Exchange";
|
||||||
}
|
}
|
||||||
else if (!mPath.startsWith("/"))
|
else if (!mPath.startsWith("/"))
|
||||||
{
|
{
|
||||||
@ -236,11 +234,11 @@ public class WebDavStore extends Store
|
|||||||
mMailboxPath = "/" + mMailboxPath;
|
mMailboxPath = "/" + mMailboxPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mAuthPath != null &&
|
if (mAuthPath != null &&
|
||||||
!mAuthPath.equals("") &&
|
!mAuthPath.equals("") &&
|
||||||
!mAuthPath.startsWith("/"))
|
!mAuthPath.startsWith("/"))
|
||||||
{
|
{
|
||||||
mAuthPath = "/" + mAuthPath;
|
mAuthPath = "/" + mAuthPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The URL typically looks like the following: "https://mail.domain.com/Exchange/alias".
|
// The URL typically looks like the following: "https://mail.domain.com/Exchange/alias".
|
||||||
@ -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();
|
||||||
@ -514,7 +513,7 @@ public class WebDavStore extends Store
|
|||||||
}
|
}
|
||||||
|
|
||||||
// For flag:
|
// For flag:
|
||||||
// http://www.devnewsgroups.net/group/microsoft.public.exchange.development/topic27175.aspx
|
// http://www.devnewsgroups.net/group/microsoft.public.exchange.development/topic27175.aspx
|
||||||
// "<m:0x10900003>1</m:0x10900003>" & _
|
// "<m:0x10900003>1</m:0x10900003>" & _
|
||||||
|
|
||||||
private String getMoveOrCopyMessagesReadXml(String[] urls, boolean isMove)
|
private String getMoveOrCopyMessagesReadXml(String[] urls, boolean isMove)
|
||||||
@ -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
|
||||||
{
|
{
|
||||||
@ -573,7 +573,7 @@ public class WebDavStore extends Store
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new MessagingException("Error with code " + response.getStatusLine().getStatusCode() +
|
throw new MessagingException("Error with code " + response.getStatusLine().getStatusCode() +
|
||||||
" during request processing: " + response.getStatusLine().toString());
|
" during request processing: " + response.getStatusLine().toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (info.requiredAuthType == AUTH_TYPE_FORM_BASED)
|
else if (info.requiredAuthType == AUTH_TYPE_FORM_BASED)
|
||||||
@ -602,20 +602,22 @@ 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:
|
||||||
// https://mail.server.com/Exchange/alias
|
// https://mail.server.com/Exchange/alias
|
||||||
//
|
//
|
||||||
// Possible status codes include:
|
// Possible status codes include:
|
||||||
// 401 - the server uses basic authentication
|
// 401 - the server uses basic authentication
|
||||||
// 30x - the server is trying to redirect us to an OWA login
|
// 30x - the server is trying to redirect us to an OWA login
|
||||||
// 20x - success
|
// 20x - success
|
||||||
//
|
//
|
||||||
// The latter two indicate form-based authentication.
|
// The latter two indicate form-based authentication.
|
||||||
ConnectionInfo info = new ConnectionInfo();
|
ConnectionInfo info = new ConnectionInfo();
|
||||||
@ -637,8 +639,8 @@ public class WebDavStore extends Store
|
|||||||
info.requiredAuthType = AUTH_TYPE_BASIC;
|
info.requiredAuthType = AUTH_TYPE_BASIC;
|
||||||
}
|
}
|
||||||
else if ((info.statusCode >= 200 && info.statusCode < 300) || // Success
|
else if ((info.statusCode >= 200 && info.statusCode < 300) || // Success
|
||||||
(info.statusCode >= 300 && info.statusCode < 400) || // Redirect
|
(info.statusCode >= 300 && info.statusCode < 400) || // Redirect
|
||||||
(info.statusCode == 440)) // Unauthorized
|
(info.statusCode == 440)) // Unauthorized
|
||||||
|
|
||||||
{
|
{
|
||||||
// We will handle all 3 situations the same. First we take an educated
|
// We will handle all 3 situations the same. First we take an educated
|
||||||
@ -668,11 +670,11 @@ public class WebDavStore extends Store
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new IOException("Error with code " + info.statusCode + " during request processing: "+
|
throw new IOException("Error with code " + info.statusCode + " during request processing: " +
|
||||||
response.getStatusLine().toString());
|
response.getStatusLine().toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(IOException ioe)
|
catch (IOException ioe)
|
||||||
{
|
{
|
||||||
Log.e(K9.LOG_TAG, "IOException: " + ioe + "\nTrace: " + processException(ioe));
|
Log.e(K9.LOG_TAG, "IOException: " + ioe + "\nTrace: " + processException(ioe));
|
||||||
throw new MessagingException("IOException", ioe);
|
throw new MessagingException("IOException", ioe);
|
||||||
@ -683,15 +685,17 @@ 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();
|
||||||
|
|
||||||
WebDavHttpClient httpClient = getHttpClient();
|
WebDavHttpClient httpClient = getHttpClient();
|
||||||
|
|
||||||
String loginUrl = "";
|
String loginUrl = "";
|
||||||
if (info != null)
|
if (info != null)
|
||||||
{
|
{
|
||||||
@ -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() +
|
loginUrl = info.redirectUrl;
|
||||||
request.getRequestLine().getUri();
|
|
||||||
|
request = new HttpGeneric(loginUrl);
|
||||||
|
request.setMethod("GET");
|
||||||
|
|
||||||
|
response = httpClient.executeOverride(request, mContext);
|
||||||
|
formAction = findFormAction(WebDavHttpClient.getUngzippedContent(response.getEntity()));
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
if (info != null)
|
|
||||||
{
|
|
||||||
loginUrl = info.redirectUrl;
|
|
||||||
}
|
}
|
||||||
else if (mRedirectUrl != null && !mRedirectUrl.equals(""))
|
if (formAction != null)
|
||||||
{
|
{
|
||||||
loginUrl = mRedirectUrl;
|
try
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new MessagingException("No valid login URL available for form-based authentication.");
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
InputStream istream = sendRequest(loginUrl, "GET", null, null, false);
|
|
||||||
if (istream != null)
|
|
||||||
{
|
{
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(istream), 4096);
|
URI formActionUri = new URI(formAction);
|
||||||
String tempText = "";
|
URI loginUri = new URI(loginUrl);
|
||||||
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
|
|
||||||
{
|
|
||||||
loginUrl = getRoot() + tagParts[1];
|
|
||||||
this.mAuthPath = new URI(loginUrl).getPath();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
istream.close();
|
else
|
||||||
|
{
|
||||||
|
// Append the form action to our current URL, minus the file name.
|
||||||
|
String urlPath = loginUri.getPath();
|
||||||
|
int lastPathPos = urlPath.lastIndexOf('/');
|
||||||
|
if (lastPathPos > -1)
|
||||||
|
{
|
||||||
|
urlPath = urlPath.substring(0, lastPathPos + 1);
|
||||||
|
urlPath = urlPath.concat(formAction);
|
||||||
|
}
|
||||||
|
|
||||||
// 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)
|
||||||
|
{
|
||||||
|
Log.e(K9.LOG_TAG, "URISyntaxException caught " + e + "\nTrace: " + processException(e));
|
||||||
|
throw new MessagingException("URISyntaxException caught", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch(URISyntaxException use)
|
else
|
||||||
{
|
{
|
||||||
throw new MessagingException("An invalid login URL was detected: " + loginUrl);
|
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,
|
||||||
throws MessagingException
|
HashMap<String, String> headers, boolean tryAuth)
|
||||||
|
throws MessagingException
|
||||||
{
|
{
|
||||||
InputStream istream = null;
|
InputStream istream = null;
|
||||||
|
|
||||||
if (url == null ||
|
if (url == null || method == null)
|
||||||
method == null)
|
|
||||||
{
|
{
|
||||||
return istream;
|
return istream;
|
||||||
}
|
}
|
||||||
@ -885,9 +925,12 @@ public class WebDavStore extends Store
|
|||||||
httpmethod.setEntity(messageBody);
|
httpmethod.setEntity(messageBody);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (String headerName : headers.keySet())
|
if (headers != null)
|
||||||
{
|
{
|
||||||
httpmethod.setHeader(headerName, headers.get(headerName));
|
for (String headerName : headers.keySet())
|
||||||
|
{
|
||||||
|
httpmethod.setHeader(headerName, headers.get(headerName));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mAuthentication == AUTH_TYPE_NONE)
|
if (mAuthentication == AUTH_TYPE_NONE)
|
||||||
@ -928,7 +971,7 @@ public class WebDavStore extends Store
|
|||||||
else if (statusCode < 200 || statusCode >= 300)
|
else if (statusCode < 200 || statusCode >= 300)
|
||||||
{
|
{
|
||||||
throw new IOException("Error with code " + statusCode + " during request processing: " +
|
throw new IOException("Error with code " + statusCode + " during request processing: " +
|
||||||
response.getStatusLine().toString());
|
response.getStatusLine().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entity != null)
|
if (entity != null)
|
||||||
@ -956,23 +999,25 @@ 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
|
||||||
{
|
{
|
||||||
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,
|
||||||
throws MessagingException
|
boolean needsParsing)
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1059,7 +1105,7 @@ public class WebDavStore extends Store
|
|||||||
@Override
|
@Override
|
||||||
public void sendMessages(Message[] messages) throws MessagingException
|
public void sendMessages(Message[] messages) throws MessagingException
|
||||||
{
|
{
|
||||||
WebDavFolder tmpFolder = (WebDavStore.WebDavFolder)getFolder(DAV_MAIL_TMP_FOLDER);
|
WebDavFolder tmpFolder = (WebDavStore.WebDavFolder) getFolder(DAV_MAIL_TMP_FOLDER);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
tmpFolder.open(OpenMode.READ_WRITE);
|
tmpFolder.open(OpenMode.READ_WRITE);
|
||||||
@ -1105,7 +1151,7 @@ public class WebDavStore extends Store
|
|||||||
|
|
||||||
if (DAV_MAIL_SEND_FOLDER.equals(name))
|
if (DAV_MAIL_SEND_FOLDER.equals(name))
|
||||||
{
|
{
|
||||||
this.mFolderUrl = getUrl() + "/" + name +"/";
|
this.mFolderUrl = getUrl() + "/" + name + "/";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1136,12 +1182,12 @@ 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();
|
||||||
|
|
||||||
if (encodedName.equals("INBOX"))
|
if (encodedName.equals("INBOX"))
|
||||||
{
|
{
|
||||||
@ -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];
|
||||||
|
|
||||||
@ -1207,13 +1255,13 @@ public class WebDavStore extends Store
|
|||||||
urls[i] = uidToUrl.get(uids[i]);
|
urls[i] = uidToUrl.get(uids[i]);
|
||||||
if (urls[i] == null && messages[i] instanceof WebDavMessage)
|
if (urls[i] == null && messages[i] instanceof WebDavMessage)
|
||||||
{
|
{
|
||||||
WebDavMessage wdMessage = (WebDavMessage)messages[i];
|
WebDavMessage wdMessage = (WebDavMessage) messages[i];
|
||||||
urls[i] = wdMessage.getUrl();
|
urls[i] = wdMessage.getUrl();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
messageBody = getMoveOrCopyMessagesReadXml(urls, isMove);
|
messageBody = getMoveOrCopyMessagesReadXml(urls, isMove);
|
||||||
WebDavFolder destFolder = (WebDavFolder)store.getFolder(folderName);
|
WebDavFolder destFolder = (WebDavFolder) store.getFolder(folderName);
|
||||||
headers.put("Destination", destFolder.mFolderUrl);
|
headers.put("Destination", destFolder.mFolderUrl);
|
||||||
headers.put("Brief", "t");
|
headers.put("Brief", "t");
|
||||||
headers.put("If-Match", "*");
|
headers.put("If-Match", "*");
|
||||||
@ -1325,7 +1373,7 @@ public class WebDavStore extends Store
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Message[] getMessages(int start, int end, Date earliestDate, MessageRetrievalListener listener)
|
public Message[] getMessages(int start, int end, Date earliestDate, MessageRetrievalListener listener)
|
||||||
throws MessagingException
|
throws MessagingException
|
||||||
{
|
{
|
||||||
ArrayList<Message> messages = new ArrayList<Message>();
|
ArrayList<Message> messages = new ArrayList<Message>();
|
||||||
String[] uids;
|
String[] uids;
|
||||||
@ -1437,7 +1485,7 @@ public class WebDavStore extends Store
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fetch(Message[] messages, FetchProfile fp, MessageRetrievalListener listener)
|
public void fetch(Message[] messages, FetchProfile fp, MessageRetrievalListener listener)
|
||||||
throws MessagingException
|
throws MessagingException
|
||||||
{
|
{
|
||||||
if (messages == null ||
|
if (messages == null ||
|
||||||
messages.length == 0)
|
messages.length == 0)
|
||||||
@ -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;
|
||||||
@ -1535,7 +1585,7 @@ public class WebDavStore extends Store
|
|||||||
statusCode > 300)
|
statusCode > 300)
|
||||||
{
|
{
|
||||||
throw new IOException("Error during with code " + statusCode + " during fetch: "
|
throw new IOException("Error during with code " + statusCode + " during fetch: "
|
||||||
+ response.getStatusLine().toString());
|
+ response.getStatusLine().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entity != null)
|
if (entity != null)
|
||||||
@ -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>();
|
||||||
@ -1762,7 +1813,7 @@ public class WebDavStore extends Store
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setFlags(Message[] messages, Flag[] flags, boolean value)
|
public void setFlags(Message[] messages, Flag[] flags, boolean value)
|
||||||
throws MessagingException
|
throws MessagingException
|
||||||
{
|
{
|
||||||
String[] uids = new String[messages.length];
|
String[] uids = new String[messages.length];
|
||||||
|
|
||||||
@ -1867,7 +1918,7 @@ public class WebDavStore extends Store
|
|||||||
|
|
||||||
open(OpenMode.READ_WRITE);
|
open(OpenMode.READ_WRITE);
|
||||||
EOLConvertingOutputStream msgOut = new EOLConvertingOutputStream(
|
EOLConvertingOutputStream msgOut = new EOLConvertingOutputStream(
|
||||||
new BufferedOutputStream(out, 1024));
|
new BufferedOutputStream(out, 1024));
|
||||||
message.writeTo(msgOut);
|
message.writeTo(msgOut);
|
||||||
msgOut.flush();
|
msgOut.flush();
|
||||||
|
|
||||||
@ -1901,8 +1952,8 @@ public class WebDavStore extends Store
|
|||||||
statusCode > 300)
|
statusCode > 300)
|
||||||
{
|
{
|
||||||
throw new IOException("Error with status code " + statusCode
|
throw new IOException("Error with status code " + statusCode
|
||||||
+ " while sending/appending message. Response = "
|
+ " while sending/appending message. Response = "
|
||||||
+ response.getStatusLine().toString() + " for message " + messageURL);
|
+ response.getStatusLine().toString() + " for message " + messageURL);
|
||||||
}
|
}
|
||||||
WebDavMessage retMessage = new WebDavMessage(message.getUid(), this);
|
WebDavMessage retMessage = new WebDavMessage(message.getUid(), this);
|
||||||
|
|
||||||
@ -1932,15 +1983,17 @@ 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,
|
||||||
+ " being uploaded to the Sent folder");
|
"Unimplemented method getUidFromMessageId in WebDavStore.WebDavFolder could lead to duplicate messages "
|
||||||
|
+ " being uploaded to the Sent folder");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@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;
|
||||||
@ -1961,8 +2013,8 @@ public class WebDavStore extends Store
|
|||||||
|
|
||||||
public void setUrl(String url)
|
public void setUrl(String url)
|
||||||
{
|
{
|
||||||
//TODO: This is a not as ugly hack (ie, it will actually work)
|
// TODO: This is a not as ugly hack (ie, it will actually work)
|
||||||
//XXX: prevent URLs from getting to us that are broken
|
// XXX: prevent URLs from getting to us that are broken
|
||||||
if (!(url.toLowerCase().contains("http")))
|
if (!(url.toLowerCase().contains("http")))
|
||||||
{
|
{
|
||||||
if (!(url.startsWith("/")))
|
if (!(url.startsWith("/")))
|
||||||
@ -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++)
|
||||||
@ -2061,7 +2114,7 @@ public class WebDavStore extends Store
|
|||||||
@Override
|
@Override
|
||||||
public void delete(String trashFolderName) throws MessagingException
|
public void delete(String trashFolderName) throws MessagingException
|
||||||
{
|
{
|
||||||
WebDavFolder wdFolder = (WebDavFolder)getFolder();
|
WebDavFolder wdFolder = (WebDavFolder) getFolder();
|
||||||
Log.i(K9.LOG_TAG, "Deleting message by moving to " + trashFolderName);
|
Log.i(K9.LOG_TAG, "Deleting message by moving to " + trashFolderName);
|
||||||
wdFolder.moveMessages(new Message[] { this }, wdFolder.getStore().getFolder(trashFolderName));
|
wdFolder.moveMessages(new Message[] { this }, wdFolder.getStore().getFolder(trashFolderName));
|
||||||
}
|
}
|
||||||
@ -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
|
||||||
{
|
{
|
||||||
@ -2102,7 +2154,7 @@ public class WebDavStore extends Store
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startElement(String namespaceURI, String localName,
|
public void startElement(String namespaceURI, String localName,
|
||||||
String qName, Attributes atts) throws SAXException
|
String qName, Attributes atts) throws SAXException
|
||||||
{
|
{
|
||||||
mOpenTags.push(localName);
|
mOpenTags.push(localName);
|
||||||
}
|
}
|
||||||
@ -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
|
||||||
@ -2139,7 +2190,7 @@ public class WebDavStore extends Store
|
|||||||
* Holds the mappings from the name returned from Exchange to the MIME format header name
|
* Holds the mappings from the name returned from Exchange to the MIME format header name
|
||||||
*/
|
*/
|
||||||
private final HashMap<String, String> mHeaderMappings = new HashMap<String, String>()
|
private final HashMap<String, String> mHeaderMappings = new HashMap<String, String>()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
put("mime-version", "MIME-Version");
|
put("mime-version", "MIME-Version");
|
||||||
put("content-type", "Content-Type");
|
put("content-type", "Content-Type");
|
||||||
@ -2206,13 +2257,13 @@ 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
|
||||||
{
|
{
|
||||||
private HashMap<String, HashMap<String, String>> mData = new HashMap<String, HashMap<String, String>>();
|
private HashMap<String, HashMap<String, String>> mData = new HashMap<String, HashMap<String, String>>();
|
||||||
//private HashMap<String, String> mLostData = new HashMap<String, String>();
|
// private HashMap<String, String> mLostData = new HashMap<String, String>();
|
||||||
private String mUid = "";
|
private String mUid = "";
|
||||||
private HashMap<String, String> mTempData = new HashMap<String, String>();
|
private HashMap<String, String> mTempData = new HashMap<String, String>();
|
||||||
|
|
||||||
@ -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.
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2375,8 +2427,9 @@ public class WebDavStore extends Store
|
|||||||
else if (header.equals("date"))
|
else if (header.equals("date"))
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* 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);
|
||||||
@ -2392,7 +2445,7 @@ public class WebDavStore extends Store
|
|||||||
}
|
}
|
||||||
catch (java.text.ParseException pe)
|
catch (java.text.ParseException pe)
|
||||||
{
|
{
|
||||||
Log.e(K9.LOG_TAG, "Error parsing date: "+ pe + "\nTrace: " + processException(pe));
|
Log.e(K9.LOG_TAG, "Error parsing date: " + pe + "\nTrace: " + processException(pe));
|
||||||
}
|
}
|
||||||
envelope.addHeader(header, tempDate);
|
envelope.addHeader(header, tempDate);
|
||||||
}
|
}
|
||||||
@ -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++)
|
||||||
@ -2485,7 +2540,7 @@ public class WebDavStore extends Store
|
|||||||
if (K9.DEBUG && K9.DEBUG_PROTOCOL_WEBDAV)
|
if (K9.DEBUG && K9.DEBUG_PROTOCOL_WEBDAV)
|
||||||
{
|
{
|
||||||
Log.v(K9.LOG_TAG, "url = '" + url + "' length = " + url.length()
|
Log.v(K9.LOG_TAG, "url = '" + url + "' length = " + url.length()
|
||||||
+ ", end = '" + end + "' length = " + end.length());
|
+ ", end = '" + end + "' length = " + end.length());
|
||||||
}
|
}
|
||||||
url = url + "/" + end;
|
url = url + "/" + end;
|
||||||
|
|
||||||
@ -2511,20 +2566,17 @@ public class WebDavStore extends Store
|
|||||||
public static class WebDavHttpClient extends DefaultHttpClient
|
public static class WebDavHttpClient extends DefaultHttpClient
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* 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 distributed under the License is
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* the License for the specific language governing permissions and limitations under the License.
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
public static void modifyRequestToAcceptGzipResponse(HttpRequest request)
|
public static void modifyRequestToAcceptGzipResponse(HttpRequest request)
|
||||||
{
|
{
|
||||||
Log.i(K9.LOG_TAG, "Requesting gzipped data");
|
Log.i(K9.LOG_TAG, "Requesting gzipped data");
|
||||||
@ -2532,14 +2584,17 @@ public class WebDavStore extends Store
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static InputStream getUngzippedContent(HttpEntity entity)
|
public static InputStream getUngzippedContent(HttpEntity entity)
|
||||||
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");
|
||||||
@ -2549,7 +2604,7 @@ public class WebDavStore extends Store
|
|||||||
}
|
}
|
||||||
|
|
||||||
public HttpResponse executeOverride(HttpUriRequest request, HttpContext context)
|
public HttpResponse executeOverride(HttpUriRequest request, HttpContext context)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
modifyRequestToAcceptGzipResponse(request);
|
modifyRequestToAcceptGzipResponse(request);
|
||||||
return super.execute(request, context);
|
return super.execute(request, context);
|
||||||
|
Loading…
Reference in New Issue
Block a user