[ Index ] |
|
Code source de Drupal 5.3 |
1 <?php 2 // $Id: user.module,v 1.745.2.20 2007/10/17 21:29:00 drumm Exp $ 3 4 /** 5 * @file 6 * Enables the user registration and login system. 7 */ 8 9 define('USERNAME_MAX_LENGTH', 60); 10 define('EMAIL_MAX_LENGTH', 64); 11 12 /** 13 * Invokes hook_user() in every module. 14 * 15 * We cannot use module_invoke() for this, because the arguments need to 16 * be passed by reference. 17 */ 18 function user_module_invoke($type, &$array, &$user, $category = NULL) { 19 foreach (module_list() as $module) { 20 $function = $module .'_user'; 21 if (function_exists($function)) { 22 $function($type, $array, $user, $category); 23 } 24 } 25 } 26 27 function user_external_load($authname) { 28 $result = db_query("SELECT uid FROM {authmap} WHERE authname = '%s'", $authname); 29 30 if ($user = db_fetch_array($result)) { 31 return user_load($user); 32 } 33 else { 34 return 0; 35 } 36 } 37 38 /** 39 * Fetch a user object. 40 * 41 * @param $array 42 * An associative array of attributes to search for in selecting the 43 * user, such as user name or e-mail address. 44 * 45 * @return 46 * A fully-loaded $user object upon successful user load or FALSE if user cannot be loaded. 47 */ 48 function user_load($array = array()) { 49 // Dynamically compose a SQL query: 50 $query = array(); 51 $params = array(); 52 53 foreach ($array as $key => $value) { 54 if ($key == 'uid' || $key == 'status') { 55 $query[] = "$key = %d"; 56 $params[] = $value; 57 } 58 else if ($key == 'pass') { 59 $query[] = "pass = '%s'"; 60 $params[] = md5($value); 61 } 62 else { 63 $query[]= "LOWER($key) = LOWER('%s')"; 64 $params[] = $value; 65 } 66 } 67 $result = db_query('SELECT * FROM {users} u WHERE '. implode(' AND ', $query), $params); 68 69 if (db_num_rows($result)) { 70 $user = db_fetch_object($result); 71 $user = drupal_unpack($user); 72 73 $user->roles = array(); 74 if ($user->uid) { 75 $user->roles[DRUPAL_AUTHENTICATED_RID] = 'authenticated user'; 76 } 77 else { 78 $user->roles[DRUPAL_ANONYMOUS_RID] = 'anonymous user'; 79 } 80 $result = db_query('SELECT r.rid, r.name FROM {role} r INNER JOIN {users_roles} ur ON ur.rid = r.rid WHERE ur.uid = %d', $user->uid); 81 while ($role = db_fetch_object($result)) { 82 $user->roles[$role->rid] = $role->name; 83 } 84 user_module_invoke('load', $array, $user); 85 } 86 else { 87 $user = FALSE; 88 } 89 90 return $user; 91 } 92 93 /** 94 * Save changes to a user account or add a new user. 95 * 96 * @param $account 97 * The $user object for the user to modify or add. If $user->uid is 98 * omitted, a new user will be added. 99 * 100 * @param $array 101 * An array of fields and values to save. For example array('name' => 'My name'); 102 * Setting a field to NULL deletes it from the data column. 103 * 104 * @param $category 105 * (optional) The category for storing profile information in. 106 */ 107 function user_save($account, $array = array(), $category = 'account') { 108 // Dynamically compose a SQL query: 109 $user_fields = user_fields(); 110 if ($account->uid) { 111 user_module_invoke('update', $array, $account, $category); 112 113 $data = unserialize(db_result(db_query('SELECT data FROM {users} WHERE uid = %d', $account->uid))); 114 foreach ($array as $key => $value) { 115 if ($key == 'pass' && !empty($value)) { 116 $query .= "$key = '%s', "; 117 $v[] = md5($value); 118 } 119 else if ((substr($key, 0, 4) !== 'auth') && ($key != 'pass')) { 120 if (in_array($key, $user_fields)) { 121 // Save standard fields 122 $query .= "$key = '%s', "; 123 $v[] = $value; 124 } 125 else if ($key != 'roles') { 126 // Roles is a special case: it used below. 127 if ($value === NULL) { 128 unset($data[$key]); 129 } 130 else { 131 $data[$key] = $value; 132 } 133 } 134 } 135 } 136 $query .= "data = '%s' "; 137 $v[] = serialize($data); 138 139 db_query("UPDATE {users} SET $query WHERE uid = %d", array_merge($v, array($account->uid))); 140 141 // Reload user roles if provided 142 if (is_array($array['roles'])) { 143 db_query('DELETE FROM {users_roles} WHERE uid = %d', $account->uid); 144 145 foreach (array_keys($array['roles']) as $rid) { 146 if (!in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) { 147 db_query('INSERT INTO {users_roles} (uid, rid) VALUES (%d, %d)', $account->uid, $rid); 148 } 149 } 150 } 151 152 // Delete a blocked user's sessions to kick them if they are online. 153 if (isset($array['status']) && $array['status'] == 0) { 154 sess_destroy_uid($account->uid); 155 } 156 157 // If the password changed, delete all open sessions and recreate 158 // the current one. 159 if (!empty($array['pass'])) { 160 sess_destroy_uid($account->uid); 161 sess_regenerate(); 162 } 163 164 // Refresh user object 165 $user = user_load(array('uid' => $account->uid)); 166 user_module_invoke('after_update', $array, $user, $category); 167 } 168 else { 169 $array['uid'] = db_next_id('{users}_uid'); 170 171 if (!isset($array['created'])) { // Allow 'created' to be set by hook_auth 172 $array['created'] = time(); 173 } 174 175 // Note, we wait with saving the data column to prevent module-handled 176 // fields from being saved there. We cannot invoke hook_user('insert') here 177 // because we don't have a fully initialized user object yet. 178 foreach ($array as $key => $value) { 179 switch ($key) { 180 case 'pass': 181 $fields[] = $key; 182 $values[] = md5($value); 183 $s[] = "'%s'"; 184 break; 185 case 'uid': case 'mode': case 'sort': 186 case 'threshold': case 'created': case 'access': 187 case 'login': case 'status': 188 $fields[] = $key; 189 $values[] = $value; 190 $s[] = "%d"; 191 break; 192 default: 193 if (substr($key, 0, 4) !== 'auth' && in_array($key, $user_fields)) { 194 $fields[] = $key; 195 $values[] = $value; 196 $s[] = "'%s'"; 197 } 198 break; 199 } 200 } 201 db_query('INSERT INTO {users} ('. implode(', ', $fields) .') VALUES ('. implode(', ', $s) .')', $values); 202 203 // Build the initial user object. 204 $user = user_load(array('uid' => $array['uid'])); 205 206 user_module_invoke('insert', $array, $user, $category); 207 208 // Build and save the serialized data field now 209 $data = array(); 210 foreach ($array as $key => $value) { 211 if ((substr($key, 0, 4) !== 'auth') && ($key != 'roles') && (!in_array($key, $user_fields)) && ($value !== NULL)) { 212 $data[$key] = $value; 213 } 214 } 215 db_query("UPDATE {users} SET data = '%s' WHERE uid = %d", serialize($data), $user->uid); 216 217 // Save user roles (delete just to be safe). 218 if (is_array($array['roles'])) { 219 db_query('DELETE FROM {users_roles} WHERE uid = %d', $array['uid']); 220 foreach (array_keys($array['roles']) as $rid) { 221 if (!in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) { 222 db_query('INSERT INTO {users_roles} (uid, rid) VALUES (%d, %d)', $array['uid'], $rid); 223 } 224 } 225 } 226 227 // Build the finished user object. 228 $user = user_load(array('uid' => $array['uid'])); 229 } 230 231 // Save distributed authentication mappings 232 $authmaps = array(); 233 foreach ($array as $key => $value) { 234 if (substr($key, 0, 4) == 'auth') { 235 $authmaps[$key] = $value; 236 } 237 } 238 if (sizeof($authmaps) > 0) { 239 user_set_authmaps($user, $authmaps); 240 } 241 242 return $user; 243 } 244 245 /** 246 * Verify the syntax of the given name. 247 */ 248 function user_validate_name($name) { 249 if (!strlen($name)) return t('You must enter a username.'); 250 if (substr($name, 0, 1) == ' ') return t('The username cannot begin with a space.'); 251 if (substr($name, -1) == ' ') return t('The username cannot end with a space.'); 252 if (strpos($name, ' ') !== FALSE) return t('The username cannot contain multiple spaces in a row.'); 253 if (ereg("[^\x80-\xF7 [:alnum:]@_.-]", $name)) return t('The username contains an illegal character.'); 254 if (preg_match('/[\x{80}-\x{A0}'. // Non-printable ISO-8859-1 + NBSP 255 '\x{AD}'. // Soft-hyphen 256 '\x{2000}-\x{200F}'. // Various space characters 257 '\x{2028}-\x{202F}'. // Bidirectional text overrides 258 '\x{205F}-\x{206F}'. // Various text hinting characters 259 '\x{FEFF}'. // Byte order mark 260 '\x{FF01}-\x{FF60}'. // Full-width latin 261 '\x{FFF9}-\x{FFFD}'. // Replacement characters 262 '\x{0}]/u', // NULL byte 263 $name)) { 264 return t('The username contains an illegal character.'); 265 } 266 if (strpos($name, '@') !== FALSE && !eregi('@([0-9a-z](-?[0-9a-z])*.)+[a-z]{2}([zmuvtg]|fo|me)?$', $name)) return t('The username is not a valid authentication ID.'); 267 if (strlen($name) > USERNAME_MAX_LENGTH) return t('The username %name is too long: it must be %max characters or less.', array('%name' => $name, '%max' => USERNAME_MAX_LENGTH)); 268 } 269 270 function user_validate_mail($mail) { 271 if (!$mail) return t('You must enter an e-mail address.'); 272 if (!valid_email_address($mail)) { 273 return t('The e-mail address %mail is not valid.', array('%mail' => $mail)); 274 } 275 } 276 277 function user_validate_picture($file, &$edit, $user) { 278 global $form_values; 279 // Initialize the picture: 280 $form_values['picture'] = $user->picture; 281 282 // Check that uploaded file is an image, with a maximum file size 283 // and maximum height/width. 284 $info = image_get_info($file->filepath); 285 list($maxwidth, $maxheight) = explode('x', variable_get('user_picture_dimensions', '85x85')); 286 287 if (!$info || !$info['extension']) { 288 form_set_error('picture_upload', t('The uploaded file was not an image.')); 289 } 290 else if (image_get_toolkit()) { 291 image_scale($file->filepath, $file->filepath, $maxwidth, $maxheight); 292 } 293 else if (filesize($file->filepath) > (variable_get('user_picture_file_size', '30') * 1000)) { 294 form_set_error('picture_upload', t('The uploaded image is too large; the maximum file size is %size kB.', array('%size' => variable_get('user_picture_file_size', '30')))); 295 } 296 else if ($info['width'] > $maxwidth || $info['height'] > $maxheight) { 297 form_set_error('picture_upload', t('The uploaded image is too large; the maximum dimensions are %dimensions pixels.', array('%dimensions' => variable_get('user_picture_dimensions', '85x85')))); 298 } 299 300 if (!form_get_errors()) { 301 if ($file = file_save_upload('picture_upload', variable_get('user_picture_path', 'pictures') .'/picture-'. $user->uid .'.'. $info['extension'], 1)) { 302 $form_values['picture'] = $file->filepath; 303 } 304 else { 305 form_set_error('picture_upload', t("Failed to upload the picture image; the %directory directory doesn't exist or is not writable.", array('%directory' => variable_get('user_picture_path', 'pictures')))); 306 } 307 } 308 } 309 310 /** 311 * Generate a random alphanumeric password. 312 */ 313 function user_password($length = 10) { 314 // This variable contains the list of allowable characters for the 315 // password. Note that the number 0 and the letter 'O' have been 316 // removed to avoid confusion between the two. The same is true 317 // of 'I', 1, and l. 318 $allowable_characters = 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789'; 319 320 // Zero-based count of characters in the allowable list: 321 $len = strlen($allowable_characters) - 1; 322 323 // Declare the password as a blank string. 324 $pass = ''; 325 326 // Loop the number of times specified by $length. 327 for ($i = 0; $i < $length; $i++) { 328 329 // Each iteration, pick a random character from the 330 // allowable string and append it to the password: 331 $pass .= $allowable_characters[mt_rand(0, $len)]; 332 } 333 334 return $pass; 335 } 336 337 /** 338 * Determine whether the user has a given privilege. 339 * 340 * @param $string 341 * The permission, such as "administer nodes", being checked for. 342 * @param $account 343 * (optional) The account to check, if not given use currently logged in user. 344 * 345 * @return 346 * boolean TRUE if the current user has the requested permission. 347 * 348 * All permission checks in Drupal should go through this function. This 349 * way, we guarantee consistent behavior, and ensure that the superuser 350 * can perform all actions. 351 */ 352 function user_access($string, $account = NULL) { 353 global $user; 354 static $perm = array(); 355 356 if (is_null($account)) { 357 $account = $user; 358 } 359 360 // User #1 has all privileges: 361 if ($account->uid == 1) { 362 return TRUE; 363 } 364 365 // To reduce the number of SQL queries, we cache the user's permissions 366 // in a static variable. 367 if (!isset($perm[$account->uid])) { 368 $rids = array_keys($account->roles); 369 $placeholders = implode(',', array_fill(0, count($rids), '%d')); 370 $result = db_query("SELECT DISTINCT(p.perm) FROM {role} r INNER JOIN {permission} p ON p.rid = r.rid WHERE r.rid IN ($placeholders)", $rids); 371 $perm[$account->uid] = ''; 372 while ($row = db_fetch_object($result)) { 373 $perm[$account->uid] .= "$row->perm, "; 374 } 375 } 376 377 if (isset($perm[$account->uid])) { 378 return strpos($perm[$account->uid], "$string, ") !== FALSE; 379 } 380 381 return FALSE; 382 } 383 384 /** 385 * Checks for usernames blocked by user administration 386 * 387 * @return boolean TRUE for blocked users, FALSE for active 388 */ 389 function user_is_blocked($name) { 390 $deny = db_fetch_object(db_query("SELECT name FROM {users} WHERE status = 0 AND name = LOWER('%s')", $name)); 391 392 return $deny; 393 } 394 395 function user_fields() { 396 static $fields; 397 398 if (!$fields) { 399 $result = db_query('SELECT * FROM {users} WHERE uid = 1'); 400 if (db_num_rows($result)) { 401 $fields = array_keys(db_fetch_array($result)); 402 } 403 else { 404 // Make sure we return the default fields at least 405 $fields = array('uid', 'name', 'pass', 'mail', 'picture', 'mode', 'sort', 'threshold', 'theme', 'signature', 'created', 'access', 'login', 'status', 'timezone', 'language', 'init', 'data'); 406 } 407 } 408 409 return $fields; 410 } 411 412 /** 413 * Implementation of hook_perm(). 414 */ 415 function user_perm() { 416 return array('administer access control', 'administer users', 'access user profiles', 'change own username'); 417 } 418 419 /** 420 * Implementation of hook_file_download(). 421 * 422 * Ensure that user pictures (avatars) are always downloadable. 423 */ 424 function user_file_download($file) { 425 if (strpos($file, variable_get('user_picture_path', 'pictures') .'/picture-') === 0) { 426 $info = image_get_info(file_create_path($file)); 427 return array('Content-type: '. $info['mime_type']); 428 } 429 } 430 431 /** 432 * Implementation of hook_search(). 433 */ 434 function user_search($op = 'search', $keys = NULL) { 435 switch ($op) { 436 case 'name': 437 if (user_access('access user profiles')) { 438 return t('Users'); 439 } 440 case 'search': 441 if (user_access('access user profiles')) { 442 $find = array(); 443 // Replace wildcards with MySQL/PostgreSQL wildcards. 444 $keys = preg_replace('!\*+!', '%', $keys); 445 $result = pager_query("SELECT name, uid FROM {users} WHERE LOWER(name) LIKE LOWER('%%%s%%')", 15, 0, NULL, $keys); 446 while ($account = db_fetch_object($result)) { 447 $find[] = array('title' => $account->name, 'link' => url('user/'. $account->uid, NULL, NULL, TRUE)); 448 } 449 return $find; 450 } 451 } 452 } 453 454 /** 455 * Implementation of hook_user(). 456 */ 457 function user_user($type, &$edit, &$user, $category = NULL) { 458 if ($type == 'view') { 459 $items['history'] = array('title' => t('Member for'), 460 'value' => format_interval(time() - $user->created), 461 'class' => 'member', 462 ); 463 464 return array(t('History') => $items); 465 } 466 if ($type == 'form' && $category == 'account') { 467 return user_edit_form(arg(1), $edit); 468 } 469 470 if ($type == 'validate' && $category == 'account') { 471 return _user_edit_validate(arg(1), $edit); 472 } 473 474 if ($type == 'submit' && $category == 'account') { 475 return _user_edit_submit(arg(1), $edit); 476 } 477 478 if ($type == 'categories') { 479 return array(array('name' => 'account', 'title' => t('Account settings'), 'weight' => 1)); 480 } 481 } 482 483 function user_login_block() { 484 $form = array( 485 '#action' => url($_GET['q'], drupal_get_destination()), 486 '#id' => 'user-login-form', 487 '#base' => 'user_login', 488 ); 489 $form['name'] = array('#type' => 'textfield', 490 '#title' => t('Username'), 491 '#maxlength' => USERNAME_MAX_LENGTH, 492 '#size' => 15, 493 '#required' => TRUE, 494 ); 495 $form['pass'] = array('#type' => 'password', 496 '#title' => t('Password'), 497 '#maxlength' => 60, 498 '#size' => 15, 499 '#required' => TRUE, 500 ); 501 $form['submit'] = array('#type' => 'submit', 502 '#value' => t('Log in'), 503 ); 504 $items = array(); 505 if (variable_get('user_register', 1)) { 506 $items[] = l(t('Create new account'), 'user/register', array('title' => t('Create a new user account.'))); 507 } 508 $items[] = l(t('Request new password'), 'user/password', array('title' => t('Request new password via e-mail.'))); 509 $form['links'] = array('#value' => theme('item_list', $items)); 510 return $form; 511 } 512 513 /** 514 * Implementation of hook_block(). 515 */ 516 function user_block($op = 'list', $delta = 0, $edit = array()) { 517 global $user; 518 519 if ($op == 'list') { 520 $blocks[0]['info'] = t('User login'); 521 $blocks[1]['info'] = t('Navigation'); 522 $blocks[2]['info'] = t('Who\'s new'); 523 $blocks[3]['info'] = t('Who\'s online'); 524 525 return $blocks; 526 } 527 else if ($op == 'configure' && $delta == 2) { 528 $form['user_block_whois_new_count'] = array( 529 '#type' => 'select', 530 '#title' => t('Number of users to display'), 531 '#default_value' => variable_get('user_block_whois_new_count', 5), 532 '#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)), 533 ); 534 return $form; 535 } 536 else if ($op == 'configure' && $delta == 3) { 537 $period = drupal_map_assoc(array(30, 60, 120, 180, 300, 600, 900, 1800, 2700, 3600, 5400, 7200, 10800, 21600, 43200, 86400), 'format_interval'); 538 $form['user_block_seconds_online'] = array('#type' => 'select', '#title' => t('User activity'), '#default_value' => variable_get('user_block_seconds_online', 900), '#options' => $period, '#description' => t('A user is considered online for this long after they have last viewed a page.')); 539 $form['user_block_max_list_count'] = array('#type' => 'select', '#title' => t('User list length'), '#default_value' => variable_get('user_block_max_list_count', 10), '#options' => drupal_map_assoc(array(0, 5, 10, 15, 20, 25, 30, 40, 50, 75, 100)), '#description' => t('Maximum number of currently online users to display.')); 540 541 return $form; 542 } 543 else if ($op == 'save' && $delta == 2) { 544 variable_set('user_block_whois_new_count', $edit['user_block_whois_new_count']); 545 } 546 else if ($op == 'save' && $delta == 3) { 547 variable_set('user_block_seconds_online', $edit['user_block_seconds_online']); 548 variable_set('user_block_max_list_count', $edit['user_block_max_list_count']); 549 } 550 else if ($op == 'view') { 551 $block = array(); 552 553 switch ($delta) { 554 case 0: 555 // For usability's sake, avoid showing two login forms on one page. 556 if (!$user->uid && !(arg(0) == 'user' && !is_numeric(arg(1)))) { 557 558 $block['subject'] = t('User login'); 559 $block['content'] = drupal_get_form('user_login_block'); 560 } 561 return $block; 562 563 case 1: 564 if ($menu = theme('menu_tree')) { 565 $block['subject'] = $user->uid ? check_plain($user->name) : t('Navigation'); 566 $block['content'] = $menu; 567 } 568 return $block; 569 570 case 2: 571 if (user_access('access content')) { 572 // Retrieve a list of new users who have subsequently accessed the site successfully. 573 $result = db_query_range('SELECT uid, name FROM {users} WHERE status != 0 AND access != 0 ORDER BY created DESC', 0, variable_get('user_block_whois_new_count', 5)); 574 while ($account = db_fetch_object($result)) { 575 $items[] = $account; 576 } 577 $output = theme('user_list', $items); 578 579 $block['subject'] = t('Who\'s new'); 580 $block['content'] = $output; 581 } 582 return $block; 583 584 case 3: 585 if (user_access('access content')) { 586 // Count users active within the defined period. 587 $interval = time() - variable_get('user_block_seconds_online', 900); 588 589 // Perform database queries to gather online user lists. We use s.timestamp 590 // rather than u.access because it is much faster. 591 $anonymous_count = sess_count($interval); 592 $authenticated_users = db_query('SELECT DISTINCT u.uid, u.name, s.timestamp FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.timestamp >= %d AND s.uid > 0 ORDER BY s.timestamp DESC', $interval); 593 $authenticated_count = db_num_rows($authenticated_users); 594 595 // Format the output with proper grammar. 596 if ($anonymous_count == 1 && $authenticated_count == 1) { 597 $output = t('There is currently %members and %visitors online.', array('%members' => format_plural($authenticated_count, '1 user', '@count users'), '%visitors' => format_plural($anonymous_count, '1 guest', '@count guests'))); 598 } 599 else { 600 $output = t('There are currently %members and %visitors online.', array('%members' => format_plural($authenticated_count, '1 user', '@count users'), '%visitors' => format_plural($anonymous_count, '1 guest', '@count guests'))); 601 } 602 603 // Display a list of currently online users. 604 $max_users = variable_get('user_block_max_list_count', 10); 605 if ($authenticated_count && $max_users) { 606 $items = array(); 607 608 while ($max_users-- && $account = db_fetch_object($authenticated_users)) { 609 $items[] = $account; 610 } 611 612 $output .= theme('user_list', $items, t('Online users')); 613 } 614 615 $block['subject'] = t('Who\'s online'); 616 $block['content'] = $output; 617 } 618 return $block; 619 } 620 } 621 } 622 623 function theme_user_picture($account) { 624 if (variable_get('user_pictures', 0)) { 625 if ($account->picture && file_exists($account->picture)) { 626 $picture = file_create_url($account->picture); 627 } 628 else if (variable_get('user_picture_default', '')) { 629 $picture = variable_get('user_picture_default', ''); 630 } 631 632 if (isset($picture)) { 633 $alt = t("@user's picture", array('@user' => $account->name ? $account->name : variable_get('anonymous', t('Anonymous')))); 634 $picture = theme('image', $picture, $alt, $alt, '', FALSE); 635 if (!empty($account->uid) && user_access('access user profiles')) { 636 $picture = l($picture, "user/$account->uid", array('title' => t('View user profile.')), NULL, NULL, FALSE, TRUE); 637 } 638 639 return "<div class=\"picture\">$picture</div>"; 640 } 641 } 642 } 643 644 /** 645 * Theme a user page 646 * @param $account the user object 647 * @param $fields a multidimensional array for the fields, in the form of array ( 648 * 'category1' => array(item_array1, item_array2), 'category2' => array(item_array3, 649 * .. etc.). Item arrays are formatted as array(array('title' => 'item title', 650 * 'value' => 'item value', 'class' => 'class-name'), ... etc.). Module names are incorporated 651 * into the CSS class. 652 * 653 * @ingroup themeable 654 */ 655 function theme_user_profile($account, $fields) { 656 $output = '<div class="profile">'; 657 $output .= theme('user_picture', $account); 658 foreach ($fields as $category => $items) { 659 if (strlen($category) > 0) { 660 $output .= '<h2 class="title">'. check_plain($category) .'</h2>'; 661 } 662 $output .= '<dl>'; 663 foreach ($items as $item) { 664 if (isset($item['title'])) { 665 $output .= '<dt class="'. $item['class'] .'">'. $item['title'] .'</dt>'; 666 } 667 $output .= '<dd class="'. $item['class'] .'">'. $item['value'] .'</dd>'; 668 } 669 $output .= '</dl>'; 670 } 671 $output .= '</div>'; 672 673 return $output; 674 } 675 676 /** 677 * Make a list of users. 678 * @param $items an array with user objects. Should contain at least the name and uid 679 * 680 * @ingroup themeable 681 */ 682 function theme_user_list($users, $title = NULL) { 683 if (!empty($users)) { 684 foreach ($users as $user) { 685 $items[] = theme('username', $user); 686 } 687 } 688 return theme('item_list', $items, $title); 689 } 690 691 /** 692 * Implementation of hook_menu(). 693 */ 694 function user_menu($may_cache) { 695 global $user; 696 697 $items = array(); 698 699 $admin_access = user_access('administer users'); 700 $access_access = user_access('administer access control'); 701 $view_access = user_access('access user profiles'); 702 703 if ($may_cache) { 704 $items[] = array('path' => 'user', 'title' => t('User account'), 705 'callback' => 'drupal_get_form', 'callback arguments' => array('user_login'), 706 'access' => !$user->uid, 'type' => MENU_CALLBACK); 707 708 $items[] = array('path' => 'user/autocomplete', 'title' => t('User autocomplete'), 709 'callback' => 'user_autocomplete', 'access' => $view_access, 'type' => MENU_CALLBACK); 710 711 // Registration and login pages. 712 $items[] = array('path' => 'user/login', 'title' => t('Log in'), 713 'callback' => 'drupal_get_form', 'callback arguments' => array('user_login'), 714 'access' => !$user->uid, 'type' => MENU_DEFAULT_LOCAL_TASK); 715 $items[] = array('path' => 'user/register', 'title' => t('Create new account'), 716 'callback' => 'drupal_get_form', 'callback arguments' => array('user_register'), 'access' => !$user->uid && variable_get('user_register', 1), 'type' => MENU_LOCAL_TASK); 717 $items[] = array('path' => 'user/password', 'title' => t('Request new password'), 718 'callback' => 'drupal_get_form', 'callback arguments' => array('user_pass'), 'access' => !$user->uid, 'type' => MENU_LOCAL_TASK); 719 $items[] = array('path' => 'user/reset', 'title' => t('Reset password'), 720 'callback' => 'drupal_get_form', 'callback arguments' => array('user_pass_reset'), 'access' => TRUE, 'type' => MENU_CALLBACK); 721 $items[] = array('path' => 'user/help', 'title' => t('Help'), 722 'callback' => 'user_help_page', 'type' => MENU_CALLBACK); 723 724 // Admin user pages 725 $items[] = array('path' => 'admin/user', 726 'title' => t('User management'), 727 'description' => t('Manage your site\'s users, groups and access to site features.'), 728 'position' => 'left', 729 'callback' => 'system_admin_menu_block_page', 730 'access' => user_access('administer site configuration'), 731 ); 732 $items[] = array('path' => 'admin/user/user', 'title' => t('Users'), 733 'description' => t('List, add, and edit users.'), 734 'callback' => 'user_admin', 'callback arguments' => array('list'), 'access' => $admin_access); 735 $items[] = array('path' => 'admin/user/user/list', 'title' => t('List'), 736 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10); 737 $items[] = array('path' => 'admin/user/user/create', 'title' => t('Add user'), 738 'callback' => 'user_admin', 'callback arguments' => array('create'), 'access' => $admin_access, 739 'type' => MENU_LOCAL_TASK); 740 $items[] = array('path' => 'admin/user/settings', 'title' => t('User settings'), 741 'description' => t('Configure default behavior of users, including registration requirements, e-mails, and user pictures.'), 742 'callback' => 'drupal_get_form', 'callback arguments' => array('user_admin_settings')); 743 744 // Admin access pages 745 $items[] = array('path' => 'admin/user/access', 'title' => t('Access control'), 746 'description' => t('Determine access to features by selecting permissions for roles.'), 747 'callback' => 'drupal_get_form', 'callback arguments' => array('user_admin_perm'), 'access' => $access_access); 748 $items[] = array('path' => 'admin/user/roles', 'title' => t('Roles'), 749 'description' => t('List, edit, or add user roles.'), 750 'callback' => 'drupal_get_form', 'callback arguments' => array('user_admin_new_role'), 'access' => $access_access, 751 'type' => MENU_NORMAL_ITEM); 752 $items[] = array('path' => 'admin/user/roles/edit', 'title' => t('Edit role'), 753 'callback' => 'drupal_get_form', 'callback arguments' => array('user_admin_role'), 'access' => $access_access, 754 'type' => MENU_CALLBACK); 755 $items[] = array('path' => 'admin/user/rules', 'title' => t('Access rules'), 756 'description' => t('List and create rules to disallow usernames, e-mail addresses, and IP addresses.'), 757 'callback' => 'user_admin_access', 'access' => $access_access); 758 $items[] = array('path' => 'admin/user/rules/list', 'title' => t('List'), 759 'access' => $access_access, 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10); 760 $items[] = array('path' => 'admin/user/rules/add', 'title' => t('Add rule'), 761 'callback' => 'user_admin_access_add', 'access' => $access_access, 762 'type' => MENU_LOCAL_TASK); 763 $items[] = array('path' => 'admin/user/rules/check', 'title' => t('Check rules'), 764 'callback' => 'user_admin_access_check', 'access' => $access_access, 765 'type' => MENU_LOCAL_TASK); 766 $items[] = array('path' => 'admin/user/rules/edit', 'title' => t('Edit rule'), 767 'callback' => 'user_admin_access_edit', 'access' => $access_access, 768 'type' => MENU_CALLBACK); 769 $items[] = array('path' => 'admin/user/rules/delete', 'title' => t('Delete rule'), 770 'callback' => 'drupal_get_form', 'callback arguments' => array('user_admin_access_delete_confirm'), 771 'access' => $access_access, 'type' => MENU_CALLBACK); 772 773 if (module_exists('search')) { 774 $items[] = array('path' => 'admin/user/search', 'title' => t('Search users'), 775 'description' => t('Search users by name.'), 776 'callback' => 'user_admin', 'callback arguments' => array('search'), 'access' => $admin_access, 777 'type' => MENU_NORMAL_ITEM); 778 } 779 780 // Your personal page 781 if ($user->uid) { 782 $items[] = array('path' => 'user/'. $user->uid, 'title' => t('My account'), 783 'callback' => 'user_view', 'callback arguments' => array(arg(1)), 'access' => TRUE, 784 'type' => MENU_DYNAMIC_ITEM); 785 } 786 787 $items[] = array('path' => 'logout', 'title' => t('Log out'), 788 'access' => $user->uid, 789 'callback' => 'user_logout', 790 'weight' => 10); 791 } 792 else { 793 // Add the CSS for this module. We put this in !$may_cache so it is only 794 // added once per request. 795 drupal_add_css(drupal_get_path('module', 'user') .'/user.css', 'module'); 796 if ($_GET['q'] == 'user' && $user->uid) { 797 // We want to make the current user's profile accessible without knowing 798 // their uid, so just linking to /user is enough. 799 drupal_goto('user/'. $user->uid); 800 } 801 802 if (arg(0) == 'user' && is_numeric(arg(1)) && arg(1) > 0) { 803 $account = user_load(array('uid' => arg(1))); 804 805 if ($user !== FALSE) { 806 // Always let a user view their own account 807 $view_access |= $user->uid == arg(1); 808 // Only admins can view blocked accounts 809 $view_access &= $account->status || $admin_access; 810 811 $items[] = array('path' => 'user/'. arg(1), 'title' => t('User'), 812 'type' => MENU_CALLBACK, 'callback' => 'user_view', 813 'callback arguments' => array(arg(1)), 'access' => $view_access); 814 815 $items[] = array('path' => 'user/'. arg(1) .'/view', 'title' => t('View'), 816 'access' => $view_access, 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10); 817 818 $items[] = array('path' => 'user/'. arg(1) .'/edit', 'title' => t('Edit'), 819 'callback' => 'drupal_get_form', 'callback arguments' => array('user_edit'), 820 'access' => $admin_access || $user->uid == arg(1), 'type' => MENU_LOCAL_TASK); 821 $items[] = array('path' => 'user/'. arg(1) .'/delete', 'title' => t('Delete'), 822 'callback' => 'user_edit', 'access' => $admin_access, 823 'type' => MENU_CALLBACK); 824 825 if (arg(2) == 'edit') { 826 if (($categories = _user_categories($account)) && (count($categories) > 1)) { 827 foreach ($categories as $key => $category) { 828 $items[] = array( 829 'path' => 'user/'. arg(1) .'/edit/'. $category['name'], 830 'title' => $category['title'], 831 'type' => $category['name'] == 'account' ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK, 832 'weight' => $category['weight'], 833 'access' => ($admin_access || $user->uid == arg(1))); 834 } 835 } 836 } 837 } 838 } 839 } 840 841 return $items; 842 } 843 844 /** 845 * Accepts an user object, $account, or a DA name and returns an associative 846 * array of modules and DA names. Called at external login. 847 */ 848 function user_get_authmaps($authname = NULL) { 849 $result = db_query("SELECT authname, module FROM {authmap} WHERE authname = '%s'", $authname); 850 if (db_num_rows($result) > 0) { 851 while ($authmap = db_fetch_object($result)) { 852 $authmaps[$authmap->module] = $authmap->authname; 853 } 854 return $authmaps; 855 } 856 else { 857 return 0; 858 } 859 } 860 861 function user_set_authmaps($account, $authmaps) { 862 foreach ($authmaps as $key => $value) { 863 $module = explode('_', $key, 2); 864 if ($value) { 865 db_query("UPDATE {authmap} SET authname = '%s' WHERE uid = %d AND module = '%s'", $value, $account->uid, $module[1]); 866 if (!db_affected_rows()) { 867 db_query("INSERT INTO {authmap} (authname, uid, module) VALUES ('%s', %d, '%s')", $value, $account->uid, $module[1]); 868 } 869 } 870 else { 871 db_query("DELETE FROM {authmap} WHERE uid = %d AND module = '%s'", $account->uid, $module[1]); 872 } 873 } 874 } 875 876 function user_auth_help_links() { 877 $links = array(); 878 foreach (module_list() as $module) { 879 if (module_hook($module, 'auth')) { 880 $links[] = l(module_invoke($module, 'info', 'name'), 'user/help', array(), NULL, $module); 881 } 882 } 883 return $links; 884 } 885 886 /*** User features *********************************************************/ 887 888 889 890 function user_login($msg = '') { 891 global $user; 892 893 // If we are already logged on, go to the user page instead. 894 if ($user->uid) { 895 drupal_goto('user/'. $user->uid); 896 } 897 898 // Display login form: 899 if ($msg) { 900 $form['message'] = array('#value' => '<p>'. check_plain($msg) .'</p>'); 901 } 902 $form['name'] = array('#type' => 'textfield', 903 '#title' => t('Username'), 904 '#size' => 60, 905 '#maxlength' => USERNAME_MAX_LENGTH, 906 '#required' => TRUE, 907 '#attributes' => array('tabindex' => '1'), 908 ); 909 if (variable_get('drupal_authentication_service', FALSE) && count(user_auth_help_links()) > 0) { 910 $form['name']['#description'] = t('Enter your @s username, or an ID from one of our affiliates: !a.', array('@s' => variable_get('site_name', 'Drupal'), '!a' => implode(', ', user_auth_help_links()))); 911 } 912 else { 913 $form['name']['#description'] = t('Enter your @s username.', array('@s' => variable_get('site_name', 'Drupal'))); 914 } 915 $form['pass'] = array('#type' => 'password', 916 '#title' => t('Password'), 917 '#description' => t('Enter the password that accompanies your username.'), 918 '#required' => TRUE, 919 '#attributes' => array('tabindex' => '2'), 920 ); 921 $form['submit'] = array('#type' => 'submit', '#value' => t('Log in'), '#weight' => 2, '#attributes' => array('tabindex' => '3')); 922 923 return $form; 924 } 925 926 function user_login_validate($form_id, $form_values) { 927 if ($form_values['name']) { 928 if (user_is_blocked($form_values['name'])) { 929 // blocked in user administration 930 form_set_error('name', t('The username %name has not been activated or is blocked.', array('%name' => $form_values['name']))); 931 } 932 else if (drupal_is_denied('user', $form_values['name'])) { 933 // denied by access controls 934 form_set_error('name', t('The name %name is a reserved username.', array('%name' => $form_values['name']))); 935 } 936 else if ($form_values['pass']) { 937 $user = user_authenticate($form_values['name'], trim($form_values['pass'])); 938 939 if (!$user->uid) { 940 form_set_error('name', t('Sorry, unrecognized username or password. <a href="@password">Have you forgotten your password?</a>', array('@password' => url('user/password')))); 941 watchdog('user', t('Login attempt failed for %user.', array('%user' => $form_values['name']))); 942 } 943 } 944 } 945 } 946 947 function user_login_submit($form_id, $form_values) { 948 global $user; 949 if ($user->uid) { 950 // To handle the edge case where this function is called during a 951 // bootstrap, check for the existence of t(). 952 if (function_exists('t')) { 953 $message = t('Session opened for %name.', array('%name' => $user->name)); 954 } 955 else { 956 $message = "Session opened for ". check_plain($user->name); 957 } 958 watchdog('user', $message); 959 960 // Update the user table timestamp noting user has logged in. 961 db_query("UPDATE {users} SET login = %d WHERE uid = %d", time(), $user->uid); 962 963 user_module_invoke('login', $form_values, $user); 964 965 sess_regenerate(); 966 return 'user/'. $user->uid; 967 } 968 } 969 970 function user_authenticate($name, $pass) { 971 global $user; 972 973 // Try to log in the user locally. Don't set $user unless successful. 974 if ($account = user_load(array('name' => $name, 'pass' => $pass, 'status' => 1))) { 975 $user = $account; 976 return $user; 977 } 978 979 // Strip name and server from ID: 980 if ($server = strrchr($name, '@')) { 981 $name = substr($name, 0, strlen($name) - strlen($server)); 982 $server = substr($server, 1); 983 } 984 985 // When possible, determine corresponding external auth source. Invoke 986 // source, and log in user if successful: 987 if ($server && ($result = user_get_authmaps("$name@$server"))) { 988 if (module_invoke(key($result), 'auth', $name, $pass, $server)) { 989 $user = user_external_load("$name@$server"); 990 watchdog('user', t('External load by %user using module %module.', array('%user' => $name .'@'. $server, '%module' => key($result)))); 991 } 992 } 993 994 // Try each external authentication source in series. Register user if 995 // successful. 996 else { 997 foreach (module_implements('auth') as $module) { 998 if (module_invoke($module, 'auth', $name, $pass, $server)) { 999 if ($server) { 1000 $name .= '@'. $server; 1001 } 1002 $user = user_load(array('name' => $name)); 1003 if (!$user->uid) { // Register this new user. 1004 $userinfo = array('name' => $name, 'pass' => user_password(), 'init' => $name, 'status' => 1); 1005 if ($server) { 1006 $userinfo["authname_$module"] = $name; 1007 } 1008 $user = user_save('', $userinfo); 1009 watchdog('user', t('New external user: %user using module %module.', array('%user' => $name, '%module' => $module)), WATCHDOG_NOTICE, l(t('edit'), 'user/'. $user->uid .'/edit')); 1010 break; 1011 } 1012 } 1013 } 1014 } 1015 return $user; 1016 } 1017 1018 /** 1019 * Menu callback; logs the current user out, and redirects to the home page. 1020 */ 1021 function user_logout() { 1022 global $user; 1023 1024 watchdog('user', t('Session closed for %name.', array('%name' => $user->name))); 1025 1026 // Destroy the current session: 1027 session_destroy(); 1028 module_invoke_all('user', 'logout', NULL, $user); 1029 1030 // Load the anonymous user 1031 $user = drupal_anonymous_user(); 1032 1033 drupal_goto(); 1034 } 1035 1036 function user_pass() { 1037 1038 // Display form: 1039 $form['name'] = array('#type' => 'textfield', 1040 '#title' => t('Username or e-mail address'), 1041 '#size' => 60, 1042 '#maxlength' => max(USERNAME_MAX_LENGTH, EMAIL_MAX_LENGTH), 1043 '#required' => TRUE, 1044 ); 1045 $form['submit'] = array('#type' => 'submit', 1046 '#value' => t('E-mail new password'), 1047 '#weight' => 2, 1048 ); 1049 return $form; 1050 } 1051 1052 function user_pass_validate($form_id, $form_values) { 1053 $name = $form_values['name']; 1054 $account = user_load(array('mail' => $name, 'status' => 1)); 1055 if (!$account) { 1056 $account = user_load(array('name' => $name, 'status' => 1)); 1057 } 1058 if ($account->uid) { 1059 form_set_value(array('#parents' => array('account')), $account); 1060 } 1061 else { 1062 form_set_error('name', t('Sorry, %name is not recognized as a user name or an email address.', array('%name' => $name))); 1063 } 1064 } 1065 1066 function user_pass_submit($form_id, $form_values) { 1067 global $base_url; 1068 1069 $account = $form_values['account']; 1070 $from = variable_get('site_mail', ini_get('sendmail_from')); 1071 1072 // Mail one time login URL and instructions. 1073 $variables = array('!username' => $account->name, '!site' => variable_get('site_name', 'Drupal'), '!login_url' => user_pass_reset_url($account), '!uri' => $base_url, '!uri_brief' => substr($base_url, strlen('http://')), '!mailto' => $account->mail, '!date' => format_date(time()), '!login_uri' => url('user', NULL, NULL, TRUE), '!edit_uri' => url('user/'. $account->uid .'/edit', NULL, NULL, TRUE)); 1074 $subject = _user_mail_text('pass_subject', $variables); 1075 $body = _user_mail_text('pass_body', $variables); 1076 $mail_success = drupal_mail('user-pass', $account->mail, $subject, $body, $from); 1077 1078 if ($mail_success) { 1079 watchdog('user', t('Password reset instructions mailed to %name at %email.', array('%name' => $account->name, '%email' => $account->mail))); 1080 drupal_set_message(t('Further instructions have been sent to your e-mail address.')); 1081 } 1082 else { 1083 watchdog('user', t('Error mailing password reset instructions to %name at %email.', array('%name' => $account->name, '%email' => $account->mail)), WATCHDOG_ERROR); 1084 drupal_set_message(t('Unable to send mail. Please contact the site admin.')); 1085 } 1086 return 'user'; 1087 } 1088 1089 /** 1090 * Menu callback; process one time login link and redirects to the user page on success. 1091 */ 1092 function user_pass_reset($uid, $timestamp, $hashed_pass, $action = NULL) { 1093 global $user; 1094 1095 // Check if the user is already logged in. The back button is often the culprit here. 1096 if ($user->uid) { 1097 drupal_set_message(t('You have already used this one-time login link. It is not necessary to use this link to login anymore. You are already logged in.')); 1098 drupal_goto(); 1099 } 1100 else { 1101 // Time out, in seconds, until login URL expires. 24 hours = 86400 seconds. 1102 $timeout = 86400; 1103 $current = time(); 1104 // Some redundant checks for extra security ? 1105 if ($timestamp < $current && $account = user_load(array('uid' => $uid, 'status' => 1)) ) { 1106 // No time out for first time login. 1107 if ($account->login && $current - $timestamp > $timeout) { 1108 drupal_set_message(t('You have tried to use a one-time login link that has expired. Please request a new one using the form below.')); 1109 drupal_goto('user/password'); 1110 } 1111 else if ($account->uid && $timestamp > $account->login && $timestamp < $current && $hashed_pass == user_pass_rehash($account->pass, $timestamp, $account->login)) { 1112 // First stage is a confirmation form, then login 1113 if ($action == 'login') { 1114 watchdog('user', t('User %name used one-time login link at time %timestamp.', array('%name' => $account->name, '%timestamp' => $timestamp))); 1115 // Update the user table noting user has logged in. 1116 // And this also makes this hashed password a one-time-only login. 1117 db_query("UPDATE {users} SET login = %d WHERE uid = %d", time(), $account->uid); 1118 // Now we can set the new user. 1119 $user = $account; 1120 // And proceed with normal login, going to user page. 1121 $edit = array(); 1122 user_module_invoke('login', $edit, $user); 1123 drupal_set_message(t('You have just used your one-time login link. It is no longer necessary to use this link to login. Please change your password.')); 1124 drupal_goto('user/'. $user->uid .'/edit'); 1125 } 1126 else { 1127 $form['message'] = array('#value' => t('<p>This is a one-time login for %user_name and will expire on %expiration_date</p><p>Click on this button to login to the site and change your password.</p>', array('%user_name' => $account->name, '%expiration_date' => format_date($timestamp + $timeout)))); 1128 $form['help'] = array('#value' => '<p>'. t('This login can be used only once.') .'</p>'); 1129 $form['submit'] = array('#type' => 'submit', '#value' => t('Log in')); 1130 $form['#action'] = url("user/reset/$uid/$timestamp/$hashed_pass/login"); 1131 return $form; 1132 } 1133 } 1134 else { 1135 drupal_set_message(t('You have tried to use a one-time login link which has either been used or is no longer valid. Please request a new one using the form below.')); 1136 drupal_goto('user/password'); 1137 } 1138 } 1139 else { 1140 // Deny access, no more clues. 1141 // Everything will be in the watchdog's URL for the administrator to check. 1142 drupal_access_denied(); 1143 } 1144 } 1145 } 1146 1147 function user_pass_reset_url($account) { 1148 $timestamp = time(); 1149 return url("user/reset/$account->uid/$timestamp/".user_pass_rehash($account->pass, $timestamp, $account->login), NULL, NULL, TRUE); 1150 } 1151 1152 function user_pass_rehash($password, $timestamp, $login) { 1153 return md5($timestamp . $password . $login); 1154 } 1155 1156 function user_register() { 1157 global $user; 1158 1159 $admin = user_access('administer users'); 1160 1161 // If we aren't admin but already logged on, go to the user page instead. 1162 if (!$admin && $user->uid) { 1163 drupal_goto('user/'. $user->uid); 1164 } 1165 1166 $form = array(); 1167 1168 // Display the registration form. 1169 if (!$admin) { 1170 $form['user_registration_help'] = array('#value' => filter_xss_admin(variable_get('user_registration_help', ''))); 1171 } 1172 $affiliates = user_auth_help_links(); 1173 if (!$admin && count($affiliates) > 0) { 1174 $affiliates = implode(', ', $affiliates); 1175 $form['affiliates'] = array('#value' => '<p>'. t('Note: if you have an account with one of our affiliates (!s), you may <a href="@login_uri">login now</a> instead of registering.', array('!s' => $affiliates, '@login_uri' => url('user'))) .'</p>'); 1176 } 1177 // Merge in the default user edit fields. 1178 $form = array_merge($form, user_edit_form(NULL, NULL, TRUE)); 1179 if ($admin) { 1180 $form['account']['notify'] = array( 1181 '#type' => 'checkbox', 1182 '#title' => t('Notify user of new account') 1183 ); 1184 // Redirect back to page which initiated the create request; usually admin/user/user/create 1185 $form['destination'] = array('#type' => 'hidden', '#value' => $_GET['q']); 1186 } 1187 1188 // Create a dummy variable for pass-by-reference parameters. 1189 $null = NULL; 1190 $extra = _user_forms($null, NULL, NULL, 'register'); 1191 1192 // Remove form_group around default fields if there are no other groups. 1193 if (!$extra) { 1194 $form['name'] = $form['account']['name']; 1195 $form['mail'] = $form['account']['mail']; 1196 $form['pass'] = $form['account']['pass']; 1197 $form['status'] = $form['account']['status']; 1198 $form['roles'] = $form['account']['roles']; 1199 $form['notify'] = $form['account']['notify']; 1200 unset($form['account']); 1201 } 1202 else { 1203 $form = array_merge($form, $extra); 1204 } 1205 $form['submit'] = array('#type' => 'submit', '#value' => t('Create new account'), '#weight' => 30); 1206 1207 return $form; 1208 } 1209 1210 function user_register_validate($form_id, $form_values) { 1211 user_module_invoke('validate', $form_values, $form_values, 'account'); 1212 } 1213 1214 function user_register_submit($form_id, $form_values) { 1215 global $base_url; 1216 $admin = user_access('administer users'); 1217 1218 $mail = $form_values['mail']; 1219 $name = $form_values['name']; 1220 if (!variable_get('user_email_verification', TRUE) || $admin) { 1221 $pass = $form_values['pass']; 1222 } 1223 else { 1224 $pass = user_password(); 1225 }; 1226 $notify = $form_values['notify']; 1227 $from = variable_get('site_mail', ini_get('sendmail_from')); 1228 if (isset($form_values['roles'])) { 1229 $roles = array_filter($form_values['roles']); // Remove unset roles 1230 } 1231 1232 if (!$admin && array_intersect(array_keys($form_values), array('uid', 'roles', 'init', 'session', 'status'))) { 1233 watchdog('security', t('Detected malicious attempt to alter protected user fields.'), WATCHDOG_WARNING); 1234 return 'user/register'; 1235 } 1236 //the unset below is needed to prevent these form values from being saved as user data 1237 unset($form_values['form_token'], $form_values['submit'], $form_values['op'], $form_values['notify'], $form_values['form_id'], $form_values['affiliates'], $form_values['destination']); 1238 1239 $merge_data = array('pass' => $pass, 'init' => $mail, 'roles' => $roles); 1240 if (!$admin) { 1241 // Set the user's status because it was not displayed in the form. 1242 $merge_data['status'] = variable_get('user_register', 1) == 1; 1243 } 1244 $account = user_save('', array_merge($form_values, $merge_data)); 1245 watchdog('user', t('New user: %name %email.', array('%name' => $name, '%email' => '<'. $mail .'>')), WATCHDOG_NOTICE, l(t('edit'), 'user/'. $account->uid .'/edit')); 1246 1247 $variables = array('!username' => $name, '!site' => variable_get('site_name', 'Drupal'), '!password' => $pass, '!uri' => $base_url, '!uri_brief' => substr($base_url, strlen('http://')), '!mailto' => $mail, '!date' => format_date(time()), '!login_uri' => url('user', NULL, NULL, TRUE), '!edit_uri' => url('user/'. $account->uid .'/edit', NULL, NULL, TRUE), '!login_url' => user_pass_reset_url($account)); 1248 1249 // The first user may login immediately, and receives a customized welcome e-mail. 1250 if ($account->uid == 1) { 1251 drupal_mail('user-register-admin', $mail, t('Drupal user account details for !s', array('!s' => $name)), strtr(t("!username,\n\nYou may now login to !uri using the following username and password:\n\n username: !username\n password: !password\n\n!edit_uri\n\n--drupal"), $variables), $from); 1252 drupal_set_message(t('<p>Welcome to Drupal. You are user #1, which gives you full and immediate access. All future registrants will receive their passwords via e-mail, so please make sure your website e-mail address is set properly under the general settings on the <a href="@settings">site information settings page</a>.</p><p> Your password is <strong>%pass</strong>. You may change your password below.</p>', array('%pass' => $pass, '@settings' => url('admin/settings/site-information')))); 1253 user_authenticate($account->name, trim($pass)); 1254 1255 return 'user/1/edit'; 1256 } 1257 else { 1258 if ($admin && !$notify) { 1259 drupal_set_message(t('Created a new user account. No e-mail has been sent.')); 1260 } 1261 else if (!variable_get('user_email_verification', TRUE) && $account->status && !$admin) { 1262 // No e-mail verification is required, create new user account, and login user immediately. 1263 $subject = _user_mail_text('welcome_subject', $variables); 1264 $body = _user_mail_text('welcome_body', $variables); 1265 drupal_mail('user-register-welcome', $mail, $subject, $body, $from); 1266 user_authenticate($account->name, trim($pass)); 1267 $edit = array(); 1268 user_module_invoke('login', $edit, $account); 1269 return ''; 1270 } 1271 else if ($account->status || $notify) { 1272 // Create new user account, no administrator approval required. 1273 $subject = $notify ? _user_mail_text('admin_subject', $variables) : _user_mail_text('welcome_subject', $variables); 1274 $body = $notify ? _user_mail_text('admin_body', $variables) : _user_mail_text('welcome_body', $variables); 1275 1276 drupal_mail(($notify ? 'user-register-notify' : 'user-register-welcome'), $mail, $subject, $body, $from); 1277 1278 if ($notify) { 1279 drupal_set_message(t('Password and further instructions have been e-mailed to the new user %user.', array('%user' => $name))); 1280 } 1281 else { 1282 drupal_set_message(t('Your password and further instructions have been sent to your e-mail address.')); 1283 return ''; 1284 } 1285 } 1286 else { 1287 // Create new user account, administrator approval required. 1288 $subject = _user_mail_text('approval_subject', $variables); 1289 $body = _user_mail_text('approval_body', $variables); 1290 1291 drupal_mail('user-register-approval-user', $mail, $subject, $body, $from); 1292 drupal_mail('user-register-approval-admin', $from, $subject, t("!username has applied for an account.\n\n!edit_uri", $variables), $from); 1293 drupal_set_message(t('Thank you for applying for an account. Your account is currently pending approval by the site administrator.<br />In the meantime, your password and further instructions have been sent to your e-mail address.')); 1294 return ''; 1295 } 1296 } 1297 } 1298 1299 function user_edit_form($uid, $edit, $register = FALSE) { 1300 $admin = user_access('administer users'); 1301 1302 // Account information: 1303 $form['account'] = array('#type' => 'fieldset', 1304 '#title' => t('Account information'), 1305 ); 1306 if (user_access('change own username') || $admin || $register) { 1307 $form['account']['name'] = array('#type' => 'textfield', 1308 '#title' => t('Username'), 1309 '#default_value' => $edit['name'], 1310 '#maxlength' => USERNAME_MAX_LENGTH, 1311 '#description' => t('Your preferred username; punctuation is not allowed except for periods, hyphens, and underscores.'), 1312 '#required' => TRUE, 1313 ); 1314 } 1315 $form['account']['mail'] = array('#type' => 'textfield', 1316 '#title' => t('E-mail address'), 1317 '#default_value' => $edit['mail'], 1318 '#maxlength' => EMAIL_MAX_LENGTH, 1319 '#description' => t('A valid e-mail address. All e-mails from the system will be sent to this address. The e-mail address is not made public and will only be used if you wish to receive a new password or wish to receive certain news or notifications by e-mail.'), 1320 '#required' => TRUE, 1321 ); 1322 if (!$register) { 1323 $form['account']['pass'] = array('#type' => 'password_confirm', 1324 '#description' => t('To change the current user password, enter the new password in both fields.'), 1325 '#size' => 25, 1326 ); 1327 } 1328 elseif (!variable_get('user_email_verification', TRUE) || $admin) { 1329 $form['account']['pass'] = array( 1330 '#type' => 'password_confirm', 1331 '#description' => t('Provide a password for the new account in both fields.'), 1332 '#required' => TRUE, 1333 '#size' => 25, 1334 ); 1335 } 1336 if ($admin) { 1337 $form['account']['status'] = array('#type' => 'radios', '#title' => t('Status'), '#default_value' => isset($edit['status']) ? $edit['status'] : 1, '#options' => array(t('Blocked'), t('Active'))); 1338 } 1339 if (user_access('administer access control')) { 1340 $roles = user_roles(1); 1341 unset($roles[DRUPAL_AUTHENTICATED_RID]); 1342 if ($roles) { 1343 $form['account']['roles'] = array('#type' => 'checkboxes', '#title' => t('Roles'), '#default_value' => array_keys((array)$edit['roles']), '#options' => $roles, '#description' => t('The user receives the combined permissions of the %au role, and all roles selected here.', array('%au' => t('authenticated user')))); 1344 } 1345 } 1346 1347 // Picture/avatar: 1348 if (variable_get('user_pictures', 0) && !$register) { 1349 $form['picture'] = array('#type' => 'fieldset', '#title' => t('Picture'), '#weight' => 1); 1350 $picture = theme('user_picture', (object)$edit); 1351 if ($picture) { 1352 $form['picture']['current_picture'] = array('#value' => $picture); 1353 $form['picture']['picture_delete'] = array('#type' => 'checkbox', '#title' => t('Delete picture'), '#description' => t('Check this box to delete your current picture.')); 1354 } 1355 else { 1356 $form['picture']['picture_delete'] = array('#type' => 'hidden'); 1357 } 1358 $form['picture']['picture_upload'] = array('#type' => 'file', '#title' => t('Upload picture'), '#size' => 48, '#description' => t('Your virtual face or picture. Maximum dimensions are %dimensions and the maximum size is %size kB.', array('%dimensions' => variable_get('user_picture_dimensions', '85x85'), '%size' => variable_get('user_picture_file_size', '30'))) .' '. variable_get('user_picture_guidelines', '')); 1359 } 1360 1361 return $form; 1362 } 1363 1364 function _user_edit_validate($uid, &$edit) { 1365 $user = user_load(array('uid' => $uid)); 1366 // Validate the username: 1367 if (user_access('change own username') || user_access('administer users') || arg(1) == 'register') { 1368 if ($error = user_validate_name($edit['name'])) { 1369 form_set_error('name', $error); 1370 } 1371 else if (db_num_rows(db_query("SELECT uid FROM {users} WHERE uid != %d AND LOWER(name) = LOWER('%s')", $uid, $edit['name'])) > 0) { 1372 form_set_error('name', t('The name %name is already taken.', array('%name' => $edit['name']))); 1373 } 1374 else if (drupal_is_denied('user', $edit['name'])) { 1375 form_set_error('name', t('The name %name has been denied access.', array('%name' => $edit['name']))); 1376 } 1377 } 1378 1379 // Validate the e-mail address: 1380 if ($error = user_validate_mail($edit['mail'])) { 1381 form_set_error('mail', $error); 1382 } 1383 else if (db_num_rows(db_query("SELECT uid FROM {users} WHERE uid != %d AND LOWER(mail) = LOWER('%s')", $uid, $edit['mail'])) > 0) { 1384 form_set_error('mail', t('The e-mail address %email is already registered. <a href="@password">Have you forgotten your password?</a>', array('%email' => $edit['mail'], '@password' => url('user/password')))); 1385 } 1386 else if (drupal_is_denied('mail', $edit['mail'])) { 1387 form_set_error('mail', t('The e-mail address %email has been denied access.', array('%email' => $edit['mail']))); 1388 } 1389 1390 // If required, validate the uploaded picture. 1391 if ($file = file_check_upload('picture_upload')) { 1392 user_validate_picture($file, $edit, $user); 1393 } 1394 } 1395 1396 function _user_edit_submit($uid, &$edit) { 1397 $user = user_load(array('uid' => $uid)); 1398 // Delete picture if requested, and if no replacement picture was given. 1399 if ($edit['picture_delete']) { 1400 if ($user->picture && file_exists($user->picture)) { 1401 file_delete($user->picture); 1402 } 1403 $edit['picture'] = ''; 1404 } 1405 if (isset($edit['roles'])) { 1406 $edit['roles'] = array_filter($edit['roles']); 1407 } 1408 } 1409 1410 function user_edit($category = 'account') { 1411 global $user; 1412 1413 $account = user_load(array('uid' => arg(1))); 1414 if ($account === FALSE) { 1415 drupal_set_message(t('The account does not exist or has already been deleted.')); 1416 drupal_goto('admin/user/user'); 1417 } 1418 1419 $edit = $_POST['op'] ? $_POST : (array)$account; 1420 1421 if (arg(2) == 'delete') { 1422 return drupal_get_form('user_confirm_delete', $account->name, $account->uid); 1423 } 1424 else if ($_POST['op'] == t('Delete')) { 1425 if ($_REQUEST['destination']) { 1426 $destination = drupal_get_destination(); 1427 unset($_REQUEST['destination']); 1428 } 1429 // Note: we redirect from user/uid/edit to user/uid/delete to make the tabs disappear. 1430 drupal_goto("user/$account->uid/delete", $destination); 1431 } 1432 1433 $form = _user_forms($edit, $account, $category); 1434 $form['_category'] = array('#type' => 'value', '#value' => $category); 1435 $form['_account'] = array('#type' => 'value', '#value' => $account); 1436 $form['submit'] = array('#type' => 'submit', '#value' => t('Submit'), '#weight' => 30); 1437 if (user_access('administer users')) { 1438 $form['delete'] = array('#type' => 'submit', '#value' => t('Delete'), '#weight' => 31); 1439 } 1440 $form['#attributes']['enctype'] = 'multipart/form-data'; 1441 1442 drupal_set_title(check_plain($account->name)); 1443 return $form; 1444 } 1445 1446 function user_confirm_delete($name, $uid) { 1447 $form['uid'] = array('#type' => 'value', '#value' => $uid); 1448 return confirm_form($form, 1449 t('Are you sure you want to delete the account %name?', array('%name' => $name)), 1450 'user/'. $uid, 1451 t('All submissions made by this user will be attributed to the anonymous account. This action cannot be undone.'), 1452 t('Delete'), t('Cancel')); 1453 } 1454 1455 function user_confirm_delete_submit($form_id, $form_values) { 1456 $account = user_load(array('uid' => $form_values['uid'])); 1457 user_delete((array) $account, $form_values['uid']); 1458 return 'admin/user/user'; 1459 } 1460 1461 /** 1462 * Delete a user. 1463 * 1464 * @param $edit An array of submitted form values. 1465 * @param $uid The user ID of the user to delete. 1466 */ 1467 function user_delete($edit, $uid) { 1468 $account = user_load(array('uid' => $uid)); 1469 sess_destroy_uid($uid); 1470 db_query('DELETE FROM {users} WHERE uid = %d', $uid); 1471 db_query('DELETE FROM {users_roles} WHERE uid = %d', $uid); 1472 db_query('DELETE FROM {authmap} WHERE uid = %d', $uid); 1473 $array = array('%name' => $account->name, '%email' => '<'. $account->mail .'>'); 1474 watchdog('user', t('Deleted user: %name %email.', $array), WATCHDOG_NOTICE); 1475 drupal_set_message(t('%name has been deleted.', $array)); 1476 module_invoke_all('user', 'delete', $edit, $account); 1477 } 1478 1479 function user_edit_validate($form_id, $form_values) { 1480 user_module_invoke('validate', $form_values, $form_values['_account'], $form_values['_category']); 1481 // Validate input to ensure that non-privileged users can't alter protected data. 1482 if ((!user_access('administer users') && array_intersect(array_keys($form_values), array('uid', 'init', 'session'))) || (!user_access('administer access control') && isset($form_values['roles']))) { 1483 $message = t('Detected malicious attempt to alter protected user fields.'); 1484 watchdog('security', $message, WATCHDOG_WARNING); 1485 // set this to a value type field 1486 form_set_error('category', $message); 1487 } 1488 } 1489 1490 function user_edit_submit($form_id, $form_values) { 1491 $account = $form_values['_account']; 1492 $category = $form_values['_category']; 1493 unset($form_values['_account'], $form_values['op'], $form_values['submit'], $form_values['delete'], $form_values['form_token'], $form_values['form_id'], $form_values['_category']); 1494 user_module_invoke('submit', $form_values, $account, $category); 1495 user_save($account, $form_values, $category); 1496 1497 // Delete that user's menu cache: 1498 cache_clear_all($account->uid .':', 'cache_menu', TRUE); 1499 1500 // Clear the page cache because pages can contain usernames and/or profile information: 1501 cache_clear_all(); 1502 1503 drupal_set_message(t('The changes have been saved.')); 1504 return 'user/'. $account->uid; 1505 } 1506 1507 function user_view($uid = 0) { 1508 global $user; 1509 1510 $account = user_load(array('uid' => $uid)); 1511 if ($account === FALSE || ($account->access == 0 && !user_access('administer users'))) { 1512 return drupal_not_found(); 1513 } 1514 // Retrieve and merge all profile fields: 1515 $fields = array(); 1516 foreach (module_list() as $module) { 1517 if ($data = module_invoke($module, 'user', 'view', '', $account)) { 1518 foreach ($data as $category => $items) { 1519 foreach ($items as $key => $item) { 1520 $item['class'] = "$module-". $item['class']; 1521 $fields[$category][$key] = $item; 1522 } 1523 } 1524 } 1525 } 1526 1527 // Let modules change the returned fields - useful for personal privacy 1528 // controls. Since modules communicate changes by reference, we cannot use 1529 // module_invoke_all(). 1530 foreach (module_implements('profile_alter') as $module) { 1531 $function = $module .'_profile_alter'; 1532 $function($account, $fields); 1533 } 1534 1535 drupal_set_title(check_plain($account->name)); 1536 return theme('user_profile', $account, $fields); 1537 } 1538 1539 /*** Administrative features ***********************************************/ 1540 1541 function _user_mail_text($messageid, $variables = array()) { 1542 1543 // Check if an admin setting overrides the default string. 1544 if ($admin_setting = variable_get('user_mail_'. $messageid, FALSE)) { 1545 return strtr($admin_setting, $variables); 1546 } 1547 // No override, return with default strings. 1548 else { 1549 switch ($messageid) { 1550 case 'welcome_subject': 1551 return t('Account details for !username at !site', $variables); 1552 case 'welcome_body': 1553 return t("!username,\n\nThank you for registering at !site. You may now log in to !login_uri using the following username and password:\n\nusername: !username\npassword: !password\n\nYou may also log in by clicking on this link or copying and pasting it in your browser:\n\n!login_url\n\nThis is a one-time login, so it can be used only once.\n\nAfter logging in, you will be redirected to !edit_uri so you can change your password.\n\n\n-- !site team", $variables); 1554 case 'admin_subject': 1555 return t('An administrator created an account for you at !site', $variables); 1556 case 'admin_body': 1557 return t("!username,\n\nA site administrator at !site has created an account for you. You may now log in to !login_uri using the following username and password:\n\nusername: !username\npassword: !password\n\nYou may also log in by clicking on this link or copying and pasting it in your browser:\n\n!login_url\n\nThis is a one-time login, so it can be used only once.\n\nAfter logging in, you will be redirected to !edit_uri so you can change your password.\n\n\n-- !site team", $variables); 1558 case 'approval_subject': 1559 return t('Account details for !username at !site (pending admin approval)', $variables); 1560 case 'approval_body': 1561 return t("!username,\n\nThank you for registering at !site. Your application for an account is currently pending approval. Once it has been granted, you may log in to !login_uri using the following username and password:\n\nusername: !username\npassword: !password\n\nYou may also log in by clicking on this link or copying and pasting it in your browser:\n\n!login_url\n\nThis is a one-time login, so it can be used only once.\n\nAfter logging in, you may wish to change your password at !edit_uri\n\n\n-- !site team", $variables); 1562 case 'pass_subject': 1563 return t('Replacement login information for !username at !site', $variables); 1564 case 'pass_body': 1565 return t("!username,\n\nA request to reset the password for your account has been made at !site.\n\nYou may now log in to !uri_brief clicking on this link or copying and pasting it in your browser:\n\n!login_url\n\nThis is a one-time login, so it can be used only once. It expires after one day and nothing will happen if it's not used.\n\nAfter logging in, you will be redirected to !edit_uri so you can change your password.", $variables); 1566 } 1567 } 1568 } 1569 1570 function user_admin_check_user() { 1571 $form['user'] = array('#type' => 'fieldset', '#title' => t('Username')); 1572 $form['user']['test'] = array('#type' => 'textfield', '#title' => '', '#description' => t('Enter a username to check if it will be denied or allowed.'), '#size' => 30, '#maxlength' => USERNAME_MAX_LENGTH); 1573 $form['user']['type'] = array('#type' => 'hidden', '#value' => 'user'); 1574 $form['user']['submit'] = array('#type' => 'submit', '#value' => t('Check username')); 1575 $form['#base'] = 'user_admin_access_check'; 1576 return $form; 1577 } 1578 1579 function user_admin_check_mail() { 1580 $form['mail'] = array('#type' => 'fieldset', '#title' => t('E-mail')); 1581 $form['mail']['test'] = array('#type' => 'textfield', '#title' => '', '#description' => t('Enter an e-mail address to check if it will be denied or allowed.'), '#size' => 30, '#maxlength' => EMAIL_MAX_LENGTH); 1582 $form['mail']['type'] = array('#type' => 'hidden', '#value' => 'mail'); 1583 $form['mail']['submit'] = array('#type' => 'submit', '#value' => t('Check e-mail')); 1584 $form['#base'] = 'user_admin_access_check'; 1585 return $form; 1586 } 1587 1588 function user_admin_check_host() { 1589 $form['host'] = array('#type' => 'fieldset', '#title' => t('Hostname')); 1590 $form['host']['test'] = array('#type' => 'textfield', '#title' => '', '#description' => t('Enter a hostname or IP address to check if it will be denied or allowed.'), '#size' => 30, '#maxlength' => 64); 1591 $form['host']['type'] = array('#type' => 'hidden', '#value' => 'host'); 1592 $form['host']['submit'] = array('#type' => 'submit', '#value' => t('Check hostname')); 1593 $form['#base'] = 'user_admin_access_check'; 1594 return $form; 1595 } 1596 1597 /** 1598 * Menu callback: check an access rule 1599 */ 1600 function user_admin_access_check() { 1601 $output = drupal_get_form('user_admin_check_user'); 1602 $output .= drupal_get_form('user_admin_check_mail'); 1603 $output .= drupal_get_form('user_admin_check_host'); 1604 return $output; 1605 } 1606 1607 function user_admin_access_check_validate($form_id, $form_values) { 1608 if (empty($form_values['test'])) { 1609 form_set_error($form_values['type'], t('No value entered. Please enter a test string and try again.')); 1610 } 1611 } 1612 1613 function user_admin_access_check_submit($form_id, $form_values) { 1614 switch ($form_values['type']) { 1615 case 'user': 1616 if (drupal_is_denied('user', $form_values['test'])) { 1617 drupal_set_message(t('The username %name is not allowed.', array('%name' => $form_values['test']))); 1618 } 1619 else { 1620 drupal_set_message(t('The username %name is allowed.', array('%name' => $form_values['test']))); 1621 } 1622 break; 1623 case 'mail': 1624 if (drupal_is_denied('mail', $form_values['test'])) { 1625 drupal_set_message(t('The e-mail address %mail is not allowed.', array('%mail' => $form_values['test']))); 1626 } 1627 else { 1628 drupal_set_message(t('The e-mail address %mail is allowed.', array('%mail' => $form_values['test']))); 1629 } 1630 break; 1631 case 'host': 1632 if (drupal_is_denied('host', $form_values['test'])) { 1633 drupal_set_message(t('The hostname %host is not allowed.', array('%host' => $form_values['test']))); 1634 } 1635 else { 1636 drupal_set_message(t('The hostname %host is allowed.', array('%host' => $form_values['test']))); 1637 } 1638 break; 1639 default: 1640 break; 1641 } 1642 } 1643 1644 /** 1645 * Menu callback: add an access rule 1646 */ 1647 function user_admin_access_add($mask = NULL, $type = NULL) { 1648 if ($edit = $_POST) { 1649 if (!$edit['mask']) { 1650 form_set_error('mask', t('You must enter a mask.')); 1651 } 1652 else { 1653 $aid = db_next_id('{access}_aid'); 1654 db_query("INSERT INTO {access} (aid, mask, type, status) VALUES ('%s', '%s', '%s', %d)", $aid, $edit['mask'], $edit['type'], $edit['status']); 1655 drupal_set_message(t('The access rule has been added.')); 1656 drupal_goto('admin/user/rules'); 1657 } 1658 } 1659 else { 1660 $edit['mask'] = $mask; 1661 $edit['type'] = $type; 1662 } 1663 return drupal_get_form('user_admin_access_add_form', $edit, t('Add rule')); 1664 } 1665 1666 /** 1667 * Menu callback: delete an access rule 1668 */ 1669 function user_admin_access_delete_confirm($aid = 0) { 1670 $access_types = array('user' => t('username'), 'mail' => t('e-mail'), 'host' => t('host')); 1671 $edit = db_fetch_object(db_query('SELECT aid, type, status, mask FROM {access} WHERE aid = %d', $aid)); 1672 1673 $form = array(); 1674 $form['aid'] = array('#type' => 'hidden', '#value' => $aid); 1675 $output = confirm_form($form, 1676 t('Are you sure you want to delete the @type rule for %rule?', array('@type' => $access_types[$edit->type], '%rule' => $edit->mask)), 1677 'admin/user/rules', 1678 t('This action cannot be undone.'), 1679 t('Delete'), 1680 t('Cancel')); 1681 return $output; 1682 } 1683 1684 function user_admin_access_delete_confirm_submit($form_id, $form_values) { 1685 db_query('DELETE FROM {access} WHERE aid = %d', $form_values['aid']); 1686 drupal_set_message(t('The access rule has been deleted.')); 1687 return 'admin/user/rules'; 1688 } 1689 1690 /** 1691 * Menu callback: edit an access rule 1692 */ 1693 function user_admin_access_edit($aid = 0) { 1694 if ($edit = $_POST) { 1695 if (!$edit['mask']) { 1696 form_set_error('mask', t('You must enter a mask.')); 1697 } 1698 else { 1699 db_query("UPDATE {access} SET mask = '%s', type = '%s', status = '%s' WHERE aid = %d", $edit['mask'], $edit['type'], $edit['status'], $aid); 1700 drupal_set_message(t('The access rule has been saved.')); 1701 drupal_goto('admin/user/rules'); 1702 } 1703 } 1704 else { 1705 $edit = db_fetch_array(db_query('SELECT aid, type, status, mask FROM {access} WHERE aid = %d', $aid)); 1706 } 1707 return drupal_get_form('user_admin_access_edit_form', $edit, t('Save rule')); 1708 } 1709 1710 function user_admin_access_form($edit, $submit) { 1711 $form['status'] = array( 1712 '#type' => 'radios', 1713 '#title' => t('Access type'), 1714 '#default_value' => $edit['status'], 1715 '#options' => array('1' => t('Allow'), '0' => t('Deny')), 1716 ); 1717 $type_options = array('user' => t('Username'), 'mail' => t('E-mail'), 'host' => t('Host')); 1718 $form['type'] = array( 1719 '#type' => 'radios', 1720 '#title' => t('Rule type'), 1721 '#default_value' => (isset($type_options[$edit['type']]) ? $edit['type'] : 'user'), 1722 '#options' => $type_options, 1723 ); 1724 $form['mask'] = array( 1725 '#type' => 'textfield', 1726 '#title' => t('Mask'), 1727 '#size' => 30, 1728 '#maxlength' => 64, 1729 '#default_value' => $edit['mask'], 1730 '#description' => '%: '. t('Matches any number of characters, even zero characters') .'.<br />_: '. t('Matches exactly one character.'), 1731 '#required' => TRUE, 1732 ); 1733 $form['submit'] = array('#type' => 'submit', '#value' => $submit); 1734 1735 return $form; 1736 } 1737 1738 /** 1739 * Menu callback: list all access rules 1740 */ 1741 function user_admin_access() { 1742 $header = array(array('data' => t('Access type'), 'field' => 'status'), array('data' => t('Rule type'), 'field' => 'type'), array('data' => t('Mask'), 'field' => 'mask'), array('data' => t('Operations'), 'colspan' => 2)); 1743 $result = db_query("SELECT aid, type, status, mask FROM {access}". tablesort_sql($header)); 1744 $access_types = array('user' => t('username'), 'mail' => t('e-mail'), 'host' => t('host')); 1745 $rows = array(); 1746 while ($rule = db_fetch_object($result)) { 1747 $rows[] = array($rule->status ? t('allow') : t('deny'), $access_types[$rule->type], $rule->mask, l(t('edit'), 'admin/user/rules/edit/'. $rule->aid), l(t('delete'), 'admin/user/rules/delete/'. $rule->aid)); 1748 } 1749 if (count($rows) == 0) { 1750 $rows[] = array(array('data' => '<em>'. t('There are currently no access rules.') .'</em>', 'colspan' => 5)); 1751 } 1752 $output .= theme('table', $header, $rows); 1753 1754 return $output; 1755 } 1756 1757 /** 1758 * Retrieve an array of roles matching specified conditions. 1759 * 1760 * @param $membersonly 1761 * Set this to TRUE to exclude the 'anonymous' role. 1762 * @param $permission 1763 * A string containing a permission. If set, only roles containing that permission are returned. 1764 * 1765 * @return 1766 * An associative array with the role id as the key and the role name as value. 1767 */ 1768 function user_roles($membersonly = 0, $permission = 0) { 1769 $roles = array(); 1770 1771 if ($permission) { 1772 $result = db_query("SELECT r.* FROM {role} r INNER JOIN {permission} p ON r.rid = p.rid WHERE p.perm LIKE '%%%s%%' ORDER BY r.name", $permission); 1773 } 1774 else { 1775 $result = db_query('SELECT * FROM {role} ORDER BY name'); 1776 } 1777 while ($role = db_fetch_object($result)) { 1778 if (!$membersonly || ($membersonly && $role->rid != DRUPAL_ANONYMOUS_RID)) { 1779 $roles[$role->rid] = $role->name; 1780 } 1781 } 1782 return $roles; 1783 } 1784 1785 /** 1786 * Menu callback: administer permissions. 1787 */ 1788 function user_admin_perm($rid = NULL) { 1789 if (is_numeric($rid)) { 1790 $result = db_query('SELECT r.rid, p.perm FROM {role} r LEFT JOIN {permission} p ON r.rid = p.rid WHERE r.rid = %d', $rid); 1791 } 1792 else { 1793 $result = db_query('SELECT r.rid, p.perm FROM {role} r LEFT JOIN {permission} p ON r.rid = p.rid ORDER BY name'); 1794 } 1795 1796 // Compile role array: 1797 // Add a comma at the end so when searching for a permission, we can 1798 // always search for "$perm," to make sure we do not confuse 1799 // permissions that are substrings of each other. 1800 while ($role = db_fetch_object($result)) { 1801 $role_permissions[$role->rid] = $role->perm .','; 1802 } 1803 1804 if (is_numeric($rid)) { 1805 $result = db_query('SELECT rid, name FROM {role} r WHERE r.rid = %d ORDER BY name', $rid); 1806 } 1807 else { 1808 $result = db_query('SELECT rid, name FROM {role} ORDER BY name'); 1809 } 1810 1811 $role_names = array(); 1812 while ($role = db_fetch_object($result)) { 1813 $role_names[$role->rid] = $role->name; 1814 } 1815 1816 // Render role/permission overview: 1817 $options = array(); 1818 foreach (module_list(FALSE, FALSE, TRUE) as $module) { 1819 if ($permissions = module_invoke($module, 'perm')) { 1820 $form['permission'][] = array( 1821 '#value' => $module, 1822 ); 1823 asort($permissions); 1824 foreach ($permissions as $perm) { 1825 $options[$perm] = ''; 1826 $form['permission'][$perm] = array('#value' => t($perm)); 1827 foreach ($role_names as $rid => $name) { 1828 // Builds arrays for checked boxes for each role 1829 if (strpos($role_permissions[$rid], $perm .',') !== FALSE) { 1830 $status[$rid][] = $perm; 1831 } 1832 } 1833 } 1834 } 1835 } 1836 1837 // Have to build checkboxes here after checkbox arrays are built 1838 foreach ($role_names as $rid => $name) { 1839 $form['checkboxes'][$rid] = array('#type' => 'checkboxes', '#options' => $options, '#default_value' => $status[$rid]); 1840 $form['role_names'][$rid] = array('#value' => $name, '#tree' => TRUE); 1841 } 1842 $form['submit'] = array('#type' => 'submit', '#value' => t('Save permissions')); 1843 1844 return $form; 1845 } 1846 1847 function theme_user_admin_perm($form) { 1848 foreach (element_children($form['permission']) as $key) { 1849 // Don't take form control structures 1850 if (is_array($form['permission'][$key])) { 1851 $row = array(); 1852 // Module name 1853 if (is_numeric($key)) { 1854 $row[] = array('data' => t('@module module', array('@module' => drupal_render($form['permission'][$key]))), 'class' => 'module', 'id' => 'module-'. $form['permission'][$key]['#value'], 'colspan' => count($form['role_names']) + 1); 1855 } 1856 else { 1857 $row[] = array('data' => drupal_render($form['permission'][$key]), 'class' => 'permission'); 1858 foreach (element_children($form['checkboxes']) as $rid) { 1859 if (is_array($form['checkboxes'][$rid])) { 1860 $row[] = array('data' => drupal_render($form['checkboxes'][$rid][$key]), 'align' => 'center', 'title' => t($key)); 1861 } 1862 } 1863 } 1864 $rows[] = $row; 1865 } 1866 } 1867 $header[] = (t('Permission')); 1868 foreach (element_children($form['role_names']) as $rid) { 1869 if (is_array($form['role_names'][$rid])) { 1870 $header[] = drupal_render($form['role_names'][$rid]); 1871 } 1872 } 1873 $output = theme('table', $header, $rows, array('id' => 'permissions')); 1874 $output .= drupal_render($form); 1875 return $output; 1876 } 1877 1878 function user_admin_perm_submit($form_id, $form_values) { 1879 // Save permissions: 1880 $result = db_query('SELECT * FROM {role}'); 1881 while ($role = db_fetch_object($result)) { 1882 if (isset($form_values[$role->rid])) { 1883 // Delete, so if we clear every checkbox we reset that role; 1884 // otherwise permissions are active and denied everywhere. 1885 db_query('DELETE FROM {permission} WHERE rid = %d', $role->rid); 1886 $form_values[$role->rid] = array_filter($form_values[$role->rid]); 1887 if (count($form_values[$role->rid])) { 1888 db_query("INSERT INTO {permission} (rid, perm) VALUES (%d, '%s')", $role->rid, implode(', ', array_keys($form_values[$role->rid]))); 1889 } 1890 } 1891 } 1892 1893 drupal_set_message(t('The changes have been saved.')); 1894 1895 // Clear the cached pages and menus: 1896 menu_rebuild(); 1897 1898 } 1899 1900 /** 1901 * Menu callback: administer roles. 1902 */ 1903 function user_admin_role() { 1904 $id = arg(4); 1905 if ($id) { 1906 if (DRUPAL_ANONYMOUS_RID == $id || DRUPAL_AUTHENTICATED_RID == $id) { 1907 drupal_goto('admin/user/roles'); 1908 } 1909 // Display the edit role form. 1910 $role = db_fetch_object(db_query('SELECT * FROM {role} WHERE rid = %d', $id)); 1911 $form['name'] = array( 1912 '#type' => 'textfield', 1913 '#title' => t('Role name'), 1914 '#default_value' => $role->name, 1915 '#size' => 30, 1916 '#required' => TRUE, 1917 '#maxlength' => 64, 1918 '#description' => t('The name for this role. Example: "moderator", "editorial board", "site architect".'), 1919 ); 1920 $form['rid'] = array( 1921 '#type' => 'value', 1922 '#value' => $id, 1923 ); 1924 $form['submit'] = array( 1925 '#type' => 'submit', 1926 '#value' => t('Save role'), 1927 ); 1928 $form['delete'] = array( 1929 '#type' => 'submit', 1930 '#value' => t('Delete role'), 1931 ); 1932 } 1933 else { 1934 $form['name'] = array( 1935 '#type' => 'textfield', 1936 '#size' => 32, 1937 '#maxlength' => 64, 1938 ); 1939 $form['submit'] = array( 1940 '#type' => 'submit', 1941 '#value' => t('Add role'), 1942 ); 1943 $form['#base'] = 'user_admin_role'; 1944 } 1945 return $form; 1946 } 1947 1948 function user_admin_role_validate($form_id, $form_values) { 1949 if ($form_values['name']) { 1950 if ($form_values['op'] == t('Save role')) { 1951 if (db_result(db_query("SELECT COUNT(*) FROM {role} WHERE name = '%s' AND rid != %d", $form_values['name'], $form_values['rid']))) { 1952 form_set_error('name', t('The role name %name already exists. Please choose another role name.', array('%name' => $form_values['name']))); 1953 } 1954 } 1955 else if ($form_values['op'] == t('Add role')) { 1956 if (db_result(db_query("SELECT COUNT(*) FROM {role} WHERE name = '%s'", $form_values['name']))) { 1957 form_set_error('name', t('The role name %name already exists. Please choose another role name.', array('%name' => $form_values['name']))); 1958 } 1959 } 1960 } 1961 else { 1962 form_set_error('name', t('You must specify a valid role name.')); 1963 } 1964 } 1965 1966 function user_admin_role_submit($form_id, $form_values) { 1967 if ($form_values['op'] == t('Save role')) { 1968 db_query("UPDATE {role} SET name = '%s' WHERE rid = %d", $form_values['name'], $form_values['rid']); 1969 drupal_set_message(t('The role has been renamed.')); 1970 } 1971 else if ($form_values['op'] == t('Delete role')) { 1972 db_query('DELETE FROM {role} WHERE rid = %d', $form_values['rid']); 1973 db_query('DELETE FROM {permission} WHERE rid = %d', $form_values['rid']); 1974 // Update the users who have this role set: 1975 db_query('DELETE FROM {users_roles} WHERE rid = %d', $form_values['rid']); 1976 1977 drupal_set_message(t('The role has been deleted.')); 1978 } 1979 else if ($form_values['op'] == t('Add role')) { 1980 db_query("INSERT INTO {role} (name) VALUES ('%s')", $form_values['name']); 1981 drupal_set_message(t('The role has been added.')); 1982 } 1983 return 'admin/user/roles'; 1984 } 1985 1986 function theme_user_admin_new_role($form) { 1987 $header = array(t('Name'), array('data' => t('Operations'), 'colspan' => 2)); 1988 foreach (user_roles() as $rid => $name) { 1989 $edit_permissions = l(t('edit permissions'), 'admin/user/access/'. $rid); 1990 if (!in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) { 1991 $rows[] = array($name, l(t('edit role'), 'admin/user/roles/edit/'. $rid), $edit_permissions); 1992 } 1993 else { 1994 $rows[] = array($name, t('locked'), $edit_permissions); 1995 } 1996 } 1997 $rows[] = array(drupal_render($form['name']), array('data' => drupal_render($form['submit']), colspan => 2)); 1998 1999 $output = drupal_render($form); 2000 $output .= theme('table', $header, $rows); 2001 2002 return $output; 2003 } 2004 2005 function user_admin_account() { 2006 $filter = user_build_filter_query(); 2007 2008 $header = array( 2009 array(), 2010 array('data' => t('Username'), 'field' => 'u.name'), 2011 array('data' => t('Status'), 'field' => 'u.status'), 2012 t('Roles'), 2013 array('data' => t('Member for'), 'field' => 'u.created', 'sort' => 'desc'), 2014 array('data' => t('Last access'), 'field' => 'u.access'), 2015 t('Operations') 2016 ); 2017 2018 $sql = 'SELECT DISTINCT u.uid, u.name, u.status, u.created, u.access FROM {users} u LEFT JOIN {users_roles} ur ON u.uid = ur.uid '. $filter['join'] .' WHERE u.uid != 0 '. $filter['where']; 2019 $sql .= tablesort_sql($header); 2020 $result = pager_query($sql, 50, 0, NULL, $filter['args']); 2021 2022 $form['options'] = array( 2023 '#type' => 'fieldset', 2024 '#title' => t('Update options'), 2025 '#prefix' => '<div class="container-inline">', 2026 '#suffix' => '</div>', 2027 ); 2028 $options = array(); 2029 foreach (module_invoke_all('user_operations') as $operation => $array) { 2030 $options[$operation] = $array['label']; 2031 } 2032 $form['options']['operation'] = array( 2033 '#type' => 'select', 2034 '#options' => $options, 2035 '#default_value' => 'unblock', 2036 ); 2037 $form['options']['submit'] = array( 2038 '#type' => 'submit', 2039 '#value' => t('Update'), 2040 ); 2041 2042 $destination = drupal_get_destination(); 2043 2044 $status = array(t('blocked'), t('active')); 2045 $roles = user_roles(1); 2046 2047 while ($account = db_fetch_object($result)) { 2048 $accounts[$account->uid] = ''; 2049 $form['name'][$account->uid] = array('#value' => theme('username', $account)); 2050 $form['status'][$account->uid] = array('#value' => $status[$account->status]); 2051 $users_roles = array(); 2052 $roles_result = db_query('SELECT rid FROM {users_roles} WHERE uid = %d', $account->uid); 2053 while ($user_role = db_fetch_object($roles_result)) { 2054 $users_roles[] = $roles[$user_role->rid]; 2055 } 2056 asort($users_roles); 2057 $form['roles'][$account->uid][0] = array('#value' => theme('item_list', $users_roles)); 2058 $form['member_for'][$account->uid] = array('#value' => format_interval(time() - $account->created)); 2059 $form['last_access'][$account->uid] = array('#value' => $account->access ? t('@time ago', array('@time' => format_interval(time() - $account->access))) : t('never')); 2060 $form['operations'][$account->uid] = array('#value' => l(t('edit'), "user/$account->uid/edit", array(), $destination)); 2061 } 2062 $form['accounts'] = array( 2063 '#type' => 'checkboxes', 2064 '#options' => $accounts 2065 ); 2066 $form['pager'] = array('#value' => theme('pager', NULL, 50, 0)); 2067 2068 return $form; 2069 } 2070 2071 /** 2072 * Theme user administration overview. 2073 */ 2074 function theme_user_admin_account($form) { 2075 // Overview table: 2076 $header = array( 2077 theme('table_select_header_cell'), 2078 array('data' => t('Username'), 'field' => 'u.name'), 2079 array('data' => t('Status'), 'field' => 'u.status'), 2080 t('Roles'), 2081 array('data' => t('Member for'), 'field' => 'u.created', 'sort' => 'desc'), 2082 array('data' => t('Last access'), 'field' => 'u.access'), 2083 t('Operations') 2084 ); 2085 2086 $output = drupal_render($form['options']); 2087 if (isset($form['name']) && is_array($form['name'])) { 2088 foreach (element_children($form['name']) as $key) { 2089 $rows[] = array( 2090 drupal_render($form['accounts'][$key]), 2091 drupal_render($form['name'][$key]), 2092 drupal_render($form['status'][$key]), 2093 drupal_render($form['roles'][$key]), 2094 drupal_render($form['member_for'][$key]), 2095 drupal_render($form['last_access'][$key]), 2096 drupal_render($form['operations'][$key]), 2097 ); 2098 } 2099 } 2100 else { 2101 $rows[] = array(array('data' => t('No users available.'), 'colspan' => '7')); 2102 } 2103 2104 $output .= theme('table', $header, $rows); 2105 if ($form['pager']['#value']) { 2106 $output .= drupal_render($form['pager']); 2107 } 2108 2109 $output .= drupal_render($form); 2110 2111 return $output; 2112 } 2113 2114 /** 2115 * Submit the user administration update form. 2116 */ 2117 function user_admin_account_submit($form_id, $form_values) { 2118 $operations = module_invoke_all('user_operations'); 2119 $operation = $operations[$form_values['operation']]; 2120 // Filter out unchecked accounts. 2121 $accounts = array_filter($form_values['accounts']); 2122 if ($function = $operation['callback']) { 2123 // Add in callback arguments if present. 2124 if (isset($operation['callback arguments'])) { 2125 $args = array_merge(array($accounts), $operation['callback arguments']); 2126 } 2127 else { 2128 $args = array($accounts); 2129 } 2130 call_user_func_array($function, $args); 2131 2132 cache_clear_all('*', 'cache_menu', TRUE); 2133 drupal_set_message(t('The update has been performed.')); 2134 } 2135 } 2136 2137 function user_admin_account_validate($form_id, $form_values) { 2138 $form_values['accounts'] = array_filter($form_values['accounts']); 2139 if (count($form_values['accounts']) == 0) { 2140 form_set_error('', t('No users selected.')); 2141 } 2142 } 2143 2144 /** 2145 * Implementation of hook_user_operations(). 2146 */ 2147 function user_user_operations() { 2148 global $form_values; 2149 2150 $operations = array( 2151 'unblock' => array( 2152 'label' => t('Unblock the selected users'), 2153 'callback' => 'user_user_operations_unblock', 2154 ), 2155 'block' => array( 2156 'label' => t('Block the selected users'), 2157 'callback' => 'user_user_operations_block', 2158 ), 2159 'delete' => array( 2160 'label' => t('Delete the selected users'), 2161 ), 2162 ); 2163 2164 if (user_access('administer access control')) { 2165 $roles = user_roles(1); 2166 unset($roles[DRUPAL_AUTHENTICATED_RID]); // Can't edit authenticated role. 2167 2168 $add_roles = array(); 2169 foreach ($roles as $key => $value) { 2170 $add_roles['add_role-'. $key] = $value; 2171 } 2172 2173 $remove_roles = array(); 2174 foreach ($roles as $key => $value) { 2175 $remove_roles['remove_role-'. $key] = $value; 2176 } 2177 2178 if (count($roles)) { 2179 $role_operations = array( 2180 t('Add a role to the selected users') => array( 2181 'label' => $add_roles, 2182 ), 2183 t('Remove a role from the selected users') => array( 2184 'label' => $remove_roles, 2185 ), 2186 ); 2187 2188 $operations += $role_operations; 2189 } 2190 } 2191 2192 // If the form has been posted, we need to insert the proper data for role editing if necessary. 2193 if ($form_values) { 2194 $operation_rid = explode('-', $form_values['operation']); 2195 $operation = $operation_rid[0]; 2196 $rid = $operation_rid[1]; 2197 if ($operation == 'add_role' || $operation == 'remove_role') { 2198 if (user_access('administer access control')) { 2199 $operations[$form_values['operation']] = array( 2200 'callback' => 'user_multiple_role_edit', 2201 'callback arguments' => array($operation, $rid), 2202 ); 2203 } 2204 else { 2205 watchdog('security', t('Detected malicious attempt to alter protected user fields.'), WATCHDOG_WARNING); 2206 return; 2207 } 2208 } 2209 } 2210 2211 return $operations; 2212 } 2213 2214 /** 2215 * Callback function for admin mass unblocking users. 2216 */ 2217 function user_user_operations_unblock($accounts) { 2218 foreach ($accounts as $uid) { 2219 $account = user_load(array('uid' => (int)$uid)); 2220 // Skip unblocking user if they are already unblocked. 2221 if ($account !== FALSE && $account->status == 0) { 2222 user_save($account, array('status' => 1)); 2223 } 2224 } 2225 } 2226 2227 /** 2228 * Callback function for admin mass blocking users. 2229 */ 2230 function user_user_operations_block($accounts) { 2231 foreach ($accounts as $uid) { 2232 $account = user_load(array('uid' => (int)$uid)); 2233 // Skip blocking user if they are already blocked. 2234 if ($account !== FALSE && $account->status == 1) { 2235 user_save($account, array('status' => 0)); 2236 } 2237 } 2238 } 2239 2240 /** 2241 * Callback function for admin mass adding/deleting a user role. 2242 */ 2243 function user_multiple_role_edit($accounts, $operation, $rid) { 2244 // The role name is not necessary as user_save() will reload the user 2245 // object, but some modules' hook_user() may look at this first. 2246 $role_name = db_result(db_query('SELECT name FROM {role} WHERE rid = %d', $rid)); 2247 2248 switch ($operation) { 2249 case 'add_role': 2250 foreach ($accounts as $uid) { 2251 $account = user_load(array('uid' => (int)$uid)); 2252 // Skip adding the role to the user if they already have it. 2253 if ($account !== FALSE && !isset($account->roles[$rid])) { 2254 $roles = $account->roles + array($rid => $role_name); 2255 user_save($account, array('roles' => $roles)); 2256 } 2257 } 2258 break; 2259 case 'remove_role': 2260 foreach ($accounts as $uid) { 2261 $account = user_load(array('uid' => (int)$uid)); 2262 // Skip removing the role from the user if they already don't have it. 2263 if ($account !== FALSE && isset($account->roles[$rid])) { 2264 $roles = array_diff($account->roles, array($rid => $role_name)); 2265 user_save($account, array('roles' => $roles)); 2266 } 2267 } 2268 break; 2269 } 2270 } 2271 2272 function user_multiple_delete_confirm() { 2273 $edit = $_POST; 2274 2275 $form['accounts'] = array('#prefix' => '<ul>', '#suffix' => '</ul>', '#tree' => TRUE); 2276 // array_filter returns only elements with TRUE values 2277 foreach (array_filter($edit['accounts']) as $uid => $value) { 2278 $user = db_result(db_query('SELECT name FROM {users} WHERE uid = %d', $uid)); 2279 $form['accounts'][$uid] = array('#type' => 'hidden', '#value' => $uid, '#prefix' => '<li>', '#suffix' => check_plain($user) ."</li>\n"); 2280 } 2281 $form['operation'] = array('#type' => 'hidden', '#value' => 'delete'); 2282 2283 return confirm_form($form, 2284 t('Are you sure you want to delete these users?'), 2285 'admin/user/user', t('This action cannot be undone.'), 2286 t('Delete all'), t('Cancel')); 2287 } 2288 2289 function user_multiple_delete_confirm_submit($form_id, $form_values) { 2290 if ($form_values['confirm']) { 2291 foreach ($form_values['accounts'] as $uid => $value) { 2292 user_delete($form_values, $uid); 2293 } 2294 drupal_set_message(t('The users have been deleted.')); 2295 } 2296 return 'admin/user/user'; 2297 } 2298 2299 function user_admin_settings() { 2300 // User registration settings. 2301 $form['registration'] = array('#type' => 'fieldset', '#title' => t('User registration settings')); 2302 $form['registration']['user_register'] = array('#type' => 'radios', '#title' => t('Public registrations'), '#default_value' => variable_get('user_register', 1), '#options' => array(t('Only site administrators can create new user accounts.'), t('Visitors can create accounts and no administrator approval is required.'), t('Visitors can create accounts but administrator approval is required.'))); 2303 $form['registration']['user_email_verification'] = array('#type' => 'checkbox', '#title' => t('Require e-mail verification when a visitor creates an account'), '#default_value' => variable_get('user_email_verification', TRUE), '#description' => t('If this box is checked, new users will be required to validate their e-mail address prior to logging into to the site, and will be assigned a system-generated password. With it unchecked, users will be logged in immediately upon registering, and may select their own passwords during registration.')); 2304 $form['registration']['user_registration_help'] = array('#type' => 'textarea', '#title' => t('User registration guidelines'), '#default_value' => variable_get('user_registration_help', ''), '#description' => t("This text is displayed at the top of the user registration form. It's useful for helping or instructing your users.")); 2305 2306 // User e-mail settings. 2307 $form['email'] = array('#type' => 'fieldset', '#title' => t('User e-mail settings')); 2308 $form['email']['user_mail_welcome_subject'] = array('#type' => 'textfield', '#title' => t('Subject of welcome e-mail'), '#default_value' => _user_mail_text('welcome_subject'), '#maxlength' => 180, '#description' => t('Customize the subject of your welcome e-mail, which is sent to new members upon registering.') .' '. t('Available variables are:') .' !username, !site, !password, !uri, !uri_brief, !mailto, !date, !login_uri, !edit_uri, !login_url.'); 2309 $form['email']['user_mail_welcome_body'] = array('#type' => 'textarea', '#title' => t('Body of welcome e-mail'), '#default_value' => _user_mail_text('welcome_body'), '#rows' => 15, '#description' => t('Customize the body of the welcome e-mail, which is sent to new members upon registering.') .' '. t('Available variables are:') .' !username, !site, !password, !uri, !uri_brief, !mailto, !login_uri, !edit_uri, !login_url.'); 2310 $form['email']['user_mail_admin_subject'] = array('#type' => 'textfield', '#title' => t('Subject of welcome e-mail (user created by administrator)'), '#default_value' => _user_mail_text('admin_subject'), '#maxlength' => 180, '#description' => t('Customize the subject of your welcome e-mail, which is sent to new member accounts created by an administrator.') .' '. t('Available variables are:') .' !username, !site, !password, !uri, !uri_brief, !mailto, !date, !login_uri, !edit_uri, !login_url.'); 2311 $form['email']['user_mail_admin_body'] = array('#type' => 'textarea', '#title' => t('Body of welcome e-mail (user created by administrator)'), '#default_value' => _user_mail_text('admin_body'), '#rows' => 15, '#description' => t('Customize the body of the welcome e-mail, which is sent to new member accounts created by an administrator.') .' '. t('Available variables are:') .' !username, !site, !password, !uri, !uri_brief, !mailto, !login_uri, !edit_uri, !login_url.'); 2312 $form['email']['user_mail_approval_subject'] = array('#type' => 'textfield', '#title' => t('Subject of welcome e-mail (awaiting admin approval)'), '#default_value' => _user_mail_text('approval_subject'), '#maxlength' => 180, '#description' => t('Customize the subject of your awaiting approval welcome e-mail, which is sent to new members upon registering.') .' '. t('Available variables are:') .' !username, !site, !password, !uri, !uri_brief, !mailto, !date, !login_uri, !edit_uri, !login_url.'); 2313 $form['email']['user_mail_approval_body'] = array('#type' => 'textarea', '#title' => t('Body of welcome e-mail (awaiting admin approval)'), '#default_value' => _user_mail_text('approval_body'), '#rows' => 15, '#description' => t('Customize the body of the awaiting approval welcome e-mail, which is sent to new members upon registering.') .' '. t('Available variables are:') .' !username, !site, !password, !uri, !uri_brief, !mailto, !login_uri, !edit_uri, !login_url.'); 2314 $form['email']['user_mail_pass_subject'] = array('#type' => 'textfield', '#title' => t('Subject of password recovery e-mail'), '#default_value' => _user_mail_text('pass_subject'), '#maxlength' => 180, '#description' => t('Customize the subject of your forgotten password e-mail.') .' '. t('Available variables are:') .' !username, !site, !login_url, !uri, !uri_brief, !mailto, !date, !login_uri, !edit_uri.'); 2315 $form['email']['user_mail_pass_body'] = array('#type' => 'textarea', '#title' => t('Body of password recovery e-mail'), '#default_value' => _user_mail_text('pass_body'), '#rows' => 15, '#description' => t('Customize the body of the forgotten password e-mail.') .' '. t('Available variables are:') .' !username, !site, !login_url, !uri, !uri_brief, !mailto, !login_uri, !edit_uri.'); 2316 2317 // If picture support is enabled, check whether the picture directory exists: 2318 if (variable_get('user_pictures', 0)) { 2319 $picture_path = file_create_path(variable_get('user_picture_path', 'pictures')); 2320 file_check_directory($picture_path, 1, 'user_picture_path'); 2321 } 2322 2323 $form['pictures'] = array('#type' => 'fieldset', '#title' => t('Pictures')); 2324 $form['pictures']['user_pictures'] = array('#type' => 'radios', '#title' => t('Picture support'), '#default_value' => variable_get('user_pictures', 0), '#options' => array(t('Disabled'), t('Enabled')), '#description' => t('Enable picture support.')); 2325 $form['pictures']['user_picture_path'] = array('#type' => 'textfield', '#title' => t('Picture image path'), '#default_value' => variable_get('user_picture_path', 'pictures'), '#size' => 30, '#maxlength' => 255, '#description' => t('Subdirectory in the directory %dir where pictures will be stored.', array('%dir' => file_directory_path() .'/'))); 2326 $form['pictures']['user_picture_default'] = array('#type' => 'textfield', '#title' => t('Default picture'), '#default_value' => variable_get('user_picture_default', ''), '#size' => 30, '#maxlength' => 255, '#description' => t('URL of picture to display for users with no custom picture selected. Leave blank for none.')); 2327 $form['pictures']['user_picture_dimensions'] = array('#type' => 'textfield', '#title' => t('Picture maximum dimensions'), '#default_value' => variable_get('user_picture_dimensions', '85x85'), '#size' => 15, '#maxlength' => 10, '#description' => t('Maximum dimensions for pictures, in pixels.')); 2328 $form['pictures']['user_picture_file_size'] = array('#type' => 'textfield', '#title' => t('Picture maximum file size'), '#default_value' => variable_get('user_picture_file_size', '30'), '#size' => 15, '#maxlength' => 10, '#description' => t('Maximum file size for pictures, in kB.')); 2329 $form['pictures']['user_picture_guidelines'] = array('#type' => 'textarea', '#title' => t('Picture guidelines'), '#default_value' => variable_get('user_picture_guidelines', ''), '#description' => t("This text is displayed at the picture upload form in addition to the default guidelines. It's useful for helping or instructing your users.")); 2330 2331 return system_settings_form($form); 2332 } 2333 2334 function user_admin($callback_arg = '') { 2335 $op = isset($_POST['op']) ? $_POST['op'] : $callback_arg; 2336 2337 switch ($op) { 2338 case 'search': 2339 case t('Search'): 2340 $output = drupal_get_form('search_form', url('admin/user/search'), $_POST['keys'], 'user') . search_data($_POST['keys'], 'user'); 2341 break; 2342 case t('Create new account'): 2343 case 'create': 2344 $output = drupal_get_form('user_register'); 2345 break; 2346 default: 2347 if ($_POST['accounts'] && $_POST['operation'] == 'delete') { 2348 $output = drupal_get_form('user_multiple_delete_confirm'); 2349 } 2350 else { 2351 $output = drupal_get_form('user_filter_form'); 2352 $output .= drupal_get_form('user_admin_account'); 2353 } 2354 } 2355 return $output; 2356 } 2357 2358 /** 2359 * Implementation of hook_help(). 2360 */ 2361 function user_help($section) { 2362 global $user; 2363 2364 switch ($section) { 2365 case 'admin/help#user': 2366 $output = '<p>'. t('The user module allows users to register, login, and log out. Users benefit from being able to sign on because it associates content they create with their account and allows various permissions to be set for their roles. The user module supports user roles which can setup fine grained permissions allowing each role to do only what the administrator wants them to. Each user is assigned to one or more roles. By default there are two roles <em>anonymous</em> - a user who has not logged in, and <em>authenticated</em> a user who has signed up and who has been authorized.') .'</p>'; 2367 $output .= '<p>'. t('Users can use their own name or handle and can fine tune some personal configuration settings through their individual my account page. Registered users need to authenticate by supplying either a local username and password, or a remote username and password such as DelphiForums ID, or one from a Drupal powered website. A visitor accessing your website is assigned an unique ID, the so-called session ID, which is stored in a cookie. For security\'s sake, the cookie does not contain personal information but acts as a key to retrieve the information stored on your server.') .'</p>'; 2368 $output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="@user">User page</a>.', array('@user' => 'http://drupal.org/handbook/modules/user/')) .'</p>'; 2369 return $output; 2370 case 'admin/user/user': 2371 return '<p>'. t('Drupal allows users to register, login, log out, maintain user profiles, etc. Users of the site may not use their own names to post content until they have signed up for a user account.') .'</p>'; 2372 case 'admin/user/user/create': 2373 case 'admin/user/user/account/create': 2374 return '<p>'. t('This web page allows the administrators to register new users by hand. Note that you cannot have a user where either the e-mail address or the username match another user in the system.') .'</p>'; 2375 case 'admin/user/rules': 2376 return '<p>'. t('Set up username and e-mail address access rules for new <em>and</em> existing accounts (currently logged in accounts will not be logged out). If a username or e-mail address for an account matches any deny rule, but not an allow rule, then the account will not be allowed to be created or to log in. A host rule is effective for every page view, not just registrations.') .'</p>'; 2377 case 'admin/user/access': 2378 return '<p>'. t('Permissions let you control what users can do on your site. Each user role (defined on the <a href="@role">user roles page</a>) has its own set of permissions. For example, you could give users classified as "Administrators" permission to "administer nodes" but deny this power to ordinary, "authenticated" users. You can use permissions to reveal new features to privileged users (those with subscriptions, for example). Permissions also allow trusted users to share the administrative burden of running a busy site.', array('@role' => url('admin/user/roles'))) .'</p>'; 2379 case 'admin/user/roles': 2380 return t('<p>Roles allow you to fine tune the security and administration of Drupal. A role defines a group of users that have certain privileges as defined in <a href="@permissions">user permissions</a>. Examples of roles include: anonymous user, authenticated user, moderator, administrator and so on. In this area you will define the <em>role names</em> of the various roles. To delete a role choose "edit".</p><p>By default, Drupal comes with two user roles:</p> 2381 <ul> 2382 <li>Anonymous user: this role is used for users that don\'t have a user account or that are not authenticated.</li> 2383 <li>Authenticated user: this role is automatically granted to all logged in users.</li> 2384 </ul>', array('@permissions' => url('admin/user/access'))); 2385 case 'admin/user/search': 2386 return '<p>'. t('Enter a simple pattern ("*" may be used as a wildcard match) to search for a username. For example, one may search for "br" and Drupal might return "brian", "brad", and "brenda".') .'</p>'; 2387 case 'user/help#user': 2388 $site = variable_get('site_name', 'Drupal'); 2389 2390 $affiliates = user_auth_help_links(); 2391 if (count($affiliates)) { 2392 $affiliate_info = implode(', ', user_auth_help_links()); 2393 } 2394 else { 2395 $affiliate_info = t('one of our affiliates'); 2396 } 2397 2398 $output = t(' 2399 <h3>Distributed authentication<a id="da"></a></h3> 2400 <p>One of the more tedious moments in visiting a new website is filling out the registration form. Here at @site, you do not have to fill out a registration form if you are already a member of !affiliate-info. This capability is called <em>distributed authentication</em>, and <a href="@drupal">Drupal</a>, the software which powers @site, fully supports it.</p> 2401 <p>Distributed authentication enables a new user to input a username and password into the login box, and immediately be recognized, even if that user never registered at @site. This works because Drupal knows how to communicate with external registration databases. For example, lets say that new user \'Joe\' is already a registered member of <a href="@delphi-forums">Delphi Forums</a>. Drupal informs Joe on registration and login screens that he may login with his Delphi ID instead of registering with @site. Joe likes that idea, and logs in with a username of joe@remote.delphiforums.com and his usual Delphi password. Drupal then contacts the <em>remote.delphiforums.com</em> server behind the scenes (usually using <a href="@xml">XML-RPC</a>, <a href="@http-post">HTTP POST</a>, or <a href="@soap">SOAP</a>) and asks: "Is the password for user Joe correct?". If Delphi replies yes, then we create a new @site account for Joe and log him into it. Joe may keep on logging into @site in the same manner, and he will always be logged into the same account.</p>', array('!affiliate-info' => $affiliate_info, '@site' => $site, '@drupal' => 'http://drupal.org', '@delphi-forums' => 'http://www.delphiforums.com', '@xml' => 'http://www.xmlrpc.com', '@http-post' => 'http://www.w3.org/Protocols/', '@soap' => 'http://www.soapware.org')); 2402 2403 foreach (module_list() as $module) { 2404 if (module_hook($module, 'auth')) { 2405 $output .= "<h4><a id=\"$module\"></a>". module_invoke($module, 'info', 'name') .'</h4>'; 2406 $output .= module_invoke($module, 'help', "user/help#$module"); 2407 } 2408 } 2409 2410 return $output; 2411 } 2412 2413 } 2414 2415 /** 2416 * Menu callback; Prints user-specific help information. 2417 */ 2418 function user_help_page() { 2419 return user_help('user/help#user'); 2420 } 2421 2422 /** 2423 * Retrieve a list of all user setting/information categories and sort them by weight. 2424 */ 2425 function _user_categories($account) { 2426 $categories = array(); 2427 2428 foreach (module_list() as $module) { 2429 if ($data = module_invoke($module, 'user', 'categories', NULL, $account, '')) { 2430 $categories = array_merge($data, $categories); 2431 } 2432 } 2433 2434 usort($categories, '_user_sort'); 2435 2436 return $categories; 2437 } 2438 2439 function _user_sort($a, $b) { 2440 return $a['weight'] < $b['weight'] ? -1 : ($a['weight'] > $b['weight'] ? 1 : ($a['title'] < $b['title'] ? -1 : 1)); 2441 } 2442 2443 /** 2444 * Retrieve a list of all form elements for the specified category. 2445 */ 2446 function _user_forms(&$edit, $account, $category, $hook = 'form') { 2447 $groups = array(); 2448 foreach (module_list() as $module) { 2449 if ($data = module_invoke($module, 'user', $hook, $edit, $account, $category)) { 2450 $groups = array_merge_recursive($data, $groups); 2451 } 2452 } 2453 uasort($groups, '_user_sort'); 2454 2455 return empty($groups) ? FALSE : $groups; 2456 } 2457 2458 /** 2459 * Retrieve a pipe delimited string of autocomplete suggestions for existing users 2460 */ 2461 function user_autocomplete($string = '') { 2462 $matches = array(); 2463 if ($string) { 2464 $result = db_query_range("SELECT name FROM {users} WHERE LOWER(name) LIKE LOWER('%s%%')", $string, 0, 10); 2465 while ($user = db_fetch_object($result)) { 2466 $matches[$user->name] = check_plain($user->name); 2467 } 2468 } 2469 print drupal_to_js($matches); 2470 exit(); 2471 } 2472 2473 /** 2474 * List user administration filters that can be applied. 2475 */ 2476 function user_filters() { 2477 // Regular filters 2478 $filters = array(); 2479 $roles = user_roles(1); 2480 unset($roles[DRUPAL_AUTHENTICATED_RID]); // Don't list authorized role. 2481 if (count($roles)) { 2482 $filters['role'] = array('title' => t('role'), 2483 'where' => "ur.rid = %d", 2484 'options' => $roles, 2485 ); 2486 } 2487 2488 $options = array(); 2489 $t_module = t('module'); 2490 foreach (module_list() as $module) { 2491 if ($permissions = module_invoke($module, 'perm')) { 2492 asort($permissions); 2493 foreach ($permissions as $permission) { 2494 $options["$module $t_module"][$permission] = t($permission); 2495 } 2496 } 2497 } 2498 ksort($options); 2499 $filters['permission'] = array('title' => t('permission'), 2500 'join' => 'LEFT JOIN {permission} p ON ur.rid = p.rid', 2501 'where' => " ((p.perm IS NOT NULL AND p.perm LIKE '%%%s%%') OR u.uid = 1) ", 2502 'options' => $options, 2503 ); 2504 2505 $filters['status'] = array('title' => t('status'), 2506 'where' => 'u.status = %d', 2507 'options' => array(1 => t('active'), 0 => t('blocked')), 2508 ); 2509 return $filters; 2510 } 2511 2512 /** 2513 * Build query for user administration filters based on session. 2514 */ 2515 function user_build_filter_query() { 2516 $filters = user_filters(); 2517 2518 // Build query 2519 $where = $args = $join = array(); 2520 foreach ($_SESSION['user_overview_filter'] as $filter) { 2521 list($key, $value) = $filter; 2522 // This checks to see if this permission filter is an enabled permission for the authenticated role. 2523 // If so, then all users would be listed, and we can skip adding it to the filter query. 2524 if ($key == 'permission') { 2525 $account = new stdClass(); 2526 $account->uid = 'user_filter'; 2527 $account->roles = array(DRUPAL_AUTHENTICATED_RID => 1); 2528 if (user_access($value, $account)) { 2529 continue; 2530 } 2531 } 2532 $where[] = $filters[$key]['where']; 2533 $args[] = $value; 2534 $join[] = $filters[$key]['join']; 2535 } 2536 $where = count($where) ? 'AND '. implode(' AND ', $where) : ''; 2537 $join = count($join) ? ' '. implode(' ', array_unique($join)) : ''; 2538 2539 return array('where' => $where, 2540 'join' => $join, 2541 'args' => $args, 2542 ); 2543 } 2544 2545 /** 2546 * Return form for user administration filters. 2547 */ 2548 function user_filter_form() { 2549 $session = &$_SESSION['user_overview_filter']; 2550 $session = is_array($session) ? $session : array(); 2551 $filters = user_filters(); 2552 2553 $i = 0; 2554 $form['filters'] = array('#type' => 'fieldset', 2555 '#title' => t('Show only users where'), 2556 '#theme' => 'user_filters', 2557 ); 2558 foreach ($session as $filter) { 2559 list($type, $value) = $filter; 2560 // Merge an array of arrays into one if necessary. 2561 $options = $type == 'permission' ? call_user_func_array('array_merge', $filters[$type]['options']) : $filters[$type]['options']; 2562 $params = array('%property' => $filters[$type]['title'] , '%value' => $options[$value]); 2563 if ($i++ > 0) { 2564 $form['filters']['current'][] = array('#value' => t('<em>and</em> where <strong>%property</strong> is <strong>%value</strong>', $params)); 2565 } 2566 else { 2567 $form['filters']['current'][] = array('#value' => t('<strong>%property</strong> is <strong>%value</strong>', $params)); 2568 } 2569 } 2570 2571 foreach ($filters as $key => $filter) { 2572 $names[$key] = $filter['title']; 2573 $form['filters']['status'][$key] = array('#type' => 'select', 2574 '#options' => $filter['options'], 2575 ); 2576 } 2577 2578 $form['filters']['filter'] = array('#type' => 'radios', 2579 '#options' => $names, 2580 ); 2581 $form['filters']['buttons']['submit'] = array('#type' => 'submit', 2582 '#value' => (count($session) ? t('Refine') : t('Filter')) 2583 ); 2584 if (count($session)) { 2585 $form['filters']['buttons']['undo'] = array('#type' => 'submit', 2586 '#value' => t('Undo') 2587 ); 2588 $form['filters']['buttons']['reset'] = array('#type' => 'submit', 2589 '#value' => t('Reset') 2590 ); 2591 } 2592 2593 return $form; 2594 } 2595 2596 /** 2597 * Theme user administration filter form. 2598 */ 2599 function theme_user_filter_form($form) { 2600 $output = '<div id="user-admin-filter">'; 2601 $output .= drupal_render($form['filters']); 2602 $output .= '</div>'; 2603 $output .= drupal_render($form); 2604 return $output; 2605 } 2606 2607 /** 2608 * Theme user administration filter selector. 2609 */ 2610 function theme_user_filters($form) { 2611 $output = '<ul class="clear-block">'; 2612 if (sizeof($form['current'])) { 2613 foreach (element_children($form['current']) as $key) { 2614 $output .= '<li>'. drupal_render($form['current'][$key]) .'</li>'; 2615 } 2616 } 2617 2618 $output .= '<li><dl class="multiselect">'. (sizeof($form['current']) ? '<dt><em>'. t('and') .'</em> '. t('where') .'</dt>' : '') .'<dd class="a">'; 2619 foreach (element_children($form['filter']) as $key) { 2620 $output .= drupal_render($form['filter'][$key]); 2621 } 2622 $output .= '</dd>'; 2623 2624 $output .= '<dt>'. t('is') .'</dt><dd class="b">'; 2625 2626 foreach (element_children($form['status']) as $key) { 2627 $output .= drupal_render($form['status'][$key]); 2628 } 2629 $output .= '</dd>'; 2630 2631 $output .= '</dl>'; 2632 $output .= '<div class="container-inline" id="user-admin-buttons">'. drupal_render($form['buttons']) .'</div>'; 2633 $output .= '</li></ul>'; 2634 2635 return $output; 2636 } 2637 2638 /** 2639 * Process result from user administration filter form. 2640 */ 2641 function user_filter_form_submit($form_id, $form_values) { 2642 $op = $form_values['op']; 2643 $filters = user_filters(); 2644 switch ($op) { 2645 case t('Filter'): case t('Refine'): 2646 if (isset($form_values['filter'])) { 2647 $filter = $form_values['filter']; 2648 // Merge an array of arrays into one if necessary. 2649 $options = $filter == 'permission' ? call_user_func_array('array_merge', $filters[$filter]['options']) : $filters[$filter]['options']; 2650 if (isset($options[$form_values[$filter]])) { 2651 $_SESSION['user_overview_filter'][] = array($filter, $form_values[$filter]); 2652 } 2653 } 2654 break; 2655 case t('Undo'): 2656 array_pop($_SESSION['user_overview_filter']); 2657 break; 2658 case t('Reset'): 2659 $_SESSION['user_overview_filter'] = array(); 2660 break; 2661 case t('Update'): 2662 return; 2663 } 2664 2665 return 'admin/user/user'; 2666 } 2667 2668 2669 function user_forms() { 2670 $forms['user_admin_access_add_form']['callback'] = 'user_admin_access_form'; 2671 $forms['user_admin_access_edit_form']['callback'] = 'user_admin_access_form'; 2672 $forms['user_admin_new_role']['callback'] = 'user_admin_role'; 2673 return $forms; 2674 } 2675
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Fri Nov 30 16:20:15 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |