]> git.eshelyaron.com Git - emacs.git/commitdiff
Update Android port
authorPo Lu <luangruo@yahoo.com>
Thu, 27 Jul 2023 13:59:58 +0000 (21:59 +0800)
committerPo Lu <luangruo@yahoo.com>
Thu, 27 Jul 2023 13:59:58 +0000 (21:59 +0800)
* 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.

doc/emacs/android.texi
java/org/gnu/emacs/EmacsService.java
src/android.c
src/androidvfs.c

index 1f32fdfc1d2a24460d52811968e0087a09c25d0a..b86c71cea49ae92b97ceb395646948ff7ecdd0b2 100644 (file)
@@ -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
index 6059439551f4243c29cfb3196720f870639f8e1c..bc62e050345f1e991150c934d3779a67481315c0 100644 (file)
@@ -1282,7 +1282,7 @@ public final class EmacsService extends Service
 
     try
       {
-       providerName = new String (provider, "ASCII");
+       providerName = new String (provider, "US-ASCII");
       }
     catch (UnsupportedEncodingException exception)
       {
@@ -1306,24 +1306,6 @@ public final class EmacsService extends Service
     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 @@ public final class EmacsService extends Service
      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 @@ public final class EmacsService extends Service
     /* 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 @@ public final class EmacsService extends Service
 
            try
              {
-               nameString = cursor.getString (column);
+               name = cursor.getString (column);
              }
            catch (Exception exception)
              {
@@ -1473,7 +1451,7 @@ public final class EmacsService extends Service
            /* Break out of the loop only once a matching component is
               found.  */
 
-           if (nameString.equals (component))
+           if (name.equals (component))
              break;
          }
 
index d8b264a849111c6ac2e138577c364c78a8bc7a65..098fa6c383d9b3ce8d4c817884907d49ed88f517 100644 (file)
@@ -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;");
index bab3977ed5ac8a5750f3a79dfb9ba393be30dd21..c174c35f02bcef95da6ad690ddf6422d53873ef9 100644 (file)
@@ -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);