mirror of
https://github.com/mitb-archive/filebot
synced 2024-12-23 08:18:52 -05:00
Refactor
This commit is contained in:
parent
749e614d50
commit
6f481c0102
@ -8,7 +8,6 @@ import static net.filebot.util.RegularExpressions.*;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.Serializable;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.StandardCopyOption;
|
import java.nio.file.StandardCopyOption;
|
||||||
@ -19,55 +18,118 @@ import java.time.ZonedDateTime;
|
|||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
import net.filebot.util.SystemProperty;
|
import net.filebot.util.SystemProperty;
|
||||||
import net.filebot.web.WebRequest;
|
import net.filebot.web.WebRequest;
|
||||||
|
|
||||||
public class License implements Serializable {
|
public class License {
|
||||||
|
|
||||||
private String product;
|
private final String product;
|
||||||
private String id;
|
private final String id;
|
||||||
private Instant expires;
|
private final Instant expires;
|
||||||
|
|
||||||
private Exception error;
|
private final Exception error;
|
||||||
|
|
||||||
public License(File file) {
|
private License(String product, String id, Instant expires) {
|
||||||
try {
|
this.product = product;
|
||||||
// read and verify license file
|
this.id = id;
|
||||||
if (!file.exists()) {
|
this.expires = expires;
|
||||||
throw new FileNotFoundException("UNREGISTERED");
|
this.error = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private License(Exception error) {
|
||||||
|
this.product = null;
|
||||||
|
this.id = null;
|
||||||
|
this.expires = null;
|
||||||
|
this.error = error;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean expires() {
|
||||||
|
return expires != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean error() {
|
||||||
|
return error != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public License check() throws Exception {
|
||||||
|
if (error()) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expires()) {
|
||||||
|
checkExpirationDate(expires);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
// FileBot License T1000
|
||||||
|
StringBuilder s = new StringBuilder().append(product).append(" License ").append(id);
|
||||||
|
|
||||||
|
// Valid-Until: 2019-07-04
|
||||||
|
if (expires()) {
|
||||||
|
s.append(" (Valid-Until: ").append(formatExpirationDate(expires)).append(")");
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static License parseLicenseFile(File file) {
|
||||||
|
if (!file.exists()) {
|
||||||
|
return new License(new FileNotFoundException("UNREGISTERED"));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// read and verify license file
|
||||||
byte[] bytes = Files.readAllBytes(file.toPath());
|
byte[] bytes = Files.readAllBytes(file.toPath());
|
||||||
|
|
||||||
// verify and get clear signed content
|
// verify and get clear signed content
|
||||||
Map<String, String> properties = getProperties(bytes);
|
Map<String, String> properties = getProperties(bytes);
|
||||||
|
|
||||||
this.product = properties.get("Product");
|
String product = properties.get("Product");
|
||||||
this.id = properties.get("Order");
|
String id = properties.get("Order");
|
||||||
this.expires = LocalDate.parse(properties.get("Valid-Until"), DateTimeFormatter.ISO_LOCAL_DATE).atStartOfDay(ZoneOffset.UTC).plusDays(1).minusSeconds(1).toInstant();
|
Instant expires = Optional.ofNullable(properties.get("Valid-Until")).map(License::parseExpirationDate).orElse(null);
|
||||||
|
|
||||||
|
// check validity
|
||||||
|
checkExpirationDate(expires);
|
||||||
|
|
||||||
// verify license online
|
// verify license online
|
||||||
verifyLicense(bytes);
|
verifyLicense(id, bytes);
|
||||||
} catch (Exception e) {
|
|
||||||
error = e;
|
return new License(product, id, expires);
|
||||||
|
} catch (Exception error) {
|
||||||
|
return new License(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getExpirationDate() {
|
private static Map<String, String> getProperties(byte[] bytes) throws Exception {
|
||||||
return expires == null ? null : expires.atZone(ZoneOffset.UTC).format(DateTimeFormatter.ISO_LOCAL_DATE);
|
byte[] pub = IOUtils.toByteArray(License.class.getResource("license.key"));
|
||||||
}
|
|
||||||
|
|
||||||
private Map<String, String> getProperties(byte[] bytes) throws Exception {
|
|
||||||
byte[] pub = IOUtils.toByteArray(getClass().getResource("license.key"));
|
|
||||||
String msg = verifyClearSignMessage(bytes, pub);
|
String msg = verifyClearSignMessage(bytes, pub);
|
||||||
|
|
||||||
return NEWLINE.splitAsStream(msg).map(s -> s.split(": ", 2)).collect(toMap(a -> a[0], a -> a[1]));
|
return NEWLINE.splitAsStream(msg).map(s -> s.split(": ", 2)).collect(toMap(a -> a[0], a -> a[1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void verifyLicense(byte[] bytes) throws Exception {
|
private static Instant parseExpirationDate(String date) {
|
||||||
|
return LocalDate.parse(date, DateTimeFormatter.ISO_LOCAL_DATE).atStartOfDay(ZoneOffset.UTC).plusDays(1).minusSeconds(1).toInstant();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String formatExpirationDate(Instant expires) {
|
||||||
|
return expires.atZone(ZoneOffset.UTC).format(DateTimeFormatter.ISO_LOCAL_DATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void checkExpirationDate(Instant expires) throws Exception {
|
||||||
|
if (expires != null && Instant.now().isAfter(expires)) {
|
||||||
|
throw new IllegalStateException("EXPIRED since " + formatExpirationDate(expires));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void verifyLicense(String id, byte[] bytes) throws Exception {
|
||||||
Cache cache = CacheManager.getInstance().getCache("license", CacheType.Persistent);
|
Cache cache = CacheManager.getInstance().getCache("license", CacheType.Persistent);
|
||||||
Object json = cache.json(id, i -> new URL("https://license.filebot.net/verify/" + i)).fetch((url, modified) -> WebRequest.post(url, bytes, "application/octet-stream", getRequestParameters())).expire(Cache.ONE_MONTH).get();
|
Object json = cache.json(id, i -> new URL("https://license.filebot.net/verify/" + i)).fetch((url, modified) -> WebRequest.post(url, bytes, "application/octet-stream", getRequestParameters())).expire(Cache.ONE_MONTH).get();
|
||||||
|
|
||||||
@ -76,7 +138,7 @@ public class License implements Serializable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, String> getRequestParameters() {
|
private static Map<String, String> getRequestParameters() {
|
||||||
Map<String, String> parameters = new HashMap<String, String>(2);
|
Map<String, String> parameters = new HashMap<String, String>(2);
|
||||||
|
|
||||||
// add standard HTTP headers
|
// add standard HTTP headers
|
||||||
@ -89,31 +151,14 @@ public class License implements Serializable {
|
|||||||
return parameters;
|
return parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
public License check() throws Exception {
|
|
||||||
if (error != null) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Instant.now().isAfter(expires)) {
|
|
||||||
throw new IllegalStateException("EXPIRED since " + getExpirationDate());
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("%s License %s (Valid-Until: %s)", product, id, getExpirationDate());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final SystemProperty<File> FILE = SystemProperty.of("net.filebot.license", File::new, ApplicationFolder.AppData.resolve("license.txt"));
|
public static final SystemProperty<File> FILE = SystemProperty.of("net.filebot.license", File::new, ApplicationFolder.AppData.resolve("license.txt"));
|
||||||
public static final MemoizedResource<License> INSTANCE = Resource.lazy(() -> new License(FILE.get()));
|
public static final MemoizedResource<License> INSTANCE = Resource.lazy(() -> parseLicenseFile(FILE.get()));
|
||||||
|
|
||||||
public static License importLicenseFile(File file) throws Exception {
|
public static License importLicenseFile(File file) throws Exception {
|
||||||
// lock memoized resource while validating and setting a new license
|
// lock memoized resource while validating and setting a new license
|
||||||
synchronized (License.INSTANCE) {
|
synchronized (License.INSTANCE) {
|
||||||
// check if license file is valid and not expired
|
// check if license file is valid and not expired
|
||||||
License license = new License(file).check();
|
License license = parseLicenseFile(file).check();
|
||||||
|
|
||||||
// write to default license file path
|
// write to default license file path
|
||||||
Files.copy(file.toPath(), License.FILE.get().toPath(), StandardCopyOption.REPLACE_EXISTING);
|
Files.copy(file.toPath(), License.FILE.get().toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
Loading…
Reference in New Issue
Block a user