From bab0d11c59071d33efbc00f1eb2f56671d24a401 Mon Sep 17 00:00:00 2001 From: sirjonasxx <36828922+sirjonasxx@users.noreply.github.com> Date: Thu, 7 May 2020 03:17:20 +0200 Subject: [PATCH] redoing part of hpacket code --- .../InvalidPacketException.java | 4 + .../packetrepresentation/PacketStructure.java | 143 ++++++++++++ .../main/java/gearth/protocol/HPacket.java | 211 ++---------------- 3 files changed, 165 insertions(+), 193 deletions(-) create mode 100644 G-Earth/src/main/java/gearth/misc/packetrepresentation/InvalidPacketException.java create mode 100644 G-Earth/src/main/java/gearth/misc/packetrepresentation/PacketStructure.java diff --git a/G-Earth/src/main/java/gearth/misc/packetrepresentation/InvalidPacketException.java b/G-Earth/src/main/java/gearth/misc/packetrepresentation/InvalidPacketException.java new file mode 100644 index 0000000..e360c58 --- /dev/null +++ b/G-Earth/src/main/java/gearth/misc/packetrepresentation/InvalidPacketException.java @@ -0,0 +1,4 @@ +package gearth.misc.packetrepresentation; + +public class InvalidPacketException extends Exception { +} diff --git a/G-Earth/src/main/java/gearth/misc/packetrepresentation/PacketStructure.java b/G-Earth/src/main/java/gearth/misc/packetrepresentation/PacketStructure.java new file mode 100644 index 0000000..79dc962 --- /dev/null +++ b/G-Earth/src/main/java/gearth/misc/packetrepresentation/PacketStructure.java @@ -0,0 +1,143 @@ +package gearth.misc.packetrepresentation; + +import gearth.protocol.HPacket; + +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +// for all the logistics behind bytes-string conversion +public class PacketStructure { + + private static String replaceAll(String templateText, String regex, + Function replacer) { + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(templateText); + StringBuffer result = new StringBuffer(); + while (matcher.find()) { + matcher.appendReplacement(result, replacer.apply(matcher)); + } + matcher.appendTail(result); + return result.toString(); + } + + + public static HPacket fromString(String packet) throws InvalidPacketException { + boolean fixLengthLater = false; + if (packet.startsWith("{l}")) { + fixLengthLater = true; + packet = packet.substring(3); + } + + // note: in String expressions {s:"string"}, character " needs to be backslashed -> \" if used in string + packet = replaceAll(packet, "\\{i:(-?[0-9]+)}", + m -> toString(ByteBuffer.allocate(4).putInt(Integer.parseInt(m.group(1))).array())); + + packet = replaceAll(packet, "\\{d:(-?[0-9]*\\.[0-9]*)}", + m -> toString(ByteBuffer.allocate(8).putDouble(Double.parseDouble(m.group(1))).array())); + + packet = replaceAll(packet, "\\{u:([0-9]+)}", + m -> "[" + (Integer.parseInt(m.group(1))/256) + "][" + (Integer.parseInt(m.group(1)) % 256) + "]"); + + packet = replaceAll(packet, "\\{b:([Ff]alse|[Tt]rue)}", + m -> m.group(1).toLowerCase().equals("true") ? "[1]" : "[0]"); + + packet = replaceAll(packet, "\\{b:([0-9]{1,3})}", + m -> "[" + Integer.parseInt(m.group(1)) + "]"); + + packet = replaceAll(packet, "\\{s:\"(([^\"]|(\\\\\"))*)\"}", + m -> { + String match = m.group(1).replace("\\\"", "\""); + return toString(new HPacket(0, match).readBytes(match.length() + 2, 6)); + }); + + if (packet.contains("{") || packet.contains("}")) { + throw new InvalidPacketException(); + } + + boolean[] corrupted = new boolean[]{false}; + packet = replaceAll(packet, "\\[([0-9]{1,3})]", m -> { + int b = Integer.parseInt(m.group(1)); + if (b < 0 || b >= 256) { + corrupted[0] = true; + return ""; + } + return new String(new byte[]{(byte) (b > 127 ? b - 256 : b)}, StandardCharsets.ISO_8859_1); + }); + if (corrupted[0]) { + throw new InvalidPacketException(); + } + + byte[] packetInBytes = packet.getBytes(StandardCharsets.ISO_8859_1); + if (fixLengthLater) { + byte[] combined = new byte[4 + packetInBytes.length]; + System.arraycopy(packetInBytes,0, combined, 4, packetInBytes.length); + packetInBytes = combined; + } + + HPacket hPacket = new HPacket(packetInBytes); + if (fixLengthLater) { + hPacket.fixLength(); + } + return hPacket; + } + + public static String toString(byte[] packet) { + StringBuilder teststring = new StringBuilder(); + for (byte x : packet) { + if ((x < 32 && x >= 0) || x < -96 || x == 93 || x == 91 || x == 125 || x == 123 || x == 127 ) + teststring.append("[").append((((int) x) + 256) % 256).append("]"); + else { + teststring.append(new String(new byte[]{x}, StandardCharsets.ISO_8859_1)); + } + } + return teststring.toString(); + } + + public static boolean structureEquals(HPacket packet, String structure) { + if (packet.isCorrupted()) return false; + + int indexbuffer = packet.getReadIndex(); + packet.setReadIndex(6); + + String[] split = structure.split(","); + + for (int i = 0; i < split.length; i++) { + String s = split[i]; + + if (s.equals("s")) { + if (packet.getReadIndex() + 2 > packet.getBytesLength() || + packet.readUshort(packet.getReadIndex()) + 2 + packet.getReadIndex() > packet.getBytesLength()) return false; + packet.readString(); + } + else if (s.equals("i")) { + if (packet.getReadIndex() + 4 > packet.getBytesLength()) return false; + packet.readInteger(); + } + else if (s.equals("u")) { + if (packet.getReadIndex() + 2 > packet.getBytesLength()) return false; + packet.readUshort(); + } + else if (s.equals("b")) { + if (packet.getReadIndex() + 1 > packet.getBytesLength()) return false; + packet.readBoolean(); + } + } + + boolean result = (packet.isEOF() == 1); + packet.setReadIndex(indexbuffer); + return result; + } + + public static void main(String[] args) throws InvalidPacketException { + HPacket p1 = fromString("{l}{u:1129}{s:\"g\\\"fs\"}{i:0}{i:0}{d:5.7}"); + System.out.println(p1); + + HPacket p2 = fromString("{l}{u:4564}{i:3}{i:0}{s:\"hi\"}{i:0}{i:1}{s:\"how\"}{i:3}{b:1}{b:2}{b:3}{i:2}{s:\"r u\"}{i:1}{b:120}{i:2}{b:true}"); + System.out.println(p2); + + } + +} diff --git a/G-Earth/src/main/java/gearth/protocol/HPacket.java b/G-Earth/src/main/java/gearth/protocol/HPacket.java index 5dc7587..84477c8 100644 --- a/G-Earth/src/main/java/gearth/protocol/HPacket.java +++ b/G-Earth/src/main/java/gearth/protocol/HPacket.java @@ -3,12 +3,13 @@ package gearth.protocol; import gearth.misc.StringifyAble; import gearth.misc.harble_api.HarbleAPI; import gearth.misc.harble_api.HarbleAPIFetcher; +import gearth.misc.packetrepresentation.InvalidPacketException; +import gearth.misc.packetrepresentation.PacketStructure; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.security.InvalidParameterException; -import java.util.ArrayList; import java.util.Arrays; public class HPacket implements StringifyAble { @@ -25,7 +26,13 @@ public class HPacket implements StringifyAble { isEdited = packet.isEdited; } public HPacket(String packet) { - packetInBytes = fromStringToBytes(fromExpressionToString(packet)); + try { + packetInBytes = PacketStructure.fromString(packet).packetInBytes; + } catch (InvalidPacketException e) { + packetInBytes = new byte[0]; + // will be corrupted + e.printStackTrace(); + } } public HPacket(int header) { packetInBytes = new byte[]{0,0,0,2,0,0}; @@ -68,193 +75,11 @@ public class HPacket implements StringifyAble { } public String toString() { - String teststring = ""; - for (byte x : packetInBytes) { - if ((x < 32 && x >= 0) || x < -96 || x == 93 || x == 91 || x == 125 || x == 123 || x == 127 ) - teststring+="["+((((int)x) + 256 ) % 256)+"]"; - else - try { - teststring+=new String(new byte[]{x}, "ISO-8859-1"); //"ISO-8859-1" - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - } - return teststring; - } - - /** - * returns "" if invalid expression, replaces all {} occurences except {l} - * @return - */ - private static String fromExpressionToString(String input) { - try { - int i = 0; - char[] asChararray = input.toCharArray(); - StringBuilder newString = new StringBuilder(); - if (input.startsWith("{l}")) { - newString.append("{l}"); - i = 3; - } - - while (i < input.length()) { - if (asChararray[i] != '{') { - newString.append(asChararray[i]); - i++; - } - else { - i++; - StringBuilder typeBuilder = new StringBuilder(); - while (i < input.length() && asChararray[i] != ':') { - typeBuilder.append(asChararray[i]); - i++; - } - if (i == input.length()) throw new Exception(); - String type = typeBuilder.toString(); - i++; - - StringBuilder inhoudBuilder = new StringBuilder(); - while (i < input.length() && asChararray[i] != '}') { - inhoudBuilder.append(asChararray[i]); - i++; - } - if (i == input.length()) throw new Exception(); - String inhoud = inhoudBuilder.toString(); - i++; - - if (type.equals("u")) { - int probs = Integer.parseInt(inhoud); - if (probs < 0 || probs >= 256 * 256) throw new Exception(); - newString.append("[").append(probs / 256).append("][").append(probs % 256).append("]"); - } - else if (type.equals("i")) { - ByteBuffer b = ByteBuffer.allocate(4).putInt(Integer.parseInt(inhoud)); - newString.append(new HPacket(b.array()).toString()); - } - else if (type.equals("d")) { - ByteBuffer b = ByteBuffer.allocate(8).putDouble(Double.parseDouble(inhoud)); - newString.append(new HPacket(b.array()).toString()); - } - else if (type.equals("b")) { // could be a byte or a boolean, no one cares - if (inhoud.toLowerCase().equals("true") || inhoud.toLowerCase().equals("false")) { - newString.append(inhoud.toLowerCase().equals("true") ? "[1]" : "[0]"); - } - else { - int probs = Integer.parseInt(inhoud); - if (probs < 0 || probs >= 256) throw new Exception(); - newString.append("[").append(probs).append("]"); - } - } - else if (type.equals("s")) { - int probs = inhoud.length(); - if (probs < 0 || probs >= 256 * 256) throw new Exception(); - newString.append("[").append(probs / 256).append("][").append(probs % 256).append("]"); - - byte[] bts = inhoud.getBytes(StandardCharsets.ISO_8859_1); - for (int j = 0; j < inhoud.length(); j++) { - newString.append("[").append((((int)(bts[j])) + 256) % 256).append("]"); - } - } - else throw new Exception(); - - } - } - return newString.toString(); - } - catch( Exception e) { - return ""; - } - } - private static byte[] fromStringToBytes(String curstring) { - try { - ArrayList bytes = new ArrayList<>(); - int index = 0; - char[] asChararray = curstring.toCharArray(); - byte[] asliteralbytes = curstring.getBytes("ISO-8859-1"); - - boolean startWithLength = false; - if (curstring.startsWith("{l}")) { - startWithLength = true; - index = 3; - } - - while (index < curstring.length()) { - if (asChararray[index] == '[') { - int l = 2; - while (index + l < curstring.length() && asChararray[index + l] != ']') l++; - if (index + l == curstring.length()) throw new Exception(); - - int result = Integer.parseInt(curstring.substring(index + 1, index + l)); - if (result > 255 || result < 0) throw new Exception(); - - byte rl = result > 127 ? (byte)(result - 256) : (byte)result ; - - bytes.add(rl); - index = index + 1 + l; - } - else { - bytes.add(asliteralbytes[index]); - index++; - } - } - - byte[] result; - if (startWithLength) { - result = new byte[bytes.size() + 4]; - - ByteBuffer b = ByteBuffer.allocate(4); - b.putInt(bytes.size()); - for (int i = 0; i < 4; i++) { - result[i] = b.array()[i]; - } - for (int i = 0; i < bytes.size(); i++) { - result[i + 4] = bytes.get(i); - } - } - else { - result = new byte[bytes.size()]; - for (int i = 0; i < bytes.size(); i++) { - result[i] = bytes.get(i); - } - } - - return result; - } - catch (Exception e){} - return new byte[0]; + return PacketStructure.toString(packetInBytes); } public boolean structureEquals(String structure) { - if (isCorrupted()) return false; - - int indexbuffer = readIndex; - readIndex = 6; - - String[] split = structure.split(","); - - for (int i = 0; i < split.length; i++) { - String s = split[i]; - - if (s.equals("s")) { - if (readIndex + 2 > getBytesLength() || readUshort(readIndex) + 2 + readIndex > getBytesLength()) return false; - readString(); - } - else if (s.equals("i")) { - if (readIndex + 4 > getBytesLength()) return false; - readInteger(); - } - else if (s.equals("u")) { - if (readIndex + 2 > getBytesLength()) return false; - readUshort(); - } - else if (s.equals("b")) { - if (readIndex + 1 > getBytesLength()) return false; - readBoolean(); - } - } - - boolean result = (isEOF() == 1); - readIndex = indexbuffer; - return result; + return PacketStructure.structureEquals(this, structure); } public int isEOF() { @@ -711,7 +536,7 @@ public class HPacket implements StringifyAble { } } else if (c == 'i') builder.append("{i:").append(prevInt = readInteger()).append('}'); - else if (c == 's') builder.append("{s:").append(readString()).append('}'); + else if (c == 's') builder.append("{s:\"").append(readString().replace("\"", "\\\"")).append("\"}"); else if (c == 'd') builder.append("{d:").append(readDouble()).append('}'); else if (c == 'b') builder.append("{b:").append(readByte()).append('}'); else if (c == 'B') builder.append("{b:").append(readBoolean()).append('}'); @@ -769,7 +594,7 @@ public class HPacket implements StringifyAble { for (int j = i; j < potentialstringlength+i+2; j++) { mask[j] = true; } - resultTest[i] = "{s:"+readString(i)+"}"; + resultTest[i] = "{s:\""+readString(i).replace("\"", "\\\"")+"\"}"; i += (1 + potentialstringlength); } } @@ -875,7 +700,7 @@ public class HPacket implements StringifyAble { mask[j] = true; } changed = true; - resultTest[i] = "{s:"+readString(i)+"}"; + resultTest[i] = "{s:\""+readString(i).replace("\"", "\\\"")+"\"}"; i += (1 + potentialstringlength); } } @@ -961,7 +786,7 @@ public class HPacket implements StringifyAble { for (int j = i; j < potentialstringlength+i+2; j++) { mask[j] = true; } - resultTest[i] = "{s:"+readString(i)+"}"; + resultTest[i] = "{s:\""+readString(i).replace("\"", "\\\"")+"\"}"; i += (1 + potentialstringlength); changed = true; } @@ -1000,7 +825,7 @@ public class HPacket implements StringifyAble { if (resultTest[i] != null) expression.append(resultTest[i]); } - return expression.toString().replace("{i:0}{b:false}{b:true}", "{s:}{i:1}"); + return expression.toString().replace("{i:0}{b:false}{b:true}", "{s:\"\"}{i:1}"); } @Override @@ -1025,9 +850,9 @@ public class HPacket implements StringifyAble { } public static void main(String[] args) { - HPacket packet = new HPacket("{l}{u:4564}{i:3}{i:0}{s:hi}{i:0}{i:1}{s:how}{i:3}{b:1}{b:2}{b:3}{i:2}{s:r u}{i:1}{b:120}{i:2}{b:true}"); + HPacket packet = new HPacket("{l}{u:4564}{i:3}{i:0}{s:\"hi\"}{i:0}{i:1}{s:\"how\"}{i:3}{b:1}{b:2}{b:3}{i:2}{s:\"r u\"}{i:1}{b:120}{i:2}{b:true}{d:1.4}"); - String str = packet.toExpressionFromGivenStructure("i(isi(b))iB"); + String str = packet.toExpressionFromGivenStructure("i(isi(b))iBd"); HPacket packetverify = new HPacket(str);