diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:45 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:45 -0800 |
commit | d83a98f4ce9cfa908f5c54bbd70f03eec07e7553 (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /core/java/android/text/util | |
parent | 076357b8567458d4b6dfdcf839ef751634cd2bfb (diff) | |
download | frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.zip frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.gz frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.bz2 |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'core/java/android/text/util')
-rw-r--r-- | core/java/android/text/util/Linkify.java | 541 | ||||
-rw-r--r-- | core/java/android/text/util/Regex.java | 204 | ||||
-rw-r--r-- | core/java/android/text/util/Rfc822Token.java | 172 | ||||
-rw-r--r-- | core/java/android/text/util/Rfc822Tokenizer.java | 292 | ||||
-rw-r--r-- | core/java/android/text/util/Rfc822Validator.java | 132 | ||||
-rw-r--r-- | core/java/android/text/util/package.html | 6 |
6 files changed, 0 insertions, 1347 deletions
diff --git a/core/java/android/text/util/Linkify.java b/core/java/android/text/util/Linkify.java deleted file mode 100644 index d61e888..0000000 --- a/core/java/android/text/util/Linkify.java +++ /dev/null @@ -1,541 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.text.util; - -import android.text.method.LinkMovementMethod; -import android.text.method.MovementMethod; -import android.text.style.URLSpan; -import android.text.Spannable; -import android.text.SpannableString; -import android.text.Spanned; -import android.webkit.WebView; -import android.widget.TextView; - -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Linkify take a piece of text and a regular expression and turns all of the - * regex matches in the text into clickable links. This is particularly - * useful for matching things like email addresses, web urls, etc. and making - * them actionable. - * - * Alone with the pattern that is to be matched, a url scheme prefix is also - * required. Any pattern match that does not begin with the supplied scheme - * will have the scheme prepended to the matched text when the clickable url - * is created. For instance, if you are matching web urls you would supply - * the scheme <code>http://</code>. If the pattern matches example.com, which - * does not have a url scheme prefix, the supplied scheme will be prepended to - * create <code>http://example.com</code> when the clickable url link is - * created. - */ - -public class Linkify { - /** - * Bit field indicating that web URLs should be matched in methods that - * take an options mask - */ - public static final int WEB_URLS = 0x01; - - /** - * Bit field indicating that email addresses should be matched in methods - * that take an options mask - */ - public static final int EMAIL_ADDRESSES = 0x02; - - /** - * Bit field indicating that phone numbers should be matched in methods that - * take an options mask - */ - public static final int PHONE_NUMBERS = 0x04; - - /** - * Bit field indicating that street addresses should be matched in methods that - * take an options mask - */ - public static final int MAP_ADDRESSES = 0x08; - - /** - * Bit mask indicating that all available patterns should be matched in - * methods that take an options mask - */ - public static final int ALL = WEB_URLS | EMAIL_ADDRESSES | PHONE_NUMBERS | MAP_ADDRESSES; - - /** - * Don't treat anything with fewer than this many digits as a - * phone number. - */ - private static final int PHONE_NUMBER_MINIMUM_DIGITS = 5; - - /** - * Filters out web URL matches that occur after an at-sign (@). This is - * to prevent turning the domain name in an email address into a web link. - */ - public static final MatchFilter sUrlMatchFilter = new MatchFilter() { - public final boolean acceptMatch(CharSequence s, int start, int end) { - if (start == 0) { - return true; - } - - if (s.charAt(start - 1) == '@') { - return false; - } - - return true; - } - }; - - /** - * Filters out URL matches that don't have enough digits to be a - * phone number. - */ - public static final MatchFilter sPhoneNumberMatchFilter = new MatchFilter() { - public final boolean acceptMatch(CharSequence s, int start, int end) { - int digitCount = 0; - - for (int i = start; i < end; i++) { - if (Character.isDigit(s.charAt(i))) { - digitCount++; - if (digitCount >= PHONE_NUMBER_MINIMUM_DIGITS) { - return true; - } - } - } - return false; - } - }; - - /** - * Transforms matched phone number text into something suitable - * to be used in a tel: URL. It does this by removing everything - * but the digits and plus signs. For instance: - * '+1 (919) 555-1212' - * becomes '+19195551212' - */ - public static final TransformFilter sPhoneNumberTransformFilter = new TransformFilter() { - public final String transformUrl(final Matcher match, String url) { - return Regex.digitsAndPlusOnly(match); - } - }; - - /** - * MatchFilter enables client code to have more control over - * what is allowed to match and become a link, and what is not. - * - * For example: when matching web urls you would like things like - * http://www.example.com to match, as well as just example.com itelf. - * However, you would not want to match against the domain in - * support@example.com. So, when matching against a web url pattern you - * might also include a MatchFilter that disallows the match if it is - * immediately preceded by an at-sign (@). - */ - public interface MatchFilter { - /** - * Examines the character span matched by the pattern and determines - * if the match should be turned into an actionable link. - * - * @param s The body of text against which the pattern - * was matched - * @param start The index of the first character in s that was - * matched by the pattern - inclusive - * @param end The index of the last character in s that was - * matched - exclusive - * - * @return Whether this match should be turned into a link - */ - boolean acceptMatch(CharSequence s, int start, int end); - } - - /** - * TransformFilter enables client code to have more control over - * how matched patterns are represented as URLs. - * - * For example: when converting a phone number such as (919) 555-1212 - * into a tel: URL the parentheses, white space, and hyphen need to be - * removed to produce tel:9195551212. - */ - public interface TransformFilter { - /** - * Examines the matched text and either passes it through or uses the - * data in the Matcher state to produce a replacement. - * - * @param match The regex matcher state that found this URL text - * @param url The text that was matched - * - * @return The transformed form of the URL - */ - String transformUrl(final Matcher match, String url); - } - - /** - * Scans the text of the provided Spannable and turns all occurrences - * of the link types indicated in the mask into clickable links. - * If the mask is nonzero, it also removes any existing URLSpans - * attached to the Spannable, to avoid problems if you call it - * repeatedly on the same text. - */ - public static final boolean addLinks(Spannable text, int mask) { - if (mask == 0) { - return false; - } - - URLSpan[] old = text.getSpans(0, text.length(), URLSpan.class); - - for (int i = old.length - 1; i >= 0; i--) { - text.removeSpan(old[i]); - } - - ArrayList<LinkSpec> links = new ArrayList<LinkSpec>(); - - if ((mask & WEB_URLS) != 0) { - gatherLinks(links, text, Regex.WEB_URL_PATTERN, - new String[] { "http://", "https://" }, - sUrlMatchFilter, null); - } - - if ((mask & EMAIL_ADDRESSES) != 0) { - gatherLinks(links, text, Regex.EMAIL_ADDRESS_PATTERN, - new String[] { "mailto:" }, - null, null); - } - - if ((mask & PHONE_NUMBERS) != 0) { - gatherLinks(links, text, Regex.PHONE_PATTERN, - new String[] { "tel:" }, - sPhoneNumberMatchFilter, sPhoneNumberTransformFilter); - } - - if ((mask & MAP_ADDRESSES) != 0) { - gatherMapLinks(links, text); - } - - pruneOverlaps(links); - - if (links.size() == 0) { - return false; - } - - for (LinkSpec link: links) { - applyLink(link.url, link.start, link.end, text); - } - - return true; - } - - /** - * Scans the text of the provided TextView and turns all occurrences of - * the link types indicated in the mask into clickable links. If matches - * are found the movement method for the TextView is set to - * LinkMovementMethod. - */ - public static final boolean addLinks(TextView text, int mask) { - if (mask == 0) { - return false; - } - - CharSequence t = text.getText(); - - if (t instanceof Spannable) { - if (addLinks((Spannable) t, mask)) { - addLinkMovementMethod(text); - return true; - } - - return false; - } else { - SpannableString s = SpannableString.valueOf(t); - - if (addLinks(s, mask)) { - addLinkMovementMethod(text); - text.setText(s); - - return true; - } - - return false; - } - } - - private static final void addLinkMovementMethod(TextView t) { - MovementMethod m = t.getMovementMethod(); - - if ((m == null) || !(m instanceof LinkMovementMethod)) { - if (t.getLinksClickable()) { - t.setMovementMethod(LinkMovementMethod.getInstance()); - } - } - } - - /** - * Applies a regex to the text of a TextView turning the matches into - * links. If links are found then UrlSpans are applied to the link - * text match areas, and the movement method for the text is changed - * to LinkMovementMethod. - * - * @param text TextView whose text is to be marked-up with links - * @param pattern Regex pattern to be used for finding links - * @param scheme Url scheme string (eg <code>http://</code> to be - * prepended to the url of links that do not have - * a scheme specified in the link text - */ - public static final void addLinks(TextView text, Pattern pattern, String scheme) { - addLinks(text, pattern, scheme, null, null); - } - - /** - * Applies a regex to the text of a TextView turning the matches into - * links. If links are found then UrlSpans are applied to the link - * text match areas, and the movement method for the text is changed - * to LinkMovementMethod. - * - * @param text TextView whose text is to be marked-up with links - * @param p Regex pattern to be used for finding links - * @param scheme Url scheme string (eg <code>http://</code> to be - * prepended to the url of links that do not have - * a scheme specified in the link text - * @param matchFilter The filter that is used to allow the client code - * additional control over which pattern matches are - * to be converted into links. - */ - public static final void addLinks(TextView text, Pattern p, String scheme, - MatchFilter matchFilter, TransformFilter transformFilter) { - SpannableString s = SpannableString.valueOf(text.getText()); - - if (addLinks(s, p, scheme, matchFilter, transformFilter)) { - text.setText(s); - addLinkMovementMethod(text); - } - } - - /** - * Applies a regex to a Spannable turning the matches into - * links. - * - * @param text Spannable whose text is to be marked-up with - * links - * @param pattern Regex pattern to be used for finding links - * @param scheme Url scheme string (eg <code>http://</code> to be - * prepended to the url of links that do not have - * a scheme specified in the link text - */ - public static final boolean addLinks(Spannable text, Pattern pattern, String scheme) { - return addLinks(text, pattern, scheme, null, null); - } - - /** - * Applies a regex to a Spannable turning the matches into - * links. - * - * @param s Spannable whose text is to be marked-up with - * links - * @param p Regex pattern to be used for finding links - * @param scheme Url scheme string (eg <code>http://</code> to be - * prepended to the url of links that do not have - * a scheme specified in the link text - * @param matchFilter The filter that is used to allow the client code - * additional control over which pattern matches are - * to be converted into links. - */ - public static final boolean addLinks(Spannable s, Pattern p, - String scheme, MatchFilter matchFilter, - TransformFilter transformFilter) { - boolean hasMatches = false; - String prefix = (scheme == null) ? "" : scheme.toLowerCase(); - Matcher m = p.matcher(s); - - while (m.find()) { - int start = m.start(); - int end = m.end(); - boolean allowed = true; - - if (matchFilter != null) { - allowed = matchFilter.acceptMatch(s, start, end); - } - - if (allowed) { - String url = makeUrl(m.group(0), new String[] { prefix }, - m, transformFilter); - - applyLink(url, start, end, s); - hasMatches = true; - } - } - - return hasMatches; - } - - private static final void applyLink(String url, int start, int end, Spannable text) { - URLSpan span = new URLSpan(url); - - text.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - } - - private static final String makeUrl(String url, String[] prefixes, - Matcher m, TransformFilter filter) { - if (filter != null) { - url = filter.transformUrl(m, url); - } - - boolean hasPrefix = false; - - for (int i = 0; i < prefixes.length; i++) { - if (url.regionMatches(true, 0, prefixes[i], 0, - prefixes[i].length())) { - hasPrefix = true; - - // Fix capitalization if necessary - if (!url.regionMatches(false, 0, prefixes[i], 0, - prefixes[i].length())) { - url = prefixes[i] + url.substring(prefixes[i].length()); - } - - break; - } - } - - if (!hasPrefix) { - url = prefixes[0] + url; - } - - return url; - } - - private static final void gatherLinks(ArrayList<LinkSpec> links, - Spannable s, Pattern pattern, String[] schemes, - MatchFilter matchFilter, TransformFilter transformFilter) { - Matcher m = pattern.matcher(s); - - while (m.find()) { - int start = m.start(); - int end = m.end(); - - if (matchFilter == null || matchFilter.acceptMatch(s, start, end)) { - LinkSpec spec = new LinkSpec(); - String url = makeUrl(m.group(0), schemes, m, transformFilter); - - spec.url = url; - spec.start = start; - spec.end = end; - - links.add(spec); - } - } - } - - private static final void gatherMapLinks(ArrayList<LinkSpec> links, Spannable s) { - String string = s.toString(); - String address; - int base = 0; - - while ((address = WebView.findAddress(string)) != null) { - int start = string.indexOf(address); - - if (start < 0) { - break; - } - - LinkSpec spec = new LinkSpec(); - int length = address.length(); - int end = start + length; - - spec.start = base + start; - spec.end = base + end; - string = string.substring(end); - base += end; - - String encodedAddress = null; - - try { - encodedAddress = URLEncoder.encode(address,"UTF-8"); - } catch (UnsupportedEncodingException e) { - continue; - } - - spec.url = "geo:0,0?q=" + encodedAddress; - links.add(spec); - } - } - - private static final void pruneOverlaps(ArrayList<LinkSpec> links) { - Comparator<LinkSpec> c = new Comparator<LinkSpec>() { - public final int compare(LinkSpec a, LinkSpec b) { - if (a.start < b.start) { - return -1; - } - - if (a.start > b.start) { - return 1; - } - - if (a.end < b.end) { - return 1; - } - - if (a.end > b.end) { - return -1; - } - - return 0; - } - - public final boolean equals(Object o) { - return false; - } - }; - - Collections.sort(links, c); - - int len = links.size(); - int i = 0; - - while (i < len - 1) { - LinkSpec a = links.get(i); - LinkSpec b = links.get(i + 1); - int remove = -1; - - if ((a.start <= b.start) && (a.end > b.start)) { - if (b.end <= a.end) { - remove = i + 1; - } else if ((a.end - a.start) > (b.end - b.start)) { - remove = i + 1; - } else if ((a.end - a.start) < (b.end - b.start)) { - remove = i; - } - - if (remove != -1) { - links.remove(remove); - len--; - continue; - } - - } - - i++; - } - } -} - -class LinkSpec { - String url; - int start; - int end; -} diff --git a/core/java/android/text/util/Regex.java b/core/java/android/text/util/Regex.java deleted file mode 100644 index 4c128ad..0000000 --- a/core/java/android/text/util/Regex.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.text.util; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * @hide - */ -public class Regex { - /** - * Regular expression pattern to match all IANA top-level domains. - * List accurate as of 2007/06/15. List taken from: - * http://data.iana.org/TLD/tlds-alpha-by-domain.txt - * This pattern is auto-generated by //device/tools/make-iana-tld-pattern.py - */ - public static final Pattern TOP_LEVEL_DOMAIN_PATTERN - = Pattern.compile( - "((aero|arpa|asia|a[cdefgilmnoqrstuwxz])" - + "|(biz|b[abdefghijmnorstvwyz])" - + "|(cat|com|coop|c[acdfghiklmnoruvxyz])" - + "|d[ejkmoz]" - + "|(edu|e[cegrstu])" - + "|f[ijkmor]" - + "|(gov|g[abdefghilmnpqrstuwy])" - + "|h[kmnrtu]" - + "|(info|int|i[delmnoqrst])" - + "|(jobs|j[emop])" - + "|k[eghimnrwyz]" - + "|l[abcikrstuvy]" - + "|(mil|mobi|museum|m[acdghklmnopqrstuvwxyz])" - + "|(name|net|n[acefgilopruz])" - + "|(org|om)" - + "|(pro|p[aefghklmnrstwy])" - + "|qa" - + "|r[eouw]" - + "|s[abcdeghijklmnortuvyz]" - + "|(tel|travel|t[cdfghjklmnoprtvwz])" - + "|u[agkmsyz]" - + "|v[aceginu]" - + "|w[fs]" - + "|y[etu]" - + "|z[amw])"); - - /** - * Regular expression pattern to match RFC 1738 URLs - * List accurate as of 2007/06/15. List taken from: - * http://data.iana.org/TLD/tlds-alpha-by-domain.txt - * This pattern is auto-generated by //device/tools/make-iana-tld-pattern.py - */ - public static final Pattern WEB_URL_PATTERN - = Pattern.compile( - "((?:(http|https|Http|Https):\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)" - + "\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2}))+(?:\\:(?:[a-zA-Z0-9\\$\\-\\_" - + "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2}))+)?\\@)?)?" - + "((?:(?:[a-zA-Z0-9][a-zA-Z0-9\\-]*\\.)+" // named host - + "(?:" // plus top level domain - + "(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])" - + "|(?:biz|b[abdefghijmnorstvwyz])" - + "|(?:cat|com|coop|c[acdfghiklmnoruvxyz])" - + "|d[ejkmoz]" - + "|(?:edu|e[cegrstu])" - + "|f[ijkmor]" - + "|(?:gov|g[abdefghilmnpqrstuwy])" - + "|h[kmnrtu]" - + "|(?:info|int|i[delmnoqrst])" - + "|(?:jobs|j[emop])" - + "|k[eghimnrwyz]" - + "|l[abcikrstuvy]" - + "|(?:mil|mobi|museum|m[acdghklmnopqrstuvwxyz])" - + "|(?:name|net|n[acefgilopruz])" - + "|(?:org|om)" - + "|(?:pro|p[aefghklmnrstwy])" - + "|qa" - + "|r[eouw]" - + "|s[abcdeghijklmnortuvyz]" - + "|(?:tel|travel|t[cdfghjklmnoprtvwz])" - + "|u[agkmsyz]" - + "|v[aceginu]" - + "|w[fs]" - + "|y[etu]" - + "|z[amw]))" - + "|(?:(?:25[0-5]|2[0-4]" // or ip address - + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(?:25[0-5]|2[0-4][0-9]" - + "|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1]" - + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}" - + "|[1-9][0-9]|[0-9])))" - + "(?:\\:\\d{1,5})?)" // plus option port number - + "(\\/(?:(?:[a-zA-Z0-9\\;\\/\\?\\:\\@\\&\\=\\#\\~" // plus option query params - + "\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])|(?:\\%[a-fA-F0-9]{2}))*)?" - + "(?:\\b|$)"); // and finally, a word boundary or end of - // input. This is to stop foo.sure from - // matching as foo.su - - public static final Pattern IP_ADDRESS_PATTERN - = Pattern.compile( - "((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]" - + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]" - + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}" - + "|[1-9][0-9]|[0-9]))"); - - public static final Pattern DOMAIN_NAME_PATTERN - = Pattern.compile( - "(((([a-zA-Z0-9][a-zA-Z0-9\\-]*)*[a-zA-Z0-9]\\.)+" - + TOP_LEVEL_DOMAIN_PATTERN + ")|" - + IP_ADDRESS_PATTERN + ")"); - - public static final Pattern EMAIL_ADDRESS_PATTERN - = Pattern.compile( - "[a-zA-Z0-9\\+\\.\\_\\%\\-]+" + - "\\@" + - "[a-zA-Z0-9][a-zA-Z0-9\\-]*" + - "(" + - "\\." + - "[a-zA-Z0-9][a-zA-Z0-9\\-]*" + - ")+" - ); - - /** - * This pattern is intended for searching for things that look like they - * might be phone numbers in arbitrary text, not for validating whether - * something is in fact a phone number. It will miss many things that - * are legitimate phone numbers. - * - * <p> The pattern matches the following: - * <ul> - * <li>Optionally, a + sign followed immediately by one or more digits. Spaces, dots, or dashes - * may follow. - * <li>Optionally, sets of digits in parentheses, separated by spaces, dots, or dashes. - * <li>A string starting and ending with a digit, containing digits, spaces, dots, and/or dashes. - * </ul> - */ - public static final Pattern PHONE_PATTERN - = Pattern.compile( // sdd = space, dot, or dash - "(\\+[0-9]+[\\- \\.]*)?" // +<digits><sdd>* - + "(\\([0-9]+\\)[\\- \\.]*)?" // (<digits>)<sdd>* - + "([0-9][0-9\\- \\.][0-9\\- \\.]+[0-9])"); // <digit><digit|sdd>+<digit> - - /** - * Convenience method to take all of the non-null matching groups in a - * regex Matcher and return them as a concatenated string. - * - * @param matcher The Matcher object from which grouped text will - * be extracted - * - * @return A String comprising all of the non-null matched - * groups concatenated together - */ - public static final String concatGroups(Matcher matcher) { - StringBuilder b = new StringBuilder(); - final int numGroups = matcher.groupCount(); - - for (int i = 1; i <= numGroups; i++) { - String s = matcher.group(i); - - System.err.println("Group(" + i + ") : " + s); - - if (s != null) { - b.append(s); - } - } - - return b.toString(); - } - - /** - * Convenience method to return only the digits and plus signs - * in the matching string. - * - * @param matcher The Matcher object from which digits and plus will - * be extracted - * - * @return A String comprising all of the digits and plus in - * the match - */ - public static final String digitsAndPlusOnly(Matcher matcher) { - StringBuilder buffer = new StringBuilder(); - String matchingRegion = matcher.group(); - - for (int i = 0, size = matchingRegion.length(); i < size; i++) { - char character = matchingRegion.charAt(i); - - if (character == '+' || Character.isDigit(character)) { - buffer.append(character); - } - } - return buffer.toString(); - } -} diff --git a/core/java/android/text/util/Rfc822Token.java b/core/java/android/text/util/Rfc822Token.java deleted file mode 100644 index e6472df..0000000 --- a/core/java/android/text/util/Rfc822Token.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.text.util; - -/** - * This class stores an RFC 822-like name, address, and comment, - * and provides methods to convert them to quoted strings. - */ -public class Rfc822Token { - private String mName, mAddress, mComment; - - /** - * Creates a new Rfc822Token with the specified name, address, - * and comment. - */ - public Rfc822Token(String name, String address, String comment) { - mName = name; - mAddress = address; - mComment = comment; - } - - /** - * Returns the name part. - */ - public String getName() { - return mName; - } - - /** - * Returns the address part. - */ - public String getAddress() { - return mAddress; - } - - /** - * Returns the comment part. - */ - public String getComment() { - return mComment; - } - - /** - * Changes the name to the specified name. - */ - public void setName(String name) { - mName = name; - } - - /** - * Changes the address to the specified address. - */ - public void setAddress(String address) { - mAddress = address; - } - - /** - * Changes the comment to the specified comment. - */ - public void setComment(String comment) { - mComment = comment; - } - - /** - * Returns the name (with quoting added if necessary), - * the comment (in parentheses), and the address (in angle brackets). - * This should be suitable for inclusion in an RFC 822 address list. - */ - public String toString() { - StringBuilder sb = new StringBuilder(); - - if (mName != null && mName.length() != 0) { - sb.append(quoteNameIfNecessary(mName)); - sb.append(' '); - } - - if (mComment != null && mComment.length() != 0) { - sb.append('('); - sb.append(quoteComment(mComment)); - sb.append(") "); - } - - if (mAddress != null && mAddress.length() != 0) { - sb.append('<'); - sb.append(mAddress); - sb.append('>'); - } - - return sb.toString(); - } - - /** - * Returns the name, conservatively quoting it if there are any - * characters that are likely to cause trouble outside of a - * quoted string, or returning it literally if it seems safe. - */ - public static String quoteNameIfNecessary(String name) { - int len = name.length(); - - for (int i = 0; i < len; i++) { - char c = name.charAt(i); - - if (! ((c >= 'A' && i <= 'Z') || - (c >= 'a' && c <= 'z') || - (c == ' ') || - (c >= '0' && c <= '9'))) { - return '"' + quoteName(name) + '"'; - } - } - - return name; - } - - /** - * Returns the name, with internal backslashes and quotation marks - * preceded by backslashes. The outer quote marks themselves are not - * added by this method. - */ - public static String quoteName(String name) { - StringBuilder sb = new StringBuilder(); - - int len = name.length(); - for (int i = 0; i < len; i++) { - char c = name.charAt(i); - - if (c == '\\' || c == '"') { - sb.append('\\'); - } - - sb.append(c); - } - - return sb.toString(); - } - - /** - * Returns the comment, with internal backslashes and parentheses - * preceded by backslashes. The outer parentheses themselves are - * not added by this method. - */ - public static String quoteComment(String comment) { - int len = comment.length(); - StringBuilder sb = new StringBuilder(); - - for (int i = 0; i < len; i++) { - char c = comment.charAt(i); - - if (c == '(' || c == ')' || c == '\\') { - sb.append('\\'); - } - - sb.append(c); - } - - return sb.toString(); - } -} - diff --git a/core/java/android/text/util/Rfc822Tokenizer.java b/core/java/android/text/util/Rfc822Tokenizer.java deleted file mode 100644 index d4e78b0..0000000 --- a/core/java/android/text/util/Rfc822Tokenizer.java +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.text.util; - -import android.widget.MultiAutoCompleteTextView; - -import java.util.ArrayList; - -/** - * This class works as a Tokenizer for MultiAutoCompleteTextView for - * address list fields, and also provides a method for converting - * a string of addresses (such as might be typed into such a field) - * into a series of Rfc822Tokens. - */ -public class Rfc822Tokenizer implements MultiAutoCompleteTextView.Tokenizer { - /** - * This constructor will try to take a string like - * "Foo Bar (something) <foo\@google.com>, - * blah\@google.com (something)" - * and convert it into one or more Rfc822Tokens. - * It does *not* decode MIME encoded-words; charset conversion - * must already have taken place if necessary. - * It will try to be tolerant of broken syntax instead of - * returning an error. - */ - public static Rfc822Token[] tokenize(CharSequence text) { - ArrayList<Rfc822Token> out = new ArrayList<Rfc822Token>(); - StringBuilder name = new StringBuilder(); - StringBuilder address = new StringBuilder(); - StringBuilder comment = new StringBuilder(); - - int i = 0; - int cursor = text.length(); - - while (i < cursor) { - char c = text.charAt(i); - - if (c == ',' || c == ';') { - i++; - - while (i < cursor && text.charAt(i) == ' ') { - i++; - } - - crunch(name); - - if (address.length() > 0) { - out.add(new Rfc822Token(name.toString(), - address.toString(), - comment.toString())); - } else if (name.length() > 0) { - out.add(new Rfc822Token(null, - name.toString(), - comment.toString())); - } - - name.setLength(0); - address.setLength(0); - address.setLength(0); - } else if (c == '"') { - i++; - - while (i < cursor) { - c = text.charAt(i); - - if (c == '"') { - i++; - break; - } else if (c == '\\') { - name.append(text.charAt(i + 1)); - i += 2; - } else { - name.append(c); - i++; - } - } - } else if (c == '(') { - int level = 1; - i++; - - while (i < cursor && level > 0) { - c = text.charAt(i); - - if (c == ')') { - if (level > 1) { - comment.append(c); - } - - level--; - i++; - } else if (c == '(') { - comment.append(c); - level++; - i++; - } else if (c == '\\') { - comment.append(text.charAt(i + 1)); - i += 2; - } else { - comment.append(c); - i++; - } - } - } else if (c == '<') { - i++; - - while (i < cursor) { - c = text.charAt(i); - - if (c == '>') { - i++; - break; - } else { - address.append(c); - i++; - } - } - } else if (c == ' ') { - name.append('\0'); - i++; - } else { - name.append(c); - i++; - } - } - - crunch(name); - - if (address.length() > 0) { - out.add(new Rfc822Token(name.toString(), - address.toString(), - comment.toString())); - } else if (name.length() > 0) { - out.add(new Rfc822Token(null, - name.toString(), - comment.toString())); - } - - return out.toArray(new Rfc822Token[out.size()]); - } - - private static void crunch(StringBuilder sb) { - int i = 0; - int len = sb.length(); - - while (i < len) { - char c = sb.charAt(i); - - if (c == '\0') { - if (i == 0 || i == len - 1 || - sb.charAt(i - 1) == ' ' || - sb.charAt(i - 1) == '\0' || - sb.charAt(i + 1) == ' ' || - sb.charAt(i + 1) == '\0') { - sb.deleteCharAt(i); - len--; - } else { - i++; - } - } else { - i++; - } - } - - for (i = 0; i < len; i++) { - if (sb.charAt(i) == '\0') { - sb.setCharAt(i, ' '); - } - } - } - - /** - * {@inheritDoc} - */ - public int findTokenStart(CharSequence text, int cursor) { - /* - * It's hard to search backward, so search forward until - * we reach the cursor. - */ - - int best = 0; - int i = 0; - - while (i < cursor) { - i = findTokenEnd(text, i); - - if (i < cursor) { - i++; // Skip terminating punctuation - - while (i < cursor && text.charAt(i) == ' ') { - i++; - } - - if (i < cursor) { - best = i; - } - } - } - - return best; - } - - /** - * {@inheritDoc} - */ - public int findTokenEnd(CharSequence text, int cursor) { - int len = text.length(); - int i = cursor; - - while (i < len) { - char c = text.charAt(i); - - if (c == ',' || c == ';') { - return i; - } else if (c == '"') { - i++; - - while (i < len) { - c = text.charAt(i); - - if (c == '"') { - i++; - break; - } else if (c == '\\') { - i += 2; - } else { - i++; - } - } - } else if (c == '(') { - int level = 1; - i++; - - while (i < len && level > 0) { - c = text.charAt(i); - - if (c == ')') { - level--; - i++; - } else if (c == '(') { - level++; - i++; - } else if (c == '\\') { - i += 2; - } else { - i++; - } - } - } else if (c == '<') { - i++; - - while (i < len) { - c = text.charAt(i); - - if (c == '>') { - i++; - break; - } else { - i++; - } - } - } else { - i++; - } - } - - return i; - } - - /** - * Terminates the specified address with a comma and space. - * This assumes that the specified text already has valid syntax. - * The Adapter subclass's convertToString() method must make that - * guarantee. - */ - public CharSequence terminateToken(CharSequence text) { - return text + ", "; - } -} diff --git a/core/java/android/text/util/Rfc822Validator.java b/core/java/android/text/util/Rfc822Validator.java deleted file mode 100644 index 6a6bf69..0000000 --- a/core/java/android/text/util/Rfc822Validator.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.text.util; - -import android.text.TextUtils; -import android.widget.AutoCompleteTextView; - -import java.util.regex.Pattern; - -/** - * This class works as a Validator for AutoCompleteTextView for - * email addresses. If a token does not appear to be a valid address, - * it is trimmed of characters that cannot legitimately appear in one - * and has the specified domain name added. It is meant for use with - * {@link Rfc822Token} and {@link Rfc822Tokenizer}. - * - * @deprecated In the future make sure we don't quietly alter the user's - * text in ways they did not intend. Meanwhile, hide this - * class from the public API because it does not even have - * a full understanding of the syntax it claims to correct. - * @hide - */ -public class Rfc822Validator implements AutoCompleteTextView.Validator { - /* - * Regex.EMAIL_ADDRESS_PATTERN hardcodes the TLD that we accept, but we - * want to make sure we will keep accepting email addresses with TLD's - * that don't exist at the time of this writing, so this regexp relaxes - * that constraint by accepting any kind of top level domain, not just - * ".com", ".fr", etc... - */ - private static final Pattern EMAIL_ADDRESS_PATTERN = - Pattern.compile("[^\\s@]+@[^\\s@]+\\.[a-zA-z][a-zA-Z][a-zA-Z]*"); - - private String mDomain; - - /** - * Constructs a new validator that uses the specified domain name as - * the default when none is specified. - */ - public Rfc822Validator(String domain) { - mDomain = domain; - } - - /** - * {@inheritDoc} - */ - public boolean isValid(CharSequence text) { - Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(text); - - return tokens.length == 1 && - EMAIL_ADDRESS_PATTERN. - matcher(tokens[0].getAddress()).matches(); - } - - /** - * @return a string in which all the characters that are illegal for the username - * or the domain name part of the email address have been removed. - */ - private String removeIllegalCharacters(String s) { - StringBuilder result = new StringBuilder(); - int length = s.length(); - for (int i = 0; i < length; i++) { - char c = s.charAt(i); - - /* - * An RFC822 atom can contain any ASCII printing character - * except for periods and any of the following punctuation. - * A local-part can contain multiple atoms, concatenated by - * periods, so do allow periods here. - */ - - if (c <= ' ' || c > '~') { - continue; - } - - if (c == '(' || c == ')' || c == '<' || c == '>' || - c == '@' || c == ',' || c == ';' || c == ':' || - c == '\\' || c == '"' || c == '[' || c == ']') { - continue; - } - - result.append(c); - } - return result.toString(); - } - - /** - * {@inheritDoc} - */ - public CharSequence fixText(CharSequence cs) { - // Return an empty string if the email address only contains spaces, \n or \t - if (TextUtils.getTrimmedLength(cs) == 0) return ""; - - Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(cs); - StringBuilder sb = new StringBuilder(); - - for (int i = 0; i < tokens.length; i++) { - String text = tokens[i].getAddress(); - int index = text.indexOf('@'); - if (index < 0) { - // If there is no @, just append the domain of the account - tokens[i].setAddress(removeIllegalCharacters(text) + "@" + mDomain); - } else { - // Otherwise, remove the illegal characters on both sides of the '@' - String fix = removeIllegalCharacters(text.substring(0, index)); - String domain = removeIllegalCharacters(text.substring(index + 1)); - tokens[i].setAddress(fix + "@" + (domain.length() != 0 ? domain : mDomain)); - } - - sb.append(tokens[i].toString()); - if (i + 1 < tokens.length) { - sb.append(", "); - } - } - - return sb; - } -} diff --git a/core/java/android/text/util/package.html b/core/java/android/text/util/package.html deleted file mode 100644 index d9312aa2..0000000 --- a/core/java/android/text/util/package.html +++ /dev/null @@ -1,6 +0,0 @@ -<HTML> -<BODY> -Utilities for converting identifiable text strings into clickable links -and creating RFC 822-type message (SMTP) tokens. -</BODY> -</HTML>
\ No newline at end of file |