~quam-plures-core/quam-plures/qp5_colls-blogs_chaps-cats

« back to all changes in this revision

Viewing changes to qp_inc/sessions/model/_session.class.php

  • Committer: EdB
  • Date: 2013-03-12 06:26:03 UTC
  • Revision ID: 1912webworks@gmail.com-20130312062603-tnlb5zco5mglydqj
lots of changes in this branch. tested and functional, but not going into merge just yet ...

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 * are tracked with a cookie containing the session ID. The cookie also contains
12
12
 * a random key to prevent sessions hacking.
13
13
 *
14
 
 * @todo (1111): vars type 'foo' need useful/valid descriptions
15
 
 * @todo (1111): session_unserialize_callback() and session_unserialize_load_all_classes()
 
14
 * @todo (1111) vars type 'foo' need useful/valid descriptions
 
15
 * @todo (1111) session_unserialize_callback() and session_unserialize_load_all_classes()
16
16
 * are leftovers from when we had "load_class()" but pretty much do nothing and
17
17
 * need to be totally pulled out. I'm too lazy to do it right now though, so it's
18
18
 * another todo to do :)
19
 
 *
20
19
 * @author {@link http://wonderwinds.com/ Ed Bennett}
21
20
 * @author {@link http://daniel.hahler.de/ Daniel HAHLER}
22
21
 * @author {@link http://fplanque.net/ Francois PLANQUE}
 
22
 * @author {@link http://www.mfollett.com/ Matt FOLLETT}
23
23
 * @author {@link http://www.jeffbearer.com/ Jeff BEARER}
24
 
 * @author {@link http://www.mfollett.com/ Matt FOLLETT}
25
24
 * @copyright (c) 2009 by {@link http://quamplures.net/ the Quam Plures project}
26
25
 * @license http://www.gnu.org/licenses/gpl.txt GNU General Public License v3
27
26
 * @package sessions
52
51
        var $user_ID;
53
52
        /**
54
53
         * Is the session validated?
 
54
         *
55
55
         * This means that it was created from a received cookie.
 
56
         *
56
57
         * @var boolean
57
58
         */
58
59
        var $is_validated = false;
60
61
         * Data stored for the session
61
62
         *
62
63
         * This holds an array( expire, value ) for each data item key.
 
64
         *
63
65
         * @var array
64
66
         */
65
67
        var $_data;
72
74
        /**
73
75
         * Constructor
74
76
         *
75
 
         * If valid session cookie received: pull session from DB
76
 
         * Otherwise, INSERT a session into DB
 
77
         * If valid session cookie received: pull session from DB Otherwise, INSERT a
 
78
         * session into DB
77
79
         */
78
80
        function Session()
79
81
        {
109
111
 
110
112
                                $row = $DB->get_row( '
111
113
                                        SELECT sess_ID, sess_key, sess_data, sess_user_ID
112
 
                                          FROM T_sessions
113
 
                                         WHERE sess_ID  = '.$DB->quote( $session_id_by_cookie ).'
114
 
                                           AND sess_key = '.$DB->quote( $session_key_by_cookie ).'
115
 
                                           AND UNIX_TIMESTAMP(sess_lastseen) > '.( $localtimenow - $Settings->get('timeout_sessions') ) );
 
114
                                        FROM T_sessions
 
115
                                        WHERE sess_ID = '.$DB->quote( $session_id_by_cookie ).'
 
116
                                        AND sess_key = '.$DB->quote( $session_key_by_cookie ).'
 
117
                                        AND UNIX_TIMESTAMP(sess_lastseen) > '.( $localtimenow - $Settings->get('timeout_sessions') ) );
116
118
                                if( empty( $row ) )
117
119
                                {
118
120
                                        // debuglog-add removed
132
134
                                        else
133
135
                                        {
134
136
                                                // Some session data has been previsouly stored
135
 
                                                // Unserialize session data (using an own callback that should provide class definitions):
 
137
                                                // Unserialize session data (using an own callback that should provide class definitions)
136
138
                                                $old_callback = ini_set( 'unserialize_callback_func', 'session_unserialize_callback' );
137
139
                                                if( $old_callback === false || is_null( $old_callback ) /* disabled, reported with PHP 5.2.5 */ )
138
140
                                                {
139
141
                                                        // NULL if ini_set has been disabled for security reasons
140
142
                                                        // Brutally load all classes that we might need:
141
 
                                                        session_unserialize_load_all_classes();
 
143
                                                        session_unserialize_load_all_classes();
142
144
                                                }
143
 
                                                // @todo (0000): dh> This can fail, if there are special chars in sess_data: It will
144
 
                                                // be encoded in $app_charset _after_ "SET NAMES", but get retrieved here, _before_
145
 
                                                // any "SET NAMES" (if $app_db_config['connection_charset'] is not set (default))!
 
145
                                                // @todo (0000) dh> This can fail, if there are special chars in sess_data:
 
146
                                                // It will be encoded in $app_charset _after_ "SET NAMES", but get retrieved
 
147
                                                // here, _before_ any "SET NAMES" (if $app_db_config['connection_charset']
 
148
                                                // is not set (default))!
146
149
                                                $this->_data = @unserialize( $row->sess_data );
147
150
 
148
151
                                                if( $old_callback !== false )
157
160
                                                }
158
161
                                                else
159
162
                                                {
160
 
                                                        // Load a Messages object from session data, if available:
 
163
                                                        // Load a Messages object from session data, if available
161
164
                                                        if( ( $sess_Messages = $this->get( 'Messages' ) ) && is_a( $sess_Messages, 'log' ) )
162
165
                                                        {
163
 
                                                                // dh> TODO: "old" messages should rather get prepended to any existing ones from the current request, rather than appended
 
166
                                                                // @todo (0000) dh> "old" messages should rather get prepended to
 
167
                                                                // any existing ones from the current request, rather than appended
164
168
                                                                $Messages->add_messages( $sess_Messages->messages );
165
169
                                                                $this->delete( 'Messages' );
166
170
                                                        }
192
196
                        $this->ID = $DB->insert_id;
193
197
 
194
198
                        // Set a cookie valid for ~ 10 years:
195
 
                        setcookie( $cookie_session, $this->ID.'_'.$this->key, time()+315360000, $cookie_path, $cookie_domain );
 
199
                        setcookie( $cookie_session, $this->ID.'_'.$this->key, time() + 315360000, $cookie_path, $cookie_domain );
196
200
                }
197
201
        }
198
202
 
199
203
 
200
204
        /**
201
 
         * Attach a User object to the session.
 
205
         * Attach a User object to the session
202
206
         *
203
207
         * @param User The user to attach
204
208
         */
209
213
 
210
214
 
211
215
        /**
212
 
         * Attach a user ID to the session.
 
216
         * Attach a user ID to the session
213
217
         *
214
 
         * NOTE: ID gets saved to DB on shutdown. This may be a "problem" when querying T_sessions for sess_user_ID.
 
218
         * NOTE: ID gets saved to DB on shutdown. This may be a "problem" when querying
 
219
         * T_sessions for sess_user_ID.
215
220
         *
216
221
         * @param integer The ID of the user to attach
217
222
         */
238
243
        /**
239
244
         * Logout the user, by invalidating the session key and unsetting {@link $user_ID}.
240
245
         *
241
 
         * We want to keep the user in the session log, but we're unsetting {@link $user_ID}, which refers
242
 
         * to the current session.
243
 
         *
244
 
         * Because the session key is invalid/broken, on the next request a new session will be started.
 
246
         * We want to keep the user in the session log, but we're unsetting {@link $user_ID},
 
247
         * which refers to the current session. Because the session key is invalid/broken,
 
248
         * on the next request a new session will be started.
245
249
         *
246
250
         * NOTE: we MIGHT want to link subsequent sessions together if we want to keep track...
247
251
         */
253
257
 
254
258
                // Invalidate the session key (no one will be able to use this session again)
255
259
                $this->key = NULL;
256
 
                $this->_data = array(); // We don't need to keep old data
 
260
                // We don't need to keep old data
 
261
                $this->_data = array();
257
262
                $this->_session_needs_save = true;
258
263
                $this->dbsave();
259
264
 
260
 
                $this->user_ID = NULL; // Unset user_ID after invalidating/saving the session above, to keep the user info attached to the old session.
 
265
                // Unset user_ID after invalidating/saving the session above, to keep the user
 
266
                // info attached to the old session.
 
267
                $this->user_ID = NULL;
261
268
 
262
 
                // clean up the session cookie:
 
269
                // clean up the session cookie
263
270
                setcookie( $cookie_session, '', 200000000, $cookie_path, $cookie_domain );
264
271
        }
265
272
 
266
273
 
267
274
        /**
268
 
         * Check if session has a user attached.
 
275
         * Check if session has a user attached
269
276
         *
270
277
         * @return boolean
271
278
         */
276
283
 
277
284
 
278
285
        /**
279
 
         * Get the attached User.
 
286
         * Get the attached User
280
287
         *
281
288
         * @return false|User
282
289
         */
294
301
 
295
302
 
296
303
        /**
297
 
         * Get a data value for the session. This checks for the data to be expired and unsets it then.
 
304
         * Get a data value for the session
 
305
         *
 
306
         * This checks for the data to be expired and unsets it then.
298
307
         *
299
308
         * @param string Name of the data's key.
300
309
         * @param mixed Default value to use if key is not set or has expired. (since 1.10.0)
306
315
 
307
316
                if( isset( $this->_data[$param] ) )
308
317
                {
309
 
                        if( array_key_exists(1, $this->_data[$param]) // can be NULL!
310
 
                          && ( is_null( $this->_data[$param][0] ) || $this->_data[$param][0] > $localtimenow ) ) // check for expired data
 
318
                        if( array_key_exists( 1, $this->_data[$param] ) // can be NULL!
 
319
                                && ( is_null( $this->_data[$param][0] ) || $this->_data[$param][0] > $localtimenow ) ) // check for expired data
311
320
                        {
312
321
                                return $this->_data[$param][1];
313
322
                        }
324
333
 
325
334
 
326
335
        /**
327
 
         * Set a data value for the session.
 
336
         * Set a data value for the session
328
337
         *
329
338
         * Updated values get saved to the DB automatically on shutdown, in {@link shutdown()}.
330
339
         *
356
365
 
357
366
 
358
367
        /**
359
 
         * Delete a value from the session data.
 
368
         * Delete a value from the session data
360
369
         *
361
370
         * @param string Name of the data's key.
362
371
         */
371
380
 
372
381
 
373
382
        /**
374
 
         * Updates session data in database.
 
383
         * Updates session data in database
375
384
         *
376
 
         * NOTE: Debuglog additions will may not be displayed since the debuglog may alreayd have been displayed (shutdown function)
 
385
         * NOTE: Debuglog additions will may not be displayed since the debuglog may already
 
386
         * have been displayed (shutdown function)
377
387
         */
378
388
        function dbsave()
379
389
        {
396
406
                $sess_data = empty( $this->_data ) ? NULL : serialize( $this->_data );
397
407
 
398
408
                // Note: The key actually only needs to be updated on a logout.
399
 
                // Note: we increase the hitcoutn every time. That assumes that there will be no 2 calls for a single hit.
400
 
                //       Anyway it is not a big problem if this number is approximate.
 
409
                // Note: we increase the hitcoutn every time. That assumes that there will be no 2
 
410
                // calls for a single hit. Anyway it is not a big problem if this number is approximate.
401
411
                $sql = "UPDATE T_sessions SET
402
 
                                sess_hitcount = sess_hitcount + 1,
403
 
                                sess_lastseen = '".date( 'Y-m-d H:i:s', $localtimenow )."',
404
 
                                sess_data = ".$DB->quote( $sess_data ).",
405
 
                                sess_ipaddress = '".$Hit->IP."',
406
 
                                sess_key = ".$DB->quote( $this->key );
 
412
                        sess_hitcount = sess_hitcount + 1,
 
413
                        sess_lastseen = '".date( 'Y-m-d H:i:s', $localtimenow )."',
 
414
                        sess_data = ".$DB->quote( $sess_data ).",
 
415
                        sess_ipaddress = '".$Hit->IP."',
 
416
                        sess_key = ".$DB->quote( $this->key );
407
417
                if( ! is_null( $this->user_ID ) )
408
418
                {
409
419
                        // We do NOT erase existing IDs at logout. We only want to set IDs at login
418
428
 
419
429
 
420
430
        /**
421
 
         * Reload session data.
 
431
         * Reload session data
422
432
         *
423
433
         * This is needed if the running process waits for a child process to write data
424
434
         * into the Session, e.g. the captcha plugin in test mode waiting for the Debuglog
435
445
 
436
446
                $sess_data = $DB->get_var( '
437
447
                        SELECT sess_data FROM T_sessions
438
 
                         WHERE sess_ID = '.$this->ID );
 
448
                        WHERE sess_ID = '.$this->ID );
439
449
 
440
450
                $sess_data = @unserialize( $sess_data );
441
451
                if( $sess_data === false )
447
457
                        $this->_data = $sess_data;
448
458
                }
449
459
        }
 
460
 
450
461
}
451
462
 
452
463
 
453
464
/**
454
 
 * This gets used as a {@link unserialize()} callback function, which is
455
 
 * responsible for loading the requested class.
 
465
 * This gets used as a {@link unserialize()} callback function
 
466
 *
 
467
 * This is responsible for loading the requested class.
456
468
 *
457
469
 * IMPORTANT: when modifying this also modify {@link session_unserialize_load_all_classes()}
458
470
 *
463
475
        switch( strtolower( $classname ) )
464
476
        {
465
477
                case 'blog':
466
 
                case 'collectionsettings':
 
478
                case 'blogsettings':
467
479
                case 'comment':
468
480
                case 'item':
469
481
                case 'group':
470
482
                case 'user':
471
483
                return true;
472
484
        }
473
 
 
474
485
        return false;
475
486
}
476
487
 
481
492
 */
482
493
function session_unserialize_load_all_classes()
483
494
{
484
 
        // this used to do a handful of "load_class()" bits that returned true no matter what
485
 
        // haven't yanked this function due to it is used above and I'm lazy right now ;)
 
495
        // this used to do a handful of "load_class()" bits that returned true no matter
 
496
        // what haven't yanked this function due to it is used above and I'm lazy ;)
486
497
}
487
498
 
488
499
?>