add detailed checking of incoming repos based on fingerprint in DB

When a new repo is being added, whether manually or via an incoming Intent,
check the address and fingerprint against repos in the DB.  If the repo is
not in the DB, offer to add it.  If the repo address is in the DB, then do
more checks:

* If that address has no fingerprint in the DB, then offer to add the new
  repo including that fingerprint.  This might happen when upgrading a repo
  from unsigned to signed.
* if the incoming info matches a repo in the DB, offer to enable that repo
* if the address matches a repo in the DB but the incoming fingerprint does
  not match the fingerprint in the DB, warn the user, and tell them to
  delete the existing repo if they truly want to override the existing info
This commit is contained in:
Hans-Christoph Steiner 2013-12-02 20:12:52 -05:00
parent 711a1418b6
commit c7b076e5ea
3 changed files with 86 additions and 51 deletions

View File

@ -4,17 +4,6 @@
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="@+id/repo_alert"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@android:drawable/ic_dialog_alert"
android:gravity="center"
android:text="@string/repo_exists"
android:textAppearance="@android:style/TextAppearance.Large"
android:textColor="@color/red"
android:visibility="gone" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -25,7 +14,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textUri"
android:maxLines="1"
android:maxLines="2"
android:text="https://" />
<TextView
@ -39,15 +28,17 @@
android:layout_height="wrap_content"
android:digits="0123456789ABCDEFabcedf: "
android:inputType="textNoSuggestions"
android:maxLines="1"
android:maxLines="3"
android:typeface="monospace" />
<CheckBox
android:id="@+id/overwrite_repo"
<TextView
android:id="@+id/overwrite_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@android:drawable/ic_dialog_alert"
android:drawablePadding="20dp"
android:padding="20dp"
android:text="@string/repo_overwrite"
android:text="@string/repo_delete_to_overwrite"
android:textAppearance="@android:style/TextAppearance.Medium"
android:visibility="gone" />

View File

@ -56,6 +56,9 @@
<string name="repo_add_add">Add</string>
<string name="cancel">Cancel</string>
<string name="enable">Enable</string>
<string name="add_key">Add Key</string>
<string name="overwrite">Overwrite</string>
<string name="repo_delete_title">Choose repository to remove</string>
<string name="repo_update_title">Update repositories</string>
@ -72,7 +75,9 @@
<string name="repo_add_url">Repository address</string>
<string name="repo_add_fingerprint">fingerprint (optional)</string>
<string name="repo_exists">This repo already exists!</string>
<string name="repo_overwrite">Overwrite the existing repo?</string>
<string name="repo_exists_add_fingerprint">This repo is already setup, this will add new key information.</string>
<string name="repo_exists_enable">This repo is already setup, confirm that you want to re-enable it.</string>
<string name="repo_delete_to_overwrite">You must first delete this repo before you can add one with a different key!</string>
<string name="repo_alrt">The list of used repositories has
changed.\nDo you

View File

@ -35,24 +35,21 @@ import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.NavUtils;
import android.support.v4.view.MenuItemCompat;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import org.fdroid.fdroid.DB.Repo;
import android.support.v4.app.NavUtils;
import android.support.v4.view.MenuItemCompat;
import org.fdroid.fdroid.compat.ActionBarCompat;
public class ManageRepo extends ListActivity {
@ -62,6 +59,11 @@ public class ManageRepo extends ListActivity {
private boolean changed = false;
private enum PositiveAction {
ADD_NEW, ENABLE, IGNORE
}
private PositiveAction positiveAction;
private List<DB.Repo> repos;
private static List<String> reposToDisable;
@ -231,10 +233,10 @@ public class ManageRepo extends ListActivity {
return repos;
}
protected Repo getRepo(String repoUri, List<Repo> repos) {
if (repoUri != null)
protected Repo getRepoByAddress(String address, List<Repo> repos) {
if (address != null)
for (Repo repo : repos)
if (repoUri.equals(repo.address))
if (address.equals(repo.address))
return repo;
return null;
}
@ -249,7 +251,7 @@ public class ManageRepo extends ListActivity {
return super.onOptionsItemSelected(item);
}
private void showAddRepo(String uriString, String fingerprint) {
private void showAddRepo(String newAddress, String newFingerprint) {
LayoutInflater li = LayoutInflater.from(this);
View view = li.inflate(R.layout.addrepo, null);
Builder p = new AlertDialog.Builder(this).setView(view);
@ -257,6 +259,9 @@ public class ManageRepo extends ListActivity {
final EditText uriEditText = (EditText) view.findViewById(R.id.edit_uri);
final EditText fingerprintEditText = (EditText) view.findViewById(R.id.edit_fingerprint);
List<Repo> repos = getRepos();
final Repo repo = getRepoByAddress(newAddress, repos);
alrt.setIcon(android.R.drawable.ic_menu_add);
alrt.setTitle(getString(R.string.repo_add_title));
alrt.setButton(DialogInterface.BUTTON_POSITIVE,
@ -264,10 +269,15 @@ public class ManageRepo extends ListActivity {
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
addRepo(uriEditText.getText().toString(),
fingerprintEditText.getText().toString());
changed = true;
redraw();
String fp = fingerprintEditText.getText().toString();
// the DB uses null for no fingerprint but the above
// code returns "" rather than null if its blank
if (fp.equals(""))
fp = null;
if (positiveAction == PositiveAction.ADD_NEW)
addRepoPositiveAction(uriEditText.getText().toString(), fp, null);
else if (positiveAction == PositiveAction.ENABLE)
addRepoPositiveAction(null, null, repo);
}
});
@ -281,30 +291,59 @@ public class ManageRepo extends ListActivity {
});
alrt.show();
List<Repo> repos = getRepos();
Repo repo = getRepo(uriString, repos);
if (repo != null) {
TextView tv = (TextView) view.findViewById(R.id.repo_alert);
tv.setVisibility(0);
tv.setText(R.string.repo_exists);
final TextView overwriteMessage = (TextView) view.findViewById(R.id.overwrite_message);
overwriteMessage.setVisibility(View.GONE);
if (repo == null) {
// no existing repo, add based on what we have
positiveAction = PositiveAction.ADD_NEW;
} else {
// found the address in the DB of existing repos
final Button addButton = alrt.getButton(DialogInterface.BUTTON_POSITIVE);
alrt.setTitle(R.string.repo_exists);
overwriteMessage.setVisibility(View.VISIBLE);
if (repo.fingerprint == null && newFingerprint != null) {
// we're upgrading from unsigned to signed repo
overwriteMessage.setText(R.string.repo_exists_add_fingerprint);
addButton.setText(R.string.add_key);
positiveAction = PositiveAction.ADD_NEW;
} else if (newFingerprint == null || newFingerprint.equals(repo.fingerprint)) {
// this entry already exists, offer to enable it
overwriteMessage.setText(R.string.repo_exists_enable);
addButton.setText(R.string.enable);
positiveAction = PositiveAction.ENABLE;
} else {
// same address with different fingerprint, this could be
// malicious, so force the user to manually delete the repo
// before adding this one
overwriteMessage.setTextColor(getResources().getColor(R.color.red));
overwriteMessage.setText(R.string.repo_delete_to_overwrite);
addButton.setText(R.string.overwrite);
addButton.setEnabled(false);
final CheckBox overwriteCheckBox = (CheckBox) view.findViewById(R.id.overwrite_repo);
overwriteCheckBox.setVisibility(0);
overwriteCheckBox.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
addButton.setEnabled(overwriteCheckBox.isChecked());
positiveAction = PositiveAction.IGNORE;
}
});
// TODO if address and fingerprint match, then enable existing repo
// TODO if address matches but fingerprint doesn't, handle this with extra widgets
}
if (uriString != null)
uriEditText.setText(uriString);
if (fingerprint != null)
fingerprintEditText.setText(fingerprint);
if (newAddress != null)
uriEditText.setText(newAddress);
if (newFingerprint != null)
fingerprintEditText.setText(newFingerprint);
}
private void addRepoPositiveAction(String address, String fingerprint, Repo repo) {
if (address != null) {
addRepo(address, fingerprint);
} else if (repo != null) {
// force-enable an existing repo
repo.inuse = true;
try {
DB db = DB.getDB();
db.updateRepoByAddress(repo);
} finally {
DB.releaseDB();
}
}
changed = true;
redraw();
}
@Override