PageRenderTime 65ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/app/src/test/java/org/fdroid/fdroid/data/RepoXMLHandlerTest.java

https://gitlab.com/eighthave/fdroidclient
Java | 953 lines | 877 code | 46 blank | 30 comment | 12 complexity | ee5bb9c74885a2f655010885b3f853b2 MD5 | raw file
Possible License(s): GPL-3.0
  1. /*
  2. * Copyright (C) 2016 Blue Jay Wireless
  3. * Copyright (C) 2015 Daniel Martí <mvdan@mvdan.cc>
  4. * Copyright (C) 2014-2016 Hans-Christoph Steiner <hans@eds.org>
  5. * Copyright (C) 2014-2016 Peter Serwylo <peter@serwylo.com>
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version 3
  10. * of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  20. * MA 02110-1301, USA.
  21. */
  22. package org.fdroid.fdroid.data;
  23. import android.support.annotation.NonNull;
  24. import android.text.TextUtils;
  25. import android.util.Log;
  26. import org.apache.commons.io.FileUtils;
  27. import org.fdroid.fdroid.BuildConfig;
  28. import org.fdroid.fdroid.mock.MockRepo;
  29. import org.fdroid.fdroid.mock.RepoDetails;
  30. import org.junit.BeforeClass;
  31. import org.junit.Test;
  32. import org.junit.runner.RunWith;
  33. import org.robolectric.RobolectricTestRunner;
  34. import org.robolectric.annotation.Config;
  35. import org.xml.sax.InputSource;
  36. import org.xml.sax.XMLReader;
  37. import javax.xml.parsers.SAXParser;
  38. import javax.xml.parsers.SAXParserFactory;
  39. import java.io.BufferedInputStream;
  40. import java.io.File;
  41. import java.io.IOException;
  42. import java.io.InputStream;
  43. import java.util.ArrayList;
  44. import java.util.Arrays;
  45. import java.util.Collections;
  46. import java.util.HashMap;
  47. import java.util.List;
  48. import java.util.Map;
  49. import java.util.TimeZone;
  50. import static org.junit.Assert.assertEquals;
  51. import static org.junit.Assert.assertFalse;
  52. import static org.junit.Assert.assertNotNull;
  53. import static org.junit.Assert.assertNull;
  54. import static org.junit.Assert.assertTrue;
  55. import static org.junit.Assert.fail;
  56. @Config(constants = BuildConfig.class)
  57. @RunWith(RobolectricTestRunner.class)
  58. public class RepoXMLHandlerTest {
  59. private static final String TAG = "RepoXMLHandlerTest";
  60. private static final String FAKE_SIGNING_CERT = "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345"; // NOCHECKSTYLE LineLength
  61. /**
  62. * Set to random time zone to make sure that the dates are properly parsed.
  63. */
  64. @BeforeClass
  65. public static void setRandomTimeZone() {
  66. TimeZone.setDefault(TimeZone.getTimeZone(String.format("GMT-%d:%02d",
  67. System.currentTimeMillis() % 12, System.currentTimeMillis() % 60)));
  68. System.out.println("TIME ZONE for this test: " + TimeZone.getDefault());
  69. }
  70. @Test
  71. public void testExtendedPerms() throws IOException {
  72. Repo expectedRepo = new Repo();
  73. expectedRepo.name = "F-Droid";
  74. expectedRepo.signingCertificate = "3082035e30820246a00302010202044c49cd00300d06092a864886f70d01010505003071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b73301e170d3130303732333137313032345a170d3337313230383137313032345a3071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b7330820122300d06092a864886f70d01010105000382010f003082010a028201010096d075e47c014e7822c89fd67f795d23203e2a8843f53ba4e6b1bf5f2fd0e225938267cfcae7fbf4fe596346afbaf4070fdb91f66fbcdf2348a3d92430502824f80517b156fab00809bdc8e631bfa9afd42d9045ab5fd6d28d9e140afc1300917b19b7c6c4df4a494cf1f7cb4a63c80d734265d735af9e4f09455f427aa65a53563f87b336ca2c19d244fcbba617ba0b19e56ed34afe0b253ab91e2fdb1271f1b9e3c3232027ed8862a112f0706e234cf236914b939bcf959821ecb2a6c18057e070de3428046d94b175e1d89bd795e535499a091f5bc65a79d539a8d43891ec504058acb28c08393b5718b57600a211e803f4a634e5c57f25b9b8c4422c6fd90203010001300d06092a864886f70d0101050500038201010008e4ef699e9807677ff56753da73efb2390d5ae2c17e4db691d5df7a7b60fc071ae509c5414be7d5da74df2811e83d3668c4a0b1abc84b9fa7d96b4cdf30bba68517ad2a93e233b042972ac0553a4801c9ebe07bf57ebe9a3b3d6d663965260e50f3b8f46db0531761e60340a2bddc3426098397fda54044a17e5244549f9869b460ca5e6e216b6f6a2db0580b480ca2afe6ec6b46eedacfa4aa45038809ece0c5978653d6c85f678e7f5a2156d1bedd8117751e64a4b0dcd140f3040b021821a8d93aed8d01ba36db6c82372211fed714d9a32607038cdfd565bd529ffc637212aaa2c224ef22b603eccefb5bf1e085c191d4b24fe742b17ab3f55d4e6f05ef"; // NOCHECKSTYLE LineLength
  75. expectedRepo.description = "This is just a test of the extended permissions attributes.";
  76. expectedRepo.timestamp = 1467169032;
  77. RepoDetails actualDetails = getFromFile("extendedPerms.xml");
  78. handlerTestSuite(expectedRepo, actualDetails, 2, 6, 14, 16);
  79. }
  80. @Test
  81. public void testObbIndex() throws IOException {
  82. writeResourceToObbDir("main.1101613.obb.main.twoversions.obb");
  83. writeResourceToObbDir("main.1101615.obb.main.twoversions.obb");
  84. writeResourceToObbDir("main.1434483388.obb.main.oldversion.obb");
  85. writeResourceToObbDir("main.1619.obb.mainpatch.current.obb");
  86. writeResourceToObbDir("patch.1619.obb.mainpatch.current.obb");
  87. RepoDetails actualDetails = getFromFile("obbIndex.xml");
  88. for (Apk indexApk : actualDetails.apks) {
  89. Apk localApk = new Apk();
  90. localApk.packageName = indexApk.packageName;
  91. localApk.versionCode = indexApk.versionCode;
  92. localApk.hashType = indexApk.hashType;
  93. App.initInstalledObbFiles(localApk);
  94. assertEquals(indexApk.obbMainFile, localApk.obbMainFile);
  95. assertEquals(indexApk.obbMainFileSha256, localApk.obbMainFileSha256);
  96. assertEquals(indexApk.obbPatchFile, localApk.obbPatchFile);
  97. assertEquals(indexApk.obbPatchFileSha256, localApk.obbPatchFileSha256);
  98. }
  99. }
  100. @Test
  101. public void testSimpleIndex() {
  102. Repo expectedRepo = new Repo();
  103. expectedRepo.name = "F-Droid";
  104. expectedRepo.signingCertificate = "308201ee30820157a0030201020204300d845b300d06092a864886f70d01010b0500302a3110300e060355040b1307462d44726f6964311630140603550403130d70616c6174736368696e6b656e301e170d3134303432373030303633315a170d3431303931323030303633315a302a3110300e060355040b1307462d44726f6964311630140603550403130d70616c6174736368696e6b656e30819f300d06092a864886f70d010101050003818d0030818902818100a439472e4b6d01141bfc94ecfe131c7c728fdda670bb14c57ca60bd1c38a8b8bc0879d22a0a2d0bc0d6fdd4cb98d1d607c2caefbe250a0bd0322aedeb365caf9b236992fac13e6675d3184a6c7c6f07f73410209e399a9da8d5d7512bbd870508eebacff8b57c3852457419434d34701ccbf692267cbc3f42f1c5d1e23762d790203010001a321301f301d0603551d0e041604140b1840691dab909746fde4bfe28207d1cae15786300d06092a864886f70d01010b05000381810062424c928ffd1b6fd419b44daafef01ca982e09341f7077fb865905087aeac882534b3bd679b51fdfb98892cef38b63131c567ed26c9d5d9163afc775ac98ad88c405d211d6187bde0b0d236381cc574ba06ef9080721a92ae5a103a7301b2c397eecc141cc850dd3e123813ebc41c59d31ddbcb6e984168280c53272f6a442b"; // NOCHECKSTYLE LineLength
  105. expectedRepo.description = "The official repository of the F-Droid client. 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://gitorious.org/f-droid."; // NOCHECKSTYLE LineLength
  106. expectedRepo.timestamp = 1398733213;
  107. RepoDetails actualDetails = getFromFile("simpleIndex.xml");
  108. handlerTestSuite(expectedRepo, actualDetails, 0, 0, -1, 12);
  109. }
  110. @Test
  111. public void testSmallRepo() {
  112. Repo expectedRepo = new Repo();
  113. expectedRepo.name = "Android-Nexus-7-20139453 on UNSET";
  114. expectedRepo.signingCertificate = "308202da308201c2a00302010202080eb08c796fec91aa300d06092a864886f70d0101050500302d3111300f060355040a0c084b6572706c61707031183016060355040b0c0f477561726469616e50726f6a656374301e170d3134313030333135303631325a170d3135313030333135303631325a302d3111300f060355040a0c084b6572706c61707031183016060355040b0c0f477561726469616e50726f6a65637430820122300d06092a864886f70d01010105000382010f003082010a0282010100c7ab44b130be5c00eedcc3625462f6f6ac26e502641cd641f3e30cbb0ff1ba325158611e7fc2448a35b6a6df30dc6e23602cf6909448befcf11e2fe486b580f1e76fe5887d159050d00afd2c4079f6538896bb200627f4b3e874f011ce5df0fef5d150fcb0b377b531254e436eaf4083ea72fe3b8c3ef450789fa858f2be8f6c5335bb326aff3dda689fbc7b5ba98dea53651dbea7452c38d294985ac5dd8a9e491a695de92c706d682d6911411fcaef3b0a08a030fe8a84e47acaab0b7edcda9d190ce39e810b79b1d8732eca22b15f0d048c8d6f00503a7ee81ab6e08919ff465883432304d95238b95e95c5f74e0a421809e2a6a85825aed680e0d6939e8f0203010001300d06092a864886f70d010105050003820101006d17aad3271b8b2c299dbdb7b1182849b0d5ddb9f1016dcb3487ae0db02b6be503344c7d066e2050bcd01d411b5ee78c7ed450f0ff9da5ce228f774cbf41240361df53d9c6078159d16f4d34379ab7dedf6186489397c83b44b964251a2ebb42b7c4689a521271b1056d3b5a5fa8f28ba64fb8ce5e2226c33c45d27ba3f632dc266c12abf582b8438c2abcf3eae9de9f31152b4158ace0ef33435c20eb809f1b3988131db6e5a1442f2617c3491d9565fedb3e320e8df4236200d3bd265e47934aa578f84d0d1a5efeb49b39907e876452c46996d0feff9404b41aa5631b4482175d843d5512ded45e12a514690646492191e7add434afce63dbff8f0b03ec0c"; // NOCHECKSTYLE LineLength
  115. expectedRepo.description = "A local FDroid repo generated from apps installed on Android-Nexus-7-20139453";
  116. expectedRepo.timestamp = 1412696461;
  117. RepoDetails actualDetails = getFromFile("smallRepo.xml");
  118. handlerTestSuite(expectedRepo, actualDetails, 12, 12, 14, -1);
  119. checkIncludedApps(actualDetails.apps, new String[]{
  120. "org.mozilla.firefox",
  121. "com.koushikdutta.superuser",
  122. "info.guardianproject.courier",
  123. "org.adaway",
  124. "info.guardianproject.gilga",
  125. "com.google.zxing.client.android",
  126. "info.guardianproject.lildebi",
  127. "de.danoeh.antennapod",
  128. "info.guardianproject.otr.app.im",
  129. "org.torproject.android",
  130. "org.gege.caldavsyncadapter",
  131. "info.guardianproject.checkey",
  132. });
  133. for (App app : actualDetails.apps) {
  134. if ("org.mozilla.firefox".equals(app.packageName)) {
  135. assertEquals(1411776000000L, app.added.getTime());
  136. assertEquals(1411862400000L, app.lastUpdated.getTime());
  137. }
  138. }
  139. }
  140. @Test(expected = IllegalArgumentException.class)
  141. public void testSimpleIndexWithCorruptedPackageName() throws Throwable {
  142. Repo expectedRepo = new Repo();
  143. expectedRepo.name = "F-Droid";
  144. expectedRepo.signingCertificate = "308201ee30820157a0030201020204300d845b300d06092a864886f70d01010b0500302a3110300e060355040b1307462d44726f6964311630140603550403130d70616c6174736368696e6b656e301e170d3134303432373030303633315a170d3431303931323030303633315a302a3110300e060355040b1307462d44726f6964311630140603550403130d70616c6174736368696e6b656e30819f300d06092a864886f70d010101050003818d0030818902818100a439472e4b6d01141bfc94ecfe131c7c728fdda670bb14c57ca60bd1c38a8b8bc0879d22a0a2d0bc0d6fdd4cb98d1d607c2caefbe250a0bd0322aedeb365caf9b236992fac13e6675d3184a6c7c6f07f73410209e399a9da8d5d7512bbd870508eebacff8b57c3852457419434d34701ccbf692267cbc3f42f1c5d1e23762d790203010001a321301f301d0603551d0e041604140b1840691dab909746fde4bfe28207d1cae15786300d06092a864886f70d01010b05000381810062424c928ffd1b6fd419b44daafef01ca982e09341f7077fb865905087aeac882534b3bd679b51fdfb98892cef38b63131c567ed26c9d5d9163afc775ac98ad88c405d211d6187bde0b0d236381cc574ba06ef9080721a92ae5a103a7301b2c397eecc141cc850dd3e123813ebc41c59d31ddbcb6e984168280c53272f6a442b"; // NOCHECKSTYLE LineLength
  145. expectedRepo.description = "The official repository of the F-Droid client. 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://gitorious.org/f-droid."; // NOCHECKSTYLE LineLength
  146. expectedRepo.timestamp = 1398733213;
  147. InputStream inputStream = getClass().getClassLoader()
  148. .getResourceAsStream("simpleIndexWithCorruptedPackageName.xml");
  149. SAXParserFactory factory = SAXParserFactory.newInstance();
  150. factory.setNamespaceAware(true);
  151. SAXParser parser = factory.newSAXParser();
  152. XMLReader reader = parser.getXMLReader();
  153. RepoDetails repoDetails = new RepoDetails();
  154. MockRepo mockRepo = new MockRepo(100, Repo.PUSH_REQUEST_IGNORE);
  155. RepoXMLHandler handler = new RepoXMLHandler(mockRepo, repoDetails);
  156. reader.setContentHandler(handler);
  157. InputSource is = new InputSource(new BufferedInputStream(inputStream));
  158. try {
  159. reader.parse(is);
  160. } catch (org.xml.sax.SAXException e) {
  161. throw e.getCause();
  162. }
  163. fail();
  164. }
  165. @Test
  166. public void testPushRequestsRepoIgnore() {
  167. Repo expectedRepo = new Repo();
  168. expectedRepo.name = "non-public test repo";
  169. expectedRepo.signingCertificate = "308204e1308202c9a0030201020204483450fa300d06092a864886f70d01010b050030213110300e060355040b1307462d44726f6964310d300b06035504031304736f7661301e170d3136303832333133333131365a170d3434303130393133333131365a30213110300e060355040b1307462d44726f6964310d300b06035504031304736f766130820222300d06092a864886f70d01010105000382020f003082020a0282020100dfdcd120f3ab224999dddf4ea33ea588d295e4d7130bef48c143e9d76e5c0e0e9e5d45e64208e35feebc79a83f08939dd6a343b7d1e2179930a105a1249ccd36d88ff3feffc6e4dc53dae0163a7876dd45ecc1ddb0adf5099aa56c1a84b52affcd45d0711ffa4de864f35ac0333ebe61ea8673eeda35a88f6af678cc4d0f80b089338ac8f2a8279a64195c611d19445cab3fd1a020afed9bd739bb95142fb2c00a8f847db5ef3325c814f8eb741bacf86ed3907bfe6e4564d2de5895df0c263824e0b75407589bae2d3a4666c13b92102d8781a8ee9bb4a5a1a78c4a9c21efdaf5584da42e84418b28f5a81d0456a3dc5b420991801e6b21e38c99bbe018a5b2d690894a114bc860d35601416aa4dc52216aff8a288d4775cddf8b72d45fd2f87303a8e9c0d67e442530be28eaf139894337266e0b33d57f949256ab32083bcc545bc18a83c9ab8247c12aea037e2b68dee31c734cb1f04f241d3b94caa3a2b258ffaf8e6eae9fbbe029a934dc0a0859c5f120334812693a1c09352340a39f2a678dbc1afa2a978bfee43afefcb7e224a58af2f3d647e5745db59061236b8af6fcfd93b3602f9e456978534f3a7851e800071bf56da80401c81d91c45f82568373af0576b1cc5eef9b85654124b6319770be3cdba3fbebe3715e8918fb6c8966624f3d0e815effac3d2ee06dd34ab9c693218b2c7c06ba99d6b74d4f17b8c3cb0203010001a321301f301d0603551d0e04160414d62bee9f3798509546acc62eb1de14b08b954d4f300d06092a864886f70d01010b05000382020100743f7c5692085895f9d1fffad390fb4202c15f123ed094df259185960fd6dadf66cb19851070f180297bba4e6996a4434616573b375cfee94fee73a4505a7ec29136b7e6c22e6436290e3686fe4379d4e3140ec6a08e70cfd3ed5b634a5eb5136efaaabf5f38e0432d3d79568a556970b8cfba2972f5d23a3856d8a981b9e9bbbbb88f35e708bde9cbc5f681cbd974085b9da28911296fe2579fa64bbe9fa0b93475a7a8db051080b0c5fade0d1c018e7858cd4cbe95145b0620e2f632cbe0f8af9cbf22e2fdaa72245ae31b0877b07181cc69dd2df74454251d8de58d25e76354abe7eb690f22e59b08795a8f2c98c578e0599503d9085927634072c82c9f82abd50fd12b8fd1a9d1954eb5cc0b4cfb5796b5aaec0356643b4a65a368442d92ef94edd3ac6a2b7fe3571b8cf9f462729228aab023ef9183f73792f5379633ccac51079177d604c6bc1873ada6f07d8da6d68c897e88a5fa5d63fdb8df820f46090e0716e7562dd3c140ba279a65b996f60addb0abe29d4bf2f5abe89480771d492307b926d91f02f341b2148502903c43d40f3c6c86a811d060711f0698b384acdcc0add44eb54e42962d3d041accc715afd49407715adc09350cb55e8d9281a3b0b6b5fcd91726eede9b7c8b13afdebb2c2b377629595f1096ba62fb14946dbac5f3c5f0b4e5b712e7acc7dcf6c46cdc5e6d6dfdeee55a0c92c2d70f080ac6"; // NOCHECKSTYLE LineLength
  170. 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."; // NOCHECKSTYLE LineLength
  171. expectedRepo.timestamp = 1472071347;
  172. RepoDetails actualDetails = getFromFile("pushRequestsIndex.xml", Repo.PUSH_REQUEST_IGNORE);
  173. handlerTestSuite(expectedRepo, actualDetails, 2, 14, -1, 17);
  174. checkPushRequests(actualDetails);
  175. List<RepoPushRequest> repoPushRequests = actualDetails.repoPushRequestList;
  176. assertNotNull(repoPushRequests);
  177. assertEquals(0, repoPushRequests.size());
  178. }
  179. @Test
  180. public void testPushRequestsRepoAlways() {
  181. Repo expectedRepo = new Repo();
  182. expectedRepo.name = "non-public test repo";
  183. expectedRepo.signingCertificate = "308204e1308202c9a0030201020204483450fa300d06092a864886f70d01010b050030213110300e060355040b1307462d44726f6964310d300b06035504031304736f7661301e170d3136303832333133333131365a170d3434303130393133333131365a30213110300e060355040b1307462d44726f6964310d300b06035504031304736f766130820222300d06092a864886f70d01010105000382020f003082020a0282020100dfdcd120f3ab224999dddf4ea33ea588d295e4d7130bef48c143e9d76e5c0e0e9e5d45e64208e35feebc79a83f08939dd6a343b7d1e2179930a105a1249ccd36d88ff3feffc6e4dc53dae0163a7876dd45ecc1ddb0adf5099aa56c1a84b52affcd45d0711ffa4de864f35ac0333ebe61ea8673eeda35a88f6af678cc4d0f80b089338ac8f2a8279a64195c611d19445cab3fd1a020afed9bd739bb95142fb2c00a8f847db5ef3325c814f8eb741bacf86ed3907bfe6e4564d2de5895df0c263824e0b75407589bae2d3a4666c13b92102d8781a8ee9bb4a5a1a78c4a9c21efdaf5584da42e84418b28f5a81d0456a3dc5b420991801e6b21e38c99bbe018a5b2d690894a114bc860d35601416aa4dc52216aff8a288d4775cddf8b72d45fd2f87303a8e9c0d67e442530be28eaf139894337266e0b33d57f949256ab32083bcc545bc18a83c9ab8247c12aea037e2b68dee31c734cb1f04f241d3b94caa3a2b258ffaf8e6eae9fbbe029a934dc0a0859c5f120334812693a1c09352340a39f2a678dbc1afa2a978bfee43afefcb7e224a58af2f3d647e5745db59061236b8af6fcfd93b3602f9e456978534f3a7851e800071bf56da80401c81d91c45f82568373af0576b1cc5eef9b85654124b6319770be3cdba3fbebe3715e8918fb6c8966624f3d0e815effac3d2ee06dd34ab9c693218b2c7c06ba99d6b74d4f17b8c3cb0203010001a321301f301d0603551d0e04160414d62bee9f3798509546acc62eb1de14b08b954d4f300d06092a864886f70d01010b05000382020100743f7c5692085895f9d1fffad390fb4202c15f123ed094df259185960fd6dadf66cb19851070f180297bba4e6996a4434616573b375cfee94fee73a4505a7ec29136b7e6c22e6436290e3686fe4379d4e3140ec6a08e70cfd3ed5b634a5eb5136efaaabf5f38e0432d3d79568a556970b8cfba2972f5d23a3856d8a981b9e9bbbbb88f35e708bde9cbc5f681cbd974085b9da28911296fe2579fa64bbe9fa0b93475a7a8db051080b0c5fade0d1c018e7858cd4cbe95145b0620e2f632cbe0f8af9cbf22e2fdaa72245ae31b0877b07181cc69dd2df74454251d8de58d25e76354abe7eb690f22e59b08795a8f2c98c578e0599503d9085927634072c82c9f82abd50fd12b8fd1a9d1954eb5cc0b4cfb5796b5aaec0356643b4a65a368442d92ef94edd3ac6a2b7fe3571b8cf9f462729228aab023ef9183f73792f5379633ccac51079177d604c6bc1873ada6f07d8da6d68c897e88a5fa5d63fdb8df820f46090e0716e7562dd3c140ba279a65b996f60addb0abe29d4bf2f5abe89480771d492307b926d91f02f341b2148502903c43d40f3c6c86a811d060711f0698b384acdcc0add44eb54e42962d3d041accc715afd49407715adc09350cb55e8d9281a3b0b6b5fcd91726eede9b7c8b13afdebb2c2b377629595f1096ba62fb14946dbac5f3c5f0b4e5b712e7acc7dcf6c46cdc5e6d6dfdeee55a0c92c2d70f080ac6"; // NOCHECKSTYLE LineLength
  184. 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."; // NOCHECKSTYLE LineLength
  185. expectedRepo.timestamp = 1472071347;
  186. RepoDetails actualDetails = getFromFile("pushRequestsIndex.xml", Repo.PUSH_REQUEST_ACCEPT_ALWAYS);
  187. handlerTestSuite(expectedRepo, actualDetails, 2, 14, -1, 17);
  188. checkPushRequests(actualDetails);
  189. List<RepoPushRequest> repoPushRequests = actualDetails.repoPushRequestList;
  190. assertNotNull(repoPushRequests);
  191. assertEquals(6, repoPushRequests.size());
  192. }
  193. @Test
  194. public void testPushRequestsRepoCorruption() {
  195. RepoPushRequest repoPushRequest;
  196. repoPushRequest = new RepoPushRequest(null, null, null); // request with no data
  197. assertEquals(repoPushRequest.request, null);
  198. assertEquals(repoPushRequest.packageName, null);
  199. assertEquals(repoPushRequest.versionCode, null);
  200. repoPushRequest = new RepoPushRequest("install", "org.fdroid.fdroid", "999999999999");
  201. assertEquals(repoPushRequest.versionCode, null);
  202. repoPushRequest = new RepoPushRequest("install", "org.fdroid.fdroid",
  203. String.valueOf(((long) Integer.MAX_VALUE) + 1));
  204. assertEquals(repoPushRequest.versionCode, null);
  205. repoPushRequest = new RepoPushRequest("install", "org.fdroid.fdroid",
  206. String.valueOf(((long) Integer.MIN_VALUE) - 1));
  207. assertEquals(repoPushRequest.versionCode, null);
  208. repoPushRequest = new RepoPushRequest("Robert'); DROP TABLE Students; --", "org.fdroid.fdroid", null);
  209. assertEquals(repoPushRequest.request, null);
  210. assertEquals(repoPushRequest.packageName, "org.fdroid.fdroid");
  211. assertEquals(repoPushRequest.versionCode, null);
  212. repoPushRequest = new RepoPushRequest("install", "Robert'); DROP TABLE Students; --", "123.1.1");
  213. assertEquals(repoPushRequest.request, "install");
  214. assertEquals(repoPushRequest.packageName, null);
  215. assertEquals(repoPushRequest.versionCode, null);
  216. repoPushRequest = new RepoPushRequest("install", "--", "123");
  217. assertEquals(repoPushRequest.request, "install");
  218. assertEquals(repoPushRequest.packageName, null);
  219. assertEquals(repoPushRequest.versionCode, Integer.valueOf(123));
  220. repoPushRequest = new RepoPushRequest("uninstall", "Robert'); DROP TABLE Students; --", "123");
  221. assertEquals(repoPushRequest.request, "uninstall");
  222. assertEquals(repoPushRequest.packageName, null);
  223. assertEquals(repoPushRequest.versionCode, Integer.valueOf(123));
  224. repoPushRequest = new RepoPushRequest("badrquest", "asdfasdfasdf", "123");
  225. assertEquals(repoPushRequest.request, null);
  226. assertEquals(repoPushRequest.packageName, "asdfasdfasdf");
  227. assertEquals(repoPushRequest.versionCode, Integer.valueOf(123));
  228. }
  229. @Test
  230. public void testMediumRepo() {
  231. Repo expectedRepo = new Repo();
  232. expectedRepo.name = "Guardian Project Official Releases";
  233. expectedRepo.signingCertificate = "308205d8308203c0020900a397b4da7ecda034300d06092a864886f70d01010505003081ad310b30090603550406130255533111300f06035504080c084e657720596f726b3111300f06035504070c084e657720596f726b31143012060355040b0c0b4644726f6964205265706f31193017060355040a0c10477561726469616e2050726f6a656374311d301b06035504030c14677561726469616e70726f6a6563742e696e666f3128302606092a864886f70d0109011619726f6f7440677561726469616e70726f6a6563742e696e666f301e170d3134303632363139333931385a170d3431313131303139333931385a3081ad310b30090603550406130255533111300f06035504080c084e657720596f726b3111300f06035504070c084e657720596f726b31143012060355040b0c0b4644726f6964205265706f31193017060355040a0c10477561726469616e2050726f6a656374311d301b06035504030c14677561726469616e70726f6a6563742e696e666f3128302606092a864886f70d0109011619726f6f7440677561726469616e70726f6a6563742e696e666f30820222300d06092a864886f70d01010105000382020f003082020a0282020100b3cd79121b9b883843be3c4482e320809106b0a23755f1dd3c7f46f7d315d7bb2e943486d61fc7c811b9294dcc6b5baac4340f8db2b0d5e14749e7f35e1fc211fdbc1071b38b4753db201c314811bef885bd8921ad86facd6cc3b8f74d30a0b6e2e6e576f906e9581ef23d9c03e926e06d1f033f28bd1e21cfa6a0e3ff5c9d8246cf108d82b488b9fdd55d7de7ebb6a7f64b19e0d6b2ab1380a6f9d42361770d1956701a7f80e2de568acd0bb4527324b1e0973e89595d91c8cc102d9248525ae092e2c9b69f7414f724195b81427f28b1d3d09a51acfe354387915fd9521e8c890c125fc41a12bf34d2a1b304067ab7251e0e9ef41833ce109e76963b0b256395b16b886bca21b831f1408f836146019e7908829e716e72b81006610a2af08301de5d067c9e114a1e5759db8a6be6a3cc2806bcfe6fafd41b5bc9ddddb3dc33d6f605b1ca7d8a9e0ecdd6390d38906649e68a90a717bea80fa220170eea0c86fc78a7e10dac7b74b8e62045a3ecca54e035281fdc9fe5920a855fde3c0be522e3aef0c087524f13d973dff3768158b01a5800a060c06b451ec98d627dd052eda804d0556f60dbc490d94e6e9dea62ffcafb5beffbd9fc38fb2f0d7050004fe56b4dda0a27bc47554e1e0a7d764e17622e71f83a475db286bc7862deee1327e2028955d978272ea76bf0b88e70a18621aba59ff0c5993ef5f0e5d6b6b98e68b70203010001300d06092a864886f70d0101050500038202010079c79c8ef408a20d243d8bd8249fb9a48350dc19663b5e0fce67a8dbcb7de296c5ae7bbf72e98a2020fb78f2db29b54b0e24b181aa1c1d333cc0303685d6120b03216a913f96b96eb838f9bff125306ae3120af838c9fc07ebb5100125436bd24ec6d994d0bff5d065221871f8410daf536766757239bf594e61c5432c9817281b985263bada8381292e543a49814061ae11c92a316e7dc100327b59e3da90302c5ada68c6a50201bda1fcce800b53f381059665dbabeeb0b50eb22b2d7d2d9b0aa7488ca70e67ac6c518adb8e78454a466501e89d81a45bf1ebc350896f2c3ae4b6679ecfbf9d32960d4f5b493125c7876ef36158562371193f600bc511000a67bdb7c664d018f99d9e589868d103d7e0994f166b2ba18ff7e67d8c4da749e44dfae1d930ae5397083a51675c409049dfb626a96246c0015ca696e94ebb767a20147834bf78b07fece3f0872b057c1c519ff882501995237d8206b0b3832f78753ebd8dcbd1d3d9f5ba733538113af6b407d960ec4353c50eb38ab29888238da843cd404ed8f4952f59e4bbc0035fc77a54846a9d419179c46af1b4a3b7fc98e4d312aaa29b9b7d79e739703dc0fa41c7280d5587709277ffa11c3620f5fba985b82c238ba19b17ebd027af9424be0941719919f620dd3bb3c3f11638363708aa11f858e153cf3a69bce69978b90e4a273836100aa1e617ba455cd00426847f"; // NOCHECKSTYLE LineLength
  234. expectedRepo.description = "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."; // NOCHECKSTYLE LineLength
  235. expectedRepo.timestamp = 1411427879;
  236. RepoDetails actualDetails = getFromFile("mediumRepo.xml");
  237. handlerTestSuite(expectedRepo, actualDetails, 15, 36, 60, 12);
  238. checkIncludedApps(actualDetails.apps, new String[]{
  239. "info.guardianproject.cacert",
  240. "info.guardianproject.otr.app.im",
  241. "info.guardianproject.soundrecorder",
  242. "info.guardianproject.checkey",
  243. "info.guardianproject.courier",
  244. "org.fdroid.fdroid",
  245. "info.guardianproject.gpg",
  246. "info.guardianproject.lildebi",
  247. "info.guardianproject.notepadbot",
  248. "org.witness.sscphase1",
  249. "org.torproject.android",
  250. "info.guardianproject.browser",
  251. "info.guardianproject.pixelknot",
  252. "info.guardianproject.chatsecure.emoji.core",
  253. "info.guardianproject.mrapp",
  254. });
  255. }
  256. @Test
  257. public void testLargeRepo() {
  258. Repo expectedRepo = new Repo();
  259. expectedRepo.name = "F-Droid";
  260. expectedRepo.signingCertificate = "3082035e30820246a00302010202044c49cd00300d06092a864886f70d01010505003071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b73301e170d3130303732333137313032345a170d3337313230383137313032345a3071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b7330820122300d06092a864886f70d01010105000382010f003082010a028201010096d075e47c014e7822c89fd67f795d23203e2a8843f53ba4e6b1bf5f2fd0e225938267cfcae7fbf4fe596346afbaf4070fdb91f66fbcdf2348a3d92430502824f80517b156fab00809bdc8e631bfa9afd42d9045ab5fd6d28d9e140afc1300917b19b7c6c4df4a494cf1f7cb4a63c80d734265d735af9e4f09455f427aa65a53563f87b336ca2c19d244fcbba617ba0b19e56ed34afe0b253ab91e2fdb1271f1b9e3c3232027ed8862a112f0706e234cf236914b939bcf959821ecb2a6c18057e070de3428046d94b175e1d89bd795e535499a091f5bc65a79d539a8d43891ec504058acb28c08393b5718b57600a211e803f4a634e5c57f25b9b8c4422c6fd90203010001300d06092a864886f70d0101050500038201010008e4ef699e9807677ff56753da73efb2390d5ae2c17e4db691d5df7a7b60fc071ae509c5414be7d5da74df2811e83d3668c4a0b1abc84b9fa7d96b4cdf30bba68517ad2a93e233b042972ac0553a4801c9ebe07bf57ebe9a3b3d6d663965260e50f3b8f46db0531761e60340a2bddc3426098397fda54044a17e5244549f9869b460ca5e6e216b6f6a2db0580b480ca2afe6ec6b46eedacfa4aa45038809ece0c5978653d6c85f678e7f5a2156d1bedd8117751e64a4b0dcd140f3040b021821a8d93aed8d01ba36db6c82372211fed714d9a32607038cdfd565bd529ffc637212aaa2c224ef22b603eccefb5bf1e085c191d4b24fe742b17ab3f55d4e6f05ef"; // NOCHECKSTYLE LineLength
  261. expectedRepo.description = "The official FDroid 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."; // NOCHECKSTYLE LineLength
  262. expectedRepo.timestamp = 1412746769;
  263. RepoDetails actualDetails = getFromFile("largeRepo.xml");
  264. handlerTestSuite(expectedRepo, actualDetails, 1211, 2381, 14, 12);
  265. // Generated using something like the following:
  266. // sed 's,<application,\n<application,g' largeRepo.xml | grep "antifeatures" | sed 's,.*id="\(.*\)".*<antifeatures>\(.*\)</antifeatures>.*,\1 \2,p' | sort | uniq // NOCHECKSTYLE LineLength
  267. Map<String, List<String>> expectedAntiFeatures = new HashMap<>();
  268. expectedAntiFeatures.put("org.fdroid.fdroid", new ArrayList<String>());
  269. expectedAntiFeatures.put("org.adblockplus.android", Arrays.asList("Tracking", "Ads"));
  270. expectedAntiFeatures.put("org.microg.nlp.backend.apple", Arrays.asList("Tracking", "NonFreeNet"));
  271. expectedAntiFeatures.put("com.ds.avare", Collections.singletonList("NonFreeDep"));
  272. expectedAntiFeatures.put("com.miracleas.bitcoin_spinner", Collections.singletonList("NonFreeAdd"));
  273. expectedAntiFeatures.put("de.Cherubin7th.blackscreenpresentationremote", Collections.singletonList("Ads"));
  274. expectedAntiFeatures.put("budo.budoist", Collections.singletonList("NonFreeNet"));
  275. expectedAntiFeatures.put("no.rkkc.bysykkel", Collections.singletonList("NonFreeDep"));
  276. expectedAntiFeatures.put("com.jadn.cc", Collections.singletonList("Tracking"));
  277. expectedAntiFeatures.put("org.atai.TessUI", Collections.singletonList("NonFreeNet"));
  278. expectedAntiFeatures.put("org.zephyrsoft.checknetwork", Collections.singletonList("Tracking"));
  279. expectedAntiFeatures.put("de.bashtian.dashclocksunrise", Collections.singletonList("NonFreeDep"));
  280. expectedAntiFeatures.put("org.geometerplus.zlibrary.ui.android", Collections.singletonList("NonFreeAdd"));
  281. expectedAntiFeatures.put("org.mozilla.firefox", Arrays.asList("NonFreeAdd", "Tracking"));
  282. expectedAntiFeatures.put("com.gmail.charleszq", Collections.singletonList("NonFreeDep"));
  283. expectedAntiFeatures.put("it.andreascarpino.forvodroid", Arrays.asList("NonFreeNet", "NonFreeDep"));
  284. expectedAntiFeatures.put("de.b0nk.fp1_epo_autoupdate", Collections.singletonList("NonFreeNet"));
  285. expectedAntiFeatures.put("com.blogspot.tonyatkins.freespeech", Collections.singletonList("Tracking"));
  286. expectedAntiFeatures.put("com.frostwire.android", Collections.singletonList("Tracking"));
  287. expectedAntiFeatures.put("com.namsor.api.samples.gendre", Collections.singletonList("NonFreeNet"));
  288. expectedAntiFeatures.put("com.github.mobile", Collections.singletonList("NonFreeNet"));
  289. expectedAntiFeatures.put("com.cradle.iitc_mobile", Collections.singletonList("NonFreeNet"));
  290. expectedAntiFeatures.put("com.matteopacini.katana", Collections.singletonList("Tracking"));
  291. expectedAntiFeatures.put("de.enaikoon.android.keypadmapper3", Collections.singletonList("Tracking"));
  292. expectedAntiFeatures.put("org.linphone", Collections.singletonList("NonFreeDep"));
  293. expectedAntiFeatures.put("ch.rrelmy.android.locationcachemap", Collections.singletonList("NonFreeDep"));
  294. expectedAntiFeatures.put("com.powerpoint45.lucidbrowser", Arrays.asList("Ads", "NonFreeDep"));
  295. expectedAntiFeatures.put("org.mixare", Collections.singletonList("NonFreeDep"));
  296. expectedAntiFeatures.put("apps.droidnotify", Collections.singletonList("NonFreeAdd"));
  297. expectedAntiFeatures.put("com.numix.calculator", Collections.singletonList("NonFreeAdd"));
  298. expectedAntiFeatures.put("com.numix.icons_circle", Collections.singletonList("NonFreeAdd"));
  299. expectedAntiFeatures.put("com.gh4a", Collections.singletonList("NonFreeNet"));
  300. expectedAntiFeatures.put("at.tomtasche.reader", Collections.singletonList("Tracking"));
  301. expectedAntiFeatures.put("de.uni_potsdam.hpi.openmensa", Collections.singletonList("NonFreeNet"));
  302. expectedAntiFeatures.put("net.osmand.plus", Collections.singletonList("Tracking"));
  303. expectedAntiFeatures.put("byrne.utilities.pasteedroid", Collections.singletonList("NonFreeNet"));
  304. expectedAntiFeatures.put("com.bwx.bequick", Collections.singletonList("NonFreeAdd"));
  305. expectedAntiFeatures.put("be.geecko.QuickLyric", Collections.singletonList("Tracking"));
  306. expectedAntiFeatures.put("com.wanghaus.remembeer", Collections.singletonList("NonFreeNet"));
  307. expectedAntiFeatures.put("cri.sanity", Collections.singletonList("Ads"));
  308. expectedAntiFeatures.put("com.showmehills", Collections.singletonList("Tracking"));
  309. expectedAntiFeatures.put("com.akop.bach", Collections.singletonList("NonFreeNet"));
  310. expectedAntiFeatures.put("org.dmfs.tasks", Collections.singletonList("NonFreeAdd"));
  311. expectedAntiFeatures.put("org.telegram.messenger", Collections.singletonList("NonFreeNet"));
  312. expectedAntiFeatures.put("com.danvelazco.fbwrapper", Collections.singletonList("Tracking"));
  313. expectedAntiFeatures.put("org.zephyrsoft.trackworktime", Collections.singletonList("Tracking"));
  314. expectedAntiFeatures.put("org.transdroid", Collections.singletonList("Tracking"));
  315. expectedAntiFeatures.put("com.lonepulse.travisjr", Collections.singletonList("NonFreeNet"));
  316. expectedAntiFeatures.put("com.twsitedapps.homemanager", Collections.singletonList("NonFreeAdd"));
  317. expectedAntiFeatures.put("org.zeitgeist.movement", Collections.singletonList("NonFreeDep"));
  318. expectedAntiFeatures.put("net.wigle.wigleandroid", Collections.singletonList("NonFreeNet"));
  319. expectedAntiFeatures.put("org.nick.wwwjdic", Collections.singletonList("Tracking"));
  320. checkAntiFeatures(actualDetails.apps, expectedAntiFeatures);
  321. /*
  322. * generated using: sed 's,<application,\n<application,g' largeRepo.xml
  323. * | sed -n 's,.*id="\(.[^"]*\)".*,"\1"\,,p'
  324. */
  325. checkIncludedApps(actualDetails.apps, new String[]{
  326. "org.zeroxlab.zeroxbenchmark", "com.uberspot.a2048", "com.traffar.a24game",
  327. "info.staticfree.android.twentyfourhour", "nerd.tuxmobil.fahrplan.congress",
  328. "com.jecelyin.editor", "com.markuspage.android.atimetracker", "a2dp.Vol",
  329. "com.zoffcc.applications.aagtl", "aarddict.android", "com.kai1973i",
  330. "net.georgewhiteside.android.abstractart", "com.morphoss.acal",
  331. "org.billthefarmer.accordion", "com.achep.acdisplay", "anupam.acrylic",
  332. "net.androidcomics.acv", "org.adaway", "com.matoski.adbm",
  333. "org.adblockplus.android", "siir.es.adbWireless", "org.dgtale.icsimport",
  334. "com.addi", "org.hystudio.android.dosbox", "hu.vsza.adsdroid", "org.adw.launcher",
  335. "dev.ukanth.ufirewall", "com.madgag.agit", "jp.sblo.pandora.aGrep",
  336. "net.gorry.aicia", "com.brosmike.airpushdetector", "org.ligi.ajsha",
  337. "org.akvo.rsr.up", "com.angrydoughnuts.android.alarmclock", "org.jtb.alogcat",
  338. "rs.pedjaapps.alogcatroot.app", "org.ametro", "com.orphan.amplayer",
  339. "eu.domob.anacam", "com.as.anagramsolver", "com.nephoapp.anarxiv",
  340. "net.bible.android.activity", "li.klass.fhem", "org.xapek.andiodine", "net.avs234",
  341. "com.github.andlyticsproject", "org.quovadit.apps.andof",
  342. "com.gpl.rpg.AndorsTrail", "net.progval.android.andquote", "net.rocrail.androc",
  343. "de.hechler.andfish", "com.android.inputmethod.latin", "aws.apps.androidDrawables",
  344. "org.yuttadhammo.tipitaka", "uk.co.bitethebullet.android.token",
  345. "jp.ksksue.app.terminal", "com.templaro.opsiz.aka", "fr.asterope",
  346. "android.androidVNC", "com.tritop.androsense2", "net.tedstein.AndroSS",
  347. "com.androzic", "org.andstatus.app", "net.sourceforge.andsys",
  348. "com.miqote.angelplayerwp", "eu.domob.angulo", "com.ichi2.anki",
  349. "net.haltcondition.anode", "An.stop", "de.danoeh.antennapod",
  350. "com.fivasim.antikythera", "de.antonwolf.agendawidget", "com.example.anycut",
  351. "org.liberty.android.fantastischmemo", "com.menny.android.anysoftkeyboard",
  352. "com.anysoftkeyboard.languagepack.catalan", "com.anysoftkeyboard.theme.classic_pc",
  353. "com.anysoftkeyboard.languagepack.danish",
  354. "com.anysoftkeyboard.languagepack.esperanto",
  355. "com.anysoftkeyboard.languagepack.french_xlarge",
  356. "com.anysoftkeyboard.languagepack.georgian.fdroid",
  357. "com.anysoftkeyboard.languagepack.greek",
  358. "com.anysoftkeyboard.languagepack.hebrew_large",
  359. "org.herrlado.ask.languagepack.lithuanian",
  360. "com.anysoftkeyboard.languagepack.hungarian",
  361. "com.anysoftkeyboard.languagepack.malayalam",
  362. "com.anysoftkeyboard.languagepack.pali",
  363. "com.anysoftkeyboard.languagepack.persian",
  364. "com.anysoftkeyboard.languagepack.spain", "com.anysoftkeyboard.languagepack.SSH",
  365. "com.anysoftkeyboard.languagepack.ukrainian", "com.scar45.aokp.co.webviewer",
  366. "org.thialfihar.android.apg", "ch.blinkenlights.android.apnswitch",
  367. "com.andrew.apollo", "com.nolanlawson.apptracker",
  368. "com.episode6.android.appalarm.pro", "org.moparisthebest.appbak",
  369. "org.microg.nlp.backend.apple", "com.gueei.applocker",
  370. "com.google.code.appsorganizer", "com.google.code.apps2org",
  371. "cx.hell.android.pdfview", "org.androidfromfrankfurt.archnews", "org.ardour",
  372. "com.primavera.arduino.listener", "arity.calculator",
  373. "com.commonsware.android.arXiv", "com.dozingcatsoftware.asciicam",
  374. "com.alfray.asqare", "dk.andsen.asqlitemanager", "net.somethingdreadful.MAL",
  375. "org.tamanegi.atmosphere", "indrora.atomic",
  376. "com.google.android.apps.authenticator2", "com.teamdc.stephendiniz.autoaway",
  377. "com.everysoft.autoanswer", "com.elsdoerfer.android.autostarts", "com.ds.avare",
  378. "apps.babycaretimer", "com.tkjelectronics.balanduino", "com.liato.bankdroid",
  379. "uk.ac.cam.cl.dtg.android.barcodebox", "com.google.zxing.client.android",
  380. "net.szym.barnacle", "com.dougkeen.bart", "ch.blinkenlights.battery",
  381. "net.sf.andbatdog.batterydog", "ch.rrelmy.android.batterymanager",
  382. "org.droidparts.battery_widget", "org.androidappdev.batterywidget",
  383. "com.darshancomputing.BatteryIndicatorPro", "com.tobykurien.batteryfu",
  384. "com.mohammadag.beamfile", "com.corner23.android.beautyclocklivewallpaper",
  385. "com.knirirr.beecount", "com.beem.project.beem", "com.glanznig.beepme",
  386. "headrevision.BehatReporter", "com.asksven.betterwifionoff",
  387. "com.asksven.betterbatterystats", "net.imatruck.betterweather",
  388. "org.segin.bfinterpreter", "com.ihunda.android.binauralbeat",
  389. "org.birthdayadapter", "com.rigid.birthdroid", "com.saibotd.bitbeaker",
  390. "de.schildbach.wallet", "com.veken0m.bitcoinium", "com.miracleas.bitcoin_spinner",
  391. "caldwell.ben.bites", "eu.domob.bjtrainer",
  392. "de.Cherubin7th.blackscreenpresentationremote", "com.miqote.brswp",
  393. "com.blippex.app", "de.grobox.blitzmail", "org.blockinger.game",
  394. "org.scoutant.blokish", "org.broeuschmeul.android.gps.bluetooth.provider",
  395. "com.hermit.btreprap", "ru.sash0k.bluetooth_terminal", "net.bluetoothviewer",
  396. "com.hexad.bluezime", "com.hexad.bluezime.hidenabler", "cxa.lineswallpaper",
  397. "com.zola.bmi", "com.boardgamegeek", "byrne.utilities.converter",
  398. "org.yuttadhammo.BodhiTimer", "mobi.boilr.boilr", "org.beide.bomber",
  399. "org.bombusmod", "com.eleybourn.bookcatalogue", "com.totsp.bookworm",
  400. "com.botbrew.basil", "com.github.grimpy.botifier",
  401. "priv.twoerner.brightnesswidget", "nl.frankkie.bronylivewallpaper",
  402. "com.intrications.android.sharebrowser", "fr.strasweb.browserquest",
  403. "net.androgames.level", "com.notriddle.budget", "budo.budoist",
  404. "org.nathan.jf.build.prop.editor", "com.sandeel.bushidoblocks", "no.rkkc.bysykkel",
  405. "info.guardianproject.cacert", "com.frozendevs.cache.cleaner",
  406. "at.bitfire.cadroid", "org.iilab.pb", "home.jmstudios.calc",
  407. "com.android2.calculator3", "org.gege.caldavsyncadapter",
  408. "de.k3b.android.calendar.ics.adapter", "com.plusonelabs.calendar",
  409. "de.ub0r.android.callmeter", "com.call.recorder",
  410. "com.wordpress.sarfraznawaz.callerdetails", "com.integralblue.callerid",
  411. "com.android.camera2", "campyre.android", "com.dozingcatsoftware.cameratimer",
  412. "com.jadn.cc", "me.kuehle.carreport", "org.systemcall.scores",
  413. "com.ridgelineapps.resdicegame", "com.nolanlawson.logcat", "com.github.cetoolbox",
  414. "fr.strasweb.asso", "com.linkomnia.android.Changjie", "org.atai.TessUI",
  415. "com.kkinder.charmap", "com.googlecode.chartdroid",
  416. "info.guardianproject.otr.app.im", "org.zephyrsoft.checknetwork",
  417. "jwtc.android.chess", "cz.hejl.chesswalk", "org.hekmatof.chesswatch",
  418. "org.scoutant.cc", "com.nilhcem.frcndict", "com.nolanlawson.chordreader",
  419. "net.pmarks.chromadoze", "me.bpear.chromeapkpackager",
  420. "us.lindanrandy.cidrcalculator", "name.starnberger.guenther.android.cbw",
  421. "com.sapos_aplastados.game.clash_of_balls", "de.qspool.clementineremote",
  422. "de.ub0r.android.clipboardbeam", "com.ssaurel.clocklw", "org.floens.chan",
  423. "dk.mide.fas.cmnightlies", "de.fmaul.android.cmis", "com.banasiak.coinflip",
  424. "com.banasiak.coinflipext.example", "com.coinbase.android",
  425. "com.brianco.colorclock", "com.color.colornamer", "com.nauj27.android.colorpicker",
  426. "org.androidsoft.coloring", "org.gringene.colourclock", "net.kervala.comicsreader",
  427. "com.sgr_b2.compass", "net.micode.compass", "org.dyndns.fules.ck",
  428. "org.gringene.concentricclock", "org.connectbot", "de.measite.contactmerger",
  429. "com.appengine.paranoid_android.lost", "com.boombuler.widgets.contacts",
  430. "com.github.nutomic.controldlna", "eu.siacs.conversations", "org.coolreader",
  431. "com.dconstructing.cooper", "se.johanhil.clipboard", "ru.o2genum.coregame",
  432. "net.vivekiyer.GAL", "com.example.CosyDVR", "de.mreiter.countit",
  433. "com.cr5315.cfdc", "ch.fixme.cowsay", "com.qubling.sidekick",
  434. "com.bvalosek.cpuspy", "com.github.alijc.cricketsalarm", "groomiac.crocodilenote",
  435. "org.eehouse.android.xw4", "org.nick.cryptfs.passwdmanager", "com.csipsimple",
  436. "com.hykwok.CurrencyConverter", "com.elsewhat.android.currentwallpaper",
  437. "com.manor.currentwidget", "net.cyclestreets", "org.mult.daap",
  438. "com.bottleworks.dailymoney", "org.jessies.dalvikexplorer", "com.darknessmap",
  439. "net.nurik.roman.dashclock",
  440. "it.gmariotti.android.apps.dashclock.extensions.battery", "com.mridang.cellinfo",
  441. "net.logomancy.dashquotes.civ5", "me.malladi.dashcricket", "com.dwak.lastcall",
  442. "de.bashtian.dashclocksunrise", "com.mridang.wifiinfo", "dasher.android",
  443. "com.umang.dashnotifier", "at.bitfire.davdroid", "net.czlee.debatekeeper",
  444. "org.dyndns.sven_ola.debian_kit", "net.debian.debiandroid", "com.wentam.defcol",
  445. "com.serone.desktoplabel", "com.f2prateek.dfg", "org.dnaq.dialer2",
  446. "jpf.android.diary", "com.voidcode.diasporawebclient",
  447. "com.edwardoyarzun.diccionario", "de.kugihan.dictionaryformids.hmi_android",
  448. "si.modrajagoda.didi", "net.logomancy.diedroid",
  449. "kaljurand_at_gmail_dot_com.diktofon", "in.shick.diode",
  450. "com.google.android.diskusage", "to.networld.android.divedroid",
  451. "org.diygenomics.pg", "org.sufficientlysecure.viewer",
  452. "org.sufficientlysecure.viewer.fontpack", "com.dozingcatsoftware.dodge",
  453. "org.katsarov.dofcalc", "org.dolphinemu.dolphinemu", "us.bravender.android.dongsa",
  454. "net.iowaline.dotdash", "de.stefan_oltmann.kaesekaestchen", "steele.gerry.dotty",
  455. "fr.xtof54.dragonGoApp", "com.drismo", "com.xatik.app.droiddraw.client",
  456. "jackpal.droidexaminer", "edu.rit.poe.atomix", "org.petero.droidfish",
  457. "org.beide.droidgain", "org.jtb.droidlife", "com.mkf.droidsat", "org.droidseries",
  458. "org.droidupnp", "com.googlecode.droidwall", "de.delusions.measure",
  459. "com.shurik.droidzebra", "de.onyxbits.drudgery", "ch.dissem.android.drupal",
  460. "github.daneren2005.dsub", "se.johanhil.duckduckgo",
  461. "com.duckduckgo.mobile.android", "it.ecosw.dudo", "org.dynalogin.android",
  462. "org.uaraven.e", "com.seb.SLWP", "com.seb.SLWPmaps", "net.pejici.easydice",
  463. "de.audioattack.openlink", "app.easytoken", "com.f0x.eddymalou",
  464. "org.congresointeractivo.elegilegi", "com.ultramegatech.ey",
  465. "com.blntsoft.emailpopup", "com.kibab.android.EncPassChanger",
  466. "org.epstudios.epmobile", "org.jamienicol.episodes",
  467. "com.mirasmithy.epochlauncher", "it.angrydroids.epub3reader", "it.iiizio.epubator",
  468. "com.googlecode.awsms", "com.mehmetakiftutuncu.eshotroid",
  469. "com.googlecode.eyesfree.espeak", "com.sweetiepiggy.everylocale",
  470. "de.pinyto.exalteddicer", "org.kost.externalip", "ch.hsr.eyecam",
  471. "com.google.marvin.shell", "org.fdroid.fdroid",
  472. "com.easwareapps.f2lflap2lock_adfree", "faenza.adw.theme", "org.balau.fakedawn",
  473. "de.stefan_oltmann.falling_blocks", "com.codebutler.farebot", "org.ligi.fast",
  474. "com.mod.android.widget.fbcw", "org.fastergps",
  475. "org.geometerplus.zlibrary.ui.android",
  476. "org.geometerplus.fbreader.plugin.local_opds_scanner",
  477. "org.geometerplus.fbreader.plugin.tts", "com.hyperionics.fbreader.plugin.tts_plus",
  478. "net.micode.fileexplorer", "com.cyanogenmod.filemanager.ics",
  479. "com.michaldabski.filemanager", "com.github.wdkapps.fillup",
  480. "se.erikofsweden.findmyphone", "org.mozilla.firefox", "com.ten15.diyfish",
  481. "org.mysociety.FixMyStreet", "uk.co.danieljarvis.android.flashback",
  482. "com.nightshadelabs.anotherbrowser", "com.studio332.flickit",
  483. "com.gmail.charleszq", "fi.harism.wallpaper.flier", "org.aja.flightmode",
  484. "dk.nindroid.rss", "genius.mohammad.floating.stickies", "net.fred.feedex",
  485. "fr.xplod.focal", "com.oakley.fon", "com.sputnik.wispr", "ro.ieval.fonbot",
  486. "net.phunehehe.foocam", "com.iazasoft.footguy", "org.jsharkey.sky",
  487. "it.andreascarpino.forvodroid", "be.digitalia.fosdem",
  488. "de.b0nk.fp1_epo_autoupdate", "pt.isec.tp.am",
  489. "com.blogspot.tonyatkins.freespeech", "org.fedorahosted.freeotp",
  490. "de.cwde.freeshisen", "nf.frex.android", "de.wikilab.android.friendica01",
  491. "de.serverfrog.pw.android", "org.froscon.schedule", "com.frostwire.android",
  492. "org.jfedor.frozenbubble", "be.ppareit.swiftp_free", "com.easwareapps.g2l",
  493. "com.nesswit.galbijjimsearcher", "com.traffar.game_of_life", "com.androidemu.gba",
  494. "com.tobykurien.google_news", "com.androidemu.gbc", "com.gcstar.scanner",
  495. "com.gcstar.viewer", "com.jeffboody.GearsES2eclair",
  496. "com.namsor.api.samples.gendre", "de.onyxbits.geobookmark", "pl.nkg.geokrety",
  497. "se.danielj.geometridestroyer", "eu.hydrologis.geopaparazzi",
  498. "org.herrlado.geofonts", "com.github.ruleant.getback_gps", "at.bitfire.gfxtablet",
  499. "com.ghostsq.commander", "com.ghostsq.commander.samba",
  500. "com.ghostsq.commander.sftp", "net.gaast.giggity", "info.guardianproject.gilga",
  501. "com.github.mobile", "com.timvdalen.gizmooi", "com.glTron",
  502. "zame.GloomyDungeons.opensource.game", "com.kaeruct.glxy", "de.duenndns.gmdice",
  503. "org.gmote.client.android", "org.gnucash.android", "info.guardianproject.gpg",
  504. "org.ligi.gobandroid_hd", "com.googlecode.gogodroid",
  505. "org.wroot.android.goldeneye", "com.traffar.gomoku", "net.sf.crypt.gort",
  506. "com.mendhak.gpslogger", "com.gpstether", "com.Bisha.TI89EmuDonation",
  507. "org.cyanogenmod.great.freedom", "it.greenaddress.cordova", "org.gfd.gsmlocation",
  508. "de.srlabs.gsmmap", "com.googlecode.gtalksms", "ru.zxalexis.ugaday",
  509. "com.gulshansingh.hackerlivewallpaper", "org.pocketworkstation.pckeyboard",
  510. "net.sf.times", "org.durka.hallmonitor", "com.smerty.ham", "net.tapi.handynotes",
  511. "ca.mimic.apphangar", "com.hobbyone.HashDroid", "com.ginkel.hashit",
  512. "byrne.utilities.hashpass", "com.zaren", "com.jakebasile.android.hearingsaver",
  513. "ca.ddaly.android.heart", "com.vanderbie.heart_rate_monitor",
  514. "com.jwetherell.heart_rate_monitor", "fi.testbed2", "com.borneq.heregpslocation",
  515. "net.damsy.soupeaucaillou.heriswap", "com.sam.hex",
  516. "org.gitorious.jamesjrh.isokeys", "com.manuelmaly.hn", "com.gluegadget.hndroid",
  517. "com.omegavesko.holocounter", "com.tortuca.holoken",
  518. "com.dynamicg.homebuttonlauncher", "com.naholyr.android.horairessncf",
  519. "it.andreascarpino.hostisdown", "com.nilhcem.hostseditor",
  520. "com.smorgasbork.hotdeath", "net.sf.andhsli.hotspotlogin",
  521. "com.bobbyrne01.howfardoyouswim", "hsware.HSTempo", "org.jtb.httpmon",
  522. "eu.woju.android.packages.hud", "de.nico.ha_manager", "com.roguetemple.hydroid",
  523. "com.frankcalise.h2droid", "de.boesling.hydromemo", "com.roguetemple.hyperroid",
  524. "com.ancantus.HYPNOTOAD", "com.kostmo.wallpaper.spiral", "net.i2p.android.router",
  525. "com.germainz.identiconizer", "com.dozuki.ifixit", "com.cradle.iitc_mobile",
  526. "eu.e43.impeller", "am.ed.importcontacts", "org.libreoffice.impressremote",
  527. "com.shahul3d.indiasatelliteweather", "org.smc.inputmethod.indic",
  528. "net.luniks.android.inetify", "com.bri1.soundbored", "com.silentlexx.instead",
  529. "uk.co.ashtonbrsc.android.intentintercept", "org.smblott.intentradio",
  530. "org.safermobile.intheclear", "to.doc.android.ipv6config",
  531. "org.woltage.irssiconnectbot", "org.valos.isolmoa", "com.github.egonw.isotopes",
  532. "de.tui.itlogger", "com.teleca.jamendo", "com.nolanlawson.jnameconverter",
  533. "julianwi.javainstaller", "com.achep.widget.jellyclock", "com.jlyr",
  534. "com.jonglen7.jugglinglab", "jupiter.broadcasting.live.tv",
  535. "uk.co.jarofgreen.JustADamnCompass", "jp.co.kayo.android.localplayer",
  536. "jp.co.kayo.android.localplayer.ds.ampache",
  537. "jp.co.kayo.android.localplayer.ds.podcast", "com.brocktice.JustSit",
  538. "com.fsck.k9", "de.cketti.dashclock.k9", "vnd.blueararat.kaleidoscope6",
  539. "com.leafdigital.kanji.android", "com.matteopacini.katana",
  540. "org.kde.kdeconnect_tp", "net.lardcave.keepassnfc", "com.android.keepass",
  541. "com.seawolfsanctuary.keepingtracks", "com.nolanlawson.keepscore",
  542. "de.enaikoon.android.keypadmapper3", "com.concentricsky.android.khan",
  543. "com.leinardi.kitchentimer", "org.nerdcircus.android.klaxon", "at.dasz.KolabDroid",
  544. "org.kontalk", "org.kwaak3", "pro.oneredpixel.l9droid", "eu.prismsw.lampshade",
  545. "com.adstrosoftware.launchappops", "com.android.launcher3",
  546. "com.example.android.maxpapers", "de.danielweisser.android.ldapsync",
  547. "net.fercanet.LNM", "org.pulpdust.lesserpad", "net.healeys.lexic",
  548. "com.mykola.lexinproject", "com.martinborjesson.o2xtouchlednotifications",
  549. "de.grobox.liberario", "fm.libre.droid", "acr.browser.barebones",
  550. "acr.browser.lightning", "info.guardianproject.lildebi",
  551. "com.willhauck.linconnectclient", "org.peterbaldwin.client.android.tinyurl",
  552. "org.linphone", "it.mn.salvi.linuxDayOSM", "com.xenris.liquidwarsos",
  553. "de.onyxbits.listmyapps", "name.juodumas.ext_kbd_lithuanian", "com.lligainterm",
  554. "ch.rrelmy.android.locationcachemap", "in.shick.lockpatterngenerator",
  555. "it.reyboz.screenlock", "sk.madzik.android.logcatudp",
  556. "in.shubhamchaudhary.logmein", "com.powerpoint45.lucidbrowser",
  557. "org.lumicall.android", "jpf.android.magiadni", "com.anoshenko.android.mahjongg",
  558. "info.kesavan.malartoon", "uk.ac.ed.inf.mandelbrotmaps", "com.zapta.apps.maniana",
  559. "be.quentinloos.manille", "com.chmod0.manpages", "net.pierrox.mcompass",
  560. "org.dsandler.apps.markers", "org.evilsoft.pathfinder.reference",
  561. "de.ph1b.audiobook", "net.cactii.mathdoku", "org.jessies.mathdroid",
  562. "org.aminb.mathtools.app", "jp.yhonda", "org.projectmaxs.main",
  563. "org.projectmaxs.module.alarmset", "org.projectmaxs.module.bluetooth",
  564. "org.projectmaxs.module.bluetoothadmin", "org.projectmaxs.module.clipboard",
  565. "org.projectmaxs.module.contactsread", "org.projectmaxs.module.fileread",
  566. "org.projectmaxs.module.filewrite", "org.projectmaxs.module.locationfine",
  567. "org.projectmaxs.module.misc", "org.projectmaxs.module.nfc",
  568. "org.projectmaxs.module.notification", "org.projectmaxs.module.phonestateread",
  569. "org.projectmaxs.module.ringermode", "org.projectmaxs.module.shell",
  570. "org.projectmaxs.module.smsnotify", "org.projectmaxs.module.smsread",
  571. "org.projectmaxs.module.smssend", "org.projectmaxs.module.smswrite",
  572. "org.projectmaxs.module.wifiaccess", "org.projectmaxs.module.wifichange",
  573. "org.projectmaxs.transport.xmpp", "com.harleensahni.android.mbr",
  574. "eu.johncasson.meerkatchallenge", "org.billthefarmer.melodeon",
  575. "org.zakky.memopad", "org.androidsoft.games.memory.kids", "net.asceai.meritous",
  576. "com.intervigil.micdroid", "com.midisheetmusic", "de.syss.MifareClassicTool",
  577. "com.rhiannonweb.android.migrainetracker", "com.evancharlton.mileage",
  578. "com.xlythe.minecraftclock", "it.reyboz.minesweeper", "com.example.sshtry",
  579. "jp.gr.java_conf.hatalab.mnv", "nitezh.ministock", "org.kde.necessitas.ministro",
  580. "com.jaygoel.virginminuteschecker", "de.azapps.mirakelandroid",
  581. "de.azapps.mirakel.dashclock", "org.bitbucket.tickytacky.mirrormirror",
  582. "de.homac.Mirrored", "org.mixare", "edu.harvard.android.mmskeeper",
  583. "org.tbrk.mnemododo", "com.matburt.mobileorg", "com.gs.mobileprint",
  584. "org.n52.sosmobileclient", "com.dngames.mobilewebcam", "com.mobiperf",
  585. "dev.drsoran.moloko", "ivl.android.moneybalance",
  586. "com.tobiaskuban.android.monthcalendarwidgetfoss", "org.montrealtransit.android",
  587. "org.montrealtransit.android.schedule.stmbus", "akk.astro.droid.moonphase",
  588. "org.epstudios.morbidmeter", "org.mosspaper", "org.cry.otp", "com.morlunk.mountie",
  589. "com.spazedog.mounts2sd", "com.nutomic.zertman",
  590. "org.logicallycreative.movingpolygons", "org.mozilla.mozstumbler",
  591. "com.uraroji.garage.android.mp3recvoice", "com.namelessdev.mpdroid",
  592. "org.bc_bd.mrwhite", "com.fgrim.msnake", "com.gelakinetic.mtgfam",
  593. "com.hectorone.multismssender", "org.tamanegi.wallpaper.multipicture.dnt",
  594. "kr.softgear.multiping", "com.artifex.mupdfdemo",
  595. "paulscode.android.mupen64plusae", "com.android.music",
  596. "com.danielme.muspyforandroid", "org.mustard.android", "org.mumod.android",
  597. "net.nurik.roman.muzei", "net.ebt.muzei.miyazaki",
  598. "com.projectsexception.myapplist.open", "net.dahanne.banq.notifications",
  599. "org.totschnig.myexpenses", "com.futonredemption.mylocation", "ch.fixme.status",
  600. "i4nc4mp.myLock", "org.aykit.MyOwnNotes", "org.mythdroid",
  601. "tkj.android.homecontrol.mythmote", "org.coolfrood.mytronome",
  602. "name.livitski.games.puzzle.android", "de.laxu.apps.nachtlagerdownloader",
  603. "com.nanoconverter.zlab", "fr.miximum.napply", "org.vono.narau",
  604. "com.example.muzei.muzeiapod", "de.msal.muzei.nationalgeographic",
  605. "org.navitproject.navit", "org.ndeftools.boilerplate", "jp.sfjp.webglmol.NDKmol",
  606. "com.opendoorstudios.ds4droid", "com.kvance.Nectroid", "jp.sawada.np2android",
  607. "com.androidemu.nes", "net.jaqpot.netcounter", "free.yhc.netmbuddy",
  608. "org.ncrmnt.nettts", "de.mangelow.network", "info.lamatricexiste.network",
  609. "com.googlecode.networklog", "org.gc.networktester", "com.newsblur",
  610. "jp.softstudio.DriversLicenseReader", "pl.net.szafraniec.NFCKey",
  611. "se.anyro.nfc_reader", "pl.net.szafraniec.NFCTagmaker", "com.sinpo.xnfc",
  612. "com.digitallizard.nicecompass", "net.gorry.android.input.nicownng",
  613. "ru.glesik.nostrangersms", "it.sineo.android.noFrillsCPUClassic",
  614. "com.netthreads.android.noiz2", "pe.moe.nori", "info.guardianproject.notepadbot",
  615. "bander.notepad", "ru.ttyh.neko259.notey", "org.jmoyer.NotificationPlus",
  616. "apps.droidnotify", "net.thauvin.erik.android.noussd", "org.npr.android.news",
  617. "mobi.cyann.nstools", "org.ntpsync", "com.notriddle.null_launcer",
  618. "com.numix.calculator", "com.numix.icons_circle", "org.jfedor.nxtremotecontrol",
  619. "com.powerje.nyan", "com.palliser.nztides", "dk.jens.backup",
  620. "com.valleytg.oasvn.android", "eu.lighthouselabs.obd.reader",
  621. "nz.gen.geek_central.ObjViewer", "trikita.obsqr", "edu.sfsu.cs.orange.ocr",
  622. "com.gh4a", "org.odk.collect.android", "org.sufficientlysecure.localcalendar",
  623. "com.sli.ohmcalc", "org.openintents.about", "org.openintents.filemanager",
  624. "org.openintents.safe", "edu.nyu.cs.omnidroid.app", "org.hanenoshino.onscripter",
  625. "com.euedge.openaviationmap.android", "pro.dbro.bart",
  626. "net.sourceforge.opencamera", "org.brandroid.openmanager",
  627. "io.github.sanbeg.flashlight", "com.nexes.manager", "de.skubware.opentraining",
  628. "com.dje.openwifinetworkremover", "be.brunoparmentier.openbikesharing.app",
  629. "app.openconnect", "at.tomtasche.reader", "org.opengpx",
  630. "org.sufficientlysecure.keychain", "de.jdsoft.law", "org.openlp.android",
  631. "de.uni_potsdam.hpi.openmensa", "jp.redmine.redmineclient",
  632. "cz.romario.opensudoku", "edu.killerud.kitchentimer", "de.blinkt.openvpn",
  633. "de.schaeuffelhut.android.openvpn", "org.ale.openwatch", "com.vwp.owmap",
  634. "com.vwp.owmini", "jp.co.omronsoft.openwnn", "com.googlecode.openwnn.legacy",
  635. "orbitlivewallpaperfree.puzzleduck.com", "org.torproject.android",
  636. "org.ethack.orwall", "info.guardianproject.browser", "com.eolwral.osmonitor",
  637. "net.oschina.app", "org.billthefarmer.scope",
  638. "ch.nexuscomputing.android.osciprimeics", "net.osmand.srtmPlugin.paid",
  639. "net.osmand.parkingPlugin", "net.osmand.plus", "net.anzix.osm.upload",
  640. "me.guillaumin.android.osmtracker", "de.ub0r.android.otpdroid",
  641. "com.traffar.oware", "com.owncloud.android", "de.luhmer.owncloudnewsreader",
  642. "nu.firetech.android.pactrack", "it.rgp.nyagua.pafcalc",
  643. "org.moparisthebest.pageplus", "net.nightwhistler.pageturner",
  644. "com.cybrosys.palmcalc", "com.niparasc.papanikolis", "ru.valle.btc",
  645. "com.paranoid.ParanoidWallpapers", "org.ligi.passandroid", "com.passcard",
  646. "gg.mw.passera", "com.jefftharris.passwdsafe", "com.uploadedlobster.PwdHash",
  647. "com.zeapo.pwdstore", "org.passwordmaker.android", "byrne.utilities.pasteedroid",
  648. "com.th.XenonWallpapers", "io.github.droidapps.pdfreader",
  649. "name.bagi.levente.pedometer", "org.jf.Penroser", "fi.harism.wallpaper.flowers",
  650. "mobi.omegacentauri.PerApp", "com.brewcrewfoo.performance",
  651. "com.frozendevs.periodictable", "de.arnowelzel.android.periodical",
  652. "org.androidsoft.app.permission", "com.FireFart.Permissions2",
  653. "com.byagowi.persiancalendar", "org.dyndns.ipignoli.petronius",
  654. "org.lf_net.pgpunlocker", "de.onyxbits.photobookmark",
  655. "unisiegen.photographers.activity", "com.ruesga.android.wallpapers.photophase",
  656. "org.esteban.piano", "org.musicbrainz.picard.barcodescanner", "com.pindroid",
  657. "com.boombuler.piraten.map", "com.rj.pixelesque", "info.guardianproject.pixelknot",
  658. "com.morlunk.mumbleclient", "eu.lavarde.pmtd", "de.onyxbits.pocketbandit",
  659. "com.zachrattner.pockettalk", "edu.cmu.pocketsphinx.demo", "com.axelby.podax",
  660. "com.polipoid", "com.politedroid", "com.hlidskialf.android.pomodoro",
  661. "com.kpz.pomodorotasks.activity", "com.tinkerlog.android.pongtime",
  662. "org.sixgun.ponyexpress", "com.xargsgrep.portknocker", "net.tevp.postcode",
  663. "org.ppsspp.ppsspp", "com.proch.practicehub", "android.game.prboom",
  664. "fr.simon.marquis.preferencesmanager", "damo.three.ie",
  665. "com.gracecode.android.presentation", "com.falconware.prestissimo", "org.primftpd",
  666. "org.us.andriod", "org.okfn.pod", "ro.ui.pttdroid", "org.macno.puma",
  667. "com.boztalay.puppyframeuid", "com.purplefoto.pfdock", "org.example.pushupbuddy",
  668. "name.boyle.chris.sgtpuzzles", "com.littlebytesofpi.pylauncher",
  669. "org.pyload.android.client", "com.zagayevskiy.pacman",
  670. "com.lgallardo.qbittorrentclient", "com.android.quake", "com.jeyries.quake2",
  671. "com.iskrembilen.quasseldroid", "com.qsp.player", "com.bwx.bequick",
  672. "com.hughes.android.dictionary", "vu.de.urpool.quickdroid", "be.geecko.QuickLyric",
  673. "net.vreeken.quickmsg", "com.lightbox.android.camera", "com.write.Quill",
  674. "es.cesar.quitesleep", "net.xenotropic.quizznworldcap", "com.radioreddit.android",
  675. "org.openbmap", "com.tmarki.comicmaker", "cc.rainwave.android",
  676. "be.norio.randomapp", "org.recentwidget", "au.com.wallaceit.reddinator",
  677. "com.btmura.android.reddit", "org.quantumbadger.redreader",
  678. "net.dahanne.android.regalandroid", "urbanstew.RehearsalAssistant",
  679. "com.reicast.emulator", "com.harasoft.relaunch", "com.wanghaus.remembeer",
  680. "net.noio.Reminder", "com.lostrealm.lembretes",
  681. "org.peterbaldwin.client.android.vlcremote", "de.onyxbits.remotekeyboard",
  682. "org.damazio.notifier", "com.vsmartcard.remotesmartcardreader.app",
  683. "remuco.client.android", "com.replica.replicaisland", "br.usp.ime.retrobreaker",
  684. "org.retroarch", "buet.rafi.dictionary", "fr.keuse.rightsalert",
  685. "org.hoi_polloi.android.ringcode", "com.ringdroid", "com.dririan.RingyDingyDingy",
  686. "fr.hnit.riverferry", "se.norenh.rkfread", "com.robert.maps", "org.rmll",
  687. "info.staticfree.android.robotfindskitten", "com.abcdjdj.rootverifier",
  688. "de.zieren.rot13", "org.penghuang.tools.rotationlock",
  689. "com.spydiko.rotationmanager_foss", "mohammad.adib.roundr", "com.ath0.rpn",
  690. "ru0xdc.rtkgps", "de.steinpfeffer.rdt", "net.aangle.rvclock", "org.sagemath.droid",
  691. "com.cepmuvakkit.times", "monakhv.android.samlib",
  692. "com.maxfierke.sandwichroulette", "cri.sanity", "it.sasabz.android.sasabus",
  693. "org.ligi.satoshiproof", "com.vonglasow.michael.satstat",
  694. "org.chorem.android.saymytexts", "org.crocodile.sbautologin",
  695. "org.ale.scanner.zotero", "org.scid.android", "com.lukekorth.screennotifications",
  696. "com.jotabout.screeninfo", "com.gmail.altakey.effy",
  697. "net.jjc1138.android.scrobbler", "org.scummvm.scummvm", "gr.ndre.scuttloid",
  698. "com.gmail.jerickson314.sdscanner", "com.seafile.seadroid",
  699. "com.seafile.seadroid2", "com.ideasfrombrain.search_based_launcher_v2",
  700. "com.scottmain.android.searchlight", "com.shadcat.secdroid",
  701. "com.doplgangr.secrecy", "fr.simon.marquis.secretcodes", "fr.seeks",
  702. "com.ariwilson.seismowallpaper", "mobi.omegacentauri.SendReduced",
  703. "com.ivanvolosyuk.sharetobrowser", "ru.gelin.android.sendtosd",
  704. "org.totschnig.sendwithftp", "de.onyxbits.sensorreadout", "at.univie.sensorium",
  705. "com.monead.games.android.sequence", "org.servalproject", "org.servDroid.web",
  706. "net.sourceforge.servestream", "me.sheimi.sgit", "org.emergent.android.weave",
  707. "net.sylvek.sharemyposition", "com.MarcosDiez.shareviahttp", "com.android.shellms",
  708. "com.boombuler.games.shift", "name.soulayrol.rhaa.sholi",
  709. "com.github.nicolassmith.urlevaluator", "com.totsp.crossword.shortyz",
  710. "com.showmehills", "be.ppareit.shutdown", "org.sickstache", "kr.hybdms.sidepanel",
  711. "org.billthefarmer.siggen", "ru.neverdark.silentnight", "com.better.alarm",
  712. "com.brentpanther.bitcoinwidget", "nl.ttys0.simplec25k", "com.chessclock.android",
  713. "com.casimirlab.simpleDeadlines", "com.mareksebera.simpledilbert",
  714. "com.dnielfe.manager", "com.adam.aslfms", "ee.smkv.calc.loan",
  715. "com.poloure.simplerss", "nl.mpcjanssen.simpletask", "kdk.android.simplydo",
  716. "eu.siebeck.sipswitch", "org.sipdroid.sipua", "com.sismics.reader",
  717. "com.google.android.stardroid", "eu.flatworld.android.slider",
  718. "de.shandschuh.slightbackup", "org.androidsoft.games.slowit",
  719. "tritop.androidSLWCpuWidget", "tritop.android.SLWTrafficMeterWidget",
  720. "wb.receiptspro", "com.unleashyouradventure.swaccess", "com.java.SmokeReducer",
  721. "com.zegoggles.smssync", "bughunter2.smsfilter", "net.everythingandroid.smspopup",
  722. "de.ub0r.android.smsdroid", "org.addhen.smssync", "com.mobilepearls.sokoban",
  723. "com.kmagic.solitaire", "org.andglkmod.hunkypunk", "sonoroxadc.garethmurfin.co.uk",
  724. "com.htruong.inputmethod.latin", "com.roozen.SoundManagerv2",
  725. "net.micode.soundrecorder", "com.akop.bach", "org.sparkleshare.android",
  726. "de.shandschuh.sparserss", "mixedbit.speechtrainer", "net.codechunk.speedofsound",
  727. "fly.speedmeter.grub", "isn.fly.speedmeter", "SpeedoMeterApp.main",
  728. "net.majorkernelpanic.spydroid", "csci567.squeez", "uk.org.ngo.squeezer",
  729. "org.sufficientlysecure.standalonecalendar", "fr.bellev.stdatmosphere",
  730. "com.piwi.stickeroid", "net.stkaddons.viewer", "com.nma.util.sdcardtrac",
  731. "com.gokhanmoral.stweaks.app", "net.sourceforge.subsonic.androidapp",
  732. "org.subsurface", "in.ac.dtu.subtlenews", "com.app2go.sudokufree", "de.sudoq",
  733. "org.sudowars", "net.pejici.summation", "info.staticfree.SuperGenPass",
  734. "com.koushikdutta.superuser", "com.omegavesko.sutransplus",
  735. "biz.codefuture.svgviewer", "com.nutomic.syncthingandroid",
  736. "org.ciasaboark.tacere", "com.kyakujin.android.tagnotepad",
  737. "com.weicheng.taipeiyoubikeoffline", "com.google.android.marvin.talkback",
  738. "com.ciarang.tallyphant", "org.tof", "com.acvarium.tasclock", "org.dmfs.tasks",
  739. "org.tasks", "goo.TeaTimer", "net.chilon.matt.teacup", "fr.xgouchet.texteditor",
  740. "org.telegram.messenger", "com.jmartin.temaki", "jackpal.androidterm",
  741. "de.schildbach.wallet_test", "org.paulmach.textedit", "de.onyxbits.textfiction",
  742. "com.myopicmobile.textwarrior.android", "pl.narfsoftware.thermometer",
  743. "com.threedlite.livePolys", "org.ironrabbit.bhoboard", "org.ironrabbit",
  744. "de.smasi.tickmate", "com.gladis.tictactoe", "org.tigase.messenger.phone.pro",
  745. "com.lecz.android.tiltmazes", "org.dpadgett.timer", "com.alfray.timeriffic",
  746. "com.tastycactus.timesheet", "org.poirsouille.tinc_gui",
  747. "com.danvelazco.fbwrapper", "org.tint", "org.tint.adblock",
  748. "com.xmission.trevin.android.todo", "org.chrisbailey.todo",
  749. "com.earthblood.tictactoe", "com.dwalkes.android.toggleheadset2", "org.tomdroid",
  750. "ch.hgdev.toposuite", "com.colinmcdonough.android.torch", "com.piratebayfree",
  751. "com.amphoras.tpthelper", "org.traccar.client", "org.zephyrsoft.trackworktime",
  752. "org.softcatala.traductor", "com.aselalee.trainschedule",
  753. "com.andybotting.tramhunter", "org.transdroid.full", "org.transdroid",
  754. "org.transdroid.search", "fr.ybo.transportsbordeaux", "fr.ybo.transportsrennes",
  755. "com.lonepulse.travisjr", "de.koelle.christian.trickytripper",
  756. "org.hermit.tricorder", "caldwell.ben.trolly", "fr.strasweb.campus",
  757. "com.unwrappedapps.android.wallpaper.creative", "org.tryton.client",
  758. "org.segin.ttleditor", "org.ttrssreader", "com.seavenois.tetris",
  759. "com.dalthed.tucan", "tuioDroid.impl", "de.tum.in.tumcampus",
  760. "org.billthefarmer.tuner", "org.tunesremote", "com.tunes.viewer",
  761. "com.maskyn.fileeditorpro", "com.drodin.tuxrider", "org.me.tvhguide",
  762. "org.mariotaku.twidere", "org.mariotaku.twidere.extension.twitlonger",
  763. "com.reddyetwo.hashmypass.app", "com.twsitedapps.homemanager",
  764. "szelok.app.twister", "com.googamaphone.typeandspeak", "org.zeitgeist.movement",
  765. "ro.weednet.contactssync", "org.madore.android.unicodeMap",
  766. "info.staticfree.android.units", "net.ralphbroenink.muzei.unsplash",
  767. "com.u17od.upm", "cc.co.eurdev.urecorder", "com.threedlite.urforms",
  768. "com.bretternst.URLazy", "me.hda.urlhda", "aws.apps.usbDeviceEnumerator",
  769. "com.threedlite.userhash.location", "ch.blinkenlights.android.vanilla",
  770. "org.kreed.vanilla", "com.dozingcatsoftware.bouncy", "de.blau.android",
  771. "net.momodalo.app.vimtouch", "com.code.android.vibevault",
  772. "com.pheelicks.visualizer", "org.videolan.vlc", "com.vlille.checker",
  773. "com.pilot51.voicenotify", "de.jurihock.voicesmith",
  774. "mancioboxblog.altervista.it.volumecontrol",
  775. "org.projectvoodoo.simplecarrieriqdetector", "org.projectvoodoo.otarootkeeper",
  776. "org.projectvoodoo.screentestpatterns", "com.poinsart.votar", "org.vudroid",
  777. "sk.vx.connectbot", "net.mafro.android.wakeonlan", "fr.gaulupeau.apps.InThePoche",
  778. "de.markusfisch.android.wavelines", "ru.gelin.android.weather.notification",
  779. "ru.gelin.android.weather.notification.skin.blacktext",
  780. "ru.gelin.android.weather.notification.skin.whitetext",
  781. "de.geeksfactory.opacclient", "net.solutinno.websearch", "de.ub0r.android.websms",
  782. "de.ub0r.android.websms.connector.gmx",
  783. "de.ub0r.android.websms.connector.smspilotru", "com.ubergeek42.WeechatAndroid",
  784. "jp.co.qsdn.android.jinbei3d", "fr.ludo1520.whatexp",
  785. "org.wheelmap.android.online", "org.edunivers.whereami", "seanfoy.wherering",
  786. "de.freewarepoint.whohasmystuff", "org.cprados.wificellmanager",
  787. "ru.glesik.wifireminders", "org.androidappdev.wifiwidget",
  788. "org.marcus905.wifi.ace", "de.j4velin.wifiAutoOff", "teaonly.droideye",
  789. "org.wahtod.wififixer", "net.sourceforge.wifiremoteplay", "com.volosyukivan",
  790. "net.wigle.wigleandroid", "org.wikilovesmonuments",
  791. "de.mbutscher.wikiandpad.alphabeta", "org.wikimedia.commons",
  792. "org.wikimedia.commons.muzei", "org.wikipedia", "fr.renzo.wikipoff",
  793. "org.github.OxygenGuide", "org.wiktionary", "uk.org.cardboardbox.wonderdroid",
  794. "com.developfreedom.wordpowermadeeasy", "org.wordpress.android",
  795. "eu.vranckaert.worktime", "com.irahul.worldclock", "com.sigseg.android.worldmap",
  796. "mazechazer.android.wottankquiz", "org.nick.wwwjdic", "au.com.darkside.XServer",
  797. "com.xabber.androiddev", "org.xbmc.android.remote", "org.xcsoar",
  798. "net.bytten.xkcdviewer", "org.helllabs.android.xmp", "biz.gyrus.yaab", "de.yaacc",
  799. "org.yaaic", "org.yabause.android", "uobikiemukot.yaft", "com.tum.yahtzee",
  800. "org.yaxim.androidclient", "fi.harism.wallpaper.yinyang",
  801. "dentex.youtube.downloader", "com.yubico.yubiclip", "com.yubico.yubioath",
  802. "com.yubico.yubitotp", "de.antonfluegge.android.yubnubwidgetadfree",
  803. "com.gimranov.zandy.app", "org.zirco", "org.smerty.zooborns", "org.qii.weiciyuan",
  804. "com.googlecode.tcime",
  805. });
  806. }
  807. private void checkAntiFeatures(List<App> apps, Map<String, List<String>> expectedAntiFeatures) {
  808. for (App app : apps) {
  809. if (expectedAntiFeatures.containsKey(app.packageName)) {
  810. List<String> antiFeatures = expectedAntiFeatures.get(app.packageName);
  811. if (antiFeatures.isEmpty()) {
  812. assertNull(app.antiFeatures);
  813. } else {
  814. List<String> actualAntiFeatures = new ArrayList<>();
  815. Collections.addAll(actualAntiFeatures, app.antiFeatures);
  816. assertTrue(actualAntiFeatures.containsAll(antiFeatures));
  817. assertTrue(antiFeatures.containsAll(actualAntiFeatures));
  818. }
  819. }
  820. }
  821. }
  822. private void checkIncludedApps(List<App> actualApps, String[] expctedAppIds) {
  823. assertNotNull(actualApps);
  824. assertNotNull(expctedAppIds);
  825. assertEquals(actualApps.size(), expctedAppIds.length);
  826. for (String id : expctedAppIds) {
  827. boolean thisAppMissing = true;
  828. for (App app : actualApps) {
  829. if (TextUtils.equals(app.packageName, id)) {
  830. thisAppMissing = false;
  831. break;
  832. }
  833. }
  834. assertFalse(thisAppMissing);
  835. }
  836. }
  837. private void checkPushRequests(RepoDetails actualDetails) {
  838. final Object[] expectedPushRequestsIndex = new Object[]{
  839. "install", "org.fdroid.fdroid", 101002,
  840. "install", "org.fdroid.fdroid.privileged", null,
  841. "uninstall", "com.android.vending", null,
  842. "uninstall", "com.facebook.orca", -12345,
  843. "uninstall", null, null, // request with no data
  844. "install", "asdfasdfasdf", null, // non-existent app
  845. };
  846. checkIncludedApps(actualDetails.apps, new String[]{
  847. "org.fdroid.fdroid", "org.fdroid.fdroid.privileged",
  848. });
  849. List<RepoPushRequest> repoPushRequestList = actualDetails.repoPushRequestList;
  850. int i = 0;
  851. for (RepoPushRequest repoPushRequest : repoPushRequestList) {
  852. assertEquals(repoPushRequest.request, expectedPushRequestsIndex[i]);
  853. assertEquals(repoPushRequest.packageName, expectedPushRequestsIndex[i + 1]);
  854. assertEquals(repoPushRequest.versionCode, expectedPushRequestsIndex[i + 2]);
  855. i += 3;
  856. }
  857. }
  858. private void handlerTestSuite(Repo expectedRepo, RepoDetails actualDetails,
  859. int appCount, int apkCount, int maxAge, int version) {
  860. assertNotNull(actualDetails);
  861. assertFalse(TextUtils.isEmpty(actualDetails.signingCert));
  862. assertEquals(expectedRepo.signingCertificate.length(), actualDetails.signingCert.length());
  863. assertEquals(expectedRepo.signingCertificate, actualDetails.signingCert);
  864. assertFalse(FAKE_SIGNING_CERT.equals(actualDetails.signingCert));
  865. assertFalse(TextUtils.isEmpty(actualDetails.name));
  866. assertEquals(expectedRepo.name.length(), actualDetails.name.length());
  867. assertEquals(expectedRepo.name, actualDetails.name);
  868. assertFalse(TextUtils.isEmpty(actualDetails.description));
  869. assertEquals(expectedRepo.description.length(), actualDetails.description.length());
  870. assertEquals(expectedRepo.description, actualDetails.description);
  871. assertEquals(actualDetails.maxAge, maxAge);
  872. assertEquals(actualDetails.version, version);
  873. assertEquals(expectedRepo.timestamp, actualDetails.timestamp);
  874. List<App> apps = actualDetails.apps;
  875. assertNotNull(apps);
  876. assertEquals(apps.size(), appCount);
  877. for (App app : apps) {
  878. assertTrue("Added should have been set", app.added.getTime() > 0);
  879. assertTrue("Last Updated should have been set", app.lastUpdated.getTime() > 0);
  880. }
  881. List<Apk> apks = actualDetails.apks;
  882. assertNotNull(apks);
  883. assertEquals(apks.size(), apkCount);
  884. }
  885. @NonNull
  886. private RepoDetails getFromFile(String indexFilename) {
  887. return getFromFile(indexFilename, Repo.PUSH_REQUEST_IGNORE);
  888. }
  889. @NonNull
  890. private RepoDetails getFromFile(String indexFilename, int pushRequests) {
  891. return getFromFile(getClass().getClassLoader(), indexFilename, pushRequests);
  892. }
  893. @NonNull
  894. public static RepoDetails getFromFile(ClassLoader classLoader, String indexFilename, int pushRequests) {
  895. Log.i(TAG, "test file: " + classLoader.getResource(indexFilename));
  896. InputStream inputStream = classLoader.getResourceAsStream(indexFilename);
  897. return RepoDetails.getFromFile(inputStream, pushRequests);
  898. }
  899. private void writeResourceToObbDir(String assetName) throws IOException {
  900. InputStream input = getClass().getClassLoader().getResourceAsStream(assetName);
  901. String packageName = assetName.substring(assetName.indexOf("obb"),
  902. assetName.lastIndexOf('.'));
  903. File f = new File(App.getObbDir(packageName), assetName);
  904. FileUtils.copyToFile(input, f);
  905. input.close();
  906. }
  907. }