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 @@ invocation of app_process (through android-emacs) can
|
|||
}
|
||||
}
|
||||
|
||||
/* 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
|
||||
checkContentUri (byte[] string, boolean readable, boolean writable)
|
||||
checkContentUri (String name, boolean readable, boolean writable)
|
||||
{
|
||||
String mode, name;
|
||||
String mode;
|
||||
ParcelFileDescriptor fd;
|
||||
Uri uri;
|
||||
int rc, flags;
|
||||
|
||||
/* Decode this into a URI. */
|
||||
uri = Uri.parse (name);
|
||||
flags = 0;
|
||||
|
||||
try
|
||||
{
|
||||
/* 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 (readable)
|
||||
flags |= Intent.FLAG_GRANT_READ_URI_PERMISSION;
|
||||
|
||||
if (writable)
|
||||
mode += "w";
|
||||
flags |= Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
|
||||
|
||||
try
|
||||
{
|
||||
fd = resolver.openFileDescriptor (Uri.parse (name), mode);
|
||||
fd.close ();
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
/* Fall through. */
|
||||
}
|
||||
|
||||
return false;
|
||||
rc = checkCallingUriPermission (uri, flags);
|
||||
return rc == PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
/* Build a content file name for URI.
|
||||
|
|
|
@ -1107,41 +1107,6 @@ android_get_content_name (const char *filename)
|
|||
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 */
|
||||
|
||||
/* 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",
|
||||
"([BZZZ)I");
|
||||
FIND_METHOD (check_content_uri, "checkContentUri",
|
||||
"([BZZ)Z");
|
||||
"(Ljava/lang/String;ZZ)Z");
|
||||
FIND_METHOD (query_battery, "queryBattery", "()[J");
|
||||
FIND_METHOD (update_extracted_text, "updateExtractedText",
|
||||
"(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'
|
||||
file name, or NULL if it is invalid for some reason. FILENAME
|
||||
should be relative to /content/by-authority, with no leading
|
||||
directory separator character.
|
||||
directory separator character. */
|
||||
|
||||
This function is not reentrant. */
|
||||
|
||||
static const char *
|
||||
static char *
|
||||
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
|
||||
authority name and a file name component. */
|
||||
|
@ -2784,48 +2783,53 @@ android_get_content_name (const char *filename)
|
|||
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;
|
||||
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 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
|
||||
android_check_content_access (const char *uri, int mode)
|
||||
{
|
||||
jobject string;
|
||||
size_t length;
|
||||
jboolean rc;
|
||||
jboolean rc, read, write;
|
||||
|
||||
length = strlen (uri);
|
||||
|
||||
string = (*android_java_env)->NewByteArray (android_java_env,
|
||||
length);
|
||||
string = (*android_java_env)->NewStringUTF (android_java_env, uri);
|
||||
android_exception_check ();
|
||||
|
||||
(*android_java_env)->SetByteArrayRegion (android_java_env,
|
||||
string, 0, length,
|
||||
(jbyte *) uri);
|
||||
/* Establish what is being checked. Checking for read access is
|
||||
identical to checking if the file exists. */
|
||||
|
||||
read = (bool) (mode & R_OK || (mode == F_OK));
|
||||
write = (bool) (mode & W_OK);
|
||||
|
||||
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));
|
||||
string, read, write);
|
||||
android_exception_check_1 (string);
|
||||
ANDROID_DELETE_LOCAL_REF (string);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -2889,7 +2893,7 @@ android_authority_name (struct android_vnode *vnode, char *name,
|
|||
size_t length)
|
||||
{
|
||||
struct android_authority_vnode *vp;
|
||||
const char *uri_name;
|
||||
char *uri_name;
|
||||
|
||||
if (!android_init_gui)
|
||||
{
|
||||
|
@ -2922,6 +2926,12 @@ android_authority_name (struct android_vnode *vnode, char *name,
|
|||
if (*name == '/')
|
||||
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);
|
||||
if (!uri_name)
|
||||
goto error;
|
||||
|
@ -2931,11 +2941,12 @@ android_authority_name (struct android_vnode *vnode, char *name,
|
|||
vp->vnode.ops = &authority_vfs_ops;
|
||||
vp->vnode.type = ANDROID_VNODE_CONTENT_AUTHORITY;
|
||||
vp->vnode.flags = 0;
|
||||
vp->uri = xstrdup (uri_name);
|
||||
vp->uri = uri_name;
|
||||
return &vp->vnode;
|
||||
}
|
||||
|
||||
/* Content files can't have children. */
|
||||
no_entry:
|
||||
errno = ENOENT;
|
||||
error:
|
||||
return NULL;
|
||||
|
|
Loading…
Add table
Reference in a new issue