3 * GNU social's implementation of SessionHandler
5 * StatusNet - the distributed open-source microblogging tool
6 * Copyright (C) 2009, StatusNet, Inc.
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Affero General Public License for more details.
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 if (!defined('GNUSOCIAL')) {
27 * Superclass representing the associated interfaces of session handling.
31 class InternalSessionHandler implements SessionHandlerInterface
34 * A helper function to print a session-related message to the debug log if
35 * the site session debug configuration option is enabled.
39 public static function logdeb($msg)
41 if (common_config('sessions', 'debug')) {
42 common_debug("Session: " . $msg);
47 * Dummy option for saving to file needed for full PHP adherence.
50 * @param $session_name
53 public function open($save_path, $session_name)
59 * Dummy option for saving to file needed for full PHP adherence.
63 public function close()
69 * Fetch the session data for the session with the given $id.
72 * @return string Returns an encoded string of the read data. If nothing was read, it must return an empty string. Note this value is returned internally to PHP for processing.
74 public function read($id)
76 self::logdeb("Fetching session '$id'.");
78 $session = Session::getKV('id', $id);
80 if (empty($session)) {
81 self::logdeb("Couldn't find '$id'.");
84 self::logdeb("Found '$id', returning " .
85 strlen($session->session_data) .
87 return (string)$session->session_data;
92 * Write the session data for session with given $id as $session_data.
95 * @param $session_data
96 * @return bool Returns TRUE on success or FALSE on failure.
98 public function write($id, $session_data)
100 self::logdeb("Writing session '$id'.");
102 $session = Session::getKV('id', $id);
104 if (empty($session)) {
105 self::logdeb("'$id' doesn't yet exist; inserting.");
106 $session = new Session();
109 $session->session_data = $session_data;
110 $session->created = common_sql_now();
112 $result = $session->insert();
115 common_log_db_error($session, 'INSERT', __FILE__);
116 self::logdeb("Failed to insert '$id'.");
118 self::logdeb("Successfully inserted '$id' (result = $result).");
120 return (bool) $result;
122 self::logdeb("'$id' already exists; updating.");
123 if (strcmp($session->session_data, $session_data) == 0) {
124 self::logdeb("Not writing session '$id' - unchanged.");
127 self::logdeb("Session '$id' data changed - updating.");
129 // Only update the required field
130 $orig = clone($session);
131 $session->session_data = $session_data;
132 $result = $session->update($orig);
135 common_log_db_error($session, 'UPDATE', __FILE__);
136 self::logdeb("Failed to update '$id'.");
138 self::logdeb("Successfully updated '$id' (result = $result).");
141 return (bool) $result;
147 * Find sessions that have persisted beyond $maxlifetime and delete them.
148 * This will be limited by config['sessions']['gc_limit'] - it won't delete
149 * more than the number of sessions specified there at a single pass.
151 * @param $maxlifetime
152 * @return bool Returns TRUE on success or FALSE on failure.
154 public function gc($maxlifetime)
156 self::logdeb("Garbage Collector has now started with maxlifetime = '$maxlifetime'.");
158 $epoch = common_sql_date(time() - $maxlifetime);
162 $session = new Session();
163 $session->whereAdd('modified < "' . $epoch . '"');
164 $session->selectAdd();
165 $session->selectAdd('id');
167 $limit = common_config('sessions', 'gc_limit');
169 // On large sites, too many sessions to expire
170 // at once will just result in failure.
171 $session->limit($limit);
176 while ($session->fetch()) {
177 $ids[] = $session->id;
182 self::logdeb("Garbage Collector found " . count($ids) . " ids to delete.");
184 foreach ($ids as $id) {
185 self::logdeb("Garbage Collector will now delete session '$id'.");
193 * Deletes session with given id $id.
196 * @return bool Returns TRUE on success or FALSE on failure.
198 public function destroy($id)
200 self::logdeb("Destroying session '$id'.");
202 $session = Session::getKV('id', $id);
204 if (empty($session)) {
205 self::logdeb("Can't find '$id' to destroy.");
208 $result = $session->delete();
210 common_log_db_error($session, 'DELETE', __FILE__);
211 self::logdeb("Failed to destroy '$id'.");
213 self::logdeb("Successfully destroyed '$id' (result = $result).");
215 return (bool) $result;