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

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

Dries's avatar
   
Dries committed
6
7
8
9
// we cannot use module_invoke because we need passing by reference
function user_module_invoke($type, &$array, &$user) {
  foreach (module_list() as $module) {
    $function = $module .'_user';
Dries's avatar
   
Dries committed
10
    if (function_exists($function)) $function($type, $array, $user);
Dries's avatar
   
Dries committed
11
12
13
  }
}

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

Dries's avatar
   
Dries committed
17
18
  if ($user = db_fetch_object($result)) {
    return user_load($user);
Dries's avatar
   
Dries committed
19
20
21
22
23
24
25
26
27
28
29
  }
  else {
    return 0;
  }
}

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

Dries's avatar
   
Dries committed
30
31
  $query = "";

Dries's avatar
   
Dries committed
32
  foreach ($array as $key => $value) {
Dries's avatar
   
Dries committed
33
    if ($key == 'pass') {
Kjartan's avatar
Kjartan committed
34
      $query .= "u.$key = '". md5($value) ."' AND ";
35
    }
Dries's avatar
   
Dries committed
36
    else {
Dries's avatar
   
Dries committed
37
      $query .= "u.$key = '". check_query($value) ."' AND ";
Dries's avatar
   
Dries committed
38
39
    }
  }
Dries's avatar
   
Dries committed
40
  $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
41
42

  $user = db_fetch_object($result);
Dries's avatar
   
Dries committed
43
44
  $user = drupal_unpack($user);

Dries's avatar
   
Dries committed
45

Dries's avatar
   
Dries committed
46
47
  user_module_invoke("load", $array, $user);

Dries's avatar
   
Dries committed
48
49
50
51
52
53
54
55
  return $user;
}

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

Kjartan's avatar
Kjartan committed
56
  $user_fields = user_fields();
Dries's avatar
   
Dries committed
57
  if ($account->uid) {
Dries's avatar
   
Dries committed
58
59
    user_module_invoke("update", $array, $account);

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

Dries's avatar
   
Dries committed
81
    db_query("UPDATE {users} SET $query timestamp = %d WHERE uid = %d", array_merge($v, array(time(), $account->uid)));
Dries's avatar
   
Dries committed
82

Dries's avatar
   
Dries committed
83
    $user = user_load(array('uid' => $account->uid));
Dries's avatar
   
Dries committed
84
85
  }
  else {
Dries's avatar
   
Dries committed
86
87
    $array['timestamp'] = time();
    $array['uid'] = db_next_id("{users}_uid");
Dries's avatar
   
Dries committed
88
89

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

Dries's avatar
   
Dries committed
107
    $fields[] = "data";
Dries's avatar
   
Dries committed
108
109
    $values[] = serialize($data);
    $s[] = "'%s'";
Dries's avatar
   
Dries committed
110

Dries's avatar
   
Dries committed
111
    db_query("INSERT INTO {users} (". implode(", ", $fields) .") VALUES (". implode(", ", $s) .")", $values);
Dries's avatar
   
Dries committed
112

Dries's avatar
   
Dries committed
113
    $user = user_load(array('name' => $array['name']));
Dries's avatar
   
Dries committed
114

Dries's avatar
   
Dries committed
115
    module_invoke_all('user', "insert", $array, $user);
Dries's avatar
   
Dries committed
116
117
118
119
120
121
122
123
124
  }

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

  if ($authmaps) {
Dries's avatar
   
Dries committed
125
    user_set_authmaps($user, $authmaps);
Dries's avatar
   
Dries committed
126
127
128
129
130
131
132
133
134
135
  }

  return $user;
}

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

Dries's avatar
   
Dries committed
136
  if (!$name) return t("You must enter a username.");
Dries's avatar
   
Dries committed
137
138
  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
139
  if (ereg("  ", $name)) return t("The username cannot contain multiple spaces in a row.");
Dries's avatar
   
Dries committed
140
141
  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
142
  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
143
144
145
}

function user_validate_mail($mail) {
Dries's avatar
   
Dries committed
146
  if (!$mail) return t("You must enter an e-mail address.");
Dries's avatar
   
Dries committed
147
  if ($mail && !valid_email_address($mail)) {
Dries's avatar
   
Dries committed
148
    return t("The e-mail address '%mail' is not valid.", array("%mail" => $mail));
Dries's avatar
   
Dries committed
149
150
151
  }
}

152
function user_validate_authmap($account, $authname, $module) {
Dries's avatar
   
Dries committed
153
  $result = db_query("SELECT COUNT(*) from {authmap} WHERE uid != %d AND authname = '%s'", $account->uid, $authname);
Dries's avatar
   
Dries committed
154
  if (db_result($result) > 0) {
Dries's avatar
   
Dries committed
155
    $name = module_invoke($module, 'info', 'name');
Dries's avatar
   
Dries committed
156
157
    return t("The %u ID %s is already taken.", array("%u" => ucfirst($name), "%s" => "<i>$authname</i>"));
  }
Dries's avatar
   
Dries committed
158
159
}

Dries's avatar
   
Dries committed
160
function user_password($length = 10) {
Dries's avatar
   
Dries committed
161
  /*
Dries's avatar
   
Dries committed
162
  ** Generate a random alphanumeric password.
Dries's avatar
   
Dries committed
163
164
  */

Dries's avatar
   
Dries committed
165
166
167
168
169
170
171
172
173
  // 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
174
  mt_srand((double)microtime() * 1000000);
Dries's avatar
   
Dries committed
175
176
177
178
179
180
181
182
183
184
185
186
187

  // 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
188
189
190
191
}

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

Dries's avatar
   
Dries committed
194
  // User #1 has all priveleges:
Dries's avatar
   
Dries committed
195
196
197
198
  if ($user->uid == 1) {
    return 1;
  }

Dries's avatar
   
Dries committed
199
200
201
202
  /*
  ** To reduce the number of SQL queries, we cache the user's permissions
  ** in a static variable.
  */
Dries's avatar
   
Dries committed
203

Dries's avatar
   
Dries committed
204
205
  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
206
207
  }

Dries's avatar
   
Dries committed
208
  return strstr($perm, $string);
Dries's avatar
   
Dries committed
209
210
211
212
213
}

function user_mail($mail, $subject, $message, $header) {
  if (variable_get("smtp_library", "") && file_exists(variable_get("smtp_library", ""))) {
    include_once variable_get("smtp_library", "");
214
    return user_mail_wrapper($mail, $subject, $message, $header);
Dries's avatar
   
Dries committed
215
216
  }
  else {
217
218
219
220
221
222
223
    /*
    ** 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
224
225
226
227
228
229
230
231
232
233
234
235
    **
    ** 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
    **
236
    */
Dries's avatar
   
Dries committed
237
238
239
240
    return mail(
      $mail,
      user_mail_encode($subject),
      str_replace("\r", "", $message),
Dries's avatar
   
Dries committed
241
      "MIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8; format=flowed\nContent-transfer-encoding: 8Bit\n" . $header
Dries's avatar
   
Dries committed
242
    );
Dries's avatar
   
Dries committed
243
244
245
  }
}

Kjartan's avatar
Kjartan committed
246
247
248
249
250
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
251
252
253
254
255
256
257
258
  **
  ** 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
259
  */
Kjartan's avatar
Kjartan committed
260
261
262
  $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
263
264
  $string = trim(preg_replace('/^(.*)$/m', " =?$charset?B?\\1?=", $string));
  return $string;
Dries's avatar
   
Dries committed
265
266
}

Dries's avatar
   
Dries committed
267
function user_deny($type, $mask) {
Dries's avatar
   
Dries committed
268
269
  $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
270

Dries's avatar
   
Dries committed
271
  return $deny && !$allow;
Dries's avatar
   
Dries committed
272
273
}

Dries's avatar
   
Dries committed
274
275
function user_fields() {
  static $fields;
Dries's avatar
   
Dries committed
276

Dries's avatar
   
Dries committed
277
  if (!$fields) {
Dries's avatar
   
Dries committed
278
    $result = db_query("SELECT * FROM {users} WHERE uid = 1");
Kjartan's avatar
Kjartan committed
279
280
281
    if (db_num_rows($result)) {
      $fields = array_keys(db_fetch_array($result));
    }
Dries's avatar
   
Dries committed
282
283
    else {
      // Make sure we return the default fields at least
Dries's avatar
   
Dries committed
284
      $fields = array('uid', 'name', 'pass', "mail", "mode", "sort", "threshold", "theme", "signature", "timestamp", "status", "timezone", "language", "init", "data", "rid");
Dries's avatar
   
Dries committed
285
    }
Dries's avatar
   
Dries committed
286
  }
Dries's avatar
   
Dries committed
287

Dries's avatar
   
Dries committed
288
  return $fields;
Dries's avatar
   
Dries committed
289
290
}

Dries's avatar
   
Dries committed
291
292
293
/*** Module hooks **********************************************************/

function user_perm() {
Dries's avatar
   
Dries committed
294
  return array("administer users", "access user list");
Dries's avatar
   
Dries committed
295
296
297
}

function user_search($keys) {
Dries's avatar
   
Dries committed
298
299
  $find = array();
  $result = db_query_range("SELECT * FROM {users} WHERE name LIKE '%%%s%%'", $keys, 0, 20);
Dries's avatar
   
Dries committed
300
  while ($account = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
301
    $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
302
  }
Dries's avatar
   
Dries committed
303
  return array(t("Matching users"), $find);
Dries's avatar
   
Dries committed
304
305
}

Dries's avatar
   
Dries committed
306
function user_block($op = "list", $delta = 0) {
Dries's avatar
   
Dries committed
307
308
  global $user;

Dries's avatar
   
Dries committed
309
  if ($op == "list") {
Dries's avatar
   
Dries committed
310
311
312
313
     $blocks[0]['info'] = t("User login");
     $blocks[1]['info'] = t("Navigation");
     $blocks[2]['info'] = t("Who's new");
     $blocks[3]['info'] = t("Who's online");
314

315
     return $blocks;
316
317
  }
  else {
Dries's avatar
   
Dries committed
318
319
    $block = array();

Dries's avatar
   
Dries committed
320
321
    switch ($delta) {
      case 0:
Dries's avatar
   
Dries committed
322

323
        if (!$user->uid) {
Dries's avatar
   
Dries committed
324
325
326
327
328
          /*
          ** For usability's sake, avoid showing two login forms on one
          ** page.
          */

Dries's avatar
   
Dries committed
329
          if (arg(0) == 'user' && arg(1) != "view") {
Dries's avatar
   
Dries committed
330
331
332
            return;
          }

Dries's avatar
   
Dries committed
333
334
          $edit = $_POST["edit"];

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

337
          /*
Dries's avatar
Dries committed
338
339
          ** Save the referer.  We record where the user came from such
          ** that we/ can redirect him after having completed the login
340
341
          ** form.
          */
Dries's avatar
Dries committed
342

343
          if (empty($edit)) {
Dries's avatar
Dries committed
344
            $edit["destination"] = $_GET["q"];
345
346
          }
          // 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
347

Dries's avatar
   
Dries committed
348
          $output .= form_hidden("destination", $edit["destination"]);
Dries's avatar
   
Dries committed
349
350
          $output .= form_textfield(t("Username"), 'name', $edit['name'], 15, 64);
          $output .= form_password(t("Password"), 'pass', $pass, 15, 64);
Dries's avatar
   
Dries committed
351
          $output .= form_submit(t("Log in"));
Dries's avatar
   
Dries committed
352
          $output .= "</div>\n";
Dries's avatar
   
Dries committed
353

Dries's avatar
   
Dries committed
354
355
          $output  = form($output, "post", url("user/login"));

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

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

Dries's avatar
   
Dries committed
363
          $block["subject"] = t("User login");
Dries's avatar
   
Dries committed
364
          $block["content"] = $output;
Dries's avatar
   
Dries committed
365
        }
Dries's avatar
Dries committed
366
        return $block;
367
      case 1:
Dries's avatar
   
Dries committed
368
369
        if ($menu = menu_tree()) {
           $block["subject"] = $user->uid ? $user->name : t("Navigation");
Dries's avatar
   
Dries committed
370
           $block["content"] = "<div class=\"menu\">". $menu ."</div>";
Dries's avatar
   
Dries committed
371
        }
372
        return $block;
Dries's avatar
   
Dries committed
373
      case 2:
374
375
376
        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)) {
377
            $items[] = format_name($account);
378
          }
Dries's avatar
   
Dries committed
379

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

382
383
384
385
          $block["subject"] = t("Who's new");
          $block["content"] = $output;
          return $block;
        }
Dries's avatar
   
Dries committed
386
387
      case 3:
        if (user_access("access content")) {
Dries's avatar
   
Dries committed
388
389
          /* count users with activity in the past defined period */
          $time_period = variable_get("user_block_seconds_online", 2700);
Dries's avatar
   
Dries committed
390

Dries's avatar
   
Dries committed
391
392
393
          /* 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 );
Dries's avatar
   
Dries committed
394
          $total_users = db_num_rows($users);
Dries's avatar
   
Dries committed
395
396
397
398

          /* 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")));
Dries's avatar
   
Dries committed
399
400
          }
          else {
Dries's avatar
   
Dries committed
401
402
403
404
            $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 user list") && $total_users) {
Dries's avatar
   
Dries committed
405

Dries's avatar
   
Dries committed
406
            // Display a list of currently online users
Dries's avatar
   
Dries committed
407
            $max_users = variable_get("user_block_max_list_count", 10);
Dries's avatar
   
Dries committed
408
409
            if ($max_users) {
              $items = array();
Dries's avatar
   
Dries committed
410

Dries's avatar
   
Dries committed
411
              while ($max_users-- && $uid = db_fetch_object($users)) {
Dries's avatar
   
Dries committed
412
                $items[] = format_name(user_load(array('uid' => $uid->uid)));
Dries's avatar
   
Dries committed
413
414
415
              }

              if ($items) {
Dries's avatar
   
Dries committed
416
417
418
                if (db_fetch_object($users)) {
                  $items[] = "...";
                }
Dries's avatar
   
Dries committed
419
420
                $output .= theme("item_list", $items, t("Online users:"));
              }
Dries's avatar
   
Dries committed
421
            }
Dries's avatar
   
Dries committed
422
          }
Dries's avatar
   
Dries committed
423
424
          $block["subject"] = t("Who's online");
          $block["content"] = $output;
Dries's avatar
   
Dries committed
425
        }
Dries's avatar
   
Dries committed
426
        return $block;
Dries's avatar
   
Dries committed
427
428
    }
  }
429
430
}

Dries's avatar
   
Dries committed
431
function theme_user_list($items, $title = NULL) {
Dries's avatar
   
Dries committed
432
  return theme("item_list", $items, $title);
Dries's avatar
   
Dries committed
433
434
}

Dries's avatar
   
Dries committed
435
function user_link($type) {
Dries's avatar
   
Dries committed
436
  global $user;
Dries's avatar
   
Dries committed
437

Dries's avatar
   
Dries committed
438
  if ($type == "system") {
Dries's avatar
Dries committed
439
    if ($user->uid) {
Dries's avatar
   
Dries committed
440
      menu('user', t("my account"), "user_page", 8);
Dries's avatar
   
Dries committed
441
442
      menu("user/edit", t("edit account"), "user_page", 0);
      menu("user/logout", t("log out"), "user_page", 10);
Dries's avatar
Dries committed
443
    }
Dries's avatar
   
Dries committed
444
    else {
Dries's avatar
   
Dries committed
445
      menu('user', t("my account"), "user_page", 8, MENU_HIDE);
Dries's avatar
   
Dries committed
446
    }
Dries's avatar
   
Dries committed
447

Dries's avatar
   
Dries committed
448
    if (user_access("administer users")) {
Dries's avatar
   
Dries committed
449
450
      menu("admin/user", t("accounts"), "user_admin", 2);
      menu("admin/user/create", t("new user"), "user_admin", 1);
Dries's avatar
   
Dries committed
451
      menu("admin/user/access", t("access rules"), "user_admin", 3);
452
453
      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
454
455
      menu("admin/user/role", t("roles"), "user_admin", 4);
      menu("admin/user/permission", t("permissions"), "user_admin", 5);
Dries's avatar
   
Dries committed
456
      menu("admin/user/help", t("help"), "user_help_page", 9);
Dries's avatar
   
Dries committed
457
      menu("admin/user/edit", t("edit user account"), "user_admin", 0, MENU_HIDE);
Dries's avatar
   
Dries committed
458
459
460
      if (module_exist('search')) {
        menu("admin/user/search", t("search"), "user_admin", 8);
      }
Dries's avatar
   
Dries committed
461
    }
Dries's avatar
   
Dries committed
462
463
464
465
466
  }
}

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

467
function user_get_authname($account, $module) {
Dries's avatar
   
Dries committed
468
469

  /*
470
  **  Called by authentication modules in order to edit/view their authmap information.
Dries's avatar
   
Dries committed
471
472
  */

Dries's avatar
   
Dries committed
473
  $result = db_query("SELECT authname FROM {authmap} WHERE uid = %d AND module = '%s'", $account->uid, $module);
474
475
476
  return db_result($result);
}

Dries's avatar
   
Dries committed
477

478
479
480
481
482
483
484
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
485
  $result = db_query("SELECT authname, module FROM {authmap} WHERE authname = '%s'", $authname);
Dries's avatar
   
Dries committed
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
  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
501
502
503
      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
504
505
506
      }
    }
    else {
Dries's avatar
   
Dries committed
507
      db_query("DELETE FROM {authmap} WHERE uid = %d AND module = '%s'", $account->uid, $module["1"]);
Dries's avatar
   
Dries committed
508
509
510
511
512
    }
  }
}

function user_auth_help_links() {
513
  $links = array();
Dries's avatar
   
Dries committed
514
  foreach (module_list() as $module) {
Dries's avatar
   
Dries committed
515
    if (module_hook($module, "auth")) {
Dries's avatar
   
Dries committed
516
      $links[] = l(module_invoke($module, 'info', 'name'), "user/help#$module");
Dries's avatar
   
Dries committed
517
518
519
520
521
522
523
    }
  }
  return $links;
}

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

Dries's avatar
   
Dries committed
524
function user_login($edit = array(), $msg = "") {
Dries's avatar
   
Dries committed
525
  global $user, $base_url;
Dries's avatar
   
Dries committed
526
527
528
529
530
531

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

  if ($user->uid) {
Dries's avatar
Dries committed
532
    drupal_goto('user');
Dries's avatar
   
Dries committed
533
534
  }

Dries's avatar
   
Dries committed
535
536
  if (user_deny('user', $edit['name'])) {
    $error = t("The name '%s' has been denied access.", array("%s" => $edit['name']));
Dries's avatar
   
Dries committed
537
  }
Dries's avatar
   
Dries committed
538
  else if ($edit['name'] && $edit['pass']) {
Dries's avatar
   
Dries committed
539
540

    /*
Dries's avatar
   
Dries committed
541
    ** Try to log in the user locally:
Dries's avatar
   
Dries committed
542
543
    */

Dries's avatar
   
Dries committed
544
    if (!$user->uid) {
Dries's avatar
   
Dries committed
545
546
547
      $name = $edit['name'];
      $pass = $edit['pass'];
      $user = user_load(array('name' => $name, 'pass' => $pass, "status" => 1));
Dries's avatar
   
Dries committed
548
549
550
551
552
553
    }

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

Dries's avatar
   
Dries committed
554
555
    if ($server = strrchr($edit['name'], "@")) {
      $name = substr($edit['name'], 0, strlen($edit['name']) - strlen($server));
556
      $server = substr($server, 1);
Dries's avatar
   
Dries committed
557
      $pass = $edit['pass'];
Dries's avatar
   
Dries committed
558
    }
Dries's avatar
   
Dries committed
559

Dries's avatar
   
Dries committed
560
    /*
Dries's avatar
   
Dries committed
561
    ** When possible, determine corresponding external auth source. Invoke
Dries's avatar
   
Dries committed
562
    ** source, and login user if successful:
Dries's avatar
   
Dries committed
563
564
    */

Dries's avatar
   
Dries committed
565
    if (!$user->uid && $server && $result = user_get_authmaps("$name@$server")) {
Dries's avatar
   
Dries committed
566
567
      if (module_invoke(key($result), "auth", $name, $pass, $server)) {
        $user = user_external_load("$name@$server");
Dries's avatar
   
Dries committed
568
        watchdog('user', "external load: $name@$server, module: ". key($result));
Dries's avatar
   
Dries committed
569
570
      }
      else {
Dries's avatar
   
Dries committed
571
        $error = t("Invalid password for %s.", array("%s" => "<i>$name@$server</i>"));
Dries's avatar
   
Dries committed
572
573
574
      }
    }

Dries's avatar
   
Dries committed
575
    /*
Dries's avatar
   
Dries committed
576
    ** Try each external authentication source in series. Register user if
Dries's avatar
   
Dries committed
577
    ** successful.
Dries's avatar
   
Dries committed
578
579
    */

Dries's avatar
   
Dries committed
580
    else if (!$user->uid && $server) {
Dries's avatar
   
Dries committed
581
582
583
      foreach (module_list() as $module) {
        if (module_hook($module, "auth")) {
          if (module_invoke($module, "auth", $name, $pass, $server)) {
Dries's avatar
   
Dries committed
584
585
586
            if (variable_get("user_register", 1) == 1 && !user_load(array('name' => "$name@$server"))) { //register this new user
              $user = user_save("", array('name' => "$name@$server", 'pass' => user_password(), "init" => "$name@$server", "status" => 1, "authname_$module" => "$name@$server", "rid" => _user_authenticated_id()));
              watchdog('user', "new user: $name@$server ($module ID)", l(t("edit user"), "admin/user/edit/$user->uid"));
Dries's avatar
   
Dries committed
587
588
589
590
591
592
593
594
              break;
            }
          }
        }
      }
    }

    if ($user->uid) {
Dries's avatar
   
Dries committed
595
      watchdog('user', "session opened for '$user->name'");
Dries's avatar
   
Dries committed
596

Dries's avatar
   
Dries committed
597
598
      // 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
599

Dries's avatar
   
Dries committed
600
601
      user_module_invoke("login", $edit, $user);

Dries's avatar
   
Dries committed
602
603
604
605
606
      /*
      ** If the user wants to be remembered, set the proper cookie such
      ** that the session won't expire.
      */

Dries's avatar
   
Dries committed
607
      $path = preg_replace("/.+\/\/[^\/]+(.*)/", "\$1/", $base_url);
Dries's avatar
   
Dries committed
608
      setcookie(session_name(), session_id(), FALSE, $path);
Dries's avatar
   
Dries committed
609
610

      /*
Dries's avatar
   
Dries committed
611
      ** Redirect the user to the page he logged on from.
Dries's avatar
   
Dries committed
612
613
      */

Dries's avatar
   
Dries committed
614
      drupal_goto($edit["destination"]);
Dries's avatar
   
Dries committed
615
616
617
    }
    else {
      if (!$error) {
Dries's avatar
   
Dries committed
618
        $error = t("Sorry.  Unrecognized username or password.") ." ". l(t("Have you forgotten your password?"), "user/password");
Dries's avatar
   
Dries committed
619
620
      }
      if ($server) {
Dries's avatar
   
Dries committed
621
        watchdog('user', "failed login for '$name@$server': $error");
Dries's avatar
   
Dries committed
622
623
      }
      else {
Dries's avatar
   
Dries committed
624
        watchdog('user', "failed login for '$name': $error");
Dries's avatar
   
Dries committed
625
626
627
628
629
630
631
632
633
      }
    }
  }

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

  if ($error) {
Dries's avatar
   
Dries committed
634
    drupal_set_message($error, 'error');
Dries's avatar
   
Dries committed
635
636
  }

Dries's avatar
   
Dries committed
637
  /*
Dries's avatar
   
Dries committed
638
  ** Save the referrer.  We record where the user came from such that we
Dries's avatar
   
Dries committed
639
640
641
  ** can redirect him after having completed the login form.
  */

642
  if (empty($edit)) {
Dries's avatar
Dries committed
643
    $edit["destination"] = $_GET["q"];
Dries's avatar
   
Dries committed
644
645
646
  }
  $output .= form_hidden("destination", $edit["destination"]);

Dries's avatar
   
Dries committed
647
648
649
650
  /*
  ** Display login form:
  */

Dries's avatar
   
Dries committed
651
652
653
  if ($msg) {
    $output .= "<p>$msg</p>";
  }
Dries's avatar
   
Dries committed
654
  if (count(user_auth_help_links()) > 0) {
Dries's avatar
   
Dries committed
655
    $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
656
657
  }
  else {
Dries's avatar
   
Dries committed
658
    $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
659
  }
Dries's avatar
   
Dries committed
660
  $output .= form_password(t("Password"), 'pass', $pass, 30, 64, t("Enter the password that accompanies your username."));
Dries's avatar
   
Dries committed
661
  $output .= form_submit(t("Log in"));
Dries's avatar
   
Dries committed
662
  $items[] = l(t("Request new password"), "user/password");
663
  if (variable_get("user_register", 1)) {
Dries's avatar
   
Dries committed
664
    $items[] = l(t("Create new account"), "user/register");
665
  }
Dries's avatar
   
Dries committed
666
  $output .= theme("item_list", $items);
Dries's avatar
   
Dries committed
667

Dries's avatar
   
Dries committed
668
669
  $output  = form_group(t('User login'), $output);

Dries's avatar
   
Dries committed
670
  return form($output, "post", url('user'));
Dries's avatar
   
Dries committed
671
672
}

673
function _user_authenticated_id() {
Dries's avatar
   
Dries committed
674
  return db_result(db_query("SELECT rid FROM {role} WHERE name = 'authenticated user'"));
675
676
}

Dries's avatar
   
Dries committed
677
678
679
680
function user_logout() {
  global $user;

  if ($user->uid) {
Dries's avatar
   
Dries committed
681
    watchdog('user', "session closed for '$user->name'");
Dries's avatar
   
Dries committed
682
683
684
685
686
687

    /*
    ** Destroy the current session:
    */

    session_destroy();
Dries's avatar
   
Dries committed
688
    module_invoke_all('user', "logout", NULL, $user);
Dries's avatar
   
Dries committed
689
690
691
    unset($user);
  }

Dries's avatar
Dries committed
692
  drupal_goto();
Dries's avatar
   
Dries committed
693
694
695
}

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

Dries's avatar
   
Dries committed
698
699
700
  if ($edit['name']) {
    $account = db_fetch_object(db_query("SELECT uid, name, mail FROM {users} WHERE status = 1 AND name = '%s'", $edit['name']));
    if (!$account) $error = t("Sorry. The username <i>%s</i> is not recognized.", array("%s" => $edit['name']));
701
  }
Dries's avatar
   
Dries committed
702
703
704
  else if ($edit['mail']) {
    $account = db_fetch_object(db_query("SELECT uid, name, mail FROM {users} WHERE status = 1 AND mail = '%s'", $edit['mail']));
    if (!$account) $error = t("Sorry. The e-mail address <i>%s</i> is not recognized.", array("%s" => $edit['mail']));
Kjartan's avatar
Kjartan committed
705
706
  }
  if ($account) {
Dries's avatar
   
Dries committed
707

708
      $from = variable_get("site_mail", ini_get("sendmail_from"));
Dries's avatar
   
Dries committed
709
710
711
712
713
714
      $pass = user_password();

      /*
      ** Save new password:
      */

Dries's avatar
   
Dries committed
715
      user_save($account, array('pass' => $pass));
Dries's avatar
   
Dries committed
716
717
718
719
720

      /*
      ** Mail new password:
      */

Dries's avatar
Dries committed
721
      $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()), '%login_uri' => url('user/login', NULL, NULL, TRUE), '%edit_uri' => url('user/edit', NULL, NULL, TRUE));
Dries's avatar
   
Dries committed
722
723
      $subject = _user_mail_text("pass_subject", $variables);
      $body = _user_mail_text("pass_body", $variables);
724
      $headers = "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from";
Dries's avatar
   
Dries committed
725
      $mail_success = user_mail($account->mail, $subject, $body, $headers);
Dries's avatar
   
Dries committed
726

Dries's avatar
   
Dries committed
727
      if ($mail_success) {
Dries's avatar
   
Dries committed
728
        watchdog('user', "mail password: '". $account->name ."' &lt;". $account->mail ."&gt;");
Dries's avatar
   
Dries committed
729
730
731
        return t("Your password and further instructions have been sent to your e-mail address.");
      }
      else {
Dries's avatar
   
Dries committed
732
        watchdog('error', "error mailing new password: '". $account->name ."' &lt;". $account->mail ."&gt;");
Dries's avatar
   
Dries committed
733
734
        return t("Unable to send mail. Please contact the site admin.");
      }
Dries's avatar
   
Dries committed
735
736
    }
    else {
737

Kjartan's avatar
Kjartan committed
738
739
    // Display error message if necessary.
    if ($error) {
Dries's avatar
   
Dries committed
740
      drupal_set_message($error, 'error');
Dries's avatar
   
Dries committed
741
742
743
744
745
746
    }

    /*
    ** Display form:
    */

Dries's avatar
   
Dries committed
747
    $output .= "<p>". t("Enter your username <strong><em>or</em></strong> your e-mail address.") ."</p>";
Dries's avatar
   
Dries committed
748
749
    $output .= form_textfield(t("Username"), 'name', $edit['name'], 30, 64);
    $output .= form_textfield(t("E-mail address"), "mail", $edit['mail'], 30, 64);
Dries's avatar
   
Dries committed
750
    $output .= form_submit(t("E-mail new password"));
Dries's avatar
   
Dries committed
751
    $items[] = l(t("Log in"), "user/login");
752
    if (variable_get("user_register", 1)) {
Dries's avatar
   
Dries committed
753
      $items[] = l(t("Create new account"), "user/register");
754
    }
Dries's avatar
   
Dries committed
755
    $output .= theme("item_list", $items);
Dries's avatar
   
Dries committed
756
    $output  = form_group(t('Request new password'), $output);
Dries's avatar
   
Dries committed
757
    return form($output, "post", url('user'));
Dries's avatar
   
Dries committed
758
759
760
761
  }
}

function user_register($edit = array()) {
Dries's avatar
   
Dries committed
762
  global $user, $base_url;
763
764
765
766
767
768

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

  if ($user->uid) {
Dries's avatar
Dries committed
769
    drupal_goto("user/edit");
770
  }
Dries's avatar
   
Dries committed
771

Dries's avatar
   
Dries committed
772
773
  if (!(is_null($edit['name']) && is_null($edit['mail']))) {
    if ($error = user_validate_name($edit['name'])) {
Dries's avatar
   
Dries committed
774
775
      // do nothing
    }
Dries's avatar
   
Dries committed
776
    else if ($error = user_validate_mail($edit['mail'])) {
Dries's avatar
   
Dries committed
777
778
      // do nothing
    }
Dries's avatar
   
Dries committed
779
780
    else if (user_deny('user', $edit['name'])) {
      $error = t("The name '%s' has been denied access.", array("%s" => $edit['name']));
Dries's avatar
   
Dries committed
781
    }
Dries's avatar
   
Dries committed
782
783
    else if (user_deny("mail", $edit['mail'])) {
      $error = t("The e-mail address '%s' has been denied access.", array("%s" => $edit['mail']));
Dries's avatar
   
Dries committed
784
    }
Dries's avatar
   
Dries committed
785
786
    else if (db_num_rows(db_query("SELECT name FROM {users} WHERE LOWER(name) = LOWER('%s')", $edit['name'])) > 0) {
      $error = t("The name '%s' is already taken.", array("%s" => $edit['name']));
Dries's avatar
   
Dries committed
787
    }
Dries's avatar
   
Dries committed
788
789
    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) {
      $error = t("The e-mail address '%s' is already taken.", array("%s" => $edit['mail']));
Dries's avatar
   
Dries committed
790
    }
Dries's avatar
   
Dries committed
791
    else if (variable_get("user_register", 1) == 0) {
Dries's avatar
   
Dries committed
792
793
      $error = t("Public registrations have been disabled by the site administrator.");
    }
794
795
796
    else {
      $success = true;
    }
Dries's avatar
   
Dries committed
797
798
799
800
  }

  if ($success) {

801
    $from = variable_get("site_mail", ini_get("sendmail_from"));
Dries's avatar
   
Dries committed
802
803
    $pass = user_password();

804
805
    // TODO: is this necessary? Won't session_write replicate this?
    unset($edit["session"]);
Dries's avatar
   
Dries committed
806
807
    $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));
    watchdog('user', "new user: '". $edit['name'] ."' &lt;". $edit['mail'] ."&gt;", l(t("edit user"), "admin/user/edit/$account->uid"));
Dries's avatar
   
Dries committed
808

Dries's avatar
Dries committed
809
    $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()), "%login_uri" => url('user/login', NULL, NULL, TRUE), "%edit_uri" => url("user/edit", NULL, NULL, TRUE));
810

Dries's avatar
   
Dries committed
811
    //the first user may login immediately, and receives a customized welcome e-mail.
812
    if ($account->uid == 1) {
Dries's avatar
   
Dries committed
813
      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%edit_uri\n\n--drupal"), $variables), "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from");
814
      // 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
815
      $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 <strong>$pass</strong>. You may change your password on the next page.</p><p>Please login below.</p>";
Dries's avatar
Dries committed
816
      $output .= form_hidden("destination", "user/edit");
Dries's avatar
   
Dries committed
817
818
      $output .= form_hidden('name', $account->name);
      $output .= form_hidden('pass', $pass);
819
820
821
822
      $output .= form_submit(t("Log in"));
      return form($output);
    }
    else {
823
824
825
826
827
      if ($account->status) {
        /*
        ** Create new user account, no administrator approval required:
        */

Dries's avatar
   
Dries committed
828
829
        $subject = _user_mail_text("welcome_subject", $variables);
        $body = _user_mail_text("welcome_body", $variables);
Dries's avatar
   
Dries committed
830
        user_mail($edit['mail'], $subject, $body, "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from");
831
832
833
834
835
836
        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
837
838
839
        $subject = _user_mail_text("approval_subject", $variables);
        $body = _user_mail_text("approval_body", $variables);

Dries's avatar
   
Dries committed
840
        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
841
        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", NULL, NULL, TRUE))), "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from");
Dries's avatar
   
Dries committed
842
        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.");
843
      }
844
    }
Dries's avatar
   
Dries committed
845
846
847
  }
  else {
    if ($error) {
Dries's avatar
   
Dries committed
848
      drupal_set_message($error, 'error');
Dries's avatar
   
Dries committed
849
    }
850
  }
Dries's avatar
   
Dries committed
851

852
  // display the registration form
853
  $output .= variable_get("user_registration_help", "");
854
  $affiliates = user_auth_help_links();
Dries's avatar
   
Dries committed
855
  if (count($affiliates) > 0) {
856
    $affiliates = implode(", ", $affiliates);
Dries's avatar
   
Dries committed
857
    $output .= "<p>". t("Note: if you have an account with one of our affiliates (%s), you may <a href=\"%login_uri\">login now</a> instead of registering.", array("%s" => $affiliates, "%login_uri" => url("user/login"))) ."</p>";
858
  }
Dries's avatar
   
Dries committed
859
860
  $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."));
  $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."));
861
  $output .= form_submit(t("Create new account"));
862
  $items[] = l(t("Request new password"), "user/password");
Dries's avatar
   
Dries committed
863
  $items[] = l(t("Log in"), "user/login");
Dries's avatar
   
Dries committed
864
  $output .= theme("item_list", $items);
Dries's avatar
   
Dries committed
865
  $output  = form_group(t('Create new user account'), $output);
Kjartan's avatar
Kjartan committed
866

867
  return form($output);
Dries's avatar
   
Dries committed
868
869
870
}

function user_edit($edit = array()) {
Dries's avatar
   
Dries committed
871
  global $user;
Dries's avatar
   
Dries committed
872
873

  if ($user->uid) {
Dries's avatar
   
Dries committed
874
875
    if (!(is_null($edit['name']) && is_null($edit['mail']))) {
      if ($error = user_validate_name($edit['name'])) {
Dries's avatar
   
Dries committed
876
877
        // do nothing
      }
Dries's avatar
   
Dries committed
878
      else if ($error = user_validate_mail($edit['mail'])) {
Dries's avatar
   
Dries committed
879
880
        // do nothing
      }
Dries's avatar
   
Dries committed
881
882
      else if (db_num_rows(db_query("SELECT uid FROM {users} WHERE uid != '$user->uid' AND LOWER(name) = LOWER('%s')", $edit['name'])) > 0) {
        $error = t("The name '%s' is already taken.", array("%s" => $edit['name']));
Dries's avatar
   
Dries committed
883
      }
Dries's avatar
   
Dries committed
884
885
      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) {
        $error = t("The e-mail address '%s' is already taken.", array("%s" => $edit['mail']));
Dries's avatar
   
Dries committed
886
887
888
889
890
891
892
      }
      else if ($user->uid) {
        /*
        ** If required, check that proposed passwords match.  If so,
        ** add new password to $edit.
        */

Dries's avatar
   
Dries committed
893
894
895
        if ($edit['pass1']) {
          if ($edit['pass1'] == $edit['pass2']) {
            $edit['pass'] = $edit['pass1'];
Dries's avatar
   
Dries committed
896
897
898
899
900
          }
          else {
            $error = t("The specified passwords do not match.");
          }
        }
Dries's avatar
   
Dries committed
901
        unset($edit['pass1'], $edit['pass2']);
Dries's avatar
   
Dries committed
902

Dries's avatar
   
Dries committed
903
904
905
906
907
908
        /*
        ** Validate input fields to make sure users don't submit
        ** invalid form data.
        */

        if (!user_access("administer users")) {
909
           if (array_intersect(array_keys($edit), array("rid", "init", "session"))) {
Dries's avatar
   
Dries committed
910
911
912
913
914
915
916
             watchdog("warning", "detected malicious attempt to alter a protected database field");
           }

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

Dries's avatar
   
Dries committed
918
919
920
921
922
923
        /*
        ** Have the modules that extend the user information validate
        ** their data.
        */

        foreach (module_list() as $module) {
Dries's avatar
   
Dries committed
924
925
          if (module_hook($module, 'user')) {
            $result = module_invoke($module, 'user', "edit_validate", $edit, $user);
Dries's avatar
   
Dries committed
926
927
928
929
930
931
932
933
934
935
          }
          if (is_array($result)) {
            $data = array_merge($data, $result);
          }
          elseif (is_string($result)) {
            $error = $result;
            break;
          }
        }

Dries's avatar
   
Dries committed
936
937
938
939
        if (!$error) {
          /*
          ** Save user information:
          */
Dries's avatar
   
Dries committed
940

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

Dries's avatar
   
Dries committed
943
          drupal_set_message(t("your user information changes have been saved."));
Dries's avatar
   
Dries committed
944
        }