diff --git a/app/Controllers/Controller.php b/app/Controllers/Controller.php
index 9f07e97..ef024d4 100644
--- a/app/Controllers/Controller.php
+++ b/app/Controllers/Controller.php
@@ -7,7 +7,6 @@ use League\Flysystem\Adapter\Local;
use League\Flysystem\FileNotFoundException;
use League\Flysystem\Filesystem;
use Slim\Container;
-use Slim\Http\Request;
use Slim\Http\Response;
abstract class Controller
@@ -34,20 +33,6 @@ abstract class Controller
return null;
}
-
- /**
- * Generate a human readable file size
- * @param $size
- * @param int $precision
- * @return string
- */
- protected function humanFilesize($size, $precision = 2): string
- {
- for ($i = 0; ($size / 1024) > 0.9; $i++, $size /= 1024) {
- }
- return round($size, $precision) . ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'][$i];
- }
-
/**
* Get a filesystem instance
* @return Filesystem
@@ -57,19 +42,6 @@ abstract class Controller
return new Filesystem(new Local($this->settings['storage_dir']));
}
- /**
- * @param $path
- */
- protected function removeDirectory($path)
- {
- $files = glob($path . '/*');
- foreach ($files as $file) {
- is_dir($file) ? $this->removeDirectory($file) : unlink($file);
- }
- rmdir($path);
- return;
- }
-
/**
* @param $id
* @return int
@@ -90,4 +62,14 @@ abstract class Controller
return $totalSize;
}
+
+ /**
+ * @param Response $response
+ * @param string $path
+ * @return Response
+ */
+ function redirectTo(Response $response, string $path): Response
+ {
+ return $response->withRedirect($this->settings['base_url'] . $path);
+ }
}
\ No newline at end of file
diff --git a/app/Controllers/DashboardController.php b/app/Controllers/DashboardController.php
index d9a7cc4..b91631b 100644
--- a/app/Controllers/DashboardController.php
+++ b/app/Controllers/DashboardController.php
@@ -24,10 +24,10 @@ class DashboardController extends Controller
if ($request->getParam('afterInstall') !== null && is_dir('install')) {
Session::alert('Installation completed successfully!', 'success');
- $this->removeDirectory('install');
+ removeDirectory('install');
}
- return $response->withRedirect('/home');
+ return $this->redirectTo($response,'/home');
}
/**
@@ -61,7 +61,7 @@ class DashboardController extends Controller
}
$media->mimetype = $mime;
$media->extension = $extension;
- $media->size = $this->humanFilesize($size);
+ $media->size = humanFileSize($size);
}
return $this->view->render(
@@ -101,7 +101,7 @@ class DashboardController extends Controller
'usersCount' => $usersCount,
'mediasCount' => $mediasCount,
'orphanFilesCount' => $orphanFilesCount,
- 'totalSize' => $this->humanFilesize($totalSize),
+ 'totalSize' => humanFileSize($totalSize),
'post_max_size' => ini_get('post_max_size'),
'upload_max_filesize' => ini_get('upload_max_filesize'),
]);
@@ -129,6 +129,6 @@ class DashboardController extends Controller
public function applyTheme(Request $request, Response $response): Response
{
file_put_contents('static/bootstrap/css/bootstrap.min.css', file_get_contents($request->getParam('css')));
- return $response->withRedirect('/system')->withAddedHeader('Cache-Control', 'no-cache, must-revalidate');
+ return $this->redirectTo($response,'/system')->withAddedHeader('Cache-Control', 'no-cache, must-revalidate');
}
}
\ No newline at end of file
diff --git a/app/Controllers/LoginController.php b/app/Controllers/LoginController.php
index 2234bb6..ac4d4b8 100644
--- a/app/Controllers/LoginController.php
+++ b/app/Controllers/LoginController.php
@@ -19,7 +19,7 @@ class LoginController extends Controller
public function show(Request $request, Response $response): Response
{
if (Session::get('logged', false)) {
- return $response->withRedirect('/home');
+ return $this->redirectTo($response, '/home');
}
return $this->view->render($response, 'auth/login.twig');
}
@@ -36,19 +36,19 @@ class LoginController extends Controller
if (!$result || !password_verify($request->getParam('password'), $result->password)) {
Session::alert('Wrong credentials', 'danger');
- return $response->withRedirect('/login');
+ return $this->redirectTo($response, '/login');
}
if (!$result->active) {
Session::alert('Your account is disabled.', 'danger');
- return $response->withRedirect('/login');
+ return $this->redirectTo($response, '/login');
}
Session::set('logged', true);
Session::set('user_id', $result->id);
Session::set('username', $result->username);
Session::set('admin', $result->is_admin);
- Session::set('used_space', $this->humanFilesize($this->getUsedSpaceByUser($result->id)));
+ Session::set('used_space', humanFileSize($this->getUsedSpaceByUser($result->id)));
Session::alert("Welcome, $result->username!", 'info');
$this->logger->info("User $result->username logged in.");
@@ -57,7 +57,7 @@ class LoginController extends Controller
return $response->withRedirect(Session::get('redirectTo'));
}
- return $response->withRedirect('/home');
+ return $this->redirectTo($response,'/home');
}
/**
@@ -70,7 +70,7 @@ class LoginController extends Controller
Session::clear();
Session::set('logged', false);
Session::alert('Goodbye!', 'warning');
- return $response->withRedirect('/login');
+ return $this->redirectTo($response,'/login');
}
}
\ No newline at end of file
diff --git a/app/Controllers/UploadController.php b/app/Controllers/UploadController.php
index f109fc7..bacc5fe 100644
--- a/app/Controllers/UploadController.php
+++ b/app/Controllers/UploadController.php
@@ -223,7 +223,7 @@ class UploadController extends Controller
} finally {
$this->database->query('DELETE FROM `uploads` WHERE `id` = ?', $args['id']);
$this->logger->info('User ' . Session::get('username') . ' deleted a media.', [$args['id']]);
- Session::set('used_space', $this->humanFilesize($this->getUsedSpaceByUser(Session::get('user_id'))));
+ Session::set('used_space', humanFileSize($this->getUsedSpaceByUser(Session::get('user_id'))));
}
} else {
throw new UnauthorizedException();
diff --git a/app/Controllers/UserController.php b/app/Controllers/UserController.php
index 13f1c48..c1a2e68 100644
--- a/app/Controllers/UserController.php
+++ b/app/Controllers/UserController.php
@@ -58,22 +58,22 @@ class UserController extends Controller
{
if ($request->getParam('email') === null) {
Session::alert('The email is required.', 'danger');
- return $response->withRedirect('/user/create');
+ return $this->redirectTo($response,'/user/create');
}
if ($request->getParam('username') === null) {
Session::alert('The username is required.', 'danger');
- return $response->withRedirect('/user/create');
+ return $this->redirectTo($response,'/user/create');
}
if ($request->getParam('password') === null) {
Session::alert('The password is required.', 'danger');
- return $response->withRedirect('/user/create');
+ return $this->redirectTo($response,'/user/create');
}
if ($this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `username` = ?', $request->getParam('username'))->fetch()->count > 0) {
Session::alert('The username already taken.', 'danger');
- return $response->withRedirect('/user/create');
+ return $this->redirectTo($response,'/user/create');
}
do {
@@ -95,7 +95,7 @@ class UserController extends Controller
Session::alert("User '{$request->getParam('username')}' created!", 'success');
$this->logger->info('User ' . Session::get('username') . ' created a new user.', [array_diff($request->getParams(), ['password'])]);
- return $response->withRedirect('/users');
+ return $this->redirectTo($response,'/users');
}
/**
@@ -135,22 +135,22 @@ class UserController extends Controller
if ($request->getParam('email') === null) {
Session::alert('The email is required.', 'danger');
- return $response->withRedirect('/user/' . $args['id'] . '/edit');
+ return $this->redirectTo($response,'/user/' . $args['id'] . '/edit');
}
if ($request->getParam('username') === null) {
Session::alert('The username is required.', 'danger');
- return $response->withRedirect('/user/' . $args['id'] . '/edit');
+ return $this->redirectTo($response,'/user/' . $args['id'] . '/edit');
}
if ($this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `username` = ? AND `username` <> ?', [$request->getParam('username'), $user->username])->fetch()->count > 0) {
Session::alert('The username already taken.', 'danger');
- return $response->withRedirect('/user/' . $args['id'] . '/edit');
+ return $this->redirectTo($response,'/user/' . $args['id'] . '/edit');
}
if ($user->id === Session::get('user_id') && $request->getParam('is_admin') === null) {
Session::alert('You cannot demote yourself.', 'danger');
- return $response->withRedirect('/user/' . $args['id'] . '/edit');
+ return $this->redirectTo($response,'/user/' . $args['id'] . '/edit');
}
if ($request->getParam('password') !== null && !empty($request->getParam('password'))) {
@@ -175,7 +175,7 @@ class UserController extends Controller
Session::alert("User '{$request->getParam('username')}' updated!", 'success');
$this->logger->info('User ' . Session::get('username') . " updated $user->id.", [$user, array_diff($request->getParams(), ['password'])]);
- return $response->withRedirect('/users');
+ return $this->redirectTo($response,'/users');
}
@@ -196,7 +196,7 @@ class UserController extends Controller
if ($user->id === Session::get('user_id')) {
Session::alert('You cannot delete yourself.', 'danger');
- return $response->withRedirect('/users');
+ return $this->redirectTo($response,'/users');
}
$this->database->query('DELETE FROM `users` WHERE `id` = ?', $user->id);
@@ -204,7 +204,7 @@ class UserController extends Controller
Session::alert('User deleted.', 'success');
$this->logger->info('User ' . Session::get('username') . " deleted $user->id.");
- return $response->withRedirect('/users');
+ return $this->redirectTo($response,'/users');
}
/**
@@ -253,7 +253,7 @@ class UserController extends Controller
if ($request->getParam('email') === null) {
Session::alert('The email is required.', 'danger');
- return $response->withRedirect('/profile');
+ return $this->redirectTo($response,'/profile');
}
if ($request->getParam('password') !== null && !empty($request->getParam('password'))) {
@@ -272,7 +272,7 @@ class UserController extends Controller
Session::alert('Profile updated successfully!', 'success');
$this->logger->info('User ' . Session::get('username') . " updated profile of $user->id.");
- return $response->withRedirect('/profile');
+ return $this->redirectTo($response,'/profile');
}
/**
diff --git a/app/Middleware/AuthMiddleware.php b/app/Middleware/AuthMiddleware.php
index 5610958..315c0e8 100644
--- a/app/Middleware/AuthMiddleware.php
+++ b/app/Middleware/AuthMiddleware.php
@@ -28,14 +28,14 @@ class AuthMiddleware
{
if (!Session::get('logged', false)) {
Session::set('redirectTo', (isset($_SERVER['HTTPS']) ? 'https' : 'http') . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]");
- return $response->withRedirect('/login');
+ return $response->withRedirect($this->container->settings['base_url'] . '/login');
}
if (!$this->container->database->query('SELECT `id`, `active` FROM `users` WHERE `id` = ? LIMIT 1', [Session::get('user_id')])->fetch()->active) {
Session::alert('Your account is not active anymore.', 'danger');
Session::set('logged', false);
Session::set('redirectTo', (isset($_SERVER['HTTPS']) ? 'https' : 'http') . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]");
- return $response->withRedirect('/login');
+ return $response->withRedirect($this->container->settings['base_url'] . '/login');
}
return $next($request, $response);
diff --git a/app/helpers.php b/app/helpers.php
new file mode 100644
index 0000000..d5c13b5
--- /dev/null
+++ b/app/helpers.php
@@ -0,0 +1,51 @@
+ 0.9; $i++, $size /= 1024) {
+ }
+ return round($size, $precision) . ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'][$i];
+ }
+}
+
+if (!function_exists('removeDirectory')) {
+ /**
+ * Remove a directory and it's content
+ * @param $path
+ */
+ function removeDirectory($path)
+ {
+ $files = glob($path . '/*');
+ foreach ($files as $file) {
+ is_dir($file) ? removeDirectory($file) : unlink($file);
+ }
+ rmdir($path);
+ return;
+ }
+}
+
+if (!function_exists('cleanDirectory')) {
+ /**
+ * Removes all directory contents
+ * @param $path
+ */
+ function cleanDirectory($path)
+ {
+ $directoryIterator = new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS);
+ $iteratorIterator = new RecursiveIteratorIterator($directoryIterator, RecursiveIteratorIterator::CHILD_FIRST);
+ foreach ($iteratorIterator as $file) {
+ if ($file->getFilename() !== '.gitkeep') {
+ $file->isDir() ? rmdir($file) : unlink($file);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/bin/clean b/bin/clean
index 97ed9b8..5724a7a 100644
--- a/bin/clean
+++ b/bin/clean
@@ -7,29 +7,18 @@ if (php_sapi_name() !== 'cli') {
die();
}
-function cleanDir($path)
-{
- $directoryIterator = new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS);
- $iteratorIterator = new RecursiveIteratorIterator($directoryIterator, RecursiveIteratorIterator::CHILD_FIRST);
- foreach ($iteratorIterator as $file) {
- if ($file->getFilename() !== '.gitkeep') {
- $file->isDir() ? rmdir($file) : unlink($file);
- }
- }
-}
-
$action = isset($argv[1]) ? $argv[1] : 'all';
switch ($action) {
case 'cache':
- cleanDir(__DIR__ . '/../resources/cache');
+ cleanDirectory(__DIR__ . '/../resources/cache');
break;
case 'sessions':
- cleanDir(__DIR__ . '/../resources/sessions');
+ cleanDirectory(__DIR__ . '/../resources/sessions');
break;
case 'all':
- cleanDir(__DIR__ . '/../resources/cache');
- cleanDir(__DIR__ . '/../resources/sessions');
+ cleanDirectory(__DIR__ . '/../resources/cache');
+ cleanDirectory(__DIR__ . '/../resources/sessions');
break;
case 'help':
default:
diff --git a/bootstrap/app.php b/bootstrap/app.php
index 353acdc..d318644 100644
--- a/bootstrap/app.php
+++ b/bootstrap/app.php
@@ -9,7 +9,7 @@ use Slim\App;
use Slim\Container;
if (!file_exists('config.php') && is_dir('install/')) {
- header('Location: /install/');
+ header('Location: ./install/');
exit();
} else if (!file_exists('config.php') && !is_dir('install/')) {
die('Cannot find the config file.');
@@ -23,11 +23,12 @@ $config = array_replace_recursive([
'displayErrorDetails' => false,
'db' => [
'connection' => 'sqlite',
- 'dsn' => 'resources/database/xbackbone.db',
+ 'dsn' => __DIR__ . '/../resources/database/xbackbone.db',
'username' => null,
'password' => null,
],
-], require 'config.php');
+ 'routerCacheFile' => __DIR__ . '/../resources/cache/routes.cache.php',
+], require __DIR__ . '/../config.php');
$container = new Container(['settings' => $config]);
@@ -43,10 +44,11 @@ $container['logger'] = function ($container) {
};
// Session init
-Session::init('xbackbone_session', 'resources/sessions');
+Session::init('xbackbone_session', __DIR__ . '/../resources/sessions');
// Set the database dsn
-DB::setDsn($config['db']['connection'] . ':' . $config['db']['dsn'], $config['db']['username'], $config['db']['password']);
+$dsn = $config['db']['connection'] === 'sqlite' ? __DIR__ . '/../' . $config['db']['dsn'] : $config['db']['dsn'];
+DB::setDsn($config['db']['connection'] . ':' . $dsn, $config['db']['username'], $config['db']['password']);
$container['database'] = function ($container) use (&$config) {
return DB::getInstance();
@@ -54,8 +56,8 @@ $container['database'] = function ($container) use (&$config) {
$container['view'] = function ($container) use (&$config) {
- $view = new \Slim\Views\Twig('resources/templates', [
- 'cache' => 'resources/cache',
+ $view = new \Slim\Views\Twig(__DIR__ . '/../resources/templates', [
+ 'cache' => __DIR__ . '/../resources/cache',
'autoescape' => 'html',
'debug' => $config['displayErrorDetails'],
'auto_reload' => $config['displayErrorDetails'],
@@ -95,5 +97,23 @@ $container['notFoundHandler'] = function ($container) {
$app = new App($container);
+// Permanently redirect paths with a trailing slash to their non-trailing counterpart
+$app->add(function (\Slim\Http\Request $request, \Slim\Http\Response $response, callable $next) {
+ $uri = $request->getUri();
+ $path = $uri->getPath();
+
+ if ($path !== '/' && substr($path, -1) === '/') {
+ $uri = $uri->withPath(substr($path, 0, -1));
+
+ if ($request->getMethod() === 'GET') {
+ return $response->withRedirect((string)$uri, 301);
+ } else {
+ return $next($request->withUri($uri), $response);
+ }
+ }
+
+ return $next($request, $response);
+});
+
// Load the application routes
require 'app/routes.php';
\ No newline at end of file
diff --git a/composer.json b/composer.json
index 0f1c379..b1997d5 100644
--- a/composer.json
+++ b/composer.json
@@ -14,6 +14,9 @@
"ext-pdo": "*"
},
"autoload": {
+ "files": [
+ "app/helpers.php"
+ ],
"psr-4": {
"App\\": "app/"
}
diff --git a/install/index.php b/install/index.php
index 488899f..b6330eb 100644
--- a/install/index.php
+++ b/install/index.php
@@ -11,7 +11,6 @@ use Slim\Http\Response;
define('PLATFORM_VERSION', json_decode(file_get_contents(__DIR__ . '/../composer.json'))->version);
$config = [
- 'app_name' => 'XBackBone',
'base_url' => isset($_SERVER['HTTPS']) ? 'https://' . $_SERVER['HTTP_HOST'] : 'http://' . $_SERVER['HTTP_HOST'],
'storage_dir' => 'storage',
'displayErrorDetails' => true,
@@ -28,7 +27,7 @@ $container = new Container(['settings' => $config]);
Session::init('xbackbone_session');
$container['view'] = function ($container) use (&$config) {
- $view = new \Slim\Views\Twig('templates', [
+ $view = new \Slim\Views\Twig(__DIR__ . '/templates', [
'cache' => false,
'autoescape' => 'html',
'debug' => $config['displayErrorDetails'],
@@ -51,7 +50,7 @@ $container['view'] = function ($container) use (&$config) {
function migrate($config)
{
$firstMigrate = false;
- if (!file_exists(__DIR__ . '/../' . $config['db']['dsn']) && DB::driver() === 'sqlite') {
+ if ($config['db']['connection'] === 'sqlite' && !file_exists(__DIR__ . '/../' . $config['db']['dsn'])) {
touch(__DIR__ . '/../' . $config['db']['dsn']);
$firstMigrate = true;
}
@@ -110,17 +109,6 @@ function migrate($config)
}
}
-function cleanDir($path)
-{
- $directoryIterator = new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS);
- $iteratorIterator = new RecursiveIteratorIterator($directoryIterator, RecursiveIteratorIterator::CHILD_FIRST);
- foreach ($iteratorIterator as $file) {
- if ($file->getFilename() !== '.gitkeep') {
- $file->isDir() ? rmdir($file) : unlink($file);
- }
- }
-}
-
$app = new App($container);
$app->get('/', function (Request $request, Response $response) {
@@ -131,7 +119,10 @@ $app->get('/', function (Request $request, Response $response) {
});
$app->post('/', function (Request $request, Response $response) use (&$config) {
+ $installed = true;
if (!file_exists(__DIR__ . '/../config.php')) {
+ $installed = false;
+
$config['base_url'] = $request->getParam('base_url');
$config['storage_dir'] = $request->getParam('storage_dir');
$config['displayErrorDetails'] = false;
@@ -144,14 +135,18 @@ $app->post('/', function (Request $request, Response $response) use (&$config) {
file_put_contents(__DIR__ . '/../config.php', 'getParam('email'), password_hash($request->getParam('password'), PASSWORD_DEFAULT), substr(md5(microtime()), rand(0, 26), 5)]);
+ if (!$installed) {
+ DB::query("INSERT INTO `users` (`email`, `username`, `password`, `is_admin`, `user_code`) VALUES (?, 'admin', ?, 1, ?)", [$request->getParam('email'), password_hash($request->getParam('password'), PASSWORD_DEFAULT), substr(md5(microtime()), rand(0, 26), 5)]);
+ }
- cleanDir(__DIR__ . '/../resources/cache');
- cleanDir(__DIR__ . '/../resources/sessions');
+ cleanDirectory(__DIR__ . '/../resources/cache');
+ cleanDirectory(__DIR__ . '/../resources/sessions');
return $response->withRedirect('../?afterInstall=true');
});
diff --git a/install/templates/install.twig b/install/templates/install.twig
index 54c1357..7ff21fc 100644
--- a/install/templates/install.twig
+++ b/install/templates/install.twig
@@ -6,16 +6,16 @@
-
-
-
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+