diff --git a/AndroidManifest.xml b/AndroidManifest.xml index e9e3f1a3a..6040a50d6 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -60,10 +60,11 @@ android:name="android.app.default_searchable" android:value=".SearchResults" /> - - + diff --git a/res/layout/addrepo.xml b/res/layout/addrepo.xml index 95882888e..0638049ee 100644 --- a/res/layout/addrepo.xml +++ b/res/layout/addrepo.xml @@ -4,17 +4,6 @@ android:layout_height="wrap_content" android:orientation="vertical" > - - - diff --git a/res/values/strings.xml b/res/values/strings.xml index 58f105812..1093ddcd3 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -56,6 +56,9 @@ Add Cancel + Enable + Add Key + Overwrite Choose repository to remove Update repositories @@ -72,7 +75,10 @@ Repository address fingerprint (optional) This repo already exists! - Overwrite the existing repo? + This repo is already setup, this will add new key information. + 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! The list of used repositories has changed.\nDo you diff --git a/src/org/fdroid/fdroid/DB.java b/src/org/fdroid/fdroid/DB.java index ef950ef69..73236124e 100644 --- a/src/org/fdroid/fdroid/DB.java +++ b/src/org/fdroid/fdroid/DB.java @@ -11,7 +11,7 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -465,6 +465,8 @@ public class DB { public static String calcFingerprint(String pubkey) { String ret = null; + if (pubkey == null) + return null; try { // keytool -list -v gives you the SHA-256 fingerprint MessageDigest digest = MessageDigest.getInstance("SHA-256"); @@ -1410,7 +1412,7 @@ public class DB { String calcedFingerprint = DB.calcFingerprint(pubkey); if (fingerprint == null) { fingerprint = calcedFingerprint; - } else { + } else if (calcedFingerprint != null) { fingerprint = fingerprint.toUpperCase(); if (!fingerprint.equals(calcedFingerprint)) { throw new SecurityException("Given fingerprint does not match calculated one! (" diff --git a/src/org/fdroid/fdroid/FDroid.java b/src/org/fdroid/fdroid/FDroid.java index 63353ffec..e78135ef9 100644 --- a/src/org/fdroid/fdroid/FDroid.java +++ b/src/org/fdroid/fdroid/FDroid.java @@ -11,7 +11,7 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/src/org/fdroid/fdroid/FDroidApp.java b/src/org/fdroid/fdroid/FDroidApp.java index b7dea120d..a9cb64ab0 100644 --- a/src/org/fdroid/fdroid/FDroidApp.java +++ b/src/org/fdroid/fdroid/FDroidApp.java @@ -10,7 +10,7 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/src/org/fdroid/fdroid/ManageRepo.java b/src/org/fdroid/fdroid/ManageRepo.java index 4185e89fc..de5b6c884 100644 --- a/src/org/fdroid/fdroid/ManageRepo.java +++ b/src/org/fdroid/fdroid/ManageRepo.java @@ -11,7 +11,7 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -26,6 +26,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import android.app.Activity; import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.app.ListActivity; @@ -35,24 +36,22 @@ 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 android.widget.Toast; 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 +61,11 @@ public class ManageRepo extends ListActivity { private boolean changed = false; + private enum PositiveAction { + ADD_NEW, ENABLE, IGNORE + } + private PositiveAction positiveAction; + private List repos; private static List reposToDisable; @@ -103,7 +107,7 @@ public class ManageRepo extends ListActivity { s_lastUpdateCheck = getString(R.string.never); } else { Date d = new Date(lastUpdate); - s_lastUpdateCheck = DateFormat.getDateFormat(this).format(d) + + s_lastUpdateCheck = DateFormat.getDateFormat(this).format(d) + " " + DateFormat.getTimeFormat(this).format(d); } tv_lastCheck.setText(getString(R.string.last_update_check,s_lastUpdateCheck)); @@ -116,13 +120,25 @@ public class ManageRepo extends ListActivity { /* an URL from a click or a QRCode scan */ Uri uri = intent.getData(); if (uri != null) { - // scheme should only ever be pure ASCII: + // scheme should only ever be pure ASCII aka Locale.ENGLISH String scheme = intent.getScheme().toLowerCase(Locale.ENGLISH); String fingerprint = uri.getUserInfo(); + String host = uri.getHost().toLowerCase(Locale.ENGLISH); if (scheme.equals("fdroidrepos") || scheme.equals("fdroidrepo") || scheme.equals("https") || scheme.equals("http")) { - String uriString = uri.toString().replace("fdroidrepo", "http"). - replace(fingerprint + "@", ""); + // QRCode are more efficient in all upper case, so some incoming + // URLs might be encoded in all upper case. Therefore, we allow + // the standard paths to be encoded all upper case, then they'll + // be forced to lower case. The scheme and host are downcased + // just to make them more readable in the dialog. + String uriString = uri.toString() + .replace(fingerprint + "@", "") // remove fingerprint + .replaceAll("/*$", "") // remove all trailing slashes + .replaceAll("/FDROID/REPO$", "/fdroid/repo") + .replaceAll("/FDROID/ARCHIVE$", "/fdroid/archive") + .replace(uri.getHost(), host) // downcase host name + .replace(intent.getScheme(), scheme) // downcase scheme + .replace("fdroidrepo", "http"); // make proper URL showAddRepo(uriString, fingerprint); Log.i("ManageRepo", uriString + " fingerprint: " + fingerprint); } @@ -219,10 +235,10 @@ public class ManageRepo extends ListActivity { return repos; } - protected Repo getRepo(String repoUri, List repos) { - if (repoUri != null) + protected Repo getRepoByAddress(String address, List repos) { + if (address != null) for (Repo repo : repos) - if (repoUri.equals(repo.address)) + if (address.equals(repo.address)) return repo; return null; } @@ -237,7 +253,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); @@ -245,6 +261,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 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, @@ -252,10 +271,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); } }); @@ -264,35 +288,74 @@ public class ManageRepo extends ListActivity { new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { + setResult(Activity.RESULT_CANCELED); + finish(); return; } }); alrt.show(); - List 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); - 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()); + 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 and is not enabled, offer to enable it + if (repo.inuse) { + alrt.dismiss(); + Toast.makeText(this, R.string.repo_exists_and_enabled, Toast.LENGTH_LONG).show(); + return; + } else { + overwriteMessage.setText(R.string.repo_exists_enable); + addButton.setText(R.string.enable); + positiveAction = PositiveAction.ENABLE; } - }); - // TODO if address and fingerprint match, then enable existing repo - // TODO if address matches but fingerprint doesn't, handle this with extra widgets + } 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); + positiveAction = PositiveAction.IGNORE; + } } - 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(); + setResult(Activity.RESULT_OK); + finish(); } @Override diff --git a/src/org/fdroid/fdroid/PackageReceiver.java b/src/org/fdroid/fdroid/PackageReceiver.java index 5716c5dc7..180aa3f8c 100644 --- a/src/org/fdroid/fdroid/PackageReceiver.java +++ b/src/org/fdroid/fdroid/PackageReceiver.java @@ -10,7 +10,7 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/src/org/fdroid/fdroid/PreferencesActivity.java b/src/org/fdroid/fdroid/PreferencesActivity.java index d0690d808..1303e9f09 100644 --- a/src/org/fdroid/fdroid/PreferencesActivity.java +++ b/src/org/fdroid/fdroid/PreferencesActivity.java @@ -10,7 +10,7 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/src/org/fdroid/fdroid/RepoXMLHandler.java b/src/org/fdroid/fdroid/RepoXMLHandler.java index 8af50821f..29648f7c9 100644 --- a/src/org/fdroid/fdroid/RepoXMLHandler.java +++ b/src/org/fdroid/fdroid/RepoXMLHandler.java @@ -11,7 +11,7 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -359,7 +359,7 @@ public class RepoXMLHandler extends DefaultHandler { // This is a signed repo - we download the jar file, // check the signature, and extract the index... - Log.d("FDroid", "Getting signed index from " + repo.address + " at " + + Log.d("FDroid", "Getting signed index from " + repo.address + " at " + logDateFormat.format(new Date(System.currentTimeMillis()))); String address = repo.address + "/index.jar?" + ctx.getString(R.string.version_name); diff --git a/src/org/fdroid/fdroid/SearchResults.java b/src/org/fdroid/fdroid/SearchResults.java index e1b2ece03..e8afcb002 100644 --- a/src/org/fdroid/fdroid/SearchResults.java +++ b/src/org/fdroid/fdroid/SearchResults.java @@ -10,7 +10,7 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/src/org/fdroid/fdroid/StartupReceiver.java b/src/org/fdroid/fdroid/StartupReceiver.java index db82be4ca..2d04342dd 100644 --- a/src/org/fdroid/fdroid/StartupReceiver.java +++ b/src/org/fdroid/fdroid/StartupReceiver.java @@ -10,7 +10,7 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/src/org/fdroid/fdroid/UpdateService.java b/src/org/fdroid/fdroid/UpdateService.java index 5323d0e60..c9854f331 100644 --- a/src/org/fdroid/fdroid/UpdateService.java +++ b/src/org/fdroid/fdroid/UpdateService.java @@ -10,7 +10,7 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.