From bb273cd2f54b9b1f91fa9ca7c99adacef1c865f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 23 May 2016 21:01:40 +0300 Subject: [PATCH] Use Uris more often instead of File --- .../fdroid/installer/DefaultInstaller.java | 18 +++----- .../fdroid/fdroid/installer/Installer.java | 43 ++++++------------- .../fdroid/installer/InstallerFactory.java | 1 + .../InstallExtensionDialogActivity.java | 5 ++- 4 files changed, 24 insertions(+), 43 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/installer/DefaultInstaller.java b/app/src/main/java/org/fdroid/fdroid/installer/DefaultInstaller.java index a424460dc..dac7c5bc3 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/DefaultInstaller.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/DefaultInstaller.java @@ -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); diff --git a/app/src/main/java/org/fdroid/fdroid/installer/Installer.java b/app/src/main/java/org/fdroid/fdroid/installer/Installer.java index 458cd1f3a..b53d5e06e 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/Installer.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/Installer.java @@ -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 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) { diff --git a/app/src/main/java/org/fdroid/fdroid/installer/InstallerFactory.java b/app/src/main/java/org/fdroid/fdroid/installer/InstallerFactory.java index 52663b42b..1d6f6fc6e 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/InstallerFactory.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/InstallerFactory.java @@ -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); diff --git a/app/src/main/java/org/fdroid/fdroid/privileged/install/InstallExtensionDialogActivity.java b/app/src/main/java/org/fdroid/fdroid/privileged/install/InstallExtensionDialogActivity.java index 5305483d2..fcecc45ec 100644 --- a/app/src/main/java/org/fdroid/fdroid/privileged/install/InstallExtensionDialogActivity.java +++ b/app/src/main/java/org/fdroid/fdroid/privileged/install/InstallExtensionDialogActivity.java @@ -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: