Rework how the app handles the removal of plain copy of encrypted files when VFS is enabled

This commit is contained in:
Sylvain Berfini 2023-04-03 09:50:54 +02:00
parent 31e30e6214
commit 09d5868820
10 changed files with 42 additions and 48 deletions

View file

@ -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

View file

@ -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 ?: ""

View file

@ -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()
}
}
},

View file

@ -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)
}

View file

@ -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

View file

@ -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

View file

@ -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()
}

View file

@ -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)

View file

@ -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}")
}
)
}

View file

@ -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
}
}
}