2018-04-03 11:56:20 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
error_reporting(E_ALL);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Step 1: Require the Slim Framework using Composer's autoloader
|
|
|
|
*
|
|
|
|
* If you are not using Composer, you need to load Slim Framework with your own
|
|
|
|
* PSR-4 autoloader.
|
|
|
|
*/
|
|
|
|
|
|
|
|
use Carbon\Carbon;
|
2019-08-07 15:56:21 +00:00
|
|
|
use JeremyKendall\Slim\Auth\ServiceProvider\SlimAuthProvider;
|
2018-04-03 11:56:20 +00:00
|
|
|
use Slim\Http\Request;
|
|
|
|
use Slim\Http\Response;
|
2019-08-07 15:56:21 +00:00
|
|
|
use Slim\Middleware\Session;
|
|
|
|
use Slim\Views\Twig;
|
|
|
|
use Slim\Views\TwigExtension;
|
|
|
|
use SlimSession\Helper;
|
2019-11-10 14:34:32 +00:00
|
|
|
use Symfony\Bridge\Twig\Extension\TranslationExtension;
|
|
|
|
use Twig\Extension\DebugExtension;
|
|
|
|
use Twig\TwigFilter;
|
|
|
|
use Twig\TwigFunction;
|
2018-04-03 11:56:20 +00:00
|
|
|
|
|
|
|
// To help the built-in PHP dev server, check if the request was actually for
|
|
|
|
// something which should probably be served as a static file
|
|
|
|
if (PHP_SAPI === 'cli-server' && $_SERVER['SCRIPT_FILENAME'] !== __FILE__) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
require __DIR__ . DIRECTORY_SEPARATOR . '../vendor/autoload.php';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Step 2: Bootstrap database, ACL, Twig, FlashMessages, Logger
|
|
|
|
*/
|
|
|
|
$app = new Slim\App(['settings' => ['slim_settings' => [
|
|
|
|
'displayErrorDetails' => true,
|
|
|
|
'determineRouteBeforeAppMiddleware' => true,
|
|
|
|
]]]);
|
|
|
|
|
|
|
|
// container
|
|
|
|
$container = $app->getContainer();
|
|
|
|
|
|
|
|
// environment
|
|
|
|
try {
|
|
|
|
$env = BootstrapHelper::bootEnvironment();
|
|
|
|
} catch (Exception $e) {
|
|
|
|
die('Error bootstrapping environment: ' . $e->getMessage());
|
|
|
|
}
|
|
|
|
$container['env'] = function() use ($env) {
|
|
|
|
return $env;
|
|
|
|
};
|
|
|
|
|
|
|
|
// translation
|
|
|
|
$translator = BootstrapHelper::bootTranslator();
|
|
|
|
$container['translator'] = function () use ($translator) {
|
|
|
|
return $translator;
|
|
|
|
};
|
|
|
|
|
|
|
|
// date
|
2019-08-06 18:25:50 +00:00
|
|
|
Carbon::setLocale(getenv(EnvConstants::SITE_LANGUAGE));
|
|
|
|
Carbon::setToStringFormat(getenv(EnvConstants::SITE_DATE_FORMAT));
|
2018-04-03 11:56:20 +00:00
|
|
|
|
|
|
|
// logger
|
2018-04-04 10:25:47 +00:00
|
|
|
try {
|
2018-04-03 11:56:20 +00:00
|
|
|
$logger = BootstrapHelper::bootLogger();
|
2023-04-06 20:55:21 +00:00
|
|
|
$logger->info("Starting ts3web version " . Constants::VERSION);
|
2018-04-04 10:25:47 +00:00
|
|
|
|
|
|
|
$container['logger'] = function () use ($logger) {
|
|
|
|
return $logger;
|
|
|
|
};
|
|
|
|
} catch (Exception $e) {
|
|
|
|
die('Error bootstrapping logger: ' . $e->getMessage());
|
|
|
|
}
|
2018-04-03 11:56:20 +00:00
|
|
|
|
|
|
|
// teamspeak
|
2018-04-04 10:25:47 +00:00
|
|
|
$container['ts'] = function () use ($logger) {
|
|
|
|
return new TSInstance($logger);
|
2018-04-03 11:56:20 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// auth
|
|
|
|
$container['authAdapter'] = function ($container) {
|
2019-08-06 18:25:50 +00:00
|
|
|
$adapter = new TSAuthAdapter(getenv(EnvConstants::TEAMSPEAK_HOST),
|
|
|
|
getenv(EnvConstants::TEAMSPEAK_QUERY_PORT), $container['logger'], $container['ts']);
|
2018-04-03 11:56:20 +00:00
|
|
|
return $adapter;
|
|
|
|
};
|
|
|
|
$container['acl'] = function () {
|
|
|
|
return new ACL();
|
|
|
|
};
|
2019-08-07 15:56:21 +00:00
|
|
|
$container->register(new SlimAuthProvider());
|
2018-04-03 11:56:20 +00:00
|
|
|
$app->add($app->getContainer()->get('slimAuthRedirectMiddleware'));
|
|
|
|
|
2018-04-05 10:30:06 +00:00
|
|
|
// session
|
2019-08-07 15:56:21 +00:00
|
|
|
$app->add(new Session([
|
2018-04-05 10:30:06 +00:00
|
|
|
'name' => 'dummy_session',
|
|
|
|
'autorefresh' => true,
|
|
|
|
'lifetime' => '1 hour'
|
|
|
|
]));
|
|
|
|
$container['session'] = function () {
|
2019-08-07 15:56:21 +00:00
|
|
|
return new Helper;
|
2018-04-05 10:30:06 +00:00
|
|
|
};
|
|
|
|
|
2018-04-03 11:56:20 +00:00
|
|
|
// view
|
|
|
|
$container['flash'] = function () {
|
|
|
|
return new Slim\Flash\Messages;
|
|
|
|
};
|
|
|
|
$container['view'] = function ($container) use ($app) {
|
2019-08-06 18:25:50 +00:00
|
|
|
$themeDir = __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'View' . DIRECTORY_SEPARATOR . getenv(EnvConstants::THEME);
|
2018-04-03 11:56:20 +00:00
|
|
|
|
2019-08-06 18:25:50 +00:00
|
|
|
if (!empty(getenv(EnvConstants::THEME_CACHE) && getenv(EnvConstants::THEME_CACHE) == 'true')) {
|
2018-04-03 11:56:20 +00:00
|
|
|
$themeCacheDir = __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'cache';
|
|
|
|
} else {
|
|
|
|
$themeCacheDir = false;
|
|
|
|
}
|
|
|
|
|
2019-08-07 15:56:21 +00:00
|
|
|
$view = new Twig($themeDir, ['cache' => $themeCacheDir]);
|
|
|
|
$view->addExtension(new TwigExtension(
|
2018-04-03 11:56:20 +00:00
|
|
|
$container['router'],
|
|
|
|
$container['request']->getUri()
|
|
|
|
));
|
2019-11-10 14:34:32 +00:00
|
|
|
$view->addExtension(new DebugExtension());
|
2018-04-03 11:56:20 +00:00
|
|
|
|
2018-04-05 19:20:29 +00:00
|
|
|
// dynamically apply filters
|
|
|
|
$view->getEnvironment()->addExtension(new ApplyFilterExtension());
|
|
|
|
|
|
|
|
// encode url
|
2019-11-10 14:34:32 +00:00
|
|
|
$encodeUrl = new TwigFilter('escape_url', function($str) {
|
2018-04-05 19:20:29 +00:00
|
|
|
return urlencode($str);
|
|
|
|
});
|
|
|
|
$view->getEnvironment()->addFilter($encodeUrl);
|
|
|
|
|
|
|
|
// translation
|
2019-11-10 14:34:32 +00:00
|
|
|
$view->addExtension(new TranslationExtension($container['translator']));
|
2019-08-06 18:25:50 +00:00
|
|
|
$view->getEnvironment()->getExtension('Twig_Extension_Core')->setDateFormat(getenv(EnvConstants::SITE_DATE_FORMAT));
|
2018-04-05 19:20:29 +00:00
|
|
|
|
|
|
|
// env
|
2019-11-10 14:34:32 +00:00
|
|
|
$view->getEnvironment()->addFunction(new TwigFunction('getenv', function($value) {
|
2018-04-05 19:20:29 +00:00
|
|
|
$res = getenv($value);
|
|
|
|
return $res;
|
|
|
|
}));
|
|
|
|
|
2019-11-10 14:34:32 +00:00
|
|
|
// constants
|
|
|
|
$view->getEnvironment()->addFunction(new TwigFunction('getconstant', function($value) {
|
|
|
|
return Constants::get($value);
|
|
|
|
}));
|
|
|
|
|
2018-04-05 19:20:29 +00:00
|
|
|
// session exist
|
2019-11-10 14:34:32 +00:00
|
|
|
$view->getEnvironment()->addFunction(new TwigFunction('session_exists', function($key) use ($container) {
|
2018-04-05 19:20:29 +00:00
|
|
|
return $container['session']->exists($key);
|
|
|
|
}));
|
|
|
|
|
|
|
|
// session get
|
2019-11-10 14:34:32 +00:00
|
|
|
$view->getEnvironment()->addFunction(new TwigFunction('session_get', function($key) use ($container) {
|
2018-04-05 19:20:29 +00:00
|
|
|
return $container['session']->get($key);
|
|
|
|
}));
|
|
|
|
|
2018-04-06 11:36:08 +00:00
|
|
|
// file size
|
2019-11-10 14:34:32 +00:00
|
|
|
$fileSizeFilter = new TwigFilter('file', function($bytes, $decimals = 2) {
|
2018-04-06 11:36:08 +00:00
|
|
|
return FileHelper::humanFileSize($bytes, $decimals);
|
2018-04-03 11:56:20 +00:00
|
|
|
});
|
|
|
|
$view->getEnvironment()->addFilter($fileSizeFilter);
|
|
|
|
|
2020-03-22 12:41:45 +00:00
|
|
|
$bandWidthFilter = new TwigFilter('bandwidth', function($bytes, $decimals = 2) {
|
|
|
|
return FileHelper::humanBandwidth($bytes, $decimals);
|
|
|
|
});
|
|
|
|
$view->getEnvironment()->addFilter($bandWidthFilter);
|
|
|
|
|
2018-04-05 19:20:29 +00:00
|
|
|
// ts specific: time in seconds to human readable
|
2019-11-10 14:34:32 +00:00
|
|
|
$timeInSecondsFilter = new TwigFilter('timeInSeconds', function($seconds) use ($container) {
|
2018-04-03 11:56:20 +00:00
|
|
|
return $container['ts']->getInstance()->convertSecondsToStrTime($seconds);
|
|
|
|
});
|
|
|
|
$view->getEnvironment()->addFilter($timeInSecondsFilter);
|
|
|
|
|
2019-11-10 14:34:32 +00:00
|
|
|
$timeInMillisFilter = new TwigFilter('timeInMillis', function($millis) use ($container) {
|
2018-04-05 12:55:44 +00:00
|
|
|
return $container['ts']->getInstance()->convertSecondsToStrTime(floor($millis/1000));
|
|
|
|
});
|
|
|
|
$view->getEnvironment()->addFilter($timeInMillisFilter);
|
|
|
|
|
2018-04-05 19:20:29 +00:00
|
|
|
// ts specific: timestamp to carbon
|
2019-11-10 14:34:32 +00:00
|
|
|
$timestampFilter = new TwigFilter('timestamp', function($timestamp) {
|
2018-04-03 11:56:20 +00:00
|
|
|
return Carbon::createFromTimestamp($timestamp);
|
|
|
|
});
|
|
|
|
$view->getEnvironment()->addFilter($timestampFilter);
|
|
|
|
|
2018-04-05 19:20:29 +00:00
|
|
|
// ts specific: token type
|
2019-11-10 14:34:32 +00:00
|
|
|
$tokenTypeFilter = new TwigFilter('tokentype', function($type) {
|
2018-04-05 19:20:29 +00:00
|
|
|
$tokenTypes = TSInstance::getTokenTypes();
|
2018-04-03 11:56:20 +00:00
|
|
|
|
2018-04-05 19:20:29 +00:00
|
|
|
foreach ($tokenTypes as $name => $tokenType) {
|
|
|
|
if ($type == $tokenType) return $name;
|
|
|
|
}
|
2018-04-03 11:56:20 +00:00
|
|
|
|
2018-04-05 19:20:29 +00:00
|
|
|
return $type;
|
|
|
|
});
|
|
|
|
$view->getEnvironment()->addFilter($tokenTypeFilter);
|
2018-04-03 11:56:20 +00:00
|
|
|
|
2018-04-05 19:20:29 +00:00
|
|
|
// ts specific: group type
|
2019-11-10 14:34:32 +00:00
|
|
|
$groupTypeFilter = new TwigFilter('permgrouptype', function($type) {
|
2018-04-05 19:20:29 +00:00
|
|
|
$groupTypes = TSInstance::getPermGroupTypes();
|
2018-04-05 10:30:06 +00:00
|
|
|
|
2018-04-05 19:20:29 +00:00
|
|
|
foreach ($groupTypes as $name => $groupType) {
|
|
|
|
if ($type == $groupType) return $name;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $type;
|
|
|
|
});
|
|
|
|
$view->getEnvironment()->addFilter($groupTypeFilter);
|
2018-04-05 10:30:06 +00:00
|
|
|
|
2018-04-03 11:56:20 +00:00
|
|
|
// flash
|
|
|
|
$view['flash'] = $container['flash'];
|
|
|
|
|
|
|
|
// currentUser, currentRole, ACL.isPermitted
|
2018-04-03 19:21:47 +00:00
|
|
|
$view['currentUser'] = ($container['authenticator']->hasIdentity() ? $container['authenticator']->getIdentity() : NULL); // currentUser in twig
|
2018-04-03 11:56:20 +00:00
|
|
|
$view['currentRole'] = (!empty($user) ? $role = $user->role : $role = ACL::ACL_DEFAULT_ROLE_GUEST);
|
|
|
|
|
2019-11-10 14:34:32 +00:00
|
|
|
$view->getEnvironment()->addFunction(new TwigFunction('isPermitted', function ($currentRole, $targetRole) use ($container) {
|
2018-04-03 11:56:20 +00:00
|
|
|
return $container['acl']->isPermitted($currentRole, $targetRole);
|
|
|
|
}));
|
|
|
|
|
|
|
|
return $view;
|
|
|
|
};
|
|
|
|
|
|
|
|
// comment out for specific info
|
|
|
|
// error handling
|
|
|
|
$container['notFoundHandler'] = function ($container) {
|
|
|
|
return function (Request $request, Response $response) use ($container) {
|
|
|
|
return $response->withRedirect('404');
|
|
|
|
};
|
|
|
|
};
|
|
|
|
$container['errorHandler'] = function ($container) {
|
|
|
|
return function (Request $request, Response $response, $exception) use ($container) {
|
|
|
|
|
2019-08-07 15:34:39 +00:00
|
|
|
// handle all TeamSpeak exceptions with a flash message
|
2018-04-03 11:56:20 +00:00
|
|
|
if ($exception instanceof TSException) {
|
|
|
|
$container->flash->addMessage('error', $exception->getMessage());
|
|
|
|
|
|
|
|
$refererHeader = $request->getHeader('HTTP_REFERER');
|
|
|
|
|
|
|
|
if ($refererHeader) {
|
|
|
|
$referer = array_shift($refererHeader);
|
|
|
|
return $response->withRedirect($referer);
|
|
|
|
} else {
|
|
|
|
return $container['view']->render($response, 'error.twig', [
|
|
|
|
'title' => $container['translator']->trans('error.500.title'),
|
|
|
|
'content' => $exception->getMessage()
|
|
|
|
]);
|
|
|
|
}
|
2019-08-07 15:34:39 +00:00
|
|
|
} else {
|
2018-04-03 11:56:20 +00:00
|
|
|
$container['logger']->error($container['translator']->trans('log.internal.application.error'), [
|
|
|
|
'file' => $exception->getFile(),
|
|
|
|
'line' => $exception->getLine(),
|
|
|
|
'code' => $exception->getCode(),
|
|
|
|
'message' => $exception->getMessage(),
|
|
|
|
'previous' => $exception->getPrevious(),
|
|
|
|
'trace' => $exception->getTraceAsString(),
|
|
|
|
]);
|
|
|
|
|
|
|
|
return $container['view']->render($response, 'error.twig', [
|
|
|
|
'title' => $container['translator']->trans('error.500.title'),
|
|
|
|
'content' => $exception->getMessage()
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
$container['phpErrorHandler'] = function ($container) {
|
|
|
|
return function (Request $request, Response $response) use ($container) {
|
|
|
|
return $response->withRedirect('500');
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Step 3: Define the Slim application routes
|
|
|
|
*/
|
|
|
|
require_once __DIR__ . DIRECTORY_SEPARATOR . '../config/routes.php';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Step 4: Run the Slim application
|
|
|
|
*/
|
|
|
|
try {
|
|
|
|
$app->run();
|
|
|
|
} catch (Exception $e) {
|
|
|
|
die($e->getMessage());
|
|
|
|
}
|