Manifest file loading, hashing, pack file loading

This commit is contained in:
comp500 2019-06-08 14:22:30 +01:00
parent e32d98fb98
commit c181a36edc
No known key found for this signature in database
GPG Key ID: 214C822FFEC586B5
6 changed files with 186 additions and 1 deletions

View File

@ -8,8 +8,9 @@ plugins {
dependencies {
implementation 'commons-cli:commons-cli:1.4'
implementation 'com.moandjiezana.toml:toml4j:0.7.2'
// TODO: Implement tests
//testImplementation 'junit:junit:4.12'
// TODO: add GSON, as toml4j depends on it anyway
implementation 'com.google.code.gson:gson:2.8.1'
}
repositories {

View File

@ -1,7 +1,20 @@
package link.infra.packwiz.installer;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
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 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.request.HandlerManager;
import link.infra.packwiz.installer.ui.IUserInterface;
import link.infra.packwiz.installer.ui.InstallProgress;
@ -71,7 +84,42 @@ public class UpdateManager {
protected void start() {
this.checkOptions();
ui.submitProgress(new InstallProgress("Loading manifest file..."));
Gson gson = new GsonBuilder().registerTypeHierarchyAdapter(byte[].class, new HashTypeAdapter()).create();
ManifestFile manifest;
try {
manifest = gson.fromJson(new FileReader(Paths.get(opts.packFolder, opts.manifestFile).toString()),
ManifestFile.class);
} catch (FileNotFoundException e) {
manifest = new ManifestFile();
} catch (JsonSyntaxException | JsonIOException e) {
ui.handleExceptionAndExit(e);
return;
}
ui.submitProgress(new InstallProgress("Loading pack file..."));
HashInputStream packFileStream;
try {
packFileStream = new HashInputStream(HandlerManager.getFileInputStream(opts.downloadURI));
} catch (Exception e) {
ui.handleExceptionAndExit(e);
return;
}
// TODO: read file
try {
packFileStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
byte[] packFileHash = packFileStream.getHashValue();
if (packFileHash.equals(manifest.packFileHash)) {
// WOOO it's already up to date
// todo: --force?
}
// TODO: save manifest file
}
protected void checkOptions() {

View File

@ -0,0 +1,60 @@
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;
}
}

View File

@ -0,0 +1,66 @@
package link.infra.packwiz.installer.metadata;
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());
}
// Why did Java remove this in 1.9????!
public static byte[] parseHexBinary(String s) {
final int len = s.length();
// "111" is not a valid hex encoding.
if( len%2 != 0 )
throw new IllegalArgumentException("hexBinary needs to be even-length: "+s);
byte[] out = new byte[len/2];
for( int i=0; i<len; i+=2 ) {
int h = hexToBin(s.charAt(i ));
int l = hexToBin(s.charAt(i+1));
if( h==-1 || l==-1 )
throw new IllegalArgumentException("contains illegal character for hexBinary: "+s);
out[i/2] = (byte)(h*16+l);
}
return out;
}
private static int hexToBin( char ch ) {
if( '0'<=ch && ch<='9' ) return ch-'0';
if( 'A'<=ch && ch<='F' ) return ch-'A'+10;
if( 'a'<=ch && ch<='f' ) return ch-'a'+10;
return -1;
}
private static final char[] hexCode = "0123456789ABCDEF".toCharArray();
public static String printHexBinary(byte[] data) {
StringBuilder r = new StringBuilder(data.length*2);
for ( byte b : data) {
r.append(hexCode[(b >> 4) & 0xF]);
r.append(hexCode[(b & 0xF)]);
}
return r.toString();
}
}

View File

@ -0,0 +1,5 @@
package link.infra.packwiz.installer.metadata;
public class ManifestFile {
public byte[] packFileHash = null;
}

View File

@ -0,0 +1,5 @@
package link.infra.packwiz.installer.metadata;
public class PackFile {
}