19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.net; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Set; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * MailTo URL parser 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This class parses a mailto scheme URL and then can be queried for 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the parsed parameters. This implements RFC 2368. 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class MailTo { 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static public final String MAILTO_SCHEME = "mailto:"; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // All the parsed content is added to the headers. 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private HashMap<String, String> mHeaders; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Well known headers 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static private final String TO = "to"; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static private final String BODY = "body"; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static private final String CC = "cc"; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static private final String SUBJECT = "subject"; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Test to see if the given string is a mailto URL 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param url string to be tested 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if the string is a mailto URL 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static boolean isMailTo(String url) { 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (url != null && url.startsWith(MAILTO_SCHEME)) { 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Parse and decode a mailto scheme string. This parser implements 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * RFC 2368. The returned object can be queried for the parsed parameters. 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param url String containing a mailto URL 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return MailTo object 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @exception ParseException if the scheme is not a mailto URL 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static MailTo parse(String url) throws ParseException { 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (url == null) { 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new NullPointerException(); 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!isMailTo(url)) { 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new ParseException("Not a mailto scheme"); 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Strip the scheme as the Uri parser can't cope with it. 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String noScheme = url.substring(MAILTO_SCHEME.length()); 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Uri email = Uri.parse(noScheme); 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MailTo m = new MailTo(); 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Parse out the query parameters 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String query = email.getQuery(); 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (query != null ) { 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String[] queries = query.split("&"); 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String q : queries) { 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String[] nameval = q.split("="); 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nameval.length == 0) { 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // insert the headers with the name in lowercase so that 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we can easily find common headers 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project m.mHeaders.put(Uri.decode(nameval[0]).toLowerCase(), 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nameval.length > 1 ? Uri.decode(nameval[1]) : null); 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Address can be specified in both the headers and just after the 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // mailto line. Join the two together. 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String address = email.getPath(); 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (address != null) { 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String addr = m.getTo(); 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (addr != null) { 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address += ", " + addr; 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project m.mHeaders.put(TO, address); 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return m; 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Retrieve the To address line from the parsed mailto URL. This could be 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * several email address that are comma-space delimited. 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If no To line was specified, then null is return 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return comma delimited email addresses or null 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String getTo() { 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mHeaders.get(TO); 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Retrieve the CC address line from the parsed mailto URL. This could be 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * several email address that are comma-space delimited. 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If no CC line was specified, then null is return 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return comma delimited email addresses or null 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String getCc() { 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mHeaders.get(CC); 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Retrieve the subject line from the parsed mailto URL. 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If no subject line was specified, then null is return 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return subject or null 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String getSubject() { 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mHeaders.get(SUBJECT); 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Retrieve the body line from the parsed mailto URL. 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If no body line was specified, then null is return 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return body or null 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String getBody() { 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mHeaders.get(BODY); 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Retrieve all the parsed email headers from the mailto URL 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return map containing all parsed values 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Map<String, String> getHeaders() { 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mHeaders; 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String toString() { 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder sb = new StringBuilder(MAILTO_SCHEME); 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append('?'); 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (Map.Entry<String,String> header : mHeaders.entrySet()) { 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(Uri.encode(header.getKey())); 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append('='); 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(Uri.encode(header.getValue())); 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append('&'); 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sb.toString(); 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Private constructor. The only way to build a Mailto object is through 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the parse() method. 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private MailTo() { 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHeaders = new HashMap<String, String>(); 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 173