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" />
|
||||
</intent-filter>
|
||||
</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 -->
|
||||
<!-- whenever the user invokes search while in this Activity. -->
|
||||
<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) {
|
||||
|
||||
|
||||
LOGD("InputSize: %d; OutputSize: %d", inputLen, outputSize);
|
||||
LOGD("InputSize: %d; InputOffset: %d, OutputOffset: %d, OutputSize: %d", inputLen, inputOffset,
|
||||
outputOffset, outputSize);
|
||||
if ( inputLen == 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);
|
||||
|
||||
free(c_output);
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
<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_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="FileNotFound">File not found.</string>
|
||||
<string name="group">Group</string>
|
||||
|
||||
@@ -34,8 +34,10 @@ import java.util.Vector;
|
||||
import android.content.Context;
|
||||
import android.os.Debug;
|
||||
|
||||
import com.keepassdroid.database.PwDatabaseV3;
|
||||
import com.keepassdroid.database.PwEntryV3;
|
||||
import com.keepassdroid.database.PwDatabase;
|
||||
import com.keepassdroid.database.PwEntry;
|
||||
import com.keepassdroid.database.PwGroup;
|
||||
import com.keepassdroid.database.PwGroupId;
|
||||
import com.keepassdroid.database.PwGroupV3;
|
||||
import com.keepassdroid.database.exception.InvalidDBSignatureException;
|
||||
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.ImporterFactory;
|
||||
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.utils.Types;
|
||||
|
||||
@@ -54,11 +56,11 @@ import com.keepassdroid.utils.Types;
|
||||
* @author bpellin
|
||||
*/
|
||||
public class Database {
|
||||
public HashMap<Integer, WeakReference<PwGroupV3>> groups = new HashMap<Integer, WeakReference<PwGroupV3>>();
|
||||
public HashMap<UUID, WeakReference<PwEntryV3>> entries = new HashMap<UUID, WeakReference<PwEntryV3>>();
|
||||
public HashMap<PwGroupV3, WeakReference<PwGroupV3>> dirty = new HashMap<PwGroupV3, WeakReference<PwGroupV3>>();
|
||||
public PwGroupV3 root;
|
||||
public PwDatabaseV3 pm;
|
||||
public HashMap<PwGroupId, WeakReference<PwGroup>> groups = new HashMap<PwGroupId, WeakReference<PwGroup>>();
|
||||
public HashMap<UUID, WeakReference<PwEntry>> entries = new HashMap<UUID, WeakReference<PwEntry>>();
|
||||
public HashMap<PwGroup, WeakReference<PwGroup>> dirty = new HashMap<PwGroup, WeakReference<PwGroup>>();
|
||||
public PwGroup root;
|
||||
public PwDatabase pm;
|
||||
public String mFilename;
|
||||
public SearchDbHelper searchHelper;
|
||||
public boolean indexBuilt = false;
|
||||
@@ -119,7 +121,6 @@ public class Database {
|
||||
|
||||
pm = Importer.openDatabase(bis, password, keyfile, status);
|
||||
if ( pm != null ) {
|
||||
pm.constructTree(null);
|
||||
populateGlobals(null);
|
||||
}
|
||||
|
||||
@@ -138,7 +139,7 @@ public class Database {
|
||||
initSearch();
|
||||
|
||||
searchHelper.open();
|
||||
searchHelper.insertEntry(pm.entries);
|
||||
searchHelper.insertEntry(pm.getEntries());
|
||||
/*for ( int i = 0; i < pm.entries.size(); i++) {
|
||||
PwEntryV3 entry = pm.entries.get(i);
|
||||
if ( ! entry.isMetaStream() ) {
|
||||
@@ -170,7 +171,7 @@ public class Database {
|
||||
//BufferedOutputStream bos = new BufferedOutputStream(fos);
|
||||
|
||||
//PwDbV3Output pmo = new PwDbV3Output(pm, bos, App.getCalendar());
|
||||
PwDbV3Output pmo = new PwDbV3Output(pm, fos);
|
||||
PwDbOutput pmo = PwDbOutput.getInstance(pm, fos);
|
||||
pmo.output();
|
||||
//bos.flush();
|
||||
//bos.close();
|
||||
@@ -187,30 +188,30 @@ public class Database {
|
||||
|
||||
}
|
||||
|
||||
private void populateGlobals(PwGroupV3 currentGroup) {
|
||||
private void populateGlobals(PwGroup currentGroup) {
|
||||
if (currentGroup == null) {
|
||||
Vector<PwGroupV3> rootChildGroups = pm.getGrpRoots();
|
||||
Vector<? extends PwGroup> rootChildGroups = pm.getGrpRoots();
|
||||
for (int i = 0; i < rootChildGroups.size(); i++ ){
|
||||
PwGroupV3 cur = rootChildGroups.elementAt(i);
|
||||
root = cur.parent;
|
||||
groups.put(cur.groupId, new WeakReference<PwGroupV3>(cur));
|
||||
PwGroup cur = rootChildGroups.elementAt(i);
|
||||
root = cur.getParent();
|
||||
groups.put(cur.getId(), new WeakReference<PwGroup>(cur));
|
||||
populateGlobals(cur);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Vector<PwGroupV3> childGroups = currentGroup.childGroups;
|
||||
Vector<PwEntryV3> childEntries = currentGroup.childEntries;
|
||||
Vector<PwGroup> childGroups = currentGroup.childGroups;
|
||||
Vector<PwEntry> childEntries = currentGroup.childEntries;
|
||||
|
||||
for (int i = 0; i < childEntries.size(); i++ ) {
|
||||
PwEntryV3 cur = childEntries.elementAt(i);
|
||||
entries.put(Types.bytestoUUID(cur.uuid), new WeakReference<PwEntryV3>(cur));
|
||||
PwEntry cur = childEntries.elementAt(i);
|
||||
entries.put(Types.bytestoUUID(cur.uuid), new WeakReference<PwEntry>(cur));
|
||||
}
|
||||
|
||||
for (int i = 0; i < childGroups.size(); i++ ) {
|
||||
PwGroupV3 cur = childGroups.elementAt(i);
|
||||
groups.put(cur.groupId, new WeakReference<PwGroupV3>(cur));
|
||||
PwGroup cur = childGroups.elementAt(i);
|
||||
groups.put(cur.getId(), new WeakReference<PwGroup>(cur));
|
||||
populateGlobals(cur);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,12 +20,11 @@
|
||||
package com.keepassdroid;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
@@ -51,7 +50,7 @@ import android.widget.Toast;
|
||||
import com.android.keepass.KeePass;
|
||||
import com.android.keepass.R;
|
||||
import com.keepassdroid.app.App;
|
||||
import com.keepassdroid.database.PwDate;
|
||||
import com.keepassdroid.database.PwEntry;
|
||||
import com.keepassdroid.database.PwEntryV3;
|
||||
import com.keepassdroid.intents.Intents;
|
||||
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_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);
|
||||
|
||||
i.putExtra(KEY_ENTRY, pw.uuid);
|
||||
@@ -84,7 +83,7 @@ public class EntryActivity extends LockCloseActivity {
|
||||
act.startActivityForResult(i,0);
|
||||
}
|
||||
|
||||
private PwEntryV3 mEntry;
|
||||
private PwEntry mEntry;
|
||||
private Timer mTimer = new Timer();
|
||||
private boolean mShowPassword;
|
||||
private int mPos;
|
||||
@@ -113,8 +112,7 @@ public class EntryActivity extends LockCloseActivity {
|
||||
mEntry = db.entries.get(uuid).get();
|
||||
|
||||
// Update last access time.
|
||||
Calendar cal = Calendar.getInstance();
|
||||
mEntry.tLastAccess = new PwDate(cal.getTime());
|
||||
mEntry.stampLastAccess();
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
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();
|
||||
|
||||
if ( action.equals(Intents.COPY_USERNAME) ) {
|
||||
String username = mEntry.username;
|
||||
String username = mEntry.getUsername();
|
||||
if ( username.length() > 0 ) {
|
||||
timeoutCopyToClipboard(mEntry.username);
|
||||
timeoutCopyToClipboard(username);
|
||||
}
|
||||
} else if ( action.equals(Intents.COPY_PASSWORD) ) {
|
||||
String password = new String(mEntry.getPassword());
|
||||
@@ -199,20 +197,21 @@ public class EntryActivity extends LockCloseActivity {
|
||||
|
||||
private void fillData() {
|
||||
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_password, new String(mEntry.getPassword()));
|
||||
populateText(R.id.entry_password, mEntry.getPassword());
|
||||
setPasswordStyle();
|
||||
|
||||
DateFormat df = DateFormat.getInstance();
|
||||
populateText(R.id.entry_created, df.format(mEntry.tCreation.getJDate()));
|
||||
populateText(R.id.entry_modified, df.format(mEntry.tLastMod.getJDate()));
|
||||
populateText(R.id.entry_accessed, df.format(mEntry.tLastAccess.getJDate()));
|
||||
populateText(R.id.entry_created, df.format(mEntry.getCreate()));
|
||||
populateText(R.id.entry_modified, df.format(mEntry.getMod()));
|
||||
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);
|
||||
} 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);
|
||||
|
||||
@@ -317,7 +316,7 @@ public class EntryActivity extends LockCloseActivity {
|
||||
return true;
|
||||
|
||||
case MENU_COPY_USER:
|
||||
timeoutCopyToClipboard(mEntry.username);
|
||||
timeoutCopyToClipboard(mEntry.getUsername());
|
||||
return true;
|
||||
|
||||
case MENU_COPY_PASS:
|
||||
|
||||
@@ -24,7 +24,6 @@ import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
@@ -42,7 +41,9 @@ import com.android.keepass.KeePass;
|
||||
import com.android.keepass.R;
|
||||
import com.keepassdroid.app.App;
|
||||
import com.keepassdroid.database.PwDate;
|
||||
import com.keepassdroid.database.PwEntry;
|
||||
import com.keepassdroid.database.PwEntryV3;
|
||||
import com.keepassdroid.database.PwGroup;
|
||||
import com.keepassdroid.database.PwGroupV3;
|
||||
import com.keepassdroid.database.edit.AddEntry;
|
||||
import com.keepassdroid.database.edit.OnFinish;
|
||||
@@ -62,7 +63,11 @@ public class EntryEditActivity extends LockCloseActivity {
|
||||
private boolean mShowPassword = false;
|
||||
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);
|
||||
|
||||
i.putExtra(KEY_ENTRY, pw.uuid);
|
||||
@@ -70,9 +75,14 @@ public class EntryEditActivity extends LockCloseActivity {
|
||||
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);
|
||||
|
||||
PwGroupV3 parent = (PwGroupV3) pw;
|
||||
i.putExtra(KEY_PARENT, parent.groupId);
|
||||
|
||||
act.startActivityForResult(i, 0);
|
||||
@@ -105,7 +115,7 @@ public class EntryEditActivity extends LockCloseActivity {
|
||||
UUID uuid = Types.bytestoUUID(uuidBytes);
|
||||
assert(uuid != null);
|
||||
|
||||
mEntry = db.entries.get(uuid).get();
|
||||
mEntry = (PwEntryV3) db.entries.get(uuid).get();
|
||||
mIsNew = false;
|
||||
|
||||
fillData();
|
||||
@@ -179,7 +189,7 @@ public class EntryEditActivity extends LockCloseActivity {
|
||||
OnFinish onFinish = act.new AfterSave(new Handler());
|
||||
|
||||
if ( mIsNew ) {
|
||||
task = new AddEntry(App.getDB(), newEntry, onFinish);
|
||||
task = AddEntry.getInstance(App.getDB(), newEntry, onFinish);
|
||||
} else {
|
||||
task = new UpdateEntry(App.getDB(), mEntry, newEntry, onFinish);
|
||||
}
|
||||
@@ -259,7 +269,7 @@ public class EntryEditActivity extends LockCloseActivity {
|
||||
|
||||
private void fillData() {
|
||||
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);
|
||||
|
||||
String password = new String(mEntry.getPassword());
|
||||
|
||||
@@ -21,7 +21,6 @@ package com.keepassdroid;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
@@ -39,10 +38,15 @@ import android.widget.AdapterView.AdapterContextMenuInfo;
|
||||
import com.android.keepass.KeePass;
|
||||
import com.android.keepass.R;
|
||||
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.edit.AddGroup;
|
||||
|
||||
public class GroupActivity extends GroupBaseActivity {
|
||||
public abstract class GroupActivity extends GroupBaseActivity {
|
||||
|
||||
public static final int UNINIT = -1;
|
||||
public static final int VIEW_ONLY = 0;
|
||||
@@ -50,11 +54,22 @@ public class GroupActivity extends GroupBaseActivity {
|
||||
public static final int FULL = 2;
|
||||
private static final String TAG = "Group Activity:";
|
||||
|
||||
public static void Launch(Activity act, PwGroupV3 group, int mode) {
|
||||
Intent i = new Intent(act, GroupActivity.class);
|
||||
|
||||
if ( group != null ) {
|
||||
i.putExtra(KEY_ENTRY, group.groupId);
|
||||
public static void Launch(Activity act, PwGroup group, int mode) {
|
||||
Intent i;
|
||||
|
||||
PwDatabase pm = App.getDB().pm;
|
||||
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);
|
||||
@@ -62,6 +77,9 @@ public class GroupActivity extends GroupBaseActivity {
|
||||
act.startActivityForResult(i,0);
|
||||
}
|
||||
|
||||
protected abstract PwGroupId retrieveGroupId(Intent i);
|
||||
protected abstract PwGroup getGroup();
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@@ -89,13 +107,13 @@ public class GroupActivity extends GroupBaseActivity {
|
||||
}
|
||||
Log.w(TAG, "Set view");
|
||||
|
||||
int id = intent.getIntExtra(KEY_ENTRY, -1);
|
||||
PwGroupId id = retrieveGroupId(intent);
|
||||
|
||||
Database db = App.getDB();
|
||||
if ( id == -1 ) {
|
||||
if ( id == null ) {
|
||||
mGroup = db.root;
|
||||
} else {
|
||||
WeakReference<PwGroupV3> wPw = db.groups.get(id);
|
||||
WeakReference<PwGroup> wPw = db.groups.get(id);
|
||||
mGroup = wPw.get();
|
||||
}
|
||||
Log.w(TAG, "Retrieved group");
|
||||
@@ -104,7 +122,6 @@ public class GroupActivity extends GroupBaseActivity {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ( mode == FULL || mode == ADD_GROUP_ONLY ) {
|
||||
// Add Group button
|
||||
@@ -155,10 +172,10 @@ public class GroupActivity extends GroupBaseActivity {
|
||||
|
||||
private class GroupAddHandler implements View.OnClickListener {
|
||||
private GroupBaseActivity mAct;
|
||||
private PwGroupV3 mGroup;
|
||||
private PwGroup mGroup;
|
||||
private GroupCreateDialog mDialog;
|
||||
|
||||
GroupAddHandler(GroupBaseActivity act, PwGroupV3 group) {
|
||||
GroupAddHandler(GroupBaseActivity act, PwGroup group) {
|
||||
mAct = act;
|
||||
mGroup = group;
|
||||
}
|
||||
@@ -178,7 +195,7 @@ public class GroupActivity extends GroupBaseActivity {
|
||||
if ( ! mDialog.canceled() && res.length() > 0 ) {
|
||||
GroupActivity act = GroupActivity.this;
|
||||
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);
|
||||
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;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.view.Menu;
|
||||
@@ -37,7 +35,7 @@ import android.widget.Toast;
|
||||
import com.android.keepass.KeePass;
|
||||
import com.android.keepass.R;
|
||||
import com.keepassdroid.app.App;
|
||||
import com.keepassdroid.database.PwGroupV3;
|
||||
import com.keepassdroid.database.PwGroup;
|
||||
import com.keepassdroid.database.edit.OnFinish;
|
||||
import com.keepassdroid.settings.AppSettingsActivity;
|
||||
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_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);
|
||||
|
||||
if ( group != null ) {
|
||||
@@ -63,6 +62,7 @@ public abstract class GroupBaseActivity extends LockCloseListActivity {
|
||||
|
||||
act.startActivityForResult(i,0);
|
||||
}
|
||||
*/
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
@@ -117,7 +117,7 @@ public abstract class GroupBaseActivity extends LockCloseListActivity {
|
||||
|
||||
protected void setGroupTitle() {
|
||||
if ( mGroup != null ) {
|
||||
String name = mGroup.name;
|
||||
String name = mGroup.getName();
|
||||
if ( name != null && name.length() > 0 ) {
|
||||
TextView tv = (TextView) findViewById(R.id.group_name);
|
||||
if ( tv != null ) {
|
||||
|
||||
@@ -30,21 +30,21 @@ import android.widget.TextView;
|
||||
|
||||
import com.android.keepass.R;
|
||||
import com.keepassdroid.app.App;
|
||||
import com.keepassdroid.database.PwEntryV3;
|
||||
import com.keepassdroid.database.PwEntry;
|
||||
import com.keepassdroid.database.edit.DeleteEntry;
|
||||
import com.keepassdroid.settings.PrefsUtil;
|
||||
|
||||
public class PwEntryView extends ClickView {
|
||||
|
||||
private GroupBaseActivity mAct;
|
||||
private PwEntryV3 mPw;
|
||||
private PwEntry mPw;
|
||||
private TextView mTv;
|
||||
private int mPos;
|
||||
|
||||
private static final int MENU_OPEN = Menu.FIRST;
|
||||
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);
|
||||
mAct = act;
|
||||
mPw = pw;
|
||||
|
||||
@@ -21,14 +21,15 @@ package com.keepassdroid;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
|
||||
import com.keepassdroid.database.PwEntryV3;
|
||||
import com.keepassdroid.database.PwGroupV3;
|
||||
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
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 {
|
||||
|
||||
@Override
|
||||
@@ -46,10 +47,10 @@ public class PwListAdapter extends BaseAdapter {
|
||||
}
|
||||
|
||||
private GroupBaseActivity mAct;
|
||||
private PwGroupV3 mGroup;
|
||||
private Vector<PwEntryV3> filteredEntries;
|
||||
private PwGroup mGroup;
|
||||
private Vector<PwEntry> filteredEntries;
|
||||
|
||||
public PwListAdapter(GroupBaseActivity act, PwGroupV3 group) {
|
||||
public PwListAdapter(GroupBaseActivity act, PwGroup group) {
|
||||
mAct = act;
|
||||
mGroup = group;
|
||||
|
||||
@@ -58,7 +59,7 @@ public class PwListAdapter extends BaseAdapter {
|
||||
}
|
||||
|
||||
private void filter() {
|
||||
filteredEntries = new Vector<PwEntryV3>();
|
||||
filteredEntries = new Vector<PwEntry>();
|
||||
|
||||
for (int i = 0; i < mGroup.childEntries.size(); 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) {
|
||||
mBuffered = 0;
|
||||
|
||||
int outputSize = engineGetOutputSize(inputLen);
|
||||
|
||||
@@ -145,7 +144,11 @@ public class NativeAESCipherSpi extends CipherSpi {
|
||||
|
||||
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);
|
||||
@@ -163,10 +166,12 @@ public class NativeAESCipherSpi extends CipherSpi {
|
||||
@Override
|
||||
protected int engineGetOutputSize(int inputLen) {
|
||||
int totalLen = mBuffered + inputLen;
|
||||
|
||||
|
||||
/*
|
||||
if ( ! mPadding || ! mEncrypting ) {
|
||||
return totalLen;
|
||||
}
|
||||
*/
|
||||
|
||||
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) {
|
||||
mBuffered = (mBuffered + inputLen) % AES_BLOCK_SIZE;
|
||||
return nativeUpdate(mCtxPtr, input, inputOffset, inputLen, output, outputOffset, engineGetOutputSize(inputLen));
|
||||
int outputSize = 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);
|
||||
|
||||
@@ -27,6 +27,7 @@ import java.io.UnsupportedEncodingException;
|
||||
import java.security.DigestOutputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Vector;
|
||||
|
||||
import com.keepassdroid.crypto.finalkey.FinalKey;
|
||||
import com.keepassdroid.crypto.finalkey.FinalKeyFactory;
|
||||
@@ -37,7 +38,7 @@ public abstract class PwDatabase {
|
||||
|
||||
public byte masterKey[] = new byte[32];
|
||||
public byte[] finalKey;
|
||||
|
||||
|
||||
public void makeFinalKey(byte[] masterSeed, byte[] masterSeed2, int numRounds) throws IOException {
|
||||
|
||||
// Write checksum Checksum
|
||||
@@ -203,4 +204,14 @@ public abstract class PwDatabase {
|
||||
|
||||
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";
|
||||
|
||||
// Special entry for settings
|
||||
public PwEntryV3 metaInfo;
|
||||
public PwEntry metaInfo;
|
||||
|
||||
// all entries
|
||||
public Vector<PwEntryV3> entries = new Vector<PwEntryV3>();
|
||||
public Vector<PwEntry> entries = new Vector<PwEntry>();
|
||||
// all groups
|
||||
public Vector<PwGroupV3> groups = new Vector<PwGroupV3>();
|
||||
private Vector<PwGroup> groups = new Vector<PwGroup>();
|
||||
// Algorithm used to encrypt the database
|
||||
public int algorithm;
|
||||
public int numKeyEncRounds;
|
||||
@@ -74,12 +74,28 @@ public class PwDatabaseV3 extends PwDatabase {
|
||||
public int getNumKeyEncRecords() {
|
||||
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;
|
||||
Vector<PwGroupV3> kids = new Vector<PwGroupV3>();
|
||||
Vector<PwGroup> kids = new Vector<PwGroup>();
|
||||
for( int i=0; i < groups.size(); i++ ) {
|
||||
PwGroupV3 grp = groups.elementAt( i );
|
||||
PwGroupV3 grp = (PwGroupV3) groups.elementAt( i );
|
||||
if( grp.level == target )
|
||||
kids.addElement( grp );
|
||||
}
|
||||
@@ -88,7 +104,7 @@ public class PwDatabaseV3 extends PwDatabase {
|
||||
|
||||
public int getRootGroupId() {
|
||||
for ( int i = 0; i < groups.size(); i++ ) {
|
||||
PwGroupV3 grp = groups.elementAt(i);
|
||||
PwGroupV3 grp = (PwGroupV3) groups.elementAt(i);
|
||||
if ( grp.level == 0 ) {
|
||||
return grp.groupId;
|
||||
}
|
||||
@@ -97,35 +113,34 @@ public class PwDatabaseV3 extends PwDatabase {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public Vector<PwGroupV3> getGrpChildren( PwGroupV3 parent ) {
|
||||
int idx = groups.indexOf( parent );
|
||||
int target = parent.level + 1;
|
||||
Vector<PwGroupV3> kids = new Vector<PwGroupV3>();
|
||||
while( ++idx < groups.size() ) {
|
||||
PwGroupV3 grp = groups.elementAt( idx );
|
||||
if( grp.level < target )
|
||||
break;
|
||||
else
|
||||
if( grp.level == target )
|
||||
kids.addElement( grp );
|
||||
public Vector<PwGroup> getGrpChildren(PwGroupV3 parent) {
|
||||
int idx = groups.indexOf(parent);
|
||||
int target = parent.level + 1;
|
||||
Vector<PwGroup> kids = new Vector<PwGroup>();
|
||||
while (++idx < groups.size()) {
|
||||
PwGroupV3 grp = (PwGroupV3) groups.elementAt(idx);
|
||||
if (grp.level < target)
|
||||
break;
|
||||
else if (grp.level == target)
|
||||
kids.addElement(grp);
|
||||
}
|
||||
return kids;
|
||||
}
|
||||
return kids;
|
||||
}
|
||||
|
||||
public Vector<PwEntryV3> getEntries( PwGroupV3 parent ) {
|
||||
Vector<PwEntryV3> kids = new Vector<PwEntryV3>();
|
||||
/*for( Iterator i = entries.iterator(); i.hasNext(); ) {
|
||||
PwEntryV3 ent = (PwEntryV3)i.next();
|
||||
if( ent.groupId == parent.groupId )
|
||||
kids.add( ent );
|
||||
}*/
|
||||
for (int i=0; i<entries.size(); i++) {
|
||||
PwEntryV3 ent = entries.elementAt(i);
|
||||
if( ent.groupId == parent.groupId )
|
||||
kids.addElement( ent );
|
||||
public Vector<PwEntry> getEntries(PwGroupV3 parent) {
|
||||
Vector<PwEntry> kids = new Vector<PwEntry>();
|
||||
/*
|
||||
* for( Iterator i = entries.iterator(); i.hasNext(); ) { PwEntryV3 ent
|
||||
* = (PwEntryV3)i.next(); if( ent.groupId == parent.groupId ) kids.add(
|
||||
* ent ); }
|
||||
*/
|
||||
for (int i = 0; i < entries.size(); i++) {
|
||||
PwEntryV3 ent = (PwEntryV3) entries.elementAt(i);
|
||||
if (ent.groupId == parent.groupId)
|
||||
kids.addElement(ent);
|
||||
}
|
||||
return kids;
|
||||
}
|
||||
return kids;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return name;
|
||||
@@ -149,30 +164,33 @@ public class PwDatabaseV3 extends PwDatabase {
|
||||
if (currentGroup == null) {
|
||||
rootGroup = new PwGroupV3();
|
||||
|
||||
Vector<PwGroupV3> rootChildGroups = getGrpRoots();
|
||||
rootGroup.childGroups = rootChildGroups;
|
||||
rootGroup.childEntries = new Vector<PwEntryV3>();
|
||||
Vector<PwGroup> rootChildGroups = getGrpRoots();
|
||||
rootGroup.setGroups(rootChildGroups);
|
||||
rootGroup.childEntries = new Vector<PwEntry>();
|
||||
rootGroup.level = -1;
|
||||
for (int i=0; i<rootChildGroups.size(); i++) {
|
||||
rootChildGroups.elementAt(i).parent = rootGroup;
|
||||
constructTree(rootChildGroups.elementAt(i));
|
||||
PwGroupV3 grp = (PwGroupV3) rootChildGroups.elementAt(i);
|
||||
grp.parent = rootGroup;
|
||||
constructTree(grp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// I'm in non-root
|
||||
// get child groups
|
||||
currentGroup.childGroups = getGrpChildren(currentGroup);
|
||||
currentGroup.setGroups(getGrpChildren(currentGroup));
|
||||
currentGroup.childEntries = getEntries(currentGroup);
|
||||
|
||||
// set parent in child entries
|
||||
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
|
||||
for (int i=0; i<currentGroup.childGroups.size(); i++) {
|
||||
currentGroup.childGroups.elementAt(i).parent = currentGroup;
|
||||
constructTree(currentGroup.childGroups.elementAt(i));
|
||||
PwGroupV3 grp = (PwGroupV3) currentGroup.childGroups.elementAt(i);
|
||||
grp.parent = currentGroup;
|
||||
constructTree((PwGroupV3) currentGroup.childGroups.elementAt(i));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -194,8 +212,8 @@ public class PwDatabaseV3 extends PwDatabase {
|
||||
|
||||
group.level = parent.level + 1;
|
||||
|
||||
group.childEntries = new Vector<PwEntryV3>();
|
||||
group.childGroups = new Vector<PwGroupV3>();
|
||||
group.childEntries = new Vector<PwEntry>();
|
||||
group.setGroups(new Vector<PwGroup>());
|
||||
|
||||
// Add group PwDatabaseV3 and Parent
|
||||
parent.childGroups.add(group);
|
||||
@@ -235,7 +253,8 @@ public class PwDatabaseV3 extends PwDatabase {
|
||||
*/
|
||||
private boolean isGroupIdUsed(int id) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -263,4 +282,19 @@ public class PwDatabaseV3 extends PwDatabase {
|
||||
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.NoSuchAlgorithmException;
|
||||
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;
|
||||
|
||||
|
||||
@@ -32,7 +38,11 @@ public class PwDatabaseV4 extends PwDatabase {
|
||||
public UUID dataCipher;
|
||||
public PwCompressionAlgorithm compressionAlgorithm;
|
||||
public long numKeyEncRounds;
|
||||
|
||||
private Document doc;
|
||||
|
||||
//private Vector<PwGroupV4> groups = new Vector<PwGroupV4>();
|
||||
private PwGroupV4 rootGroup;
|
||||
|
||||
@Override
|
||||
public byte[] getMasterKey(String key, String keyFileName)
|
||||
throws InvalidKeyFileException, IOException {
|
||||
@@ -65,4 +75,51 @@ public class PwDatabaseV4 extends PwDatabase {
|
||||
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;
|
||||
|
||||
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 imageId;
|
||||
|
||||
public String title;
|
||||
public String url;
|
||||
public String username;
|
||||
|
||||
private byte[] password;
|
||||
|
||||
public String additional;
|
||||
|
||||
public PwDate tCreation;
|
||||
public PwDate tLastMod;
|
||||
public PwDate tLastAccess;
|
||||
@@ -132,17 +127,20 @@ public class PwEntryV3 extends PwEntry {
|
||||
public PwGroupV3 parent = null;
|
||||
|
||||
public PwEntryV3() {
|
||||
super();
|
||||
}
|
||||
|
||||
/*
|
||||
public PwEntryV3(PwEntryV3 source) {
|
||||
assign(source);
|
||||
}
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
Random random = new Random();
|
||||
@@ -162,6 +160,7 @@ public class PwEntryV3 extends PwEntry {
|
||||
return title.equals(PMS_TAN_ENTRY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayTitle() {
|
||||
if ( isTan() ) {
|
||||
return PMS_TAN_ENTRY + " " + username;
|
||||
@@ -173,7 +172,12 @@ public class PwEntryV3 extends PwEntry {
|
||||
/**
|
||||
* @return the actual password byte array.
|
||||
*/
|
||||
public byte[] getPassword() {
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return new String(password);
|
||||
}
|
||||
|
||||
public byte[] getPasswordBytes() {
|
||||
return password;
|
||||
}
|
||||
|
||||
@@ -235,19 +239,31 @@ public class PwEntryV3 extends PwEntry {
|
||||
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;
|
||||
imageId = source.imageId;
|
||||
title = source.title;
|
||||
url = source.url;
|
||||
username = source.username;
|
||||
|
||||
int passLen = source.password.length;
|
||||
password = new byte[passLen];
|
||||
System.arraycopy(source.password, 0, password, 0, passLen);
|
||||
|
||||
additional = source.additional;
|
||||
tCreation = (PwDate) source.tCreation.clone();
|
||||
tLastMod = (PwDate) source.tLastMod.clone();
|
||||
tLastAccess = (PwDate) source.tLastAccess.clone();
|
||||
@@ -264,5 +280,69 @@ public class PwEntryV3 extends PwEntry {
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
// for tree traversing
|
||||
public Vector<PwGroupV3> childGroups = null;
|
||||
public Vector<PwEntryV3> childEntries = null;
|
||||
public PwGroupV3 parent = null;
|
||||
|
||||
public int groupId;
|
||||
@@ -75,29 +73,49 @@ public class PwGroupV3 extends PwGroup {
|
||||
/** Used by KeePass internally, don't use */
|
||||
public int flags;
|
||||
|
||||
public void setGroups(Vector<PwGroup> groups) {
|
||||
childGroups = groups;
|
||||
}
|
||||
|
||||
public void sortGroupsByName() {
|
||||
Collections.sort(childGroups, new GroupNameComparator());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PwGroup getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public void sortEntriesByName() {
|
||||
Collections.sort(childEntries, new EntryNameComparator());
|
||||
}
|
||||
|
||||
private class GroupNameComparator implements Comparator<PwGroupV3> {
|
||||
private class GroupNameComparator implements Comparator<PwGroup> {
|
||||
|
||||
@Override
|
||||
public int compare(PwGroupV3 object1, PwGroupV3 object2) {
|
||||
return object1.name.compareToIgnoreCase(object2.name);
|
||||
public int compare(PwGroup object1, PwGroup object2) {
|
||||
return object1.getName().compareToIgnoreCase(object2.getName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class EntryNameComparator implements Comparator<PwEntryV3> {
|
||||
private class EntryNameComparator implements Comparator<PwEntry> {
|
||||
|
||||
@Override
|
||||
public int compare(PwEntryV3 object1, PwEntryV3 object2) {
|
||||
public int compare(PwEntry object1, PwEntry object2) {
|
||||
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 com.keepassdroid.Database;
|
||||
import com.keepassdroid.database.PwEntry;
|
||||
import com.keepassdroid.database.PwEntryV3;
|
||||
import com.keepassdroid.database.PwGroupV3;
|
||||
import com.keepassdroid.database.PwGroup;
|
||||
import com.keepassdroid.search.SearchDbHelper;
|
||||
import com.keepassdroid.utils.Types;
|
||||
|
||||
public class AddEntry extends RunnableOnFinish {
|
||||
private Database mDb;
|
||||
private PwEntryV3 mEntry;
|
||||
public abstract class AddEntry extends RunnableOnFinish {
|
||||
protected Database mDb;
|
||||
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);
|
||||
|
||||
mDb = db;
|
||||
@@ -41,18 +50,11 @@ public class AddEntry extends RunnableOnFinish {
|
||||
mFinish = new AfterAdd(mFinish);
|
||||
}
|
||||
|
||||
public abstract void addEntry();
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
PwGroupV3 parent = mEntry.parent;
|
||||
|
||||
// Add entry to group
|
||||
parent.childEntries.add(mEntry);
|
||||
|
||||
// Add entry to PwDatabaseV3
|
||||
mDb.pm.entries.add(mEntry);
|
||||
|
||||
// Sort entries
|
||||
parent.sortEntriesByName();
|
||||
addEntry();
|
||||
|
||||
// Commit to disk
|
||||
SaveDB save = new SaveDB(mDb, mFinish);
|
||||
@@ -68,13 +70,13 @@ public class AddEntry extends RunnableOnFinish {
|
||||
@Override
|
||||
public void run() {
|
||||
if ( mSuccess ) {
|
||||
PwGroupV3 parent = mEntry.parent;
|
||||
PwGroup parent = mEntry.getParent();
|
||||
|
||||
// Mark parent group dirty
|
||||
mDb.dirty.put(parent, new WeakReference<PwGroupV3>(parent));
|
||||
mDb.dirty.put(parent, new WeakReference<PwGroup>(parent));
|
||||
|
||||
// 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 ) {
|
||||
// Add entry to search index
|
||||
@@ -85,10 +87,10 @@ public class AddEntry extends RunnableOnFinish {
|
||||
}
|
||||
} else {
|
||||
// Remove from group
|
||||
mEntry.parent.childEntries.removeElement(mEntry);
|
||||
mEntry.getParent().childEntries.removeElement(mEntry);
|
||||
|
||||
// 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;
|
||||
|
||||
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 AddGroup extends RunnableOnFinish {
|
||||
private Database mDb;
|
||||
private String mName;
|
||||
private PwGroupV3 mParent;
|
||||
private PwGroupV3 mGroup;
|
||||
private boolean mDontSave;
|
||||
public abstract class AddGroup extends RunnableOnFinish {
|
||||
protected Database mDb;
|
||||
protected 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);
|
||||
|
||||
mDb = db;
|
||||
mName = name;
|
||||
mParent = parent;
|
||||
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();
|
||||
|
||||
// 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();
|
||||
AddGroup email = new AddGroup(db, "eMail", pm.rootGroup, null, true);
|
||||
AddGroup email = AddGroup.getInstance(db, "eMail", pm.rootGroup, null, true);
|
||||
email.run();
|
||||
|
||||
// Commit changes
|
||||
|
||||
@@ -21,10 +21,9 @@ package com.keepassdroid.database.edit;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
|
||||
import com.keepassdroid.Database;
|
||||
import com.keepassdroid.database.PwEntryV3;
|
||||
import com.keepassdroid.database.PwGroupV3;
|
||||
import com.keepassdroid.database.PwEntry;
|
||||
import com.keepassdroid.database.PwGroup;
|
||||
import com.keepassdroid.search.SearchDbHelper;
|
||||
|
||||
/** Task to delete entries
|
||||
@@ -34,10 +33,10 @@ import com.keepassdroid.search.SearchDbHelper;
|
||||
public class DeleteEntry extends RunnableOnFinish {
|
||||
|
||||
private Database mDb;
|
||||
private PwEntryV3 mEntry;
|
||||
private PwEntry mEntry;
|
||||
private boolean mDontSave;
|
||||
|
||||
public DeleteEntry(Database db, PwEntryV3 entry, OnFinish finish) {
|
||||
public DeleteEntry(Database db, PwEntry entry, OnFinish finish) {
|
||||
super(finish);
|
||||
|
||||
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);
|
||||
|
||||
mDb = db;
|
||||
@@ -59,11 +58,11 @@ public class DeleteEntry extends RunnableOnFinish {
|
||||
public void run() {
|
||||
|
||||
// Remove Entry from parent
|
||||
PwGroupV3 parent = mEntry.parent;
|
||||
PwGroup parent = mEntry.getParent();
|
||||
parent.childEntries.remove(mEntry);
|
||||
|
||||
// Remove Entry from PwDatabaseV3
|
||||
mDb.pm.entries.remove(mEntry);
|
||||
// Remove Entry from PwDatabase
|
||||
mDb.pm.getEntries().remove(mEntry);
|
||||
|
||||
// Save
|
||||
mFinish = new AfterDelete(mFinish, parent, mEntry);
|
||||
@@ -74,14 +73,13 @@ public class DeleteEntry extends RunnableOnFinish {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private class AfterDelete extends OnFinish {
|
||||
|
||||
private PwGroupV3 mParent;
|
||||
private PwEntryV3 mEntry;
|
||||
private PwGroup mParent;
|
||||
private PwEntry mEntry;
|
||||
|
||||
public AfterDelete(OnFinish finish, PwGroupV3 parent, PwEntryV3 entry) {
|
||||
public AfterDelete(OnFinish finish, PwGroup parent, PwEntry entry) {
|
||||
super(finish);
|
||||
|
||||
mParent = parent;
|
||||
@@ -105,22 +103,21 @@ public class DeleteEntry extends RunnableOnFinish {
|
||||
|
||||
// Mark parent dirty
|
||||
if ( mParent != null ) {
|
||||
mDb.dirty.put(mParent, new WeakReference<PwGroupV3>(mParent));
|
||||
mDb.dirty.put(mParent, new WeakReference<PwGroup>(mParent));
|
||||
}
|
||||
} else {
|
||||
// Undo remove entry
|
||||
mDb.pm.entries.add(mEntry);
|
||||
mDb.pm.getEntries().add(mEntry);
|
||||
|
||||
PwGroupV3 parent = mEntry.parent;
|
||||
PwGroup parent = mEntry.getParent();
|
||||
if ( parent != null ) {
|
||||
parent.childEntries.add(mEntry);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
super.run();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,36 +22,36 @@ package com.keepassdroid.database.edit;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Vector;
|
||||
|
||||
|
||||
import com.keepassdroid.Database;
|
||||
import com.keepassdroid.GroupBaseActivity;
|
||||
import com.keepassdroid.database.PwEntryV3;
|
||||
import com.keepassdroid.database.PwGroupV3;
|
||||
import com.keepassdroid.app.App;
|
||||
import com.keepassdroid.database.PwEntry;
|
||||
import com.keepassdroid.database.PwGroup;
|
||||
|
||||
public class DeleteGroup extends RunnableOnFinish {
|
||||
|
||||
private Database mDb;
|
||||
private PwGroupV3 mGroup;
|
||||
private PwGroup mGroup;
|
||||
private GroupBaseActivity mAct;
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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;
|
||||
mGroup = group;
|
||||
mAct = act;
|
||||
@@ -67,14 +67,14 @@ public class DeleteGroup extends RunnableOnFinish {
|
||||
public void run() {
|
||||
|
||||
// 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++ ) {
|
||||
DeleteEntry task = new DeleteEntry(mDb, childEnt.get(i), null, true);
|
||||
task.run();
|
||||
}
|
||||
|
||||
// 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++ ) {
|
||||
DeleteGroup task = new DeleteGroup(mDb, childGrp.get(i), mAct, null, true);
|
||||
task.run();
|
||||
@@ -82,13 +82,13 @@ public class DeleteGroup extends RunnableOnFinish {
|
||||
|
||||
|
||||
// Remove from parent
|
||||
PwGroupV3 parent = mGroup.parent;
|
||||
PwGroup parent = mGroup.getParent();
|
||||
if ( parent != null ) {
|
||||
parent.childGroups.remove(mGroup);
|
||||
}
|
||||
|
||||
// Remove from PwDatabaseV3
|
||||
mDb.pm.groups.remove(mGroup);
|
||||
mDb.pm.getGroups().remove(mGroup);
|
||||
|
||||
// Save
|
||||
SaveDB save = new SaveDB(mDb, mFinish, mDontSave);
|
||||
@@ -104,7 +104,7 @@ public class DeleteGroup extends RunnableOnFinish {
|
||||
public void run() {
|
||||
if ( mSuccess ) {
|
||||
// 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
|
||||
try {
|
||||
@@ -114,12 +114,13 @@ public class DeleteGroup extends RunnableOnFinish {
|
||||
}
|
||||
|
||||
// Mark parent dirty
|
||||
PwGroupV3 parent = mGroup.parent;
|
||||
PwGroup parent = mGroup.getParent();
|
||||
if ( parent != null ) {
|
||||
mDb.dirty.put(parent, new WeakReference<PwGroupV3>(parent));
|
||||
mDb.dirty.put(parent, new WeakReference<PwGroup>(parent));
|
||||
}
|
||||
} else {
|
||||
// Let's not bother recovering from a failure to save a deleted group. It is too much work.
|
||||
App.setShutdown();
|
||||
}
|
||||
|
||||
super.run();
|
||||
|
||||
@@ -21,18 +21,19 @@ package com.keepassdroid.database.edit;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
|
||||
import com.keepassdroid.Database;
|
||||
import com.keepassdroid.database.PwEntry;
|
||||
import com.keepassdroid.database.PwEntryV3;
|
||||
import com.keepassdroid.database.PwGroup;
|
||||
import com.keepassdroid.database.PwGroupV3;
|
||||
import com.keepassdroid.search.SearchDbHelper;
|
||||
|
||||
public class UpdateEntry extends RunnableOnFinish {
|
||||
private Database mDb;
|
||||
private PwEntryV3 mOldE;
|
||||
private PwEntryV3 mNewE;
|
||||
private PwEntry mOldE;
|
||||
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);
|
||||
|
||||
mDb = db;
|
||||
@@ -40,7 +41,9 @@ public class UpdateEntry extends RunnableOnFinish {
|
||||
mNewE = newE;
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
@@ -74,7 +77,7 @@ public class UpdateEntry extends RunnableOnFinish {
|
||||
parent.sortEntriesByName();
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
newManager.constructTree(null);
|
||||
|
||||
return newManager;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
*/
|
||||
package com.keepassdroid.database.load;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
@@ -29,20 +29,27 @@ import java.util.Arrays;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.CipherInputStream;
|
||||
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.crypto.CipherFactory;
|
||||
import com.keepassdroid.database.PwCompressionAlgorithm;
|
||||
import com.keepassdroid.database.PwDatabaseV4;
|
||||
import com.keepassdroid.database.PwDbHeaderV4;
|
||||
import com.keepassdroid.database.exception.InconsistentDBException;
|
||||
import com.keepassdroid.database.exception.InvalidDBSignatureException;
|
||||
import com.keepassdroid.database.exception.InvalidDBVersionException;
|
||||
import com.keepassdroid.database.exception.InvalidKeyFileException;
|
||||
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.LEDataInputStream;
|
||||
|
||||
public class ImporterV4 extends Importer {
|
||||
|
||||
@@ -60,12 +67,14 @@ public class ImporterV4 extends Importer {
|
||||
InvalidKeyFileException, InvalidPasswordException,
|
||||
InvalidDBSignatureException, InvalidDBVersionException {
|
||||
|
||||
|
||||
// TODO: Measure whether this buffer is better or worse for performance
|
||||
BufferedInputStream bis = new BufferedInputStream(inStream);
|
||||
|
||||
PwDatabaseV4 db = new PwDatabaseV4();
|
||||
|
||||
PwDbHeaderV4 header = new PwDbHeaderV4(db);
|
||||
|
||||
header.loadFromFile(inStream);
|
||||
header.loadFromFile(bis);
|
||||
|
||||
db.setMasterKey(password, keyfile);
|
||||
db.makeFinalKey(header.masterSeed, header.transformSeed, (int)db.numKeyEncRounds);
|
||||
@@ -84,7 +93,7 @@ public class ImporterV4 extends Importer {
|
||||
throw new IOException("Invalid algorithm.");
|
||||
}
|
||||
|
||||
InputStream decrypted = new CipherInputStream(inStream, cipher);
|
||||
InputStream decrypted = new BetterCipherInputStream(bis, cipher, 50 * 1024);
|
||||
LEDataInputStream dataDecrypted = new LEDataInputStream(decrypted);
|
||||
byte[] storedStartBytes = dataDecrypted.readBytes(32);
|
||||
if ( storedStartBytes == null || storedStartBytes.length != 32 ) {
|
||||
@@ -96,8 +105,8 @@ public class ImporterV4 extends Importer {
|
||||
// an incorrect password/key
|
||||
throw new IOException("Bad database key");
|
||||
}
|
||||
|
||||
HashedBlockInputStream hashed = new HashedBlockInputStream(decrypted);
|
||||
|
||||
HashedBlockInputStream hashed = new HashedBlockInputStream(dataDecrypted);
|
||||
|
||||
InputStream decompressed;
|
||||
if ( db.compressionAlgorithm == PwCompressionAlgorithm.Gzip ) {
|
||||
@@ -106,18 +115,44 @@ public class ImporterV4 extends Importer {
|
||||
decompressed = hashed;
|
||||
}
|
||||
|
||||
// TODO: output into database instead of file
|
||||
FileOutputStream fos = new FileOutputStream("/sdcard/output.xml");
|
||||
// TODO: Measure whether this buffer is better or worse for performance
|
||||
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];
|
||||
int bytesRead;
|
||||
while ( (bytesRead = decompressed.read(buf)) != -1 ) {
|
||||
fos.write(buf, 0, bytesRead);
|
||||
}
|
||||
|
||||
fos.close();
|
||||
*/
|
||||
|
||||
return db;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -26,11 +26,11 @@ import java.io.OutputStream;
|
||||
import com.keepassdroid.database.PwDbHeaderV3;
|
||||
import com.keepassdroid.utils.Types;
|
||||
|
||||
public class PwDbHeaderOutput {
|
||||
public class PwDbHeaderOutputV3 {
|
||||
private PwDbHeaderV3 mHeader;
|
||||
private OutputStream mOS;
|
||||
|
||||
public PwDbHeaderOutput(PwDbHeaderV3 header, OutputStream os) {
|
||||
public PwDbHeaderOutputV3(PwDbHeaderV3 header, OutputStream os) {
|
||||
mHeader = header;
|
||||
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.PwDbHeaderV3;
|
||||
import com.keepassdroid.database.PwEntryV3;
|
||||
import com.keepassdroid.database.PwGroup;
|
||||
import com.keepassdroid.database.PwGroupV3;
|
||||
import com.keepassdroid.database.exception.PwDbOutputException;
|
||||
import com.keepassdroid.stream.NullOutputStream;
|
||||
|
||||
public class PwDbV3Output {
|
||||
public class PwDbV3Output extends PwDbOutput {
|
||||
private PwDatabaseV3 mPM;
|
||||
private OutputStream mOS;
|
||||
private final boolean mDebug;
|
||||
@@ -121,7 +122,7 @@ public class PwDbV3Output {
|
||||
}
|
||||
|
||||
header.version = PwDbHeaderV3.DBVER_DW;
|
||||
header.numGroups = mPM.groups.size();
|
||||
header.numGroups = mPM.getGroups().size();
|
||||
header.numEntries = mPM.entries.size();
|
||||
header.numKeyEncRounds = mPM.getNumKeyEncRecords();
|
||||
|
||||
@@ -165,7 +166,7 @@ public class PwDbV3Output {
|
||||
header.contentsHash = md.digest();
|
||||
|
||||
// Output header
|
||||
PwDbHeaderOutput pho = new PwDbHeaderOutput(header, os);
|
||||
PwDbHeaderOutputV3 pho = new PwDbHeaderOutputV3(header, os);
|
||||
try {
|
||||
pho.output();
|
||||
} catch (IOException e) {
|
||||
@@ -179,9 +180,10 @@ public class PwDbV3Output {
|
||||
//long size = 0;
|
||||
|
||||
// Groups
|
||||
for ( int i = 0; i < mPM.groups.size(); i++ ) {
|
||||
PwGroupV3 pg = mPM.groups.get(i);
|
||||
PwGroupOutput pgo = new PwGroupOutput(pg, os);
|
||||
Vector<PwGroup> groups = mPM.getGroups();
|
||||
for ( int i = 0; i < groups.size(); i++ ) {
|
||||
PwGroupV3 pg = (PwGroupV3) groups.get(i);
|
||||
PwGroupOutputV3 pgo = new PwGroupOutputV3(pg, os);
|
||||
try {
|
||||
pgo.output();
|
||||
} catch (IOException e) {
|
||||
@@ -191,8 +193,8 @@ public class PwDbV3Output {
|
||||
|
||||
// Entries
|
||||
for (int i = 0; i < mPM.entries.size(); i++ ) {
|
||||
PwEntryV3 pe = mPM.entries.get(i);
|
||||
PwEntryOutput peo = new PwEntryOutput(pe, os);
|
||||
PwEntryV3 pe = (PwEntryV3) mPM.entries.get(i);
|
||||
PwEntryOutputV3 peo = new PwEntryOutputV3(pe, os);
|
||||
try {
|
||||
peo.output();
|
||||
} catch (IOException e) {
|
||||
@@ -202,24 +204,24 @@ public class PwDbV3Output {
|
||||
}
|
||||
|
||||
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
|
||||
Vector<PwGroupV3> roots = mPM.getGrpRoots();
|
||||
Vector<PwGroup> roots = mPM.getGrpRoots();
|
||||
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
|
||||
groupList.add(group);
|
||||
|
||||
// Recurse over children
|
||||
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.utils.Types;
|
||||
|
||||
public class PwEntryOutput {
|
||||
public class PwEntryOutputV3 {
|
||||
// Constants
|
||||
public static final byte[] UUID_FIELD_TYPE = Types.writeShort(1);
|
||||
public static final byte[] GROUPID_FIELD_TYPE = Types.writeShort(2);
|
||||
@@ -61,7 +61,7 @@ public class PwEntryOutput {
|
||||
* @param pe
|
||||
* @param os
|
||||
*/
|
||||
public PwEntryOutput(PwEntryV3 pe, OutputStream os) {
|
||||
public PwEntryOutputV3(PwEntryV3 pe, OutputStream os) {
|
||||
mPE = pe;
|
||||
mOS = os;
|
||||
}
|
||||
@@ -103,7 +103,7 @@ public class PwEntryOutput {
|
||||
outputBytes += userLen;
|
||||
|
||||
// Password
|
||||
byte[] password = mPE.getPassword();
|
||||
byte[] password = mPE.getPasswordBytes();
|
||||
mOS.write(PASSWORD_FIELD_TYPE);
|
||||
mOS.write(Types.writeInt(password.length+1));
|
||||
mOS.write(password);
|
||||
@@ -26,7 +26,7 @@ import java.io.OutputStream;
|
||||
import com.keepassdroid.database.PwGroupV3;
|
||||
import com.keepassdroid.utils.Types;
|
||||
|
||||
public class PwGroupOutput {
|
||||
public class PwGroupOutputV3 {
|
||||
// Constants
|
||||
public static final byte[] GROUPID_FIELD_TYPE = Types.writeShort(1);
|
||||
public static final byte[] NAME_FIELD_TYPE = Types.writeShort(2);
|
||||
@@ -53,7 +53,7 @@ public class PwGroupOutput {
|
||||
* @param pg
|
||||
* @param os
|
||||
*/
|
||||
public PwGroupOutput(PwGroupV3 pg, OutputStream os) {
|
||||
public PwGroupOutputV3(PwGroupV3 pg, OutputStream os) {
|
||||
mPG = pg;
|
||||
mOS = os;
|
||||
}
|
||||
@@ -22,7 +22,6 @@ package com.keepassdroid.search;
|
||||
import java.util.UUID;
|
||||
import java.util.Vector;
|
||||
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
@@ -32,7 +31,9 @@ import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.util.Log;
|
||||
|
||||
import com.keepassdroid.Database;
|
||||
import com.keepassdroid.database.PwEntry;
|
||||
import com.keepassdroid.database.PwEntryV3;
|
||||
import com.keepassdroid.database.PwGroup;
|
||||
import com.keepassdroid.database.PwGroupV3;
|
||||
import com.keepassdroid.utils.Types;
|
||||
|
||||
@@ -96,7 +97,7 @@ public class SearchDbHelper {
|
||||
mDb.delete(SEARCH_TABLE, null, null);
|
||||
}
|
||||
|
||||
private ContentValues buildNewEntryContent(PwEntryV3 entry) {
|
||||
private ContentValues buildNewEntryContent(PwEntry entry) {
|
||||
|
||||
ContentValues cv = new ContentValues();
|
||||
UUID uuid = Types.bytestoUUID(entry.uuid);
|
||||
@@ -110,12 +111,12 @@ public class SearchDbHelper {
|
||||
return cv;
|
||||
}
|
||||
|
||||
public void insertEntry(PwEntryV3 entry) {
|
||||
public void insertEntry(PwEntry entry) {
|
||||
ContentValues cv = buildNewEntryContent(entry);
|
||||
mDb.insert(SEARCH_TABLE, null, cv);
|
||||
}
|
||||
|
||||
public void insertEntry(Vector<PwEntryV3> entries) {
|
||||
public void insertEntry(Vector<? extends PwEntry> entries) {
|
||||
mDb.beginTransaction();
|
||||
|
||||
try {
|
||||
@@ -128,14 +129,14 @@ public class SearchDbHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public void updateEntry(PwEntryV3 entry) {
|
||||
public void updateEntry(PwEntry entry) {
|
||||
ContentValues cv = buildNewEntryContent(entry);
|
||||
String uuidStr = cv.getAsString(KEY_UUID);
|
||||
|
||||
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);
|
||||
String uuidStr = uuid.toString();
|
||||
|
||||
@@ -148,15 +149,15 @@ public class SearchDbHelper {
|
||||
|
||||
PwGroupV3 group = new PwGroupV3();
|
||||
group.name = "Search results";
|
||||
group.childEntries = new Vector<PwEntryV3>();
|
||||
group.childGroups = new Vector<PwGroupV3>();
|
||||
group.childEntries = new Vector<PwEntry>();
|
||||
group.setGroups(new Vector<PwGroup>());
|
||||
|
||||
cursor.moveToFirst();
|
||||
while ( ! cursor.isAfterLast() ) {
|
||||
String sUUID = cursor.getString(0);
|
||||
UUID uuid = UUID.fromString(sUUID);
|
||||
Log.d("TAG", uuid.toString());
|
||||
PwEntryV3 entry = db.entries.get(uuid).get();
|
||||
PwEntryV3 entry = (PwEntryV3) db.entries.get(uuid).get();
|
||||
group.childEntries.add(entry);
|
||||
|
||||
cursor.moveToNext();
|
||||
|
||||
@@ -84,7 +84,7 @@ public class AppSettingsActivity extends LockingClosePreferenceActivity {
|
||||
}
|
||||
|
||||
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.ProgressTask;
|
||||
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.SaveDB;
|
||||
|
||||
public class RoundsPreference extends DialogPreference {
|
||||
|
||||
private PwDatabaseV3 mPM;
|
||||
private PwDatabase mPM;
|
||||
private TextView mRoundsView;
|
||||
|
||||
@Override
|
||||
@@ -49,8 +49,8 @@ public class RoundsPreference extends DialogPreference {
|
||||
|
||||
Database db = App.getDB();
|
||||
mPM = db.pm;
|
||||
int numRounds = mPM.numKeyEncRounds;
|
||||
mRoundsView.setText(Integer.toString(numRounds));
|
||||
long numRounds = mPM.getNumRounds();
|
||||
mRoundsView.setText(Long.toString(numRounds));
|
||||
|
||||
return view;
|
||||
}
|
||||
@@ -82,8 +82,13 @@ public class RoundsPreference extends DialogPreference {
|
||||
rounds = 1;
|
||||
}
|
||||
|
||||
int oldRounds = mPM.numKeyEncRounds;
|
||||
mPM.numKeyEncRounds = rounds;
|
||||
long oldRounds = mPM.getNumRounds();
|
||||
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();
|
||||
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 int mOldRounds;
|
||||
private long mOldRounds;
|
||||
private Context mCtx;
|
||||
|
||||
public AfterSave(Context ctx, Handler handler, int oldRounds) {
|
||||
public AfterSave(Context ctx, Handler handler, long oldRounds) {
|
||||
super(handler);
|
||||
|
||||
mCtx = ctx;
|
||||
@@ -114,7 +119,7 @@ public class RoundsPreference extends DialogPreference {
|
||||
}
|
||||
} else {
|
||||
displayMessage(mCtx);
|
||||
mPM.numKeyEncRounds = mOldRounds;
|
||||
mPM.setNumRonuds(mOldRounds);
|
||||
}
|
||||
|
||||
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 {
|
||||
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";
|
||||
byte[] password = sPass.getBytes("UTF-8");
|
||||
|
||||
assertArrayEquals(password, mPE.getPassword());
|
||||
assertArrayEquals(password, mPE.getPasswordBytes());
|
||||
}
|
||||
|
||||
public void testCreation() {
|
||||
|
||||
@@ -33,7 +33,7 @@ public class PwGroupTest extends AndroidTestCase {
|
||||
protected void setUp() throws Exception {
|
||||
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 android.content.Context;
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
import com.keepassdroid.Database;
|
||||
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.edit.DeleteGroup;
|
||||
import com.keepassdroid.search.SearchDbHelper;
|
||||
@@ -54,8 +54,8 @@ public class DeleteEntry extends AndroidTestCase {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
PwGroupV3 group1 = getGroup(db.pm, GROUP1_NAME);
|
||||
PwDatabaseV3 pm = (PwDatabaseV3) db.pm;
|
||||
PwGroup group1 = getGroup(pm, GROUP1_NAME);
|
||||
assertNotNull("Could not find group1", group1);
|
||||
|
||||
// Delete the group
|
||||
@@ -63,10 +63,10 @@ public class DeleteEntry extends AndroidTestCase {
|
||||
task.run();
|
||||
|
||||
// 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);
|
||||
|
||||
PwEntryV3 entry2 = getEntry(db.pm, ENTRY2_NAME);
|
||||
PwEntry entry2 = getEntry(pm, ENTRY2_NAME);
|
||||
assertNull("Entry 2 was not removed", entry2);
|
||||
|
||||
// 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());
|
||||
|
||||
// Verify the group was deleted
|
||||
group1 = getGroup(db.pm, GROUP1_NAME);
|
||||
group1 = getGroup(pm, GROUP1_NAME);
|
||||
assertNull("Group 1 was not removed.", group1);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
private PwEntryV3 getEntry(PwDatabaseV3 pm, String name) {
|
||||
Vector<PwEntryV3> entries = pm.entries;
|
||||
private PwEntry getEntry(PwDatabaseV3 pm, String name) {
|
||||
Vector<PwEntry> entries = pm.entries;
|
||||
for ( int i = 0; i < entries.size(); i++ ) {
|
||||
PwEntryV3 entry = entries.get(i);
|
||||
PwEntry entry = entries.get(i);
|
||||
if ( entry.title.equals(name) ) {
|
||||
return entry;
|
||||
}
|
||||
@@ -100,11 +100,11 @@ public class DeleteEntry extends AndroidTestCase {
|
||||
|
||||
}
|
||||
|
||||
private PwGroupV3 getGroup(PwDatabaseV3 pm, String name) {
|
||||
Vector<PwGroupV3> groups = pm.groups;
|
||||
private PwGroup getGroup(PwDatabaseV3 pm, String name) {
|
||||
Vector<PwGroup> groups = pm.getGroups();
|
||||
for ( int i = 0; i < groups.size(); i++ ) {
|
||||
PwGroupV3 group = groups.get(i);
|
||||
if ( group.name.equals(name) ) {
|
||||
PwGroup group = groups.get(i);
|
||||
if ( group.getName().equals(name) ) {
|
||||
return group;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,9 @@ public class Kdb4 extends AndroidTestCase {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
is.close();
|
||||
|
||||
assertTrue(false);
|
||||
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ public class Kdb4Header extends AndroidTestCase {
|
||||
|
||||
assertTrue(db.dataCipher.equals(CipherFactory.AES_CIPHER));
|
||||
|
||||
am.close();
|
||||
is.close();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,6 @@ public class TestData {
|
||||
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.PwDbHeaderV3;
|
||||
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.stream.NullOutputStream;
|
||||
import com.keepassdroid.tests.database.TestData;
|
||||
@@ -99,7 +99,7 @@ public class PwManagerOutputTest extends AndroidTestCase {
|
||||
PwDbHeaderV3 header = pActual.outputHeader(bActual);
|
||||
|
||||
ByteArrayOutputStream bExpected = new ByteArrayOutputStream();
|
||||
PwDbHeaderOutput outExpected = new PwDbHeaderOutput(mPM.dbHeader, bExpected);
|
||||
PwDbHeaderOutputV3 outExpected = new PwDbHeaderOutputV3(mPM.dbHeader, bExpected);
|
||||
outExpected.output();
|
||||
|
||||
assertHeadersEquals(mPM.dbHeader, header);
|
||||
|
||||
Reference in New Issue
Block a user