123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- /*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you 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 org.apache.cordova;
-
- import java.net.MalformedURLException;
- import java.util.ArrayList;
- import java.util.Iterator;
- import java.util.regex.Matcher;
- import java.util.regex.Pattern;
-
- import org.apache.cordova.LOG;
-
- import android.net.Uri;
-
- public class Whitelist {
- private static class URLPattern {
- public Pattern scheme;
- public Pattern host;
- public Integer port;
- public Pattern path;
-
- private String regexFromPattern(String pattern, boolean allowWildcards) {
- final String toReplace = "\\.[]{}()^$?+|";
- StringBuilder regex = new StringBuilder();
- for (int i=0; i < pattern.length(); i++) {
- char c = pattern.charAt(i);
- if (c == '*' && allowWildcards) {
- regex.append(".");
- } else if (toReplace.indexOf(c) > -1) {
- regex.append('\\');
- }
- regex.append(c);
- }
- return regex.toString();
- }
-
- public URLPattern(String scheme, String host, String port, String path) throws MalformedURLException {
- try {
- if (scheme == null || "*".equals(scheme)) {
- this.scheme = null;
- } else {
- this.scheme = Pattern.compile(regexFromPattern(scheme, false), Pattern.CASE_INSENSITIVE);
- }
- if ("*".equals(host)) {
- this.host = null;
- } else if (host.startsWith("*.")) {
- this.host = Pattern.compile("([a-z0-9.-]*\\.)?" + regexFromPattern(host.substring(2), false), Pattern.CASE_INSENSITIVE);
- } else {
- this.host = Pattern.compile(regexFromPattern(host, false), Pattern.CASE_INSENSITIVE);
- }
- if (port == null || "*".equals(port)) {
- this.port = null;
- } else {
- this.port = Integer.parseInt(port,10);
- }
- if (path == null || "/*".equals(path)) {
- this.path = null;
- } else {
- this.path = Pattern.compile(regexFromPattern(path, true));
- }
- } catch (NumberFormatException e) {
- throw new MalformedURLException("Port must be a number");
- }
- }
-
- public boolean matches(Uri uri) {
- try {
- return ((scheme == null || scheme.matcher(uri.getScheme()).matches()) &&
- (host == null || host.matcher(uri.getHost()).matches()) &&
- (port == null || port.equals(uri.getPort())) &&
- (path == null || path.matcher(uri.getPath()).matches()));
- } catch (Exception e) {
- LOG.d(TAG, e.toString());
- return false;
- }
- }
- }
-
- private ArrayList<URLPattern> whiteList;
-
- public static final String TAG = "Whitelist";
-
- public Whitelist() {
- this.whiteList = new ArrayList<URLPattern>();
- }
-
- /* Match patterns (from http://developer.chrome.com/extensions/match_patterns.html)
- *
- * <url-pattern> := <scheme>://<host><path>
- * <scheme> := '*' | 'http' | 'https' | 'file' | 'ftp' | 'chrome-extension'
- * <host> := '*' | '*.' <any char except '/' and '*'>+
- * <path> := '/' <any chars>
- *
- * We extend this to explicitly allow a port attached to the host, and we allow
- * the scheme to be omitted for backwards compatibility. (Also host is not required
- * to begin with a "*" or "*.".)
- */
- public void addWhiteListEntry(String origin, boolean subdomains) {
- if (whiteList != null) {
- try {
- // Unlimited access to network resources
- if (origin.compareTo("*") == 0) {
- LOG.d(TAG, "Unlimited access to network resources");
- whiteList = null;
- }
- else { // specific access
- Pattern parts = Pattern.compile("^((\\*|[A-Za-z-]+):(//)?)?(\\*|((\\*\\.)?[^*/:]+))?(:(\\d+))?(/.*)?");
- Matcher m = parts.matcher(origin);
- if (m.matches()) {
- String scheme = m.group(2);
- String host = m.group(4);
- // Special case for two urls which are allowed to have empty hosts
- if (("file".equals(scheme) || "content".equals(scheme)) && host == null) host = "*";
- String port = m.group(8);
- String path = m.group(9);
- if (scheme == null) {
- // XXX making it stupid friendly for people who forget to include protocol/SSL
- whiteList.add(new URLPattern("http", host, port, path));
- whiteList.add(new URLPattern("https", host, port, path));
- } else {
- whiteList.add(new URLPattern(scheme, host, port, path));
- }
- }
- }
- } catch (Exception e) {
- LOG.d(TAG, "Failed to add origin %s", origin);
- }
- }
- }
-
-
- /**
- * Determine if URL is in approved list of URLs to load.
- *
- * @param uri
- * @return true if wide open or whitelisted
- */
- public boolean isUrlWhiteListed(String uri) {
- // If there is no whitelist, then it's wide open
- if (whiteList == null) return true;
-
- Uri parsedUri = Uri.parse(uri);
- // Look for match in white list
- Iterator<URLPattern> pit = whiteList.iterator();
- while (pit.hasNext()) {
- URLPattern p = pit.next();
- if (p.matches(parsedUri)) {
- return true;
- }
- }
- return false;
- }
-
- }
|