1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.net; 18 19 import java.util.HashMap; 20 import java.util.Locale; 21 import java.util.Map; 22 import java.util.Set; 23 24 /** 25 * 26 * MailTo URL parser 27 * 28 * This class parses a mailto scheme URL and then can be queried for 29 * the parsed parameters. This implements RFC 2368. 30 * 31 */ 32 public class MailTo { 33 34 static public final String MAILTO_SCHEME = "mailto:"; 35 36 // All the parsed content is added to the headers. 37 private HashMap<String, String> mHeaders; 38 39 // Well known headers 40 static private final String TO = "to"; 41 static private final String BODY = "body"; 42 static private final String CC = "cc"; 43 static private final String SUBJECT = "subject"; 44 45 46 /** 47 * Test to see if the given string is a mailto URL 48 * @param url string to be tested 49 * @return true if the string is a mailto URL 50 */ isMailTo(String url)51 public static boolean isMailTo(String url) { 52 if (url != null && url.startsWith(MAILTO_SCHEME)) { 53 return true; 54 } 55 return false; 56 } 57 58 /** 59 * Parse and decode a mailto scheme string. This parser implements 60 * RFC 2368. The returned object can be queried for the parsed parameters. 61 * @param url String containing a mailto URL 62 * @return MailTo object 63 * @exception ParseException if the scheme is not a mailto URL 64 */ parse(String url)65 public static MailTo parse(String url) throws ParseException { 66 if (url == null) { 67 throw new NullPointerException(); 68 } 69 if (!isMailTo(url)) { 70 throw new ParseException("Not a mailto scheme"); 71 } 72 // Strip the scheme as the Uri parser can't cope with it. 73 String noScheme = url.substring(MAILTO_SCHEME.length()); 74 Uri email = Uri.parse(noScheme); 75 MailTo m = new MailTo(); 76 77 // Parse out the query parameters 78 String query = email.getQuery(); 79 if (query != null ) { 80 String[] queries = query.split("&"); 81 for (String q : queries) { 82 String[] nameval = q.split("="); 83 if (nameval.length == 0) { 84 continue; 85 } 86 // insert the headers with the name in lowercase so that 87 // we can easily find common headers 88 m.mHeaders.put(Uri.decode(nameval[0]).toLowerCase(Locale.ROOT), 89 nameval.length > 1 ? Uri.decode(nameval[1]) : null); 90 } 91 } 92 93 // Address can be specified in both the headers and just after the 94 // mailto line. Join the two together. 95 String address = email.getPath(); 96 if (address != null) { 97 String addr = m.getTo(); 98 if (addr != null) { 99 address += ", " + addr; 100 } 101 m.mHeaders.put(TO, address); 102 } 103 104 return m; 105 } 106 107 /** 108 * Retrieve the To address line from the parsed mailto URL. This could be 109 * several email address that are comma-space delimited. 110 * If no To line was specified, then null is return 111 * @return comma delimited email addresses or null 112 */ getTo()113 public String getTo() { 114 return mHeaders.get(TO); 115 } 116 117 /** 118 * Retrieve the CC address line from the parsed mailto URL. This could be 119 * several email address that are comma-space delimited. 120 * If no CC line was specified, then null is return 121 * @return comma delimited email addresses or null 122 */ getCc()123 public String getCc() { 124 return mHeaders.get(CC); 125 } 126 127 /** 128 * Retrieve the subject line from the parsed mailto URL. 129 * If no subject line was specified, then null is return 130 * @return subject or null 131 */ getSubject()132 public String getSubject() { 133 return mHeaders.get(SUBJECT); 134 } 135 136 /** 137 * Retrieve the body line from the parsed mailto URL. 138 * If no body line was specified, then null is return 139 * @return body or null 140 */ getBody()141 public String getBody() { 142 return mHeaders.get(BODY); 143 } 144 145 /** 146 * Retrieve all the parsed email headers from the mailto URL 147 * @return map containing all parsed values 148 */ getHeaders()149 public Map<String, String> getHeaders() { 150 return mHeaders; 151 } 152 153 @Override toString()154 public String toString() { 155 StringBuilder sb = new StringBuilder(MAILTO_SCHEME); 156 sb.append('?'); 157 for (Map.Entry<String,String> header : mHeaders.entrySet()) { 158 sb.append(Uri.encode(header.getKey())); 159 sb.append('='); 160 sb.append(Uri.encode(header.getValue())); 161 sb.append('&'); 162 } 163 return sb.toString(); 164 } 165 166 /** 167 * Private constructor. The only way to build a Mailto object is through 168 * the parse() method. 169 */ MailTo()170 private MailTo() { 171 mHeaders = new HashMap<String, String>(); 172 } 173 } 174