Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.preference.Preference;
import androidx.preference.PreferenceManager;

Expand All @@ -35,12 +34,10 @@
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.ZipHelper;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

Expand Down Expand Up @@ -70,13 +67,10 @@ public void onAttach(@NonNull final Context context) {
@Override
public void onCreatePreferences(@Nullable final Bundle savedInstanceState,
@Nullable final String rootKey) {
final File homeDir = ContextCompat.getDataDir(requireContext());
Objects.requireNonNull(homeDir);
manager = new ImportExportManager(new BackupFileLocator(homeDir));
manager = new ImportExportManager(new BackupFileLocator(requireContext()));

importExportDataPathKey = getString(R.string.import_export_data_path);


addPreferencesFromResourceRegistry();

final Preference importDataPreference = requirePreference(R.string.import_data);
Expand Down Expand Up @@ -204,9 +198,7 @@ private void importDatabase(final StoredFileHelper file, final Uri importDataUri
}

try {
if (!manager.ensureDbDirectoryExists()) {
throw new IOException("Could not create databases dir");
}
manager.ensureDbDirectoryExists();

// replace the current database
if (!manager.extractDb(file)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package org.schabi.newpipe.settings.export

import java.io.File
import android.content.Context
import java.nio.file.Path
import kotlin.io.path.div

/**
* Locates specific files of NewPipe based on the home directory of the app.
*/
class BackupFileLocator(private val homeDir: File) {
class BackupFileLocator(context: Context) {
companion object {
const val FILE_NAME_DB = "newpipe.db"

Expand All @@ -17,13 +19,8 @@ class BackupFileLocator(private val homeDir: File) {
const val FILE_NAME_JSON_PREFS = "preferences.json"
}

val dbDir by lazy { File(homeDir, "/databases") }

val db by lazy { File(dbDir, FILE_NAME_DB) }

val dbJournal by lazy { File(dbDir, "$FILE_NAME_DB-journal") }

val dbShm by lazy { File(dbDir, "$FILE_NAME_DB-shm") }

val dbWal by lazy { File(dbDir, "$FILE_NAME_DB-wal") }
val db: Path = context.getDatabasePath(FILE_NAME_DB).toPath()
val dbJournal: Path = db.resolveSibling("$FILE_NAME_DB-journal")
val dbShm: Path = db.resolveSibling("$FILE_NAME_DB-shm")
val dbWal: Path = db.resolveSibling("$FILE_NAME_DB-wal")
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import java.io.FileNotFoundException
import java.io.IOException
import java.io.ObjectOutputStream
import java.util.zip.ZipOutputStream
import kotlin.io.path.createParentDirectories
import kotlin.io.path.deleteIfExists
import org.schabi.newpipe.streams.io.SharpOutputStream
import org.schabi.newpipe.streams.io.StoredFileHelper
import org.schabi.newpipe.util.ZipHelper
Expand All @@ -28,11 +30,8 @@ class ImportExportManager(private val fileLocator: BackupFileLocator) {
// previous file size, the file will retain part of the previous content and be corrupted
ZipOutputStream(SharpOutputStream(file.openAndTruncateStream()).buffered()).use { outZip ->
// add the database
ZipHelper.addFileToZip(
outZip,
BackupFileLocator.FILE_NAME_DB,
fileLocator.db.path
)
val name = BackupFileLocator.FILE_NAME_DB
ZipHelper.addFileToZip(outZip, name, fileLocator.db)

// add the legacy vulnerable serialized preferences (will be removed in the future)
ZipHelper.addFileToZip(
Expand Down Expand Up @@ -61,11 +60,10 @@ class ImportExportManager(private val fileLocator: BackupFileLocator) {

/**
* Tries to create database directory if it does not exist.
*
* @return Whether the directory exists afterwards.
*/
fun ensureDbDirectoryExists(): Boolean {
return fileLocator.dbDir.exists() || fileLocator.dbDir.mkdir()
@Throws(IOException::class)
fun ensureDbDirectoryExists() {
fileLocator.db.createParentDirectories()
}

/**
Expand All @@ -75,16 +73,13 @@ class ImportExportManager(private val fileLocator: BackupFileLocator) {
* @return true if the database was successfully extracted, false otherwise
*/
fun extractDb(file: StoredFileHelper): Boolean {
val success = ZipHelper.extractFileFromZip(
file,
BackupFileLocator.FILE_NAME_DB,
fileLocator.db.path
)
val name = BackupFileLocator.FILE_NAME_DB
val success = ZipHelper.extractFileFromZip(file, name, fileLocator.db)

if (success) {
fileLocator.dbJournal.delete()
fileLocator.dbWal.delete()
fileLocator.dbShm.delete()
fileLocator.dbJournal.deleteIfExists()
fileLocator.dbWal.deleteIfExists()
fileLocator.dbShm.deleteIfExists()
}

return success
Expand Down
68 changes: 21 additions & 47 deletions app/src/main/java/org/schabi/newpipe/util/ZipHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
Expand All @@ -37,9 +37,6 @@
*/

public final class ZipHelper {

private static final int BUFFER_SIZE = 2048;

@FunctionalInterface
public interface InputStreamConsumer {
void acceptStream(InputStream inputStream) throws IOException;
Expand All @@ -55,17 +52,17 @@ private ZipHelper() { }


/**
* This function helps to create zip files. Caution this will overwrite the original file.
* This function helps to create zip files. Caution, this will overwrite the original file.
*
* @param outZip the ZipOutputStream where the data should be stored in
* @param nameInZip the path of the file inside the zip
* @param fileOnDisk the path of the file on the disk that should be added to zip
* @param path the path of the file on the disk that should be added to zip
*/
public static void addFileToZip(final ZipOutputStream outZip,
final String nameInZip,
final String fileOnDisk) throws IOException {
try (FileInputStream fi = new FileInputStream(fileOnDisk)) {
addFileToZip(outZip, nameInZip, fi);
final Path path) throws IOException {
try (var inputStream = Files.newInputStream(path)) {
addFileToZip(outZip, nameInZip, inputStream);
}
}

Expand All @@ -80,13 +77,13 @@ public static void addFileToZip(final ZipOutputStream outZip,
final String nameInZip,
final OutputStreamConsumer streamConsumer) throws IOException {
final byte[] bytes;
try (ByteArrayOutputStream byteOutput = new ByteArrayOutputStream()) {
try (var byteOutput = new ByteArrayOutputStream()) {
streamConsumer.acceptStream(byteOutput);
bytes = byteOutput.toByteArray();
}

try (ByteArrayInputStream byteInput = new ByteArrayInputStream(bytes)) {
ZipHelper.addFileToZip(outZip, nameInZip, byteInput);
try (var byteInput = new ByteArrayInputStream(bytes)) {
addFileToZip(outZip, nameInZip, byteInput);
}
}

Expand All @@ -97,49 +94,26 @@ public static void addFileToZip(final ZipOutputStream outZip,
* @param nameInZip the path of the file inside the zip
* @param inputStream the content to put inside the file
*/
public static void addFileToZip(final ZipOutputStream outZip,
final String nameInZip,
final InputStream inputStream) throws IOException {
final byte[] data = new byte[BUFFER_SIZE];
try (BufferedInputStream bufferedInputStream =
new BufferedInputStream(inputStream, BUFFER_SIZE)) {
final ZipEntry entry = new ZipEntry(nameInZip);
outZip.putNextEntry(entry);
int count;
while ((count = bufferedInputStream.read(data, 0, BUFFER_SIZE)) != -1) {
outZip.write(data, 0, count);
}
}
private static void addFileToZip(final ZipOutputStream outZip,
final String nameInZip,
final InputStream inputStream) throws IOException {
outZip.putNextEntry(new ZipEntry(nameInZip));
inputStream.transferTo(outZip);
}

/**
* This will extract data from ZipInputStream. Caution this will overwrite the original file.
* This will extract data from ZipInputStream. Caution, this will overwrite the original file.
*
* @param zipFile the zip file to extract from
* @param nameInZip the path of the file inside the zip
* @param fileOnDisk the path of the file on the disk where the data should be extracted to
* @param path the path of the file on the disk where the data should be extracted to
* @return will return true if the file was found within the zip file
*/
public static boolean extractFileFromZip(final StoredFileHelper zipFile,
final String nameInZip,
final String fileOnDisk) throws IOException {
return extractFileFromZip(zipFile, nameInZip, input -> {
// delete old file first
final File oldFile = new File(fileOnDisk);
if (oldFile.exists()) {
if (!oldFile.delete()) {
throw new IOException("Could not delete " + fileOnDisk);
}
}

final byte[] data = new byte[BUFFER_SIZE];
try (FileOutputStream outFile = new FileOutputStream(fileOnDisk)) {
int count;
while ((count = input.read(data)) != -1) {
outFile.write(data, 0, count);
}
}
});
final Path path) throws IOException {
return extractFileFromZip(zipFile, nameInZip, input ->
Files.copy(input, path, StandardCopyOption.REPLACE_EXISTING));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package org.schabi.newpipe.settings
import android.content.SharedPreferences
import java.io.File
import java.io.IOException
import java.nio.file.Files
import kotlin.io.path.createTempFile
import kotlin.io.path.exists
import kotlin.io.path.fileSize
import org.junit.Assert
import org.junit.Test
import org.mockito.Mockito
Expand Down Expand Up @@ -47,10 +49,10 @@ class ImportAllCombinationsTest {
BackupFileLocator::class.java,
Mockito.withSettings().stubOnly()
)
val db = File.createTempFile("newpipe_", "")
val dbJournal = File.createTempFile("newpipe_", "")
val dbWal = File.createTempFile("newpipe_", "")
val dbShm = File.createTempFile("newpipe_", "")
val db = createTempFile("newpipe_", "")
val dbJournal = createTempFile("newpipe_", "")
val dbWal = createTempFile("newpipe_", "")
val dbShm = createTempFile("newpipe_", "")
Mockito.`when`(fileLocator.db).thenReturn(db)
Mockito.`when`(fileLocator.dbJournal).thenReturn(dbJournal)
Mockito.`when`(fileLocator.dbShm).thenReturn(dbShm)
Expand All @@ -62,15 +64,15 @@ class ImportAllCombinationsTest {
Assert.assertFalse(dbJournal.exists())
Assert.assertFalse(dbWal.exists())
Assert.assertFalse(dbShm.exists())
Assert.assertTrue("database file size is zero", Files.size(db.toPath()) > 0)
Assert.assertTrue("database file size is zero", db.fileSize() > 0)
}
} else {
runTest {
Assert.assertFalse(ImportExportManager(fileLocator).extractDb(zip))
Assert.assertTrue(dbJournal.exists())
Assert.assertTrue(dbWal.exists())
Assert.assertTrue(dbShm.exists())
Assert.assertEquals(0, Files.size(db.toPath()))
Assert.assertEquals(0, db.fileSize())
}
}

Expand Down
Loading
Loading