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