user.module 83.5 KB
Newer Older
Dries's avatar
 
Dries committed
1 2 3 4 5 6
<?php
// $Id$

/*** Common functions ******************************************************/

function user_external_load($authname) {
Dries's avatar
 
Dries committed
7
  $result = db_query("SELECT uid FROM {authmap} WHERE authname = '%s'", $authname);
Dries's avatar
 
Dries committed
8

Dries's avatar
 
Dries committed
9 10
  if ($user = db_fetch_object($result)) {
    return user_load($user);
Dries's avatar
 
Dries committed
11 12 13 14 15 16 17 18 19 20 21
  }
  else {
    return 0;
  }
}

function user_load($array = array()) {
  /*
  ** Dynamically compose a SQL query:
  */

Dries's avatar
 
Dries committed
22 23
  $query = "";

Dries's avatar
 
Dries committed
24 25
  foreach ($array as $key => $value) {
    if ($key == "pass") {
Kjartan's avatar
Kjartan committed
26
      $query .= "u.$key = '". md5($value) ."' AND ";
27
    }
Dries's avatar
 
Dries committed
28
    else {
Dries's avatar
 
Dries committed
29
      $query .= "u.$key = '". check_query($value) ."' AND ";
Dries's avatar
 
Dries committed
30 31
    }
  }
Dries's avatar
 
Dries committed
32
  $result = db_query_range("SELECT u.*, r.name AS role FROM {role} r INNER JOIN {users} u ON r.rid = u.rid WHERE $query u.status < 3", 0, 1);
Dries's avatar
 
Dries committed
33 34

  $user = db_fetch_object($result);
Dries's avatar
 
Dries committed
35
  if ($user->data && $data = unserialize($user->data)) {
Dries's avatar
 
Dries committed
36 37 38 39 40 41
    foreach ($data as $key => $value) {
      if (!isset($user->$key)) {
        $user->$key = $value;
      }
    }
  }
Dries's avatar
 
Dries committed
42 43 44 45 46 47 48 49 50

  return $user;
}

function user_save($account, $array = array()) {
  /*
  ** Dynamically compose a SQL query:
  */

Kjartan's avatar
Kjartan committed
51
  $user_fields = user_fields();
Dries's avatar
 
Dries committed
52
  if ($account->uid) {
Dries's avatar
 
Dries committed
53
    $data = unserialize(db_result(db_query("SELECT data FROM {users} WHERE uid = %d", $account->uid)));
Dries's avatar
 
Dries committed
54 55
    foreach ($array as $key => $value) {
      if ($key == "pass") {
Dries's avatar
 
Dries committed
56 57
        $query .= "$key = '%s', ";
        $v[] = md5($value);
Dries's avatar
 
Dries committed
58 59
      }
      else if (substr($key, 0, 4) !== "auth") {
Kjartan's avatar
Kjartan committed
60
        if (in_array($key, $user_fields)) {
Dries's avatar
 
Dries committed
61 62
          // escape '%'s:
          $value = str_replace("%", "%%", $value);
Dries's avatar
 
Dries committed
63 64
          $query .= "$key = '%s', ";
          $v[] = $value;
Dries's avatar
 
Dries committed
65 66 67 68
        }
        else {
          $data[$key] = $value;
        }
Dries's avatar
 
Dries committed
69 70
      }
    }
Dries's avatar
 
Dries committed
71 72
    $query .= "data = '%s', ";
    $v[] = serialize($data);
Dries's avatar
 
Dries committed
73

Dries's avatar
 
Dries committed
74
    db_query("UPDATE {users} SET $query timestamp = %d WHERE uid = %d", array_merge($v, array(time(), $account->uid)));
Dries's avatar
 
Dries committed
75 76 77 78 79

    $user = user_load(array("uid" => $account->uid));
  }
  else {
    $array["timestamp"] = time();
Dries's avatar
 
Dries committed
80
    $array["uid"] = db_next_id("{users}_uid");
Dries's avatar
 
Dries committed
81 82 83 84

    foreach ($array as $key => $value) {
      if ($key == "pass") {
        $fields[] = check_query($key);
Dries's avatar
 
Dries committed
85 86
        $values[] = md5($value);
        $s[] = "'%s'";
Dries's avatar
 
Dries committed
87 88
      }
      else if (substr($key, 0, 4) !== "auth") {
Kjartan's avatar
Kjartan committed
89
        if (in_array($key, $user_fields)) {
Dries's avatar
 
Dries committed
90
          $fields[] = check_query($key);
Dries's avatar
 
Dries committed
91 92
          $values[] = $value;
          $s[] = "'%s'";
Dries's avatar
 
Dries committed
93 94 95 96
        }
        else {
          $data[$key] = $value;
        }
Dries's avatar
 
Dries committed
97 98 99
      }
    }

Dries's avatar
 
Dries committed
100
    $fields[] = "data";
Dries's avatar
 
Dries committed
101 102
    $values[] = serialize($data);
    $s[] = "'%s'";
Dries's avatar
 
Dries committed
103

Dries's avatar
 
Dries committed
104
    db_query("INSERT INTO {users} (". implode(", ", $fields) .") VALUES (". implode(", ", $s) .")", $values);
Dries's avatar
 
Dries committed
105 106 107 108 109 110 111 112 113 114 115

    $user = user_load(array("name" => $array["name"]));
  }

  foreach ($array as $key => $value) {
    if (substr($key, 0, 4) == "auth") {
      $authmaps[$key] = $value;
    }
  }

  if ($authmaps) {
Dries's avatar
 
Dries committed
116
    user_set_authmaps($user, $authmaps);
Dries's avatar
 
Dries committed
117 118 119 120 121 122 123 124 125 126
  }

  return $user;
}

function user_validate_name($name) {
  /*
  ** Verify the syntax of the given name:
  */

Dries's avatar
 
Dries committed
127
  if (!$name) return t("You must enter a username.");
Dries's avatar
 
Dries committed
128 129
  if (substr($name, 0, 1) == ' ') return t("The username cannot begin with a space.");
  if (substr($name, -1) == ' ') return t("The username cannot end with a space.");
Dries's avatar
 
Dries committed
130
  if (ereg("  ", $name)) return t("The username cannot contain multiple spaces in a row.");
Dries's avatar
 
Dries committed
131 132
  if (ereg('[^ [:alnum:]@_.-]', $name)) return t("The username contains an illegal character.");
  if (ereg('@', $name) && !eregi('@([0-9a-z](-?[0-9a-z])*.)+[a-z]{2}([zmuvtg]|fo|me)?$', $name)) return t("The username is not a valid authentication ID.");
Dries's avatar
 
Dries committed
133
  if (strlen($name) > 56) return t("The username '%name' is too long: it must be less than 56 characters.", array("%name" => $name));
Dries's avatar
 
Dries committed
134 135 136
}

function user_validate_mail($mail) {
Dries's avatar
 
Dries committed
137
  if ($mail && !valid_email_address($mail)) {
Dries's avatar
 
Dries committed
138
    return t("The e-mail address '%mail' is not valid.", array("%mail" => $mail));
Dries's avatar
 
Dries committed
139 140 141
  }
}

142
function user_validate_authmap($account, $authname, $module) {
Dries's avatar
 
Dries committed
143
  $result = db_query("SELECT COUNT(*) from {authmap} WHERE uid != %d AND authname = '%s'", $account->uid, $authname);
Dries's avatar
 
Dries committed
144 145 146 147
  if (db_result($result) > 0) {
    $name = module_invoke($module, "info", "name");
    return t("The %u ID %s is already taken.", array("%u" => ucfirst($name), "%s" => "<i>$authname</i>"));
  }
Dries's avatar
 
Dries committed
148 149
}

Dries's avatar
 
Dries committed
150
function user_password($length = 10) {
Dries's avatar
 
Dries committed
151
  /*
Dries's avatar
 
Dries committed
152
  ** Generate a random alphanumeric password.
Dries's avatar
 
Dries committed
153 154
  */

Dries's avatar
 
Dries committed
155 156 157 158 159 160 161 162 163
  // This variable contains the list of allowable characters for the
  // password.  Note that the number 0 and the letter 'O' have been
  // removed to avoid confusion between the two.  The same is true
  // of 'I' and 1.
  $allowable_characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789";
  // We see how many characters are in the allowable list:
  $len = strlen($allowable_characters);

  // Seed the random number generator with the microtime stamp:
Dries's avatar
 
Dries committed
164
  mt_srand((double)microtime() * 1000000);
Dries's avatar
 
Dries committed
165 166 167 168 169 170 171 172 173 174 175 176 177

  // Declare the password as a blank string:
  $pass = "";

  // Loop the number of times specified by $length:
  for ($i = 0; $i < $length; $i++) {

    // Each iteration, pick a random character from the
    // allowable string and append it to the password:
    $pass .= $allowable_characters[mt_rand(0, $len - 1)];
  }

  return $pass;
Dries's avatar
 
Dries committed
178 179 180 181
}

function user_access($string) {
  global $user;
Dries's avatar
 
Dries committed
182
  static $perm = 0;
Dries's avatar
 
Dries committed
183

Dries's avatar
 
Dries committed
184
  // User #1 has all priveleges:
Dries's avatar
 
Dries committed
185 186 187 188
  if ($user->uid == 1) {
    return 1;
  }

Dries's avatar
 
Dries committed
189 190 191 192
  /*
  ** To reduce the number of SQL queries, we cache the user's permissions
  ** in a static variable.
  */
Dries's avatar
 
Dries committed
193

Dries's avatar
 
Dries committed
194 195
  if ($perm === 0) {
    $perm = db_result(db_query("SELECT p.perm FROM {role} r, {permission} p WHERE r.rid = p.rid AND r.rid = %d", $user->rid), 0);
Dries's avatar
 
Dries committed
196 197
  }

Dries's avatar
 
Dries committed
198
  return strstr($perm, $string);
Dries's avatar
 
Dries committed
199 200 201 202 203
}

function user_mail($mail, $subject, $message, $header) {
  if (variable_get("smtp_library", "") && file_exists(variable_get("smtp_library", ""))) {
    include_once variable_get("smtp_library", "");
204
    return user_mail_wrapper($mail, $subject, $message, $header);
Dries's avatar
 
Dries committed
205 206
  }
  else {
207 208 209 210 211 212 213
    /*
    ** Note: if you are having problems with sending mail, or mails look wrong
    ** when they are recieved you may have to modify the str_replace to suit
    ** your systems.
    **  - \r\n will work under dos and windows.
    **  - \n will work for linux, unix and BSDs.
    **  - \r will work for macs.
Dries's avatar
 
Dries committed
214 215 216 217 218 219 220 221 222 223 224 225
    **
    ** According to RFC 2646, it's quite rude to not wrap your e-mails:
    **
    ** "The Text/Plain media type is the lowest common denominator of
    ** Internet email, with lines of no more than 997 characters (by
    ** convention usually no more than 80), and where the CRLF sequence
    ** represents a line break [MIME-IMT]."
    **
    ** CRLF === \r\n
    **
    ** http://www.rfc-editor.org/rfc/rfc2646.txt
    **
226
    */
Dries's avatar
 
Dries committed
227 228 229 230
    return mail(
      $mail,
      user_mail_encode($subject),
      str_replace("\r", "", $message),
Kjartan's avatar
Kjartan committed
231
      "MIME-Version: 1.0\nContent-type: text/plain; charset=UTF-8; format=flowed\nContent-transfer-encoding: 8Bit\n" . $header
Dries's avatar
 
Dries committed
232
    );
Dries's avatar
 
Dries committed
233 234 235
  }
}

Kjartan's avatar
Kjartan committed
236 237 238 239 240
function user_mail_encode($string, $charset = "UTF-8") {
  /*
  ** Used to encodes mail headers that contain non US- ASCII
  ** characters.
  ** http://www.rfc-editor.org/rfc/rfc2047.txt
Kjartan's avatar
Kjartan committed
241 242 243 244 245 246 247 248
  **
  ** Notes:
  **   - The chunks come in groupings of 4 bytes when using base64
  **     encoded.
  **   - trim() is used to ensure that no extra spacing is added by
  **     chunk_split() or preg_replace().
  **   - Using \n as the chunk separator may cause problems on some
  **     systems and may have to be changed to \r\n or \r.
Kjartan's avatar
Kjartan committed
249
  */
Kjartan's avatar
Kjartan committed
250 251 252
  $chunk_size = 75 - 7 - strlen($charset);
  $chunk_size -= $chunk_size % 4;
  $string = trim(chunk_split(base64_encode($string), $chunk_size, "\n"));
Kjartan's avatar
Kjartan committed
253 254
  $string = trim(preg_replace('/^(.*)$/m', " =?$charset?B?\\1?=", $string));
  return $string;
Dries's avatar
 
Dries committed
255 256
}

Dries's avatar
 
Dries committed
257
function user_deny($type, $mask) {
Dries's avatar
 
Dries committed
258 259
  $allow = db_fetch_object(db_query("SELECT * FROM {access} WHERE status = '1' AND type = '%s' AND LOWER('%s') LIKE LOWER(mask)", $type, $mask));
  $deny = db_fetch_object(db_query("SELECT * FROM {access} WHERE status = '0' AND type = '%s' AND LOWER('%s') LIKE LOWER(mask)", $type, $mask));
Dries's avatar
 
Dries committed
260

Dries's avatar
 
Dries committed
261
  return $deny && !$allow;
Dries's avatar
 
Dries committed
262 263
}

Dries's avatar
 
Dries committed
264 265
function user_fields() {
  static $fields;
Dries's avatar
 
Dries committed
266

Dries's avatar
 
Dries committed
267
  if (!$fields) {
Dries's avatar
 
Dries committed
268
    $result = db_query("SELECT * FROM {users} WHERE uid = 1");
Kjartan's avatar
Kjartan committed
269 270 271
    if (db_num_rows($result)) {
      $fields = array_keys(db_fetch_array($result));
    }
Dries's avatar
 
Dries committed
272 273 274 275
    else {
      // Make sure we return the default fields at least
      $fields = array("uid", "name", "pass", "mail", "mode", "sort", "threshold", "theme", "signature", "timestamp", "status", "timezone", "language", "init", "data", "rid");
    }
Dries's avatar
 
Dries committed
276
  }
Dries's avatar
 
Dries committed
277

Dries's avatar
 
Dries committed
278
  return $fields;
Dries's avatar
 
Dries committed
279 280
}

Dries's avatar
 
Dries committed
281 282 283
/*** Module hooks **********************************************************/

function user_perm() {
Dries's avatar
 
Dries committed
284
  return array("administer users", "access userlist");
Dries's avatar
 
Dries committed
285 286 287
}

function user_search($keys) {
Dries's avatar
 
Dries committed
288 289
  $find = array();
  $result = db_query_range("SELECT * FROM {users} WHERE name LIKE '%%%s%%'", $keys, 0, 20);
Dries's avatar
 
Dries committed
290
  while ($account = db_fetch_object($result)) {
Dries's avatar
 
Dries committed
291
    $find[] = array("title" => $account->name, "link" => (strstr(request_uri(), "admin") ? url("admin/user/edit/$account->uid") : url("user/view/$account->uid")), "user" => $account->name);
Dries's avatar
 
Dries committed
292 293 294 295
  }
  return $find;
}

Dries's avatar
 
Dries committed
296
function user_block($op = "list", $delta = 0) {
Dries's avatar
 
Dries committed
297 298
  global $user;

Dries's avatar
 
Dries committed
299
  if ($op == "list") {
Dries's avatar
 
Dries committed
300
     $blocks[0]["info"] = t("User login");
301
     $blocks[1]["info"] = t("Navigation");
302
     $blocks[2]["info"] = t("Who's new");
Dries's avatar
 
Dries committed
303
     $blocks[3]["info"] = t("Who's online");
304

305
     return $blocks;
306 307
  }
  else {
Dries's avatar
 
Dries committed
308 309
    switch ($delta) {
      case 0:
310
        if (!$user->uid) {
Dries's avatar
 
Dries committed
311 312 313 314 315 316 317 318 319
          /*
          ** For usability's sake, avoid showing two login forms on one
          ** page.
          */

          if (arg(0) == "user" && arg(1) != "view") {
            return;
          }

Dries's avatar
 
Dries committed
320 321
          $edit = $_POST["edit"];

Dries's avatar
 
Dries committed
322 323
          $output = "<div class=\"user-login-block\">\n";

324
          /*
Dries's avatar
Dries committed
325 326
          ** Save the referer.  We record where the user came from such
          ** that we/ can redirect him after having completed the login
327 328
          ** form.
          */
Dries's avatar
Dries committed
329

330
          if (empty($edit)) {
Dries's avatar
 
Dries committed
331
            $edit["destination"] = url($_GET["q"]);
332 333
          }
          // NOTE: special care needs to be taken because on pages with forms, such as node and comment submission pages, the $edit variable might already be set.
Dries's avatar
Dries committed
334

Dries's avatar
 
Dries committed
335 336 337
          $form = form_hidden("destination", $edit["destination"]);
          $form .= form_textfield(t("Username"), "name", $edit["name"], 15, 64);
          $form .= form_password(t("Password"), "pass", $pass, 15, 64);
Dries's avatar
 
Dries committed
338 339

          if (variable_get("user_remember", 0) == 0) {
Dries's avatar
 
Dries committed
340
            $form .= form_checkbox(t("Remember me"), "remember_me", 1, 0, 0);
Dries's avatar
 
Dries committed
341 342
          }
          elseif (variable_get("user_remember", 1) == 1) {
Dries's avatar
 
Dries committed
343
            $form .= form_hidden("remember_me", 1);
Dries's avatar
 
Dries committed
344
          }
345

Dries's avatar
 
Dries committed
346 347 348 349 350
          $form .= form_submit(t("Log in"));

          $output .= form($form, "post", url("user/login"));

          $output .= "</div>\n";
Dries's avatar
 
Dries committed
351

Dries's avatar
 
Dries committed
352
          if (variable_get("user_register", 1)) {
Dries's avatar
 
Dries committed
353
            $items[] = l(t("Create new account"), "user/register", array("title" => t("Create a new user account.")));
Dries's avatar
 
Dries committed
354
          }
Dries's avatar
 
Dries committed
355
          $items[] = l(t("Request new password"), "user/password", array("title" => t("Request new password via e-mail.")));
Dries's avatar
 
Dries committed
356

Dries's avatar
 
Dries committed
357
          $output .= theme("item_list", $items);
358

Dries's avatar
 
Dries committed
359
          $block["subject"] = t("User login");
Dries's avatar
 
Dries committed
360
          $block["content"] = "<div class=\"user-login-link\">$output</div>";
Dries's avatar
 
Dries committed
361
        }
Dries's avatar
Dries committed
362
        return $block;
363
      case 1:
Dries's avatar
 
Dries committed
364 365
        if ($menu = menu_tree()) {
           $block["subject"] = $user->uid ? $user->name : t("Navigation");
Dries's avatar
 
Dries committed
366
           $block["content"] = "<div class=\"menu\">". $menu ."</div>";
Dries's avatar
 
Dries committed
367 368
        }

369
        return $block;
Dries's avatar
 
Dries committed
370
      case 2:
371 372 373 374 375
        if (user_access("access content")) {
          $result = db_query_range("SELECT uid, name FROM {users} WHERE status != '0' ORDER BY uid DESC", 0, 5);
          while ($account = db_fetch_object($result)) {
            $items[] = l((strlen($account->name) > 15 ? substr($account->name, 0, 15) . '...' : $account->name), "user/view/$account->uid");
          }
Dries's avatar
 
Dries committed
376

Dries's avatar
 
Dries committed
377
          $output = theme("user_list", $items);
Dries's avatar
 
Dries committed
378

379 380 381 382
          $block["subject"] = t("Who's new");
          $block["content"] = $output;
          return $block;
        }
Dries's avatar
 
Dries committed
383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430
      case 3:
        if (user_access("access content")) {
          /* utilize auto-throttle to disable when this site is too busy */
          if (function_exists("throttle_status"))
            $throttle = throttle_status();
          else
            $throttle = 0;

          /* be sure the site isn't too busy prior to performing db queries */
          if ($throttle < 5) {
            /* count users with activity in the past defined period */
            $time_period = variable_get("user_block_seconds_online", 2700);

            /* perform database queries to gather online user lists */
            $guests = db_fetch_object(db_query("SELECT COUNT(DISTINCT sid) AS count FROM {sessions} WHERE timestamp >= %d AND uid = 0", time() - $time_period));
            $users = db_query("SELECT DISTINCT uid, MAX(timestamp) AS max_timestamp FROM {sessions} WHERE timestamp >= %d AND uid != 0 GROUP BY uid ORDER BY max_timestamp DESC", time() - $time_period );
            $total_users = db_affected_rows();

            /* format the output with proper grammar */
            if ($total_users == 1 && $guests->count == 1) {
              $output = t("There is currently %members and %visitors online.", array("%members" => format_plural($total_users, "1 user", "%count users"), "%visitors" => format_plural($guests->count, "1 guest", "%count guests")));
            }
            else {
              $output = t("There are currently %members and %visitors online.", array("%members" => format_plural($total_users, "1 user", "%count users"), "%visitors" => format_plural($guests->count, "1 guest", "%count guests")));
            }

            if (user_access("access userlist") && $total_users) {
              /* Display a list of currently online users */
              $max_users = variable_get("user_block_max_list_count", 10);
              $items = array();
              while ($uid = db_fetch_object($users)) {
                $items[] = format_name(user_load(array("uid" => $uid->uid)));
              }

              if ($items) {
                $output .= "<br /><br />";
                $output .= theme("item_list", $items, t("Online users:"));
              }
            }
          }
          else {
            /* the site is too busy -- display a simple "too busy" message */
            $output = t("This site is currently sustaining more than %total page views a minute.", array("%total" => ($throttle * variable_get("statistics_throttle_multiplier", 60))));
          }
          $block["subject"] = t("Who's online");
          $block["content"] = $output;
          return $block;
        }
Dries's avatar
 
Dries committed
431 432
    }
  }
433 434
}

Dries's avatar
 
Dries committed
435
function theme_user_list($items, $title = NULL) {
Dries's avatar
 
Dries committed
436
  return theme("item_list", $items, $title);
Dries's avatar
 
Dries committed
437 438
}

Dries's avatar
 
Dries committed
439
function user_link($type) {
Dries's avatar
 
Dries committed
440 441 442

  $links = array();

Dries's avatar
 
Dries committed
443
  if ($type == "page") {
444
    $links[] = l(t("my account"), "user", array("title" => t("Create a user account, request a new password or edit your account settings.")));
Dries's avatar
 
Dries committed
445 446
  }

Dries's avatar
 
Dries committed
447
  if ($type == "system") {
Dries's avatar
Dries committed
448 449
    global $user;
    if ($user->uid) {
Dries's avatar
 
Dries committed
450 451 452
      menu("user", t("my account"), "user_page", 8);
      menu("user/edit", t("edit account"), "user_page", 0);
      menu("user/logout", t("log out"), "user_page", 10);
Dries's avatar
Dries committed
453
    }
Dries's avatar
 
Dries committed
454 455 456
    else {
      menu("user", t("my account"), "user_page", 8, 1);
    }
Dries's avatar
 
Dries committed
457

Dries's avatar
 
Dries committed
458
    if (user_access("administer users")) {
Dries's avatar
 
Dries committed
459 460 461
      menu("admin/user", t("accounts"), "user_admin", 2);
      menu("admin/user/create", t("new user"), "user_admin", 1);
      menu("admin/user/access", t("access rules"), NULL, 3);
462 463
      menu("admin/user/access/mail", t("e-mail rules"), "user_admin");
      menu("admin/user/access/user", t("name rules"), "user_admin");
Dries's avatar
 
Dries committed
464 465 466
      menu("admin/user/role", t("roles"), "user_admin", 4);
      menu("admin/user/permission", t("permissions"), "user_admin", 5);
      menu("admin/user/search", t("search"), "user_admin", 8);
Dries's avatar
 
Dries committed
467
      menu("admin/user/help", t("help"), "user_help_page", 9);
Dries's avatar
 
Dries committed
468
      menu("admin/user/edit", t("edit user account"), "user_admin", 0, 1); // hidden menu
Dries's avatar
 
Dries committed
469
    }
Dries's avatar
 
Dries committed
470 471
  }

Dries's avatar
 
Dries committed
472
  return $links;
Dries's avatar
 
Dries committed
473 474 475 476
}

/*** Authentication methods ************************************************/

477
function user_get_authname($account, $module) {
Dries's avatar
 
Dries committed
478 479

  /*
480
  **  Called by authentication modules in order to edit/view their authmap information.
Dries's avatar
 
Dries committed
481 482
  */

Dries's avatar
 
Dries committed
483
  $result = db_query("SELECT authname FROM {authmap} WHERE uid = %d AND module = '%s'", $account->uid, $module);
484 485 486
  return db_result($result);
}

Dries's avatar
 
Dries committed
487

488 489 490 491 492 493 494
function user_get_authmaps($authname = NULL) {

  /*
  ** Accepts an user object, $account, or an DA name and returns an
  ** associtive array of modules and DA names. Called at external login.
  */

Dries's avatar
 
Dries committed
495
  $result = db_query("SELECT authname, module FROM {authmap} WHERE authname = '%s'", $authname);
Dries's avatar
 
Dries committed
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510
  if (db_num_rows($result) > 0) {
    while ($authmap = db_fetch_object($result)) {
      $authmaps[$authmap->module] = $authmap->authname;
    }
    return $authmaps;
  }
  else {
    return 0;
  }
}

function user_set_authmaps($account, $authmaps) {
  foreach ($authmaps as $key => $value) {
    $module = explode("_", $key, 2);
    if ($value) {
Dries's avatar
 
Dries committed
511 512 513
      db_query("UPDATE {authmap} SET authname = '%s' WHERE uid = %d AND module = '%s'", $value, $account->uid, $module["1"]);
      if (!db_affected_rows()) {
        db_query("INSERT INTO {authmap} (authname, uid, module) VALUES ('%s', %d, '%s')", $value, $account->uid, $module[1]);
Dries's avatar
 
Dries committed
514 515 516
      }
    }
    else {
Dries's avatar
 
Dries committed
517
      db_query("DELETE FROM {authmap} WHERE uid = %d AND module = '%s'", $account->uid, $module["1"]);
Dries's avatar
 
Dries committed
518 519 520 521 522
    }
  }
}

function user_auth_help_links() {
523
  $links = array();
Dries's avatar
 
Dries committed
524
  foreach (module_list() as $module) {
Dries's avatar
 
Dries committed
525
    if (module_hook($module, "auth")) {
Dries's avatar
 
Dries committed
526
      $links[] = l(module_invoke($module, "info", "name"), "user/help#$module");
Dries's avatar
 
Dries committed
527 528 529 530 531 532 533
    }
  }
  return $links;
}

/*** User features *********************************************************/

Dries's avatar
 
Dries committed
534
function user_login($edit = array(), $msg = "") {
Dries's avatar
 
Dries committed
535
  global $user, $base_url;
Dries's avatar
 
Dries committed
536 537 538 539 540 541

  /*
  ** If we are already logged on, go to the user page instead.
  */

  if ($user->uid) {
Dries's avatar
 
Dries committed
542
    drupal_goto(url("user"));
Dries's avatar
 
Dries committed
543 544 545
  }

  if (user_deny("user", $edit["name"])) {
Dries's avatar
 
Dries committed
546
    $error = t("The name '%s' has been denied access.", array("%s" => $edit["name"]));
Dries's avatar
 
Dries committed
547 548 549 550
  }
  else if ($edit["name"] && $edit["pass"]) {

    /*
Dries's avatar
 
Dries committed
551
    ** Try to log in the user locally:
Dries's avatar
 
Dries committed
552 553
    */

Dries's avatar
 
Dries committed
554
    if (!$user->uid) {
555 556
      $name = $edit["name"];
      $pass = $edit["pass"];
Dries's avatar
 
Dries committed
557 558 559 560 561 562 563 564
      $user = user_load(array("name" => $name, "pass" => $pass, "status" => 1));
    }

    /*
    ** Strip name and server from ID:
    */

    if ($server = strrchr($edit["name"], "@")) {
565 566 567
      $name = substr($edit["name"], 0, strlen($edit["name"]) - strlen($server));
      $server = substr($server, 1);
      $pass = $edit["pass"];
Dries's avatar
 
Dries committed
568
    }
Dries's avatar
 
Dries committed
569

Dries's avatar
 
Dries committed
570
    /*
Dries's avatar
 
Dries committed
571
    ** When possible, determine corresponding external auth source. Invoke source, and login user if successful:
Dries's avatar
 
Dries committed
572 573
    */

Dries's avatar
 
Dries committed
574
    if (!$user->uid && $server && $result = user_get_authmaps("$name@$server")) {
Dries's avatar
 
Dries committed
575 576
      if (module_invoke(key($result), "auth", $name, $pass, $server)) {
        $user = user_external_load("$name@$server");
Dries's avatar
 
Dries committed
577
        watchdog("user", "external load: $name@$server, module: ". key($result));
Dries's avatar
 
Dries committed
578 579
      }
      else {
Dries's avatar
 
Dries committed
580
        $error = t("Invalid password for %s.", array("%s" => "<i>$name@$server</i>"));
Dries's avatar
 
Dries committed
581 582 583 584 585 586 587
      }
    }

     /*
    ** Try each external authentication source in series. Register user if successful.
    */

Dries's avatar
 
Dries committed
588
    else if (!$user->uid && $server) {
Dries's avatar
 
Dries committed
589 590 591 592
      foreach (module_list() as $module) {
        if (module_hook($module, "auth")) {
          if (module_invoke($module, "auth", $name, $pass, $server)) {
            if (variable_get("user_register", 1) == 1 && !user_load(array("name" => "$name@$server"))) { //register this new user
Dries's avatar
Dries committed
593
              $user = user_save("", array("name" => "$name@$server", "pass" => user_password(), "init" => "$name@$server", "status" => 1, "authname_$module" => "$name@$server", "rid" => _user_authenticated_id()));
Dries's avatar
 
Dries committed
594
              watchdog("user", "new user: $name@$server ($module ID)", l(t("edit user"), "admin/user/edit/$user->uid"));
Dries's avatar
 
Dries committed
595 596 597 598 599 600 601 602 603 604
              break;
            }
          }
        }
      }
    }

    if ($user->uid) {
      watchdog("user", "session opened for '$user->name'");

Dries's avatar
 
Dries committed
605 606
      // update the user table timestamp noting user has logged in
      db_query("UPDATE {users} SET timestamp = '%d' WHERE uid = '%s'", time(), $user->uid);
Dries's avatar
 
Dries committed
607 608 609 610 611 612

      /*
      ** If the user wants to be remembered, set the proper cookie such
      ** that the session won't expire.
      */

Dries's avatar
 
Dries committed
613
      $path = preg_replace("/.+\/\/[^\/]+(.*)/", "\$1/", $base_url);
Dries's avatar
 
Dries committed
614
      if ($edit["remember_me"]) {
Dries's avatar
 
Dries committed
615
        setcookie(session_name(), session_id(), time() + 3600 * 24 * 365, $path);
Dries's avatar
 
Dries committed
616
      }
Dries's avatar
 
Dries committed
617
      else {
Dries's avatar
 
Dries committed
618
        setcookie(session_name(), session_id(), FALSE, $path);
Dries's avatar
 
Dries committed
619 620 621
      }

      /*
Dries's avatar
 
Dries committed
622
      ** Redirect the user to the page he logged on from.
Dries's avatar
 
Dries committed
623 624
      */

Dries's avatar
 
Dries committed
625
      drupal_goto($edit["destination"]);
Dries's avatar
 
Dries committed
626 627 628
    }
    else {
      if (!$error) {
Dries's avatar
 
Dries committed
629
        $error = t("Sorry.  Unrecognized username or password.") ." ". l(t("Have you forgotten your password?"), "user/password");
Dries's avatar
 
Dries committed
630 631 632 633 634 635 636 637 638 639 640 641 642 643 644
      }
      if ($server) {
        watchdog("user", "failed login for '$name@$server': $error");
      }
      else {
        watchdog("user", "failed login for '$name': $error");
      }
    }
  }

  /*
  ** Display error message (if any):
  */

  if ($error) {
Dries's avatar
 
Dries committed
645
    $output .= theme("error", $error);
Dries's avatar
 
Dries committed
646 647
  }

Dries's avatar
 
Dries committed
648
  /*
Dries's avatar
 
Dries committed
649
  ** Save the referrer.  We record where the user came from such that we
Dries's avatar
 
Dries committed
650 651 652
  ** can redirect him after having completed the login form.
  */

653
  if (empty($edit)) {
Dries's avatar
 
Dries committed
654
    $edit["destination"] = url($_GET["q"]);
Dries's avatar
 
Dries committed
655 656 657
  }
  $output .= form_hidden("destination", $edit["destination"]);

Dries's avatar
 
Dries committed
658 659 660 661
  /*
  ** Display login form:
  */

Dries's avatar
 
Dries committed
662 663 664
  if ($msg) {
    $output .= "<p>$msg</p>";
  }
Dries's avatar
 
Dries committed
665
  if (count(user_auth_help_links()) > 0) {
Dries's avatar
 
Dries committed
666
    $output .= form_textfield(t("Username"), "name", $edit["name"], 30, 64, t("Enter your %s username, or an ID from one of our affiliates: %a.", array("%s" => variable_get("site_name", "local"), "%a" => implode(", ", user_auth_help_links()))));
Dries's avatar
 
Dries committed
667 668
  }
  else {
Dries's avatar
 
Dries committed
669
    $output .= form_textfield(t("Username"), "name", $edit["name"], 30, 64, t("Enter your %s username.", array("%s" => variable_get("site_name", "local"))));
Dries's avatar
 
Dries committed
670
  }
Dries's avatar
 
Dries committed
671
  $output .= form_password(t("Password"), "pass", $pass, 30, 64, t("Enter the password that accompanies your username."));
672
  $output .= form_checkbox(t("Remember me"), "remember_me", 1, 0, 0);
Dries's avatar
 
Dries committed
673
  $output .= form_submit(t("Log in"));
Dries's avatar
 
Dries committed
674
  $items[] = l(t("Request new password"), "user/password");
675
  if (variable_get("user_register", 1)) {
Dries's avatar
 
Dries committed
676
    $items[] = l(t("Create new account"), "user/register");
677
  }
Dries's avatar
 
Dries committed
678
  $output .= theme("item_list", $items);
Dries's avatar
 
Dries committed
679

Dries's avatar
 
Dries committed
680
  return form($output, "post", url("user"));
Dries's avatar
 
Dries committed
681 682
}

683
function _user_authenticated_id() {
Dries's avatar
 
Dries committed
684
  return db_result(db_query("SELECT rid FROM {role} WHERE name = 'authenticated user'"));
685 686
}

Dries's avatar
 
Dries committed
687 688 689 690 691 692 693 694 695 696 697 698 699 700
function user_logout() {
  global $user;

  if ($user->uid) {
    watchdog("user", "session closed for user '$user->name'");

    /*
    ** Destroy the current session:
    */

    session_destroy();
    unset($user);
  }

Dries's avatar
 
Dries committed
701
  drupal_goto(url());
Dries's avatar
 
Dries committed
702 703 704
}

function user_pass($edit = array()) {
Dries's avatar
 
Dries committed
705 706
  global $base_url;

Kjartan's avatar
Kjartan committed
707
  if ($edit["name"]) {
Dries's avatar
 
Dries committed
708
    $account = db_fetch_object(db_query("SELECT uid, name, mail FROM {users} WHERE name = '%s'", $edit["name"]));
Dries's avatar
 
Dries committed
709
    if (!$account) $error = t("Sorry. The username <i>%s</i> is not recognized.", array("%s" => $edit["name"]));
710
  }
Kjartan's avatar
Kjartan committed
711
  else if ($edit["mail"]) {
Dries's avatar
 
Dries committed
712
    $account = db_fetch_object(db_query("SELECT uid, name, mail FROM {users} WHERE mail = '%s'", $edit["mail"]));
Dries's avatar
 
Dries committed
713
    if (!$account) $error = t("Sorry. The e-mail address <i>%s</i> is not recognized.", array("%s" => $edit["mail"]));
Kjartan's avatar
Kjartan committed
714 715
  }
  if ($account) {
Dries's avatar
 
Dries committed
716

717
      $from = variable_get("site_mail", ini_get("sendmail_from"));
Dries's avatar
 
Dries committed
718 719 720 721 722 723 724 725 726 727 728 729
      $pass = user_password();

      /*
      ** Save new password:
      */

      user_save($account, array("pass" => $pass));

      /*
      ** Mail new password:
      */

Dries's avatar
 
Dries committed
730
      $variables = array("%username" => $account->name, "%site" => variable_get("site_name", "drupal"), "%password" => $pass, "%uri" => $base_url, "%uri_brief" => substr($base_url, strlen("http://")), "%mailto" => $account->mail, "%date" => format_date(time()));
Dries's avatar
 
Dries committed
731 732
      $subject = strtr(variable_get("user_mail_pass_subject", _user_mail_text("pass_subject")), $variables);
      $body = strtr(variable_get("user_mail_pass_body", _user_mail_text("pass_body")), $variables);
733
      $headers = "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from";
Dries's avatar
 
Dries committed
734
      $mail_success = user_mail($account->mail, $subject, $body, $headers);
Dries's avatar
 
Dries committed
735

Dries's avatar
 
Dries committed
736 737 738 739 740 741 742 743
      if ($mail_success) {
        watchdog("user", "mail password: '". $account->name ."' &lt;". $account->mail ."&gt;");
        return t("Your password and further instructions have been sent to your e-mail address.");
      }
      else {
        watchdog("error", "error mailing new password: '". $account->name ."' &lt;". $account->mail ."&gt;");
        return t("Unable to send mail. Please contact the site admin.");
      }
Dries's avatar
 
Dries committed
744 745
    }
    else {
746

Kjartan's avatar
Kjartan committed
747 748
    // Display error message if necessary.
    if ($error) {
Dries's avatar
 
Dries committed
749
      $output .= theme("error", $error);
Dries's avatar
 
Dries committed
750 751 752 753 754 755
    }

    /*
    ** Display form:
    */

Dries's avatar
 
Dries committed
756
    $output .= "<p>". sprintf(t("Enter your username %sor%s your e-mail address."), "<b><i>", "</i></b>") ."</p>";
Dries's avatar
 
Dries committed
757 758 759
    $output .= form_textfield(t("Username"), "name", $edit["name"], 30, 64);
    $output .= form_textfield(t("E-mail address"), "mail", $edit["mail"], 30, 64);
    $output .= form_submit(t("E-mail new password"));
Dries's avatar
 
Dries committed
760
    $items[] = l(t("Log in"), "user/login");
761
    if (variable_get("user_register", 1)) {
Dries's avatar
 
Dries committed
762
      $items[] = l(t("Create new account"), "user/register");
763
    }
Dries's avatar
 
Dries committed
764
    $output .= theme("item_list", $items);
Dries's avatar
 
Dries committed
765

Dries's avatar
 
Dries committed
766
    return form($output, "post", url("user"));
Dries's avatar
 
Dries committed
767 768 769 770
  }
}

function user_register($edit = array()) {
Dries's avatar
 
Dries committed
771
  global $user, $base_url;
772 773 774 775 776 777

  /*
  ** If we are already logged on, go to the user page instead.
  */

  if ($user->uid) {
Dries's avatar
 
Dries committed
778
    drupal_goto(url("user/edit"));
779
  }
Dries's avatar
 
Dries committed
780 781 782 783 784 785 786 787 788

  if ($edit["name"] && $edit["mail"]) {
    if ($error = user_validate_name($edit["name"])) {
      // do nothing
    }
    else if ($error = user_validate_mail($edit["mail"])) {
      // do nothing
    }
    else if (user_deny("user", $edit["name"])) {
Dries's avatar
 
Dries committed
789
      $error = t("The name '%s' has been denied access.", array("%s" => $edit["name"]));
Dries's avatar
 
Dries committed
790 791
    }
    else if (user_deny("mail", $edit["mail"])) {
Dries's avatar
 
Dries committed
792
      $error = t("The e-mail address '%s' has been denied access.", array("%s" => $edit["mail"]));
Dries's avatar
 
Dries committed
793
    }
Dries's avatar
 
Dries committed
794
    else if (db_num_rows(db_query("SELECT name FROM {users} WHERE LOWER(name) = LOWER('%s')", $edit["name"])) > 0) {
Dries's avatar
 
Dries committed
795
      $error = t("The name '%s' is already taken.", array("%s" => $edit["name"]));
Dries's avatar
 
Dries committed
796
    }
Dries's avatar
 
Dries committed
797
    else if (db_num_rows(db_query("SELECT mail FROM {users} WHERE LOWER(mail) = LOWER('%s') OR LOWER(init) = LOWER('%s')", $edit["mail"], $edit["mail"])) > 0) {
Dries's avatar
 
Dries committed
798
      $error = t("The e-mail address '%s' is already taken.", array("%s" => $edit["mail"]));
Dries's avatar
 
Dries committed
799
    }
Dries's avatar
 
Dries committed
800
    else if (variable_get("user_register", 1) == 0) {
Dries's avatar
 
Dries committed
801 802 803
      $error = t("Public registrations have been disabled by the site administrator.");
    }
    else {
Dries's avatar
 
Dries committed
804 805 806 807 808 809 810 811 812 813 814 815 816 817 818
      foreach (module_list() as $module) {
        if (module_hook($module, "user")) {
          $result = module_invoke($module, "user", "register_validate", $edit, $user);
          if (is_array($result)) {
            $data = array_merge($data, $result);
          }
          elseif (is_string($result)) {
            $error = $result;
            break;
          }
        }
      }
      if (!$error) {
        $success = 1;
      }
Dries's avatar
 
Dries committed
819 820 821 822 823
    }
  }

  if ($success) {

824
    $from = variable_get("site_mail", ini_get("sendmail_from"));
Dries's avatar
 
Dries committed
825 826
    $pass = user_password();

827
    // create new user account, noting whether administrator approval is required
828 829 830
    user_role_init();
    // TODO: is this necessary? Won't session_write replicate this?
    unset($edit["session"]);
831
    $account = user_save("", array_merge(array("name" => $edit["name"], "pass" => $pass, "init" => $edit["mail"], "mail" => $edit["mail"], "rid" => _user_authenticated_id(), "status" => (variable_get("user_register", 1) == 1 ? 1 : 0)), $data));
Dries's avatar
 
Dries committed
832
    watchdog("user", "new user: '". $edit["name"] ."' &lt;". $edit["mail"] ."&gt;", l(t("edit user"), "admin/user/edit/$account->uid"));
Dries's avatar
 
Dries committed
833

Dries's avatar
 
Dries committed
834
    $variables = array("%username" => $edit["name"], "%site" => variable_get("site_name", "drupal"), "%password" => $pass, "%uri" => $base_url, "%uri_brief" => substr($base_url, strlen("http://")), "%mailto" => $edit["mail"], "%date" => format_date(time()));
835

Dries's avatar
 
Dries committed
836
    //the first user may login immediately, and receives a customized welcome e-mail.
837
    if ($account->uid == 1) {
Dries's avatar
 
Dries committed
838
      user_mail($edit["mail"], t("drupal user account details for %s", array("%s" => $edit["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". url("user/edit") ."\n\n--drupal"), $variables), "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from");
839
      // This should not be t()'ed. No point as its only shown once in the sites lifetime, and it would be bad to store the password
Dries's avatar
 
Dries committed
840
      $output .= "<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 configure your e-mail settings using the Administration pages.</p><p> Your password is <b>$pass</b>. You may change your password on the next page.</p><p>Please login below.</p>";
Dries's avatar
 
Dries committed
841
      $output .= form_hidden("destination", url("user/edit"));
842
      $output .= form_hidden("name", $account->name);
843 844 845 846 847
      $output .= form_hidden("pass", $pass);
      $output .= form_submit(t("Log in"));
      return form($output);
    }
    else {
848 849 850 851 852
      if ($account->status) {
        /*
        ** Create new user account, no administrator approval required:
        */

Dries's avatar
 
Dries committed
853 854
        $subject = strtr(variable_get("user_mail_welcome_subject", _user_mail_text("welcome_subject")), $variables);
        $body = strtr(variable_get("user_mail_welcome_body", _user_mail_text("welcome_body")), $variables);
855 856 857 858 859 860 861
        user_mail($edit["mail"], $subject, $body, "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from");
        return t("Your password and further instructions have been sent to your e-mail address.");
      }
      else {
        /*
        ** Create new user account, administrator approval required:
        */
Dries's avatar
 
Dries committed
862 863
        $subject = strtr(variable_get("user_mail_approval_subject", _user_mail_text("welcome_approval_subject")), $variables);
        $body = strtr(variable_get("user_mail_approval_body", _user_mail_text("welcome_approval_body")), $variables);
864
        user_mail($edit["mail"], $subject, $body, "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from");
Dries's avatar
 
Dries committed
865
        user_mail(variable_get("site_mail", ini_get("sendmail_from")), $subject, t("%u has applied for an account.\n\n%uri", array("%u" => $account->name, "%uri" => url("admin/user/edit/$account->uid"))), "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from");
Dries's avatar
 
Dries committed
866
        return 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.");
867
      }
868
    }
Dries's avatar
 
Dries committed
869 870 871
  }
  else {
    if ($error) {
Dries's avatar
 
Dries committed
872
      $output .= theme("error", $error);
Dries's avatar
 
Dries committed
873
    }
874
  }
Dries's avatar
 
Dries committed
875

876
  // display the registration form
877
  $output .= variable_get("user_registration_help", "");
878
  $affiliates = user_auth_help_links();
Dries's avatar
 
Dries committed
879
  if (count($affiliates) > 0) {
880
    $affiliates = implode(", ", $affiliates);
Dries's avatar
 
Dries committed
881
    $output .= "<p>". t("Note: If you have an account with one of our affiliates (%s), you may ". l("login now", "user/login") ." instead of registering.", array("%s" => $affiliates)) ."</p>";
882
  }
Dries's avatar
 
Dries committed
883
  $output .= form_textfield(t("Username"), "name", $edit["name"], 30, 64, t("Your full name or your preferred username: only letters, numbers and spaces are allowed."));
884 885 886 887
  $output .= form_textfield(t("E-mail address"), "mail", $edit["mail"], 30, 64, t("A password and instructions will be sent to this e-mail address, so make sure it is accurate."));
  foreach (module_list() as $module) {
    if (module_hook($module, "user")) {
      $output .= module_invoke($module, "user", "register_form", $edit, $user);
Dries's avatar
 
Dries committed
888
    }
Dries's avatar
 
Dries committed
889
  }
890
  $output .= form_submit(t("Create new account"));
891
  $items[] = l(t("Request new password"), "user/password");
Dries's avatar
 
Dries committed
892
  $items[] = l(t("Log in"), "user/login");
Dries's avatar
 
Dries committed
893
  $output .= theme("item_list", $items);
Kjartan's avatar
Kjartan committed
894

895
  return form($output);
Dries's avatar
 
Dries committed
896 897 898
}

function user_edit($edit = array()) {
Dries's avatar
 
Dries committed
899
  global $user;
Dries's avatar
 
Dries committed
900 901 902 903 904 905 906 907 908

  if ($user->uid) {
    if ($edit["name"]) {
      if ($error = user_validate_name($edit["name"])) {
        // do nothing
      }
      else if ($error = user_validate_mail($edit["mail"])) {
        // do nothing
      }
Dries's avatar
 
Dries committed
909
      else if (db_num_rows(db_query("SELECT uid FROM {users} WHERE uid != '$user->uid' AND LOWER(name) = LOWER('%s')", $edit["name"])) > 0) {
Dries's avatar
 
Dries committed
910
        $error = t("The name '%s' is already taken.", array("%s" => $edit["name"]));
Dries's avatar
 
Dries committed
911
      }
Dries's avatar
 
Dries committed
912
      else if ($edit["mail"] && db_num_rows(db_query("SELECT uid FROM {users} WHERE uid != '$user->uid' AND LOWER(mail) = LOWER('%s')", $edit["mail"])) > 0) {
Dries's avatar
 
Dries committed
913
        $error = t("The e-mail address '%s' is already taken.", array("%s" => $edit["mail"]));
Dries's avatar
 
Dries committed
914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930
      }
      else if ($user->uid) {
        /*
        ** If required, check that proposed passwords match.  If so,
        ** add new password to $edit.
        */

        if ($edit["pass1"]) {
          if ($edit["pass1"] == $edit["pass2"]) {
            $edit["pass"] = $edit["pass1"];
          }
          else {
            $error = t("The specified passwords do not match.");
          }
        }
        unset($edit["pass1"], $edit["pass2"]);

Dries's avatar
 
Dries committed
931 932 933 934 935 936
        /*
        ** Validate input fields to make sure users don't submit
        ** invalid form data.
        */

        if (!user_access("administer users")) {
937
           if (array_intersect(array_keys($edit), array("rid", "init", "session"))) {
Dries's avatar
 
Dries committed
938 939 940 941 942 943 944
             watchdog("warning", "detected malicious attempt to alter a protected database field");
           }

           $edit["rid"] = $user->rid;
           $edit["init"] = $user->init;
           $edit["session"] = $user->session;
        }
945

Dries's avatar
 
Dries committed
946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963
        /*
        ** Have the modules that extend the user information validate
        ** their data.
        */

        foreach (module_list() as $module) {
          if (module_hook($module, "user")) {
            $result = module_invoke($module, "user", "edit_validate", $edit, $user);
          }
          if (is_array($result)) {
            $data = array_merge($data, $result);
          }
          elseif (is_string($result)) {
            $error = $result;
            break;
          }
        }

Dries's avatar
 
Dries committed
964 965 966 967
        if (!$error) {
          /*
          ** Save user information:
          */
Dries's avatar
 
Dries committed
968

Dries's avatar
 
Dries committed
969
          $user = user_save($user, array_merge($edit, $data));
Dries's avatar
 
Dries committed
970

Dries's avatar
 
Dries committed
971
          $output .= status(t("your user information changes have been saved."));
Dries's avatar
 
Dries committed
972
        }
Dries's avatar
 
Dries committed
973 974 975 976
      }
    }

    if ($error) {
Dries's avatar