user.module 81.8 KB
Newer Older
Dries's avatar
 
Dries committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
<?php
// $Id$

session_set_save_handler("sess_open", "sess_close", "sess_read", "sess_write", "sess_destroy", "sess_gc");
session_start();

/*** Session functions *****************************************************/

function sess_open($save_path, $session_name) {
  return 1;
}

function sess_close() {
  return 1;
}

function sess_read($key) {
  global $user;
Dries's avatar
 
Dries committed
19 20 21

  $result = db_query_range("SELECT u.*, s.*, r.name AS role FROM {users} u INNER JOIN {role} r ON u.rid = r.rid INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.sid = '". check_query($key) ."' AND u.status < 3", 0, 1);
  $user = db_fetch_object($result);
Dries's avatar
 
Dries committed
22 23 24 25 26 27 28
  if ($user->data && $data = unserialize($user->data)) {
    foreach ($data as $key => $value) {
      if (!isset($user->$key)) {
        $user->$key = $value;
      }
    }
  }
Dries's avatar
 
Dries committed
29

30
  return !empty($user->session) ? $user->session : '';
Dries's avatar
 
Dries committed
31 32 33
}

function sess_write($key, $value) {
Dries's avatar
 
Dries committed
34 35 36
  global $user;

  db_query("UPDATE {sessions} SET uid = %d, hostname = '%s', session = '%s', timestamp = %d WHERE sid = '$key'", $user->uid, $_SERVER["REMOTE_ADDR"], $value, time());
Dries's avatar
 
Dries committed
37

Dries's avatar
 
Dries committed
38 39 40
  if (!db_affected_rows()) {
    db_query("INSERT INTO {sessions} (uid, sid, hostname, session, timestamp) values(%d, '%s', '%s', '%s', %d)", $user->uid, $key, $_SERVER["REMOTE_ADDR"], $value, time());
  }
Dries's avatar
 
Dries committed
41

Dries's avatar
 
Dries committed
42 43 44 45 46
  return '';
}

function sess_destroy($key) {

Dries's avatar
 
Dries committed
47 48
  db_query("DELETE FROM {sessions} WHERE sid = '$key'");

Dries's avatar
 
Dries committed
49 50 51
}

function sess_gc($lifetime) {
Dries's avatar
 
Dries committed
52 53 54 55 56 57 58 59 60 61

  /*
  **  Be sure to adjust 'php_value session.gc_maxlifetime' to a large enough
  **   value.  For example, if you want user sessions to stay in your database
  **   for three weeks before deleting them, you need to set gc_maxlifetime
  **   to '1814400'.  At that value, only after a user doesn't log in after
  **   three weeks (1814400 seconds) will his/her session be removed.
  */
  db_query("DELETE FROM {sessions} WHERE timestamp < %d", time() - $lifetime);

Dries's avatar
 
Dries committed
62
  return 1;
Dries's avatar
 
Dries committed
63

Dries's avatar
 
Dries committed
64 65 66 67 68
}

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

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

Dries's avatar
 
Dries committed
71 72
  if ($user = db_fetch_object($result)) {
    return user_load($user);
Dries's avatar
 
Dries committed
73 74 75 76 77 78 79 80 81 82 83 84
  }
  else {
    return 0;
  }
}

function user_load($array = array()) {

  /*
  ** Dynamically compose a SQL query:
  */

Dries's avatar
 
Dries committed
85 86
  $query = "";

Dries's avatar
 
Dries committed
87 88
  foreach ($array as $key => $value) {
    if ($key == "pass") {
Kjartan's avatar
Kjartan committed
89
      $query .= "u.$key = '". md5($value) ."' AND ";
90
    }
Dries's avatar
 
Dries committed
91
    else {
Dries's avatar
 
Dries committed
92
      $query .= "u.$key = '". check_query($value) ."' AND ";
Dries's avatar
 
Dries committed
93 94
    }
  }
Dries's avatar
 
Dries committed
95
  $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
96 97

  $user = db_fetch_object($result);
Dries's avatar
 
Dries committed
98
  if ($user->data && $data = unserialize($user->data)) {
Dries's avatar
 
Dries committed
99 100 101 102 103 104
    foreach ($data as $key => $value) {
      if (!isset($user->$key)) {
        $user->$key = $value;
      }
    }
  }
Dries's avatar
 
Dries committed
105 106 107 108 109 110 111 112 113

  return $user;
}

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

Kjartan's avatar
Kjartan committed
114
  $user_fields = user_fields();
Dries's avatar
 
Dries committed
115
  if ($account->uid) {
Dries's avatar
 
Dries committed
116
    $data = unserialize(db_result(db_query("SELECT data FROM {users} WHERE uid = %d", $account->uid)));
Dries's avatar
 
Dries committed
117 118
    foreach ($array as $key => $value) {
      if ($key == "pass") {
Dries's avatar
 
Dries committed
119 120
        $query .= "$key = '%s', ";
        $v[] = md5($value);
Dries's avatar
 
Dries committed
121 122
      }
      else if (substr($key, 0, 4) !== "auth") {
Kjartan's avatar
Kjartan committed
123
        if (in_array($key, $user_fields)) {
Dries's avatar
 
Dries committed
124 125
          // escape '%'s:
          $value = str_replace("%", "%%", $value);
Dries's avatar
 
Dries committed
126 127
          $query .= "$key = '%s', ";
          $v[] = $value;
Dries's avatar
 
Dries committed
128 129 130 131
        }
        else {
          $data[$key] = $value;
        }
Dries's avatar
 
Dries committed
132 133
      }
    }
Dries's avatar
 
Dries committed
134 135
    $query .= "data = '%s', ";
    $v[] = serialize($data);
Dries's avatar
 
Dries committed
136

Dries's avatar
 
Dries committed
137
    db_query("UPDATE {users} SET $query timestamp = %d WHERE uid = %d", array_merge($v, array(time(), $account->uid)));
Dries's avatar
 
Dries committed
138 139 140 141 142

    $user = user_load(array("uid" => $account->uid));
  }
  else {
    $array["timestamp"] = time();
Dries's avatar
 
Dries committed
143
    $array["uid"] = db_next_id("{users}_uid");
Dries's avatar
 
Dries committed
144 145 146 147

    foreach ($array as $key => $value) {
      if ($key == "pass") {
        $fields[] = check_query($key);
Dries's avatar
 
Dries committed
148 149
        $values[] = md5($value);
        $s[] = "'%s'";
Dries's avatar
 
Dries committed
150 151
      }
      else if (substr($key, 0, 4) !== "auth") {
Kjartan's avatar
Kjartan committed
152
        if (in_array($key, $user_fields)) {
Dries's avatar
 
Dries committed
153
          $fields[] = check_query($key);
Dries's avatar
 
Dries committed
154 155
          $values[] = $value;
          $s[] = "'%s'";
Dries's avatar
 
Dries committed
156 157 158 159
        }
        else {
          $data[$key] = $value;
        }
Dries's avatar
 
Dries committed
160 161 162
      }
    }

Dries's avatar
 
Dries committed
163
    $fields[] = "data";
Dries's avatar
 
Dries committed
164 165
    $values[] = serialize($data);
    $s[] = "'%s'";
Dries's avatar
 
Dries committed
166

Dries's avatar
 
Dries committed
167
    db_query("INSERT INTO {users} (". implode(", ", $fields) .") VALUES (". implode(", ", $s) .")", $values);
Dries's avatar
 
Dries committed
168 169 170 171 172 173 174 175 176 177 178

    $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
179
    user_set_authmaps($user, $authmaps);
Dries's avatar
 
Dries committed
180 181 182 183 184 185 186 187 188 189 190
  }

  return $user;
}

function user_validate_name($name) {

  /*
  ** Verify the syntax of the given name:
  */

Dries's avatar
 
Dries committed
191
  if (!$name) return t("You must enter a username.");
Dries's avatar
 
Dries committed
192 193
  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
194
  if (ereg("  ", $name)) return t("The username cannot contain multiple spaces in a row.");
Dries's avatar
 
Dries committed
195 196
  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
197
  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
198 199 200
}

function user_validate_mail($mail) {
Dries's avatar
 
Dries committed
201
  if ($mail && !valid_email_address($mail)) {
Dries's avatar
 
Dries committed
202
    return t("The e-mail address '%mail' is not valid.", array("%mail" => $mail));
Dries's avatar
 
Dries committed
203 204 205
  }
}

206
function user_validate_authmap($account, $authname, $module) {
Dries's avatar
 
Dries committed
207
  $result = db_query("SELECT COUNT(*) from {authmap} WHERE uid != %d AND authname = '%s'", $account->uid, $authname);
Dries's avatar
 
Dries committed
208 209 210 211
  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
212 213
}

Dries's avatar
 
Dries committed
214
function user_password($length = 10) {
Dries's avatar
 
Dries committed
215 216

  /*
Dries's avatar
 
Dries committed
217
  ** Generate a random alphanumeric password.
Dries's avatar
 
Dries committed
218 219
  */

Dries's avatar
 
Dries committed
220 221 222 223 224 225 226 227 228
  // 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
229
  mt_srand((double)microtime() * 1000000);
Dries's avatar
 
Dries committed
230 231 232 233 234 235 236 237 238 239 240 241 242

  // 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
243 244 245 246
}

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

Dries's avatar
 
Dries committed
249
  // User #1 has all priveleges:
Dries's avatar
 
Dries committed
250 251 252 253
  if ($user->uid == 1) {
    return 1;
  }

Dries's avatar
 
Dries committed
254 255 256 257
  /*
  ** To reduce the number of SQL queries, we cache the user's permissions
  ** in a static variable.
  */
Dries's avatar
 
Dries committed
258

Dries's avatar
 
Dries committed
259 260
  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
261 262
  }

Dries's avatar
 
Dries committed
263
  return strstr($perm, $string);
Dries's avatar
 
Dries committed
264 265 266 267 268
}

function user_mail($mail, $subject, $message, $header) {
  if (variable_get("smtp_library", "") && file_exists(variable_get("smtp_library", ""))) {
    include_once variable_get("smtp_library", "");
269
    return user_mail_wrapper($mail, $subject, $message, $header);
Dries's avatar
 
Dries committed
270 271
  }
  else {
272 273 274 275 276 277 278
    /*
    ** 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
279 280 281 282 283 284 285 286 287 288 289 290
    **
    ** 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
    **
291
    */
Dries's avatar
 
Dries committed
292 293 294 295
    return mail(
      $mail,
      user_mail_encode($subject),
      str_replace("\r", "", $message),
Kjartan's avatar
Kjartan committed
296
      "MIME-Version: 1.0\nContent-type: text/plain; charset=UTF-8; format=flowed\nContent-transfer-encoding: 8Bit\n" . $header
Dries's avatar
 
Dries committed
297
    );
Dries's avatar
 
Dries committed
298 299 300
  }
}

Kjartan's avatar
Kjartan committed
301 302 303 304 305
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
306 307 308 309 310 311 312 313
  **
  ** 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
314
  */
Kjartan's avatar
Kjartan committed
315 316 317
  $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
318 319
  $string = trim(preg_replace('/^(.*)$/m', " =?$charset?B?\\1?=", $string));
  return $string;
Dries's avatar
 
Dries committed
320 321
}

Dries's avatar
 
Dries committed
322
function user_deny($type, $mask) {
Dries's avatar
 
Dries committed
323 324
  $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
325

Dries's avatar
 
Dries committed
326
  return $deny && !$allow;
Dries's avatar
 
Dries committed
327 328
}

Dries's avatar
 
Dries committed
329 330
function user_fields() {
  static $fields;
Dries's avatar
 
Dries committed
331

Dries's avatar
 
Dries committed
332
  if (!$fields) {
Dries's avatar
 
Dries committed
333
    $result = db_query("SELECT * FROM {users} WHERE uid = 1");
Kjartan's avatar
Kjartan committed
334 335 336
    if (db_num_rows($result)) {
      $fields = array_keys(db_fetch_array($result));
    }
Dries's avatar
 
Dries committed
337 338 339 340
    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
341
  }
Dries's avatar
 
Dries committed
342

Dries's avatar
 
Dries committed
343
  return $fields;
Dries's avatar
 
Dries committed
344 345
}

Dries's avatar
 
Dries committed
346 347 348 349 350 351 352
/*** Module hooks **********************************************************/

function user_perm() {
  return array("administer users");
}

function user_search($keys) {
Dries's avatar
 
Dries committed
353 354
  $find = array();
  $result = db_query_range("SELECT * FROM {users} WHERE name LIKE '%%%s%%'", $keys, 0, 20);
Dries's avatar
 
Dries committed
355
  while ($account = db_fetch_object($result)) {
Dries's avatar
 
Dries committed
356
    $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
357 358 359 360
  }
  return $find;
}

Dries's avatar
 
Dries committed
361
function user_block($op = "list", $delta = 0) {
Dries's avatar
 
Dries committed
362 363
  global $user;

Dries's avatar
 
Dries committed
364
  if ($op == "list") {
Dries's avatar
 
Dries committed
365
     $blocks[0]["info"] = t("User login");
366
     $blocks[1]["info"] = t("Navigation");
367
     $blocks[2]["info"] = t("Who's new");
368

369
     return $blocks;
370 371
  }
  else {
Dries's avatar
 
Dries committed
372 373
    switch ($delta) {
      case 0:
374
        if (!$user->uid) {
Dries's avatar
 
Dries committed
375 376 377 378 379 380 381 382 383
          /*
          ** 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
384 385
          $edit = $_POST["edit"];

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

388
          /*
Dries's avatar
Dries committed
389 390
          ** Save the referer.  We record where the user came from such
          ** that we/ can redirect him after having completed the login
391 392
          ** form.
          */
Dries's avatar
Dries committed
393

394
          if (empty($edit)) {
Dries's avatar
 
Dries committed
395
            $edit["destination"] = url($_GET["q"]);
396 397
          }
          // 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
398

Dries's avatar
 
Dries committed
399 400 401
          $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
402 403

          if (variable_get("user_remember", 0) == 0) {
Dries's avatar
 
Dries committed
404
            $form .= form_checkbox(t("Remember me"), "remember_me", 1, 0, 0);
Dries's avatar
 
Dries committed
405 406
          }
          elseif (variable_get("user_remember", 1) == 1) {
Dries's avatar
 
Dries committed
407
            $form .= form_hidden("remember_me", 1);
Dries's avatar
 
Dries committed
408
          }
409

Dries's avatar
 
Dries committed
410 411 412 413 414
          $form .= form_submit(t("Log in"));

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

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

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

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

Dries's avatar
 
Dries committed
423
          $block["subject"] = t("User login");
Dries's avatar
 
Dries committed
424
          $block["content"] = "<div class=\"user-login-link\">$output</div>";
Dries's avatar
 
Dries committed
425
        }
Dries's avatar
Dries committed
426
        return $block;
427
      case 1:
Dries's avatar
 
Dries committed
428 429
        if ($menu = menu_tree()) {
           $block["subject"] = $user->uid ? $user->name : t("Navigation");
Dries's avatar
 
Dries committed
430
           $block["content"] = "<div class=\"menu\">". $menu ."</div>";
Dries's avatar
 
Dries committed
431 432
        }

433
        return $block;
Dries's avatar
 
Dries committed
434
      case 2:
435 436 437 438 439
        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
440

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

443 444 445 446
          $block["subject"] = t("Who's new");
          $block["content"] = $output;
          return $block;
        }
Dries's avatar
 
Dries committed
447 448
    }
  }
449 450
}

Dries's avatar
 
Dries committed
451
function theme_user_list($items, $title = NULL) {
Dries's avatar
 
Dries committed
452
  return theme("item_list", $items, $title);
Dries's avatar
 
Dries committed
453 454
}

Dries's avatar
 
Dries committed
455
function user_link($type) {
Dries's avatar
 
Dries committed
456 457 458

  $links = array();

Dries's avatar
 
Dries committed
459
  if ($type == "page") {
460
    $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
461 462
  }

Dries's avatar
 
Dries committed
463
  if ($type == "system") {
Dries's avatar
Dries committed
464 465
    global $user;
    if ($user->uid) {
Dries's avatar
 
Dries committed
466 467 468
      menu("user", t("my account"), "page", 8);
      menu("user/edit", t("edit account"), "page", 0);
      menu("user/logout", t("log out"), "page", 10);
Dries's avatar
Dries committed
469
    }
Dries's avatar
 
Dries committed
470

Dries's avatar
 
Dries committed
471
    if (user_access("administer users")) {
Dries's avatar
 
Dries committed
472 473 474
      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);
475 476
      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
477 478 479 480 481
      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);
      menu("admin/user/help", t("help"), "user_help", 9);
      menu("admin/user/edit", t("edit user account"), "user_admin", 0, 1); // hidden menu
Dries's avatar
 
Dries committed
482
    }
Dries's avatar
 
Dries committed
483 484
  }

Dries's avatar
 
Dries committed
485
  return $links;
Dries's avatar
 
Dries committed
486 487 488 489
}

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

490
function user_get_authname($account, $module) {
Dries's avatar
 
Dries committed
491 492

  /*
493
  **  Called by authentication modules in order to edit/view their authmap information.
Dries's avatar
 
Dries committed
494 495
  */

Dries's avatar
 
Dries committed
496
  $result = db_query("SELECT authname FROM {authmap} WHERE uid = %d AND module = '%s'", $account->uid, $module);
497 498 499
  return db_result($result);
}

Dries's avatar
 
Dries committed
500

501 502 503 504 505 506 507
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
508
  $result = db_query("SELECT authname, module FROM {authmap} WHERE authname = '%s'", $authname);
Dries's avatar
 
Dries committed
509 510 511 512 513 514 515 516 517 518 519 520 521 522 523
  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
524 525 526
      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
527 528 529
      }
    }
    else {
Dries's avatar
 
Dries committed
530
      db_query("DELETE FROM {authmap} WHERE uid = %d AND module = '%s'", $account->uid, $module["1"]);
Dries's avatar
 
Dries committed
531 532 533 534 535
    }
  }
}

function user_auth_help_links() {
536
  $links = array();
Dries's avatar
 
Dries committed
537
  foreach (module_list() as $module) {
Dries's avatar
 
Dries committed
538
    if (module_hook($module, "auth")) {
Dries's avatar
 
Dries committed
539
      $links[] = l(module_invoke($module, "info", "name"), "user/help#$module");
Dries's avatar
 
Dries committed
540 541 542 543 544 545 546
    }
  }
  return $links;
}

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

Dries's avatar
 
Dries committed
547
function user_login($edit = array(), $msg = "") {
Dries's avatar
 
Dries committed
548
  global $user, $base_url;
Dries's avatar
 
Dries committed
549 550 551 552 553 554

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

  if ($user->uid) {
Dries's avatar
 
Dries committed
555
    drupal_goto(url("user"));
Dries's avatar
 
Dries committed
556 557 558
  }

  if (user_deny("user", $edit["name"])) {
Dries's avatar
 
Dries committed
559
    $error = t("The name '%s' has been denied access.", array("%s" => $edit["name"]));
Dries's avatar
 
Dries committed
560 561 562 563
  }
  else if ($edit["name"] && $edit["pass"]) {

    /*
Dries's avatar
 
Dries committed
564
    ** Try to log in the user locally:
Dries's avatar
 
Dries committed
565 566
    */

Dries's avatar
 
Dries committed
567
    if (!$user->uid) {
568 569
      $name = $edit["name"];
      $pass = $edit["pass"];
Dries's avatar
 
Dries committed
570 571 572 573 574 575 576 577
      $user = user_load(array("name" => $name, "pass" => $pass, "status" => 1));
    }

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

    if ($server = strrchr($edit["name"], "@")) {
578 579 580
      $name = substr($edit["name"], 0, strlen($edit["name"]) - strlen($server));
      $server = substr($server, 1);
      $pass = $edit["pass"];
Dries's avatar
 
Dries committed
581
    }
Dries's avatar
 
Dries committed
582

Dries's avatar
 
Dries committed
583
    /*
Dries's avatar
 
Dries committed
584
    ** When possible, determine corresponding external auth source. Invoke source, and login user if successful:
Dries's avatar
 
Dries committed
585 586
    */

Dries's avatar
 
Dries committed
587
    if (!$user->uid && $server && $result = user_get_authmaps("$name@$server")) {
Dries's avatar
 
Dries committed
588 589
      if (module_invoke(key($result), "auth", $name, $pass, $server)) {
        $user = user_external_load("$name@$server");
Dries's avatar
 
Dries committed
590
        watchdog("user", "external load: $name@$server, module: ". key($result));
Dries's avatar
 
Dries committed
591 592
      }
      else {
Dries's avatar
 
Dries committed
593
        $error = t("Invalid password for %s.", array("%s" => "<i>$name@$server</i>"));
Dries's avatar
 
Dries committed
594 595 596 597 598 599 600
      }
    }

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

Dries's avatar
 
Dries committed
601
    else if (!$user->uid && $server) {
Dries's avatar
 
Dries committed
602 603 604 605
      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
606
              $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
607
              watchdog("user", "new user: $name@$server ($module ID)", l(t("edit user"), "admin/user/edit/$user->uid"));
Dries's avatar
 
Dries committed
608 609 610 611 612 613 614 615 616 617
              break;
            }
          }
        }
      }
    }

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

Dries's avatar
 
Dries committed
618 619
      // 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
620 621 622 623 624 625

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

Dries's avatar
 
Dries committed
626
      $path = preg_replace("/.+\/\/[^\/]+(.*)/", "\$1/", $base_url);
Dries's avatar
 
Dries committed
627
      if ($edit["remember_me"]) {
Dries's avatar
 
Dries committed
628
        setcookie(session_name(), session_id(), time() + 3600 * 24 * 365, $path);
Dries's avatar
 
Dries committed
629
      }
Dries's avatar
 
Dries committed
630
      else {
Dries's avatar
 
Dries committed
631
        setcookie(session_name(), session_id(), FALSE, $path);
Dries's avatar
 
Dries committed
632 633 634
      }

      /*
Dries's avatar
 
Dries committed
635
      ** Redirect the user to the page he logged on from.
Dries's avatar
 
Dries committed
636 637
      */

Dries's avatar
 
Dries committed
638
      drupal_goto($edit["destination"]);
Dries's avatar
 
Dries committed
639 640 641
    }
    else {
      if (!$error) {
Dries's avatar
 
Dries committed
642
        $error = t("Sorry.  Unrecognized username or password.") ." ". l(t("Have you forgotten your password?"), "user/password");
Dries's avatar
 
Dries committed
643 644 645 646 647 648 649 650 651 652 653 654 655 656 657
      }
      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
658
    $output .= theme("error", $error);
Dries's avatar
 
Dries committed
659 660
  }

Dries's avatar
 
Dries committed
661
  /*
Dries's avatar
 
Dries committed
662
  ** Save the referrer.  We record where the user came from such that we
Dries's avatar
 
Dries committed
663 664 665
  ** can redirect him after having completed the login form.
  */

666
  if (empty($edit)) {
Dries's avatar
 
Dries committed
667
    $edit["destination"] = url($_GET["q"]);
Dries's avatar
 
Dries committed
668 669 670
  }
  $output .= form_hidden("destination", $edit["destination"]);

Dries's avatar
 
Dries committed
671 672 673 674
  /*
  ** Display login form:
  */

Dries's avatar
 
Dries committed
675 676 677
  if ($msg) {
    $output .= "<p>$msg</p>";
  }
Dries's avatar
 
Dries committed
678
  if (count(user_auth_help_links()) > 0) {
Dries's avatar
 
Dries committed
679
    $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
680 681
  }
  else {
Dries's avatar
 
Dries committed
682
    $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
683
  }
Dries's avatar
 
Dries committed
684
  $output .= form_password(t("Password"), "pass", $pass, 30, 64, t("Enter the password that accompanies your username."));
685
  $output .= form_checkbox(t("Remember me"), "remember_me", 1, 0, 0);
Dries's avatar
 
Dries committed
686
  $output .= form_submit(t("Log in"));
Dries's avatar
 
Dries committed
687
  $items[] = l(t("Request new password"), "user/password");
688
  if (variable_get("user_register", 1)) {
Dries's avatar
 
Dries committed
689
    $items[] = l(t("Create new account"), "user/register");
690
  }
Dries's avatar
 
Dries committed
691
  $output .= theme("item_list", $items);
Dries's avatar
 
Dries committed
692

Dries's avatar
 
Dries committed
693
  return form($output, "post", url("user"));
Dries's avatar
 
Dries committed
694 695
}

696
function _user_authenticated_id() {
Dries's avatar
 
Dries committed
697
  return db_result(db_query("SELECT rid FROM {role} WHERE name = 'authenticated user'"));
698 699
}

Dries's avatar
 
Dries committed
700 701 702 703 704 705 706 707 708 709 710 711 712 713
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
714
  drupal_goto(url());
Dries's avatar
 
Dries committed
715 716 717 718

}

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

Kjartan's avatar
Kjartan committed
721
  if ($edit["name"]) {
Dries's avatar
 
Dries committed
722
    $account = db_fetch_object(db_query("SELECT uid, name, mail FROM {users} WHERE name = '%s'", $edit["name"]));
Dries's avatar
 
Dries committed
723
    if (!$account) $error = t("Sorry. The username <i>%s</i> is not recognized.", array("%s" => $edit["name"]));
724
  }
Kjartan's avatar
Kjartan committed
725
  else if ($edit["mail"]) {
Dries's avatar
 
Dries committed
726
    $account = db_fetch_object(db_query("SELECT uid, name, mail FROM {users} WHERE mail = '%s'", $edit["mail"]));
Dries's avatar
 
Dries committed
727
    if (!$account) $error = t("Sorry. The e-mail address <i>%s</i> is not recognized.", array("%s" => $edit["mail"]));
Kjartan's avatar
Kjartan committed
728 729
  }
  if ($account) {
Dries's avatar
 
Dries committed
730

731
      $from = variable_get("site_mail", ini_get("sendmail_from"));
Dries's avatar
 
Dries committed
732 733 734 735 736 737 738 739 740 741 742 743
      $pass = user_password();

      /*
      ** Save new password:
      */

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

      /*
      ** Mail new password:
      */

Dries's avatar
 
Dries committed
744
      $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
745 746
      $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);
747
      $headers = "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from";
Dries's avatar
 
Dries committed
748
      $mail_success = user_mail($account->mail, $subject, $body, $headers);
Dries's avatar
 
Dries committed
749

Dries's avatar
 
Dries committed
750 751 752 753 754 755 756 757
      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
758 759
    }
    else {
760

Kjartan's avatar
Kjartan committed
761 762
    // Display error message if necessary.
    if ($error) {
Dries's avatar
 
Dries committed
763
      $output .= theme("error", $error);
Dries's avatar
 
Dries committed
764 765 766 767 768 769
    }

    /*
    ** Display form:
    */

Dries's avatar
 
Dries committed
770
    $output .= "<p>". sprintf(t("Enter your username %sor%s your e-mail address."), "<b><i>", "</i></b>") ."</p>";
Dries's avatar
 
Dries committed
771 772 773
    $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
774
    $items[] = l(t("Log in"), "user/login");
775
    if (variable_get("user_register", 1)) {
Dries's avatar
 
Dries committed
776
      $items[] = l(t("Create new account"), "user/register");
777
    }
Dries's avatar
 
Dries committed
778
    $output .= theme("item_list", $items);
Dries's avatar
 
Dries committed
779

Dries's avatar
 
Dries committed
780
    return form($output, "post", url("user"));
Dries's avatar
 
Dries committed
781 782 783 784
  }
}

function user_register($edit = array()) {
Dries's avatar
 
Dries committed
785
  global $user, $base_url;
786 787 788 789 790 791

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

  if ($user->uid) {
Dries's avatar
 
Dries committed
792
    drupal_goto(url("user/edit"));
793
  }
Dries's avatar
 
Dries committed
794 795 796 797 798 799 800 801 802

  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
803
      $error = t("The name '%s' has been denied access.", array("%s" => $edit["name"]));
Dries's avatar
 
Dries committed
804 805
    }
    else if (user_deny("mail", $edit["mail"])) {
Dries's avatar
 
Dries committed
806
      $error = t("The e-mail address '%s' has been denied access.", array("%s" => $edit["mail"]));
Dries's avatar
 
Dries committed
807
    }
Dries's avatar
 
Dries committed
808
    else if (db_num_rows(db_query("SELECT name FROM {users} WHERE LOWER(name) = LOWER('%s')", $edit["name"])) > 0) {
Dries's avatar
 
Dries committed
809
      $error = t("The name '%s' is already taken.", array("%s" => $edit["name"]));
Dries's avatar
 
Dries committed
810
    }
Dries's avatar
 
Dries committed
811
    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
812
      $error = t("The e-mail address '%s' is already taken.", array("%s" => $edit["mail"]));
Dries's avatar
 
Dries committed
813
    }
Dries's avatar
 
Dries committed
814
    else if (variable_get("user_register", 1) == 0) {
Dries's avatar
 
Dries committed
815 816 817
      $error = t("Public registrations have been disabled by the site administrator.");
    }
    else {
Dries's avatar
 
Dries committed
818 819 820 821 822 823 824 825 826 827 828 829 830 831 832
      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
833 834 835 836 837
    }
  }

  if ($success) {

838
    $from = variable_get("site_mail", ini_get("sendmail_from"));
Dries's avatar
 
Dries committed
839 840
    $pass = user_password();

841
    // create new user account, noting whether administrator approval is required
842 843 844
    user_role_init();
    // TODO: is this necessary? Won't session_write replicate this?
    unset($edit["session"]);
845
    $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
846
    watchdog("user", "new user: '". $edit["name"] ."' &lt;". $edit["mail"] ."&gt;", l(t("edit user"), "admin/user/edit/$account->uid"));
Dries's avatar
 
Dries committed
847

Dries's avatar
 
Dries committed
848
    $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()));
849

Dries's avatar
 
Dries committed
850
    //the first user may login immediately, and receives a customized welcome e-mail.
851
    if ($account->uid == 1) {
Dries's avatar
 
Dries committed
852
      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");
853
      // 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
854
      $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
855
      $output .= form_hidden("destination", url("user/edit"));
856
      $output .= form_hidden("name", $account->name);
857 858 859 860 861
      $output .= form_hidden("pass", $pass);
      $output .= form_submit(t("Log in"));
      return form($output);
    }
    else {
862 863 864 865 866
      if ($account->status) {
        /*
        ** Create new user account, no administrator approval required:
        */

Dries's avatar
 
Dries committed
867 868
        $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);
869 870 871 872 873 874 875
        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
876 877
        $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);
878
        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
879
        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
880
        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.");
881
      }
882
    }
Dries's avatar
 
Dries committed
883 884 885
  }
  else {
    if ($error) {
Dries's avatar
 
Dries committed
886
      $output .= theme("error", $error);
Dries's avatar
 
Dries committed
887
    }
888
  }
Dries's avatar
 
Dries committed
889

890
  // display the registration form
891
  $output .= variable_get("user_registration_help", "");
892
  $affiliates = user_auth_help_links();
Dries's avatar
 
Dries committed
893
  if (count($affiliates) > 0) {
894
    $affiliates = implode(", ", $affiliates);
Dries's avatar
 
Dries committed
895
    $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>";
896
  }
Dries's avatar
 
Dries committed
897
  $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."));
898 899 900 901
  $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
902
    }
Dries's avatar
 
Dries committed
903
  }
904
  $output .= form_submit(t("Create new account"));
905
  $items[] = l(t("Request new password"), "user/password");
Dries's avatar
 
Dries committed
906
  $items[] = l(t("Log in"), "user/login");
Dries's avatar
 
Dries committed
907
  $output .= theme("item_list", $items);
Kjartan's avatar
Kjartan committed
908

909
  return form($output);
Dries's avatar
 
Dries committed
910 911 912
}

function user_edit($edit = array()) {
Dries's avatar
 
Dries committed
913
  global $user;
Dries's avatar
 
Dries committed
914 915 916 917 918 919 920 921 922

  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
923
      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
924
        $error = t("The name '%s' is already taken.", array("%s" => $edit["name"]));
Dries's avatar
 
Dries committed
925
      }
Dries's avatar
 
Dries committed
926
      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
927
        $error = t("The e-mail address '%s' is already taken.", array("%s" => $edit["mail"]));
Dries's avatar
 
Dries committed
928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944
      }
      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
945 946 947 948 949 950
        /*
        ** Validate input fields to make sure users don't submit
        ** invalid form data.
        */

        if (!user_access("administer users")) {
951
           if (array_intersect(array_keys($edit), array("rid", "init", "session"))) {
Dries's avatar
 
Dries committed
952 953 954 955 956 957 958
             watchdog("warning", "detected malicious attempt to alter a protected database field");
           }

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

Dries's avatar
 
Dries committed
960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977
        /*
        ** 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