Refactor masterpassword-model
This commit is contained in:
		@@ -5,10 +5,10 @@ plugins {
 | 
				
			|||||||
description = 'Master Password Algorithm Implementation'
 | 
					description = 'Master Password Algorithm Implementation'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dependencies {
 | 
					dependencies {
 | 
				
			||||||
    compile( group: 'com.lyndir.lhunath.opal', name: 'opal-system', version: '1.6-p11' ) {
 | 
					    compile( group: 'com.lyndir.lhunath.opal', name: 'opal-system', version: 'GIT-SNAPSHOT' ) {
 | 
				
			||||||
        exclude( module: 'joda-time' )
 | 
					        exclude( module: 'joda-time' )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    compile group: 'com.lyndir.lhunath.opal', name: 'opal-crypto', version: '1.6-p11'
 | 
					    compile group: 'com.lyndir.lhunath.opal', name: 'opal-crypto', version: 'GIT-SNAPSHOT'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    compile group: 'com.lambdaworks', name: 'scrypt', version: '1.4.0'
 | 
					    compile group: 'com.lambdaworks', name: 'scrypt', version: '1.4.0'
 | 
				
			||||||
    compile 'com.fasterxml.jackson.core:jackson-annotations:2.9.5'
 | 
					    compile 'com.fasterxml.jackson.core:jackson-annotations:2.9.5'
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -59,7 +59,7 @@ public abstract class MPAlgorithm {
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * mpw: defaults: password result type.
 | 
					     * mpw: defaults: password result type.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public abstract MPResultType mpw_default_password_type();
 | 
					    public abstract MPResultType mpw_default_result_type();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * mpw: defaults: login result type.
 | 
					     * mpw: defaults: login result type.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -247,7 +247,7 @@ public class MPAlgorithmV0 extends MPAlgorithm {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public MPResultType mpw_default_password_type() {
 | 
					    public MPResultType mpw_default_result_type() {
 | 
				
			||||||
        return MPResultType.GeneratedLong;
 | 
					        return MPResultType.GeneratedLong;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,212 +0,0 @@
 | 
				
			|||||||
//==============================================================================
 | 
					 | 
				
			||||||
// This file is part of Master Password.
 | 
					 | 
				
			||||||
// Copyright (c) 2011-2017, Maarten Billemont.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Master Password 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.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Master Password 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/>.
 | 
					 | 
				
			||||||
//==============================================================================
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package com.lyndir.masterpassword.model;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import static com.lyndir.lhunath.opal.system.util.ObjectUtils.*;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import com.google.common.primitives.UnsignedInteger;
 | 
					 | 
				
			||||||
import com.lyndir.masterpassword.*;
 | 
					 | 
				
			||||||
import java.util.*;
 | 
					 | 
				
			||||||
import javax.annotation.Nonnull;
 | 
					 | 
				
			||||||
import javax.annotation.Nullable;
 | 
					 | 
				
			||||||
import org.joda.time.Instant;
 | 
					 | 
				
			||||||
import org.joda.time.ReadableInstant;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @author lhunath, 14-12-05
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
public class MPFileSite extends MPSite {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private final MPFileUser user;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private String          siteName;
 | 
					 | 
				
			||||||
    private UnsignedInteger siteCounter;
 | 
					 | 
				
			||||||
    @Nullable
 | 
					 | 
				
			||||||
    private String          siteState;
 | 
					 | 
				
			||||||
    private MPResultType    resultType;
 | 
					 | 
				
			||||||
    private MPAlgorithm     algorithm;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Nullable
 | 
					 | 
				
			||||||
    private String       loginState;
 | 
					 | 
				
			||||||
    private MPResultType loginType;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Nullable
 | 
					 | 
				
			||||||
    private String          url;
 | 
					 | 
				
			||||||
    private int             uses;
 | 
					 | 
				
			||||||
    private ReadableInstant lastUsed;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private final Collection<MPFileQuestion> questions = new LinkedHashSet<>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public MPFileSite(final MPFileUser user, final String siteName) {
 | 
					 | 
				
			||||||
        this( user, siteName, null, null, user.getAlgorithm() );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public MPFileSite(final MPFileUser user, final String siteName, @Nullable final UnsignedInteger siteCounter,
 | 
					 | 
				
			||||||
                      @Nullable final MPResultType resultType, final MPAlgorithm algorithm) {
 | 
					 | 
				
			||||||
        this( user, siteName, null, siteCounter, resultType, algorithm,
 | 
					 | 
				
			||||||
              null, null, null, 0, new Instant() );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected MPFileSite(final MPFileUser user, final String siteName, @Nullable final String siteState,
 | 
					 | 
				
			||||||
                         @Nullable final UnsignedInteger siteCounter, @Nullable final MPResultType resultType, final MPAlgorithm algorithm,
 | 
					 | 
				
			||||||
                         @Nullable final String loginState, @Nullable final MPResultType loginType,
 | 
					 | 
				
			||||||
                         @Nullable final String url, final int uses, final ReadableInstant lastUsed) {
 | 
					 | 
				
			||||||
        this.user = user;
 | 
					 | 
				
			||||||
        this.algorithm = algorithm;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        this.siteName = siteName;
 | 
					 | 
				
			||||||
        this.siteState = siteState;
 | 
					 | 
				
			||||||
        this.siteCounter = ifNotNullElse( siteCounter, getAlgorithm().mpw_default_counter() );
 | 
					 | 
				
			||||||
        this.resultType = ifNotNullElse( resultType, getAlgorithm().mpw_default_password_type() );
 | 
					 | 
				
			||||||
        this.loginState = loginState;
 | 
					 | 
				
			||||||
        this.loginType = ifNotNullElse( loginType, getAlgorithm().mpw_default_login_type() );
 | 
					 | 
				
			||||||
        this.url = url;
 | 
					 | 
				
			||||||
        this.uses = uses;
 | 
					 | 
				
			||||||
        this.lastUsed = lastUsed;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public String getResult()
 | 
					 | 
				
			||||||
            throws MPKeyUnavailableException {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return getResult( MPKeyPurpose.Authentication, null );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public String getResult(final MPKeyPurpose keyPurpose, @Nullable final String keyContext)
 | 
					 | 
				
			||||||
            throws MPKeyUnavailableException {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return getResult( keyPurpose, keyContext, siteState );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public String getLogin()
 | 
					 | 
				
			||||||
            throws MPKeyUnavailableException {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return getLogin( loginState );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public MPUser<?> getUser() {
 | 
					 | 
				
			||||||
        return user;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public String getSiteName() {
 | 
					 | 
				
			||||||
        return siteName;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public void setSiteName(final String siteName) {
 | 
					 | 
				
			||||||
        this.siteName = siteName;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Nullable
 | 
					 | 
				
			||||||
    public String getSiteState() {
 | 
					 | 
				
			||||||
        return siteState;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void setSitePassword(final MPResultType resultType, @Nullable final String password)
 | 
					 | 
				
			||||||
            throws MPKeyUnavailableException {
 | 
					 | 
				
			||||||
        this.resultType = resultType;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (password == null)
 | 
					 | 
				
			||||||
            this.siteState = null;
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            this.siteState = getState(
 | 
					 | 
				
			||||||
                    MPKeyPurpose.Authentication, null, siteCounter, resultType, password );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public UnsignedInteger getSiteCounter() {
 | 
					 | 
				
			||||||
        return siteCounter;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public void setSiteCounter(final UnsignedInteger siteCounter) {
 | 
					 | 
				
			||||||
        this.siteCounter = siteCounter;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public MPResultType getResultType() {
 | 
					 | 
				
			||||||
        return resultType;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public void setResultType(final MPResultType resultType) {
 | 
					 | 
				
			||||||
        this.resultType = resultType;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public MPResultType getLoginType() {
 | 
					 | 
				
			||||||
        return loginType;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public void setLoginType(@Nullable final MPResultType loginType) {
 | 
					 | 
				
			||||||
        this.loginType = ifNotNullElse( loginType, getAlgorithm().mpw_default_login_type() );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public MPAlgorithm getAlgorithm() {
 | 
					 | 
				
			||||||
        return algorithm;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public void setAlgorithm(final MPAlgorithm algorithm) {
 | 
					 | 
				
			||||||
        this.algorithm = algorithm;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public Collection<? extends MPQuestion> getQuestions() {
 | 
					 | 
				
			||||||
        return Collections.unmodifiableCollection( questions );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Nullable
 | 
					 | 
				
			||||||
    public String getLoginState() {
 | 
					 | 
				
			||||||
        return loginState;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void setLoginName(@Nonnull final MPResultType loginType, @Nonnull final String loginName)
 | 
					 | 
				
			||||||
            throws MPKeyUnavailableException {
 | 
					 | 
				
			||||||
        this.loginType = loginType;
 | 
					 | 
				
			||||||
        this.loginState = getState( MPKeyPurpose.Identification, null, null, this.loginType, loginName );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Nullable
 | 
					 | 
				
			||||||
    public String getUrl() {
 | 
					 | 
				
			||||||
        return url;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void setUrl(@Nullable final String url) {
 | 
					 | 
				
			||||||
        this.url = url;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public int getUses() {
 | 
					 | 
				
			||||||
        return uses;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public ReadableInstant getLastUsed() {
 | 
					 | 
				
			||||||
        return lastUsed;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void use() {
 | 
					 | 
				
			||||||
        uses++;
 | 
					 | 
				
			||||||
        lastUsed = new Instant();
 | 
					 | 
				
			||||||
        user.use();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -18,20 +18,21 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package com.lyndir.masterpassword.model;
 | 
					package com.lyndir.masterpassword.model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @author lhunath, 14-12-17
 | 
					 * @author lhunath, 14-12-17
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public class MPIncorrectMasterPasswordException extends Exception {
 | 
					public class MPIncorrectMasterPasswordException extends Exception {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private final MPFileUser user;
 | 
					    private final MPUser<?> user;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public MPIncorrectMasterPasswordException(final MPFileUser user) {
 | 
					    public MPIncorrectMasterPasswordException(final MPUser<?> user) {
 | 
				
			||||||
        super( "Incorrect master password for user: " + user.getFullName() );
 | 
					        super( "Incorrect master password for user: " + user.getFullName() );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.user = user;
 | 
					        this.user = user;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public MPFileUser getUser() {
 | 
					    public MPUser<?> getUser() {
 | 
				
			||||||
        return user;
 | 
					        return user;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,24 +18,35 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package com.lyndir.masterpassword.model;
 | 
					package com.lyndir.masterpassword.model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.lyndir.masterpassword.*;
 | 
					import com.lyndir.masterpassword.MPKeyUnavailableException;
 | 
				
			||||||
 | 
					import com.lyndir.masterpassword.MPResultType;
 | 
				
			||||||
 | 
					import javax.annotation.Nonnull;
 | 
				
			||||||
import javax.annotation.Nullable;
 | 
					import javax.annotation.Nullable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @author lhunath, 2018-05-14
 | 
					 * @author lhunath, 2018-05-15
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public abstract class MPQuestion {
 | 
					public interface MPQuestion extends Comparable<MPQuestion> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract MPSite getSite();
 | 
					    // -- Meta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract String getKeyword();
 | 
					    @Nonnull
 | 
				
			||||||
 | 
					    String getKeyword();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract MPResultType getType();
 | 
					    // -- Algorithm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public String getAnswer(@Nullable final String state)
 | 
					    @Nonnull
 | 
				
			||||||
            throws MPKeyUnavailableException {
 | 
					    MPResultType getType();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return getSite().getResult( MPKeyPurpose.Recovery, getKeyword(), null, getType(), state );
 | 
					    void setType(MPResultType type);
 | 
				
			||||||
    }
 | 
					
 | 
				
			||||||
 | 
					    @Nonnull
 | 
				
			||||||
 | 
					    String getAnswer(@Nullable String state)
 | 
				
			||||||
 | 
					            throws MPKeyUnavailableException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // -- Relationship
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Nonnull
 | 
				
			||||||
 | 
					    MPSite getSite();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,90 +18,50 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package com.lyndir.masterpassword.model;
 | 
					package com.lyndir.masterpassword.model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static com.lyndir.lhunath.opal.system.util.ObjectUtils.*;
 | 
					 | 
				
			||||||
import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import com.google.common.primitives.UnsignedInteger;
 | 
					import com.google.common.primitives.UnsignedInteger;
 | 
				
			||||||
import com.lyndir.masterpassword.*;
 | 
					import com.lyndir.masterpassword.*;
 | 
				
			||||||
import java.util.Collection;
 | 
					import java.util.Collection;
 | 
				
			||||||
import java.util.Objects;
 | 
					 | 
				
			||||||
import javax.annotation.Nullable;
 | 
					import javax.annotation.Nullable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @author lhunath, 14-12-16
 | 
					 * @author lhunath, 2018-05-14
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public abstract class MPSite {
 | 
					public interface MPSite extends Comparable<MPSite> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract MPUser<?> getUser();
 | 
					    // - Meta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract String getSiteName();
 | 
					    String getName();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract void setSiteName(String siteName);
 | 
					    void setName(String name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract UnsignedInteger getSiteCounter();
 | 
					    // - Algorithm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract void setSiteCounter(UnsignedInteger siteCounter);
 | 
					    MPAlgorithm getAlgorithm();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract MPResultType getResultType();
 | 
					    void setAlgorithm(MPAlgorithm algorithm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract void setResultType(MPResultType resultType);
 | 
					    UnsignedInteger getCounter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract MPResultType getLoginType();
 | 
					    void setCounter(UnsignedInteger counter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract void setLoginType(@Nullable MPResultType loginType);
 | 
					    MPResultType getResultType();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract MPAlgorithm getAlgorithm();
 | 
					    void setResultType(MPResultType resultType);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract void setAlgorithm(MPAlgorithm algorithm);
 | 
					    MPResultType getLoginType();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public String getResult(final MPKeyPurpose keyPurpose, @Nullable final String keyContext,
 | 
					    void setLoginType(@Nullable MPResultType loginType);
 | 
				
			||||||
                            @Nullable final String state)
 | 
					 | 
				
			||||||
            throws MPKeyUnavailableException {
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return getResult( keyPurpose, keyContext, getSiteCounter(), getResultType(), state );
 | 
					    String getResult(MPKeyPurpose keyPurpose, @Nullable String keyContext, @Nullable String state)
 | 
				
			||||||
    }
 | 
					            throws MPKeyUnavailableException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected String getResult(final MPKeyPurpose keyPurpose, @Nullable final String keyContext,
 | 
					    String getLogin(@Nullable String state)
 | 
				
			||||||
                               @Nullable final UnsignedInteger siteCounter, final MPResultType type,
 | 
					            throws MPKeyUnavailableException;
 | 
				
			||||||
                               @Nullable final String state)
 | 
					 | 
				
			||||||
            throws MPKeyUnavailableException {
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return getUser().getMasterKey().siteResult(
 | 
					    // - Relations
 | 
				
			||||||
                getSiteName(), ifNotNullElse( siteCounter, getAlgorithm().mpw_default_counter() ), keyPurpose, keyContext,
 | 
					 | 
				
			||||||
                type, state, getAlgorithm() );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected String getState(final MPKeyPurpose keyPurpose, @Nullable final String keyContext,
 | 
					    MPUser<? extends MPSite> getUser();
 | 
				
			||||||
                               @Nullable final UnsignedInteger siteCounter, final MPResultType type,
 | 
					 | 
				
			||||||
                               @Nullable final String state)
 | 
					 | 
				
			||||||
            throws MPKeyUnavailableException {
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return getUser().getMasterKey().siteState(
 | 
					    Collection<? extends MPQuestion> getQuestions();
 | 
				
			||||||
                getSiteName(), ifNotNullElse( siteCounter, getAlgorithm().mpw_default_counter() ), keyPurpose, keyContext,
 | 
					 | 
				
			||||||
                type, state, getAlgorithm() );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public String getLogin(@Nullable final String loginContent)
 | 
					 | 
				
			||||||
            throws MPKeyUnavailableException {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return getResult( MPKeyPurpose.Identification, null,null, getLoginType(), loginContent );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public abstract Collection<? extends MPQuestion> getQuestions();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public boolean equals(final Object obj) {
 | 
					 | 
				
			||||||
        return (this == obj) || ((obj instanceof MPSite) && Objects.equals( getSiteName(), ((MPSite) obj).getSiteName() ));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public int hashCode() {
 | 
					 | 
				
			||||||
        return Objects.hashCode( getSiteName() );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public String toString() {
 | 
					 | 
				
			||||||
        return strf( "{%s: %s}", getClass().getSimpleName(), getSiteName() );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,35 +21,41 @@ package com.lyndir.masterpassword.model;
 | 
				
			|||||||
import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
 | 
					import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.Objects;
 | 
					import java.util.Objects;
 | 
				
			||||||
 | 
					import org.jetbrains.annotations.NotNull;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @author lhunath, 14-12-07
 | 
					 * @author lhunath, 14-12-07
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public class MPSiteResult {
 | 
					public class MPSiteResult implements Comparable<MPSiteResult> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private final MPFileSite site;
 | 
					    private final MPSite site;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public MPSiteResult(final MPFileSite site) {
 | 
					    public MPSiteResult(final MPSite site) {
 | 
				
			||||||
        this.site = site;
 | 
					        this.site = site;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public MPFileSite getSite() {
 | 
					    public MPSite getSite() {
 | 
				
			||||||
        return site;
 | 
					        return site;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public boolean equals(final Object obj) {
 | 
					    public int hashCode() {
 | 
				
			||||||
        return (this == obj) || ((obj instanceof MPSiteResult) && Objects.equals( site, ((MPSiteResult) obj).site ));
 | 
					        return Objects.hashCode( getSite() );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public int hashCode() {
 | 
					    public boolean equals(final Object obj) {
 | 
				
			||||||
        return Objects.hashCode( site );
 | 
					        return (this == obj) || ((obj instanceof MPSiteResult) && Objects.equals( getSite(), ((MPSiteResult) obj).getSite() ));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public int compareTo(@NotNull final MPSiteResult o) {
 | 
				
			||||||
 | 
					        return getSite().compareTo( o.getSite() );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public String toString() {
 | 
					    public String toString() {
 | 
				
			||||||
        return strf( "{MPSiteResult: %s}", site );
 | 
					        return strf( "{%s: %s}", getClass().getSimpleName(), getSite() );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										110
									
								
								core/java/model/src/main/java/com/lyndir/masterpassword/model/MPUser.java
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										110
									
								
								core/java/model/src/main/java/com/lyndir/masterpassword/model/MPUser.java
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							@@ -18,72 +18,78 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package com.lyndir.masterpassword.model;
 | 
					package com.lyndir.masterpassword.model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import com.lyndir.lhunath.opal.system.CodeUtils;
 | 
					 | 
				
			||||||
import com.lyndir.masterpassword.*;
 | 
					import com.lyndir.masterpassword.*;
 | 
				
			||||||
import java.util.Collection;
 | 
					import java.util.Collection;
 | 
				
			||||||
import java.util.Objects;
 | 
					 | 
				
			||||||
import javax.annotation.Nonnull;
 | 
					import javax.annotation.Nonnull;
 | 
				
			||||||
import javax.annotation.Nullable;
 | 
					import javax.annotation.Nullable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @author lhunath, 2014-06-08
 | 
					 * @author lhunath, 2018-05-14
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public abstract class MPUser<S extends MPSite> {
 | 
					public interface MPUser<S extends MPSite> extends Comparable<MPUser<?>> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // - Meta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int getAvatar();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void setAvatar(int avatar);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Nonnull
 | 
				
			||||||
 | 
					    String getFullName();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // - Algorithm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Nonnull
 | 
				
			||||||
 | 
					    MPAlgorithm getAlgorithm();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void setAlgorithm(MPAlgorithm algorithm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Nullable
 | 
					    @Nullable
 | 
				
			||||||
    protected MPMasterKey key;
 | 
					    byte[] getKeyID();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract String getFullName();
 | 
					    @Nullable
 | 
				
			||||||
 | 
					    String exportKeyID();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public boolean isMasterKeyAvailable() {
 | 
					    /**
 | 
				
			||||||
        return key != null;
 | 
					     * Performs an authentication attempt against the keyID for this user.
 | 
				
			||||||
    }
 | 
					     *
 | 
				
			||||||
 | 
					     * Note: If a keyID is not set, authentication will always succeed and the keyID will be set to match the given master password.
 | 
				
			||||||
    @Nonnull
 | 
					     *
 | 
				
			||||||
    public MPMasterKey getMasterKey()
 | 
					     * @param masterPassword The password to authenticate with.
 | 
				
			||||||
            throws MPKeyUnavailableException {
 | 
					     *
 | 
				
			||||||
        if (key == null)
 | 
					     * @throws MPIncorrectMasterPasswordException If authentication fails due to the given master password not matching the user's keyID.
 | 
				
			||||||
            throw new MPKeyUnavailableException();
 | 
					     */
 | 
				
			||||||
 | 
					    void authenticate(char[] masterPassword)
 | 
				
			||||||
        return key;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public String exportKeyID()
 | 
					 | 
				
			||||||
            throws MPKeyUnavailableException {
 | 
					 | 
				
			||||||
        return CodeUtils.encodeHex( getMasterKey().getKeyID( getAlgorithm() ) );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public abstract MPAlgorithm getAlgorithm();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public int getAvatar() {
 | 
					 | 
				
			||||||
        return 0;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public abstract void addSite(S site);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public abstract void deleteSite(S site);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public abstract Collection<S> findSites(String query);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Nonnull
 | 
					 | 
				
			||||||
    public abstract MPMasterKey authenticate(char[] masterPassword)
 | 
					 | 
				
			||||||
            throws MPIncorrectMasterPasswordException;
 | 
					            throws MPIncorrectMasterPasswordException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    /**
 | 
				
			||||||
    public int hashCode() {
 | 
					     * Performs an authentication attempt against the keyID for this user.
 | 
				
			||||||
        return Objects.hashCode( getFullName() );
 | 
					     *
 | 
				
			||||||
    }
 | 
					     * Note: If a keyID is not set, authentication will always succeed and the keyID will be set to match the given key.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param masterKey The master key to authenticate with.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @throws MPIncorrectMasterPasswordException If authentication fails due to the given master password not matching the user's keyID.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void authenticate(MPMasterKey masterKey)
 | 
				
			||||||
 | 
					            throws MPIncorrectMasterPasswordException, MPKeyUnavailableException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    boolean isMasterKeyAvailable();
 | 
				
			||||||
    public boolean equals(final Object obj) {
 | 
					 | 
				
			||||||
        return (this == obj) || ((obj instanceof MPUser) && Objects.equals( getFullName(), ((MPUser<?>) obj).getFullName() ));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Nonnull
 | 
				
			||||||
    public String toString() {
 | 
					    MPMasterKey getMasterKey()
 | 
				
			||||||
        return strf( "{%s: %s}", getClass().getSimpleName(), getFullName() );
 | 
					            throws MPKeyUnavailableException;
 | 
				
			||||||
    }
 | 
					
 | 
				
			||||||
 | 
					    // - Relations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void addSite(S site);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void deleteSite(S site);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Nonnull
 | 
				
			||||||
 | 
					    Collection<S> getSites();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Nonnull
 | 
				
			||||||
 | 
					    Collection<S> findSites(String query);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,6 +19,7 @@
 | 
				
			|||||||
package com.lyndir.masterpassword.model;
 | 
					package com.lyndir.masterpassword.model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.google.common.collect.*;
 | 
					import com.google.common.collect.*;
 | 
				
			||||||
 | 
					import com.lyndir.masterpassword.model.impl.MPFileUser;
 | 
				
			||||||
import java.util.Map;
 | 
					import java.util.Map;
 | 
				
			||||||
import java.util.SortedSet;
 | 
					import java.util.SortedSet;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -26,28 +27,28 @@ import java.util.SortedSet;
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * @author lhunath, 14-12-05
 | 
					 * @author lhunath, 14-12-05
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public abstract class MPUserManager {
 | 
					public abstract class MPUserManager<U extends MPUser<?>> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private final Map<String, MPFileUser> usersByName = Maps.newHashMap();
 | 
					    private final Map<String, U> usersByName = Maps.newHashMap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected MPUserManager(final Iterable<MPFileUser> users) {
 | 
					    protected MPUserManager(final Iterable<U> users) {
 | 
				
			||||||
        for (final MPFileUser user : users)
 | 
					        for (final U user : users)
 | 
				
			||||||
            usersByName.put( user.getFullName(), user );
 | 
					            usersByName.put( user.getFullName(), user );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public SortedSet<MPFileUser> getUsers() {
 | 
					    public SortedSet<U> getUsers() {
 | 
				
			||||||
        return FluentIterable.from( usersByName.values() ).toSortedSet( Ordering.natural() );
 | 
					        return FluentIterable.from( usersByName.values() ).toSortedSet( Ordering.natural() );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public MPFileUser getUserNamed(final String fullName) {
 | 
					    public U getUserNamed(final String fullName) {
 | 
				
			||||||
        return usersByName.get( fullName );
 | 
					        return usersByName.get( fullName );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void addUser(final MPFileUser user) {
 | 
					    public void addUser(final U user) {
 | 
				
			||||||
        usersByName.put( user.getFullName(), user );
 | 
					        usersByName.put( user.getFullName(), user );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void deleteUser(final MPFileUser user) {
 | 
					    public void deleteUser(final U user) {
 | 
				
			||||||
        usersByName.remove( user.getFullName() );
 | 
					        usersByName.remove( user.getFullName() );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,93 @@
 | 
				
			|||||||
 | 
					//==============================================================================
 | 
				
			||||||
 | 
					// This file is part of Master Password.
 | 
				
			||||||
 | 
					// Copyright (c) 2011-2017, Maarten Billemont.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Master Password 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.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Master Password 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/>.
 | 
				
			||||||
 | 
					//==============================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package com.lyndir.masterpassword.model.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import static com.lyndir.lhunath.opal.system.util.StringUtils.strf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.lyndir.masterpassword.*;
 | 
				
			||||||
 | 
					import com.lyndir.masterpassword.model.MPQuestion;
 | 
				
			||||||
 | 
					import java.util.Objects;
 | 
				
			||||||
 | 
					import javax.annotation.Nonnull;
 | 
				
			||||||
 | 
					import javax.annotation.Nullable;
 | 
				
			||||||
 | 
					import org.jetbrains.annotations.NotNull;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @author lhunath, 2018-05-14
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public abstract class MPBasicQuestion implements MPQuestion {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private final String       keyword;
 | 
				
			||||||
 | 
					    private       MPResultType type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected MPBasicQuestion(final String keyword, final MPResultType type) {
 | 
				
			||||||
 | 
					        this.keyword = keyword;
 | 
				
			||||||
 | 
					        this.type = type;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Nonnull
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public String getKeyword() {
 | 
				
			||||||
 | 
					        return keyword;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Nonnull
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public MPResultType getType() {
 | 
				
			||||||
 | 
					        return type;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void setType(final MPResultType type) {
 | 
				
			||||||
 | 
					        this.type = type;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Nonnull
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public String getAnswer(@Nullable final String state)
 | 
				
			||||||
 | 
					            throws MPKeyUnavailableException {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return getSite().getResult( MPKeyPurpose.Recovery, getKeyword(), null, getType(), state );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Nonnull
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public abstract MPBasicSite getSite();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public int hashCode() {
 | 
				
			||||||
 | 
					        return Objects.hashCode( getKeyword() );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public boolean equals(final Object obj) {
 | 
				
			||||||
 | 
					        return (this == obj) || ((obj instanceof MPQuestion) && Objects.equals( getKeyword(), ((MPQuestion) obj).getKeyword() ));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public int compareTo(@NotNull final MPQuestion o) {
 | 
				
			||||||
 | 
					        return getKeyword().compareTo( o.getKeyword() );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public String toString() {
 | 
				
			||||||
 | 
					        return strf( "{%s: %s}", getClass().getSimpleName(), getKeyword() );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,165 @@
 | 
				
			|||||||
 | 
					//==============================================================================
 | 
				
			||||||
 | 
					// This file is part of Master Password.
 | 
				
			||||||
 | 
					// Copyright (c) 2011-2017, Maarten Billemont.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Master Password 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.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Master Password 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/>.
 | 
				
			||||||
 | 
					//==============================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package com.lyndir.masterpassword.model.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import static com.lyndir.lhunath.opal.system.util.ObjectUtils.*;
 | 
				
			||||||
 | 
					import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.google.common.primitives.UnsignedInteger;
 | 
				
			||||||
 | 
					import com.lyndir.masterpassword.*;
 | 
				
			||||||
 | 
					import com.lyndir.masterpassword.model.MPQuestion;
 | 
				
			||||||
 | 
					import com.lyndir.masterpassword.model.MPSite;
 | 
				
			||||||
 | 
					import java.util.*;
 | 
				
			||||||
 | 
					import javax.annotation.Nullable;
 | 
				
			||||||
 | 
					import org.jetbrains.annotations.NotNull;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @author lhunath, 14-12-16
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public abstract class MPBasicSite implements MPSite {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private String          name;
 | 
				
			||||||
 | 
					    private MPAlgorithm     algorithm;
 | 
				
			||||||
 | 
					    private UnsignedInteger counter;
 | 
				
			||||||
 | 
					    private MPResultType    resultType;
 | 
				
			||||||
 | 
					    private MPResultType    loginType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private final Collection<MPFileQuestion> questions = new LinkedHashSet<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected MPBasicSite(final String name, final MPAlgorithm algorithm) {
 | 
				
			||||||
 | 
					        this( name, algorithm, null, null, null );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected MPBasicSite(final String name, final MPAlgorithm algorithm, @Nullable final UnsignedInteger counter,
 | 
				
			||||||
 | 
					                          @Nullable final MPResultType resultType, @Nullable final MPResultType loginType) {
 | 
				
			||||||
 | 
					        this.name = name;
 | 
				
			||||||
 | 
					        this.algorithm = algorithm;
 | 
				
			||||||
 | 
					        this.counter = (counter == null)? algorithm.mpw_default_counter(): counter;
 | 
				
			||||||
 | 
					        this.resultType = (resultType == null)? algorithm.mpw_default_result_type(): resultType;
 | 
				
			||||||
 | 
					        this.loginType = (loginType == null)? algorithm.mpw_default_login_type(): loginType;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public String getName() {
 | 
				
			||||||
 | 
					        return name;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void setName(final String name) {
 | 
				
			||||||
 | 
					        this.name = name;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public MPAlgorithm getAlgorithm() {
 | 
				
			||||||
 | 
					        return algorithm;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void setAlgorithm(final MPAlgorithm algorithm) {
 | 
				
			||||||
 | 
					        this.algorithm = algorithm;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public UnsignedInteger getCounter() {
 | 
				
			||||||
 | 
					        return counter;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void setCounter(final UnsignedInteger counter) {
 | 
				
			||||||
 | 
					        this.counter = counter;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public MPResultType getResultType() {
 | 
				
			||||||
 | 
					        return resultType;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void setResultType(final MPResultType resultType) {
 | 
				
			||||||
 | 
					        this.resultType = resultType;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public MPResultType getLoginType() {
 | 
				
			||||||
 | 
					        return loginType;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void setLoginType(@Nullable final MPResultType loginType) {
 | 
				
			||||||
 | 
					        this.loginType = ifNotNullElse( loginType, getAlgorithm().mpw_default_login_type() );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public String getResult(final MPKeyPurpose keyPurpose, @Nullable final String keyContext, @Nullable final String state)
 | 
				
			||||||
 | 
					            throws MPKeyUnavailableException {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return getResult( keyPurpose, keyContext, getCounter(), getResultType(), state );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected String getResult(final MPKeyPurpose keyPurpose, @Nullable final String keyContext,
 | 
				
			||||||
 | 
					                               @Nullable final UnsignedInteger counter, final MPResultType type, @Nullable final String state)
 | 
				
			||||||
 | 
					            throws MPKeyUnavailableException {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return getUser().getMasterKey().siteResult(
 | 
				
			||||||
 | 
					                getName(), ifNotNullElse( counter, getAlgorithm().mpw_default_counter() ), keyPurpose, keyContext,
 | 
				
			||||||
 | 
					                type, state, getAlgorithm() );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected String getState(final MPKeyPurpose keyPurpose, @Nullable final String keyContext,
 | 
				
			||||||
 | 
					                              @Nullable final UnsignedInteger counter, final MPResultType type, @Nullable final String state)
 | 
				
			||||||
 | 
					            throws MPKeyUnavailableException {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return getUser().getMasterKey().siteState(
 | 
				
			||||||
 | 
					                getName(), ifNotNullElse( counter, getAlgorithm().mpw_default_counter() ), keyPurpose, keyContext,
 | 
				
			||||||
 | 
					                type, state, getAlgorithm() );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public String getLogin(@Nullable final String state)
 | 
				
			||||||
 | 
					            throws MPKeyUnavailableException {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return getResult( MPKeyPurpose.Identification, null, null, getLoginType(), state );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public Collection<? extends MPQuestion> getQuestions() {
 | 
				
			||||||
 | 
					        return Collections.unmodifiableCollection( questions );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public int hashCode() {
 | 
				
			||||||
 | 
					        return Objects.hashCode( getName() );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public boolean equals(final Object obj) {
 | 
				
			||||||
 | 
					        return (this == obj) || ((obj instanceof MPSite) && Objects.equals( getName(), ((MPSite) obj).getName() ));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public int compareTo(@NotNull final MPSite o) {
 | 
				
			||||||
 | 
					        return getName().compareTo( o.getName() );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public String toString() {
 | 
				
			||||||
 | 
					        return strf( "{%s: %s}", getClass().getSimpleName(), getName() );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,186 @@
 | 
				
			|||||||
 | 
					//==============================================================================
 | 
				
			||||||
 | 
					// This file is part of Master Password.
 | 
				
			||||||
 | 
					// Copyright (c) 2011-2017, Maarten Billemont.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Master Password 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.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Master Password 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/>.
 | 
				
			||||||
 | 
					//==============================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package com.lyndir.masterpassword.model.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.google.common.collect.ImmutableList;
 | 
				
			||||||
 | 
					import com.lyndir.lhunath.opal.system.CodeUtils;
 | 
				
			||||||
 | 
					import com.lyndir.masterpassword.*;
 | 
				
			||||||
 | 
					import com.lyndir.masterpassword.model.MPIncorrectMasterPasswordException;
 | 
				
			||||||
 | 
					import com.lyndir.masterpassword.model.MPUser;
 | 
				
			||||||
 | 
					import java.util.*;
 | 
				
			||||||
 | 
					import javax.annotation.Nonnull;
 | 
				
			||||||
 | 
					import javax.annotation.Nullable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @author lhunath, 2014-06-08
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public abstract class MPBasicUser<S extends MPBasicSite> implements MPUser<S> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private       int         avatar;
 | 
				
			||||||
 | 
					    private final String      fullName;
 | 
				
			||||||
 | 
					    private       MPAlgorithm algorithm;
 | 
				
			||||||
 | 
					    @Nullable
 | 
				
			||||||
 | 
					    protected     MPMasterKey masterKey;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private final Collection<S> sites = new LinkedHashSet<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected MPBasicUser(final String fullName, final MPAlgorithm algorithm) {
 | 
				
			||||||
 | 
					        this( 0, fullName, algorithm );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected MPBasicUser(final int avatar, final String fullName, final MPAlgorithm algorithm) {
 | 
				
			||||||
 | 
					        this.avatar = avatar;
 | 
				
			||||||
 | 
					        this.fullName = fullName;
 | 
				
			||||||
 | 
					        this.algorithm = algorithm;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public int getAvatar() {
 | 
				
			||||||
 | 
					        return avatar;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void setAvatar(final int avatar) {
 | 
				
			||||||
 | 
					        this.avatar = avatar;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Nonnull
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public String getFullName() {
 | 
				
			||||||
 | 
					        return fullName;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Nonnull
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public MPAlgorithm getAlgorithm() {
 | 
				
			||||||
 | 
					        return algorithm;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void setAlgorithm(final MPAlgorithm algorithm) {
 | 
				
			||||||
 | 
					        this.algorithm = algorithm;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Nullable
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public byte[] getKeyID() {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            return getMasterKey().getKeyID( getAlgorithm() );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        catch (final MPKeyUnavailableException ignore) {
 | 
				
			||||||
 | 
					            return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Nullable
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public String exportKeyID() {
 | 
				
			||||||
 | 
					        return CodeUtils.encodeHex( getKeyID() );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void authenticate(final char[] masterPassword)
 | 
				
			||||||
 | 
					            throws MPIncorrectMasterPasswordException {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            authenticate( new MPMasterKey( getFullName(), masterPassword ) );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        catch (final MPKeyUnavailableException e) {
 | 
				
			||||||
 | 
					            throw new IllegalStateException( e );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void authenticate(final MPMasterKey masterKey)
 | 
				
			||||||
 | 
					            throws MPIncorrectMasterPasswordException, MPKeyUnavailableException {
 | 
				
			||||||
 | 
					        if (!masterKey.getFullName().equals( getFullName() ))
 | 
				
			||||||
 | 
					            throw new IllegalArgumentException(
 | 
				
			||||||
 | 
					                    "Master key (for " + masterKey.getFullName() + ") is not for this user (" + getFullName() + ")." );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        byte[] keyID = getKeyID();
 | 
				
			||||||
 | 
					        if ((keyID != null) && !Arrays.equals( masterKey.getKeyID( getAlgorithm() ), keyID ))
 | 
				
			||||||
 | 
					            throw new MPIncorrectMasterPasswordException( this );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.masterKey = masterKey;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public boolean isMasterKeyAvailable() {
 | 
				
			||||||
 | 
					        return masterKey != null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Nonnull
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public MPMasterKey getMasterKey()
 | 
				
			||||||
 | 
					            throws MPKeyUnavailableException {
 | 
				
			||||||
 | 
					        if (masterKey == null)
 | 
				
			||||||
 | 
					            throw new MPKeyUnavailableException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return masterKey;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void addSite(final S site) {
 | 
				
			||||||
 | 
					        sites.add( site );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void deleteSite(final S site) {
 | 
				
			||||||
 | 
					        sites.remove( site );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Nonnull
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public Collection<S> getSites() {
 | 
				
			||||||
 | 
					        return Collections.unmodifiableCollection( sites );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Nonnull
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public Collection<S> findSites(final String query) {
 | 
				
			||||||
 | 
					        ImmutableList.Builder<S> results = ImmutableList.builder();
 | 
				
			||||||
 | 
					        for (final S site : getSites())
 | 
				
			||||||
 | 
					            if (site.getName().startsWith( query ))
 | 
				
			||||||
 | 
					                results.add( site );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return results.build();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public int hashCode() {
 | 
				
			||||||
 | 
					        return Objects.hashCode( getFullName() );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public boolean equals(final Object obj) {
 | 
				
			||||||
 | 
					        return (this == obj) || ((obj instanceof MPUser) && Objects.equals( getFullName(), ((MPUser<?>) obj).getFullName() ));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public int compareTo(final MPUser<?> o) {
 | 
				
			||||||
 | 
					        return getFullName().compareTo( o.getFullName() );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public String toString() {
 | 
				
			||||||
 | 
					        return strf( "{%s: %s}", getClass().getSimpleName(), getFullName() );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -16,69 +16,52 @@
 | 
				
			|||||||
// LICENSE file.  Alternatively, see <http://www.gnu.org/licenses/>.
 | 
					// LICENSE file.  Alternatively, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
//==============================================================================
 | 
					//==============================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package com.lyndir.masterpassword.model;
 | 
					package com.lyndir.masterpassword.model.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static com.lyndir.lhunath.opal.system.util.ObjectUtils.ifNotNullElse;
 | 
					import static com.lyndir.lhunath.opal.system.util.ObjectUtils.ifNotNullElse;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.lyndir.masterpassword.*;
 | 
					import com.lyndir.masterpassword.*;
 | 
				
			||||||
 | 
					import javax.annotation.Nonnull;
 | 
				
			||||||
import javax.annotation.Nullable;
 | 
					import javax.annotation.Nullable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @author lhunath, 2018-05-14
 | 
					 * @author lhunath, 2018-05-14
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public class MPFileQuestion extends MPQuestion {
 | 
					public class MPFileQuestion extends MPBasicQuestion {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private final MPSite site;
 | 
					    private final MPFileSite site;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private String       keyword;
 | 
					 | 
				
			||||||
    @Nullable
 | 
					    @Nullable
 | 
				
			||||||
    private String       state;
 | 
					    private String       state;
 | 
				
			||||||
    private MPResultType type;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public MPFileQuestion(final MPSite site, final String keyword, @Nullable final String state, @Nullable final MPResultType type) {
 | 
					    public MPFileQuestion(final MPFileSite site, final String keyword,
 | 
				
			||||||
 | 
					                          @Nullable final MPResultType type, @Nullable final String state) {
 | 
				
			||||||
 | 
					        super( keyword, ifNotNullElse( type, site.getAlgorithm().mpw_default_answer_type() ) );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.site = site;
 | 
					        this.site = site;
 | 
				
			||||||
        this.keyword = keyword;
 | 
					 | 
				
			||||||
        this.state = state;
 | 
					        this.state = state;
 | 
				
			||||||
        this.type = ifNotNullElse( type, site.getAlgorithm().mpw_default_answer_type() );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public MPSite getSite() {
 | 
					 | 
				
			||||||
        return site;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public String getKeyword() {
 | 
					 | 
				
			||||||
        return keyword;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void setKeyword(final String keyword) {
 | 
					 | 
				
			||||||
        this.keyword = keyword;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void setAnswer(final MPResultType type, @Nullable final String answer)
 | 
					 | 
				
			||||||
            throws MPKeyUnavailableException {
 | 
					 | 
				
			||||||
        this.type = type;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (answer == null)
 | 
					 | 
				
			||||||
            this.state = null;
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            this.state = getSite().getState(
 | 
					 | 
				
			||||||
                    MPKeyPurpose.Recovery, getKeyword(), null, type, answer );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public MPResultType getType() {
 | 
					 | 
				
			||||||
        return type;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void setType(final MPResultType type) {
 | 
					 | 
				
			||||||
        this.type = type;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public String getAnswer()
 | 
					    public String getAnswer()
 | 
				
			||||||
            throws MPKeyUnavailableException {
 | 
					            throws MPKeyUnavailableException {
 | 
				
			||||||
        return getAnswer( state );
 | 
					        return getAnswer( state );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void setAnswer(final MPResultType type, @Nullable final String answer)
 | 
				
			||||||
 | 
					            throws MPKeyUnavailableException {
 | 
				
			||||||
 | 
					        setType( type );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (answer == null)
 | 
				
			||||||
 | 
					            this.state = null;
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            this.state = getSite().getState(
 | 
				
			||||||
 | 
					                    MPKeyPurpose.Recovery, getKeyword(), null, getType(), answer );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Nonnull
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public MPFileSite getSite() {
 | 
				
			||||||
 | 
					        return site;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,150 @@
 | 
				
			|||||||
 | 
					//==============================================================================
 | 
				
			||||||
 | 
					// This file is part of Master Password.
 | 
				
			||||||
 | 
					// Copyright (c) 2011-2017, Maarten Billemont.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Master Password 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.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Master Password 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/>.
 | 
				
			||||||
 | 
					//==============================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package com.lyndir.masterpassword.model.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.google.common.primitives.UnsignedInteger;
 | 
				
			||||||
 | 
					import com.lyndir.masterpassword.*;
 | 
				
			||||||
 | 
					import com.lyndir.masterpassword.model.MPUser;
 | 
				
			||||||
 | 
					import javax.annotation.Nonnull;
 | 
				
			||||||
 | 
					import javax.annotation.Nullable;
 | 
				
			||||||
 | 
					import org.joda.time.Instant;
 | 
				
			||||||
 | 
					import org.joda.time.ReadableInstant;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @author lhunath, 14-12-05
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public class MPFileSite extends MPBasicSite {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private final MPFileUser user;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Nullable
 | 
				
			||||||
 | 
					    private String          url;
 | 
				
			||||||
 | 
					    private int             uses;
 | 
				
			||||||
 | 
					    private ReadableInstant lastUsed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Nullable
 | 
				
			||||||
 | 
					    private String resultState;
 | 
				
			||||||
 | 
					    @Nullable
 | 
				
			||||||
 | 
					    private String loginState;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public MPFileSite(final MPFileUser user, final String name) {
 | 
				
			||||||
 | 
					        this( user, name, null, null, null );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public MPFileSite(final MPFileUser user, final String name,
 | 
				
			||||||
 | 
					                      @Nullable final MPAlgorithm algorithm, @Nullable final UnsignedInteger counter,
 | 
				
			||||||
 | 
					                      @Nullable final MPResultType resultType) {
 | 
				
			||||||
 | 
					        this( user, name, algorithm, counter, resultType, null,
 | 
				
			||||||
 | 
					              null, null, null, 0, new Instant() );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected MPFileSite(final MPFileUser user, final String name,
 | 
				
			||||||
 | 
					                         @Nullable final MPAlgorithm algorithm, @Nullable final UnsignedInteger counter,
 | 
				
			||||||
 | 
					                         @Nullable final MPResultType resultType, @Nullable final String resultState,
 | 
				
			||||||
 | 
					                         @Nullable final MPResultType loginType, @Nullable final String loginState,
 | 
				
			||||||
 | 
					                         @Nullable final String url, final int uses, final ReadableInstant lastUsed) {
 | 
				
			||||||
 | 
					        super( name, (algorithm == null)? user.getAlgorithm(): algorithm, counter, resultType, loginType );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.user = user;
 | 
				
			||||||
 | 
					        this.resultState = resultState;
 | 
				
			||||||
 | 
					        this.loginState = loginState;
 | 
				
			||||||
 | 
					        this.url = url;
 | 
				
			||||||
 | 
					        this.uses = uses;
 | 
				
			||||||
 | 
					        this.lastUsed = lastUsed;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Nullable
 | 
				
			||||||
 | 
					    public String getUrl() {
 | 
				
			||||||
 | 
					        return url;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void setUrl(@Nullable final String url) {
 | 
				
			||||||
 | 
					        this.url = url;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public int getUses() {
 | 
				
			||||||
 | 
					        return uses;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public ReadableInstant getLastUsed() {
 | 
				
			||||||
 | 
					        return lastUsed;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void use() {
 | 
				
			||||||
 | 
					        uses++;
 | 
				
			||||||
 | 
					        lastUsed = new Instant();
 | 
				
			||||||
 | 
					        user.use();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public String getResult()
 | 
				
			||||||
 | 
					            throws MPKeyUnavailableException {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return getResult( MPKeyPurpose.Authentication, null );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public String getResult(final MPKeyPurpose keyPurpose, @Nullable final String keyContext)
 | 
				
			||||||
 | 
					            throws MPKeyUnavailableException {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return getResult( keyPurpose, keyContext, getResultState() );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public String getLogin()
 | 
				
			||||||
 | 
					            throws MPKeyUnavailableException {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return getLogin( getLoginState() );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Nullable
 | 
				
			||||||
 | 
					    public String getResultState() {
 | 
				
			||||||
 | 
					        return resultState;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void setSitePassword(final MPResultType resultType, @Nullable final String password)
 | 
				
			||||||
 | 
					            throws MPKeyUnavailableException {
 | 
				
			||||||
 | 
					        setResultType( resultType );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (password == null)
 | 
				
			||||||
 | 
					            this.resultState = null;
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            this.resultState = getState(
 | 
				
			||||||
 | 
					                    MPKeyPurpose.Authentication, null, getCounter(), getResultType(), password );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Nullable
 | 
				
			||||||
 | 
					    public String getLoginState() {
 | 
				
			||||||
 | 
					        return loginState;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void setLoginName(@Nonnull final MPResultType loginType, @Nullable final String loginName)
 | 
				
			||||||
 | 
					            throws MPKeyUnavailableException {
 | 
				
			||||||
 | 
					        setLoginType( loginType );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (loginName == null)
 | 
				
			||||||
 | 
					            this.loginState = null;
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            this.loginState = getState(
 | 
				
			||||||
 | 
					                    MPKeyPurpose.Identification, null, null, getLoginType(), loginName );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public MPUser<? extends com.lyndir.masterpassword.model.MPSite> getUser() {
 | 
				
			||||||
 | 
					        return user;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -16,13 +16,12 @@
 | 
				
			|||||||
// LICENSE file.  Alternatively, see <http://www.gnu.org/licenses/>.
 | 
					// LICENSE file.  Alternatively, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
//==============================================================================
 | 
					//==============================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package com.lyndir.masterpassword.model;
 | 
					package com.lyndir.masterpassword.model.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.google.common.collect.ImmutableList;
 | 
					 | 
				
			||||||
import com.google.common.collect.Sets;
 | 
					 | 
				
			||||||
import com.lyndir.lhunath.opal.system.logging.Logger;
 | 
					import com.lyndir.lhunath.opal.system.logging.Logger;
 | 
				
			||||||
import com.lyndir.masterpassword.*;
 | 
					import com.lyndir.masterpassword.*;
 | 
				
			||||||
import java.util.*;
 | 
					import com.lyndir.masterpassword.model.MPIncorrectMasterPasswordException;
 | 
				
			||||||
 | 
					import com.lyndir.masterpassword.model.MPUser;
 | 
				
			||||||
import javax.annotation.Nonnull;
 | 
					import javax.annotation.Nonnull;
 | 
				
			||||||
import javax.annotation.Nullable;
 | 
					import javax.annotation.Nullable;
 | 
				
			||||||
import org.joda.time.Instant;
 | 
					import org.joda.time.Instant;
 | 
				
			||||||
@@ -33,21 +32,16 @@ import org.joda.time.ReadableInstant;
 | 
				
			|||||||
 * @author lhunath, 14-12-07
 | 
					 * @author lhunath, 14-12-07
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@SuppressWarnings("ComparableImplementedButEqualsNotOverridden")
 | 
					@SuppressWarnings("ComparableImplementedButEqualsNotOverridden")
 | 
				
			||||||
public class MPFileUser extends MPUser<MPFileSite> implements Comparable<MPFileUser> {
 | 
					public class MPFileUser extends MPBasicUser<MPFileSite> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @SuppressWarnings("UnusedDeclaration")
 | 
					    @SuppressWarnings("UnusedDeclaration")
 | 
				
			||||||
    private static final Logger logger = Logger.get( MPFileUser.class );
 | 
					    private static final Logger logger = Logger.get( MPFileUser.class );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private final String                 fullName;
 | 
					 | 
				
			||||||
    private final Collection<MPFileSite> sites = new LinkedHashSet<>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Nullable
 | 
					    @Nullable
 | 
				
			||||||
    private byte[]                   keyID;
 | 
					    private byte[]                   keyID;
 | 
				
			||||||
    private MPAlgorithm              algorithm;
 | 
					 | 
				
			||||||
    private MPMarshalFormat          format;
 | 
					    private MPMarshalFormat          format;
 | 
				
			||||||
    private MPMarshaller.ContentMode contentMode;
 | 
					    private MPMarshaller.ContentMode contentMode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private int             avatar;
 | 
					 | 
				
			||||||
    private MPResultType    defaultType;
 | 
					    private MPResultType    defaultType;
 | 
				
			||||||
    private ReadableInstant lastUsed;
 | 
					    private ReadableInstant lastUsed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -59,40 +53,43 @@ public class MPFileUser extends MPUser<MPFileSite> implements Comparable<MPFileU
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public MPFileUser(final String fullName, @Nullable final byte[] keyID, final MPAlgorithm algorithm) {
 | 
					    public MPFileUser(final String fullName, @Nullable final byte[] keyID, final MPAlgorithm algorithm) {
 | 
				
			||||||
        this( fullName, keyID, algorithm, 0, algorithm.mpw_default_password_type(), new Instant(),
 | 
					        this( fullName, keyID, algorithm, 0, algorithm.mpw_default_result_type(), new Instant(),
 | 
				
			||||||
              MPMarshalFormat.DEFAULT, MPMarshaller.ContentMode.PROTECTED );
 | 
					              MPMarshalFormat.DEFAULT, MPMarshaller.ContentMode.PROTECTED );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public MPFileUser(final String fullName, @Nullable final byte[] keyID, final MPAlgorithm algorithm, final int avatar,
 | 
					    public MPFileUser(final String fullName, @Nullable final byte[] keyID, final MPAlgorithm algorithm,
 | 
				
			||||||
                      final MPResultType defaultType, final ReadableInstant lastUsed,
 | 
					                      final int avatar, final MPResultType defaultType, final ReadableInstant lastUsed,
 | 
				
			||||||
                      final MPMarshalFormat format, final MPMarshaller.ContentMode contentMode) {
 | 
					                      final MPMarshalFormat format, final MPMarshaller.ContentMode contentMode) {
 | 
				
			||||||
        this.fullName = fullName;
 | 
					        super( avatar, fullName, algorithm );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.keyID = (keyID == null)? null: keyID.clone();
 | 
					        this.keyID = (keyID == null)? null: keyID.clone();
 | 
				
			||||||
        this.algorithm = algorithm;
 | 
					 | 
				
			||||||
        this.avatar = avatar;
 | 
					 | 
				
			||||||
        this.defaultType = defaultType;
 | 
					        this.defaultType = defaultType;
 | 
				
			||||||
        this.lastUsed = lastUsed;
 | 
					        this.lastUsed = lastUsed;
 | 
				
			||||||
        this.format = format;
 | 
					        this.format = format;
 | 
				
			||||||
        this.contentMode = contentMode;
 | 
					        this.contentMode = contentMode;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public String getFullName() {
 | 
					 | 
				
			||||||
        return fullName;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Nullable
 | 
					    @Nullable
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
    public byte[] getKeyID() {
 | 
					    public byte[] getKeyID() {
 | 
				
			||||||
        return (keyID == null)? null: keyID.clone();
 | 
					        return (keyID == null)? null: keyID.clone();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public MPAlgorithm getAlgorithm() {
 | 
					 | 
				
			||||||
        return algorithm;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void setAlgorithm(final MPAlgorithm algorithm) {
 | 
					    public void setAlgorithm(final MPAlgorithm algorithm) {
 | 
				
			||||||
        this.algorithm = algorithm;
 | 
					        if (!algorithm.equals( getAlgorithm() ) && (keyID != null)) {
 | 
				
			||||||
 | 
					            if (masterKey == null)
 | 
				
			||||||
 | 
					                throw new IllegalStateException( "Cannot update algorithm when keyID is set but masterKey is unavailable." );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                keyID = masterKey.getKeyID( algorithm );
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            catch (final MPKeyUnavailableException e) {
 | 
				
			||||||
 | 
					                throw new IllegalStateException( "Cannot update algorithm when keyID is set but masterKey is unavailable.", e );
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        super.setAlgorithm( algorithm );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public MPMarshalFormat getFormat() {
 | 
					    public MPMarshalFormat getFormat() {
 | 
				
			||||||
@@ -111,15 +108,6 @@ public class MPFileUser extends MPUser<MPFileSite> implements Comparable<MPFileU
 | 
				
			|||||||
        this.contentMode = contentMode;
 | 
					        this.contentMode = contentMode;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public int getAvatar() {
 | 
					 | 
				
			||||||
        return avatar;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void setAvatar(final int avatar) {
 | 
					 | 
				
			||||||
        this.avatar = avatar;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public MPResultType getDefaultType() {
 | 
					    public MPResultType getDefaultType() {
 | 
				
			||||||
        return defaultType;
 | 
					        return defaultType;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -136,30 +124,6 @@ public class MPFileUser extends MPUser<MPFileSite> implements Comparable<MPFileU
 | 
				
			|||||||
        lastUsed = new Instant();
 | 
					        lastUsed = new Instant();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public Collection<MPFileSite> getSites() {
 | 
					 | 
				
			||||||
        return Collections.unmodifiableCollection( sites );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public void addSite(final MPFileSite site) {
 | 
					 | 
				
			||||||
        sites.add( site );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public void deleteSite(final MPFileSite site) {
 | 
					 | 
				
			||||||
        sites.remove( site );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public Collection<MPFileSite> findSites(final String query) {
 | 
					 | 
				
			||||||
        ImmutableList.Builder<MPFileSite> results = ImmutableList.builder();
 | 
					 | 
				
			||||||
        for (final MPFileSite site : getSites())
 | 
					 | 
				
			||||||
            if (site.getSiteName().startsWith( query ))
 | 
					 | 
				
			||||||
                results.add( site );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return results.build();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void setJSON(final MPJSONFile json) {
 | 
					    public void setJSON(final MPJSONFile json) {
 | 
				
			||||||
        this.json = json;
 | 
					        this.json = json;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -169,33 +133,13 @@ public class MPFileUser extends MPUser<MPFileSite> implements Comparable<MPFileU
 | 
				
			|||||||
        return (json == null)? json = new MPJSONFile(): json;
 | 
					        return (json == null)? json = new MPJSONFile(): json;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Performs an authentication attempt against the keyID for this user.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * Note: If this user doesn't have a keyID set yet, authentication will always succeed and the key ID will be set as a result.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param masterPassword The password to authenticate with.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return The master key for the user if authentication was successful.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @throws MPIncorrectMasterPasswordException If authentication fails due to the given master password not matching the user's keyID.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    @Nonnull
 | 
					 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public MPMasterKey authenticate(final char[] masterPassword)
 | 
					    public void authenticate(final MPMasterKey masterKey)
 | 
				
			||||||
            throws MPIncorrectMasterPasswordException {
 | 
					            throws MPIncorrectMasterPasswordException, MPKeyUnavailableException {
 | 
				
			||||||
        try {
 | 
					        super.authenticate( masterKey );
 | 
				
			||||||
            key = new MPMasterKey( getFullName(), masterPassword );
 | 
					 | 
				
			||||||
            if ((keyID == null) || (keyID.length == 0))
 | 
					 | 
				
			||||||
                keyID = key.getKeyID( algorithm );
 | 
					 | 
				
			||||||
            else if (!Arrays.equals( key.getKeyID( algorithm ), keyID ))
 | 
					 | 
				
			||||||
                throw new MPIncorrectMasterPasswordException( this );
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return key;
 | 
					        if (keyID == null)
 | 
				
			||||||
        }
 | 
					            keyID = masterKey.getKeyID( getAlgorithm() );
 | 
				
			||||||
        catch (final MPKeyUnavailableException e) {
 | 
					 | 
				
			||||||
            throw logger.bug( e );
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void save()
 | 
					    void save()
 | 
				
			||||||
@@ -204,11 +148,11 @@ public class MPFileUser extends MPUser<MPFileSite> implements Comparable<MPFileU
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public int compareTo(final MPFileUser o) {
 | 
					    public int compareTo(final MPUser<?> o) {
 | 
				
			||||||
        int comparison = getLastUsed().compareTo( o.getLastUsed() );
 | 
					        int comparison = (o instanceof MPFileUser)? getLastUsed().compareTo( ((MPFileUser) o).getLastUsed() ): 0;
 | 
				
			||||||
        if (comparison == 0)
 | 
					        if (comparison != 0)
 | 
				
			||||||
            comparison = getFullName().compareTo( o.getFullName() );
 | 
					            return comparison;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return comparison;
 | 
					        return super.compareTo( o );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -16,7 +16,7 @@
 | 
				
			|||||||
// LICENSE file.  Alternatively, see <http://www.gnu.org/licenses/>.
 | 
					// LICENSE file.  Alternatively, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
//==============================================================================
 | 
					//==============================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package com.lyndir.masterpassword.model;
 | 
					package com.lyndir.masterpassword.model.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static com.lyndir.lhunath.opal.system.util.ObjectUtils.*;
 | 
					import static com.lyndir.lhunath.opal.system.util.ObjectUtils.*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -25,6 +25,7 @@ import com.google.common.collect.ImmutableList;
 | 
				
			|||||||
import com.google.common.io.CharSink;
 | 
					import com.google.common.io.CharSink;
 | 
				
			||||||
import com.lyndir.lhunath.opal.system.logging.Logger;
 | 
					import com.lyndir.lhunath.opal.system.logging.Logger;
 | 
				
			||||||
import com.lyndir.masterpassword.*;
 | 
					import com.lyndir.masterpassword.*;
 | 
				
			||||||
 | 
					import com.lyndir.masterpassword.model.*;
 | 
				
			||||||
import java.io.*;
 | 
					import java.io.*;
 | 
				
			||||||
import java.util.HashMap;
 | 
					import java.util.HashMap;
 | 
				
			||||||
import java.util.Map;
 | 
					import java.util.Map;
 | 
				
			||||||
@@ -37,7 +38,7 @@ import javax.annotation.Nonnull;
 | 
				
			|||||||
 * @author lhunath, 14-12-07
 | 
					 * @author lhunath, 14-12-07
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@SuppressWarnings("CallToSystemGetenv")
 | 
					@SuppressWarnings("CallToSystemGetenv")
 | 
				
			||||||
public class MPFileUserManager extends MPUserManager {
 | 
					public class MPFileUserManager extends MPUserManager<MPFileUser> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @SuppressWarnings("UnusedDeclaration")
 | 
					    @SuppressWarnings("UnusedDeclaration")
 | 
				
			||||||
    private static final Logger            logger = Logger.get( MPFileUserManager.class );
 | 
					    private static final Logger            logger = Logger.get( MPFileUserManager.class );
 | 
				
			||||||
@@ -137,7 +138,7 @@ public class MPFileUserManager extends MPUserManager {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Nonnull
 | 
					    @Nonnull
 | 
				
			||||||
    private File getUserFile(final MPFileUser user, final MPMarshalFormat format) {
 | 
					    private File getUserFile(final MPUser<?> user, final MPMarshalFormat format) {
 | 
				
			||||||
        return new File( path, user.getFullName() + format.fileSuffix() );
 | 
					        return new File( path, user.getFullName() + format.fileSuffix() );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -16,7 +16,7 @@
 | 
				
			|||||||
// LICENSE file.  Alternatively, see <http://www.gnu.org/licenses/>.
 | 
					// LICENSE file.  Alternatively, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
//==============================================================================
 | 
					//==============================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package com.lyndir.masterpassword.model;
 | 
					package com.lyndir.masterpassword.model.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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.*;
 | 
					import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
 | 
				
			||||||
@@ -59,7 +59,7 @@ public class MPFlatMarshaller implements MPMarshaller {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        for (final MPFileSite site : user.getSites()) {
 | 
					        for (final MPFileSite site : user.getSites()) {
 | 
				
			||||||
            String loginName = site.getLoginState();
 | 
					            String loginName = site.getLoginState();
 | 
				
			||||||
            String password  = site.getSiteState();
 | 
					            String password  = site.getResultState();
 | 
				
			||||||
            if (!user.getContentMode().isRedacted()) {
 | 
					            if (!user.getContentMode().isRedacted()) {
 | 
				
			||||||
                loginName = site.getLogin();
 | 
					                loginName = site.getLogin();
 | 
				
			||||||
                password = site.getResult();
 | 
					                password = site.getResult();
 | 
				
			||||||
@@ -71,9 +71,9 @@ public class MPFlatMarshaller implements MPMarshaller {
 | 
				
			|||||||
                                  strf( "%d:%d:%d", //
 | 
					                                  strf( "%d:%d:%d", //
 | 
				
			||||||
                                        site.getResultType().getType(), // type
 | 
					                                        site.getResultType().getType(), // type
 | 
				
			||||||
                                        site.getAlgorithm().version().toInt(), // algorithm
 | 
					                                        site.getAlgorithm().version().toInt(), // algorithm
 | 
				
			||||||
                                        site.getSiteCounter().intValue() ), // counter
 | 
					                                        site.getCounter().intValue() ), // counter
 | 
				
			||||||
                                  ifNotNullElse( loginName, "" ), // loginName
 | 
					                                  ifNotNullElse( loginName, "" ), // loginName
 | 
				
			||||||
                                  site.getSiteName(), // siteName
 | 
					                                  site.getName(), // siteName
 | 
				
			||||||
                                  ifNotNullElse( password, "" ) // password
 | 
					                                  ifNotNullElse( password, "" ) // password
 | 
				
			||||||
            ) );
 | 
					            ) );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -16,7 +16,7 @@
 | 
				
			|||||||
// LICENSE file.  Alternatively, see <http://www.gnu.org/licenses/>.
 | 
					// LICENSE file.  Alternatively, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
//==============================================================================
 | 
					//==============================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package com.lyndir.masterpassword.model;
 | 
					package com.lyndir.masterpassword.model.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.google.common.base.*;
 | 
					import com.google.common.base.*;
 | 
				
			||||||
import com.google.common.io.CharStreams;
 | 
					import com.google.common.io.CharStreams;
 | 
				
			||||||
@@ -25,6 +25,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.ConversionUtils;
 | 
					import com.lyndir.lhunath.opal.system.util.ConversionUtils;
 | 
				
			||||||
import com.lyndir.masterpassword.*;
 | 
					import com.lyndir.masterpassword.*;
 | 
				
			||||||
 | 
					import com.lyndir.masterpassword.model.MPIncorrectMasterPasswordException;
 | 
				
			||||||
import java.io.*;
 | 
					import java.io.*;
 | 
				
			||||||
import java.util.regex.Matcher;
 | 
					import java.util.regex.Matcher;
 | 
				
			||||||
import java.util.regex.Pattern;
 | 
					import java.util.regex.Pattern;
 | 
				
			||||||
@@ -115,11 +116,11 @@ public class MPFlatUnmarshaller implements MPUnmarshaller {
 | 
				
			|||||||
                switch (importFormat) {
 | 
					                switch (importFormat) {
 | 
				
			||||||
                    case 0:
 | 
					                    case 0:
 | 
				
			||||||
                        site = new MPFileSite( user, //
 | 
					                        site = new MPFileSite( user, //
 | 
				
			||||||
                                               siteMatcher.group( 5 ), clearContent? null: siteMatcher.group( 6 ),
 | 
					                                               siteMatcher.group( 5 ), MPMasterKey.Version.fromInt( ConversionUtils.toIntegerNN(
 | 
				
			||||||
 | 
					                                                       colon.matcher( siteMatcher.group( 4 ) ).replaceAll( "" ) ) ).getAlgorithm(),
 | 
				
			||||||
                                               user.getAlgorithm().mpw_default_counter(),
 | 
					                                               user.getAlgorithm().mpw_default_counter(),
 | 
				
			||||||
                                               MPResultType.forType( ConversionUtils.toIntegerNN( siteMatcher.group( 3 ) ) ),
 | 
					                                               MPResultType.forType( ConversionUtils.toIntegerNN( siteMatcher.group( 3 ) ) ),
 | 
				
			||||||
                                               MPMasterKey.Version.fromInt( ConversionUtils.toIntegerNN(
 | 
					                                               clearContent? null: siteMatcher.group( 6 ),
 | 
				
			||||||
                                                       colon.matcher( siteMatcher.group( 4 ) ).replaceAll( "" ) ) ).getAlgorithm(),
 | 
					 | 
				
			||||||
                                               null, null, null, ConversionUtils.toIntegerNN( siteMatcher.group( 2 ) ),
 | 
					                                               null, null, null, ConversionUtils.toIntegerNN( siteMatcher.group( 2 ) ),
 | 
				
			||||||
                                               MPConstant.dateTimeFormatter.parseDateTime( siteMatcher.group( 1 ) ).toInstant() );
 | 
					                                               MPConstant.dateTimeFormatter.parseDateTime( siteMatcher.group( 1 ) ).toInstant() );
 | 
				
			||||||
                        if (clearContent)
 | 
					                        if (clearContent)
 | 
				
			||||||
@@ -128,12 +129,12 @@ public class MPFlatUnmarshaller implements MPUnmarshaller {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                    case 1:
 | 
					                    case 1:
 | 
				
			||||||
                        site = new MPFileSite( user, //
 | 
					                        site = new MPFileSite( user, //
 | 
				
			||||||
                                               siteMatcher.group( 7 ), clearContent? null: siteMatcher.group( 8 ),
 | 
					                                               siteMatcher.group( 7 ), MPMasterKey.Version.fromInt( ConversionUtils.toIntegerNN(
 | 
				
			||||||
 | 
					                                                       colon.matcher( siteMatcher.group( 4 ) ).replaceAll( "" ) ) ).getAlgorithm(),
 | 
				
			||||||
                                               UnsignedInteger.valueOf( colon.matcher( siteMatcher.group( 5 ) ).replaceAll( "" ) ),
 | 
					                                               UnsignedInteger.valueOf( colon.matcher( siteMatcher.group( 5 ) ).replaceAll( "" ) ),
 | 
				
			||||||
                                               MPResultType.forType( ConversionUtils.toIntegerNN( siteMatcher.group( 3 ) ) ),
 | 
					                                               MPResultType.forType( ConversionUtils.toIntegerNN( siteMatcher.group( 3 ) ) ),
 | 
				
			||||||
                                               MPMasterKey.Version.fromInt( ConversionUtils.toIntegerNN(
 | 
					                                               clearContent? null: siteMatcher.group( 8 ),
 | 
				
			||||||
                                                       colon.matcher( siteMatcher.group( 4 ) ).replaceAll( "" ) ) ).getAlgorithm(),
 | 
					                                               MPResultType.GeneratedName, clearContent? null: siteMatcher.group( 6 ), null,
 | 
				
			||||||
                                               clearContent? null: siteMatcher.group( 6 ), MPResultType.GeneratedName, null,
 | 
					 | 
				
			||||||
                                               ConversionUtils.toIntegerNN( siteMatcher.group( 2 ) ),
 | 
					                                               ConversionUtils.toIntegerNN( siteMatcher.group( 2 ) ),
 | 
				
			||||||
                                               MPConstant.dateTimeFormatter.parseDateTime( siteMatcher.group( 1 ) ).toInstant() );
 | 
					                                               MPConstant.dateTimeFormatter.parseDateTime( siteMatcher.group( 1 ) ).toInstant() );
 | 
				
			||||||
                        if (clearContent) {
 | 
					                        if (clearContent) {
 | 
				
			||||||
@@ -16,7 +16,7 @@
 | 
				
			|||||||
// LICENSE file.  Alternatively, see <http://www.gnu.org/licenses/>.
 | 
					// LICENSE file.  Alternatively, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
//==============================================================================
 | 
					//==============================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package com.lyndir.masterpassword.model;
 | 
					package com.lyndir.masterpassword.model.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.fasterxml.jackson.annotation.JsonAnyGetter;
 | 
					import com.fasterxml.jackson.annotation.JsonAnyGetter;
 | 
				
			||||||
import com.fasterxml.jackson.annotation.JsonAnySetter;
 | 
					import com.fasterxml.jackson.annotation.JsonAnySetter;
 | 
				
			||||||
@@ -16,20 +16,16 @@
 | 
				
			|||||||
// LICENSE file.  Alternatively, see <http://www.gnu.org/licenses/>.
 | 
					// LICENSE file.  Alternatively, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
//==============================================================================
 | 
					//==============================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package com.lyndir.masterpassword.model;
 | 
					package com.lyndir.masterpassword.model.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static com.lyndir.lhunath.opal.system.util.ObjectUtils.*;
 | 
					import static com.lyndir.lhunath.opal.system.util.ObjectUtils.*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.fasterxml.jackson.annotation.*;
 | 
					import com.fasterxml.jackson.annotation.*;
 | 
				
			||||||
import com.fasterxml.jackson.core.*;
 | 
					 | 
				
			||||||
import com.fasterxml.jackson.databind.*;
 | 
					import com.fasterxml.jackson.databind.*;
 | 
				
			||||||
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
 | 
					 | 
				
			||||||
import com.fasterxml.jackson.databind.module.SimpleModule;
 | 
					 | 
				
			||||||
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
 | 
					 | 
				
			||||||
import com.google.common.primitives.UnsignedInteger;
 | 
					import com.google.common.primitives.UnsignedInteger;
 | 
				
			||||||
import com.lyndir.lhunath.opal.system.CodeUtils;
 | 
					import com.lyndir.lhunath.opal.system.CodeUtils;
 | 
				
			||||||
import com.lyndir.masterpassword.*;
 | 
					import com.lyndir.masterpassword.*;
 | 
				
			||||||
import java.io.IOException;
 | 
					import com.lyndir.masterpassword.model.MPIncorrectMasterPasswordException;
 | 
				
			||||||
import java.util.*;
 | 
					import java.util.*;
 | 
				
			||||||
import javax.annotation.Nullable;
 | 
					import javax.annotation.Nullable;
 | 
				
			||||||
import org.joda.time.Instant;
 | 
					import org.joda.time.Instant;
 | 
				
			||||||
@@ -62,7 +58,7 @@ public class MPJSONFile extends MPJSONAnyObject {
 | 
				
			|||||||
        user.avatar = modelUser.getAvatar();
 | 
					        user.avatar = modelUser.getAvatar();
 | 
				
			||||||
        user.full_name = modelUser.getFullName();
 | 
					        user.full_name = modelUser.getFullName();
 | 
				
			||||||
        user.last_used = MPConstant.dateTimeFormatter.print( modelUser.getLastUsed() );
 | 
					        user.last_used = MPConstant.dateTimeFormatter.print( modelUser.getLastUsed() );
 | 
				
			||||||
        user.key_id = CodeUtils.encodeHex( modelUser.getKeyID() );
 | 
					        user.key_id = modelUser.exportKeyID();
 | 
				
			||||||
        user.algorithm = modelUser.getAlgorithm().version();
 | 
					        user.algorithm = modelUser.getAlgorithm().version();
 | 
				
			||||||
        user.default_type = modelUser.getDefaultType();
 | 
					        user.default_type = modelUser.getDefaultType();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -75,21 +71,21 @@ public class MPJSONFile extends MPJSONAnyObject {
 | 
				
			|||||||
                // Clear Text
 | 
					                // Clear Text
 | 
				
			||||||
                content = modelSite.getResult();
 | 
					                content = modelSite.getResult();
 | 
				
			||||||
                loginContent = modelUser.getMasterKey().siteResult(
 | 
					                loginContent = modelUser.getMasterKey().siteResult(
 | 
				
			||||||
                        modelSite.getSiteName(), modelSite.getAlgorithm().mpw_default_counter(),
 | 
					                        modelSite.getName(), modelSite.getAlgorithm().mpw_default_counter(),
 | 
				
			||||||
                        MPKeyPurpose.Identification, null, modelSite.getLoginType(), modelSite.getLoginState(), modelSite.getAlgorithm() );
 | 
					                        MPKeyPurpose.Identification, null, modelSite.getLoginType(), modelSite.getLoginState(), modelSite.getAlgorithm() );
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                // Redacted
 | 
					                // Redacted
 | 
				
			||||||
                if (modelSite.getResultType().supportsTypeFeature( MPSiteFeature.ExportContent ))
 | 
					                if (modelSite.getResultType().supportsTypeFeature( MPSiteFeature.ExportContent ))
 | 
				
			||||||
                    content = modelSite.getSiteState();
 | 
					                    content = modelSite.getResultState();
 | 
				
			||||||
                if (modelSite.getLoginType().supportsTypeFeature( MPSiteFeature.ExportContent ))
 | 
					                if (modelSite.getLoginType().supportsTypeFeature( MPSiteFeature.ExportContent ))
 | 
				
			||||||
                    loginContent = modelSite.getLoginState();
 | 
					                    loginContent = modelSite.getLoginState();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Site site = sites.get( modelSite.getSiteName() );
 | 
					            Site site = sites.get( modelSite.getName() );
 | 
				
			||||||
            if (site == null)
 | 
					            if (site == null)
 | 
				
			||||||
                sites.put( modelSite.getSiteName(), site = new Site() );
 | 
					                sites.put( modelSite.getName(), site = new Site() );
 | 
				
			||||||
            site.type = modelSite.getResultType();
 | 
					            site.type = modelSite.getResultType();
 | 
				
			||||||
            site.counter = modelSite.getSiteCounter().longValue();
 | 
					            site.counter = modelSite.getCounter().longValue();
 | 
				
			||||||
            site.algorithm = modelSite.getAlgorithm().version();
 | 
					            site.algorithm = modelSite.getAlgorithm().version();
 | 
				
			||||||
            site.password = content;
 | 
					            site.password = content;
 | 
				
			||||||
            site.login_name = loginContent;
 | 
					            site.login_name = loginContent;
 | 
				
			||||||
@@ -140,7 +136,7 @@ public class MPJSONFile extends MPJSONAnyObject {
 | 
				
			|||||||
        MPAlgorithm algorithm = ifNotNullElse( user.algorithm, MPMasterKey.Version.CURRENT ).getAlgorithm();
 | 
					        MPAlgorithm algorithm = ifNotNullElse( user.algorithm, MPMasterKey.Version.CURRENT ).getAlgorithm();
 | 
				
			||||||
        MPFileUser model = new MPFileUser(
 | 
					        MPFileUser model = new MPFileUser(
 | 
				
			||||||
                user.full_name, CodeUtils.decodeHex( user.key_id ), algorithm, user.avatar,
 | 
					                user.full_name, CodeUtils.decodeHex( user.key_id ), algorithm, user.avatar,
 | 
				
			||||||
                (user.default_type != null)? user.default_type: algorithm.mpw_default_password_type(),
 | 
					                (user.default_type != null)? user.default_type: algorithm.mpw_default_result_type(),
 | 
				
			||||||
                (user.last_used != null)? MPConstant.dateTimeFormatter.parseDateTime( user.last_used ): new Instant(),
 | 
					                (user.last_used != null)? MPConstant.dateTimeFormatter.parseDateTime( user.last_used ): new Instant(),
 | 
				
			||||||
                MPMarshalFormat.JSON, export.redacted? MPMarshaller.ContentMode.PROTECTED: MPMarshaller.ContentMode.VISIBLE );
 | 
					                MPMarshalFormat.JSON, export.redacted? MPMarshaller.ContentMode.PROTECTED: MPMarshaller.ContentMode.VISIBLE );
 | 
				
			||||||
        model.setJSON( this );
 | 
					        model.setJSON( this );
 | 
				
			||||||
@@ -151,9 +147,9 @@ public class MPJSONFile extends MPJSONAnyObject {
 | 
				
			|||||||
            String siteName = siteEntry.getKey();
 | 
					            String siteName = siteEntry.getKey();
 | 
				
			||||||
            Site   fileSite = siteEntry.getValue();
 | 
					            Site   fileSite = siteEntry.getValue();
 | 
				
			||||||
            MPFileSite site = new MPFileSite(
 | 
					            MPFileSite site = new MPFileSite(
 | 
				
			||||||
                    model, siteName, export.redacted? fileSite.password: null, UnsignedInteger.valueOf( fileSite.counter ),
 | 
					                    model, siteName, fileSite.algorithm.getAlgorithm(), UnsignedInteger.valueOf( fileSite.counter ), fileSite.type,
 | 
				
			||||||
                    fileSite.type, fileSite.algorithm.getAlgorithm(),
 | 
					                    export.redacted? fileSite.password: null,
 | 
				
			||||||
                    export.redacted? fileSite.login_name: null, fileSite.login_type,
 | 
					                    fileSite.login_type, export.redacted? fileSite.login_name: null,
 | 
				
			||||||
                    (fileSite._ext_mpw != null)? fileSite._ext_mpw.url: null, fileSite.uses,
 | 
					                    (fileSite._ext_mpw != null)? fileSite._ext_mpw.url: null, fileSite.uses,
 | 
				
			||||||
                    (fileSite.last_used != null)? MPConstant.dateTimeFormatter.parseDateTime( fileSite.last_used ): new Instant() );
 | 
					                    (fileSite.last_used != null)? MPConstant.dateTimeFormatter.parseDateTime( fileSite.last_used ): new Instant() );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -16,9 +16,9 @@
 | 
				
			|||||||
// LICENSE file.  Alternatively, see <http://www.gnu.org/licenses/>.
 | 
					// LICENSE file.  Alternatively, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
//==============================================================================
 | 
					//==============================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package com.lyndir.masterpassword.model;
 | 
					package com.lyndir.masterpassword.model.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static com.lyndir.masterpassword.model.MPJSONFile.objectMapper;
 | 
					import static com.lyndir.masterpassword.model.impl.MPJSONFile.objectMapper;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.fasterxml.jackson.core.JsonProcessingException;
 | 
					import com.fasterxml.jackson.core.JsonProcessingException;
 | 
				
			||||||
import com.lyndir.masterpassword.MPKeyUnavailableException;
 | 
					import com.lyndir.masterpassword.MPKeyUnavailableException;
 | 
				
			||||||
@@ -16,13 +16,14 @@
 | 
				
			|||||||
// LICENSE file.  Alternatively, see <http://www.gnu.org/licenses/>.
 | 
					// LICENSE file.  Alternatively, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
//==============================================================================
 | 
					//==============================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package com.lyndir.masterpassword.model;
 | 
					package com.lyndir.masterpassword.model.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static com.lyndir.masterpassword.model.MPJSONFile.objectMapper;
 | 
					import static com.lyndir.masterpassword.model.impl.MPJSONFile.objectMapper;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.fasterxml.jackson.core.JsonParseException;
 | 
					import com.fasterxml.jackson.core.JsonParseException;
 | 
				
			||||||
import com.fasterxml.jackson.databind.JsonMappingException;
 | 
					import com.fasterxml.jackson.databind.JsonMappingException;
 | 
				
			||||||
import com.lyndir.masterpassword.MPKeyUnavailableException;
 | 
					import com.lyndir.masterpassword.MPKeyUnavailableException;
 | 
				
			||||||
 | 
					import com.lyndir.masterpassword.model.MPIncorrectMasterPasswordException;
 | 
				
			||||||
import java.io.File;
 | 
					import java.io.File;
 | 
				
			||||||
import java.io.IOException;
 | 
					import java.io.IOException;
 | 
				
			||||||
import javax.annotation.Nonnull;
 | 
					import javax.annotation.Nonnull;
 | 
				
			||||||
@@ -16,7 +16,7 @@
 | 
				
			|||||||
// LICENSE file.  Alternatively, see <http://www.gnu.org/licenses/>.
 | 
					// LICENSE file.  Alternatively, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
//==============================================================================
 | 
					//==============================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package com.lyndir.masterpassword.model;
 | 
					package com.lyndir.masterpassword.model.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @author lhunath, 2018-04-26
 | 
					 * @author lhunath, 2018-04-26
 | 
				
			||||||
@@ -16,7 +16,7 @@
 | 
				
			|||||||
// LICENSE file.  Alternatively, see <http://www.gnu.org/licenses/>.
 | 
					// LICENSE file.  Alternatively, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
//==============================================================================
 | 
					//==============================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package com.lyndir.masterpassword.model;
 | 
					package com.lyndir.masterpassword.model.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @author lhunath, 2017-09-20
 | 
					 * @author lhunath, 2017-09-20
 | 
				
			||||||
@@ -16,7 +16,7 @@
 | 
				
			|||||||
// LICENSE file.  Alternatively, see <http://www.gnu.org/licenses/>.
 | 
					// LICENSE file.  Alternatively, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
//==============================================================================
 | 
					//==============================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package com.lyndir.masterpassword.model;
 | 
					package com.lyndir.masterpassword.model.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.lyndir.masterpassword.MPKeyUnavailableException;
 | 
					import com.lyndir.masterpassword.MPKeyUnavailableException;
 | 
				
			||||||
import javax.annotation.Nonnull;
 | 
					import javax.annotation.Nonnull;
 | 
				
			||||||
@@ -16,9 +16,10 @@
 | 
				
			|||||||
// LICENSE file.  Alternatively, see <http://www.gnu.org/licenses/>.
 | 
					// LICENSE file.  Alternatively, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
//==============================================================================
 | 
					//==============================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package com.lyndir.masterpassword.model;
 | 
					package com.lyndir.masterpassword.model.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.lyndir.masterpassword.MPKeyUnavailableException;
 | 
					import com.lyndir.masterpassword.MPKeyUnavailableException;
 | 
				
			||||||
 | 
					import com.lyndir.masterpassword.model.MPIncorrectMasterPasswordException;
 | 
				
			||||||
import java.io.File;
 | 
					import java.io.File;
 | 
				
			||||||
import java.io.IOException;
 | 
					import java.io.IOException;
 | 
				
			||||||
import javax.annotation.Nonnull;
 | 
					import javax.annotation.Nonnull;
 | 
				
			||||||
@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					//==============================================================================
 | 
				
			||||||
 | 
					// This file is part of Master Password.
 | 
				
			||||||
 | 
					// Copyright (c) 2011-2017, Maarten Billemont.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Master Password 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.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Master Password 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/>.
 | 
				
			||||||
 | 
					//==============================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @author lhunath, 2018-05-14
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					@ParametersAreNonnullByDefault
 | 
				
			||||||
 | 
					package com.lyndir.masterpassword.model.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import javax.annotation.ParametersAreNonnullByDefault;
 | 
				
			||||||
@@ -148,7 +148,7 @@ public final class Preferences {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Nonnull
 | 
					    @Nonnull
 | 
				
			||||||
    public MPResultType getDefaultResultType() {
 | 
					    public MPResultType getDefaultResultType() {
 | 
				
			||||||
        return MPResultType.values()[prefs().getInt( PREF_RESULT_TYPE, getDefaultVersion().getAlgorithm().mpw_default_password_type().ordinal() )];
 | 
					        return MPResultType.values()[prefs().getInt( PREF_RESULT_TYPE, getDefaultVersion().getAlgorithm().mpw_default_result_type().ordinal() )];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public boolean setDefaultVersion(final MPMasterKey.Version value) {
 | 
					    public boolean setDefaultVersion(final MPMasterKey.Version value) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,97 +18,32 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package com.lyndir.masterpassword.gui.model;
 | 
					package com.lyndir.masterpassword.gui.model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static com.lyndir.lhunath.opal.system.util.ObjectUtils.ifNotNullElse;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import com.google.common.collect.ImmutableCollection;
 | 
					 | 
				
			||||||
import com.google.common.collect.ImmutableList;
 | 
					import com.google.common.collect.ImmutableList;
 | 
				
			||||||
import com.google.common.primitives.UnsignedInteger;
 | 
					 | 
				
			||||||
import com.lyndir.masterpassword.MPAlgorithm;
 | 
					 | 
				
			||||||
import com.lyndir.masterpassword.MPResultType;
 | 
					 | 
				
			||||||
import com.lyndir.masterpassword.model.*;
 | 
					import com.lyndir.masterpassword.model.*;
 | 
				
			||||||
 | 
					import com.lyndir.masterpassword.model.impl.MPBasicSite;
 | 
				
			||||||
import java.util.Collection;
 | 
					import java.util.Collection;
 | 
				
			||||||
import javax.annotation.Nullable;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @author lhunath, 14-12-16
 | 
					 * @author lhunath, 14-12-16
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public class IncognitoSite extends MPSite {
 | 
					public class IncognitoSite extends MPBasicSite {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private final IncognitoUser user;
 | 
					    private final IncognitoUser user;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private String          siteName;
 | 
					    public IncognitoSite(final IncognitoUser user, final String siteName) {
 | 
				
			||||||
    private UnsignedInteger siteCounter;
 | 
					        super( siteName, user.getAlgorithm() );
 | 
				
			||||||
    private MPResultType    resultType;
 | 
					 | 
				
			||||||
    private MPResultType loginType;
 | 
					 | 
				
			||||||
    private MPAlgorithm     algorithm;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public IncognitoSite(final IncognitoUser user, final String siteName, final UnsignedInteger siteCounter, final MPResultType resultType,
 | 
					 | 
				
			||||||
                         final MPAlgorithm algorithm) {
 | 
					 | 
				
			||||||
        this.user = user;
 | 
					        this.user = user;
 | 
				
			||||||
        this.siteName = siteName;
 | 
					 | 
				
			||||||
        this.siteCounter = siteCounter;
 | 
					 | 
				
			||||||
        this.resultType = resultType;
 | 
					 | 
				
			||||||
        this.algorithm = algorithm;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public MPUser<?> getUser() {
 | 
					    public MPUser<? extends MPSite> getUser() {
 | 
				
			||||||
        return user;
 | 
					        return user;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public String getSiteName() {
 | 
					 | 
				
			||||||
        return siteName;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public void setSiteName(final String siteName) {
 | 
					 | 
				
			||||||
        this.siteName = siteName;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public MPResultType getResultType() {
 | 
					 | 
				
			||||||
        return resultType;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public void setResultType(final MPResultType resultType) {
 | 
					 | 
				
			||||||
        this.resultType = resultType;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public MPResultType getLoginType() {
 | 
					 | 
				
			||||||
        return loginType;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public void setLoginType(@Nullable final MPResultType loginType) {
 | 
					 | 
				
			||||||
        this.loginType = ifNotNullElse( loginType, getAlgorithm().mpw_default_login_type() );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public MPAlgorithm getAlgorithm() {
 | 
					 | 
				
			||||||
        return algorithm;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public void setAlgorithm(final MPAlgorithm algorithm) {
 | 
					 | 
				
			||||||
        this.algorithm = algorithm;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public Collection<MPQuestion> getQuestions() {
 | 
					    public Collection<MPQuestion> getQuestions() {
 | 
				
			||||||
        return ImmutableList.of();
 | 
					        return ImmutableList.of();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public UnsignedInteger getSiteCounter() {
 | 
					 | 
				
			||||||
        return siteCounter;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public void setSiteCounter(final UnsignedInteger siteCounter) {
 | 
					 | 
				
			||||||
        this.siteCounter = siteCounter;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,53 +18,23 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package com.lyndir.masterpassword.gui.model;
 | 
					package com.lyndir.masterpassword.gui.model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.google.common.collect.ImmutableList;
 | 
					 | 
				
			||||||
import com.lyndir.masterpassword.MPAlgorithm;
 | 
					 | 
				
			||||||
import com.lyndir.masterpassword.MPMasterKey;
 | 
					import com.lyndir.masterpassword.MPMasterKey;
 | 
				
			||||||
import com.lyndir.masterpassword.model.MPIncorrectMasterPasswordException;
 | 
					import com.lyndir.masterpassword.model.impl.MPBasicUser;
 | 
				
			||||||
import com.lyndir.masterpassword.model.MPUser;
 | 
					import javax.annotation.Nullable;
 | 
				
			||||||
import java.util.Collection;
 | 
					 | 
				
			||||||
import javax.annotation.Nonnull;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @author lhunath, 2014-06-08
 | 
					 * @author lhunath, 2014-06-08
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public class IncognitoUser extends MPUser<IncognitoSite> {
 | 
					public class IncognitoUser extends MPBasicUser<IncognitoSite> {
 | 
				
			||||||
 | 
					 | 
				
			||||||
    private final String fullName;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public IncognitoUser(final String fullName) {
 | 
					    public IncognitoUser(final String fullName) {
 | 
				
			||||||
        this.fullName = fullName;
 | 
					        super(fullName, MPMasterKey.Version.CURRENT.getAlgorithm());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Nullable
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public String getFullName() {
 | 
					    public byte[] getKeyID() {
 | 
				
			||||||
        return fullName;
 | 
					        return null;
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public MPAlgorithm getAlgorithm() {
 | 
					 | 
				
			||||||
        return MPMasterKey.Version.CURRENT.getAlgorithm();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public void addSite(final IncognitoSite site) {
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public void deleteSite(final IncognitoSite site) {
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public Collection<IncognitoSite> findSites(final String query) {
 | 
					 | 
				
			||||||
        return ImmutableList.of();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Nonnull
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public MPMasterKey authenticate(final char[] masterPassword)
 | 
					 | 
				
			||||||
            throws MPIncorrectMasterPasswordException {
 | 
					 | 
				
			||||||
        return key = new MPMasterKey( getFullName(), masterPassword );
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,6 +29,8 @@ import com.lyndir.masterpassword.MPResultType;
 | 
				
			|||||||
import com.lyndir.masterpassword.gui.Res;
 | 
					import com.lyndir.masterpassword.gui.Res;
 | 
				
			||||||
import com.lyndir.masterpassword.gui.util.Components;
 | 
					import com.lyndir.masterpassword.gui.util.Components;
 | 
				
			||||||
import com.lyndir.masterpassword.model.*;
 | 
					import com.lyndir.masterpassword.model.*;
 | 
				
			||||||
 | 
					import com.lyndir.masterpassword.model.impl.*;
 | 
				
			||||||
 | 
					import com.lyndir.masterpassword.model.impl.MPFileSite;
 | 
				
			||||||
import java.awt.*;
 | 
					import java.awt.*;
 | 
				
			||||||
import java.awt.event.*;
 | 
					import java.awt.event.*;
 | 
				
			||||||
import javax.annotation.Nonnull;
 | 
					import javax.annotation.Nonnull;
 | 
				
			||||||
@@ -214,7 +216,7 @@ public class ModelAuthenticationPanel extends AuthenticationPanel<MPFileUser> im
 | 
				
			|||||||
            protected MPFileSite createSite(final MPFileUser user, final String siteName, final UnsignedInteger siteCounter,
 | 
					            protected MPFileSite createSite(final MPFileUser user, final String siteName, final UnsignedInteger siteCounter,
 | 
				
			||||||
                                            final MPResultType resultType,
 | 
					                                            final MPResultType resultType,
 | 
				
			||||||
                                            final MPAlgorithm algorithm) {
 | 
					                                            final MPAlgorithm algorithm) {
 | 
				
			||||||
                return new MPFileSite( user, siteName, siteCounter, resultType, algorithm );
 | 
					                return new MPFileSite( user, siteName, algorithm, siteCounter, resultType );
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,6 +31,9 @@ import com.lyndir.masterpassword.gui.Res;
 | 
				
			|||||||
import com.lyndir.masterpassword.gui.util.Components;
 | 
					import com.lyndir.masterpassword.gui.util.Components;
 | 
				
			||||||
import com.lyndir.masterpassword.gui.util.UnsignedIntegerModel;
 | 
					import com.lyndir.masterpassword.gui.util.UnsignedIntegerModel;
 | 
				
			||||||
import com.lyndir.masterpassword.model.*;
 | 
					import com.lyndir.masterpassword.model.*;
 | 
				
			||||||
 | 
					import com.lyndir.masterpassword.model.impl.MPBasicSite;
 | 
				
			||||||
 | 
					import com.lyndir.masterpassword.model.impl.MPFileSite;
 | 
				
			||||||
 | 
					import com.lyndir.masterpassword.model.impl.MPFileUser;
 | 
				
			||||||
import java.awt.*;
 | 
					import java.awt.*;
 | 
				
			||||||
import java.awt.datatransfer.StringSelection;
 | 
					import java.awt.datatransfer.StringSelection;
 | 
				
			||||||
import java.awt.datatransfer.Transferable;
 | 
					import java.awt.datatransfer.Transferable;
 | 
				
			||||||
@@ -45,7 +48,7 @@ import javax.swing.event.*;
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * @author lhunath, 2014-06-08
 | 
					 * @author lhunath, 2014-06-08
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public abstract class PasswordFrame<U extends MPUser<S>, S extends MPSite> extends JFrame implements DocumentListener {
 | 
					public abstract class PasswordFrame<U extends MPUser<S>, S extends MPBasicSite> extends JFrame implements DocumentListener {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @SuppressWarnings("FieldCanBeLocal")
 | 
					    @SuppressWarnings("FieldCanBeLocal")
 | 
				
			||||||
    private final Components.GradientPanel       root;
 | 
					    private final Components.GradientPanel       root;
 | 
				
			||||||
@@ -147,7 +150,7 @@ public abstract class PasswordFrame<U extends MPUser<S>, S extends MPSite> exten
 | 
				
			|||||||
                                                        siteCounterField = Components.spinner( siteCounterModel ) );
 | 
					                                                        siteCounterField = Components.spinner( siteCounterModel ) );
 | 
				
			||||||
        sitePanel.add( siteSettings );
 | 
					        sitePanel.add( siteSettings );
 | 
				
			||||||
        resultTypeField.setFont( Res.valueFont().deriveFont( resultTypeField.getFont().getSize2D() ) );
 | 
					        resultTypeField.setFont( Res.valueFont().deriveFont( resultTypeField.getFont().getSize2D() ) );
 | 
				
			||||||
        resultTypeField.setSelectedItem( user.getAlgorithm().mpw_default_password_type() );
 | 
					        resultTypeField.setSelectedItem( user.getAlgorithm().mpw_default_result_type() );
 | 
				
			||||||
        resultTypeField.addItemListener( new ItemListener() {
 | 
					        resultTypeField.addItemListener( new ItemListener() {
 | 
				
			||||||
            @Override
 | 
					            @Override
 | 
				
			||||||
            public void itemStateChanged(final ItemEvent e) {
 | 
					            public void itemStateChanged(final ItemEvent e) {
 | 
				
			||||||
@@ -245,15 +248,15 @@ public abstract class PasswordFrame<U extends MPUser<S>, S extends MPSite> exten
 | 
				
			|||||||
            siteResults = FluentIterable.from( siteResults ).filter( new Predicate<S>() {
 | 
					            siteResults = FluentIterable.from( siteResults ).filter( new Predicate<S>() {
 | 
				
			||||||
                @Override
 | 
					                @Override
 | 
				
			||||||
                public boolean apply(@Nullable final S siteResult) {
 | 
					                public boolean apply(@Nullable final S siteResult) {
 | 
				
			||||||
                    return (siteResult != null) && siteNameQuery.equals( siteResult.getSiteName() );
 | 
					                    return (siteResult != null) && siteNameQuery.equals( siteResult.getName() );
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            } );
 | 
					            } );
 | 
				
			||||||
        final S site = ifNotNullElse( Iterables.getFirst( siteResults, null ),
 | 
					        final S site = ifNotNullElse( Iterables.getFirst( siteResults, null ),
 | 
				
			||||||
                                      createSite( user, siteNameQuery, siteCounter, resultType, siteAlgorithm ) );
 | 
					                                      createSite( user, siteNameQuery, siteCounter, resultType, siteAlgorithm ) );
 | 
				
			||||||
        if ((currentSite != null) && currentSite.getSiteName().equals( site.getSiteName() )) {
 | 
					        if ((currentSite != null) && currentSite.getName().equals( site.getName() )) {
 | 
				
			||||||
            site.setResultType( resultType );
 | 
					            site.setResultType( resultType );
 | 
				
			||||||
            site.setAlgorithm( siteAlgorithm );
 | 
					            site.setAlgorithm( siteAlgorithm );
 | 
				
			||||||
            site.setSiteCounter( siteCounter );
 | 
					            site.setCounter( siteCounter );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ListenableFuture<String> passwordFuture = Res.execute( this, new Callable<String>() {
 | 
					        ListenableFuture<String> passwordFuture = Res.execute( this, new Callable<String>() {
 | 
				
			||||||
@@ -278,8 +281,8 @@ public abstract class PasswordFrame<U extends MPUser<S>, S extends MPSite> exten
 | 
				
			|||||||
                            siteActionButton.setText( "Add Site" );
 | 
					                            siteActionButton.setText( "Add Site" );
 | 
				
			||||||
                        resultTypeField.setSelectedItem( currentSite.getResultType() );
 | 
					                        resultTypeField.setSelectedItem( currentSite.getResultType() );
 | 
				
			||||||
                        siteVersionField.setSelectedItem( currentSite.getAlgorithm() );
 | 
					                        siteVersionField.setSelectedItem( currentSite.getAlgorithm() );
 | 
				
			||||||
                        siteCounterField.setValue( currentSite.getSiteCounter() );
 | 
					                        siteCounterField.setValue( currentSite.getCounter() );
 | 
				
			||||||
                        siteNameField.setText( currentSite.getSiteName() );
 | 
					                        siteNameField.setText( currentSite.getName() );
 | 
				
			||||||
                        if (siteNameField.getText().startsWith( siteNameQuery ))
 | 
					                        if (siteNameField.getText().startsWith( siteNameQuery ))
 | 
				
			||||||
                            siteNameField.select( siteNameQuery.length(), siteNameField.getText().length() );
 | 
					                            siteNameField.select( siteNameQuery.length(), siteNameField.getText().length() );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,8 +24,7 @@ import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
 | 
				
			|||||||
import com.lyndir.masterpassword.MPIdenticon;
 | 
					import com.lyndir.masterpassword.MPIdenticon;
 | 
				
			||||||
import com.lyndir.masterpassword.gui.Res;
 | 
					import com.lyndir.masterpassword.gui.Res;
 | 
				
			||||||
import com.lyndir.masterpassword.gui.util.Components;
 | 
					import com.lyndir.masterpassword.gui.util.Components;
 | 
				
			||||||
import com.lyndir.masterpassword.model.MPIncorrectMasterPasswordException;
 | 
					import com.lyndir.masterpassword.model.*;
 | 
				
			||||||
import com.lyndir.masterpassword.model.MPUser;
 | 
					 | 
				
			||||||
import java.awt.*;
 | 
					import java.awt.*;
 | 
				
			||||||
import java.awt.event.*;
 | 
					import java.awt.event.*;
 | 
				
			||||||
import java.util.concurrent.Future;
 | 
					import java.util.concurrent.Future;
 | 
				
			||||||
@@ -49,7 +48,7 @@ public class UnlockFrame extends JFrame {
 | 
				
			|||||||
    private       Future<?>                identiconFuture;
 | 
					    private       Future<?>                identiconFuture;
 | 
				
			||||||
    private       boolean                  incognito;
 | 
					    private       boolean                  incognito;
 | 
				
			||||||
    @Nullable
 | 
					    @Nullable
 | 
				
			||||||
    private       MPUser<?>                user;
 | 
					    private       MPUser<? extends MPSite> user;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public UnlockFrame(final SignInCallback signInCallback) {
 | 
					    public UnlockFrame(final SignInCallback signInCallback) {
 | 
				
			||||||
        super( "Unlock Master Password" );
 | 
					        super( "Unlock Master Password" );
 | 
				
			||||||
@@ -158,7 +157,7 @@ public class UnlockFrame extends JFrame {
 | 
				
			|||||||
        } );
 | 
					        } );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void updateUser(@Nullable final MPUser<?> user) {
 | 
					    void updateUser(@Nullable final MPUser<? extends MPSite> user) {
 | 
				
			||||||
        this.user = user;
 | 
					        this.user = user;
 | 
				
			||||||
        checkSignIn();
 | 
					        checkSignIn();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user