SelectRow('SELECT count, unbanDate AS unbanDateIP FROM ?_account_bannedIPs WHERE ip = ? AND type = 0', $_SERVER['REMOTE_ADDR'] ); // explicit " > "; incremented first, checked after self::$bannedIP = $ipBan && $ipBan['count'] > CFG_FAILED_AUTH_COUNT && $ipBan['unbanDateIP'] > time(); $query = !$userId ? null : DB::Aowow()->SelectRow(' SELECT a.id, a.authId, a.user, a.passHash, a.displayName, a.email, a.lastIP, a.lastLogin, a.joindate, a.locale, a.avatar, a.description, a.userGroups, a.userPerms, a.timeout, ab.bannedBy, ab.banReason, ab.isActive, ab.unbanDate FROM ?_account a LEFT JOIN ?_account_banned ab ON a.id = ab.id AND ab.isActive = 1 WHERE a.id = ?d ORDER BY ab.banDate DESC LIMIT 1 ', $userId ); if ($query) { self::$authId = intval($query['authId']); self::$user = $query['user']; self::$passHash = $query['passHash']; self::$email = $query['email']; self::$lastIP = $query['lastIP']; self::$lastLogin = intval($query['lastLogin']); self::$joindate = intval($query['joindate']); self::$localeId = intval($query['locale']); self::$localeString = self::localeString(self::$localeId); self::$timeout = intval($query['timeout']); self::$groups = intval($query['userGroups']); self::$perms = intval($query['userPerms']); self::$banned = $query['isActive'] == 1 && $query['unbanDate'] > time(); self::$unbanDate = intval($query['unbanDate']); self::$bannedBy = intval($query['bannedBy']); self::$banReason = $query['banReason']; self::$displayName = $query['displayName']; self::$avatar = $query['avatar']; self::$description = $query['description']; } else self::setLocale(); } // set and use until further notice public static function setLocale($set = -1) { if ($set != -1) { $loc = isset(Util::$localeStrings[$set]) ? $set : 0; if (self::$id) { DB::Aowow()->query('UPDATE ?_account SET locale = ? WHERE id = ?', $loc, self::$id ); } } else if (isset($_COOKIE[COOKIE_AUTH])) { $loc = intval(substr($_COOKIE[COOKIE_AUTH], 0, 1)); $loc = isset(Util::$localeStrings[$loc]) ? $loc : 0; } else { if (empty($_SERVER["HTTP_ACCEPT_LANGUAGE"])) $loc = 0; else { $loc = strtolower(substr($_SERVER["HTTP_ACCEPT_LANGUAGE"], 0, 2)); switch ($loc) { case 'ru': $loc = 8; break; case 'es': $loc = 6; break; case 'de': $loc = 3; break; case 'fr': $loc = 2; break; default: $loc = 0; } } } // set self::$localeId = $loc; self::$localeString = self::localeString($loc); Lang::load(self::$localeString); } // only use this once public static function useLocale($use) { self::$localeId = isset(Util::$localeStrings[$use]) ? $use : 0; self::$localeString = self::localeString(self::$localeId); } public static function isInGroup($group) { return (self::$groups & $group) != 0; } public static function Auth($pass = '') { if (self::$bannedIP) return AUTH_IPBANNED; if (!$pass) // pass not set, check against cookie { $offset = intVal($_COOKIE[COOKIE_AUTH][1]) + 2; // value of second char in string + 1 for locale $cookiePass = base64_decode(substr($_COOKIE[COOKIE_AUTH], $offset)); if ($cookiePass != self::$passHash) return AUTH_WRONGPASS; // "stay logged in" unchecked; kill session in time() + 5min // if (self::$timeout > 0 && self::$timeout < time()) // return AUTH_TIMEDOUT; if (self::$timeout > 0) DB::Aowow()->query('UPDATE ?_account SET timeout = ?d WHERE id = ?d', time() + CFG_SESSION_TIMEOUT_DELAY, self::$id ); } else { if (self::$passHash[0] == '$') // salted hash -> aowow-password { if (!self::verifyCrypt($pass)) return AUTH_WRONGPASS; } else // assume sha1 hash; account got copied from wow database { if (self::verifySHA1($pass)) self::convertAuthInfo($pass); // drop sha1 and generate with crypt else return AUTH_WRONGPASS; } } if (self::$banned) return AUTH_BANNED; return AUTH_OK; } private static function localeString($loc = -1) { if (!isset(Util::$localeStrings[$loc])) $loc = 0; return Util::$localeStrings[$loc]; } private static function createSalt() { static $seed = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; $algo = '$2a'; $strength = '$09'; $salt = '$'; for ($i = 0; $i < 22; $i++) $salt .= substr($seed, mt_rand(0, 63), 1); return $algo.$strength.$salt; } private static function hashCrypt($pass) { return crypt($pass, self::createSalt()); } private static function hashSHA1($pass) { return sha1(strtoupper(self::$user).':'.strtoupper($pass)); } private static function verifyCrypt($pass) { return self::$passHash == crypt($pass, self::$passHash); } private static function verifySHA1($pass) { return self::$passHash == self::hashSHA1($pass); } private static function convertAuthInfo($pass) { self::$passHash = self::hashCrypt($pass); DB::Aowow()->query('UPDATE ?_account SET passHash = ? WHERE id = ?d', self::$passHash, self::$id ); } public static function getUserGlobals() { $set = array( 'commentban' => false, // enforce this for now 'ratingban' => false, // enforce this for now 'id' => self::$id, 'name' => self::$displayName ? self::$displayName : '', 'roles' => self::$groups ? self::$groups : 0, 'permissions' => self::$perms ? self::$perms : 0, 'cookies' => [] ); if (!self::$id) return $set; if ($_ = self::getCharacters()) $subSet['characters'] = $_; if ($_ = self::getProfiles()) $subSet['profiles'] = $_; if ($_ = self::getWeightScales()) $subSet['weightscales'] = $_; if ($_ = self::getCookies()) $subSet['cookies'] = $_; return array_merge($set, $subSet); } public static function getWeightScales() { $data = []; $res = DB::Aowow()->select('SELECT * FROM ?_account_weightscales WHERE account = ?d', self::$id); foreach ($res as $i) { $set = array ( 'name' => $i['name'], 'id' => $i['id'] ); $weights = explode(',', $i['weights']); foreach ($weights as $weight) { $w = explode(':', $weight); if ($w[1] === 'undefined') $w[1] = 0; $set[$w[0]] = $w[1]; } $data[] = $set; } return $data; } public static function getCharacters($asJSON = true) { if (empty(self::$characters)) { // todo: do after profiler @include('datasets/ProfilerExampleChar'); // existing chars on realm(s) self::$characters = array( array( 'name' => $character['name'], 'realmname' => $character['realm'][1], 'region' => $character['region'][0], 'realm' => $character['realm'][0], 'race' => $character['race'], 'classs' => $character['classs'], 'level' => $character['level'], 'gender' => $character['gender'], 'pinned' => $character['pinned'] ) ); } return self::$characters; } public static function getProfiles($asJSON = true) { if (empty(self::$profiles)) { // todo => do after profiler // chars build in profiler self::$profiles = array( array('id' => 21, 'name' => 'Example Profile 1', 'race' => 4, 'classs' => 5, 'level' => 72, 'gender' => 1, 'icon' => 'inv_axe_04'), array('id' => 23, 'name' => 'Example Profile 2', 'race' => 11, 'classs' => 3, 'level' => 17, 'gender' => 0) ); } return self::$profiles; } public static function getCookies() { $data = []; if (self::$id) $data = DB::Aowow()->selectCol('SELECT name AS ARRAY_KEY, data FROM ?_account_cookies WHERE userId = ?d', self::$id); return $data; } public static function writeCookie() { $cookie = self::$localeId.count(dechex(self::$id)).dechex(self::$id).base64_encode(self::$passHash); SetCookie(COOKIE_AUTH, $cookie, time() + YEAR); } public static function destroy() { $cookie = self::$localeId.'10'; // id = 0, length of this is 1, empty base64_encode is 0 SetCookie(COOKIE_AUTH, $cookie, time() + YEAR); self::$id = 0; self::$displayName = ''; self::$perms = 0; self::$groups = 0; self::$characters = NULL; self::$profiles = NULL; } } ?>