From 5065c37e13e6f3f34b9e8187d2b4f238a972d218 Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Tue, 19 May 2015 22:42:45 +1000 Subject: [PATCH] Fix #263 "cannot manually add repo that was swapped before" Pretends that the swap repo never existed, by deleting it before adding the new repo, and showing the same message that is shown when a new repo is added. This does not change behaviour for existing non-swap repos. They are not deleted before being added again, or else we would lose the ability to verify the fingerprint of an existing repo is the same as a newly added one with the same URL. Note that this has the effect that the fingerprint/pubkey of the swap repo is nuked when adding that repo manually. Internationalised the string "BAD FINGERPRINT" while I was at it. --- F-Droid/res/values/strings.xml | 1 + F-Droid/src/org/fdroid/fdroid/Utils.java | 5 +-- .../fdroid/views/ManageReposActivity.java | 23 +++++++++++-- .../views/fragments/RepoDetailsFragment.java | 4 +-- .../views/swap/ConnectSwapActivity.java | 5 --- .../test/src/org/fdroid/fdroid/UtilsTest.java | 32 +++++++++---------- 6 files changed, 43 insertions(+), 27 deletions(-) diff --git a/F-Droid/res/values/strings.xml b/F-Droid/res/values/strings.xml index 5da5d0d1f..3a1e7d20d 100644 --- a/F-Droid/res/values/strings.xml +++ b/F-Droid/res/values/strings.xml @@ -97,6 +97,7 @@ This repo is already setup, confirm that you want to re-enable it. The incoming repo is already setup and enabled. You must first delete this repo before you can add one with a different key. + BAD FINGERPRINT This is not a valid URL. Ignoring malformed repo URI: %s diff --git a/F-Droid/src/org/fdroid/fdroid/Utils.java b/F-Droid/src/org/fdroid/fdroid/Utils.java index 290aa4136..1eab916e5 100644 --- a/F-Droid/src/org/fdroid/fdroid/Utils.java +++ b/F-Droid/src/org/fdroid/fdroid/Utils.java @@ -21,6 +21,7 @@ package org.fdroid.fdroid; import android.content.Context; import android.content.pm.PackageManager; import android.content.res.AssetManager; +import android.content.res.Resources; import android.content.res.XmlResourceParser; import android.net.Uri; import android.support.annotation.NonNull; @@ -281,11 +282,11 @@ public final class Utils { } // return a fingerprint formatted for display - public static String formatFingerprint(String fingerprint) { + public static String formatFingerprint(Context context, String fingerprint) { if (TextUtils.isEmpty(fingerprint) || fingerprint.length() != 64 // SHA-256 is 64 hex chars || fingerprint.matches(".*[^0-9a-fA-F].*")) // its a hex string - return "BAD FINGERPRINT"; + return context.getString(R.string.bad_fingerprint); String displayFP = fingerprint.substring(0, 2); for (int i = 2; i < fingerprint.length(); i = i + 2) displayFP += " " + fingerprint.substring(i, i + 2); diff --git a/F-Droid/src/org/fdroid/fdroid/views/ManageReposActivity.java b/F-Droid/src/org/fdroid/fdroid/views/ManageReposActivity.java index 166fbee5c..efc938962 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/ManageReposActivity.java +++ b/F-Droid/src/org/fdroid/fdroid/views/ManageReposActivity.java @@ -100,7 +100,8 @@ public class ManageReposActivity extends ActionBarActivity { private enum AddRepoState { DOESNT_EXIST, EXISTS_FINGERPRINT_MISMATCH, EXISTS_FINGERPRINT_MATCH, - EXISTS_DISABLED, EXISTS_ENABLED, EXISTS_UPGRADABLE_TO_SIGNED, INVALID_URL + EXISTS_DISABLED, EXISTS_ENABLED, EXISTS_UPGRADABLE_TO_SIGNED, INVALID_URL, + IS_SWAP } private UpdateService.UpdateReceiver updateHandler = null; @@ -404,6 +405,13 @@ public class ManageReposActivity extends ActionBarActivity { prepareToCreateNewRepo(url, fp); break; + case IS_SWAP: + Log.i(TAG, "Removing existing swap repo " + url + " before adding new repo."); + Repo repo = RepoProvider.Helper.findByAddress(context, url); + RepoProvider.Helper.remove(context, repo.getId()); + prepareToCreateNewRepo(url, fp); + break; + case EXISTS_DISABLED: case EXISTS_UPGRADABLE_TO_SIGNED: case EXISTS_FINGERPRINT_MATCH: @@ -473,7 +481,9 @@ public class ManageReposActivity extends ActionBarActivity { if (repo == null) { repoDoesntExist(); } else { - if (repo.fingerprint == null && fingerprint.length() > 0) { + if (repo.isSwap) { + repoIsSwap(); + } else if (repo.fingerprint == null && fingerprint.length() > 0) { upgradingToSigned(); } else if (repo.fingerprint != null && !repo.fingerprint.equalsIgnoreCase(fingerprint)) { repoFingerprintDoesntMatch(); @@ -493,6 +503,10 @@ public class ManageReposActivity extends ActionBarActivity { updateUi(AddRepoState.DOESNT_EXIST, 0, false, R.string.repo_add_add, true); } + private void repoIsSwap() { + updateUi(AddRepoState.IS_SWAP, 0, false, R.string.repo_add_add, true); + } + /** * Same address with different fingerprint, this could be malicious, so display a message * force the user to manually delete the repo before adding this one. @@ -654,6 +668,11 @@ public class ManageReposActivity extends ActionBarActivity { } private void createNewRepo(String address, String fingerprint) { + try { + address = normalizeUrl(address); + } catch (URISyntaxException e) { + // Leave address as it was. + } ContentValues values = new ContentValues(2); values.put(RepoProvider.DataColumns.ADDRESS, address); if (fingerprint != null && fingerprint.length() > 0) { diff --git a/F-Droid/src/org/fdroid/fdroid/views/fragments/RepoDetailsFragment.java b/F-Droid/src/org/fdroid/fdroid/views/fragments/RepoDetailsFragment.java index fae620592..0e8711aa7 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/fragments/RepoDetailsFragment.java +++ b/F-Droid/src/org/fdroid/fdroid/views/fragments/RepoDetailsFragment.java @@ -366,7 +366,7 @@ public class RepoDetailsFragment extends Fragment { String repoFingerprint; int repoFingerprintColor; -// TODO show the current state of the signature check, not just whether there is a key or not + // TODO show the current state of the signature check, not just whether there is a key or not if (TextUtils.isEmpty(repo.fingerprint) && TextUtils.isEmpty(repo.pubkey)) { repoFingerprint = getResources().getString(R.string.unsigned); repoFingerprintColor = getResources().getColor(R.color.unsigned); @@ -374,7 +374,7 @@ public class RepoDetailsFragment extends Fragment { repoFingerprintDescView.setText(getResources().getString(R.string.unsigned_description)); } else { // this is based on repo.fingerprint always existing, which it should - repoFingerprint = Utils.formatFingerprint(repo.fingerprint); + repoFingerprint = Utils.formatFingerprint(getActivity(), repo.fingerprint); repoFingerprintColor = getResources().getColor(R.color.signed); repoFingerprintDescView.setVisibility(View.GONE); } diff --git a/F-Droid/src/org/fdroid/fdroid/views/swap/ConnectSwapActivity.java b/F-Droid/src/org/fdroid/fdroid/views/swap/ConnectSwapActivity.java index aab818f48..bd0a4d4f5 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/swap/ConnectSwapActivity.java +++ b/F-Droid/src/org/fdroid/fdroid/views/swap/ConnectSwapActivity.java @@ -149,11 +149,6 @@ public class ConnectSwapActivity extends ActionBarActivity implements ProgressLi values.put(RepoProvider.DataColumns.IS_SWAP, true); Uri uri = RepoProvider.Helper.insert(this, values); repo = RepoProvider.Helper.findByUri(this, uri); - } else if (!repo.isSwap) { - Log.d(TAG, "Old local repo being marked as \"Swap\" repo, so that it wont appear in the list of repositories in the future."); - ContentValues values = new ContentValues(1); - values.put(RepoProvider.DataColumns.IS_SWAP, true); - RepoProvider.Helper.update(this, repo, values); } if (!newRepoConfig.preventFurtherSwaps()) { diff --git a/F-Droid/test/src/org/fdroid/fdroid/UtilsTest.java b/F-Droid/test/src/org/fdroid/fdroid/UtilsTest.java index 5b0a1a08d..270f89fb6 100644 --- a/F-Droid/test/src/org/fdroid/fdroid/UtilsTest.java +++ b/F-Droid/test/src/org/fdroid/fdroid/UtilsTest.java @@ -34,54 +34,54 @@ public class UtilsTest extends AndroidTestCase { String fingerprintLongByOnePubkey = "308203c5308202ada00302010202047b7cf549300d06092a864886f70d01010b0500308192310b30090603550406130255533111300f060355040813084e657720596f726b3111300f060355040713084e657720596f726b311d301b060355040a131454686520477561726469616e2050726f6a656374311f301d060355040b1316477561726469616e20462d44726f6964204275696c64311d301b06035504031314677561726469616e70726f6a6563742e696e666f301e170d3132313032393130323530305a170d3430303331363130323530305a308192310b30090603550406130255533111300f060355040813084e657720596f726b3111300f060355040713084e657720596f726b311d301b060355040a131454686520477561726469616e2050726f6a656374311f301d060355040b1316477561726469616e20462d44726f6964204275696c64311d301b06035504031314677561726469616e70726f6a6563742e696e666f30820122300d06092a864886f70d01010105000382010f003082010a0282010100b7f1f635fa3fce1a8042aaa960c2dc557e4ad2c082e5787488cba587fd26207cf59507919fc4dcebda5c8c0959d14146d0445593aa6c29dc639570b71712451fd5c231b0c9f5f0bec380503a1c2a3bc00048bc5db682915afa54d1ecf67b45e1e05c0934b3037a33d3a565899131f27a72c03a5de93df17a2376cc3107f03ee9d124c474dfab30d4053e8f39f292e2dcb6cc131bce12a0c5fc307985195d256bf1d7a2703d67c14bf18ed6b772bb847370b20335810e337c064fef7e2795a524c664a853cd46accb8494f865164dabfb698fa8318236432758bc40d52db00d5ce07fe2210dc06cd95298b4f09e6c9b7b7af61c1d62ea43ea36a2331e7b2d4e250203010001a321301f301d0603551d0e0416041404d763e981cf3a295b94a790d8536a783097232b300d06092a864886f70d01010b05000382010100654e6484ff032c54fed1d96d3c8e731302be9dbd7bb4fe635f2dac05b69f3ecbb5acb7c9fe405e2a066567a8f5c2beb8b199b5a4d5bb1b435cf02df026d4fb4edd9d8849078f085b00950083052d57467d65c6eebd98f037cff9b148d621cf8819c4f7dc1459bf8fc5c7d76f901495a7caf35d1e5c106e1d50610c4920c3c1b50adcfbd4ad83ce7353cdea7d856bba0419c224f89a2f3ebc203d20eb6247711ad2b55fd4737936dc42ced7a047cbbd24012079204a2883b6d55d5d5b66d9fd82fb51fca9a5db5fad9af8564cb380ff30ae8263dbbf01b46e01313f53279673daa3f893380285646b244359203e7eecde94ae141b7dfa8e6499bb8e7e0b25ab85"; public void testFormatFingerprint() { - String badResult = Utils.formatFingerprint(""); + String badResult = Utils.formatFingerprint(getContext(), ""); // real fingerprints - String formatted = null; - formatted = Utils.formatFingerprint(fdroidFingerprint); + String formatted; + formatted = Utils.formatFingerprint(getContext(), fdroidFingerprint); assertFalse(formatted.equals(badResult)); assertTrue(formatted.matches("[A-Z0-9][A-Z0-9] [A-Z0-9 ]+")); - formatted = Utils.formatFingerprint(gpRepoFingerprint); + formatted = Utils.formatFingerprint(getContext(), gpRepoFingerprint); assertFalse(formatted.equals(badResult)); assertTrue(formatted.matches("[A-Z0-9][A-Z0-9] [A-Z0-9 ]+")); - formatted = Utils.formatFingerprint(gpTest1Fingerprint); + formatted = Utils.formatFingerprint(getContext(), gpTest1Fingerprint); assertFalse(formatted.equals(badResult)); assertTrue(formatted.matches("[A-Z0-9][A-Z0-9] [A-Z0-9 ]+")); // random garbage assertEquals( badResult, - Utils.formatFingerprint("234k2lk3jljwlk4j2lk3jlkmqwekljrlkj34lk2jlk2j34lkjl2k3j4lk2j34lja")); + Utils.formatFingerprint(getContext(), "234k2lk3jljwlk4j2lk3jlkmqwekljrlkj34lk2jlk2j34lkjl2k3j4lk2j34lja")); assertEquals( badResult, - Utils.formatFingerprint("g000000000000000000000000000000000000000000000000000000000000000")); + Utils.formatFingerprint(getContext(), "g000000000000000000000000000000000000000000000000000000000000000")); assertEquals( badResult, - Utils.formatFingerprint("98273498723948728934789237489273p1928731982731982739182739817238")); + Utils.formatFingerprint(getContext(), "98273498723948728934789237489273p1928731982731982739182739817238")); // too short assertEquals( badResult, - Utils.formatFingerprint("C63AED1AC79D37C7B0474472AC6EFA6C3AB2B11A767A4F42CF360FA5496E3C5")); + Utils.formatFingerprint(getContext(), "C63AED1AC79D37C7B0474472AC6EFA6C3AB2B11A767A4F42CF360FA5496E3C5")); assertEquals( badResult, - Utils.formatFingerprint("C63AED1")); + Utils.formatFingerprint(getContext(), "C63AED1")); assertEquals( badResult, - Utils.formatFingerprint("f")); + Utils.formatFingerprint(getContext(), "f")); assertEquals( badResult, - Utils.formatFingerprint("")); + Utils.formatFingerprint(getContext(), "")); assertEquals( badResult, - Utils.formatFingerprint(null)); + Utils.formatFingerprint(getContext(), null)); // real digits but too long assertEquals( badResult, - Utils.formatFingerprint("43238D512C1E5EB2D6569F4A3AFBF5523418B82E0A3ED1552770ABB9A9C9CCAB43238D512C1E5EB2D6569F4A3AFBF5523418B82E0A3ED1552770ABB9A9C9CCAB")); + Utils.formatFingerprint(getContext(), "43238D512C1E5EB2D6569F4A3AFBF5523418B82E0A3ED1552770ABB9A9C9CCAB43238D512C1E5EB2D6569F4A3AFBF5523418B82E0A3ED1552770ABB9A9C9CCAB")); assertEquals( badResult, - Utils.formatFingerprint("C63AED1AC79D37C7B0474472AC6EFA6C3AB2B11A767A4F42CF360FA5496E3C50F")); + Utils.formatFingerprint(getContext(), "C63AED1AC79D37C7B0474472AC6EFA6C3AB2B11A767A4F42CF360FA5496E3C50F")); assertEquals( badResult, - Utils.formatFingerprint("3082035e30820246a00302010202044c49cd00300d06092a864886f70d01010505003071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b73301e170d3130303732333137313032345a170d3337313230383137313032345a3071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b7330820122300d06092a864886f70d01010105000382010f003082010a028201010096d075e47c014e7822c89fd67f795d23203e2a8843f53ba4e6b1bf5f2fd0e225938267cfcae7fbf4fe596346afbaf4070fdb91f66fbcdf2348a3d92430502824f80517b156fab00809bdc8e631bfa9afd42d9045ab5fd6d28d9e140afc1300917b19b7c6c4df4a494cf1f7cb4a63c80d734265d735af9e4f09455f427aa65a53563f87b336ca2c19d244fcbba617ba0b19e56ed34afe0b253ab91e2fdb1271f1b9e3c3232027ed8862a112f0706e234cf236914b939bcf959821ecb2a6c18057e070de3428046d94b175e1d89bd795e535499a091f5bc65a79d539a8d43891ec504058acb28c08393b5718b57600a211e803f4a634e5c57f25b9b8c4422c6fd90203010001300d06092a864886f70d0101050500038201010008e4ef699e9807677ff56753da73efb2390d5ae2c17e4db691d5df7a7b60fc071ae509c5414be7d5da74df2811e83d3668c4a0b1abc84b9fa7d96b4cdf30bba68517ad2a93e233b042972ac0553a4801c9ebe07bf57ebe9a3b3d6d663965260e50f3b8f46db0531761e60340a2bddc3426098397fda54044a17e5244549f9869b460ca5e6e216b6f6a2db0580b480ca2afe6ec6b46eedacfa4aa45038809ece0c5978653d6c85f678e7f5a2156d1bedd8117751e64a4b0dcd140f3040b021821a8d93aed8d01ba36db6c82372211fed714d9a32607038cdfd565bd529ffc637212aaa2c224ef22b603eccefb5bf1e085c191d4b24fe742b17ab3f55d4e6f05ef")); + Utils.formatFingerprint(getContext(), "3082035e30820246a00302010202044c49cd00300d06092a864886f70d01010505003071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b73301e170d3130303732333137313032345a170d3337313230383137313032345a3071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b7330820122300d06092a864886f70d01010105000382010f003082010a028201010096d075e47c014e7822c89fd67f795d23203e2a8843f53ba4e6b1bf5f2fd0e225938267cfcae7fbf4fe596346afbaf4070fdb91f66fbcdf2348a3d92430502824f80517b156fab00809bdc8e631bfa9afd42d9045ab5fd6d28d9e140afc1300917b19b7c6c4df4a494cf1f7cb4a63c80d734265d735af9e4f09455f427aa65a53563f87b336ca2c19d244fcbba617ba0b19e56ed34afe0b253ab91e2fdb1271f1b9e3c3232027ed8862a112f0706e234cf236914b939bcf959821ecb2a6c18057e070de3428046d94b175e1d89bd795e535499a091f5bc65a79d539a8d43891ec504058acb28c08393b5718b57600a211e803f4a634e5c57f25b9b8c4422c6fd90203010001300d06092a864886f70d0101050500038201010008e4ef699e9807677ff56753da73efb2390d5ae2c17e4db691d5df7a7b60fc071ae509c5414be7d5da74df2811e83d3668c4a0b1abc84b9fa7d96b4cdf30bba68517ad2a93e233b042972ac0553a4801c9ebe07bf57ebe9a3b3d6d663965260e50f3b8f46db0531761e60340a2bddc3426098397fda54044a17e5244549f9869b460ca5e6e216b6f6a2db0580b480ca2afe6ec6b46eedacfa4aa45038809ece0c5978653d6c85f678e7f5a2156d1bedd8117751e64a4b0dcd140f3040b021821a8d93aed8d01ba36db6c82372211fed714d9a32607038cdfd565bd529ffc637212aaa2c224ef22b603eccefb5bf1e085c191d4b24fe742b17ab3f55d4e6f05ef")); } public void testCalcFingerprintString() {