/[drupal]/contributions/modules/memcache/memcache-session.inc
ViewVC logotype

Contents of /contributions/modules/memcache/memcache-session.inc

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


Revision 1.4 - (show annotations) (download) (as text)
Tue Nov 11 03:09:41 2008 UTC (12 months, 2 weeks ago) by jeremy
Branch: MAIN
CVS Tags: HEAD
Changes since 1.3: +2 -2 lines
File MIME type: text/x-php
Bug #332719: don't lose anonymous sessions.
1 <?php
2 // $Id: memcache-session.inc,v 1.3 2008/11/11 03:05:10 jeremy Exp $
3
4 /**
5 * @file
6 * User session handling functions.
7 */
8
9 function sess_open($save_path, $session_name) {
10 return TRUE;
11 }
12
13 function sess_close() {
14 return TRUE;
15 }
16
17 function sess_read($key) {
18 global $user;
19
20 // Write and Close handlers are called after destructing objects since PHP 5.0.5
21 // Thus destructors can use sessions but session handler can't use objects.
22 // So we are moving session closure before destructing objects.
23 register_shutdown_function('session_write_close');
24
25 // Handle the case of first time visitors and clients that don't store cookies (eg. web crawlers).
26 if (!isset($_COOKIE[session_name()])) {
27 $user = drupal_anonymous_user();
28 return '';
29 }
30
31 // Otherwise, if the session is still active, we have a record of the client's session in memcache.
32 $session = dmemcache_get($key, 'session');
33
34 $user = sess_user_load($session);
35
36 return $user->session;
37 }
38
39 function sess_write($key, $value) {
40 global $user;
41
42 // If the client doesn't have a session, and one isn't being created ($value), do nothing.
43 if (empty($_COOKIE[session_name()]) && empty($value)) {
44 return TRUE;
45 }
46
47 // Prepare the information to be saved
48 $session = new stdClass;
49 $session->sid = $key;
50 $session->uid = $user->uid;
51 $session->cache = $user->cache;
52 $session->hostname = $_SERVER["REMOTE_ADDR"];
53 $session->session = $value;
54 $session->timestamp = time();
55
56 if ($user->uid || $value) {
57 dmemcache_set($key, $session, ini_get('session.gc_maxlifetime'), 'session');
58 dmemcache_set($user->uid, $user, ini_get('session.gc_maxlifetime'), 'users');
59 if ($user->uid && $user->access < time() - 300) {
60 db_query("UPDATE {users} SET access = %d WHERE uid = %d", time(), $user->uid);
61 }
62 }
63
64 return TRUE;
65 }
66
67 function sess_regenerate() {
68 // We code around http://bugs.php.net/bug.php?id=32802 by destroying
69 // the session cookie by setting expiration in the past (a negative
70 // value). This issue only arises in PHP versions before 4.4.0,
71 // regardless of the Drupal configuration.
72 // TODO: remove this when we require at least PHP 4.4.0
73 if (isset($_COOKIE[session_name()])) {
74 setcookie(session_name(), '', time() - 42000, '/');
75 }
76
77 // Store the current (anonymous) session id.
78 $old_session_id = session_id();
79
80 // Generate the new (authenticated) session id.
81 session_regenerate_id();
82 $key = session_id();
83
84 // Grab the user's information that is cached with the anonymous key
85 $info = dmemcache_get($old_session_id, 'session');
86
87 // Update it.
88 $info->sid = $key;
89
90 // Store it with the new key.
91 dmemcache_set($key, $info, ini_get('session.gc_maxlifetime'), 'session');
92
93 // Clear the old data from the cache.
94 dmemcache_delete($old_session_id, 'session');
95 }
96
97 /**
98 * Counts how many users have sessions. Can count either anonymous sessions, authenticated sessions, or both.
99 * Would be insane slow with memcached as we would need to retrieve at least the stats of all object.
100 * Not implemented.
101 */
102 function sess_count($timestamp = 0, $anonymous = true) {
103 }
104
105 /**
106 * Called by PHP session handling with the PHP session ID to end a user's session.
107 *
108 * @param string $sid
109 * the session id
110 */
111 function sess_destroy_sid($sid) {
112 dmemcache_delete($sid, 'session');
113 }
114
115 /**
116 * End a specific user's session. Not implemented.
117 */
118 function sess_destroy_uid($uid) {
119 }
120
121 function sess_gc($lifetime) {
122 // Automatic with memcached.
123 // Be sure to adjust 'php_value session.gc_maxlifetime' to a large enough
124 // value. For example, if you want user sessions to stay in your database
125 // for three weeks before deleting them, you need to set gc_maxlifetime
126 // to '1814400'. At that value, only after a user doesn't log in after
127 // three weeks (1814400 seconds) will his/her session be removed.
128 return TRUE;
129 }
130
131 function sess_user_load($session) {
132 $user = new stdClass;
133 // We found the client's session record and they are an authenticated user
134 if ($session && $session->uid > 0) {
135 $user = dmemcache_get($session->uid, 'users');
136 if (!$user->uid && $user->uid != 0) {
137 $user = db_fetch_object(db_query("SELECT u.* FROM {users} u WHERE u.uid = %d", $session->uid));
138 $user = drupal_unpack($user);
139 $user->session = empty($session->session) ? '' : $session->session;
140
141 // Add roles element to $user
142 $user->roles = array();
143 $user->roles[DRUPAL_AUTHENTICATED_RID] = 'authenticated user';
144 $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);
145 while ($role = db_fetch_object($result)) {
146 $user->roles[$role->rid] = $role->name;
147 }
148 }
149 else if ($user->uid) {
150 $user->from_cache = TRUE;
151 $user->session = empty($session->session) ? '' : $session->session;
152 }
153 else {
154 // This is a rare case that we have a session cached, but no session user object cached.
155 // This usually only happens if you kill memcached and restart it.
156 $user = drupal_anonymous_user($session->session);
157 }
158 }
159 // We didn't find the client's record (session has expired), or they are an anonymous user.
160 else {
161 $session = isset($session->session) ? $session->session : '';
162 $user = drupal_anonymous_user($session);
163 }
164
165 return $user;
166 }

  ViewVC Help
Powered by ViewVC 1.1.2