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.app.Dialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
@@ -31,26 +32,31 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.widget.Button; import android.widget.Button;
import android.widget.CompoundButton; import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import com.keepassdroid.utils.EmptyUtils; import com.keepassdroid.utils.EmptyUtils;
import com.keepassdroid.utils.UriUtil; import com.keepassdroid.utils.UriUtil;
import com.keepassdroid.view.KeyFileHelper;
import com.kunzisoft.keepass.R; import com.kunzisoft.keepass.R;
public class AssignPasswordDialog extends DialogFragment { public class AssignPasswordDialog extends DialogFragment {
private String masterPassword; private String masterPassword;
private Uri mKeyfile; private Uri mKeyfile;
private View rootView; private View rootView;
private CompoundButton passwordCheckBox;
private CompoundButton keyfileCheckBox;
private AssignPasswordDialogListener mListener; private AssignPasswordDialogListener mListener;
private KeyFileHelper keyFileHelper;
public interface AssignPasswordDialogListener { public interface AssignPasswordDialogListener {
void onDialogPositiveClick(String masterPassword, Uri keyFile); void onAssignKeyDialogPositiveClick(String masterPassword, Uri keyFile);
void onDialogNegativeClick(String masterPassword, Uri keyFile); void onAssignKeyDialogNegativeClick(String masterPassword, Uri keyFile);
} }
@Override @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(); AlertDialog dialog = builder.create();
dialog.setOnShowListener(new DialogInterface.OnShowListener() { dialog.setOnShowListener(new DialogInterface.OnShowListener() {
@@ -94,8 +114,7 @@ public class AssignPasswordDialog extends DialogFragment {
positiveButton.setOnClickListener(new View.OnClickListener() { positiveButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(final View v) { 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 = ""; masterPassword = "";
mKeyfile = null; mKeyfile = null;
@@ -130,10 +149,11 @@ public class AssignPasswordDialog extends DialogFragment {
} }
if (!error) { if (!error) {
if (masterPassword == null || masterPassword.isEmpty()) { if (!keyfileCheckBox.isChecked() &&
(masterPassword == null || masterPassword.isEmpty())) {
showEmptyPasswordConfirmationDialog(); showEmptyPasswordConfirmationDialog();
} else { } else {
mListener.onDialogPositiveClick(masterPassword, mKeyfile); mListener.onAssignKeyDialogPositiveClick(masterPassword, mKeyfile);
dismiss(); dismiss();
} }
} }
@@ -143,7 +163,7 @@ public class AssignPasswordDialog extends DialogFragment {
negativeButton.setOnClickListener(new View.OnClickListener() { negativeButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(final View v) { public void onClick(final View v) {
mListener.onDialogNegativeClick(masterPassword, mKeyfile); mListener.onAssignKeyDialogNegativeClick(masterPassword, mKeyfile);
dismiss(); dismiss();
} }
}); });
@@ -159,16 +179,31 @@ public class AssignPasswordDialog extends DialogFragment {
builder.setMessage(R.string.warning_empty_password) builder.setMessage(R.string.warning_empty_password)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
mListener.onDialogPositiveClick(masterPassword, mKeyfile); mListener.onAssignKeyDialogPositiveClick(masterPassword, mKeyfile);
AssignPasswordDialog.this.dismiss(); AssignPasswordDialog.this.dismiss();
} }
}) })
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
mListener.onDialogNegativeClick(masterPassword, mKeyfile); mListener.onAssignKeyDialogNegativeClick(masterPassword, mKeyfile);
} }
}); });
builder.create().show(); 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 @Override
public void onDialogPositiveClick(String masterPassword, Uri keyFile) { public void onAssignKeyDialogPositiveClick(String masterPassword, Uri keyFile) {
AssignPasswordHelper assignPasswordHelper = AssignPasswordHelper assignPasswordHelper =
new AssignPasswordHelper(this, new AssignPasswordHelper(this,
@@ -278,7 +278,7 @@ public abstract class GroupBaseActivity extends LockCloseListActivity
} }
@Override @Override
public void onDialogNegativeClick(String masterPassword, Uri keyFile) { public void onAssignKeyDialogNegativeClick(String masterPassword, Uri keyFile) {
} }

View File

@@ -20,7 +20,6 @@
package com.keepassdroid; package com.keepassdroid;
import android.app.Activity; import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener; import android.content.DialogInterface.OnClickListener;
@@ -50,18 +49,15 @@ import com.keepassdroid.app.App;
import com.keepassdroid.compat.BackupManagerCompat; import com.keepassdroid.compat.BackupManagerCompat;
import com.keepassdroid.compat.ClipDataCompat; import com.keepassdroid.compat.ClipDataCompat;
import com.keepassdroid.compat.EditorCompat; import com.keepassdroid.compat.EditorCompat;
import com.keepassdroid.compat.StorageAF;
import com.keepassdroid.database.edit.LoadDB; import com.keepassdroid.database.edit.LoadDB;
import com.keepassdroid.database.edit.OnFinish; import com.keepassdroid.database.edit.OnFinish;
import com.keepassdroid.dialog.PasswordEncodingDialogHelper; import com.keepassdroid.dialog.PasswordEncodingDialogHelper;
import com.keepassdroid.fileselect.BrowserDialog;
import com.keepassdroid.fingerprint.FingerPrintHelper; import com.keepassdroid.fingerprint.FingerPrintHelper;
import com.keepassdroid.intents.Intents;
import com.keepassdroid.utils.EmptyUtils; import com.keepassdroid.utils.EmptyUtils;
import com.keepassdroid.utils.Interaction;
import com.keepassdroid.utils.MenuUtil; import com.keepassdroid.utils.MenuUtil;
import com.keepassdroid.utils.UriUtil; import com.keepassdroid.utils.UriUtil;
import com.keepassdroid.utils.Util; import com.keepassdroid.utils.Util;
import com.keepassdroid.view.KeyFileHelper;
import com.kunzisoft.keepass.KeePass; import com.kunzisoft.keepass.KeePass;
import com.kunzisoft.keepass.R; 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 KEY_LAUNCH_IMMEDIATELY = "launchImmediately";
private static final String VIEW_INTENT = "android.intent.action.VIEW"; 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 mDbUri = null;
private Uri mKeyUri = null; private Uri mKeyUri = null;
private boolean mRememberKeyfile; private boolean mRememberKeyfile;
@@ -100,6 +92,8 @@ public class PasswordActivity extends LockingActivity implements FingerPrintHelp
private EditText passwordView; private EditText passwordView;
private Button confirmButton; private Button confirmButton;
private KeyFileHelper keyFileHelper;
public static void Launch( public static void Launch(
Activity act, Activity act,
String fileName) throws FileNotFoundException { String fileName) throws FileNotFoundException {
@@ -139,6 +133,17 @@ public class PasswordActivity extends LockingActivity implements FingerPrintHelp
Intent data) { Intent data) {
super.onActivityResult(requestCode, resultCode, 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) { switch (requestCode) {
case KeePass.EXIT_NORMAL: case KeePass.EXIT_NORMAL:
setEditText(R.id.password, ""); setEditText(R.id.password, "");
@@ -151,37 +156,8 @@ public class PasswordActivity extends LockingActivity implements FingerPrintHelp
finish(); finish();
App.getDB().clear(); App.getDB().clear();
break; 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 @Override
@@ -497,14 +473,6 @@ public class PasswordActivity extends LockingActivity implements FingerPrintHelp
String pass, String pass,
Uri keyfile) { Uri keyfile) {
/*
TODO Remove
if (pass.length() == 0 && (keyfile == null || keyfile.toString().length() == 0)) {
errorMessage(R.string.error_nopass);
return;
}
*/
// Clear before we load // Clear before we load
Database db = App.getDB(); Database db = App.getDB();
db.clear(); db.clear();
@@ -664,62 +632,9 @@ public class PasswordActivity extends LockingActivity implements FingerPrintHelp
CompoundButton defaultCheck = (CompoundButton) findViewById(R.id.default_database); CompoundButton defaultCheck = (CompoundButton) findViewById(R.id.default_database);
defaultCheck.setOnCheckedChangeListener(new DefaultCheckChange()); defaultCheck.setOnCheckedChangeListener(new DefaultCheckChange());
View browse = findViewById(R.id.browse_button); View browseView = findViewById(R.id.browse_button);
browse.setOnClickListener(new View.OnClickListener() { keyFileHelper = new KeyFileHelper(PasswordActivity.this);
browseView.setOnClickListener(keyFileHelper.getOpenFileOnClickViewListener());
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();
}
});
retrieveSettings(); retrieveSettings();

View File

@@ -299,7 +299,7 @@ public class FileSelectActivity extends StylishActivity implements
} }
@Override @Override
public void onDialogPositiveClick(String masterPassword, Uri keyFile) { public void onAssignKeyDialogPositiveClick(String masterPassword, Uri keyFile) {
String filename = Util.getEditText(FileSelectActivity.this, String filename = Util.getEditText(FileSelectActivity.this,
R.id.file_filename); R.id.file_filename);
@@ -328,7 +328,7 @@ public class FileSelectActivity extends StylishActivity implements
} }
@Override @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> </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> </RelativeLayout>

View File

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

View File

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