Apply 'Lhunath' code inspection fixes and improvements.
This commit is contained in:
		@@ -10,7 +10,7 @@ import java.nio.charset.Charset;
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * @author lhunath, 2016-10-29
 | 
					 * @author lhunath, 2016-10-29
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public class MPConstant {
 | 
					public final class MPConstant {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Environment */
 | 
					    /* Environment */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -58,17 +58,24 @@ public class MPConstant {
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * mpw: Input character encoding.
 | 
					     * mpw: Input character encoding.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public static final Charset                      mpw_charset   = Charsets.UTF_8;
 | 
					    public static final Charset                      mpw_charset         = Charsets.UTF_8;
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * mpw: Platform-agnostic byte order.
 | 
					     * mpw: Platform-agnostic byte order.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public static final ByteOrder                    mpw_byteOrder = ByteOrder.BIG_ENDIAN;
 | 
					    public static final ByteOrder                    mpw_byteOrder       = ByteOrder.BIG_ENDIAN;
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * mpw: Site digest.
 | 
					     * mpw: Site digest.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public static final MessageAuthenticationDigests mpw_digest    = MessageAuthenticationDigests.HmacSHA256;
 | 
					    public static final MessageAuthenticationDigests mpw_digest          = MessageAuthenticationDigests.HmacSHA256;
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * mpw: Key ID hash.
 | 
					     * mpw: Key ID hash.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public static final MessageDigests               mpw_hash      = MessageDigests.SHA256;
 | 
					    public static final MessageDigests               mpw_hash            = MessageDigests.SHA256;
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * mpw: validity for the time-based rolling counter.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static final int                          mpw_counter_timeout = 5 * 60 /* s */;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static final int MS_PER_S = 1000;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,12 +19,12 @@ public class MPIdenticon {
 | 
				
			|||||||
    private static final Logger logger = Logger.get( MPIdenticon.class );
 | 
					    private static final Logger logger = Logger.get( MPIdenticon.class );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private static final Charset charset   = Charsets.UTF_8;
 | 
					    private static final Charset charset   = Charsets.UTF_8;
 | 
				
			||||||
    private static final Color[] colors    = new Color[]{
 | 
					    private static final Color[] colors    = {
 | 
				
			||||||
            Color.RED, Color.GREEN, Color.YELLOW, Color.BLUE, Color.MAGENTA, Color.CYAN, Color.MONO };
 | 
					            Color.RED, Color.GREEN, Color.YELLOW, Color.BLUE, Color.MAGENTA, Color.CYAN, Color.MONO };
 | 
				
			||||||
    private static final char[]  leftArm   = new char[]{ '╔', '╚', '╰', '═' };
 | 
					    private static final char[]  leftArm   = { '╔', '╚', '╰', '═' };
 | 
				
			||||||
    private static final char[]  rightArm  = new char[]{ '╗', '╝', '╯', '═' };
 | 
					    private static final char[]  rightArm  = { '╗', '╝', '╯', '═' };
 | 
				
			||||||
    private static final char[]  body      = new char[]{ '█', '░', '▒', '▓', '☺', '☻' };
 | 
					    private static final char[]  body      = { '█', '░', '▒', '▓', '☺', '☻' };
 | 
				
			||||||
    private static final char[]  accessory = new char[]{
 | 
					    private static final char[]  accessory = {
 | 
				
			||||||
            '◈', '◎', '◐', '◑', '◒', '◓', '☀', '☁', '☂', '☃', '☄', '★', '☆', '☎', '☏', '⎈', '⌂', '☘', '☢', '☣', '☕', '⌚', '⌛', '⏰', '⚡',
 | 
					            '◈', '◎', '◐', '◑', '◒', '◓', '☀', '☁', '☂', '☃', '☄', '★', '☆', '☎', '☏', '⎈', '⌂', '☘', '☢', '☣', '☕', '⌚', '⌛', '⏰', '⚡',
 | 
				
			||||||
            '⛄', '⛅', '☔', '♔', '♕', '♖', '♗', '♘', '♙', '♚', '♛', '♜', '♝', '♞', '♟', '♨', '♩', '♪', '♫', '⚐', '⚑', '⚔', '⚖', '⚙', '⚠',
 | 
					            '⛄', '⛅', '☔', '♔', '♕', '♖', '♗', '♘', '♙', '♚', '♛', '♜', '♝', '♞', '♟', '♨', '♩', '♪', '♫', '⚐', '⚑', '⚔', '⚖', '⚙', '⚠',
 | 
				
			||||||
            '⌘', '⏎', '✄', '✆', '✈', '✉', '✌' };
 | 
					            '⌘', '⏎', '✄', '✆', '✈', '✉', '✌' };
 | 
				
			||||||
@@ -33,11 +33,12 @@ public class MPIdenticon {
 | 
				
			|||||||
    private final Color  color;
 | 
					    private final Color  color;
 | 
				
			||||||
    private final String text;
 | 
					    private final String text;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public MPIdenticon(String fullName, String masterPassword) {
 | 
					    public MPIdenticon(final String fullName, final String masterPassword) {
 | 
				
			||||||
        this( fullName, masterPassword.toCharArray() );
 | 
					        this( fullName, masterPassword.toCharArray() );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public MPIdenticon(String fullName, char[] masterPassword) {
 | 
					    @SuppressWarnings("MethodCanBeVariableArityMethod")
 | 
				
			||||||
 | 
					    public MPIdenticon(final String fullName, final char[] masterPassword) {
 | 
				
			||||||
        this.fullName = fullName;
 | 
					        this.fullName = fullName;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        byte[] masterPasswordBytes = charset.encode( CharBuffer.wrap( masterPassword ) ).array();
 | 
					        byte[] masterPasswordBytes = charset.encode( CharBuffer.wrap( masterPassword ) ).array();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,10 +3,10 @@ package com.lyndir.masterpassword;
 | 
				
			|||||||
import com.google.common.collect.ImmutableList;
 | 
					import com.google.common.collect.ImmutableList;
 | 
				
			||||||
import com.google.common.collect.ImmutableSet;
 | 
					import com.google.common.collect.ImmutableSet;
 | 
				
			||||||
import com.lyndir.lhunath.opal.system.logging.Logger;
 | 
					import com.lyndir.lhunath.opal.system.logging.Logger;
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.*;
 | 
				
			||||||
import java.util.Set;
 | 
					 | 
				
			||||||
import javax.annotation.Nullable;
 | 
					import javax.annotation.Nullable;
 | 
				
			||||||
import org.jetbrains.annotations.Contract;
 | 
					import org.jetbrains.annotations.Contract;
 | 
				
			||||||
 | 
					import org.jetbrains.annotations.NonNls;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@@ -17,12 +17,12 @@ import org.jetbrains.annotations.Contract;
 | 
				
			|||||||
public enum MPSiteType {
 | 
					public enum MPSiteType {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GeneratedMaximum( "Max", "20 characters, contains symbols.", //
 | 
					    GeneratedMaximum( "Max", "20 characters, contains symbols.", //
 | 
				
			||||||
                      ImmutableList.of( "x", "max", "maximum" ), //
 | 
					                      ImmutableList.of( "x", "max", "maximum" ), // NON-NLS
 | 
				
			||||||
                      ImmutableList.of( new MPTemplate( "anoxxxxxxxxxxxxxxxxx" ), new MPTemplate( "axxxxxxxxxxxxxxxxxno" ) ), //
 | 
					                      ImmutableList.of( new MPTemplate( "anoxxxxxxxxxxxxxxxxx" ), new MPTemplate( "axxxxxxxxxxxxxxxxxno" ) ), //
 | 
				
			||||||
                      MPSiteTypeClass.Generated, 0x0 ),
 | 
					                      MPSiteTypeClass.Generated, 0x0 ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GeneratedLong( "Long", "Copy-friendly, 14 characters, contains symbols.", //
 | 
					    GeneratedLong( "Long", "Copy-friendly, 14 characters, contains symbols.", //
 | 
				
			||||||
                   ImmutableList.of( "l", "long" ),  //
 | 
					                   ImmutableList.of( "l", "long" ), // NON-NLS
 | 
				
			||||||
                   ImmutableList.of( new MPTemplate( "CvcvnoCvcvCvcv" ), new MPTemplate( "CvcvCvcvnoCvcv" ),
 | 
					                   ImmutableList.of( new MPTemplate( "CvcvnoCvcvCvcv" ), new MPTemplate( "CvcvCvcvnoCvcv" ),
 | 
				
			||||||
                                     new MPTemplate( "CvcvCvcvCvcvno" ), new MPTemplate( "CvccnoCvcvCvcv" ),
 | 
					                                     new MPTemplate( "CvcvCvcvCvcvno" ), new MPTemplate( "CvccnoCvcvCvcv" ),
 | 
				
			||||||
                                     new MPTemplate( "CvccCvcvnoCvcv" ), new MPTemplate( "CvccCvcvCvcvno" ),
 | 
					                                     new MPTemplate( "CvccCvcvnoCvcv" ), new MPTemplate( "CvccCvcvCvcvno" ),
 | 
				
			||||||
@@ -37,43 +37,43 @@ public enum MPSiteType {
 | 
				
			|||||||
                   MPSiteTypeClass.Generated, 0x1 ),
 | 
					                   MPSiteTypeClass.Generated, 0x1 ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GeneratedMedium( "Medium", "Copy-friendly, 8 characters, contains symbols.", //
 | 
					    GeneratedMedium( "Medium", "Copy-friendly, 8 characters, contains symbols.", //
 | 
				
			||||||
                     ImmutableList.of( "m", "med", "medium" ), //
 | 
					                     ImmutableList.of( "m", "med", "medium" ), // NON-NLS
 | 
				
			||||||
                     ImmutableList.of( new MPTemplate( "CvcnoCvc" ), new MPTemplate( "CvcCvcno" ) ), //
 | 
					                     ImmutableList.of( new MPTemplate( "CvcnoCvc" ), new MPTemplate( "CvcCvcno" ) ), //
 | 
				
			||||||
                     MPSiteTypeClass.Generated, 0x2 ),
 | 
					                     MPSiteTypeClass.Generated, 0x2 ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GeneratedBasic( "Basic", "8 characters, no symbols.", //
 | 
					    GeneratedBasic( "Basic", "8 characters, no symbols.", //
 | 
				
			||||||
                    ImmutableList.of( "b", "basic" ), //
 | 
					                    ImmutableList.of( "b", "basic" ), // NON-NLS
 | 
				
			||||||
                    ImmutableList.of( new MPTemplate( "aaanaaan" ), new MPTemplate( "aannaaan" ), new MPTemplate( "aaannaaa" ) ), //
 | 
					                    ImmutableList.of( new MPTemplate( "aaanaaan" ), new MPTemplate( "aannaaan" ), new MPTemplate( "aaannaaa" ) ), //
 | 
				
			||||||
                    MPSiteTypeClass.Generated, 0x3 ),
 | 
					                    MPSiteTypeClass.Generated, 0x3 ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GeneratedShort( "Short", "Copy-friendly, 4 characters, no symbols.", //
 | 
					    GeneratedShort( "Short", "Copy-friendly, 4 characters, no symbols.", //
 | 
				
			||||||
                    ImmutableList.of( "s", "short" ), //
 | 
					                    ImmutableList.of( "s", "short" ), // NON-NLS
 | 
				
			||||||
                    ImmutableList.of( new MPTemplate( "Cvcn" ) ), //
 | 
					                    ImmutableList.of( new MPTemplate( "Cvcn" ) ), //
 | 
				
			||||||
                    MPSiteTypeClass.Generated, 0x4 ),
 | 
					                    MPSiteTypeClass.Generated, 0x4 ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GeneratedPIN( "PIN", "4 numbers.", //
 | 
					    GeneratedPIN( "PIN", "4 numbers.", //
 | 
				
			||||||
                  ImmutableList.of( "i", "pin" ), //
 | 
					                  ImmutableList.of( "i", "pin" ), // NON-NLS
 | 
				
			||||||
                  ImmutableList.of( new MPTemplate( "nnnn" ) ), //
 | 
					                  ImmutableList.of( new MPTemplate( "nnnn" ) ), //
 | 
				
			||||||
                  MPSiteTypeClass.Generated, 0x5 ),
 | 
					                  MPSiteTypeClass.Generated, 0x5 ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GeneratedName( "Name", "9 letter name.", //
 | 
					    GeneratedName( "Name", "9 letter name.", //
 | 
				
			||||||
                   ImmutableList.of( "n", "name" ), //
 | 
					                   ImmutableList.of( "n", "name" ), // NON-NLS
 | 
				
			||||||
                   ImmutableList.of( new MPTemplate( "cvccvcvcv" ) ), //
 | 
					                   ImmutableList.of( new MPTemplate( "cvccvcvcv" ) ), //
 | 
				
			||||||
                   MPSiteTypeClass.Generated, 0xE ),
 | 
					                   MPSiteTypeClass.Generated, 0xE ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GeneratedPhrase( "Phrase", "20 character sentence.", //
 | 
					    GeneratedPhrase( "Phrase", "20 character sentence.", //
 | 
				
			||||||
                     ImmutableList.of( "p", "phrase" ), //
 | 
					                     ImmutableList.of( "p", "phrase" ), // NON-NLS
 | 
				
			||||||
                     ImmutableList.of( new MPTemplate( "cvcc cvc cvccvcv cvc" ), new MPTemplate( "cvc cvccvcvcv cvcv" ),
 | 
					                     ImmutableList.of( new MPTemplate( "cvcc cvc cvccvcv cvc" ), new MPTemplate( "cvc cvccvcvcv cvcv" ),
 | 
				
			||||||
                                       new MPTemplate( "cv cvccv cvc cvcvccv" ) ), //
 | 
					                                       new MPTemplate( "cv cvccv cvc cvcvccv" ) ), //
 | 
				
			||||||
                     MPSiteTypeClass.Generated, 0xF ),
 | 
					                     MPSiteTypeClass.Generated, 0xF ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    StoredPersonal( "Personal", "AES-encrypted, exportable.", //
 | 
					    StoredPersonal( "Personal", "AES-encrypted, exportable.", //
 | 
				
			||||||
                    ImmutableList.of( "personal" ), //
 | 
					                    ImmutableList.of( "personal" ), // NON-NLS
 | 
				
			||||||
                    ImmutableList.<MPTemplate>of(), //
 | 
					                    ImmutableList.<MPTemplate>of(), //
 | 
				
			||||||
                    MPSiteTypeClass.Stored, 0x0, MPSiteFeature.ExportContent ),
 | 
					                    MPSiteTypeClass.Stored, 0x0, MPSiteFeature.ExportContent ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    StoredDevicePrivate( "Device", "AES-encrypted, not exported.", //
 | 
					    StoredDevicePrivate( "Device", "AES-encrypted, not exported.", //
 | 
				
			||||||
                         ImmutableList.of( "device" ), //
 | 
					                         ImmutableList.of( "device" ), // NON-NLS
 | 
				
			||||||
                         ImmutableList.<MPTemplate>of(), //
 | 
					                         ImmutableList.<MPTemplate>of(), //
 | 
				
			||||||
                         MPSiteTypeClass.Stored, 0x1, MPSiteFeature.DevicePrivate );
 | 
					                         MPSiteTypeClass.Stored, 0x1, MPSiteFeature.DevicePrivate );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -129,7 +129,7 @@ public enum MPSiteType {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public int getType() {
 | 
					    public int getType() {
 | 
				
			||||||
        int mask = typeIndex | typeClass.getMask();
 | 
					        int mask = typeIndex | typeClass.getMask();
 | 
				
			||||||
        for (MPSiteFeature typeFeature : typeFeatures)
 | 
					        for (final MPSiteFeature typeFeature : typeFeatures)
 | 
				
			||||||
            mask |= typeFeature.getMask();
 | 
					            mask |= typeFeature.getMask();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return mask;
 | 
					        return mask;
 | 
				
			||||||
@@ -143,7 +143,7 @@ public enum MPSiteType {
 | 
				
			|||||||
    public static MPSiteType forOption(final String option) {
 | 
					    public static MPSiteType forOption(final String option) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (final MPSiteType type : values())
 | 
					        for (final MPSiteType type : values())
 | 
				
			||||||
            if (type.getOptions().contains( option.toLowerCase() ))
 | 
					            if (type.getOptions().contains( option.toLowerCase( Locale.ROOT ) ))
 | 
				
			||||||
                return type;
 | 
					                return type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        throw logger.bug( "No type for option: %s", option );
 | 
					        throw logger.bug( "No type for option: %s", option );
 | 
				
			||||||
@@ -154,7 +154,7 @@ public enum MPSiteType {
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return The type registered with the given name.
 | 
					     * @return The type registered with the given name.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    @Contract("!null -> !null, null -> null")
 | 
					    @Contract("!null -> !null")
 | 
				
			||||||
    public static MPSiteType forName(@Nullable final String name) {
 | 
					    public static MPSiteType forName(@Nullable final String name) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (name == null)
 | 
					        if (name == null)
 | 
				
			||||||
@@ -189,7 +189,7 @@ public enum MPSiteType {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public static MPSiteType forType(final int type) {
 | 
					    public static MPSiteType forType(final int type) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (MPSiteType siteType : values())
 | 
					        for (final MPSiteType siteType : values())
 | 
				
			||||||
            if (siteType.getType() == type)
 | 
					            if (siteType.getType() == type)
 | 
				
			||||||
                return siteType;
 | 
					                return siteType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -205,7 +205,7 @@ public enum MPSiteType {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        int typeMask = mask & ~0xF;
 | 
					        int typeMask = mask & ~0xF;
 | 
				
			||||||
        ImmutableList.Builder<MPSiteType> types = ImmutableList.builder();
 | 
					        ImmutableList.Builder<MPSiteType> types = ImmutableList.builder();
 | 
				
			||||||
        for (MPSiteType siteType : values())
 | 
					        for (final MPSiteType siteType : values())
 | 
				
			||||||
            if (((siteType.getType() & ~0xF) & typeMask) != 0)
 | 
					            if (((siteType.getType() & ~0xF) & typeMask) != 0)
 | 
				
			||||||
                types.add( siteType );
 | 
					                types.add( siteType );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,8 +3,10 @@ package com.lyndir.masterpassword;
 | 
				
			|||||||
import com.google.common.collect.ImmutableList;
 | 
					import com.google.common.collect.ImmutableList;
 | 
				
			||||||
import com.lyndir.lhunath.opal.system.logging.Logger;
 | 
					import com.lyndir.lhunath.opal.system.logging.Logger;
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					import java.util.Locale;
 | 
				
			||||||
import javax.annotation.Nullable;
 | 
					import javax.annotation.Nullable;
 | 
				
			||||||
import org.jetbrains.annotations.Contract;
 | 
					import org.jetbrains.annotations.Contract;
 | 
				
			||||||
 | 
					import org.jetbrains.annotations.NonNls;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@@ -12,11 +14,11 @@ import org.jetbrains.annotations.Contract;
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
public enum MPSiteVariant {
 | 
					public enum MPSiteVariant {
 | 
				
			||||||
    Password( "Generate a key for authentication.", "Doesn't currently use a context.", //
 | 
					    Password( "Generate a key for authentication.", "Doesn't currently use a context.", //
 | 
				
			||||||
              ImmutableList.of( "p", "password" ), "com.lyndir.masterpassword" ),
 | 
					              ImmutableList.of( "p", "password" ), "com.lyndir.masterpassword" ), // NON-NLS
 | 
				
			||||||
    Login( "Generate a name for identification.", "Doesn't currently use a context.", //
 | 
					    Login( "Generate a name for identification.", "Doesn't currently use a context.", //
 | 
				
			||||||
           ImmutableList.of( "l", "login" ), "com.lyndir.masterpassword.login" ),
 | 
					           ImmutableList.of( "l", "login" ), "com.lyndir.masterpassword.login" ), // NON-NLS
 | 
				
			||||||
    Answer( "Generate an answer to a security question.", "Empty for a universal site answer or\nthe most significant word(s) of the question.", //
 | 
					    Answer( "Generate an answer to a security question.", "Empty for a universal site answer or\nthe most significant word(s) of the question.", //
 | 
				
			||||||
            ImmutableList.of( "a", "answer" ), "com.lyndir.masterpassword.answer" );
 | 
					            ImmutableList.of( "a", "answer" ), "com.lyndir.masterpassword.answer" ); // NON-NLS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static final Logger logger = Logger.get( MPSiteType.class );
 | 
					    static final Logger logger = Logger.get( MPSiteType.class );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -25,7 +27,7 @@ public enum MPSiteVariant {
 | 
				
			|||||||
    private final List<String> options;
 | 
					    private final List<String> options;
 | 
				
			||||||
    private final String       scope;
 | 
					    private final String       scope;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    MPSiteVariant(final String description, final String contextDescription, final List<String> options, final String scope) {
 | 
					    MPSiteVariant(final String description, final String contextDescription, final List<String> options, @NonNls final String scope) {
 | 
				
			||||||
        this.contextDescription = contextDescription;
 | 
					        this.contextDescription = contextDescription;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.options = options;
 | 
					        this.options = options;
 | 
				
			||||||
@@ -57,7 +59,7 @@ public enum MPSiteVariant {
 | 
				
			|||||||
    public static MPSiteVariant forOption(final String option) {
 | 
					    public static MPSiteVariant forOption(final String option) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (final MPSiteVariant variant : values())
 | 
					        for (final MPSiteVariant variant : values())
 | 
				
			||||||
            if (variant.getOptions().contains( option.toLowerCase() ))
 | 
					            if (variant.getOptions().contains( option.toLowerCase( Locale.ROOT ) ))
 | 
				
			||||||
                return variant;
 | 
					                return variant;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        throw logger.bug( "No variant for option: %s", option );
 | 
					        throw logger.bug( "No variant for option: %s", option );
 | 
				
			||||||
@@ -67,7 +69,7 @@ public enum MPSiteVariant {
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return The variant registered with the given name.
 | 
					     * @return The variant registered with the given name.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    @Contract("!null -> !null, null -> null")
 | 
					    @Contract("!null -> !null")
 | 
				
			||||||
    public static MPSiteVariant forName(@Nullable final String name) {
 | 
					    public static MPSiteVariant forName(@Nullable final String name) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (name == null)
 | 
					        if (name == null)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,9 @@ import static com.lyndir.lhunath.opal.system.util.StringUtils.strf;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import com.google.common.collect.ImmutableList;
 | 
					import com.google.common.collect.ImmutableList;
 | 
				
			||||||
import com.lyndir.lhunath.opal.system.util.MetaObject;
 | 
					import com.lyndir.lhunath.opal.system.util.MetaObject;
 | 
				
			||||||
 | 
					import java.io.Serializable;
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					import org.jetbrains.annotations.NonNls;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@@ -12,12 +14,14 @@ import java.util.List;
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 * @author lhunath
 | 
					 * @author lhunath
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public class MPTemplate extends MetaObject {
 | 
					public class MPTemplate extends MetaObject implements Serializable {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private final String                         templateString;
 | 
					    private static final long serialVersionUID = 1L;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private final String templateString;
 | 
				
			||||||
    private final List<MPTemplateCharacterClass> template;
 | 
					    private final List<MPTemplateCharacterClass> template;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    MPTemplate(final String templateString) {
 | 
					    MPTemplate(@NonNls final String templateString) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ImmutableList.Builder<MPTemplateCharacterClass> builder = ImmutableList.builder();
 | 
					        ImmutableList.Builder<MPTemplateCharacterClass> builder = ImmutableList.builder();
 | 
				
			||||||
        for (int i = 0; i < templateString.length(); ++i)
 | 
					        for (int i = 0; i < templateString.length(); ++i)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
package com.lyndir.masterpassword;
 | 
					package com.lyndir.masterpassword;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.lyndir.lhunath.opal.system.logging.Logger;
 | 
					import com.lyndir.lhunath.opal.system.logging.Logger;
 | 
				
			||||||
 | 
					import org.jetbrains.annotations.NonNls;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@@ -27,7 +28,7 @@ public enum MPTemplateCharacterClass {
 | 
				
			|||||||
    private final char   identifier;
 | 
					    private final char   identifier;
 | 
				
			||||||
    private final char[] characters;
 | 
					    private final char[] characters;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    MPTemplateCharacterClass(final char identifier, final String characters) {
 | 
					    MPTemplateCharacterClass(final char identifier, @NonNls final String characters) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.identifier = identifier;
 | 
					        this.identifier = identifier;
 | 
				
			||||||
        this.characters = characters.toCharArray();
 | 
					        this.characters = characters.toCharArray();
 | 
				
			||||||
@@ -44,7 +45,7 @@ public enum MPTemplateCharacterClass {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static MPTemplateCharacterClass forIdentifier(final char identifier) {
 | 
					    public static MPTemplateCharacterClass forIdentifier(final char identifier) {
 | 
				
			||||||
        for (MPTemplateCharacterClass characterClass : values())
 | 
					        for (final MPTemplateCharacterClass characterClass : values())
 | 
				
			||||||
            if (characterClass.getIdentifier() == identifier)
 | 
					            if (characterClass.getIdentifier() == identifier)
 | 
				
			||||||
                return characterClass;
 | 
					                return characterClass;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,7 @@
 | 
				
			|||||||
package com.lyndir.masterpassword;
 | 
					package com.lyndir.masterpassword;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import static com.lyndir.lhunath.opal.system.util.StringUtils.strf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.google.common.base.Preconditions;
 | 
					import com.google.common.base.Preconditions;
 | 
				
			||||||
import com.google.common.primitives.UnsignedInteger;
 | 
					import com.google.common.primitives.UnsignedInteger;
 | 
				
			||||||
import com.lyndir.lhunath.opal.system.*;
 | 
					import com.lyndir.lhunath.opal.system.*;
 | 
				
			||||||
@@ -7,7 +9,6 @@ import com.lyndir.lhunath.opal.system.logging.Logger;
 | 
				
			|||||||
import java.util.Arrays;
 | 
					import java.util.Arrays;
 | 
				
			||||||
import javax.annotation.Nonnull;
 | 
					import javax.annotation.Nonnull;
 | 
				
			||||||
import javax.annotation.Nullable;
 | 
					import javax.annotation.Nullable;
 | 
				
			||||||
import org.jetbrains.annotations.NotNull;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@@ -26,13 +27,15 @@ public abstract class MasterKey {
 | 
				
			|||||||
    @Nullable
 | 
					    @Nullable
 | 
				
			||||||
    private byte[] masterKey;
 | 
					    private byte[] masterKey;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @SuppressWarnings("MethodCanBeVariableArityMethod")
 | 
				
			||||||
    public static MasterKey create(final String fullName, final char[] masterPassword) {
 | 
					    public static MasterKey create(final String fullName, final char[] masterPassword) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return create( Version.CURRENT, fullName, masterPassword );
 | 
					        return create( Version.CURRENT, fullName, masterPassword );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Nonnull
 | 
					    @Nonnull
 | 
				
			||||||
    public static MasterKey create(Version version, final String fullName, final char[] masterPassword) {
 | 
					    @SuppressWarnings("MethodCanBeVariableArityMethod")
 | 
				
			||||||
 | 
					    public static MasterKey create(final Version version, final String fullName, final char[] masterPassword) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        switch (version) {
 | 
					        switch (version) {
 | 
				
			||||||
            case V0:
 | 
					            case V0:
 | 
				
			||||||
@@ -45,7 +48,7 @@ public abstract class MasterKey {
 | 
				
			|||||||
                return new MasterKeyV3( fullName ).revalidate( masterPassword );
 | 
					                return new MasterKeyV3( fullName ).revalidate( masterPassword );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        throw new UnsupportedOperationException( "Unsupported version: " + version );
 | 
					        throw new UnsupportedOperationException( strf( "Unsupported version: %s", version ) );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static boolean isAllowNativeByDefault() {
 | 
					    public static boolean isAllowNativeByDefault() {
 | 
				
			||||||
@@ -65,18 +68,19 @@ public abstract class MasterKey {
 | 
				
			|||||||
        allowNativeByDefault = allowNative;
 | 
					        allowNativeByDefault = allowNative;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected MasterKey(@NotNull final String fullName) {
 | 
					    protected MasterKey(@Nonnull final String fullName) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.fullName = fullName;
 | 
					        this.fullName = fullName;
 | 
				
			||||||
        logger.trc( "fullName: %s", fullName );
 | 
					        logger.trc( "fullName: %s", fullName );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Nullable
 | 
					    @Nullable
 | 
				
			||||||
    protected abstract byte[] deriveKey(final char[] masterPassword);
 | 
					    @SuppressWarnings("MethodCanBeVariableArityMethod")
 | 
				
			||||||
 | 
					    protected abstract byte[] deriveKey(char[] masterPassword);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract Version getAlgorithmVersion();
 | 
					    public abstract Version getAlgorithmVersion();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @NotNull
 | 
					    @Nonnull
 | 
				
			||||||
    public String getFullName() {
 | 
					    public String getFullName() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return fullName;
 | 
					        return fullName;
 | 
				
			||||||
@@ -103,8 +107,8 @@ public abstract class MasterKey {
 | 
				
			|||||||
        return idForBytes( getKey() );
 | 
					        return idForBytes( getKey() );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract String encode(@Nonnull final String siteName, final MPSiteType siteType, @Nonnull final UnsignedInteger siteCounter,
 | 
					    public abstract String encode(@Nonnull String siteName, MPSiteType siteType, @Nonnull UnsignedInteger siteCounter,
 | 
				
			||||||
                                  final MPSiteVariant siteVariant, @Nullable final String siteContext);
 | 
					                                  MPSiteVariant siteVariant, @Nullable String siteContext);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public boolean isValid() {
 | 
					    public boolean isValid() {
 | 
				
			||||||
        return masterKey != null;
 | 
					        return masterKey != null;
 | 
				
			||||||
@@ -118,6 +122,7 @@ public abstract class MasterKey {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @SuppressWarnings("MethodCanBeVariableArityMethod")
 | 
				
			||||||
    public MasterKey revalidate(final char[] masterPassword) {
 | 
					    public MasterKey revalidate(final char[] masterPassword) {
 | 
				
			||||||
        invalidate();
 | 
					        invalidate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -127,19 +132,19 @@ public abstract class MasterKey {
 | 
				
			|||||||
        masterKey = deriveKey( masterPassword );
 | 
					        masterKey = deriveKey( masterPassword );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (masterKey == null)
 | 
					        if (masterKey == null)
 | 
				
			||||||
            logger.dbg( "masterKey calculation failed after %.2fs.", (System.currentTimeMillis() - start) / 1000D );
 | 
					            logger.dbg( "masterKey calculation failed after %.2fs.", (double)(System.currentTimeMillis() - start) / MPConstant.MS_PER_S );
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
            logger.trc( "masterKey ID: %s (derived in %.2fs)", CodeUtils.encodeHex( idForBytes( masterKey ) ),
 | 
					            logger.trc( "masterKey ID: %s (derived in %.2fs)", CodeUtils.encodeHex( idForBytes( masterKey ) ),
 | 
				
			||||||
                        (System.currentTimeMillis() - start) / 1000D );
 | 
					                        (double)(System.currentTimeMillis() - start) / MPConstant.MS_PER_S );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return this;
 | 
					        return this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected abstract byte[] bytesForInt(final int number);
 | 
					    protected abstract byte[] bytesForInt(int number);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected abstract byte[] bytesForInt(@Nonnull final UnsignedInteger number);
 | 
					    protected abstract byte[] bytesForInt(@Nonnull UnsignedInteger number);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected abstract byte[] idForBytes(final byte[] bytes);
 | 
					    protected abstract byte[] idForBytes(byte[] bytes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public enum Version {
 | 
					    public enum Version {
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
@@ -190,7 +195,7 @@ public abstract class MasterKey {
 | 
				
			|||||||
                    return "2.2";
 | 
					                    return "2.2";
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            throw new UnsupportedOperationException( "Unsupported version: " + this );
 | 
					            throw new UnsupportedOperationException( strf( "Unsupported version: %s", this ) );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -58,6 +58,7 @@ public class MasterKeyV0 extends MasterKey {
 | 
				
			|||||||
        return scrypt( masterKeySalt, mpBytes );
 | 
					        return scrypt( masterKeySalt, mpBytes );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Nullable
 | 
				
			||||||
    protected byte[] scrypt(final byte[] masterKeySalt, final byte[] mpBytes) {
 | 
					    protected byte[] scrypt(final byte[] masterKeySalt, final byte[] mpBytes) {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            if (isAllowNative())
 | 
					            if (isAllowNative())
 | 
				
			||||||
@@ -65,7 +66,7 @@ public class MasterKeyV0 extends MasterKey {
 | 
				
			|||||||
            else
 | 
					            else
 | 
				
			||||||
                return SCrypt.scryptJ( mpBytes, masterKeySalt, MPConstant.scrypt_N, MPConstant.scrypt_r, MPConstant.scrypt_p, MPConstant.mpw_dkLen );
 | 
					                return SCrypt.scryptJ( mpBytes, masterKeySalt, MPConstant.scrypt_N, MPConstant.scrypt_r, MPConstant.scrypt_p, MPConstant.mpw_dkLen );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        catch (GeneralSecurityException e) {
 | 
					        catch (final GeneralSecurityException e) {
 | 
				
			||||||
            logger.bug( e );
 | 
					            logger.bug( e );
 | 
				
			||||||
            return null;
 | 
					            return null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -86,18 +87,18 @@ public class MasterKeyV0 extends MasterKey {
 | 
				
			|||||||
        logger.trc( "siteType: %d (%s)", siteType.ordinal(), siteType );
 | 
					        logger.trc( "siteType: %d (%s)", siteType.ordinal(), siteType );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (siteCounter.longValue() == 0)
 | 
					        if (siteCounter.longValue() == 0)
 | 
				
			||||||
            siteCounter = UnsignedInteger.valueOf( (System.currentTimeMillis() / (300 * 1000)) * 300 );
 | 
					            siteCounter = UnsignedInteger.valueOf( (System.currentTimeMillis() / (MPConstant.mpw_counter_timeout * 1000)) * MPConstant.mpw_counter_timeout );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        String siteScope = siteVariant.getScope();
 | 
					        String siteScope = siteVariant.getScope();
 | 
				
			||||||
        byte[] siteNameBytes = siteName.getBytes( MPConstant.mpw_charset );
 | 
					        byte[] siteNameBytes = siteName.getBytes( MPConstant.mpw_charset );
 | 
				
			||||||
        byte[] siteNameLengthBytes = bytesForInt( siteName.length() );
 | 
					        byte[] siteNameLengthBytes = bytesForInt( siteName.length() );
 | 
				
			||||||
        byte[] siteCounterBytes = bytesForInt( siteCounter );
 | 
					        byte[] siteCounterBytes = bytesForInt( siteCounter );
 | 
				
			||||||
        byte[] siteContextBytes = siteContext == null || siteContext.isEmpty()? null: siteContext.getBytes( MPConstant.mpw_charset );
 | 
					        byte[] siteContextBytes = ((siteContext == null) || siteContext.isEmpty())? null: siteContext.getBytes( MPConstant.mpw_charset );
 | 
				
			||||||
        byte[] siteContextLengthBytes = bytesForInt( siteContextBytes == null? 0: siteContextBytes.length );
 | 
					        byte[] siteContextLengthBytes = bytesForInt( (siteContextBytes == null)? 0: siteContextBytes.length );
 | 
				
			||||||
        logger.trc( "site scope: %s, context: %s", siteScope, siteContextBytes == null? "<empty>": siteContext );
 | 
					        logger.trc( "site scope: %s, context: %s", siteScope, (siteContextBytes == null)? "<empty>": siteContext );
 | 
				
			||||||
        logger.trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)", siteScope, CodeUtils.encodeHex( siteNameLengthBytes ),
 | 
					        logger.trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)", siteScope, CodeUtils.encodeHex( siteNameLengthBytes ),
 | 
				
			||||||
                    siteName, CodeUtils.encodeHex( siteCounterBytes ), CodeUtils.encodeHex( siteContextLengthBytes ),
 | 
					                    siteName, CodeUtils.encodeHex( siteCounterBytes ), CodeUtils.encodeHex( siteContextLengthBytes ),
 | 
				
			||||||
                    siteContextBytes == null? "(null)": siteContext );
 | 
					                    (siteContextBytes == null)? "(null)": siteContext );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        byte[] sitePasswordInfo = Bytes.concat( siteScope.getBytes( MPConstant.mpw_charset ), siteNameLengthBytes, siteNameBytes, siteCounterBytes );
 | 
					        byte[] sitePasswordInfo = Bytes.concat( siteScope.getBytes( MPConstant.mpw_charset ), siteNameLengthBytes, siteNameBytes, siteCounterBytes );
 | 
				
			||||||
        if (siteContextBytes != null)
 | 
					        if (siteContextBytes != null)
 | 
				
			||||||
@@ -108,7 +109,7 @@ public class MasterKeyV0 extends MasterKey {
 | 
				
			|||||||
        int[] sitePasswordSeed = new int[sitePasswordSeedBytes.length];
 | 
					        int[] sitePasswordSeed = new int[sitePasswordSeedBytes.length];
 | 
				
			||||||
        for (int i = 0; i < sitePasswordSeedBytes.length; ++i) {
 | 
					        for (int i = 0; i < sitePasswordSeedBytes.length; ++i) {
 | 
				
			||||||
            ByteBuffer buf = ByteBuffer.allocate( Integer.SIZE / Byte.SIZE ).order( ByteOrder.BIG_ENDIAN );
 | 
					            ByteBuffer buf = ByteBuffer.allocate( Integer.SIZE / Byte.SIZE ).order( ByteOrder.BIG_ENDIAN );
 | 
				
			||||||
            Arrays.fill( buf.array(), sitePasswordSeedBytes[i] > 0? (byte) 0x00: (byte) 0xFF );
 | 
					            Arrays.fill( buf.array(), (byte) ((sitePasswordSeedBytes[i] > 0)? 0x00: 0xFF) );
 | 
				
			||||||
            buf.position( 2 );
 | 
					            buf.position( 2 );
 | 
				
			||||||
            buf.put( sitePasswordSeedBytes[i] ).rewind();
 | 
					            buf.put( sitePasswordSeedBytes[i] ).rewind();
 | 
				
			||||||
            sitePasswordSeed[i] = buf.getInt() & 0xFFFF;
 | 
					            sitePasswordSeed[i] = buf.getInt() & 0xFFFF;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -43,18 +43,18 @@ public class MasterKeyV1 extends MasterKeyV0 {
 | 
				
			|||||||
        logger.trc( "siteType: %d (%s)", siteType.ordinal(), siteType );
 | 
					        logger.trc( "siteType: %d (%s)", siteType.ordinal(), siteType );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (siteCounter.longValue() == 0)
 | 
					        if (siteCounter.longValue() == 0)
 | 
				
			||||||
            siteCounter = UnsignedInteger.valueOf( (System.currentTimeMillis() / (300 * 1000)) * 300 );
 | 
					            siteCounter = UnsignedInteger.valueOf( (System.currentTimeMillis() / (MPConstant.mpw_counter_timeout * 1000)) * MPConstant.mpw_counter_timeout );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        String siteScope = siteVariant.getScope();
 | 
					        String siteScope = siteVariant.getScope();
 | 
				
			||||||
        byte[] siteNameBytes = siteName.getBytes( MPConstant.mpw_charset );
 | 
					        byte[] siteNameBytes = siteName.getBytes( MPConstant.mpw_charset );
 | 
				
			||||||
        byte[] siteNameLengthBytes = bytesForInt( siteName.length() );
 | 
					        byte[] siteNameLengthBytes = bytesForInt( siteName.length() );
 | 
				
			||||||
        byte[] siteCounterBytes = bytesForInt( siteCounter );
 | 
					        byte[] siteCounterBytes = bytesForInt( siteCounter );
 | 
				
			||||||
        byte[] siteContextBytes = siteContext == null || siteContext.isEmpty()? null: siteContext.getBytes( MPConstant.mpw_charset );
 | 
					        byte[] siteContextBytes = ((siteContext == null) || siteContext.isEmpty())? null: siteContext.getBytes( MPConstant.mpw_charset );
 | 
				
			||||||
        byte[] siteContextLengthBytes = bytesForInt( siteContextBytes == null? 0: siteContextBytes.length );
 | 
					        byte[] siteContextLengthBytes = bytesForInt( (siteContextBytes == null)? 0: siteContextBytes.length );
 | 
				
			||||||
        logger.trc( "site scope: %s, context: %s", siteScope, siteContextBytes == null? "<empty>": siteContext );
 | 
					        logger.trc( "site scope: %s, context: %s", siteScope, (siteContextBytes == null)? "<empty>": siteContext );
 | 
				
			||||||
        logger.trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)", siteScope, CodeUtils.encodeHex( siteNameLengthBytes ),
 | 
					        logger.trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)", siteScope, CodeUtils.encodeHex( siteNameLengthBytes ),
 | 
				
			||||||
                    siteName, CodeUtils.encodeHex( siteCounterBytes ), CodeUtils.encodeHex( siteContextLengthBytes ),
 | 
					                    siteName, CodeUtils.encodeHex( siteCounterBytes ), CodeUtils.encodeHex( siteContextLengthBytes ),
 | 
				
			||||||
                    siteContextBytes == null? "(null)": siteContext );
 | 
					                    (siteContextBytes == null)? "(null)": siteContext );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        byte[] sitePasswordInfo = Bytes.concat( siteScope.getBytes( MPConstant.mpw_charset ), siteNameLengthBytes, siteNameBytes, siteCounterBytes );
 | 
					        byte[] sitePasswordInfo = Bytes.concat( siteScope.getBytes( MPConstant.mpw_charset ), siteNameLengthBytes, siteNameBytes, siteCounterBytes );
 | 
				
			||||||
        if (siteContextBytes != null)
 | 
					        if (siteContextBytes != null)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,18 +42,18 @@ public class MasterKeyV2 extends MasterKeyV1 {
 | 
				
			|||||||
        logger.trc( "siteType: %d (%s)", siteType.ordinal(), siteType );
 | 
					        logger.trc( "siteType: %d (%s)", siteType.ordinal(), siteType );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (siteCounter.longValue() == 0)
 | 
					        if (siteCounter.longValue() == 0)
 | 
				
			||||||
            siteCounter = UnsignedInteger.valueOf( (System.currentTimeMillis() / (300 * 1000)) * 300 );
 | 
					            siteCounter = UnsignedInteger.valueOf( (System.currentTimeMillis() / (MPConstant.mpw_counter_timeout * 1000)) * MPConstant.mpw_counter_timeout );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        String siteScope = siteVariant.getScope();
 | 
					        String siteScope = siteVariant.getScope();
 | 
				
			||||||
        byte[] siteNameBytes = siteName.getBytes( MPConstant.mpw_charset );
 | 
					        byte[] siteNameBytes = siteName.getBytes( MPConstant.mpw_charset );
 | 
				
			||||||
        byte[] siteNameLengthBytes = bytesForInt( siteNameBytes.length );
 | 
					        byte[] siteNameLengthBytes = bytesForInt( siteNameBytes.length );
 | 
				
			||||||
        byte[] siteCounterBytes = bytesForInt( siteCounter );
 | 
					        byte[] siteCounterBytes = bytesForInt( siteCounter );
 | 
				
			||||||
        byte[] siteContextBytes = siteContext == null || siteContext.isEmpty()? null: siteContext.getBytes( MPConstant.mpw_charset );
 | 
					        byte[] siteContextBytes = ((siteContext == null) || siteContext.isEmpty())? null: siteContext.getBytes( MPConstant.mpw_charset );
 | 
				
			||||||
        byte[] siteContextLengthBytes = bytesForInt( siteContextBytes == null? 0: siteContextBytes.length );
 | 
					        byte[] siteContextLengthBytes = bytesForInt( (siteContextBytes == null)? 0: siteContextBytes.length );
 | 
				
			||||||
        logger.trc( "site scope: %s, context: %s", siteScope, siteContextBytes == null? "<empty>": siteContext );
 | 
					        logger.trc( "site scope: %s, context: %s", siteScope, (siteContextBytes == null)? "<empty>": siteContext );
 | 
				
			||||||
        logger.trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)", siteScope, CodeUtils.encodeHex( siteNameLengthBytes ),
 | 
					        logger.trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)", siteScope, CodeUtils.encodeHex( siteNameLengthBytes ),
 | 
				
			||||||
                    siteName, CodeUtils.encodeHex( siteCounterBytes ), CodeUtils.encodeHex( siteContextLengthBytes ),
 | 
					                    siteName, CodeUtils.encodeHex( siteCounterBytes ), CodeUtils.encodeHex( siteContextLengthBytes ),
 | 
				
			||||||
                    siteContextBytes == null? "(null)": siteContext );
 | 
					                    (siteContextBytes == null)? "(null)": siteContext );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        byte[] sitePasswordInfo = Bytes.concat( siteScope.getBytes( MPConstant.mpw_charset ), siteNameLengthBytes, siteNameBytes, siteCounterBytes );
 | 
					        byte[] sitePasswordInfo = Bytes.concat( siteScope.getBytes( MPConstant.mpw_charset ), siteNameLengthBytes, siteNameBytes, siteCounterBytes );
 | 
				
			||||||
        if (siteContextBytes != null)
 | 
					        if (siteContextBytes != null)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,7 +6,7 @@ plugins {
 | 
				
			|||||||
description = 'Master Password Site Model'
 | 
					description = 'Master Password Site Model'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dependencies {
 | 
					dependencies {
 | 
				
			||||||
    compile     project(':masterpassword:algorithm')
 | 
					    compile     project(':masterpassword-algorithm')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    compile     group: 'joda-time', name: 'joda-time', version:'2.4'
 | 
					    compile     group: 'joda-time', name: 'joda-time', version:'2.4'
 | 
				
			||||||
    compileOnly group: 'com.google.auto.value', name: 'auto-value', version: '1.2'
 | 
					    compileOnly group: 'com.google.auto.value', name: 'auto-value', version: '1.2'
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -128,7 +128,7 @@ public class MPSite {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public boolean equals(final Object obj) {
 | 
					    public boolean equals(final Object obj) {
 | 
				
			||||||
        return this == obj || obj instanceof MPSite && Objects.equals( siteName, ((MPSite) obj).siteName );
 | 
					        return (this == obj) || ((obj instanceof MPSite) && Objects.equals( siteName, ((MPSite) obj).siteName ));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,7 +26,7 @@ public class MPSiteMarshaller {
 | 
				
			|||||||
    public static MPSiteMarshaller marshallSafe(final MPUser user) {
 | 
					    public static MPSiteMarshaller marshallSafe(final MPUser user) {
 | 
				
			||||||
        MPSiteMarshaller marshaller = new MPSiteMarshaller();
 | 
					        MPSiteMarshaller marshaller = new MPSiteMarshaller();
 | 
				
			||||||
        marshaller.marshallHeaderForSafeContent( user );
 | 
					        marshaller.marshallHeaderForSafeContent( user );
 | 
				
			||||||
        for (MPSite site : user.getSites())
 | 
					        for (final MPSite site : user.getSites())
 | 
				
			||||||
            marshaller.marshallSite( site );
 | 
					            marshaller.marshallSite( site );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return marshaller;
 | 
					        return marshaller;
 | 
				
			||||||
@@ -35,7 +35,7 @@ public class MPSiteMarshaller {
 | 
				
			|||||||
    public static MPSiteMarshaller marshallVisible(final MPUser user, final MasterKey masterKey) {
 | 
					    public static MPSiteMarshaller marshallVisible(final MPUser user, final MasterKey masterKey) {
 | 
				
			||||||
        MPSiteMarshaller marshaller = new MPSiteMarshaller();
 | 
					        MPSiteMarshaller marshaller = new MPSiteMarshaller();
 | 
				
			||||||
        marshaller.marshallHeaderForVisibleContentWithKey( user, masterKey );
 | 
					        marshaller.marshallHeaderForVisibleContentWithKey( user, masterKey );
 | 
				
			||||||
        for (MPSite site : user.getSites())
 | 
					        for (final MPSite site : user.getSites())
 | 
				
			||||||
            marshaller.marshallSite( site );
 | 
					            marshaller.marshallSite( site );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return marshaller;
 | 
					        return marshaller;
 | 
				
			||||||
@@ -77,7 +77,7 @@ public class MPSiteMarshaller {
 | 
				
			|||||||
        return header.toString();
 | 
					        return header.toString();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public String marshallSite(MPSite site) {
 | 
					    public String marshallSite(final MPSite site) {
 | 
				
			||||||
        String exportLine = strf( "%s  %8d  %8s  %25s\t%25s\t%s", //
 | 
					        String exportLine = strf( "%s  %8d  %8s  %25s\t%25s\t%s", //
 | 
				
			||||||
                                  rfc3339.print( site.getLastUsed() ), // lastUsed
 | 
					                                  rfc3339.print( site.getLastUsed() ), // lastUsed
 | 
				
			||||||
                                  site.getUses(), // uses
 | 
					                                  site.getUses(), // uses
 | 
				
			||||||
@@ -126,6 +126,6 @@ public class MPSiteMarshaller {
 | 
				
			|||||||
            return description;
 | 
					            return description;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public abstract String contentForSite(final MPSite site, final MasterKey masterKey);
 | 
					        public abstract String contentForSite(MPSite site, MasterKey masterKey);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,7 +22,7 @@ public class MPSiteResult {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public boolean equals(final Object obj) {
 | 
					    public boolean equals(final Object obj) {
 | 
				
			||||||
        return this == obj || obj instanceof MPSiteResult && Objects.equals( site, ((MPSiteResult) obj).site );
 | 
					        return (this == obj) || ((obj instanceof MPSiteResult) && Objects.equals( site, ((MPSiteResult) obj).site ));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@ package com.lyndir.masterpassword.model;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import static com.lyndir.lhunath.opal.system.util.ObjectUtils.*;
 | 
					import static com.lyndir.lhunath.opal.system.util.ObjectUtils.*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.google.common.base.Charsets;
 | 
				
			||||||
import com.google.common.base.Preconditions;
 | 
					import com.google.common.base.Preconditions;
 | 
				
			||||||
import com.google.common.collect.ImmutableList;
 | 
					import com.google.common.collect.ImmutableList;
 | 
				
			||||||
import com.google.common.io.CharStreams;
 | 
					import com.google.common.io.CharStreams;
 | 
				
			||||||
@@ -31,26 +32,28 @@ public class MPSiteUnmarshaller {
 | 
				
			|||||||
    @SuppressWarnings("UnusedDeclaration")
 | 
					    @SuppressWarnings("UnusedDeclaration")
 | 
				
			||||||
    private static final Logger            logger            = Logger.get( MPSite.class );
 | 
					    private static final Logger            logger            = Logger.get( MPSite.class );
 | 
				
			||||||
    private static final DateTimeFormatter rfc3339           = ISODateTimeFormat.dateTimeNoMillis();
 | 
					    private static final DateTimeFormatter rfc3339           = ISODateTimeFormat.dateTimeNoMillis();
 | 
				
			||||||
    private static final Pattern[]         unmarshallFormats = new Pattern[]{
 | 
					    private static final Pattern[]         unmarshallFormats = {
 | 
				
			||||||
            Pattern.compile( "^([^ ]+) +(\\d+) +(\\d+)(:\\d+)? +([^\t]+)\t(.*)" ),
 | 
					            Pattern.compile( "^([^ ]+) +(\\d+) +(\\d+)(:\\d+)? +([^\t]+)\t(.*)" ),
 | 
				
			||||||
            Pattern.compile( "^([^ ]+) +(\\d+) +(\\d+)(:\\d+)?(:\\d+)? +([^\t]*)\t *([^\t]+)\t(.*)" ) };
 | 
					            Pattern.compile( "^([^ ]+) +(\\d+) +(\\d+)(:\\d+)?(:\\d+)? +([^\t]*)\t *([^\t]+)\t(.*)" ) };
 | 
				
			||||||
    private static final Pattern           headerFormat      = Pattern.compile( "^#\\s*([^:]+): (.*)" );
 | 
					    private static final Pattern           headerFormat      = Pattern.compile( "^#\\s*([^:]+): (.*)" );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private final int     importFormat;
 | 
					    private final int     importFormat;
 | 
				
			||||||
 | 
					    @SuppressWarnings({ "FieldCanBeLocal", "unused" })
 | 
				
			||||||
    private final int     mpVersion;
 | 
					    private final int     mpVersion;
 | 
				
			||||||
 | 
					    @SuppressWarnings({ "FieldCanBeLocal", "unused" })
 | 
				
			||||||
    private final boolean clearContent;
 | 
					    private final boolean clearContent;
 | 
				
			||||||
    private final MPUser  user;
 | 
					    private final MPUser  user;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Nonnull
 | 
					    @Nonnull
 | 
				
			||||||
    public static MPSiteUnmarshaller unmarshall(@Nonnull File file)
 | 
					    public static MPSiteUnmarshaller unmarshall(@Nonnull final File file)
 | 
				
			||||||
            throws IOException {
 | 
					            throws IOException {
 | 
				
			||||||
        try (Reader reader = new FileReader( file )) {
 | 
					        try (Reader reader = new InputStreamReader( new FileInputStream( file ), Charsets.UTF_8 )) {
 | 
				
			||||||
            return unmarshall( CharStreams.readLines( reader ) );
 | 
					            return unmarshall( CharStreams.readLines( reader ) );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Nonnull
 | 
					    @Nonnull
 | 
				
			||||||
    public static MPSiteUnmarshaller unmarshall(@Nonnull List<String> lines) {
 | 
					    public static MPSiteUnmarshaller unmarshall(@Nonnull final List<String> lines) {
 | 
				
			||||||
        byte[] keyID = null;
 | 
					        byte[] keyID = null;
 | 
				
			||||||
        String fullName = null;
 | 
					        String fullName = null;
 | 
				
			||||||
        int mpVersion = 0, importFormat = 0, avatar = 0;
 | 
					        int mpVersion = 0, importFormat = 0, avatar = 0;
 | 
				
			||||||
@@ -59,7 +62,7 @@ public class MPSiteUnmarshaller {
 | 
				
			|||||||
        MPSiteUnmarshaller marshaller = null;
 | 
					        MPSiteUnmarshaller marshaller = null;
 | 
				
			||||||
        final ImmutableList.Builder<MPSite> sites = ImmutableList.builder();
 | 
					        final ImmutableList.Builder<MPSite> sites = ImmutableList.builder();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (String line : lines)
 | 
					        for (final String line : lines)
 | 
				
			||||||
            // Header delimitor.
 | 
					            // Header delimitor.
 | 
				
			||||||
            if (line.startsWith( "##" ))
 | 
					            if (line.startsWith( "##" ))
 | 
				
			||||||
                if (!headerStarted)
 | 
					                if (!headerStarted)
 | 
				
			||||||
@@ -71,7 +74,7 @@ public class MPSiteUnmarshaller {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                // Comment.
 | 
					                // Comment.
 | 
				
			||||||
            else if (line.startsWith( "#" )) {
 | 
					            else if (line.startsWith( "#" )) {
 | 
				
			||||||
                if (headerStarted && marshaller == null) {
 | 
					                if (headerStarted && (marshaller == null)) {
 | 
				
			||||||
                    // In header.
 | 
					                    // In header.
 | 
				
			||||||
                    Matcher headerMatcher = headerFormat.matcher( line );
 | 
					                    Matcher headerMatcher = headerFormat.matcher( line );
 | 
				
			||||||
                    if (headerMatcher.matches()) {
 | 
					                    if (headerMatcher.matches()) {
 | 
				
			||||||
@@ -87,7 +90,7 @@ public class MPSiteUnmarshaller {
 | 
				
			|||||||
                        else if ("Avatar".equalsIgnoreCase( name ))
 | 
					                        else if ("Avatar".equalsIgnoreCase( name ))
 | 
				
			||||||
                            avatar = ConversionUtils.toIntegerNN( value );
 | 
					                            avatar = ConversionUtils.toIntegerNN( value );
 | 
				
			||||||
                        else if ("Passwords".equalsIgnoreCase( name ))
 | 
					                        else if ("Passwords".equalsIgnoreCase( name ))
 | 
				
			||||||
                            clearContent = value.equalsIgnoreCase( "visible" );
 | 
					                            clearContent = "visible".equalsIgnoreCase( value );
 | 
				
			||||||
                        else if ("Default Type".equalsIgnoreCase( name ))
 | 
					                        else if ("Default Type".equalsIgnoreCase( name ))
 | 
				
			||||||
                            defaultType = MPSiteType.forType( ConversionUtils.toIntegerNN( value ) );
 | 
					                            defaultType = MPSiteType.forType( ConversionUtils.toIntegerNN( value ) );
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
@@ -116,7 +119,7 @@ public class MPSiteUnmarshaller {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Nullable
 | 
					    @Nullable
 | 
				
			||||||
    public MPSite unmarshallSite(@Nonnull String siteLine) {
 | 
					    public MPSite unmarshallSite(@Nonnull final String siteLine) {
 | 
				
			||||||
        Matcher siteMatcher = unmarshallFormats[importFormat].matcher( siteLine );
 | 
					        Matcher siteMatcher = unmarshallFormats[importFormat].matcher( siteLine );
 | 
				
			||||||
        if (!siteMatcher.matches())
 | 
					        if (!siteMatcher.matches())
 | 
				
			||||||
            return null;
 | 
					            return null;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,16 +39,16 @@ public class MPUser implements Comparable<MPUser> {
 | 
				
			|||||||
    public MPUser(final String fullName, @Nullable final byte[] keyID, final MasterKey.Version algorithmVersion, final int avatar,
 | 
					    public MPUser(final String fullName, @Nullable final byte[] keyID, final MasterKey.Version algorithmVersion, final int avatar,
 | 
				
			||||||
                  final MPSiteType defaultType, final ReadableInstant lastUsed) {
 | 
					                  final MPSiteType defaultType, final ReadableInstant lastUsed) {
 | 
				
			||||||
        this.fullName = fullName;
 | 
					        this.fullName = fullName;
 | 
				
			||||||
        this.keyID = keyID;
 | 
					        this.keyID = (keyID == null)? null: keyID.clone();
 | 
				
			||||||
        this.algorithmVersion = algorithmVersion;
 | 
					        this.algorithmVersion = algorithmVersion;
 | 
				
			||||||
        this.avatar = avatar;
 | 
					        this.avatar = avatar;
 | 
				
			||||||
        this.defaultType = defaultType;
 | 
					        this.defaultType = defaultType;
 | 
				
			||||||
        this.lastUsed = lastUsed;
 | 
					        this.lastUsed = lastUsed;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public Collection<MPSiteResult> findSitesByName(String query) {
 | 
					    public Collection<MPSiteResult> findSitesByName(final String query) {
 | 
				
			||||||
        ImmutableList.Builder<MPSiteResult> results = ImmutableList.builder();
 | 
					        ImmutableList.Builder<MPSiteResult> results = ImmutableList.builder();
 | 
				
			||||||
        for (MPSite site : getSites())
 | 
					        for (final MPSite site : getSites())
 | 
				
			||||||
            if (site.getSiteName().startsWith( query ))
 | 
					            if (site.getSiteName().startsWith( query ))
 | 
				
			||||||
                results.add( new MPSiteResult( site ) );
 | 
					                results.add( new MPSiteResult( site ) );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -87,10 +87,11 @@ public class MPUser implements Comparable<MPUser> {
 | 
				
			|||||||
     * @throws IncorrectMasterPasswordException If authentication fails due to the given master password not matching the user's keyID.
 | 
					     * @throws IncorrectMasterPasswordException If authentication fails due to the given master password not matching the user's keyID.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    @Nonnull
 | 
					    @Nonnull
 | 
				
			||||||
 | 
					    @SuppressWarnings("MethodCanBeVariableArityMethod")
 | 
				
			||||||
    public MasterKey authenticate(final char[] masterPassword)
 | 
					    public MasterKey authenticate(final char[] masterPassword)
 | 
				
			||||||
            throws IncorrectMasterPasswordException {
 | 
					            throws IncorrectMasterPasswordException {
 | 
				
			||||||
        MasterKey masterKey = MasterKey.create( algorithmVersion, getFullName(), masterPassword );
 | 
					        MasterKey masterKey = MasterKey.create( algorithmVersion, getFullName(), masterPassword );
 | 
				
			||||||
        if (keyID == null || keyID.length == 0)
 | 
					        if ((keyID == null) || (keyID.length == 0))
 | 
				
			||||||
            keyID = masterKey.getKeyID();
 | 
					            keyID = masterKey.getKeyID();
 | 
				
			||||||
        else if (!Arrays.equals( masterKey.getKeyID(), keyID ))
 | 
					        else if (!Arrays.equals( masterKey.getKeyID(), keyID ))
 | 
				
			||||||
            throw new IncorrectMasterPasswordException( this );
 | 
					            throw new IncorrectMasterPasswordException( this );
 | 
				
			||||||
@@ -119,7 +120,7 @@ public class MPUser implements Comparable<MPUser> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void updateLastUsed() {
 | 
					    public void updateLastUsed() {
 | 
				
			||||||
        this.lastUsed = new Instant();
 | 
					        lastUsed = new Instant();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public Iterable<MPSite> getSites() {
 | 
					    public Iterable<MPSite> getSites() {
 | 
				
			||||||
@@ -128,7 +129,7 @@ public class MPUser implements Comparable<MPUser> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public boolean equals(final Object obj) {
 | 
					    public boolean equals(final Object obj) {
 | 
				
			||||||
        return this == obj || obj instanceof MPUser && Objects.equals( fullName, ((MPUser) obj).fullName );
 | 
					        return (this == obj) || ((obj instanceof MPUser) && Objects.equals( fullName, ((MPUser) obj).fullName ));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -59,7 +59,7 @@ public class MPUserFileManager extends MPUserManager {
 | 
				
			|||||||
                try {
 | 
					                try {
 | 
				
			||||||
                    return MPSiteUnmarshaller.unmarshall( Preconditions.checkNotNull( file ) ).getUser();
 | 
					                    return MPSiteUnmarshaller.unmarshall( Preconditions.checkNotNull( file ) ).getUser();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                catch (IOException e) {
 | 
					                catch (final IOException e) {
 | 
				
			||||||
                    logger.err( e, "Couldn't read user from: %s", file );
 | 
					                    logger.err( e, "Couldn't read user from: %s", file );
 | 
				
			||||||
                    return null;
 | 
					                    return null;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@@ -99,16 +99,17 @@ public class MPUserFileManager extends MPUserManager {
 | 
				
			|||||||
                    @Override
 | 
					                    @Override
 | 
				
			||||||
                    public Writer openStream()
 | 
					                    public Writer openStream()
 | 
				
			||||||
                            throws IOException {
 | 
					                            throws IOException {
 | 
				
			||||||
                        return new FileWriter( new File( userFilesDirectory, user.getFullName() + ".mpsites" ) );
 | 
					                        File mpsitesFile = new File( userFilesDirectory, user.getFullName() + ".mpsites" );
 | 
				
			||||||
 | 
					                        return new OutputStreamWriter( new FileOutputStream( mpsitesFile ), Charsets.UTF_8 );
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }.write( MPSiteMarshaller.marshallSafe( user ).getExport() );
 | 
					                }.write( MPSiteMarshaller.marshallSafe( user ).getExport() );
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            catch (IOException e) {
 | 
					            catch (final IOException e) {
 | 
				
			||||||
                logger.err( e, "Unable to save sites for user: %s", user );
 | 
					                logger.err( e, "Unable to save sites for user: %s", user );
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Remove deleted users.
 | 
					        // Remove deleted users.
 | 
				
			||||||
        for (File userFile : listUserFiles( userFilesDirectory ))
 | 
					        for (final File userFile : listUserFiles( userFilesDirectory ))
 | 
				
			||||||
            if (getUserNamed( userFile.getName().replaceFirst( "\\.mpsites$", "" ) ) == null)
 | 
					            if (getUserNamed( userFile.getName().replaceFirst( "\\.mpsites$", "" ) ) == null)
 | 
				
			||||||
                if (!userFile.delete())
 | 
					                if (!userFile.delete())
 | 
				
			||||||
                    logger.err( "Couldn't delete file: %s", userFile );
 | 
					                    logger.err( "Couldn't delete file: %s", userFile );
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,7 +17,7 @@ public abstract class MPUserManager {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected MPUserManager(final Iterable<MPUser> users) {
 | 
					    protected MPUserManager(final Iterable<MPUser> users) {
 | 
				
			||||||
        for (MPUser user : users)
 | 
					        for (final MPUser user : users)
 | 
				
			||||||
            usersByName.put( user.getFullName(), user );
 | 
					            usersByName.put( user.getFullName(), user );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -25,7 +25,7 @@ public abstract class MPUserManager {
 | 
				
			|||||||
        return FluentIterable.from( usersByName.values() ).toSortedSet( Ordering.natural() );
 | 
					        return FluentIterable.from( usersByName.values() ).toSortedSet( Ordering.natural() );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public MPUser getUserNamed(String fullName) {
 | 
					    public MPUser getUserNamed(final String fullName) {
 | 
				
			||||||
        return usersByName.get( fullName );
 | 
					        return usersByName.get( fullName );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,7 @@ plugins {
 | 
				
			|||||||
description = 'Master Password Test Suite'
 | 
					description = 'Master Password Test Suite'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dependencies {
 | 
					dependencies {
 | 
				
			||||||
    compile     project(':masterpassword:algorithm')
 | 
					    compile     project(':masterpassword-algorithm')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    testCompile group: 'org.testng', name: 'testng', version:'6.8.5'
 | 
					    testCompile group: 'org.testng', name: 'testng', version:'6.8.5'
 | 
				
			||||||
    testCompile group: 'ch.qos.logback', name: 'logback-classic', version:'1.1.2'
 | 
					    testCompile group: 'ch.qos.logback', name: 'logback-classic', version:'1.1.2'
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,29 +20,30 @@ import org.xml.sax.ext.DefaultHandler2;
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * @author lhunath, 2015-12-22
 | 
					 * @author lhunath, 2015-12-22
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					@SuppressWarnings("HardCodedStringLiteral")
 | 
				
			||||||
public class MPTestSuite implements Callable<Boolean> {
 | 
					public class MPTestSuite implements Callable<Boolean> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @SuppressWarnings("UnusedDeclaration")
 | 
					    @SuppressWarnings("UnusedDeclaration")
 | 
				
			||||||
    private static final Logger logger                = Logger.get( MPTestSuite.class );
 | 
					    private static final Logger logger                = Logger.get( MPTestSuite.class );
 | 
				
			||||||
    private static final String DEFAULT_RESOURCE_NAME = "mpw_tests.xml";
 | 
					    private static final String DEFAULT_RESOURCE_NAME = "mpw_tests.xml";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private MPTests  tests;
 | 
					    private final MPTests  tests;
 | 
				
			||||||
    private Listener listener;
 | 
					    private       Listener listener;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public MPTestSuite()
 | 
					    public MPTestSuite()
 | 
				
			||||||
            throws UnavailableException {
 | 
					            throws UnavailableException {
 | 
				
			||||||
        this( DEFAULT_RESOURCE_NAME );
 | 
					        this( DEFAULT_RESOURCE_NAME );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public MPTestSuite(String resourceName)
 | 
					    public MPTestSuite(final String resourceName)
 | 
				
			||||||
            throws UnavailableException {
 | 
					            throws UnavailableException {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            tests = new MPTests();
 | 
					            tests = new MPTests();
 | 
				
			||||||
            tests.cases = Lists.newLinkedList();
 | 
					            tests.cases = Lists.newLinkedList();
 | 
				
			||||||
            SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
 | 
					            SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
 | 
				
			||||||
            parser.parse( Thread.currentThread().getContextClassLoader().getResourceAsStream( resourceName ), new DefaultHandler2() {
 | 
					            parser.parse( Thread.currentThread().getContextClassLoader().getResourceAsStream( resourceName ), new DefaultHandler2() {
 | 
				
			||||||
                private Deque<String> currentTags = Lists.newLinkedList();
 | 
					                private final Deque<String> currentTags = Lists.newLinkedList();
 | 
				
			||||||
                private Deque<StringBuilder> currentTexts = Lists.newLinkedList();
 | 
					                private final Deque<StringBuilder> currentTexts = Lists.newLinkedList();
 | 
				
			||||||
                private MPTests.Case currentCase;
 | 
					                private MPTests.Case currentCase;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                @Override
 | 
					                @Override
 | 
				
			||||||
@@ -103,7 +104,7 @@ public class MPTestSuite implements Callable<Boolean> {
 | 
				
			|||||||
            throw new UnavailableException( e );
 | 
					            throw new UnavailableException( e );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (MPTests.Case testCase : tests.getCases())
 | 
					        for (final MPTests.Case testCase : tests.getCases())
 | 
				
			||||||
            testCase.initializeParentHierarchy( tests );
 | 
					            testCase.initializeParentHierarchy( tests );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -115,7 +116,7 @@ public class MPTestSuite implements Callable<Boolean> {
 | 
				
			|||||||
        return tests;
 | 
					        return tests;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public boolean forEach(String testName, NNFunctionNN<MPTests.Case, Boolean> testFunction) {
 | 
					    public boolean forEach(final String testName, final NNFunctionNN<MPTests.Case, Boolean> testFunction) {
 | 
				
			||||||
        List<MPTests.Case> cases = tests.getCases();
 | 
					        List<MPTests.Case> cases = tests.getCases();
 | 
				
			||||||
        for (int c = 0; c < cases.size(); c++) {
 | 
					        for (int c = 0; c < cases.size(); c++) {
 | 
				
			||||||
            MPTests.Case testCase = cases.get( c );
 | 
					            MPTests.Case testCase = cases.get( c );
 | 
				
			||||||
@@ -164,6 +165,8 @@ public class MPTestSuite implements Callable<Boolean> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public static class UnavailableException extends Exception {
 | 
					    public static class UnavailableException extends Exception {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private static final long serialVersionUID = 1L;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public UnavailableException(final Throwable cause) {
 | 
					        public UnavailableException(final Throwable cause) {
 | 
				
			||||||
            super( cause );
 | 
					            super( cause );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@ package com.lyndir.masterpassword;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import static com.google.common.base.Preconditions.checkNotNull;
 | 
					import static com.google.common.base.Preconditions.checkNotNull;
 | 
				
			||||||
import static com.lyndir.lhunath.opal.system.util.ObjectUtils.*;
 | 
					import static com.lyndir.lhunath.opal.system.util.ObjectUtils.*;
 | 
				
			||||||
 | 
					import static com.lyndir.lhunath.opal.system.util.StringUtils.strf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.google.common.primitives.UnsignedInteger;
 | 
					import com.google.common.primitives.UnsignedInteger;
 | 
				
			||||||
import com.lyndir.lhunath.opal.system.logging.Logger;
 | 
					import com.lyndir.lhunath.opal.system.logging.Logger;
 | 
				
			||||||
@@ -28,20 +29,20 @@ public class MPTests {
 | 
				
			|||||||
        return checkNotNull( cases );
 | 
					        return checkNotNull( cases );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public Case getCase(String identifier) {
 | 
					    public Case getCase(final String identifier) {
 | 
				
			||||||
        for (Case testCase : getCases())
 | 
					        for (final Case testCase : getCases())
 | 
				
			||||||
            if (identifier.equals( testCase.getIdentifier() ))
 | 
					            if (identifier.equals( testCase.getIdentifier() ))
 | 
				
			||||||
                return testCase;
 | 
					                return testCase;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        throw new IllegalArgumentException( "No case for identifier: " + identifier );
 | 
					        throw new IllegalArgumentException( strf( "No case for identifier: %s", identifier ) );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public Case getDefaultCase() {
 | 
					    public Case getDefaultCase() {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            return getCase( ID_DEFAULT );
 | 
					            return getCase( ID_DEFAULT );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        catch (IllegalArgumentException e) {
 | 
					        catch (final IllegalArgumentException e) {
 | 
				
			||||||
            throw new IllegalStateException( "Missing default case in test suite.  Add a case with id: " + ID_DEFAULT, e );
 | 
					            throw new IllegalStateException( strf( "Missing default case in test suite.  Add a case with id: %d", ID_DEFAULT ), e );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -62,7 +63,7 @@ public class MPTests {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        private transient Case parentCase;
 | 
					        private transient Case parentCase;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public void initializeParentHierarchy(MPTests tests) {
 | 
					        public void initializeParentHierarchy(final MPTests tests) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (parent != null) {
 | 
					            if (parent != null) {
 | 
				
			||||||
                parentCase = tests.getCase( parent );
 | 
					                parentCase = tests.getCase( parent );
 | 
				
			||||||
@@ -129,14 +130,14 @@ public class MPTests {
 | 
				
			|||||||
                @Nonnull
 | 
					                @Nonnull
 | 
				
			||||||
                @Override
 | 
					                @Override
 | 
				
			||||||
                public String get() {
 | 
					                public String get() {
 | 
				
			||||||
                    return parentCase == null? "": checkNotNull( parentCase.siteContext );
 | 
					                    return (parentCase == null)? "": checkNotNull( parentCase.siteContext );
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            } );
 | 
					            } );
 | 
				
			||||||
            result = ifNotNullElse( result, new NNSupplier<String>() {
 | 
					            result = ifNotNullElse( result, new NNSupplier<String>() {
 | 
				
			||||||
                @Nonnull
 | 
					                @Nonnull
 | 
				
			||||||
                @Override
 | 
					                @Override
 | 
				
			||||||
                public String get() {
 | 
					                public String get() {
 | 
				
			||||||
                    return parentCase == null? "": checkNotNull( parentCase.result );
 | 
					                    return (parentCase == null)? "": checkNotNull( parentCase.result );
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            } );
 | 
					            } );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,6 +6,7 @@ import com.lyndir.lhunath.opal.system.CodeUtils;
 | 
				
			|||||||
import com.lyndir.lhunath.opal.system.logging.Logger;
 | 
					import com.lyndir.lhunath.opal.system.logging.Logger;
 | 
				
			||||||
import com.lyndir.lhunath.opal.system.util.NNFunctionNN;
 | 
					import com.lyndir.lhunath.opal.system.util.NNFunctionNN;
 | 
				
			||||||
import javax.annotation.Nonnull;
 | 
					import javax.annotation.Nonnull;
 | 
				
			||||||
 | 
					import org.jetbrains.annotations.NonNls;
 | 
				
			||||||
import org.testng.annotations.BeforeMethod;
 | 
					import org.testng.annotations.BeforeMethod;
 | 
				
			||||||
import org.testng.annotations.Test;
 | 
					import org.testng.annotations.Test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -15,6 +16,7 @@ public class MasterKeyTest {
 | 
				
			|||||||
    @SuppressWarnings("UnusedDeclaration")
 | 
					    @SuppressWarnings("UnusedDeclaration")
 | 
				
			||||||
    private static final Logger logger = Logger.get( MasterKeyTest.class );
 | 
					    private static final Logger logger = Logger.get( MasterKeyTest.class );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @NonNls
 | 
				
			||||||
    private MPTestSuite testSuite;
 | 
					    private MPTestSuite testSuite;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @BeforeMethod
 | 
					    @BeforeMethod
 | 
				
			||||||
@@ -86,7 +88,7 @@ public class MasterKeyTest {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            fail( "[testInvalidate] Master key should have been invalidated, but was still usable." );
 | 
					            fail( "[testInvalidate] Master key should have been invalidated, but was still usable." );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        catch (IllegalStateException ignored) {
 | 
					        catch (final IllegalStateException ignored) {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										9
									
								
								gradle/.idea/codeStyleSettings.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								gradle/.idea/codeStyleSettings.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<project version="4">
 | 
				
			||||||
 | 
					  <component name="ProjectCodeStyleSettingsManager">
 | 
				
			||||||
 | 
					    <option name="PER_PROJECT_SETTINGS">
 | 
				
			||||||
 | 
					      <value />
 | 
				
			||||||
 | 
					    </option>
 | 
				
			||||||
 | 
					    <option name="PREFERRED_PROJECT_CODE_STYLE" value="Lhunath" />
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
 | 
					</project>
 | 
				
			||||||
							
								
								
									
										6
									
								
								gradle/.idea/copyright/GPLv3.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								gradle/.idea/copyright/GPLv3.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					<component name="CopyrightManager">
 | 
				
			||||||
 | 
					  <copyright>
 | 
				
			||||||
 | 
					    <option name="myName" value="GPLv3" />
 | 
				
			||||||
 | 
					    <option name="notice" value="This file is part of &#36;project.name.

&#36;project.name 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.

&#36;project.name 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 can find a copy of the GNU General Public License in the
LICENSE file.  Alternatively, see <http://www.gnu.org/licenses/>." />
 | 
				
			||||||
 | 
					  </copyright>
 | 
				
			||||||
 | 
					</component>
 | 
				
			||||||
							
								
								
									
										8
									
								
								gradle/.idea/copyright/profiles_settings.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								gradle/.idea/copyright/profiles_settings.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					<component name="CopyrightManager">
 | 
				
			||||||
 | 
					  <settings>
 | 
				
			||||||
 | 
					    <LanguageOptions name="__TEMPLATE__">
 | 
				
			||||||
 | 
					      <option name="separateBefore" value="true" />
 | 
				
			||||||
 | 
					      <option name="separateAfter" value="true" />
 | 
				
			||||||
 | 
					    </LanguageOptions>
 | 
				
			||||||
 | 
					  </settings>
 | 
				
			||||||
 | 
					</component>
 | 
				
			||||||
							
								
								
									
										9
									
								
								gradle/.idea/inspectionProfiles/profiles_settings.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								gradle/.idea/inspectionProfiles/profiles_settings.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					<component name="InspectionProjectProfileManager">
 | 
				
			||||||
 | 
					  <settings>
 | 
				
			||||||
 | 
					    <option name="projectProfile" value="Lhunath" />
 | 
				
			||||||
 | 
					    <option name="useProjectProfile" value="false" />
 | 
				
			||||||
 | 
					    <option name="PROJECT_PROFILE" value="Lhunath" />
 | 
				
			||||||
 | 
					    <option name="USE_PROJECT_PROFILE" value="false" />
 | 
				
			||||||
 | 
					    <version value="1.0" />
 | 
				
			||||||
 | 
					  </settings>
 | 
				
			||||||
 | 
					</component>
 | 
				
			||||||
							
								
								
									
										40
									
								
								gradle/.idea/misc.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								gradle/.idea/misc.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<project version="4">
 | 
				
			||||||
 | 
					  <component name="MavenProjectsManager">
 | 
				
			||||||
 | 
					    <option name="originalFiles">
 | 
				
			||||||
 | 
					      <list>
 | 
				
			||||||
 | 
					        <option value="$PROJECT_DIR$/../../opal/pom.xml" />
 | 
				
			||||||
 | 
					      </list>
 | 
				
			||||||
 | 
					    </option>
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
 | 
					  <component name="NullableNotNullManager">
 | 
				
			||||||
 | 
					    <option name="myDefaultNullable" value="javax.annotation.Nullable" />
 | 
				
			||||||
 | 
					    <option name="myDefaultNotNull" value="javax.annotation.Nonnull" />
 | 
				
			||||||
 | 
					    <option name="myNullables">
 | 
				
			||||||
 | 
					      <value>
 | 
				
			||||||
 | 
					        <list size="4">
 | 
				
			||||||
 | 
					          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
 | 
				
			||||||
 | 
					          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
 | 
				
			||||||
 | 
					          <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
 | 
				
			||||||
 | 
					          <item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
 | 
				
			||||||
 | 
					        </list>
 | 
				
			||||||
 | 
					      </value>
 | 
				
			||||||
 | 
					    </option>
 | 
				
			||||||
 | 
					    <option name="myNotNulls">
 | 
				
			||||||
 | 
					      <value>
 | 
				
			||||||
 | 
					        <list size="4">
 | 
				
			||||||
 | 
					          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
 | 
				
			||||||
 | 
					          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
 | 
				
			||||||
 | 
					          <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
 | 
				
			||||||
 | 
					          <item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
 | 
				
			||||||
 | 
					        </list>
 | 
				
			||||||
 | 
					      </value>
 | 
				
			||||||
 | 
					    </option>
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
 | 
					  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="false" project-jdk-name="1.8" project-jdk-type="JavaSDK">
 | 
				
			||||||
 | 
					    <output url="file://$PROJECT_DIR$/classes" />
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
 | 
					  <component name="ThriftCompiler">
 | 
				
			||||||
 | 
					    <compilers />
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
 | 
					</project>
 | 
				
			||||||
							
								
								
									
										3
									
								
								gradle/.idea/scopes/masterpassword.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								gradle/.idea/scopes/masterpassword.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					<component name="DependencyValidationManager">
 | 
				
			||||||
 | 
					  <scope name="masterpassword" pattern="com.lyndir.masterpassword.*" />
 | 
				
			||||||
 | 
					</component>
 | 
				
			||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
#Mon Mar 06 18:26:17 EST 2017
 | 
					#Sun Mar 26 09:11:08 EDT 2017
 | 
				
			||||||
distributionBase=GRADLE_USER_HOME
 | 
					distributionBase=GRADLE_USER_HOME
 | 
				
			||||||
distributionPath=wrapper/dists
 | 
					distributionPath=wrapper/dists
 | 
				
			||||||
zipStoreBase=GRADLE_USER_HOME
 | 
					zipStoreBase=GRADLE_USER_HOME
 | 
				
			||||||
zipStorePath=wrapper/dists
 | 
					zipStorePath=wrapper/dists
 | 
				
			||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-bin.zip
 | 
					distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,2 +0,0 @@
 | 
				
			|||||||
sdk.dir=/usr/local/opt/android-sdk
 | 
					 | 
				
			||||||
ndk.dir=/usr/local/opt/android-ndk
 | 
					 | 
				
			||||||
@@ -1,19 +1,19 @@
 | 
				
			|||||||
rootProject.name = ':masterpassword'
 | 
					rootProject.name = 'masterpassword'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
include ':masterpassword:algorithm'
 | 
					include 'masterpassword-algorithm'
 | 
				
			||||||
project(':masterpassword:algorithm').projectDir = new File( '../core/java/algorithm' )
 | 
					project(':masterpassword-algorithm').projectDir = new File( '../core/java/algorithm' )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
include ':masterpassword:model'
 | 
					include 'masterpassword-model'
 | 
				
			||||||
project(':masterpassword:model').projectDir = new File( '../core/java/model' )
 | 
					project(':masterpassword-model').projectDir = new File( '../core/java/model' )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
include ':masterpassword:tests'
 | 
					include 'masterpassword-tests'
 | 
				
			||||||
project(':masterpassword:tests').projectDir = new File( '../core/java/tests' )
 | 
					project(':masterpassword-tests').projectDir = new File( '../core/java/tests' )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
include ':masterpassword:android'
 | 
					include 'masterpassword-cli'
 | 
				
			||||||
project(':masterpassword:android').projectDir = new File( '../platform-android' )
 | 
					project(':masterpassword-cli').projectDir = new File( '../platform-independent/cli-java' )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
include ':masterpassword:cli'
 | 
					include 'masterpassword-gui'
 | 
				
			||||||
project(':masterpassword:cli').projectDir = new File( '../platform-independent/cli-java' )
 | 
					project(':masterpassword-gui').projectDir = new File( '../platform-independent/gui-java' )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
include ':masterpassword:gui'
 | 
					include 'masterpassword-android'
 | 
				
			||||||
project(':masterpassword:gui').projectDir = new File( '../platform-independent/gui-java' )
 | 
					project(':masterpassword-android').projectDir = new File( '../platform-android' )
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,8 +36,8 @@ android {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dependencies {
 | 
					dependencies {
 | 
				
			||||||
    compile             project( ':masterpassword:algorithm' )
 | 
					    compile             project( ':masterpassword-algorithm' )
 | 
				
			||||||
    compile             project( ':masterpassword:tests' )
 | 
					    compile             project( ':masterpassword-tests' )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    compile             group: 'org.slf4j', name: 'slf4j-android', version:'1.7.13-underscore'
 | 
					    compile             group: 'org.slf4j', name: 'slf4j-android', version:'1.7.13-underscore'
 | 
				
			||||||
    compile             group: 'com.jakewharton', name: 'butterknife', version:'8.5.1'
 | 
					    compile             group: 'com.jakewharton', name: 'butterknife', version:'8.5.1'
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,6 +32,7 @@ public class EmergencyActivity extends Activity {
 | 
				
			|||||||
    private static final Logger   logger                = Logger.get( EmergencyActivity.class );
 | 
					    private static final Logger   logger                = Logger.get( EmergencyActivity.class );
 | 
				
			||||||
    private static final ClipData EMPTY_CLIP            = new ClipData( new ClipDescription( "", new String[0] ), new ClipData.Item( "" ) );
 | 
					    private static final ClipData EMPTY_CLIP            = new ClipData( new ClipDescription( "", new String[0] ), new ClipData.Item( "" ) );
 | 
				
			||||||
    private static final int      PASSWORD_NOTIFICATION = 0;
 | 
					    private static final int      PASSWORD_NOTIFICATION = 0;
 | 
				
			||||||
 | 
					    public static final int CLIPBOARD_CLEAR_DELAY = 20 /* s */ * MPConstant.MS_PER_S;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private final Preferences                      preferences  = Preferences.get( this );
 | 
					    private final Preferences                      preferences  = Preferences.get( this );
 | 
				
			||||||
    private final ListeningExecutorService         executor     = MoreExecutors.listeningDecorator( Executors.newSingleThreadExecutor() );
 | 
					    private final ListeningExecutorService         executor     = MoreExecutors.listeningDecorator( Executors.newSingleThreadExecutor() );
 | 
				
			||||||
@@ -81,14 +82,13 @@ public class EmergencyActivity extends Activity {
 | 
				
			|||||||
    private int    id_version;
 | 
					    private int    id_version;
 | 
				
			||||||
    private String sitePassword;
 | 
					    private String sitePassword;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static void start(Context context) {
 | 
					    public static void start(final Context context) {
 | 
				
			||||||
        context.startActivity( new Intent( context, EmergencyActivity.class ) );
 | 
					        context.startActivity( new Intent( context, EmergencyActivity.class ) );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void onCreate(@Nullable Bundle savedInstanceState) {
 | 
					    public void onCreate(@Nullable final Bundle savedInstanceState) {
 | 
				
			||||||
        super.onCreate( savedInstanceState );
 | 
					        super.onCreate( savedInstanceState );
 | 
				
			||||||
        Res.init( getResources() );
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        getWindow().setFlags( WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE );
 | 
					        getWindow().setFlags( WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE );
 | 
				
			||||||
        setContentView( R.layout.activity_emergency );
 | 
					        setContentView( R.layout.activity_emergency );
 | 
				
			||||||
@@ -157,13 +157,13 @@ public class EmergencyActivity extends Activity {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        } );
 | 
					        } );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fullNameField.setTypeface( Res.exo_Thin );
 | 
					        fullNameField.setTypeface( Res.get( this ).exo_Thin );
 | 
				
			||||||
        fullNameField.setPaintFlags( fullNameField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
 | 
					        fullNameField.setPaintFlags( fullNameField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
 | 
				
			||||||
        masterPasswordField.setTypeface( Res.sourceCodePro_ExtraLight );
 | 
					        masterPasswordField.setTypeface( Res.get( this ).sourceCodePro_ExtraLight );
 | 
				
			||||||
        masterPasswordField.setPaintFlags( masterPasswordField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
 | 
					        masterPasswordField.setPaintFlags( masterPasswordField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
 | 
				
			||||||
        siteNameField.setTypeface( Res.exo_Regular );
 | 
					        siteNameField.setTypeface( Res.get( this ).exo_Regular );
 | 
				
			||||||
        siteNameField.setPaintFlags( siteNameField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
 | 
					        siteNameField.setPaintFlags( siteNameField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
 | 
				
			||||||
        sitePasswordField.setTypeface( Res.sourceCodePro_Black );
 | 
					        sitePasswordField.setTypeface( Res.get( this ).sourceCodePro_Black );
 | 
				
			||||||
        sitePasswordField.setPaintFlags( sitePasswordField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
 | 
					        sitePasswordField.setPaintFlags( sitePasswordField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        rememberFullNameField.setOnCheckedChangeListener( new CompoundButton.OnCheckedChangeListener() {
 | 
					        rememberFullNameField.setOnCheckedChangeListener( new CompoundButton.OnCheckedChangeListener() {
 | 
				
			||||||
@@ -243,9 +243,11 @@ public class EmergencyActivity extends Activity {
 | 
				
			|||||||
        final String fullName = fullNameField.getText().toString();
 | 
					        final String fullName = fullNameField.getText().toString();
 | 
				
			||||||
        final char[] masterPassword = masterPasswordField.getText().toString().toCharArray();
 | 
					        final char[] masterPassword = masterPasswordField.getText().toString().toCharArray();
 | 
				
			||||||
        final MasterKey.Version version = (MasterKey.Version) siteVersionButton.getTag();
 | 
					        final MasterKey.Version version = (MasterKey.Version) siteVersionButton.getTag();
 | 
				
			||||||
        if (fullName.hashCode() == id_userName && Arrays.hashCode( masterPassword ) == id_masterPassword &&
 | 
					        if ((id_userName == fullName.hashCode())
 | 
				
			||||||
            version.ordinal() == id_version && masterKeyFuture != null && !masterKeyFuture.isCancelled())
 | 
					            && (id_masterPassword == Arrays.hashCode( masterPassword ))
 | 
				
			||||||
            return;
 | 
					            && (id_version == version.ordinal()))
 | 
				
			||||||
 | 
					            if ((masterKeyFuture != null) && !masterKeyFuture.isCancelled())
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        id_userName = fullName.hashCode();
 | 
					        id_userName = fullName.hashCode();
 | 
				
			||||||
        id_masterPassword = Arrays.hashCode( masterPassword );
 | 
					        id_masterPassword = Arrays.hashCode( masterPassword );
 | 
				
			||||||
@@ -257,7 +259,7 @@ public class EmergencyActivity extends Activity {
 | 
				
			|||||||
        if (masterKeyFuture != null)
 | 
					        if (masterKeyFuture != null)
 | 
				
			||||||
            masterKeyFuture.cancel( true );
 | 
					            masterKeyFuture.cancel( true );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (fullName.isEmpty() || masterPassword.length == 0) {
 | 
					        if (fullName.isEmpty() || (masterPassword.length == 0)) {
 | 
				
			||||||
            sitePasswordField.setText( "" );
 | 
					            sitePasswordField.setText( "" );
 | 
				
			||||||
            progressView.setVisibility( View.INVISIBLE );
 | 
					            progressView.setVisibility( View.INVISIBLE );
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
@@ -272,7 +274,7 @@ public class EmergencyActivity extends Activity {
 | 
				
			|||||||
                try {
 | 
					                try {
 | 
				
			||||||
                    return MasterKey.create( version, fullName, masterPassword );
 | 
					                    return MasterKey.create( version, fullName, masterPassword );
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                catch (Exception e) {
 | 
					                catch (final Exception e) {
 | 
				
			||||||
                    sitePasswordField.setText( "" );
 | 
					                    sitePasswordField.setText( "" );
 | 
				
			||||||
                    progressView.setVisibility( View.INVISIBLE );
 | 
					                    progressView.setVisibility( View.INVISIBLE );
 | 
				
			||||||
                    logger.err( e, "While generating master key." );
 | 
					                    logger.err( e, "While generating master key." );
 | 
				
			||||||
@@ -297,7 +299,7 @@ public class EmergencyActivity extends Activity {
 | 
				
			|||||||
        final MPSiteType type = (MPSiteType) siteTypeButton.getTag();
 | 
					        final MPSiteType type = (MPSiteType) siteTypeButton.getTag();
 | 
				
			||||||
        final UnsignedInteger counter = UnsignedInteger.valueOf( siteCounterButton.getText().toString() );
 | 
					        final UnsignedInteger counter = UnsignedInteger.valueOf( siteCounterButton.getText().toString() );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (masterKeyFuture == null || siteName.isEmpty() || type == null) {
 | 
					        if ((masterKeyFuture == null) || siteName.isEmpty() || (type == null)) {
 | 
				
			||||||
            sitePasswordField.setText( "" );
 | 
					            sitePasswordField.setText( "" );
 | 
				
			||||||
            progressView.setVisibility( View.INVISIBLE );
 | 
					            progressView.setVisibility( View.INVISIBLE );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -322,17 +324,17 @@ public class EmergencyActivity extends Activity {
 | 
				
			|||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    } );
 | 
					                    } );
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                catch (InterruptedException ignored) {
 | 
					                catch (final InterruptedException ignored) {
 | 
				
			||||||
                    sitePasswordField.setText( "" );
 | 
					                    sitePasswordField.setText( "" );
 | 
				
			||||||
                    progressView.setVisibility( View.INVISIBLE );
 | 
					                    progressView.setVisibility( View.INVISIBLE );
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                catch (ExecutionException e) {
 | 
					                catch (final ExecutionException e) {
 | 
				
			||||||
                    sitePasswordField.setText( "" );
 | 
					                    sitePasswordField.setText( "" );
 | 
				
			||||||
                    progressView.setVisibility( View.INVISIBLE );
 | 
					                    progressView.setVisibility( View.INVISIBLE );
 | 
				
			||||||
                    logger.err( e, "While generating site password." );
 | 
					                    logger.err( e, "While generating site password." );
 | 
				
			||||||
                    throw Throwables.propagate( e );
 | 
					                    throw Throwables.propagate( e );
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                catch (RuntimeException e) {
 | 
					                catch (final RuntimeException e) {
 | 
				
			||||||
                    sitePasswordField.setText( "" );
 | 
					                    sitePasswordField.setText( "" );
 | 
				
			||||||
                    progressView.setVisibility( View.INVISIBLE );
 | 
					                    progressView.setVisibility( View.INVISIBLE );
 | 
				
			||||||
                    logger.err( e, "While generating site password." );
 | 
					                    logger.err( e, "While generating site password." );
 | 
				
			||||||
@@ -342,7 +344,7 @@ public class EmergencyActivity extends Activity {
 | 
				
			|||||||
        } );
 | 
					        } );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void integrityTests(View view) {
 | 
					    public void integrityTests(final View view) {
 | 
				
			||||||
        if (masterKeyFuture != null) {
 | 
					        if (masterKeyFuture != null) {
 | 
				
			||||||
            masterKeyFuture.cancel( true );
 | 
					            masterKeyFuture.cancel( true );
 | 
				
			||||||
            masterKeyFuture = null;
 | 
					            masterKeyFuture = null;
 | 
				
			||||||
@@ -350,8 +352,8 @@ public class EmergencyActivity extends Activity {
 | 
				
			|||||||
        TestActivity.startNoSkip( this );
 | 
					        TestActivity.startNoSkip( this );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void copySitePassword(View view) {
 | 
					    public void copySitePassword(final View view) {
 | 
				
			||||||
        final String currentSitePassword = this.sitePassword;
 | 
					        final String currentSitePassword = sitePassword;
 | 
				
			||||||
        if (TextUtils.isEmpty( currentSitePassword ))
 | 
					        if (TextUtils.isEmpty( currentSitePassword ))
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -384,7 +386,7 @@ public class EmergencyActivity extends Activity {
 | 
				
			|||||||
                notificationManager.cancel( PASSWORD_NOTIFICATION );
 | 
					                notificationManager.cancel( PASSWORD_NOTIFICATION );
 | 
				
			||||||
                timer.cancel();
 | 
					                timer.cancel();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }, 20000 );
 | 
					        }, CLIPBOARD_CLEAR_DELAY );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Intent startMain = new Intent( Intent.ACTION_MAIN );
 | 
					        Intent startMain = new Intent( Intent.ACTION_MAIN );
 | 
				
			||||||
        startMain.addCategory( Intent.CATEGORY_HOME );
 | 
					        startMain.addCategory( Intent.CATEGORY_HOME );
 | 
				
			||||||
@@ -392,7 +394,7 @@ public class EmergencyActivity extends Activity {
 | 
				
			|||||||
        startActivity( startMain );
 | 
					        startActivity( startMain );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private abstract class ValueChangedListener
 | 
					    private abstract static class ValueChangedListener
 | 
				
			||||||
            implements TextWatcher, NumberPicker.OnValueChangeListener, AdapterView.OnItemSelectedListener, View.OnFocusChangeListener {
 | 
					            implements TextWatcher, NumberPicker.OnValueChangeListener, AdapterView.OnItemSelectedListener, View.OnFocusChangeListener {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        abstract void update();
 | 
					        abstract void update();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -53,7 +53,7 @@ public class MainThreadExecutor extends AbstractExecutorService {
 | 
				
			|||||||
        synchronized (commands) {
 | 
					        synchronized (commands) {
 | 
				
			||||||
            ImmutableList<Runnable> pendingTasks = ImmutableList.copyOf( commands );
 | 
					            ImmutableList<Runnable> pendingTasks = ImmutableList.copyOf( commands );
 | 
				
			||||||
            commands.clear();
 | 
					            commands.clear();
 | 
				
			||||||
            commands.notify();
 | 
					            commands.notifyAll();
 | 
				
			||||||
            return pendingTasks;
 | 
					            return pendingTasks;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,7 @@ import javax.annotation.Nullable;
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * @author lhunath, 2016-02-20
 | 
					 * @author lhunath, 2016-02-20
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public class Preferences {
 | 
					public final class Preferences {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private static final String PREF_TESTS_PASSED       = "integrityTestsPassed";
 | 
					    private static final String PREF_TESTS_PASSED       = "integrityTestsPassed";
 | 
				
			||||||
    private static final String PREF_NATIVE_KDF         = "nativeKDF";
 | 
					    private static final String PREF_NATIVE_KDF         = "nativeKDF";
 | 
				
			||||||
@@ -35,7 +35,7 @@ public class Preferences {
 | 
				
			|||||||
        return instance;
 | 
					        return instance;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private Preferences(Context context) {
 | 
					    private Preferences(final Context context) {
 | 
				
			||||||
        this.context = context;
 | 
					        this.context = context;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -47,7 +47,7 @@ public class Preferences {
 | 
				
			|||||||
        return prefs;
 | 
					        return prefs;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public boolean setNativeKDFEnabled(boolean enabled) {
 | 
					    public boolean setNativeKDFEnabled(final boolean enabled) {
 | 
				
			||||||
        if (isAllowNativeKDF() == enabled)
 | 
					        if (isAllowNativeKDF() == enabled)
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -71,7 +71,7 @@ public class Preferences {
 | 
				
			|||||||
        return prefs().getStringSet( PREF_TESTS_PASSED, ImmutableSet.<String>of() );
 | 
					        return prefs().getStringSet( PREF_TESTS_PASSED, ImmutableSet.<String>of() );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public boolean setRememberFullName(boolean enabled) {
 | 
					    public boolean setRememberFullName(final boolean enabled) {
 | 
				
			||||||
        if (isRememberFullName() == enabled)
 | 
					        if (isRememberFullName() == enabled)
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -83,7 +83,7 @@ public class Preferences {
 | 
				
			|||||||
        return prefs().getBoolean( PREF_REMEMBER_FULL_NAME, false );
 | 
					        return prefs().getBoolean( PREF_REMEMBER_FULL_NAME, false );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public boolean setForgetPassword(boolean enabled) {
 | 
					    public boolean setForgetPassword(final boolean enabled) {
 | 
				
			||||||
        if (isForgetPassword() == enabled)
 | 
					        if (isForgetPassword() == enabled)
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -95,7 +95,7 @@ public class Preferences {
 | 
				
			|||||||
        return prefs().getBoolean( PREF_FORGET_PASSWORD, false );
 | 
					        return prefs().getBoolean( PREF_FORGET_PASSWORD, false );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public boolean setMaskPassword(boolean enabled) {
 | 
					    public boolean setMaskPassword(final boolean enabled) {
 | 
				
			||||||
        if (isMaskPassword() == enabled)
 | 
					        if (isMaskPassword() == enabled)
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -107,7 +107,7 @@ public class Preferences {
 | 
				
			|||||||
        return prefs().getBoolean( PREF_MASK_PASSWORD, false );
 | 
					        return prefs().getBoolean( PREF_MASK_PASSWORD, false );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public boolean setFullName(@Nullable String value) {
 | 
					    public boolean setFullName(@Nullable final String value) {
 | 
				
			||||||
        if (getFullName().equals( value ))
 | 
					        if (getFullName().equals( value ))
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -120,8 +120,8 @@ public class Preferences {
 | 
				
			|||||||
        return prefs().getString( PREF_FULL_NAME, "" );
 | 
					        return prefs().getString( PREF_FULL_NAME, "" );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public boolean setDefaultSiteType(@Nonnull MPSiteType value) {
 | 
					    public boolean setDefaultSiteType(@Nonnull final MPSiteType value) {
 | 
				
			||||||
        if (getDefaultSiteType().equals( value ))
 | 
					        if (getDefaultSiteType() == value)
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        prefs().edit().putInt( PREF_SITE_TYPE, value.ordinal() ).apply();
 | 
					        prefs().edit().putInt( PREF_SITE_TYPE, value.ordinal() ).apply();
 | 
				
			||||||
@@ -133,8 +133,8 @@ public class Preferences {
 | 
				
			|||||||
        return MPSiteType.values()[prefs().getInt( PREF_SITE_TYPE, MPSiteType.GeneratedLong.ordinal() )];
 | 
					        return MPSiteType.values()[prefs().getInt( PREF_SITE_TYPE, MPSiteType.GeneratedLong.ordinal() )];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public boolean setDefaultVersion(@Nonnull MasterKey.Version value) {
 | 
					    public boolean setDefaultVersion(@Nonnull final MasterKey.Version value) {
 | 
				
			||||||
        if (getDefaultVersion().equals( value ))
 | 
					        if (getDefaultVersion() == value)
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        prefs().edit().putInt( PREF_ALGORITHM_VERSION, value.ordinal() ).apply();
 | 
					        prefs().edit().putInt( PREF_ALGORITHM_VERSION, value.ordinal() ).apply();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,6 @@
 | 
				
			|||||||
package com.lyndir.masterpassword;
 | 
					package com.lyndir.masterpassword;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import android.content.Context;
 | 
				
			||||||
import android.content.res.Resources;
 | 
					import android.content.res.Resources;
 | 
				
			||||||
import android.graphics.Typeface;
 | 
					import android.graphics.Typeface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -7,28 +8,32 @@ import android.graphics.Typeface;
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * @author lhunath, 2014-08-25
 | 
					 * @author lhunath, 2014-08-25
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public class Res {
 | 
					public final class Res {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static Typeface sourceCodePro_Black;
 | 
					    public final Typeface sourceCodePro_Black;
 | 
				
			||||||
    public static Typeface sourceCodePro_ExtraLight;
 | 
					    public final Typeface sourceCodePro_ExtraLight;
 | 
				
			||||||
    public static Typeface exo_Bold;
 | 
					    public final Typeface exo_Bold;
 | 
				
			||||||
    public static Typeface exo_ExtraBold;
 | 
					    public final Typeface exo_ExtraBold;
 | 
				
			||||||
    public static Typeface exo_Regular;
 | 
					    public final Typeface exo_Regular;
 | 
				
			||||||
    public static Typeface exo_Thin;
 | 
					    public final Typeface exo_Thin;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private static boolean initialized;
 | 
					    private static Res res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static void init(Resources resources) {
 | 
					    public static synchronized Res get(final Context context) {
 | 
				
			||||||
 | 
					        if (res == null)
 | 
				
			||||||
 | 
					            res = new Res( context );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (initialized)
 | 
					        return res;
 | 
				
			||||||
            return;
 | 
					    }
 | 
				
			||||||
        initialized = true;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        sourceCodePro_Black = Typeface.createFromAsset( resources.getAssets(), "SourceCodePro-Black.otf" );
 | 
					    @SuppressWarnings("HardCodedStringLiteral")
 | 
				
			||||||
        sourceCodePro_ExtraLight = Typeface.createFromAsset( resources.getAssets(), "SourceCodePro-ExtraLight.otf" );
 | 
					    private Res(final Context context) {
 | 
				
			||||||
        exo_Bold = Typeface.createFromAsset( resources.getAssets(), "Exo2.0-Bold.otf" );
 | 
					
 | 
				
			||||||
        exo_ExtraBold = Typeface.createFromAsset( resources.getAssets(), "Exo2.0-ExtraBold.otf" );
 | 
					        sourceCodePro_Black = Typeface.createFromAsset( context.getResources().getAssets(), "SourceCodePro-Black.otf" );
 | 
				
			||||||
        exo_Regular = Typeface.createFromAsset( resources.getAssets(), "Exo2.0-Regular.otf" );
 | 
					        sourceCodePro_ExtraLight = Typeface.createFromAsset( context.getResources().getAssets(), "SourceCodePro-ExtraLight.otf" );
 | 
				
			||||||
        exo_Thin = Typeface.createFromAsset( resources.getAssets(), "Exo2.0-Thin.otf" );
 | 
					        exo_Bold = Typeface.createFromAsset( context.getResources().getAssets(), "Exo2.0-Bold.otf" );
 | 
				
			||||||
 | 
					        exo_ExtraBold = Typeface.createFromAsset( context.getResources().getAssets(), "Exo2.0-ExtraBold.otf" );
 | 
				
			||||||
 | 
					        exo_Regular = Typeface.createFromAsset( context.getResources().getAssets(), "Exo2.0-Regular.otf" );
 | 
				
			||||||
 | 
					        exo_Thin = Typeface.createFromAsset( context.getResources().getAssets(), "Exo2.0-Thin.otf" );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,14 +47,13 @@ public class TestActivity extends Activity implements MPTestSuite.Listener {
 | 
				
			|||||||
    private Runnable                  action;
 | 
					    private Runnable                  action;
 | 
				
			||||||
    private ImmutableSet<String>      testNames;
 | 
					    private ImmutableSet<String>      testNames;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static void startNoSkip(Context context) {
 | 
					    public static void startNoSkip(final Context context) {
 | 
				
			||||||
        context.startActivity( new Intent( context, TestActivity.class ) );
 | 
					        context.startActivity( new Intent( context, TestActivity.class ) );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void onCreate(@Nullable Bundle savedInstanceState) {
 | 
					    public void onCreate(@Nullable final Bundle savedInstanceState) {
 | 
				
			||||||
        super.onCreate( savedInstanceState );
 | 
					        super.onCreate( savedInstanceState );
 | 
				
			||||||
        Res.init( getResources() );
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        setContentView( R.layout.activity_test );
 | 
					        setContentView( R.layout.activity_test );
 | 
				
			||||||
        ButterKnife.bind( this );
 | 
					        ButterKnife.bind( this );
 | 
				
			||||||
@@ -76,11 +75,11 @@ public class TestActivity extends Activity implements MPTestSuite.Listener {
 | 
				
			|||||||
                        @Nullable
 | 
					                        @Nullable
 | 
				
			||||||
                        @Override
 | 
					                        @Override
 | 
				
			||||||
                        public String apply(@Nullable final MPTests.Case input) {
 | 
					                        public String apply(@Nullable final MPTests.Case input) {
 | 
				
			||||||
                            return input == null? null: input.identifier;
 | 
					                            return (input == null)? null: input.identifier;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    } ).filter( Predicates.notNull() ).toSet();
 | 
					                    } ).filter( Predicates.notNull() ).toSet();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        catch (MPTestSuite.UnavailableException e) {
 | 
					        catch (final MPTestSuite.UnavailableException e) {
 | 
				
			||||||
            logger.err( e, "While loading test suite" );
 | 
					            logger.err( e, "While loading test suite" );
 | 
				
			||||||
            setStatus( R.string.tests_unavailable, R.string.tests_btn_unavailable, new Runnable() {
 | 
					            setStatus( R.string.tests_unavailable, R.string.tests_btn_unavailable, new Runnable() {
 | 
				
			||||||
                @Override
 | 
					                @Override
 | 
				
			||||||
@@ -111,7 +110,7 @@ public class TestActivity extends Activity implements MPTestSuite.Listener {
 | 
				
			|||||||
        Futures.addCallback( testFuture = backgroundExecutor.submit( testSuite ), new FutureCallback<Boolean>() {
 | 
					        Futures.addCallback( testFuture = backgroundExecutor.submit( testSuite ), new FutureCallback<Boolean>() {
 | 
				
			||||||
            @Override
 | 
					            @Override
 | 
				
			||||||
            public void onSuccess(@Nullable final Boolean result) {
 | 
					            public void onSuccess(@Nullable final Boolean result) {
 | 
				
			||||||
                if (result != null && result)
 | 
					                if ((result != null) && result)
 | 
				
			||||||
                    setStatus( R.string.tests_passed, R.string.tests_btn_passed, new Runnable() {
 | 
					                    setStatus( R.string.tests_passed, R.string.tests_btn_passed, new Runnable() {
 | 
				
			||||||
                        @Override
 | 
					                        @Override
 | 
				
			||||||
                        public void run() {
 | 
					                        public void run() {
 | 
				
			||||||
@@ -141,12 +140,12 @@ public class TestActivity extends Activity implements MPTestSuite.Listener {
 | 
				
			|||||||
        }, mainExecutor );
 | 
					        }, mainExecutor );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void onAction(View v) {
 | 
					    public void onAction(final View v) {
 | 
				
			||||||
        if (action != null)
 | 
					        if (action != null)
 | 
				
			||||||
            action.run();
 | 
					            action.run();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void setStatus(int statusId, int buttonId, @Nullable Runnable action) {
 | 
					    private void setStatus(final int statusId, final int buttonId, @Nullable final Runnable action) {
 | 
				
			||||||
        this.action = action;
 | 
					        this.action = action;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (statusId == 0)
 | 
					        if (statusId == 0)
 | 
				
			||||||
@@ -166,7 +165,7 @@ public class TestActivity extends Activity implements MPTestSuite.Listener {
 | 
				
			|||||||
        runOnUiThread( new Runnable() {
 | 
					        runOnUiThread( new Runnable() {
 | 
				
			||||||
            @Override
 | 
					            @Override
 | 
				
			||||||
            public void run() {
 | 
					            public void run() {
 | 
				
			||||||
                logView.append( strf( '\n' + messageFormat, args ) );
 | 
					                logView.append( strf( "%n" + messageFormat, args ) );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                progressView.setMax( max );
 | 
					                progressView.setMax( max );
 | 
				
			||||||
                progressView.setProgress( current );
 | 
					                progressView.setProgress( current );
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,8 +3,7 @@
 | 
				
			|||||||
            xmlns:tools="http://schemas.android.com/tools"
 | 
					            xmlns:tools="http://schemas.android.com/tools"
 | 
				
			||||||
            android:layout_width="match_parent"
 | 
					            android:layout_width="match_parent"
 | 
				
			||||||
            android:layout_height="match_parent"
 | 
					            android:layout_height="match_parent"
 | 
				
			||||||
            android:fillViewport="true"
 | 
					            android:fillViewport="true">
 | 
				
			||||||
            android:background="@drawable/background">
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <LinearLayout
 | 
					    <LinearLayout
 | 
				
			||||||
            android:layout_width="match_parent"
 | 
					            android:layout_width="match_parent"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,8 +3,7 @@
 | 
				
			|||||||
            xmlns:tools="http://schemas.android.com/tools"
 | 
					            xmlns:tools="http://schemas.android.com/tools"
 | 
				
			||||||
            android:layout_width="match_parent"
 | 
					            android:layout_width="match_parent"
 | 
				
			||||||
            android:layout_height="match_parent"
 | 
					            android:layout_height="match_parent"
 | 
				
			||||||
            android:fillViewport="true"
 | 
					            android:fillViewport="true">
 | 
				
			||||||
            android:background="@drawable/background">
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <LinearLayout
 | 
					    <LinearLayout
 | 
				
			||||||
            android:layout_width="match_parent"
 | 
					            android:layout_width="match_parent"
 | 
				
			||||||
@@ -53,6 +52,7 @@
 | 
				
			|||||||
                android:layout_marginTop="20dp"
 | 
					                android:layout_marginTop="20dp"
 | 
				
			||||||
                android:gravity="bottom"
 | 
					                android:gravity="bottom"
 | 
				
			||||||
                android:background="@android:color/transparent"
 | 
					                android:background="@android:color/transparent"
 | 
				
			||||||
 | 
					                android:textIsSelectable="true"
 | 
				
			||||||
                android:textSize="9sp"
 | 
					                android:textSize="9sp"
 | 
				
			||||||
                android:textColor="@android:color/tertiary_text_dark" />
 | 
					                android:textColor="@android:color/tertiary_text_dark" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,5 +2,6 @@
 | 
				
			|||||||
<resources>
 | 
					<resources>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <style name="MPTheme" parent="android:Theme.Holo.Dialog.MinWidth">
 | 
					    <style name="MPTheme" parent="android:Theme.Holo.Dialog.MinWidth">
 | 
				
			||||||
 | 
					        <item name="android:windowBackground">@drawable/background</item>
 | 
				
			||||||
    </style>
 | 
					    </style>
 | 
				
			||||||
</resources>
 | 
					</resources>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@ description = 'Master Password CLI'
 | 
				
			|||||||
mainClassName = 'com.lyndir.masterpassword.CLI'
 | 
					mainClassName = 'com.lyndir.masterpassword.CLI'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dependencies {
 | 
					dependencies {
 | 
				
			||||||
    compile project(':masterpassword:algorithm')
 | 
					    compile project(':masterpassword-algorithm')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    compile group: 'ch.qos.logback', name: 'logback-classic', version:'1.1.2'
 | 
					    compile group: 'ch.qos.logback', name: 'logback-classic', version:'1.1.2'
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,6 +19,7 @@ package com.lyndir.masterpassword;
 | 
				
			|||||||
import static com.lyndir.lhunath.opal.system.util.ObjectUtils.ifNotNullElse;
 | 
					import static com.lyndir.lhunath.opal.system.util.ObjectUtils.ifNotNullElse;
 | 
				
			||||||
import static com.lyndir.lhunath.opal.system.util.StringUtils.strf;
 | 
					import static com.lyndir.lhunath.opal.system.util.StringUtils.strf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.google.common.base.Charsets;
 | 
				
			||||||
import com.google.common.base.Joiner;
 | 
					import com.google.common.base.Joiner;
 | 
				
			||||||
import com.google.common.collect.Maps;
 | 
					import com.google.common.collect.Maps;
 | 
				
			||||||
import com.google.common.io.LineReader;
 | 
					import com.google.common.io.LineReader;
 | 
				
			||||||
@@ -35,9 +36,10 @@ import java.util.Map;
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 * @author mbillemo
 | 
					 * @author mbillemo
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public class CLI {
 | 
					@SuppressWarnings({ "UseOfSystemOutOrSystemErr", "HardCodedStringLiteral" })
 | 
				
			||||||
 | 
					public final class CLI {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static void main(final String[] args)
 | 
					    public static void main(final String... args)
 | 
				
			||||||
            throws IOException {
 | 
					            throws IOException {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Read information from the environment.
 | 
					        // Read information from the environment.
 | 
				
			||||||
@@ -96,68 +98,68 @@ public class CLI {
 | 
				
			|||||||
            // Help
 | 
					            // Help
 | 
				
			||||||
            else if ("-h".equals( arg ) || "--help".equals( arg )) {
 | 
					            else if ("-h".equals( arg ) || "--help".equals( arg )) {
 | 
				
			||||||
                System.out.println();
 | 
					                System.out.println();
 | 
				
			||||||
                System.out.format( "Usage: mpw [-u name] [-t type] [-c counter] site\n\n" );
 | 
					                System.out.format( "Usage: mpw [-u name] [-t type] [-c counter] site%n%n" );
 | 
				
			||||||
                System.out.format( "    -u name      Specify the full name of the user.\n" );
 | 
					                System.out.format( "    -u name      Specify the full name of the user.%n" );
 | 
				
			||||||
                System.out.format( "                 Defaults to %s in env.\n\n", MPConstant.env_userName );
 | 
					                System.out.format( "                 Defaults to %s in env.%n%n", MPConstant.env_userName );
 | 
				
			||||||
                System.out.format( "    -t type      Specify the password's template.\n" );
 | 
					                System.out.format( "    -t type      Specify the password's template.%n" );
 | 
				
			||||||
                System.out.format( "                 Defaults to %s in env or 'long' for password, 'name' for login.\n", MPConstant.env_siteType );
 | 
					                System.out.format( "                 Defaults to %s in env or 'long' for password, 'name' for login.%n", MPConstant.env_siteType );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                int optionsLength = 0;
 | 
					                int optionsLength = 0;
 | 
				
			||||||
                Map<String, MPSiteType> typeMap = Maps.newLinkedHashMap();
 | 
					                Map<String, MPSiteType> typeMap = Maps.newLinkedHashMap();
 | 
				
			||||||
                for (MPSiteType elementType : MPSiteType.values()) {
 | 
					                for (final MPSiteType elementType : MPSiteType.values()) {
 | 
				
			||||||
                    String options = Joiner.on( ", " ).join( elementType.getOptions() );
 | 
					                    String options = Joiner.on( ", " ).join( elementType.getOptions() );
 | 
				
			||||||
                    typeMap.put( options, elementType );
 | 
					                    typeMap.put( options, elementType );
 | 
				
			||||||
                    optionsLength = Math.max( optionsLength, options.length() );
 | 
					                    optionsLength = Math.max( optionsLength, options.length() );
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                for (Map.Entry<String, MPSiteType> entry : typeMap.entrySet()) {
 | 
					                for (final Map.Entry<String, MPSiteType> entry : typeMap.entrySet()) {
 | 
				
			||||||
                    String infoString = strf( "                  -v %" + optionsLength + "s | ", entry.getKey() );
 | 
					                    String infoString = strf( "                  -v %" + optionsLength + "s | ", entry.getKey() );
 | 
				
			||||||
                    String infoNewline = "\n" + StringUtils.repeat( " ", infoString.length() - 3 ) + " | ";
 | 
					                    String infoNewline = strf( "%n%s | ", StringUtils.repeat( " ", infoString.length() - 3 ) );
 | 
				
			||||||
                    infoString += entry.getValue().getDescription().replaceAll( "\n", infoNewline );
 | 
					                    infoString += entry.getValue().getDescription().replaceAll( strf( "%n" ), infoNewline );
 | 
				
			||||||
                    System.out.println( infoString );
 | 
					                    System.out.println( infoString );
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                System.out.println();
 | 
					                System.out.println();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                System.out.format( "    -c counter   The value of the counter.\n" );
 | 
					                System.out.format( "    -c counter   The value of the counter.%n" );
 | 
				
			||||||
                System.out.format( "                 Defaults to %s in env or '1'.\n\n", MPConstant.env_siteCounter );
 | 
					                System.out.format( "                 Defaults to %s in env or '1'.%n%n", MPConstant.env_siteCounter );
 | 
				
			||||||
                System.out.format( "    -v variant   The kind of content to generate.\n" );
 | 
					                System.out.format( "    -v variant   The kind of content to generate.%n" );
 | 
				
			||||||
                System.out.format( "                 Defaults to 'password'.\n" );
 | 
					                System.out.format( "                 Defaults to 'password'.%n" );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                optionsLength = 0;
 | 
					                optionsLength = 0;
 | 
				
			||||||
                Map<String, MPSiteVariant> variantMap = Maps.newLinkedHashMap();
 | 
					                Map<String, MPSiteVariant> variantMap = Maps.newLinkedHashMap();
 | 
				
			||||||
                for (MPSiteVariant elementVariant : MPSiteVariant.values()) {
 | 
					                for (final MPSiteVariant elementVariant : MPSiteVariant.values()) {
 | 
				
			||||||
                    String options = Joiner.on( ", " ).join( elementVariant.getOptions() );
 | 
					                    String options = Joiner.on( ", " ).join( elementVariant.getOptions() );
 | 
				
			||||||
                    variantMap.put( options, elementVariant );
 | 
					                    variantMap.put( options, elementVariant );
 | 
				
			||||||
                    optionsLength = Math.max( optionsLength, options.length() );
 | 
					                    optionsLength = Math.max( optionsLength, options.length() );
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                for (Map.Entry<String, MPSiteVariant> entry : variantMap.entrySet()) {
 | 
					                for (final Map.Entry<String, MPSiteVariant> entry : variantMap.entrySet()) {
 | 
				
			||||||
                    String infoString = strf( "                  -v %" + optionsLength + "s | ", entry.getKey() );
 | 
					                    String infoString = strf( "                  -v %" + optionsLength + "s | ", entry.getKey() );
 | 
				
			||||||
                    String infoNewline = "\n" + StringUtils.repeat( " ", infoString.length() - 3 ) + " | ";
 | 
					                    String infoNewline = strf( "%n%s | ", StringUtils.repeat( " ", infoString.length() - 3 ) );
 | 
				
			||||||
                    infoString += entry.getValue().getDescription().replaceAll( "\n", infoNewline );
 | 
					                    infoString += entry.getValue().getDescription().replaceAll( strf( "%n" ), infoNewline );
 | 
				
			||||||
                    System.out.println( infoString );
 | 
					                    System.out.println( infoString );
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                System.out.println();
 | 
					                System.out.println();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                System.out.format( "    -C context   A variant-specific context.\n" );
 | 
					                System.out.format( "    -C context   A variant-specific context.%n" );
 | 
				
			||||||
                System.out.format( "                 Defaults to empty.\n" );
 | 
					                System.out.format( "                 Defaults to empty.%n" );
 | 
				
			||||||
                for (Map.Entry<String, MPSiteVariant> entry : variantMap.entrySet()) {
 | 
					                for (final Map.Entry<String, MPSiteVariant> entry : variantMap.entrySet()) {
 | 
				
			||||||
                    String infoString = strf( "                  -v %" + optionsLength + "s | ", entry.getKey() );
 | 
					                    String infoString = strf( "                  -v %" + optionsLength + "s | ", entry.getKey() );
 | 
				
			||||||
                    String infoNewline = "\n" + StringUtils.repeat( " ", infoString.length() - 3 ) + " | ";
 | 
					                    String infoNewline = strf( "%n%s | ", StringUtils.repeat( " ", infoString.length() - 3 ) );
 | 
				
			||||||
                    infoString += entry.getValue().getContextDescription().replaceAll( "\n", infoNewline );
 | 
					                    infoString += entry.getValue().getContextDescription().replaceAll( strf( "%n" ), infoNewline );
 | 
				
			||||||
                    System.out.println( infoString );
 | 
					                    System.out.println( infoString );
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                System.out.println();
 | 
					                System.out.println();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                System.out.format( "    ENVIRONMENT\n\n" );
 | 
					                System.out.format( "    ENVIRONMENT%n%n" );
 | 
				
			||||||
                System.out.format( "        MP_USERNAME    | The full name of the user.\n" );
 | 
					                System.out.format( "        MP_USERNAME    | The full name of the user.%n" );
 | 
				
			||||||
                System.out.format( "        MP_SITETYPE    | The default password template.\n" );
 | 
					                System.out.format( "        MP_SITETYPE    | The default password template.%n" );
 | 
				
			||||||
                System.out.format( "        MP_SITECOUNTER | The default counter value.\n\n" );
 | 
					                System.out.format( "        MP_SITECOUNTER | The default counter value.%n%n" );
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            } else
 | 
					            } else
 | 
				
			||||||
                siteName = arg;
 | 
					                siteName = arg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Read missing information from the console.
 | 
					        // Read missing information from the console.
 | 
				
			||||||
        Console console = System.console();
 | 
					        Console console = System.console();
 | 
				
			||||||
        try (InputStreamReader inReader = new InputStreamReader( System.in )) {
 | 
					        try (InputStreamReader inReader = new InputStreamReader( System.in, Charsets.UTF_8 )) {
 | 
				
			||||||
            LineReader lineReader = new LineReader( inReader );
 | 
					            LineReader lineReader = new LineReader( inReader );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (siteName == null) {
 | 
					            if (siteName == null) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@ description = 'Master Password GUI'
 | 
				
			|||||||
mainClassName = 'com.lyndir.masterpassword.gui.GUI'
 | 
					mainClassName = 'com.lyndir.masterpassword.gui.GUI'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dependencies {
 | 
					dependencies {
 | 
				
			||||||
    compile project(':masterpassword:model')
 | 
					    compile project(':masterpassword-model')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    compile group: 'ch.qos.logback', name: 'logback-classic', version:'1.1.2'
 | 
					    compile group: 'ch.qos.logback', name: 'logback-classic', version:'1.1.2'
 | 
				
			||||||
    compile group: 'com.yuvimasory', name: 'orange-extensions', version:'1.3.0'
 | 
					    compile group: 'com.yuvimasory', name: 'orange-extensions', version:'1.3.0'
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -46,8 +46,7 @@ public class GUI implements UnlockFrame.SignInCallback {
 | 
				
			|||||||
    private final UnlockFrame unlockFrame = new UnlockFrame( this );
 | 
					    private final UnlockFrame unlockFrame = new UnlockFrame( this );
 | 
				
			||||||
    private PasswordFrame passwordFrame;
 | 
					    private PasswordFrame passwordFrame;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static void main(final String[] args)
 | 
					    public static void main(final String... args) {
 | 
				
			||||||
            throws IOException {
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (Config.get().checkForUpdates())
 | 
					        if (Config.get().checkForUpdates())
 | 
				
			||||||
            checkUpdate();
 | 
					            checkUpdate();
 | 
				
			||||||
@@ -76,7 +75,7 @@ public class GUI implements UnlockFrame.SignInCallback {
 | 
				
			|||||||
                String upstreamRevision = upstream.readFirstLine();
 | 
					                String upstreamRevision = upstream.readFirstLine();
 | 
				
			||||||
                logger.inf( "Local Revision:    <%s>", manifestRevision );
 | 
					                logger.inf( "Local Revision:    <%s>", manifestRevision );
 | 
				
			||||||
                logger.inf( "Upstream Revision: <%s>", upstreamRevision );
 | 
					                logger.inf( "Upstream Revision: <%s>", upstreamRevision );
 | 
				
			||||||
                if (manifestRevision != null && !manifestRevision.equalsIgnoreCase( upstreamRevision )) {
 | 
					                if ((manifestRevision != null) && !manifestRevision.equalsIgnoreCase( upstreamRevision )) {
 | 
				
			||||||
                    logger.wrn( "You are not running the current official version.  Please update from:\n"
 | 
					                    logger.wrn( "You are not running the current official version.  Please update from:\n"
 | 
				
			||||||
                                + "http://masterpasswordapp.com/masterpassword-gui.jar" );
 | 
					                                + "http://masterpasswordapp.com/masterpassword-gui.jar" );
 | 
				
			||||||
                    JOptionPane.showMessageDialog( null, "A new version of Master Password is available.\n"
 | 
					                    JOptionPane.showMessageDialog( null, "A new version of Master Password is available.\n"
 | 
				
			||||||
@@ -85,7 +84,7 @@ public class GUI implements UnlockFrame.SignInCallback {
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        catch (IOException e) {
 | 
					        catch (final IOException e) {
 | 
				
			||||||
            logger.wrn( e, "Couldn't check for version update." );
 | 
					            logger.wrn( e, "Couldn't check for version update." );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,14 +23,17 @@ import java.util.concurrent.*;
 | 
				
			|||||||
import java.util.regex.Matcher;
 | 
					import java.util.regex.Matcher;
 | 
				
			||||||
import java.util.regex.Pattern;
 | 
					import java.util.regex.Pattern;
 | 
				
			||||||
import javax.swing.*;
 | 
					import javax.swing.*;
 | 
				
			||||||
 | 
					import org.jetbrains.annotations.NonNls;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @author lhunath, 2014-06-11
 | 
					 * @author lhunath, 2014-06-11
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					@SuppressWarnings("HardcodedFileSeparator")
 | 
				
			||||||
public abstract class Res {
 | 
					public abstract class Res {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private static final WeakHashMap<Window, ScheduledExecutorService> executorByWindow = new WeakHashMap<>();
 | 
					    private static final int AVATAR_COUNT = 19;
 | 
				
			||||||
 | 
					    private static final Map<Window, ScheduledExecutorService> executorByWindow = new WeakHashMap<>();
 | 
				
			||||||
    private static final Logger                                        logger           = Logger.get( Res.class );
 | 
					    private static final Logger                                        logger           = Logger.get( Res.class );
 | 
				
			||||||
    private static final Colors                                        colors           = new Colors();
 | 
					    private static final Colors                                        colors           = new Colors();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -45,7 +48,7 @@ public abstract class Res {
 | 
				
			|||||||
                try {
 | 
					                try {
 | 
				
			||||||
                    job.run();
 | 
					                    job.run();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                catch (Throwable t) {
 | 
					                catch (final Throwable t) {
 | 
				
			||||||
                    logger.err( t, "Unexpected: %s", t.getLocalizedMessage() );
 | 
					                    logger.err( t, "Unexpected: %s", t.getLocalizedMessage() );
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -65,9 +68,9 @@ public abstract class Res {
 | 
				
			|||||||
                try {
 | 
					                try {
 | 
				
			||||||
                    return job.call();
 | 
					                    return job.call();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                catch (Throwable t) {
 | 
					                catch (final Throwable t) {
 | 
				
			||||||
                    logger.err( t, "Unexpected: %s", t.getLocalizedMessage() );
 | 
					                    logger.err( t, "Unexpected: %s", t.getLocalizedMessage() );
 | 
				
			||||||
                    throw t;
 | 
					                    throw Throwables.propagate( t );
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }, delay, timeUnit ), executor );
 | 
					        }, delay, timeUnit ), executor );
 | 
				
			||||||
@@ -109,7 +112,7 @@ public abstract class Res {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static int avatars() {
 | 
					    public static int avatars() {
 | 
				
			||||||
        return 19;
 | 
					        return AVATAR_COUNT;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static Font emoticonsFont() {
 | 
					    public static Font emoticonsFont() {
 | 
				
			||||||
@@ -180,10 +183,10 @@ public abstract class Res {
 | 
				
			|||||||
        return font( "fonts/Arimo-Regular.ttf" );
 | 
					        return font( "fonts/Arimo-Regular.ttf" );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private static Font font(String fontResourceName) {
 | 
					    private static Font font(@NonNls final String fontResourceName) {
 | 
				
			||||||
        Map<String, SoftReference<Font>> fontsByResourceName = Maps.newHashMap();
 | 
					        Map<String, SoftReference<Font>> fontsByResourceName = Maps.newHashMap();
 | 
				
			||||||
        SoftReference<Font> fontRef = fontsByResourceName.get( fontResourceName );
 | 
					        SoftReference<Font> fontRef = fontsByResourceName.get( fontResourceName );
 | 
				
			||||||
        Font font = fontRef == null? null: fontRef.get();
 | 
					        Font font = (fontRef == null)? null: fontRef.get();
 | 
				
			||||||
        if (font == null)
 | 
					        if (font == null)
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                fontsByResourceName.put( fontResourceName, new SoftReference<>(
 | 
					                fontsByResourceName.put( fontResourceName, new SoftReference<>(
 | 
				
			||||||
@@ -203,17 +206,15 @@ public abstract class Res {
 | 
				
			|||||||
    private static final class RetinaIcon extends ImageIcon {
 | 
					    private static final class RetinaIcon extends ImageIcon {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private static final Pattern scalePattern = Pattern.compile( ".*@(\\d+)x.[^.]+$" );
 | 
					        private static final Pattern scalePattern = Pattern.compile( ".*@(\\d+)x.[^.]+$" );
 | 
				
			||||||
 | 
					        private static final long serialVersionUID = 1L;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private final float scale;
 | 
					        private final float scale;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public RetinaIcon(final URL url) {
 | 
					        private RetinaIcon(final URL url) {
 | 
				
			||||||
            super( url );
 | 
					            super( url );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Matcher scaleMatcher = scalePattern.matcher( url.getPath() );
 | 
					            Matcher scaleMatcher = scalePattern.matcher( url.getPath() );
 | 
				
			||||||
            if (scaleMatcher.matches())
 | 
					            scale = scaleMatcher.matches()? Float.parseFloat( scaleMatcher.group( 1 ) ): 1;
 | 
				
			||||||
                scale = Float.parseFloat( scaleMatcher.group( 1 ) );
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
                scale = 1;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //private static URL retinaURL(final URL url) {
 | 
					        //private static URL retinaURL(final URL url) {
 | 
				
			||||||
@@ -242,13 +243,14 @@ public abstract class Res {
 | 
				
			|||||||
            return (int) (super.getIconHeight() / scale);
 | 
					            return (int) (super.getIconHeight() / scale);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public synchronized void paintIcon(Component c, Graphics g, int x, int y) {
 | 
					        @Override
 | 
				
			||||||
 | 
					        public synchronized void paintIcon(final Component c, final Graphics g, final int x, final int y) {
 | 
				
			||||||
            ImageObserver observer = ifNotNullElse( getImageObserver(), c );
 | 
					            ImageObserver observer = ifNotNullElse( getImageObserver(), c );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Image image = getImage();
 | 
					            Image image = getImage();
 | 
				
			||||||
            int width = image.getWidth( observer );
 | 
					            int width = image.getWidth( observer );
 | 
				
			||||||
            int height = image.getHeight( observer );
 | 
					            int height = image.getHeight( observer );
 | 
				
			||||||
            final Graphics2D g2d = (Graphics2D) g.create( x, y, width, height );
 | 
					            Graphics2D g2d = (Graphics2D) g.create( x, y, width, height );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            g2d.scale( 1 / scale, 1 / scale );
 | 
					            g2d.scale( 1 / scale, 1 / scale );
 | 
				
			||||||
            g2d.drawImage( image, 0, 0, observer );
 | 
					            g2d.drawImage( image, 0, 0, observer );
 | 
				
			||||||
@@ -276,7 +278,7 @@ public abstract class Res {
 | 
				
			|||||||
            return controlBorder;
 | 
					            return controlBorder;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public Color fromIdenticonColor(MPIdenticon.Color identiconColor, BackgroundMode backgroundMode) {
 | 
					        public Color fromIdenticonColor(final MPIdenticon.Color identiconColor, final BackgroundMode backgroundMode) {
 | 
				
			||||||
            switch (identiconColor) {
 | 
					            switch (identiconColor) {
 | 
				
			||||||
                case RED:
 | 
					                case RED:
 | 
				
			||||||
                    switch (backgroundMode) {
 | 
					                    switch (backgroundMode) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,18 +23,22 @@ public class IncognitoSite extends Site {
 | 
				
			|||||||
        this.algorithmVersion = algorithmVersion;
 | 
					        this.algorithmVersion = algorithmVersion;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
    public String getSiteName() {
 | 
					    public String getSiteName() {
 | 
				
			||||||
        return siteName;
 | 
					        return siteName;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
    public void setSiteName(final String siteName) {
 | 
					    public void setSiteName(final String siteName) {
 | 
				
			||||||
        this.siteName = siteName;
 | 
					        this.siteName = siteName;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
    public MPSiteType getSiteType() {
 | 
					    public MPSiteType getSiteType() {
 | 
				
			||||||
        return siteType;
 | 
					        return siteType;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
    public void setSiteType(final MPSiteType siteType) {
 | 
					    public void setSiteType(final MPSiteType siteType) {
 | 
				
			||||||
        this.siteType = siteType;
 | 
					        this.siteType = siteType;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -49,10 +53,12 @@ public class IncognitoSite extends Site {
 | 
				
			|||||||
        this.algorithmVersion = algorithmVersion;
 | 
					        this.algorithmVersion = algorithmVersion;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
    public UnsignedInteger getSiteCounter() {
 | 
					    public UnsignedInteger getSiteCounter() {
 | 
				
			||||||
        return siteCounter;
 | 
					        return siteCounter;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
    public void setSiteCounter(final UnsignedInteger siteCounter) {
 | 
					    public void setSiteCounter(final UnsignedInteger siteCounter) {
 | 
				
			||||||
        this.siteCounter = siteCounter;
 | 
					        this.siteCounter = siteCounter;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,12 +11,14 @@ import javax.annotation.Nullable;
 | 
				
			|||||||
public class IncognitoUser extends User {
 | 
					public class IncognitoUser extends User {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private final String fullName;
 | 
					    private final String fullName;
 | 
				
			||||||
 | 
					    @Nullable
 | 
				
			||||||
    private       char[] masterPassword;
 | 
					    private       char[] masterPassword;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public IncognitoUser(final String fullName) {
 | 
					    public IncognitoUser(final String fullName) {
 | 
				
			||||||
        this.fullName = fullName;
 | 
					        this.fullName = fullName;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
    public String getFullName() {
 | 
					    public String getFullName() {
 | 
				
			||||||
        return fullName;
 | 
					        return fullName;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -30,7 +32,7 @@ public class IncognitoUser extends User {
 | 
				
			|||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void authenticate(final char[] masterPassword)
 | 
					    public void authenticate(final char[] masterPassword)
 | 
				
			||||||
            throws IncorrectMasterPasswordException {
 | 
					            throws IncorrectMasterPasswordException {
 | 
				
			||||||
        this.masterPassword = masterPassword;
 | 
					        this.masterPassword = masterPassword.clone();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
@@ -43,6 +45,6 @@ public class IncognitoUser extends User {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void deleteSite(Site site) {
 | 
					    public void deleteSite(final Site site) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,13 +14,14 @@ public class ModelSite extends Site {
 | 
				
			|||||||
    private final MPSite model;
 | 
					    private final MPSite model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public ModelSite(final MPSiteResult result) {
 | 
					    public ModelSite(final MPSiteResult result) {
 | 
				
			||||||
        this.model = result.getSite();
 | 
					        model = result.getSite();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public MPSite getModel() {
 | 
					    public MPSite getModel() {
 | 
				
			||||||
        return model;
 | 
					        return model;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
    public String getSiteName() {
 | 
					    public String getSiteName() {
 | 
				
			||||||
        return model.getSiteName();
 | 
					        return model.getSiteName();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -31,6 +32,7 @@ public class ModelSite extends Site {
 | 
				
			|||||||
        MPUserFileManager.get().save();
 | 
					        MPUserFileManager.get().save();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
    public MPSiteType getSiteType() {
 | 
					    public MPSiteType getSiteType() {
 | 
				
			||||||
        return model.getSiteType();
 | 
					        return model.getSiteType();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -56,6 +58,7 @@ public class ModelSite extends Site {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
    public UnsignedInteger getSiteCounter() {
 | 
					    public UnsignedInteger getSiteCounter() {
 | 
				
			||||||
        return model.getSiteCounter();
 | 
					        return model.getSiteCounter();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,7 +19,7 @@ public class ModelUser extends User {
 | 
				
			|||||||
    @Nullable
 | 
					    @Nullable
 | 
				
			||||||
    private char[] masterPassword;
 | 
					    private char[] masterPassword;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public ModelUser(MPUser model) {
 | 
					    public ModelUser(final MPUser model) {
 | 
				
			||||||
        this.model = model;
 | 
					        this.model = model;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -48,10 +48,11 @@ public class ModelUser extends User {
 | 
				
			|||||||
        MPUserFileManager.get().save();
 | 
					        MPUserFileManager.get().save();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
    public void authenticate(final char[] masterPassword)
 | 
					    public void authenticate(final char[] masterPassword)
 | 
				
			||||||
            throws IncorrectMasterPasswordException {
 | 
					            throws IncorrectMasterPasswordException {
 | 
				
			||||||
        putKey( model.authenticate( masterPassword ) );
 | 
					        putKey( model.authenticate( masterPassword ) );
 | 
				
			||||||
        this.masterPassword = masterPassword;
 | 
					        this.masterPassword = masterPassword.clone();
 | 
				
			||||||
        MPUserFileManager.get().save();
 | 
					        MPUserFileManager.get().save();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -66,8 +67,8 @@ public class ModelUser extends User {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public Iterable<Site> findSitesByName(final String query) {
 | 
					    public Iterable<Site> findSitesByName(final String siteName) {
 | 
				
			||||||
        return FluentIterable.from( model.findSitesByName( query ) ).transform( new Function<MPSiteResult, Site>() {
 | 
					        return FluentIterable.from( model.findSitesByName( siteName ) ).transform( new Function<MPSiteResult, Site>() {
 | 
				
			||||||
            @Nullable
 | 
					            @Nullable
 | 
				
			||||||
            @Override
 | 
					            @Override
 | 
				
			||||||
            public Site apply(@Nullable final MPSiteResult site) {
 | 
					            public Site apply(@Nullable final MPSiteResult site) {
 | 
				
			||||||
@@ -84,7 +85,7 @@ public class ModelUser extends User {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void deleteSite(Site site) {
 | 
					    public void deleteSite(final Site site) {
 | 
				
			||||||
        if (site instanceof ModelSite) {
 | 
					        if (site instanceof ModelSite) {
 | 
				
			||||||
            model.deleteSite(((ModelSite) site).getModel());
 | 
					            model.deleteSite(((ModelSite) site).getModel());
 | 
				
			||||||
            MPUserFileManager.get().save();
 | 
					            MPUserFileManager.get().save();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,19 +14,19 @@ public abstract class Site {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public abstract String getSiteName();
 | 
					    public abstract String getSiteName();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract void setSiteName(final String siteName);
 | 
					    public abstract void setSiteName(String siteName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract MPSiteType getSiteType();
 | 
					    public abstract MPSiteType getSiteType();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract void setSiteType(final MPSiteType siteType);
 | 
					    public abstract void setSiteType(MPSiteType siteType);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract MasterKey.Version getAlgorithmVersion();
 | 
					    public abstract MasterKey.Version getAlgorithmVersion();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract void setAlgorithmVersion(final MasterKey.Version algorithmVersion);
 | 
					    public abstract void setAlgorithmVersion(MasterKey.Version algorithmVersion);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract UnsignedInteger getSiteCounter();
 | 
					    public abstract UnsignedInteger getSiteCounter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract void setSiteCounter(final UnsignedInteger siteCounter);
 | 
					    public abstract void setSiteCounter(UnsignedInteger siteCounter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public String toString() {
 | 
					    public String toString() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,8 +4,7 @@ import com.google.common.base.Preconditions;
 | 
				
			|||||||
import com.google.common.collect.Maps;
 | 
					import com.google.common.collect.Maps;
 | 
				
			||||||
import com.lyndir.masterpassword.MasterKey;
 | 
					import com.lyndir.masterpassword.MasterKey;
 | 
				
			||||||
import com.lyndir.masterpassword.model.IncorrectMasterPasswordException;
 | 
					import com.lyndir.masterpassword.model.IncorrectMasterPasswordException;
 | 
				
			||||||
import java.util.EnumMap;
 | 
					import java.util.*;
 | 
				
			||||||
import java.util.Objects;
 | 
					 | 
				
			||||||
import javax.annotation.Nonnull;
 | 
					import javax.annotation.Nonnull;
 | 
				
			||||||
import javax.annotation.Nullable;
 | 
					import javax.annotation.Nullable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -16,14 +15,15 @@ import javax.annotation.Nullable;
 | 
				
			|||||||
public abstract class User {
 | 
					public abstract class User {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Nonnull
 | 
					    @Nonnull
 | 
				
			||||||
    private final EnumMap<MasterKey.Version, MasterKey> keyByVersion = Maps.newEnumMap( MasterKey.Version.class  );
 | 
					    private final Map<MasterKey.Version, MasterKey> keyByVersion = Maps.newEnumMap( MasterKey.Version.class  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract String getFullName();
 | 
					    public abstract String getFullName();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Nullable
 | 
					    @Nullable
 | 
				
			||||||
    protected abstract char[] getMasterPassword();
 | 
					    protected abstract char[] getMasterPassword();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract void authenticate(final char[] masterPassword)
 | 
					    @SuppressWarnings("MethodCanBeVariableArityMethod")
 | 
				
			||||||
 | 
					    public abstract void authenticate(char[] masterPassword)
 | 
				
			||||||
            throws IncorrectMasterPasswordException;
 | 
					            throws IncorrectMasterPasswordException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public int getAvatar() {
 | 
					    public int getAvatar() {
 | 
				
			||||||
@@ -35,7 +35,7 @@ public abstract class User {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Nonnull
 | 
					    @Nonnull
 | 
				
			||||||
    public MasterKey getKey(MasterKey.Version algorithmVersion) {
 | 
					    public MasterKey getKey(final MasterKey.Version algorithmVersion) {
 | 
				
			||||||
        char[] masterPassword = Preconditions.checkNotNull( getMasterPassword(), "User is not authenticated: " + getFullName() );
 | 
					        char[] masterPassword = Preconditions.checkNotNull( getMasterPassword(), "User is not authenticated: " + getFullName() );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        MasterKey key = keyByVersion.get( algorithmVersion );
 | 
					        MasterKey key = keyByVersion.get( algorithmVersion );
 | 
				
			||||||
@@ -47,26 +47,26 @@ public abstract class User {
 | 
				
			|||||||
        return key;
 | 
					        return key;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected void putKey(MasterKey masterKey) {
 | 
					    protected void putKey(final MasterKey masterKey) {
 | 
				
			||||||
        MasterKey oldKey = keyByVersion.put( masterKey.getAlgorithmVersion(), masterKey );
 | 
					        MasterKey oldKey = keyByVersion.put( masterKey.getAlgorithmVersion(), masterKey );
 | 
				
			||||||
        if (oldKey != null)
 | 
					        if (oldKey != null)
 | 
				
			||||||
            oldKey.invalidate();
 | 
					            oldKey.invalidate();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void reset() {
 | 
					    public void reset() {
 | 
				
			||||||
        for (MasterKey key : keyByVersion.values())
 | 
					        for (final MasterKey key : keyByVersion.values())
 | 
				
			||||||
            key.invalidate();
 | 
					            key.invalidate();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract Iterable<Site> findSitesByName(final String siteName);
 | 
					    public abstract Iterable<Site> findSitesByName(String siteName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract void addSite(final Site site);
 | 
					    public abstract void addSite(Site site);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract void deleteSite(final Site site);
 | 
					    public abstract void deleteSite(Site site);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public boolean equals(final Object obj) {
 | 
					    public boolean equals(final Object obj) {
 | 
				
			||||||
        return this == obj || obj instanceof User && Objects.equals( getFullName(), ((User) obj).getFullName() );
 | 
					        return (this == obj) || ((obj instanceof User) && Objects.equals( getFullName(), ((User) obj).getFullName() ));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @author lhunath, 15-02-04
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@ParametersAreNonnullByDefault
 | 
				
			||||||
 | 
					package com.lyndir.masterpassword.gui.model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import javax.annotation.ParametersAreNonnullByDefault;
 | 
				
			||||||
@@ -19,17 +19,17 @@ public class AppleGUI extends GUI {
 | 
				
			|||||||
        application.addAppEventListener( new AppForegroundListener() {
 | 
					        application.addAppEventListener( new AppForegroundListener() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            @Override
 | 
					            @Override
 | 
				
			||||||
            public void appMovedToBackground(AppEvent.AppForegroundEvent arg0) {
 | 
					            public void appMovedToBackground(final AppEvent.AppForegroundEvent arg0) {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            @Override
 | 
					            @Override
 | 
				
			||||||
            public void appRaisedToForeground(AppEvent.AppForegroundEvent arg0) {
 | 
					            public void appRaisedToForeground(final AppEvent.AppForegroundEvent arg0) {
 | 
				
			||||||
                open();
 | 
					                open();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } );
 | 
					        } );
 | 
				
			||||||
        application.addAppEventListener( new AppReOpenedListener() {
 | 
					        application.addAppEventListener( new AppReOpenedListener() {
 | 
				
			||||||
            @Override
 | 
					            @Override
 | 
				
			||||||
            public void appReOpened(AppEvent.AppReOpenedEvent arg0) {
 | 
					            public void appReOpened(final AppEvent.AppReOpenedEvent arg0) {
 | 
				
			||||||
                open();
 | 
					                open();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } );
 | 
					        } );
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,11 +13,11 @@ import javax.swing.border.CompoundBorder;
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
public abstract class Components {
 | 
					public abstract class Components {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static GradientPanel boxLayout(int axis, Component... components) {
 | 
					    public static GradientPanel boxLayout(final int axis, final Component... components) {
 | 
				
			||||||
        GradientPanel container = gradientPanel( null, null );
 | 
					        GradientPanel container = gradientPanel( null, null );
 | 
				
			||||||
        //        container.setBackground( Color.red );
 | 
					        //        container.setBackground( Color.red );
 | 
				
			||||||
        container.setLayout( new BoxLayout( container, axis ) );
 | 
					        container.setLayout( new BoxLayout( container, axis ) );
 | 
				
			||||||
        for (Component component : components)
 | 
					        for (final Component component : components)
 | 
				
			||||||
            container.add( component );
 | 
					            container.add( component );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return container;
 | 
					        return container;
 | 
				
			||||||
@@ -27,7 +27,7 @@ public abstract class Components {
 | 
				
			|||||||
        return borderPanel( component, border, null );
 | 
					        return borderPanel( component, border, null );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static GradientPanel borderPanel(final JComponent component, @Nullable final Border border, @Nullable Color background) {
 | 
					    public static GradientPanel borderPanel(final JComponent component, @Nullable final Border border, @Nullable final Color background) {
 | 
				
			||||||
        GradientPanel box = boxLayout( BoxLayout.LINE_AXIS, component );
 | 
					        GradientPanel box = boxLayout( BoxLayout.LINE_AXIS, component );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (border != null)
 | 
					        if (border != null)
 | 
				
			||||||
@@ -83,7 +83,7 @@ public abstract class Components {
 | 
				
			|||||||
        };
 | 
					        };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static JButton button(String label) {
 | 
					    public static JButton button(final String label) {
 | 
				
			||||||
        return new JButton( label ) {
 | 
					        return new JButton( label ) {
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                setFont( Res.controlFont().deriveFont( 12f ) );
 | 
					                setFont( Res.controlFont().deriveFont( 12f ) );
 | 
				
			||||||
@@ -126,18 +126,18 @@ public abstract class Components {
 | 
				
			|||||||
        };
 | 
					        };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static JLabel label(@Nullable String label) {
 | 
					    public static JLabel label(@Nullable final String label) {
 | 
				
			||||||
        return label( label, SwingConstants.LEADING );
 | 
					        return label( label, SwingConstants.LEADING );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @param horizontalAlignment One of the following constants
 | 
					     * @param horizontalAlignment One of the following constants
 | 
				
			||||||
     *                            defined in <code>SwingConstants</code>:
 | 
					     *                            defined in {@code SwingConstants}:
 | 
				
			||||||
     *                            <code>LEFT</code>,
 | 
					     *                            {@code LEFT},
 | 
				
			||||||
     *                            <code>CENTER</code>,
 | 
					     *                            {@code CENTER},
 | 
				
			||||||
     *                            <code>RIGHT</code>,
 | 
					     *                            {@code RIGHT},
 | 
				
			||||||
     *                            <code>LEADING</code> or
 | 
					     *                            {@code LEADING} or
 | 
				
			||||||
     *                            <code>TRAILING</code>.
 | 
					     *                            {@code TRAILING}.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public static JLabel label(@Nullable final String label, final int horizontalAlignment) {
 | 
					    public static JLabel label(@Nullable final String label, final int horizontalAlignment) {
 | 
				
			||||||
        return new JLabel( label, horizontalAlignment ) {
 | 
					        return new JLabel( label, horizontalAlignment ) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,7 +9,6 @@ import java.awt.*;
 | 
				
			|||||||
import javax.annotation.Nonnull;
 | 
					import javax.annotation.Nonnull;
 | 
				
			||||||
import javax.annotation.Nullable;
 | 
					import javax.annotation.Nullable;
 | 
				
			||||||
import javax.swing.*;
 | 
					import javax.swing.*;
 | 
				
			||||||
import org.jetbrains.annotations.NotNull;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@@ -20,7 +19,7 @@ public abstract class AuthenticationPanel extends Components.GradientPanel {
 | 
				
			|||||||
    protected final UnlockFrame unlockFrame;
 | 
					    protected final UnlockFrame unlockFrame;
 | 
				
			||||||
    protected final JLabel      avatarLabel;
 | 
					    protected final JLabel      avatarLabel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public AuthenticationPanel(final UnlockFrame unlockFrame) {
 | 
					    protected AuthenticationPanel(final UnlockFrame unlockFrame) {
 | 
				
			||||||
        super( null, null );
 | 
					        super( null, null );
 | 
				
			||||||
        this.unlockFrame = unlockFrame;
 | 
					        this.unlockFrame = unlockFrame;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -39,7 +38,7 @@ public abstract class AuthenticationPanel extends Components.GradientPanel {
 | 
				
			|||||||
        avatarLabel.setToolTipText( "The avatar for your user.  Click to change it." );
 | 
					        avatarLabel.setToolTipText( "The avatar for your user.  Click to change it." );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected void updateUser(boolean repack) {
 | 
					    protected void updateUser(final boolean repack) {
 | 
				
			||||||
        unlockFrame.updateUser( getSelectedUser() );
 | 
					        unlockFrame.updateUser( getSelectedUser() );
 | 
				
			||||||
        validate();
 | 
					        validate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -50,7 +49,6 @@ public abstract class AuthenticationPanel extends Components.GradientPanel {
 | 
				
			|||||||
    @Nullable
 | 
					    @Nullable
 | 
				
			||||||
    protected abstract User getSelectedUser();
 | 
					    protected abstract User getSelectedUser();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @NotNull
 | 
					 | 
				
			||||||
    @Nonnull
 | 
					    @Nonnull
 | 
				
			||||||
    public abstract char[] getMasterPassword();
 | 
					    public abstract char[] getMasterPassword();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,10 +7,10 @@ import com.lyndir.masterpassword.gui.util.Components;
 | 
				
			|||||||
import java.awt.*;
 | 
					import java.awt.*;
 | 
				
			||||||
import java.awt.event.ActionEvent;
 | 
					import java.awt.event.ActionEvent;
 | 
				
			||||||
import java.awt.event.ActionListener;
 | 
					import java.awt.event.ActionListener;
 | 
				
			||||||
 | 
					import javax.annotation.Nonnull;
 | 
				
			||||||
import javax.swing.*;
 | 
					import javax.swing.*;
 | 
				
			||||||
import javax.swing.event.DocumentEvent;
 | 
					import javax.swing.event.DocumentEvent;
 | 
				
			||||||
import javax.swing.event.DocumentListener;
 | 
					import javax.swing.event.DocumentListener;
 | 
				
			||||||
import org.jetbrains.annotations.NotNull;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@@ -62,7 +62,7 @@ public class IncognitoAuthenticationPanel extends AuthenticationPanel implements
 | 
				
			|||||||
        return new IncognitoUser( fullNameField.getText() );
 | 
					        return new IncognitoUser( fullNameField.getText() );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @NotNull
 | 
					    @Nonnull
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public char[] getMasterPassword() {
 | 
					    public char[] getMasterPassword() {
 | 
				
			||||||
        return masterPasswordField.getPassword();
 | 
					        return masterPasswordField.getPassword();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,12 +13,12 @@ import com.lyndir.masterpassword.model.MPUserFileManager;
 | 
				
			|||||||
import com.lyndir.masterpassword.gui.util.Components;
 | 
					import com.lyndir.masterpassword.gui.util.Components;
 | 
				
			||||||
import java.awt.*;
 | 
					import java.awt.*;
 | 
				
			||||||
import java.awt.event.*;
 | 
					import java.awt.event.*;
 | 
				
			||||||
 | 
					import javax.annotation.Nonnull;
 | 
				
			||||||
import javax.annotation.Nullable;
 | 
					import javax.annotation.Nullable;
 | 
				
			||||||
import javax.swing.*;
 | 
					import javax.swing.*;
 | 
				
			||||||
import javax.swing.event.DocumentEvent;
 | 
					import javax.swing.event.DocumentEvent;
 | 
				
			||||||
import javax.swing.event.DocumentListener;
 | 
					import javax.swing.event.DocumentListener;
 | 
				
			||||||
import javax.swing.plaf.metal.MetalComboBoxEditor;
 | 
					import javax.swing.plaf.metal.MetalComboBoxEditor;
 | 
				
			||||||
import org.jetbrains.annotations.NotNull;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@@ -109,7 +109,7 @@ public class ModelAuthenticationPanel extends AuthenticationPanel implements Ite
 | 
				
			|||||||
        return userField.getModel().getElementAt( selectedIndex );
 | 
					        return userField.getModel().getElementAt( selectedIndex );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @NotNull
 | 
					    @Nonnull
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public char[] getMasterPassword() {
 | 
					    public char[] getMasterPassword() {
 | 
				
			||||||
        return masterPasswordField.getPassword();
 | 
					        return masterPasswordField.getPassword();
 | 
				
			||||||
@@ -175,7 +175,7 @@ public class ModelAuthenticationPanel extends AuthenticationPanel implements Ite
 | 
				
			|||||||
        masterPasswordField.setText( "" );
 | 
					        masterPasswordField.setText( "" );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private ModelUser[] readConfigUsers() {
 | 
					    private static ModelUser[] readConfigUsers() {
 | 
				
			||||||
        return FluentIterable.from( MPUserFileManager.get().getUsers() ).transform( new Function<MPUser, ModelUser>() {
 | 
					        return FluentIterable.from( MPUserFileManager.get().getUsers() ).transform( new Function<MPUser, ModelUser>() {
 | 
				
			||||||
            @Nullable
 | 
					            @Nullable
 | 
				
			||||||
            @Override
 | 
					            @Override
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,7 +28,7 @@ import javax.swing.event.*;
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
public class PasswordFrame extends JFrame implements DocumentListener {
 | 
					public class PasswordFrame extends JFrame implements DocumentListener {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private final User                         user;
 | 
					    @SuppressWarnings("FieldCanBeLocal")
 | 
				
			||||||
    private final Components.GradientPanel     root;
 | 
					    private final Components.GradientPanel     root;
 | 
				
			||||||
    private final JTextField                   siteNameField;
 | 
					    private final JTextField                   siteNameField;
 | 
				
			||||||
    private final JButton                      siteActionButton;
 | 
					    private final JButton                      siteActionButton;
 | 
				
			||||||
@@ -41,13 +41,13 @@ public class PasswordFrame extends JFrame implements DocumentListener {
 | 
				
			|||||||
    private final JCheckBox                    maskPasswordField;
 | 
					    private final JCheckBox                    maskPasswordField;
 | 
				
			||||||
    private final char                         passwordEchoChar;
 | 
					    private final char                         passwordEchoChar;
 | 
				
			||||||
    private final Font                         passwordEchoFont;
 | 
					    private final Font                         passwordEchoFont;
 | 
				
			||||||
 | 
					    private final User                         user;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Nullable
 | 
					    @Nullable
 | 
				
			||||||
    private Site    currentSite;
 | 
					    private Site    currentSite;
 | 
				
			||||||
    private boolean updatingUI;
 | 
					    private boolean updatingUI;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public PasswordFrame(User user)
 | 
					    public PasswordFrame(final User user) {
 | 
				
			||||||
            throws HeadlessException {
 | 
					 | 
				
			||||||
        super( "Master Password" );
 | 
					        super( "Master Password" );
 | 
				
			||||||
        this.user = user;
 | 
					        this.user = user;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -104,7 +104,7 @@ public class PasswordFrame extends JFrame implements DocumentListener {
 | 
				
			|||||||
            public void actionPerformed(final ActionEvent e) {
 | 
					            public void actionPerformed(final ActionEvent e) {
 | 
				
			||||||
                if (currentSite == null)
 | 
					                if (currentSite == null)
 | 
				
			||||||
                    return;
 | 
					                    return;
 | 
				
			||||||
                else if (currentSite instanceof ModelSite)
 | 
					                if (currentSite instanceof ModelSite)
 | 
				
			||||||
                    PasswordFrame.this.user.deleteSite( currentSite );
 | 
					                    PasswordFrame.this.user.deleteSite( currentSite );
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
                    PasswordFrame.this.user.addSite( currentSite );
 | 
					                    PasswordFrame.this.user.addSite( currentSite );
 | 
				
			||||||
@@ -160,7 +160,7 @@ public class PasswordFrame extends JFrame implements DocumentListener {
 | 
				
			|||||||
        maskPasswordField.setSelected( true );
 | 
					        maskPasswordField.setSelected( true );
 | 
				
			||||||
        maskPasswordField.addItemListener( new ItemListener() {
 | 
					        maskPasswordField.addItemListener( new ItemListener() {
 | 
				
			||||||
            @Override
 | 
					            @Override
 | 
				
			||||||
            public void itemStateChanged(ItemEvent e) {
 | 
					            public void itemStateChanged(final ItemEvent e) {
 | 
				
			||||||
                updateMask();
 | 
					                updateMask();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } );
 | 
					        } );
 | 
				
			||||||
@@ -203,33 +203,33 @@ public class PasswordFrame extends JFrame implements DocumentListener {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Nonnull
 | 
					    @Nonnull
 | 
				
			||||||
    private ListenableFuture<String> updatePassword(boolean allowNameCompletion) {
 | 
					    private ListenableFuture<String> updatePassword(final boolean allowNameCompletion) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        final String siteNameQuery = siteNameField.getText();
 | 
					        final String siteNameQuery = siteNameField.getText();
 | 
				
			||||||
        if (updatingUI)
 | 
					        if (updatingUI)
 | 
				
			||||||
            return Futures.immediateCancelledFuture();
 | 
					            return Futures.immediateCancelledFuture();
 | 
				
			||||||
        if (siteNameQuery == null || siteNameQuery.isEmpty() || !user.isKeyAvailable()) {
 | 
					        if ((siteNameQuery == null) || siteNameQuery.isEmpty() || !user.isKeyAvailable()) {
 | 
				
			||||||
            siteActionButton.setVisible( false );
 | 
					            siteActionButton.setVisible( false );
 | 
				
			||||||
            tipLabel.setText( null );
 | 
					            tipLabel.setText( null );
 | 
				
			||||||
            passwordField.setText( null );
 | 
					            passwordField.setText( null );
 | 
				
			||||||
            return Futures.immediateCancelledFuture();
 | 
					            return Futures.immediateCancelledFuture();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        final MPSiteType siteType = siteTypeField.getModel().getElementAt( siteTypeField.getSelectedIndex() );
 | 
					        MPSiteType        siteType    = siteTypeField.getModel().getElementAt( siteTypeField.getSelectedIndex() );
 | 
				
			||||||
        final MasterKey.Version siteVersion = siteVersionField.getItemAt( siteVersionField.getSelectedIndex() );
 | 
					        MasterKey.Version siteVersion = siteVersionField.getItemAt( siteVersionField.getSelectedIndex() );
 | 
				
			||||||
        final UnsignedInteger siteCounter = siteCounterModel.getNumber();
 | 
					        UnsignedInteger   siteCounter = siteCounterModel.getNumber();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Iterable<Site> siteResults = user.findSitesByName( siteNameQuery );
 | 
					        Iterable<Site> siteResults = user.findSitesByName( siteNameQuery );
 | 
				
			||||||
        if (!allowNameCompletion)
 | 
					        if (!allowNameCompletion)
 | 
				
			||||||
            siteResults = FluentIterable.from( siteResults ).filter( new Predicate<Site>() {
 | 
					            siteResults = FluentIterable.from( siteResults ).filter( new Predicate<Site>() {
 | 
				
			||||||
                @Override
 | 
					                @Override
 | 
				
			||||||
                public boolean apply(@Nullable Site siteResult) {
 | 
					                public boolean apply(@Nullable final Site siteResult) {
 | 
				
			||||||
                    return siteResult != null && siteNameQuery.equals( siteResult.getSiteName() );
 | 
					                    return (siteResult != null) && siteNameQuery.equals( siteResult.getSiteName() );
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            } );
 | 
					            } );
 | 
				
			||||||
        final Site site = ifNotNullElse( Iterables.getFirst( siteResults, null ),
 | 
					        final Site site = ifNotNullElse( Iterables.getFirst( siteResults, null ),
 | 
				
			||||||
                                         new IncognitoSite( siteNameQuery, siteType, siteCounter, siteVersion ) );
 | 
					                                         new IncognitoSite( siteNameQuery, siteType, siteCounter, siteVersion ) );
 | 
				
			||||||
        if (currentSite != null && currentSite.getSiteName().equals( site.getSiteName() )) {
 | 
					        if ((currentSite != null) && currentSite.getSiteName().equals( site.getSiteName() )) {
 | 
				
			||||||
            site.setSiteType( siteType );
 | 
					            site.setSiteType( siteType );
 | 
				
			||||||
            site.setAlgorithmVersion( siteVersion );
 | 
					            site.setAlgorithmVersion( siteVersion );
 | 
				
			||||||
            site.setSiteCounter( siteCounter );
 | 
					            site.setSiteCounter( siteCounter );
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,22 +28,21 @@ public class UnlockFrame extends JFrame {
 | 
				
			|||||||
    private       AuthenticationPanel      authenticationPanel;
 | 
					    private       AuthenticationPanel      authenticationPanel;
 | 
				
			||||||
    private       Future<?>                identiconFuture;
 | 
					    private       Future<?>                identiconFuture;
 | 
				
			||||||
    private       boolean                  incognito;
 | 
					    private       boolean                  incognito;
 | 
				
			||||||
    public        User                     user;
 | 
					    private       User                     user;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public UnlockFrame(final SignInCallback signInCallback)
 | 
					    public UnlockFrame(final SignInCallback signInCallback) {
 | 
				
			||||||
            throws HeadlessException {
 | 
					 | 
				
			||||||
        super( "Unlock Master Password" );
 | 
					        super( "Unlock Master Password" );
 | 
				
			||||||
        this.signInCallback = signInCallback;
 | 
					        this.signInCallback = signInCallback;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        setDefaultCloseOperation( DISPOSE_ON_CLOSE );
 | 
					        setDefaultCloseOperation( DISPOSE_ON_CLOSE );
 | 
				
			||||||
        addWindowFocusListener( new WindowAdapter() {
 | 
					        addWindowFocusListener( new WindowAdapter() {
 | 
				
			||||||
            @Override
 | 
					            @Override
 | 
				
			||||||
            public void windowGainedFocus(WindowEvent e) {
 | 
					            public void windowGainedFocus(final WindowEvent e) {
 | 
				
			||||||
                root.setGradientColor( Res.colors().frameBg() );
 | 
					                root.setGradientColor( Res.colors().frameBg() );
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            @Override
 | 
					            @Override
 | 
				
			||||||
            public void windowLostFocus(WindowEvent e) {
 | 
					            public void windowLostFocus(final WindowEvent e) {
 | 
				
			||||||
                root.setGradientColor( Color.RED );
 | 
					                root.setGradientColor( Color.RED );
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } );
 | 
					        } );
 | 
				
			||||||
@@ -118,7 +117,7 @@ public class UnlockFrame extends JFrame {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        JComponent toolsPanel = Components.boxLayout( BoxLayout.LINE_AXIS, incognitoCheckBox, Box.createGlue() );
 | 
					        JComponent toolsPanel = Components.boxLayout( BoxLayout.LINE_AXIS, incognitoCheckBox, Box.createGlue() );
 | 
				
			||||||
        authenticationContainer.add( toolsPanel );
 | 
					        authenticationContainer.add( toolsPanel );
 | 
				
			||||||
        for (JButton button : authenticationPanel.getButtons()) {
 | 
					        for (final JButton button : authenticationPanel.getButtons()) {
 | 
				
			||||||
            toolsPanel.add( button );
 | 
					            toolsPanel.add( button );
 | 
				
			||||||
            button.setBorder( BorderFactory.createEmptyBorder() );
 | 
					            button.setBorder( BorderFactory.createEmptyBorder() );
 | 
				
			||||||
            button.setMargin( new Insets( 0, 0, 0, 0 ) );
 | 
					            button.setMargin( new Insets( 0, 0, 0, 0 ) );
 | 
				
			||||||
@@ -138,7 +137,7 @@ public class UnlockFrame extends JFrame {
 | 
				
			|||||||
        } );
 | 
					        } );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void updateUser(@Nullable User user) {
 | 
					    void updateUser(@Nullable final User user) {
 | 
				
			||||||
        this.user = user;
 | 
					        this.user = user;
 | 
				
			||||||
        checkSignIn();
 | 
					        checkSignIn();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -152,10 +151,10 @@ public class UnlockFrame extends JFrame {
 | 
				
			|||||||
                SwingUtilities.invokeLater( new Runnable() {
 | 
					                SwingUtilities.invokeLater( new Runnable() {
 | 
				
			||||||
                    @Override
 | 
					                    @Override
 | 
				
			||||||
                    public void run() {
 | 
					                    public void run() {
 | 
				
			||||||
                        String fullName = user == null? "": user.getFullName();
 | 
					                        String fullName = (user == null)? "": user.getFullName();
 | 
				
			||||||
                        char[] masterPassword = authenticationPanel.getMasterPassword();
 | 
					                        char[] masterPassword = authenticationPanel.getMasterPassword();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        if (fullName.isEmpty() || masterPassword.length == 0) {
 | 
					                        if (fullName.isEmpty() || (masterPassword.length == 0)) {
 | 
				
			||||||
                            identiconLabel.setText( " " );
 | 
					                            identiconLabel.setText( " " );
 | 
				
			||||||
                            return;
 | 
					                            return;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
@@ -169,9 +168,9 @@ public class UnlockFrame extends JFrame {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }, 300, TimeUnit.MILLISECONDS );
 | 
					        }, 300, TimeUnit.MILLISECONDS );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        String fullName = user == null? "": user.getFullName();
 | 
					        String fullName = (user == null)? "": user.getFullName();
 | 
				
			||||||
        char[] masterPassword = authenticationPanel.getMasterPassword();
 | 
					        char[] masterPassword = authenticationPanel.getMasterPassword();
 | 
				
			||||||
        boolean enabled = !fullName.isEmpty() && masterPassword.length > 0;
 | 
					        boolean enabled = !fullName.isEmpty() && (masterPassword.length > 0);
 | 
				
			||||||
        signInButton.setEnabled( enabled );
 | 
					        signInButton.setEnabled( enabled );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return enabled;
 | 
					        return enabled;
 | 
				
			||||||
@@ -181,7 +180,7 @@ public class UnlockFrame extends JFrame {
 | 
				
			|||||||
        if (!checkSignIn())
 | 
					        if (!checkSignIn())
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (JComponent signInComponent : signInComponents)
 | 
					        for (final JComponent signInComponent : signInComponents)
 | 
				
			||||||
            signInComponent.setEnabled( false );
 | 
					            signInComponent.setEnabled( false );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        signInButton.setEnabled( false );
 | 
					        signInButton.setEnabled( false );
 | 
				
			||||||
@@ -208,7 +207,7 @@ public class UnlockFrame extends JFrame {
 | 
				
			|||||||
                            JOptionPane.showMessageDialog( null, e.getLocalizedMessage(), "Sign In Failed", JOptionPane.ERROR_MESSAGE );
 | 
					                            JOptionPane.showMessageDialog( null, e.getLocalizedMessage(), "Sign In Failed", JOptionPane.ERROR_MESSAGE );
 | 
				
			||||||
                            authenticationPanel.reset();
 | 
					                            authenticationPanel.reset();
 | 
				
			||||||
                            signInButton.setText( "Sign In" );
 | 
					                            signInButton.setText( "Sign In" );
 | 
				
			||||||
                            for (JComponent signInComponent : signInComponents)
 | 
					                            for (final JComponent signInComponent : signInComponents)
 | 
				
			||||||
                                signInComponent.setEnabled( true );
 | 
					                                signInComponent.setEnabled( true );
 | 
				
			||||||
                            checkSignIn();
 | 
					                            checkSignIn();
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user