• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

GESIOR 2012 - ideas, bug reports

- Added outfit images in highscores.php, whoisonline.php and characters.php
- small change in flag detection (when can't detect country it set it to 'unknown', not '', as file '.png' on linux is not 'png' and server returns it with wrong mime type)
- Added new options in config.php that let you reduce your servers transfer:
PHP:
// OUTFIT IMAGES
$config['site']['outfit_images_url'] = 'http://outfit-images.ots.me/outfit.php';

// ITEM IMAGES
$config['site']['item_images_url'] = 'http://item-images.ots.me/960/';
$config['site']['item_images_extension'] = '.gif';

// FLAG IMAGES
$config['site']['flag_images_url'] = 'http://flag-images.ots.me/';
$config['site']['flag_images_extension'] = '.png';

I will update it on github tommorow and upload outfit images generator code (optimized script from forum, as there are ~52.000.000.000 possible outfits and colors combinations it must be generator, can't generate it all and keep on some hosting [~104 TB xD ])
 
Last edited:
Hello Use one webserver and another dedicaded server to run my TFS. How do Install your website if the server path is on another server. Can you tel me how to pass by that?
 
Hello Use one webserver and another dedicaded server to run my TFS. How do Install your website if the server path is on another server. Can you tel me how to pass by that?
Make copy of server files (not all, only 'config.lua' and folder 'data/XML/') to web server (of course to folder that people from internet can't view) and set path to that folder as path to server.

EDIT:
- If database is on dedic with ots and you connect to database on 'localhost' or '127.0.0.1' you must edit config.lua on web server and set database IP to dedic IP.
- You should also read how to make mysql works as internet server (by default it run as localhost server on IP 127.0.0.1).
- You should check what is password to root (or change it) in phpmyadmin for user from IP [Host] '%' if there is not root user with Host '%' then you must add it to login from web server to mysql on dedic.
- You can also have a problem with webhost anti-hack protection which will not let you connect to mysql on other host or limit number of connections (I tried it on ovh.com webhosting [+my dedic] and they got limit of 1 connection to 3306 port per 45 seconds). I had to change port of my mysql server from 3306 to other (for example 3307) [and edit config.lua on dedic and on webhost]

Config of mysql on linux is in:
/etc/mysql/my.ini
(edit as text file)

EDIT 2:
In 2 days I will make version for TFS 0.2 [just remove not working things from 0.3 version] and reupload all to github (with branches this time).
 
Last edited:
system/load.page.php
PHP:
<?php
if(!defined('INITIALIZED'))
	exit;

ob_start();
$main_content = '';
include("pages/" . $subtopic . ".php");
$main_content .= ob_get_clean();
If anyone make script for new account maker, he can use 'echo' in place of '$main_content .=', but in layouts you must still put in right place 'echo $main_content;'. I want keep it compatible with old scripts/layouts.

'sellchar.php' code for Gesior 2012:
PHP:
<?PHP 
################################################# 
### Scripted by PhoOwned                      ### 
### All rights reserverd                      ### 
### Do not use/distribute without permission! ### 
### Contact: [email protected]                   ### 
###          [email protected]               ### 
################################################# 
/* 
In MySQL: 
CREATE TABLE `characters_auctions` ( 
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY , 
`state` TINYINT( 1 ) NOT NULL DEFAULT '0' , 
`finish_time` INT NOT NULL , 
`char_id` INT NOT NULL , 
`buy_now` INT NOT NULL , 
`bid` INT NOT NULL , 
`bidder` INT NOT NULL , 
INDEX ( `finish_time` )); 
*/ 
$add_character_page_access = 3; 
$auctions_default_time = 3 * 24;// auction item in hours 
// styles and scripts 
$main_content .= '  
    <style type="text/css"> 
    .tableFonts {color: #FFFFFF}
    .tableRow0 {background-color: #F1E0C6;text-align: left;vertical-align: middle;font-size: 12pt}
    .tableRow1 {background-color: #D4C0A1;text-align: left;vertical-align: middle;font-size: 12pt}
    .tableRowSmall0 {background-color: #F1E0C6;text-align: left;vertical-align: middle;font-size: 10pt}
    .tableRowSmall1 {background-color: #D4C0A1;text-align: left;vertical-align: middle;font-size: 10pt}
    .linkButton {font-size: 14pt;padding: 6px;text-shadow: 2mm 2mm 2mm #342423;letter-spacing: 2mm} 
    .linkButton:hover {font-size: 16pt;} 
    .bigText {font-size: 24pt} 
    .normalText {font-size: 12pt;} 
    .showItemSquare {height: 49px;width: 39px;padding: 7px;} 
    .showItemImage {height: 40px;width: 40px;padding: 0px;} 
    input {text-align: right;} 
     
    .er{display:block} 
    .er *{ 
      display:block; 
      height:1px; 
      overflow:hidden; 
      font-size:.01em; 
      background:#b20000} 
    .er1{ 
      margin-left:3px; 
      margin-right:3px; 
      padding-left:1px; 
      padding-right:1px; 
      border-left:1px solid #870000; 
      border-right:1px solid #870000; 
      background:#9f0000} 
    .er2{ 
      margin-left:1px; 
      margin-right:1px; 
      padding-right:1px; 
      padding-left:1px; 
      border-left:1px solid #6f0000; 
      border-right:1px solid #6f0000; 
      background:#a30000} 
    .er3{ 
      margin-left:1px; 
      margin-right:1px; 
      border-left:1px solid #a30000; 
      border-right:1px solid #a30000;} 
    .er4{ 
      border-left:1px solid #870000; 
      border-right:1px solid #870000} 
    .er5{ 
      border-left:1px solid #9f0000; 
      border-right:1px solid #9f0000} 
    .erfg{ 
      background:#b20000;font-size: 16pt;text-align: center} 
    </style> 
    <script type="text/javascript"> 
        function checkLogin(account_id) { 
        if(account_id == 0) 
        { 
        alert ("You are not logged in."); 
        return false 
        } 
        return true 
        } 
         
        function checkBid(account_id, bidder_id, user_points, bid_now) { 
        if(!checkLogin(account_id)) 
        return false 
        var bid = window.document.getElementById("bid").value; 
        if(bid <= bid_now) 
        { 
            alert ("Current highest bid is " + bid_now + ". You can not bid " + bid + "."); 
            return false 
        } 
        if(bid > user_points) 
        { 
            alert ("You can not bid " + bid + ". You have only " + user_points + "."); 
            return false 
        } 
        if(account_id == bidder_id) 
        { 
        var answer = confirm ("You have highest bid in this auction. Are you sure you want make higher bid?") 
        if (answer) 
        return true 
        else 
        return false 
        } 
        return true 
        } 
         
        function checkBuyNow(account_id, user_points, buy_now) { 
        if(!checkLogin(account_id)) 
        return false 
        if(user_points < buy_now) 
        { 
            alert ("This character cost " + buy_now + ". You have only " + user_points + "."); 
            return false 
        } 
        var answer = confirm ("This character cost " + buy_now + ". Do you want to buy it?") 
        if (answer) 
        return true 
        else 
        return false 
        } 
         
        var innerHTML; 
        function countdown(Time_Left, target_id) 
        { 
        if(Time_Left <= 0) 
        { 
            document.getElementById(target_id).innerHTML = \'Finished\'; 
            return 0; 
        } 
        setTimeout(countdown, 1000, Time_Left-1, target_id); 
        //More datailed. 
        days = Math.floor(Time_Left / (60 * 60 * 24)); 
        Time_Left %= (60 * 60 * 24); 
        hours = Math.floor(Time_Left / (60 * 60)); 
        Time_Left %= (60 * 60); 
        minutes = Math.floor(Time_Left / 60); 
        Time_Left %= 60; 
        seconds = Time_Left; 

        dps = \'s\'; hps = \'s\'; mps = \'s\'; sps = \'s\'; 
        //ps is short for plural suffix. 
        if(days == 1) dps =\'\'; 
        if(hours == 1) hps =\'\'; 
        if(minutes == 1) mps =\'\'; 
        if(seconds == 1) sps =\'\'; 

        innerHTML = days + \' day\' + dps + \' \'; 
        innerHTML += hours + \' hour\' + hps + \' \'; 
        innerHTML += minutes + \' minute\' + mps + \' and \'; 
        innerHTML += seconds + \' second\' + sps; 

        document.getElementById(target_id).innerHTML = innerHTML; 
        } 
    </script>'; 
     
$errorFormStart = '<div><b class="er"><b class="er1"><b></b></b><b class="er2"><b></b></b><b class="er3"></b><b class="er4"></b><b class="er5"></b></b><div class="erfg">'; 
$errorFormEnd = '</div><b class="er"><b class="er5"></b><b class="er4"></b><b class="er3"></b><b class="er2"><b></b></b><b class="er1"><b></b></b></b></div>'; 
function time_left($integer) 
 {  
     if($integer <= 0) return "Finished"; 
     $seconds=$integer; 
     if ($seconds/60 >=1)  
     { 
         $minutes=floor($seconds/60); 
         if ($minutes/60 >= 1)  
         { # Hours  
             $hours=floor($minutes/60); 
             if ($hours/24 >= 1)  
             { #days  
                     $days=floor($hours/24); 
                     if ($days/7 >=1)  
                     { #weeks  
                         $weeks=floor($days/7); 
                         if ($weeks>=2) $return="$weeks weeks"; 
                         else $return="$weeks week"; 
                     } #end of weeks  
                     $days=$days-(floor($days/7))*7; 
                     if ($weeks>=1 && $days >=1) $return="$return, "; 
                     if ($days >=2) $return="$return $days d"; 
                     if ($days ==1) $return="$return $days d"; 
             } #end of days 
             $hours=$hours-(floor($hours/24))*24; 
             if ($days>=1 && $hours >=1) $return="$return, "; 
             if ($hours >=2 || $hours ==0) $return="$return $hours h"; 
             if ($hours ==1) $return="$return $hours h"; 
         } #end of Hours 
         $minutes=$minutes-(floor($minutes/60))*60; 
         if ($hours>=1 && $minutes >=1) $return="$return, "; 
         if ($minutes >=2 || $minutes ==0) $return="$return $minutes m"; 
         if ($minutes ==1) $return="$return $minutes m"; 
     } #end of minutes  
     $seconds=$integer-(floor($integer/60))*60; 
     if ($minutes>=1 && $seconds >=1) $return="$return, "; 
     if ($seconds >=2 || $seconds ==0) $return="$return $seconds sec"; 
     if ($seconds ==1) $return="$return $seconds sec"; 
     $return="$return."; 
     return $return; 
 } 
############ FINISH AUCTIONS AND ADD CHARACTERS ############ 
foreach($SQL->query('SELECT * FROM `characters_auctions` WHERE `state` = 0 AND `finish_time` <= ' . time())->fetchAll() as $finishedAuction) 
{ 
    if($finishedAuction['bidder'] > 0) 
    { 
        // if server show error in one of lines below it mean 
        // someone delete character or account that won auction 
        // admin must check it manualy (give points back to account that won auction?) 
        $finishedAuctionBidder = new Account($finishedAuction['bidder']);
        $finishedAuctionChar = new Player($finishedAuction['char_id']);
        $finishedAuctionChar->setAccount($finishedAuctionBidder); 
        $finishedAuctionChar->setGroup(1); 
        $finishedAuctionChar->save(); 
        $SQL->query('UPDATE `characters_auctions` SET `state` = 2 WHERE `id` = ' . $finishedAuction['id']); 
        //$SQL->query('INSERT INTO `bans` (`id` , `type` , `value` ,`param` ,`active` ,`expires` ,`added` ,`admin_id` ,`comment` ,`reason` ,`action` ,`statement`) VALUES (NULL , 2, ' .$auctionChar->getId() . ', 2, 1, -1, ' . time() . ', 1, \'BUY CHAR\', 0, 1, \'\');'); 
    } 
    else 
        $SQL->query('UPDATE `characters_auctions` SET `state` = 1 WHERE `id` = ' . $finishedAuction['id']); 
} 
############ VISIBLE THINGS ############ 
if($logged && $account_logged->getPageAccess() >= $add_character_page_access) 
    $main_content .= '<div class="normalText"><a rel="nofollow" href="?subtopic=sellchar&action=addauction">ADMIN PANEL: >ADD AUCTION<</a></div>'; 
if($action == "addauction") ############ ADD AUCTION / VIEW CHARACTERS LIST ############ 
{ 
    if($logged && $account_logged->getPageAccess() >= $add_character_page_access) 
    {
        $daysAgo = (int) $_REQUEST['days_ago']; 
        $nameContains = $_REQUEST['name_contains']; 
        $minLevel = (int) $_REQUEST['min_level']; 
        $maxLastLogout = time() - $daysAgo * 24 * 3600; 
        $orderBy = ($_REQUEST['order_by'] == 'lastlogout') ? $_REQUEST['order_by'] : 'level'; 
        $orderType = ($_REQUEST['order_type'] == 'DESC') ? $_REQUEST['order_type'] : 'ASC'; 
        $resultsLimit = (isset($_REQUEST['results_limit'])) ? (int) $_REQUEST['results_limit'] : 30; 
        if(isset($_REQUEST['id'])) 
        { 
            $id = (int) $_REQUEST['id']; 
            $priceAuction = (int) $_REQUEST['price_auction']; 
            $priceBuyNow = (int) $_REQUEST['price_buy_now']; 
            $auctionTime = (int) $_REQUEST['auction_time'] * 3600; 
            $SQL->query('INSERT INTO `characters_auctions` (`id` ,`finish_time` ,`char_id` ,`buy_now` ,`bid` ,`bidder`) VALUES (NULL , ' . (time() + $auctionTime) . ', ' . $id . ', ' . $priceBuyNow . ', ' . $priceAuction . ', 0);'); 
            $main_content .= $errorFormStart . 'Character with ID ' . $id . ' auction added.' . $errorFormEnd; 
        } 
        $charsAlreadyOnAuctions = array(0); 
        foreach($SQL->query('SELECT `char_id` FROM `characters_auctions` WHERE `state` = 0') as $charsAlreadyOnAuction) 
            $charsAlreadyOnAuctions[] = $charsAlreadyOnAuction['char_id']; 
        $main_content .= '<div class="bigText" style="text-align: center">Add Auction</div>'; 
        $main_content .= '<div class="normalText">If you leave Buy Now field empty or set it to 0 it will be not possible to buy character by option \'Buy Now\'.</div>'; 
        $main_content .= '<table class="tableFonts" style="margin-left: auto;margin-right: auto;">'; 
        $main_content .= '<tr style="background-color:'.$config['site']['vdarkborder'].'"><td colspan="8">CHARACTERS LIST</td></tr>'; 
        $main_content .= '<form action="" method="get"><input type="hidden" name="subtopic" value="sellchar" /><input type="hidden" name="action" value="addauction" />'; 
        $main_content .= '<tr style="background-color:'.$config['site']['vdarkborder'].'" style="font-size: 10pt;"><td colspan="2">ORDER BY</td><td><select name="order_by"><option' . (($orderBy == 'lastlogout') ? ' selected="selected"' : '') . '>lastlogout</option><option' . (($orderBy == 'level') ? ' selected="selected"' : '') . '>level</option></select></td><td><select name="order_type"><option' . (($orderType == 'ASC') ? ' selected="selected"' : '') . '>ASC</option><option' . (($orderType == 'DESC') ? ' selected="selected"' : '') . '>DESC</option></select></td><td colspan="4"></td></tr>'; 
        $main_content .= '<tr style="background-color:'.$config['site']['vdarkborder'].'" style="font-size: 10pt;"><td colspan="3">Nick contains:<br /><input type="text" name="name_contains" value="' . htmlspecialchars($nameContains) .'" size="30" /><td colspan="2">Min. <input type="text" name="min_level" value="' . $minLevel .'" size="4" /> level</td><td>Min. <input type="text" name="days_ago" value="' . $daysAgo .'" size="2" /> days</td><td>Results<br /><input type="text" name="results_limit" value="' . $resultsLimit .'" size="3" /></td><td><input type="submit" value="Search"/></td></tr>'; 
        $main_content .= '</form>'; 
        ############ SEARCH FORM ############ 
        $main_content .= '<tr style="background-color:'.$config['site']['vdarkborder'].'" style="font-size: 14pt;"><td>ID</td><td>Nick</td><td>Level & Vocation</td><td>Offline</td><td>Auction time</td><td>Auction min. offer</td><td>Buy Now</td><td>Add</td></tr>'; 
        foreach($SQL->query('SELECT * FROM `players` WHERE `id` NOT IN (' . implode(",", $charsAlreadyOnAuctions) . ') AND `lastlogout` > 0 AND `level` >= ' . $SQL->quote($minLevel) . ' AND `lastlogout` <= ' . $SQL->quote($maxLastLogout) . ' AND `name` LIKE ' . $SQL->quote('%'.$nameContains.'%') . ' ORDER BY `' . $orderBy . '` ' . $orderType . ', `name` ASC LIMIT ' . $resultsLimit .';') as $player)
		{
            $main_content .= '<form action="?subtopic=sellchar&action=addauction&order_by=' . $orderBy .'&order_type=' . $orderType . '&name_contains=' . urlencode($nameContains) . '&min_level=' . $minLevel . '&days_ago=' . $daysAgo . '&results_limit=' . $resultsLimit . '" method="post"><input type="hidden" name="id" value="' . $player['id'] . '" /><tr class="tableRow' . ($row++ % 2) . '"><td>' . $player['id'] . '</td><td>' . $player['name'] . '</td><td>' . $player['level'] . ' ' . htmlspecialchars(Website::getVocationName($player['vocation'], $player['promotion'])) . '</td><td style="float: right;">' . (floor((time() - $player['lastlogin']) / 86400)) . ' days</td><td><input type="text" name="auction_time" value="' . $auctions_default_time . '" size="3" /> hours</td><td><input type="text" name="price_auction" value="" size="5" /> pp</td><td><input type="text" name="price_buy_now" value="" size="5" /> pp</td><td><input type="submit" value="Add Auction" /></td></tr></form>'; 
		}
        $main_content .= '</table>'; 
    } 
    else 
        $main_content .= $errorFormStart . 'ERROR! You do not have access to this page.' . $errorFormEnd; 
} 
elseif($action == "show") ############ SHOW CHARACTER INFO ############ 
{ 
    $auctionInfo = $SQL->query('SELECT * FROM `characters_auctions` WHERE `id` = ' . (int) $_REQUEST['id'])->fetch(); 
    $main_content .= '<div class="bigText" style="text-align: center">Auction Info</div>'; 
    if(isset($auctionInfo['id'])) 
    { 
        $auctionChar = new Player($auctionInfo['char_id']);
        if($auctionChar->isLoaded()) 
        { 
            if($logged && $account_logged->getPageAccess() >= $add_character_page_access) 
                $main_content .= '<div class="normalText"><a rel="nofollow" href="?subtopic=sellchar&delete=' . $auctionInfo['id'] . '">ADMIN PANEL: >DELETE AUCTION<</a></div>'; 
############ SHOW STATS ############ 
            $row = 0; 
            $main_content .= '<table class="tableFonts" style="margin-left: auto;margin-right: auto;">'; 
            $main_content .= '<tr style="background-color:'.$config['site']['vdarkborder'].'"><td colspan="3">CHARACTER INFO</td></tr>'; 
            $main_content .= '<tr><td><table style="width: 360px;border-spacing: 1px">'; 
            $main_content .= '<tr class="tableRow' . ($row++ % 2) . '"><td>AUCTION ID:</td><td>' . $auctionInfo['id'] . '</td></tr>'; 
            $main_content .= '<tr class="tableRow' . ($row++ % 2) . '"><td>Name:</td><td>' . $auctionChar->getName() . '<br /><div style="font-size: 8pt;">(You select new name when you win auction.)</div></td></tr>'; 
            $main_content .= '<tr class="tableRow' . ($row++ % 2) . '"><td>Level:</td><td>' . $auctionChar->getLevel() . '</td></tr>'; 
            $main_content .= '<tr class="tableRow' . ($row++ % 2) . '"><td>Vocation:</td><td>' . htmlspecialchars(Website::getVocationName($auctionChar->getVocation(), $auctionChar->getPromotion())) . '</td></tr>';
            $main_content .= '<tr class="tableRow' . ($row++ % 2) . '"><td>Health:</td><td>' . $auctionChar->getHealthMax() . '</td></tr>'; 
            $main_content .= '<tr class="tableRow' . ($row++ % 2) . '"><td>Mana:</td><td>' . $auctionChar->getManaMax() . '</td></tr>'; 
            $main_content .= '<tr class="tableRowSmall' . ($row++ % 2) . '"><td>Magic Level:</td><td>' . $auctionChar->getMagLevel() . '</td></tr>'; 
            $main_content .= '<tr class="tableRowSmall' . ($row++ % 2) . '"><td>Sword:</td><td>' . $auctionChar->getSkill(2) . '</td></tr>'; 
            $main_content .= '<tr class="tableRowSmall' . ($row++ % 2) . '"><td>Axe:</td><td>' . $auctionChar->getSkill(3) . '</td></tr>'; 
            $main_content .= '<tr class="tableRowSmall' . ($row++ % 2) . '"><td>Club:</td><td>' . $auctionChar->getSkill(1) . '</td></tr>'; 
            $main_content .= '<tr class="tableRowSmall' . ($row++ % 2) . '"><td>Distance:</td><td>' . $auctionChar->getSkill(4) . '</td></tr>'; 
            $main_content .= '<tr class="tableRowSmall' . ($row++ % 2) . '"><td>Shielding:</td><td>' . $auctionChar->getSkill(5) . '</td></tr>'; 
            $main_content .= '</table></td>'; 
############ SHOW EQ ############ 

            $main_content .= '<td>'; 
			
			
			
			
			
			$itemsList = $auctionChar->getItems();
			$main_content .= '<table with=100% style="border: solid 1px #888888;" CELLSPACING="1"><TR>';		
			$list = array('2','1','3','6','4','5','9','7','10','8');
			foreach ($list as $number_of_items_showed => $slot)
			{
				if($slot == '8') // add Soul before show 'feet'
				{
					$main_content .= '<td style="background-color: '.$config['site']['darkborder'].'; text-align: center;">Soul:<br/>'. $auctionChar->getSoul() .'</td>';
				}
				if($itemsList->getSlot($slot) === false) // item does not exist in database
				{
					$main_content .= '<TD style="background-color: '.$config['site']['darkborder'].';"><img src="http://static2.otland.net/i/items/'. $slot .'.gif" width="45"/></TD>';
				}
				else
				{
					$main_content .= '<TD style="background-color: '.$config['site']['darkborder'].';"><img src="http://static2.otland.net/i/items/'. $itemsList->getSlot($slot)->getID() . '.gif" width="45"/></TD>';
				}
				if($number_of_items_showed % 3 == 2)
				{
					$main_content .= '</tr><tr>';
				}
				if($slot == '8') // add Capacity after show 'feet'
				{
					$main_content .= '<td style="background-color: '.$config['site']['darkborder'].'; text-align: center;">Cap:<br/>'. $auctionChar->getCap() .'</td>';
				}
			}
			$main_content .= '</tr></TABLE>';
			
			
			
			
			
			
			
			
			
			
            $main_content .= '</td>'; 
            $main_content .= '</tr></table>'; 
############ SHOW DONATORS SHOP ITEMS ############ 
            $donators_items = $SQL->query('SELECT `player_items`.`itemtype`, SUM(`player_items`.`count`) AS count, `z_shop_offer`.`offer_name` AS name FROM `player_items`, `z_shop_offer` WHERE `player_items`.`player_id` = ' . $auctionChar->getId() . ' AND `z_shop_offer`.`offer_type` = \'item\' AND `player_items`.`itemtype` = `z_shop_offer`.`itemid1` GROUP BY `player_items`.`itemtype`;')->fetchAll(); 
            $donators_depotitems = $SQL->query('SELECT `player_depotitems`.`itemtype`, SUM(`player_depotitems`.`count`) AS count, `z_shop_offer`.`offer_name` AS name FROM `player_depotitems`, `z_shop_offer` WHERE `player_depotitems`.`player_id` = ' . $auctionChar->getId() . ' AND `z_shop_offer`.`offer_type` = \'item\' AND `player_depotitems`.`itemtype` = `z_shop_offer`.`itemid1` GROUP BY `player_depotitems`.`itemtype`;')->fetchAll(); 
            if(count($donators_items) > 0 || count($donators_depotitems) > 0) 
            { 
                $main_content .= '<table class="tableFonts" style="margin-left: auto;margin-right: auto;padding-top: 30px;">'; 
                if(count($donators_items) > 0) 
                { 
                    $main_content .= '<tr style="background-color:'.$config['site']['vdarkborder'].'"><td colspan="3">DONATORS ITEMS</td></tr>'; 
                    $row = 0; 
                    foreach($donators_items as $donator_item) 
                        $main_content .= '<tr class="tableRow' . ($row++ % 2) . '"><td class="showItemSquare"><img src="/images/items/'. $donator_item['itemtype'] . '.gif" alt="" class="showItemImage"/></td><td>' . $donator_item['count'] .'x</td><td>' . $donator_item['name'] . '</td></tr>'; 
                } 
                if(count($donators_depotitems) > 0) 
                { 
                    $main_content .= '<tr style="background-color:'.$config['site']['vdarkborder'].'"><td colspan="3">DONATORS IN DEPOT</td></tr>'; 
                    $row = 0; 
                    foreach($donators_depotitems as $donator_depotitem) 
                        $main_content .= '<tr class="tableRow' . ($row++ % 2) . '"><td class="showItemSquare"><img src="/images/items/'. $donator_depotitem['itemtype'] . '.gif" alt="" class="showItemImage"/></td><td>' . $donator_depotitem['count'] .'x</td><td>' . $donator_depotitem['name'] . '</td></tr>'; 
                } 
                $main_content .= '</table>'; 
            } 
############ SHOW AUCTION INFO ############ 
            $row = 0; 
            $main_content .= '<table class="tableFonts" style="margin-left: auto;margin-right: auto;padding-top: 30px;">'; 
            $main_content .= '<tr style="background-color:'.$config['site']['vdarkborder'].'"><td colspan="2">AUCTION INFO</td></tr>'; 
            if($auctionInfo['buy_now'] > 0) 
                $main_content .= '<tr class="tableRow' . ($row++ % 2) . '"><td>Buy now:</td><td>' . $auctionInfo['buy_now'] . ' premium points</td></tr>'; 
            $main_content .= '<tr class="tableRow' . ($row++ % 2) . '"><td>Highest bid:</td><td>' . $auctionInfo['bid'] . ' premium points</td></tr>'; 
            $main_content .= '<tr class="tableRow' . ($row++ % 2) . '"><td>Time left:</td><td><div name="timer_' . $auctionInfo['id'] . '" id="timer_' . $auctionInfo['id'] . '">' . time_left($auctionInfo['finish_time'] - time()) . '</div></td></tr>'; 
            $main_content .= '</table><br /><script type="text/javascript">countdown(' . ($auctionInfo['finish_time'] - time()) . ', \'timer_' . $auctionInfo['id'] . '\');</script>'; 
            if($auctionInfo['state'] == 0) 
            { 
                $main_content .= '<form action="?subtopic=sellchar&action=bid&id=' . $auctionInfo['id'] . '" method="post" onsubmit="return checkBid(' . (($logged) ? $account_logged->getId() : 0) . ', ' . $auctionInfo['bidder'] . ', ' . (($logged) ? $account_logged->getPremiumPoints() : 0) . ', ' . $auctionInfo['bid'] . ');">'; 
                $main_content .= '<table class="tableFonts" style="float: left;">'; 
                $main_content .= '<tr style="background-color:'.$config['site']['vdarkborder'].'"><td colspan="2">YOUR BID</td></tr>'; 
                $main_content .= '<tr class="tableRow' . ($row++ % 2) . '"><td>Bid:</td><td><input type="text" id="bid" name="bid" value="' . ($auctionInfo['bid'] + 1) . '" /> pp</td></tr>'; 
                $main_content .= '<tr class="tableRow' . ($row++ % 2) . '"><td colspan="2" style="text-align: center;"><input type="submit" value="BID" /></td></tr></table></form><br />'; 
                if($auctionInfo['buy_now'] > 0) 
                    $main_content .= '<a rel="nofollow" href="?subtopic=sellchar&action=buy&id=' . $auctionInfo['id'] . '" class="linkButton" style="float: right;" onclick="return checkBuyNow(' . (($logged) ? $account_logged->getId() : 0) . ', ' . (($logged) ? $account_logged->getPremiumPoints() : 0) . ', ' . $auctionInfo['buy_now'] . ');">BUY NOW!</a>'; 
            } 
            $main_content .= '<div style="padding-top: 120px;padding-left: 45%"><a rel="nofollow" href="?subtopic=sellchar" class="linkButton">BACK</a></div>'; 
        } 
        else 
            $main_content .= $errorFormStart . 'ERROR! Character doesn\'t exist.' . $errorFormEnd; 
    } 
    else 
        $main_content .= $errorFormStart . 'ERROR! Auction with this ID doesn\'t exist.' . $errorFormEnd; 
} 
elseif($action == "bid") ############ BID CHARACTER ############ 
{ 
    $main_content .= '<div class="bigText" style="text-align: center">Bid character</div>'; 
    if($logged) 
    { 
        $auctionInfo = $SQL->query('SELECT * FROM `characters_auctions` WHERE `state` = 0 AND `id` = ' . (int) $_REQUEST['id'])->fetch(); 
        if(isset($auctionInfo['id'])) 
        { 
            $auctionChar = new Player($auctionInfo['char_id']);
            if($auctionChar->isLoaded()) 
            { 
                if($account_logged->getPremiumPoints() > $auctionInfo['bid'] || ($account_logged->getId() == $auctionInfo['bidder'] && $account_logged->getPremiumPoints() > 0)) 
                { 
                    if(isset($_REQUEST['bid']) && (int) $_REQUEST['bid'] > 0) 
                    { 
                        $userBid = (int) $_REQUEST['bid']; 
                        if($account_logged->getPremiumPoints() >= $userBid || ($account_logged->getId() == $auctionInfo['bidder'] && $account_logged->getPremiumPoints() + $auctionInfo['bid'] >= $userBid)) 
                        { 
                            if($userBid > $auctionInfo['bid']) 
                            { 
                                if($account_logged->getId() != $auctionInfo['bidder']) 
                                { 
                                    $last_bidder = new Account($auctionInfo['bidder']);
                                    if($last_bidder->isLoaded()) 
                                    { 
                                        $last_bidder->setPremiumPoints($last_bidder->getPremiumPoints() + $auctionInfo['bid']); 
                                        $last_bidder->save(); 
                                    } 
                                    $account_logged->setPremiumPoints($account_logged->getPremiumPoints() - $userBid); 
                                } 
                                else 
                                    $account_logged->setPremiumPoints($account_logged->getPremiumPoints() + $auctionInfo['bid'] - $userBid); 
                                $account_logged->save(); 
                                $SQL->query('UPDATE `characters_auctions` SET `bid` = ' . $userBid . ', `bidder` = ' . $account_logged->getId() . ' WHERE `id` = ' . $auctionInfo['id']); 
                                if($auctionInfo['finish_time'] - time() < 60) 
                                    $SQL->query('UPDATE `characters_auctions` SET `finish_time` = ' . time() + 60 . ' WHERE `id` = ' . $auctionInfo['id']); 
                                $main_content .= '<div class="normalText">You have bidded ' . $userBid . ' premium points on auction ID ' . $auctionInfo['id'] . '!</div>'; 
                                $main_content .= '<div style="padding-top: 120px;padding-left: 45%"><a rel="nofollow" href="?subtopic=sellchar&action=show&id=' . $auctionInfo['id'] . '" class="linkButton">BACK</a></div>'; 
                            } 
                            else 
                                $main_content .= $errorFormStart . 'Sorry! Your bid is lower then current highest bid.<br />Your bid is: ' . $userBid . '<br />Highest bid: ' . $auctionInfo['bid'] . '' . $errorFormEnd; 
                        } 
                        else 
                            $main_content .= $errorFormStart . 'Sorry! You do not have enought premium points.<br />Your bid is: ' . $userBid . '<br />You have: ' . $account_logged->getPremiumPoints() . '' . $errorFormEnd; 
                    } 
                    else 
                        $main_content .= $errorFormStart . 'You must bid more then 0.' . $errorFormEnd; 
                } 
                else 
                    $main_content .= $errorFormStart . 'Sorry! You do not have enought premium points.<br />Highest bid is: ' . $auctionInfo['bid'] . '<br />You have: ' . $account_logged->getPremiumPoints() . '' . $errorFormEnd; 
            } 
            else 
                $main_content .= $errorFormStart . 'ERROR! Character doesn\'t exist.' . $errorFormEnd; 
        } 
        else 
            $main_content .= $errorFormStart . 'ERROR! Auction with this ID doesn\'t exist.' . $errorFormEnd; 
    } 
    else 
        $main_content .= $errorFormStart . 'You are not logged in.' . $errorFormEnd; 
} 
elseif($action == "buy") ############ BUY CHARACTER ############ 
{ 
    $main_content .= '<div class="bigText" style="text-align: center">Buy character</div>'; 
    if($logged) 
    { 
        $auctionInfo = $SQL->query('SELECT * FROM `characters_auctions` WHERE `state` = 0 AND `id` = ' . (int) $_REQUEST['id'])->fetch(); 
        if(isset($auctionInfo['id'])) 
        { 
            if($auctionInfo['buy_now'] > 0) 
            { 
                $auctionChar = new Player($auctionInfo['char_id']);
                if($auctionChar->isLoaded()) 
                { 
                    if($account_logged->getPremiumPoints() >= $auctionInfo['buy_now'] || ($account_logged->getId() == $auctionInfo['bidder'] && $account_logged->getPremiumPoints() + $auctionInfo['bid'] >= $auctionInfo['buy_now'])) 
                    { 
                        if($account_logged->getId() != $auctionInfo['bidder']) 
                        { 
                            $last_bidder = new Account($auctionInfo['bidder']);
                            if($last_bidder->isLoaded()) 
                            { 
                                $last_bidder->setPremiumPoints($last_bidder->getPremiumPoints() + $auctionInfo['bid']); 
                                $last_bidder->save(); 
                            } 
                            $account_logged->setPremiumPoints($account_logged->getPremiumPoints() - $auctionInfo['buy_now']); 
                        } 
                        else 
                            $account_logged->setPremiumPoints($account_logged->getPremiumPoints() + $auctionInfo['bid'] - $auctionInfo['buy_now']); 
                        $account_logged->save(); 
                        $auctionChar->setAccount($account_logged); 
                        $auctionChar->setGroup(1); 
                        $auctionChar->save(); 
                        $SQL->query('INSERT INTO `bans` (`id` , `type` , `value` ,`param` ,`active` ,`expires` ,`added` ,`admin_id` ,`comment` ,`reason` ,`action` ,`statement`) VALUES (NULL , 2, ' .$auctionChar->getId() . ', 2, 1, -1, ' . time() . ', 1, \'BUY CHAR\', 0, 1, \'\');'); 
                        $SQL->query('UPDATE `characters_auctions` SET `state` = 2, `finish_time` = ' . time() . ', `bidder` = ' . $account_logged->getId() . ', `bid` = `buy_now` WHERE `id` = ' . $auctionInfo['id']); 
                        $main_content .= '<div class="normalText">You have bought new character! Character is now on your account. Login in game and select new name for your character.</div>'; 
                        $main_content .= '<div style="padding-top: 120px;padding-left: 45%"><a rel="nofollow" href="?subtopic=sellchar" class="linkButton">BACK</a></div>'; 
                    } 
                    else 
                        $main_content .= $errorFormStart . 'Sorry! You do not have enought premium points.<br />It cost: ' . $auctionInfo['buy_now'] . '<br />You have: ' . $account_logged->getPremiumPoints() . '' . $errorFormEnd;
                } 
                else 
                    $main_content .= $errorFormStart . 'ERROR! Character doesn\'t exist.' . $errorFormEnd; 
            } 
            else 
                $main_content .= $errorFormStart . 'ERROR! You can not buy this character by Buy Now option. You can only Bid on auction.' . $errorFormEnd; 
        } 
        else 
            $main_content .= $errorFormStart . 'ERROR! Auction with this ID doesn\'t exist.' . $errorFormEnd; 
    } 
    else 
        $main_content .= $errorFormStart . 'You are not logged in.' . $errorFormEnd; 
} 
else ############ SHOW LIST OF AUCTIONS ############ 
{ 
    if(isset($_REQUEST['delete'])) 
        if($logged && $account_logged->getPageAccess() >= $add_character_page_access) 
        { 
            $SQL->query('DELETE FROM `characters_auctions` WHERE `id` = ' . (int) $_REQUEST['delete']); 
            $main_content .= $errorFormStart . 'Auction ' . (int) $_REQUEST['delete'] . ' should be deleted.' . $errorFormEnd; 
        } 
        else 
            $main_content .= $errorFormStart . 'You can not delete. You do not have access.' . $errorFormEnd; 
    $main_content .= '<div class="bigText" style="text-align: center">Characters Auctions</div>'; 
    $main_content .= '<div class="normalText">With this system you can buy un-used (inactive) characters by auctioning for them. When you bid on a character it will automatically take premium points from your account. If someone out-bids you, you will get those premium points added back to your account. If the auction time is under 2 minutes when someone bids, 1 minute will automatically be added to the auction time to give time for a re-bid from the previous bidder. If you choose to "buy now" you will get the character within 1 minute.</div>'; 
    $main_content .= '<table class="tableFonts"><tr style="background-color:'.$config['site']['vdarkborder'].'" style="font-size: 28px;text-align: center"><td>Time left</td><td>Char info</td><td>Buy now</td><td>Highest bid</td></tr>'; 
	$timers = array();
    foreach($SQL->query('SELECT * FROM `characters_auctions` WHERE `finish_time` > ' . time())->fetchAll() as $auctionInfo)
    { 
        $auctionChar = new Player($auctionInfo['char_id']);
        if($auctionChar->isLoaded()) 
            $main_content .= '<tr class="tableRow' . ($row++ % 2) . '" style="font-size: 16px;text-align: center" onclick="window.location = \'?subtopic=sellchar&action=show&id=' . $auctionInfo['id'] . '\'"><td><div id="timer_' . $auctionInfo['id'] . '">' . time_left($auctionInfo['finish_time'] - time()) . '</div></td><td>' . $auctionChar->getLevel() . ' ' . htmlspecialchars(Website::getVocationName($auctionChar->getVocation(), $auctionChar->getPromotion())) . '</td><td>' . $auctionInfo['buy_now'] . ' pp</td><td>' . $auctionInfo['bid'] . ' pp</td></tr>'; 
        $timers['timer_' . $auctionInfo['id']] = $auctionInfo['finish_time'] - time(); 
    } 
    $main_content .= '</table><br /><div class="normalText">Press on auction to get more informations.</div>'; 
    $main_content .= '<script type="text/javascript">'; 
    foreach($timers as $timer_id => $time_left) 
        $main_content .= 'countdown(' . $time_left . ', \'' . $timer_id . '\');'; 
    $main_content .= '</script>'; 
} 
$main_content .= '<br /><br />'; 
?>

Gesior, I usually like your code, but do you have a good reason for using $_REQUEST? I really doubt you have in this case. This 'method' returns an associative array containing $_GET, $_POST and even $_COOKIE data, is that really what you want? You open the doors for CSRF attacks if all data is not being filtered correctly. Also, have you considered using the MVC pattern in the future for Gesior AAC? Anyway, keep going mate. :)
 
Last edited:
I have Bug on Gesior Acc ;((

I would like someone to help me change the look of the login and AccountManagement. The rest is well-programmed in such colors like HighScoress!
blad4.jpg

And here AccountManagement problem ... They are different colors and some huge mess ... Please help me.

blad3s.jpg

Layout LINK :::

Thanks in advance.
 
That's not an bug within Gesior AAC.

Change colors in the CSS files.
 
how to find exactly what is on the brown? this particular item? do not know much about php .. : (
 
use google chrome to find from which .css file it loads that attribute (color of text, color of background, image etc.). Press right mouse button on thing that you want check and select from menu 'check element'. It will show new window at bottomof current 'card' and at right side of it will be list of .css files loaded and lines of each file used by this element.

@nik...
How $_REQUEST makes it easier to attack with method CSFR? Can you describe some possible attack which could be blocked if I limit incoming data in places where it's possible?
 
use google chrome to find from which .css file it loads that attribute (color of text, color of background, image etc.). Press right mouse button on thing that you want check and select from menu 'check element'. It will show new window at bottomof current 'card' and at right side of it will be list of .css files loaded and lines of each file used by this element.

@nik...
How $_REQUEST makes it easier to attack with method CSFR? Can you describe some possible attack which could be blocked if I limit incoming data in places where it's possible?

The problem is that $_COOKIE is mixed into $_REQUEST, and that it takes precedence. However, as long as all incoming data from the client is being sanitized and done in the right way, it should be ok. But I still can't figure out the reason why you're using it for that purpose, as it's best to explicity request the data from where it's coming from.
 
Last edited:
I did update acc. maker for 0.4 and 0.3.6, but it's not on github yet. First I want be sure it's ready to use.
If you got 5-10 minutes please try to:
- install acc. maker on clean TFS X.X database
- create 2 accounts
- create characters on them
- create guild by one char (first all level by phpmyadmin), join to guild by second char
- open pages: 'Characters' (of one of chars), 'Highscore' and 'who is online' (set in database 'online' to 1 in table 'players' so they will be visible on list) and CHECK IF THERE ARE ITEMS IMAGES AND OUTFIT IMAGES
- if you install acc. maker on VPS/dedic and make account from home there should be also visible 'flag' of your country (if you make on home PC then it will be 'unknown')

Links to newest acc. maker:
http://gesior2012.ots.me/TFS-0.3.6_and_0.4_to_rev_3703.zip - for 0.3.6 and 0.4 without salt
http://gesior2012.ots.me/TFS-0.4_rev_3703+.zip - for 0.4 with salt (salt is from rev. 3703)

Short tutorial about 'config.php':
http://otland.net/f479/configuration-gesior2012-config-php-file-description-172012/
 
UPDATE:
I fixed one big bug in guilds.php [guild name length could be 0].

Fixed bug with character creation when you use SQLite database.

Almost done version for TFS 0.2.13+.
 
Gesior, i did not tested the Gesior 2012 yet but, some bugs that i know is..

If a player which is leader of a guild be deleted, the guild page cant see more viewed, and you can put characters like 'ç á à' on name of guilds.

Sorry if you already fixed them. Continue your great work ;)
 
Gesior, i did not tested the Gesior 2012 yet but, some bugs that i know is..

If a player which is leader of a guild be deleted, the guild page cant see more viewed, and you can put characters like 'ç á à' on name of guilds.

Sorry if you already fixed them. Continue your great work ;)
IDK in which version it was possible to use not-english letters in names :blink:
Script to verify name:
PHP:
function check_guild_name($name)
{
	$name = (string) $name;
	$words_blocked = array('--', "''","' ", " '", '- ', ' -', "-'", "'-", '  ');
	$temp = strspn("$name", "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789-' ");
	if($temp != strlen($name))
		return false;
	if(strlen($name) < 1)
		return false;
	if(strlen($name) > 60)
		return false;

	foreach($words_blocked as $word)
		if (!(strpos($name, $word) === false))
			return false;

	return true;
}
Length: 1-59 letters
Allowed letters: qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789-' (+ space)
Not allowed letters combinations in name of guild: '--', "''","' ", " '", '- ', ' -', "-'", "'-", ' '
-------------------------------------------------
If you delete guild leader from 'players', guild will not disappear on guilds list and as a member you can view it's page (without leader on list and 2 small errors on page as it's not normal to delete ) and click 'Leave Guild'. To remove guild bugged admin (of site) must visit Guilds list and press link 'Delete this guild (for ADMIN only!)'.

- - - Updated - - -

Github updated. Now I use branches:
https://github.com/gesior/Gesior2012
Available versions [branches]:
- TFS-0.2.13+
- TFS-0.3.6_and_0.4_to_rev_3703
- TFS-0.4_rev_3703+
[from that rev. TFS uses 'salt' when you login to account]
Each version size in .zip is around 1.3 MB, unzipped 2 MB, but it will grow up to 10 MB (download files from ots.me when they are required).

'pages' from 0.3.6 and 0.4 branches are compatible. Version 0.2.13+ has less pages [houses page not ready yet, top fraggers removed, top guilds in news removed etc.] and they are not compatible with other versions, because there is no 'multiworld' in TFS 0.2.
Example:
show vocation name in 0.2.13+:
PHP:
Website::getVocationName($player->getVocation())
// OR:
$vocation_names[$player->getVocation()]
in 0.3.6 and 0.4:
PHP:
Website::getVocationName($player->getVocation(), $player->getPromotion())
// OR:
$vocation_names[$player->getPromotion()][$player->getVocation()]

First release:
http://otland.net/f118/gesior-2012-version-1-0-0-beta-173280/
 
Last edited:
Humm.. Gesior, i forget, thats not guild name, thats 'player nickname in guild', you are allowed to put non-english letters. And, you should put some delay to be able to create new accounts/players, its a cool feature.
 
I always did love how you DON'T know how to use PHP language. Learned nothing, that's sad.
I didn't even browse the code neither the topic - just this page, and... guild name verifier function, which could simply look like that:

Code:
function check_guild_name(string $name)
{
	if(!preg_match("/^[A-Za-z0-9-' ]{1,60}$/", $name))
		return false;

	foreach(array('--', "''","' ", " '", '- ', ' -', "-'", "'-", '  ') as $word)
	{
		if(strpos($name, $word) !== false)
			return false;
	}

	return true;
}

(probably that other "word" checking function could be also moved over to preg query, but I am not a regex king)

Benchmarked it with yours and for 1000 tries with the guild name Real'ly extended as hell with 60 characters long guild name got following result:

dawid@s1:~$ php lol.php
Gesior.pl check_guild_name function 1000 times execution time: 0.00536608695984
preg_matched check_guild_name function 1000 times execution time: 0.00376009941101

Anyway as mentioned by yourself, the only difference between new and old Gesior (if we can call it even new...) is removed POT which people got used over to and in fact didn't fuck up performance that bad as all your other code. Don't defend with injection protection as users also have fixed that over years and I am quite sure there is still much left.
I don't see a single reason why you have decided to add new features (outfits, flags and stuff) to something that bad, buggy and useless. No framework (even own), no theme manager and probably still using $main_content.
Conclusion is only one: you shouldn't have touch your old work and let it rot in peace.
 
@up
It should, but I did not update that code as I did not update any code that was not bugged [mean return what it should return, no matter of execution time/clean code].
Don't defend with injection protection as users also have fixed that over years and I am quite sure there is still much left.
Users fixed it over years, but no one posted version with all bugs fixed. In this version is 0 sql injections. All SQL queries rewritten.

So you say that if users attempt to create guild 1.000.000 times server can use 2 seconds of CPU less? It must be quite interesting for acc. maker users with use 'top 3 guilds' code in 'news' which execution time is ~0.5 sec on 3GHz CPU.

Want clean and optimized code? Make it (yes, you elf) or pay for it. I don't have time to rewrite whole acc. maker for free.
 
So you say that if users attempt to create guild 1.000.000 times server can use 2 seconds of CPU less? It must be quite interesting for acc. maker users with use 'top 3 guilds' code in 'news' which execution time is ~0.5 sec on 3GHz CPU.

You probably don't know what are you talking about... This is just a single function. Backtrace yourself a single page and see how many different functions are executed. Now imagine that page is attacked with 10.000 requests and calculate how long it will take to execute. Now cut off from each function even that 0.0016sec and calculate how long it will take. Think wider, please.

Want clean and optimized code? Make it (yes, you elf) or pay for it. I don't have time to rewrite whole acc. maker for free.

I had attempted few years ago to help you optimizing and improving the code. Most of my suggestions were denied without a reason. It is your jar now. If you want money for it, ask people to appreciate your work with a donation. With the amount of users 3 years ago you could easily get satisfying amount to rewrite it clean and optimized.
 
I had attempted few years ago to help you optimizing and improving the code. Most of my suggestions were denied without a reason.
Yes. I remember that. You sent me your version of gesior acc. maker. I did open it on XAMPP and get blank page. I did ask you 'why?', what is wrong and you did not answer. Post it on forum -> people download it -> see blank page -> report to you -> you ignore them. Sounds like good plan ;)

I remember when Talaturen wrote me that there will be 'otland acc. maker in few weeks'. I was not sure if I should learn PHP and make my acc. maker [all acc. makers on forum were one big bug - hack in 5 minutes after you add ots to otservlist]. Why should I make it, if there will be awesome acc. maker by experienced programmers in few weeks... It was 5 years ago!
 
In my humble opinion you should ignore backward compatibility and write AAC from scratch.
 
Back
Top