2020-07-07 10:15:56 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
|
|
namespace Shaarli\Front\Controller\Visitor;
|
|
|
|
|
|
|
|
use Shaarli\Container\ShaarliContainer;
|
|
|
|
use Shaarli\Front\Exception\AlreadyInstalledException;
|
|
|
|
use Shaarli\Front\Exception\ResourcePermissionException;
|
2020-10-16 13:34:59 +02:00
|
|
|
use Shaarli\Helper\ApplicationUtils;
|
2020-07-07 10:15:56 +02:00
|
|
|
use Shaarli\Languages;
|
|
|
|
use Shaarli\Security\SessionManager;
|
|
|
|
use Slim\Http\Request;
|
|
|
|
use Slim\Http\Response;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Slim controller used to render install page, and create initial configuration file.
|
|
|
|
*/
|
|
|
|
class InstallController extends ShaarliVisitorController
|
|
|
|
{
|
|
|
|
public const SESSION_TEST_KEY = 'session_tested';
|
|
|
|
public const SESSION_TEST_VALUE = 'Working';
|
|
|
|
|
|
|
|
public function __construct(ShaarliContainer $container)
|
|
|
|
{
|
|
|
|
parent::__construct($container);
|
|
|
|
|
|
|
|
if (is_file($this->container->conf->getConfigFileExt())) {
|
|
|
|
throw new AlreadyInstalledException();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Display the install template page.
|
|
|
|
* Also test file permissions and sessions beforehand.
|
|
|
|
*/
|
|
|
|
public function index(Request $request, Response $response): Response
|
|
|
|
{
|
|
|
|
// Before installation, we'll make sure that permissions are set properly, and sessions are working.
|
|
|
|
$this->checkPermissions();
|
|
|
|
|
2020-09-22 20:25:47 +02:00
|
|
|
if (
|
|
|
|
static::SESSION_TEST_VALUE
|
2020-07-07 10:15:56 +02:00
|
|
|
!== $this->container->sessionManager->getSessionParameter(static::SESSION_TEST_KEY)
|
|
|
|
) {
|
|
|
|
$this->container->sessionManager->setSessionParameter(static::SESSION_TEST_KEY, static::SESSION_TEST_VALUE);
|
|
|
|
|
|
|
|
return $this->redirect($response, '/install/session-test');
|
|
|
|
}
|
|
|
|
|
|
|
|
[$continents, $cities] = generateTimeZoneData(timezone_identifiers_list(), date_default_timezone_get());
|
|
|
|
|
|
|
|
$this->assignView('continents', $continents);
|
|
|
|
$this->assignView('cities', $cities);
|
|
|
|
$this->assignView('languages', Languages::getAvailableLanguages());
|
|
|
|
|
2020-10-21 13:12:15 +02:00
|
|
|
$phpEol = new \DateTimeImmutable(ApplicationUtils::getPhpEol(PHP_VERSION));
|
|
|
|
|
2020-11-24 13:28:17 +01:00
|
|
|
$permissions = array_merge(
|
|
|
|
ApplicationUtils::checkResourcePermissions($this->container->conf),
|
|
|
|
ApplicationUtils::checkDatastoreMutex()
|
|
|
|
);
|
|
|
|
|
2020-10-21 13:12:15 +02:00
|
|
|
$this->assignView('php_version', PHP_VERSION);
|
|
|
|
$this->assignView('php_eol', format_date($phpEol, false));
|
|
|
|
$this->assignView('php_has_reached_eol', $phpEol < new \DateTimeImmutable());
|
|
|
|
$this->assignView('php_extensions', ApplicationUtils::getPhpExtensionsRequirement());
|
2020-11-24 13:28:17 +01:00
|
|
|
$this->assignView('permissions', $permissions);
|
2020-10-21 13:12:15 +02:00
|
|
|
|
|
|
|
$this->assignView('pagetitle', t('Install Shaarli'));
|
|
|
|
|
2020-07-07 10:15:56 +02:00
|
|
|
return $response->write($this->render('install'));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Route checking that the session parameter has been properly saved between two distinct requests.
|
|
|
|
* If the session parameter is preserved, redirect to install template page, otherwise displays error.
|
|
|
|
*/
|
|
|
|
public function sessionTest(Request $request, Response $response): Response
|
|
|
|
{
|
|
|
|
// This part makes sure sessions works correctly.
|
|
|
|
// (Because on some hosts, session.save_path may not be set correctly,
|
|
|
|
// or we may not have write access to it.)
|
2020-09-22 20:25:47 +02:00
|
|
|
if (
|
|
|
|
static::SESSION_TEST_VALUE
|
2020-07-07 10:15:56 +02:00
|
|
|
!== $this->container->sessionManager->getSessionParameter(static::SESSION_TEST_KEY)
|
|
|
|
) {
|
|
|
|
// Step 2: Check if data in session is correct.
|
|
|
|
$msg = t(
|
2020-09-22 20:25:47 +02:00
|
|
|
'<pre>Sessions do not seem to work correctly on your server.<br>' .
|
|
|
|
'Make sure the variable "session.save_path" is set correctly in your PHP config, ' .
|
|
|
|
'and that you have write access to it.<br>' .
|
|
|
|
'It currently points to %s.<br>' .
|
|
|
|
'On some browsers, accessing your server via a hostname like \'localhost\' ' .
|
|
|
|
'or any custom hostname without a dot causes cookie storage to fail. ' .
|
2020-07-07 10:15:56 +02:00
|
|
|
'We recommend accessing your server via it\'s IP address or Fully Qualified Domain Name.<br>'
|
|
|
|
);
|
|
|
|
$msg = sprintf($msg, $this->container->sessionManager->getSavePath());
|
|
|
|
|
|
|
|
$this->assignView('message', $msg);
|
|
|
|
|
|
|
|
return $response->write($this->render('error'));
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->redirect($response, '/install');
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Save installation form and initialize config file and datastore if necessary.
|
|
|
|
*/
|
|
|
|
public function save(Request $request, Response $response): Response
|
|
|
|
{
|
|
|
|
$timezone = 'UTC';
|
2020-09-22 20:25:47 +02:00
|
|
|
if (
|
|
|
|
!empty($request->getParam('continent'))
|
2020-07-07 10:15:56 +02:00
|
|
|
&& !empty($request->getParam('city'))
|
|
|
|
&& isTimeZoneValid($request->getParam('continent'), $request->getParam('city'))
|
|
|
|
) {
|
|
|
|
$timezone = $request->getParam('continent') . '/' . $request->getParam('city');
|
|
|
|
}
|
|
|
|
$this->container->conf->set('general.timezone', $timezone);
|
|
|
|
|
|
|
|
$login = $request->getParam('setlogin');
|
|
|
|
$this->container->conf->set('credentials.login', $login);
|
2020-09-22 20:25:47 +02:00
|
|
|
$salt = sha1(uniqid('', true) . '_' . mt_rand());
|
2020-07-07 10:15:56 +02:00
|
|
|
$this->container->conf->set('credentials.salt', $salt);
|
|
|
|
$this->container->conf->set('credentials.hash', sha1($request->getParam('setpassword') . $login . $salt));
|
|
|
|
|
|
|
|
if (!empty($request->getParam('title'))) {
|
|
|
|
$this->container->conf->set('general.title', escape($request->getParam('title')));
|
|
|
|
} else {
|
|
|
|
$this->container->conf->set(
|
|
|
|
'general.title',
|
2021-08-22 16:13:58 +02:00
|
|
|
t('My links')
|
2020-07-07 10:15:56 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->container->conf->set('translation.language', escape($request->getParam('language')));
|
|
|
|
$this->container->conf->set('updates.check_updates', !empty($request->getParam('updateCheck')));
|
|
|
|
$this->container->conf->set('api.enabled', !empty($request->getParam('enableApi')));
|
|
|
|
$this->container->conf->set(
|
|
|
|
'api.secret',
|
|
|
|
generate_api_secret(
|
|
|
|
$this->container->conf->get('credentials.login'),
|
|
|
|
$this->container->conf->get('credentials.salt')
|
|
|
|
)
|
|
|
|
);
|
2020-07-24 10:30:47 +02:00
|
|
|
$this->container->conf->set('general.header_link', $this->container->basePath . '/');
|
2020-07-07 10:15:56 +02:00
|
|
|
|
|
|
|
try {
|
|
|
|
// Everything is ok, let's create config file.
|
|
|
|
$this->container->conf->write($this->container->loginManager->isLoggedIn());
|
|
|
|
} catch (\Exception $e) {
|
2020-07-23 16:41:32 +02:00
|
|
|
$this->assignView('message', t('Error while writing config file after configuration update.'));
|
|
|
|
$this->assignView('stacktrace', $e->getMessage() . PHP_EOL . $e->getTraceAsString());
|
2020-07-07 10:15:56 +02:00
|
|
|
|
|
|
|
return $response->write($this->render('error'));
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->container->sessionManager->setSessionParameter(
|
|
|
|
SessionManager::KEY_SUCCESS_MESSAGES,
|
|
|
|
[t('Shaarli is now configured. Please login and start shaaring your bookmarks!')]
|
|
|
|
);
|
|
|
|
|
2020-07-24 10:30:47 +02:00
|
|
|
return $this->redirect($response, '/login');
|
2020-07-07 10:15:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
protected function checkPermissions(): bool
|
|
|
|
{
|
|
|
|
// Ensure Shaarli has proper access to its resources
|
2020-10-21 13:12:15 +02:00
|
|
|
$errors = ApplicationUtils::checkResourcePermissions($this->container->conf, true);
|
2020-07-07 10:15:56 +02:00
|
|
|
if (empty($errors)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-07-23 16:41:32 +02:00
|
|
|
$message = t('Insufficient permissions:') . PHP_EOL;
|
2020-07-07 10:15:56 +02:00
|
|
|
foreach ($errors as $error) {
|
2020-07-23 16:41:32 +02:00
|
|
|
$message .= PHP_EOL . $error;
|
2020-07-07 10:15:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
throw new ResourcePermissionException($message);
|
|
|
|
}
|
|
|
|
}
|