0
0
mirror of https://github.com/schwabe/ics-openvpn.git synced 2024-09-20 12:02:28 +02:00

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...
This commit is contained in:
Arne Schwabe 2016-02-18 13:58:10 +01:00
parent db5f46e1ce
commit 88fa7a63ce
2 changed files with 106 additions and 66 deletions

View File

@ -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,64 +627,7 @@ 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);
}
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;
}
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", "");
}
try {
InputStream is = getContentResolver().openInputStream(data);
doImport(is, possibleName);
} catch (NetworkOnMainThreadException nom) {
throw new RuntimeException("Network on Main: + " + data);
}
} catch (FileNotFoundException e) {
log(R.string.import_content_resolve_error);
} catch (SecurityException se) {
log(R.string.import_content_resolve_error + ":" + se.getLocalizedMessage());
}
}
doImportIntent(intent);
// We parsed the intent, relay on saved instance for restoring
setIntent(null);
@ -682,12 +636,89 @@ public class ConfigConverter extends BaseActivity implements FileSelectCallback,
}
private void doImportIntent(Intent intent) {
final Uri data = intent.getData();
if (data != null) {
mSourceUri = data;
doImportUri(data);
}
}
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);
}
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;
}
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", "");
}
try {
InputStream is = getContentResolver().openInputStream(data);
doImport(is, possibleName);
} catch (NetworkOnMainThreadException nom) {
throw new RuntimeException("Network on Main: + " + data);
}
} 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);
}
@Override
protected void onStart() {
super.onStart();
}
private void log(String logmessage) {

View File

@ -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(""))