]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - classes/Session.php
Merge branch 'case-sensitive-openid' into 'master'
[quix0rs-gnu-social.git] / classes / Session.php
1 <?php
2 /**
3  * Table Definition for session
4  *
5  * StatusNet - the distributed open-source microblogging tool
6  * Copyright (C) 2009, StatusNet, Inc.
7  *
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.
12  *
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.
17  *
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/>.
20  */
21
22 if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
23
24 require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
25
26 class Session extends Managed_DataObject
27 {
28     ###START_AUTOCODE
29     /* the code below is auto generated do not remove the above tag */
30
31     public $__table = 'session';                         // table name
32     public $id;                              // varchar(32)  primary_key not_null
33     public $session_data;                    // text()
34     public $created;                         // datetime()   not_null
35     public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP
36
37     /* the code above is auto generated do not remove the tag below */
38     ###END_AUTOCODE
39
40     public static function schemaDef()
41     {
42         return array(
43             'fields' => array(
44                 'id' => array('type' => 'varchar', 'length' => 32, 'not null' => true, 'description' => 'session ID'),
45                 'session_data' => array('type' => 'text', 'description' => 'session data'),
46                 'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
47                 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
48             ),
49             'primary key' => array('id'),
50             'indexes' => array(
51                 'session_modified_idx' => array('modified'),
52             ),
53         );
54     }
55
56     static function logdeb($msg)
57     {
58         if (common_config('sessions', 'debug')) {
59             common_debug("Session: " . $msg);
60         }
61     }
62
63     static function open($save_path, $session_name)
64     {
65         return true;
66     }
67
68     static function close()
69     {
70         return true;
71     }
72
73     static function read($id)
74     {
75         self::logdeb("Fetching session '$id'");
76
77         $session = Session::getKV('id', $id);
78
79         if (empty($session)) {
80             self::logdeb("Couldn't find '$id'");
81             return '';
82         } else {
83             self::logdeb("Found '$id', returning " .
84                          strlen($session->session_data) .
85                          " chars of data");
86             return (string)$session->session_data;
87         }
88     }
89
90     static function write($id, $session_data)
91     {
92         self::logdeb("Writing session '$id'");
93
94         $session = Session::getKV('id', $id);
95
96         if (empty($session)) {
97             self::logdeb("'$id' doesn't yet exist; inserting.");
98             $session = new Session();
99
100             $session->id           = $id;
101             $session->session_data = $session_data;
102             $session->created      = common_sql_now();
103
104             $result = $session->insert();
105
106             if (!$result) {
107                 common_log_db_error($session, 'INSERT', __FILE__);
108                 self::logdeb("Failed to insert '$id'.");
109             } else {
110                 self::logdeb("Successfully inserted '$id' (result = $result).");
111             }
112             return $result;
113         } else {
114             self::logdeb("'$id' already exists; updating.");
115             if (strcmp($session->session_data, $session_data) == 0) {
116                 self::logdeb("Not writing session '$id'; unchanged");
117                 return true;
118             } else {
119                 self::logdeb("Session '$id' data changed; updating");
120
121                 $orig = clone($session);
122
123                 $session->session_data = $session_data;
124
125                 $result = $session->update($orig);
126
127                 if (!$result) {
128                     common_log_db_error($session, 'UPDATE', __FILE__);
129                     self::logdeb("Failed to update '$id'.");
130                 } else {
131                     self::logdeb("Successfully updated '$id' (result = $result).");
132                 }
133
134                 return $result;
135             }
136         }
137     }
138
139     static function destroy($id)
140     {
141         self::logdeb("Deleting session $id");
142
143         $session = Session::getKV('id', $id);
144
145         if (empty($session)) {
146             self::logdeb("Can't find '$id' to delete.");
147         } else {
148             $result = $session->delete();
149             if (!$result) {
150                 common_log_db_error($session, 'DELETE', __FILE__);
151                 self::logdeb("Failed to delete '$id'.");
152             } else {
153                 self::logdeb("Successfully deleted '$id' (result = $result).");
154             }
155             return $result;
156         }
157     }
158
159     static function gc($maxlifetime)
160     {
161         self::logdeb("garbage collection (maxlifetime = $maxlifetime)");
162
163         $epoch = common_sql_date(time() - $maxlifetime);
164
165         $ids = array();
166
167         $session = new Session();
168         $session->whereAdd('modified < "'.$epoch.'"');
169         $session->selectAdd();
170         $session->selectAdd('id');
171
172         $limit = common_config('sessions', 'gc_limit');
173         if ($limit > 0) {
174             // On large sites, too many sessions to expire
175             // at once will just result in failure.
176             $session->limit($limit);
177         }
178
179         $session->find();
180
181         while ($session->fetch()) {
182             $ids[] = $session->id;
183         }
184
185         $session->free();
186
187         self::logdeb("Found " . count($ids) . " ids to delete.");
188
189         foreach ($ids as $id) {
190             self::logdeb("Destroying session '$id'.");
191             self::destroy($id);
192         }
193     }
194
195     static function setSaveHandler()
196     {
197         self::logdeb("setting save handlers");
198         $result = session_set_save_handler('Session::open', 'Session::close', 'Session::read',
199                                            'Session::write', 'Session::destroy', 'Session::gc');
200         self::logdeb("save handlers result = $result");
201
202         // PHP 5.3 with APC ends up destroying a bunch of object stuff before the session
203         // save handlers get called on request teardown.
204         // Registering an explicit shutdown function should take care of this before
205         // everything breaks on us.
206         register_shutdown_function('Session::cleanup');
207         
208         return $result;
209     }
210
211     static function cleanup()
212     {
213         session_write_close();
214     }
215 }