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