Rework how the app handles the removal of plain copy of encrypted files when VFS is enabled
This commit is contained in:
parent
31e30e6214
commit
09d5868820
10 changed files with 42 additions and 48 deletions
|
@ -24,6 +24,9 @@ Group changes to describe their impact on the project, as follows:
|
|||
- Replaced voice recordings file name by localized placeholder text, like for video conferences invitations
|
||||
- Removed jetifier as it is not needed
|
||||
|
||||
### Fixed
|
||||
- Plain copy of encrypted files (when VFS is enabled) not cleaned
|
||||
|
||||
## [5.0.8] - 2023-03-20
|
||||
|
||||
### Fixed
|
||||
|
|
|
@ -209,7 +209,7 @@ class ChatMessageContentData(
|
|||
private fun deletePlainFilePath() {
|
||||
val path = filePath.value.orEmpty()
|
||||
if (path.isNotEmpty() && isFileEncrypted) {
|
||||
Log.i("[Content] Deleting file used for preview: $path")
|
||||
Log.i("[Content] [VFS] Deleting file used for preview: $path")
|
||||
FileUtils.deleteFile(path)
|
||||
filePath.value = ""
|
||||
}
|
||||
|
@ -247,7 +247,7 @@ class ChatMessageContentData(
|
|||
|
||||
if (content.isFile || (content.isFileTransfer && chatMessage.isOutgoing)) {
|
||||
val path = if (isFileEncrypted) {
|
||||
Log.i("[Content] Content is encrypted, requesting plain file path")
|
||||
Log.i("[Content] [VFS] Content is encrypted, requesting plain file path for file [${content.filePath}]")
|
||||
content.exportPlainFile()
|
||||
} else {
|
||||
content.filePath ?: ""
|
||||
|
|
|
@ -1204,16 +1204,10 @@ class DetailChatRoomFragment : MasterFragment<ChatRoomDetailFragmentBinding, Cha
|
|||
{
|
||||
dialog.dismiss()
|
||||
lifecycleScope.launch {
|
||||
Log.w("[Chat Room] Content is encrypted, requesting plain file path")
|
||||
Log.i("[Chat Room] [VFS] Content is encrypted, requesting plain file path for file [${content.filePath}]")
|
||||
val plainFilePath = content.exportPlainFile()
|
||||
Log.i("[Chat Room] Making a copy of [$plainFilePath] to the cache directory before exporting it")
|
||||
val cacheCopyPath = FileUtils.copyFileToCache(plainFilePath)
|
||||
if (cacheCopyPath != null) {
|
||||
Log.i("[Chat Room] Cache copy has been made: $cacheCopyPath")
|
||||
FileUtils.deleteFile(plainFilePath)
|
||||
if (!FileUtils.openFileInThirdPartyApp(requireActivity(), cacheCopyPath)) {
|
||||
showDialogToSuggestOpeningFileAsText()
|
||||
}
|
||||
if (!FileUtils.openFileInThirdPartyApp(requireActivity(), plainFilePath)) {
|
||||
showDialogToSuggestOpeningFileAsText()
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -33,7 +33,7 @@ open class FileViewerViewModel(val content: Content) : ViewModel() {
|
|||
|
||||
init {
|
||||
filePath = if (deleteAfterUse) {
|
||||
Log.i("[File Viewer] Content is encrypted, requesting plain file path")
|
||||
Log.i("[File Viewer] [VFS] Content is encrypted, requesting plain file path for file [${content.filePath}]")
|
||||
content.exportPlainFile()
|
||||
} else {
|
||||
content.filePath.orEmpty()
|
||||
|
@ -42,7 +42,7 @@ open class FileViewerViewModel(val content: Content) : ViewModel() {
|
|||
|
||||
override fun onCleared() {
|
||||
if (deleteAfterUse) {
|
||||
Log.i("[File Viewer] Deleting temporary plain file: $filePath")
|
||||
Log.i("[File Viewer] [VFS] Deleting temporary plain file [$filePath]")
|
||||
FileUtils.deleteFile(filePath)
|
||||
}
|
||||
|
||||
|
|
|
@ -168,7 +168,7 @@ class Api23Compatibility {
|
|||
val isContentEncrypted = content.isFileEncrypted
|
||||
val filePath = if (content.isFileEncrypted) {
|
||||
val plainFilePath = content.exportPlainFile().orEmpty()
|
||||
Log.w("[Media Store] Content is encrypted, plain file path is: $plainFilePath")
|
||||
Log.i("[Media Store] [VFS] Content is encrypted, plain file path is: $plainFilePath")
|
||||
plainFilePath
|
||||
} else content.filePath
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ class Api29Compatibility {
|
|||
val isContentEncrypted = content.isFileEncrypted
|
||||
val filePath = if (content.isFileEncrypted) {
|
||||
val plainFilePath = content.exportPlainFile().orEmpty()
|
||||
Log.w("[Media Store] Content is encrypted, plain file path is: $plainFilePath")
|
||||
Log.i("[Media Store] [VFS] Content is encrypted, plain file path is: $plainFilePath")
|
||||
plainFilePath
|
||||
} else content.filePath
|
||||
|
||||
|
|
|
@ -358,6 +358,10 @@ class CoreContext(
|
|||
collator.strength = Collator.NO_DECOMPOSITION
|
||||
|
||||
if (corePreferences.vfsEnabled) {
|
||||
val notClearedCount = FileUtils.countFilesInDirectory(corePreferences.vfsCachePath)
|
||||
if (notClearedCount != 0) {
|
||||
Log.w("[Context] [VFS] There are [$notClearedCount] plain files not cleared from previous app lifetime, removing them now")
|
||||
}
|
||||
FileUtils.clearExistingPlainFiles()
|
||||
}
|
||||
|
||||
|
|
|
@ -661,6 +661,9 @@ class CorePreferences constructor(private val context: Context) {
|
|||
val staticPicturePath: String
|
||||
get() = context.filesDir.absolutePath + "/share/images/nowebcamcif.jpg"
|
||||
|
||||
val vfsCachePath: String
|
||||
get() = context.cacheDir.absolutePath + "/evfs/"
|
||||
|
||||
fun copyAssetsFromPackage() {
|
||||
copy("linphonerc_default", configPath)
|
||||
copy("linphonerc_factory", factoryConfigPath, true)
|
||||
|
|
|
@ -324,12 +324,12 @@ fun loadRoundImageWithCoil(imageView: ImageView, path: String?) {
|
|||
@BindingAdapter("coil")
|
||||
fun loadImageWithCoil(imageView: ImageView, path: String?) {
|
||||
if (path != null && path.isNotEmpty() && FileUtils.isExtensionImage(path)) {
|
||||
if (corePreferences.vfsEnabled && path.endsWith(FileUtils.VFS_PLAIN_FILE_EXTENSION)) {
|
||||
if (corePreferences.vfsEnabled && path.startsWith(corePreferences.vfsCachePath)) {
|
||||
imageView.load(path) {
|
||||
diskCachePolicy(CachePolicy.DISABLED)
|
||||
listener(
|
||||
onError = { _, result ->
|
||||
Log.e("[Data Binding] [Coil] Error loading [$path]: ${result.throwable}")
|
||||
Log.e("[Data Binding] [VFS] [Coil] Error loading [$path]: ${result.throwable}")
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
@ -37,13 +37,12 @@ import kotlinx.coroutines.async
|
|||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.LinphoneApplication.Companion.corePreferences
|
||||
import org.linphone.R
|
||||
import org.linphone.core.tools.Log
|
||||
|
||||
class FileUtils {
|
||||
companion object {
|
||||
const val VFS_PLAIN_FILE_EXTENSION = ".bctbx_evfs_plain"
|
||||
|
||||
fun getNameFromFilePath(filePath: String): String {
|
||||
var name = filePath
|
||||
val i = filePath.lastIndexOf('/')
|
||||
|
@ -54,15 +53,11 @@ class FileUtils {
|
|||
}
|
||||
|
||||
fun getExtensionFromFileName(fileName: String): String {
|
||||
val realFileName = if (fileName.endsWith(VFS_PLAIN_FILE_EXTENSION)) {
|
||||
fileName.substring(0, fileName.length - VFS_PLAIN_FILE_EXTENSION.length)
|
||||
} else fileName
|
||||
|
||||
var extension = MimeTypeMap.getFileExtensionFromUrl(realFileName)
|
||||
var extension = MimeTypeMap.getFileExtensionFromUrl(fileName)
|
||||
if (extension.isNullOrEmpty()) {
|
||||
val i = realFileName.lastIndexOf('.')
|
||||
val i = fileName.lastIndexOf('.')
|
||||
if (i > 0) {
|
||||
extension = realFileName.substring(i + 1)
|
||||
extension = fileName.substring(i + 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,21 +97,10 @@ class FileUtils {
|
|||
}
|
||||
|
||||
fun clearExistingPlainFiles() {
|
||||
for (file in coreContext.context.filesDir.listFiles().orEmpty()) {
|
||||
if (file.path.endsWith(VFS_PLAIN_FILE_EXTENSION)) {
|
||||
Log.w("[File Utils] Found forgotten plain file: ${file.path}, deleting it")
|
||||
deleteFile(file.path)
|
||||
}
|
||||
}
|
||||
for (file in coreContext.context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)?.listFiles().orEmpty()) {
|
||||
if (file.path.endsWith(VFS_PLAIN_FILE_EXTENSION)) {
|
||||
Log.w("[File Utils] Found forgotten plain file: ${file.path}, deleting it")
|
||||
deleteFile(file.path)
|
||||
}
|
||||
}
|
||||
for (file in coreContext.context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)?.listFiles().orEmpty()) {
|
||||
if (file.path.endsWith(VFS_PLAIN_FILE_EXTENSION)) {
|
||||
Log.w("[File Utils] Found forgotten plain file: ${file.path}, deleting it")
|
||||
val dir = File(corePreferences.vfsCachePath)
|
||||
if (dir.exists()) {
|
||||
for (file in dir.listFiles().orEmpty()) {
|
||||
Log.w("[File Utils] [VFS] Found forgotten plain file [${file.path}], deleting it")
|
||||
deleteFile(file.path)
|
||||
}
|
||||
}
|
||||
|
@ -144,14 +128,10 @@ class FileUtils {
|
|||
val path = coreContext.context.cacheDir
|
||||
Log.i("[File Utils] Cache directory is: $path")
|
||||
|
||||
val realFileName = if (fileName.endsWith(VFS_PLAIN_FILE_EXTENSION)) {
|
||||
fileName.substring(0, fileName.length - VFS_PLAIN_FILE_EXTENSION.length)
|
||||
} else fileName
|
||||
var file = File(path, realFileName)
|
||||
|
||||
var file = File(path, fileName)
|
||||
var prefix = 1
|
||||
while (file.exists()) {
|
||||
file = File(path, prefix.toString() + "_" + realFileName)
|
||||
file = File(path, prefix.toString() + "_" + fileName)
|
||||
Log.w("[File Utils] File with that name already exists, renamed to ${file.name}")
|
||||
prefix += 1
|
||||
}
|
||||
|
@ -299,7 +279,9 @@ class FileUtils {
|
|||
} else {
|
||||
Log.e("[File Utils] Copy failed")
|
||||
}
|
||||
remoteFile?.close()
|
||||
withContext(Dispatchers.IO) {
|
||||
remoteFile?.close()
|
||||
}
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
Log.e("[File Utils] getFilePath exception: ", e)
|
||||
|
@ -535,5 +517,13 @@ class FileUtils {
|
|||
outStream.flush()
|
||||
outStream.close()
|
||||
}
|
||||
|
||||
fun countFilesInDirectory(path: String): Int {
|
||||
val dir = File(path)
|
||||
if (dir.exists()) {
|
||||
return dir.listFiles().orEmpty().size
|
||||
}
|
||||
return -1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue