Fix warnings and inspections.
This commit is contained in:
parent
82e2d0b5ac
commit
cb74b1f3fc
@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
package com.lyndir.masterpassword;
|
package com.lyndir.masterpassword;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
|
||||||
import com.google.common.primitives.UnsignedInteger;
|
import com.google.common.primitives.UnsignedInteger;
|
||||||
import com.lyndir.lhunath.opal.system.MessageAuthenticationDigests;
|
import com.lyndir.lhunath.opal.system.MessageAuthenticationDigests;
|
||||||
import com.lyndir.lhunath.opal.system.MessageDigests;
|
import com.lyndir.lhunath.opal.system.MessageDigests;
|
||||||
@ -30,25 +29,28 @@ import javax.annotation.Nullable;
|
|||||||
/**
|
/**
|
||||||
* @see MPMasterKey.Version
|
* @see MPMasterKey.Version
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({ "FieldMayBeStatic", "NewMethodNamingConvention" })
|
@SuppressWarnings({ "FieldMayBeStatic", "NewMethodNamingConvention", "MethodReturnAlwaysConstant" })
|
||||||
public abstract class MPAlgorithm {
|
public abstract class MPAlgorithm {
|
||||||
|
|
||||||
public abstract byte[] masterKey(String fullName, char[] masterPassword);
|
public abstract byte[] masterKey(String fullName, char[] masterPassword);
|
||||||
|
|
||||||
public abstract byte[] siteKey(byte[] masterKey, String siteName, UnsignedInteger siteCounter, MPKeyPurpose keyPurpose,
|
public abstract byte[] siteKey(byte[] masterKey, String siteName, UnsignedInteger siteCounter,
|
||||||
@Nullable String keyContext);
|
MPKeyPurpose keyPurpose, @Nullable String keyContext);
|
||||||
|
|
||||||
public abstract String siteResult(byte[] masterKey, byte[] siteKey, String siteName, UnsignedInteger siteCounter, MPKeyPurpose keyPurpose,
|
public abstract String siteResult(byte[] masterKey, byte[] siteKey, String siteName, UnsignedInteger siteCounter,
|
||||||
@Nullable String keyContext, MPResultType resultType, @Nullable String resultParam);
|
MPKeyPurpose keyPurpose, @Nullable String keyContext,
|
||||||
|
MPResultType resultType, @Nullable String resultParam);
|
||||||
|
|
||||||
public abstract String sitePasswordFromTemplate(byte[] masterKey, byte[] siteKey, MPResultType resultType, @Nullable String resultParam);
|
public abstract String sitePasswordFromTemplate(byte[] masterKey, byte[] siteKey,
|
||||||
|
MPResultType resultType, @Nullable String resultParam);
|
||||||
|
|
||||||
public abstract String sitePasswordFromCrypt(byte[] masterKey, byte[] siteKey, MPResultType resultType, @Nullable String resultParam);
|
public abstract String sitePasswordFromCrypt(byte[] masterKey, byte[] siteKey, MPResultType resultType, @Nullable String resultParam);
|
||||||
|
|
||||||
public abstract String sitePasswordFromDerive(byte[] masterKey, byte[] siteKey, MPResultType resultType, @Nullable String resultParam);
|
public abstract String sitePasswordFromDerive(byte[] masterKey, byte[] siteKey, MPResultType resultType, @Nullable String resultParam);
|
||||||
|
|
||||||
public abstract String siteState(byte[] masterKey, byte[] siteKey, String siteName, UnsignedInteger siteCounter, MPKeyPurpose keyPurpose,
|
public abstract String siteState(byte[] masterKey, byte[] siteKey, String siteName, UnsignedInteger siteCounter,
|
||||||
@Nullable String keyContext, MPResultType resultType, String resultParam);
|
MPKeyPurpose keyPurpose, @Nullable String keyContext,
|
||||||
|
MPResultType resultType, String resultParam);
|
||||||
|
|
||||||
// Configuration
|
// Configuration
|
||||||
|
|
||||||
|
@ -47,10 +47,10 @@ public class MPAlgorithmV3 extends MPAlgorithmV2 {
|
|||||||
// Calculate the master key.
|
// Calculate the master key.
|
||||||
logger.trc( "masterKey: scrypt( masterPassword, masterKeySalt, N=%d, r=%d, p=%d )",
|
logger.trc( "masterKey: scrypt( masterPassword, masterKeySalt, N=%d, r=%d, p=%d )",
|
||||||
scrypt_N(), scrypt_r(), scrypt_p() );
|
scrypt_N(), scrypt_r(), scrypt_p() );
|
||||||
byte[] mpBytes = toBytes( masterPassword );
|
byte[] masterPasswordBytes = toBytes( masterPassword );
|
||||||
byte[] masterKey = scrypt( masterKeySalt, mpBytes );
|
byte[] masterKey = scrypt( masterKeySalt, masterPasswordBytes );
|
||||||
Arrays.fill( masterKeySalt, (byte) 0 );
|
Arrays.fill( masterKeySalt, (byte) 0 );
|
||||||
Arrays.fill( mpBytes, (byte) 0 );
|
Arrays.fill( masterPasswordBytes, (byte) 0 );
|
||||||
logger.trc( " => masterKey.id: %s", CodeUtils.encodeHex( toID( masterKey ) ) );
|
logger.trc( " => masterKey.id: %s", CodeUtils.encodeHex( toID( masterKey ) ) );
|
||||||
|
|
||||||
return masterKey;
|
return masterKey;
|
||||||
|
@ -22,7 +22,6 @@ import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
|
|||||||
|
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
import com.google.common.primitives.UnsignedBytes;
|
import com.google.common.primitives.UnsignedBytes;
|
||||||
import com.google.common.primitives.UnsignedInteger;
|
|
||||||
import com.lyndir.lhunath.opal.system.MessageAuthenticationDigests;
|
import com.lyndir.lhunath.opal.system.MessageAuthenticationDigests;
|
||||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||||
import java.nio.*;
|
import java.nio.*;
|
||||||
|
@ -21,7 +21,8 @@ package com.lyndir.masterpassword;
|
|||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||||
import java.util.*;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import org.jetbrains.annotations.Contract;
|
import org.jetbrains.annotations.Contract;
|
||||||
|
|
||||||
@ -31,7 +32,7 @@ import org.jetbrains.annotations.Contract;
|
|||||||
*
|
*
|
||||||
* @author lhunath
|
* @author lhunath
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("RedundantTypeArguments" /* IDEA-191043 */)
|
@SuppressWarnings({ "RedundantTypeArguments", "SpellCheckingInspection" })
|
||||||
public enum MPResultType {
|
public enum MPResultType {
|
||||||
// bit 0-3 | MPResultTypeClass | MPSiteFeature
|
// bit 0-3 | MPResultTypeClass | MPSiteFeature
|
||||||
|
|
||||||
@ -130,11 +131,11 @@ public enum MPResultType {
|
|||||||
|
|
||||||
static final Logger logger = Logger.get( MPResultType.class );
|
static final Logger logger = Logger.get( MPResultType.class );
|
||||||
|
|
||||||
private final String shortName;
|
private final String shortName;
|
||||||
private final String description;
|
private final String description;
|
||||||
private final List<MPTemplate> templates;
|
private final List<MPTemplate> templates;
|
||||||
private final MPResultTypeClass typeClass;
|
private final MPResultTypeClass typeClass;
|
||||||
private final int typeIndex;
|
private final int typeIndex;
|
||||||
private final ImmutableSet<MPSiteFeature> typeFeatures;
|
private final ImmutableSet<MPSiteFeature> typeFeatures;
|
||||||
|
|
||||||
MPResultType(final String shortName, final String description, final List<MPTemplate> templates,
|
MPResultType(final String shortName, final String description, final List<MPTemplate> templates,
|
||||||
@ -167,7 +168,7 @@ public enum MPResultType {
|
|||||||
return typeClass;
|
return typeClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("AssignmentOrReturnOfFieldWithMutableType" /* IDEA-191042 */ )
|
@SuppressWarnings("AssignmentOrReturnOfFieldWithMutableType" /* IDEA-191042 */)
|
||||||
public ImmutableSet<MPSiteFeature> getTypeFeatures() {
|
public ImmutableSet<MPSiteFeature> getTypeFeatures() {
|
||||||
|
|
||||||
return typeFeatures;
|
return typeFeatures;
|
||||||
|
@ -27,6 +27,7 @@ import org.jetbrains.annotations.NonNls;
|
|||||||
*
|
*
|
||||||
* @author lhunath
|
* @author lhunath
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings({ "HardcodedFileSeparator", "SpellCheckingInspection" })
|
||||||
public enum MPTemplateCharacterClass {
|
public enum MPTemplateCharacterClass {
|
||||||
|
|
||||||
UpperVowel( 'V', "AEIOU" ),
|
UpperVowel( 'V', "AEIOU" ),
|
||||||
|
@ -29,13 +29,13 @@ import org.joda.time.Instant;
|
|||||||
*/
|
*/
|
||||||
public class MPFileSite extends MPSite {
|
public class MPFileSite extends MPSite {
|
||||||
|
|
||||||
private final MPFileUser user;
|
private final MPFileUser user;
|
||||||
private String siteName;
|
private String siteName;
|
||||||
@Nullable
|
@Nullable
|
||||||
private String siteContent;
|
private String siteContent;
|
||||||
private UnsignedInteger siteCounter;
|
private UnsignedInteger siteCounter;
|
||||||
private MPResultType resultType;
|
private MPResultType resultType;
|
||||||
private MPAlgorithm algorithm;
|
private MPAlgorithm algorithm;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private String loginContent;
|
private String loginContent;
|
||||||
@ -122,14 +122,15 @@ public class MPFileSite extends MPSite {
|
|||||||
return siteContent;
|
return siteContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSitePassword(final MPMasterKey masterKey, @Nullable final MPResultType resultType, @Nullable final String result)
|
public void setSitePassword(final MPMasterKey masterKey, final MPResultType resultType, @Nullable final String result)
|
||||||
throws MPInvalidatedException {
|
throws MPInvalidatedException {
|
||||||
this.resultType = resultType;
|
this.resultType = resultType;
|
||||||
|
|
||||||
if (result == null)
|
if (result == null)
|
||||||
this.siteContent = null;
|
this.siteContent = null;
|
||||||
else
|
else
|
||||||
this.siteContent = masterKey.siteState(
|
this.siteContent = masterKey.siteState(
|
||||||
getSiteName(), getSiteCounter(), MPKeyPurpose.Authentication, null, getResultType(), result, algorithm );
|
siteName, siteCounter, MPKeyPurpose.Authentication, null, resultType, result, algorithm );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -32,6 +32,7 @@ import org.joda.time.ReadableInstant;
|
|||||||
/**
|
/**
|
||||||
* @author lhunath, 14-12-07
|
* @author lhunath, 14-12-07
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("ComparableImplementedButEqualsNotOverridden")
|
||||||
public class MPFileUser extends MPUser<MPFileSite> implements Comparable<MPFileUser> {
|
public class MPFileUser extends MPUser<MPFileSite> implements Comparable<MPFileUser> {
|
||||||
|
|
||||||
@SuppressWarnings("UnusedDeclaration")
|
@SuppressWarnings("UnusedDeclaration")
|
||||||
@ -41,9 +42,9 @@ public class MPFileUser extends MPUser<MPFileSite> implements Comparable<MPFileU
|
|||||||
private final Collection<MPFileSite> sites = Sets.newHashSet();
|
private final Collection<MPFileSite> sites = Sets.newHashSet();
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private byte[] keyID;
|
private byte[] keyID;
|
||||||
private MPAlgorithm algorithm;
|
private MPAlgorithm algorithm;
|
||||||
private MPMarshalFormat format;
|
private MPMarshalFormat format;
|
||||||
|
|
||||||
private int avatar;
|
private int avatar;
|
||||||
private MPResultType defaultType;
|
private MPResultType defaultType;
|
||||||
|
@ -36,6 +36,7 @@ import javax.annotation.Nonnull;
|
|||||||
*
|
*
|
||||||
* @author lhunath, 14-12-07
|
* @author lhunath, 14-12-07
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("CallToSystemGetenv")
|
||||||
public class MPFileUserManager extends MPUserManager {
|
public class MPFileUserManager extends MPUserManager {
|
||||||
|
|
||||||
@SuppressWarnings("UnusedDeclaration")
|
@SuppressWarnings("UnusedDeclaration")
|
||||||
@ -50,21 +51,20 @@ public class MPFileUserManager extends MPUserManager {
|
|||||||
instance = create( new File( ifNotNullElseNullable( System.getProperty( "user.home" ), System.getenv( "HOME" ) ), ".mpw.d" ) );
|
instance = create( new File( ifNotNullElseNullable( System.getProperty( "user.home" ), System.getenv( "HOME" ) ), ".mpw.d" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
private final File userFilesDirectory;
|
private final File path;
|
||||||
|
|
||||||
public static MPFileUserManager get() {
|
public static MPFileUserManager get() {
|
||||||
MPUserManager.instance = instance;
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MPFileUserManager create(final File userFilesDirectory) {
|
public static MPFileUserManager create(final File path) {
|
||||||
return new MPFileUserManager( userFilesDirectory );
|
return new MPFileUserManager( path );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected MPFileUserManager(final File userFilesDirectory) {
|
protected MPFileUserManager(final File path) {
|
||||||
|
|
||||||
super( unmarshallUsers( userFilesDirectory ) );
|
super( unmarshallUsers( path ) );
|
||||||
this.userFilesDirectory = userFilesDirectory;
|
this.path = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Iterable<MPFileUser> unmarshallUsers(final File userFilesDirectory) {
|
private static Iterable<MPFileUser> unmarshallUsers(final File userFilesDirectory) {
|
||||||
@ -76,7 +76,7 @@ public class MPFileUserManager extends MPUserManager {
|
|||||||
Map<String, MPFileUser> users = new HashMap<>();
|
Map<String, MPFileUser> users = new HashMap<>();
|
||||||
for (final File userFile : listUserFiles( userFilesDirectory ))
|
for (final File userFile : listUserFiles( userFilesDirectory ))
|
||||||
for (final MPMarshalFormat format : MPMarshalFormat.values())
|
for (final MPMarshalFormat format : MPMarshalFormat.values())
|
||||||
if (userFile.getName().endsWith( '.' + format.fileExtension() ))
|
if (userFile.getName().endsWith( format.fileSuffix() ))
|
||||||
try {
|
try {
|
||||||
MPFileUser user = format.unmarshaller().unmarshall( userFile );
|
MPFileUser user = format.unmarshaller().unmarshall( userFile );
|
||||||
MPFileUser previousUser = users.put( user.getFullName(), user );
|
MPFileUser previousUser = users.put( user.getFullName(), user );
|
||||||
@ -95,7 +95,7 @@ public class MPFileUserManager extends MPUserManager {
|
|||||||
@Override
|
@Override
|
||||||
public boolean accept(final File dir, final String name) {
|
public boolean accept(final File dir, final String name) {
|
||||||
for (final MPMarshalFormat format : MPMarshalFormat.values())
|
for (final MPMarshalFormat format : MPMarshalFormat.values())
|
||||||
if (name.endsWith( '.' + format.fileExtension() ))
|
if (name.endsWith( format.fileSuffix() ))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -134,13 +134,13 @@ public class MPFileUserManager extends MPUserManager {
|
|||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
private File getUserFile(final MPFileUser user) {
|
private File getUserFile(final MPFileUser user) {
|
||||||
return new File( userFilesDirectory, user.getFullName() + ".mpsites" );
|
return new File( path, user.getFullName() + ".mpsites" );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The location on the file system where the user models are stored.
|
* @return The location on the file system where the user models are stored.
|
||||||
*/
|
*/
|
||||||
public File getPath() {
|
public File getPath() {
|
||||||
return userFilesDirectory;
|
return path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ import org.joda.time.Instant;
|
|||||||
/**
|
/**
|
||||||
* @author lhunath, 2017-09-20
|
* @author lhunath, 2017-09-20
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings({ "HardcodedLineSeparator", "MagicCharacter" })
|
||||||
public class MPFlatMarshaller implements MPMarshaller {
|
public class MPFlatMarshaller implements MPMarshaller {
|
||||||
|
|
||||||
private static final int FORMAT = 1;
|
private static final int FORMAT = 1;
|
||||||
|
@ -39,8 +39,8 @@ public enum MPMarshalFormat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String fileExtension() {
|
public String fileSuffix() {
|
||||||
return "mpsites";
|
return ".mpsites";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -59,8 +59,8 @@ public enum MPMarshalFormat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String fileExtension() {
|
public String fileSuffix() {
|
||||||
return "mpsites.json";
|
return ".mpsites.json";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -70,5 +70,6 @@ public enum MPMarshalFormat {
|
|||||||
|
|
||||||
public abstract MPUnmarshaller unmarshaller();
|
public abstract MPUnmarshaller unmarshaller();
|
||||||
|
|
||||||
public abstract String fileExtension();
|
@SuppressWarnings("MethodReturnAlwaysConstant")
|
||||||
|
public abstract String fileSuffix();
|
||||||
}
|
}
|
||||||
|
@ -33,14 +33,15 @@ public interface MPMarshaller {
|
|||||||
throws MPInvalidatedException, MPMarshalException;
|
throws MPInvalidatedException, MPMarshalException;
|
||||||
|
|
||||||
enum ContentMode {
|
enum ContentMode {
|
||||||
PROTECTED( "Export of site names and stored passwords (unless device-private) encrypted with the master key." ),
|
PROTECTED( "Export of site names and stored passwords (unless device-private) encrypted with the master key.", true ),
|
||||||
VISIBLE( "Export of site names and passwords in clear-text." );
|
VISIBLE( "Export of site names and passwords in clear-text.", false );
|
||||||
|
|
||||||
private final String description;
|
private final String description;
|
||||||
private boolean redacted;
|
private final boolean redacted;
|
||||||
|
|
||||||
ContentMode(final String description) {
|
ContentMode(final String description, final boolean redacted) {
|
||||||
this.description = description;
|
this.description = description;
|
||||||
|
this.redacted = redacted;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String description() {
|
public String description() {
|
||||||
|
@ -45,7 +45,7 @@ public abstract class MPUser<S extends MPSite> {
|
|||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public MPMasterKey getMasterKey() {
|
public MPMasterKey getMasterKey() {
|
||||||
return Preconditions.checkNotNull( key, "User is not authenticated: " + getFullName() );
|
return Preconditions.checkNotNull( key, "User is not authenticated: %s", getFullName() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public String exportKeyID()
|
public String exportKeyID()
|
||||||
|
@ -29,11 +29,6 @@ import java.util.SortedSet;
|
|||||||
public abstract class MPUserManager {
|
public abstract class MPUserManager {
|
||||||
|
|
||||||
private final Map<String, MPFileUser> usersByName = Maps.newHashMap();
|
private final Map<String, MPFileUser> usersByName = Maps.newHashMap();
|
||||||
static MPUserManager instance;
|
|
||||||
|
|
||||||
public static MPUserManager get() {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected MPUserManager(final Iterable<MPFileUser> users) {
|
protected MPUserManager(final Iterable<MPFileUser> users) {
|
||||||
for (final MPFileUser user : users)
|
for (final MPFileUser user : users)
|
||||||
|
@ -24,8 +24,8 @@ import com.google.common.primitives.UnsignedInteger;
|
|||||||
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 java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Deque;
|
import java.net.URL;
|
||||||
import java.util.List;
|
import java.util.*;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import javax.xml.parsers.*;
|
import javax.xml.parsers.*;
|
||||||
import org.xml.sax.Attributes;
|
import org.xml.sax.Attributes;
|
||||||
@ -56,7 +56,8 @@ public class MPTestSuite implements Callable<Boolean> {
|
|||||||
try {
|
try {
|
||||||
tests = new MPTests();
|
tests = new MPTests();
|
||||||
tests.cases = Lists.newLinkedList();
|
tests.cases = Lists.newLinkedList();
|
||||||
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
|
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
|
||||||
|
Enumeration<URL> resources = Thread.currentThread().getContextClassLoader().getResources( "." );
|
||||||
parser.parse( Thread.currentThread().getContextClassLoader().getResourceAsStream( resourceName ), new DefaultHandler2() {
|
parser.parse( Thread.currentThread().getContextClassLoader().getResourceAsStream( resourceName ), new DefaultHandler2() {
|
||||||
private final Deque<String> currentTags = Lists.newLinkedList();
|
private final Deque<String> currentTags = Lists.newLinkedList();
|
||||||
private final Deque<StringBuilder> currentTexts = Lists.newLinkedList();
|
private final Deque<StringBuilder> currentTexts = Lists.newLinkedList();
|
||||||
@ -81,7 +82,7 @@ public class MPTestSuite implements Callable<Boolean> {
|
|||||||
throws SAXException {
|
throws SAXException {
|
||||||
super.endElement( uri, localName, qName );
|
super.endElement( uri, localName, qName );
|
||||||
Preconditions.checkState( qName.equals( currentTags.pop() ) );
|
Preconditions.checkState( qName.equals( currentTags.pop() ) );
|
||||||
String text = currentTexts.pop().toString();
|
String text = Preconditions.checkNotNull( currentTexts.pop() ).toString();
|
||||||
|
|
||||||
if ("case".equals( qName ))
|
if ("case".equals( qName ))
|
||||||
tests.cases.add( currentCase );
|
tests.cases.add( currentCase );
|
||||||
@ -112,11 +113,11 @@ public class MPTestSuite implements Callable<Boolean> {
|
|||||||
throws SAXException {
|
throws SAXException {
|
||||||
super.characters( ch, start, length );
|
super.characters( ch, start, length );
|
||||||
|
|
||||||
currentTexts.peek().append( ch, start, length );
|
Preconditions.checkNotNull( currentTexts.peek() ).append( ch, start, length );
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException | ParserConfigurationException | SAXException | IOException e) {
|
catch (final IllegalArgumentException | ParserConfigurationException | SAXException | IOException e) {
|
||||||
throw new UnavailableException( e );
|
throw new UnavailableException( e );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ import com.lyndir.lhunath.opal.system.util.NNSupplier;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import javax.xml.bind.annotation.XmlTransient;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -66,20 +67,23 @@ public class MPTests {
|
|||||||
|
|
||||||
public static class Case {
|
public static class Case {
|
||||||
|
|
||||||
String identifier;
|
String identifier;
|
||||||
String parent;
|
String parent;
|
||||||
Integer algorithm;
|
@Nullable
|
||||||
String fullName;
|
Integer algorithm;
|
||||||
String masterPassword;
|
String fullName;
|
||||||
String keyID;
|
String masterPassword;
|
||||||
String siteName;
|
String keyID;
|
||||||
|
String siteName;
|
||||||
|
@Nullable
|
||||||
UnsignedInteger siteCounter;
|
UnsignedInteger siteCounter;
|
||||||
String resultType;
|
String resultType;
|
||||||
String keyPurpose;
|
String keyPurpose;
|
||||||
String keyContext;
|
String keyContext;
|
||||||
String result;
|
String result;
|
||||||
|
|
||||||
private transient Case parentCase;
|
@XmlTransient
|
||||||
|
private Case parentCase;
|
||||||
|
|
||||||
public void initializeParentHierarchy(final MPTests tests) {
|
public void initializeParentHierarchy(final MPTests tests) {
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ public class MPMasterKeyTest {
|
|||||||
char[] masterPassword = testCase.getMasterPassword().toCharArray();
|
char[] masterPassword = testCase.getMasterPassword().toCharArray();
|
||||||
MPMasterKey masterKey = new MPMasterKey( testCase.getFullName(), masterPassword );
|
MPMasterKey masterKey = new MPMasterKey( testCase.getFullName(), masterPassword );
|
||||||
|
|
||||||
String password = randomString( 8 );
|
String password = randomString( 8 );
|
||||||
MPResultType resultType = MPResultType.StoredPersonal;
|
MPResultType resultType = MPResultType.StoredPersonal;
|
||||||
for (final MPMasterKey.Version version : MPMasterKey.Version.values()) {
|
for (final MPMasterKey.Version version : MPMasterKey.Version.values()) {
|
||||||
MPAlgorithm algorithm = version.getAlgorithm();
|
MPAlgorithm algorithm = version.getAlgorithm();
|
||||||
@ -126,7 +126,7 @@ public class MPMasterKeyTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String randomString(int length) {
|
private static String randomString(int length) {
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="Tests" type="TestNG" factoryName="TestNG" show_console_on_std_err="true">
|
<configuration default="false" name="Tests" type="TestNG" factoryName="TestNG" show_console_on_std_err="true">
|
||||||
<module name="" />
|
<module name="masterpassword-tests" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH" />
|
<option name="ALTERNATIVE_JRE_PATH" />
|
||||||
<option name="SUITE_NAME" value="" />
|
<option name="SUITE_NAME" value="" />
|
||||||
@ -13,15 +13,12 @@
|
|||||||
<option name="PARAMETERS" value="" />
|
<option name="PARAMETERS" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/../core/java/tests" />
|
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/../core/java/tests" />
|
||||||
<option name="OUTPUT_DIRECTORY" value="" />
|
<option name="OUTPUT_DIRECTORY" value="" />
|
||||||
<option name="ANNOTATION_TYPE" />
|
|
||||||
<option name="ENV_VARIABLES" />
|
|
||||||
<option name="PASS_PARENT_ENVS" value="true" />
|
<option name="PASS_PARENT_ENVS" value="true" />
|
||||||
<option name="TEST_SEARCH_SCOPE">
|
<option name="TEST_SEARCH_SCOPE">
|
||||||
<value defaultName="wholeProject" />
|
<value defaultName="moduleWithDependencies" />
|
||||||
</option>
|
</option>
|
||||||
<option name="USE_DEFAULT_REPORTERS" value="false" />
|
<option name="USE_DEFAULT_REPORTERS" value="false" />
|
||||||
<option name="PROPERTIES_FILE" value="" />
|
<option name="PROPERTIES_FILE" value="" />
|
||||||
<envs />
|
|
||||||
<properties />
|
<properties />
|
||||||
<listeners />
|
<listeners />
|
||||||
<method />
|
<method />
|
||||||
|
@ -50,7 +50,7 @@ public class EmergencyActivity extends Activity {
|
|||||||
private static final Logger logger = Logger.get( EmergencyActivity.class );
|
private static final Logger logger = Logger.get( EmergencyActivity.class );
|
||||||
private static final ClipData EMPTY_CLIP = new ClipData( new ClipDescription( "", new String[0] ), new ClipData.Item( "" ) );
|
private static final ClipData EMPTY_CLIP = new ClipData( new ClipDescription( "", new String[0] ), new ClipData.Item( "" ) );
|
||||||
private static final int PASSWORD_NOTIFICATION = 0;
|
private static final int PASSWORD_NOTIFICATION = 0;
|
||||||
public static final int CLIPBOARD_CLEAR_DELAY = 20 /* s */ * MPConstant.MS_PER_S;
|
private static final int CLIPBOARD_CLEAR_DELAY = 20 /* s */ * MPConstant.MS_PER_S;
|
||||||
|
|
||||||
private final Preferences preferences = Preferences.get( this );
|
private final Preferences preferences = Preferences.get( this );
|
||||||
private final ListeningExecutorService executor = MoreExecutors.listeningDecorator(
|
private final ListeningExecutorService executor = MoreExecutors.listeningDecorator(
|
||||||
@ -59,6 +59,7 @@ public class EmergencyActivity extends Activity {
|
|||||||
MPResultType.forClass( MPResultTypeClass.Template ) );
|
MPResultType.forClass( MPResultTypeClass.Template ) );
|
||||||
private final ImmutableList<MPMasterKey.Version> allVersions = ImmutableList.copyOf( MPMasterKey.Version.values() );
|
private final ImmutableList<MPMasterKey.Version> allVersions = ImmutableList.copyOf( MPMasterKey.Version.values() );
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private MPMasterKey masterKey;
|
private MPMasterKey masterKey;
|
||||||
|
|
||||||
@BindView(R.id.progressView)
|
@BindView(R.id.progressView)
|
||||||
@ -99,6 +100,7 @@ public class EmergencyActivity extends Activity {
|
|||||||
|
|
||||||
private int id_userName;
|
private int id_userName;
|
||||||
private int id_masterPassword;
|
private int id_masterPassword;
|
||||||
|
@Nullable
|
||||||
private String sitePassword;
|
private String sitePassword;
|
||||||
|
|
||||||
public static void start(final Context context) {
|
public static void start(final Context context) {
|
||||||
@ -176,13 +178,13 @@ public class EmergencyActivity extends Activity {
|
|||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
fullNameField.setTypeface( Res.get( this ).exo_Thin );
|
fullNameField.setTypeface( Res.get( this ).exo_Thin() );
|
||||||
fullNameField.setPaintFlags( fullNameField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
fullNameField.setPaintFlags( fullNameField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
||||||
masterPasswordField.setTypeface( Res.get( this ).sourceCodePro_ExtraLight );
|
masterPasswordField.setTypeface( Res.get( this ).sourceCodePro_ExtraLight() );
|
||||||
masterPasswordField.setPaintFlags( masterPasswordField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
masterPasswordField.setPaintFlags( masterPasswordField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
||||||
siteNameField.setTypeface( Res.get( this ).exo_Regular );
|
siteNameField.setTypeface( Res.get( this ).exo_Regular() );
|
||||||
siteNameField.setPaintFlags( siteNameField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
siteNameField.setPaintFlags( siteNameField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
||||||
sitePasswordField.setTypeface( Res.get( this ).sourceCodePro_Black );
|
sitePasswordField.setTypeface( Res.get( this ).sourceCodePro_Black() );
|
||||||
sitePasswordField.setPaintFlags( sitePasswordField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
sitePasswordField.setPaintFlags( sitePasswordField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
||||||
|
|
||||||
rememberFullNameField.setOnCheckedChangeListener( new CompoundButton.OnCheckedChangeListener() {
|
rememberFullNameField.setOnCheckedChangeListener( new CompoundButton.OnCheckedChangeListener() {
|
||||||
@ -257,8 +259,8 @@ public class EmergencyActivity extends Activity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void updateMasterKey() {
|
private synchronized void updateMasterKey() {
|
||||||
final String fullName = fullNameField.getText().toString();
|
String fullName = fullNameField.getText().toString();
|
||||||
final char[] masterPassword = masterPasswordField.getText().toString().toCharArray();
|
char[] masterPassword = masterPasswordField.getText().toString().toCharArray();
|
||||||
if ((id_userName == fullName.hashCode())
|
if ((id_userName == fullName.hashCode())
|
||||||
&& (id_masterPassword == Arrays.hashCode( masterPassword )))
|
&& (id_masterPassword == Arrays.hashCode( masterPassword )))
|
||||||
if (masterKey != null)
|
if (masterKey != null)
|
||||||
@ -303,7 +305,8 @@ public class EmergencyActivity extends Activity {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
sitePassword = masterKey.siteResult( siteName, counter, MPKeyPurpose.Authentication, null, type, null, version.getAlgorithm() );
|
sitePassword = masterKey.siteResult( siteName, counter, MPKeyPurpose.Authentication, null, type, null,
|
||||||
|
version.getAlgorithm() );
|
||||||
|
|
||||||
runOnUiThread( new Runnable() {
|
runOnUiThread( new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
@ -341,31 +344,39 @@ public class EmergencyActivity extends Activity {
|
|||||||
|
|
||||||
final ClipboardManager clipboardManager = (ClipboardManager) getSystemService( CLIPBOARD_SERVICE );
|
final ClipboardManager clipboardManager = (ClipboardManager) getSystemService( CLIPBOARD_SERVICE );
|
||||||
final NotificationManager notificationManager = (NotificationManager) getSystemService( Context.NOTIFICATION_SERVICE );
|
final NotificationManager notificationManager = (NotificationManager) getSystemService( Context.NOTIFICATION_SERVICE );
|
||||||
|
if (clipboardManager == null)
|
||||||
|
return;
|
||||||
|
|
||||||
String title = strf( "Password for %s", siteNameField.getText() );
|
String title = strf( "Password for %s", siteNameField.getText() );
|
||||||
ClipDescription description = new ClipDescription( title, new String[]{ ClipDescription.MIMETYPE_TEXT_PLAIN } );
|
ClipDescription description = new ClipDescription( title, new String[]{ ClipDescription.MIMETYPE_TEXT_PLAIN } );
|
||||||
clipboardManager.setPrimaryClip( new ClipData( description, new ClipData.Item( currentSitePassword ) ) );
|
clipboardManager.setPrimaryClip( new ClipData( description, new ClipData.Item( currentSitePassword ) ) );
|
||||||
|
|
||||||
Notification.Builder notificationBuilder = new Notification.Builder( this ).setContentTitle( title )
|
if (notificationManager != null) {
|
||||||
.setContentText( "Paste the password into your app." )
|
Notification.Builder notificationBuilder = new Notification.Builder( this ).setContentTitle( title )
|
||||||
.setSmallIcon( R.drawable.icon )
|
.setContentText(
|
||||||
.setAutoCancel( true );
|
"Paste the password into your app." )
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
|
.setSmallIcon( R.drawable.icon )
|
||||||
notificationBuilder.setVisibility( Notification.VISIBILITY_SECRET )
|
.setAutoCancel( true );
|
||||||
.setCategory( Notification.CATEGORY_RECOMMENDATION )
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
|
||||||
.setLocalOnly( true );
|
notificationBuilder.setVisibility( Notification.VISIBILITY_SECRET )
|
||||||
notificationManager.notify( PASSWORD_NOTIFICATION, notificationBuilder.build() );
|
.setCategory( Notification.CATEGORY_RECOMMENDATION )
|
||||||
|
.setLocalOnly( true );
|
||||||
|
notificationManager.notify( PASSWORD_NOTIFICATION, notificationBuilder.build() );
|
||||||
|
}
|
||||||
|
|
||||||
final Timer timer = new Timer();
|
final Timer timer = new Timer();
|
||||||
timer.schedule( new TimerTask() {
|
timer.schedule( new TimerTask() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
ClipData clip = clipboardManager.getPrimaryClip();
|
ClipData clip = clipboardManager.getPrimaryClip();
|
||||||
for (int i = 0; i < clip.getItemCount(); ++i)
|
for (int i = 0; i < clip.getItemCount(); ++i)
|
||||||
if (currentSitePassword.equals( clip.getItemAt( i ).coerceToText( EmergencyActivity.this ) )) {
|
if (currentSitePassword.contentEquals( clip.getItemAt( i ).coerceToText( EmergencyActivity.this ) )) {
|
||||||
clipboardManager.setPrimaryClip( EMPTY_CLIP );
|
clipboardManager.setPrimaryClip( EMPTY_CLIP );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
notificationManager.cancel( PASSWORD_NOTIFICATION );
|
|
||||||
|
if (notificationManager != null)
|
||||||
|
notificationManager.cancel( PASSWORD_NOTIFICATION );
|
||||||
timer.cancel();
|
timer.cancel();
|
||||||
}
|
}
|
||||||
}, CLIPBOARD_CLEAR_DELAY );
|
}, CLIPBOARD_CLEAR_DELAY );
|
||||||
|
@ -25,6 +25,7 @@ import com.google.common.collect.Sets;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -64,6 +65,7 @@ public class MainThreadExecutor extends AbstractExecutorService {
|
|||||||
shutdown = true;
|
shutdown = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public List<Runnable> shutdownNow() {
|
public List<Runnable> shutdownNow() {
|
||||||
shutdown = true;
|
shutdown = true;
|
||||||
|
@ -25,14 +25,15 @@ import android.graphics.Typeface;
|
|||||||
/**
|
/**
|
||||||
* @author lhunath, 2014-08-25
|
* @author lhunath, 2014-08-25
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("NewMethodNamingConvention")
|
||||||
public final class Res {
|
public final class Res {
|
||||||
|
|
||||||
public final Typeface sourceCodePro_Black;
|
private final Typeface sourceCodePro_Black;
|
||||||
public final Typeface sourceCodePro_ExtraLight;
|
private final Typeface sourceCodePro_ExtraLight;
|
||||||
public final Typeface exo_Bold;
|
private final Typeface exo_Bold;
|
||||||
public final Typeface exo_ExtraBold;
|
private final Typeface exo_ExtraBold;
|
||||||
public final Typeface exo_Regular;
|
private final Typeface exo_Regular;
|
||||||
public final Typeface exo_Thin;
|
private final Typeface exo_Thin;
|
||||||
|
|
||||||
private static Res res;
|
private static Res res;
|
||||||
|
|
||||||
@ -53,4 +54,28 @@ public final class Res {
|
|||||||
exo_Regular = Typeface.createFromAsset( context.getResources().getAssets(), "Exo2.0-Regular.otf" );
|
exo_Regular = Typeface.createFromAsset( context.getResources().getAssets(), "Exo2.0-Regular.otf" );
|
||||||
exo_Thin = Typeface.createFromAsset( context.getResources().getAssets(), "Exo2.0-Thin.otf" );
|
exo_Thin = Typeface.createFromAsset( context.getResources().getAssets(), "Exo2.0-Thin.otf" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Typeface sourceCodePro_Black() {
|
||||||
|
return sourceCodePro_Black;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Typeface sourceCodePro_ExtraLight() {
|
||||||
|
return sourceCodePro_ExtraLight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Typeface exo_Bold() {
|
||||||
|
return exo_Bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Typeface exo_ExtraBold() {
|
||||||
|
return exo_ExtraBold;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Typeface exo_Regular() {
|
||||||
|
return exo_Regular;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Typeface exo_Thin() {
|
||||||
|
return exo_Thin;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ import com.lyndir.masterpassword.MPConstant;
|
|||||||
/**
|
/**
|
||||||
* @author lhunath, 2014-08-31
|
* @author lhunath, 2014-08-31
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("CallToSystemGetenv")
|
||||||
public class Config {
|
public class Config {
|
||||||
|
|
||||||
private static final Config instance = new Config();
|
private static final Config instance = new Config();
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
package com.lyndir.masterpassword.gui;
|
package com.lyndir.masterpassword.gui;
|
||||||
|
|
||||||
|
import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
import com.google.common.io.CharSource;
|
import com.google.common.io.CharSource;
|
||||||
@ -57,7 +59,7 @@ public class GUI implements UnlockFrame.SignInCallback {
|
|||||||
try {
|
try {
|
||||||
UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
|
UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
|
||||||
}
|
}
|
||||||
catch (UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException | IllegalAccessException ignored) {
|
catch (final UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException | IllegalAccessException ignored) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -69,7 +71,7 @@ public class GUI implements UnlockFrame.SignInCallback {
|
|||||||
else // No special platform handling.
|
else // No special platform handling.
|
||||||
new GUI().open();
|
new GUI().open();
|
||||||
}
|
}
|
||||||
catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) {
|
catch (final IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) {
|
||||||
throw logger.bug( e );
|
throw logger.bug( e );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -77,29 +79,35 @@ public class GUI implements UnlockFrame.SignInCallback {
|
|||||||
private static void checkUpdate() {
|
private static void checkUpdate() {
|
||||||
try {
|
try {
|
||||||
Enumeration<URL> manifestURLs = Thread.currentThread().getContextClassLoader().getResources( JarFile.MANIFEST_NAME );
|
Enumeration<URL> manifestURLs = Thread.currentThread().getContextClassLoader().getResources( JarFile.MANIFEST_NAME );
|
||||||
while (manifestURLs.hasMoreElements()) {
|
while (manifestURLs.hasMoreElements())
|
||||||
InputStream manifestStream = manifestURLs.nextElement().openStream();
|
try (InputStream manifestStream = manifestURLs.nextElement().openStream()) {
|
||||||
Attributes attributes = new Manifest( manifestStream ).getMainAttributes();
|
Attributes attributes = new Manifest( manifestStream ).getMainAttributes();
|
||||||
if (!GUI.class.getCanonicalName().equals( attributes.getValue( Attributes.Name.MAIN_CLASS ) ))
|
if (!GUI.class.getCanonicalName().equals( attributes.getValue( Attributes.Name.MAIN_CLASS ) ))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
String manifestRevision = attributes.getValue( Attributes.Name.IMPLEMENTATION_VERSION );
|
String manifestRevision = attributes.getValue( Attributes.Name.IMPLEMENTATION_VERSION );
|
||||||
String upstreamRevisionURL = "https://masterpasswordapp.com/masterpassword-gui.jar.rev";
|
String upstreamRevisionURL = "https://masterpasswordapp.com/masterpassword-gui.jar.rev";
|
||||||
CharSource upstream = Resources.asCharSource( URI.create( upstreamRevisionURL ).toURL(), Charsets.UTF_8 );
|
CharSource upstream = Resources.asCharSource( URI.create( upstreamRevisionURL ).toURL(), Charsets.UTF_8 );
|
||||||
String upstreamRevision = upstream.readFirstLine();
|
String upstreamRevision = upstream.readFirstLine();
|
||||||
if ((manifestRevision != null) && (upstreamRevision != null) && !manifestRevision.equalsIgnoreCase( upstreamRevision )) {
|
if ((manifestRevision != null) && (upstreamRevision != null) && !manifestRevision.equalsIgnoreCase(
|
||||||
logger.inf( "Local Revision: <%s>", manifestRevision );
|
upstreamRevision )) {
|
||||||
logger.inf( "Upstream Revision: <%s>", upstreamRevision );
|
logger.inf( "Local Revision: <%s>", manifestRevision );
|
||||||
logger.wrn( "You are not running the current official version. Please update from:\n"
|
logger.inf( "Upstream Revision: <%s>", upstreamRevision );
|
||||||
+ "https://masterpasswordapp.com/masterpassword-gui.jar" );
|
logger.wrn( "You are not running the current official version. Please update from:%n%s",
|
||||||
JOptionPane.showMessageDialog( null, "A new version of Master Password is available.\n"
|
"https://masterpasswordapp.com/masterpassword-gui.jar" );
|
||||||
+ "Please download the latest version from http://masterpasswordapp.com",
|
JOptionPane.showMessageDialog( null,
|
||||||
"Update Available", JOptionPane.WARNING_MESSAGE );
|
strf( "A new version of Master Password is available.%n "
|
||||||
|
+ "Please download the latest version from %s",
|
||||||
|
"https://masterpasswordapp.com" ),
|
||||||
|
"Update Available", JOptionPane.WARNING_MESSAGE );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (final IOException e) {
|
||||||
|
logger.wrn( e, "Couldn't check for version update." );
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (final IOException e) {
|
catch (final IOException e) {
|
||||||
logger.wrn( e, "Couldn't check for version update." );
|
logger.wrn( e, "Couldn't inspect JAR." );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ import org.jetbrains.annotations.NonNls;
|
|||||||
/**
|
/**
|
||||||
* @author lhunath, 2014-06-11
|
* @author lhunath, 2014-06-11
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("HardcodedFileSeparator")
|
@SuppressWarnings({ "HardcodedFileSeparator", "MethodReturnAlwaysConstant", "SpellCheckingInspection" })
|
||||||
public abstract class Res {
|
public abstract class Res {
|
||||||
|
|
||||||
private static final int AVATAR_COUNT = 19;
|
private static final int AVATAR_COUNT = 19;
|
||||||
@ -210,7 +210,7 @@ public abstract class Res {
|
|||||||
fontsByResourceName.put( fontResourceName, new SoftReference<>(
|
fontsByResourceName.put( fontResourceName, new SoftReference<>(
|
||||||
font = Font.createFont( Font.TRUETYPE_FONT, Resources.getResource( fontResourceName ).openStream() ) ) );
|
font = Font.createFont( Font.TRUETYPE_FONT, Resources.getResource( fontResourceName ).openStream() ) ) );
|
||||||
}
|
}
|
||||||
catch (FontFormatException | IOException e) {
|
catch (final FontFormatException | IOException e) {
|
||||||
throw Throwables.propagate( e );
|
throw Throwables.propagate( e );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,8 @@
|
|||||||
package com.lyndir.masterpassword.gui.model;
|
package com.lyndir.masterpassword.gui.model;
|
||||||
|
|
||||||
import com.google.common.primitives.UnsignedInteger;
|
import com.google.common.primitives.UnsignedInteger;
|
||||||
import com.lyndir.masterpassword.*;
|
import com.lyndir.masterpassword.MPAlgorithm;
|
||||||
|
import com.lyndir.masterpassword.MPResultType;
|
||||||
import com.lyndir.masterpassword.model.MPSite;
|
import com.lyndir.masterpassword.model.MPSite;
|
||||||
|
|
||||||
|
|
||||||
|
@ -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-04-26
|
||||||
|
*/
|
||||||
|
@ParametersAreNonnullByDefault
|
||||||
|
package com.lyndir.masterpassword.gui.platform.mac;
|
||||||
|
|
||||||
|
import javax.annotation.ParametersAreNonnullByDefault;
|
@ -31,7 +31,7 @@ import javax.swing.border.CompoundBorder;
|
|||||||
*/
|
*/
|
||||||
public abstract class Components {
|
public abstract class Components {
|
||||||
|
|
||||||
public static final float CONTROL_TEXT_SIZE = 12f;
|
private static final float CONTROL_TEXT_SIZE = 12f;
|
||||||
|
|
||||||
public static GradientPanel boxLayout(final int axis, final Component... components) {
|
public static GradientPanel boxLayout(final int axis, final Component... components) {
|
||||||
GradientPanel container = gradientPanel( null, null );
|
GradientPanel container = gradientPanel( null, null );
|
||||||
|
@ -20,7 +20,8 @@ package com.lyndir.masterpassword.gui.view;
|
|||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.primitives.UnsignedInteger;
|
import com.google.common.primitives.UnsignedInteger;
|
||||||
import com.lyndir.masterpassword.*;
|
import com.lyndir.masterpassword.MPAlgorithm;
|
||||||
|
import com.lyndir.masterpassword.MPResultType;
|
||||||
import com.lyndir.masterpassword.gui.Res;
|
import com.lyndir.masterpassword.gui.Res;
|
||||||
import com.lyndir.masterpassword.gui.model.IncognitoSite;
|
import com.lyndir.masterpassword.gui.model.IncognitoSite;
|
||||||
import com.lyndir.masterpassword.gui.model.IncognitoUser;
|
import com.lyndir.masterpassword.gui.model.IncognitoUser;
|
||||||
|
@ -20,10 +20,12 @@ package com.lyndir.masterpassword.gui.view;
|
|||||||
|
|
||||||
import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
|
import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.primitives.UnsignedInteger;
|
import com.google.common.primitives.UnsignedInteger;
|
||||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||||
import com.lyndir.masterpassword.*;
|
import com.lyndir.masterpassword.MPAlgorithm;
|
||||||
|
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.*;
|
||||||
@ -171,7 +173,7 @@ public class ModelAuthenticationPanel extends AuthenticationPanel<MPFileUser> im
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (JOptionPane.showConfirmDialog( ModelAuthenticationPanel.this, //
|
if (JOptionPane.showConfirmDialog( ModelAuthenticationPanel.this, //
|
||||||
strf( "Are you sure you want to delete the user and sites remembered for:\n%s.",
|
strf( "Are you sure you want to delete the user and sites remembered for:%n%s.",
|
||||||
deleteUser.getFullName() ), //
|
deleteUser.getFullName() ), //
|
||||||
"Delete User", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE )
|
"Delete User", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE )
|
||||||
== JOptionPane.CANCEL_OPTION)
|
== JOptionPane.CANCEL_OPTION)
|
||||||
@ -190,7 +192,7 @@ public class ModelAuthenticationPanel extends AuthenticationPanel<MPFileUser> im
|
|||||||
@Override
|
@Override
|
||||||
public void actionPerformed(final ActionEvent e) {
|
public void actionPerformed(final ActionEvent e) {
|
||||||
JOptionPane.showMessageDialog( ModelAuthenticationPanel.this, //
|
JOptionPane.showMessageDialog( ModelAuthenticationPanel.this, //
|
||||||
strf( "Reads users and sites from the directory at:\n%s",
|
strf( "Reads users and sites from the directory at:%n%s",
|
||||||
MPFileUserManager.get().getPath().getAbsolutePath() ), //
|
MPFileUserManager.get().getPath().getAbsolutePath() ), //
|
||||||
"Help", JOptionPane.INFORMATION_MESSAGE );
|
"Help", JOptionPane.INFORMATION_MESSAGE );
|
||||||
}
|
}
|
||||||
@ -207,7 +209,7 @@ public class ModelAuthenticationPanel extends AuthenticationPanel<MPFileUser> im
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PasswordFrame<MPFileUser, MPFileSite> newPasswordFrame() {
|
public PasswordFrame<MPFileUser, MPFileSite> newPasswordFrame() {
|
||||||
return new PasswordFrame<MPFileUser, MPFileSite>( getSelectedUser() ) {
|
return new PasswordFrame<MPFileUser, MPFileSite>( Preconditions.checkNotNull( getSelectedUser() ) ) {
|
||||||
@Override
|
@Override
|
||||||
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,
|
||||||
|
@ -66,7 +66,7 @@ public abstract class PasswordFrame<U extends MPUser<S>, S extends MPSite> exten
|
|||||||
private S currentSite;
|
private S currentSite;
|
||||||
private boolean updatingUI;
|
private boolean updatingUI;
|
||||||
|
|
||||||
@SuppressWarnings({ "MagicNumber", "OverridableMethodCallDuringObjectConstruction" })
|
@SuppressWarnings("MagicNumber")
|
||||||
protected PasswordFrame(final U user) {
|
protected PasswordFrame(final U user) {
|
||||||
super( "Master Password" );
|
super( "Master Password" );
|
||||||
this.user = user;
|
this.user = user;
|
||||||
|
@ -19,12 +19,13 @@
|
|||||||
package com.lyndir.masterpassword.gui.view;
|
package com.lyndir.masterpassword.gui.view;
|
||||||
|
|
||||||
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 com.lyndir.masterpassword.MPIdenticon;
|
import com.lyndir.masterpassword.MPIdenticon;
|
||||||
import com.lyndir.masterpassword.gui.*;
|
import com.lyndir.masterpassword.gui.Res;
|
||||||
import com.lyndir.masterpassword.model.MPUser;
|
|
||||||
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.MPIncorrectMasterPasswordException;
|
||||||
|
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;
|
||||||
@ -47,6 +48,7 @@ public class UnlockFrame extends JFrame {
|
|||||||
private AuthenticationPanel<?> authenticationPanel;
|
private AuthenticationPanel<?> authenticationPanel;
|
||||||
private Future<?> identiconFuture;
|
private Future<?> identiconFuture;
|
||||||
private boolean incognito;
|
private boolean incognito;
|
||||||
|
@Nullable
|
||||||
private MPUser<?> user;
|
private MPUser<?> user;
|
||||||
|
|
||||||
public UnlockFrame(final SignInCallback signInCallback) {
|
public UnlockFrame(final SignInCallback signInCallback) {
|
||||||
@ -86,7 +88,7 @@ public class UnlockFrame extends JFrame {
|
|||||||
authenticationContainer.setBorder( BorderFactory.createEmptyBorder( 20, 20, 20, 20 ) );
|
authenticationContainer.setBorder( BorderFactory.createEmptyBorder( 20, 20, 20, 20 ) );
|
||||||
identiconLabel.setFont( Res.emoticonsFont().deriveFont( 14.f ) );
|
identiconLabel.setFont( Res.emoticonsFont().deriveFont( 14.f ) );
|
||||||
identiconLabel.setToolTipText(
|
identiconLabel.setToolTipText(
|
||||||
"A representation of your identity across all Master Password apps.\nIt should always be the same." );
|
strf( "A representation of your identity across all Master Password apps.%nIt should always be the same." ) );
|
||||||
signInButton.addActionListener( new AbstractAction() {
|
signInButton.addActionListener( new AbstractAction() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(final ActionEvent e) {
|
public void actionPerformed(final ActionEvent e) {
|
||||||
|
Loading…
Reference in New Issue
Block a user