2
0

Fix warnings and inspections.

This commit is contained in:
Maarten Billemont 2018-04-27 11:32:54 -04:00
parent 82e2d0b5ac
commit cb74b1f3fc
30 changed files with 225 additions and 142 deletions

View File

@ -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

View File

@ -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;

View File

@ -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.*;

View File

@ -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;

View File

@ -27,6 +27,7 @@ import org.jetbrains.annotations.NonNls;
*
* @author lhunath
*/
@SuppressWarnings({ "HardcodedFileSeparator", "SpellCheckingInspection" })
public enum MPTemplateCharacterClass {
UpperVowel( 'V', "AEIOU" ),

View File

@ -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

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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();
}

View File

@ -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() {

View File

@ -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()

View File

@ -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)

View File

@ -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 );
}

View File

@ -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) {

View File

@ -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();

View File

@ -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 />

View File

@ -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 );

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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();

View File

@ -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." );
}
}

View File

@ -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 );
}

View File

@ -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;

View File

@ -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;

View File

@ -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 );

View File

@ -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;

View File

@ -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,

View File

@ -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;

View File

@ -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) {