source: trunk/Modules/User/User.php@ 880

Last change on this file since 880 was 880, checked in by chronos, 5 years ago
  • Modified: Improved code formatting.
File size: 11.7 KB
Line 
1<?php
2
3include_once(dirname(__FILE__).'/UserList.php');
4include_once(dirname(__FILE__).'/Options.php');
5include_once(dirname(__FILE__).'/Registration.php');
6include_once(dirname(__FILE__).'/Profile.php');
7
8class ModuleUser extends AppModule
9{
10 function __construct(System $System)
11 {
12 parent::__construct($System);
13 $this->Name = 'User';
14 $this->Version = '1.1';
15 $this->Creator = 'Chronos';
16 $this->License = 'GNU/GPL';
17 $this->Description = 'User and permission management';
18 $this->Dependencies = array();
19 }
20
21 function DoStart()
22 {
23 $this->System->User = new User($this->System);
24 $this->System->RegisterPage('users', 'PageUserList');
25 $this->System->RegisterPage('options', 'PageUserOptions');
26 $this->System->RegisterPage('registration', 'PageUserRegistration');
27 $this->System->RegisterPage('user', 'PageUserProfile');
28 $this->System->RegisterPage('login', 'PageUserLogin');
29 $this->System->RegisterMenuItem(array(
30 'Title' => T('Translators'),
31 'Hint' => 'Seznam registrovaných uživatelů',
32 'Link' => $this->System->Link('/users/'),
33 'Permission' => LICENCE_ANONYMOUS,
34 'Icon' => '',
35 ), 0);
36 if (array_key_exists('Search', $this->System->ModuleManager->Modules))
37 $this->System->ModuleManager->Modules['Search']->RegisterSearch('user',
38 T('Translators'), array('Name'), '`User`', $this->System->Link('/users/?search='));
39 $this->System->RegisterPageBarItem('Top', 'User', array($this, 'TopBarCallback'));
40 $this->System->RegisterPageBarItem('Left', 'User', array($this, 'ShowOnlineList'));
41 }
42
43 function ShowOnlineList()
44 {
45 $Output = T('Online translators').':<br />';
46 $DbResult = $this->System->Database->query('SELECT * FROM ('.
47 'SELECT `User`.`Name`, `User`.`ID` FROM `UserOnline` '.
48 'JOIN `User` ON `User`.`ID` = `UserOnline`.`User` '.
49 'WHERE (`ActivityTime` >= NOW() - 300) '.
50 'ORDER BY `ActivityTime` DESC ) AS `T` GROUP BY `Name`');
51 while ($DbUser = $DbResult->fetch_assoc())
52 {
53 $Name = '<a href="'.$this->System->Link('/user/?user='.$DbUser['ID']).'">'.$DbUser['Name'].'</a>';
54 $Output .= $Name.'<br />';
55 }
56 return $Output;
57 }
58
59 function TopBarCallback()
60 {
61 $Output = '';
62 if ($this->System->User->Licence(LICENCE_USER))
63 {
64 //$DbResult =$this->Database->query('SELECT `Id`, `Name` FROM `Team` WHERE `Id`='.$this->System->User->Team);
65 //$Team = $DbResult->fetch_assoc();
66 //$Output .= ''<span class="MenuItem">Moje překlady: <a href="">Dokončené</a> <a href="">Rozpracované</a> <a href="">Exporty</a> Tým: <a href="">'.$Team['name'].'</a></span>';
67 $Output .= $this->System->User->Name.' <a href="'.$this->System->Link('/?action=logout').'">'.T('Logout').'</a>'.
68 ' <a href="'.$this->System->Link('/user/?user='.$this->System->User->Id).'">'.T('My page').'</a>'.
69 ' <a href="'.$this->System->Link('/options/').'">'.T('Options').'</a>'.
70 ' <a title="Vámi přeložené texty" href="'.$this->System->Link('/TranslationList.php?user='.
71 $this->System->User->Id.'&amp;group=0&amp;state=2&amp;text=&amp;entry=').'">'.T('Translated').'</a>'.
72 ' <a title="Vaše rozpracované text" href="'.$this->System->Link('/TranslationList.php?user='.
73 $this->System->User->Id.'&amp;group=0&amp;state=3&amp;text=&amp;entry=').'">'.T('Unfinished').'</a>'.
74 ' <a title="Nikým nepřeložené texty" href="'.
75 $this->System->Link('/TranslationList.php?user=0&amp;group=0&amp;state=1&amp;text=&amp;entry=').'">'.T('Untranslated').'</a>';
76 } else
77 {
78 $Output .= '<a href="'.$this->System->Link('/login/').'">'.T('Login').'</a>&nbsp;'.
79 '<a href="'.$this->System->Link('/registration/').'">'.T('Registration').'</a>';
80 }
81 return $Output;
82 }
83}
84
85class PageUserLogin extends Page
86{
87 function Show()
88 {
89 $Output = '<form action="'.$this->System->Link('/?action=login').'" method="post" class="Form">'.
90 '<fieldset><legend>'.T('Login').'</legend>
91 <table>
92 <tr>
93 <th class="Left">'.T('Name').':</th><td><input type="text" name="LoginUser" size="13" /></td>
94 </tr>
95 <tr>
96 <th class="Left">'.T('Password').':</th><td><input type="password" name="LoginPass" size="13" /></td>
97 </tr>
98 <tr>
99 <th class="Left">'.T('Stay logged').':</th><td><input type="checkbox" name="StayLogged" /></td>
100 </tr>
101 <tr>
102 <th class="Center"colspan="2"><input type="submit" value="'.T('Do login').'" /></th>
103 </tr>
104 </table>
105 </fieldset></form>';
106 return $Output;
107 }
108}
109
110// User licence levels
111define('LICENCE_ANONYMOUS', -1);
112define('LICENCE_USER', 0);
113define('LICENCE_MODERATOR', 1);
114define('LICENCE_ADMIN', 2);
115
116class User
117{
118 var $Id;
119 var $Name;
120 var $Team;
121 var $Role;
122 var $Redirecting;
123 var $Language;
124 var $System;
125 var $Database;
126 var $OnlineStateTimeout;
127 var $PreferredVersion = 0;
128
129 function __construct(System $System)
130 {
131 $this->System = &$System;
132 $this->Database = &$System->Database;
133 $this->OnlineStateTimeout = 600; // in seconds
134 if (isset($_SESSION)) $this->Check();
135 }
136
137 function __destroy()
138 {
139 }
140
141 function Login($Name, $Password, $StayLogged = false)
142 {
143 $SID = session_id();
144 $DbResult = $this->Database->query('SELECT `ID` FROM `User` WHERE '.
145 'LOWER(`Name`) = LOWER("'.$Name.'") AND `Pass` = '.$this->CryptPasswordSQL('"'.$Password.'"', '`Salt`'));
146 if ($DbResult->num_rows > 0)
147 {
148 $User = $DbResult->fetch_assoc();
149 $this->Id = $User['ID'];
150
151 // Prepare cookies for permanent login
152 $StayLoggedSalt = $this->GetPasswordSalt();
153 if ($StayLogged == true) $StayLoggedValue = 1; else $StayLoggedValue = 0;
154 $this->Database->update('UserOnline', '`SessionId`="'.$SID.'"', array(
155 'User' => $User['ID'], 'StayLogged' => $StayLoggedValue, 'StayLoggedHash' => $StayLoggedSalt));
156 if ($StayLogged)
157 {
158 setcookie('LoginUserId', $User['ID'], time() + 365 * 24 * 60 * 60);
159 setcookie('LoginHash', sha1($User['ID'].$StayLoggedSalt), time() + 365 * 24 * 60 * 60);
160 } else {
161 setcookie('LoginUserId', '', time() - 3600);
162 setcookie('LoginHash', '', time() - 3600);
163 }
164
165 $this->Database->query('UPDATE `UserTrace` SET '.
166 '`LastLogin` = NOW(), '.
167 '`LastIP` = "'.GetRemoteAddress().'", '.
168 '`UserAgent` = "'.$this->System->Database->real_escape_string($_SERVER['HTTP_USER_AGENT']).'" '.
169 ' WHERE `User` = '.$this->Id);
170 $this->System->ModuleManager->Modules['Log']->WriteLog('Login', LOG_TYPE_USER);
171 $this->Check();
172 };
173 }
174
175 function Logout()
176 {
177 $SID = session_id();
178 if ($this->Role != LICENCE_ANONYMOUS)
179 {
180 $this->Database->update('UserOnline', '`SessionId`="'.$SID.'"', array('User' => null));
181 $this->Database->query('UPDATE `UserTrace` SET '.
182 '`LastLogout` = NOW() WHERE `User` = '.$this->Id);
183 $this->System->ModuleManager->Modules['Log']->WriteLog('Logout: '.$this->Name, LOG_TYPE_USER);
184 $this->Check();
185 }
186 }
187
188 function Load()
189 {
190 $DbResult = $this->Database->query('SELECT `User`.`PreferredVersion`,`User`.`ID`,`User`.`Team`,`User`.`Redirecting`,`User`.`Email`,`User`.`Info`,'.
191 '`User`.`Language`,`User`.`Name`,`User`.`GM`,`ClientVersion`.`Version` AS `PreferredVersionGame` FROM `User` '.
192 'LEFT JOIN `ClientVersion` ON `ClientVersion`.`Id` = `User`.`PreferredVersion` '.
193 'WHERE `User`.`ID` = '.$this->Id);
194 if ($DbResult->num_rows > 0)
195 {
196 $User = $DbResult->fetch_assoc();
197 // Security: Password and Salt hash should not be loaded to variables
198 $this->Id = $User['ID'];
199 $this->Team = $User['Team'];
200 $this->Redirecting = $User['Redirecting'];
201 $this->Language = $User['Language'];
202 $this->Name = $User['Name'];
203 $this->Role = $User['GM'];
204 $this->Email = $User['Email'];
205 $this->Info = $User['Info'];
206 $this->PreferredVersion = $User['PreferredVersion'];
207 $this->PreferredVersionGame = $User['PreferredVersionGame'];
208 } else $this->SetAnonymous();
209 }
210
211 function SetAnonymous()
212 {
213 $this->Id = NULL;
214 $this->Name = 'anonymous';
215 $this->Role = LICENCE_ANONYMOUS;
216 $this->Language = NULL;
217 $this->Redirecting = 1;
218 $this->Team = '';
219 $this->Email = '';
220 }
221
222 function Licence($Licence)
223 {
224 if (GetRemoteAddress() == '') return true; // Execution from command line
225 else return $this->Role >= $Licence;
226 }
227
228 function CheckToken($Licence, $Token)
229 {
230 $DbResult = $this->Database->select('APIToken', 'User', '`Token`="'.$Token.'"');
231 if ($DbResult->num_rows > 0)
232 {
233 $DbRow = $DbResult->fetch_assoc();
234 $DbResult2 = $this->Database->select('User', 'GM', '`ID`="'.$DbRow['User'].'"');
235 $DbRow2 = $DbResult2->fetch_assoc();
236 return $DbRow2['GM'] >= $Licence;
237 } else return false;
238 }
239
240 function GetPasswordSalt()
241 {
242 return substr(sha1(mt_rand()), 0, 8);
243 }
244
245 function CryptPasswordSQL($Password, $Salt)
246 {
247 return 'SHA1(CONCAT(SHA1('.$Password.'), '.$Salt.'))';
248 }
249
250 function Check()
251 {
252 $SID = session_id();
253 // Lookup user record
254 $Query = $this->Database->select('UserOnline', '*', 'SessionId="'.$SID.'"');
255 if ($Query->num_rows > 0)
256 {
257 // Refresh time of last access
258 $this->Database->update('UserOnline', 'SessionId="'.$SID.'"', array('ActivityTime' => 'NOW()'));
259 } else {
260 if (GetRemoteAddress() != '') $HostName = gethostbyaddr(GetRemoteAddress());
261 else $HostName = '';
262 $this->Database->insert('UserOnline', array('SessionId' => $SID,
263 'User' => null, 'LoginTime' => 'NOW()', 'ActivityTime' => 'NOW()',
264 'IpAddress' => GetRemoteAddress(), 'HostName' => $HostName,
265 'ScriptName' => GetRequestURI(), 'StayLogged' => 0, 'StayLoggedHash' => ''));
266 }
267
268 // Logged permanently?
269 if (array_key_exists('LoginHash', $_COOKIE))
270 {
271 $DbResult = $this->Database->query('SELECT * FROM `UserOnline` WHERE `User`='.$_COOKIE['LoginUserId'].
272 ' AND `StayLogged`=1 AND SessionId!="'.$SID.'"');
273 if ($DbResult->num_rows > 0)
274 {
275 $DbRow = $DbResult->fetch_assoc();
276 if (sha1($_COOKIE['LoginUserId'].$DbRow['StayLoggedHash']) == $_COOKIE['LoginHash'])
277 {
278 $this->Database->query('DELETE FROM `UserOnline` WHERE `SessionId`="'.$SID.'"');
279 $this->Database->query('UPDATE `UserOnline` SET `SessionId`="'.$SID.'" WHERE `Id`='.$DbRow['Id']);
280 }
281 }
282 }
283
284 // Check login
285 $Query = $this->Database->select('UserOnline', '*', '`SessionId`="'.$SID.'"');
286 $Row = $Query->fetch_assoc();
287 if ($Row['User'] != '')
288 {
289 $this->Id = $Row['User'];
290 $this->Load();
291 } else
292 {
293 $this->SetAnonymous();
294 }
295
296 // Remove nonactive users
297 $DbResult = $this->Database->select('UserOnline', '`Id`, `User`', '(`ActivityTime` < DATE_SUB(NOW(), INTERVAL '.$this->OnlineStateTimeout.' SECOND)) AND (`StayLogged` = 0)');
298 while ($DbRow = $DbResult->fetch_array())
299 {
300 $this->Database->delete('UserOnline', 'Id='.$DbRow['Id']);
301 }
302 }
303
304 function Register($UserName, $Password, $Email, $Language, $Team, $PreferredVersion)
305 {
306 $Salt = $this->GetPasswordSalt();
307 if ($Team == null) $Team = 'NULL';
308 if ($PreferredVersion == null) $PreferredVersion = 'NULL';
309 $this->Database->query('INSERT INTO `User` '.
310 '(`Name` , `Pass` , `Salt`, `Email` , `Language` , `Team` , `NeedUpdate`, `RegistrationTime`, `PreferredVersion` ) '.
311 'VALUES ("'.$UserName.'", '.$this->CryptPasswordSQL('"'.$Password.'"', '"'.$Salt.'"').
312 ', "'.$Salt.'", "'.$Email.'", '.$Language.', '.$Team.', 1, NOW(), '.$PreferredVersion.')');
313 $UserId = $this->Database->insert_id;
314 $this->Database->query('INSERT INTO `UserTrace` (`User`, `LastIP`, `UserAgent`) '.
315 'VALUES ('.$UserId.', "'.GetRemoteAddress().'", '.
316 '"'.$this->Database->real_escape_string($_SERVER['HTTP_USER_AGENT']).'")');
317 }
318}
Note: See TracBrowser for help on using the repository browser.