Update Android port
* doc/emacs/android.texi (Android Document Providers): Improve wording of paragraph clarifying limits on subprocesses. * java/org/gnu/emacs/EmacsService.java (getDocumentTrees): Use Java standard US-ASCII coding standard instead of the undocumented ``ASCII'' alias. (decodeFileName): Remove unused function. (documentIdFromName): * src/android.c (android_init_emacs_service): Take a String for NAME instead of a byte array. * src/androidvfs.c (android_verify_jni_string): New function. (android_document_id_from_name): Verify that STRING is a valid Modified UTF-8 string.
This commit is contained in:
parent
4e754817b5
commit
de0e0939f0
4 changed files with 85 additions and 38 deletions
|
@ -298,11 +298,12 @@ subsequently made available within a new directory named
|
|||
a unique identifier assigned to the directory by the document
|
||||
provider.
|
||||
|
||||
Because these directories do not exist within the Unix file-system,
|
||||
sub-processes cannot be created within them, just as with the
|
||||
@file{/assets} directory (@pxref{Android File System}.) In addition,
|
||||
although Emacs can normally write and create files inside these
|
||||
directories, it cannot create symlinks or hard links.
|
||||
The same limitations applied to the @file{/assets} directory
|
||||
(@pxref{Android File System}) are applied when creating sub-processes
|
||||
within those directories, because they do not exist within the Unix
|
||||
file-system. In addition, although Emacs can normally write and
|
||||
create files inside these directories, it cannot create symlinks or
|
||||
hard links.
|
||||
|
||||
@c TODO: fix this!
|
||||
Since document providers are allowed to perform expensive network
|
||||
|
|
|
@ -1282,7 +1282,7 @@ else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
|
|||
|
||||
try
|
||||
{
|
||||
providerName = new String (provider, "ASCII");
|
||||
providerName = new String (provider, "US-ASCII");
|
||||
}
|
||||
catch (UnsupportedEncodingException exception)
|
||||
{
|
||||
|
@ -1306,24 +1306,6 @@ else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
|
|||
return treeList.toArray (new String[0]);
|
||||
}
|
||||
|
||||
/* Decode the specified STRING into a String object using the UTF-8
|
||||
format. If an exception is thrown, return null. */
|
||||
|
||||
private String
|
||||
decodeFileName (byte[] string)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new String (string, "UTF-8");
|
||||
}
|
||||
catch (Exception e) /* UnsupportedEncodingException, etc. */
|
||||
{
|
||||
;;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/* Find the document ID of the file within TREE_URI designated by
|
||||
NAME.
|
||||
|
||||
|
@ -1342,11 +1324,10 @@ else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
|
|||
If the designated file can't be located, return -1. */
|
||||
|
||||
private int
|
||||
documentIdFromName (String tree_uri, byte name[],
|
||||
String[] id_return)
|
||||
documentIdFromName (String tree_uri, String name, String[] id_return)
|
||||
{
|
||||
Uri uri, treeUri;
|
||||
String nameString, id, type;
|
||||
String id, type;
|
||||
String[] components, projection;
|
||||
Cursor cursor;
|
||||
int column;
|
||||
|
@ -1360,11 +1341,8 @@ else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
|
|||
/* Parse the URI identifying the tree first. */
|
||||
uri = Uri.parse (tree_uri);
|
||||
|
||||
/* Next, decode NAME. */
|
||||
nameString = decodeFileName (name);
|
||||
|
||||
/* Now, split NAME into its individual components. */
|
||||
components = nameString.split ("/");
|
||||
components = name.split ("/");
|
||||
|
||||
/* Set id and type to the value at the root of the tree. */
|
||||
type = id = null;
|
||||
|
@ -1462,7 +1440,7 @@ and the current document ID (belonging to the
|
|||
|
||||
try
|
||||
{
|
||||
nameString = cursor.getString (column);
|
||||
name = cursor.getString (column);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
|
@ -1473,7 +1451,7 @@ and the current document ID (belonging to the
|
|||
/* Break out of the loop only once a matching component is
|
||||
found. */
|
||||
|
||||
if (nameString.equals (component))
|
||||
if (name.equals (component))
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -1556,7 +1556,8 @@ android_init_emacs_service (void)
|
|||
FIND_METHOD (get_document_trees, "getDocumentTrees",
|
||||
"([B)[Ljava/lang/String;");
|
||||
FIND_METHOD (document_id_from_name, "documentIdFromName",
|
||||
"(Ljava/lang/String;[B[Ljava/lang/String;)I");
|
||||
"(Ljava/lang/String;Ljava/lang/String;"
|
||||
"[Ljava/lang/String;)I");
|
||||
FIND_METHOD (get_tree_uri, "getTreeUri",
|
||||
"(Ljava/lang/String;Ljava/lang/String;)"
|
||||
"Ljava/lang/String;");
|
||||
|
|
|
@ -3936,6 +3936,66 @@ static struct android_vops saf_new_vfs_ops;
|
|||
/* Chain of all open SAF directory streams. */
|
||||
static struct android_saf_tree_vdir *all_saf_tree_vdirs;
|
||||
|
||||
/* Verify that the specified NULL-terminated STRING is a valid JNI
|
||||
``UTF-8'' string. Return 0 if so, 1 otherwise.
|
||||
|
||||
The native coding system used by the JVM to store strings derives
|
||||
from UTF-8, but deviates from it in two aspects in an attempt to
|
||||
better represent the UCS-16 based Java String format, and to let
|
||||
strings contain NULL characters while remaining valid C strings:
|
||||
NULL bytes are encoded as two-byte sequences, and Unicode surrogate
|
||||
pairs encoded as two-byte sequences are prefered to four-byte
|
||||
sequences when encoding characters above the BMP. */
|
||||
|
||||
static int
|
||||
android_verify_jni_string (const char *name)
|
||||
{
|
||||
const unsigned char *chars;
|
||||
|
||||
chars = (unsigned char *) name;
|
||||
while (*chars)
|
||||
{
|
||||
/* Switch on the high 4 bits. */
|
||||
|
||||
switch (*chars++ >> 4)
|
||||
{
|
||||
case 0 ... 7:
|
||||
/* The 8th bit is clean, so this is a regular C
|
||||
character. */
|
||||
break;
|
||||
|
||||
case 8 ... 0xb:
|
||||
/* Invalid starting byte! */
|
||||
return 1;
|
||||
|
||||
case 0xf:
|
||||
/* The start of a four byte sequence. These aren't allowed
|
||||
in Java. */
|
||||
return 1;
|
||||
|
||||
case 0xe:
|
||||
/* The start of a three byte sequence. Verify that its
|
||||
continued. */
|
||||
|
||||
if ((*chars++ & 0xc0) != 0x80)
|
||||
return 1;
|
||||
|
||||
FALLTHROUGH;
|
||||
|
||||
case 0xc ... 0xd:
|
||||
/* The start of a two byte sequence. Verify that the
|
||||
next byte exists and has its high bit set. */
|
||||
|
||||
if ((*chars++ & 0xc0) != 0x80)
|
||||
return 1;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Find the document ID of the file within TREE_URI designated by
|
||||
NAME.
|
||||
|
||||
|
@ -3943,6 +4003,9 @@ static struct android_saf_tree_vdir *all_saf_tree_vdirs;
|
|||
individual files. Each constituent component prior to the last
|
||||
must name a directory file within TREE_URI.
|
||||
|
||||
If NAME is not correct for the Java ``modified UTF-8'' coding
|
||||
system, return -1.
|
||||
|
||||
Upon success, return 0 or 1 (contingent upon whether or not the
|
||||
last component within NAME is a directory) and place the document
|
||||
ID of the named file in ID.
|
||||
|
@ -3965,6 +4028,12 @@ android_document_id_from_name (const char *tree_uri, char *name,
|
|||
jmethodID method;
|
||||
const char *doc_id;
|
||||
|
||||
/* Verify the format of NAME. Don't allow creating files that
|
||||
contain characters that can't be encoded in Java. */
|
||||
|
||||
if (android_verify_jni_string (name))
|
||||
return -1;
|
||||
|
||||
/* First, create the array that will hold the result. */
|
||||
result = (*android_java_env)->NewObjectArray (android_java_env, 1,
|
||||
java_string_class,
|
||||
|
@ -3972,11 +4041,9 @@ android_document_id_from_name (const char *tree_uri, char *name,
|
|||
android_exception_check ();
|
||||
|
||||
/* Next, create the string for the tree URI and name. */
|
||||
length = strlen (name);
|
||||
java_name = (*android_java_env)->NewByteArray (android_java_env, length);
|
||||
java_name = (*android_java_env)->NewStringUTF (android_java_env,
|
||||
name);
|
||||
android_exception_check_1 (result);
|
||||
(*android_java_env)->SetByteArrayRegion (android_java_env, java_name,
|
||||
0, length, (jbyte *) name);
|
||||
uri = (*android_java_env)->NewStringUTF (android_java_env, tree_uri);
|
||||
android_exception_check_2 (result, java_name);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue