New keyfile management

This commit is contained in:
J-Jamet
2017-12-01 20:03:22 +01:00
parent 7cce527e43
commit e6cc9b628e
8 changed files with 243 additions and 134 deletions

View File

@@ -22,6 +22,7 @@ package com.keepassdroid;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
@@ -31,26 +32,31 @@ import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.keepassdroid.utils.EmptyUtils;
import com.keepassdroid.utils.UriUtil;
import com.keepassdroid.view.KeyFileHelper;
import com.kunzisoft.keepass.R;
public class AssignPasswordDialog extends DialogFragment {
private String masterPassword;
private Uri mKeyfile;
private View rootView;
private CompoundButton passwordCheckBox;
private CompoundButton keyfileCheckBox;
private AssignPasswordDialogListener mListener;
private KeyFileHelper keyFileHelper;
public interface AssignPasswordDialogListener {
void onDialogPositiveClick(String masterPassword, Uri keyFile);
void onDialogNegativeClick(String masterPassword, Uri keyFile);
void onAssignKeyDialogPositiveClick(String masterPassword, Uri keyFile);
void onAssignKeyDialogNegativeClick(String masterPassword, Uri keyFile);
}
@Override
@@ -85,6 +91,20 @@ public class AssignPasswordDialog extends DialogFragment {
}
});
passwordCheckBox = (CompoundButton) rootView.findViewById(R.id.password_checkBox);
keyfileCheckBox = (CompoundButton) rootView.findViewById(R.id.keyfile_checkox);
keyFileHelper = new KeyFileHelper(this);
rootView.findViewById(R.id.browse_button)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
keyfileCheckBox.setChecked(true);
keyFileHelper.getOpenFileOnClickViewListener().onClick(view);
}
});
AlertDialog dialog = builder.create();
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
@@ -94,8 +114,7 @@ public class AssignPasswordDialog extends DialogFragment {
positiveButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
CompoundButton passwordCheckBox = (CompoundButton) rootView.findViewById(R.id.password_checkBox);
CompoundButton keyfileCheckBox = (CompoundButton) rootView.findViewById(R.id.keyfile_checkox);
masterPassword = "";
mKeyfile = null;
@@ -130,10 +149,11 @@ public class AssignPasswordDialog extends DialogFragment {
}
if (!error) {
if (masterPassword == null || masterPassword.isEmpty()) {
if (!keyfileCheckBox.isChecked() &&
(masterPassword == null || masterPassword.isEmpty())) {
showEmptyPasswordConfirmationDialog();
} else {
mListener.onDialogPositiveClick(masterPassword, mKeyfile);
mListener.onAssignKeyDialogPositiveClick(masterPassword, mKeyfile);
dismiss();
}
}
@@ -143,7 +163,7 @@ public class AssignPasswordDialog extends DialogFragment {
negativeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
mListener.onDialogNegativeClick(masterPassword, mKeyfile);
mListener.onAssignKeyDialogNegativeClick(masterPassword, mKeyfile);
dismiss();
}
});
@@ -159,16 +179,31 @@ public class AssignPasswordDialog extends DialogFragment {
builder.setMessage(R.string.warning_empty_password)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
mListener.onDialogPositiveClick(masterPassword, mKeyfile);
mListener.onAssignKeyDialogPositiveClick(masterPassword, mKeyfile);
AssignPasswordDialog.this.dismiss();
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
mListener.onDialogNegativeClick(masterPassword, mKeyfile);
mListener.onAssignKeyDialogNegativeClick(masterPassword, mKeyfile);
}
});
builder.create().show();
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
keyFileHelper.onActivityResultCallback(requestCode, resultCode, data,
new KeyFileHelper.KeyFileCallback() {
@Override
public void onResultCallback(Uri uri) {
if(uri != null) {
EditText keyFileView = (EditText) rootView.findViewById(R.id.pass_keyfile);
keyFileView.setText(uri.toString());
}
}
});
}
}

View File

@@ -269,7 +269,7 @@ public abstract class GroupBaseActivity extends LockCloseListActivity
}
@Override
public void onDialogPositiveClick(String masterPassword, Uri keyFile) {
public void onAssignKeyDialogPositiveClick(String masterPassword, Uri keyFile) {
AssignPasswordHelper assignPasswordHelper =
new AssignPasswordHelper(this,
@@ -278,7 +278,7 @@ public abstract class GroupBaseActivity extends LockCloseListActivity
}
@Override
public void onDialogNegativeClick(String masterPassword, Uri keyFile) {
public void onAssignKeyDialogNegativeClick(String masterPassword, Uri keyFile) {
}

View File

@@ -20,7 +20,6 @@
package com.keepassdroid;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
@@ -50,18 +49,15 @@ import com.keepassdroid.app.App;
import com.keepassdroid.compat.BackupManagerCompat;
import com.keepassdroid.compat.ClipDataCompat;
import com.keepassdroid.compat.EditorCompat;
import com.keepassdroid.compat.StorageAF;
import com.keepassdroid.database.edit.LoadDB;
import com.keepassdroid.database.edit.OnFinish;
import com.keepassdroid.dialog.PasswordEncodingDialogHelper;
import com.keepassdroid.fileselect.BrowserDialog;
import com.keepassdroid.fingerprint.FingerPrintHelper;
import com.keepassdroid.intents.Intents;
import com.keepassdroid.utils.EmptyUtils;
import com.keepassdroid.utils.Interaction;
import com.keepassdroid.utils.MenuUtil;
import com.keepassdroid.utils.UriUtil;
import com.keepassdroid.utils.Util;
import com.keepassdroid.view.KeyFileHelper;
import com.kunzisoft.keepass.KeePass;
import com.kunzisoft.keepass.R;
@@ -79,10 +75,6 @@ public class PasswordActivity extends LockingActivity implements FingerPrintHelp
private static final String KEY_LAUNCH_IMMEDIATELY = "launchImmediately";
private static final String VIEW_INTENT = "android.intent.action.VIEW";
private static final int FILE_BROWSE = 256;
public static final int GET_CONTENT = 257;
private static final int OPEN_DOC = 258;
private Uri mDbUri = null;
private Uri mKeyUri = null;
private boolean mRememberKeyfile;
@@ -100,6 +92,8 @@ public class PasswordActivity extends LockingActivity implements FingerPrintHelp
private EditText passwordView;
private Button confirmButton;
private KeyFileHelper keyFileHelper;
public static void Launch(
Activity act,
String fileName) throws FileNotFoundException {
@@ -139,6 +133,17 @@ public class PasswordActivity extends LockingActivity implements FingerPrintHelp
Intent data) {
super.onActivityResult(requestCode, resultCode, data);
keyFileHelper.onActivityResultCallback(requestCode, resultCode, data,
new KeyFileHelper.KeyFileCallback() {
@Override
public void onResultCallback(Uri uri) {
if(uri != null) {
EditText fn = (EditText) findViewById(R.id.pass_keyfile);
fn.setText(uri.toString());
}
}
});
switch (requestCode) {
case KeePass.EXIT_NORMAL:
setEditText(R.id.password, "");
@@ -151,37 +156,8 @@ public class PasswordActivity extends LockingActivity implements FingerPrintHelp
finish();
App.getDB().clear();
break;
case FILE_BROWSE:
if (resultCode == RESULT_OK) {
String filename = data.getDataString();
if (filename != null) {
EditText fn = (EditText) findViewById(R.id.pass_keyfile);
fn.setText(filename);
mKeyUri = UriUtil.parseDefaultFile(filename);
}
}
break;
case GET_CONTENT:
case OPEN_DOC:
if (resultCode == RESULT_OK) {
if (data != null) {
Uri uri = data.getData();
if (uri != null) {
if (requestCode == GET_CONTENT) {
uri = UriUtil.translate(this, uri);
}
String path = uri.toString();
if (path != null) {
EditText fn = (EditText) findViewById(R.id.pass_keyfile);
fn.setText(path);
}
mKeyUri = uri;
}
}
}
break;
}
}
@Override
@@ -497,14 +473,6 @@ public class PasswordActivity extends LockingActivity implements FingerPrintHelp
String pass,
Uri keyfile) {
/*
TODO Remove
if (pass.length() == 0 && (keyfile == null || keyfile.toString().length() == 0)) {
errorMessage(R.string.error_nopass);
return;
}
*/
// Clear before we load
Database db = App.getDB();
db.clear();
@@ -664,62 +632,9 @@ public class PasswordActivity extends LockingActivity implements FingerPrintHelp
CompoundButton defaultCheck = (CompoundButton) findViewById(R.id.default_database);
defaultCheck.setOnCheckedChangeListener(new DefaultCheckChange());
View browse = findViewById(R.id.browse_button);
browse.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (StorageAF.useStorageFramework(PasswordActivity.this)) {
Intent i = new Intent(StorageAF.ACTION_OPEN_DOCUMENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
startActivityForResult(i, OPEN_DOC);
} else {
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
try {
startActivityForResult(i, GET_CONTENT);
} catch (ActivityNotFoundException e) {
lookForOpenIntentsFilePicker();
}
}
}
private void lookForOpenIntentsFilePicker() {
if (Interaction.isIntentAvailable(PasswordActivity.this, Intents.OPEN_INTENTS_FILE_BROWSE)) {
Intent i = new Intent(Intents.OPEN_INTENTS_FILE_BROWSE);
// Get file path parent if possible
try {
if (mDbUri != null && mDbUri.toString().length() > 0) {
if (mDbUri.getScheme().equals("file")) {
File keyfile = new File(mDbUri.getPath());
File parent = keyfile.getParentFile();
if (parent != null) {
i.setData(Uri.parse("file://" + parent.getAbsolutePath()));
}
}
}
} catch (Exception e) {
// Ignore
}
try {
startActivityForResult(i, FILE_BROWSE);
} catch (ActivityNotFoundException e) {
showBrowserDialog();
}
} else {
showBrowserDialog();
}
}
private void showBrowserDialog() {
BrowserDialog browserDialog = new BrowserDialog(PasswordActivity.this);
browserDialog.show();
}
});
View browseView = findViewById(R.id.browse_button);
keyFileHelper = new KeyFileHelper(PasswordActivity.this);
browseView.setOnClickListener(keyFileHelper.getOpenFileOnClickViewListener());
retrieveSettings();

View File

@@ -299,7 +299,7 @@ public class FileSelectActivity extends StylishActivity implements
}
@Override
public void onDialogPositiveClick(String masterPassword, Uri keyFile) {
public void onAssignKeyDialogPositiveClick(String masterPassword, Uri keyFile) {
String filename = Util.getEditText(FileSelectActivity.this,
R.id.file_filename);
@@ -328,7 +328,7 @@ public class FileSelectActivity extends StylishActivity implements
}
@Override
public void onDialogNegativeClick(String masterPassword, Uri keyFile) {
public void onAssignKeyDialogNegativeClick(String masterPassword, Uri keyFile) {
}

View File

@@ -0,0 +1,162 @@
package com.keepassdroid.view;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.support.v4.app.Fragment;
import android.view.View;
import com.keepassdroid.compat.StorageAF;
import com.keepassdroid.fileselect.BrowserDialog;
import com.keepassdroid.intents.Intents;
import com.keepassdroid.utils.Interaction;
import com.keepassdroid.utils.UriUtil;
import java.io.File;
import static android.app.Activity.RESULT_OK;
/**
* Created by joker on 01/12/17.
*/
public class KeyFileHelper {
public static final int GET_CONTENT = 25745;
private static final int OPEN_DOC = 25845;
private static final int FILE_BROWSE = 25645;
private Activity activity;
private Fragment fragment;
private Uri mDbUri;
public KeyFileHelper(Activity context) {
this(context, null);
}
public KeyFileHelper(Activity context, Uri mDbUri) {
this.activity = context;
this.fragment = null;
this.mDbUri = mDbUri;
}
public KeyFileHelper(Fragment context) {
this(context, null);
}
public KeyFileHelper(Fragment context, Uri mDbUri) {
this.activity = context.getActivity();
this.fragment = context;
this.mDbUri = mDbUri;
}
public View.OnClickListener getOpenFileOnClickViewListener() {
return new View.OnClickListener() {
public void onClick(View v) {
if (StorageAF.useStorageFramework(activity)) {
Intent i = new Intent(StorageAF.ACTION_OPEN_DOCUMENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
if(fragment != null)
fragment.startActivityForResult(i, OPEN_DOC);
else
activity.startActivityForResult(i, OPEN_DOC);
} else {
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
try {
if(fragment != null)
fragment.startActivityForResult(i, GET_CONTENT);
else
activity.startActivityForResult(i, GET_CONTENT);
} catch (ActivityNotFoundException e) {
lookForOpenIntentsFilePicker();
}
}
}
};
}
private void lookForOpenIntentsFilePicker() {
if (Interaction.isIntentAvailable(activity, Intents.OPEN_INTENTS_FILE_BROWSE)) {
Intent i = new Intent(Intents.OPEN_INTENTS_FILE_BROWSE);
// Get file path parent if possible
try {
if (mDbUri != null && mDbUri.toString().length() > 0) {
if (mDbUri.getScheme().equals("file")) {
File keyfile = new File(mDbUri.getPath());
File parent = keyfile.getParentFile();
if (parent != null) {
i.setData(Uri.parse("file://" + parent.getAbsolutePath()));
}
}
}
} catch (Exception e) {
// Ignore
}
try {
if(fragment != null)
fragment.startActivityForResult(i, FILE_BROWSE);
else
activity.startActivityForResult(i, FILE_BROWSE);
} catch (ActivityNotFoundException e) {
showBrowserDialog();
}
} else {
showBrowserDialog();
}
}
private void showBrowserDialog() {
BrowserDialog browserDialog = new BrowserDialog(activity);
browserDialog.show();
}
public void onActivityResultCallback(
int requestCode,
int resultCode,
Intent data,
KeyFileCallback keyFileCallback) {
switch (requestCode) {
case FILE_BROWSE:
if (resultCode == RESULT_OK) {
String filename = data.getDataString();
Uri keyUri = null;
if (filename != null) {
keyUri = UriUtil.parseDefaultFile(filename);
}
if (keyFileCallback != null)
keyFileCallback.onResultCallback(keyUri);
}
break;
case GET_CONTENT:
case OPEN_DOC:
if (resultCode == RESULT_OK) {
if (data != null) {
Uri uri = data.getData();
if (uri != null) {
if (requestCode == GET_CONTENT) {
uri = UriUtil.translate(activity, uri);
}
if (keyFileCallback != null)
keyFileCallback.onResultCallback(uri);
}
}
}
break;
}
}
public interface KeyFileCallback {
void onResultCallback(Uri uri);
}
}

View File

@@ -50,4 +50,14 @@
</LinearLayout>
<android.support.design.widget.FloatingActionButton
android:id="@+id/create_database"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:src="@drawable/ic_database_plus_white_24dp"
style="@style/KeepassDXStyle.Fab"/>
</RelativeLayout>

View File

@@ -75,25 +75,11 @@
</android.support.v7.widget.CardView>
<android.support.design.widget.FloatingActionButton
android:id="@+id/open_database"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/filename_container"
android:layout_toLeftOf="@+id/create_database"
android:layout_toStartOf="@+id/create_database"
android:layout_marginTop="-22dp"
android:layout_marginRight="16dp"
android:layout_marginEnd="16dp"
app:fabSize="mini"
android:src="@drawable/ic_open_folder_white_24dp" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/create_database"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/filename_container"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_marginEnd="24dp"
@@ -101,6 +87,6 @@
android:layout_marginTop="-22dp"
android:layout_marginBottom="5dp"
app:fabSize="mini"
android:src="@drawable/ic_database_plus_white_24dp" />
android:src="@drawable/ic_open_folder_white_24dp" />
</RelativeLayout>

View File

@@ -108,14 +108,15 @@
android:src="@drawable/ic_folder_white_24dp"
android:tint="?attr/colorAccentCompat" />
<EditText
<android.support.v7.widget.AppCompatEditText
android:id="@+id/pass_keyfile"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toLeftOf="@+id/browse_button"
android:layout_toStartOf="@+id/browse_button"
android:hint="@string/hint_keyfile"
android:maxLines="1" />
android:maxLines="1"
android:singleLine="true"/>
</RelativeLayout>