Utils { public static String formatFingerprint(Context context, String fingerprint) { if (TextUtils.isEmpty(fingerprint) || fingerprint.length() != 64 || fingerprint.matches(".*[^0-9a-fA-F].*")) { return context.getString(R.string.bad_fingerprint); } StringBuilder displayFP = new StringBuilder(fingerprint.substring(0, 2)); for (int i = 2; i < fingerprint.length(); i = i + 2) { displayFP.append(" ").append(fingerprint.substring(i, i + 2)); } return displayFP.toString(); }  static String getIconsDir(final Context context, final double dpiMultiplier); static File getImageCacheDir(Context context); static long getImageCacheDirAvailableMemory(Context context); static long getImageCacheDirTotalMemory(Context context); static void copy(InputStream input, OutputStream output); static boolean symlinkOrCopyFileQuietly(SanitizedFile inFile, SanitizedFile outFile); static void consumeStream(InputStream stream); static boolean copyQuietly(File inFile, File outFile); static void closeQuietly(Closeable closeable); static String getFriendlySize(long size); static String getAndroidVersionName(int sdkLevel); static String formatFingerprint(Context context, String fingerprint); @NonNull static Uri getLocalRepoUri(Repo repo); static Uri getSharingUri(Repo repo); static Uri getPackageUri(String packageName); static String calcFingerprint(String keyHexString); static String calcFingerprint(Certificate cert); static String getPackageSig(PackageInfo info); static Locale getLocaleFromAndroidLangTag(String languageTag); static DisplayImageOptions.Builder getDefaultDisplayImageOptionsBuilder(); static DisplayImageOptions getRepoAppDisplayImageOptions(); static void setIconFromRepoOrPM(@NonNull App app, ImageView iv, Context context); static String hashBytes(byte[] input, String algo); @Nullable static String getBinaryHash(File apk, String algo); static String toHexString(byte[] bytes); static int parseInt(String str, int fallback); @Nullable static String[] parseCommaSeparatedString(String values); @Nullable static String serializeCommaSeparatedString(@Nullable String[] values); static Date parseDate(String str, Date fallback); static String formatDate(Date date, String fallback); static Date parseTime(String str, Date fallback); static String formatTime(Date date, String fallback); static CharSequence formatAppNameAndSummary(String appName, String summary); static boolean isSafePackageName(@Nullable String packageName); static int daysSince(@NonNull Date date); static String formatLastUpdated(@NonNull Resources res, @NonNull Date date); static void debugLog(String tag, String msg); static void debugLog(String tag, String msg, Throwable tr); static String getVersionName(Context context); static PackageInfo getPackageInfo(Context context, String packageName); @SuppressWarnings("unused") @RequiresApi(api = 11) static List<Map<String, String>> dumpCursor(Cursor cursor); static int dpToPx(int dp, Context ctx); static int bytesToKb(long bytes); static int getPercent(long current, long total); static void showToastFromService(final Context context, final String msg, final int length); static void applySwipeLayoutColors(SwipeRefreshLayout swipeLayout); static boolean canConnectToSocket(String host, int port); static boolean isServerSocketInUse(int port); static final String FALLBACK_ICONS_DIR; }
@Test public void testFormatFingerprint() { Context context = ApplicationProvider.getApplicationContext(); String badResult = Utils.formatFingerprint(context, ""); String formatted; formatted = Utils.formatFingerprint(context, fdroidFingerprint); assertFalse(formatted.equals(badResult)); assertTrue(formatted.matches("[A-Z0-9][A-Z0-9] [A-Z0-9 ]+")); formatted = Utils.formatFingerprint(context, gpRepoFingerprint); assertFalse(formatted.equals(badResult)); assertTrue(formatted.matches("[A-Z0-9][A-Z0-9] [A-Z0-9 ]+")); formatted = Utils.formatFingerprint(context, gpTest1Fingerprint); assertFalse(formatted.equals(badResult)); assertTrue(formatted.matches("[A-Z0-9][A-Z0-9] [A-Z0-9 ]+")); assertEquals( badResult, Utils.formatFingerprint(context, "234k2lk3jljwlk4j2lk3jlkmqwekljrlkj34lk2jlk2j34lkjl2k3j4lk2j34lja")); assertEquals( badResult, Utils.formatFingerprint(context, "g000000000000000000000000000000000000000000000000000000000000000")); assertEquals( badResult, Utils.formatFingerprint(context, "98273498723948728934789237489273p1928731982731982739182739817238")); assertEquals( badResult, Utils.formatFingerprint(context, "C63AED1AC79D37C7B0474472AC6EFA6C3AB2B11A767A4F42CF360FA5496E3C5")); assertEquals( badResult, Utils.formatFingerprint(context, "C63AED1")); assertEquals( badResult, Utils.formatFingerprint(context, "f")); assertEquals( badResult, Utils.formatFingerprint(context, "")); assertEquals( badResult, Utils.formatFingerprint(context, null)); assertEquals( badResult, Utils.formatFingerprint(context, "43238D512C1E5EB2D6569F4A3AFBF5523418B82E0A3ED1552770ABB9A9C9CCAB43238D512C1E5EB2D6569F4A3AFBF5523418B82E0A3ED1552770ABB9A9C9CCAB")); assertEquals( badResult, Utils.formatFingerprint(context, "C63AED1AC79D37C7B0474472AC6EFA6C3AB2B11A767A4F42CF360FA5496E3C50F")); assertEquals( badResult, Utils.formatFingerprint(context, "3082035e30820246a00302010202044c49cd00300d06092a864886f70d01010505003071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b73301e170d3130303732333137313032345a170d3337313230383137313032345a3071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b7330820122300d06092a864886f70d01010105000382010f003082010a028201010096d075e47c014e7822c89fd67f795d23203e2a8843f53ba4e6b1bf5f2fd0e225938267cfcae7fbf4fe596346afbaf4070fdb91f66fbcdf2348a3d92430502824f80517b156fab00809bdc8e631bfa9afd42d9045ab5fd6d28d9e140afc1300917b19b7c6c4df4a494cf1f7cb4a63c80d734265d735af9e4f09455f427aa65a53563f87b336ca2c19d244fcbba617ba0b19e56ed34afe0b253ab91e2fdb1271f1b9e3c3232027ed8862a112f0706e234cf236914b939bcf959821ecb2a6c18057e070de3428046d94b175e1d89bd795e535499a091f5bc65a79d539a8d43891ec504058acb28c08393b5718b57600a211e803f4a634e5c57f25b9b8c4422c6fd90203010001300d06092a864886f70d0101050500038201010008e4ef699e9807677ff56753da73efb2390d5ae2c17e4db691d5df7a7b60fc071ae509c5414be7d5da74df2811e83d3668c4a0b1abc84b9fa7d96b4cdf30bba68517ad2a93e233b042972ac0553a4801c9ebe07bf57ebe9a3b3d6d663965260e50f3b8f46db0531761e60340a2bddc3426098397fda54044a17e5244549f9869b460ca5e6e216b6f6a2db0580b480ca2afe6ec6b46eedacfa4aa45038809ece0c5978653d6c85f678e7f5a2156d1bedd8117751e64a4b0dcd140f3040b021821a8d93aed8d01ba36db6c82372211fed714d9a32607038cdfd565bd529ffc637212aaa2c224ef22b603eccefb5bf1e085c191d4b24fe742b17ab3f55d4e6f05ef")); }