diff --git a/TMessagesProj/src/main/assets/strings/strings_be.xml b/TMessagesProj/src/main/assets/strings/strings_be.xml index 00b7427f2..e9d5a3335 100644 --- a/TMessagesProj/src/main/assets/strings/strings_be.xml +++ b/TMessagesProj/src/main/assets/strings/strings_be.xml @@ -291,4 +291,6 @@ Уключыць сакрэтныя групы Сакрэтныя групы ўключаныя Сакрэтныя групы дазваляюць некалькім карыстальнікам размаўляць з выкарыстаннем скразнога шыфравання. Каб стварыць сакрэтную групу, уключыце гэты функцыянал пры дапамозе кнопкі вышэй, вярніцеся ў спіс дыялогаў, націсніце на іконку алоўка ў правым ніжнім куце і абярыце \"%1$s\". + Абарона файлаў + Абарона файлаў дазваляе абараніцца ад вымання файлаў прыкладання пры даглядзе тэлефона. Уключэнне опцыі можа прывесці да некарэктнай працы прыкладання. Вы можаце ўключыць гэтую опцыю, а потым, калі сутыкнецеся з праблемамі, адключыць яе. Уключэнне опцыі прывядзе да ачысткі кэша паведамленняў. Опцыя будзе прыменена пасля перазапуску прыкладання. \ No newline at end of file diff --git a/TMessagesProj/src/main/assets/strings/strings_ru.xml b/TMessagesProj/src/main/assets/strings/strings_ru.xml index 350cdf2fe..72081c617 100644 --- a/TMessagesProj/src/main/assets/strings/strings_ru.xml +++ b/TMessagesProj/src/main/assets/strings/strings_ru.xml @@ -291,4 +291,6 @@ Включить секретные группы Секретные группы включены Секретные группы позволяют нескольким пользователям общаться с использованием сквозного шифрования. Чтобы создать секретную группу, включите этот функционал при помощи кнопки выше, вернитесь в список диалогов, нажмите на иконку карандаша в правом нижнем углу и выберите \"%1$s\". + Защита файлов + Защита файлов позволяет защититься от извлечения файлов приложения при досмотре телефона. Включение опции может привести к некорректной работе приложения. Вы можете включить эту опцию а потом, если столкнётесь с проблемами, отключить её. Включение опции приведёт к очистке кэша сообщений. Опция будет применена после перезапуска приложения. \ No newline at end of file diff --git a/TMessagesProj/src/main/assets/strings/strings_uk.xml b/TMessagesProj/src/main/assets/strings/strings_uk.xml index 2e5912a36..493b7a076 100644 --- a/TMessagesProj/src/main/assets/strings/strings_uk.xml +++ b/TMessagesProj/src/main/assets/strings/strings_uk.xml @@ -291,4 +291,6 @@ Увімкнути секретні групи Секретні групи включені Секретні групи дозволяють декільком користувачам спілкуватися з використанням наскрізного шифрування. Щоб створити секретну групу, увімкніть цей функціонал за допомогою кнопки вище, поверніться до списку діалогів, натисніть на іконку олівця в правому нижньому кутку та виберіть \"%1$s\". + Захист файлів + Захист файлів дозволяє захиститись від виймання файлів програми під час перегляду телефону. Увімкнення опції може призвести до некоректної роботи програми. Ви можете включити цю опцію, а потім, якщо зіткнетеся з проблемами, відключити її. Увімкнення опції призведе до очищення кешу повідомлень. Опція буде застосована після перезапуску програми. дозволяє захиститись від виймання файлів програми під час перегляду телефону. Увімкнення опції може призвести до некоректної роботи програми. Ви можете включити цю опцію, а потім, якщо зіткнетеся з проблемами, відключити її. Увімкнення опції призведе до очищення кешу повідомлень. Опція буде застосована після перезапуску програми. diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java index 7fa936548..51cbe15a1 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java @@ -321,7 +321,11 @@ public class MessagesStorage extends BaseController { createTable = true; } try { - database = new SQLiteDatabaseWrapper(cacheFile.getPath()); + if (fileProtectionEnabled()) { + database = new SQLiteDatabaseWrapper(cacheFile.getPath()); + } else { + database = new SQLiteDatabase(cacheFile.getPath()); + } database.executeFast("PRAGMA secure_delete = ON").stepThis().dispose(); database.executeFast("PRAGMA temp_store = MEMORY").stepThis().dispose(); database.executeFast("PRAGMA journal_mode = WAL").stepThis().dispose(); @@ -435,7 +439,11 @@ public class MessagesStorage extends BaseController { FileLog.e("Database restored = " + restored); if (restored) { try { - database = new SQLiteDatabaseWrapper(cacheFile.getPath()); + if (fileProtectionEnabled()) { + database = new SQLiteDatabaseWrapper(cacheFile.getPath()); + } else { + database = new SQLiteDatabase(cacheFile.getPath()); + } database.executeFast("PRAGMA secure_delete = ON").stepThis().dispose(); database.executeFast("PRAGMA temp_store = MEMORY").stepThis().dispose(); database.executeFast("PRAGMA journal_mode = WAL").stepThis().dispose(); @@ -10703,12 +10711,35 @@ public class MessagesStorage extends BaseController { private SQLitePreparedStatement executeFastForBothDbIfNeeded(String sql) throws SQLiteException { if (database instanceof SQLiteDatabaseWrapper) { - return ((SQLiteDatabaseWrapper)database).executeFastForBothDb("REPLACE INTO messages_v2 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, ?, ?, ?)"); + return ((SQLiteDatabaseWrapper)database).executeFastForBothDb(sql); } else { - return database.executeFast("REPLACE INTO messages_v2 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, ?, ?, ?)"); + return database.executeFast(sql); } } + public boolean fileProtectionEnabled() { + return SharedConfig.fileProtectionForAllAccountsEnabled; + } + + public void finishFileProtectionEnabling() { + storageQueue.postRunnable(() -> { + try { + database.executeFast("DELETE FROM messages_v2").stepThis().dispose(); + database.executeFast("DELETE FROM chats").stepThis().dispose(); + database.executeFast("DELETE FROM contacts").stepThis().dispose(); + database.executeFast("DELETE FROM dialogs").stepThis().dispose(); + database.executeFast("DELETE FROM messages_holes").stepThis().dispose(); + } catch (Exception e) { + checkSQLException(e); + } finally { + if (database != null) { + database.commitTransaction(); + } + AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.onFileProtectionEnabled)); + } + }); + } + private void putUsersAndChatsInternal(List users, List chats, boolean withTransaction) { try { if (withTransaction) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java index e501a1c49..fbda42b0b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java @@ -284,6 +284,7 @@ public class NotificationCenter { public static final int unknownPartisanActionLinkOpened = totalEvents++; public static final int updateDownloadingStarted = totalEvents++; public static final int encryptedGroupUpdated = totalEvents++; + public static final int onFileProtectionEnabled = totalEvents++; //global diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java index d148e453c..d8c931600 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java @@ -442,6 +442,7 @@ public class SharedConfig { public static boolean confirmDangerousActions; public static boolean showEncryptedChatsFromEncryptedGroups = false; public static boolean encryptedGroupsEnabled = false; + public static boolean fileProtectionForAllAccountsEnabled = false; private static final int[] LOW_SOC = { -1775228513, // EXYNOS 850 @@ -952,6 +953,7 @@ public class SharedConfig { confirmDangerousActions = preferences.getBoolean("confirmDangerousActions", false); showEncryptedChatsFromEncryptedGroups = preferences.getBoolean("showEncryptedChatsFromEncryptedGroups", false); encryptedGroupsEnabled = preferences.getBoolean("encryptedGroupsEnabled", encryptedGroupsEnabled); + fileProtectionForAllAccountsEnabled = preferences.getBoolean("fileProtectionForAllAccountsEnabled", fileProtectionForAllAccountsEnabled); dayNightWallpaperSwitchHint = preferences.getInt("dayNightWallpaperSwitchHint", 0); bigCameraForRound = preferences.getBoolean("bigCameraForRound", false); useNewBlur = preferences.getBoolean("useNewBlur", true); @@ -1064,6 +1066,14 @@ public class SharedConfig { editor.commit(); } + public static void toggleFileProtectionForAllAccountsEnabled() { + fileProtectionForAllAccountsEnabled = !fileProtectionForAllAccountsEnabled; + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + SharedPreferences.Editor editor = preferences.edit(); + editor.putBoolean("fileProtectionForAllAccountsEnabled", fileProtectionForAllAccountsEnabled); + editor.commit(); + } + public static List getBadPasscodeAttemptList() { return badPasscodeAttemptList; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java index 594e81edf..c2308e51b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java @@ -717,7 +717,7 @@ public class UserConfig extends BaseController { } public long[] getDialogLoadOffsets(int folderId) { - if (true) { + if (getMessagesStorage().fileProtectionEnabled()) { return new long[]{-1, -1, -1, -1, -1, -1}; } SharedPreferences preferences = getPreferences(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PartisanSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PartisanSettingsActivity.java index 0ebad02df..528ce8b7c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PartisanSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PartisanSettingsActivity.java @@ -19,9 +19,11 @@ import androidx.annotation.NonNull; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import org.telegram.messenger.AccountInstance; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; @@ -55,10 +57,11 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.function.Consumer; import java.util.function.Function; -public class PartisanSettingsActivity extends BaseFragment { +public class PartisanSettingsActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { private ListAdapter listAdapter; private RecyclerListView listView; @@ -97,6 +100,8 @@ public class PartisanSettingsActivity extends BaseFragment { private int verifiedDetailRow; private int confirmDangerousActionRow; private int confirmDangerousActionDetailRow; + private int fileProtectionRow; + private int fileProtectionDetailRow; private int transferDataToOtherPtgRow; private int transferDataToOtherPtgDetailRow; @@ -104,12 +109,15 @@ public class PartisanSettingsActivity extends BaseFragment { private int enableSecretGroupsRow; private int enableSecretGroupsDetailRow; + private AlertDialog enablingFileProtectionDialog; + Set accountsWithEnabledFileProtection = new HashSet<>(); + private class DangerousSettingSwitcher { public Context context; public View view; public boolean value; public Consumer setValue; - public Consumer dangerousAction; + public Consumer dangerousAction; public Function isChanged; public String dangerousActionTitle; public String positiveButtonText; @@ -135,7 +143,7 @@ public class PartisanSettingsActivity extends BaseFragment { SharedConfig.saveConfig(); ((TextCheckCell) view).setChecked(!value); if (runDangerousAction) { - foreachActivatedConfig(dangerousAction); + foreachActivatedAccountInstance(dangerousAction); } } @@ -158,11 +166,24 @@ public class PartisanSettingsActivity extends BaseFragment { @Override public boolean onFragmentCreate() { + foreachActivatedAccountInstance(accountInstance -> { + accountInstance.getNotificationCenter().addObserver(this, NotificationCenter.onDatabaseReset); + accountInstance.getNotificationCenter().addObserver(this, NotificationCenter.onFileProtectionEnabled); + }); super.onFragmentCreate(); updateRows(); return true; } + @Override + public void onFragmentDestroy() { + super.onFragmentDestroy(); + foreachActivatedAccountInstance(accountInstance -> { + accountInstance.getNotificationCenter().removeObserver(this, NotificationCenter.onDatabaseReset); + accountInstance.getNotificationCenter().removeObserver(this, NotificationCenter.onFileProtectionEnabled); + }); + } + @Override public View createView(Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); @@ -217,11 +238,11 @@ public class PartisanSettingsActivity extends BaseFragment { switcher.positiveButtonText = LocaleController.getString("Reset", R.string.Reset); switcher.negativeButtonText = LocaleController.getString("NotReset", R.string.NotReset); switcher.neutralButtonText = LocaleController.getString("Cancel", R.string.Cancel); - switcher.dangerousAction = config -> { - for (UserConfig.ChatInfoOverride override : config.chatInfoOverrides.values()) { + switcher.dangerousAction = accountInstance -> { + for (UserConfig.ChatInfoOverride override : accountInstance.getUserConfig().chatInfoOverrides.values()) { override.avatarEnabled = true; } - config.saveConfig(false); + accountInstance.getUserConfig().saveConfig(false); }; switcher.switchSetting(); } else if (position == renameChatRow) { @@ -235,11 +256,11 @@ public class PartisanSettingsActivity extends BaseFragment { switcher.positiveButtonText = LocaleController.getString("Reset", R.string.Reset); switcher.negativeButtonText = LocaleController.getString("NotReset", R.string.NotReset); switcher.neutralButtonText = LocaleController.getString("Cancel", R.string.Cancel); - switcher.dangerousAction = config -> { - for (UserConfig.ChatInfoOverride override : config.chatInfoOverrides.values()) { + switcher.dangerousAction = accountInstance -> { + for (UserConfig.ChatInfoOverride override : accountInstance.getUserConfig().chatInfoOverrides.values()) { override.title = null; } - config.saveConfig(false); + accountInstance.getUserConfig().saveConfig(false); }; switcher.switchSetting(); } else if (position == deleteMyMessagesRow) { @@ -271,7 +292,8 @@ public class PartisanSettingsActivity extends BaseFragment { switcher.positiveButtonText = LocaleController.getString("ClearButton", R.string.ClearButton); switcher.negativeButtonText = LocaleController.getString("NotClear", R.string.NotClear); switcher.neutralButtonText = LocaleController.getString("Cancel", R.string.Cancel); - switcher.dangerousAction = (config) -> { + switcher.dangerousAction = accountInstance -> { + UserConfig config = accountInstance.getUserConfig(); List savedChannels = Arrays.asList(config.defaultChannels.split(",")); config.savedChannels = new HashSet<>(savedChannels); config.pinnedSavedChannels = new ArrayList<>(savedChannels); @@ -304,6 +326,22 @@ public class PartisanSettingsActivity extends BaseFragment { } else if (position == confirmDangerousActionRow) { SharedConfig.toggleIsConfirmDangerousActions(); ((TextCheckCell) view).setChecked(SharedConfig.confirmDangerousActions); + } else if (position == fileProtectionRow) { + + AlertsCreator.showConfirmationDialog(this, getContext(), LocaleController.getString(R.string.Continue), () -> { + if (!SharedConfig.fileProtectionForAllAccountsEnabled) { + accountsWithEnabledFileProtection.clear(); + foreachActivatedAccountInstance(accountInstance -> { + accountInstance.getMessagesStorage().clearLocalDatabase(); + }); + enablingFileProtectionDialog = new AlertDialog(getParentActivity(), AlertDialog.ALERT_TYPE_SPINNER); + showDialog(enablingFileProtectionDialog); + } else { + SharedConfig.toggleFileProtectionForAllAccountsEnabled(); + ((TextCheckCell) view).setChecked(SharedConfig.fileProtectionForAllAccountsEnabled); + System.exit(0); + } + }); } else if (position == verifiedRow) { if (LocaleController.isRTL && x > AndroidUtilities.dp(76) || !LocaleController.isRTL && x < view.getMeasuredWidth() - AndroidUtilities.dp(76)) { List storages = VerificationRepository.getInstance().getStorages(); @@ -348,11 +386,11 @@ public class PartisanSettingsActivity extends BaseFragment { return fragmentView; } - private static void foreachActivatedConfig(Consumer action) { + private static void foreachActivatedAccountInstance(Consumer action) { for (int a = 0; a < UserConfig.MAX_ACCOUNT_COUNT; a++) { UserConfig config = UserConfig.getInstance(a); if (config.isClientActivated()) { - action.accept(config); + action.accept(AccountInstance.getInstance(a)); } } } @@ -365,6 +403,33 @@ public class PartisanSettingsActivity extends BaseFragment { } } + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.onDatabaseReset) { + if (enablingFileProtectionDialog != null) { + MessagesStorage.getInstance(account).finishFileProtectionEnabling(); + } + } else if (id == NotificationCenter.onFileProtectionEnabled) { + if (enablingFileProtectionDialog != null) { + accountsWithEnabledFileProtection.add(account); + boolean fileProtectionEnabledForAllAccounts = true; + for (int a = 0; a < UserConfig.MAX_ACCOUNT_COUNT; a++) { + UserConfig config = UserConfig.getInstance(a); + if (config.isClientActivated() && !accountsWithEnabledFileProtection.contains(a)) { + fileProtectionEnabledForAllAccounts = false; + break; + } + } + if (fileProtectionEnabledForAllAccounts) { + if (!SharedConfig.fileProtectionForAllAccountsEnabled) { + SharedConfig.toggleFileProtectionForAllAccountsEnabled(); + } + System.exit(0); + } + } + } + } + private void updateRows() { rowCount = 0; @@ -405,6 +470,8 @@ public class PartisanSettingsActivity extends BaseFragment { verifiedDetailRow = rowCount++; confirmDangerousActionRow = rowCount++; confirmDangerousActionDetailRow = rowCount++; + fileProtectionRow = rowCount++; + fileProtectionDetailRow = rowCount++; if (AppMigrator.isNewerPtgInstalled(ApplicationLoader.applicationContext, false) || AppMigratorPreferences.isMigrationToMaskedPtg()) { transferDataToOtherPtgRow = rowCount++; @@ -452,6 +519,7 @@ public class PartisanSettingsActivity extends BaseFragment { && position != onScreenLockActionDetailRow && position != isClearAllDraftsOnScreenLockDetailRow && position != showCallButtonDetailRow && position != isDeleteMessagesForAllByDefaultDetailRow && position != marketIconsDetailRow && position!= confirmDangerousActionDetailRow + && position != fileProtectionDetailRow && position != transferDataToOtherPtgDetailRow && position != experimentalHeaderRow && (position != enableSecretGroupsRow || !SharedConfig.encryptedGroupsEnabled) && position != enableSecretGroupsDetailRow; @@ -540,6 +608,9 @@ public class PartisanSettingsActivity extends BaseFragment { } else if (position == confirmDangerousActionRow) { textCell.setTextAndCheck(LocaleController.getString("ConfirmDangerousAction", R.string.ConfirmDangerousAction), SharedConfig.confirmDangerousActions, false); + } else if (position == fileProtectionRow) { + textCell.setTextAndCheck(LocaleController.getString(R.string.FileProtection), + SharedConfig.fileProtectionForAllAccountsEnabled, false); } break; } @@ -591,7 +662,10 @@ public class PartisanSettingsActivity extends BaseFragment { cell.setText(LocaleController.getString(R.string.AdditionalVerifiedSettingInfo)); cell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); } else if (position == confirmDangerousActionDetailRow) { - cell.setText(LocaleController.getString( R.string.ConfirmDangerousActionInfo)); + cell.setText(LocaleController.getString(R.string.ConfirmDangerousActionInfo)); + cell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); + } else if (position == fileProtectionDetailRow) { + cell.setText(LocaleController.getString(R.string.FileProtectionInfo)); cell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); } else if (position == transferDataToOtherPtgDetailRow) { cell.setText(LocaleController.getString(R.string.TransferDataToOtherPtgInfo)); @@ -667,7 +741,7 @@ public class PartisanSettingsActivity extends BaseFragment { || position == savedChannelsRow || position == reactionsRow || position == foreignAgentsRow || position == isClearAllDraftsOnScreenLockRow || position == showCallButtonRow || position == isDeleteMessagesForAllByDefaultRow || position == marketIconsRow - || position == confirmDangerousActionRow) { + || position == confirmDangerousActionRow || position == fileProtectionRow) { return 0; } else if (position == versionDetailRow || position == idDetailRow || position == disableAvatarDetailRow || position == renameChatDetailRow || position == deleteMyMessagesDetailRow @@ -676,8 +750,8 @@ public class PartisanSettingsActivity extends BaseFragment { || position == onScreenLockActionDetailRow || position == isClearAllDraftsOnScreenLockDetailRow || position == showCallButtonDetailRow || position == isDeleteMessagesForAllByDefaultDetailRow || position == marketIconsDetailRow || position == verifiedDetailRow - || position == confirmDangerousActionDetailRow || position == transferDataToOtherPtgDetailRow - || position == enableSecretGroupsDetailRow) { + || position == confirmDangerousActionDetailRow || position == fileProtectionDetailRow + || position == transferDataToOtherPtgDetailRow || position == enableSecretGroupsDetailRow) { return 1; } else if (position == onScreenLockActionRow || position == transferDataToOtherPtgRow || position == enableSecretGroupsRow) { diff --git a/TMessagesProj/src/main/res/values/strings.xml b/TMessagesProj/src/main/res/values/strings.xml index d9371139c..0a75faa8b 100644 --- a/TMessagesProj/src/main/res/values/strings.xml +++ b/TMessagesProj/src/main/res/values/strings.xml @@ -8805,4 +8805,6 @@ Enable Secret Groups Secret Groups Enabled Secret groups allow multiple users to communicate using end-to-end encryption. To create a secret group, enable this feature using the button above, return to the list of conversations, click the pencil icon in the lower right corner and select \"%1$s\". + File Protection + File protection allows you to protect against extraction of application files during phone inspection. Enabling this option may result in incorrect operation of the application. You can enable this option and then disable it if you encounter problems. Enabling this option will clear the message cache. The option will be applied after restarting the application. \ No newline at end of file