mirror of
https://github.com/mitb-archive/filebot
synced 2024-12-22 15:58:52 -05:00
Experiment with PGP signed messages
This commit is contained in:
parent
bb21d86ec4
commit
204e1e22c6
@ -2,10 +2,12 @@ package net.filebot;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.*;
|
||||
import static java.util.stream.Collectors.*;
|
||||
import static net.filebot.util.FileUtilities.*;
|
||||
import static net.filebot.util.JsonUtilities.*;
|
||||
import static net.filebot.util.RegularExpressions.*;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.Serializable;
|
||||
import java.net.URL;
|
||||
import java.time.Instant;
|
||||
@ -25,39 +27,38 @@ import org.bouncycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
|
||||
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider;
|
||||
|
||||
import net.filebot.util.ByteBufferOutputStream;
|
||||
import net.filebot.util.SystemProperty;
|
||||
import net.filebot.web.WebRequest;
|
||||
|
||||
public class License implements Serializable {
|
||||
|
||||
private byte[] bytes;
|
||||
|
||||
private String product;
|
||||
private long id;
|
||||
private long expires;
|
||||
|
||||
private Exception error;
|
||||
|
||||
public License(byte[] bytes) {
|
||||
this.bytes = bytes;
|
||||
|
||||
try {
|
||||
// verify and get clear signed content
|
||||
Map<String, String> properties = getProperties();
|
||||
Map<String, String> properties = getProperties(bytes);
|
||||
|
||||
this.product = properties.get("Product");
|
||||
this.id = Long.parseLong(properties.get("Order"));
|
||||
this.expires = LocalDate.parse(properties.get("Valid-Until"), DateTimeFormatter.ISO_LOCAL_DATE).atStartOfDay(ZoneOffset.UTC).plusDays(1).minusSeconds(1).toInstant().toEpochMilli();
|
||||
|
||||
// verify license online
|
||||
verifyLicense();
|
||||
verifyLicense(bytes);
|
||||
} catch (Exception e) {
|
||||
error = e;
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, String> getProperties() throws Exception {
|
||||
return NEWLINE.splitAsStream(verifyClearSignMessage()).map(s -> s.split(": ", 2)).collect(toMap(a -> a[0], a -> a[1]));
|
||||
private Map<String, String> getProperties(byte[] bytes) throws Exception {
|
||||
return NEWLINE.splitAsStream(verifyClearSignMessage(bytes)).map(s -> s.split(": ", 2)).collect(toMap(a -> a[0], a -> a[1]));
|
||||
}
|
||||
|
||||
public String verifyClearSignMessage() throws Exception {
|
||||
private String verifyClearSignMessage(byte[] bytes) throws Exception {
|
||||
ArmoredInputStream armoredInput = new ArmoredInputStream(new ByteArrayInputStream(bytes));
|
||||
|
||||
// read content
|
||||
@ -90,7 +91,7 @@ public class License implements Serializable {
|
||||
return clearSignMessage;
|
||||
}
|
||||
|
||||
private void verifyLicense() throws Exception {
|
||||
private void verifyLicense(byte[] bytes) throws Exception {
|
||||
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", null)).expire(Cache.ONE_MONTH).get();
|
||||
|
||||
@ -111,7 +112,26 @@ public class License implements Serializable {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("License %s (Valid-Until: %s)", id, Instant.ofEpochMilli(expires).atZone(ZoneOffset.UTC).format(DateTimeFormatter.ISO_LOCAL_DATE));
|
||||
return String.format("%s License %s (Valid-Until: %s)", product, id, Instant.ofEpochMilli(expires).atZone(ZoneOffset.UTC).format(DateTimeFormatter.ISO_LOCAL_DATE));
|
||||
}
|
||||
|
||||
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(readFile(FILE.get())));
|
||||
|
||||
public static License configure(File file) throws Exception {
|
||||
byte[] bytes = readFile(file);
|
||||
|
||||
// check if license file is valid and not expired
|
||||
License license = new License(bytes);
|
||||
license.check();
|
||||
|
||||
// write to default license file path
|
||||
writeFile(bytes, FILE.get());
|
||||
|
||||
// clear memoized instance and reload on next access
|
||||
INSTANCE.clear();
|
||||
|
||||
return license;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,13 +1,9 @@
|
||||
package net.filebot;
|
||||
|
||||
import static net.filebot.Settings.*;
|
||||
import static net.filebot.platform.windows.WinAppUtilities.*;
|
||||
import static net.filebot.util.FileUtilities.*;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import net.filebot.util.SystemProperty;
|
||||
|
||||
public enum LicenseModel {
|
||||
|
||||
MicrosoftStore {
|
||||
@ -32,13 +28,10 @@ public enum LicenseModel {
|
||||
|
||||
PGPSignedMessage {
|
||||
|
||||
public final SystemProperty<File> LICENSE_FILE = SystemProperty.of("net.filebot.license", File::new, ApplicationFolder.AppData.resolve("license.txt"));
|
||||
public final MemoizedResource<License> LICENSE = Resource.lazy(() -> new License(readFile(LICENSE_FILE.get())));
|
||||
|
||||
@Override
|
||||
public void check() throws LicenseError {
|
||||
try {
|
||||
LICENSE.get().check();
|
||||
License.INSTANCE.get().check();
|
||||
} catch (Exception e) {
|
||||
throw new LicenseError(e.getMessage());
|
||||
}
|
||||
@ -47,13 +40,4 @@ public enum LicenseModel {
|
||||
|
||||
public abstract void check() throws LicenseError;
|
||||
|
||||
public static LicenseModel get() {
|
||||
if (isUWP())
|
||||
return MicrosoftStore;
|
||||
if (isMacSandbox())
|
||||
return MacAppStore;
|
||||
|
||||
return PGPSignedMessage;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -162,11 +162,23 @@ public class Main {
|
||||
SwingEventBus.getInstance().post(new FileTransferable(files));
|
||||
}
|
||||
|
||||
// import license if started with license file
|
||||
if (LicenseModel.PGPSignedMessage == LICENSE) {
|
||||
args.getLicenseFile().ifPresent(f -> {
|
||||
try {
|
||||
License license = License.configure(f);
|
||||
log.info(license + " has been activated.");
|
||||
} catch (Throwable e) {
|
||||
log.severe("License Error: " + e.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// JavaFX is used for ProgressMonitor and GettingStartedDialog
|
||||
try {
|
||||
initJavaFX();
|
||||
} catch (Throwable e) {
|
||||
log.log(Level.SEVERE, "Failed to initialize JavaFX. Please install JavaFX.", e);
|
||||
log.log(Level.SEVERE, "Failed to initialize JavaFX", e);
|
||||
}
|
||||
|
||||
// check if application help should be shown
|
||||
|
@ -25,7 +25,7 @@ import net.filebot.util.PreferencesMap.StringAdapter;
|
||||
|
||||
public final class Settings {
|
||||
|
||||
public static final LicenseModel LICENSE = LicenseModel.get();
|
||||
public static final LicenseModel LICENSE = getLicenseModel();
|
||||
|
||||
public static String getApplicationName() {
|
||||
return getApplicationProperty("application.name");
|
||||
@ -137,6 +137,15 @@ public final class Settings {
|
||||
return Runtime.getRuntime().availableProcessors();
|
||||
}
|
||||
|
||||
public static LicenseModel getLicenseModel() {
|
||||
if (isUWP())
|
||||
return LicenseModel.MicrosoftStore;
|
||||
if (isMacSandbox())
|
||||
return LicenseModel.MacAppStore;
|
||||
|
||||
return LicenseModel.PGPSignedMessage;
|
||||
}
|
||||
|
||||
public static String getAppStoreName() {
|
||||
if (isMacApp())
|
||||
return "Mac App Store";
|
||||
|
@ -139,6 +139,9 @@ public class ArgumentBean {
|
||||
@Option(name = "-help", usage = "Print this help message")
|
||||
public boolean help = false;
|
||||
|
||||
@Option(name = "--license", usage = "Import license file", metaVar = "file")
|
||||
public String license = null;
|
||||
|
||||
@Option(name = "--def", usage = "Define script variables", handler = BindingsHandler.class)
|
||||
public Map<String, String> defines = new LinkedHashMap<String, String>();
|
||||
|
||||
@ -348,6 +351,10 @@ public class ArgumentBean {
|
||||
}).orElseThrow(error("Illegal mode", mode));
|
||||
}
|
||||
|
||||
public Optional<File> getLicenseFile() {
|
||||
return optional(license).map(File::new);
|
||||
}
|
||||
|
||||
private final String[] args;
|
||||
|
||||
public ArgumentBean(String... args) throws CmdLineException {
|
||||
|
@ -225,6 +225,10 @@ public final class FileUtilities {
|
||||
return destination;
|
||||
}
|
||||
|
||||
public static File writeFile(byte[] data, File destination) throws IOException {
|
||||
return Files.write(destination.toPath(), data, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE).toFile();
|
||||
}
|
||||
|
||||
public static Reader createTextReader(InputStream in, boolean guess, Charset declaredEncoding) throws IOException {
|
||||
byte head[] = new byte[BOM.SIZE];
|
||||
in.mark(head.length);
|
||||
|
Loading…
Reference in New Issue
Block a user