From 1c4c0fe4ad32a15893b20556f5e6a2759a1c9bae Mon Sep 17 00:00:00 2001 From: nuclearfog Date: Sun, 24 Jan 2021 19:32:33 +0100 Subject: [PATCH] added TLS 1.2 support for old android versions, fixed crash on android < 21, layout fix --- .../twidda/activity/LoginActivity.java | 28 ------- .../twidda/adapter/ListAdapter.java | 7 +- .../twidda/adapter/MessageAdapter.java | 7 +- .../twidda/adapter/TweetAdapter.java | 7 +- .../twidda/adapter/UserAdapter.java | 7 +- .../backend/engine/TLSSocketFactory.java | 82 +++++++++++++++++++ .../twidda/backend/engine/TwitterEngine.java | 21 +++++ .../twidda/backend/utils/AppStyles.java | 12 ++- app/src/main/res/layout/dialog_app_info.xml | 1 + app/src/main/res/values-de-rDE/strings.xml | 3 - app/src/main/res/values/strings.xml | 3 - app/src/main/res/values/styles.xml | 2 +- 12 files changed, 134 insertions(+), 46 deletions(-) create mode 100644 app/src/main/java/org/nuclearfog/twidda/backend/engine/TLSSocketFactory.java diff --git a/app/src/main/java/org/nuclearfog/twidda/activity/LoginActivity.java b/app/src/main/java/org/nuclearfog/twidda/activity/LoginActivity.java index 0c5d7f71..efa81e3e 100644 --- a/app/src/main/java/org/nuclearfog/twidda/activity/LoginActivity.java +++ b/app/src/main/java/org/nuclearfog/twidda/activity/LoginActivity.java @@ -25,11 +25,6 @@ import org.nuclearfog.twidda.backend.utils.AppStyles; import org.nuclearfog.twidda.backend.utils.ErrorHandler; import org.nuclearfog.twidda.database.GlobalSettings; -import java.security.NoSuchAlgorithmException; - -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLParameters; - import static android.content.Intent.ACTION_VIEW; import static android.os.AsyncTask.Status.FINISHED; import static android.os.AsyncTask.Status.RUNNING; @@ -65,7 +60,6 @@ public class LoginActivity extends AppCompatActivity implements OnClickListener linkButton.setOnClickListener(this); loginButton.setOnClickListener(this); - checkTLSSupport(); } @@ -167,26 +161,4 @@ public class LoginActivity extends AppCompatActivity implements OnClickListener public void onError(EngineException error) { ErrorHandler.handleFailure(this, error); } - - /** - * Check if phone supports TLS 1.2 which is required for twitter api - */ - private void checkTLSSupport() { - boolean tls12Found = false; - try { - SSLParameters param = SSLContext.getDefault().getDefaultSSLParameters(); - String[] protocols = param.getProtocols(); - for (String protocol : protocols) { - if (protocol.equals("TLSv1.2") || protocol.equals("TLSv1.3")) { - tls12Found = true; - break; - } - } - } catch (NoSuchAlgorithmException er) { - // ignore - } - if (!tls12Found) { - Toast.makeText(this, R.string.info_phone_tls_support, LENGTH_LONG).show(); - } - } } \ No newline at end of file diff --git a/app/src/main/java/org/nuclearfog/twidda/adapter/ListAdapter.java b/app/src/main/java/org/nuclearfog/twidda/adapter/ListAdapter.java index 40294903..5bd286bc 100644 --- a/app/src/main/java/org/nuclearfog/twidda/adapter/ListAdapter.java +++ b/app/src/main/java/org/nuclearfog/twidda/adapter/ListAdapter.java @@ -16,6 +16,7 @@ import android.widget.TextView; import androidx.annotation.MainThread; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.appcompat.content.res.AppCompatResources; import androidx.cardview.widget.CardView; import androidx.recyclerview.widget.RecyclerView.Adapter; import androidx.recyclerview.widget.RecyclerView.ViewHolder; @@ -77,8 +78,10 @@ public class ListAdapter extends Adapter { TypedArray drawables = context.getResources().obtainTypedArray(R.array.list_item_icons); icons = new Drawable[drawables.length()]; - for (int index = 0; index < drawables.length(); index++) - icons[index] = drawables.getDrawable(index); + for (int index = 0; index < drawables.length(); index++) { + int resId = drawables.getResourceId(index, 0); + icons[index] = AppCompatResources.getDrawable(context, resId); + } drawables.recycle(); colorIcons(); } diff --git a/app/src/main/java/org/nuclearfog/twidda/adapter/MessageAdapter.java b/app/src/main/java/org/nuclearfog/twidda/adapter/MessageAdapter.java index 9462413a..ef3b0a27 100644 --- a/app/src/main/java/org/nuclearfog/twidda/adapter/MessageAdapter.java +++ b/app/src/main/java/org/nuclearfog/twidda/adapter/MessageAdapter.java @@ -15,6 +15,7 @@ import android.widget.TextView; import androidx.annotation.MainThread; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.appcompat.content.res.AppCompatResources; import androidx.cardview.widget.CardView; import androidx.recyclerview.widget.RecyclerView.Adapter; import androidx.recyclerview.widget.RecyclerView.ViewHolder; @@ -57,8 +58,10 @@ public class MessageAdapter extends Adapter { TypedArray drawables = context.getResources().obtainTypedArray(R.array.dm_item_icons); icons = new Drawable[drawables.length()]; - for (int index = 0; index < drawables.length(); index++) - icons[index] = drawables.getDrawable(index); + for (int index = 0; index < drawables.length(); index++) { + int resId = drawables.getResourceId(index, 0); + icons[index] = AppCompatResources.getDrawable(context, resId); + } drawables.recycle(); setIconColor(); } diff --git a/app/src/main/java/org/nuclearfog/twidda/adapter/TweetAdapter.java b/app/src/main/java/org/nuclearfog/twidda/adapter/TweetAdapter.java index 6d256842..922646d7 100644 --- a/app/src/main/java/org/nuclearfog/twidda/adapter/TweetAdapter.java +++ b/app/src/main/java/org/nuclearfog/twidda/adapter/TweetAdapter.java @@ -18,6 +18,7 @@ import android.widget.TextView; import androidx.annotation.MainThread; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.appcompat.content.res.AppCompatResources; import androidx.cardview.widget.CardView; import androidx.recyclerview.widget.RecyclerView.Adapter; import androidx.recyclerview.widget.RecyclerView.ViewHolder; @@ -85,8 +86,10 @@ public class TweetAdapter extends Adapter { TypedArray tArray = context.getResources().obtainTypedArray(R.array.tweet_item_icons); icons = new Drawable[tArray.length()]; - for (int index = 0; index < icons.length; index++) - icons[index] = tArray.getDrawable(index); + for (int index = 0; index < icons.length; index++) { + int resId = tArray.getResourceId(index, 0); + icons[index] = AppCompatResources.getDrawable(context, resId); + } tArray.recycle(); setIconColors(); } diff --git a/app/src/main/java/org/nuclearfog/twidda/adapter/UserAdapter.java b/app/src/main/java/org/nuclearfog/twidda/adapter/UserAdapter.java index ce95a349..16229fa7 100644 --- a/app/src/main/java/org/nuclearfog/twidda/adapter/UserAdapter.java +++ b/app/src/main/java/org/nuclearfog/twidda/adapter/UserAdapter.java @@ -17,6 +17,7 @@ import android.widget.TextView; import androidx.annotation.MainThread; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.appcompat.content.res.AppCompatResources; import androidx.cardview.widget.CardView; import androidx.recyclerview.widget.RecyclerView.Adapter; import androidx.recyclerview.widget.RecyclerView.ViewHolder; @@ -79,8 +80,10 @@ public class UserAdapter extends Adapter { TypedArray drawables = context.getResources().obtainTypedArray(R.array.user_item_icons); icons = new Drawable[drawables.length()]; - for (int index = 0; index < drawables.length(); index++) - icons[index] = drawables.getDrawable(index); + for (int index = 0; index < drawables.length(); index++) { + int resId = drawables.getResourceId(index, 0); + icons[index] = AppCompatResources.getDrawable(context, resId); + } drawables.recycle(); setIconColor(); } diff --git a/app/src/main/java/org/nuclearfog/twidda/backend/engine/TLSSocketFactory.java b/app/src/main/java/org/nuclearfog/twidda/backend/engine/TLSSocketFactory.java new file mode 100644 index 00000000..6c60cfca --- /dev/null +++ b/app/src/main/java/org/nuclearfog/twidda/backend/engine/TLSSocketFactory.java @@ -0,0 +1,82 @@ +package org.nuclearfog.twidda.backend.engine; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; + +/** + * @author fkrauthan + * @see + */ +public class TLSSocketFactory extends SSLSocketFactory { + + private SSLSocketFactory internalSSLSocketFactory; + + public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException { + SSLContext context = SSLContext.getInstance("TLS"); + context.init(null, null, null); + internalSSLSocketFactory = context.getSocketFactory(); + } + + + @Override + public String[] getDefaultCipherSuites() { + return internalSSLSocketFactory.getDefaultCipherSuites(); + } + + + @Override + public String[] getSupportedCipherSuites() { + return internalSSLSocketFactory.getSupportedCipherSuites(); + } + + + @Override + public Socket createSocket() throws IOException { + return enableTLSOnSocket(internalSSLSocketFactory.createSocket()); + } + + + @Override + public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { + return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose)); + } + + + @Override + public Socket createSocket(String host, int port) throws IOException { + return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port)); + } + + + @Override + public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException { + return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort)); + } + + + @Override + public Socket createSocket(InetAddress host, int port) throws IOException { + return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port)); + } + + + @Override + public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { + return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort)); + } + + + private Socket enableTLSOnSocket(Socket socket) { + if (socket instanceof SSLSocket) { + ((SSLSocket) socket).setEnabledProtocols(new String[]{"TLSv1.1", "TLSv1.2"}); + } + return socket; + } +} \ No newline at end of file diff --git a/app/src/main/java/org/nuclearfog/twidda/backend/engine/TwitterEngine.java b/app/src/main/java/org/nuclearfog/twidda/backend/engine/TwitterEngine.java index bafd0e3c..e84dc9da 100644 --- a/app/src/main/java/org/nuclearfog/twidda/backend/engine/TwitterEngine.java +++ b/app/src/main/java/org/nuclearfog/twidda/backend/engine/TwitterEngine.java @@ -30,6 +30,10 @@ import java.net.URL; import java.util.LinkedList; import java.util.List; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; + import io.michaelrocks.paranoid.Obfuscate; import twitter4j.DirectMessage; import twitter4j.GeoLocation; @@ -76,6 +80,23 @@ public class TwitterEngine { * Initialize Twitter4J instance */ private void initTwitter() { + // check for TLS 1.2 support and activate it + try { + boolean tlsEnabled = false; + SSLParameters param = SSLContext.getDefault().getDefaultSSLParameters(); + String[] protocols = param.getProtocols(); + for (String protocol : protocols) { + if (protocol.equals("TLSv1.2") || protocol.equals("TLSv1.3")) { + tlsEnabled = true; + break; + } + } + if (!tlsEnabled) { + HttpsURLConnection.setDefaultSSLSocketFactory(new TLSSocketFactory()); + } + } catch (Exception err) { + err.printStackTrace(); + } ConfigurationBuilder builder = new ConfigurationBuilder(); if (settings.isCustomApiSet()) { builder.setOAuthConsumerKey(settings.getConsumerKey()); diff --git a/app/src/main/java/org/nuclearfog/twidda/backend/utils/AppStyles.java b/app/src/main/java/org/nuclearfog/twidda/backend/utils/AppStyles.java index adfe4ac2..d6b37126 100644 --- a/app/src/main/java/org/nuclearfog/twidda/backend/utils/AppStyles.java +++ b/app/src/main/java/org/nuclearfog/twidda/backend/utils/AppStyles.java @@ -22,6 +22,7 @@ import android.widget.TextView; import androidx.annotation.ArrayRes; import androidx.annotation.Nullable; +import androidx.appcompat.content.res.AppCompatResources; import androidx.cardview.widget.CardView; import androidx.viewpager.widget.ViewPager; @@ -231,7 +232,10 @@ public final class AppStyles { } /** - * set Tab icons for TabLayout + * set tab icons + * + * @param tabLayout tablayout to set tab icons + * @param settings settings to set color */ public static void setTabIcons(TabLayout tabLayout, GlobalSettings settings, @ArrayRes int array) { Context context = tabLayout.getContext(); @@ -239,7 +243,8 @@ public final class AppStyles { for (int index = 0; index < tArray.length(); index++) { TabLayout.Tab mTab = tabLayout.getTabAt(index); if (mTab != null) { - Drawable icon = tArray.getDrawable(index); + int resId = tArray.getResourceId(index, 0); + Drawable icon = AppCompatResources.getDrawable(context, resId); setDrawableColor(icon, settings.getIconColor()); mTab.setIcon(icon); } @@ -262,7 +267,8 @@ public final class AppStyles { for (int index = 0; index < tArray.length(); index++) { TabLayout.Tab mTab = tabLayout.getTabAt(index); if (mTab != null) { - Drawable icon = tArray.getDrawable(index); + int resId = tArray.getResourceId(index, 0); + Drawable icon = AppCompatResources.getDrawable(context, resId); setDrawableColor(icon, settings.getIconColor()); View v = View.inflate(context, R.layout.icon_profile_tab, null); ImageView imageIcon = v.findViewById(R.id.tab_icon); diff --git a/app/src/main/res/layout/dialog_app_info.xml b/app/src/main/res/layout/dialog_app_info.xml index a5dd00c8..bf058940 100644 --- a/app/src/main/res/layout/dialog_app_info.xml +++ b/app/src/main/res/layout/dialog_app_info.xml @@ -4,6 +4,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" + android:background="@android:color/white" android:orientation="vertical"> Passwort Direktnachricht konnte nicht an diesen Nutzer gesendet werden! Nutzer stummschalten? - Standort konnte nicht ermittelt werden! Link konnte nicht kopiert werden! GPS Position hinzugefügt - starte GPS lokalisierung… GPS lokalisierung fehlgeschlagen! PIN muss erst von Twitter abgefragt werden! Bitte den ersten Button drücken! Bitte zuerst link anklicken! @@ -134,7 +132,6 @@ Falsche Verbindung angegeben! Link konnte nicht geöffnet werden! Sensible Inhalte - TLS 1.2 wird nicht unterstützt. Die App wird möglicherweise nicht funktionieren! 3 Schritte zum Login öffne Twitter login Seite Melde in Twitter an diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 66214e96..9060a77c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -112,12 +112,10 @@ Userlist created redirecting to Twitter login login to Twitter - Phone does not support TLS 1.2. App will probably not work! Wrong connection settings! can\'t add video get Twitter PIN from browser first. Please press the first button! GPS position added - starting location… retweeted Retweet removed Tweet added to favorites @@ -153,7 +151,6 @@ No gallery app found! Connection failed! Invalid link! - could not fetch location! can\'t copy link to clipboard! could not fetch GPS data! Please get link first! diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index ca271971..cd6a374b 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -1,7 +1,7 @@ -