From 39e43fa9236a7aef879ec8a49c576f08d3861ecb Mon Sep 17 00:00:00 2001 From: a1denvalu3 <43107113+a1denvalu3@users.noreply.github.com> Date: Thu, 15 Jan 2026 16:32:30 +0100 Subject: [PATCH] security: ensure media files are deleted during panic mode (#607) Closes #591 - Added FileUtils.clearAllMedia() to recursively delete media directories and cache. - Called clearAllMedia() in ChatViewModel.panicClearAllData(). fix: correct voice notes directory path for cleanup - Updated FileUtils.clearAllMedia to use 'voicenotes' instead of 'voice_notes' to match VoiceRecorder.kt fix: update media cleanup to include cache directories - Updated FileUtils.clearAllMedia to explicitly clean 'files/incoming' and 'images/incoming' from context.cacheDir, reflecting the storage location change from issue #592. - Maintained legacy cleanup for context.filesDir. Co-authored-by: a1denvalu3 <> --- .../android/features/file/FileUtils.kt | 50 +++++++++++++++++++ .../com/bitchat/android/ui/ChatViewModel.kt | 3 ++ 2 files changed, 53 insertions(+) diff --git a/app/src/main/java/com/bitchat/android/features/file/FileUtils.kt b/app/src/main/java/com/bitchat/android/features/file/FileUtils.kt index a1f83a7e..10765416 100644 --- a/app/src/main/java/com/bitchat/android/features/file/FileUtils.kt +++ b/app/src/main/java/com/bitchat/android/features/file/FileUtils.kt @@ -273,4 +273,54 @@ object FileUtils { else -> com.bitchat.android.model.BitchatMessageType.File } } + + /** + * Recursively delete all media files (incoming and outgoing) + * Used for Panic Mode cleanup + */ + fun clearAllMedia(context: Context) { + try { + // Clear files dir subdirectories (legacy storage and outgoing) + val filesDir = context.filesDir + val dirsToClear = listOf( + "files/incoming", + "files/outgoing", + "images/incoming", + "images/outgoing", + "voicenotes" + ) + + dirsToClear.forEach { subDir -> + val dir = File(filesDir, subDir) + if (dir.exists()) { + dir.deleteRecursively() + Log.d(TAG, "Deleted media directory from filesDir: $subDir") + } + } + + // Clear cache dir subdirectories (new incoming storage) + // Note: cacheDir.deleteRecursively() below would handle this, but being explicit ensures these + // specific media folders are targeted even if full cache clear fails or is modified later. + val cacheDir = context.cacheDir + val cacheDirsToClear = listOf( + "files/incoming", + "images/incoming" + ) + + cacheDirsToClear.forEach { subDir -> + val dir = File(cacheDir, subDir) + if (dir.exists()) { + dir.deleteRecursively() + Log.d(TAG, "Deleted media directory from cacheDir: $subDir") + } + } + + // Also clear entire cache dir as a catch-all + context.cacheDir.deleteRecursively() + Log.d(TAG, "Cleared entire cache directory") + + } catch (e: Exception) { + Log.e(TAG, "Failed to clear media files", e) + } + } } diff --git a/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt b/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt index ca33a6a9..5456ca4d 100644 --- a/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt +++ b/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt @@ -926,6 +926,9 @@ class ChatViewModel( // Clear all notifications notificationManager.clearAllNotifications() + + // Clear all media files + com.bitchat.android.features.file.FileUtils.clearAllMedia(getApplication()) // Clear Nostr/geohash state, keys, connections, bookmarks, and reinitialize from scratch try {