user.module 89.8 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.* FROM {users} u 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
  $user = drupal_unpack($user);
Dries's avatar
   
Dries committed
44
  $user->roles = array();
Dries's avatar
   
Dries committed
45

Dries's avatar
   
Dries committed
46
47
48
49
50
  $result = db_query("SELECT r.rid, r.name FROM {role} r INNER JOIN {users_roles} ur ON ur.rid = r.rid WHERE ur.uid = %d", $user->uid);

  while ($role = db_fetch_object($result)) {
    $user->roles[$role->rid] = $role->name;
  }
Dries's avatar
   
Dries committed
51

Dries's avatar
   
Dries committed
52
53
  user_module_invoke("load", $array, $user);

Dries's avatar
   
Dries committed
54
55
56
57
58
59
60
61
  return $user;
}

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

Kjartan's avatar
Kjartan committed
62
  $user_fields = user_fields();
Dries's avatar
   
Dries committed
63
  if ($account->uid) {
Dries's avatar
   
Dries committed
64
65
    user_module_invoke("update", $array, $account);

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

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

Dries's avatar
   
Dries committed
89
90
91
92
93
94
95
    // reload user roles
    db_query("DELETE FROM {users_roles} WHERE uid = %d", $account->uid);

    foreach ($array['rid'] as $rid) {
      db_query("INSERT INTO {users_roles} (uid, rid) VALUES (%d, %d)", $account->uid, $rid);
    }

Dries's avatar
   
Dries committed
96
    $user = user_load(array('uid' => $account->uid));
Dries's avatar
   
Dries committed
97
98
  }
  else {
Dries's avatar
   
Dries committed
99
100
    $array['created'] = time();
    $array['changed'] = time();
Dries's avatar
   
Dries committed
101
    $array['uid'] = db_next_id("{users}_uid");
Dries's avatar
   
Dries committed
102
103

    foreach ($array as $key => $value) {
Dries's avatar
   
Dries committed
104
      if ($key == 'pass') {
Dries's avatar
   
Dries committed
105
        $fields[] = check_query($key);
Dries's avatar
   
Dries committed
106
107
        $values[] = md5($value);
        $s[] = "'%s'";
Dries's avatar
   
Dries committed
108
109
      }
      else if (substr($key, 0, 4) !== "auth") {
Kjartan's avatar
Kjartan committed
110
        if (in_array($key, $user_fields)) {
Dries's avatar
   
Dries committed
111
          $fields[] = check_query($key);
Dries's avatar
   
Dries committed
112
113
          $values[] = $value;
          $s[] = "'%s'";
Dries's avatar
   
Dries committed
114
115
116
117
        }
        else {
          $data[$key] = $value;
        }
Dries's avatar
   
Dries committed
118
119
120
      }
    }

Dries's avatar
   
Dries committed
121
    $fields[] = "data";
Dries's avatar
   
Dries committed
122
123
    $values[] = serialize($data);
    $s[] = "'%s'";
Dries's avatar
   
Dries committed
124

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

Dries's avatar
   
Dries committed
127
128
129
130
131
132
133
    // reload user roles (delete just to be safe)
    db_query("DELETE FROM {users_roles} WHERE uid = %d", $array['uid']);

    foreach ($array['rid'] as $rid) {
      db_query("INSERT INTO {users_roles} (uid, rid) VALUES (%d, %d)", $array['uid'], $rid);
    }

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

Dries's avatar
   
Dries committed
136
    module_invoke_all('user', 'insert', $array, $user);
Dries's avatar
   
Dries committed
137
138
139
  }

  foreach ($array as $key => $value) {
Dries's avatar
   
Dries committed
140
    if (substr($key, 0, 4) == 'auth') {
Dries's avatar
   
Dries committed
141
142
143
144
145
      $authmaps[$key] = $value;
    }
  }

  if ($authmaps) {
Dries's avatar
   
Dries committed
146
    user_set_authmaps($user, $authmaps);
Dries's avatar
   
Dries committed
147
148
149
150
151
152
153
154
155
156
  }

  return $user;
}

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

Dries's avatar
   
Dries committed
157
  if (!$name) return t("You must enter a username.");
Dries's avatar
   
Dries committed
158
159
  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
160
  if (ereg('  ', $name)) return t("The username cannot contain multiple spaces in a row.");
Dries's avatar
   
Dries committed
161
162
  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
163
  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
164
165
166
}

function user_validate_mail($mail) {
Dries's avatar
   
Dries committed
167
  if (!$mail) return t("You must enter an e-mail address.");
Dries's avatar
   
Dries committed
168
  if ($mail && !valid_email_address($mail)) {
Dries's avatar
   
Dries committed
169
    return t("The e-mail address '%mail' is not valid.", array("%mail" => $mail));
Dries's avatar
   
Dries committed
170
171
172
  }
}

Dries's avatar
   
Dries committed
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
function user_validate_picture($file, &$edit, $user) {

  // initialize the picture:
  $edit['picture'] = $user->picture;

  // check that uploaded file is an image, with a maximum file size and maximum height/width
  $extension = strtolower(strrchr($file->name, "."));
  $size = getimagesize($file->path);
  list($maxwidth, $maxheight) = explode("x", variable_get('user_picture_dimensions', "85x85"));

  if ((!in_array($size[2], array(1, 2, 3))) || (!in_array($extension, array(".gif", ".jpg", ".png", ".jpeg")))) {
    $error = t("The uploaded file was not an image.");
  }
  else if ($file->size > (variable_get('user_picture_file_size', "30") * 1000)) {
    $error = t("The uploaded image is too large; the maximum file size is %a kB.", array("%a" => variable_get('user_picture_file_size', "30")));
  }
  else if ($size[0] > $maxwidth || $size[1] > $maxheight) {
    $error = t("The uploaded image is too large; the maximum dimensions are %a pixels.", array("%a" => variable_get('user_picture_dimensions', "85x85")));
  }
  else if ($file = file_save_upload('picture', variable_get('user_picture_path', "pictures") . FILE_SEPARATOR .'picture-'. $user->uid . $extension, 1)) {
    $edit['picture'] = $file->path;
  }
  else {
    $error = t("Failed to upload the picture image; the '%directory' directory doesn't exist.", array("%directory" => variable_get('user_picture_path', "pictures")));
  }

  return $error;
}

202
function user_validate_authmap($account, $authname, $module) {
Dries's avatar
   
Dries committed
203
  $result = db_query("SELECT COUNT(*) from {authmap} WHERE uid != %d AND authname = '%s'", $account->uid, $authname);
Dries's avatar
   
Dries committed
204
  if (db_result($result) > 0) {
Dries's avatar
   
Dries committed
205
    $name = module_invoke($module, 'info', 'name');
Dries's avatar
   
Dries committed
206
207
    return t("The %u ID %s is already taken.", array("%u" => ucfirst($name), "%s" => "<i>$authname</i>"));
  }
Dries's avatar
   
Dries committed
208
209
}

Dries's avatar
   
Dries committed
210
function user_password($length = 10) {
Dries's avatar
   
Dries committed
211
  /*
Dries's avatar
   
Dries committed
212
  ** Generate a random alphanumeric password.
Dries's avatar
   
Dries committed
213
214
  */

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

  // 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
238
239
240
241
}

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

Dries's avatar
   
Dries committed
244
  // User #1 has all priveleges:
Dries's avatar
   
Dries committed
245
246
247
248
  if ($user->uid == 1) {
    return 1;
  }

Dries's avatar
   
Dries committed
249
250
251
252
  /*
  ** To reduce the number of SQL queries, we cache the user's permissions
  ** in a static variable.
  */
Dries's avatar
   
Dries committed
253

Dries's avatar
   
Dries committed
254
  if ($perm === 0) {
Dries's avatar
   
Dries committed
255
256
257
258
259
    $result = db_query("SELECT DISTINCT p.perm FROM {role} r INNER JOIN {permission} p ON p.rid = r.rid INNER JOIN {users_roles} ur ON ur.rid = r.rid WHERE ur.uid = %d", $user->uid);

    while ($row = db_fetch_object($result)) {
      $perm .= "$row->perm, ";
    }
Dries's avatar
   
Dries committed
260
261
  }

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

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

Kjartan's avatar
Kjartan committed
300
301
302
303
304
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
305
306
  **
  ** Notes:
307
  **   - Only encode strings that contain non-ASCII characters.
Kjartan's avatar
Kjartan committed
308
309
310
311
312
313
  **   - The chunks come in groupings of 4 bytes when using base64
  **     encoded.
  **   - trim() is used to ensure that no extra spacing is added by
  **     chunk_split() or preg_replace().
  **   - Using \n as the chunk separator may cause problems on some
  **     systems and may have to be changed to \r\n or \r.
Kjartan's avatar
Kjartan committed
314
  */
315
316
317
318
319
320
  if (!preg_match('/^[\x20-\x7E]*$/', $string)) {
    $chunk_size = 75 - 7 - strlen($charset);
    $chunk_size -= $chunk_size % 4;
    $string = trim(chunk_split(base64_encode($string), $chunk_size, "\n"));
    $string = trim(preg_replace('/^(.*)$/m', " =?$charset?B?\\1?=", $string));
  }
Kjartan's avatar
Kjartan committed
321
  return $string;
Dries's avatar
   
Dries committed
322
323
}

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

Dries's avatar
   
Dries committed
328
  return $deny && !$allow;
Dries's avatar
   
Dries committed
329
330
}

Dries's avatar
   
Dries committed
331
332
function user_fields() {
  static $fields;
Dries's avatar
   
Dries committed
333

Dries's avatar
   
Dries committed
334
  if (!$fields) {
Dries's avatar
   
Dries committed
335
    $result = db_query("SELECT * FROM {users} WHERE uid = 1");
Kjartan's avatar
Kjartan committed
336
337
338
    if (db_num_rows($result)) {
      $fields = array_keys(db_fetch_array($result));
    }
Dries's avatar
   
Dries committed
339
340
    else {
      // Make sure we return the default fields at least
Dries's avatar
   
Dries committed
341
      $fields = array('uid', 'name', 'pass', 'mail', 'picture', 'mode', 'sort', 'threshold', 'theme', 'signature', 'created', 'changed', 'status', 'timezone', 'language', 'init', 'data');
Dries's avatar
   
Dries committed
342
    }
Dries's avatar
   
Dries committed
343
  }
Dries's avatar
   
Dries committed
344

Dries's avatar
   
Dries committed
345
  return $fields;
Dries's avatar
   
Dries committed
346
347
}

Dries's avatar
   
Dries committed
348
349
350
/*** Module hooks **********************************************************/

function user_perm() {
Dries's avatar
   
Dries committed
351
  return array("administer users", "access user list");
Dries's avatar
   
Dries committed
352
353
}

Dries's avatar
   
Dries committed
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
function user_file_download($file) {
  if (strpos($file, variable_get('user_picture_path', "pictures") . FILE_SEPARATOR . 'picture-') === 0) {
    list($width, $height, $type, $attr) = getimagesize(file_create_path($file));
    $types = array(
      IMAGETYPE_GIF => 'image/gif',
      IMAGETYPE_JPEG => 'image/jpeg',
      IMAGETYPE_PNG => 'image/png',
      IMAGETYPE_SWF => 'application/x-shockwave-flash',
      IMAGETYPE_PSD => 'image/psd',
      IMAGETYPE_BMP => 'image/bmp',
      IMAGETYPE_TIFF_II => 'image/tiff',
      IMAGETYPE_TIFF_MM  => 'image/tiff',
      IMAGETYPE_JPC => 'application/octet-stream',
      IMAGETYPE_JP2 => 'image/jp2',
      IMAGETYPE_JPX => 'application/octet-stream',
      IMAGETYPE_JB2 => 'application/octet-stream',
      IMAGETYPE_SWC => 'application/x-shockwave-flash',
      IMAGETYPE_IFF => 'image/iff',
      IMAGETYPE_WBMP => 'image/vnd.wap.wbmp',
      IMAGETYPE_XBM => 'image/xbm'
    );
    return array('Content-type: '. $types[$type]);
  }
}

Dries's avatar
   
Dries committed
379
function user_search($keys) {
Dries's avatar
   
Dries committed
380
  $find = array();
381
382
383
384

  // Replace wildcards with mysql wildcards
  $keys = str_replace("*", "%", $keys);

Dries's avatar
   
Dries committed
385
  $result = db_query_range("SELECT * FROM {users} WHERE name LIKE '%%%s%%'", $keys, 0, 20);
Dries's avatar
   
Dries committed
386
  while ($account = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
387
    $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
388
  }
Dries's avatar
   
Dries committed
389
  return array(t("Matching users"), $find);
Dries's avatar
   
Dries committed
390
391
}

Dries's avatar
Dries committed
392
function user_user($type, &$edit, &$user) {
Dries's avatar
Dries committed
393
  if ($type == 'view') {
Dries's avatar
Dries committed
394
    return array(t('History') => form_item(t('Member for'), format_interval(time() - $user->created)));
Dries's avatar
Dries committed
395
396
397
  }
}

Dries's avatar
   
Dries committed
398
function user_block($op = "list", $delta = 0) {
Dries's avatar
   
Dries committed
399
400
  global $user;

Dries's avatar
   
Dries committed
401
  if ($op == "list") {
Dries's avatar
   
Dries committed
402
403
404
405
     $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");
406

407
     return $blocks;
408
409
  }
  else {
Dries's avatar
   
Dries committed
410
411
    $block = array();

Dries's avatar
   
Dries committed
412
413
    switch ($delta) {
      case 0:
Dries's avatar
   
Dries committed
414

415
        if (!$user->uid) {
Dries's avatar
   
Dries committed
416
417
418
419
420
          /*
          ** For usability's sake, avoid showing two login forms on one
          ** page.
          */

Dries's avatar
   
Dries committed
421
          if (arg(0) == 'user' && arg(1) != "view") {
Dries's avatar
   
Dries committed
422
423
424
            return;
          }

Dries's avatar
   
Dries committed
425
426
          $edit = $_POST["edit"];

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

429
          /*
Dries's avatar
Dries committed
430
431
          ** Save the referer.  We record where the user came from such
          ** that we/ can redirect him after having completed the login
432
433
          ** form.
          */
Dries's avatar
Dries committed
434

435
          if (empty($edit)) {
Dries's avatar
Dries committed
436
            $edit["destination"] = $_GET["q"];
437
438
          }
          // 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
439

Dries's avatar
   
Dries committed
440
          $output .= form_hidden("destination", $edit["destination"]);
Dries's avatar
   
Dries committed
441
442
          $output .= form_textfield(t("Username"), 'name', $edit['name'], 15, 64);
          $output .= form_password(t("Password"), 'pass', $pass, 15, 64);
Dries's avatar
   
Dries committed
443
          $output .= form_submit(t("Log in"));
Dries's avatar
   
Dries committed
444
          $output .= "</div>\n";
Dries's avatar
   
Dries committed
445

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

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

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

Dries's avatar
   
Dries committed
455
          $block["subject"] = t("User login");
Dries's avatar
   
Dries committed
456
          $block["content"] = $output;
Dries's avatar
   
Dries committed
457
        }
Dries's avatar
Dries committed
458
        return $block;
459
      case 1:
Dries's avatar
   
Dries committed
460
461
        if ($menu = menu_tree()) {
           $block["subject"] = $user->uid ? $user->name : t("Navigation");
Dries's avatar
   
Dries committed
462
           $block["content"] = "<div class=\"menu\">". $menu ."</div>";
Dries's avatar
   
Dries committed
463
        }
464
        return $block;
Dries's avatar
   
Dries committed
465
      case 2:
466
467
468
        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)) {
469
            $items[] = format_name($account);
470
          }
Dries's avatar
   
Dries committed
471

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

474
475
476
477
          $block["subject"] = t("Who's new");
          $block["content"] = $output;
          return $block;
        }
Dries's avatar
   
Dries committed
478
479
      case 3:
        if (user_access("access content")) {
Dries's avatar
   
Dries committed
480
481
          /* count users with activity in the past defined period */
          $time_period = variable_get("user_block_seconds_online", 2700);
Dries's avatar
   
Dries committed
482

Dries's avatar
   
Dries committed
483
484
485
          /* 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
486
          $total_users = db_num_rows($users);
Dries's avatar
   
Dries committed
487
488
489
490

          /* 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
491
492
          }
          else {
Dries's avatar
   
Dries committed
493
494
495
496
            $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
497

Dries's avatar
   
Dries committed
498
            // Display a list of currently online users
Dries's avatar
   
Dries committed
499
            $max_users = variable_get("user_block_max_list_count", 10);
Dries's avatar
   
Dries committed
500
501
            if ($max_users) {
              $items = array();
Dries's avatar
   
Dries committed
502

Dries's avatar
   
Dries committed
503
              while ($max_users-- && $uid = db_fetch_object($users)) {
Dries's avatar
   
Dries committed
504
                $items[] = format_name(user_load(array('uid' => $uid->uid)));
Dries's avatar
   
Dries committed
505
506
507
              }

              if ($items) {
Dries's avatar
   
Dries committed
508
509
510
                if (db_fetch_object($users)) {
                  $items[] = "...";
                }
Dries's avatar
   
Dries committed
511
512
                $output .= theme("item_list", $items, t("Online users:"));
              }
Dries's avatar
   
Dries committed
513
            }
Dries's avatar
   
Dries committed
514
          }
Dries's avatar
   
Dries committed
515
516
          $block["subject"] = t("Who's online");
          $block["content"] = $output;
Dries's avatar
   
Dries committed
517
        }
Dries's avatar
   
Dries committed
518
        return $block;
Dries's avatar
   
Dries committed
519
520
    }
  }
521
522
}

Dries's avatar
   
Dries committed
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
function theme_user_picture($account) {
  if (variable_get('user_pictures', 0)) {
    if ($account->picture && file_exists($account->picture)) {
      $picture = file_create_url($account->picture);
    }
    else if (variable_get('user_picture_default', '')) {
      $picture = variable_get('user_picture_default', '');
    }

    if ($picture) {
      $picture = "<img src=\"$picture\" alt=\"" . t("%user's picture", array("%user" => $account->name ? $account->name : t(variable_get("anonymous", "Anonymous")))) . "\" />";
      if ($account->uid) {
        $picture = l($picture, "user/view/$account->uid", array("title" => t("View user profile.")));
      }

      return "<div class=\"picture\">$picture</div>";
    }
  }
}

Dries's avatar
Dries committed
543
function theme_user_profile($account, $fields) {
Dries's avatar
   
Dries committed
544
545
  $output = "<div class=\"profile\">\n";
  $output .= theme('user_picture', $account);
Dries's avatar
Dries committed
546
547
548
  foreach ($fields as $category => $value) {
    $output .= "<h2>$category</h2>$value";
  }
Dries's avatar
   
Dries committed
549
550
551
552
553
554
555
556
557
558

  if (user_access("administer users")) {
    $output .= form_item(t("Administration"), l(t("edit account"), "admin/user/edit/$account->uid"));
  }

  $output .= "</div>\n";

  return $output;
}

Dries's avatar
   
Dries committed
559
function theme_user_list($items, $title = NULL) {
Dries's avatar
   
Dries committed
560
  return theme("item_list", $items, $title);
Dries's avatar
   
Dries committed
561
562
}

Dries's avatar
   
Dries committed
563
564
565
/**
 * Implementation of hook_link().
 */
Dries's avatar
   
Dries committed
566
function user_link($type) {
Dries's avatar
   
Dries committed
567
  global $user;
Dries's avatar
   
Dries committed
568

Dries's avatar
   
Dries committed
569
  if ($type == 'system') {
570
571
572
573
574
575
576
577
578
    if ($user->uid) {
      menu('user', t('my account'), 'user_page', 0);
      menu('user/edit', t('edit account'), 'user_page', 0);
      menu('logout', t('log out'), 'user_logout', 10);
    }
    else {
      menu('user', t('user'), 'user_page', 0, MENU_HIDE);
      menu('user/edit', t('edit account'), MENU_DENIED);
      menu('logout', t('log out'), MENU_DENIED);
Dries's avatar
   
Dries committed
579
    }
Dries's avatar
   
Dries committed
580
581
582
583
584
585
586
587
588
589
590
591
592

    $access = user_access('administer users');
    menu('admin/user', t('accounts'), $access ? 'user_admin' : MENU_DENIED, 2);
    menu('admin/user/create', t('new user'), $access ? 'user_admin' : MENU_DENIED, 1);
    menu('admin/user/access', t('access rules'), $access ? 'user_admin' : MENU_DENIED, 3);
    menu('admin/user/access/mail', t('e-mail rules'), $access ? 'user_admin' : MENU_DENIED);
    menu('admin/user/access/user', t('name rules'), $access ? 'user_admin' : MENU_DENIED);
    menu('admin/user/role', t('roles'), $access ? 'user_admin' : MENU_DENIED, 4);
    menu('admin/user/permission', t('permissions'), $access ? 'user_admin' : MENU_DENIED, 5);
    menu('admin/user/help', t('help'), $access ? 'user_help_page' : MENU_DENIED, 9);
    menu('admin/user/edit', t('edit user account'), $access ? 'user_admin' : MENU_DENIED, 0, MENU_HIDE, MENU_LOCKED);
    if (module_exist('search')) {
      menu('admin/user/search', t('search'), $access ? 'user_admin' : MENU_DENIED, 8);
Dries's avatar
   
Dries committed
593
    }
Dries's avatar
   
Dries committed
594
595
596
597
598
  }
}

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

599
function user_get_authname($account, $module) {
Dries's avatar
   
Dries committed
600
601

  /*
602
  **  Called by authentication modules in order to edit/view their authmap information.
Dries's avatar
   
Dries committed
603
604
  */

Dries's avatar
   
Dries committed
605
  $result = db_query("SELECT authname FROM {authmap} WHERE uid = %d AND module = '%s'", $account->uid, $module);
606
607
608
  return db_result($result);
}

Dries's avatar
   
Dries committed
609

610
611
612
613
614
615
616
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
617
  $result = db_query("SELECT authname, module FROM {authmap} WHERE authname = '%s'", $authname);
Dries's avatar
   
Dries committed
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
  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
633
634
635
      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
636
637
638
      }
    }
    else {
Dries's avatar
   
Dries committed
639
      db_query("DELETE FROM {authmap} WHERE uid = %d AND module = '%s'", $account->uid, $module["1"]);
Dries's avatar
   
Dries committed
640
641
642
643
644
    }
  }
}

function user_auth_help_links() {
645
  $links = array();
Dries's avatar
   
Dries committed
646
  foreach (module_list() as $module) {
Dries's avatar
   
Dries committed
647
    if (module_hook($module, "auth")) {
Dries's avatar
   
Dries committed
648
      $links[] = l(module_invoke($module, 'info', 'name'), "user/help#$module");
Dries's avatar
   
Dries committed
649
650
651
652
653
654
655
    }
  }
  return $links;
}

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

Dries's avatar
   
Dries committed
656
function user_login($edit = array(), $msg = "") {
Dries's avatar
   
Dries committed
657
  global $user, $base_url;
Dries's avatar
   
Dries committed
658
659
660
661
662
663

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

  if ($user->uid) {
Dries's avatar
Dries committed
664
    drupal_goto('user');
Dries's avatar
   
Dries committed
665
666
  }

Dries's avatar
   
Dries committed
667
668
  if (user_deny('user', $edit['name'])) {
    $error = t("The name '%s' has been denied access.", array("%s" => $edit['name']));
Dries's avatar
   
Dries committed
669
  }
Dries's avatar
   
Dries committed
670
  else if ($edit['name'] && $edit['pass']) {
Dries's avatar
   
Dries committed
671
672

    /*
Dries's avatar
   
Dries committed
673
    ** Try to log in the user locally:
Dries's avatar
   
Dries committed
674
675
    */

Dries's avatar
   
Dries committed
676
    if (!$user->uid) {
Dries's avatar
   
Dries committed
677
678
679
      $name = $edit['name'];
      $pass = $edit['pass'];
      $user = user_load(array('name' => $name, 'pass' => $pass, "status" => 1));
Dries's avatar
   
Dries committed
680
681
682
683
684
685
    }

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

Dries's avatar
   
Dries committed
686
687
    if ($server = strrchr($edit['name'], "@")) {
      $name = substr($edit['name'], 0, strlen($edit['name']) - strlen($server));
688
      $server = substr($server, 1);
Dries's avatar
   
Dries committed
689
      $pass = $edit['pass'];
Dries's avatar
   
Dries committed
690
    }
Dries's avatar
   
Dries committed
691

Dries's avatar
   
Dries committed
692
    /*
Dries's avatar
   
Dries committed
693
    ** When possible, determine corresponding external auth source. Invoke
Dries's avatar
   
Dries committed
694
    ** source, and login user if successful:
Dries's avatar
   
Dries committed
695
696
    */

Dries's avatar
   
Dries committed
697
    if (!$user->uid && $server && $result = user_get_authmaps("$name@$server")) {
Dries's avatar
   
Dries committed
698
699
      if (module_invoke(key($result), "auth", $name, $pass, $server)) {
        $user = user_external_load("$name@$server");
Dries's avatar
   
Dries committed
700
        watchdog('user', "external load: $name@$server, module: ". key($result));
Dries's avatar
   
Dries committed
701
702
      }
      else {
Dries's avatar
   
Dries committed
703
        $error = t("Invalid password for %s.", array("%s" => "<i>$name@$server</i>"));
Dries's avatar
   
Dries committed
704
705
706
      }
    }

Dries's avatar
   
Dries committed
707
    /*
Dries's avatar
   
Dries committed
708
    ** Try each external authentication source in series. Register user if
Dries's avatar
   
Dries committed
709
    ** successful.
Dries's avatar
   
Dries committed
710
711
    */

Dries's avatar
   
Dries committed
712
    else if (!$user->uid && $server) {
Dries's avatar
   
Dries committed
713
714
715
      foreach (module_list() as $module) {
        if (module_hook($module, "auth")) {
          if (module_invoke($module, "auth", $name, $pass, $server)) {
Dries's avatar
   
Dries committed
716
            if (variable_get("user_register", 1) == 1 && !user_load(array('name' => "$name@$server"))) { //register this new user
Dries's avatar
   
Dries committed
717
              $user = user_save('', array('name' => "$name@$server", 'pass' => user_password(), 'init' => "$name@$server", 'status' => 1, "authname_$module" => "$name@$server", 'rid' => array(_user_authenticated_id())));
Dries's avatar
   
Dries committed
718
              watchdog('user', "new user: $name@$server ($module ID)", l(t("edit user"), "admin/user/edit/$user->uid"));
Dries's avatar
   
Dries committed
719
720
721
722
723
724
725
726
              break;
            }
          }
        }
      }
    }

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

Dries's avatar
   
Dries committed
729
      // update the user table timestamp noting user has logged in
Dries's avatar
   
Dries committed
730
      db_query("UPDATE {users} SET changed = '%d' WHERE uid = '%s'", time(), $user->uid);
Dries's avatar
   
Dries committed
731

Dries's avatar
   
Dries committed
732
733
      user_module_invoke("login", $edit, $user);

Dries's avatar
   
Dries committed
734
735
736
737
738
      /*
      ** If the user wants to be remembered, set the proper cookie such
      ** that the session won't expire.
      */

Dries's avatar
   
Dries committed
739
      $path = preg_replace("/.+\/\/[^\/]+(.*)/", "\$1/", $base_url);
Dries's avatar
   
Dries committed
740
      setcookie(session_name(), session_id(), FALSE, $path);
Dries's avatar
   
Dries committed
741
742

      /*
Dries's avatar
   
Dries committed
743
      ** Redirect the user to the page he logged on from.
Dries's avatar
   
Dries committed
744
745
      */

Dries's avatar
   
Dries committed
746
      drupal_goto($edit["destination"]);
Dries's avatar
   
Dries committed
747
748
749
    }
    else {
      if (!$error) {
Dries's avatar
   
Dries committed
750
        $error = t("Sorry.  Unrecognized username or password.") ." ". l(t("Have you forgotten your password?"), "user/password");
Dries's avatar
   
Dries committed
751
752
      }
      if ($server) {
Dries's avatar
   
Dries committed
753
        watchdog('user', "failed login for '$name@$server': $error");
Dries's avatar
   
Dries committed
754
755
      }
      else {
Dries's avatar
   
Dries committed
756
        watchdog('user', "failed login for '$name': $error");
Dries's avatar
   
Dries committed
757
758
759
760
761
762
763
764
765
      }
    }
  }

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

  if ($error) {
Dries's avatar
   
Dries committed
766
    drupal_set_message($error, 'error');
Dries's avatar
   
Dries committed
767
768
  }

Dries's avatar
   
Dries committed
769
  /*
Dries's avatar
   
Dries committed
770
  ** Save the referrer.  We record where the user came from such that we
Dries's avatar
   
Dries committed
771
772
773
  ** can redirect him after having completed the login form.
  */

774
  if (empty($edit)) {
Dries's avatar
Dries committed
775
    $edit["destination"] = $_GET["q"];
Dries's avatar
   
Dries committed
776
777
778
  }
  $output .= form_hidden("destination", $edit["destination"]);

Dries's avatar
   
Dries committed
779
780
781
782
  /*
  ** Display login form:
  */

Dries's avatar
   
Dries committed
783
784
785
  if ($msg) {
    $output .= "<p>$msg</p>";
  }
Dries's avatar
   
Dries committed
786
  if (count(user_auth_help_links()) > 0) {
Dries's avatar
   
Dries committed
787
    $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
788
789
  }
  else {
Dries's avatar
   
Dries committed
790
    $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
791
  }
Dries's avatar
   
Dries committed
792
  $output .= form_password(t("Password"), 'pass', $pass, 30, 64, t("Enter the password that accompanies your username."));
Dries's avatar
   
Dries committed
793
  $output .= form_submit(t("Log in"));
Dries's avatar
   
Dries committed
794
  $items[] = l(t("Request new password"), "user/password");
795
  if (variable_get("user_register", 1)) {
Dries's avatar
   
Dries committed
796
    $items[] = l(t("Create new account"), "user/register");
797
  }
Dries's avatar
   
Dries committed
798
  $output .= theme("item_list", $items);
Dries's avatar
   
Dries committed
799

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

802
  return form($output, "post", url('user/login'));
Dries's avatar
   
Dries committed
803
804
}

805
function _user_authenticated_id() {
Dries's avatar
   
Dries committed
806
  return db_result(db_query("SELECT rid FROM {role} WHERE name = 'authenticated user'"));
807
808
}

Dries's avatar
   
Dries committed
809
810
811
812
function user_logout() {
  global $user;

  if ($user->uid) {
Dries's avatar
   
Dries committed
813
    watchdog('user', "session closed for '$user->name'");
Dries's avatar
   
Dries committed
814
815
816
817
818
819

    /*
    ** Destroy the current session:
    */

    session_destroy();
Dries's avatar
   
Dries committed
820
    module_invoke_all('user', 'logout', NULL, $user);
Dries's avatar
   
Dries committed
821
822
823
    unset($user);
  }

Dries's avatar
Dries committed
824
  drupal_goto();
Dries's avatar
   
Dries committed
825
826
827
}

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

Dries's avatar
   
Dries committed
830
831
832
  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']));
833
  }
Dries's avatar
   
Dries committed
834
835
836
  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
837
838
  }
  if ($account) {
Dries's avatar
   
Dries committed
839

840
      $from = variable_get("site_mail", ini_get("sendmail_from"));
Dries's avatar
   
Dries committed
841
842
843
844
845
846
      $pass = user_password();

      /*
      ** Save new password:
      */

Dries's avatar
   
Dries committed
847
      user_save($account, array('pass' => $pass));
Dries's avatar
   
Dries committed
848
849
850
851
852

      /*
      ** Mail new password:
      */

Dries's avatar
Dries committed
853
      $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
854
855
      $subject = _user_mail_text("pass_subject", $variables);
      $body = _user_mail_text("pass_body", $variables);
856
      $headers = "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from";
Dries's avatar
   
Dries committed
857
      $mail_success = user_mail($account->mail, $subject, $body, $headers);
Dries's avatar
   
Dries committed
858

Dries's avatar
   
Dries committed
859
      if ($mail_success) {
Dries's avatar
   
Dries committed
860
        watchdog('user', "mail password: '". $account->name ."' &lt;". $account->mail ."&gt;");
Dries's avatar
   
Dries committed
861
862
863
        return t("Your password and further instructions have been sent to your e-mail address.");
      }
      else {
Dries's avatar
   
Dries committed
864
        watchdog('error', "error mailing new password: '". $account->name ."' &lt;". $account->mail ."&gt;");
Dries's avatar
   
Dries committed
865
866
        return t("Unable to send mail. Please contact the site admin.");
      }
Dries's avatar
   
Dries committed
867
868
    }
    else {
869

Kjartan's avatar
Kjartan committed
870
871
    // Display error message if necessary.
    if ($error) {
Dries's avatar
   
Dries committed
872
      drupal_set_message($error, 'error');
Dries's avatar
   
Dries committed
873
874
875
876
877
878
    }

    /*
    ** Display form:
    */

Dries's avatar
   
Dries committed
879
    $output .= "<p>". t("Enter your username <strong><em>or</em></strong> your e-mail address.") ."</p>";
Dries's avatar
   
Dries committed
880
881
    $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
882
    $output .= form_submit(t("E-mail new password"));
Dries's avatar
   
Dries committed
883
    $items[] = l(t("Log in"), "user/login");
884
    if (variable_get("user_register", 1)) {
Dries's avatar
   
Dries committed
885
      $items[] = l(t("Create new account"), "user/register");
886
    }
Dries's avatar
   
Dries committed
887
    $output .= theme("item_list", $items);
Dries's avatar
   
Dries committed
888
    $output  = form_group(t('Request new password'), $output);
889
    return form($output, "post", url('user/password'));
Dries's avatar
   
Dries committed
890
891
892
893
  }
}

function user_register($edit = array()) {
Dries's avatar
   
Dries committed
894
  global $user, $base_url;
895
896
897
898
899
900

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

  if ($user->uid) {
Dries's avatar
Dries committed
901
    drupal_goto("user/edit");
902
  }
Dries's avatar
   
Dries committed
903

Dries's avatar
   
Dries committed
904
905
  if (!(is_null($edit['name']) && is_null($edit['mail']))) {
    if ($error = user_validate_name($edit['name'])) {
Dries's avatar
   
Dries committed
906
907
      // do nothing
    }
Dries's avatar
   
Dries committed
908
    else if ($error = user_validate_mail($edit['mail'])) {
Dries's avatar
   
Dries committed
909
910
      // do nothing
    }
Dries's avatar
   
Dries committed
911
912
    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
913
    }
Dries's avatar
   
Dries committed
914
915
    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
916
    }
Dries's avatar
   
Dries committed
917
918
    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
919
    }
Dries's avatar
   
Dries committed
920
921
    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
922
    }
Dries's avatar
   
Dries committed
923
    else if (variable_get("user_register", 1) == 0) {
Dries's avatar
   
Dries committed
924
925
      $error = t("Public registrations have been disabled by the site administrator.");
    }
926
    else {
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
      foreach (module_list() as $module) {
        if (module_hook($module, 'user')) {
          $result = module_invoke($module, 'user', 'validate', $edit, $user);
          if (is_array($result)) {
            $data = array_merge($data, $result);
          }
          elseif (is_string($result)) {
            $error = $result;
            break;
          }
        }
      }
      if (!$error) {
        $success = true;
      }
942
    }
Dries's avatar
   
Dries committed
943
944
945
946
  }

  if ($success) {

947
    $from = variable_get("site_mail", ini_get("sendmail_from"));
Dries's avatar
   
Dries committed
948
949
    $pass = user_password();

950
951
    // TODO: is this necessary? Won't session_write replicate this?
    unset($edit["session"]);
Dries's avatar
   
Dries committed
952
    $account = user_save('', array_merge(array('name' => $edit['name'], 'pass' => $pass, 'init' => $edit['mail'], 'mail' => $edit['mail'], 'rid' => array(_user_authenticated_id()), 'status' => (variable_get('user_register', 1) == 1 ? 1 : 0)), $data));
Dries's avatar
   
Dries committed
953
    watchdog('user', "new user: '". $edit['name'] ."' &lt;". $edit['mail'] ."&gt;", l(t("edit user"), "admin/user/edit/$account->uid"));
Dries's avatar
   
Dries committed
954

Dries's avatar
Dries committed
955
    $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));
956

Dries's avatar
   
Dries committed
957
    //the first user may login immediately, and receives a customized welcome e-mail.
958
    if ($account->uid == 1) {
Dries's avatar
   
Dries committed
959
      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");
960
      // 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
961
      $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
962
      $output .= form_hidden("destination", "user/edit");
Dries's avatar
   
Dries committed
963
964
      $output .= form_hidden('name', $account->name);
      $output .= form_hidden('pass', $pass);
965
966
967
968
      $output .= form_submit(t("Log in"));
      return form($output);
    }
    else {
969
970
971
972
973
      if ($account->status) {
        /*
        ** Create new user account, no administrator approval required:
        */

Dries's avatar
   
Dries committed
974
975
        $subject = _user_mail_text("welcome_subject", $variables);
        $body = _user_mail_text("welcome_body", $variables);
Dries's avatar
   
Dries committed
976
        user_mail($edit['mail'], $subject, $body, "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from");
977
978
979
980
981
982
        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
983
984
985
        $subject = _user_mail_text("approval_subject", $variables);
        $body = _user_mail_text("approval_body", $variables);

Dries's avatar
   
Dries committed
986
        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
987
        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
988
        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.");
989
      }
990
    }
Dries's avatar
   
Dries committed
991
992
993
  }
  else {
    if ($error) {
Dries's avatar
   
Dries committed
994
      drupal_set_message($error, 'error');
Dries's avatar
   
Dries committed
995
    }
996
  }
Dries's avatar
   
Dries committed
997

998
  // display the registration form
999
  $output .= variable_get("user_registration_help", "");
1000
  $affiliates = user_auth_help_links();
Dries's avatar
   
Dries committed
1001
  if (count($affiliates) > 0) {
1002