1 | <?php
|
---|
2 |
|
---|
3 | include_once(dirname(__FILE__).'/UserList.php');
|
---|
4 | include_once(dirname(__FILE__).'/Options.php');
|
---|
5 | include_once(dirname(__FILE__).'/Registration.php');
|
---|
6 | include_once(dirname(__FILE__).'/Profile.php');
|
---|
7 |
|
---|
8 | class 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.'&group=0&state=2&text=&entry=').'">'.T('Translated').'</a>'.
|
---|
72 | ' <a title="Vaše rozpracované text" href="'.$this->System->Link('/TranslationList.php?user='.
|
---|
73 | $this->System->User->Id.'&group=0&state=3&text=&entry=').'">'.T('Unfinished').'</a>'.
|
---|
74 | ' <a title="Nikým nepřeložené texty" href="'.
|
---|
75 | $this->System->Link('/TranslationList.php?user=0&group=0&state=1&text=&entry=').'">'.T('Untranslated').'</a>';
|
---|
76 | } else
|
---|
77 | {
|
---|
78 | $Output .= '<a href="'.$this->System->Link('/login/').'">'.T('Login').'</a> '.
|
---|
79 | '<a href="'.$this->System->Link('/registration/').'">'.T('Registration').'</a>';
|
---|
80 | }
|
---|
81 | return $Output;
|
---|
82 | }
|
---|
83 | }
|
---|
84 |
|
---|
85 | class 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
|
---|
111 | define('LICENCE_ANONYMOUS', -1);
|
---|
112 | define('LICENCE_USER', 0);
|
---|
113 | define('LICENCE_MODERATOR', 1);
|
---|
114 | define('LICENCE_ADMIN', 2);
|
---|
115 |
|
---|
116 | class 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 | }
|
---|