mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-09 13:10:57 -08:00
Respect display names of Android content URIs
* java/org/gnu/emacs/EmacsNative.java (displayNameHash): New function. * java/org/gnu/emacs/EmacsService.java (buildContentName): New argument RESOLVER. Generate names holding URI's display name if available. All callers changed. * lisp/international/mule-cmds.el (set-default-coding-systems): Fix file name coding system as utf-8-unix on Android as on Mac OS. * src/androidvfs.c (enum android_vnode_type): New enum ANDROID_VNODE_CONTENT_AUTHORITY_NAMED. (android_content_name): Register root directories for this new type. (displayNameHash): New function. (android_get_content_name): New argument WITH_CHECKSUM. If present, treat the final two components as a pair of checksum and display name, and verify and exclude the two. (android_authority_name): Provide new argument as appropriate. (android_authority_initial_name): New function.
This commit is contained in:
parent
ce29ae32d0
commit
f2e239c6a7
5 changed files with 231 additions and 25 deletions
|
|
@ -281,7 +281,7 @@ public final class EmacsNative
|
|||
public static native int[] getSelection (short window);
|
||||
|
||||
|
||||
/* Graphics functions used as a replacement for potentially buggy
|
||||
/* Graphics functions used as replacements for potentially buggy
|
||||
Android APIs. */
|
||||
|
||||
public static native void blitRect (Bitmap src, Bitmap dest, int x1,
|
||||
|
|
@ -289,7 +289,6 @@ public final class EmacsNative
|
|||
|
||||
/* Increment the generation ID of the specified BITMAP, forcing its
|
||||
texture to be re-uploaded to the GPU. */
|
||||
|
||||
public static native void notifyPixelsChanged (Bitmap bitmap);
|
||||
|
||||
|
||||
|
|
@ -313,6 +312,13 @@ public final class EmacsNative
|
|||
in the process. */
|
||||
public static native boolean ftruncate (int fd);
|
||||
|
||||
|
||||
/* Functions that assist in generating content file names. */
|
||||
|
||||
/* Calculate an 8 digit checksum for the byte array DISPLAYNAME
|
||||
suitable for inclusion in a content file name. */
|
||||
public static native String displayNameHash (byte[] displayName);
|
||||
|
||||
static
|
||||
{
|
||||
/* Older versions of Android cannot link correctly with shared
|
||||
|
|
|
|||
|
|
@ -252,7 +252,7 @@ public final class EmacsOpenActivity extends Activity
|
|||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
|
||||
{
|
||||
content = EmacsService.buildContentName (uri);
|
||||
content = EmacsService.buildContentName (uri, getContentResolver ());
|
||||
return content;
|
||||
}
|
||||
|
||||
|
|
@ -423,6 +423,7 @@ public final class EmacsOpenActivity extends Activity
|
|||
/* Obtain the intent that started Emacs. */
|
||||
intent = getIntent ();
|
||||
action = intent.getAction ();
|
||||
resolver = getContentResolver ();
|
||||
|
||||
if (action == null)
|
||||
{
|
||||
|
|
@ -536,7 +537,7 @@ public final class EmacsOpenActivity extends Activity
|
|||
if ((scheme = uri.getScheme ()) != null
|
||||
&& scheme.equals ("content"))
|
||||
{
|
||||
tem1 = EmacsService.buildContentName (uri);
|
||||
tem1 = EmacsService.buildContentName (uri, resolver);
|
||||
attachmentString = ("'(\"" + (tem1.replace ("\\", "\\\\")
|
||||
.replace ("\"", "\\\"")
|
||||
.replace ("$", "\\$"))
|
||||
|
|
@ -568,7 +569,8 @@ public final class EmacsOpenActivity extends Activity
|
|||
&& (scheme = uri.getScheme ()) != null
|
||||
&& scheme.equals ("content"))
|
||||
{
|
||||
tem1 = EmacsService.buildContentName (uri);
|
||||
tem1
|
||||
= EmacsService.buildContentName (uri, resolver);
|
||||
builder.append ("\"");
|
||||
builder.append (tem1.replace ("\\", "\\\\")
|
||||
.replace ("\"", "\\\"")
|
||||
|
|
@ -609,7 +611,6 @@ public final class EmacsOpenActivity extends Activity
|
|||
underlying file, but it cannot be found without
|
||||
opening the file and doing readlink on its file
|
||||
descriptor in /proc/self/fd. */
|
||||
resolver = getContentResolver ();
|
||||
fd = null;
|
||||
|
||||
try
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ import android.os.VibrationEffect;
|
|||
|
||||
import android.provider.DocumentsContract;
|
||||
import android.provider.DocumentsContract.Document;
|
||||
import android.provider.OpenableColumns;
|
||||
import android.provider.Settings;
|
||||
|
||||
import android.util.Log;
|
||||
|
|
@ -1033,22 +1034,87 @@ public final class EmacsService extends Service
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Return a 8 character checksum for the string STRING, after encoding
|
||||
as UTF-8 data. */
|
||||
|
||||
public static String
|
||||
getDisplayNameHash (String string)
|
||||
{
|
||||
byte[] encoded;
|
||||
|
||||
try
|
||||
{
|
||||
encoded = string.getBytes ("UTF-8");
|
||||
return EmacsNative.displayNameHash (encoded);
|
||||
}
|
||||
catch (UnsupportedEncodingException exception)
|
||||
{
|
||||
/* This should be impossible. */
|
||||
return "error";
|
||||
}
|
||||
}
|
||||
|
||||
/* Build a content file name for URI.
|
||||
|
||||
Return a file name within the /contents/by-authority
|
||||
pseudo-directory that `android_get_content_name' can then
|
||||
transform back into an encoded URI.
|
||||
|
||||
If a display name can be requested from URI (using the resolver
|
||||
RESOLVER), append it to this file name.
|
||||
|
||||
A content name consists of any number of unencoded path segments
|
||||
separated by `/' characters, possibly followed by a question mark
|
||||
and an encoded query string. */
|
||||
|
||||
public static String
|
||||
buildContentName (Uri uri)
|
||||
buildContentName (Uri uri, ContentResolver resolver)
|
||||
{
|
||||
StringBuilder builder;
|
||||
String displayName;
|
||||
String[] projection;
|
||||
Cursor cursor;
|
||||
int column;
|
||||
|
||||
builder = new StringBuilder ("/content/by-authority/");
|
||||
displayName = null;
|
||||
cursor = null;
|
||||
|
||||
try
|
||||
{
|
||||
projection = new String[] { OpenableColumns.DISPLAY_NAME, };
|
||||
cursor = resolver.query (uri, projection, null, null, null);
|
||||
|
||||
if (cursor != null)
|
||||
{
|
||||
cursor.moveToFirst ();
|
||||
column
|
||||
= cursor.getColumnIndexOrThrow (OpenableColumns.DISPLAY_NAME);
|
||||
displayName
|
||||
= cursor.getString (column);
|
||||
|
||||
/* Verify that the display name is valid, i.e. it
|
||||
contains no characters unsuitable for a file name and
|
||||
is nonempty. */
|
||||
if (displayName.isEmpty () || displayName.contains ("/"))
|
||||
displayName = null;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
/* Ignored. */
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (cursor != null)
|
||||
cursor.close ();
|
||||
}
|
||||
|
||||
/* If a display name is available, at this point it should be the
|
||||
value of displayName. */
|
||||
|
||||
builder = new StringBuilder (displayName != null
|
||||
? "/content/by-authority-named/"
|
||||
: "/content/by-authority/");
|
||||
builder.append (uri.getAuthority ());
|
||||
|
||||
/* First, append each path segment. */
|
||||
|
|
@ -1065,6 +1131,16 @@ public final class EmacsService extends Service
|
|||
if (uri.getEncodedQuery () != null)
|
||||
builder.append ('?').append (uri.getEncodedQuery ());
|
||||
|
||||
/* Append the display name. */
|
||||
|
||||
if (displayName != null)
|
||||
{
|
||||
builder.append ('/');
|
||||
builder.append (getDisplayNameHash (displayName));
|
||||
builder.append ('/');
|
||||
builder.append (displayName);
|
||||
}
|
||||
|
||||
return builder.toString ();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue