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.text.util;
18 
19 /**
20  * This class stores an RFC 822-like name, address, and comment,
21  * and provides methods to convert them to quoted strings.
22  */
23 public class Rfc822Token {
24     private String mName, mAddress, mComment;
25 
26     /**
27      * Creates a new Rfc822Token with the specified name, address,
28      * and comment.
29      */
Rfc822Token(String name, String address, String comment)30     public Rfc822Token(String name, String address, String comment) {
31         mName = name;
32         mAddress = address;
33         mComment = comment;
34     }
35 
36     /**
37      * Returns the name part.
38      */
getName()39     public String getName() {
40         return mName;
41     }
42 
43     /**
44      * Returns the address part.
45      */
getAddress()46     public String getAddress() {
47         return mAddress;
48     }
49 
50     /**
51      * Returns the comment part.
52      */
getComment()53     public String getComment() {
54         return mComment;
55     }
56 
57     /**
58      * Changes the name to the specified name.
59      */
setName(String name)60     public void setName(String name) {
61         mName = name;
62     }
63 
64     /**
65      * Changes the address to the specified address.
66      */
setAddress(String address)67     public void setAddress(String address) {
68         mAddress = address;
69     }
70 
71     /**
72      * Changes the comment to the specified comment.
73      */
setComment(String comment)74     public void setComment(String comment) {
75         mComment = comment;
76     }
77 
78     /**
79      * Returns the name (with quoting added if necessary),
80      * the comment (in parentheses), and the address (in angle brackets).
81      * This should be suitable for inclusion in an RFC 822 address list.
82      */
toString()83     public String toString() {
84         StringBuilder sb = new StringBuilder();
85 
86         if (mName != null && mName.length() != 0) {
87             sb.append(quoteNameIfNecessary(mName));
88             sb.append(' ');
89         }
90 
91         if (mComment != null && mComment.length() != 0) {
92             sb.append('(');
93             sb.append(quoteComment(mComment));
94             sb.append(") ");
95         }
96 
97         if (mAddress != null && mAddress.length() != 0) {
98             sb.append('<');
99             sb.append(mAddress);
100             sb.append('>');
101         }
102 
103         return sb.toString();
104     }
105 
106     /**
107      * Returns the name, conservatively quoting it if there are any
108      * characters that are likely to cause trouble outside of a
109      * quoted string, or returning it literally if it seems safe.
110      */
quoteNameIfNecessary(String name)111     public static String quoteNameIfNecessary(String name) {
112         int len = name.length();
113 
114         for (int i = 0; i < len; i++) {
115             char c = name.charAt(i);
116 
117             if (! ((c >= 'A' && c <= 'Z') ||
118                    (c >= 'a' && c <= 'z') ||
119                    (c == ' ') ||
120                    (c >= '0' && c <= '9'))) {
121                 return '"' + quoteName(name) + '"';
122             }
123         }
124 
125         return name;
126     }
127 
128     /**
129      * Returns the name, with internal backslashes and quotation marks
130      * preceded by backslashes.  The outer quote marks themselves are not
131      * added by this method.
132      */
quoteName(String name)133     public static String quoteName(String name) {
134         StringBuilder sb = new StringBuilder();
135 
136         int len = name.length();
137         for (int i = 0; i < len; i++) {
138             char c = name.charAt(i);
139 
140             if (c == '\\' || c == '"') {
141                 sb.append('\\');
142             }
143 
144             sb.append(c);
145         }
146 
147         return sb.toString();
148     }
149 
150     /**
151      * Returns the comment, with internal backslashes and parentheses
152      * preceded by backslashes.  The outer parentheses themselves are
153      * not added by this method.
154      */
quoteComment(String comment)155     public static String quoteComment(String comment) {
156         int len = comment.length();
157         StringBuilder sb = new StringBuilder();
158 
159         for (int i = 0; i < len; i++) {
160             char c = comment.charAt(i);
161 
162             if (c == '(' || c == ')' || c == '\\') {
163                 sb.append('\\');
164             }
165 
166             sb.append(c);
167         }
168 
169         return sb.toString();
170     }
171 
hashCode()172     public int hashCode() {
173         int result = 17;
174         if (mName != null) result = 31 * result + mName.hashCode();
175         if (mAddress != null) result = 31 * result + mAddress.hashCode();
176         if (mComment != null) result = 31 * result + mComment.hashCode();
177         return result;
178     }
179 
stringEquals(String a, String b)180     private static boolean stringEquals(String a, String b) {
181         if (a == null) {
182             return (b == null);
183         } else {
184             return (a.equals(b));
185         }
186     }
187 
equals(Object o)188     public boolean equals(Object o) {
189         if (!(o instanceof Rfc822Token)) {
190             return false;
191         }
192         Rfc822Token other = (Rfc822Token) o;
193         return (stringEquals(mName, other.mName) &&
194                 stringEquals(mAddress, other.mAddress) &&
195                 stringEquals(mComment, other.mComment));
196     }
197 }
198 
199