From 28198dddb478b8ee41d0aa2510a14ff1bc095d45 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 24 Aug 2016 14:44:00 +0200 Subject: [PATCH 1/4] rename default_repo.xml to default_repos.xml, there are many Just to make it clear that there can be and are multiple repos configured in the file. --- app/src/main/res/values/{default_repo.xml => default_repos.xml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename app/src/main/res/values/{default_repo.xml => default_repos.xml} (100%) diff --git a/app/src/main/res/values/default_repo.xml b/app/src/main/res/values/default_repos.xml similarity index 100% rename from app/src/main/res/values/default_repo.xml rename to app/src/main/res/values/default_repos.xml From d34a1285e8810b2d66dd17bfa45089d7eb54eb60 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 24 Aug 2016 14:53:06 +0200 Subject: [PATCH 2/4] convert default_repo.xml to more flexible format This is a step towards supporting easy whitelabeling, using gradle flavors. This allows the whitelabel version to set the default repos just by making their own default_repos.xml in app/src/whitelabel/res/values. That one will then override the built-in F-Droid one. --- .../java/org/fdroid/fdroid/data/DBHelper.java | 89 +++++--------- app/src/main/res/values/default_repos.xml | 114 ++++++++++++------ .../fdroid/fdroid/data/RepoProviderTest.java | 53 +++----- 3 files changed, 125 insertions(+), 131 deletions(-) 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..680772bd8 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/DBHelper.java +++ b/app/src/main/java/org/fdroid/fdroid/data/DBHelper.java @@ -229,55 +229,29 @@ 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] // 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 pubKey) { ContentValues values = new ContentValues(); values.put(RepoTable.Cols.ADDRESS, address); values.put(RepoTable.Cols.NAME, name); @@ -285,9 +259,9 @@ 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); @@ -542,15 +516,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 + ); + } } /** diff --git a/app/src/main/res/values/default_repos.xml b/app/src/main/res/values/default_repos.xml index 342561b6a..640364aa5 100644 --- a/app/src/main/res/values/default_repos.xml +++ b/app/src/main/res/values/default_repos.xml @@ -1,48 +1,86 @@ - - F-Droid + - 13 - 1 - 10 + + 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 + + + 3082035e30820246a00302010202044c49cd00300d06092a864886f70d01010505003071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b73301e170d3130303732333137313032345a170d3337313230383137313032345a3071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b7330820122300d06092a864886f70d01010105000382010f003082010a028201010096d075e47c014e7822c89fd67f795d23203e2a8843f53ba4e6b1bf5f2fd0e225938267cfcae7fbf4fe596346afbaf4070fdb91f66fbcdf2348a3d92430502824f80517b156fab00809bdc8e631bfa9afd42d9045ab5fd6d28d9e140afc1300917b19b7c6c4df4a494cf1f7cb4a63c80d734265d735af9e4f09455f427aa65a53563f87b336ca2c19d244fcbba617ba0b19e56ed34afe0b253ab91e2fdb1271f1b9e3c3232027ed8862a112f0706e234cf236914b939bcf959821ecb2a6c18057e070de3428046d94b175e1d89bd795e535499a091f5bc65a79d539a8d43891ec504058acb28c08393b5718b57600a211e803f4a634e5c57f25b9b8c4422c6fd90203010001300d06092a864886f70d0101050500038201010008e4ef699e9807677ff56753da73efb2390d5ae2c17e4db691d5df7a7b60fc071ae509c5414be7d5da74df2811e83d3668c4a0b1abc84b9fa7d96b4cdf30bba68517ad2a93e233b042972ac0553a4801c9ebe07bf57ebe9a3b3d6d663965260e50f3b8f46db0531761e60340a2bddc3426098397fda54044a17e5244549f9869b460ca5e6e216b6f6a2db0580b480ca2afe6ec6b46eedacfa4aa45038809ece0c5978653d6c85f678e7f5a2156d1bedd8117751e64a4b0dcd140f3040b021821a8d93aed8d01ba36db6c82372211fed714d9a32607038cdfd565bd529ffc637212aaa2c224ef22b603eccefb5bf1e085c191d4b24fe742b17ab3f55d4e6f05ef + - 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 + + 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 + + + 3082035e30820246a00302010202044c49cd00300d06092a864886f70d01010505003071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b73301e170d3130303732333137313032345a170d3337313230383137313032345a3071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b7330820122300d06092a864886f70d01010105000382010f003082010a028201010096d075e47c014e7822c89fd67f795d23203e2a8843f53ba4e6b1bf5f2fd0e225938267cfcae7fbf4fe596346afbaf4070fdb91f66fbcdf2348a3d92430502824f80517b156fab00809bdc8e631bfa9afd42d9045ab5fd6d28d9e140afc1300917b19b7c6c4df4a494cf1f7cb4a63c80d734265d735af9e4f09455f427aa65a53563f87b336ca2c19d244fcbba617ba0b19e56ed34afe0b253ab91e2fdb1271f1b9e3c3232027ed8862a112f0706e234cf236914b939bcf959821ecb2a6c18057e070de3428046d94b175e1d89bd795e535499a091f5bc65a79d539a8d43891ec504058acb28c08393b5718b57600a211e803f4a634e5c57f25b9b8c4422c6fd90203010001300d06092a864886f70d0101050500038201010008e4ef699e9807677ff56753da73efb2390d5ae2c17e4db691d5df7a7b60fc071ae509c5414be7d5da74df2811e83d3668c4a0b1abc84b9fa7d96b4cdf30bba68517ad2a93e233b042972ac0553a4801c9ebe07bf57ebe9a3b3d6d663965260e50f3b8f46db0531761e60340a2bddc3426098397fda54044a17e5244549f9869b460ca5e6e216b6f6a2db0580b480ca2afe6ec6b46eedacfa4aa45038809ece0c5978653d6c85f678e7f5a2156d1bedd8117751e64a4b0dcd140f3040b021821a8d93aed8d01ba36db6c82372211fed714d9a32607038cdfd565bd529ffc637212aaa2c224ef22b603eccefb5bf1e085c191d4b24fe742b17ab3f55d4e6f05ef + - - F-Droid Archive + + 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 + + + 308205d8308203c0020900a397b4da7ecda034300d06092a864886f70d01010505003081ad310b30090603550406130255533111300f06035504080c084e657720596f726b3111300f06035504070c084e657720596f726b31143012060355040b0c0b4644726f6964205265706f31193017060355040a0c10477561726469616e2050726f6a656374311d301b06035504030c14677561726469616e70726f6a6563742e696e666f3128302606092a864886f70d0109011619726f6f7440677561726469616e70726f6a6563742e696e666f301e170d3134303632363139333931385a170d3431313131303139333931385a3081ad310b30090603550406130255533111300f06035504080c084e657720596f726b3111300f06035504070c084e657720596f726b31143012060355040b0c0b4644726f6964205265706f31193017060355040a0c10477561726469616e2050726f6a656374311d301b06035504030c14677561726469616e70726f6a6563742e696e666f3128302606092a864886f70d0109011619726f6f7440677561726469616e70726f6a6563742e696e666f30820222300d06092a864886f70d01010105000382020f003082020a0282020100b3cd79121b9b883843be3c4482e320809106b0a23755f1dd3c7f46f7d315d7bb2e943486d61fc7c811b9294dcc6b5baac4340f8db2b0d5e14749e7f35e1fc211fdbc1071b38b4753db201c314811bef885bd8921ad86facd6cc3b8f74d30a0b6e2e6e576f906e9581ef23d9c03e926e06d1f033f28bd1e21cfa6a0e3ff5c9d8246cf108d82b488b9fdd55d7de7ebb6a7f64b19e0d6b2ab1380a6f9d42361770d1956701a7f80e2de568acd0bb4527324b1e0973e89595d91c8cc102d9248525ae092e2c9b69f7414f724195b81427f28b1d3d09a51acfe354387915fd9521e8c890c125fc41a12bf34d2a1b304067ab7251e0e9ef41833ce109e76963b0b256395b16b886bca21b831f1408f836146019e7908829e716e72b81006610a2af08301de5d067c9e114a1e5759db8a6be6a3cc2806bcfe6fafd41b5bc9ddddb3dc33d6f605b1ca7d8a9e0ecdd6390d38906649e68a90a717bea80fa220170eea0c86fc78a7e10dac7b74b8e62045a3ecca54e035281fdc9fe5920a855fde3c0be522e3aef0c087524f13d973dff3768158b01a5800a060c06b451ec98d627dd052eda804d0556f60dbc490d94e6e9dea62ffcafb5beffbd9fc38fb2f0d7050004fe56b4dda0a27bc47554e1e0a7d764e17622e71f83a475db286bc7862deee1327e2028955d978272ea76bf0b88e70a18621aba59ff0c5993ef5f0e5d6b6b98e68b70203010001300d06092a864886f70d0101050500038202010079c79c8ef408a20d243d8bd8249fb9a48350dc19663b5e0fce67a8dbcb7de296c5ae7bbf72e98a2020fb78f2db29b54b0e24b181aa1c1d333cc0303685d6120b03216a913f96b96eb838f9bff125306ae3120af838c9fc07ebb5100125436bd24ec6d994d0bff5d065221871f8410daf536766757239bf594e61c5432c9817281b985263bada8381292e543a49814061ae11c92a316e7dc100327b59e3da90302c5ada68c6a50201bda1fcce800b53f381059665dbabeeb0b50eb22b2d7d2d9b0aa7488ca70e67ac6c518adb8e78454a466501e89d81a45bf1ebc350896f2c3ae4b6679ecfbf9d32960d4f5b493125c7876ef36158562371193f600bc511000a67bdb7c664d018f99d9e589868d103d7e0994f166b2ba18ff7e67d8c4da749e44dfae1d930ae5397083a51675c409049dfb626a96246c0015ca696e94ebb767a20147834bf78b07fece3f0872b057c1c519ff882501995237d8206b0b3832f78753ebd8dcbd1d3d9f5ba733538113af6b407d960ec4353c50eb38ab29888238da843cd404ed8f4952f59e4bbc0035fc77a54846a9d419179c46af1b4a3b7fc98e4d312aaa29b9b7d79e739703dc0fa41c7280d5587709277ffa11c3620f5fba985b82c238ba19b17ebd027af9424be0941719919f620dd3bb3c3f11638363708aa11f858e153cf3a69bce69978b90e4a273836100aa1e617ba455cd00426847f + - 13 - 0 - 20 + + 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 + + + 308205d8308203c0020900a397b4da7ecda034300d06092a864886f70d01010505003081ad310b30090603550406130255533111300f06035504080c084e657720596f726b3111300f06035504070c084e657720596f726b31143012060355040b0c0b4644726f6964205265706f31193017060355040a0c10477561726469616e2050726f6a656374311d301b06035504030c14677561726469616e70726f6a6563742e696e666f3128302606092a864886f70d0109011619726f6f7440677561726469616e70726f6a6563742e696e666f301e170d3134303632363139333931385a170d3431313131303139333931385a3081ad310b30090603550406130255533111300f06035504080c084e657720596f726b3111300f06035504070c084e657720596f726b31143012060355040b0c0b4644726f6964205265706f31193017060355040a0c10477561726469616e2050726f6a656374311d301b06035504030c14677561726469616e70726f6a6563742e696e666f3128302606092a864886f70d0109011619726f6f7440677561726469616e70726f6a6563742e696e666f30820222300d06092a864886f70d01010105000382020f003082020a0282020100b3cd79121b9b883843be3c4482e320809106b0a23755f1dd3c7f46f7d315d7bb2e943486d61fc7c811b9294dcc6b5baac4340f8db2b0d5e14749e7f35e1fc211fdbc1071b38b4753db201c314811bef885bd8921ad86facd6cc3b8f74d30a0b6e2e6e576f906e9581ef23d9c03e926e06d1f033f28bd1e21cfa6a0e3ff5c9d8246cf108d82b488b9fdd55d7de7ebb6a7f64b19e0d6b2ab1380a6f9d42361770d1956701a7f80e2de568acd0bb4527324b1e0973e89595d91c8cc102d9248525ae092e2c9b69f7414f724195b81427f28b1d3d09a51acfe354387915fd9521e8c890c125fc41a12bf34d2a1b304067ab7251e0e9ef41833ce109e76963b0b256395b16b886bca21b831f1408f836146019e7908829e716e72b81006610a2af08301de5d067c9e114a1e5759db8a6be6a3cc2806bcfe6fafd41b5bc9ddddb3dc33d6f605b1ca7d8a9e0ecdd6390d38906649e68a90a717bea80fa220170eea0c86fc78a7e10dac7b74b8e62045a3ecca54e035281fdc9fe5920a855fde3c0be522e3aef0c087524f13d973dff3768158b01a5800a060c06b451ec98d627dd052eda804d0556f60dbc490d94e6e9dea62ffcafb5beffbd9fc38fb2f0d7050004fe56b4dda0a27bc47554e1e0a7d764e17622e71f83a475db286bc7862deee1327e2028955d978272ea76bf0b88e70a18621aba59ff0c5993ef5f0e5d6b6b98e68b70203010001300d06092a864886f70d0101050500038202010079c79c8ef408a20d243d8bd8249fb9a48350dc19663b5e0fce67a8dbcb7de296c5ae7bbf72e98a2020fb78f2db29b54b0e24b181aa1c1d333cc0303685d6120b03216a913f96b96eb838f9bff125306ae3120af838c9fc07ebb5100125436bd24ec6d994d0bff5d065221871f8410daf536766757239bf594e61c5432c9817281b985263bada8381292e543a49814061ae11c92a316e7dc100327b59e3da90302c5ada68c6a50201bda1fcce800b53f381059665dbabeeb0b50eb22b2d7d2d9b0aa7488ca70e67ac6c518adb8e78454a466501e89d81a45bf1ebc350896f2c3ae4b6679ecfbf9d32960d4f5b493125c7876ef36158562371193f600bc511000a67bdb7c664d018f99d9e589868d103d7e0994f166b2ba18ff7e67d8c4da749e44dfae1d930ae5397083a51675c409049dfb626a96246c0015ca696e94ebb767a20147834bf78b07fece3f0872b057c1c519ff882501995237d8206b0b3832f78753ebd8dcbd1d3d9f5ba733538113af6b407d960ec4353c50eb38ab29888238da843cd404ed8f4952f59e4bbc0035fc77a54846a9d419179c46af1b4a3b7fc98e4d312aaa29b9b7d79e739703dc0fa41c7280d5587709277ffa11c3620f5fba985b82c238ba19b17ebd027af9424be0941719919f620dd3bb3c3f11638363708aa11f858e153cf3a69bce69978b90e4a273836100aa1e617ba455cd00426847f + - 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/test/java/org/fdroid/fdroid/data/RepoProviderTest.java b/app/src/test/java/org/fdroid/fdroid/data/RepoProviderTest.java index db1cea291..a7ea0b36b 100644 --- a/app/src/test/java/org/fdroid/fdroid/data/RepoProviderTest.java +++ b/app/src/test/java/org/fdroid/fdroid/data/RepoProviderTest.java @@ -74,48 +74,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 + 6]), // pubkey + reposFromXml[offset] // name + ); + } } @Test From 5c9dd1a11ecca9c8cfd57b020424d3a868a258b4 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 1 Sep 2016 22:14:36 +0200 Subject: [PATCH 3/4] basic support for repo push requests, configed in default_repos This allows whitelabel versions of apps to specify built-in app repos that have push requests accepted by default. This is useful for the case where there is a central manager of the core apps that are installed. https://gitlab.com/fdroid/fdroidserver/issues/177 --- .../java/org/fdroid/fdroid/RepoUpdater.java | 107 ++++++++++++++++-- .../org/fdroid/fdroid/RepoXMLHandler.java | 16 +++ .../java/org/fdroid/fdroid/data/DBHelper.java | 73 ++++++++++-- .../java/org/fdroid/fdroid/data/Repo.java | 37 ++++++ .../fdroid/fdroid/data/RepoPushRequest.java | 58 ++++++++++ .../java/org/fdroid/fdroid/data/Schema.java | 3 +- app/src/main/res/values/default_repos.xml | 8 ++ .../org/fdroid/fdroid/RepoXMLHandlerTest.java | 91 ++++++++++++++- .../fdroid/fdroid/data/RepoProviderTest.java | 23 +++- .../java/org/fdroid/fdroid/mock/MockRepo.java | 9 +- app/src/test/resources/pushRequestsIndex.xml | 1 + 11 files changed, 403 insertions(+), 23 deletions(-) create mode 100644 app/src/main/java/org/fdroid/fdroid/data/RepoPushRequest.java create mode 100644 app/src/test/resources/pushRequestsIndex.xml diff --git a/app/src/main/java/org/fdroid/fdroid/RepoUpdater.java b/app/src/main/java/org/fdroid/fdroid/RepoUpdater.java index 3d6e85fcf..7abd9d7a2 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,52 @@ 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); + 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 680772bd8..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; @@ -244,14 +270,15 @@ class DBHelper extends SQLiteOpenHelper { defaultRepos[offset + 3], // version defaultRepos[offset + 4], // enabled defaultRepos[offset + 5], // priority - defaultRepos[offset + 6] // pubkey + defaultRepos[offset + 6], // pushRequests + defaultRepos[offset + 7] // pubkey ); } } private void insertRepo(SQLiteDatabase db, String name, String address, String description, String version, String enabled, - String priority, String pubKey) { + String priority, String pushRequests, String pubKey) { ContentValues values = new ContentValues(); values.put(RepoTable.Cols.ADDRESS, address); values.put(RepoTable.Cols.NAME, name); @@ -265,7 +292,21 @@ class DBHelper extends SQLiteOpenHelper { 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); } @@ -302,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) { @@ -490,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, }); } @@ -770,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/res/values/default_repos.xml b/app/src/main/res/values/default_repos.xml index 640364aa5..6a09a6920 100644 --- a/app/src/main/res/values/default_repos.xml +++ b/app/src/main/res/values/default_repos.xml @@ -18,6 +18,8 @@ 1 10 + + ignore 3082035e30820246a00302010202044c49cd00300d06092a864886f70d01010505003071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b73301e170d3130303732333137313032345a170d3337313230383137313032345a3071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b7330820122300d06092a864886f70d01010105000382010f003082010a028201010096d075e47c014e7822c89fd67f795d23203e2a8843f53ba4e6b1bf5f2fd0e225938267cfcae7fbf4fe596346afbaf4070fdb91f66fbcdf2348a3d92430502824f80517b156fab00809bdc8e631bfa9afd42d9045ab5fd6d28d9e140afc1300917b19b7c6c4df4a494cf1f7cb4a63c80d734265d735af9e4f09455f427aa65a53563f87b336ca2c19d244fcbba617ba0b19e56ed34afe0b253ab91e2fdb1271f1b9e3c3232027ed8862a112f0706e234cf236914b939bcf959821ecb2a6c18057e070de3428046d94b175e1d89bd795e535499a091f5bc65a79d539a8d43891ec504058acb28c08393b5718b57600a211e803f4a634e5c57f25b9b8c4422c6fd90203010001300d06092a864886f70d0101050500038201010008e4ef699e9807677ff56753da73efb2390d5ae2c17e4db691d5df7a7b60fc071ae509c5414be7d5da74df2811e83d3668c4a0b1abc84b9fa7d96b4cdf30bba68517ad2a93e233b042972ac0553a4801c9ebe07bf57ebe9a3b3d6d663965260e50f3b8f46db0531761e60340a2bddc3426098397fda54044a17e5244549f9869b460ca5e6e216b6f6a2db0580b480ca2afe6ec6b46eedacfa4aa45038809ece0c5978653d6c85f678e7f5a2156d1bedd8117751e64a4b0dcd140f3040b021821a8d93aed8d01ba36db6c82372211fed714d9a32607038cdfd565bd529ffc637212aaa2c224ef22b603eccefb5bf1e085c191d4b24fe742b17ab3f55d4e6f05ef @@ -37,6 +39,8 @@ 0 20 + + ignore 3082035e30820246a00302010202044c49cd00300d06092a864886f70d01010505003071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b73301e170d3130303732333137313032345a170d3337313230383137313032345a3071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b7330820122300d06092a864886f70d01010105000382010f003082010a028201010096d075e47c014e7822c89fd67f795d23203e2a8843f53ba4e6b1bf5f2fd0e225938267cfcae7fbf4fe596346afbaf4070fdb91f66fbcdf2348a3d92430502824f80517b156fab00809bdc8e631bfa9afd42d9045ab5fd6d28d9e140afc1300917b19b7c6c4df4a494cf1f7cb4a63c80d734265d735af9e4f09455f427aa65a53563f87b336ca2c19d244fcbba617ba0b19e56ed34afe0b253ab91e2fdb1271f1b9e3c3232027ed8862a112f0706e234cf236914b939bcf959821ecb2a6c18057e070de3428046d94b175e1d89bd795e535499a091f5bc65a79d539a8d43891ec504058acb28c08393b5718b57600a211e803f4a634e5c57f25b9b8c4422c6fd90203010001300d06092a864886f70d0101050500038201010008e4ef699e9807677ff56753da73efb2390d5ae2c17e4db691d5df7a7b60fc071ae509c5414be7d5da74df2811e83d3668c4a0b1abc84b9fa7d96b4cdf30bba68517ad2a93e233b042972ac0553a4801c9ebe07bf57ebe9a3b3d6d663965260e50f3b8f46db0531761e60340a2bddc3426098397fda54044a17e5244549f9869b460ca5e6e216b6f6a2db0580b480ca2afe6ec6b46eedacfa4aa45038809ece0c5978653d6c85f678e7f5a2156d1bedd8117751e64a4b0dcd140f3040b021821a8d93aed8d01ba36db6c82372211fed714d9a32607038cdfd565bd529ffc637212aaa2c224ef22b603eccefb5bf1e085c191d4b24fe742b17ab3f55d4e6f05ef @@ -57,6 +61,8 @@ 0 10 + + ignore 308205d8308203c0020900a397b4da7ecda034300d06092a864886f70d01010505003081ad310b30090603550406130255533111300f06035504080c084e657720596f726b3111300f06035504070c084e657720596f726b31143012060355040b0c0b4644726f6964205265706f31193017060355040a0c10477561726469616e2050726f6a656374311d301b06035504030c14677561726469616e70726f6a6563742e696e666f3128302606092a864886f70d0109011619726f6f7440677561726469616e70726f6a6563742e696e666f301e170d3134303632363139333931385a170d3431313131303139333931385a3081ad310b30090603550406130255533111300f06035504080c084e657720596f726b3111300f06035504070c084e657720596f726b31143012060355040b0c0b4644726f6964205265706f31193017060355040a0c10477561726469616e2050726f6a656374311d301b06035504030c14677561726469616e70726f6a6563742e696e666f3128302606092a864886f70d0109011619726f6f7440677561726469616e70726f6a6563742e696e666f30820222300d06092a864886f70d01010105000382020f003082020a0282020100b3cd79121b9b883843be3c4482e320809106b0a23755f1dd3c7f46f7d315d7bb2e943486d61fc7c811b9294dcc6b5baac4340f8db2b0d5e14749e7f35e1fc211fdbc1071b38b4753db201c314811bef885bd8921ad86facd6cc3b8f74d30a0b6e2e6e576f906e9581ef23d9c03e926e06d1f033f28bd1e21cfa6a0e3ff5c9d8246cf108d82b488b9fdd55d7de7ebb6a7f64b19e0d6b2ab1380a6f9d42361770d1956701a7f80e2de568acd0bb4527324b1e0973e89595d91c8cc102d9248525ae092e2c9b69f7414f724195b81427f28b1d3d09a51acfe354387915fd9521e8c890c125fc41a12bf34d2a1b304067ab7251e0e9ef41833ce109e76963b0b256395b16b886bca21b831f1408f836146019e7908829e716e72b81006610a2af08301de5d067c9e114a1e5759db8a6be6a3cc2806bcfe6fafd41b5bc9ddddb3dc33d6f605b1ca7d8a9e0ecdd6390d38906649e68a90a717bea80fa220170eea0c86fc78a7e10dac7b74b8e62045a3ecca54e035281fdc9fe5920a855fde3c0be522e3aef0c087524f13d973dff3768158b01a5800a060c06b451ec98d627dd052eda804d0556f60dbc490d94e6e9dea62ffcafb5beffbd9fc38fb2f0d7050004fe56b4dda0a27bc47554e1e0a7d764e17622e71f83a475db286bc7862deee1327e2028955d978272ea76bf0b88e70a18621aba59ff0c5993ef5f0e5d6b6b98e68b70203010001300d06092a864886f70d0101050500038202010079c79c8ef408a20d243d8bd8249fb9a48350dc19663b5e0fce67a8dbcb7de296c5ae7bbf72e98a2020fb78f2db29b54b0e24b181aa1c1d333cc0303685d6120b03216a913f96b96eb838f9bff125306ae3120af838c9fc07ebb5100125436bd24ec6d994d0bff5d065221871f8410daf536766757239bf594e61c5432c9817281b985263bada8381292e543a49814061ae11c92a316e7dc100327b59e3da90302c5ada68c6a50201bda1fcce800b53f381059665dbabeeb0b50eb22b2d7d2d9b0aa7488ca70e67ac6c518adb8e78454a466501e89d81a45bf1ebc350896f2c3ae4b6679ecfbf9d32960d4f5b493125c7876ef36158562371193f600bc511000a67bdb7c664d018f99d9e589868d103d7e0994f166b2ba18ff7e67d8c4da749e44dfae1d930ae5397083a51675c409049dfb626a96246c0015ca696e94ebb767a20147834bf78b07fece3f0872b057c1c519ff882501995237d8206b0b3832f78753ebd8dcbd1d3d9f5ba733538113af6b407d960ec4353c50eb38ab29888238da843cd404ed8f4952f59e4bbc0035fc77a54846a9d419179c46af1b4a3b7fc98e4d312aaa29b9b7d79e739703dc0fa41c7280d5587709277ffa11c3620f5fba985b82c238ba19b17ebd027af9424be0941719919f620dd3bb3c3f11638363708aa11f858e153cf3a69bce69978b90e4a273836100aa1e617ba455cd00426847f @@ -76,6 +82,8 @@ 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 a7ea0b36b..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; @@ -93,7 +114,7 @@ public class RepoProviderTest extends FDroidProviderTest { defaultRepos.get(i), reposFromXml[offset + 1], // address reposFromXml[offset + 2], // description - Utils.calcFingerprint(reposFromXml[offset + 6]), // pubkey + Utils.calcFingerprint(reposFromXml[offset + 7]), // pubkey reposFromXml[offset] // name ); } 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 From b90cf7386cb69f824d2924039b7415761642400a Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 28 Sep 2016 21:59:54 +0200 Subject: [PATCH 4/4] prevent crashing if push requests include bad packageNames F-Droid shouldn't crash if a push request includes a bad package name. This just makes it silently ignore those push requests. If its a debug build, it will send a message to logcat. I'm not sure this is best way to handle this, but this is better than crashing the app. This will make it harder for repo operators to debug issues with push requests. --- app/src/main/java/org/fdroid/fdroid/RepoUpdater.java | 5 +++++ .../org/fdroid/fdroid/installer/InstallManagerService.java | 4 ++++ .../java/org/fdroid/fdroid/installer/InstallerService.java | 7 ++++++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/fdroid/fdroid/RepoUpdater.java b/app/src/main/java/org/fdroid/fdroid/RepoUpdater.java index 7abd9d7a2..9d30651e1 100644 --- a/app/src/main/java/org/fdroid/fdroid/RepoUpdater.java +++ b/app/src/main/java/org/fdroid/fdroid/RepoUpdater.java @@ -459,6 +459,11 @@ public class RepoUpdater { 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; 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())) {