Mercurial > hg > vamp-website
comparison forum/Sources/Subs-Auth.php @ 76:e3e11437ecea website
Add forum code
author | Chris Cannam |
---|---|
date | Sun, 07 Jul 2013 11:25:48 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
75:72f59aa7e503 | 76:e3e11437ecea |
---|---|
1 <?php | |
2 | |
3 /** | |
4 * Simple Machines Forum (SMF) | |
5 * | |
6 * @package SMF | |
7 * @author Simple Machines http://www.simplemachines.org | |
8 * @copyright 2011 Simple Machines | |
9 * @license http://www.simplemachines.org/about/smf/license.php BSD | |
10 * | |
11 * @version 2.0 | |
12 */ | |
13 | |
14 if (!defined('SMF')) | |
15 die('Hacking attempt...'); | |
16 | |
17 /* This file has functions in it to do with authentication, user handling, | |
18 and the like. It provides these functions: | |
19 | |
20 void setLoginCookie(int cookie_length, int id_member, string password = '') | |
21 - sets the SMF-style login cookie and session based on the id_member | |
22 and password passed. | |
23 - password should be already encrypted with the cookie salt. | |
24 - logs the user out if id_member is zero. | |
25 - sets the cookie and session to last the number of seconds specified | |
26 by cookie_length. | |
27 - when logging out, if the globalCookies setting is enabled, attempts | |
28 to clear the subdomain's cookie too. | |
29 | |
30 array url_parts(bool local, bool global) | |
31 - returns the path and domain to set the cookie on. | |
32 - normally, local and global should be the localCookies and | |
33 globalCookies settings, respectively. | |
34 - uses boardurl to determine these two things. | |
35 - returns an array with domain and path in it, in that order. | |
36 | |
37 void KickGuest() | |
38 - throws guests out to the login screen when guest access is off. | |
39 - sets $_SESSION['login_url'] to $_SERVER['REQUEST_URL']. | |
40 - uses the 'kick_guest' sub template found in Login.template.php. | |
41 | |
42 void InMaintenance() | |
43 - display a message about being in maintenance mode. | |
44 - display a login screen with sub template 'maintenance'. | |
45 | |
46 void adminLogin() | |
47 - double check the verity of the admin by asking for his or her | |
48 password. | |
49 - loads Login.template.php and uses the admin_login sub template. | |
50 - sends data to template so the admin is sent on to the page they | |
51 wanted if their password is correct, otherwise they can try | |
52 again. | |
53 | |
54 string adminLogin_outputPostVars(string key, string value) | |
55 - used by the adminLogin() function. | |
56 - returns 'hidden' HTML form fields, containing key-value-pairs. | |
57 - if 'value' is an array, the function is called recursively. | |
58 | |
59 array findMembers(array names, bool use_wildcards = false, | |
60 bool buddies_only = false, int max = 500) | |
61 - searches for members whose username, display name, or e-mail address | |
62 match the given pattern of array names. | |
63 - accepts wildcards ? and * in the patern if use_wildcards is set. | |
64 - retrieves a maximum of max members, if passed. | |
65 - searches only buddies if buddies_only is set. | |
66 - returns an array containing information about the matching members. | |
67 | |
68 void JSMembers() | |
69 - called by index.php?action=findmember. | |
70 - is used as a popup for searching members. | |
71 - uses sub template find_members of the Help template. | |
72 - also used to add members for PM's sent using wap2/imode protocol. | |
73 | |
74 void RequestMembers() | |
75 - used by javascript to find members matching the request. | |
76 - outputs each member name on its own line. | |
77 | |
78 void resetPassword(int id_member, string username = null) | |
79 - called by Profile.php when changing someone's username. | |
80 - checks the validity of the new username. | |
81 - generates and sets a new password for the given user. | |
82 - mails the new password to the email address of the user. | |
83 - if username is not set, only a new password is generated and sent. | |
84 | |
85 string validateUsername(int memID, string username) | |
86 - checks a username obeys a load of rules. Returns null if fine. | |
87 | |
88 string validatePassword(string password, string username, | |
89 array restrict_in = none) | |
90 - called when registering/choosing a password. | |
91 - checks the password obeys the current forum settings for password | |
92 strength. | |
93 - if password checking is enabled, will check that none of the words | |
94 in restrict_in appear in the password. | |
95 - returns an error identifier if the password is invalid, or null. | |
96 | |
97 void rebuildModCache() | |
98 - stores some useful information on the current users moderation powers in the session. | |
99 | |
100 */ | |
101 | |
102 // Actually set the login cookie... | |
103 function setLoginCookie($cookie_length, $id, $password = '') | |
104 { | |
105 global $cookiename, $boardurl, $modSettings; | |
106 | |
107 // If changing state force them to re-address some permission caching. | |
108 $_SESSION['mc']['time'] = 0; | |
109 | |
110 // The cookie may already exist, and have been set with different options. | |
111 $cookie_state = (empty($modSettings['localCookies']) ? 0 : 1) | (empty($modSettings['globalCookies']) ? 0 : 2); | |
112 if (isset($_COOKIE[$cookiename]) && preg_match('~^a:[34]:\{i:0;(i:\d{1,6}|s:[1-8]:"\d{1,8}");i:1;s:(0|40):"([a-fA-F0-9]{40})?";i:2;[id]:\d{1,14};(i:3;i:\d;)?\}$~', $_COOKIE[$cookiename]) === 1) | |
113 { | |
114 $array = @unserialize($_COOKIE[$cookiename]); | |
115 | |
116 // Out with the old, in with the new! | |
117 if (isset($array[3]) && $array[3] != $cookie_state) | |
118 { | |
119 $cookie_url = url_parts($array[3] & 1 > 0, $array[3] & 2 > 0); | |
120 setcookie($cookiename, serialize(array(0, '', 0)), time() - 3600, $cookie_url[1], $cookie_url[0], !empty($modSettings['secureCookies'])); | |
121 } | |
122 } | |
123 | |
124 // Get the data and path to set it on. | |
125 $data = serialize(empty($id) ? array(0, '', 0) : array($id, $password, time() + $cookie_length, $cookie_state)); | |
126 $cookie_url = url_parts(!empty($modSettings['localCookies']), !empty($modSettings['globalCookies'])); | |
127 | |
128 // Set the cookie, $_COOKIE, and session variable. | |
129 setcookie($cookiename, $data, time() + $cookie_length, $cookie_url[1], $cookie_url[0], !empty($modSettings['secureCookies'])); | |
130 | |
131 // If subdomain-independent cookies are on, unset the subdomain-dependent cookie too. | |
132 if (empty($id) && !empty($modSettings['globalCookies'])) | |
133 setcookie($cookiename, $data, time() + $cookie_length, $cookie_url[1], '', !empty($modSettings['secureCookies'])); | |
134 | |
135 // Any alias URLs? This is mainly for use with frames, etc. | |
136 if (!empty($modSettings['forum_alias_urls'])) | |
137 { | |
138 $aliases = explode(',', $modSettings['forum_alias_urls']); | |
139 | |
140 $temp = $boardurl; | |
141 foreach ($aliases as $alias) | |
142 { | |
143 // Fake the $boardurl so we can set a different cookie. | |
144 $alias = strtr(trim($alias), array('http://' => '', 'https://' => '')); | |
145 $boardurl = 'http://' . $alias; | |
146 | |
147 $cookie_url = url_parts(!empty($modSettings['localCookies']), !empty($modSettings['globalCookies'])); | |
148 | |
149 if ($cookie_url[0] == '') | |
150 $cookie_url[0] = strtok($alias, '/'); | |
151 | |
152 setcookie($cookiename, $data, time() + $cookie_length, $cookie_url[1], $cookie_url[0], !empty($modSettings['secureCookies'])); | |
153 } | |
154 | |
155 $boardurl = $temp; | |
156 } | |
157 | |
158 $_COOKIE[$cookiename] = $data; | |
159 | |
160 // Make sure the user logs in with a new session ID. | |
161 if (!isset($_SESSION['login_' . $cookiename]) || $_SESSION['login_' . $cookiename] !== $data) | |
162 { | |
163 // Backup and remove the old session. | |
164 $oldSessionData = $_SESSION; | |
165 $_SESSION = array(); | |
166 session_destroy(); | |
167 | |
168 // Recreate and restore the new session. | |
169 loadSession(); | |
170 session_regenerate_id(); | |
171 $_SESSION = $oldSessionData; | |
172 | |
173 // Version 4.3.2 didn't store the cookie of the new session. | |
174 if (version_compare(PHP_VERSION, '4.3.2') === 0) | |
175 { | |
176 $sessionCookieLifetime = @ini_get('session.cookie_lifetime'); | |
177 setcookie(session_name(), session_id(), time() + (empty($sessionCookieLifetime) ? $cookie_length : $sessionCookieLifetime), $cookie_url[1], $cookie_url[0], !empty($modSettings['secureCookies'])); | |
178 } | |
179 | |
180 $_SESSION['login_' . $cookiename] = $data; | |
181 } | |
182 } | |
183 | |
184 // PHP < 4.3.2 doesn't have this function | |
185 if (!function_exists('session_regenerate_id')) | |
186 { | |
187 function session_regenerate_id() | |
188 { | |
189 // Too late to change the session now. | |
190 if (headers_sent()) | |
191 return false; | |
192 | |
193 session_id(strtolower(md5(uniqid(mt_rand(), true)))); | |
194 return true; | |
195 } | |
196 | |
197 } | |
198 | |
199 // Get the domain and path for the cookie... | |
200 function url_parts($local, $global) | |
201 { | |
202 global $boardurl; | |
203 | |
204 // Parse the URL with PHP to make life easier. | |
205 $parsed_url = parse_url($boardurl); | |
206 | |
207 // Is local cookies off? | |
208 if (empty($parsed_url['path']) || !$local) | |
209 $parsed_url['path'] = ''; | |
210 | |
211 // Globalize cookies across domains (filter out IP-addresses)? | |
212 if ($global && preg_match('~^\d{1,3}(\.\d{1,3}){3}$~', $parsed_url['host']) == 0 && preg_match('~(?:[^\.]+\.)?([^\.]{2,}\..+)\z~i', $parsed_url['host'], $parts) == 1) | |
213 $parsed_url['host'] = '.' . $parts[1]; | |
214 | |
215 // We shouldn't use a host at all if both options are off. | |
216 elseif (!$local && !$global) | |
217 $parsed_url['host'] = ''; | |
218 | |
219 // The host also shouldn't be set if there aren't any dots in it. | |
220 elseif (!isset($parsed_url['host']) || strpos($parsed_url['host'], '.') === false) | |
221 $parsed_url['host'] = ''; | |
222 | |
223 return array($parsed_url['host'], $parsed_url['path'] . '/'); | |
224 } | |
225 | |
226 // Kick out a guest when guest access is off... | |
227 function KickGuest() | |
228 { | |
229 global $txt, $context; | |
230 | |
231 loadLanguage('Login'); | |
232 loadTemplate('Login'); | |
233 | |
234 // Never redirect to an attachment | |
235 if (strpos($_SERVER['REQUEST_URL'], 'dlattach') === false) | |
236 $_SESSION['login_url'] = $_SERVER['REQUEST_URL']; | |
237 | |
238 $context['sub_template'] = 'kick_guest'; | |
239 $context['page_title'] = $txt['login']; | |
240 } | |
241 | |
242 // Display a message about the forum being in maintenance mode, etc. | |
243 function InMaintenance() | |
244 { | |
245 global $txt, $mtitle, $mmessage, $context; | |
246 | |
247 loadLanguage('Login'); | |
248 loadTemplate('Login'); | |
249 | |
250 // Send a 503 header, so search engines don't bother indexing while we're in maintenance mode. | |
251 header('HTTP/1.1 503 Service Temporarily Unavailable'); | |
252 | |
253 // Basic template stuff.. | |
254 $context['sub_template'] = 'maintenance'; | |
255 $context['title'] = &$mtitle; | |
256 $context['description'] = &$mmessage; | |
257 $context['page_title'] = $txt['maintain_mode']; | |
258 } | |
259 | |
260 function adminLogin() | |
261 { | |
262 global $context, $scripturl, $txt, $user_info, $user_settings; | |
263 | |
264 loadLanguage('Admin'); | |
265 loadTemplate('Login'); | |
266 | |
267 // They used a wrong password, log it and unset that. | |
268 if (isset($_POST['admin_hash_pass']) || isset($_POST['admin_pass'])) | |
269 { | |
270 $txt['security_wrong'] = sprintf($txt['security_wrong'], isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : $txt['unknown'], $_SERVER['HTTP_USER_AGENT'], $user_info['ip']); | |
271 log_error($txt['security_wrong'], 'critical'); | |
272 | |
273 if (isset($_POST['admin_hash_pass'])) | |
274 unset($_POST['admin_hash_pass']); | |
275 if (isset($_POST['admin_pass'])) | |
276 unset($_POST['admin_pass']); | |
277 | |
278 $context['incorrect_password'] = true; | |
279 } | |
280 | |
281 // Figure out the get data and post data. | |
282 $context['get_data'] = '?' . construct_query_string($_GET); | |
283 $context['post_data'] = ''; | |
284 | |
285 // Now go through $_POST. Make sure the session hash is sent. | |
286 $_POST[$context['session_var']] = $context['session_id']; | |
287 foreach ($_POST as $k => $v) | |
288 $context['post_data'] .= adminLogin_outputPostVars($k, $v); | |
289 | |
290 // Now we'll use the admin_login sub template of the Login template. | |
291 $context['sub_template'] = 'admin_login'; | |
292 | |
293 // And title the page something like "Login". | |
294 if (!isset($context['page_title'])) | |
295 $context['page_title'] = $txt['login']; | |
296 | |
297 obExit(); | |
298 | |
299 // We MUST exit at this point, because otherwise we CANNOT KNOW that the user is privileged. | |
300 trigger_error('Hacking attempt...', E_USER_ERROR); | |
301 } | |
302 | |
303 function adminLogin_outputPostVars($k, $v) | |
304 { | |
305 global $smcFunc; | |
306 | |
307 if (!is_array($v)) | |
308 return ' | |
309 <input type="hidden" name="' . htmlspecialchars($k) . '" value="' . strtr($v, array('"' => '"', '<' => '<', '>' => '>')) . '" />'; | |
310 else | |
311 { | |
312 $ret = ''; | |
313 foreach ($v as $k2 => $v2) | |
314 $ret .= adminLogin_outputPostVars($k . '[' . $k2 . ']', $v2); | |
315 | |
316 return $ret; | |
317 } | |
318 } | |
319 | |
320 function construct_query_string($get) | |
321 { | |
322 global $scripturl; | |
323 | |
324 $query_string = ''; | |
325 | |
326 // Awww, darn. The $scripturl contains GET stuff! | |
327 $q = strpos($scripturl, '?'); | |
328 if ($q !== false) | |
329 { | |
330 parse_str(preg_replace('/&(\w+)(?=&|$)/', '&$1=', strtr(substr($scripturl, $q + 1), ';', '&')), $temp); | |
331 | |
332 foreach ($get as $k => $v) | |
333 { | |
334 // Only if it's not already in the $scripturl! | |
335 if (!isset($temp[$k])) | |
336 $query_string .= urlencode($k) . '=' . urlencode($v) . ';'; | |
337 // If it changed, put it out there, but with an ampersand. | |
338 elseif ($temp[$k] != $get[$k]) | |
339 $query_string .= urlencode($k) . '=' . urlencode($v) . '&'; | |
340 } | |
341 } | |
342 else | |
343 { | |
344 // Add up all the data from $_GET into get_data. | |
345 foreach ($get as $k => $v) | |
346 $query_string .= urlencode($k) . '=' . urlencode($v) . ';'; | |
347 } | |
348 | |
349 $query_string = substr($query_string, 0, -1); | |
350 return $query_string; | |
351 } | |
352 | |
353 // Find members by email address, username, or real name. | |
354 function findMembers($names, $use_wildcards = false, $buddies_only = false, $max = 500) | |
355 { | |
356 global $scripturl, $user_info, $modSettings, $smcFunc; | |
357 | |
358 // If it's not already an array, make it one. | |
359 if (!is_array($names)) | |
360 $names = explode(',', $names); | |
361 | |
362 $maybe_email = false; | |
363 foreach ($names as $i => $name) | |
364 { | |
365 // Trim, and fix wildcards for each name. | |
366 $names[$i] = trim($smcFunc['strtolower']($name)); | |
367 | |
368 $maybe_email |= strpos($name, '@') !== false; | |
369 | |
370 // Make it so standard wildcards will work. (* and ?) | |
371 if ($use_wildcards) | |
372 $names[$i] = strtr($names[$i], array('%' => '\%', '_' => '\_', '*' => '%', '?' => '_', '\'' => ''')); | |
373 else | |
374 $names[$i] = strtr($names[$i], array('\'' => ''')); | |
375 } | |
376 | |
377 // What are we using to compare? | |
378 $comparison = $use_wildcards ? 'LIKE' : '='; | |
379 | |
380 // Nothing found yet. | |
381 $results = array(); | |
382 | |
383 // This ensures you can't search someones email address if you can't see it. | |
384 $email_condition = allowedTo('moderate_forum') ? '' : 'hide_email = 0 AND '; | |
385 | |
386 if ($use_wildcards || $maybe_email) | |
387 $email_condition = ' | |
388 OR (' . $email_condition . 'email_address ' . $comparison . ' \'' . implode( '\') OR (' . $email_condition . ' email_address ' . $comparison . ' \'', $names) . '\')'; | |
389 else | |
390 $email_condition = ''; | |
391 | |
392 // Get the case of the columns right - but only if we need to as things like MySQL will go slow needlessly otherwise. | |
393 $member_name = $smcFunc['db_case_sensitive'] ? 'LOWER(member_name)' : 'member_name'; | |
394 $real_name = $smcFunc['db_case_sensitive'] ? 'LOWER(real_name)' : 'real_name'; | |
395 | |
396 // Search by username, display name, and email address. | |
397 $request = $smcFunc['db_query']('', ' | |
398 SELECT id_member, member_name, real_name, email_address, hide_email | |
399 FROM {db_prefix}members | |
400 WHERE ({raw:member_name_search} | |
401 OR {raw:real_name_search} {raw:email_condition}) | |
402 ' . ($buddies_only ? 'AND id_member IN ({array_int:buddy_list})' : '') . ' | |
403 AND is_activated IN (1, 11) | |
404 LIMIT {int:limit}', | |
405 array( | |
406 'buddy_list' => $user_info['buddies'], | |
407 'member_name_search' => $member_name . ' ' . $comparison . ' \'' . implode( '\' OR ' . $member_name . ' ' . $comparison . ' \'', $names) . '\'', | |
408 'real_name_search' => $real_name . ' ' . $comparison . ' \'' . implode( '\' OR ' . $real_name . ' ' . $comparison . ' \'', $names) . '\'', | |
409 'email_condition' => $email_condition, | |
410 'limit' => $max, | |
411 ) | |
412 ); | |
413 while ($row = $smcFunc['db_fetch_assoc']($request)) | |
414 { | |
415 $results[$row['id_member']] = array( | |
416 'id' => $row['id_member'], | |
417 'name' => $row['real_name'], | |
418 'username' => $row['member_name'], | |
419 'email' => in_array(showEmailAddress(!empty($row['hide_email']), $row['id_member']), array('yes', 'yes_permission_override')) ? $row['email_address'] : '', | |
420 'href' => $scripturl . '?action=profile;u=' . $row['id_member'], | |
421 'link' => '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['real_name'] . '</a>' | |
422 ); | |
423 } | |
424 $smcFunc['db_free_result']($request); | |
425 | |
426 // Return all the results. | |
427 return $results; | |
428 } | |
429 | |
430 function JSMembers() | |
431 { | |
432 global $context, $scripturl, $user_info, $smcFunc; | |
433 | |
434 checkSession('get'); | |
435 | |
436 if (WIRELESS) | |
437 $context['sub_template'] = WIRELESS_PROTOCOL . '_pm'; | |
438 else | |
439 { | |
440 // Why is this in the Help template, you ask? Well, erm... it helps you. Does that work? | |
441 loadTemplate('Help'); | |
442 | |
443 $context['template_layers'] = array(); | |
444 $context['sub_template'] = 'find_members'; | |
445 } | |
446 | |
447 if (isset($_REQUEST['search'])) | |
448 $context['last_search'] = $smcFunc['htmlspecialchars']($_REQUEST['search'], ENT_QUOTES); | |
449 else | |
450 $_REQUEST['start'] = 0; | |
451 | |
452 // Allow the user to pass the input to be added to to the box. | |
453 $context['input_box_name'] = isset($_REQUEST['input']) && preg_match('~^[\w-]+$~', $_REQUEST['input']) === 1 ? $_REQUEST['input'] : 'to'; | |
454 | |
455 // Take the delimiter over GET in case it's \n or something. | |
456 $context['delimiter'] = isset($_REQUEST['delim']) ? ($_REQUEST['delim'] == 'LB' ? "\n" : $_REQUEST['delim']) : ', '; | |
457 $context['quote_results'] = !empty($_REQUEST['quote']); | |
458 | |
459 // List all the results. | |
460 $context['results'] = array(); | |
461 | |
462 // Some buddy related settings ;) | |
463 $context['show_buddies'] = !empty($user_info['buddies']); | |
464 $context['buddy_search'] = isset($_REQUEST['buddies']); | |
465 | |
466 // If the user has done a search, well - search. | |
467 if (isset($_REQUEST['search'])) | |
468 { | |
469 $_REQUEST['search'] = $smcFunc['htmlspecialchars']($_REQUEST['search'], ENT_QUOTES); | |
470 | |
471 $context['results'] = findMembers(array($_REQUEST['search']), true, $context['buddy_search']); | |
472 $total_results = count($context['results']); | |
473 | |
474 $context['page_index'] = constructPageIndex($scripturl . '?action=findmember;search=' . $context['last_search'] . ';' . $context['session_var'] . '=' . $context['session_id'] . ';input=' . $context['input_box_name'] . ($context['quote_results'] ? ';quote=1' : '') . ($context['buddy_search'] ? ';buddies' : ''), $_REQUEST['start'], $total_results, 7); | |
475 | |
476 // Determine the navigation context (especially useful for the wireless template). | |
477 $base_url = $scripturl . '?action=findmember;search=' . urlencode($context['last_search']) . (empty($_REQUEST['u']) ? '' : ';u=' . $_REQUEST['u']) . ';' . $context['session_var'] . '=' . $context['session_id']; | |
478 $context['links'] = array( | |
479 'first' => $_REQUEST['start'] >= 7 ? $base_url . ';start=0' : '', | |
480 'prev' => $_REQUEST['start'] >= 7 ? $base_url . ';start=' . ($_REQUEST['start'] - 7) : '', | |
481 'next' => $_REQUEST['start'] + 7 < $total_results ? $base_url . ';start=' . ($_REQUEST['start'] + 7) : '', | |
482 'last' => $_REQUEST['start'] + 7 < $total_results ? $base_url . ';start=' . (floor(($total_results - 1) / 7) * 7) : '', | |
483 'up' => $scripturl . '?action=pm;sa=send' . (empty($_REQUEST['u']) ? '' : ';u=' . $_REQUEST['u']), | |
484 ); | |
485 $context['page_info'] = array( | |
486 'current_page' => $_REQUEST['start'] / 7 + 1, | |
487 'num_pages' => floor(($total_results - 1) / 7) + 1 | |
488 ); | |
489 | |
490 $context['results'] = array_slice($context['results'], $_REQUEST['start'], 7); | |
491 } | |
492 else | |
493 $context['links']['up'] = $scripturl . '?action=pm;sa=send' . (empty($_REQUEST['u']) ? '' : ';u=' . $_REQUEST['u']); | |
494 } | |
495 | |
496 function RequestMembers() | |
497 { | |
498 global $user_info, $txt, $smcFunc; | |
499 | |
500 checkSession('get'); | |
501 | |
502 $_REQUEST['search'] = $smcFunc['htmlspecialchars']($_REQUEST['search']) . '*'; | |
503 $_REQUEST['search'] = trim($smcFunc['strtolower']($_REQUEST['search'])); | |
504 $_REQUEST['search'] = strtr($_REQUEST['search'], array('%' => '\%', '_' => '\_', '*' => '%', '?' => '_', '&' => '&')); | |
505 | |
506 if (function_exists('iconv')) | |
507 header('Content-Type: text/plain; charset=UTF-8'); | |
508 | |
509 $request = $smcFunc['db_query']('', ' | |
510 SELECT real_name | |
511 FROM {db_prefix}members | |
512 WHERE real_name LIKE {string:search}' . (isset($_REQUEST['buddies']) ? ' | |
513 AND id_member IN ({array_int:buddy_list})' : '') . ' | |
514 AND is_activated IN (1, 11) | |
515 LIMIT ' . ($smcFunc['strlen']($_REQUEST['search']) <= 2 ? '100' : '800'), | |
516 array( | |
517 'buddy_list' => $user_info['buddies'], | |
518 'search' => $_REQUEST['search'], | |
519 ) | |
520 ); | |
521 while ($row = $smcFunc['db_fetch_assoc']($request)) | |
522 { | |
523 if (function_exists('iconv')) | |
524 { | |
525 $utf8 = iconv($txt['lang_character_set'], 'UTF-8', $row['real_name']); | |
526 if ($utf8) | |
527 $row['real_name'] = $utf8; | |
528 } | |
529 | |
530 $row['real_name'] = strtr($row['real_name'], array('&' => '&', '<' => '<', '>' => '>', '"' => '"')); | |
531 | |
532 if (preg_match('~&#\d+;~', $row['real_name']) != 0) | |
533 { | |
534 $fixchar = create_function('$n', ' | |
535 if ($n < 128) | |
536 return chr($n); | |
537 elseif ($n < 2048) | |
538 return chr(192 | $n >> 6) . chr(128 | $n & 63); | |
539 elseif ($n < 65536) | |
540 return chr(224 | $n >> 12) . chr(128 | $n >> 6 & 63) . chr(128 | $n & 63); | |
541 else | |
542 return chr(240 | $n >> 18) . chr(128 | $n >> 12 & 63) . chr(128 | $n >> 6 & 63) . chr(128 | $n & 63);'); | |
543 | |
544 $row['real_name'] = preg_replace('~&#(\d+);~e', '$fixchar(\'$1\')', $row['real_name']); | |
545 } | |
546 | |
547 echo $row['real_name'], "\n"; | |
548 } | |
549 $smcFunc['db_free_result']($request); | |
550 | |
551 obExit(false); | |
552 } | |
553 | |
554 // This function generates a random password for a user and emails it to them. | |
555 function resetPassword($memID, $username = null) | |
556 { | |
557 global $scripturl, $context, $txt, $sourcedir, $modSettings, $smcFunc, $language; | |
558 | |
559 // Language... and a required file. | |
560 loadLanguage('Login'); | |
561 require_once($sourcedir . '/Subs-Post.php'); | |
562 | |
563 // Get some important details. | |
564 $request = $smcFunc['db_query']('', ' | |
565 SELECT member_name, email_address, lngfile | |
566 FROM {db_prefix}members | |
567 WHERE id_member = {int:id_member}', | |
568 array( | |
569 'id_member' => $memID, | |
570 ) | |
571 ); | |
572 list ($user, $email, $lngfile) = $smcFunc['db_fetch_row']($request); | |
573 $smcFunc['db_free_result']($request); | |
574 | |
575 if ($username !== null) | |
576 { | |
577 $old_user = $user; | |
578 $user = trim($username); | |
579 } | |
580 | |
581 // Generate a random password. | |
582 $newPassword = substr(preg_replace('/\W/', '', md5(mt_rand())), 0, 10); | |
583 $newPassword_sha1 = sha1(strtolower($user) . $newPassword); | |
584 | |
585 // Do some checks on the username if needed. | |
586 if ($username !== null) | |
587 { | |
588 validateUsername($memID, $user); | |
589 | |
590 // Update the database... | |
591 updateMemberData($memID, array('member_name' => $user, 'passwd' => $newPassword_sha1)); | |
592 } | |
593 else | |
594 updateMemberData($memID, array('passwd' => $newPassword_sha1)); | |
595 | |
596 call_integration_hook('integrate_reset_pass', array($old_user, $user, $newPassword)); | |
597 | |
598 $replacements = array( | |
599 'USERNAME' => $user, | |
600 'PASSWORD' => $newPassword, | |
601 ); | |
602 | |
603 $emaildata = loadEmailTemplate('change_password', $replacements, empty($lngfile) || empty($modSettings['userLanguage']) ? $language : $lngfile); | |
604 | |
605 // Send them the email informing them of the change - then we're done! | |
606 sendmail($email, $emaildata['subject'], $emaildata['body'], null, null, false, 0); | |
607 } | |
608 | |
609 // Is this a valid username? | |
610 function validateUsername($memID, $username) | |
611 { | |
612 global $sourcedir, $txt; | |
613 | |
614 // No name?! How can you register with no name? | |
615 if ($username == '') | |
616 fatal_lang_error('need_username', false); | |
617 | |
618 // Only these characters are permitted. | |
619 if (in_array($username, array('_', '|')) || preg_match('~[<>&"\'=\\\\]~', preg_replace('~&#(?:\\d{1,7}|x[0-9a-fA-F]{1,6});~', '', $username)) != 0 || strpos($username, '[code') !== false || strpos($username, '[/code') !== false) | |
620 fatal_lang_error('error_invalid_characters_username', false); | |
621 | |
622 if (stristr($username, $txt['guest_title']) !== false) | |
623 fatal_lang_error('username_reserved', true, array($txt['guest_title'])); | |
624 | |
625 require_once($sourcedir . '/Subs-Members.php'); | |
626 if (isReservedName($username, $memID, false)) | |
627 fatal_error('(' . htmlspecialchars($username) . ') ' . $txt['name_in_use'], false); | |
628 | |
629 return null; | |
630 } | |
631 | |
632 // This function simply checks whether a password meets the current forum rules. | |
633 function validatePassword($password, $username, $restrict_in = array()) | |
634 { | |
635 global $modSettings, $smcFunc; | |
636 | |
637 // Perform basic requirements first. | |
638 if ($smcFunc['strlen']($password) < (empty($modSettings['password_strength']) ? 4 : 8)) | |
639 return 'short'; | |
640 | |
641 // Is this enough? | |
642 if (empty($modSettings['password_strength'])) | |
643 return null; | |
644 | |
645 // Otherwise, perform the medium strength test - checking if password appears in the restricted string. | |
646 if (preg_match('~\b' . preg_quote($password, '~') . '\b~', implode(' ', $restrict_in)) != 0) | |
647 return 'restricted_words'; | |
648 elseif ($smcFunc['strpos']($password, $username) !== false) | |
649 return 'restricted_words'; | |
650 | |
651 // !!! If pspell is available, use it on the word, and return restricted_words if it doesn't give "bad spelling"? | |
652 | |
653 // If just medium, we're done. | |
654 if ($modSettings['password_strength'] == 1) | |
655 return null; | |
656 | |
657 // Otherwise, hard test next, check for numbers and letters, uppercase too. | |
658 $good = preg_match('~(\D\d|\d\D)~', $password) != 0; | |
659 $good &= $smcFunc['strtolower']($password) != $password; | |
660 | |
661 return $good ? null : 'chars'; | |
662 } | |
663 | |
664 // Quickly find out what this user can and cannot do. | |
665 function rebuildModCache() | |
666 { | |
667 global $user_info, $smcFunc; | |
668 | |
669 // What groups can they moderate? | |
670 $group_query = allowedTo('manage_membergroups') ? '1=1' : '0=1'; | |
671 | |
672 if ($group_query == '0=1') | |
673 { | |
674 $request = $smcFunc['db_query']('', ' | |
675 SELECT id_group | |
676 FROM {db_prefix}group_moderators | |
677 WHERE id_member = {int:current_member}', | |
678 array( | |
679 'current_member' => $user_info['id'], | |
680 ) | |
681 ); | |
682 $groups = array(); | |
683 while ($row = $smcFunc['db_fetch_assoc']($request)) | |
684 $groups[] = $row['id_group']; | |
685 $smcFunc['db_free_result']($request); | |
686 | |
687 if (empty($groups)) | |
688 $group_query = '0=1'; | |
689 else | |
690 $group_query = 'id_group IN (' . implode(',', $groups) . ')'; | |
691 } | |
692 | |
693 // Then, same again, just the boards this time! | |
694 $board_query = allowedTo('moderate_forum') ? '1=1' : '0=1'; | |
695 | |
696 if ($board_query == '0=1') | |
697 { | |
698 $boards = boardsAllowedTo('moderate_board', true); | |
699 | |
700 if (empty($boards)) | |
701 $board_query = '0=1'; | |
702 else | |
703 $board_query = 'id_board IN (' . implode(',', $boards) . ')'; | |
704 } | |
705 | |
706 // What boards are they the moderator of? | |
707 $boards_mod = array(); | |
708 if (!$user_info['is_guest']) | |
709 { | |
710 $request = $smcFunc['db_query']('', ' | |
711 SELECT id_board | |
712 FROM {db_prefix}moderators | |
713 WHERE id_member = {int:current_member}', | |
714 array( | |
715 'current_member' => $user_info['id'], | |
716 ) | |
717 ); | |
718 while ($row = $smcFunc['db_fetch_assoc']($request)) | |
719 $boards_mod[] = $row['id_board']; | |
720 $smcFunc['db_free_result']($request); | |
721 } | |
722 | |
723 $mod_query = empty($boards_mod) ? '0=1' : 'b.id_board IN (' . implode(',', $boards_mod) . ')'; | |
724 | |
725 $_SESSION['mc'] = array( | |
726 'time' => time(), | |
727 // This looks a bit funny but protects against the login redirect. | |
728 'id' => $user_info['id'] && $user_info['name'] ? $user_info['id'] : 0, | |
729 // If you change the format of 'gq' and/or 'bq' make sure to adjust 'can_mod' in Load.php. | |
730 'gq' => $group_query, | |
731 'bq' => $board_query, | |
732 'ap' => boardsAllowedTo('approve_posts'), | |
733 'mb' => $boards_mod, | |
734 'mq' => $mod_query, | |
735 ); | |
736 | |
737 $user_info['mod_cache'] = $_SESSION['mc']; | |
738 } | |
739 | |
740 ?> |