| 1 | <?php
|
|---|
| 2 |
|
|---|
| 3 | include_once(dirname(__FILE__).'/ModuleUser.php');
|
|---|
| 4 | include_once(dirname(__FILE__).'/UserList.php');
|
|---|
| 5 | include_once(dirname(__FILE__).'/Options.php');
|
|---|
| 6 | include_once(dirname(__FILE__).'/Registration.php');
|
|---|
| 7 | include_once(dirname(__FILE__).'/Profile.php');
|
|---|
| 8 |
|
|---|
| 9 | class PageUserLogin extends Page
|
|---|
| 10 | {
|
|---|
| 11 | function Show(): string
|
|---|
| 12 | {
|
|---|
| 13 | $Output = '<form action="'.$this->System->Link('/?action=login').'" method="post" class="Form">'.
|
|---|
| 14 | '<fieldset><legend>'.T('Login').'</legend>
|
|---|
| 15 | <table>
|
|---|
| 16 | <tr>
|
|---|
| 17 | <th class="Left">'.T('Name').':</th><td><input type="text" name="LoginUser" size="13" /></td>
|
|---|
| 18 | </tr>
|
|---|
| 19 | <tr>
|
|---|
| 20 | <th class="Left">'.T('Password').':</th><td><input type="password" name="LoginPass" size="13" /></td>
|
|---|
| 21 | </tr>
|
|---|
| 22 | <tr>
|
|---|
| 23 | <th class="Left">'.T('Stay logged').':</th><td><input type="checkbox" name="StayLogged" /></td>
|
|---|
| 24 | </tr>
|
|---|
| 25 | <tr>
|
|---|
| 26 | <th class="Center"colspan="2"><input type="submit" value="'.T('Do login').'" /></th>
|
|---|
| 27 | </tr>
|
|---|
| 28 | </table>
|
|---|
| 29 | </fieldset></form>';
|
|---|
| 30 | return $Output;
|
|---|
| 31 | }
|
|---|
| 32 | }
|
|---|
| 33 |
|
|---|
| 34 | // User licence levels
|
|---|
| 35 | define('LICENCE_ANONYMOUS', -1);
|
|---|
| 36 | define('LICENCE_USER', 0);
|
|---|
| 37 | define('LICENCE_MODERATOR', 1);
|
|---|
| 38 | define('LICENCE_ADMIN', 2);
|
|---|
| 39 |
|
|---|
| 40 | class User
|
|---|
| 41 | {
|
|---|
| 42 | var $Id;
|
|---|
| 43 | public string $Name;
|
|---|
| 44 | var $Team;
|
|---|
| 45 | var $Role;
|
|---|
| 46 | var $Redirecting;
|
|---|
| 47 | var $Language;
|
|---|
| 48 | var $System;
|
|---|
| 49 | var $Database;
|
|---|
| 50 | var $OnlineStateTimeout;
|
|---|
| 51 | var $PreferredVersion = 0;
|
|---|
| 52 | public string $PreferredVersionGame;
|
|---|
| 53 | public string $Email;
|
|---|
| 54 | public string $Info;
|
|---|
| 55 |
|
|---|
| 56 | function __construct(System $System)
|
|---|
| 57 | {
|
|---|
| 58 | $this->System = &$System;
|
|---|
| 59 | $this->Database = &$System->Database;
|
|---|
| 60 | $this->OnlineStateTimeout = 600; // in seconds
|
|---|
| 61 | if (isset($_SESSION)) $this->Check();
|
|---|
| 62 | }
|
|---|
| 63 |
|
|---|
| 64 | function __destroy()
|
|---|
| 65 | {
|
|---|
| 66 | }
|
|---|
| 67 |
|
|---|
| 68 | function Login($Name, $Password, $StayLogged = false)
|
|---|
| 69 | {
|
|---|
| 70 | $SID = session_id();
|
|---|
| 71 | $DbResult = $this->Database->query('SELECT `ID` FROM `User` WHERE '.
|
|---|
| 72 | 'LOWER(`Name`) = LOWER("'.$Name.'") AND `Pass` = '.$this->CryptPasswordSQL('"'.$Password.'"', '`Salt`'));
|
|---|
| 73 | if ($DbResult->num_rows > 0)
|
|---|
| 74 | {
|
|---|
| 75 | $User = $DbResult->fetch_assoc();
|
|---|
| 76 | $this->Id = $User['ID'];
|
|---|
| 77 |
|
|---|
| 78 | // Prepare cookies for permanent login
|
|---|
| 79 | $StayLoggedSalt = $this->GetPasswordSalt();
|
|---|
| 80 | if ($StayLogged == true) $StayLoggedValue = 1; else $StayLoggedValue = 0;
|
|---|
| 81 | $this->Database->update('UserOnline', '`SessionId`="'.$SID.'"', array(
|
|---|
| 82 | 'User' => $User['ID'], 'StayLogged' => $StayLoggedValue, 'StayLoggedHash' => $StayLoggedSalt));
|
|---|
| 83 | if ($StayLogged)
|
|---|
| 84 | {
|
|---|
| 85 | setcookie('LoginUserId', $User['ID'], time() + 365 * 24 * 60 * 60);
|
|---|
| 86 | setcookie('LoginHash', sha1($User['ID'].$StayLoggedSalt), time() + 365 * 24 * 60 * 60);
|
|---|
| 87 | } else {
|
|---|
| 88 | setcookie('LoginUserId', '', time() - 3600);
|
|---|
| 89 | setcookie('LoginHash', '', time() - 3600);
|
|---|
| 90 | }
|
|---|
| 91 |
|
|---|
| 92 | $this->Database->query('UPDATE `UserTrace` SET '.
|
|---|
| 93 | '`LastLogin` = NOW(), '.
|
|---|
| 94 | '`LastIP` = "'.GetRemoteAddress().'", '.
|
|---|
| 95 | '`UserAgent` = "'.$this->System->Database->real_escape_string($_SERVER['HTTP_USER_AGENT']).'" '.
|
|---|
| 96 | ' WHERE `User` = '.$this->Id);
|
|---|
| 97 | $this->System->ModuleManager->Modules['Log']->WriteLog('Login', LOG_TYPE_USER);
|
|---|
| 98 | $this->Check();
|
|---|
| 99 | };
|
|---|
| 100 | }
|
|---|
| 101 |
|
|---|
| 102 | function Logout()
|
|---|
| 103 | {
|
|---|
| 104 | $SID = session_id();
|
|---|
| 105 | if ($this->Role != LICENCE_ANONYMOUS)
|
|---|
| 106 | {
|
|---|
| 107 | $this->Database->update('UserOnline', '`SessionId`="'.$SID.'"', array('User' => null));
|
|---|
| 108 | $this->Database->query('UPDATE `UserTrace` SET '.
|
|---|
| 109 | '`LastLogout` = NOW() WHERE `User` = '.$this->Id);
|
|---|
| 110 | $this->System->ModuleManager->Modules['Log']->WriteLog('Logout: '.$this->Name, LOG_TYPE_USER);
|
|---|
| 111 | $this->Check();
|
|---|
| 112 | }
|
|---|
| 113 | }
|
|---|
| 114 |
|
|---|
| 115 | function Load()
|
|---|
| 116 | {
|
|---|
| 117 | $DbResult = $this->Database->query('SELECT `User`.`PreferredVersion`,`User`.`ID`,`User`.`Team`,`User`.`Redirecting`,`User`.`Email`,`User`.`Info`,'.
|
|---|
| 118 | '`User`.`Language`,`User`.`Name`,`User`.`GM`,`ClientVersion`.`Version` AS `PreferredVersionGame` FROM `User` '.
|
|---|
| 119 | 'LEFT JOIN `ClientVersion` ON `ClientVersion`.`Id` = `User`.`PreferredVersion` '.
|
|---|
| 120 | 'WHERE `User`.`ID` = '.$this->Id);
|
|---|
| 121 | if ($DbResult->num_rows > 0)
|
|---|
| 122 | {
|
|---|
| 123 | $User = $DbResult->fetch_assoc();
|
|---|
| 124 | // Security: Password and Salt hash should not be loaded to variables
|
|---|
| 125 | $this->Id = $User['ID'];
|
|---|
| 126 | $this->Team = $User['Team'];
|
|---|
| 127 | $this->Redirecting = $User['Redirecting'];
|
|---|
| 128 | $this->Language = $User['Language'];
|
|---|
| 129 | $this->Name = $User['Name'];
|
|---|
| 130 | $this->Role = $User['GM'];
|
|---|
| 131 | $this->Email = $User['Email'];
|
|---|
| 132 | if ($User['Info'] != null) $this->Info = $User['Info'];
|
|---|
| 133 | else $this->Info = '';
|
|---|
| 134 | if ($User['PreferredVersionGame'] != null) $this->PreferredVersionGame = $User['PreferredVersionGame'];
|
|---|
| 135 | else $this->PreferredVersionGame = '';
|
|---|
| 136 | } else $this->SetAnonymous();
|
|---|
| 137 | }
|
|---|
| 138 |
|
|---|
| 139 | function SetAnonymous()
|
|---|
| 140 | {
|
|---|
| 141 | $this->Id = NULL;
|
|---|
| 142 | $this->Name = 'anonymous';
|
|---|
| 143 | $this->Role = LICENCE_ANONYMOUS;
|
|---|
| 144 | $this->Language = NULL;
|
|---|
| 145 | $this->Redirecting = 1;
|
|---|
| 146 | $this->Team = '';
|
|---|
| 147 | $this->Email = '';
|
|---|
| 148 | }
|
|---|
| 149 |
|
|---|
| 150 | function Licence($Licence)
|
|---|
| 151 | {
|
|---|
| 152 | if (GetRemoteAddress() == '') return true; // Execution from command line
|
|---|
| 153 | else return $this->Role >= $Licence;
|
|---|
| 154 | }
|
|---|
| 155 |
|
|---|
| 156 | function CheckToken($Licence, $Token)
|
|---|
| 157 | {
|
|---|
| 158 | $DbResult = $this->Database->select('APIToken', 'User', '`Token`="'.$Token.'"');
|
|---|
| 159 | if ($DbResult->num_rows > 0)
|
|---|
| 160 | {
|
|---|
| 161 | $DbRow = $DbResult->fetch_assoc();
|
|---|
| 162 | $DbResult2 = $this->Database->select('User', 'GM', '`ID`="'.$DbRow['User'].'"');
|
|---|
| 163 | $DbRow2 = $DbResult2->fetch_assoc();
|
|---|
| 164 | return $DbRow2['GM'] >= $Licence;
|
|---|
| 165 | } else return false;
|
|---|
| 166 | }
|
|---|
| 167 |
|
|---|
| 168 | function GetPasswordSalt()
|
|---|
| 169 | {
|
|---|
| 170 | return substr(sha1(mt_rand()), 0, 8);
|
|---|
| 171 | }
|
|---|
| 172 |
|
|---|
| 173 | function CryptPasswordSQL($Password, $Salt)
|
|---|
| 174 | {
|
|---|
| 175 | return 'SHA1(CONCAT(SHA1('.$Password.'), '.$Salt.'))';
|
|---|
| 176 | }
|
|---|
| 177 |
|
|---|
| 178 | function Check()
|
|---|
| 179 | {
|
|---|
| 180 | $SID = session_id();
|
|---|
| 181 | // Lookup user record
|
|---|
| 182 | $Query = $this->Database->select('UserOnline', '*', 'SessionId="'.$SID.'"');
|
|---|
| 183 | if ($Query->num_rows > 0)
|
|---|
| 184 | {
|
|---|
| 185 | // Refresh time of last access
|
|---|
| 186 | $this->Database->update('UserOnline', 'SessionId="'.$SID.'"', array('ActivityTime' => 'NOW()'));
|
|---|
| 187 | } else
|
|---|
| 188 | {
|
|---|
| 189 | if (GetRemoteAddress() != '') $HostName = gethostbyaddr(GetRemoteAddress());
|
|---|
| 190 | else $HostName = '';
|
|---|
| 191 | $this->Database->insert('UserOnline', array('SessionId' => $SID,
|
|---|
| 192 | 'User' => null, 'LoginTime' => 'NOW()', 'ActivityTime' => 'NOW()',
|
|---|
| 193 | 'IpAddress' => GetRemoteAddress(), 'HostName' => $HostName,
|
|---|
| 194 | 'ScriptName' => GetRequestURI(), 'StayLogged' => 0, 'StayLoggedHash' => ''));
|
|---|
| 195 | }
|
|---|
| 196 |
|
|---|
| 197 | // Logged permanently?
|
|---|
| 198 | if (array_key_exists('LoginHash', $_COOKIE))
|
|---|
| 199 | {
|
|---|
| 200 | $DbResult = $this->Database->query('SELECT * FROM `UserOnline` WHERE `User`='.$_COOKIE['LoginUserId'].
|
|---|
| 201 | ' AND `StayLogged`=1 AND SessionId!="'.$SID.'"');
|
|---|
| 202 | if ($DbResult->num_rows > 0)
|
|---|
| 203 | {
|
|---|
| 204 | $DbRow = $DbResult->fetch_assoc();
|
|---|
| 205 | if (sha1($_COOKIE['LoginUserId'].$DbRow['StayLoggedHash']) == $_COOKIE['LoginHash'])
|
|---|
| 206 | {
|
|---|
| 207 | $this->Database->query('DELETE FROM `UserOnline` WHERE `SessionId`="'.$SID.'"');
|
|---|
| 208 | $this->Database->query('UPDATE `UserOnline` SET `SessionId`="'.$SID.'" WHERE `Id`='.$DbRow['Id']);
|
|---|
| 209 | }
|
|---|
| 210 | }
|
|---|
| 211 | }
|
|---|
| 212 |
|
|---|
| 213 | // Check login
|
|---|
| 214 | $Query = $this->Database->select('UserOnline', '*', '`SessionId`="'.$SID.'"');
|
|---|
| 215 | $Row = $Query->fetch_assoc();
|
|---|
| 216 | if ($Row['User'] != '')
|
|---|
| 217 | {
|
|---|
| 218 | $this->Id = $Row['User'];
|
|---|
| 219 | $this->Load();
|
|---|
| 220 | } else
|
|---|
| 221 | {
|
|---|
| 222 | $this->SetAnonymous();
|
|---|
| 223 | }
|
|---|
| 224 |
|
|---|
| 225 | // Remove nonactive users
|
|---|
| 226 | $DbResult = $this->Database->select('UserOnline', '`Id`, `User`', '(`ActivityTime` < DATE_SUB(NOW(), INTERVAL '.$this->OnlineStateTimeout.' SECOND)) AND (`StayLogged` = 0)');
|
|---|
| 227 | while ($DbRow = $DbResult->fetch_array())
|
|---|
| 228 | {
|
|---|
| 229 | $this->Database->delete('UserOnline', 'Id='.$DbRow['Id']);
|
|---|
| 230 | }
|
|---|
| 231 | }
|
|---|
| 232 |
|
|---|
| 233 | function Register($UserName, $Password, $Email, $Language, $Team, $PreferredVersion)
|
|---|
| 234 | {
|
|---|
| 235 | $Salt = $this->GetPasswordSalt();
|
|---|
| 236 | if ($Team == null) $Team = 'NULL';
|
|---|
| 237 | if ($PreferredVersion == null) $PreferredVersion = 'NULL';
|
|---|
| 238 | $this->Database->query('INSERT INTO `User` '.
|
|---|
| 239 | '(`Name` , `Pass` , `Salt`, `Email` , `Language` , `Team` , `NeedUpdate`, `RegistrationTime`, `PreferredVersion` ) '.
|
|---|
| 240 | 'VALUES ("'.$UserName.'", '.$this->CryptPasswordSQL('"'.$Password.'"', '"'.$Salt.'"').
|
|---|
| 241 | ', "'.$Salt.'", "'.$Email.'", '.$Language.', '.$Team.', 1, NOW(), '.$PreferredVersion.')');
|
|---|
| 242 | $UserId = $this->Database->insert_id;
|
|---|
| 243 | $this->Database->query('INSERT INTO `UserTrace` (`User`, `LastIP`, `UserAgent`) '.
|
|---|
| 244 | 'VALUES ('.$UserId.', "'.GetRemoteAddress().'", '.
|
|---|
| 245 | '"'.$this->Database->real_escape_string($_SERVER['HTTP_USER_AGENT']).'")');
|
|---|
| 246 | }
|
|---|
| 247 | }
|
|---|