changeset 1240 | 2b6cdff92b09 |
parent 1231 | 4797a4a88533 |
child 1242 | 9aa09b0a7544 |
1239:e88534039a8d | 1240:2b6cdff92b09 |
---|---|
23 class sessionManager { |
23 class sessionManager { |
24 |
24 |
25 # Variables |
25 # Variables |
26 |
26 |
27 /** |
27 /** |
28 * Whether we're logged in or not |
28 * Whether we're logged in or not |
29 * @var bool |
29 * @var bool |
30 */ |
30 */ |
31 |
31 |
32 var $user_logged_in = false; |
32 var $user_logged_in = false; |
33 |
33 |
34 /** |
34 /** |
35 * Our current low-privilege session key |
35 * Our current low-privilege session key |
36 * @var string |
36 * @var string |
37 */ |
37 */ |
38 |
38 |
39 var $sid; |
39 var $sid; |
40 |
40 |
41 /** |
41 /** |
42 * Username of currently logged-in user, or IP address if not logged in |
42 * Username of currently logged-in user, or IP address if not logged in |
43 * @var string |
43 * @var string |
44 */ |
44 */ |
45 |
45 |
46 var $username; |
46 var $username; |
47 |
47 |
48 /** |
48 /** |
49 * User ID of currently logged-in user, or 1 if not logged in |
49 * User ID of currently logged-in user, or 1 if not logged in |
50 * @var int |
50 * @var int |
51 */ |
51 */ |
52 |
52 |
53 var $user_id = 1; |
53 var $user_id = 1; |
54 |
54 |
55 /** |
55 /** |
56 * Real name of currently logged-in user, or blank if not logged in |
56 * Real name of currently logged-in user, or blank if not logged in |
57 * @var string |
57 * @var string |
58 */ |
58 */ |
59 |
59 |
60 var $real_name; |
60 var $real_name; |
61 |
61 |
62 /** |
62 /** |
63 * E-mail address of currently logged-in user, or blank if not logged in |
63 * E-mail address of currently logged-in user, or blank if not logged in |
64 * @var string |
64 * @var string |
65 */ |
65 */ |
66 |
66 |
67 var $email; |
67 var $email; |
68 |
68 |
69 /** |
69 /** |
70 * List of "extra" user information fields (IM handles, etc.) |
70 * List of "extra" user information fields (IM handles, etc.) |
71 * @var array (associative) |
71 * @var array (associative) |
72 */ |
72 */ |
73 |
73 |
74 var $user_extra; |
74 var $user_extra; |
75 |
75 |
76 /** |
76 /** |
77 * User level of current user |
77 * User level of current user |
78 * USER_LEVEL_GUEST: guest |
78 * USER_LEVEL_GUEST: guest |
79 * USER_LEVEL_MEMBER: regular user |
79 * USER_LEVEL_MEMBER: regular user |
80 * USER_LEVEL_CHPREF: default - pseudo-level that allows changing password and e-mail address (requires re-authentication) |
80 * USER_LEVEL_CHPREF: default - pseudo-level that allows changing password and e-mail address (requires re-authentication) |
81 * USER_LEVEL_MOD: moderator |
81 * USER_LEVEL_MOD: moderator |
82 * USER_LEVEL_ADMIN: administrator |
82 * USER_LEVEL_ADMIN: administrator |
83 * @var int |
83 * @var int |
84 */ |
84 */ |
85 |
85 |
86 var $user_level; |
86 var $user_level; |
87 |
87 |
88 /** |
88 /** |
89 * High-privilege session key |
89 * High-privilege session key |
90 * @var string or false if not running on high-level authentication |
90 * @var string or false if not running on high-level authentication |
91 */ |
91 */ |
92 |
92 |
93 var $sid_super; |
93 var $sid_super; |
94 |
94 |
95 /** |
95 /** |
96 * The user's theme preference, defaults to $template->default_theme |
96 * The user's theme preference, defaults to $template->default_theme |
97 * @var string |
97 * @var string |
98 */ |
98 */ |
99 |
99 |
100 var $theme; |
100 var $theme; |
101 |
101 |
102 /** |
102 /** |
103 * The user's style preference, or style auto-detected based on theme if not logged in |
103 * The user's style preference, or style auto-detected based on theme if not logged in |
104 * @var string |
104 * @var string |
105 */ |
105 */ |
106 |
106 |
107 var $style; |
107 var $style; |
108 |
108 |
109 /** |
109 /** |
110 * Signature of current user - appended to comments, etc. |
110 * Signature of current user - appended to comments, etc. |
111 * @var string |
111 * @var string |
112 */ |
112 */ |
113 |
113 |
114 var $signature; |
114 var $signature; |
115 |
115 |
116 /** |
116 /** |
117 * UNIX timestamp of when we were registered, or 0 if not logged in |
117 * UNIX timestamp of when we were registered, or 0 if not logged in |
118 * @var int |
118 * @var int |
119 */ |
119 */ |
120 |
120 |
121 var $reg_time; |
121 var $reg_time; |
122 |
122 |
123 /** |
123 /** |
124 * The number of unread private messages this user has. |
124 * The number of unread private messages this user has. |
125 * @var int |
125 * @var int |
126 */ |
126 */ |
127 |
127 |
128 var $unread_pms = 0; |
128 var $unread_pms = 0; |
129 |
129 |
130 /** |
130 /** |
131 * AES key used to encrypt passwords and session key info. |
131 * AES key used to encrypt passwords and session key info. |
132 * @var string |
132 * @var string |
133 * @access private |
133 * @access private |
134 */ |
134 */ |
135 |
135 |
136 protected $private_key; |
136 protected $private_key; |
137 |
137 |
138 /** |
138 /** |
139 * Regex that defines a valid username, minus the ^ and $, these are added later |
139 * Regex that defines a valid username, minus the ^ and $, these are added later |
140 * @var string |
140 * @var string |
141 */ |
141 */ |
142 |
142 |
143 var $valid_username = '([^<>&\?\'"%\n\r\t\a\/]+)'; |
143 var $valid_username = '([^<>&\?\'"%\n\r\t\a\/]+)'; |
144 |
144 |
145 /** |
145 /** |
146 * The current user's user title. Defaults to NULL. |
146 * The current user's user title. Defaults to NULL. |
147 * @var string |
147 * @var string |
148 */ |
148 */ |
149 |
149 |
150 var $user_title = null; |
150 var $user_title = null; |
151 |
151 |
152 /** |
152 /** |
153 * What we're allowed to do as far as permissions go. This changes based on the value of the "auth" URI param. |
153 * What we're allowed to do as far as permissions go. This changes based on the value of the "auth" URI param. |
154 * @var string |
154 * @var string |
155 */ |
155 */ |
156 |
156 |
157 var $auth_level = 1; |
157 var $auth_level = 1; |
158 |
158 |
159 /** |
159 /** |
160 * Preference for date formatting |
160 * Preference for date formatting |
161 * @var string |
161 * @var string |
162 */ |
162 */ |
163 |
163 |
164 var $date_format = DATE_4; |
164 var $date_format = DATE_4; |
165 |
165 |
166 /** |
166 /** |
167 * Preference for time formatting |
167 * Preference for time formatting |
168 * @var string |
168 * @var string |
169 */ |
169 */ |
170 |
170 |
171 var $time_format = TIME_24_NS; |
171 var $time_format = TIME_24_NS; |
172 |
172 |
173 /** |
173 /** |
174 * State variable to track if a session timed out |
174 * State variable to track if a session timed out |
175 * @var bool |
175 * @var bool |
176 */ |
176 */ |
177 |
177 |
178 var $sw_timed_out = false; |
178 var $sw_timed_out = false; |
179 |
179 |
180 /** |
180 /** |
181 * Token appended to some important forms to prevent CSRF. |
181 * Token appended to some important forms to prevent CSRF. |
182 * @var string |
182 * @var string |
183 */ |
183 */ |
184 |
184 |
185 var $csrf_token = false; |
185 var $csrf_token = false; |
186 |
186 |
187 /** |
187 /** |
188 * Password change disabled, for auth plugins |
188 * Password change disabled, for auth plugins |
189 * @var bool |
189 * @var bool |
190 */ |
190 */ |
191 |
191 |
192 var $password_change_disabled = false; |
192 var $password_change_disabled = false; |
193 |
193 |
194 /** |
194 /** |
195 * Password change page URL + title, for auth plugins |
195 * Password change page URL + title, for auth plugins |
196 * @var array |
196 * @var array |
197 */ |
197 */ |
198 |
198 |
199 var $password_change_dest = array('url' => '', 'title' => ''); |
199 var $password_change_dest = array('url' => '', 'title' => ''); |
200 |
200 |
201 /** |
201 /** |
202 * Switch to track if we're started or not. |
202 * Switch to track if we're started or not. |
203 * @access private |
203 * @access private |
204 * @var bool |
204 * @var bool |
205 */ |
205 */ |
206 |
206 |
207 var $started = false; |
207 var $started = false; |
208 |
208 |
209 /** |
209 /** |
210 * Switch to control compatibility mode (for older Enano websites being upgraded) |
210 * Switch to control compatibility mode (for older Enano websites being upgraded) |
211 * @access private |
211 * @access private |
212 * @var bool |
212 * @var bool |
213 */ |
213 */ |
214 |
214 |
215 var $compat = false; |
215 var $compat = false; |
216 |
216 |
217 /** |
217 /** |
218 * Our list of permission types. |
218 * Our list of permission types. |
219 * @access private |
219 * @access private |
220 * @var array |
220 * @var array |
221 */ |
221 */ |
222 |
222 |
223 var $acl_types = Array(); |
223 var $acl_types = Array(); |
224 |
224 |
225 /** |
225 /** |
226 * The list of descriptions for the permission types |
226 * The list of descriptions for the permission types |
227 * @var array |
227 * @var array |
228 */ |
228 */ |
229 |
229 |
230 var $acl_descs = Array(); |
230 var $acl_descs = Array(); |
231 |
231 |
232 /** |
232 /** |
233 * A list of dependencies for ACL types. |
233 * A list of dependencies for ACL types. |
234 * @var array |
234 * @var array |
235 */ |
235 */ |
236 |
236 |
237 var $acl_deps = Array(); |
237 var $acl_deps = Array(); |
238 |
238 |
239 /** |
239 /** |
240 * Our tell-all list of permissions. Do not even try to change this. |
240 * Our tell-all list of permissions. Do not even try to change this. |
241 * @access private |
241 * @access private |
242 * @var array |
242 * @var array |
243 */ |
243 */ |
244 |
244 |
245 var $perms = Array(); |
245 var $perms = Array(); |
246 |
246 |
247 /** |
247 /** |
248 * A cache variable - saved after sitewide permissions are checked but before page-specific permissions. |
248 * A cache variable - saved after sitewide permissions are checked but before page-specific permissions. |
249 * @var array |
249 * @var array |
250 * @access private |
250 * @access private |
251 */ |
251 */ |
252 |
252 |
253 var $acl_base_cache = Array(); |
253 var $acl_base_cache = Array(); |
254 |
254 |
255 /** |
255 /** |
256 * Stores the scope information for ACL types. |
256 * Stores the scope information for ACL types. |
257 * @var array |
257 * @var array |
258 * @access private |
258 * @access private |
259 */ |
259 */ |
260 |
260 |
261 var $acl_scope = Array(); |
261 var $acl_scope = Array(); |
262 |
262 |
263 /** |
263 /** |
264 * Array to track which default permissions are being used |
264 * Array to track which default permissions are being used |
265 * @var array |
265 * @var array |
266 * @access private |
266 * @access private |
267 */ |
267 */ |
268 |
268 |
269 var $acl_defaults_used = Array(); |
269 var $acl_defaults_used = Array(); |
270 |
270 |
271 /** |
271 /** |
272 * Array to track group membership. |
272 * Array to track group membership. |
273 * @var array |
273 * @var array |
274 */ |
274 */ |
275 |
275 |
276 var $groups = Array(); |
276 var $groups = Array(); |
277 |
277 |
278 /** |
278 /** |
279 * Associative array to track group modship. |
279 * Associative array to track group modship. |
280 * @var array |
280 * @var array |
281 */ |
281 */ |
282 |
282 |
283 var $group_mod = Array(); |
283 var $group_mod = Array(); |
284 |
284 |
285 /** |
285 /** |
286 * A constant array of user-level-to-rank default associations. |
286 * A constant array of user-level-to-rank default associations. |
287 * @var array |
287 * @var array |
288 */ |
288 */ |
289 |
289 |
290 var $level_rank_table = array( |
290 var $level_rank_table = array( |
291 USER_LEVEL_ADMIN => RANK_ID_ADMIN, |
291 USER_LEVEL_ADMIN => RANK_ID_ADMIN, |
292 USER_LEVEL_MOD => RANK_ID_MOD, |
292 USER_LEVEL_MOD => RANK_ID_MOD, |
293 USER_LEVEL_MEMBER => RANK_ID_MEMBER, |
293 USER_LEVEL_MEMBER => RANK_ID_MEMBER, |
294 USER_LEVEL_CHPREF => RANK_ID_MEMBER, |
294 USER_LEVEL_CHPREF => RANK_ID_MEMBER, |
295 USER_LEVEL_GUEST => RANK_ID_GUEST |
295 USER_LEVEL_GUEST => RANK_ID_GUEST |
296 ); |
296 ); |
297 |
297 |
298 /** |
298 /** |
299 * A constant array that maps precedence constants to language strings |
299 * A constant array that maps precedence constants to language strings |
300 * @var array |
300 * @var array |
301 */ |
301 */ |
302 |
302 |
303 var $acl_inherit_lang_table = array( |
303 var $acl_inherit_lang_table = array( |
304 ACL_INHERIT_ENANO_DEFAULT => 'acl_inherit_enano_default', |
304 ACL_INHERIT_ENANO_DEFAULT => 'acl_inherit_enano_default', |
305 ACL_INHERIT_GLOBAL_EVERYONE => 'acl_inherit_global_everyone', |
305 ACL_INHERIT_GLOBAL_EVERYONE => 'acl_inherit_global_everyone', |
306 ACL_INHERIT_GLOBAL_GROUP => 'acl_inherit_global_group', |
306 ACL_INHERIT_GLOBAL_GROUP => 'acl_inherit_global_group', |
312 ACL_INHERIT_LOCAL_GROUP => 'acl_inherit_local_group', |
312 ACL_INHERIT_LOCAL_GROUP => 'acl_inherit_local_group', |
313 ACL_INHERIT_LOCAL_USER => 'acl_inherit_local_user' |
313 ACL_INHERIT_LOCAL_USER => 'acl_inherit_local_user' |
314 ); |
314 ); |
315 |
315 |
316 # Basic functions |
316 # Basic functions |
317 |
317 |
318 /** |
318 /** |
319 * Constructor. |
319 * Constructor. |
320 */ |
320 */ |
321 |
321 |
322 function __construct() |
322 function __construct() |
323 { |
323 { |
324 global $db, $session, $paths, $template, $plugins; // Common objects |
324 global $db, $session, $paths, $template, $plugins; // Common objects |
325 |
325 |
326 if ( defined('IN_ENANO_INSTALL') && !defined('IN_ENANO_UPGRADE') ) |
326 if ( defined('IN_ENANO_INSTALL') && !defined('IN_ENANO_UPGRADE') ) |
385 $db->free_result(); |
385 $db->free_result(); |
386 } |
386 } |
387 } |
387 } |
388 |
388 |
389 /** |
389 /** |
390 * PHP 4 compatible constructor. Deprecated in 1.1.x. |
390 * PHP 4 compatible constructor. Deprecated in 1.1.x. |
391 */ |
391 */ |
392 |
392 |
393 /* |
393 /* |
394 function sessionManager() |
394 function sessionManager() |
395 { |
395 { |
396 $this->__construct(); |
396 $this->__construct(); |
397 } |
397 } |
398 */ |
398 */ |
399 |
399 |
400 /** |
400 /** |
401 * Wrapper function to sanitize strings for MySQL and HTML |
401 * Wrapper function to sanitize strings for MySQL and HTML |
402 * @param string $text The text to sanitize |
402 * @param string $text The text to sanitize |
403 * @return string |
403 * @return string |
404 */ |
404 */ |
405 |
405 |
406 function prepare_text($text) |
406 function prepare_text($text) |
407 { |
407 { |
408 global $db; |
408 global $db; |
409 return $db->escape(htmlspecialchars($text)); |
409 return $db->escape(htmlspecialchars($text)); |
410 } |
410 } |
411 |
411 |
412 /** |
412 /** |
413 * Makes a SQL query and handles error checking |
413 * Makes a SQL query and handles error checking |
414 * @param string $query The SQL query to make |
414 * @param string $query The SQL query to make |
415 * @return resource |
415 * @return resource |
416 */ |
416 */ |
417 |
417 |
418 function sql($query) |
418 function sql($query) |
419 { |
419 { |
420 global $db, $session, $paths, $template, $plugins; // Common objects |
420 global $db, $session, $paths, $template, $plugins; // Common objects |
421 $result = $db->sql_query($query); |
421 $result = $db->sql_query($query); |
425 } |
425 } |
426 return $result; |
426 return $result; |
427 } |
427 } |
428 |
428 |
429 /** |
429 /** |
430 * Returns true if we're currently on a page that shouldn't be blocked even if we have an inactive or banned account |
430 * Returns true if we're currently on a page that shouldn't be blocked even if we have an inactive or banned account |
431 * @param bool strict - if true, whitelist of pages is even stricter (Login, Logout and CSS only). if false (default), admin access is allowed, assuming other factors allow it |
431 * @param bool strict - if true, whitelist of pages is even stricter (Login, Logout and CSS only). if false (default), admin access is allowed, assuming other factors allow it |
432 * @return bool |
432 * @return bool |
433 */ |
433 */ |
434 |
434 |
435 function on_critical_page($strict = false) |
435 function on_critical_page($strict = false) |
436 { |
436 { |
437 global $urlname; |
437 global $urlname; |
438 list($page_id, $namespace) = RenderMan::strToPageID($urlname); |
438 list($page_id, $namespace) = RenderMan::strToPageID($urlname); |
449 } |
449 } |
450 |
450 |
451 # Session restoration and permissions |
451 # Session restoration and permissions |
452 |
452 |
453 /** |
453 /** |
454 * Initializes the basic state of things, including most user prefs, login data, cookie stuff |
454 * Initializes the basic state of things, including most user prefs, login data, cookie stuff |
455 */ |
455 */ |
456 |
456 |
457 function start() |
457 function start() |
458 { |
458 { |
459 global $db, $session, $paths, $template, $plugins; // Common objects |
459 global $db, $session, $paths, $template, $plugins; // Common objects |
460 global $lang; |
460 global $lang; |
603 } |
603 } |
604 |
604 |
605 # Logins |
605 # Logins |
606 |
606 |
607 /** |
607 /** |
608 * Attempts to perform a login using crypto functions |
608 * Attempts to perform a login using crypto functions |
609 * @param string $username The username |
609 * @param string $username The username |
610 * @param string $aes_data The encrypted password, hex-encoded |
610 * @param string $aes_data The encrypted password, hex-encoded |
611 * @param string $aes_key The MD5 hash of the encryption key, hex-encoded |
611 * @param string $aes_key The MD5 hash of the encryption key, hex-encoded |
612 * @param string $challenge The 256-bit MD5 challenge string - first 128 bits should be the hash, the last 128 should be the challenge salt |
612 * @param string $challenge The 256-bit MD5 challenge string - first 128 bits should be the hash, the last 128 should be the challenge salt |
613 * @param int $level The privilege level we're authenticating for, defaults to 0 |
613 * @param int $level The privilege level we're authenticating for, defaults to 0 |
614 * @param string $captcha_hash Optional. If we're locked out and the lockout policy is captcha, this should be the identifier for the code. |
614 * @param string $captcha_hash Optional. If we're locked out and the lockout policy is captcha, this should be the identifier for the code. |
615 * @param string $captcha_code Optional. If we're locked out and the lockout policy is captcha, this should be the code the user entered. |
615 * @param string $captcha_code Optional. If we're locked out and the lockout policy is captcha, this should be the code the user entered. |
616 * @param bool $remember Optional. If true, remembers the session for X days. Otherwise, assigns a short session. Defaults to false. |
616 * @param bool $remember Optional. If true, remembers the session for X days. Otherwise, assigns a short session. Defaults to false. |
617 * @param bool $lookup_key Optional. If true (default) this queries the database for the "real" encryption key. Else, uses what is given. |
617 * @param bool $lookup_key Optional. If true (default) this queries the database for the "real" encryption key. Else, uses what is given. |
618 * @return string 'success' on success, or error string on failure |
618 * @return string 'success' on success, or error string on failure |
619 */ |
619 */ |
620 |
620 |
621 function login_with_crypto($username, $aes_data, $aes_key_id, $challenge, $level = USER_LEVEL_MEMBER, $captcha_hash = false, $captcha_code = false, $remember = false, $lookup_key = true) |
621 function login_with_crypto($username, $aes_data, $aes_key_id, $challenge, $level = USER_LEVEL_MEMBER, $captcha_hash = false, $captcha_code = false, $remember = false, $lookup_key = true) |
622 { |
622 { |
623 global $db, $session, $paths, $template, $plugins; // Common objects |
623 global $db, $session, $paths, $template, $plugins; // Common objects |
624 |
624 |
625 // Instanciate the Rijndael encryption object |
625 // Instanciate the Rijndael encryption object |
667 // Let the LoginAPI do the rest. |
667 // Let the LoginAPI do the rest. |
668 return $this->login_without_crypto($username, $password, false, $level, $captcha_hash, $captcha_code, $remember); |
668 return $this->login_without_crypto($username, $password, false, $level, $captcha_hash, $captcha_code, $remember); |
669 } |
669 } |
670 |
670 |
671 /** |
671 /** |
672 * Attempts to login without using crypto stuff, mainly for use when the other side doesn't like Javascript |
672 * Attempts to login without using crypto stuff, mainly for use when the other side doesn't like Javascript |
673 * This method of authentication is inherently insecure, there's really nothing we can do about it except hope and pray that everyone moves to Firefox |
673 * This method of authentication is inherently insecure, there's really nothing we can do about it except hope and pray that everyone moves to Firefox |
674 * Technically it still uses crypto, but it only decrypts the password already stored, which is (obviously) required for authentication |
674 * Technically it still uses crypto, but it only decrypts the password already stored, which is (obviously) required for authentication |
675 * @param string $username The username |
675 * @param string $username The username |
676 * @param string $password The password -OR- the MD5 hash of the password if $already_md5ed is true |
676 * @param string $password The password -OR- the MD5 hash of the password if $already_md5ed is true |
677 * @param bool $already_md5ed This should be set to true if $password is an MD5 hash, and should be false if it's plaintext. Defaults to false. |
677 * @param bool $already_md5ed This should be set to true if $password is an MD5 hash, and should be false if it's plaintext. Defaults to false. |
678 * @param int $level The privilege level we're authenticating for, defaults to 0 |
678 * @param int $level The privilege level we're authenticating for, defaults to 0 |
679 * @param bool $remember Optional. If true, remembers the session for X days. Otherwise, assigns a short session. Defaults to false. |
679 * @param bool $remember Optional. If true, remembers the session for X days. Otherwise, assigns a short session. Defaults to false. |
680 */ |
680 */ |
681 |
681 |
682 function login_without_crypto($username, $password, $already_md5ed = false, $level = USER_LEVEL_MEMBER, $remember = false) |
682 function login_without_crypto($username, $password, $already_md5ed = false, $level = USER_LEVEL_MEMBER, $remember = false) |
683 { |
683 { |
684 global $db, $session, $paths, $template, $plugins; // Common objects |
684 global $db, $session, $paths, $template, $plugins; // Common objects |
685 |
685 |
710 |
710 |
711 // Retrieve the real password from the database |
711 // Retrieve the real password from the database |
712 $username_db = $db->escape(strtolower($username)); |
712 $username_db = $db->escape(strtolower($username)); |
713 $username_db_upper = $db->escape($username); |
713 $username_db_upper = $db->escape($username); |
714 if ( !$db->sql_query('SELECT password,password_salt,old_encryption,user_id,user_level,temp_password,temp_password_time FROM '.table_prefix."users\n" |
714 if ( !$db->sql_query('SELECT password,password_salt,old_encryption,user_id,user_level,temp_password,temp_password_time FROM '.table_prefix."users\n" |
715 . " WHERE ( " . ENANO_SQLFUNC_LOWERCASE . "(username) = '$username_db' OR username = '$username_db_upper' );") ) |
715 . " WHERE ( " . ENANO_SQLFUNC_LOWERCASE . "(username) = '$username_db' OR username = '$username_db_upper' );") ) |
716 { |
716 { |
717 $this->sql('SELECT password,\'\' AS password_salt,old_encryption,user_id,user_level,temp_password,temp_password_time FROM '.table_prefix."users\n" |
717 $this->sql('SELECT password,\'\' AS password_salt,old_encryption,user_id,user_level,temp_password,temp_password_time FROM '.table_prefix."users\n" |
718 . " WHERE ( " . ENANO_SQLFUNC_LOWERCASE . "(username) = '$username_db' OR username = '$username_db_upper' );"); |
718 . " WHERE ( " . ENANO_SQLFUNC_LOWERCASE . "(username) = '$username_db' OR username = '$username_db_upper' );"); |
719 } |
719 } |
720 if ( $db->numrows() < 1 ) |
720 if ( $db->numrows() < 1 ) |
721 { |
721 { |
722 // This wasn't logged in <1.0.2, dunno how it slipped through |
722 // This wasn't logged in <1.0.2, dunno how it slipped through |
723 if ( $level > USER_LEVEL_MEMBER ) |
723 if ( $level > USER_LEVEL_MEMBER ) |
724 $this->sql('INSERT INTO ' . table_prefix . "logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES\n" |
724 $this->sql('INSERT INTO ' . table_prefix . "logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES\n" |
725 . ' (\'security\', \'admin_auth_bad\', '.time().', \''.enano_date(ED_DATE | ED_TIME).'\', \''.$db->escape($username).'\', ' |
725 . ' (\'security\', \'admin_auth_bad\', '.time().', \''.enano_date(ED_DATE | ED_TIME).'\', \''.$db->escape($username).'\', ' |
726 . '\''.$db->escape($_SERVER['REMOTE_ADDR']).'\', ' . intval($level) . ')'); |
726 . '\''.$db->escape($_SERVER['REMOTE_ADDR']).'\', ' . intval($level) . ')'); |
727 else |
727 else |
728 $this->sql('INSERT INTO ' . table_prefix . "logs(log_type,action,time_id,date_string,author,edit_summary) VALUES\n" |
728 $this->sql('INSERT INTO ' . table_prefix . "logs(log_type,action,time_id,date_string,author,edit_summary) VALUES\n" |
729 . ' (\'security\', \'auth_bad\', '.time().', \''.enano_date(ED_DATE | ED_TIME).'\', \''.$db->escape($username).'\', ' |
729 . ' (\'security\', \'auth_bad\', '.time().', \''.enano_date(ED_DATE | ED_TIME).'\', \''.$db->escape($username).'\', ' |
730 . '\''.$db->escape($_SERVER['REMOTE_ADDR']).'\')'); |
730 . '\''.$db->escape($_SERVER['REMOTE_ADDR']).'\')'); |
731 |
731 |
732 // Do we also need to increment the lockout countdown? |
732 // Do we also need to increment the lockout countdown? |
733 if ( !defined('IN_ENANO_INSTALL') ) |
733 if ( !defined('IN_ENANO_INSTALL') ) |
734 $lockout_data = $this->get_lockout_info(); |
734 $lockout_data = $this->get_lockout_info(); |
875 ); |
875 ); |
876 } |
876 } |
877 } |
877 } |
878 |
878 |
879 /** |
879 /** |
880 * Attempts to log in using the old table structure and algorithm. This is for upgrades from old 1.0.x releases. |
880 * Attempts to log in using the old table structure and algorithm. This is for upgrades from old 1.0.x releases. |
881 * @param string $username |
881 * @param string $username |
882 * @param string $password This should be an MD5 hash |
882 * @param string $password This should be an MD5 hash |
883 * @return string 'success' if successful, or error message on failure |
883 * @return string 'success' if successful, or error message on failure |
884 */ |
884 */ |
885 |
885 |
886 function login_compat($username, $password, $level = 0) |
886 function login_compat($username, $password, $level = 0) |
887 { |
887 { |
888 global $db, $session, $paths, $template, $plugins; // Common objects |
888 global $db, $session, $paths, $template, $plugins; // Common objects |
889 $pass_hashed =& $password; |
889 $pass_hashed =& $password; |
906 return 'The username and/or password is incorrect.'; |
906 return 'The username and/or password is incorrect.'; |
907 } |
907 } |
908 } |
908 } |
909 |
909 |
910 /** |
910 /** |
911 * Registers a session key in the database. This function *ASSUMES* that the username and password have already been validated! |
911 * Registers a session key in the database. This function *ASSUMES* that the username and password have already been validated! |
912 * Basically the session key is a hex-encoded cookie (encrypted with the site's private key) that says "u=[username];p=[sha1 of password];s=[unique key id]" |
912 * Basically the session key is a hex-encoded cookie (encrypted with the site's private key) that says "u=[username];p=[sha1 of password];s=[unique key id]" |
913 * @param int $user_id |
913 * @param int $user_id |
914 * @param string $username |
914 * @param string $username |
915 * @param string $password_hmac The HMAC of the user's password, right from the database |
915 * @param string $password_hmac The HMAC of the user's password, right from the database |
916 * @param int $level The level of access to grant, defaults to USER_LEVEL_MEMBER |
916 * @param int $level The level of access to grant, defaults to USER_LEVEL_MEMBER |
917 * @param bool $remember Whether the session should be long-term (true) or not (false). Defaults to short-term. |
917 * @param bool $remember Whether the session should be long-term (true) or not (false). Defaults to short-term. |
918 * @return bool |
918 * @return bool |
919 */ |
919 */ |
920 |
920 |
921 function register_session($user_id, $username, $password_hmac, $level = USER_LEVEL_MEMBER, $remember = false) |
921 function register_session($user_id, $username, $password_hmac, $level = USER_LEVEL_MEMBER, $remember = false) |
922 { |
922 { |
923 global $db, $session, $paths, $template, $plugins; // Common objects |
923 global $db, $session, $paths, $template, $plugins; // Common objects |
924 |
924 |
925 // Random key identifier |
925 // Random key identifier |
995 |
995 |
996 return true; |
996 return true; |
997 } |
997 } |
998 |
998 |
999 /** |
999 /** |
1000 * Identical to register_session in nature, but uses the old login/table structure. DO NOT use this except in the upgrade script under very controlled circumstances. |
1000 * Identical to register_session in nature, but uses the old login/table structure. DO NOT use this except in the upgrade script under very controlled circumstances. |
1001 * @see sessionManager::register_session() |
1001 * @see sessionManager::register_session() |
1002 * @access private |
1002 * @access private |
1003 */ |
1003 */ |
1004 |
1004 |
1005 function register_session_compat($user_id, $username, $password, $level = 0) |
1005 function register_session_compat($user_id, $username, $password, $level = 0) |
1006 { |
1006 { |
1007 $salt = md5(microtime() . mt_rand()); |
1007 $salt = md5(microtime() . mt_rand()); |
1008 $thekey = md5($password . $salt); |
1008 $thekey = md5($password . $salt); |
1026 $query = $this->sql('INSERT INTO '.table_prefix.'session_keys(session_key, salt, user_id, auth_level, source_ip, time) VALUES(\''.$thekey.'\', \''.$salt.'\', '.$user_id.', '.$level.', \''.$ip.'\', '.$time.');'); |
1026 $query = $this->sql('INSERT INTO '.table_prefix.'session_keys(session_key, salt, user_id, auth_level, source_ip, time) VALUES(\''.$thekey.'\', \''.$salt.'\', '.$user_id.', '.$level.', \''.$ip.'\', '.$time.');'); |
1027 return true; |
1027 return true; |
1028 } |
1028 } |
1029 |
1029 |
1030 /** |
1030 /** |
1031 * Tells us if we're locked out from logging in or not. |
1031 * Tells us if we're locked out from logging in or not. |
1032 * @param reference will be filled with information regarding in-progress lockout |
1032 * @param reference will be filled with information regarding in-progress lockout |
1033 * @return bool True if locked out, false otherwise |
1033 * @return bool True if locked out, false otherwise |
1034 */ |
1034 */ |
1035 |
1035 |
1036 function get_lockout_info() |
1036 function get_lockout_info() |
1037 { |
1037 { |
1038 global $db; |
1038 global $db; |
1039 |
1039 |
1085 } |
1085 } |
1086 return $lockdata; |
1086 return $lockdata; |
1087 } |
1087 } |
1088 |
1088 |
1089 /** |
1089 /** |
1090 * Creates/restores a guest session |
1090 * Creates/restores a guest session |
1091 * @todo implement real session management for guests |
1091 * @todo implement real session management for guests |
1092 */ |
1092 */ |
1093 |
1093 |
1094 function register_guest_session() |
1094 function register_guest_session() |
1095 { |
1095 { |
1096 global $db, $session, $paths, $template, $plugins; // Common objects |
1096 global $db, $session, $paths, $template, $plugins; // Common objects |
1097 global $lang; |
1097 global $lang; |
1098 $this->username = $_SERVER['REMOTE_ADDR']; |
1098 $this->username = $_SERVER['REMOTE_ADDR']; |
1118 // make a CSRF token |
1118 // make a CSRF token |
1119 $this->csrf_token = hmac_sha1($_SERVER['REMOTE_ADDR'], sha1($this->private_key)); |
1119 $this->csrf_token = hmac_sha1($_SERVER['REMOTE_ADDR'], sha1($this->private_key)); |
1120 } |
1120 } |
1121 |
1121 |
1122 /** |
1122 /** |
1123 * Validates a session key, and returns the userdata associated with the key or false |
1123 * Validates a session key, and returns the userdata associated with the key or false |
1124 * @param string $key The session key to validate |
1124 * @param string $key The session key to validate |
1125 * @return array Keys are 'user_id', 'username', 'email', 'real_name', 'user_level', 'theme', 'style', 'signature', 'reg_time', 'account_active', 'activation_key', and 'auth_level' or bool false if validation failed. The key 'auth_level' is the maximum authorization level that this key provides. |
1125 * @return array Keys are 'user_id', 'username', 'email', 'real_name', 'user_level', 'theme', 'style', 'signature', 'reg_time', 'account_active', 'activation_key', and 'auth_level' or bool false if validation failed. The key 'auth_level' is the maximum authorization level that this key provides. |
1126 */ |
1126 */ |
1127 |
1127 |
1128 function validate_session($key) |
1128 function validate_session($key) |
1129 { |
1129 { |
1130 global $db, $session, $paths, $template, $plugins; // Common objects |
1130 global $db, $session, $paths, $template, $plugins; // Common objects |
1131 profiler_log("SessionManager: checking session: " . sha1($key)); |
1131 profiler_log("SessionManager: checking session: " . sha1($key)); |
1132 |
1132 |
1139 |
1139 |
1140 return $this->validate_session_shared($key, ''); |
1140 return $this->validate_session_shared($key, ''); |
1141 } |
1141 } |
1142 |
1142 |
1143 /** |
1143 /** |
1144 * Validates an old-format AES session key. DO NOT USE THIS. Will return false if called outside of an upgrade. |
1144 * Validates an old-format AES session key. DO NOT USE THIS. Will return false if called outside of an upgrade. |
1145 * @param string Session key |
1145 * @param string Session key |
1146 * @return array |
1146 * @return array |
1147 */ |
1147 */ |
1148 |
1148 |
1149 protected function validate_aes_session($key) |
1149 protected function validate_aes_session($key) |
1150 { |
1150 { |
1151 global $db, $session, $paths, $template, $plugins; // Common objects |
1151 global $db, $session, $paths, $template, $plugins; // Common objects |
1152 |
1152 |
1172 |
1172 |
1173 return $this->validate_session_shared($keyhash, $salt, true); |
1173 return $this->validate_session_shared($keyhash, $salt, true); |
1174 } |
1174 } |
1175 |
1175 |
1176 /** |
1176 /** |
1177 * Shared portion of session validation. Do not try to call this. |
1177 * Shared portion of session validation. Do not try to call this. |
1178 * @return array |
1178 * @return array |
1179 * @access private |
1179 * @access private |
1180 */ |
1180 */ |
1181 |
1181 |
1182 protected function validate_session_shared($key, $salt, $loose_call = false) |
1182 protected function validate_session_shared($key, $salt, $loose_call = false) |
1183 { |
1183 { |
1184 global $db, $session, $paths, $template, $plugins; // Common objects |
1184 global $db, $session, $paths, $template, $plugins; // Common objects |
1185 |
1185 |
1221 |
1221 |
1222 if ( !$query && ( defined('IN_ENANO_INSTALL') or defined('IN_ENANO_UPGRADE') ) ) |
1222 if ( !$query && ( defined('IN_ENANO_INSTALL') or defined('IN_ENANO_UPGRADE') ) ) |
1223 { |
1223 { |
1224 $key_md5 = $loose_call ? $key : md5($key); |
1224 $key_md5 = $loose_call ? $key : md5($key); |
1225 $query = $this->sql('SELECT u.user_id AS uid,u.username,u.password,\'\' AS password_salt,u.email,u.real_name,u.user_level,u.theme,u.style,u.signature,u.reg_time,u.account_active,u.activation_key,k.source_ip,k.time,k.auth_level,COUNT(p.message_id) AS num_pms, 1440 AS user_timezone, \'0;0;0;0;60\' AS user_dst, ' . SK_SHORT . ' AS key_type, k.salt FROM '.table_prefix.'session_keys AS k |
1225 $query = $this->sql('SELECT u.user_id AS uid,u.username,u.password,\'\' AS password_salt,u.email,u.real_name,u.user_level,u.theme,u.style,u.signature,u.reg_time,u.account_active,u.activation_key,k.source_ip,k.time,k.auth_level,COUNT(p.message_id) AS num_pms, 1440 AS user_timezone, \'0;0;0;0;60\' AS user_dst, ' . SK_SHORT . ' AS key_type, k.salt FROM '.table_prefix.'session_keys AS k |
1226 LEFT JOIN '.table_prefix.'users AS u |
1226 LEFT JOIN '.table_prefix.'users AS u |
1227 ON ( u.user_id=k.user_id ) |
1227 ON ( u.user_id=k.user_id ) |
1228 LEFT JOIN '.table_prefix.'privmsgs AS p |
1228 LEFT JOIN '.table_prefix.'privmsgs AS p |
1229 ON ( p.message_to=u.username AND p.message_read=0 ) |
1229 ON ( p.message_to=u.username AND p.message_read=0 ) |
1230 WHERE k.session_key=\''.$key_md5.'\' |
1230 WHERE k.session_key=\''.$key_md5.'\' |
1231 GROUP BY u.user_id,u.username,u.password,u.email,u.real_name,u.user_level,u.theme,u.style,u.signature,u.reg_time,u.account_active,u.activation_key,k.source_ip,k.time,k.auth_level,k.salt;'); |
1231 GROUP BY u.user_id,u.username,u.password,u.email,u.real_name,u.user_level,u.theme,u.style,u.signature,u.reg_time,u.account_active,u.activation_key,k.source_ip,k.time,k.auth_level,k.salt;'); |
1232 } |
1232 } |
1233 else if ( !$query ) |
1233 else if ( !$query ) |
1234 { |
1234 { |
1235 $db->_die(); |
1235 $db->_die(); |
1236 } |
1236 } |
1361 |
1361 |
1362 return $row; |
1362 return $row; |
1363 } |
1363 } |
1364 |
1364 |
1365 /** |
1365 /** |
1366 * Validates a session key, and returns the userdata associated with the key or false. Optimized for compatibility with the old MD5-based auth system. |
1366 * Validates a session key, and returns the userdata associated with the key or false. Optimized for compatibility with the old MD5-based auth system. |
1367 * @param string $key The session key to validate |
1367 * @param string $key The session key to validate |
1368 * @return array Keys are 'user_id', 'username', 'email', 'real_name', 'user_level', 'theme', 'style', 'signature', 'reg_time', 'account_active', 'activation_key', and 'auth_level' or bool false if validation failed. The key 'auth_level' is the maximum authorization level that this key provides. |
1368 * @return array Keys are 'user_id', 'username', 'email', 'real_name', 'user_level', 'theme', 'style', 'signature', 'reg_time', 'account_active', 'activation_key', and 'auth_level' or bool false if validation failed. The key 'auth_level' is the maximum authorization level that this key provides. |
1369 */ |
1369 */ |
1370 |
1370 |
1371 function compat_validate_session($key) |
1371 function compat_validate_session($key) |
1372 { |
1372 { |
1373 global $db, $session, $paths, $template, $plugins; // Common objects |
1373 global $db, $session, $paths, $template, $plugins; // Common objects |
1374 $key = $db->escape($key); |
1374 $key = $db->escape($key); |
1375 |
1375 |
1376 $query = $this->sql('SELECT u.user_id,u.username,u.password,u.email,u.real_name,u.user_level,k.source_ip,k.salt,k.time,k.auth_level,1440 AS user_timezone FROM '.table_prefix.'session_keys AS k |
1376 $query = $this->sql('SELECT u.user_id,u.username,u.password,u.email,u.real_name,u.user_level,k.source_ip,k.salt,k.time,k.auth_level,1440 AS user_timezone FROM '.table_prefix.'session_keys AS k |
1377 LEFT JOIN '.table_prefix.'users AS u |
1377 LEFT JOIN '.table_prefix.'users AS u |
1378 ON u.user_id=k.user_id |
1378 ON u.user_id=k.user_id |
1379 WHERE k.session_key=\''.$key.'\';'); |
1379 WHERE k.session_key=\''.$key.'\';'); |
1380 if($db->numrows() < 1) |
1380 if($db->numrows() < 1) |
1381 { |
1381 { |
1382 // echo '(debug) $session->validate_session: Key '.$key.' was not found in database<br />'; |
1382 // echo '(debug) $session->validate_session: Key '.$key.' was not found in database<br />'; |
1383 return false; |
1383 return false; |
1384 } |
1384 } |
1420 |
1420 |
1421 $row['user_timezone'] = intval($row['user_timezone']) - 1440; |
1421 $row['user_timezone'] = intval($row['user_timezone']) - 1440; |
1422 |
1422 |
1423 return $row; |
1423 return $row; |
1424 } |
1424 } |
1425 |
1425 |
1426 /** |
1426 /** |
1427 * Demotes us to one less than the specified auth level. AKA destroys elevated authentication and/or logs out the user, depending on $level |
1427 * Demotes us to one less than the specified auth level. AKA destroys elevated authentication and/or logs out the user, depending on $level |
1428 * @param int $level How low we should go - USER_LEVEL_MEMBER means demote to USER_LEVEL_GUEST, and anything more powerful than USER_LEVEL_MEMBER means demote to USER_LEVEL_MEMBER |
1428 * @param int $level How low we should go - USER_LEVEL_MEMBER means demote to USER_LEVEL_GUEST, and anything more powerful than USER_LEVEL_MEMBER means demote to USER_LEVEL_MEMBER |
1429 * @return string 'success' if successful, or error on failure |
1429 * @return string 'success' if successful, or error on failure |
1430 */ |
1430 */ |
1431 |
1431 |
1432 function logout($level = USER_LEVEL_MEMBER) |
1432 function logout($level = USER_LEVEL_MEMBER) |
1433 { |
1433 { |
1434 global $db, $session, $paths, $template, $plugins; // Common objects |
1434 global $db, $session, $paths, $template, $plugins; // Common objects |
1435 $ou = $this->username; |
1435 $ou = $this->username; |
1436 $oid = $this->user_id; |
1436 $oid = $this->user_id; |
1470 } |
1470 } |
1471 |
1471 |
1472 # Miscellaneous stuff |
1472 # Miscellaneous stuff |
1473 |
1473 |
1474 /** |
1474 /** |
1475 * Alerts the user that their account is inactive, and tells them appropriate steps to remedy the situation. Halts execution. |
1475 * Alerts the user that their account is inactive, and tells them appropriate steps to remedy the situation. Halts execution. |
1476 * @param array Return from validate_session() |
1476 * @param array Return from validate_session() |
1477 */ |
1477 */ |
1478 |
1478 |
1479 function show_inactive_error($userdata) |
1479 function show_inactive_error($userdata) |
1480 { |
1480 { |
1481 global $db, $session, $paths, $template, $plugins; // Common objects |
1481 global $db, $session, $paths, $template, $plugins; // Common objects |
1482 global $lang; |
1482 global $lang; |
1524 } |
1524 } |
1525 |
1525 |
1526 if ( $can_request && !isset($_POST['activation_request']) ) |
1526 if ( $can_request && !isset($_POST['activation_request']) ) |
1527 { |
1527 { |
1528 $form = '<p>' . $lang->get('user_login_noact_msg_ask_admins') . '</p> |
1528 $form = '<p>' . $lang->get('user_login_noact_msg_ask_admins') . '</p> |
1529 <form action="' . makeUrlNS('System', 'ActivateStub') . '" method="post"> |
1529 <form action="' . makeUrlNS('System', 'ActivateStub') . '" method="post"> |
1530 <p><input type="submit" name="activation_request" value="' . $lang->get('user_login_noact_btn_request_activation') . '" /> <input type="submit" name="logout" value="' . $lang->get('user_login_noact_btn_log_out') . '" /></p> |
1530 <p><input type="submit" name="activation_request" value="' . $lang->get('user_login_noact_btn_request_activation') . '" /> <input type="submit" name="logout" value="' . $lang->get('user_login_noact_btn_log_out') . '" /></p> |
1531 </form>'; |
1531 </form>'; |
1532 } |
1532 } |
1533 else |
1533 else |
1534 { |
1534 { |
1535 if ( $can_request && isset($_POST['activation_request']) ) |
1535 if ( $can_request && isset($_POST['activation_request']) ) |
1536 { |
1536 { |
1537 $this->admin_activation_request($userdata['username']); |
1537 $this->admin_activation_request($userdata['username']); |
1538 $form = '<p>' . $lang->get('user_login_noact_msg_admins_just_asked') . '</p> |
1538 $form = '<p>' . $lang->get('user_login_noact_msg_admins_just_asked') . '</p> |
1539 <form action="' . makeUrlNS('System', 'ActivateStub') . '" method="post"> |
1539 <form action="' . makeUrlNS('System', 'ActivateStub') . '" method="post"> |
1540 <p><input type="submit" name="logout" value="' . $lang->get('user_login_noact_btn_log_out') . '" /></p> |
1540 <p><input type="submit" name="logout" value="' . $lang->get('user_login_noact_btn_log_out') . '" /></p> |
1541 </form>'; |
1541 </form>'; |
1542 } |
1542 } |
1543 else |
1543 else |
1544 { |
1544 { |
1545 $form = '<p>' . $lang->get('user_login_noact_msg_admins_asked') . '</p> |
1545 $form = '<p>' . $lang->get('user_login_noact_msg_admins_asked') . '</p> |
1546 <form action="' . makeUrlNS('System', 'ActivateStub') . '" method="post"> |
1546 <form action="' . makeUrlNS('System', 'ActivateStub') . '" method="post"> |
1547 <p><input type="submit" name="logout" value="' . $lang->get('user_login_noact_btn_log_out') . '" /></p> |
1547 <p><input type="submit" name="logout" value="' . $lang->get('user_login_noact_btn_log_out') . '" /></p> |
1548 </form>'; |
1548 </form>'; |
1549 } |
1549 } |
1550 } |
1550 } |
1551 |
1551 |
1552 global $output; |
1552 global $output; |
1553 $output = new Output_HTML(); |
1553 $output = new Output_HTML(); |
1554 $output->set_title($lang->get('user_login_noact_title')); |
1554 $output->set_title($lang->get('user_login_noact_title')); |
1555 die_friendly($lang->get('user_login_noact_title'), '<p>' . $lang->get('user_login_noact_msg_intro') . ' '.$solution.'</p>' . $form); |
1555 die_friendly($lang->get('user_login_noact_title'), '<p>' . $lang->get('user_login_noact_msg_intro') . ' '.$solution.'</p>' . $form); |
1556 } |
1556 } |
1557 |
1557 |
1558 /** |
1558 /** |
1559 * Appends the high-privilege session key to the URL if we are authorized to do high-privilege stuff |
1559 * Appends the high-privilege session key to the URL if we are authorized to do high-privilege stuff |
1560 * @param string $url The URL to add session data to |
1560 * @param string $url The URL to add session data to |
1561 * @return string |
1561 * @return string |
1562 */ |
1562 */ |
1563 |
1563 |
1564 function append_sid($url) |
1564 function append_sid($url) |
1565 { |
1565 { |
1566 $sep = ( strstr($url, '?') ) ? '&' : '?'; |
1566 $sep = ( strstr($url, '?') ) ? '&' : '?'; |
1567 if ( $this->sid_super ) |
1567 if ( $this->sid_super ) |
1571 } |
1571 } |
1572 return $url; |
1572 return $url; |
1573 } |
1573 } |
1574 |
1574 |
1575 /** |
1575 /** |
1576 * Prevent the user from changing their password. Authentication plugins may call this to enforce single sign-on. |
1576 * Prevent the user from changing their password. Authentication plugins may call this to enforce single sign-on. |
1577 * @param string URL to page where the user may change their password |
1577 * @param string URL to page where the user may change their password |
1578 * @param string Title of the page where the user may change their password |
1578 * @param string Title of the page where the user may change their password |
1579 * @return null |
1579 * @return null |
1580 */ |
1580 */ |
1581 |
1581 |
1582 function disable_password_change($change_url = false, $change_title = false) |
1582 function disable_password_change($change_url = false, $change_title = false) |
1583 { |
1583 { |
1584 if ( $this->password_change_disabled ) |
1584 if ( $this->password_change_disabled ) |
1585 { |
1585 { |
1604 |
1604 |
1605 $this->password_change_disabled = true; |
1605 $this->password_change_disabled = true; |
1606 } |
1606 } |
1607 |
1607 |
1608 /** |
1608 /** |
1609 * Grabs the user's password MD5 - NOW DEPRECATED AND DISABLED. |
1609 * Grabs the user's password MD5 - NOW DEPRECATED AND DISABLED. |
1610 * @return bool false |
1610 * @return bool false |
1611 */ |
1611 */ |
1612 |
1612 |
1613 function grab_password_hash() |
1613 function grab_password_hash() |
1614 { |
1614 { |
1615 return false; |
1615 return false; |
1616 } |
1616 } |
1617 |
1617 |
1618 /** |
1618 /** |
1619 * Destroys the user's password MD5 in memory |
1619 * Destroys the user's password MD5 in memory |
1620 */ |
1620 */ |
1621 |
1621 |
1622 function disallow_password_grab() |
1622 function disallow_password_grab() |
1623 { |
1623 { |
1624 $this->password_hash = false; |
1624 $this->password_hash = false; |
1625 return false; |
1625 return false; |
1626 } |
1626 } |
1627 |
1627 |
1628 /** |
1628 /** |
1629 * Generates an AES key and stashes it in the database |
1629 * Generates an AES key and stashes it in the database |
1630 * @return string Hex-encoded AES key |
1630 * @return string Hex-encoded AES key |
1631 */ |
1631 */ |
1632 |
1632 |
1633 function rijndael_genkey() |
1633 static function rijndael_genkey() |
1634 { |
1634 { |
1635 $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE); |
1635 $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE); |
1636 $key = $aes->gen_readymade_key(); |
1636 $key = $aes->gen_readymade_key(); |
1637 $keys = getConfig('login_key_cache'); |
1637 $keys = getConfig('login_key_cache'); |
1638 if(is_string($keys)) |
1638 if(is_string($keys)) |
1642 setConfig('login_key_cache', $keys); |
1642 setConfig('login_key_cache', $keys); |
1643 return $key; |
1643 return $key; |
1644 } |
1644 } |
1645 |
1645 |
1646 /** |
1646 /** |
1647 * Generate a totally random 128-bit value for MD5 challenges |
1647 * Generate a totally random 128-bit value for MD5 challenges |
1648 * @return string |
1648 * @return string |
1649 */ |
1649 */ |
1650 |
1650 |
1651 function dss_rand() |
1651 static function dss_rand() |
1652 { |
1652 { |
1653 $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE); |
1653 $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE); |
1654 $random = $aes->randkey(128); |
1654 $random = $aes->randkey(128); |
1655 unset($aes); |
1655 unset($aes); |
1656 return md5(microtime() . $random); |
1656 return md5(microtime() . $random); |
1657 } |
1657 } |
1658 |
1658 |
1659 /** |
1659 /** |
1660 * Fetch a cached login public key using the MD5sum as an identifier. Each key can only be fetched once before it is destroyed. |
1660 * Fetch a cached login public key using the MD5sum as an identifier. Each key can only be fetched once before it is destroyed. |
1661 * @param string $md5 The MD5 sum of the key |
1661 * @param string $md5 The MD5 sum of the key |
1662 * @return string, or bool false on failure |
1662 * @return string, or bool false on failure |
1663 */ |
1663 */ |
1664 |
1664 |
1665 function fetch_public_key($md5) |
1665 function fetch_public_key($md5) |
1666 { |
1666 { |
1667 $keys = getConfig('login_key_cache'); |
1667 $keys = getConfig('login_key_cache'); |
1668 $keys = enano_str_split($keys, AES_BITS / 4); |
1668 $keys = enano_str_split($keys, AES_BITS / 4); |
1669 |
1669 |
1695 // Couldn't find the key... |
1695 // Couldn't find the key... |
1696 return false; |
1696 return false; |
1697 } |
1697 } |
1698 |
1698 |
1699 /** |
1699 /** |
1700 * Adds a user to a group. |
1700 * Adds a user to a group. |
1701 * @param int User ID |
1701 * @param int User ID |
1702 * @param int Group ID |
1702 * @param int Group ID |
1703 * @param bool Group moderator - defaults to false |
1703 * @param bool Group moderator - defaults to false |
1704 * @return bool True on success, false on failure |
1704 * @return bool True on success, false on failure |
1705 */ |
1705 */ |
1706 |
1706 |
1707 function add_user_to_group($user_id, $group_id, $is_mod = false) |
1707 function add_user_to_group($user_id, $group_id, $is_mod = false) |
1708 { |
1708 { |
1709 global $db, $session, $paths, $template, $plugins; // Common objects |
1709 global $db, $session, $paths, $template, $plugins; // Common objects |
1710 |
1710 |
1742 } |
1742 } |
1743 return false; |
1743 return false; |
1744 } |
1744 } |
1745 |
1745 |
1746 /** |
1746 /** |
1747 * Removes a user from a group. |
1747 * Removes a user from a group. |
1748 * @param int User ID |
1748 * @param int User ID |
1749 * @param int Group ID |
1749 * @param int Group ID |
1750 * @return bool True on success, false on failure |
1750 * @return bool True on success, false on failure |
1751 * @todo put a little more error checking in... |
1751 * @todo put a little more error checking in... |
1752 */ |
1752 */ |
1753 |
1753 |
1754 function remove_user_from_group($user_id, $group_id) |
1754 function remove_user_from_group($user_id, $group_id) |
1755 { |
1755 { |
1756 if ( !is_int($user_id) || !is_int($group_id) ) |
1756 if ( !is_int($user_id) || !is_int($group_id) ) |
1757 return false; |
1757 return false; |
1758 $this->sql('DELETE FROM '.table_prefix."group_members WHERE user_id=$user_id AND group_id=$group_id;"); |
1758 $this->sql('DELETE FROM '.table_prefix."group_members WHERE user_id=$user_id AND group_id=$group_id;"); |
1759 return true; |
1759 return true; |
1760 } |
1760 } |
1761 |
1761 |
1762 /** |
1762 /** |
1763 * Checks the banlist to ensure that we're an allowed user. Doesn't return anything because it dies if the user is banned. |
1763 * Checks the banlist to ensure that we're an allowed user. Doesn't return anything because it dies if the user is banned. |
1764 */ |
1764 */ |
1765 |
1765 |
1766 function check_banlist() |
1766 function check_banlist() |
1767 { |
1767 { |
1768 global $db, $session, $paths, $template, $plugins; // Common objects |
1768 global $db, $session, $paths, $template, $plugins; // Common objects |
1769 global $lang; |
1769 global $lang; |
1770 |
1770 |
1882 } |
1882 } |
1883 |
1883 |
1884 # Registration |
1884 # Registration |
1885 |
1885 |
1886 /** |
1886 /** |
1887 * Registers a user. This does not perform any type of login. |
1887 * Registers a user. This does not perform any type of login. |
1888 * @param string New user's username |
1888 * @param string New user's username |
1889 * @param string This should be unencrypted. |
1889 * @param string This should be unencrypted. |
1890 * @param string E-mail address. |
1890 * @param string E-mail address. |
1891 * @param string Optional, defaults to ''. |
1891 * @param string Optional, defaults to ''. |
1892 * @param bool Optional. If true, the account is not activated initially and an admin activation request is sent. The caller is responsible for sending the address info and notice. |
1892 * @param bool Optional. If true, the account is not activated initially and an admin activation request is sent. The caller is responsible for sending the address info and notice. |
1893 */ |
1893 */ |
1894 |
1894 |
1895 function create_user($username, $password, $email, $real_name = '', $coppa = false) |
1895 function create_user($username, $password, $email, $real_name = '', $coppa = false) |
1896 { |
1896 { |
1897 global $db, $session, $paths, $template, $plugins; // Common objects |
1897 global $db, $session, $paths, $template, $plugins; // Common objects |
1898 global $lang; |
1898 global $lang; |
1899 |
1899 |
1970 // Generate a totally random activation key |
1970 // Generate a totally random activation key |
1971 $actkey = sha1 ( microtime() . mt_rand() ); |
1971 $actkey = sha1 ( microtime() . mt_rand() ); |
1972 |
1972 |
1973 // We good, create the user |
1973 // We good, create the user |
1974 $this->sql('INSERT INTO ' . table_prefix . "users ( username, email, real_name, theme, style, reg_time, account_active, activation_key, user_level, user_coppa,\n" |
1974 $this->sql('INSERT INTO ' . table_prefix . "users ( username, email, real_name, theme, style, reg_time, account_active, activation_key, user_level, user_coppa,\n" |
1975 . " user_registration_ip, user_lang, user_has_avatar, avatar_type ) VALUES\n" |
1975 . " user_registration_ip, user_lang, user_has_avatar, avatar_type ) VALUES\n" |
1976 . " ( '$username', '$email', '$real_name', '$template->default_theme', '$template->default_style', " . time() . ", $active, '$actkey', \n" |
1976 . " ( '$username', '$email', '$real_name', '$template->default_theme', '$template->default_style', " . time() . ", $active, '$actkey', \n" |
1977 . " " . USER_LEVEL_CHPREF . ", $coppa_col, '$ip', $lang->lang_id, 0, 'png' );"); |
1977 . " " . USER_LEVEL_CHPREF . ", $coppa_col, '$ip', $lang->lang_id, 0, 'png' );"); |
1978 |
1978 |
1979 // Get user ID and create users_extra entry |
1979 // Get user ID and create users_extra entry |
1980 $q = $this->sql('SELECT user_id FROM '.table_prefix."users WHERE username='$username';"); |
1980 $q = $this->sql('SELECT user_id FROM '.table_prefix."users WHERE username='$username';"); |
1981 if ( $db->numrows() > 0 ) |
1981 if ( $db->numrows() > 0 ) |
1982 { |
1982 { |
2053 |
2053 |
2054 return 'success'; |
2054 return 'success'; |
2055 } |
2055 } |
2056 |
2056 |
2057 /** |
2057 /** |
2058 * Attempts to send an e-mail to the specified user with activation instructions. |
2058 * Attempts to send an e-mail to the specified user with activation instructions. |
2059 * @param string $u The usernamd of the user requesting activation |
2059 * @param string $u The usernamd of the user requesting activation |
2060 * @return bool true on success, false on failure |
2060 * @return bool true on success, false on failure |
2061 */ |
2061 */ |
2062 |
2062 |
2063 function send_activation_mail($u, $actkey = false) |
2063 function send_activation_mail($u, $actkey = false) |
2064 { |
2064 { |
2065 global $db, $session, $paths, $template, $plugins; // Common objects |
2065 global $db, $session, $paths, $template, $plugins; // Common objects |
2066 global $lang; |
2066 global $lang; |
2067 $q = $this->sql('SELECT username,activation_key,account_active,email FROM '.table_prefix.'users WHERE username=\''.$db->escape($u).'\';'); |
2067 $q = $this->sql('SELECT username,activation_key,account_active,email FROM '.table_prefix.'users WHERE username=\''.$db->escape($u).'\';'); |
2094 } |
2094 } |
2095 return $result; |
2095 return $result; |
2096 } |
2096 } |
2097 |
2097 |
2098 /** |
2098 /** |
2099 * Attempts to send an e-mail to the specified user's e-mail address on file intended for the parents |
2099 * Attempts to send an e-mail to the specified user's e-mail address on file intended for the parents |
2100 * @param string $u The usernamd of the user requesting activation |
2100 * @param string $u The usernamd of the user requesting activation |
2101 * @return bool true on success, false on failure |
2101 * @return bool true on success, false on failure |
2102 */ |
2102 */ |
2103 |
2103 |
2104 function send_coppa_mail($u, $actkey = false) |
2104 function send_coppa_mail($u, $actkey = false) |
2105 { |
2105 { |
2106 global $db, $session, $paths, $template, $plugins; // Common objects |
2106 global $db, $session, $paths, $template, $plugins; // Common objects |
2107 global $lang; |
2107 global $lang; |
2108 |
2108 |
2157 } |
2157 } |
2158 return $result; |
2158 return $result; |
2159 } |
2159 } |
2160 |
2160 |
2161 /** |
2161 /** |
2162 * Sends an e-mail to a user so they can reset their password. |
2162 * Sends an e-mail to a user so they can reset their password. |
2163 * @param int $user The user ID, or username if it's a string |
2163 * @param int $user The user ID, or username if it's a string |
2164 * @return bool true on success, false on failure |
2164 * @return bool true on success, false on failure |
2165 */ |
2165 */ |
2166 |
2166 |
2167 function mail_password_reset($user) |
2167 function mail_password_reset($user) |
2168 { |
2168 { |
2169 global $db, $session, $paths, $template, $plugins; // Common objects |
2169 global $db, $session, $paths, $template, $plugins; // Common objects |
2170 global $lang; |
2170 global $lang; |
2171 |
2171 |
2213 } |
2213 } |
2214 return $result; |
2214 return $result; |
2215 } |
2215 } |
2216 |
2216 |
2217 /** |
2217 /** |
2218 * Sets the temporary password for the specified user to whatever is specified. |
2218 * Sets the temporary password for the specified user to whatever is specified. |
2219 * @param int $user_id |
2219 * @param int $user_id |
2220 * @param string $password |
2220 * @param string $password |
2221 * @return bool |
2221 * @return bool |
2222 */ |
2222 */ |
2223 |
2223 |
2224 function register_temp_password($user_id, $password) |
2224 function register_temp_password($user_id, $password) |
2225 { |
2225 { |
2226 global $db; |
2226 global $db; |
2227 if ( !is_int($user_id) ) |
2227 if ( !is_int($user_id) ) |
2228 return false; |
2228 return false; |
2237 $temp_pass = hmac_sha1($password, $salt); |
2237 $temp_pass = hmac_sha1($password, $salt); |
2238 $this->sql('UPDATE '.table_prefix.'users SET temp_password=\'' . $temp_pass . '\',temp_password_time='.time().' WHERE user_id='.intval($user_id).';'); |
2238 $this->sql('UPDATE '.table_prefix.'users SET temp_password=\'' . $temp_pass . '\',temp_password_time='.time().' WHERE user_id='.intval($user_id).';'); |
2239 } |
2239 } |
2240 |
2240 |
2241 /** |
2241 /** |
2242 * Sends a request to the admin panel to have the username $u activated. |
2242 * Sends a request to the admin panel to have the username $u activated. |
2243 * @param string $u The username of the user requesting activation |
2243 * @param string $u The username of the user requesting activation |
2244 */ |
2244 */ |
2245 |
2245 |
2246 function admin_activation_request($u) |
2246 function admin_activation_request($u) |
2247 { |
2247 { |
2248 global $db; |
2248 global $db; |
2249 $this->sql('INSERT INTO '.table_prefix.'logs(log_type, action, time_id, date_string, author, edit_summary) VALUES(\'admin\', \'activ_req\', '.time().', \''.enano_date(ED_DATE | ED_TIME).'\', \''.$this->username.'\', \''.$db->escape($u).'\');'); |
2249 $this->sql('INSERT INTO '.table_prefix.'logs(log_type, action, time_id, date_string, author, edit_summary) VALUES(\'admin\', \'activ_req\', '.time().', \''.enano_date(ED_DATE | ED_TIME).'\', \''.$this->username.'\', \''.$db->escape($u).'\');'); |
2250 } |
2250 } |
2251 |
2251 |
2252 /** |
2252 /** |
2253 * Activates a user account. If the action fails, a report is sent to the admin. |
2253 * Activates a user account. If the action fails, a report is sent to the admin. |
2254 * @param string $user The username of the user requesting activation |
2254 * @param string $user The username of the user requesting activation |
2255 * @param string $key The activation key |
2255 * @param string $key The activation key |
2256 */ |
2256 */ |
2257 |
2257 |
2258 function activate_account($user, $key) |
2258 function activate_account($user, $key) |
2259 { |
2259 { |
2260 global $db, $session, $paths, $template, $plugins; // Common objects |
2260 global $db, $session, $paths, $template, $plugins; // Common objects |
2261 $q = $this->sql('SELECT 1 FROM ' . table_prefix . 'users WHERE username = \''.$db->escape($user).'\' AND activation_key = \''.$db->escape($key).'\''); |
2261 $q = $this->sql('SELECT 1 FROM ' . table_prefix . 'users WHERE username = \''.$db->escape($user).'\' AND activation_key = \''.$db->escape($key).'\''); |
2272 return false; |
2272 return false; |
2273 } |
2273 } |
2274 } |
2274 } |
2275 |
2275 |
2276 /** |
2276 /** |
2277 * For a given user level identifier (USER_LEVEL_*), returns a string describing that user level. |
2277 * For a given user level identifier (USER_LEVEL_*), returns a string describing that user level. |
2278 * @param int User level |
2278 * @param int User level |
2279 * @param bool If true, returns a shorter string. Optional. |
2279 * @param bool If true, returns a shorter string. Optional. |
2280 * @return string |
2280 * @return string |
2281 */ |
2281 */ |
2282 |
2282 |
2283 function userlevel_to_string($user_level, $short = false) |
2283 function userlevel_to_string($user_level, $short = false) |
2284 { |
2284 { |
2285 global $lang; |
2285 global $lang; |
2286 |
2286 |
2343 return 'Linux rocks!'; |
2343 return 'Linux rocks!'; |
2344 |
2344 |
2345 } |
2345 } |
2346 |
2346 |
2347 /** |
2347 /** |
2348 * Change a user's e-mail address. |
2348 * Change a user's e-mail address. |
2349 * @param int $user_id The user ID of the user to update - this cannot be changed |
2349 * @param int $user_id The user ID of the user to update - this cannot be changed |
2350 * @param string $email The new e-mail address |
2350 * @param string $email The new e-mail address |
2351 * @return string 'success' if successful, or array of error strings on failure |
2351 * @return string 'success' if successful, or array of error strings on failure |
2352 */ |
2352 */ |
2353 |
2353 |
2354 function change_email($user_id, $email) |
2354 function change_email($user_id, $email) |
2355 { |
2355 { |
2356 global $db, $session, $paths, $template, $plugins; // Common objects |
2356 global $db, $session, $paths, $template, $plugins; // Common objects |
2357 |
2357 |
2358 // Create some arrays |
2358 // Create some arrays |
2420 // Yay! We're done |
2420 // Yay! We're done |
2421 return 'success'; |
2421 return 'success'; |
2422 } |
2422 } |
2423 |
2423 |
2424 /** |
2424 /** |
2425 * Sets a user's password. |
2425 * Sets a user's password. |
2426 * @param int|string User ID or username |
2426 * @param int|string User ID or username |
2427 * @param string New password |
2427 * @param string New password |
2428 */ |
2428 */ |
2429 |
2429 |
2430 function set_password($user, $password) |
2430 function set_password($user, $password) |
2431 { |
2431 { |
2432 // Generate new password and salt |
2432 // Generate new password and salt |
2433 $hmac_secret = hexencode(AESCrypt::randkey(20), '', ''); |
2433 $hmac_secret = hexencode(AESCrypt::randkey(20), '', ''); |
2441 |
2441 |
2442 return true; |
2442 return true; |
2443 } |
2443 } |
2444 |
2444 |
2445 /** |
2445 /** |
2446 * Encrypts a string using the site's private key. |
2446 * Encrypts a string using the site's private key. |
2447 * @param string |
2447 * @param string |
2448 * @param int Return type - one of ENC_BINARY, ENC_HEX, ENC_BASE64 |
2448 * @param int Return type - one of ENC_BINARY, ENC_HEX, ENC_BASE64 |
2449 * @return string |
2449 * @return string |
2450 */ |
2450 */ |
2451 |
2451 |
2452 function pk_encrypt($string, $return_type = ENC_HEX) |
2452 function pk_encrypt($string, $return_type = ENC_HEX) |
2453 { |
2453 { |
2454 $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE); |
2454 $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE); |
2455 return $aes->encrypt($string, $this->private_key, $return_type); |
2455 return $aes->encrypt($string, $this->private_key, $return_type); |
2456 } |
2456 } |
2457 |
2457 |
2458 /** |
2458 /** |
2459 * Encrypts a string using the site's private key. |
2459 * Encrypts a string using the site's private key. |
2460 * @param string |
2460 * @param string |
2461 * @param int Input type - one of ENC_BINARY, ENC_HEX, ENC_BASE64 |
2461 * @param int Input type - one of ENC_BINARY, ENC_HEX, ENC_BASE64 |
2462 * @return string |
2462 * @return string |
2463 */ |
2463 */ |
2464 |
2464 |
2465 function pk_decrypt($string, $input_type = ENC_HEX) |
2465 function pk_decrypt($string, $input_type = ENC_HEX) |
2466 { |
2466 { |
2467 $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE); |
2467 $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE); |
2468 return $aes->decrypt($string, $this->private_key, $input_type); |
2468 return $aes->decrypt($string, $this->private_key, $input_type); |
2471 # |
2471 # |
2472 # USER RANKS |
2472 # USER RANKS |
2473 # |
2473 # |
2474 |
2474 |
2475 /** |
2475 /** |
2476 * SYNOPSIS OF THE RANK SYSTEM |
2476 * SYNOPSIS OF THE RANK SYSTEM |
2477 * Enano's rank logic calculates a user's rank based on a precedence scale. The way things are checked is: |
2477 * Enano's rank logic calculates a user's rank based on a precedence scale. The way things are checked is: |
2478 * 1. Check to see if the user has a specific rank assigned. Use that if possible. |
2478 * 1. Check to see if the user has a specific rank assigned. Use that if possible. |
2479 * 2. Check the user's primary group to see if it specifies a rank. Use that if possible. |
2479 * 2. Check the user's primary group to see if it specifies a rank. Use that if possible. |
2480 * 3. Check the other groups a user is in. If one that has a custom rank is encountered, use that rank. |
2480 * 3. Check the other groups a user is in. If one that has a custom rank is encountered, use that rank. |
2481 * 4. See if the user's user level has a specific rank hard-coded to be associated with it. (Always overrideable as can be seen above) |
2481 * 4. See if the user's user level has a specific rank hard-coded to be associated with it. (Always overrideable as can be seen above) |
2482 * 5. Use the "member" rank |
2482 * 5. Use the "member" rank |
2483 */ |
2483 */ |
2484 |
2484 |
2485 /** |
2485 /** |
2486 * Generates a textual SQL query for fetching rank data to be sent to calculate_user_rank(). |
2486 * Generates a textual SQL query for fetching rank data to be sent to calculate_user_rank(). |
2487 * @param string Text to append, possibly a WHERE clause or so |
2487 * @param string Text to append, possibly a WHERE clause or so |
2488 * @return string |
2488 * @return string |
2489 */ |
2489 */ |
2490 |
2490 |
2491 function generate_rank_sql($append = '') |
2491 function generate_rank_sql($append = '') |
2492 { |
2492 { |
2493 // Generate level-to-rank associations |
2493 // Generate level-to-rank associations |
2494 $assoc = array(); |
2494 $assoc = array(); |
2502 'array_to_string(' . table_prefix . 'array_accum(m.group_id), \',\') AS group_list' : |
2502 'array_to_string(' . table_prefix . 'array_accum(m.group_id), \',\') AS group_list' : |
2503 'GROUP_CONCAT(m.group_id) AS group_list'; |
2503 'GROUP_CONCAT(m.group_id) AS group_list'; |
2504 |
2504 |
2505 // The actual query |
2505 // The actual query |
2506 $sql = "SELECT u.user_id, u.username, u.user_level, u.user_group, u.user_rank, u.user_title, g.group_rank,\n" |
2506 $sql = "SELECT u.user_id, u.username, u.user_level, u.user_group, u.user_rank, u.user_title, g.group_rank,\n" |
2507 . " COALESCE(ru.rank_id, rg.rank_id, rl.rank_id, rd.rank_id ) AS rank_id,\n" |
2507 . " COALESCE(ru.rank_id, rg.rank_id, rl.rank_id, rd.rank_id ) AS rank_id,\n" |
2508 . " COALESCE(ru.rank_title, rg.rank_title, rl.rank_title, rd.rank_title) AS rank_title,\n" |
2508 . " COALESCE(ru.rank_title, rg.rank_title, rl.rank_title, rd.rank_title) AS rank_title,\n" |
2509 . " COALESCE(ru.rank_style, rg.rank_style, rl.rank_style, rd.rank_style) AS rank_style,\n" |
2509 . " COALESCE(ru.rank_style, rg.rank_style, rl.rank_style, rd.rank_style) AS rank_style,\n" |
2510 . " rg.rank_id AS group_rank_id,\n" |
2510 . " rg.rank_id AS group_rank_id,\n" |
2511 . " ( ru.rank_id IS NULL AND rg.rank_id IS NULL ) AS using_default,\n" |
2511 . " ( ru.rank_id IS NULL AND rg.rank_id IS NULL ) AS using_default,\n" |
2512 . " ( ru.rank_id IS NULL AND rg.rank_id IS NOT NULL ) AS using_group,\n" |
2512 . " ( ru.rank_id IS NULL AND rg.rank_id IS NOT NULL ) AS using_group,\n" |
2513 . " ( ru.rank_id IS NOT NULL ) AS using_user,\n" |
2513 . " ( ru.rank_id IS NOT NULL ) AS using_user,\n" |
2514 . " u.user_rank_userset,\n" |
2514 . " u.user_rank_userset,\n" |
2515 . " $gid_col\n" |
2515 . " $gid_col\n" |
2516 . " FROM " . table_prefix . "users AS u\n" |
2516 . " FROM " . table_prefix . "users AS u\n" |
2517 . " LEFT JOIN " . table_prefix . "groups AS g\n" |
2517 . " LEFT JOIN " . table_prefix . "groups AS g\n" |
2518 . " ON ( g.group_id = u.user_group )\n" |
2518 . " ON ( g.group_id = u.user_group )\n" |
2519 . " LEFT JOIN " . table_prefix . "group_members AS m\n" |
2519 . " LEFT JOIN " . table_prefix . "group_members AS m\n" |
2520 . " ON ( u.user_id = m.user_id )\n" |
2520 . " ON ( u.user_id = m.user_id )\n" |
2521 . " LEFT JOIN " . table_prefix . "ranks AS ru\n" |
2521 . " LEFT JOIN " . table_prefix . "ranks AS ru\n" |
2522 . " ON ( u.user_rank = ru.rank_id )\n" |
2522 . " ON ( u.user_rank = ru.rank_id )\n" |
2523 . " LEFT JOIN " . table_prefix . "ranks AS rg\n" |
2523 . " LEFT JOIN " . table_prefix . "ranks AS rg\n" |
2524 . " ON ( g.group_rank = rg.rank_id )\n" |
2524 . " ON ( g.group_rank = rg.rank_id )\n" |
2525 . " LEFT JOIN " . table_prefix . "ranks AS rl\n" |
2525 . " LEFT JOIN " . table_prefix . "ranks AS rl\n" |
2526 . " ON (\n" |
2526 . " ON (\n" |
2527 . $assoc |
2527 . $assoc |
2528 . " )\n" |
2528 . " )\n" |
2529 . " LEFT JOIN " . table_prefix . "ranks AS rd\n" |
2529 . " LEFT JOIN " . table_prefix . "ranks AS rd\n" |
2530 . " ON ( rd.rank_id = 1 )$append\n" |
2530 . " ON ( rd.rank_id = 1 )$append\n" |
2531 . " GROUP BY u.user_id, u.username, u.user_level, u.user_group, u.user_rank, u.user_title, u.user_rank_userset, g.group_rank,\n" |
2531 . " GROUP BY u.user_id, u.username, u.user_level, u.user_group, u.user_rank, u.user_title, u.user_rank_userset, g.group_rank,\n" |
2532 . " ru.rank_id, ru.rank_title, ru.rank_style,rg.rank_id, rg.rank_title, rg.rank_style,\n" |
2532 . " ru.rank_id, ru.rank_title, ru.rank_style,rg.rank_id, rg.rank_title, rg.rank_style,\n" |
2533 . " rl.rank_id, rl.rank_title, rl.rank_style,rd.rank_id, rd.rank_title, rd.rank_style;"; |
2533 . " rl.rank_id, rl.rank_title, rl.rank_style,rd.rank_id, rd.rank_title, rd.rank_style;"; |
2534 |
2534 |
2535 return $sql; |
2535 return $sql; |
2536 } |
2536 } |
2537 |
2537 |
2538 /** |
2538 /** |
2539 * Returns an associative array with a user's rank information. |
2539 * Returns an associative array with a user's rank information. |
2540 * The array will contain the following values: |
2540 * The array will contain the following values: |
2541 * username: string The user's username |
2541 * username: string The user's username |
2542 * user_id: integer Numerical user ID |
2542 * user_id: integer Numerical user ID |
2543 * rank_id: integer Numerical rank ID |
2543 * rank_id: integer Numerical rank ID |
2544 * rank: string The user's current rank |
2544 * rank: string The user's current rank |
2545 * title: string The user's custom user title if applicable; should be displayed one line below the rank |
2545 * title: string The user's custom user title if applicable; should be displayed one line below the rank |
2546 * style: string CSS for the username |
2546 * style: string CSS for the username |
2547 * @param int|string Username *or* user ID |
2547 * @param int|string Username *or* user ID |
2548 * @return array or false on failure |
2548 * @return array or false on failure |
2549 */ |
2549 */ |
2550 |
2550 |
2551 function get_user_rank($id) |
2551 function get_user_rank($id) |
2552 { |
2552 { |
2553 global $db, $session, $paths, $template, $plugins; // Common objects |
2553 global $db, $session, $paths, $template, $plugins; // Common objects |
2554 global $lang; |
2554 global $lang; |
2613 $_cache[$id] = $row; |
2613 $_cache[$id] = $row; |
2614 return $row; |
2614 return $row; |
2615 } |
2615 } |
2616 |
2616 |
2617 /** |
2617 /** |
2618 * Performs the actual rank calculation based on the contents of a row. |
2618 * Performs the actual rank calculation based on the contents of a row. |
2619 * @param array |
2619 * @param array |
2620 * @return array |
2620 * @return array |
2621 */ |
2621 */ |
2622 |
2622 |
2623 function calculate_user_rank($row) |
2623 function calculate_user_rank($row) |
2624 { |
2624 { |
2625 global $db, $session, $paths, $template, $plugins; // Common objects |
2625 global $db, $session, $paths, $template, $plugins; // Common objects |
2626 global $lang; |
2626 global $lang; |
2716 unset($row['user_rank'], $row['group_rank'], $row['group_list'], $row['using_default'], $row['using_group'], $row['user_level'], $row['user_group'], $row['username']); |
2716 unset($row['user_rank'], $row['group_rank'], $row['group_list'], $row['using_default'], $row['using_group'], $row['user_level'], $row['user_group'], $row['username']); |
2717 return $row; |
2717 return $row; |
2718 } |
2718 } |
2719 |
2719 |
2720 /** |
2720 /** |
2721 * Get the list of ranks that a user is allowed to use. Returns false if they cannot change it. |
2721 * Get the list of ranks that a user is allowed to use. Returns false if they cannot change it. |
2722 * @param string|int User ID or username |
2722 * @param string|int User ID or username |
2723 * @return array Associative by rank ID |
2723 * @return array Associative by rank ID |
2724 */ |
2724 */ |
2725 |
2725 |
2726 function get_user_possible_ranks($id) |
2726 function get_user_possible_ranks($id) |
2727 { |
2727 { |
2728 global $db, $session, $paths, $template, $plugins; // Common objects |
2728 global $db, $session, $paths, $template, $plugins; // Common objects |
2729 |
2729 |
2823 # |
2823 # |
2824 # Access Control Lists |
2824 # Access Control Lists |
2825 # |
2825 # |
2826 |
2826 |
2827 /** |
2827 /** |
2828 * Creates a new permission field in memory. If the permissions are set in the database, they are used. Otherwise, $default_perm is used. |
2828 * Creates a new permission field in memory. If the permissions are set in the database, they are used. Otherwise, $default_perm is used. |
2829 * @param string $acl_type An identifier for this field |
2829 * @param string $acl_type An identifier for this field |
2830 * @param int $default_perm Whether permission should be granted or not if it's not specified in the ACLs. |
2830 * @param int $default_perm Whether permission should be granted or not if it's not specified in the ACLs. |
2831 * @param string $desc A human readable name for the permission type |
2831 * @param string $desc A human readable name for the permission type |
2832 * @param array $deps The list of dependencies - this should be an array of ACL types |
2832 * @param array $deps The list of dependencies - this should be an array of ACL types |
2833 * @param string $scope Which namespaces this field should apply to. This should be either a pipe-delimited list of namespace IDs or just "All". |
2833 * @param string $scope Which namespaces this field should apply to. This should be either a pipe-delimited list of namespace IDs or just "All". |
2834 */ |
2834 */ |
2835 |
2835 |
2836 function register_acl_type($acl_type, $default_perm = AUTH_DISALLOW, $desc = false, $deps = Array(), $scope = 'All') |
2836 function register_acl_type($acl_type, $default_perm = AUTH_DISALLOW, $desc = false, $deps = Array(), $scope = 'All') |
2837 { |
2837 { |
2838 if(isset($this->acl_types[$acl_type])) |
2838 if(isset($this->acl_types[$acl_type])) |
2839 return false; |
2839 return false; |
2840 else |
2840 else |
2850 } |
2850 } |
2851 return true; |
2851 return true; |
2852 } |
2852 } |
2853 |
2853 |
2854 /** |
2854 /** |
2855 * Tells us whether permission $type is allowed or not based on the current rules. |
2855 * Tells us whether permission $type is allowed or not based on the current rules. |
2856 * @param string $type The permission identifier ($acl_type passed to sessionManager::register_acl_type()) |
2856 * @param string $type The permission identifier ($acl_type passed to sessionManager::register_acl_type()) |
2857 * @param bool $no_deps If true, disables dependency checking |
2857 * @param bool $no_deps If true, disables dependency checking |
2858 * @return bool True if allowed, false if denied or if an error occured |
2858 * @return bool True if allowed, false if denied or if an error occured |
2859 */ |
2859 */ |
2860 |
2860 |
2861 function get_permissions($type, $no_deps = false) |
2861 function get_permissions($type, $no_deps = false) |
2862 { |
2862 { |
2863 global $db, $session, $paths, $template, $plugins; // Common objects |
2863 global $db, $session, $paths, $template, $plugins; // Common objects |
2864 if ( isset( $this->perms[$type] ) ) |
2864 if ( isset( $this->perms[$type] ) ) |
2865 { |
2865 { |
2900 } |
2900 } |
2901 return $ret; |
2901 return $ret; |
2902 } |
2902 } |
2903 |
2903 |
2904 /** |
2904 /** |
2905 * Fetch the permissions that apply to the current user for the page specified. The object you get will have the get_permissions method |
2905 * Fetch the permissions that apply to the current user for the page specified. The object you get will have the get_permissions method |
2906 * and several other abilities. |
2906 * and several other abilities. |
2907 * @param string $page_id |
2907 * @param string $page_id |
2908 * @param string $namespace |
2908 * @param string $namespace |
2909 * @return object |
2909 * @return object |
2910 */ |
2910 */ |
2911 |
2911 |
2912 function fetch_page_acl($page_id, $namespace) |
2912 function fetch_page_acl($page_id, $namespace) |
2913 { |
2913 { |
2914 global $db, $session, $paths, $template, $plugins; // Common objects |
2914 global $db, $session, $paths, $template, $plugins; // Common objects |
2915 |
2915 |
2916 if ( count ( $this->acl_base_cache ) < 1 ) |
2916 if ( count ( $this->acl_base_cache ) < 1 ) |
2942 |
2942 |
2943 return $object; |
2943 return $object; |
2944 } |
2944 } |
2945 |
2945 |
2946 /** |
2946 /** |
2947 * Fetch the permissions that apply to an arbitrary user for the page specified. The object you get will have the get_permissions method |
2947 * Fetch the permissions that apply to an arbitrary user for the page specified. The object you get will have the get_permissions method |
2948 * and several other abilities. |
2948 * and several other abilities. |
2949 * @param int|string $user_id_or_name; user ID *or* username of the user |
2949 * @param int|string $user_id_or_name; user ID *or* username of the user |
2950 * @param string $page_id; if null, will be default effective permissions. |
2950 * @param string $page_id; if null, will be default effective permissions. |
2951 * @param string $namespace; if null, will be default effective permissions. |
2951 * @param string $namespace; if null, will be default effective permissions. |
2952 * @return object |
2952 * @return object |
2953 */ |
2953 */ |
2954 |
2954 |
2955 function fetch_page_acl_user($user_id_or_name, $page_id, $namespace) |
2955 function fetch_page_acl_user($user_id_or_name, $page_id, $namespace) |
2956 { |
2956 { |
2957 global $db, $session, $paths, $template, $plugins; // Common objects |
2957 global $db, $session, $paths, $template, $plugins; // Common objects |
2958 |
2958 |
3103 |
3103 |
3104 return $object; |
3104 return $object; |
3105 } |
3105 } |
3106 |
3106 |
3107 /** |
3107 /** |
3108 * Checks if the given ACL rule type applies to a namespace. |
3108 * Checks if the given ACL rule type applies to a namespace. |
3109 * @param string ACL rule type |
3109 * @param string ACL rule type |
3110 * @param string Namespace |
3110 * @param string Namespace |
3111 * @return bool |
3111 * @return bool |
3112 */ |
3112 */ |
3113 |
3113 |
3114 function check_acl_scope($acl_rule, $namespace) |
3114 function check_acl_scope($acl_rule, $namespace) |
3115 { |
3115 { |
3116 if ( !isset($this->acl_scope[$acl_rule]) ) |
3116 if ( !isset($this->acl_scope[$acl_rule]) ) |
3117 return false; |
3117 return false; |
3119 return true; |
3119 return true; |
3120 return ( in_array($namespace, $this->acl_scope[$acl_rule]) ) ? true : false; |
3120 return ( in_array($namespace, $this->acl_scope[$acl_rule]) ) ? true : false; |
3121 } |
3121 } |
3122 |
3122 |
3123 /** |
3123 /** |
3124 * Read all of our permissions from the database and process/apply them. This should be called after the page is determined. |
3124 * Read all of our permissions from the database and process/apply them. This should be called after the page is determined. |
3125 * @access private |
3125 * @access private |
3126 */ |
3126 */ |
3127 |
3127 |
3128 function init_permissions() |
3128 function init_permissions() |
3129 { |
3129 { |
3130 global $db, $session, $paths, $template, $plugins; // Common objects |
3130 global $db, $session, $paths, $template, $plugins; // Common objects |
3131 // Initialize the permissions list with some defaults |
3131 // Initialize the permissions list with some defaults |
3132 $this->perms = $this->acl_types; |
3132 $this->perms = $this->acl_types; |
3133 $this->acl_defaults_used = $this->perms; |
3133 $this->acl_defaults_used = $this->perms; |
3134 |
3134 |
3135 // Fetch sitewide defaults from the permissions table |
3135 // Fetch sitewide defaults from the permissions table |
3136 $bs = 'SELECT rules, target_type, target_id FROM '.table_prefix.'acl' . "\n" |
3136 $bs = 'SELECT rules, target_type, target_id FROM '.table_prefix.'acl' . "\n" |
3137 . ' WHERE page_id IS NULL AND namespace IS NULL AND' . "\n" |
3137 . ' WHERE page_id IS NULL AND namespace IS NULL AND' . "\n" |
3138 . ' ( '; |
3138 . ' ( '; |
3139 |
3139 |
3140 $q = Array(); |
3140 $q = Array(); |
3141 $q[] = '( target_type='.ACL_TYPE_USER.' AND target_id='.$this->user_id.' )'; |
3141 $q[] = '( target_type='.ACL_TYPE_USER.' AND target_id='.$this->user_id.' )'; |
3142 if(count($this->groups) > 0) |
3142 if(count($this->groups) > 0) |
3143 { |
3143 { |
3167 $this->perms = $page_acl->perms; |
3167 $this->perms = $page_acl->perms; |
3168 $this->acl_defaults_used = $page_acl->acl_defaults_used; |
3168 $this->acl_defaults_used = $page_acl->acl_defaults_used; |
3169 } |
3169 } |
3170 |
3170 |
3171 /** |
3171 /** |
3172 * Extends the scope of a permission type. |
3172 * Extends the scope of a permission type. |
3173 * @param string The name of the permission type |
3173 * @param string The name of the permission type |
3174 * @param string The namespace(s) that should be covered. This can be either one namespace ID or a pipe-delimited list. |
3174 * @param string The namespace(s) that should be covered. This can be either one namespace ID or a pipe-delimited list. |
3175 * @param object Optional - the current $paths object, in case we're doing this from the acl_rule_init hook |
3175 * @param object Optional - the current $paths object, in case we're doing this from the acl_rule_init hook |
3176 */ |
3176 */ |
3177 |
3177 |
3178 function acl_extend_scope($perm_type, $namespaces, &$p_in) |
3178 function acl_extend_scope($perm_type, $namespaces, &$p_in) |
3179 { |
3179 { |
3180 global $db, $session, $paths, $template, $plugins; // Common objects |
3180 global $db, $session, $paths, $template, $plugins; // Common objects |
3181 $p_obj = ( is_object($p_in) ) ? $p_in : $paths; |
3181 $p_obj = ( is_object($p_in) ) ? $p_in : $paths; |
3182 $nslist = explode('|', $namespaces); |
3182 $nslist = explode('|', $namespaces); |
3197 } |
3197 } |
3198 } |
3198 } |
3199 } |
3199 } |
3200 |
3200 |
3201 /** |
3201 /** |
3202 * Converts a permissions field into a string for database insertion. Similar in spirit to serialize(). |
3202 * Converts a permissions field into a string for database insertion. Similar in spirit to serialize(). |
3203 * @param array $perms An associative array with only integers as values |
3203 * @param array $perms An associative array with only integers as values |
3204 * @return string |
3204 * @return string |
3205 */ |
3205 */ |
3206 |
3206 |
3207 function perm_to_string($perms) |
3207 function perm_to_string($perms) |
3208 { |
3208 { |
3209 $s = ''; |
3209 $s = ''; |
3210 foreach($perms as $perm => $ac) |
3210 foreach($perms as $perm => $ac) |
3211 { |
3211 { |
3215 } |
3215 } |
3216 return $s; |
3216 return $s; |
3217 } |
3217 } |
3218 |
3218 |
3219 /** |
3219 /** |
3220 * Converts a permissions string back to an array. |
3220 * Converts a permissions string back to an array. |
3221 * @param string $perms The result from sessionManager::perm_to_string() |
3221 * @param string $perms The result from sessionManager::perm_to_string() |
3222 * @return array |
3222 * @return array |
3223 */ |
3223 */ |
3224 |
3224 |
3225 function string_to_perm($perms) |
3225 function string_to_perm($perms) |
3226 { |
3226 { |
3227 $ret = Array(); |
3227 $ret = Array(); |
3228 preg_match_all('#([a-z0-9_-]+)=([0-9]+);#i', $perms, $matches); |
3228 preg_match_all('#([a-z0-9_-]+)=([0-9]+);#i', $perms, $matches); |
3229 foreach($matches[1] as $i => $t) |
3229 foreach($matches[1] as $i => $t) |
3232 } |
3232 } |
3233 return $ret; |
3233 return $ret; |
3234 } |
3234 } |
3235 |
3235 |
3236 /** |
3236 /** |
3237 * Merges two ACL arrays. Both parameters should be permission list arrays. The second group takes precedence over the first, but AUTH_DENY always prevails. |
3237 * Merges two ACL arrays. Both parameters should be permission list arrays. The second group takes precedence over the first, but AUTH_DENY always prevails. |
3238 * @param array $perm1 The first set of permissions |
3238 * @param array $perm1 The first set of permissions |
3239 * @param array $perm2 The second set of permissions |
3239 * @param array $perm2 The second set of permissions |
3240 * @param bool $is_everyone If true, applies exceptions for "Everyone" group |
3240 * @param bool $is_everyone If true, applies exceptions for "Everyone" group |
3241 * @param array|reference $defaults_used Array that will be filled with default usage data |
3241 * @param array|reference $defaults_used Array that will be filled with default usage data |
3242 * @return array |
3242 * @return array |
3243 */ |
3243 */ |
3244 |
3244 |
3245 function acl_merge($perm1, $perm2, $is_everyone = false, &$defaults_used = array()) |
3245 function acl_merge($perm1, $perm2, $is_everyone = false, &$defaults_used = array()) |
3246 { |
3246 { |
3247 $ret = $perm1; |
3247 $ret = $perm1; |
3248 if ( !is_array(@$defaults_used) ) |
3248 if ( !is_array(@$defaults_used) ) |
3249 { |
3249 { |
3288 } |
3288 } |
3289 return $perm1; |
3289 return $perm1; |
3290 } |
3290 } |
3291 |
3291 |
3292 /** |
3292 /** |
3293 * Merges two ACL arrays, but instead of calculating inheritance for missing permission types, just returns 'i' for that type. Useful |
3293 * Merges two ACL arrays, but instead of calculating inheritance for missing permission types, just returns 'i' for that type. Useful |
3294 * for explicitly requiring inheritance in ACL editing interfaces |
3294 * for explicitly requiring inheritance in ACL editing interfaces |
3295 * @param array $perm1 The first set of permissions |
3295 * @param array $perm1 The first set of permissions |
3296 * @param array $perm2 The second, authoritative set of permissions |
3296 * @param array $perm2 The second, authoritative set of permissions |
3297 */ |
3297 */ |
3298 |
3298 |
3299 function acl_merge_inherit($perm1, $perm2) |
3299 function acl_merge_inherit($perm1, $perm2) |
3300 { |
3300 { |
3301 foreach ( $perm1 as $type => $level ) |
3301 foreach ( $perm1 as $type => $level ) |
3302 { |
3302 { |
3313 } |
3313 } |
3314 return $ret; |
3314 return $ret; |
3315 } |
3315 } |
3316 |
3316 |
3317 /** |
3317 /** |
3318 * Merges the ACL array sent with the current permissions table, deciding precedence based on whether defaults are in effect or not. |
3318 * Merges the ACL array sent with the current permissions table, deciding precedence based on whether defaults are in effect or not. |
3319 * @param array The array to merge into the master ACL list |
3319 * @param array The array to merge into the master ACL list |
3320 * @param bool If true, $perm is treated as the "new default" |
3320 * @param bool If true, $perm is treated as the "new default" |
3321 * @param int 1 if this is a site-wide ACL, 2 if page-specific. Defaults to 2. |
3321 * @param int 1 if this is a site-wide ACL, 2 if page-specific. Defaults to 2. |
3322 */ |
3322 */ |
3323 |
3323 |
3324 function acl_merge_with_current($perm, $is_everyone = false, $scope = 2) |
3324 function acl_merge_with_current($perm, $is_everyone = false, $scope = 2) |
3325 { |
3325 { |
3326 $this->perms = $this->acl_merge($this->perms, $perm, $is_everyone, $this->acl_defaults_used); |
3326 $this->perms = $this->acl_merge($this->perms, $perm, $is_everyone, $this->acl_defaults_used); |
3327 } |
3327 } |
3328 |
3328 |
3329 /** |
3329 /** |
3330 * Merges two ACL arrays. Both parameters should be permission list arrays. The second group takes precedence |
3330 * Merges two ACL arrays. Both parameters should be permission list arrays. The second group takes precedence |
3331 * over the first, without exceptions. This is used to merge the hardcoded defaults with admin-specified |
3331 * over the first, without exceptions. This is used to merge the hardcoded defaults with admin-specified |
3332 * defaults, which take precedence. |
3332 * defaults, which take precedence. |
3333 * @param array $perm1 The first set of permissions |
3333 * @param array $perm1 The first set of permissions |
3334 * @param array $perm2 The second set of permissions |
3334 * @param array $perm2 The second set of permissions |
3335 * @return array |
3335 * @return array |
3336 */ |
3336 */ |
3337 |
3337 |
3338 function acl_merge_complete($perm1, $perm2) |
3338 function acl_merge_complete($perm1, $perm2) |
3339 { |
3339 { |
3340 $ret = $perm1; |
3340 $ret = $perm1; |
3341 foreach ( $perm2 as $type => $level ) |
3341 foreach ( $perm2 as $type => $level ) |
3342 { |
3342 { |
3344 } |
3344 } |
3345 return $ret; |
3345 return $ret; |
3346 } |
3346 } |
3347 |
3347 |
3348 /** |
3348 /** |
3349 * Tell us if the dependencies for a given permission are met. |
3349 * Tell us if the dependencies for a given permission are met. |
3350 * @param string The ACL permission ID |
3350 * @param string The ACL permission ID |
3351 * @return bool |
3351 * @return bool |
3352 */ |
3352 */ |
3353 |
3353 |
3354 function acl_check_deps($type, $debug = false) |
3354 function acl_check_deps($type, $debug = false) |
3355 { |
3355 { |
3356 global $paths; |
3356 global $paths; |
3357 |
3357 |
3358 // This will only happen if the permissions table is hacked or improperly accessed |
3358 // This will only happen if the permissions table is hacked or improperly accessed |
3402 } |
3402 } |
3403 return $debug ? $debugdata : true; |
3403 return $debug ? $debugdata : true; |
3404 } |
3404 } |
3405 |
3405 |
3406 /** |
3406 /** |
3407 * Makes a CAPTCHA code and caches the code in the database |
3407 * Makes a CAPTCHA code and caches the code in the database |
3408 * @param int $len The length of the code, in bytes |
3408 * @param int $len The length of the code, in bytes |
3409 * @param string Optional, the hash to reuse |
3409 * @param string Optional, the hash to reuse |
3410 * @return string A unique identifier assigned to the code. This hash should be passed to sessionManager::getCaptcha() to retrieve the code. |
3410 * @return string A unique identifier assigned to the code. This hash should be passed to sessionManager::getCaptcha() to retrieve the code. |
3411 */ |
3411 */ |
3412 |
3412 |
3413 function make_captcha($len = 7, $hash = '') |
3413 function make_captcha($len = 7, $hash = '') |
3414 { |
3414 { |
3415 global $db, $session, $paths, $template, $plugins; // Common objects |
3415 global $db, $session, $paths, $template, $plugins; // Common objects |
3416 $code = $this->generate_captcha_code($len); |
3416 $code = $this->generate_captcha_code($len); |
3426 $this->sql('INSERT INTO ' . table_prefix . 'captcha(session_id, code, session_data, source_ip, user_id)' . " VALUES('$hash', '$code', '$session_data', '{$_SERVER['REMOTE_ADDR']}', {$this->user_id});"); |
3426 $this->sql('INSERT INTO ' . table_prefix . 'captcha(session_id, code, session_data, source_ip, user_id)' . " VALUES('$hash', '$code', '$session_data', '{$_SERVER['REMOTE_ADDR']}', {$this->user_id});"); |
3427 return $hash; |
3427 return $hash; |
3428 } |
3428 } |
3429 |
3429 |
3430 /** |
3430 /** |
3431 * Generates a "pronouncable" or "human-friendly" word using various phonics rules |
3431 * Generates a "pronouncable" or "human-friendly" word using various phonics rules |
3432 * @param int Optional. The length of the word. |
3432 * @param int Optional. The length of the word. |
3433 * @return string |
3433 * @return string |
3434 */ |
3434 */ |
3435 |
3435 |
3436 function generate_captcha_code($len = 7) |
3436 function generate_captcha_code($len = 7) |
3437 { |
3437 { |
3438 // don't use k and x, they get mixed up a lot |
3438 // don't use k and x, they get mixed up a lot |
3439 $consonants = 'bcdfghmnpqrsvwyz'; |
3439 $consonants = 'bcdfghmnpqrsvwyz'; |
3484 } |
3484 } |
3485 return $word; |
3485 return $word; |
3486 } |
3486 } |
3487 |
3487 |
3488 /** |
3488 /** |
3489 * For the given code ID, returns the correct CAPTCHA code, or false on failure |
3489 * For the given code ID, returns the correct CAPTCHA code, or false on failure |
3490 * @param string $hash The unique ID assigned to the code |
3490 * @param string $hash The unique ID assigned to the code |
3491 * @param bool If true, the code is NOT deleted from the database. Use with caution! |
3491 * @param bool If true, the code is NOT deleted from the database. Use with caution! |
3492 * @return string The correct confirmation code |
3492 * @return string The correct confirmation code |
3493 */ |
3493 */ |
3494 |
3494 |
3495 function get_captcha($hash, $nodelete = false) |
3495 function get_captcha($hash, $nodelete = false) |
3496 { |
3496 { |
3497 global $db, $session, $paths, $template, $plugins; // Common objects |
3497 global $db, $session, $paths, $template, $plugins; // Common objects |
3498 |
3498 |
3525 |
3525 |
3526 return $code; |
3526 return $code; |
3527 } |
3527 } |
3528 |
3528 |
3529 /** |
3529 /** |
3530 * (AS OF 1.0.2: Deprecated. Captcha codes are now killed on first fetch for security.) Deletes all CAPTCHA codes cached in the DB for this user. |
3530 * (AS OF 1.0.2: Deprecated. Captcha codes are now killed on first fetch for security.) Deletes all CAPTCHA codes cached in the DB for this user. |
3531 */ |
3531 */ |
3532 |
3532 |
3533 function kill_captcha() |
3533 function kill_captcha() |
3534 { |
3534 { |
3535 return true; |
3535 return true; |
3536 } |
3536 } |
3537 |
3537 |
3538 /** |
3538 /** |
3539 * Generates a random password. |
3539 * Generates a random password. |
3540 * @param int $length Optional - length of password |
3540 * @param int $length Optional - length of password |
3541 * @return string |
3541 * @return string |
3542 */ |
3542 */ |
3543 |
3543 |
3544 function random_pass($length = 10) |
3544 function random_pass($length = 10) |
3545 { |
3545 { |
3546 $valid_chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_+@#%&<>'; |
3546 $valid_chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_+@#%&<>'; |
3547 $valid_chars = enano_str_split($valid_chars); |
3547 $valid_chars = enano_str_split($valid_chars); |
3548 $ret = ''; |
3548 $ret = ''; |
3552 } |
3552 } |
3553 return $ret; |
3553 return $ret; |
3554 } |
3554 } |
3555 |
3555 |
3556 /** |
3556 /** |
3557 * Generates some Javascript that calls the AES encryption library. Put this after your </form>. |
3557 * Generates some Javascript that calls the AES encryption library. Put this after your </form>. |
3558 * @param string The name of the form |
3558 * @param string The name of the form |
3559 * @param string The name of the password field |
3559 * @param string The name of the password field |
3560 * @param string The name of the field that switches encryption on or off |
3560 * @param string The name of the field that switches encryption on or off |
3561 * @param string The name of the field that contains the encryption key |
3561 * @param string The name of the field that contains the encryption key |
3562 * @param string The name of the field that will contain the encrypted password |
3562 * @param string The name of the field that will contain the encrypted password |
3563 * @param string The name of the field that handles MD5 challenge data |
3563 * @param string The name of the field that handles MD5 challenge data |
3564 * @param string The name of the field that tells if the server supports DiffieHellman |
3564 * @param string The name of the field that tells if the server supports DiffieHellman |
3565 * @param string The name of the field with the DiffieHellman public key |
3565 * @param string The name of the field with the DiffieHellman public key |
3566 * @param string The name of the field that the client should populate with its public key |
3566 * @param string The name of the field that the client should populate with its public key |
3567 * @return string |
3567 * @return string |
3568 */ |
3568 */ |
3569 |
3569 |
3570 function aes_javascript($form_name, $pw_field, $use_crypt = 'use_crypt', $crypt_key = 'crypt_key', $crypt_data = 'crypt_data', $challenge = 'challenge_data', $dh_supported = 'dh_supported', $dh_pubkey = 'dh_public_key', $dh_client_pubkey = 'dh_client_public_key') |
3570 static function aes_javascript($form_name, $pw_field, $use_crypt = 'use_crypt', $crypt_key = 'crypt_key', $crypt_data = 'crypt_data', $challenge = 'challenge_data', $dh_supported = 'dh_supported', $dh_pubkey = 'dh_public_key', $dh_client_pubkey = 'dh_client_public_key') |
3571 { |
3571 { |
3572 $code = ' |
3572 $code = ' |
3573 <script type="text/javascript"> |
3573 <script type="text/javascript"> |
3574 |
3574 |
3575 function runEncryption(nowhiteout) |
3575 function runEncryption(nowhiteout) |
3630 */ |
3630 */ |
3631 |
3631 |
3632 frm.'.$use_crypt.'.value = \'yes_dh\'; |
3632 frm.'.$use_crypt.'.value = \'yes_dh\'; |
3633 |
3633 |
3634 // Perform Diffie Hellman stuff |
3634 // Perform Diffie Hellman stuff |
3635 // console.info("DiffieHellman: started keygen process"); |
3635 console.info("DiffieHellman: started keygen process"); |
3636 var dh_priv = dh_gen_private(); |
3636 var dh_priv = dh_gen_private(); |
3637 var dh_pub = dh_gen_public(dh_priv); |
3637 var dh_pub = dh_gen_public(dh_priv); |
3638 var secret = dh_gen_shared_secret(dh_priv, frm.' . $dh_pubkey . '.value); |
3638 var secret = dh_gen_shared_secret(dh_priv, frm.' . $dh_pubkey . '.value); |
3639 // console.info("DiffieHellman: finished keygen process"); |
3639 console.info("DiffieHellman: finished keygen process"); |
3640 |
3640 |
3641 // secret_hash is used to verify that the server guesses the correct secret |
3641 // secret_hash is used to verify that the server guesses the correct secret |
3642 var secret_hash = hex_sha1(secret); |
3642 var secret_hash = hex_sha1(secret); |
3643 |
3643 |
3644 // give the server our values |
3644 // give the server our values |
3658 if(!cryptstring) |
3658 if(!cryptstring) |
3659 { |
3659 { |
3660 return false; |
3660 return false; |
3661 } |
3661 } |
3662 cryptstring = byteArrayToHex(cryptstring); |
3662 cryptstring = byteArrayToHex(cryptstring); |
3663 // console.info("DiffieHellman: finished AES"); |
3663 console.info("DiffieHellman: finished AES. Result: " + cryptstring); |
3664 console.debug(frm); |
|
3664 frm.'.$crypt_data.'.value = cryptstring; |
3665 frm.'.$crypt_data.'.value = cryptstring; |
3665 frm.'.$pw_field.'.value = \'\'; |
3666 frm.'.$pw_field.'.value = \'\'; |
3666 // console.info("DiffieHellman: ready to submit"); |
3667 // console.info("DiffieHellman: ready to submit"); |
3667 } |
3668 } |
3668 else if ( testpassed && !use_diffiehellman ) |
3669 else if ( testpassed && !use_diffiehellman ) |
3696 '; |
3697 '; |
3697 return $code; |
3698 return $code; |
3698 } |
3699 } |
3699 |
3700 |
3700 /** |
3701 /** |
3701 * Generates the HTML form elements required for an encrypted logon experience. |
3702 * Generates the HTML form elements required for an encrypted logon experience. |
3702 * @return string |
3703 * @param reference Optional variable to fill with the server's public and private key. If IN_ENANO_INSTALL is defined, storing and retrieving the key |
3703 */ |
3704 * is YOUR responsibility. |
3704 |
3705 * @return string |
3705 function generate_aes_form() |
3706 */ |
3706 { |
3707 |
3708 static function generate_aes_form(&$dh_store = array()) |
|
3709 { |
|
3710 $is_static = !( isset($this) && get_class($this) === __CLASS__ ); |
|
3711 if ( $is_static ) |
|
3712 { |
|
3713 $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE); |
|
3714 $aes_key = $aes->gen_readymade_key(); |
|
3715 } |
|
3716 else |
|
3717 { |
|
3718 $aes_key = self::rijndael_genkey(); |
|
3719 } |
|
3720 $dh_store = array('aes' => $aes_key, 'public' => '', 'private' => ''); |
|
3721 |
|
3707 $return = '<input type="hidden" name="use_crypt" value="no" />'; |
3722 $return = '<input type="hidden" name="use_crypt" value="no" />'; |
3708 $return .= '<input type="hidden" name="crypt_key" value="' . $this->rijndael_genkey() . '" />'; |
3723 $return .= '<input type="hidden" name="crypt_key" value="' . $aes_key . '" />'; |
3709 $return .= '<input type="hidden" name="crypt_data" value="" />'; |
3724 $return .= '<input type="hidden" name="crypt_data" value="" />'; |
3710 $return .= '<input type="hidden" name="challenge_data" value="' . $this->dss_rand() . '" />'; |
3725 $return .= '<input type="hidden" name="challenge_data" value="' . self::dss_rand() . '" />'; |
3711 |
3726 |
3712 require_once(ENANO_ROOT . '/includes/math.php'); |
3727 require_once(ENANO_ROOT . '/includes/math.php'); |
3713 require_once(ENANO_ROOT . '/includes/diffiehellman.php'); |
3728 require_once(ENANO_ROOT . '/includes/diffiehellman.php'); |
3714 |
3729 |
3715 global $dh_supported, $_math; |
3730 global $dh_supported, $_math; |
3718 $dh_key_priv = dh_gen_private(); |
3733 $dh_key_priv = dh_gen_private(); |
3719 $dh_key_pub = dh_gen_public($dh_key_priv); |
3734 $dh_key_pub = dh_gen_public($dh_key_priv); |
3720 $dh_key_priv = $_math->str($dh_key_priv); |
3735 $dh_key_priv = $_math->str($dh_key_priv); |
3721 $dh_key_pub = $_math->str($dh_key_pub); |
3736 $dh_key_pub = $_math->str($dh_key_pub); |
3722 // store the keys in the DB |
3737 // store the keys in the DB |
3723 $this->sql('INSERT INTO ' . table_prefix . "diffiehellman( public_key, private_key ) VALUES ( '$dh_key_pub', '$dh_key_priv' );"); |
3738 // this is doing a static call check to avoid using $this in a static call |
3739 if ( !defined('IN_ENANO_INSTALL') && isset($this) && get_class($this) === __CLASS__ ) |
|
3740 $this->sql('INSERT INTO ' . table_prefix . "diffiehellman( public_key, private_key ) VALUES ( '$dh_key_pub', '$dh_key_priv' );"); |
|
3741 // also give the key to the calling function |
|
3742 $dh_store['public'] = $dh_key_pub; |
|
3743 $dh_store['private'] = $dh_key_priv; |
|
3724 |
3744 |
3725 $return .= "<input type=\"hidden\" name=\"dh_supported\" value=\"true\" /> |
3745 $return .= "<input type=\"hidden\" name=\"dh_supported\" value=\"true\" /> |
3726 <input type=\"hidden\" name=\"dh_public_key\" value=\"$dh_key_pub\" /> |
3746 <input type=\"hidden\" name=\"dh_public_key\" value=\"$dh_key_pub\" /> |
3727 <input type=\"hidden\" name=\"dh_client_public_key\" value=\"\" />"; |
3747 <input type=\"hidden\" name=\"dh_client_public_key\" value=\"\" />"; |
3728 } |
3748 } |
3732 } |
3752 } |
3733 return $return; |
3753 return $return; |
3734 } |
3754 } |
3735 |
3755 |
3736 /** |
3756 /** |
3737 * If you used all the same form fields as the normal login interface, this will take care of DiffieHellman for you and return the key. |
3757 * If you used all the same form fields as the normal login interface, this will take care of DiffieHellman for you and return the key. |
3738 * @param string Password field name (defaults to "password") |
3758 * @param string Password field name (defaults to "password") |
3739 * @return string |
3759 * @param array Optional associative array with fields "public", "private", and "aes". |
3740 */ |
3760 * @return string |
3741 |
3761 */ |
3742 function get_aes_post($fieldname = 'password') |
3762 |
3763 static function get_aes_post($fieldname = 'password', $keys = false) |
|
3743 { |
3764 { |
3744 global $db, $session, $paths, $template, $plugins; // Common objects |
3765 global $db, $session, $paths, $template, $plugins; // Common objects |
3745 |
3766 |
3746 $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE); |
3767 $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE); |
3747 if ( $_POST['use_crypt'] == 'yes' ) |
3768 if ( $_POST['use_crypt'] == 'yes' ) |
3748 { |
3769 { |
3749 $crypt_key = $this->fetch_public_key($_POST['crypt_key']); |
3770 $is_static = !( isset($this) && get_class($this) === __CLASS__ ); |
3771 if ( $is_static && ( !is_array($keys) || (is_array($keys) && !isset($keys['aes'])) ) ) |
|
3772 { |
|
3773 throw new Exception('ERR_STATIC_REQUIRES_KEY'); |
|
3774 } |
|
3775 $crypt_key = $is_static ? $keys['aes'] : $this->fetch_public_key($_POST['crypt_key']); |
|
3750 if ( !$crypt_key ) |
3776 if ( !$crypt_key ) |
3751 { |
3777 { |
3752 throw new Exception($lang->get('user_err_key_not_found')); |
3778 throw new Exception($lang->get('user_err_key_not_found')); |
3753 } |
3779 } |
3754 $crypt_key = hexdecode($crypt_key); |
3780 $crypt_key = hexdecode($crypt_key); |
3770 $dh_public = $_POST['dh_public_key']; |
3796 $dh_public = $_POST['dh_public_key']; |
3771 if ( !ctype_digit($dh_public) ) |
3797 if ( !ctype_digit($dh_public) ) |
3772 { |
3798 { |
3773 throw new Exception('ERR_DH_KEY_NOT_INTEGER'); |
3799 throw new Exception('ERR_DH_KEY_NOT_INTEGER'); |
3774 } |
3800 } |
3775 $q = $db->sql_query('SELECT private_key, key_id FROM ' . table_prefix . "diffiehellman WHERE public_key = '$dh_public';"); |
3801 if ( is_array($keys) && isset($keys['public']) && isset($keys['private']) ) |
3776 if ( !$q ) |
3802 { |
3777 $db->die_json(); |
3803 if ( $keys['public'] !== $dh_public ) |
3778 |
3804 throw new Exception('ERR_DH_KEY_NOT_FOUND'); |
3779 if ( $db->numrows() < 1 ) |
3805 $dh_private = $keys['private']; |
3780 { |
3806 } |
3781 throw new Exception('ERR_DH_KEY_NOT_FOUND'); |
3807 else |
3782 } |
3808 { |
3783 |
3809 $q = $db->sql_query('SELECT private_key, key_id FROM ' . table_prefix . "diffiehellman WHERE public_key = '$dh_public';"); |
3784 list($dh_private, $dh_key_id) = $db->fetchrow_num(); |
3810 if ( !$q ) |
3785 $db->free_result(); |
3811 $db->die_json(); |
3786 |
3812 |
3787 // We have the private key, now delete the key pair, we no longer need it |
3813 if ( $db->numrows() < 1 ) |
3788 $q = $db->sql_query('DELETE FROM ' . table_prefix . "diffiehellman WHERE key_id = $dh_key_id;"); |
3814 { |
3789 if ( !$q ) |
3815 throw new Exception('ERR_DH_KEY_NOT_FOUND'); |
3790 $db->die_json(); |
3816 } |
3817 |
|
3818 list($dh_private, $dh_key_id) = $db->fetchrow_num(); |
|
3819 $db->free_result(); |
|
3820 |
|
3821 // We have the private key, now delete the key pair, we no longer need it |
|
3822 $q = $db->sql_query('DELETE FROM ' . table_prefix . "diffiehellman WHERE key_id = $dh_key_id;"); |
|
3823 if ( !$q ) |
|
3824 $db->die_json(); |
|
3825 } |
|
3791 |
3826 |
3792 // Generate the shared secret |
3827 // Generate the shared secret |
3793 $dh_secret = dh_gen_shared_secret($dh_private, $_POST['dh_client_public_key']); |
3828 $dh_secret = dh_gen_shared_secret($dh_private, $_POST['dh_client_public_key']); |
3794 $dh_secret = $_math->str($dh_secret); |
3829 $dh_secret = $_math->str($dh_secret); |
3795 |
3830 |
3815 } |
3850 } |
3816 return $data; |
3851 return $data; |
3817 } |
3852 } |
3818 |
3853 |
3819 /** |
3854 /** |
3820 * Backend code for the JSON login interface. Basically a frontend to the session API that takes all parameters in one huge array. |
3855 * Backend code for the JSON login interface. Basically a frontend to the session API that takes all parameters in one huge array. |
3821 * @param array LoginAPI request |
3856 * @param array LoginAPI request |
3822 * @return array LoginAPI response |
3857 * @return array LoginAPI response |
3823 */ |
3858 */ |
3824 |
3859 |
3825 function process_login_request($req) |
3860 function process_login_request($req) |
3826 { |
3861 { |
3827 global $db, $session, $paths, $template, $plugins; // Common objects |
3862 global $db, $session, $paths, $template, $plugins; // Common objects |
3828 |
3863 |
3975 return $this->get_login_response('login_failure', 'lockout_request_denied'); |
4010 return $this->get_login_response('login_failure', 'lockout_request_denied'); |
3976 } |
4011 } |
3977 |
4012 |
3978 // At this point if any extra info was injected into the login data packet, we need to let plugins process it |
4013 // At this point if any extra info was injected into the login data packet, we need to let plugins process it |
3979 /** |
4014 /** |
3980 * Called upon processing an incoming login request. If you added anything to the userinfo object during the jshook |
4015 * Called upon processing an incoming login request. If you added anything to the userinfo object during the jshook |
3981 * login_build_userinfo, that will be in the $userinfo array here. Expected return values are: true if your plugin has |
4016 * login_build_userinfo, that will be in the $userinfo array here. Expected return values are: true if your plugin has |
3982 * not only succeeded but ALSO issued a session key (bypass the whole Enano builtin login process) and an associative array |
4017 * not only succeeded but ALSO issued a session key (bypass the whole Enano builtin login process) and an associative array |
3983 * with "mode" set to "error" and an error string in "error" to send an error back to the client. Any return value other |
4018 * with "mode" set to "error" and an error string in "error" to send an error back to the client. Any return value other |
3984 * than these will be treated as a pass-through, and the user's password will be validated through Enano's standard process. |
4019 * than these will be treated as a pass-through, and the user's password will be validated through Enano's standard process. |
3985 * @hook login_process_userdata_json |
4020 * @hook login_process_userdata_json |
3986 */ |
4021 */ |
3987 |
4022 |
3988 $code = $plugins->setHook('login_process_userdata_json', true); |
4023 $code = $plugins->setHook('login_process_userdata_json', true); |
3989 |
4024 |
3990 foreach ( $code as $cmd ) |
4025 foreach ( $code as $cmd ) |
3991 { |
4026 { |
4094 } |
4129 } |
4095 |
4130 |
4096 } |
4131 } |
4097 |
4132 |
4098 /** |
4133 /** |
4099 * Generate a packet to send to the client for logins. |
4134 * Generate a packet to send to the client for logins. |
4100 * @param string mode |
4135 * @param string mode |
4101 * @param array |
4136 * @param array |
4102 * @return array |
4137 * @return array |
4103 */ |
4138 */ |
4104 |
4139 |
4105 function get_login_response($mode, $error = false, $base = array()) |
4140 function get_login_response($mode, $error = false, $base = array()) |
4106 { |
4141 { |
4107 $this->start(); |
4142 $this->start(); |
4108 |
4143 |
4117 $response['username'] = $this->user_logged_in ? $this->username : false; |
4152 $response['username'] = $this->user_logged_in ? $this->username : false; |
4118 return $response; |
4153 return $response; |
4119 } |
4154 } |
4120 |
4155 |
4121 /** |
4156 /** |
4122 * Get a packet of crypto flags for login. |
4157 * Get a packet of crypto flags for login. |
4123 * @return array |
4158 * @return array |
4124 */ |
4159 */ |
4125 |
4160 |
4126 function get_login_crypto_packet() |
4161 function get_login_crypto_packet() |
4127 { |
4162 { |
4128 global $dh_supported, $_math; |
4163 global $dh_supported, $_math; |
4129 |
4164 |
4158 */ |
4193 */ |
4159 |
4194 |
4160 class Session_ACLPageInfo { |
4195 class Session_ACLPageInfo { |
4161 |
4196 |
4162 /** |
4197 /** |
4163 * The page ID of this ACL info package |
4198 * The page ID of this ACL info package |
4164 * @var string |
4199 * @var string |
4165 */ |
4200 */ |
4166 |
4201 |
4167 var $page_id; |
4202 var $page_id; |
4168 |
4203 |
4169 /** |
4204 /** |
4170 * The namespace of the page being checked |
4205 * The namespace of the page being checked |
4171 * @var string |
4206 * @var string |
4172 */ |
4207 */ |
4173 |
4208 |
4174 var $namespace; |
4209 var $namespace; |
4175 |
4210 |
4176 /** |
4211 /** |
4177 * Our list of permission types. |
4212 * Our list of permission types. |
4178 * @access private |
4213 * @access private |
4179 * @var array |
4214 * @var array |
4180 */ |
4215 */ |
4181 |
4216 |
4182 var $acl_types = Array(); |
4217 var $acl_types = Array(); |
4183 |
4218 |
4184 /** |
4219 /** |
4185 * The list of descriptions for the permission types |
4220 * The list of descriptions for the permission types |
4186 * @var array |
4221 * @var array |
4187 */ |
4222 */ |
4188 |
4223 |
4189 var $acl_descs = Array(); |
4224 var $acl_descs = Array(); |
4190 |
4225 |
4191 /** |
4226 /** |
4192 * A list of dependencies for ACL types. |
4227 * A list of dependencies for ACL types. |
4193 * @var array |
4228 * @var array |
4194 */ |
4229 */ |
4195 |
4230 |
4196 var $acl_deps = Array(); |
4231 var $acl_deps = Array(); |
4197 |
4232 |
4198 /** |
4233 /** |
4199 * Our tell-all list of permissions. Do not even try to change this. |
4234 * Our tell-all list of permissions. Do not even try to change this. |
4200 * @access private |
4235 * @access private |
4201 * @var array |
4236 * @var array |
4202 */ |
4237 */ |
4203 |
4238 |
4204 var $perms = Array(); |
4239 var $perms = Array(); |
4205 |
4240 |
4206 /** |
4241 /** |
4207 * Array to track which default permissions are being used |
4242 * Array to track which default permissions are being used |
4208 * @var array |
4243 * @var array |
4209 * @access private |
4244 * @access private |
4210 */ |
4245 */ |
4211 |
4246 |
4212 var $acl_defaults_used = Array(); |
4247 var $acl_defaults_used = Array(); |
4213 |
4248 |
4214 /** |
4249 /** |
4215 * Tracks whether Wiki Mode is on for the page we're operating on. |
4250 * Tracks whether Wiki Mode is on for the page we're operating on. |
4216 * @var bool |
4251 * @var bool |
4217 */ |
4252 */ |
4218 |
4253 |
4219 var $wiki_mode = false; |
4254 var $wiki_mode = false; |
4220 |
4255 |
4221 /** |
4256 /** |
4222 * Tracks where permissions were calculated using the ACL_INHERIT_* constants. Layout: |
4257 * Tracks where permissions were calculated using the ACL_INHERIT_* constants. Layout: |
4223 * array( |
4258 * array( |
4224 * [permission_name] => array( |
4259 * [permission_name] => array( |
4225 * [src] => ACL_INHERIT_* |
4260 * [src] => ACL_INHERIT_* |
4226 * [rule_id] => integer |
4261 * [rule_id] => integer |
4227 * ), |
4262 * ), |
4228 * ... |
4263 * ... |
4229 * ) |
4264 * ) |
4230 * |
4265 * |
4231 * @var array |
4266 * @var array |
4232 */ |
4267 */ |
4233 |
4268 |
4234 var $perm_resolve_table = array(); |
4269 var $perm_resolve_table = array(); |
4235 |
4270 |
4236 # |
4271 # |
4237 # USER PARAMETERS |
4272 # USER PARAMETERS |
4238 # |
4273 # |
4239 |
4274 |
4240 /** |
4275 /** |
4241 * User ID |
4276 * User ID |
4242 * @var int |
4277 * @var int |
4243 */ |
4278 */ |
4244 |
4279 |
4245 var $user_id = 1; |
4280 var $user_id = 1; |
4246 |
4281 |
4247 /** |
4282 /** |
4248 * Group membership associative array (group_id => group_name) |
4283 * Group membership associative array (group_id => group_name) |
4249 * @var array |
4284 * @var array |
4250 */ |
4285 */ |
4251 |
4286 |
4252 var $groups = array(); |
4287 var $groups = array(); |
4253 |
4288 |
4254 /** |
4289 /** |
4255 * Constructor. |
4290 * Constructor. |
4256 * @param string $page_id The ID of the page to check |
4291 * @param string $page_id The ID of the page to check |
4257 * @param string $namespace The namespace of the page to check. |
4292 * @param string $namespace The namespace of the page to check. |
4258 * @param array $acl_types List of ACL types |
4293 * @param array $acl_types List of ACL types |
4259 * @param array $acl_descs List of human-readable descriptions for permissions (associative) |
4294 * @param array $acl_descs List of human-readable descriptions for permissions (associative) |
4260 * @param array $acl_deps List of dependencies for permissions. For example, viewing history/diffs depends on the ability to read the page. |
4295 * @param array $acl_deps List of dependencies for permissions. For example, viewing history/diffs depends on the ability to read the page. |
4261 * @param array $base What to start with - this is an attempt to reduce the number of SQL queries. |
4296 * @param array $base What to start with - this is an attempt to reduce the number of SQL queries. |
4262 * @param int|string $user_id_or_name Username or ID to search for, defaults to current user |
4297 * @param int|string $user_id_or_name Username or ID to search for, defaults to current user |
4263 * @param array $resolve_table Debugging info for tracking where rules came from, defaults to a blank array. |
4298 * @param array $resolve_table Debugging info for tracking where rules came from, defaults to a blank array. |
4264 */ |
4299 */ |
4265 |
4300 |
4266 function __construct($page_id, $namespace, $acl_types, $acl_descs, $acl_deps, $base, $user_id = null, $groups = null, $resolve_table = array()) |
4301 function __construct($page_id, $namespace, $acl_types, $acl_descs, $acl_deps, $base, $user_id = null, $groups = null, $resolve_table = array()) |
4267 { |
4302 { |
4268 global $db, $session, $paths, $template, $plugins; // Common objects |
4303 global $db, $session, $paths, $template, $plugins; // Common objects |
4269 |
4304 |
4270 // hack |
4305 // hack |
4311 |
4346 |
4312 $this->__calculate(); |
4347 $this->__calculate(); |
4313 } |
4348 } |
4314 |
4349 |
4315 /** |
4350 /** |
4316 * Performs the actual permission calculation. |
4351 * Performs the actual permission calculation. |
4317 * @access private |
4352 * @access private |
4318 */ |
4353 */ |
4319 |
4354 |
4320 private function __calculate() |
4355 private function __calculate() |
4321 { |
4356 { |
4322 global $db, $session, $paths, $template, $plugins; // Common objects |
4357 global $db, $session, $paths, $template, $plugins; // Common objects |
4323 |
4358 |
4436 return false; |
4471 return false; |
4437 } |
4472 } |
4438 } |
4473 } |
4439 |
4474 |
4440 /** |
4475 /** |
4441 * Tells us whether permission $type is allowed or not based on the current rules. |
4476 * Tells us whether permission $type is allowed or not based on the current rules. |
4442 * @param string $type The permission identifier ($acl_type passed to sessionManager::register_acl_type()) |
4477 * @param string $type The permission identifier ($acl_type passed to sessionManager::register_acl_type()) |
4443 * @param bool $no_deps If true, disables dependency checking |
4478 * @param bool $no_deps If true, disables dependency checking |
4444 * @return bool True if allowed, false if denied or if an error occured |
4479 * @return bool True if allowed, false if denied or if an error occured |
4445 */ |
4480 */ |
4446 |
4481 |
4447 function get_permissions($type, $no_deps = false) |
4482 function get_permissions($type, $no_deps = false) |
4448 { |
4483 { |
4449 // echo '<pre>' . print_r($this->perms, true) . '</pre>'; |
4484 // echo '<pre>' . print_r($this->perms, true) . '</pre>'; |
4450 global $db, $session, $paths, $template, $plugins; // Common objects |
4485 global $db, $session, $paths, $template, $plugins; // Common objects |
4451 |
4486 |
4514 } |
4549 } |
4515 return $ret; |
4550 return $ret; |
4516 } |
4551 } |
4517 |
4552 |
4518 /** |
4553 /** |
4519 * Tell us if the dependencies for a given permission are met. |
4554 * Tell us if the dependencies for a given permission are met. |
4520 * @param string The ACL permission ID |
4555 * @param string The ACL permission ID |
4521 * @param bool If true, does not return a boolean value, but instead returns array of dependencies that fail |
4556 * @param bool If true, does not return a boolean value, but instead returns array of dependencies that fail |
4522 * @return bool |
4557 * @return bool |
4523 */ |
4558 */ |
4524 |
4559 |
4525 function acl_check_deps($type, $debug = false) |
4560 function acl_check_deps($type, $debug = false) |
4526 { |
4561 { |
4527 // This will only happen if the permissions table is hacked or improperly accessed |
4562 // This will only happen if the permissions table is hacked or improperly accessed |
4528 if(!isset($this->acl_deps[$type])) |
4563 if(!isset($this->acl_deps[$type])) |
4529 return $debug ? array() : true; |
4564 return $debug ? array() : true; |
4570 } |
4605 } |
4571 return $debug ? $debugdata : true; |
4606 return $debug ? $debugdata : true; |
4572 } |
4607 } |
4573 |
4608 |
4574 /** |
4609 /** |
4575 * Merges the ACL array sent with the current permissions table, deciding precedence based on whether defaults are in effect or not. |
4610 * Merges the ACL array sent with the current permissions table, deciding precedence based on whether defaults are in effect or not. |
4576 * @param array The array to merge into the master ACL list |
4611 * @param array The array to merge into the master ACL list |
4577 * @param bool If true, $perm is treated as the "new default" |
4612 * @param bool If true, $perm is treated as the "new default" |
4578 * @param int 1 if this is a site-wide ACL, 2 if page-specific. Defaults to 2. |
4613 * @param int 1 if this is a site-wide ACL, 2 if page-specific. Defaults to 2. |
4579 */ |
4614 */ |
4580 |
4615 |
4581 function acl_merge_with_current($perm, $is_everyone = false, $scope = 2) |
4616 function acl_merge_with_current($perm, $is_everyone = false, $scope = 2) |
4582 { |
4617 { |
4583 foreach ( $this->perms as $i => $p ) |
4618 foreach ( $this->perms as $i => $p ) |
4584 { |
4619 { |