mirror of
				https://github.com/SimpleMobileTools/Simple-Contacts.git
				synced 2025-06-05 21:59:27 +02:00 
			
		
		
		
	fix #62, properly handle ansi encoded names
This commit is contained in:
		| @@ -29,7 +29,7 @@ const val DEFAULT_EVENT_TYPE = CommonDataKinds.Event.TYPE_BIRTHDAY | |||||||
| // export/import | // export/import | ||||||
| const val BEGIN_VCARD = "BEGIN:VCARD" | const val BEGIN_VCARD = "BEGIN:VCARD" | ||||||
| const val END_VCARD = "END:VCARD" | const val END_VCARD = "END:VCARD" | ||||||
| const val N = "N:" | const val N = "N" | ||||||
| const val TEL = "TEL" | const val TEL = "TEL" | ||||||
| const val BDAY = "BDAY:" | const val BDAY = "BDAY:" | ||||||
| const val ANNIVERSARY = "ANNIVERSARY:" | const val ANNIVERSARY = "ANNIVERSARY:" | ||||||
|   | |||||||
| @@ -0,0 +1,43 @@ | |||||||
|  | package com.simplemobiletools.contacts.helpers | ||||||
|  |  | ||||||
|  | import java.io.ByteArrayOutputStream | ||||||
|  |  | ||||||
|  | // https://alvinalexander.com/java/jwarehouse/android/core/java/com/google/android/mms/pdu/QuotedPrintable.java.shtml | ||||||
|  | object QuotedPrintable { | ||||||
|  |     private const val ESCAPE_CHAR: Byte = '='.toByte() | ||||||
|  |     fun decode(value: String?): String { | ||||||
|  |         val bytes = value?.toByteArray() | ||||||
|  |         if (bytes == null || bytes.isEmpty()) { | ||||||
|  |             return "" | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         val buffer = ByteArrayOutputStream() | ||||||
|  |         var i = 0 | ||||||
|  |         while (i < bytes.size) { | ||||||
|  |             val b = bytes[i].toInt() | ||||||
|  |             if (b == ESCAPE_CHAR.toInt()) { | ||||||
|  |                 try { | ||||||
|  |                     if ('\r' == bytes[i + 1].toChar() && '\n' == bytes[i + 2].toChar()) { | ||||||
|  |                         i += 2 | ||||||
|  |                         continue | ||||||
|  |                     } | ||||||
|  |  | ||||||
|  |                     val u = Character.digit(bytes[++i].toChar(), 16) | ||||||
|  |                     val l = Character.digit(bytes[++i].toChar(), 16) | ||||||
|  |                     if (u == -1 || l == -1) { | ||||||
|  |                         return "" | ||||||
|  |                     } | ||||||
|  |  | ||||||
|  |                     buffer.write(((u shl 4) + l).toChar().toInt()) | ||||||
|  |                 } catch (e: ArrayIndexOutOfBoundsException) { | ||||||
|  |                     return "" | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |             } else { | ||||||
|  |                 buffer.write(b) | ||||||
|  |             } | ||||||
|  |             i++ | ||||||
|  |         } | ||||||
|  |         return String(buffer.toByteArray()) | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -36,7 +36,7 @@ class VcfExporter { | |||||||
|                     for (contact in contacts) { |                     for (contact in contacts) { | ||||||
|                         out.writeLn(BEGIN_VCARD) |                         out.writeLn(BEGIN_VCARD) | ||||||
|                         out.writeLn(VERSION_2_1) |                         out.writeLn(VERSION_2_1) | ||||||
|                         out.writeLn("$N${contact.surname};${contact.firstName};${contact.middleName};;") |                         out.writeLn("$N:${contact.surname};${contact.firstName};${contact.middleName};;") | ||||||
|  |  | ||||||
|                         contact.phoneNumbers.forEach { |                         contact.phoneNumbers.forEach { | ||||||
|                             out.writeLn("$TEL;${getPhoneNumberLabel(it.type)}:${it.value}") |                             out.writeLn("$TEL;${getPhoneNumberLabel(it.type)}:${it.value}") | ||||||
|   | |||||||
| @@ -82,11 +82,13 @@ class VcfImporter(val activity: SimpleActivity) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     private fun parseNames(names: String) { |     private fun parseNames(names: String) { | ||||||
|         val nameParts = names.split(";") |         val parts = names.split(":") | ||||||
|         curSurname = nameParts[0] |         val isANSI = parts.first().toUpperCase().contains("QUOTED-PRINTABLE") | ||||||
|         curFirstName = nameParts[1] |         val nameParts = parts[1].split(";") | ||||||
|  |         curSurname = if (isANSI) QuotedPrintable.decode(nameParts[0]) else nameParts[0] | ||||||
|  |         curFirstName = if (isANSI) QuotedPrintable.decode(nameParts[1]) else nameParts[1] | ||||||
|         if (nameParts.size > 2) { |         if (nameParts.size > 2) { | ||||||
|             curMiddleName = nameParts[2] |             curMiddleName = if (isANSI) QuotedPrintable.decode(nameParts[2]) else nameParts[2] | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user