[ Index ]
 

Code source de Drupal 5.3

Accédez au Source d'autres logiciels libres

Classes | Fonctions | Variables | Constantes | Tables

title

Body

[fermer]

/modules/user/ -> user.module (source)

   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  


Généré le : Fri Nov 30 16:20:15 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics