mirror of https://github.com/termux/termux-app
Fixed: Fix termux-open failing to open files with "#" and remove hardcoded "content" and "file" strings
termux-open "/data/data/com.termux/files/home/te#st.sh"
This commit is contained in:
parent
d96883c4d6
commit
3e518a6a75
|
@ -2,6 +2,7 @@ package com.termux.app;
|
|||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
@ -15,6 +16,7 @@ import android.webkit.MimeTypeMap;
|
|||
|
||||
import com.termux.app.utils.PluginUtils;
|
||||
import com.termux.shared.data.IntentUtils;
|
||||
import com.termux.shared.data.UriUtils;
|
||||
import com.termux.shared.logger.Logger;
|
||||
import com.termux.shared.termux.TermuxConstants;
|
||||
|
||||
|
@ -37,8 +39,8 @@ public class TermuxOpenReceiver extends BroadcastReceiver {
|
|||
}
|
||||
|
||||
Logger.logVerbose(LOG_TAG, "Intent Received:\n" + IntentUtils.getIntentString(intent));
|
||||
Logger.logVerbose(LOG_TAG, "uri: \"" + data + "\", path: \"" + data.getPath() + "\", fragment: \"" + data.getFragment() + "\"");
|
||||
|
||||
final String filePath = data.getPath();
|
||||
final String contentTypeExtra = intent.getStringExtra("content-type");
|
||||
final boolean useChooser = intent.getBooleanExtra("chooser", false);
|
||||
final String intentAction = intent.getAction() == null ? Intent.ACTION_VIEW : intent.getAction();
|
||||
|
@ -52,8 +54,8 @@ public class TermuxOpenReceiver extends BroadcastReceiver {
|
|||
break;
|
||||
}
|
||||
|
||||
final boolean isExternalUrl = data.getScheme() != null && !data.getScheme().equals("file");
|
||||
if (isExternalUrl) {
|
||||
String scheme = data.getScheme();
|
||||
if (scheme != null && !ContentResolver.SCHEME_FILE.equals(scheme)) {
|
||||
Intent urlIntent = new Intent(intentAction, data);
|
||||
if (intentAction.equals(Intent.ACTION_SEND)) {
|
||||
urlIntent.putExtra(Intent.EXTRA_TEXT, data.toString());
|
||||
|
@ -70,6 +72,9 @@ public class TermuxOpenReceiver extends BroadcastReceiver {
|
|||
return;
|
||||
}
|
||||
|
||||
// Get full path including fragment (anything after last "#")
|
||||
String filePath = UriUtils.getUriFilePath(data);
|
||||
|
||||
final File fileToShare = new File(filePath);
|
||||
if (!(fileToShare.isFile() && fileToShare.canRead())) {
|
||||
Logger.logError(LOG_TAG, "termux-open: Not a readable file: '" + fileToShare.getAbsolutePath() + "'");
|
||||
|
@ -93,7 +98,8 @@ public class TermuxOpenReceiver extends BroadcastReceiver {
|
|||
contentTypeToUse = contentTypeExtra;
|
||||
}
|
||||
|
||||
Uri uriToShare = Uri.parse("content://" + TermuxConstants.TERMUX_FILE_SHARE_URI_AUTHORITY + fileToShare.getAbsolutePath());
|
||||
// Do not create Uri with Uri.parse() and use Uri.Builder().path(), check UriUtils.getUriFilePath().
|
||||
Uri uriToShare = UriUtils.getContentUri(TermuxConstants.TERMUX_FILE_SHARE_URI_AUTHORITY, fileToShare.getAbsolutePath());
|
||||
|
||||
if (Intent.ACTION_SEND.equals(intentAction)) {
|
||||
sendIntent.putExtra(Intent.EXTRA_STREAM, uriToShare);
|
||||
|
@ -184,8 +190,8 @@ public class TermuxOpenReceiver extends BroadcastReceiver {
|
|||
File file = new File(uri.getPath());
|
||||
try {
|
||||
String path = file.getCanonicalPath();
|
||||
String callingPackage = getCallingPackage();
|
||||
Logger.logDebug(LOG_TAG, "Open file request received from " + callingPackage + " for \"" + path + "\" with mode \"" + mode + "\"");
|
||||
String callingPackageName = getCallingPackage();
|
||||
Logger.logDebug(LOG_TAG, "Open file request received from " + callingPackageName + " for \"" + path + "\" with mode \"" + mode + "\"");
|
||||
String storagePath = Environment.getExternalStorageDirectory().getCanonicalPath();
|
||||
// See https://support.google.com/faqs/answer/7496913:
|
||||
if (!(path.startsWith(TermuxConstants.TERMUX_FILES_DIR_PATH) || path.startsWith(storagePath))) {
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
package com.termux.shared.data;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public class UriUtils {
|
||||
|
||||
/**
|
||||
* Get the full file path from a {@link Uri}.
|
||||
*
|
||||
* If the {@link Uri} was created from file path with {@link Uri#parse(String)}, like "am"
|
||||
* command "-d" option does, and the path contained a "#", then anything after it would become
|
||||
* the fragment and {@link Uri#getPath()} will only return the path before it, which would be
|
||||
* invalid. The fragment must be manually appended to the path to get the full path.
|
||||
*
|
||||
* If the {@link Uri} was created with {@link Uri.Builder} and path was set
|
||||
* with {@link Uri.Builder#path(String)}, then "#" will automatically be encoded to "%23"
|
||||
* and separate fragment will not exist.
|
||||
*
|
||||
* @param uri The {@link Uri} to get basename from.
|
||||
* @return Returns the file path if found, otherwise {@code null}.
|
||||
*/
|
||||
public static String getUriFilePath(Uri uri) {
|
||||
if (uri == null) return null;
|
||||
String path = uri.getPath();
|
||||
if (DataUtils.isNullOrEmpty(path)) return null;
|
||||
String fragment = uri.getFragment();
|
||||
return path + (DataUtils.isNullOrEmpty(fragment) ? "" : "#" + fragment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get {@link ContentResolver#SCHEME_FILE} {@link Uri} for path.
|
||||
*
|
||||
* @param path The path for the {@link Uri}.
|
||||
* @return Returns the {@link Uri}.
|
||||
*/
|
||||
public static Uri getFileUri(@NonNull String path) {
|
||||
return new Uri.Builder().scheme(ContentResolver.SCHEME_FILE).path(path).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get {@link ContentResolver#SCHEME_FILE} {@link Uri} for path.
|
||||
*
|
||||
* @param authority The authority for the {@link Uri}.
|
||||
* @param path The path for the {@link Uri}.
|
||||
* @return Returns the {@link Uri}.
|
||||
*/
|
||||
public static Uri getFileUri(@NonNull String authority, @NonNull String path) {
|
||||
return new Uri.Builder().scheme(ContentResolver.SCHEME_FILE).authority(authority).path(path).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get {@link ContentResolver#SCHEME_CONTENT} {@link Uri} for path.
|
||||
*
|
||||
* @param path The path for the {@link Uri}.
|
||||
* @return Returns the {@link Uri}.
|
||||
*/
|
||||
public static Uri getContentUri(@NonNull String path) {
|
||||
return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).path(path).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get {@link ContentResolver#SCHEME_CONTENT} {@link Uri} for path.
|
||||
*
|
||||
* @param authority The authority for the {@link Uri}.
|
||||
* @param path The path for the {@link Uri}.
|
||||
* @return Returns the {@link Uri}.
|
||||
*/
|
||||
public static Uri getContentUri(@NonNull String authority, @NonNull String path) {
|
||||
return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(authority).path(path).build();
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue