summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArne Schwabe <arne@rfc2549.org>2016-02-18 13:58:10 +0100
committerArne Schwabe <arne@rfc2549.org>2016-02-18 13:58:10 +0100
commit88fa7a63ceb27258676c0c5ab5ab4afdae00a461 (patch)
tree2d7ee47ec2984f5cda2fcbe8f7960c6e33908912
parentdb5f46e1ce191d1b8a635f5e62f63370753cf020 (diff)
Workaround broken file manager implementation in Android 6.0
In an ideal world, application developers would read the documentation and realize that the *calling* app needs to ensure that the target app can read the URI (e.g. by GRANT_PERMISSION) but ES file explorer (and from user report the internal file manager of cyanogenmod?!) call OpenVPN for Android with a file:// URI which OpenVPN for Android cannot read without SD card permission. Always to try request SD card permission on file:// urls...
-rw-r--r--main/src/main/java/de/blinkt/openvpn/activities/ConfigConverter.java145
-rw-r--r--main/src/main/java/de/blinkt/openvpn/activities/FileSelect.java11
2 files changed, 98 insertions, 58 deletions
diff --git a/main/src/main/java/de/blinkt/openvpn/activities/ConfigConverter.java b/main/src/main/java/de/blinkt/openvpn/activities/ConfigConverter.java
index 4f698008..d89b6291 100644
--- a/main/src/main/java/de/blinkt/openvpn/activities/ConfigConverter.java
+++ b/main/src/main/java/de/blinkt/openvpn/activities/ConfigConverter.java
@@ -15,6 +15,7 @@ import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
+import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
@@ -67,7 +68,8 @@ public class ConfigConverter extends BaseActivity implements FileSelectCallback,
private static final int RESULT_INSTALLPKCS12 = 7;
private static final int CHOOSE_FILE_OFFSET = 1000;
public static final String VPNPROFILE = "vpnProfile";
- private static final int PERMISSION_REQUEST = 37231;
+ private static final int PERMISSION_REQUEST_EMBED_FILES = 37231;
+ private static final int PERMISSION_REQUEST_READ_URL = PERMISSION_REQUEST_EMBED_FILES+1;
private VpnProfile mResult;
@@ -80,19 +82,20 @@ public class ConfigConverter extends BaseActivity implements FileSelectCallback,
private String mEmbeddedPwFile;
private Vector<String> mLogEntries = new Vector<>();
private String mCrlFileName;
+ private Uri mSourceUri;
@Override
public void onClick(View v) {
if (v.getId() == R.id.fab_save)
userActionSaveProfile();
if (v.getId() == R.id.permssion_hint && Build.VERSION.SDK_INT == Build.VERSION_CODES.M)
- doRequestSDCardPermission();
+ doRequestSDCardPermission(PERMISSION_REQUEST_EMBED_FILES);
}
@TargetApi(Build.VERSION_CODES.M)
- private void doRequestSDCardPermission() {
- requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, PERMISSION_REQUEST);
+ private void doRequestSDCardPermission(int requestCode) {
+ requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, requestCode);
}
@Override
@@ -108,8 +111,13 @@ public class ConfigConverter extends BaseActivity implements FileSelectCallback,
i++;
}
- if (requestCode == PERMISSION_REQUEST)
+ if (requestCode == PERMISSION_REQUEST_EMBED_FILES)
embedFiles(null);
+
+ else if (requestCode == PERMISSION_REQUEST_READ_URL) {
+ if(mSourceUri!=null)
+ doImportUri(mSourceUri);
+ }
}
@Override
@@ -163,6 +171,8 @@ public class ConfigConverter extends BaseActivity implements FileSelectCallback,
outState.putIntArray("fileselects", fileselects);
outState.putString("pwfile", mEmbeddedPwFile);
outState.putString("crlfile", mCrlFileName);
+
+ outState.putParcelable("mSourceUri", mSourceUri);
}
@Override
@@ -597,6 +607,7 @@ public class ConfigConverter extends BaseActivity implements FileSelectCallback,
mAliasName = savedInstanceState.getString("mAliasName");
mEmbeddedPwFile = savedInstanceState.getString("pwfile");
mCrlFileName = savedInstanceState.getString("crlfile");
+ mSourceUri = savedInstanceState.getParcelable("mSourceUri");
if (savedInstanceState.containsKey("logentries")) {
//noinspection ConstantConditions
@@ -616,69 +627,91 @@ public class ConfigConverter extends BaseActivity implements FileSelectCallback,
final android.content.Intent intent = getIntent();
if (intent != null) {
- final android.net.Uri data = intent.getData();
- if (data != null) {
- //log(R.string.import_experimental);
- log(R.string.importing_config, data.toString());
- try {
- String possibleName = null;
- if ((data.getScheme() != null && data.getScheme().equals("file")) ||
- (data.getLastPathSegment() != null &&
- (data.getLastPathSegment().endsWith(".ovpn") ||
- data.getLastPathSegment().endsWith(".conf")))
- ) {
- possibleName = data.getLastPathSegment();
- if (possibleName.lastIndexOf('/') != -1)
- possibleName = possibleName.substring(possibleName.lastIndexOf('/') + 1);
+ doImportIntent(intent);
- }
+ // We parsed the intent, relay on saved instance for restoring
+ setIntent(null);
+ }
- mPathsegments = data.getPathSegments();
- Cursor cursor = null;
- cursor = getContentResolver().query(data, null, null, null, null);
+ }
- try {
+ private void doImportIntent(Intent intent) {
+ final Uri data = intent.getData();
+ if (data != null) {
+ mSourceUri = data;
+ doImportUri(data);
+ }
+ }
- if (cursor != null && cursor.moveToFirst()) {
- int columnIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
+ private void doImportUri(Uri data) {
+ //log(R.string.import_experimental);
+ log(R.string.importing_config, data.toString());
+ try {
+ String possibleName = null;
+ if ((data.getScheme() != null && data.getScheme().equals("file")) ||
+ (data.getLastPathSegment() != null &&
+ (data.getLastPathSegment().endsWith(".ovpn") ||
+ data.getLastPathSegment().endsWith(".conf")))
+ ) {
+ possibleName = data.getLastPathSegment();
+ if (possibleName.lastIndexOf('/') != -1)
+ possibleName = possibleName.substring(possibleName.lastIndexOf('/') + 1);
- if (columnIndex != -1) {
- String displayName = cursor.getString(columnIndex);
- if (displayName != null)
- possibleName = displayName;
- }
- columnIndex = cursor.getColumnIndex("mime_type");
- if (columnIndex != -1) {
- log("Opening Mime TYPE: " + cursor.getString(columnIndex));
- }
- }
- } finally {
- if (cursor != null)
- cursor.close();
- }
- if (possibleName != null) {
- possibleName = possibleName.replace(".ovpn", "");
- possibleName = possibleName.replace(".conf", "");
+ }
+
+ mPathsegments = data.getPathSegments();
+
+ Cursor cursor = null;
+ cursor = getContentResolver().query(data, null, null, null, null);
+
+ try {
+
+ if (cursor != null && cursor.moveToFirst()) {
+ int columnIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
+
+ if (columnIndex != -1) {
+ String displayName = cursor.getString(columnIndex);
+ if (displayName != null)
+ possibleName = displayName;
}
- try {
- InputStream is = getContentResolver().openInputStream(data);
- doImport(is, possibleName);
- } catch (NetworkOnMainThreadException nom) {
- throw new RuntimeException("Network on Main: + " + data);
+ columnIndex = cursor.getColumnIndex("mime_type");
+ if (columnIndex != -1) {
+ log("Opening Mime TYPE: " + cursor.getString(columnIndex));
}
-
- } catch (FileNotFoundException e) {
- log(R.string.import_content_resolve_error);
- } catch (SecurityException se) {
- log(R.string.import_content_resolve_error + ":" + se.getLocalizedMessage());
}
+ } finally {
+ if (cursor != null)
+ cursor.close();
+ }
+ if (possibleName != null) {
+ possibleName = possibleName.replace(".ovpn", "");
+ possibleName = possibleName.replace(".conf", "");
+ }
+ try {
+ InputStream is = getContentResolver().openInputStream(data);
+ doImport(is, possibleName);
+ } catch (NetworkOnMainThreadException nom) {
+ throw new RuntimeException("Network on Main: + " + data);
}
- // We parsed the intent, relay on saved instance for restoring
- setIntent(null);
+ } catch (FileNotFoundException | SecurityException se) {
+ log(R.string.import_content_resolve_error + ":" + se.getLocalizedMessage());
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
+ checkMarschmallowFileImportError(data);
}
+ }
+ @TargetApi(Build.VERSION_CODES.M)
+ private void checkMarschmallowFileImportError(Uri data) {
+ // Permission already granted, not the source of the error
+ if(checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)
+ return;
+
+ // We got a file:/// URL and have no permission to read it. Technically an error of the calling app since
+ // it makes an assumption about other apps being able to read the url but well ...
+ if (data !=null && "file".equals(data.getScheme()))
+ doRequestSDCardPermission(PERMISSION_REQUEST_READ_URL);
}
@@ -686,8 +719,6 @@ public class ConfigConverter extends BaseActivity implements FileSelectCallback,
@Override
protected void onStart() {
super.onStart();
-
-
}
private void log(String logmessage) {
diff --git a/main/src/main/java/de/blinkt/openvpn/activities/FileSelect.java b/main/src/main/java/de/blinkt/openvpn/activities/FileSelect.java
index a3301399..b0b94e66 100644
--- a/main/src/main/java/de/blinkt/openvpn/activities/FileSelect.java
+++ b/main/src/main/java/de/blinkt/openvpn/activities/FileSelect.java
@@ -27,6 +27,7 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.util.Base64;
+import android.widget.Toast;
import de.blinkt.openvpn.R;
import de.blinkt.openvpn.VpnProfile;
@@ -100,10 +101,18 @@ public class FileSelect extends BaseActivity {
private void checkPermission() {
if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, PERMISSION_REQUEST);
-
}
}
+ @Override
+ public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+
+ if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
+ setResult(RESULT_CANCELED);
+ finish();
+ }
+ }
public boolean showClear() {
if(mData == null || mData.equals(""))