diff --git a/app/src/main/java/org/fdroid/fdroid/RepoUpdater.java b/app/src/main/java/org/fdroid/fdroid/RepoUpdater.java index 3d6e85fcf..9d30651e1 100644 --- a/app/src/main/java/org/fdroid/fdroid/RepoUpdater.java +++ b/app/src/main/java/org/fdroid/fdroid/RepoUpdater.java @@ -1,18 +1,48 @@ +/* + * Copyright (C) 2016 Blue Jay Wireless + * Copyright (C) 2015-2016 Daniel Martí + * Copyright (C) 2014-2016 Hans-Christoph Steiner + * Copyright (C) 2014-2016 Peter Serwylo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 3 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * 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. + */ + package org.fdroid.fdroid; +import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.text.TextUtils; import android.util.Log; import org.fdroid.fdroid.data.Apk; +import org.fdroid.fdroid.data.ApkProvider; import org.fdroid.fdroid.data.App; +import org.fdroid.fdroid.data.AppProvider; import org.fdroid.fdroid.data.Repo; import org.fdroid.fdroid.data.RepoPersister; import org.fdroid.fdroid.data.RepoProvider; +import org.fdroid.fdroid.data.RepoPushRequest; import org.fdroid.fdroid.data.Schema.RepoTable; +import org.fdroid.fdroid.installer.InstallManagerService; +import org.fdroid.fdroid.installer.InstallerService; import org.fdroid.fdroid.net.Downloader; import org.fdroid.fdroid.net.DownloaderFactory; import org.xml.sax.InputSource; @@ -27,6 +57,7 @@ import java.net.URL; import java.security.CodeSigner; import java.security.cert.Certificate; import java.security.cert.X509Certificate; +import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.jar.JarEntry; @@ -37,12 +68,15 @@ import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; /** - * Responsible for updating an individual repository. This will: - * * Download the index.jar - * * Verify that it is signed correctly and by the correct certificate - * * Parse the index.xml from the .jar file - * * Save the resulting repo, apps, and apks to the database. - * + * Updates the local database with a repository's app/apk metadata and verifying + * the JAR signature on the file received from the repository. As an overview: + *
    + *
  • Download the {@code index.jar} + *
  • Verify that it is signed correctly and by the correct certificate + *
  • Parse the {@code index.xml} that is in {@code index.jar} + *
  • Save the resulting repo, apps, and apks to the database. + *
  • Process any push install/uninstall requests included in the repository + *
* WARNING: this class is the central piece of the entire security model of * FDroid! Avoid modifying it when possible, if you absolutely must, be very, * very careful with the changes that you are making! @@ -66,7 +100,10 @@ public class RepoUpdater { private String cacheTag; private X509Certificate signingCertFromJar; - @NonNull private final RepoPersister persister; + @NonNull + private final RepoPersister persister; + + private final List repoPushRequestList = new ArrayList<>(); /** * Updates an app repo as read out of the database into a {@link Repo} instance. @@ -148,6 +185,7 @@ public class RepoUpdater { // successful download, then we will have a file ready to use: cacheTag = downloader.getCacheTag(); processDownloadedFile(downloader.outputFile); + processRepoPushRequests(); } } @@ -170,6 +208,11 @@ public class RepoUpdater { throw new RuntimeException("Error while saving repo details to database.", e); } } + + @Override + public void receiveRepoPushRequest(RepoPushRequest repoPushRequest) { + repoPushRequestList.add(repoPushRequest); + } }; } @@ -188,7 +231,7 @@ public class RepoUpdater { JarFile jarFile = new JarFile(downloadedFile, true); JarEntry indexEntry = (JarEntry) jarFile.getEntry("index.xml"); indexInputStream = new ProgressBufferedInputStream(jarFile.getInputStream(indexEntry), - processXmlProgressListener, new URL(repo.address), (int) indexEntry.getSize()); + processXmlProgressListener, new URL(repo.address), (int) indexEntry.getSize()); // Process the index... SAXParserFactory factory = SAXParserFactory.newInstance(); @@ -396,4 +439,57 @@ public class RepoUpdater { throw new SigningException(repo, "Signing certificate does not match!"); } + /** + * Server index XML can include optional {@code install} and {@code uninstall} + * requests. This processes those requests, figuring out whether the client + * should always accept, prompt the user, or ignore those requests on a + * per repo basis. + */ + private void processRepoPushRequests() { + PackageManager pm = context.getPackageManager(); + + for (RepoPushRequest repoPushRequest : repoPushRequestList) { + String packageName = repoPushRequest.packageName; + PackageInfo packageInfo = null; + try { + packageInfo = pm.getPackageInfo(packageName, 0); + } catch (PackageManager.NameNotFoundException e) { + // ignored + } + if (RepoPushRequest.INSTALL.equals(repoPushRequest.request)) { + ContentResolver cr = context.getContentResolver(); + App app = AppProvider.Helper.findByPackageName(cr, packageName); + if (app == null) { + Utils.debugLog(TAG, packageName + " not in local database, ignoring request to" + + repoPushRequest.request); + continue; + } + int versionCode; + if (repoPushRequest.versionCode == null) { + versionCode = app.suggestedVersionCode; + } else { + versionCode = repoPushRequest.versionCode; + } + if (packageInfo != null && versionCode == packageInfo.versionCode) { + Utils.debugLog(TAG, repoPushRequest + " already installed, ignoring"); + } else { + Apk apk = ApkProvider.Helper.find(context, packageName, versionCode); + InstallManagerService.queue(context, app, apk); + } + } else if (RepoPushRequest.UNINSTALL.equals(repoPushRequest.request)) { + if (packageInfo == null) { + Utils.debugLog(TAG, "ignoring request, not installed: " + repoPushRequest); + continue; + } + if (repoPushRequest.versionCode == null + || repoPushRequest.versionCode == packageInfo.versionCode) { + InstallerService.uninstall(context, packageName); + } else { + Utils.debugLog(TAG, "ignoring request based on versionCode:" + repoPushRequest); + } + } else { + Utils.debugLog(TAG, "Unknown Repo Push Request: " + repoPushRequest.request); + } + } + } } diff --git a/app/src/main/java/org/fdroid/fdroid/RepoXMLHandler.java b/app/src/main/java/org/fdroid/fdroid/RepoXMLHandler.java index 780d82f55..d58307c5e 100644 --- a/app/src/main/java/org/fdroid/fdroid/RepoXMLHandler.java +++ b/app/src/main/java/org/fdroid/fdroid/RepoXMLHandler.java @@ -25,6 +25,7 @@ import android.support.annotation.Nullable; import org.fdroid.fdroid.data.Apk; import org.fdroid.fdroid.data.App; import org.fdroid.fdroid.data.Repo; +import org.fdroid.fdroid.data.RepoPushRequest; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; @@ -64,6 +65,8 @@ public class RepoXMLHandler extends DefaultHandler { void receiveRepo(String name, String description, String signingCert, int maxage, int version, long timestamp); void receiveApp(App app, List packages); + + void receiveRepoPushRequest(RepoPushRequest repoPushRequest); } private final IndexReceiver receiver; @@ -250,6 +253,10 @@ public class RepoXMLHandler extends DefaultHandler { receiver.receiveRepo(repoName, repoDescription, repoSigningCert, repoMaxAge, repoVersion, repoTimestamp); } + private void onRepoPushRequestParsed(RepoPushRequest repoPushRequest) { + receiver.receiveRepoPushRequest(repoPushRequest); + } + @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { @@ -262,6 +269,15 @@ public class RepoXMLHandler extends DefaultHandler { repoName = cleanWhiteSpace(attributes.getValue("", "name")); repoDescription = cleanWhiteSpace(attributes.getValue("", "description")); repoTimestamp = parseLong(attributes.getValue("", "timestamp"), 0); + } else if (RepoPushRequest.INSTALL.equals(localName) + || RepoPushRequest.UNINSTALL.equals(localName)) { + if (repo.pushRequests == Repo.PUSH_REQUEST_ACCEPT_ALWAYS) { + RepoPushRequest r = new RepoPushRequest( + localName, + attributes.getValue("packageName"), + attributes.getValue("versionCode")); + onRepoPushRequestParsed(r); + } } else if ("application".equals(localName) && curapp == null) { curapp = new App(); curapp.packageName = attributes.getValue("", "id"); diff --git a/app/src/main/java/org/fdroid/fdroid/data/DBHelper.java b/app/src/main/java/org/fdroid/fdroid/data/DBHelper.java index 1397c44b4..bcf757446 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/DBHelper.java +++ b/app/src/main/java/org/fdroid/fdroid/data/DBHelper.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2016 Blue Jay Wireless + * Copyright (C) 2015-2016 Daniel Martí + * Copyright (C) 2015 Christian Morgner + * Copyright (C) 2014-2016 Hans-Christoph Steiner + * Copyright (C) 2013-2016 Peter Serwylo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 3 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * 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. + */ + package org.fdroid.fdroid.data; import android.content.ContentValues; @@ -23,6 +46,8 @@ class DBHelper extends SQLiteOpenHelper { private static final String TAG = "DBHelper"; + public static final int REPO_XML_ARG_COUNT = 8; + private static final String DATABASE_NAME = "fdroid"; private static final String CREATE_TABLE_REPO = "create table " @@ -42,7 +67,8 @@ class DBHelper extends SQLiteOpenHelper { + RepoTable.Cols.IS_SWAP + " integer boolean default 0," + RepoTable.Cols.USERNAME + " string, " + RepoTable.Cols.PASSWORD + " string," - + RepoTable.Cols.TIMESTAMP + " integer not null default 0" + + RepoTable.Cols.TIMESTAMP + " integer not null default 0, " + + RepoTable.Cols.PUSH_REQUESTS + " integer not null default " + Repo.PUSH_REQUEST_IGNORE + ");"; static final String CREATE_TABLE_APK = @@ -120,7 +146,7 @@ class DBHelper extends SQLiteOpenHelper { + " );"; private static final String DROP_TABLE_INSTALLED_APP = "DROP TABLE " + InstalledAppTable.NAME + ";"; - private static final int DB_VERSION = 61; + private static final int DB_VERSION = 62; private final Context context; @@ -229,55 +255,30 @@ class DBHelper extends SQLiteOpenHelper { db.execSQL(CREATE_TABLE_APP_PREFS); ensureIndexes(db); - insertRepo( - db, - context.getString(R.string.fdroid_repo_name), - context.getString(R.string.fdroid_repo_address), - context.getString(R.string.fdroid_repo_description), - context.getString(R.string.fdroid_repo_pubkey), - context.getResources().getInteger(R.integer.fdroid_repo_version), - context.getResources().getInteger(R.integer.fdroid_repo_inuse), - context.getResources().getInteger(R.integer.fdroid_repo_priority) - ); - - insertRepo( - db, - context.getString(R.string.fdroid_archive_name), - context.getString(R.string.fdroid_archive_address), - context.getString(R.string.fdroid_archive_description), - context.getString(R.string.fdroid_archive_pubkey), - context.getResources().getInteger(R.integer.fdroid_archive_version), - context.getResources().getInteger(R.integer.fdroid_archive_inuse), - context.getResources().getInteger(R.integer.fdroid_archive_priority) - ); - - insertRepo( - db, - context.getString(R.string.guardianproject_repo_name), - context.getString(R.string.guardianproject_repo_address), - context.getString(R.string.guardianproject_repo_description), - context.getString(R.string.guardianproject_repo_pubkey), - context.getResources().getInteger(R.integer.guardianproject_repo_version), - context.getResources().getInteger(R.integer.guardianproject_repo_inuse), - context.getResources().getInteger(R.integer.guardianproject_repo_priority) - ); - - insertRepo( - db, - context.getString(R.string.guardianproject_archive_name), - context.getString(R.string.guardianproject_archive_address), - context.getString(R.string.guardianproject_archive_description), - context.getString(R.string.guardianproject_archive_pubkey), - context.getResources().getInteger(R.integer.guardianproject_archive_version), - context.getResources().getInteger(R.integer.guardianproject_archive_inuse), - context.getResources().getInteger(R.integer.guardianproject_archive_priority) - ); + String[] defaultRepos = context.getResources().getStringArray(R.array.default_repos); + if (defaultRepos.length % REPO_XML_ARG_COUNT != 0) { + throw new IllegalArgumentException( + "default_repo.xml array does not have the right number of elements"); + } + for (int i = 0; i < defaultRepos.length / REPO_XML_ARG_COUNT; i++) { + int offset = i * REPO_XML_ARG_COUNT; + insertRepo( + db, + defaultRepos[offset], // name + defaultRepos[offset + 1], // address + defaultRepos[offset + 2], // description + defaultRepos[offset + 3], // version + defaultRepos[offset + 4], // enabled + defaultRepos[offset + 5], // priority + defaultRepos[offset + 6], // pushRequests + defaultRepos[offset + 7] // pubkey + ); + } } private void insertRepo(SQLiteDatabase db, String name, String address, - String description, String pubKey, int version, int inUse, - int priority) { - + String description, String version, String enabled, + String priority, String pushRequests, String pubKey) { ContentValues values = new ContentValues(); values.put(RepoTable.Cols.ADDRESS, address); values.put(RepoTable.Cols.NAME, name); @@ -285,13 +286,27 @@ class DBHelper extends SQLiteOpenHelper { values.put(RepoTable.Cols.SIGNING_CERT, pubKey); values.put(RepoTable.Cols.FINGERPRINT, Utils.calcFingerprint(pubKey)); values.put(RepoTable.Cols.MAX_AGE, 0); - values.put(RepoTable.Cols.VERSION, version); - values.put(RepoTable.Cols.IN_USE, inUse); - values.put(RepoTable.Cols.PRIORITY, priority); + values.put(RepoTable.Cols.VERSION, Utils.parseInt(version, 0)); + values.put(RepoTable.Cols.IN_USE, Utils.parseInt(enabled, 0)); + values.put(RepoTable.Cols.PRIORITY, Utils.parseInt(priority, Integer.MAX_VALUE)); values.put(RepoTable.Cols.LAST_ETAG, (String) null); values.put(RepoTable.Cols.TIMESTAMP, 0); - Utils.debugLog(TAG, "Adding repository " + name); + switch (pushRequests) { + case "ignore": + values.put(RepoTable.Cols.PUSH_REQUESTS, Repo.PUSH_REQUEST_IGNORE); + break; + case "prompt": + values.put(RepoTable.Cols.PUSH_REQUESTS, Repo.PUSH_REQUEST_PROMPT); + break; + case "always": + values.put(RepoTable.Cols.PUSH_REQUESTS, Repo.PUSH_REQUEST_ACCEPT_ALWAYS); + break; + default: + throw new IllegalArgumentException(pushRequests + " is not a supported option!"); + } + + Utils.debugLog(TAG, "Adding repository " + name + " with push requests as " + pushRequests); db.insert(RepoTable.NAME, null, values); } @@ -328,6 +343,7 @@ class DBHelper extends SQLiteOpenHelper { removeApkPackageNameColumn(db, oldVersion); addAppPrefsTable(db, oldVersion); lowerCaseApkHashes(db, oldVersion); + supportRepoPushRequests(db, oldVersion); } private void lowerCaseApkHashes(SQLiteDatabase db, int oldVersion) { @@ -516,13 +532,13 @@ class DBHelper extends SQLiteOpenHelper { } private void insertNameAndDescription(SQLiteDatabase db, - int addressResId, int nameResId, int descriptionResId) { + String name, String address, String description) { ContentValues values = new ContentValues(); values.clear(); - values.put(RepoTable.Cols.NAME, context.getString(nameResId)); - values.put(RepoTable.Cols.DESCRIPTION, context.getString(descriptionResId)); - db.update(RepoTable.NAME, values, RepoTable.Cols.ADDRESS + " = ?", new String[] { - context.getString(addressResId), + values.put(RepoTable.Cols.NAME, name); + values.put(RepoTable.Cols.DESCRIPTION, description); + db.update(RepoTable.NAME, values, RepoTable.Cols.ADDRESS + " = ?", new String[]{ + address, }); } @@ -542,15 +558,16 @@ class DBHelper extends SQLiteOpenHelper { if (!descriptionExists) { db.execSQL("alter table " + RepoTable.NAME + " add column " + RepoTable.Cols.DESCRIPTION + " text"); } - insertNameAndDescription(db, R.string.fdroid_repo_address, - R.string.fdroid_repo_name, R.string.fdroid_repo_description); - insertNameAndDescription(db, R.string.fdroid_archive_address, - R.string.fdroid_archive_name, R.string.fdroid_archive_description); - insertNameAndDescription(db, R.string.guardianproject_repo_address, - R.string.guardianproject_repo_name, R.string.guardianproject_repo_description); - insertNameAndDescription(db, R.string.guardianproject_archive_address, - R.string.guardianproject_archive_name, R.string.guardianproject_archive_description); + String[] defaultRepos = context.getResources().getStringArray(R.array.default_repos); + for (int i = 0; i < defaultRepos.length / REPO_XML_ARG_COUNT; i++) { + int offset = i * REPO_XML_ARG_COUNT; + insertNameAndDescription(db, + defaultRepos[offset], // name + defaultRepos[offset + 1], // address + defaultRepos[offset + 2] // description + ); + } } /** @@ -795,6 +812,17 @@ class DBHelper extends SQLiteOpenHelper { + ApkTable.Cols.TARGET_SDK_VERSION + " integer"); } + private void supportRepoPushRequests(SQLiteDatabase db, int oldVersion) { + if (oldVersion >= 61) { + return; + } + Utils.debugLog(TAG, "Adding " + RepoTable.Cols.PUSH_REQUESTS + + " columns to " + RepoTable.NAME); + db.execSQL("alter table " + RepoTable.NAME + " add column " + + RepoTable.Cols.PUSH_REQUESTS + " integer not null default " + + Repo.PUSH_REQUEST_IGNORE); + } + private static boolean columnExists(SQLiteDatabase db, String table, String column) { Cursor cursor = db.rawQuery("select * from " + table + " limit 0,1", null); boolean exists = cursor.getColumnIndex(column) != -1; diff --git a/app/src/main/java/org/fdroid/fdroid/data/Repo.java b/app/src/main/java/org/fdroid/fdroid/data/Repo.java index 62746de2b..fa8289bdf 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/Repo.java +++ b/app/src/main/java/org/fdroid/fdroid/data/Repo.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2016 Blue Jay Wireless + * Copyright (C) 2014-2016 Daniel Martí + * Copyright (C) 2014-2016 Hans-Christoph Steiner + * Copyright (C) 2014-2016 Peter Serwylo + * Copyright (C) 2015 Christian Morgner + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 3 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * 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. + */ + package org.fdroid.fdroid.data; import android.content.ContentValues; @@ -15,6 +38,10 @@ public class Repo extends ValueObject { public static final int VERSION_DENSITY_SPECIFIC_ICONS = 11; + public static final int PUSH_REQUEST_IGNORE = 0; + public static final int PUSH_REQUEST_PROMPT = 1; + public static final int PUSH_REQUEST_ACCEPT_ALWAYS = 2; + protected long id; public String address; @@ -44,6 +71,9 @@ public class Repo extends ValueObject { /** When the signed repo index was generated, used to protect against replay attacks */ public long timestamp; + /** How to treat push requests included in this repo's index XML */ + public int pushRequests = PUSH_REQUEST_IGNORE; + public Repo() { } @@ -101,6 +131,9 @@ public class Repo extends ValueObject { case Cols.TIMESTAMP: timestamp = cursor.getLong(i); break; + case Cols.PUSH_REQUESTS: + pushRequests = cursor.getInt(i); + break; } } } @@ -223,5 +256,9 @@ public class Repo extends ValueObject { if (values.containsKey(Cols.TIMESTAMP)) { timestamp = toInt(values.getAsInteger(Cols.TIMESTAMP)); } + + if (values.containsKey(Cols.PUSH_REQUESTS)) { + pushRequests = toInt(values.getAsInteger(Cols.PUSH_REQUESTS)); + } } } diff --git a/app/src/main/java/org/fdroid/fdroid/data/RepoPushRequest.java b/app/src/main/java/org/fdroid/fdroid/data/RepoPushRequest.java new file mode 100644 index 000000000..1c89b0884 --- /dev/null +++ b/app/src/main/java/org/fdroid/fdroid/data/RepoPushRequest.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2016 Blue Jay Wireless + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 3 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * 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. + */ + +package org.fdroid.fdroid.data; + +import android.support.annotation.Nullable; + +/** + * Represents action requests embedded in the index XML received from a repo. + * When {@link #versionCode} is {@code null}, that means that the + * {@code versionCode} was not specified by the server, and F-Droid should + * install the best available version. + */ +public class RepoPushRequest { + public static final String TAG = "RepoPushRequest"; + + public static final String INSTALL = "install"; + public static final String UNINSTALL = "uninstall"; + + public final String request; + public final String packageName; + @Nullable + public final Integer versionCode; + + public RepoPushRequest(String request, String packageName, String versionCode) { + this.request = request; + this.packageName = packageName; + + Integer i; + try { + i = Integer.parseInt(versionCode); + } catch (NumberFormatException e) { + i = null; + } + this.versionCode = i; + } + + @Override + public String toString() { + return request + " " + packageName + " " + versionCode; + } +} diff --git a/app/src/main/java/org/fdroid/fdroid/data/Schema.java b/app/src/main/java/org/fdroid/fdroid/data/Schema.java index 88987b1de..dc5432958 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/Schema.java +++ b/app/src/main/java/org/fdroid/fdroid/data/Schema.java @@ -196,11 +196,12 @@ public interface Schema { String USERNAME = "username"; String PASSWORD = "password"; String TIMESTAMP = "timestamp"; + String PUSH_REQUESTS = "pushRequests"; String[] ALL = { _ID, ADDRESS, NAME, DESCRIPTION, IN_USE, PRIORITY, SIGNING_CERT, FINGERPRINT, MAX_AGE, LAST_UPDATED, LAST_ETAG, VERSION, IS_SWAP, - USERNAME, PASSWORD, TIMESTAMP, + USERNAME, PASSWORD, TIMESTAMP, PUSH_REQUESTS, }; } } diff --git a/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java b/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java index 320789a5f..1a21bd9db 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java @@ -148,6 +148,10 @@ public class InstallManagerService extends Service { App app = intent.getParcelableExtra(EXTRA_APP); Apk apk = intent.getParcelableExtra(EXTRA_APK); + if (app == null || apk == null) { + Utils.debugLog(TAG, "Intent had null EXTRA_APP and/or EXTRA_APK: " + intent); + return START_NOT_STICKY; + } addToActive(urlString, app, apk); NotificationCompat.Builder builder = createNotificationBuilder(urlString, apk); diff --git a/app/src/main/java/org/fdroid/fdroid/installer/InstallerService.java b/app/src/main/java/org/fdroid/fdroid/installer/InstallerService.java index 7ceee54c2..4e3b3ad9f 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/InstallerService.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/InstallerService.java @@ -24,6 +24,7 @@ import android.content.Context; import android.content.Intent; import android.net.Uri; +import org.fdroid.fdroid.Utils; import org.fdroid.fdroid.data.Apk; /** @@ -41,6 +42,7 @@ import org.fdroid.fdroid.data.Apk; * {@link InstallManagerService}. */ public class InstallerService extends IntentService { + public static final String TAG = "InstallerService"; private static final String ACTION_INSTALL = "org.fdroid.fdroid.installer.InstallerService.action.INSTALL"; private static final String ACTION_UNINSTALL = "org.fdroid.fdroid.installer.InstallerService.action.UNINSTALL"; @@ -52,7 +54,10 @@ public class InstallerService extends IntentService { @Override protected void onHandleIntent(Intent intent) { Apk apk = intent.getParcelableExtra(Installer.EXTRA_APK); - + if (apk == null) { + Utils.debugLog(TAG, "ignoring intent with null EXTRA_APK: " + intent); + return; + } Installer installer = InstallerFactory.create(this, apk); if (ACTION_INSTALL.equals(intent.getAction())) { diff --git a/app/src/main/res/values/default_repo.xml b/app/src/main/res/values/default_repo.xml deleted file mode 100644 index 342561b6a..000000000 --- a/app/src/main/res/values/default_repo.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - F-Droid - - 13 - 1 - 10 - - https://f-droid.org/repo - The official F-Droid repository. Applications in this repository are mostly built directory from the source code. Some are official binaries built by the original application developers - these will be replaced by source-built versions over time. - 3082035e30820246a00302010202044c49cd00300d06092a864886f70d01010505003071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b73301e170d3130303732333137313032345a170d3337313230383137313032345a3071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b7330820122300d06092a864886f70d01010105000382010f003082010a028201010096d075e47c014e7822c89fd67f795d23203e2a8843f53ba4e6b1bf5f2fd0e225938267cfcae7fbf4fe596346afbaf4070fdb91f66fbcdf2348a3d92430502824f80517b156fab00809bdc8e631bfa9afd42d9045ab5fd6d28d9e140afc1300917b19b7c6c4df4a494cf1f7cb4a63c80d734265d735af9e4f09455f427aa65a53563f87b336ca2c19d244fcbba617ba0b19e56ed34afe0b253ab91e2fdb1271f1b9e3c3232027ed8862a112f0706e234cf236914b939bcf959821ecb2a6c18057e070de3428046d94b175e1d89bd795e535499a091f5bc65a79d539a8d43891ec504058acb28c08393b5718b57600a211e803f4a634e5c57f25b9b8c4422c6fd90203010001300d06092a864886f70d0101050500038201010008e4ef699e9807677ff56753da73efb2390d5ae2c17e4db691d5df7a7b60fc071ae509c5414be7d5da74df2811e83d3668c4a0b1abc84b9fa7d96b4cdf30bba68517ad2a93e233b042972ac0553a4801c9ebe07bf57ebe9a3b3d6d663965260e50f3b8f46db0531761e60340a2bddc3426098397fda54044a17e5244549f9869b460ca5e6e216b6f6a2db0580b480ca2afe6ec6b46eedacfa4aa45038809ece0c5978653d6c85f678e7f5a2156d1bedd8117751e64a4b0dcd140f3040b021821a8d93aed8d01ba36db6c82372211fed714d9a32607038cdfd565bd529ffc637212aaa2c224ef22b603eccefb5bf1e085c191d4b24fe742b17ab3f55d4e6f05ef - - - F-Droid Archive - - 13 - 0 - 20 - - https://f-droid.org/archive - The archive repository of the F-Droid client. This contains older versions of applications from the main repository. - 3082035e30820246a00302010202044c49cd00300d06092a864886f70d01010505003071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b73301e170d3130303732333137313032345a170d3337313230383137313032345a3071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b7330820122300d06092a864886f70d01010105000382010f003082010a028201010096d075e47c014e7822c89fd67f795d23203e2a8843f53ba4e6b1bf5f2fd0e225938267cfcae7fbf4fe596346afbaf4070fdb91f66fbcdf2348a3d92430502824f80517b156fab00809bdc8e631bfa9afd42d9045ab5fd6d28d9e140afc1300917b19b7c6c4df4a494cf1f7cb4a63c80d734265d735af9e4f09455f427aa65a53563f87b336ca2c19d244fcbba617ba0b19e56ed34afe0b253ab91e2fdb1271f1b9e3c3232027ed8862a112f0706e234cf236914b939bcf959821ecb2a6c18057e070de3428046d94b175e1d89bd795e535499a091f5bc65a79d539a8d43891ec504058acb28c08393b5718b57600a211e803f4a634e5c57f25b9b8c4422c6fd90203010001300d06092a864886f70d0101050500038201010008e4ef699e9807677ff56753da73efb2390d5ae2c17e4db691d5df7a7b60fc071ae509c5414be7d5da74df2811e83d3668c4a0b1abc84b9fa7d96b4cdf30bba68517ad2a93e233b042972ac0553a4801c9ebe07bf57ebe9a3b3d6d663965260e50f3b8f46db0531761e60340a2bddc3426098397fda54044a17e5244549f9869b460ca5e6e216b6f6a2db0580b480ca2afe6ec6b46eedacfa4aa45038809ece0c5978653d6c85f678e7f5a2156d1bedd8117751e64a4b0dcd140f3040b021821a8d93aed8d01ba36db6c82372211fed714d9a32607038cdfd565bd529ffc637212aaa2c224ef22b603eccefb5bf1e085c191d4b24fe742b17ab3f55d4e6f05ef - - - Guardian Project - - 13 - 0 - 10 - - https://guardianproject.info/fdroid/repo - The official app repository of The Guardian Project. Applications in this repository are official binaries build by the original application developers and signed by the same key as the APKs that are released in the Google Play store. - 308205d8308203c0020900a397b4da7ecda034300d06092a864886f70d01010505003081ad310b30090603550406130255533111300f06035504080c084e657720596f726b3111300f06035504070c084e657720596f726b31143012060355040b0c0b4644726f6964205265706f31193017060355040a0c10477561726469616e2050726f6a656374311d301b06035504030c14677561726469616e70726f6a6563742e696e666f3128302606092a864886f70d0109011619726f6f7440677561726469616e70726f6a6563742e696e666f301e170d3134303632363139333931385a170d3431313131303139333931385a3081ad310b30090603550406130255533111300f06035504080c084e657720596f726b3111300f06035504070c084e657720596f726b31143012060355040b0c0b4644726f6964205265706f31193017060355040a0c10477561726469616e2050726f6a656374311d301b06035504030c14677561726469616e70726f6a6563742e696e666f3128302606092a864886f70d0109011619726f6f7440677561726469616e70726f6a6563742e696e666f30820222300d06092a864886f70d01010105000382020f003082020a0282020100b3cd79121b9b883843be3c4482e320809106b0a23755f1dd3c7f46f7d315d7bb2e943486d61fc7c811b9294dcc6b5baac4340f8db2b0d5e14749e7f35e1fc211fdbc1071b38b4753db201c314811bef885bd8921ad86facd6cc3b8f74d30a0b6e2e6e576f906e9581ef23d9c03e926e06d1f033f28bd1e21cfa6a0e3ff5c9d8246cf108d82b488b9fdd55d7de7ebb6a7f64b19e0d6b2ab1380a6f9d42361770d1956701a7f80e2de568acd0bb4527324b1e0973e89595d91c8cc102d9248525ae092e2c9b69f7414f724195b81427f28b1d3d09a51acfe354387915fd9521e8c890c125fc41a12bf34d2a1b304067ab7251e0e9ef41833ce109e76963b0b256395b16b886bca21b831f1408f836146019e7908829e716e72b81006610a2af08301de5d067c9e114a1e5759db8a6be6a3cc2806bcfe6fafd41b5bc9ddddb3dc33d6f605b1ca7d8a9e0ecdd6390d38906649e68a90a717bea80fa220170eea0c86fc78a7e10dac7b74b8e62045a3ecca54e035281fdc9fe5920a855fde3c0be522e3aef0c087524f13d973dff3768158b01a5800a060c06b451ec98d627dd052eda804d0556f60dbc490d94e6e9dea62ffcafb5beffbd9fc38fb2f0d7050004fe56b4dda0a27bc47554e1e0a7d764e17622e71f83a475db286bc7862deee1327e2028955d978272ea76bf0b88e70a18621aba59ff0c5993ef5f0e5d6b6b98e68b70203010001300d06092a864886f70d0101050500038202010079c79c8ef408a20d243d8bd8249fb9a48350dc19663b5e0fce67a8dbcb7de296c5ae7bbf72e98a2020fb78f2db29b54b0e24b181aa1c1d333cc0303685d6120b03216a913f96b96eb838f9bff125306ae3120af838c9fc07ebb5100125436bd24ec6d994d0bff5d065221871f8410daf536766757239bf594e61c5432c9817281b985263bada8381292e543a49814061ae11c92a316e7dc100327b59e3da90302c5ada68c6a50201bda1fcce800b53f381059665dbabeeb0b50eb22b2d7d2d9b0aa7488ca70e67ac6c518adb8e78454a466501e89d81a45bf1ebc350896f2c3ae4b6679ecfbf9d32960d4f5b493125c7876ef36158562371193f600bc511000a67bdb7c664d018f99d9e589868d103d7e0994f166b2ba18ff7e67d8c4da749e44dfae1d930ae5397083a51675c409049dfb626a96246c0015ca696e94ebb767a20147834bf78b07fece3f0872b057c1c519ff882501995237d8206b0b3832f78753ebd8dcbd1d3d9f5ba733538113af6b407d960ec4353c50eb38ab29888238da843cd404ed8f4952f59e4bbc0035fc77a54846a9d419179c46af1b4a3b7fc98e4d312aaa29b9b7d79e739703dc0fa41c7280d5587709277ffa11c3620f5fba985b82c238ba19b17ebd027af9424be0941719919f620dd3bb3c3f11638363708aa11f858e153cf3a69bce69978b90e4a273836100aa1e617ba455cd00426847f - - - Guardian Project Archive - - 13 - 0 - 20 - - https://guardianproject.info/fdroid/archive - The official repository of The Guardian Project apps for use with F-Droid client. This contains older versions of applications from the main repository. - 308205d8308203c0020900a397b4da7ecda034300d06092a864886f70d01010505003081ad310b30090603550406130255533111300f06035504080c084e657720596f726b3111300f06035504070c084e657720596f726b31143012060355040b0c0b4644726f6964205265706f31193017060355040a0c10477561726469616e2050726f6a656374311d301b06035504030c14677561726469616e70726f6a6563742e696e666f3128302606092a864886f70d0109011619726f6f7440677561726469616e70726f6a6563742e696e666f301e170d3134303632363139333931385a170d3431313131303139333931385a3081ad310b30090603550406130255533111300f06035504080c084e657720596f726b3111300f06035504070c084e657720596f726b31143012060355040b0c0b4644726f6964205265706f31193017060355040a0c10477561726469616e2050726f6a656374311d301b06035504030c14677561726469616e70726f6a6563742e696e666f3128302606092a864886f70d0109011619726f6f7440677561726469616e70726f6a6563742e696e666f30820222300d06092a864886f70d01010105000382020f003082020a0282020100b3cd79121b9b883843be3c4482e320809106b0a23755f1dd3c7f46f7d315d7bb2e943486d61fc7c811b9294dcc6b5baac4340f8db2b0d5e14749e7f35e1fc211fdbc1071b38b4753db201c314811bef885bd8921ad86facd6cc3b8f74d30a0b6e2e6e576f906e9581ef23d9c03e926e06d1f033f28bd1e21cfa6a0e3ff5c9d8246cf108d82b488b9fdd55d7de7ebb6a7f64b19e0d6b2ab1380a6f9d42361770d1956701a7f80e2de568acd0bb4527324b1e0973e89595d91c8cc102d9248525ae092e2c9b69f7414f724195b81427f28b1d3d09a51acfe354387915fd9521e8c890c125fc41a12bf34d2a1b304067ab7251e0e9ef41833ce109e76963b0b256395b16b886bca21b831f1408f836146019e7908829e716e72b81006610a2af08301de5d067c9e114a1e5759db8a6be6a3cc2806bcfe6fafd41b5bc9ddddb3dc33d6f605b1ca7d8a9e0ecdd6390d38906649e68a90a717bea80fa220170eea0c86fc78a7e10dac7b74b8e62045a3ecca54e035281fdc9fe5920a855fde3c0be522e3aef0c087524f13d973dff3768158b01a5800a060c06b451ec98d627dd052eda804d0556f60dbc490d94e6e9dea62ffcafb5beffbd9fc38fb2f0d7050004fe56b4dda0a27bc47554e1e0a7d764e17622e71f83a475db286bc7862deee1327e2028955d978272ea76bf0b88e70a18621aba59ff0c5993ef5f0e5d6b6b98e68b70203010001300d06092a864886f70d0101050500038202010079c79c8ef408a20d243d8bd8249fb9a48350dc19663b5e0fce67a8dbcb7de296c5ae7bbf72e98a2020fb78f2db29b54b0e24b181aa1c1d333cc0303685d6120b03216a913f96b96eb838f9bff125306ae3120af838c9fc07ebb5100125436bd24ec6d994d0bff5d065221871f8410daf536766757239bf594e61c5432c9817281b985263bada8381292e543a49814061ae11c92a316e7dc100327b59e3da90302c5ada68c6a50201bda1fcce800b53f381059665dbabeeb0b50eb22b2d7d2d9b0aa7488ca70e67ac6c518adb8e78454a466501e89d81a45bf1ebc350896f2c3ae4b6679ecfbf9d32960d4f5b493125c7876ef36158562371193f600bc511000a67bdb7c664d018f99d9e589868d103d7e0994f166b2ba18ff7e67d8c4da749e44dfae1d930ae5397083a51675c409049dfb626a96246c0015ca696e94ebb767a20147834bf78b07fece3f0872b057c1c519ff882501995237d8206b0b3832f78753ebd8dcbd1d3d9f5ba733538113af6b407d960ec4353c50eb38ab29888238da843cd404ed8f4952f59e4bbc0035fc77a54846a9d419179c46af1b4a3b7fc98e4d312aaa29b9b7d79e739703dc0fa41c7280d5587709277ffa11c3620f5fba985b82c238ba19b17ebd027af9424be0941719919f620dd3bb3c3f11638363708aa11f858e153cf3a69bce69978b90e4a273836100aa1e617ba455cd00426847f - - diff --git a/app/src/main/res/values/default_repos.xml b/app/src/main/res/values/default_repos.xml new file mode 100644 index 000000000..6a09a6920 --- /dev/null +++ b/app/src/main/res/values/default_repos.xml @@ -0,0 +1,94 @@ + + + + + + + F-Droid + + https://f-droid.org/repo + + The official F-Droid repository. Applications in this repository are mostly built + directory from the source code. Some are official binaries built by the original + application developers - these will be replaced by source-built versions over time. + + + 13 + + 1 + + 10 + + ignore + + + 3082035e30820246a00302010202044c49cd00300d06092a864886f70d01010505003071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b73301e170d3130303732333137313032345a170d3337313230383137313032345a3071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b7330820122300d06092a864886f70d01010105000382010f003082010a028201010096d075e47c014e7822c89fd67f795d23203e2a8843f53ba4e6b1bf5f2fd0e225938267cfcae7fbf4fe596346afbaf4070fdb91f66fbcdf2348a3d92430502824f80517b156fab00809bdc8e631bfa9afd42d9045ab5fd6d28d9e140afc1300917b19b7c6c4df4a494cf1f7cb4a63c80d734265d735af9e4f09455f427aa65a53563f87b336ca2c19d244fcbba617ba0b19e56ed34afe0b253ab91e2fdb1271f1b9e3c3232027ed8862a112f0706e234cf236914b939bcf959821ecb2a6c18057e070de3428046d94b175e1d89bd795e535499a091f5bc65a79d539a8d43891ec504058acb28c08393b5718b57600a211e803f4a634e5c57f25b9b8c4422c6fd90203010001300d06092a864886f70d0101050500038201010008e4ef699e9807677ff56753da73efb2390d5ae2c17e4db691d5df7a7b60fc071ae509c5414be7d5da74df2811e83d3668c4a0b1abc84b9fa7d96b4cdf30bba68517ad2a93e233b042972ac0553a4801c9ebe07bf57ebe9a3b3d6d663965260e50f3b8f46db0531761e60340a2bddc3426098397fda54044a17e5244549f9869b460ca5e6e216b6f6a2db0580b480ca2afe6ec6b46eedacfa4aa45038809ece0c5978653d6c85f678e7f5a2156d1bedd8117751e64a4b0dcd140f3040b021821a8d93aed8d01ba36db6c82372211fed714d9a32607038cdfd565bd529ffc637212aaa2c224ef22b603eccefb5bf1e085c191d4b24fe742b17ab3f55d4e6f05ef + + + + F-Droid Archive + + https://f-droid.org/archive + + The archive repository of the F-Droid client. This contains older versions of + applications from the main repository. + + + 13 + + 0 + + 20 + + ignore + + + 3082035e30820246a00302010202044c49cd00300d06092a864886f70d01010505003071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b73301e170d3130303732333137313032345a170d3337313230383137313032345a3071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b7330820122300d06092a864886f70d01010105000382010f003082010a028201010096d075e47c014e7822c89fd67f795d23203e2a8843f53ba4e6b1bf5f2fd0e225938267cfcae7fbf4fe596346afbaf4070fdb91f66fbcdf2348a3d92430502824f80517b156fab00809bdc8e631bfa9afd42d9045ab5fd6d28d9e140afc1300917b19b7c6c4df4a494cf1f7cb4a63c80d734265d735af9e4f09455f427aa65a53563f87b336ca2c19d244fcbba617ba0b19e56ed34afe0b253ab91e2fdb1271f1b9e3c3232027ed8862a112f0706e234cf236914b939bcf959821ecb2a6c18057e070de3428046d94b175e1d89bd795e535499a091f5bc65a79d539a8d43891ec504058acb28c08393b5718b57600a211e803f4a634e5c57f25b9b8c4422c6fd90203010001300d06092a864886f70d0101050500038201010008e4ef699e9807677ff56753da73efb2390d5ae2c17e4db691d5df7a7b60fc071ae509c5414be7d5da74df2811e83d3668c4a0b1abc84b9fa7d96b4cdf30bba68517ad2a93e233b042972ac0553a4801c9ebe07bf57ebe9a3b3d6d663965260e50f3b8f46db0531761e60340a2bddc3426098397fda54044a17e5244549f9869b460ca5e6e216b6f6a2db0580b480ca2afe6ec6b46eedacfa4aa45038809ece0c5978653d6c85f678e7f5a2156d1bedd8117751e64a4b0dcd140f3040b021821a8d93aed8d01ba36db6c82372211fed714d9a32607038cdfd565bd529ffc637212aaa2c224ef22b603eccefb5bf1e085c191d4b24fe742b17ab3f55d4e6f05ef + + + + Guardian Project + + https://guardianproject.info/fdroid/repo + + The official app repository of The Guardian Project. Applications in this repository + are official binaries build by the original application developers and signed by the + same key as the APKs that are released in the Google Play store. + + + 13 + + 0 + + 10 + + ignore + + + 308205d8308203c0020900a397b4da7ecda034300d06092a864886f70d01010505003081ad310b30090603550406130255533111300f06035504080c084e657720596f726b3111300f06035504070c084e657720596f726b31143012060355040b0c0b4644726f6964205265706f31193017060355040a0c10477561726469616e2050726f6a656374311d301b06035504030c14677561726469616e70726f6a6563742e696e666f3128302606092a864886f70d0109011619726f6f7440677561726469616e70726f6a6563742e696e666f301e170d3134303632363139333931385a170d3431313131303139333931385a3081ad310b30090603550406130255533111300f06035504080c084e657720596f726b3111300f06035504070c084e657720596f726b31143012060355040b0c0b4644726f6964205265706f31193017060355040a0c10477561726469616e2050726f6a656374311d301b06035504030c14677561726469616e70726f6a6563742e696e666f3128302606092a864886f70d0109011619726f6f7440677561726469616e70726f6a6563742e696e666f30820222300d06092a864886f70d01010105000382020f003082020a0282020100b3cd79121b9b883843be3c4482e320809106b0a23755f1dd3c7f46f7d315d7bb2e943486d61fc7c811b9294dcc6b5baac4340f8db2b0d5e14749e7f35e1fc211fdbc1071b38b4753db201c314811bef885bd8921ad86facd6cc3b8f74d30a0b6e2e6e576f906e9581ef23d9c03e926e06d1f033f28bd1e21cfa6a0e3ff5c9d8246cf108d82b488b9fdd55d7de7ebb6a7f64b19e0d6b2ab1380a6f9d42361770d1956701a7f80e2de568acd0bb4527324b1e0973e89595d91c8cc102d9248525ae092e2c9b69f7414f724195b81427f28b1d3d09a51acfe354387915fd9521e8c890c125fc41a12bf34d2a1b304067ab7251e0e9ef41833ce109e76963b0b256395b16b886bca21b831f1408f836146019e7908829e716e72b81006610a2af08301de5d067c9e114a1e5759db8a6be6a3cc2806bcfe6fafd41b5bc9ddddb3dc33d6f605b1ca7d8a9e0ecdd6390d38906649e68a90a717bea80fa220170eea0c86fc78a7e10dac7b74b8e62045a3ecca54e035281fdc9fe5920a855fde3c0be522e3aef0c087524f13d973dff3768158b01a5800a060c06b451ec98d627dd052eda804d0556f60dbc490d94e6e9dea62ffcafb5beffbd9fc38fb2f0d7050004fe56b4dda0a27bc47554e1e0a7d764e17622e71f83a475db286bc7862deee1327e2028955d978272ea76bf0b88e70a18621aba59ff0c5993ef5f0e5d6b6b98e68b70203010001300d06092a864886f70d0101050500038202010079c79c8ef408a20d243d8bd8249fb9a48350dc19663b5e0fce67a8dbcb7de296c5ae7bbf72e98a2020fb78f2db29b54b0e24b181aa1c1d333cc0303685d6120b03216a913f96b96eb838f9bff125306ae3120af838c9fc07ebb5100125436bd24ec6d994d0bff5d065221871f8410daf536766757239bf594e61c5432c9817281b985263bada8381292e543a49814061ae11c92a316e7dc100327b59e3da90302c5ada68c6a50201bda1fcce800b53f381059665dbabeeb0b50eb22b2d7d2d9b0aa7488ca70e67ac6c518adb8e78454a466501e89d81a45bf1ebc350896f2c3ae4b6679ecfbf9d32960d4f5b493125c7876ef36158562371193f600bc511000a67bdb7c664d018f99d9e589868d103d7e0994f166b2ba18ff7e67d8c4da749e44dfae1d930ae5397083a51675c409049dfb626a96246c0015ca696e94ebb767a20147834bf78b07fece3f0872b057c1c519ff882501995237d8206b0b3832f78753ebd8dcbd1d3d9f5ba733538113af6b407d960ec4353c50eb38ab29888238da843cd404ed8f4952f59e4bbc0035fc77a54846a9d419179c46af1b4a3b7fc98e4d312aaa29b9b7d79e739703dc0fa41c7280d5587709277ffa11c3620f5fba985b82c238ba19b17ebd027af9424be0941719919f620dd3bb3c3f11638363708aa11f858e153cf3a69bce69978b90e4a273836100aa1e617ba455cd00426847f + + + + Guardian Project Archive + + https://guardianproject.info/fdroid/archive + + The official repository of The Guardian Project apps for use with F-Droid client. This + contains older versions of applications from the main repository. + + + 13 + + 0 + + 20 + + ignore + + + 308205d8308203c0020900a397b4da7ecda034300d06092a864886f70d01010505003081ad310b30090603550406130255533111300f06035504080c084e657720596f726b3111300f06035504070c084e657720596f726b31143012060355040b0c0b4644726f6964205265706f31193017060355040a0c10477561726469616e2050726f6a656374311d301b06035504030c14677561726469616e70726f6a6563742e696e666f3128302606092a864886f70d0109011619726f6f7440677561726469616e70726f6a6563742e696e666f301e170d3134303632363139333931385a170d3431313131303139333931385a3081ad310b30090603550406130255533111300f06035504080c084e657720596f726b3111300f06035504070c084e657720596f726b31143012060355040b0c0b4644726f6964205265706f31193017060355040a0c10477561726469616e2050726f6a656374311d301b06035504030c14677561726469616e70726f6a6563742e696e666f3128302606092a864886f70d0109011619726f6f7440677561726469616e70726f6a6563742e696e666f30820222300d06092a864886f70d01010105000382020f003082020a0282020100b3cd79121b9b883843be3c4482e320809106b0a23755f1dd3c7f46f7d315d7bb2e943486d61fc7c811b9294dcc6b5baac4340f8db2b0d5e14749e7f35e1fc211fdbc1071b38b4753db201c314811bef885bd8921ad86facd6cc3b8f74d30a0b6e2e6e576f906e9581ef23d9c03e926e06d1f033f28bd1e21cfa6a0e3ff5c9d8246cf108d82b488b9fdd55d7de7ebb6a7f64b19e0d6b2ab1380a6f9d42361770d1956701a7f80e2de568acd0bb4527324b1e0973e89595d91c8cc102d9248525ae092e2c9b69f7414f724195b81427f28b1d3d09a51acfe354387915fd9521e8c890c125fc41a12bf34d2a1b304067ab7251e0e9ef41833ce109e76963b0b256395b16b886bca21b831f1408f836146019e7908829e716e72b81006610a2af08301de5d067c9e114a1e5759db8a6be6a3cc2806bcfe6fafd41b5bc9ddddb3dc33d6f605b1ca7d8a9e0ecdd6390d38906649e68a90a717bea80fa220170eea0c86fc78a7e10dac7b74b8e62045a3ecca54e035281fdc9fe5920a855fde3c0be522e3aef0c087524f13d973dff3768158b01a5800a060c06b451ec98d627dd052eda804d0556f60dbc490d94e6e9dea62ffcafb5beffbd9fc38fb2f0d7050004fe56b4dda0a27bc47554e1e0a7d764e17622e71f83a475db286bc7862deee1327e2028955d978272ea76bf0b88e70a18621aba59ff0c5993ef5f0e5d6b6b98e68b70203010001300d06092a864886f70d0101050500038202010079c79c8ef408a20d243d8bd8249fb9a48350dc19663b5e0fce67a8dbcb7de296c5ae7bbf72e98a2020fb78f2db29b54b0e24b181aa1c1d333cc0303685d6120b03216a913f96b96eb838f9bff125306ae3120af838c9fc07ebb5100125436bd24ec6d994d0bff5d065221871f8410daf536766757239bf594e61c5432c9817281b985263bada8381292e543a49814061ae11c92a316e7dc100327b59e3da90302c5ada68c6a50201bda1fcce800b53f381059665dbabeeb0b50eb22b2d7d2d9b0aa7488ca70e67ac6c518adb8e78454a466501e89d81a45bf1ebc350896f2c3ae4b6679ecfbf9d32960d4f5b493125c7876ef36158562371193f600bc511000a67bdb7c664d018f99d9e589868d103d7e0994f166b2ba18ff7e67d8c4da749e44dfae1d930ae5397083a51675c409049dfb626a96246c0015ca696e94ebb767a20147834bf78b07fece3f0872b057c1c519ff882501995237d8206b0b3832f78753ebd8dcbd1d3d9f5ba733538113af6b407d960ec4353c50eb38ab29888238da843cd404ed8f4952f59e4bbc0035fc77a54846a9d419179c46af1b4a3b7fc98e4d312aaa29b9b7d79e739703dc0fa41c7280d5587709277ffa11c3620f5fba985b82c238ba19b17ebd027af9424be0941719919f620dd3bb3c3f11638363708aa11f858e153cf3a69bce69978b90e4a273836100aa1e617ba455cd00426847f + + + + + diff --git a/app/src/test/java/org/fdroid/fdroid/RepoXMLHandlerTest.java b/app/src/test/java/org/fdroid/fdroid/RepoXMLHandlerTest.java index ac1056331..2f40767db 100644 --- a/app/src/test/java/org/fdroid/fdroid/RepoXMLHandlerTest.java +++ b/app/src/test/java/org/fdroid/fdroid/RepoXMLHandlerTest.java @@ -1,3 +1,24 @@ +/* + * Copyright (C) 2016 Blue Jay Wireless + * Copyright (C) 2015 Daniel Martí + * Copyright (C) 2014-2016 Hans-Christoph Steiner + * Copyright (C) 2014-2016 Peter Serwylo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 3 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * 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. + */ package org.fdroid.fdroid; @@ -8,6 +29,7 @@ import android.util.Log; import org.fdroid.fdroid.data.Apk; import org.fdroid.fdroid.data.App; import org.fdroid.fdroid.data.Repo; +import org.fdroid.fdroid.data.RepoPushRequest; import org.fdroid.fdroid.mock.MockRepo; import org.junit.Test; import org.junit.runner.RunWith; @@ -82,6 +104,38 @@ public class RepoXMLHandlerTest { }); } + @Test + public void testPushRequestsRepoIgnore() { + Repo expectedRepo = new Repo(); + expectedRepo.name = "non-public test repo"; + expectedRepo.signingCertificate = "308204e1308202c9a0030201020204483450fa300d06092a864886f70d01010b050030213110300e060355040b1307462d44726f6964310d300b06035504031304736f7661301e170d3136303832333133333131365a170d3434303130393133333131365a30213110300e060355040b1307462d44726f6964310d300b06035504031304736f766130820222300d06092a864886f70d01010105000382020f003082020a0282020100dfdcd120f3ab224999dddf4ea33ea588d295e4d7130bef48c143e9d76e5c0e0e9e5d45e64208e35feebc79a83f08939dd6a343b7d1e2179930a105a1249ccd36d88ff3feffc6e4dc53dae0163a7876dd45ecc1ddb0adf5099aa56c1a84b52affcd45d0711ffa4de864f35ac0333ebe61ea8673eeda35a88f6af678cc4d0f80b089338ac8f2a8279a64195c611d19445cab3fd1a020afed9bd739bb95142fb2c00a8f847db5ef3325c814f8eb741bacf86ed3907bfe6e4564d2de5895df0c263824e0b75407589bae2d3a4666c13b92102d8781a8ee9bb4a5a1a78c4a9c21efdaf5584da42e84418b28f5a81d0456a3dc5b420991801e6b21e38c99bbe018a5b2d690894a114bc860d35601416aa4dc52216aff8a288d4775cddf8b72d45fd2f87303a8e9c0d67e442530be28eaf139894337266e0b33d57f949256ab32083bcc545bc18a83c9ab8247c12aea037e2b68dee31c734cb1f04f241d3b94caa3a2b258ffaf8e6eae9fbbe029a934dc0a0859c5f120334812693a1c09352340a39f2a678dbc1afa2a978bfee43afefcb7e224a58af2f3d647e5745db59061236b8af6fcfd93b3602f9e456978534f3a7851e800071bf56da80401c81d91c45f82568373af0576b1cc5eef9b85654124b6319770be3cdba3fbebe3715e8918fb6c8966624f3d0e815effac3d2ee06dd34ab9c693218b2c7c06ba99d6b74d4f17b8c3cb0203010001a321301f301d0603551d0e04160414d62bee9f3798509546acc62eb1de14b08b954d4f300d06092a864886f70d01010b05000382020100743f7c5692085895f9d1fffad390fb4202c15f123ed094df259185960fd6dadf66cb19851070f180297bba4e6996a4434616573b375cfee94fee73a4505a7ec29136b7e6c22e6436290e3686fe4379d4e3140ec6a08e70cfd3ed5b634a5eb5136efaaabf5f38e0432d3d79568a556970b8cfba2972f5d23a3856d8a981b9e9bbbbb88f35e708bde9cbc5f681cbd974085b9da28911296fe2579fa64bbe9fa0b93475a7a8db051080b0c5fade0d1c018e7858cd4cbe95145b0620e2f632cbe0f8af9cbf22e2fdaa72245ae31b0877b07181cc69dd2df74454251d8de58d25e76354abe7eb690f22e59b08795a8f2c98c578e0599503d9085927634072c82c9f82abd50fd12b8fd1a9d1954eb5cc0b4cfb5796b5aaec0356643b4a65a368442d92ef94edd3ac6a2b7fe3571b8cf9f462729228aab023ef9183f73792f5379633ccac51079177d604c6bc1873ada6f07d8da6d68c897e88a5fa5d63fdb8df820f46090e0716e7562dd3c140ba279a65b996f60addb0abe29d4bf2f5abe89480771d492307b926d91f02f341b2148502903c43d40f3c6c86a811d060711f0698b384acdcc0add44eb54e42962d3d041accc715afd49407715adc09350cb55e8d9281a3b0b6b5fcd91726eede9b7c8b13afdebb2c2b377629595f1096ba62fb14946dbac5f3c5f0b4e5b712e7acc7dcf6c46cdc5e6d6dfdeee55a0c92c2d70f080ac6"; + expectedRepo.description = "This is a repository of apps to be used with F-Droid. Applications in this repository are either official binaries built by the original application developers, or are binaries built from source by the admin of f-droid.org using the tools on https://gitlab.com/u/fdroid."; + expectedRepo.timestamp = 1472071347; + RepoDetails actualDetails = getFromFile("pushRequestsIndex.xml", Repo.PUSH_REQUEST_IGNORE); + handlerTestSuite(expectedRepo, actualDetails, 2, 14, -1, 17); + checkPushRequests(actualDetails); + + List repoPushRequests = actualDetails.repoPushRequestList; + assertNotNull(repoPushRequests); + assertEquals(0, repoPushRequests.size()); + } + + @Test + public void testPushRequestsRepoAlways() { + Repo expectedRepo = new Repo(); + expectedRepo.name = "non-public test repo"; + expectedRepo.signingCertificate = "308204e1308202c9a0030201020204483450fa300d06092a864886f70d01010b050030213110300e060355040b1307462d44726f6964310d300b06035504031304736f7661301e170d3136303832333133333131365a170d3434303130393133333131365a30213110300e060355040b1307462d44726f6964310d300b06035504031304736f766130820222300d06092a864886f70d01010105000382020f003082020a0282020100dfdcd120f3ab224999dddf4ea33ea588d295e4d7130bef48c143e9d76e5c0e0e9e5d45e64208e35feebc79a83f08939dd6a343b7d1e2179930a105a1249ccd36d88ff3feffc6e4dc53dae0163a7876dd45ecc1ddb0adf5099aa56c1a84b52affcd45d0711ffa4de864f35ac0333ebe61ea8673eeda35a88f6af678cc4d0f80b089338ac8f2a8279a64195c611d19445cab3fd1a020afed9bd739bb95142fb2c00a8f847db5ef3325c814f8eb741bacf86ed3907bfe6e4564d2de5895df0c263824e0b75407589bae2d3a4666c13b92102d8781a8ee9bb4a5a1a78c4a9c21efdaf5584da42e84418b28f5a81d0456a3dc5b420991801e6b21e38c99bbe018a5b2d690894a114bc860d35601416aa4dc52216aff8a288d4775cddf8b72d45fd2f87303a8e9c0d67e442530be28eaf139894337266e0b33d57f949256ab32083bcc545bc18a83c9ab8247c12aea037e2b68dee31c734cb1f04f241d3b94caa3a2b258ffaf8e6eae9fbbe029a934dc0a0859c5f120334812693a1c09352340a39f2a678dbc1afa2a978bfee43afefcb7e224a58af2f3d647e5745db59061236b8af6fcfd93b3602f9e456978534f3a7851e800071bf56da80401c81d91c45f82568373af0576b1cc5eef9b85654124b6319770be3cdba3fbebe3715e8918fb6c8966624f3d0e815effac3d2ee06dd34ab9c693218b2c7c06ba99d6b74d4f17b8c3cb0203010001a321301f301d0603551d0e04160414d62bee9f3798509546acc62eb1de14b08b954d4f300d06092a864886f70d01010b05000382020100743f7c5692085895f9d1fffad390fb4202c15f123ed094df259185960fd6dadf66cb19851070f180297bba4e6996a4434616573b375cfee94fee73a4505a7ec29136b7e6c22e6436290e3686fe4379d4e3140ec6a08e70cfd3ed5b634a5eb5136efaaabf5f38e0432d3d79568a556970b8cfba2972f5d23a3856d8a981b9e9bbbbb88f35e708bde9cbc5f681cbd974085b9da28911296fe2579fa64bbe9fa0b93475a7a8db051080b0c5fade0d1c018e7858cd4cbe95145b0620e2f632cbe0f8af9cbf22e2fdaa72245ae31b0877b07181cc69dd2df74454251d8de58d25e76354abe7eb690f22e59b08795a8f2c98c578e0599503d9085927634072c82c9f82abd50fd12b8fd1a9d1954eb5cc0b4cfb5796b5aaec0356643b4a65a368442d92ef94edd3ac6a2b7fe3571b8cf9f462729228aab023ef9183f73792f5379633ccac51079177d604c6bc1873ada6f07d8da6d68c897e88a5fa5d63fdb8df820f46090e0716e7562dd3c140ba279a65b996f60addb0abe29d4bf2f5abe89480771d492307b926d91f02f341b2148502903c43d40f3c6c86a811d060711f0698b384acdcc0add44eb54e42962d3d041accc715afd49407715adc09350cb55e8d9281a3b0b6b5fcd91726eede9b7c8b13afdebb2c2b377629595f1096ba62fb14946dbac5f3c5f0b4e5b712e7acc7dcf6c46cdc5e6d6dfdeee55a0c92c2d70f080ac6"; + expectedRepo.description = "This is a repository of apps to be used with F-Droid. Applications in this repository are either official binaries built by the original application developers, or are binaries built from source by the admin of f-droid.org using the tools on https://gitlab.com/u/fdroid."; + expectedRepo.timestamp = 1472071347; + RepoDetails actualDetails = getFromFile("pushRequestsIndex.xml", Repo.PUSH_REQUEST_ACCEPT_ALWAYS); + handlerTestSuite(expectedRepo, actualDetails, 2, 14, -1, 17); + checkPushRequests(actualDetails); + + List repoPushRequests = actualDetails.repoPushRequestList; + assertNotNull(repoPushRequests); + assertEquals(6, repoPushRequests.size()); + } + @Test public void testMediumRepo() { Repo expectedRepo = new Repo(); @@ -697,6 +751,30 @@ public class RepoXMLHandlerTest { } } + private void checkPushRequests(RepoDetails actualDetails) { + final Object[] expectedPushRequestsIndex = new Object[]{ + "install", "org.fdroid.fdroid", 101002, + "install", "org.fdroid.fdroid.privileged", null, + "uninstall", "com.android.vending", null, + "uninstall", "com.facebook.orca", -12345, + "uninstall", null, null, // request with no data + "install", "asdfasdfasdf", null, // non-existent app + }; + + checkIncludedApps(actualDetails.apps, new String[]{ + "org.fdroid.fdroid", "org.fdroid.fdroid.privileged", + }); + + List repoPushRequestList = actualDetails.repoPushRequestList; + int i = 0; + for (RepoPushRequest repoPushRequest : repoPushRequestList) { + assertEquals(repoPushRequest.request, expectedPushRequestsIndex[i]); + assertEquals(repoPushRequest.packageName, expectedPushRequestsIndex[i + 1]); + assertEquals(repoPushRequest.versionCode, expectedPushRequestsIndex[i + 2]); + i += 3; + } + } + private void handlerTestSuite(Repo expectedRepo, RepoDetails actualDetails, int appCount, int apkCount, int maxAge, int version) { assertNotNull(actualDetails); assertFalse(TextUtils.isEmpty(actualDetails.signingCert)); @@ -736,6 +814,7 @@ public class RepoXMLHandlerTest { public List apks = new ArrayList<>(); public List apps = new ArrayList<>(); + public List repoPushRequestList = new ArrayList<>(); @Override public void receiveRepo(String name, String description, String signingCert, int maxage, int version, long timestamp) { @@ -753,17 +832,27 @@ public class RepoXMLHandlerTest { apps.add(app); } + @Override + public void receiveRepoPushRequest(RepoPushRequest repoPushRequest) { + repoPushRequestList.add(repoPushRequest); + } } @NonNull private RepoDetails getFromFile(String indexFilename) { + return getFromFile(indexFilename, Repo.PUSH_REQUEST_IGNORE); + } + + @NonNull + private RepoDetails getFromFile(String indexFilename, int pushRequests) { try { SAXParserFactory factory = SAXParserFactory.newInstance(); factory.setNamespaceAware(true); SAXParser parser = factory.newSAXParser(); XMLReader reader = parser.getXMLReader(); RepoDetails repoDetails = new RepoDetails(); - RepoXMLHandler handler = new RepoXMLHandler(new MockRepo(100), repoDetails); + MockRepo mockRepo = new MockRepo(100, pushRequests); + RepoXMLHandler handler = new RepoXMLHandler(mockRepo, repoDetails); reader.setContentHandler(handler); Log.i(TAG, "test file: " + getClass().getClassLoader().getResource(indexFilename)); InputStream input = getClass().getClassLoader().getResourceAsStream(indexFilename); diff --git a/app/src/test/java/org/fdroid/fdroid/data/RepoProviderTest.java b/app/src/test/java/org/fdroid/fdroid/data/RepoProviderTest.java index db1cea291..c9553c83c 100644 --- a/app/src/test/java/org/fdroid/fdroid/data/RepoProviderTest.java +++ b/app/src/test/java/org/fdroid/fdroid/data/RepoProviderTest.java @@ -1,3 +1,24 @@ +/* + * Copyright (C) 2016 Blue Jay Wireless + * Copyright (C) 2014-2016 Hans-Christoph Steiner + * Copyright (C) 2014-2016 Peter Serwylo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 3 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * 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. + */ + package org.fdroid.fdroid.data; import android.app.Application; @@ -74,48 +95,29 @@ public class RepoProviderTest extends FDroidProviderTest { } /** - * The {@link DBHelper} class populates four default repos when it first creates a database: - * * F-Droid - * * F-Droid (Archive) - * * Guardian Project - * * Guardian Project (Archive) + * The {@link DBHelper} class populates the default repos when it first creates a database. * The names/URLs/signing certificates for these repos are all hard coded in the source/res. */ @Test public void defaultRepos() { List defaultRepos = RepoProvider.Helper.all(context); - assertEquals(defaultRepos.size(), 4); - assertRepo( - defaultRepos.get(0), - context.getString(R.string.fdroid_repo_address), - context.getString(R.string.fdroid_repo_description), - Utils.calcFingerprint(context.getString(R.string.fdroid_repo_pubkey)), - context.getString(R.string.fdroid_repo_name) - ); + assertEquals(defaultRepos.size(), 4); // based on app/src/main/res/default_repo.xml - assertRepo( - defaultRepos.get(1), - context.getString(R.string.fdroid_archive_address), - context.getString(R.string.fdroid_archive_description), - Utils.calcFingerprint(context.getString(R.string.fdroid_archive_pubkey)), - context.getString(R.string.fdroid_archive_name) - ); - - assertRepo( - defaultRepos.get(2), - context.getString(R.string.guardianproject_repo_address), - context.getString(R.string.guardianproject_repo_description), - Utils.calcFingerprint(context.getString(R.string.guardianproject_repo_pubkey)), - context.getString(R.string.guardianproject_repo_name) - ); - - assertRepo( - defaultRepos.get(3), - context.getString(R.string.guardianproject_archive_address), - context.getString(R.string.guardianproject_archive_description), - Utils.calcFingerprint(context.getString(R.string.guardianproject_archive_pubkey)), - context.getString(R.string.guardianproject_archive_name) - ); + String[] reposFromXml = context.getResources().getStringArray(R.array.default_repos); + if (reposFromXml.length % DBHelper.REPO_XML_ARG_COUNT != 0) { + throw new IllegalArgumentException( + "default_repo.xml array does not have the right number of elements"); + } + for (int i = 0; i < reposFromXml.length / DBHelper.REPO_XML_ARG_COUNT; i++) { + int offset = i * DBHelper.REPO_XML_ARG_COUNT; + assertRepo( + defaultRepos.get(i), + reposFromXml[offset + 1], // address + reposFromXml[offset + 2], // description + Utils.calcFingerprint(reposFromXml[offset + 7]), // pubkey + reposFromXml[offset] // name + ); + } } @Test diff --git a/app/src/test/java/org/fdroid/fdroid/mock/MockRepo.java b/app/src/test/java/org/fdroid/fdroid/mock/MockRepo.java index 3b3fce976..5926c7b88 100644 --- a/app/src/test/java/org/fdroid/fdroid/mock/MockRepo.java +++ b/app/src/test/java/org/fdroid/fdroid/mock/MockRepo.java @@ -4,8 +4,13 @@ import org.fdroid.fdroid.data.Repo; public class MockRepo extends Repo { - public MockRepo(long repoId) { - id = repoId; + public MockRepo(long id) { + this.id = id; + } + + public MockRepo(long id, int pushRequests) { + this.id = id; + this.pushRequests = pushRequests; } } diff --git a/app/src/test/resources/pushRequestsIndex.xml b/app/src/test/resources/pushRequestsIndex.xml new file mode 100644 index 000000000..7a9d88d0e --- /dev/null +++ b/app/src/test/resources/pushRequestsIndex.xml @@ -0,0 +1 @@ +This is a repository of apps to be used with F-Droid. Applications in this repository are either official binaries built by the original application developers, or are binaries built from source by the admin of f-droid.org using the tools on https://gitlab.com/u/fdroid. https://testy.at.or.at/fdroid/repohttp://frkcchxlcvnb4m5a.onion/fdroid/repoorg.fdroid.fdroid2011-01-172016-08-21F-DroidApplication managerorg.fdroid.fdroid.101005.png<p>Connects to F-Droid compatible repositories. The default repo is hosted at f-droid.org, which contains only bona fide FOSS.</p><p>Android is open in the sense that you are free to install apks from anywhere you wish, but there are many good reasons for using a client/repository setup:</p><ul><li> Be notified when updates are available</li><li> Keep track of older and beta versions</li><li> Filter apps that aren't compatible with the device</li><li> Find apps via categories and searchable descriptions</li><li> Access associated urls for donations, source code etc.</li><li> Stay safe by checking repo index signatures and apk hashes</li></ul>GPLv3+SystemSystemhttps://f-droid.orghttps://gitlab.com/fdroid/fdroidclienthttps://gitlab.com/fdroid/fdroidclient/issueshttps://gitlab.com/fdroid/fdroidclient/raw/HEAD/CHANGELOG.mdhttps://f-droid.org/about15u8aAPK4jJ5N8wpWJ5gutAyyeHtKX5i183430530.100.11001500.101-alpha5101005org.fdroid.fdroid_101005.apkorg.fdroid.fdroid_101005_src.tar.gz981b5f02c8dbaefc0426576250808d1f5f28bb0595055fa3812bb716d09aefb59063aaadfff9cfd811a9c72fb5012f28467215410242016-08-21RECEIVE_BOOT_COMPLETED,BLUETOOTH_ADMIN,ACCESS_NETWORK_STATE,WRITE_SETTINGS,ACCESS_WIFI_STATE,WRITE_EXTERNAL_STORAGE,READ_EXTERNAL_STORAGE,BLUETOOTH,org.fdroid.fdroid.privileged.USE_SERVICE,CHANGE_NETWORK_STATE,INTERNET,ACCESS_SUPERUSER,CHANGE_WIFI_MULTICAST_STATE,CHANGE_WIFI_STATE,NFC0.101-alpha4101004org.fdroid.fdroid_101004.apkorg.fdroid.fdroid_101004_src.tar.gzf8fafc7a1fc2520bd27149a14c61a8a8edcbca8819ce50d3ee4e1c65d9395f959063aaadfff9cfd811a9c72fb5012f28465939010242016-08-04RECEIVE_BOOT_COMPLETED,BLUETOOTH_ADMIN,ACCESS_NETWORK_STATE,WRITE_SETTINGS,ACCESS_WIFI_STATE,WRITE_EXTERNAL_STORAGE,READ_EXTERNAL_STORAGE,BLUETOOTH,org.fdroid.fdroid.privileged.USE_SERVICE,CHANGE_NETWORK_STATE,INTERNET,ACCESS_SUPERUSER,CHANGE_WIFI_MULTICAST_STATE,CHANGE_WIFI_STATE,NFC0.101-alpha3101003org.fdroid.fdroid_101003.apkorg.fdroid.fdroid_101003_src.tar.gz8b8617a2725be617ae12c3471fb067bba15026f08b3590e29d41ff20f8bb934a9063aaadfff9cfd811a9c72fb5012f28467328710232016-07-27RECEIVE_BOOT_COMPLETED,BLUETOOTH_ADMIN,ACCESS_NETWORK_STATE,WRITE_SETTINGS,ACCESS_WIFI_STATE,WRITE_EXTERNAL_STORAGE,READ_EXTERNAL_STORAGE,BLUETOOTH,org.fdroid.fdroid.privileged.USE_SERVICE,CHANGE_NETWORK_STATE,INTERNET,ACCESS_SUPERUSER,CHANGE_WIFI_MULTICAST_STATE,CHANGE_WIFI_STATE,NFC0.101-alpha2101002org.fdroid.fdroid_101002.apkorg.fdroid.fdroid_101002_src.tar.gz04487136c5d4c0b9ad5bb549b041ca7b9bac99490c03a5c2cfafc95efc20f59e9063aaadfff9cfd811a9c72fb5012f28465470610232016-07-07RECEIVE_BOOT_COMPLETED,BLUETOOTH_ADMIN,ACCESS_NETWORK_STATE,WRITE_SETTINGS,ACCESS_WIFI_STATE,WRITE_EXTERNAL_STORAGE,READ_EXTERNAL_STORAGE,BLUETOOTH,org.fdroid.fdroid.privileged.USE_SERVICE,CHANGE_NETWORK_STATE,INTERNET,ACCESS_SUPERUSER,CHANGE_WIFI_MULTICAST_STATE,CHANGE_WIFI_STATE,NFC0.101-alpha1101001org.fdroid.fdroid_101001.apkorg.fdroid.fdroid_101001_src.tar.gze34929048a664bc6cd7af8e8fce90edb8c4dcf648d1db0ccc4472e96ae30aa5b9063aaadfff9cfd811a9c72fb5012f28463282610232016-06-21RECEIVE_BOOT_COMPLETED,BLUETOOTH_ADMIN,ACCESS_NETWORK_STATE,WRITE_SETTINGS,ACCESS_WIFI_STATE,WRITE_EXTERNAL_STORAGE,READ_EXTERNAL_STORAGE,BLUETOOTH,org.fdroid.fdroid.privileged.USE_SERVICE,CHANGE_NETWORK_STATE,INTERNET,ACCESS_SUPERUSER,CHANGE_WIFI_MULTICAST_STATE,CHANGE_WIFI_STATE,NFC0.100.1100150org.fdroid.fdroid_100150.apkorg.fdroid.fdroid_100150_src.tar.gz105c6ebbc78c8919ed1d659e091156db12a9fb07a2e8a39c2e22ddb00b96f7809063aaadfff9cfd811a9c72fb5012f2845770978232016-06-22RECEIVE_BOOT_COMPLETED,BLUETOOTH_ADMIN,ACCESS_NETWORK_STATE,WRITE_SETTINGS,ACCESS_WIFI_STATE,WRITE_EXTERNAL_STORAGE,READ_EXTERNAL_STORAGE,BLUETOOTH,org.fdroid.fdroid.privileged.USE_SERVICE,CHANGE_NETWORK_STATE,INTERNET,ACCESS_SUPERUSER,CHANGE_WIFI_MULTICAST_STATE,CHANGE_WIFI_STATE,NFC0.100100050org.fdroid.fdroid_100050.apkorg.fdroid.fdroid_100050_src.tar.gz9870531d4ae60201eb045ed7b8dcba2999406b07477881ac1a2de5e731b773fe9063aaadfff9cfd811a9c72fb5012f2845772108232016-06-08RECEIVE_BOOT_COMPLETED,BLUETOOTH_ADMIN,ACCESS_NETWORK_STATE,WRITE_SETTINGS,ACCESS_WIFI_STATE,WRITE_EXTERNAL_STORAGE,READ_EXTERNAL_STORAGE,BLUETOOTH,org.fdroid.fdroid.privileged.USE_SERVICE,CHANGE_NETWORK_STATE,INTERNET,ACCESS_SUPERUSER,CHANGE_WIFI_MULTICAST_STATE,CHANGE_WIFI_STATE,NFC0.100-alpha8100008org.fdroid.fdroid_100008.apkorg.fdroid.fdroid_100008_src.tar.gzfe733f9f592f294a230d1465b86285ff22c868c27399bfd6718eead5f7f66aac9063aaadfff9cfd811a9c72fb5012f2845770098232016-05-24RECEIVE_BOOT_COMPLETED,BLUETOOTH_ADMIN,ACCESS_NETWORK_STATE,WRITE_SETTINGS,ACCESS_WIFI_STATE,WRITE_EXTERNAL_STORAGE,READ_EXTERNAL_STORAGE,BLUETOOTH,org.fdroid.fdroid.privileged.USE_SERVICE,CHANGE_NETWORK_STATE,INTERNET,ACCESS_SUPERUSER,CHANGE_WIFI_MULTICAST_STATE,CHANGE_WIFI_STATE,NFC0.100-alpha7100007org.fdroid.fdroid_100007.apkorg.fdroid.fdroid_100007_src.tar.gze741c3c5413ed63ae6fb3616fd199f394c93ca3188a26a233d9034ca2b8074979063aaadfff9cfd811a9c72fb5012f2845712608232016-05-13RECEIVE_BOOT_COMPLETED,BLUETOOTH_ADMIN,ACCESS_NETWORK_STATE,WRITE_SETTINGS,ACCESS_WIFI_STATE,WRITE_EXTERNAL_STORAGE,READ_EXTERNAL_STORAGE,BLUETOOTH,org.fdroid.fdroid.privileged.USE_SERVICE,CHANGE_NETWORK_STATE,INTERNET,ACCESS_SUPERUSER,CHANGE_WIFI_MULTICAST_STATE,CHANGE_WIFI_STATE,NFC0.100-alpha6100006org.fdroid.fdroid_100006.apkorg.fdroid.fdroid_100006_src.tar.gz70dfb60b5b16debbcdecddddae4c7a013843a8cf269979fd1e5effa3132f9fe49063aaadfff9cfd811a9c72fb5012f2845700038232016-05-03RECEIVE_BOOT_COMPLETED,BLUETOOTH_ADMIN,ACCESS_NETWORK_STATE,ACCESS_WIFI_STATE,WRITE_EXTERNAL_STORAGE,READ_EXTERNAL_STORAGE,BLUETOOTH,org.fdroid.fdroid.privileged.USE_SERVICE,CHANGE_NETWORK_STATE,ACCESS_SUPERUSER,INTERNET,CHANGE_WIFI_MULTICAST_STATE,CHANGE_WIFI_STATE,NFC0.100-alpha5100005org.fdroid.fdroid_100005.apkorg.fdroid.fdroid_100005_src.tar.gzd5fc82ab6050a9649a8fe995eb53a168dd8987df409857626778671286c9d2f79063aaadfff9cfd811a9c72fb5012f2845475208232016-04-23RECEIVE_BOOT_COMPLETED,BLUETOOTH_ADMIN,ACCESS_NETWORK_STATE,ACCESS_WIFI_STATE,WRITE_EXTERNAL_STORAGE,READ_EXTERNAL_STORAGE,BLUETOOTH,org.fdroid.fdroid.privileged.USE_SERVICE,CHANGE_NETWORK_STATE,ACCESS_SUPERUSER,INTERNET,CHANGE_WIFI_MULTICAST_STATE,CHANGE_WIFI_STATE,NFC0.100-alpha4100004org.fdroid.fdroid_100004.apkorg.fdroid.fdroid_100004_src.tar.gz417e0cb16e7e7d95e6bf2d797d87b0ecce9711e693e1a93c678805e35363b7c79063aaadfff9cfd811a9c72fb5012f2845368778232016-04-17RECEIVE_BOOT_COMPLETED,BLUETOOTH_ADMIN,ACCESS_NETWORK_STATE,ACCESS_WIFI_STATE,WRITE_EXTERNAL_STORAGE,READ_EXTERNAL_STORAGE,BLUETOOTH,org.fdroid.fdroid.privileged.USE_SERVICE,CHANGE_NETWORK_STATE,ACCESS_SUPERUSER,INTERNET,CHANGE_WIFI_MULTICAST_STATE,CHANGE_WIFI_STATE,NFCorg.fdroid.fdroid.privileged2015-09-102016-01-20F-Droid Privileged ExtensionHelp F-Droid acquire system privilegesorg.fdroid.fdroid.privileged.1050.png<p><b>Note:</b> F-Droid will need root privileges to install this app as a system app.</p><p><a href="fdroid.app:org.fdroid.fdroid">F-Droid</a> can make use of system privileges or permissions to install, update and remove applications on its own. The only way to obtain those privileges is to become a system app.</p><p>This is where the Privileged Extension comes in - being a separate app and much smaller, it can be installed as a system app and communicate with the main app via AIDL IPC.</p><p>This has several advantages:</p><ul><li> Reduced disk usage in the system partition</li><li> System updates don't remove F-Droid</li><li> The process of installing into system via root is safer</li></ul>GPLv3+SystemSystemhttps://f-droid.orghttps://gitlab.com/fdroid/fdroidclienthttps://gitlab.com/fdroid/fdroidclient/issueshttps://f-droid.org/about15u8aAPK4jJ5N8wpWJ5gutAyyeHtKX5i183430530.110500.11050org.fdroid.fdroid.privileged_1050.apkorg.fdroid.fdroid.privileged_1050_src.tar.gza0b19494f1a065d477807a49693456c2a305f947cfdb4f54ecfb3c4ce1511c1a9063aaadfff9cfd811a9c72fb5012f28336638222016-01-20INSTALL_PACKAGES,DELETE_PACKAGES0.1-alpha01000org.fdroid.fdroid.privileged_1000.apkorg.fdroid.fdroid.privileged_1000_src.tar.gz4d2251bbf1468ca69cead98b190ceab1f74bd2901e18ed22b237797098ce36e69063aaadfff9cfd811a9c72fb5012f28456058222015-09-10INSTALL_PACKAGES,DELETE_PACKAGES