]> git.immae.eu Git - github/shaarli/Shaarli.git/blobdiff - index.php
Refactor PHP session handling during login/logout
[github/shaarli/Shaarli.git] / index.php
index bd34c0cd05aeab499d26fc8b650218544adf53b1..347852090cc9e7720dac72bd38b92d8be5e05917 100644 (file)
--- a/index.php
+++ b/index.php
@@ -101,8 +101,6 @@ if (dirname($_SERVER['SCRIPT_NAME']) != '/') {
 // Set default cookie expiration and path.
 session_set_cookie_params($cookie['lifetime'], $cookiedir, $_SERVER['SERVER_NAME']);
 // Set session parameters on server side.
-// If the user does not access any page within this time, his/her session is considered expired.
-define('INACTIVITY_TIMEOUT', 3600); // in seconds.
 // Use cookies to store session.
 ini_set('session.use_cookies', 1);
 // Force cookies for session (phpsessionID forbidden in URL).
@@ -183,11 +181,12 @@ define('STAY_SIGNED_IN_TOKEN', sha1($conf->get('credentials.hash') . $_SERVER['R
 /**
  * Checking session state (i.e. is the user still logged in)
  *
- * @param ConfigManager $conf The configuration manager.
+ * @param ConfigManager  $conf           Configuration Manager instance.
+ * @param SessionManager $sessionManager SessionManager instance
  *
- * @return bool: true if the user is logged in, false otherwise.
+ * @return bool true if the user is logged in, false otherwise.
  */
-function setup_login_state($conf)
+function setup_login_state($conf, $sessionManager)
 {
     if ($conf->get('security.open_shaarli')) {
         return true;
@@ -198,27 +197,26 @@ function setup_login_state($conf)
         $userIsLoggedIn = false;  // Shaarli is not configured yet.
         $loginFailure = true;
     }
-    if (isset($_COOKIE['shaarli_staySignedIn']) &&
-        $_COOKIE['shaarli_staySignedIn']===STAY_SIGNED_IN_TOKEN &&
-        !$loginFailure)
-    {
-        fillSessionInfo($conf);
+    if (isset($_COOKIE[SessionManager::$LOGGED_IN_COOKIE])
+        && $_COOKIE[SessionManager::$LOGGED_IN_COOKIE] === STAY_SIGNED_IN_TOKEN
+        && !$loginFailure
+    {
+        $sessionManager->storeLoginInfo($_SERVER);
         $userIsLoggedIn = true;
     }
     // If session does not exist on server side, or IP address has changed, or session has expired, logout.
     if (empty($_SESSION['uid'])
-        || ($conf->get('security.session_protection_disabled') === false && $_SESSION['ip'] != allIPs())
+        || ($conf->get('security.session_protection_disabled') === false && $_SESSION['ip'] != client_ip_id($_SERVER))
         || time() >= $_SESSION['expires_on'])
     {
-        logout();
+        $sessionManager->logout(WEB_PATH);
         $userIsLoggedIn = false;
         $loginFailure = true;
     }
     if (!empty($_SESSION['longlastingsession'])) {
         $_SESSION['expires_on']=time()+$_SESSION['longlastingsession']; // In case of "Stay signed in" checked.
-    }
-    else {
-        $_SESSION['expires_on']=time()+INACTIVITY_TIMEOUT; // Standard session expiration date.
+    } else {
+        $_SESSION['expires_on'] = time() + $sessionManager::$INACTIVITY_TIMEOUT;
     }
     if (!$loginFailure) {
         $userIsLoggedIn = true;
@@ -226,49 +224,28 @@ function setup_login_state($conf)
 
     return $userIsLoggedIn;
 }
-$userIsLoggedIn = setup_login_state($conf);
+
+$userIsLoggedIn = setup_login_state($conf, $sessionManager);
 
 // ------------------------------------------------------------------------------------------
 // Session management
 
-// Returns the IP address of the client (Used to prevent session cookie hijacking.)
-function allIPs()
-{
-    $ip = $_SERVER['REMOTE_ADDR'];
-    // Then we use more HTTP headers to prevent session hijacking from users behind the same proxy.
-    if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { $ip=$ip.'_'.$_SERVER['HTTP_X_FORWARDED_FOR']; }
-    if (isset($_SERVER['HTTP_CLIENT_IP'])) { $ip=$ip.'_'.$_SERVER['HTTP_CLIENT_IP']; }
-    return $ip;
-}
-
-/**
- * Load user session.
- *
- * @param ConfigManager $conf Configuration Manager instance.
- */
-function fillSessionInfo($conf)
-{
-    $_SESSION['uid'] = sha1(uniqid('',true).'_'.mt_rand()); // Generate unique random number (different than phpsessionid)
-    $_SESSION['ip']=allIPs();                // We store IP address(es) of the client to make sure session is not hijacked.
-    $_SESSION['username']= $conf->get('credentials.login');
-    $_SESSION['expires_on']=time()+INACTIVITY_TIMEOUT;  // Set session expiration.
-}
-
 /**
  * Check that user/password is correct.
  *
- * @param string        $login    Username
- * @param string        $password User password
- * @param ConfigManager $conf     Configuration Manager instance.
+ * @param string         $login          Username
+ * @param string         $password       User password
+ * @param ConfigManager  $conf           Configuration Manager instance.
+ * @param SessionManager $sessionManager SessionManager instance
  *
  * @return bool: authentication successful or not.
  */
-function check_auth($login, $password, $conf)
+function check_auth($login, $password, $conf, $sessionManager)
 {
     $hash = sha1($password . $login . $conf->get('credentials.salt'));
-    if ($login == $conf->get('credentials.login') && $hash == $conf->get('credentials.hash'))
-    {   // Login/password is correct.
-        fillSessionInfo($conf);
+    if ($login == $conf->get('credentials.login') && $hash == $conf->get('credentials.hash')) {
+        // Login/password is correct.
+        $sessionManager->storeLoginInfo($_SERVER);
         logm($conf->get('resource.log'), $_SERVER['REMOTE_ADDR'], 'Login successful');
         return true;
     }
@@ -283,28 +260,15 @@ function isLoggedIn()
     return $userIsLoggedIn;
 }
 
-// Force logout.
-function logout() {
-    if (isset($_SESSION)) {
-        unset($_SESSION['uid']);
-        unset($_SESSION['ip']);
-        unset($_SESSION['username']);
-        unset($_SESSION['visibility']);
-        unset($_SESSION['untaggedonly']);
-    }
-    setcookie('shaarli_staySignedIn', FALSE, 0, WEB_PATH);
-}
-
 // ------------------------------------------------------------------------------------------
 // Process login form: Check if login/password is correct.
-if (isset($_POST['login']))
-{
+if (isset($_POST['login'])) {
     if (! $loginManager->canLogin($_SERVER)) {
         die(t('I said: NO. You are banned for the moment. Go away.'));
     }
     if (isset($_POST['password'])
         && $sessionManager->checkToken($_POST['token'])
-        && (check_auth($_POST['login'], $_POST['password'], $conf))
+        && (check_auth($_POST['login'], $_POST['password'], $conf, $sessionManager))
     ) {
         // Login/password is OK.
         $loginManager->handleSuccessfulLogin($_SERVER);
@@ -313,10 +277,13 @@ if (isset($_POST['login']))
         if (!empty($_POST['longlastingsession'])) {
             $_SESSION['longlastingsession'] = 31536000; // (31536000 seconds = 1 year)
             $expiration = time() + $_SESSION['longlastingsession']; // calculate relative cookie expiration (1 year from now)
-            setcookie('shaarli_staySignedIn', STAY_SIGNED_IN_TOKEN, $expiration, WEB_PATH);
+            setcookie($sessionManager::$LOGGED_IN_COOKIE, STAY_SIGNED_IN_TOKEN, $expiration, WEB_PATH);
             $_SESSION['expires_on'] = $expiration;  // Set session expiration on server-side.
 
-            $cookiedir = ''; if(dirname($_SERVER['SCRIPT_NAME'])!='/') $cookiedir=dirname($_SERVER["SCRIPT_NAME"]).'/';
+            $cookiedir = '';
+            if (dirname($_SERVER['SCRIPT_NAME']) != '/') {
+                $cookiedir = dirname($_SERVER["SCRIPT_NAME"]) . '/';
+            }
             session_set_cookie_params($_SESSION['longlastingsession'],$cookiedir,$_SERVER['SERVER_NAME']); // Set session cookie expiration on client side
             // Note: Never forget the trailing slash on the cookie path!
             session_regenerate_id(true);  // Send cookie with new expiration date to browser.
@@ -686,7 +653,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
     if (isset($_SERVER['QUERY_STRING']) && startsWith($_SERVER['QUERY_STRING'], 'do=logout'))
     {
         invalidateCaches($conf->get('resource.page_cache'));
-        logout();
+        $sessionManager->logout(WEB_PATH);
         header('Location: ?');
         exit;
     }
@@ -887,7 +854,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
         if (empty($params['searchtags'])) {
             $params['searchtags'] = trim($_GET['addtag']);
         }
-        else if ($addtag) {
+        elseif ($addtag) {
             $params['searchtags'] = trim($params['searchtags']).' '.trim($_GET['addtag']);
         }
 
@@ -953,7 +920,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
             } else {
                 unset($_SESSION['visibility']);
             }
-        } else if ($_GET['visibility'] === 'public') {
+        } elseif ($_GET['visibility'] === 'public') {
             if (empty($_SESSION['visibility']) || $_SESSION['visibility'] !== 'public') {
                 // See only public links
                 $_SESSION['visibility'] = 'public';
@@ -1093,7 +1060,6 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
             $conf->set('general.title', escape($_POST['title']));
             $conf->set('general.header_link', escape($_POST['titleLink']));
             $conf->set('resource.theme', escape($_POST['theme']));
-            $conf->set('redirector.url', escape($_POST['redirector']));
             $conf->set('security.session_protection_disabled', !empty($_POST['disablesessionprotection']));
             $conf->set('privacy.default_private_links', !empty($_POST['privateLinkByDefault']));
             $conf->set('feed.rss_permalinks', !empty($_POST['enableRssPermalinks']));
@@ -1126,7 +1092,6 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
             $PAGE->assign('title', $conf->get('general.title'));
             $PAGE->assign('theme', $conf->get('resource.theme'));
             $PAGE->assign('theme_available', ThemeUtils::getThemes($conf->get('resource.raintpl_tpl')));
-            $PAGE->assign('redirector', $conf->get('redirector.url'));
             list($continents, $cities) = generateTimeZoneData(
                 timezone_identifiers_list(),
                 $conf->get('general.timezone')
@@ -1376,7 +1341,12 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
             if (empty($title) && strpos(get_url_scheme($url), 'http') !== false) {
                 // Short timeout to keep the application responsive
                 // The callback will fill $charset and $title with data from the downloaded page.
-                get_http_response($url, 25, 4194304, get_curl_download_callback($charset, $title));
+                get_http_response(
+                    $url,
+                    $conf->get('general.download_timeout', 30),
+                    $conf->get('general.download_max_size', 4194304),
+                    get_curl_download_callback($charset, $title)
+                );
                 if (! empty($title) && strtolower($charset) != 'utf-8') {
                     $title = mb_convert_encoding($title, 'utf-8', $charset);
                 }