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

Dries's avatar
Dries committed
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.
 */
Dries's avatar
   
Dries committed
10
11
12
function user_module_invoke($type, &$array, &$user) {
  foreach (module_list() as $module) {
    $function = $module .'_user';
Dries's avatar
   
Dries committed
13
    if (function_exists($function)) $function($type, $array, $user);
Dries's avatar
   
Dries committed
14
15
16
  }
}

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

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

Dries's avatar
Dries committed
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's avatar
   
Dries committed
38
function user_load($array = array()) {
Dries's avatar
Dries committed
39
40
  // Dynamically compose a SQL query:
  $query = '';
Dries's avatar
   
Dries committed
41

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

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

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

  return $user;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  return $user;
}

Dries's avatar
Dries committed
159
160
161
/**
 * Verify the syntax of the given name.
 */
Dries's avatar
   
Dries committed
162
function user_validate_name($name) {
Dries's avatar
Dries committed
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's avatar
   
Dries committed
170
171
172
}

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

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

Dries's avatar
Dries committed
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's avatar
   
Dries committed
186
  $size = getimagesize($file->path);
Dries's avatar
Dries committed
187
  list($maxwidth, $maxheight) = explode('x', variable_get('user_picture_dimensions', '85x85'));
Dries's avatar
   
Dries committed
188

Dries's avatar
Dries committed
189
  if ((!in_array($size[2], array(1, 2, 3))) || (!in_array($extension, array('.gif', '.jpg', '.png', '.jpeg')))) {
Dries's avatar
   
Dries committed
190
    form_set_error('picture', t('The uploaded file was not an image.'));
Dries's avatar
   
Dries committed
191
  }
Dries's avatar
Dries committed
192
  else if ($file->size > (variable_get('user_picture_file_size', '30') * 1000)) {
Dries's avatar
   
Dries 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's avatar
   
Dries committed
194
195
  }
  else if ($size[0] > $maxwidth || $size[1] > $maxheight) {
Dries's avatar
   
Dries 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's avatar
   
Dries committed
197
  }
Dries's avatar
Dries committed
198
  else if ($file = file_save_upload('picture', variable_get('user_picture_path', 'pictures') . FILE_SEPARATOR .'picture-'. $user->uid . $extension, 1)) {
Dries's avatar
   
Dries committed
199
200
201
    $edit['picture'] = $file->path;
  }
  else {
Dries's avatar
   
Dries 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's avatar
   
Dries committed
203
204
205
  }
}

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

Dries's avatar
Dries committed
214
215
216
/**
 * Generate a random alphanumeric password.
 */
Dries's avatar
   
Dries 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.
Dries's avatar
Dries committed
222
223
  $allowable_characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789';

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

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

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

Dries's avatar
Dries committed
233
  // Loop the number of times specified by $length.
Dries's avatar
   
Dries 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's avatar
   
Dries committed
242
243
}

Dries's avatar
Dries committed
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's avatar
   
Dries committed
257
258
function user_access($string) {
  global $user;
Dries's avatar
   
Dries committed
259
  static $perm = 0;
Dries's avatar
   
Dries committed
260

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

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

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

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

Dries's avatar
Dries committed
279
280
281
/**
 * Send an e-mail message.
 */
Dries's avatar
   
Dries committed
282
function user_mail($mail, $subject, $message, $header) {
Dries's avatar
Dries committed
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's avatar
   
Dries 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's avatar
   
Dries 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's avatar
   
Dries committed
308
309
310
    return mail(
      $mail,
      user_mail_encode($subject),
Dries's avatar
Dries committed
311
      str_replace("\r", '', $message),
Dries's avatar
   
Dries committed
312
      "MIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8; format=flowed\nContent-transfer-encoding: 8Bit\n" . $header
Dries's avatar
   
Dries committed
313
    );
Dries's avatar
   
Dries committed
314
315
316
  }
}

Dries's avatar
Dries committed
317
function user_mail_encode($string, $charset = 'UTF-8') {
Kjartan's avatar
Kjartan committed
318
319
320
321
  /*
  ** Used to encodes mail headers that contain non US- ASCII
  ** characters.
  ** http://www.rfc-editor.org/rfc/rfc2047.txt
Kjartan's avatar
Kjartan committed
322
323
  **
  ** Notes:
324
  **   - Only encode strings that contain non-ASCII characters.
Kjartan's avatar
Kjartan 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.
Kjartan's avatar
Kjartan committed
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));
  }
Kjartan's avatar
Kjartan committed
338
  return $string;
Dries's avatar
   
Dries committed
339
340
}

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

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

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

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

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

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

Dries's avatar
Dries committed
372
373
374
375
376
/**
 * Implementation of hook_file_download().
 *
 * Ensure that user pictures (avatars) are always downloadable.
 */
Dries's avatar
   
Dries committed
377
function user_file_download($file) {
Dries's avatar
Dries committed
378
  if (strpos($file, variable_get('user_picture_path', 'pictures') . FILE_SEPARATOR . 'picture-') === 0) {
Dries's avatar
   
Dries 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]);
  }
}

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

Dries's avatar
Dries committed
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's avatar
   
Dries committed
412
  while ($account = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
413
    $find[] = array('title' => $account->name, 'link' => url("user/$account->uid/view"), 'user' => $account->name);
Dries's avatar
   
Dries committed
414
  }
Dries's avatar
Dries committed
415
  return array(t('Matching users'), $find);
Dries's avatar
   
Dries committed
416
417
}

Dries's avatar
Dries committed
418
419
420
/**
 * Implementation of hook_user().
 */
Dries's avatar
Dries committed
421
function user_user($type, &$edit, &$user) {
Dries's avatar
Dries committed
422
  if ($type == 'view') {
Dries's avatar
Dries committed
423
    return array(t('History') => form_item(t('Member for'), format_interval(time() - $user->created)));
Dries's avatar
Dries committed
424
425
426
  }
}

Dries's avatar
Dries committed
427
428
429
430
/**
 * Implementation of hook_block().
 */
function user_block($op = 'list', $delta = 0) {
Dries's avatar
   
Dries committed
431
432
  global $user;

Dries's avatar
Dries committed
433
434
435
436
437
  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');
438

439
     return $blocks;
440
441
  }
  else {
Dries's avatar
   
Dries committed
442
443
    $block = array();

Dries's avatar
   
Dries committed
444
445
    switch ($delta) {
      case 0:
Dries's avatar
   
Dries committed
446

447
        if (!$user->uid) {
Dries's avatar
Dries committed
448
449
          // For usability's sake, avoid showing two login forms on one page.
          if (arg(0) == 'user' && arg(1) != 'view') {
Dries's avatar
   
Dries committed
450
451
452
            return;
          }

Dries's avatar
Dries committed
453
          $edit = $_POST['edit'];
Dries's avatar
   
Dries committed
454

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

Dries's avatar
Dries committed
457
458
          // Save the referer.  We record where the user came from such
          // that we can redirect him after having completed the login form.
Dries's avatar
Dries committed
459

460
          if (empty($edit)) {
Dries's avatar
Dries committed
461
            $edit['destination'] = $_GET['q'];
462
          }
Dries's avatar
Dries committed
463
464
465
466
467
468
469
470
          // 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's avatar
   
Dries committed
471
          $output .= "</div>\n";
Dries's avatar
   
Dries committed
472

Dries's avatar
Dries committed
473
          $output  = form($output, 'post', url('user/login'));
Dries's avatar
   
Dries committed
474

Dries's avatar
Dries committed
475
476
          if (variable_get('user_register', 1)) {
            $items[] = l(t('Create new account'), 'user/register', array('title' => t('Create a new user account.')));
Dries's avatar
   
Dries committed
477
          }
Dries's avatar
Dries committed
478
          $items[] = l(t('Request new password'), 'user/password', array('title' => t('Request new password via e-mail.')));
Dries's avatar
   
Dries committed
479

Dries's avatar
Dries committed
480
          $output .= theme('item_list', $items);
481

Dries's avatar
Dries committed
482
483
          $block['subject'] = t('User login');
          $block['content'] = $output;
Dries's avatar
   
Dries committed
484
        }
Dries's avatar
Dries committed
485
        return $block;
486
      case 1:
Dries's avatar
   
Dries committed
487
        if ($menu = theme('menu_tree')) {
Dries's avatar
Dries committed
488
489
           $block['subject'] = $user->uid ? $user->name : t('Navigation');
           $block['content'] = '<div class="menu">'. $menu .'</div>';
Dries's avatar
   
Dries committed
490
        }
491
        return $block;
Dries's avatar
   
Dries committed
492
      case 2:
Dries's avatar
Dries committed
493
494
        if (user_access('access content')) {
          $result = db_query_range('SELECT uid, name FROM {users} WHERE status != 0 ORDER BY uid DESC', 0, 5);
495
          while ($account = db_fetch_object($result)) {
496
            $items[] = format_name($account);
497
          }
Dries's avatar
   
Dries committed
498

Dries's avatar
Dries committed
499
          $output = theme('user_list', $items);
Dries's avatar
   
Dries committed
500

Dries's avatar
Dries committed
501
502
          $block['subject'] = t('Who\'s new');
          $block['content'] = $output;
503
504
          return $block;
        }
Dries's avatar
   
Dries committed
505
      case 3:
Dries's avatar
Dries committed
506
507
508
        if (user_access('access content')) {
          // Count users with activity in the past defined period.
          $time_period = variable_get('user_block_seconds_online', 2700);
Dries's avatar
   
Dries committed
509

Dries's avatar
Dries committed
510
511
512
          // 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
513
          $total_users = db_num_rows($users);
Dries's avatar
   
Dries committed
514

Dries's avatar
Dries committed
515
          // Format the output with proper grammar.
Dries's avatar
   
Dries committed
516
          if ($total_users == 1 && $guests->count == 1) {
Dries's avatar
Dries committed
517
            $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
518
519
          }
          else {
Dries's avatar
Dries committed
520
            $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's avatar
   
Dries committed
521
522
          }

Dries's avatar
Dries committed
523
          if (user_access('access user list') && $total_users) {
Dries's avatar
   
Dries committed
524

Dries's avatar
Dries committed
525
526
            // Display a list of currently online users.
            $max_users = variable_get('user_block_max_list_count', 10);
Dries's avatar
   
Dries committed
527
528
            if ($max_users) {
              $items = array();
Dries's avatar
   
Dries committed
529

Dries's avatar
   
Dries committed
530
              while ($max_users-- && $uid = db_fetch_object($users)) {
Dries's avatar
   
Dries committed
531
                $items[] = format_name(user_load(array('uid' => $uid->uid)));
Dries's avatar
   
Dries committed
532
533
534
              }

              if ($items) {
Dries's avatar
   
Dries committed
535
                if (db_fetch_object($users)) {
Dries's avatar
Dries committed
536
                  $items[] = '...';
Dries's avatar
   
Dries committed
537
                }
Dries's avatar
Dries committed
538
                $output .= theme('item_list', $items, t('Online users:'));
Dries's avatar
   
Dries committed
539
              }
Dries's avatar
   
Dries committed
540
            }
Dries's avatar
   
Dries committed
541
          }
Dries's avatar
Dries committed
542
543
          $block['subject'] = t('Who\'s online');
          $block['content'] = $output;
Dries's avatar
   
Dries committed
544
        }
Dries's avatar
   
Dries committed
545
        return $block;
Dries's avatar
   
Dries committed
546
547
    }
  }
548
549
}

Dries's avatar
   
Dries committed
550
551
552
553
554
555
556
557
558
559
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) {
Dries's avatar
Dries committed
560
      $picture = "<img src=\"$picture\" alt=\"" . t('%user\'s picture', array('%user' => $account->name ? $account->name : t(variable_get('anonymous', 'Anonymous')))) . '" />';
Dries's avatar
   
Dries committed
561
      if ($account->uid) {
Dries's avatar
Dries committed
562
        $picture = l($picture, "user/view/$account->uid", array('title' => t('View user profile.')));
Dries's avatar
   
Dries committed
563
564
565
566
567
568
569
      }

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

Dries's avatar
Dries committed
570
function theme_user_profile($account, $fields) {
Dries's avatar
   
Dries committed
571
572
  $output = "<div class=\"profile\">\n";
  $output .= theme('user_picture', $account);
Dries's avatar
Dries committed
573
574
575
  foreach ($fields as $category => $value) {
    $output .= "<h2>$category</h2>$value";
  }
Dries's avatar
   
Dries committed
576
577
578
579
580
  $output .= "</div>\n";

  return $output;
}

Dries's avatar
   
Dries committed
581
function theme_user_list($items, $title = NULL) {
Dries's avatar
Dries committed
582
  return theme('item_list', $items, $title);
Dries's avatar
   
Dries committed
583
584
}

Dries's avatar
   
Dries committed
585
/**
Dries's avatar
   
Dries committed
586
 * Implementation of hook_menu().
Dries's avatar
   
Dries committed
587
 */
Dries's avatar
   
Dries committed
588
function user_menu() {
Dries's avatar
   
Dries committed
589
  global $user;
Dries's avatar
   
Dries committed
590

Dries's avatar
   
Dries committed
591
  $items = array();
Dries's avatar
   
Dries committed
592

Dries's avatar
   
Dries committed
593
594
595
596
597
598
599
  $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);
    // Add the edit menu:
    if ($access) $function = 'user_admin_edit';
Dries's avatar
   
Dries committed
600
    else $function = 'user_page';
Dries's avatar
   
Dries committed
601
602
603
    $items[] = array('path' => 'user/'. arg(1) .'/edit', 'title' => t('edit'),
      'callback' => $function, 'access' => $access || $user->uid == arg(1),
      'type' => MENU_LOCAL_TASK);
Dries's avatar
   
Dries committed
604
  }
Dries's avatar
   
Dries committed
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661

  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'),
    'type' => MENU_CALLBACK);

  $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's avatar
   
Dries committed
662
663
}

Dries's avatar
Dries committed
664
665
666
/**
 * Called by authentication modules in order to edit/view their authmap information.
 */
667
function user_get_authname($account, $module) {
Dries's avatar
   
Dries committed
668
  $result = db_query("SELECT authname FROM {authmap} WHERE uid = %d AND module = '%s'", $account->uid, $module);
669
670
671
  return db_result($result);
}

Dries's avatar
Dries committed
672
673
674
675
/**
 * Accepts an user object, $account, or a DA name and returns an associative
 * array of modules and DA names. Called at external login.
 */
676
function user_get_authmaps($authname = NULL) {
Dries's avatar
   
Dries committed
677
  $result = db_query("SELECT authname, module FROM {authmap} WHERE authname = '%s'", $authname);
Dries's avatar
   
Dries committed
678
679
680
681
682
683
684
685
686
687
688
689
690
  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) {
Dries's avatar
Dries committed
691
    $module = explode('_', $key, 2);
Dries's avatar
   
Dries committed
692
    if ($value) {
Dries's avatar
Dries committed
693
      db_query("UPDATE {authmap} SET authname = '%s' WHERE uid = %d AND module = '%s'", $value, $account->uid, $module['1']);
Dries's avatar
   
Dries committed
694
695
      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
696
697
698
      }
    }
    else {
Dries's avatar
Dries committed
699
      db_query("DELETE FROM {authmap} WHERE uid = %d AND module = '%s'", $account->uid, $module['1']);
Dries's avatar
   
Dries committed
700
701
702
703
704
    }
  }
}

function user_auth_help_links() {
705
  $links = array();
Dries's avatar
   
Dries committed
706
  foreach (module_list() as $module) {
Dries's avatar
Dries committed
707
    if (module_hook($module, 'auth')) {
Dries's avatar
   
Dries committed
708
      $links[] = l(module_invoke($module, 'info', 'name'), "user/help#$module");
Dries's avatar
   
Dries committed
709
710
711
712
713
714
715
    }
  }
  return $links;
}

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

Dries's avatar
Dries committed
716
function user_login($edit = array(), $msg = '') {
Dries's avatar
   
Dries committed
717
  global $user, $base_url;
Dries's avatar
   
Dries committed
718

Dries's avatar
Dries committed
719
  // If we are already logged on, go to the user page instead.
Dries's avatar
   
Dries committed
720
  if ($user->uid) {
Dries's avatar
Dries committed
721
    drupal_goto('user');
Dries's avatar
   
Dries committed
722
723
  }

Dries's avatar
   
Dries committed
724
  if (user_deny('user', $edit['name'])) {
Dries's avatar
Dries committed
725
    $error = t('The name "%s" has been denied access.', array('%s' => $edit['name']));
Dries's avatar
   
Dries committed
726
  }
Dries's avatar
   
Dries committed
727
  else if ($edit['name'] && $edit['pass']) {
Dries's avatar
   
Dries committed
728

Dries's avatar
Dries committed
729
    // Try to log in the user locally:
Dries's avatar
   
Dries committed
730
    if (!$user->uid) {
Dries's avatar
   
Dries committed
731
732
      $name = $edit['name'];
      $pass = $edit['pass'];
Dries's avatar
Dries committed
733
      $user = user_load(array('name' => $name, 'pass' => $pass, 'status' => 1));
Dries's avatar
   
Dries committed
734
735
    }

Dries's avatar
Dries committed
736
737
    // Strip name and server from ID:
    if ($server = strrchr($edit['name'], '@')) {
Dries's avatar
   
Dries committed
738
      $name = substr($edit['name'], 0, strlen($edit['name']) - strlen($server));
739
      $server = substr($server, 1);
Dries's avatar
   
Dries committed
740
      $pass = $edit['pass'];
Dries's avatar
   
Dries committed
741
    }
Dries's avatar
   
Dries committed
742

Dries's avatar
Dries committed
743
744
    // When possible, determine corresponding external auth source. Invoke
    // source, and log in user if successful:
Dries's avatar
   
Dries committed
745
    if (!$user->uid && $server && $result = user_get_authmaps("$name@$server")) {
Dries's avatar
Dries committed
746
      if (module_invoke(key($result), 'auth', $name, $pass, $server)) {
Dries's avatar
   
Dries committed
747
        $user = user_external_load("$name@$server");
Dries's avatar
   
Dries committed
748
        watchdog('user', "external load: $name@$server, module: ". key($result));
Dries's avatar
   
Dries committed
749
750
      }
      else {
Dries's avatar
Dries committed
751
        $error = t('Invalid password for %s.', array('%s' => "<i>$name@$server</i>"));
Dries's avatar
   
Dries committed
752
753
754
      }
    }

Dries's avatar
Dries committed
755
756
    // Try each external authentication source in series. Register user if
    // successful.
Dries's avatar
   
Dries committed
757
    else if (!$user->uid && $server) {
Dries's avatar
   
Dries committed
758
      foreach (module_list() as $module) {
Dries's avatar
Dries committed
759
760
761
        if (module_hook($module, 'auth')) {
          if (module_invoke($module, 'auth', $name, $pass, $server)) {
            if (variable_get('user_register', 1) == 1 && !user_load(array('name' => "$name@$server"))) { // Register this new user.
Dries's avatar
   
Dries committed
762
              $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
763
              watchdog('user', "new user: $name@$server ($module ID)", l(t('edit user'), "user/$user->uid/edit"));
Dries's avatar
   
Dries committed
764
765
766
767
768
769
770
771
              break;
            }
          }
        }
      }
    }

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

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

Dries's avatar
Dries committed
777
      user_module_invoke('login', $edit, $user);
Dries's avatar
   
Dries committed
778

Dries's avatar
Dries committed
779
780
      // If the user wants to be remembered, set the proper cookie such
      // that the session won't expire.
Dries's avatar
   
Dries committed
781
      $path = preg_replace("/.+\/\/[^\/]+(.*)/", "\$1/", $base_url);
Dries's avatar
   
Dries committed
782
      setcookie(session_name(), session_id(), FALSE, $path);
Dries's avatar
   
Dries committed
783

Dries's avatar
Dries committed
784
785
      // Redirect the user to the page he logged on from.
      drupal_goto($edit['destination']);
Dries's avatar
   
Dries committed
786
787
788
    }
    else {
      if (!$error) {
Dries's avatar
Dries committed
789
        $error = t('Sorry.  Unrecognized username or password.') .' '. l(t('Have you forgotten your password?'), 'user/password');
Dries's avatar
   
Dries committed
790
791
      }
      if ($server) {
Dries's avatar
   
Dries committed
792
        watchdog('user', "failed login for '$name@$server': $error");
Dries's avatar
   
Dries committed
793
794
      }
      else {
Dries's avatar
   
Dries committed
795
        watchdog('user', "failed login for '$name': $error");
Dries's avatar
   
Dries committed
796
797
798
799
      }
    }
  }

Dries's avatar
Dries committed
800
  // Display error message (if any):
Dries's avatar
   
Dries committed
801
  if ($error) {
Dries's avatar
   
Dries committed
802
    drupal_set_message($error, 'error');
Dries's avatar
   
Dries committed
803
804
  }

Dries's avatar
Dries committed
805
806
  // Save the referrer.  We record where the user came from such that we
  // can redirect him after having completed the login form.
807
  if (empty($edit)) {
Dries's avatar
Dries committed
808
    $edit['destination'] = $_GET['q'];
Dries's avatar
   
Dries committed
809
  }
Dries's avatar
Dries committed
810
  $output .= form_hidden('destination', $edit['destination']);
Dries's avatar
   
Dries committed
811

Dries's avatar
Dries committed
812
  // Display login form:
Dries's avatar
   
Dries committed
813
814
815
  if ($msg) {
    $output .= "<p>$msg</p>";
  }
Dries's avatar
   
Dries committed
816
  if (count(user_auth_help_links()) > 0) {
Dries's avatar
Dries committed
817
    $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
818
819
  }
  else {
Dries's avatar
Dries committed
820
    $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
821
  }
Dries's avatar
Dries committed
822
823
824
825
826
  $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');
827
  }
Dries's avatar
Dries committed
828
  $output .= theme('item_list', $items);
Dries's avatar
   
Dries committed
829

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

Dries's avatar
Dries committed
832
  return form($output, 'post', url('user/login'));
Dries's avatar
   
Dries committed
833
834
}

835
function _user_authenticated_id() {
Dries's avatar
   
Dries committed
836
  return db_result(db_query("SELECT rid FROM {role} WHERE name = 'authenticated user'"));
837
838
}

Dries's avatar
Dries committed
839
840
841
/**
 * Menu callback; logs the current user out, and redirects to the home page.
 */
Dries's avatar
   
Dries committed
842
843
844
845
function user_logout() {
  global $user;

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

Dries's avatar
Dries committed
848
    // Destroy the current session:
Dries's avatar
   
Dries committed
849
    session_destroy();
Dries's avatar
   
Dries committed
850
    module_invoke_all('user', 'logout', NULL, $user);
Dries's avatar
   
Dries committed
851
852
853
    unset($user);
  }

Dries's avatar
Dries committed
854
  drupal_goto();
Dries's avatar
   
Dries committed
855
856
857
}

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

Dries's avatar
   
Dries committed
860
  if ($edit['name']) {
861
    $account = db_fetch_object(db_query("SELECT uid, name, mail FROM {users} WHERE status = 1 AND LOWER(name) = '%s'", strtolower($edit['name'])));
Dries's avatar
   
Dries committed
862
    if (!$account) form_set_error('name', t('Sorry. The username "<i>%s</i>" is not recognized.', array('%s' => $edit['name'])));
863
  }
Dries's avatar
   
Dries committed
864
  else if ($edit['mail']) {
865
    $account = db_fetch_object(db_query("SELECT uid, name, mail FROM {users} WHERE status = 1 AND LOWER(mail) = '%s'", strtolower($edit['mail'])));
Dries's avatar
   
Dries committed
866
    if (!$account) form_set_error('name', t('Sorry. The e-mail address "<i>%s</i>" is not recognized.', array('%s' => $edit['mail'])));
Kjartan's avatar
Kjartan committed
867
868
  }
  if ($account) {
Dries's avatar
   
Dries committed
869

Dries's avatar
Dries committed
870
      $from = variable_get('site_mail', ini_get('sendmail_from'));
Dries's avatar
   
Dries committed
871
872
      $pass = user_password();

Dries's avatar
Dries committed
873
      // Save new password:
Dries's avatar
   
Dries committed
874
      user_save($account, array('pass' => $pass));
Dries's avatar
   
Dries committed
875

Dries's avatar
Dries committed
876
877
878
879
      // Mail new password:
      $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));
      $subject = _user_mail_text('pass_subject', $variables);
      $body = _user_mail_text('pass_body', $variables);
880
      $headers = "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from";
Dries's avatar
   
Dries committed
881
      $mail_success = user_mail($account->mail, $subject, $body, $headers);
Dries's avatar
   
Dries committed
882

Dries's avatar
   
Dries committed
883
      if ($mail_success) {
Dries's avatar
Dries committed
884
885
        watchdog('user', 'mail password: "'. $account->name .'" &lt;'. $account->mail .'&gt;');
        return t('Your password and further instructions have been sent to your e-mail address.');
Dries's avatar
   
Dries committed
886
887
      }
      else {
Dries's avatar
Dries committed
888
889
        watchdog('error', 'error mailing new password: "'. $account->name .'" &lt;'. $account->mail .'&gt;');
        return t('Unable to send mail. Please contact the site admin.');
Dries's avatar
   
Dries committed
890
      }
Dries's avatar
   
Dries committed
891
892
    }
    else {
893

Dries's avatar
Dries committed
894
895
896
897
898
899
900
901
    // Display form:
    $output .= '<p>'. t('Enter your username <strong><em>or</em></strong> your e-mail address.') .'</p>';
    $output .= form_textfield(t('Username'), 'name', $edit['name'], 30, 64);
    $output .= form_textfield(t('E-mail address'), 'mail', $edit['mail'], 30, 64);
    $output .= form_submit(t('E-mail new password'));
    $items[] = l(t('Log in'), 'user/login');
    if (variable_get('user_register', 1)) {
      $items[] = l(t('Create new account'), 'user/register');
902
    }
Dries's avatar
Dries committed
903
    $output .= theme('item_list', $items);
Dries's avatar
   
Dries committed
904
    $output  = form_group(t('Request new password'), $output);
Dries's avatar
Dries committed
905
    return form($output, 'post', url('user/password'));
Dries's avatar
   
Dries committed
906
907
908
909
  }
}

function user_register($edit = array()) {