Update Android port
* doc/emacs/android.texi (Android File System): Describe how to access real files named /assets or /contents if so required. * java/org/gnu/emacs/EmacsService.java (validAuthority): * src/android.c (android_init_emacs_service): * src/android.h: New function. * src/androidvfs.c (android_saf_valid_authority_p): New function. Wrap the Java function. (android_saf_root_stat, android_saf_root_access): Don't return success if no authority by vp->authority's name exists. (android_saf_tree_from_name): Check validity of string data before giving it to JNI.
This commit is contained in:
parent
b022398b8f
commit
e41349dd93
5 changed files with 123 additions and 11 deletions
|
@ -219,6 +219,15 @@ containing files provided by external programs (@pxref{Android
|
|||
Document Providers}.)
|
||||
@end itemize
|
||||
|
||||
Despite ordinary installations of Android not having files within
|
||||
the (normally read-only) root directory named @file{content} or
|
||||
@file{assets}, you may want to access real files by these names if the
|
||||
Android installation in use has been customized. These files will
|
||||
conflict with the aformentioned special directories, but can
|
||||
nevertheless be accessed by writing their names relative to the
|
||||
``parent'' directory of the root directory, as so illustrated:
|
||||
@file{/../content}, @file{/../assets}.
|
||||
|
||||
The external storage directory is found at @file{/sdcard}. The
|
||||
other directories are not found at any fixed location (but see below),
|
||||
although the app data directory is typically symlinked to
|
||||
|
@ -268,10 +277,8 @@ System -> Apps -> Special App Access -> All files access -> Emacs
|
|||
|
||||
After you disable or enable this setting as appropriate and grant
|
||||
Emacs the ``Files and Media'' permission, it will be able to access
|
||||
files under @file{/sdcard} as usual.
|
||||
|
||||
These settings are not present on many proprietary versions of
|
||||
Android.
|
||||
files under @file{/sdcard} as usual. These settings are not present
|
||||
on some proprietary versions of Android.
|
||||
|
||||
@node Android Document Providers
|
||||
@section Accessing files from other programs under Android
|
||||
|
|
|
@ -1769,4 +1769,29 @@ In addition, arbitrary runtime exceptions (such as
|
|||
? DocumentsContract.getDocumentId (name)
|
||||
: null);
|
||||
}
|
||||
|
||||
/* Return if there is a content provider by the name of AUTHORITY
|
||||
supplying at least one tree URI Emacs retains persistent rights
|
||||
to access. */
|
||||
|
||||
public boolean
|
||||
validAuthority (String authority)
|
||||
{
|
||||
List<UriPermission> permissions;
|
||||
Uri uri;
|
||||
|
||||
permissions = resolver.getPersistedUriPermissions ();
|
||||
|
||||
for (UriPermission permission : permissions)
|
||||
{
|
||||
uri = permission.getUri ();
|
||||
|
||||
if (DocumentsContract.isTreeUri (uri)
|
||||
&& permission.isReadPermission ()
|
||||
&& uri.getAuthority ().equals (authority))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1592,6 +1592,8 @@ android_init_emacs_service (void)
|
|||
"(Ljava/lang/String;Ljava/lang/String;"
|
||||
"Ljava/lang/String;Ljava/lang/String;"
|
||||
"Ljava/lang/String;)Ljava/lang/String;");
|
||||
FIND_METHOD (valid_authority, "validAuthority",
|
||||
"(Ljava/lang/String;)Z");
|
||||
#undef FIND_METHOD
|
||||
}
|
||||
|
||||
|
|
|
@ -284,6 +284,7 @@ struct android_emacs_service
|
|||
jmethodID delete_document;
|
||||
jmethodID rename_document;
|
||||
jmethodID move_document;
|
||||
jmethodID valid_authority;
|
||||
};
|
||||
|
||||
extern JNIEnv *android_java_env;
|
||||
|
|
|
@ -3249,6 +3249,43 @@ static struct android_saf_root_vdir *all_saf_root_vdirs;
|
|||
static struct android_vnode *android_saf_tree_from_name (char *, const char *,
|
||||
const char *);
|
||||
|
||||
/* Forward declaration. */
|
||||
static int android_verify_jni_string (const char *);
|
||||
|
||||
/* Ascertain and return whether or not AUTHORITY designates a content
|
||||
provider offering at least one directory tree accessible to
|
||||
Emacs. */
|
||||
|
||||
static bool
|
||||
android_saf_valid_authority_p (const char *authority)
|
||||
{
|
||||
jobject string;
|
||||
jboolean valid;
|
||||
jmethodID method;
|
||||
|
||||
/* Make certain AUTHORITY can actually be represented as a Java
|
||||
string. */
|
||||
|
||||
if (android_verify_jni_string (authority))
|
||||
return false;
|
||||
|
||||
/* Build a string containing AUTHORITY. */
|
||||
|
||||
string = (*android_java_env)->NewStringUTF (android_java_env,
|
||||
authority);
|
||||
android_exception_check ();
|
||||
|
||||
method = service_class.valid_authority;
|
||||
valid
|
||||
= (*android_java_env)->CallNonvirtualBooleanMethod (android_java_env,
|
||||
emacs_service,
|
||||
service_class.class,
|
||||
method, string);
|
||||
android_exception_check_1 (string);
|
||||
ANDROID_DELETE_LOCAL_REF (string);
|
||||
return valid;
|
||||
}
|
||||
|
||||
static struct android_vnode *
|
||||
android_saf_root_name (struct android_vnode *vnode, char *name,
|
||||
size_t length)
|
||||
|
@ -3311,9 +3348,6 @@ android_saf_root_name (struct android_vnode *vnode, char *name,
|
|||
return android_saf_tree_from_name (component_end, component,
|
||||
vp->authority);
|
||||
|
||||
/* Otherwise, find the first component of NAME and create a vnode
|
||||
representing it as an authority. */
|
||||
|
||||
/* Create the vnode. */
|
||||
vp = xmalloc (sizeof *vp);
|
||||
vp->vnode.ops = &saf_root_vfs_ops;
|
||||
|
@ -3414,6 +3448,22 @@ static int
|
|||
android_saf_root_stat (struct android_vnode *vnode,
|
||||
struct stat *statb)
|
||||
{
|
||||
struct android_saf_root_vnode *vp;
|
||||
|
||||
/* Verify that the authority actually exists and return ENOENT
|
||||
otherwise, lest `locate-dominating-file' & co call an operation
|
||||
that doesn't require listing URIs under this authority, such as
|
||||
access. */
|
||||
|
||||
vp = (struct android_saf_root_vnode *) vnode;
|
||||
|
||||
if (vp->authority
|
||||
&& !android_saf_valid_authority_p (vp->authority))
|
||||
{
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Make up some imaginary statistics for this vnode. */
|
||||
|
||||
memset (statb, 0, sizeof *statb);
|
||||
|
@ -3428,6 +3478,8 @@ android_saf_root_stat (struct android_vnode *vnode,
|
|||
static int
|
||||
android_saf_root_access (struct android_vnode *vnode, int mode)
|
||||
{
|
||||
struct android_saf_root_vnode *vp;
|
||||
|
||||
/* Validate MODE. */
|
||||
|
||||
if (mode != F_OK && !(mode & (W_OK | X_OK | R_OK)))
|
||||
|
@ -3444,6 +3496,20 @@ android_saf_root_access (struct android_vnode *vnode, int mode)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* Verify that the authority actually exists and return ENOENT
|
||||
otherwise, lest `locate-dominating-file' & co call an operation
|
||||
that doesn't require listing URIs under this authority, such as
|
||||
access. */
|
||||
|
||||
vp = (struct android_saf_root_vnode *) vnode;
|
||||
|
||||
if (vp->authority
|
||||
&& !android_saf_valid_authority_p (vp->authority))
|
||||
{
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -5309,9 +5375,9 @@ android_saf_tree_opendir (struct android_vnode *vnode)
|
|||
AUTHORITY is the name of the content provider authority that is
|
||||
offering TREE.
|
||||
|
||||
Value is NULL if no document tree or provider by those names
|
||||
exists, or some other error takes place (for example, if TREE and
|
||||
AUTHORITY aren't encoded correctly.) */
|
||||
Value is NULL and errno is set if no document tree or provider by
|
||||
those names exists, or some other error takes place (for example,
|
||||
if TREE and AUTHORITY aren't encoded correctly.) */
|
||||
|
||||
static struct android_vnode *
|
||||
android_saf_tree_from_name (char *name, const char *tree,
|
||||
|
@ -5323,7 +5389,18 @@ android_saf_tree_from_name (char *name, const char *tree,
|
|||
const char *uri;
|
||||
struct android_vnode *vp;
|
||||
|
||||
/* Assume that TREE and NAME are in ``modified UTF-8 format''. */
|
||||
/* It's not a given that NAME and TREE are actually in the modified
|
||||
UTF-8 format used by the JVM to encode strings, and the JVM
|
||||
aborts when encountering a string that is not. Make sure they
|
||||
are valid before continuing. */
|
||||
|
||||
if (android_verify_jni_string (name)
|
||||
|| android_verify_jni_string (authority))
|
||||
{
|
||||
errno = ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tree_string = (*android_java_env)->NewStringUTF (android_java_env,
|
||||
tree);
|
||||
android_exception_check ();
|
||||
|
|
Loading…
Add table
Reference in a new issue