mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-07 23:10:28 -08:00
Improve efficiency of checking for access to authority documents
* java/org/gnu/emacs/EmacsService.java (checkContentUri): Take a string instead of a byte array. Then, use checkCallingUriPermission, in lieu of opening the file. * src/android.c (android_check_content_access): Delete unused function. (android_init_emacs_service): Adjust for changes to checkContentUri's signature. * src/androidvfs.c (android_get_content_name): Return the file name in a new buffer. (android_check_content_access): Adjust correspondingly. (android_authority_name): Verify NAME is a valid JNI string.
This commit is contained in:
parent
3895f88233
commit
9fb00904f9
3 changed files with 51 additions and 89 deletions
|
|
@ -960,44 +960,30 @@ public final class EmacsService extends Service
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return whether Emacs is directly permitted to access the
|
||||||
|
content:// URI NAME. This is not a suitable test for files which
|
||||||
|
Emacs can access by virtue of their containing document
|
||||||
|
trees. */
|
||||||
|
|
||||||
public boolean
|
public boolean
|
||||||
checkContentUri (byte[] string, boolean readable, boolean writable)
|
checkContentUri (String name, boolean readable, boolean writable)
|
||||||
{
|
{
|
||||||
String mode, name;
|
String mode;
|
||||||
ParcelFileDescriptor fd;
|
ParcelFileDescriptor fd;
|
||||||
|
Uri uri;
|
||||||
|
int rc, flags;
|
||||||
|
|
||||||
/* Decode this into a URI. */
|
uri = Uri.parse (name);
|
||||||
|
flags = 0;
|
||||||
|
|
||||||
try
|
if (readable)
|
||||||
{
|
flags |= Intent.FLAG_GRANT_READ_URI_PERMISSION;
|
||||||
/* The usual file name encoding question rears its ugly head
|
|
||||||
again. */
|
|
||||||
name = new String (string, "UTF-8");
|
|
||||||
}
|
|
||||||
catch (UnsupportedEncodingException exception)
|
|
||||||
{
|
|
||||||
name = null;
|
|
||||||
throw new RuntimeException (exception);
|
|
||||||
}
|
|
||||||
|
|
||||||
mode = "r";
|
|
||||||
|
|
||||||
if (writable)
|
if (writable)
|
||||||
mode += "w";
|
flags |= Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
|
||||||
|
|
||||||
try
|
rc = checkCallingUriPermission (uri, flags);
|
||||||
{
|
return rc == PackageManager.PERMISSION_GRANTED;
|
||||||
fd = resolver.openFileDescriptor (Uri.parse (name), mode);
|
|
||||||
fd.close ();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (Exception exception)
|
|
||||||
{
|
|
||||||
/* Fall through. */
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Build a content file name for URI.
|
/* Build a content file name for URI.
|
||||||
|
|
|
||||||
|
|
@ -1107,41 +1107,6 @@ android_get_content_name (const char *filename)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return whether or not the specified FILENAME is an accessible
|
|
||||||
content URI. MODE specifies what to check. */
|
|
||||||
|
|
||||||
static bool
|
|
||||||
android_check_content_access (const char *filename, int mode)
|
|
||||||
{
|
|
||||||
const char *name;
|
|
||||||
jobject string;
|
|
||||||
size_t length;
|
|
||||||
jboolean rc;
|
|
||||||
|
|
||||||
name = android_get_content_name (filename);
|
|
||||||
length = strlen (name);
|
|
||||||
|
|
||||||
string = (*android_java_env)->NewByteArray (android_java_env,
|
|
||||||
length);
|
|
||||||
android_exception_check ();
|
|
||||||
|
|
||||||
(*android_java_env)->SetByteArrayRegion (android_java_env,
|
|
||||||
string, 0, length,
|
|
||||||
(jbyte *) name);
|
|
||||||
rc = (*android_java_env)->CallBooleanMethod (android_java_env,
|
|
||||||
emacs_service,
|
|
||||||
service_class.check_content_uri,
|
|
||||||
string,
|
|
||||||
(jboolean) ((mode & R_OK)
|
|
||||||
!= 0),
|
|
||||||
(jboolean) ((mode & W_OK)
|
|
||||||
!= 0));
|
|
||||||
android_exception_check_1 (string);
|
|
||||||
ANDROID_DELETE_LOCAL_REF (string);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* 0 */
|
#endif /* 0 */
|
||||||
|
|
||||||
/* Return the current user's ``home'' directory, which is actually the
|
/* Return the current user's ``home'' directory, which is actually the
|
||||||
|
|
@ -1549,7 +1514,7 @@ android_init_emacs_service (void)
|
||||||
FIND_METHOD (open_content_uri, "openContentUri",
|
FIND_METHOD (open_content_uri, "openContentUri",
|
||||||
"([BZZZ)I");
|
"([BZZZ)I");
|
||||||
FIND_METHOD (check_content_uri, "checkContentUri",
|
FIND_METHOD (check_content_uri, "checkContentUri",
|
||||||
"([BZZ)Z");
|
"(Ljava/lang/String;ZZ)Z");
|
||||||
FIND_METHOD (query_battery, "queryBattery", "()[J");
|
FIND_METHOD (query_battery, "queryBattery", "()[J");
|
||||||
FIND_METHOD (update_extracted_text, "updateExtractedText",
|
FIND_METHOD (update_extracted_text, "updateExtractedText",
|
||||||
"(Lorg/gnu/emacs/EmacsWindow;"
|
"(Lorg/gnu/emacs/EmacsWindow;"
|
||||||
|
|
|
||||||
|
|
@ -2765,14 +2765,13 @@ android_content_initial (char *name, size_t length)
|
||||||
/* Return the content URI corresponding to a `/content/by-authority'
|
/* Return the content URI corresponding to a `/content/by-authority'
|
||||||
file name, or NULL if it is invalid for some reason. FILENAME
|
file name, or NULL if it is invalid for some reason. FILENAME
|
||||||
should be relative to /content/by-authority, with no leading
|
should be relative to /content/by-authority, with no leading
|
||||||
directory separator character.
|
directory separator character. */
|
||||||
|
|
||||||
This function is not reentrant. */
|
static char *
|
||||||
|
|
||||||
static const char *
|
|
||||||
android_get_content_name (const char *filename)
|
android_get_content_name (const char *filename)
|
||||||
{
|
{
|
||||||
static char buffer[PATH_MAX + 1], *fill;
|
char *fill, *buffer;
|
||||||
|
size_t length;
|
||||||
|
|
||||||
/* Make sure FILENAME isn't obviously invalid: it must contain an
|
/* Make sure FILENAME isn't obviously invalid: it must contain an
|
||||||
authority name and a file name component. */
|
authority name and a file name component. */
|
||||||
|
|
@ -2784,48 +2783,53 @@ android_get_content_name (const char *filename)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FILENAME must also not be a directory. */
|
/* FILENAME must also not be a directory. Accessing content
|
||||||
|
provider directories is not supported by this interface. */
|
||||||
|
|
||||||
if (filename[strlen (filename)] == '/')
|
length = strlen (filename);
|
||||||
|
if (filename[length] == '/')
|
||||||
{
|
{
|
||||||
errno = ENOTDIR;
|
errno = ENOTDIR;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf (buffer, PATH_MAX + 1, "content://%s", filename);
|
/* Prefix FILENAME with content:// and return the buffer containing
|
||||||
|
that URI. */
|
||||||
|
|
||||||
|
buffer = xmalloc (sizeof "content://" + length);
|
||||||
|
sprintf (buffer, "content://%s", filename);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return whether or not the specified URI is an accessible content
|
/* Return whether or not the specified URI is an accessible content
|
||||||
URI. MODE specifies what to check. */
|
URI. MODE specifies what to check.
|
||||||
|
|
||||||
|
URI must be a string in the JVM's extended UTF-8 format. */
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
android_check_content_access (const char *uri, int mode)
|
android_check_content_access (const char *uri, int mode)
|
||||||
{
|
{
|
||||||
jobject string;
|
jobject string;
|
||||||
size_t length;
|
size_t length;
|
||||||
jboolean rc;
|
jboolean rc, read, write;
|
||||||
|
|
||||||
length = strlen (uri);
|
length = strlen (uri);
|
||||||
|
|
||||||
string = (*android_java_env)->NewByteArray (android_java_env,
|
string = (*android_java_env)->NewStringUTF (android_java_env, uri);
|
||||||
length);
|
|
||||||
android_exception_check ();
|
android_exception_check ();
|
||||||
|
|
||||||
(*android_java_env)->SetByteArrayRegion (android_java_env,
|
/* Establish what is being checked. Checking for read access is
|
||||||
string, 0, length,
|
identical to checking if the file exists. */
|
||||||
(jbyte *) uri);
|
|
||||||
|
read = (bool) (mode & R_OK || (mode == F_OK));
|
||||||
|
write = (bool) (mode & W_OK);
|
||||||
|
|
||||||
rc = (*android_java_env)->CallBooleanMethod (android_java_env,
|
rc = (*android_java_env)->CallBooleanMethod (android_java_env,
|
||||||
emacs_service,
|
emacs_service,
|
||||||
service_class.check_content_uri,
|
service_class.check_content_uri,
|
||||||
string,
|
string, read, write);
|
||||||
(jboolean) ((mode & R_OK)
|
|
||||||
!= 0),
|
|
||||||
(jboolean) ((mode & W_OK)
|
|
||||||
!= 0));
|
|
||||||
android_exception_check_1 (string);
|
android_exception_check_1 (string);
|
||||||
ANDROID_DELETE_LOCAL_REF (string);
|
ANDROID_DELETE_LOCAL_REF (string);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2889,7 +2893,7 @@ android_authority_name (struct android_vnode *vnode, char *name,
|
||||||
size_t length)
|
size_t length)
|
||||||
{
|
{
|
||||||
struct android_authority_vnode *vp;
|
struct android_authority_vnode *vp;
|
||||||
const char *uri_name;
|
char *uri_name;
|
||||||
|
|
||||||
if (!android_init_gui)
|
if (!android_init_gui)
|
||||||
{
|
{
|
||||||
|
|
@ -2922,6 +2926,12 @@ android_authority_name (struct android_vnode *vnode, char *name,
|
||||||
if (*name == '/')
|
if (*name == '/')
|
||||||
name++, length -= 1;
|
name++, length -= 1;
|
||||||
|
|
||||||
|
/* NAME must be a valid JNI string, so that it can be encoded
|
||||||
|
properly. */
|
||||||
|
|
||||||
|
if (android_verify_jni_string (name))
|
||||||
|
goto no_entry;
|
||||||
|
|
||||||
uri_name = android_get_content_name (name);
|
uri_name = android_get_content_name (name);
|
||||||
if (!uri_name)
|
if (!uri_name)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
@ -2931,11 +2941,12 @@ android_authority_name (struct android_vnode *vnode, char *name,
|
||||||
vp->vnode.ops = &authority_vfs_ops;
|
vp->vnode.ops = &authority_vfs_ops;
|
||||||
vp->vnode.type = ANDROID_VNODE_CONTENT_AUTHORITY;
|
vp->vnode.type = ANDROID_VNODE_CONTENT_AUTHORITY;
|
||||||
vp->vnode.flags = 0;
|
vp->vnode.flags = 0;
|
||||||
vp->uri = xstrdup (uri_name);
|
vp->uri = uri_name;
|
||||||
return &vp->vnode;
|
return &vp->vnode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Content files can't have children. */
|
/* Content files can't have children. */
|
||||||
|
no_entry:
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
error:
|
error:
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue