1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-13 06:50:39 -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:
Po Lu 2024-03-19 12:08:17 +08:00
parent ce29ae32d0
commit f2e239c6a7
5 changed files with 231 additions and 25 deletions

View file

@ -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 ();
}