Skip to content

Commit

Permalink
Various locale fixes
Browse files Browse the repository at this point in the history
Fixes install on Arabic
Fixes cert year calculation for Thailand
Catches JNA issues introduced with Big Sur
Closes qzind#680
Related qzind#683
  • Loading branch information
tresf authored Jul 2, 2020
1 parent e679074 commit 11b032d
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 25 deletions.
Binary file added lib/java-semver-0.10.0.jar
Binary file not shown.
Binary file removed lib/java-semver-0.9.0.jar
Binary file not shown.
11 changes: 1 addition & 10 deletions src/qz/common/AboutInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@
import java.security.GeneralSecurityException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

public class AboutInfo {
Expand Down Expand Up @@ -110,7 +108,7 @@ private static JSONObject ssl(CertificateManager certificateManager) throws JSON
cert.put("rootca", false);
}
cert.put("subject", x509.getSubjectX500Principal().getName());
cert.put("expires", toISO(x509.getNotAfter()));
cert.put("expires", SystemUtilities.toISO(x509.getNotAfter()));
cert.put("data", formatCert(x509.getEncoded()));
certs.put(cert);
}
Expand Down Expand Up @@ -144,13 +142,6 @@ public static String getPreferredHostname() {
return preferredHostname;
}

private static String toISO(Date d) {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'");
TimeZone tz = TimeZone.getTimeZone("UTC");
df.setTimeZone(tz);
return df.format(d);
}

public static Version findLatestVersion() {
try {
URL api = new URL(Constants.VERSION_CHECK_URL);
Expand Down
30 changes: 25 additions & 5 deletions src/qz/common/SecurityInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,26 @@
* Created by Kyle B. on 10/27/2017.
*/
public class SecurityInfo {
/**
* Wrap throwable operations into a try/catch
*/
private static class CheckedTreeMap<K, V> extends TreeMap<K, V> {
private static final Logger log = LoggerFactory.getLogger(CheckedTreeMap.class);

interface CheckedValue {
Object check() throws Throwable;
}

@SuppressWarnings("unchecked")
public V put(K key, CheckedValue value) {
try {
return put(key, (V)value.check());
} catch(Throwable t) {
log.warn("A checked exception was suppressed adding key \"{}\"", key, t);
}
return null;
}
}

private static final Logger log = LoggerFactory.getLogger(SecurityInfo.class);

Expand All @@ -44,19 +64,19 @@ public static KeyStore getKeyStore(Properties props) {
}

public static SortedMap<String,String> getLibVersions() {
SortedMap<String,String> libVersions = new TreeMap<>();
CheckedTreeMap<String,String> libVersions = new CheckedTreeMap<>();

// Use API-provided mechanism if available
libVersions.put("jna (native)", Native.VERSION_NATIVE);
libVersions.put("jna (native)", () -> Native.VERSION_NATIVE);
libVersions.put("jna", Native.VERSION);
libVersions.put("jssc", jssc.SerialNativeInterface.getLibraryVersion());
libVersions.put("jssc", () -> jssc.SerialNativeInterface.getLibraryVersion());
libVersions.put("jetty", Jetty.VERSION);
libVersions.put("pdfbox", org.apache.pdfbox.util.Version.getVersion());
libVersions.put("purejavahidapi", PureJavaHidApi.getVersion());
libVersions.put("purejavahidapi", () -> PureJavaHidApi.getVersion());
libVersions.put("usb-api", javax.usb.Version.getApiVersion());
libVersions.put("not-yet-commons-ssl", org.apache.commons.ssl.Version.VERSION);
libVersions.put("mslinks", mslinks.ShellLink.VERSION);
libVersions.put("simplersa", null);
libVersions.put("simplersa", (String)null);
libVersions.put("bouncycastle", "" + new BouncyCastleProvider().getVersion());

libVersions.put("jre", Constants.JAVA_VERSION.toString());
Expand Down
13 changes: 9 additions & 4 deletions src/qz/installer/certificate/CertificateChainBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.math.BigInteger;
import java.security.*;
import java.util.Calendar;
import java.util.Locale;

import org.bouncycastle.asn1.*;
import org.bouncycastle.asn1.x500.X500Name;
Expand All @@ -30,6 +31,7 @@
import org.bouncycastle.operator.OperatorException;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import qz.common.Constants;
import qz.utils.SystemUtilities;

import static qz.installer.certificate.KeyPairWrapper.Type.*;

Expand Down Expand Up @@ -96,7 +98,7 @@ private static KeyPair createRsaKey() throws GeneralSecurityException {
}

private static X509v3CertificateBuilder createX509Cert(KeyPair keyPair, int age, String ... hostNames) {
String cn = hostNames.length > 0 ? hostNames[0] : DEFAULT_HOSTNAMES[0];
String cn = hostNames.length > 0? hostNames[0]:DEFAULT_HOSTNAMES[0];
X500Name name = new X500NameBuilder()
.addRDN(BCStyle.C, Constants.ABOUT_COUNTRY)
.addRDN(BCStyle.ST, Constants.ABOUT_STATE)
Expand All @@ -107,12 +109,15 @@ private static X509v3CertificateBuilder createX509Cert(KeyPair keyPair, int age,
.addRDN(BCStyle.CN, cn)
.build();
BigInteger serial = BigInteger.valueOf(System.currentTimeMillis());
Calendar notBefore = Calendar.getInstance();
Calendar notAfter = Calendar.getInstance();
Calendar notBefore = Calendar.getInstance(Locale.ENGLISH);
Calendar notAfter = Calendar.getInstance(Locale.ENGLISH);
notBefore.add(Calendar.DAY_OF_YEAR, -1);
notAfter.add(Calendar.DAY_OF_YEAR, age - 1);

return new JcaX509v3CertificateBuilder(name, serial, notBefore.getTime(), notAfter.getTime(), name, keyPair.getPublic());
SystemUtilities.swapLocale();
X509v3CertificateBuilder x509builder = new JcaX509v3CertificateBuilder(name, serial, notBefore.getTime(), notAfter.getTime(), name, keyPair.getPublic());
SystemUtilities.restoreLocale();
return x509builder;
}

/**
Expand Down
11 changes: 6 additions & 5 deletions src/qz/installer/certificate/ExpiryTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.slf4j.LoggerFactory;
import qz.common.Constants;
import qz.utils.ShellUtilities;
import qz.utils.SystemUtilities;

import javax.naming.InvalidNameException;
import javax.naming.ldap.LdapName;
Expand Down Expand Up @@ -122,26 +123,26 @@ public static ExpiryState getExpiry(X509Certificate cert) {
}

Date expireDate = cert.getNotAfter();
Calendar now = Calendar.getInstance();
Calendar expires = Calendar.getInstance();
Calendar now = Calendar.getInstance(Locale.ENGLISH);
Calendar expires = Calendar.getInstance(Locale.ENGLISH);
expires.setTime(expireDate);

// Expired
if (now.after(expires)) {
log.info("SSL certificate has expired {}. It must be renewed immediately.", expireDate);
log.info("SSL certificate has expired {}. It must be renewed immediately.", SystemUtilities.toISO(expireDate));
return ExpiryState.EXPIRED;
}

// Expiring
expires.add(Calendar.DAY_OF_YEAR, -DEFAULT_GRACE_PERIOD_DAYS);
if (now.after(expires)) {
log.info("SSL certificate will expire in less than {} days: {}", DEFAULT_GRACE_PERIOD_DAYS, expireDate);
log.info("SSL certificate will expire in less than {} days: {}", DEFAULT_GRACE_PERIOD_DAYS, SystemUtilities.toISO(expireDate));
return ExpiryState.EXPIRING;
}

// Valid
int days = (int)Math.round((expireDate.getTime() - new Date().getTime()) / (double)86400000);
log.info("SSL certificate is still valid for {} more days: {}. We'll make a new one automatically when needed.", days, expireDate);
log.info("SSL certificate is still valid for {} more days: {}. We'll make a new one automatically when needed.", days, SystemUtilities.toISO(expireDate));
return ExpiryState.VALID;
}

Expand Down
24 changes: 24 additions & 0 deletions src/qz/utils/SystemUtilities.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@
import java.net.URLDecoder;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

import static com.sun.jna.platform.win32.WinReg.*;

Expand All @@ -37,6 +41,7 @@ public class SystemUtilities {
// Name of the os, i.e. "Windows XP", "Mac OS X"
private static final String OS_NAME = System.getProperty("os.name").toLowerCase(Locale.ENGLISH);
private static final Logger log = LoggerFactory.getLogger(TrayManager.class);
private static final Locale defaultLocale = Locale.getDefault();

private static Boolean darkDesktop;
private static Boolean darkTaskbar;
Expand All @@ -55,6 +60,25 @@ public static String getOS() {
return OS_NAME;
}

/**
* Call to workaround Locale-specific bugs (See issue #680)
* Please call <code>restoreLocale()</code> as soon as possible
*/
public static synchronized void swapLocale() {
Locale.setDefault(Locale.ENGLISH);
}

public static synchronized void restoreLocale() {
Locale.setDefault(defaultLocale);
}

public static String toISO(Date d) {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'", Locale.ENGLISH);
TimeZone tz = TimeZone.getTimeZone("UTC");
df.setTimeZone(tz);
return df.format(d);
}

public static Version getOSVersion() {
if (osVersion == null) {
String version = System.getProperty("os.version");
Expand Down
4 changes: 3 additions & 1 deletion src/qz/ws/HttpAboutServlet.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) {
private void generateHtmlResponse(HttpServletRequest request, HttpServletResponse response) {
StringBuilder display = new StringBuilder();

display.append("<html><body>")
display.append("<html>")
.append("<head><meta charset=\"UTF-8\"></head>")
.append("<body>")
.append("<h1>About</h1>");

display.append(newTable());
Expand Down

0 comments on commit 11b032d

Please sign in to comment.