Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/bitfireAT/vcard4android.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRicki Hirner <hirner@bitfire.at>2022-03-09 18:07:13 +0300
committerRicki Hirner <hirner@bitfire.at>2022-03-09 18:09:08 +0300
commit381d65c7bc9640932f34f68936b9fada150b6598 (patch)
treef285b4511a06cd5fb967b61c37dc48e86963d4a4
parentbbb197d28dd44c9b98ffa19da88b8ad045c65548 (diff)
Introduce mapping of IM URIs to Messenger names
-rw-r--r--src/main/java/at/bitfire/vcard4android/contactrow/ImBuilder.kt51
-rw-r--r--src/main/java/at/bitfire/vcard4android/contactrow/ImHandler.kt27
-rw-r--r--src/main/java/at/bitfire/vcard4android/contactrow/ImMapping.kt61
3 files changed, 99 insertions, 40 deletions
diff --git a/src/main/java/at/bitfire/vcard4android/contactrow/ImBuilder.kt b/src/main/java/at/bitfire/vcard4android/contactrow/ImBuilder.kt
index e775f8f..0cc9ef2 100644
--- a/src/main/java/at/bitfire/vcard4android/contactrow/ImBuilder.kt
+++ b/src/main/java/at/bitfire/vcard4android/contactrow/ImBuilder.kt
@@ -23,11 +23,8 @@ class ImBuilder(dataRowUri: Uri, rawContactId: Long?, contact: Contact)
for (labeledIm in contact.impps) {
val impp = labeledIm.property
- val protocol = impp.protocol ?: ""
- /*if (protocol == null) {
- Constants.log.warning("Ignoring IM address without protocol")
- continue
- }*/
+ var protocol = impp.protocol ?: ""
+ var user = impp.handle
var typeCode = Im.TYPE_OTHER
var typeLabel: String? = null
@@ -46,8 +43,35 @@ class ImBuilder(dataRowUri: Uri, rawContactId: Long?, contact: Contact)
var protocolCode = Im.PROTOCOL_CUSTOM
var customProtocol: String? = null
- if (Build.VERSION.SDK_INT >= 31) {
+ // look for known messengers
+ ImMapping.uriToMessenger(impp.uri)?.let { (messenger, handle) ->
+ customProtocol = messenger
+ user = handle
+ }
+
+ if (customProtocol == null) {
+ // TODO move this code to ImMapping.uriToMessenger
+
+ // We parse SERVICE-TYPE (for instance used by iCloud), but don't use it actively.
+ val serviceType =
+ impp.getParameter(CustomType.Im.PARAMETER_SERVICE_TYPE)
+ ?: impp.getParameter(CustomType.Im.PARAMETER_SERVICE_TYPE_ALT)
+
+ customProtocol = // protocol name shown in Android
+ serviceType?.let { StringUtils.capitalize(it) } // use service type, if available
+ ?: StringUtils.capitalize(protocol) // fall back to raw URI scheme
+ }
+
+ if (Build.VERSION.SDK_INT < 31) {
// Since API level 31, PROTOCOL_XXX values are deprecated and only PROTOCOL_CUSTOM should be used.
+ @Suppress("DEPRECATION")
+ when (customProtocol) {
+ ImMapping.MESSENGER_AIM -> protocolCode = Im.PROTOCOL_AIM
+ // TODO
+ }
+ }
+
+ /*if (Build.VERSION.SDK_INT >= 31) {
} else {
/* On Android <12, we assign specific protocols like AIM etc. although most of them are not used anymore.
@@ -80,22 +104,11 @@ class ImBuilder(dataRowUri: Uri, rawContactId: Long?, contact: Contact)
// IMPP:sip:… is handled by SipAddressBuilder
continue
}
- }
-
- if (protocolCode == Im.PROTOCOL_CUSTOM) {
- // We parse SERVICE-TYPE (for instance used by iCloud), but don't use it actively.
- val serviceType =
- impp.getParameter(CustomType.Im.PARAMETER_SERVICE_TYPE) ?:
- impp.getParameter(CustomType.Im.PARAMETER_SERVICE_TYPE_ALT)
-
- customProtocol = // protocol name shown in Android
- serviceType?.let { StringUtils.capitalize(it) } ?: // use service type, if available
- StringUtils.capitalize(protocol) // fall back to raw URI scheme
- }
+ }*/
// save as IM address
result += newDataRow()
- .withValue(Im.DATA, impp.handle)
+ .withValue(Im.DATA, user)
.withValue(Im.TYPE, typeCode)
.withValue(Im.LABEL, typeLabel)
.withValue(Im.PROTOCOL, protocolCode)
diff --git a/src/main/java/at/bitfire/vcard4android/contactrow/ImHandler.kt b/src/main/java/at/bitfire/vcard4android/contactrow/ImHandler.kt
index ee0c8ea..afcaf7c 100644
--- a/src/main/java/at/bitfire/vcard4android/contactrow/ImHandler.kt
+++ b/src/main/java/at/bitfire/vcard4android/contactrow/ImHandler.kt
@@ -15,6 +15,7 @@ import at.bitfire.vcard4android.property.CustomType
import ezvcard.parameter.ImppType
import ezvcard.property.Impp
import org.apache.commons.lang3.StringUtils
+import java.net.URI
import java.util.logging.Level
object ImHandler: DataRowHandler() {
@@ -31,7 +32,8 @@ object ImHandler: DataRowHandler() {
return
}
- val impp = when (values.getAsInteger(Im.PROTOCOL)) {
+ val protocolCode = values.getAsInteger(Im.PROTOCOL)
+ val impp = when (protocolCode) {
Im.PROTOCOL_AIM ->
Impp.aim(handle)
Im.PROTOCOL_MSN ->
@@ -51,16 +53,11 @@ object ImHandler: DataRowHandler() {
Im.PROTOCOL_YAHOO ->
Impp.yahoo(handle)
Im.PROTOCOL_CUSTOM -> {
- val protocol = StringUtils.trimToNull(values.getAsString(Im.CUSTOM_PROTOCOL))
- try {
- Impp(protocolToUriScheme(protocol), handle)
- } catch (e: IllegalArgumentException) {
- Constants.log.warning("IM type/value can't be expressed as URI; ignoring")
- return
- }
+ val customProtocol = values.getAsString(Im.CUSTOM_PROTOCOL)
+ Impp(ImMapping.messengerToUri(customProtocol, handle))
}
else -> {
- Constants.log.log(Level.WARNING, "Unknown IM type", values)
+ Constants.log.log(Level.WARNING, "Unknown IM protocol: $protocolCode")
return
}
}
@@ -80,16 +77,4 @@ object ImHandler: DataRowHandler() {
contact.impps += labeledImpp
}
- fun protocolToUriScheme(s: String?) = s
- ?.normalizeNFD() // normalize with decomposition first (e.g. Á → A+ ́)
-
- /* then filter according to RFC 3986 3.1:
- scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
- ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
- DIGIT = %x30-39 ; 0-9
- */
- ?.replace(Regex("^[^a-zA-Z]+"), "")
- ?.replace(Regex("[^\\da-zA-Z+-.]"), "")
- ?.lowercase()
-
} \ No newline at end of file
diff --git a/src/main/java/at/bitfire/vcard4android/contactrow/ImMapping.kt b/src/main/java/at/bitfire/vcard4android/contactrow/ImMapping.kt
new file mode 100644
index 0000000..a14177e
--- /dev/null
+++ b/src/main/java/at/bitfire/vcard4android/contactrow/ImMapping.kt
@@ -0,0 +1,61 @@
+/***************************************************************************************************
+ * Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
+ **************************************************************************************************/
+
+package at.bitfire.vcard4android.contactrow
+
+import at.bitfire.vcard4android.Constants
+import at.bitfire.vcard4android.Utils.normalizeNFD
+import java.net.URI
+import java.net.URISyntaxException
+import java.util.logging.Level
+
+object ImMapping {
+
+ const val MESSENGER_AIM = "AIM"
+ const val MESSENGER_IRC = "IRC"
+ const val MESSENGER_THREEMA = "Threema"
+
+ // TODO Tests
+
+
+ fun messengerToUri(messenger: String, handle: String): URI? =
+ try {
+ when (messenger.lowercase()) {
+ MESSENGER_AIM.lowercase() -> URI("aim", handle, null)
+ MESSENGER_IRC.lowercase() -> URI("irc", handle, null)
+ MESSENGER_THREEMA.lowercase() -> URI("https", "threema.id", "/${handle}", null)
+ else ->
+ // fallback for unknown messengers
+ URI(messengerToUriScheme(messenger), handle, null)
+ }
+ } catch (e: URISyntaxException) {
+ Constants.log.log(Level.WARNING, "Couldn't generate URI from IM: $messenger / $handle", e)
+ null
+ }
+
+ fun uriToMessenger(uri: URI): Pair<String, String>? =
+ when {
+ uri.scheme.equals("aim", true) ->
+ Pair(MESSENGER_AIM, uri.schemeSpecificPart)
+ uri.scheme.equals("irc", true) ->
+ Pair(MESSENGER_IRC, uri.schemeSpecificPart)
+ uri.authority.equals("threema.id", true) ->
+ Pair(MESSENGER_THREEMA, uri.path.trimStart('/'))
+ else -> null
+ }
+
+
+ fun messengerToUriScheme(s: String?) = s
+ ?.normalizeNFD() // normalize with decomposition first (e.g. Á → A+ ́)
+
+ /* then filter according to RFC 3986 3.1:
+ scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+ ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
+ DIGIT = %x30-39 ; 0-9
+ */
+ ?.replace(Regex("^[^a-zA-Z]+"), "")
+ ?.replace(Regex("[^\\da-zA-Z+-.]"), "")
+ ?.lowercase()
+
+} \ No newline at end of file