19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.net;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Set;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.StringTokenizer;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sanitizes the Query portion of a URL. Simple example:
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <code>
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * UrlQuerySanitizer sanitizer = new UrlQuerySanitizer();
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * sanitizer.setAllowUnregisteredParamaters(true);
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * sanitizer.parseUrl("http://example.com/?name=Joe+User");
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * String name = sanitizer.getValue("name"));
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * // name now contains "Joe_User"
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </code>
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Register ValueSanitizers to customize the way individual
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * parameters are sanitized:
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <code>
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * UrlQuerySanitizer sanitizer = new UrlQuerySanitizer();
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * sanitizer.registerParamater("name", UrlQuerySanitizer.createSpaceLegal());
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * sanitizer.parseUrl("http://example.com/?name=Joe+User");
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * String name = sanitizer.getValue("name"));
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * // name now contains "Joe User". (The string is first decoded, which
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * // converts the '+' to a ' '. Then the string is sanitized, which
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * // converts the ' ' to an '_'. (The ' ' is converted because the default
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * unregistered parameter sanitizer does not allow any special characters,
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and ' ' is a special character.)
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </code>
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * There are several ways to create ValueSanitizers. In order of increasing
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * sophistication:
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ol>
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>Call one of the UrlQuerySanitizer.createXXX() methods.
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>Construct your own instance of
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * UrlQuerySanitizer.IllegalCharacterValueSanitizer.
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>Subclass UrlQuerySanitizer.ValueSanitizer to define your own value
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * sanitizer.
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ol>
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class UrlQuerySanitizer {
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * A simple tuple that holds parameter-value pairs.
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public class ParameterValuePair {
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Construct a parameter-value tuple.
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param parameter an unencoded parameter
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param value an unencoded value
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public ParameterValuePair(String parameter,
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String value) {
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mParameter = parameter;
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mValue = value;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * The unencoded parameter
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String mParameter;
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * The unencoded value
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String mValue;
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final private HashMap<String, ValueSanitizer> mSanitizers =
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new HashMap<String, ValueSanitizer>();
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final private HashMap<String, String> mEntries =
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new HashMap<String, String>();
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final private ArrayList<ParameterValuePair> mEntriesList =
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new ArrayList<ParameterValuePair>();
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mAllowUnregisteredParamaters;
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mPreferFirstRepeatedParameter;
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ValueSanitizer mUnregisteredParameterValueSanitizer =
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        getAllIllegal();
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * A functor used to sanitize a single query value.
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static interface ValueSanitizer {
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Sanitize an unencoded value.
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param value
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @return the sanitized unencoded value
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String sanitize(String value);
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sanitize values based on which characters they contain. Illegal
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * characters are replaced with either space or '_', depending upon
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * whether space is a legal character or not.
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static class IllegalCharacterValueSanitizer implements
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ValueSanitizer {
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private int mFlags;
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Allow space (' ') characters.
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final static int SPACE_OK =              1 << 0;
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Allow whitespace characters other than space. The
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * other whitespace characters are
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * '\t' '\f' '\n' '\r' and '\0x000b' (vertical tab)
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final static int OTHER_WHITESPACE_OK =  1 << 1;
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Allow characters with character codes 128 to 255.
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final static int NON_7_BIT_ASCII_OK =    1 << 2;
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Allow double quote characters. ('"')
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final static int DQUOTE_OK =             1 << 3;
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Allow single quote characters. ('\'')
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final static int SQUOTE_OK =             1 << 4;
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Allow less-than characters. ('<')
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final static int LT_OK =                 1 << 5;
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Allow greater-than characters. ('>')
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final static int GT_OK =                 1 << 6;
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Allow ampersand characters ('&')
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final static int AMP_OK =                1 << 7;
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Allow percent-sign characters ('%')
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final static int PCT_OK =                1 << 8;
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Allow nul characters ('\0')
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final static int NUL_OK =                1 << 9;
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Allow text to start with a script URL
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * such as "javascript:" or "vbscript:"
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final static int SCRIPT_URL_OK =         1 << 10;
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Mask with all fields set to OK
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final static int ALL_OK =                0x7ff;
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Mask with both regular space and other whitespace OK
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final static int ALL_WHITESPACE_OK =
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SPACE_OK | OTHER_WHITESPACE_OK;
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Common flag combinations:
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <ul>
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <li>Deny all special characters.
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <li>Deny script URLs.
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * </ul>
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final static int ALL_ILLEGAL =
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            0;
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <ul>
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <li>Allow all special characters except Nul. ('\0').
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <li>Allow script URLs.
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * </ul>
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final static int ALL_BUT_NUL_LEGAL =
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ALL_OK & ~NUL_OK;
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <ul>
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <li>Allow all special characters except for:
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <ul>
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *  <li>whitespace characters
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *  <li>Nul ('\0')
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * </ul>
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <li>Allow script URLs.
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * </ul>
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final static int ALL_BUT_WHITESPACE_LEGAL =
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ALL_OK & ~(ALL_WHITESPACE_OK | NUL_OK);
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <ul>
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <li>Allow characters used by encoded URLs.
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <li>Deny script URLs.
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * </ul>
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final static int URL_LEGAL =
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            NON_7_BIT_ASCII_OK | SQUOTE_OK | AMP_OK | PCT_OK;
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <ul>
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <li>Allow characters used by encoded URLs.
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <li>Allow spaces.
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <li>Deny script URLs.
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * </ul>
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final static int URL_AND_SPACE_LEGAL =
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            URL_LEGAL | SPACE_OK;
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <ul>
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <li>Allow ampersand.
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <li>Deny script URLs.
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * </ul>
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final static int AMP_LEGAL =
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            AMP_OK;
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <ul>
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <li>Allow ampersand.
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <li>Allow space.
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <li>Deny script URLs.
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * </ul>
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final static int AMP_AND_SPACE_LEGAL =
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            AMP_OK | SPACE_OK;
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <ul>
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <li>Allow space.
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <li>Deny script URLs.
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * </ul>
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final static int SPACE_LEGAL =
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SPACE_OK;
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <ul>
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <li>Allow all but.
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <ul>
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *  <li>Nul ('\0')
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *  <li>Angle brackets ('<', '>')
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * </ul>
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <li>Deny script URLs.
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * </ul>
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final static int ALL_BUT_NUL_AND_ANGLE_BRACKETS_LEGAL =
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ALL_OK & ~(NUL_OK | LT_OK | GT_OK);
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *  Script URL definitions
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private final static String JAVASCRIPT_PREFIX = "javascript:";
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private final static String VBSCRIPT_PREFIX = "vbscript:";
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private final static int MIN_SCRIPT_PREFIX_LENGTH = Math.min(
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                JAVASCRIPT_PREFIX.length(), VBSCRIPT_PREFIX.length());
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Construct a sanitizer. The parameters set the behavior of the
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * sanitizer.
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param flags some combination of the XXX_OK flags.
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public IllegalCharacterValueSanitizer(
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int flags) {
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFlags = flags;
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Sanitize a value.
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <ol>
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <li>If script URLs are not OK, the will be removed.
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <li>If neither spaces nor other white space is OK, then
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * white space will be trimmed from the beginning and end of
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * the URL. (Just the actual white space characters are trimmed, not
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * other control codes.)
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <li> Illegal characters will be replaced with
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * either ' ' or '_', depending on whether a space is itself a
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * legal character.
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * </ol>
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param value
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @return the sanitized value
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String sanitize(String value) {
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (value == null) {
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return null;
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int length = value.length();
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((mFlags & SCRIPT_URL_OK) != 0) {
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (length >= MIN_SCRIPT_PREFIX_LENGTH) {
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String asLower = value.toLowerCase();
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (asLower.startsWith(JAVASCRIPT_PREFIX)  ||
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        asLower.startsWith(VBSCRIPT_PREFIX)) {
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        return "";
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If whitespace isn't OK, get rid of whitespace at beginning
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // and end of value.
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ( (mFlags & ALL_WHITESPACE_OK) == 0) {
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                value = trimWhitespace(value);
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // The length could have changed, so we need to correct
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // the length variable.
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                length = value.length();
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            StringBuilder stringBuilder = new StringBuilder(length);
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for(int i = 0; i < length; i++) {
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                char c = value.charAt(i);
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!characterIsLegal(c)) {
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if ((mFlags & SPACE_OK) != 0) {
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        c = ' ';
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    else {
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        c = '_';
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                stringBuilder.append(c);
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return stringBuilder.toString();
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Trim whitespace from the beginning and end of a string.
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <p>
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Note: can't use {@link String#trim} because {@link String#trim} has a
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * different definition of whitespace than we want.
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param value the string to trim
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @return the trimmed string
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private String trimWhitespace(String value) {
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int start = 0;
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int last = value.length() - 1;
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int end = last;
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while (start <= end && isWhitespace(value.charAt(start))) {
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                start++;
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while (end >= start && isWhitespace(value.charAt(end))) {
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                end--;
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (start == 0 && end == last) {
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return value;
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return value.substring(start, end + 1);
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Check if c is whitespace.
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param c character to test
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @return true if c is a whitespace character
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private boolean isWhitespace(char c) {
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch(c) {
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case ' ':
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case '\t':
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case '\f':
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case '\n':
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case '\r':
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case 11: /* VT */
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            default:
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Check whether an individual character is legal. Uses the
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * flag bit-set passed into the constructor.
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param c
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @return true if c is a legal character
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private boolean characterIsLegal(char c) {
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch(c) {
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case ' ' : return (mFlags & SPACE_OK) != 0;
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case '\t': case '\f': case '\n': case '\r': case 11: /* VT */
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project              return (mFlags & OTHER_WHITESPACE_OK) != 0;
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case '\"': return (mFlags & DQUOTE_OK) != 0;
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case '\'': return (mFlags & SQUOTE_OK) != 0;
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case '<' : return (mFlags & LT_OK) != 0;
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case '>' : return (mFlags & GT_OK) != 0;
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case '&' : return (mFlags & AMP_OK) != 0;
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case '%' : return (mFlags & PCT_OK) != 0;
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case '\0': return (mFlags & NUL_OK) != 0;
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            default  : return (c >= 32 && c < 127) ||
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ((c >= 128) && ((mFlags & NON_7_BIT_ASCII_OK) != 0));
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Get the current value sanitizer used when processing
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * unregistered parameter values.
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <b>Note:</b> The default unregistered parameter value sanitizer is
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * one that doesn't allow any special characters, similar to what
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is returned by calling createAllIllegal.
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the current ValueSanitizer used to sanitize unregistered
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * parameter values.
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public ValueSanitizer getUnregisteredParameterValueSanitizer() {
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mUnregisteredParameterValueSanitizer;
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set the value sanitizer used when processing unregistered
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * parameter values.
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param sanitizer set the ValueSanitizer used to sanitize unregistered
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * parameter values.
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setUnregisteredParameterValueSanitizer(
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ValueSanitizer sanitizer) {
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mUnregisteredParameterValueSanitizer = sanitizer;
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Private fields for singleton sanitizers:
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final ValueSanitizer sAllIllegal =
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new IllegalCharacterValueSanitizer(
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                IllegalCharacterValueSanitizer.ALL_ILLEGAL);
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final ValueSanitizer sAllButNulLegal =
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new IllegalCharacterValueSanitizer(
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                IllegalCharacterValueSanitizer.ALL_BUT_NUL_LEGAL);
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final ValueSanitizer sAllButWhitespaceLegal =
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new IllegalCharacterValueSanitizer(
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                IllegalCharacterValueSanitizer.ALL_BUT_WHITESPACE_LEGAL);
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final ValueSanitizer sURLLegal =
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new IllegalCharacterValueSanitizer(
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                IllegalCharacterValueSanitizer.URL_LEGAL);
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final ValueSanitizer sUrlAndSpaceLegal =
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new IllegalCharacterValueSanitizer(
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                IllegalCharacterValueSanitizer.URL_AND_SPACE_LEGAL);
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final ValueSanitizer sAmpLegal =
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new IllegalCharacterValueSanitizer(
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                IllegalCharacterValueSanitizer.AMP_LEGAL);
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final ValueSanitizer sAmpAndSpaceLegal =
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new IllegalCharacterValueSanitizer(
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                IllegalCharacterValueSanitizer.AMP_AND_SPACE_LEGAL);
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final ValueSanitizer sSpaceLegal =
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new IllegalCharacterValueSanitizer(
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                IllegalCharacterValueSanitizer.SPACE_LEGAL);
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final ValueSanitizer sAllButNulAndAngleBracketsLegal =
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new IllegalCharacterValueSanitizer(
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                IllegalCharacterValueSanitizer.ALL_BUT_NUL_AND_ANGLE_BRACKETS_LEGAL);
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return a value sanitizer that does not allow any special characters,
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and also does not allow script URLs.
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a value sanitizer
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final ValueSanitizer getAllIllegal() {
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return sAllIllegal;
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return a value sanitizer that allows everything except Nul ('\0')
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * characters. Script URLs are allowed.
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a value sanitizer
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final ValueSanitizer getAllButNulLegal() {
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return sAllButNulLegal;
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return a value sanitizer that allows everything except Nul ('\0')
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * characters, space (' '), and other whitespace characters.
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Script URLs are allowed.
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a value sanitizer
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final ValueSanitizer getAllButWhitespaceLegal() {
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return sAllButWhitespaceLegal;
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return a value sanitizer that allows all the characters used by
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * encoded URLs. Does not allow script URLs.
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a value sanitizer
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final ValueSanitizer getUrlLegal() {
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return sURLLegal;
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return a value sanitizer that allows all the characters used by
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * encoded URLs and allows spaces, which are not technically legal
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * in encoded URLs, but commonly appear anyway.
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Does not allow script URLs.
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a value sanitizer
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final ValueSanitizer getUrlAndSpaceLegal() {
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return sUrlAndSpaceLegal;
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return a value sanitizer that does not allow any special characters
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * except ampersand ('&'). Does not allow script URLs.
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a value sanitizer
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final ValueSanitizer getAmpLegal() {
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return sAmpLegal;
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return a value sanitizer that does not allow any special characters
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * except ampersand ('&') and space (' '). Does not allow script URLs.
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a value sanitizer
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final ValueSanitizer getAmpAndSpaceLegal() {
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return sAmpAndSpaceLegal;
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return a value sanitizer that does not allow any special characters
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * except space (' '). Does not allow script URLs.
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a value sanitizer
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final ValueSanitizer getSpaceLegal() {
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return sSpaceLegal;
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return a value sanitizer that allows any special characters
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * except angle brackets ('<' and '>') and Nul ('\0').
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Allows script URLs.
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a value sanitizer
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final ValueSanitizer getAllButNulAndAngleBracketsLegal() {
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return sAllButNulAndAngleBracketsLegal;
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Constructs a UrlQuerySanitizer.
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Defaults:
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <ul>
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>unregistered parameters are not allowed.
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>the last instance of a repeated parameter is preferred.
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>The default value sanitizer is an AllIllegal value sanitizer.
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <ul>
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public UrlQuerySanitizer() {
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Constructs a UrlQuerySanitizer and parse a URL.
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This constructor is provided for convenience when the
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * default parsing behavior is acceptable.
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Because the URL is parsed before the constructor returns, there isn't
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a chance to configure the sanitizer to change the parsing behavior.
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <code>
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * UrlQuerySanitizer sanitizer = new UrlQuerySanitizer(myUrl);
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * String name = sanitizer.getValue("name");
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * </code>
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Defaults:
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <ul>
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>unregistered parameters <em>are</em> allowed.
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>the last instance of a repeated parameter is preferred.
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>The default value sanitizer is an AllIllegal value sanitizer.
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <ul>
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public UrlQuerySanitizer(String url) {
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setAllowUnregisteredParamaters(true);
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        parseUrl(url);
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Parse the query parameters out of an encoded URL.
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Works by extracting the query portion from the URL and then
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * calling parseQuery(). If there is no query portion it is
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * treated as if the query portion is an empty string.
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param url the encoded URL to parse.
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void parseUrl(String url) {
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int queryIndex = url.indexOf('?');
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String query;
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (queryIndex >= 0) {
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            query = url.substring(queryIndex + 1);
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        else {
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            query = "";
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        parseQuery(query);
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Parse a query. A query string is any number of parameter-value clauses
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * separated by any non-zero number of ampersands. A parameter-value clause
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is a parameter followed by an equal sign, followed by a value. If the
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * equal sign is missing, the value is assumed to be the empty string.
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param query the query to parse.
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void parseQuery(String query) {
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        clear();
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Split by '&'
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        StringTokenizer tokenizer = new StringTokenizer(query, "&");
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while(tokenizer.hasMoreElements()) {
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String attributeValuePair = tokenizer.nextToken();
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (attributeValuePair.length() > 0) {
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int assignmentIndex = attributeValuePair.indexOf('=');
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (assignmentIndex < 0) {
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // No assignment found, treat as if empty value
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    parseEntry(attributeValuePair, "");
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                else {
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    parseEntry(attributeValuePair.substring(0, assignmentIndex),
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            attributeValuePair.substring(assignmentIndex + 1));
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Get a set of all of the parameters found in the sanitized query.
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Note: Do not modify this set. Treat it as a read-only set.
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return all the parameters found in the current query.
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Set<String> getParameterSet() {
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mEntries.keySet();
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * An array list of all of the parameter value pairs in the sanitized
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * query, in the order they appeared in the query. May contain duplicate
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * parameters.
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p class="note"><b>Note:</b> Do not modify this list. Treat it as a read-only list.</p>
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<ParameterValuePair> getParameterList() {
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mEntriesList;
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Check if a parameter exists in the current sanitized query.
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param parameter the unencoded name of a parameter.
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the paramater exists in the current sanitized queary.
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean hasParameter(String parameter) {
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mEntries.containsKey(parameter);
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Get the value for a parameter in the current sanitized query.
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns null if the parameter does not
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * exit.
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param parameter the unencoded name of a parameter.
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the sanitized unencoded value of the parameter,
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * or null if the parameter does not exist.
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String getValue(String parameter) {
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mEntries.get(parameter);
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Register a value sanitizer for a particular parameter. Can also be used
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to replace or remove an already-set value sanitizer.
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Registering a non-null value sanitizer for a particular parameter
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * makes that parameter a registered parameter.
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param parameter an unencoded parameter name
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param valueSanitizer the value sanitizer to use for a particular
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * parameter. May be null in order to unregister that parameter.
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #getAllowUnregisteredParamaters()
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void registerParameter(String parameter,
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ValueSanitizer valueSanitizer) {
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (valueSanitizer == null) {
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSanitizers.remove(parameter);
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mSanitizers.put(parameter, valueSanitizer);
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Register a value sanitizer for an array of parameters.
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param parameters An array of unencoded parameter names.
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param valueSanitizer
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #registerParameter
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void registerParameters(String[] parameters,
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ValueSanitizer valueSanitizer) {
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int length = parameters.length;
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for(int i = 0; i < length; i++) {
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSanitizers.put(parameters[i], valueSanitizer);
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set whether or not unregistered parameters are allowed. If they
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * are not allowed, then they will be dropped when a query is sanitized.
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Defaults to false.
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param allowUnregisteredParamaters true to allow unregistered parameters.
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #getAllowUnregisteredParamaters()
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setAllowUnregisteredParamaters(
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean allowUnregisteredParamaters) {
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAllowUnregisteredParamaters = allowUnregisteredParamaters;
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Get whether or not unregistered parameters are allowed. If not
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * allowed, they will be dropped when a query is parsed.
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if unregistered parameters are allowed.
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setAllowUnregisteredParamaters(boolean)
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean getAllowUnregisteredParamaters() {
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mAllowUnregisteredParamaters;
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set whether or not the first occurrence of a repeated parameter is
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * preferred. True means the first repeated parameter is preferred.
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * False means that the last repeated parameter is preferred.
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The preferred parameter is the one that is returned when getParameter
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is called.
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * defaults to false.
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param preferFirstRepeatedParameter True if the first repeated
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * parameter is preferred.
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #getPreferFirstRepeatedParameter()
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setPreferFirstRepeatedParameter(
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean preferFirstRepeatedParameter) {
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPreferFirstRepeatedParameter = preferFirstRepeatedParameter;
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Get whether or not the first occurrence of a repeated parameter is
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * preferred.
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the first occurrence of a repeated parameter is
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * preferred.
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setPreferFirstRepeatedParameter(boolean)
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean getPreferFirstRepeatedParameter() {
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mPreferFirstRepeatedParameter;
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Parse an escaped parameter-value pair. The default implementation
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * unescapes both the parameter and the value, then looks up the
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * effective value sanitizer for the parameter and uses it to sanitize
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the value. If all goes well then addSanitizedValue is called with
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the unescaped parameter and the sanitized unescaped value.
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param parameter an escaped parameter
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param value an unsanitzied escaped value
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void parseEntry(String parameter, String value) {
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String unescapedParameter = unescape(parameter);
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         ValueSanitizer valueSanitizer =
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            getEffectiveValueSanitizer(unescapedParameter);
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (valueSanitizer == null) {
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String unescapedValue = unescape(value);
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String sanitizedValue = valueSanitizer.sanitize(unescapedValue);
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        addSanitizedEntry(unescapedParameter, sanitizedValue);
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Record a sanitized parameter-value pair. Override if you want to
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * do additional filtering or validation.
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param parameter an unescaped parameter
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param value a sanitized unescaped value
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void addSanitizedEntry(String parameter, String value) {
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEntriesList.add(
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                new ParameterValuePair(parameter, value));
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mPreferFirstRepeatedParameter) {
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mEntries.containsKey(parameter)) {
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEntries.put(parameter, value);
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Get the value sanitizer for a parameter. Returns null if there
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is no value sanitizer registered for the parameter.
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param parameter the unescaped parameter
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the currently registered value sanitizer for this parameter.
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #registerParameter(String, android.net.UrlQuerySanitizer.ValueSanitizer)
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public ValueSanitizer getValueSanitizer(String parameter) {
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mSanitizers.get(parameter);
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Get the effective value sanitizer for a parameter. Like getValueSanitizer,
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * except if there is no value sanitizer registered for a parameter, and
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * unregistered paramaters are allowed, then the default value sanitizer is
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * returned.
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param parameter an unescaped parameter
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the effective value sanitizer for a parameter.
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public ValueSanitizer getEffectiveValueSanitizer(String parameter) {
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ValueSanitizer sanitizer = getValueSanitizer(parameter);
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (sanitizer == null && mAllowUnregisteredParamaters) {
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sanitizer = getUnregisteredParameterValueSanitizer();
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return sanitizer;
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Unescape an escaped string.
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <ul>
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>'+' characters are replaced by
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * ' ' characters.
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>Valid "%xx" escape sequences are replaced by the
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * corresponding unescaped character.
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>Invalid escape sequences such as %1z", are passed through unchanged.
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <ol>
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param string the escaped string
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the unescaped string.
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String unescape(String string) {
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Early exit if no escaped characters.
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int firstEscape = string.indexOf('%');
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ( firstEscape < 0) {
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            firstEscape = string.indexOf('+');
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (firstEscape < 0) {
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return string;
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int length = string.length();
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        StringBuilder stringBuilder = new StringBuilder(length);
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        stringBuilder.append(string.substring(0, firstEscape));
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = firstEscape; i < length; i++) {
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            char c = string.charAt(i);
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (c == '+') {
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                c = ' ';
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            else if ( c == '%' && i + 2 < length) {
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                char c1 = string.charAt(i + 1);
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                char c2 = string.charAt(i + 2);
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (isHexDigit(c1) && isHexDigit(c2)) {
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    c = (char) (decodeHexDigit(c1) * 16 + decodeHexDigit(c2));
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    i += 2;
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stringBuilder.append(c);
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return stringBuilder.toString();
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Test if a character is a hexidecimal digit. Both upper case and lower
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * case hex digits are allowed.
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param c the character to test
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if c is a hex digit.
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected boolean isHexDigit(char c) {
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return decodeHexDigit(c) >= 0;
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Convert a character that represents a hexidecimal digit into an integer.
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If the character is not a hexidecimal digit, then -1 is returned.
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Both upper case and lower case hex digits are allowed.
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param c the hexidecimal digit.
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the integer value of the hexidecimal digit.
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected int decodeHexDigit(char c) {
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (c >= '0' && c <= '9') {
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return c - '0';
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        else if (c >= 'A' && c <= 'F') {
8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return c - 'A' + 10;
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        else if (c >= 'a' && c <= 'f') {
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return c - 'a' + 10;
8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        else {
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Clear the existing entries. Called to get ready to parse a new
9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * query string.
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void clear() {
9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEntries.clear();
9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEntriesList.clear();
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
914