use of org.fdroid.fdroid.data.App in project fdroidclient by f-droid.
the class FDroidMetricsWorker method generateReport.
public static String generateReport(Context context) {
long weekStart = getReportingWeekStart();
CleanInsightsReport cleanInsightsReport = new CleanInsightsReport();
PackageManager pm = context.getPackageManager();
List<PackageInfo> packageInfoList = pm.getInstalledPackages(0);
Collections.sort(packageInfoList, new Comparator<PackageInfo>() {
@Override
public int compare(PackageInfo p1, PackageInfo p2) {
return p1.packageName.compareTo(p2.packageName);
}
});
App[] installedApps = InstalledAppProvider.Helper.all(context);
EVENTS.add(getDeviceEvent(weekStart, "isPrivilegedInstallerEnabled", Preferences.get().isPrivilegedInstallerEnabled()));
EVENTS.add(getDeviceEvent(weekStart, "Build.VERSION.SDK_INT", Build.VERSION.SDK_INT));
if (Build.VERSION.SDK_INT >= 21) {
EVENTS.add(getDeviceEvent(weekStart, "Build.SUPPORTED_ABIS", Arrays.toString(Build.SUPPORTED_ABIS)));
}
for (PackageInfo packageInfo : packageInfoList) {
boolean found = false;
for (App app : installedApps) {
if (packageInfo.packageName.equals(app.packageName)) {
found = true;
break;
}
}
if (!found)
continue;
if (isTimestampInReportingWeek(weekStart, packageInfo.firstInstallTime)) {
addFirstInstallEvent(pm, packageInfo);
}
if (isTimestampInReportingWeek(weekStart, packageInfo.lastUpdateTime)) {
addLastUpdateTimeEvent(pm, packageInfo);
}
}
EVENTS.addAll(parseInstallHistoryCsv(context, weekStart));
cleanInsightsReport.events = EVENTS.toArray(new MatomoEvent[0]);
ObjectMapper mapper = new ObjectMapper();
mapper.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);
mapper.enable(SerializationFeature.INDENT_OUTPUT);
try {
return mapper.writeValueAsString(cleanInsightsReport);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
use of org.fdroid.fdroid.data.App in project fdroidclient by f-droid.
the class UpdatesAdapter method onKnownVulnLoadFinished.
private void onKnownVulnLoadFinished(Cursor cursor) {
knownVulnApps.clear();
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
knownVulnApps.add(new KnownVulnApp(activity, new App(cursor)));
cursor.moveToNext();
}
}
use of org.fdroid.fdroid.data.App in project fdroidclient by f-droid.
the class AntiFeaturesTest method allVulnerableButIgnored.
@Test
public void allVulnerableButIgnored() {
install(allVuln, 101);
List<App> installed = AppProvider.Helper.findInstalledAppsWithKnownVulns(context);
assertEquals(1, installed.size());
App app = installed.get(0);
AppPrefs prefs = app.getPrefs(context);
prefs.ignoreVulnerabilities = true;
AppPrefsProvider.Helper.update(context, app, prefs);
List<App> installedButIgnored = AppProvider.Helper.findInstalledAppsWithKnownVulns(context);
assertEquals(0, installedButIgnored.size());
}
use of org.fdroid.fdroid.data.App in project fdroidclient by f-droid.
the class Assert method insertApp.
public static App insertApp(Context context, String packageName, String name, ContentValues additionalValues) {
ContentValues values = new ContentValues();
values.put(AppMetadataTable.Cols.REPO_ID, 1);
values.put(AppMetadataTable.Cols.Package.PACKAGE_NAME, packageName);
values.put(AppMetadataTable.Cols.NAME, name);
// Required fields (NOT NULL in the database).
values.put(AppMetadataTable.Cols.SUMMARY, "test summary");
values.put(AppMetadataTable.Cols.DESCRIPTION, "test description");
values.put(AppMetadataTable.Cols.LICENSE, "GPL?");
values.put(AppMetadataTable.Cols.IS_COMPATIBLE, 1);
values.putAll(additionalValues);
// Don't hard code to 1, let consumers override it in additionalValues then ask for it back.
int repoId = values.getAsInteger(AppMetadataTable.Cols.REPO_ID);
Uri uri = AppProvider.getContentUri();
context.getContentResolver().insert(uri, values);
App app = AppProvider.Helper.findSpecificApp(context.getContentResolver(), packageName, repoId, AppMetadataTable.Cols.ALL);
assertNotNull(app);
return app;
}
use of org.fdroid.fdroid.data.App in project fdroidclient by f-droid.
the class IndexV1Updater method processIndexV1.
/**
* Parses the index and feeds it to the database via {@link Repo}, {@link App},
* and {@link Apk} instances. This uses {@link RepoPersister} to add the apps
* and packages to the database in {@link RepoPersister#saveToDb(App, List)}
* to write the {@link Repo}, and commit the whole thing in
* {@link RepoPersister#commit(ContentValues, long)}. One confusing thing about this
* whole process is that {@link RepoPersister} needs to first create and entry
* in the database, then fetch the ID from the database to populate
* {@link Repo#id}. That has to happen first, then the rest of the {@code Repo}
* data must be added later.
*
* @param indexInputStream {@link InputStream} to {@code index-v1.json}
* @param etag the {@code etag} value from HTTP headers
* @throws IOException
* @throws UpdateException
*/
public void processIndexV1(InputStream indexInputStream, JarEntry indexEntry, String etag) throws IOException, UpdateException {
Utils.Profiler profiler = new Utils.Profiler(TAG);
profiler.log("Starting to process index-v1.json");
ObjectMapper mapper = getObjectMapperInstance(repo.getId());
JsonFactory f = mapper.getFactory();
JsonParser parser = f.createParser(indexInputStream);
HashMap<String, Object> repoMap = null;
App[] apps = null;
Map<String, String[]> requests = null;
Map<String, List<Apk>> packages = null;
// go into the main object block
parser.nextToken();
while (true) {
String fieldName = parser.nextFieldName();
if (fieldName == null) {
break;
}
switch(fieldName) {
case "repo":
repoMap = parseRepo(mapper, parser);
break;
case "requests":
requests = parseRequests(mapper, parser);
break;
case "apps":
apps = parseApps(mapper, parser);
break;
case "packages":
packages = parsePackages(mapper, parser);
break;
}
}
// ensure resources get cleaned up timely and properly
parser.close();
profiler.log("Finished processing index-v1.json. Now verifying certificate...");
if (repoMap == null) {
return;
}
long timestamp = (Long) repoMap.get("timestamp") / 1000;
if (repo.timestamp > timestamp) {
throw new IndexUpdater.UpdateException(repo, "index.jar is older that current index! " + timestamp + " < " + repo.timestamp);
}
X509Certificate certificate = getSigningCertFromJar(indexEntry);
verifySigningCertificate(certificate);
profiler.log("Certificate verified. Now saving to database...");
// timestamp is absolutely required
repo.timestamp = timestamp;
// below are optional, can be null
repo.lastetag = etag;
repo.name = getStringRepoValue(repoMap, "name");
repo.icon = getStringRepoValue(repoMap, "icon");
repo.description = getStringRepoValue(repoMap, "description");
// ensure the canonical URL is included in the "mirrors" list as the first entry
LinkedHashSet<String> mirrors = new LinkedHashSet<>();
mirrors.add(repo.address);
mirrors.addAll(getStringListRepoValue(repoMap, "mirrors"));
repo.mirrors = mirrors.toArray(new String[mirrors.size()]);
// below are optional, can be default value
repo.maxage = getIntRepoValue(repoMap, "maxage");
repo.version = getIntRepoValue(repoMap, "version");
if (TextUtils.isEmpty(platformSigCache)) {
PackageInfo androidPackageInfo = Utils.getPackageInfoWithSignatures(context, "android");
platformSigCache = Utils.getPackageSig(androidPackageInfo);
}
RepoPersister repoPersister = new RepoPersister(context, repo);
if (apps != null && apps.length > 0) {
int appCount = 0;
for (App app : apps) {
appCount++;
List<Apk> apks = null;
if (packages != null) {
apks = packages.get(app.packageName);
}
if (apks == null) {
Log.i(TAG, "processIndexV1 empty packages");
apks = new ArrayList<>(0);
}
if (apks.size() > 0) {
app.preferredSigner = apks.get(0).sig;
app.isApk = true;
for (Apk apk : apks) {
if (!apk.isApk()) {
app.isApk = false;
} else if (apk.sig.equals(platformSigCache)) {
app.preferredSigner = platformSigCache;
}
}
}
if (appCount % 50 == 0) {
notifyProcessingApps(appCount, apps.length);
}
repoPersister.saveToDb(app, apks);
}
}
profiler.log("Saved to database, but only a temporary table. Now persisting to database...");
notifyCommittingToDb();
ContentValues contentValues = new ContentValues();
contentValues.put(Schema.RepoTable.Cols.LAST_UPDATED, Utils.formatTime(new Date(), ""));
contentValues.put(Schema.RepoTable.Cols.TIMESTAMP, repo.timestamp);
contentValues.put(Schema.RepoTable.Cols.LAST_ETAG, repo.lastetag);
if (repo.version != Repo.INT_UNSET_VALUE) {
contentValues.put(Schema.RepoTable.Cols.VERSION, repo.version);
}
if (repo.maxage != Repo.INT_UNSET_VALUE) {
contentValues.put(Schema.RepoTable.Cols.MAX_AGE, repo.maxage);
}
if (repo.description != null) {
contentValues.put(Schema.RepoTable.Cols.DESCRIPTION, repo.description);
}
if (repo.name != null) {
contentValues.put(Schema.RepoTable.Cols.NAME, repo.name);
}
if (repo.icon != null) {
contentValues.put(Schema.RepoTable.Cols.ICON, repo.icon);
}
if (repo.mirrors != null && repo.mirrors.length > 0) {
contentValues.put(Schema.RepoTable.Cols.MIRRORS, Utils.serializeCommaSeparatedString(repo.mirrors));
}
repoPersister.commit(contentValues, repo.getId());
profiler.log("Persisted to database.");
if (repo.pushRequests == Repo.PUSH_REQUEST_ACCEPT_ALWAYS) {
processRepoPushRequests(requests);
Utils.debugLog(TAG, "Completed Repo Push Requests: " + requests);
}
}
Aggregations