/[drupal]/contributions/sandbox/bjaspan/remember_me/remember_me.module
ViewVC logotype

Contents of /contributions/sandbox/bjaspan/remember_me/remember_me.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.1 - (show annotations) (download) (as text)
Mon Oct 9 14:38:35 2006 UTC (3 years, 1 month ago) by bjaspan
Branch: MAIN
CVS Tags: HEAD
File MIME type: text/x-php
initial revision
1 <?php
2 // $Id: remember_me.module,v 1.4 2006/10/09 14:20:29 bjaspan Exp $
3
4 // Include $base_path in REMEMBER_ME so a user can be logged in
5 // to more than one Drupal site per domain.
6 global $base_path;
7 define('REMEMBER_ME_COOKIE',
8 'REMEMBER_ME_'.preg_replace('/[^a-zA-Z0-9_]/', '_', $base_path));
9 define('REMEMBER_ME_SECURE_PATHS',
10 "user/*/edit\nuser/*/address\n".
11 "cart/checkout\n".
12 "admin/settings/remember_me\n");
13 define('REMEMBER_ME_MAXLIFE', 30);
14
15 /**
16 * Implementation of hook_help().
17 */
18 function remember_me_help($section) {
19 if ($section == 'admin/modules#description') {
20 return t('Provide a "Remember Me" checkbox in the login form');
21 }
22 }
23
24 /**
25 * Implementation of hook_perm().
26 */
27 function remember_me_perm() {
28 return array('administer Remember Me');
29 }
30
31 /**
32 * Implementation of hook_menu().
33 */
34 function remember_me_menu($may_cache) {
35 $items = array();
36 if ($may_cache) {
37 $items[] = array
38 ('path' => 'remember_me/erase',
39 'callback' => 'remember_me_erase',
40 'access' => TRUE,
41 'type' => MENU_CALLBACK);
42 }
43 return $items;
44 }
45
46 function remember_me_settings() {
47 if (!user_access('administer Remember Me'))
48 return;
49
50 $form['remember_me_maxlife'] = array
51 ('#type' => 'textfield',
52 '#title' => 'Days to remember the user',
53 '#default_value' => variable_get('remember_me_maxlife',
54 REMEMBER_ME_MAXLIFE),
55 '#description' => t('The maximum number of days for which a Remember Me '.
56 'login session is valid; afterwards, the user will '.
57 'need to log in again. Enter 0 for no expiration.'));
58 $form['remember_me_secure'] = array(
59 '#type' => 'radios',
60 '#title' => t('Pages which require an explicit login'),
61 '#default_value' => variable_get('remember_me_secure', 1),
62 '#options' => array(t('Every page except the listed pages.'),
63 t('Only the listed pages.')),
64 );
65 $form['remember_me_pages'] = array(
66 '#type' => 'textarea',
67 '#title' => t('Pages'),
68 '#default_value' => variable_get('remember_me_pages',
69 REMEMBER_ME_SECURE_PATHS),
70 '#cols' => 40,
71 '#rows' => 5,
72 '#description' => t("Enter one page per line as Drupal paths. The '*' character is a wildcard. Example paths are '<em>blog</em>' for the blog page, '<em>blog/*</em>' for every personal blog, and '<em>blog*</em>' for both. '<em>&lt;front&gt;</em>' is the front page."),
73 );
74 return $form;
75 }
76
77 /**
78 * Implementation of hook_form_alter().
79 */
80 function remember_me_form_alter($form_id, &$form) {
81 $element = array
82 ('#type' => 'checkbox',
83 '#title' => t('Remember me'));
84 if ($form_id == 'user_login') {
85 $form['remember_me'] = $element;
86 } else if ($form_id == 'user_login_block') {
87 /* there must be a better way! */
88 $tmp = $form;
89 $form = array();
90 foreach ($tmp as $k => $v) {
91 $form[$k] = $v;
92 if ($k == 'pass') {
93 $form['remember_me'] = $element;
94 }
95 }
96 }
97 }
98
99 /**
100 * Implementation of hook_init().
101 *
102 * If a non-logged in user has a valid Remember Me cookie, log her in,
103 * disable the old cookie, and issue a new one for next time. Then
104 * reload the current page so the user is logged in from the
105 * beginning.
106 *
107 * If a user logged in by Remember Me tries to access a protected
108 * page, redirect them to the login page. Their remembered login is
109 * preserved, though, so they can skip the login and keep browsing
110 * non-protected pages.
111 */
112 function remember_me_init() {
113 global $user;
114 $path = $_GET['q'];
115
116 /* do not interfere with login/logout pages */
117 if ($path === 'user/login' || $path === 'logout') {
118 return;
119 }
120
121 if ($user->uid == 0 && !is_null($_COOKIE[REMEMBER_ME_COOKIE]) &&
122 !$_SESSION['remember_me_check']) {
123 /* for efficiency, only check once per session unless something changes */
124 $_SESSION['remember_me_check'] = true;
125
126 $cookie = explode(':', $_COOKIE[REMEMBER_ME_COOKIE]);
127 $now = time();
128 $r = db_fetch_array
129 (db_query('SELECT u.name, rm.uid, rm.expires FROM {remember_me} rm '.
130 'INNER JOIN {users} u on u.uid = rm.uid '.
131 'WHERE rm.uid=%d AND rm.rnd="%s" AND '.
132 ' (rm.expires = 0 OR rm.expires > %d)',
133 $cookie[0], $cookie[1], $now));
134 if (is_array($r) && count($r) > 0) {
135 /*
136 The Remember Me cookie is valid. $r is a 'user form' that
137 contains only name, uid, and expires. Change expires to
138 remember_me_expires so keep the namespace clean. Also add
139 remember_me so we and other modules can tell what is going on.
140 */
141 $r['remember_me'] = 1;
142 $r['remember_me_expires'] = $r['expires'];
143 unset($r['expires']);
144
145 /*
146 Verify the account is still valid. Without $r['pass'], no
147 actual authentication will occur.
148
149 Note that if an admin edits a user to be blocked, all existing
150 remember me tokens are deleted from the db anyway. A user
151 account might passively expire, though.
152 */
153 user_login_validate('remember_me', $r);
154 if (form_get_errors()) {
155 /* user is not logged in; may get access denied depending on page */
156 return;
157 }
158
159 /* Delete the one-time use remember me cookie */
160 db_query('DELETE FROM {remember_me} WHERE uid=%d AND rnd="%s"',
161 $cookie[0], $cookie[1]);
162
163 /*
164 Log in the user. Use user_login_submit here so
165 hook_user('login') is invoked, login is watchdogged, and db is
166 updated. Be sure to override remember_me_login set in our
167 hook_user.
168 */
169 $user = user_load(array('uid' => $r['uid']));
170 user_login_submit('remember_me', $r);
171 $_SESSION['remember_me_login'] = true;
172 drupal_set_message(t('Welcome back, %name.',
173 array('%name' => check_plain($r['name']))));
174
175 /* reload this page as the user in case some other init hook cares */
176 drupal_goto(substr(drupal_get_destination(), 12));
177 return; /*not reached*/
178 }
179 } else if ($_SESSION['remember_me_login']) {
180 /*
181 User is logged in only via Remember Me. Don't let them visit
182 restricted pages.
183 */
184 $path = $_GET['q'];
185 $page_match = _remember_me_match($path);
186 if ($page_match) {
187 $user = user_load(array('uid' => 0));
188 $_SESSION['remember_me_check'] = FALSE;
189 $_SESSION['remember_me_login'] = FALSE;
190 drupal_set_message(t('You must log in with your username and password '.
191 'to perform this action.'));
192 drupal_goto('user/login', drupal_get_destination());
193 }
194 }
195 }
196
197
198 /**
199 * Implementation of hook_user().
200 */
201 function remember_me_user($op, &$edit, &$account, $category = NULL) {
202 global $user;
203 switch ($op) {
204 case 'login':
205 if ($edit['remember_me'] == 1) {
206 /* set a new cookie, preserving original expiration if present */
207 _remember_me_setcookie($user, $edit['remember_me_expires']);
208 }
209 $_SESSION['remember_me_login'] = FALSE;
210 break;
211
212 case 'logout':
213 if (! is_null($_COOKIE[REMEMBER_ME_COOKIE])) {
214 $_SESSION['remember_me_check'] = NULL;
215 $_SESSION['remember_me_login'] = NULL;
216 $cookie = explode(':', $_COOKIE[REMEMBER_ME_COOKIE]);
217 db_query('DELETE FROM {remember_me} WHERE uid=%d AND rnd="%s"',
218 $cookie[0], $cookie[1]);
219 }
220 break;
221
222 case 'view':
223 if ($user->uid == $account->uid ||
224 user_access('administer Remember Me')) {
225 $n = db_result(db_query('SELECT count(*) FROM {remember_me} '.
226 'WHERE uid=%d AND (expires = 0 OR expires > %d)',
227 $account->uid, time()));
228 $items[] = array
229 ('title' => t('Remembered logins'),
230 'value' => t('You have %n persistent login session(s) created with '.
231 'the "Remember Me" login option on this site.<br />'.
232 l(t('Erase persistent logins now'),
233 'remember_me/erase/'.$account->uid, array(),
234 drupal_get_destination()).
235 ' (this will not log you out).',
236 array('%n' => $n)),
237 'class' => 'logins',
238 );
239
240 return ($n > 0) ? array(t('History') => $items) : NULL;
241 }
242 break;
243
244 case 'update':
245 case 'delete':
246 db_query('DELETE FROM {remember_me} WHERE uid=%d', $account->uid);
247 $_SESSION['remember_me_check'] = NULL;
248 $_SESSION['remember_me_login'] = NULL;
249 break;
250 }
251 }
252
253 /**
254 * Implementation of hook_cron().
255 */
256 function remember_me_cron() {
257 db_query('DELETE FROM {remember_me} WHERE expires < %d', time());
258 }
259
260 function remember_me_erase($uid = NULL) {
261 global $user;
262 if (! isset($uid)) {
263 $uid = $user->uid;
264 }
265 if ($uid > 0 &&
266 ($user->uid == $uid || user_access('administer Remember Me'))) {
267 db_query('DELETE FROM {remember_me} WHERE uid=%d', $uid);
268 }
269 drupal_goto();
270 }
271
272 function _remember_me_setcookie($user, $expires = NULL) {
273 $tok = md5(mt_rand().$user->pass.mt_rand());
274 $days = variable_get('remember_me_maxlife', REMEMBER_ME_MAXLIFE);
275 if (! isset($expires)) {
276 $expires = ($days > 0) ? time()+$days*86400 : 0;
277 }
278 setcookie(REMEMBER_ME_COOKIE, $user->uid.':'.$tok,
279 $expires > 0 ? $expires : 2147483647, '/');
280 db_query('INSERT INTO {remember_me} (rnd, uid, expires) '.
281 'VALUES ("%s", %d, %d)', $tok, $user->uid, $expires);
282 }
283
284 /**
285 * _remember_me_match()
286 *
287 * check the page past and see if it should be secure or insecure.
288 *
289 * @@param $path
290 * the page of the page to check.
291 *
292 * @@return
293 * 0 - page should be insecure.
294 * 1 - page should be secure.
295 * NULL - do not change page.
296 */
297 function _remember_me_match($path) {
298 $secure = variable_get('remember_me_secure', 1);
299 $pages = variable_get('remember_me_pages', REMEMBER_ME_SECURE_PATHS);
300
301 if ($pages) {
302 $regexp = '/^('. preg_replace(array('/(\r\n?|\n)/', '/\\\\\*/', '/(^|\|)\\\\<front\\\\>($|\|)/'), array('|', '.*', '\1'. preg_quote(variable_get('site_frontpage', 'node'), '/') .'\2'), preg_quote($pages, '/')) .')$/';
303 return !($secure xor preg_match($regexp, $path));
304 }
305 else {
306 return;
307 }
308 }

  ViewVC Help
Powered by ViewVC 1.1.2