PageRenderTime 76ms CodeModel.GetById 57ms app.highlight 13ms RepoModel.GetById 1ms app.codeStats 0ms

/phpmyfaq/inc/Session.php

https://github.com/cyrke/phpMyFAQ
PHP | 387 lines | 236 code | 40 blank | 111 comment | 24 complexity | bb2a0340fbba35c33ea3f29dd5b75c1d MD5 | raw file
  1<?php
  2/**
  3 * The main User session class
  4 *
  5 * PHP Version 5.3
  6 *
  7 * This Source Code Form is subject to the terms of the Mozilla Public License,
  8 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
  9 * obtain one at http://mozilla.org/MPL/2.0/.
 10 *
 11 * @category  phpMyFAQ
 12 * @package   PMF_Session
 13 * @author    Thorsten Rinne <thorsten@phpmyfaq.de>
 14 * @copyright 2007-2012 phpMyFAQ Team
 15 * @license   http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
 16 * @link      http://www.phpmyfaq.de
 17 * @since     2007-03-31
 18 */
 19
 20if (!defined('IS_VALID_PHPMYFAQ')) {
 21    exit();
 22}
 23
 24/**
 25 * PMF_Session
 26 *
 27 * @category  phpMyFAQ
 28 * @package   PMF_Session
 29 * @author    Thorsten Rinne <thorsten@phpmyfaq.de>
 30 * @copyright 2007-2012 phpMyFAQ Team
 31 * @license   http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
 32 * @link      http://www.phpmyfaq.de
 33 * @since     2007-03-31
 34 */
 35class PMF_Session
 36{
 37    /**
 38     * Constants
 39     */
 40    const PMF_COOKIE_NAME_REMEMBERME = 'pmf_rememberme';
 41    const PMF_COOKIE_NAME_AUTH = 'pmf_auth';
 42    const PMF_COOKIE_NAME_SESSIONID = 'pmf_sid';
 43
 44    /**
 45     * @var PMF_Configuration
 46     */
 47    private $_config;
 48
 49    /**
 50     * Constructor
 51     *
 52     * @param PMF_Configuration
 53     *
 54     * @return PMF_Session
 55     */
 56    public function __construct(PMF_Configuration $config)
 57    {
 58        $this->_config = $config;
 59    }
 60    
 61    /**
 62     * Tracks the user and log what he did
 63     *
 64     * @param  string  $action Action string
 65     * @param  integer $id     Current ID
 66     *
 67     * @return void
 68     */
 69    public function userTracking($action, $id = 0)
 70    {
 71        global $sid, $user, $botBlacklist;
 72
 73        if ($this->_config->get('main.enableUserTracking')) {
 74
 75            $bots   = 0;
 76            $banned = false;
 77            $agent  = $_SERVER['HTTP_USER_AGENT'];
 78            $sid    = PMF_Filter::filterInput(INPUT_GET, PMF_GET_KEY_NAME_SESSIONID, FILTER_VALIDATE_INT);
 79            $sidc   = PMF_Filter::filterInput(INPUT_COOKIE, self::PMF_COOKIE_NAME_SESSIONID, FILTER_VALIDATE_INT);
 80            
 81            if (!is_null($sidc)) {
 82                $sid = $sidc;
 83            }
 84            if ($action == 'old_session') {
 85                $sid = null;
 86            }
 87
 88            foreach ($botBlacklist as $bot) {
 89                if ((bool)PMF_String::strstr($agent, $bot)) {
 90                    $bots++;
 91                }
 92            }
 93
 94            $network = new PMF_Network($this->_config);
 95
 96            if (!$network->checkIp($_SERVER['REMOTE_ADDR'])) {
 97                $banned = true;
 98            }
 99
100            if (0 == $bots && false == $banned) {
101                if (!isset($sid)) {
102                    $sid = $this->_config->getDb()->nextId(PMF_Db::getTablePrefix() . 'faqsessions', 'sid');
103                    // Sanity check: force the session cookie to contains the current $sid
104                    if (!is_null($sidc) && (!$sidc != $sid)) {
105                        self::setCookie(self::PMF_COOKIE_NAME_SESSIONID, $sid);
106                    }
107
108                    $query = sprintf("
109                        INSERT INTO 
110                            %sfaqsessions
111                        (sid, user_id, ip, time)
112                            VALUES
113                        (%d, %d, '%s', %d)",
114                        PMF_Db::getTablePrefix(),
115                        $sid,
116                        ($user ? $user->getUserId() : -1),
117                        $_SERVER['REMOTE_ADDR'],
118                        $_SERVER['REQUEST_TIME']
119                    );
120                    $this->_config->getDb()->query($query);
121                }
122
123                $data = $sid.';' . 
124                        str_replace(';', ',', $action) . ';' . 
125                        $id . ';' . 
126                        $_SERVER['REMOTE_ADDR'] . ';' . 
127                        str_replace(';', ',', $_SERVER['QUERY_STRING']) . ';' . 
128                        str_replace(';', ',', isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '') . ';' . 
129                        str_replace(';', ',', urldecode($_SERVER['HTTP_USER_AGENT'])) . ';' . 
130                        $_SERVER['REQUEST_TIME'] . ";\n";
131                $file = './data/tracking' . date('dmY');
132                file_put_contents($file, $data, FILE_APPEND);
133            }
134        }
135    }
136
137    /**
138     * Returns the timestamp of a session
139     *
140     * @param  integer $sid Session ID
141     *
142     * @return integer
143     */
144    public function getTimeFromSessionId($sid)
145    {
146        $timestamp = 0;
147
148        $query = sprintf("
149            SELECT
150                time
151            FROM
152                %sfaqsessions
153            WHERE
154                sid = %d",
155            PMF_Db::getTablePrefix(),
156            $sid);
157
158        $result = $this->_config->getDb()->query($query);
159
160        if ($result) {
161        	$res       = $this->_config->getDb()->fetchObject($result);
162        	$timestamp = $res->time;
163        }
164
165        return $timestamp;
166    }
167
168    /**
169     * Returns all session from a date
170     *
171     * @param integer $firstHour First hour
172     * @param integer $lastHour  Last hour
173     *
174     * @return array
175     */
176    public function getSessionsbyDate($firstHour, $lastHour)
177    {
178        $sessions = array();
179
180        $query = sprintf("
181            SELECT
182                sid, ip, time
183            FROM
184                %sfaqsessions
185            WHERE
186                time > %d
187            AND
188                time < %d
189            ORDER BY
190                time",
191            PMF_Db::getTablePrefix(),
192            $firstHour,
193            $lastHour);
194
195        $result = $this->_config->getDb()->query($query);
196        while ($row = $this->_config->getDb()->fetchObject($result)) {
197            $sessions[$row->sid] = array(
198                'ip'   => $row->ip,
199                'time' => $row->time);
200        }
201
202        return $sessions;
203    }
204
205    /**
206     * Returns the number of sessions
207     *
208     * @return integer
209     */
210    public function getNumberOfSessions()
211    {
212        $num = 0;
213
214        $query = sprintf("
215            SELECT
216                sid
217            FROM
218                %sfaqsessions",
219            PMF_Db::getTablePrefix());
220
221        $result = $this->_config->getDb()->query($query);
222        if ($result) {
223            $num = $this->_config->getDb()->numRows($result);
224        }
225
226        return $num;
227    }
228
229    /**
230     * Deletes the sessions for a given timespan
231     *
232     * @param  integer $first Frist session ID
233     * @param  integer $last  Last session ID
234     *
235     * @return boolean
236     */
237    public function deleteSessions($first, $last)
238    {
239        $query = sprintf("
240            DELETE FROM
241                %sfaqsessions
242            WHERE
243                time >= %d
244            AND
245                time <= %d",
246            PMF_Db::getTablePrefix(),
247            $first,
248            $last);
249
250        $this->_config->getDb()->query($query);
251
252        return true;
253    }
254
255    /**
256     * Checks the Session ID
257     *
258     * @param integer $sessionId Session ID
259     * @param string  $ip  IP
260     *
261     * @return void
262     */
263    public function checkSessionId($sessionId, $ip)
264    {
265        global $sid, $user;
266
267        $query = sprintf("
268            SELECT
269                sid
270            FROM
271                %sfaqsessions
272            WHERE
273                sid = %d
274            AND
275                ip = '%s'
276            AND
277                time > %d",
278            PMF_Db::getTablePrefix(),
279            $sessionId,
280            $ip,
281            $_SERVER['REQUEST_TIME'] - 86400
282        );
283        $result = $this->_config->getDb()->query($query);
284
285        if ($this->_config->getDb()->numRows($result) == 0) {
286            $this->userTracking('old_session', $sessionId);
287        } else {
288            // Update global session id
289            $sid = $sessionId;
290            // Update db tracking
291            $query = sprintf("
292                UPDATE
293                    %sfaqsessions
294                SET
295                    time = %d,
296                    user_id = %d
297                WHERE
298                    sid = %d
299                    AND ip = '%s'",
300                PMF_Db::getTablePrefix(),
301                $_SERVER['REQUEST_TIME'],
302                ($user ? $user->getUserId() : '-1'),
303                $sessionId,
304                $ip
305            );
306            $this->_config->getDb()->query($query);
307        }
308    }
309    /**
310     * Returns the number of anonymous users and registered ones.
311     * These are the numbers of unique users who have perfomed
312     * some activities within the last five minutes
313     *
314     * @param  integer $activityTimeWindow Optionally set the time window size in sec. 
315     *                                     Default: 300sec, 5 minutes
316     *
317     * @return array
318     */
319    public function getUsersOnline($activityTimeWindow = 300)
320    {
321        $users = array(0, 0);
322        
323        if ($this->_config->get('main.enableUserTracking')) {
324            $timeNow = ($_SERVER['REQUEST_TIME'] - $activityTimeWindow);
325            // Count all sids within the time window
326            // TODO: add a new field in faqsessions in order to find out only sids of anonymous users
327            $query = sprintf("
328                SELECT
329                    count(sid) AS anonymous_users
330                FROM
331                    %sfaqsessions
332                WHERE
333                    user_id = -1
334                AND 
335                    time > %d",
336                PMF_Db::getTablePrefix(),
337                $timeNow
338            );
339
340            $result = $this->_config->getDb()->query($query);
341            
342            if (isset($result)) {
343                $row      = $this->_config->getDb()->fetchObject($result);
344                $users[0] = $row->anonymous_users;
345            }
346            
347            // Count all faquser records within the time window
348            $query = sprintf("
349                SELECT
350                    count(session_id) AS registered_users
351                FROM
352                    %sfaquser
353                WHERE
354                    session_timestamp > %d",
355                PMF_Db::getTablePrefix(),
356                $timeNow);
357            $result = $this->_config->getDb()->query($query);
358            
359            if (isset($result)) {
360                $row      = $this->_config->getDb()->fetchObject($result);
361                $users[1] = $row->registered_users;
362            }
363        }
364        
365        return $users;
366    }
367
368    /**
369     * Store the Session ID into a persistent cookie expiring
370     * PMF_SESSION_EXPIRED_TIME seconds after the page request.
371     *
372     * @param string  $name      Cookie name
373     * @param integer $sessionId Session ID
374     * @param integer $timeout   Cookie timeout
375     *
376     * @return void
377     */
378    public static function setCookie($name, $sessionId, $timeout = PMF_SESSION_EXPIRED_TIME)
379    {
380        setcookie(
381            $name,
382            $sessionId, 
383            $_SERVER['REQUEST_TIME'] + PMF_SESSION_EXPIRED_TIME,
384            dirname($_SERVER['SCRIPT_NAME'])
385        );
386    }
387}