use bind 2 tag and sasl 2 user-agent

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/utils/PhoneHelper.java   | 68 +++-
src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java | 19 
2 files changed, 58 insertions(+), 29 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/utils/PhoneHelper.java 🔗

@@ -12,27 +12,51 @@ import android.provider.Settings;
 
 public class PhoneHelper {
 
-	@SuppressLint("HardwareIds")
-	public static String getAndroidId(Context context) {
-		return Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
-	}
+    @SuppressLint("HardwareIds")
+    public static String getAndroidId(Context context) {
+        return Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
+    }
 
-	public static Uri getProfilePictureUri(Context context) {
-		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
-			return null;
-		}
-		final String[] projection = new String[]{Profile._ID, Profile.PHOTO_URI};
-		final Cursor cursor;
-		try {
-			cursor = context.getContentResolver().query(Profile.CONTENT_URI, projection, null, null, null);
-		} catch (Throwable e) {
-			return null;
-		}
-		if (cursor == null) {
-			return null;
-		}
-		final String uri = cursor.moveToFirst() ? cursor.getString(1) : null;
-		cursor.close();
-		return uri == null ? null : Uri.parse(uri);
-	}
+    public static Uri getProfilePictureUri(Context context) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
+                && context.checkSelfPermission(Manifest.permission.READ_CONTACTS)
+                        != PackageManager.PERMISSION_GRANTED) {
+            return null;
+        }
+        final String[] projection = new String[] {Profile._ID, Profile.PHOTO_URI};
+        final Cursor cursor;
+        try {
+            cursor =
+                    context.getContentResolver()
+                            .query(Profile.CONTENT_URI, projection, null, null, null);
+        } catch (Throwable e) {
+            return null;
+        }
+        if (cursor == null) {
+            return null;
+        }
+        final String uri = cursor.moveToFirst() ? cursor.getString(1) : null;
+        cursor.close();
+        return uri == null ? null : Uri.parse(uri);
+    }
+
+    public static boolean isEmulator() {
+        return (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic"))
+                || Build.FINGERPRINT.startsWith("generic")
+                || Build.FINGERPRINT.startsWith("unknown")
+                || Build.HARDWARE.contains("goldfish")
+                || Build.HARDWARE.contains("ranchu")
+                || Build.MODEL.contains("google_sdk")
+                || Build.MODEL.contains("Emulator")
+                || Build.MODEL.contains("Android SDK built for x86")
+                || Build.MANUFACTURER.contains("Genymotion")
+                || Build.PRODUCT.contains("sdk_google")
+                || Build.PRODUCT.contains("google_sdk")
+                || Build.PRODUCT.contains("sdk")
+                || Build.PRODUCT.contains("sdk_x86")
+                || Build.PRODUCT.contains("sdk_gphone64_arm64")
+                || Build.PRODUCT.contains("vbox86p")
+                || Build.PRODUCT.contains("emulator")
+                || Build.PRODUCT.contains("simulator");
+    }
 }

src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java 🔗

@@ -5,6 +5,7 @@ import static eu.siacs.conversations.utils.Random.SECURE_RANDOM;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
+import android.os.Build;
 import android.os.SystemClock;
 import android.security.KeyChain;
 import android.util.Base64;
@@ -59,6 +60,7 @@ import javax.net.ssl.SSLSocketFactory;
 import javax.net.ssl.X509KeyManager;
 import javax.net.ssl.X509TrustManager;
 
+import eu.siacs.conversations.BuildConfig;
 import eu.siacs.conversations.Config;
 import eu.siacs.conversations.R;
 import eu.siacs.conversations.crypto.XmppDomainVerifier;
@@ -77,6 +79,7 @@ import eu.siacs.conversations.services.NotificationService;
 import eu.siacs.conversations.services.XmppConnectionService;
 import eu.siacs.conversations.utils.CryptoHelper;
 import eu.siacs.conversations.utils.Patterns;
+import eu.siacs.conversations.utils.PhoneHelper;
 import eu.siacs.conversations.utils.Resolver;
 import eu.siacs.conversations.utils.SSLSocketHelper;
 import eu.siacs.conversations.utils.SocksSocketFactory;
@@ -1292,6 +1295,14 @@ public class XmppConnection implements Runnable {
             if (!Strings.isNullOrEmpty(firstMessage)) {
                 authenticate.addChild("initial-response").setContent(firstMessage);
             }
+            final Element userAgent = authenticate.addChild("user-agent");
+            userAgent.setAttribute("id", account.getUuid());
+            userAgent.addChild("software").setContent(mXmppConnectionService.getString(R.string.app_name));
+            if (!PhoneHelper.isEmulator()) {
+                userAgent
+                        .addChild("device")
+                        .setContent(String.format("%s %s", Build.MANUFACTURER, Build.MODEL));
+            }
             final Element inline = this.streamFeatures.findChild("inline", Namespace.SASL_2);
             final boolean inlineStreamManagement =
                     inline != null && inline.hasChild("sm", "urn:xmpp:sm:3");
@@ -1330,9 +1341,7 @@ public class XmppConnection implements Runnable {
     private Element generateBindRequest(final Collection<String> bindFeatures) {
         Log.d(Config.LOGTAG, "inline bind features: " + bindFeatures);
         final Element bind = new Element("bind", Namespace.BIND2);
-        final Element clientId = bind.addChild("client-id");
-        clientId.setAttribute("tag", mXmppConnectionService.getString(R.string.app_name));
-        clientId.setContent(account.getUuid());
+        bind.addChild("tag").setContent(mXmppConnectionService.getString(R.string.app_name));
         final Element features = bind.addChild("features");
         if (bindFeatures.contains(Namespace.CARBONS)) {
             features.addChild("enable", Namespace.CARBONS);
@@ -1343,10 +1352,6 @@ public class XmppConnection implements Runnable {
         return bind;
     }
 
-    private static Collection<String> extractMechanisms(final Element stream) {
-        return Collections2.transform(stream.getChildren(), c -> c == null ? null : c.getContent());
-    }
-
     private void register() {
         final String preAuth = account.getKey(Account.KEY_PRE_AUTH_REGISTRATION_TOKEN);
         if (preAuth != null && features.invite()) {