Start using webmozart/pathutil for joining paths (#4287)

This commit is contained in:
Dylan T 2021-06-29 19:40:43 +01:00 committed by GitHub
parent aee7b03c1d
commit 32d7b1e6af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 252 additions and 172 deletions

View File

@ -48,7 +48,8 @@
"pocketmine/snooze": "^0.3.0",
"pocketmine/spl": "dev-master",
"ramsey/uuid": "^4.1",
"respect/validation": "^2.0"
"respect/validation": "^2.0",
"webmozart/path-util": "^2.3"
},
"require-dev": {
"phpstan/phpstan": "0.12.90",

168
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "1ec8a08d7688ec903c9b67945feab26e",
"content-hash": "3e3b505ec39bbf9e449e0466f154d5aa",
"packages": [
{
"name": "adhocore/json-comment",
@ -1310,6 +1310,114 @@
}
],
"time": "2021-05-27T09:27:20+00:00"
},
{
"name": "webmozart/assert",
"version": "1.10.0",
"source": {
"type": "git",
"url": "https://github.com/webmozarts/assert.git",
"reference": "6964c76c7804814a842473e0c8fd15bab0f18e25"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25",
"reference": "6964c76c7804814a842473e0c8fd15bab0f18e25",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0",
"symfony/polyfill-ctype": "^1.8"
},
"conflict": {
"phpstan/phpstan": "<0.12.20",
"vimeo/psalm": "<4.6.1 || 4.6.2"
},
"require-dev": {
"phpunit/phpunit": "^8.5.13"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.10-dev"
}
},
"autoload": {
"psr-4": {
"Webmozart\\Assert\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "Assertions to validate method input/output with nice error messages.",
"keywords": [
"assert",
"check",
"validate"
],
"support": {
"issues": "https://github.com/webmozarts/assert/issues",
"source": "https://github.com/webmozarts/assert/tree/1.10.0"
},
"time": "2021-03-09T10:59:23+00:00"
},
{
"name": "webmozart/path-util",
"version": "2.3.0",
"source": {
"type": "git",
"url": "https://github.com/webmozart/path-util.git",
"reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozart/path-util/zipball/d939f7edc24c9a1bb9c0dee5cb05d8e859490725",
"reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"webmozart/assert": "~1.0"
},
"require-dev": {
"phpunit/phpunit": "^4.6",
"sebastian/version": "^1.0.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.3-dev"
}
},
"autoload": {
"psr-4": {
"Webmozart\\PathUtil\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "A robust cross-platform utility for normalizing, comparing and modifying file paths.",
"support": {
"issues": "https://github.com/webmozart/path-util/issues",
"source": "https://github.com/webmozart/path-util/tree/2.3.0"
},
"time": "2015-12-17T08:42:14+00:00"
}
],
"packages-dev": [
@ -3435,64 +3543,6 @@
}
],
"time": "2020-07-12T23:59:07+00:00"
},
{
"name": "webmozart/assert",
"version": "1.10.0",
"source": {
"type": "git",
"url": "https://github.com/webmozarts/assert.git",
"reference": "6964c76c7804814a842473e0c8fd15bab0f18e25"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25",
"reference": "6964c76c7804814a842473e0c8fd15bab0f18e25",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0",
"symfony/polyfill-ctype": "^1.8"
},
"conflict": {
"phpstan/phpstan": "<0.12.20",
"vimeo/psalm": "<4.6.1 || 4.6.2"
},
"require-dev": {
"phpunit/phpunit": "^8.5.13"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.10-dev"
}
},
"autoload": {
"psr-4": {
"Webmozart\\Assert\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "Assertions to validate method input/output with nice error messages.",
"keywords": [
"assert",
"check",
"validate"
],
"support": {
"issues": "https://github.com/webmozarts/assert/issues",
"source": "https://github.com/webmozarts/assert/tree/1.10.0"
},
"time": "2021-03-09T10:59:23+00:00"
}
],
"aliases": [],

View File

@ -31,6 +31,7 @@ use pocketmine\plugin\PluginManager;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\Filesystem;
use pocketmine\utils\Utils;
use Webmozart\PathUtil\Path;
use function base64_encode;
use function date;
use function error_get_last;
@ -103,10 +104,12 @@ class CrashDump{
public function __construct(Server $server){
$this->time = microtime(true);
$this->server = $server;
if(!is_dir($this->server->getDataPath() . "crashdumps")){
mkdir($this->server->getDataPath() . "crashdumps");
$crashPath = Path::join($this->server->getDataPath(), "crashdumps");
if(!is_dir($crashPath)){
mkdir($crashPath);
}
$this->path = $this->server->getDataPath() . "crashdumps/" . date("D_M_j-H.i.s-T_Y", (int) $this->time) . ".log";
$this->path = Path::join($crashPath, date("D_M_j-H.i.s-T_Y", (int) $this->time) . ".log");
$fp = @fopen($this->path, "wb");
if(!is_resource($fp)){
throw new \RuntimeException("Could not create Crash Dump");
@ -193,12 +196,12 @@ class CrashDump{
if($this->server->getConfigGroup()->getPropertyBool("auto-report.send-settings", true)){
$this->data["parameters"] = (array) $argv;
if(($serverDotProperties = @file_get_contents($this->server->getDataPath() . "server.properties")) !== false){
if(($serverDotProperties = @file_get_contents(Path::join($this->server->getDataPath(), "server.properties"))) !== false){
$this->data["server.properties"] = preg_replace("#^rcon\\.password=(.*)$#m", "rcon.password=******", $serverDotProperties);
}else{
$this->data["server.properties"] = $serverDotProperties;
}
if(($pocketmineDotYml = @file_get_contents($this->server->getDataPath() . "pocketmine.yml")) !== false){
if(($pocketmineDotYml = @file_get_contents(Path::join($this->server->getDataPath(), "pocketmine.yml"))) !== false){
$this->data["pocketmine.yml"] = $pocketmineDotYml;
}else{
$this->data["pocketmine.yml"] = "";

View File

@ -30,6 +30,7 @@ use pocketmine\timings\Timings;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\Process;
use pocketmine\utils\Utils;
use Webmozart\PathUtil\Path;
use function arsort;
use function count;
use function fclose;
@ -316,7 +317,7 @@ class MemoryManager{
mkdir($outputFolder, 0777, true);
}
$obData = fopen($outputFolder . "/objects.js", "wb+");
$obData = fopen(Path::join($outputFolder, "objects.js"), "wb+");
$data = [];
@ -367,7 +368,7 @@ class MemoryManager{
}
}
file_put_contents($outputFolder . "/staticProperties.js", json_encode($staticProperties, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
file_put_contents(Path::join($outputFolder, "staticProperties.js"), json_encode($staticProperties, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
$logger->info("Wrote $staticCount static properties");
if(isset($GLOBALS)){ //This might be null if we're on a different thread
@ -395,7 +396,7 @@ class MemoryManager{
$globalVariables[$varName] = self::continueDump($value, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
}
file_put_contents($outputFolder . "/globalVariables.js", json_encode($globalVariables, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
file_put_contents(Path::join($outputFolder, "globalVariables.js"), json_encode($globalVariables, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
$logger->info("Wrote $globalCount global variables");
}
@ -411,7 +412,7 @@ class MemoryManager{
$functionStaticVarsCount += count($vars);
}
}
file_put_contents($outputFolder . '/functionStaticVars.js', json_encode($functionStaticVars, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
file_put_contents(Path::join($outputFolder, 'functionStaticVars.js'), json_encode($functionStaticVars, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
$logger->info("Wrote $functionStaticVarsCount function static variables");
$data = self::continueDump($startingObject, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
@ -483,11 +484,11 @@ class MemoryManager{
fclose($obData);
file_put_contents($outputFolder . "/serverEntry.js", json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
file_put_contents($outputFolder . "/referenceCounts.js", json_encode($refCounts, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
file_put_contents(Path::join($outputFolder, "serverEntry.js"), json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
file_put_contents(Path::join($outputFolder, "referenceCounts.js"), json_encode($refCounts, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
arsort($instanceCounts, SORT_NUMERIC);
file_put_contents($outputFolder . "/instanceCounts.js", json_encode($instanceCounts, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
file_put_contents(Path::join($outputFolder, "instanceCounts.js"), json_encode($instanceCounts, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
$logger->info("Finished!");

View File

@ -33,6 +33,7 @@ namespace pocketmine {
use pocketmine\utils\Terminal;
use pocketmine\utils\Timezone;
use pocketmine\wizard\SetupWizard;
use Webmozart\PathUtil\Path;
use function extension_loaded;
use function phpversion;
use function preg_match;
@ -234,7 +235,7 @@ namespace pocketmine {
mkdir($dataPath, 0777, true);
}
$lockFilePath = $dataPath . '/server.lock';
$lockFilePath = Path::join($dataPath, 'server.lock');
if(($pid = Filesystem::createLockFile($lockFilePath)) !== null){
critical_error("Another " . VersionInfo::NAME . " instance (PID $pid) is already using this folder (" . realpath($dataPath) . ").");
critical_error("Please stop the other server first before running a new one.");
@ -252,14 +253,14 @@ namespace pocketmine {
Terminal::init();
}
$logger = new MainLogger($dataPath . "server.log", Terminal::hasFormattingCodes(), "Server", new \DateTimeZone(Timezone::get()));
$logger = new MainLogger(Path::join($dataPath, "server.log"), Terminal::hasFormattingCodes(), "Server", new \DateTimeZone(Timezone::get()));
\GlobalLogger::set($logger);
emit_performance_warnings($logger);
$exitCode = 0;
do{
if(!file_exists($dataPath . "server.properties") and !isset($opts["no-wizard"])){
if(!file_exists(Path::join($dataPath, "server.properties")) and !isset($opts["no-wizard"])){
$installer = new SetupWizard($dataPath);
if(!$installer->run()){
$exitCode = -1;

View File

@ -105,6 +105,7 @@ use pocketmine\world\World;
use pocketmine\world\WorldCreationOptions;
use pocketmine\world\WorldManager;
use Ramsey\Uuid\UuidInterface;
use Webmozart\PathUtil\Path;
use function array_shift;
use function array_sum;
use function base64_encode;
@ -515,7 +516,7 @@ class Server{
}
private function getPlayerDataPath(string $username) : string{
return $this->getDataPath() . '/players/' . strtolower($username) . '.dat';
return Path::join($this->getDataPath(), 'players', strtolower($username) . '.dat');
}
/**
@ -811,33 +812,33 @@ class Server{
$this->logger = $logger;
try{
if(!file_exists($dataPath . "worlds/")){
mkdir($dataPath . "worlds/", 0777);
}
if(!file_exists($dataPath . "players/")){
mkdir($dataPath . "players/", 0777);
}
if(!file_exists($pluginPath)){
mkdir($pluginPath, 0777);
foreach([
$dataPath,
$pluginPath,
Path::join($dataPath, "worlds"),
Path::join($dataPath, "players")
] as $neededPath){
if(!file_exists($neededPath)){
mkdir($neededPath, 0777);
}
}
$this->dataPath = realpath($dataPath) . DIRECTORY_SEPARATOR;
$this->pluginPath = realpath($pluginPath) . DIRECTORY_SEPARATOR;
$this->logger->info("Loading server configuration");
if(!file_exists($this->dataPath . "pocketmine.yml")){
$content = file_get_contents(\pocketmine\RESOURCE_PATH . "pocketmine.yml");
$pocketmineYmlPath = Path::join($this->dataPath, "pocketmine.yml");
if(!file_exists($pocketmineYmlPath)){
$content = file_get_contents(Path::join(\pocketmine\RESOURCE_PATH, "pocketmine.yml"));
if(VersionInfo::IS_DEVELOPMENT_BUILD){
$content = str_replace("preferred-channel: stable", "preferred-channel: beta", $content);
}
@file_put_contents($this->dataPath . "pocketmine.yml", $content);
@file_put_contents($pocketmineYmlPath, $content);
}
$this->configGroup = new ServerConfigGroup(
new Config($this->dataPath . "pocketmine.yml", Config::YAML, []),
new Config($this->dataPath . "server.properties", Config::PROPERTIES, [
new Config($pocketmineYmlPath, Config::YAML, []),
new Config(Path::join($this->dataPath, "server.properties"), Config::PROPERTIES, [
"motd" => VersionInfo::NAME . " Server",
"server-port" => 19132,
"white-list" => false,
@ -934,16 +935,20 @@ class Server{
$this->doTitleTick = $this->configGroup->getPropertyBool("console.title-tick", true) && Terminal::hasFormattingCodes();
$this->operators = new Config($this->dataPath . "ops.txt", Config::ENUM);
$this->whitelist = new Config($this->dataPath . "white-list.txt", Config::ENUM);
if(file_exists($this->dataPath . "banned.txt") and !file_exists($this->dataPath . "banned-players.txt")){
@rename($this->dataPath . "banned.txt", $this->dataPath . "banned-players.txt");
$this->operators = new Config(Path::join($this->dataPath, "ops.txt"), Config::ENUM);
$this->whitelist = new Config(Path::join($this->dataPath, "white-list.txt"), Config::ENUM);
$bannedTxt = Path::join($this->dataPath, "banned.txt");
$bannedPlayersTxt = Path::join($this->dataPath, "banned-players.txt");
if(file_exists($bannedTxt) and !file_exists($bannedPlayersTxt)){
@rename($bannedTxt, $bannedPlayersTxt);
}
@touch($this->dataPath . "banned-players.txt");
$this->banByName = new BanList($this->dataPath . "banned-players.txt");
@touch($bannedPlayersTxt);
$this->banByName = new BanList($bannedPlayersTxt);
$this->banByName->load();
@touch($this->dataPath . "banned-ips.txt");
$this->banByIP = new BanList($this->dataPath . "banned-ips.txt");
$bannedIpsTxt = Path::join($this->dataPath, "banned-ips.txt");
@touch($bannedIpsTxt);
$this->banByIP = new BanList($bannedIpsTxt);
$this->banByIP->load();
$this->maxPlayers = $this->configGroup->getConfigInt("max-players", 20);
@ -985,14 +990,14 @@ class Server{
$this->commandMap = new SimpleCommandMap($this);
$this->craftingManager = CraftingManagerFromDataHelper::make(\pocketmine\RESOURCE_PATH . '/vanilla/recipes.json');
$this->craftingManager = CraftingManagerFromDataHelper::make(Path::join(\pocketmine\RESOURCE_PATH, "vanilla", "recipes.json"));
$this->resourceManager = new ResourcePackManager($this->getDataPath() . "resource_packs" . DIRECTORY_SEPARATOR, $this->logger);
$this->resourceManager = new ResourcePackManager(Path::join($this->getDataPath(), "resource_packs"), $this->logger);
$pluginGraylist = null;
$graylistFile = $this->dataPath . "plugin_list.yml";
$graylistFile = Path::join($this->dataPath, "plugin_list.yml");
if(!file_exists($graylistFile)){
copy(\pocketmine\RESOURCE_PATH . 'plugin_list.yml', $graylistFile);
copy(Path::join(\pocketmine\RESOURCE_PATH, 'plugin_list.yml'), $graylistFile);
}
try{
$pluginGraylist = PluginGraylist::fromArray(yaml_parse(file_get_contents($graylistFile)));
@ -1001,7 +1006,7 @@ class Server{
$this->forceShutdown();
return;
}
$this->pluginManager = new PluginManager($this, $this->configGroup->getPropertyBool("plugins.legacy-data-dir", true) ? null : $this->getDataPath() . "plugin_data" . DIRECTORY_SEPARATOR, $pluginGraylist);
$this->pluginManager = new PluginManager($this, $this->configGroup->getPropertyBool("plugins.legacy-data-dir", true) ? null : Path::join($this->getDataPath(), "plugin_data"), $pluginGraylist);
$this->pluginManager->registerInterface(new PharPluginLoader($this->autoloader));
$this->pluginManager->registerInterface(new ScriptPluginLoader());
@ -1015,7 +1020,7 @@ class Server{
$this->logger->warning($this->language->translateString("pocketmine.level.badDefaultFormat", [$formatName]));
}
$this->worldManager = new WorldManager($this, $this->dataPath . "/worlds", $providerManager);
$this->worldManager = new WorldManager($this, Path::join($this->dataPath, "worlds"), $providerManager);
$this->worldManager->setAutoSave($this->configGroup->getConfigBool("auto-save", $this->worldManager->getAutoSave()));
$this->worldManager->setAutoSaveInterval($this->configGroup->getPropertyInt("ticks-per.autosave", 6000));
@ -1504,7 +1509,7 @@ class Server{
if($this->configGroup->getPropertyBool("auto-report.enabled", true)){
$report = true;
$stamp = $this->getDataPath() . "crashdumps/.last_crash";
$stamp = Path::join($this->getDataPath(), "crashdumps", ".last_crash");
$crashInterval = 120; //2 minutes
if(file_exists($stamp) and !($report = (filemtime($stamp) + $crashInterval < time()))){
$this->logger->debug("Not sending crashdump due to last crash less than $crashInterval seconds ago");

View File

@ -25,6 +25,7 @@ namespace pocketmine\command\defaults;
use pocketmine\command\CommandSender;
use pocketmine\permission\DefaultPermissionNames;
use Webmozart\PathUtil\Path;
use function date;
class DumpMemoryCommand extends VanillaCommand{
@ -43,7 +44,7 @@ class DumpMemoryCommand extends VanillaCommand{
return true;
}
$sender->getServer()->getMemoryManager()->dumpServerMemory($args[0] ?? ($sender->getServer()->getDataPath() . "/memory_dumps/" . date("D_M_j-H.i.s-T_Y")), 48, 80);
$sender->getServer()->getMemoryManager()->dumpServerMemory($args[0] ?? (Path::join($sender->getServer()->getDataPath(), "memory_dumps" . date("D_M_j-H.i.s-T_Y"))), 48, 80);
return true;
}
}

View File

@ -34,6 +34,7 @@ use pocketmine\scheduler\BulkCurlTaskOperation;
use pocketmine\timings\TimingsHandler;
use pocketmine\utils\InternetException;
use pocketmine\utils\InternetRequestResult;
use Webmozart\PathUtil\Path;
use function count;
use function fclose;
use function file_exists;
@ -107,14 +108,14 @@ class TimingsCommand extends VanillaCommand{
$fileTimings = fopen("php://temp", "r+b");
}else{
$index = 0;
$timingFolder = $sender->getServer()->getDataPath() . "timings/";
$timingFolder = Path::join($sender->getServer()->getDataPath(), "timings");
if(!file_exists($timingFolder)){
mkdir($timingFolder, 0777);
}
$timings = $timingFolder . "timings.txt";
$timings = Path::join($timingFolder, "timings.txt");
while(file_exists($timings)){
$timings = $timingFolder . "timings" . (++$index) . ".txt";
$timings = Path::join($timingFolder, "timings" . (++$index) . ".txt");
}
$fileTimings = fopen($timings, "a+b");

View File

@ -24,11 +24,12 @@ declare(strict_types=1);
namespace pocketmine\data\bedrock;
use pocketmine\utils\SingletonTrait;
use Webmozart\PathUtil\Path;
final class LegacyBlockIdToStringIdMap extends LegacyToStringBidirectionalIdMap{
use SingletonTrait;
public function __construct(){
parent::__construct(\pocketmine\RESOURCE_PATH . 'vanilla/block_id_map.json');
parent::__construct(Path::join(\pocketmine\RESOURCE_PATH, 'vanilla', 'block_id_map.json'));
}
}

View File

@ -24,11 +24,12 @@ declare(strict_types=1);
namespace pocketmine\data\bedrock;
use pocketmine\utils\SingletonTrait;
use Webmozart\PathUtil\Path;
final class LegacyEntityIdToStringIdMap extends LegacyToStringBidirectionalIdMap{
use SingletonTrait;
public function __construct(){
parent::__construct(\pocketmine\RESOURCE_PATH . '/vanilla/entity_id_map.json');
parent::__construct(Path::join(\pocketmine\RESOURCE_PATH, 'vanilla', 'entity_id_map.json'));
}
}

View File

@ -24,11 +24,12 @@ declare(strict_types=1);
namespace pocketmine\data\bedrock;
use pocketmine\utils\SingletonTrait;
use Webmozart\PathUtil\Path;
final class LegacyItemIdToStringIdMap extends LegacyToStringBidirectionalIdMap{
use SingletonTrait;
public function __construct(){
parent::__construct(\pocketmine\RESOURCE_PATH . 'vanilla/item_id_map.json');
parent::__construct(Path::join(\pocketmine\RESOURCE_PATH, 'vanilla', 'item_id_map.json'));
}
}

View File

@ -26,9 +26,9 @@ namespace pocketmine\inventory;
use pocketmine\item\Durable;
use pocketmine\item\Item;
use pocketmine\utils\SingletonTrait;
use Webmozart\PathUtil\Path;
use function file_get_contents;
use function json_decode;
use const DIRECTORY_SEPARATOR;
final class CreativeInventory{
use SingletonTrait;
@ -37,7 +37,7 @@ final class CreativeInventory{
private $creative = [];
private function __construct(){
$creativeItems = json_decode(file_get_contents(\pocketmine\RESOURCE_PATH . "vanilla" . DIRECTORY_SEPARATOR . "creativeitems.json"), true);
$creativeItems = json_decode(file_get_contents(Path::join(\pocketmine\RESOURCE_PATH, "vanilla", "creativeitems.json")), true);
foreach($creativeItems as $data){
$item = Item::jsonDeserialize($data);

View File

@ -25,6 +25,7 @@ namespace pocketmine\item;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\SingletonTrait;
use Webmozart\PathUtil\Path;
use function explode;
use function file_get_contents;
use function is_array;
@ -51,7 +52,7 @@ final class LegacyStringToItemParser{
private static function make() : self{
$result = new self(ItemFactory::getInstance());
$mappingsRaw = @file_get_contents(\pocketmine\RESOURCE_PATH . '/item_from_string_bc_map.json');
$mappingsRaw = @file_get_contents(Path::join(\pocketmine\RESOURCE_PATH, 'item_from_string_bc_map.json'));
if($mappingsRaw === false) throw new AssumptionFailedError("Missing required resource file");
$mappings = json_decode($mappingsRaw, true);

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\lang;
use Webmozart\PathUtil\Path;
use function array_filter;
use function array_map;
use function explode;
@ -51,7 +52,7 @@ class Language{
*/
public static function getLanguageList(string $path = "") : array{
if($path === ""){
$path = \pocketmine\RESOURCE_PATH . "locale/";
$path = Path::join(\pocketmine\RESOURCE_PATH, "locale");
}
if(is_dir($path)){
@ -100,7 +101,7 @@ class Language{
$this->langName = strtolower($lang);
if($path === null){
$path = \pocketmine\RESOURCE_PATH . "locale/";
$path = Path::join(\pocketmine\RESOURCE_PATH, "locale");
}
$this->lang = self::loadLang($path, $this->langName);
@ -120,7 +121,7 @@ class Language{
* @phpstan-return array<string, string>
*/
protected static function loadLang(string $path, string $languageCode) : array{
$file = $path . $languageCode . ".ini";
$file = Path::join($path, $languageCode . ".ini");
if(file_exists($file)){
return array_map('\stripcslashes', parse_ini_file($file, false, INI_SCANNER_RAW));
}

View File

@ -28,6 +28,7 @@ use pocketmine\network\mcpe\protocol\BiomeDefinitionListPacket;
use pocketmine\network\mcpe\protocol\serializer\NetworkNbtSerializer;
use pocketmine\network\mcpe\protocol\types\CacheableNbt;
use pocketmine\utils\SingletonTrait;
use Webmozart\PathUtil\Path;
use function file_get_contents;
class StaticPacketCache{
@ -49,8 +50,8 @@ class StaticPacketCache{
private static function make() : self{
return new self(
BiomeDefinitionListPacket::create(self::loadCompoundFromFile(\pocketmine\RESOURCE_PATH . '/vanilla/biome_definitions.nbt')),
AvailableActorIdentifiersPacket::create(self::loadCompoundFromFile(\pocketmine\RESOURCE_PATH . '/vanilla/entity_identifiers.nbt'))
BiomeDefinitionListPacket::create(self::loadCompoundFromFile(Path::join(\pocketmine\RESOURCE_PATH, 'vanilla', 'biome_definitions.nbt'))),
AvailableActorIdentifiersPacket::create(self::loadCompoundFromFile(Path::join(\pocketmine\RESOURCE_PATH, 'vanilla', 'entity_identifiers.nbt')))
);
}

View File

@ -27,6 +27,7 @@ use pocketmine\network\mcpe\protocol\serializer\ItemTypeDictionary;
use pocketmine\network\mcpe\protocol\types\ItemTypeEntry;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\SingletonTrait;
use Webmozart\PathUtil\Path;
use function file_get_contents;
use function is_array;
use function is_bool;
@ -38,7 +39,7 @@ final class GlobalItemTypeDictionary{
use SingletonTrait;
private static function make() : self{
$data = file_get_contents(\pocketmine\RESOURCE_PATH . '/vanilla/required_item_list.json');
$data = file_get_contents(Path::join(\pocketmine\RESOURCE_PATH, 'vanilla', 'required_item_list.json'));
if($data === false) throw new AssumptionFailedError("Missing required resource file");
$table = json_decode($data, true);
if(!is_array($table)){

View File

@ -26,6 +26,7 @@ namespace pocketmine\network\mcpe\convert;
use pocketmine\network\mcpe\protocol\serializer\ItemTypeDictionary;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\SingletonTrait;
use Webmozart\PathUtil\Path;
use function array_key_exists;
use function file_get_contents;
use function is_array;
@ -64,14 +65,14 @@ final class ItemTranslator{
private $complexNetToCoreMapping = [];
private static function make() : self{
$data = file_get_contents(\pocketmine\RESOURCE_PATH . '/vanilla/r16_to_current_item_map.json');
$data = file_get_contents(Path::join(\pocketmine\RESOURCE_PATH, 'vanilla', 'r16_to_current_item_map.json'));
if($data === false) throw new AssumptionFailedError("Missing required resource file");
$json = json_decode($data, true);
if(!is_array($json) or !isset($json["simple"], $json["complex"]) || !is_array($json["simple"]) || !is_array($json["complex"])){
throw new AssumptionFailedError("Invalid item table format");
}
$legacyStringToIntMapRaw = file_get_contents(\pocketmine\RESOURCE_PATH . '/vanilla/item_id_map.json');
$legacyStringToIntMapRaw = file_get_contents(Path::join(\pocketmine\RESOURCE_PATH, 'vanilla', 'item_id_map.json'));
if($legacyStringToIntMapRaw === false){
throw new AssumptionFailedError("Missing required resource file");
}

View File

@ -31,6 +31,7 @@ use pocketmine\network\mcpe\protocol\serializer\NetworkNbtSerializer;
use pocketmine\network\mcpe\protocol\serializer\PacketSerializer;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\SingletonTrait;
use Webmozart\PathUtil\Path;
use function file_get_contents;
/**
@ -47,7 +48,7 @@ final class RuntimeBlockMapping{
private $bedrockKnownStates;
private function __construct(){
$canonicalBlockStatesFile = file_get_contents(\pocketmine\RESOURCE_PATH . "vanilla/canonical_block_states.nbt");
$canonicalBlockStatesFile = file_get_contents(Path::join(\pocketmine\RESOURCE_PATH, "vanilla", "canonical_block_states.nbt"));
if($canonicalBlockStatesFile === false){
throw new AssumptionFailedError("Missing required resource file");
}
@ -65,7 +66,7 @@ final class RuntimeBlockMapping{
$legacyIdMap = LegacyBlockIdToStringIdMap::getInstance();
/** @var R12ToCurrentBlockMapEntry[] $legacyStateMap */
$legacyStateMap = [];
$legacyStateMapReader = new PacketSerializer(file_get_contents(\pocketmine\RESOURCE_PATH . "vanilla/r12_to_current_block_map.bin"));
$legacyStateMapReader = new PacketSerializer(file_get_contents(Path::join(\pocketmine\RESOURCE_PATH, "vanilla", "r12_to_current_block_map.bin")));
$nbtReader = new NetworkNbtSerializer();
while(!$legacyStateMapReader->feof()){
$id = $legacyStateMapReader->getString();

View File

@ -31,6 +31,7 @@ use pocketmine\scheduler\TaskScheduler;
use pocketmine\Server;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\Config;
use Webmozart\PathUtil\Path;
use function count;
use function dirname;
use function fclose;
@ -86,7 +87,7 @@ abstract class PluginBase implements Plugin, CommandExecutor{
$this->dataFolder = rtrim($dataFolder, "/" . DIRECTORY_SEPARATOR) . "/";
//TODO: this is accessed externally via reflection, not unused
$this->file = rtrim($file, "/" . DIRECTORY_SEPARATOR) . "/";
$this->configFile = $this->dataFolder . "config.yml";
$this->configFile = Path::join($this->dataFolder, "config.yml");
$prefix = $this->getDescription()->getPrefix();
$this->logger = new PluginLogger($server->getLogger(), $prefix !== "" ? $prefix : $this->getName());
@ -261,7 +262,7 @@ abstract class PluginBase implements Plugin, CommandExecutor{
return false;
}
$out = $this->dataFolder . $filename;
$out = Path::join($this->dataFolder, $filename);
if(!file_exists(dirname($out))){
mkdir(dirname($out), 0755, true);
}

View File

@ -39,6 +39,7 @@ use pocketmine\Server;
use pocketmine\timings\TimingsHandler;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\Utils;
use Webmozart\PathUtil\Path;
use function array_intersect;
use function array_merge;
use function class_exists;
@ -59,7 +60,6 @@ use function shuffle;
use function stripos;
use function strpos;
use function strtolower;
use const DIRECTORY_SEPARATOR;
/**
* Manages all the plugins
@ -121,9 +121,9 @@ class PluginManager{
private function getDataDirectory(string $pluginPath, string $pluginName) : string{
if($this->pluginDataDirectory !== null){
return $this->pluginDataDirectory . $pluginName;
return Path::join($this->pluginDataDirectory, $pluginName);
}
return dirname($pluginPath) . DIRECTORY_SEPARATOR . $pluginName;
return Path::join(dirname($pluginPath), $pluginName);
}
/**

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\resourcepacks;
use pocketmine\utils\Config;
use Webmozart\PathUtil\Path;
use function array_keys;
use function copy;
use function count;
@ -63,11 +64,12 @@ class ResourcePackManager{
throw new \InvalidArgumentException("Resource packs path $path exists and is not a directory");
}
if(!file_exists($this->path . "resource_packs.yml")){
copy(\pocketmine\RESOURCE_PATH . "resource_packs.yml", $this->path . "resource_packs.yml");
$resourcePacksYml = Path::join($this->path, "resource_packs.yml");
if(!file_exists($resourcePacksYml)){
copy(Path::join(\pocketmine\RESOURCE_PATH, "resource_packs.yml"), $resourcePacksYml);
}
$resourcePacksConfig = new Config($this->path . "resource_packs.yml", Config::YAML, []);
$resourcePacksConfig = new Config($resourcePacksYml, Config::YAML, []);
$this->serverForceResources = (bool) $resourcePacksConfig->get("force_resources", false);
@ -84,7 +86,7 @@ class ResourcePackManager{
continue;
}
try{
$packPath = $this->path . DIRECTORY_SEPARATOR . $pack;
$packPath = Path::join($this->path, $pack);
if(!file_exists($packPath)){
throw new ResourcePackException("File or directory not found");
}
@ -120,7 +122,7 @@ class ResourcePackManager{
* Returns the directory which resource packs are loaded from.
*/
public function getPath() : string{
return $this->path;
return $this->path . DIRECTORY_SEPARATOR;
}
/**

View File

@ -24,7 +24,7 @@ declare(strict_types=1);
namespace pocketmine\scheduler;
use pocketmine\MemoryManager;
use const DIRECTORY_SEPARATOR;
use Webmozart\PathUtil\Path;
/**
* Task used to dump memory from AsyncWorkers
@ -46,7 +46,7 @@ class DumpWorkerMemoryTask extends AsyncTask{
public function onRun() : void{
MemoryManager::dumpMemory(
$this->worker,
$this->outputFolder . DIRECTORY_SEPARATOR . "AsyncWorker#" . $this->worker->getAsyncWorkerId(),
Path::join($this->outputFolder, "AsyncWorker#" . $this->worker->getAsyncWorkerId()),
$this->maxNesting,
$this->maxStringSize,
new \PrefixedLogger($this->worker->getLogger(), "Memory Dump")

View File

@ -23,11 +23,10 @@ declare(strict_types=1);
namespace pocketmine\utils;
use Webmozart\PathUtil\Path;
use function array_change_key_case;
use function array_keys;
use function array_pop;
use function array_shift;
use function basename;
use function count;
use function date;
use function explode;
@ -152,8 +151,7 @@ class Config{
$this->type = $type;
if($this->type === Config::DETECT){
$extension = explode(".", basename($this->file));
$extension = strtolower(trim(array_pop($extension)));
$extension = strtolower(Path::getExtension($this->file));
if(isset(Config::$formats[$extension])){
$this->type = Config::$formats[$extension];
}else{

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\utils;
use Webmozart\PathUtil\Path;
use function copy;
use function dirname;
use function fclose;
@ -79,10 +80,11 @@ final class Filesystem{
if($objects === false) throw new AssumptionFailedError("scandir() shouldn't return false when is_dir() returns true");
foreach($objects as $object){
if($object !== "." and $object !== ".."){
if(is_dir($dir . "/" . $object)){
self::recursiveUnlink($dir . "/" . $object);
$fullObject = Path::join($dir, $object);
if(is_dir($fullObject)){
self::recursiveUnlink($fullObject);
}else{
unlink($dir . "/" . $object);
unlink($fullObject);
}
}
}
@ -128,7 +130,7 @@ final class Filesystem{
if($object === "." || $object === ".."){
continue;
}
self::recursiveCopyInternal($origin . "/" . $object, $destination . "/" . $object);
self::recursiveCopyInternal(Path::join($origin, $object), Path::join($destination, $object));
}
}else{
$dirName = dirname($destination);

View File

@ -35,6 +35,7 @@ use pocketmine\utils\Config;
use pocketmine\utils\Internet;
use pocketmine\utils\InternetException;
use pocketmine\VersionInfo;
use Webmozart\PathUtil\Path;
use function fgets;
use function sleep;
use function strtolower;
@ -88,7 +89,7 @@ class SetupWizard{
}
//this has to happen here to prevent user avoiding agreeing to license
$config = new Config($this->dataPath . "/server.properties", Config::PROPERTIES);
$config = new Config(Path::join($this->dataPath, "server.properties"), Config::PROPERTIES);
$config->set("language", $lang);
$config->save();
@ -138,7 +139,7 @@ LICENSE;
}
private function generateBaseConfig() : void{
$config = new Config($this->dataPath . "/server.properties", Config::PROPERTIES);
$config = new Config(Path::join($this->dataPath, "server.properties"), Config::PROPERTIES);
$config->set("motd", ($name = $this->getInput($this->lang->get("name_your_server"), self::DEFAULT_NAME)));
$config->set("server-name", $name);
@ -175,14 +176,14 @@ LICENSE;
if($op === ""){
$this->error($this->lang->get("op_warning"));
}else{
$ops = new Config($this->dataPath . "/ops.txt", Config::ENUM);
$ops = new Config(Path::join($this->dataPath, "ops.txt"), Config::ENUM);
$ops->set($op, true);
$ops->save();
}
$this->message($this->lang->get("whitelist_info"));
$config = new Config($this->dataPath . "/server.properties", Config::PROPERTIES);
$config = new Config(Path::join($this->dataPath, "server.properties"), Config::PROPERTIES);
if(strtolower($this->getInput($this->lang->get("whitelist_enable"), "n", "y/N")) === "y"){
$this->error($this->lang->get("whitelist_warning"));
$config->set("white-list", true);
@ -193,7 +194,7 @@ LICENSE;
}
private function networkFunctions() : void{
$config = new Config($this->dataPath . "/server.properties", Config::PROPERTIES);
$config = new Config(Path::join($this->dataPath, "server.properties"), Config::PROPERTIES);
$this->error($this->lang->get("query_warning1"));
$this->error($this->lang->get("query_warning2"));
if(strtolower($this->getInput($this->lang->get("query_disable"), "n", "y/N")) === "y"){

View File

@ -37,6 +37,7 @@ use pocketmine\world\format\io\WorldProvider;
use pocketmine\world\format\io\WorldProviderManager;
use pocketmine\world\format\io\WritableWorldProvider;
use pocketmine\world\generator\GeneratorManager;
use Webmozart\PathUtil\Path;
use function array_keys;
use function array_shift;
use function assert;
@ -49,7 +50,6 @@ use function microtime;
use function round;
use function sprintf;
use function trim;
use const DIRECTORY_SEPARATOR;
class WorldManager{
/** @var string */
@ -228,7 +228,7 @@ class WorldManager{
}
$this->server->getLogger()->notice("Upgrading world \"$name\" to new format. This may take a while.");
$converter = new FormatConverter($provider, $this->providerManager->getDefault(), $this->server->getDataPath() . "backups" . DIRECTORY_SEPARATOR . "worlds", $this->server->getLogger());
$converter = new FormatConverter($provider, $this->providerManager->getDefault(), Path::join($this->server->getDataPath(), "backups", "worlds"), $this->server->getLogger());
$provider = $converter->execute();
$this->server->getLogger()->notice("Upgraded world \"$name\" to new format successfully. Backed up pre-conversion world at " . $converter->getBackupPath());
@ -300,7 +300,7 @@ class WorldManager{
}
private function getWorldPath(string $name) : string{
return $this->dataPath . "/" . $name . "/";
return Path::join($this->dataPath, $name) . "/"; //TODO: check if we still need the trailing dirsep (I'm a little scared to remove it)
}
public function isWorldGenerated(string $name) : bool{

View File

@ -27,6 +27,7 @@ use pocketmine\utils\Filesystem;
use pocketmine\utils\Utils;
use pocketmine\world\generator\GeneratorManager;
use pocketmine\world\WorldCreationOptions;
use Webmozart\PathUtil\Path;
use function basename;
use function crc32;
use function file_exists;
@ -71,7 +72,7 @@ class FormatConverter{
}
$nextSuffix = "";
do{
$this->backupPath = $backupPath . DIRECTORY_SEPARATOR . basename($this->oldProvider->getPath()) . $nextSuffix;
$this->backupPath = Path::join($backupPath, basename($this->oldProvider->getPath()) . $nextSuffix);
$nextSuffix = "_" . crc32(random_bytes(4));
}while(file_exists($this->backupPath));
}

View File

@ -47,6 +47,7 @@ use pocketmine\world\format\io\WritableWorldProvider;
use pocketmine\world\format\PalettedBlockArray;
use pocketmine\world\format\SubChunk;
use pocketmine\world\WorldCreationOptions;
use Webmozart\PathUtil\Path;
use function array_map;
use function array_values;
use function chr;
@ -62,7 +63,6 @@ use function strlen;
use function substr;
use function trim;
use function unpack;
use const DIRECTORY_SEPARATOR;
use const LEVELDB_ZLIB_RAW_COMPRESSION;
class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
@ -110,7 +110,7 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
* @throws \LevelDBException
*/
private static function createDB(string $path) : \LevelDB{
return new \LevelDB($path . "/db", [
return new \LevelDB(Path::join($path, "db"), [
"compression" => LEVELDB_ZLIB_RAW_COMPRESSION,
"block_size" => 64 * 1024 //64KB, big enough for most chunks
]);
@ -129,7 +129,7 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
}
protected function loadLevelData() : WorldData{
return new BedrockWorldData($this->getPath() . DIRECTORY_SEPARATOR . "level.dat");
return new BedrockWorldData(Path::join($this->getPath(), "level.dat"));
}
public function getWorldMinY() : int{
@ -141,14 +141,15 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
}
public static function isValid(string $path) : bool{
return file_exists($path . "/level.dat") and is_dir($path . "/db/");
return file_exists(Path::join($path, "level.dat")) and is_dir(Path::join($path, "db"));
}
public static function generate(string $path, string $name, WorldCreationOptions $options) : void{
self::checkForLevelDBExtension();
if(!file_exists($path . "/db")){
mkdir($path . "/db", 0777, true);
$dbPath = Path::join($path, "db");
if(!file_exists($dbPath)){
mkdir($dbPath, 0777, true);
}
BedrockWorldData::generate($path, $name, $options);

View File

@ -32,6 +32,7 @@ use pocketmine\world\format\io\BaseWorldProvider;
use pocketmine\world\format\io\data\JavaWorldData;
use pocketmine\world\format\io\exception\CorruptedChunkException;
use pocketmine\world\format\io\WorldData;
use Webmozart\PathUtil\Path;
use function assert;
use function file_exists;
use function is_dir;
@ -43,7 +44,6 @@ use function strlen;
use function strrpos;
use function substr;
use function time;
use const DIRECTORY_SEPARATOR;
use const SCANDIR_SORT_NONE;
abstract class RegionWorldProvider extends BaseWorldProvider{
@ -59,8 +59,8 @@ abstract class RegionWorldProvider extends BaseWorldProvider{
abstract protected static function getPcWorldFormatVersion() : int;
public static function isValid(string $path) : bool{
if(file_exists($path . "/level.dat") and is_dir($path . "/region/")){
foreach(scandir($path . "/region/", SCANDIR_SORT_NONE) as $file){
if(file_exists(Path::join($path, "level.dat")) and is_dir($regionPath = Path::join($path, "region"))){
foreach(scandir($regionPath, SCANDIR_SORT_NONE) as $file){
$extPos = strrpos($file, ".");
if($extPos !== false && substr($file, $extPos + 1) === static::getRegionFileExtension()){
//we don't care if other region types exist, we only care if this format is possible
@ -76,7 +76,7 @@ abstract class RegionWorldProvider extends BaseWorldProvider{
protected $regions = [];
protected function loadLevelData() : WorldData{
return new JavaWorldData($this->getPath() . DIRECTORY_SEPARATOR . "level.dat");
return new JavaWorldData(Path::join($this->getPath(), "level.dat"));
}
public function doGarbageCollection() : void{
@ -106,7 +106,7 @@ abstract class RegionWorldProvider extends BaseWorldProvider{
* Returns the path to a specific region file based on its X/Z coordinates
*/
protected function pathToRegion(int $regionX, int $regionZ) : string{
return $this->path . "/region/r.$regionX.$regionZ." . static::getRegionFileExtension();
return Path::join($this->path, "region", "r.$regionX.$regionZ." . static::getRegionFileExtension());
}
protected function loadRegion(int $regionX, int $regionZ) : RegionLoader{
@ -205,7 +205,7 @@ abstract class RegionWorldProvider extends BaseWorldProvider{
private function createRegionIterator() : \RegexIterator{
return new \RegexIterator(
new \FilesystemIterator(
$this->path . '/region/',
Path::join($this->path, 'region'),
\FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::UNIX_PATHS
),
'/\/r\.(-?\d+)\.(-?\d+)\.' . static::getRegionFileExtension() . '$/',

View File

@ -27,6 +27,7 @@ use pocketmine\world\format\Chunk;
use pocketmine\world\format\io\data\JavaWorldData;
use pocketmine\world\format\io\WritableWorldProvider;
use pocketmine\world\WorldCreationOptions;
use Webmozart\PathUtil\Path;
use function file_exists;
use function mkdir;
@ -42,8 +43,9 @@ abstract class WritableRegionWorldProvider extends RegionWorldProvider implement
mkdir($path, 0777, true);
}
if(!file_exists($path . "/region")){
mkdir($path . "/region", 0777);
$regionPath = Path::join($path, "region");
if(!file_exists($regionPath)){
mkdir($regionPath, 0777);
}
JavaWorldData::generate($path, $name, $options, static::getPcWorldFormatVersion());

View File

@ -25,6 +25,7 @@ namespace pocketmine\world\format\io\region;
use PHPUnit\Framework\TestCase;
use pocketmine\world\format\ChunkException;
use Webmozart\PathUtil\Path;
use function bin2hex;
use function clearstatcache;
use function file_exists;
@ -32,7 +33,6 @@ use function random_bytes;
use function str_repeat;
use function sys_get_temp_dir;
use function unlink;
use const DIRECTORY_SEPARATOR;
class RegionLoaderTest extends TestCase{
@ -42,7 +42,7 @@ class RegionLoaderTest extends TestCase{
private $region;
public function setUp() : void{
$this->regionPath = sys_get_temp_dir() . '/test.testregion';
$this->regionPath = Path::join(sys_get_temp_dir(), 'test.testregion');
if(file_exists($this->regionPath)){
unlink($this->regionPath);
}
@ -140,7 +140,7 @@ class RegionLoaderTest extends TestCase{
clearstatcache();
do{
$randfile = sys_get_temp_dir() . DIRECTORY_SEPARATOR . bin2hex(random_bytes(6)) . ".mca";
$randfile = Path::join(sys_get_temp_dir(), bin2hex(random_bytes(6)) . ".mca");
}while(file_exists($randfile));
$this->expectException(\RuntimeException::class);
RegionLoader::loadExisting($randfile);