mirror of
https://github.com/packwiz/packwiz-installer.git
synced 2025-04-19 13:06:30 +02:00
Redo hashing sytem, pack file reading, write json
This commit is contained in:
parent
8be5cb8e60
commit
fbd54b4604
@ -2,19 +2,21 @@ package link.infra.packwiz.installer;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Writer;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonIOException;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import com.moandjiezana.toml.Toml;
|
||||
|
||||
import link.infra.packwiz.installer.metadata.HashInputStream;
|
||||
import link.infra.packwiz.installer.metadata.HashTypeAdapter;
|
||||
import link.infra.packwiz.installer.metadata.ManifestFile;
|
||||
import link.infra.packwiz.installer.metadata.PackFile;
|
||||
import link.infra.packwiz.installer.metadata.hash.Hash;
|
||||
import link.infra.packwiz.installer.request.HandlerManager;
|
||||
import link.infra.packwiz.installer.ui.IUserInterface;
|
||||
import link.infra.packwiz.installer.ui.InstallProgress;
|
||||
@ -87,7 +89,7 @@ public class UpdateManager {
|
||||
this.checkOptions();
|
||||
|
||||
ui.submitProgress(new InstallProgress("Loading manifest file..."));
|
||||
Gson gson = new GsonBuilder().registerTypeHierarchyAdapter(byte[].class, new HashTypeAdapter()).create();
|
||||
Gson gson = new Gson();
|
||||
ManifestFile manifest;
|
||||
try {
|
||||
manifest = gson.fromJson(new FileReader(Paths.get(opts.packFolder, opts.manifestFile).toString()),
|
||||
@ -100,31 +102,47 @@ public class UpdateManager {
|
||||
}
|
||||
|
||||
ui.submitProgress(new InstallProgress("Loading pack file..."));
|
||||
HashInputStream packFileStream;
|
||||
Hash.HashInputStream packFileStream;
|
||||
try {
|
||||
InputStream stream = HandlerManager.getFileInputStream(opts.downloadURI);
|
||||
if (stream == null) {
|
||||
throw new Exception("Pack file URI is invalid, is it supported?");
|
||||
}
|
||||
packFileStream = new HashInputStream(stream);
|
||||
packFileStream = new Hash.HashInputStream(stream, "sha256");
|
||||
} catch (Exception e) {
|
||||
// TODO: still launch the game if updating doesn't work?
|
||||
ui.handleExceptionAndExit(e);
|
||||
return;
|
||||
}
|
||||
// TODO: read file
|
||||
PackFile pf;
|
||||
try {
|
||||
packFileStream.close();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
pf = new Toml().read(packFileStream).to(PackFile.class);
|
||||
} catch (IllegalStateException e) {
|
||||
ui.handleExceptionAndExit(e);
|
||||
return;
|
||||
}
|
||||
byte[] packFileHash = packFileStream.getHashValue();
|
||||
|
||||
Hash packFileHash = packFileStream.get();
|
||||
if (packFileHash.equals(manifest.packFileHash)) {
|
||||
System.out.println("Hash already up to date!");
|
||||
// WOOO it's already up to date
|
||||
// todo: --force?
|
||||
}
|
||||
|
||||
// TODO: save manifest file
|
||||
System.out.println(pf.name);
|
||||
|
||||
|
||||
// When successfully updated
|
||||
manifest.packFileHash = packFileHash;
|
||||
// update other hashes
|
||||
// TODO: don't do this on failure?
|
||||
try (Writer writer = new FileWriter(Paths.get(opts.packFolder, opts.manifestFile).toString())) {
|
||||
gson.toJson(manifest, writer);
|
||||
} catch (IOException e) {
|
||||
// TODO: add message?
|
||||
ui.handleException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected void checkOptions() {
|
||||
|
@ -1,60 +0,0 @@
|
||||
package link.infra.packwiz.installer.metadata;
|
||||
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
public class HashInputStream extends FilterInputStream {
|
||||
|
||||
private MessageDigest md;
|
||||
private byte[] output;
|
||||
|
||||
public HashInputStream(InputStream in) throws NoSuchAlgorithmException {
|
||||
super(in);
|
||||
md = MessageDigest.getInstance("SHA-256");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
int value = super.read();
|
||||
if (value == -1) {
|
||||
return value;
|
||||
}
|
||||
md.update((byte) value);
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
int bytesRead = super.read(b, off, len);
|
||||
if (bytesRead > 0) {
|
||||
md.update(b, off, len);
|
||||
}
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() throws IOException {
|
||||
throw new IOException("HashInputStream doesn't support reset()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean markSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mark(int readlimit) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
public byte[] getHashValue() {
|
||||
if (output == null) {
|
||||
output = md.digest();
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package link.infra.packwiz.installer.metadata;
|
||||
|
||||
public class IndexFile {
|
||||
|
||||
}
|
@ -1,5 +1,13 @@
|
||||
package link.infra.packwiz.installer.metadata;
|
||||
|
||||
import link.infra.packwiz.installer.metadata.hash.Hash;
|
||||
|
||||
public class ManifestFile {
|
||||
public byte[] packFileHash = null;
|
||||
|
||||
public Hash packFileHash = null;
|
||||
public Hash indexFileHash = null;
|
||||
|
||||
public static class File {
|
||||
public Hash hash = null;
|
||||
}
|
||||
}
|
@ -1,5 +1,21 @@
|
||||
package link.infra.packwiz.installer.metadata;
|
||||
|
||||
public class PackFile {
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class PackFile {
|
||||
public String name;
|
||||
|
||||
public IndexFileLoc index;
|
||||
public static class IndexFileLoc {
|
||||
public String file;
|
||||
@SerializedName("hash-format")
|
||||
public String hashFormat;
|
||||
public String hash;
|
||||
}
|
||||
|
||||
public Map<String, String> versions;
|
||||
public Map<String, Object> client;
|
||||
public Map<String, Object> server;
|
||||
}
|
@ -0,0 +1,115 @@
|
||||
package link.infra.packwiz.installer.metadata.hash;
|
||||
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class Hash {
|
||||
public final String value;
|
||||
public final String type;
|
||||
|
||||
public Hash(String value, String type) {
|
||||
this.value = value;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
private static final Map<String, IHasher> hashTypeConversion = new HashMap<String, IHasher>();
|
||||
static {
|
||||
try {
|
||||
hashTypeConversion.put("sha256", new HasherMessageDigest("SHA-256"));
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public IHasher getHasher() {
|
||||
return hashTypeConversion.get(type);
|
||||
}
|
||||
|
||||
public static IHasher getHasher(String type) {
|
||||
return hashTypeConversion.get(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null || !(obj instanceof Hash)) {
|
||||
return false;
|
||||
}
|
||||
Hash hash = (Hash)obj;
|
||||
return type.equals(hash.type) && getHasher().equalValues(value, hash.value);
|
||||
}
|
||||
|
||||
public static class HashInputStream extends FilterInputStream {
|
||||
|
||||
private IHasher md;
|
||||
private Hash output;
|
||||
private final String hashType;
|
||||
private Hash compare = null;
|
||||
|
||||
public HashInputStream(InputStream in, String hashType) throws NoSuchAlgorithmException {
|
||||
super(in);
|
||||
this.hashType = hashType;
|
||||
md = hashTypeConversion.get(hashType);
|
||||
}
|
||||
|
||||
public HashInputStream(InputStream in, Hash compare) throws NoSuchAlgorithmException {
|
||||
this(in, compare.type);
|
||||
this.compare = compare;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
int value = super.read();
|
||||
if (value == -1) {
|
||||
return value;
|
||||
}
|
||||
md.update((byte) value);
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
int bytesRead = super.read(b, off, len);
|
||||
if (bytesRead > 0) {
|
||||
md.update(b, off, len);
|
||||
}
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() throws IOException {
|
||||
throw new IOException("HashInputStream doesn't support reset()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean markSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mark(int readlimit) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
public Hash get() {
|
||||
if (output == null) {
|
||||
String value = md.get();
|
||||
if (value != null) {
|
||||
output = new Hash(value, hashType);
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
public boolean isNew() {
|
||||
if (output != null) {
|
||||
return !output.equals(compare);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,27 +1,7 @@
|
||||
package link.infra.packwiz.installer.metadata;
|
||||
package link.infra.packwiz.installer.metadata.hash;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
|
||||
public class HashTypeAdapter implements JsonSerializer<byte[]>, JsonDeserializer<byte[]> {
|
||||
|
||||
@Override
|
||||
public JsonElement serialize(byte[] src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
return new JsonPrimitive(printHexBinary(src));
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
return parseHexBinary(json.getAsString());
|
||||
}
|
||||
public class HashUtils {
|
||||
private HashUtils() {}
|
||||
|
||||
// Why did Java remove this in 1.9????!
|
||||
public static byte[] parseHexBinary(String s) {
|
||||
@ -52,7 +32,7 @@ public class HashTypeAdapter implements JsonSerializer<byte[]>, JsonDeserializer
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static final char[] hexCode = "0123456789ABCDEF".toCharArray();
|
||||
private static final char[] hexCode = "0123456789abcdef".toCharArray();
|
||||
|
||||
public static String printHexBinary(byte[] data) {
|
||||
StringBuilder r = new StringBuilder(data.length*2);
|
@ -0,0 +1,45 @@
|
||||
package link.infra.packwiz.installer.metadata.hash;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
public class HasherMessageDigest implements IHasher {
|
||||
MessageDigest md;
|
||||
|
||||
public HasherMessageDigest(String hashType) throws NoSuchAlgorithmException {
|
||||
md = MessageDigest.getInstance(hashType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(byte[] data) {
|
||||
md.update(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(byte[] data, int offset, int length) {
|
||||
md.update(data, offset, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(byte data) {
|
||||
md.update(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String get() {
|
||||
return HashUtils.printHexBinary(md.digest());
|
||||
}
|
||||
|
||||
// Enforce case insensitivity
|
||||
@Override
|
||||
public boolean equalValues(String a, String b) {
|
||||
if (a == null) {
|
||||
if (b == null) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return a.equalsIgnoreCase(b);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package link.infra.packwiz.installer.metadata.hash;
|
||||
|
||||
public interface IHasher {
|
||||
public void update(byte[] data);
|
||||
public void update(byte[] data, int offset, int length);
|
||||
public void update(byte data);
|
||||
public String get();
|
||||
public default boolean equalValues(String a, String b) {
|
||||
if (a == null) {
|
||||
if (b == null) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return a.equals(b);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user