Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 67 additions & 38 deletions src/main/java/net/rptools/maptool/client/functions/TokenImage.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,6 @@ final int getValue() {
public static final String SET_IMAGE = "setImage";
public static final String SET_PORTRAIT = "setTokenPortrait";
public static final String SET_HANDOUT = "setTokenHandout";
public static final String FILE_HEADER_WEBP = "RIFF";
public static final String FILE_HEADER_JPG = "ÿØÿà";
public static final String FILE_HEADER_PNG = "‰PNG";

private TokenImage() {
super(
Expand All @@ -86,6 +83,26 @@ private TokenImage() {
"createAsset");
}

private static boolean isPNG(byte[] b) {
return b.length >= 8 && (b[0] & 0xFF) == 0x89 && b[1] == 0x50 && b[2] == 0x4E && b[3] == 0x47;
}

private static boolean isJPG(byte[] b) {
return b.length >= 3 && (b[0] & 0xFF) == 0xFF && (b[1] & 0xFF) == 0xD8 && (b[2] & 0xFF) == 0xFF;
}

private static boolean isWEBP(byte[] b) {
return b.length >= 12
&& b[0] == 'R'
&& b[1] == 'I'
&& b[2] == 'F'
&& b[3] == 'F'
&& b[8] == 'W'
&& b[9] == 'E'
&& b[10] == 'B'
&& b[11] == 'P';
}

/**
* Gets the TokenImage instance.
*
Expand Down Expand Up @@ -192,47 +209,56 @@ public Object childEvaluate(
if (imageName.isEmpty() || imageString.isEmpty()) {
throw new ParserException(
I18N.getText("macro.function.general.paramCannotBeEmpty", functionName));
} else if (imageString.length() > 8) {
Asset asset;
URI uri;
}
if (imageString.length() <= 8) {
throw new ParserException(
I18N.getText("macro.function.general.wrongParamType", functionName));
}
Asset asset;
boolean isBase64Image = false;
byte[] base64Bytes = null;
try {
base64Bytes = Base64.decode(imageString);
if (isPNG(base64Bytes) || isJPG(base64Bytes) || isWEBP(base64Bytes)) {
isBase64Image = true;
}
} catch (Exception ignore) {
}
URI uri = null;
if (!isBase64Image) {
try {
uri = new URI(imageString);
if (uri.getScheme() == null) {
uri = null;
}
} catch (URISyntaxException e) {
uri = null;
}
if (uri != null && isValidAssetScheme(uri) && isValidAssetExtension(uri)) {
try {
URL url = uri.toURL();
BufferedImage imageRAW = ImageIO.read(url);
asset = Asset.createImageAsset(imageName, imageRAW);
} catch (MalformedURLException | IllegalArgumentException e) {
throw new ParserException(
I18N.getText("macro.function.input.illegalArgumentType", imageString));
} catch (IOException e1) {
throw new ParserException(I18N.getText("macro.function.html5.invalidURI", imageString));
}
} else {
byte[] imageBytes = Base64.decode(imageString);
String imageCheck;
try {
imageCheck = new String(imageBytes, 0, 4);
} catch (Exception e) {
throw new ParserException(I18N.getText("dragdrop.unsupportedType", functionName));
}
if (imageCheck.equals(FILE_HEADER_WEBP)
|| imageCheck.equals(FILE_HEADER_JPG)
|| imageCheck.equals(FILE_HEADER_PNG)) {
asset = Asset.createImageAsset(imageName, imageBytes);
} else {
throw new ParserException(I18N.getText("dragdrop.unsupportedType", functionName));
}
}
if (uri != null
&& uri.getScheme() != null
&& isValidAssetScheme(uri)
&& isValidAssetExtension(uri)) {
try {
URL url = uri.toURL();
BufferedImage imageRAW = ImageIO.read(url);
asset = Asset.createImageAsset(imageName, imageRAW);
} catch (MalformedURLException | IllegalArgumentException e) {
throw new ParserException(
I18N.getText("macro.function.input.illegalArgumentType", imageString));
} catch (IOException e) {
throw new ParserException(I18N.getText("macro.function.html5.invalidURI", imageString));
}
AssetManager.putAsset(asset);
return "asset://" + asset.getMD5Key().toString();
} else {
throw new ParserException(
I18N.getText("macro.function.general.wrongParamType", functionName));
byte[] imageBytes = isBase64Image ? base64Bytes : Base64.decode(imageString);
if (isPNG(imageBytes) || isJPG(imageBytes) || isWEBP(imageBytes)) {
asset = Asset.createImageAsset(imageName, imageBytes);
} else {
throw new ParserException(I18N.getText("dragdrop.unsupportedType", functionName));
}
}
AssetManager.putAsset(asset);
return "asset://" + asset.getMD5Key().toString();
}

/* getImage, getTokenImage, getTokenPortrait, or getTokenHandout */
Expand Down Expand Up @@ -388,10 +414,13 @@ private static Token findImageToken(final String name, String functionName) {
* @param uri The URI to check.
* @return {@code true} if the scheme is valid.
*/
private boolean isValidAssetScheme(URI uri) {
public boolean isValidAssetScheme(URI uri) {
if (uri == null || uri.getScheme() == null) {
return false;
}
return uri.getScheme().equalsIgnoreCase("http")
|| uri.getScheme().equalsIgnoreCase("https")
|| uri.getScheme().equalsIgnoreCase("lib");
|| uri.getScheme().equalsIgnoreCase("asset");
}

/**
Expand Down