Compare commits

..

7 Commits

13 changed files with 472 additions and 193 deletions

View File

@@ -3,8 +3,10 @@
namespace ManiaControl\Admin;
use FML\Controls\Frame;
use FML\Controls\Label;
use FML\Controls\Labels\Label_Button;
use FML\Controls\Labels\Label_Text;
use FML\Controls\Quad;
use FML\Controls\Quads\Quad_BgRaceScore2;
use FML\Controls\Quads\Quad_BgsPlayerCard;
use FML\Controls\Quads\Quad_UIConstruction_Buttons;
@@ -20,6 +22,7 @@ use ManiaControl\Manialinks\LabelLine;
use ManiaControl\Manialinks\ManialinkManager;
use ManiaControl\Manialinks\ManialinkPageAnswerListener;
use ManiaControl\Players\Player;
use ManiaControl\Utils\Formatter;
/**
* Widget Class listing Authorized Players
@@ -118,11 +121,14 @@ class AdminLists implements ManialinkPageAnswerListener, CallbackListener, Usage
$frame->addChild($headFrame);
$headFrame->setY($posY - 5);
$mainFieldWidth = (($width - 45) / 3) - 2;
$labelLine = new LabelLine($headFrame);
$labelLine->addLabelEntryText('Id', $posX + 5);
$labelLine->addLabelEntryText('Nickname', $posX + 18);
$labelLine->addLabelEntryText('Login', $posX + 70);
$labelLine->addLabelEntryText('Actions', $posX + 120);
$labelLine->addLabelEntryText('Login', $posX + 18 + $mainFieldWidth + 2);
$labelLine->addLabelEntryText('Location', $posX + 18 + ($mainFieldWidth + 2) * 2);
$labelLine->addLabelEntryText('Actions', $posX + $width - 18);
$labelLine->render();
$index = 1;
@@ -151,10 +157,13 @@ class AdminLists implements ManialinkPageAnswerListener, CallbackListener, Usage
$lineQuad->setZ(-0.1);
}
$path = $admin->getProvince();
$labelLine = new LabelLine($playerFrame);
$labelLine->addLabelEntryText($index, $posX + 5, 13);
$labelLine->addLabelEntryText($admin->nickname, $posX + 18, 52);
$labelLine->addLabelEntryText($admin->login, $posX + 70, 48);
$labelLine->addLabelEntryText($admin->nickname, $posX + 18, $mainFieldWidth - 10);
$labelLine->addLabelEntryText($admin->login, $posX + 18 + $mainFieldWidth + 2, $mainFieldWidth - 6);
$labelLine->addLabelEntryText($path, $posX + 18 + ($mainFieldWidth + 2) * 2 + 5, $mainFieldWidth - 2, '', true);
$labelLine->render();
// Level Quad
@@ -174,6 +183,52 @@ class AdminLists implements ManialinkPageAnswerListener, CallbackListener, Usage
$description = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($admin) . " " . $admin->nickname;
$rightLabel->addTooltipLabelFeature($descriptionLabel, $description);
// Copy admin name
$quad = new Quad();
$playerFrame->addChild($quad);
$quad->setX($posX + 18 + $mainFieldWidth - 3);
$quad->setSize(3., 3.);
$quad->setStyle('UICommon64_1');
$quad->setSubStyle('Copy_light');
$quad->addClipboardFeature($admin->nickname);
$description = 'Copy player name';
$quad->addTooltipLabelFeature($descriptionLabel, $description);
// Trackmania.io button
$label = new Label();
$playerFrame->addChild($label);
$label->setX($posX + 18 + ($mainFieldWidth + 2) * 2 - 3);
$label->setSize(3., 3.);
$label->setText('$28d');
$label->setTextSize(.8);
$label->setAreaColor('00000000');
$label->setUrl('https://trackmania.io/#/player/'. $admin->login);
$description = 'Open player profile on Trackmania.io';
$label->addTooltipLabelFeature($descriptionLabel, $description);
// Copy admin login
$quad = new Quad();
$playerFrame->addChild($quad);
$quad->setX($posX + 18 + ($mainFieldWidth + 2) * 2 - 6);
$quad->setSize(3., 3.);
$quad->setStyle('UICommon64_1');
$quad->setSubStyle('Copy_light');
$quad->addClipboardFeature($admin->login);
$description = 'Copy player login';
$quad->addTooltipLabelFeature($descriptionLabel, $description);
$countryCode = Formatter::mapCountry($admin->getCountry());
if ($countryCode !== 'OTH') {
// Nation Quad
$countryQuad = new Quad();
$playerFrame->addChild($countryQuad);
$countryQuad->setImageUrl("file://ZoneFlags/Login/{$admin->login}/country");
$countryQuad->setX($posX + 18 + ($mainFieldWidth + 2) * 2 + 2);
$countryQuad->setSize(4, 4);
$countryQuad->addTooltipLabelFeature($descriptionLabel, '$<' . $admin->nickname . '$> from ' . $admin->path);
}
//Revoke Button
if ($admin->authLevel > 0
&& $this->maniaControl->getAuthenticationManager()->checkRight($player, $admin->authLevel + 1)
@@ -188,7 +243,7 @@ class AdminLists implements ManialinkPageAnswerListener, CallbackListener, Usage
$quad = new Quad_BgsPlayerCard();
$playerFrame->addChild($quad);
$quad->setZ(11);
$quad->setX($posX + 130);
$quad->setX($posX + $width - 12.5);
$quad->setSubStyle($quad::SUBSTYLE_BgPlayerCardBig);
$quad->setSize($quadWidth, $quadHeight);
$quad->setAction(self::ACTION_REVOKE_RIGHTS . "." . $admin->login);
@@ -196,7 +251,7 @@ class AdminLists implements ManialinkPageAnswerListener, CallbackListener, Usage
//Label
$label = new Label_Button();
$playerFrame->addChild($label);
$label->setX($posX + 130);
$label->setX($posX + $width - 12.5);
$quad->setZ(12);
$label->setStyle($style);
$label->setTextSize(1);

View File

@@ -3,6 +3,7 @@
namespace ManiaControl\Commands;
use FML\Controls\Frame;
use FML\Controls\Quad;
use FML\Controls\Quads\Quad_BgsPlayerCard;
use FML\Controls\Quads\Quad_UIConstruction_Buttons;
use FML\ManiaLink;
@@ -232,7 +233,7 @@ class HelpManager implements CommandListener, CallbackListener, ManialinkPageAns
$labelLine = new LabelLine($headFrame);
$labelLine->addLabelEntryText('Command', $posX + 5);
$labelLine->addLabelEntryText('Description', $posX + 50);
$labelLine->addLabelEntryText('Description', $posX + 5 + $width / 3 + 5);
$labelLine->render();
$index = 1;
@@ -261,10 +262,27 @@ class HelpManager implements CommandListener, CallbackListener, ManialinkPageAns
}
$labelLine = new LabelLine($playerFrame);
$labelLine->addLabelEntryText($command['Name'], $posX + 5, 45);
$labelLine->addLabelEntryText($command['Description'], $posX + 50, $width / 2 - $posX + 50);
$labelLine->addLabelEntryText($command['Name'], $posX + 5, $width / 3 - 5);
$labelLine->addLabelEntryText($command['Description'], $posX + 5 + $width / 3 + 5, $width / 3 * 2 - 15);
$labelLine->render();
$clipboardValue = '/';
if ($command['IsAdminCommand']) {
$clipboardValue .= '/';
}
$clipboardValue .= explode('|', $command['Name'])[0] . ' ';
// Copy command
$playerQuad = new Quad();
$playerFrame->addChild($playerQuad);
$playerQuad->setX($posX + 5 + $width / 3);
$playerQuad->setSize(3., 3.);
$playerQuad->setStyle('UICommon64_1');
$playerQuad->setSubStyle('Copy_light');
$playerQuad->addClipboardFeature($clipboardValue);
$description = 'Copy Command';
$playerQuad->addTooltipLabelFeature($descriptionLabel, $description);
$posY -= 4;
$index++;
}
@@ -284,9 +302,9 @@ class HelpManager implements CommandListener, CallbackListener, ManialinkPageAns
public function registerCommand($name, $adminCommand = false, $description = '', $method = '') {
// TODO replace with new class Command
if ($adminCommand) {
array_push($this->adminCommands, array("Name" => $name, "Description" => $description, "Method" => $method));
array_push($this->adminCommands, array("Name" => $name, "Description" => $description, "Method" => $method, "IsAdminCommand" => true));
} else {
array_push($this->playerCommands, array("Name" => $name, "Description" => $description, "Method" => $method));
array_push($this->playerCommands, array("Name" => $name, "Description" => $description, "Method" => $method, "IsAdminCommand" => false));
}
}
}

View File

@@ -2,6 +2,8 @@
namespace ManiaControl\Database;
use ManiaControl\Callbacks\CallbackListener;
use ManiaControl\Callbacks\Callbacks;
use ManiaControl\Callbacks\TimerListener;
use ManiaControl\Logger;
use ManiaControl\ManiaControl;
@@ -13,7 +15,7 @@ use ManiaControl\ManiaControl;
* @copyright 2014-2020 ManiaControl Team
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
*/
class Database implements TimerListener {
class Database implements CallbackListener, TimerListener {
/*
* Public properties
*/
@@ -56,12 +58,14 @@ class Database implements TimerListener {
return;
}
$this->getMysqli()->set_charset("utf8");
$this->reduceLockWaitTimeout();
$this->initDatabase();
// $this->optimizeTables();
// Register Method which checks the Database Connection every 5 seconds
$this->maniaControl->getTimerManager()->registerTimerListening($this, 'checkConnection', 5000);
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::AFTERINIT, $this, 'handleAfterInit');
// Children
$this->migrationHelper = new MigrationHelper($maniaControl);
@@ -201,6 +205,24 @@ class Database implements TimerListener {
return true;
}
/**
* Reduce session lock wait timeout value to between 5 and 10 seconds
* designed to be used during the initialization to prevent maniacontrol to be stuck when launched in parallel with other instances
*/
public function reduceLockWaitTimeout() {
// limit session lock during initialization
$this->getMysqli()->query("SET SESSION lock_wait_timeout = ". rand(5, 10) .";");
}
/**
* Reset session lock wait timeout value to the default one
* designed to be used during the initialization to prevent maniacontrol to be stuck when launched in parallel with other instances
*/
public function resetLockWaitTimeout() {
// limit session lock during initialization
$this->getMysqli()->query("SET SESSION lock_wait_timeout = @@GLOBAL.lock_wait_timeout;");
}
/**
* Return the database config
*
@@ -228,6 +250,10 @@ class Database implements TimerListener {
}
}
public function handleAfterInit() {
$this->resetLockWaitTimeout();
}
/**
* Destruct Database Connection
*/

View File

@@ -36,6 +36,7 @@ class AsyncHttpRequest implements UsageInformationAble {
private $contentType = 'text/xml; charset=UTF-8;';
private $timeout = 60;
private $headers = array();
private $handle = null;
public function __construct($maniaControl, $url) {
$this->maniaControl = $maniaControl;
@@ -57,8 +58,7 @@ class AsyncHttpRequest implements UsageInformationAble {
->set(CURLOPT_USERAGENT, 'ManiaControl v' . ManiaControl::VERSION)// user-agent
->set(CURLOPT_RETURNTRANSFER, true)//
->set(CURLOPT_FOLLOWLOCATION, true)// support redirect
->set(CURLOPT_SSL_VERIFYPEER, false)
->set(CURLOPT_HEADER, true);
->set(CURLOPT_SSL_VERIFYPEER, false);
return $request;
}
@@ -76,9 +76,15 @@ class AsyncHttpRequest implements UsageInformationAble {
array_push($this->headers, 'Accept-Charset: utf-8');
$request = $this->newRequest($this->url, $this->timeout);
$request->getOptions()->set(CURLOPT_AUTOREFERER, true)// accept link reference
$request->getOptions()
->set(CURLOPT_AUTOREFERER, true)// accept link reference
->set(CURLOPT_HTTPHEADER, $this->headers); // headers
if ($this->handle !== null) {
$request->getOptions()
->set(CURLOPT_FILE, $this->handle);
}
$this->processRequest($request);
}
@@ -287,4 +293,22 @@ class AsyncHttpRequest implements UsageInformationAble {
public function setTimeout($timeout) {
$this->timeout = $timeout;
}
/**
* Gets the File Resource handle
*
* @return int
*/
public function getHandle() {
return $this->handle;
}
/**
* Sets the File Resource handle
*
* @param int $handle
*/
public function setHandle($handle) {
$this->handle = $handle;
}
}

View File

@@ -630,9 +630,18 @@ class DirectoryBrowser implements ManialinkPageAnswerListener {
$folderPath = $player->getCache($this, self::CACHE_FOLDER_PATH);
if (filter_var($url, FILTER_VALIDATE_URL)) {
try {
$tempFile = tempnam(sys_get_temp_dir(), 'map_');
$fp = fopen($tempFile, 'w+');
$this->maniaControl->getChat()->sendSuccess('Starting download...', $player);
$asyncHttpRequest = new AsyncHttpRequest($this->maniaControl, $url);
$asyncHttpRequest->setCallable(function ($file, $error, $headers) use ($url, $folderPath, $player) {
if (!$file || $error) {
$asyncHttpRequest->setHandle($fp);
$asyncHttpRequest->setCallable(function ($file, $error, $headers) use ($url, $folderPath, $tempFile, $fp, $player) {
// closing file handle
fclose($fp);
if ($error) {
$message = "Impossible to download the file: " . $error;
$this->maniaControl->getChat()->sendError($message, $player);
Logger::logError(AuthenticationManager::getAuthLevelName($player->authLevel) .' "'. $player->nickname . '" ('. $player->login .') encountered an error during the download of the zip file "'. $url .'": '. $error);
@@ -641,12 +650,9 @@ class DirectoryBrowser implements ManialinkPageAnswerListener {
$filePath = "";
$finfo = new finfo(FILEINFO_MIME_TYPE);
if ($finfo->buffer($file) === "application/zip") {
$zip = new ZipArchive();
// Create a temporary file
$tempFile = tempnam(sys_get_temp_dir(), 'zip');
file_put_contents($tempFile, $file);
if ($finfo->file($tempFile) === "application/zip") {
$zip = new ZipArchive();
$open = $zip->open($tempFile);
@@ -720,6 +726,10 @@ class DirectoryBrowser implements ManialinkPageAnswerListener {
$message = "File is not a map: " . $fileName;
$this->maniaControl->getChat()->sendError($message, $player);
Logger::logError(AuthenticationManager::getAuthLevelName($player->authLevel) .' "'. $player->nickname . '" ('. $player->login .') encountered an error when downloadeding the map file "'. $fileName .'": File is not a map');
// Clean up the temporary file
unlink($tempFile);
return;
}
} else {
@@ -742,11 +752,16 @@ class DirectoryBrowser implements ManialinkPageAnswerListener {
}
$filePath = substr($filePath, 0, -8) . "-" . $index . ".Map.Gbx";
}
$bytes = file_put_contents($filePath, $file);
if (!$bytes || $bytes <= 0) {
$renamed = rename($tempFile, $filePath);
if (!$renamed) {
$message = "Failed to write file " . $filePath;
$this->maniaControl->getChat()->sendError($message, $player);
Logger::logError(AuthenticationManager::getAuthLevelName($player->authLevel) .' "'. $player->nickname . '" ('. $player->login .') encountered an error when downloadeding the map file "'. $fileName .'": Failed to write the file');
// Clean up the temporary file
unlink($tempFile);
return;
}
@@ -760,6 +775,10 @@ class DirectoryBrowser implements ManialinkPageAnswerListener {
});
$asyncHttpRequest->getData();
} catch (\Throwable $th) {
Logger::logError('Error when downloading file: '. $th->getMessage());
$this->maniaControl->getChat()->sendError('Error when downloading file: '. $th->getMessage(), $player);
}
}
}
}

View File

@@ -210,12 +210,15 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
$headFrame->setY($height / 2 - 5);
$posX = -$width / 2;
$mainFieldTotalWidth = $width - 45;
$labelLine = new LabelLine($headFrame);
$labelLine->addLabelEntryText('Id', $posX + 5);
$labelLine->addLabelEntryText('Mx Id', $posX + 10);
$labelLine->addLabelEntryText('Map Name', $posX + 20);
$labelLine->addLabelEntryText('Author', $width / 2 - 56);
$labelLine->addLabelEntryText('Actions', $width / 2 - 16);
$labelLine->addLabelEntryText('Map Uid', $posX + 20 + $mainFieldTotalWidth * 0.4);
$labelLine->addLabelEntryText('Author', $posX + 20 + $mainFieldTotalWidth * 0.4 + $mainFieldTotalWidth * 0.35);
$labelLine->addLabelEntryText('Actions', $posX + $width - 16);
$labelLine->setY(-7);
$labelLine->render();
@@ -285,7 +288,7 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
$mxQuad->setSize(3, 3);
$mxQuad->setImageUrl($mxIcon);
$mxQuad->setImageFocusUrl($mxIconHover);
$mxQuad->setX($width / 2 - 63);
$mxQuad->setX($posX + $width - 16);
$mxQuad->setUrl($map->mx->pageurl);
$mxQuad->setZ(0.01);
$description = 'View ' . $map->getEscapedName() . ' on Mania-Exchange';
@@ -297,7 +300,7 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
$mxQuad->setSize(3, 3);
$mxQuad->setImageUrl($mxIconGreen);
$mxQuad->setImageFocusUrl($mxIconGreenHover);
$mxQuad->setX($width / 2 - 60);
$mxQuad->setX($posX + $width - 19);
$mxQuad->setUrl($map->mx->pageurl);
$mxQuad->setZ(0.01);
$description = 'Update for ' . $map->getEscapedName() . ' available on Mania-Exchange!';
@@ -310,17 +313,31 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
}
}
// Display Karma bar
$karmaGauge = $this->maniaControl->getManialinkManager()->getElementBuilder()->buildKarmaGauge(
$map,
17,
10
);
$karmaGaugeWidth = 0.;
if ($karmaGauge) {
$mapFrame->addChild($karmaGauge);
$karmaGauge->setX($posX + $width - 25);
$karmaGaugeWidth = 12.;
}
// Display Maps
$labelLine = new LabelLine($mapFrame);
$labelLine->addLabelEntryText($mapListId, $posX + 5, 5);
$labelLine->addLabelEntryText($mxId, $posX + 10, 10);
$labelLine->addLabelEntryText(Formatter::stripDirtyCodes($map->name), $posX + 20, $width - 20 - 56 - 5);
$labelLine->addLabelEntryText($mapListId, $posX + 5, 4);
$labelLine->addLabelEntryText($mxId, $posX + 10, 9);
$labelLine->addLabelEntryText(Formatter::stripDirtyCodes($map->name), $posX + 20, $mainFieldTotalWidth * 0.4 - 5);
$labelLine->addLabelEntryText($map->uid, $posX + 20 + $mainFieldTotalWidth * 0.4, $mainFieldTotalWidth * 0.35 - 8);
$label = new Label_Text();
$mapFrame->addChild($label);
$label->setText($map->authorNick);
$label->setX($width / 2 - 56);
$label->setSize(47, 0);
$label->setX($posX + 20 + $mainFieldTotalWidth * 0.4 + $mainFieldTotalWidth * 0.35);
$label->setSize($mainFieldTotalWidth * 0.25 - $karmaGaugeWidth, 0);
$label->setAction(MapCommands::ACTION_SHOW_AUTHOR . $map->authorLogin);
$description = 'Click to checkout all maps by $<' . $map->authorLogin . '$>!';
$label->addTooltipLabelFeature($descriptionLabel, $description);
@@ -328,13 +345,47 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
$labelLine->render();
// Copy Map Uid
$label = new Label();
$mapFrame->addChild($label);
$label->setX($posX + 20 + $mainFieldTotalWidth * 0.4 + $mainFieldTotalWidth * 0.35 - 3);
$label->setSize(3., 3.);
$label->setText('$28d');
$label->setTextSize(.8);
$label->setAreaColor('00000000');
$label->setUrl('https://trackmania.io/#/leaderboard/'. $map->uid);
$description = 'Open map leaderboard on Trackmania.io';
$label->addTooltipLabelFeature($descriptionLabel, $description);
// Copy Map Uid
$quad = new Quad();
$mapFrame->addChild($quad);
$quad->setX($posX + 20 + $mainFieldTotalWidth * 0.4 + $mainFieldTotalWidth * 0.35 - 6);
$quad->setSize(3., 3.);
$quad->setStyle('UICommon64_1');
$quad->setSubStyle('Copy_light');
$quad->addClipboardFeature($map->uid);
$description = 'Copy Map Uid';
$quad->addTooltipLabelFeature($descriptionLabel, $description);
// Copy Author Login
$quad = new Quad();
$mapFrame->addChild($quad);
$quad->setX($posX + $width - 23 - $karmaGaugeWidth);
$quad->setSize(3., 3.);
$quad->setStyle('UICommon64_1');
$quad->setSubStyle('Copy_light');
$quad->addClipboardFeature($map->authorLogin);
$description = 'Copy Author login';
$quad->addTooltipLabelFeature($descriptionLabel, $description);
// TODO action detailed map info including mx info
// Map-Queue-Map-Label
if (isset($queuedMaps[$map->uid])) {
$label = new Label_Text();
$mapFrame->addChild($label);
$label->setX($width / 2 - 13);
$label->setX($posX + $width - 13);
$label->setZ(0.2);
$label->setTextSize(1.5);
$label->setText($queuedMaps[$map->uid]);
@@ -378,7 +429,7 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
// remove map button
$removeButton = new Label_Button();
$mapFrame->addChild($removeButton);
$removeButton->setX($width / 2 - 5);
$removeButton->setX($posX + $width - 5);
$removeButton->setZ(0.2);
$removeButton->setSize(3, 3);
$removeButton->setTextSize(1);
@@ -395,7 +446,7 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
// Switch to button
$switchLabel = new Label_Button();
$mapFrame->addChild($switchLabel);
$switchLabel->setX($width / 2 - 9);
$switchLabel->setX($posX + $width - 9);
$switchLabel->setZ(0.2);
$switchLabel->setSize(3, 3);
$switchLabel->setTextSize(2);
@@ -413,7 +464,7 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
// Switch Map Voting for Admins
$switchQuad = new Quad_UIConstruction_Buttons();
$mapFrame->addChild($switchQuad);
$switchQuad->setX($width / 2 - 17);
$switchQuad->setX($posX + $width - 21);
$switchQuad->setZ(0.2);
$switchQuad->setSubStyle($switchQuad::SUBSTYLE_Validate_Step2);
$switchQuad->setSize(3.8, 3.8);
@@ -424,7 +475,7 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
// Switch Map Voting for Player
$switchLabel = new Label_Button();
$mapFrame->addChild($switchLabel);
$switchLabel->setX($width / 2 - 7);
$switchLabel->setX($posX + $width - 7);
$switchLabel->setZ(0.2);
$switchLabel->setSize(3, 3);
$switchLabel->setTextSize(2);
@@ -436,17 +487,6 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
}
}
// Display Karma bar
$karmaGauge = $this->maniaControl->getManialinkManager()->getElementBuilder()->buildKarmaGauge(
$map,
20,
10
);
if ($karmaGauge) {
$mapFrame->addChild($karmaGauge);
$karmaGauge->setX($posX + 120);
}
$posY -= 4;
$mapListId++;
$index++;

View File

@@ -3,6 +3,7 @@
namespace ManiaControl\Players;
use FML\Controls\Frame;
use FML\Controls\Label;
use FML\Controls\Labels\Label_Text;
use FML\Controls\Quad;
use FML\Controls\Quads\Quad_BgRaceScore2;
@@ -189,13 +190,15 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
$frame->addChild($headFrame);
$headFrame->setY($posY - 5);
$mainFieldWidth = (($width - 30) / 3) - 2;
$labelLine = new LabelLine($headFrame);
$labelLine->addLabelEntryText('Id', $posX + 5);
$labelLine->addLabelEntryText('Nickname', $posX + 18);
$labelLine->addLabelEntryText('Login', $posX + 70);
$labelLine->addLabelEntryText('Location', $posX + 101);
$labelLine->addLabelEntryText('Login', $posX + 18 + $mainFieldWidth + 2);
$labelLine->addLabelEntryText('Location', $posX + 18 + ($mainFieldWidth + 2) * 2);
if ($this->maniaControl->getAuthenticationManager()->checkRight($player, AuthenticationManager::AUTH_LEVEL_MODERATOR)) {
$labelLine->addLabelEntryText('Actions', $posX + 135);
$labelLine->addLabelEntryText('Actions', $posX + $width - 15);
}
$labelLine->render();
@@ -220,6 +223,7 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
}
$path = $listPlayer->getProvince();
$playerFrame = new Frame();
$pageFrame->addChild($playerFrame);
@@ -233,9 +237,9 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
$labelLine = new LabelLine($playerFrame);
$labelLine->addLabelEntryText($playerIndex, $posX + 5, 13);
$labelLine->addLabelEntryText($listPlayer->nickname, $posX + 18, 43);
$labelLine->addLabelEntryText($listPlayer->login, $posX + 70, 26);
$labelLine->addLabelEntryText($path, $posX + 101, 27);
$labelLine->addLabelEntryText($listPlayer->nickname, $posX + 18, $mainFieldWidth - 10);
$labelLine->addLabelEntryText($listPlayer->login, $posX + 18 + $mainFieldWidth + 2, $mainFieldWidth - 6);
$labelLine->addLabelEntryText($path, $posX + 18 + ($mainFieldWidth + 2) * 2 + 5, $mainFieldWidth - 8);
$labelLine->render();
@@ -281,7 +285,7 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
$countryQuad = new Quad();
$playerFrame->addChild($countryQuad);
$countryQuad->setImageUrl("file://ZoneFlags/Login/{$listPlayer->login}/country");
$countryQuad->setX($posX + 98);
$countryQuad->setX($posX + 18 + ($mainFieldWidth + 2) * 2 + 2);
$countryQuad->setSize(4, 4);
$countryQuad->addTooltipLabelFeature($descriptionLabel, '$<' . $listPlayer->nickname . '$> from ' . $listPlayer->path);
@@ -305,10 +309,21 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
$description = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($listPlayer) . ' ' . $listPlayer->nickname;
$rightLabel->addTooltipLabelFeature($descriptionLabel, $description);
// Copy player name
$playerQuad = new Quad();
$playerFrame->addChild($playerQuad);
$playerQuad->setX($posX + 18 + $mainFieldWidth - 10);
$playerQuad->setSize(3., 3.);
$playerQuad->setStyle('UICommon64_1');
$playerQuad->setSubStyle('Copy_light');
$playerQuad->addClipboardFeature($listPlayer->nickname);
$description = 'Copy player name';
$playerQuad->addTooltipLabelFeature($descriptionLabel, $description);
// Player Statistics
$playerQuad = new Quad_Icons64x64_1();
$playerFrame->addChild($playerQuad);
$playerQuad->setX($posX + 61);
$playerQuad->setX($posX + 18 + $mainFieldWidth - 7);
$playerQuad->setSize(2.7, 2.7);
$playerQuad->setSubStyle($playerQuad::SUBSTYLE_TrackInfo);
$playerQuad->setAction(self::ACTION_OPEN_PLAYER_DETAILED . '.' . $listPlayer->login);
@@ -316,32 +331,57 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
$playerQuad->addTooltipLabelFeature($descriptionLabel, $description);
// Camera Quad
$playerQuad = new Quad_UIConstruction_Buttons();
$playerQuad = new Quad();
$playerFrame->addChild($playerQuad);
$playerQuad->setX($posX + 64.5);
$playerQuad->setX($posX + 18 + $mainFieldWidth - 4);
$playerQuad->setSize(3.8, 3.8);
$playerQuad->setSubStyle($playerQuad::SUBSTYLE_Camera);
$playerQuad->setStyle('UICommon64_1');
$playerQuad->setSubStyle('Camera_light');
$description = 'Spectate $<' . $listPlayer->nickname . '$>';
$playerQuad->addTooltipLabelFeature($descriptionLabel, $description);
$playerQuad->setAction(self::ACTION_SPECTATE_PLAYER . '.' . $listPlayer->login);
// Player Profile Quad
$playerQuad = new Quad_UIConstruction_Buttons();
$playerQuad = new Quad();
$playerFrame->addChild($playerQuad);
$playerQuad->setX($posX + 68);
$playerQuad->setX($posX + 18 + $mainFieldWidth - 1);
$playerQuad->setSize(3.8, 3.8);
$playerQuad->setSubStyle($playerQuad::SUBSTYLE_Author);
$playerQuad->setStyle('UICommon64_1');
$playerQuad->setSubStyle('User_light');
$playerQuad->addPlayerProfileFeature($listPlayer->login);
// Description Label
$description = 'View Player Profile of $<' . $listPlayer->nickname . '$>';
$playerQuad->addTooltipLabelFeature($descriptionLabel, $description);
// Trackmania.io button
$label = new Label();
$playerFrame->addChild($label);
$label->setX($posX + 18 + ($mainFieldWidth + 2) * 2 - 3);
$label->setSize(3., 3.);
$label->setText('$28d');
$label->setTextSize(.8);
$label->setAreaColor('00000000');
$label->setUrl('https://trackmania.io/#/player/'. $listPlayer->login);
$description = 'Open player profile on Trackmania.io';
$label->addTooltipLabelFeature($descriptionLabel, $description);
// Copy player login
$playerQuad = new Quad();
$playerFrame->addChild($playerQuad);
$playerQuad->setX($posX + 18 + ($mainFieldWidth + 2) * 2 - 6);
$playerQuad->setSize(3., 3.);
$playerQuad->setStyle('UICommon64_1');
$playerQuad->setSubStyle('Copy_light');
$playerQuad->addClipboardFeature($listPlayer->login);
$description = 'Copy player login';
$playerQuad->addTooltipLabelFeature($descriptionLabel, $description);
if ($this->maniaControl->getAuthenticationManager()->checkRight($player, AuthenticationManager::AUTH_LEVEL_MODERATOR)) {
// Further Player actions Quad
$playerQuad = new Quad_Icons64x64_1();
$playerFrame->addChild($playerQuad);
$playerQuad->setX($posX + 132);
$playerQuad->setX($posX + $width - 15);
$playerQuad->setSize(3.8, 3.8);
$playerQuad->setSubStyle($playerQuad::SUBSTYLE_Buddy);
$playerQuad->setAction(self::ACTION_PLAYER_ADV . '.' . $listPlayer->login);
@@ -356,7 +396,7 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
// Force to Red-Team Quad
$redQuad = new Quad_Emblems();
$playerFrame->addChild($redQuad);
$redQuad->setX($posX + 144);
$redQuad->setX($posX + $width - 15 + 12);
$redQuad->setSize(3.8, 3.8);
$redQuad->setSubStyle($redQuad::SUBSTYLE_2);
$redQuad->setAction(self::ACTION_FORCE_RED . '.' . $listPlayer->login);
@@ -368,7 +408,7 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
// Force to Blue-Team Quad
$blueQuad = new Quad_Emblems();
$playerFrame->addChild($blueQuad);
$blueQuad->setX($posX + 140);
$blueQuad->setX($posX + $width - 15 + 8);
$blueQuad->setSize(3.8, 3.8);
$blueQuad->setSubStyle($blueQuad::SUBSTYLE_1);
$blueQuad->setAction(self::ACTION_FORCE_BLUE . '.' . $listPlayer->login);
@@ -381,7 +421,7 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
// Kick Player Vote
$kickQuad = new Quad_UIConstruction_Buttons();
$playerFrame->addChild($kickQuad);
$kickQuad->setX($posX + 140);
$kickQuad->setX($posX + $width - 15 + 8);
$kickQuad->setSize(3.8, 3.8);
$kickQuad->setSubStyle($kickQuad::SUBSTYLE_Validate_Step2);
$kickQuad->setAction(self::ACTION_KICK_PLAYER_VOTE . '.' . $listPlayer->login);
@@ -394,7 +434,7 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
// Force to Play
$playQuad = new Quad_Emblems();
$playerFrame->addChild($playQuad);
$playQuad->setX($posX + 142);
$playQuad->setX($posX + $width - 15 + 8);
$playQuad->setSize(3.8, 3.8);
$playQuad->setSubStyle($playQuad::SUBSTYLE_2);
$playQuad->setAction(self::ACTION_FORCE_PLAY . '.' . $listPlayer->login);
@@ -408,7 +448,7 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
// Force to Spectator Quad
$spectatorQuad = new Quad_BgRaceScore2();
$playerFrame->addChild($spectatorQuad);
$spectatorQuad->setX($posX + 136);
$spectatorQuad->setX($posX + $width - 15 + 4);
$spectatorQuad->setSize(3.8, 3.8);
$spectatorQuad->setSubStyle($spectatorQuad::SUBSTYLE_Spectator);
$spectatorQuad->setAction(self::ACTION_FORCE_SPEC . '.' . $listPlayer->login);
@@ -420,7 +460,7 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
// Force to Spectator Quad
$spectatorQuad = new Quad_BgRaceScore2();
$playerFrame->addChild($spectatorQuad);
$spectatorQuad->setX($posX + 136);
$spectatorQuad->setX($posX + $width - 15 + 4);
$spectatorQuad->setSize(3.8, 3.8);
$spectatorQuad->setSubStyle($spectatorQuad::SUBSTYLE_Spectator);
$spectatorQuad->setAction(self::ACTION_FORCE_SPEC_VOTE . '.' . $listPlayer->login);

View File

@@ -380,6 +380,15 @@ class ServerOptionsMenu implements CallbackListener, ConfiguratorMenu, TimerList
}
}");
$optionsFrame->addChild($checkBox);
// Copy player name
$quad = new Quad();
$quad->setX($width - $width * 0.3 - 7);
$quad->setSize(3., 3.);
$quad->setStyle('UICommon64_1');
$quad->setSubStyle('Copy_light');
$quad->addClipboardFeature($value);
$optionsFrame->addChild($quad);
}
}

View File

@@ -47,8 +47,7 @@ abstract class WebReader {
->set(CURLOPT_USERAGENT, 'ManiaControl v' . ManiaControl::VERSION)// user-agent
->set(CURLOPT_RETURNTRANSFER, true)// return instead of output content
->set(CURLOPT_AUTOREFERER, true)// follow redirects
->set(CURLOPT_SSL_VERIFYPEER, false)
->set(CURLOPT_HEADER, true);;
->set(CURLOPT_SSL_VERIFYPEER, false);
return $request;
}

View File

@@ -71,6 +71,9 @@ class Clipboard extends ScriptFeature
}
$this->control = $control;
if ($this->control instanceof Scriptable) {
$this->control->setScriptEvents(true);
}
if ($this->value !== null) {
$this->setValue($this->value);

View File

@@ -6,7 +6,7 @@ use Symfony\Component\EventDispatcher\EventDispatcher;
class Request extends EventDispatcher implements RequestInterface
{
/**
* @var resource cURL handler
* @var \CurlHandle cURL handler
*/
protected $ch;
@@ -20,6 +20,11 @@ class Request extends EventDispatcher implements RequestInterface
*/
protected $options = null;
/**
* @var array Response Headers feed by the CURLOPT_HEADERFUNCTION callback
*/
protected $responseHeaders;
/**
* Create new cURL handle
*
@@ -30,6 +35,35 @@ class Request extends EventDispatcher implements RequestInterface
if ($url !== null) {
$this->getOptions()->set(CURLOPT_URL, $url);
}
$this->getOptions()->set(CURLOPT_HEADERFUNCTION, function($ch, $headerLine) {
$len = strlen($headerLine);
// Handle HTTP status lines (e.g., HTTP/1.1 200 OK)
if (preg_match('/^HTTP\/\d\.\d\s+\d+/', $headerLine)) {
$this->responseHeaders = []; // Reset on redirect or multiple responses
}
$parts = explode(':', $headerLine, 2);
if (count($parts) === 2) {
$key = strtolower(trim($parts[0]));
$value = trim($parts[1]);
// Handle multiple headers with same name
if (!isset($this->responseHeaders[$key])) {
$this->responseHeaders[$key] = $value;
} else {
if (is_array($this->responseHeaders[$key])) {
$this->responseHeaders[$key][] = $value;
} else {
$this->responseHeaders[$key] = [$this->responseHeaders[$key], $value];
}
}
}
return $len;
});
$this->ch = curl_init();
}
@@ -72,7 +106,7 @@ class Request extends EventDispatcher implements RequestInterface
/**
* Returns cURL raw resource
*
* @return resource cURL handle
* @return \CurlHandle cURL handle
*/
public function getHandle()
{
@@ -90,6 +124,16 @@ class Request extends EventDispatcher implements RequestInterface
return (int)$this->ch;
}
/**
* Get the response headers
*
* @return array
*/
public function getResponseHeaders()
{
return $this->responseHeaders;
}
/**
* Perform a cURL session.
* Equivalent to curl_exec().
@@ -108,6 +152,7 @@ class Request extends EventDispatcher implements RequestInterface
$content = curl_exec($this->ch);
$response = new Response($this, $content);
$response->setHeaders($this->responseHeaders);
$errorCode = curl_errno($this->ch);
if ($errorCode !== CURLE_OK) {
$response->setError(new Error(curl_error($this->ch), $errorCode));

View File

@@ -11,7 +11,7 @@ class RequestsQueue extends EventDispatcher implements RequestsQueueInterface, \
protected $defaultOptions = null;
/**
* @var resource cURL multi handler
* @var \CurlMultiHandle cURL multi handler
*/
protected $mh;
@@ -115,6 +115,7 @@ class RequestsQueue extends EventDispatcher implements RequestsQueueInterface, \
$event = new Event();
$event->request = $request;
$event->response = new Response($request, curl_multi_getcontent($request->getHandle()));
$event->response->setHeaders($event->request->getResponseHeaders());
if ($result !== CURLE_OK) {
$event->response->setError(new Error(curl_error($request->getHandle()), $result));
}

View File

@@ -19,18 +19,7 @@ class Response
$this->ch = $request->getHandle();
if ($content != null) {
$header_size = $this->getInfo(CURLINFO_HEADER_SIZE);
foreach (explode("\r\n", substr($content, 0, $header_size)) as $value) {
if(false !== ($matches = explode(':', $value, 2))) {
if (count($matches) === 2) {
$headers_arr["{$matches[0]}"] = trim($matches[1]);
}
}
}
$this->headers = $headers_arr;
$this->content = substr($content, $header_size);
$this->content = $content;
}
}
@@ -89,6 +78,17 @@ class Response
return isset($this->error);
}
/**
* Sets headers
*
* @param array|null $headers headers to set
* @return void
*/
public function setHeaders(?array $headers)
{
$this->headers = $headers;
}
/**
* Returns headers of request
*