Don't accidentally return Apk instances from the wrong repo
There may be multiple apk files with the same hash. Although it is not a security issue to install one or the other (they are exactly the same binary), they may have different metadata to display in the client. Thus, it may result in weirdness if one has a different name/description/summary etc). This change takes each of the matching Apk objects from the database, then asks them where they expect to be downloaded. It matches this against the File that we are looking at and only returns if they match.
This commit is contained in:
parent
ccdd8a168c
commit
0d1e00b6cf
@ -5,6 +5,7 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.net.Uri;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
@ -68,33 +69,20 @@ public class AppUpdateStatusService extends IntentService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: This presumes SHA256 is the only supported hash. It seems like that is an assumption
|
|
||||||
// in more than one place in the F-Droid client. If this becomes a problem in the future, we
|
|
||||||
// can query the Apk table for `SELECT DISTINCT hashType FROM fdroid_apk` and then we can just
|
|
||||||
// try each of the hash types that have been specified in the metadata. Seems a bit overkill
|
|
||||||
// at the time of writing though.
|
|
||||||
Utils.debugLog(TAG, "Found package for " + downloadedInfo.packageName + ", checking its hash to see if it downloaded correctly.");
|
Utils.debugLog(TAG, "Found package for " + downloadedInfo.packageName + ", checking its hash to see if it downloaded correctly.");
|
||||||
String hash = Utils.getBinaryHash(apkPath, "sha256");
|
Apk downloadedApk = findApkMatchingHash(apkPath);
|
||||||
|
if (downloadedApk == null) {
|
||||||
List<Apk> apksMatchingHash = ApkProvider.Helper.findApksByHash(this, hash);
|
|
||||||
Utils.debugLog(TAG, "Found " + apksMatchingHash.size() + " apk(s) matching the hash " + hash);
|
|
||||||
|
|
||||||
if (apksMatchingHash.size() == 0) {
|
|
||||||
Utils.debugLog(TAG, "Either the apk wasn't downloaded fully, or the repo it came from has been disabled. Either way, not notifying the user about it.");
|
Utils.debugLog(TAG, "Either the apk wasn't downloaded fully, or the repo it came from has been disabled. Either way, not notifying the user about it.");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// It makes zero difference which apk we get from this list. By definition they all have
|
|
||||||
// the exact same hash, and are thus the same binary.
|
|
||||||
Apk downloadedApk = apksMatchingHash.get(0);
|
|
||||||
|
|
||||||
PackageInfo installedInfo = null;
|
PackageInfo installedInfo = null;
|
||||||
try {
|
try {
|
||||||
installedInfo = getPackageManager().getPackageInfo(downloadedApk.packageName, PackageManager.GET_META_DATA);
|
installedInfo = getPackageManager().getPackageInfo(downloadedApk.packageName, PackageManager.GET_META_DATA);
|
||||||
} catch (PackageManager.NameNotFoundException ignored) { }
|
} catch (PackageManager.NameNotFoundException ignored) { }
|
||||||
|
|
||||||
if (installedInfo == null) {
|
if (installedInfo == null) {
|
||||||
if (AppUpdateStatusManager.getInstance(this).isPendingInstall(hash)) {
|
if (AppUpdateStatusManager.getInstance(this).isPendingInstall(downloadedApk.hash)) {
|
||||||
Utils.debugLog(TAG, downloadedApk.packageName + " is not installed, so presuming we need to notify the user about installing it.");
|
Utils.debugLog(TAG, downloadedApk.packageName + " is not installed, so presuming we need to notify the user about installing it.");
|
||||||
return downloadedApk;
|
return downloadedApk;
|
||||||
} else {
|
} else {
|
||||||
@ -112,4 +100,35 @@ public class AppUpdateStatusService extends IntentService {
|
|||||||
|
|
||||||
return downloadedApk;
|
return downloadedApk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* There could be multiple apks with the same hash, provided by different repositories.
|
||||||
|
* This method looks for all matching records in the database. It then asks each of these
|
||||||
|
* {@link Apk} instances where they expect to be downloaded. If they expect to be downloaded
|
||||||
|
* to {@param apkPath} then that instance is returned.
|
||||||
|
*
|
||||||
|
* If no files have a matching hash, or only those which don't belong to the correct repo, then
|
||||||
|
* this will return null.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
private Apk findApkMatchingHash(File apkPath) {
|
||||||
|
|
||||||
|
// NOTE: This presumes SHA256 is the only supported hash. It seems like that is an assumption
|
||||||
|
// in more than one place in the F-Droid client. If this becomes a problem in the future, we
|
||||||
|
// can query the Apk table for `SELECT DISTINCT hashType FROM fdroid_apk` and then we can just
|
||||||
|
// try each of the hash types that have been specified in the metadata. Seems a bit overkill
|
||||||
|
// at the time of writing though.
|
||||||
|
String hash = Utils.getBinaryHash(apkPath, "sha256");
|
||||||
|
|
||||||
|
List<Apk> apksMatchingHash = ApkProvider.Helper.findApksByHash(this, hash);
|
||||||
|
Utils.debugLog(TAG, "Found " + apksMatchingHash.size() + " apk(s) matching the hash " + hash);
|
||||||
|
|
||||||
|
for (Apk apk : apksMatchingHash) {
|
||||||
|
if (apkPath.equals(ApkCache.getApkDownloadPath(this, Uri.parse(apk.getUrl())))) {
|
||||||
|
return apk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user