aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJorge Ruesga <jorge@ruesga.com>2013-03-22 01:07:01 +0100
committerJorge Ruesga <jorge@ruesga.com>2013-03-22 01:07:01 +0100
commite9c9b1b5bd0c17a239eb5d8c10a4f5f8ce33a611 (patch)
treeaf04a9b66b2db37cfbda29748dcfe5099963b32d /src
parentf2803c7506e37cdac33c8a0b6b4adf7994212a34 (diff)
downloadandroid_packages_apps_CMFileManager-e9c9b1b5bd0c17a239eb5d8c10a4f5f8ce33a611.tar.gz
android_packages_apps_CMFileManager-e9c9b1b5bd0c17a239eb5d8c10a4f5f8ce33a611.tar.bz2
android_packages_apps_CMFileManager-e9c9b1b5bd0c17a239eb5d8c10a4f5f8ce33a611.zip
CMFM: Ask to gain privileges for asynchronous commands
Change-Id: I35c48174e2e6093ada8e45786fe9320193effb96 Signed-off-by: Jorge Ruesga <jorge@ruesga.com>
Diffstat (limited to 'src')
-rw-r--r--src/com/cyanogenmod/filemanager/activities/EditorActivity.java140
-rw-r--r--src/com/cyanogenmod/filemanager/activities/NavigationActivity.java2
-rw-r--r--src/com/cyanogenmod/filemanager/activities/ShortcutActivity.java2
-rw-r--r--src/com/cyanogenmod/filemanager/console/RelaunchableException.java12
-rw-r--r--src/com/cyanogenmod/filemanager/console/java/JavaConsole.java14
-rw-r--r--src/com/cyanogenmod/filemanager/ui/policy/InfoActionPolicy.java37
-rw-r--r--src/com/cyanogenmod/filemanager/util/FileHelper.java192
7 files changed, 293 insertions, 106 deletions
diff --git a/src/com/cyanogenmod/filemanager/activities/EditorActivity.java b/src/com/cyanogenmod/filemanager/activities/EditorActivity.java
index df5751e1..21267bec 100644
--- a/src/com/cyanogenmod/filemanager/activities/EditorActivity.java
+++ b/src/com/cyanogenmod/filemanager/activities/EditorActivity.java
@@ -47,7 +47,6 @@ import android.widget.TextView;
import android.widget.TextView.BufferType;
import android.widget.Toast;
-import com.cyanogenmod.filemanager.FileManagerApplication;
import com.cyanogenmod.filemanager.R;
import com.cyanogenmod.filemanager.activities.preferences.SettingsPreferences;
import com.cyanogenmod.filemanager.activities.preferences.SettingsPreferences.EditorPreferenceFragment;
@@ -56,10 +55,7 @@ import com.cyanogenmod.filemanager.adapters.SimpleMenuListAdapter;
import com.cyanogenmod.filemanager.commands.AsyncResultListener;
import com.cyanogenmod.filemanager.commands.WriteExecutable;
import com.cyanogenmod.filemanager.console.ConsoleBuilder;
-import com.cyanogenmod.filemanager.console.InsufficientPermissionsException;
-import com.cyanogenmod.filemanager.console.RelaunchableException;
import com.cyanogenmod.filemanager.model.FileSystemObject;
-import com.cyanogenmod.filemanager.preferences.AccessMode;
import com.cyanogenmod.filemanager.preferences.FileManagerSettings;
import com.cyanogenmod.filemanager.preferences.Preferences;
import com.cyanogenmod.filemanager.ui.ThemeManager;
@@ -69,6 +65,8 @@ import com.cyanogenmod.filemanager.util.AndroidHelper;
import com.cyanogenmod.filemanager.util.CommandHelper;
import com.cyanogenmod.filemanager.util.DialogHelper;
import com.cyanogenmod.filemanager.util.ExceptionUtil;
+import com.cyanogenmod.filemanager.util.ExceptionUtil.OnRelaunchCommandResult;
+import com.cyanogenmod.filemanager.util.FileHelper;
import java.io.ByteArrayInputStream;
import java.io.File;
@@ -547,7 +545,7 @@ public class EditorActivity extends Activity implements TextWatcher {
switch (view.getId()) {
case R.id.ab_button1:
// Save the file
- writeFile();
+ checkAndWrite();
break;
case R.id.ab_button2:
@@ -565,7 +563,7 @@ public class EditorActivity extends Activity implements TextWatcher {
*/
private boolean initializeConsole() {
try {
- ConsoleBuilder.createDefaultConsole(this);
+ ConsoleBuilder.getConsole(this);
// There is a console allocated. Use it.
return true;
} catch (Throwable _throw) {
@@ -609,7 +607,7 @@ public class EditorActivity extends Activity implements TextWatcher {
File f = new File(path);
this.mTitle.setText(f.getName());
- // Check that we have access to the file (the real file, not the symlink)
+ // Check that the file exists (the real file, not the symlink)
try {
this.mFso = CommandHelper.getFileInfo(this, path, true, null);
if (this.mFso == null) {
@@ -631,8 +629,36 @@ public class EditorActivity extends Activity implements TextWatcher {
return;
}
- // Read the file in background
- asyncRead();
+ // Check that we have read access
+ try {
+ FileHelper.ensureReadAccess(
+ ConsoleBuilder.getConsole(this),
+ this.mFso,
+ null);
+
+ // Read the file in background
+ asyncRead();
+
+ } catch (Exception ex) {
+ ExceptionUtil.translateException(
+ this, ex, false, true, new OnRelaunchCommandResult() {
+ @Override
+ public void onSuccess() {
+ // Read the file in background
+ asyncRead();
+ }
+
+ @Override
+ public void onFailed(Throwable cause) {
+ finish();
+ }
+
+ @Override
+ public void onCancelled() {
+ finish();
+ }
+ });
+ }
}
/**
@@ -687,21 +713,6 @@ public class EditorActivity extends Activity implements TextWatcher {
// Check if the read was successfully
if (this.mReader.mCause != null) {
- // Check if we can't read the file because we don't the require
- // permissions. If we are in a ChRooted environment, resolve the
- // error without doing anymore
- if (this.mReader.mCause instanceof InsufficientPermissionsException) {
- if (!ConsoleBuilder.isPrivileged() &&
- FileManagerApplication.getAccessMode().
- compareTo(AccessMode.SAFE) != 0) {
- // We don't have a privileged console, we can't ask the user
- // to gain privileges and relauch the command again
- askGainAccessAndRead(
- (RelaunchableException)this.mReader.mCause);
- return Boolean.TRUE;
- }
- }
-
this.mCause = this.mReader.mCause;
return Boolean.FALSE;
}
@@ -778,10 +789,40 @@ public class EditorActivity extends Activity implements TextWatcher {
mReadTask.execute(this.mFso);
}
+ private void checkAndWrite() {
+ // Check that we have write access
+ try {
+ FileHelper.ensureWriteAccess(
+ ConsoleBuilder.getConsole(this),
+ this.mFso,
+ null);
+
+ // Write the file
+ syncWrite();
+
+ } catch (Exception ex) {
+ ExceptionUtil.translateException(
+ this, ex, false, true, new OnRelaunchCommandResult() {
+ @Override
+ public void onSuccess() {
+ // Write the file
+ syncWrite();
+ }
+
+ @Override
+ public void onFailed(Throwable cause) {/**NON BLOCK**/}
+
+ @Override
+ public void onCancelled() {/**NON BLOCK**/}
+ });
+ }
+ }
+
/**
- * Method that reads the requested file.
+ * Method that write the file.
+ * @hide
*/
- private void writeFile() {
+ void syncWrite() {
try {
// Configure the writer
AsyncWriter writer = new AsyncWriter();
@@ -846,53 +887,6 @@ public class EditorActivity extends Activity implements TextWatcher {
}
/**
- * Method that asks the user for gain access and reexecute the read command
- *
- * @param cause The cause of the reexecution
- * @hide
- */
- void askGainAccessAndRead(final RelaunchableException cause) {
- // We cannot use the ExceptionUtil class because the read command is asynchronous
- // and doesn't have the common mechanism of capture exception. we do our self one.
-
- //Create a yes/no dialog and ask the user
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- AlertDialog alert = DialogHelper.createYesNoDialog(
- EditorActivity.this,
- R.string.confirm_operation,
- cause.getQuestionResourceId(),
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- if (which == DialogInterface.BUTTON_POSITIVE) {
- // Change to privileged console
- if (!ConsoleBuilder.
- changeToPrivilegedConsole(EditorActivity.this)) {
-
- // Capture the exception
- ExceptionUtil.translateException(
- EditorActivity.this,
- cause);
- EditorActivity.this.mEditor.setEnabled(false);
- return;
- }
-
- //Read the file again
- asyncRead();
- } else {
- // Finish the application
- EditorActivity.this.finish();
- }
- }
- });
- DialogHelper.delegateDialogShow(EditorActivity.this, alert);
- }
- });
- }
-
- /**
* {@inheritDoc}
*/
@Override
diff --git a/src/com/cyanogenmod/filemanager/activities/NavigationActivity.java b/src/com/cyanogenmod/filemanager/activities/NavigationActivity.java
index cac8503e..2f491df7 100644
--- a/src/com/cyanogenmod/filemanager/activities/NavigationActivity.java
+++ b/src/com/cyanogenmod/filemanager/activities/NavigationActivity.java
@@ -576,7 +576,7 @@ public class NavigationActivity extends Activity
public void run() {
//Create the default console (from the preferences)
try {
- Console console = ConsoleBuilder.createDefaultConsole(NavigationActivity.this);
+ Console console = ConsoleBuilder.getConsole(NavigationActivity.this);
if (console == null) {
throw new ConsoleAllocException("console == null"); //$NON-NLS-1$
}
diff --git a/src/com/cyanogenmod/filemanager/activities/ShortcutActivity.java b/src/com/cyanogenmod/filemanager/activities/ShortcutActivity.java
index 8c5a6674..d61b10b0 100644
--- a/src/com/cyanogenmod/filemanager/activities/ShortcutActivity.java
+++ b/src/com/cyanogenmod/filemanager/activities/ShortcutActivity.java
@@ -200,7 +200,7 @@ public class ShortcutActivity extends Activity implements OnCancelListener, OnDi
*/
private boolean initializeConsole() {
try {
- ConsoleBuilder.createDefaultConsole(this);
+ ConsoleBuilder.getConsole(this);
// There is a console allocated. Use it.
return true;
} catch (Throwable _throw) {
diff --git a/src/com/cyanogenmod/filemanager/console/RelaunchableException.java b/src/com/cyanogenmod/filemanager/console/RelaunchableException.java
index db5ece7b..9bb0e10a 100644
--- a/src/com/cyanogenmod/filemanager/console/RelaunchableException.java
+++ b/src/com/cyanogenmod/filemanager/console/RelaunchableException.java
@@ -41,7 +41,9 @@ public abstract class RelaunchableException extends Exception {
public RelaunchableException(SyncResultExecutable executable) {
super();
this.mExecutables = new ArrayList<SyncResultExecutable>();
- addExecutable(executable);
+ if (executable != null) {
+ addExecutable(executable);
+ }
}
/**
@@ -53,7 +55,9 @@ public abstract class RelaunchableException extends Exception {
public RelaunchableException(String detailMessage, SyncResultExecutable executable) {
super(detailMessage);
this.mExecutables = new ArrayList<SyncResultExecutable>();
- addExecutable(executable);
+ if (executable != null) {
+ addExecutable(executable);
+ }
}
/**
@@ -67,7 +71,9 @@ public abstract class RelaunchableException extends Exception {
String detailMessage, Throwable throwable, SyncResultExecutable executable) {
super(detailMessage, throwable);
this.mExecutables = new ArrayList<SyncResultExecutable>();
- addExecutable(executable);
+ if (executable != null) {
+ addExecutable(executable);
+ }
}
/**
diff --git a/src/com/cyanogenmod/filemanager/console/java/JavaConsole.java b/src/com/cyanogenmod/filemanager/console/java/JavaConsole.java
index 2edb42a9..daf30525 100644
--- a/src/com/cyanogenmod/filemanager/console/java/JavaConsole.java
+++ b/src/com/cyanogenmod/filemanager/console/java/JavaConsole.java
@@ -17,6 +17,7 @@
package com.cyanogenmod.filemanager.console.java;
import android.content.Context;
+import android.os.Process;
import android.util.Log;
import com.cyanogenmod.filemanager.commands.Executable;
@@ -32,7 +33,13 @@ import com.cyanogenmod.filemanager.console.InsufficientPermissionsException;
import com.cyanogenmod.filemanager.console.NoSuchFileOrDirectory;
import com.cyanogenmod.filemanager.console.OperationTimeoutException;
import com.cyanogenmod.filemanager.console.ReadOnlyFilesystemException;
+import com.cyanogenmod.filemanager.model.AID;
+import com.cyanogenmod.filemanager.model.Group;
import com.cyanogenmod.filemanager.model.Identity;
+import com.cyanogenmod.filemanager.model.User;
+import com.cyanogenmod.filemanager.util.AIDHelper;
+
+import java.util.ArrayList;
/**
* An implementation of a {@link Console} based on a java implementation.<br/>
@@ -110,7 +117,12 @@ public final class JavaConsole extends Console {
*/
@Override
public Identity getIdentity() {
- return null;
+ AID aid = AIDHelper.getAID(Process.myUid());
+ if (aid == null) return null;
+ return new Identity(
+ new User(aid.getId(), aid.getName()),
+ new Group(aid.getId(), aid.getName()),
+ new ArrayList<Group>());
}
/**
diff --git a/src/com/cyanogenmod/filemanager/ui/policy/InfoActionPolicy.java b/src/com/cyanogenmod/filemanager/ui/policy/InfoActionPolicy.java
index d35eddb2..811c85f3 100644
--- a/src/com/cyanogenmod/filemanager/ui/policy/InfoActionPolicy.java
+++ b/src/com/cyanogenmod/filemanager/ui/policy/InfoActionPolicy.java
@@ -20,11 +20,15 @@ import android.content.Context;
import android.content.DialogInterface;
import android.widget.Toast;
+import com.cyanogenmod.filemanager.console.ConsoleBuilder;
import com.cyanogenmod.filemanager.listeners.OnRequestRefreshListener;
import com.cyanogenmod.filemanager.model.FileSystemObject;
import com.cyanogenmod.filemanager.ui.dialogs.ComputeChecksumDialog;
import com.cyanogenmod.filemanager.ui.dialogs.FsoPropertiesDialog;
import com.cyanogenmod.filemanager.util.DialogHelper;
+import com.cyanogenmod.filemanager.util.ExceptionUtil;
+import com.cyanogenmod.filemanager.util.ExceptionUtil.OnRelaunchCommandResult;
+import com.cyanogenmod.filemanager.util.FileHelper;
/**
* A class with the convenience methods for resolve the display of info actions
@@ -78,8 +82,33 @@ public final class InfoActionPolicy extends ActionsPolicy {
*/
public static void showComputeChecksumDialog(
final Context ctx, final FileSystemObject fso) {
- //Show a the filesystem info dialog
- final ComputeChecksumDialog dialog = new ComputeChecksumDialog(ctx, fso);
- dialog.show();
+ // Check that we have read access
+ try {
+ FileHelper.ensureReadAccess(
+ ConsoleBuilder.getConsole(ctx),
+ fso,
+ null);
+
+ //Show a the filesystem info dialog
+ final ComputeChecksumDialog dialog = new ComputeChecksumDialog(ctx, fso);
+ dialog.show();
+
+ } catch (Exception ex) {
+ ExceptionUtil.translateException(
+ ctx, ex, false, true, new OnRelaunchCommandResult() {
+ @Override
+ public void onSuccess() {
+ //Show a the filesystem info dialog
+ final ComputeChecksumDialog dialog = new ComputeChecksumDialog(ctx, fso);
+ dialog.show();
+ }
+
+ @Override
+ public void onFailed(Throwable cause) {/**NON BLOCK**/}
+
+ @Override
+ public void onCancelled() {/**NON BLOCK**/}
+ });
+ }
}
-} \ No newline at end of file
+}
diff --git a/src/com/cyanogenmod/filemanager/util/FileHelper.java b/src/com/cyanogenmod/filemanager/util/FileHelper.java
index eff18ced..d1515047 100644
--- a/src/com/cyanogenmod/filemanager/util/FileHelper.java
+++ b/src/com/cyanogenmod/filemanager/util/FileHelper.java
@@ -23,8 +23,11 @@ import android.util.Log;
import com.cyanogenmod.filemanager.FileManagerApplication;
import com.cyanogenmod.filemanager.R;
+import com.cyanogenmod.filemanager.commands.SyncResultExecutable;
import com.cyanogenmod.filemanager.commands.shell.ResolveLinkCommand;
+import com.cyanogenmod.filemanager.console.Console;
import com.cyanogenmod.filemanager.console.ExecutionException;
+import com.cyanogenmod.filemanager.console.InsufficientPermissionsException;
import com.cyanogenmod.filemanager.model.AID;
import com.cyanogenmod.filemanager.model.BlockDevice;
import com.cyanogenmod.filemanager.model.CharacterDevice;
@@ -32,6 +35,7 @@ import com.cyanogenmod.filemanager.model.Directory;
import com.cyanogenmod.filemanager.model.DomainSocket;
import com.cyanogenmod.filemanager.model.FileSystemObject;
import com.cyanogenmod.filemanager.model.Group;
+import com.cyanogenmod.filemanager.model.Identity;
import com.cyanogenmod.filemanager.model.NamedPipe;
import com.cyanogenmod.filemanager.model.ParentDirectory;
import com.cyanogenmod.filemanager.model.Permissions;
@@ -184,29 +188,6 @@ public final class FileHelper {
}
/**
- * Method that returns if an file system object requires elevated privileges.
- * This occurs when the user is "root" or when the user console doesn't have
- * sufficient permissions over the file system object.
- *
- * @param fso File system object
- * @return boolean If the file system object requires elevated privileges
- */
- public static boolean isPrivileged(FileSystemObject fso) {
- //Parent directory doesn't require privileges
- if (fso instanceof ParentDirectory) {
- return false;
- }
-
- //Checks if user is the administrator user
- if (fso.getUser().getName().compareTo(USER_ROOT) == 0) {
- return true;
- }
-
- //No privileged
- return false;
- }
-
- /**
* Method that returns if the file system object if the root directory.
*
* @param fso The file system object to check
@@ -1115,4 +1096,169 @@ public final class FileHelper {
}
return new File(file, ".nomedia").getAbsoluteFile(); //$NON-NLS-1$
}
+
+ /**
+ * Method that ensures that the actual console has access to read the
+ * {@link FileSystemObject} passed.
+ *
+ * @param console The console
+ * @param fso The {@link FileSystemObject} to check
+ * @param executable The executable to associate to the {@link InsufficientPermissionsException}
+ * @throws InsufficientPermissionsException If the console doesn't have enough rights
+ */
+ public static void ensureReadAccess(
+ Console console, FileSystemObject fso, SyncResultExecutable executable)
+ throws InsufficientPermissionsException {
+ try {
+ if (console.isPrivileged()) {
+ // Should have access
+ return;
+ }
+ Identity identity = console.getIdentity();
+ if (identity == null) {
+ throw new InsufficientPermissionsException(executable);
+ }
+ Permissions permissions = fso.getPermissions();
+ User user = fso.getUser();
+ Group group = fso.getGroup();
+ List<Group> groups = identity.getGroups();
+ if ( permissions == null || user == null || group == null) {
+ throw new InsufficientPermissionsException(executable);
+ }
+ // Check others
+ if (permissions.getOthers().isRead() ){
+ return;
+ }
+ // Check user
+ if (user.getId() == identity.getUser().getId() && permissions.getUser().isRead() ){
+ return;
+ }
+ // Check group
+ if (group.getId() == identity.getGroup().getId() && permissions.getGroup().isRead() ){
+ return;
+ }
+ // Check groups
+ int cc = groups.size();
+ for (int i = 0; i < cc; i++) {
+ Group g = groups.get(i);
+ if (group.getId() == g.getId() && permissions.getGroup().isRead() ){
+ return;
+ }
+ }
+
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to check fso read permission,", e); //$NON-NLS-1$
+ }
+ throw new InsufficientPermissionsException(executable);
+ }
+
+ /**
+ * Method that ensures that the actual console has access to write the
+ * {@link FileSystemObject} passed.
+ *
+ * @param console The console
+ * @param fso The {@link FileSystemObject} to check
+ * @param executable The executable to associate to the {@link InsufficientPermissionsException}
+ * @throws InsufficientPermissionsException If the console doesn't have enough rights
+ */
+ public static void ensureWriteAccess(
+ Console console, FileSystemObject fso, SyncResultExecutable executable)
+ throws InsufficientPermissionsException {
+ try {
+ if (console.isPrivileged()) {
+ // Should have access
+ return;
+ }
+ Identity identity = console.getIdentity();
+ if (identity == null) {
+ throw new InsufficientPermissionsException(executable);
+ }
+ Permissions permissions = fso.getPermissions();
+ User user = fso.getUser();
+ Group group = fso.getGroup();
+ List<Group> groups = identity.getGroups();
+ if ( permissions == null || user == null || group == null) {
+ throw new InsufficientPermissionsException(executable);
+ }
+ // Check others
+ if (permissions.getOthers().isWrite() ){
+ return;
+ }
+ // Check user
+ if (user.getId() == identity.getUser().getId() && permissions.getUser().isWrite() ){
+ return;
+ }
+ // Check group
+ if (group.getId() == identity.getGroup().getId() && permissions.getGroup().isWrite() ){
+ return;
+ }
+ // Check groups
+ int cc = groups.size();
+ for (int i = 0; i < cc; i++) {
+ Group g = groups.get(i);
+ if (group.getId() == g.getId() && permissions.getGroup().isWrite() ){
+ return;
+ }
+ }
+
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to check fso write permission,", e); //$NON-NLS-1$
+ }
+ throw new InsufficientPermissionsException(executable);
+ }
+
+ /**
+ * Method that ensures that the actual console has access to execute the
+ * {@link FileSystemObject} passed.
+ *
+ * @param console The console
+ * @param fso The {@link FileSystemObject} to check
+ * @param executable The executable to associate to the {@link InsufficientPermissionsException}
+ * @throws InsufficientPermissionsException If the console doesn't have enough rights
+ */
+ public static void ensureExecuteAccess(
+ Console console, FileSystemObject fso, SyncResultExecutable executable)
+ throws InsufficientPermissionsException {
+ try {
+ if (console.isPrivileged()) {
+ // Should have access
+ return;
+ }
+ Identity identity = console.getIdentity();
+ if (identity == null) {
+ throw new InsufficientPermissionsException(executable);
+ }
+ Permissions permissions = fso.getPermissions();
+ User user = fso.getUser();
+ Group group = fso.getGroup();
+ List<Group> groups = identity.getGroups();
+ if ( permissions == null || user == null || group == null) {
+ throw new InsufficientPermissionsException(executable);
+ }
+ // Check others
+ if (permissions.getOthers().isExecute() ){
+ return;
+ }
+ // Check user
+ if (user.getId() == identity.getUser().getId() && permissions.getUser().isExecute() ){
+ return;
+ }
+ // Check group
+ if (group.getId() == identity.getGroup().getId() && permissions.getGroup().isExecute() ){
+ return;
+ }
+ // Check groups
+ int cc = groups.size();
+ for (int i = 0; i < cc; i++) {
+ Group g = groups.get(i);
+ if (group.getId() == g.getId() && permissions.getGroup().isExecute() ){
+ return;
+ }
+ }
+
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to check fso execute permission,", e); //$NON-NLS-1$
+ }
+ throw new InsufficientPermissionsException(executable);
+ }
}