LoginFilter.java revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.text;
18
19/**
20 * Abstract class for filtering login-related text (user names and passwords)
21 *
22 */
23public abstract class LoginFilter implements InputFilter {
24    private boolean mAppendInvalid;  // whether to append or ignore invalid characters
25    /**
26     * Base constructor for LoginFilter
27     * @param appendInvalid whether or not to append invalid characters.
28     */
29    LoginFilter(boolean appendInvalid) {
30        mAppendInvalid = appendInvalid;
31    }
32
33    /**
34     * Default constructor for LoginFilter doesn't append invalid characters.
35     */
36    LoginFilter() {
37        mAppendInvalid = false;
38    }
39
40    /**
41     * This method is called when the buffer is going to replace the
42     * range <code>dstart &hellip; dend</code> of <code>dest</code>
43     * with the new text from the range <code>start &hellip; end</code>
44     * of <code>source</code>.  Returns the CharSequence that we want
45     * placed there instead, including an empty string
46     * if appropriate, or <code>null</code> to accept the original
47     * replacement.  Be careful to not to reject 0-length replacements,
48     * as this is what happens when you delete text.
49     */
50    public CharSequence filter(CharSequence source, int start, int end,
51            Spanned dest, int dstart, int dend) {
52        char[] out = new char[end - start]; // reserve enough space for whole string
53        int outidx = 0;
54        boolean changed = false;
55
56        onStart();
57
58        // Scan through beginning characters in dest, calling onInvalidCharacter()
59        // for each invalid character.
60        for (int i = 0; i < dstart; i++) {
61            char c = dest.charAt(i);
62            if (!isAllowed(c)) onInvalidCharacter(c);
63        }
64
65        // Scan through changed characters rejecting disallowed chars
66        for (int i = start; i < end; i++) {
67            char c = source.charAt(i);
68            if (isAllowed(c)) {
69                // Character allowed. Add it to the sequence.
70                out[outidx++] = c;
71            } else {
72                if (mAppendInvalid) out[outidx++] = c;
73                else changed = true; // we changed the original string
74                onInvalidCharacter(c);
75            }
76        }
77
78        // Scan through remaining characters in dest, calling onInvalidCharacter()
79        // for each invalid character.
80        for (int i = dend; i < dest.length(); i++) {
81            char c = dest.charAt(i);
82            if (!isAllowed(c)) onInvalidCharacter(c);
83        }
84
85        onStop();
86
87        if (!changed) {
88            return null;
89        }
90
91        String s = new String(out, 0, outidx);
92
93        if (source instanceof Spanned) {
94            SpannableString sp = new SpannableString(s);
95            TextUtils.copySpansFrom((Spanned) source,
96                                    start, end, null, sp, 0);
97            return sp;
98        } else {
99            return s;
100        }
101    }
102
103    /**
104     * Called when we start processing filter.
105     */
106    public void onStart() {
107
108    }
109
110    /**
111     * Called whenever we encounter an invalid character.
112     * @param c the invalid character
113     */
114    public void onInvalidCharacter(char c) {
115
116    }
117
118    /**
119     * Called when we're done processing filter
120     */
121    public void onStop() {
122
123    }
124
125    /**
126     * Returns whether or not we allow character c.
127     * Subclasses must override this method.
128     */
129    public abstract boolean isAllowed(char c);
130
131    /**
132     * This filter rejects characters in the user name that are not compatible with GMail
133     * account creation. It prevents the user from entering user names with characters other than
134     * [a-zA-Z0-9.].
135     *
136     */
137    public static class UsernameFilterGMail extends LoginFilter {
138
139        public UsernameFilterGMail() {
140            super(false);
141        }
142
143        public UsernameFilterGMail(boolean appendInvalid) {
144            super(appendInvalid);
145        }
146
147        @Override
148        public boolean isAllowed(char c) {
149            // Allow [a-zA-Z0-9@.]
150            if ('0' <= c && c <= '9')
151                return true;
152            if ('a' <= c && c <= 'z')
153                return true;
154            if ('A' <= c && c <= 'Z')
155                return true;
156            if ('.' == c)
157                return true;
158            return false;
159        }
160    }
161
162    /**
163     * This filter rejects characters in the user name that are not compatible with Google login.
164     * It is slightly less restrictive than the above filter in that it allows [a-zA-Z0-9._-].
165     *
166     */
167    public static class UsernameFilterGeneric extends LoginFilter {
168        private static final String mAllowed = "@_-."; // Additional characters
169
170        public UsernameFilterGeneric() {
171            super(false);
172        }
173
174        public UsernameFilterGeneric(boolean appendInvalid) {
175            super(appendInvalid);
176        }
177
178        @Override
179        public boolean isAllowed(char c) {
180            // Allow [a-zA-Z0-9@.]
181            if ('0' <= c && c <= '9')
182                return true;
183            if ('a' <= c && c <= 'z')
184                return true;
185            if ('A' <= c && c <= 'Z')
186                return true;
187            if (mAllowed.indexOf(c) != -1)
188                return true;
189            return false;
190        }
191    }
192
193    /**
194     * This filter is compatible with GMail passwords which restricts characters to
195     * the Latin-1 (ISO8859-1) char set.
196     *
197     */
198    public static class PasswordFilterGMail extends LoginFilter {
199
200        public PasswordFilterGMail() {
201            super(false);
202        }
203
204        public PasswordFilterGMail(boolean appendInvalid) {
205            super(appendInvalid);
206        }
207
208        // We should reject anything not in the Latin-1 (ISO8859-1) charset
209        @Override
210        public boolean isAllowed(char c) {
211            if (32 <= c && c <= 127)
212                return true; // standard charset
213            // if (128 <= c && c <= 159) return true;  // nonstandard (Windows(TM)(R)) charset
214            if (160 <= c && c <= 255)
215                return true; // extended charset
216            return false;
217        }
218    }
219}
220