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