Yoshi2889 /
SMF2.1
| 1 | <?php |
||
| 2 | |||
| 3 | /** |
||
| 4 | * This file contains some useful functions for members and membergroups. |
||
| 5 | * |
||
| 6 | * Simple Machines Forum (SMF) |
||
| 7 | * |
||
| 8 | * @package SMF |
||
| 9 | * @author Simple Machines http://www.simplemachines.org |
||
| 10 | * @copyright 2019 Simple Machines and individual contributors |
||
| 11 | * @license http://www.simplemachines.org/about/smf/license.php BSD |
||
| 12 | * |
||
| 13 | * @version 2.1 RC2 |
||
| 14 | */ |
||
| 15 | |||
| 16 | if (!defined('SMF')) |
||
| 17 | die('No direct access...'); |
||
| 18 | |||
| 19 | /** |
||
| 20 | * Delete one or more members. |
||
| 21 | * Requires profile_remove_own or profile_remove_any permission for |
||
| 22 | * respectively removing your own account or any account. |
||
| 23 | * Non-admins cannot delete admins. |
||
| 24 | * The function: |
||
| 25 | * - changes author of messages, topics and polls to guest authors. |
||
| 26 | * - removes all log entries concerning the deleted members, except the |
||
| 27 | * error logs, ban logs and moderation logs. |
||
| 28 | * - removes these members' personal messages (only the inbox), avatars, |
||
| 29 | * ban entries, theme settings, moderator positions, poll and votes. |
||
| 30 | * - updates member statistics afterwards. |
||
| 31 | * |
||
| 32 | * @param int|array $users The ID of a user or an array of user IDs |
||
| 33 | * @param bool $check_not_admin Whether to verify that the users aren't admins |
||
| 34 | */ |
||
| 35 | function deleteMembers($users, $check_not_admin = false) |
||
| 36 | { |
||
| 37 | global $sourcedir, $modSettings, $user_info, $smcFunc, $cache_enable; |
||
| 38 | |||
| 39 | // Try give us a while to sort this out... |
||
| 40 | @set_time_limit(600); |
||
| 41 | |||
| 42 | // Try to get some more memory. |
||
| 43 | setMemoryLimit('128M'); |
||
| 44 | |||
| 45 | // If it's not an array, make it so! |
||
| 46 | if (!is_array($users)) |
||
| 47 | $users = array($users); |
||
| 48 | else |
||
| 49 | $users = array_unique($users); |
||
| 50 | |||
| 51 | // Make sure there's no void user in here. |
||
| 52 | $users = array_diff($users, array(0)); |
||
| 53 | |||
| 54 | // How many are they deleting? |
||
| 55 | if (empty($users)) |
||
| 56 | return; |
||
| 57 | elseif (count($users) == 1) |
||
| 58 | { |
||
| 59 | list ($user) = $users; |
||
| 60 | |||
| 61 | if ($user == $user_info['id']) |
||
| 62 | isAllowedTo('profile_remove_own'); |
||
| 63 | else |
||
| 64 | isAllowedTo('profile_remove_any'); |
||
| 65 | } |
||
| 66 | else |
||
| 67 | { |
||
| 68 | foreach ($users as $k => $v) |
||
| 69 | $users[$k] = (int) $v; |
||
| 70 | |||
| 71 | // Deleting more than one? You can't have more than one account... |
||
| 72 | isAllowedTo('profile_remove_any'); |
||
| 73 | } |
||
| 74 | |||
| 75 | // Get their names for logging purposes. |
||
| 76 | $request = $smcFunc['db_query']('', ' |
||
| 77 | SELECT id_member, member_name, CASE WHEN id_group = {int:admin_group} OR FIND_IN_SET({int:admin_group}, additional_groups) != 0 THEN 1 ELSE 0 END AS is_admin |
||
| 78 | FROM {db_prefix}members |
||
| 79 | WHERE id_member IN ({array_int:user_list}) |
||
| 80 | LIMIT {int:limit}', |
||
| 81 | array( |
||
| 82 | 'user_list' => $users, |
||
| 83 | 'admin_group' => 1, |
||
| 84 | 'limit' => count($users), |
||
| 85 | ) |
||
| 86 | ); |
||
| 87 | $admins = array(); |
||
| 88 | $user_log_details = array(); |
||
| 89 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
| 90 | { |
||
| 91 | if ($row['is_admin']) |
||
| 92 | $admins[] = $row['id_member']; |
||
| 93 | $user_log_details[$row['id_member']] = array($row['id_member'], $row['member_name']); |
||
| 94 | } |
||
| 95 | $smcFunc['db_free_result']($request); |
||
| 96 | |||
| 97 | if (empty($user_log_details)) |
||
| 98 | return; |
||
| 99 | |||
| 100 | // Make sure they aren't trying to delete administrators if they aren't one. But don't bother checking if it's just themself. |
||
| 101 | if (!empty($admins) && ($check_not_admin || (!allowedTo('admin_forum') && (count($users) != 1 || $users[0] != $user_info['id'])))) |
||
| 102 | { |
||
| 103 | $users = array_diff($users, $admins); |
||
| 104 | foreach ($admins as $id) |
||
| 105 | unset($user_log_details[$id]); |
||
| 106 | } |
||
| 107 | |||
| 108 | // No one left? |
||
| 109 | if (empty($users)) |
||
| 110 | return; |
||
| 111 | |||
| 112 | // Log the action - regardless of who is deleting it. |
||
| 113 | $log_changes = array(); |
||
| 114 | foreach ($user_log_details as $user) |
||
| 115 | { |
||
| 116 | $log_changes[] = array( |
||
| 117 | 'action' => 'delete_member', |
||
| 118 | 'log_type' => 'admin', |
||
| 119 | 'extra' => array( |
||
| 120 | 'member' => $user[0], |
||
| 121 | 'name' => $user[1], |
||
| 122 | 'member_acted' => $user_info['name'], |
||
| 123 | ), |
||
| 124 | ); |
||
| 125 | |||
| 126 | // Remove any cached data if enabled. |
||
| 127 | if (!empty($cache_enable) && $cache_enable >= 2) |
||
| 128 | cache_put_data('user_settings-' . $user[0], null, 60); |
||
| 129 | } |
||
| 130 | |||
| 131 | // Make these peoples' posts guest posts. |
||
| 132 | $smcFunc['db_query']('', ' |
||
| 133 | UPDATE {db_prefix}messages |
||
| 134 | SET id_member = {int:guest_id}' . (!empty($modSettings['deleteMembersRemovesEmail']) ? ', |
||
| 135 | poster_email = {string:blank_email}' : '') . ' |
||
| 136 | WHERE id_member IN ({array_int:users})', |
||
| 137 | array( |
||
| 138 | 'guest_id' => 0, |
||
| 139 | 'blank_email' => '', |
||
| 140 | 'users' => $users, |
||
| 141 | ) |
||
| 142 | ); |
||
| 143 | $smcFunc['db_query']('', ' |
||
| 144 | UPDATE {db_prefix}polls |
||
| 145 | SET id_member = {int:guest_id} |
||
| 146 | WHERE id_member IN ({array_int:users})', |
||
| 147 | array( |
||
| 148 | 'guest_id' => 0, |
||
| 149 | 'users' => $users, |
||
| 150 | ) |
||
| 151 | ); |
||
| 152 | |||
| 153 | // Make these peoples' posts guest first posts and last posts. |
||
| 154 | $smcFunc['db_query']('', ' |
||
| 155 | UPDATE {db_prefix}topics |
||
| 156 | SET id_member_started = {int:guest_id} |
||
| 157 | WHERE id_member_started IN ({array_int:users})', |
||
| 158 | array( |
||
| 159 | 'guest_id' => 0, |
||
| 160 | 'users' => $users, |
||
| 161 | ) |
||
| 162 | ); |
||
| 163 | $smcFunc['db_query']('', ' |
||
| 164 | UPDATE {db_prefix}topics |
||
| 165 | SET id_member_updated = {int:guest_id} |
||
| 166 | WHERE id_member_updated IN ({array_int:users})', |
||
| 167 | array( |
||
| 168 | 'guest_id' => 0, |
||
| 169 | 'users' => $users, |
||
| 170 | ) |
||
| 171 | ); |
||
| 172 | |||
| 173 | $smcFunc['db_query']('', ' |
||
| 174 | UPDATE {db_prefix}log_actions |
||
| 175 | SET id_member = {int:guest_id} |
||
| 176 | WHERE id_member IN ({array_int:users})', |
||
| 177 | array( |
||
| 178 | 'guest_id' => 0, |
||
| 179 | 'users' => $users, |
||
| 180 | ) |
||
| 181 | ); |
||
| 182 | |||
| 183 | $smcFunc['db_query']('', ' |
||
| 184 | UPDATE {db_prefix}log_banned |
||
| 185 | SET id_member = {int:guest_id} |
||
| 186 | WHERE id_member IN ({array_int:users})', |
||
| 187 | array( |
||
| 188 | 'guest_id' => 0, |
||
| 189 | 'users' => $users, |
||
| 190 | ) |
||
| 191 | ); |
||
| 192 | |||
| 193 | $smcFunc['db_query']('', ' |
||
| 194 | UPDATE {db_prefix}log_errors |
||
| 195 | SET id_member = {int:guest_id} |
||
| 196 | WHERE id_member IN ({array_int:users})', |
||
| 197 | array( |
||
| 198 | 'guest_id' => 0, |
||
| 199 | 'users' => $users, |
||
| 200 | ) |
||
| 201 | ); |
||
| 202 | |||
| 203 | // Delete the member. |
||
| 204 | $smcFunc['db_query']('', ' |
||
| 205 | DELETE FROM {db_prefix}members |
||
| 206 | WHERE id_member IN ({array_int:users})', |
||
| 207 | array( |
||
| 208 | 'users' => $users, |
||
| 209 | ) |
||
| 210 | ); |
||
| 211 | |||
| 212 | // Delete any drafts... |
||
| 213 | $smcFunc['db_query']('', ' |
||
| 214 | DELETE FROM {db_prefix}user_drafts |
||
| 215 | WHERE id_member IN ({array_int:users})', |
||
| 216 | array( |
||
| 217 | 'users' => $users, |
||
| 218 | ) |
||
| 219 | ); |
||
| 220 | |||
| 221 | // Delete anything they liked. |
||
| 222 | $smcFunc['db_query']('', ' |
||
| 223 | DELETE FROM {db_prefix}user_likes |
||
| 224 | WHERE id_member IN ({array_int:users})', |
||
| 225 | array( |
||
| 226 | 'users' => $users, |
||
| 227 | ) |
||
| 228 | ); |
||
| 229 | |||
| 230 | // Delete their mentions |
||
| 231 | $smcFunc['db_query']('', ' |
||
| 232 | DELETE FROM {db_prefix}mentions |
||
| 233 | WHERE id_member IN ({array_int:members})', |
||
| 234 | array( |
||
| 235 | 'members' => $users, |
||
| 236 | ) |
||
| 237 | ); |
||
| 238 | |||
| 239 | // Delete the logs... |
||
| 240 | $smcFunc['db_query']('', ' |
||
| 241 | DELETE FROM {db_prefix}log_actions |
||
| 242 | WHERE id_log = {int:log_type} |
||
| 243 | AND id_member IN ({array_int:users})', |
||
| 244 | array( |
||
| 245 | 'log_type' => 2, |
||
| 246 | 'users' => $users, |
||
| 247 | ) |
||
| 248 | ); |
||
| 249 | $smcFunc['db_query']('', ' |
||
| 250 | DELETE FROM {db_prefix}log_boards |
||
| 251 | WHERE id_member IN ({array_int:users})', |
||
| 252 | array( |
||
| 253 | 'users' => $users, |
||
| 254 | ) |
||
| 255 | ); |
||
| 256 | $smcFunc['db_query']('', ' |
||
| 257 | DELETE FROM {db_prefix}log_comments |
||
| 258 | WHERE id_recipient IN ({array_int:users}) |
||
| 259 | AND comment_type = {string:warntpl}', |
||
| 260 | array( |
||
| 261 | 'users' => $users, |
||
| 262 | 'warntpl' => 'warntpl', |
||
| 263 | ) |
||
| 264 | ); |
||
| 265 | $smcFunc['db_query']('', ' |
||
| 266 | DELETE FROM {db_prefix}log_group_requests |
||
| 267 | WHERE id_member IN ({array_int:users})', |
||
| 268 | array( |
||
| 269 | 'users' => $users, |
||
| 270 | ) |
||
| 271 | ); |
||
| 272 | $smcFunc['db_query']('', ' |
||
| 273 | DELETE FROM {db_prefix}log_mark_read |
||
| 274 | WHERE id_member IN ({array_int:users})', |
||
| 275 | array( |
||
| 276 | 'users' => $users, |
||
| 277 | ) |
||
| 278 | ); |
||
| 279 | $smcFunc['db_query']('', ' |
||
| 280 | DELETE FROM {db_prefix}log_notify |
||
| 281 | WHERE id_member IN ({array_int:users})', |
||
| 282 | array( |
||
| 283 | 'users' => $users, |
||
| 284 | ) |
||
| 285 | ); |
||
| 286 | $smcFunc['db_query']('', ' |
||
| 287 | DELETE FROM {db_prefix}log_online |
||
| 288 | WHERE id_member IN ({array_int:users})', |
||
| 289 | array( |
||
| 290 | 'users' => $users, |
||
| 291 | ) |
||
| 292 | ); |
||
| 293 | $smcFunc['db_query']('', ' |
||
| 294 | DELETE FROM {db_prefix}log_subscribed |
||
| 295 | WHERE id_member IN ({array_int:users})', |
||
| 296 | array( |
||
| 297 | 'users' => $users, |
||
| 298 | ) |
||
| 299 | ); |
||
| 300 | $smcFunc['db_query']('', ' |
||
| 301 | DELETE FROM {db_prefix}log_topics |
||
| 302 | WHERE id_member IN ({array_int:users})', |
||
| 303 | array( |
||
| 304 | 'users' => $users, |
||
| 305 | ) |
||
| 306 | ); |
||
| 307 | |||
| 308 | // Make their votes appear as guest votes - at least it keeps the totals right. |
||
| 309 | // @todo Consider adding back in cookie protection. |
||
| 310 | $smcFunc['db_query']('', ' |
||
| 311 | UPDATE {db_prefix}log_polls |
||
| 312 | SET id_member = {int:guest_id} |
||
| 313 | WHERE id_member IN ({array_int:users})', |
||
| 314 | array( |
||
| 315 | 'guest_id' => 0, |
||
| 316 | 'users' => $users, |
||
| 317 | ) |
||
| 318 | ); |
||
| 319 | |||
| 320 | // Delete personal messages. |
||
| 321 | require_once($sourcedir . '/PersonalMessage.php'); |
||
| 322 | deleteMessages(null, null, $users); |
||
| 323 | |||
| 324 | $smcFunc['db_query']('', ' |
||
| 325 | UPDATE {db_prefix}personal_messages |
||
| 326 | SET id_member_from = {int:guest_id} |
||
| 327 | WHERE id_member_from IN ({array_int:users})', |
||
| 328 | array( |
||
| 329 | 'guest_id' => 0, |
||
| 330 | 'users' => $users, |
||
| 331 | ) |
||
| 332 | ); |
||
| 333 | |||
| 334 | // They no longer exist, so we don't know who it was sent to. |
||
| 335 | $smcFunc['db_query']('', ' |
||
| 336 | DELETE FROM {db_prefix}pm_recipients |
||
| 337 | WHERE id_member IN ({array_int:users})', |
||
| 338 | array( |
||
| 339 | 'users' => $users, |
||
| 340 | ) |
||
| 341 | ); |
||
| 342 | |||
| 343 | // Delete avatar. |
||
| 344 | require_once($sourcedir . '/ManageAttachments.php'); |
||
| 345 | removeAttachments(array('id_member' => $users)); |
||
| 346 | |||
| 347 | // It's over, no more moderation for you. |
||
| 348 | $smcFunc['db_query']('', ' |
||
| 349 | DELETE FROM {db_prefix}moderators |
||
| 350 | WHERE id_member IN ({array_int:users})', |
||
| 351 | array( |
||
| 352 | 'users' => $users, |
||
| 353 | ) |
||
| 354 | ); |
||
| 355 | $smcFunc['db_query']('', ' |
||
| 356 | DELETE FROM {db_prefix}group_moderators |
||
| 357 | WHERE id_member IN ({array_int:users})', |
||
| 358 | array( |
||
| 359 | 'users' => $users, |
||
| 360 | ) |
||
| 361 | ); |
||
| 362 | |||
| 363 | // If you don't exist we can't ban you. |
||
| 364 | $smcFunc['db_query']('', ' |
||
| 365 | DELETE FROM {db_prefix}ban_items |
||
| 366 | WHERE id_member IN ({array_int:users})', |
||
| 367 | array( |
||
| 368 | 'users' => $users, |
||
| 369 | ) |
||
| 370 | ); |
||
| 371 | |||
| 372 | // Remove individual theme settings. |
||
| 373 | $smcFunc['db_query']('', ' |
||
| 374 | DELETE FROM {db_prefix}themes |
||
| 375 | WHERE id_member IN ({array_int:users})', |
||
| 376 | array( |
||
| 377 | 'users' => $users, |
||
| 378 | ) |
||
| 379 | ); |
||
| 380 | |||
| 381 | // These users are nobody's buddy nomore. |
||
| 382 | $request = $smcFunc['db_query']('', ' |
||
| 383 | SELECT id_member, pm_ignore_list, buddy_list |
||
| 384 | FROM {db_prefix}members |
||
| 385 | WHERE FIND_IN_SET({raw:pm_ignore_list}, pm_ignore_list) != 0 OR FIND_IN_SET({raw:buddy_list}, buddy_list) != 0', |
||
| 386 | array( |
||
| 387 | 'pm_ignore_list' => implode(', pm_ignore_list) != 0 OR FIND_IN_SET(', $users), |
||
| 388 | 'buddy_list' => implode(', buddy_list) != 0 OR FIND_IN_SET(', $users), |
||
| 389 | ) |
||
| 390 | ); |
||
| 391 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
| 392 | $smcFunc['db_query']('', ' |
||
| 393 | UPDATE {db_prefix}members |
||
| 394 | SET |
||
| 395 | pm_ignore_list = {string:pm_ignore_list}, |
||
| 396 | buddy_list = {string:buddy_list} |
||
| 397 | WHERE id_member = {int:id_member}', |
||
| 398 | array( |
||
| 399 | 'id_member' => $row['id_member'], |
||
| 400 | 'pm_ignore_list' => implode(',', array_diff(explode(',', $row['pm_ignore_list']), $users)), |
||
| 401 | 'buddy_list' => implode(',', array_diff(explode(',', $row['buddy_list']), $users)), |
||
| 402 | ) |
||
| 403 | ); |
||
| 404 | $smcFunc['db_free_result']($request); |
||
| 405 | |||
| 406 | // Make sure no member's birthday is still sticking in the calendar... |
||
| 407 | updateSettings(array( |
||
| 408 | 'calendar_updated' => time(), |
||
| 409 | )); |
||
| 410 | |||
| 411 | // Integration rocks! |
||
| 412 | call_integration_hook('integrate_delete_members', array($users)); |
||
| 413 | |||
| 414 | updateStats('member'); |
||
| 415 | |||
| 416 | require_once($sourcedir . '/Logging.php'); |
||
| 417 | logActions($log_changes); |
||
| 418 | } |
||
| 419 | |||
| 420 | /** |
||
| 421 | * Registers a member to the forum. |
||
| 422 | * Allows two types of interface: 'guest' and 'admin'. The first |
||
| 423 | * includes hammering protection, the latter can perform the |
||
| 424 | * registration silently. |
||
| 425 | * The strings used in the options array are assumed to be escaped. |
||
| 426 | * Allows to perform several checks on the input, e.g. reserved names. |
||
| 427 | * The function will adjust member statistics. |
||
| 428 | * If an error is detected will fatal error on all errors unless return_errors is true. |
||
| 429 | * |
||
| 430 | * @param array $regOptions An array of registration options |
||
| 431 | * @param bool $return_errors Whether to return the errors |
||
| 432 | * @return int|array The ID of the newly registered user or an array of error info if $return_errors is true |
||
| 433 | */ |
||
| 434 | function registerMember(&$regOptions, $return_errors = false) |
||
| 435 | { |
||
| 436 | global $scripturl, $txt, $modSettings, $context, $sourcedir; |
||
| 437 | global $user_info, $smcFunc; |
||
| 438 | |||
| 439 | loadLanguage('Login'); |
||
| 440 | |||
| 441 | // We'll need some external functions. |
||
| 442 | require_once($sourcedir . '/Subs-Auth.php'); |
||
| 443 | require_once($sourcedir . '/Subs-Post.php'); |
||
| 444 | |||
| 445 | // Put any errors in here. |
||
| 446 | $reg_errors = array(); |
||
| 447 | |||
| 448 | // Registration from the admin center, let them sweat a little more. |
||
| 449 | if ($regOptions['interface'] == 'admin') |
||
| 450 | { |
||
| 451 | is_not_guest(); |
||
| 452 | isAllowedTo('moderate_forum'); |
||
| 453 | } |
||
| 454 | // If you're an admin, you're special ;). |
||
| 455 | elseif ($regOptions['interface'] == 'guest') |
||
| 456 | { |
||
| 457 | // You cannot register twice... |
||
| 458 | if (empty($user_info['is_guest'])) |
||
| 459 | redirectexit(); |
||
| 460 | |||
| 461 | // Make sure they didn't just register with this session. |
||
| 462 | if (!empty($_SESSION['just_registered']) && empty($modSettings['disableRegisterCheck'])) |
||
| 463 | fatal_lang_error('register_only_once', false); |
||
| 464 | } |
||
| 465 | |||
| 466 | // Spaces and other odd characters are evil... |
||
| 467 | $regOptions['username'] = trim(preg_replace('~[\t\n\r \x0B\0' . ($context['utf8'] ? '\x{A0}\x{AD}\x{2000}-\x{200F}\x{201F}\x{202F}\x{3000}\x{FEFF}' : '\x00-\x08\x0B\x0C\x0E-\x19\xA0') . ']+~' . ($context['utf8'] ? 'u' : ''), ' ', $regOptions['username'])); |
||
| 468 | |||
| 469 | // Convert character encoding for non-utf8mb4 database |
||
| 470 | $regOptions['username'] = $smcFunc['htmlspecialchars']($regOptions['username']); |
||
| 471 | |||
| 472 | // @todo Separate the sprintf? |
||
| 473 | if (empty($regOptions['email']) || !filter_var($regOptions['email'], FILTER_VALIDATE_EMAIL) || strlen($regOptions['email']) > 255) |
||
| 474 | $reg_errors[] = array('lang', 'profile_error_bad_email'); |
||
| 475 | |||
| 476 | $username_validation_errors = validateUsername(0, $regOptions['username'], true, !empty($regOptions['check_reserved_name'])); |
||
| 477 | if (!empty($username_validation_errors)) |
||
| 478 | $reg_errors = array_merge($reg_errors, $username_validation_errors); |
||
| 479 | |||
| 480 | // Generate a validation code if it's supposed to be emailed. |
||
| 481 | $validation_code = ''; |
||
| 482 | if ($regOptions['require'] == 'activation') |
||
| 483 | $validation_code = generateValidationCode(); |
||
| 484 | |||
| 485 | // If you haven't put in a password generate one. |
||
| 486 | if ($regOptions['interface'] == 'admin' && $regOptions['password'] == '') |
||
| 487 | { |
||
| 488 | mt_srand(time() + 1277); |
||
| 489 | $regOptions['password'] = generateValidationCode(); |
||
| 490 | $regOptions['password_check'] = $regOptions['password']; |
||
| 491 | } |
||
| 492 | // Does the first password match the second? |
||
| 493 | elseif ($regOptions['password'] != $regOptions['password_check']) |
||
| 494 | $reg_errors[] = array('lang', 'passwords_dont_match'); |
||
| 495 | |||
| 496 | // That's kind of easy to guess... |
||
| 497 | if ($regOptions['password'] == '') |
||
| 498 | { |
||
| 499 | $reg_errors[] = array('lang', 'no_password'); |
||
| 500 | } |
||
| 501 | |||
| 502 | // Now perform hard password validation as required. |
||
| 503 | if (!empty($regOptions['check_password_strength']) && $regOptions['password'] != '') |
||
| 504 | { |
||
| 505 | $passwordError = validatePassword($regOptions['password'], $regOptions['username'], array($regOptions['email'])); |
||
| 506 | |||
| 507 | // Password isn't legal? |
||
| 508 | if ($passwordError != null) |
||
|
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||
| 509 | $reg_errors[] = array('lang', 'profile_error_password_' . $passwordError); |
||
| 510 | } |
||
| 511 | |||
| 512 | // You may not be allowed to register this email. |
||
| 513 | if (!empty($regOptions['check_email_ban'])) |
||
| 514 | isBannedEmail($regOptions['email'], 'cannot_register', $txt['ban_register_prohibited']); |
||
| 515 | |||
| 516 | // Check if the email address is in use. |
||
| 517 | $request = $smcFunc['db_query']('', ' |
||
| 518 | SELECT id_member |
||
| 519 | FROM {db_prefix}members |
||
| 520 | WHERE email_address = {string:email_address} |
||
| 521 | OR email_address = {string:username} |
||
| 522 | LIMIT 1', |
||
| 523 | array( |
||
| 524 | 'email_address' => $regOptions['email'], |
||
| 525 | 'username' => $regOptions['username'], |
||
| 526 | ) |
||
| 527 | ); |
||
| 528 | // @todo Separate the sprintf? |
||
| 529 | if ($smcFunc['db_num_rows']($request) != 0) |
||
| 530 | $reg_errors[] = array('lang', 'email_in_use', false, array($smcFunc['htmlspecialchars']($regOptions['email']))); |
||
| 531 | |||
| 532 | $smcFunc['db_free_result']($request); |
||
| 533 | |||
| 534 | // Perhaps someone else wants to check this user. |
||
| 535 | call_integration_hook('integrate_register_check', array(&$regOptions, &$reg_errors)); |
||
| 536 | |||
| 537 | // If we found any errors we need to do something about it right away! |
||
| 538 | foreach ($reg_errors as $key => $error) |
||
| 539 | { |
||
| 540 | /* Note for each error: |
||
| 541 | 0 = 'lang' if it's an index, 'done' if it's clear text. |
||
| 542 | 1 = The text/index. |
||
| 543 | 2 = Whether to log. |
||
| 544 | 3 = sprintf data if necessary. */ |
||
| 545 | if ($error[0] == 'lang') |
||
| 546 | loadLanguage('Errors'); |
||
| 547 | $message = $error[0] == 'lang' ? (empty($error[3]) ? $txt[$error[1]] : vsprintf($txt[$error[1]], $error[3])) : $error[1]; |
||
| 548 | |||
| 549 | // What to do, what to do, what to do. |
||
| 550 | if ($return_errors) |
||
| 551 | { |
||
| 552 | if (!empty($error[2])) |
||
| 553 | log_error($message, $error[2]); |
||
| 554 | $reg_errors[$key] = $message; |
||
| 555 | } |
||
| 556 | else |
||
| 557 | fatal_error($message, empty($error[2]) ? false : $error[2]); |
||
| 558 | } |
||
| 559 | |||
| 560 | // If there's any errors left return them at once! |
||
| 561 | if (!empty($reg_errors)) |
||
| 562 | return $reg_errors; |
||
| 563 | |||
| 564 | $reservedVars = array( |
||
| 565 | 'actual_theme_url', |
||
| 566 | 'actual_images_url', |
||
| 567 | 'base_theme_dir', |
||
| 568 | 'base_theme_url', |
||
| 569 | 'default_images_url', |
||
| 570 | 'default_theme_dir', |
||
| 571 | 'default_theme_url', |
||
| 572 | 'default_template', |
||
| 573 | 'images_url', |
||
| 574 | 'number_recent_posts', |
||
| 575 | 'smiley_sets_default', |
||
| 576 | 'theme_dir', |
||
| 577 | 'theme_id', |
||
| 578 | 'theme_layers', |
||
| 579 | 'theme_templates', |
||
| 580 | 'theme_url', |
||
| 581 | ); |
||
| 582 | |||
| 583 | // Can't change reserved vars. |
||
| 584 | if (isset($regOptions['theme_vars']) && count(array_intersect(array_keys($regOptions['theme_vars']), $reservedVars)) != 0) |
||
| 585 | fatal_lang_error('no_theme'); |
||
| 586 | |||
| 587 | // Some of these might be overwritten. (the lower ones that are in the arrays below.) |
||
| 588 | $regOptions['register_vars'] = array( |
||
| 589 | 'member_name' => $regOptions['username'], |
||
| 590 | 'email_address' => $regOptions['email'], |
||
| 591 | 'passwd' => hash_password($regOptions['username'], $regOptions['password']), |
||
| 592 | 'password_salt' => substr(md5($smcFunc['random_int']()), 0, 4), |
||
| 593 | 'posts' => 0, |
||
| 594 | 'date_registered' => time(), |
||
| 595 | 'member_ip' => $regOptions['interface'] == 'admin' ? '127.0.0.1' : $user_info['ip'], |
||
| 596 | 'member_ip2' => $regOptions['interface'] == 'admin' ? '127.0.0.1' : $_SERVER['BAN_CHECK_IP'], |
||
| 597 | 'validation_code' => $validation_code, |
||
| 598 | 'real_name' => $regOptions['username'], |
||
| 599 | 'personal_text' => $modSettings['default_personal_text'], |
||
| 600 | 'id_theme' => 0, |
||
| 601 | 'id_post_group' => 4, |
||
| 602 | 'lngfile' => '', |
||
| 603 | 'buddy_list' => '', |
||
| 604 | 'pm_ignore_list' => '', |
||
| 605 | 'website_title' => '', |
||
| 606 | 'website_url' => '', |
||
| 607 | 'time_format' => '', |
||
| 608 | 'signature' => '', |
||
| 609 | 'avatar' => '', |
||
| 610 | 'usertitle' => '', |
||
| 611 | 'secret_question' => '', |
||
| 612 | 'secret_answer' => '', |
||
| 613 | 'additional_groups' => '', |
||
| 614 | 'ignore_boards' => '', |
||
| 615 | 'smiley_set' => '', |
||
| 616 | 'timezone' => !empty($regOptions['timezone']) ? $regOptions['timezone'] : 'UTC', |
||
| 617 | ); |
||
| 618 | |||
| 619 | // Setup the activation status on this new account so it is correct - firstly is it an under age account? |
||
| 620 | if ($regOptions['require'] == 'coppa') |
||
| 621 | { |
||
| 622 | $regOptions['register_vars']['is_activated'] = 5; |
||
| 623 | // @todo This should be changed. To what should be it be changed?? |
||
| 624 | $regOptions['register_vars']['validation_code'] = ''; |
||
| 625 | } |
||
| 626 | // Maybe it can be activated right away? |
||
| 627 | elseif ($regOptions['require'] == 'nothing') |
||
| 628 | $regOptions['register_vars']['is_activated'] = 1; |
||
| 629 | // Maybe it must be activated by email? |
||
| 630 | elseif ($regOptions['require'] == 'activation') |
||
| 631 | $regOptions['register_vars']['is_activated'] = 0; |
||
| 632 | // Otherwise it must be awaiting approval! |
||
| 633 | else |
||
| 634 | $regOptions['register_vars']['is_activated'] = 3; |
||
| 635 | |||
| 636 | if (isset($regOptions['memberGroup'])) |
||
| 637 | { |
||
| 638 | // Make sure the id_group will be valid, if this is an administrator. |
||
| 639 | $regOptions['register_vars']['id_group'] = $regOptions['memberGroup'] == 1 && !allowedTo('admin_forum') ? 0 : $regOptions['memberGroup']; |
||
| 640 | |||
| 641 | // Check if this group is assignable. |
||
| 642 | $unassignableGroups = array(-1, 3); |
||
| 643 | $request = $smcFunc['db_query']('', ' |
||
| 644 | SELECT id_group |
||
| 645 | FROM {db_prefix}membergroups |
||
| 646 | WHERE min_posts != {int:min_posts}' . (allowedTo('admin_forum') ? '' : ' |
||
| 647 | OR group_type = {int:is_protected}'), |
||
| 648 | array( |
||
| 649 | 'min_posts' => -1, |
||
| 650 | 'is_protected' => 1, |
||
| 651 | ) |
||
| 652 | ); |
||
| 653 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
| 654 | $unassignableGroups[] = $row['id_group']; |
||
| 655 | $smcFunc['db_free_result']($request); |
||
| 656 | |||
| 657 | if (in_array($regOptions['register_vars']['id_group'], $unassignableGroups)) |
||
| 658 | $regOptions['register_vars']['id_group'] = 0; |
||
| 659 | } |
||
| 660 | |||
| 661 | // Integrate optional member settings to be set. |
||
| 662 | if (!empty($regOptions['extra_register_vars'])) |
||
| 663 | foreach ($regOptions['extra_register_vars'] as $var => $value) |
||
| 664 | $regOptions['register_vars'][$var] = $value; |
||
| 665 | |||
| 666 | // Integrate optional user theme options to be set. |
||
| 667 | $theme_vars = array(); |
||
| 668 | if (!empty($regOptions['theme_vars'])) |
||
| 669 | foreach ($regOptions['theme_vars'] as $var => $value) |
||
| 670 | $theme_vars[$var] = $value; |
||
| 671 | |||
| 672 | // Right, now let's prepare for insertion. |
||
| 673 | $knownInts = array( |
||
| 674 | 'date_registered', 'posts', 'id_group', 'last_login', 'instant_messages', 'unread_messages', |
||
| 675 | 'new_pm', 'pm_prefs', 'show_online', |
||
| 676 | 'id_theme', 'is_activated', 'id_msg_last_visit', 'id_post_group', 'total_time_logged_in', 'warning', |
||
| 677 | ); |
||
| 678 | $knownFloats = array( |
||
| 679 | 'time_offset', |
||
| 680 | ); |
||
| 681 | $knownInets = array( |
||
| 682 | 'member_ip', 'member_ip2', |
||
| 683 | ); |
||
| 684 | |||
| 685 | // Call an optional function to validate the users' input. |
||
| 686 | call_integration_hook('integrate_register', array(&$regOptions, &$theme_vars, &$knownInts, &$knownFloats)); |
||
| 687 | |||
| 688 | $column_names = array(); |
||
| 689 | $values = array(); |
||
| 690 | foreach ($regOptions['register_vars'] as $var => $val) |
||
| 691 | { |
||
| 692 | $type = 'string'; |
||
| 693 | if (in_array($var, $knownInts)) |
||
| 694 | $type = 'int'; |
||
| 695 | elseif (in_array($var, $knownFloats)) |
||
| 696 | $type = 'float'; |
||
| 697 | elseif (in_array($var, $knownInets)) |
||
| 698 | $type = 'inet'; |
||
| 699 | elseif ($var == 'birthdate') |
||
| 700 | $type = 'date'; |
||
| 701 | |||
| 702 | $column_names[$var] = $type; |
||
| 703 | $values[$var] = $val; |
||
| 704 | } |
||
| 705 | |||
| 706 | // Register them into the database. |
||
| 707 | $memberID = $smcFunc['db_insert']('', |
||
| 708 | '{db_prefix}members', |
||
| 709 | $column_names, |
||
| 710 | $values, |
||
| 711 | array('id_member'), |
||
| 712 | 1 |
||
| 713 | ); |
||
| 714 | |||
| 715 | // Call an optional function as notification of registration. |
||
| 716 | call_integration_hook('integrate_post_register', array(&$regOptions, &$theme_vars, &$memberID)); |
||
| 717 | |||
| 718 | // Update the number of members and latest member's info - and pass the name, but remove the 's. |
||
| 719 | if ($regOptions['register_vars']['is_activated'] == 1) |
||
| 720 | updateStats('member', $memberID, $regOptions['register_vars']['real_name']); |
||
| 721 | else |
||
| 722 | updateStats('member'); |
||
| 723 | |||
| 724 | // Theme variables too? |
||
| 725 | if (!empty($theme_vars)) |
||
| 726 | { |
||
| 727 | $inserts = array(); |
||
| 728 | foreach ($theme_vars as $var => $val) |
||
| 729 | $inserts[] = array($memberID, $var, $val); |
||
| 730 | $smcFunc['db_insert']('insert', |
||
| 731 | '{db_prefix}themes', |
||
| 732 | array('id_member' => 'int', 'variable' => 'string-255', 'value' => 'string-65534'), |
||
| 733 | $inserts, |
||
| 734 | array('id_member', 'variable') |
||
| 735 | ); |
||
| 736 | } |
||
| 737 | |||
| 738 | // If it's enabled, increase the registrations for today. |
||
| 739 | trackStats(array('registers' => '+')); |
||
| 740 | |||
| 741 | // Administrative registrations are a bit different... |
||
| 742 | if ($regOptions['interface'] == 'admin') |
||
| 743 | { |
||
| 744 | if ($regOptions['require'] == 'activation') |
||
| 745 | $email_message = 'admin_register_activate'; |
||
| 746 | elseif (!empty($regOptions['send_welcome_email'])) |
||
| 747 | $email_message = 'admin_register_immediate'; |
||
| 748 | |||
| 749 | if (isset($email_message)) |
||
| 750 | { |
||
| 751 | $replacements = array( |
||
| 752 | 'REALNAME' => $regOptions['register_vars']['real_name'], |
||
| 753 | 'USERNAME' => $regOptions['username'], |
||
| 754 | 'PASSWORD' => $regOptions['password'], |
||
| 755 | 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder', |
||
| 756 | 'ACTIVATIONLINK' => $scripturl . '?action=activate;u=' . $memberID . ';code=' . $validation_code, |
||
| 757 | 'ACTIVATIONLINKWITHOUTCODE' => $scripturl . '?action=activate;u=' . $memberID, |
||
| 758 | 'ACTIVATIONCODE' => $validation_code, |
||
| 759 | ); |
||
| 760 | |||
| 761 | $emaildata = loadEmailTemplate($email_message, $replacements); |
||
| 762 | |||
| 763 | sendmail($regOptions['email'], $emaildata['subject'], $emaildata['body'], null, $email_message . $memberID, $emaildata['is_html'], 0); |
||
| 764 | } |
||
| 765 | |||
| 766 | // All admins are finished here. |
||
| 767 | return $memberID; |
||
| 768 | } |
||
| 769 | |||
| 770 | // Can post straight away - welcome them to your fantastic community... |
||
| 771 | if ($regOptions['require'] == 'nothing') |
||
| 772 | { |
||
| 773 | if (!empty($regOptions['send_welcome_email'])) |
||
| 774 | { |
||
| 775 | $replacements = array( |
||
| 776 | 'REALNAME' => $regOptions['register_vars']['real_name'], |
||
| 777 | 'USERNAME' => $regOptions['username'], |
||
| 778 | 'PASSWORD' => $regOptions['password'], |
||
| 779 | 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder', |
||
| 780 | ); |
||
| 781 | $emaildata = loadEmailTemplate('register_immediate', $replacements); |
||
| 782 | sendmail($regOptions['email'], $emaildata['subject'], $emaildata['body'], null, 'register', $emaildata['is_html'], 0); |
||
| 783 | } |
||
| 784 | |||
| 785 | // Send admin their notification. |
||
| 786 | adminNotify('standard', $memberID, $regOptions['username']); |
||
| 787 | } |
||
| 788 | // Need to activate their account - or fall under COPPA. |
||
| 789 | elseif ($regOptions['require'] == 'activation' || $regOptions['require'] == 'coppa') |
||
| 790 | { |
||
| 791 | $replacements = array( |
||
| 792 | 'REALNAME' => $regOptions['register_vars']['real_name'], |
||
| 793 | 'USERNAME' => $regOptions['username'], |
||
| 794 | 'PASSWORD' => $regOptions['password'], |
||
| 795 | 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder', |
||
| 796 | ); |
||
| 797 | |||
| 798 | if ($regOptions['require'] == 'activation') |
||
| 799 | $replacements += array( |
||
| 800 | 'ACTIVATIONLINK' => $scripturl . '?action=activate;u=' . $memberID . ';code=' . $validation_code, |
||
| 801 | 'ACTIVATIONLINKWITHOUTCODE' => $scripturl . '?action=activate;u=' . $memberID, |
||
| 802 | 'ACTIVATIONCODE' => $validation_code, |
||
| 803 | ); |
||
| 804 | else |
||
| 805 | $replacements += array( |
||
| 806 | 'COPPALINK' => $scripturl . '?action=coppa;u=' . $memberID, |
||
| 807 | ); |
||
| 808 | |||
| 809 | $emaildata = loadEmailTemplate('register_' . ($regOptions['require'] == 'activation' ? 'activate' : 'coppa'), $replacements); |
||
| 810 | |||
| 811 | sendmail($regOptions['email'], $emaildata['subject'], $emaildata['body'], null, 'reg_' . $regOptions['require'] . $memberID, $emaildata['is_html'], 0); |
||
| 812 | } |
||
| 813 | // Must be awaiting approval. |
||
| 814 | else |
||
| 815 | { |
||
| 816 | $replacements = array( |
||
| 817 | 'REALNAME' => $regOptions['register_vars']['real_name'], |
||
| 818 | 'USERNAME' => $regOptions['username'], |
||
| 819 | 'PASSWORD' => $regOptions['password'], |
||
| 820 | 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder', |
||
| 821 | ); |
||
| 822 | |||
| 823 | $emaildata = loadEmailTemplate('register_pending', $replacements); |
||
| 824 | |||
| 825 | sendmail($regOptions['email'], $emaildata['subject'], $emaildata['body'], null, 'reg_pending', $emaildata['is_html'], 0); |
||
| 826 | |||
| 827 | // Admin gets informed here... |
||
| 828 | adminNotify('approval', $memberID, $regOptions['username']); |
||
| 829 | } |
||
| 830 | |||
| 831 | // Okay, they're for sure registered... make sure the session is aware of this for security. (Just married :P!) |
||
| 832 | $_SESSION['just_registered'] = 1; |
||
| 833 | |||
| 834 | // If they are for sure registered, let other people to know about it |
||
| 835 | call_integration_hook('integrate_register_after', array($regOptions, $memberID)); |
||
| 836 | |||
| 837 | return $memberID; |
||
| 838 | } |
||
| 839 | |||
| 840 | /** |
||
| 841 | * Check if a name is in the reserved words list. |
||
| 842 | * (name, current member id, name/username?.) |
||
| 843 | * - checks if name is a reserved name or username. |
||
| 844 | * - if is_name is false, the name is assumed to be a username. |
||
| 845 | * - the id_member variable is used to ignore duplicate matches with the |
||
| 846 | * current member. |
||
| 847 | * |
||
| 848 | * @param string $name The name to check |
||
| 849 | * @param int $current_ID_MEMBER The ID of the current member (to avoid false positives with the current member) |
||
| 850 | * @param bool $is_name Whether we're checking against reserved names or just usernames |
||
| 851 | * @param bool $fatal Whether to die with a fatal error if the name is reserved |
||
| 852 | * @return bool|void False if name is not reserved, otherwise true if $fatal is false or dies with a fatal_lang_error if $fatal is true |
||
| 853 | */ |
||
| 854 | function isReservedName($name, $current_ID_MEMBER = 0, $is_name = true, $fatal = true) |
||
| 855 | { |
||
| 856 | global $modSettings, $smcFunc; |
||
| 857 | |||
| 858 | $name = preg_replace_callback('~(&#(\d{1,7}|x[0-9a-fA-F]{1,6});)~', 'replaceEntities__callback', $name); |
||
| 859 | $checkName = $smcFunc['strtolower']($name); |
||
| 860 | |||
| 861 | // Administrators are never restricted ;). |
||
| 862 | if (!allowedTo('moderate_forum') && ((!empty($modSettings['reserveName']) && $is_name) || !empty($modSettings['reserveUser']) && !$is_name)) |
||
| 863 | { |
||
| 864 | $reservedNames = explode("\n", $modSettings['reserveNames']); |
||
| 865 | // Case sensitive check? |
||
| 866 | $checkMe = empty($modSettings['reserveCase']) ? $checkName : $name; |
||
| 867 | |||
| 868 | // Check each name in the list... |
||
| 869 | foreach ($reservedNames as $reserved) |
||
| 870 | { |
||
| 871 | if ($reserved == '') |
||
| 872 | continue; |
||
| 873 | |||
| 874 | // The admin might've used entities too, level the playing field. |
||
| 875 | $reservedCheck = preg_replace('~(&#(\d{1,7}|x[0-9a-fA-F]{1,6});)~', 'replaceEntities__callback', $reserved); |
||
| 876 | |||
| 877 | // Case sensitive name? |
||
| 878 | if (empty($modSettings['reserveCase'])) |
||
| 879 | $reservedCheck = $smcFunc['strtolower']($reservedCheck); |
||
| 880 | |||
| 881 | // If it's not just entire word, check for it in there somewhere... |
||
| 882 | if ($checkMe == $reservedCheck || ($smcFunc['strpos']($checkMe, $reservedCheck) !== false && empty($modSettings['reserveWord']))) |
||
| 883 | if ($fatal) |
||
| 884 | fatal_lang_error('username_reserved', 'password', array($reserved)); |
||
| 885 | else |
||
| 886 | return true; |
||
| 887 | } |
||
| 888 | |||
| 889 | $censor_name = $name; |
||
| 890 | if (censorText($censor_name) != $name) |
||
| 891 | if ($fatal) |
||
| 892 | fatal_lang_error('name_censored', 'password', array($name)); |
||
| 893 | else |
||
| 894 | return true; |
||
| 895 | } |
||
| 896 | |||
| 897 | // Characters we just shouldn't allow, regardless. |
||
| 898 | foreach (array('*') as $char) |
||
| 899 | if (strpos($checkName, $char) !== false) |
||
| 900 | if ($fatal) |
||
| 901 | fatal_lang_error('username_reserved', 'password', array($char)); |
||
| 902 | else |
||
| 903 | return true; |
||
| 904 | |||
| 905 | // Get rid of any SQL parts of the reserved name... |
||
| 906 | $checkName = strtr($name, array('_' => '\\_', '%' => '\\%')); |
||
| 907 | |||
| 908 | //when we got no wildcard we can use equal -> fast |
||
| 909 | $operator = (strpos($checkName, '%') || strpos($checkName, '_') ? 'LIKE' : '='); |
||
| 910 | |||
| 911 | // Make sure they don't want someone else's name. |
||
| 912 | $request = $smcFunc['db_query']('', ' |
||
| 913 | SELECT id_member |
||
| 914 | FROM {db_prefix}members |
||
| 915 | WHERE ' . (empty($current_ID_MEMBER) ? '' : 'id_member != {int:current_member} |
||
| 916 | AND ') . '({raw:real_name} {raw:operator} LOWER({string:check_name}) OR {raw:member_name} {raw:operator} LOWER({string:check_name})) |
||
| 917 | LIMIT 1', |
||
| 918 | array( |
||
| 919 | 'real_name' => $smcFunc['db_case_sensitive'] ? 'LOWER(real_name)' : 'real_name', |
||
| 920 | 'member_name' => $smcFunc['db_case_sensitive'] ? 'LOWER(member_name)' : 'member_name', |
||
| 921 | 'current_member' => $current_ID_MEMBER, |
||
| 922 | 'check_name' => $checkName, |
||
| 923 | 'operator' => $operator, |
||
| 924 | ) |
||
| 925 | ); |
||
| 926 | if ($smcFunc['db_num_rows']($request) > 0) |
||
| 927 | { |
||
| 928 | $smcFunc['db_free_result']($request); |
||
| 929 | return true; |
||
| 930 | } |
||
| 931 | |||
| 932 | // Does name case insensitive match a member group name? |
||
| 933 | $request = $smcFunc['db_query']('', ' |
||
| 934 | SELECT id_group |
||
| 935 | FROM {db_prefix}membergroups |
||
| 936 | WHERE {raw:group_name} LIKE {string:check_name} |
||
| 937 | LIMIT 1', |
||
| 938 | array( |
||
| 939 | 'group_name' => $smcFunc['db_case_sensitive'] ? 'LOWER(group_name)' : 'group_name', |
||
| 940 | 'check_name' => $checkName, |
||
| 941 | ) |
||
| 942 | ); |
||
| 943 | if ($smcFunc['db_num_rows']($request) > 0) |
||
| 944 | { |
||
| 945 | $smcFunc['db_free_result']($request); |
||
| 946 | return true; |
||
| 947 | } |
||
| 948 | |||
| 949 | // Okay, they passed. |
||
| 950 | $is_reserved = false; |
||
| 951 | |||
| 952 | // Maybe a mod wants to perform further checks? |
||
| 953 | call_integration_hook('integrate_check_name', array($checkName, &$is_reserved, $current_ID_MEMBER, $is_name)); |
||
| 954 | |||
| 955 | return $is_reserved; |
||
| 956 | } |
||
| 957 | |||
| 958 | // Get a list of groups that have a given permission (on a given board). |
||
| 959 | /** |
||
| 960 | * Retrieves a list of membergroups that are allowed to do the given |
||
| 961 | * permission. (on the given board) |
||
| 962 | * If board_id is not null, a board permission is assumed. |
||
| 963 | * The function takes different permission settings into account. |
||
| 964 | * |
||
| 965 | * @param string $permission The permission to check |
||
| 966 | * @param int $board_id = null If set, checks permissions for the specified board |
||
| 967 | * @return array An array containing two arrays - 'allowed', which has which groups are allowed to do it and 'denied' which has the groups that are denied |
||
| 968 | */ |
||
| 969 | function groupsAllowedTo($permission, $board_id = null) |
||
| 970 | { |
||
| 971 | global $board_info, $smcFunc; |
||
| 972 | |||
| 973 | // Admins are allowed to do anything. |
||
| 974 | $member_groups = array( |
||
| 975 | 'allowed' => array(1), |
||
| 976 | 'denied' => array(), |
||
| 977 | ); |
||
| 978 | |||
| 979 | // Assume we're dealing with regular permissions (like profile_view). |
||
| 980 | if ($board_id === null) |
||
| 981 | { |
||
| 982 | $request = $smcFunc['db_query']('', ' |
||
| 983 | SELECT id_group, add_deny |
||
| 984 | FROM {db_prefix}permissions |
||
| 985 | WHERE permission = {string:permission}', |
||
| 986 | array( |
||
| 987 | 'permission' => $permission, |
||
| 988 | ) |
||
| 989 | ); |
||
| 990 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
| 991 | $member_groups[$row['add_deny'] === '1' ? 'allowed' : 'denied'][] = $row['id_group']; |
||
| 992 | $smcFunc['db_free_result']($request); |
||
| 993 | } |
||
| 994 | |||
| 995 | // Otherwise it's time to look at the board. |
||
| 996 | else |
||
| 997 | { |
||
| 998 | // First get the profile of the given board. |
||
| 999 | if (isset($board_info['id']) && $board_info['id'] == $board_id) |
||
| 1000 | $profile_id = $board_info['profile']; |
||
| 1001 | elseif ($board_id !== 0) |
||
| 1002 | { |
||
| 1003 | $request = $smcFunc['db_query']('', ' |
||
| 1004 | SELECT id_profile |
||
| 1005 | FROM {db_prefix}boards |
||
| 1006 | WHERE id_board = {int:id_board} |
||
| 1007 | LIMIT 1', |
||
| 1008 | array( |
||
| 1009 | 'id_board' => $board_id, |
||
| 1010 | ) |
||
| 1011 | ); |
||
| 1012 | if ($smcFunc['db_num_rows']($request) == 0) |
||
| 1013 | fatal_lang_error('no_board'); |
||
| 1014 | list ($profile_id) = $smcFunc['db_fetch_row']($request); |
||
| 1015 | $smcFunc['db_free_result']($request); |
||
| 1016 | } |
||
| 1017 | else |
||
| 1018 | $profile_id = 1; |
||
| 1019 | |||
| 1020 | $request = $smcFunc['db_query']('', ' |
||
| 1021 | SELECT bp.id_group, bp.add_deny |
||
| 1022 | FROM {db_prefix}board_permissions AS bp |
||
| 1023 | WHERE bp.permission = {string:permission} |
||
| 1024 | AND bp.id_profile = {int:profile_id}', |
||
| 1025 | array( |
||
| 1026 | 'profile_id' => $profile_id, |
||
| 1027 | 'permission' => $permission, |
||
| 1028 | ) |
||
| 1029 | ); |
||
| 1030 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
| 1031 | $member_groups[$row['add_deny'] === '1' ? 'allowed' : 'denied'][] = $row['id_group']; |
||
| 1032 | $smcFunc['db_free_result']($request); |
||
| 1033 | |||
| 1034 | $moderator_groups = array(); |
||
| 1035 | |||
| 1036 | // "Inherit" any moderator permissions as needed |
||
| 1037 | if (isset($board_info['moderator_groups'])) |
||
| 1038 | { |
||
| 1039 | $moderator_groups = array_keys($board_info['moderator_groups']); |
||
| 1040 | } |
||
| 1041 | elseif ($board_id !== 0) |
||
| 1042 | { |
||
| 1043 | // Get the groups that can moderate this board |
||
| 1044 | $request = $smcFunc['db_query']('', ' |
||
| 1045 | SELECT id_group |
||
| 1046 | FROM {db_prefix}moderator_groups |
||
| 1047 | WHERE id_board = {int:board_id}', |
||
| 1048 | array( |
||
| 1049 | 'board_id' => $board_id, |
||
| 1050 | ) |
||
| 1051 | ); |
||
| 1052 | |||
| 1053 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
| 1054 | { |
||
| 1055 | $moderator_groups[] = $row['id_group']; |
||
| 1056 | } |
||
| 1057 | |||
| 1058 | $smcFunc['db_free_result']($request); |
||
| 1059 | } |
||
| 1060 | |||
| 1061 | // "Inherit" any additional permissions from the "Moderators" group |
||
| 1062 | foreach ($moderator_groups as $mod_group) |
||
| 1063 | { |
||
| 1064 | // If they're not specifically allowed, but the moderator group is, then allow it |
||
| 1065 | if (in_array(3, $member_groups['allowed']) && !in_array($mod_group, $member_groups['allowed'])) |
||
| 1066 | { |
||
| 1067 | $member_groups['allowed'][] = $mod_group; |
||
| 1068 | } |
||
| 1069 | |||
| 1070 | // They're not denied, but the moderator group is, so deny it |
||
| 1071 | if (in_array(3, $member_groups['denied']) && !in_array($mod_group, $member_groups['denied'])) |
||
| 1072 | { |
||
| 1073 | $member_groups['denied'][] = $mod_group; |
||
| 1074 | } |
||
| 1075 | } |
||
| 1076 | } |
||
| 1077 | |||
| 1078 | // Denied is never allowed. |
||
| 1079 | $member_groups['allowed'] = array_diff($member_groups['allowed'], $member_groups['denied']); |
||
| 1080 | |||
| 1081 | return $member_groups; |
||
| 1082 | } |
||
| 1083 | |||
| 1084 | /** |
||
| 1085 | * Retrieves a list of members that have a given permission |
||
| 1086 | * (on a given board). |
||
| 1087 | * If board_id is not null, a board permission is assumed. |
||
| 1088 | * Takes different permission settings into account. |
||
| 1089 | * Takes possible moderators (on board 'board_id') into account. |
||
| 1090 | * |
||
| 1091 | * @param string $permission The permission to check |
||
| 1092 | * @param int $board_id If set, checks permission for that specific board |
||
| 1093 | * @return array An array containing the IDs of the members having that permission |
||
| 1094 | */ |
||
| 1095 | function membersAllowedTo($permission, $board_id = null) |
||
| 1096 | { |
||
| 1097 | global $smcFunc; |
||
| 1098 | |||
| 1099 | $member_groups = groupsAllowedTo($permission, $board_id); |
||
| 1100 | |||
| 1101 | $all_groups = array_merge($member_groups['allowed'], $member_groups['denied']); |
||
| 1102 | |||
| 1103 | $include_moderators = in_array(3, $member_groups['allowed']) && $board_id !== null; |
||
| 1104 | $member_groups['allowed'] = array_diff($member_groups['allowed'], array(3)); |
||
| 1105 | |||
| 1106 | $exclude_moderators = in_array(3, $member_groups['denied']) && $board_id !== null; |
||
| 1107 | $member_groups['denied'] = array_diff($member_groups['denied'], array(3)); |
||
| 1108 | |||
| 1109 | $request = $smcFunc['db_query']('', ' |
||
| 1110 | SELECT mem.id_member |
||
| 1111 | FROM {db_prefix}members AS mem' . ($include_moderators || $exclude_moderators ? ' |
||
| 1112 | LEFT JOIN {db_prefix}moderators AS mods ON (mods.id_member = mem.id_member AND mods.id_board = {int:board_id})' : '') . ' |
||
| 1113 | WHERE (' . ($include_moderators ? 'mods.id_member IS NOT NULL OR ' : '') . 'mem.id_group IN ({array_int:member_groups_allowed}) OR FIND_IN_SET({raw:member_group_allowed_implode}, mem.additional_groups) != 0 OR mem.id_post_group IN ({array_int:member_groups_allowed}))' . (empty($member_groups['denied']) ? '' : ' |
||
| 1114 | AND NOT (' . ($exclude_moderators ? 'mods.id_member IS NOT NULL OR ' : '') . 'mem.id_group IN ({array_int:member_groups_denied}) OR FIND_IN_SET({raw:member_group_denied_implode}, mem.additional_groups) != 0 OR mem.id_post_group IN ({array_int:member_groups_denied}))'), |
||
| 1115 | array( |
||
| 1116 | 'member_groups_allowed' => $member_groups['allowed'], |
||
| 1117 | 'member_groups_denied' => $member_groups['denied'], |
||
| 1118 | 'all_member_groups' => $all_groups, |
||
| 1119 | 'board_id' => $board_id, |
||
| 1120 | 'member_group_allowed_implode' => implode(', mem.additional_groups) != 0 OR FIND_IN_SET(', $member_groups['allowed']), |
||
| 1121 | 'member_group_denied_implode' => implode(', mem.additional_groups) != 0 OR FIND_IN_SET(', $member_groups['denied']), |
||
| 1122 | ) |
||
| 1123 | ); |
||
| 1124 | $members = array(); |
||
| 1125 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
| 1126 | $members[] = $row['id_member']; |
||
| 1127 | $smcFunc['db_free_result']($request); |
||
| 1128 | |||
| 1129 | return $members; |
||
| 1130 | } |
||
| 1131 | |||
| 1132 | /** |
||
| 1133 | * This function is used to reassociate members with relevant posts. |
||
| 1134 | * Reattribute guest posts to a specified member. |
||
| 1135 | * Does not check for any permissions. |
||
| 1136 | * If add_to_post_count is set, the member's post count is increased. |
||
| 1137 | * |
||
| 1138 | * @param int $memID The ID of the original poster |
||
| 1139 | * @param bool|string $email If set, should be the email of the poster |
||
| 1140 | * @param bool|string $membername If set, the membername of the poster |
||
| 1141 | * @param bool $post_count Whether to adjust post counts |
||
| 1142 | * @return array An array containing the number of messages, topics and reports updated |
||
| 1143 | */ |
||
| 1144 | function reattributePosts($memID, $email = false, $membername = false, $post_count = false) |
||
| 1145 | { |
||
| 1146 | global $smcFunc, $modSettings; |
||
| 1147 | |||
| 1148 | $updated = array( |
||
| 1149 | 'messages' => 0, |
||
| 1150 | 'topics' => 0, |
||
| 1151 | 'reports' => 0, |
||
| 1152 | ); |
||
| 1153 | |||
| 1154 | // Firstly, if email and username aren't passed find out the members email address and name. |
||
| 1155 | if ($email === false && $membername === false) |
||
| 1156 | { |
||
| 1157 | $request = $smcFunc['db_query']('', ' |
||
| 1158 | SELECT email_address, member_name |
||
| 1159 | FROM {db_prefix}members |
||
| 1160 | WHERE id_member = {int:memID} |
||
| 1161 | LIMIT 1', |
||
| 1162 | array( |
||
| 1163 | 'memID' => $memID, |
||
| 1164 | ) |
||
| 1165 | ); |
||
| 1166 | list ($email, $membername) = $smcFunc['db_fetch_row']($request); |
||
| 1167 | $smcFunc['db_free_result']($request); |
||
| 1168 | } |
||
| 1169 | |||
| 1170 | // If they want the post count restored then we need to do some research. |
||
| 1171 | if ($post_count) |
||
| 1172 | { |
||
| 1173 | $recycle_board = !empty($modSettings['recycle_enable']) && !empty($modSettings['recycle_board']) ? (int) $modSettings['recycle_board'] : 0; |
||
| 1174 | $request = $smcFunc['db_query']('', ' |
||
| 1175 | SELECT COUNT(*) |
||
| 1176 | FROM {db_prefix}messages AS m |
||
| 1177 | INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board AND b.count_posts = {int:count_posts}) |
||
| 1178 | WHERE m.id_member = {int:guest_id} |
||
| 1179 | AND m.approved = {int:is_approved}' . (!empty($recycle_board) ? ' |
||
| 1180 | AND m.id_board != {int:recycled_board}' : '') . (empty($email) ? '' : ' |
||
| 1181 | AND m.poster_email = {string:email_address}') . (empty($membername) ? '' : ' |
||
| 1182 | AND m.poster_name = {string:member_name}'), |
||
| 1183 | array( |
||
| 1184 | 'count_posts' => 0, |
||
| 1185 | 'guest_id' => 0, |
||
| 1186 | 'email_address' => $email, |
||
| 1187 | 'member_name' => $membername, |
||
| 1188 | 'is_approved' => 1, |
||
| 1189 | 'recycled_board' => $recycle_board, |
||
| 1190 | ) |
||
| 1191 | ); |
||
| 1192 | list ($messageCount) = $smcFunc['db_fetch_row']($request); |
||
| 1193 | $smcFunc['db_free_result']($request); |
||
| 1194 | |||
| 1195 | updateMemberData($memID, array('posts' => 'posts + ' . $messageCount)); |
||
| 1196 | } |
||
| 1197 | |||
| 1198 | $query_parts = array(); |
||
| 1199 | if (!empty($email)) |
||
| 1200 | $query_parts[] = 'poster_email = {string:email_address}'; |
||
| 1201 | if (!empty($membername)) |
||
| 1202 | $query_parts[] = 'poster_name = {string:member_name}'; |
||
| 1203 | $query = implode(' AND ', $query_parts); |
||
| 1204 | |||
| 1205 | // Finally, update the posts themselves! |
||
| 1206 | $smcFunc['db_query']('', ' |
||
| 1207 | UPDATE {db_prefix}messages |
||
| 1208 | SET id_member = {int:memID} |
||
| 1209 | WHERE ' . $query, |
||
| 1210 | array( |
||
| 1211 | 'memID' => $memID, |
||
| 1212 | 'email_address' => $email, |
||
| 1213 | 'member_name' => $membername, |
||
| 1214 | ) |
||
| 1215 | ); |
||
| 1216 | $updated['messages'] = $smcFunc['db_affected_rows'](); |
||
| 1217 | |||
| 1218 | // Did we update any messages? |
||
| 1219 | if ($updated['messages'] > 0) |
||
| 1220 | { |
||
| 1221 | // First, check for updated topics. |
||
| 1222 | $smcFunc['db_query']('', ' |
||
| 1223 | UPDATE {db_prefix}topics as t, {db_prefix}messages as m |
||
| 1224 | SET t.id_member_started = {int:memID} |
||
| 1225 | WHERE m.id_member = {int:memID} |
||
| 1226 | AND t.id_first_msg = m.id_msg', |
||
| 1227 | array( |
||
| 1228 | 'memID' => $memID, |
||
| 1229 | ) |
||
| 1230 | ); |
||
| 1231 | $updated['topics'] = $smcFunc['db_affected_rows'](); |
||
| 1232 | |||
| 1233 | // Second, check for updated reports. |
||
| 1234 | $smcFunc['db_query']('', ' |
||
| 1235 | UPDATE {db_prefix}log_reported AS lr, {db_prefix}messages AS m |
||
| 1236 | SET lr.id_member = {int:memID} |
||
| 1237 | WHERE lr.id_msg = m.id_msg |
||
| 1238 | AND m.id_member = {int:memID}', |
||
| 1239 | array( |
||
| 1240 | 'memID' => $memID, |
||
| 1241 | ) |
||
| 1242 | ); |
||
| 1243 | $updated['reports'] = $smcFunc['db_affected_rows'](); |
||
| 1244 | } |
||
| 1245 | |||
| 1246 | // Allow mods with their own post tables to reattribute posts as well :) |
||
| 1247 | call_integration_hook('integrate_reattribute_posts', array($memID, $email, $membername, $post_count, &$updated)); |
||
| 1248 | |||
| 1249 | return $updated; |
||
| 1250 | } |
||
| 1251 | |||
| 1252 | /** |
||
| 1253 | * This simple function adds/removes the passed user from the current users buddy list. |
||
| 1254 | * Requires profile_identity_own permission. |
||
| 1255 | * Called by ?action=buddy;u=x;session_id=y. |
||
| 1256 | * Redirects to ?action=profile;u=x. |
||
| 1257 | */ |
||
| 1258 | function BuddyListToggle() |
||
| 1259 | { |
||
| 1260 | global $user_info, $smcFunc; |
||
| 1261 | |||
| 1262 | checkSession('get'); |
||
| 1263 | |||
| 1264 | isAllowedTo('profile_extra_own'); |
||
| 1265 | is_not_guest(); |
||
| 1266 | |||
| 1267 | $userReceiver = (int) !empty($_REQUEST['u']) ? $_REQUEST['u'] : 0; |
||
| 1268 | |||
| 1269 | if (empty($userReceiver)) |
||
| 1270 | fatal_lang_error('no_access', false); |
||
| 1271 | |||
| 1272 | // Remove if it's already there... |
||
| 1273 | if (in_array($userReceiver, $user_info['buddies'])) |
||
| 1274 | $user_info['buddies'] = array_diff($user_info['buddies'], array($userReceiver)); |
||
| 1275 | |||
| 1276 | // ...or add if it's not and if it's not you. |
||
| 1277 | elseif ($user_info['id'] != $userReceiver) |
||
| 1278 | { |
||
| 1279 | $user_info['buddies'][] = $userReceiver; |
||
| 1280 | |||
| 1281 | // And add a nice alert. Don't abuse though! |
||
| 1282 | if ((cache_get_data('Buddy-sent-' . $user_info['id'] . '-' . $userReceiver, 86400)) == null) |
||
| 1283 | { |
||
| 1284 | $smcFunc['db_insert']('insert', |
||
| 1285 | '{db_prefix}background_tasks', |
||
| 1286 | array('task_file' => 'string', 'task_class' => 'string', 'task_data' => 'string', 'claimed_time' => 'int'), |
||
| 1287 | array('$sourcedir/tasks/Buddy-Notify.php', 'Buddy_Notify_Background', $smcFunc['json_encode'](array( |
||
| 1288 | 'receiver_id' => $userReceiver, |
||
| 1289 | 'id_member' => $user_info['id'], |
||
| 1290 | 'member_name' => $user_info['username'], |
||
| 1291 | 'time' => time(), |
||
| 1292 | )), 0), |
||
| 1293 | array('id_task') |
||
| 1294 | ); |
||
| 1295 | |||
| 1296 | // Store this in a cache entry to avoid creating multiple alerts. Give it a long life cycle. |
||
| 1297 | cache_put_data('Buddy-sent-' . $user_info['id'] . '-' . $userReceiver, '1', 86400); |
||
| 1298 | } |
||
| 1299 | } |
||
| 1300 | |||
| 1301 | // Update the settings. |
||
| 1302 | updateMemberData($user_info['id'], array('buddy_list' => implode(',', $user_info['buddies']))); |
||
| 1303 | |||
| 1304 | // Redirect back to the profile |
||
| 1305 | redirectexit('action=profile;u=' . $userReceiver); |
||
| 1306 | } |
||
| 1307 | |||
| 1308 | /** |
||
| 1309 | * Callback for createList(). |
||
| 1310 | * |
||
| 1311 | * @param int $start Which item to start with (for pagination purposes) |
||
| 1312 | * @param int $items_per_page How many items to show per page |
||
| 1313 | * @param string $sort An SQL query indicating how to sort the results |
||
| 1314 | * @param string $where An SQL query used to filter the results |
||
| 1315 | * @param array $where_params An array of parameters for $where |
||
| 1316 | * @param bool $get_duplicates Whether to get duplicates (used for the admin member list) |
||
| 1317 | * @return array An array of information for displaying the list of members |
||
| 1318 | */ |
||
| 1319 | function list_getMembers($start, $items_per_page, $sort, $where, $where_params = array(), $get_duplicates = false) |
||
| 1320 | { |
||
| 1321 | global $smcFunc; |
||
| 1322 | |||
| 1323 | $request = $smcFunc['db_query']('', ' |
||
| 1324 | SELECT |
||
| 1325 | mem.id_member, mem.member_name, mem.real_name, mem.email_address, mem.member_ip, mem.member_ip2, mem.last_login, |
||
| 1326 | mem.posts, mem.is_activated, mem.date_registered, mem.id_group, mem.additional_groups, mg.group_name |
||
| 1327 | FROM {db_prefix}members AS mem |
||
| 1328 | LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = mem.id_group) |
||
| 1329 | WHERE ' . ($where == '1' ? '1=1' : $where) . ' |
||
| 1330 | ORDER BY {raw:sort} |
||
| 1331 | LIMIT {int:start}, {int:per_page}', |
||
| 1332 | array_merge($where_params, array( |
||
| 1333 | 'sort' => $sort, |
||
| 1334 | 'start' => $start, |
||
| 1335 | 'per_page' => $items_per_page, |
||
| 1336 | )) |
||
| 1337 | ); |
||
| 1338 | |||
| 1339 | $members = array(); |
||
| 1340 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
| 1341 | { |
||
| 1342 | $row['member_ip'] = inet_dtop($row['member_ip']); |
||
| 1343 | $row['member_ip2'] = inet_dtop($row['member_ip2']); |
||
| 1344 | $members[] = $row; |
||
| 1345 | } |
||
| 1346 | $smcFunc['db_free_result']($request); |
||
| 1347 | |||
| 1348 | // If we want duplicates pass the members array off. |
||
| 1349 | if ($get_duplicates) |
||
| 1350 | populateDuplicateMembers($members); |
||
| 1351 | |||
| 1352 | return $members; |
||
| 1353 | } |
||
| 1354 | |||
| 1355 | /** |
||
| 1356 | * Callback for createList(). |
||
| 1357 | * |
||
| 1358 | * @param string $where An SQL query to filter the results |
||
| 1359 | * @param array $where_params An array of parameters for $where |
||
| 1360 | * @return int The number of members matching the given situation |
||
| 1361 | */ |
||
| 1362 | function list_getNumMembers($where, $where_params = array()) |
||
| 1363 | { |
||
| 1364 | global $smcFunc, $modSettings; |
||
| 1365 | |||
| 1366 | // We know how many members there are in total. |
||
| 1367 | if (empty($where) || $where == '1=1') |
||
| 1368 | $num_members = $modSettings['totalMembers']; |
||
| 1369 | |||
| 1370 | // The database knows the amount when there are extra conditions. |
||
| 1371 | else |
||
| 1372 | { |
||
| 1373 | $request = $smcFunc['db_query']('', ' |
||
| 1374 | SELECT COUNT(*) |
||
| 1375 | FROM {db_prefix}members AS mem |
||
| 1376 | WHERE ' . $where, |
||
| 1377 | array_merge($where_params, array( |
||
| 1378 | )) |
||
| 1379 | ); |
||
| 1380 | list ($num_members) = $smcFunc['db_fetch_row']($request); |
||
| 1381 | $smcFunc['db_free_result']($request); |
||
| 1382 | } |
||
| 1383 | |||
| 1384 | return $num_members; |
||
| 1385 | } |
||
| 1386 | |||
| 1387 | /** |
||
| 1388 | * Find potential duplicate registration members based on the same IP address |
||
| 1389 | * |
||
| 1390 | * @param array $members An array of members |
||
| 1391 | */ |
||
| 1392 | function populateDuplicateMembers(&$members) |
||
| 1393 | { |
||
| 1394 | global $smcFunc; |
||
| 1395 | |||
| 1396 | // This will hold all the ip addresses. |
||
| 1397 | $ips = array(); |
||
| 1398 | foreach ($members as $key => $member) |
||
| 1399 | { |
||
| 1400 | // Create the duplicate_members element. |
||
| 1401 | $members[$key]['duplicate_members'] = array(); |
||
| 1402 | |||
| 1403 | // Store the IPs. |
||
| 1404 | if (!empty($member['member_ip'])) |
||
| 1405 | $ips[] = $member['member_ip']; |
||
| 1406 | if (!empty($member['member_ip2'])) |
||
| 1407 | $ips[] = $member['member_ip2']; |
||
| 1408 | } |
||
| 1409 | |||
| 1410 | $ips = array_unique($ips); |
||
| 1411 | |||
| 1412 | if (empty($ips)) |
||
| 1413 | return false; |
||
| 1414 | |||
| 1415 | // Fetch all members with this IP address, we'll filter out the current ones in a sec. |
||
| 1416 | $request = $smcFunc['db_query']('', ' |
||
| 1417 | SELECT |
||
| 1418 | id_member, member_name, email_address, member_ip, member_ip2, is_activated |
||
| 1419 | FROM {db_prefix}members |
||
| 1420 | WHERE member_ip IN ({array_inet:ips}) |
||
| 1421 | OR member_ip2 IN ({array_inet:ips})', |
||
| 1422 | array( |
||
| 1423 | 'ips' => $ips, |
||
| 1424 | ) |
||
| 1425 | ); |
||
| 1426 | $duplicate_members = array(); |
||
| 1427 | $duplicate_ids = array(); |
||
| 1428 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
| 1429 | { |
||
| 1430 | //$duplicate_ids[] = $row['id_member']; |
||
| 1431 | $row['member_ip'] = inet_dtop($row['member_ip']); |
||
| 1432 | $row['member_ip2'] = inet_dtop($row['member_ip2']); |
||
| 1433 | |||
| 1434 | $member_context = array( |
||
| 1435 | 'id' => $row['id_member'], |
||
| 1436 | 'name' => $row['member_name'], |
||
| 1437 | 'email' => $row['email_address'], |
||
| 1438 | 'is_banned' => $row['is_activated'] > 10, |
||
| 1439 | 'ip' => $row['member_ip'], |
||
| 1440 | 'ip2' => $row['member_ip2'], |
||
| 1441 | ); |
||
| 1442 | |||
| 1443 | if (in_array($row['member_ip'], $ips)) |
||
| 1444 | $duplicate_members[$row['member_ip']][] = $member_context; |
||
| 1445 | if ($row['member_ip'] != $row['member_ip2'] && in_array($row['member_ip2'], $ips)) |
||
| 1446 | $duplicate_members[$row['member_ip2']][] = $member_context; |
||
| 1447 | } |
||
| 1448 | $smcFunc['db_free_result']($request); |
||
| 1449 | |||
| 1450 | // Also try to get a list of messages using these ips. |
||
| 1451 | $request = $smcFunc['db_query']('', ' |
||
| 1452 | SELECT |
||
| 1453 | m.poster_ip, mem.id_member, mem.member_name, mem.email_address, mem.is_activated |
||
| 1454 | FROM {db_prefix}messages AS m |
||
| 1455 | INNER JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member) |
||
| 1456 | WHERE m.id_member != 0 |
||
| 1457 | ' . (!empty($duplicate_ids) ? 'AND m.id_member NOT IN ({array_int:duplicate_ids})' : '') . ' |
||
| 1458 | AND m.poster_ip IN ({array_inet:ips})', |
||
| 1459 | array( |
||
| 1460 | 'duplicate_ids' => $duplicate_ids, |
||
| 1461 | 'ips' => $ips, |
||
| 1462 | ) |
||
| 1463 | ); |
||
| 1464 | |||
| 1465 | $had_ips = array(); |
||
| 1466 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
| 1467 | { |
||
| 1468 | $row['poster_ip'] = inet_dtop($row['poster_ip']); |
||
| 1469 | |||
| 1470 | // Don't collect lots of the same. |
||
| 1471 | if (isset($had_ips[$row['poster_ip']]) && in_array($row['id_member'], $had_ips[$row['poster_ip']])) |
||
| 1472 | continue; |
||
| 1473 | $had_ips[$row['poster_ip']][] = $row['id_member']; |
||
| 1474 | |||
| 1475 | $duplicate_members[$row['poster_ip']][] = array( |
||
| 1476 | 'id' => $row['id_member'], |
||
| 1477 | 'name' => $row['member_name'], |
||
| 1478 | 'email' => $row['email_address'], |
||
| 1479 | 'is_banned' => $row['is_activated'] > 10, |
||
| 1480 | 'ip' => $row['poster_ip'], |
||
| 1481 | 'ip2' => $row['poster_ip'], |
||
| 1482 | ); |
||
| 1483 | } |
||
| 1484 | $smcFunc['db_free_result']($request); |
||
| 1485 | |||
| 1486 | // Now we have all the duplicate members, stick them with their respective member in the list. |
||
| 1487 | if (!empty($duplicate_members)) |
||
| 1488 | foreach ($members as $key => $member) |
||
| 1489 | { |
||
| 1490 | if (isset($duplicate_members[$member['member_ip']])) |
||
| 1491 | $members[$key]['duplicate_members'] = $duplicate_members[$member['member_ip']]; |
||
| 1492 | if ($member['member_ip'] != $member['member_ip2'] && isset($duplicate_members[$member['member_ip2']])) |
||
| 1493 | $members[$key]['duplicate_members'] = array_merge($member['duplicate_members'], $duplicate_members[$member['member_ip2']]); |
||
| 1494 | |||
| 1495 | // Check we don't have lots of the same member. |
||
| 1496 | $member_track = array($member['id_member']); |
||
| 1497 | foreach ($members[$key]['duplicate_members'] as $duplicate_id_member => $duplicate_member) |
||
| 1498 | { |
||
| 1499 | if (in_array($duplicate_member['id'], $member_track)) |
||
| 1500 | { |
||
| 1501 | unset($members[$key]['duplicate_members'][$duplicate_id_member]); |
||
| 1502 | continue; |
||
| 1503 | } |
||
| 1504 | |||
| 1505 | $member_track[] = $duplicate_member['id']; |
||
| 1506 | } |
||
| 1507 | } |
||
| 1508 | } |
||
| 1509 | |||
| 1510 | /** |
||
| 1511 | * Generate a random validation code. |
||
| 1512 | * |
||
| 1513 | * @todo Err. Whatcha doin' here. |
||
| 1514 | * |
||
| 1515 | * @return string A random validation code |
||
| 1516 | */ |
||
| 1517 | function generateValidationCode() |
||
| 1518 | { |
||
| 1519 | global $smcFunc, $modSettings; |
||
| 1520 | |||
| 1521 | $request = $smcFunc['db_query']('get_random_number', ' |
||
| 1522 | SELECT RAND()', |
||
| 1523 | array( |
||
| 1524 | ) |
||
| 1525 | ); |
||
| 1526 | |||
| 1527 | list ($dbRand) = $smcFunc['db_fetch_row']($request); |
||
| 1528 | $smcFunc['db_free_result']($request); |
||
| 1529 | |||
| 1530 | return substr(preg_replace('/\W/', '', sha1(microtime() . $smcFunc['random_int']() . $dbRand . $modSettings['rand_seed'])), 0, 10); |
||
| 1531 | } |
||
| 1532 | |||
| 1533 | ?> |