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 1204d748..4298014e 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/MainActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/MainActivity.kt @@ -627,6 +627,7 @@ class MainActivity : SimpleActivity() { Intent(Intent.ACTION_GET_CONTENT).apply { addCategory(Intent.CATEGORY_OPENABLE) type = EXPORT_MIME_TYPE + putExtra(Intent.EXTRA_MIME_TYPES, arrayOf(EXPORT_MIME_TYPE, XML_IMPORT_MIME_TYPE)) try { startActivityForResult(this, PICK_IMPORT_SOURCE_INTENT) @@ -639,27 +640,27 @@ class MainActivity : SimpleActivity() { } else { handlePermission(PERMISSION_READ_STORAGE) { if (it) { - importEvents() + importMessages() } } } } - private fun importEvents() { + private fun importMessages() { FilePickerDialog(this) { - showImportEventsDialog(it) + showImportMessagesDialog(it) } } - private fun showImportEventsDialog(path: String) { + private fun showImportMessagesDialog(path: String) { ImportMessagesDialog(this, path) } private fun tryImportMessagesFromFile(uri: Uri) { when (uri.scheme) { - "file" -> showImportEventsDialog(uri.path!!) + "file" -> showImportMessagesDialog(uri.path!!) "content" -> { - val tempFile = getTempFile("messages", "backup.json") + var tempFile = getTempFile("messages", "backup.json") if (tempFile == null) { toast(R.string.unknown_error_occurred) return @@ -669,7 +670,18 @@ class MainActivity : SimpleActivity() { val inputStream = contentResolver.openInputStream(uri) val out = FileOutputStream(tempFile) inputStream!!.copyTo(out) - showImportEventsDialog(tempFile.absolutePath) + // Check is XML and properly rename + tempFile.bufferedReader().use { + if (it.readLine().startsWith(" - val jsonReader = gson.newJsonReader(reader) - val smsMessageType = object : TypeToken() {}.type - val mmsMessageType = object : TypeToken() {}.type - - jsonReader.beginArray() - while (jsonReader.hasNext()) { - jsonReader.beginObject() - while (jsonReader.hasNext()) { - val nextToken = jsonReader.peek() - if (nextToken.ordinal == JsonToken.NAME.ordinal) { - val msgType = jsonReader.nextName() - - if ((!msgType.equals("sms") && !msgType.equals("mms")) || - (msgType.equals("sms") && !config.importSms) || - (msgType.equals("mms") && !config.importMms) - ) { - jsonReader.skipValue() - continue - } - - jsonReader.beginArray() - while (jsonReader.hasNext()) { - try { - if (msgType.equals("sms")) { - val message = gson.fromJson(jsonReader, smsMessageType) - messageWriter.writeSmsMessage(message) - } else { - val message = gson.fromJson(jsonReader, mmsMessageType) - messageWriter.writeMmsMessage(message) - } - - messagesImported++ - } catch (e: Exception) { - context.showErrorToast(e) - messagesFailed++ - - } - } - jsonReader.endArray() - } else { - jsonReader.skipValue() - } - } - - jsonReader.endObject() - refreshMessages() - } - - jsonReader.endArray() + if (path.endsWith("xml")) { + inputStream.importXml() + } else { + inputStream.importJson() } + } catch (e: Exception) { context.showErrorToast(e) messagesFailed++ @@ -101,4 +59,131 @@ class MessagesImporter(private val context: Context) { ) } } + + private fun InputStream.importJson() { + bufferedReader().use { reader -> + val jsonReader = gson.newJsonReader(reader) + val smsMessageType = object : TypeToken() {}.type + val mmsMessageType = object : TypeToken() {}.type + + jsonReader.beginArray() + while (jsonReader.hasNext()) { + jsonReader.beginObject() + while (jsonReader.hasNext()) { + val nextToken = jsonReader.peek() + if (nextToken.ordinal == JsonToken.NAME.ordinal) { + val msgType = jsonReader.nextName() + + if ((!msgType.equals("sms") && !msgType.equals("mms")) || + (msgType.equals("sms") && !config.importSms) || + (msgType.equals("mms") && !config.importMms) + ) { + jsonReader.skipValue() + continue + } + + jsonReader.beginArray() + while (jsonReader.hasNext()) { + try { + if (msgType.equals("sms")) { + val message = gson.fromJson(jsonReader, smsMessageType) + messageWriter.writeSmsMessage(message) + } else { + val message = gson.fromJson(jsonReader, mmsMessageType) + messageWriter.writeMmsMessage(message) + } + + messagesImported++ + } catch (e: Exception) { + context.showErrorToast(e) + messagesFailed++ + + } + } + jsonReader.endArray() + } else { + jsonReader.skipValue() + } + } + + jsonReader.endObject() + refreshMessages() + } + + jsonReader.endArray() + } + } + + private fun InputStream.importXml() { + bufferedReader().use { reader -> + val xmlParser = Xml.newPullParser().apply { + setInput(reader) + } + + xmlParser.nextTag() + xmlParser.require(XmlPullParser.START_TAG, null, "smses") + + var depth = 1 + while (depth != 0) { + when (xmlParser.next()) { + XmlPullParser.END_TAG -> depth-- + XmlPullParser.START_TAG -> depth++ + } + + if (xmlParser.eventType != XmlPullParser.START_TAG) { + continue + } + + try { + if (xmlParser.name == "sms") { + if (config.importSms) { + val message = xmlParser.readSms() + messageWriter.writeSmsMessage(message) + messagesImported++ + } else { + xmlParser.skip() + } + } else { + xmlParser.skip() + } + } catch (e: Exception) { + context.showErrorToast(e) + messagesFailed++ + } + } + + refreshMessages() + } + } + + private fun XmlPullParser.readSms(): SmsBackup { + require(XmlPullParser.START_TAG, null, "sms") + + return SmsBackup( + subscriptionId = 0, + address = getAttributeValue(null, "address"), + body = getAttributeValue(null, "body"), + date = getAttributeValue(null, "date").toLong(), + dateSent = getAttributeValue(null, "date").toLong(), + locked = getAttributeValue(null, "locked").toInt(), + protocol = getAttributeValue(null, "protocol"), + read = getAttributeValue(null, "read").toInt(), + status = getAttributeValue(null, "status").toInt(), + type = getAttributeValue(null, "type").toInt(), + serviceCenter = getAttributeValue(null, "service_center") + ) + } + + private fun XmlPullParser.skip() { + if (eventType != XmlPullParser.START_TAG) { + throw IllegalStateException() + } + var depth = 1 + while (depth != 0) { + when (next()) { + XmlPullParser.END_TAG -> depth-- + XmlPullParser.START_TAG -> depth++ + } + } + } }