Initial support for serializing groups and entries. Not quite right yet.

This commit is contained in:
Brian Pellin
2009-04-23 23:47:38 -05:00
parent 7810b1e3b9
commit 32024f393c
21 changed files with 789 additions and 62 deletions

View File

@@ -297,7 +297,17 @@
</exec>
</target>
<target name="tests" depends="reinstall">
<!-- Copy testing files to device -->
<target name="stage">
<echo>Copying test files..</echo>
<exec executable="${adb}">
<arg value="push" />
<arg value="tests/assets/test1.kdb" />
<arg value="/sdcard/test1.kdb" />
</exec>
</target>
<target name="tests" depends="reinstall, stage">
<echo>Building and installing tests..</echo>
<exec executable="ant" failonerror="true">
<arg value="-f" />

View File

@@ -20,7 +20,7 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<!-- Title -->
<TextView android:id="@+id/entry_title_label"
android:layout_width="100px"
android:layout_height="wrap_content"
@@ -30,6 +30,7 @@
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_toRightOf="@id/entry_title_label"/>
<!-- Username -->
<TextView android:id="@+id/entry_user_name_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -42,6 +43,7 @@
android:layout_alignLeft="@id/entry_title"
android:layout_alignParentRight="true"
android:layout_alignTop="@id/entry_user_name_label"/>
<!-- URL -->
<TextView android:id="@+id/entry_url_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -54,6 +56,7 @@
android:layout_alignLeft="@id/entry_title"
android:layout_alignParentRight="true"
android:layout_alignTop="@id/entry_url_label"/>
<!-- Password -->
<TextView android:id="@+id/entry_password_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -66,11 +69,25 @@
android:layout_alignLeft="@id/entry_title"
android:layout_alignParentRight="true"
android:layout_alignTop="@id/entry_password_label"/>
<!-- Created -->
<TextView android:id="@+id/entry_created_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@id/entry_password_label"
android:text="@string/entry_created" />
<TextView android:id="@+id/entry_created"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@id/entry_title"
android:layout_alignParentRight="true"
android:layout_alignTop="@id/entry_created_label"/>
<!-- Comment -->
<TextView android:id="@+id/entry_comment_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@id/entry_password"
android:layout_below="@id/entry_created"
android:text="@string/entry_comment" />
<TextView android:id="@+id/entry_comment"
android:layout_width="wrap_content"

View File

@@ -38,4 +38,5 @@
<string name="about_homepage">Homepage:</string>
<string name="about_twitter">Twitter:</string>
<string name="about_ok">OK</string>
<string name="entry_created">Created: </string>
</resources>

View File

@@ -19,6 +19,7 @@
*/
package com.android.keepass;
import java.text.DateFormat;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;
@@ -80,6 +81,10 @@ public class EntryActivity extends LockingActivity {
populateText(R.id.entry_user_name, mEntry.username);
populateText(R.id.entry_url, mEntry.url);
populateText(R.id.entry_password, getString(R.string.MaskedPassword));
DateFormat df = DateFormat.getInstance();
String date = df.format(mEntry.tCreation);
populateText(R.id.entry_created, date);
populateText(R.id.entry_comment, mEntry.additional);
TextView comment = (TextView)findViewById(R.id.entry_comment);
comment.setScrollBarStyle(View.SCROLLBARS_INSIDE_INSET);

View File

@@ -24,6 +24,7 @@ import java.lang.ref.WeakReference;
import org.phoneid.keepassj2me.PwEntry;
import org.phoneid.keepassj2me.PwGroup;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;

View File

@@ -24,6 +24,7 @@ import java.util.Vector;
import org.phoneid.keepassj2me.PwEntry;
import org.phoneid.keepassj2me.PwGroup;
import android.app.Activity;
import android.view.View;
import android.view.ViewGroup;

View File

@@ -0,0 +1,11 @@
package com.android.keepass.keepasslib;
import java.io.OutputStream;
import org.phoneid.keepassj2me.PwManager;
public class Exporter {
public void saveDatabase(PwManager manager, OutputStream outStream) {
}
}

View File

@@ -0,0 +1,150 @@
/*
* Copyright 2009 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.android.keepass.keepasslib;
import java.io.IOException;
import java.io.OutputStream;
import org.phoneid.keepassj2me.PwEntry;
import org.phoneid.keepassj2me.Types;
public class PwEntryOutput {
private OutputStream mOS;
private PwEntry mPE;
/** Output the PwGroup to the stream
* @param pe
* @param os
*/
public PwEntryOutput(PwEntry pe, OutputStream os) {
mPE = pe;
mOS = os;
}
//NOTE: Need be to careful about using ints. The actual type written to file is a unsigned int
public void output() throws IOException {
// UUID
mOS.write(UUID_FIELD_TYPE);
mOS.write(UUID_FIELD_SIZE);
mOS.write(mPE.uuid);
// Group ID
mOS.write(GROUPID_FIELD_TYPE);
mOS.write(LONG_FOUR);
mOS.write(Types.writeInt(mPE.groupId));
// Image ID
mOS.write(IMAGEID_FIELD_TYPE);
mOS.write(LONG_FOUR);
mOS.write(Types.writeInt(mPE.imageId));
// Title
byte[] title = mPE.title.getBytes("UTF-8");
mOS.write(TITLE_FIELD_TYPE);
mOS.write(Types.writeInt(title.length));
mOS.write(title);
// URL
byte[] url = mPE.url.getBytes("UTF-8");
mOS.write(URL_FIELD_TYPE);
mOS.write(Types.writeInt(url.length));
mOS.write(url);
// Username
byte[] username = mPE.username.getBytes("UTF-8");
mOS.write(USERNAME_FIELD_TYPE);
mOS.write(Types.writeInt(username.length));
mOS.write(username);
// Password
byte[] password = mPE.getPassword();
mOS.write(PASSWORD_FIELD_TYPE);
mOS.write(Types.writeInt(password.length));
mOS.write(password);
// Additional
byte[] additional = mPE.additional.getBytes("UTF-8");
mOS.write(ADDITIONAL_FIELD_TYPE);
mOS.write(Types.writeInt(additional.length));
mOS.write(additional);
// Create date
mOS.write(CREATE_FIELD_TYPE);
mOS.write(DATE_FIELD_SIZE);
mOS.write(Types.writeTime(mPE.tCreation));
// Modification date
mOS.write(MOD_FIELD_TYPE);
mOS.write(DATE_FIELD_SIZE);
mOS.write(Types.writeTime(mPE.tLastMod));
// Access date
mOS.write(ACCESS_FIELD_TYPE);
mOS.write(DATE_FIELD_SIZE);
mOS.write(Types.writeTime(mPE.tLastAccess));
// Expiration date
mOS.write(EXPIRE_FIELD_TYPE);
mOS.write(DATE_FIELD_SIZE);
mOS.write(Types.writeTime(mPE.tExpire));
// Binary desc
byte[] binaryDesc = mPE.binaryDesc.getBytes("UTF-8");
mOS.write(BINARY_DESC_FIELD_TYPE);
mOS.write(Types.writeInt(binaryDesc.length));
mOS.write(binaryDesc);
// Binary data
byte[] data = mPE.getBinaryData();
mOS.write(BINARY_DATA_FIELD_TYPE);
mOS.write(Types.writeInt(data.length));
mOS.write(data);
// End
mOS.write(END_FIELD_TYPE);
mOS.write(ZERO_FIELD_SIZE);
}
public static final byte[] UUID_FIELD_TYPE = { 0x00, 0x01};
public static final byte[] GROUPID_FIELD_TYPE = { 0x00, 0x02};
public static final byte[] IMAGEID_FIELD_TYPE = { 0x00, 0x03};
public static final byte[] TITLE_FIELD_TYPE = { 0x00, 0x04};
public static final byte[] URL_FIELD_TYPE = { 0x00, 0x05};
public static final byte[] USERNAME_FIELD_TYPE = { 0x00, 0x06};
public static final byte[] PASSWORD_FIELD_TYPE = { 0x00, 0x07};
public static final byte[] ADDITIONAL_FIELD_TYPE = { 0x00, 0x08};
public static final byte[] CREATE_FIELD_TYPE = { 0x00, 0x09};
public static final byte[] MOD_FIELD_TYPE = { 0x00, 0x0A};
public static final byte[] ACCESS_FIELD_TYPE = { 0x00, 0x0B};
public static final byte[] EXPIRE_FIELD_TYPE = { 0x00, 0x0C};
public static final byte[] BINARY_DESC_FIELD_TYPE = { 0x00, 0x0D};
public static final byte[] BINARY_DATA_FIELD_TYPE = { 0x00, 0x0E};
public static final byte[] END_FIELD_TYPE = Types.writeUByte(0xFFFF);
public static final byte[] LONG_FOUR = { 0x00, 0x00, 0x00, 0x04};
public static final byte[] UUID_FIELD_SIZE = { 0x00, 0x00, 0x00, 0x10};
public static final byte[] DATE_FIELD_SIZE = { 0x00, 0x00, 0x00, 0x05};
public static final byte[] IMAGEID_FIELD_SIZE = LONG_FOUR;
public static final byte[] LEVEL_FIELD_SIZE = LONG_FOUR;
public static final byte[] FLAGS_FIELD_SIZE = LONG_FOUR;
public static final byte[] ZERO_FIELD_SIZE = { 0x00, 0x00, 0x00, 0x00};
}

View File

@@ -0,0 +1,112 @@
/*
* Copyright 2009 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.android.keepass.keepasslib;
import java.io.IOException;
import java.io.OutputStream;
import org.phoneid.keepassj2me.PwGroup;
import org.phoneid.keepassj2me.Types;
public class PwGroupOutput {
private OutputStream mOS;
private PwGroup mPG;
/** Output the PwGroup to the stream
* @param pg
* @param os
*/
public PwGroupOutput(PwGroup pg, OutputStream os) {
mPG = pg;
mOS = os;
}
//NOTE: Need be to careful about using ints. The actual type written to file is a unsigned int
public void output() throws IOException {
// Group ID
mOS.write(GROUPID_FIELD_TYPE);
mOS.write(GROUPID_FIELD_SIZE);
mOS.write(Types.writeInt(mPG.groupId));
// Name
mOS.write(NAME_FIELD_TYPE);
mOS.write(Types.writeInt(mPG.name.length()));
mOS.write(mPG.name.getBytes("UTF-8"));
// Create date
mOS.write(CREATE_FIELD_TYPE);
mOS.write(DATE_FIELD_SIZE);
mOS.write(Types.writeTime(mPG.tCreation));
// Modification date
mOS.write(MOD_FIELD_TYPE);
mOS.write(DATE_FIELD_SIZE);
mOS.write(Types.writeTime(mPG.tLastMod));
// Access date
mOS.write(ACCESS_FIELD_TYPE);
mOS.write(DATE_FIELD_SIZE);
mOS.write(Types.writeTime(mPG.tLastAccess));
// Expiration date
mOS.write(EXPIRE_FIELD_TYPE);
mOS.write(DATE_FIELD_SIZE);
mOS.write(Types.writeTime(mPG.tExpire));
// Image ID
mOS.write(IMAGEID_FIELD_TYPE);
mOS.write(IMAGEID_FIELD_SIZE);
mOS.write(Types.writeInt(mPG.imageId));
// Level
mOS.write(LEVEL_FIELD_TYPE);
mOS.write(LEVEL_FIELD_SIZE);
mOS.write(Types.writeShort(mPG.level));
// Flags
mOS.write(FLAGS_FIELD_TYPE);
mOS.write(FLAGS_FIELD_SIZE);
mOS.write(Types.writeInt(mPG.flags));
// End
mOS.write(END_FIELD_TYPE);
mOS.write(ZERO_FIELD_SIZE);
}
public static final byte[] GROUPID_FIELD_TYPE = { 0x00, 0x01};
public static final byte[] NAME_FIELD_TYPE = { 0x00, 0x02};
public static final byte[] CREATE_FIELD_TYPE = { 0x00, 0x03};
public static final byte[] MOD_FIELD_TYPE = { 0x00, 0x04};
public static final byte[] ACCESS_FIELD_TYPE = { 0x00, 0x05};
public static final byte[] EXPIRE_FIELD_TYPE = { 0x00, 0x06};
public static final byte[] IMAGEID_FIELD_TYPE = { 0x00, 0x07};
public static final byte[] LEVEL_FIELD_TYPE = { 0x00, 0x08};
public static final byte[] FLAGS_FIELD_TYPE = { 0x00, 0x09};
public static final byte[] END_FIELD_TYPE = Types.writeUByte(0xFFFF);
public static final byte[] LONG_FOUR = { 0x00, 0x00, 0x00, 0x04};
public static final byte[] GROUPID_FIELD_SIZE = LONG_FOUR;
public static final byte[] DATE_FIELD_SIZE = { 0x00, 0x00, 0x00, 0x05};
public static final byte[] IMAGEID_FIELD_SIZE = LONG_FOUR;
public static final byte[] LEVEL_FIELD_SIZE = { 0x00, 0x00, 0x00, 0x02};
public static final byte[] FLAGS_FIELD_SIZE = LONG_FOUR;
public static final byte[] ZERO_FIELD_SIZE = { 0x00, 0x00, 0x00, 0x00};
}

View File

@@ -127,6 +127,7 @@ public class ImporterV3 {
if( newManager.algorithm == PwManager.ALGO_TWOFISH )
throw new IOException( "TwoFish algorithm is not supported" );
newManager.dbHeader = hdr;
newManager.numKeyEncRounds = hdr.numKeyEncRounds;
@@ -174,7 +175,12 @@ public class ImporterV3 {
// NI
byte[] plainContent = new byte[encryptedPartSize];
System.arraycopy(filebuf, PwDbHeader.BUF_SIZE, plainContent, 0, encryptedPartSize);
// TODO: Delete Me
newManager.postHeader = new byte[encryptedPartSize];
System.arraycopy(filebuf, PwDbHeader.BUF_SIZE, newManager.postHeader, 0, encryptedPartSize);
//if( pRepair == null ) {
md = new SHA256Digest();
md.update( filebuf, PwDbHeader.BUF_SIZE, encryptedPartSize );
@@ -200,8 +206,8 @@ public class ImporterV3 {
//KeePassMIDlet.logS ( newGrp.level + " " + newGrp.name );
// End-Group record. Save group and count it.
//newManager.groups.add( newGrp );
newManager.addGroup( newGrp );
//newManager.groups.add( newGrp );
newManager.addGroup( newGrp );
newGrp = new PwGroup();
i++;
}

View File

@@ -27,6 +27,7 @@ package org.phoneid.keepassj2me;
// PhoneID
import org.phoneid.*;
// Java
import java.util.*;

View File

@@ -1,5 +1,7 @@
/*
KeePass for J2ME
* Copyright 2009 Brian Pellin.
This file was derived from
Copyright 2007 Naomaru Itoi <nao@phoneid.org>
@@ -8,57 +10,63 @@ This file was derived from
Java clone of KeePass - A KeePass file viewer for Java
Copyright 2006 Bill Zwicky <billzwicky@users.sourceforge.net>
This program 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; version 2
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* 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 org.phoneid.keepassj2me;
import java.util.*;
import java.util.Date;
import java.util.Vector;
/**
* @author Brian Pellin <bpellin@gmail.com>
* @author Naomaru Itoi <nao@phoneid.org>
* @author Bill Zwicky <wrzwicky@pobox.com>
* @author Dominik Reichl <dominik.reichl@t-online.de>
*/
public class PwGroup {
public PwGroup() {
}
public String toString() {
return name;
}
}
public String toString() {
return name;
}
/** Size of byte buffer needed to hold this struct. */
public static final int BUF_SIZE = 124;
/** Size of byte buffer needed to hold this struct. */
public static final int BUF_SIZE = 124;
// for tree traversing
public Vector<PwGroup> childGroups = null;
public Vector<PwEntry> childEntries = null;
public PwGroup parent = null;
// for tree traversing
public Vector<PwGroup> childGroups = null;
public Vector<PwEntry> childEntries = null;
public PwGroup parent = null;
public int groupId;
public int imageId;
public String name;
public int groupId;
public int imageId;
public String name;
public Date tCreation;
public Date tLastMod;
public Date tLastAccess;
public Date tExpire;
public Date tCreation;
public Date tLastMod;
public Date tLastAccess;
public Date tExpire;
public int level; // short
public int level; //short
/** Used by KeePass internally, don't use */
public int flags;
/** Used by KeePass internally, don't use */
public int flags;
}

View File

@@ -42,7 +42,9 @@ import com.android.keepass.keepasslib.InvalidKeyFileException;
* @author Dominik Reichl <dominik.reichl@t-online.de>
*/
public class PwManager {
// TODO: delete ME
public byte[] postHeader;
// Constants
// private static final int PWM_SESSION_KEY_SIZE = 12;
// DB sig from KeePass 1.03
@@ -81,6 +83,8 @@ public class PwManager {
// Algorithm used to encrypt the database
int algorithm;
int numKeyEncRounds;
public PwDbHeader dbHeader;
// root group
PwGroup rootGroup;

View File

@@ -24,6 +24,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
package org.phoneid.keepassj2me;
import java.util.Calendar;
import java.util.Date;
/**
@@ -32,6 +33,38 @@ import java.util.Date;
* @author Bill Zwicky <wrzwicky@pobox.com>
*/
public class Types {
public static long readUInt(byte buf[], int offset) {
int firstByte = 0;
int secondByte = 0;
int thirdByte = 0;
int fourthByte = 0;
firstByte = (0x000000FF & ((int)buf[offset]));
secondByte = (0x000000FF & ((int)buf[offset+1]));
thirdByte = (0x000000FF & ((int)buf[offset+2]));
fourthByte = (0x000000FF & ((int)buf[offset+3]));
return ((long) (firstByte << 24
| secondByte << 16
| thirdByte << 8
| fourthByte))
& 0xFFFFFFFFL;
}
public static byte[] writeUInt(long val) {
byte[] buf = new byte[4];
buf[0] = (byte) ((val & 0xFF000000L) >> 24);
buf[1] = (byte) ((val & 0x00FF0000L) >> 16);
buf[2] = (byte) ((val & 0x0000FF00L) >> 8);
buf[3] = (byte) (val & 0x000000FFL);
return buf;
}
/**
* Read a 32-bit value.
*
@@ -59,8 +92,13 @@ public class Types {
buf[offset + 2] = (byte)((val >>> 16) & 0xFF);
buf[offset + 3] = (byte)((val >>> 24) & 0xFF);
}
public static byte[] writeInt(int val) {
byte[] buf = new byte[4];
writeInt(val, buf, 0);
return buf;
}
/**
* Read an unsigned 16-bit value.
@@ -72,15 +110,48 @@ public class Types {
public static int readShort( byte[] buf, int offset ) {
return (buf[offset + 0] & 0xFF) + ((buf[offset + 1] & 0xFF) << 8);
}
/** Write an unsigned 16-bit value
*
* @param val
* @param buf
* @param offset
*/
public static void writeShort(int val, byte[] buf, int offset) {
buf[offset + 0] = (byte)(val & 0xFF);
buf[offset + 1] = (byte)((val >>> 8) & 0xFF);
}
public static byte[] writeShort(int val) {
byte[] buf = new byte[2];
writeShort(val, buf, 0);
return buf;
}
/** Read an unsigned byte */
public static int readUByte( byte[] buf, int offset ) {
return ((int)buf[offset] & 0xFF);
}
/** Write an unsigned byte
*
* @param val
* @param buf
* @param offset
*/
public static void writeUByte(int val, byte[] buf, int offset) {
buf[offset] = (byte)(val & 0xFF);
}
public static byte[] writeUByte(int val) {
byte[] buf = new byte[2];
writeUByte(val, buf, 0);
return buf;
}
/**
* Return len of null-terminated string (i.e. distance to null)
@@ -134,11 +205,33 @@ public class Types {
int minute = ((dw4 & 0x0000000F) << 2) | (dw5 >> 6);
int second = dw5 & 0x0000003F;
//Calendar time = Calendar.getInstance();
//time.set( year, month, day, hour, minute, second );
Calendar time = Calendar.getInstance();
time.set( year, month, day, hour, minute, second );
//return time.getTime();
return time.getTime();
return null;
//return null;
}
public static byte[] writeTime(Date date) {
byte[] buf = new byte[5];
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH);
int day = cal.get(Calendar.DAY_OF_MONTH);
int hour = cal.get(Calendar.HOUR_OF_DAY);
int minute = cal.get(Calendar.MINUTE);
int second = cal.get(Calendar.SECOND);
buf[0] = (byte)((year >> 6) & 0x0000003F);
buf[1] = (byte)(((year & 0x0000003F) << 2) | ((month >> 2) & 3) );
buf[2] = (byte)(((month & 0x00000003) << 6) | ((day & 0x0000001F) << 1) | ((hour >> 4) & 0x00000001));
buf[3] = (byte)(((hour & 0x0000000F) << 4) | ((minute >> 2) & 0x0000000F));
buf[4] = (byte)(((minute & 0x00000003) << 6) | (second & 0x0000003F));
return buf;
}
}

BIN
tests/assets/test1.kdb Normal file

Binary file not shown.

View File

@@ -287,7 +287,7 @@
</exec>
</target>
<!-- Uinstall the package from the default emulator -->
<!-- Uninstall the package from the default emulator -->
<target name="uninstall">
<echo>Uninstalling ${application-package} from the default emulator...</echo>
<exec executable="${adb}" failonerror="true">

View File

@@ -0,0 +1,61 @@
/*
* Copyright 2009 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 3 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.android.keepass.tests;
import java.io.UnsupportedEncodingException;
import java.util.Calendar;
import junit.framework.TestCase;
import static org.junit.Assert.*;
import org.phoneid.keepassj2me.PwEntry;
public class PwEntryTest extends TestCase {
PwEntry mPE;
@Override
protected void setUp() throws Exception {
super.setUp();
mPE = TestData.GetTest1().entries.get(0);
}
public void testName() {
assertTrue("Name was " + mPE.title, mPE.title.equals("Amazon"));
}
public void testPassword() throws UnsupportedEncodingException {
String sPass = "12345";
byte[] password = sPass.getBytes("UTF-8");
assertArrayEquals(password, mPE.getPassword());
}
public void testCreation() {
Calendar cal = Calendar.getInstance();
cal.setTime(mPE.tCreation);
assertTrue("Incorrect year.", cal.get(Calendar.YEAR) == 2009);
assertTrue("Incorrect month.", cal.get(Calendar.MONTH) == 4);
assertTrue("Incorrect day.", cal.get(Calendar.DAY_OF_MONTH) == 23);
}
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright 2009 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 3 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.android.keepass.tests;
import static org.junit.Assert.assertArrayEquals;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.DigestOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import junit.framework.TestCase;
import org.phoneid.keepassj2me.PwEntry;
import org.phoneid.keepassj2me.PwGroup;
import org.phoneid.keepassj2me.PwManager;
import com.android.keepass.keepasslib.PwEntryOutput;
import com.android.keepass.keepasslib.PwGroupOutput;
public class PwGroupOutputTest extends TestCase {
PwManager mPM;
@Override
protected void setUp() throws Exception {
super.setUp();
mPM = TestData.GetTest1();
}
public void testPlainContent() throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
// Groups
for (int i = 0; i < mPM.groups.size(); i++ ) {
PwGroup pg = mPM.groups.get(i);
PwGroupOutput pgo = new PwGroupOutput(pg, bos);
pgo.output();
}
// Entries
for (int i = 0; i < mPM.entries.size(); i++ ) {
PwEntry pe = mPM.entries.get(i);
PwEntryOutput peo = new PwEntryOutput(pe, bos);
peo.output();
}
byte[] buf = bos.toByteArray();
for (int i = 0; i < buf.length; i++) {
assertEquals("Difference at byte " + i, mPM.postHeader[i], buf[i]);
}
//assertArrayEquals(mPM.postHeader, bos.toByteArray());
}
public void testChecksum() throws NoSuchAlgorithmException, IOException {
FileOutputStream fos = new FileOutputStream("/dev/null");
MessageDigest md = MessageDigest.getInstance("SHA-256");
DigestOutputStream dos = new DigestOutputStream(fos, md);
// Groups
for (int i = 0; i < mPM.groups.size(); i++ ) {
PwGroup pg = mPM.groups.get(i);
PwGroupOutput pgo = new PwGroupOutput(pg, dos);
pgo.output();
}
// Entries
for (int i = 0; i < mPM.entries.size(); i++ ) {
PwEntry pe = mPM.entries.get(i);
PwEntryOutput peo = new PwEntryOutput(pe, dos);
peo.output();
}
assertArrayEquals("Hash of groups and entries failed.", md.digest(), mPM.dbHeader.contentsHash);
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2009 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 3 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.android.keepass.tests;
import junit.framework.TestCase;
import org.phoneid.keepassj2me.PwGroup;
public class PwGroupTest extends TestCase {
PwGroup mPG;
@Override
protected void setUp() throws Exception {
super.setUp();
mPG = TestData.GetTest1().groups.get(0);
}
public void testGroupName() {
assertTrue("Name was " + mPG.name, mPG.name.equals("Internet"));
}
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright 2009 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 3 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.android.keepass.tests;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.bouncycastle1.crypto.InvalidCipherTextException;
import org.phoneid.keepassj2me.ImporterV3;
import org.phoneid.keepassj2me.PwManager;
import com.android.keepass.keepasslib.InvalidKeyFileException;
public class TestData {
private static PwManager test1;
public static PwManager GetTest1() throws InvalidCipherTextException, IOException, InvalidKeyFileException {
if ( test1 == null ) {
FileInputStream fis = new FileInputStream("/sdcard/test1.kdb");
ImporterV3 importer = new ImporterV3();
test1 = importer.openDatabase(fis, "12345", "");
if (test1 != null) {
test1.constructTree(null);
}
}
return test1;
}
}

View File

@@ -25,29 +25,86 @@ import static org.junit.Assert.*;
public class TypesTest extends TestCase {
public void testReadWriteInt() {
byte[] orig = new byte[8];
byte[] dest = new byte[8];
public void testReadWriteIntZero() {
testReadWriteInt((byte) 0);
}
public void testReadWriteIntMin() {
testReadWriteInt(Byte.MIN_VALUE);
}
public void testReadWriteIntMax() {
testReadWriteInt(Byte.MAX_VALUE);
}
private void testReadWriteInt(byte value) {
byte[] orig = new byte[4];
byte[] dest = new byte[4];
for (int i = 0; i < 4; i++ ) {
orig[i] = 0;
}
for (int i = 4; i < 8; i++ ) {
orig[4] = Byte.MAX_VALUE;
}
setArray(orig, value, 0, 4);
int one = Types.readInt(orig, 0);
int two = Types.readInt(orig, 4);
Types.writeInt(one, dest, 0);
Types.writeInt(two, dest, 4);
assertArrayEquals(orig, dest);
}
private void setArray(byte[] buf, byte value, int offset, int size) {
for (int i = offset; i < offset + size; i++) {
buf[i] = value;
}
}
public void testReadWriteShortZero() {
testReadWriteShort((byte) 0);
}
public void testReadWriteShortMin() {
testReadWriteShort(Byte.MIN_VALUE);
}
public void testReadWriteShortMax() {
testReadWriteShort(Byte.MAX_VALUE);
}
private void testReadWriteShort(byte value) {
byte[] orig = new byte[2];
byte[] dest = new byte[2];
setArray(orig, value, 0, 2);
int one = Types.readShort(orig, 0);
Types.writeShort(one, dest, 0);
}
public void testReadWriteByteZero() {
testReadWriteByte((byte) 0);
}
public void testReadWriteByteMin() {
testReadWriteByte(Byte.MIN_VALUE);
}
public void testReadWriteByteMax() {
testReadWriteShort(Byte.MAX_VALUE);
}
private void testReadWriteByte(byte value) {
byte[] orig = new byte[1];
byte[] dest = new byte[1];
setArray(orig, value, 0, 1);
int one = Types.readUByte(orig, 0);
Types.writeUByte(one, dest, 0);
}
}