Fix #85: Remove downloaded index files that hang around.
If the download process is interrupted, a "dl-" file hangs around in F-Droid's cache directory. If the download succeeds, extracts an xml file from the downloaded .jar file, and then the rest of the process is interrupted, then a "index-*.xml" file hangs around in F-Droids files directory. This fix removes these two types of left over files when F-Droid is started. In addition, it also makes it so that the downloaded repo indexes are now more clearly named "index-*-downloaded" (with no extension, because the code which does it doesn't know whether it is a .jar or .xml file, and it doesn't matter anyway). Also, it extracts the .xml files to the cache directory too (instead of the files dir) and names them "index-*-extracted.xml". There is some code which removes the old "dl-" files that will become redundant after the first time it is executed on a users device after upgrading F-Droid. It is a very small amount of code run on startup, so I am not concerned about the performance implications of leaving it there, but I put a comment explaining that it can be removed in the future. Includes minor formatting changes, and a few annotations.
This commit is contained in:
		
							parent
							
								
									c2eb9a9b67
								
							
						
					
					
						commit
						eaea0e2c23
					
				@ -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();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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()) {
 | 
			
		||||
 | 
			
		||||
@ -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 {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user