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 23 /** 24 * 25 * MailTo URL parser 26 * 27 * This class parses a mailto scheme URL and then can be queried for 28 * the parsed parameters. This implements RFC 2368. 29 * 30 */ 31 public class MailTo { 32 33 static public final String MAILTO_SCHEME = "mailto:"; 34 35 // All the parsed content is added to the headers. 36 private HashMap<String, String> mHeaders; 37 38 // Well known headers 39 static private final String TO = "to"; 40 static private final String BODY = "body"; 41 static private final String CC = "cc"; 42 static private final String SUBJECT = "subject"; 43 44 45 /** 46 * Test to see if the given string is a mailto URL 47 * @param url string to be tested 48 * @return true if the string is a mailto URL 49 */ isMailTo(String url)50 public static boolean isMailTo(String url) { 51 if (url != null && url.startsWith(MAILTO_SCHEME)) { 52 return true; 53 } 54 return false; 55 } 56 57 /** 58 * Parse and decode a mailto scheme string. This parser implements 59 * RFC 2368. The returned object can be queried for the parsed parameters. 60 * @param url String containing a mailto URL 61 * @return MailTo object 62 * @exception ParseException if the scheme is not a mailto URL 63 */ parse(String url)64 public static MailTo parse(String url) throws ParseException { 65 if (url == null) { 66 throw new NullPointerException(); 67 } 68 if (!isMailTo(url)) { 69 throw new ParseException("Not a mailto scheme"); 70 } 71 // Strip the scheme as the Uri parser can't cope with it. 72 String noScheme = url.substring(MAILTO_SCHEME.length()); 73 Uri email = Uri.parse(noScheme); 74 MailTo m = new MailTo(); 75 76 // Parse out the query parameters 77 String query = email.getQuery(); 78 if (query != null ) { 79 String[] queries = query.split("&"); 80 for (String q : queries) { 81 String[] nameval = q.split("="); 82 if (nameval.length == 0) { 83 continue; 84 } 85 // insert the headers with the name in lowercase so that 86 // we can easily find common headers 87 m.mHeaders.put(Uri.decode(nameval[0]).toLowerCase(Locale.ROOT), 88 nameval.length > 1 ? Uri.decode(nameval[1]) : null); 89 } 90 } 91 92 // Address can be specified in both the headers and just after the 93 // mailto line. Join the two together. 94 String address = email.getPath(); 95 if (address != null) { 96 String addr = m.getTo(); 97 if (addr != null) { 98 address += ", " + addr; 99 } 100 m.mHeaders.put(TO, address); 101 } 102 103 return m; 104 } 105 106 /** 107 * Retrieve the To address line from the parsed mailto URL. This could be 108 * several email address that are comma-space delimited. 109 * If no To line was specified, then null is return 110 * @return comma delimited email addresses or null 111 */ getTo()112 public String getTo() { 113 return mHeaders.get(TO); 114 } 115 116 /** 117 * Retrieve the CC address line from the parsed mailto URL. This could be 118 * several email address that are comma-space delimited. 119 * If no CC line was specified, then null is return 120 * @return comma delimited email addresses or null 121 */ getCc()122 public String getCc() { 123 return mHeaders.get(CC); 124 } 125 126 /** 127 * Retrieve the subject line from the parsed mailto URL. 128 * If no subject line was specified, then null is return 129 * @return subject or null 130 */ getSubject()131 public String getSubject() { 132 return mHeaders.get(SUBJECT); 133 } 134 135 /** 136 * Retrieve the body line from the parsed mailto URL. 137 * If no body line was specified, then null is return 138 * @return body or null 139 */ getBody()140 public String getBody() { 141 return mHeaders.get(BODY); 142 } 143 144 /** 145 * Retrieve all the parsed email headers from the mailto URL 146 * @return map containing all parsed values 147 */ getHeaders()148 public Map<String, String> getHeaders() { 149 return mHeaders; 150 } 151 152 @Override toString()153 public String toString() { 154 StringBuilder sb = new StringBuilder(MAILTO_SCHEME); 155 sb.append('?'); 156 for (Map.Entry<String,String> header : mHeaders.entrySet()) { 157 sb.append(Uri.encode(header.getKey())); 158 sb.append('='); 159 sb.append(Uri.encode(header.getValue())); 160 sb.append('&'); 161 } 162 return sb.toString(); 163 } 164 165 /** 166 * Private constructor. The only way to build a Mailto object is through 167 * the parse() method. 168 */ MailTo()169 private MailTo() { 170 mHeaders = new HashMap<String, String>(); 171 } 172 } 173