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

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

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

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

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

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

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

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

  return $user;
}

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

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

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

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

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

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

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

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

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

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

  return $user;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Dries Buytaert's avatar
   
Dries Buytaert committed
281
282
283
284
285
286
287
/*** Module hooks **********************************************************/

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

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

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

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

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

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

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

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

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

329
          if (empty($edit)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
330
            $edit["destination"] = url($_GET["q"]);
331
332
          }
          // 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 Buytaert's avatar
Dries Buytaert committed
333

Dries Buytaert's avatar
   
Dries Buytaert committed
334
335
336
          $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 Buytaert's avatar
   
Dries Buytaert committed
337
338

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

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

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

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

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

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

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

368
        return $block;
Dries Buytaert's avatar
   
Dries Buytaert committed
369
      case 2:
370
371
372
373
374
        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 Buytaert's avatar
   
Dries Buytaert committed
375

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

378
379
380
381
          $block["subject"] = t("Who's new");
          $block["content"] = $output;
          return $block;
        }
Dries Buytaert's avatar
   
Dries Buytaert committed
382
383
    }
  }
384
385
}

Dries Buytaert's avatar
   
Dries Buytaert committed
386
function theme_user_list($items, $title = NULL) {
Dries Buytaert's avatar
   
Dries Buytaert committed
387
  return theme("item_list", $items, $title);
Dries Buytaert's avatar
   
Dries Buytaert committed
388
389
}

Dries Buytaert's avatar
   
Dries Buytaert committed
390
function user_link($type) {
Dries Buytaert's avatar
   
Dries Buytaert committed
391
392
393

  $links = array();

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

Dries Buytaert's avatar
   
Dries Buytaert committed
398
  if ($type == "system") {
Dries Buytaert's avatar
Dries Buytaert committed
399
400
    global $user;
    if ($user->uid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
401
402
403
      menu("user", t("my account"), "user_page", 8);
      menu("user/edit", t("edit account"), "user_page", 0);
      menu("user/logout", t("log out"), "user_page", 10);
Dries Buytaert's avatar
Dries Buytaert committed
404
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
405
406
407
    else {
      menu("user", t("my account"), "user_page", 8, 1);
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
408

Dries Buytaert's avatar
   
Dries Buytaert committed
409
    if (user_access("administer users")) {
Dries Buytaert's avatar
   
Dries Buytaert committed
410
411
412
      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);
413
414
      menu("admin/user/access/mail", t("e-mail rules"), "user_admin");
      menu("admin/user/access/user", t("name rules"), "user_admin");
Dries Buytaert's avatar
   
Dries Buytaert committed
415
416
417
      menu("admin/user/role", t("roles"), "user_admin", 4);
      menu("admin/user/permission", t("permissions"), "user_admin", 5);
      menu("admin/user/search", t("search"), "user_admin", 8);
Dries Buytaert's avatar
   
Dries Buytaert committed
418
      menu("admin/user/help", t("help"), "user_help_page", 9);
Dries Buytaert's avatar
   
Dries Buytaert committed
419
      menu("admin/user/edit", t("edit user account"), "user_admin", 0, 1); // hidden menu
Dries Buytaert's avatar
   
Dries Buytaert committed
420
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
421
422
  }

Dries Buytaert's avatar
   
Dries Buytaert committed
423
  return $links;
Dries Buytaert's avatar
   
Dries Buytaert committed
424
425
426
427
}

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

428
function user_get_authname($account, $module) {
Dries Buytaert's avatar
   
Dries Buytaert committed
429
430

  /*
431
  **  Called by authentication modules in order to edit/view their authmap information.
Dries Buytaert's avatar
   
Dries Buytaert committed
432
433
  */

Dries Buytaert's avatar
   
Dries Buytaert committed
434
  $result = db_query("SELECT authname FROM {authmap} WHERE uid = %d AND module = '%s'", $account->uid, $module);
435
436
437
  return db_result($result);
}

Dries Buytaert's avatar
   
Dries Buytaert committed
438

439
440
441
442
443
444
445
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 Buytaert's avatar
   
Dries Buytaert committed
446
  $result = db_query("SELECT authname, module FROM {authmap} WHERE authname = '%s'", $authname);
Dries Buytaert's avatar
   
Dries Buytaert committed
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
  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 Buytaert's avatar
   
Dries Buytaert committed
462
463
464
      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 Buytaert's avatar
   
Dries Buytaert committed
465
466
467
      }
    }
    else {
Dries Buytaert's avatar
   
Dries Buytaert committed
468
      db_query("DELETE FROM {authmap} WHERE uid = %d AND module = '%s'", $account->uid, $module["1"]);
Dries Buytaert's avatar
   
Dries Buytaert committed
469
470
471
472
473
    }
  }
}

function user_auth_help_links() {
474
  $links = array();
Dries Buytaert's avatar
   
Dries Buytaert committed
475
  foreach (module_list() as $module) {
Dries Buytaert's avatar
   
Dries Buytaert committed
476
    if (module_hook($module, "auth")) {
Dries Buytaert's avatar
   
Dries Buytaert committed
477
      $links[] = l(module_invoke($module, "info", "name"), "user/help#$module");
Dries Buytaert's avatar
   
Dries Buytaert committed
478
479
480
481
482
483
484
    }
  }
  return $links;
}

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

Dries Buytaert's avatar
   
Dries Buytaert committed
485
function user_login($edit = array(), $msg = "") {
Dries Buytaert's avatar
   
Dries Buytaert committed
486
  global $user, $base_url;
Dries Buytaert's avatar
   
Dries Buytaert committed
487
488
489
490
491
492

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

  if ($user->uid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
493
    drupal_goto(url("user"));
Dries Buytaert's avatar
   
Dries Buytaert committed
494
495
496
  }

  if (user_deny("user", $edit["name"])) {
Dries Buytaert's avatar
   
Dries Buytaert committed
497
    $error = t("The name '%s' has been denied access.", array("%s" => $edit["name"]));
Dries Buytaert's avatar
   
Dries Buytaert committed
498
499
500
501
  }
  else if ($edit["name"] && $edit["pass"]) {

    /*
Dries Buytaert's avatar
   
Dries Buytaert committed
502
    ** Try to log in the user locally:
Dries Buytaert's avatar
   
Dries Buytaert committed
503
504
    */

Dries Buytaert's avatar
   
Dries Buytaert committed
505
    if (!$user->uid) {
506
507
      $name = $edit["name"];
      $pass = $edit["pass"];
Dries Buytaert's avatar
   
Dries Buytaert committed
508
509
510
511
512
513
514
515
      $user = user_load(array("name" => $name, "pass" => $pass, "status" => 1));
    }

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

    if ($server = strrchr($edit["name"], "@")) {
516
517
518
      $name = substr($edit["name"], 0, strlen($edit["name"]) - strlen($server));
      $server = substr($server, 1);
      $pass = $edit["pass"];
Dries Buytaert's avatar
   
Dries Buytaert committed
519
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
520

Dries Buytaert's avatar
   
Dries Buytaert committed
521
    /*
Dries Buytaert's avatar
   
Dries Buytaert committed
522
    ** When possible, determine corresponding external auth source. Invoke source, and login user if successful:
Dries Buytaert's avatar
   
Dries Buytaert committed
523
524
    */

Dries Buytaert's avatar
   
Dries Buytaert committed
525
    if (!$user->uid && $server && $result = user_get_authmaps("$name@$server")) {
Dries Buytaert's avatar
   
Dries Buytaert committed
526
527
      if (module_invoke(key($result), "auth", $name, $pass, $server)) {
        $user = user_external_load("$name@$server");
Dries Buytaert's avatar
   
Dries Buytaert committed
528
        watchdog("user", "external load: $name@$server, module: ". key($result));
Dries Buytaert's avatar
   
Dries Buytaert committed
529
530
      }
      else {
Dries Buytaert's avatar
   
Dries Buytaert committed
531
        $error = t("Invalid password for %s.", array("%s" => "<i>$name@$server</i>"));
Dries Buytaert's avatar
   
Dries Buytaert committed
532
533
534
535
536
537
538
      }
    }

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

Dries Buytaert's avatar
   
Dries Buytaert committed
539
    else if (!$user->uid && $server) {
Dries Buytaert's avatar
   
Dries Buytaert committed
540
541
542
543
      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 Buytaert's avatar
Dries Buytaert committed
544
              $user = user_save("", array("name" => "$name@$server", "pass" => user_password(), "init" => "$name@$server", "status" => 1, "authname_$module" => "$name@$server", "rid" => _user_authenticated_id()));
Dries Buytaert's avatar
   
Dries Buytaert committed
545
              watchdog("user", "new user: $name@$server ($module ID)", l(t("edit user"), "admin/user/edit/$user->uid"));
Dries Buytaert's avatar
   
Dries Buytaert committed
546
547
548
549
550
551
552
553
554
555
              break;
            }
          }
        }
      }
    }

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

Dries Buytaert's avatar
   
Dries Buytaert committed
556
557
      // update the user table timestamp noting user has logged in
      db_query("UPDATE {users} SET timestamp = '%d' WHERE uid = '%s'", time(), $user->uid);
Dries Buytaert's avatar
   
Dries Buytaert committed
558
559
560
561
562
563

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

Dries Buytaert's avatar
   
Dries Buytaert committed
564
      $path = preg_replace("/.+\/\/[^\/]+(.*)/", "\$1/", $base_url);
Dries Buytaert's avatar
   
Dries Buytaert committed
565
      if ($edit["remember_me"]) {
Dries Buytaert's avatar
   
Dries Buytaert committed
566
        setcookie(session_name(), session_id(), time() + 3600 * 24 * 365, $path);
Dries Buytaert's avatar
   
Dries Buytaert committed
567
      }
Dries Buytaert's avatar
   
Dries Buytaert committed
568
      else {
Dries Buytaert's avatar
   
Dries Buytaert committed
569
        setcookie(session_name(), session_id(), FALSE, $path);
Dries Buytaert's avatar
   
Dries Buytaert committed
570
571
572
      }

      /*
Dries Buytaert's avatar
   
Dries Buytaert committed
573
      ** Redirect the user to the page he logged on from.
Dries Buytaert's avatar
   
Dries Buytaert committed
574
575
      */

Dries Buytaert's avatar
   
Dries Buytaert committed
576
      drupal_goto($edit["destination"]);
Dries Buytaert's avatar
   
Dries Buytaert committed
577
578
579
    }
    else {
      if (!$error) {
Dries Buytaert's avatar
   
Dries Buytaert committed
580
        $error = t("Sorry.  Unrecognized username or password.") ." ". l(t("Have you forgotten your password?"), "user/password");
Dries Buytaert's avatar
   
Dries Buytaert committed
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
      }
      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 Buytaert's avatar
   
Dries Buytaert committed
596
    $output .= theme("error", $error);
Dries Buytaert's avatar
   
Dries Buytaert committed
597
598
  }

Dries Buytaert's avatar
   
Dries Buytaert committed
599
  /*
Dries Buytaert's avatar
   
Dries Buytaert committed
600
  ** Save the referrer.  We record where the user came from such that we
Dries Buytaert's avatar
   
Dries Buytaert committed
601
602
603
  ** can redirect him after having completed the login form.
  */

604
  if (empty($edit)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
605
    $edit["destination"] = url($_GET["q"]);
Dries Buytaert's avatar
   
Dries Buytaert committed
606
607
608
  }
  $output .= form_hidden("destination", $edit["destination"]);

Dries Buytaert's avatar
   
Dries Buytaert committed
609
610
611
612
  /*
  ** Display login form:
  */

Dries Buytaert's avatar
   
Dries Buytaert committed
613
614
615
  if ($msg) {
    $output .= "<p>$msg</p>";
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
616
  if (count(user_auth_help_links()) > 0) {
Dries Buytaert's avatar
   
Dries Buytaert committed
617
    $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 Buytaert's avatar
   
Dries Buytaert committed
618
619
  }
  else {
Dries Buytaert's avatar
   
Dries Buytaert committed
620
    $output .= form_textfield(t("Username"), "name", $edit["name"], 30, 64, t("Enter your %s username.", array("%s" => variable_get("site_name", "local"))));
Dries Buytaert's avatar
   
Dries Buytaert committed
621
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
622
  $output .= form_password(t("Password"), "pass", $pass, 30, 64, t("Enter the password that accompanies your username."));
623
  $output .= form_checkbox(t("Remember me"), "remember_me", 1, 0, 0);
Dries Buytaert's avatar
   
Dries Buytaert committed
624
  $output .= form_submit(t("Log in"));
Dries Buytaert's avatar
   
Dries Buytaert committed
625
  $items[] = l(t("Request new password"), "user/password");
626
  if (variable_get("user_register", 1)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
627
    $items[] = l(t("Create new account"), "user/register");
628
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
629
  $output .= theme("item_list", $items);
Dries Buytaert's avatar
   
Dries Buytaert committed
630

Dries Buytaert's avatar
   
Dries Buytaert committed
631
  return form($output, "post", url("user"));
Dries Buytaert's avatar
   
Dries Buytaert committed
632
633
}

634
function _user_authenticated_id() {
Dries Buytaert's avatar
   
Dries Buytaert committed
635
  return db_result(db_query("SELECT rid FROM {role} WHERE name = 'authenticated user'"));
636
637
}

Dries Buytaert's avatar
   
Dries Buytaert committed
638
639
640
641
642
643
644
645
646
647
648
649
650
651
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 Buytaert's avatar
   
Dries Buytaert committed
652
  drupal_goto(url());
Dries Buytaert's avatar
   
Dries Buytaert committed
653
654
655
}

function user_pass($edit = array()) {
Dries Buytaert's avatar
   
Dries Buytaert committed
656
657
  global $base_url;

Kjartan Mannes's avatar
Kjartan Mannes committed
658
  if ($edit["name"]) {
Dries Buytaert's avatar
   
Dries Buytaert committed
659
    $account = db_fetch_object(db_query("SELECT uid, name, mail FROM {users} WHERE name = '%s'", $edit["name"]));
Dries Buytaert's avatar
   
Dries Buytaert committed
660
    if (!$account) $error = t("Sorry. The username <i>%s</i> is not recognized.", array("%s" => $edit["name"]));
661
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
662
  else if ($edit["mail"]) {
Dries Buytaert's avatar
   
Dries Buytaert committed
663
    $account = db_fetch_object(db_query("SELECT uid, name, mail FROM {users} WHERE mail = '%s'", $edit["mail"]));
Dries Buytaert's avatar
   
Dries Buytaert committed
664
    if (!$account) $error = t("Sorry. The e-mail address <i>%s</i> is not recognized.", array("%s" => $edit["mail"]));
Kjartan Mannes's avatar
Kjartan Mannes committed
665
666
  }
  if ($account) {
Dries Buytaert's avatar
   
Dries Buytaert committed
667

668
      $from = variable_get("site_mail", ini_get("sendmail_from"));
Dries Buytaert's avatar
   
Dries Buytaert committed
669
670
671
672
673
674
675
676
677
678
679
680
      $pass = user_password();

      /*
      ** Save new password:
      */

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

      /*
      ** Mail new password:
      */

Dries Buytaert's avatar
   
Dries Buytaert committed
681
      $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 Buytaert's avatar
   
Dries Buytaert committed
682
683
      $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);
684
      $headers = "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from";
Dries Buytaert's avatar
   
Dries Buytaert committed
685
      $mail_success = user_mail($account->mail, $subject, $body, $headers);
Dries Buytaert's avatar
   
Dries Buytaert committed
686

Dries Buytaert's avatar
   
Dries Buytaert committed
687
688
689
690
691
692
693
694
      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 Buytaert's avatar
   
Dries Buytaert committed
695
696
    }
    else {
697

Kjartan Mannes's avatar
Kjartan Mannes committed
698
699
    // Display error message if necessary.
    if ($error) {
Dries Buytaert's avatar
   
Dries Buytaert committed
700
      $output .= theme("error", $error);
Dries Buytaert's avatar
   
Dries Buytaert committed
701
702
703
704
705
706
    }

    /*
    ** Display form:
    */

Dries Buytaert's avatar
   
Dries Buytaert committed
707
    $output .= "<p>". sprintf(t("Enter your username %sor%s your e-mail address."), "<b><i>", "</i></b>") ."</p>";
Dries Buytaert's avatar
   
Dries Buytaert committed
708
709
710
    $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 Buytaert's avatar
   
Dries Buytaert committed
711
    $items[] = l(t("Log in"), "user/login");
712
    if (variable_get("user_register", 1)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
713
      $items[] = l(t("Create new account"), "user/register");
714
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
715
    $output .= theme("item_list", $items);
Dries Buytaert's avatar
   
Dries Buytaert committed
716

Dries Buytaert's avatar
   
Dries Buytaert committed
717
    return form($output, "post", url("user"));
Dries Buytaert's avatar
   
Dries Buytaert committed
718
719
720
721
  }
}

function user_register($edit = array()) {
Dries Buytaert's avatar
   
Dries Buytaert committed
722
  global $user, $base_url;
723
724
725
726
727
728

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

  if ($user->uid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
729
    drupal_goto(url("user/edit"));
730
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
731
732
733
734
735
736
737
738
739

  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 Buytaert's avatar
   
Dries Buytaert committed
740
      $error = t("The name '%s' has been denied access.", array("%s" => $edit["name"]));
Dries Buytaert's avatar
   
Dries Buytaert committed
741
742
    }
    else if (user_deny("mail", $edit["mail"])) {
Dries Buytaert's avatar
   
Dries Buytaert committed
743
      $error = t("The e-mail address '%s' has been denied access.", array("%s" => $edit["mail"]));
Dries Buytaert's avatar
   
Dries Buytaert committed
744
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
745
    else if (db_num_rows(db_query("SELECT name FROM {users} WHERE LOWER(name) = LOWER('%s')", $edit["name"])) > 0) {
Dries Buytaert's avatar
   
Dries Buytaert committed
746
      $error = t("The name '%s' is already taken.", array("%s" => $edit["name"]));
Dries Buytaert's avatar
   
Dries Buytaert committed
747
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
748
    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 Buytaert's avatar
   
Dries Buytaert committed
749
      $error = t("The e-mail address '%s' is already taken.", array("%s" => $edit["mail"]));
Dries Buytaert's avatar
   
Dries Buytaert committed
750
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
751
    else if (variable_get("user_register", 1) == 0) {
Dries Buytaert's avatar
   
Dries Buytaert committed
752
753
754
      $error = t("Public registrations have been disabled by the site administrator.");
    }
    else {
Dries Buytaert's avatar
   
Dries Buytaert committed
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
      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 Buytaert's avatar
   
Dries Buytaert committed
770
771
772
773
774
    }
  }

  if ($success) {

775
    $from = variable_get("site_mail", ini_get("sendmail_from"));
Dries Buytaert's avatar
   
Dries Buytaert committed
776
777
    $pass = user_password();

778
    // create new user account, noting whether administrator approval is required
779
780
781
    user_role_init();
    // TODO: is this necessary? Won't session_write replicate this?
    unset($edit["session"]);
782
    $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 Buytaert's avatar
   
Dries Buytaert committed
783
    watchdog("user", "new user: '". $edit["name"] ."' &lt;". $edit["mail"] ."&gt;", l(t("edit user"), "admin/user/edit/$account->uid"));
Dries Buytaert's avatar
   
Dries Buytaert committed
784

Dries Buytaert's avatar
   
Dries Buytaert committed
785
    $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()));
786

Dries Buytaert's avatar
   
Dries Buytaert committed
787
    //the first user may login immediately, and receives a customized welcome e-mail.
788
    if ($account->uid == 1) {
Dries Buytaert's avatar
   
Dries Buytaert committed
789
      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");
790
      // 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 Buytaert's avatar
   
Dries Buytaert committed
791
      $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 Buytaert's avatar
   
Dries Buytaert committed
792
      $output .= form_hidden("destination", url("user/edit"));
793
      $output .= form_hidden("name", $account->name);
794
795
796
797
798
      $output .= form_hidden("pass", $pass);
      $output .= form_submit(t("Log in"));
      return form($output);
    }
    else {
799
800
801
802
803
      if ($account->status) {
        /*
        ** Create new user account, no administrator approval required:
        */

Dries Buytaert's avatar
   
Dries Buytaert committed
804
805
        $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);
806
807
808
809
810
811
812
        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 Buytaert's avatar
   
Dries Buytaert committed
813
814
        $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);
815
        user_mail($edit["mail"], $subject, $body, "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from");
Dries Buytaert's avatar
   
Dries Buytaert committed
816
        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 Buytaert's avatar
   
Dries Buytaert committed
817
        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.");
818
      }
819
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
820
821
822
  }
  else {
    if ($error) {
Dries Buytaert's avatar
   
Dries Buytaert committed
823
      $output .= theme("error", $error);
Dries Buytaert's avatar
   
Dries Buytaert committed
824
    }
825
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
826

827
  // display the registration form
828
  $output .= variable_get("user_registration_help", "");
829
  $affiliates = user_auth_help_links();
Dries Buytaert's avatar
   
Dries Buytaert committed
830
  if (count($affiliates) > 0) {
831
    $affiliates = implode(", ", $affiliates);
Dries Buytaert's avatar
   
Dries Buytaert committed
832
    $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>";
833
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
834
  $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."));
835
836
837
838
  $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 Buytaert's avatar
   
Dries Buytaert committed
839
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
840
  }
841
  $output .= form_submit(t("Create new account"));
842
  $items[] = l(t("Request new password"), "user/password");
Dries Buytaert's avatar
   
Dries Buytaert committed
843
  $items[] = l(t("Log in"), "user/login");
Dries Buytaert's avatar
   
Dries Buytaert committed
844
  $output .= theme("item_list", $items);
Kjartan Mannes's avatar
Kjartan Mannes committed
845

846
  return form($output);
Dries Buytaert's avatar
   
Dries Buytaert committed
847
848
849
}

function user_edit($edit = array()) {
Dries Buytaert's avatar
   
Dries Buytaert committed
850
  global $user;
Dries Buytaert's avatar
   
Dries Buytaert committed
851
852
853
854
855
856
857
858
859

  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 Buytaert's avatar
   
Dries Buytaert committed
860
      else if (db_num_rows(db_query("SELECT uid FROM {users} WHERE uid != '$user->uid' AND LOWER(name) = LOWER('%s')", $edit["name"])) > 0) {
Dries Buytaert's avatar
   
Dries Buytaert committed
861
        $error = t("The name '%s' is already taken.", array("%s" => $edit["name"]));
Dries Buytaert's avatar
   
Dries Buytaert committed
862
      }
Dries Buytaert's avatar
   
Dries Buytaert committed
863
      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 Buytaert's avatar
   
Dries Buytaert committed
864
        $error = t("The e-mail address '%s' is already taken.", array("%s" => $edit["mail"]));
Dries Buytaert's avatar
   
Dries Buytaert committed
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
      }
      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 Buytaert's avatar
   
Dries Buytaert committed
882
883
884
885
886
887
        /*
        ** Validate input fields to make sure users don't submit
        ** invalid form data.
        */

        if (!user_access("administer users")) {
888
           if (array_intersect(array_keys($edit), array("rid", "init", "session"))) {
Dries Buytaert's avatar
   
Dries Buytaert committed
889
890
891
892
893
894
895
             watchdog("warning", "detected malicious attempt to alter a protected database field");
           }

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

Dries Buytaert's avatar
   
Dries Buytaert committed
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
        /*
        ** 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 Buytaert's avatar
   
Dries Buytaert committed
915
916
917
918
        if (!$error) {
          /*
          ** Save user information:
          */
Dries Buytaert's avatar
   
Dries Buytaert committed
919

Dries Buytaert's avatar
   
Dries Buytaert committed
920
          $user = user_save($user, array_merge($edit, $data));
Dries Buytaert's avatar
   
Dries Buytaert committed
921

Dries Buytaert's avatar
   
Dries Buytaert committed
922
          $output .= status(t("your user information changes have been saved."));
Dries Buytaert's avatar
   
Dries Buytaert committed
923
        }
Dries Buytaert's avatar
   
Dries Buytaert committed
924
925
926
927
      }
    }

    if ($error) {
Dries Buytaert's avatar
   
Dries Buytaert committed
928
      $output .= theme("error", $error);
Dries Buytaert's avatar
   
Dries Buytaert committed
929
930
    }

Kjartan Mannes's avatar
Kjartan Mannes committed
931
932
933
934
    if (!$edit) {
      $edit = object2array($user);
    }

Dries Buytaert's avatar
   
Dries Buytaert committed
935
    $output .= form_textfield(t("Username"), "name", $edit["name"], 30, 55, t("Your full name or your preferred username: only letters, numbers and spaces are allowed."));
Kjartan Mannes's avatar
Kjartan Mannes committed
936
    $output .= form_textfield(t("E-mail address"), "mail", $edit["mail"], 30, 55, t("Insert a valid e-mail address.  All e-mails from the system will be sent to this address. The e-mail address is not made public and will only be used if you wish to receive a new password or wish to receive certain news or notifications by e-mail."));
Dries Buytaert's avatar
   
Dries Buytaert committed
937

Dries Buytaert's avatar
   
Dries Buytaert committed
938
    $output .= implode("\n", module_invoke_all("user", "edit_form", $edit, $user));
Dries Buytaert's avatar
   
Dries Buytaert committed
939

Dries Buytaert's avatar
   
Dries Buytaert committed
940
    $output .= form_item(t("Password"), "<input type=\"password\" name=\"edit[pass1]\" size=\"12\" maxlength=\"24\" /> <input type=\"password\" name=\"edit[pass2]\" size=\"12\" maxlength=\"24\" />", t("Enter your new password twice if you want to change your current password or leave it blank if you are happy with your current password."));
Dries Buytaert's avatar
   
Dries Buytaert committed
941
    $output .= form_submit(t("Save user information"));
942

Dries Buytaert's avatar
   
Dries Buytaert committed
943
    $output = form($output, "post", 0, array("enctype" => "multipart/form-data"));
Dries Buytaert's avatar
Dries Buytaert committed
944
      // the "enctype" attribute is required to upload files such as avatars
Dries Buytaert's avatar
   
Dries Buytaert committed
945
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
946
947
948
  else {
    $output = user_login();
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
949
950
951
952
953

  return $output;
}

function user_view($uid = 0) {
Dries Buytaert's avatar
   
Dries Buytaert committed
954
  global $user;
Dries Buytaert's avatar
   
Dries Buytaert committed
955
956
957
958
959
960

  if (!$uid) {
    $uid = $user->uid;
  }

  if ($user->uid && $user->uid == $uid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
961
    $output = form_item(t("Name"), "$user->name ($user->init)");
962
    $output .= form_item(t("E-mail address"), $user->mail, t("Please note that only you can see your own e-mail address - it is not publicly visible."));
Dries Buytaert's avatar
   
Dries Buytaert committed
963

Dries Buytaert's avatar
   
Dries Buytaert committed
964
    $output .= implode("\n", module_invoke_all("user", "view_private", "", $user));
Dries Buytaert's avatar
   
Dries Buytaert committed
965

Dries Buytaert's avatar
   
Dries Buytaert committed
966
    print theme("page", $output, $user->name);
Dries Buytaert's avatar
   
Dries Buytaert committed
967
968
  }
  else if ($uid && $account = user_load(array("uid" => $uid, "status" => 1))) {
Dries Buytaert's avatar
   
Dries Buytaert committed
969
    $output = form_item(t("Name"), $account->name);
Dries Buytaert's avatar
   
Dries Buytaert committed
970

Dries Buytaert's avatar
   
Dries Buytaert committed
971
    $output .= implode("\n", module_invoke_all("user", "view_public", "", $account));
Dries Buytaert's avatar
   
Dries Buytaert committed
972

Dries Buytaert's avatar
   
Dries Buytaert committed
973
974
975
976
    if (user_access("administer users")) {
      $output .= form_item(t("Administration"), l(t("edit account"), "admin/user/edit/$account->uid"));
    }

Dries Buytaert's avatar
   
Dries Buytaert committed
977