diff --git a/F-Droid/src/org/fdroid/fdroid/FDroidApp.java b/F-Droid/src/org/fdroid/fdroid/FDroidApp.java index 6b31b1e9b..b9c5ed9ef 100644 --- a/F-Droid/src/org/fdroid/fdroid/FDroidApp.java +++ b/F-Droid/src/org/fdroid/fdroid/FDroidApp.java @@ -166,22 +166,25 @@ public class FDroidApp extends Application { .getDefaultSharedPreferences(getBaseContext()); curTheme = Theme.valueOf(prefs.getString(Preferences.PREF_THEME, "dark")); if (!prefs.getBoolean(Preferences.PREF_CACHE_APK, false)) { - - File local_path = Utils.getApkCacheDir(this); - // Things can be null if the SD card is not ready - we'll just - // ignore that and do it next time. - if (local_path != null) { - final File[] files = local_path.listFiles(); - if (files != null) { - for (File f : files) { - if (f.getName().endsWith(".apk")) { - f.delete(); - } - } - } - } + Utils.deleteFiles(Utils.getApkCacheDir(this), null, ".apk"); } + // Index files which downloaded, but were not removed (e.g. due to F-Droid being force + // closed during processing of the file, before getting a chance to delete). This may + // include both "index-*-downloaded" and "index-*-extracted.xml" files. The first is from + // either signed or unsigned repos, and the later is from signed repos. + Utils.deleteFiles(getCacheDir(), "index-", null); + + // As above, but for legacy F-Droid clients that downloaded under a different name, and + // extracted to the files directory rather than the cache directory. + // TODO: This can be removed in a a few months or a year (e.g. 2016) because people will + // have upgraded their clients, this code will have executed, and they will not have any + // left over files any more. Even if they do hold off upgrading until this code is removed, + // the only side effect is that they will have a few more MiB of storage taken up on their + // device until they uninstall and re-install F-Droid. + Utils.deleteFiles(getCacheDir(), "dl-", null); + Utils.deleteFiles(getFilesDir(), "index-", null); + UpdateService.schedule(getApplicationContext()); bluetoothAdapter = getBluetoothAdapter(); diff --git a/F-Droid/src/org/fdroid/fdroid/Utils.java b/F-Droid/src/org/fdroid/fdroid/Utils.java index 01430b396..427ba52c3 100644 --- a/F-Droid/src/org/fdroid/fdroid/Utils.java +++ b/F-Droid/src/org/fdroid/fdroid/Utils.java @@ -23,6 +23,8 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.AssetManager; import android.content.res.XmlResourceParser; import android.net.Uri; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.text.Editable; import android.text.Html; import android.text.TextUtils; @@ -45,7 +47,6 @@ import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import java.io.OutputStream; import java.math.BigInteger; import java.security.MessageDigest; @@ -72,6 +73,8 @@ public final class Utils { public static final SimpleDateFormat LOG_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH); + private static final String TAG = "org.fdroid.fdroid.Utils"; + public static String getIconsDir(Context context) { DisplayMetrics metrics = context.getResources().getDisplayMetrics(); String iconsDir; @@ -511,4 +514,39 @@ public final class Utils { return false; } + /** + * Remove all files from the {@parm directory} either beginning with {@param startsWith} + * or ending with {@param endsWith}. Note that if the SD card is not ready, then the + * cache directory will probably not be available. In this situation no files will be + * deleted (and thus they may still exist after the SD card becomes available). + */ + public static void deleteFiles(@Nullable File directory, @Nullable String startsWith, @Nullable String endsWith) { + + if (directory == null) { + return; + } + + final File[] files = directory.listFiles(); + if (files == null) { + return; + } + + if (startsWith != null) { + Log.i(TAG, "Cleaning up files in " + directory + " that start with \"" + startsWith + "\""); + } + + if (endsWith != null) { + Log.i(TAG, "Cleaning up files in " + directory + " that end with \"" + endsWith + "\""); + } + + for (File f : files) { + if ((startsWith != null && f.getName().startsWith(startsWith)) + || (endsWith != null && f.getName().endsWith(endsWith))) { + if (!f.delete()) { + Log.i(TAG, "Couldn't delete cache file " + f); + } + } + } + } + } diff --git a/F-Droid/src/org/fdroid/fdroid/net/Downloader.java b/F-Droid/src/org/fdroid/fdroid/net/Downloader.java index 593777d52..0e877ec56 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/Downloader.java +++ b/F-Droid/src/org/fdroid/fdroid/net/Downloader.java @@ -2,6 +2,7 @@ package org.fdroid.fdroid.net; import android.content.Context; import android.os.Bundle; +import android.support.annotation.NonNull; import android.util.Log; import org.fdroid.fdroid.ProgressListener; @@ -33,13 +34,13 @@ public abstract class Downloader { public abstract InputStream getInputStream() throws IOException; // The context is required for opening the file to write to. - Downloader(String destFile, Context ctx) + Downloader(String destFile, @NonNull Context ctx) throws FileNotFoundException, MalformedURLException { this(new File(ctx.getFilesDir() + File.separator + destFile)); } // The context is required for opening the file to write to. - Downloader(Context ctx) throws IOException { + Downloader(@NonNull Context ctx) throws IOException { this(File.createTempFile("dl-", "", ctx.getCacheDir())); } diff --git a/F-Droid/src/org/fdroid/fdroid/updater/RepoUpdater.java b/F-Droid/src/org/fdroid/fdroid/updater/RepoUpdater.java index a25a368a3..dab1afbec 100644 --- a/F-Droid/src/org/fdroid/fdroid/updater/RepoUpdater.java +++ b/F-Droid/src/org/fdroid/fdroid/updater/RepoUpdater.java @@ -82,15 +82,15 @@ abstract public class RepoUpdater { * * @throws UpdateException All error states will come from here. */ - protected abstract File getIndexFromFile(File downloadedFile) throws - UpdateException; + protected abstract File getIndexFromFile(File downloadedFile) throws UpdateException; protected abstract String getIndexAddress(); protected Downloader downloadIndex() throws UpdateException { Downloader downloader = null; try { - downloader = DownloaderFactory.create(getIndexAddress(), context); + downloader = DownloaderFactory.create( + getIndexAddress(), File.createTempFile("index-", "-downloaded", context.getCacheDir())); downloader.setCacheTag(repo.lastetag); if (progressListener != null) { // interactive session, show progress @@ -104,18 +104,14 @@ abstract public class RepoUpdater { if (downloader.isCached()) { // The index is unchanged since we last read it. We just mark // everything that came from this repo as being updated. - Log.d("FDroid", "Repo index for " + getIndexAddress() - + " is up to date (by etag)"); + Log.d("FDroid", "Repo index for " + getIndexAddress() + " is up to date (by etag)"); } } catch (IOException e) { if (downloader != null && downloader.getFile() != null) { downloader.getFile().delete(); } - throw new UpdateException( - repo, - "Error getting index file from " + repo.address, - e); + throw new UpdateException(repo, "Error getting index file from " + repo.address, e); } return downloader; } @@ -177,21 +173,10 @@ abstract public class RepoUpdater { rememberer.repo = repo; rememberer.values = prepareRepoDetailsForSaving(handler, downloader.getCacheTag()); } - } catch (SAXException e) { - throw new UpdateException( - repo, "Error parsing index for repo " + repo.address, e); - } catch (FileNotFoundException e) { - throw new UpdateException( - repo, "Error parsing index for repo " + repo.address, e); - } catch (ParserConfigurationException e) { - throw new UpdateException( - repo, "Error parsing index for repo " + repo.address, e); - } catch (IOException e) { - throw new UpdateException( - repo, "Error parsing index for repo " + repo.address, e); + } catch (SAXException | ParserConfigurationException | IOException e) { + throw new UpdateException(repo, "Error parsing index for repo " + repo.address, e); } finally { - if (downloadedFile != null && - downloadedFile != indexFile && downloadedFile.exists()) { + if (downloadedFile != null && downloadedFile != indexFile && downloadedFile.exists()) { downloadedFile.delete(); } if (indexFile != null && indexFile.exists()) { diff --git a/F-Droid/src/org/fdroid/fdroid/updater/SignedRepoUpdater.java b/F-Droid/src/org/fdroid/fdroid/updater/SignedRepoUpdater.java index 31b14e7ec..2054a1e72 100644 --- a/F-Droid/src/org/fdroid/fdroid/updater/SignedRepoUpdater.java +++ b/F-Droid/src/org/fdroid/fdroid/updater/SignedRepoUpdater.java @@ -58,7 +58,7 @@ public class SignedRepoUpdater extends RepoUpdater { jarFile = new JarFile(indexJar, true); JarEntry indexEntry = (JarEntry)jarFile.getEntry("index.xml"); - indexFile = File.createTempFile("index-", ".xml", context.getFilesDir()); + indexFile = File.createTempFile("index-", "-extracted.xml", context.getCacheDir()); InputStream input = null; OutputStream output = null; try {