Merge pull request #872 from stokito/refactor_cleanup

SPARK-2337 Refactor and cleanup
This commit is contained in:
ilyaHlevnoy 2024-08-22 21:53:02 +03:00 committed by GitHub
commit b53b814740
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 144 additions and 547 deletions

View File

@ -154,8 +154,8 @@ public class LoginDialog {
1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH,
new Insets(0, 0, 0, 0), 0, 0));
final String showPoweredBy = Default.getString(Default.SHOW_POWERED_BY);
if (ModelUtil.hasLength(showPoweredBy) && "true".equals(showPoweredBy)) {
final boolean showPoweredBy = Default.getBoolean(Default.SHOW_POWERED_BY);
if (showPoweredBy) {
// Handle Powered By for custom clients.
final JLabel poweredBy = new JLabel(SparkRes.getImageIcon(SparkRes.POWERED_BY_IMAGE));
mainPanel.add(poweredBy,

View File

@ -31,7 +31,9 @@ import javax.swing.JWindow;
import org.jivesoftware.resource.Res;
import org.jivesoftware.resource.SparkRes;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.StanzaError.Condition;
import org.jivesoftware.smackx.vcardtemp.packet.VCard;
import org.jivesoftware.smackx.iqlast.packet.LastActivity;
import org.jivesoftware.smackx.iqlast.LastActivityManager;
@ -261,9 +263,14 @@ public class ContactInfoWindow extends JPanel {
status += Res.getString("message.idle.for", time);
}
}
} catch (Exception e1) {
Log.warning( "Unable to get Last Activity from: " + contactItem.toString(), e1 );
}
} catch (XMPPException.XMPPErrorException e) {
Condition condition = e.getStanzaError().getCondition();
if (condition != Condition.feature_not_implemented) {
Log.warning("Unable to get Last Activity from: " + contactItem, e);
}
} catch (Exception e) {
Log.warning("Unable to get Last Activity from: " + contactItem, e);
}
}
statusLabel.setText(status);

View File

@ -211,7 +211,7 @@ public class RoomCreationDialog extends JPanel {
return false;
}
if (!ModelUtil.areEqual(password, confirmPassword)) {
if (!password.equals(confirmPassword)) {
showError(Res.getString("message.passwords.no.match"));
passwordField.requestFocus();
return false;

View File

@ -18,11 +18,11 @@ package org.jivesoftware.spark.util;
import org.jivesoftware.resource.Res;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
/**
* Utility methods frequently used by data classes and design-time
* classes.
@ -33,185 +33,6 @@ public final class ModelUtil {
// Prevent instantiation.
}
/**
* This is a utility method that compares two objects when one or
* both of the objects might be <CODE>null</CODE> The result of
* this method is determined as follows:
* <OL>
* <LI>If <CODE>o1</CODE> and <CODE>o2</CODE> are the same object
* according to the <CODE>==</CODE> operator, return
* <CODE>true</CODE>.
* <LI>Otherwise, if either <CODE>o1</CODE> or <CODE>o2</CODE> is
* <CODE>null</CODE>, return <CODE>false</CODE>.
* <LI>Otherwise, return <CODE>o1.equals(o2)</CODE>.
* </OL>
* <p/>
* This method produces the exact logically inverted result as the
* {@link #areDifferent(Object, Object)} method.<P>
* <p/>
* For array types, one of the <CODE>equals</CODE> methods in
* {@link java.util.Arrays} should be used instead of this method.
* Note that arrays with more than one dimension will require some
* custom code in order to implement <CODE>equals</CODE> properly.
*
* @param o1 first object to compare
* @param o2 second object to compare
* @return true if they are equal
*/
public static boolean areEqual(Object o1, Object o2) {
if (o1 == o2) {
return true;
}
else if (o1 == null || o2 == null) {
return false;
}
else {
return o1.equals(o2);
}
}
/**
* This is a utility method that compares two Booleans when one or
* both of the objects might be <CODE>null</CODE> The result of
* this method is determined as follows:
* <OL>
* <LI>If <CODE>b1</CODE> and <CODE>b2</CODE> are both TRUE or
* neither <CODE>b1</CODE> nor <CODE>b2</CODE> is TRUE,
* return <CODE>true</CODE>.
* <LI>Otherwise, return <CODE>false</CODE>.
* </OL>
* <p/>
* This method produces the exact logically inverted result as the
* areDifferent(Boolean, Boolean) method.<P>
*
* @param b1 First Boolean to compare
* @param b2 Second Boolean to compare
* @return True if the booleans are equal
*/
public static boolean areBooleansEqual(Boolean b1, Boolean b2) {
// !jwetherb treat NULL the same as Boolean.FALSE
return (b1 == Boolean.TRUE && b2 == Boolean.TRUE) ||
(b1 != Boolean.TRUE && b2 != Boolean.TRUE);
}
/**
* This is a utility method that compares two objects when one or
* both of the objects might be <CODE>null</CODE>. The result
* returned by this method is determined as follows:
* <OL>
* <LI>If <CODE>o1</CODE> and <CODE>o2</CODE> are the same object
* according to the <CODE>==</CODE> operator, return
* <CODE>false</CODE>.
* <LI>Otherwise, if either <CODE>o1</CODE> or <CODE>o2</CODE> is
* <CODE>null</CODE>, return <CODE>true</CODE>.
* <LI>Otherwise, return <CODE>!o1.equals(o2)</CODE>.
* </OL>
* <p/>
* This method produces the exact logically inverted result as the
* {@link #areEqual(Object, Object)} method.<P>
* <p/>
* For array types, one of the <CODE>equals</CODE> methods in
* {@link java.util.Arrays} should be used instead of this method.
* Note that arrays with more than one dimension will require some
* custom code in order to implement <CODE>equals</CODE> properly.
*
* @param o1 First object to compare
* @param o2 Second object to compare
* @return True if objects are different
*/
public static boolean areDifferent(Object o1, Object o2) {
return !areEqual(o1, o2);
}
/**
* This is a utility method that compares two Booleans when one or
* both of the objects might be <CODE>null</CODE> The result of
* this method is determined as follows:
* <OL>
* <LI>If <CODE>b1</CODE> and <CODE>b2</CODE> are both TRUE or
* neither <CODE>b1</CODE> nor <CODE>b2</CODE> is TRUE,
* return <CODE>false</CODE>.
* <LI>Otherwise, return <CODE>true</CODE>.
* </OL>
* <p/>
* This method produces the exact logically inverted result as the
* {@link #areBooleansEqual(Boolean, Boolean)} method.<P>
*
* @param b1 First boolean to compare
* @param b2 Second boolean to compare
* @return True if booleans are different
*/
public static boolean areBooleansDifferent(Boolean b1, Boolean b2) {
return !areBooleansEqual(b1, b2);
}
/**
* Returns <CODE>true</CODE> if the specified array is not null
* and contains a non-null element. Returns <CODE>false</CODE>
* if the array is null or if all the array elements are null.
*
* @param array Array to scan.
* @return True if there's a null element.
*/
public static boolean hasNonNullElement(Object[] array) {
if (array != null) {
for (Object o : array) {
if (o != null) {
return true;
}
}
}
return false;
}
/**
* Returns a single string that is the concatenation of all the
* strings in the specified string array. A single space is
* put between each string array element. Null array elements
* are skipped. If the array itself is null, the empty string
* is returned. This method is guaranteed to return a non-null
* value, if no expections are thrown.
*
* @param strs Array of strings to concatenate.
* @return Concatenated string.
*/
public static String concat(String[] strs) {
return concat(strs, " "); //NOTRANS
}
/**
* Returns a single string that is the concatenation of all the
* strings in the specified string array. The strings are separated
* by the specified delimiter. Null array elements are skipped. If
* the array itself is null, the empty string is returned. This
* method is guaranteed to return a non-null value, if no expections
* are thrown.
*
* @param strs Array of strings to concatenate.
* @param delim Delimeter to separate strings.
* @return Concatenated string.
*/
public static String concat(String[] strs, String delim) {
if (strs != null) {
final StringBuilder buf = new StringBuilder();
for (final String str : strs) {
if (str != null) {
buf.append(str).append(delim);
}
}
final int length = buf.length();
if (length > 0) {
// Trim trailing space.
buf.setLength(length - 1);
}
return buf.toString();
}
else {
return ""; // NOTRANS
}
}
/**
* Returns <CODE>true</CODE> if the specified {@link String} is not
@ -222,65 +43,20 @@ public final class ModelUtil {
* @return True if string is null or empty
*/
public static boolean hasLength(CharSequence s) {
return (s != null && !s.toString().trim().isEmpty());
return isNotBlank(s);
}
/**
* Returns <CODE>null</CODE> if the specified string is empty or
* <CODE>null</CODE>. Otherwise the string itself is returned.
*
* @param s String to check
* @return Returns null string if string is empty, otherwise string itself.
*/
public static String nullifyIfEmpty(String s) {
return ModelUtil.hasLength(s) ? s : null;
}
/**
* Returns <CODE>null</CODE> if the specified object is null
* or if its <CODE>toString()</CODE> representation is empty.
* Otherwise, the <CODE>toString()</CODE> representation of the
* object itself is returned.
*
* @param o Object to check
* @return Returns null string if string(object) is empty, otherwise string itself.
*/
public static String nullifyingToString(Object o) {
return o != null ? nullifyIfEmpty(o.toString()) : null;
}
/**
* Determines if a string has been changed.
*
* @param oldString is the initial value of the String
* @param newString is the new value of the String
* @return true If both oldString and newString are null or if they are
* both not null and equal to each other. Otherwise returns false.
*/
public static boolean hasStringChanged(String oldString, String newString) {
if (oldString == null && newString == null) {
return false;
}
else if (oldString == null || newString == null) {
return true;
}
else {
return !oldString.equals(newString);
}
}
/**
* Returns a formatted String from time.
*
* @param diff the amount of elapsed time.
* @return the formatte String.
* @return the formatted String.
*/
public static String getTimeFromLong(long diff) {
final String DAYS = Res.getString("time.days");
final String HOURS = Res.getString("time.hours");
final String MINUTES = Res.getString("time.minutes");
final String SECONDS = Res.getString("time.seconds");
final String LESS_THAN_ONE_MINUTE = Res.getString("time.less.than.one.minute");
final long MS_IN_A_DAY = 1000 * 60 * 60 * 24;
@ -291,47 +67,22 @@ public final class ModelUtil {
long numHours = diff / MS_IN_AN_HOUR;
diff = diff % MS_IN_AN_HOUR;
long numMinutes = diff / MS_IN_A_MINUTE;
if (numDays == 0 && numHours == 0 && numMinutes == 0) {
return LESS_THAN_ONE_MINUTE;
}
StringBuilder buf = new StringBuilder();
StringBuilder buf = new StringBuilder(40);
if(numDays > 0){
buf.append(numDays).append(" ").append(DAYS).append(", ");
buf.append(numDays).append(' ').append(DAYS).append(", ");
}
if (numHours > 0) {
buf.append(numHours).append(" ").append(HOURS).append(", ");
buf.append(numHours).append(' ').append(HOURS).append(", ");
}
if (numMinutes > 0) {
buf.append(numMinutes).append(" ").append(MINUTES);
}
//buf.append(numSeconds + " " + SECONDS);
String result = buf.toString();
if (numMinutes < 1) {
result = LESS_THAN_ONE_MINUTE;
}
return result;
buf.append(numMinutes).append(' ').append(MINUTES);
return buf.toString();
}
/**
* Build a List of all elements in an Iterator.
*
* @param i Iterator to return as a list.
* @return List converted from iterator.
*/
public static <T> List<T> iteratorAsList(Iterator<T> i) {
ArrayList<T> list = new ArrayList<>( 10 );
while (i.hasNext()) {
list.add(i.next());
}
return list;
}
/**
* Creates an Iterator that is the reverse of a ListIterator.
*

View File

@ -104,40 +104,6 @@ public class URLFileSystem {
out.flush();
}
/**
* If a dot ('.') occurs in the path portion of the {@link URL}, then
* all of the text starting at the last dot is returned, including
* the dot. If the last dot is also the last character in the path,
* then the dot by itself is returned. If there is no dot in the
* path, then the empty string is returned.
*
* @param url the URL.
* @return suffix of url path
*/
public static String getSuffix(URL url) {
final String path = url.getPath();
int lastDot = path.lastIndexOf('.');
return (lastDot >= 0) ? path.substring(lastDot) : "";
}
/**
* If a dot ('.') occurs in the path portion of the {@link File}, then
* all of the text starting at the last dot is returned, including
* the dot. If the last dot is also the last character in the path,
* then the dot by itself is returned. If there is no dot in the
* path, then the empty string is returned.
*
* @param file the File.
* @return suffix of filename
*/
public static String getSuffix(File file) {
final String path = file.getAbsolutePath();
int lastDot = path.lastIndexOf('.');
return (lastDot >= 0) ? path.substring(lastDot) : "";
}
//--------------------------------------------------------------------------
// URLFileSystemHelper public API...
//--------------------------------------------------------------------------

View File

@ -7,6 +7,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore;
import java.security.KeyStoreException;
@ -39,68 +40,84 @@ import org.jivesoftware.sparkimpl.settings.local.LocalPreferences;
* This class contain some methods and fields that are common for CertificateController and IdentityController classes.
* According to MVC it stands as Controller behind CertificatesManagerSettingsPanel and
* MutualAuthenticationSettingsPanel which are Views.
*
* @author Paweł Ścibiorski
*
* @author Paweł Ścibiorski
*/
public abstract class CertManager {
protected LocalPreferences localPreferences;
public final static char[] passwd = "changeit".toCharArray();
public final static char[] passwd = "changeit".toCharArray();
protected boolean addToKeystore;
// BLACKLIST is KeyStore with certificates revoked certificates, it isn't directly displayed but when other
// KeyStores content is added then it is compared with this list and information about revocation is added to
// certificate status
public final static File BLACKLIST = new File( Spark.getSparkUserHome() + File.separator + "security" + File.separator + "blacklist");
// contain all certificates, used for help in managing certificates, but isn't directly displayed on the certificate
// table
/**
* BLACKLIST is KeyStore with certificates revoked certificates, it isn't directly displayed but when other
* KeyStores content is added then it is compared with this list and information about revocation
* is added to certificate status
*/
public final static File BLACKLIST = new File(Spark.getSparkUserHome() + File.separator + "security" + File.separator + "blacklist");
/**
* Contain all certificates, used for help in managing certificates, but isn't directly displayed on the certificate table
*/
protected KeyStore blackListStore;
protected final List<CertificateModel> allCertificates = new LinkedList<>();
protected final List<CertificateModel> blackListedCertificates = new LinkedList<>(); //contain only revoked certificates
protected final List<CertificateModel> allCertificates = new LinkedList<>();
/**
* Contains only revoked certificates
*/
protected final List<CertificateModel> blackListedCertificates = new LinkedList<>();
protected DefaultTableModel tableModel;
public abstract void deleteEntry(String alias) throws KeyStoreException;
public abstract void addOrRemoveFromExceptionList(boolean checked);
public abstract boolean isOnExceptionList(CertificateModel cert);
public abstract void createTableModel();
protected abstract void refreshCertTable();
public abstract void addEntryFileToKeyStore(File file)
throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException, HeadlessException,
InvalidNameException, InvalidKeySpecException;
/**
* Check if there is certificate entry in KeyStore with the same alias.
* @param alias which is checked if it already exist in keystore
* @return
* @throws HeadlessException
* @throws KeyStoreException
*/
throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException, HeadlessException,
InvalidNameException, InvalidKeySpecException;
/**
* Check if there is certificate entry in KeyStore with the same alias.
*
* @param alias which is checked if it already exist in keystore
* @return
* @throws HeadlessException
* @throws KeyStoreException
*/
protected abstract boolean checkForSameAlias(String alias) throws HeadlessException, KeyStoreException;
/**
* Save the KeyStores.
*/
public abstract void loadKeyStores();
public abstract void overWriteKeyStores();
public void setAddToKeystore(boolean addToKeystore) {
this.addToKeystore = addToKeystore;
}
public boolean isAddToKeystore() {
return addToKeystore;
}
/**
* Check if this certificate already exist in Truststore.
*
*
* @param addedCert the certificate for which it method look in the model list
* @return true if KeyStore already have this certificate.
*/
protected boolean checkForSameCertificate(X509Certificate addedCert) {
// check if this certificate isn't already added to Truststore
for(CertificateModel model :allCertificates){
for (CertificateModel model : allCertificates) {
X509Certificate certificateCheck = model.getCertificate();
String signature = Base64.getEncoder().encodeToString(certificateCheck.getSignature());
String addedSignature = Base64.getEncoder().encodeToString(addedCert.getSignature());
@ -114,6 +131,7 @@ public abstract class CertManager {
/**
* Check if given certificate is revoked looking on it's CRL (if exist).
*
* @param cert which is validated
* @return true if certificate is revoked, false if it isn't or CRL cannot be accessed (because it might not exist).
*/
@ -121,7 +139,7 @@ public abstract class CertManager {
boolean revoked = false;
try {
SparkTrustManager man = new SparkTrustManager();
Collection<X509CRL> crls = man.loadCRL(new X509Certificate[] { cert });
Collection<X509CRL> crls = man.loadCRL(new X509Certificate[]{cert});
CertificateFactory cf = CertificateFactory.getInstance("X.509");
for (X509CRL crl : crls) {
if (crl.isRevoked(cert)) {
@ -130,7 +148,7 @@ public abstract class CertManager {
}
}
} catch (CRLException | CertificateException | IOException | InvalidAlgorithmParameterException
| NoSuchAlgorithmException e) {
| NoSuchAlgorithmException e) {
Log.warning("Cannot check validity", e);
}
return revoked;
@ -138,7 +156,7 @@ public abstract class CertManager {
/**
* This method adds certificate to blackList
*
*
* @param cert the certificate to be added to blacklist
* @throws KeyStoreException
* @throws InvalidNameException
@ -150,12 +168,12 @@ public abstract class CertManager {
blackListedCertificates.add(new CertificateModel(cert));
}
/**
* Extract from certificate common name ("CN") and returns it to use as certificate name.
* This method also assure that it will not add second same alias to Truststore by adding number to alias.
* This method also assure that it will not add second same alias to Truststore by adding number to alias.
* In case when common name cannot be extracted method will return "cert{number}".
*
*
* @param cert Certificate which Common Name is meant to use
* @return String Common Name of the certificate
* @throws InvalidNameException
@ -188,24 +206,24 @@ public abstract class CertManager {
}
return alias;
}
/**
* Open dialog with certificate.
*
*/
public abstract void showCertificate();
/**
* Open dialog with certificate.
*
*
* @param certModel Model of the certificate which details are meant to be shown.
* @param reason The reason for Certificate dialog to be shown.
* @param reason The reason for Certificate dialog to be shown.
*/
public CertificateDialog showCertificate(CertificateModel certModel, CertificateDialogReason reason) {
return new CertificateDialog(localPreferences, certModel, this, reason);
}
protected KeyStore openKeyStore(File file){
protected KeyStore openKeyStore(File file) {
KeyStore keyStore = null;
try {
keyStore = KeyStore.getInstance("JKS");
@ -214,7 +232,7 @@ public abstract class CertManager {
try (InputStream inputStream = new FileInputStream(file)) {
keyStore.load(inputStream, passwd);
} catch (IOException | NoSuchAlgorithmException | CertificateException e) {
Log.error("Error at accesing exceptions KeyStore", e);
Log.error("Unable to access KeyStore", e);
}
} else {
keyStore.load(null, passwd); // if cannot open KeyStore then new empty one will be created
@ -224,20 +242,18 @@ public abstract class CertManager {
}
return keyStore;
}
/**
* Add certificates from keyStore to list. Useful for displaying in certificate table.
*
*
* @param keyStore source keystore.
* @param list list which will be filled with certificate models.
* @param list list which will be filled with certificate models.
*/
protected List<CertificateModel> fillTableListWithKeyStoreContent(KeyStore keyStore, List<CertificateModel> list) {
if (keyStore != null) {
Enumeration<String> store;
try {
store = keyStore.aliases();
Enumeration<String> store = keyStore.aliases();
while (store.hasMoreElements()) {
String alias = store.nextElement();
X509Certificate certificate = (X509Certificate) keyStore.getCertificate(alias);
@ -254,17 +270,17 @@ public abstract class CertManager {
}
return list;
}
protected void saveKeyStore(KeyStore keyStore, File file){
try (OutputStream outputStream = new FileOutputStream(file)) {
protected void saveKeyStore(KeyStore keyStore, File file) {
try (OutputStream outputStream = Files.newOutputStream(file.toPath())) {
if (keyStore != null) {
keyStore.store(outputStream, passwd);
}
} catch (IOException | KeyStoreException | NoSuchAlgorithmException | CertificateException e) {
Log.error("Couldn't save KeyStore" , e);
Log.error("Couldn't save KeyStore", e);
}
}
public DefaultTableModel getTableModel() {
return tableModel;
}

View File

@ -19,13 +19,13 @@ import org.jivesoftware.sparkimpl.settings.local.SettingsManager;
/**
* This class contain some of the methods and variables that are common for Spark's TrustManagers
* @author Pawel Scibiorski
*
*/
public abstract class GeneralTrustManager implements X509TrustManager {
protected final LocalPreferences localPref = SettingsManager.getLocalPreferences();
protected final CertificateController certControll = new CertificateController(localPref);
protected KeyStore allStore;
protected abstract void loadKeyStores();
/**
* Adds content of the keystore to allStore which should contain all certificates from accepted issuers.
* @param keyStore
@ -37,20 +37,21 @@ public abstract class GeneralTrustManager implements X509TrustManager {
throws KeyStoreException, HeadlessException, InvalidNameException {
Enumeration<String> aliases = keyStore.aliases();
// Retrieve all of the certificates out of the KeyStore using aliases
// Retrieve all the certificates out of the KeyStore using aliases
while (aliases.hasMoreElements()) {
String alias = aliases.nextElement();
X509Certificate certificate = (X509Certificate) keyStore.getCertificate(alias);
allStore.setCertificateEntry(certControll.useCommonNameAsAlias(certificate), certificate);
}
}
protected void loadAllStore() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
allStore = KeyStore.getInstance("JKS");
allStore.load(null, CertificateController.passwd);
protected void loadAllStore() {
try {
allStore = KeyStore.getInstance("JKS");
allStore.load(null, CertificateController.passwd);
} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException | HeadlessException e) {
Log.error("Cannot create allStore KeyStore", e);
}
}
@Override
@ -59,16 +60,13 @@ public abstract class GeneralTrustManager implements X509TrustManager {
try {
// See how many certificates are in the keystore.
int numberOfEntry = allStore.size();
// Create an array of X509Certificates
X509Certs = new X509Certificate[numberOfEntry];
// If there are any certificates in the keystore.
if (numberOfEntry > 0) {
// Get all of the certificate alias out of the keystore.
// Get all the certificate alias out of the keystore.
Enumeration<String> aliases = allStore.aliases();
// Retrieve all of the certificates out of the keystore
// Retrieve all the certificates out of the keystore
// via the alias name.
int i = 0;
while (aliases.hasMoreElements()) {

View File

@ -17,15 +17,16 @@ import javax.net.ssl.X509TrustManager;
import org.jivesoftware.spark.util.log.Log;
/**
* This TrustManager serves for purpose of accepting certificates from exceptions lists. The only check it does is check
* if certification path can be builded. It doesn't do any checks against time of expiration or revocation.
* This TrustManager serves for purpose of accepting certificates from exceptions lists.
* The only check it does is check if certification path can be built.
* It doesn't do any checks against time of expiration or revocation.
*
* @author Pawel Scibiorski
*
*/
public class SparkExceptionsTrustManager extends GeneralTrustManager implements X509TrustManager {
KeyStore exceptionsStore, cacertsExceptionsStore;
public SparkExceptionsTrustManager() {
loadKeyStores();
}
@ -51,9 +52,10 @@ public class SparkExceptionsTrustManager extends GeneralTrustManager implements
}
/**
* Validate certificate path. As it is exception, no checks against revocation or time validity are done but path
* still have to be validated in order to find connection between certificate presented by server and root CA in
* KeyStore
* Validate certificate path.
* As it is exception, no checks against revocation or time validity are done.
* But the path still have to be validated in order to find connection between
* certificate presented by server and root CA in KeyStore
*
* @throws NoSuchAlgorithmException
* @throws KeyStoreException
@ -70,8 +72,8 @@ public class SparkExceptionsTrustManager extends GeneralTrustManager implements
throw new IllegalArgumentException("Method cannot be used with self-signed certificate.");
}
// The certificate representing the {@link TrustAnchor TrustAnchor} should not be included in the certification
// path. If it does, certain validation (like OCSP) might give unexpected results/fail. SPARK-2188
// The certificate representing the {@link TrustAnchor} should not be included in the certification path.
// If it does, certain validation (like OCSP) might give unexpected results/fail. SPARK-2188
final List<X509Certificate> certificates = Arrays.stream(chain)
.filter( cert -> !SparkTrustManager.isRootCACertificate(cert))
.collect(Collectors.toList());
@ -101,7 +103,6 @@ public class SparkExceptionsTrustManager extends GeneralTrustManager implements
PKIXCertPathValidatorResult validationResult = (PKIXCertPathValidatorResult) certPathValidator
.validate(certPath, parameters);
X509Certificate trustAnchor = validationResult.getTrustAnchor().getTrustedCert();
if (trustAnchor == null) {
throw new CertificateException("certificate path failed: Trusted CA is NULL");
}
@ -130,7 +131,6 @@ public class SparkExceptionsTrustManager extends GeneralTrustManager implements
} else {
return exceptionsStore.getCertificateAlias(chain[chain.length - 1]) != null;
}
}
/**
@ -140,12 +140,8 @@ public class SparkExceptionsTrustManager extends GeneralTrustManager implements
protected void loadKeyStores() {
exceptionsStore = certControll.openKeyStore(CertificateController.EXCEPTIONS);
cacertsExceptionsStore = certControll.openKeyStore(CertificateController.CACERTS_EXCEPTIONS);
try {
loadAllStore();
} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException | HeadlessException e) {
Log.error("Cannot create allStore KeyStore");
}
loadAllStore();
try {
addKeyStoreContentToAllStore(exceptionsStore);
} catch (HeadlessException | KeyStoreException | InvalidNameException e) {
@ -156,7 +152,6 @@ public class SparkExceptionsTrustManager extends GeneralTrustManager implements
} catch (HeadlessException | KeyStoreException | InvalidNameException e) {
Log.error("Cannot add cacertsExceptionsStore to allStore", e);
}
}
}

View File

@ -19,6 +19,7 @@ import java.util.stream.Collectors;
import javax.naming.InvalidNameException;
import javax.net.ssl.X509TrustManager;
import org.apache.commons.lang3.ArrayUtils;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.x509.CRLDistPoint;
import org.bouncycastle.asn1.x509.DistributionPoint;
@ -30,13 +31,12 @@ import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils;
import org.jivesoftware.spark.util.log.Log;
/**
* This trust manager wrap around SparkExceptionsTrustManager. In case when SparkExceptionsTrustManager fail then this
* This trust manager wrap around SparkExceptionsTrustManager.
* In case when SparkExceptionsTrustManager fail then this
* TrustManager will provide certificates from TRUSTED KeyStore which are checked against data validity, revocation,
* acceptance of self-signed certificates and basic constraints.
*
*
* @author Pawel Scibiorsk
*
* @author Pawel Scibiorsk
*/
public class SparkTrustManager extends GeneralTrustManager implements X509TrustManager {
@ -101,13 +101,13 @@ public class SparkTrustManager extends GeneralTrustManager implements X509TrustM
/**
* Do chain validity checks
* @param chain with certificates from server
* @param authType
* @param authType "RSA" etc.
* @throws CertificateException
* @throws CertPathValidatorException
*/
private void doTheChecks(X509Certificate[] chain, String authType) throws CertificateException, CertPathValidatorException {
try {
// first check if certificate is accepted as as certificate from exceptions list, exceptionsTrustManager
// first check if certificate is accepted as a certificate from exceptions list, exceptionsTrustManager
// will make use of chain provided by exceptions KeyStore
exceptionsTrustManager.checkServerTrusted(chain, authType);
} catch (CertificateException ex) {
@ -121,22 +121,18 @@ public class SparkTrustManager extends GeneralTrustManager implements X509TrustM
// validate certificate path
try {
validatePath(chain);
} catch (NoSuchAlgorithmException | KeyStoreException | InvalidAlgorithmParameterException | CertPathValidatorException e) {
Log.error("Validating path failed", e);
throw new CertPathValidatorException("Certificate path validation failed", e);
}
} else if (isSelfSigned(chain) && !acceptSelfSigned) {
// Self Signed certificate while it isn't accepted
throw new CertificateException("Self Signed certificate");
} else if (isSelfSigned(chain) && acceptSelfSigned) {
// check if certificate is in Keystore and check CRL, but do not validate path as certificate is Self
// Signed important reminder: hostname validation must be also turned off to accept self signed
// certificate
List<X509Certificate> certList = new ArrayList<>(Arrays.asList(getAcceptedIssuers()));
if (!certList.contains(chain[0])) {
if (!ArrayUtils.contains(getAcceptedIssuers(), chain[0])) {
throw new CertPathValidatorException("Certificate not in the TrustStore");
}
try {
@ -239,7 +235,6 @@ public class SparkTrustManager extends GeneralTrustManager implements X509TrustM
// if revoked certificates aren't accepted, but no revocation checks then only
// certificates from blacklist will be rejected
if (!acceptRevoked) {
// OCSP checking is done according to Java PKI Programmer's Guide, PKIXRevocationChecker was added in Java 8:
// https://docs.oracle.com/javase/8/docs/technotes/guides/security/certpath/CertPathProgGuide.html#PKIXRevocationChecker
PKIXRevocationChecker checker = (PKIXRevocationChecker) certPathBuilder.getRevocationChecker();
@ -262,14 +257,12 @@ public class SparkTrustManager extends GeneralTrustManager implements X509TrustM
checker.setOptions(checkerOptions);
parameters.addCertPathChecker(checker);
}
}
try {
PKIXCertPathValidatorResult validationResult = (PKIXCertPathValidatorResult) certPathValidator
.validate(certPath, parameters);
X509Certificate trustAnchor = validationResult.getTrustAnchor().getTrustedCert();
if (trustAnchor == null) {
throw new CertificateException("certificate path failed: Trusted CA is NULL");
}
@ -312,7 +305,6 @@ public class SparkTrustManager extends GeneralTrustManager implements X509TrustM
* @throws CertificateException
*/
private void checkDateValidity(X509Certificate[] chain) throws CertificateException {
for (X509Certificate cert : chain) {
// expiration check
try {
@ -328,7 +320,6 @@ public class SparkTrustManager extends GeneralTrustManager implements X509TrustM
throw new CertificateException("Certificate is not valid yet");
}
}
}
}
@ -377,7 +368,7 @@ public class SparkTrustManager extends GeneralTrustManager implements X509TrustM
}
/**
* loads truststores and potentially (depending on settings) blacklist
* loads trust stores and potentially (depending on settings) blacklist
*/
@Override
protected void loadKeyStores() {
@ -385,12 +376,7 @@ public class SparkTrustManager extends GeneralTrustManager implements X509TrustM
trustStore = certControll.openKeyStore(CertificateController.TRUSTED);
displayedCaCerts = certControll.openCacertsKeyStore();
try {
loadAllStore();
} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException
| HeadlessException e) {
Log.error("Cannot create allStore KeyStore");
}
loadAllStore();
try {
addKeyStoreContentToAllStore(trustStore);
@ -402,7 +388,6 @@ public class SparkTrustManager extends GeneralTrustManager implements X509TrustM
} catch (HeadlessException | KeyStoreException | InvalidNameException e) {
Log.error("Cannot add displayedCaCerts to the allStore", e);
}
}
@ -469,7 +454,6 @@ public class SparkTrustManager extends GeneralTrustManager implements X509TrustM
* @throws CRLException
*/
private X509CRL downloadCRL(URL url) throws IOException, CertificateException, CRLException {
try (InputStream crlStream = url.openStream()) {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
return (X509CRL) cf.generateCRL(crlStream);

View File

@ -19,7 +19,6 @@ import org.jivesoftware.resource.Res;
import org.jivesoftware.spark.util.GraphicUtils;
import org.jivesoftware.spark.util.ResourceUtils;
import org.jivesoftware.spark.util.SwingWorker;
import org.jivesoftware.spark.util.URLFileSystem;
import org.jivesoftware.spark.util.log.Log;
import net.coobird.thumbnailator.Thumbnails;
@ -47,9 +46,10 @@ import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import static org.apache.commons.lang3.StringUtils.endsWithAny;
/**
* UI to view/edit avatar.
*/
@ -101,7 +101,7 @@ public class AvatarPanel extends JPanel implements ActionListener {
/**
* Sets if the Avatar can be edited.
*
* @param editable true if edtiable.
* @param editable true if editable.
*/
public void setEditable(boolean editable) {
browseButton.setVisible(editable);
@ -109,7 +109,7 @@ public class AvatarPanel extends JPanel implements ActionListener {
}
/**
* Sets the displayable icon with the users avatar.
* Sets the displayable icon with the user's avatar.
*
* @param icon the icon.
*/
@ -167,22 +167,13 @@ public class AvatarPanel extends JPanel implements ActionListener {
fileChooser.setVisible(true);
if (fileChooser.getDirectory() != null && fileChooser.getFile() != null) {
File file = new File(fileChooser.getDirectory(), fileChooser.getFile());
String suffix = URLFileSystem.getSuffix(file);
if (suffix.toLowerCase().equals(".jpeg") ||
suffix.toLowerCase().equals(".gif") ||
suffix.toLowerCase().equals(".jpg") ||
suffix.toLowerCase().equals(".png")) {
changeAvatar(file, this);
}
else {
UIManager.put("OptionPane.okButtonText", Res.getString("ok"));
JOptionPane.showMessageDialog(this, "Please choose a valid image file.", Res.getString("title.error"), JOptionPane.ERROR_MESSAGE);
}
final File[] files = fileChooser.getFiles();
if (files.length == 0) {
// no selection
return;
}
File file = files[0]; // Single-file selection is used. Using the first array item is safe.
changeAvatar(file, this);
}
private void changeAvatar(final File selectedFile, final Component parent) {
@ -195,6 +186,10 @@ public class AvatarPanel extends JPanel implements ActionListener {
@Override
public void finished() {
BufferedImage avatarImage = (BufferedImage)get();
if (avatarImage == null) {
UIManager.put("OptionPane.okButtonText", Res.getString("ok"));
JOptionPane.showMessageDialog(parent, "Please choose a valid image file.", Res.getString("title.error"), JOptionPane.ERROR_MESSAGE);
}
String message = "";
int finalImageWidth = avatarImage.getWidth();
int finalImageHeight = avatarImage.getHeight();
@ -239,47 +234,6 @@ public class AvatarPanel extends JPanel implements ActionListener {
worker.start();
}
public static class ImageFilter implements FilenameFilter {
public final String jpeg = "jpeg";
public final String jpg = "jpg";
public final String gif = "gif";
public final String png = "png";
//Accept all directories and all gif, jpg, tiff, or png files.
@Override
public boolean accept(File f, String string) {
if (f.isDirectory()) {
return true;
}
String extension = getExtension(f);
if (extension != null) {
return extension.equals(gif) || extension.equals(jpeg) || extension.equals(jpg) || extension.equals(png);
}
return false;
}
/*
* Get the extension of a file.
*/
public String getExtension(File f) {
String ext = null;
String s = f.getName();
int i = s.lastIndexOf('.');
if (i > 0 && i < s.length() - 1) {
ext = s.substring(i + 1).toLowerCase();
}
return ext;
}
//The description of this filter
public String getDescription() {
return "*.JPEG, *.GIF, *.PNG";
}
}
public void allowEditing(boolean allowEditing) {
Component[] comps = getComponents();
if (comps != null) {
@ -294,7 +248,7 @@ public class AvatarPanel extends JPanel implements ActionListener {
public void initFileChooser() {
if (fileChooser == null) {
fileChooser = new FileDialog(dlg, "Choose Avatar", FileDialog.LOAD);
fileChooser.setFilenameFilter(new ImageFilter());
fileChooser.setFilenameFilter((dir, name) -> endsWithAny(name.toLowerCase(), ".jpeg", ".jpg", ".gif", ".png"));
}
}
@ -302,31 +256,15 @@ public class AvatarPanel extends JPanel implements ActionListener {
this.dlg = dialog;
}
/*
* Resize images larger than 96 pixels
* without changing aspect ratio.
* Resize images larger than 96 pixels without changing aspect ratio.
* Returns modified image as BufferedImage.
*/
private BufferedImage resizeImage(File selectedFile) {
int targetImagePixels = 64;
BufferedImage resizedImage = null;
try {
BufferedImage avatarImageBuffered = ImageIO.read(selectedFile);
int currentImageWidth = avatarImageBuffered.getWidth(null);
int currentImageHeight = avatarImageBuffered.getHeight(null);
if (currentImageHeight <= 96 && currentImageWidth <= 96) {
// no need to resize
resizedImage = avatarImageBuffered;
} else {
double scaleFactor;
if (currentImageHeight > currentImageWidth) {
scaleFactor = (double) targetImagePixels / (double) currentImageHeight;
} else {
scaleFactor = (double) targetImagePixels / (double) currentImageWidth;
}
// resize image
resizedImage = Thumbnails.of(avatarImageBuffered).scale(scaleFactor).asBufferedImage();
}
resizedImage = Thumbnails.of(selectedFile)
.size(96, 96)
.asBufferedImage();
} catch (IOException ex) {
Log.error(ex);
}

View File

@ -81,10 +81,6 @@ public class UserSettings {
return getSettings().get(name);
}
public String getEmptyPropertyIfNull(String name) {
return ModelUtil.nullifyIfEmpty(getSettings().get(name));
}
public void save() {
try {
privateDataManager.setPrivateData(settingsData);

View File

@ -185,7 +185,7 @@ public class LocalPreferences {
/**
* Checks if the preferences contain any stored/saved account passwords.
*
* @return true if at least one stored account passsword was found, otherwise null.
* @return true if at least one stored account password was found, otherwise null.
*/
public boolean hasStoredPasswords() {
return !findPropertyNamesForStoredPasswords().isEmpty();
@ -210,7 +210,7 @@ public class LocalPreferences {
private Set<String> findPropertyNamesForStoredPasswords() {
return props.stringPropertyNames().stream()
// The property name starts with 'password'.
.filter(name -> name.startsWith("password"))
.filter(name -> name.startsWith("password") && !name.equals("passwordSaved"))
// The value of the property is an encrypted value.
.filter( name -> {

View File

@ -922,7 +922,6 @@ title.certificate = Certificate
time.days = d
time.hours = h
time.minutes = min
time.seconds = sec
time.since = since
time.less.than.one.minute = less than 1 minute

View File

@ -921,7 +921,6 @@ title.certificate = Certificaat
time.days = d
time.hours = h
time.minutes = min
time.seconds = sec
time.since = sinds
time.less.than.one.minute = minder dan 1 minuut

View File

@ -922,7 +922,6 @@ title.certificate = Сертификат
time.days = д
time.hours = ч
time.minutes = мин
time.seconds = с
time.since = с
time.less.than.one.minute = меньше 1 минуты

View File

@ -922,7 +922,6 @@ title.certificate = 证书
time.days =
time.hours = 小时
time.minutes = 分钟
time.seconds =
time.since = 自从
time.less.than.one.minute = 少于 1 分钟

View File

@ -155,49 +155,4 @@ final public class FormUtils {
return message.getFrom().getResourceOrThrow();
}
/**
* Returns better looking time String.
* @param seconds the number of seconds to calculate.
*/
public static String getTimeFromLong(long seconds) {
final String DAYS = Res.getString("time.days");
final String HOURS = Res.getString("time.hours");
final String MINUTES = Res.getString("time.minutes");
final String SECONDS = Res.getString("time.seconds");
final String LESS_THAN_ONE_MINUTE = Res.getString("time.less.than.one.minute");
final long MS_IN_A_DAY = 1000 * 60 * 60 * 24;
final long MS_IN_AN_HOUR = 1000 * 60 * 60;
final long MS_IN_A_MINUTE = 1000 * 60;
final long MS_IN_A_SECOND = 1000;
Date currentTime = new Date();
long numDays = seconds / MS_IN_A_DAY;
seconds = seconds % MS_IN_A_DAY;
long numHours = seconds / MS_IN_AN_HOUR;
seconds = seconds % MS_IN_AN_HOUR;
long numMinutes = seconds / MS_IN_A_MINUTE;
seconds = seconds % MS_IN_A_MINUTE;
long numSeconds = seconds / MS_IN_A_SECOND;
seconds = seconds % MS_IN_A_SECOND;
long numMilliseconds = seconds;
StringBuilder buf = new StringBuilder();
if (numHours > 0) {
buf.append(numHours).append(" ").append(HOURS).append(", ");
}
if (numMinutes > 0) {
buf.append(numMinutes).append(" ").append(MINUTES);
}
String result = buf.toString();
if (numMinutes < 1) {
result = LESS_THAN_ONE_MINUTE;
}
return result;
}
}

View File

@ -365,7 +365,7 @@ public class WorkgroupManager {
while (true) {
if (workgroup.isInQueue()) {
queuePostionLabel.setText("Current Position in Queue: " + workgroup.getQueuePosition());
queueWaitTime.setText("It is estimated your wait time to now be " + FormUtils.getTimeFromLong(workgroup.getQueueRemainingTime()));
queueWaitTime.setText("It is estimated your wait time to now be " + ModelUtil.getTimeFromLong(workgroup.getQueueRemainingTime()));
}
else {
return true;

View File

@ -144,7 +144,6 @@ title.number.of.conversations.found = # of conversations found:
time.days = d
time.hours = h
time.minutes = min
time.seconds = sec
time.since = since
time.less.than.one.minute = less than 1 minute

View File

@ -144,7 +144,6 @@ title.number.of.conversations.found = # de conversaciones encontradas:
time.days = d
time.hours = h
time.minutes = min
time.seconds = seg
time.since = desde
time.less.than.one.minute = menos de 1 minuto

View File

@ -144,7 +144,6 @@ title.number.of.conversations.found = # de conversações encontradas:
time.days = d
time.hours = h
time.minutes = min
time.seconds = seg
time.since = desde
time.less.than.one.minute = menos do que 1 minuto

View File

@ -144,7 +144,6 @@ title.number.of.conversations.found = # количество найденных
time.days = д
time.hours = ч
time.minutes = мин
time.seconds = сек
time.since = начиная
time.less.than.one.minute = меньше чем 1 минута

View File

@ -144,7 +144,6 @@ title.number.of.conversations.found = # 的对话已找到:
time.days =
time.hours =
time.minutes =
time.seconds =
time.since =
time.less.than.one.minute = 小于 1 分钟