diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/MainActivity.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/MainActivity.kt index 4c4ef9edd..d6d6a5141 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/MainActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/MainActivity.kt @@ -24,10 +24,7 @@ import com.simplemobiletools.smsmessenger.adapters.ConversationsAdapter import com.simplemobiletools.smsmessenger.dialogs.ExportMessagesDialog import com.simplemobiletools.smsmessenger.dialogs.ImportMessagesDialog import com.simplemobiletools.smsmessenger.extensions.* -import com.simplemobiletools.smsmessenger.helpers.EXPORT_MIME_TYPE -import com.simplemobiletools.smsmessenger.helpers.MessagesExporter -import com.simplemobiletools.smsmessenger.helpers.THREAD_ID -import com.simplemobiletools.smsmessenger.helpers.THREAD_TITLE +import com.simplemobiletools.smsmessenger.helpers.* import com.simplemobiletools.smsmessenger.models.Conversation import com.simplemobiletools.smsmessenger.models.Events import kotlinx.android.synthetic.main.activity_main.* @@ -37,7 +34,7 @@ import org.greenrobot.eventbus.ThreadMode import java.io.FileOutputStream import java.io.OutputStream import java.util.* -import kotlin.collections.ArrayList + class MainActivity : SimpleActivity() { private val MAKE_DEFAULT_APP_REQUEST = 1 @@ -367,7 +364,7 @@ class MainActivity : SimpleActivity() { if (isQPlus()) { ExportMessagesDialog(this, config.lastExportPath, true) { file -> Intent(Intent.ACTION_CREATE_DOCUMENT).apply { - type = EXPORT_MIME_TYPE + type = if (config.exportBackupPassword != "") EXPORT_SECURE_MIME_TYPE else EXPORT_MIME_TYPE putExtra(Intent.EXTRA_TITLE, file.name) addCategory(Intent.CATEGORY_OPENABLE) startActivityForResult(this, PICK_EXPORT_FILE_INTENT) @@ -388,12 +385,17 @@ class MainActivity : SimpleActivity() { private fun exportMessagesTo(outputStream: OutputStream?) { toast(R.string.exporting) + val exportNotification = ImportExportProgressNotification(this, ImportExportProgressNotification.ImportOrExport.EXPORT) ensureBackgroundThread { - smsExporter.exportMessages(outputStream) { + exportNotification.spawnProgressNotification() + smsExporter.exportMessages(outputStream, { state, total, current -> + exportNotification.updateNotification(state, total, current) + }) { val toastId = when (it) { MessagesExporter.ExportResult.EXPORT_OK -> R.string.exporting_successful else -> R.string.exporting_failed } + exportNotification.setFinish(it == MessagesExporter.ExportResult.EXPORT_OK) toast(toastId) } @@ -404,7 +406,7 @@ class MainActivity : SimpleActivity() { if (isQPlus()) { Intent(Intent.ACTION_GET_CONTENT).apply { addCategory(Intent.CATEGORY_OPENABLE) - type = EXPORT_MIME_TYPE + type = "*/*" startActivityForResult(this, PICK_IMPORT_SOURCE_INTENT) } } else { @@ -423,7 +425,8 @@ class MainActivity : SimpleActivity() { } private fun showImportEventsDialog(path: String) { - ImportMessagesDialog(this, path) + val importNotification = ImportExportProgressNotification(this, ImportExportProgressNotification.ImportOrExport.IMPORT) + ImportMessagesDialog(this, path, importNotification) } private fun tryImportMessagesFromFile(uri: Uri) { @@ -435,7 +438,6 @@ class MainActivity : SimpleActivity() { toast(R.string.unknown_error_occurred) return } - try { val inputStream = contentResolver.openInputStream(uri) val out = FileOutputStream(tempFile) diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/ExportMessagesDialog.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/ExportMessagesDialog.kt index 672e09f43..52bd3c609 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/ExportMessagesDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/ExportMessagesDialog.kt @@ -8,6 +8,7 @@ import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.activities.SimpleActivity import com.simplemobiletools.smsmessenger.extensions.config import com.simplemobiletools.smsmessenger.helpers.EXPORT_FILE_EXT +import com.simplemobiletools.smsmessenger.helpers.EXPORT_SECURE_FILE_EXT import kotlinx.android.synthetic.main.dialog_export_messages.view.* import java.io.File @@ -51,7 +52,9 @@ class ExportMessagesDialog( when { filename.isEmpty() -> activity.toast(R.string.empty_name) filename.isAValidFilename() -> { - val file = File(realPath, "$filename$EXPORT_FILE_EXT") + config.exportBackupPassword = view.export_messages_password.value //We need to get this early to set proper extension + val exportFileExtension = if (config.exportBackupPassword == "") EXPORT_FILE_EXT else EXPORT_SECURE_FILE_EXT + val file = File(realPath, "$filename$exportFileExtension") if (!hidePath && file.exists()) { activity.toast(R.string.name_taken) return@setOnClickListener diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/ImportMessagesDialog.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/ImportMessagesDialog.kt index 54df49be3..6775fd6b5 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/ImportMessagesDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/ImportMessagesDialog.kt @@ -4,10 +4,12 @@ import android.view.ViewGroup import androidx.appcompat.app.AlertDialog import com.simplemobiletools.commons.extensions.setupDialogStuff import com.simplemobiletools.commons.extensions.toast +import com.simplemobiletools.commons.extensions.value import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.activities.SimpleActivity import com.simplemobiletools.smsmessenger.extensions.config +import com.simplemobiletools.smsmessenger.helpers.ImportExportProgressNotification import com.simplemobiletools.smsmessenger.helpers.MessagesImporter import com.simplemobiletools.smsmessenger.helpers.MessagesImporter.ImportResult.IMPORT_OK import com.simplemobiletools.smsmessenger.helpers.MessagesImporter.ImportResult.IMPORT_PARTIAL @@ -16,6 +18,7 @@ import kotlinx.android.synthetic.main.dialog_import_messages.view.* class ImportMessagesDialog( private val activity: SimpleActivity, private val path: String, + private val importNotification: ImportExportProgressNotification, ) { private val config = activity.config @@ -43,11 +46,14 @@ class ImportMessagesDialog( } ignoreClicks = true + importNotification.spawnProgressNotification() activity.toast(R.string.importing) config.importSms = view.import_sms_checkbox.isChecked config.importMms = view.import_mms_checkbox.isChecked + config.importBackupPassword = view.import_messages_password.value ensureBackgroundThread { - MessagesImporter(activity).importMessages(path) { + MessagesImporter(activity).importMessages(path, + { state, total, current -> importNotification.updateNotification(state, total, current) }) { handleParseResult(it) dismiss() } @@ -65,5 +71,6 @@ class ImportMessagesDialog( else -> R.string.no_items_found } ) + importNotification.setFinish(result == IMPORT_OK) } } diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/Config.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/Config.kt index 79d4c3983..9b3494a48 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/Config.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/Config.kt @@ -64,6 +64,10 @@ class Config(context: Context) : BaseConfig(context) { get() = prefs.getString(LAST_EXPORT_PATH, "")!! set(lastExportPath) = prefs.edit().putString(LAST_EXPORT_PATH, lastExportPath).apply() + var exportBackupPassword: String + get() = prefs.getString(EXPORT_BACKUP_PASSWORD, "")!! + set(exportBackupPassword) = prefs.edit().putString(EXPORT_BACKUP_PASSWORD, exportBackupPassword).apply() + var exportSms: Boolean get() = prefs.getBoolean(EXPORT_SMS, true) set(exportSms) = prefs.edit().putBoolean(EXPORT_SMS, exportSms).apply() @@ -72,6 +76,10 @@ class Config(context: Context) : BaseConfig(context) { get() = prefs.getBoolean(EXPORT_MMS, true) set(exportMms) = prefs.edit().putBoolean(EXPORT_MMS, exportMms).apply() + var importBackupPassword: String + get() = prefs.getString(IMPORT_BACKUP_PASSWORD, "")!! + set(importBackupPassword) = prefs.edit().putString(IMPORT_BACKUP_PASSWORD, importBackupPassword).apply() + var importSms: Boolean get() = prefs.getBoolean(IMPORT_SMS, true) set(importSms) = prefs.edit().putBoolean(IMPORT_SMS, importSms).apply() diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/Constants.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/Constants.kt index 8359b33b1..c52f7cbee 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/Constants.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/Constants.kt @@ -20,14 +20,22 @@ const val SEND_LONG_MESSAGE_MMS = "send_long_message_mms" const val MMS_FILE_SIZE_LIMIT = "mms_file_size_limit" const val PINNED_CONVERSATIONS = "pinned_conversations" const val LAST_EXPORT_PATH = "last_export_path" +const val EXPORT_BACKUP_PASSWORD = "export_backup_password" const val EXPORT_SMS = "export_sms" const val EXPORT_MMS = "export_mms" const val EXPORT_MIME_TYPE = "application/json" +const val EXPORT_SECURE_MIME_TYPE = "application/sec" const val EXPORT_FILE_EXT = ".json" +const val EXPORT_SECURE_FILE_EXT = ".sec" +const val IMPORT_BACKUP_PASSWORD = "import_backup_password" const val IMPORT_SMS = "import_sms" const val IMPORT_MMS = "import_mms" const val WAS_DB_CLEARED = "was_db_cleared" +//Secure Backup Cipher Parameters +const val KEY_ITERATIONS = 65536 +const val KEY_LENGTH = 256 + private const val PATH = "com.simplemobiletools.smsmessenger.action." const val MARK_AS_READ = PATH + "mark_as_read" const val REPLY = PATH + "reply" @@ -45,6 +53,9 @@ const val LOCK_SCREEN_SENDER_MESSAGE = 1 const val LOCK_SCREEN_SENDER = 2 const val LOCK_SCREEN_NOTHING = 3 +//Notifications +const val EXPORT_IMPORT_NOTIFICATION_ID = 33 + const val FILE_SIZE_NONE = -1L const val FILE_SIZE_100_KB = 102_400L const val FILE_SIZE_200_KB = 204_800L diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/ImportExportProgressNotification.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/ImportExportProgressNotification.kt new file mode 100644 index 000000000..c384f3b9f --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/ImportExportProgressNotification.kt @@ -0,0 +1,110 @@ +package com.simplemobiletools.smsmessenger.helpers + +import android.app.* +import android.content.Context.NOTIFICATION_SERVICE +import androidx.core.app.NotificationCompat +import com.simplemobiletools.commons.helpers.isOreoPlus +import com.simplemobiletools.smsmessenger.R +import com.simplemobiletools.smsmessenger.activities.SimpleActivity +import java.util.* + +class ImportExportProgressNotification( + private val activity: SimpleActivity, + private val type: ImportOrExport +) { + enum class ImportOrExport { + IMPORT, EXPORT + } + + private var isInit = false + private lateinit var notification: NotificationCompat.Builder + private lateinit var channelId: String + private val progressMax = 100 + private val notificationManager = activity.getSystemService(NOTIFICATION_SERVICE) as NotificationManager + private var waitTime = 0L + private var startTime = 0L + + init { + startTime = System.currentTimeMillis() + if (isOreoPlus()) { + channelId = activity.getString(R.string.channel_import_export) + val name = activity.getString(R.string.channel_import_export) + val importance = NotificationManager.IMPORTANCE_LOW + val mChannel = NotificationChannel(channelId, name, importance) + + notificationManager.createNotificationChannel(mChannel) + } + } + + fun setFinish(hasSucceed: Boolean) { + if (isInit) { + isInit = false + val contentTitle = + if (type == ImportOrExport.EXPORT) activity.getString(R.string.exporting_successful) else activity.getString(R.string.importing_successful) + notification.setContentTitle(contentTitle) + + if (hasSucceed) { + notification.setContentText("Success") + .setProgress(0, 0, false) + .setOngoing(false) + .setAutoCancel(true) + } else { + notification.setContentText("Something went wrong") + .setProgress(0, 0, false) + .setOngoing(false) + .setAutoCancel(true) + } + notificationManager.notify(EXPORT_IMPORT_NOTIFICATION_ID, notification.build()) + } + } + + fun spawnProgressNotification() { + val contentTitle = + if (type == ImportOrExport.IMPORT) activity.getString(R.string.importing_messages) else activity.getString(R.string.exporting_messages) + //Creating a notification and setting its various attributes + notification = + NotificationCompat.Builder(activity, channelId) + .setSmallIcon(R.drawable.ic_messenger) + .setContentTitle(contentTitle) + .setContentText("0%") + .setPriority(NotificationCompat.PRIORITY_DEFAULT) + .setOngoing(true) + .setProgress(progressMax, 0, false) + + notificationManager.notify(EXPORT_IMPORT_NOTIFICATION_ID, notification.build()) + isInit = true + } + + fun updateNotification(state: Any, total: Int, current: Int) { + if (isInit) { + if (waitTime > 500) { + if (total > 1 && current <= total && current > 0) { + val progress = current.toDouble() / total * 100.00 + notification.setContentText(progress.toInt().toString() + "%") + .setProgress(progressMax, progress.toInt(), false) + } + + if (type == ImportOrExport.EXPORT) { + when (state) { + MessagesExporter.ExportState.EXPORT -> notification.setContentTitle(activity.getString(R.string.exporting_messages)) + MessagesExporter.ExportState.ENCRYPT -> notification.setContentTitle(activity.getString(R.string.encrypting_backup)) + } + } else { + when (state) { + MessagesImporter.ImportState.DECRYPTING -> { + notification.setContentTitle(activity.getString(R.string.decrypting_backup)) + .setProgress(100, 50, true) + } + MessagesImporter.ImportState.RESTORING -> notification.setContentTitle(activity.getString(R.string.importing_messages)) + } + } + + notificationManager.notify(EXPORT_IMPORT_NOTIFICATION_ID, notification.build()) + startTime = System.currentTimeMillis() + waitTime = 0L + } else { + waitTime = Date().time - startTime + } + } + } +} diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/MessagesExporter.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/MessagesExporter.kt index 49c2d4b61..d738393a7 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/MessagesExporter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/MessagesExporter.kt @@ -6,63 +6,127 @@ import com.google.gson.stream.JsonWriter import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.smsmessenger.extensions.config import com.simplemobiletools.smsmessenger.extensions.getConversationIds -import java.io.OutputStream +import java.io.* +import java.security.SecureRandom +import java.security.spec.KeySpec +import javax.crypto.Cipher +import javax.crypto.CipherOutputStream +import javax.crypto.SecretKey +import javax.crypto.SecretKeyFactory +import javax.crypto.spec.PBEKeySpec class MessagesExporter(private val context: Context) { enum class ExportResult { EXPORT_FAIL, EXPORT_OK } + enum class ExportState { + EXPORT, ENCRYPT + } + private val config = context.config private val messageReader = MessagesReader(context) private val gson = Gson() - fun exportMessages(outputStream: OutputStream?, onProgress: (total: Int, current: Int) -> Unit = { _, _ -> }, callback: (result: ExportResult) -> Unit) { + private fun jsonWriter( + workOutputStream: OutputStream, + onProgress: (state: ExportState, total: Int, current: Int) -> Unit = { _, _, _ -> }, + callback: (result: ExportResult) -> Unit + ) { + val writer = JsonWriter(workOutputStream.bufferedWriter()) + writer.use { + try { + var written = 0 + writer.beginArray() + val conversationIds = context.getConversationIds() + val totalMessages = messageReader.getMessagesCount(config.exportSms, config.exportMms) + for (threadId in conversationIds) { + writer.beginObject() + + if (config.exportSms && messageReader.getSmsCount() > 0) { + writer.name("sms") + writer.beginArray() + messageReader.forEachSms(threadId) { + writer.jsonValue(gson.toJson(it)) + written++ + onProgress.invoke(ExportState.EXPORT, totalMessages, written) + } + writer.endArray() + } + + if (config.exportMms && messageReader.getMmsCount() > 0) { + writer.name("mms") + writer.beginArray() + messageReader.forEachMms(threadId) { + writer.jsonValue(gson.toJson(it)) + written++ + onProgress.invoke(ExportState.EXPORT, totalMessages, written) + } + + writer.endArray() + } + + writer.endObject() + } + writer.endArray() + } catch (e: Exception) { + callback.invoke(ExportResult.EXPORT_FAIL) + } + } + } + + fun exportMessages( + outputStream: OutputStream?, + onProgress: (state: ExportState, total: Int, current: Int) -> Unit = { _, _, _ -> }, + callback: (result: ExportResult) -> Unit + ) { ensureBackgroundThread { if (outputStream == null) { callback.invoke(ExportResult.EXPORT_FAIL) return@ensureBackgroundThread } - val writer = JsonWriter(outputStream.bufferedWriter()) - writer.use { - try { - var written = 0 - writer.beginArray() - val conversationIds = context.getConversationIds() - val totalMessages = messageReader.getMessagesCount() - for (threadId in conversationIds) { - writer.beginObject() - if (config.exportSms && messageReader.getSmsCount() > 0) { - writer.name("sms") - writer.beginArray() - messageReader.forEachSms(threadId) { - writer.jsonValue(gson.toJson(it)) - written++ - onProgress.invoke(totalMessages, written) - } - writer.endArray() - } - if (config.exportMms && messageReader.getMmsCount() > 0) { - writer.name("mms") - writer.beginArray() - messageReader.forEachMms(threadId) { - writer.jsonValue(gson.toJson(it)) - written++ - onProgress.invoke(totalMessages, written) - } + if (config.exportBackupPassword == "") { + jsonWriter(outputStream, onProgress, callback) + } else { + val outputFile = File(context.cacheDir, "output.json") + jsonWriter(outputFile.outputStream(), onProgress, callback) + val salt = ByteArray(16) + val random = SecureRandom() + random.nextBytes(salt) - writer.endArray() - } + //Taken from FairEmail project (setting export mechanism) + // https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#Cipher + val keyFactory: SecretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1") + val keySpec: KeySpec = PBEKeySpec(config.exportBackupPassword.toCharArray(), salt, KEY_ITERATIONS, KEY_LENGTH) + val secret: SecretKey = keyFactory.generateSecret(keySpec) + val cipher: Cipher = Cipher.getInstance("AES/CBC/PKCS5Padding") + cipher.init(Cipher.ENCRYPT_MODE, secret) - writer.endObject() - } - writer.endArray() - callback.invoke(ExportResult.EXPORT_OK) - } catch (e: Exception) { - callback.invoke(ExportResult.EXPORT_FAIL) - } + outputStream.write(salt) + outputStream.write(cipher.iv) + + val cout = CipherOutputStream(outputStream, cipher) + val cin: InputStream = outputFile.inputStream() + + var left = cin.available() + val total = left + do { + onProgress.invoke(ExportState.ENCRYPT, total, total - left) + val byteArray = ByteArray(8192) + val readBytes = cin.read(byteArray, 0, 8192) + left -= readBytes + cout.write(byteArray, 0, readBytes) + } while (left > 0) + + cout.flush() + + cin.close() + outputFile.delete() + + outputStream.write(cipher.doFinal()) } + callback.invoke(ExportResult.EXPORT_OK) } } } diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/MessagesImporter.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/MessagesImporter.kt index 4ff1f5b78..d7dfa7dfa 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/MessagesImporter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/MessagesImporter.kt @@ -1,7 +1,6 @@ package com.simplemobiletools.smsmessenger.helpers import android.content.Context -import android.provider.Telephony.* import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.simplemobiletools.commons.extensions.showErrorToast @@ -9,58 +8,117 @@ import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.smsmessenger.extensions.* import com.simplemobiletools.smsmessenger.helpers.MessagesImporter.ImportResult.* import com.simplemobiletools.smsmessenger.models.ExportedMessage -import java.io.File +import java.io.* +import java.security.spec.KeySpec +import javax.crypto.Cipher +import javax.crypto.CipherInputStream +import javax.crypto.SecretKey +import javax.crypto.SecretKeyFactory +import javax.crypto.spec.IvParameterSpec +import javax.crypto.spec.PBEKeySpec + class MessagesImporter(private val context: Context) { enum class ImportResult { IMPORT_FAIL, IMPORT_OK, IMPORT_PARTIAL, IMPORT_NOTHING_NEW } + enum class ImportState { + DECRYPTING, RESTORING + } + private val gson = Gson() private val messageWriter = MessagesWriter(context) private val config = context.config private var messagesImported = 0 private var messagesFailed = 0 - fun importMessages(path: String, onProgress: (total: Int, current: Int) -> Unit = { _, _ -> }, callback: (result: ImportResult) -> Unit) { + private fun readBuffer(inputStream: InputStream, buffer: ByteArray) { + var left = buffer.size + + while (left > 0) { + val count = inputStream.read(buffer, buffer.size - left, left) + if (count < 0) + throw Exception("Bad file encryption") + left -= count + } + } + + fun importMessages( + path: String, + onProgress: (state: ImportState, total: Int, current: Int) -> Unit = { _, _, _ -> }, + callback: (result: ImportResult) -> Unit + ) { ensureBackgroundThread { try { - val inputStream = if (path.contains("/")) { File(path).inputStream() } else { context.assets.open(path) } - inputStream.bufferedReader().use { reader -> - val json = reader.readText() - val type = object : TypeToken>() {}.type - val messages = gson.fromJson>(json, type) - val totalMessages = messages.flatMap { it.sms ?: emptyList() }.size + messages.flatMap { it.mms ?: emptyList() }.size - if (totalMessages <= 0) { - callback.invoke(IMPORT_NOTHING_NEW) - return@ensureBackgroundThread + val password = config.importBackupPassword + + val data: InputStream + var rawInputStream: InputStream? = null + + if (password != "") { + try { + onProgress.invoke(ImportState.DECRYPTING, 0, 0) + rawInputStream = BufferedInputStream(inputStream) + val salt = ByteArray(16) + val prefix = ByteArray(16) + readBuffer(rawInputStream, salt) + readBuffer(rawInputStream, prefix) + val keyFactory: SecretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1") + val keySpec: KeySpec = PBEKeySpec(password.toCharArray(), salt, KEY_ITERATIONS, KEY_LENGTH) + val secret: SecretKey = keyFactory.generateSecret(keySpec) + val cipher: Cipher = Cipher.getInstance("AES/CBC/PKCS5Padding") + val iv = IvParameterSpec(prefix) + cipher.init(Cipher.DECRYPT_MODE, secret, iv) + data = CipherInputStream(rawInputStream, cipher) + + } catch (e: Exception) { + throw Exception("Error while decrypting backup, please check your password.") } + } else { + data = inputStream + } + + val type = object : TypeToken>() {}.type + + val messages: List + data.bufferedReader().use { + messages = gson.fromJson(it, type) + } - onProgress.invoke(totalMessages, messagesImported) - for (message in messages) { - if (config.importSms) { - message.sms?.forEach { backup -> - messageWriter.writeSmsMessage(backup) - messagesImported++ - onProgress.invoke(totalMessages, messagesImported) - } + val totalMessages = messages.flatMap { it.sms ?: emptyList() }.size + messages.flatMap { it.mms ?: emptyList() }.size + if (totalMessages <= 0) { + callback.invoke(IMPORT_NOTHING_NEW) + return@ensureBackgroundThread + } + + onProgress.invoke(ImportState.RESTORING, totalMessages, messagesImported) + for (message in messages) { + if (config.importSms) { + message.sms?.forEach { backup -> + messageWriter.writeSmsMessage(backup) + messagesImported++ + onProgress.invoke(ImportState.RESTORING, totalMessages, messagesImported) } - if (config.importMms) { - message.mms?.forEach { backup -> - messageWriter.writeMmsMessage(backup) - messagesImported++ - onProgress.invoke(totalMessages, messagesImported) - } + } + if (config.importMms) { + message.mms?.forEach { backup -> + messageWriter.writeMmsMessage(backup) + messagesImported++ + onProgress.invoke(ImportState.RESTORING, totalMessages, messagesImported) } - refreshMessages() } + refreshMessages() + + rawInputStream?.close() } + } catch (e: Exception) { context.showErrorToast(e) messagesFailed++ diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/MessagesReader.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/MessagesReader.kt index 175ad735d..8e3ad86b9 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/MessagesReader.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/MessagesReader.kt @@ -212,8 +212,10 @@ class MessagesReader(private val context: Context) { return addresses } - fun getMessagesCount(): Int { - return getSmsCount() + getMmsCount() + fun getMessagesCount(sms: Boolean, mms: Boolean): Int { + val smsCount = if(sms) getSmsCount() else 0 + val mmsCount = if(mms) getMmsCount() else 0 + return smsCount + mmsCount } fun getMmsCount(): Int { diff --git a/app/src/main/res/layout/dialog_export_messages.xml b/app/src/main/res/layout/dialog_export_messages.xml index 25bf1ca37..b780bc0fe 100644 --- a/app/src/main/res/layout/dialog_export_messages.xml +++ b/app/src/main/res/layout/dialog_export_messages.xml @@ -49,6 +49,25 @@ android:textSize="@dimen/normal_text_size" tools:text="Messages" /> + + + + @@ -13,6 +14,25 @@ android:paddingTop="@dimen/activity_margin" android:paddingEnd="@dimen/activity_margin"> + + + + رسالة جديدة ضع إشارة مقروء وضع علامة كغير مقروءة + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… هل أنت متأكد أنك تريد حذف كافة رسائل هذه المحادثة؟ @@ -61,7 +67,9 @@ Send group messages as MMS Send long messages as MMS + Password (leave blank if not needed) الرسائل + Password تصدير الرسائل تصدير الرسائل القصيرة تصدير رسائل الوسائط diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index 4bfea0f5a..1d1e573cc 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -29,6 +29,12 @@ Missatge nou Marca com a llegit Marcar com no llegit + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… Confirmeu que voleu suprimir tots els missatges d\'aquesta conversa\? @@ -53,7 +59,9 @@ Envia missatges de grup com a MMS Envia missatges llargs com a MMS + Password (leave blank if not needed) Missatges + Password Exporta els missatges Exporta SMS Exporta MMS @@ -76,4 +84,4 @@ --> La mida dels MMS està limitada pels operadors, podeu provar d\'establir un límit més petit a la configuració de l\'aplicació. L\'altre extrem no ha rebut el meu MMS, hi puc fer alguna cosa\? - \ No newline at end of file + diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index d633b8d79..653e68a05 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -29,6 +29,12 @@ Nová zpráva Označit jako přečtené Označit jako nepřečtené + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… Opravdu chcete smazat všechny zprávy z této konverzace? @@ -53,8 +59,10 @@ Send group messages as MMS Send long messages as MMS + Password (leave blank if not needed) Export zpráv Messages + Password Export SMS Export MMS Import zpráv diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index db0bc2074..2e0840a3b 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -29,6 +29,12 @@ Ny Besked Marker som læst Marker som ulæst + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… Er du sikker på, at du vil slette alle beskeder i denne samtale\? @@ -53,7 +59,9 @@ Send gruppemeddelelser som MMS Send lange beskeder som MMS + Password (leave blank if not needed) Messages + Password Eksporter beskeder Export SMS Eksportér MMS @@ -77,4 +85,4 @@ Haven't found some strings? There's more at https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res --> - \ No newline at end of file + diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 537d8f2e5..45f138640 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -29,6 +29,12 @@ Neue Nachricht Als gelesen markieren Als ungelesen markieren + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… Möchtest du wirklich alle Nachrichten dieses Chats löschen\? @@ -53,7 +59,9 @@ Gruppennachrichten als MMS versenden Send long messages as MMS + Password (leave blank if not needed) Nachrichten + Password Nachrichten exportieren SMS exportieren MMS exportieren diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 025e891b2..be2a727b0 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -30,6 +30,12 @@ Νέο μήνυμα Σήμανση ως αναγνωσμένο Σήμανση ως μη αναγνωσμένο + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… Είστε βέβαιοι ότι θέλετε να διαγράψετε όλα τα μηνύματα αυτής της συνομιλίας; @@ -59,7 +65,9 @@ Send long messages as MMS + Password (leave blank if not needed) Μηνύματα + Password Εξαγωγή μηνυμάτων Εξαγωγή SMS Εξαγωγή MMS diff --git a/app/src/main/res/values-eo/strings.xml b/app/src/main/res/values-eo/strings.xml index 9028aa738..1aa8c9c3b 100644 --- a/app/src/main/res/values-eo/strings.xml +++ b/app/src/main/res/values-eo/strings.xml @@ -29,6 +29,12 @@ Nova mesaĝo Marki kiel legitan Marki kiel nelegitan + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… Are you sure you want to delete all messages of this conversation? @@ -53,7 +59,9 @@ Send group messages as MMS Send long messages as MMS + Password (leave blank if not needed) Mesaĝoj + Password Export messages Export SMS Export MMS diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 1cc21590b..667a029bc 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -30,6 +30,12 @@ Nuevo mensaje Marcar como leído Marcar como no leído + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… ¿Estás seguro que quieres eliminar todos los mensajes en esta conversación? @@ -59,7 +65,9 @@ Send long messages as MMS + Password (leave blank if not needed) Messages + Password Export messages Export SMS Export MMS diff --git a/app/src/main/res/values-et/strings.xml b/app/src/main/res/values-et/strings.xml index 0751da107..fbc49e71f 100644 --- a/app/src/main/res/values-et/strings.xml +++ b/app/src/main/res/values-et/strings.xml @@ -29,6 +29,12 @@ Uus sõnum Märgi loetuks Märgi mitteloetuks + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… Kas oled kindel, et soovid kustutada kõik selle vestluse sõnumid\? @@ -53,7 +59,9 @@ Saada rühmasõnumid MMS-sõnumitena Send long messages as MMS + Password (leave blank if not needed) Messages + Password Export messages Export SMS Ekspordi MMS-sõnumid diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 3332edf5a..8d7defd0e 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -29,6 +29,12 @@ Uusi viesti Merkitse luetuksi Merkitse lukemattomaksi + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… Haluatko varmasti poistaa kaikki tämän keskustelun viestit\? @@ -53,7 +59,9 @@ Send group messages as MMS Send long messages as MMS + Password (leave blank if not needed) Messages + Password Export messages Export SMS Export MMS diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 860dcb4d7..6426497bd 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -29,6 +29,12 @@ Nouveau message Marquer comme lu Marquer comme non lu + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… Voulez-vous vraiment supprimer tous les messages de cette conversation \? @@ -53,7 +59,9 @@ Envoyer des messages de groupe en MMS Send long messages as MMS + Password (leave blank if not needed) Messages + Password Exporter des messages Exporter le SMS Exporter le MMS diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index a2294ebbb..b2648392e 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -30,6 +30,12 @@ Nova mensaxe Marcar como lida Marcar como non lida + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… Ten a certeza de que desexa eliminar todas as mensaxes desta conversa? @@ -59,7 +65,9 @@ Send long messages as MMS + Password (leave blank if not needed) Messages + Password Export messages Export SMS Export MMS diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index aa7230d93..54d1452e2 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -29,6 +29,12 @@ Új üzenet Megjelölés olvasottként Megjelölés olvasatlanként + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… Biztos, hogy törli az összes üzenetet ebből a beszélgetésből\? @@ -53,7 +59,9 @@ Send group messages as MMS Send long messages as MMS + Password (leave blank if not needed) Üzenetek + Password Üzenetek exportálása SMS exportálása MMS exportálása diff --git a/app/src/main/res/values-id/strings.xml b/app/src/main/res/values-id/strings.xml index 23d0ce38d..31302c456 100644 --- a/app/src/main/res/values-id/strings.xml +++ b/app/src/main/res/values-id/strings.xml @@ -29,6 +29,12 @@ Pesan baru Tandai sebagai Dibaca Tandai sebagai Belum dibaca + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… Apakah Anda yakin ingin menghapus semua pesan dari percakapan ini? @@ -53,7 +59,9 @@ Send group messages as MMS Send long messages as MMS + Password (leave blank if not needed) Messages + Password Export messages Export SMS Export MMS @@ -83,4 +91,4 @@ Haven't found some strings? There's more at https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res --> - \ No newline at end of file + diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 3489baca8..2a082a209 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -29,6 +29,12 @@ Nuovo messaggio Letto Non letto + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… Vuoi davvero eliminare tutti i messaggi di questa conversazione\? @@ -53,7 +59,9 @@ Invia messaggi di gruppo come MMS Send long messages as MMS + Password (leave blank if not needed) Messaggi + Password Esporta messaggi Esporta SMS Esporta MMS diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 2fb0db9b9..3234354c2 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -30,6 +30,12 @@ 新しいメッセージ 既読にする 未読にする + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… 本当にこの会話の全てのメッセージを削除しますか? @@ -59,7 +65,9 @@ Send long messages as MMS + Password (leave blank if not needed) Messages + Password Export messages Export SMS Export MMS diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml index 1055f4514..e5e690d29 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-lt/strings.xml @@ -29,6 +29,12 @@ Nauja žinutė Mark as Read Mark as Unread + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… Ar tikrai norite ištrinti visas šio pokalbio žinutes? @@ -53,7 +59,9 @@ Send group messages as MMS Send long messages as MMS + Password (leave blank if not needed) Messages + Password Export messages Export SMS Export MMS diff --git a/app/src/main/res/values-ml/strings.xml b/app/src/main/res/values-ml/strings.xml index b20b924e8..a3e91d1a2 100644 --- a/app/src/main/res/values-ml/strings.xml +++ b/app/src/main/res/values-ml/strings.xml @@ -30,6 +30,12 @@ പുതിയ മെസ്സേജ് വായിച്ചതായി അടയാളപ്പെടുത്തുക വായിച്ചിട്ടില്ലെന്ന് അടയാളപ്പെടുത്തുക + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… ഈ സംഭാഷണത്തിന്റെ എല്ലാ സന്ദേശങ്ങൾ ഇല്ലാതാക്കാൻ നിങ്ങൾ ആഗ്രഹിക്കുന്നുണ്ടോ? @@ -59,7 +65,9 @@ Send long messages as MMS + Password (leave blank if not needed) Messages + Password Export messages Export SMS Export MMS diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index 8b4f58a80..03bfdf9cd 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -29,6 +29,12 @@ Ny melding Marker som lest Marker som ulest + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… Are you sure you want to delete all messages of this conversation? @@ -53,7 +59,9 @@ Send group messages as MMS Send long messages as MMS + Password (leave blank if not needed) Meldinger + Password Eksporter meldinger Eksporter SMS Eksporter MMS diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index e96bd0756..655963670 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -29,6 +29,12 @@ Nieuw bericht Als gelezen markeren Als ongelezen markeren + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… Alle berichten in dit gesprek verwijderen\? @@ -53,7 +59,9 @@ Groepsberichten sturen als MMS Lange berichten als MMS versturen + Password (leave blank if not needed) Berichten + Password Berichten exporteren SMS-berichten exporteren MMS-berichten exporteren @@ -96,4 +104,4 @@ Haven't found some strings? There's more at https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res --> - \ No newline at end of file + diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index d80f51ad3..c528b81f3 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -29,6 +29,12 @@ Nowa wiadomość Oznacz jako przeczytane Oznacz jako nieprzeczytane + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… Czy usunąć wszystkie wiadomości z tej rozmowy\? @@ -55,7 +61,9 @@ Wysyłaj wiadomości grupowe jako MMS-y Wysyłaj długie wiadomości jako MMS-y + Password (leave blank if not needed) Wiadomości + Password Eksportuj wiadomości Eksportuj SMS-y Eksportuj MMS-y diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 8a7746023..7a6fa74fe 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -29,6 +29,12 @@ Nova mensagem Marcar como lida Marcar como não lida + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… Tem a certeza de que pretende apagar todas as mensagens desta conversa\? @@ -53,7 +59,9 @@ Enviar mensagens de grupo como MMS Send long messages as MMS + Password (leave blank if not needed) Mensagens + Password Exportar mensagens Exportar SMS Exportar MMS diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 6986a53a1..d8144d1ff 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -30,6 +30,12 @@ Mesaj nou Marchează ca citit Marchează ca necitit + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… Eşti sigur că vrei să ştergi toate mesajele din această conversaţie? @@ -59,7 +65,9 @@ Send long messages as MMS + Password (leave blank if not needed) Mesajele + Password Exportă mesajele Exportă mesajele SMS Exportă mesajele MMS diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 7c9114cab..0c7c67662 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -29,6 +29,12 @@ Новое сообщение Прочитано Не прочитано + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… Удалить все сообщения в этой переписке\? @@ -55,7 +61,9 @@ Отправлять групповые сообщения как MMS Отправлять длинные сообщения как MMS + Password (leave blank if not needed) Сообщения + Password Экспорт сообщений Экспорт SMS Экспорт MMS @@ -98,4 +106,4 @@ Haven't found some strings? There's more at https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res --> - \ No newline at end of file + diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index 61e88cc7d..825e45c20 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -30,6 +30,12 @@ Nová správa Označiť ako prečítané Označiť ako neprečítané + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… Ste si istý, že chcete odstrániť všetky správy tejto konverzácie? @@ -61,7 +67,9 @@ Odosielať dlhé správy ako MMS + Password (leave blank if not needed) Správy + Password Exportovať správy Exportovať SMS Exportovať MMS diff --git a/app/src/main/res/values-ta/strings.xml b/app/src/main/res/values-ta/strings.xml index 664b67436..defdde49b 100644 --- a/app/src/main/res/values-ta/strings.xml +++ b/app/src/main/res/values-ta/strings.xml @@ -29,6 +29,12 @@ புதிய செய்தி படித்ததாக குறியிடு படிக்காததாக குறியிடு + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… இந்த உரையாடலின் அனைத்து செய்திகளையும் நிச்சயமாக நீக்க விரும்புகிறீர்களா\? @@ -53,7 +59,9 @@ Send group messages as MMS Send long messages as MMS + Password (leave blank if not needed) செய்திகளை + Password செய்திகளை ஏற்றுமதி செய்யவும் ஏற்றுமதி எஸ்எம்எஸ் ஏற்றுமதி MMS diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 414679e4e..65d560c21 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -29,6 +29,12 @@ Yeni mesaj Okundu olarak işaretle Okunmadı olarak işaretle + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… Bu görüşmenin tüm mesajlarını silmek istediğinizden emin misiniz\? @@ -53,7 +59,9 @@ Grup mesajlarını MMS olarak gönder Uzun mesajları MMS olarak gönder + Password (leave blank if not needed) Mesajlar + Password Mesajları dışa aktar SMS\'i dışa aktar MMS\'i dışa aktar @@ -77,4 +85,4 @@ Haven't found some strings? There's more at https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res --> - \ No newline at end of file + diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 4f3e21455..d61e472ca 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -29,6 +29,12 @@ Нове повідомлення Прочитано Не прочитано + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… Справді видалити всі повідомлення у цьому листуванні\? @@ -57,7 +63,9 @@ Надсилати групові повідомлення як MMS Надсилати довгі повідомлення як MMS + Password (leave blank if not needed) Messages + Password Export messages Export SMS Експорт MMS @@ -81,4 +89,4 @@ Haven't found some strings? There's more at https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res --> - \ No newline at end of file + diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 8494afa08..19da86a6d 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -29,6 +29,12 @@ 新消息 标记为已读 标记为未读 + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… 您确定要删除此对话的所有消息吗\? @@ -53,7 +59,9 @@ 将群组信息作为彩信发送 将长消息作为彩信发送 + Password (leave blank if not needed) 消息 + Password 导出消息 导出短信 导出彩信 @@ -96,4 +104,4 @@ Haven't found some strings? There's more at https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res --> - \ No newline at end of file + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 88b1121b7..b5658c1ac 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -29,6 +29,12 @@ New message Mark as Read Mark as Unread + + Import/Export Progress + Importing messages… + Exporting messages… + Encrypting backup… + Decrypting backup… Are you sure you want to delete all messages of this conversation? @@ -53,7 +59,9 @@ Send group messages as MMS Send long messages as MMS + Password (leave blank if not needed) Messages + Password Export messages Export SMS Export MMS