Use Uris more often instead of File
This commit is contained in:
parent
a2356b05d6
commit
bb273cd2f5
@ -4,6 +4,7 @@ import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import org.fdroid.fdroid.BuildConfig;
|
||||
import org.fdroid.fdroid.Utils;
|
||||
@ -21,21 +22,17 @@ public class DefaultInstaller extends Installer {
|
||||
|
||||
@Override
|
||||
protected void installPackage(Uri uri, Uri originatingUri, String packageName) {
|
||||
|
||||
sendBroadcastInstall(uri, originatingUri, Installer.ACTION_INSTALL_STARTED);
|
||||
|
||||
Utils.debugLog(TAG, "ACTION_INSTALL uri: " + uri + " file: " + new File(uri.getPath()));
|
||||
|
||||
// TODO: rework for uri
|
||||
File sanitizedFile = null;
|
||||
Uri sanitizedUri;
|
||||
try {
|
||||
sanitizedFile = Installer.prepareApkFile(mContext, new File(uri.getPath()), packageName);
|
||||
sanitizedUri = Installer.prepareApkFile(mContext, uri, packageName);
|
||||
} catch (Installer.InstallFailedException e) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "prepareApkFile failed", e);
|
||||
return;
|
||||
}
|
||||
Uri sanitizedUri = Uri.fromFile(sanitizedFile);
|
||||
|
||||
Utils.debugLog(TAG, "ACTION_INSTALL sanitizedUri: " + sanitizedUri);
|
||||
|
||||
Intent installIntent;
|
||||
// special case: F-Droid Privileged Extension
|
||||
@ -44,14 +41,13 @@ public class DefaultInstaller extends Installer {
|
||||
// extension must be signed with the same public key as main F-Droid
|
||||
// NOTE: Disabled for debug builds to be able to use official extension from repo
|
||||
ApkSignatureVerifier signatureVerifier = new ApkSignatureVerifier(mContext);
|
||||
if (!BuildConfig.DEBUG && !signatureVerifier.hasFDroidSignature(sanitizedFile)) {
|
||||
if (!BuildConfig.DEBUG && !signatureVerifier.hasFDroidSignature(new File(sanitizedUri.getPath()))) {
|
||||
throw new RuntimeException("APK signature of extension not correct!");
|
||||
}
|
||||
|
||||
installIntent = new Intent(mContext, InstallExtensionDialogActivity.class);
|
||||
installIntent.setAction(InstallExtensionDialogActivity.ACTION_INSTALL);
|
||||
installIntent.putExtra(InstallExtensionDialogActivity.EXTRA_INSTALL_APK,
|
||||
sanitizedFile.getAbsolutePath());
|
||||
installIntent.setData(sanitizedUri);
|
||||
} else {
|
||||
installIntent = new Intent(mContext, AndroidInstallerActivity.class);
|
||||
installIntent.setAction(AndroidInstallerActivity.ACTION_INSTALL_PACKAGE);
|
||||
|
@ -37,7 +37,6 @@ import org.fdroid.fdroid.data.ApkProvider;
|
||||
import org.fdroid.fdroid.data.SanitizedFile;
|
||||
import org.fdroid.fdroid.privileged.views.AppDiff;
|
||||
import org.fdroid.fdroid.privileged.views.AppSecurityPermissions;
|
||||
import org.fdroid.fdroid.privileged.views.InstallConfirmActivity;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -81,44 +80,28 @@ public abstract class Installer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback from Installer. NOTE: This callback can be in a different thread
|
||||
* than the UI thread
|
||||
*/
|
||||
// public interface InstallerCallback {
|
||||
//
|
||||
// int OPERATION_INSTALL = 1;
|
||||
// int OPERATION_DELETE = 2;
|
||||
//
|
||||
// // Avoid using [-1,1] as they may conflict with Activity.RESULT_*
|
||||
// int ERROR_CODE_CANCELED = 2;
|
||||
// int ERROR_CODE_OTHER = 3;
|
||||
// int ERROR_CODE_CANNOT_PARSE = 4;
|
||||
//
|
||||
// void onSuccess(int operation);
|
||||
//
|
||||
// void onError(int operation, int errorCode);
|
||||
// }
|
||||
|
||||
Installer(Context context) {
|
||||
this.mContext = context;
|
||||
this.mPm = context.getPackageManager();
|
||||
localBroadcastManager = LocalBroadcastManager.getInstance(context);
|
||||
}
|
||||
|
||||
public static SanitizedFile prepareApkFile(Context context, File apkFile, String packageName)
|
||||
public static Uri prepareApkFile(Context context, Uri uri, String packageName)
|
||||
throws InstallFailedException {
|
||||
SanitizedFile apkToInstall = null;
|
||||
|
||||
File apkFile = new File(uri.getPath());
|
||||
|
||||
SanitizedFile sanitizedApkFile = null;
|
||||
try {
|
||||
Map<String, Object> attributes = AndroidXMLDecompress.getManifestHeaderAttributes(apkFile.getAbsolutePath());
|
||||
|
||||
/* This isn't really needed, but might as well since we have the data already */
|
||||
if (attributes.containsKey("packageName") && !TextUtils.equals(packageName, (String) attributes.get("packageName"))) {
|
||||
throw new InstallFailedException(apkFile + " has packageName that clashes with " + packageName);
|
||||
throw new InstallFailedException(uri + " has packageName that clashes with " + packageName);
|
||||
}
|
||||
|
||||
if (!attributes.containsKey("versionCode")) {
|
||||
throw new InstallFailedException(apkFile + " is missing versionCode!");
|
||||
throw new InstallFailedException(uri + " is missing versionCode!");
|
||||
}
|
||||
int versionCode = (Integer) attributes.get("versionCode");
|
||||
Apk apk = ApkProvider.Helper.find(context, packageName, versionCode, new String[]{
|
||||
@ -129,10 +112,10 @@ public abstract class Installer {
|
||||
* of the app to prevent attacks based on other apps swapping the file
|
||||
* out during the install process. Most likely, apkFile was just downloaded,
|
||||
* so it should still be in the RAM disk cache */
|
||||
apkToInstall = SanitizedFile.knownSanitized(File.createTempFile("install-", ".apk",
|
||||
sanitizedApkFile = SanitizedFile.knownSanitized(File.createTempFile("install-", ".apk",
|
||||
context.getFilesDir()));
|
||||
FileUtils.copyFile(apkFile, apkToInstall);
|
||||
if (!verifyApkFile(apkToInstall, apk.hash, apk.hashType)) {
|
||||
FileUtils.copyFile(apkFile, sanitizedApkFile);
|
||||
if (!verifyApkFile(sanitizedApkFile, apk.hash, apk.hashType)) {
|
||||
FileUtils.deleteQuietly(apkFile);
|
||||
throw new InstallFailedException(apkFile + " failed to verify!");
|
||||
}
|
||||
@ -143,7 +126,7 @@ public abstract class Installer {
|
||||
// have access is insecure, because apps with permission to write to the external
|
||||
// storage can overwrite the app between F-Droid asking for it to be installed and
|
||||
// the installer actually installing it.
|
||||
apkToInstall.setReadable(true, false);
|
||||
sanitizedApkFile.setReadable(true, false);
|
||||
|
||||
} catch (NumberFormatException | IOException | NoSuchAlgorithmException e) {
|
||||
throw new InstallFailedException(e);
|
||||
@ -151,7 +134,7 @@ public abstract class Installer {
|
||||
throw new InstallFailedException("F-Droid Privileged can only be updated using an activity!");
|
||||
} finally {
|
||||
// 20 minutes the start of the install process, delete the file
|
||||
final File apkToDelete = apkToInstall;
|
||||
final File apkToDelete = sanitizedApkFile;
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -167,7 +150,7 @@ public abstract class Installer {
|
||||
}.start();
|
||||
}
|
||||
|
||||
return apkToInstall;
|
||||
return Uri.fromFile(sanitizedApkFile);
|
||||
}
|
||||
|
||||
public PendingIntent getPermissionScreen(Apk apk) {
|
||||
|
@ -40,6 +40,7 @@ public class InstallerFactory {
|
||||
installer = new PrivilegedInstaller(context);
|
||||
} else {
|
||||
Log.e(TAG, "PrivilegedInstaller is enabled in prefs, but permissions are not granted!");
|
||||
// TODO: better error handling?
|
||||
|
||||
// fallback to default installer
|
||||
installer = new DefaultInstaller(context);
|
||||
|
@ -43,6 +43,8 @@ import org.fdroid.fdroid.Preferences;
|
||||
import org.fdroid.fdroid.R;
|
||||
import org.fdroid.fdroid.installer.PrivilegedInstaller;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import eu.chainfire.libsuperuser.Shell;
|
||||
|
||||
/**
|
||||
@ -53,7 +55,6 @@ public class InstallExtensionDialogActivity extends FragmentActivity {
|
||||
private static final String TAG = "InstallIntoSystem";
|
||||
|
||||
public static final String ACTION_INSTALL = "install";
|
||||
public static final String EXTRA_INSTALL_APK = "apk_file";
|
||||
|
||||
public static final String ACTION_UNINSTALL = "uninstall";
|
||||
public static final String ACTION_POST_INSTALL = "post_install";
|
||||
@ -73,7 +74,7 @@ public class InstallExtensionDialogActivity extends FragmentActivity {
|
||||
return;
|
||||
}
|
||||
|
||||
apkFile = getIntent().getStringExtra(EXTRA_INSTALL_APK);
|
||||
apkFile = (new File(getIntent().getData().getPath())).getAbsolutePath();
|
||||
|
||||
switch (getIntent().getAction()) {
|
||||
case ACTION_UNINSTALL:
|
||||
|
Loading…
x
Reference in New Issue
Block a user