issue#964 Extract code to decode mailto URIs

This commit is contained in:
Swapnil Tailor 2016-01-05 22:41:16 -08:00
parent 69590af824
commit a6ab976ac9
4 changed files with 295 additions and 44 deletions

View file

@ -0,0 +1,130 @@
package com.fsck.k9.helper;
import android.net.Uri;
import android.support.test.runner.AndroidJUnit4;
import com.fsck.k9.mail.Address;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.Arrays;
import java.util.List;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertEquals;
@RunWith(AndroidJUnit4.class)
public class MailToTest {
@Test
public void testIsMailTo_validMailToURI() {
Uri uri = Uri.parse("mailto:nobody");
boolean result = MailTo.isMailTo(uri);
assertTrue(result);
}
@Test
public void testIsMailTo_invalidMailToUri() {
Uri uri = Uri.parse("mailto1:nobody");
boolean result = MailTo.isMailTo(uri);
assertFalse(result);
}
@Test
public void testGetTo_singleEmailAddress() {
Uri uri = Uri.parse("mailto:test@abc.com");
MailTo mailToHelper = MailTo.parse(uri);
Address[] emailAddressList = mailToHelper.getTo();
assertEquals(emailAddressList[0].getAddress(), "test@abc.com");
}
@Test
public void testGetTo_multipleEmailAddress() {
Uri uri = Uri.parse("mailto:test1@abc.com?to=test2@abc.com");
MailTo mailToHelper = MailTo.parse(uri);
Address[] emailAddressList = mailToHelper.getTo();
assertEquals(emailAddressList[0].getAddress(), "test1@abc.com");
assertEquals(emailAddressList[1].getAddress(), "test2@abc.com");
}
@Test
public void testGetCc_singleEmailAddress() {
Uri uri = Uri.parse("mailto:test1@abc.com?to=test2@abc.com&cc=test3@abc.com");
MailTo mailToHelper = MailTo.parse(uri);
Address[] emailAddressList = mailToHelper.getCc();
assertEquals(emailAddressList[0].getAddress(), "test3@abc.com");
}
@Test
public void testGetCc_multipleEmailAddress() {
Uri uri = Uri.parse("mailto:test1@abc.com?to=test2@abc.com&cc=test3@abc.com,test4@abc.com");
MailTo mailToHelper = MailTo.parse(uri);
Address[] emailAddressList = mailToHelper.getCc();
assertEquals(emailAddressList[0].getAddress(), "test3@abc.com");
assertEquals(emailAddressList[1].getAddress(), "test4@abc.com");
}
@Test
public void testGetBcc_singleEmailAddress() {
Uri uri = Uri.parse("mailto:test1@abc.com?to=test2@abc.com&bcc=test3@abc.com");
MailTo mailToHelper = MailTo.parse(uri);
Address[] emailAddressList = mailToHelper.getBcc();
assertEquals(emailAddressList[0].getAddress(), "test3@abc.com");
}
@Test
public void testGetBcc_multipleEmailAddress() {
Uri uri = Uri.parse("mailto:test1@abc.com?to=test2@abc.com&bcc=test3@abc.com,test4@abc.com");
MailTo mailToHelper = MailTo.parse(uri);
Address[] emailAddressList = mailToHelper.getBcc();
assertEquals(emailAddressList[0].getAddress(), "test3@abc.com");
assertEquals(emailAddressList[1].getAddress(), "test4@abc.com");
}
@Test
public void testGetSubject() {
Uri uri = Uri.parse("mailto:test1@abc.com?to=test2@abc.com&cc=test3@abc.com&subject=Hello");
MailTo mailToHelper = MailTo.parse(uri);
String subject = mailToHelper.getSubject();
assertEquals(subject, "Hello");
}
@Test
public void testGetBody() {
Uri uri = Uri.parse("mailto:test1@abc.com?to=test2@abc.com&cc=test3@abc.com&subject=Hello&body=Test Body");
MailTo mailToHelper = MailTo.parse(uri);
String subject = mailToHelper.getBody();
assertEquals(subject, "Test Body");
}
@Test
public void testCaseInsensitiveParamWrapper() {
Uri uri = Uri.parse("mailto:test1@abc.com?to=test2@abc.com&cc=test3@abc.com&subject=Hello&body=Test Body");
MailTo.CaseInsensitiveParamWrapper caseInsensitiveParamWrapper = new MailTo.CaseInsensitiveParamWrapper(
Uri.parse("foo://bar?" + uri.getEncodedQuery()));
List<String> actualTo = caseInsensitiveParamWrapper.getQueryParameters("to");
List<String> expectedTo = Arrays.asList(new String[]{"test2@abc.com"});
}
}

View file

@ -85,6 +85,7 @@ import com.fsck.k9.fragment.ProgressDialogFragment.CancelListener;
import com.fsck.k9.helper.Contacts;
import com.fsck.k9.helper.HtmlConverter;
import com.fsck.k9.helper.IdentityHelper;
import com.fsck.k9.helper.MailTo;
import com.fsck.k9.helper.SimpleTextWatcher;
import com.fsck.k9.helper.Utility;
import com.fsck.k9.mail.Address;
@ -815,8 +816,9 @@ public class MessageCompose extends K9Activity implements OnClickListener,
*/
if (intent.getData() != null) {
Uri uri = intent.getData();
if ("mailto".equals(uri.getScheme())) {
initializeFromMailto(uri);
if (MailTo.isMailTo(uri)) {
MailTo mailTo = MailTo.parse(uri);
initializeFromMailto(mailTo);
}
}
@ -2795,32 +2797,30 @@ public class MessageCompose extends K9Activity implements OnClickListener,
* When we are launched with an intent that includes a mailto: URI, we can actually
* gather quite a few of our message fields from it.
*
* @param mailtoUri
* The mailto: URI we use to initialize the message fields.
* @param mailTo
* The MailTo object we use to initialize message field
*/
private void initializeFromMailto(Uri mailtoUri) {
/*
* mailto URIs are not hierarchical. So calling getQueryParameters()
* will throw an UnsupportedOperationException. We avoid this by
* creating a new hierarchical dummy Uri object with the query
* parameters of the original URI.
*/
CaseInsensitiveParamWrapper uri = new CaseInsensitiveParamWrapper(
Uri.parse("foo://bar?" + mailtoUri.getEncodedQuery()));
private void initializeFromMailto(MailTo mailTo) {
recipientPresenter.initFromMailto(mailtoUri, uri);
Address[] toList = mailTo.getTo();
// Read subject from the "subject" parameter.
List<String> subject = uri.getQueryParameters("subject");
if (!subject.isEmpty()) {
mSubjectView.setText(subject.get(0));
Address[] ccList = mailTo.getCc();
Address[] bccList = mailTo.getBcc();
recipientPresenter.initFromMailto(toList, ccList, bccList);
String subject = mailTo.getSubject();
if (subject != null && !subject.isEmpty()) {
mSubjectView.setText(subject);
}
// Read message body from the "body" parameter.
List<String> body = uri.getQueryParameters("body");
if (!body.isEmpty()) {
mMessageContentView.setCharacters(body.get(0));
String body = mailTo.getBody();
if (body != null && !subject.isEmpty()) {
mMessageContentView.setCharacters(body);
}
}
static class CaseInsensitiveParamWrapper {

View file

@ -17,7 +17,6 @@ import android.view.Menu;
import com.fsck.k9.Account;
import com.fsck.k9.Identity;
import com.fsck.k9.R;
import com.fsck.k9.activity.MessageCompose.CaseInsensitiveParamWrapper;
import com.fsck.k9.activity.RecipientMvpView.CryptoStatusType;
import com.fsck.k9.helper.Contacts;
import com.fsck.k9.helper.Utility;
@ -158,29 +157,12 @@ public class RecipientPresenter {
}
}
public void initFromMailto(Uri mailtoUri, CaseInsensitiveParamWrapper uri) {
String schemaSpecific = mailtoUri.getSchemeSpecificPart();
int end = schemaSpecific.indexOf('?');
if (end == -1) {
end = schemaSpecific.length();
}
public void initFromMailto(Address[] toList, Address[] ccList, Address[] bccList) {
addToAddresses(toList);
// Extract the recipient's email address from the mailto URI if there's one.
String recipient = Uri.decode(schemaSpecific.substring(0, end));
addCcAddresses(ccList);
// Read additional recipients from the "to" parameter.
List<String> to = uri.getQueryParameters("to");
if (recipient.length() != 0) {
to = new ArrayList<String>(to);
to.add(0, recipient);
}
addToAddresses(addressFromStringArray(to));
// Read carbon copy recipients from the "cc" parameter.
addCcAddresses(addressFromStringArray(uri.getQueryParameters("cc")));
// Read blind carbon copy recipients from the "bcc" parameter.
addBccAddresses(addressFromStringArray(uri.getQueryParameters("bcc")));
addBccAddresses(bccList);
}
public void initFromSendOrViewIntent(Intent intent) {

View file

@ -0,0 +1,139 @@
package com.fsck.k9.helper;
import android.net.Uri;
import com.fsck.k9.mail.Address;
import java.util.ArrayList;
import java.util.List;
public class MailTo {
static public final String MAILTO_SCHEME = "mailto";
private final Address[] toAddresses;
private final Address[] ccAddresses;
private final Address[] bccAddresses;
private final String subject;
private final String body;
// Well known headers
static private final String TO = "to";
static private final String BODY = "body";
static private final String CC = "cc";
static private final String BCC = "bcc";
static private final String SUBJECT = "subject";
public static boolean isMailTo(Uri uri) {
if (uri == null) {
return false;
}
return MAILTO_SCHEME.equals(uri.getScheme());
}
public static MailTo parse(Uri uri) throws NullPointerException, IllegalArgumentException {
if (uri == null || uri.toString() == null) {
throw new NullPointerException();
}
if (!isMailTo(uri)) {
throw new IllegalArgumentException("Not a mail to scheme");
}
String schemaSpecific = uri.getSchemeSpecificPart();
int end = schemaSpecific.indexOf('?');
if (end == -1) {
end = schemaSpecific.length();
}
CaseInsensitiveParamWrapper caseInsensitiveParamWrapper = new CaseInsensitiveParamWrapper(
Uri.parse("foo://bar?" + uri.getEncodedQuery()));
// Extract the recipient's email address from the mailto URI if there's one.
String recipient = Uri.decode(schemaSpecific.substring(0, end));
// Read additional recipients from the "to" parameter.
List<String> toList = caseInsensitiveParamWrapper.getQueryParameters(TO);
if (recipient.length() != 0) {
toList = new ArrayList<String>(toList);
toList.add(0, recipient);
}
List<String> ccList = caseInsensitiveParamWrapper.getQueryParameters(CC);
List<String> bccList = caseInsensitiveParamWrapper.getQueryParameters(BCC);
List<String> subjectList = caseInsensitiveParamWrapper.getQueryParameters(SUBJECT);
String subject = null;
if (!subjectList.isEmpty()) {
subject = subjectList.get(0);
}
List<String> bodyList = caseInsensitiveParamWrapper.getQueryParameters(BODY);
String body = null;
if (!bodyList.isEmpty()) {
body = bodyList.get(0);
}
return new MailTo(listToCommaSeperatedString(toList), listToCommaSeperatedString(ccList), listToCommaSeperatedString(bccList), subject, body);
}
private MailTo(String toAddresses, String ccAddresses, String bccAddresses, String subject, String body) {
this.toAddresses = Address.parseUnencoded(toAddresses);
this.ccAddresses = Address.parseUnencoded(ccAddresses);
this.bccAddresses = Address.parseUnencoded(bccAddresses);
this.subject = subject;
this.body = body;
}
private static String listToCommaSeperatedString(List<String> listStr) {
StringBuilder strBuilder = new StringBuilder();
String sep = "";
for (String str : listStr) {
strBuilder.append(sep).append(str);
sep = ",";
}
return strBuilder.toString();
}
static class CaseInsensitiveParamWrapper {
private final Uri uri;
public CaseInsensitiveParamWrapper(Uri uri) {
this.uri = uri;
}
public List<String> getQueryParameters(String key) {
final List<String> params = new ArrayList<String>();
for (String paramName : uri.getQueryParameterNames()) {
if (paramName.equalsIgnoreCase(key)) {
params.addAll(uri.getQueryParameters(paramName));
}
}
return params;
}
}
public Address[] getTo() {
return toAddresses;
}
public Address[] getCc() {
return ccAddresses;
}
public Address[] getBcc() {
return bccAddresses;
}
public String getSubject() {
return subject;
}
public String getBody() {
return body;
}
}