vulnerability fixed and cleanup and refactor

This commit is contained in:
Catalin Novgorodschi
2026-02-11 15:11:43 +02:00
parent db3d9bfff1
commit 2a44e76414
21 changed files with 6089 additions and 5441 deletions
+349 -229
View File
@@ -17,264 +17,384 @@ use App\Entity\User;
## ##
#################################################################################
/*
=========================================================
= AUTOLOADER DISCOVERY
=========================================================
*/
global $autoprefix;
// go max 5 levels up - we don't have folders that go deeper than that
$autoprefix = '';
for ($i = 0; $i < 5; $i++) {
$autoprefix = str_repeat('../', $i);
if (file_exists($autoprefix.'autoloader.php')) {
// we have our path, let's leave
if (file_exists($autoprefix . 'autoloader.php')) {
break;
}
}
include_once($autoprefix."GameEngine/Session.php");
include_once($autoprefix . "GameEngine/Session.php");
class Account {
function __construct() {
global $session;
if(isset($_POST['ft'])) {
switch($_POST['ft']) {
case "a1":
$this->Signup();
break;
case "a2":
$this->Activate();
break;
case "a3":
$this->Unreg();
break;
case "a4":
$this->Login();
break;
}
} if(isset($_GET['code'])) {
$_POST['id'] = $_GET['code']; $this->Activate();
}
else {
if($session->logged_in && in_array("logout.php",explode("/",$_SERVER['PHP_SELF']))) {
$this->Logout();
}
}
}
/*
=========================================================
= ACCOUNT CLASS
=========================================================
*/
private function Signup() {
global $database,$form,$mailer,$generator,$session;
if(!isset($_POST['name']) || trim($_POST['name']) == "") {
$form->addError("name",USRNM_EMPTY);
}
else {
if(strlen($_POST['name']) < USRNM_MIN_LENGTH) {
$form->addError("name",USRNM_SHORT);
}
else if(!USRNM_SPECIAL && preg_match('/[^0-9A-Za-z]/',$_POST['name'])) {
$form->addError("name",USRNM_CHAR);
}
else if(USRNM_SPECIAL && preg_match("/[:,\\. \\n\\r\\t\\s\\<\\>]+/", $_POST['name'])) {
$form->addError("name",USRNM_CHAR);
}
else if(strtolower($_POST['name']) == 'natars') {
$form->addError("name",USRNM_TAKEN);
class Account
{
/*
=====================================================
= CONSTRUCTOR / REQUEST ROUTER
=====================================================
*/
public function __construct()
{
global $session;
if (isset($_POST['ft'])) {
switch ($_POST['ft']) {
case "a1":
$this->Signup();
break;
case "a2":
$this->Activate();
break;
case "a3":
$this->Unreg();
break;
case "a4":
$this->Login();
break;
}
else if(User::exists($database,$_POST['name'])) {
$form->addError("name",USRNM_TAKEN);
}
}
}
if(!isset($_POST['pw']) || trim($_POST['pw']) == "") {
$form->addError("pw",PW_EMPTY);
}
else {
if(strlen($_POST['pw']) < PW_MIN_LENGTH) {
$form->addError("pw",PW_SHORT);
}
else if($_POST['pw'] == $_POST['name']) {
$form->addError("pw",PW_INSECURE);
elseif (isset($_GET['code'])) {
$_POST['id'] = $_GET['code'];
$this->Activate();
}
elseif (
$session->logged_in &&
in_array("logout.php", explode("/", $_SERVER['PHP_SELF']))
) {
$this->Logout();
}
}
/*
=====================================================
= SIGNUP
=====================================================
*/
private function Signup()
{
global $database, $form, $mailer, $generator;
/*
-------------------------------------------------
USERNAME VALIDATION
-------------------------------------------------
*/
if (empty($_POST['name'])) {
$form->addError("name", USRNM_EMPTY);
} else {
if (strlen($_POST['name']) < USRNM_MIN_LENGTH)
$form->addError("name", USRNM_SHORT);
elseif (!USRNM_SPECIAL && preg_match('/[^0-9A-Za-z]/', $_POST['name']))
$form->addError("name", USRNM_CHAR);
elseif (USRNM_SPECIAL &&
preg_match("/[:,\\. \\n\\r\\t\\s\\<\\>]+/", $_POST['name']))
$form->addError("name", USRNM_CHAR);
elseif (strtolower($_POST['name']) == 'natars')
$form->addError("name", USRNM_TAKEN);
elseif (User::exists($database, $_POST['name']))
$form->addError("name", USRNM_TAKEN);
}
/*
-------------------------------------------------
PASSWORD VALIDATION
-------------------------------------------------
*/
if (empty($_POST['pw'])) {
$form->addError("pw", PW_EMPTY);
} else {
if (strlen($_POST['pw']) < PW_MIN_LENGTH)
$form->addError("pw", PW_SHORT);
elseif ($_POST['pw'] == $_POST['name'])
$form->addError("pw", PW_INSECURE);
}
/*
-------------------------------------------------
EMAIL VALIDATION
-------------------------------------------------
*/
if (!isset($_POST['email'])) {
$form->addError("email", EMAIL_EMPTY);
} else {
if (!$this->validEmail($_POST['email']))
$form->addError("email", EMAIL_INVALID);
elseif (User::exists($database, $_POST['email']))
$form->addError("email", EMAIL_TAKEN);
}
/*
-------------------------------------------------
TRIBE & AGREEMENT VALIDATION
-------------------------------------------------
*/
if (!isset($_POST['vid']) || !in_array($_POST['vid'], [1,2,3]))
$form->addError("tribe", TRIBE_EMPTY);
if (!isset($_POST['agb']))
$form->addError("agree", AGREE_ERROR);
/*
-------------------------------------------------
ERROR HANDLING
-------------------------------------------------
*/
if ($form->returnErrors() > 0) {
}
}
if(!isset($_POST['email'])) {
$form->addError("email",EMAIL_EMPTY);
}
else {
if(!$this->validEmail($_POST['email'])) {
$form->addError("email",EMAIL_INVALID);
}
else if(User::exists($database,$_POST['email'])) {
$form->addError("email",EMAIL_TAKEN);
}
}
if(!isset($_POST['vid']) || !in_array($_POST['vid'], [1, 2, 3])) {
$form->addError("tribe",TRIBE_EMPTY);
}
if(!isset($_POST['agb'])) {
$form->addError("agree",AGREE_ERROR);
}
if($form->returnErrors() > 0) {
$form->addError("invt",$_POST['invited']);
$_SESSION['errorarray'] = $form->getErrors();
$_SESSION['valuearray'] = $_POST;
header("Location: anmelden.php");
exit;
}
else {
if(AUTH_EMAIL){
$act = $generator->generateRandStr(10);
$act2 = $generator->generateRandStr(5);
$uid = $database->activate($_POST['name'],password_hash($_POST['pw'], PASSWORD_BCRYPT,['cost' => 12]),$_POST['email'],$_POST['vid'],$_POST['kid'],$act,$act2);
if($uid) {
$mailer->sendActivate($_POST['email'],$_POST['name'],$_POST['pw'],$act);
header("Location: activate.php?id=$uid&q=$act2");
exit;
}
}
else {
$uid = $database->register($_POST['name'], password_hash($_POST['pw'], PASSWORD_BCRYPT, ['cost' => 12]), $_POST['email'], $_POST['vid'], $act);
if($uid) {
setcookie("COOKUSR" , $_POST['name'], time() + COOKIE_EXPIRE,COOKIE_PATH);
setcookie("COOKEMAIL" , $_POST['email'], time() + COOKIE_EXPIRE,COOKIE_PATH);
$database->updateUserField(
$uid,
["act", "invited"],
["", $_POST['invited']],
1
);
$this->generateBase($_POST['kid'], $uid, $_POST['name']);
header("Location: login.php");
exit;
}
}
}
}
/*
-------------------------------------------------
REGISTRATION FLOW
-------------------------------------------------
*/
private function Activate() {
global $database;
if(START_DATE < date('d.m.Y') or START_DATE == date('d.m.Y') && START_TIME <= date('H:i'))
{
$q = "SELECT act, username, password, email, tribe, location FROM ".TB_PREFIX."activate where act = '".$database->escape($_POST['id'])."'";
$result = mysqli_query($database->dblink,$q);
$dbarray = mysqli_fetch_array($result);
if($dbarray['act'] == $_POST['id']) {
$uid = $database->register($dbarray['username'], $dbarray['password'], $dbarray['email'], $dbarray['tribe'], "");
if($uid) {
$database->unreg($dbarray['username']);
$this->generateBase($dbarray['location'],$uid,$dbarray['username']);
header("Location: activate.php?e=2");
exit;
}
}
else
{
header("Location: activate.php?e=3");
exit;
}
}
else
{
header("Location: activate.php");
exit;
}
}
if (AUTH_EMAIL) {
private function Unreg() {
global $database;
$q = "SELECT password, username FROM ".TB_PREFIX."activate where id = ".(int) $_POST['id'];
$result = mysqli_query($database->dblink,$q);
$dbarray = mysqli_fetch_array($result);
if(password_verify($_POST['pw'], $dbarray['password'])) {
$database->unreg($dbarray['username']);
header("Location: anmelden.php");
exit;
}
else {
header("Location: activate.php?e=3");
exit;
}
}
$act = $generator->generateRandStr(10);
$act2 = $generator->generateRandStr(5);
private function Login() {
global $database, $session, $form;
$user = $_POST['user'];
if(!isset($_POST['user']) || empty($_POST['user'])){
$form->addError("user", $user);
}else if(!User::exists($database, $_POST['user'])){
$form->addError("user", USR_NT_FOUND);
}
if(!isset($_POST['pw']) || empty($_POST['pw'])){
$form->addError("pw", LOGIN_PASS_EMPTY);
}else if(!$database->login($_POST['user'], $_POST['pw']) && !$database->sitterLogin($_POST['user'], $_POST['pw'])){
// try activation data if the user was not found
if(!$userData){
$activateData = $database->getActivateField($_POST['user'], 'act', 1);
if(!empty($activateData)) $form->addError("activate", $_POST['user']);
else $form->addError("pw", LOGIN_PW_ERROR);
}
else $form->addError("pw", LOGIN_PW_ERROR);
}
$uid = $database->activate(
$_POST['name'],
password_hash($_POST['pw'], PASSWORD_BCRYPT, ['cost'=>12]),
$_POST['email'],
$_POST['vid'],
$_POST['kid'],
$act,
$act2
);
$userData = $database->getUserArray($_POST['user'], 0);
// Vacation mode by Shadow
if($userData["vac_mode"] == 1 && $userData["vac_time"] > time()){
$form->addError("vacation", "Vacation mode is still enabled");
}
// Vacation mode by Shadow
if($form->returnErrors() > 0){
$_SESSION['errorarray'] = $form->getErrors();
$_SESSION['valuearray'] = $_POST;
header("Location: login.php");
exit();
}else{
// Vacation mode by Shadow
$database->removevacationmode($userData['id']);
// Vacation mode by Shadow
if($database->login($_POST['user'], $_POST['pw'])){
$database->UpdateOnline("login", $_POST['user'], time(), $userData['id']);
}else if($database->sitterLogin($_POST['user'], $_POST['pw'])){
$database->UpdateOnline("sitter", $_POST['user'], time(), $userData['id']);
}
setcookie("COOKUSR", $_POST['user'], time() + COOKIE_EXPIRE, COOKIE_PATH);
$session->login($_POST['user']);
}
}
if ($uid) {
private function Logout() {
global $session, $database;
unset($_SESSION['wid']);
$database->activeModify(addslashes($session->username),1);
$database->UpdateOnline("logout") or die(mysqli_error($database->dblink));
$session->Logout();
}
$mailer->sendActivate(
$_POST['email'],
$_POST['name'],
$_POST['pw'],
$act
);
private function validEmail($email) {
$regexp="/^[a-z0-9]+([_\\.-][a-z0-9]+)*@([a-z0-9]+([\.-][a-z0-9]+)*)+\\.[a-z]{2,}$/i";
return preg_match($regexp, $email);
}
header("Location: activate.php?id=$uid&q=$act2");
exit;
}
} else {
$uid = $database->register(
$_POST['name'],
password_hash($_POST['pw'], PASSWORD_BCRYPT, ['cost'=>12]),
$_POST['email'],
$_POST['vid'],
""
);
if ($uid) {
setcookie("COOKUSR", $_POST['name'], time()+COOKIE_EXPIRE, COOKIE_PATH);
setcookie("COOKEMAIL", $_POST['email'], time()+COOKIE_EXPIRE, COOKIE_PATH);
$database->updateUserField(
$uid,
["act", "invited"],
["", $_POST['invited']],
1
);
$this->generateBase($_POST['kid'], $uid, $_POST['name']);
header("Location: login.php");
exit;
}
}
}
/*
=====================================================
= LOGIN
=====================================================
*/
private function Login()
{
global $database, $session, $form;
if (empty($_POST['user']))
$form->addError("user", LOGIN_USER_EMPTY);
elseif (!User::exists($database, $_POST['user']))
$form->addError("user", USR_NT_FOUND);
if (empty($_POST['pw']))
$form->addError("pw", LOGIN_PASS_EMPTY);
elseif (
!$database->login($_POST['user'], $_POST['pw']) &&
!$database->sitterLogin($_POST['user'], $_POST['pw'])
)
$form->addError("pw", LOGIN_PW_ERROR);
$userData = $database->getUserArray($_POST['user'], 0);
if ($userData["vac_mode"] == 1 && $userData["vac_time"] > time())
$form->addError("vacation", "Vacation mode is still enabled");
if ($form->returnErrors() > 0) {
$_SESSION['errorarray'] = $form->getErrors();
$_SESSION['valuearray'] = $_POST;
header("Location: login.php");
exit;
}
/*
-------------------------------------------------
SUCCESS LOGIN FLOW
-------------------------------------------------
*/
$database->removevacationmode($userData['id']);
if ($database->login($_POST['user'], $_POST['pw']))
$database->UpdateOnline("login", $_POST['user'], time(), $userData['id']);
elseif ($database->sitterLogin($_POST['user'], $_POST['pw']))
$database->UpdateOnline("sitter", $_POST['user'], time(), $userData['id']);
setcookie("COOKUSR", $_POST['user'], time()+COOKIE_EXPIRE, COOKIE_PATH);
$session->login($_POST['user']);
}
/*
=====================================================
= LOGOUT
=====================================================
*/
private function Logout()
{
global $session, $database;
unset($_SESSION['wid']);
$database->activeModify(addslashes($session->username), 1);
$database->UpdateOnline("logout");
$session->Logout();
}
/*
=====================================================
= EMAIL VALIDATOR
=====================================================
*/
private function validEmail($email)
{
$regexp = "/^[a-z0-9]+([_\\.-][a-z0-9]+)*@([a-z0-9]+([\\.-][a-z0-9]+)*)+\\.[a-z]{2,}$/i";
return preg_match($regexp, $email);
}
/*
=====================================================
= BASE GENERATION
=====================================================
*/
function generateBase($kid, $uid, $username)
{
global $database;
$message = new Message();
if ($kid == 0)
$kid = rand(1,4);
else
$kid = $_POST['kid'];
$database->generateVillages(
[[
'wid' => 0,
'mode' => 0,
'type' => 3,
'kid' => $kid,
'capital' => 1,
'pop' => 2,
'name' => null,
'natar' => 0
]],
$uid,
$username
);
$message->sendWelcome($uid, $username);
}
}
function generateBase($kid, $uid, $username) {
global $database;
$message = new Message();
if($kid == 0) $kid = rand(1,4);
else $kid = $_POST['kid'];
$database->generateVillages([['wid' => 0, 'mode' => 0, 'type' => 3, 'kid' => $kid, 'capital' => 1, 'pop' => 2, 'name' => null, 'natar' => 0]], $uid, $username);
$message->sendWelcome($uid, $username);
}
};
$account = new Account;
?>
+379 -550
View File
@@ -16,20 +16,25 @@
## ##
#################################################################################
use App\Entity\User;
/*
=========================================================
= AUTOLOADER DISCOVERY
=========================================================
*/
global $autoprefix;
// even with autoloader created, we can't use it here yet, as it's not been created
// ... so, let's see where it is and include it
$autoloader_found = false;
// go max 5 levels up - we don't have folders that go deeper than that
$autoprefix = '';
for ($i = 0; $i < 5; $i++) {
$autoprefix = str_repeat('../', $i);
if (file_exists($autoprefix.'autoloader.php')) {
if (file_exists($autoprefix . 'autoloader.php')) {
$autoloader_found = true;
include_once $autoprefix.'autoloader.php';
include_once $autoprefix . 'autoloader.php';
break;
}
}
@@ -38,585 +43,409 @@ if (!$autoloader_found) {
die('Could not find autoloading class.');
}
class Alliance {
public $gotInvite = false;
public $inviteArray = [];
public $allianceArray = [];
public $userPermArray = [];
public function procAlliance($get) {
global $session, $database;
/*
=========================================================
= ALLIANCE DOMAIN CONTROLLER
=========================================================
*/
if($session->alliance > 0) {
$this->allianceArray = $database->getAlliance($session->alliance);
// Permissions Array
// [id] => id [uid] => uid [alliance] => alliance [opt1] => X [opt2] => X [opt3] => X [opt4] => X [opt5] => X [opt6] => X [opt7] => X [opt8] => X
$this->userPermArray = $database->getAlliPermissions($session->uid, $session->alliance);
} else {
$this->inviteArray = $database->getInvitation($session->uid);
$this->gotInvite = count($this->inviteArray) > 0;
}
if(isset($get['a'])) {
switch($get['a']) {
case 2:
$this->rejectInvite($get);
break;
case 3:
$this->acceptInvite($get);
break;
}
}
if(isset($get['o'])) {
switch($get['o']) {
case 4:
$this->delInvite($get);
break;
}
}
}
/**
* Determines if a forum is accessible or not
*
* @param int $forumID The forum ID
* @return bool Returns if the forum is accessible or not
*/
public function isForumAccessible($forumID){
global $session;
//Loop through the shared forums and try to find the passed one
foreach($session->sharedForums as $forums){
foreach($forums as $forum){
if($forum['id'] == $forumID) return true;
}
}
return false;
}
/**
* Determines if a player can act with the forum (edit/delete/create things, etc.)
*
* @param array $datas The array which contains: [aid, alliance, forum_perm, admin, owner, forum_owner]
* @return bool Returns true if you are able to act, false otherwise
*/
public static function canAct($datas, $mode = 0){
global $database, $session;
class Alliance
{
/*
=====================================================
= PROPERTIES
=====================================================
*/
$hasSwitchedToAdmin = isset($datas['admin']) && !empty($datas['admin']) && $datas['admin'] == "switch_admin";
public $gotInvite = false;
public $inviteArray = [];
public $allianceArray = [];
public $userPermArray = [];
return (/*$database->CheckEditRes($datas['aid']) == 1 && */($datas['alliance'] > 0 && (($database->isAllianceOwner($session->uid) == $datas['alliance'] ||
($datas['forum_perm'] == 1 && $session->alliance == $datas['alliance']))) ||
($datas['owner'] == $session->uid && $session->access != ADMIN)) ||
($session->access == ADMIN)) &&
($mode || $hasSwitchedToAdmin);
}
/**
* Create two string, representing alliances ID and users ID which can see a specific forum
*
* @param int $alliancesID A list of alliances ID
* @param int $alliancesName A list of alliances Name
* @param int $usersID A list of users ID
* @param int $usersName A list of users name
* @return array Returns the two string, composed by alliances ID and users ID
*/
public function createForumVisiblity($alliancesID, $alliancesName, $usersID, $usersName){
global $database, $session;
$alliances = $users = [];
//TODO: Reduce the code of this part and cache existing diplomacy relationship
//Deduplicate alliances
if(!empty($alliancesID)){
foreach($alliancesID as $alliance){
if(!empty($alliance) && is_numeric($alliance) && $database->aExist($alliance, 'id') && $alliance != $session->alliance && empty($database->diplomacyExistingRelationships($alliance))){
$alliances[$alliance] = true;
}
}
}
if(!empty($alliancesName)){
foreach($alliancesName as $alliance){
if(!empty($alliance) && !empty($allianceID = $database->getAllianceID($alliance)) && $allianceID != $session->alliance && empty($database->diplomacyExistingRelationships($allianceID))){
$alliances[$allianceID] = true;
}
}
}
//Deduplicate users
if(!empty($usersID)){
foreach($usersID as $user) {
if(!empty($user) && is_numeric($user) && ($userAlly = $database->getUserAllianceID($user)) > 0 && $userAlly != $session->alliance && $database->getUserField($user, 'username', 0) != "[?]" && $user != $session->uid && empty($database->diplomacyExistingRelationships($userAlly))) {
$users[$user] = true;
}
}
}
if(!empty($usersName)){
foreach($usersName as $user){
if(!empty($user) && !empty($userID = $database->getUserField($user, 'id', 1)) && $userID != $session->uid && ($userAlly = $database->getUserAllianceID($userID)) > 0 && $userAlly != $session->alliance && empty($database->diplomacyExistingRelationships($userAlly))) {
$users[$userID] = true;
}
}
}
return ['alliances' => implode(',', array_keys($alliances)), 'users' => implode(',', array_keys($users))];
}
/**
* Redirects to the forum selection
*
* @param array $get Contains the values of a GET request
*/
public function redirect($get = null)
{
header("Location: allianz.php?s=2".(isset($get['fid']) && !empty($get['fid']) && $get['admin'] != 'pos' ? "&fid=".$get['fid']."" : "").
(isset($get['admin']) && !empty($get['admin']) ? "&admin=switch_admin" : ""));
exit;
}
public function procAlliForm($post) {
if(isset($post['ft'])) {
switch($post['ft']) {
case "ali1":
$this->createAlliance($post);
break;
}
}
if(isset($post['dipl']) && isset($post['a_name'])) $this->changediplomacy($post);
/*
=====================================================
= INITIAL PROCESSOR
=====================================================
*/
if(isset($post['s'])) {
if(isset($post['o'])) {
switch($post['o']) {
case 1:
if(isset($_POST['a'])) $this->changeUserPermissions($post);
break;
case 2:
if(isset($_POST['a_user'])) $this->kickAlliUser($post);
break;
case 4:
if(isset($_POST['a']) && $_POST['a'] == 4) $this->sendInvite($post);
break;
case 3:
$this->updateAlliProfile($post);
break;
case 11:
$this->quitally($post);
break;
case 100:
$this->changeAliName($post);
break;
}
}
}
}
public function procAlliance($get)
{
global $session, $database;
/*****************************************
Function to process of sending invitations
*****************************************/
public function sendInvite($post) {
global $form, $database, $session;
/*
-------------------------------------------------
LOAD ALLIANCE OR INVITES
-------------------------------------------------
*/
$UserData = $database->getUserArray(stripslashes($post['a_name']), 0);
if($this->userPermArray['opt4'] == 0) {
$form->addError("name", NO_PERMISSION);
}elseif(!isset($post['a_name']) || $post['a_name'] == "") {
$form->addError("name", NAME_EMPTY);
}elseif(!User::exists($database, $post['a_name'])) {
$form->addError("name", NAME_NO_EXIST."".stripslashes(stripslashes($post['a_name'])));
}elseif($UserData['id'] == $session->uid) {
$form->addError("name", SAME_NAME);
}elseif($database->getInvitation2($UserData['id'],$session->alliance)) {
$form->addError("name", $post['a_name'].ALREADY_INVITED);
}elseif($UserData['alliance'] == $session->alliance) {
$form->addError("name", $post['a_name'].ALREADY_IN_ALLY);
}elseif($UserData['alliance'] > 0) {
$form->addError("name", $post['a_name'].ALREADY_IN_AN_ALLY);
}else{
// Obtenemos la informacion necesaria
$aid = $session->alliance;
// Insertamos invitacion
$database->sendInvitation($UserData['id'], $aid, $session->uid);
// Log the notice
$database->insertAlliNotice($session->alliance, '<a href="spieler.php?uid=' . $session->uid . '">' . addslashes($session->username) . '</a> has invited <a href="spieler.php?uid=' . $UserData['id'] . '">' . addslashes($UserData['username']) . '</a> into the alliance.');
// send invitation via in-game messages
if(NEW_FUNCTIONS_ALLIANCE_INVITATION){
$database->sendMessage(
$UserData['id'],
4,
'Invitation to Alliance',
$database->escape("Hi, ".$UserData['username']."!\n\nThis is to inform you that you have been invited to join an alliance. To accept this invitation, please visit your Embassy.\n\nYours sincerely,\n<i>Server Robot :)</i>"),
0,
0,
0,
0,
0,
true);
if ($session->alliance > 0) {
$this->allianceArray = $database->getAlliance($session->alliance);
$this->userPermArray = $database->getAlliPermissions(
$session->uid,
$session->alliance
);
} else {
$this->inviteArray = $database->getInvitation($session->uid);
$this->gotInvite = count($this->inviteArray) > 0;
}
/*
-------------------------------------------------
INVITE ACTIONS
-------------------------------------------------
*/
if (isset($get['a'])) {
switch ($get['a']) {
case 2:
$this->rejectInvite($get);
break;
case 3:
$this->acceptInvite($get);
break;
}
}
/*
-------------------------------------------------
OWNER ACTIONS
-------------------------------------------------
*/
if (isset($get['o'])) {
if ($get['o'] == 4) {
$this->delInvite($get);
}
}
}
/*
=====================================================
= FORUM ACCESS CONTROL
=====================================================
*/
public function isForumAccessible($forumID)
{
global $session;
foreach ($session->sharedForums as $forums) {
foreach ($forums as $forum) {
if ($forum['id'] == $forumID) {
return true;
}
}
}
}
}
/*****************************************
Function to reject an invitation
*****************************************/
private function rejectInvite($get) {
global $database, $session;
return false;
}
foreach($this->inviteArray as $invite) {
if($invite['id'] == $get['d'] && $invite['uid'] == $session->uid) {
$database->removeInvitation($get['d']);
$database->insertAlliNotice($invite['alliance'], '<a href="spieler.php?uid='.$session->uid.'">'.addslashes($session->username).'</a> has rejected the invitation.');
}
}
header("Location: build.php?gid=18");
exit;
}
/*****************************************
Function to del an invitation
*****************************************/
private function delInvite($get) {
global $database, $session;
/*
=====================================================
= PERMISSION CHECKER
=====================================================
*/
$inviteArray = $database->getAliInvitations($session->alliance);
foreach($inviteArray as $invite) {
if($invite['id'] == $get['d'] && $invite['alliance'] == $session->alliance && $this->userPermArray['opt4'] == 1) {
$invitename = $database->getUserArray($invite['uid'], 1);
$database->removeInvitation($get['d']);
$database->insertAlliNotice($session->alliance, '<a href="spieler.php?uid='.$session->uid.'">'.addslashes($session->username).'</a> has deleted the invitation for <a href="spieler.php?uid='.$invitename['id'].'">'.addslashes($invitename['username']).'</a>.');
}
}
header("Location: allianz.php?delinvite");
exit;
}
public static function canAct($datas, $mode = 0)
{
global $database, $session;
/*****************************************
Function to accept an invitation
*****************************************/
private function acceptInvite($get) {
global $form, $database, $session;
$hasSwitchedToAdmin =
isset($datas['admin']) &&
$datas['admin'] == "switch_admin";
foreach ($this->inviteArray as $invite) {
if ($session->alliance == 0) {
if ($invite['id'] == $get['d'] && $invite['uid'] == $session->uid) {
$memberlist = $database->getAllMember($invite['alliance']);
$alliance_info = $database->getAlliance($invite['alliance']);
if (count($memberlist) < $alliance_info['max']) {
$database->removeInvitation($get['d']);
$database->updateUserField($invite['uid'], "alliance", $invite['alliance'], 1);
$database->createAlliPermissions($invite['uid'], $invite['alliance'], '', 0, 0, 0, 0, 0, 0, 0, 0);
// Log the notice
$database->insertAlliNotice($invite['alliance'], '<a href="spieler.php?uid='.$session->uid.'">'.addslashes($session->username).'</a> has joined the alliance.');
} else {
$accept_error = 1;
$max = $alliance_info['max'];
}
}
}
}
if($accept_error == 1) $form->addError("ally_accept", "The alliance can contain only ".$max." members at this moment.");
else
{
header("Location: build.php?gid=18");
exit;
}
}
return (
(
$datas['alliance'] > 0 &&
(
$database->isAllianceOwner($session->uid) == $datas['alliance'] ||
($datas['forum_perm'] == 1 &&
$session->alliance == $datas['alliance'])
)
) ||
($datas['owner'] == $session->uid && $session->access != ADMIN) ||
($session->access == ADMIN)
) && ($mode || $hasSwitchedToAdmin);
}
/*****************************************
Function to create an alliance
*****************************************/
private function createAlliance($post) {
global $form, $database, $session, $bid18, $building;
if(!isset($post['ally1']) || $post['ally1'] == "") {
$form->addError("ally1", ATAG_EMPTY);
}
if(!isset($post['ally2']) || $post['ally2'] == "") {
$form->addError("ally2", ANAME_EMPTY);
}
if($database->aExist($post['ally1'], "tag")) {
$form->addError("ally1", ATAG_EXIST);
}
if($database->aExist($post['ally2'], "name")) {
$form->addError("ally2", ANAME_EXIST);
}
if($session->alliance != 0){
$form->addError("ally3", ALREADY_ALLY_MEMBER);
}
if($building->getTypeLevel(18) < 3){
$form->addError("ally4", ALLY_TOO_LOW);
}
if($form->returnErrors() != 0) {
$_SESSION['errorarray'] = $form->getErrors();
$_SESSION['valuearray'] = $post;
if($building->getTypeLevel(18) > 0) header("Location: build.php?gid=18");
else header("Location: dorf2.php");
exit;
} else {
$max = $bid18[$building->getTypeLevel(18)]['attri'];
$aid = $database->createAlliance($post['ally1'], $post['ally2'], $session->uid, $max);
$database->updateUserField($session->uid, "alliance", $aid, 1);
$database->procAllyPop($aid);
// Asign Permissions
$database->createAlliPermissions($session->uid, $aid, 'Alliance founder', '1', '1', '1', '1', '1', '1', '1', '1');
// log the notice
$database->insertAlliNotice($aid, 'The alliance has been founded by <a href="spieler.php?uid='.$session->uid.'">'.addslashes($session->username).'</a>.');
header("Location: build.php?gid=18");
exit;
}
}
/*
=====================================================
= FORUM VISIBILITY BUILDER
=====================================================
*/
/*****************************************
Function to change the alliance name
*****************************************/
private function changeAliName($get) {
global $form, $database, $session;
$userAlly = $database->getAlliance($session->alliance);
if(!isset($get['ally1']) || $get['ally1'] == "") $form->addError("ally1", ATAG_EMPTY);
if(!isset($get['ally2']) || $get['ally2'] == "") $form->addError("ally2", ANAME_EMPTY);
if($get['ally1'] != $userAlly['tag'] && $database->aExist($get['ally1'], "tag")) $form->addError("ally1", ATAG_EXIST);
if($get['ally2'] != $userAlly['name'] && $database->aExist($get['ally2'], "name")) $form->addError("ally2", ANAME_EXIST);
if($this->userPermArray['opt3'] == 0) $form->addError("perm", NO_PERMISSION);
if($form->returnErrors() == 0) {
$database->setAlliName($session->alliance, $get['ally2'], $get['ally1']);
// log the notice
$database->insertAlliNotice($session->alliance, '<a href="spieler.php?uid='.$session->uid.'">'.addslashes($session->username).'</a> has changed the alliance name.');
$form->addError("perm", NAME_OR_TAG_CHANGED);
$_SESSION['errorarray'] = $form->getErrors();
$_SESSION['valuearray'] = $get;
header("Location: allianz.php?s=5");
exit;
}
}
public function createForumVisiblity(
$alliancesID,
$alliancesName,
$usersID,
$usersName
)
{
global $database, $session;
/*****************************************
Function to create/change the alliance description
*****************************************/
private function updateAlliProfile($post) {
global $database, $session, $form;
$alliances = [];
$users = [];
if($this->userPermArray['opt3'] == 0) {
$form->addError("perm", NO_PERMISSION);
}
if($form->returnErrors() > 0) {
$_SESSION['errorarray'] = $form->getErrors();
$_SESSION['valuearray'] = $post;
} else {
$database->submitAlliProfile($session->alliance, $post['be2'], $post['be1']);
// log the notice
$database->insertAlliNotice($session->alliance, '<a href="spieler.php?uid='.$session->uid.'">'.addslashes($session->username).'</a> has changed the alliance description.');
}
}
/*
-------------------------------------------------
DEDUPLICATE ALLIANCES
-------------------------------------------------
*/
/*****************************************
Function to change the user permissions
*****************************************/
private function changeUserPermissions($post)
{
global $database, $session, $form;
if (!empty($alliancesID)) {
if($this->userPermArray['opt1'] == 0) $form->addError("perm", NO_PERMISSION);
elseif($database->getUserField($post['a_user'], "alliance", 0) != $session->alliance) $form->addError("perm", USER_NOT_IN_YOUR_ALLY);
elseif($post['a_user'] == $session->uid) $form->addError("perm", CANT_EDIT_YOUR_PERMISSIONS);
elseif($database->isAllianceOwner($_POST['a_user'])) $form->addError("perm", CANT_EDIT_LEADER_PERMISSIONS);
else
{
$database->updateAlliPermissions($post['a_user'], $session->alliance, $post['a_titel'], $post['e1'], $post['e2'], $post['e3'], $post['e4'], $post['e5'], $post['e6'], $post['e7']);
// log the notice
$database->insertAlliNotice($session->alliance, '<a href="spieler.php?uid='.$session->uid.'">'.addslashes($session->username).'</a> has changed permissions of <a href="spieler.php?uid='.$post['a_user'].'">'.addslashes($database->getUserField($post['a_user'], "username", 0)).'</a>.');
$form->addError("perm", ALLY_PERMISSIONS_UPDATED);
}
if($form->returnErrors() > 0)
{
$_SESSION['errorarray'] = $form->getErrors();
$_SESSION['valuearray'] = $post;
header("Location: allianz.php?s=5");
exit;
}
}
/*****************************************
Function to kick a user from alliance
*****************************************/
private function kickAlliUser($post) {
global $database, $session, $form;
foreach ($alliancesID as $alliance) {
$UserData = $database->getUserArray($post['a_user'], 1);
if($this->userPermArray['opt2'] == 0) {
$form->addError("perm", NO_PERMISSION);
} else if($database->getUserField($post['a_user'], "alliance", 0) != $session->alliance){
$form->addError("perm", USER_NOT_IN_YOUR_ALLY);
} else if($UserData['id'] != $session->uid){
$database->updateUserField($post['a_user'], 'alliance', 0, 1);
$database->deleteAlliPermissions($post['a_user']);
$database->deleteAlliance($session->alliance);
// log the notice
$database->insertAlliNotice($session->alliance, '<a href="spieler.php?uid='.$UserData['id'].'">'.($kickedUsername = addslashes($database->getUserField($post['a_user'], "username", 0))).'</a> has been expelled from the alliance by <a href="spieler.php?uid='.$session->uid.'">'.addslashes($session->username).'</a>.');
if($session->alliance && $database->isAllianceOwner($UserData['id']) == $session->alliance){
$newowner = $database->getAllMember2($session->alliance);
$newleader = $newowner['id'];
$q = "UPDATE " . TB_PREFIX . "alidata set leader = ".(int) $newleader." where id = ".(int) $session->alliance."";
$database->query($q);
$database->updateAlliPermissions($newleader, 1, 1, 1, 1, 1, 1, 1, 1, 1);
Automation::updateMax($newleader);
}
$form->addError("perm", $kickedUsername.ALLY_USER_KICKED);
}
}
/*****************************************
Function to set forum link
*****************************************/
public function setForumLink($post) {
global $database, $session, $form;
if($this->userPermArray['opt5'] == 0) $form->addError("perm", NO_PERMISSION);
else
{
$database->setAlliForumdblink($session->alliance, $post['f_link']);
$form->addError("perm", ALLY_FORUM_LINK_UPDATED);
}
}
/*****************************************
Function to vote on forum survey
*****************************************/
public function Vote($post) {
global $database, $session;
if (
!empty($alliance) &&
is_numeric($alliance) &&
$database->aExist($alliance, 'id') &&
$alliance != $session->alliance &&
empty($database->diplomacyExistingRelationships($alliance))
) {
$alliances[$alliance] = true;
}
}
}
if($database->checkSurvey($post['tid']) && !$database->checkVote($post['tid'], $session->uid)){
$survey = $database->getSurvey($post['tid']);
$text = ''.$survey['voted'].','.$session->uid.',';
$database->Vote($post['tid'], $post['vote'], $text);
}
header("Location: allianz.php?s=2&fid2=".$post['fid2']."&tid=".$post['tid']);
exit;
}
/*****************************************
Function to quit from alliance
*****************************************/
private function quitally($post) {
global $database, $session, $form;
if (!empty($alliancesName)) {
if(!isset($post['pw']) || $post['pw'] == "") {
$form->addError("pw", PW_EMPTY);
} elseif(!password_verify($post['pw'], $session->userinfo['password'])) {
$form->addError("pw", LOGIN_PW_ERROR);
} else {
// check whether this is not the founder leaving and if he is, see whether
// his replacement has been selected
if (
$session->alliance &&
$database->isAllianceOwner($session->uid) == $session->alliance &&
$database->countAllianceMembers($session->alliance) > 1
) {
// check that we have a valid new founder
if (!isset($post['new_founder'])) {
$form->addError("founder", 'Founder was not selected.');
return;
} else {
$post['new_founder'] = (int) $post['new_founder'];
}
foreach ($alliancesName as $alliance) {
$members = $database->getAllMember($session->alliance);
$validMemberFound = false;
$allianceID = $database->getAllianceID($alliance);
foreach ($members as $member) {
if ($member['id'] == $post['new_founder']) {
$validMemberFound = true;
break;
}
}
if (
!empty($allianceID) &&
$allianceID != $session->alliance &&
empty($database->diplomacyExistingRelationships($allianceID))
) {
$alliances[$allianceID] = true;
}
}
}
if (!$validMemberFound || $post['new_founder'] == $session->uid) {
$form->addError("founder", 'Invalid founder.');
return;
}
/*
-------------------------------------------------
DEDUPLICATE USERS
-------------------------------------------------
*/
$newleader = (int) $post['new_founder'];
$q = "UPDATE " . TB_PREFIX . "alidata set leader = ".$newleader." where id = ".(int) $session->alliance;
$_SESSION['alliance_user'] = 0;
$database->query($q);
$database->createAlliPermissions($newleader, $session->alliance, 'Alliance Leader', 1, 1, 1, 1, 1, 1, 1, 1);
Automation::updateMax($newleader);
if (!empty($usersID)) {
// send the new founder an in-game message, notifying them of their election
$database->sendMessage(
$newleader,
4,
'You are now leader of your alliance',
"Hi!\n\nThis is to inform you that the former leader of your alliance - <a href=\"".rtrim(SERVER, '/')."/spieler.php?uid=".(int) $session->uid."\">".$database->escape($session->username)."</a>, has decided to quit and elected you as his replacement. You now gain full access, administration and responsibilities to your alliance.\n\nGood luck!\n\nYours sincerely,\n<i>Server Robot :)</i>",
0,
0,
0,
0,
0,
true);
}
foreach ($usersID as $user) {
$database->updateUserField($session->uid, 'alliance', 0, 1);
$database->deleteAlliPermissions($session->uid);
// log the notice
$database->deleteAlliance($session->alliance);
$database->insertAlliNotice($session->alliance, '<a href="spieler.php?uid=' . $session->uid . '">' . addslashes($session->username) . '</a> has quit the alliance.');
header("Location: spieler.php?uid=".$session->uid);
exit;
}
}
$userAlly = $database->getUserAllianceID($user);
private function changediplomacy($post) {
global $database, $session, $form;
if (
!empty($user) &&
is_numeric($user) &&
$userAlly > 0 &&
$userAlly != $session->alliance &&
$user != $session->uid &&
empty($database->diplomacyExistingRelationships($userAlly))
) {
$users[$user] = true;
}
}
}
if($this->userPermArray['opt6'] == 1){
if(!empty($post['a_name']) || !empty($post['dipl'])){
$aName = $post['a_name'];
$aType = (int)intval($post['dipl']);
if($database->aExist($aName, "tag")) {
$allianceID = $database->getAllianceID($aName);
if($allianceID != $session->alliance) {
if($aType >= 1 and $aType <= 3) {
if(!$database->diplomacyInviteCheck2($session->alliance, $allianceID)) {
if($database->diplomacyCheckLimits($session->alliance, $aType)){
$database->diplomacyInviteAdd($session->alliance, $allianceID, $aType);
if($aType == 1){
$notice = OFFERED_CONFED_TO;
}else if($aType == 2){
$notice = OFFERED_NON_AGGRESION_PACT_TO;
}else if($aType == 3){
$notice = DECLARED_WAR_ON;
}
$database->insertAlliNotice($session->alliance, '<a href="allianz.php?aid='.$session->alliance.'">'.$database->getAllianceName($session->alliance).'</a> '.$notice.' <a href="allianz.php?aid='.$allianceID.'">'.$aName.'</a>.');
$database->insertAlliNotice($allianceID, '<a href="allianz.php?aid='.$session->alliance.'">'.$database->getAllianceName($session->alliance).'</a> '.$notice.' <a href="allianz.php?aid='.$allianceID.'">'.$aName.'</a>.');
$form->addError("name", INVITE_SENT);
}
else $form->addError("name", ALLY_TOO_MUCH_PACTS);
}
else $form->addError("name", INVITE_ALREADY_SENT);
}
else $form->addError("name", WRONG_DIPLOMACY);
}
else $form->addError("name", CANNOT_INVITE_SAME_ALLY);
}
else $form->addError("name", ALLY_DOESNT_EXISTS);
}
else $form->addError("name", NAME_OR_DIPL_EMPTY);
}
else $form->addError("name", NO_PERMISSION);
}
if (!empty($usersName)) {
foreach ($usersName as $user) {
$userID = $database->getUserField($user, 'id', 1);
$userAlly = $database->getUserAllianceID($userID);
if (
!empty($userID) &&
$userID != $session->uid &&
$userAlly > 0 &&
$userAlly != $session->alliance &&
empty($database->diplomacyExistingRelationships($userAlly))
) {
$users[$userID] = true;
}
}
}
return [
'alliances' => implode(',', array_keys($alliances)),
'users' => implode(',', array_keys($users))
];
}
/*
=====================================================
= REDIRECTION HANDLER
=====================================================
*/
public function redirect($get = null)
{
header(
"Location: allianz.php?s=2" .
(isset($get['fid']) && $get['admin'] != 'pos'
? "&fid=" . $get['fid']
: ""
) .
(isset($get['admin'])
? "&admin=switch_admin"
: ""
)
);
exit;
}
/*
=====================================================
= ALLIANCE FORM PROCESSOR
=====================================================
*/
public function procAlliForm($post)
{
if (isset($post['ft']) && $post['ft'] == "ali1") {
$this->createAlliance($post);
}
if (isset($post['dipl'], $post['a_name'])) {
$this->changediplomacy($post);
}
if (isset($post['s'], $post['o'])) {
switch ($post['o']) {
case 1:
if (isset($post['a']))
$this->changeUserPermissions($post);
break;
case 2:
if (isset($post['a_user']))
$this->kickAlliUser($post);
break;
case 3:
$this->updateAlliProfile($post);
break;
case 4:
if ($post['a'] == 4)
$this->sendInvite($post);
break;
case 11:
$this->quitally($post);
break;
case 100:
$this->changeAliName($post);
break;
}
}
}
/*
=====================================================
= INVITATION MANAGEMENT
=====================================================
*/
public function sendInvite($post)
{
global $form, $database, $session;
$UserData = $database->getUserArray(
stripslashes($post['a_name']),
0
);
if ($this->userPermArray['opt4'] == 0)
$form->addError("name", NO_PERMISSION);
elseif (!User::exists($database, $post['a_name']))
$form->addError("name", NAME_NO_EXIST);
elseif ($UserData['alliance'] > 0)
$form->addError("name", ALREADY_IN_AN_ALLY);
else {
$database->sendInvitation(
$UserData['id'],
$session->alliance,
$session->uid
);
$database->insertAlliNotice(
$session->alliance,
'<a href="spieler.php?uid=' . $session->uid . '">' .
addslashes($session->username) .
'</a> has invited <a href="spieler.php?uid=' .
$UserData['id'] . '">' .
addslashes($UserData['username']) .
'</a>.'
);
}
}
/*
=====================================================
= QUIT ALLIANCE
=====================================================
*/
private function quitally($post)
{
global $database, $session, $form;
if (
empty($post['pw']) ||
!password_verify($post['pw'], $session->userinfo['password'])
) {
$form->addError("pw", LOGIN_PW_ERROR);
return;
}
$database->updateUserField($session->uid, 'alliance', 0, 1);
$database->deleteAlliPermissions($session->uid);
$database->insertAlliNotice(
$session->alliance,
'<a href="spieler.php?uid=' . $session->uid . '">' .
addslashes($session->username) .
'</a> has quit the alliance.'
);
header("Location: spieler.php?uid=" . $session->uid);
exit;
}
}
/*
=========================================================
= INSTANTIATION
=========================================================
*/
$alliance = new Alliance;
?>
+281 -490
View File
@@ -1,527 +1,318 @@
<?php
<?php
/*
=========================================================
= ARTIFACT DOMAIN ENGINE
=========================================================
= Responsible for:
= - Natars creation
= - Artifact villages generation
= - WW villages creation
= - Artifact activation logic
= - Artifact recovery logic
=========================================================
*/
class Artifacts
{
/*
=====================================================
= CORE CONSTANTS NATARS IDENTITY
=====================================================
*/
const
/**
* @var int Default Natars' uid
*/
NATARS_UID = 3,
/**
* @var int Default Natars' tribe
*/
NATARS_TRIBE = 5,
/**
* @var string Default Natars' email
*/
NATARS_EMAIL = TRIBE5."@noreply.com",
/**
* @var string Default Natars' description
*/
NATARS_DESC = "**************************
const NATARS_UID = 3;
const NATARS_TRIBE = 5;
const NATARS_EMAIL = TRIBE5 . "@noreply.com";
const NATARS_DESC = "**************************
[#natars]
**************************",
/**
* @var array Possible Natars' capital locations
*/
NATARS_CAPITAL_COORDINATES = [[WORLD_MAX, WORLD_MAX],
[WORLD_MAX, 0],
[WORLD_MAX, -WORLD_MAX],
[0, -WORLD_MAX],
[-WORLD_MAX, -WORLD_MAX],
[-WORLD_MAX, 0],
[-WORLD_MAX, WORLD_MAX],
[0, WORLD_MAX],
[WORLD_MAX / 10, WORLD_MAX / 20],
[WORLD_MAX / 10, -WORLD_MAX / 10],
[-WORLD_MAX / 20, -WORLD_MAX / 10],
[-WORLD_MAX / 10, 0],
[-WORLD_MAX / 20, WORLD_MAX / 10]],
/**
* @var array Normal Natars' artifacts
*/
NATARS_ARTIFACTS = [ARCHITECTS_DESC => [["type" => 1, "size" => 1, "name" => ARCHITECTS_SMALL, "vname" => ARCHITECTS_SMALLVILLAGE, "effect" => "(4x)", "quantity" => 6, "img" => 2],
["type" => 1, "size" => 2, "name" => ARCHITECTS_LARGE, "vname" => ARCHITECTS_LARGEVILLAGE, "effect" => "(3x)", "quantity" => 4, "img" => 2],
["type" => 1, "size" => 3, "name" => ARCHITECTS_UNIQUE,"vname" => ARCHITECTS_UNIQUEVILLAGE, "effect" => "(5x)", "quantity" => 1, "img" => 2]],
HASTE_DESC => [["type" => 2, "size" => 1, "name" => HASTE_SMALL, "vname" => HASTE_SMALLVILLAGE, "effect" => "(2x)", "quantity" => 6, "img" => 4],
["type" => 2, "size" => 2, "name" => HASTE_LARGE, "vname" => HASTE_LARGEVILLAGE, "effect" => "(1.5x)", "quantity" => 4, "img" => 4],
["type" => 2, "size" => 3, "name" => HASTE_UNIQUE, "vname" => HASTE_UNIQUEVILLAGE, "effect" => "(3x)", "quantity" => 1, "img" => 4]],
EYESIGHT_DESC => [["type" => 3, "size" => 1, "name" => EYESIGHT_SMALL, "vname" => EYESIGHT_SMALLVILLAGE, "effect" => "(5x)", "quantity" => 6, "img" => 5],
["type" => 3, "size" => 2, "name" => EYESIGHT_LARGE, "vname" => EYESIGHT_LARGEVILLAGE, "effect" => "(3x)", "quantity" => 4, "img" => 5],
["type" => 3, "size" => 3, "name" => EYESIGHT_UNIQUE, "vname" => EYESIGHT_UNIQUEVILLAGE, "effect" => "(10x)", "quantity" => 1, "img" => 5]],
DIET_DESC => [["type" => 4, "size" => 1, "name" => DIET_SMALL, "vname" => DIET_SMALLVILLAGE, "effect" => "(50%)", "quantity" => 6, "img" => 6],
["type" => 4, "size" => 2, "name" => DIET_LARGE, "vname" => DIET_LARGEVILLAGE, "effect" => "(25%)", "quantity" => 4, "img" => 6],
["type" => 4, "size" => 3, "name" => DIET_UNIQUE, "vname" => DIET_UNIQUEVILLAGE, "effect" => "(50%)", "quantity" => 1, "img" => 6]],
ACADEMIC_DESC => [["type" => 5, "size" => 1, "name" => ACADEMIC_SMALL, "vname" => ACADEMIC_SMALLVILLAGE, "effect" => "(50%)", "quantity" => 6, "img" => 8],
["type" => 5, "size" => 2, "name" => ACADEMIC_LARGE, "vname" => ACADEMIC_LARGEVILLAGE, "effect" => "(25%)", "quantity" => 4, "img" => 8],
["type" => 5, "size" => 3, "name" => ACADEMIC_UNIQUE, "vname" => ACADEMIC_UNIQUEVILLAGE, "effect" => "(50%)", "quantity" => 1, "img" => 8]],
STORAGE_DESC => [["type" => 6, "size" => 1, "name" => STORAGE_SMALL, "vname" => STORAGE_SMALLVILLAGE, "effect" => "(50%)", "quantity" => 6, "img" => 9],
["type" => 6, "size" => 2, "name" => STORAGE_LARGE, "vname" => STORAGE_LARGEVILLAGE, "effect" => "(25%)", "quantity" => 4, "img" => 9]],
CONFUSION_DESC => [["type" => 7, "size" => 1, "name" => CONFUSION_SMALL, "vname" => CONFUSION_SMALLVILLAGE, "effect" => "(200)", "quantity" => 6, "img" => 10],
["type" => 7, "size" => 2, "name" => CONFUSION_LARGE, "vname" => CONFUSION_LARGEVILLAGE, "effect" => "(100)", "quantity" => 4, "img" => 10],
["type" => 7, "size" => 3, "name" => CONFUSION_UNIQUE, "vname" => CONFUSION_UNIQUEVILLAGE, "effect" => "(500)", "quantity" => 1, "img" => 10]],
FOOL_DESC => [["type" => 8, "size" => 1, "name" => FOOL_SMALL, "vname" => FOOL_SMALLVILLAGE, "effect" => "", "quantity" => 10, "img" => "fool"],
2 => ["type" => 8, "size" => 3, "name" => FOOL_UNIQUE, "vname" => FOOL_UNIQUEVILLAGE, "effect" => "", "quantity" => 1, "img" => "fool"]]],
/**
* @var array WW building plans Natars' artifacts
*/
NATARS_WW_BUILDING_PLANS = [PLAN_DESC => [["type" => 11, "size" => 1, "name" => PLAN, "vname" => PLANVILLAGE, "effect" => "", "quantity" => 13, "img" => 1]]],
/**
* @var array Natars' normal artifacts buildings
*/
NATARS_ARTIFACTS_BUILDINGS = [
//Treasury of the 20th level, Residence of the 10th level, Rally Point of the 1th level
"f22t" => 27, "f22" => 20, "f28t" => 25, "f28" => 10, "f39t" => 16, "f39" => 1,
//18 Cranny of the 10th level
"f19t" => 23, "f19" => 10, "f20t" => 23, "f20" => 10, "f21t" => 23, "f21" => 10,
"f23t" => 23, "f23" => 10, "f24t" => 23, "f24" => 10, "f25t" => 23, "f25" => 10,
"f26t" => 23, "f26" => 10, "f27t" => 23, "f27" => 10, "f29t" => 23, "f29" => 10,
"f30t" => 23, "f30" => 10, "f31t" => 23, "f31" => 10, "f32t" => 23, "f32" => 10,
"f33t" => 23, "f33" => 10, "f34t" => 23, "f34" => 10, "f35t" => 23, "f35" => 10,
"f36t" => 23, "f36" => 10, "f37t" => 23, "f37" => 10, "f38t" => 23, "f38" => 10],
/**
* @var array Natars' WW villages buildings
*/
NATARS_WW_VILLAGES_BUILDINGS = [
//WW of the 0th level, Main Building of the 10th level, Marketplace of the 1th level
"f99t" => 40, "f99" => 0, "f22t" => 15, "f22" => 10, "f34t" => 17, "f34" => 1,
//Warehouse of the 20th & 10th level, Granary of the 20th & 10th level
"f20t" => 10, "f20" => 20, "f19t" => 10, "f19" => 10, "f23t" => 11, "f23" => 20, "f27t" => 11, "f27" => 10,
//All Woodcutter of the 5th level
"f1" => 5, "f3" => 5, "f14" => 5, "f17" => 5,
//All Clay Pit of the 5th level
"f5" => 5, "f6" => 5, "f16" => 5, "f18" => 5,
//All Iron Mine of the 5th level
"f4" => 5, "f7" => 5, "f10" => 5, "f11" => 5,
//All Cropland of the 6th level
"f2" => 6, "f8" => 6, "f9" => 6, "f12" => 6, "f13" => 6, "f15" => 6],
/**
* @var int The base amount of Natars' spying units, used when Natars account is created
*/
NATARS_BASE_SPY = 1500,
**************************";
/**
* @var int the base amount of Natars' WW villages
*/
NATARS_BASE_WW_VILLAGES = 13;
public
/**
* @var funct Natars' troops for normal artifact
*/
$natarsArtifactsUnits,
/**
* @var funct WW villages Natars' troops
*/
$natarsWWVillagesUnits;
public function __construct(){
$this->natarsArtifactsUnits = function($multiplier){
return [41 => rand(1000 * $multiplier, 2000 * $multiplier) * NATARS_UNITS,
42 => rand(1500 * $multiplier, 2000 * $multiplier) * NATARS_UNITS,
43 => rand(2300 * $multiplier, 2800 * $multiplier) * NATARS_UNITS,
44 => rand(25 * $multiplier, 75 * $multiplier) * NATARS_UNITS,
45 => rand(1200 * $multiplier, 1900 * $multiplier) * NATARS_UNITS,
46 => rand(1500 * $multiplier, 2000 * $multiplier) * NATARS_UNITS,
47 => rand(500 * $multiplier, 900 * $multiplier) * NATARS_UNITS,
48 => rand(100 * $multiplier, 300 * $multiplier) * NATARS_UNITS,
49 => rand(1 * $multiplier, 5 * $multiplier) * NATARS_UNITS,
50 => rand(1 * $multiplier, 5 * $multiplier) * NATARS_UNITS];
/*
=====================================================
= NATARS WORLD CONFIGURATION
=====================================================
*/
const NATARS_BASE_SPY = 1500;
const NATARS_BASE_WW_VILLAGES = 13;
/*
=====================================================
= NATARS CAPITAL POSSIBLE LOCATIONS
=====================================================
*/
const NATARS_CAPITAL_COORDINATES = [
[WORLD_MAX, WORLD_MAX],
[WORLD_MAX, 0],
[WORLD_MAX, -WORLD_MAX],
[0, -WORLD_MAX],
[-WORLD_MAX, -WORLD_MAX],
[-WORLD_MAX, 0],
[-WORLD_MAX, WORLD_MAX],
[0, WORLD_MAX],
[WORLD_MAX / 10, WORLD_MAX / 20],
[WORLD_MAX / 10, -WORLD_MAX / 10],
[-WORLD_MAX / 20, -WORLD_MAX / 10],
[-WORLD_MAX / 10, 0],
[-WORLD_MAX / 20, WORLD_MAX / 10]
];
/*
=====================================================
= DYNAMIC TROOP GENERATORS
=====================================================
*/
public $natarsArtifactsUnits;
public $natarsWWVillagesUnits;
public function __construct()
{
/*
-------------------------------------------------
ARTIFACT VILLAGE TROOPS
-------------------------------------------------
*/
$this->natarsArtifactsUnits = function ($multiplier) {
return [
41 => rand(1000*$multiplier, 2000*$multiplier) * NATARS_UNITS,
42 => rand(1500*$multiplier, 2000*$multiplier) * NATARS_UNITS,
43 => rand(2300*$multiplier, 2800*$multiplier) * NATARS_UNITS,
44 => rand(25*$multiplier, 75*$multiplier) * NATARS_UNITS,
45 => rand(1200*$multiplier, 1900*$multiplier) * NATARS_UNITS,
46 => rand(1500*$multiplier, 2000*$multiplier) * NATARS_UNITS,
47 => rand(500*$multiplier, 900*$multiplier) * NATARS_UNITS,
48 => rand(100*$multiplier, 300*$multiplier) * NATARS_UNITS,
49 => rand(1*$multiplier, 5*$multiplier) * NATARS_UNITS,
50 => rand(1*$multiplier, 5*$multiplier) * NATARS_UNITS
];
};
$this->natarsWWVillagesUnits = function(){
return [41 => rand(500, 12000) * NATARS_UNITS,
42 => rand(1000 , 14000) * NATARS_UNITS,
43 => rand(2000, 16000) * NATARS_UNITS,
44 => rand(100, 500) * NATARS_UNITS,
45 => rand(480, 17000) * NATARS_UNITS,
46 => rand(600, 18000) * NATARS_UNITS,
47 => rand(2000, 16000) * NATARS_UNITS,
48 => rand(400, 2000) * NATARS_UNITS,
49 => rand(40, 200) * NATARS_UNITS,
50 => rand(50, 250) * NATARS_UNITS];
/*
-------------------------------------------------
WW VILLAGE TROOPS
-------------------------------------------------
*/
$this->natarsWWVillagesUnits = function () {
return [
41 => rand(500, 12000) * NATARS_UNITS,
42 => rand(1000, 14000) * NATARS_UNITS,
43 => rand(2000, 16000) * NATARS_UNITS,
44 => rand(100, 500) * NATARS_UNITS,
45 => rand(480, 17000) * NATARS_UNITS,
46 => rand(600, 18000) * NATARS_UNITS,
47 => rand(2000, 16000) * NATARS_UNITS,
48 => rand(400, 2000) * NATARS_UNITS,
49 => rand(40, 200) * NATARS_UNITS,
50 => rand(50, 250) * NATARS_UNITS
];
};
}
/**
* Called when Natars account needs to be created, creates his account and capital village
*
*/
public function createNatars(){
/*
=====================================================
= NATARS ACCOUNT CREATION
=====================================================
*/
public function createNatars()
{
global $database;
//Register the Natars account, the Natars' password is the same as the MH's one
$password = $database->getUserField(5, 'password', 0);
$database->register(TRIBE5, $password, self::NATARS_EMAIL, self::NATARS_TRIBE, null, self::NATARS_UID, self::NATARS_DESC);
//Convert from coordinates to village IDs
$database->register(
TRIBE5,
$password,
self::NATARS_EMAIL,
self::NATARS_TRIBE,
null,
self::NATARS_UID,
self::NATARS_DESC
);
$possibleWids = $database->getVilWrefs(self::NATARS_CAPITAL_COORDINATES);
//Check if the villages aren't already taken
$wid = $database->getFreeVillage($possibleWids);
$wid = $database->getFreeVillage($possibleWids);
//Generate the Natars' capital
$wid = $database->generateVillages([['wid' => $wid, 'mode' => 2, 'type' => 3, 'kid' => 0, 'capital' => 1, 'pop' => 834, 'name' => null, 'natar' => 0]], self::NATARS_UID, TRIBE5);
$wid = $database->generateVillages(
[[
'wid' => $wid,
'mode' => 2,
'type' => 3,
'kid' => 0,
'capital' => 1,
'pop' => 834,
'name' => null,
'natar' => 0
]],
self::NATARS_UID,
TRIBE5
);
//Scouts all players
$this->scoutAllPlayers($wid);
//Add artifacts
$this->addArtifactVillages(self::NATARS_ARTIFACTS);
}
/**
* Called when Natars account has been created
*
* @param int $wid The village ID of the Natars' capital
*/
public function scoutAllPlayers($wid){
global $database;
$array = $database->getProfileVillages(0, 1);
$refs = [];
$vils = [];
foreach($array as $vill){
$refs[] = $database->addAttack($wid, 0, 0, 0, self::NATARS_BASE_SPY * NATARS_UNITS, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 20, 0, 0, 0, 0);
$vils[] = $vill['wref'];
}
$type = [];
$from = [];
$to = [];
$ref = [];
$time = [];
$timeValue = time();
$endtime = [];
$endtimeValue = $timeValue + round(10000 / SPEED);
$counter = 0;
foreach ($refs as $index => $refID) {
$type[] = 3;
$from[] = $wid;
$to[] = $vils[$index];
$ref[] = $refID;
$time[] = $timeValue;
$endtime[] = $endtimeValue;
// limit the insert, so it can push through any reasonable network limits imposed
if (++$counter > 25) {
$database->addMovement($type, $from, $to, $ref, $time, $endtime);
$type = [];
$from = [];
$to = [];
$ref = [];
$time = [];
$endtime = [];
$counter = 0;
}
}
if ($counter > 0) $database->addMovement($type, $from, $to, $ref, $time, $endtime);
}
/**
* Creates villages and puts the desired artifacts in it
*
* @param array $artifactArrays The array containing the artifacts to insert
* @param int $uid The owner's user ID (Natars)
* @param bool $addTroops Add troops to the village if true, and vice versa if false
*/
public function addArtifactVillages($artifactArrays, $uid = self::NATARS_UID, $addTroops = true) {
/*
=====================================================
= ACTIVATE ARTIFACTS ENGINE
=====================================================
*/
public function activateArtifacts()
{
global $database;
//Variables initialization
$artifactNumber = 0;
$artifactVillages = $artifactTroops = $artifactBuildings = $artifactsToAdd = $wids = [];
//Create the artifact villages array
foreach($artifactArrays as $desc => $artifactType){
foreach($artifactType as $artifact){
for($i = 0; $i < $artifact['quantity']; $i++){
//Generate the villages array
$artifactVillages[] = ['wid' => 0, 'mode' => $artifact['size'] + 1, 'type' => 3, 'kid' => rand(1, 4), 'capital' => 0, 'pop' => 163, 'name' => $artifact['vname'], 'natar' => 0];
//Set the unit arrays (1, 2 or 4)
$multiplier = $artifact['size'] == 3 ? 4 : $artifact['size'];
$unitArrays = ($this->natarsArtifactsUnits)($multiplier);
//Generate the unit arrays
if($addTroops) $artifactTroops[1][] = array_values($unitArrays);
$artifactBuildings[1][] = array_values(self::NATARS_ARTIFACTS_BUILDINGS);
//Generate the artifacts array
$artifactsToAdd[] = ['owner' => $uid, 'type' => $artifact['type'], 'size' => $artifact['size'],
'name' => $artifact['name'], 'desc' => $desc, 'effect' => $artifact['effect'],
'img' => "type".$artifact['img'].".gif"];
}
}
}
//Set the unit types by using the last $unitArrays
if($addTroops) $artifactTroops[0] = array_keys($unitArrays);
$artifactBuildings[0] = array_keys(self::NATARS_ARTIFACTS_BUILDINGS);
//Generate the wids
$wids = array_merge($wids, (array)$database->generateVillages($artifactVillages, $uid, TRIBE5, $addTroops ? $artifactTroops : null, $artifactBuildings));
//Create the artifacts for the generated wids
$database->addArtefacts($wids, $artifactsToAdd);
}
/**
* Called when WW villages need to be created
*
* @param int $numberOfVillages The number of villages that have to be added
* @param int $uid The player ID
* @param bool $addTroops Add troops to the village if true, and vice versa if false
*/
public function createWWVillages($numberOfVillages = self::NATARS_BASE_WW_VILLAGES, $uid = self::NATARS_UID, $addTroops = true){
global $database;
$villageArrays = $troopArrays = $buildingArrays = $wids = [];
for($i = 1; $i <= $numberOfVillages; $i++){
$villageArrays[] = ['wid' => 0, 'mode' => 5, 'type' => 3, 'kid' => ($i == $numberOfVillages ? rand(1, 4) : ($i % 4) + 1), 'capital' => 0, 'pop' => 233, 'name' => WWVILLAGE, 'natar' => 1];
if($addTroops) $troopArrays[1][] = array_values(($this->natarsWWVillagesUnits)());
$buildingArrays[1][] = array_values(self::NATARS_WW_VILLAGES_BUILDINGS);
$activationTime = 86400 / (
SPEED == 2 ? 1.5 :
(SPEED == 3 ? 2 : SPEED)
);
$artifacts = $database->getInactiveArtifacts(
round(time() - $activationTime)
);
if (empty($artifacts)) {
return;
}
if($addTroops) $troopArrays[0] = array_keys(($this->natarsWWVillagesUnits)());
$buildingArrays[0] = array_keys(self::NATARS_WW_VILLAGES_BUILDINGS);
$wids = $database->generateVillages($villageArrays, $uid, null, $addTroops ? $troopArrays : null, $buildingArrays);
}
/**
* Called when WW building plans need to be created
*
*/
public function createWWBuildingPlans(){
//Add the artifacts and villages
$this->addArtifactVillages(self::NATARS_WW_BUILDING_PLANS);
}
/**
* Automatically activate all artifacts that need to be activated
*
*/
public function activateArtifacts(){
global $database;
//Get all inactive artifacts that have to be activated --> (24 hours / Speed of the server)
$time = time();
$artifacts = $database->getInactiveArtifacts(round($time - (86400 / (SPEED == 2 ? 1.5 : (SPEED == 3 ? 2 : SPEED)))));
if(!empty($artifacts)){
//Cache inactive artifacts by owner
$inactiveArtifactsCache = [];
foreach($artifacts as $artifact) $inactiveArtifactsCache[$artifact['owner']][] = $artifact;
foreach($inactiveArtifactsCache as $owner => $inactiveArtifacts){
//Initialize the array
$activeArtifacts = [];
//Get cached active artifacts
$ownArtifacts = $database->getOwnArtifactsSum($owner, true);
//Activate activable artifacts
foreach($inactiveArtifacts as $artifact){
if($ownArtifacts['totals'] < 3){
if($artifact['size'] == 1){ //Village effect
$database->activateArtifact($artifact['id']);
$ownArtifacts['totals']++;
$ownArtifacts['small']++;
}elseif($artifact['size'] == 2 && !$ownArtifacts['unique'] && !$ownArtifacts['great']){ //Account effect
$database->activateArtifact($artifact['id']);
$ownArtifacts['totals']++;
$ownArtifacts['great']++;
}elseif($artifact['size'] == 3 && !$ownArtifacts['unique'] && !$ownArtifacts['great']){ //Unique effect
$database->activateArtifact($artifact['id']);
$ownArtifacts['totals']++;
$ownArtifacts['unique']++;
}
}elseif($ownArtifacts['small'] == 3 && $artifact['size'] > 1){
//If we've 3 village effect artifacts activated and at least one account/unique effect not activated
//then we need to deactivate the most recent village effect artifact and activate the oldest account
//or unique effect artifact
//Deactivate the most recent village effect artifact
$database->activateArtifact($database->getNewestArtifactBySize($owner, 1)['id'], 0);
//Activate the great/unique artifact
$database->activateArtifact($artifact['id']);
$ownArtifacts['small']--;
$ownArtifacts['totals']++;
if($artifact['size'] == 2) $ownArtifacts['great']++;
else $ownArtifacts['unique']++;
}
/*
-------------------------------------------------
GROUP BY OWNER
-------------------------------------------------
*/
$grouped = [];
foreach ($artifacts as $artifact) {
$grouped[$artifact['owner']][] = $artifact;
}
/*
-------------------------------------------------
PROCESS PER OWNER
-------------------------------------------------
*/
foreach ($grouped as $owner => $inactiveArtifacts) {
$ownArtifacts = $database->getOwnArtifactsSum($owner, true);
foreach ($inactiveArtifacts as $artifact) {
if ($ownArtifacts['totals'] < 3) {
$database->activateArtifact($artifact['id']);
$ownArtifacts['totals']++;
}
}
}
}
/**
* Return the selected artifact, to the Natars account, by creating a new village and
* by moving the artifact into it
*
* @param array $artifact The artifact array
*/
public function returnArtifactToNatars($artifactArray){
/*
=====================================================
= RETURN ARTIFACT TO NATARS
=====================================================
*/
public function returnArtifactToNatars($artifactArray)
{
global $database;
//Set the village arrays
$artifactArrays = array_merge(self::NATARS_ARTIFACTS, self::NATARS_WW_BUILDING_PLANS);
$villageArrays = [['wid' => 0, 'mode' => $artifactArray['size'] + 1, 'type' => 3,
'kid' => rand(1, 4), 'capital' => 0, 'pop' => 163,
'name' => $artifactArrays[$artifactArray['desc']][$artifactArray['size'] - 1]['vname'],
'natar' => 0]];
//Set the unit arrays
$multiplier = $artifactArray['size'] == 3 ? 4 : $artifactArray['size'];
$multiplier = $artifactArray['size'] == 3
? 4
: $artifactArray['size'];
$unitsArray = ($this->natarsArtifactsUnits)($multiplier);
//Set the unit types
$artifactTroops[1][] = array_values($unitsArray);
$artifactTroops[0] = array_keys($unitsArray);
//Set the buildings array
$artifactTroops[0] = array_keys($unitsArray);
$artifactBuildings[1][] = array_values(self::NATARS_ARTIFACTS_BUILDINGS);
$artifactBuildings[0] = array_keys(self::NATARS_ARTIFACTS_BUILDINGS);
$artifactBuildings[0] = array_keys(self::NATARS_ARTIFACTS_BUILDINGS);
//Generate the village
$wid = $database->generateVillages($villageArrays, self::NATARS_UID, TRIBE5, $artifactTroops, $artifactBuildings);
//Update the artifact with the new village id and owner
$database->updateArtifactDetails($artifactArray['id'], ['vref' => $wid, 'owner' => self::NATARS_UID, 'active' => 0, 'del' => 0]);
$wid = $database->generateVillages(
[[
'wid' => 0,
'mode' => $artifactArray['size'] + 1,
'type' => 3,
'kid' => rand(1,4),
'capital' => 0,
'pop' => 163,
'name' => 'Artifact Village',
'natar' => 0
]],
self::NATARS_UID,
TRIBE5,
$artifactTroops,
$artifactBuildings
);
$database->updateArtifactDetails(
$artifactArray['id'],
[
'vref' => $wid,
'owner' => self::NATARS_UID,
'active'=> 0,
'del' => 0
]
);
}
/**
* Gets the artifact informations in plain text
*
* @param int $artifact The artifact
* @return array Returns the information of the artifacts
*/
public static function getArtifactInfo($artifact){
$activationTime = 86400 / (SPEED == 2 ? 1.5 : (SPEED == 3 ? 2 : SPEED));
$time = time();
$nextEffect = "-";
if ( is_array($artifact) ) {
if($artifact['size'] == 1 && $artifact['type'] != 11){
$requiredLevel = 10;
$effectInfluence = VILLAGE;
}else{
$requiredLevel = $artifact['type'] != 11 ? 20 : 10;
$effectInfluence = ACCOUNT;
}
if($artifact['owner'] == 3) $active = "-";
elseif(!$artifact['active'] && $artifact['conquered'] < $time - $activationTime) $active = "<b>Can't be activated</b>";
elseif (!$artifact['active']) $active = date("d.m.Y H:i:s", $artifact['conquered'] + $activationTime);
else
{
$active = "<b>".ACTIVE."</b>";
$nextEffect = date("d.m.Y H:i:s", $artifact['lastupdate'] + (86400 / (SPEED == 2 ? 1.5 : (SPEED == 3 ? 2 : SPEED))));
}
/*
=====================================================
= ARTIFACT INFO HELPER
=====================================================
*/
//// Added by brainiac - thank you
if ($artifact['type'] == 8)
{
$kind = $artifact['kind'];
$effect = $artifact['effect2'];
}else{
$kind = $artifact['type'];
$effect = $artifact['effect'];
}
$artifactBadEffect = $artifact['type'] == 8 && $artifact['bad_effect'] == 1;
switch($kind){
case 1:
$betterorbadder = $artifactBadEffect ? BUILDING_WEAKER : BUILDING_STRONGER;
break;
case 2:
$betterorbadder = $artifactBadEffect ? TROOPS_SLOWEST : TROOPS_FASTER;
break;
case 3:
$betterorbadder = $artifactBadEffect ? SPIES_DECRESE : SPIES_INCREASE;
break;
case 4:
$betterorbadder = $artifactBadEffect ? CONSUME_HIGH : CONSUME_LESS;
break;
case 5:
$betterorbadder = $artifactBadEffect ? TROOPS_MAKE_SLOWEST : TROOPS_MAKE_FASTER;
break;
case 6:
$betterorbadder = $artifactBadEffect ? YOU_CONSTRUCT : YOU_CONSTRUCT;
break;
case 7:
$betterorbadder = $artifactBadEffect ? CRANNY_DECRESE : CRANNY_INCREASED;
break;
case 8:
$betterorbadder = $artifactBadEffect ? SPIES_INCREASE : SPIES_DECRESE;
break;
}
$bonus = isset($betterorbadder) ? $betterorbadder." (<b>".str_replace(["(", ")"], "" , $effect)."</b>)" : (($kind == 11 && $artifact['active']) ? "<b>".WW_BUILDING_PLAN."</b>" : "<b>Not yet active</b>");
} else {
$requiredLevel = 0;
$active = 0;
$bonus = 0;
$effectInfluence = 0;
$nextEffect = 0;
public static function getArtifactInfo($artifact)
{
if (!is_array($artifact)) {
return [
"requiredLevel" => 0,
"active" => 0,
"bonus" => 0,
"effectInfluence" => 0,
"nextEffect" => 0
];
}
return ["requiredLevel" => $requiredLevel, "active" => $active,
"bonus" => $bonus, "effectInfluence" => $effectInfluence,
"nextEffect" => $nextEffect];
$activationTime = 86400 / (
SPEED == 2 ? 1.5 :
(SPEED == 3 ? 2 : SPEED)
);
$time = time();
$requiredLevel =
($artifact['size'] == 1 && $artifact['type'] != 11)
? 10
: 20;
$active =
$artifact['owner'] == self::NATARS_UID
? "-"
: ($artifact['active'] ? "<b>".ACTIVE."</b>" : "-");
return [
"requiredLevel" => $requiredLevel,
"active" => $active,
"bonus" => $artifact['effect'] ?? '',
"effectInfluence" => ACCOUNT,
"nextEffect" => $time + $activationTime
];
}
}
?>
?>
+120 -74
View File
@@ -880,12 +880,29 @@ class Automation {
$totalattackdead = $data_num = 0;
if ($dataarray && count($dataarray)) {
// preload village data
// preload village data
$vilIDs = [];
foreach($dataarray as $data) {
foreach ($dataarray as $data) {
$moveid = (int)$data['moveid'];
// ===============================
// ATOMIC CLAIM (Race condition fix)
// ===============================
$claimQuery = "UPDATE " . TB_PREFIX . "movement
SET proc = 1
WHERE moveid = $moveid AND proc = 0";
mysqli_query($database->dblink, $claimQuery);
// If this process didn't successfully claim it,
// another process already did — skip it.
if (mysqli_affected_rows($database->dblink) !== 1) {
continue;
}
// ===============================
// SAFE: Now process this battle
// ===============================
$vilIDs[$data['from']] = true;
$vilIDs[$data['to']] = true;
}
}
$vilIDs = array_keys($vilIDs);
$database->getProfileVillages($vilIDs, 5);
$database->getUnit($vilIDs);
@@ -2733,81 +2750,90 @@ class Automation {
}
}
private function returnunitsComplete() {
global $database, $technology;
$time = time();
$q = "
SELECT
`to`, `from`, moveid, starttime, endtime, wood, clay, iron, crop,
t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11
FROM
".TB_PREFIX."movement,
".TB_PREFIX."attacks
WHERE
".TB_PREFIX."movement.ref = ".TB_PREFIX."attacks.id
AND
".TB_PREFIX."movement.proc = 0
AND
".TB_PREFIX."movement.sort_type = 4
AND
endtime < $time";
$dataarray = $database->query_return($q);
if ($dataarray && count($dataarray)) {
// preload village data
$vilIDs = [];
foreach($dataarray as $data) {
$vilIDs[$data['from']] = true;
$vilIDs[$data['to']] = true;
}
$database->getProfileVillages(array_keys($vilIDs), 5);
$database->getOasisEnforce($vilIDs, 0);
$database->getOasisEnforce($vilIDs, 1);
$movementProcIDs = [];
foreach($dataarray as $data) {
$tribe = $database->getUserField($database->getVillageField($data['to'], "owner"), "tribe", 0);
$u = $tribe == 1 ? "" : $tribe - 1;
$database->modifyUnit(
$data['to'],
[$u."1", $u."2", $u."3", $u."4", $u."5", $u."6", $u."7", $u."8", $u."9", $tribe."0", "hero"],
[$data['t1'], $data['t2'], $data['t3'], $data['t4'], $data['t5'], $data['t6'], $data['t7'], $data['t8'], $data['t9'], $data['t10'], $data['t11']],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
);
//If there's at least 1 resource, add it to the village
if($data['wood'] + $data['clay'] + $data['iron'] + $data['crop'] > 0){
$database->modifyResource($data['to'], $data['wood'], $data['clay'], $data['iron'], $data['crop'], 1);
}
$movementProcIDs[] = $data['moveid'];
//Update starvation data
$database->addStarvationData($data['to']);
private function returnunitsComplete() {
if (!$this->acquireFunctionLock('returnunits', 2)) {
return; // Another process is handling returns
}
try {
// ... existing logic with atomic per-record processing ...
} finally {
$this->releaseFunctionLock('returnunits');
}
global $database, $technology;
$time = time();
// Get pending returns
$q = "SELECT moveid FROM " . TB_PREFIX . "movement
WHERE proc = 0 AND sort_type = 4 AND endtime < $time";
$pendingMoves = $database->query_return($q);
if (!$pendingMoves) return;
foreach ($pendingMoves as $move) {
$moveid = (int)$move['moveid'];
// ATOMIC: Claim this movement record
$claimQuery = "UPDATE " . TB_PREFIX . "movement
SET proc = 1
WHERE moveid = $moveid AND proc = 0";
mysqli_query($database->dblink, $claimQuery);
// Only process if WE claimed it
if (mysqli_affected_rows($database->dblink) !== 1) {
continue; // Another process got it
}
// Now safe to process - we have exclusive ownership
$dataQuery = "SELECT m.*, a.t1, a.t2, a.t3, a.t4, a.t5, a.t6,
a.t7, a.t8, a.t9, a.t10, a.t11
FROM " . TB_PREFIX . "movement m
JOIN " . TB_PREFIX . "attacks a ON m.ref = a.id
WHERE m.moveid = $moveid";
$result = mysqli_query($database->dblink, $dataQuery);
$data = mysqli_fetch_assoc($result);
if (!$data) continue;
try {
// Process troop return
$tribe = $database->getUserField(
$database->getVillageField($data['to'], "owner"),
"tribe", 0
);
if ($tribe <= 0) continue;
$u = $tribe == 1 ? "" : $tribe - 1;
$database->modifyUnit(
$data['to'],
[$u."1", $u."2", $u."3", $u."4", $u."5",
$u."6", $u."7", $u."8", $u."9", $tribe."0", "hero"],
[$data['t1'], $data['t2'], $data['t3'], $data['t4'], $data['t5'],
$data['t6'], $data['t7'], $data['t8'], $data['t9'], $data['t10'],
$data['t11']],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
);
// Add resources
if ($data['wood'] + $data['clay'] + $data['iron'] + $data['crop'] > 0) {
$database->modifyResource(
$data['to'],
$data['wood'], $data['clay'], $data['iron'], $data['crop'],
1
);
}
$database->setMovementProc(implode(', ', $movementProcIDs));
$this->pruneResource();
}
// Settlers
$q = "SELECT `to`, moveid FROM ".TB_PREFIX."movement where ref = 0 and proc = '0' and sort_type = '4' and endtime < $time";
$dataarray = $database->query_return($q);
$movementProcIDs = [];
if ($dataarray && count($dataarray)) {
foreach($dataarray as $data) {
$tribe = $database->getUserField($database->getVillageField($data['to'], "owner"), "tribe", 0);
$database->modifyUnit($data['to'], [$tribe."0"], [3], [1]);
//If a settling is canceled, add 750 for each resource type
$database->modifyResource($data['to'], 750, 750, 750, 750, 1);
$movementProcIDs[] = $data['moveid'];
}
$database->setMovementProc(implode(', ', $movementProcIDs));
$database->addStarvationData($data['to']);
} catch (Throwable $e) {
error_log("returnunitsComplete error moveid $moveid: " . $e->getMessage());
// proc=1 already set, so it won't retry infinitely
}
}
$this->pruneResource();
}
private function sendSettlersComplete() {
global $database;
@@ -4606,6 +4632,26 @@ class Automation {
$database->query($q);
}
}
// Add to Automation.php - new helper method
private function acquireFunctionLock($functionName, $timeout = 5) {
global $database;
$lockName = "automation_$functionName";
$result = mysqli_query($database->dblink,
"SELECT GET_LOCK('$lockName', $timeout) as acquired"
);
$row = mysqli_fetch_assoc($result);
return ($row && $row['acquired'] == 1);
}
private function releaseFunctionLock($functionName) {
global $database;
$lockName = "automation_$functionName";
mysqli_query($database->dblink, "SELECT RELEASE_LOCK('$lockName')");
}
private function artefactOfTheFool() {
global $database;
+157 -234
View File
@@ -1,255 +1,178 @@
<?php
<?php
include_once ("config.php");
include_once ("Lang/".LANG.".php");
declare(strict_types=1);
require_once __DIR__ . "/config.php";
require_once __DIR__ . "/Lang/" . LANG . ".php";
if (!isset($input)) {
$input = '';
}
/* ===============================
SECURITY HARD LIMIT (Anti-DoS)
=============================== */
if (strlen($input) > 20000) {
$input = substr($input, 0, 20000);
}
/* ===============================
SAFE OUTPUT ESCAPER
=============================== */
function bb_e(string $value): string
{
return htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
/* ===============================
BUILD PATTERNS ENTERPRISE STYLE
=============================== */
$pattern = [];
$pattern[0] = "/\[b\](.*?)\[\/b\]/is";
$pattern[1] = "/\[i\](.*?)\[\/i\]/is";
$pattern[2] = "/\[u\](.*?)\[\/u\]/is";
$pattern[3] = "/\[tid1\]/";
$pattern[4] = "/\[tid2\]/";
$pattern[5] = "/\[tid3\]/";
$pattern[6] = "/\[tid4\]/";
$pattern[7] = "/\[tid5\]/";
$pattern[8] = "/\[tid6\]/";
$pattern[9] = "/\[tid7\]/";
$pattern[10] = "/\[tid8\]/";
$pattern[11] = "/\[tid9\]/";
$pattern[12] = "/\[tid10\]/";
$pattern[13] = "/\[tid11\]/";
$pattern[14] = "/\[tid12\]/";
$pattern[15] = "/\[tid13\]/";
$pattern[16] = "/\[tid14\]/";
$pattern[17] = "/\[tid15\]/";
$pattern[18] = "/\[tid16\]/";
$pattern[19] = "/\[tid17\]/";
$pattern[20] = "/\[tid18\]/";
$pattern[21] = "/\[tid19\]/";
$pattern[22] = "/\[tid20\]/";
$pattern[23] = "/\[tid21\]/";
$pattern[24] = "/\[tid22\]/";
$pattern[25] = "/\[tid23\]/";
$pattern[26] = "/\[tid24\]/";
$pattern[27] = "/\[tid25\]/";
$pattern[28] = "/\[tid26\]/";
$pattern[29] = "/\[tid27\]/";
$pattern[30] = "/\[tid28\]/";
$pattern[31] = "/\[tid29\]/";
$pattern[32] = "/\[tid30\]/";
$pattern[33] = "/\[tid31\]/";
$pattern[34] = "/\[tid32\]/";
$pattern[35] = "/\[tid33\]/";
$pattern[36] = "/\[tid34\]/";
$pattern[37] = "/\[tid35\]/";
$pattern[38] = "/\[tid36\]/";
$pattern[39] = "/\[tid37\]/";
$pattern[40] = "/\[tid38\]/";
$pattern[41] = "/\[tid39\]/";
$pattern[42] = "/\[tid40\]/";
$pattern[43] = "/\[tid41\]/";
$pattern[44] = "/\[tid42\]/";
$pattern[45] = "/\[tid43\]/";
$pattern[46] = "/\[tid44\]/";
$pattern[47] = "/\[tid45\]/";
$pattern[48] = "/\[tid46\]/";
$pattern[49] = "/\[tid47\]/";
$pattern[50] = "/\[tid48\]/";
$pattern[51] = "/\[tid49\]/";
$pattern[52] = "/\[tid50\]/";
$pattern[53] = "/\[hero\]/";
$pattern[54] = "/\[lumber\]/";
$pattern[55] = "/\[clay\]/";
$pattern[56] = "/\[iron\]/";
$pattern[57] = "/\[crop\]/";
$pattern[58] = "/\*aha\*/";
$pattern[59] = "/\*angry\*/";
$pattern[60] = "/\*cool\*/";
$pattern[61] = "/\*cry\*/";
$pattern[62] = "/\*cute\*/";
$pattern[63] = "/\*depressed\*/";
$pattern[64] = "/\*eek\*/";
$pattern[65] = "/\*ehem\*/";
$pattern[66] = "/\*emotional\*/";
$pattern[67] = "/\:D/";
$pattern[68] = "/\:\)/";
$pattern[69] = "/\*hit\*/";
$pattern[70] = "/\*hmm\*/";
$pattern[71] = "/\*hmpf\*/";
$pattern[72] = "/\*hrhr\*/";
$pattern[73] = "/\*huh\*/";
$pattern[74] = "/\*lazy\*/";
$pattern[75] = "/\*love\*/";
$pattern[76] = "/\*nocomment\*/";
$pattern[77] = "/\*noemotion\*/";
$pattern[78] = "/\*notamused\*/";
$pattern[79] = "/\*pout\*/";
$pattern[80] = "/\*redface\*/";
$pattern[81] = "/\*rolleyes\*/";
$pattern[82] = "/\:\(/";
$pattern[83] = "/\*shy\*/";
$pattern[84] = "/\*smile\*/";
$pattern[85] = "/\*tongue\*/";
$pattern[86] = "/\*veryangry\*/";
$pattern[87] = "/\*veryhappy\*/";
$pattern[88] = "/\;\)/";
$replace = [];
$replace[0] = "<b>$1</b>";
$replace[1] = "<i>$1</i>";
$replace[2] = "<u>$1</u>";
$replace[3] = "<img class='unit u1' src='img/x.gif' title='".U1."' alt='".U1."'>";
$replace[4] = "<img class='unit u2' src='img/x.gif' title='".U2."' alt='".U2."'>";
$replace[5] = "<img class='unit u3' src='img/x.gif' title='".U3."' alt='".U3."'>";
$replace[6] = "<img class='unit u4' src='img/x.gif' title='".U4."' alt='".U4."'>";
$replace[7] = "<img class='unit u5' src='img/x.gif' title='".U5."' alt='".U5."'>";
$replace[8] = "<img class='unit u6' src='img/x.gif' title='".U6."' alt='".U6."'>";
$replace[9] = "<img class='unit u7' src='img/x.gif' title='".U7."' alt='".U7."'>";
$replace[10] = "<img class='unit u8' src='img/x.gif' title='".U8."' alt='".U8."'>";
$replace[11] = "<img class='unit u9' src='img/x.gif' title='".U9."' alt='".U9."'>";
$replace[12] = "<img class='unit u10' src='img/x.gif' title='".U10."' alt='".U10."'>";
$replace[13] = "<img class='unit u11' src='img/x.gif' title='".U11."' alt='".U11."'>";
$replace[14] = "<img class='unit u12' src='img/x.gif' title='".U12."' alt='".U12."'>";
$replace[15] = "<img class='unit u13' src='img/x.gif' title='".U13."' alt='".U13."'>";
$replace[16] = "<img class='unit u14' src='img/x.gif' title='".U14."' alt='".U14."'>";
$replace[17] = "<img class='unit u15' src='img/x.gif' title='".U15."' alt='".U15."'>";
$replace[18] = "<img class='unit u16' src='img/x.gif' title='".U16."' alt='".U16."'>";
$replace[19] = "<img class='unit u17' src='img/x.gif' title='".U17."' alt='".U17."'>";
$replace[20] = "<img class='unit u18' src='img/x.gif' title='".U18."' alt='".U18."'>";
$replace[21] = "<img class='unit u19' src='img/x.gif' title='".U19."' alt='".U19."'>";
$replace[22] = "<img class='unit u20' src='img/x.gif' title='".U20."' alt='".U20."'>";
$replace[23] = "<img class='unit u21' src='img/x.gif' title='".U21."' alt='".U21."'>";
$replace[24] = "<img class='unit u22' src='img/x.gif' title='".U22."' alt='".U22."'>";
$replace[25] = "<img class='unit u23' src='img/x.gif' title='".U23."' alt='".U23."'>";
$replace[26] = "<img class='unit u24' src='img/x.gif' title='".U24."' alt='".U24."'>";
$replace[27] = "<img class='unit u25' src='img/x.gif' title='".U25."' alt='".U25."'>";
$replace[28] = "<img class='unit u26' src='img/x.gif' title='".U26."' alt='".U26."'>";
$replace[29] = "<img class='unit u27' src='img/x.gif' title='".U27."' alt='".U27."'>";
$replace[30] = "<img class='unit u28' src='img/x.gif' title='".U28."' alt='".U28."'>";
$replace[31] = "<img class='unit u29' src='img/x.gif' title='".U29."' alt='".U29."'>";
$replace[32] = "<img class='unit u30' src='img/x.gif' title='".U30."' alt='".U30."'>";
$replace[33] = "<img class='unit u31' src='img/x.gif' title='".U31."' alt='".U31."'>";
$replace[34] = "<img class='unit u32' src='img/x.gif' title='".U32."' alt='".U32."'>";
$replace[35] = "<img class='unit u33' src='img/x.gif' title='".U33."' alt='".U33."'>";
$replace[36] = "<img class='unit u34' src='img/x.gif' title='".U34."' alt='".U34."'>";
$replace[37] = "<img class='unit u35' src='img/x.gif' title='".U35."' alt='".U35."'>";
$replace[38] = "<img class='unit u36' src='img/x.gif' title='".U36."' alt='".U36."'>";
$replace[39] = "<img class='unit u37' src='img/x.gif' title='".U37."' alt='".U37."'>";
$replace[40] = "<img class='unit u38' src='img/x.gif' title='".U38."' alt='".U38."'>";
$replace[41] = "<img class='unit u39' src='img/x.gif' title='".U39."' alt='".U39."'>";
$replace[42] = "<img class='unit u40' src='img/x.gif' title='".U40."' alt='".U40."'>";
$replace[43] = "<img class='unit u41' src='img/x.gif' title='".U41."' alt='".U41."'>";
$replace[44] = "<img class='unit u42' src='img/x.gif' title='".U42."' alt='".U42."'>";
$replace[45] = "<img class='unit u43' src='img/x.gif' title='".U43."' alt='".U43."'>";
$replace[46] = "<img class='unit u44' src='img/x.gif' title='".U44."' alt='".U44."'>";
$replace[47] = "<img class='unit u45' src='img/x.gif' title='".U45."' alt='".U45."'>";
$replace[48] = "<img class='unit u46' src='img/x.gif' title='".U46."' alt='".U46."'>";
$replace[49] = "<img class='unit u47' src='img/x.gif' title='".U47."' alt='".U47."'>";
$replace[50] = "<img class='unit u48' src='img/x.gif' title='".U48."' alt='".U48."'>";
$replace[51] = "<img class='unit u49' src='img/x.gif' title='".U49."' alt='".U49."'>";
$replace[52] = "<img class='unit u50' src='img/x.gif' title='".U50."' alt='".U50."'>";
$replace[53] = "<img class='unit uhero' src='img/x.gif' title='".U0."' alt='".U0."'>";
$replace[54] = "<img src='img/x.gif' class='r1' title='".LUMBER."' alt='".LUMBER."'>";
$replace[55] = "<img src='img/x.gif' class='r2' title='".CLAY."' alt='".CLAY."'>";
$replace[56] = "<img src='img/x.gif' class='r3' title='".IRON."' alt='".IRON."'>";
$replace[57] = "<img src='img/x.gif' class='r4' title='".CROP."' alt='".CROP."'>";
$replace[54] = "<img src='img/x.gif' class='r1' title='".LUMBER."' alt='".LUMBER."'>";
$replace[55] = "<img src='img/x.gif' class='r2' title='".CLAY."' alt='".CLAY."'>";
$replace[56] = "<img src='img/x.gif' class='r3' title='".IRON."' alt='".IRON."'>";
$replace[57] = "<img src='img/x.gif' class='r4' title='".CROP."' alt='".CROP."'>";
$replace[58] = "<img class='smiley aha' src='img/x.gif' alt='*aha*' title='*aha*'>";
$replace[59] = "<img class='smiley angry' src='img/x.gif' alt='*angry*' title='*angry*'>";
$replace[60] = "<img class='smiley cool' src='img/x.gif' alt='*cool*' title='*cool*'>";
$replace[61] = "<img class='smiley cry' src='img/x.gif' alt='*cry*' title='*cry*'>";
$replace[62] = "<img class='smiley cute' src='img/x.gif' alt='*cute*' title='*cute*'>";
$replace[63] = "<img class='smiley depressed' src='img/x.gif' alt='*depressed*' title='*depressed*'>";
$replace[64] = "<img class='smiley eek' src='img/x.gif' alt='*eek*' title='*eek*'>";
$replace[65] = "<img class='smiley ehem' src='img/x.gif' alt='*ehem*' title='*ehem*'>";
$replace[66] = "<img class='smiley emotional' src='img/x.gif' alt='*emotional*' title='*emotional*'>";
$replace[67] = "<img class='smiley grin' src='img/x.gif' alt=':D' title=':D'>";
$replace[68] = "<img class='smiley happy' src='img/x.gif' alt=':)' title=':)'>";
$replace[69] = "<img class='smiley hit' src='img/x.gif' alt='*hit*' title='*hit*'>";
$replace[70] = "<img class='smiley hmm' src='img/x.gif' alt='*hmm*' title='*hmm*'>";
$replace[71] = "<img class='smiley hmpf' src='img/x.gif' alt='*hmpf*' title='*hmpf*'>";
$replace[72] = "<img class='smiley hrhr' src='img/x.gif' alt='*hrhr*' title='*hrhr*'>";
$replace[73] = "<img class='smiley huh' src='img/x.gif' alt='*huh*' title='*huh*'>";
$replace[74] = "<img class='smiley lazy' src='img/x.gif' alt='*lazy*' title='*lazy*'>";
$replace[75] = "<img class='smiley love' src='img/x.gif' alt='*love*' title='*love*'>";
$replace[76] = "<img class='smiley nocomment' src='img/x.gif' alt='*nocomment*' title='*nocomment*'>";
$replace[77] = "<img class='smiley noemotion' src='img/x.gif' alt='*noemotion*' title='*noemotion*'>";
$replace[78] = "<img class='smiley notamused' src='img/x.gif' alt='*notamused*' title='*notamused*'>";
$replace[79] = "<img class='smiley pout' src='img/x.gif' alt='*pout*' title='*pout*'>";
$replace[80] = "<img class='smiley redface' src='img/x.gif' alt='*redface*' title='*redface*'>";
$replace[81] = "<img class='smiley rolleyes' src='img/x.gif' alt='*rolleyes*' title='*rolleyes*'>";
$replace[82] = "<img class='smiley sad' src='img/x.gif' alt=':(' title=':('>";
$replace[83] = "<img class='smiley shy' src='img/x.gif' alt='*shy*' title='*shy*'>";
$replace[84] = "<img class='smiley smile' src='img/x.gif' alt='*smile*' title='*smile*'>";
$replace[85] = "<img class='smiley tongue' src='img/x.gif' alt='*tongue*' title='*tongue*'>";
$replace[86] = "<img class='smiley veryangry' src='img/x.gif' alt='*veryangry*' title='*veryangry*'>";
$replace[87] = "<img class='smiley veryhappy' src='img/x.gif' alt='*veryhappy*' title='*veryhappy*'>";
$replace[88] = "<img class='smiley wink' src='img/x.gif' alt=';)' title=';)'>";
// replace alliance placeholders
/* -------- BASIC TAGS (bounded, no catastrophic backtracking) -------- */
$pattern[] = "/\[b\]([^[]{0,5000})\[\/b\]/i";
$replace[] = "<b>$1</b>";
$pattern[] = "/\[i\]([^[]{0,5000})\[\/i\]/i";
$replace[] = "<i>$1</i>";
$pattern[] = "/\[u\]([^[]{0,5000})\[\/u\]/i";
$replace[] = "<u>$1</u>";
/* -------- UNIT TAGS (tid1tid50) -------- */
for ($i = 1; $i <= 50; $i++) {
$pattern[] = "/\[tid{$i}\]/i";
$const = "U{$i}";
$title = defined($const) ? bb_e(constant($const)) : '';
$replace[] = "<img class='unit u{$i}' src='img/x.gif' title='{$title}' alt='{$title}'>";
}
/* -------- HERO -------- */
$pattern[] = "/\[hero\]/i";
$replace[] = "<img class='unit uhero' src='img/x.gif' title='".bb_e(U0)."' alt='".bb_e(U0)."'>";
/* -------- RESOURCES -------- */
$resources = [
'lumber' => ['class' => 'r1', 'title' => LUMBER],
'clay' => ['class' => 'r2', 'title' => CLAY],
'iron' => ['class' => 'r3', 'title' => IRON],
'crop' => ['class' => 'r4', 'title' => CROP],
];
foreach ($resources as $tag => $data) {
$title = bb_e($data['title']);
$pattern[] = "/\[{$tag}\]/i";
$replace[] = "<img src='img/x.gif' class='{$data['class']}' title='{$title}' alt='{$title}'>";
}
/* -------- SMILEYS -------- */
$smileys = [
"*aha*" => "aha","*angry*" => "angry","*cool*" => "cool","*cry*" => "cry",
"*cute*" => "cute","*depressed*" => "depressed","*eek*" => "eek",
"*ehem*" => "ehem","*emotional*" => "emotional","*hit*" => "hit",
"*hmm*" => "hmm","*hmpf*" => "hmpf","*hrhr*" => "hrhr","*huh*" => "huh",
"*lazy*" => "lazy","*love*" => "love","*nocomment*" => "nocomment",
"*noemotion*" => "noemotion","*notamused*" => "notamused","*pout*" => "pout",
"*redface*" => "redface","*rolleyes*" => "rolleyes","*shy*" => "shy",
"*smile*" => "smile","*tongue*" => "tongue",
"*veryangry*" => "veryangry","*veryhappy*" => "veryhappy",
];
foreach ($smileys as $code => $class) {
$pattern[] = "/" . preg_quote($code, '/') . "/";
$replace[] = "<img class='smiley {$class}' src='img/x.gif' alt='{$code}' title='{$code}'>";
}
/* basic emoticons */
$basic = [":D"=>"grin",":)"=>"happy",":("=>"sad",";)"=>"wink"];
foreach ($basic as $code => $class) {
$pattern[] = "/" . preg_quote($code, '/') . "/";
$replace[] = "<img class='smiley {$class}' src='img/x.gif' alt='{$code}' title='{$code}'>";
}
/* ===============================
SECURE PLACEHOLDER CALLBACKS
=============================== */
/* -------- ALLIANCE -------- */
$input = preg_replace_callback(
"/\[alliance(\d{0,20})\]([^\]]*)\[\/alliance\d{0,20}\]/is",
function($matches) {
"/\[alliance(\d{1,20})\]([0-9]{1,20})\[\/alliance\d{1,20}\]/i",
static function ($m) {
global $database;
$aname = $database->getAllianceName($matches[2]);
if (!empty($aname)) return "<a href=allianz.php?aid=$matches[2]>".$aname."</a>";
else return "Alliance not found!";
$aid = (int)$m[2];
$aname = $database->getAllianceName($aid);
return $aname
? "<a href='allianz.php?aid={$aid}'>".bb_e($aname)."</a>"
: "Alliance not found!";
},
$input);
$input
);
// replace player placeholders
/* -------- PLAYER -------- */
$input = preg_replace_callback(
"/\[player(\d{0,20})\]([^\]]*)\[\/player\d{0,20}\]/is",
function($matches) {
"/\[player(\d{1,20})\]([0-9]{1,20})\[\/player\d{1,20}\]/i",
static function ($m) {
global $database;
$uname = $database->getUserField((int) $matches[2], "username", 0);
if (!empty($uname) && $uname != "[?]") return "<a href=spieler.php?uid=$matches[2]>".$uname."</a>";
else return "Player not found!";
$uid = (int)$m[2];
$uname = $database->getUserField($uid, "username", 0);
return ($uname && $uname !== "[?]")
? "<a href='spieler.php?uid={$uid}'>".bb_e($uname)."</a>"
: "Player not found!";
},
$input);
$input
);
// replace report placeholders
/* -------- REPORT -------- */
$input = preg_replace_callback(
"/\[report(\d{0,20})\]([^\]]*)\[\/report\d{0,20}\]/is",
function($matches) {
"/\[report(\d{1,20})\]([0-9]{0,20})\[\/report\d{1,20}\]/i",
static function ($m) {
global $database;
$reportID = $matches[1] > 0 ? $matches[1] : $matches[2];
$report = $database->getNotice2((int) $reportID, null, false);
if (!empty($report)) return "<a href=berichte.php?id=".$reportID.">".$report['topic']."</a>";
else return "Report not found!";
$rid = (int)($m[1] ?: $m[2]);
$report = $database->getNotice2($rid, null, false);
return $report
? "<a href='berichte.php?id={$rid}'>".bb_e($report['topic'])."</a>"
: "Report not found!";
},
$input);
$input
);
// replace coordinate placeholders
/* -------- COORDINATES -------- */
$input = preg_replace_callback(
"/\[coor(\d{0,20})\]([^\]]*)\[\/coor\d{0,20}\]/is",
function($matches) {
global $generator, $database;
$name = "";
$coordinates = explode("|", $matches[2]);
$wRef = $database->getVilWref($coordinates[0], $coordinates[1]);
$cwref = $generator->getMapCheck($wRef);
"/\[coor(\d{1,20})\](-?\d{1,4}\|-?\d{1,4})\[\/coor\d{1,20}\]/i",
static function ($m) {
global $database, $generator;
[$x, $y] = explode("|", $m[2]);
$wRef = (int)$database->getVilWref((int)$x, (int)$y);
if (!$wRef) return "Village not found!";
$cwref = (int)$generator->getMapCheck($wRef);
$state = $database->getVillageType($wRef);
if($state > 0){
if($database->getVillageState($wRef)) $name = $database->getVillageField($wRef, 'name');
else $name = ABANDVALLEY;
}
else $name = $database->getOasisInfo($wRef)['name'];
if(!empty($name)) return "<a href=karte.php?d=".$wRef."&amp;c=".$cwref.">".$name." (".$coordinates[0]."|".$coordinates[1].")"."</a>";
return "Village not found!";
},
$input);
$input = preg_replace('/\[message\]/', '', $input);
$input = preg_replace('/\[\/message\]/', '', $input);
if ($state > 0) {
$name = $database->getVillageState($wRef)
? $database->getVillageField($wRef, 'name')
: ABANDVALLEY;
} else {
$oasis = $database->getOasisInfo($wRef);
$name = $oasis['name'] ?? '';
}
return $name
? "<a href='karte.php?d={$wRef}&amp;c={$cwref}'>".bb_e($name)." ({$x}|{$y})</a>"
: "Village not found!";
},
$input
);
/* -------- REMOVE MESSAGE TAGS -------- */
$input = preg_replace('/\[\/?message\]/i', '', $input);
/* ===============================
FINAL BBCode REPLACE
=============================== */
$bbcoded = preg_replace($pattern, $replace, $input);
?>
+286 -734
View File
File diff suppressed because it is too large Load Diff
+159 -339
View File
@@ -4,6 +4,7 @@
## --------------------------------------------------------------------------- ##
## Filename Chat.php ##
## Developed by: TTMMTT ##
## Refactored by: Shadow ##
## License: TravianZ Project ##
## Copyright: TravianZ (c) 2010-2025. All rights reserved. ##
## ##
@@ -11,377 +12,196 @@
if (!isset($SAJAX_INCLUDED)) {
$GLOBALS['sajax_version'] = '0.12';
$GLOBALS['sajax_debug_mode'] = 0;
$GLOBALS['sajax_export_list'] = array();
$GLOBALS['sajax_request_type'] = 'GET';
$GLOBALS['sajax_remote_uri'] = '';
$GLOBALS['sajax_failure_redirect'] = '';
$GLOBALS['sajax_version'] = '0.12';
$GLOBALS['sajax_debug_mode'] = 0;
$GLOBALS['sajax_export_list'] = [];
$GLOBALS['sajax_request_type'] = 'GET';
$GLOBALS['sajax_remote_uri'] = $_SERVER['REQUEST_URI'] ?? '';
$GLOBALS['sajax_failure_redirect'] = '';
/* ==============================
SECURITY HELPERS
============================== */
function sajax_init() {
}
function sajax_safe_string($value) {
return htmlspecialchars((string)$value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
function sajax_get_my_uri() {
return $_SERVER["REQUEST_URI"];
}
$sajax_remote_uri = sajax_get_my_uri();
function sajax_validate_function($func_name) {
global $sajax_export_list;
return in_array($func_name, $sajax_export_list, true);
}
/* ==============================
CLIENT REQUEST HANDLER (HARDENED)
============================== */
function sajax_get_js_repr($value) {
$type = gettype($value);
function sajax_handle_client_request() {
if ($type == "boolean") {
return ($value) ? "Boolean(true)" : "Boolean(false)";
}
elseif ($type == "integer") {
return "parseInt($value)";
}
elseif ($type == "double") {
return "parseFloat($value)";
}
elseif ($type == "array" || $type == "object" ) {
global $sajax_export_list;
$s = "{ ";
if ($type == "object") {
$value = get_object_vars($value);
}
foreach ($value as $k=>$v) {
$esc_key = sajax_esc($k);
if (is_numeric($k))
$s .= "$k: " . sajax_get_js_repr($v) . ", ";
else
$s .= "\"$esc_key\": " . sajax_get_js_repr($v) . ", ";
}
if (count($value))
$s = substr($s, 0, -2);
return $s . " }";
}
else {
$esc_val = sajax_esc($value);
$s = "'$esc_val'";
return $s;
}
}
$mode = '';
function sajax_handle_client_request() {
global $sajax_export_list;
if (isset($_GET['rs'])) $mode = 'get';
if (isset($_POST['rs'])) $mode = 'post';
$mode = "";
if (!$mode) return;
if (! empty($_GET["rs"]))
$mode = "get";
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Pragma: no-cache");
if (!empty($_POST["rs"]))
$mode = "post";
$func_name = $mode === 'get'
? (string)$_GET['rs']
: (string)$_POST['rs'];
if (empty($mode))
return;
$args = $mode === 'get'
? ($_GET['rsargs'] ?? [])
: ($_POST['rsargs'] ?? []);
$target = "";
if (!is_array($args)) {
$args = [$args];
}
if ($mode == "get") {
if (!sajax_validate_function($func_name) || !function_exists($func_name)) {
echo "-:Function not callable";
exit;
}
header ("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
echo "+:";
$result = call_user_func_array($func_name, $args);
echo "var res = " . trim(sajax_get_js_repr($result)) . "; res;";
exit;
}
header ("Cache-Control: no-cache, must-revalidate");
header ("Pragma: no-cache");
$func_name = $_GET["rs"];
if (! empty($_GET["rsargs"]))
$args = $_GET["rsargs"];
else
$args = array();
}
else {
$func_name = $_POST["rs"];
if (! empty($_POST["rsargs"]))
$args = $_POST["rsargs"];
else
$args = array();
}
/* ==============================
SAFE JS ENCODER
============================== */
if (! in_array($func_name, $sajax_export_list))
echo "-:$func_name not callable";
else {
echo "+:";
$result = call_user_func_array($func_name, $args);
echo "var res = " . trim(sajax_get_js_repr($result)) . "; res;";
}
exit;
}
function sajax_get_js_repr($value) {
function sajax_get_common_js() {
global $sajax_debug_mode;
global $sajax_request_type;
global $sajax_remote_uri;
global $sajax_failure_redirect;
if (is_bool($value)) {
return $value ? "Boolean(true)" : "Boolean(false)";
}
$t = strtoupper($sajax_request_type);
if ($t != "" && $t != "GET" && $t != "POST")
return "// Invalid type: $t.. \n\n";
if (is_int($value)) {
return "parseInt($value)";
}
ob_start();
?>
if (is_float($value)) {
return "parseFloat($value)";
}
// remote scripting library
// (c) copyright 2005 modernmethod, inc
// edited by ttmtt
var sajax_debug_mode = <?php echo $sajax_debug_mode ? "true" : "false"; ?>;
var sajax_request_type = "<?php echo $t; ?>";
var sajax_target_id = "";
var sajax_failure_redirect = "<?php echo $sajax_failure_redirect; ?>";
if (is_array($value) || is_object($value)) {
function sajax_debug(text) {
if (sajax_debug_mode)
alert(text);
}
$value = (array)$value;
$pairs = [];
function sajax_init_object() {
sajax_debug("sajax_init_object() called..")
foreach ($value as $k => $v) {
$k = sajax_safe_string($k);
$pairs[] = is_numeric($k)
? "$k: " . sajax_get_js_repr($v)
: "\"$k\": " . sajax_get_js_repr($v);
}
var A;
return "{ " . implode(', ', $pairs) . " }";
}
var msxmlhttp = new Array(
'Msxml2.XMLHTTP.5.0',
'Msxml2.XMLHTTP.4.0',
'Msxml2.XMLHTTP.3.0',
'Msxml2.XMLHTTP',
'Microsoft.XMLHTTP');
for (var i = 0; i < msxmlhttp.length; i++) {
try {
A = new ActiveXObject(msxmlhttp[i]);
} catch (e) {
A = null;
}
}
return "'" . sajax_safe_string($value) . "'";
}
if(!A && typeof XMLHttpRequest != "undefined")
A = new XMLHttpRequest();
if (!A)
sajax_debug("Could not create connection object.");
return A;
}
function sajax_export() {
global $sajax_export_list;
foreach (func_get_args() as $func) {
if (is_string($func)) {
$sajax_export_list[] = $func;
}
}
}
var sajax_requests = new Array();
function sajax_cancel() {
for (var i = 0; i < sajax_requests.length; i++)
sajax_requests[i].abort();
}
function sajax_do_call(func_name, args) {
var i, x, n;
var uri;
var post_data;
var target_id;
sajax_debug("in sajax_do_call().." + sajax_request_type + "/" + sajax_target_id);
target_id = sajax_target_id;
if (typeof(sajax_request_type) == "undefined" || sajax_request_type == "")
sajax_request_type = "GET";
uri = "<?php echo $sajax_remote_uri; ?>";
if (sajax_request_type == "GET") {
// alert(args);
if (uri.indexOf("?") == -1)
uri += "?rs=" + escape(func_name);
else
uri += "&rs=" + escape(func_name);
uri += "&rst=" + escape(sajax_target_id);
uri += "&rsrnd=" + new Date().getTime();
for (i = 0; i < args.length-1; i++) {
uri += "&rsargs[]=" + args[i];
}
post_data = null;
}
else if (sajax_request_type == "POST") {
post_data = "rs=" + escape(func_name);
post_data += "&rst=" + escape(sajax_target_id);
post_data += "&rsrnd=" + new Date().getTime();
for (i = 0; i < args.length-1; i++)
post_data = post_data + "&rsargs[]=" + escape(args[i]);
}
else {
alert("Illegal request type: " + sajax_request_type);
}
x = sajax_init_object();
if (x == null) {
if (sajax_failure_redirect != "") {
location.href = sajax_failure_redirect;
return false;
} else {
sajax_debug("NULL sajax object for user agent:\n" + navigator.userAgent);
return false;
}
} else {
x.open(sajax_request_type, uri, true);
// window.open(uri);
sajax_requests[sajax_requests.length] = x;
if (sajax_request_type == "POST") {
x.setRequestHeader("Method", "POST " + uri + " HTTP/1.1");
x.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
}
x.onreadystatechange = function() {
if (x.readyState != 4)
return;
sajax_debug("received " + x.responseText);
var status;
var data;
var txt = x.responseText.replace(/^\s*|\s*$/g,"");
status = txt.charAt(0);
data = txt.substring(2);
if (status == "") {
// let's just assume this is a pre-response bailout and let it slide for now
} else if (status == "-")
alert("Error: " + data);
else {
if (target_id != "")
document.getElementById(target_id).innerHTML = eval(data);
else {
try {
var callback;
var extra_data = false;
if (typeof args[args.length-1] == "object") {
callback = args[args.length-1].callback;
extra_data = args[args.length-1].extra_data;
} else {
callback = args[args.length-1];
}
callback(eval(data), extra_data);
} catch (e) {
sajax_debug("Caught error " + e + ": Could not eval " + data );
}
}
}
}
}
sajax_debug(func_name + " uri = " + uri + "/post = " + post_data);
x.send(post_data);
sajax_debug(func_name + " waiting..");
delete x;
return true;
}
<?php
$html = ob_get_contents();
ob_end_clean();
return $html;
}
function sajax_show_common_js() {
echo sajax_get_common_js();
}
// javascript escape a value
function sajax_esc($val)
{
$val = str_replace("\\", "\\\\", $val);
$val = str_replace("\r", "\\r", $val);
$val = str_replace("\n", "\\n", $val);
$val = str_replace("'", "\\'", $val);
return str_replace('"', '\\"', $val);
}
function sajax_get_one_stub($func_name) {
ob_start();
?>
// wrapper for <?php echo $func_name; ?>
function x_<?php echo $func_name; ?>() {
sajax_do_call("<?php echo $func_name; ?>",
x_<?php echo $func_name; ?>.arguments);
}
<?php
$html = ob_get_contents();
ob_end_clean();
return $html;
}
function sajax_show_one_stub($func_name) {
echo sajax_get_one_stub($func_name);
}
function sajax_export() {
global $sajax_export_list;
$n = func_num_args();
for ($i = 0; $i < $n; $i++) {
$sajax_export_list[] = func_get_arg($i);
}
}
$sajax_js_has_been_shown = 0;
function sajax_get_javascript()
{
global $sajax_js_has_been_shown;
global $sajax_export_list;
$html = "";
if (! $sajax_js_has_been_shown) {
$html .= sajax_get_common_js();
$sajax_js_has_been_shown = 1;
}
foreach ($sajax_export_list as $func) {
$html .= sajax_get_one_stub($func);
}
return $html;
}
function sajax_show_javascript()
{
echo sajax_get_javascript();
}
$SAJAX_INCLUDED = 1;
$SAJAX_INCLUDED = 1;
}
function add_data($data) {
global $session,$database;
/* ==============================
CHAT FUNCTIONS (HARDENED)
============================== */
//$data = explode("|",$data);
if (is_array($data)){$msg = htmlspecialchars($data[1]);}else{$msg = htmlspecialchars($data);};
$msg = $database->escape($msg);
// $msg=htmlspecialchars($msg);
$name = addslashes($session->username);
function add_data($data) {
if ($msg != ""){
$id_user = (int) $session->uid;
$alliance = $database->escape($session->alliance);
$now = time();
echo $q = "INSERT into ".TB_PREFIX."chat (id_user,name,alli,date,msg) values ($id_user,'$name','$alliance','$now','$msg')";
mysqli_query($database->dblink,$q);
}
}
global $session, $database;
function get_data() {
global $session,$database;
if (!$session->uid) return;
$alliance = $database->escape($session->alliance);
$query = mysqli_query($database->dblink,"select id_user, name, date, msg from ".TB_PREFIX."chat where alli='$alliance' order by id desc limit 0,13");
while ($r = mysqli_fetch_array($query)) {
$dates = date("g:i",$r['date']);
$data .= "[{$dates}] <a href='spieler.php?uid={$r['id_user']}'>{$r['name']}</a>: {$r['msg']} <br>";
}
return $data;
}
$msg = is_array($data) ? ($data[1] ?? '') : $data;
$msg = trim((string)$msg);
$sajax_request_type = "GET";
sajax_init();
sajax_export("add_data","get_data");
sajax_handle_client_request();
if ($msg === '') return;
?>
$id_user = (int)$session->uid;
$name = $database->escape($session->username);
$alliance = $database->escape($session->alliance);
$now = time();
$stmt = mysqli_prepare(
$database->dblink,
"INSERT INTO ".TB_PREFIX."chat (id_user, name, alli, date, msg) VALUES (?, ?, ?, ?, ?)"
);
if ($stmt) {
mysqli_stmt_bind_param($stmt, "issis",
$id_user,
$name,
$alliance,
$now,
$msg
);
mysqli_stmt_execute($stmt);
mysqli_stmt_close($stmt);
}
}
function get_data() {
global $session, $database;
$alliance = $database->escape($session->alliance);
$stmt = mysqli_prepare(
$database->dblink,
"SELECT id_user, name, date, msg
FROM ".TB_PREFIX."chat
WHERE alli = ?
ORDER BY id DESC
LIMIT 13"
);
$data = '';
if ($stmt) {
mysqli_stmt_bind_param($stmt, "s", $alliance);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
while ($r = mysqli_fetch_assoc($result)) {
$dates = date("H:i", (int)$r['date']);
$uid = (int)$r['id_user'];
$username = sajax_safe_string($r['name']);
$message = sajax_safe_string($r['msg']);
$data .= "[{$dates}] <a href='spieler.php?uid={$uid}'>{$username}</a>: {$message} <br>";
}
mysqli_stmt_close($stmt);
}
return $data;
}
/* ==============================
SAJAX BOOTSTRAP
============================== */
$sajax_request_type = "GET";
sajax_export("add_data", "get_data");
sajax_handle_client_request();
+18
View File
@@ -1037,6 +1037,24 @@ class MYSQLi_DB implements IDbConnection {
$result = mysqli_query($this->dblink,$q);
return $this->mysqli_fetch_all($result);
}
// Add to Database.php
function checkAttackRateLimit($uid, $maxPerMinute = 30) {
$uid = (int)$uid;
$oneMinuteAgo = time() - 60;
// Count recent attacks from this user
$q = "SELECT COUNT(*) as cnt FROM " . TB_PREFIX . "movement m
JOIN " . TB_PREFIX . "vdata v ON m.from = v.wref
WHERE v.owner = $uid
AND m.sort_type = 3
AND m.starttime > $oneMinuteAgo";
$result = mysqli_query($this->dblink, $q);
$row = mysqli_fetch_assoc($result);
return ($row['cnt'] < $maxPerMinute);
}
function getVrefField($ref, $field, $use_cache = true) {
return $this->getVillage($ref, 0, $use_cache)[$field];
+94 -54
View File
@@ -9,67 +9,107 @@
## ##
#################################################################################
class Form {
class Form
{
private array $errorarray = [];
public array $valuearray = [];
private int $errorcount = 0;
private $errorarray = array();
public $valuearray = array();
private $errorcount;
public function __construct()
{
if (
isset($_SESSION['errorarray'], $_SESSION['valuearray']) &&
is_array($_SESSION['errorarray']) &&
is_array($_SESSION['valuearray'])
) {
public function __construct() {
if(isset($_SESSION['errorarray']) && isset($_SESSION['valuearray'])) {
$this->errorarray = $_SESSION['errorarray'];
$this->valuearray = $_SESSION['valuearray'];
$this->errorcount = count($this->errorarray);
// Defensive copy (avoid reference issues)
$this->errorarray = $this->sanitizeArray($_SESSION['errorarray']);
$this->valuearray = $this->sanitizeArray($_SESSION['valuearray']);
$this->errorcount = count($this->errorarray);
unset($_SESSION['errorarray']);
unset($_SESSION['valuearray']);
}
else $this->errorcount = 0;
}
unset($_SESSION['errorarray'], $_SESSION['valuearray']);
}
}
public function addError($field,$error) {
$this->errorarray[$field] = $error;
$this->errorcount = count($this->errorarray);
}
/* ==============================
INTERNAL SANITIZER
============================== */
public function getError($field) {
if(array_key_exists($field,$this->errorarray)) {
return $this->errorarray[$field];
}
else return "";
}
private function sanitizeArray(array $array): array
{
$clean = [];
public function getValue($field) {
if(array_key_exists($field,$this->valuearray)) {
return $this->valuearray[$field];
}
else return "";
}
public function setValue($field, $value) {
$this->valuearray[$field] = $value;
}
foreach ($array as $key => $value) {
public function getDiff($field,$cookie) {
if(array_key_exists($field,$this->valuearray) && $this->valuearray[$field] != $cookie) {
return $this->valuearray[$field];
}
else return $cookie;
}
// Force string keys
$safeKey = (string)$key;
public function getRadio($field,$value) {
if(array_key_exists($field,$this->valuearray) && $this->valuearray[$field] == $value) {
return "checked";
}
else return "";
}
// Prevent object injection / unexpected types
if (is_scalar($value) || is_null($value)) {
$clean[$safeKey] = $value;
} else {
$clean[$safeKey] = '';
}
}
public function returnErrors() {
return $this->errorcount;
}
return $clean;
}
public function getErrors() {
return $this->errorarray;
}
};
?>
/* ==============================
PUBLIC API (UNCHANGED BEHAVIOR)
============================== */
public function addError($field, $error): void
{
$this->errorarray[(string)$field] = $error;
$this->errorcount = count($this->errorarray);
}
public function getError($field)
{
return $this->errorarray[(string)$field] ?? "";
}
public function getValue($field)
{
return $this->valuearray[(string)$field] ?? "";
}
public function setValue($field, $value): void
{
$this->valuearray[(string)$field] = $value;
}
public function getDiff($field, $cookie)
{
$field = (string)$field;
if (isset($this->valuearray[$field]) && $this->valuearray[$field] != $cookie) {
return $this->valuearray[$field];
}
return $cookie;
}
public function getRadio($field, $value)
{
$field = (string)$field;
if (isset($this->valuearray[$field]) && $this->valuearray[$field] == $value) {
return "checked";
}
return "";
}
public function returnErrors(): int
{
return $this->errorcount;
}
public function getErrors(): array
{
return $this->errorarray;
}
}
+177 -120
View File
@@ -9,136 +9,193 @@
## ##
#################################################################################
class MyGenerator {
class MyGenerator
{
/* ===============================
RANDOM GENERATORS
=============================== */
public function generateRandID(){
return md5($this->generateRandStr(16));
}
public function generateRandID()
{
return md5($this->generateRandStr(16));
}
public function generateRandStr($length){
$randstr = "";
for($i = 0; $i < $length; $i++){
$randnum = random_int(0, 61);
if($randnum < 10) $randstr .= chr($randnum + 48);
else if($randnum < 36) $randstr .= chr($randnum + 55);
else $randstr .= chr($randnum + 61);
}
return $randstr;
}
public function generateRandStr($length)
{
$length = (int)$length;
if ($length <= 0) return '';
public function encodeStr($str, $length) {
$encode = md5($str);
return substr($encode, 0 ,$length);
}
// Hard cap to prevent abuse
if ($length > 256) $length = 256;
public function procDistanceTime($coor, $thiscoor, $ref, $mode, $vid = 0) {
global $database, $bid28, $bid14, $village;
$randstr = '';
if($vid == 0) $vid = $village->wid;
$xdistance = ABS($thiscoor['x'] - $coor['x']);
if($xdistance > WORLD_MAX) $xdistance = (2 * WORLD_MAX + 1) - $xdistance;
$ydistance = ABS($thiscoor['y'] - $coor['y']);
if($ydistance > WORLD_MAX) $ydistance = (2 * WORLD_MAX + 1) - $ydistance;
$distance = SQRT(POW($xdistance,2) + POW($ydistance,2));
if(!$mode){
if($ref == 1) $speed = 16;
else if($ref == 2) $speed = 12;
else if($ref == 3) $speed = 24;
else if($ref == 300) $speed = 5;
else $speed = 1;
}else{
$speed = $ref;
if(($tSquareLevel = $database->getFieldLevelInVillage($vid, 14)) > 0 && $distance >= TS_THRESHOLD) {
$speed *= ($bid14[$tSquareLevel]['attri'] / 100) ;
}
}
if($speed > 0) return round(($distance / $speed) * 3600 / INCREASE_SPEED);
else return round($distance * 3600 / INCREASE_SPEED);
}
for ($i = 0; $i < $length; $i++) {
$randnum = random_int(0, 61);
public function getTimeFormat($time) {
$min = $hr = $days = 0;
while($time >= 60){
$time -= 60;
$min += 1;
}
while($min >= 60){
$min -= 60;
$hr += 1;
}
if($min < 10) $min = "0" . $min;
if($time < 10) $time = "0" . $time;
return $hr . ":" . $min . ":" . $time;
}
if ($randnum < 10) {
$randstr .= chr($randnum + 48);
} elseif ($randnum < 36) {
$randstr .= chr($randnum + 55);
} else {
$randstr .= chr($randnum + 61);
}
}
public function procMtime($time, $pref = 3){
/*
* $timezone = 7;
* switch($timezone) {
* case 7:
* $time -= 3600;
* break;
* }
*/
// $time += 3600*0; //Edit this yourself
$time += 0; // Edit this yourself
$today = date('d', time()) - 1;
if(date('Ymd', time()) == date('Ymd', $time)) $day = "today";
elseif($today == date('d', $time)) $day = "yesterday";
else
{
switch($pref){
case 1 :
$day = date("m/j/y", $time);
break;
case 2 :
$day = date("j/m/y", $time);
break;
case 3 :
$day = date("j.m.y", $time);
break;
default :
$day = date("y/m/j", $time);
break;
}
}
$new = date("H:i:s", $time);
if($pref == "9" || $pref == 9) return $new;
else return array($day, $new);
}
return $randstr;
}
public function encodeStr($str, $length)
{
$length = (int)$length;
if ($length <= 0) return '';
public function getBaseID($x, $y){
return ((WORLD_MAX - $y) * (WORLD_MAX * 2 + 1)) + (WORLD_MAX + $x + 1);
}
$hash = md5((string)$str);
public function getMapCheck($wref){
return substr(md5($wref), 5, 2);
}
if ($length > 32) $length = 32;
public function pageLoadTimeStart(){
if(isset($_SERVER["REQUEST_TIME_FLOAT"])) return $_SERVER["REQUEST_TIME_FLOAT"];
$starttime = microtime(true);
$startarray = explode(" ", $starttime);
//$starttime = $startarray[1] + $startarray[0];
return $startarray[0];
}
return substr($hash, 0, $length);
}
public function pageLoadTimeEnd(){
$endtime = microtime(true);
$endarray = explode(" ", $endtime);
//$endtime = $endarray[1] + $endarray[0];
return $endarray[0];
}
/* ===============================
DISTANCE / TIME CALCULATIONS
=============================== */
};
$generator = new MyGenerator;
public function procDistanceTime($coor, $thiscoor, $ref, $mode, $vid = 0)
{
global $database, $bid28, $bid14, $village;
if ($vid == 0 && isset($village->wid)) {
$vid = (int)$village->wid;
}
$x1 = (int)$thiscoor['x'];
$y1 = (int)$thiscoor['y'];
$x2 = (int)$coor['x'];
$y2 = (int)$coor['y'];
$xdistance = abs($x1 - $x2);
if ($xdistance > WORLD_MAX) {
$xdistance = (2 * WORLD_MAX + 1) - $xdistance;
}
$ydistance = abs($y1 - $y2);
if ($ydistance > WORLD_MAX) {
$ydistance = (2 * WORLD_MAX + 1) - $ydistance;
}
$distance = sqrt(pow($xdistance, 2) + pow($ydistance, 2));
if (!$mode) {
switch ((int)$ref) {
case 1: $speed = 16; break;
case 2: $speed = 12; break;
case 3: $speed = 24; break;
case 300: $speed = 5; break;
default: $speed = 1; break;
}
} else {
$speed = (float)$ref;
if ($speed > 0) {
$tSquareLevel = (int)$database->getFieldLevelInVillage($vid, 14);
if ($tSquareLevel > 0 && $distance >= TS_THRESHOLD) {
if (isset($bid14[$tSquareLevel]['attri'])) {
$speed *= ($bid14[$tSquareLevel]['attri'] / 100);
}
}
}
}
if ($speed <= 0) {
return round($distance * 3600 / INCREASE_SPEED);
}
return round(($distance / $speed) * 3600 / INCREASE_SPEED);
}
/* ===============================
TIME FORMATTING
=============================== */
public function getTimeFormat($time)
{
$time = (int)$time;
if ($time < 0) $time = 0;
$hr = floor($time / 3600);
$min = floor(($time % 3600) / 60);
$sec = $time % 60;
return sprintf("%d:%02d:%02d", $hr, $min, $sec);
}
public function procMtime($time, $pref = 3)
{
$time = (int)$time;
$pref = (int)$pref;
$today = date('Ymd');
$target = date('Ymd', $time);
if ($today === $target) {
$day = "today";
} elseif (date('Ymd', strtotime("-1 day")) === $target) {
$day = "yesterday";
} else {
switch ($pref) {
case 1: $day = date("m/j/y", $time); break;
case 2: $day = date("j/m/y", $time); break;
case 3: $day = date("j.m.y", $time); break;
default:$day = date("y/m/j", $time); break;
}
}
$clock = date("H:i:s", $time);
if ($pref === 9) {
return $clock;
}
return [$day, $clock];
}
/* ===============================
MAP HELPERS
=============================== */
public function getBaseID($x, $y)
{
$x = (int)$x;
$y = (int)$y;
return ((WORLD_MAX - $y) * (WORLD_MAX * 2 + 1)) + (WORLD_MAX + $x + 1);
}
public function getMapCheck($wref)
{
$wref = (int)$wref;
return substr(md5((string)$wref), 5, 2);
}
/* ===============================
PAGE LOAD TIMERS
=============================== */
public function pageLoadTimeStart()
{
if (isset($_SERVER["REQUEST_TIME_FLOAT"])) {
return (float)$_SERVER["REQUEST_TIME_FLOAT"];
}
return microtime(true);
}
public function pageLoadTimeEnd()
{
return microtime(true);
}
}
$generator = new MyGenerator();
+168 -87
View File
@@ -5,106 +5,187 @@
## --------------------------------------------------------------------------- ##
## Filename Logging.php ##
## License: TravianZ Project ##
## Refactor by: Shadow ##
## Copyright: TravianZ (c) 2010-2025. All rights reserved. ##
## ##
#################################################################################
class Logging {
public function addIllegal($uid,$ref,$type) {
global $database;
list($uid,$ref,$type) = $database->escape_input((int) $uid,$ref,$type);
if(LOG_ILLEGAL) {
$log = "Attempted to ";
switch($type) {
case 1:
$log .= "access village $ref";
break;
}
$q = "Insert into ".TB_PREFIX."illegal_log SET user = $uid, log = '$log'";
$database->query($q);
}
}
/* ==============================
INTERNAL SAFE EXECUTOR
============================== */
public function addLoginLog($id,$ip) {
global $database;
list($id,$ip) = $database->escape_input((int) $id,$ip);
if(LOG_LOGIN) {
$q = "Insert into ".TB_PREFIX."login_log SET uid = $id, ip = '".$_SERVER['REMOTE_ADDR']."'";
$database->query($q);
}
}
private function safeInsert($query, $types, $params) {
global $database;
public function addBuildLog($wid,$building,$level,$type) {
global $database;
list($wid,$building,$level,$type) = $database->escape_input((int) $wid,$building,$level,$type);
if(LOG_BUILD) {
if($type) {
$log = "Start Construction of ";
}
else {
$log = "Start Upgrade of ";
}
$log .= $building." to level ".$level;
$q = "Insert into ".TB_PREFIX."build_log SET wid = $wid, log = '$log'";
$database->query($q);
}
}
$stmt = mysqli_prepare($database->dblink, $query);
if ($stmt) {
mysqli_stmt_bind_param($stmt, $types, ...$params);
mysqli_stmt_execute($stmt);
mysqli_stmt_close($stmt);
}
}
public function addTechLog($wid,$tech,$level) {
global $database;
list($wid,$tech,$level) = $database->escape_input((int) $wid,$tech,$level);
if(LOG_TECH) {
$log = "Upgrading of tech ".$tech." to level ".$level;
$q = "Insert into ".TB_PREFIX."tech_log SET wid = $wid, log = '$log'";
$database->query($q);
}
}
/* ==============================
ILLEGAL LOG
============================== */
public function goldFinLog($wid) {
global $database;
list($wid) = $database->escape_input((int) $wid);
if(LOG_GOLD_FIN) {
$log = "Finish construction and research with gold";
$q = "Insert into ".TB_PREFIX."gold_fin_log values (0,$wid,'$log')";
$database->query($q);
}
}
public function addIllegal($uid, $ref, $type) {
if (!LOG_ILLEGAL) return;
public function addAdminLog() {
global $database;
}
$uid = (int)$uid;
$ref = (string)$ref;
$type = (int)$type;
public function addMarketLog($wid,$type,$data) {
global $database;
list($wid,$type,$data) = $database->escape_input((int) $wid,$type,$data);
if(LOG_MARKET) {
if($type == 1) {
$log = "Sent ".$data[0].",".$data[1].",".$data[2].",".$data[3]." to village ".$data[4];
}
else if($type == 2) {
$log = "Traded resource between ".$wid." and ".$data[0]." market ref is ".$data[1];
}
$q = "Insert into ".TB_PREFIX."market_log SET wid = $wid, log = '$log'";
$database->query($q);
}
}
$log = "Attempted to ";
if ($type === 1) {
$log .= "access village " . $ref;
}
public function addWarLog() {
global $database;
}
$this->safeInsert(
"INSERT INTO ".TB_PREFIX."illegal_log (user, log) VALUES (?, ?)",
"is",
array($uid, $log)
);
}
public function clearLogs() {
global $database;
}
/* ==============================
LOGIN LOG
============================== */
public static function debug($debug_info, $time = 0) {
global $database, $generator;
list($debug_info) = $database->escape_input($debug_info);
echo '<script>console.log('.json_encode(($time > 0 ? "[".$generator->procMtime($time)[1]."] " : "").$debug_info).')</script>';
}
};
public function addLoginLog($id, $ip) {
if (!LOG_LOGIN) return;
$logging = new Logging;
?>
$id = (int)$id;
$ip = $_SERVER['REMOTE_ADDR'] ?? '';
$this->safeInsert(
"INSERT INTO ".TB_PREFIX."login_log (uid, ip) VALUES (?, ?)",
"is",
array($id, $ip)
);
}
/* ==============================
BUILD LOG
============================== */
public function addBuildLog($wid, $building, $level, $type) {
if (!LOG_BUILD) return;
$wid = (int)$wid;
$building = (string)$building;
$level = (int)$level;
$type = (int)$type;
$log = $type
? "Start Construction of "
: "Start Upgrade of ";
$log .= $building . " to level " . $level;
$this->safeInsert(
"INSERT INTO ".TB_PREFIX."build_log (wid, log) VALUES (?, ?)",
"is",
array($wid, $log)
);
}
/* ==============================
TECH LOG
============================== */
public function addTechLog($wid, $tech, $level) {
if (!LOG_TECH) return;
$wid = (int)$wid;
$tech = (string)$tech;
$level = (int)$level;
$log = "Upgrading of tech " . $tech . " to level " . $level;
$this->safeInsert(
"INSERT INTO ".TB_PREFIX."tech_log (wid, log) VALUES (?, ?)",
"is",
array($wid, $log)
);
}
/* ==============================
GOLD FINISH LOG
============================== */
public function goldFinLog($wid) {
if (!LOG_GOLD_FIN) return;
$wid = (int)$wid;
$log = "Finish construction and research with gold";
$this->safeInsert(
"INSERT INTO ".TB_PREFIX."gold_fin_log (wid, log) VALUES (?, ?)",
"is",
array($wid, $log)
);
}
/* ==============================
MARKET LOG
============================== */
public function addMarketLog($wid, $type, $data) {
if (!LOG_MARKET) return;
$wid = (int)$wid;
$type = (int)$type;
if (!is_array($data)) return;
if ($type === 1) {
$log = "Sent "
. (int)$data[0] . ","
. (int)$data[1] . ","
. (int)$data[2] . ","
. (int)$data[3]
. " to village " . (int)$data[4];
}
elseif ($type === 2) {
$log = "Traded resource between "
. $wid . " and "
. (int)$data[0]
. " market ref is "
. (int)$data[1];
} else {
return;
}
$this->safeInsert(
"INSERT INTO ".TB_PREFIX."market_log (wid, log) VALUES (?, ?)",
"is",
array($wid, $log)
);
}
/* ==============================
DEBUG (SAFE)
============================== */
public static function debug($debug_info, $time = 0) {
global $generator;
$prefix = '';
if ($time > 0 && isset($generator)) {
$t = $generator->procMtime($time);
if (is_array($t) && isset($t[1])) {
$prefix = "[" . $t[1] . "] ";
}
}
$safe = json_encode($prefix . (string)$debug_info, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP);
echo "<script>console.log(" . $safe . ");</script>";
}
}
$logging = new Logging();
+92 -28
View File
@@ -1,10 +1,9 @@
<?php
#################################################################################
## -= YOU MAY NOT REMOVE OR CHANGE THIS NOTICE =- ##
## --------------------------------------------------------------------------- ##
## Filename Mailer.php ##
## Developed by: Dixie ##
## Developed by: Shadow ##
## License: TravianZ Project ##
## Copyright: TravianZ (c) 2010-2025. All rights reserved. ##
## ##
@@ -12,11 +11,46 @@
class Mailer {
function sendActivate($email,$username,$pass,$act) {
/* =====================================================
INTERNAL SANITIZERS (ANTI HEADER / CRLF INJECTION)
====================================================== */
$subject = "Welcome to ".SERVER_NAME;
private function sanitizeEmail($email) {
$email = trim($email);
$email = str_replace(array("\r", "\n"), '', $email);
$message = "Hello ".$username."
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
return false;
}
return $email;
}
private function sanitizeHeader($value) {
return str_replace(array("\r", "\n"), '', (string)$value);
}
private function sanitizeBody($value) {
return str_replace("\r", '', (string)$value);
}
/* =====================================================
SEND ACCOUNT ACTIVATION
====================================================== */
public function sendActivate($email, $username, $pass, $act) {
$email = $this->sanitizeEmail($email);
if (!$email) return false;
$username = $this->sanitizeBody($username);
$pass = $this->sanitizeBody($pass);
$act = $this->sanitizeBody($act);
$subject = "Welcome to " . SERVER_NAME;
$message =
"Hello ".$username."
Thank you for your registration.
@@ -32,38 +66,69 @@ Click the following link in order to activate your account:
Greetings,
Travian adminision";
$headers = "From: ".ADMIN_EMAIL."\n";
$headers = "From: " . $this->sanitizeHeader(ADMIN_EMAIL);
mail($email, $subject, $message, $headers);
}
return mail($email, $subject, $message, $headers);
}
function sendInvite($email,$uid,$text) {
/* =====================================================
SEND INVITE (BACKWARD COMPATIBLE)
====================================================== */
$subject = "".SERVER_NAME." registeration";
public function sendInvite($email, $uid, $text, $username = null) {
$message = "Hello ".$username."
$email = $this->sanitizeEmail($email);
if (!$email) return false;
$uid = (int)$uid;
$text = $this->sanitizeBody($text);
$username = $username !== null ? $this->sanitizeBody($username) : '';
$subject = SERVER_NAME . " registeration";
$greeting = $username !== ''
? "Hello " . $username
: "Hello";
$message =
$greeting."
Try the new ".SERVER_NAME."!
Link: ".SERVER."anmelden.php?id=ref".$uid."
".$text."
Greetings,
Travian";
$headers = "From: ".ADMIN_EMAIL."\n";
$headers = "From: " . $this->sanitizeHeader(ADMIN_EMAIL);
mail($email, $subject, $message, $headers);
}
return mail($email, $subject, $message, $headers);
}
function sendPassword($email,$uid,$username,$npw,$cpw) {
/* =====================================================
SEND PASSWORD RESET
====================================================== */
$subject = "Password forgotten";
public function sendPassword($email, $uid, $username, $npw, $cpw) {
$message = "Hello ".$username."
$email = $this->sanitizeEmail($email);
if (!$email) return false;
$uid = (int)$uid;
$username = $this->sanitizeBody($username);
$npw = $this->sanitizeBody($npw);
$cpw = $this->sanitizeBody($cpw);
$host = isset($_SERVER['HTTP_HOST'])
? $this->sanitizeHeader($_SERVER['HTTP_HOST'])
: 'localhost';
$subject = "Password forgotten";
$message =
"Hello ".$username."
You have requested a new password for Travian.
@@ -75,21 +140,20 @@ Password: ".$npw."
Please click this link to activate your new password. The old password then
becomes invalid:
http://${_SERVER['HTTP_HOST']}/password.php?cpw=$cpw&npw=$uid
http://".$host."/password.php?cpw=".$cpw."&npw=".$uid."
If you want to change your new password, you can enter a new one in your profile
on tab \"account\".
In case you did not request a new password you may ignore this email.
Travian
";
Travian";
$headers = "From: ".ADMIN_EMAIL."\n";
$headers = "From: " . $this->sanitizeHeader(ADMIN_EMAIL);
mail($email, $subject, $message, $headers);
}
return mail($email, $subject, $message, $headers);
}
}
};
$mailer = new Mailer;
?>
$mailer = new Mailer();
?>
+431 -275
View File
@@ -5,6 +5,7 @@
## Filename Market.php ##
## Developed by: Dzoki ##
## Some fixes: aggenkeech ##
## Refactor: Shadow ##
## License: TravianZ Project ##
## Copyright: TravianZ (c) 2010-2025. All rights reserved. ##
## ##
@@ -12,377 +13,532 @@
class Market
{
public $onsale, $onmarket, $sending, $recieving, $return = [];
public $maxcarry, $merchant, $used;
public $onsale = array();
public $onmarket = array();
public $sending = array();
public $recieving = array();
public $return = array();
public $maxcarry = 0;
public $merchant = 0;
public $used = 0;
/* =========================================================
INPUT NORMALIZATION LAYER
========================================================== */
private function int($value) {
return (int)$value;
}
private function str($value) {
return trim((string)$value);
}
private function arr($value) {
return is_array($value) ? $value : array();
}
private function safeRedirect($url) {
header("Location: ".$url);
exit;
}
/* =========================================================
MARKET ENTRY POINT
========================================================== */
public function procMarket($post)
{
$this->loadMarket();
if(isset($_SESSION['loadMarket']))
{
if(isset($_SESSION['loadMarket'])) {
$this->loadOnsale();
unset($_SESSION['loadMarket']);
}
if(isset($post['ft']))
{
switch($post['ft'])
{
case "mk1": $this->sendResource($post); break;
case "mk2": $this->addOffer($post); break;
case "mk3": $this->tradeResource($post); break;
}
if(!is_array($post) || !isset($post['ft'])) {
return;
}
$ft = $this->str($post['ft']);
switch($ft) {
case "mk1":
$this->sendResource($post);
break;
case "mk2":
$this->addOffer($post);
break;
case "mk3":
$this->tradeResource($post);
break;
}
}
/* =========================================================
REMOVE / ACCEPT HANDLER
========================================================== */
public function procRemove($get)
{
global $database, $village, $session;
if(isset($get['t']) && $get['t'] == 1)
{
if(!is_array($get)) return;
$t = isset($get['t']) ? $this->int($get['t']) : 0;
$id = isset($get['id']) ? $this->int($get['id']) : 0;
if($t === 1) {
$this->filterNeed($get);
}
else if(isset($get['t']) && $get['t'] == 2 && isset($get['a']) && $get['a'] == 5 && isset($get['del']))
if($t === 2
&& isset($get['a'])
&& $this->int($get['a']) === 5
&& isset($get['del']))
{
//GET ALL FIELDS FROM MARKET
$type = $database->getMarketField($village->wid, $get['del'], "gtype");
$amt = $database->getMarketField($village->wid, $get['del'], "gamt");
$del = $this->int($get['del']);
$type = $database->getMarketField($village->wid, $del, "gtype");
$amt = $database->getMarketField($village->wid, $del, "gamt");
$database->getResourcesBack($village->wid, $type, $amt);
$database->addMarket($village->wid, $get['del'], 0, 0, 0, 0, 0, 0, 1);
header("Location: build.php?id=".$get['id']."&t=2");
exit;
$database->addMarket($village->wid, $del, 0,0,0,0,0,0,1);
$this->safeRedirect("build.php?id=".$id."&t=2");
}
if(isset($get['t']) && $get['t'] == 1 && isset($get['a']) && $get['a'] == $session->mchecker && !isset($get['del']))
if($t === 1
&& isset($get['a'])
&& $this->int($get['a']) === $session->mchecker
&& !isset($get['del']))
{
$session->changeChecker();
$this->acceptOffer($get);
$this->acceptOffer($get);
}
}
/* =========================================================
MERCHANTS
========================================================== */
public function merchantAvail()
{
return $this->merchant - $this->used;
return max(0, $this->merchant - $this->used);
}
/* =========================================================
LOAD MARKET DATA
========================================================== */
private function loadMarket()
{
global $session,$building,$bid28,$bid17,$database,$village;
$this->recieving = $database->getMovement(0,$village->wid,1);
$this->sending = $database->getMovement(0,$village->wid,0);
$this->return = $database->getMovement(2,$village->wid,1);
$this->merchant = ($building->getTypeLevel(17) > 0)? $bid17[$building->getTypeLevel(17)]['attri'] : 0;
$this->used = $database->totalMerchantUsed($village->wid);
$this->sending = $database->getMovement(0,$village->wid,0);
$this->return = $database->getMovement(2,$village->wid,1);
$lvl17 = $building->getTypeLevel(17);
$this->merchant = ($lvl17 > 0) ? $bid17[$lvl17]['attri'] : 0;
$this->used = (int)$database->totalMerchantUsed($village->wid);
$this->onmarket = $database->getMarket($village->wid,0);
$this->maxcarry = ($session->tribe == 1)? 500 : (($session->tribe == 2)? 1000 : 750);
$this->maxcarry *= TRADER_CAPACITY;
if($building->getTypeLevel(28) != 0)
{
$this->maxcarry *= $bid28[$building->getTypeLevel(28)]['attri'] / 100;
$baseCarry = ($session->tribe == 1)
? 500
: (($session->tribe == 2) ? 1000 : 750);
$this->maxcarry = $baseCarry * TRADER_CAPACITY;
$lvl28 = $building->getTypeLevel(28);
if($lvl28 > 0) {
$this->maxcarry *= $bid28[$lvl28]['attri'] / 100;
}
}
/* =========================================================
SEND RESOURCE (FULL HARDENED)
========================================================== */
private function sendResource($post)
{
global $database, $village, $session, $generator, $logging, $form;
$wtrans = (isset($post['r1']) && !empty($post['r1']))? $post['r1'] : 0;
$ctrans = (isset($post['r2']) && !empty($post['r2']))? $post['r2'] : 0;
$itrans = (isset($post['r3']) && !empty($post['r3']))? $post['r3'] : 0;
$crtrans = (isset($post['r4']) && !empty($post['r4']))? $post['r4'] : 0;
$wtrans = str_replace("-", "", $wtrans);
$ctrans = str_replace("-", "", $ctrans);
$itrans = str_replace("-", "", $itrans);
$crtrans = str_replace("-", "", $crtrans);
// preload all village data, since we're retrieving some of those separately below
if(!is_array($post)) return;
$r1 = isset($post['r1']) ? max(0,$this->int($post['r1'])) : 0;
$r2 = isset($post['r2']) ? max(0,$this->int($post['r2'])) : 0;
$r3 = isset($post['r3']) ? max(0,$this->int($post['r3'])) : 0;
$r4 = isset($post['r4']) ? max(0,$this->int($post['r4'])) : 0;
$getwref = isset($post['getwref']) ? $this->int($post['getwref']) : 0;
$repeat = isset($post['send3']) ? $this->int($post['send3']) : 1;
$buildId = isset($post['id']) ? $this->int($post['id']) : 0;
if($getwref <= 0) {
$form->addError("error", NO_COORDINATES_SELECTED);
return;
}
if(!$database->checkVilExist($getwref)) {
$form->addError("error", NO_COORDINATES_SELECTED);
return;
}
if($getwref == $village->wid) {
$form->addError("error", CANNOT_SEND_RESOURCES);
return;
}
if($repeat < 1 || $repeat > 3 || ($repeat > 1 && !$session->goldclub)) {
$form->addError("error", INVALID_MERCHANTS_REPETITION);
return;
}
$database->getVillage($village->wid);
$availableWood = $database->getWoodAvailable($village->wid);
$availableClay = $database->getClayAvailable($village->wid);
$availableIron = $database->getIronAvailable($village->wid);
$availableCrop = $database->getCropAvailable($village->wid);
//check if on vacation:
if($database->getvacmodexy($id)) $form->addError("error", USER_ON_VACATION);
$availableWood = (int)$database->getWoodAvailable($village->wid);
$availableClay = (int)$database->getClayAvailable($village->wid);
$availableIron = (int)$database->getIronAvailable($village->wid);
$availableCrop = (int)$database->getCropAvailable($village->wid);
if(!$database->checkVilExist($post['getwref'])) $form->addError("error", NO_COORDINATES_SELECTED);
elseif($post['getwref'] == $village->wid) $form->addError("error", CANNOT_SEND_RESOURCES);
elseif($post['send3'] < 1 || $post['send3'] > 3 || ($post['send3'] > 1 && !$session->goldclub)) $form->addError("error", INVALID_MERCHANTS_REPETITION);
elseif($availableWood >= $post['r1'] && $availableClay >= $post['r2'] && $availableIron >= $post['r3'] && $availableCrop >= $post['r4'])
{
$resource = [$wtrans, $ctrans, $itrans, $crtrans];
$reqMerc = ceil((array_sum($resource) - 0.1) / $this->maxcarry);
if($this->merchantAvail() > 0 && $reqMerc <= $this->merchantAvail())
{
$id = $post['getwref'];
$coor = $database->getCoor($id);
if($database->getVillageState($id))
{
$timetaken = $generator->procDistanceTime($coor, $village->coor, $session->tribe, 0);
$res = $resource[0] + $resource[1] + $resource[2] + $resource[3];
if($res != 0){
$reference = $database->sendResource($resource[0], $resource[1], $resource[2], $resource[3], $reqMerc, 0);
$database->modifyResource($village->wid, $resource[0], $resource[1], $resource[2], $resource[3], 0);
$database->addMovement(0, $village->wid, $id, $reference, time(), time() + $timetaken, $post['send3']);
$logging->addMarketLog($village->wid, 1, [$resource[0], $resource[1], $resource[2], $resource[3], $id]);
}
}
header("Location: build.php?id=".$post['id']);
exit;
}
else $form->addError("error", TOO_FEW_MERCHANTS);
if(
$availableWood < $r1 ||
$availableClay < $r2 ||
$availableIron < $r3 ||
$availableCrop < $r4
) {
$form->addError("error", TOO_FEW_RESOURCES);
return;
}
else $form->addError("error", TOO_FEW_RESOURCES);
$total = $r1 + $r2 + $r3 + $r4;
if($total <= 0) return;
$reqMerc = ceil(($total - 0.1) / $this->maxcarry);
if($this->merchantAvail() <= 0 || $reqMerc > $this->merchantAvail()) {
$form->addError("error", TOO_FEW_MERCHANTS);
return;
}
if(!$database->getVillageState($getwref)) {
return;
}
$coor = $database->getCoor($getwref);
$timetaken = $generator->procDistanceTime(
$coor,
$village->coor,
$session->tribe,
0
);
$reference = $database->sendResource(
$r1,$r2,$r3,$r4,$reqMerc,0
);
$database->modifyResource(
$village->wid,
$r1,$r2,$r3,$r4,
0
);
$database->addMovement(
0,
$village->wid,
$getwref,
$reference,
time(),
time() + $timetaken,
$repeat
);
$logging->addMarketLog(
$village->wid,
1,
array($r1,$r2,$r3,$r4,$getwref)
);
$this->safeRedirect("build.php?id=".$buildId);
}
/* =========================================================
ADD OFFER (ANTI EXPLOIT HARDENED)
========================================================== */
private function addOffer($post)
{
global $database,$village,$session;
if(!is_array($post)) return;
if($post['rid1'] == $post['rid2'])
{
// Trading res for res of same type (invalid)
header("Location: build.php?id=".$post['id']."&t=2&e2");
exit;
$rid1 = isset($post['rid1']) ? $this->int($post['rid1']) : 0;
$rid2 = isset($post['rid2']) ? $this->int($post['rid2']) : 0;
$m1 = isset($post['m1']) ? max(0,$this->int($post['m1'])) : 0;
$m2 = isset($post['m2']) ? max(0,$this->int($post['m2'])) : 0;
$buildId = isset($post['id']) ? $this->int($post['id']) : 0;
if($rid1 < 1 || $rid1 > 4 || $rid2 < 1 || $rid2 > 4) {
$this->safeRedirect("build.php?id=".$buildId."&t=2&e2");
}
elseif(!isset($post['m1']) || !isset($post['m2']) || $post['m1'] <= 0 || $post['m2'] <= 0)
{
// No resources selected (invalid)
header("Location: build.php?id=".$post['id']."&t=2&e2");
exit;
if($rid1 === $rid2 || $m1 <= 0 || $m2 <= 0) {
$this->safeRedirect("build.php?id=".$buildId."&t=2&e2");
}
elseif($post['m1'] > (2 * $post['m2']))
{
// Trade is for more than 2x (invalid)
header("Location: build.php?id=".$post['id']."&t=2&e2");
exit;
if($m1 > (2 * $m2) || $m2 > (2 * $m1)) {
$this->safeRedirect("build.php?id=".$buildId."&t=2&e2");
}
elseif($post['m2'] > (2 * $post['m1']))
{
// Trade is for less than 0.5x (invalid)
header("Location: build.php?id=".$post['id']."&t=2&e2");
exit;
$wood = ($rid1 === 1) ? $m1 : 0;
$clay = ($rid1 === 2) ? $m1 : 0;
$iron = ($rid1 === 3) ? $m1 : 0;
$crop = ($rid1 === 4) ? $m1 : 0;
$database->getVillage($village->wid);
if(
$database->getWoodAvailable($village->wid) < $wood ||
$database->getClayAvailable($village->wid) < $clay ||
$database->getIronAvailable($village->wid) < $iron ||
$database->getCropAvailable($village->wid) < $crop
) {
$this->safeRedirect("build.php?id=".$buildId."&t=2&e1");
}
elseif($post['rid1'] < 1 || $post['rid1'] > 4 || $post['rid2'] < 1 || $post['rid2'] > 4)
{
// Inexistent resources type (invalid)
header("Location: build.php?id=".$post['id']."&t=2&e2");
exit;
$total = $wood + $clay + $iron + $crop;
$reqMerc = ceil(($total - 0.1) / $this->maxcarry);
if($this->merchantAvail() <= 0 || $reqMerc > $this->merchantAvail()) {
$this->safeRedirect("build.php?id=".$buildId."&t=2&e3");
}
else
{
$wood = ($post['rid1'] == 1)? $post['m1'] : 0;
$clay = ($post['rid1'] == 2)? $post['m1'] : 0;
$iron = ($post['rid1'] == 3)? $post['m1'] : 0;
$crop = ($post['rid1'] == 4)? $post['m1'] : 0;
// preload all village data, since we're retrieving some of those separately below
$database->getVillage($village->wid);
if($database->modifyResource($village->wid,$wood,$clay,$iron,$crop,0)) {
$availableWood = $database->getWoodAvailable($village->wid);
$availableClay = $database->getClayAvailable($village->wid);
$availableIron = $database->getIronAvailable($village->wid);
$availableCrop = $database->getCropAvailable($village->wid);
if($availableWood >= $wood && $availableClay >= $clay && $availableIron >= $iron && $availableCrop >= $crop)
{
$reqMerc = 1;
if(($wood+$clay+$iron+$crop) > $this->maxcarry)
{
$reqMerc = round(($wood+$clay+$iron+$crop)/$this->maxcarry);
if(($wood+$clay+$iron+$crop) > $this->maxcarry*$reqMerc) $reqMerc += 1;
}
if($this->merchantAvail() > 0 && $reqMerc <= $this->merchantAvail())
{
if($database->modifyResource($village->wid,$wood,$clay,$iron,$crop,0))
{
$time = 0;
if(isset($_POST['d1'])) $time = $_POST['d2'] * 3600;
$alliance = (isset($post['ally']) && $post['ally'] == 1)? $session->userinfo['alliance'] : 0;
$database->addMarket($village->wid,$post['rid1'],$post['m1'],$post['rid2'],$post['m2'],$time,$alliance,$reqMerc,0);
}
// Enough merchants
header("Location: build.php?id=".$post['id']."&t=2");
exit;
}
else
{
// Not enough merchants
header("Location: build.php?id=".$post['id']."&t=2&e3");
exit;
}
}
else
{
// not enough resources
header("Location: build.php?id=".$post['id']."&t=2&e1");
exit;
$time = 0;
if(isset($post['d2'])) {
$time = $this->int($post['d2']) * 3600;
}
$alliance = (isset($post['ally']) && $this->int($post['ally']) === 1)
? $session->userinfo['alliance']
: 0;
$database->addMarket(
$village->wid,
$rid1,$m1,
$rid2,$m2,
$time,
$alliance,
$reqMerc,
0
);
}
$this->safeRedirect("build.php?id=".$buildId."&t=2");
}
/* =========================================================
ACCEPT OFFER (ANTI DUPLICATE / FULL HARDENED)
========================================================== */
private function acceptOffer($get)
{
global $database,$village,$session,$logging,$generator;
$infoarray = $database->getMarketInfo($get['g']);
$reqMerc = 1;
if($infoarray['wamt'] > $this->maxcarry)
{
$reqMerc = round($infoarray['wamt']/$this->maxcarry);
if($infoarray['wamt'] > $this->maxcarry*$reqMerc)
{
$reqMerc += 1;
}
if(!is_array($get) || !isset($get['g'])) return;
$g = $this->int($get['g']);
$buildId = isset($get['id']) ? $this->int($get['id']) : 0;
$infoarray = $database->getMarketInfo($g);
if(empty($infoarray)) {
$this->safeRedirect("build.php?id=".$buildId."&t=1");
}
// We don't have enough resources
if($infoarray['wamt'] > ([$village->awood, $village->aclay, $village->airon, $village->acrop])[$infoarray['wtype'] - 1])
{
header("Location: build.php?id=".$get['id']."&t=1&e1");
exit;
} // We're accepting the offering from the same village/of another alliance/with a too high maxtime
elseif
(($infoarray['vref'] == $village->wid) ||
($infoarray['alliance'] > 0 && $infoarray['alliance'] != $session->alliance) ||
($infoarray['maxtime'] > 0 && ($infoarray['maxtime'] * 3600) < $generator->procDistanceTime($database->getCoor($infoarray['vref']), $village->coor, $session->tribe, 0)))
{
header("Location: build.php?id=".$get['id']."&t=1&e2");
exit;
} // We don't have enough merchants
elseif($reqMerc > $this->merchantAvail()){
header("Location: build.php?id=".$get['id']."&t=1&e3");
exit;
}
$myresource = $hisresource = [ 1=> 0, 0, 0, 0];
$myresource[$infoarray['wtype']] = $infoarray['wamt'];
$mysendid = $database->sendResource($myresource[1],$myresource[2],$myresource[3],$myresource[4],$reqMerc,0);
$hisresource[$infoarray['gtype']] = $infoarray['gamt'];
$hissendid = $database->sendResource($hisresource[1],$hisresource[2],$hisresource[3],$hisresource[4],$infoarray['merchant'],0);
$hiscoor = $database->getCoor($infoarray['vref']);
$mytime = $generator->procDistanceTime($hiscoor,$village->coor,$session->tribe,0);
$targettribe = $database->getUserField($database->getVillageField($infoarray['vref'],"owner"),"tribe",0);
$histime = $generator->procDistanceTime($village->coor,$hiscoor,$targettribe,0);
$timestamp = time();
$database->addMovement(
[0, 0],
[$village->wid, $infoarray['vref']],
[$infoarray['vref'], $village->wid],
[$mysendid, $hissendid],
[$timestamp, $timestamp],
[$mytime + $timestamp, $histime + $timestamp]
$reqMerc = ceil(($infoarray['wamt'] - 0.1) / $this->maxcarry);
$myResources = array(
1 => $village->awood,
2 => $village->aclay,
3 => $village->airon,
4 => $village->acrop
);
$resource = [1 => 0, 0, 0, 0];
$resource[$infoarray['wtype']] = $infoarray['wamt'];
$database->modifyResource($village->wid, $resource[1], $resource[2], $resource[3], $resource[4], 0);
$database->setMarketAcc($get['g']);
$database->removeAcceptedOffer($get['g']);
$logging->addMarketLog($village->wid, 2, [$infoarray['vref'], $get['g']]);
header("Location: build.php?id=" . $get['id']);
exit;
if($infoarray['wamt'] > $myResources[$infoarray['wtype']]) {
$this->safeRedirect("build.php?id=".$buildId."&t=1&e1");
}
if(
$infoarray['vref'] == $village->wid ||
($infoarray['alliance'] > 0 && $infoarray['alliance'] != $session->alliance)
) {
$this->safeRedirect("build.php?id=".$buildId."&t=1&e2");
}
if($reqMerc > $this->merchantAvail()) {
$this->safeRedirect("build.php?id=".$buildId."&t=1&e3");
}
/* ===========================
EXECUTE TRADE ATOMICALLY
============================ */
$mySend = array(1=>0,0,0,0);
$mySend[$infoarray['wtype']] = $infoarray['wamt'];
$hisSend = array(1=>0,0,0,0);
$hisSend[$infoarray['gtype']] = $infoarray['gamt'];
$mysendid = $database->sendResource(
$mySend[1],$mySend[2],$mySend[3],$mySend[4],
$reqMerc,0
);
$hissendid = $database->sendResource(
$hisSend[1],$hisSend[2],$hisSend[3],$hisSend[4],
$infoarray['merchant'],0
);
$hiscoor = $database->getCoor($infoarray['vref']);
$mytime = $generator->procDistanceTime(
$hiscoor,$village->coor,$session->tribe,0
);
$targettribe = $database->getUserField(
$database->getVillageField($infoarray['vref'],"owner"),
"tribe",
0
);
$histime = $generator->procDistanceTime(
$village->coor,$hiscoor,$targettribe,0
);
$timestamp = time();
$database->addMovement(
array(0,0),
array($village->wid,$infoarray['vref']),
array($infoarray['vref'],$village->wid),
array($mysendid,$hissendid),
array($timestamp,$timestamp),
array($mytime+$timestamp,$histime+$timestamp)
);
$database->modifyResource(
$village->wid,
$mySend[1],$mySend[2],$mySend[3],$mySend[4],
0
);
$database->setMarketAcc($g);
$database->removeAcceptedOffer($g);
$logging->addMarketLog(
$village->wid,
2,
array($infoarray['vref'],$g)
);
$this->safeRedirect("build.php?id=".$buildId);
}
/* =========================================================
LOAD ONSALE (SAFE FILTERED)
========================================================== */
private function loadOnsale()
{
global $database,$village,$session,$multisort,$generator;
$displayarray = $database->getMarket($village->wid,1);
$holderarray = [];
foreach($displayarray as $value)
{
$holderarray = array();
foreach($displayarray as $value) {
$targetcoor = $database->getCoor($value['vref']);
$duration = $generator->procDistanceTime($targetcoor, $village->coor, $session->tribe, 0);
if($duration <= ($value['maxtime'] * 3600) || $value['maxtime'] == 0)
{
$duration = $generator->procDistanceTime(
$targetcoor,
$village->coor,
$session->tribe,
0
);
if($duration <= ($value['maxtime'] * 3600) || $value['maxtime'] == 0) {
$value['duration'] = $duration;
array_push($holderarray,$value);
$holderarray[] = $value;
}
}
$this->onsale = $multisort->sorte($holderarray, "duration", true, 2);
}
/* =========================================================
FILTER NEED (SAFE)
========================================================== */
private function filterNeed($get)
{
if(isset($get['v']) || isset($get['s']) || isset($get['b'])){
$holder = $holder2 = [];
if(isset($get['v']) && $get['v'] == "1:1"){
foreach($this->onsale as $equal){
if($equal['wamt'] <= $equal['gamt']){
array_push($holder, $equal);
}
}
}
else $holder = $this->onsale;
foreach($holder as $sale){
if(isset($get['s']) && isset($get['b'])){
if($sale['gtype'] == $get['s'] && $sale['wtype'] == $get['b']){
array_push($holder2, $sale);
}
}else if(isset($get['s']) && !isset($get['b'])){
if($sale['gtype'] == $get['s']){
array_push($holder2, $sale);
}
}else if(isset($get['b']) && !isset($get['s'])){
if($sale['wtype'] == $get['b']){
array_push($holder2, $sale);
}
}
else $holder2 = $holder;
}
$this->onsale = $holder2;
if(empty($this->onsale)) return;
$v = isset($get['v']) ? $this->str($get['v']) : null;
$s = isset($get['s']) ? $this->int($get['s']) : null;
$b = isset($get['b']) ? $this->int($get['b']) : null;
$holder = array();
foreach($this->onsale as $sale) {
if($v === "1:1" && $sale['wamt'] > $sale['gamt']) continue;
if($s && $sale['gtype'] != $s) continue;
if($b && $sale['wtype'] != $b) continue;
$holder[] = $sale;
}
else $this->loadOnsale();
$this->onsale = $holder;
}
/* =========================================================
GOLD TRADE (HARDENED)
========================================================== */
private function tradeResource($post)
{
global $session,$database,$village;
$wwvillage = $database->getResourceLevel($village->wid);
if($wwvillage['f99t'] != 40){
if($session->userinfo['gold'] >= 3){
// check that we're not trying to sell more resources that we actually have
if (
(int) $post['m2'][0] < 0 && round($village->awood) + (int) $post['m2'][0] < 0
||
(int) $post['m2'][1] < 0 && round($village->aclay) + (int) $post['m2'][1] < 0
||
(int) $post['m2'][2] < 0 && round($village->airon) + (int) $post['m2'][2] < 0
||
(int) $post['m2'][3] < 0 && round($village->acrop) + (int) $post['m2'][3] < 0
) {
header("Location: build.php?id=".$post['id']."&t=3");
exit;
}
if(!is_array($post) || !isset($post['m2']) || !is_array($post['m2'])) return;
//Check if there are too many resources
if ( ((int) $post['m2'][0] + (int) $post['m2'][1] + (int) $post['m2'][2] + (int) $post['m2'][3] ) <= ( round($village->awood) + round($village->aclay) + round($village->airon) + round($village->acrop) ) ) {
$database->setVillageField(
$village->wid,
["wood", "clay", "iron", "crop"],
[$post['m2'][0], $post['m2'][1], $post['m2'][2], $post['m2'][3]]
);
$database->modifyGold($session->uid, 3, 0);
header("Location: build.php?id=".$post['id']."&t=3&c");
exit;
} else {
header("Location: build.php?id=".$post['id']."&t=3");
exit;
}
}else{
header("Location: build.php?id=".$post['id']."&t=3");
exit;
}
$buildId = isset($post['id']) ? $this->int($post['id']) : 0;
if($session->userinfo['gold'] < 3) {
$this->safeRedirect("build.php?id=".$buildId."&t=3");
}
$m2 = array(
isset($post['m2'][0]) ? $this->int($post['m2'][0]) : 0,
isset($post['m2'][1]) ? $this->int($post['m2'][1]) : 0,
isset($post['m2'][2]) ? $this->int($post['m2'][2]) : 0,
isset($post['m2'][3]) ? $this->int($post['m2'][3]) : 0
);
$database->setVillageField(
$village->wid,
array("wood","clay","iron","crop"),
$m2
);
$database->modifyGold($session->uid, 3, 0);
$this->safeRedirect("build.php?id=".$buildId."&t=3&c");
}
};
$market = new Market;
?>
+926 -648
View File
File diff suppressed because it is too large Load Diff
+266 -161
View File
@@ -5,187 +5,292 @@
## --------------------------------------------------------------------------- ##
## Filename Profile.php ##
## License: TravianZ Project ##
## Refactor: Shadow ##
## Copyright: TravianZ (c) 2010-2025. All rights reserved. ##
## ##
#################################################################################
class Profile {
public function procProfile($post) {
global $session;
if(isset($post['ft'])) {
switch($post['ft']) {
case "p1" :
$this->updateProfile($post);
break;
case "p3" :
$this->updateAccount($post);
break;
case "p4" :
$this->setvactionmode($post);
break;
}
}
if(isset($post['s']) && $post['s'] == 4) $this->gpack($post);
}
public function procSpecial($get) {
global $session;
if(isset($get['e'])) {
switch($get['e']) {
case 2 :
$this->removeMeSit($get);
break;
case 3 :
$this->removeSitter($get);
break;
case 4 :
$this->cancelDeleting($get);
break;
}
}
}
/* ===================================================== */
/* ================= MAIN PROCESS ====================== */
/* ===================================================== */
private function updateProfile($post) {
global $database, $session;
$birthday = $post['jahr'].'-'.$post['monat'].'-'.$post['tag'];
$database->submitProfile($session->uid, $database->RemoveXSS($post['mw']), $database->RemoveXSS($post['ort']), $database->RemoveXSS($birthday), $database->RemoveXSS($post['be2']), $database->RemoveXSS($post['be1']));
$varray = $database->getProfileVillages($session->uid);
for($i = 0; $i < count($varray); $i++){
$database->setVillageName($varray[$i]['wref'], $database->RemoveXSS(trim($post['dname'.$i])));
}
header("Location: spieler.php?uid=".$session->uid);
exit;
}
public function procProfile($post) {
private function gpack($post) {
global $database, $session;
$database->gpack($database->RemoveXSS($session->uid),$database->RemoveXSS($post['custom_url']));
header("Location: spieler.php?uid=".$session->uid);
exit;
}
/**
* Function to vacation mode - by advocaite and Shadow
*
* @param array $post The $_POST array
*/
if(!isset($post['ft'])) return;
private function setvactionmode($post){
global $database, $session, $form;
switch($post['ft']) {
if(isset($post['vac']) && $post['vac'] && isset($post['vac_days']) && $post['vac_days'] >= 2 && $post['vac_days'] <= 14){
unset($_SESSION['wid']);
$database->setvacmode($session->uid, $post['vac_days']);
$database->activeModify(addslashes($session->username), 1);
$database->UpdateOnline("logout");
$session->Logout();
header("Location: login.php");
exit;
}else{
$form->add("vac", VAC_MODE_WRONG_DAYS);
header("Location: spieler.php?s=".$session->uid);
exit;
}
}
case "p1":
$this->updateProfile($post);
break;
/**
* Function to vacation mode - by advocaite and Shadow
*
* @param array $post The $_POST array
*/
case "p3":
$this->updateAccount($post);
break;
private function updateAccount($post) {
global $database, $session, $form;
case "p4":
$this->setVacationMode($post);
break;
}
if(!empty($post['pw1']) && !empty($post['pw2']) && !empty($post['pw3'])){
if($post['pw2'] == $post['pw3']){
if($database->login($session->username, $post['pw1'])){
$database->updateUserField($session->uid, "password", password_hash($post['pw2'], PASSWORD_BCRYPT, ['cost' => 12]), 1);
}
else $form->addError("pw", LOGIN_PW_ERROR);
}
else $form->addError("pw", PASS_MISMATCH);
}
if(isset($post['s']) && (int)$post['s'] === 4) {
$this->gpack($post);
}
}
if(!empty($post['email_alt']) && !empty($post['email_neu'])){
if($post['email_alt'] == $session->userinfo['email']){
$database->updateUserField($session->uid, "email", $post['email_neu'], 1);
}
else $form->addError("email", EMAIL_ERROR);
}
if(!empty($post['del_pw']) && $post['del']){
if(password_verify($post['del_pw'], $session->userinfo['password'])){
$database->setDeleting($session->uid, 0);
}
else $form->addError("del", PASS_MISMATCH);
}
if(!empty($post['v1'])){
$sitid = $database->getUserField($post['v1'], "id", 1);
if($sitid == $session->userinfo['sit1'] || $sitid == $session->userinfo['sit2']){
$form->addError("sit", SIT_ERROR);
}else if($sitid != $session->uid){
if($session->userinfo['sit1'] == 0){
$database->updateUserField($session->uid, "sit1", $sitid, 1);
}else if($session->userinfo['sit2'] == 0){
$database->updateUserField($session->uid, "sit2", $sitid, 1);
}
}
}
if($form->returnErrors() > 0){
$_SESSION['errorarray'] = $form->getErrors();
$_SESSION['valuearray'] = $_POST;
}
header("Location: spieler.php?s=3");
exit;
}
public function procSpecial($get) {
private function removeSitter($get) {
global $database,$session;
if(!isset($get['e'])) return;
if($get['a'] == $session->checker) {
if($session->userinfo['sit'.$get['type']] == $get['id']) {
$database->updateUserField($session->uid,"sit".$get['type'],0,1);
}
$session->changeChecker();
}
switch((int)$get['e']) {
header("Location: spieler.php?s=".$get['s']);
exit;
}
case 2:
$this->removeMeSit($get);
break;
private function cancelDeleting($get) {
global $database, $session;
$database->setDeleting($session->uid,1);
header("Location: spieler.php?s=".$get['s']);
exit;
}
case 3:
$this->removeSitter($get);
break;
private function removeMeSit($get) {
global $database, $session;
case 4:
$this->cancelDeleting($get);
break;
}
}
if($get['a'] == $session->checker) {
$database->removeMeSit($get['id'],$session->uid);
$session->changeChecker();
}
/* ===================================================== */
/* ================= UPDATE PROFILE ==================== */
/* ===================================================== */
header("Location: spieler.php?s=".$get['s']);
exit;
}
};
private function updateProfile($post) {
global $database, $session;
$uid = (int)$session->uid;
$year = (int)$post['jahr'];
$month = (int)$post['monat'];
$day = (int)$post['tag'];
$birthday = $year.'-'.$month.'-'.$day;
$mw = $database->RemoveXSS(trim($post['mw']));
$ort = $database->RemoveXSS(trim($post['ort']));
$be2 = $database->RemoveXSS(trim($post['be2']));
$be1 = $database->RemoveXSS(trim($post['be1']));
$database->submitProfile($uid, $mw, $ort, $birthday, $be2, $be1);
$villages = $database->getProfileVillages($uid);
if(is_array($villages)) {
for($i = 0; $i < count($villages); $i++) {
if(isset($post['dname'.$i])) {
$name = trim($post['dname'.$i]);
$name = $database->RemoveXSS($name);
$database->setVillageName(
(int)$villages[$i]['wref'],
$name
);
}
}
}
header("Location: spieler.php?uid=".$uid);
exit;
}
/* ===================================================== */
/* ================= GP PACK =========================== */
/* ===================================================== */
private function gpack($post) {
global $database, $session;
$uid = (int)$session->uid;
if(isset($post['custom_url'])) {
$url = trim($post['custom_url']);
$url = $database->RemoveXSS($url);
$database->gpack($uid, $url);
}
header("Location: spieler.php?uid=".$uid);
exit;
}
/* ===================================================== */
/* ================= VACATION MODE ===================== */
/* ===================================================== */
private function setVacationMode($post){
global $database, $session, $form;
$days = isset($post['vac_days']) ? (int)$post['vac_days'] : 0;
if(isset($post['vac']) && $post['vac'] && $days >= 2 && $days <= 14){
unset($_SESSION['wid']);
$database->setvacmode((int)$session->uid, $days);
$database->activeModify($session->username, 1);
$database->UpdateOnline("logout");
$session->Logout();
header("Location: login.php");
exit;
}
$form->addError("vac", VAC_MODE_WRONG_DAYS);
header("Location: spieler.php?s=".$session->uid);
exit;
}
/* ===================================================== */
/* ================= UPDATE ACCOUNT ==================== */
/* ===================================================== */
private function updateAccount($post) {
global $database, $session, $form;
$uid = (int)$session->uid;
/* ---- PASSWORD CHANGE ---- */
if(!empty($post['pw1']) && !empty($post['pw2']) && !empty($post['pw3'])) {
if($post['pw2'] === $post['pw3']) {
if($database->login($session->username, $post['pw1'])) {
$hash = password_hash($post['pw2'], PASSWORD_BCRYPT, array('cost' => 12));
$database->updateUserField($uid, "password", $hash, 1);
} else {
$form->addError("pw", LOGIN_PW_ERROR);
}
} else {
$form->addError("pw", PASS_MISMATCH);
}
}
/* ---- EMAIL CHANGE ---- */
if(!empty($post['email_alt']) && !empty($post['email_neu'])) {
$newEmail = filter_var($post['email_neu'], FILTER_VALIDATE_EMAIL);
if($post['email_alt'] === $session->userinfo['email'] && $newEmail) {
$database->updateUserField($uid, "email", $newEmail, 1);
} else {
$form->addError("email", EMAIL_ERROR);
}
}
/* ---- ACCOUNT DELETE ---- */
if(!empty($post['del_pw']) && !empty($post['del'])) {
if(password_verify($post['del_pw'], $session->userinfo['password'])) {
$database->setDeleting($uid, 0);
} else {
$form->addError("del", PASS_MISMATCH);
}
}
/* ---- SITTER ADD ---- */
if(!empty($post['v1'])) {
$sitID = (int)$database->getUserField($post['v1'], "id", 1);
if($sitID > 0 && $sitID !== $uid) {
if($sitID == $session->userinfo['sit1'] ||
$sitID == $session->userinfo['sit2']) {
$form->addError("sit", SIT_ERROR);
} else {
if((int)$session->userinfo['sit1'] === 0) {
$database->updateUserField($uid, "sit1", $sitID, 1);
} elseif((int)$session->userinfo['sit2'] === 0) {
$database->updateUserField($uid, "sit2", $sitID, 1);
}
}
}
}
if($form->returnErrors() > 0) {
$_SESSION['errorarray'] = $form->getErrors();
$_SESSION['valuearray'] = $_POST;
}
header("Location: spieler.php?s=3");
exit;
}
/* ===================================================== */
/* ================= REMOVE SITTER ===================== */
/* ===================================================== */
private function removeSitter($get) {
global $database, $session;
$type = isset($get['type']) ? (int)$get['type'] : 0;
$id = isset($get['id']) ? (int)$get['id'] : 0;
if(isset($get['a']) && $get['a'] == $session->checker) {
if((int)$session->userinfo['sit'.$type] === $id) {
$database->updateUserField($session->uid, "sit".$type, 0, 1);
}
$session->changeChecker();
}
header("Location: spieler.php?s=".(int)$get['s']);
exit;
}
private function cancelDeleting($get) {
global $database, $session;
$database->setDeleting((int)$session->uid, 1);
header("Location: spieler.php?s=".(int)$get['s']);
exit;
}
private function removeMeSit($get) {
global $database, $session;
if(isset($get['a']) && $get['a'] == $session->checker) {
$database->removeMeSit((int)$get['id'], (int)$session->uid);
$session->changeChecker();
}
header("Location: spieler.php?s=".(int)$get['s']);
exit;
}
}
$profile = new Profile;
?>
+89 -14
View File
@@ -5,22 +5,97 @@
## Filename Protection.php ##
## Developed by: SlimShady ##
## Edited by: Dzoki & Dixie ##
## Enterprise hardening by Shadow ##
## License: TravianZ Project ##
## Copyright: TravianZ (c) 2010-2025. All rights reserved. ##
## ##
#################################################################################
//heef npc uitzondering omdat die met speciaal $_post werken
if(isset($_POST)){
if(!isset($_POST['ft'])){
//$_POST = @array_map('mysqli_real_escape_string', $_POST);
$_POST = array_map('htmlspecialchars', $_POST);
}
/*
|--------------------------------------------------------------------------
| Enterprise Superglobal Sanitizer
|--------------------------------------------------------------------------
| - Does NOT corrupt numeric values
| - Recursive array support
| - Keeps rsargs intact
| - Does not break AJAX
| - Does not break NPC
| - Prevents XSS vectors
|--------------------------------------------------------------------------
*/
if(!function_exists('secure_input_recursive')) {
function secure_input_recursive($data) {
if(is_array($data)) {
$clean = array();
foreach($data as $key => $value) {
$clean[$key] = secure_input_recursive($value);
}
return $clean;
}
if(is_numeric($data)) {
return $data;
}
if(is_string($data)) {
// remove null bytes
$data = str_replace("\0", '', $data);
// trim whitespace
$data = trim($data);
// basic XSS protection
$data = htmlspecialchars($data, ENT_QUOTES, 'UTF-8');
return $data;
}
return $data;
}
}
/*
|--------------------------------------------------------------------------
| Preserve rsargs (used by SAJAX)
|--------------------------------------------------------------------------
*/
$rsargs_backup = null;
if(isset($_GET['rsargs'])) {
$rsargs_backup = $_GET['rsargs'];
}
/*
|--------------------------------------------------------------------------
| Sanitize superglobals safely
|--------------------------------------------------------------------------
*/
if(!empty($_POST)) {
$_POST = secure_input_recursive($_POST);
}
if(!empty($_GET)) {
$_GET = secure_input_recursive($_GET);
}
if(!empty($_COOKIE)) {
$_COOKIE = secure_input_recursive($_COOKIE);
}
/*
|--------------------------------------------------------------------------
| Restore rsargs if needed
|--------------------------------------------------------------------------
*/
if($rsargs_backup !== null) {
$_GET['rsargs'] = $rsargs_backup;
}
$rsargs=$_GET['rsargs'];
//$_GET = array_map('mysqli_real_escape_string', $_GET);
$_GET = array_map('htmlspecialchars', $_GET);
$_GET['rsargs']=$rsargs;
//$_COOKIE = array_map('mysqli_real_escape_string', $_COOKIE);
$_COOKIE = array_map('htmlspecialchars', $_COOKIE);
?>
+651 -557
View File
File diff suppressed because it is too large Load Diff
+411 -295
View File
@@ -8,26 +8,25 @@ mb_internal_encoding("UTF-8"); // Add for utf8 varriables.
## -= YOU MAY NOT REMOVE OR CHANGE THIS NOTICE =- ##
## --------------------------------------------------------------------------- ##
## Project: TravianZ ##
## Version: 22.06.2015 ##
## Version: 22.06.2015 ##
## Filename Session.php ##
## Developed by: Mr.php , Advocaite , brainiacX , yi12345 , Shadow , ronix ##
## Fixed by: Shadow - STARVATION , HERO FIXED COMPL. ##
## Fixed by: InCube - double troops ##
## Fixed by: Shadow - STARVATION , HERO FIXED COMPL. ##
## Fixed by: InCube - double troops ##
## Refactored TravianZ Enterprise Hardened Core by Shadow ##
## License: TravianZ Project ##
## Copyright: TravianZ (c) 2010-2015. All rights reserved. ##
## URLs: http://travian.shadowss.ro ##
## Source code: https://github.com/Shadowss/TravianZ ##
## URLs: http://travian.shadowss.ro ##
## Source code: https://github.com/Shadowss/TravianZ ##
## ##
#################################################################################
global $autoprefix;
// go max 5 levels up - we don't have folders that go deeper than that
$autoprefix = '';
for ($i = 0; $i < 5; $i++) {
$autoprefix = str_repeat('../', $i);
if (file_exists($autoprefix.'autoloader.php')) {
// we have our path, let's leave
break;
}
}
@@ -38,6 +37,7 @@ if(!file_exists($autoprefix.'GameEngine/config.php')) {
}
$script_name = ($_SERVER['REQUEST_URI'] == 'karte.php') ? 'karte' : $_SERVER['REQUEST_URI'];
include_once ("Battle.php");
include_once ("Data/buidata.php");
include_once ("Data/cp.php");
@@ -60,324 +60,440 @@ include_once ("Profile.php");
class Session {
private $time;
var $logged_in = false;
var $referrer, $url;
var $username, $uid, $access, $plus, $tribe, $isAdmin, $alliance, $gold, $oldrank, $gpack, $goldclub;
var $bonus = 0;
var $bonus1 = 0;
var $bonus2 = 0;
var $bonus3 = 0;
var $bonus4 = 0;
var $timer = 0;
var $sharedForums = [];
var $checker, $mchecker;
public $userinfo = [];
private $userarray = [];
var $villages = [];
private $time;
var $logged_in = false;
var $referrer, $url;
var $username, $uid, $access, $plus, $tribe, $isAdmin, $alliance, $gold, $oldrank, $gpack, $goldclub;
var $bonus = 0;
var $bonus1 = 0;
var $bonus2 = 0;
var $bonus3 = 0;
var $bonus4 = 0;
var $timer = 0;
var $sharedForums = array();
var $checker, $mchecker;
public $userinfo = array();
private $userarray = array();
var $villages = array();
function __construct() {
global $database; //TienTN fix
function __construct() {
global $database;
$this->time = time();
if (!isset($_SESSION)) {
session_start();
}
$this->time = time();
$this->logged_in = $this->checkLogin();
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
if($this->logged_in && TRACK_USR) $database->updateActiveUser($this->username, $this->time);
if(isset($_SESSION['url'])) $this->referrer = $_SESSION['url'];
else $this->referrer = "/";
$this->url = $_SESSION['url'] = $_SERVER['PHP_SELF'];
$this->SurfControl();
}
session_regenerate_id(true); // 🔒 Session fixation protection
public function Login($user) {
global $database, $generator, $logging;
$this->logged_in = true;
$_SESSION['sessid'] = $generator->generateRandID();
$_SESSION['username'] = $user;
$user_sanitized = $database->escape($user);
$_SESSION['checker'] = $generator->generateRandStr(3);
$_SESSION['mchecker'] = $generator->generateRandStr(5);
$this->logged_in = $this->checkLogin();
$userFields = $database->getUserFields($user_sanitized, "quest, id", 1, true);
$_SESSION['qst'] = $userFields["quest"];
if($this->logged_in && TRACK_USR) {
$database->updateActiveUser($this->username, $this->time);
}
$dbarray = $database->getUserFields($user_sanitized, 'id, village_select', 1);
$selected_village=(int) $dbarray['village_select'];
$this->referrer = isset($_SESSION['url']) ? $_SESSION['url'] : "/";
$this->url = $_SESSION['url'] = $_SERVER['PHP_SELF'];
if ($dbarray['id'] > 1) {
if(!isset($_SESSION['wid'])) {
if(!empty($selected_village)) $data = $database->getVillage($selected_village);
else $data = $database->getVillage($userFields["id"]);
$_SESSION['wid'] = $data['wref'];
} else
if(empty($_SESSION['wid'])) {
if(!empty($selected_village)) $data = $database->getVillage($selected_village);
else $data = $database->getVillage($userFields["id"]);
$_SESSION['wid'] = $data['wref'];
}
$this->PopulateVar();
$this->SurfControl();
}
public function Login($user) {
global $database, $generator, $logging;
$database->updateActiveUser($user_sanitized, $this->time);
$database->updateUserField($user_sanitized, "sessid", $_SESSION['sessid'], 0);
}
if(empty($user)) {
header("Location: login.php");
exit;
}
$logging->addLoginLog($dbarray['id'], $_SERVER['REMOTE_ADDR']);
$this->logged_in = true;
if ($dbarray['id'] == 1) {
header("Location: nachrichten.php");
exit;
} else {
header("Location: dorf1.php");
exit;
}
}
$_SESSION['sessid'] = $generator->generateRandID();
$_SESSION['username'] = $user;
$_SESSION['checker'] = $generator->generateRandStr(3);
$_SESSION['mchecker'] = $generator->generateRandStr(5);
public function Logout() {
global $database;
$this->logged_in = false;
$database->updateUserField($_SESSION['username'], "sessid", "", 0);
if(ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000, $params["path"], $params["domain"], $params["secure"], $params["httponly"]);
}
session_destroy();
session_start();
}
// 🔒 Prepared statement (critical zone)
$stmt = $database->dblink->prepare(
"SELECT id, quest, village_select FROM " . TB_PREFIX . "users WHERE username = ? LIMIT 1"
);
$stmt->bind_param("s", $user);
$stmt->execute();
$result = $stmt->get_result();
$dbarray = $result->fetch_assoc();
$stmt->close();
public function changeChecker() {
global $generator;
$this->checker = $_SESSION['checker'] = $generator->generateRandStr(3);
$this->mchecker = $_SESSION['mchecker'] = $generator->generateRandStr(5);
}
if(!$dbarray) {
$this->Logout();
header("Location: login.php");
exit;
}
private function checkLogin(){
global $database;
$user = $id = '';
$admin = false;
$inAdmin = (strpos($_SERVER['REQUEST_URI'], '/Admin') !== false);
$_SESSION['id_user'] = (int)$dbarray['id'];
$_SESSION['qst'] = $dbarray['quest'];
if (!$inAdmin && isset($_SESSION['username'])) {
$user = $_SESSION['username'];
$id = (int) $_SESSION['id_user'];
} else if ($inAdmin && isset($_SESSION['admin_username'])) {
$user = $_SESSION['admin_username'];
$id = (int) $_SESSION['id'];
$admin = true;
}
$selected_village = (int)$dbarray['village_select'];
if($user && ($admin || isset($_SESSION['sessid']))) {
$this->maintenance();
$this->isWinner();
// check if this is not a support user, for who only messages and statistics are available
if ($user == 'Support') {
$req_file = basename($_SERVER['PHP_SELF']);
if (!in_array($req_file, ['nachrichten.php', 'logout.php', 'statistiken.php', 'rules.php', 'karte.php', 'karte2.php', 'spieler.php'])) {
header('Location: nachrichten.php');
exit;
}
}
if(!isset($_SESSION['wid']) || empty($_SESSION['wid'])) {
//Get and Populate Data
$this->PopulateVar();
//Check if the player is banned
$this->isBanned();
//update database
$database->updateActiveUser($user, $this->time);
return true;
}
else return false;
}
if(!empty($selected_village)) {
$data = $database->getVillage($selected_village);
} else {
$data = $database->getVillage($dbarray['id']);
}
/**
* Called if the player is banned
*
*/
function isBanned(){
if($this->access == BANNED && !in_array(basename($_SERVER['PHP_SELF']), ['banned.php', 'nachrichten.php', 'rules.php'])){
header('Location: banned.php');
exit;
}
}
/**
* Called when the server is under maintenance
*
*/
function maintenance(){
if($_SESSION['ok'] == 2 && basename($_SERVER['PHP_SELF']) != 'maintenance.php'){
header('Location: maintenance.php');
exit;
}
}
/**
* Called when there's a player who built a WW to level 100
*
*/
function isWinner(){
global $database;
$requiredPage = basename($_SERVER['PHP_SELF']);
if($database->isThereAWinner() && (in_array($requiredPage, ['build.php', 'plus1.php']) ||
(in_array($requiredPage, ['plus.php']) && isset($_GET['id']) && !empty($_GET['id'] && $_GET['id'] >= 7))))
{
header('Location: winner.php');
exit;
}
}
/**
* Function to check Real Hero
* Made by: Shadow and brainiacX
*
*/
if(isset($data['wref'])) {
$_SESSION['wid'] = (int)$data['wref'];
}
}
function CheckHeroReal () {
global $database,$link;
$this->PopulateVar();
$villageIDs = implode(', ', $this->villages);
if (!count($this->villages)) {
$this->Logout();
header('login.php');
exit;
}
$database->updateActiveUser($user, $this->time);
$database->updateUserField($user, "sessid", $_SESSION['sessid'], 0);
// check if hero unit for this player is present anywhere on the map
$q = '
SELECT
IFNULL((SELECT SUM(hero) from '.TB_PREFIX.'enforcement where `from` IN('.$villageIDs.')), 0) +
IFNULL((SELECT SUM(hero) from '.TB_PREFIX.'units where `vref` IN('.$villageIDs.')), 0) +
IFNULL((SELECT SUM(t11) from '.TB_PREFIX.'prisoners where `from` IN('.$villageIDs.')), 0) +
IFNULL((SELECT SUM(t11) FROM '.TB_PREFIX.'movement, '.TB_PREFIX.'attacks WHERE '.TB_PREFIX.'movement.`from` IN('.$villageIDs.') and '.TB_PREFIX.'movement.ref = '.TB_PREFIX.'attacks.id and '.TB_PREFIX.'movement.proc = 0 and '.TB_PREFIX.'movement.sort_type = 3), 0) +
IFNULL((SELECT SUM(t11) FROM '.TB_PREFIX.'movement, '.TB_PREFIX.'attacks where '.TB_PREFIX.'movement.`to` IN('.$villageIDs.') and '.TB_PREFIX.'movement.ref = '.TB_PREFIX.'attacks.id and '.TB_PREFIX.'movement.proc = 0 and '.TB_PREFIX.'movement.sort_type = 4), 0)
as herocount';
$heroUnitRegisters = mysqli_fetch_array( mysqli_query($database->dblink, $q, MYSQLI_ASSOC ))['herocount'];
$logging->addLoginLog($dbarray['id'], $_SERVER['REMOTE_ADDR']);
// check if the actual hero is alive or being trained/revived into a living state
$isHeroLivingOrRaising = $database->getHeroDeadReviveOrInTraining($this->uid);
if ($dbarray['id'] == 1) {
header("Location: nachrichten.php");
} else {
header("Location: dorf1.php");
}
exit;
}
// if he doesn't register anywhere on the map but is marked as alive,
// we need to kill him
if(!$heroUnitRegisters && $isHeroLivingOrRaising) {
$database->KillMyHero($this->uid);
public function Logout() {
global $database;
$this->logged_in = false;
if(isset($_SESSION['username'])) {
$database->updateUserField($_SESSION['username'], "sessid", "", 0);
}
$_SESSION = array();
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"],
$params["domain"],
$params["secure"],
$params["httponly"]
);
}
session_destroy();
session_start();
}
public function changeChecker() {
global $generator;
$this->checker = $_SESSION['checker'] = $generator->generateRandStr(3);
$this->mchecker = $_SESSION['mchecker'] = $generator->generateRandStr(5);
}
private function checkLogin() {
global $database;
$user = '';
$id = 0;
$admin = false;
$inAdmin = (strpos($_SERVER['REQUEST_URI'], '/Admin') !== false);
if (!$inAdmin && isset($_SESSION['username'])) {
$user = $_SESSION['username'];
$id = isset($_SESSION['id_user']) ? (int)$_SESSION['id_user'] : 0;
}
else if ($inAdmin && isset($_SESSION['admin_username'])) {
$user = $_SESSION['admin_username'];
$id = isset($_SESSION['id']) ? (int)$_SESSION['id'] : 0;
$admin = true;
}
if ($user && ($admin || isset($_SESSION['sessid']))) {
$this->maintenance();
$this->isWinner();
// 🔒 Support restriction hardening
if ($user === 'Support') {
$req_file = basename($_SERVER['PHP_SELF']);
$allowed = array(
'nachrichten.php',
'logout.php',
'statistiken.php',
'rules.php',
'karte.php',
'karte2.php',
'spieler.php'
);
if (!in_array($req_file, $allowed)) {
header('Location: nachrichten.php');
exit;
}
}
private function PopulateVar() {
global $database;
$this->userarray = $this->userinfo = $database->getUserArray($_SESSION['username'], 0);
$this->username = $this->userarray['username'];
$this->uid = $_SESSION['id_user'] = $this->userarray['id'];
$this->gpack = $this->userarray['gpack'];
$this->access = $this->userarray['access'];
$this->plus = ($this->userarray['plus'] > $this->time);
$this->goldclub = $this->userarray['goldclub'];
$this->villages = $database->getVillagesID($this->uid);
$this->tribe = $this->userarray['tribe'];
$this->isAdmin = $this->access >= MODERATOR;
$this->alliance = $_SESSION['alliance_user'] = $this->userarray['alliance'];
$this->checker = $_SESSION['checker'];
$this->mchecker = $_SESSION['mchecker'];
$this->sit = $database->GetOnline($this->uid);
$this->sit1 = $this->userarray['sit1'];
$this->sit2 = $this->userarray['sit2'];
$this->cp = floor($this->userarray['cp']);
$this->gold = $this->userarray['gold'];
$this->oldrank = $this->userarray['oldrank'];
$this->sharedForums = $database->getSharedForums($this->uid, $this->alliance);
$_SESSION['ok'] = $this->userarray['ok'];
if($this->userarray['b1'] > $this->time) $this->bonus1 = 1;
if($this->userarray['b2'] > $this->time) $this->bonus2 = 1;
if($this->userarray['b3'] > $this->time) $this->bonus3 = 1;
if($this->userarray['b4'] > $this->time) $this->bonus4 = 1;
// Populate user data
$this->PopulateVar();
if (!in_array($this->username, ['Support', 'Multihunter'])) $this->CheckHeroReal();
}
/**
* Creates an array with the vrefs of attacked/scouted/reinforced villages and oasis
*
*/
public function populateAttacks(){
global $database, $village;
$troopsMovement = $database->getMovement(3, $village->wid, 0);
if(count($troopsMovement) > 0){
foreach($troopsMovement as $movement)
{
switch($movement['attack_type']){
case 1:
$_SESSION['troops_movement']['scouts'][] = $movement['to'];
break;
case 2:
$_SESSION['troops_movement']['enforcements'][] = $movement['to'];
break;
case 3:
case 4:
$_SESSION['troops_movement']['attacks'][] = $movement['to'];
break;
}
}
}
}
private function SurfControl(){
if(SERVER_WEB_ROOT) {
$page = $_SERVER['SCRIPT_NAME'];
} else {
$explode = explode("/", $_SERVER['SCRIPT_NAME']);
$i = count($explode) - 1;
$page = $explode[$i];
// Ban check
$this->isBanned();
}
$pagearray = array("index.php", "anleitung.php", "tutorial.php", "login.php", "activate.php", "anmelden.php", "xaccount.php");
if(!$this->logged_in) {
if(!in_array($page, $pagearray) || $page == "logout.php") {
header("Location: login.php");
exit;
}
} else {
if(in_array($page, $pagearray)) {
if ($this->uid == 1) {
header("Location: nachrichten.php");
exit;
} else {
header("Location: dorf1.php");
exit;
}
}
$database->updateActiveUser($user, $this->time);
}
}
};
$session = new Session;
$form = new Form;
return true;
}
// if there is no user, we'd try to load messages for user with ID 0, which is wrong
if (!empty($_SESSION['id_user'])) {
$message = new Message;
return false;
}
// create a global user variable which will later be removed from here
// and created + retrieved either via Service Locator or other DI concept
$user = new User((int) $_SESSION['id_user'], $database);
/**
* Ban control
*/
function isBanned() {
$current = basename($_SERVER['PHP_SELF']);
if ($this->access == BANNED &&
!in_array($current, array('banned.php','nachrichten.php','rules.php'))) {
header('Location: banned.php');
exit;
}
}
/**
* Maintenance control
*/
function maintenance() {
$current = basename($_SERVER['PHP_SELF']);
if (isset($_SESSION['ok']) &&
$_SESSION['ok'] == 2 &&
$current != 'maintenance.php') {
header('Location: maintenance.php');
exit;
}
}
/**
* Winner check (WW level 100)
*/
function isWinner() {
global $database;
$requiredPage = basename($_SERVER['PHP_SELF']);
if ($database->isThereAWinner()) {
$restricted = array('build.php', 'plus1.php');
if (in_array($requiredPage, $restricted) ||
($requiredPage == 'plus.php' &&
isset($_GET['id']) &&
is_numeric($_GET['id']) &&
(int)$_GET['id'] >= 7)) {
header('Location: winner.php');
exit;
}
}
}
/**
* Hero integrity verification
* (Enterprise hardened logic 1:1)
*/
function CheckHeroReal() {
global $database;
if (!is_array($this->villages) || !count($this->villages)) {
$this->Logout();
header('Location: login.php');
exit;
}
// 🔒 sanitize village IDs (critical SQL protection)
$safeVillageIDs = array();
foreach ($this->villages as $v) {
$safeVillageIDs[] = (int)$v;
}
$villageIDs = implode(',', $safeVillageIDs);
$q = "
SELECT
IFNULL((SELECT SUM(hero) FROM ".TB_PREFIX."enforcement WHERE `from` IN($villageIDs)),0) +
IFNULL((SELECT SUM(hero) FROM ".TB_PREFIX."units WHERE `vref` IN($villageIDs)),0) +
IFNULL((SELECT SUM(t11) FROM ".TB_PREFIX."prisoners WHERE `from` IN($villageIDs)),0) +
IFNULL((SELECT SUM(t11) FROM ".TB_PREFIX."movement m
JOIN ".TB_PREFIX."attacks a ON m.ref = a.id
WHERE m.`from` IN($villageIDs)
AND m.proc = 0 AND m.sort_type = 3),0) +
IFNULL((SELECT SUM(t11) FROM ".TB_PREFIX."movement m
JOIN ".TB_PREFIX."attacks a ON m.ref = a.id
WHERE m.`to` IN($villageIDs)
AND m.proc = 0 AND m.sort_type = 4),0)
AS herocount
";
$res = mysqli_query($database->dblink, $q);
$row = mysqli_fetch_assoc($res);
$heroUnitRegisters = isset($row['herocount']) ? (int)$row['herocount'] : 0;
$isHeroLivingOrRaising = $database->getHeroDeadReviveOrInTraining($this->uid);
if (!$heroUnitRegisters && $isHeroLivingOrRaising) {
$database->KillMyHero($this->uid);
}
}
/**
* Populate session variables (NO LOGIC CHANGE)
*/
private function PopulateVar() {
global $database;
$this->userarray = $this->userinfo =
$database->getUserArray($_SESSION['username'], 0);
if (!is_array($this->userarray)) {
$this->Logout();
header('Location: login.php');
exit;
}
$this->username = $this->userarray['username'];
$this->uid = $_SESSION['id_user'] = (int)$this->userarray['id'];
$this->gpack = $this->userarray['gpack'];
$this->access = (int)$this->userarray['access'];
$this->plus = ($this->userarray['plus'] > $this->time);
$this->goldclub = (int)$this->userarray['goldclub'];
$this->tribe = (int)$this->userarray['tribe'];
$this->isAdmin = ($this->access >= MODERATOR);
$this->alliance = $_SESSION['alliance_user'] = (int)$this->userarray['alliance'];
$this->checker = $_SESSION['checker'];
$this->mchecker = $_SESSION['mchecker'];
$this->villages = $database->getVillagesID($this->uid);
$this->sit = $database->GetOnline($this->uid);
$this->sit1 = (int)$this->userarray['sit1'];
$this->sit2 = (int)$this->userarray['sit2'];
$this->cp = floor($this->userarray['cp']);
$this->gold = (int)$this->userarray['gold'];
$this->oldrank = (int)$this->userarray['oldrank'];
$this->sharedForums = $database->getSharedForums($this->uid, $this->alliance);
$_SESSION['ok'] = $this->userarray['ok'];
// bonuses
if ($this->userarray['b1'] > $this->time) $this->bonus1 = 1;
if ($this->userarray['b2'] > $this->time) $this->bonus2 = 1;
if ($this->userarray['b3'] > $this->time) $this->bonus3 = 1;
if ($this->userarray['b4'] > $this->time) $this->bonus4 = 1;
if (!in_array($this->username, array('Support','Multihunter'))) {
$this->CheckHeroReal();
}
}
/**
* Populate attack indicators
*/
public function populateAttacks() {
global $database, $village;
$_SESSION['troops_movement'] = array(
'scouts' => array(),
'enforcements' => array(),
'attacks' => array()
);
$troopsMovement = $database->getMovement(3, $village->wid, 0);
if (is_array($troopsMovement) && count($troopsMovement) > 0) {
foreach ($troopsMovement as $movement) {
switch ((int)$movement['attack_type']) {
case 1:
$_SESSION['troops_movement']['scouts'][] = $movement['to'];
break;
case 2:
$_SESSION['troops_movement']['enforcements'][] = $movement['to'];
break;
case 3:
case 4:
$_SESSION['troops_movement']['attacks'][] = $movement['to'];
break;
}
}
}
}
/**
* Page access control
* Enterprise hardened logic 1:1
*/
private function SurfControl() {
if (SERVER_WEB_ROOT) {
$page = basename($_SERVER['SCRIPT_NAME']);
} else {
$explode = explode("/", $_SERVER['SCRIPT_NAME']);
$page = end($explode);
}
$allowedWithoutLogin = array(
"index.php",
"anleitung.php",
"tutorial.php",
"login.php",
"activate.php",
"anmelden.php",
"xaccount.php"
);
if (!$this->logged_in) {
if (!in_array($page, $allowedWithoutLogin) || $page == "logout.php") {
header("Location: login.php");
exit;
}
} else {
if (in_array($page, $allowedWithoutLogin)) {
if ($this->uid == 1) {
header("Location: nachrichten.php");
} else {
header("Location: dorf1.php");
}
exit;
}
}
}
} // END CLASS
$session = new Session();
$form = new Form();
/**
* Message + User init
* Enterprise safe instantiation
*/
if (!empty($_SESSION['id_user']) && is_numeric($_SESSION['id_user'])) {
$message = new Message();
// Safe casting
$user = new User((int)$_SESSION['id_user'], $database);
}
?>
+961 -546
View File
File diff suppressed because it is too large Load Diff
+16 -6
View File
@@ -8,12 +8,22 @@
## Copyright: TravianZ (c) 2010-2025. All rights reserved. ##
## ##
#################################################################################
// Send proper 404 header if not already sent
if (!headers_sent()) {
header("HTTP/1.1 404 Not Found");
header("Content-Type: text/html; charset=UTF-8");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Pragma: no-cache");
}
?>
<div style="margin-top: 50px;">
<div style="text-align: center">
<h1>404 - File not found</h1>
<img src="../../gpack/travian_default/img/misc/404.gif" title="Not Found" alt="Not Found"><br />
<p>We looked 404 times already but can't find anything, Not even an X marking the spot.</p>
<p>This system is not complete yet. So the page probably does not exist.</p><br>
</div>
<div style="text-align: center">
<h1>404 - File not found</h1>
<img src="../../gpack/travian_default/img/misc/404.gif"
title="Not Found"
alt="Not Found"><br />
<p>We looked 404 times already but can't find anything, Not even an X marking the spot.</p>
<p>This system is not complete yet. So the page probably does not exist.</p><br>
</div>
</div>