diff options
author | Arne Schwabe <arne@rfc2549.org> | 2021-09-28 01:24:09 +0200 |
---|---|---|
committer | Arne Schwabe <arne@rfc2549.org> | 2021-10-01 19:56:39 +0200 |
commit | f6227082f1c70f0443e0f5d6a5f10c2838e1b7ee (patch) | |
tree | a44ba5d3290fd4c292097bea3566742d67ffb016 /main/src/ui/java | |
parent | 9e704d04dc7f2f93bddf85d371772340fa5af0b1 (diff) |
Implement using compat-mode
Diffstat (limited to 'main/src/ui/java')
4 files changed, 278 insertions, 301 deletions
diff --git a/main/src/ui/java/de/blinkt/openvpn/activities/ConfigConverter.kt b/main/src/ui/java/de/blinkt/openvpn/activities/ConfigConverter.kt index d01797f2..6ccf4c8a 100644 --- a/main/src/ui/java/de/blinkt/openvpn/activities/ConfigConverter.kt +++ b/main/src/ui/java/de/blinkt/openvpn/activities/ConfigConverter.kt @@ -55,6 +55,8 @@ class ConfigConverter : BaseActivity(), FileSelectCallback, View.OnClickListener private val mLogEntries = Vector<String>() private var mSourceUri: Uri? = null private lateinit var mProfilename: EditText + private lateinit var mCompatmode: Spinner + private lateinit var mCompatmodeLabel: TextView private var mImportTask: AsyncTask<Void, Void, Int>? = null private lateinit var mLogLayout: LinearLayout private lateinit var mProfilenameLabel: TextView @@ -124,6 +126,8 @@ class ConfigConverter : BaseActivity(), FileSelectCallback, View.OnClickListener return true } + mResult!!.mCompatMode = Utils.mapCompatMode(mCompatmode.selectedItemPosition) + val `in` = installPKCS12() if (`in` != null) @@ -573,12 +577,17 @@ class ConfigConverter : BaseActivity(), FileSelectCallback, View.OnClickListener mProfilename = findViewById<View>(R.id.profilename) as EditText mProfilenameLabel = findViewById<View>(R.id.profilename_label) as TextView + mCompatmode = findViewById(R.id.compatmode) as Spinner + mCompatmodeLabel = findViewById(R.id.compatmode_label) as TextView + + if (savedInstanceState != null && savedInstanceState.containsKey(VPNPROFILE)) { mResult = savedInstanceState.getSerializable(VPNPROFILE) as VpnProfile? mAliasName = savedInstanceState.getString("mAliasName") mEmbeddedPwFile = savedInstanceState.getString("pwfile") mSourceUri = savedInstanceState.getParcelable("mSourceUri") mProfilename.setText(mResult!!.mName) + mCompatmode.setSelection(Utils.mapCompatVer(mResult!!.mCompatMode)) if (savedInstanceState.containsKey("logentries")) { @@ -714,6 +723,10 @@ class ConfigConverter : BaseActivity(), FileSelectCallback, View.OnClickListener mProfilenameLabel.visibility = View.VISIBLE mProfilename.setText(mResult!!.name) + mCompatmode.visibility = View.VISIBLE + mCompatmodeLabel.visibility = View.VISIBLE + mCompatmode.setSelection(Utils.mapCompatVer(mResult!!.mCompatMode)) + log(R.string.import_done) } } diff --git a/main/src/ui/java/de/blinkt/openvpn/fragments/Settings_Basic.java b/main/src/ui/java/de/blinkt/openvpn/fragments/Settings_Basic.java index 0afb754d..0899dd13 100644 --- a/main/src/ui/java/de/blinkt/openvpn/fragments/Settings_Basic.java +++ b/main/src/ui/java/de/blinkt/openvpn/fragments/Settings_Basic.java @@ -17,7 +17,6 @@ import android.widget.AdapterView.OnItemSelectedListener; import de.blinkt.openvpn.R; import de.blinkt.openvpn.R.id; import de.blinkt.openvpn.VpnProfile; -import de.blinkt.openvpn.core.ProfileManager; import de.blinkt.openvpn.views.FileSelectLayout; public class Settings_Basic extends KeyChainSettingsFragment implements OnItemSelectedListener, FileSelectLayout.FileSelectCallback, CompoundButton.OnCheckedChangeListener { @@ -28,6 +27,7 @@ public class Settings_Basic extends KeyChainSettingsFragment implements OnItemSe private FileSelectLayout mClientKey; private CheckBox mUseLzo; private Spinner mType; + private Spinner mCompatMode; private FileSelectLayout mpkcs12; private FileSelectLayout mCrlFile; private TextView mPKCS12Password; @@ -69,6 +69,7 @@ public class Settings_Basic extends KeyChainSettingsFragment implements OnItemSe mCrlFile = mView.findViewById(id.crlfile); mUseLzo = mView.findViewById(id.lzo); mType = mView.findViewById(id.type); + mCompatMode = mView.findViewById(id.compatmode); mPKCS12Password = mView.findViewById(id.pkcs12password); mEnablePeerFingerprint = mView.findViewById(id.enable_peer_fingerprint); mPeerFingerprints = mView.findViewById(id.peer_fingerprint); @@ -191,6 +192,7 @@ public class Settings_Basic extends KeyChainSettingsFragment implements OnItemSe mUseLzo.setChecked(mProfile.mUseLzo); mType.setSelection(mProfile.mAuthenticationType); + mCompatMode.setSelection(Utils.mapCompatVer(mProfile.mCompatMode)); mpkcs12.setData(mProfile.mPKCS12Filename, getActivity()); mPKCS12Password.setText(mProfile.mPKCS12Password); mUserName.setText(mProfile.mUsername); @@ -220,7 +222,7 @@ public class Settings_Basic extends KeyChainSettingsFragment implements OnItemSe mProfile.mAuthRetry = mAuthRetry.getSelectedItemPosition(); mProfile.mCheckPeerFingerprint = mEnablePeerFingerprint.isChecked(); mProfile.mPeerFingerPrints = mPeerFingerprints.getText().toString(); - + mProfile.mCompatMode = Utils.mapCompatMode(mCompatMode.getSelectedItemPosition()); } @Override diff --git a/main/src/ui/java/de/blinkt/openvpn/fragments/Utils.java b/main/src/ui/java/de/blinkt/openvpn/fragments/Utils.java deleted file mode 100644 index 3692624b..00000000 --- a/main/src/ui/java/de/blinkt/openvpn/fragments/Utils.java +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright (c) 2012-2016 Arne Schwabe - * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt - */ - -package de.blinkt.openvpn.fragments; - -import android.annotation.TargetApi; -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.database.Cursor; -import android.net.Uri; -import android.os.Build; -import android.provider.OpenableColumns; -import android.util.Base64; -import android.webkit.MimeTypeMap; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.List; -import java.util.TreeSet; -import java.util.Vector; - -import de.blinkt.openvpn.VpnProfile; -import de.blinkt.openvpn.core.Preferences; - -public class Utils { - - - @TargetApi(Build.VERSION_CODES.KITKAT) - public static Intent getFilePickerIntent(Context c, FileType fileType) { - Intent i = new Intent(Intent.ACTION_GET_CONTENT); - i.addCategory(Intent.CATEGORY_OPENABLE); - TreeSet<String> supportedMimeTypes = new TreeSet<String>(); - Vector<String> extensions = new Vector<>(); - - switch (fileType) { - case PKCS12: - i.setType("application/x-pkcs12"); - supportedMimeTypes.add("application/x-pkcs12"); - extensions.add("p12"); - extensions.add("pfx"); - break; - case CLIENT_CERTIFICATE: - case CA_CERTIFICATE: - i.setType("application/x-pem-file"); - supportedMimeTypes.add("application/x-x509-ca-cert"); - supportedMimeTypes.add("application/x-x509-user-cert"); - supportedMimeTypes.add("application/x-pem-file"); - supportedMimeTypes.add("application/pkix-cert"); - supportedMimeTypes.add("text/plain"); - - extensions.add("pem"); - extensions.add("crt"); - extensions.add("cer"); - break; - case KEYFILE: - i.setType("application/x-pem-file"); - supportedMimeTypes.add("application/x-pem-file"); - supportedMimeTypes.add("application/pkcs8"); - - // Google drive .... - supportedMimeTypes.add("application/x-iwork-keynote-sffkey"); - extensions.add("key"); - break; - - case TLS_AUTH_FILE: - i.setType("text/plain"); - - // Backup .... - supportedMimeTypes.add("application/pkcs8"); - // Google Drive is kind of crazy ..... - supportedMimeTypes.add("application/x-iwork-keynote-sffkey"); - - extensions.add("txt"); - extensions.add("key"); - break; - - case OVPN_CONFIG: - i.setType("application/x-openvpn-profile"); - supportedMimeTypes.add("application/x-openvpn-profile"); - supportedMimeTypes.add("application/openvpn-profile"); - supportedMimeTypes.add("application/ovpn"); - supportedMimeTypes.add("text/plain"); - extensions.add("ovpn"); - extensions.add("conf"); - break; - - case CRL_FILE: - supportedMimeTypes.add("application/x-pkcs7-crl"); - supportedMimeTypes.add("application/pkix-crl"); - extensions.add("crl"); - break; - - case USERPW_FILE: - i.setType("text/plain"); - supportedMimeTypes.add("text/plain"); - break; - } - - MimeTypeMap mtm = MimeTypeMap.getSingleton(); - - for (String ext : extensions) { - String mimeType = mtm.getMimeTypeFromExtension(ext); - if (mimeType != null) - supportedMimeTypes.add(mimeType); - } - - // Always add this as fallback - supportedMimeTypes.add("application/octet-stream"); - - i.putExtra(Intent.EXTRA_MIME_TYPES, supportedMimeTypes.toArray(new String[supportedMimeTypes.size()])); - - // People don't know that this is actually a system setting. Override it ... - // DocumentsContract.EXTRA_SHOW_ADVANCED is hidden - i.putExtra("android.content.extra.SHOW_ADVANCED", true); - - /* Samsung has decided to do something strange, on stock Android GET_CONTENT opens the document UI */ - /* fist try with documentsui */ - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N) - i.setPackage("com.android.documentsui"); - - - /* - * Android 11 is much stricter about allowing what to query. Since the app has the - * QUERY_ALL permission we can still check on Android 11 but otherwise we would just - * assume the documents ui to be always there: - */ - - /* - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - return i; - }*/ - - - - //noinspection ConstantConditions - if (!isIntentAvailable(c,i)) { - i.setAction(Intent.ACTION_OPEN_DOCUMENT); - i.setPackage(null); - - // Check for really broken devices ... :( - if (!isIntentAvailable(c,i)) { - return null; - } - } - - - /* - final PackageManager packageManager = c.getPackageManager(); - ResolveInfo list = packageManager.resolveActivity(i, 0); - - Toast.makeText(c, "Starting package: "+ list.activityInfo.packageName - + "with ACTION " + i.getAction(), Toast.LENGTH_LONG).show(); - - */ - return i; - } - - public static boolean alwaysUseOldFileChooser(Context c) - { - /* Android P does not allow access to the file storage anymore */ - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) - return false; - - SharedPreferences prefs = Preferences.getDefaultSharedPreferences(c); - return prefs.getBoolean("useInternalFileSelector", false); - } - - public static boolean isIntentAvailable(Context context, Intent i) { - final PackageManager packageManager = context.getPackageManager(); - List<ResolveInfo> list = - packageManager.queryIntentActivities(i, - PackageManager.MATCH_DEFAULT_ONLY); - - // Ignore the Android TV framework app in the list - int size = list.size(); - for (ResolveInfo ri: list) - { - // Ignore stub apps - if ("com.google.android.tv.frameworkpackagestubs".equals(ri.activityInfo.packageName)) - { - size--; - } - } - - return size > 0; - } - - - public enum FileType { - PKCS12(0), - CLIENT_CERTIFICATE(1), - CA_CERTIFICATE(2), - OVPN_CONFIG(3), - KEYFILE(4), - TLS_AUTH_FILE(5), - USERPW_FILE(6), - CRL_FILE(7); - - private int value; - - FileType(int i) { - value = i; - } - - public static FileType getFileTypeByValue(int value) { - switch (value) { - case 0: - return PKCS12; - case 1: - return CLIENT_CERTIFICATE; - case 2: - return CA_CERTIFICATE; - case 3: - return OVPN_CONFIG; - case 4: - return KEYFILE; - case 5: - return TLS_AUTH_FILE; - case 6: - return USERPW_FILE; - case 7: - return CRL_FILE; - default: - return null; - } - } - - public int getValue() { - return value; - } - } - - static private byte[] readBytesFromStream(InputStream input) throws IOException { - - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - - int nRead; - byte[] data = new byte[16384]; - - ; - - long totalread = 0; - while ((nRead = input.read(data, 0, data.length)) != -1 && totalread <VpnProfile.MAX_EMBED_FILE_SIZE ) { - buffer.write(data, 0, nRead); - totalread+=nRead; - } - - buffer.flush(); - input.close(); - return buffer.toByteArray(); - } - - public static String getFilePickerResult(FileType ft, Intent result, Context c) throws IOException, SecurityException { - - Uri uri = result.getData(); - if (uri == null) - return null; - - byte[] fileData = readBytesFromStream(c.getContentResolver().openInputStream(uri)); - String newData = null; - - Cursor cursor = c.getContentResolver().query(uri, null, null, null, null); - - String prefix = ""; - try { - if (cursor!=null && cursor.moveToFirst()) { - int cidx = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME); - if (cidx != -1) { - String displayName = cursor.getString(cidx); - - if (!displayName.contains(VpnProfile.INLINE_TAG) && !displayName.contains(VpnProfile.DISPLAYNAME_TAG)) - prefix = VpnProfile.DISPLAYNAME_TAG + displayName; - } - } - } finally { - if(cursor!=null) - cursor.close(); - } - - switch (ft) { - case PKCS12: - newData = Base64.encodeToString(fileData, Base64.DEFAULT); - break; - default: - newData = new String(fileData, "UTF-8"); - break; - } - - return prefix + VpnProfile.INLINE_TAG + newData; - } - -} diff --git a/main/src/ui/java/de/blinkt/openvpn/fragments/Utils.kt b/main/src/ui/java/de/blinkt/openvpn/fragments/Utils.kt new file mode 100644 index 00000000..64a8d3ba --- /dev/null +++ b/main/src/ui/java/de/blinkt/openvpn/fragments/Utils.kt @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2012-2016 Arne Schwabe + * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt + */ +package de.blinkt.openvpn.fragments + +import android.annotation.TargetApi +import android.content.Context +import android.content.Intent +import android.content.pm.PackageManager +import android.os.Build +import android.provider.OpenableColumns +import android.util.Base64 +import android.webkit.MimeTypeMap +import kotlin.Throws +import de.blinkt.openvpn.VpnProfile +import de.blinkt.openvpn.core.Preferences +import java.io.ByteArrayOutputStream +import java.io.IOException +import java.io.InputStream +import java.nio.charset.Charset +import java.util.* + +object Utils { + @JvmStatic + @TargetApi(Build.VERSION_CODES.KITKAT) + fun getFilePickerIntent(c: Context, fileType: FileType?): Intent? { + val i = Intent(Intent.ACTION_GET_CONTENT) + i.addCategory(Intent.CATEGORY_OPENABLE) + val supportedMimeTypes = TreeSet<String>() + val extensions = Vector<String>() + when (fileType) { + FileType.PKCS12 -> { + i.type = "application/x-pkcs12" + supportedMimeTypes.add("application/x-pkcs12") + extensions.add("p12") + extensions.add("pfx") + } + FileType.CLIENT_CERTIFICATE, FileType.CA_CERTIFICATE -> { + i.type = "application/x-pem-file" + supportedMimeTypes.add("application/x-x509-ca-cert") + supportedMimeTypes.add("application/x-x509-user-cert") + supportedMimeTypes.add("application/x-pem-file") + supportedMimeTypes.add("application/pkix-cert") + supportedMimeTypes.add("text/plain") + extensions.add("pem") + extensions.add("crt") + extensions.add("cer") + } + FileType.KEYFILE -> { + i.type = "application/x-pem-file" + supportedMimeTypes.add("application/x-pem-file") + supportedMimeTypes.add("application/pkcs8") + + // Google drive .... + supportedMimeTypes.add("application/x-iwork-keynote-sffkey") + extensions.add("key") + } + FileType.TLS_AUTH_FILE -> { + i.type = "text/plain" + + // Backup .... + supportedMimeTypes.add("application/pkcs8") + // Google Drive is kind of crazy ..... + supportedMimeTypes.add("application/x-iwork-keynote-sffkey") + extensions.add("txt") + extensions.add("key") + } + FileType.OVPN_CONFIG -> { + i.type = "application/x-openvpn-profile" + supportedMimeTypes.add("application/x-openvpn-profile") + supportedMimeTypes.add("application/openvpn-profile") + supportedMimeTypes.add("application/ovpn") + supportedMimeTypes.add("text/plain") + extensions.add("ovpn") + extensions.add("conf") + } + FileType.CRL_FILE -> { + supportedMimeTypes.add("application/x-pkcs7-crl") + supportedMimeTypes.add("application/pkix-crl") + extensions.add("crl") + } + FileType.USERPW_FILE -> { + i.type = "text/plain" + supportedMimeTypes.add("text/plain") + } + } + val mtm = MimeTypeMap.getSingleton() + for (ext in extensions) { + val mimeType = mtm.getMimeTypeFromExtension(ext) + if (mimeType != null) supportedMimeTypes.add(mimeType) + } + + // Always add this as fallback + supportedMimeTypes.add("application/octet-stream") + i.putExtra(Intent.EXTRA_MIME_TYPES, supportedMimeTypes.toTypedArray()) + + // People don't know that this is actually a system setting. Override it ... + // DocumentsContract.EXTRA_SHOW_ADVANCED is hidden + i.putExtra("android.content.extra.SHOW_ADVANCED", true) + + /* Samsung has decided to do something strange, on stock Android GET_CONTENT opens the document UI */ + /* fist try with documentsui */if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N) i.setPackage( + "com.android.documentsui" + ) + + + /* + * Android 11 is much stricter about allowing what to query. Since the app has the + * QUERY_ALL permission we can still check on Android 11 but otherwise we would just + * assume the documents ui to be always there: + */ + + /* + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + return i; + }*/if (!isIntentAvailable(c, i)) { + i.action = Intent.ACTION_OPEN_DOCUMENT + i.setPackage(null) + + // Check for really broken devices ... :( + if (!isIntentAvailable(c, i)) { + return null + } + } + + + /* + final PackageManager packageManager = c.getPackageManager(); + ResolveInfo list = packageManager.resolveActivity(i, 0); + + Toast.makeText(c, "Starting package: "+ list.activityInfo.packageName + + "with ACTION " + i.getAction(), Toast.LENGTH_LONG).show(); + + */return i + } + + @JvmStatic + fun alwaysUseOldFileChooser(c: Context?): Boolean { + /* Android P does not allow access to the file storage anymore */ + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) return false + val prefs = Preferences.getDefaultSharedPreferences(c) + return prefs.getBoolean("useInternalFileSelector", false) + } + + fun isIntentAvailable(context: Context, i: Intent?): Boolean { + val packageManager = context.packageManager + val list = packageManager.queryIntentActivities( + i!!, + PackageManager.MATCH_DEFAULT_ONLY + ) + + // Ignore the Android TV framework app in the list + var size = list.size + for (ri in list) { + // Ignore stub apps + if ("com.google.android.tv.frameworkpackagestubs" == ri.activityInfo.packageName) { + size-- + } + } + return size > 0 + } + + @Throws(IOException::class) + private fun readBytesFromStream(input: InputStream?): ByteArray { + val buffer = ByteArrayOutputStream() + var nRead: Int + val data = ByteArray(16384) + var totalread: Long = 0 + while (input!!.read(data, 0, data.size) + .also { nRead = it } != -1 && totalread < VpnProfile.MAX_EMBED_FILE_SIZE + ) { + buffer.write(data, 0, nRead) + totalread += nRead.toLong() + } + buffer.flush() + input.close() + return buffer.toByteArray() + } + + @JvmStatic + @Throws(IOException::class, SecurityException::class) + fun getFilePickerResult(ft: FileType?, result: Intent, c: Context): String? { + val uri = result.data ?: return null + val fileData = readBytesFromStream(c.contentResolver.openInputStream(uri)) + var newData: String? = null + val cursor = c.contentResolver.query(uri, null, null, null, null) + var prefix = "" + try { + if (cursor != null && cursor.moveToFirst()) { + val cidx = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME) + if (cidx != -1) { + val displayName = cursor.getString(cidx) + if (!displayName.contains(VpnProfile.INLINE_TAG) && !displayName.contains( + VpnProfile.DISPLAYNAME_TAG + ) + ) prefix = VpnProfile.DISPLAYNAME_TAG + displayName + } + } + } finally { + cursor?.close() + } + newData = when (ft) { + FileType.PKCS12 -> Base64.encodeToString( + fileData, + Base64.DEFAULT + ) + else -> String(fileData, Charset.forName("UTF-8")) + } + return prefix + VpnProfile.INLINE_TAG + newData + } + + enum class FileType(val value: Int) { + PKCS12(0), CLIENT_CERTIFICATE(1), CA_CERTIFICATE(2), OVPN_CONFIG(3), KEYFILE(4), TLS_AUTH_FILE( + 5 + ), + USERPW_FILE(6), CRL_FILE(7); + + companion object { + fun getFileTypeByValue(value: Int): FileType? { + return when (value) { + 0 -> PKCS12 + 1 -> CLIENT_CERTIFICATE + 2 -> CA_CERTIFICATE + 3 -> OVPN_CONFIG + 4 -> KEYFILE + 5 -> TLS_AUTH_FILE + 6 -> USERPW_FILE + 7 -> CRL_FILE + else -> null + } + } + } + } + + /* These functions make assumptions about the R.arrays.compat_mode contents */ + @JvmStatic + fun mapCompatVer(ver: Int): Int { + if (ver == 0 || ver >= 20600) + return 0 + else if (ver < 20400) + return 3 + else if (ver < 20500) + return 2 + else if (ver < 20600) + return 1 + return 0 + } + + @JvmStatic + + fun mapCompatMode(mode: Int): Int { + when (mode) { + 0 -> return 0 + 1 -> return 20500 + 2 -> return 20400 + 3 -> return 20300 + else -> return 0 + } + } +}
\ No newline at end of file |