Fix problem with unencoded data in URI sent to EAS
* We need to encode the itemId and collectionId for SmartForward and SmartReply * Add unit test for the fix * Small change + test to EasSyncService usage of URI encoding to use a non-deprecated method Bug: 2787725 Change-Id: I428b308b56cc359b8cdd9e42bc3f42c65b6797dc
This commit is contained in:
parent
8d8f86e899
commit
51f5b2f3fa
@ -36,6 +36,7 @@ import android.content.ContentUris;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import java.io.File;
|
||||
@ -71,6 +72,11 @@ public class EasOutboxService extends EasSyncService {
|
||||
}
|
||||
}
|
||||
|
||||
/*package*/ String generateSmartSendCmd(boolean reply, String itemId, String collectionId) {
|
||||
return (reply ? "SmartReply" : "SmartForward") + "&ItemId=" + Uri.encode(itemId) +
|
||||
"&CollectionId=" + Uri.encode(collectionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a single message via EAS
|
||||
* Note that we mark messages SEND_FAILED when there is a permanent failure, rather than an
|
||||
@ -130,11 +136,12 @@ public class EasOutboxService extends EasSyncService {
|
||||
new InputStreamEntity(inputStream, tmpFile.length());
|
||||
|
||||
// Create the appropriate command and POST it to the server
|
||||
String cmd = "SendMail&SaveInSent=T";
|
||||
String cmd = "SendMail";
|
||||
if (smartSend) {
|
||||
cmd = reply ? "SmartReply" : "SmartForward";
|
||||
cmd += "&ItemId=" + itemId + "&CollectionId=" + collectionId + "&SaveInSent=T";
|
||||
cmd = generateSmartSendCmd(reply, itemId, collectionId);
|
||||
}
|
||||
cmd += "&SaveInSent=T";
|
||||
|
||||
userLog("Send cmd: " + cmd);
|
||||
HttpResponse resp = sendHttpClientPost(cmd, inputEntity, SEND_MAIL_TIMEOUT);
|
||||
|
||||
|
@ -77,6 +77,7 @@ import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.Entity;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
@ -94,7 +95,6 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.Thread.State;
|
||||
import java.net.URI;
|
||||
import java.net.URLEncoder;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@ -185,7 +185,7 @@ public class EasSyncService extends AbstractSyncService {
|
||||
protected String mDeviceId = null;
|
||||
/*package*/ String mDeviceType = "Android";
|
||||
/*package*/ String mAuthString = null;
|
||||
private String mCmdString = null;
|
||||
/*package*/ String mCmdString = null;
|
||||
public String mHostAddress;
|
||||
public String mUserName;
|
||||
public String mPassword;
|
||||
@ -1099,17 +1099,16 @@ public class EasSyncService extends AbstractSyncService {
|
||||
* in all HttpPost commands. This should be called if these strings are null, or if mUserName
|
||||
* and/or mPassword are changed
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private void cacheAuthAndCmdString() {
|
||||
String safeUserName = URLEncoder.encode(mUserName);
|
||||
String safeUserName = Uri.encode(mUserName);
|
||||
String cs = mUserName + ':' + mPassword;
|
||||
mAuthString = "Basic " + Base64.encodeToString(cs.getBytes(), Base64.NO_WRAP);
|
||||
mCmdString = "&User=" + safeUserName + "&DeviceId=" + mDeviceId +
|
||||
"&DeviceType=" + mDeviceType;
|
||||
}
|
||||
|
||||
private String makeUriString(String cmd, String extra) throws IOException {
|
||||
// Cache the authentication string and the command string
|
||||
/*package*/ String makeUriString(String cmd, String extra) throws IOException {
|
||||
// Cache the authentication string and the command string
|
||||
if (mAuthString == null || mCmdString == null) {
|
||||
cacheAuthAndCmdString();
|
||||
}
|
||||
|
48
tests/src/com/android/exchange/EasOutboxServiceTests.java
Normal file
48
tests/src/com/android/exchange/EasOutboxServiceTests.java
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.exchange;
|
||||
|
||||
import com.android.email.provider.EmailContent.Mailbox;
|
||||
|
||||
import android.content.Context;
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
/**
|
||||
* You can run this entire test case with:
|
||||
* runtest -c com.android.exchange.EasOutboxServiceTests email
|
||||
*/
|
||||
|
||||
public class EasOutboxServiceTests extends AndroidTestCase {
|
||||
|
||||
Context mMockContext;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
mMockContext = getContext();
|
||||
}
|
||||
|
||||
public void testGenerateSmartSendCmd() {
|
||||
EasOutboxService svc = new EasOutboxService(mMockContext, new Mailbox());
|
||||
// Test encoding of collection id
|
||||
String cmd = svc.generateSmartSendCmd(true, "1339085683659694034", "Mail:^f");
|
||||
assertEquals("SmartReply&ItemId=1339085683659694034&CollectionId=Mail%3A%5Ef", cmd);
|
||||
// Test encoding of item id
|
||||
cmd = svc.generateSmartSendCmd(false, "14:3", "6");
|
||||
assertEquals("SmartForward&ItemId=14%3A3&CollectionId=6", cmd);
|
||||
}
|
||||
}
|
@ -25,6 +25,7 @@ import org.apache.http.client.methods.HttpRequestBase;
|
||||
|
||||
import android.content.Context;
|
||||
import android.test.AndroidTestCase;
|
||||
import android.util.Base64;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -35,6 +36,12 @@ import java.io.IOException;
|
||||
*/
|
||||
|
||||
public class EasSyncServiceTests extends AndroidTestCase {
|
||||
static private final String USER = "user";
|
||||
static private final String PASSWORD = "password";
|
||||
static private final String HOST = "xxx.host.zzz";
|
||||
static private final String ID = "id";
|
||||
static private final String TYPE = "type";
|
||||
|
||||
Context mMockContext;
|
||||
|
||||
@Override
|
||||
@ -130,4 +137,39 @@ public class EasSyncServiceTests extends AndroidTestCase {
|
||||
assertEquals(Eas.SUPPORTED_PROTOCOL_EX2007_SP1_DOUBLE,
|
||||
Eas.getProtocolVersionDouble(Eas.SUPPORTED_PROTOCOL_EX2007_SP1));
|
||||
}
|
||||
|
||||
private EasSyncService setupService(String user) {
|
||||
EasSyncService svc = new EasSyncService();
|
||||
svc.mUserName = user;
|
||||
svc.mPassword = PASSWORD;
|
||||
svc.mDeviceId = ID;
|
||||
svc.mDeviceType = TYPE;
|
||||
svc.mHostAddress = HOST;
|
||||
return svc;
|
||||
}
|
||||
|
||||
public void testMakeUriString() throws IOException {
|
||||
// Simple user name and command
|
||||
EasSyncService svc = setupService(USER);
|
||||
String uriString = svc.makeUriString("OPTIONS", null);
|
||||
// These next two should now be cached
|
||||
assertNotNull(svc.mAuthString);
|
||||
assertNotNull(svc.mCmdString);
|
||||
assertEquals("Basic " + Base64.encodeToString((USER+":"+PASSWORD).getBytes(),
|
||||
Base64.NO_WRAP), svc.mAuthString);
|
||||
assertEquals("&User=" + USER + "&DeviceId=" + ID + "&DeviceType=" + TYPE, svc.mCmdString);
|
||||
assertEquals("https://" + HOST + "/Microsoft-Server-ActiveSync?Cmd=OPTIONS" +
|
||||
svc.mCmdString, uriString);
|
||||
// User name that requires encoding
|
||||
String user = "name_with_underscore@foo%bar.com";
|
||||
svc = setupService(user);
|
||||
uriString = svc.makeUriString("OPTIONS", null);
|
||||
assertEquals("Basic " + Base64.encodeToString((user+":"+PASSWORD).getBytes(),
|
||||
Base64.NO_WRAP), svc.mAuthString);
|
||||
String safeUserName = "name_with_underscore%40foo%25bar.com";
|
||||
assertEquals("&User=" + safeUserName + "&DeviceId=" + ID + "&DeviceType=" + TYPE,
|
||||
svc.mCmdString);
|
||||
assertEquals("https://" + HOST + "/Microsoft-Server-ActiveSync?Cmd=OPTIONS" +
|
||||
svc.mCmdString, uriString);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user