From 64c63677ed3920c97cf0e510dc5550514a3145cb Mon Sep 17 00:00:00 2001 From: Fish4203 Date: Sun, 30 Oct 2022 19:28:38 +1100 Subject: [PATCH 1/4] xor --- mcpi_sec.py | 22 +++ .../raspberryjuice/RemoteSession.java | 162 ++++++++++-------- 2 files changed, 114 insertions(+), 70 deletions(-) create mode 100644 mcpi_sec.py diff --git a/mcpi_sec.py b/mcpi_sec.py new file mode 100644 index 00000000..37578c88 --- /dev/null +++ b/mcpi_sec.py @@ -0,0 +1,22 @@ +from mcpi.minecraft import Minecraft + +# Assignment 3 main file +# Feel free to modify, and/or to add other modules/classes in this or other files + + +import base64 + + +st = "Ben test string" + +li = [] +for i in range(len(st)): + li.append(chr( (ord(st[i]) + i) ^ 1417 )) + + +out = ''.join(li) +print(out) + +mc = Minecraft.create("127.0.0.1", 4711) + +mc.postToChat(out) diff --git a/src/main/java/net/zhuoweizhang/raspberryjuice/RemoteSession.java b/src/main/java/net/zhuoweizhang/raspberryjuice/RemoteSession.java index 318ae98d..53ed77ea 100644 --- a/src/main/java/net/zhuoweizhang/raspberryjuice/RemoteSession.java +++ b/src/main/java/net/zhuoweizhang/raspberryjuice/RemoteSession.java @@ -9,6 +9,8 @@ import java.util.ArrayDeque; import java.util.Collection; import java.util.Iterator; +import java.util.Base64; +import java.lang.Math; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -38,9 +40,9 @@ public class RemoteSession { private BufferedReader in; private BufferedWriter out; - + private Thread inThread; - + private Thread outThread; private ArrayDeque inQueue = new ArrayDeque(); @@ -54,9 +56,9 @@ public class RemoteSession { public RaspberryJuicePlugin plugin; protected ArrayDeque interactEventQueue = new ArrayDeque(); - + protected ArrayDeque chatPostedQueue = new ArrayDeque(); - + protected ArrayDeque projectileHitQueue = new ArrayDeque(); private int maxCommandsPerTick = 9000; @@ -111,7 +113,7 @@ public void queueChatPostedEvent(AsyncPlayerChatEvent event) { //plugin.getLogger().info(event.toString()); chatPostedQueue.add(event); } - + public void queueProjectileHitEvent(ProjectileHitEvent event) { //plugin.getLogger().info(event.toString()); @@ -155,6 +157,7 @@ public void tick() { } protected void handleLine(String line) { + plugin.getLogger().info(line); //System.out.println(line); String methodName = line.substring(0, line.indexOf("(")); //split string into args, handles , inside " i.e. "," @@ -164,35 +167,38 @@ protected void handleLine(String line) { } protected void handleCommand(String c, String[] args) { - + try { // get the server Server server = plugin.getServer(); - + // get the world World world = origin.getWorld(); - + + plugin.getLogger().info("Ben Test stuff"); + plugin.getLogger().info(c); + // world.getBlock if (c.equals("world.getBlock")) { Location loc = parseRelativeBlockLocation(args[0], args[1], args[2]); send(world.getBlockTypeIdAt(loc)); - + // world.getBlocks } else if (c.equals("world.getBlocks")) { Location loc1 = parseRelativeBlockLocation(args[0], args[1], args[2]); Location loc2 = parseRelativeBlockLocation(args[3], args[4], args[5]); send(getBlocks(loc1, loc2)); - + // world.getBlockWithData } else if (c.equals("world.getBlockWithData")) { Location loc = parseRelativeBlockLocation(args[0], args[1], args[2]); send(world.getBlockTypeIdAt(loc) + "," + world.getBlockAt(loc).getData()); - + // world.setBlock } else if (c.equals("world.setBlock")) { Location loc = parseRelativeBlockLocation(args[0], args[1], args[2]); updateBlock(world, loc, Integer.parseInt(args[3]), (args.length > 4? Byte.parseByte(args[4]) : (byte) 0)); - + // world.setBlocks } else if (c.equals("world.setBlocks")) { Location loc1 = parseRelativeBlockLocation(args[0], args[1], args[2]); @@ -200,7 +206,7 @@ protected void handleCommand(String c, String[] args) { int blockType = Integer.parseInt(args[6]); byte data = args.length > 7? Byte.parseByte(args[7]) : (byte) 0; setCuboid(loc1, loc2, blockType, data); - + // world.getPlayerIds } else if (c.equals("world.getPlayerIds")) { StringBuilder bdr = new StringBuilder(); @@ -215,7 +221,7 @@ protected void handleCommand(String c, String[] args) { } else { send("Fail"); } - + // world.getPlayerId } else if (c.equals("world.getPlayerId")) { Player p = plugin.getNamedPlayer(args[0]); @@ -225,7 +231,7 @@ protected void handleCommand(String c, String[] args) { plugin.getLogger().info("Player [" + args[0] + "] not found."); send("Fail"); } - + // entity.getListName } else if (c.equals("entity.getName")) { Entity e = plugin.getEntity(Integer.parseInt(args[0])); @@ -238,12 +244,12 @@ protected void handleCommand(String c, String[] args) { } else if (e != null) { send(e.getName()); } - + // world.getEntities } else if (c.equals("world.getEntities")) { int entityType = Integer.parseInt(args[0]); send(getEntities(world, entityType)); - + // world.removeEntity } else if (c.equals("world.removeEntity")) { int result = 0; @@ -256,7 +262,7 @@ protected void handleCommand(String c, String[] args) { } } send(result); - + // world.removeEntities } else if (c.equals("world.removeEntities")) { int entityType = Integer.parseInt(args[0]); @@ -269,7 +275,7 @@ protected void handleCommand(String c, String[] args) { } } send(removedEntitiesCount); - + // chat.post } else if (c.equals("chat.post")) { //create chat message from args as it was split by , @@ -279,50 +285,66 @@ protected void handleCommand(String c, String[] args) { chatMessage = chatMessage + args[count] + ","; } chatMessage = chatMessage.substring(0, chatMessage.length() - 1); + + char[] ch = chatMessage.toCharArray(); + + // Traverse the character array + for (int i = 0; i < ch.length; i++) { + + // Print current character + int temp = (int) ch[i]; + temp = temp ^ 1417; + temp = temp - i; + ch[i] = (char) temp; + + } + + chatMessage = String.valueOf(ch); + server.broadcastMessage(chatMessage); // events.clear } else if (c.equals("events.clear")) { interactEventQueue.clear(); chatPostedQueue.clear(); - + // events.block.hits } else if (c.equals("events.block.hits")) { send(getBlockHits()); - + // events.chat.posts } else if (c.equals("events.chat.posts")) { send(getChatPosts()); - + // events.projectile.hits } else if(c.equals("events.projectile.hits")) { send(getProjectileHits()); - + // entity.events.clear } else if (c.equals("entity.events.clear")) { int entityId = Integer.parseInt(args[0]); clearEntityEvents(entityId); - + // entity.events.block.hits } else if (c.equals("entity.events.block.hits")) { int entityId = Integer.parseInt(args[0]); send(getBlockHits(entityId)); - + // entity.events.chat.posts } else if (c.equals("entity.events.chat.posts")) { int entityId = Integer.parseInt(args[0]); send(getChatPosts(entityId)); - + // entity.events.projectile.hits } else if(c.equals("entity.events.projectile.hits")) { int entityId = Integer.parseInt(args[0]); send(getProjectileHits(entityId)); - + // player.getTile }else if (c.equals("player.getTile")) { Player currentPlayer = getCurrentPlayer(); send(blockLocationToRelative(currentPlayer.getLocation())); - + // player.setTile } else if (c.equals("player.setTile")) { String x = args[0], y = args[1], z = args[2]; @@ -330,12 +352,12 @@ protected void handleCommand(String c, String[] args) { //get players current location, so when they are moved we will use the same pitch and yaw (rotation) Location loc = currentPlayer.getLocation(); currentPlayer.teleport(parseRelativeBlockLocation(x, y, z, loc.getPitch(), loc.getYaw())); - + // player.getAbsPos } else if (c.equals("player.getAbsPos")) { Player currentPlayer = getCurrentPlayer(); send(currentPlayer.getLocation()); - + // player.setAbsPos } else if (c.equals("player.setAbsPos")) { String x = args[0], y = args[1], z = args[2]; @@ -363,7 +385,7 @@ protected void handleCommand(String c, String[] args) { // player.setDirection } else if (c.equals("player.setDirection")) { Double x = Double.parseDouble(args[0]); - Double y = Double.parseDouble(args[1]); + Double y = Double.parseDouble(args[1]); Double z = Double.parseDouble(args[2]); Player currentPlayer = getCurrentPlayer(); Location loc = currentPlayer.getLocation(); @@ -387,7 +409,7 @@ protected void handleCommand(String c, String[] args) { } else if (c.equals("player.getRotation")) { Player currentPlayer = getCurrentPlayer(); float yaw = currentPlayer.getLocation().getYaw(); - // turn bukkit's 0 - -360 to positive numbers + // turn bukkit's 0 - -360 to positive numbers if (yaw < 0) yaw = yaw * -1; send(yaw); @@ -398,7 +420,7 @@ protected void handleCommand(String c, String[] args) { Location loc = currentPlayer.getLocation(); loc.setPitch(pitch); currentPlayer.teleport(loc); - + // player.getPitch } else if (c.equals("player.getPitch")) { Player currentPlayer = getCurrentPlayer(); @@ -424,26 +446,26 @@ protected void handleCommand(String c, String[] args) { } else if (c.equals("player.events.block.hits")) { Player currentPlayer = getCurrentPlayer(); send(getBlockHits(currentPlayer.getEntityId())); - + // player.events.chat.posts } else if (c.equals("player.events.chat.posts")) { Player currentPlayer = getCurrentPlayer(); send(getChatPosts(currentPlayer.getEntityId())); - + // player.events.projectile.hits } else if(c.equals("player.events.projectile.hits")) { Player currentPlayer = getCurrentPlayer(); send(getProjectileHits(currentPlayer.getEntityId())); - + // player.events.clear } else if (c.equals("player.events.clear")) { Player currentPlayer = getCurrentPlayer(); clearEntityEvents(currentPlayer.getEntityId()); - + // world.getHeight } else if (c.equals("world.getHeight")) { send(world.getHighestBlockYAt(parseRelativeBlockLocation(args[0], "0", args[1])) - origin.getBlockY()); - + // entity.getTile } else if (c.equals("entity.getTile")) { //get entity based on id @@ -454,7 +476,7 @@ protected void handleCommand(String c, String[] args) { plugin.getLogger().info("Entity [" + args[0] + "] not found."); send("Fail"); } - + // entity.setTile } else if (c.equals("entity.setTile")) { String x = args[1], y = args[2], z = args[3]; @@ -480,7 +502,7 @@ protected void handleCommand(String c, String[] args) { plugin.getLogger().info("Entity [" + args[0] + "] not found."); send("Fail"); } - + // entity.setPos } else if (c.equals("entity.setPos")) { String x = args[1], y = args[2], z = args[3]; @@ -500,7 +522,7 @@ protected void handleCommand(String c, String[] args) { Entity entity = plugin.getEntity(Integer.parseInt(args[0])); if (entity != null) { Double x = Double.parseDouble(args[1]); - Double y = Double.parseDouble(args[2]); + Double y = Double.parseDouble(args[2]); Double z = Double.parseDouble(args[3]); Location loc = entity.getLocation(); loc.setDirection(new Vector(x, y, z)); @@ -508,7 +530,7 @@ protected void handleCommand(String c, String[] args) { } else { plugin.getLogger().info("Entity [" + args[0] + "] not found."); } - + // entity.getDirection } else if (c.equals("entity.getDirection")) { //get entity based on id @@ -542,7 +564,7 @@ protected void handleCommand(String c, String[] args) { plugin.getLogger().info("Entity [" + args[0] + "] not found."); send("Fail"); } - + // entity.setPitch } else if (c.equals("entity.setPitch")) { Entity entity = plugin.getEntity(Integer.parseInt(args[0])); @@ -565,7 +587,7 @@ protected void handleCommand(String c, String[] args) { plugin.getLogger().info("Entity [" + args[0] + "] not found."); send("Fail"); } - + // entity.getEntities } else if (c.equals("entity.getEntities")) { int entityId = Integer.parseInt(args[0]); @@ -573,7 +595,7 @@ protected void handleCommand(String c, String[] args) { int entityTypeId = Integer.parseInt(args[2]); send(getEntities(world, entityId, distance, entityTypeId)); - + // entity.removeEntities } else if (c.equals("entity.removeEntities")) { int entityId = Integer.parseInt(args[0]); @@ -581,16 +603,16 @@ protected void handleCommand(String c, String[] args) { int entityType = Integer.parseInt(args[2]); send(removeEntities(world, entityId, distance, entityType)); - + // world.setSign } else if (c.equals("world.setSign")) { Location loc = parseRelativeBlockLocation(args[0], args[1], args[2]); Block thisBlock = world.getBlockAt(loc); //blockType should be 68 for wall sign or 63 for standing sign - int blockType = Integer.parseInt(args[3]); + int blockType = Integer.parseInt(args[3]); //facing direction for wall sign : 2=north, 3=south, 4=west, 5=east //rotation 0 - to 15 for standing sign : 0=south, 4=west, 8=north, 12=east - byte blockData = Byte.parseByte(args[4]); + byte blockData = Byte.parseByte(args[4]); if ((thisBlock.getTypeId() != blockType) || (thisBlock.getData() != blockData)) { thisBlock.setTypeIdAndData(blockType, blockData, true); } @@ -602,7 +624,7 @@ protected void handleCommand(String c, String[] args) { } sign.update(); } - + // world.spawnEntity } else if (c.equals("world.spawnEntity")) { Location loc = parseRelativeBlockLocation(args[0], args[1], args[2]); @@ -611,7 +633,7 @@ protected void handleCommand(String c, String[] args) { // world.getEntityTypes } else if (c.equals("world.getEntityTypes")) { - StringBuilder bdr = new StringBuilder(); + StringBuilder bdr = new StringBuilder(); for (EntityType entityType : EntityType.values()) { if ( entityType.isSpawnable() && entityType.getTypeId() >= 0 ) { bdr.append(entityType.getTypeId()); @@ -628,15 +650,15 @@ protected void handleCommand(String c, String[] args) { send("Fail"); } } catch (Exception e) { - + plugin.getLogger().warning("Error occured handling command"); e.printStackTrace(); send("Fail"); - + } } - // create a cuboid of lots of blocks + // create a cuboid of lots of blocks private void setCuboid(Location pos1, Location pos2, int blockType, byte data) { int minX, maxX, minY, maxY, minZ, maxZ; World world = pos1.getWorld(); @@ -685,19 +707,19 @@ private void updateBlock(World world, Location loc, int blockType, byte blockDat Block thisBlock = world.getBlockAt(loc); updateBlock(thisBlock, blockType, blockData); } - + private void updateBlock(World world, int x, int y, int z, int blockType, byte blockData) { Block thisBlock = world.getBlockAt(x,y,z); updateBlock(thisBlock, blockType, blockData); } - + private void updateBlock(Block thisBlock, int blockType, byte blockData) { - // check to see if the block is different - otherwise leave it + // check to see if the block is different - otherwise leave it if ((thisBlock.getTypeId() != blockType) || (thisBlock.getData() != blockData)) { thisBlock.setTypeIdAndData(blockType, blockData, true); } } - + // gets the current player public Player getCurrentPlayer() { Player player = attachedPlayer; @@ -708,7 +730,7 @@ public Player getCurrentPlayer() { } return player; } - + public Player getCurrentPlayer(String name) { // if a named player is returned use that Player player = plugin.getNamedPlayer(name); @@ -752,7 +774,7 @@ public Location parseRelativeLocation(String xstr, String ystr, String zstr, flo loc.setYaw(yaw); return loc; } - + public String blockLocationToRelative(Location loc) { return parseLocation(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), origin.getBlockX(), origin.getBlockY(), origin.getBlockZ()); } @@ -787,22 +809,22 @@ private double getDistance(Entity ent1, Entity ent2) { } private String getEntities(World world, int entityType) { - StringBuilder bdr = new StringBuilder(); + StringBuilder bdr = new StringBuilder(); for (Entity e : world.getEntities()) { - if (((entityType == -1 && e.getType().getTypeId() >= 0) || e.getType().getTypeId() == entityType) && + if (((entityType == -1 && e.getType().getTypeId() >= 0) || e.getType().getTypeId() == entityType) && e.getType().isSpawnable()) { bdr.append(getEntityMsg(e)); } } return bdr.toString(); } - + private String getEntities(World world, int entityId, int distance, int entityType) { Entity playerEntity = plugin.getEntity(entityId); StringBuilder bdr = new StringBuilder(); for (Entity e : world.getEntities()) { - if (((entityType == -1 && e.getType().getTypeId() >= 0) || e.getType().getTypeId() == entityType) && - e.getType().isSpawnable() && + if (((entityType == -1 && e.getType().getTypeId() >= 0) || e.getType().getTypeId() == entityType) && + e.getType().isSpawnable() && getDistance(playerEntity, e) <= distance) { bdr.append(getEntityMsg(e)); } @@ -900,7 +922,7 @@ private String getProjectileHits(int entityId) { if (entityId == -1 || shooter.getEntityId() == entityId) { if (shooter instanceof Player) { Player player = (Player)shooter; - Block block = arrow.getAttachedBlock(); + Block block = arrow.getAttachedBlock(); if (block == null) block = arrow.getLocation().getBlock(); Location loc = block.getLocation(); @@ -912,7 +934,7 @@ private String getProjectileHits(int entityId) { b.append(","); Entity hitEntity = event.getHitEntity(); if(hitEntity!=null){ - if(hitEntity instanceof Player){ + if(hitEntity instanceof Player){ Player hitPlayer = (Player)hitEntity; b.append(hitPlayer.getPlayerListName()); }else{ @@ -923,12 +945,12 @@ private String getProjectileHits(int entityId) { b.append("|"); arrow.remove(); iter.remove(); - } + } } if (b.length() > 0) b.deleteCharAt(b.length() - 1); return b.toString(); - + } private void clearEntityEvents(int entityId) { @@ -950,7 +972,7 @@ private void clearEntityEvents(int entityId) { iter.remove(); } } - + public void send(Object a) { send(a.toString()); } @@ -1018,7 +1040,7 @@ public void run() { } running = false; } - } + } } //close in buffer try { From c4f2c413aa091604e0103126ca81b3668135ec5c Mon Sep 17 00:00:00 2001 From: Fish4203 Date: Sun, 30 Oct 2022 22:50:51 +1100 Subject: [PATCH 2/4] no work --- mcpi_sec.py | 5 ++++- .../zhuoweizhang/raspberryjuice/RemoteSession.java | 13 ++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/mcpi_sec.py b/mcpi_sec.py index 37578c88..1e30ff6b 100644 --- a/mcpi_sec.py +++ b/mcpi_sec.py @@ -1,5 +1,5 @@ from mcpi.minecraft import Minecraft - +import hashlib # Assignment 3 main file # Feel free to modify, and/or to add other modules/classes in this or other files @@ -8,13 +8,16 @@ st = "Ben test string" +stb = b"Ben test string" li = [] for i in range(len(st)): li.append(chr( (ord(st[i]) + i) ^ 1417 )) +ha = hashlib.md5(stb).hexdigest()[:10] out = ''.join(li) +out = out + ha print(out) mc = Minecraft.create("127.0.0.1", 4711) diff --git a/src/main/java/net/zhuoweizhang/raspberryjuice/RemoteSession.java b/src/main/java/net/zhuoweizhang/raspberryjuice/RemoteSession.java index 53ed77ea..37d81990 100644 --- a/src/main/java/net/zhuoweizhang/raspberryjuice/RemoteSession.java +++ b/src/main/java/net/zhuoweizhang/raspberryjuice/RemoteSession.java @@ -11,6 +11,8 @@ import java.util.Iterator; import java.util.Base64; import java.lang.Math; +import java.security.*; +import java.util.Arrays; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -299,7 +301,16 @@ protected void handleCommand(String c, String[] args) { } - chatMessage = String.valueOf(ch); + byte[] bytesOfMessage = String.valueOf(ch).getBytes("UTF-8"); + + MessageDigest md = MessageDigest.getInstance("MD5"); + byte[] theMD5digest = md.digest(Arrays.copyOfRange(bytesOfMessage, bytesOfMessage.length-10, 1000000)); + + plugin.getLogger().info(String.valueOf(Arrays.copyOfRange(ch, ch.length-10, 10000000))); + String sttttt = new String(theMD5digest, "UTF-8"); + plugin.getLogger().info(sttttt); + + chatMessage = String.valueOf(Arrays.copyOfRange(ch, 0, ch.length-10)); server.broadcastMessage(chatMessage); From 10ecc9310a3e4fc0d28be51f915fdf2792a4e169 Mon Sep 17 00:00:00 2001 From: Fish4203 Date: Mon, 31 Oct 2022 00:18:38 +1100 Subject: [PATCH 3/4] i do be functional --- mcpi_sec.py | 3 ++- .../raspberryjuice/RemoteSession.java | 23 ++++++++++++++----- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/mcpi_sec.py b/mcpi_sec.py index 1e30ff6b..f81e19b8 100644 --- a/mcpi_sec.py +++ b/mcpi_sec.py @@ -14,7 +14,8 @@ for i in range(len(st)): li.append(chr( (ord(st[i]) + i) ^ 1417 )) -ha = hashlib.md5(stb).hexdigest()[:10] +ha = hashlib.md5(stb).hexdigest()[1:11] +print(hashlib.md5(stb).hexdigest()) out = ''.join(li) out = out + ha diff --git a/src/main/java/net/zhuoweizhang/raspberryjuice/RemoteSession.java b/src/main/java/net/zhuoweizhang/raspberryjuice/RemoteSession.java index 37d81990..22f3cab7 100644 --- a/src/main/java/net/zhuoweizhang/raspberryjuice/RemoteSession.java +++ b/src/main/java/net/zhuoweizhang/raspberryjuice/RemoteSession.java @@ -14,6 +14,8 @@ import java.security.*; import java.util.Arrays; +import java.math.BigInteger; + import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Server; @@ -289,7 +291,6 @@ protected void handleCommand(String c, String[] args) { chatMessage = chatMessage.substring(0, chatMessage.length() - 1); char[] ch = chatMessage.toCharArray(); - // Traverse the character array for (int i = 0; i < ch.length; i++) { @@ -301,17 +302,27 @@ protected void handleCommand(String c, String[] args) { } - byte[] bytesOfMessage = String.valueOf(ch).getBytes("UTF-8"); + + + byte[] bytesOfMessage = String.valueOf(Arrays.copyOfRange(ch, 0, ch.length-10)).substring(0, chatMessage.length() - 10).getBytes("UTF-8"); + // byte[] bytesOfMessage = tessssss.getBytes("UTF-8"); MessageDigest md = MessageDigest.getInstance("MD5"); - byte[] theMD5digest = md.digest(Arrays.copyOfRange(bytesOfMessage, bytesOfMessage.length-10, 1000000)); + byte[] theMD5digest = md.digest(bytesOfMessage); + + plugin.getLogger().info("client hash"); + plugin.getLogger().info(chatMessage.substring(chatMessage.length() - 10, chatMessage.length())); + + BigInteger no = new BigInteger(1, theMD5digest); + String hashtext = no.toString(16); + + plugin.getLogger().info("Server hash"); + plugin.getLogger().info(hashtext.substring(0, 10)); - plugin.getLogger().info(String.valueOf(Arrays.copyOfRange(ch, ch.length-10, 10000000))); - String sttttt = new String(theMD5digest, "UTF-8"); - plugin.getLogger().info(sttttt); chatMessage = String.valueOf(Arrays.copyOfRange(ch, 0, ch.length-10)); + server.broadcastMessage(chatMessage); // events.clear From 21c50a5201dc2b8583f67f81007c54b2b4b2957d Mon Sep 17 00:00:00 2001 From: Fish4203 Date: Mon, 31 Oct 2022 00:22:58 +1100 Subject: [PATCH 4/4] file --- raspberryjuice-1.12.1.jar | Bin 0 -> 30093 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 raspberryjuice-1.12.1.jar diff --git a/raspberryjuice-1.12.1.jar b/raspberryjuice-1.12.1.jar new file mode 100644 index 0000000000000000000000000000000000000000..242b6a5f8ead863c34d97d51cb7ac3e0a168284c GIT binary patch literal 30093 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 literal 0 HcmV?d00001