diff --git a/config/extAuth.php.in b/config/extAuth.php.in
new file mode 100644
index 00000000..1181c946
--- /dev/null
+++ b/config/extAuth.php.in
@@ -0,0 +1,19 @@
+
\ No newline at end of file
diff --git a/includes/ajaxHandler.class.php b/includes/ajaxHandler.class.php
index 9ccf40ee..1463d15a 100644
--- a/includes/ajaxHandler.class.php
+++ b/includes/ajaxHandler.class.php
@@ -27,7 +27,7 @@ class AjaxHandler
public function handle($what)
{
$f = 'handle'.ucFirst($what);
- if (!method_exists($this, $f))
+ if (!$what || !method_exists($this, $f))
return null;
return $this->$f();
@@ -139,7 +139,7 @@ class AjaxHandler
break;
}
}
-
+
return $result;
}
@@ -253,9 +253,50 @@ class AjaxHandler
private function handleLocale() // not sure if this should be here..
{
User::setLocale($this->params[0]);
- User::writeCookie();
+ User::save();
+
header('Location: '.(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '.'));
}
+
+ private function handleAccount()
+ {
+ if (!$this->params || !User::$id)
+ return null;
+
+ switch ($this->params[0])
+ {
+ case 'exclude':
+ // profiler completion exclude handler
+ // $this->post['groups'] = bitMask of excludeGroupIds when using .. excludeGroups .. duh
+ // should probably occur in g_user.excludegroups (dont forget to also set g_users.settings = {})
+ return '';
+ case 'weightscales':
+ if (isset($this->post['save']))
+ {
+ if (!isset($this->post['id']))
+ {
+ $res = DB::Aowow()->selectRow('SELECT max(id) as max, count(id) as num FROM ?_account_weightscales WHERE account = ?d', User::$id);
+ if ($res['num'] < 5) // more or less hard-defined in LANG.message_weightscalesaveerror
+ $this->post['id'] = ++$res['max'];
+ else
+ return 0;
+ }
+
+ if (DB::Aowow()->query('REPLACE INTO ?_account_weightscales VALUES (?d, ?d, ?, ?)', intVal($this->post['id']), User::$id, $this->post['name'], $this->post['scale']))
+ return $this->post['id'];
+ else
+ return 0;
+ }
+ else if (isset($this->post['delete']) && isset($this->post['id']))
+ DB::Aowow()->query('DELETE FROM ?_account_weightscales WHERE id = ?d AND account = ?d', intVal($this->post['id']), User::$id);
+ else
+ return 0;
+ }
+
+
+ return null;
+ }
+
}
?>
diff --git a/includes/defines.php b/includes/defines.php
index acb47fb7..ffb1479b 100644
--- a/includes/defines.php
+++ b/includes/defines.php
@@ -43,15 +43,31 @@ define('DB_WORLD', 1);
define('DB_AUTH', 2);
define('DB_CHARACTERS', 3);
+// Account Status
+define('ACC_STATUS_OK', 0); // nothing special
+define('ACC_STATUS_NEW', 1); // just created, awaiting confirmation
+define('ACC_STATUS_RECOVER_USER', 2); // currently recovering username
+define('ACC_STATUS_RECOVER_PASS', 3); // currently recovering password
+
+define('ACC_BAN_NONE', 0x00); // all clear
+define('ACC_BAN_TEMP', 0x01);
+define('ACC_BAN_PERM', 0x02);
+define('ACC_BAN_RATE', 0x04); // cannot rate community items
+define('ACC_BAN_COMMENT', 0x08); // cannot create comments
+define('ACC_BAN_UPLOAD', 0x10); // cannot upload screenshots / suggest videos
+
// Auth Result
define('AUTH_OK', 0);
-define('AUTH_WRONGPASS', 1);
-define('AUTH_TIMEDOUT', 2);
+define('AUTH_WRONGUSER', 1);
+define('AUTH_WRONGPASS', 2);
define('AUTH_BANNED', 3);
define('AUTH_IPBANNED', 4);
+define('AUTH_ACC_INACTIVE', 5);
+define('AUTH_INTERNAL_ERR', 6);
-// Cookie Names
-define('COOKIE_AUTH', 'aw_a');
+define('AUTH_MODE_SELF', 0); // uses ?_accounts
+define('AUTH_MODE_REALM', 1); // uses given realm-table
+define('AUTH_MODE_EXTERNAL', 2); // uses external script
// Times
define('MINUTE', 60);
@@ -74,6 +90,11 @@ define('U_GROUP_BLOGGER', 0x0080);
define('U_GROUP_PREMIUM', 0x0100);
define('U_GROUP_LOCALIZER', 0x0200);
define('U_GROUP_SALESAGENT', 0x0400);
+define('U_GROUP_SCREENSHOT', 0x0800);
+define('U_GROUP_VIDEO', 0x1000);
+// define('U_GROUP_APIONLY, 0x2000); // the heck..?
+// define('U_GROUP_PENDING, 0x4000);
+
define('U_GROUP_STAFF', (U_GROUP_ADMIN|U_GROUP_EDITOR|U_GROUP_MOD|U_GROUP_BUREAU|U_GROUP_DEV|U_GROUP_BLOGGER|U_GROUP_LOCALIZER|U_GROUP_SALESAGENT));
define('U_GROUP_EMPLOYEE', (U_GROUP_ADMIN|U_GROUP_BUREAU|U_GROUP_DEV));
define('U_GROUP_GREEN_TEXT', (U_GROUP_MOD|U_GROUP_BUREAU|U_GROUP_DEV));
diff --git a/includes/kernel.php b/includes/kernel.php
index 7489bacc..c239b332 100644
--- a/includes/kernel.php
+++ b/includes/kernel.php
@@ -8,7 +8,6 @@ ini_set('serialize_precision', 4);
require 'includes/defines.php';
require 'config/config.php';
-require 'includes/genericPage.class.php';
require 'includes/libs/DbSimple/Generic.php'; // Libraray: http://en.dklab.ru/lib/DbSimple (using mysqli variant: https://bitbucket.org/brainreaver/dbsimple/src)
require 'includes/utilities.php'; // misc™ data 'n func
require 'includes/ajaxHandler.class.php'; // handles ajax and jsonp requests
@@ -17,6 +16,7 @@ require 'includes/database.class.php'; // wrap DBSimple
require 'includes/community.class.php'; // handle comments, screenshots and videos
require 'includes/loot.class.php'; // build lv-tabs containing loot-information
require 'localization/lang.class.php';
+require 'pages/genericPage.class.php';
// autoload List-classes, associated filters and pages
@@ -63,10 +63,11 @@ foreach ($AoWoWconf['characters'] as $realm => $charDBInfo)
unset($AoWoWconf); // link set up: delete passwords
+
// load config to constants
$sets = DB::Aowow()->select('SELECT `key` AS ARRAY_KEY, intValue as i, strValue as s FROM ?_config');
foreach ($sets as $k => $v)
- define('CFG_'.strtoupper($k), $v['s'] ? $v['s'] : intVal($v['i']));
+ define('CFG_'.strtoupper($k), $v['s'] ?: intVal($v['i']));
define('STATIC_URL', substr('http://'.$_SERVER['SERVER_NAME'].strtr($_SERVER['SCRIPT_NAME'], ['index.php' => '']), 0, -1).'/static'); // points js to images & scripts (change here if you want to use a separate subdomain)
define('HOST_URL', substr('http://'.$_SERVER['SERVER_NAME'].strtr($_SERVER['SCRIPT_NAME'], ['index.php' => '']), 0, -1)); // points js to executable files
@@ -76,54 +77,25 @@ $e = CFG_DEBUG ? (E_ALL & ~(E_DEPRECATED | E_USER_DEPRECATED | E_STRICT)) : 0;
error_reporting($e);
-// php session (used for profiler: g_dataKey) (todo (high): merge to user-class at some point)
-session_start();
-if (empty($_SESSION['timeout']) || $_SESSION['timeout'] < time())
-{
- $seed = "abcdefghijklmnopqrstuvwxyz0123456789";
- $_SESSION['dataKey'] = ''; // just some random numbers for identifictaion purpose
- for ($i = 0; $i < 40; $i++)
- $_SESSION['dataKey'] .= substr($seed, mt_rand(0, 35), 1);
-}
-$_SESSION['timeout'] = time() + CFG_SESSION_TIMEOUT_DELAY;
-
-
// debug: measure execution times
Util::execTime(CFG_DEBUG);
// Setup Session
-if (isset($_COOKIE[COOKIE_AUTH]))
-{
- $offset = intval($_COOKIE[COOKIE_AUTH][1]);
+ini_set('session.cookie_httponly', true);
+session_cache_limiter('private');
+session_start();
+if (User::init())
+ User::save(); // save user-variables in session
- if ($id = hexdec(substr($_COOKIE[COOKIE_AUTH], 2, $offset)))
- {
- User::init($id);
- switch (User::Auth())
- {
- case AUTH_OK:
- case AUTH_BANNED:
- User::writeCookie();
- break;
- default:
- User::destroy();
- }
- }
- else
- User::init(0);
-}
-else
- User::init(0);
+// all strings attached..
+Lang::load(User::$localeString);
-User::setLocale();
// parse page-parameters .. sanitize before use!
@list($str, $trash) = explode('&', $_SERVER['QUERY_STRING'], 2);
@list($pageCall, $pageParam) = explode('=', $str, 2);
Util::$wowheadLink = 'http://'.Util::$subDomains[User::$localeId].'.wowhead.com/'.$str;
-$ajax = new AjaxHandler($pageParam);
-
?>
diff --git a/includes/types/basetype.class.php b/includes/types/basetype.class.php
index b9a369bd..bf5271cf 100644
--- a/includes/types/basetype.class.php
+++ b/includes/types/basetype.class.php
@@ -320,9 +320,11 @@ abstract class BaseType
public function getRandomId()
{
- // its not optimal, so if anyone has an alternative idea..
+ // ORDER BY RAND() is not optimal, so if anyone has an alternative idea..
+ $where = User::isInGroup(U_GROUP_EMPLOYEE) ? 'WHERE (cuFlags & '.CUSTOM_EXCLUDE_FOR_LISTVIEW.') = 0' : null;
$pattern = '/SELECT .* (-?`?[\w_]*\`?.?`?(id|entry)`?) AS ARRAY_KEY,?.* FROM (\?[\w_-]+) (`?\w*`?)/i';
- $replace = 'SELECT $1 FROM $3 $4 WHERE (cuFlags & '.CUSTOM_EXCLUDE_FOR_LISTVIEW.') = 0 ORDER BY RAND() ASC LIMIT 1';
+ $replace = 'SELECT $1 FROM $3 $4 '.$where.' ORDER BY RAND() ASC LIMIT 1';
+
$query = preg_replace($pattern, $replace, $this->queryBase);
return DB::Aowow()->selectCell($query);
diff --git a/includes/types/item.class.php b/includes/types/item.class.php
index baabc71c..8bb793af 100644
--- a/includes/types/item.class.php
+++ b/includes/types/item.class.php
@@ -655,7 +655,7 @@ class ItemList extends BaseType
{
$gems = DB::Aowow()->select('SELECT i.id AS ARRAY_KEY, i.iconString, ae.*, i.gemColorMask AS colorMask FROM ?_items i JOIN ?_itemenchantment ae ON ae.id = i.gemEnchantmentId WHERE i.id IN (?a)', $enhance['g']);
foreach ($enhance['g'] as $k => $v)
- if (!in_array(array_keys($gems), $v))
+ if (!in_array($v, array_keys($gems)))
unset($enhance['g'][$k]);
}
else
diff --git a/includes/user.class.php b/includes/user.class.php
index c9454f24..5d275610 100644
--- a/includes/user.class.php
+++ b/includes/user.class.php
@@ -3,148 +3,113 @@
if (!defined('AOWOW_REVISION'))
die('illegal access');
-/*
- Cookie-Content
- W X Y [Z] : base64
- Z : passHash length: ? exampleValue: base64_encode('+RQGbSW7Yqyz6fTNAUrI3BE-Zt0FoiMh8ke1_sCmLDwOjgXda9JxH2KcPVu4l5vnp')
- Y : X chars accId as hex length: X exampleValue: 0xF29
- X : [1-9] num chars of Y as int length: 1 exampleValue: 3
- W : locale [0, 2, 3, 6, 8] length: 1 exampleValue: 0
-
- 03F29K1JRR2JTVzdZcXl6NmZUTkFVckkzQkUtWnQwRm9pTWg4a2UxX3NDbUxEd09qZ1hkYTlKeEgyS2NQVnU0bDV2bnA=
-*/
class User
{
- public static $id;
- public static $authId;
- public static $displayName;
- public static $email;
+ public static $id = 0;
+ public static $displayName = '';
+ public static $banStatus = 0x0; // &1: banedIP; &2: banUser; &4: ratingBan; &8: commentBan; &16: disableUpload
+ public static $groups = 0x0;
+ public static $perms = 0;
+ public static $localeId = 0;
+ public static $localeString = 'enus';
- public static $user;
- private static $passHash;
- private static $timeout;
+ private static $dataKey = '';
+ private static $expires = false;
+ private static $passHash = '';
- public static $lastIP;
- public static $lastLogin;
- public static $joindate;
-
- public static $groups;
- public static $perms;
- public static $localeId;
- public static $localeString;
- public static $profiles;
- public static $characters;
- public static $avatar;
- public static $description;
-
- /* public static $ratingBan; */
- /* public static $commentBan; .. jeez.. banflags..? &1: banIP; &2: banUser; &4: disableRating; &8: disableComment; &16: disableUpload ?? */
- public static $bannedIP;
- public static $banned;
- public static $unbanDate;
- public static $bannedBy;
- public static $banReason;
-
- public static function init($userId)
+ public static function init()
{
- self::$id = $userId;
+ self::setLocale();
- $ipBan = DB::Aowow()->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();
+ // session have a dataKey to access the JScripts (yes, also the anons)
+ if (empty($_SESSION['dataKey']))
+ $_SESSION['dataKey'] = Util::createHash(); // just some random numbers for identifictaion purpose
- $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
- );
+ self::$dataKey = $_SESSION['dataKey'];
- if ($query)
+ // check IP bans
+ if ($ipBan = DB::Aowow()->selectRow('SELECT count, unbanDate FROM ?_account_bannedIPs WHERE ip = ? AND type = 0', $_SERVER['REMOTE_ADDR']))
{
- 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'];
+ if ($ipBan['count'] > CFG_FAILED_AUTH_COUNT && $ipBan['unbanDate'] > time())
+ return false;
+ else if ($ipBan['unbanDate'] <= time())
+ DB::Aowow()->query('DELETE FROM ?_account_bannedIPs WHERE ip = ?', $_SERVER['REMOTE_ADDR']);
}
- else
- self::setLocale();
+
+ // try to restore session
+ if (empty($_SESSION['user']))
+ return false;
+
+ // timed out...
+ if (!empty($_SESSION['timeout']) && $_SESSION['timeout'] <= time())
+ return false;
+
+ $query = DB::Aowow()->SelectRow('
+ SELECT a.id, a.passHash, a.displayName, a.locale, a.userGroups, a.userPerms, a.allowExpire, BIT_OR(ab.typeMask) AS bans
+ FROM ?_account a
+ LEFT JOIN ?_account_banned ab ON a.id = ab.userId AND ab.end > UNIX_TIMESTAMP()
+ WHERE a.id = ?d
+ GROUP BY a.id',
+ $_SESSION['user']
+ );
+
+ if (!$query)
+ return false;
+
+ // password changed, terminate session
+ if (AUTH_MODE_SELF && $query['passHash'] != $_SESSION['hash'])
+ {
+ self::destroy();
+ return;
+ }
+
+ self::$id = intval($query['id']);
+ self::$displayName = $query['displayName'];
+ self::$passHash = $query['passHash'];
+ self::$expires = (bool)$query['allowExpire'];
+ self::$banStatus = $query['bans'];
+ self::$groups = $query['bans'] & (ACC_BAN_TEMP | ACC_BAN_PERM) ? 0 : intval($query['userGroups']);
+ self::$perms = $query['bans'] & (ACC_BAN_TEMP | ACC_BAN_PERM) ? 0 : intval($query['userPerms']);
+
+ self::setLocale(intVal($query['locale'])); // reset, if changed
+
+ return true;
}
- // set and use until further notice
+ // set and save
public static function setLocale($set = -1)
{
- if ($set != -1)
+ $loc = LOCALE_EN;
+
+ // get
+ if ($set != -1 && isset(Util::$localeStrings[$set]))
+ $loc = $set;
+ else if (isset($_SESSION['locale']) && isset(Util::$localeStrings[$_SESSION['locale']]))
+ $loc = $_SESSION['locale'];
+ else if (!empty($_SERVER["HTTP_ACCEPT_LANGUAGE"]))
{
- $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;
- }
+ $loc = strtolower(substr($_SERVER["HTTP_ACCEPT_LANGUAGE"], 0, 2));
+ switch ($loc) {
+ case 'ru': $loc = LOCALE_RU; break;
+ case 'es': $loc = LOCALE_ES; break;
+ case 'de': $loc = LOCALE_DE; break;
+ case 'fr': $loc = LOCALE_FR; break;
+ default: $loc = LOCALE_EN;
}
}
// set
- self::$localeId = $loc;
- self::$localeString = self::localeString($loc);
+ if ($loc != self::$localeId)
+ {
+ if (self::$id)
+ DB::Aowow()->query('UPDATE ?_account SET locale = ? WHERE id = ?', $loc, self::$id);
- Lang::load(self::$localeString);
+ self::useLocale($loc);
+ }
}
- // only use this once
+ // only use once
public static function useLocale($use)
{
self::$localeId = isset(Util::$localeStrings[$use]) ? $use : 0;
@@ -156,50 +121,6 @@ class User
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]))
@@ -208,77 +129,185 @@ class User
return Util::$localeStrings[$loc];
}
+ public static function Auth($name, $pass)
+ {
+ $user = 0;
+ $hash = '';
+
+ switch (CFG_AUTH_MODE)
+ {
+ case AUTH_MODE_SELF:
+ {
+ // handle login try limitation
+ $ip = DB::Aowow()->selectRow('SELECT ip, count, unbanDate FROM ?_account_bannedIPs WHERE type = 0 AND ip = ?', $_SERVER['REMOTE_ADDR']);
+ if (!$ip || $ip['unbanDate'] < time()) // no entry exists or time expired; set count to 1
+ DB::Aowow()->query('REPLACE INTO ?_account_bannedIPs (ip, type, count, unbanDate) VALUES (?, 0, 1, UNIX_TIMESTAMP() + ?d)', $_SERVER['REMOTE_ADDR'], CFG_FAILED_AUTH_EXCLUSION);
+ else // entry already exists; increment count
+ DB::Aowow()->query('UPDATE ?_account_bannedIPs SET count = count + 1, unbanDate = UNIX_TIMESTAMP() + ?d WHERE ip = ?', CFG_FAILED_AUTH_EXCLUSION, $_SERVER['REMOTE_ADDR']);
+
+ if ($ip && $ip['count'] >= CFG_FAILED_AUTH_COUNT && $ip['unbanDate'] >= time())
+ return AUTH_IPBANNED;
+
+ $query = DB::Aowow()->SelectRow('
+ SELECT a.id, a.passHash, BIT_OR(ab.typeMask) AS bans, status
+ FROM ?_account a
+ LEFT JOIN ?_account_banned ab ON a.id = ab.userId AND ab.end > UNIX_TIMESTAMP()
+ WHERE a.user = ?
+ GROUP BY a.id',
+ $name
+ );
+ if (!$query)
+ return AUTH_WRONGUSER;
+
+ self::$passHash = $query['passHash'];
+ if (!self::verifyCrypt($pass))
+ return AUTH_WRONGPASS;
+
+ if ($query['status'] & ACC_STATUS_NEW)
+ return AUTH_ACC_INACTIVE;
+
+ // successfull auth; clear bans for this IP
+ DB::Aowow()->query('DELETE FROM ?_account_bannedIPs WHERE type = 0 AND ip = ?', $_SERVER['REMOTE_ADDR']);
+
+ if ($query['bans'] & (ACC_BAN_PERM | ACC_BAN_TEMP))
+ return AUTH_BANNED;
+
+ $user = $query['id'];
+ $hash = $query['passHash'];
+ break;
+ }
+ case AUTH_MODE_REALM:
+ {
+ if (!DB::isConnected(DB_AUTH))
+ return AUTH_INTERNAL_ERR;
+
+ $wow = DB::Auth()->selectRow('SELECT a.id, a.sha_pass_hash, ab.active AS hasBan FROM account a LEFT JOIN account_banned ab ON ab.id = a.id WHERE username = ? AND ORDER BY ab.active DESC LIMIT 1', $name);
+ if (!$wow)
+ return AUTH_WRONGUSER;
+
+ self::$passHash = $wow['sha_pass_hash'];
+ if (!self::verifySHA1($pass))
+ return AUTH_WRONGPASS;
+
+ if ($wow && !$wow['hasBan'])
+ if (!self::checkOrCreateInDB($wow['id'], $name))
+ return AUTH_INTERNAL_ERR;
+
+ else if ($wow['hasBan'])
+ return AUTH_BANNED;
+
+ $user = $wow['id'];
+ break;
+ }
+ case AUTH_MODE_EXTERNAL:
+ {
+ if (!file_exists('/config/extAuth.php'))
+ return AUTH_INTERNAL_ERR;
+
+ require '/config/extAuth.php';
+ $result = extAuth($name, $pass, $extId);
+
+ if ($result == AUTH_OK && $extId)
+ {
+ if (!self::checkOrCreateInDB($extId, $name))
+ return AUTH_INTERNAL_ERR;
+
+ $user = $extId;
+ break;
+ }
+
+ return $result;
+ }
+ default:
+ return AUTH_INTERNAL_ERR;
+ }
+
+ // kickstart session
+ session_unset();
+ $_SESSION['user'] = $user;
+ $_SESSION['hash'] = $hash;
+
+ return AUTH_OK;
+ }
+
+ // create a linked account for our settings if nessecary
+ private static function checkOrCreateInDB($extId, $name)
+ {
+ if (DB::Aowow()->selectCell('SELECT 1 FROM ?_account WHERE extId = ?d', $extId))
+ return true;
+
+ $ok = DB::Aowow()->query('INSERT INTO ?_account (extId, user, displayName, lastIP, locale, status) VALUES (?d, ?, ?, ?, ?d, ?d)',
+ $extId,
+ $name,
+ Util::ucFirst($name),
+ isset($_SERVER["REMOTE_ADDR"]) ? $_SERVER["REMOTE_ADDR"] : '',
+ User::$localeId,
+ ACC_STATUS_OK
+ );
+
+ return $ok;
+ }
+
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);
+ $salt = '$'.Util::createHash(22);
return $algo.$strength.$salt;
}
- private static function hashCrypt($pass)
+ // crypt used by aowow
+ public static function hashCrypt($pass)
{
return crypt($pass, self::createSalt());
}
+ public static function verifyCrypt($pass, $hash = '')
+ {
+ $_ = $hash ?: self::$passHash;
+ return $_ == crypt($pass, $_);
+ }
+
+ // sha1 used by TC / MaNGOS
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
+ $gUser = array(
+ 'commentban' => (bool)(self::$banStatus & ACC_BAN_COMMENT),
+ 'ratingban' => (bool)(self::$banStatus & ACC_BAN_RATE),
'id' => self::$id,
- 'name' => self::$displayName ? self::$displayName : '',
- 'roles' => self::$groups ? self::$groups : 0,
- 'permissions' => self::$perms ? self::$perms : 0,
+ 'name' => self::$displayName,
+ 'roles' => self::$groups,
+ 'permissions' => self::$perms,
'cookies' => []
);
- if (!self::$id)
- return $set;
+ if (!self::$id || self::$banStatus & (ACC_BAN_TEMP | ACC_BAN_PERM))
+ return $gUser;
if ($_ = self::getCharacters())
- $subSet['characters'] = $_;
+ $gUser['characters'] = $_;
if ($_ = self::getProfiles())
- $subSet['profiles'] = $_;
+ $gUser['profiles'] = $_;
if ($_ = self::getWeightScales())
- $subSet['weightscales'] = $_;
+ $gUser['weightscales'] = $_;
if ($_ = self::getCookies())
- $subSet['cookies'] = $_;
+ $gUser['cookies'] = $_;
- return array_merge($set, $subSet);
+ return $gUser;
}
public static function getWeightScales()
@@ -312,43 +341,37 @@ class User
public static function getCharacters($asJSON = true)
{
- if (empty(self::$characters))
- {
- // todo: do after profiler
- @include('datasets/ProfilerExampleChar');
+ // 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']
- )
- );
- }
+ // existing chars on realm(s)
+ $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;
+ return $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)
- );
- }
+ // todo => do after profiler
+ // chars build in profiler
+ $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;
+ return $profiles;
}
public static function getCookies()
@@ -361,23 +384,25 @@ class User
return $data;
}
- public static function writeCookie()
+ public static function save()
{
- $cookie = self::$localeId.count(dechex(self::$id)).dechex(self::$id).base64_encode(self::$passHash);
- SetCookie(COOKIE_AUTH, $cookie, time() + YEAR);
+ $_SESSION['user'] = self::$id;
+ $_SESSION['hash'] = self::$passHash;
+ $_SESSION['locale'] = self::$localeId;
+ $_SESSION['timeout'] = self::$expires ? time() + CFG_SESSION_TIMEOUT_DELAY : 0;
+ // $_SESSION['dataKey'] does not depend on user login status and is set in User::init()
}
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);
+ session_unset();
+ $_SESSION['locale'] = self::$localeId; // keep locale
+ $_SESSION['dataKey'] = self::$dataKey; // keep dataKey
- self::$id = 0;
- self::$displayName = '';
- self::$perms = 0;
- self::$groups = 0;
- self::$characters = NULL;
- self::$profiles = NULL;
+ self::$id = 0;
+ self::$displayName = '';
+ self::$perms = 0;
+ self::$groups = U_GROUP_NONE;
}
}
diff --git a/includes/utilities.php b/includes/utilities.php
index 06dc07e8..47efcb13 100644
--- a/includes/utilities.php
+++ b/includes/utilities.php
@@ -1339,6 +1339,11 @@ class Util
return str;
}
+ public static function isValidEmail($email)
+ {
+ return preg_match('/^([a-z0-9._-]+)(\+[a-z0-9._-]+)?(@[a-z0-9.-]+\.[a-z]{2,4})$/i', $email);
+ }
+
public static function loadStaticFile($file, &$result, $localized = false)
{
$success = true;
@@ -1362,6 +1367,17 @@ class Util
return $success;
}
+ public static function createHash($length = 40) // just some random numbers for unsafe identifictaion purpose
+ {
+ static $seed = ".abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ $hash = '';
+
+ for ($i = 0; $i < $length; $i++)
+ $hash .= substr($seed, mt_rand(0, 62), 1);
+
+ return $hash;
+ }
+
public static function createShowOnMap()
{
/*
diff --git a/index.php b/index.php
index 9c297aca..864fb7d3 100644
--- a/index.php
+++ b/index.php
@@ -27,6 +27,11 @@ switch ($pageCall)
case '': // no parameter given -> MainPage
$altClass = 'main';
case 'account': // account management [nyi]
+ if (($_ = (new AjaxHandler($pageParam))->handle($pageCall)) !== null)
+ {
+ header('Content-type: application/x-javascript; charset=utf-8');
+ die((string)$_);
+ }
case 'achievement':
case 'achievements':
// case 'arena-team':
@@ -72,7 +77,7 @@ switch ($pageCall)
case 'talent': // tool: talent calculator
case 'title':
case 'titles':
- case 'user': // tool: user profiles [nyi]
+ // case 'user': // tool: user profiles [nyi]
case 'zone':
case 'zones':
$_ = ($altClass ?: $pageCall).'Page';
@@ -97,7 +102,7 @@ switch ($pageCall)
case 'missing-screenshots':
case 'most-comments':
case 'random':
- require 'pages/miscTools.php';
+ (new UtilityPage($pageCall, $pageParam))->display();
break;
/* called by script */
case 'data': // tool: dataset-loader
@@ -105,10 +110,11 @@ switch ($pageCall)
case 'contactus':
case 'comment':
case 'locale': // subdomain-workaround, change the language
- header('Content-type: application/x-javascript; charset=utf-8');
- if (($_ = $ajax->handle($pageCall)) !== null)
+ if (($_ = (new AjaxHandler($pageParam))->handle($pageCall)) !== null)
+ {
+ header('Content-type: application/x-javascript; charset=utf-8');
die((string)$_);
-
+ }
break;
/* setup */
case 'build':
diff --git a/localization/lang.class.php b/localization/lang.class.php
index d6902bd4..56cfa33e 100644
--- a/localization/lang.class.php
+++ b/localization/lang.class.php
@@ -5,6 +5,7 @@ class Lang
public static $timeUnits;
public static $main;
public static $account;
+ public static $mail;
public static $game;
public static $search;
@@ -99,10 +100,10 @@ class Lang
$skill = 0;
switch ($prop)
{
- case 1: $skill = 633; break; // Lockpicking
- case 2: $skill = 182; break; // Herbing
- case 3: $skill = 186; break; // Mining
- case 20: $skill = 773; break; // Scribing
+ case 1: $skill = 633; break; // Lockpicking
+ case 2: $skill = 182; break; // Herbing
+ case 3: $skill = 186; break; // Mining
+ case 20: $skill = 773; break; // Scribing
}
if ($skill)
diff --git a/localization/locale_dede.php b/localization/locale_dede.php
index 22727d93..4de7322f 100644
--- a/localization/locale_dede.php
+++ b/localization/locale_dede.php
@@ -47,14 +47,6 @@ $lang = array(
'forum' => "Forum",
'n_a' => "n. v.",
- // err_title = Fehler in AoWoW
- // un_err = Gib bitte deinen Benutzernamen ein
- // pwd_err = Gib bitte dein Passwort ein
- // signin_msg = Gib bitte deinen Accountnamen ein
- // c_pwd = Passwort wiederholen
- // facts = Übersicht
- // This_Object_cant_be_found = Der Standort dieses Objekts ist nicht bekannt.
-
// filter
'extSearch' => "Erweiterte Suche",
'addFilter' => "Weiteren Filter hinzufügen",
@@ -197,12 +189,14 @@ $lang = array(
'expansions' => ["Classic", "The Burning Crusade", "Wrath of the Lich King"],
'stats' => ["Stärke", "Beweglichkeit", "Ausdauer", "Intelligenz", "Willenskraft"],
'sources' => array(
- null, "Hergestellt", "Drop", "PvP", "Quest", "Händler", "Lehrer", "Entdeckung",
- "Einlösung", "Talent", "Startausrüstung", "Ereignis", "Erfolg"
+ null, "Hergestellt", "Drop", "PvP", "Quest", "Händler",
+ "Lehrer", "Entdeckung", "Einlösung", "Talent", "Startausrüstung", "Ereignis",
+ "Erfolg"
),
'languages' => array(
- 1 => "Orcisch", 2 => "Darnassisch", 3 => "Taurisch", 6 => "Zwergisch", 7 => "Gemeinsprache", 8 => "Dämonisch", 9 => "Titanisch", 10 => "Thalassisch",
- 11 => "Drachisch", 12 => "Kalimagisch", 13 => "Gnomisch", 14 => "Trollisch", 33 => "Gossensprache", 35 => "Draeneiisch", 36 => "Zombie", 37 => "Gnomenbinär", 38 => "Goblinbinär"
+ 1 => "Orcisch", 2 => "Darnassisch", 3 => "Taurisch", 6 => "Zwergisch", 7 => "Gemeinsprache", 8 => "Dämonisch",
+ 9 => "Titanisch", 10 => "Thalassisch", 11 => "Drachisch", 12 => "Kalimagisch", 13 => "Gnomisch", 14 => "Trollisch",
+ 33 => "Gossensprache", 35 => "Draeneiisch", 36 => "Zombie", 37 => "Gnomenbinär", 38 => "Goblinbinär"
),
'gl' => [null, "Erhebliche", "Geringe"],
'si' => [1 => "Allianz", -1 => "Nur für Allianz", 2 => "Horde", -2 => "Nur für Horde", 3 => "Beide"],
@@ -213,72 +207,118 @@ $lang = array(
'ra' => [-2 => "Horde", -1 => "Allianz", "Beide", "Mensch", "Orc", "Zwerg", "Nachtelf", "Untoter", "Tauren", "Gnom", "Troll", null, "Blutelf", "Draenei"],
'rep' => ["Hasserfüllt", "Feindselig", "Unfreundlich", "Neutral", "Freundlich", "Wohlwollend", "Respektvoll", "Ehrfürchtig"],
'st' => array(
- "Vorgabe", "Katzengestalt", "Baum des Lebens", "Reisegestalt", "Wassergestalt",
- "Bärengestalt", null, null, "Terrorbärengestalt", null,
- null, null, null, "Schattentanz", null,
- null, "Geisterwolf", "Kampfhaltung", "Verteidigungshaltung", "Berserkerhaltung",
- null, null, "Metamorphosis", null, null,
- null, null, "Schnelle Fluggestalt", "Schattengestalt", "Fluggestalt",
- "Verstohlenheit", "Mondkingestalt", "Geist der Erlösung"
+ "Vorgabe", "Katzengestalt", "Baum des Lebens", "Reisegestalt", "Wassergestalt", "Bärengestalt",
+ null, null, "Terrorbärengestalt", null, null, null,
+ null, "Schattentanz", null, null, "Geisterwolf", "Kampfhaltung",
+ "Verteidigungshaltung", "Berserkerhaltung", null, null, "Metamorphosis", null,
+ null, null, null, "Schnelle Fluggestalt", "Schattengestalt", "Fluggestalt",
+ "Verstohlenheit", "Mondkingestalt", "Geist der Erlösung"
),
'me' => array(
- null, "Bezaubert", "Desorientiert", "Entwaffnet", "Abgelenkt", "Flüchtend", "Ergriffen", "Unbeweglich",
- "Befriedet", "Schweigend", "Schlafend", "Verlangsamt", "Betäubt", "Eingefroren", "Handlungsunfähig", "Blutend",
- "Heilung", "Verwandelt", "Verbannt", "Abgeschirmt", "Gefesselt", "Reitend", "Verführt", "Vertrieben",
- "Entsetzt", "Unverwundbar", "Unterbrochen", "Benommen", "Entdeckung", "Unverwundbar", "Kopfnuss", "Wütend"
+ null, "Bezaubert", "Desorientiert", "Entwaffnet", "Abgelenkt", "Flüchtend",
+ "Ergriffen", "Unbeweglich", "Befriedet", "Schweigend", "Schlafend", "Verlangsamt",
+ "Betäubt", "Eingefroren", "Handlungsunfähig", "Blutend", "Heilung", "Verwandelt",
+ "Verbannt", "Abgeschirmt", "Gefesselt", "Reitend", "Verführt", "Vertrieben",
+ "Entsetzt", "Unverwundbar", "Unterbrochen", "Benommen", "Entdeckung", "Unverwundbar",
+ "Kopfnuss", "Wütend"
),
'ct' => array(
- "Nicht kategorisiert", "Wildtier", "Drachkin", "Dämon", "Elementar", "Riese", "Untoter", "Humanoid",
- "Tier", "Mechanisch", "Nicht spezifiziert", "Totem", "Haustier", "Gaswolke"
+ "Nicht kategorisiert", "Wildtier", "Drachkin", "Dämon", "Elementar", "Riese",
+ "Untoter", "Humanoid", "Tier", "Mechanisch", "Nicht spezifiziert", "Totem",
+ "Haustier", "Gaswolke"
),
'fa' => array(
- 1 => "Wolf", 2 => "Katze", 3 => "Spinne", 4 => "Bär", 5 => "Eber", 6 => "Krokilisk", 7 => "Aasvogel", 8 => "Krebs",
- 9 => "Gorilla", 11 => "Raptor", 12 => "Weitschreiter", 20 => "Skorpid", 21 => "Schildkröte", 24 => "Fledermaus", 25 => "Hyäne", 26 => "Raubvogel",
- 27 => "Windnatter", 30 => "Drachenfalke", 31 => "Felshetzer", 32 => "Sphärenjäger", 33 => "Sporensegler", 34 => "Netherrochen", 35 => "Schlange", 37 => "Motte",
- 38 => "Schimäre", 39 => "Teufelssaurier", 41 => "Silithid", 42 => "Wurm", 43 => "Rhinozeros", 44 => "Wespe", 45 => "Kernhund", 46 => "Geisterbestie"
+ 1 => "Wolf", 2 => "Katze", 3 => "Spinne", 4 => "Bär", 5 => "Eber", 6 => "Krokilisk",
+ 7 => "Aasvogel", 8 => "Krebs", 9 => "Gorilla", 11 => "Raptor", 12 => "Weitschreiter", 20 => "Skorpid",
+ 21 => "Schildkröte", 24 => "Fledermaus", 25 => "Hyäne", 26 => "Raubvogel", 27 => "Windnatter", 30 => "Drachenfalke",
+ 31 => "Felshetzer", 32 => "Sphärenjäger", 33 => "Sporensegler", 34 => "Netherrochen", 35 => "Schlange", 37 => "Motte",
+ 38 => "Schimäre", 39 => "Teufelssaurier", 41 => "Silithid", 42 => "Wurm", 43 => "Rhinozeros", 44 => "Wespe",
+ 45 => "Kernhund", 46 => "Geisterbestie"
),
'pvpRank' => array(
- null, "Gefreiter / Späher", "Fußknecht / Grunzer",
- "Landsknecht / Waffenträger", "Feldwebel / Schlachtrufer", "Fähnrich / Rottenmeister",
- "Leutnant / Steingardist", "Hauptmann / Blutgardist", "Kürassier / Zornbringer",
- "Ritter der Allianz / Klinge der Horde", "Feldkomandant / Feldherr", "Rittmeister / Sturmreiter",
- "Marschall / Kriegsherr", "Feldmarschall / Kriegsfürst", "Großmarschall / Oberster Kriegsfürst"
+ null, "Gefreiter / Späher", "Fußknecht / Grunzer",
+ "Landsknecht / Waffenträger", "Feldwebel / Schlachtrufer", "Fähnrich / Rottenmeister",
+ "Leutnant / Steingardist", "Hauptmann / Blutgardist", "Kürassier / Zornbringer",
+ "Ritter der Allianz / Klinge der Horde", "Feldkomandant / Feldherr", "Rittmeister / Sturmreiter",
+ "Marschall / Kriegsherr", "Feldmarschall / Kriegsfürst", "Großmarschall / Oberster Kriegsfürst"
),
),
'account' => array(
+ 'title' => "Aowow-Konto",
+ 'email' => "E-Mail-Adresse",
+ 'continue' => "Fortsetzen",
+ 'groups' => array(
+ -1 => "Keine", "Tester", "Administrator", "Editor", "Moderator", "Bürokrat",
+ "Entwickler", "VIP", "Blogger", "Premium", "Übersetzer", "Handelsvertreter",
+ "Screenshot-Verwalter", "Video-Verwalter"
+ ),
+ // signIn
'doSignIn' => "Mit Eurem AoWoW-Konto anmelden",
+ 'signIn' => "Anmelden",
'user' => "Benutzername",
'pass' => "Kennwort",
'rememberMe' => "Angemeldet bleiben",
'forgot' => "Vergessen",
- 'accNoneYet' => "Noch kein Konto",
- 'accCreateNow' => "Jetzt eins erstellen",
- 'userNotFound' => "Ein Konto mit diesem Namen existiert nicht",
- 'userBanned' => "Dieses Konto wurde geschlossen",
- 'passMismatch' => "Die eingegebenen Passwörter stimmen nicht überein",
- 'loginsExceeded'=> "Die maximale Anzahl an Login-Versuchen von dieser IP wurde überschritten. Bitte versuchen Sie es in %s Minuten noch einmal.",
- 'nameInUse' => "Es existiert bereits ein Konto mit diesem Namen",
- 'email' => "E-Mail-Adresse",
- 'unkError' => "Unbekannter Fehler bei der Accounterstellung",
- 'accCreate' => "Konto erstellen",
- 'passConfirm' => "Passwort bestätigen",
- 'signup' => "Anmelden",
- 'requestName' => "Username Request",
- 'resetPass' => "Password Reset",
- 'emailInvalid' => "Diese E-Mail-Adresse ist ungültig.",
- 'emailUnknown' => "Die E-Mail-Adresse, die Ihr eingegeben habt, ist mit keinem Konto verbunden.
Falls Ihr die E-Mail-Adresse vergessen habt, mit der Ihr Euer Konto erstellt habt, kontaktiert Ihr bitte feedback@aowow.com für Hilfestellung.",
- 'passJustSend' => "Eine Nachricht mit einem neuen Passwort wurde soeben an %s versandt.",
- 'nameJustSend' => "Eine Nachricht mit Eurem Benutzernamen wurde soeben an %s versandt.",
- 'wrongPass' => "Falsches Passwort",
+ 'forgotUser' => "Benutzername",
+ 'forgotPass' => "Kennwort",
+ 'accCreate' => 'Noch kein Konto? Jetzt eins erstellen!',
+
+ // recovery
+ 'recoverUser' => "Benutzernamenanfrage",
+ 'recoverPass' => "Kennwort zurücksetzen: Schritt %s von 2",
+ 'newPass' => "Neues Kennwort",
+
+ // creation
+ 'register' => "Registrierung: Schritt %s von 2",
+
+ // dashboard
'ipAddress' => "IP-Adresse",
'lastIP' => "Letzte bekannte IP",
'joinDate' => "Mitglied seit",
'lastLogin' => "Letzter Besuch",
- 'userGroups' => "Role",
+ 'userGroups' => "Rolle",
'myAccount' => "Mein Account",
'editAccount' => "Benutze die folgenden Formulare um deine Account-Informationen zu aktualisieren",
'publicDesc' => "Öffentliche Beschreibung",
'viewPubDesc' => 'Die Beschreibung in deinem öffentlichen Profil ansehen',
+
+ // bans
+ 'accBanned' => "Dieses Konto wurde geschlossen",
+ 'bannedBy' => "Gebannt durch",
+ 'ends' => "Endet am",
+ 'permanent' => "Der Bann ist permanent",
+ 'reason' => "Grund",
+ 'noReason' => "Es wurde kein Grund angegeben.",
+
+ // form-text
+ 'emailInvalid' => "Diese E-Mail-Adresse ist ungültig.", // message_emailnotvalid
+ 'emailNotFound' => "Die E-Mail-Adresse, die Ihr eingegeben habt, ist mit keinem Konto verbunden.
Falls Ihr die E-Mail-Adresse vergessen habt, mit der Ihr Euer Konto erstellt habt, kontaktiert Ihr bitte ".CFG_CONTACT_EMAIL." für Hilfestellung.",
+ 'createAccSent' => "Eine Nachricht wurde soeben an %s versandt. Folgt den Anweisungen um euer Konto zu erstellen.",
+ 'recovUserSent' => "Eine Nachricht wurde soeben an %s versandt. Folgt den Anweisungen um euren Benutzernamen zu erhalten.",
+ 'recovPassSent' => "Eine Nachricht wurde soeben an %s versandt. Folgt den Anweisungen um euer Kennwort zurückzusetzen.",
+ 'accActivated' => 'Euer Konto wurde soeben aktiviert. Ihr könnt euch nun anmelden',
+ 'userNotFound' => "Ein Konto mit diesem Namen existiert nicht.",
+ 'wrongPass' => "Dieses Kennwort ist ungültig.",
+ 'accInactive' => "Dieses Konto wurde bisher nicht aktiviert.",
+ 'loginExceeded' => "Die maximale Anzahl an Anmelde-Versuchen von dieser IP wurde überschritten. Bitte versucht es in %s erneut.",
+ 'signupExceeded'=> "Die maximale Anzahl an Regustrierungen von dieser IP wurde überschritten. Bitte versucht es in %s erneut.",
+ 'errNameLength' => "Euer Benutzername muss mindestens 4 Zeichen lang sein.", // message_usernamemin
+ 'errNameChars' => "Euer Benutzername kann nur aus Buchstaben und Zahlen bestehen.", // message_usernamenotvalid
+ 'errPassLength' => "Euer Kennwort muss mindestens 6 Zeichen lang sein.", // message_passwordmin
+ 'passMismatch' => "Die eingegebenen Kennworte stimmen nicht überein.",
+ 'nameInUse' => "Es existiert bereits ein Konto mit diesem Namen.",
+ 'mailInUse' => "Diese E-Mail-Adresse ist bereits mit einem Konto verbunden.",
+ 'intError' => "Ein interner Fehler ist aufgetreten.",
+ 'intError2' => "Ein interner Fehler ist aufgetreten. (%s)",
+ 'isRecovering' => "Dieses Konto wird bereits wiederhergestellt. Folgt den Anweisungen in der Nachricht oder wartet %s bis das Token verfällt.",
+ 'passCheckFail' => "Die Kennwörter stimmen nicht überein.", // message_passwordsdonotmatch
+ 'newPassDiff' => "Euer neues Kennwort muss sich von eurem alten Kennwort unterscheiden." // message_newpassdifferent
+ ),
+ 'mail' => array(
+ 'tokenExpires' => "Das Token wird in %s verfallen.",
+ 'accConfirm' => ["Kontobestätigung", "Willkommen bei ".CFG_NAME_SHORT."!\r\n\r\nKlicke auf den Link um euren Account zu aktivieren.\r\n\r\n".HOST_URL."?account=signup&token=%s\r\n\r\nFalls Ihr diese Mail nicht angefordert habt kann sie einfach ignoriert werden."],
+ 'recoverUser' => ["Benutzernamenanfrage", "Folgt diesem Link um euch anzumelden.\r\n\r\n".HOST_URL."?account=signin&token=%s\r\n\r\nFalls Ihr diese Mail nicht angefordert habt kann sie einfach ignoriert werden."],
+ 'resetPass' => ["Kennwortreset", "Folgt diesem Link um euer Kennwort zurückzusetzen.\r\n\r\n".HOST_URL."?account=forgotpassword&token=%s\r\n\r\nFalls Ihr diese Mail nicht angefordert habt kann sie einfach ignoriert werden."]
),
'gameObject' => array(
'cat' => [0 => "Anderes", 9 => "Bücher", 3 => "Behälter", -5 => "Truhen", 25 => "Fischschwärme", -3 => "Kräuter", -4 => "Erzadern", -2 => "Quest", -6 => "Werkzeuge"],
diff --git a/localization/locale_enus.php b/localization/locale_enus.php
index b18c3c98..a8d872c1 100644
--- a/localization/locale_enus.php
+++ b/localization/locale_enus.php
@@ -184,12 +184,14 @@ $lang = array(
'expansions' => ["Classic", "The Burning Crusade", "Wrath of the Lich King"],
'stats' => ["Strength", "Agility", "Stamina", "Intellect", "Spirit"],
'sources' => array(
- null, "Crafted", "Drop", "PvP", "Quest", "Vendor", "Trainer", "Discovery",
- "Redemption", "Talent", "Starter", "Event", "Achievement"
+ null, "Crafted", "Drop", "PvP", "Quest", "Vendor",
+ "Trainer", "Discovery", "Redemption", "Talent", "Starter", "Event",
+ "Achievement"
),
'languages' => array(
- 1 => "Orcish", 2 => "Darnassian", 3 => "Taurahe", 6 => "Dwarvish", 7 => "Common", 8 => "Demonic", 9 => "Titan", 10 => "Thalassian",
- 11 => "Draconic", 12 => "Kalimag", 13 => "Gnomish", 14 => "Troll", 33 => "Gutterspeak", 35 => "Draenei", 36 => "Zombie", 37 => "Gnomish Binary", 38 => "Goblin Binary"
+ 1 => "Orcish", 2 => "Darnassian", 3 => "Taurahe", 6 => "Dwarvish", 7 => "Common", 8 => "Demonic",
+ 9 => "Titan", 10 => "Thalassian", 11 => "Draconic", 12 => "Kalimag", 13 => "Gnomish", 14 => "Troll",
+ 33 => "Gutterspeak", 35 => "Draenei", 36 => "Zombie", 37 => "Gnomish Binary", 38 => "Goblin Binary"
),
'gl' => [null, "Major", "Minor"],
'si' => [1 => "Alliance", -1 => "Alliance only", 2 => "Horde", -2 => "Horde only", 3 => "Both"],
@@ -200,72 +202,118 @@ $lang = array(
'ra' => [-2 => "Horde", -1 => "Alliance", "Both", "Human", "Orc", "Dwarf", "Night Elf", "Undead", "Tauren", "Gnome", "Troll", null, "Blood Elf", "Draenei"],
'rep' => ["Hated", "Hostile", "Unfriendly", "Neutral", "Friendly", "Honored", "Revered", "Exalted"],
'st' => array(
- "Default", "Cat Form", "Tree of Life", "Travel Form", "Aquatic Form",
- "Bear From", null, null, "Dire Bear Form", null,
- null, null, null, "Shadowdance", null,
- null, "Ghostwolf", "Battle Stance", "Defensive Stance", "Berserker Stance",
- null, null, "Metamorphosis", null, null,
- null, null, "Swift Flight Form", "Shadow Form", "Flight Form",
- "Stealth", "Moonkin Form", "Spirit of Redemption"
+ "Default", "Cat Form", "Tree of Life", "Travel Form", "Aquatic Form", "Bear From",
+ null, null, "Dire Bear Form", null, null, null,
+ null, "Shadowdance", null, null, "Ghostwolf", "Battle Stance",
+ "Defensive Stance", "Berserker Stance", null, null, "Metamorphosis", null,
+ null, null, null, "Swift Flight Form", "Shadow Form", "Flight Form",
+ "Stealth", "Moonkin Form", "Spirit of Redemption"
),
'me' => array(
- null, "Charmed", "Disoriented", "Disarmed", "Distracted", "Fleeing", "Gripped", "Rooted",
- "Pacified", "Silenced", "Asleep", "Ensnared", "Stunned", "Frozen", "Incapacitated", "Bleeding",
- "Healing", "Polymorphed", "Banished", "Shielded", "Shackled", "Mounted", "Seduced", "Turned",
- "Horrified", "Invulnerable", "Interrupted", "Dazed", "Discovery", "Invulnerable", "Sapped", "Enraged"
+ null, "Charmed", "Disoriented", "Disarmed", "Distracted", "Fleeing",
+ "Gripped", "Rooted", "Pacified", "Silenced", "Asleep", "Ensnared",
+ "Stunned", "Frozen", "Incapacitated", "Bleeding", "Healing", "Polymorphed",
+ "Banished", "Shielded", "Shackled", "Mounted", "Seduced", "Turned",
+ "Horrified", "Invulnerable", "Interrupted", "Dazed", "Discovery", "Invulnerable",
+ "Sapped", "Enraged"
),
'ct' => array(
- "Uncategorized", "Beast", "Dragonkin", "Demon", "Elemental", "Giant", "Undead", "Humanoid",
- "Critter", "Mechanical", "Not specified", "Totem", "Non-combat Pet", "Gas Cloud"
+ "Uncategorized", "Beast", "Dragonkin", "Demon", "Elemental", "Giant",
+ "Undead", "Humanoid", "Critter", "Mechanical", "Not specified", "Totem",
+ "Non-combat Pet", "Gas Cloud"
),
'fa' => array(
- 1 => "Wolf", 2 => "Cat", 3 => "Spider", 4 => "Bear", 5 => "Boar", 6 => "Crocolisk", 7 => "Carrion Bird", 8 => "Crab",
- 9 => "Gorilla", 11 => "Raptor", 12 => "Tallstrider", 20 => "Scorpid", 21 => "Turtle", 24 => "Bat", 25 => "Hyena", 26 => "Bird of Prey",
- 27 => "Wind Serpent", 30 => "Dragonhawk", 31 => "Ravager", 32 => "Warp Stalker", 33 => "Sporebat", 34 => "Nether Ray", 35 => "Serpent", 37 => "Moth",
- 38 => "Chimaera", 39 => "Devilsaur", 41 => "Silithid", 42 => "Worm", 43 => "Rhino", 44 => "Wasp", 45 => "Core Hound", 46 => "Spirit Beast"
+ 1 => "Wolf", 2 => "Cat", 3 => "Spider", 4 => "Bear", 5 => "Boar", 6 => "Crocolisk",
+ 7 => "Carrion Bird", 8 => "Crab", 9 => "Gorilla", 11 => "Raptor", 12 => "Tallstrider", 20 => "Scorpid",
+ 21 => "Turtle", 24 => "Bat", 25 => "Hyena", 26 => "Bird of Prey", 27 => "Wind Serpent", 30 => "Dragonhawk",
+ 31 => "Ravager", 32 => "Warp Stalker", 33 => "Sporebat", 34 => "Nether Ray", 35 => "Serpent", 37 => "Moth",
+ 38 => "Chimaera", 39 => "Devilsaur", 41 => "Silithid", 42 => "Worm", 43 => "Rhino", 44 => "Wasp",
+ 45 => "Core Hound", 46 => "Spirit Beast"
),
'pvpRank' => array(
- null, "Private / Scout", "Corporal / Grunt",
- "Sergeant / Sergeant", "Master Sergeant / Senior Sergeant", "Sergeant Major / First Sergeant",
- "Knight / Stone Guard", "Knight-Lieutenant / Blood Guard", "Knight-Captain / Legionnare",
- "Knight-Champion / Centurion", "Lieutenant Commander / Champion", "Commander / Lieutenant General",
- "Marshal / General", "Field Marshal / Warlord", "Grand Marshal / High Warlord"
+ null, "Private / Scout", "Corporal / Grunt",
+ "Sergeant / Sergeant", "Master Sergeant / Senior Sergeant", "Sergeant Major / First Sergeant",
+ "Knight / Stone Guard", "Knight-Lieutenant / Blood Guard", "Knight-Captain / Legionnare",
+ "Knight-Champion / Centurion", "Lieutenant Commander / Champion", "Commander / Lieutenant General",
+ "Marshal / General", "Field Marshal / Warlord", "Grand Marshal / High Warlord"
),
),
'account' => array(
+ 'title' => "Aowow Account",
+ 'email' => "Email address",
+ 'continue' => "Continue",
+ 'groups' => array(
+ -1 => "None", "Tester", "Administrator", "Editor", "Moderator", "Bureaucrat",
+ "Developer", "VIP", "Blogger", "Premium", "Localizer", "Sales agent",
+ "Screenshot manager", "Video manager"
+ ),
+ // signIn
'doSignIn' => "Log in to your AoWoW Account",
+ 'signIn' => "Log In",
'user' => "Username",
'pass' => "Password",
'rememberMe' => "Stay logged in",
'forgot' => "Forgot",
- 'accNoneYet' => "Don't have an account",
- 'accCreateNow' => "Create one now",
- 'userNotFound' => "Such user does not exists",
- 'userBanned' => "This Account was closed",
- 'passMismatch' => "Entered passwords does not match",
- 'loginsExceeded'=> "The maximum number of logins from this IP has been exceeded. Please try again in %s minutes.",
- 'nameInUse' => "Such user already exists",
- 'email' => "Email address",
- 'unkError' => "Unknown error on account create",
- 'accCreate' => "Create your account",
- 'passConfirm' => "Confirm password",
- 'signup' => "Signup",
- 'requestName' => "Username Request",
- 'resetPass' => "Password Reset",
- 'emailInvalid' => "This email address is invalid.",
- 'emailUnknown' => "The email address you entered is not associated with any account.
If you forgot the email you registered your account with email feedback@aowow.com for assistance.",
- 'passJustSend' => "An email containing a new password was just sent to %s",
- 'nameJustSend' => "An email containing your username was just sent to %s",
- 'wrongPass' => "Wrong Password",
+ 'forgotUser' => "Username",
+ 'forgotPass' => "Password",
+ 'accCreate' => 'Don\'t have an account? Create one now!',
+
+ // recovery
+ 'recoverUser' => "Username Request",
+ 'recoverPass' => "Password Reset: Step %s of 2",
+ 'newPass' => "New Password",
+
+ // creation
+ 'register' => "Registration - Step %s of 2",
+
+ // dashboard
'ipAddress' => "IP-Adress",
'lastIP' => "last used IP",
'joinDate' => "Joined",
'lastLogin' => "Last visit",
- 'userGroups' => "Rolle",
+ 'userGroups' => "Role",
'myAccount' => "My Account",
'editAccount' => "Simply use the forms below to update your account information",
'publicDesc' => "Public Description",
'viewPubDesc' => 'View your Public Description in your Profile Page',
+
+ // bans
+ 'accBanned' => "This Account was closed",
+ 'bannedBy' => "Banned by",
+ 'ends' => "Ends on",
+ 'permanent' => "The ban is permanent",
+ 'reason' => "Reason",
+ 'noReason' => "No reason was given.",
+
+ // form-text
+ 'emailInvalid' => "That email address is not valid.", // message_emailnotvalid
+ 'emailNotFound' => "The email address you entered is not associated with any account.
If you forgot the email you registered your account with email ".CFG_CONTACT_EMAIL." for assistance.",
+ 'createAccSent' => "An email was sent to %s. Simply follow the instructions to create your account.",
+ 'recovUserSent' => "An email was sent to %s. Simply follow the instructions to recover your username.",
+ 'recovPassSent' => "An email was sent to %s. Simply follow the instructions to reset your password.",
+ 'accActivated' => 'Your account has been activated. Proceed to sign in',
+ 'userNotFound' => "The username you entered does not exists.",
+ 'wrongPass' => "That password is not vaild.",
+ 'accInactive' => "That account has not yet been confirmed active.",
+ 'loginExceeded' => "The maximum number of logins from this IP has been exceeded. Please try again in %s.",
+ 'signupExceeded'=> "The maximum number of signups from this IP has been exceeded. Please try again in %s.",
+ 'errNameLength' => "Your username must be at least 4 characters long.", // message_usernamemin
+ 'errNameChars' => "Your username can only contain letters and numbers.", // message_usernamenotvalid
+ 'errPassLength' => "Your password must be at least 6 characters long.", // message_passwordmin
+ 'passMismatch' => "The passwords you entered do not match.",
+ 'nameInUse' => "That username is already taken.",
+ 'mailInUse' => "That email is already registered to an account.",
+ 'intError' => "An internal error occured.",
+ 'intError2' => "An internal error occured. (%s)",
+ 'isRecovering' => "This account is already recovering. Follow the instructions in your email or wait %s for the token to expire.",
+ 'passCheckFail' => "Passwords do not match.", // message_passwordsdonotmatch
+ 'newPassDiff' => "Your new password must be different than your previous one." // message_newpassdifferent
+ ),
+ 'mail' => array(
+ 'tokenExpires' => "This token expires in %s.",
+ 'accConfirm' => ["Account Confirmation", "Welcome to ".CFG_NAME_SHORT."!\r\n\r\nClick the Link below to activate your account.\r\n\r\n".HOST_URL."?account=signup&token=%s\r\n\r\nIf you did not request this mail simply ignore it."],
+ 'recoverUser' => ["User Recovery", "Follow this link to log in.\r\n\r\n".HOST_URL."?account=signin&token=%s\r\n\r\nIf you did not request this mail simply ignore it."],
+ 'resetPass' => ["Password Reset", "Follow this link to reset your password.\r\n\r\n".HOST_URL."?account=forgotpassword&token=%s\r\n\r\nIf you did not request this mail simply ignore it."]
),
'gameObject' => array(
'cat' => [0 => "Other", 9 => "Books", 3 => "Containers", -5 => "Chests", 25 => "Fishing Pools", -3 => "Herbs", -4 => "Mineral Veins", -2 => "Quest", -6 => "Tools"],
diff --git a/localization/locale_eses.php b/localization/locale_eses.php
index d2e63aed..51498214 100644
--- a/localization/locale_eses.php
+++ b/localization/locale_eses.php
@@ -237,7 +237,84 @@ $lang = array(
"Marshal / General", "Field Marshal / Warlord", "Grand Marshal / High Warlord"
),
),
- 'account' => [],
+ 'account' => array(
+ 'title' => "Cuenta de Aowow",
+ 'email' => "Dirección de correo electrónico",
+ 'continue' => "Continuar",
+ 'groups' => array(
+ -1 => "Ninguno", "Probador", "Administrador", "Editor", "Moderador", "Burócrata",
+ "Desarrollador", "VIP", "Bloggor", "Premium", "Traductor", "Agente de ventas",
+ "Gestor de Capturas de pantalla","Gestor de vídeos"
+ ),
+
+ // signIn
+ 'doSignIn' => "Iniciar sesión con tu cuenta de Aowow",
+ 'signIn' => "Iniciar sesión",
+ 'user' => "Nombre de usuario",
+ 'pass' => "Contraseña",
+ 'rememberMe' => "Seguir conectado",
+ 'forgot' => "Se me olvidó mi",
+ 'forgotUser' => "Nombre de usuario",
+ 'forgotPass' => "Contraseña",
+ 'accCreate ' => '¿No tienes una cuenta? ¡Crea una ahora!',
+
+ // recovery
+ 'recoverUser' => "Pedir nombre de usuario",
+ 'recoverPass' => "Reiniciar contraseña: Paso %s de 2",
+ 'newPass' => "New Password",
+
+ // creation
+ 'register' => "Inscripción: Paso %s de 2",
+
+ // dashboard
+ 'ipAddress' => "IP-Adress",
+ 'lastIP' => "last used IP",
+ 'joinDate' => "Joined",
+ 'lastLogin' => "Last visit",
+ 'userGroups' => "Role",
+ 'myAccount' => "My Account",
+ 'editAccount' => "Simply use the forms below to update your account information",
+ 'publicDesc' => "Public Description",
+ 'viewPubDesc' => 'View your Public Description in your Profile Page',
+
+ // bans
+ 'accBanned' => "This Account was closed",
+ 'bannedBy' => "Banned by",
+ 'ends' => "Ends on",
+ 'permanent' => "The ban is permanent",
+ 'reason' => "Reason",
+ 'noReason' => "No reason was given.",
+
+ // form-text
+ 'emailInvalid' => "Esa dirección de correo electrónico no es válida.", // message_emailnotvalid
+ 'emailNotFound' => "The email address you entered is not associated with any account.
If you forgot the email you registered your account with email ".CFG_CONTACT_EMAIL." for assistance.",
+ 'createAccSent' => "An email was sent to %s. Simply follow the instructions to create your account.",
+ 'recovUserSent' => "An email was sent to %s. Simply follow the instructions to recover your username.",
+ 'recovPassSent' => "An email was sent to %s. Simply follow the instructions to reset your password.",
+ 'accActivated' => 'Your account has been activated. Proceed to sign in',
+ 'userNotFound' => "The username you entered does not exists.",
+ 'wrongPass' => "That password is not vaild.",
+ 'accInactive' => "That account has not yet been confirmed active.",
+ 'loginExceeded' => "The maximum number of logins from this IP has been exceeded. Please try again in %s.",
+ 'signupExceeded'=> "The maximum number of signups from this IP has been exceeded. Please try again in %s.",
+ 'errNameLength' => "Tu nombre de usuario tiene que tener por lo menos cuatro caracteres.", // message_usernamemin
+ 'errNameChars' => "Tu nombre de usuario solo puede contener números y letras.", // message_usernamenotvalid
+ 'errPassLength' => "Tu contraseña tiene que tener por lo menos seis caracteres.", // message_passwordmin
+ 'passMismatch' => "The passwords you entered do not match.",
+ 'nameInUse' => "That username is already taken.",
+ 'mailInUse' => "That email is already registered to an account.",
+ 'intError' => "An internal error occured.",
+ 'intError2' => "An internal error occured. (%s)",
+ 'isRecovering' => "This account is already recovering. Follow the instructions in your email or wait %s for the token to expire.",
+ 'passCheckFail' => "Las contraseñas no son iguales.", // message_passwordsdonotmatch
+ 'newPassDiff' => "Su nueva contraseña tiene que ser diferente a Su contraseña anterior." // message_newpassdifferent
+ ),
+ 'mail' => array(
+ 'tokenExpires' => "This token expires in %s.",
+ 'accConfirm' => ["Account Confirmation", "Welcome to ".CFG_NAME_SHORT."!\r\n\r\nClick the Link below to activate your account.\r\n\r\n".HOST_URL."?account=signup&token=%s\r\n\r\nIf you did not request this mail simply ignore it."],
+ 'recoverUser' => ["User Recovery", "Follow this link to log in.\r\n\r\n".HOST_URL."?account=signin&token=%s\r\n\r\nIf you did not request this mail simply ignore it."],
+ 'resetPass' => ["Password Reset", "Follow this link to reset your password.\r\n\r\n".HOST_URL."?account=forgotpassword&token=%s\r\n\r\nIf you did not request this mail simply ignore it."]
+ ),
'gameObject' => array(
'cat' => [0 => "Otros", 9 => "Libros", 3 => "Contenedores", -5 => "Cofres", 25 => "Bancos de peces", -3 => "Hierbas", -4 => "Venas de minerales", -2 => "Misiones", -6 => "Herramientas"],
'type' => [ 9 => "Libro", 3 => "Contenedore", -5 => "Cofre", 25 => "", -3 => "Hierba", -4 => "Filóne de mineral", -2 => "Misión", -6 => ""],
diff --git a/localization/locale_frfr.php b/localization/locale_frfr.php
index a77b470d..f35ed465 100644
--- a/localization/locale_frfr.php
+++ b/localization/locale_frfr.php
@@ -237,7 +237,83 @@ $lang = array(
"Marshal / General", "Field Marshal / Warlord", "Grand Marshal / High Warlord"
),
),
- 'account' => [],
+ 'account' => array(
+ 'title' => "Compte Aowow",
+ 'email' => "Courriel",
+ 'continue' => "Poursuivre",
+ 'groups' => array(
+ -1 => "None", "Testeur", "Administrateur", "Éditeur", "Modérateur", "Bureaucrate",
+ "Développeur", "VIP", "Bloggeur", "Premium", "Traducteur", "Agent de ventes",
+ "Gestionnaire de capture d'écran","Gestionnaire de vidéos"
+ ),
+ // signIn
+ 'doSignIn' => "Connexion à votre compte Aowow",
+ 'signIn' => "Connexion",
+ 'user' => "Nom d'utilisateur",
+ 'pass' => "Mot de passe",
+ 'rememberMe' => "Rester connecté",
+ 'forgot' => "Oublié",
+ 'forgotUser' => "Nom d'utilisateur",
+ 'forgotPass' => "Mot de passe",
+ 'accCreate' => 'Vous n\'avez pas encore de compte ? Créez-en un maintenant !',
+
+ // recovery
+ 'recoverUser' => "Demande de nom d'utilisateur",
+ 'recoverPass' => "Changement de mot de passe : Étape %s de 2",
+ 'newPass' => "New Password",
+
+ // creation
+ 'register' => "Enregistrement : Étape %s de 2",
+
+ // dashboard
+ 'ipAddress' => "IP-Adress",
+ 'lastIP' => "last used IP",
+ 'joinDate' => "Joined",
+ 'lastLogin' => "Last visit",
+ 'userGroups' => "Role",
+ 'myAccount' => "My Account",
+ 'editAccount' => "Simply use the forms below to update your account information",
+ 'publicDesc' => "Public Description",
+ 'viewPubDesc' => 'View your Public Description in your Profile Page',
+
+ // bans
+ 'accBanned' => "This Account was closed",
+ 'bannedBy' => "Banned by",
+ 'ends' => "Ends on",
+ 'permanent' => "The ban is permanent",
+ 'reason' => "Reason",
+ 'noReason' => "No reason was given.",
+
+ // form-text
+ 'emailInvalid' => "Cette adresse courriel est invalide.", // message_emailnotvalid
+ 'emailNotFound' => "The email address you entered is not associated with any account.
If you forgot the email you registered your account with email ".CFG_CONTACT_EMAIL." for assistance.",
+ 'createAccSent' => "An email was sent to %s. Simply follow the instructions to create your account.",
+ 'recovUserSent' => "An email was sent to %s. Simply follow the instructions to recover your username.",
+ 'recovPassSent' => "An email was sent to %s. Simply follow the instructions to reset your password.",
+ 'accActivated' => 'Your account has been activated. Proceed to sign in',
+ 'userNotFound' => "The username you entered does not exists.",
+ 'wrongPass' => "That password is not vaild.",
+ 'accInactive' => "That account has not yet been confirmed active.",
+ 'loginExceeded' => "The maximum number of logins from this IP has been exceeded. Please try again in %s.",
+ 'signupExceeded'=> "The maximum number of signups from this IP has been exceeded. Please try again in %s.",
+ 'errNameLength' => "Votre nom d'utilisateur doit faire au moins 4 caractères de long.", // message_usernamemin
+ 'errNameChars' => "Votre nom d'utilisateur doit contenir seulement des lettres et des chiffres.", // message_usernamenotvalid
+ 'errPassLength' => "Votre mot de passe doit faire au moins 6 caractères de long.", // message_passwordmin
+ 'passMismatch' => "The passwords you entered do not match.",
+ 'nameInUse' => "That username is already taken.",
+ 'mailInUse' => "That email is already registered to an account.",
+ 'intError' => "An internal error occured.",
+ 'intError2' => "An internal error occured. (%s)",
+ 'isRecovering' => "This account is already recovering. Follow the instructions in your email or wait %s for the token to expire.",
+ 'passCheckFail' => "Les mots de passe ne correspondent pas.", // message_passwordsdonotmatch
+ 'newPassDiff' => "Votre nouveau mot de passe doit être différent de l'ancien." // message_newpassdifferent
+ ),
+ 'mail' => array(
+ 'tokenExpires' => "This token expires in %s.",
+ 'accConfirm' => ["Account Confirmation", "Welcome to ".CFG_NAME_SHORT."!\r\n\r\nClick the Link below to activate your account.\r\n\r\n".HOST_URL."?account=signup&token=%s\r\n\r\nIf you did not request this mail simply ignore it."],
+ 'recoverUser' => ["User Recovery", "Follow this link to log in.\r\n\r\n".HOST_URL."?account=signin&token=%s\r\n\r\nIf you did not request this mail simply ignore it."],
+ 'resetPass' => ["Password Reset", "Follow this link to reset your password.\r\n\r\n".HOST_URL."?account=forgotpassword&token=%s\r\n\r\nIf you did not request this mail simply ignore it."]
+ ),
'gameObject' => array(
'cat' => [0 => "Autre", 9 => "Livres", 3 => "Conteneurs", -5 => "Coffres", 25 => "Bancs de poissons", -3 => "Herbes", -4 => "Filons de minerai", -2 => "Quêtes", -6 => "Outils"],
'type' => [ 9 => "Livre", 3 => "Conteneur", -5 => "Coffre", 25 => "", -3 => "Herbe", -4 => "Filon de minerai", -2 => "Quête", -6 => ""],
diff --git a/localization/locale_ruru.php b/localization/locale_ruru.php
index 8536ef8a..02af784e 100644
--- a/localization/locale_ruru.php
+++ b/localization/locale_ruru.php
@@ -189,12 +189,14 @@ $lang = array(
'expansions' => array("World of Warcraft", "The Burning Crusade", "Wrath of the Lich King"),
'stats' => array("к силе", "к ловкости", "к выносливости", "к интеллекту", "к духу"),
'sources' => array(
- null, "Ремесло", "Добыча", "PvP", "Задание", "Продавец", "Тренер", "Открытие",
- "Рекламная акция", "Талант", "Начальное заклинание", "Мероприятие", "Достижение"
+ null, "Ремесло", "Добыча", "PvP", "Задание", "Продавец",
+ "Тренер", "Открытие", "Рекламная акция", "Талант", "Начальное заклинание", "Мероприятие",
+ "Достижение"
),
'languages' => array(
- 1 => "орочий", 2 => "дарнасский", 3 => "таурахэ", 6 => "дворфийский", 7 => "всеобщий", 8 => "язык демонов", 9 => "язык титанов", 10 => "талассийский",
- 11 => "драконий", 12 => "калимаг", 13 => "гномский", 14 => "язык троллей", 33 => "наречие нежити", 35 => "дренейский", 36 => "наречие зомби", 37 => "машинный гномский", 38 => "машинный гоблинский"
+ 1 => "орочий", 2 => "дарнасский", 3 => "таурахэ", 6 => "дворфийский", 7 => "всеобщий", 8 => "язык демонов",
+ 9 => "язык титанов", 10 => "талассийский", 11 => "драконий", 12 => "калимаг", 13 => "гномский", 14 => "язык троллей",
+ 33 => "наречие нежити", 35 => "дренейский", 36 => "наречие зомби", 37 => "машинный гномский", 38 => "машинный гоблинский"
),
'gl' => array(null, "Большой", "Малый"),
'si' => array(1 => "Альянс", -1 => "Альянс только", 2 => "Орда", -2 => "Орда только", null, 3 => "Обе"),
@@ -205,39 +207,119 @@ $lang = array(
'ra' => array(-2 => "Орда", -1 => "Альянс", "Обе", "Человек", "Орк", "Дворф", "Ночной эльф", "Нежить", "Таурен", "Гном", "Тролль", null, "Эльф крови", "Дреней"),
'rep' => array("Ненависть", "Враждебность", "Неприязнь", "Равнодушие", "Дружелюбие", "Уважение", "Почтение", "Превознесение"),
'st' => array(
- "По-умолчанию", "Облик кошки", "TОблик Древа жизни", "Походный облик", "Водный облик",
- "Облик медведя", null, null, "Облик лютого медведя", null,
- null, null, null, "Танец теней", null,
- null, "Призрачный волк", "Боевая стойка", "Оборонительная стойка", "Стойка берсерка",
- null, null, "Метаморфоза", null, null,
- null, null, "Облик стремительной птицы", "Облик Тьмы", "Облик птицы",
- "Незаметность", "Облик лунного совуха", "Дух воздаяния"
+ "По-умолчанию", "Облик кошки", "TОблик Древа жизни", "Походный облик", "Водный облик", "Облик медведя",
+ null, null, "Облик лютого медведя", null, null, null,
+ null, "Танец теней", null, null, "Призрачный волк", "Боевая стойка",
+ "Оборонительная стойка", "Стойка берсерка", null, null, "Метаморфоза", null,
+ null, null, null, "Облик стремительной птицы", "Облик Тьмы", "Облик птицы",
+ "Незаметность", "Облик лунного совуха", "Дух воздаяния"
),
'me' => array(
- null, "Подчинённый", "Дезориентирован", "Разоружённый", "Отвлечён", "Убегающий", "Неуклюжий", "Оплетён",
- "Немота", "В покое", "Усыплён", "Пойманный в ловушку", "Оглушен", "Замороженный", "Бездейственный", "Кровоточащий",
- "Целительное", "Превращён", "Изгнан", "Ограждён", "Скован", "Оседлавший", "Соблазнён", "Обращение",
- "Испуганный", "Неуязвимый", "Прервано", "Замедленный", "Открытие", "Неуязвимый", "Ошеломлён", "Исступление"
+ null, "Подчинённый", "Дезориентирован", "Разоружённый", "Отвлечён", "Убегающий",
+ "Неуклюжий", "Оплетён", "Немота", "В покое", "Усыплён", "Пойманный в ловушку",
+ "Оглушен", "Замороженный", "Бездейственный", "Кровоточащий", "Целительное", "Превращён",
+ "Изгнан", "Ограждён", "Скован", "Оседлавший", "Соблазнён", "Обращение",
+ "Испуганный", "Неуязвимый", "Прервано", "Замедленный", "Открытие", "Неуязвимый",
+ "Ошеломлён", "Исступление"
),
'ct' => array(
- "Разное", "Животное", "Дракон", "Демон", "Элементаль", "Великан", "Нежить", "Гуманоид",
- "Существо", "Механизм", "Не указано", "Тотем", "Спутник", "Облако газа"
+ "Разное", "Животное", "Дракон", "Демон", "Элементаль", "Великан",
+ "Нежить", "Гуманоид", "Существо", "Механизм", "Не указано", "Тотем",
+ "Спутник", "Облако газа"
),
'fa' => array(
- 1 => "Волк", 2 => "Кошка", 3 => "Паук", 4 => "Медведь", 5 => "Вепрь", 6 => "Кроколиск", 7 => "Падальщик", 8 => "Краб",
- 9 => "Горилла", 11 => "Ящер", 12 => "Долгоног", 20 => "Скорпид", 21 => "Черепаха", 24 => "Летучая мышь", 25 => "Гиена", 26 => "Сова",
- 27 => "Крылатый змей", 30 => "Дракондор", 31 => "Опустошитель", 32 => "Прыгуана", 33 => "Спороскат", 34 => "Скат Пустоты", 35 => "Змей", 37 => "Мотылек",
- 38 => "Химера", 39 => "Дьявозавр", 41 => "Силитид", 42 => "Червь", 43 => "Люторог", 44 => "Оса", 45 => "Гончая Недр", 46 => "Дух зверя"
+ 1 => "Волк", 2 => "Кошка", 3 => "Паук", 4 => "Медведь", 5 => "Вепрь", 6 => "Кроколиск",
+ 7 => "Падальщик", 8 => "Краб", 9 => "Горилла", 11 => "Ящер", 12 => "Долгоног", 20 => "Скорпид",
+ 21 => "Черепаха", 24 => "Летучая мышь", 25 => "Гиена", 26 => "Сова", 27 => "Крылатый змей", 30 => "Дракондор",
+ 31 => "Опустошитель", 32 => "Прыгуана", 33 => "Спороскат", 34 => "Скат Пустоты", 35 => "Змей", 37 => "Мотылек",
+ 38 => "Химера", 39 => "Дьявозавр", 41 => "Силитид", 42 => "Червь", 43 => "Люторог", 44 => "Оса",
+ 45 => "Гончая Недр", 46 => "Дух зверя"
),
'pvpRank' => array(
- null, "Private / Scout", "Corporal / Grunt",
- "Sergeant / Sergeant", "Master Sergeant / Senior Sergeant", "Sergeant Major / First Sergeant",
- "Knight / Stone Guard", "Knight-Lieutenant / Blood Guard", "Knight-Captain / Legionnare",
- "Knight-Champion / Centurion", "Lieutenant Commander / Champion", "Commander / Lieutenant General",
- "Marshal / General", "Field Marshal / Warlord", "Grand Marshal / High Warlord"
+ null, "Private / Scout", "Corporal / Grunt",
+ "Sergeant / Sergeant", "Master Sergeant / Senior Sergeant", "Sergeant Major / First Sergeant",
+ "Knight / Stone Guard", "Knight-Lieutenant / Blood Guard", "Knight-Captain / Legionnare",
+ "Knight-Champion / Centurion", "Lieutenant Commander / Champion", "Commander / Lieutenant General",
+ "Marshal / General", "Field Marshal / Warlord", "Grand Marshal / High Warlord"
),
),
- 'account' => [],
+ 'account' => array(
+ 'title' => "Учетная запись Aowow",
+ 'email' => "Email",
+ 'continue' => "Продолжить",
+ 'groups' => array(
+ -1 => "Нет", "Тестер", "Администратор", "Редактор", "Модератор", "Бюрократ",
+ "Разработчик", "VIP", "Блогер", "Учетная запись Премиум", "Переводчик", "Агент по продажам",
+ "Менеджер изображений", "Менеджер видео"
+ ),
+ // signIn
+ 'doSignIn' => "Войти в вашу учетную запись Aowow",
+ 'signIn' => "Вход",
+ 'user' => "Логин",
+ 'pass' => "Пароль",
+ 'rememberMe' => "Запомнить меня на этом компьютере",
+ 'forgot' => "Забыл",
+ 'forgotUser' => "Имя пользователя",
+ 'forgotPass' => "Пароль",
+ 'accCreate' => 'У вас еще нет учетной записи? Зарегистрируйтесь прямо сейчас!',
+
+ // recovery
+ 'recoverUser' => "Запрос имени пользователя",
+ 'recoverPass' => "Сброс пароля: Шаг %s из 2",
+ 'newPass' => "New Password",
+
+ // creation
+ 'register' => "Регистрация: Шаг %s из 2",
+
+ // dashboard
+ 'ipAddress' => "IP-Adress",
+ 'lastIP' => "last used IP",
+ 'joinDate' => "Joined",
+ 'lastLogin' => "Last visit",
+ 'userGroups' => "Role",
+ 'myAccount' => "My Account",
+ 'editAccount' => "Simply use the forms below to update your account information",
+ 'publicDesc' => "Public Description",
+ 'viewPubDesc' => 'View your Public Description in your Profile Page',
+
+ // bans
+ 'accBanned' => "This Account was closed",
+ 'bannedBy' => "Banned by",
+ 'ends' => "Ends on",
+ 'permanent' => "The ban is permanent",
+ 'reason' => "Reason",
+ 'noReason' => "No reason was given.",
+
+ // form-text
+ 'emailInvalid' => "Недопустимый адрес email.", // message_emailnotvalid
+ 'emailNotFound' => "The email address you entered is not associated with any account.
If you forgot the email you registered your account with email ".CFG_CONTACT_EMAIL." for assistance.",
+ 'createAccSent' => "An email was sent to %s. Simply follow the instructions to create your account.",
+ 'recovUserSent' => "An email was sent to %s. Simply follow the instructions to recover your username.",
+ 'recovPassSent' => "An email was sent to %s. Simply follow the instructions to reset your password.",
+ 'accActivated' => 'Your account has been activated. Proceed to sign in',
+ 'userNotFound' => "The username you entered does not exists.",
+ 'wrongPass' => "That password is not vaild.",
+ 'accInactive' => "That account has not yet been confirmed active.",
+ 'loginExceeded' => "The maximum number of logins from this IP has been exceeded. Please try again in %s.",
+ 'signupExceeded'=> "The maximum number of signups from this IP has been exceeded. Please try again in %s.",
+ 'errNameLength' => "Имя пользователя не должно быть короче 4 символов.", // message_usernamemin
+ 'errNameChars' => "Имя пользователя может содержать только буквы и цифры.", // message_usernamenotvalid
+ 'errPassLength' => "Ваш пароль должен состоять минимум из 6 знаков.", // message_passwordmin
+ 'passMismatch' => "The passwords you entered do not match.",
+ 'nameInUse' => "That username is already taken.",
+ 'mailInUse' => "That email is already registered to an account.",
+ 'intError' => "An internal error occured.",
+ 'intError2' => "An internal error occured. (%s)",
+ 'isRecovering' => "This account is already recovering. Follow the instructions in your email or wait %s for the token to expire.",
+ 'passCheckFail' => "Пароли не совпадают.", // message_passwordsdonotmatch
+ 'newPassDiff' => "Прежний и новый пароли не должны совпадать." // message_newpassdifferent
+ ),
+ 'mail' => array(
+ 'tokenExpires' => "This token expires in %s.",
+ 'accConfirm' => ["Account Confirmation", "Welcome to ".CFG_NAME_SHORT."!\r\n\r\nClick the Link below to activate your account.\r\n\r\n".HOST_URL."?account=signup&token=%s\r\n\r\nIf you did not request this mail simply ignore it."],
+ 'recoverUser' => ["User Recovery", "Follow this link to log in.\r\n\r\n".HOST_URL."?account=signin&token=%s\r\n\r\nIf you did not request this mail simply ignore it."],
+ 'resetPass' => ["Password Reset", "Follow this link to reset your password.\r\n\r\n".HOST_URL."?account=forgotpassword&token=%s\r\n\r\nIf you did not request this mail simply ignore it."]
+ ),
'gameObject' => array(
'cat' => [0 => "Другое", 9 => "Книги", 3 => "Контейнеры", -5 => "Сундуки", 25 => "Рыболовные лунки",-3 => "Травы", -4 => "Полезные ископаемые", -2 => "Задания", -6 => "Инструменты"],
'type' => [ 9 => "Книга", 3 => "Контейнер", -5 => "Сундук", 25 => "", -3 => "Растение", -4 => "Полезное ископаемое", -2 => "Задание", -6 => ""],
diff --git a/pages/account.php b/pages/account.php
index 0e584f9f..7b826a96 100644
--- a/pages/account.php
+++ b/pages/account.php
@@ -1,4 +1,9 @@
'activate_usernamelength',
@@ -18,342 +23,448 @@ enum(array( // AcctError
'ACCT_INTERNAL_ERROR' => 'internal_error',
));
-enum(array( // UserPropsLimits
- 'USERNAME_LENGTH_MIN' => 4,
- 'USERNAME_LENGTH_MAX' => 16,
- 'PASSWORD_LENGTH_MIN' => 6,
- 'PASSWORD_LENGTH_MAX' => 16,
-));
+message_emailnotvalid: "That email address is not valid.",
+message_newemaildifferent: "Your new email address must be different than your previous one.",
+message_newpassdifferent: "Your new password must be different than your previous one.",
+message_passwordmin: "Your password must be at least 6 characters long.",
+message_passwordsdonotmatch: "Passwords do not match.",
+message_usernamemin: "Your username must be at least 4 characters long.",
+message_usernamenotvalid: "Your username can only contain letters and numbers.",
+
*/
-function signin()
+// exclude & weightscales are handled as Ajax
+class AccountPage extends GenericPage
{
- if (!isset($_POST['username']) || !isset($_POST['password']))
- return Lang::$account['userNotFound'];
-
- $username = $_POST['username'];
- $password = $_POST['password'];
- $remember = $_POST['remember_me'] == 'yes';
-
- // handle login try limitation
- $ipBan = DB::Aowow()->selectRow('SELECT ip, count, UNIX_TIMESTAMP(unbanDate) as unbanDate FROM ?_account_bannedIPs WHERE type = 0 AND ip = ?',
- $_SERVER['REMOTE_ADDR']
+ protected $tpl = 'acc-dashboard';
+ protected $js = ['user.js', 'profile.js'];
+ protected $css = [['path' => 'Profiler.css']];
+ protected $mode = CACHETYPE_NONE;
+ protected $category = null;
+ protected $validCats = array(
+ 'signin' => [false],
+ 'signup' => [false],
+ 'signout' => [true],
+ 'forgotpassword' => [false],
+ 'forgotusername' => [false]
);
- if (!$ipBan) // no entry exists; set count to 1
- DB::Aowow()->query('INSERT INTO ?_account_bannedIPs VALUES (?, 0, 1, FROM_UNIXTIME(?))',
- $_SERVER['REMOTE_ADDR'],
- time() + CFG_FAILED_AUTH_EXCLUSION
- );
- else if ($ipBan['unbanDate'] < time()) // ip has accumulated counts but time expired; reset count to 1
- DB::Aowow()->query('INSERT IGNORE INTO ?_account_bannedIPs VALUES (?, 0, 1, ?)',
- $_SERVER['REMOTE_ADDR'],
- time() + CFG_FAILED_AUTH_EXCLUSION
- );
- else // entry already exists; increment count
- DB::Aowow()->query('UPDATE ?_account_bannedIPs SET count = count + 1, unbanDate = FROM_UNIXTIME(?) WHERE ip = ?',
- time() + CFG_FAILED_AUTH_EXCLUSION,
- $_SERVER['REMOTE_ADDR']
- );
+ protected $user = '';
+ protected $error = '';
+ protected $next = '';
- $id = DB::Aowow()->SelectCell('SELECT id FROM ?_account WHERE user = ?', $username);
- if (!$id)
- return Lang::$account['userNotFound'];
-
- User::init($id);
-
- switch (User::Auth($password))
+ public function __construct($pageCall, $pageParam)
{
- case AUTH_OK:
- DB::Aowow()->query('DELETE FROM ?_account_bannedIPs WHERE type = 0 AND ip = ?',
- $_SERVER['REMOTE_ADDR']
- );
- DB::Aowow()->query('UPDATE ?_account SET lastLogin = FROM_UNIXTIME(?), timeout = FROM_UNIXTIME(?) WHERE id = ?',
- time(),
- $remember ? 0 : time() + CFG_SESSION_TIMEOUT_DELAY,
- $id
- );
- User::writeCookie(); // overwrites the current user
- return;
- case AUTH_BANNED:
- User::writeCookie();
- return Lang::$account['userBanned'];
- case AUTH_WRONGPASS:
- User::destroy();
- return Lang::$account['wrongPass'];
- case AUTH_IPBANNED:
- User::destroy();
- return sprintf(Lang::$account['loginsExceeded'], round(CFG_FAILED_AUTH_EXCLUSION / 60));
- default:
- return;
- }
-}
+ if ($pageParam)
+ $this->category = [$pageParam];
-function signup()
-{
- global $smarty;
+ parent::__construct($pageCall, $pageParam);
-/*
- $username = Get(GET_STRING, 'username', 'POST');
- $password = Get(GET_STRING, 'password', 'POST');
- $pwd2 = Get(GET_STRING, 'password2', 'POST');
- $email = Get(GET_STRING, 'email', 'POST');
- $remember = Get(GET_BOOL, 'remember_me', 'POST');
-
- if($password != $pwd2)
+ if ($pageParam)
{
- $this->acct_error = ACCT_PASSWORDS_NOT_EQUAL;
- $this->type = 'signup';
- return;
- }
-
- // Check length
- if(strlen($username) > USERNAME_LENGTH_MAX || strlen($username) < USERNAME_LENGTH_MIN)
- {
- $this->acct_error = ACCT_USERNAME_LENGTH;
- $this->type = 'signup';
- return;
- }
- if(strlen($password) > PASSWORD_LENGTH_MAX || strlen($password) < PASSWORD_LENGTH_MIN)
- {
- $this->acct_error = ACCT_PASSWORD_LENGTH;
- $this->type = 'signup';
- return;
- }
-
- // Check symbols
- if(preg_match('/[^\w\d]/i', $username))
- {
- $this->acct_error = ACCT_USERNAME_SYMBOLS;
- $this->type = 'signup';
- return;
- }
- if(preg_match('/[^\w\d!"#\$%]/', $password))
- {
- $this->acct_error = ACCT_PASSWORD_SYMBOLS;
- $this->type = 'signup';
- return;
- }
- if(!preg_match('/^([a-z0-9._-]+)(\+[a-z0-9._-]+)?(@[a-z0-9.-]+\.[a-z]{2,4})$/i', $email))
- {
- $this->acct_error = ACCT_EMAIL_SYMBOLS;
- $this->type = 'signup';
- return;
- }
-
- // After 5 signup tries in a row,
- // or after a single successful signup,
- // the signup feature is blocked for 3 min
- // and the time is expanded to full-time block.
-
- DB::Realm()->Query('DELETE FROM account_ip_signup WHERE ip = ? AND time <= ?d', $_SERVER['REMOTE_ADDR'], time() - 3*MINUTE);
- DB::Realm()->Query('INSERT IGNORE INTO account_ip_signup (ip,time,tries) VALUES (?,?d,?d)', $_SERVER['REMOTE_ADDR'], time(), 0);
- $tries = DB::Realm()->SelectCell('SELECT tries FROM account_ip_signup WHERE ip = ?', $_SERVER['REMOTE_ADDR']);
- if($tries >= 5)
- {
- DB::Realm()->Query('UPDATE account_ip_signup SET time = ?d WHERE ip = ?', time(), $_SERVER['REMOTE_ADDR']);
- $this->acct_error = ACCT_SIGNUP_BLOCKED;
- $this->type = 'signup';
- return;
- }
- DB::Realm()->Query('UPDATE account_ip_signup SET tries = tries + 1 WHERE ip = ?', $_SERVER['REMOTE_ADDR']);
-
- $result = DB::Realm()->SelectCell('SELECT 1 FROM account WHERE username = ?', $username);
- if($result)
- {
- $this->acct_error = ACCT_USERNAME_EXISTS;
- $this->type = 'signup';
- return;
- }
-
- DB::Realm()->Query('UPDATE account_ip_signup SET tries = tries + 5 WHERE ip = ?', $_SERVER['REMOTE_ADDR']);
- $id = DB::Realm()->Query('
- INSERT INTO account (username,sha_pass_hash,email,joindate,expansion,last_ip)
- VALUES (?,?,?,NOW(),?d,?)
- ',
- strtoupper($username),
- $hash = AccountPage::CreateHash($username, $password),
- strtolower($email),
- 2,
- $_SERVER['REMOTE_ADDR']
- );
- if($id)
- {
- DB::Realm()->Query('UPDATE account_ip_signup SET tries = tries + 5 WHERE ip = ?', $_SERVER['REMOTE_ADDR']);
- DB::Realm()->Query('INSERT INTO account_aowow_extend (id,name) VALUES (?d,?)', $id, 'user-'.wn_create($id, WN_));
-
- $us = new User($id);
- if($us->Auth($hash) == AUTH_OK)
- $us->SetAuthCookies($remember);
- else
- {
- $this->acct_error = ACCT_INTERNAL_ERROR;
- $this->type = 'signin';
- return;
- }
- }
- else
- {
- $this->acct_error = ACCT_INTERNAL_ERROR;
- $this->type = 'signup';
- return;
- }
-*/
-
- // Account creation
- if (isset($_POST['username']) && isset($_POST['password']) && isset($_POST['c_password']) && CFG_ALLOW_REGISTER)
- {
- // password mismatch
- if ($_POST['password'] != $_POST['c_password'])
- $smarty->assign('signup_error', Lang::$account['passMismatch']);
- else
- {
- // AccName already in use
- if (DB::Aowow()->selectCell('SELECT 1 FROM aowow_account WHERE user = ? LIMIT 1', $_POST['username']))
- $smarty->assign('signup_error', Lang::$account['nameInUse']);
- else
- {
- $success = DB::Aowow()->query('INSERT INTO aowow_account (user, passHash, displayName, email, joindate, lastIP, locale) VALUES (?, ?, ?, ?, NOW(), ?, ?)',
- $_POST['username'],
- sha1(strtoupper($_POST['username']).':'.strtoupper($_POST['password'])),
- Util::ucFirst($_POST['username']),
- (isset($_POST['email']))? $_POST['email'] : '',
- (isset($_SERVER["REMOTE_ADDR"]))? $_SERVER["REMOTE_ADDR"] : '',
- 0
- );
- if ($success > 0)
- // all fine, send to login
- $_REQUEST['account']='signin';
- else
- // something went wrong
- $smarty->assign('signup_error', Lang::$account['unkError']);
- }
+ // requires auth && not authed
+ if ($this->validCats[$pageParam][0] && !User::$id)
+ $this->forwardToSignIn('account='.$pageParam);
+ // doesn't require auth && authed
+ else if (!$this->validCats[$pageParam][0] && User::$id)
+ header('Location: ?account'); // goto dashboard
}
}
-}
-function dashboard()
-{
- // cpmsg change pass messaeg class:failure|success, msg:blabla
-}
-
-function recoverPass()
-{
-}
-
-function recoverUser()
-{
-}
-
-$smarty->updatePageVars(array(
- 'reqCSS' => array(
- ['path' => STATIC_URL.'/css/Profiler.css'],
- ),
- 'reqJS' => array(
- STATIC_URL.'/js/user.js',
- STATIC_URL.'/js/profile.js',
- ),
-));
-
-$smarty->assign('lang', array_merge(Lang::$main, Lang::$account, ['colon' => Lang::$colon]));
-
-if (User::$id)
-{
- switch ($pageParam)
+ protected function generateContent()
{
- case 'exclude':
- // profiler completion exclude handler
- // $_POST['groups'] = bitMask of excludeGroupIds when using .. excludeGroups .. duh
- // should probably occur in g_user.excludegroups (dont forget to also set g_users.settings = {})
- die();
- break;
- case 'signout':
- User::destroy();
- $next = explode('?', $_SERVER['HTTP_REFERER']);
- $next = !empty($next[1]) ? '?'.$next[1] : '.';
- header('Location: '.$next);
- case 'weightscales':
- if (isset($_POST['save']))
- {
- if (!isset($_POST['id']))
+ if (!$this->category)
+ {
+ $this->createDashboard();
+ return;
+ }
+
+ switch ($this->category[0])
+ {
+ case 'forgotpassword':
+ if (CFG_AUTH_MODE != AUTH_MODE_SELF) // only recover own accounts
+ $this->error();
+
+ $this->tpl = 'acc-recover';
+ $this->resetPass = false;
+
+ if ($this->createRecoverPass($nStep)) // location-header after final step
+ header('Location: ?account=signin');
+
+ $this->head = sprintf(Lang::$account['recoverPass'], $nStep);
+ break;
+ case 'forgotusername':
+ if (CFG_AUTH_MODE != AUTH_MODE_SELF) // only recover own accounts
+ $this->error();
+
+ $this->tpl = 'acc-recover';
+ if (isset($_POST['email']))
{
- $res = DB::Aowow()->selectRow('SELECT max(id) as max, count(id) as num FROM ?_account_weightscales WHERE account = ?d', User::$id);
- if ($res['num'] < 5) // more or less hard-defined in LANG.message_weightscalesaveerror
- $_POST['id'] = ++$res['max'];
+ if (!Util::isValidEmail($_POST['email']))
+ $this->error = Lang::$account['emailInvalid'];
+ else if (!DB::Aowow()->selectCell('SELECT 1 FROM ?_account WHERE email = ?', $_POST['email']))
+ $this->error = Lang::$account['emailNotFound'];
+ else if ($err = $this->doRecoverUser($_POST['email']))
+ $this->error = $err;
else
- die('0');
+ $this->text = sprintf(Lang::$account['recovUserSent']. $_POST['email']);
}
- if (DB::Aowow()->query('REPLACE INTO ?_account_weightscales VALUES (?d, ?d, ?, ?)', intVal($_POST['id']), User::$id, $_POST['name'], $_POST['scale']))
- die((string)$_POST['id']);
+ $this->head = Lang::$account['recoverUser'];
+ break;
+ case 'signin':
+ $this->tpl = 'acc-signIn';
+ if (isset($_POST['username']) || isset($_POST['password']))
+ {
+ if ($err = $this->doSignIn())
+ $this->error = $err;
+ else
+ header('Location: '.$this->getNext(true));
+ }
+ else if (!empty($_GET['token']) && ($_ = DB::Aowow()->selectCell('SELECT user FROM ?_account WHERE status IN (?a) AND token = ? AND statusTimer > UNIX_TIMESTAMP()', [ACC_STATUS_RECOVER_USER, ACC_STATUS_OK], $_GET['token'])))
+ $this->user = $_;
+
+ break;
+ case 'signup':
+ if (!CFG_ALLOW_REGISTER || CFG_AUTH_MODE != AUTH_MODE_SELF)
+ $this->error();
+
+ $this->tpl = 'acc-signUp';
+ $nStep = 1;
+ if (isset($_POST['username']) || isset($_POST['password']) || isset($_POST['c_password']) || isset($_POST['email']))
+ {
+ if ($err = $this->doSignUp())
+ $this->error = $err;
+ else
+ {
+ $nStep = 1.5;
+ $this->text = sprintf(Lang::$account['createAccSent']. $_POST['email']);
+ }
+ }
+ else if (!empty($_GET['token']) && DB::Aowow()->query('SELECT 1 FROM ?_account WHERE status = ?d AND token = ?', ACC_STATUS_NEW, $_GET['token']))
+ {
+ $nStep = 2;
+ DB::Aowow()->query('UPDATE ?_account SET status = ?d WHERE token = ?', ACC_STATUS_OK, $_GET['token']);
+ DB::Aowow()->query('REPLACE INTO ?_account_bannedips (ip, type, count, unbanDate) VALUES (?, 1, ?d + 1, UNIX_TIMESTAMP() + ?d)', $_SERVER['REMOTE_ADDR'], CFG_FAILED_AUTH_COUNT, CFG_FAILED_AUTH_EXCLUSION);
+ $this->text = sprintf(Lang::$account['accActivated'], $_GET['token']);
+ }
else
- die('0');
- }
- else if (isset($_POST['delete']) && isset($_POST['id']) && User::$id)
- DB::Aowow()->query('DELETE FROM ?_account_weightscales WHERE id = ?d AND account = ?d', intVal($_POST['id']), User::$id);
- else
- die('0');
+ $this->next = $this->getNext();
- break;
- case '';
- dashboard();
- $smarty->display('dashboard.tpl');
- break;
- default:
- $smarty->error();
+ $this->head = sprintf(Lang::$account['register'], $nStep);
+ break;
+ case 'signout':
+ User::destroy();
+ default:
+ header('Location: '.$this->getNext(true));
+ break;
+ }
}
-}
-else
-{
- switch ($pageParam)
+
+ protected function generateTitle()
{
- case 'signin_do':
- $error = signin();
- if ($error)
- $smarty->assign('signinError', $error);
- else
- header('Location: '.$_GET['next']);
- case 'signin':
- if (!isset($_GET['next']))
- {
- $next = isset($_SERVER['HTTP_REFERER']) ? explode('?', $_SERVER['HTTP_REFERER']) : '.';
- $smarty->assign('next', isset($next[1]) ? '?'.$next[1] : '.');
- }
- else
- $smarty->assign('next', $_GET['next']);
+ $this->title = [Lang::$account['title']];
+ }
- $smarty->assign('register', CFG_ALLOW_REGISTER);
- $smarty->display('signin.tpl');
- break;
- case 'signup_do':
- $error = signup();
- if ($error)
- $smarty->assign('signupError', $error);
+ protected function generatePath() { }
+
+ private function createDashboard()
+ {
+ if (!User::$id)
+ $this->forwardToSignIn('account');
+
+ $user = DB::Aowow()->selectRow('SELECT * FROM ?_account WHERE id = ?d', User::$id);
+ $bans = DB::Aowow()->select('SELECT ab.*, a.displayName, ab.id AS ARRAY_KEY FROM ?_account_banned ab LEFT JOIN ?_account a ON a.id = ab.staffId WHERE ab.userId = ?d', User::$id);
+
+ /***********/
+ /* Infobox */
+ /***********/
+
+ $infobox = [];
+ $infobox[] = Lang::$account['joinDate']. Lang::$main['colon'].'[tooltip name=joinDate]'. date('l, G:i:s', $user['joinDate']). '[/tooltip][span class=tip tooltip=joinDate]'. date(Lang::$main['dateFmtShort'], $user['joinDate']). '[/span]';
+ $infobox[] = Lang::$account['lastLogin'].Lang::$main['colon'].'[tooltip name=lastLogin]'.date('l, G:i:s', $user['prevLogin']).'[/tooltip][span class=tip tooltip=lastLogin]'.date(Lang::$main['dateFmtShort'], $user['prevLogin']).'[/span]';
+ $infobox[] = Lang::$account['lastIP']. Lang::$main['colon'].$user['prevIP'];
+ $infobox[] = Lang::$account['email']. Lang::$main['colon'].$user['email'];
+
+ $groups = [];
+ foreach (Lang::$account['groups'] as $idx => $key)
+ if ($idx >= 0 && $user['userGroups'] & (1 << $idx))
+ $groups[] = (!fMod(count($groups) + 1, 3) ? '[br]' : null).Lang::$account['groups'][$idx];
+
+ $infobox[] = Lang::$account['userGroups'].Lang::$main['colon'].($groups ? implode(', ', $groups) : Lang::$account['groups'][-1]);
+
+ $this->infobox = '[ul][li]'.implode('[/li][li]', $infobox).'[/li][/ul]';
+
+ /*************/
+ /* Ban Popup */
+ /*************/
+
+ $this->banned = [];
+ foreach ($bans as $b)
+ {
+ if (!($b['typeMask'] & (ACC_BAN_TEMP | ACC_BAN_PERM)) || ($b['end'] && $b['end'] <= time()))
+ continue;
+
+ $this->banned = array(
+ 'by' => [$b['staffId'], $b['displayName']],
+ 'end' => $b['end'],
+ 'reason' => $b['reason']
+ );
+
+ break; // one is enough
+ }
+
+ /************/
+ /* Listview */
+ /************/
+
+ // claimed characters
+ // profiles
+ // own screenshots
+ // own videos
+ // own comments (preview)
+ // articles guides..?
+
+ $this->lvData = [];
+
+ // cpmsg change pass messaeg class:failure|success, msg:blabla
+ }
+
+ private function createRecoverPass(&$step)
+ {
+ $step = 1;
+
+ if (isset($_POST['email'])) // step 1
+ {
+ if (!Util::isValidEmail($_POST['email']))
+ $this->error = Lang::$account['emailInvalid'];
+ else if (!DB::Aowow()->selectCell('SELECT 1 FROM ?_account WHERE email = ?', $_POST['email']))
+ $this->error = Lang::$account['emailNotFound'];
+ else if ($err = $this->doRecoverPass($_POST['email']))
+ $this->error = $err;
else
- header('Location: '.$_GET['next']);
- break;
- case 'signup':
- if (!isset($_GET['next']))
{
- $next = isset($_SERVER['HTTP_REFERER']) ? explode('?', $_SERVER['HTTP_REFERER']) : '.';
- $smarty->assign('next', isset($next[1]) ? '?'.$next[1] : '.');
+ $step = 1.5;
+ $this->text = sprintf(Lang::$account['recovPassSent'], $_POST['email']);
}
+ }
+ else if (isset($_GET['token'])) // step 2
+ {
+ $step = 2;
+ $this->resetPass = true;
+ $this->token = $_GET['token'];
+ }
+ else if (isset($_POST['token']) && isset($_POST['email']) && isset($_POST['password']) && isset($_POST['c_password']))
+ {
+ $step = 2;
+ $this->resetPass = true;
+ $this->token = $_GET['token']; // insecure source .. that sucks; but whats the worst that could happen .. this account cannot be recovered for some minutes
+
+ if ($err = $this->doResetPass())
+ $this->error = $err;
else
- $smarty->assign('next', $_GET['next']);
- $smarty->display('signup.tpl');
- break;
- case 'forgotpassword':
- recoverPass();
- $smarty->display('recoverPass.tpl');
- break;
- case 'forgotusername':
- recoverUser();
- $smarty->display('recoverUser.tpl');
- break;
- default:
- header('Location: '.($_GET['next'] ? $_GET['next'] : '.'));
- break;
+ return true;
+ }
+
+ return false;
+ }
+
+ private function doSignIn()
+ {
+ if (!isset($_POST['username']) || !isset($_POST['password']))
+ return Lang::$account['userNotFound'];
+
+ $username = $_POST['username'];
+ $password = $_POST['password'];
+ $doExpire = $_POST['remember_me'] != 'yes';
+
+ switch (User::Auth($username, $password))
+ {
+ case AUTH_OK:
+ // reset account status, update expiration
+ DB::Aowow()->query('UPDATE ?_account SET prevLogin = curLogin, curLogin = UNIX_TIMESTAMP(), prevIP = curIP, curIP = ?, allowExpire = ?d, status = 0, statusTimer = 0, token = "" WHERE user = ?',
+ $_SERVER['REMOTE_ADDR'],
+ $doExpire,
+ $username
+ );
+ if (User::init())
+ User::save(); // overwrites the current user
+ return;
+ case AUTH_BANNED:
+ if (User::init())
+ User::save();
+ return Lang::$account['accBanned'];
+ case AUTH_WRONGUSER:
+ User::destroy();
+ return Lang::$account['userNotFound'];
+ case AUTH_WRONGPASS:
+ User::destroy();
+ return Lang::$account['wrongPass'];
+ case AUTH_ACC_INACTIVE:
+ User::destroy();
+ return Lang::$account['accInactive'];
+ case AUTH_IPBANNED:
+ User::destroy();
+ return sprintf(Lang::$account['loginExceeded'], Util::formatTime(CFG_FAILED_AUTH_EXCLUSION * 1000));
+ default:
+ return;
+ }
+ }
+
+ private function doSignUp()
+ {
+ $username = @$_POST['username'];
+ $password = @$_POST['password'];
+ $cPassword = @$_POST['c_password'];
+ $email = @$_POST['email'];
+ $doExpire = @$_POST['remember_me'] != 'yes';
+
+ // check username
+ if (strlen($username) > 4 || strlen($username) < 16)
+ return Lang::$account['errNameLength'];
+
+ if (preg_match('/[^\w\d]/i', $username))
+ return Lang::$account['errNameChars'];
+
+ // check password
+ if (strlen($password) > 6 || strlen($password) < 16)
+ return Lang::$account['errPassLength'];
+
+ // if (preg_match('/[^\w\d!"#\$%]/', $password)) // such things exist..? :o
+ // return Lang::$account['errPassChars'];
+
+ if ($password != $cPassword)
+ return Lang::$account['passMismatch'];
+
+ // check email
+ if (!Util::isValidEmail($email))
+ return Lang::$account['emailInvalid'];
+
+ // limit account creation
+ $ip = DB::Aowow()->selectRow('SELECT ip, count, unbanDate FROM ?_account_bannedIPs WHERE type = 1 AND ip = ?', $_SERVER['REMOTE_ADDR']);
+ if ($ip && $ip['count'] >= CFG_FAILED_AUTH_COUNT && $ip['unbanDate'] >= time())
+ {
+ DB::Aowow()->query('UPDATE ?_account_bannedips SET count = count + 1, unbanDate = UNIX_TIMESTAMP() + ?d WHERE ip = ? AND type = 1', CFG_FAILED_AUTH_EXCLUSION, $_SERVER['REMOTE_ADDR']);
+ return sprintf(Lang::$account['signupExceeded'], Util::formatTime(CFG_FAILED_AUTH_EXCLUSION * 1000));
+ }
+
+ // username taken
+ if ($_ = DB::Aowow()->SelectCell('SELECT user FROM ?_account WHERE (user = ? OR email = ?) AND (status <> ?d OR (status = ?d AND statusTimer > UNIX_TIMESTAMP()))', $username, $email, ACC_STATUS_NEW, ACC_STATUS_NEW))
+ return $_ == $username ? Lang::$account['nameInUse'] : Lang::$account['mailInUse'];
+
+ // create..
+ $token = Util::createHash();
+ $delay = 7 * DAY;
+ $id = DB::Aowow()->query('INSERT INTO ?_account (user, passHash, displayName, email, joindate, curIP, allowExpire, locale, status, statusTimer, token) VALUES (?, ?, ?, ?, UNIX_TIMESTAMP(), ?, ?d, ?d, ?d, UNIX_TIMESTAMP() + ?d, ?)',
+ $username,
+ User::hashCrypt($_POST['password']),
+ Util::ucFirst($username),
+ $email,
+ isset($_SERVER["REMOTE_ADDR"]) ? $_SERVER["REMOTE_ADDR"] : '',
+ $doExpire,
+ User::$localeId,
+ ACC_STATUS_NEW,
+ $delay,
+ $token
+ );
+ if (!$id) // something went wrong
+ return Lang::$account['intError'];
+ else if ($_ = $this->sendMail($email, Lang::$mail['accConfirm'][0], sprintf(Lang::$mail['accConfirm'][1], $token), $delay))
+ {
+ // success:: update ip-bans
+ if (!$ip || $ip['unbanDate'] < time())
+ DB::Aowow()->query('REPLACE INTO ?_account_bannedips (ip, type, count, unbanDate) VALUES (?, 1, 1, UNIX_TIMESTAMP() + ?d)', $_SERVER['REMOTE_ADDR'], CFG_FAILED_AUTH_EXCLUSION);
+ else
+ DB::Aowow()->query('UPDATE ?_account_bannedips SET count = count + 1, unbanDate = UNIX_TIMESTAMP() + ?d WHERE ip = ? AND type = 1', CFG_FAILED_AUTH_EXCLUSION, $_SERVER['REMOTE_ADDR']);
+
+ return $_;
+ }
+ }
+
+ private function doRecoverPass($target)
+ {
+ $delay = 5 * MINUTE;
+ if ($_ = $this->initRecovery(ACC_STATUS_RECOVER_PASS, $target, $delay, $token))
+ return $_;
+
+ // send recovery mail
+ return $this->sendMail($target, Lang::$mail['resetPass'][0], sprintf(Lang::$mail['resetPass'][1], $token), $delay);
+ }
+
+ private function doResetPass()
+ {
+ $token = $_POST['token'];
+ $email = $_POST['email'];
+ $pass = $_POST['password'];
+ $cPass = $_POST['c_password'];
+
+ if ($pass != $cPass)
+ return Lang::$account['passCheckFail'];
+
+ $uRow = DB::Aowow()->selectRow('SELECT id, user, passHash FROM ?_account WHERE token = ? AND email = ? AND status = ?d AND statusTimer > UNIX_TIMESTAMP()', $token, $email, ACC_STATUS_RECOVER_PASS);
+ if (!$uRow)
+ return Lang::$account['emailNotFound']; // assume they didn't meddle with the token
+
+ if (!User::verifyCrypt($newPass))
+ return Lang::$account['newPassDiff'];
+
+ if (!DB::Aowow()->query('UPDATE ?_account SET passHash = ?, status = ?d WHERE id = ?d', User::hashcrypt($newPass), ACC_STATUS_OK, $uRow['id']))
+ return Lang::$account['intError'];
+ }
+
+ private function doRecoverUser($target)
+ {
+ $delay = 5 * MINUTE;
+ if ($_ = $this->initRecovery(ACC_STATUS_RECOVER_USER, $target, $delay, $token))
+ return $_;
+
+ // send recovery mail
+ return $this->sendMail($target, Lang::$mail['recoverUser'][0], sprintf(Lang::$mail['recoverUser'][1], $token), $delay);
+ }
+
+ private function initRecovery($type, $target, $delay, &$token)
+ {
+ if (!$type)
+ return Lang::$account['intError'];
+
+ // check if already processing
+ if ($_ = DB::Aowow()->selectCell('SELECT statusTimer - UNIX_TIMESTAMP() FROM ?_account WHERE email = ? AND status <> ?d AND statusTimer > UNIX_TIMESTAMP()', $target, ACC_STATUS_OK))
+ return sprintf(lang::$account['isRecovering'], Util::formatTime($_));
+
+ // create new token and write to db
+ $token = Util::createHash();
+ if (!DB::Aowow()->query('UPDATE ?_account SET token = ?, status = ?d, statusTimer = UNIX_TIMESTAMP() + ?d WHERE email = ?', $token, $type, $delay, $target))
+ return Lang::$account['intError'];
+ }
+
+ private function sendMail($target, $subj, $msg, $delay = 300)
+ {
+ // send recovery mail
+ $subj = CFG_NAME_SHORT.Lang::$main['colon'] . $subj;
+ $msg .= "\r\n\r\n".sprintf(Lang::$mail['tokenExpires'], Util::formatTime($delay * 1000))."\r\n";
+ $header = 'From: '.CFG_CONTACT_EMAIL . "\r\n" .
+ 'Reply-To: '.CFG_CONTACT_EMAIL . "\r\n" .
+ 'X-Mailer: PHP/' . phpversion();
+
+ if (!mail($target, $subj, $msg, $header))
+ return sprintf(Lang::$account['intError2'], 'send mail');
+ }
+
+ private function getNext($forHeader = false)
+ {
+ $next = $forHeader ? '.' : '';
+ if (isset($_GET['next']))
+ $next = $_GET['next'];
+ else if (isset($_SERVER['HTTP_REFERER']) && strstr($_SERVER['HTTP_REFERER'], '?'))
+ $next = explode('?', $_SERVER['HTTP_REFERER'])[1];
+
+ if ($forHeader && !$next)
+ $next = '.';
+
+ return ($forHeader && $next != '.' ? '?' : '').$next;
}
}
+
+
?>
diff --git a/includes/genericPage.class.php b/pages/genericPage.class.php
similarity index 98%
rename from includes/genericPage.class.php
rename to pages/genericPage.class.php
index 99a5c2e8..11679e3a 100644
--- a/includes/genericPage.class.php
+++ b/pages/genericPage.class.php
@@ -81,11 +81,6 @@ class GenericPage
if ($this->restrictedGroups && !User::isInGroup($this->restrictedGroups))
$this->error();
- if (CFG_MAINTENANCE && !User::isInGroup(U_GROUP_EMPLOYEE))
- $this->maintenance();
- else if (CFG_MAINTENANCE && User::isInGroup(U_GROUP_EMPLOYEE))
- Util::addNote(U_GROUP_EMPLOYEE, 'Maintenance mode enabled!');
-
// display modes
if (isset($_GET['power']) && method_exists($this, 'generateTooltip'))
$this->mode = CACHETYPE_TOOLTIP;
@@ -102,6 +97,11 @@ class GenericPage
if (!$this->isValidPage() || !$this->tpl)
$this->error();
}
+
+ if (CFG_MAINTENANCE && !User::isInGroup(U_GROUP_EMPLOYEE))
+ $this->maintenance();
+ else if (CFG_MAINTENANCE && User::isInGroup(U_GROUP_EMPLOYEE))
+ Util::addNote(U_GROUP_EMPLOYEE, 'Maintenance mode enabled!');
}
/**********/
@@ -311,6 +311,12 @@ class GenericPage
$this->category = $params;
}
+ protected function forwardToSignIn($next = '')
+ {
+ $next = $next ? '&next='.$next : '';
+ header('Location: ?account=signin'.$next);
+ }
+
/*******************/
/* Special Display */
/*******************/
@@ -351,6 +357,8 @@ class GenericPage
public function display($override = '') // load given template string or GenericPage::$tpl
{
+ session_regenerate_id(true); // can only reagenerate for real pages, otherwise a simple tooltip would be fatal for the session
+
if ($override)
{
$this->addAnnouncements();
@@ -562,7 +570,7 @@ class GenericPage
catch (ReflectionException $e) { } // shut up!
}
- $data .= serialize($cache);
+ $data .= gzcompress(serialize($cache), 9);
}
else
$data .= (string)$saveString;
@@ -594,7 +602,7 @@ class GenericPage
if ($type == '0')
{
- $data = unserialize($cache[1]);
+ $data = unserialize(gzuncompress($cache[1]));
foreach ($data as $k => $v)
$this->$k = $v;
diff --git a/pages/item.php b/pages/item.php
index eca518dd..d4c33b72 100644
--- a/pages/item.php
+++ b/pages/item.php
@@ -66,8 +66,11 @@ class ItemPage extends genericPage
$this->name = $this->subject->getField('name', true);
- $jsg = $this->subject->getJSGlobals(GLOBALINFO_EXTRA | GLOBALINFO_SELF, $extra);
- $this->extendGlobalData($jsg, $extra);
+ if ($this->mode == CACHETYPE_PAGE)
+ {
+ $jsg = $this->subject->getJSGlobals(GLOBALINFO_EXTRA | GLOBALINFO_SELF, $extra);
+ $this->extendGlobalData($jsg, $extra);
+ }
}
protected function generatePath()
@@ -918,7 +921,7 @@ class ItemPage extends genericPage
{
$itemString = $this->typeId;
foreach ($this->enhancedTT as $k => $val)
- $itemString .= $k.(is_array($val) ? implode(':', $val) : $val);
+ $itemString .= $k.(is_array($val) ? implode(',', $val) : $val);
if ($asError)
return '$WowheadPower.registerItem(\''.$itemString.'\', '.User::$localeId.', {})';
diff --git a/pages/miscTools.php b/pages/miscTools.php
deleted file mode 100644
index d5ce31a7..00000000
--- a/pages/miscTools.php
+++ /dev/null
@@ -1,164 +0,0 @@
-getRandomId();
-
- header('Location: ?'.Util::$typeStrings[$type].'='.$typeId);
- die();
- case 'latest-comments':
- $menu = 2;
- $lv = array(
- array(
- 'file' => 'commentpreview',
- 'data' => [],
- 'params' => []
- )
- );
- break;
- case 'latest-screenshots':
- $menu = 3;
- $lv[] = array(
- 'file' => 'screenshot',
- 'data' => [],
- 'params' => []
- );
- break;
- case 'latest-videos':
- $menu = 11;
- $lv[] = array(
- 'file' => 'video',
- 'data' => [],
- 'params' => []
- );
- break;
- case 'latest-articles':
- $menu = 1;
- $lv = [];
- break;
- case 'latest-additions':
- $menu = 0;
- $extraText = '';
- break;
- case 'unrated-comments':
- $menu = 5;
- $lv[] = array(
- 'file' => 'commentpreview',
- 'data' => [],
- 'params' => []
- );
- break;
- case 'missing-screenshots':
- $menu = 13;
- $cnd = [[['cuFlags', CUSTOM_HAS_SCREENSHOT, '&'], 0]];
-
- if (!User::isInGroup(U_GROUP_STAFF))
- $cnd[] = [['cuFlags', CUSTOM_EXCLUDE_FOR_LISTVIEW, '&'], 0];
-
- foreach (Util::$typeClasses as $classStr)
- {
- $typeObj = new $classStr($cnd);
- if (!$typeObj->error)
- {
- $typeObj->addGlobalsToJScript(GLOBALINFO_SELF | GLOBALINFO_RELATED);
-
- $lv[] = array(
- 'file' => (new ReflectionProperty($typeObj, 'brickFile'))->getValue(),
- 'data' => $typeObj->getListviewData(),
- 'params' => ['tabs' => '$myTabs']
- );
- }
- }
- break;
- case 'most-comments':
- if ($pageParam && !in_array($pageParam, [1, 7, 30]))
- header('Location: ?most-comments=1'.($_rss ? '&rss' : null));
-
- if (in_array($pageParam, [7, 30]))
- {
- $subMenu = $pageParam;
- $_title = sprintf(Lang::$main['mostComments'][1], $pageParam);
- }
- else
- {
- $subMenu = 1;
- $_title = Lang::$main['mostComments'][0];
- }
-
- $menu = 12;
- $lv[] = array(
- 'file' => 'commentpreview',
- 'data' => [],
- 'params' => []
- );
- break;
- default:
- $smarty->error();
-}
-
-if (strstr($pageCall, 'latest') || $pageCall == 'most-comments')
-{
- if ($_rss)
- {
- header("Content-Type: application/rss+xml; charset=ISO-8859-1");
-
- $xml = "\n".
- "\n\t\n".
- "\t\t".CFG_NAME_SHORT.' - '.Lang::$main['utilities'][$menu] . ($_title ? Lang::$colon . $_title : null)."\n".
- "\t\t".HOST_URL.'?'.$pageCall . ($pageParam ? '='.$pageParam : null)."\n".
- "\t\t".CFG_NAME."\n".
- "\t\t".implode('-', str_split(User::$localeString, 2))."\n".
- "\t\t".CFG_TTL_RSS."\n".
- // Sat, 31 Aug 2013 15:33:16 -0500
- "\t\n";
-
- /*
- generate 's here
- */
-
- $xml .= '';
-
- die($xml);
- }
- else
- $h1Links = ''.Lang::$main['subscribe'].'';
-}
-
-array_push($_path, $menu);
-if ($subMenu)
- array_push($_path, $subMenu);
-
-
-// menuId 8: Utilities g_initPath()
-// tabId 1: Tools g_initHeader()
-$smarty->updatePageVars(array(
- 'name' => Lang::$main['utilities'][$menu] . ($_title ? Lang::$colon . $_title : null),
- 'h1Links' => $h1Links,
- 'title' => Lang::$main['utilities'][$menu] . ($_title ? ' - ' . $_title : null),
- 'path' => json_encode($_path, JSON_NUMERIC_CHECK),
- 'tab' => 1
-));
-$smarty->assign('lang', Lang::$main);
-$smarty->assign('lvData', $lv);
-
-// load the page
-$smarty->display('list-page-generic.tpl');
-
-?>
diff --git a/pages/more.php b/pages/more.php
index 0b31d34c..dfc082bb 100644
--- a/pages/more.php
+++ b/pages/more.php
@@ -40,8 +40,7 @@ class MorePage extends GenericPage
if (($_[1] = array_search($subPage, $this->subPages[$_[0]])) === false)
$this->error();
- // ye.. hack .. can for some reason not be defined in the array itself
- if ($page == 'help')
+ if ($page == 'help') // ye.. hack .. class definitions only allow static values
$_[2] = Lang::$main['helpTopics'][$_[1]];
}
$this->type = $_[0];
diff --git a/pages/utility.php b/pages/utility.php
new file mode 100644
index 00000000..2e9f1244
--- /dev/null
+++ b/pages/utility.php
@@ -0,0 +1,185 @@
+ 'latest-videos', 12 => 'most-comments', 13 => 'missing-screenshots'
+ );
+ private $page = '';
+ private $rss = false;
+
+ public function __construct($pageCall, $pageParam)
+ {
+ $this->getCategoryFromUrl($pageParam);
+
+ parent::__construct($pageCall, $pageParam);
+
+ $this->page = $pageCall;
+ $this->rss = isset($_GET['rss']);
+ $this->name = Lang::$main['utilities'][array_search($pageCall, $this->validPages)];
+
+ if ($this->page == 'most-comments')
+ {
+ if ($this->category && in_array($this->category[0], [7, 30]))
+ $this->name .= Lang::$main['colon'] . sprintf(Lang::$main['mostComments'][1], $this->category[0]);
+ else
+ $this->name .= Lang::$main['colon'] . Lang::$main['mostComments'][0];
+ }
+ }
+
+ public function display($override = '')
+ {
+ if ($this->rss) // this should not be cached
+ {
+ header('Content-Type: application/rss+xml; charset=ISO-8859-1');
+ die($this->generateRSS());
+ }
+ else
+ return parent::display($override);
+ }
+
+ protected function generateContent()
+ {
+ /****************/
+ /* Main Content */
+ /****************/
+
+ if (in_array(array_search($this->page, $this->validPages), [0, 1, 2, 3, 11, 12]))
+ $this->h1Links = ''.Lang::$main['subscribe'].'';
+
+ switch ($this->page)
+ {
+ case 'random':
+ $type = array_rand(array_filter(Util::$typeStrings));
+ $typeId = (new Util::$typeClasses[$type](null))->getRandomId();
+
+ header('Location: ?'.Util::$typeStrings[$type].'='.$typeId);
+ die();
+ case 'latest-comments':
+ $this->lvData[] = array(
+ 'file' => 'commentpreview',
+ 'data' => [],
+ 'params' => []
+ );
+ break;
+ case 'latest-screenshots':
+ $this->lvData[] = array(
+ 'file' => 'screenshot',
+ 'data' => [],
+ 'params' => []
+ );
+ break;
+ case 'latest-videos':
+ $this->lvData[] = array(
+ 'file' => 'video',
+ 'data' => [],
+ 'params' => []
+ );
+ break;
+ case 'latest-articles':
+ $this->lvData = [];
+ break;
+ case 'latest-additions':
+ $extraText = '';
+ break;
+ case 'unrated-comments':
+ $this->lvData[] = array(
+ 'file' => 'commentpreview',
+ 'data' => [],
+ 'params' => []
+ );
+ break;
+ case 'missing-screenshots':
+ $cnd = [[['cuFlags', CUSTOM_HAS_SCREENSHOT, '&'], 0]];
+
+ if (!User::isInGroup(U_GROUP_EMPLOYEE))
+ $cnd[] = [['cuFlags', CUSTOM_EXCLUDE_FOR_LISTVIEW, '&'], 0];
+
+ foreach (Util::$typeClasses as $classStr)
+ {
+ if (!$classStr)
+ continue;
+
+ $typeObj = new $classStr($cnd);
+ if (!$typeObj->error)
+ {
+ $this->extendGlobalData($typeObj->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED | GLOBALINFO_REWARDS));
+ $this->lvData[] = array(
+ 'file' => $typeObj::$brickFile,
+ 'data' => $typeObj->getListviewData(),
+ 'params' => ['tabs' => '$myTabs']
+ );
+ }
+ }
+ break;
+ case 'most-comments':
+ if ($this->category && !in_array($this->category[0], [1, 7, 30]))
+ header('Location: ?most-comments=1'.($this->rss ? '&rss' : null));
+
+ $this->lvData[] = array(
+ 'file' => 'commentpreview',
+ 'data' => [],
+ 'params' => []
+ );
+ break;
+ }
+ }
+
+ protected function generateRSS()
+ {
+ $xml = "\n".
+ "\n\t\n".
+ "\t\t".CFG_NAME_SHORT.' - '.$this->name."\n".
+ "\t\t".HOST_URL.'?'.$this->page . ($this->category ? '='.$this->category[0] : null)."\n".
+ "\t\t".CFG_NAME."\n".
+ "\t\t".implode('-', str_split(User::$localeString, 2))."\n".
+ "\t\t".CFG_TTL_RSS."\n".
+ "\t\t".date(DATE_RSS)."\n".
+ "\t\n";
+
+ # generate 's here
+
+ $xml .= '';
+
+ return $xml;
+ }
+
+ protected function generateTitle()
+ {
+ if ($this->page == 'most-comments')
+ {
+ if ($this->category && in_array($this->category[0], [7, 30]))
+ array_unshift($this->title, sprintf(Lang::$main['mostComments'][1], $this->category[0]));
+ else
+ array_unshift($this->title, Lang::$main['mostComments'][0]);
+ }
+
+ array_unshift($this->title, Lang::$main['utilities'][array_search($this->page, $this->validPages)]);
+ }
+
+ protected function generatePath()
+ {
+ $this->path[] = array_search($this->page, $this->validPages);
+
+ if ($this->page == 'most-comments')
+ {
+ if ($this->category && in_array($this->category[0], [7, 30]))
+ $this->path[] = $this->category[0];
+ else
+ $this->path[] = 1;
+ }
+ }
+}
+
+?>
diff --git a/setup/u1_account.sql b/setup/u1_account.sql
new file mode 100644
index 00000000..4e78a2a2
--- /dev/null
+++ b/setup/u1_account.sql
@@ -0,0 +1,82 @@
+-- --------------------------------------------------------
+-- Host: 127.0.0.1
+-- Server Version: 5.6.16 - MySQL Community Server (GPL)
+-- Server Betriebssystem: Win32
+-- HeidiSQL Version: 8.3.0.4792
+-- --------------------------------------------------------
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET NAMES utf8 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+
+-- Exportiere Struktur von Tabelle world.aowow_account
+DROP TABLE IF EXISTS `aowow_account`;
+CREATE TABLE IF NOT EXISTS `aowow_account` (
+ `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `extId` int(10) unsigned NOT NULL COMMENT 'external user id',
+ `user` varchar(64) NOT NULL COMMENT 'login',
+ `passHash` varchar(128) NOT NULL,
+ `displayName` varchar(64) NOT NULL COMMENT 'nickname',
+ `email` varchar(64) NOT NULL,
+ `joinDate` int(10) unsigned NOT NULL COMMENT 'unixtime',
+ `allowExpire` tinyint(1) unsigned NOT NULL,
+ `curIP` varchar(15) NOT NULL,
+ `prevIP` varchar(15) NOT NULL,
+ `curLogin` int(10) unsigned NOT NULL COMMENT 'unixtime',
+ `prevLogin` int(10) unsigned NOT NULL,
+ `locale` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT '0,2,3,6,8',
+ `userGroups` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'bitmask',
+ `avatar` varchar(16) NOT NULL COMMENT 'icon-string for internal or id for upload',
+ `description` text NOT NULL COMMENT 'markdown formated',
+ `userPerms` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT 'bool isAdmin',
+ `status` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT 'flag, see defines',
+ `statusTimer` int(10) unsigned NOT NULL DEFAULT '0',
+ `token` varchar(40) NOT NULL COMMENT 'creation & recovery',
+ PRIMARY KEY (`id`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+-- Daten Export vom Benutzer nicht ausgewählt
+
+
+-- Exportiere Struktur von Tabelle world.aowow_account_banned
+DROP TABLE IF EXISTS `aowow_account_banned`;
+CREATE TABLE IF NOT EXISTS `aowow_account_banned` (
+ `id` int(16) unsigned NOT NULL,
+ `userId` int(11) unsigned NOT NULL COMMENT 'affected accountId',
+ `staffId` int(11) unsigned NOT NULL COMMENT 'executive accountId',
+ `typeMask` tinyint(4) unsigned NOT NULL COMMENT 'ACC_BAN_*',
+ `start` int(10) unsigned NOT NULL COMMENT 'unixtime',
+ `end` int(10) unsigned NOT NULL COMMENT 'automatic unban @ unixtime',
+ `reason` varchar(255) NOT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+-- Daten Export vom Benutzer nicht ausgewählt
+
+-- Exportiere Daten aus Tabelle world.aowow_config: 18 rows
+DELETE FROM `aowow_config`;
+/*!40000 ALTER TABLE `aowow_config` DISABLE KEYS */;
+INSERT INTO `aowow_config` (`key`, `intValue`, `strValue`, `comment`) VALUES
+ ('sql_limit_search', 500, NULL, 'default: 500 - Limit of some SQL queries'),
+ ('sql_limit_default', 300, NULL, 'default: 300 - Limit of some SQL queries'),
+ ('sql_limit_quicksearch', 10, NULL, 'default: 10 - Limit of some SQL queries'),
+ ('sql_limit_none', 0, NULL, 'default: 0 - Limit of some SQL queries (yes, i\'m lazy)'),
+ ('ttl_rss', 60, NULL, 'default: 60 - time to live for RSS'),
+ ('cache_decay', 604800, NULL, 'default: 60 * 60 * 7 - Time to keep cache in seconds'),
+ ('session_timeout_delay', 3600, NULL, 'default: 60 * 60 - non-permanent session times out in time() + X'),
+ ('failed_auth_exclusion', 900, NULL, 'default: 15 * 60 - how long an account is closed after exceeding failed_auth_count'),
+ ('failed_auth_count', 5, NULL, 'default: 5 - how often invalid passwords are tolerated'),
+ ('name', NULL, 'Aowow Database Viewer (ADV)', 'website title'),
+ ('name_short', NULL, 'Aowow', 'feed title'),
+ ('board_url', NULL, 'http://www.wowhead.com/forums?board=', 'a javascript thing..'),
+ ('contact_email', NULL, 'feedback@aowow.org', 'ah well...'),
+ ('battlegroup', NULL, 'Pure Pwnage', 'pretend, we belong to a battlegroup to satisfy profiler-related Jscripts; region can be determined from realmlist.timezone'),
+ ('allow_register', 1, NULL, 'default: 1 - Allow/disallow account creation (requires auth_mode 0)'),
+ ('debug', 0, NULL, 'default: 0 - Disable cache, enable sql-errors, enable error_reporting'),
+ ('maintenance', 0, NULL, 'default: 0 - brb gnomes'),
+ ('auth_mode', 0, NULL, 'default: 0 - 0:aowow, 1:wow-auth, 2:external');
+
+/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
+/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
diff --git a/static/js/Markup.js b/static/js/Markup.js
index 65709bc6..ed45ee40 100644
--- a/static/js/Markup.js
+++ b/static/js/Markup.js
@@ -1858,7 +1858,7 @@ var Markup = {
if(attr.url && Markup._isUrlSafe(attr.url))
str += '' + username + '';
else if(g_isUsernameValid(username))
- str += '' + username + '';
+ str += '' + username + '';
else
str += username;
str += ' '+ LANG.markup_said + '