Răsfoiți Sursa

Modernize Constants and use new constant for string 'currentUser' (#5089)

* Modernize Constants and use new constant 'currentUser'

* Add FreshRSS_Context::currentUser() function and use

* Add FreshRSS_Context::currentUser() function and use

* Add FreshRSS_Context::currentUser() function and use

* Add FreshRSS_Context::currentUser() function and use

* Add FreshRSS_Context::currentUser() function and use

* Update app/Controllers/userController.php

* Update app/Controllers/userController.php

* Update app/Controllers/userController.php

* Update app/Models/Auth.php

* Update p/api/greader.php

* Update p/api/greader.php

* Update p/api/greader.php

* Update app/Models/Context.php

* Update app/Models/LogDAO.php

* Update lib/Minz/Log.php

* Update p/api/greader.php

* Update app/layout/header.phtml

* Update app/views/helpers/export/articles.phtml

* Update cli/do-install.php

* Remarque's from Alkarex

* Remarque's from Alkarex

* Refactor using new Minz_User class

* Consistent naming of public constants

---------

Co-authored-by: Luc <sanchezluc+freshrss@gmail.com>
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
Luc SANCHEZ 3 ani în urmă
părinte
comite
5f898dcc5e

+ 1 - 1
app/Controllers/apiController.php

@@ -11,7 +11,7 @@ class FreshRSS_api_Controller extends FreshRSS_ActionController {
 	 * @return false|string
 	 */
 	public static function updatePassword(string $apiPasswordPlain) {
-		$username = Minz_Session::param('currentUser');
+		$username = Minz_User::name();
 		$userConfig = FreshRSS_Context::$user_conf;
 
 		$apiPasswordHash = FreshRSS_password_Util::hash($apiPasswordPlain);

+ 3 - 3
app/Controllers/authController.php

@@ -72,7 +72,7 @@ class FreshRSS_auth_Controller extends FreshRSS_ActionController {
 		}
 
 		$auth_type = FreshRSS_Context::$system_conf->auth_type;
-		FreshRSS_Context::initUser('_', false);
+		FreshRSS_Context::initUser(Minz_User::INTERNAL_USER, false);
 		switch ($auth_type) {
 			case 'form':
 				Minz_Request::forward(array('c' => 'auth', 'a' => 'formLogin'));
@@ -145,7 +145,7 @@ class FreshRSS_auth_Controller extends FreshRSS_ActionController {
 			if ($ok) {
 				// Set session parameter to give access to the user.
 				Minz_Session::_params([
-					'currentUser' => $username,
+					Minz_User::CURRENT_USER => $username,
 					'passwordHash' => FreshRSS_Context::$user_conf->passwordHash,
 					'csrf' => false,
 				]);
@@ -195,7 +195,7 @@ class FreshRSS_auth_Controller extends FreshRSS_ActionController {
 			unset($password);
 			if ($ok) {
 				Minz_Session::_params([
-					'currentUser' => $username,
+					Minz_User::CURRENT_USER => $username,
 					'passwordHash' => $s,
 					'csrf' => false,
 				]);

+ 1 - 1
app/Controllers/importExportController.php

@@ -586,7 +586,7 @@ class FreshRSS_importExport_Controller extends FreshRSS_ActionController {
 			);
 		}
 
-		$username = Minz_Session::param('currentUser');
+		$username = Minz_User::name();
 		$export_service = new FreshRSS_Export_Service($username);
 
 		$export_opml = Minz_Request::param('export_opml', false);

+ 5 - 5
app/Controllers/userController.php

@@ -68,7 +68,7 @@ class FreshRSS_user_Controller extends FreshRSS_ActionController {
 			));
 
 			if ($ok) {
-				$isSelfUpdate = Minz_Session::param('currentUser', '_') === $username;
+				$isSelfUpdate = Minz_User::name() === $username;
 				if ($passwordPlain == '' || !$isSelfUpdate) {
 					Minz_Request::good(_t('feedback.user.updated', $username), array('c' => 'user', 'a' => 'manage'));
 				} else {
@@ -124,7 +124,7 @@ class FreshRSS_user_Controller extends FreshRSS_ActionController {
 			}
 
 			$ok = self::updateUser(
-				Minz_Session::param('currentUser'),
+				Minz_User::name(),
 				$email,
 				$passwordPlain,
 				array(
@@ -359,7 +359,7 @@ class FreshRSS_user_Controller extends FreshRSS_ActionController {
 			if ($ok && !FreshRSS_Auth::hasAccess('admin')) {
 				$user_conf = get_user_configuration($new_user_name);
 				Minz_Session::_params([
-					'currentUser' => $new_user_name,
+					Minz_User::CURRENT_USER => $new_user_name,
 					'passwordHash' => $user_conf->passwordHash,
 					'csrf' => false,
 				]);
@@ -487,7 +487,7 @@ class FreshRSS_user_Controller extends FreshRSS_ActionController {
 			Minz_Error::error(404);
 		}
 
-		$username = Minz_Session::param('currentUser', '_');
+		$username = Minz_User::name();
 		$user_config = FreshRSS_Context::$user_conf;
 
 		if ($user_config->email_validation_token === '') {
@@ -524,7 +524,7 @@ class FreshRSS_user_Controller extends FreshRSS_ActionController {
 	 */
 	public function deleteAction() {
 		$username = Minz_Request::param('username');
-		$self_deletion = Minz_Session::param('currentUser', '_') === $username;
+		$self_deletion = Minz_User::name() === $username;
 
 		if (!FreshRSS_Auth::hasAccess('admin') && !$self_deletion) {
 			Minz_Error::error(403);

+ 8 - 8
app/Models/Auth.php

@@ -21,11 +21,11 @@ class FreshRSS_Auth {
 		}
 
 		self::$login_ok = Minz_Session::param('loginOk', false);
-		$current_user = Minz_Session::param('currentUser', '');
-		if ($current_user == '') {
+		$current_user = Minz_User::name();
+		if ($current_user === null) {
 			$current_user = FreshRSS_Context::$system_conf->default_user;
 			Minz_Session::_params([
-				'currentUser' => $current_user,
+				Minz_User::CURRENT_USER => $current_user,
 				'csrf' => false,
 			]);
 		}
@@ -58,7 +58,7 @@ class FreshRSS_Auth {
 			if (isset($credentials[1])) {
 				$current_user = trim($credentials[0]);
 				Minz_Session::_params([
-					'currentUser' => $current_user,
+					Minz_User::CURRENT_USER => $current_user,
 					'passwordHash' => trim($credentials[1]),
 					'csrf' => false,
 				]);
@@ -84,7 +84,7 @@ class FreshRSS_Auth {
 			}
 			if ($login_ok) {
 				Minz_Session::_params([
-					'currentUser' => $current_user,
+					Minz_User::CURRENT_USER => $current_user,
 					'csrf' => false,
 				]);
 			}
@@ -112,7 +112,7 @@ class FreshRSS_Auth {
 			self::$login_ok = Minz_Session::param('passwordHash') === FreshRSS_Context::$user_conf->passwordHash;
 			break;
 		case 'http_auth':
-			$current_user = Minz_Session::param('currentUser');
+			$current_user = Minz_User::name();
 			self::$login_ok = strcasecmp($current_user, httpAuthUser()) === 0;
 			break;
 		case 'none':
@@ -140,7 +140,7 @@ class FreshRSS_Auth {
 		if (FreshRSS_Context::$user_conf == null) {
 			return false;
 		}
-		$currentUser = Minz_Session::param('currentUser');
+		$currentUser = Minz_User::name();
 		$isAdmin = FreshRSS_Context::$user_conf->is_admin;
 		$default_user = FreshRSS_Context::$system_conf->default_user;
 		$ok = self::$login_ok;
@@ -181,7 +181,7 @@ class FreshRSS_Auth {
 		if ($username == '') {
 			$username = FreshRSS_Context::$system_conf->default_user;
 		}
-		Minz_Session::_param('currentUser', $username);
+		Minz_User::change($username);
 
 		switch (FreshRSS_Context::$system_conf->auth_type) {
 		case 'form':

+ 12 - 9
app/Models/Context.php

@@ -4,7 +4,7 @@
  * The context object handles the current configuration file and different
  * useful functions associated to the current view state.
  */
-class FreshRSS_Context {
+final class FreshRSS_Context {
 
 	/**
 	 * @var FreshRSS_UserConfiguration|null
@@ -55,7 +55,7 @@ class FreshRSS_Context {
 	/**
 	 * Initialize the context for the global system.
 	 */
-	public static function initSystem($reload = false) {
+	public static function initSystem(bool $reload = false): FreshRSS_SystemConfiguration {
 		if ($reload || FreshRSS_Context::$system_conf == null) {
 			//TODO: Keep in session what we need instead of always reloading from disk
 			FreshRSS_Context::$system_conf = FreshRSS_SystemConfiguration::init(DATA_PATH . '/config.php', FRESHRSS_PATH . '/config.default.php');
@@ -68,8 +68,9 @@ class FreshRSS_Context {
 
 	/**
 	 * Initialize the context for the current user.
+	 * @return FreshRSS_UserConfiguration|false
 	 */
-	public static function initUser($username = '', $userMustExist = true) {
+	public static function initUser(string $username = '', bool $userMustExist = true) {
 		FreshRSS_Context::$user_conf = null;
 		if (!isset($_SESSION)) {
 			Minz_Session::init('FreshRSS');
@@ -77,9 +78,9 @@ class FreshRSS_Context {
 
 		Minz_Session::lock();
 		if ($username == '') {
-			$username = Minz_Session::param('currentUser', '');
+			$username = Minz_User::name() ?? '';
 		}
-		if (($username === '_' || FreshRSS_user_Controller::checkUsername($username)) &&
+		if (($username === Minz_User::INTERNAL_USER || FreshRSS_user_Controller::checkUsername($username)) &&
 			(!$userMustExist || FreshRSS_user_Controller::userExists($username))) {
 			try {
 				//TODO: Keep in session what we need instead of always reloading from disk
@@ -88,7 +89,7 @@ class FreshRSS_Context {
 					FRESHRSS_PATH . '/config-user.default.php',
 					FreshRSS_Context::$system_conf->configurationSetter());
 
-				Minz_Session::_param('currentUser', $username);
+				Minz_User::change($username);
 			} catch (Exception $ex) {
 				Minz_Log::warning($ex->getMessage(), USERS_PATH . '/_/' . LOG_FILENAME);
 			}
@@ -96,7 +97,7 @@ class FreshRSS_Context {
 		if (FreshRSS_Context::$user_conf == null) {
 			Minz_Session::_params([
 				'loginOk' => false,
-				'currentUser' => false,
+				Minz_User::CURRENT_USER => false,
 			]);
 		}
 		Minz_Session::unlock();
@@ -212,6 +213,7 @@ class FreshRSS_Context {
 	 *
 	 * If $array is true, the first item of the returned value is 'f' or 'c' and
 	 * the second is the id.
+	 * @return string|array{string,bool|int}
 	 */
 	public static function currentGet($array = false) {
 		if (self::$current_get['all']) {
@@ -239,6 +241,7 @@ class FreshRSS_Context {
 		} elseif (self::$current_get['tags']) {
 			return 'T';
 		}
+		return '';
 	}
 
 	/**
@@ -272,8 +275,8 @@ class FreshRSS_Context {
 	/**
 	 * @return bool true if $get parameter correspond to the $current_get attribute.
 	 */
-	public static function isCurrentGet($get): bool {
-		$type = $get[0];
+	public static function isCurrentGet(string $get): bool {
+		$type = substr($get, 0, 1);
 		$id = substr($get, 2);
 
 		switch($type) {

+ 1 - 1
app/Models/Feed.php

@@ -1011,7 +1011,7 @@ class FreshRSS_Feed extends Minz_Model {
 				Minz_Log::debug($text);
 				Minz_Log::debug($text, PSHB_LOG);
 			}
-			$currentUser = Minz_Session::param('currentUser');
+			$currentUser = Minz_User::name();
 			if (FreshRSS_user_Controller::checkUsername($currentUser) && !file_exists($path . '/' . $currentUser . '.txt')) {
 				touch($path . '/' . $currentUser . '.txt');
 			}

+ 10 - 4
app/Models/LogDAO.php

@@ -1,9 +1,15 @@
 <?php
 
 class FreshRSS_LogDAO {
-	public static function lines() {
+
+	private static function logPath(): string {
+		return USERS_PATH . '/' . (Minz_User::name() ?? Minz_User::INTERNAL_USER) . '/' . LOG_FILENAME;
+	}
+
+	/** @return array<FreshRSS_Log> */
+	public static function lines(): array {
 		$logs = array();
-		$handle = @fopen(join_path(DATA_PATH, 'users', Minz_Session::param('currentUser', '_'), LOG_FILENAME), 'r');
+		$handle = @fopen(self::logPath(), 'r');
 		if ($handle) {
 			while (($line = fgets($handle)) !== false) {
 				if (preg_match('/^\[([^\[]+)\] \[([^\[]+)\] --- (.*)$/', $line, $matches)) {
@@ -19,8 +25,8 @@ class FreshRSS_LogDAO {
 		return array_reverse($logs);
 	}
 
-	public static function truncate() {
-		file_put_contents(join_path(DATA_PATH, 'users', Minz_Session::param('currentUser', '_'), LOG_FILENAME), '');
+	public static function truncate(): void {
+		file_put_contents(self::logPath(), '');
 		if (FreshRSS_Auth::hasAccess('admin')) {
 			file_put_contents(ADMIN_LOG, '');
 			file_put_contents(API_LOG, '');

+ 1 - 1
app/Models/UserDAO.php

@@ -44,7 +44,7 @@ class FreshRSS_UserDAO extends Minz_ModelPdo {
 
 	public static function touch($username = '') {
 		if (!FreshRSS_user_Controller::checkUsername($username)) {
-			$username = Minz_Session::param('currentUser', '_');
+			$username = Minz_User::name() ?? Minz_User::INTERNAL_USER;
 		}
 		return touch(USERS_PATH . '/' . $username . '/config.php');
 	}

+ 3 - 3
app/install.php

@@ -77,7 +77,7 @@ function saveStep1() {
 		Minz_Session::_params([
 				'title' => FreshRSS_Context::$system_conf->title,
 				'auth_type' => FreshRSS_Context::$system_conf->auth_type,
-				'default_user' => Minz_Session::param('currentUser'),
+				'default_user' => Minz_User::name(),
 				'passwordHash' => FreshRSS_Context::$user_conf->passwordHash,
 				'bd_type' => FreshRSS_Context::$system_conf->db['type'],
 				'bd_host' => FreshRSS_Context::$system_conf->db['host'],
@@ -164,9 +164,9 @@ function saveStep2() {
 
 		$ok = false;
 		try {
-			Minz_Session::_param('currentUser', $config_array['default_user']);
+			Minz_User::change($config_array['default_user']);
 			$error = initDb();
-			Minz_Session::_param('currentUser');
+			Minz_User::change();
 			if ($error != '') {
 				Minz_Session::_param('bd_error', $error);
 			} else {

+ 1 - 1
app/layout/aside_configure.phtml

@@ -3,7 +3,7 @@
 
 	<ul>
 		<li class="item nav-section">
-			<div class="item nav-header"><?= _t('gen.menu.account') ?>: <?= htmlspecialchars(Minz_Session::param('currentUser', '_'), ENT_NOQUOTES, 'UTF-8')?></div>
+			<div class="item nav-header"><?= _t('gen.menu.account') ?>: <?= htmlspecialchars(Minz_User::name() ?? '', ENT_NOQUOTES, 'UTF-8')?></div>
 			<ul>
 				<li class="item<?= Minz_Request::controllerName() === 'user' && Minz_Request::actionName() === 'profile' ? ' active' : '' ?>">
 					<a href="<?= _url('user', 'profile') ?>"><?= _t('gen.menu.user_profile') ?></a>

+ 2 - 2
app/layout/header.phtml

@@ -55,14 +55,14 @@
 
 				<li class="item dropdown-section">
 					<div class="dropdown-section-title">
-						<?= _t('gen.menu.account') ?>: <?= htmlspecialchars(Minz_Session::param('currentUser', '_'), ENT_NOQUOTES, 'UTF-8') ?>
+						<?= _t('gen.menu.account') ?>: <?= htmlspecialchars(Minz_User::name() ?? '', ENT_NOQUOTES, 'UTF-8') ?>
 					</div>
 					<ul>
 						<li class="item"><a href="<?= _url('user', 'profile') ?>"><?= _t('gen.menu.user_profile') ?></a></li>
 						<?php if (FreshRSS_Auth::accessNeedsAction()): ?>
 						<li class="item"><a class="signout" href="<?= _url('auth', 'logout') ?>"><?= _t('gen.auth.logout'); ?><?= _i('logout') ?></a></li>
 						<?php else: ?>
-						<li class="item"><span class="signout">(<?= htmlspecialchars(Minz_Session::param('currentUser', '_'), ENT_NOQUOTES, 'UTF-8') ?>)</span></li>
+						<li class="item"><span class="signout">(<?= htmlspecialchars(Minz_User::name() ?? '', ENT_NOQUOTES, 'UTF-8') ?>)</span></li>
 						<?php endif; ?>
 					</ul>
 				</li>

+ 3 - 3
app/layout/nav_menu.phtml

@@ -57,10 +57,10 @@
 							<?php $state = Minz_Request::param('state', ''); ?>
 							<?php if ($state != '') { ?>
 							<input type="hidden" name="state" value="<?= $state ?>" />
-							<?php } ?>	
+							<?php } ?>
 
 							<div class="stick search">
-								<input type="search" name="search" 
+								<input type="search" name="search"
 									value="<?= htmlspecialchars(htmlspecialchars_decode(FreshRSS_Context::$search, ENT_QUOTES), ENT_COMPAT, 'UTF-8'); ?>"
 									placeholder="<?= _t('gen.menu.search') ?>" title="<?= _t('gen.menu.search') ?>" /><button class="btn" type="submit" title="<?= _t('index.menu.search_short') ?>"><?= _i('search') ?></button>
 							</div>
@@ -209,7 +209,7 @@
 		<?php
 			$url_output['a'] = 'rss';
 			if (FreshRSS_Context::$user_conf->token) {
-				$url_output['params']['user'] = Minz_Session::param('currentUser');
+				$url_output['params']['user'] = Minz_User::name();
 				$url_output['params']['token'] = FreshRSS_Context::$user_conf->token;
 			}
 			if (FreshRSS_Context::$user_conf->since_hours_posts_per_rss) {

+ 1 - 1
app/layout/simple.phtml

@@ -46,7 +46,7 @@
 			<?php if (FreshRSS_Auth::accessNeedsAction()) { ?>
 				<a class="signout" href="<?= _url('auth', 'logout') ?>">
 					<?= _i('logout') . _t('gen.auth.logout') ?>
-					(<?= htmlspecialchars(Minz_Session::param('currentUser', '_'), ENT_NOQUOTES, 'UTF-8') ?>)
+					(<?= htmlspecialchars(Minz_User::name() ?? '', ENT_NOQUOTES, 'UTF-8') ?>)
 				</a>
 			<?php } ?>
 		</div>

+ 1 - 1
app/views/helpers/export/articles.phtml

@@ -1,6 +1,6 @@
 <?php
 /** @var FreshRSS_View $this */
-$username = Minz_Session::param('currentUser', '_');
+$username = Minz_User::name() ?? Minz_User::INTERNAL_USER;
 
 $options = JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE;
 

+ 3 - 3
app/views/user/profile.phtml

@@ -17,7 +17,7 @@
 		<div class="form-group">
 			<label class="group-name" for="current_user"><?= _t('conf.user.current') ?></label>
 			<div class="group-controls">
-				<input id="current_user" type="text" disabled="disabled" value="<?= Minz_Session::param('currentUser', '_') ?>" />
+				<input id="current_user" type="text" disabled="disabled" value="<?= Minz_User::name() ?>" />
 			</div>
 		</div>
 
@@ -59,7 +59,7 @@
 			<div class="group-controls">
 				<input type="text" id="token" name="token" value="<?= $token ?>" placeholder="<?= _t('gen.short.blank_to_disable') ?>" data-leave-validation="<?= $token ?>"/>
 				<p class="help"><?= _i('help') ?> <?= _t('admin.auth.token_help') ?></p>
-				<kbd><?= Minz_Url::display(array('a' => 'rss', 'params' => array('user' => Minz_Session::param('currentUser'),
+				<kbd><?= Minz_Url::display(array('a' => 'rss', 'params' => array('user' => Minz_User::name(),
 					'token' => $token, 'hours' => FreshRSS_Context::$user_conf->since_hours_posts_per_rss)), 'html', true) ?></kbd>
 			</div>
 		</div>
@@ -127,7 +127,7 @@
 					));
 				?>
 				<input type="hidden" name="r" value="<?= $redirect_url ?>" />
-				<input type="hidden" name="username" id="username" value="<?= Minz_Session::param('currentUser', '_') ?>" />
+				<input type="hidden" name="username" id="username" value="<?= Minz_User::name() ?>" />
 				<button type="submit" class="btn btn-attention confirm"><?= _t('gen.action.remove') ?></button>
 			</div>
 		</div>

+ 1 - 2
cli/do-install.php

@@ -95,8 +95,7 @@ if (function_exists('opcache_reset')) {
 }
 
 FreshRSS_Context::initSystem(true);
-
-Minz_Session::_param('currentUser', '_');	//Default user
+Minz_User::change(Minz_User::INTERNAL_USER);
 
 $ok = false;
 try {

+ 18 - 17
constants.php

@@ -2,25 +2,26 @@
 //NB: Do not edit; use ./constants.local.php instead.
 
 //<Not customisable>
-define('FRESHRSS_MIN_PHP_VERSION', '7.2.0');
-define('FRESHRSS_VERSION', '1.21.1-dev');
-define('FRESHRSS_WEBSITE', 'https://freshrss.org');
-define('FRESHRSS_WIKI', 'https://freshrss.github.io/FreshRSS/');
-
-define('APP_NAME', 'FreshRSS');
-
-define('FRESHRSS_PATH', __DIR__);
-define('PUBLIC_PATH', FRESHRSS_PATH . '/p');
-define('PUBLIC_TO_INDEX_PATH', '/i');
-define('INDEX_PATH', PUBLIC_PATH . PUBLIC_TO_INDEX_PATH);
-define('PUBLIC_RELATIVE', '..');
-define('LIB_PATH', FRESHRSS_PATH . '/lib');
-define('APP_PATH', FRESHRSS_PATH . '/app');
-define('I18N_PATH', APP_PATH . '/i18n');
-define('CORE_EXTENSIONS_PATH', LIB_PATH . '/core-extensions');
-define('TESTS_PATH', FRESHRSS_PATH . '/tests');
+const FRESHRSS_MIN_PHP_VERSION = '7.2.0';
+const FRESHRSS_VERSION = '1.21.1-dev';
+const FRESHRSS_WEBSITE = 'https://freshrss.org';
+const FRESHRSS_WIKI = 'https://freshrss.github.io/FreshRSS/';
+
+const APP_NAME = 'FreshRSS';
+
+const FRESHRSS_PATH = __DIR__;
+const PUBLIC_PATH = FRESHRSS_PATH . '/p';
+const PUBLIC_TO_INDEX_PATH = '/i';
+const INDEX_PATH = PUBLIC_PATH . PUBLIC_TO_INDEX_PATH;
+const PUBLIC_RELATIVE = '..';
+const LIB_PATH = FRESHRSS_PATH . '/lib';
+const APP_PATH = FRESHRSS_PATH . '/app';
+const I18N_PATH = APP_PATH . '/i18n';
+const CORE_EXTENSIONS_PATH = LIB_PATH . '/core-extensions';
+const TESTS_PATH = FRESHRSS_PATH . '/tests';
 //</Not customisable>
 
+
 if (file_exists(__DIR__ . '/constants.local.php')) {
 	//Include custom / local settings:
 	include(__DIR__ . '/constants.local.php');

+ 3 - 3
lib/Minz/Extension.php

@@ -155,7 +155,7 @@ abstract class Minz_Extension {
 			$file_name_url = urlencode("{$dir}/static/{$filename}");
 			$mtime = @filemtime("{$this->path}/static/{$filename}");
 		} else {
-			$username = Minz_Session::param('currentUser');
+			$username = Minz_User::name();
 			$path = USERS_PATH . "/{$username}/{$this->config_key}/{$this->getName()}/{$filename}";
 			$file_name_url = urlencode("{$username}/{$this->config_key}/{$this->getName()}/{$filename}");
 			$mtime = @filemtime($path);
@@ -343,7 +343,7 @@ abstract class Minz_Extension {
 	}
 
 	public function saveFile(string $filename, string $content) {
-		$username = Minz_Session::param('currentUser');
+		$username = Minz_User::name();
 		$path = USERS_PATH . "/{$username}/{$this->config_key}/{$this->getName()}";
 
 		if (!file_exists($path)) {
@@ -354,7 +354,7 @@ abstract class Minz_Extension {
 	}
 
 	public function removeFile(string $filename) {
-		$username = Minz_Session::param('currentUser');
+		$username = Minz_User::name();
 		$path = USERS_PATH . "/{$username}/{$this->config_key}/{$this->getName()}/{$filename}";
 
 		if (file_exists($path)) {

+ 1 - 6
lib/Minz/Log.php

@@ -31,14 +31,9 @@ class Minz_Log {
 		}
 
 		if (! ($env === 'silent' || ($env === 'production' && ($level >= LOG_NOTICE)))) {
-			$username = Minz_Session::param('currentUser', '');
-			if ($username == '') {
-				$username = '_';
-			}
+			$username = Minz_User::name() ?? Minz_User::INTERNAL_USER;
 			if ($file_name == null) {
 				$file_name = join_path(USERS_PATH, $username, LOG_FILENAME);
-			} else {
-				$username = '_';
 			}
 
 			switch ($level) {

+ 1 - 1
lib/Minz/ModelPdo.php

@@ -103,7 +103,7 @@ class Minz_ModelPdo {
 	 */
 	public function __construct($currentUser = null, $currentPdo = null) {
 		if ($currentUser === null) {
-			$currentUser = Minz_Session::param('currentUser');
+			$currentUser = Minz_User::name();
 		}
 		if ($currentPdo !== null) {
 			$this->pdo = $currentPdo;

+ 27 - 0
lib/Minz/User.php

@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * The Minz_User class handles the user information.
+ */
+final class Minz_User {
+
+	public const INTERNAL_USER = '_';
+
+	public const CURRENT_USER = 'currentUser';
+
+	/**
+	 * @return string the name of the current user, or null if there is none
+	 */
+	public static function name(): ?string {
+		$currentUser = trim(Minz_Session::param(Minz_User::CURRENT_USER, ''));
+		return $currentUser === '' ? null : $currentUser;
+	}
+
+	/**
+	 * @param string $name the name of the new user. Set to empty string to clear the user.
+	 */
+	public static function change(string $name = ''): void {
+		$name = trim($name);
+		Minz_Session::_param(Minz_User::CURRENT_USER, $name === '' ? false : $name);
+	}
+}

+ 2 - 2
lib/lib_rss.php

@@ -547,7 +547,7 @@ function uTimeString(): string {
 function invalidateHttpCache(string $username = ''): bool {
 	if (!FreshRSS_user_Controller::checkUsername($username)) {
 		Minz_Session::_param('touch', uTimeString());
-		$username = Minz_Session::param('currentUser', '_');
+		$username = Minz_User::name() ?? Minz_User::INTERNAL_USER;
 	}
 	$ok = @touch(DATA_PATH . '/users/' . $username . '/' . LOG_FILENAME);
 	//if (!$ok) {
@@ -564,7 +564,7 @@ function listUsers(): array {
 	$base_path = join_path(DATA_PATH, 'users');
 	$dir_list = array_values(array_diff(
 		scandir($base_path) ?: [],
-		['..', '.', '_']
+		['..', '.', Minz_User::INTERNAL_USER]
 	));
 	foreach ($dir_list as $file) {
 		if ($file[0] !== '.' && is_dir(join_path($base_path, $file)) && file_exists(join_path($base_path, $file, 'config.php'))) {

+ 2 - 2
p/api/fever.php

@@ -153,7 +153,7 @@ final class FeverAPI
 			throw new FreshRSS_Context_Exception('System configuration not initialised!');
 		}
 		FreshRSS_Context::$user_conf = null;
-		Minz_Session::_param('currentUser');
+		Minz_User::change();
 		$feverKey = empty($_POST['api_key']) ? '' : substr(trim($_POST['api_key']), 0, 128);
 		if (ctype_xdigit($feverKey)) {
 			$feverKey = strtolower($feverKey);
@@ -171,7 +171,7 @@ final class FeverAPI
 				}
 				Minz_Log::error('Fever API: Reset API password for user: ' . $username, API_LOG);
 				Minz_Log::error('Fever API: Please reset your API password!');
-				Minz_Session::_param('currentUser');
+				Minz_User::change();
 			}
 			Minz_Log::warning('Fever API: wrong credentials! ' . $feverKey, API_LOG);
 		}

+ 11 - 11
p/api/greader.php

@@ -231,10 +231,10 @@ final class GReaderAPI {
 	private static function token(?FreshRSS_UserConfiguration $conf) {
 		//http://blog.martindoms.com/2009/08/15/using-the-google-reader-api-part-1/
 		//https://github.com/ericmann/gReader-Library/blob/master/greader.class.php
-		if ($conf == null || FreshRSS_Context::$system_conf == null) {
+		$user = Minz_User::name();
+		if ($user === null || $conf === null || FreshRSS_Context::$system_conf === null) {
 			self::unauthorized();
 		}
-		$user = Minz_Session::param('currentUser', '_');
 		//Minz_Log::debug('token('. $user . ')', API_LOG);	//TODO: Implement real token that expires
 		$token = str_pad(sha1(FreshRSS_Context::$system_conf->salt . $user . $conf->apiPasswordHash), 57, 'Z');	//Must have 57 characters
 		echo $token, "\n";
@@ -243,11 +243,11 @@ final class GReaderAPI {
 
 	private static function checkToken(?FreshRSS_UserConfiguration $conf, string $token): bool {
 		//http://code.google.com/p/google-reader-api/wiki/ActionToken
-		if ($conf == null || FreshRSS_Context::$system_conf == null) {
+		$user = Minz_User::name();
+		if ($user === null || $conf === null || FreshRSS_Context::$system_conf === null) {
 			self::unauthorized();
 		}
-		$user = Minz_Session::param('currentUser', '_');
-		if ($user !== '_' && (	//TODO: Check security consequences
+		if ($user !== Minz_User::INTERNAL_USER && (	//TODO: Check security consequences
 			$token === '' || //FeedMe
 			$token === 'x')) { //Reeder
 			return true;
@@ -265,7 +265,7 @@ final class GReaderAPI {
 		if (FreshRSS_Context::$user_conf == null) {
 			self::unauthorized();
 		}
-		$user = Minz_Session::param('currentUser', '_');
+		$user = Minz_User::name();
 		exit(json_encode(array(
 				'userId' => $user,
 				'userName' => $user,
@@ -310,7 +310,7 @@ final class GReaderAPI {
 
 	/** @return never */
 	private static function subscriptionExport() {
-		$user = '' . Minz_Session::param('currentUser', '_');
+		$user = Minz_User::name() ?? Minz_User::INTERNAL_USER;
 		$export_service = new FreshRSS_Export_Service($user);
 		[$filename, $content] = $export_service->generateOpml();
 		header('Content-Type: application/xml; charset=UTF-8');
@@ -321,7 +321,7 @@ final class GReaderAPI {
 
 	/** @return never */
 	private static function subscriptionImport(string $opml) {
-		$user = '' . Minz_Session::param('currentUser', '_');
+		$user = Minz_User::name() ?? Minz_User::INTERNAL_USER;
 		$importService = new FreshRSS_Import_Service($user);
 		$importService->importOpml($opml);
 		if ($importService->lastStatus()) {
@@ -390,7 +390,7 @@ final class GReaderAPI {
 			if (strpos($add, 'user/-/label/') === 0) {
 				$c_name = substr($add, 13);
 			} else {
-				$user = Minz_Session::param('currentUser', '_');
+				$user = Minz_User::name();
 				$prefix = 'user/' . $user . '/label/';
 				if (strpos($add, $prefix) === 0) {
 					$c_name = substr($add, strlen($prefix));
@@ -840,7 +840,7 @@ final class GReaderAPI {
 				if (strpos($a, 'user/-/label/') === 0) {
 					$tagName = substr($a, 13);
 				} else {
-					$user = Minz_Session::param('currentUser', '_');
+					$user = Minz_User::name() ?? '';
 					$prefix = 'user/' . $user . '/label/';
 					if (strpos($a, $prefix) === 0) {
 						$tagName = substr($a, strlen($prefix));
@@ -1023,7 +1023,7 @@ final class GReaderAPI {
 				self::clientLogin($_REQUEST['Email'], $_REQUEST['Passwd']);
 			}
 		} elseif (isset($pathInfos[3], $pathInfos[4]) && $pathInfos[1] === 'reader' && $pathInfos[2] === 'api' && $pathInfos[3] === '0') {
-			if (Minz_Session::param('currentUser', '') == '') {
+			if (Minz_User::name() === null) {
 				self::unauthorized();
 			}
 			$timestamp = isset($_GET['ck']) ? (int)$_GET['ck'] : 0;	//ck=[unix timestamp] : Use the current Unix time here, helps Google with caching.

+ 2 - 2
p/i/index.php

@@ -33,8 +33,8 @@ if (!file_exists($applied_migrations_path)) {
 
 	if (!file_exists(DATA_PATH . '/no-cache.txt')) {
 		require(LIB_PATH . '/http-conditional.php');
-		$currentUser = Minz_Session::param('currentUser', '');
-		$dateLastModification = $currentUser === '' ? time() : max(
+		$currentUser = Minz_User::name();
+		$dateLastModification = $currentUser === null ? time() : max(
 			@filemtime(USERS_PATH . '/' . $currentUser . '/' . LOG_FILENAME),
 			@filemtime(DATA_PATH . '/config.php')
 		);

+ 1 - 1
tests/bootstrap.php

@@ -3,7 +3,7 @@
 error_reporting(E_ALL);
 ini_set('display_errors', 1);
 
-define('COPY_LOG_TO_SYSLOG', false);
+const COPY_LOG_TO_SYSLOG = false;
 
 require(__DIR__ . '/../constants.php');
 require(LIB_PATH . '/lib_rss.php');	//Includes class autoloader