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
17package android.net;
18
19import java.util.HashMap;
20import java.util.Map;
21import java.util.Set;
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 */
31public 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     */
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     */
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(),
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     */
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     */
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     */
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     */
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     */
148    public Map<String, String> getHeaders() {
149        return mHeaders;
150    }
151
152    @Override
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     */
169    private MailTo() {
170        mHeaders = new HashMap<String, String>();
171    }
172}
173