1 /* 2 * Copyright (C) 2017 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 17 package android.service.autofill; 18 19 import static android.view.autofill.Helper.sDebug; 20 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.annotation.TestApi; 24 import android.os.Parcel; 25 import android.os.Parcelable; 26 import android.util.Slog; 27 import android.view.autofill.AutofillValue; 28 29 import com.android.internal.util.Preconditions; 30 31 import java.util.regex.Matcher; 32 import java.util.regex.Pattern; 33 34 /** 35 * Sanitizes a text {@link AutofillValue} using a regular expression (regex) substitution. 36 * 37 * <p>For example, to remove spaces from groups of 4-digits in a credit card: 38 * 39 * <pre class="prettyprint"> 40 * new TextValueSanitizer(Pattern.compile("^(\\d{4})\\s?(\\d{4})\\s?(\\d{4})\\s?(\\d{4})$"), 41 * "$1$2$3$4") 42 * </pre> 43 */ 44 public final class TextValueSanitizer extends InternalSanitizer implements 45 Sanitizer, Parcelable { 46 private static final String TAG = "TextValueSanitizer"; 47 48 private final Pattern mRegex; 49 private final String mSubst; 50 51 /** 52 * Default constructor. 53 * 54 * @param regex regular expression with groups (delimited by {@code (} and {@code (}) that 55 * are used to substitute parts of the {@link AutofillValue#getTextValue() text value}. 56 * @param subst the string that substitutes the matched regex, using {@code $} for 57 * group substitution ({@code $1} for 1st group match, {@code $2} for 2nd, etc). 58 */ 59 public TextValueSanitizer(@NonNull Pattern regex, @NonNull String subst) { 60 mRegex = Preconditions.checkNotNull(regex); 61 mSubst = Preconditions.checkNotNull(subst); 62 } 63 64 /** @hide */ 65 @Override 66 @TestApi 67 @Nullable 68 public AutofillValue sanitize(@NonNull AutofillValue value) { 69 if (value == null) { 70 Slog.w(TAG, "sanitize() called with null value"); 71 return null; 72 } 73 if (!value.isText()) { 74 if (sDebug) Slog.d(TAG, "sanitize() called with non-text value: " + value); 75 return null; 76 } 77 78 final CharSequence text = value.getTextValue(); 79 80 try { 81 final Matcher matcher = mRegex.matcher(text); 82 if (!matcher.matches()) { 83 if (sDebug) Slog.d(TAG, "sanitize(): " + mRegex + " failed for " + value); 84 return null; 85 } 86 87 final CharSequence sanitized = matcher.replaceAll(mSubst); 88 return AutofillValue.forText(sanitized); 89 } catch (Exception e) { 90 Slog.w(TAG, "Exception evaluating " + mRegex + "/" + mSubst + ": " + e); 91 return null; 92 } 93 } 94 95 ///////////////////////////////////// 96 // Object "contract" methods. // 97 ///////////////////////////////////// 98 @Override 99 public String toString() { 100 if (!sDebug) return super.toString(); 101 102 return "TextValueSanitizer: [regex=" + mRegex + ", subst=" + mSubst + "]"; 103 } 104 105 ///////////////////////////////////// 106 // Parcelable "contract" methods. // 107 ///////////////////////////////////// 108 @Override 109 public int describeContents() { 110 return 0; 111 } 112 113 @Override 114 public void writeToParcel(Parcel parcel, int flags) { 115 parcel.writeSerializable(mRegex); 116 parcel.writeString(mSubst); 117 } 118 119 public static final Parcelable.Creator<TextValueSanitizer> CREATOR = 120 new Parcelable.Creator<TextValueSanitizer>() { 121 @Override 122 public TextValueSanitizer createFromParcel(Parcel parcel) { 123 return new TextValueSanitizer((Pattern) parcel.readSerializable(), parcel.readString()); 124 } 125 126 @Override 127 public TextValueSanitizer[] newArray(int size) { 128 return new TextValueSanitizer[size]; 129 } 130 }; 131 } 132