From 5a444f2829b18d518fa906b08c9174a2d7619e8a Mon Sep 17 00:00:00 2001 From: Hardcore Sushi Date: Sat, 1 Aug 2020 15:39:00 +0200 Subject: [PATCH] "Copy" feature, FAB icons & GitHub link --- app/build.gradle | 1 - app/libgocryptfs/main.go | 4 +- app/src/main/AndroidManifest.xml | 5 +- .../droidfs/ChangePasswordActivity.kt | 1 + .../sushi/hardcore/droidfs/ConstValues.kt | 1 + .../sushi/hardcore/droidfs/CreateActivity.kt | 1 + .../sushi/hardcore/droidfs/OpenActivity.kt | 1 + .../hardcore/droidfs/SettingsActivity.kt | 1 - .../droidfs/explorers/BaseExplorerActivity.kt | 54 ++-- .../droidfs/explorers/ExplorerActivity.kt | 230 ++++++++++++++---- .../droidfs/explorers/ExplorerActivityDrop.kt | 27 +- .../droidfs/explorers/ExplorerActivityPick.kt | 12 +- .../droidfs/explorers/ExplorerElement.kt | 6 +- .../file_viewers/GocryptfsDataSource.kt | 23 +- .../provider/RestrictedFileProvider.kt | 133 ++++++++-- .../hardcore/droidfs/util/ExternalProvider.kt | 11 +- .../hardcore/droidfs/util/GocryptfsVolume.kt | 29 ++- .../hardcore/droidfs/util/PathUtils.java | 18 +- .../sushi/hardcore/droidfs/util/SQLUtil.kt | 24 ++ .../hardcore/droidfs/widgets/ThemeColor.kt | 7 +- app/src/main/native/gocryptfs_jni.c | 4 +- app/src/main/res/drawable/icon_copy.xml | 5 + app/src/main/res/drawable/icon_decrypt.xml | 16 +- app/src/main/res/drawable/icon_encrypt.xml | 11 + app/src/main/res/drawable/icon_github.xml | 10 + app/src/main/res/drawable/icon_transfert.xml | 5 + app/src/main/res/drawable/logo.png | Bin 43443 -> 49720 bytes app/src/main/res/layout/activity_explorer.xml | 14 +- .../res/layout/activity_explorer_drop.xml | 4 +- app/src/main/res/menu/explorer.xml | 51 ++-- app/src/main/res/menu/explorer_drop.xml | 17 +- app/src/main/res/menu/explorer_pick.xml | 19 +- app/src/main/res/mipmap/ic_launcher.png | Bin 9708 -> 0 bytes app/src/main/res/mipmap/icon_launcher.png | Bin 0 -> 8709 bytes app/src/main/res/values/colors.xml | 1 - app/src/main/res/values/strings.xml | 11 +- app/src/main/res/xml/root_preferences.xml | 13 + 37 files changed, 547 insertions(+), 223 deletions(-) create mode 100644 app/src/main/java/sushi/hardcore/droidfs/util/SQLUtil.kt create mode 100644 app/src/main/res/drawable/icon_copy.xml create mode 100644 app/src/main/res/drawable/icon_encrypt.xml create mode 100644 app/src/main/res/drawable/icon_github.xml create mode 100644 app/src/main/res/drawable/icon_transfert.xml delete mode 100644 app/src/main/res/mipmap/ic_launcher.png create mode 100644 app/src/main/res/mipmap/icon_launcher.png diff --git a/app/build.gradle b/app/build.gradle index 48fd242..9ffb18e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -26,7 +26,6 @@ android { release { minifyEnabled true shrinkResources true - useProguard true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } diff --git a/app/libgocryptfs/main.go b/app/libgocryptfs/main.go index bbc0002..0d392f7 100644 --- a/app/libgocryptfs/main.go +++ b/app/libgocryptfs/main.go @@ -120,7 +120,9 @@ func openBackingDir(sessionID int, relPath string) (dirfd int, cName string, err if i == len(parts)-1 { cache_dirfd, err := syscall.Dup(dirfd) if err == nil { - sessions[sessionID].dirCache[dirRelPath] = Directory{cache_dirfd, iv} + var dirRelPathCopy strings.Builder + dirRelPathCopy.WriteString(dirRelPath) + sessions[sessionID].dirCache[dirRelPathCopy.String()] = Directory{cache_dirfd, iv} } break } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 49ae32d..b056198 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -14,7 +14,7 @@ @@ -39,9 +40,11 @@ = Build.VERSION_CODES.M && usf_fingerprint) { fingerprintPasswordHashSaver = FingerprintPasswordHashSaver(this, sharedPrefs) diff --git a/app/src/main/java/sushi/hardcore/droidfs/ConstValues.kt b/app/src/main/java/sushi/hardcore/droidfs/ConstValues.kt index a533484..78f7597 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/ConstValues.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/ConstValues.kt @@ -9,6 +9,7 @@ class ConstValues { const val saved_volumes_key = "saved_volumes" const val sort_order_key = "sort_order" val fakeUri: Uri = Uri.parse("fakeuri://droidfs") + const val MAX_KERNEL_WRITE = 128*1024 const val wipe_passes = 2 private val fileExtensions = mapOf( Pair("image", listOf("png", "jpg", "jpeg")), diff --git a/app/src/main/java/sushi/hardcore/droidfs/CreateActivity.kt b/app/src/main/java/sushi/hardcore/droidfs/CreateActivity.kt index 98e8053..fb4afd3 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/CreateActivity.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/CreateActivity.kt @@ -31,6 +31,7 @@ class CreateActivity : BaseActivity() { super.onCreate(savedInstanceState) setContentView(R.layout.activity_create) setSupportActionBar(toolbar) + supportActionBar?.setDisplayHomeAsUpEnabled(true) usf_fingerprint = sharedPrefs.getBoolean("usf_fingerprint", false) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && usf_fingerprint) { fingerprintPasswordHashSaver = FingerprintPasswordHashSaver(this, sharedPrefs) diff --git a/app/src/main/java/sushi/hardcore/droidfs/OpenActivity.kt b/app/src/main/java/sushi/hardcore/droidfs/OpenActivity.kt index b96acb9..a58745d 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/OpenActivity.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/OpenActivity.kt @@ -38,6 +38,7 @@ class OpenActivity : BaseActivity() { super.onCreate(savedInstanceState) setContentView(R.layout.activity_open) setSupportActionBar(toolbar) + supportActionBar?.setDisplayHomeAsUpEnabled(true) usf_fingerprint = sharedPrefs.getBoolean("usf_fingerprint", false) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && usf_fingerprint) { fingerprintPasswordHashSaver = FingerprintPasswordHashSaver(this, sharedPrefs) diff --git a/app/src/main/java/sushi/hardcore/droidfs/SettingsActivity.kt b/app/src/main/java/sushi/hardcore/droidfs/SettingsActivity.kt index cf1963a..dd308d6 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/SettingsActivity.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/SettingsActivity.kt @@ -26,7 +26,6 @@ class SettingsActivity : BaseActivity(), PreferenceFragmentCompat.OnPreferenceSt .beginTransaction() .replace(R.id.settings, fragment) .commit() - setTheme(R.style.AppTheme) } class SettingsFragment : PreferenceFragmentCompat() { diff --git a/app/src/main/java/sushi/hardcore/droidfs/explorers/BaseExplorerActivity.kt b/app/src/main/java/sushi/hardcore/droidfs/explorers/BaseExplorerActivity.kt index 2b10a26..417b420 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/explorers/BaseExplorerActivity.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/explorers/BaseExplorerActivity.kt @@ -63,11 +63,7 @@ open class BaseExplorerActivity : BaseActivity() { setCurrentPath(currentDirectoryPath) list_explorer.adapter = explorerAdapter list_explorer.onItemClickListener = OnItemClickListener { _, _, position, _ -> onExplorerItemClick(position) } - list_explorer.onItemLongClickListener = OnItemLongClickListener { _, _, position, _ -> - explorerAdapter.onItemLongClick(position) - invalidateOptionsMenu() - true - } + list_explorer.onItemLongClickListener = OnItemLongClickListener { _, _, position, _ -> onExplorerItemLongClick(position); true } refresher.setOnRefreshListener { setCurrentPath(currentDirectoryPath) refresher.isRefreshing = false @@ -90,13 +86,13 @@ open class BaseExplorerActivity : BaseActivity() { explorerAdapter.onItemClick(position) if (explorerAdapter.selectedItems.isEmpty()) { if (!wasSelecting) { - val fullPath = PathUtils.path_join(currentDirectoryPath, explorerElements[position].name) + val fullPath = explorerElements[position].getFullPath() when { explorerElements[position].isDirectory -> { setCurrentPath(fullPath) } explorerElements[position].isParentFolder -> { - setCurrentPath(PathUtils.get_parent_path(currentDirectoryPath)) + setCurrentPath(PathUtils.getParentPath(currentDirectoryPath)) } isImage(fullPath) -> { startFileViewer(ImageViewer::class.java, fullPath) @@ -128,8 +124,14 @@ open class BaseExplorerActivity : BaseActivity() { .show() } } + } else { + invalidateOptionsMenu() } } + } + + protected open fun onExplorerItemLongClick(position: Int) { + explorerAdapter.onItemLongClick(position) invalidateOptionsMenu() } @@ -169,7 +171,7 @@ open class BaseExplorerActivity : BaseActivity() { text_dir_empty.visibility = if (explorerElements.size == 0) View.VISIBLE else View.INVISIBLE sortExplorerElements() if (path.isNotEmpty()) { //not root - explorerElements.add(0, ExplorerElement("..", (-1).toShort(), -1, -1)) + explorerElements.add(0, ExplorerElement("..", (-1).toShort(), -1, -1, currentDirectoryPath)) } explorerAdapter.setExplorerElements(explorerElements) currentDirectoryPath = path @@ -192,16 +194,16 @@ open class BaseExplorerActivity : BaseActivity() { protected open fun closeVolumeOnDestroy() { gocryptfsVolume.close() - RestrictedFileProvider.wipeAll() //additional security + RestrictedFileProvider.wipeAll(this) //additional security } override fun onBackPressed() { if (explorerAdapter.selectedItems.isEmpty()) { - val parentPath = PathUtils.get_parent_path(currentDirectoryPath) + val parentPath = PathUtils.getParentPath(currentDirectoryPath) if (parentPath == currentDirectoryPath) { askCloseVolume() } else { - setCurrentPath(PathUtils.get_parent_path(currentDirectoryPath)) + setCurrentPath(PathUtils.getParentPath(currentDirectoryPath)) } } else { unselectAll() @@ -266,23 +268,21 @@ open class BaseExplorerActivity : BaseActivity() { } fun handleMenuItems(menu: Menu){ - menu.findItem(R.id.explorer_menu_rename).isVisible = false + menu.findItem(R.id.rename).isVisible = false if (usf_open){ - menu.findItem(R.id.explorer_menu_external_open)?.isVisible = false + menu.findItem(R.id.external_open)?.isVisible = false } - val selectedItems = explorerAdapter.selectedItems - if (selectedItems.isEmpty()){ + val noItemSelected = explorerAdapter.selectedItems.isEmpty() + menu.findItem(R.id.sort).isVisible = noItemSelected + menu.findItem(R.id.close).isVisible = noItemSelected + if (noItemSelected){ toolbar.navigationIcon = null - menu.findItem(R.id.explorer_menu_close).isVisible = true - menu.findItem(R.id.explorer_menu_sort).isVisible = true } else { toolbar.setNavigationIcon(R.drawable.icon_arrow_back) - menu.findItem(R.id.explorer_menu_close).isVisible = false - menu.findItem(R.id.explorer_menu_sort).isVisible = false - if (selectedItems.size == 1) { - menu.findItem(R.id.explorer_menu_rename).isVisible = true - if (usf_open && explorerElements[selectedItems[0]].isRegularFile) { - menu.findItem(R.id.explorer_menu_external_open)?.isVisible = true + if (explorerAdapter.selectedItems.size == 1) { + menu.findItem(R.id.rename).isVisible = true + if (usf_open && explorerElements[explorerAdapter.selectedItems[0]].isRegularFile) { + menu.findItem(R.id.external_open)?.isVisible = true } } } @@ -294,7 +294,7 @@ open class BaseExplorerActivity : BaseActivity() { unselectAll() true } - R.id.explorer_menu_sort -> { + R.id.sort -> { ColoredAlertDialogBuilder(this) .setTitle(R.string.sort_order) .setSingleChoiceItems(DialogSingleChoiceAdapter(this, sortModesEntries), currentSortModeIndex) { dialog, which -> @@ -306,7 +306,7 @@ open class BaseExplorerActivity : BaseActivity() { .show() true } - R.id.explorer_menu_rename -> { + R.id.rename -> { val dialogEditTextView = layoutInflater.inflate(R.layout.dialog_edit_text, null) val oldName = explorerElements[explorerAdapter.selectedItems[0]].name val dialogEditText = dialogEditTextView.findViewById(R.id.dialog_edit_text) @@ -331,14 +331,14 @@ open class BaseExplorerActivity : BaseActivity() { dialog.show() true } - R.id.explorer_menu_external_open -> { + R.id.external_open -> { if (usf_open){ ExternalProvider.open(this, gocryptfsVolume, PathUtils.path_join(currentDirectoryPath, explorerElements[explorerAdapter.selectedItems[0]].name)) unselectAll() } true } - R.id.explorer_menu_close -> { + R.id.close -> { askCloseVolume() true } diff --git a/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivity.kt b/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivity.kt index 4d3364c..1551823 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivity.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivity.kt @@ -8,9 +8,9 @@ import android.view.MenuItem import android.view.View import android.view.WindowManager import android.widget.EditText -import android.widget.TextView import android.widget.Toast import androidx.appcompat.app.AppCompatActivity +import com.github.clans.fab.FloatingActionButton import com.github.clans.fab.FloatingActionMenu import kotlinx.android.synthetic.main.activity_explorer.* import sushi.hardcore.droidfs.OpenActivity @@ -18,7 +18,7 @@ import sushi.hardcore.droidfs.R import sushi.hardcore.droidfs.util.* import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder import java.io.File -import java.util.* +import kotlin.collections.ArrayList class ExplorerActivity : BaseExplorerActivity() { private val PICK_DIRECTORY_REQUEST_CODE = 1 @@ -26,12 +26,20 @@ class ExplorerActivity : BaseExplorerActivity() { private val PICK_OTHER_VOLUME_ITEMS_REQUEST_CODE = 3 private var usf_decrypt = false private var usf_share = false + private var modeSelectLocation = false + private val filesToCopy = ArrayList() override fun init() { setContentView(R.layout.activity_explorer) usf_decrypt = sharedPrefs.getBoolean("usf_decrypt", false) usf_share = sharedPrefs.getBoolean("usf_share", false) } + override fun onExplorerItemLongClick(position: Int) { + cancelCopy() + explorerAdapter.onItemLongClick(position) + invalidateOptionsMenu() + } + private fun createNewFile(fileName: String){ if (fileName.isEmpty()) { Toast.makeText(this, R.string.error_filename_empty, Toast.LENGTH_SHORT).show() @@ -230,7 +238,7 @@ class ExplorerActivity : BaseExplorerActivity() { failedItem = if (types[i] == 0) { //directory recursiveImportDirectoryFromOtherVolume(remoteGocryptfsVolume, paths[i], currentDirectoryPath) } else { - if (importFileFromOtherVolume(remoteGocryptfsVolume, paths[i], currentDirectoryPath)) null else paths[i] + if (importFileFromOtherVolume(remoteGocryptfsVolume, paths[i], PathUtils.path_join(currentDirectoryPath, File(paths[i]).name))) null else paths[i] } if (failedItem != null) { break @@ -238,7 +246,7 @@ class ExplorerActivity : BaseExplorerActivity() { } } } else { - failedItem = if (importFileFromOtherVolume(remoteGocryptfsVolume, path, currentDirectoryPath)) null else path + failedItem = if (importFileFromOtherVolume(remoteGocryptfsVolume, path, PathUtils.path_join(currentDirectoryPath, File(path).name))) null else path } if (failedItem == null) { stopTask { @@ -269,24 +277,30 @@ class ExplorerActivity : BaseExplorerActivity() { override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.explorer, menu) - handleMenuItems(menu) - if (usf_share){ - menu.findItem(R.id.explorer_menu_share).isVisible = false - } - val anyItemSelected = explorerAdapter.selectedItems.isNotEmpty() - menu.findItem(R.id.explorer_menu_select_all).isVisible = anyItemSelected - menu.findItem(R.id.explorer_menu_delete).isVisible = anyItemSelected - menu.findItem(R.id.explorer_menu_decrypt).isVisible = anyItemSelected && usf_decrypt - if (anyItemSelected && usf_share){ - var containsDir = false - for (i in explorerAdapter.selectedItems) { - if (explorerElements[i].isDirectory) { - containsDir = true - break - } + if (modeSelectLocation) { + menu.findItem(R.id.validate).isVisible = true + menu.findItem(R.id.close).isVisible = false + } else { + handleMenuItems(menu) + if (usf_share){ + menu.findItem(R.id.share).isVisible = false } - if (!containsDir) { - menu.findItem(R.id.explorer_menu_share).isVisible = true + val anyItemSelected = explorerAdapter.selectedItems.isNotEmpty() + menu.findItem(R.id.select_all).isVisible = anyItemSelected + menu.findItem(R.id.delete).isVisible = anyItemSelected + menu.findItem(R.id.copy).isVisible = anyItemSelected + menu.findItem(R.id.decrypt).isVisible = anyItemSelected && usf_decrypt + if (anyItemSelected && usf_share){ + var containsDir = false + for (i in explorerAdapter.selectedItems) { + if (explorerElements[i].isDirectory) { + containsDir = true + break + } + } + if (!containsDir) { + menu.findItem(R.id.share).isVisible = true + } } } return true @@ -294,12 +308,67 @@ class ExplorerActivity : BaseExplorerActivity() { override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.itemId) { - R.id.explorer_menu_select_all -> { + android.R.id.home -> { + cancelCopy() + super.onOptionsItemSelected(item) + } + R.id.select_all -> { explorerAdapter.selectAll() invalidateOptionsMenu() true } - R.id.explorer_menu_delete -> { + R.id.copy -> { + for (i in explorerAdapter.selectedItems){ + filesToCopy.add(explorerElements[i]) + } + modeSelectLocation = true + unselectAll() + findViewById(R.id.fab_add_file).visibility = View.GONE + findViewById(R.id.fab_import_file).visibility = View.GONE + findViewById(R.id.fab_import_file_from_other_volume).visibility = View.GONE + true + } + R.id.validate -> { + object : LoadingTask(this, R.string.loading_msg_copy){ + override fun doTask(activity: AppCompatActivity) { + var failedItem: String? = null + for (element in filesToCopy) { + val originalPath = element.getFullPath() + failedItem = if (element.isDirectory) { + recursiveCopyDirectory(originalPath, currentDirectoryPath) + } else { + if (copyFile(originalPath, PathUtils.path_join(currentDirectoryPath, element.name))) null else originalPath + } + if (failedItem != null) { + stopTask { + ColoredAlertDialogBuilder(activity) + .setTitle(R.string.error) + .setMessage(getString(R.string.copy_failed, failedItem)) + .setPositiveButton(R.string.ok, null) + .show() + } + break + } + } + if (failedItem == null) { + stopTask { + ColoredAlertDialogBuilder(activity) + .setTitle(getString(R.string.copy_success)) + .setMessage(getString(R.string.copy_success_msg)) + .setPositiveButton(R.string.ok, null) + .show() + } + } + } + override fun doFinally(activity: AppCompatActivity) { + cancelCopy() + unselectAll() + setCurrentPath(currentDirectoryPath) + } + } + true + } + R.id.delete -> { val size = explorerAdapter.selectedItems.size val dialog = ColoredAlertDialogBuilder(this) dialog.setTitle(R.string.warning) @@ -313,17 +382,16 @@ class ExplorerActivity : BaseExplorerActivity() { dialog.show() true } - R.id.explorer_menu_share -> { + R.id.share -> { val paths: MutableList = ArrayList() for (i in explorerAdapter.selectedItems) { - val e = explorerElements[i] - paths.add(PathUtils.path_join(currentDirectoryPath, e.name)) + paths.add(explorerElements[i].getFullPath()) } ExternalProvider.share(this, gocryptfsVolume, paths) unselectAll() true } - R.id.explorer_menu_decrypt -> { + R.id.decrypt -> { val i = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) startActivityForResult(i, PICK_DIRECTORY_REQUEST_CODE) true @@ -332,12 +400,86 @@ class ExplorerActivity : BaseExplorerActivity() { } } - private fun importFileFromOtherVolume(remote_gocryptfsVolume: GocryptfsVolume, full_path: String, output_dir: String): Boolean { - val outputPath = PathUtils.path_join(output_dir, File(full_path).name) + private fun recursiveMapFiles(rootPath: String): MutableList { + val result = mutableListOf() + val explorerElements = gocryptfsVolume.list_dir(rootPath) + result.addAll(explorerElements) + for (e in explorerElements){ + if (e.isDirectory){ + result.addAll(recursiveMapFiles(e.getFullPath())) + } + } + return result + } + + private fun cancelCopy() { + if (modeSelectLocation){ + modeSelectLocation = false + findViewById(R.id.fab_add_file).visibility = View.VISIBLE + findViewById(R.id.fab_import_file).visibility = View.VISIBLE + findViewById(R.id.fab_import_file_from_other_volume).visibility = View.VISIBLE + filesToCopy.clear() + } + } + + private fun copyFile(srcPath: String, dstPath: String): Boolean { var success = true - val srcHandleID = remote_gocryptfsVolume.open_read_mode(full_path) + val originalHandleId = gocryptfsVolume.open_read_mode(srcPath) + if (originalHandleId != -1){ + val newHandleId = gocryptfsVolume.open_write_mode(dstPath) + if (newHandleId != -1){ + var offset: Long = 0 + val ioBuffer = ByteArray(GocryptfsVolume.DefaultBS) + var length: Int + while (gocryptfsVolume.read_file(originalHandleId, offset, ioBuffer).also { length = it } > 0) { + val written = gocryptfsVolume.write_file(newHandleId, offset, ioBuffer, length).toLong() + if (written == length.toLong()) { + offset += written + } else { + success = false + break + } + } + gocryptfsVolume.close_file(newHandleId) + } else { + success = false + } + gocryptfsVolume.close_file(originalHandleId) + } else { + success = false + } + return success + } + + private fun recursiveCopyDirectory(srcDirectoryPath: String, outputPath: String): String? { + val mappedElements = recursiveMapFiles(srcDirectoryPath) + val dstDirectoryPath = PathUtils.path_join(outputPath, File(srcDirectoryPath).name) + if (!gocryptfsVolume.path_exists(dstDirectoryPath)) { + if (!gocryptfsVolume.mkdir(dstDirectoryPath)) { + return dstDirectoryPath + } + } + for (e in mappedElements) { + val srcPath = e.getFullPath() + val dstPath = PathUtils.path_join(dstDirectoryPath, PathUtils.getRelativePath(srcDirectoryPath, srcPath)) + if (e.isDirectory) { + if (!gocryptfsVolume.mkdir(dstPath)){ + return srcPath + } + } else { + if (!copyFile(srcPath, dstPath)) { + return srcPath + } + } + } + return null + } + + private fun importFileFromOtherVolume(remote_gocryptfsVolume: GocryptfsVolume, srcPath: String, dstPath: String): Boolean { + var success = true + val srcHandleID = remote_gocryptfsVolume.open_read_mode(srcPath) if (srcHandleID != -1) { - val dstHandleID = gocryptfsVolume.open_write_mode(outputPath) + val dstHandleID = gocryptfsVolume.open_write_mode(dstPath) if (dstHandleID != -1) { var length: Int val ioBuffer = ByteArray(GocryptfsVolume.DefaultBS) @@ -358,22 +500,24 @@ class ExplorerActivity : BaseExplorerActivity() { return success } - private fun recursiveImportDirectoryFromOtherVolume(remote_gocryptfsVolume: GocryptfsVolume, remote_directory_path: String, output_dir: String): String? { - val directoryPath = PathUtils.path_join(output_dir, File(remote_directory_path).name) - if (!gocryptfsVolume.path_exists(directoryPath)) { - if (!gocryptfsVolume.mkdir(directoryPath)) { - return directoryPath + private fun recursiveImportDirectoryFromOtherVolume(remote_gocryptfsVolume: GocryptfsVolume, remote_directory_path: String, outputPath: String): String? { + val mappedElements = recursiveMapFiles(remote_directory_path) + val dstDirectoryPath = PathUtils.path_join(outputPath, File(remote_directory_path).name) + if (!gocryptfsVolume.path_exists(dstDirectoryPath)) { + if (!gocryptfsVolume.mkdir(dstDirectoryPath)) { + return dstDirectoryPath } } - val explorerElements = remote_gocryptfsVolume.list_dir(remote_directory_path) - for (e in explorerElements) { - val fullPath = PathUtils.path_join(remote_directory_path, e.name) + for (e in mappedElements) { + val srcPath = e.getFullPath() + val dstPath = PathUtils.path_join(dstDirectoryPath, PathUtils.getRelativePath(remote_directory_path, srcPath)) if (e.isDirectory) { - val failedItem = recursiveImportDirectoryFromOtherVolume(remote_gocryptfsVolume, fullPath, directoryPath) - failedItem?.let { return it } + if (!gocryptfsVolume.mkdir(dstPath)){ + return srcPath + } } else { - if (!importFileFromOtherVolume(remote_gocryptfsVolume, fullPath, directoryPath)) { - return fullPath + if (!importFileFromOtherVolume(remote_gocryptfsVolume, srcPath, dstPath)) { + return srcPath } } } diff --git a/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivityDrop.kt b/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivityDrop.kt index efe46ec..a8e926d 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivityDrop.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivityDrop.kt @@ -2,6 +2,7 @@ package sushi.hardcore.droidfs.explorers import android.content.Intent import android.net.Uri +import android.util.Log import android.view.Menu import android.view.MenuItem import sushi.hardcore.droidfs.R @@ -16,48 +17,48 @@ class ExplorerActivityDrop : BaseExplorerActivity() { override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.explorer_drop, menu) handleMenuItems(menu) - menu.findItem(R.id.explorer_menu_validate).isVisible = explorerAdapter.selectedItems.isEmpty() + menu.findItem(R.id.validate).isVisible = explorerAdapter.selectedItems.isEmpty() return true } override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.itemId) { - R.id.explorer_menu_validate -> { + R.id.validate -> { val alertDialog = ColoredAlertDialogBuilder(this) alertDialog.setCancelable(false) alertDialog.setPositiveButton(R.string.ok) { _, _ -> finish() } - var error_msg: String? = null + var errorMsg: String? = null val extras = intent.extras if (extras != null && extras.containsKey(Intent.EXTRA_STREAM)){ if (intent.action == Intent.ACTION_SEND) { val uri = intent.getParcelableExtra(Intent.EXTRA_STREAM) - val output_path = PathUtils.path_join(currentDirectoryPath, PathUtils.getFilenameFromURI(this, uri)) - error_msg = if (gocryptfsVolume.import_file(this, uri, output_path)) null else getString(R.string.import_failed, output_path) + val outputPath = PathUtils.path_join(currentDirectoryPath, PathUtils.getFilenameFromURI(this, uri)) + errorMsg = if (gocryptfsVolume.import_file(this, uri, outputPath)) null else getString(R.string.import_failed, outputPath) } else if (intent.action == Intent.ACTION_SEND_MULTIPLE) { val uris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM) if (uris != null){ for (uri in uris) { - val output_path = PathUtils.path_join(currentDirectoryPath, PathUtils.getFilenameFromURI(this, uri)) - if (!gocryptfsVolume.import_file(this, uri, output_path)) { - error_msg = getString(R.string.import_failed, output_path) + val outputPath = PathUtils.path_join(currentDirectoryPath, PathUtils.getFilenameFromURI(this, uri)) + if (!gocryptfsVolume.import_file(this, uri, outputPath)) { + errorMsg = getString(R.string.import_failed, outputPath) break } } } else { - error_msg = getString(R.string.share_intent_parsing_failed) + errorMsg = getString(R.string.share_intent_parsing_failed) } } else { - error_msg = getString(R.string.share_intent_parsing_failed) + errorMsg = getString(R.string.share_intent_parsing_failed) } } else { - error_msg = getString(R.string.share_intent_parsing_failed) + errorMsg = getString(R.string.share_intent_parsing_failed) } - if (error_msg == null) { + if (errorMsg == null) { alertDialog.setTitle(R.string.success_import) alertDialog.setMessage(R.string.success_import_msg) } else { alertDialog.setTitle(R.string.error) - alertDialog.setMessage(error_msg) + alertDialog.setMessage(errorMsg) } alertDialog.show() true diff --git a/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivityPick.kt b/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivityPick.kt index 52f99c7..2dadd9b 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivityPick.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivityPick.kt @@ -27,7 +27,7 @@ class ExplorerActivityPick : BaseExplorerActivity() { setCurrentPath(full_path) } explorerElements[position].isParentFolder -> { - setCurrentPath(PathUtils.get_parent_path(currentDirectoryPath)) + setCurrentPath(PathUtils.getParentPath(currentDirectoryPath)) } else -> { result_intent.putExtra("path", full_path) @@ -43,19 +43,19 @@ class ExplorerActivityPick : BaseExplorerActivity() { menuInflater.inflate(R.menu.explorer_pick, menu) handleMenuItems(menu) val any_item_selected = explorerAdapter.selectedItems.isNotEmpty() - menu.findItem(R.id.explorer_menu_select_all).isVisible = any_item_selected - menu.findItem(R.id.explorer_menu_validate).isVisible = any_item_selected + menu.findItem(R.id.select_all).isVisible = any_item_selected + menu.findItem(R.id.validate).isVisible = any_item_selected return true } override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.itemId) { - R.id.explorer_menu_select_all -> { + R.id.select_all -> { explorerAdapter.selectAll() invalidateOptionsMenu() true } - R.id.explorer_menu_validate -> { + R.id.validate -> { val paths = ArrayList() val types = ArrayList() for (i in explorerAdapter.selectedItems) { @@ -79,7 +79,7 @@ class ExplorerActivityPick : BaseExplorerActivity() { override fun closeVolumeOnDestroy() { //don't close volume - RestrictedFileProvider.wipeAll() + RestrictedFileProvider.wipeAll(this) } override fun closeVolumeOnUserExit() { diff --git a/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerElement.kt b/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerElement.kt index 4919385..5e81c2d 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerElement.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerElement.kt @@ -1,8 +1,9 @@ package sushi.hardcore.droidfs.explorers +import sushi.hardcore.droidfs.util.PathUtils import java.util.* -class ExplorerElement(val name: String, val elementType: Short, val size: Long, mtime: Long) { +class ExplorerElement(val name: String, val elementType: Short, val size: Long, mtime: Long, private val parentPath: String) { val mTime = Date((mtime * 1000).toString().toLong()) val isDirectory: Boolean @@ -14,4 +15,7 @@ class ExplorerElement(val name: String, val elementType: Short, val size: Long, val isRegularFile: Boolean get() = elementType.toInt() == 1 + fun getFullPath(): String { + return PathUtils.path_join(parentPath, name) + } } \ No newline at end of file diff --git a/app/src/main/java/sushi/hardcore/droidfs/file_viewers/GocryptfsDataSource.kt b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/GocryptfsDataSource.kt index ff2cd61..b7f1ce7 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/file_viewers/GocryptfsDataSource.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/GocryptfsDataSource.kt @@ -4,6 +4,8 @@ import android.net.Uri import com.google.android.exoplayer2.upstream.* import sushi.hardcore.droidfs.ConstValues import sushi.hardcore.droidfs.util.GocryptfsVolume +import kotlin.math.ceil +import kotlin.math.min class GocryptfsDataSource(private val gocryptfsVolume: GocryptfsVolume, private val filePath: String): DataSource { private var handleID = -1 @@ -34,15 +36,20 @@ class GocryptfsDataSource(private val gocryptfsVolume: GocryptfsVolume, private if (fileOffset >= fileSize){ return -1 } - val tmpBuff = if (fileOffset+readLength > fileSize){ - ByteArray((fileSize-fileOffset).toInt()) - } else { - ByteArray(readLength) + var totalRead = 0 + for (i in 0 until ceil(readLength.toDouble()/ConstValues.MAX_KERNEL_WRITE).toInt()){ + val tmpReadLength = min(readLength-totalRead, ConstValues.MAX_KERNEL_WRITE) + val tmpBuff = if (fileOffset+tmpReadLength > fileSize){ + ByteArray((fileSize-fileOffset).toInt()) + } else { + ByteArray(tmpReadLength) + } + val read = gocryptfsVolume.read_file(handleID, fileOffset, tmpBuff) + System.arraycopy(tmpBuff, 0, buffer, offset+totalRead, read) + fileOffset += read + totalRead += read } - val read = gocryptfsVolume.read_file(handleID, fileOffset, tmpBuff) - fileOffset += read - System.arraycopy(tmpBuff, 0, buffer, offset, read) - return read + return totalRead } class Factory(private val gocryptfsVolume: GocryptfsVolume, private val filePath: String): DataSource.Factory{ diff --git a/app/src/main/java/sushi/hardcore/droidfs/provider/RestrictedFileProvider.kt b/app/src/main/java/sushi/hardcore/droidfs/provider/RestrictedFileProvider.kt index 7cbe02d..0f1bfa9 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/provider/RestrictedFileProvider.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/provider/RestrictedFileProvider.kt @@ -2,12 +2,17 @@ package sushi.hardcore.droidfs.provider import android.content.ContentProvider import android.content.ContentValues +import android.content.Context import android.database.Cursor import android.database.MatrixCursor +import android.database.sqlite.SQLiteDatabase +import android.database.sqlite.SQLiteOpenHelper import android.net.Uri import android.os.ParcelFileDescriptor import android.provider.MediaStore import sushi.hardcore.droidfs.BuildConfig +import sushi.hardcore.droidfs.util.SQLUtil.appendSelectionArgs +import sushi.hardcore.droidfs.util.SQLUtil.concatenateWhere import sushi.hardcore.droidfs.util.Wiper import java.io.File import java.util.* @@ -15,48 +20,105 @@ import java.util.regex.Pattern class RestrictedFileProvider: ContentProvider() { companion object { + private const val DB_NAME = "temporary_files.db" + private const val TABLE_FILES = "files" + private const val DB_VERSION = 3 + private var dbHelper: RestrictedDatabaseHelper? = null private const val AUTHORITY = BuildConfig.APPLICATION_ID + ".temporary_provider" private val CONTENT_URI: Uri = Uri.parse("content://$AUTHORITY") const val TEMPORARY_FILES_DIR_NAME = "temp" private val UUID_PATTERN = Pattern.compile("[a-fA-F0-9-]+") private lateinit var tempFilesDir: File - private val tempFiles = mutableMapOf() - class TemporaryFile(val fileName: String, val file: File) + internal class TemporaryFileColumns { + companion object { + const val COLUMN_UUID = "uuid" + const val COLUMN_NAME = "name" + } + } + + internal class RestrictedDatabaseHelper(context: Context?): SQLiteOpenHelper(context, DB_NAME, null, DB_VERSION) { + override fun onCreate(db: SQLiteDatabase) { + db.execSQL( + "CREATE TABLE IF NOT EXISTS " + TABLE_FILES + " (" + + TemporaryFileColumns.COLUMN_UUID + " TEXT PRIMARY KEY, " + + TemporaryFileColumns.COLUMN_NAME + " TEXT" + + ");" + ) + } + + override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { + if (oldVersion == 1) { + db.execSQL("DROP TABLE IF EXISTS files") + db.execSQL( + "CREATE TABLE IF NOT EXISTS " + TABLE_FILES + " (" + + TemporaryFileColumns.COLUMN_UUID + " TEXT PRIMARY KEY, " + + TemporaryFileColumns.COLUMN_NAME + " TEXT" + + ");" + ) + } + } + } fun newFile(fileName: String): Uri? { val uuid = UUID.randomUUID().toString() val file = File(tempFilesDir, uuid) return if (file.createNewFile()){ - tempFiles[uuid] = TemporaryFile(fileName, file) - Uri.withAppendedPath(CONTENT_URI, uuid) + val contentValues = ContentValues() + contentValues.put(TemporaryFileColumns.COLUMN_UUID, uuid) + contentValues.put(TemporaryFileColumns.COLUMN_NAME, fileName) + if (dbHelper?.writableDatabase?.insert(TABLE_FILES, null, contentValues)?.toInt() != -1){ + Uri.withAppendedPath(CONTENT_URI, uuid) + } else { + null + } } else { null } } - fun wipeAll() { + fun wipeAll(context: Context) { tempFilesDir.listFiles()?.let{ for (file in it) { Wiper.wipe(file) } } + context.deleteDatabase(DB_NAME) } - private fun getFileFromUri(uri: Uri): TemporaryFile? { + private fun isValidUUID(uuid: String): Boolean { + return UUID_PATTERN.matcher(uuid).matches() + } + + private fun getUuidFromUri(uri: Uri): String? { val uuid = uri.lastPathSegment if (uuid != null) { - if (UUID_PATTERN.matcher(uuid).matches()) { - return tempFiles[uuid] + if (isValidUUID(uuid)) { + return uuid } } return null } + + private fun getFileFromUUID(uuid: String): File? { + if (isValidUUID(uuid)){ + return File(tempFilesDir, uuid) + } + return null + } + + private fun getFileFromUri(uri: Uri): File? { + getUuidFromUri(uri)?.let { + return getFileFromUUID(it) + } + return null + } } override fun onCreate(): Boolean { context?.let { + dbHelper = RestrictedDatabaseHelper(it) tempFilesDir = File(it.cacheDir, TEMPORARY_FILES_DIR_NAME) return tempFilesDir.mkdirs() } @@ -73,28 +135,47 @@ class RestrictedFileProvider: ContentProvider() { override fun query(uri: Uri, projection: Array?, selection: String?, selectionArgs: Array?, sortOrder: String?): Cursor? { val temporaryFile = getFileFromUri(uri) - if (temporaryFile != null) { - val cursor = MatrixCursor( - arrayOf( - MediaStore.MediaColumns.DISPLAY_NAME, - MediaStore.MediaColumns.SIZE - ) - ) - cursor.newRow() - .add(temporaryFile.fileName) - .add(temporaryFile.file.length()) - return cursor + temporaryFile?.let{ + val fileName = + dbHelper?.readableDatabase?.query(TABLE_FILES, arrayOf(TemporaryFileColumns.COLUMN_NAME), TemporaryFileColumns.COLUMN_UUID + "=?", arrayOf(uri.lastPathSegment), null, null, null) + fileName?.let{ + if (fileName.moveToNext()) { + val cursor = MatrixCursor( + arrayOf( + MediaStore.MediaColumns.DISPLAY_NAME, + MediaStore.MediaColumns.SIZE + ) + ) + cursor.newRow() + .add(fileName.getString(0)) + .add(temporaryFile.length()) + fileName.close() + return cursor + } + fileName.close() + } } return null } - override fun delete(uri: Uri, selection: String?, selectionArgs: Array?): Int { - val temporaryFile = getFileFromUri(uri) - if (temporaryFile != null) { - Wiper.wipe(temporaryFile.file) - tempFiles.remove(uri.lastPathSegment) + override fun delete(uri: Uri, givenSelection: String?, givenSelectionArgs: Array?): Int { + val uuid = getUuidFromUri(uri) + uuid?.let{ + val selection = concatenateWhere(givenSelection ?: "" , TemporaryFileColumns.COLUMN_UUID + "=?") + val selectionArgs = appendSelectionArgs(givenSelectionArgs, arrayOf(it)) + + val files = dbHelper?.readableDatabase?.query(TABLE_FILES, arrayOf(TemporaryFileColumns.COLUMN_UUID), selection, selectionArgs, null, null, null) + if (files != null) { + while (files.moveToNext()) { + getFileFromUUID(files.getString(0))?.let { file -> + Wiper.wipe(file) + } + } + files.close() + return dbHelper?.writableDatabase?.delete(TABLE_FILES, selection, selectionArgs) ?: 0 + } } - return 1 + return 0 } override fun getType(uri: Uri): String { @@ -104,7 +185,7 @@ class RestrictedFileProvider: ContentProvider() { override fun openFile(uri: Uri, mode: String): ParcelFileDescriptor? { if (("w" in mode && callingPackage == BuildConfig.APPLICATION_ID) || "w" !in mode) { getFileFromUri(uri)?.let{ - return ParcelFileDescriptor.open(it.file, ParcelFileDescriptor.parseMode(mode)) + return ParcelFileDescriptor.open(it, ParcelFileDescriptor.parseMode(mode)) } } else { throw SecurityException("Read-only access") diff --git a/app/src/main/java/sushi/hardcore/droidfs/util/ExternalProvider.kt b/app/src/main/java/sushi/hardcore/droidfs/util/ExternalProvider.kt index a8e00c7..0081dc0 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/util/ExternalProvider.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/util/ExternalProvider.kt @@ -9,7 +9,6 @@ import sushi.hardcore.droidfs.provider.RestrictedFileProvider import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder import java.io.File import java.net.URLConnection -import java.util.* import kotlin.collections.ArrayList object ExternalProvider { @@ -102,13 +101,13 @@ object ExternalProvider { fun removeFiles(context: Context) { Thread{ - val wiped = ArrayList() - for (uri in storedFiles) { - if (Wiper.wipe(context, uri) == null){ - wiped.add(uri) + val success = ArrayList() + for (uri in storedFiles){ + if (context.contentResolver.delete(uri, null, null) == 1){ + success.add(uri) } } - for (uri in wiped){ + for (uri in success){ storedFiles.remove(uri) } }.start() diff --git a/app/src/main/java/sushi/hardcore/droidfs/util/GocryptfsVolume.kt b/app/src/main/java/sushi/hardcore/droidfs/util/GocryptfsVolume.kt index 13f8a7a..f1f101e 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/util/GocryptfsVolume.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/util/GocryptfsVolume.kt @@ -2,7 +2,6 @@ package sushi.hardcore.droidfs.util import android.content.Context import android.net.Uri -import android.util.Log import sushi.hardcore.droidfs.explorers.ExplorerElement import java.io.* @@ -93,10 +92,10 @@ class GocryptfsVolume(var sessionID: Int) { fun export_file(handleID: Int, os: OutputStream): Boolean { var offset: Long = 0 - val io_buffer = ByteArray(DefaultBS) + val ioBuffer = ByteArray(DefaultBS) var length: Int - while (native_read_file(sessionID, handleID, offset, io_buffer).also { length = it } > 0){ - os.write(io_buffer, 0, length) + while (native_read_file(sessionID, handleID, offset, ioBuffer).also { length = it } > 0){ + os.write(ioBuffer, 0, length) offset += length.toLong() } os.close() @@ -105,10 +104,10 @@ class GocryptfsVolume(var sessionID: Int) { fun export_file(src_path: String, os: OutputStream): Boolean { var success = false - val src_handleID = open_read_mode(src_path) - if (src_handleID != -1) { - success = export_file(src_handleID, os) - close_file(src_handleID) + val srcHandleId = open_read_mode(src_path) + if (srcHandleId != -1) { + success = export_file(srcHandleId, os) + close_file(srcHandleId) } return success } @@ -127,10 +126,10 @@ class GocryptfsVolume(var sessionID: Int) { fun import_file(inputStream: InputStream, handleID: Int): Boolean { var offset: Long = 0 - val io_buffer = ByteArray(DefaultBS) + val ioBuffer = ByteArray(DefaultBS) var length: Int - while (inputStream.read(io_buffer).also { length = it } > 0) { - val written = native_write_file(sessionID, handleID, offset, io_buffer, length).toLong() + while (inputStream.read(ioBuffer).also { length = it } > 0) { + val written = native_write_file(sessionID, handleID, offset, ioBuffer, length).toLong() if (written == length.toLong()) { offset += written } else { @@ -145,10 +144,10 @@ class GocryptfsVolume(var sessionID: Int) { fun import_file(inputStream: InputStream, dst_path: String): Boolean { var success = false - val dst_handleID = open_write_mode(dst_path) - if (dst_handleID != -1) { - success = import_file(inputStream, dst_handleID) - close_file(dst_handleID) + val dstHandleId = open_write_mode(dst_path) + if (dstHandleId != -1) { + success = import_file(inputStream, dstHandleId) + close_file(dstHandleId) } return success } diff --git a/app/src/main/java/sushi/hardcore/droidfs/util/PathUtils.java b/app/src/main/java/sushi/hardcore/droidfs/util/PathUtils.java index 8647394..523fc52 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/util/PathUtils.java +++ b/app/src/main/java/sushi/hardcore/droidfs/util/PathUtils.java @@ -14,7 +14,7 @@ import java.text.DecimalFormat; public class PathUtils { - public static String get_parent_path(String path){ + public static String getParentPath(String path){ if (path.endsWith("/")){ String a = path.substring(0, path.length()-2); if (a.contains("/")){ @@ -44,16 +44,22 @@ public class PathUtils { return result.substring(0, result.length()-1); } + public static String getRelativePath(String parentPath, String childPath){ + return childPath.substring(parentPath.length()+1); + } + public static String getFilenameFromURI(Context context, Uri uri){ String result = null; if (uri.getScheme().equals("content")){ Cursor cursor = context.getContentResolver().query(uri, null, null, null, null); - try { - if (cursor != null && cursor.moveToFirst()){ - result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); + if (cursor != null){ + try { + if (cursor.moveToFirst()){ + result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); + } + } finally { + cursor.close(); } - } finally { - cursor.close(); } } if (result == null){ diff --git a/app/src/main/java/sushi/hardcore/droidfs/util/SQLUtil.kt b/app/src/main/java/sushi/hardcore/droidfs/util/SQLUtil.kt new file mode 100644 index 0000000..b727298 --- /dev/null +++ b/app/src/main/java/sushi/hardcore/droidfs/util/SQLUtil.kt @@ -0,0 +1,24 @@ +package sushi.hardcore.droidfs.util + +object SQLUtil { + @JvmStatic + fun concatenateWhere(a: String, b: String): String { + if (a.isEmpty()) { + return b + } + return if (b.isEmpty()) { + a + } else "($a) AND ($b)" + } + + @JvmStatic + fun appendSelectionArgs(originalValues: Array?, newValues: Array): Array { + if (originalValues == null || originalValues.isEmpty()) { + return newValues + } + val result = Array(originalValues.size + newValues.size){ "it = $it" } + System.arraycopy(originalValues, 0, result, 0, originalValues.size) + System.arraycopy(newValues, 0, result, originalValues.size, newValues.size) + return result + } +} \ No newline at end of file diff --git a/app/src/main/java/sushi/hardcore/droidfs/widgets/ThemeColor.kt b/app/src/main/java/sushi/hardcore/droidfs/widgets/ThemeColor.kt index 8418c79..2b4abcb 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/widgets/ThemeColor.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/widgets/ThemeColor.kt @@ -1,8 +1,6 @@ package sushi.hardcore.droidfs.widgets import android.content.Context -import android.graphics.Color -import android.graphics.drawable.Drawable import androidx.core.content.ContextCompat import androidx.core.graphics.drawable.DrawableCompat import androidx.preference.Preference @@ -20,9 +18,8 @@ object ThemeColor { for (i in 0 until preference.preferenceCount) { tintPreferenceIcons(preference.getPreference(i), color) } - } else { - val icon: Drawable = preference.icon - DrawableCompat.setTint(icon, color) + } else if (preference.icon != null) { + DrawableCompat.setTint(preference.icon, color) } } } diff --git a/app/src/main/native/gocryptfs_jni.c b/app/src/main/native/gocryptfs_jni.c index bfba488..fae1cec 100644 --- a/app/src/main/native/gocryptfs_jni.c +++ b/app/src/main/native/gocryptfs_jni.c @@ -227,7 +227,7 @@ Java_sushi_hardcore_droidfs_util_GocryptfsVolume_native_1list_1dir(JNIEnv *env, jmethodID java_util_ArrayList_add = (*env)->GetMethodID(env, java_util_ArrayList, "add", "(Ljava/lang/Object;)Z"); jclass classExplorerElement = (*env)->NewGlobalRef(env, (*env)->FindClass(env, "sushi/hardcore/droidfs/explorers/ExplorerElement")); - jmethodID classExplorerElement_init = (*env)->GetMethodID(env, classExplorerElement, "", "(Ljava/lang/String;SJJ)V"); + jmethodID classExplorerElement_init = (*env)->GetMethodID(env, classExplorerElement, "", "(Ljava/lang/String;SJJLjava/lang/String;)V"); jobject element_list = (*env)->NewObject(env, java_util_ArrayList, java_util_ArrayList_init, elements.r2); unsigned int c = 0; @@ -254,7 +254,7 @@ Java_sushi_hardcore_droidfs_util_GocryptfsVolume_native_1list_1dir(JNIEnv *env, type = 1; //regular file } jstring jname = (*env)->NewStringUTF(env, name); - jobject explorerElement = (*env)->NewObject(env, classExplorerElement, classExplorerElement_init, jname, type, (long long)attrs.r0, attrs.r1); + jobject explorerElement = (*env)->NewObject(env, classExplorerElement, classExplorerElement_init, jname, type, (long long)attrs.r0, attrs.r1, jplain_dir); (*env)->CallBooleanMethod(env, element_list, java_util_ArrayList_add, explorerElement); c += name_len+1; } diff --git a/app/src/main/res/drawable/icon_copy.xml b/app/src/main/res/drawable/icon_copy.xml new file mode 100644 index 0000000..1a638c9 --- /dev/null +++ b/app/src/main/res/drawable/icon_copy.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/icon_decrypt.xml b/app/src/main/res/drawable/icon_decrypt.xml index f48247a..f954e2c 100644 --- a/app/src/main/res/drawable/icon_decrypt.xml +++ b/app/src/main/res/drawable/icon_decrypt.xml @@ -1,12 +1,4 @@ - - - - - \ No newline at end of file + + + diff --git a/app/src/main/res/drawable/icon_encrypt.xml b/app/src/main/res/drawable/icon_encrypt.xml new file mode 100644 index 0000000..46412c1 --- /dev/null +++ b/app/src/main/res/drawable/icon_encrypt.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/app/src/main/res/drawable/icon_github.xml b/app/src/main/res/drawable/icon_github.xml new file mode 100644 index 0000000..0ffbbbc --- /dev/null +++ b/app/src/main/res/drawable/icon_github.xml @@ -0,0 +1,10 @@ + + + + + diff --git a/app/src/main/res/drawable/icon_transfert.xml b/app/src/main/res/drawable/icon_transfert.xml new file mode 100644 index 0000000..f867984 --- /dev/null +++ b/app/src/main/res/drawable/icon_transfert.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/logo.png b/app/src/main/res/drawable/logo.png index 127b9ccf51960cdc6ebd9c3a0063ce83a86b8690..426babc6575e8f0237839c8ca1f95d77373d8a6f 100644 GIT binary patch literal 49720 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 literal 43443 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 diff --git a/app/src/main/res/layout/activity_explorer.xml b/app/src/main/res/layout/activity_explorer.xml index 81550ca..586737e 100644 --- a/app/src/main/res/layout/activity_explorer.xml +++ b/app/src/main/res/layout/activity_explorer.xml @@ -47,37 +47,39 @@ app:menu_labels_style="@style/fab_label"> diff --git a/app/src/main/res/layout/activity_explorer_drop.xml b/app/src/main/res/layout/activity_explorer_drop.xml index ce8ea80..d723756 100644 --- a/app/src/main/res/layout/activity_explorer_drop.xml +++ b/app/src/main/res/layout/activity_explorer_drop.xml @@ -45,12 +45,12 @@ app:menu_labels_style="@style/fab_label"> diff --git a/app/src/main/res/menu/explorer.xml b/app/src/main/res/menu/explorer.xml index 67e320c..9b98333 100644 --- a/app/src/main/res/menu/explorer.xml +++ b/app/src/main/res/menu/explorer.xml @@ -3,52 +3,63 @@ xmlns:app="http://schemas.android.com/apk/res-auto"> + + - - + android:title="@string/decrypt"/> + + + android:id="@+id/validate" + app:showAsAction="ifRoom" + android:visible="false" + android:icon="@drawable/icon_check"/> + + - \ No newline at end of file + diff --git a/app/src/main/res/menu/explorer_drop.xml b/app/src/main/res/menu/explorer_drop.xml index 6ee8a12..3577a36 100644 --- a/app/src/main/res/menu/explorer_drop.xml +++ b/app/src/main/res/menu/explorer_drop.xml @@ -3,31 +3,30 @@ xmlns:app="http://schemas.android.com/apk/res-auto"> + android:icon="@drawable/icon_sort"/> - \ No newline at end of file + diff --git a/app/src/main/res/menu/explorer_pick.xml b/app/src/main/res/menu/explorer_pick.xml index c19758c..d01e433 100644 --- a/app/src/main/res/menu/explorer_pick.xml +++ b/app/src/main/res/menu/explorer_pick.xml @@ -3,32 +3,31 @@ xmlns:app="http://schemas.android.com/apk/res-auto"> + android:icon="@drawable/icon_sort"/> - \ No newline at end of file + diff --git a/app/src/main/res/mipmap/ic_launcher.png b/app/src/main/res/mipmap/ic_launcher.png deleted file mode 100644 index 0fd497608b5299635b352315b04770d90fc9f4fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9708 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 diff --git a/app/src/main/res/mipmap/icon_launcher.png b/app/src/main/res/mipmap/icon_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..164d6d73b824784d3329f40c6d6795d7c35ed50a GIT binary patch literal 8709 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 O^(`l*ELkOP6!0G=b7R~9 literal 0 HcmV?d00001 diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 8d7955d..28d12b9 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -12,7 +12,6 @@ #FFFFFF #5B5A5C #66666666 - #FFFFFF #111111 #FFFFFF #6CC341 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e16c41a..6727659 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -21,7 +21,7 @@ The selected files have been successfully imported. Import of %1$s failed. Export of %1$s failed. - Export Successful ! + Export successful ! The selected files have been successfully exported. Deletion of %1$s failed Passwords don\'t match @@ -130,4 +130,13 @@ Wiping original files… Exporting files… Unable to access this file + About + GitHub + Want to read the documentation, request feature, report bug, read the source code… Check the DroidFS\'s repository ! + Share + Decrypt + Copying selected items... + Copy of %1$s failed. + The selected items have been successfully copied. + Copy successful ! diff --git a/app/src/main/res/xml/root_preferences.xml b/app/src/main/res/xml/root_preferences.xml index e802898..8c317c4 100644 --- a/app/src/main/res/xml/root_preferences.xml +++ b/app/src/main/res/xml/root_preferences.xml @@ -24,11 +24,24 @@ + + + + + + + + + + \ No newline at end of file