mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
UI and backend refactoring to support both database versions.
This commit is contained in:
@@ -29,7 +29,7 @@
|
|||||||
<data android:pathPattern=".*\\.kdb" />
|
<data android:pathPattern=".*\\.kdb" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name="com.keepassdroid.GroupActivity" android:configChanges="orientation|keyboardHidden">
|
<activity android:name="com.keepassdroid.GroupActivityV3" android:configChanges="orientation|keyboardHidden">
|
||||||
<!-- This metadata entry causes .app.SearchQueryResults to be the default context -->
|
<!-- This metadata entry causes .app.SearchQueryResults to be the default context -->
|
||||||
<!-- whenever the user invokes search while in this Activity. -->
|
<!-- whenever the user invokes search while in this Activity. -->
|
||||||
<meta-data android:name="android.app.default_searchable"
|
<meta-data android:name="android.app.default_searchable"
|
||||||
|
|||||||
BIN
assets/test.kdbx
BIN
assets/test.kdbx
Binary file not shown.
@@ -68,7 +68,8 @@ jint Java_com_keepassdroid_crypto_NativeAESCipherSpi_nativeUpdate(JNIEnv *env,
|
|||||||
jint inputLen, jbyteArray output, jint outputOffset, jint outputSize) {
|
jint inputLen, jbyteArray output, jint outputOffset, jint outputSize) {
|
||||||
|
|
||||||
|
|
||||||
LOGD("InputSize: %d; OutputSize: %d", inputLen, outputSize);
|
LOGD("InputSize: %d; InputOffset: %d, OutputOffset: %d, OutputSize: %d", inputLen, inputOffset,
|
||||||
|
outputOffset, outputSize);
|
||||||
if ( inputLen == 0 ) {
|
if ( inputLen == 0 ) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -98,7 +99,7 @@ jint Java_com_keepassdroid_crypto_NativeAESCipherSpi_nativeUpdate(JNIEnv *env,
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
LOGD("PreOut: OutLen=%d", outLen);
|
LOGD("PreOut: outputSize=%d, outputOffset=%d, OutLen=%d", outputSize, outputOffset, outLen);
|
||||||
(*env)->SetByteArrayRegion(env, output, outputOffset, outLen, c_output);
|
(*env)->SetByteArrayRegion(env, output, outputOffset, outLen, c_output);
|
||||||
|
|
||||||
free(c_output);
|
free(c_output);
|
||||||
|
|||||||
@@ -73,6 +73,7 @@
|
|||||||
<string name="error_nopass">A password or a keyfile is required.</string>
|
<string name="error_nopass">A password or a keyfile is required.</string>
|
||||||
<string name="error_pass_match">Passwords do not match.</string>
|
<string name="error_pass_match">Passwords do not match.</string>
|
||||||
<string name="error_rounds_not_number">Rounds must be a number.</string>
|
<string name="error_rounds_not_number">Rounds must be a number.</string>
|
||||||
|
<string name="error_rounds_too_large">Rounds too big. Setting to 2147483648.</string>
|
||||||
<string name="error_title_required">A title is required.</string>
|
<string name="error_title_required">A title is required.</string>
|
||||||
<string name="FileNotFound">File not found.</string>
|
<string name="FileNotFound">File not found.</string>
|
||||||
<string name="group">Group</string>
|
<string name="group">Group</string>
|
||||||
|
|||||||
@@ -34,8 +34,10 @@ import java.util.Vector;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Debug;
|
import android.os.Debug;
|
||||||
|
|
||||||
import com.keepassdroid.database.PwDatabaseV3;
|
import com.keepassdroid.database.PwDatabase;
|
||||||
import com.keepassdroid.database.PwEntryV3;
|
import com.keepassdroid.database.PwEntry;
|
||||||
|
import com.keepassdroid.database.PwGroup;
|
||||||
|
import com.keepassdroid.database.PwGroupId;
|
||||||
import com.keepassdroid.database.PwGroupV3;
|
import com.keepassdroid.database.PwGroupV3;
|
||||||
import com.keepassdroid.database.exception.InvalidDBSignatureException;
|
import com.keepassdroid.database.exception.InvalidDBSignatureException;
|
||||||
import com.keepassdroid.database.exception.InvalidDBVersionException;
|
import com.keepassdroid.database.exception.InvalidDBVersionException;
|
||||||
@@ -46,7 +48,7 @@ import com.keepassdroid.database.exception.PwDbOutputException;
|
|||||||
import com.keepassdroid.database.load.Importer;
|
import com.keepassdroid.database.load.Importer;
|
||||||
import com.keepassdroid.database.load.ImporterFactory;
|
import com.keepassdroid.database.load.ImporterFactory;
|
||||||
import com.keepassdroid.database.load.ImporterV3;
|
import com.keepassdroid.database.load.ImporterV3;
|
||||||
import com.keepassdroid.database.save.PwDbV3Output;
|
import com.keepassdroid.database.save.PwDbOutput;
|
||||||
import com.keepassdroid.search.SearchDbHelper;
|
import com.keepassdroid.search.SearchDbHelper;
|
||||||
import com.keepassdroid.utils.Types;
|
import com.keepassdroid.utils.Types;
|
||||||
|
|
||||||
@@ -54,11 +56,11 @@ import com.keepassdroid.utils.Types;
|
|||||||
* @author bpellin
|
* @author bpellin
|
||||||
*/
|
*/
|
||||||
public class Database {
|
public class Database {
|
||||||
public HashMap<Integer, WeakReference<PwGroupV3>> groups = new HashMap<Integer, WeakReference<PwGroupV3>>();
|
public HashMap<PwGroupId, WeakReference<PwGroup>> groups = new HashMap<PwGroupId, WeakReference<PwGroup>>();
|
||||||
public HashMap<UUID, WeakReference<PwEntryV3>> entries = new HashMap<UUID, WeakReference<PwEntryV3>>();
|
public HashMap<UUID, WeakReference<PwEntry>> entries = new HashMap<UUID, WeakReference<PwEntry>>();
|
||||||
public HashMap<PwGroupV3, WeakReference<PwGroupV3>> dirty = new HashMap<PwGroupV3, WeakReference<PwGroupV3>>();
|
public HashMap<PwGroup, WeakReference<PwGroup>> dirty = new HashMap<PwGroup, WeakReference<PwGroup>>();
|
||||||
public PwGroupV3 root;
|
public PwGroup root;
|
||||||
public PwDatabaseV3 pm;
|
public PwDatabase pm;
|
||||||
public String mFilename;
|
public String mFilename;
|
||||||
public SearchDbHelper searchHelper;
|
public SearchDbHelper searchHelper;
|
||||||
public boolean indexBuilt = false;
|
public boolean indexBuilt = false;
|
||||||
@@ -119,7 +121,6 @@ public class Database {
|
|||||||
|
|
||||||
pm = Importer.openDatabase(bis, password, keyfile, status);
|
pm = Importer.openDatabase(bis, password, keyfile, status);
|
||||||
if ( pm != null ) {
|
if ( pm != null ) {
|
||||||
pm.constructTree(null);
|
|
||||||
populateGlobals(null);
|
populateGlobals(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,7 +139,7 @@ public class Database {
|
|||||||
initSearch();
|
initSearch();
|
||||||
|
|
||||||
searchHelper.open();
|
searchHelper.open();
|
||||||
searchHelper.insertEntry(pm.entries);
|
searchHelper.insertEntry(pm.getEntries());
|
||||||
/*for ( int i = 0; i < pm.entries.size(); i++) {
|
/*for ( int i = 0; i < pm.entries.size(); i++) {
|
||||||
PwEntryV3 entry = pm.entries.get(i);
|
PwEntryV3 entry = pm.entries.get(i);
|
||||||
if ( ! entry.isMetaStream() ) {
|
if ( ! entry.isMetaStream() ) {
|
||||||
@@ -170,7 +171,7 @@ public class Database {
|
|||||||
//BufferedOutputStream bos = new BufferedOutputStream(fos);
|
//BufferedOutputStream bos = new BufferedOutputStream(fos);
|
||||||
|
|
||||||
//PwDbV3Output pmo = new PwDbV3Output(pm, bos, App.getCalendar());
|
//PwDbV3Output pmo = new PwDbV3Output(pm, bos, App.getCalendar());
|
||||||
PwDbV3Output pmo = new PwDbV3Output(pm, fos);
|
PwDbOutput pmo = PwDbOutput.getInstance(pm, fos);
|
||||||
pmo.output();
|
pmo.output();
|
||||||
//bos.flush();
|
//bos.flush();
|
||||||
//bos.close();
|
//bos.close();
|
||||||
@@ -187,30 +188,30 @@ public class Database {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void populateGlobals(PwGroupV3 currentGroup) {
|
private void populateGlobals(PwGroup currentGroup) {
|
||||||
if (currentGroup == null) {
|
if (currentGroup == null) {
|
||||||
Vector<PwGroupV3> rootChildGroups = pm.getGrpRoots();
|
Vector<? extends PwGroup> rootChildGroups = pm.getGrpRoots();
|
||||||
for (int i = 0; i < rootChildGroups.size(); i++ ){
|
for (int i = 0; i < rootChildGroups.size(); i++ ){
|
||||||
PwGroupV3 cur = rootChildGroups.elementAt(i);
|
PwGroup cur = rootChildGroups.elementAt(i);
|
||||||
root = cur.parent;
|
root = cur.getParent();
|
||||||
groups.put(cur.groupId, new WeakReference<PwGroupV3>(cur));
|
groups.put(cur.getId(), new WeakReference<PwGroup>(cur));
|
||||||
populateGlobals(cur);
|
populateGlobals(cur);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<PwGroupV3> childGroups = currentGroup.childGroups;
|
Vector<PwGroup> childGroups = currentGroup.childGroups;
|
||||||
Vector<PwEntryV3> childEntries = currentGroup.childEntries;
|
Vector<PwEntry> childEntries = currentGroup.childEntries;
|
||||||
|
|
||||||
for (int i = 0; i < childEntries.size(); i++ ) {
|
for (int i = 0; i < childEntries.size(); i++ ) {
|
||||||
PwEntryV3 cur = childEntries.elementAt(i);
|
PwEntry cur = childEntries.elementAt(i);
|
||||||
entries.put(Types.bytestoUUID(cur.uuid), new WeakReference<PwEntryV3>(cur));
|
entries.put(Types.bytestoUUID(cur.uuid), new WeakReference<PwEntry>(cur));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < childGroups.size(); i++ ) {
|
for (int i = 0; i < childGroups.size(); i++ ) {
|
||||||
PwGroupV3 cur = childGroups.elementAt(i);
|
PwGroup cur = childGroups.elementAt(i);
|
||||||
groups.put(cur.groupId, new WeakReference<PwGroupV3>(cur));
|
groups.put(cur.getId(), new WeakReference<PwGroup>(cur));
|
||||||
populateGlobals(cur);
|
populateGlobals(cur);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,12 +20,11 @@
|
|||||||
package com.keepassdroid;
|
package com.keepassdroid;
|
||||||
|
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.util.Calendar;
|
import java.util.Date;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
@@ -51,7 +50,7 @@ import android.widget.Toast;
|
|||||||
import com.android.keepass.KeePass;
|
import com.android.keepass.KeePass;
|
||||||
import com.android.keepass.R;
|
import com.android.keepass.R;
|
||||||
import com.keepassdroid.app.App;
|
import com.keepassdroid.app.App;
|
||||||
import com.keepassdroid.database.PwDate;
|
import com.keepassdroid.database.PwEntry;
|
||||||
import com.keepassdroid.database.PwEntryV3;
|
import com.keepassdroid.database.PwEntryV3;
|
||||||
import com.keepassdroid.intents.Intents;
|
import com.keepassdroid.intents.Intents;
|
||||||
import com.keepassdroid.utils.Types;
|
import com.keepassdroid.utils.Types;
|
||||||
@@ -75,7 +74,7 @@ public class EntryActivity extends LockCloseActivity {
|
|||||||
private static final int COL_LABEL = 0;
|
private static final int COL_LABEL = 0;
|
||||||
private static final int COL_DATA = 1;
|
private static final int COL_DATA = 1;
|
||||||
|
|
||||||
public static void Launch(Activity act, PwEntryV3 pw, int pos) {
|
public static void Launch(Activity act, PwEntry pw, int pos) {
|
||||||
Intent i = new Intent(act, EntryActivity.class);
|
Intent i = new Intent(act, EntryActivity.class);
|
||||||
|
|
||||||
i.putExtra(KEY_ENTRY, pw.uuid);
|
i.putExtra(KEY_ENTRY, pw.uuid);
|
||||||
@@ -84,7 +83,7 @@ public class EntryActivity extends LockCloseActivity {
|
|||||||
act.startActivityForResult(i,0);
|
act.startActivityForResult(i,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private PwEntryV3 mEntry;
|
private PwEntry mEntry;
|
||||||
private Timer mTimer = new Timer();
|
private Timer mTimer = new Timer();
|
||||||
private boolean mShowPassword;
|
private boolean mShowPassword;
|
||||||
private int mPos;
|
private int mPos;
|
||||||
@@ -113,8 +112,7 @@ public class EntryActivity extends LockCloseActivity {
|
|||||||
mEntry = db.entries.get(uuid).get();
|
mEntry = db.entries.get(uuid).get();
|
||||||
|
|
||||||
// Update last access time.
|
// Update last access time.
|
||||||
Calendar cal = Calendar.getInstance();
|
mEntry.stampLastAccess();
|
||||||
mEntry.tLastAccess = new PwDate(cal.getTime());
|
|
||||||
|
|
||||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
mShowPassword = ! prefs.getBoolean(getString(R.string.maskpass_key), getResources().getBoolean(R.bool.maskpass_default));
|
mShowPassword = ! prefs.getBoolean(getString(R.string.maskpass_key), getResources().getBoolean(R.bool.maskpass_default));
|
||||||
@@ -152,9 +150,9 @@ public class EntryActivity extends LockCloseActivity {
|
|||||||
String action = intent.getAction();
|
String action = intent.getAction();
|
||||||
|
|
||||||
if ( action.equals(Intents.COPY_USERNAME) ) {
|
if ( action.equals(Intents.COPY_USERNAME) ) {
|
||||||
String username = mEntry.username;
|
String username = mEntry.getUsername();
|
||||||
if ( username.length() > 0 ) {
|
if ( username.length() > 0 ) {
|
||||||
timeoutCopyToClipboard(mEntry.username);
|
timeoutCopyToClipboard(username);
|
||||||
}
|
}
|
||||||
} else if ( action.equals(Intents.COPY_PASSWORD) ) {
|
} else if ( action.equals(Intents.COPY_PASSWORD) ) {
|
||||||
String password = new String(mEntry.getPassword());
|
String password = new String(mEntry.getPassword());
|
||||||
@@ -199,20 +197,21 @@ public class EntryActivity extends LockCloseActivity {
|
|||||||
|
|
||||||
private void fillData() {
|
private void fillData() {
|
||||||
populateText(R.id.entry_title, mEntry.title);
|
populateText(R.id.entry_title, mEntry.title);
|
||||||
populateText(R.id.entry_user_name, mEntry.username);
|
populateText(R.id.entry_user_name, mEntry.getUsername());
|
||||||
populateText(R.id.entry_url, mEntry.url);
|
populateText(R.id.entry_url, mEntry.url);
|
||||||
populateText(R.id.entry_password, new String(mEntry.getPassword()));
|
populateText(R.id.entry_password, mEntry.getPassword());
|
||||||
setPasswordStyle();
|
setPasswordStyle();
|
||||||
|
|
||||||
DateFormat df = DateFormat.getInstance();
|
DateFormat df = DateFormat.getInstance();
|
||||||
populateText(R.id.entry_created, df.format(mEntry.tCreation.getJDate()));
|
populateText(R.id.entry_created, df.format(mEntry.getCreate()));
|
||||||
populateText(R.id.entry_modified, df.format(mEntry.tLastMod.getJDate()));
|
populateText(R.id.entry_modified, df.format(mEntry.getMod()));
|
||||||
populateText(R.id.entry_accessed, df.format(mEntry.tLastAccess.getJDate()));
|
populateText(R.id.entry_accessed, df.format(mEntry.getAccess()));
|
||||||
|
|
||||||
if ( PwEntryV3.IsNever(mEntry.tExpire.getJDate()) ) {
|
Date expires = mEntry.getExpire();
|
||||||
|
if ( PwEntryV3.IsNever(expires) ) {
|
||||||
populateText(R.id.entry_expires, R.string.never);
|
populateText(R.id.entry_expires, R.string.never);
|
||||||
} else {
|
} else {
|
||||||
populateText(R.id.entry_expires, df.format(mEntry.tExpire.getJDate()));
|
populateText(R.id.entry_expires, df.format(expires));
|
||||||
}
|
}
|
||||||
populateText(R.id.entry_comment, mEntry.additional);
|
populateText(R.id.entry_comment, mEntry.additional);
|
||||||
|
|
||||||
@@ -317,7 +316,7 @@ public class EntryActivity extends LockCloseActivity {
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
case MENU_COPY_USER:
|
case MENU_COPY_USER:
|
||||||
timeoutCopyToClipboard(mEntry.username);
|
timeoutCopyToClipboard(mEntry.getUsername());
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case MENU_COPY_PASS:
|
case MENU_COPY_PASS:
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import java.util.Calendar;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.ActivityNotFoundException;
|
import android.content.ActivityNotFoundException;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -42,7 +41,9 @@ import com.android.keepass.KeePass;
|
|||||||
import com.android.keepass.R;
|
import com.android.keepass.R;
|
||||||
import com.keepassdroid.app.App;
|
import com.keepassdroid.app.App;
|
||||||
import com.keepassdroid.database.PwDate;
|
import com.keepassdroid.database.PwDate;
|
||||||
|
import com.keepassdroid.database.PwEntry;
|
||||||
import com.keepassdroid.database.PwEntryV3;
|
import com.keepassdroid.database.PwEntryV3;
|
||||||
|
import com.keepassdroid.database.PwGroup;
|
||||||
import com.keepassdroid.database.PwGroupV3;
|
import com.keepassdroid.database.PwGroupV3;
|
||||||
import com.keepassdroid.database.edit.AddEntry;
|
import com.keepassdroid.database.edit.AddEntry;
|
||||||
import com.keepassdroid.database.edit.OnFinish;
|
import com.keepassdroid.database.edit.OnFinish;
|
||||||
@@ -62,7 +63,11 @@ public class EntryEditActivity extends LockCloseActivity {
|
|||||||
private boolean mShowPassword = false;
|
private boolean mShowPassword = false;
|
||||||
private boolean mIsNew;
|
private boolean mIsNew;
|
||||||
|
|
||||||
public static void Launch(Activity act, PwEntryV3 pw) {
|
public static void Launch(Activity act, PwEntry pw) {
|
||||||
|
if ( !(pw instanceof PwEntryV3) ) {
|
||||||
|
throw new RuntimeException("Not yet implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
Intent i = new Intent(act, EntryEditActivity.class);
|
Intent i = new Intent(act, EntryEditActivity.class);
|
||||||
|
|
||||||
i.putExtra(KEY_ENTRY, pw.uuid);
|
i.putExtra(KEY_ENTRY, pw.uuid);
|
||||||
@@ -70,9 +75,14 @@ public class EntryEditActivity extends LockCloseActivity {
|
|||||||
act.startActivityForResult(i, 0);
|
act.startActivityForResult(i, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Launch(Activity act, PwGroupV3 parent) {
|
public static void Launch(Activity act, PwGroup pw) {
|
||||||
|
if ( !(pw instanceof PwGroupV3) ) {
|
||||||
|
throw new RuntimeException("Not yet implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
Intent i = new Intent(act, EntryEditActivity.class);
|
Intent i = new Intent(act, EntryEditActivity.class);
|
||||||
|
|
||||||
|
PwGroupV3 parent = (PwGroupV3) pw;
|
||||||
i.putExtra(KEY_PARENT, parent.groupId);
|
i.putExtra(KEY_PARENT, parent.groupId);
|
||||||
|
|
||||||
act.startActivityForResult(i, 0);
|
act.startActivityForResult(i, 0);
|
||||||
@@ -105,7 +115,7 @@ public class EntryEditActivity extends LockCloseActivity {
|
|||||||
UUID uuid = Types.bytestoUUID(uuidBytes);
|
UUID uuid = Types.bytestoUUID(uuidBytes);
|
||||||
assert(uuid != null);
|
assert(uuid != null);
|
||||||
|
|
||||||
mEntry = db.entries.get(uuid).get();
|
mEntry = (PwEntryV3) db.entries.get(uuid).get();
|
||||||
mIsNew = false;
|
mIsNew = false;
|
||||||
|
|
||||||
fillData();
|
fillData();
|
||||||
@@ -179,7 +189,7 @@ public class EntryEditActivity extends LockCloseActivity {
|
|||||||
OnFinish onFinish = act.new AfterSave(new Handler());
|
OnFinish onFinish = act.new AfterSave(new Handler());
|
||||||
|
|
||||||
if ( mIsNew ) {
|
if ( mIsNew ) {
|
||||||
task = new AddEntry(App.getDB(), newEntry, onFinish);
|
task = AddEntry.getInstance(App.getDB(), newEntry, onFinish);
|
||||||
} else {
|
} else {
|
||||||
task = new UpdateEntry(App.getDB(), mEntry, newEntry, onFinish);
|
task = new UpdateEntry(App.getDB(), mEntry, newEntry, onFinish);
|
||||||
}
|
}
|
||||||
@@ -259,7 +269,7 @@ public class EntryEditActivity extends LockCloseActivity {
|
|||||||
|
|
||||||
private void fillData() {
|
private void fillData() {
|
||||||
populateText(R.id.entry_title, mEntry.title);
|
populateText(R.id.entry_title, mEntry.title);
|
||||||
populateText(R.id.entry_user_name, mEntry.username);
|
populateText(R.id.entry_user_name, mEntry.getUsername());
|
||||||
populateText(R.id.entry_url, mEntry.url);
|
populateText(R.id.entry_url, mEntry.url);
|
||||||
|
|
||||||
String password = new String(mEntry.getPassword());
|
String password = new String(mEntry.getPassword());
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ package com.keepassdroid;
|
|||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
@@ -39,10 +38,15 @@ import android.widget.AdapterView.AdapterContextMenuInfo;
|
|||||||
import com.android.keepass.KeePass;
|
import com.android.keepass.KeePass;
|
||||||
import com.android.keepass.R;
|
import com.android.keepass.R;
|
||||||
import com.keepassdroid.app.App;
|
import com.keepassdroid.app.App;
|
||||||
|
import com.keepassdroid.database.PwDatabase;
|
||||||
|
import com.keepassdroid.database.PwDatabaseV3;
|
||||||
|
import com.keepassdroid.database.PwDatabaseV4;
|
||||||
|
import com.keepassdroid.database.PwGroup;
|
||||||
|
import com.keepassdroid.database.PwGroupId;
|
||||||
import com.keepassdroid.database.PwGroupV3;
|
import com.keepassdroid.database.PwGroupV3;
|
||||||
import com.keepassdroid.database.edit.AddGroup;
|
import com.keepassdroid.database.edit.AddGroup;
|
||||||
|
|
||||||
public class GroupActivity extends GroupBaseActivity {
|
public abstract class GroupActivity extends GroupBaseActivity {
|
||||||
|
|
||||||
public static final int UNINIT = -1;
|
public static final int UNINIT = -1;
|
||||||
public static final int VIEW_ONLY = 0;
|
public static final int VIEW_ONLY = 0;
|
||||||
@@ -50,11 +54,22 @@ public class GroupActivity extends GroupBaseActivity {
|
|||||||
public static final int FULL = 2;
|
public static final int FULL = 2;
|
||||||
private static final String TAG = "Group Activity:";
|
private static final String TAG = "Group Activity:";
|
||||||
|
|
||||||
public static void Launch(Activity act, PwGroupV3 group, int mode) {
|
public static void Launch(Activity act, PwGroup group, int mode) {
|
||||||
Intent i = new Intent(act, GroupActivity.class);
|
Intent i;
|
||||||
|
|
||||||
if ( group != null ) {
|
PwDatabase pm = App.getDB().pm;
|
||||||
i.putExtra(KEY_ENTRY, group.groupId);
|
if ( pm instanceof PwDatabaseV3 ) {
|
||||||
|
i = new Intent(act, GroupActivityV3.class);
|
||||||
|
|
||||||
|
if ( group != null ) {
|
||||||
|
PwGroupV3 g = (PwGroupV3) group;
|
||||||
|
i.putExtra(KEY_ENTRY, g.groupId);
|
||||||
|
}
|
||||||
|
} else if ( pm instanceof PwDatabaseV4 ) {
|
||||||
|
throw new RuntimeException("Not yet implemented.");
|
||||||
|
} else {
|
||||||
|
assert(true); // Should never be reached
|
||||||
|
throw new RuntimeException("Should never be reached.");
|
||||||
}
|
}
|
||||||
|
|
||||||
i.putExtra(KEY_MODE, mode);
|
i.putExtra(KEY_MODE, mode);
|
||||||
@@ -62,6 +77,9 @@ public class GroupActivity extends GroupBaseActivity {
|
|||||||
act.startActivityForResult(i,0);
|
act.startActivityForResult(i,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract PwGroupId retrieveGroupId(Intent i);
|
||||||
|
protected abstract PwGroup getGroup();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
@@ -89,13 +107,13 @@ public class GroupActivity extends GroupBaseActivity {
|
|||||||
}
|
}
|
||||||
Log.w(TAG, "Set view");
|
Log.w(TAG, "Set view");
|
||||||
|
|
||||||
int id = intent.getIntExtra(KEY_ENTRY, -1);
|
PwGroupId id = retrieveGroupId(intent);
|
||||||
|
|
||||||
Database db = App.getDB();
|
Database db = App.getDB();
|
||||||
if ( id == -1 ) {
|
if ( id == null ) {
|
||||||
mGroup = db.root;
|
mGroup = db.root;
|
||||||
} else {
|
} else {
|
||||||
WeakReference<PwGroupV3> wPw = db.groups.get(id);
|
WeakReference<PwGroup> wPw = db.groups.get(id);
|
||||||
mGroup = wPw.get();
|
mGroup = wPw.get();
|
||||||
}
|
}
|
||||||
Log.w(TAG, "Retrieved group");
|
Log.w(TAG, "Retrieved group");
|
||||||
@@ -104,7 +122,6 @@ public class GroupActivity extends GroupBaseActivity {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if ( mode == FULL || mode == ADD_GROUP_ONLY ) {
|
if ( mode == FULL || mode == ADD_GROUP_ONLY ) {
|
||||||
// Add Group button
|
// Add Group button
|
||||||
@@ -155,10 +172,10 @@ public class GroupActivity extends GroupBaseActivity {
|
|||||||
|
|
||||||
private class GroupAddHandler implements View.OnClickListener {
|
private class GroupAddHandler implements View.OnClickListener {
|
||||||
private GroupBaseActivity mAct;
|
private GroupBaseActivity mAct;
|
||||||
private PwGroupV3 mGroup;
|
private PwGroup mGroup;
|
||||||
private GroupCreateDialog mDialog;
|
private GroupCreateDialog mDialog;
|
||||||
|
|
||||||
GroupAddHandler(GroupBaseActivity act, PwGroupV3 group) {
|
GroupAddHandler(GroupBaseActivity act, PwGroup group) {
|
||||||
mAct = act;
|
mAct = act;
|
||||||
mGroup = group;
|
mGroup = group;
|
||||||
}
|
}
|
||||||
@@ -178,7 +195,7 @@ public class GroupActivity extends GroupBaseActivity {
|
|||||||
if ( ! mDialog.canceled() && res.length() > 0 ) {
|
if ( ! mDialog.canceled() && res.length() > 0 ) {
|
||||||
GroupActivity act = GroupActivity.this;
|
GroupActivity act = GroupActivity.this;
|
||||||
Handler handler = new Handler();
|
Handler handler = new Handler();
|
||||||
AddGroup task = new AddGroup(App.getDB(), res, mGroup, act.new RefreshTask(handler), false);
|
AddGroup task = AddGroup.getInstance(App.getDB(), res, mGroup, act.new RefreshTask(handler), false);
|
||||||
ProgressTask pt = new ProgressTask(act, task, R.string.saving_database);
|
ProgressTask pt = new ProgressTask(act, task, R.string.saving_database);
|
||||||
pt.run();
|
pt.run();
|
||||||
}
|
}
|
||||||
|
|||||||
28
src/com/keepassdroid/GroupActivityV3.java
Normal file
28
src/com/keepassdroid/GroupActivityV3.java
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package com.keepassdroid;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
|
||||||
|
import com.keepassdroid.database.PwGroupIdV3;
|
||||||
|
import com.keepassdroid.database.PwGroupV3;
|
||||||
|
|
||||||
|
public class GroupActivityV3 extends GroupActivity {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PwGroupV3 getGroup() {
|
||||||
|
|
||||||
|
return (PwGroupV3) mGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PwGroupIdV3 retrieveGroupId(Intent i) {
|
||||||
|
int id = i.getIntExtra(KEY_ENTRY, -1);
|
||||||
|
|
||||||
|
if ( id == -1 ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PwGroupIdV3(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -20,9 +20,7 @@
|
|||||||
package com.keepassdroid;
|
package com.keepassdroid;
|
||||||
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.ActivityNotFoundException;
|
import android.content.ActivityNotFoundException;
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
@@ -37,7 +35,7 @@ import android.widget.Toast;
|
|||||||
import com.android.keepass.KeePass;
|
import com.android.keepass.KeePass;
|
||||||
import com.android.keepass.R;
|
import com.android.keepass.R;
|
||||||
import com.keepassdroid.app.App;
|
import com.keepassdroid.app.App;
|
||||||
import com.keepassdroid.database.PwGroupV3;
|
import com.keepassdroid.database.PwGroup;
|
||||||
import com.keepassdroid.database.edit.OnFinish;
|
import com.keepassdroid.database.edit.OnFinish;
|
||||||
import com.keepassdroid.settings.AppSettingsActivity;
|
import com.keepassdroid.settings.AppSettingsActivity;
|
||||||
import com.keepassdroid.utils.Util;
|
import com.keepassdroid.utils.Util;
|
||||||
@@ -52,9 +50,10 @@ public abstract class GroupBaseActivity extends LockCloseListActivity {
|
|||||||
protected static final int MENU_CHANGE_MASTER_KEY = Menu.FIRST + 3;
|
protected static final int MENU_CHANGE_MASTER_KEY = Menu.FIRST + 3;
|
||||||
protected static final int MENU_APP_SETTINGS = Menu.FIRST + 4;
|
protected static final int MENU_APP_SETTINGS = Menu.FIRST + 4;
|
||||||
|
|
||||||
protected PwGroupV3 mGroup;
|
protected PwGroup mGroup;
|
||||||
|
|
||||||
public static void Launch(Activity act, PwGroupV3 group) {
|
/*
|
||||||
|
public static void Launch(Activity act, PwGroup group) {
|
||||||
Intent i = new Intent(act, GroupActivity.class);
|
Intent i = new Intent(act, GroupActivity.class);
|
||||||
|
|
||||||
if ( group != null ) {
|
if ( group != null ) {
|
||||||
@@ -63,6 +62,7 @@ public abstract class GroupBaseActivity extends LockCloseListActivity {
|
|||||||
|
|
||||||
act.startActivityForResult(i,0);
|
act.startActivityForResult(i,0);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
@@ -117,7 +117,7 @@ public abstract class GroupBaseActivity extends LockCloseListActivity {
|
|||||||
|
|
||||||
protected void setGroupTitle() {
|
protected void setGroupTitle() {
|
||||||
if ( mGroup != null ) {
|
if ( mGroup != null ) {
|
||||||
String name = mGroup.name;
|
String name = mGroup.getName();
|
||||||
if ( name != null && name.length() > 0 ) {
|
if ( name != null && name.length() > 0 ) {
|
||||||
TextView tv = (TextView) findViewById(R.id.group_name);
|
TextView tv = (TextView) findViewById(R.id.group_name);
|
||||||
if ( tv != null ) {
|
if ( tv != null ) {
|
||||||
|
|||||||
@@ -30,21 +30,21 @@ import android.widget.TextView;
|
|||||||
|
|
||||||
import com.android.keepass.R;
|
import com.android.keepass.R;
|
||||||
import com.keepassdroid.app.App;
|
import com.keepassdroid.app.App;
|
||||||
import com.keepassdroid.database.PwEntryV3;
|
import com.keepassdroid.database.PwEntry;
|
||||||
import com.keepassdroid.database.edit.DeleteEntry;
|
import com.keepassdroid.database.edit.DeleteEntry;
|
||||||
import com.keepassdroid.settings.PrefsUtil;
|
import com.keepassdroid.settings.PrefsUtil;
|
||||||
|
|
||||||
public class PwEntryView extends ClickView {
|
public class PwEntryView extends ClickView {
|
||||||
|
|
||||||
private GroupBaseActivity mAct;
|
private GroupBaseActivity mAct;
|
||||||
private PwEntryV3 mPw;
|
private PwEntry mPw;
|
||||||
private TextView mTv;
|
private TextView mTv;
|
||||||
private int mPos;
|
private int mPos;
|
||||||
|
|
||||||
private static final int MENU_OPEN = Menu.FIRST;
|
private static final int MENU_OPEN = Menu.FIRST;
|
||||||
private static final int MENU_DELETE = Menu.FIRST + 1;
|
private static final int MENU_DELETE = Menu.FIRST + 1;
|
||||||
|
|
||||||
public PwEntryView(GroupBaseActivity act, PwEntryV3 pw, int pos) {
|
public PwEntryView(GroupBaseActivity act, PwEntry pw, int pos) {
|
||||||
super(act);
|
super(act);
|
||||||
mAct = act;
|
mAct = act;
|
||||||
mPw = pw;
|
mPw = pw;
|
||||||
|
|||||||
@@ -21,14 +21,15 @@ package com.keepassdroid;
|
|||||||
|
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
|
|
||||||
import com.keepassdroid.database.PwEntryV3;
|
|
||||||
import com.keepassdroid.database.PwGroupV3;
|
|
||||||
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.BaseAdapter;
|
import android.widget.BaseAdapter;
|
||||||
|
|
||||||
|
import com.keepassdroid.database.PwEntry;
|
||||||
|
import com.keepassdroid.database.PwEntryV3;
|
||||||
|
import com.keepassdroid.database.PwGroup;
|
||||||
|
import com.keepassdroid.database.PwGroupV3;
|
||||||
|
|
||||||
public class PwListAdapter extends BaseAdapter {
|
public class PwListAdapter extends BaseAdapter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -46,10 +47,10 @@ public class PwListAdapter extends BaseAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private GroupBaseActivity mAct;
|
private GroupBaseActivity mAct;
|
||||||
private PwGroupV3 mGroup;
|
private PwGroup mGroup;
|
||||||
private Vector<PwEntryV3> filteredEntries;
|
private Vector<PwEntry> filteredEntries;
|
||||||
|
|
||||||
public PwListAdapter(GroupBaseActivity act, PwGroupV3 group) {
|
public PwListAdapter(GroupBaseActivity act, PwGroup group) {
|
||||||
mAct = act;
|
mAct = act;
|
||||||
mGroup = group;
|
mGroup = group;
|
||||||
|
|
||||||
@@ -58,7 +59,7 @@ public class PwListAdapter extends BaseAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void filter() {
|
private void filter() {
|
||||||
filteredEntries = new Vector<PwEntryV3>();
|
filteredEntries = new Vector<PwEntry>();
|
||||||
|
|
||||||
for (int i = 0; i < mGroup.childEntries.size(); i++) {
|
for (int i = 0; i < mGroup.childEntries.size(); i++) {
|
||||||
PwEntryV3 entry = (PwEntryV3) mGroup.childEntries.elementAt(i);
|
PwEntryV3 entry = (PwEntryV3) mGroup.childEntries.elementAt(i);
|
||||||
|
|||||||
@@ -137,7 +137,6 @@ public class NativeAESCipherSpi extends CipherSpi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int doFinal(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) {
|
private int doFinal(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) {
|
||||||
mBuffered = 0;
|
|
||||||
|
|
||||||
int outputSize = engineGetOutputSize(inputLen);
|
int outputSize = engineGetOutputSize(inputLen);
|
||||||
|
|
||||||
@@ -145,7 +144,11 @@ public class NativeAESCipherSpi extends CipherSpi {
|
|||||||
|
|
||||||
int finalAmt = nativeDoFinal(mCtxPtr, output, outputOffset + updateAmt, outputSize - updateAmt);
|
int finalAmt = nativeDoFinal(mCtxPtr, output, outputOffset + updateAmt, outputSize - updateAmt);
|
||||||
|
|
||||||
return updateAmt + finalAmt;
|
int out = updateAmt + finalAmt;
|
||||||
|
|
||||||
|
mBuffered = 0;
|
||||||
|
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
private native int nativeDoFinal(long ctxPtr, byte[] output, int outputOffest, int outputSize);
|
private native int nativeDoFinal(long ctxPtr, byte[] output, int outputOffest, int outputSize);
|
||||||
@@ -163,10 +166,12 @@ public class NativeAESCipherSpi extends CipherSpi {
|
|||||||
@Override
|
@Override
|
||||||
protected int engineGetOutputSize(int inputLen) {
|
protected int engineGetOutputSize(int inputLen) {
|
||||||
int totalLen = mBuffered + inputLen;
|
int totalLen = mBuffered + inputLen;
|
||||||
|
|
||||||
|
/*
|
||||||
if ( ! mPadding || ! mEncrypting ) {
|
if ( ! mPadding || ! mEncrypting ) {
|
||||||
return totalLen;
|
return totalLen;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
int padLen = AES_BLOCK_SIZE - (totalLen % AES_BLOCK_SIZE);
|
int padLen = AES_BLOCK_SIZE - (totalLen % AES_BLOCK_SIZE);
|
||||||
|
|
||||||
@@ -299,8 +304,15 @@ public class NativeAESCipherSpi extends CipherSpi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int update(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) {
|
int update(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) {
|
||||||
mBuffered = (mBuffered + inputLen) % AES_BLOCK_SIZE;
|
int outputSize = engineGetOutputSize(inputLen);
|
||||||
return nativeUpdate(mCtxPtr, input, inputOffset, inputLen, output, outputOffset, engineGetOutputSize(inputLen));
|
|
||||||
|
int out = nativeUpdate(mCtxPtr, input, inputOffset, inputLen, output, outputOffset, outputSize);
|
||||||
|
|
||||||
|
mBuffered = (mBuffered + ((inputLen - out))) % AES_BLOCK_SIZE;
|
||||||
|
|
||||||
|
return out;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private native int nativeUpdate(long ctxPtr, byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset, int outputSize);
|
private native int nativeUpdate(long ctxPtr, byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset, int outputSize);
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import java.io.UnsupportedEncodingException;
|
|||||||
import java.security.DigestOutputStream;
|
import java.security.DigestOutputStream;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
import com.keepassdroid.crypto.finalkey.FinalKey;
|
import com.keepassdroid.crypto.finalkey.FinalKey;
|
||||||
import com.keepassdroid.crypto.finalkey.FinalKeyFactory;
|
import com.keepassdroid.crypto.finalkey.FinalKeyFactory;
|
||||||
@@ -37,7 +38,7 @@ public abstract class PwDatabase {
|
|||||||
|
|
||||||
public byte masterKey[] = new byte[32];
|
public byte masterKey[] = new byte[32];
|
||||||
public byte[] finalKey;
|
public byte[] finalKey;
|
||||||
|
|
||||||
public void makeFinalKey(byte[] masterSeed, byte[] masterSeed2, int numRounds) throws IOException {
|
public void makeFinalKey(byte[] masterSeed, byte[] masterSeed2, int numRounds) throws IOException {
|
||||||
|
|
||||||
// Write checksum Checksum
|
// Write checksum Checksum
|
||||||
@@ -203,4 +204,14 @@ public abstract class PwDatabase {
|
|||||||
|
|
||||||
public abstract byte[] getPasswordKey(String key) throws IOException;
|
public abstract byte[] getPasswordKey(String key) throws IOException;
|
||||||
|
|
||||||
|
public abstract Vector<PwGroup> getGrpRoots();
|
||||||
|
|
||||||
|
public abstract Vector<PwGroup> getGroups();
|
||||||
|
|
||||||
|
public abstract Vector<PwEntry> getEntries();
|
||||||
|
|
||||||
|
public abstract long getNumRounds();
|
||||||
|
|
||||||
|
public abstract void setNumRonuds(long rounds) throws NumberFormatException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,12 +52,12 @@ public class PwDatabaseV3 extends PwDatabase {
|
|||||||
public String name = "KeePass database";
|
public String name = "KeePass database";
|
||||||
|
|
||||||
// Special entry for settings
|
// Special entry for settings
|
||||||
public PwEntryV3 metaInfo;
|
public PwEntry metaInfo;
|
||||||
|
|
||||||
// all entries
|
// all entries
|
||||||
public Vector<PwEntryV3> entries = new Vector<PwEntryV3>();
|
public Vector<PwEntry> entries = new Vector<PwEntry>();
|
||||||
// all groups
|
// all groups
|
||||||
public Vector<PwGroupV3> groups = new Vector<PwGroupV3>();
|
private Vector<PwGroup> groups = new Vector<PwGroup>();
|
||||||
// Algorithm used to encrypt the database
|
// Algorithm used to encrypt the database
|
||||||
public int algorithm;
|
public int algorithm;
|
||||||
public int numKeyEncRounds;
|
public int numKeyEncRounds;
|
||||||
@@ -74,12 +74,28 @@ public class PwDatabaseV3 extends PwDatabase {
|
|||||||
public int getNumKeyEncRecords() {
|
public int getNumKeyEncRecords() {
|
||||||
return numKeyEncRounds;
|
return numKeyEncRounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vector<PwGroup> getGroups() {
|
||||||
|
return groups;
|
||||||
|
}
|
||||||
|
|
||||||
public Vector<PwGroupV3> getGrpRoots() {
|
@Override
|
||||||
|
public Vector<PwEntry> getEntries() {
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setGroups(Vector<PwGroup> grp) {
|
||||||
|
groups = grp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vector<PwGroup> getGrpRoots() {
|
||||||
int target = 0;
|
int target = 0;
|
||||||
Vector<PwGroupV3> kids = new Vector<PwGroupV3>();
|
Vector<PwGroup> kids = new Vector<PwGroup>();
|
||||||
for( int i=0; i < groups.size(); i++ ) {
|
for( int i=0; i < groups.size(); i++ ) {
|
||||||
PwGroupV3 grp = groups.elementAt( i );
|
PwGroupV3 grp = (PwGroupV3) groups.elementAt( i );
|
||||||
if( grp.level == target )
|
if( grp.level == target )
|
||||||
kids.addElement( grp );
|
kids.addElement( grp );
|
||||||
}
|
}
|
||||||
@@ -88,7 +104,7 @@ public class PwDatabaseV3 extends PwDatabase {
|
|||||||
|
|
||||||
public int getRootGroupId() {
|
public int getRootGroupId() {
|
||||||
for ( int i = 0; i < groups.size(); i++ ) {
|
for ( int i = 0; i < groups.size(); i++ ) {
|
||||||
PwGroupV3 grp = groups.elementAt(i);
|
PwGroupV3 grp = (PwGroupV3) groups.elementAt(i);
|
||||||
if ( grp.level == 0 ) {
|
if ( grp.level == 0 ) {
|
||||||
return grp.groupId;
|
return grp.groupId;
|
||||||
}
|
}
|
||||||
@@ -97,35 +113,34 @@ public class PwDatabaseV3 extends PwDatabase {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector<PwGroupV3> getGrpChildren( PwGroupV3 parent ) {
|
public Vector<PwGroup> getGrpChildren(PwGroupV3 parent) {
|
||||||
int idx = groups.indexOf( parent );
|
int idx = groups.indexOf(parent);
|
||||||
int target = parent.level + 1;
|
int target = parent.level + 1;
|
||||||
Vector<PwGroupV3> kids = new Vector<PwGroupV3>();
|
Vector<PwGroup> kids = new Vector<PwGroup>();
|
||||||
while( ++idx < groups.size() ) {
|
while (++idx < groups.size()) {
|
||||||
PwGroupV3 grp = groups.elementAt( idx );
|
PwGroupV3 grp = (PwGroupV3) groups.elementAt(idx);
|
||||||
if( grp.level < target )
|
if (grp.level < target)
|
||||||
break;
|
break;
|
||||||
else
|
else if (grp.level == target)
|
||||||
if( grp.level == target )
|
kids.addElement(grp);
|
||||||
kids.addElement( grp );
|
}
|
||||||
|
return kids;
|
||||||
}
|
}
|
||||||
return kids;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vector<PwEntryV3> getEntries( PwGroupV3 parent ) {
|
public Vector<PwEntry> getEntries(PwGroupV3 parent) {
|
||||||
Vector<PwEntryV3> kids = new Vector<PwEntryV3>();
|
Vector<PwEntry> kids = new Vector<PwEntry>();
|
||||||
/*for( Iterator i = entries.iterator(); i.hasNext(); ) {
|
/*
|
||||||
PwEntryV3 ent = (PwEntryV3)i.next();
|
* for( Iterator i = entries.iterator(); i.hasNext(); ) { PwEntryV3 ent
|
||||||
if( ent.groupId == parent.groupId )
|
* = (PwEntryV3)i.next(); if( ent.groupId == parent.groupId ) kids.add(
|
||||||
kids.add( ent );
|
* ent ); }
|
||||||
}*/
|
*/
|
||||||
for (int i=0; i<entries.size(); i++) {
|
for (int i = 0; i < entries.size(); i++) {
|
||||||
PwEntryV3 ent = entries.elementAt(i);
|
PwEntryV3 ent = (PwEntryV3) entries.elementAt(i);
|
||||||
if( ent.groupId == parent.groupId )
|
if (ent.groupId == parent.groupId)
|
||||||
kids.addElement( ent );
|
kids.addElement(ent);
|
||||||
|
}
|
||||||
|
return kids;
|
||||||
}
|
}
|
||||||
return kids;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return name;
|
return name;
|
||||||
@@ -149,30 +164,33 @@ public class PwDatabaseV3 extends PwDatabase {
|
|||||||
if (currentGroup == null) {
|
if (currentGroup == null) {
|
||||||
rootGroup = new PwGroupV3();
|
rootGroup = new PwGroupV3();
|
||||||
|
|
||||||
Vector<PwGroupV3> rootChildGroups = getGrpRoots();
|
Vector<PwGroup> rootChildGroups = getGrpRoots();
|
||||||
rootGroup.childGroups = rootChildGroups;
|
rootGroup.setGroups(rootChildGroups);
|
||||||
rootGroup.childEntries = new Vector<PwEntryV3>();
|
rootGroup.childEntries = new Vector<PwEntry>();
|
||||||
rootGroup.level = -1;
|
rootGroup.level = -1;
|
||||||
for (int i=0; i<rootChildGroups.size(); i++) {
|
for (int i=0; i<rootChildGroups.size(); i++) {
|
||||||
rootChildGroups.elementAt(i).parent = rootGroup;
|
PwGroupV3 grp = (PwGroupV3) rootChildGroups.elementAt(i);
|
||||||
constructTree(rootChildGroups.elementAt(i));
|
grp.parent = rootGroup;
|
||||||
|
constructTree(grp);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// I'm in non-root
|
// I'm in non-root
|
||||||
// get child groups
|
// get child groups
|
||||||
currentGroup.childGroups = getGrpChildren(currentGroup);
|
currentGroup.setGroups(getGrpChildren(currentGroup));
|
||||||
currentGroup.childEntries = getEntries(currentGroup);
|
currentGroup.childEntries = getEntries(currentGroup);
|
||||||
|
|
||||||
// set parent in child entries
|
// set parent in child entries
|
||||||
for (int i=0; i<currentGroup.childEntries.size(); i++) {
|
for (int i=0; i<currentGroup.childEntries.size(); i++) {
|
||||||
currentGroup.childEntries.elementAt(i).parent = currentGroup;
|
PwEntryV3 entry = (PwEntryV3) currentGroup.childEntries.elementAt(i);
|
||||||
|
entry.parent = currentGroup;
|
||||||
}
|
}
|
||||||
// recursively construct child groups
|
// recursively construct child groups
|
||||||
for (int i=0; i<currentGroup.childGroups.size(); i++) {
|
for (int i=0; i<currentGroup.childGroups.size(); i++) {
|
||||||
currentGroup.childGroups.elementAt(i).parent = currentGroup;
|
PwGroupV3 grp = (PwGroupV3) currentGroup.childGroups.elementAt(i);
|
||||||
constructTree(currentGroup.childGroups.elementAt(i));
|
grp.parent = currentGroup;
|
||||||
|
constructTree((PwGroupV3) currentGroup.childGroups.elementAt(i));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -194,8 +212,8 @@ public class PwDatabaseV3 extends PwDatabase {
|
|||||||
|
|
||||||
group.level = parent.level + 1;
|
group.level = parent.level + 1;
|
||||||
|
|
||||||
group.childEntries = new Vector<PwEntryV3>();
|
group.childEntries = new Vector<PwEntry>();
|
||||||
group.childGroups = new Vector<PwGroupV3>();
|
group.setGroups(new Vector<PwGroup>());
|
||||||
|
|
||||||
// Add group PwDatabaseV3 and Parent
|
// Add group PwDatabaseV3 and Parent
|
||||||
parent.childGroups.add(group);
|
parent.childGroups.add(group);
|
||||||
@@ -235,7 +253,8 @@ public class PwDatabaseV3 extends PwDatabase {
|
|||||||
*/
|
*/
|
||||||
private boolean isGroupIdUsed(int id) {
|
private boolean isGroupIdUsed(int id) {
|
||||||
for ( int i = 0; i < groups.size(); i++ ) {
|
for ( int i = 0; i < groups.size(); i++ ) {
|
||||||
if ( groups.get(i).groupId == id ) {
|
PwGroupV3 group = (PwGroupV3) groups.get(i);
|
||||||
|
if ( group.groupId == id ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -263,4 +282,19 @@ public class PwDatabaseV3 extends PwDatabase {
|
|||||||
return getPasswordKey(key, "ISO-8859-1");
|
return getPasswordKey(key, "ISO-8859-1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getNumRounds() {
|
||||||
|
return numKeyEncRounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setNumRonuds(long rounds) throws NumberFormatException {
|
||||||
|
if ( rounds > Integer.MAX_VALUE || rounds < Integer.MIN_VALUE ) {
|
||||||
|
throw new NumberFormatException();
|
||||||
|
}
|
||||||
|
|
||||||
|
numKeyEncRounds = (int) rounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,13 @@ import java.io.IOException;
|
|||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
|
import com.keepassdroid.database.exception.InconsistentDBException;
|
||||||
import com.keepassdroid.database.exception.InvalidKeyFileException;
|
import com.keepassdroid.database.exception.InvalidKeyFileException;
|
||||||
|
|
||||||
|
|
||||||
@@ -32,7 +38,11 @@ public class PwDatabaseV4 extends PwDatabase {
|
|||||||
public UUID dataCipher;
|
public UUID dataCipher;
|
||||||
public PwCompressionAlgorithm compressionAlgorithm;
|
public PwCompressionAlgorithm compressionAlgorithm;
|
||||||
public long numKeyEncRounds;
|
public long numKeyEncRounds;
|
||||||
|
private Document doc;
|
||||||
|
|
||||||
|
//private Vector<PwGroupV4> groups = new Vector<PwGroupV4>();
|
||||||
|
private PwGroupV4 rootGroup;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] getMasterKey(String key, String keyFileName)
|
public byte[] getMasterKey(String key, String keyFileName)
|
||||||
throws InvalidKeyFileException, IOException {
|
throws InvalidKeyFileException, IOException {
|
||||||
@@ -65,4 +75,51 @@ public class PwDatabaseV4 extends PwDatabase {
|
|||||||
return getPasswordKey(key, "UTF-8");
|
return getPasswordKey(key, "UTF-8");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vector<PwGroup> getGroups() {
|
||||||
|
Vector<PwGroup> list = new Vector<PwGroup>();
|
||||||
|
rootGroup.buildChildGroupsRecursive(list);
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parseDB(Document d) throws InconsistentDBException {
|
||||||
|
doc = d;
|
||||||
|
|
||||||
|
NodeList list = doc.getElementsByTagName("Root");
|
||||||
|
|
||||||
|
int len = list.getLength();
|
||||||
|
if ( len < 0 || len > 1 ) {
|
||||||
|
throw new InconsistentDBException("Missing root node");
|
||||||
|
}
|
||||||
|
|
||||||
|
Node root = list.item(1);
|
||||||
|
|
||||||
|
rootGroup = new PwGroupV4(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vector<PwGroup> getGrpRoots() {
|
||||||
|
return rootGroup.childGroups;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vector<PwEntry> getEntries() {
|
||||||
|
Vector<PwEntry> list = new Vector<PwEntry>();
|
||||||
|
rootGroup.buildChildEntriesRecursive(list);
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getNumRounds() {
|
||||||
|
return numKeyEncRounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setNumRonuds(long rounds) throws NumberFormatException {
|
||||||
|
numKeyEncRounds = rounds;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,54 @@
|
|||||||
*/
|
*/
|
||||||
package com.keepassdroid.database;
|
package com.keepassdroid.database;
|
||||||
|
|
||||||
public abstract class PwEntry {
|
import java.util.Date;
|
||||||
|
|
||||||
|
public abstract class PwEntry implements Cloneable {
|
||||||
|
|
||||||
|
public byte uuid[] = new byte[16];
|
||||||
|
public String title;
|
||||||
|
public String url;
|
||||||
|
public String additional;
|
||||||
|
|
||||||
|
public PwEntry() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object clone() {
|
||||||
|
PwEntry newEntry;
|
||||||
|
try {
|
||||||
|
newEntry = (PwEntry) super.clone();
|
||||||
|
} catch (CloneNotSupportedException e) {
|
||||||
|
assert(false);
|
||||||
|
throw new RuntimeException("Clone should be supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
System.arraycopy(uuid, 0, newEntry.uuid, 0, uuid.length);
|
||||||
|
newEntry.title = title;
|
||||||
|
newEntry.url = url;
|
||||||
|
newEntry.additional = additional;
|
||||||
|
|
||||||
|
return newEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void assign(PwEntry source) {
|
||||||
|
System.arraycopy(source.uuid, 0, uuid, 0, source.uuid.length);
|
||||||
|
title = source.title;
|
||||||
|
url = source.url;
|
||||||
|
additional = source.additional;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void stampLastAccess();
|
||||||
|
|
||||||
|
public abstract String getUsername();
|
||||||
|
public abstract String getPassword();
|
||||||
|
public abstract Date getCreate();
|
||||||
|
public abstract Date getMod();
|
||||||
|
public abstract Date getAccess();
|
||||||
|
public abstract Date getExpire();
|
||||||
|
public abstract PwGroup getParent();
|
||||||
|
|
||||||
|
public abstract String getDisplayTitle();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,18 +70,13 @@ public class PwEntryV3 extends PwEntry {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public byte uuid[] = new byte[16];
|
|
||||||
public int groupId;
|
public int groupId;
|
||||||
public int imageId;
|
public int imageId;
|
||||||
|
|
||||||
public String title;
|
|
||||||
public String url;
|
|
||||||
public String username;
|
public String username;
|
||||||
|
|
||||||
private byte[] password;
|
private byte[] password;
|
||||||
|
|
||||||
public String additional;
|
|
||||||
|
|
||||||
public PwDate tCreation;
|
public PwDate tCreation;
|
||||||
public PwDate tLastMod;
|
public PwDate tLastMod;
|
||||||
public PwDate tLastAccess;
|
public PwDate tLastAccess;
|
||||||
@@ -132,17 +127,20 @@ public class PwEntryV3 extends PwEntry {
|
|||||||
public PwGroupV3 parent = null;
|
public PwGroupV3 parent = null;
|
||||||
|
|
||||||
public PwEntryV3() {
|
public PwEntryV3() {
|
||||||
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
public PwEntryV3(PwEntryV3 source) {
|
public PwEntryV3(PwEntryV3 source) {
|
||||||
assign(source);
|
assign(source);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
public PwEntryV3(Database db, int parentId) {
|
public PwEntryV3(Database db, int parentId) {
|
||||||
|
|
||||||
WeakReference<PwGroupV3> wPw = db.groups.get(parentId);
|
WeakReference<PwGroup> wPw = db.groups.get(parentId);
|
||||||
|
|
||||||
parent = wPw.get();
|
parent = (PwGroupV3) wPw.get();
|
||||||
groupId = parentId;
|
groupId = parentId;
|
||||||
|
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
@@ -162,6 +160,7 @@ public class PwEntryV3 extends PwEntry {
|
|||||||
return title.equals(PMS_TAN_ENTRY);
|
return title.equals(PMS_TAN_ENTRY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getDisplayTitle() {
|
public String getDisplayTitle() {
|
||||||
if ( isTan() ) {
|
if ( isTan() ) {
|
||||||
return PMS_TAN_ENTRY + " " + username;
|
return PMS_TAN_ENTRY + " " + username;
|
||||||
@@ -173,7 +172,12 @@ public class PwEntryV3 extends PwEntry {
|
|||||||
/**
|
/**
|
||||||
* @return the actual password byte array.
|
* @return the actual password byte array.
|
||||||
*/
|
*/
|
||||||
public byte[] getPassword() {
|
@Override
|
||||||
|
public String getPassword() {
|
||||||
|
return new String(password);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getPasswordBytes() {
|
||||||
return password;
|
return password;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,19 +239,31 @@ public class PwEntryV3 extends PwEntry {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void assign(PwEntryV3 source) {
|
|
||||||
System.arraycopy(source.uuid, 0, uuid, 0, source.uuid.length);
|
@Override
|
||||||
|
public void assign(PwEntry source) {
|
||||||
|
|
||||||
|
if ( ! (source instanceof PwEntryV3) ) {
|
||||||
|
throw new RuntimeException("DB version mix");
|
||||||
|
}
|
||||||
|
|
||||||
|
super.assign(source);
|
||||||
|
|
||||||
|
PwEntryV3 src = (PwEntryV3) source;
|
||||||
|
assign(src);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assign(PwEntryV3 source) {
|
||||||
|
|
||||||
groupId = source.groupId;
|
groupId = source.groupId;
|
||||||
imageId = source.imageId;
|
imageId = source.imageId;
|
||||||
title = source.title;
|
|
||||||
url = source.url;
|
|
||||||
username = source.username;
|
username = source.username;
|
||||||
|
|
||||||
int passLen = source.password.length;
|
int passLen = source.password.length;
|
||||||
password = new byte[passLen];
|
password = new byte[passLen];
|
||||||
System.arraycopy(source.password, 0, password, 0, passLen);
|
System.arraycopy(source.password, 0, password, 0, passLen);
|
||||||
|
|
||||||
additional = source.additional;
|
|
||||||
tCreation = (PwDate) source.tCreation.clone();
|
tCreation = (PwDate) source.tCreation.clone();
|
||||||
tLastMod = (PwDate) source.tLastMod.clone();
|
tLastMod = (PwDate) source.tLastMod.clone();
|
||||||
tLastAccess = (PwDate) source.tLastAccess.clone();
|
tLastAccess = (PwDate) source.tLastAccess.clone();
|
||||||
@@ -264,5 +280,69 @@ public class PwEntryV3 extends PwEntry {
|
|||||||
parent = source.parent;
|
parent = source.parent;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object clone() {
|
||||||
|
PwEntryV3 newEntry = (PwEntryV3) super.clone();
|
||||||
|
|
||||||
|
int passLen = password.length;
|
||||||
|
password = new byte[passLen];
|
||||||
|
System.arraycopy(password, 0, newEntry.password, 0, passLen);
|
||||||
|
|
||||||
|
newEntry.tCreation = (PwDate) tCreation.clone();
|
||||||
|
newEntry.tLastMod = (PwDate) tLastMod.clone();
|
||||||
|
newEntry.tLastAccess = (PwDate) tLastAccess.clone();
|
||||||
|
newEntry.tExpire = (PwDate) tExpire.clone();
|
||||||
|
|
||||||
|
newEntry.binaryDesc = binaryDesc;
|
||||||
|
|
||||||
|
if ( binaryData != null ) {
|
||||||
|
int descLen = binaryData.length;
|
||||||
|
newEntry.binaryData = new byte[descLen];
|
||||||
|
System.arraycopy(binaryData, 0, newEntry.binaryData, 0, descLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
newEntry.parent = parent;
|
||||||
|
|
||||||
|
|
||||||
|
return newEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stampLastAccess() {
|
||||||
|
Calendar cal = Calendar.getInstance();
|
||||||
|
tLastAccess = new PwDate(cal.getTime());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date getAccess() {
|
||||||
|
return tLastAccess.getJDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date getCreate() {
|
||||||
|
return tCreation.getJDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date getExpire() {
|
||||||
|
return tExpire.getJDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date getMod() {
|
||||||
|
return tLastMod.getJDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PwGroupV3 getParent() {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
109
src/com/keepassdroid/database/PwEntryV4.java
Normal file
109
src/com/keepassdroid/database/PwEntryV4.java
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010 Brian Pellin.
|
||||||
|
*
|
||||||
|
* This file is part of KeePassDroid.
|
||||||
|
*
|
||||||
|
* KeePassDroid is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* KeePassDroid is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with KeePassDroid. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.keepassdroid.database;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
|
||||||
|
public class PwEntryV4 extends PwEntry {
|
||||||
|
private Node node;
|
||||||
|
|
||||||
|
public PwEntryV4(Node n) {
|
||||||
|
node = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void assign(PwEntry source) {
|
||||||
|
super.assign(source);
|
||||||
|
|
||||||
|
if ( ! (source instanceof PwEntryV4) ) {
|
||||||
|
throw new RuntimeException("DB version mix.");
|
||||||
|
}
|
||||||
|
|
||||||
|
PwEntryV4 src = (PwEntryV4) source;
|
||||||
|
assign(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assign(PwEntryV4 source) {
|
||||||
|
node = source.node;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object clone() {
|
||||||
|
PwEntryV4 newEntry = (PwEntryV4) super.clone();
|
||||||
|
|
||||||
|
return newEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stampLastAccess() {
|
||||||
|
// TODO Implement me
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsername() {
|
||||||
|
// TODO Implement me
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPassword() {
|
||||||
|
// TODO Implement me
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date getAccess() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date getCreate() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date getExpire() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date getMod() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisplayTitle() {
|
||||||
|
// TOOD: Add special TAN handling for V4?
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PwGroupV4 getParent() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -19,6 +19,16 @@
|
|||||||
*/
|
*/
|
||||||
package com.keepassdroid.database;
|
package com.keepassdroid.database;
|
||||||
|
|
||||||
public class PwGroup {
|
import java.util.Vector;
|
||||||
|
|
||||||
|
public abstract class PwGroup {
|
||||||
|
public Vector<PwGroup> childGroups = new Vector<PwGroup>();
|
||||||
|
public Vector<PwEntry> childEntries = new Vector<PwEntry>();
|
||||||
|
|
||||||
|
public abstract PwGroup getParent();
|
||||||
|
|
||||||
|
public abstract PwGroupId getId();
|
||||||
|
|
||||||
|
public abstract String getName();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
5
src/com/keepassdroid/database/PwGroupId.java
Normal file
5
src/com/keepassdroid/database/PwGroupId.java
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package com.keepassdroid.database;
|
||||||
|
|
||||||
|
public abstract class PwGroupId {
|
||||||
|
|
||||||
|
}
|
||||||
29
src/com/keepassdroid/database/PwGroupIdV3.java
Normal file
29
src/com/keepassdroid/database/PwGroupIdV3.java
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package com.keepassdroid.database;
|
||||||
|
|
||||||
|
public class PwGroupIdV3 extends PwGroupId {
|
||||||
|
|
||||||
|
private int id;
|
||||||
|
|
||||||
|
public PwGroupIdV3(int i) {
|
||||||
|
id = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object compare) {
|
||||||
|
if ( ! (compare instanceof PwGroupIdV3) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PwGroupIdV3 cmp = (PwGroupIdV3) compare;
|
||||||
|
return id == cmp.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
Integer i = new Integer(id);
|
||||||
|
return i.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
28
src/com/keepassdroid/database/PwGroupIdV4.java
Normal file
28
src/com/keepassdroid/database/PwGroupIdV4.java
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package com.keepassdroid.database;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class PwGroupIdV4 extends PwGroupId {
|
||||||
|
private UUID uuid;
|
||||||
|
|
||||||
|
public PwGroupIdV4(UUID u) {
|
||||||
|
uuid = u;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object id) {
|
||||||
|
if ( ! (id instanceof PwGroupIdV4) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PwGroupIdV4 v4 = (PwGroupIdV4) id;
|
||||||
|
|
||||||
|
return uuid.equals(v4.uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return uuid.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -57,8 +57,6 @@ public class PwGroupV3 extends PwGroup {
|
|||||||
public static final int BUF_SIZE = 124;
|
public static final int BUF_SIZE = 124;
|
||||||
|
|
||||||
// for tree traversing
|
// for tree traversing
|
||||||
public Vector<PwGroupV3> childGroups = null;
|
|
||||||
public Vector<PwEntryV3> childEntries = null;
|
|
||||||
public PwGroupV3 parent = null;
|
public PwGroupV3 parent = null;
|
||||||
|
|
||||||
public int groupId;
|
public int groupId;
|
||||||
@@ -75,29 +73,49 @@ public class PwGroupV3 extends PwGroup {
|
|||||||
/** Used by KeePass internally, don't use */
|
/** Used by KeePass internally, don't use */
|
||||||
public int flags;
|
public int flags;
|
||||||
|
|
||||||
|
public void setGroups(Vector<PwGroup> groups) {
|
||||||
|
childGroups = groups;
|
||||||
|
}
|
||||||
|
|
||||||
public void sortGroupsByName() {
|
public void sortGroupsByName() {
|
||||||
Collections.sort(childGroups, new GroupNameComparator());
|
Collections.sort(childGroups, new GroupNameComparator());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PwGroup getParent() {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
public void sortEntriesByName() {
|
public void sortEntriesByName() {
|
||||||
Collections.sort(childEntries, new EntryNameComparator());
|
Collections.sort(childEntries, new EntryNameComparator());
|
||||||
}
|
}
|
||||||
|
|
||||||
private class GroupNameComparator implements Comparator<PwGroupV3> {
|
private class GroupNameComparator implements Comparator<PwGroup> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compare(PwGroupV3 object1, PwGroupV3 object2) {
|
public int compare(PwGroup object1, PwGroup object2) {
|
||||||
return object1.name.compareToIgnoreCase(object2.name);
|
return object1.getName().compareToIgnoreCase(object2.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class EntryNameComparator implements Comparator<PwEntryV3> {
|
private class EntryNameComparator implements Comparator<PwEntry> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compare(PwEntryV3 object1, PwEntryV3 object2) {
|
public int compare(PwEntry object1, PwEntry object2) {
|
||||||
return object1.title.compareToIgnoreCase(object2.title);
|
return object1.title.compareToIgnoreCase(object2.title);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PwGroupId getId() {
|
||||||
|
return new PwGroupIdV3(groupId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
105
src/com/keepassdroid/database/PwGroupV4.java
Normal file
105
src/com/keepassdroid/database/PwGroupV4.java
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010 Brian Pellin.
|
||||||
|
*
|
||||||
|
* This file is part of KeePassDroid.
|
||||||
|
*
|
||||||
|
* KeePassDroid is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* KeePassDroid is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with KeePassDroid. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.keepassdroid.database;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
|
import com.keepassdroid.database.exception.InconsistentDBException;
|
||||||
|
|
||||||
|
public class PwGroupV4 extends PwGroup {
|
||||||
|
|
||||||
|
private Node node;
|
||||||
|
private PwGroup parent;
|
||||||
|
|
||||||
|
public PwGroupV4(Node n) throws InconsistentDBException {
|
||||||
|
this(n, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PwGroupV4(Node n, PwGroup p) throws InconsistentDBException {
|
||||||
|
node = n;
|
||||||
|
parent = p;
|
||||||
|
buildTree();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildTree() throws InconsistentDBException {
|
||||||
|
NodeList children = node.getChildNodes();
|
||||||
|
|
||||||
|
for ( int i = 0; i < children.getLength(); i++ ) {
|
||||||
|
Node child = children.item(i);
|
||||||
|
String name = child.getNodeName();
|
||||||
|
if ( name.equalsIgnoreCase("Group") ) {
|
||||||
|
PwGroupV4 group = new PwGroupV4(child, this);
|
||||||
|
childGroups.add(group);
|
||||||
|
} else if ( name.equalsIgnoreCase("Entry") ) {
|
||||||
|
PwEntryV4 entry = new PwEntryV4(child);
|
||||||
|
childEntries.add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PwGroup getParent() {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void buildChildGroupsRecursive(Vector<PwGroup> list) {
|
||||||
|
list.add(this);
|
||||||
|
|
||||||
|
for ( int i = 0; i < childGroups.size(); i++) {
|
||||||
|
PwGroupV4 child = (PwGroupV4) childGroups.get(i);
|
||||||
|
child.buildChildGroupsRecursive(list);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void buildChildEntriesRecursive(Vector<PwEntry> list) {
|
||||||
|
for ( int i = 0; i < childEntries.size(); i++ ) {
|
||||||
|
list.add(childEntries.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( int i = 0; i < childGroups.size(); i++ ) {
|
||||||
|
PwGroupV4 child = (PwGroupV4) childGroups.get(i);
|
||||||
|
child.buildChildEntriesRecursive(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PwGroupId getId() {
|
||||||
|
return new PwGroupIdV4(getUUID());
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getUUID() {
|
||||||
|
// TODO: Get UUID from document
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -21,18 +21,27 @@ package com.keepassdroid.database.edit;
|
|||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
|
|
||||||
import com.keepassdroid.Database;
|
import com.keepassdroid.Database;
|
||||||
|
import com.keepassdroid.database.PwEntry;
|
||||||
import com.keepassdroid.database.PwEntryV3;
|
import com.keepassdroid.database.PwEntryV3;
|
||||||
import com.keepassdroid.database.PwGroupV3;
|
import com.keepassdroid.database.PwGroup;
|
||||||
import com.keepassdroid.search.SearchDbHelper;
|
import com.keepassdroid.search.SearchDbHelper;
|
||||||
import com.keepassdroid.utils.Types;
|
import com.keepassdroid.utils.Types;
|
||||||
|
|
||||||
public class AddEntry extends RunnableOnFinish {
|
public abstract class AddEntry extends RunnableOnFinish {
|
||||||
private Database mDb;
|
protected Database mDb;
|
||||||
private PwEntryV3 mEntry;
|
private PwEntry mEntry;
|
||||||
|
|
||||||
public AddEntry(Database db, PwEntryV3 entry, OnFinish finish) {
|
public static AddEntry getInstance(Database db, PwEntry entry, OnFinish finish) {
|
||||||
|
if ( entry instanceof PwEntryV3 ) {
|
||||||
|
return new AddEntryV3(db, (PwEntryV3) entry, finish);
|
||||||
|
} else {
|
||||||
|
// TODO: Implement me
|
||||||
|
throw new RuntimeException("Not implemented yet.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AddEntry(Database db, PwEntry entry, OnFinish finish) {
|
||||||
super(finish);
|
super(finish);
|
||||||
|
|
||||||
mDb = db;
|
mDb = db;
|
||||||
@@ -41,18 +50,11 @@ public class AddEntry extends RunnableOnFinish {
|
|||||||
mFinish = new AfterAdd(mFinish);
|
mFinish = new AfterAdd(mFinish);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract void addEntry();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
PwGroupV3 parent = mEntry.parent;
|
addEntry();
|
||||||
|
|
||||||
// Add entry to group
|
|
||||||
parent.childEntries.add(mEntry);
|
|
||||||
|
|
||||||
// Add entry to PwDatabaseV3
|
|
||||||
mDb.pm.entries.add(mEntry);
|
|
||||||
|
|
||||||
// Sort entries
|
|
||||||
parent.sortEntriesByName();
|
|
||||||
|
|
||||||
// Commit to disk
|
// Commit to disk
|
||||||
SaveDB save = new SaveDB(mDb, mFinish);
|
SaveDB save = new SaveDB(mDb, mFinish);
|
||||||
@@ -68,13 +70,13 @@ public class AddEntry extends RunnableOnFinish {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if ( mSuccess ) {
|
if ( mSuccess ) {
|
||||||
PwGroupV3 parent = mEntry.parent;
|
PwGroup parent = mEntry.getParent();
|
||||||
|
|
||||||
// Mark parent group dirty
|
// Mark parent group dirty
|
||||||
mDb.dirty.put(parent, new WeakReference<PwGroupV3>(parent));
|
mDb.dirty.put(parent, new WeakReference<PwGroup>(parent));
|
||||||
|
|
||||||
// Add entry to global
|
// Add entry to global
|
||||||
mDb.entries.put(Types.bytestoUUID(mEntry.uuid), new WeakReference<PwEntryV3>(mEntry));
|
mDb.entries.put(Types.bytestoUUID(mEntry.uuid), new WeakReference<PwEntry>(mEntry));
|
||||||
|
|
||||||
if ( mDb.indexBuilt ) {
|
if ( mDb.indexBuilt ) {
|
||||||
// Add entry to search index
|
// Add entry to search index
|
||||||
@@ -85,10 +87,10 @@ public class AddEntry extends RunnableOnFinish {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Remove from group
|
// Remove from group
|
||||||
mEntry.parent.childEntries.removeElement(mEntry);
|
mEntry.getParent().childEntries.removeElement(mEntry);
|
||||||
|
|
||||||
// Remove from manager
|
// Remove from manager
|
||||||
mDb.pm.entries.removeElement(mEntry);
|
mDb.pm.getEntries().removeElement(mEntry);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
53
src/com/keepassdroid/database/edit/AddEntryV3.java
Normal file
53
src/com/keepassdroid/database/edit/AddEntryV3.java
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010 Brian Pellin.
|
||||||
|
*
|
||||||
|
* This file is part of KeePassDroid.
|
||||||
|
*
|
||||||
|
* KeePassDroid is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* KeePassDroid is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with KeePassDroid. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.keepassdroid.database.edit;
|
||||||
|
|
||||||
|
import com.keepassdroid.Database;
|
||||||
|
import com.keepassdroid.database.PwDatabaseV3;
|
||||||
|
import com.keepassdroid.database.PwEntryV3;
|
||||||
|
import com.keepassdroid.database.PwGroupV3;
|
||||||
|
|
||||||
|
public class AddEntryV3 extends AddEntry {
|
||||||
|
|
||||||
|
private PwEntryV3 mEntry;
|
||||||
|
|
||||||
|
protected AddEntryV3(Database db, PwEntryV3 entry, OnFinish finish) {
|
||||||
|
super(db, entry, finish);
|
||||||
|
|
||||||
|
mEntry = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void addEntry() {
|
||||||
|
PwGroupV3 parent = mEntry.getParent();
|
||||||
|
|
||||||
|
// Add entry to group
|
||||||
|
parent.childEntries.add(mEntry);
|
||||||
|
|
||||||
|
// Add entry to PwDatabaseV3
|
||||||
|
PwDatabaseV3 pm = (PwDatabaseV3) mDb.pm;
|
||||||
|
pm.getEntries().add(mEntry);
|
||||||
|
|
||||||
|
// Sort entries
|
||||||
|
parent.sortEntriesByName();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -19,67 +19,31 @@
|
|||||||
*/
|
*/
|
||||||
package com.keepassdroid.database.edit;
|
package com.keepassdroid.database.edit;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
|
|
||||||
|
|
||||||
import com.keepassdroid.Database;
|
import com.keepassdroid.Database;
|
||||||
import com.keepassdroid.database.PwDatabaseV3;
|
import com.keepassdroid.database.PwGroup;
|
||||||
import com.keepassdroid.database.PwGroupV3;
|
import com.keepassdroid.database.PwGroupV3;
|
||||||
|
|
||||||
public class AddGroup extends RunnableOnFinish {
|
public abstract class AddGroup extends RunnableOnFinish {
|
||||||
private Database mDb;
|
protected Database mDb;
|
||||||
private String mName;
|
protected boolean mDontSave;
|
||||||
private PwGroupV3 mParent;
|
|
||||||
private PwGroupV3 mGroup;
|
|
||||||
private boolean mDontSave;
|
|
||||||
|
|
||||||
public AddGroup(Database db, String name, PwGroupV3 parent, OnFinish finish, boolean dontSave) {
|
public static AddGroup getInstance(Database db, String name, PwGroup parent, OnFinish finish, boolean dontSave) {
|
||||||
|
if ( parent instanceof PwGroupV3 ) {
|
||||||
|
return new AddGroupV3(db, name, (PwGroupV3) parent, finish, dontSave);
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Not yet implemented");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AddGroup(Database db, OnFinish finish, boolean dontSave) {
|
||||||
super(finish);
|
super(finish);
|
||||||
|
|
||||||
mDb = db;
|
mDb = db;
|
||||||
mName = name;
|
|
||||||
mParent = parent;
|
|
||||||
mDontSave = dontSave;
|
mDontSave = dontSave;
|
||||||
|
|
||||||
mFinish = new AfterAdd(mFinish);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract void run();
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
PwDatabaseV3 pm = mDb.pm;
|
|
||||||
|
|
||||||
// Generate new group
|
|
||||||
mGroup = pm.newGroup(mName, mParent);
|
|
||||||
|
|
||||||
mParent.sortGroupsByName();
|
|
||||||
|
|
||||||
// Commit to disk
|
|
||||||
SaveDB save = new SaveDB(mDb, mFinish, mDontSave);
|
|
||||||
save.run();
|
|
||||||
}
|
|
||||||
|
|
||||||
private class AfterAdd extends OnFinish {
|
|
||||||
|
|
||||||
public AfterAdd(OnFinish finish) {
|
|
||||||
super(finish);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
|
|
||||||
if ( mSuccess ) {
|
|
||||||
// Mark parent group dirty
|
|
||||||
mDb.dirty.put(mParent, new WeakReference<PwGroupV3>(mParent));
|
|
||||||
|
|
||||||
// Add group to global list
|
|
||||||
mDb.groups.put(mGroup.groupId, new WeakReference<PwGroupV3>(mGroup));
|
|
||||||
} else {
|
|
||||||
mDb.pm.removeGroup(mGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
super.run();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
67
src/com/keepassdroid/database/edit/AddGroupV3.java
Normal file
67
src/com/keepassdroid/database/edit/AddGroupV3.java
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
package com.keepassdroid.database.edit;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
|
import com.keepassdroid.Database;
|
||||||
|
import com.keepassdroid.database.PwDatabaseV3;
|
||||||
|
import com.keepassdroid.database.PwGroup;
|
||||||
|
import com.keepassdroid.database.PwGroupV3;
|
||||||
|
|
||||||
|
public class AddGroupV3 extends AddGroup {
|
||||||
|
private Database mDb;
|
||||||
|
private String mName;
|
||||||
|
private PwGroupV3 mParent;
|
||||||
|
private PwGroupV3 mGroup;
|
||||||
|
private boolean mDontSave;
|
||||||
|
|
||||||
|
protected AddGroupV3(Database db, String name, PwGroupV3 parent, OnFinish finish, boolean dontSave) {
|
||||||
|
super(db, finish, dontSave);
|
||||||
|
|
||||||
|
mDb = db;
|
||||||
|
mName = name;
|
||||||
|
mParent = parent;
|
||||||
|
mDontSave = dontSave;
|
||||||
|
|
||||||
|
mFinish = new AfterAdd(mFinish);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
PwDatabaseV3 pm = (PwDatabaseV3) mDb.pm;
|
||||||
|
|
||||||
|
// Generate new group
|
||||||
|
mGroup = pm.newGroup(mName, mParent);
|
||||||
|
|
||||||
|
mParent.sortGroupsByName();
|
||||||
|
|
||||||
|
// Commit to disk
|
||||||
|
SaveDB save = new SaveDB(mDb, mFinish, mDontSave);
|
||||||
|
save.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class AfterAdd extends OnFinish {
|
||||||
|
|
||||||
|
public AfterAdd(OnFinish finish) {
|
||||||
|
super(finish);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
|
||||||
|
if ( mSuccess ) {
|
||||||
|
// Mark parent group dirty
|
||||||
|
mDb.dirty.put(mParent, new WeakReference<PwGroup>(mParent));
|
||||||
|
|
||||||
|
// Add group to global list
|
||||||
|
mDb.groups.put(mGroup.getId(), new WeakReference<PwGroup>(mGroup));
|
||||||
|
} else {
|
||||||
|
PwDatabaseV3 pm = (PwDatabaseV3) mDb.pm;
|
||||||
|
pm.removeGroup(mGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
super.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -60,9 +60,9 @@ public class CreateDB extends RunnableOnFinish {
|
|||||||
db.setLoaded();
|
db.setLoaded();
|
||||||
|
|
||||||
// Add a couple default groups
|
// Add a couple default groups
|
||||||
AddGroup internet = new AddGroup(db, "Internet", pm.rootGroup, null, true);
|
AddGroup internet = AddGroup.getInstance(db, "Internet", pm.rootGroup, null, true);
|
||||||
internet.run();
|
internet.run();
|
||||||
AddGroup email = new AddGroup(db, "eMail", pm.rootGroup, null, true);
|
AddGroup email = AddGroup.getInstance(db, "eMail", pm.rootGroup, null, true);
|
||||||
email.run();
|
email.run();
|
||||||
|
|
||||||
// Commit changes
|
// Commit changes
|
||||||
|
|||||||
@@ -21,10 +21,9 @@ package com.keepassdroid.database.edit;
|
|||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
|
|
||||||
import com.keepassdroid.Database;
|
import com.keepassdroid.Database;
|
||||||
import com.keepassdroid.database.PwEntryV3;
|
import com.keepassdroid.database.PwEntry;
|
||||||
import com.keepassdroid.database.PwGroupV3;
|
import com.keepassdroid.database.PwGroup;
|
||||||
import com.keepassdroid.search.SearchDbHelper;
|
import com.keepassdroid.search.SearchDbHelper;
|
||||||
|
|
||||||
/** Task to delete entries
|
/** Task to delete entries
|
||||||
@@ -34,10 +33,10 @@ import com.keepassdroid.search.SearchDbHelper;
|
|||||||
public class DeleteEntry extends RunnableOnFinish {
|
public class DeleteEntry extends RunnableOnFinish {
|
||||||
|
|
||||||
private Database mDb;
|
private Database mDb;
|
||||||
private PwEntryV3 mEntry;
|
private PwEntry mEntry;
|
||||||
private boolean mDontSave;
|
private boolean mDontSave;
|
||||||
|
|
||||||
public DeleteEntry(Database db, PwEntryV3 entry, OnFinish finish) {
|
public DeleteEntry(Database db, PwEntry entry, OnFinish finish) {
|
||||||
super(finish);
|
super(finish);
|
||||||
|
|
||||||
mDb = db;
|
mDb = db;
|
||||||
@@ -46,7 +45,7 @@ public class DeleteEntry extends RunnableOnFinish {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeleteEntry(Database db, PwEntryV3 entry, OnFinish finish, boolean dontSave) {
|
public DeleteEntry(Database db, PwEntry entry, OnFinish finish, boolean dontSave) {
|
||||||
super(finish);
|
super(finish);
|
||||||
|
|
||||||
mDb = db;
|
mDb = db;
|
||||||
@@ -59,11 +58,11 @@ public class DeleteEntry extends RunnableOnFinish {
|
|||||||
public void run() {
|
public void run() {
|
||||||
|
|
||||||
// Remove Entry from parent
|
// Remove Entry from parent
|
||||||
PwGroupV3 parent = mEntry.parent;
|
PwGroup parent = mEntry.getParent();
|
||||||
parent.childEntries.remove(mEntry);
|
parent.childEntries.remove(mEntry);
|
||||||
|
|
||||||
// Remove Entry from PwDatabaseV3
|
// Remove Entry from PwDatabase
|
||||||
mDb.pm.entries.remove(mEntry);
|
mDb.pm.getEntries().remove(mEntry);
|
||||||
|
|
||||||
// Save
|
// Save
|
||||||
mFinish = new AfterDelete(mFinish, parent, mEntry);
|
mFinish = new AfterDelete(mFinish, parent, mEntry);
|
||||||
@@ -74,14 +73,13 @@ public class DeleteEntry extends RunnableOnFinish {
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class AfterDelete extends OnFinish {
|
private class AfterDelete extends OnFinish {
|
||||||
|
|
||||||
private PwGroupV3 mParent;
|
private PwGroup mParent;
|
||||||
private PwEntryV3 mEntry;
|
private PwEntry mEntry;
|
||||||
|
|
||||||
public AfterDelete(OnFinish finish, PwGroupV3 parent, PwEntryV3 entry) {
|
public AfterDelete(OnFinish finish, PwGroup parent, PwEntry entry) {
|
||||||
super(finish);
|
super(finish);
|
||||||
|
|
||||||
mParent = parent;
|
mParent = parent;
|
||||||
@@ -105,22 +103,21 @@ public class DeleteEntry extends RunnableOnFinish {
|
|||||||
|
|
||||||
// Mark parent dirty
|
// Mark parent dirty
|
||||||
if ( mParent != null ) {
|
if ( mParent != null ) {
|
||||||
mDb.dirty.put(mParent, new WeakReference<PwGroupV3>(mParent));
|
mDb.dirty.put(mParent, new WeakReference<PwGroup>(mParent));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Undo remove entry
|
mDb.pm.getEntries().add(mEntry);
|
||||||
mDb.pm.entries.add(mEntry);
|
|
||||||
|
|
||||||
PwGroupV3 parent = mEntry.parent;
|
PwGroup parent = mEntry.getParent();
|
||||||
if ( parent != null ) {
|
if ( parent != null ) {
|
||||||
parent.childEntries.add(mEntry);
|
parent.childEntries.add(mEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
super.run();
|
super.run();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,36 +22,36 @@ package com.keepassdroid.database.edit;
|
|||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
|
|
||||||
import com.keepassdroid.Database;
|
import com.keepassdroid.Database;
|
||||||
import com.keepassdroid.GroupBaseActivity;
|
import com.keepassdroid.GroupBaseActivity;
|
||||||
import com.keepassdroid.database.PwEntryV3;
|
import com.keepassdroid.app.App;
|
||||||
import com.keepassdroid.database.PwGroupV3;
|
import com.keepassdroid.database.PwEntry;
|
||||||
|
import com.keepassdroid.database.PwGroup;
|
||||||
|
|
||||||
public class DeleteGroup extends RunnableOnFinish {
|
public class DeleteGroup extends RunnableOnFinish {
|
||||||
|
|
||||||
private Database mDb;
|
private Database mDb;
|
||||||
private PwGroupV3 mGroup;
|
private PwGroup mGroup;
|
||||||
private GroupBaseActivity mAct;
|
private GroupBaseActivity mAct;
|
||||||
private boolean mDontSave;
|
private boolean mDontSave;
|
||||||
|
|
||||||
public DeleteGroup(Database db, PwGroupV3 group, GroupBaseActivity act, OnFinish finish) {
|
public DeleteGroup(Database db, PwGroup group, GroupBaseActivity act, OnFinish finish) {
|
||||||
super(finish);
|
super(finish);
|
||||||
setMembers(db, group, act, false);
|
setMembers(db, group, act, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeleteGroup(Database db, PwGroupV3 group, GroupBaseActivity act, OnFinish finish, boolean dontSave) {
|
public DeleteGroup(Database db, PwGroup group, GroupBaseActivity act, OnFinish finish, boolean dontSave) {
|
||||||
super(finish);
|
super(finish);
|
||||||
setMembers(db, group, act, dontSave);
|
setMembers(db, group, act, dontSave);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public DeleteGroup(Database db, PwGroupV3 group, OnFinish finish, boolean dontSave) {
|
public DeleteGroup(Database db, PwGroup group, OnFinish finish, boolean dontSave) {
|
||||||
super(finish);
|
super(finish);
|
||||||
setMembers(db, group, null, dontSave);
|
setMembers(db, group, null, dontSave);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setMembers(Database db, PwGroupV3 group, GroupBaseActivity act, boolean dontSave) {
|
private void setMembers(Database db, PwGroup group, GroupBaseActivity act, boolean dontSave) {
|
||||||
mDb = db;
|
mDb = db;
|
||||||
mGroup = group;
|
mGroup = group;
|
||||||
mAct = act;
|
mAct = act;
|
||||||
@@ -67,14 +67,14 @@ public class DeleteGroup extends RunnableOnFinish {
|
|||||||
public void run() {
|
public void run() {
|
||||||
|
|
||||||
// Remove child entries
|
// Remove child entries
|
||||||
Vector<PwEntryV3> childEnt = (Vector<PwEntryV3>) mGroup.childEntries.clone();
|
Vector<PwEntry> childEnt = (Vector<PwEntry>) mGroup.childEntries.clone();
|
||||||
for ( int i = 0; i < childEnt.size(); i++ ) {
|
for ( int i = 0; i < childEnt.size(); i++ ) {
|
||||||
DeleteEntry task = new DeleteEntry(mDb, childEnt.get(i), null, true);
|
DeleteEntry task = new DeleteEntry(mDb, childEnt.get(i), null, true);
|
||||||
task.run();
|
task.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove child groups
|
// Remove child groups
|
||||||
Vector<PwGroupV3> childGrp = (Vector<PwGroupV3>) mGroup.childGroups.clone();
|
Vector<PwGroup> childGrp = (Vector<PwGroup>) mGroup.childGroups.clone();
|
||||||
for ( int i = 0; i < childGrp.size(); i++ ) {
|
for ( int i = 0; i < childGrp.size(); i++ ) {
|
||||||
DeleteGroup task = new DeleteGroup(mDb, childGrp.get(i), mAct, null, true);
|
DeleteGroup task = new DeleteGroup(mDb, childGrp.get(i), mAct, null, true);
|
||||||
task.run();
|
task.run();
|
||||||
@@ -82,13 +82,13 @@ public class DeleteGroup extends RunnableOnFinish {
|
|||||||
|
|
||||||
|
|
||||||
// Remove from parent
|
// Remove from parent
|
||||||
PwGroupV3 parent = mGroup.parent;
|
PwGroup parent = mGroup.getParent();
|
||||||
if ( parent != null ) {
|
if ( parent != null ) {
|
||||||
parent.childGroups.remove(mGroup);
|
parent.childGroups.remove(mGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove from PwDatabaseV3
|
// Remove from PwDatabaseV3
|
||||||
mDb.pm.groups.remove(mGroup);
|
mDb.pm.getGroups().remove(mGroup);
|
||||||
|
|
||||||
// Save
|
// Save
|
||||||
SaveDB save = new SaveDB(mDb, mFinish, mDontSave);
|
SaveDB save = new SaveDB(mDb, mFinish, mDontSave);
|
||||||
@@ -104,7 +104,7 @@ public class DeleteGroup extends RunnableOnFinish {
|
|||||||
public void run() {
|
public void run() {
|
||||||
if ( mSuccess ) {
|
if ( mSuccess ) {
|
||||||
// Remove from group global
|
// Remove from group global
|
||||||
mDb.groups.remove(mGroup.groupId);
|
mDb.groups.remove(mGroup.getId());
|
||||||
|
|
||||||
// Remove group from the dirty global (if it is present), not a big deal if this fails
|
// Remove group from the dirty global (if it is present), not a big deal if this fails
|
||||||
try {
|
try {
|
||||||
@@ -114,12 +114,13 @@ public class DeleteGroup extends RunnableOnFinish {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Mark parent dirty
|
// Mark parent dirty
|
||||||
PwGroupV3 parent = mGroup.parent;
|
PwGroup parent = mGroup.getParent();
|
||||||
if ( parent != null ) {
|
if ( parent != null ) {
|
||||||
mDb.dirty.put(parent, new WeakReference<PwGroupV3>(parent));
|
mDb.dirty.put(parent, new WeakReference<PwGroup>(parent));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Let's not bother recovering from a failure to save a deleted group. It is too much work.
|
// Let's not bother recovering from a failure to save a deleted group. It is too much work.
|
||||||
|
App.setShutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
super.run();
|
super.run();
|
||||||
|
|||||||
@@ -21,18 +21,19 @@ package com.keepassdroid.database.edit;
|
|||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
|
|
||||||
import com.keepassdroid.Database;
|
import com.keepassdroid.Database;
|
||||||
|
import com.keepassdroid.database.PwEntry;
|
||||||
import com.keepassdroid.database.PwEntryV3;
|
import com.keepassdroid.database.PwEntryV3;
|
||||||
|
import com.keepassdroid.database.PwGroup;
|
||||||
import com.keepassdroid.database.PwGroupV3;
|
import com.keepassdroid.database.PwGroupV3;
|
||||||
import com.keepassdroid.search.SearchDbHelper;
|
import com.keepassdroid.search.SearchDbHelper;
|
||||||
|
|
||||||
public class UpdateEntry extends RunnableOnFinish {
|
public class UpdateEntry extends RunnableOnFinish {
|
||||||
private Database mDb;
|
private Database mDb;
|
||||||
private PwEntryV3 mOldE;
|
private PwEntry mOldE;
|
||||||
private PwEntryV3 mNewE;
|
private PwEntry mNewE;
|
||||||
|
|
||||||
public UpdateEntry(Database db, PwEntryV3 oldE, PwEntryV3 newE, OnFinish finish) {
|
public UpdateEntry(Database db, PwEntry oldE, PwEntry newE, OnFinish finish) {
|
||||||
super(finish);
|
super(finish);
|
||||||
|
|
||||||
mDb = db;
|
mDb = db;
|
||||||
@@ -40,7 +41,9 @@ public class UpdateEntry extends RunnableOnFinish {
|
|||||||
mNewE = newE;
|
mNewE = newE;
|
||||||
|
|
||||||
// Keep backup of original values in case save fails
|
// Keep backup of original values in case save fails
|
||||||
PwEntryV3 backup = new PwEntryV3(mOldE);
|
PwEntryV3 backup;
|
||||||
|
backup = (PwEntryV3) mOldE.clone();
|
||||||
|
|
||||||
mFinish = new AfterUpdate(backup, finish);
|
mFinish = new AfterUpdate(backup, finish);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +77,7 @@ public class UpdateEntry extends RunnableOnFinish {
|
|||||||
parent.sortEntriesByName();
|
parent.sortEntriesByName();
|
||||||
|
|
||||||
// Mark parent group dirty
|
// Mark parent group dirty
|
||||||
mDb.dirty.put(parent, new WeakReference<PwGroupV3>(parent));
|
mDb.dirty.put(parent, new WeakReference<PwGroup>(parent));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.keepassdroid.database.exception;
|
||||||
|
|
||||||
|
public class InconsistentDBException extends Exception {
|
||||||
|
|
||||||
|
public InconsistentDBException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 4879502365625912291L;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -270,6 +270,8 @@ public class ImporterV3 extends Importer {
|
|||||||
pos += 2 + 4 + fieldSize;
|
pos += 2 + 4 + fieldSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newManager.constructTree(null);
|
||||||
|
|
||||||
return newManager;
|
return newManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.keepassdroid.database.load;
|
package com.keepassdroid.database.load;
|
||||||
|
|
||||||
import java.io.FileOutputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
@@ -29,20 +29,27 @@ import java.util.Arrays;
|
|||||||
import java.util.zip.GZIPInputStream;
|
import java.util.zip.GZIPInputStream;
|
||||||
|
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
import javax.crypto.CipherInputStream;
|
|
||||||
import javax.crypto.NoSuchPaddingException;
|
import javax.crypto.NoSuchPaddingException;
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
import com.keepassdroid.UpdateStatus;
|
import com.keepassdroid.UpdateStatus;
|
||||||
import com.keepassdroid.crypto.CipherFactory;
|
import com.keepassdroid.crypto.CipherFactory;
|
||||||
import com.keepassdroid.database.PwCompressionAlgorithm;
|
import com.keepassdroid.database.PwCompressionAlgorithm;
|
||||||
import com.keepassdroid.database.PwDatabaseV4;
|
import com.keepassdroid.database.PwDatabaseV4;
|
||||||
import com.keepassdroid.database.PwDbHeaderV4;
|
import com.keepassdroid.database.PwDbHeaderV4;
|
||||||
|
import com.keepassdroid.database.exception.InconsistentDBException;
|
||||||
import com.keepassdroid.database.exception.InvalidDBSignatureException;
|
import com.keepassdroid.database.exception.InvalidDBSignatureException;
|
||||||
import com.keepassdroid.database.exception.InvalidDBVersionException;
|
import com.keepassdroid.database.exception.InvalidDBVersionException;
|
||||||
import com.keepassdroid.database.exception.InvalidKeyFileException;
|
import com.keepassdroid.database.exception.InvalidKeyFileException;
|
||||||
import com.keepassdroid.database.exception.InvalidPasswordException;
|
import com.keepassdroid.database.exception.InvalidPasswordException;
|
||||||
import com.keepassdroid.stream.LEDataInputStream;
|
import com.keepassdroid.stream.BetterCipherInputStream;
|
||||||
import com.keepassdroid.stream.HashedBlockInputStream;
|
import com.keepassdroid.stream.HashedBlockInputStream;
|
||||||
|
import com.keepassdroid.stream.LEDataInputStream;
|
||||||
|
|
||||||
public class ImporterV4 extends Importer {
|
public class ImporterV4 extends Importer {
|
||||||
|
|
||||||
@@ -60,12 +67,14 @@ public class ImporterV4 extends Importer {
|
|||||||
InvalidKeyFileException, InvalidPasswordException,
|
InvalidKeyFileException, InvalidPasswordException,
|
||||||
InvalidDBSignatureException, InvalidDBVersionException {
|
InvalidDBSignatureException, InvalidDBVersionException {
|
||||||
|
|
||||||
|
// TODO: Measure whether this buffer is better or worse for performance
|
||||||
|
BufferedInputStream bis = new BufferedInputStream(inStream);
|
||||||
|
|
||||||
PwDatabaseV4 db = new PwDatabaseV4();
|
PwDatabaseV4 db = new PwDatabaseV4();
|
||||||
|
|
||||||
PwDbHeaderV4 header = new PwDbHeaderV4(db);
|
PwDbHeaderV4 header = new PwDbHeaderV4(db);
|
||||||
|
|
||||||
header.loadFromFile(inStream);
|
header.loadFromFile(bis);
|
||||||
|
|
||||||
db.setMasterKey(password, keyfile);
|
db.setMasterKey(password, keyfile);
|
||||||
db.makeFinalKey(header.masterSeed, header.transformSeed, (int)db.numKeyEncRounds);
|
db.makeFinalKey(header.masterSeed, header.transformSeed, (int)db.numKeyEncRounds);
|
||||||
@@ -84,7 +93,7 @@ public class ImporterV4 extends Importer {
|
|||||||
throw new IOException("Invalid algorithm.");
|
throw new IOException("Invalid algorithm.");
|
||||||
}
|
}
|
||||||
|
|
||||||
InputStream decrypted = new CipherInputStream(inStream, cipher);
|
InputStream decrypted = new BetterCipherInputStream(bis, cipher, 50 * 1024);
|
||||||
LEDataInputStream dataDecrypted = new LEDataInputStream(decrypted);
|
LEDataInputStream dataDecrypted = new LEDataInputStream(decrypted);
|
||||||
byte[] storedStartBytes = dataDecrypted.readBytes(32);
|
byte[] storedStartBytes = dataDecrypted.readBytes(32);
|
||||||
if ( storedStartBytes == null || storedStartBytes.length != 32 ) {
|
if ( storedStartBytes == null || storedStartBytes.length != 32 ) {
|
||||||
@@ -96,8 +105,8 @@ public class ImporterV4 extends Importer {
|
|||||||
// an incorrect password/key
|
// an incorrect password/key
|
||||||
throw new IOException("Bad database key");
|
throw new IOException("Bad database key");
|
||||||
}
|
}
|
||||||
|
|
||||||
HashedBlockInputStream hashed = new HashedBlockInputStream(decrypted);
|
HashedBlockInputStream hashed = new HashedBlockInputStream(dataDecrypted);
|
||||||
|
|
||||||
InputStream decompressed;
|
InputStream decompressed;
|
||||||
if ( db.compressionAlgorithm == PwCompressionAlgorithm.Gzip ) {
|
if ( db.compressionAlgorithm == PwCompressionAlgorithm.Gzip ) {
|
||||||
@@ -106,18 +115,44 @@ public class ImporterV4 extends Importer {
|
|||||||
decompressed = hashed;
|
decompressed = hashed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: output into database instead of file
|
// TODO: Measure whether this buffer is better or worse for performance
|
||||||
FileOutputStream fos = new FileOutputStream("/sdcard/output.xml");
|
BufferedInputStream bis2 = new BufferedInputStream(decompressed);
|
||||||
|
|
||||||
|
// Parse the xml document
|
||||||
|
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||||
|
DocumentBuilder docB;
|
||||||
|
try {
|
||||||
|
docB = dbf.newDocumentBuilder();
|
||||||
|
} catch (ParserConfigurationException e) {
|
||||||
|
throw new IOException("Couldn't create document builder.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Document doc;
|
||||||
|
try {
|
||||||
|
doc = docB.parse(bis2);
|
||||||
|
} catch (SAXException e) {
|
||||||
|
throw new IOException("Failed to parse db xml: " + e.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
db.parseDB(doc);
|
||||||
|
} catch (InconsistentDBException e) {
|
||||||
|
throw new IOException(e.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
FileOutputStream fos = new FileOutputStream("/sdcard/outputx.xml");
|
||||||
byte[] buf = new byte[1024];
|
byte[] buf = new byte[1024];
|
||||||
int bytesRead;
|
int bytesRead;
|
||||||
while ( (bytesRead = decompressed.read(buf)) != -1 ) {
|
while ( (bytesRead = decompressed.read(buf)) != -1 ) {
|
||||||
fos.write(buf, 0, bytesRead);
|
fos.write(buf, 0, bytesRead);
|
||||||
}
|
}
|
||||||
|
|
||||||
fos.close();
|
fos.close();
|
||||||
|
*/
|
||||||
|
|
||||||
return db;
|
return db;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -26,11 +26,11 @@ import java.io.OutputStream;
|
|||||||
import com.keepassdroid.database.PwDbHeaderV3;
|
import com.keepassdroid.database.PwDbHeaderV3;
|
||||||
import com.keepassdroid.utils.Types;
|
import com.keepassdroid.utils.Types;
|
||||||
|
|
||||||
public class PwDbHeaderOutput {
|
public class PwDbHeaderOutputV3 {
|
||||||
private PwDbHeaderV3 mHeader;
|
private PwDbHeaderV3 mHeader;
|
||||||
private OutputStream mOS;
|
private OutputStream mOS;
|
||||||
|
|
||||||
public PwDbHeaderOutput(PwDbHeaderV3 header, OutputStream os) {
|
public PwDbHeaderOutputV3(PwDbHeaderV3 header, OutputStream os) {
|
||||||
mHeader = header;
|
mHeader = header;
|
||||||
mOS = os;
|
mOS = os;
|
||||||
}
|
}
|
||||||
46
src/com/keepassdroid/database/save/PwDbOutput.java
Normal file
46
src/com/keepassdroid/database/save/PwDbOutput.java
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
` * Copyright 2010 Brian Pellin.
|
||||||
|
*
|
||||||
|
* This file is part of KeePassDroid.
|
||||||
|
*
|
||||||
|
* KeePassDroid is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* KeePassDroid is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with KeePassDroid. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.keepassdroid.database.save;
|
||||||
|
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
import com.keepassdroid.database.PwDatabase;
|
||||||
|
import com.keepassdroid.database.PwDatabaseV3;
|
||||||
|
import com.keepassdroid.database.PwDatabaseV4;
|
||||||
|
import com.keepassdroid.database.exception.PwDbOutputException;
|
||||||
|
|
||||||
|
public abstract class PwDbOutput {
|
||||||
|
public abstract void output() throws PwDbOutputException;
|
||||||
|
|
||||||
|
public static PwDbOutput getInstance(PwDatabase pm, OutputStream os) {
|
||||||
|
return getInstance(pm, os, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PwDbOutput getInstance(PwDatabase pm, OutputStream os, boolean debug) {
|
||||||
|
if ( pm instanceof PwDatabaseV3 ) {
|
||||||
|
return new PwDbV3Output((PwDatabaseV3)pm, os, debug);
|
||||||
|
} else if ( pm instanceof PwDatabaseV4 ) {
|
||||||
|
// TODO: Implement me
|
||||||
|
throw new RuntimeException(".kdbx output not yet supported.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -40,11 +40,12 @@ import com.keepassdroid.database.PwDatabaseV3;
|
|||||||
import com.keepassdroid.database.PwDbHeader;
|
import com.keepassdroid.database.PwDbHeader;
|
||||||
import com.keepassdroid.database.PwDbHeaderV3;
|
import com.keepassdroid.database.PwDbHeaderV3;
|
||||||
import com.keepassdroid.database.PwEntryV3;
|
import com.keepassdroid.database.PwEntryV3;
|
||||||
|
import com.keepassdroid.database.PwGroup;
|
||||||
import com.keepassdroid.database.PwGroupV3;
|
import com.keepassdroid.database.PwGroupV3;
|
||||||
import com.keepassdroid.database.exception.PwDbOutputException;
|
import com.keepassdroid.database.exception.PwDbOutputException;
|
||||||
import com.keepassdroid.stream.NullOutputStream;
|
import com.keepassdroid.stream.NullOutputStream;
|
||||||
|
|
||||||
public class PwDbV3Output {
|
public class PwDbV3Output extends PwDbOutput {
|
||||||
private PwDatabaseV3 mPM;
|
private PwDatabaseV3 mPM;
|
||||||
private OutputStream mOS;
|
private OutputStream mOS;
|
||||||
private final boolean mDebug;
|
private final boolean mDebug;
|
||||||
@@ -121,7 +122,7 @@ public class PwDbV3Output {
|
|||||||
}
|
}
|
||||||
|
|
||||||
header.version = PwDbHeaderV3.DBVER_DW;
|
header.version = PwDbHeaderV3.DBVER_DW;
|
||||||
header.numGroups = mPM.groups.size();
|
header.numGroups = mPM.getGroups().size();
|
||||||
header.numEntries = mPM.entries.size();
|
header.numEntries = mPM.entries.size();
|
||||||
header.numKeyEncRounds = mPM.getNumKeyEncRecords();
|
header.numKeyEncRounds = mPM.getNumKeyEncRecords();
|
||||||
|
|
||||||
@@ -165,7 +166,7 @@ public class PwDbV3Output {
|
|||||||
header.contentsHash = md.digest();
|
header.contentsHash = md.digest();
|
||||||
|
|
||||||
// Output header
|
// Output header
|
||||||
PwDbHeaderOutput pho = new PwDbHeaderOutput(header, os);
|
PwDbHeaderOutputV3 pho = new PwDbHeaderOutputV3(header, os);
|
||||||
try {
|
try {
|
||||||
pho.output();
|
pho.output();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@@ -179,9 +180,10 @@ public class PwDbV3Output {
|
|||||||
//long size = 0;
|
//long size = 0;
|
||||||
|
|
||||||
// Groups
|
// Groups
|
||||||
for ( int i = 0; i < mPM.groups.size(); i++ ) {
|
Vector<PwGroup> groups = mPM.getGroups();
|
||||||
PwGroupV3 pg = mPM.groups.get(i);
|
for ( int i = 0; i < groups.size(); i++ ) {
|
||||||
PwGroupOutput pgo = new PwGroupOutput(pg, os);
|
PwGroupV3 pg = (PwGroupV3) groups.get(i);
|
||||||
|
PwGroupOutputV3 pgo = new PwGroupOutputV3(pg, os);
|
||||||
try {
|
try {
|
||||||
pgo.output();
|
pgo.output();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@@ -191,8 +193,8 @@ public class PwDbV3Output {
|
|||||||
|
|
||||||
// Entries
|
// Entries
|
||||||
for (int i = 0; i < mPM.entries.size(); i++ ) {
|
for (int i = 0; i < mPM.entries.size(); i++ ) {
|
||||||
PwEntryV3 pe = mPM.entries.get(i);
|
PwEntryV3 pe = (PwEntryV3) mPM.entries.get(i);
|
||||||
PwEntryOutput peo = new PwEntryOutput(pe, os);
|
PwEntryOutputV3 peo = new PwEntryOutputV3(pe, os);
|
||||||
try {
|
try {
|
||||||
peo.output();
|
peo.output();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@@ -202,24 +204,24 @@ public class PwDbV3Output {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void sortGroupsForOutput() {
|
private void sortGroupsForOutput() {
|
||||||
Vector<PwGroupV3> groupList = new Vector<PwGroupV3>();
|
Vector<PwGroup> groupList = new Vector<PwGroup>();
|
||||||
|
|
||||||
// Rebuild list according to coalation sorting order removing any orphaned groups
|
// Rebuild list according to coalation sorting order removing any orphaned groups
|
||||||
Vector<PwGroupV3> roots = mPM.getGrpRoots();
|
Vector<PwGroup> roots = mPM.getGrpRoots();
|
||||||
for ( int i = 0; i < roots.size(); i++ ) {
|
for ( int i = 0; i < roots.size(); i++ ) {
|
||||||
sortGroup(roots.get(i), groupList);
|
sortGroup((PwGroupV3) roots.get(i), groupList);
|
||||||
}
|
}
|
||||||
|
|
||||||
mPM.groups = groupList;
|
mPM.setGroups(groupList);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sortGroup(PwGroupV3 group, Vector<PwGroupV3> groupList) {
|
private void sortGroup(PwGroupV3 group, Vector<PwGroup> groupList) {
|
||||||
// Add current group
|
// Add current group
|
||||||
groupList.add(group);
|
groupList.add(group);
|
||||||
|
|
||||||
// Recurse over children
|
// Recurse over children
|
||||||
for ( int i = 0; i < group.childGroups.size(); i++ ) {
|
for ( int i = 0; i < group.childGroups.size(); i++ ) {
|
||||||
sortGroup(group.childGroups.get(i), groupList);
|
sortGroup((PwGroupV3) group.childGroups.get(i), groupList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import java.io.OutputStream;
|
|||||||
import com.keepassdroid.database.PwEntryV3;
|
import com.keepassdroid.database.PwEntryV3;
|
||||||
import com.keepassdroid.utils.Types;
|
import com.keepassdroid.utils.Types;
|
||||||
|
|
||||||
public class PwEntryOutput {
|
public class PwEntryOutputV3 {
|
||||||
// Constants
|
// Constants
|
||||||
public static final byte[] UUID_FIELD_TYPE = Types.writeShort(1);
|
public static final byte[] UUID_FIELD_TYPE = Types.writeShort(1);
|
||||||
public static final byte[] GROUPID_FIELD_TYPE = Types.writeShort(2);
|
public static final byte[] GROUPID_FIELD_TYPE = Types.writeShort(2);
|
||||||
@@ -61,7 +61,7 @@ public class PwEntryOutput {
|
|||||||
* @param pe
|
* @param pe
|
||||||
* @param os
|
* @param os
|
||||||
*/
|
*/
|
||||||
public PwEntryOutput(PwEntryV3 pe, OutputStream os) {
|
public PwEntryOutputV3(PwEntryV3 pe, OutputStream os) {
|
||||||
mPE = pe;
|
mPE = pe;
|
||||||
mOS = os;
|
mOS = os;
|
||||||
}
|
}
|
||||||
@@ -103,7 +103,7 @@ public class PwEntryOutput {
|
|||||||
outputBytes += userLen;
|
outputBytes += userLen;
|
||||||
|
|
||||||
// Password
|
// Password
|
||||||
byte[] password = mPE.getPassword();
|
byte[] password = mPE.getPasswordBytes();
|
||||||
mOS.write(PASSWORD_FIELD_TYPE);
|
mOS.write(PASSWORD_FIELD_TYPE);
|
||||||
mOS.write(Types.writeInt(password.length+1));
|
mOS.write(Types.writeInt(password.length+1));
|
||||||
mOS.write(password);
|
mOS.write(password);
|
||||||
@@ -26,7 +26,7 @@ import java.io.OutputStream;
|
|||||||
import com.keepassdroid.database.PwGroupV3;
|
import com.keepassdroid.database.PwGroupV3;
|
||||||
import com.keepassdroid.utils.Types;
|
import com.keepassdroid.utils.Types;
|
||||||
|
|
||||||
public class PwGroupOutput {
|
public class PwGroupOutputV3 {
|
||||||
// Constants
|
// Constants
|
||||||
public static final byte[] GROUPID_FIELD_TYPE = Types.writeShort(1);
|
public static final byte[] GROUPID_FIELD_TYPE = Types.writeShort(1);
|
||||||
public static final byte[] NAME_FIELD_TYPE = Types.writeShort(2);
|
public static final byte[] NAME_FIELD_TYPE = Types.writeShort(2);
|
||||||
@@ -53,7 +53,7 @@ public class PwGroupOutput {
|
|||||||
* @param pg
|
* @param pg
|
||||||
* @param os
|
* @param os
|
||||||
*/
|
*/
|
||||||
public PwGroupOutput(PwGroupV3 pg, OutputStream os) {
|
public PwGroupOutputV3(PwGroupV3 pg, OutputStream os) {
|
||||||
mPG = pg;
|
mPG = pg;
|
||||||
mOS = os;
|
mOS = os;
|
||||||
}
|
}
|
||||||
@@ -22,7 +22,6 @@ package com.keepassdroid.search;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
|
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
@@ -32,7 +31,9 @@ import android.database.sqlite.SQLiteOpenHelper;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.keepassdroid.Database;
|
import com.keepassdroid.Database;
|
||||||
|
import com.keepassdroid.database.PwEntry;
|
||||||
import com.keepassdroid.database.PwEntryV3;
|
import com.keepassdroid.database.PwEntryV3;
|
||||||
|
import com.keepassdroid.database.PwGroup;
|
||||||
import com.keepassdroid.database.PwGroupV3;
|
import com.keepassdroid.database.PwGroupV3;
|
||||||
import com.keepassdroid.utils.Types;
|
import com.keepassdroid.utils.Types;
|
||||||
|
|
||||||
@@ -96,7 +97,7 @@ public class SearchDbHelper {
|
|||||||
mDb.delete(SEARCH_TABLE, null, null);
|
mDb.delete(SEARCH_TABLE, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ContentValues buildNewEntryContent(PwEntryV3 entry) {
|
private ContentValues buildNewEntryContent(PwEntry entry) {
|
||||||
|
|
||||||
ContentValues cv = new ContentValues();
|
ContentValues cv = new ContentValues();
|
||||||
UUID uuid = Types.bytestoUUID(entry.uuid);
|
UUID uuid = Types.bytestoUUID(entry.uuid);
|
||||||
@@ -110,12 +111,12 @@ public class SearchDbHelper {
|
|||||||
return cv;
|
return cv;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void insertEntry(PwEntryV3 entry) {
|
public void insertEntry(PwEntry entry) {
|
||||||
ContentValues cv = buildNewEntryContent(entry);
|
ContentValues cv = buildNewEntryContent(entry);
|
||||||
mDb.insert(SEARCH_TABLE, null, cv);
|
mDb.insert(SEARCH_TABLE, null, cv);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void insertEntry(Vector<PwEntryV3> entries) {
|
public void insertEntry(Vector<? extends PwEntry> entries) {
|
||||||
mDb.beginTransaction();
|
mDb.beginTransaction();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -128,14 +129,14 @@ public class SearchDbHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateEntry(PwEntryV3 entry) {
|
public void updateEntry(PwEntry entry) {
|
||||||
ContentValues cv = buildNewEntryContent(entry);
|
ContentValues cv = buildNewEntryContent(entry);
|
||||||
String uuidStr = cv.getAsString(KEY_UUID);
|
String uuidStr = cv.getAsString(KEY_UUID);
|
||||||
|
|
||||||
mDb.update(SEARCH_TABLE, cv, KEY_UUID + " = ?", new String[] {uuidStr});
|
mDb.update(SEARCH_TABLE, cv, KEY_UUID + " = ?", new String[] {uuidStr});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteEntry(PwEntryV3 entry) {
|
public void deleteEntry(PwEntry entry) {
|
||||||
UUID uuid = Types.bytestoUUID(entry.uuid);
|
UUID uuid = Types.bytestoUUID(entry.uuid);
|
||||||
String uuidStr = uuid.toString();
|
String uuidStr = uuid.toString();
|
||||||
|
|
||||||
@@ -148,15 +149,15 @@ public class SearchDbHelper {
|
|||||||
|
|
||||||
PwGroupV3 group = new PwGroupV3();
|
PwGroupV3 group = new PwGroupV3();
|
||||||
group.name = "Search results";
|
group.name = "Search results";
|
||||||
group.childEntries = new Vector<PwEntryV3>();
|
group.childEntries = new Vector<PwEntry>();
|
||||||
group.childGroups = new Vector<PwGroupV3>();
|
group.setGroups(new Vector<PwGroup>());
|
||||||
|
|
||||||
cursor.moveToFirst();
|
cursor.moveToFirst();
|
||||||
while ( ! cursor.isAfterLast() ) {
|
while ( ! cursor.isAfterLast() ) {
|
||||||
String sUUID = cursor.getString(0);
|
String sUUID = cursor.getString(0);
|
||||||
UUID uuid = UUID.fromString(sUUID);
|
UUID uuid = UUID.fromString(sUUID);
|
||||||
Log.d("TAG", uuid.toString());
|
Log.d("TAG", uuid.toString());
|
||||||
PwEntryV3 entry = db.entries.get(uuid).get();
|
PwEntryV3 entry = (PwEntryV3) db.entries.get(uuid).get();
|
||||||
group.childEntries.add(entry);
|
group.childEntries.add(entry);
|
||||||
|
|
||||||
cursor.moveToNext();
|
cursor.moveToNext();
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ public class AppSettingsActivity extends LockingClosePreferenceActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setRounds(Database db, Preference rounds) {
|
private void setRounds(Database db, Preference rounds) {
|
||||||
rounds.setSummary(Integer.toString(db.pm.numKeyEncRounds));
|
rounds.setSummary(Long.toString(db.pm.getNumRounds()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,13 +32,13 @@ import com.android.keepass.R;
|
|||||||
import com.keepassdroid.Database;
|
import com.keepassdroid.Database;
|
||||||
import com.keepassdroid.ProgressTask;
|
import com.keepassdroid.ProgressTask;
|
||||||
import com.keepassdroid.app.App;
|
import com.keepassdroid.app.App;
|
||||||
import com.keepassdroid.database.PwDatabaseV3;
|
import com.keepassdroid.database.PwDatabase;
|
||||||
import com.keepassdroid.database.edit.OnFinish;
|
import com.keepassdroid.database.edit.OnFinish;
|
||||||
import com.keepassdroid.database.edit.SaveDB;
|
import com.keepassdroid.database.edit.SaveDB;
|
||||||
|
|
||||||
public class RoundsPreference extends DialogPreference {
|
public class RoundsPreference extends DialogPreference {
|
||||||
|
|
||||||
private PwDatabaseV3 mPM;
|
private PwDatabase mPM;
|
||||||
private TextView mRoundsView;
|
private TextView mRoundsView;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -49,8 +49,8 @@ public class RoundsPreference extends DialogPreference {
|
|||||||
|
|
||||||
Database db = App.getDB();
|
Database db = App.getDB();
|
||||||
mPM = db.pm;
|
mPM = db.pm;
|
||||||
int numRounds = mPM.numKeyEncRounds;
|
long numRounds = mPM.getNumRounds();
|
||||||
mRoundsView.setText(Integer.toString(numRounds));
|
mRoundsView.setText(Long.toString(numRounds));
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
@@ -82,8 +82,13 @@ public class RoundsPreference extends DialogPreference {
|
|||||||
rounds = 1;
|
rounds = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int oldRounds = mPM.numKeyEncRounds;
|
long oldRounds = mPM.getNumRounds();
|
||||||
mPM.numKeyEncRounds = rounds;
|
try {
|
||||||
|
mPM.setNumRonuds(rounds);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
Toast.makeText(getContext(), R.string.error_rounds_too_large, Toast.LENGTH_LONG).show();
|
||||||
|
mPM.setNumRonuds(Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
Handler handler = new Handler();
|
Handler handler = new Handler();
|
||||||
SaveDB save = new SaveDB(App.getDB(), new AfterSave(getContext(), handler, oldRounds));
|
SaveDB save = new SaveDB(App.getDB(), new AfterSave(getContext(), handler, oldRounds));
|
||||||
@@ -95,10 +100,10 @@ public class RoundsPreference extends DialogPreference {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class AfterSave extends OnFinish {
|
private class AfterSave extends OnFinish {
|
||||||
private int mOldRounds;
|
private long mOldRounds;
|
||||||
private Context mCtx;
|
private Context mCtx;
|
||||||
|
|
||||||
public AfterSave(Context ctx, Handler handler, int oldRounds) {
|
public AfterSave(Context ctx, Handler handler, long oldRounds) {
|
||||||
super(handler);
|
super(handler);
|
||||||
|
|
||||||
mCtx = ctx;
|
mCtx = ctx;
|
||||||
@@ -114,7 +119,7 @@ public class RoundsPreference extends DialogPreference {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
displayMessage(mCtx);
|
displayMessage(mCtx);
|
||||||
mPM.numKeyEncRounds = mOldRounds;
|
mPM.setNumRonuds(mOldRounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
super.run();
|
super.run();
|
||||||
|
|||||||
247
src/com/keepassdroid/stream/BetterCipherInputStream.java
Normal file
247
src/com/keepassdroid/stream/BetterCipherInputStream.java
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.keepassdroid.stream;
|
||||||
|
|
||||||
|
import java.io.FilterInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.security.GeneralSecurityException;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.NullCipher;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class wraps an {@code InputStream} and a cipher so that {@code read()}
|
||||||
|
* methods return data that are read from the underlying {@code InputStream} and
|
||||||
|
* processed by the cipher.
|
||||||
|
* <p>
|
||||||
|
* The cipher must be initialized for the requested operation before being used
|
||||||
|
* by a {@code BetterCipherInputStream}. For example, if a cipher initialized for
|
||||||
|
* decryption is used with a {@code BetterCipherInputStream}, the {@code
|
||||||
|
* BetterCipherInputStream} tries to read the data an decrypt them before returning.
|
||||||
|
*/
|
||||||
|
public class BetterCipherInputStream extends FilterInputStream {
|
||||||
|
|
||||||
|
private final Cipher cipher;
|
||||||
|
private static final int I_DEFAULT_BUFFER_SIZE = 8 * 1024;
|
||||||
|
private final byte[] i_buffer;
|
||||||
|
private int index; // index of the bytes to return from o_buffer
|
||||||
|
private byte[] o_buffer;
|
||||||
|
private boolean finished;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@code BetterCipherInputStream} instance for an {@code
|
||||||
|
* InputStream} and a cipher.
|
||||||
|
*
|
||||||
|
* @param is
|
||||||
|
* the input stream to read data from.
|
||||||
|
* @param c
|
||||||
|
* the cipher to process the data with.
|
||||||
|
*/
|
||||||
|
public BetterCipherInputStream(InputStream is, Cipher c) {
|
||||||
|
this(is, c, I_DEFAULT_BUFFER_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@code BetterCipherInputStream} instance for an {@code
|
||||||
|
* InputStream} and a cipher.
|
||||||
|
*
|
||||||
|
* @param is
|
||||||
|
* the input stream to read data from.
|
||||||
|
* @param c
|
||||||
|
* the cipher to process the data with.
|
||||||
|
* @param bufferSize
|
||||||
|
* size to buffer output from the cipher
|
||||||
|
*/
|
||||||
|
public BetterCipherInputStream(InputStream is, Cipher c, int bufferSize) {
|
||||||
|
super(is);
|
||||||
|
this.cipher = c;
|
||||||
|
i_buffer = new byte[bufferSize];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@code BetterCipherInputStream} instance for an {@code
|
||||||
|
* InputStream} without a cipher.
|
||||||
|
* <p>
|
||||||
|
* A {@code NullCipher} is created and used to process the data.
|
||||||
|
*
|
||||||
|
* @param is
|
||||||
|
* the input stream to read data from.
|
||||||
|
*/
|
||||||
|
protected BetterCipherInputStream(InputStream is) {
|
||||||
|
this(is, new NullCipher());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the next byte from this cipher input stream.
|
||||||
|
*
|
||||||
|
* @return the next byte, or {@code -1} if the end of the stream is reached.
|
||||||
|
* @throws IOException
|
||||||
|
* if an error occurs.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int read() throws IOException {
|
||||||
|
if (finished) {
|
||||||
|
return ((o_buffer == null) || (index == o_buffer.length))
|
||||||
|
? -1
|
||||||
|
: o_buffer[index++] & 0xFF;
|
||||||
|
}
|
||||||
|
if ((o_buffer != null) && (index < o_buffer.length)) {
|
||||||
|
return o_buffer[index++] & 0xFF;
|
||||||
|
}
|
||||||
|
index = 0;
|
||||||
|
o_buffer = null;
|
||||||
|
int num_read;
|
||||||
|
while (o_buffer == null) {
|
||||||
|
if ((num_read = in.read(i_buffer)) == -1) {
|
||||||
|
try {
|
||||||
|
o_buffer = cipher.doFinal();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new IOException(e.getMessage());
|
||||||
|
}
|
||||||
|
finished = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
o_buffer = cipher.update(i_buffer, 0, num_read);
|
||||||
|
}
|
||||||
|
return read();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the next {@code b.length} bytes from this input stream into buffer
|
||||||
|
* {@code b}.
|
||||||
|
*
|
||||||
|
* @param b
|
||||||
|
* the buffer to be filled with data.
|
||||||
|
* @return the number of bytes filled into buffer {@code b}, or {@code -1}
|
||||||
|
* if the end of the stream is reached.
|
||||||
|
* @throws IOException
|
||||||
|
* if an error occurs.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int read(byte[] b) throws IOException {
|
||||||
|
return read(b, 0, b.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the next {@code len} bytes from this input stream into buffer
|
||||||
|
* {@code b} starting at offset {@code off}.
|
||||||
|
* <p>
|
||||||
|
* if {@code b} is {@code null}, the next {@code len} bytes are read and
|
||||||
|
* discarded.
|
||||||
|
*
|
||||||
|
* @param b
|
||||||
|
* the buffer to be filled with data.
|
||||||
|
* @param off
|
||||||
|
* the offset to start in the buffer.
|
||||||
|
* @param len
|
||||||
|
* the maximum number of bytes to read.
|
||||||
|
* @return the number of bytes filled into buffer {@code b}, or {@code -1}
|
||||||
|
* of the of the stream is reached.
|
||||||
|
* @throws IOException
|
||||||
|
* if an error occurs.
|
||||||
|
* @throws NullPointerException
|
||||||
|
* if the underlying input stream is {@code null}.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int read(byte[] b, int off, int len) throws IOException {
|
||||||
|
if (in == null) {
|
||||||
|
throw new NullPointerException("Underlying input stream is null");
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_b;
|
||||||
|
int i;
|
||||||
|
for (i=0; i<len; i++) {
|
||||||
|
if ((read_b = read()) == -1) {
|
||||||
|
return (i == 0) ? -1 : i;
|
||||||
|
}
|
||||||
|
if (b != null) {
|
||||||
|
b[off+i] = (byte) read_b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Skips up to n bytes from this input stream.
|
||||||
|
* <p>
|
||||||
|
* The number of bytes skipped depends on the result of a call to
|
||||||
|
* {@link BetterCipherInputStream#available() available}. The smaller of n and the
|
||||||
|
* result are the number of bytes being skipped.
|
||||||
|
*
|
||||||
|
* @param n
|
||||||
|
* the number of bytes that should be skipped.
|
||||||
|
* @return the number of bytes actually skipped.
|
||||||
|
* @throws IOException
|
||||||
|
* if an error occurs
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public long skip(long n) throws IOException {
|
||||||
|
long i = 0;
|
||||||
|
int available = available();
|
||||||
|
if (available < n) {
|
||||||
|
n = available;
|
||||||
|
}
|
||||||
|
while ((i < n) && (read() != -1)) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of bytes available without blocking.
|
||||||
|
*
|
||||||
|
* @return the number of bytes available, currently zero.
|
||||||
|
* @throws IOException
|
||||||
|
* if an error occurs
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int available() throws IOException {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes this {@code BetterCipherInputStream}, also closes the underlying input
|
||||||
|
* stream and call {@code doFinal} on the cipher object.
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
* if an error occurs.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
in.close();
|
||||||
|
try {
|
||||||
|
cipher.doFinal();
|
||||||
|
} catch (GeneralSecurityException ignore) {
|
||||||
|
//do like RI does
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this input stream supports {@code mark} and
|
||||||
|
* {@code reset}, which it does not.
|
||||||
|
*
|
||||||
|
* @return false, since this input stream does not support {@code mark} and
|
||||||
|
* {@code reset}.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean markSupported() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -37,7 +37,7 @@ public class PwEntryTest extends AndroidTestCase {
|
|||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
|
|
||||||
mPE = TestData.GetTest1(getContext()).entries.get(0);
|
mPE = (PwEntryV3) TestData.GetTest1(getContext()).entries.get(0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ public class PwEntryTest extends AndroidTestCase {
|
|||||||
String sPass = "12345";
|
String sPass = "12345";
|
||||||
byte[] password = sPass.getBytes("UTF-8");
|
byte[] password = sPass.getBytes("UTF-8");
|
||||||
|
|
||||||
assertArrayEquals(password, mPE.getPassword());
|
assertArrayEquals(password, mPE.getPasswordBytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCreation() {
|
public void testCreation() {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public class PwGroupTest extends AndroidTestCase {
|
|||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
|
|
||||||
mPG = TestData.GetTest1(getContext()).groups.get(0);
|
mPG = (PwGroupV3) TestData.GetTest1(getContext()).getGroups().get(0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,13 +21,13 @@ package com.keepassdroid.tests.database;
|
|||||||
|
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.test.AndroidTestCase;
|
import android.test.AndroidTestCase;
|
||||||
|
|
||||||
import com.keepassdroid.Database;
|
import com.keepassdroid.Database;
|
||||||
import com.keepassdroid.database.PwDatabaseV3;
|
import com.keepassdroid.database.PwDatabaseV3;
|
||||||
import com.keepassdroid.database.PwEntryV3;
|
import com.keepassdroid.database.PwEntry;
|
||||||
|
import com.keepassdroid.database.PwGroup;
|
||||||
import com.keepassdroid.database.PwGroupV3;
|
import com.keepassdroid.database.PwGroupV3;
|
||||||
import com.keepassdroid.database.edit.DeleteGroup;
|
import com.keepassdroid.database.edit.DeleteGroup;
|
||||||
import com.keepassdroid.search.SearchDbHelper;
|
import com.keepassdroid.search.SearchDbHelper;
|
||||||
@@ -54,8 +54,8 @@ public class DeleteEntry extends AndroidTestCase {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PwDatabaseV3 pm = (PwDatabaseV3) db.pm;
|
||||||
PwGroupV3 group1 = getGroup(db.pm, GROUP1_NAME);
|
PwGroup group1 = getGroup(pm, GROUP1_NAME);
|
||||||
assertNotNull("Could not find group1", group1);
|
assertNotNull("Could not find group1", group1);
|
||||||
|
|
||||||
// Delete the group
|
// Delete the group
|
||||||
@@ -63,10 +63,10 @@ public class DeleteEntry extends AndroidTestCase {
|
|||||||
task.run();
|
task.run();
|
||||||
|
|
||||||
// Verify the entries were deleted
|
// Verify the entries were deleted
|
||||||
PwEntryV3 entry1 = getEntry(db.pm, ENTRY1_NAME);
|
PwEntry entry1 = getEntry(pm, ENTRY1_NAME);
|
||||||
assertNull("Entry 1 was not removed", entry1);
|
assertNull("Entry 1 was not removed", entry1);
|
||||||
|
|
||||||
PwEntryV3 entry2 = getEntry(db.pm, ENTRY2_NAME);
|
PwEntry entry2 = getEntry(pm, ENTRY2_NAME);
|
||||||
assertNull("Entry 2 was not removed", entry2);
|
assertNull("Entry 2 was not removed", entry2);
|
||||||
|
|
||||||
// Verify the entries were removed from the search index
|
// Verify the entries were removed from the search index
|
||||||
@@ -80,17 +80,17 @@ public class DeleteEntry extends AndroidTestCase {
|
|||||||
assertEquals("Entry2 was not removed from the search results", 0, results2.childEntries.size());
|
assertEquals("Entry2 was not removed from the search results", 0, results2.childEntries.size());
|
||||||
|
|
||||||
// Verify the group was deleted
|
// Verify the group was deleted
|
||||||
group1 = getGroup(db.pm, GROUP1_NAME);
|
group1 = getGroup(pm, GROUP1_NAME);
|
||||||
assertNull("Group 1 was not removed.", group1);
|
assertNull("Group 1 was not removed.", group1);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private PwEntryV3 getEntry(PwDatabaseV3 pm, String name) {
|
private PwEntry getEntry(PwDatabaseV3 pm, String name) {
|
||||||
Vector<PwEntryV3> entries = pm.entries;
|
Vector<PwEntry> entries = pm.entries;
|
||||||
for ( int i = 0; i < entries.size(); i++ ) {
|
for ( int i = 0; i < entries.size(); i++ ) {
|
||||||
PwEntryV3 entry = entries.get(i);
|
PwEntry entry = entries.get(i);
|
||||||
if ( entry.title.equals(name) ) {
|
if ( entry.title.equals(name) ) {
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
@@ -100,11 +100,11 @@ public class DeleteEntry extends AndroidTestCase {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private PwGroupV3 getGroup(PwDatabaseV3 pm, String name) {
|
private PwGroup getGroup(PwDatabaseV3 pm, String name) {
|
||||||
Vector<PwGroupV3> groups = pm.groups;
|
Vector<PwGroup> groups = pm.getGroups();
|
||||||
for ( int i = 0; i < groups.size(); i++ ) {
|
for ( int i = 0; i < groups.size(); i++ ) {
|
||||||
PwGroupV3 group = groups.get(i);
|
PwGroup group = groups.get(i);
|
||||||
if ( group.name.equals(name) ) {
|
if ( group.getName().equals(name) ) {
|
||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,9 @@ public class Kdb4 extends AndroidTestCase {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
is.close();
|
||||||
|
|
||||||
assertTrue(false);
|
assertTrue(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public class Kdb4Header extends AndroidTestCase {
|
|||||||
|
|
||||||
assertTrue(db.dataCipher.equals(CipherFactory.AES_CIPHER));
|
assertTrue(db.dataCipher.equals(CipherFactory.AES_CIPHER));
|
||||||
|
|
||||||
am.close();
|
is.close();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,6 +65,6 @@ public class TestData {
|
|||||||
GetDb1(ctx);
|
GetDb1(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mDb1.pm;
|
return (PwDatabaseV3) mDb1.pm;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ import com.keepassdroid.database.PwDatabaseV3;
|
|||||||
import com.keepassdroid.database.PwDbHeader;
|
import com.keepassdroid.database.PwDbHeader;
|
||||||
import com.keepassdroid.database.PwDbHeaderV3;
|
import com.keepassdroid.database.PwDbHeaderV3;
|
||||||
import com.keepassdroid.database.exception.PwDbOutputException;
|
import com.keepassdroid.database.exception.PwDbOutputException;
|
||||||
import com.keepassdroid.database.save.PwDbHeaderOutput;
|
import com.keepassdroid.database.save.PwDbHeaderOutputV3;
|
||||||
import com.keepassdroid.database.save.PwDbV3Output;
|
import com.keepassdroid.database.save.PwDbV3Output;
|
||||||
import com.keepassdroid.stream.NullOutputStream;
|
import com.keepassdroid.stream.NullOutputStream;
|
||||||
import com.keepassdroid.tests.database.TestData;
|
import com.keepassdroid.tests.database.TestData;
|
||||||
@@ -99,7 +99,7 @@ public class PwManagerOutputTest extends AndroidTestCase {
|
|||||||
PwDbHeaderV3 header = pActual.outputHeader(bActual);
|
PwDbHeaderV3 header = pActual.outputHeader(bActual);
|
||||||
|
|
||||||
ByteArrayOutputStream bExpected = new ByteArrayOutputStream();
|
ByteArrayOutputStream bExpected = new ByteArrayOutputStream();
|
||||||
PwDbHeaderOutput outExpected = new PwDbHeaderOutput(mPM.dbHeader, bExpected);
|
PwDbHeaderOutputV3 outExpected = new PwDbHeaderOutputV3(mPM.dbHeader, bExpected);
|
||||||
outExpected.output();
|
outExpected.output();
|
||||||
|
|
||||||
assertHeadersEquals(mPM.dbHeader, header);
|
assertHeadersEquals(mPM.dbHeader, header);
|
||||||
|
|||||||
Reference in New Issue
Block a user