mirror of
				https://github.com/slawkens/myaac.git
				synced 2025-10-30 23:46:24 +01:00 
			
		
		
		
	Merge branch 'develop' into feature/migrations-up-down
This commit is contained in:
		
							
								
								
									
										24
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -1,6 +1,28 @@ | |||||||
| # Changelog | # Changelog | ||||||
|  |  | ||||||
| ## [1.0-RC -23.07.2024] | ## [1.0-RC.2 - 25.10.2024] | ||||||
|  |  | ||||||
|  | Still waiting for your reports about bugs found in this release. We are very close to stable release. | ||||||
|  |  | ||||||
|  | ### Added | ||||||
|  | * feat: rate limit settings for blocking accounts login attempts (@gpedro, #266) | ||||||
|  | * search by email in accounts editor (https://github.com/slawkens/myaac/commit/c2ec46824621468f2a1cb4046805c485ed13fea5) | ||||||
|  | * New hooks in account manage + create (https://github.com/slawkens/myaac/commit/93641fc68ac9a5f1479329e2bd41380c19534d5d) | ||||||
|  |  | ||||||
|  | ### Changed | ||||||
|  | * chore: drop raw queries + accounts - search by email + accounts - required min size for search by account number (@gpedro, #266) | ||||||
|  | * Use https for outfit & item images (https://github.com/slawkens/myaac/commit/71c00aa5e01fbdfd88802912e200dd1025976231) | ||||||
|  | * Do not require players & guilds tables on install (https://github.com/slawkens/myaac/commit/779aa152fa940261c9b161533946f44e288597a2) | ||||||
|  | * Do not create player if there is no players table in db (https://github.com/slawkens/myaac/commit/201f95caa8b70e88fa651eac8c3c3aa7cd765bd0) | ||||||
|  |  | ||||||
|  | ### Fixed | ||||||
|  | * Highscore frags fixed for TFS 0.3 (@Scrollog, #263) | ||||||
|  | * Missing groups variable #262. thanks, @Scrollog for reporting (https://github.com/slawkens/myaac/commit/8d8bdb6dac6df21672ac77288fff2f2f8d6eb665) | ||||||
|  | * Verified email for login.php (@gpedro, #265) | ||||||
|  | * Warning if core.account_country is disabled (https://github.com/slawkens/myaac/commit/ab73d60c61e14a1cacdb6cfbf7f89f4bf3be0833) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## [1.0-RC.1 - 23.07.2024] | ||||||
|  |  | ||||||
| Changes since 1.0-beta: | Changes since 1.0-beta: | ||||||
|  |  | ||||||
|   | |||||||
| @@ -26,7 +26,7 @@ | |||||||
| if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); | if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); | ||||||
|  |  | ||||||
| const MYAAC = true; | const MYAAC = true; | ||||||
| const MYAAC_VERSION = '1.0-RC'; | const MYAAC_VERSION = '1.0-RC.2'; | ||||||
| const DATABASE_VERSION = 40; | const DATABASE_VERSION = 40; | ||||||
| const TABLE_PREFIX = 'myaac_'; | const TABLE_PREFIX = 'myaac_'; | ||||||
| define('START_TIME', microtime(true)); | define('START_TIME', microtime(true)); | ||||||
|   | |||||||
| @@ -105,4 +105,8 @@ $config['clients'] = [ | |||||||
| 	1316, | 	1316, | ||||||
| 	1320, | 	1320, | ||||||
| 	1321, | 	1321, | ||||||
|  | 	1322, | ||||||
|  | 	1330, | ||||||
|  | 	1332, | ||||||
|  | 	1340, | ||||||
| ]; | ]; | ||||||
|   | |||||||
| @@ -40,8 +40,13 @@ else | |||||||
|  |  | ||||||
| 		if(empty($errors)) | 		if(empty($errors)) | ||||||
| 		{ | 		{ | ||||||
| 			if(!admin() && !Validator::newCharacterName($name)) | 			if(!Validator::characterName($name)) { | ||||||
| 				$errors[] = Validator::getLastError(); | 				$errors[] = Validator::getLastError(); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if(!admin() && !Validator::newCharacterName($name)) { | ||||||
|  | 				$errors[] = Validator::getLastError(); | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if(empty($errors)) { | 		if(empty($errors)) { | ||||||
|   | |||||||
| @@ -148,6 +148,10 @@ if($save) | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * two hooks for compatibility | ||||||
|  | 	 */ | ||||||
|  | 	$hooks->trigger(HOOK_ACCOUNT_CREATE_AFTER_SUBMIT, $params); | ||||||
| 	if (!$hooks->trigger(HOOK_ACCOUNT_CREATE_POST, $params)) { | 	if (!$hooks->trigger(HOOK_ACCOUNT_CREATE_POST, $params)) { | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| @@ -187,6 +191,8 @@ if($save) | |||||||
| 		$new_account->setEMail($email); | 		$new_account->setEMail($email); | ||||||
| 		$new_account->save(); | 		$new_account->save(); | ||||||
|  |  | ||||||
|  | 		$hooks->trigger(HOOK_ACCOUNT_CREATE_AFTER_SAVED, ['account' => $new_account]); | ||||||
|  |  | ||||||
| 		if(USE_ACCOUNT_SALT) | 		if(USE_ACCOUNT_SALT) | ||||||
| 			$new_account->setCustomField('salt', $salt); | 			$new_account->setCustomField('salt', $salt); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -42,7 +42,7 @@ if(!empty($login_account) && !empty($login_password)) | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if($account_logged->isLoaded() && encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $login_password) == $account_logged->getPassword() && ($limiter->enabled && !$limiter->exceeded($ip)) | 	if($account_logged->isLoaded() && encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $login_password) == $account_logged->getPassword() && (!$limiter->enabled || !$limiter->exceeded($ip)) | ||||||
| 	) | 	) | ||||||
| 	{ | 	{ | ||||||
| 		if (setting('core.account_mail_verify') && (int)$account_logged->getCustomField('email_verified') !== 1) { | 		if (setting('core.account_mail_verify') && (int)$account_logged->getCustomField('email_verified') !== 1) { | ||||||
|   | |||||||
| @@ -35,11 +35,12 @@ $settingHighscoresVocationBox = setting('core.highscores_vocation_box'); | |||||||
| $configVocations = config('vocations'); | $configVocations = config('vocations'); | ||||||
| $configVocationsAmount = config('vocations_amount'); | $configVocationsAmount = config('vocations_amount'); | ||||||
|  |  | ||||||
| if($settingHighscoresVocationBox && $vocation !== 'all') | $vocationId = null; | ||||||
| { | if($settingHighscoresVocationBox && $vocation !== 'all') { | ||||||
| 	foreach($configVocations as $id => $name) { | 	foreach($configVocations as $id => $name) { | ||||||
| 		if(strtolower($name) == $vocation) { | 		if(strtolower($name) == $vocation) { | ||||||
| 			$add_vocs = array($id); | 			$vocationId = $id; | ||||||
|  | 			$add_vocs = [$id]; | ||||||
|  |  | ||||||
| 			$i = $id + $configVocationsAmount; | 			$i = $id + $configVocationsAmount; | ||||||
| 			while(isset($configVocations[$i])) { | 			while(isset($configVocations[$i])) { | ||||||
| @@ -175,7 +176,7 @@ if (empty($highscores)) { | |||||||
| 			$query | 			$query | ||||||
| 				->join('player_skills', 'player_skills.player_id', '=', 'players.id') | 				->join('player_skills', 'player_skills.player_id', '=', 'players.id') | ||||||
| 				->where('skillid', $skill) | 				->where('skillid', $skill) | ||||||
| 				->addSelect('player_skills.skillid as value'); | 				->addSelect('player_skills.value as value'); | ||||||
| 		} | 		} | ||||||
| 	} else if ($skill == SKILL_FRAGS) // frags | 	} else if ($skill == SKILL_FRAGS) // frags | ||||||
| 	{ | 	{ | ||||||
| @@ -287,6 +288,7 @@ $twig->display('highscores.html.twig', [ | |||||||
| 	'skillName' => ($skill == SKILL_FRAGS ? 'Frags' : ($skill == SKILL_BALANCE ? 'Balance' : getSkillName($skill))), | 	'skillName' => ($skill == SKILL_FRAGS ? 'Frags' : ($skill == SKILL_BALANCE ? 'Balance' : getSkillName($skill))), | ||||||
| 	'levelName' => ($skill != SKILL_FRAGS && $skill != SKILL_BALANCE ? 'Level' : ($skill == SKILL_BALANCE ? 'Balance' : 'Frags')), | 	'levelName' => ($skill != SKILL_FRAGS && $skill != SKILL_BALANCE ? 'Level' : ($skill == SKILL_BALANCE ? 'Balance' : 'Frags')), | ||||||
| 	'vocation' => $vocation !== 'all' ? $vocation :  null, | 	'vocation' => $vocation !== 'all' ? $vocation :  null, | ||||||
|  | 	'vocationId' => $vocationId, | ||||||
| 	'types' => $types, | 	'types' => $types, | ||||||
| 	'linkPreviousPage' => $linkPreviousPage, | 	'linkPreviousPage' => $linkPreviousPage, | ||||||
| 	'linkNextPage' => $linkNextPage, | 	'linkNextPage' => $linkNextPage, | ||||||
|   | |||||||
| @@ -62,7 +62,9 @@ if ($monsterModel && isset($monsterModel->name)) { | |||||||
| 	$elements = json_decode($monster['elements'], true); | 	$elements = json_decode($monster['elements'], true); | ||||||
| 	$immunities = json_decode($monster['immunities'], true); | 	$immunities = json_decode($monster['immunities'], true); | ||||||
| 	$loot = json_decode($monster['loot'], true); | 	$loot = json_decode($monster['loot'], true); | ||||||
| 	usort($loot, 'sort_by_chance'); | 	if (!empty($loot)) { | ||||||
|  | 		usort($loot, 'sort_by_chance'); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	foreach ($loot as &$item) { | 	foreach ($loot as &$item) { | ||||||
| 		$item['name'] = getItemNameById($item['id']); | 		$item['name'] = getItemNameById($item['id']); | ||||||
|   | |||||||
| @@ -100,7 +100,7 @@ foreach($playersOnline as $player) { | |||||||
| } | } | ||||||
|  |  | ||||||
| $record = ''; | $record = ''; | ||||||
| if($players > 0) { | if(count($players_data) > 0) { | ||||||
| 	if( setting('core.online_record')) { | 	if( setting('core.online_record')) { | ||||||
| 		$result = null; | 		$result = null; | ||||||
| 		$timestamp = false; | 		$timestamp = false; | ||||||
| @@ -114,7 +114,7 @@ if($players > 0) { | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if($record) { | 		if($result) { | ||||||
| 			$record = 'The maximum on this game world was ' . $result['record'] . ' players' . ($timestamp ? ' on ' . date("M d Y, H:i:s", $result['timestamp']) . '.' : '.'); | 			$record = 'The maximum on this game world was ' . $result['record'] . ' players' . ($timestamp ? ' on ' . date("M d Y, H:i:s", $result['timestamp']) . '.' : '.'); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -23,32 +23,8 @@ class CreateCharacter | |||||||
| 	 */ | 	 */ | ||||||
| 	public function checkName($name, &$errors) | 	public function checkName($name, &$errors) | ||||||
| 	{ | 	{ | ||||||
| 		$minLength = setting('core.create_character_name_min_length'); | 		if (!\Validator::characterName($name)) { | ||||||
| 		$maxLength = setting('core.create_character_name_max_length'); | 			$errors['name'] = \Validator::getLastError(); | ||||||
|  |  | ||||||
| 		if(empty($name)) { |  | ||||||
| 			$errors['name'] = 'Please enter a name for your character!'; |  | ||||||
| 			return false; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if(strlen($name) > $maxLength) { |  | ||||||
| 			$errors['name'] = 'Name is too long. Max. length <b>' . $maxLength . '</b> letters.'; |  | ||||||
| 			return false; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if(strlen($name) < $minLength) { |  | ||||||
| 			$errors['name'] = 'Name is too short. Min. length <b>' . $minLength . '</b> letters.'; |  | ||||||
| 			return false; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		$name_length = strlen($name); |  | ||||||
| 		if(strspn($name, "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM- '") != $name_length) { |  | ||||||
| 			$errors['name'] = 'This name contains invalid letters, words or format. Please use only a-Z, - , \' and space.'; |  | ||||||
| 			return false; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if(!preg_match("/[A-z ']/", $name)) { |  | ||||||
| 			$errors['name'] = 'Your name contains illegal characters.'; |  | ||||||
| 			return false; | 			return false; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ class RateLimit | |||||||
| 	public int $max_attempts; | 	public int $max_attempts; | ||||||
| 	public int $ttl; | 	public int $ttl; | ||||||
| 	public $enabled = false; | 	public $enabled = false; | ||||||
| 	protected array $data; | 	protected array $data = []; | ||||||
|  |  | ||||||
| 	public function __construct(string $key, int $max_attempts, int $ttl) | 	public function __construct(string $key, int $max_attempts, int $ttl) | ||||||
| 	{ | 	{ | ||||||
| @@ -76,7 +76,7 @@ class RateLimit | |||||||
| 	public function save(): void | 	public function save(): void | ||||||
| 	{ | 	{ | ||||||
| 		global $cache; | 		global $cache; | ||||||
| 		if (!$this->enabled) { | 		if (!$this->enabled || !$cache->enabled()) { | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -92,7 +92,7 @@ class RateLimit | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		$data = []; | 		$data = []; | ||||||
| 		if ($this->enabled && $cache->enabled()) { | 		if ($cache->enabled()) { | ||||||
| 			$tmp = ''; | 			$tmp = ''; | ||||||
| 			if ($cache->fetch($this->key, $tmp)) { | 			if ($cache->fetch($this->key, $tmp)) { | ||||||
| 				$data = unserialize($tmp); | 				$data = unserialize($tmp); | ||||||
| @@ -110,8 +110,6 @@ class RateLimit | |||||||
|  |  | ||||||
| 					$this->save(); | 					$this->save(); | ||||||
| 				} | 				} | ||||||
| 			} else { |  | ||||||
| 				$data = []; |  | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -178,8 +178,7 @@ class Validator | |||||||
| 	 */ | 	 */ | ||||||
| 	public static function characterName($name) | 	public static function characterName($name) | ||||||
| 	{ | 	{ | ||||||
| 		if(!isset($name[0])) | 		if(empty($name)) { | ||||||
| 		{ |  | ||||||
| 			self::$lastError = 'Please enter character name.'; | 			self::$lastError = 'Please enter character name.'; | ||||||
| 			return false; | 			return false; | ||||||
| 		} | 		} | ||||||
| @@ -250,7 +249,7 @@ class Validator | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if(substr($name_lower, -1) == "'" || substr($name_lower, -1) == "-") { | 		if(str_ends_with($name_lower, "'") || str_ends_with($name_lower, "-")) { | ||||||
| 			self::$lastError = 'Your name contains illegal characters.'; | 			self::$lastError = 'Your name contains illegal characters.'; | ||||||
| 			return false; | 			return false; | ||||||
| 		} | 		} | ||||||
| @@ -285,7 +284,7 @@ class Validator | |||||||
|  |  | ||||||
| 		$words_blocked = array_merge(['--', "''","' ", " '", '- ', ' -', "-'", "'-"], setting('core.create_character_name_blocked_words')); | 		$words_blocked = array_merge(['--', "''","' ", " '", '- ', ' -', "-'", "'-"], setting('core.create_character_name_blocked_words')); | ||||||
| 		foreach($words_blocked as $word) { | 		foreach($words_blocked as $word) { | ||||||
| 			if(!(strpos($name_lower, $word) === false)) { | 			if(str_contains($name_lower, $word)) { | ||||||
| 				self::$lastError = 'Your name contains illegal words.'; | 				self::$lastError = 'Your name contains illegal words.'; | ||||||
| 				return false; | 				return false; | ||||||
| 			} | 			} | ||||||
| @@ -335,7 +334,7 @@ class Validator | |||||||
| 			NPCs::load(); | 			NPCs::load(); | ||||||
| 			if(NPCs::$npcs) { | 			if(NPCs::$npcs) { | ||||||
| 				foreach (NPCs::$npcs as $npc) { | 				foreach (NPCs::$npcs as $npc) { | ||||||
| 					if(strpos($name_lower, $npc) !== false) { | 					if(str_contains($name_lower, $npc)) { | ||||||
| 						self::$lastError = 'Your name cannot contains NPC name.'; | 						self::$lastError = 'Your name cannot contains NPC name.'; | ||||||
| 						return false; | 						return false; | ||||||
| 					} | 					} | ||||||
|   | |||||||
| @@ -45,6 +45,12 @@ define('HOOK_ACCOUNT_CREATE_AFTER_TOWNS', ++$i); | |||||||
| define('HOOK_ACCOUNT_CREATE_BEFORE_SUBMIT_BUTTON', ++$i); | define('HOOK_ACCOUNT_CREATE_BEFORE_SUBMIT_BUTTON', ++$i); | ||||||
| define('HOOK_ACCOUNT_CREATE_AFTER_FORM', ++$i); | define('HOOK_ACCOUNT_CREATE_AFTER_FORM', ++$i); | ||||||
| define('HOOK_ACCOUNT_CREATE_POST', ++$i); | define('HOOK_ACCOUNT_CREATE_POST', ++$i); | ||||||
|  | define('HOOK_ACCOUNT_CREATE_AFTER_SUBMIT', ++$i); | ||||||
|  | define('HOOK_ACCOUNT_CREATE_AFTER_SAVED', ++$i); | ||||||
|  | define('HOOK_ACCOUNT_MANAGE_BEFORE_GENERAL_INFORMATION', ++$i); | ||||||
|  | define('HOOK_ACCOUNT_MANAGE_BEFORE_PUBLIC_INFORMATION', ++$i); | ||||||
|  | define('HOOK_ACCOUNT_MANAGE_BEFORE_ACCOUNT_LOGS', ++$i); | ||||||
|  | define('HOOK_ACCOUNT_MANAGE_BEFORE_CHARACTERS', ++$i); | ||||||
| define('HOOK_ACCOUNT_LOGIN_BEFORE_PAGE', ++$i); | define('HOOK_ACCOUNT_LOGIN_BEFORE_PAGE', ++$i); | ||||||
| define('HOOK_ACCOUNT_LOGIN_BEFORE_ACCOUNT', ++$i); | define('HOOK_ACCOUNT_LOGIN_BEFORE_ACCOUNT', ++$i); | ||||||
| define('HOOK_ACCOUNT_LOGIN_AFTER_ACCOUNT', ++$i); | define('HOOK_ACCOUNT_LOGIN_AFTER_ACCOUNT', ++$i); | ||||||
|   | |||||||
| @@ -142,10 +142,14 @@ function updateStatus() { | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		$status['uptime'] = $serverStatus->getUptime(); | 		$uptime = $status['uptime'] = $serverStatus->getUptime(); | ||||||
| 		$h = floor($status['uptime'] / 3600); | 		$m = date('m', $uptime); | ||||||
| 		$m = floor(($status['uptime'] - $h * 3600) / 60); | 		$m = $m > 1 ? "$m months, " : ($m == 1 ? 'month, ' : ''); | ||||||
| 		$status['uptimeReadable'] = $h . 'h ' . $m . 'm'; | 		$d = date('d', $uptime); | ||||||
|  | 		$d = $d > 1 ? "$d days, " : ($d == 1 ? 'day, ' : ''); | ||||||
|  | 		$h = date('H', $uptime); | ||||||
|  | 		$min = date('i', $uptime); | ||||||
|  | 		$status['uptimeReadable'] = "{$m}{$d}{$h}h {$min}m"; | ||||||
|  |  | ||||||
| 		$status['monsters'] = $serverStatus->getMonstersCount(); | 		$status['monsters'] = $serverStatus->getMonstersCount(); | ||||||
| 		$status['motd'] = $serverStatus->getMOTD(); | 		$status['motd'] = $serverStatus->getMOTD(); | ||||||
|   | |||||||
| @@ -88,6 +88,7 @@ | |||||||
| 			</div> | 			</div> | ||||||
| 		<br/><br/> | 		<br/><br/> | ||||||
| 		{% endif %} | 		{% endif %} | ||||||
|  | 		{{ hook('HOOK_ACCOUNT_MANAGE_BEFORE_GENERAL_INFORMATION') }} | ||||||
| 		<a name="General+Information"></a> | 		<a name="General+Information"></a> | ||||||
| 		<h2>General Information</h2> | 		<h2>General Information</h2> | ||||||
| 		<table width="100%"> | 		<table width="100%"> | ||||||
| @@ -127,6 +128,7 @@ | |||||||
| 			{% endautoescape %} | 			{% endautoescape %} | ||||||
| 		</table> | 		</table> | ||||||
| 		<br/> | 		<br/> | ||||||
|  | 		{{ hook('HOOK_ACCOUNT_MANAGE_BEFORE_PUBLIC_INFORMATION') }} | ||||||
| 		<a name="Public+Information"></a> | 		<a name="Public+Information"></a> | ||||||
| 		<h2>Public Information</h2> | 		<h2>Public Information</h2> | ||||||
| 		<table width="100%"> | 		<table width="100%"> | ||||||
| @@ -145,6 +147,7 @@ | |||||||
| 			{% include('buttons.base.html.twig') %} | 			{% include('buttons.base.html.twig') %} | ||||||
| 		</form> | 		</form> | ||||||
| 		<br/> | 		<br/> | ||||||
|  | 		{{ hook('HOOK_ACCOUNT_MANAGE_BEFORE_ACCOUNT_LOGS') }} | ||||||
| 		<a name="Account+Logs" ></a> | 		<a name="Account+Logs" ></a> | ||||||
| 		<h2>Action Log</h2> | 		<h2>Action Log</h2> | ||||||
| 		<table> | 		<table> | ||||||
| @@ -164,6 +167,7 @@ | |||||||
| 			{% endautoescape %} | 			{% endautoescape %} | ||||||
| 		</table> | 		</table> | ||||||
| 		<br/> | 		<br/> | ||||||
|  | 		{{ hook('HOOK_ACCOUNT_MANAGE_BEFORE_CHARACTERS') }} | ||||||
| 		<a name="Characters" ></a> | 		<a name="Characters" ></a> | ||||||
| 		<h2>Character list: {{ players|length }} characters.</h2> | 		<h2>Character list: {{ players|length }} characters.</h2> | ||||||
| 		<table> | 		<table> | ||||||
|   | |||||||
| @@ -7,21 +7,21 @@ | |||||||
| 				<tr> | 				<tr> | ||||||
| 					<td>Filters</td> | 					<td>Filters</td> | ||||||
| 					<td> | 					<td> | ||||||
| 						<label for="vocationFilter">Choose a Skill</label> | 						<label for="skillFilter">Choose a Skill</label> | ||||||
| 						<select onchange="location = this.value;" aria-label="skillFilter" id="skillFilter"> | 						<select onchange="location = this.value;" id="skillFilter"> | ||||||
| 							{% set i = 0 %} | 							{% set i = 0 %} | ||||||
| 							{% for link, name in types %} | 							{% for link, name in types %} | ||||||
| 								<option value="{{ getLink('highscores') }}/{{ link }}{% if vocation is not null %}{{ vocation }}{% endif %}" class="size_xs">{{ name }}</option> | 								<option value="{{ getLink('highscores') }}/{{ link }}/{% if vocation is not null %}{{ vocation }}{% endif %}" class="size_xs" {% if list is not null and list == link %}selected{% endif %}>{{ name }}</option> | ||||||
| 							{% endfor %} | 							{% endfor %} | ||||||
| 						</select> | 						</select> | ||||||
| 					</td> | 					</td> | ||||||
| 					<td> | 					<td> | ||||||
| 						<label for="vocationFilter">Choose a vocation</label> | 						<label for="vocationFilter">Choose a vocation</label> | ||||||
| 						<select onchange="location = this.value;" aria-label="vocationFilter" id="vocationFilter"> | 						<select onchange="location = this.value;" id="vocationFilter"> | ||||||
| 							<option value="{{ getLink('highscores') }}/{{ list }}" class="size_xs">[ALL]</option> | 							<option value="{{ getLink('highscores') }}/{{ list }}" class="size_xs">[ALL]</option> | ||||||
| 							{% set i = 0 %} | 							{% set i = 0 %} | ||||||
| 							{% for i in 1..config.vocations_amount %} | 							{% for i in 1..config.vocations_amount %} | ||||||
| 								<option value="{{ getLink('highscores') }}/{{ list }}/{{ config.vocations[i]|lower }}" class="size_xs">{{ config.vocations[i]}}</option> | 								<option value="{{ getLink('highscores') }}/{{ list }}/{{ config.vocations[i]|lower }}" class="size_xs" {% if vocationId is not null and vocationId == i %}selected{% endif %}>{{ config.vocations[i]}}</option> | ||||||
| 							{% endfor %} | 							{% endfor %} | ||||||
| 						</select> | 						</select> | ||||||
| 					</td> | 					</td> | ||||||
|   | |||||||
| @@ -23,6 +23,9 @@ | |||||||
| 					Currently {{ players|length }} players are online.<br/> | 					Currently {{ players|length }} players are online.<br/> | ||||||
| 				{% endif %} | 				{% endif %} | ||||||
| 			{% endif %} | 			{% endif %} | ||||||
|  | 			{% if setting('core.online_record') %} | ||||||
|  | 				{{ record }} | ||||||
|  | 			{% endif %} | ||||||
| 		</td> | 		</td> | ||||||
| 	</tr> | 	</tr> | ||||||
| </table> | </table> | ||||||
|   | |||||||
| @@ -111,6 +111,7 @@ | |||||||
| </div> | </div> | ||||||
| <br/><br/> | <br/><br/> | ||||||
| {% endif %} | {% endif %} | ||||||
|  | {{ hook('HOOK_ACCOUNT_MANAGE_BEFORE_GENERAL_INFORMATION') }} | ||||||
| <a name="General+Information" ></a> | <a name="General+Information" ></a> | ||||||
| <div class="TopButtonContainer"> | <div class="TopButtonContainer"> | ||||||
| 	<div class="TopButton"> | 	<div class="TopButton"> | ||||||
| @@ -221,6 +222,7 @@ | |||||||
| {% endset %} | {% endset %} | ||||||
| {% include 'tables.headline.html.twig' %} | {% include 'tables.headline.html.twig' %} | ||||||
| <br/> | <br/> | ||||||
|  | {{ hook('HOOK_ACCOUNT_MANAGE_BEFORE_PUBLIC_INFORMATION') }} | ||||||
| <a name="Public+Information"></a> | <a name="Public+Information"></a> | ||||||
| <div class="TopButtonContainer"> | <div class="TopButtonContainer"> | ||||||
| 	<div class="TopButton"> | 	<div class="TopButton"> | ||||||
| @@ -280,6 +282,7 @@ | |||||||
| {% endset %} | {% endset %} | ||||||
| {% include 'tables.headline.html.twig' %} | {% include 'tables.headline.html.twig' %} | ||||||
| <br/> | <br/> | ||||||
|  | {{ hook('HOOK_ACCOUNT_MANAGE_BEFORE_ACCOUNT_LOGS') }} | ||||||
| <a name="Account+Logs" ></a> | <a name="Account+Logs" ></a> | ||||||
| <div class="TopButtonContainer"> | <div class="TopButtonContainer"> | ||||||
| 	<div class="TopButton"> | 	<div class="TopButton"> | ||||||
| @@ -333,6 +336,7 @@ | |||||||
| {% endset %} | {% endset %} | ||||||
| {% include 'tables.headline.html.twig' %} | {% include 'tables.headline.html.twig' %} | ||||||
| <br/> | <br/> | ||||||
|  | {{ hook('HOOK_ACCOUNT_MANAGE_BEFORE_CHARACTERS') }} | ||||||
| <a name="Characters" ></a> | <a name="Characters" ></a> | ||||||
| <div class="TopButtonContainer"> | <div class="TopButtonContainer"> | ||||||
| 	<div class="TopButton" > | 	<div class="TopButton" > | ||||||
|   | |||||||
| @@ -23,32 +23,36 @@ if(isset($_GET['account'])) | |||||||
| { | { | ||||||
| 	$account = $_GET['account']; | 	$account = $_GET['account']; | ||||||
| 	if(USE_ACCOUNT_NAME) { | 	if(USE_ACCOUNT_NAME) { | ||||||
| 		if(!Validator::accountName($account)) | 		if(!Validator::accountName($account)) { | ||||||
| 			error_(Validator::getLastError()); | 			error_(Validator::getLastError()); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 	else if(!Validator::accountId($account)) | 	else if(!Validator::accountId($account)) { | ||||||
| 		error_(Validator::getLastError()); | 		error_(Validator::getLastError()); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	$_account = new OTS_Account(); | 	$_account = new OTS_Account(); | ||||||
| 	if(USE_ACCOUNT_NAME || USE_ACCOUNT_NUMBER) | 	if(USE_ACCOUNT_NAME || USE_ACCOUNT_NUMBER) { | ||||||
| 		$_account->find($account); | 		$_account->find($account); | ||||||
| 	else | 	} else { | ||||||
| 		$_account->load($account); | 		$_account->load($account); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	$accountNameOrNumber = (USE_ACCOUNT_NAME ? ' name' : 'number'); | 	$accountNameOrNumber = (USE_ACCOUNT_NAME ? ' name' : 'number'); | ||||||
| 	if($_account->isLoaded()) | 	if($_account->isLoaded()) { | ||||||
| 		error_("Account with this $accountNameOrNumber already exist."); | 		error_("Account with this $accountNameOrNumber already exist."); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	success_("Good account $accountNameOrNumber ($account)."); | 	success_("Good account $accountNameOrNumber ($account)."); | ||||||
| } | } | ||||||
| else if(isset($_GET['email'])) | else if(isset($_GET['email'])) | ||||||
| { | { | ||||||
| 	$email = $_GET['email']; | 	$email = $_GET['email']; | ||||||
| 	if(!Validator::email($email)) | 	if(!Validator::email($email)) { | ||||||
| 		error_(Validator::getLastError()); | 		error_(Validator::getLastError()); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if(setting('core.account_mail_unique')) | 	if(setting('core.account_mail_unique')) { | ||||||
| 	{ |  | ||||||
| 		if(Account::where('email', '=', $email)->exists()) | 		if(Account::where('email', '=', $email)->exists()) | ||||||
| 			error_('Account with this e-mail already exist.'); | 			error_('Account with this e-mail already exist.'); | ||||||
| 	} | 	} | ||||||
| @@ -62,11 +66,13 @@ else if(isset($_GET['name'])) | |||||||
| 		$name = strtolower(stripslashes($name)); | 		$name = strtolower(stripslashes($name)); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if(!Validator::characterName($name)) | 	if(!Validator::characterName($name)) { | ||||||
| 		error_(Validator::getLastError()); | 		error_(Validator::getLastError()); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if(!admin() && !Validator::newCharacterName($name)) | 	if(!admin() && !Validator::newCharacterName($name)) { | ||||||
| 		error_(Validator::getLastError()); | 		error_(Validator::getLastError()); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	$createCharacter = new CreateCharacter(); | 	$createCharacter = new CreateCharacter(); | ||||||
| 	if (!$createCharacter->checkName($name, $errors)) { | 	if (!$createCharacter->checkName($name, $errors)) { | ||||||
| @@ -83,16 +89,19 @@ else if(isset($_GET['password']) && isset($_GET['password_confirm'])) { | |||||||
| 		error_('Please enter the password for your new account.'); | 		error_('Please enter the password for your new account.'); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if(!Validator::password($password)) | 	if(!Validator::password($password)) { | ||||||
| 		error_(Validator::getLastError()); | 		error_(Validator::getLastError()); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if($password != $password_confirm) | 	if($password != $password_confirm) { | ||||||
| 		error_('Passwords are not the same.'); | 		error_('Passwords are not the same.'); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	success_(1); | 	success_(1); | ||||||
| } | } | ||||||
| else | else { | ||||||
| 	error_('Error: no input specified.'); | 	error_('Error: no input specified.'); | ||||||
|  | } | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Output message & exit. |  * Output message & exit. | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 slawkens
					slawkens