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));
                }
                if ("*".equals(host)) {
                    this.host = null;
                } else if (host.startsWith("*.")) {
                    this.host = Pattern.compile("([a-z0-9.-]*\\.)?" + regexFromPattern(host.substring(2), false));
                } else {
                    this.host = Pattern.compile(regexFromPattern(host, false));
                }
                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-z-]+)://)?(\\*|((\\*\\.)?[^*/:]+))?(:(\\d+))?(/.*)?");
                    Matcher m = parts.matcher(origin);
                    if (m.matches()) {
                        String scheme = m.group(2);
                        String host = m.group(3);
                        // 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(7);
                        String path = m.group(8);
                        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
     */
    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;
    }

}

@@ -1,8 +1,867 @@
+/*%0A       Licensed to the Apache Software Foundation (ASF) under one%0A       or more contributor license agreements.  See the NOTICE file%0A       distributed with this work for additional information%0A       regarding copyright ownership.  The ASF licenses this file%0A       to you under the Apache License, Version 2.0 (the%0A       %22License%22); you may not use this file except in compliance%0A       with the License.  You may obtain a copy of the License at%0A%0A         http://www.apache.org/licenses/LICENSE-2.0%0A%0A       Unless required by applicable law or agreed to in writing,%0A       software distributed under the License is distributed on an%0A       %22AS IS%22 BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY%0A       KIND, either express or implied.  See the License for the%0A       specific language governing permissions and limitations%0A       under the License.%0A*/%0A
 package 

Add missing copyright header for Whitelist.java.