diff --git a/resources/locale b/resources/locale index 8718542e6..157abfa5a 160000 --- a/resources/locale +++ b/resources/locale @@ -1 +1 @@ -Subproject commit 8718542e622014fa81e6c178a3c83202c86ef921 +Subproject commit 157abfa5a2ae85325fb254ec3ca19373116bb6af diff --git a/src/Server.php b/src/Server.php index 43613dd60..e33f943d6 100644 --- a/src/Server.php +++ b/src/Server.php @@ -1286,7 +1286,7 @@ class Server{ } $this->logger->info($this->getLanguage()->translateString("pocketmine.server.defaultGameMode", [$this->getGamemode()->getTranslationKey()])); - + $this->logger->info($this->getLanguage()->translateString("pocketmine.server.donate", [TextFormat::AQUA . "https://patreon.com/pocketminemp" . TextFormat::RESET])); $this->logger->info($this->getLanguage()->translateString("pocketmine.server.startFinished", [round(microtime(true) - $this->startTime, 3)])); //TODO: move console parts to a separate component diff --git a/src/network/mcpe/handler/InGamePacketHandler.php b/src/network/mcpe/handler/InGamePacketHandler.php index 774bc4d1e..f45cdab1e 100644 --- a/src/network/mcpe/handler/InGamePacketHandler.php +++ b/src/network/mcpe/handler/InGamePacketHandler.php @@ -91,8 +91,9 @@ use function json_encode; use function json_last_error_msg; use function microtime; use function preg_match; -use function preg_split; +use function strlen; use function strpos; +use function substr; use function trim; /** @@ -674,18 +675,33 @@ class InGamePacketHandler extends PacketHandler{ */ private static function stupid_json_decode(string $json, bool $assoc = false){ if(preg_match('/^\[(.+)\]$/s', $json, $matches) > 0){ - $parts = preg_split('/(?:"(?:\\"|[^"])*"|)\K(,)/', $matches[1]); //Splits on commas not inside quotes, ignoring escaped quotes - foreach($parts as $k => $part){ - $part = trim($part); - if($part === ""){ - $part = "\"\""; + $raw = $matches[1]; + $lastComma = -1; + $newParts = []; + $quoteType = null; + for($i = 0, $len = strlen($raw); $i <= $len; ++$i){ + if($i === $len or ($raw[$i] === "," and $quoteType === null)){ + $part = substr($raw, $lastComma + 1, $i - ($lastComma + 1)); + if(trim($part) === ""){ //regular parts will have quotes or something else that makes them non-empty + $part = '""'; + } + $newParts[] = $part; + $lastComma = $i; + }elseif($raw[$i] === '"'){ + if($quoteType === null){ + $quoteType = $raw[$i]; + }elseif($raw[$i] === $quoteType){ + for($backslashes = 0; $backslashes < $i && $raw[$i - $backslashes - 1] === "\\"; ++$backslashes){} + if(($backslashes % 2) === 0){ //unescaped quote + $quoteType = null; + } + } } - $parts[$k] = $part; } - $fixed = "[" . implode(",", $parts) . "]"; + $fixed = "[" . implode(",", $newParts) . "]"; if(($ret = json_decode($fixed, $assoc)) === null){ - throw new BadPacketException("Failed to fix JSON: " . json_last_error_msg() . "(original: $json, modified: $fixed)"); + throw new \InvalidArgumentException("Failed to fix JSON: " . json_last_error_msg() . "(original: $json, modified: $fixed)"); } return $ret; diff --git a/tests/phpunit/network/mcpe/handler/StupidJsonDecodeTest.php b/tests/phpunit/network/mcpe/handler/StupidJsonDecodeTest.php index c9b1f2824..1fb04c22e 100644 --- a/tests/phpunit/network/mcpe/handler/StupidJsonDecodeTest.php +++ b/tests/phpunit/network/mcpe/handler/StupidJsonDecodeTest.php @@ -41,7 +41,9 @@ class StupidJsonDecodeTest extends TestCase{ ["NULL", null], ['["\",,\"word","a\",,\"word2",]', ['",,"word', 'a",,"word2', '']], ['["\",,\"word","a\",,\"word2",""]', ['",,"word', 'a",,"word2', '']], - ['["Hello,, PocketMine"]', ['Hello,, PocketMine']] + ['["Hello,, PocketMine"]', ['Hello,, PocketMine']], + ['[,]', ['', '']], + ['[]', []] ]; }