blob: d00e8c384886699b68c7839c43e60588924ae153 [file] [log] [blame]
John Reckfb3017f2010-10-26 19:01:24 -07001/*
2 * Copyright (C) 2010 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 */
Michael Kolb8233fac2010-10-26 16:08:53 -070016
Bijan Amirzada41242f22014-03-21 12:12:18 -070017package com.android.browser;
John Reckfb3017f2010-10-26 19:01:24 -070018
Michael Kolb8233fac2010-10-26 16:08:53 -070019import android.net.Uri;
20import android.util.Patterns;
21import android.webkit.URLUtil;
22
John Reckfb3017f2010-10-26 19:01:24 -070023import java.util.regex.Matcher;
24import java.util.regex.Pattern;
Vivek Sekharcc4bc5e2014-05-13 12:46:37 -070025import java.util.HashSet;
26import java.util.Arrays;
John Reckfb3017f2010-10-26 19:01:24 -070027
Michael Kolb8233fac2010-10-26 16:08:53 -070028/**
29 * Utility methods for Url manipulation
30 */
John Reckfb3017f2010-10-26 19:01:24 -070031public class UrlUtils {
Vivek Sekharcc4bc5e2014-05-13 12:46:37 -070032 public static final String[] DOWNLOADABLE_SCHEMES_VALUES = new String[]
33 { "data", "filesystem", "http", "https" };
34
35 private static final HashSet<String> DOWNLOADABLE_SCHEMES =
36 new HashSet<String>(Arrays.asList(DOWNLOADABLE_SCHEMES_VALUES));
John Reckfb3017f2010-10-26 19:01:24 -070037
Michael Kolb8233fac2010-10-26 16:08:53 -070038 static final Pattern ACCEPTED_URI_SCHEMA = Pattern.compile(
39 "(?i)" + // switch on case insensitive matching
40 "(" + // begin group for schema
41 "(?:http|https|file):\\/\\/" +
Patrick Scottb92bbb42011-01-05 11:38:58 -050042 "|(?:inline|data|about|javascript):" +
Michael Kolb8233fac2010-10-26 16:08:53 -070043 ")" +
44 "(.*)" );
45
46 // Google search
47 private final static String QUICKSEARCH_G = "http://www.google.com/m?q=%s";
48 private final static String QUERY_PLACE_HOLDER = "%s";
49
John Reckfe5b94d2011-09-06 10:21:29 -070050 // Regular expression to strip http:// and optionally
John Reck434e9f82011-08-10 18:16:52 -070051 // the trailing slash
52 private static final Pattern STRIP_URL_PATTERN =
John Reckfe5b94d2011-09-06 10:21:29 -070053 Pattern.compile("^http://(.*?)/?$");
John Reckfb3017f2010-10-26 19:01:24 -070054
55 private UrlUtils() { /* cannot be instantiated */ }
56
57 /**
John Reckfe5b94d2011-09-06 10:21:29 -070058 * Strips the provided url of preceding "http://" and any trailing "/". Does not
John Reckfb3017f2010-10-26 19:01:24 -070059 * strip "https://". If the provided string cannot be stripped, the original string
60 * is returned.
61 *
62 * TODO: Put this in TextUtils to be used by other packages doing something similar.
63 *
64 * @param url a url to strip, like "http://www.google.com/"
John Reckfe5b94d2011-09-06 10:21:29 -070065 * @return a stripped url like "www.google.com", or the original string if it could
John Reckfb3017f2010-10-26 19:01:24 -070066 * not be stripped
67 */
John Reck2cb9dc22011-05-11 16:12:27 -070068 public static String stripUrl(String url) {
John Reckfb3017f2010-10-26 19:01:24 -070069 if (url == null) return null;
70 Matcher m = STRIP_URL_PATTERN.matcher(url);
John Reck434e9f82011-08-10 18:16:52 -070071 if (m.matches()) {
72 return m.group(1);
John Reckfb3017f2010-10-26 19:01:24 -070073 } else {
74 return url;
75 }
76 }
Michael Kolb8233fac2010-10-26 16:08:53 -070077
78 protected static String smartUrlFilter(Uri inUri) {
79 if (inUri != null) {
80 return smartUrlFilter(inUri.toString());
81 }
82 return null;
83 }
84
85 /**
86 * Attempts to determine whether user input is a URL or search
87 * terms. Anything with a space is passed to search.
88 *
89 * Converts to lowercase any mistakenly uppercased schema (i.e.,
90 * "Http://" converts to "http://"
91 *
92 * @return Original or modified URL
93 *
94 */
John Reck961d35d2011-06-23 09:45:54 -070095 public static String smartUrlFilter(String url) {
John Reck71e51422011-07-01 16:49:28 -070096 return smartUrlFilter(url, true);
97 }
Michael Kolb8233fac2010-10-26 16:08:53 -070098
Vivek Sekharcc4bc5e2014-05-13 12:46:37 -070099 public static boolean isDownloadableScheme(Uri uri) {
100 return DOWNLOADABLE_SCHEMES.contains(uri.getScheme());
101 }
102
103 public static boolean isDownloadableScheme(String uri) {
104 try {
105 return isDownloadableScheme(Uri.parse(uri));
106 } catch (Exception e) {
107 return false;
108 }
109 }
110
John Reck71e51422011-07-01 16:49:28 -0700111 /**
112 * Attempts to determine whether user input is a URL or search
113 * terms. Anything with a space is passed to search if canBeSearch is true.
114 *
115 * Converts to lowercase any mistakenly uppercased schema (i.e.,
116 * "Http://" converts to "http://"
117 *
118 * @param canBeSearch If true, will return a search url if it isn't a valid
119 * URL. If false, invalid URLs will return null
120 * @return Original or modified URL
121 *
122 */
123 public static String smartUrlFilter(String url, boolean canBeSearch) {
Michael Kolb8233fac2010-10-26 16:08:53 -0700124 String inUrl = url.trim();
125 boolean hasSpace = inUrl.indexOf(' ') != -1;
126
127 Matcher matcher = ACCEPTED_URI_SCHEMA.matcher(inUrl);
128 if (matcher.matches()) {
129 // force scheme to lowercase
130 String scheme = matcher.group(1);
131 String lcScheme = scheme.toLowerCase();
132 if (!lcScheme.equals(scheme)) {
133 inUrl = lcScheme + matcher.group(2);
134 }
John Reck71e51422011-07-01 16:49:28 -0700135 if (hasSpace && Patterns.WEB_URL.matcher(inUrl).matches()) {
Michael Kolb8233fac2010-10-26 16:08:53 -0700136 inUrl = inUrl.replace(" ", "%20");
137 }
138 return inUrl;
139 }
140 if (!hasSpace) {
141 if (Patterns.WEB_URL.matcher(inUrl).matches()) {
142 return URLUtil.guessUrl(inUrl);
143 }
144 }
John Reck71e51422011-07-01 16:49:28 -0700145 if (canBeSearch) {
146 return URLUtil.composeSearchUrl(inUrl,
147 QUICKSEARCH_G, QUERY_PLACE_HOLDER);
148 }
149 return null;
Michael Kolb8233fac2010-10-26 16:08:53 -0700150 }
151
kaiyiz6e5b3e02013-08-19 20:02:01 +0800152 public static String fixUrl(String inUrl) {
Michael Kolb8233fac2010-10-26 16:08:53 -0700153 // FIXME: Converting the url to lower case
154 // duplicates functionality in smartUrlFilter().
155 // However, changing all current callers of fixUrl to
156 // call smartUrlFilter in addition may have unwanted
157 // consequences, and is deferred for now.
158 int colon = inUrl.indexOf(':');
159 boolean allLower = true;
160 for (int index = 0; index < colon; index++) {
161 char ch = inUrl.charAt(index);
162 if (!Character.isLetter(ch)) {
163 break;
164 }
165 allLower &= Character.isLowerCase(ch);
166 if (index == colon - 1 && !allLower) {
167 inUrl = inUrl.substring(0, colon).toLowerCase()
168 + inUrl.substring(colon);
169 }
170 }
171 if (inUrl.startsWith("http://") || inUrl.startsWith("https://"))
172 return inUrl;
173 if (inUrl.startsWith("http:") ||
174 inUrl.startsWith("https:")) {
175 if (inUrl.startsWith("http:/") || inUrl.startsWith("https:/")) {
176 inUrl = inUrl.replaceFirst("/", "//");
177 } else inUrl = inUrl.replaceFirst(":", "://");
178 }
179 return inUrl;
180 }
181
John Reck324d4402011-01-11 16:56:42 -0800182 // Returns the filtered URL. Cannot return null, but can return an empty string
183 /* package */ static String filteredUrl(String inUrl) {
184 if (inUrl == null) {
185 return "";
186 }
John Recke44e5622011-01-27 17:47:46 -0800187 if (inUrl.startsWith("content:")
188 || inUrl.startsWith("browser:")) {
John Reck324d4402011-01-11 16:56:42 -0800189 return "";
190 }
191 return inUrl;
192 }
193
John Reckfb3017f2010-10-26 19:01:24 -0700194}