1<?php 2/** 3 * Authentication Plugin for authphpbb3. 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Eole <eole.dev@outlook.com> 7 */ 8 9if (!defined('DOKU_INC')) { 10 die(); 11} 12 13/** 14 * phpBB 3.x Authentication class. 15 */ 16class auth_plugin_authphpbb3 extends DokuWiki_Auth_Plugin { 17 // @var object phpBB database connection. 18 protected $_phpbb_db_link = null; 19 // @var array phpBB configuration (cached). 20 protected $_phpbb_conf = array( 21 // @var string phpBB root path. 22 'root_path' => '', 23 // @var string phpBB URL. 24 'url' => '', 25 // @var string php extension. 26 'phpEx' => '', 27 // @var string phpBB database's driver to use. 28 'dbms' => '', 29 // @var string phpBB database's host. 30 'dbhost' => '', 31 // @var string phpBB database's port. 32 'dbport' => '', 33 // @var string phpBB database's name. 34 'dbname' => '', 35 // @var string phpBB database's user. 36 'dbuser' => '', 37 // @var string phpBB database's password. 38 'dbpasswd' => '', 39 // @var string phpBB database's table prefix. 40 'table_prefix' => '', 41 // @var string phpBB cookie's name. 42 'cookie_name' => '' 43 ); 44 // @var int phpBB user ID. 45 protected $_phpbb_user_id = 0; 46 // @var int phpBB user session ID. 47 protected $_phpbb_user_session_id = ''; 48 // @var int phpBB user type (0 = normal, 1 = inactive, 2 = bot, 3 = founder). 49 protected $_phpbb_user_type = 0; 50 // @var string phpBB user name. 51 protected $_phpbb_username = ''; 52 // @var string phpBB user mail. 53 protected $_phpbb_user_email = ''; 54 // @var array phpBB user's groups. 55 protected $_phpbb_groups = array(); 56 // @var long phpBB user session time. 57 protected $_phpbb_sessiontime = 0; 58 // @var cache DokuWiki cache object. 59 protected $_cache = null; 60 // @var int Cache duration. 61 protected $_cache_duration = 0; 62 // @var int Cache extension file name. 63 protected $_cache_ext_name = '.phpbb3cache'; 64 // @var int Cache unit constant (in seconds). 65 CONST CACHE_DURATION_UNIT = 86400; /* 60 * 60 * 24 = 1 day */ 66 67 /** 68 * Constructor. 69 */ 70 public function __construct() { 71 if (method_exists(get_parent_class($this), '__construct')) { 72 parent::__construct(); 73 } 74 // Set capabilities accordingly. 75 $this->cando['addUser'] = false; // Can Users be created? 76 $this->cando['delUser'] = false; // Can Users be deleted? 77 $this->cando['modLogin'] = false; // Can login names be changed? 78 $this->cando['modPass'] = false; // Can passwords be changed? 79 $this->cando['modName'] = false; // Can real names be changed? 80 $this->cando['modMail'] = false; // Can emails be changed? 81 $this->cando['modGroups'] = false; // Can groups be changed? 82 $this->cando['getUsers'] = true; // Can a (filtered) list of users be retrieved? 83 $this->cando['getUserCount']= true; // Can the number of users be retrieved? 84 $this->cando['getGroups'] = true; // Can a list of available groups be retrieved? 85 $this->cando['external'] = true; // Does the module do external auth checking? 86 $this->cando['logout'] = true; // Can the user logout again? 87 // Check database connection requirement. 88 if (!class_exists('PDO')) { 89 $this->dbglog('PDO extension for PHP not found.'); 90 $this->success = false; 91 } else { 92 // Load plugin configuration. 93 $this->success = $this->load_configuration(); 94 } 95 if (!$this->success) { 96 msg($this->getLang('config_error'), -1); 97 } 98 } 99 100 /** 101 * Destructor. 102 */ 103 public function __destruct() { 104 $this->phpbb_disconnect(); 105 $this->_cache = null; 106 if (method_exists(get_parent_class($this), '__destruct')) { 107 parent::__destruct(); 108 } 109 } 110 111 /** 112 * Writes debug informations. 113 * 114 * @param string $msg Message to write. 115 */ 116 public function dbglog($msg) { 117 $class_name = @get_class($this); 118 119 if ($class_name !== false) { 120 $msg = $class_name . ': ' . $msg; 121 } 122 dbglog($msg); 123 } 124 125 /** 126 * Sanitizes a given username. 127 * 128 * @param string $username Username to clean. 129 * @return string Clean username. 130 */ 131 public function clean_username($username) { 132 $username = preg_replace('#(?:[\x00-\x1F\x7F]+|(?:\xC2[\x80-\x9F])+)#', '', $username); 133 $username = preg_replace('# {2,}#', ' ', $username); 134 $username = trim($username); 135 return strtolower($username); 136 } 137 138 /** 139 * Gets phpBB URL. 140 * 141 * @return string|false phpBB URL if success, false otherwise. 142 */ 143 public function get_phpbb_url() { 144 if (!empty($this->_phpbb_conf['url'])) { 145 return $this->_phpbb_conf['url']; 146 } 147 if ($this->use_phpbb_cache()) { 148 $result = unserialize($this->_cache->retrieveCache(false)); 149 if (is_array($result) && array_key_exists('url', $result)) { 150 $this->_phpbb_conf['url'] = $result['url']; 151 } 152 } 153 if (!empty($this->_phpbb_conf['url'])) { 154 return $this->_phpbb_conf['url']; 155 } 156 if (!$this->phpbb_connect()) { 157 return false; 158 } 159 $query = "SELECT config_name, config_value 160 FROM {$this->_phpbb_conf['table_prefix']}config 161 WHERE config_name IN ('server_protocol', 'server_name', 'script_path', 'server_port')"; 162 $result = $this->_phpbb_sql_link->prepare($query); 163 if ($result === false) { 164 $this->dbglog('error while preparing query for phpBB URL'); 165 return false; 166 } 167 if ($result->execute() === false) { 168 $this->dbglog('error while executing query for phpBB URL'); 169 return false; 170 } 171 $server_protocol = ''; 172 $server_name = ''; 173 $script_path = ''; 174 $server_port = ''; 175 while ($row = $result->fetch(PDO::FETCH_ASSOC)) { 176 switch ($row['config_name']) { 177 case 'server_protocol': 178 $server_protocol = strtolower(trim($row['config_value'])); 179 break; 180 case 'server_name': 181 $server_name = rtrim(trim($row['config_value']), '/'); 182 break; 183 case 'script_path': 184 $script_path = trim($row['config_value']); 185 break; 186 case 'server_port': 187 $server_port = intval($row['config_value']); 188 break; 189 default: 190 break; 191 } 192 } 193 if (empty($server_port)) { 194 $server_port = '80'; 195 if ($server_protocol === 'https://') { 196 $server_port = '443'; 197 } 198 } 199 $server_name = rtrim($server_protocol . $server_name . ':' . $server_port . $script_path, '/'); 200 $this->_phpbb_conf['url'] = $server_name; 201 $result->closeCursor(); 202 $result = null; 203 return $this->_phpbb_conf['url']; 204 } 205 206 /** 207 * Authenticates the user. Called on every page loaded. 208 * 209 * @param string $user Case sensitive user name. 210 * @param string $pass Plain text password for the user. 211 * @param boolean $sticky Remember login? 212 * @return boolean True for match, false for everything else. 213 */ 214 public function trustExternal($user, $pass, $sticky = false) { 215 global $USERINFO; 216 $b = false; 217 218 $this->_phpbb_username = ''; 219 $this->_phpbb_user_email = ''; 220 $this->_phpbb_user_session_id = ''; 221 if (empty($user)) { 222 $b = $this->do_login_cookie(); 223 } 224 if (!$b || 225 empty($this->_phpbb_username) || 226 empty($this->_phpbb_user_email)) { 227 return false; 228 } 229 $USERINFO['name'] = utf8_encode($this->_phpbb_username); 230 $USERINFO['mail'] = $this->_phpbb_user_email; 231 $USERINFO['grps'] = $this->_phpbb_groups; 232 $_SERVER['REMOTE_USER'] = $USERINFO['name']; 233 $_SESSION[DOKU_COOKIE]['auth']['user'] = $USERINFO['name']; 234 $_SESSION[DOKU_COOKIE]['auth']['info'] = $USERINFO; 235 return true; 236 } 237 238 /** 239 * Fetchs user details from phpBB. 240 * 241 * @param string $user Case sensitive username. 242 * @param boolean $requireGroups Whether or not the returned data must include groups. 243 * @return array/boolean False for error conditions and an array for success. 244 * array['name'] string User's name. 245 * array['username'] string User's name. 246 * array['mail'] string User's email address. 247 * array['phpbb_user_id'] string User's ID. 248 * array['phpbb_profile'] string User's link to profile. 249 * array['grps'] array Group names the user belongs to. 250 */ 251 public function getUserData($user, $requireGroups = true) { 252 if (empty($user)) { 253 return false; 254 } 255 $this->_cache_duration = intval($this->getConf('phpbb_cache')); 256 $depends = array('age' => self::CACHE_DURATION_UNIT * $this->_cache_duration); 257 $cache = new cache('authphpbb3_getUserData_' . $user, $this->_cache_ext_name); 258 $user_data = false; 259 260 if (($this->_cache_duration > 0) && $cache->useCache($depends)) { 261 $user_data = unserialize($cache->retrieveCache(false)); 262 } else { 263 $cache->removeCache(); 264 if (!$this->phpbb_connect()) { 265 return false; 266 } 267 $query = "SELECT user_id, username, username_clean, user_email, user_type 268 FROM {$this->_phpbb_conf['table_prefix']}users 269 WHERE username_clean = ?"; 270 $result = $this->_phpbb_sql_link->prepare($query); 271 if ($result === false) { 272 $this->dbglog('error while preparing query for user data'); 273 return false; 274 } 275 if (!$result->execute(array($this->clean_username($user)))) { 276 $this->dbglog('error while executing query for user data'); 277 return false; 278 } 279 $row = $result->fetch(PDO::FETCH_ASSOC); 280 $this->_phpbb_user_type = (int)$row['user_type']; 281 $this->_phpbb_user_id = (int)$row['user_id']; 282 $this->_phpbb_username = $row['username']; 283 $this->_phpbb_user_email = $row['user_email']; 284 $result->closeCursor(); 285 $result = null; 286 $this->get_phpbb_user_groups(); 287 $this->get_phpbb_url(); 288 $user_data = array( 289 'name' => $this->_phpbb_username, 290 'username' => $this->_phpbb_username, 291 'mail' => $this->_phpbb_user_email, 292 'phpbb_user_id' => $this->_phpbb_user_id, 293 'phpbb_profile' => $this->_phpbb_conf['url'] . '/memberlist.php?mode=viewprofile&u=' . 294 $this->_phpbb_user_id, 295 'grps' => $this->_phpbb_groups 296 ); 297 $cache->storeCache(serialize($user_data)); 298 } 299 $cache = null; 300 return $user_data; 301 } 302 303 /** 304 * Bulk retrieval of users' data (does not use cache system). 305 * 306 * @param int $start Index of first user to be returned. 307 * @param int $limit Maximum number of users to be returned. 308 * @param array $filter Array of field/pattern pairs. 309 * @return array/boolean List of arrays returned by getUserData function. 310 */ 311 public function retrieveUsers($start = 0, $limit = 0, $filter = array()) { 312 if (!$this->phpbb_connect()) { 313 return false; 314 } 315 $start = intval($start); 316 if ($start < 0) { 317 $start = 0; 318 } 319 $limit = intval($limit); 320 if ($limit <= 0) { 321 // Arbitrary limit. 322 $limit = 10000; 323 } 324 if (is_null($filter)) { 325 $filter = array(); 326 } 327 if (isset($filter['grps'])) { 328 $filter['group'] = $filter['grps']; 329 } 330 foreach (array('user', 'name', 'mail') as $key) { 331 $tmp = '%'; 332 if (isset($filter[$key])) { 333 $tmp = str_replace('%', '', $filter[$key]); 334 if (!is_string($tmp)) { 335 $tmp = ''; 336 } 337 if (empty($tmp)) { 338 $tmp = '%'; 339 } else { 340 $tmp = '%' . $tmp . '%'; 341 } 342 } 343 $filter[$key] = $tmp; 344 } 345 $filter['start'] = (int)$start; 346 $filter['end'] = (int)($start + $limit); 347 $filter['limit'] = (int)$limit; 348 // Gets users. 349 $query = "SELECT user_id, username, username_clean, user_email 350 FROM {$this->_phpbb_conf['table_prefix']}users 351 WHERE (username like :name OR username like :user OR 352 username_clean like :nameclean OR username_clean like :userclean) AND 353 user_email like :mail 354 LIMIT :limit OFFSET :start"; 355 $result = $this->_phpbb_sql_link->prepare($query); 356 if ($result === false) { 357 $this->dbglog('error while preparing query for users data'); 358 return false; 359 } 360 $result->bindValue(':name', $filter['name'], PDO::PARAM_STR); 361 $result->bindValue(':user', $filter['user'], PDO::PARAM_STR); 362 $result->bindValue(':nameclean', $filter['name'], PDO::PARAM_STR); 363 $result->bindValue(':userclean', $filter['user'], PDO::PARAM_STR); 364 $result->bindValue(':mail', $filter['mail'], PDO::PARAM_STR); 365 $result->bindValue(':limit', (int)$filter['limit'], PDO::PARAM_INT); 366 $result->bindValue(':start', (int)$filter['start'], PDO::PARAM_INT); 367 if (!$result->execute()) { 368 $this->dbglog('error while executing query for users data'); 369 return false; 370 } 371 $users = array(); 372 // Gets users' groups. 373 while ($row = $result->fetch(PDO::FETCH_ASSOC)) { 374 $user_data = array( 375 'name' => $row['username'], 376 'username' => $row['username_clean'], 377 'mail' => $row['user_email'], 378 'phpbb_user_id' => $row['user_id'], 379 'phpbb_profile' => $this->_phpbb_conf['url'] . '/memberlist.php?mode=viewprofile&u=' . 380 $row['user_id'], 381 'grps' => array() 382 ); 383 $query = "SELECT * 384 FROM {$this->_phpbb_conf['table_prefix']}groups g, 385 {$this->_phpbb_conf['table_prefix']}users u, 386 {$this->_phpbb_conf['table_prefix']}user_group ug 387 WHERE u.user_id = ug.user_id AND g.group_id = ug.group_id AND u.user_id = ?"; 388 $resgrp = $this->_phpbb_sql_link->prepare($query); 389 if (($resgrp === false) || !$resgrp->execute(array($row['user_id']))) { 390 $this->dbglog('error while executing query for ' . $row['user_id'] . ' groups'); 391 // If no group filter, we still add the user to the list. 392 if (!isset($filter['group'])) { 393 $users[$user_data['username']] = $user_data; 394 } 395 $resgrp->closeCursor(); 396 $resgrp = null; 397 continue; 398 } 399 $ingroup = false; 400 while ($rowgrp = $resgrp->fetch(PDO::FETCH_ASSOC)) { 401 $user_data['grps'][] = $rowgrp['group_name']; 402 if (!$ingroup && 403 isset($filter['group']) && 404 (strpos($rowgrp['group_name'], $filter['group']) !== false)) { 405 $ingroup = true; 406 } 407 } 408 // Apply group's filter. 409 if (!isset($filter['group']) || (isset($filter['group']) && $ingroup)) { 410 $users[$user_data['username']] = $user_data; 411 } 412 $resgrp->closeCursor(); 413 $resgrp = null; 414 } 415 $result->closeCursor(); 416 $result = null; 417 return $users; 418 } 419 420 /** 421 * Bulk retrieval of groups (does not use cache system). 422 * 423 * @param int $start Index of first group to be returned. 424 * @param int $limit Maximum number of groups to be returned. 425 * @return array/boolean List of groups. 426 */ 427 public function retrieveGroups($start = 0, $limit = 0) { 428 if (!$this->phpbb_connect()) { 429 return false; 430 } 431 $start = intval($start); 432 if ($start < 0) { 433 $start = 0; 434 } 435 $limit = intval($limit); 436 if ($limit <= 0) { 437 // Arbitrary limit. 438 $limit = 10000; 439 } 440 $query = "SELECT * 441 FROM {$this->_phpbb_conf['table_prefix']}groups 442 LIMIT :limit OFFSET :start"; 443 $result = $this->_phpbb_sql_link->prepare($query); 444 if ($result === false) { 445 $this->dbglog('error while preparing query for groups data'); 446 return false; 447 } 448 $result->bindValue(':limit', (int)$limit, PDO::PARAM_INT); 449 $result->bindValue(':start', (int)$start, PDO::PARAM_INT); 450 if (!$result->execute()) { 451 $this->dbglog('error while executing query for groups data'); 452 return false; 453 } 454 $groups = array(); 455 while ($row = $result->fetch(PDO::FETCH_ASSOC)) { 456 if (isset($row['group_name']) && !empty($row['group_name'])) { 457 $groups[$row['group_name']] = $row; 458 } 459 } 460 $result->closeCursor(); 461 $result = null; 462 ksort($groups); 463 return $groups; 464 } 465 466 /** 467 * Returns the number of users which meet $filter criteria (does not use cache system). 468 * 469 * @param array $filter Array of field/pattern pairs, empty array for no filter. 470 * @return int Number of users matching criteria. 471 */ 472 public function getUserCount($filter = array()) { 473 $users = $this->retrieveUsers(0, 0, $filter); 474 475 if ($users === false) { 476 return 0; 477 } 478 return count($users); 479 } 480 481 /** 482 * Logs off the user. 483 */ 484 public function logOff() { 485 if (method_exists(get_parent_class($this), 'logOff')) { 486 parent::logOff(); 487 } 488 if (empty($this->_phpbb_user_session_id)) { 489 $this->get_phpbb_cookie_name(); 490 if (empty($this->_phpbb_conf['cookie_name'])) { 491 return ; 492 } 493 $phpbb_cookie_sid_name = $this->_phpbb_conf['cookie_name'] . '_sid'; 494 if (array_key_exists($phpbb_cookie_sid_name, $_COOKIE)) { 495 $this->_phpbb_user_session_id = $_COOKIE[$phpbb_cookie_sid_name]; 496 } 497 } 498 if (!empty($this->_phpbb_user_session_id) && 499 ($this->get_phpbb_url() !== false) && 500 $this->_phpbb_user_id) { 501 //global $ID; 502 503 $url = $this->_phpbb_conf['url'] . '/ucp.php?mode=logout&sid=' . $this->_phpbb_user_session_id; 504 // phpBB doesn't natively support the logout redirection yet. 505 //$url .= '&redirect=' . urlencode(wl($ID, '', true)); 506 send_redirect($url); 507 } 508 } 509 510 /** 511 * Loads the plugin's configuration. 512 * 513 * @return boolean True on success, false otherwise. 514 */ 515 private function load_configuration() { 516 if ($this->use_phpbb_cache()) { 517 $this->_phpbb_conf = unserialize($this->_cache->retrieveCache(false)); 518 } else { 519 $this->_cache->removeCache(); 520 $this->_phpbb_conf['root_path'] = DOKU_INC . rtrim(trim($this->getConf('phpbb_root_path')), '/') . '/'; 521 $this->_phpbb_conf['phpEx'] = substr(strrchr(__FILE__, '.'), 1); 522 if (!@file_exists($this->_phpbb_conf['root_path'] . 'config.' . $this->_phpbb_conf['phpEx'])) { 523 $this->dbglog('phpBB installation not found'); 524 return false; 525 } 526 include($this->_phpbb_conf['root_path'] . 'config.' . $this->_phpbb_conf['phpEx']); 527 $this->_phpbb_conf['dbms'] = $dbms; 528 $this->_phpbb_conf['dbhost'] = empty($dbhost) ? '127.0.0.1' : $dbhost; 529 $this->_phpbb_conf['dbport'] = $dbport; 530 $this->_phpbb_conf['dbname'] = $dbname; 531 $this->_phpbb_conf['dbuser'] = $dbuser; 532 $this->_phpbb_conf['dbpasswd'] = $dbpasswd; 533 $this->_phpbb_conf['table_prefix'] = $table_prefix; 534 foreach (array('dbms', 'dbhost', 'dbname', 'dbuser') as $member) { 535 if (empty($this->_phpbb_conf[$member])) { 536 $this->dbglog("phpBB config variable {$member} not set"); 537 return false; 538 } 539 } 540 if ($this->get_phpbb_url() === false) { 541 $this->dbglog('cannot get phpBB URL'); 542 return false; 543 } 544 if (!$this->get_phpbb_cookie_name()) { 545 $this->dbglog('cannot get phpBB cookie name'); 546 return false; 547 } 548 $this->_cache->storeCache(serialize($this->_phpbb_conf)); 549 } 550 return (!empty($this->_phpbb_conf['url']) && 551 !empty($this->_phpbb_conf['cookie_name'])); 552 } 553 554 /** 555 * Gets the phpBB configuration cache. 556 * 557 * @return object Cache of the phpBB configuration. 558 */ 559 private function get_phpbb_cache() { 560 if ($this->_cache === null) { 561 $this->_cache = new cache('authphpbb3', $this->_cache_ext_name); 562 } 563 return $this->_cache; 564 } 565 566 /** 567 * Can use the phpBB configuration cache. 568 * 569 * @return object Cache of the phpBB configuration. 570 */ 571 private function use_phpbb_cache() { 572 $depends = array(); 573 574 $this->get_phpbb_cache(); 575 $this->_cache_duration = intval($this->getConf('phpbb_cache')); 576 if ($this->_cache_duration > 0) { 577 $depends['age'] = self::CACHE_DURATION_UNIT * $this->_cache_duration; 578 } else { 579 $depends['purge'] = true; 580 } 581 return $this->_cache->useCache($depends); 582 } 583 584 /** 585 * Connects to phpBB database. 586 * 587 * @return boolean True on success, false otherwise. 588 */ 589 private function phpbb_connect() { 590 if (!$this->_phpbb_db_link) { 591 $host = strtolower(end(explode('\\', $this->_phpbb_conf['dbms']))); 592 $port = ''; 593 $dsn = ''; 594 595 if (!empty($this->_phpbb_conf['dbport'])) { 596 $port = ';port=' . intval($this->_phpbb_conf['dbport']); 597 } 598 $dsn = ':host=' . $this->_phpbb_conf['dbhost'] . $port . 599 ';dbname=' . $this->_phpbb_conf['dbname']; 600 try { 601 switch ($host) { 602 case 'mysql': 603 case 'mysqli': 604 $dsn = 'mysql' . $dsn . ';charset=utf8'; 605 $this->_phpbb_sql_link = new PDO( 606 $dsn, 607 $this->_phpbb_conf['dbuser'], 608 $this->_phpbb_conf['dbpasswd']); 609 break; 610 case 'postgres': 611 $dsn = 'pgsql' . $dsn . 612 ';user=' . $this->_phpbb_conf['dbuser'] . 613 ';password=' . $this->_phpbb_conf['dbpasswd']; 614 $this->_phpbb_sql_link = new PDO($dsn); 615 $this->_phpbb_sql_link->exec("SET NAMES 'UTF8'"); 616 break; 617 case 'oracle': 618 $dsn = 'oci' . $dsn . ';charset=utf8'; 619 $this->_phpbb_sql_link = new PDO( 620 $dsn, 621 $this->_phpbb_conf['dbuser'], 622 $this->_phpbb_conf['dbpasswd']); 623 break; 624 case 'sqlite': 625 case 'sqlite3': 626 if ($host === 'sqlite') { 627 // SQLite 2 prefix. 628 $host = 'sqlite2'; 629 } else { 630 // SQLite 3 prefix. 631 $host = 'sqlite'; 632 } 633 $dsn = $host . ':' . $this->_phpbb_conf['root_path'] . $this->_phpbb_conf['dbhost']; 634 $this->_phpbb_sql_link = new PDO($dsn); 635 break; 636 default: 637 msg($this->getLang('database_support'), -1); 638 return false; 639 } 640 } catch (PDOException $e) { 641 $this->dbglog('cannot connect to database server (' . $e->getMessage() .')'); 642 msg($this->getLang('database_error'), -1); 643 $this->_phpbb_db_link = null; 644 return false; 645 } 646 } 647 return true; 648 } 649 650 /** 651 * Disconnects from phpBB database. 652 */ 653 private function phpbb_disconnect() { 654 if ($this->_phpbb_db_link !== null) { 655 $this->_phpbb_db_link = null; 656 } 657 } 658 659 /** 660 * Gets phpBB cookie's name. 661 * 662 * @return boolean True for success, false otherwise. 663 */ 664 private function get_phpbb_cookie_name() { 665 if (!empty($this->_phpbb_conf['cookie_name'])) { 666 return true; 667 } 668 if ($this->use_phpbb_cache()) { 669 $result = unserialize($this->_cache->retrieveCache(false)); 670 if (is_array($result) && array_key_exists('cookie_name', $result)) { 671 $this->_phpbb_conf['cookie_name'] = $result['cookie_name']; 672 } 673 } 674 if (!empty($this->_phpbb_conf['cookie_name'])) { 675 return true; 676 } 677 if (!$this->phpbb_connect()) { 678 return false; 679 } 680 // Query for cookie_name. 681 $query = "SELECT config_name, config_value 682 FROM {$this->_phpbb_conf['table_prefix']}config 683 WHERE config_name = 'cookie_name'"; 684 $result = $this->_phpbb_sql_link->prepare($query); 685 if ($result === false) { 686 $this->dbglog('error while preparing query for cookie.'); 687 return false; 688 } 689 if (!$result->execute()) { 690 $this->dbglog('error while executing query for cookie.'); 691 return false; 692 } 693 $row = $result->fetch(PDO::FETCH_ASSOC); 694 $this->_phpbb_conf['cookie_name'] = $row['config_value']; 695 $result->closeCursor(); 696 $result = null; 697 return true; 698 } 699 700 /** 701 * Gets phpBB user's groups. 702 * 703 * @return boolean True for success, false otherwise. 704 */ 705 private function get_phpbb_user_groups() { 706 $this->_phpbb_groups = array(); 707 $this->_phpbb_user_id = filter_var($this->_phpbb_user_id, FILTER_VALIDATE_INT); 708 if (!$this->_phpbb_user_id) { 709 return false; 710 } 711 if (!$this->phpbb_connect()) { 712 return false; 713 } 714 $query = "SELECT * 715 FROM {$this->_phpbb_conf['table_prefix']}groups g, 716 {$this->_phpbb_conf['table_prefix']}users u, 717 {$this->_phpbb_conf['table_prefix']}user_group ug 718 WHERE u.user_id = ug.user_id AND g.group_id = ug.group_id AND u.user_id = ?"; 719 $result = $this->_phpbb_sql_link->prepare($query); 720 if ($result === false) { 721 $this->dbglog('error while preparing query for user\'s groups'); 722 return false; 723 } 724 if (!$result->execute(array($this->_phpbb_user_id))) { 725 $this->dbglog('error while executing query for user\'s groups'); 726 return false; 727 } 728 while ($row = $result->fetch(PDO::FETCH_ASSOC)) { 729 $this->_phpbb_groups[] = $row['group_name']; 730 } 731 // If the user is a founder. 732 if ($this->_phpbb_user_type === 3) { 733 $this->_phpbb_groups[] = 'admin'; 734 } 735 $result->closeCursor(); 736 $result = null; 737 return true; 738 } 739 740 /** 741 * Authenticate the user using cookie. Called on every page load. 742 * 743 * @return boolean True for success, false otherwise. 744 */ 745 private function do_login_cookie() { 746 if (!$this->phpbb_connect()) { 747 return false; 748 } 749 if (!$this->get_phpbb_cookie_name()) { 750 return false; 751 } 752 $phpbb_cookie_user_sid = $this->_phpbb_conf['cookie_name'] . '_sid'; 753 $phpbb_cookie_user_id = $this->_phpbb_conf['cookie_name'] . '_u'; 754 $this->_phpbb_user_session_id = 755 array_key_exists($phpbb_cookie_user_sid, $_COOKIE) ? $_COOKIE[$phpbb_cookie_user_sid] : null; 756 $phpbb_cookie_user_id = 757 array_key_exists($phpbb_cookie_user_id, $_COOKIE) ? intval($_COOKIE[$phpbb_cookie_user_id]) : null; 758 if (empty($this->_phpbb_user_session_id) || !ctype_xdigit($this->_phpbb_user_session_id)) { 759 $this->dbglog('invalid SID in user\'s cookie ' . 760 '(SID=' . $phpbb_cookie_user_sid . ', Value=' . $this->_phpbb_user_session_id . ')'); 761 return false; 762 } 763 // Get session data from database. 764 $query = "SELECT session_id, session_user_id 765 FROM {$this->_phpbb_conf['table_prefix']}sessions 766 WHERE session_id = ?"; 767 $result = $this->_phpbb_sql_link->prepare($query); 768 if ($result === false) { 769 $this->dbglog('error while preparing query for session'); 770 return false; 771 } 772 if (!$result->execute(array($this->_phpbb_user_session_id))) { 773 $this->dbglog('error while executing query for session'); 774 return false; 775 } 776 $row = $result->fetch(PDO::FETCH_ASSOC); 777 if ($phpbb_cookie_user_id !== (int)$row['session_user_id']) { 778 $this->dbglog('invalid SID/User ID pair'); 779 $result->closeCursor(); 780 $result = null; 781 return false; 782 } 783 $this->_phpbb_user_id = (int)$row['session_user_id']; 784 $this->_phpbb_sessiontime = $row['session_time']; 785 $result->closeCursor(); 786 $result = null; 787 // Update session time. 788 $current_time = time(); 789 if ($current_time > $this->_phpbb_sessiontime) { 790 $query = "UPDATE {$this->_phpbb_conf['table_prefix']}sessions 791 SET session_time = ? 792 WHERE session_id = ?"; 793 $result = $this->_phpbb_sql_link->prepare($query); 794 if ($result === false) { 795 $this->dbglog('error while preparing query for session update'); 796 return false; 797 } 798 if (!$result->execute(array($current_time, $this->_phpbb_user_session_id))) { 799 $this->dbglog('error while executing query for session update'); 800 } 801 $result = null; 802 } 803 // Check for guest session. 804 if ($this->_phpbb_user_id === 1) { 805 return false; 806 } 807 // Get username from database. 808 $query = "SELECT user_id, username, user_email, user_type 809 FROM {$this->_phpbb_conf['table_prefix']}users 810 WHERE user_id = ?"; 811 $result = $this->_phpbb_sql_link->prepare($query); 812 if ($result === false) { 813 $this->dbglog('error while preparing query for username'); 814 return false; 815 } 816 if (!$result->execute(array($this->_phpbb_user_id))) { 817 $this->dbglog('error while executing query for username'); 818 return false; 819 } 820 $row = $result->fetch(PDO::FETCH_ASSOC); 821 $this->_phpbb_user_type = (int)$row['user_type']; 822 $this->_phpbb_username = $row['username']; 823 $this->_phpbb_user_email = $row['user_email']; 824 $result->closeCursor(); 825 $result = null; 826 // Get user groups from database. 827 $this->get_phpbb_user_groups(); 828 return true; 829 } 830} 831