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

4
5
6
7
8
9
/**
 * Invokes hook_user() in every module.
 *
 * We cannot use module_invoke() for this, becuse the arguments need to
 * be passed by reference.
 */
10
function user_module_invoke($type, &$array, &$user, $category = NULL) {
Dries Buytaert's avatar
   
Dries Buytaert committed
11
12
  foreach (module_list() as $module) {
    $function = $module .'_user';
13
    if (function_exists($function)) $function($type, $array, $user, $category);
Dries Buytaert's avatar
   
Dries Buytaert committed
14
15
16
  }
}

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

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

28
29
30
31
32
33
34
35
36
37
/**
 * Fetch a user object.
 *
 * @param $array
 *   An associative array of attributes to search for in selecting the
 *   user, such as user name or email address.
 *
 * @return
 *   A fully-loaded $user object.
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
38
function user_load($array = array()) {
39
40
  // Dynamically compose a SQL query:
  $query = '';
Dries Buytaert's avatar
   
Dries Buytaert committed
41

Dries Buytaert's avatar
   
Dries Buytaert committed
42
  foreach ($array as $key => $value) {
Dries Buytaert's avatar
   
Dries Buytaert committed
43
    if ($key == 'pass') {
Kjartan Mannes's avatar
Kjartan Mannes committed
44
      $query .= "u.$key = '". md5($value) ."' AND ";
45
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
46
    else {
47
      $query .= "LOWER(u.$key) = '". strtolower(check_query($value)) ."' AND ";
Dries Buytaert's avatar
   
Dries Buytaert committed
48
49
    }
  }
50
  $result = db_query_range("SELECT u.* FROM {users} u WHERE $query u.status < 3", 0, 1);
Dries Buytaert's avatar
   
Dries Buytaert committed
51
52

  $user = db_fetch_object($result);
Dries Buytaert's avatar
   
Dries Buytaert committed
53
  $user = drupal_unpack($user);
54
  user_module_invoke('load', $array, $user);
Dries Buytaert's avatar
   
Dries Buytaert committed
55

Dries Buytaert's avatar
   
Dries Buytaert committed
56
  $user->roles = array();
57
  $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);
Dries Buytaert's avatar
   
Dries Buytaert committed
58
59
60
  while ($role = db_fetch_object($result)) {
    $user->roles[$role->rid] = $role->name;
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
61
62
63
64

  return $user;
}

65
function user_save($account, $array = array(), $category = 'account') {
66
  // Dynamically compose a SQL query:
67
  $user_fields = user_fields();
Dries Buytaert's avatar
   
Dries Buytaert committed
68
  if ($account->uid) {
69
    user_module_invoke('update', $array, $account, $category);
Dries Buytaert's avatar
   
Dries Buytaert committed
70

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

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

94
    // reload user roles if provided
95
    if (is_array($array['roles'])) {
96
      db_query('DELETE FROM {users_roles} WHERE uid = %d', $account->uid);
Dries Buytaert's avatar
   
Dries Buytaert committed
97

98
      foreach ($array['roles'] as $rid) {
99
        db_query('INSERT INTO {users_roles} (uid, rid) VALUES (%d, %d)', $account->uid, $rid);
100
      }
Dries Buytaert's avatar
   
Dries Buytaert committed
101
102
    }

Dries Buytaert's avatar
   
Dries Buytaert committed
103
    $user = user_load(array('uid' => $account->uid));
Dries Buytaert's avatar
   
Dries Buytaert committed
104
105
  }
  else {
Dries Buytaert's avatar
   
Dries Buytaert committed
106
107
    $array['created'] = time();
    $array['changed'] = time();
108
    $array['uid'] = db_next_id('{users}_uid');
Dries Buytaert's avatar
   
Dries Buytaert committed
109
110

    foreach ($array as $key => $value) {
Dries Buytaert's avatar
   
Dries Buytaert committed
111
      if ($key == 'pass') {
Dries Buytaert's avatar
   
Dries Buytaert committed
112
        $fields[] = check_query($key);
Dries Buytaert's avatar
   
Dries Buytaert committed
113
114
        $values[] = md5($value);
        $s[] = "'%s'";
Dries Buytaert's avatar
   
Dries Buytaert committed
115
      }
116
      else if (substr($key, 0, 4) !== 'auth') {
117
        if (in_array($key, $user_fields)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
118
          $fields[] = check_query($key);
Dries Buytaert's avatar
   
Dries Buytaert committed
119
120
          $values[] = $value;
          $s[] = "'%s'";
Dries Buytaert's avatar
   
Dries Buytaert committed
121
122
123
124
        }
        else {
          $data[$key] = $value;
        }
Dries Buytaert's avatar
   
Dries Buytaert committed
125
126
127
      }
    }

128
    $fields[] = 'data';
Dries Buytaert's avatar
   
Dries Buytaert committed
129
130
    $values[] = serialize($data);
    $s[] = "'%s'";
Dries Buytaert's avatar
   
Dries Buytaert committed
131

132
    db_query('INSERT INTO {users} ('. implode(', ', $fields) .') VALUES ('. implode(', ', $s) .')', $values);
Dries Buytaert's avatar
   
Dries Buytaert committed
133

134
135
    // Reload user roles (delete just to be safe).
    db_query('DELETE FROM {users_roles} WHERE uid = %d', $array['uid']);
Dries Buytaert's avatar
   
Dries Buytaert committed
136

137
    foreach ($array['roles'] as $rid) {
138
      db_query('INSERT INTO {users_roles} (uid, rid) VALUES (%d, %d)', $array['uid'], $rid);
Dries Buytaert's avatar
   
Dries Buytaert committed
139
140
    }

Dries Buytaert's avatar
   
Dries Buytaert committed
141
    $user = user_load(array('name' => $array['name']));
Dries Buytaert's avatar
   
Dries Buytaert committed
142

143
    module_invoke_all('user', 'insert', $array, $user, $category);
Dries Buytaert's avatar
   
Dries Buytaert committed
144
145
146
  }

  foreach ($array as $key => $value) {
Dries Buytaert's avatar
   
Dries Buytaert committed
147
    if (substr($key, 0, 4) == 'auth') {
Dries Buytaert's avatar
   
Dries Buytaert committed
148
149
150
151
152
      $authmaps[$key] = $value;
    }
  }

  if ($authmaps) {
Dries Buytaert's avatar
   
Dries Buytaert committed
153
    user_set_authmaps($user, $authmaps);
Dries Buytaert's avatar
   
Dries Buytaert committed
154
155
156
157
158
  }

  return $user;
}

159
160
161
/**
 * Verify the syntax of the given name.
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
162
function user_validate_name($name) {
163
164
165
166
167
168
169
  if (!$name) return t('You must enter a username.');
  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.');
  if (ereg('  ', $name)) return t('The username cannot contain multiple spaces in a row.');
  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.');
  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
170
171
172
}

function user_validate_mail($mail) {
173
  if (!$mail) return t('You must enter an e-mail address.');
Dries Buytaert's avatar
   
Dries Buytaert committed
174
  if ($mail && !valid_email_address($mail)) {
175
    return t('The e-mail address "%mail" is not valid.', array('%mail' => $mail));
Dries Buytaert's avatar
   
Dries Buytaert committed
176
177
178
  }
}

Dries Buytaert's avatar
   
Dries Buytaert committed
179
function user_validate_picture($file, &$edit, $user) {
180
  // Initialize the picture:
Dries Buytaert's avatar
   
Dries Buytaert committed
181
182
  $edit['picture'] = $user->picture;

183
184
185
  // Check that uploaded file is an image, with a maximum file size
  // and maximum height/width.
  $extension = strtolower(strrchr($file->name, '.'));
Dries Buytaert's avatar
   
Dries Buytaert committed
186
  $size = getimagesize($file->path);
187
  list($maxwidth, $maxheight) = explode('x', variable_get('user_picture_dimensions', '85x85'));
Dries Buytaert's avatar
   
Dries Buytaert committed
188

189
  if ((!in_array($size[2], array(1, 2, 3))) || (!in_array($extension, array('.gif', '.jpg', '.png', '.jpeg')))) {
Dries Buytaert's avatar
   
Dries Buytaert committed
190
    form_set_error('picture', t('The uploaded file was not an image.'));
Dries Buytaert's avatar
   
Dries Buytaert committed
191
  }
192
  else if ($file->size > (variable_get('user_picture_file_size', '30') * 1000)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
193
    form_set_error('picture', t('The uploaded image is too large; the maximum file size is %a kB.', array('%a' => variable_get('user_picture_file_size', '30'))));
Dries Buytaert's avatar
   
Dries Buytaert committed
194
195
  }
  else if ($size[0] > $maxwidth || $size[1] > $maxheight) {
Dries Buytaert's avatar
   
Dries Buytaert committed
196
    form_set_error('picture', t('The uploaded image is too large; the maximum dimensions are %a pixels.', array('%a' => variable_get('user_picture_dimensions', '85x85'))));
Dries Buytaert's avatar
   
Dries Buytaert committed
197
  }
198
  else if ($file = file_save_upload('picture', variable_get('user_picture_path', 'pictures') . FILE_SEPARATOR .'picture-'. $user->uid . $extension, 1)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
199
200
201
    $edit['picture'] = $file->path;
  }
  else {
Dries Buytaert's avatar
   
Dries Buytaert committed
202
    form_set_error('picture', t('Failed to upload the picture image; the "%directory" directory doesn\'t exist.', array('%directory' => variable_get('user_picture_path', 'pictures'))));
Dries Buytaert's avatar
   
Dries Buytaert committed
203
204
205
  }
}

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

214
215
216
/**
 * Generate a random alphanumeric password.
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
217
218
219
220
221
function user_password($length = 10) {
  // 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.
222
223
  $allowable_characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789';

Dries Buytaert's avatar
   
Dries Buytaert committed
224
225
226
  // We see how many characters are in the allowable list:
  $len = strlen($allowable_characters);

227
  // Seed the random number generator with the microtime stamp.
Dries Buytaert's avatar
   
Dries Buytaert committed
228
  mt_srand((double)microtime() * 1000000);
Dries Buytaert's avatar
   
Dries Buytaert committed
229

230
231
  // Declare the password as a blank string.
  $pass = '';
Dries Buytaert's avatar
   
Dries Buytaert committed
232

233
  // Loop the number of times specified by $length.
Dries Buytaert's avatar
   
Dries Buytaert committed
234
235
236
237
238
239
240
241
  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
242
243
}

244
245
246
247
248
249
250
251
252
253
254
255
256
/**
 * Determine whether the user has a given privilege.
 *
 * @param $string
 *   The permission, such as "administer nodes", being checked for.
 *
 * @return
 *   TRUE iff the current user has the requested permission.
 *
 * All permission checks in Drupal should go through this function. This
 * way, we guarantee consistent behavior, and ensure that the superuser
 * can perform all actions.
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
257
258
function user_access($string) {
  global $user;
Dries Buytaert's avatar
   
Dries Buytaert committed
259
  static $perm = 0;
Dries Buytaert's avatar
   
Dries Buytaert committed
260

Dries Buytaert's avatar
   
Dries Buytaert committed
261
  // User #1 has all priveleges:
Dries Buytaert's avatar
   
Dries Buytaert committed
262
263
264
265
  if ($user->uid == 1) {
    return 1;
  }

266
267
  // To reduce the number of SQL queries, we cache the user's permissions
  // in a static variable.
Dries Buytaert's avatar
   
Dries Buytaert committed
268
  if ($perm === 0) {
269
    $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);
Dries Buytaert's avatar
   
Dries Buytaert committed
270
271
272
273

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

Dries Buytaert's avatar
   
Dries Buytaert committed
276
  return strstr($perm, "$string, ");
Dries Buytaert's avatar
   
Dries Buytaert committed
277
278
}

279
280
281
/**
 * Send an e-mail message.
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
282
function user_mail($mail, $subject, $message, $header) {
283
284
  if (variable_get('smtp_library', '') && file_exists(variable_get('smtp_library', ''))) {
    include_once variable_get('smtp_library', '');
285
    return user_mail_wrapper($mail, $subject, $message, $header);
Dries Buytaert's avatar
   
Dries Buytaert committed
286
287
  }
  else {
288
289
290
291
292
293
294
    /*
    ** 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
295
296
297
298
299
300
301
302
303
304
305
306
    **
    ** 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
    **
307
    */
Dries Buytaert's avatar
   
Dries Buytaert committed
308
309
310
    return mail(
      $mail,
      user_mail_encode($subject),
311
      str_replace("\r", '', $message),
Dries Buytaert's avatar
   
Dries Buytaert committed
312
      "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
313
    );
Dries Buytaert's avatar
   
Dries Buytaert committed
314
315
316
  }
}

317
function user_mail_encode($string, $charset = 'UTF-8') {
318
319
320
321
  /*
  ** 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
322
323
  **
  ** Notes:
324
  **   - Only encode strings that contain non-ASCII characters.
Kjartan Mannes's avatar
Kjartan Mannes committed
325
326
327
328
329
330
  **   - 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.
331
  */
332
333
334
335
336
337
  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));
  }
338
  return $string;
Dries Buytaert's avatar
   
Dries Buytaert committed
339
340
}

Dries Buytaert's avatar
   
Dries Buytaert committed
341
function user_deny($type, $mask) {
342
343
  $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
344

Dries Buytaert's avatar
   
Dries Buytaert committed
345
  return $deny && !$allow;
Dries Buytaert's avatar
   
Dries Buytaert committed
346
347
}

Dries Buytaert's avatar
   
Dries Buytaert committed
348
349
function user_fields() {
  static $fields;
Dries Buytaert's avatar
   
Dries Buytaert committed
350

Dries Buytaert's avatar
   
Dries Buytaert committed
351
  if (!$fields) {
352
    $result = db_query('SELECT * FROM {users} WHERE uid = 1');
353
354
355
    if (db_num_rows($result)) {
      $fields = array_keys(db_fetch_array($result));
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
356
357
    else {
      // Make sure we return the default fields at least
Dries Buytaert's avatar
   
Dries Buytaert committed
358
      $fields = array('uid', 'name', 'pass', 'mail', 'picture', 'mode', 'sort', 'threshold', 'theme', 'signature', 'created', 'changed', 'status', 'timezone', 'language', 'init', 'data');
Dries Buytaert's avatar
   
Dries Buytaert committed
359
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
360
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
361

Dries Buytaert's avatar
   
Dries Buytaert committed
362
  return $fields;
Dries Buytaert's avatar
   
Dries Buytaert committed
363
364
}

365
366
367
/**
 * Implementation of hook_perm().
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
368
function user_perm() {
Dries Buytaert's avatar
   
Dries Buytaert committed
369
  return array('administer users', 'access users');
Dries Buytaert's avatar
   
Dries Buytaert committed
370
371
}

372
373
374
375
376
/**
 * Implementation of hook_file_download().
 *
 * Ensure that user pictures (avatars) are always downloadable.
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
377
function user_file_download($file) {
378
  if (strpos($file, variable_get('user_picture_path', 'pictures') . FILE_SEPARATOR . 'picture-') === 0) {
Dries Buytaert's avatar
   
Dries Buytaert committed
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
    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]);
  }
}

402
403
404
/**
 * Implementation of hook_search().
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
405
function user_search($keys) {
Dries Buytaert's avatar
   
Dries Buytaert committed
406
  $find = array();
407

408
409
  // Replace wildcards with MySQL/PostgreSQL wildcards.
  $keys = str_replace('*', '%', $keys);
410

411
  $result = db_query_range("SELECT * FROM {users} WHERE LOWER(name) LIKE '%%%s%%'", strtolower($keys), 0, 20);
Dries Buytaert's avatar
   
Dries Buytaert committed
412
  while ($account = db_fetch_object($result)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
413
    $find[] = array('title' => $account->name, 'link' => url("user/$account->uid/view"), 'user' => $account->name);
Dries Buytaert's avatar
   
Dries Buytaert committed
414
  }
415
  return array(t('Matching users'), $find);
Dries Buytaert's avatar
   
Dries Buytaert committed
416
417
}

418
419
420
/**
 * Implementation of hook_user().
 */
421
function user_user($type, &$edit, &$user, $category = NULL) {
422
  if ($type == 'view') {
Dries Buytaert's avatar
Dries Buytaert committed
423
    return array(t('History') => form_item(t('Member for'), format_interval(time() - $user->created)));
424
  }
425
426
427
428
429
430
431
432
433
434
435
436

  if ($type == 'form' && $category == 'account') {
    return user_edit_form(arg(1), $edit);
  }

  if ($type == 'validate' && $category == 'account') {
    return user_edit_validate(arg(1), $edit);
  }

  if ($type == 'categories') {
    return array(array('name' => 'account', 'title' => t('account settings'), 'weight' => 1));
  }
437
438
}

439
440
441
442
/**
 * Implementation of hook_block().
 */
function user_block($op = 'list', $delta = 0) {
Dries Buytaert's avatar
   
Dries Buytaert committed
443
444
  global $user;

445
446
447
448
449
  if ($op == 'list') {
     $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');
450

451
     return $blocks;
452
453
  }
  else {
Dries Buytaert's avatar
   
Dries Buytaert committed
454
455
    $block = array();

Dries Buytaert's avatar
   
Dries Buytaert committed
456
457
    switch ($delta) {
      case 0:
Dries Buytaert's avatar
   
Dries Buytaert committed
458

459
        if (!$user->uid) {
460
461
          // For usability's sake, avoid showing two login forms on one page.
          if (arg(0) == 'user' && arg(1) != 'view') {
Dries Buytaert's avatar
   
Dries Buytaert committed
462
463
464
            return;
          }

465
          $edit = $_POST['edit'];
Dries Buytaert's avatar
   
Dries Buytaert committed
466

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

469
470
          // Save the referer.  We record where the user came from such
          // that we can redirect him after having completed the login form.
Dries Buytaert's avatar
Dries Buytaert committed
471

472
          if (empty($edit)) {
473
            $edit['destination'] = $_GET['q'];
474
          }
475
476
477
478
479
480
481
482
          // 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.

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

485
          $output  = form($output, 'post', url('user/login'));
Dries Buytaert's avatar
   
Dries Buytaert committed
486

487
488
          if (variable_get('user_register', 1)) {
            $items[] = l(t('Create new account'), 'user/register', array('title' => t('Create a new user account.')));
Dries Buytaert's avatar
   
Dries Buytaert committed
489
          }
490
          $items[] = l(t('Request new password'), 'user/password', array('title' => t('Request new password via e-mail.')));
Dries Buytaert's avatar
   
Dries Buytaert committed
491

492
          $output .= theme('item_list', $items);
493

494
495
          $block['subject'] = t('User login');
          $block['content'] = $output;
Dries Buytaert's avatar
   
Dries Buytaert committed
496
        }
Dries Buytaert's avatar
Dries Buytaert committed
497
        return $block;
498
      case 1:
Dries Buytaert's avatar
   
Dries Buytaert committed
499
        if ($menu = theme('menu_tree')) {
500
501
           $block['subject'] = $user->uid ? $user->name : t('Navigation');
           $block['content'] = '<div class="menu">'. $menu .'</div>';
Dries Buytaert's avatar
   
Dries Buytaert committed
502
        }
503
        return $block;
Dries Buytaert's avatar
   
Dries Buytaert committed
504
      case 2:
505
506
        if (user_access('access content')) {
          $result = db_query_range('SELECT uid, name FROM {users} WHERE status != 0 ORDER BY uid DESC', 0, 5);
507
          while ($account = db_fetch_object($result)) {
508
            $items[] = format_name($account);
509
          }
Dries Buytaert's avatar
   
Dries Buytaert committed
510

511
          $output = theme('user_list', $items);
Dries Buytaert's avatar
   
Dries Buytaert committed
512

513
514
          $block['subject'] = t('Who\'s new');
          $block['content'] = $output;
515
516
          return $block;
        }
Dries Buytaert's avatar
   
Dries Buytaert committed
517
      case 3:
518
519
520
        if (user_access('access content')) {
          // Count users with activity in the past defined period.
          $time_period = variable_get('user_block_seconds_online', 2700);
Dries Buytaert's avatar
   
Dries Buytaert committed
521

522
523
524
          // 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 Buytaert's avatar
   
Dries Buytaert committed
525
          $total_users = db_num_rows($users);
Dries Buytaert's avatar
   
Dries Buytaert committed
526

527
          // Format the output with proper grammar.
Dries Buytaert's avatar
   
Dries Buytaert committed
528
          if ($total_users == 1 && $guests->count == 1) {
529
            $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 Buytaert's avatar
   
Dries Buytaert committed
530
531
          }
          else {
532
            $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')));
Dries Buytaert's avatar
   
Dries Buytaert committed
533
534
          }

Dries Buytaert's avatar
   
Dries Buytaert committed
535
          if (user_access('access users') && $total_users) {
Dries Buytaert's avatar
   
Dries Buytaert committed
536

537
538
            // Display a list of currently online users.
            $max_users = variable_get('user_block_max_list_count', 10);
Dries Buytaert's avatar
   
Dries Buytaert committed
539
540
            if ($max_users) {
              $items = array();
Dries Buytaert's avatar
   
Dries Buytaert committed
541

Dries Buytaert's avatar
   
Dries Buytaert committed
542
              while ($max_users-- && $uid = db_fetch_object($users)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
543
                $items[] = format_name(user_load(array('uid' => $uid->uid)));
Dries Buytaert's avatar
   
Dries Buytaert committed
544
545
546
              }

              if ($items) {
Dries Buytaert's avatar
   
Dries Buytaert committed
547
                if (db_fetch_object($users)) {
548
                  $items[] = '...';
Dries Buytaert's avatar
   
Dries Buytaert committed
549
                }
550
                $output .= theme('item_list', $items, t('Online users:'));
Dries Buytaert's avatar
   
Dries Buytaert committed
551
              }
Dries Buytaert's avatar
   
Dries Buytaert committed
552
            }
Dries Buytaert's avatar
   
Dries Buytaert committed
553
          }
554
555
          $block['subject'] = t('Who\'s online');
          $block['content'] = $output;
Dries Buytaert's avatar
   
Dries Buytaert committed
556
        }
Dries Buytaert's avatar
   
Dries Buytaert committed
557
        return $block;
Dries Buytaert's avatar
   
Dries Buytaert committed
558
559
    }
  }
560
561
}

Dries Buytaert's avatar
   
Dries Buytaert committed
562
563
564
565
566
567
568
569
570
571
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) {
572
      $picture = "<img src=\"$picture\" alt=\"" . t('%user\'s picture', array('%user' => $account->name ? $account->name : t(variable_get('anonymous', 'Anonymous')))) . '" />';
Dries Buytaert's avatar
   
Dries Buytaert committed
573
      if ($account->uid) {
574
        $picture = l($picture, "user/$account->uid", array('title' => t('View user profile.')));
Dries Buytaert's avatar
   
Dries Buytaert committed
575
576
577
578
579
580
581
      }

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

582
function theme_user_profile($account, $fields) {
Dries Buytaert's avatar
   
Dries Buytaert committed
583
584
  $output = "<div class=\"profile\">\n";
  $output .= theme('user_picture', $account);
585
586
587
  foreach ($fields as $category => $value) {
    $output .= "<h2>$category</h2>$value";
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
588
589
590
591
592
  $output .= "</div>\n";

  return $output;
}

Dries Buytaert's avatar
   
Dries Buytaert committed
593
function theme_user_list($items, $title = NULL) {
594
  return theme('item_list', $items, $title);
Dries Buytaert's avatar
   
Dries Buytaert committed
595
596
}

Dries Buytaert's avatar
   
Dries Buytaert committed
597
/**
Dries Buytaert's avatar
   
Dries Buytaert committed
598
 * Implementation of hook_menu().
Dries Buytaert's avatar
   
Dries Buytaert committed
599
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
600
function user_menu() {
Dries Buytaert's avatar
   
Dries Buytaert committed
601
  global $user;
Dries Buytaert's avatar
   
Dries Buytaert committed
602

Dries Buytaert's avatar
   
Dries Buytaert committed
603
  $items = array();
Dries Buytaert's avatar
   
Dries Buytaert committed
604

Dries Buytaert's avatar
   
Dries Buytaert committed
605
606
607
608
609
610
  $access = user_access('administer users');

  if (arg(0) == 'user' && is_numeric(arg(1))) {
    $items[] = array('path' => 'user/'. arg(1), 'title' => t('user'),
      'callback' => 'user_page', 'access' => TRUE);
    $items[] = array('path' => 'user/'. arg(1) .'/edit', 'title' => t('edit'),
611
      'callback' => 'user_edit', 'access' => $access || $user->uid == arg(1),
Dries Buytaert's avatar
   
Dries Buytaert committed
612
      'type' => MENU_LOCAL_TASK);
613
614
615
616
617
618
619
620
621
622

    if (arg(2) == 'edit') {
      if (($categories = _user_categories()) && (count($categories) > 1)) {
        foreach ($categories as $key => $category) {
          $items[] = array('path' => 'user/'. arg(1) .'/edit/'. $category['name'], 'title' => $category['title'],
              'callback' => $function, 'access' => $access || $user->uid == arg(1),
              'type' => MENU_LOCAL_SUBTASK, 'weight' => $category['weight']);
        }
      }
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
623
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641

  if ($user->uid) {
    $items[] = array('path' => "user/$user->uid", 'title' => t('my account'),
      'callback' => 'user_page', 'access' => TRUE);
    $items[] = array('path' => 'logout', 'title' => t('log out'),
      'access' => TRUE,
      'callback' => 'user_logout',
      'weight' => 10);
  }
  else {
    $items[] = array('path' => 'logout', 'title' => t('log out'),
      'callback' => 'user_logout', 'access' => FALSE);
  }

  $items[] = array('path' => 'user', 'title' => t('user'),
    'callback' => 'user_page', 'access' => TRUE,
    'type' => MENU_CALLBACK);
  $items[] = array('path' => 'user/login', 'title' => t('log in'),
Dries Buytaert's avatar
   
Dries Buytaert committed
642
643
644
645
646
    'callback' => 'user_page', 'access' => TRUE, 'type' => MENU_CALLBACK);
  $items[] = array('path' => 'user/register', 'title' => t('register'),
    'callback' => 'user_page', 'access' => TRUE, 'type' => MENU_CALLBACK);
  $items[] = array('path' => 'user/password', 'title' => t('request new password'),
    'callback' => 'user_page', 'access' => TRUE, 'type' => MENU_CALLBACK);
Dries Buytaert's avatar
   
Dries Buytaert committed
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684

  $items[] = array('path' => 'admin/user', 'title' => t('users'),
    'callback' => 'user_admin', 'access' => $access);

  // Tabs:
  $items[] = array('path' => 'admin/user/create', 'title' => t('add user'),
    'callback' => 'user_admin', 'access' => $access,
    'type' => MENU_LOCAL_TASK);
  $items[] = array('path' => 'admin/user/configure', 'title' => t('configure'),
    'callback' => 'user_configure', 'access' => $access,
    'type' => MENU_LOCAL_TASK);
  if (module_exist('search')) {
    $items[] = array('path' => 'admin/user/search', 'title' => t('search'),
      'callback' => 'user_admin', 'access' => $access,
      'type' => MENU_LOCAL_TASK);
  }

  // Sub-tabs:
  $items[] = array('path' => 'admin/user/configure/settings', 'title' => t('settings'),
    'callback' => 'user_configure', 'access' => $access,
    'type' => MENU_LOCAL_SUBTASK);
  $items[] = array('path' => 'admin/user/configure/access', 'title' => t('access rules'),
    'callback' => 'user_configure', 'access' => $access,
    'type' => MENU_LOCAL_SUBTASK);
  $items[] = array('path' => 'admin/user/configure/access/mail', 'title' => t('e-mail rules'),
    'callback' => 'user_configure', 'access' => $access,
    'type' => MENU_LOCAL_SUBTASK);
  $items[] = array('path' => 'admin/user/configure/access/user', 'title' => t('name rules'),
    'callback' => 'user_configure', 'access' => $access,
    'type' => MENU_LOCAL_SUBTASK);
  $items[] = array('path' => 'admin/user/configure/role', 'title' => t('roles'),
    'callback' => 'user_configure', 'access' => $access,
    'type' => MENU_LOCAL_SUBTASK);
  $items[] = array('path' => 'admin/user/configure/permission', 'title' => t('permissions'),
    'callback' => 'user_configure', 'access' => $access,
    'type' => MENU_LOCAL_SUBTASK);

  return $items;
Dries Buytaert's avatar
   
Dries Buytaert committed
685
686
}

687
688
689
/**
 * Called by authentication modules in order to edit/view their authmap information.
 */
690
function user_get_authname($account, $module) {
Dries Buytaert's avatar
   
Dries Buytaert committed
691
  $result = db_query("SELECT authname FROM {authmap} WHERE uid = %d AND module = '%s'", $account->uid, $module);
692
693
694
  return db_result($result);
}

695
696
697
698
/**
 * Accepts an user object, $account, or a DA name and returns an associative
 * array of modules and DA names. Called at external login.
 */
699
function user_get_authmaps($authname = NULL) {
Dries Buytaert's avatar
   
Dries Buytaert committed
700
  $result = db_query("SELECT authname, module FROM {authmap} WHERE authname = '%s'", $authname);
Dries Buytaert's avatar
   
Dries Buytaert committed
701
702
703
704
705
706
707
708
709
710
711
712
713
  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) {
714
    $module = explode('_', $key, 2);
Dries Buytaert's avatar
   
Dries Buytaert committed
715
    if ($value) {
716
      db_query("UPDATE {authmap} SET authname = '%s' WHERE uid = %d AND module = '%s'", $value, $account->uid, $module['1']);
Dries Buytaert's avatar
   
Dries Buytaert committed
717
718
      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
719
720
721
      }
    }
    else {
722
      db_query("DELETE FROM {authmap} WHERE uid = %d AND module = '%s'", $account->uid, $module['1']);
Dries Buytaert's avatar
   
Dries Buytaert committed
723
724
725
726
727
    }
  }
}

function user_auth_help_links() {
728
  $links = array();
Dries Buytaert's avatar
   
Dries Buytaert committed
729
  foreach (module_list() as $module) {
730
    if (module_hook($module, 'auth')) {
Dries Buytaert's avatar
   
Dries Buytaert committed
731
      $links[] = l(module_invoke($module, 'info', 'name'), "user/help#$module");
Dries Buytaert's avatar
   
Dries Buytaert committed
732
733
734
735
736
737
738
    }
  }
  return $links;
}

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

739
function user_login($edit = array(), $msg = '') {
Dries Buytaert's avatar
   
Dries Buytaert committed
740
  global $user, $base_url;
Dries Buytaert's avatar
   
Dries Buytaert committed
741

742
  // If we are already logged on, go to the user page instead.
Dries Buytaert's avatar
   
Dries Buytaert committed
743
  if ($user->uid) {
Dries Buytaert's avatar
Dries Buytaert committed
744
    drupal_goto('user');
Dries Buytaert's avatar
   
Dries Buytaert committed
745
746
  }

Dries Buytaert's avatar
   
Dries Buytaert committed
747
  if (user_deny('user', $edit['name'])) {
748
    $error = t('The name "%s" has been denied access.', array('%s' => $edit['name']));
Dries Buytaert's avatar
   
Dries Buytaert committed
749
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
750
  else if ($edit['name'] && $edit['pass']) {
Dries Buytaert's avatar
   
Dries Buytaert committed
751

752
    // Try to log in the user locally:
Dries Buytaert's avatar
   
Dries Buytaert committed
753
    if (!$user->uid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
754
755
      $name = $edit['name'];
      $pass = $edit['pass'];
756
      $user = user_load(array('name' => $name, 'pass' => $pass, 'status' => 1));
Dries Buytaert's avatar
   
Dries Buytaert committed
757
758
    }

759
760
    // Strip name and server from ID:
    if ($server = strrchr($edit['name'], '@')) {
Dries Buytaert's avatar
   
Dries Buytaert committed
761
      $name = substr($edit['name'], 0, strlen($edit['name']) - strlen($server));
762
      $server = substr($server, 1);
Dries Buytaert's avatar
   
Dries Buytaert committed
763
      $pass = $edit['pass'];
Dries Buytaert's avatar
   
Dries Buytaert committed
764
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
765

766
767
    // When possible, determine corresponding external auth source. Invoke
    // source, and log in user if successful:
Dries Buytaert's avatar
   
Dries Buytaert committed
768
    if (!$user->uid && $server && $result = user_get_authmaps("$name@$server")) {
769
      if (module_invoke(key($result), 'auth', $name, $pass, $server)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
770
        $user = user_external_load("$name@$server");
Dries Buytaert's avatar
   
Dries Buytaert committed
771
        watchdog('user', "external load: $name@$server, module: ". key($result));
Dries Buytaert's avatar
   
Dries Buytaert committed
772
773
      }
      else {
774
        $error = t('Invalid password for %s.', array('%s' => "<i>$name@$server</i>"));
Dries Buytaert's avatar
   
Dries Buytaert committed
775
776
777
      }
    }

778
779
    // Try each external authentication source in series. Register user if
    // successful.
Dries Buytaert's avatar
   
Dries Buytaert committed
780
    else if (!$user->uid && $server) {
Dries Buytaert's avatar
   
Dries Buytaert committed
781
      foreach (module_list() as $module) {
782
783
784
        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.
785
              $user = user_save('', array('name' => "$name@$server", 'pass' => user_password(), 'init' => "$name@$server", 'status' => 1, "authname_$module" => "$name@$server", 'roles' => array(_user_authenticated_id())));
Dries Buytaert's avatar
   
Dries Buytaert committed
786
              watchdog('user', "new user: $name@$server ($module ID)", l(t('edit user'), "user/$user->uid/edit"));
Dries Buytaert's avatar
   
Dries Buytaert committed
787
788
789
790
791
792
793
794
              break;
            }
          }
        }
      }
    }

    if ($user->uid) {
795
      watchdog('user', 'session opened for "'. $user->name .'"');
Dries Buytaert's avatar
   
Dries Buytaert committed
796

797
      // Update the user table timestamp noting user has logged in.
Dries Buytaert's avatar
   
Dries Buytaert committed
798
      db_query("UPDATE {users} SET changed = '%d' WHERE uid = '%s'", time(), $user->uid);
Dries Buytaert's avatar
   
Dries Buytaert committed
799

800
      user_module_invoke('login', $edit, $user);
Dries Buytaert's avatar
   
Dries Buytaert committed
801

802
803
      // 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
804
      $path = preg_replace("/.+\/\/[^\/]+(.*)/", "\$1/", $base_url);
Dries Buytaert's avatar
   
Dries Buytaert committed
805
      setcookie(session_name(), session_id(), FALSE, $path);
Dries Buytaert's avatar
   
Dries Buytaert committed
806

807
808
      // Redirect the user to the page he logged on from.
      drupal_goto($edit['destination']);
Dries Buytaert's avatar
   
Dries Buytaert committed
809
810
811
    }
    else {
      if (!$error) {
812
        $error = t('Sorry.  Unrecognized username or password.') .' '. l(t('Have you forgotten your password?'), 'user/password');
Dries Buytaert's avatar
   
Dries Buytaert committed
813
814
      }
      if ($server) {
Dries Buytaert's avatar
   
Dries Buytaert committed
815
        watchdog('user', "failed login for '$name@$server': $error");
Dries Buytaert's avatar
   
Dries Buytaert committed
816
817
      }
      else {
Dries Buytaert's avatar
   
Dries Buytaert committed
818
        watchdog('user', "failed login for '$name': $error");
Dries Buytaert's avatar
   
Dries Buytaert committed
819
820
821
822
      }
    }
  }

823
  // Display error message (if any):
Dries Buytaert's avatar
   
Dries Buytaert committed
824
  if ($error) {
Dries Buytaert's avatar
   
Dries Buytaert committed
825
    drupal_set_message($error, 'error');
Dries Buytaert's avatar
   
Dries Buytaert committed
826
827
  }

828
829
  // Save the referrer.  We record where the user came from such that we
  // can redirect him after having completed the login form.
830
  if (empty($edit)) {
831
    $edit['destination'] = $_GET['q'];
Dries Buytaert's avatar
   
Dries Buytaert committed
832
  }
833
  $output .= form_hidden('destination', $edit['destination']);
Dries Buytaert's avatar
   
Dries Buytaert committed
834

835
  // Display login form:
Dries Buytaert's avatar
   
Dries Buytaert committed
836
837
838
  if ($msg) {
    $output .= "<p>$msg</p>";
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
839
  if (count(user_auth_help_links()) > 0) {
840
    $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
841
842
  }
  else {
843
    $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
844
  }
845
846
847
848
849
  $output .= form_password(t('Password'), 'pass', $pass, 30, 64, t('Enter the password that accompanies your username.'));
  $output .= form_submit(t('Log in'));
  $items[] = l(t('Request new password'), 'user/password');
  if (variable_get('user_register', 1)) {
    $items[] = l(t('Create new account'), 'user/register');
850
  }
851
  $output .= theme('item_list', $items);
Dries Buytaert's avatar
   
Dries Buytaert committed
852

Dries Buytaert's avatar
   
Dries Buytaert committed
853
854
  $output  = form_group(t('User login'), $output);

855
  return form($output, 'post', url('user/login'));
Dries Buytaert's avatar
   
Dries Buytaert committed
856
857
}

858
function _user_authenticated_id() {
Dries Buytaert's avatar
   
Dries Buytaert committed
859
  return db_result(db_query("SELECT rid FROM {role} WHERE name = 'authenticated user'"));
860
861
}

862
863
864
/**
 * Menu callback; logs the current user out, and redirects to the home page.
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
865
866
867
868
function user_logout() {
  global $user;

  if ($user->uid) {
869
    watchdog('user', 'session closed for "'. $user->name .'"');
Dries Buytaert's avatar
   
Dries Buytaert committed
870

871
    // Destroy the current session:
Dries Buytaert's avatar
   
Dries Buytaert committed
872
    session_destroy();
Dries Buytaert's avatar
   
Dries Buytaert committed
873
    module_invoke_all('user', 'logout', NULL, $user);
Dries Buytaert's avatar
   
Dries Buytaert committed
874
875
876
    unset($user);
  }

Dries Buytaert's avatar
Dries Buytaert committed
877
  drupal_goto();
Dries Buytaert's avatar
   
Dries Buytaert committed
878
879
880
}

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

Dries Buytaert's avatar
   
Dries Buytaert committed
883
  if ($edit['name']) {
884
    $account = db_fetch_object(db_query("SELECT uid, name, mail FROM {users} WHERE status = 1 AND LOWER(name) = '%s'", strtolower($edit['name'])));
Dries Buytaert's avatar
   
Dries Buytaert committed
885
    if (!$account) form_set_error('name', t('Sorry. The username "<i>%s</i>" is not recognized.', array('%s' => $edit['name'])));
886
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
887
  else if ($edit['mail']) {
888
    $account = db_fetch_object(db_query("SELECT uid, name, mail FROM {users} WHERE status = 1 AND LOWER(mail) = '%s'", strtolower($edit['mail'])));
Dries Buytaert's avatar
   
Dries Buytaert committed
889
    if (!$account) form_set_error('name', t('Sorry. The e-mail address "<i>%s</i>" is not recognized.', array('%s' => $edit['mail'])));
Kjartan Mannes's avatar
Kjartan Mannes committed
890
891
  }
  if ($account) {
Dries Buytaert's avatar
   
Dries Buytaert committed
892

893
      $from = variable_get('site_mail', ini_get('sendmail_from'));
Dries Buytaert's avatar
   
Dries Buytaert committed
894
895
      $pass = user_password();

896
      // Save new password:
Dries Buytaert's avatar
   
Dries Buytaert committed
897
      user_save($account, array('pass' => $pass));
Dries Buytaert's avatar
   
Dries Buytaert committed
898

899
900
901
902
      // Mail new password:
      $variables = array('%username' => $account->name, '%site' => variab