Skip to content

Commit

Permalink
Fixed issue with BOM Files
Browse files Browse the repository at this point in the history
  • Loading branch information
CoryBorek committed Mar 1, 2020
1 parent e48ce87 commit 4973c19
Show file tree
Hide file tree
Showing 6 changed files with 242 additions and 1 deletion.
3 changes: 3 additions & 0 deletions src/main/java/net/hypixel/resourcepack/Main.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package net.hypixel.resourcepack;

import joptsimple.OptionSet;
import net.hypixel.resourcepack.extra.BomDetector;

import java.io.IOException;

Expand All @@ -18,4 +19,6 @@ public static void main(String[] args) throws IOException {

}



}
14 changes: 14 additions & 0 deletions src/main/java/net/hypixel/resourcepack/PackConverter.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import joptsimple.OptionSet;
import net.hypixel.resourcepack.extra.BomDetector;
import net.hypixel.resourcepack.impl.*;
import net.hypixel.resourcepack.pack.Pack;

Expand Down Expand Up @@ -75,6 +76,19 @@ public void run() throws IOException {

pack.getHandler().setup();

BomDetector bom = new BomDetector(
pack.getWorkingPath().toString(),
".txt", ".json", ".mcmeta", ".properties"
);

int count = 0;
for(String file : bom.findBOMs()){
count++;
}
if (count > 0){
System.out.println("Removing BOMs from " + count + " files.");
} bom.removeBOMs();

System.out.println(" Running Converters");
for (Converter converter : converters.values()) {
if (PackConverter.DEBUG)
Expand Down
1 change: 0 additions & 1 deletion src/main/java/net/hypixel/resourcepack/Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ public static JsonObject readJson(Gson gson, Path path) throws IOException {
}

public static <T> T readJson(Gson gson, Path path, Class<T> clazz) throws IOException {
// TODO Improvement: this will fail if there is a BOM in the file
return gson.fromJson(new JsonReader(new FileReader(path.toFile())), clazz);
}

Expand Down
192 changes: 192 additions & 0 deletions src/main/java/net/hypixel/resourcepack/extra/BomDetector.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
package net.hypixel.resourcepack.extra;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
Retrieved from http://www.javapractices.com/topic/TopicAction.do?Id=257.
Detect and remove Byte Order Marks (BOMs) from text files saved with a
Unicode encoding.
<P>Dev tool only. If you use this tool to remove BOMs, please ensure
you have made a backup.
<P>This class assumes the UTF-8 encoding for the BOM, but
is easily changed to handle any encoding.
See http://en.wikipedia.org/wiki/Byte_order_mark for more info.
JDK 5+.
*/
public final class BomDetector {

/* /** Run the tool against a root directory.
public static void main(String... args) throws IOException{
BomDetector bom = new BomDetector(
"C:\\Temp3\\test\\",
".txt", ".jsp", ".jspf", ".tag", ".html",
".css", ".xml", ".js", ".sql", ".tld"
);
int count = 0;
for(String file : bom.findBOMs()){
log(file);
++count;
}
log("Number of files with BOM:" + count);
/*
for(String file : bom.removeBOMs()){
log("Removed BOM from: " + file);
}
}
*/

public BomDetector(String rootDirectory, String... fileExtensions){
this.rootDir = new File(rootDirectory);
this.extensions = Arrays.asList(fileExtensions);
if(!rootDir.exists() || rootDir.isFile() ){
throw new RuntimeException("Root directory not valid.");
}
}

/** Find files with BOMs under the given root directory. Return their names. */
public List<String> findBOMs() throws IOException {
List<String> result = new ArrayList<String>();
for(File textFile : findTextFilesBeneath(rootDir)){
if(startsWithBOM(textFile)){
result.add(textFile.getCanonicalPath());
}
}
return result;
}

/**
Find and remove BOMs from files under the given root directory.
Overwrites files.
Return the names of the affected files.
*/
public List<String> removeBOMs() throws IOException{
List<String> result = new ArrayList<String>();
for(String bomFile : findBOMs()){
stripBomFrom(bomFile);
result.add(bomFile);
}
return result;
}

// PRIVATE
private File rootDir;
private List<String> extensions;

/** Different encodings will have different BOMs. This is for UTF-8. */
private final int[] BYTE_ORDER_MARK = {239, 187, 191};

private static void log(Object thing){
System.out.println(String.valueOf(thing));
}

private List<File> findTextFilesBeneath(File startingDir) throws IOException {
List<File> result = new ArrayList<File>();
File[] filesAndDirs = startingDir.listFiles();
List<File> filesDirs = Arrays.asList(filesAndDirs);
for(File file : filesDirs){
if (isTextFile(file)){
result.add(file);
}
if( file.isDirectory() ) {
//recursive call!!
List<File> deeperList = findTextFilesBeneath(file);
result.addAll(deeperList);
}
}
return result;
}

private boolean isTextFile(File file) throws IOException{
boolean result = false;
String fileName = file.getCanonicalPath();
int finalDot = fileName.lastIndexOf(".");
if (finalDot > -1){
String extension = fileName.substring(finalDot);
result = extensions.contains(extension);
}
return result;
}

private boolean startsWithBOM(File textFile) throws IOException {
boolean result = false;
if(textFile.length() < BYTE_ORDER_MARK.length) return false;
//open as bytes here, not characters
int[] firstFewBytes = new int[BYTE_ORDER_MARK.length];
InputStream input = null;
try {
input = new FileInputStream(textFile);
for(int index = 0; index < BYTE_ORDER_MARK.length; ++index){
firstFewBytes[index] = input.read(); //read a single byte
}
result = Arrays.equals(firstFewBytes, BYTE_ORDER_MARK);
}
finally {
input.close();
}
return result;
}

private void stripBomFrom(String textFile) throws IOException{
File bomFile = new File(textFile);
long initialSize = bomFile.length();
long truncatedSize = initialSize - BYTE_ORDER_MARK.length;
byte[] memory = new byte[(int)(truncatedSize)];
InputStream input = null;
try {
input = new BufferedInputStream(new FileInputStream(bomFile));
input.skip(BYTE_ORDER_MARK.length);
int totalBytesReadIntoMemory = 0;
while(totalBytesReadIntoMemory < truncatedSize){
int bytesRemaining = (int)truncatedSize - totalBytesReadIntoMemory;
int bytesRead = input.read(memory, totalBytesReadIntoMemory, bytesRemaining);
if(bytesRead > 0){
totalBytesReadIntoMemory = totalBytesReadIntoMemory + bytesRead;
}
}
overwriteWithoutBOM(memory, bomFile);
}
finally {
input.close();
}
File after = new File(textFile);
long finalSize = after.length();
long changeInSize = initialSize - finalSize;
if(changeInSize != BYTE_ORDER_MARK.length){
throw new RuntimeException(
"Change in file size: " + changeInSize +
" Expected change: " + BYTE_ORDER_MARK.length
);
}
}

private void overwriteWithoutBOM(
byte[] bytesWithoutBOM, File textFile
) throws IOException{
OutputStream output = null;
try {
output = new BufferedOutputStream(new FileOutputStream(textFile));
output.write(bytesWithoutBOM);
}
finally {
output.close();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public void convert(Pack pack) throws IOException {
value.addProperty("model", "block/" + value.get("model").getAsString());
anyChanges = true;
}

} else if (entry.getValue() instanceof JsonArray) { // some states have arrays
for (JsonElement jsonElement : ((JsonArray) entry.getValue())) {
if (jsonElement instanceof JsonObject) {
Expand Down
32 changes: 32 additions & 0 deletions src/main/resources/blocks.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{
"acacia_inner_stairs": "acacia_stairs_inner",
"acacia_outer_stairs": "acacia_stairs_outer",
"anvil_base": "anvil",
"anvil_slightly_damaged": "chipped_anvil",
"anvil_top_damaged_0": "anvil_top",
Expand All @@ -9,7 +11,11 @@
"beetroots_stage_1": "beetroots_stage1",
"beetroots_stage_2": "beetroots_stage2",
"beetroots_stage_3": "beetroots_stage3",
"birch_inner_stairs": "birch_stairs_inner",
"birch_outer_stairs": "birch_stairs_outer",
"brick": "bricks",
"brick_inner_stairs": "brick_stairs_inner",
"brick_outer_stairs": "brick_stairs_outer",
"carrots_stage_0": "carrots_stage0",
"carrots_stage_1": "carrots_stage1",
"carrots_stage_2": "carrots_stage2",
Expand Down Expand Up @@ -51,6 +57,8 @@
"concrete_silver": "light_gray_concrete",
"concrete_white": "white_concrete",
"concrete_yellow": "yellow_concrete",
"dark_oak_inner_stairs": "dark_oak_stairs_inner",
"dark_oak_outer_stairs": "dark_oak_stairs_outer",
"deadbush": "dead_bush",
"dirt_podzol_side": "podzol_side",
"dirt_podzol_top": "podzol_top",
Expand Down Expand Up @@ -191,7 +199,12 @@
"hardened_clay_stained_silver": "light_gray_terracotta",
"hardened_clay_stained_white": "white_terracotta",
"hardened_clay_stained_yellow": "yellow_terracotta",
"hay": "hay_block",
"heavy_pressure_plate_up": "heavy_weighted_pressure_plate",
"heavy_pressure_plate_down": "heavy_weighted_pressure_plate_down",
"ice_packed": "packed_ice",
"jungle_inner_stairs": "jungle_stairs_inner",
"jungle_outer_stairs": "jungle_stairs_outer",
"leaves_acacia": "acacia_leaves",
"leaves_big_oak": "dark_oak_leaves",
"leaves_birch": "birch_leaves",
Expand All @@ -218,10 +231,14 @@
"mushroom_brown": "brown_mushroom",
"mushroom_red": "red_mushroom",
"nether_brick": "nether_bricks",
"nether_brick_inner_stairs": "nether_brick_stairs_inner",
"nether_brick_outer_stairs": "nether_brick_stairs_outer",
"nether_wart_stage_0": "nether_wart_stage0",
"nether_wart_stage_1": "nether_wart_stage1",
"nether_wart_stage_2": "nether_wart_stage2",
"noteblock": "note_block",
"oak_inner_stairs": "oak_stairs_inner,",
"oak_outer_stairs": "oak_stairs_outer",
"observer_back_lit": "observer_back_on",
"piston_inventory_normal": "piston_inventory",
"piston_inventory_sticky": "sticky_piston_inventory",
Expand All @@ -246,10 +263,14 @@
"purple_stained_glass": "purple_stained_glass",
"purpur_pillar": "purpur_pillar",
"purpur_pillar_top": "purpur_pillar_top",
"purpur_inner_stairs": "purpur_stairs_inner,",
"purpur_outer_stairs": "purpur_stairs_outer",
"quartz_block_chiseled": "chiseled_quartz_block",
"quartz_block_chiseled_top": "chiseled_quartz_block_top",
"quartz_block_lines": "quartz_pillar",
"quartz_block_lines_top": "quartz_pillar_top",
"quartz_inner_stairs": "quartz_stairs_inner,",
"quartz_outer_stairs": "quartz_stairs_outer",
"quartz_ore": "nether_quartz_ore",
"rail_activator": "activator_rail",
"rail_activator_powered": "activator_rail_on",
Expand All @@ -260,12 +281,16 @@
"rail_normal": "rail",
"rail_normal_turned": "rail_corner",
"red_sandstone_carved": "chiseled_red_sandstone",
"red_sandstone_inner_stairs": "red_sandstone_stairs_inner,",
"red_sandstone_outer_stairs": "red_sandstone_stairs_outer",
"red_sandstone_normal": "red_sandstone",
"red_sandstone_smooth": "cut_red_sandstone",
"redstone_torch_on": "redstone_torch",
"reeds": "sugar_cane",
"repeater_off": "repeater",
"sandstone_carved": "chiseled_sandstone",
"sandstone_inner_stairs": "sandstone_stairs_inner,",
"sandstone_outer_stairs": "sandstone_stairs_outer",
"sandstone_normal": "sandstone",
"sandstone_smooth": "cut_sandstone",
"sapling_acacia": "acacia_sapling",
Expand All @@ -292,6 +317,8 @@
"shulker_top_yellow": "yellow_shulker_box",
"slime": "slime_block",
"sponge_wet": "wet_sponge",
"spruce_inner_stairs": "spruce_stairs_inner,",
"spruce_outer_stairs": "spruce_stairs_outer",
"stone_andesite": "andesite",
"stone_andesite_smooth": "polished_andesite",
"stone_diorite": "diorite",
Expand All @@ -300,7 +327,12 @@
"stone_granite_smooth": "polished_granite",
"stone_slab_top": "smooth_stone",
"stone_slab_side": "smooth_stone_slab_side",
"stone_inner_stairs": "cobblestone_stairs_inner,",
"stone_outer_stairs": "cobblestone_stairs_outer",
"stone_stairs": "cobblestone_stairs",
"stonebrick": "stone_bricks",
"stone_brick_inner_stairs": "stone_brick_stairs_inner,",
"stone_brick_outer_stairs": "stone_brick_stairs_outer",
"stonebrick_carved": "chiseled_stone_bricks",
"stonebrick_cracked": "cracked_stone_bricks",
"stonebrick_mossy": "mossy_stone_bricks",
Expand Down

0 comments on commit 4973c19

Please sign in to comment.