<?php
/**
 *  Dolumar engine, php/html MMORTS engine
 *  Copyright (C) 2009 Thijs Van der Schaeghe
 *  CatLab Interactive bvba, Gent, Belgium
 *  http://www.catlab.eu/
 *  http://www.dolumar.com/
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

abstract class Neuron_GameServer_Windows_BaseChat
	extends Neuron_GameServer_Windows_Window
{
	const USE_BLOCKING = false;

	private $channelId;

	final public function setSettings ()
	{
		$text = Neuron_Core_Text::__getInstance ();

		// Window settings
		$this->setSize ('250px', '250px');

		// Poll once every second
		$this->setAjaxPollSeconds (1);

		// Very important, without this everything will lock
		$this->setPool ('newchat');

		$this->setClassName ('chatwindow');

		$this->setOnFirstload ("scrollDownChat('messagecontainer');");

		$this->setTitle ($this->getTitle ());

		$this->additionalSettings ();

		$this->channel->subscribe ('chat-' . $this->getChannelID ());

		$this->setContainer ('left');
	}

	protected function additionalSettings ()
	{

	}

	/**
	* Get the mapper. Depends on what system we use.
	*/
	private function getMapper ()
	{
		if (self::USE_BLOCKING)
		{
			return Neuron_GameServer_Mappers_BlockingChatMapper::getInstance ();
		}
		else
		{
			return Neuron_GameServer_Mappers_CachedChatMapper::getInstance ();
		}
	}

	protected abstract function getChannelName ();
	protected abstract function getTitle ();

	protected function getHeader ()
	{
		return '
' . $this->getTitle () . '
';
	}

	private function getChannelID ()
	{
		if (!isset ($this->channelId))
		{
			$mapper = $this->getMapper ();

			$channelname = $this->getChannelName ();
			$this->channelId = $mapper->getChannelID ($channelname);
		}

		return $this->channelId;
	}

	private function getOlderMessages ($before = null)
	{
		$mapper = $this->getMapper ();

		$channelId = $this->getChannelID ();
		$messages = $mapper->getMessages ($channelId, 10, null, $before);

		return $this->messagesToDiv ($messages, true);
	}

	private function getMessageContainer ($latest = null, $showOlderLink = false)
	{
		$mapper = $this->getMapper ();

		$channelId = $this->getChannelID ();
		$messages = $mapper->getMessages ($channelId, 20, $latest);

		if (count ($messages) > 0)
		{
			// also update the last id
			if ($mapper->getLastReceivedMessageId ())
			{
				$requestData = $this->getRequestData ();
				$requestData['lastMessage'] = $mapper->getLastReceivedMessageId ();

				$this->updateRequestData ($requestData);
			}

			$this->onReceivedMessages ($mapper);
		}

		return $this->messagesToDiv ($messages, $showOlderLink);
	}

	private function messagesToDiv ($messages, $showOlderLink = false)
	{
		if (count ($messages) > 0)
		{
			$page = new Neuron_Core_Template ();
			$page->set ('messages', $messages);
			$page->set ('showOlderMessages', $showOlderLink);
			return $page->parse ('gameserver/chat/messages.phpt');
		}

		return false;
	}

	public function getContent ()
	{
		$text = Neuron_Core_Text::getInstance ();

		$player = Neuron_GameServer::getPlayer ();
		if (!$player)
		{
			return $this->throwError ($text->get ('login', 'login', 'account'));
		}

		try
		{
			$channelId = $this->getChannelID ();
		}
		catch (Neuron_Exceptions_DataNotSet $e)
		{
			return '
Channel not found.
';
		}

		// Register us to this channel
		$mapper = $this->getMapper ();
		$mapper->joinChannel ($player, $channelId);

		// output
		$page = new Neuron_Core_Template ();

		$page->set ('header', $this->getHeader ());

		// Now get the initial messages
		$page->set ('messages', $this->getMessageContainer (null, true));

		return $page->parse ('gameserver/chat/baseview.phpt');
	}

	private function postMessage ($message)
	{
		$user = Neuron_GameServer::getPlayer ();

		$channelId = $this->getChannelID ();

		$mapper = $this->getMapper ();

		$msgid = $mapper->sendMessage ($channelId, $message, $user);

		$this->onPostMessage ($msgid, $mapper);

		$this->channel->refresh ('chat-' . $this->getChannelID ());
	}

	protected function onPostMessage ($msgId, Neuron_GameServer_Mappers_ChatMapper $mapper)
	{

	}

	protected function onReceivedMessages (Neuron_GameServer_Mappers_ChatMapper $mapper)
	{

	}

	public function processInput ()
	{
		$login = Neuron_Core_Login::getInstance ();
		$text = Neuron_Core_Text::getInstance ();

		$input = $this->getInputData ();
		if ($login->isLogin ())
		{
			if (isset ($input['message']))
			{
				$message = trim ($input['message']);

				if (!empty ($message))
				{
					$user = Neuron_GameServer::getPlayer ();

					if (!$user->isPlaying ())
					{
						$this->alert ($text->get ('registerfirst'));
					}

					elseif (!$user->isEmailVerified ())
					{
						$this->alert ($text->get ('validateEmail_short', 'main', 'account'));
					}

					elseif ($user->isBanned ('chat'))
					{
						$end = $user->getBanDuration ('chat');

						$duration = Neuron_Core_Tools::getCountdown ($end);

						$this->alert
						(
							Neuron_Core_Tools::putIntoText
							(
								$text->get ('banned'),
								array
								(
									'duration' => $duration
								)
							)
						);
					}
					else
					{
						// Post message
						$this->postMessage ($input['message']);
					}
				}
			}
		}

		// Check for input: load older messages
		if (isset ($input['loadprevious']))
		{
			$before = $input['loadprevious'];

			if ($html = $this->getOlderMessages ($before))
			{
				$this->addHtmlToElement ('messagecontainer', $html, 'top');
			}
			else
			{
				$this->addHtmlToElement ('messagecontainer', '

', 'top');
			}
		}

		// If not using blocking, we can "safely" process it right now
		if (!self::USE_BLOCKING)
		{
			$this->getRefresh ();
		}
	}

	/*
		Equals: checks if this window is a duplicate of another window
	*/
	public function equals (Neuron_GameServer_Windows_Window $window)
	{
		if ($window instanceof self)
		{
			// Check the id
			if ($this->getChannelName () == $window->getChannelName ())
			{
				return true;
			}
		}
		return false;
	}

	public function getRefresh ()
	{
		$data = $this->getRequestData ();
		$newStuff = isset ($data['lastMessage']) ? $data['lastMessage'] : null;

		if ($html = $this->getMessageContainer ($newStuff, false))
		{
			$this->addHtmlToElement ('messagecontainer', $html, 'bottom');
		}
	}
}


<?php
/**
 * Phossa Project
 *
 * PHP version 5.4
 *
 * @category  Library
 * @package   Phossa2\Shared
 * @copyright Copyright (c) 2016 phossa.com
 * @license   http://mit-license.org/ MIT License
 * @link      http://www.phossa.com/
 */
/*# declare(strict_types=1); */

namespace Phossa2\Shared\Extension;

use Phossa2\Shared\Message\Message;
use Phossa2\Shared\Exception\LogicException;
use Phossa2\Shared\Exception\BadMethodCallException;

/**
 * ExtensionAwareTrait
 *
 * @package Phossa2\Shared
 * @author  Hong Zhang <phossa@126.com>
 * @see     ExtensionAwareInterface
 * @version 2.0.23
 * @since   2.0.23 added
 */
trait ExtensionAwareTrait
{
    /**
     * Methods provided by extensions
     *
     * @var    array
     * @access protected
     */
    protected $extension_methods = [];

    /**
     * @param  string $method
     * @param  array $arguments
     * @return mixed
     * @throws BadMethodCallException if method not found
     * @access public
     */
    public function __call($method, array $arguments)
    {
        if ($this->hasExtensionMethod($method)) {
            return $this->runExtension($method, $arguments);
        }
        throw new BadMethodCallException(
            Message::get(Message::MSG_METHOD_NOTFOUND, $method),
            Message::MSG_METHOD_NOTFOUND
        );
    }

    /**
     * {@inheritDoc}
     */
    public function addExtension(
        ExtensionInterface $ext,
        /*# bool */ $forceOverride = false
    ) {
        foreach ($ext->methodsAvailable() as $method) {
            if (isset($this->extension_methods[$method]) &&
                !$forceOverride) {
                throw new LogicException(
                    Message::get(Message::MSG_EXTENSION_METHOD, $method),
                    Message::MSG_EXTENSION_METHOD
                );
            }
            $this->extension_methods[$method] = $ext;
        }
        $ext->boot($this);
        return $this;
    }

    /**
     * Is this method from extensions ?
     *
     * @param  string $method
     * @return bool
     * @access protected
     */
    protected function hasExtensionMethod(/*# string */ $method)/*# : bool */
    {
        return isset($this->extension_methods[$method]);
    }

    /**
     * Include this in server's __call()
     *
     * @param  string $method
     * @param  array $args
     * @return mixed
     * @access protected
     */
    protected function runExtension(/*# string */ $method, array $args)
    {
        /* @var $ext ExtensionInterface */
        $ext = $this->extension_methods[$method];

        // execute extesion method
        return call_user_func_array([$ext, $method], $args);
    }
}


<?php
/**
 *  Dolumar engine, php/html MMORTS engine
 *  Copyright (C) 2009 Thijs Van der Schaeghe
 *  CatLab Interactive bvba, Gent, Belgium
 *  http://www.catlab.eu/
 *  http://www.dolumar.com/
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

class Neuron_GameServer_Player_Preferences
{
	private $sPreferences = array ();

	public function __construct (Neuron_GameServer_Player $profile)
	{
		$this->objProfile = $profile;
	}

	/*
		Preferences
	*/
	private function loadPreferences ()
	{
		$db = Neuron_DB_Database::getInstance ();

		$data = $db->query
		("
			SELECT
				*
			FROM
				n_players_preferences
			WHERE
				p_plid = {$this->objProfile->getId()}
		");

		foreach ($data as $v)
		{
			$this->sPreferences[$v['p_key']] = $v['p_value'];
		}
	}

	public function setPreference ($sKey, $sValue)
	{
		$db = Neuron_DB_Database::getInstance ();

		// Check if exist
		$check = $db->query
		("
			SELECT
				*
			FROM
				n_players_preferences
			WHERE
				p_key = '{$db->escape($sKey)}'
				AND p_plid = {$this->objProfile->getId()}
		");

		if (count ($check) == 0)
		{
			$db->query
			("
				INSERT INTO
					n_players_preferences
				SET
					p_key = '{$db->escape($sKey)}',
					p_value = '{$db->escape($sValue)}',
					p_plid = {$this->objProfile->getId ()}
			");
		}
		else
		{
			$db->query
			("
				UPDATE
					n_players_preferences
				SET
					p_value = '{$db->escape($sValue)}'
				WHERE
					p_key = '{$db->escape($sKey)}' AND
					p_plid = {$this->objProfile->getId ()}
			");
		}
	}

	public function getPreference ($sKey, $default = false)
	{
		$this->loadPreferences ();
		if (isset ($this->sPreferences[$sKey]))
		{
			return $this->sPreferences[$sKey];
		}
		else
		{
			return $default;
		}
	}

	public function __destruct ()
	{
		unset ($this->objProfile);
	}
}
?>


<?php
/**
 *  Dolumar engine, php/html MMORTS engine
 *  Copyright (C) 2009 Thijs Van der Schaeghe
 *  CatLab Interactive bvba, Gent, Belgium
 *  http://www.catlab.eu/
 *  http://www.dolumar.com/
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

class Neuron_Core_Lock
{
	public static function __getInstance ()
	{
		static $in;

		if (!isset ($in))
		{
			$in = new Neuron_Core_Lock ();
		}

		return $in;
	}

	public static function getInstance ()
	{
		return self::__getInstance ();
	}

	private $softlocks;
	private $locks;

	public function __construct ()
	{
		$this->softlocks = array ();
		$this->locks = array ();
	}

	/*
		Set a lock and make sure nobody gets in.
	*/
	public function setLock ($sType, $id, $iTimeout = 300)
	{
		// First check cache and jump out of function if found
		if (isset ($this->locks[$sType]) && isset ($this->locks[$sType][$id]))
		{
			return false;
		}

		// Do a sessions lock just for the sake of fast loadyness ;)
		if ($this->setSoftLock ($sType, $id))
		{
			$db = Neuron_Core_Database::__getInstance ();

			// Lock the table
			$db->customQuery ("LOCK TABLES n_locks WRITE");

			$chk = $db->select
			(
				'n_locks',
				array ('l_id', 'l_date'),
				"l_type = '".$sType."' AND l_lid = ".intval ($id)
			);

			if (count ($chk) == 0)
			{
				$id = $db->insert
				(
					'n_locks',
					array
					(
						'l_type' => $sType,
						'l_lid' => intval ($id),
						'l_date' => time ()
					)
				);

				$db->customQuery ("UNLOCK TABLES");

				if ($id > 0)
				{
					if (!isset ($this->locks[$sType]))
					{
						$this->locks[$sType] = array ();
					}

					$this->locks[$sType][$id] = true;

					return true;
				}
				else
				{
					return false;
				}
			}
			else
			{
				$db->customQuery ("UNLOCK TABLES");

				// Check if this lock is timed out
				foreach ($chk as $v)
				{
					if ($v['l_date'] < time() - $iTimeout)
					{
						$this->releaseLock ($sType, $id);
						return $this->setLock ($sType, $id);
					}
				}

				return false;
			}
		}
		else
		{
			return false;
		}
	}

	public function releaseLock ($sType, $id)
	{
		$db = Neuron_Core_Database::__getInstance ();

		$db->remove
		(
			'n_locks',
			"l_type = '".$sType."' AND l_lid = ".intval ($id)
		);

		$this->releaseSoftLock ($sType, $id);

		if (isset ($this->locks[$sType]))
		{
			unset ($this->locks[$sType][$id]);
		}
	}

	/*
		Soft lock: doesn't use MySQL and works only during the script.
		It does allow multiple $id types
	*/
	public function setSoftLock ($sType, $id)
	{
		if (!isset ($this->softlocks[$sType]))
		{
			$this->softlocks[$sType] = array ();
		}

		if (!isset ($this->softlocks[$sType][$id]))
		{
			$this->softlocks[$sType][$id] = true;
			return true;
		}
		else
		{
			return false;
		}
	}

	public function releaseSoftLock ($sType, $id)
	{
		if (isset ($this->softlocks[$sType]))
		{
			unset ($this->softlocks[$sType][$id]);
		}
	}
}
?>


<?php
/**
 *  Dolumar engine, php/html MMORTS engine
 *  Copyright (C) 2009 Thijs Van der Schaeghe
 *  CatLab Interactive bvba, Gent, Belgium
 *  http://www.catlab.eu/
 *  http://www.dolumar.com/
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

class Neuron_GameServer_Windows_OldChat extends Neuron_GameServer_Windows_Window
{
	private $sCacheKey;
	private $objCache;

	private $user;
	private $sWhere;

	private $channel = 0;

	private $aMessages = array ();

	const CHAT_GROUP_ALL = 0;
	const CHAT_GROUP_USER = 1;
	const CHAT_GROUP_CLAN = 2;

	const CHAT_CLASS_REGULAR = 0;
	const CHAT_CLASS_ME = 1;

	const DATE_FORMAT = 'H:i';

	const USE_PERSISTENT_CONNECTIONS = true;

	public function __construct ()
	{
		$this->sCacheKey = md5 (DB_DATABASE.'_last_chat_message');
		$this->objCache = Neuron_Core_Memcache::getInstance ();

		parent::__construct ();
	}

	public function setSettings ()
	{
		$text = Neuron_Core_Text::__getInstance ();
		$text->setFile ('chat');
		$text->setSection ('chat');

		// Window settings
		$this->setSize ('250px', '250px');
		$this->setTitle ($text->get ('chat'));

		$this->setAllowOnlyOnce ();
		$this->setAjaxPollSeconds (1);

		$this->setClassName ('chat');

		// Set different pool for chat
		$this->setPool ('chat');

		$this->setMinSize (250, 20);

		$this->user = Neuron_GameServer::getPlayer ();
	}

	private function switchChannel ($sChannel)
	{
		$this->channel = $this->getChannelID ($sChannel);

		$input = $this->getRequestData ();

		$this->updateRequestData
		(
			array
			(
				'channel' => $this->channel,
				'lastMessage' => $this->getInitialLastMessage (3)
			)
		);

		$text = Neuron_Core_Text::getInstance ();

		$txt = Neuron_Core_Tools::putIntoText
		(
			$text->get ('channel', 'chat', 'chat'),
			array
			(
				'channel' => $sChannel
			)
		);

		// TODO
		// Instead of using this, just sent a new
		// message to yourself.

		$this->addHtmlToElement ('chatdiv', '

'.
			'
'.$txt.'

', 'bottom');

		$_SESSION['chat_channel_move'] = true;
	}

	private function getDefaultChannel ()
	{
		$text = Neuron_Core_Text::getInstance ();
		return '#' . $text->getCurrentLanguage ();
	}

	private function getChannelID ($sChannel)
	{
		$db = Neuron_DB_Database::getInstance ();

		$channel = $db->query
		("
			SELECT
				cc_id
			FROM
				chat_channels
			WHERE
				cc_name = '{$db->escape ($sChannel)}'
		");

		if (count ($channel) == 0)
		{
			$channelid = $db->query
			("
				INSERT INTO
					chat_channels
				SET
					cc_name = '{$db->escape ($sChannel)}'
			");
		}
		else
		{
			$channelid = $channel[0]['cc_id'];
		}

		return $channelid;
	}

	private function getInitialLastMessage ($amount = 20)
	{
		$db = Neuron_Core_Database::__getInstance ();

		// Only get the last message ID
		$lastRow = $db->select
		(
			'chat',
			array ('msgId'),
			$this->getUserRightWhere (),
			"msgId DESC",
			$amount
		);

		if (count ($lastRow) > 0)
		{
			$last = $lastRow[count ($lastRow) - 1]['msgId'];
		}

		else
		{
			$last = 0;
		}

		return $last;
	}

	public function getContent ()
	{
		$text = Neuron_Core_Text::__getInstance ();
		$text->setFile ('chat');
		$text->setSection ('chat');

		$page = new Neuron_Core_Template ();
		$page->set ('send', $text->get ('send'));

		$last = $this->getInitialLastMessage ();

		$this->channel = $this->getChannelID ($this->getDefaultChannel ());

		$this->updateRequestData (array ('lastMessage' => $last));

		return $page->parse ('chat.tpl');
	}

	public function processInput ()
	{
		$text = Neuron_Core_Text::__getInstance ();
		$text->setFile ('chat');
		$text->setSection ('chat');

		$login = Neuron_Core_Login::__getInstance ();

		$input = $this->getRequestData ();
		if (!isset ($input['channel']))
		{
			$this->switchChannel ($this->getDefaultChannel ());
		}
		else
		{
			$this->channel = intval ($input['channel']);
		}

		$input = $this->getInputData ();
		if ($login->isLogin ())
		{
			if (isset ($input['message']))
			{
				$message = trim ($input['message']);

				if (!empty ($message))
				{
					$user = Neuron_GameServer::getPlayer ();

					if (!$user->isPlaying ())
					{
						$this->alert ($text->get ('registerfirst'));
					}

					elseif (!$user->isEmailVerified ())
					{
						$this->alert ($text->get ('validateEmail_short', 'main', 'account'));
					}

					elseif ($user->isBanned ('chat'))
					{
						$end = $user->getBanDuration ('chat');

						$duration = Neuron_Core_Tools::getCountdown ($end);

						$this->alert
						(
							Neuron_Core_Tools::putIntoText
							(
								$text->get ('banned'),
								array
								(
									'duration' => $duration
								)
							)
						);
					}
					else
					{
						// Post message
						$this->postMessage ($input['message']);
					}
				}
			}
		}

		else
		{
			$this->alert ($text->get ('login'));
		}
	}

	/*
		Post the message
	*/
	private function postMessage ($msg)
	{
		// Fetch the prefix
		$group = self::CHAT_GROUP_ALL;
		$mtype = self::CHAT_CLASS_REGULAR;

		$id = $this->channel;

		$msg = trim ($msg);

		$shortcuts = array
		(
			'#' => '/clan ',
			'@' => '/msg '
		);

		foreach ($shortcuts as $k => $v)
		{
			if (substr ($msg, 0, 1) == $k)
			{
				$msg = $v . substr ($msg, 1);
			}
		}

		if (substr ($msg, 0, 1) == '/')
		{
			$params = explode (' ', substr ($msg, 1));
			$length = strlen ($params[0]) + 1;

			switch (strtolower ($params[0]))
			{
				case 'join':
					$channel = isset ($params[1]) ? $params[1] : false;

					if ($channel)
					{
						$this->switchChannel ($channel);
					}

					return;
				break;

				case 'msg':
					// Fetch the user
					$username = isset ($params[1]) ? $params[1] : false;
					$objUser  = isset ($params[1]) ? Dolumar_Players_Player::getFromName ($params[1]) : false;

					if ($username && $objUser)
					{
						$length += strlen ($username) + 2;

						$group = self::CHAT_GROUP_USER;
						$id = $objUser->getId ();
					}

				break;

				case 'clan':
					$clan = $this->user->getMainClan ();
					if ($clan)
					{
						$group = self::CHAT_GROUP_CLAN;
						$id = $clan->getId ();
					}
				break;

				case 'me':
					$msg = Neuron_Core_Tools::output_varchar ($this->user->getNickname ()).' '.substr ($msg, $length);
					$length = 0;

					$mtype = self::CHAT_CLASS_ME;
				break;
			}

			if ($length > 0)
			{
				$msg = substr ($msg, $length);
			}
		}

		if (!empty ($msg))
		{
			$mtype = intval ($mtype);

			$db = Neuron_DB_Database::getInstance ();
			$biggest = $db->query
			("
				INSERT INTO
					chat
				SET
					msg = '{$db->escape($msg)}',
					datum = '".time()."',
					plid = {$this->user->getId()},
					target_group = '{$db->escape ($group)}',
					target_id = '{$db->escape ($id)}',
					mtype = $mtype
			");

			/*
			$biggest = $db->insert
			(
				'chat',
				array
				(
					'msg' => $msg,
					'datum' => time (),
					'plid' => $this->user->getId (),
					'target_group' => $group,
					'target_id' => $id
				)
			);
			*/

			$this->objCache->setCache ($this->sCacheKey, $biggest);
		}
	}

	/*
		Return the SQL statement
		to get all messages for this player
	*/
	private function getUserRightWhere ()
	{
		if (!isset ($this->sWhere))
		{
			$groups = array ();

			$this->sWhere = "(";

			if (!$this->user)
			{
				// Only allowed to see the public messages (0/0)
				$groups[self::CHAT_GROUP_ALL] = array (array ($this->channel), false);
			}

			else
			{
				// Always show your own message
				// or don't.
				//$this->sWhere .= 'chat.plid = '.$this->user->getId ().' OR ';

				// Allowed to see private messages and clan
				$groups[self::CHAT_GROUP_ALL] = array (array ($this->channel), false);
				$groups[self::CHAT_GROUP_USER] = array (array ($this->user->getId ()), true);

				$clans = $this->user->getClans ();
				if (count ($clans) > 0)
				{
					$groups[self::CHAT_GROUP_CLAN] = array (array (), true);

					foreach ($clans as $clan)
					{
						$groups[self::CHAT_GROUP_CLAN][0][] = $clan->getId ();
					}
				}
			}

			// Build the actual *where*
			foreach ($groups as $k => $v)
			{
				if (is_array ($v) && count ($v) > 0)
				{
					$this->sWhere .= "(chat.target_group = {$k} AND (";

					if ($v[1])
					{
						$this->sWhere .= "chat.plid = {$this->user->getId()} OR ";
					}

					foreach ($v[0] as $vv)
					{
						$this->sWhere .= "chat.target_id = {$vv} OR ";
					}
					$this->sWhere = substr ($this->sWhere, 0, -4).")) OR ";
				}
				else
				{
					$this->sWhere .= "chat.target_group = {$k} OR ";
				}
			}
			$this->sWhere = substr ($this->sWhere, 0, -4).")";
		}

		return $this->sWhere;
	}

	/*
		Returns the last 20 messages
	*/
	private function getLastMessages ($newStuff)
	{
		// Let's memcache this!
		$iLastMessage = $this->objCache->getCache ($this->sCacheKey);

		if (isset ($_SESSION['chat_channel_move']) && $_SESSION['chat_channel_move'])
		{
			$_SESSION['chat_channel_move'] = false;
			unset ($_SESSION['chat_channel_move']);
			return false;
		}

		// If iLastMessage is smaller then the stuff we want...
		if ($iLastMessage && $iLastMessage <= $newStuff)
		{
			return array ();
		}

		$db = Neuron_DB_Database::getInstance ();

		// Load the user rights
		$msgs = $db->query
		("
			SELECT
				chat.msgId,
				chat.msg,
				chat.datum,
				chat.plid,
				chat.target_group,
				chat.target_id,
				chat.mtype
			FROM
				chat
			WHERE
				chat.msgId > $newStuff AND
				{$this->getUserRightWhere()}
			ORDER BY
				chat.msgId ASC
			LIMIT
				20
		");

		return $msgs;
	}

	public function getRefresh ()
	{
		$db = Neuron_Core_Database::__getInstance ();

		$input = $this->getRequestData ();
		if (!isset ($input['channel']))
		{
			$this->switchChannel ($this->getDefaultChannel ());
		}
		else
		{
			$this->channel = intval ($input['channel']);
		}

		$data = $this->getRequestData ();
		$newStuff = $data['lastMessage'];

		$maxtime = NOW + 25;

		// Check for new messages
		$messages = $this->getLastMessages ($newStuff);
		if ($messages === false)
		{
			return;
		}

		// Close the session (lock)
		session_write_close ();

		// Only use persistent connection if we also use memcache
		// Otherwise it would stress out the database
		$usePersistence = self::USE_PERSISTENT_CONNECTIONS && defined ('MEMCACHE_IP');

		// Sleep until there are messages
		if ($usePersistence)
		{
			while (count ($messages) == 0 && time () < $maxtime)
			{
				// Check again
				$messages = $this->getLastMessages ($newStuff);

				if ($messages === false)
				{
					return;
				}

				// Sleep half a second
				//usleep (500);
				usleep (0.5 * 1000000);
			}
		}
		else
		{
			$messages = $this->getLastMessages ($newStuff);

			if ($messages == false)
			{
				return;
			}
		}

		// Debug check
		if (count ($messages) == 0)
		{
			return;
		}

		$page = new Neuron_Core_Template ();
		$i = 0;

		$login = Neuron_Core_Login::__getInstance ();
		$plid = $login->isLogin () ? $login->getUserId () : 0;

		$player = Neuron_GameServer::getPlayer ();

		foreach ($messages as $v)
		{
			$sender = Neuron_GameServer::getPlayer ($v['plid']);

			$biggest = $v['msgId'];

			if ($player && $player->isIgnoring ($v['plid']))
			{
				continue;
			}

			$i ++;

			$sTarget = null;
			$iTarget = null;

			$message = $v['msg'];

			/*
				const CHAT_GROUP_ALL = 0;
				const CHAT_GROUP_USER = 1;
				const CHAT_GROUP_CLAN = 2;
			*/

			switch ($v['target_group'])
			{
				case self::CHAT_GROUP_USER:
					$sClassname = 'message';
					$sTarget = Dolumar_Players_Player::getFromId ($v['target_id'])->getDisplayName ();

					$iTarget = $v['target_id'];
				break;

				case self::CHAT_GROUP_CLAN:
					$sClassname = 'clan';
				break;

				case self::CHAT_GROUP_ALL:
				default:

					switch ($v['mtype'])
					{
						case self::CHAT_CLASS_ME:
							$sClassname = 'all me';
						break;

						case self::CHAT_CLASS_REGULAR:
						default:
							$sClassname = 'all';
						break;
					}
				break;

			}

			$page->addListValue
			(
				'msgs',
				array
				(
					'message' => Neuron_Core_Tools::output_text ($message, true, true, false, false),
					'date' => date (self::DATE_FORMAT, $v['datum']),
					'nickname' => $sender->getDisplayName (),
					'plid' => $v['plid'],
					'class' => $sClassname,
					'target' => $sTarget,
					'targetId' => $iTarget,
					'isMine' => $v['plid'] == $plid
				)
			);
		}

		if ($i > 0)
		{
			// Shouldn't ever be true... but well, just to be sure.
			if ($biggest > $this->objCache->getCache ($this->sCacheKey))
			{
				$this->objCache->setCache ($this->sCacheKey, $biggest);
			}

			$this->addHtmlToElement ('chatdiv', $page->parse ('chatmsgs.tpl'), 'bottom');
		}

		if ($biggest > $newStuff)
		{
			$this->updateRequestData (array ('lastMessage' => $biggest, 'channel' => $this->channel));
		}
	}

}

?>


<?php

namespace PhalApi\Cache;

use PhalApi\Contracts\Cache;
use PhalApi\Exceptions\InternalServerError;

class FileCache implements Cache
{
    protected $folder;

    protected $prefix;

    public function __construct($config)
    {
        $this->folder = rtrim($config['path'], '/');

        $cacheFolder = $this->createCacheFileFolder();

        if (!is_dir($cacheFolder)) {
            mkdir($cacheFolder, 0777, true);
        }

        $this->prefix = isset($config['prefix']) ? $config['prefix'] : 'phapapi';
    }

    public function set($key, $value, $expire = 600)
    {
        if ($key === null || $key === '') {
            return;
        }

        $filePath = $this->createCacheFilePath($key);

        $expireStr = sprintf('%010d', $expire + time());
        if (strlen($expireStr) > 10) {
            throw new InternalServerError(
                T('file expire is too large')
            );
        }

        if (!file_exists($filePath)) {
            touch($filePath);
            chmod($filePath, 0777);
        }
        file_put_contents($filePath, $expireStr . serialize($value));
    }

    public function get($key)
    {
        $filePath = $this->createCacheFilePath($key);

        if (file_exists($filePath)) {
            $expireTime = file_get_contents($filePath, false, null, 0, 10);

            if ($expireTime > time()) {
                return @unserialize(file_get_contents($filePath, false, null, 10));
            }
        }

        return null;
    }

    public function delete($key)
    {
        if ($key === null || $key === '') {
            return;
        }

        $filePath = $this->createCacheFilePath($key);

        @unlink($filePath);
    }

    /**
     * 考虑到Linux同一目录下的文件个数限制，这里拆分成1000个文件缓存目录
     *
     * @param string $key 缓存key
     * @return string 路径
     */
    protected function createCacheFilePath($key)
    {
        $folderSufix = sprintf('%03d', hexdec(substr(sha1($key), -5)) % 1000);
        $cacheFolder = $this->createCacheFileFolder() . DIRECTORY_SEPARATOR . $folderSufix;
        if (!is_dir($cacheFolder)) {
            mkdir($cacheFolder, 0777, true);
        }

        return $cacheFolder . DIRECTORY_SEPARATOR . md5($key) . '.dat';
    }

    protected function createCacheFileFolder()
    {
        return $this->folder . DIRECTORY_SEPARATOR . 'cache';
    }
}


<?php
/**
 * Copyright (c) 2018 Wakers.cz
 *
 * @author Jiří Zapletal (http://www.wakers.cz, zapletal@wakers.cz)
 *
 */

namespace Wakers\StructureModule\Builder;

use Nette\Application\UI\Form;
use Nette\ComponentModel\IComponent;
use Nette\Forms\Controls\SelectBox;
use Nette\Forms\Controls\TextArea;
use Nette\Forms\Controls\TextInput;
use Nette\Forms\Controls\UploadControl;
use Nette\Utils\Json;
use Wakers\PageModule\Repository\PageRepository;
use Wakers\StructureModule\Database\Recipe;
use Wakers\StructureModule\Database\RecipeVariable;
use Wakers\StructureModule\Database\Structure;
use Wakers\StructureModule\Database\StructureValue;
use Wakers\StructureModule\Repository\StructureValueFileRepository;

class VariableFormBuilder implements IVariableFormBuilder
{
    /**
     * Cesty k templates
     */
    const
        TEMPLATE_PATH = __DIR__.'/../Component/Frontend/StructureModal/templates/variable/',
        DEFAULT_TEMPLATE_PATH = __DIR__.'/../Component/Frontend/StructureModal/templates/variable/text_plain.latte';

    /**
     * @var PageRepository
     */
    protected $pageRepository;

    /**
     * @var StructureValueFileRepository
     */
    protected $structureValueFileRepository;

    /**
     * Nastavuje se při volání buildComponent()
     * @var Recipe
     */
    protected $recipe;

    /**
     * Nastavuje se při volání buildComponent()
     * @var Structure
     */
    protected $structure;

    /**
     * Nastavuje se při volání buildComponent()
     * @var RecipeVariable
     */
    protected $recipeVariable;

    /**
     * Nastavuje se při volání buildComponent()
     * @var StructureValue
     */
    protected $structureValue;

    /**
     * Cashed array pro link_internal
     * @var array
     */
    protected $pages;

    /**
     * Cashed array pro files
     * @var array
     */
    protected $filesCountBySlug = [];

    /**
     * TODO: Remove dependencies, create component by component->create()
     * ValueFormBuilder constructor.
     * @param PageRepository $pageRepository
     * @param StructureValueFileRepository $structureValueFileRepository
     */
    public function __construct(
        PageRepository $pageRepository,
        StructureValueFileRepository $structureValueFileRepository
    ) {
        $this->pageRepository = $pageRepository;
        $this->structureValueFileRepository = $structureValueFileRepository;
    }

    /**
     * @param Recipe $recipe
     * @param RecipeVariable $recipeVariable
     * @param Structure|null $structure
     * @param StructureValue|NULL $structureValue
     * @return IComponent
     */
    public function buildComponent(
        Recipe $recipe,
        RecipeVariable $recipeVariable,
        ?Structure $structure,
        ?StructureValue $structureValue
    ) : IComponent
    {
        $this->recipe = $recipe;
        $this->structure = $structure;
        $this->recipeVariable = $recipeVariable;
        $this->structureValue = $structureValue;

        $type = strtolower($recipeVariable->getType());

        /** @var IComponent|TextInput|TextArea|UploadControl|SelectBox $component */
        $component = $this->$type();

        $path = self::TEMPLATE_PATH . strtolower($recipeVariable->getType()) . '.latte';

        if (!file_exists($path))
        {
            $path = self::DEFAULT_TEMPLATE_PATH;
        }

        $component->setOption('path', $path);
        $component->setOption('variable', $recipeVariable);

        return $component;
    }

    /**
     * @return TextInput
     */
    protected function text_plain() : TextInput
    {
        $component = new TextInput($this->recipeVariable->getLabel());
        $component = $this->setRequired($component);
        $component = $this->setPattern($component);

        if ($this->structureValue)
        {
            $component->setDefaultValue($this->structureValue->getContent());
        }

        return $component;
    }

    /**
     * @return TextArea
     */
    protected function text_formatted() : TextArea
    {
        $component = new TextArea($this->recipeVariable->getLabel());
        $component = $this->setRequired($component);
        $component = $this->setPattern($component);

        if ($this->structureValue)
        {
            $component->setDefaultValue($this->structureValue->getContent());
        }

        return $component;
    }

    /**
     * @return TextInput
     */
    protected function phone() : TextInput
    {
        $label = $this->recipeVariable->getLabel();
        $labelLow = strtolower($label);

        $component = new TextInput($label);
        $component = $this->setRequired($component);
        $component = $this->setPattern($component);

        $component->addRule(
            Form::PATTERN,
            "Pole '{$labelLow}' musí být v mezinárodním formátu. Př: +420 000 000 000.",
            '\+[0-9]{1,4}\s[0-9]{1,3}\s[0-9]{1,3}\s[0-9]{1,3}'
        );

        if ($this->structureValue)
        {
            $component->setDefaultValue($this->structureValue->getContent());
        }

        return $component;
    }

    /**
     * @return TextInput
     */
    protected function email() : TextInput
    {
        $label = $this->recipeVariable->getLabel();
        $labelLow = strtolower($label);

        $component = new TextInput($label);
        $component = $this->setRequired($component);
        $component = $this->setPattern($component);

        $component->addRule(
            Form::EMAIL,
            "Pole '{$labelLow}' musí být platná e-mailová adresa."
        );

        if ($this->structureValue)
        {
            $component->setDefaultValue($this->structureValue->getContent());
        }

        return $component;
    }

    /**
     * @return TextInput
     */
    protected function date() : TextInput
    {
        $label = $this->recipeVariable->getLabel();
        $labelLow = strtolower($label);

        $component = new TextInput($label);
        $component = $this->setRequired($component);
        $component = $this->setPattern($component);

        $component->addRule(
            Form::PATTERN,
            "Pole '{$labelLow}' musí být ve formátu: 24.8.2018.",
            '([1-9]|1[0-9]|2[0-9]|3[0-1])\.([1-9]|1[0-2])\.([0-2]{1}[0-9]{3})'
        );

        if ($this->structureValue)
        {
            $component->setDefaultValue($this->structureValue->getContent());
        }

        return $component;
    }

    /**
     * @return TextInput
     */
    protected function datetime() : TextInput
    {
        $label = $this->recipeVariable->getLabel();
        $labelLow = strtolower($label);

        $component = new TextInput($label);
        $component = $this->setRequired($component);
        $component = $this->setPattern($component);

        $component->addRule(
            Form::PATTERN,
            "Pole '{$labelLow}' musí být ve formátu: 24.8.2018 08:59",
            '([1-9]|1[0-9]|2[0-9]|3[0-1])\.([1-9]|1[0-2])\.([0-2]{1}[0-9]{3})\040(0[0-9]|1[0-9]|2[0-3])\:(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])'
        );

        if ($this->structureValue)
        {
            $component->setDefaultValue($this->structureValue->getContent());
        }

        return $component;
    }

    /**
     * @return SelectBox
     * @throws \Propel\Runtime\Exception\PropelException
     */
    protected function link_internal() : SelectBox
    {
        $component = new SelectBox($this->recipeVariable->getLabel());
        $component = $this->setRequired($component);
        $component = $this->setPattern($component);

        $items = $this->getPages();
        $component->setItems($items);

        if ($this->structureValue)
        {
            $component->setDefaultValue($this->structureValue->getLinkToUrlId());
        }

        return $component;
    }

    /**
     * @return TextInput
     */
    protected function link_external() : TextInput
    {
        $label = $this->recipeVariable->getLabel();
        $labelLow = strtolower($label);

        $component = new TextInput($label);
        $component = $this->setRequired($component);
        $component = $this->setPattern($component);

        $component->addRule(
            Form::PATTERN,
            "Pole '{$labelLow}' musí být platný HTTP/s odkaz.",
            '(https?\:\/\/)(.{4,247})'
        );

        $component->addRule(
            Form::MAX_LENGTH,
            "Pole '{$labelLow}' může obsahovat maximálně %d znaků.",
            255
        );

        if ($this->structureValue)
        {
            $component->setDefaultValue($this->structureValue->getContent());
        }

        return $component;
    }

    /**
     * @return UploadControl
     * @throws \Nette\Utils\JsonException
     * @throws \Propel\Runtime\Exception\PropelException
     */
    protected function files() : UploadControl
    {
        $label = $this->recipeVariable->getLabel();
        $labelLow = strtolower($label);

        $component = new UploadControl($label, TRUE);
        $component = $this->setPattern($component);
        $component->setRequired(FALSE);

        $types = Json::decode($this->recipeVariable->getAllowedTypes(), Json::FORCE_ARRAY);

        $mimes = [];
        $extensions = [];

        foreach ($types as $extension => $mimeType)
        {
            if (!in_array($mimeType, $mimes))
            {
                $mimes[] = $mimeType;
            }

            if (!in_array($extension, $extensions))
            {
                $extensions[] = $extension;
            }
        }

        $component->addRule(
            Form::MIME_TYPE,
            "Všechny soubory v poli '{$labelLow}' musí mít mime-type: " . implode(', ', $mimes),
            $mimes
        );

        $implodedExtensions = implode('|', $extensions);

        $component->addRule(
            Form::PATTERN,
            "Všechny soubory v poli '{$labelLow}' musí mít koncovku: " . implode(', ', $extensions),
            ".*\.({$implodedExtensions})"
        );

        // Max velikosti dle PHP
        $iniMaxUpFiles = ini_get('max_file_uploads'); // Count
        $iniMaxSize = min((int) ini_get('upload_max_filesize'), (int) ini_get('post_max_size')); // Max request size in MB

        // Max velikost souboru uložená v DB
        $maxFileSize = $this->recipeVariable->getMaxFileSize(); // MB / NULL

        // Velikost pro jeden nahrávaný soubor
        $maxSize = $iniMaxSize / $iniMaxUpFiles ; // MB

        // Nastav velikost pro jeden nahrávaný soubor dle DB
        if ($maxFileSize > 0)
        {
            $maxSize = $maxFileSize; // MB
        }

        // Přidej pravidlo pro max velikost souboru
        $component->addRule(
            Form::MAX_FILE_SIZE,
            "Maximální velikost jednoho souboru v poli '{$labelLow}' může být " . round($maxSize, 2) ." MB.",
            $maxSize * 1024 * 1024 // bytes
        );

        // Nastav maximální počet nahrávaných souborů dle PHP
        $maxUpFiles = $iniMaxUpFiles;

        // Nastav maximální počet nahrávaných souborů když př (500 mb / 50 < 20mb)
        if ($iniMaxSize / $iniMaxUpFiles < $maxSize)
        {
            // ~ 500 / 20 = 25
            $maxUpFiles = (int) ($iniMaxSize / $maxSize);
        }

        // Přidej pravidlo pro max uploadovaných souborů
        $component->addRule(
            Form::MAX_LENGTH,
            "Pole '{$labelLow}' může najednou nahrávat maximálně %d souborů/y.",
            $maxUpFiles
        );

        // Maximální počet souborů v políčku
        $maxFiles = $this->recipeVariable->getMaxFiles();

        if ($maxFiles > 0)
        {
            $inDb = $this->getFilesCount($this->recipeVariable->getSlug());
            $available = $maxFiles - $inDb;

            $component->addRule(
                Form::MAX_LENGTH,
                "V poli '{$labelLow}' lze nahrát už jen %d soubory/ů.",
                $available
            );
        }

        return $component;
    }

    /**
     * @return UploadControl
     * @throws \Nette\Utils\JsonException
     * @throws \Propel\Runtime\Exception\PropelException
     */
    protected function images() : UploadControl
    {
        $component = $this->files();

        return $component;
    }

    /**
     * @return SelectBox
     * @throws \Nette\Utils\JsonException
     */
    protected function select_box() : SelectBox
    {
        $component = new SelectBox($this->recipeVariable->getLabel());
        $component = $this->setRequired($component);
        $component = $this->setPattern($component);

        $items = Json::decode($this->recipeVariable->getItems(), Json::FORCE_ARRAY);

        $component->setItems($items);

        if ($this->structureValue)
        {
            $component->setDefaultValue($this->structureValue->getContent());
        }

        return $component;
    }

    /**
     * @param IComponent|TextInput|TextArea|UploadControl|SelectBox $IComponent
     * @return IComponent|TextInput|TextArea|UploadControl|SelectBox
     */
    protected function setRequired(IComponent $IComponent) : IComponent
    {
        $IComponent->setRequired(FALSE);

        if ($this->recipeVariable->getIsRequired())
        {
            $label = strtolower($this->recipeVariable->getLabel());
            $IComponent->setRequired("Pole '{$label}' je povinné.");
        }

        return $IComponent;
    }

    /**
     * @param IComponent|TextInput|TextArea|UploadControl|SelectBox $IComponent
     * @return IComponent|TextInput|TextArea|UploadControl|SelectBox
     */
    protected function setPattern(IComponent $IComponent) : IComponent
    {
        if ($this->recipeVariable->getRegexPattern())
        {
            $IComponent->addRule(Form::PATTERN, $this->recipeVariable->getRegexMessage(), $this->recipeVariable->getRegexPattern());
        }

        return $IComponent;
    }

    /**
     * TODO: load in Form Control
     * Cashed SQL
     * @param string $slug
     * @return int
     * @throws \Propel\Runtime\Exception\PropelException
     */
    public function getFilesCount(string $slug)
    {
        if (/*!$this->filesCountBySlug &&*/ $this->structure)
        {
            $result = [];

            $files = $this->structureValueFileRepository
                ->findByRecipeAndStructure($this->recipe, $this->structure);

            foreach ($files as $structureValueFile)
            {
                $dbSlug = $structureValueFile->getStructureValue()->getRecipeVariable()->getSlug();
                $result[$dbSlug][] = $structureValueFile;
            }

            $this->filesCountBySlug = $result;
        }

        if (key_exists($slug, $this->filesCountBySlug))
        {
            return count($this->filesCountBySlug[$slug]);
        }

        return 0;

    }

    /**
     * TODO: load in Form Control
     * Cashed SQL
     * @return array
     * @throws \Propel\Runtime\Exception\PropelException
     */
    protected function getPages()
    {
        if (!$this->pages)
        {
            $items = [0 => 'Žádný odkaz'];

            $roots = $this->pageRepository->findAllJoinUrl();

            foreach ($roots as $root)
            {
                $lang = $root->getPageUrl()->getLang();
                $tree = $this->pageRepository->findAllByLevelNameByLangAsTree($lang, TRUE);
                $pages = $this->pageRepository->findAllByLevelNameByLang($tree, TRUE);

                foreach ($pages as $page)
                {
                    $items[$page->getId()] = str_repeat('––', $page->getLevel() - 2) . ' ' . $page->getName();
                }
            }

            $this->pages = $items;
        }

        return $this->pages;
    }
}


<?php

/*
 * This file is part of the Worker package.
 *
 * (c) EXSyst
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace EXSyst\Component\Worker\Internal;

use EXSyst\Component\Worker\Exception;
use stdClass;

class KillSwitch
{
    /**
     * @var string
     */
    private $path;
    /**
     * @var stdClass
     */
    private $data;

    /**
     * @param string $path
     */
    public function __construct($path)
    {
        $this->path = $path;
        $data = @json_decode(file_get_contents($path));
        if (!is_object($data)) {
            $data = new stdClass();
        }
        if (!isset($data->global)) {
            $data->global = false;
        }
        if (!isset($data->addresses) || !is_array($data->addresses)) {
            $data->addresses = [];
        }
        $this->data = $data;
    }

    /**
     * @return string
     */
    public function getPath()
    {
        return $this->path;
    }

    /**
     * @throws Exception\RuntimeException
     *
     * @return $this
     */
    public function save()
    {
        $dir = dirname($this->path);
        if (!is_dir($dir)) {
            mkdir($dir, 0777, true);
        }
        if (file_put_contents($this->path, json_encode($this->data)) === false) {
            throw new Exception\RuntimeException("Can't save the kill switch file");
        }

        return $this;
    }

    /**
     * @param bool $global
     *
     * @return $this
     */
    public function setGlobal($global)
    {
        $this->data->global = $global;

        return $this;
    }

    /**
     * @return bool
     */
    public function getGlobal()
    {
        return $this->data->global;
    }

    /**
     * @param array $addresses
     *
     * @return $this
     */
    public function setAddresses(array $addresses)
    {
        $this->data->addresses = $addresses;

        return $this;
    }

    /**
     * @param string $address
     *
     * @return $this
     */
    public function addAddress($address)
    {
        if (!$this->hasAddress($address)) {
            $this->data->addresses[] = $address;
        }

        return $this;
    }

    /**
     * @param string $address
     *
     * @return $this
     */
    public function removeAddress($address)
    {
        $key = array_search($address, $this->data->addresses, true);
        if ($key !== false) {
            array_splice($this->data->addresses, $key, 1);
        }

        return $this;
    }

    /**
     * @return array
     */
    public function getAddresses()
    {
        return $this->data->addresses;
    }

    /**
     * @param string $address
     *
     * @return bool
     */
    public function hasAddress($address)
    {
        return array_search($address, $this->data->addresses, true) !== false;
    }
}


<?php
/**
 *  Dolumar engine, php/html MMORTS engine
 *  Copyright (C) 2009 Thijs Van der Schaeghe
 *  CatLab Interactive bvba, Gent, Belgium
 *  http://www.catlab.eu/
 *  http://www.dolumar.com/
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

class Neuron_Core_Tools
{

	/*
		Resources to text
	*/
	public static function getRandomRuneOptions ()
	{
		return array
		(
			'earth',
			'fire',
			'water',
			'wind'
		);
	}

	public static function output_distance ($distance, $abbrevation = false, $round = false)
	{
		if ($distance === false)
		{
			return null;
		}
		else
		{
			$distance = Dolumar_Map_Map::tile2league ($distance);

			if ($round)
			{
				$distance = round ($distance);
			}
			else
			{
				$distance = round ($distance, 1);

				if ($distance == floor ($distance))
				{
					$distance .= '.0';
				}
			}

			return $distance . ($abbrevation ? 'L' : ' league');
		}
	}

	/*
		Modern version of the function.
	*/
	public static function getResourceToText ($resources, $income = array (), $capacity = array (), $premiumlinks = false)
	{
		return self::resourceToText
		(
			$resources,
			true,
			true,
			false,
			'rune',
			true,
			$income,
			$capacity,
			$premiumlinks
		);
	}

	public static function resourceToText
	(
		$res,
		$showRunes = true,
		$dot = true,
		$village = false,
		$runeId = 'rune',
		$html = true,
		$income = array (),
		$capacity = array (),
		$premiumlinks = false
	)
	{
		$text = Neuron_Core_Text::__getInstance ();

		$txt = '';
		$o = array ();

		if (isset ($res['gold']) && $res['gold'] > 0) 	{ $o[] = 'gold'; }
		if (isset ($res['grain']) && $res['grain'] > 0) { $o[] = 'grain'; }
		if (isset ($res['wood']) && $res['wood'] > 0) 	{ $o[] = 'wood'; }
		if (isset ($res['stone']) && $res['stone'] > 0)	{ $o[] = 'stone'; }
		if (isset ($res['iron']) && $res['iron'] > 0)	{ $o[] = 'iron'; }
		if (isset ($res['gems']) && $res['gems'] > 0)	{ $o[] = 'gems'; }

		$end = count ($o) - 1;

		if ($html)
		{
			$txt = '';
		}

		foreach ($o as $k => $v)
		{
			if ($html)
			{
				$sText = 'get ($v, 'resources', 'main')).'"> ';
				if (isset ($income[$v]))
				{
					$sInc = $income[$v] >= 0 ? '+'.$income[$v] : $income[$v];

					if (isset ($capacity[$v]))
					{
						$sInc .= '/'.$capacity[$v];
					}

					$sText .= '';

					if ($premiumlinks)
					{
						$sText .= '';

						$sText .= $res[$v];
						$sText .= '';
					}
					else
					{
						$sText .= $res[$v];
					}

					$sText .= '';
				}
				else
				{
					$sText .= $res[$v];
				}
				$sText .= ' '.ucfirst ($text->get ($v, 'resources', 'main')) . '';
				$sText .= '';

			}
			else
			{
				$sText = $res[$v] . ' ' . $text->get ($v, 'resources', 'main');
			}

			if ($k < $end)
			{
				$txt .= $html ? $sText . ', ' : $sText . ', ';
			}

			elseif ($end == 0 && $dot)
			{
				$txt .= $html ? $sText . '. ' : $sText . '. ';
			}

			elseif ($end == 0)
			{
				$txt .= $sText;
			}

			else
			{
				if ($html)
				{
					$txt = substr ($txt, 0, -28) . ' ' . $text->get ('and', 'main', 'main') . ' ';
				}
				else
				{
					$txt = substr ($txt, 0, -2) . ' ' . $text->get ('and', 'main', 'main') . ' ';
				}

				$txt .= $sText;
				if ($dot)
				{
					$txt .= $html ? '. ' : '. ';
				}
			}
		}

		if ($html)
		{
			$txt .= '';
		}

		//if (!$dot) { $txt = substr ($txt, 0, -2); }
		if (!empty ($res['runeId']) && $res['runeAmount'] > 0 && $showRunes)
		{
			// Get village runes
			if ($village)
			{
				$myRunes = $village->resources->getRunes ();
			}
			if ($res['runeId'] == 'random' && $html)
			{
				$txt .= '
<select class="selectRune building_'.$runeId.'" name="runeSelection">';

				$runes = self::getRandomRuneOptions ();

				$txt .= '<option value="random">'.$text->get ('random', 'runeSingle', 'main').'</option>';

				foreach ($runes as $v)
				{
					$sRune = $text->get ($v, $res['runeAmount'] > 1 ? 'runeDouble' : 'runeSingle', 'main');

					$t = Neuron_Core_Tools::putIntoText
					(
						$text->get ('requires', 'build', 'building'),
						array
						(
							$res['runeAmount'].' '.$sRune
						)
					);

					if ($village && isset ($myRunes[$v]) && $myRunes[$v] >= $res['runeAmount'])
					{
						$txt .= '<option class="hasRunes" value="' .$v. '">'.$t.'</option>';
					}

					elseif ($village)
					{
						$txt .= '<option class="hasntRunes" value="' .$v. '">'.$t.'</option>';
					}

					else
					{
						$txt .= '<option value="' .$v. '">'.$t.'</option>';
					}
				}

				$txt .= '</select>';
			}

			elseif ($html)
			{
				$sRune = $text->get ($res['runeId'], $res['runeAmount'] > 1 ? 'runeDouble' : 'runeSingle', 'main');

				$t = Neuron_Core_Tools::putIntoText
				(
					$text->get ('requires', 'build', 'building'),
					array
					(
						''.
						$res['runeAmount'].' '.$sRune.''
					)
				);

				if ($village && isset ($myRunes[$res['runeId']]) && $myRunes[$res['runeId']] >= $res['runeAmount'])
				{
					$txt .= '
' . $t . '';
				}
				else
				{
					$txt .= '
' . $t . '';
				}
			}

			else
			{
				$sRune = $text->get ($res['runeId'], $res['runeAmount'] > 1 ? 'runeDouble' : 'runeSingle', 'main');

				$t = Neuron_Core_Tools::putIntoText
				(
					$text->get ('requires', 'build', 'building'),
					array
					(
						$res['runeAmount'].' '.$sRune
					)
				);

				if ($village && isset ($myRunes[$res['runeId']]) && $myRunes[$res['runeId']] >= $res['runeAmount'])
				{
					$txt .= "\n" . $t;
				}
				else
				{
					$txt .= "\n" . $t;
				}
			}
		}

		return $txt;
	}

	/*
		Translate a mysql date - field to a unix timestamp.
		Returns false if date is not set.
	*/
	public static function dateToTimestamp ($date)
	{
		$db = Neuron_DB_Database::__getInstance ();
		return $db->toUnixtime ($date);

		/*
		return $date != '0000-00-00' ?
			gmmktime (

				0,
				0,
				1,
				substr ($date, 5, 2),
				substr ($date, 8, 2),
				substr ($date, 0, 4)

		): false;
		*/
	}

	public static function datetimeToTimestamp ($date)
	{
		$db = Neuron_DB_Database::__getInstance ();
		return $db->toUnixtime ($date);
		//return strtotime ($date);
	}

	/*
		This one is total bullshit.
	*/
	/*
	public static function dateToMysql ($day, $month, $year)
	{
		return self::addZeros ($year, 4).'-'.self::addZeros ($month, 2).'-'.self::addZeros ($day, 2);
	}
	*/

	/*
		This one even more
	*/
	/*
	public static function datetimeToMysql ($day, $month, $year, $hour, $minute, $seconds)
	{
		return self::addZeros ($year, 4).
			'-'.self::addZeros ($month, 2).
			'-'.self::addZeros ($day, 2)
			.' '.self::addZeros ($hour, 2)
			.':'.self::addZeros ($minute, 2).
			':'.self::addZeros ($seconds, 2);

	}
	*/

	public static function timestampToMysql ($time = null)
	{
		if ($time == null)
		{
			$time = time ();
		}

		$db = Neuron_DB_Database::__getInstance ();
		return $db->fromUnixtime ($time);
		//return self::dateToMysql (date ('d', $time), date ('m', $time), date ('Y', $time));

	}

	public static function timestampToMysqlDatetime ($time = null)
	{
		if ($time == null)
		{
			$time = time ();
		}

		$db = Neuron_DB_Database::__getInstance ();
		return $db->fromUnixtime ($time);

		//return self::datetimeToMysql (date ('d', $time), date ('m', $time), date ('Y', $time),
		//	date ('H', $time), date ('i', $time), date ('s', $time));

	}

	public static function getArrayFirstValue ($a)
	{
		foreach ($a as $k => $v)
			return array ($k, $v);
	}

	public static function addZeros ($int, $totaal)
	{
		while (strlen ($int) < $totaal)
		{
			$int = "0".$int;
		}
		return $int;
	}

	public static function getInput ($dat, $key, $type, $default = false)
	{

		global $$dat;
		$dat = $$dat;

		if (!isset ($dat[$key])) {

			return $default;
		}

		else {
			// Check if the value has the right type
			if (Neuron_Core_Tools::checkInput ($dat[$key], $type))
			{
				return $dat[$key];
			}

			else
			{
				return $default;
			}
		}
	}

	public static function checkInput ($value, $type)
	{
		if ($type == 'bool' || $type == 'text')
		{

			return true;

		}

		elseif ($type == 'varchar')
		{
			return true;
		}

		elseif ($type == 'password')
		{
			return strlen ($value) > 2;
		}

		elseif ($type == 'email')
		{
			return strlen ($value) > 2;
		}

		elseif ($type == 'username')
		{
			return preg_match ('/^[a-zA-Z0-9_]{3,20}$/', $value);
		}

		elseif ($type == 'village')
		{
			$chk = preg_match ('/^[a-zA-Z0-9\' ]{3,40}$/', $value);
			$value = trim ($value);
			$notempty = !empty ($value);
			$chk = $chk && $notempty;
			return $chk;
		}

		elseif ($type == 'unitname')
		{
			$chk = preg_match ('/^[a-zA-Z0-9 ]{3,20}$/', $value);
			$value = trim ($value);
			$notempty = !empty ($value);
			$chk = $chk && $notempty;
			return $chk;
		}

		elseif ($type == 'md5')
		{

			return strlen ($value) == 32;

		}

		elseif ($type == 'int')
		{

			return is_numeric ($value);

		}

		else {

			return false;
			echo 'fout: '.$type;

		}

	}

	public static function convert_price ($basic_price)
	{

		$basic_price = str_replace (",", ".", $basic_price);
		$basic_price = number_format ($basic_price, 2, ",", "");

		return $basic_price;

	}

	public static function putIntoText ($text, $ar = array(), $delimiter = '@@')
	{
		foreach ($ar as $k => $v)
		{
			if (is_string ($v) || is_float ($v) || is_int ($v))
			{
				$text = str_replace ($delimiter.$k, $v, $text);
			}
			else if (is_object ($v))
			{
				$text = str_replace ($delimiter.$k, (string)$v, $text);
			}
			else
			{
				throw new Exception ("putIntoText excepts an array.");
			}
		}

		// Remove all remaining "putIntoTexts"
		$text = preg_replace ('/'.$delimiter.'([^ ]+)/s', '', $text);

		return $text;
	}

	public static function output_title ($title)
	{

		return htmlspecialchars ($title, ENT_QUOTES, 'UTF-8');

	}

	public function date_long ($stamp)
	{

		$text = Neuron_Core_Text::__getInstance ();

		$dag = $text->get ('day'.(date ('w', $stamp) + 1), 'days', 'main');
		$maand = $text->get ('mon'.date ('m', $stamp), 'months', 'main');

		return Neuron_Core_Tools::putIntoText (
			$text->get ('longDateFormat', 'dateFormat', 'main'),
			array
			(
				$dag,
				date ('d', $stamp),
				$maand,
				date ('Y', $stamp)
			)
		);

	}

	public static function splitLongWords ($input)
	{

		$array = explode (' ', $input);

		foreach ($array as $k => $v)
		{

			$array[$k] = wordwrap ($v, 20, ' ', 1);

		}

		return implode (' ', $array);

	}

	public static function output_text ($convert, $tags = true, $div = true, $list = true, $layout = true)
	{
		return Neuron_NBBC_Parser::parse ($convert);

		//$input = Neuron_Core_Tools::splitLongWords ($input);
		/*

		$convert = htmlspecialchars ($convert, ENT_QUOTES, 'UTF-8');

		// Config: breaks:
		$p_open = '
';
		$p_close = '
';
		$p_break = '
';

		if ($tags)
		{
			$codeDoorgeven = array ();

			$codes = array ();

			// codes eruit halen
			preg_match_all ("/\[code\](.*?)\[\/code\]/is", $convert, $codes);

			$count = 0;

			foreach($codes[0] as $nor => $var1)
			{
				$replace = '[tmp-code-block]'.$count.'[/tmp-code-block]';
				$pom = $codes[0][$nor];
				$convert = str_replace ($pom, $replace, $convert);

				$codeDoorgeven[$count] = $codes[1][$nor];
				$count ++;
			}

			$bbcode_regex = array
			(
				 0 => '/\[b\](.+?)\[\/b\]/s',
				 1 => '/\[i\](.+?)\[\/i\]/s',
				 2 => '/\[u\](.+?)\[\/u\]/s',
				 5 => '/\[url\](.+?)\[\/url\]/s',
				 6 => '/\[url\=(.+?)\](.+?)\[\/url\]/s',
				 7 => '/\[img\](.+?)\[\/img\]/s',
				 8 => '/\[img\=noresize\](.+?)\[\/img\]/s',
				 9 => '/\[help\](.+?)\[\/help\]/s',
				10 => '/\[open\=(.+?)\](.+?)\[\/open\]/s',
				11 => "/\[quote\](.*?)\[\/quote\]/s"
			);

			if ($layout)
			{
				$bbcode_regex = array_merge
				(
					$bbcode_regex,
					array
					(
						100 => '/\[col\=(.+?)\](.+?)\[\/col\]/s',
						101 => '/\[color\=(.+?)\](.+?)\[\/color\]/s',
						102 => '/\[colour\=(.+?)\](.+?)\[\/colour\]/s',
						103 => '/\[size\=(.+?)\](.+?)\[\/size\]/s'
					)
				);
			}

			$bbcode_replace = array
			(
				 0 => '$1',
				 1 => '$1',
				 2 => '$1',
				 5 => '$1',
				 6 => '$2',
				 7 => '',
				 8 => '',
				 9 => '$1',
				10 => '$2',
				11 => '

$1

',

				100 => '$2',
				101 => '$2',
				102 => '$2',
				103 => '$2'
			);

			$convert = preg_replace ($bbcode_regex, $bbcode_replace, $convert);

			//$convert = str_replace("[/quote]", "
" . $p_open, $convert);

			// Headers
			if ($layout)
			{
				$convert = preg_replace (
					"/\[h(.*?)](.*?)\[\/h(.*?)]/si",
					'<h\\1>\\2</h\\1>',
					$convert
				);
			}

			// Hyperlinks
			$convert = eregi_replace(
				"\[url]([^\[]*)\[/url]",
				"\\1", $convert);

			$convert = eregi_replace(
				"\[url=([^\[]*)\]([^\[]*)\[/url]",
				"\\2", $convert);

			// Images align=left
			$convert = eregi_replace(
				"\[img]([-_./a-zA-Z0-9!&%#?,'=:~]+)\[/img]",
				"", $convert);

			// Images align=left
			$convert = eregi_replace(
				"\[img:([-_./a-zA-Z0-9!&%#?,'=:~]+)\]([-_./a-zA-Z0-9!&%#?,'=:~]+)\[/img]",
				"", $convert);

			// codes erin steken
			foreach($codeDoorgeven as $a => $b)
			{
				$sk = '[tmp-code-block]'.$a.'[/tmp-code-block]';
				$replace = $b;
				$convert = str_replace ($sk, $replace, $convert);
			}
		}

		// Lists (*)
		$convert = self::textToParagraph ($convert, $list);

		if ($tags)
		{
			// Let's go for the smileys
			$smileys = array
			(
				':)' 	=> 'smile',
				':-)'	=> 'smile',

				':('	=> 'sad',
				':-('	=> 'sad',

				':D'	=> 'grin',
				':-D'	=> 'grin',

				':P' 	=> 'tease',
				':-P' => 'tease',
				':p' 	=> 'tease',
				':-p'	=> 'tease',

				';)'	=> 'wink',
				';-)'	=> 'wink',

				':|'	=> 'frown',
				':-|'	=> 'frown',

				'[:/]'	=> 'unsure',
				'[:-/]'	=> 'unsure',

				':@'	=> 'angry',
				':-@'	=> 'angry'
			);

			foreach ($smileys as $k => $v)
			{
				$convert = str_replace ($k, '', $convert);
				$convert = str_replace ('['.$k.']', '', $convert);
			}
		}

		if ($div)
		{
			$convert = '
'.$convert.'
';
		}

		return $convert;
		*/
	}

	public static function textToParagraph ($convert, $showLists = true)
	{
		$lines = explode ("\n", $convert);

		$convert = "";

		$inList = false;
		$inPa = false;

		foreach ($lines as $v)
		{
			$v = trim ($v);

			if (substr ($v, 0, 1) == '*' && $showLists)
			{
				if (!$inList)
				{
					if ($inPa)
					{
						$convert .= '
';
						$inPa = false;
					}

					$convert = $convert . '
';
					$inList = true;
				}

				$convert .= '
'.substr ($v, 1).'
';
			}
			else
			{
				if ($inList)
				{
					$convert .= '
';
					$inList = false;
				}

				// Block elements don't need paragraphcs
				if (substr ($v, 0, 2) == '<h')
				{
					if ($inPa)
					{
						$convert .= '
';
					}

					$convert .= $v;
				}

				// Regular text
				else
				{
					if (empty ($v))
					{
						if ($inPa)
						{
							$convert .= '
';
							$inPa = false;
						}
					}

					else
					{
						if (!$inPa)
						{
							$convert .= '
';
							$inPa = true;
						}

						$convert .= $v . '
';
					}
				}
			}
		}

		if ($inList)
		{
			$convert .= '
';
		}

		elseif ($inPa)
		{
			$convert .= '
';
		}

		$convert = str_replace ('

', '
', $convert);
		$convert = str_replace ('

', '
', $convert);
		$convert = str_replace ('

', '', $convert);

		return $convert;
	}

	public static function output_form ($text)
	{

		return htmlspecialchars (($text) , ENT_QUOTES, 'UTF-8');

	}

	public static function output_varchar ($text)
	{

		$input = Neuron_Core_Tools::splitLongWords ($text);
		return htmlspecialchars (($text), ENT_QUOTES, 'UTF-8');

	}

	public static function color_mkwebsafe ( $in )
	{
		// put values into an easy-to-use array
		$vals['r'] = hexdec( substr($in, 0, 2) );
		$vals['g'] = hexdec( substr($in, 2, 2) );
		$vals['b'] = hexdec( substr($in, 4, 2) );

		// loop through
		foreach( $vals as $val )
		{
		// convert value
		$val = ( round($val/51) * 51 );
		// convert to HEX
		$out .= str_pad(dechex($val), 2, '0', STR_PAD_LEFT);
		}

		return $out;
	}

	public static function getConfirmLink ()
	{

		return 'confirmed';

	}

	public static function checkConfirmLink ($link)
	{
		return ($link == self::getConfirmLink ());
	}

	public static function getCountdown ($future, $class = 'counter')
	{
		$timeLeft = $future - time () + 1;

		$hours = floor ($timeLeft / 3600);
		$minutes = floor (($timeLeft - $hours * 3600) / 60);
		$seconds = $timeLeft - $hours * 3600 - $minutes * 60;

		if ($hours < 10 && $hours >= 0) $hours = '0'.$hours;
		if ($minutes < 10 && $minutes >= 0) $minutes = '0'.$minutes;
		if ($seconds < 10 && $seconds >= 0) $seconds = '0'.$seconds;

		return ''.$hours.':'.$minutes.':'.$seconds.'';
	}

	public static function getDuration ($duration)
	{
		$hours = floor ($duration / 3600);
		$minutes = floor ( ($duration - $hours * 3600) / 60 );
		$seconds = floor ( $duration - $hours * 3600 - $minutes * 60 );

		if ($hours < 10) { $hours = '0' . $hours; }
		if ($minutes < 10) { $minutes = '0' . $minutes; }
		if ($seconds < 10) { $seconds = '0' . $seconds; }

		if ($hours > 0)
		{
			$dur = $hours . ':' . $minutes . ':' . $seconds;
		}

		else
		{
			$dur = $minutes . ':' . $seconds;
		}

		return $dur;
	}

	public static function getDurationText ($duration, $short = false)
	{
		$text = Neuron_Core_Text::__getInstance ();

		$space = " ";
		$gName = 'datetime';
		if ($short)
		{
			$gName .= '_short';
			$space = "";
		}

		$day = 24 * 60 * 60;
		$hour = 60 * 60;
		$minute = 60;

		$days = floor ($duration / $day);
		$duration -= $days * $day;

		$hours = floor ($duration / $hour);
		$duration -= $hours * $hour;

		$minutes = floor ($duration / $minute);
		$duration -= $minutes * $minute;

		$seconds = $duration;

		$txt = null;

		if ($days > 1)
			$txt .= $days .$space.$text->get ('days', $gName, 'main').", ";
		elseif ($days > 0)
			$txt .= $days .$space.$text->get ('day', $gName, 'main').", ";

		if ($hours > 1)
			$txt .= $hours .$space.$text->get ('hours', $gName, 'main').", ";
		elseif ($hours > 0)
			$txt .= $hours .$space.$text->get ('hour', $gName, 'main').", ";

		if ($minutes > 1)
			$txt .= $minutes .$space.$text->get ('minutes', $gName, 'main').", ";
		elseif ($minutes > 0)
			$txt .= $minutes .$space.$text->get ('minute', $gName, 'main').", ";

		if ($seconds > 1)
			$txt .= $seconds .$space.$text->get ('seconds', $gName, 'main').", ";
		elseif ($seconds > 0)
			$txt .= $seconds .$space.$text->get ('second', $gName, 'main').", ";

		return substr ($txt, 0, -2);
	}

	public static function checkIE6 ()
	{
		if (isset ($_SERVER['HTTP_USER_AGENT']))
		{
			$ua = $_SERVER['HTTP_USER_AGENT'];
			if (strpos($ua,'MSIE') != false && strpos($ua,'Opera') === false)
			{
				$false = true;
				if (strpos($ua,'Windows NT 5.2') != false) {
					if(strpos($ua,'.NET CLR') === false) $false = false;
				}

				if (substr($ua,strpos($ua,'MSIE')+5,1) < 7 && $false)
				{
					return true;
				}
			}
		}
		return false;
	}

	public static function floor_array ($array)
	{
		foreach ($array as $k => $v)
		{
			$array[$k] = floor ($v);
		}
		return $array;
	}

	public static function splitInPages
	(
		$page,
		$total,
		$current = 0,
		$perpage = 10,
		$maxAantalSnelclicks = 10,
		$action = '',
		$module = 'module',
		$pagetoken = 'page'
	)
	{
		$pages = ceil ($total / $perpage);

		$maxAantalSnelclicks --;

		if ($current < 1)
		{
			$current = 1;
		}

		$deHelft = floor ($maxAantalSnelclicks / 2);
		if ($current < $deHelft)
		{
			$snelcount = 1;
			$morevar = $deHelft - $current + 1;
		}

		else
		{
			$snelcount = $current - $deHelft;
			$morevar = $deHelft;
		}

		if ($current > ($pages - $deHelft) && $current > $deHelft)
		{
			$snelvar = $pages - $current;
			$snelcount = $snelcount - ($morevar - $snelvar);
		}

		if ($snelcount < 1)
		{
			$snelcount = 1;
		}

		$snelmax = $snelcount + $maxAantalSnelclicks;

		// replace the stuff
		$pS = $snelcount;
		$pE = min ($snelmax, $pages);

		$page->set ('pagelist_curpage', $current);
		$page->set ('pagelist_total', $pages);
		$page->set ('pagelist_start', $pS);
		$page->set ('pagelist_end', $pE);

		$page->set ('pagelist_firstpage', 1);
		$page->set ('pagelist_lastpage', $pages);

		// Action data
		$l_action = $action;

		if (!is_array ($action))
		{
			$l_action = array ();
			$tmp = explode ('&', $action);
			foreach ($tmp as $v)
			{
				$tmp2 = explode ('=', $action);
				if (count ($tmp2) == 2)
					$l_action[$tmp2[0]] = $tmp2[1];
			}
		}

		$page->set ('pagelist_firstpage_url', self::splitInPages_getPageUrl ($pagetoken, $module, 1, $l_action, '<'));
		$page->set ('pagelist_previous_url', self::splitInPages_getPageUrl ($pagetoken, $module, $current - 1, $l_action, '«'));

		$page->set ('pagelist_lastpage_url', self::splitInPages_getPageUrl ($pagetoken, $module, $pages, $l_action, '>'));
		$page->set ('pagelist_nextpage_url', self::splitInPages_getPageUrl ($pagetoken, $module, $current + 1, $l_action, '»'));

		$shortcuts = array ();
		for ($i = $pS; $i <= $pE; $i ++)
		{
			$shortcuts[] = array
			(
				'page' => $i,
				'url' => self::splitInPages_getPageUrl ($pagetoken, $module, $i, $l_action, $i)
			);
		}

		$page->set ('pagelist_shortcuts', $shortcuts);

		return array
		(
			'limit' => ( ($current - 1) * $perpage) . ', ' . $perpage,
			'start' => ($current-1) * $perpage,
			'perpage' => $perpage
		);
	}

	private static function splitInPages_getPageUrl ($pagetoken, $module, $page, $data, $name)
	{
		$data[$pagetoken] = $page;

		return Neuron_URLBuilder::getInstance ()->getUpdateUrl
		(
			$module,
			$name,
			$data
		);
	}

	public static function writexml (XMLWriter $xml, $data, $item_name = 'item')
	{
		foreach($data as $key => $value)
		{
			if (is_int ($key))
			{
				$key = $item_name;
			}

			if (is_array($value))
			{
				if ($key != 'items')
				{
					$xml->startElement($key);
				}

				if (isset ($value['attributes']) && is_array ($value['attributes']))
				{
					foreach ($value['attributes'] as $k => $v)
					{
						$xml->writeAttribute ($k, $v);
					}

					unset ($value['attributes']);
				}

				Neuron_Core_Tools::writexml ($xml, $value, substr ($key, 0, -1));

				if ($key != 'items')
				{
					$xml->endElement();
				}
			}

			elseif ($key == 'element-content')
			{
				$xml->text ($value);
			}

			else
			{
				$xml->writeElement($key, $value);
			}
		}
	}

	public static function output_xml ($data, $version = '0.1', $root = 'root', $parameters = array (), $sItemName = 'item')
	{
		$xml = new XmlWriter();
		$xml->openMemory();
		$xml->startDocument('1.0', 'UTF-8');
		$xml->startElement($root);
		$xml->setIndent (true);

		if (!empty ($version))
		{
			$xml->writeAttribute ('version', $version);
		}

		foreach ($parameters as $paramk => $paramv)
		{
			$xml->writeAttribute ($paramk, $paramv);
		}

		Neuron_Core_Tools::writexml ($xml, $data, $sItemName);

		$xml->endElement();
		return $xml->outputMemory(true);
	}

	private static function xml_escape ($input)
	{
		//$input = str_replace ('"', '"', $input);
		//$input = str_replace ("'", ''', $input);

		$input = str_replace ('<', '<', $input);
		$input = str_replace ('>', '>', $input);
		$input = str_replace ('&', '&', $input);

		return $input;
	}

	public static function output_partly_xml ($data, $key =  null)
	{
		$output = '<'.$key;

		if (isset ($data['attributes']) && is_array ($data['attributes']))
		{
			foreach ($data['attributes'] as $k => $v)
			{
				$output .= ' '.$k.'="'.$v.'"';
			}

			unset ($data['attributes']);
		}

		$output .= '>';
		if (!is_array ($data))
		{
			$output .= self::xml_escape ($data);
		}

		elseif (count ($data) == 1 && isset ($data['element-content']))
		{
			$output .= self::xml_escape ($data['element-content']);
		}

		else
		{
			foreach ($data as $k => $v)
			{
				if (is_numeric ($k))
				{
					$k = substr ($key, 0, -1);
				}

				$output .= self::output_partly_xml ($v, $k);
			}
		}
		$output .= '</'.$key.'>'."\n";

		return $output;
	}
}

?>


<?php

namespace PhalApi\Request\Formatter;

use PhalApi\Contracts\Request\Formatter;

class BooleanFormatter extends BaseFormatter implements Formatter
{
    /**
     * 对布尔型进行格式化
     *
     * @param mixed $value 变量值
     * @param array $rule ['true' => '成立时替换的内容', 'false' => '失败时替换的内容']
     * @return boolean/string 格式化后的变量
     */
    public function parse($value, $rule)
    {
        $rs = $value;

        if (!is_bool($value)) {
            if (is_numeric($value)) {
                $rs = $value > 0 ? true : false;
            } else if (is_string($value)) {
                $rs = in_array(strtolower($value), ['ok', 'true', 'success', 'on', 'yes'])
                    ? true : false;
            } else {
                $rs = $value ? true : false;
            }
        }

        return $rs;
    }
}


<?php

namespace Cinam\Randomizer;

use Cinam\Randomizer\Exception\InvalidArgumentException;

/**
 * Class for generating random numbers.
 *
 * @author cinam <cinam@hotmail.com>
 */
class NumberGenerator
{
    /**
     * Returns random integer from given range.
     *
     * @param integer $min The minimal value.
     * @param integer $max The maximal value.
     *
     * @return integer
     *
     * @throws InvalidArgumentException If min is greater than max.
     */
    public function getInt($min, $max)
    {
        if ($min > $max) {
            throw new InvalidArgumentException('Min cannot be greater than max');
        }

        return \mt_rand($min, $max);
    }

    /**
     * Returns random float from given range.
     *
     * @param float $min The minimal value.
     * @param float $max The maximal value.
     *
     * @return float
     *
     * @throws InvalidArgumentException If min is greater than max.
     */
    public function getFloat($min, $max)
    {
        if ($min > $max) {
            throw new InvalidArgumentException('Min cannot be greater than max');
        }

        $random01 = \mt_rand() / \mt_getrandmax();

        // [0, 1] -> [min, max]:
        // y = (max - min) * x + min
        return ($max - $min) * $random01 + $min;
    }
}


<?php

namespace PhalApi\Request\Formatter;

use PhalApi\Contracts\Request\Formatter;
use PhalApi\Exceptions\InternalServerError;

class EnumFormatter extends BaseFormatter implements Formatter
{
    /**
     * 检测枚举类型
     *
     * @param string $value 变量值
     * @param array $rule ['name' => '', 'type' => 'enum', 'default' => '', 'range' => []]
     * @return mixed
     */
    public function parse($value, $rule)
    {
        $this->formatEnumRule($rule);

        $this->formatEnumValue($value, $rule);

        return $value;
    }

    /**
     * 检测枚举规则的合法性
     *
     * @param array $rule ['name' => '', 'type' => 'enum', 'default' => '', 'range' => []]
     * @throws InternalServerError
     */
    protected function formatEnumRule($rule)
    {
        if (!isset($rule['range'])) {
            throw new InternalServerError(
                T("miss {name}'s enum range", ['name' => $rule['name']]));
        }

        if (empty($rule['range']) || !is_array($rule['range'])) {
            throw new InternalServerError(
                T("{name}'s enum range can not be empty", ['name' => $rule['name']]));
        }
    }
}


<?php

namespace PhalApi\Cookie;

class Cookie
{
    /**
     * COOKIE配置
     */
    protected $config = [];

    /**
     * @param string $config ['path'] 路径
     * @param string $config ['domain'] 域名
     * @param boolean $config ['secure'] 是否加密
     * @param boolean $config ['httponly'] 是否只HTTP协议
     * @link http://php.net/manual/zh/function.setcookie.php
     */
    public function __construct($config = [])
    {
        $this->config['path'] = isset($config['path']) ? $config['path'] : null;
        $this->config['domain'] = isset($config['domain']) ? $config['domain'] : null;
        $this->config['secure'] = isset($config['secure']) ? $config['secure'] : false;
        $this->config['httponly'] = isset($config['httponly']) ? $config['httponly'] : false;
    }

    /**
     * 获取COOKIE
     *
     * @param string $name 待获取的COOKIE名字
     * @return string|null|array $name 为NULL时返回整个$_COOKIE，存在时返回COOKIE，否则返回null
     */
    public function get($name = null)
    {
        if ($name === null) {
            return $_COOKIE;
        }

        return isset($_COOKIE[$name]) ? $_COOKIE[$name] : null;
    }

    /**
     * 设置COOKIE
     *
     * @param string $name 待设置的COOKIE名字
     * @param string|int $value 建议COOKIE值为一些简单的字符串或数字，不推荐存放敏感数据
     * @param int $expire 有效期的timestamp，为NULL时默认存放一个月
     * @param boolean
     * @return bool
     */
    public function set($name, $value, $expire = null)
    {
        if ($expire === null) {
            $expire = $_SERVER['REQUEST_TIME'] + 2592000;   //a month
        }

        return setcookie(
            $name,
            $value,
            $expire,
            $this->config['path'],
            $this->config['domain'],
            $this->config['secure'],
            $this->config['httponly']
        );
    }

    /**
     * 删除COOKIE
     *
     * @param string $name 待删除的COOKIE名字
     * @param boolean
     * @return bool
     * @see \PhalApi\Cookie\Cookie::set()
     */
    public function delete($name)
    {
        return $this->set($name, '', 0);
    }

    /**
     * 获取COOKIE的配置
     *
     * @return array
     */
    public function getConfig()
    {
        return $this->config;
    }
}


<?php
/**
 * Copyright (c) 2018 Wakers.cz
 *
 * @author Jiří Zapletal (http://www.wakers.cz, zapletal@wakers.cz)
 *
 */

namespace Wakers\StructureModule\Component\Frontend\RecipeSlugModal;

use Nette\Application\UI\Form;
use Wakers\BaseModule\Component\Frontend\BaseControl;
use Wakers\BaseModule\Database\DatabaseException;
use Wakers\BaseModule\Util\AjaxValidate;
use Wakers\BaseModule\Util\SetDisabledForm;
use Wakers\StructureModule\Manager\RecipeSlugManager;
use Wakers\StructureModule\Repository\RecipeRepository;
use Wakers\StructureModule\Repository\RecipeSlugRepository;
use Wakers\StructureModule\Security\StructureAuthorizator;

class RecipeSlugModal extends BaseControl
{
    use AjaxValidate;
    use SetDisabledForm;

    /**
     * @var RecipeRepository
     */
    protected $recipeRepository;

    /**
     * @var RecipeSlugRepository
     */
    protected $recipeSlugRepository;

    /**
     * @var RecipeSlugManager
     */
    protected $recipeSlugManager;

    /**
     * @var callable
     */
    public $onOpen = [];

    /**
     * @var callable
     */
    public $onSave = [];

    /**
     * @var int
     * @persistent
     */
    public $recipeId;

    /**
     * @var int
     */
    public $recipeSlugId;

    /**
     * RecipeSlugModal constructor.
     * @param RecipeRepository $recipeRepository
     * @param RecipeSlugRepository $recipeSlugRepository
     * @param RecipeSlugManager $recipeSlugManager
     */
    public function __construct(
        RecipeRepository $recipeRepository,
        RecipeSlugRepository $recipeSlugRepository,
        RecipeSlugManager $recipeSlugManager
    ) {
        $this->recipeRepository = $recipeRepository;
        $this->recipeSlugRepository = $recipeSlugRepository;
        $this->recipeSlugManager = $recipeSlugManager;
    }

    /**
     * Render
     */
    public function render() : void
    {
        $slugs = [];

        if ($this->recipeId)
        {
            $slugs = $this->recipeSlugRepository->findByRecipeId($this->recipeId);
        }

        $this->template->slugs = $slugs;
        $this->template->setFile(__DIR__ . '/templates/recipeSlugModal.latte');
        $this->template->render();
    }

    protected function createComponentSlugForm() : Form
    {
        $form = new Form;

        $form->addText('slug')
            ->setRequired('Slug je povinný.')
            ->addRule(Form::PATTERN, 'Slug může obsahovat pouze znaky a-z 0-9 a pomlčku.', '[a-zA-Z0-9\-]*')
            ->addRule(Form::MIN_LENGTH, 'Minimální délka slugu je %d znaků.', 3)
            ->addRule(Form::MAX_LENGTH, 'Maximální délka slugu je %d znaků', 32);

        $form->addHidden('id');

        $form->addSubmit('save');

        if ($this->recipeSlugId)
        {
            $recipeSlug = $this->recipeSlugRepository->findOneById($this->recipeSlugId);

            $form->setDefaults([
                'recipeId' => $recipeSlug->getRecipeId(),
                'id' => $recipeSlug->getId(),
                'slug' => $recipeSlug->getSlug()
            ]);
        }

        $form->onValidate[] = function (Form $form) { $this->validate($form); };
        $form->onSuccess[] = function (Form $form) { $this->successSlug($form); };

        if (!$this->presenter->user->isAllowed(StructureAuthorizator::RES_RECIPE_SLUG_MODAL))
        {
            $this->setDisabledForm($form, TRUE);
        }

        return $form;
    }

    /**
     * @param Form $form
     * @throws \Propel\Runtime\Exception\PropelException
     */
    public function successSlug(Form $form) : void
    {
        if ($this->presenter->isAjax())
        {
            $values = $form->getValues();

            $recipe = $this->recipeRepository->findOneById($this->recipeId);

            $recipeSlug = $values->id > 0 ?  $this->recipeSlugRepository->findOneById($values->id) : NULL;

            try
            {
                $result = $this->recipeSlugManager->save($recipe, $recipeSlug, $values->slug);

                $form->reset();

                $this->presenter->notificationAjax('Slug uložen', "Slug '{$result->getSlug()}' byl úspěšně uložen.", 'success', FALSE);
                $this->onSave();
            }
            catch (DatabaseException $exception)
            {
                $this->presenter->notificationAjax('Chyba', $exception->getMessage(), 'error');
            }
        }
    }

    /**
     * Handle edit
     * @param int|NULL $recipeId
     */
    public function handleOpen(int $recipeId = NULL) : void
    {
        if ($this->presenter->isAjax())
        {
            $this->recipeId = $recipeId;

            $this->presenter->handleModalToggle('show', '#wakers_structure_recipe_slug_modal', FALSE);

            $this->onOpen();
        }
    }

    /**
     * @param int $id
     */
    public function handleEdit(int $id) : void
    {
        if ($this->presenter->isAjax())
        {
            $this->recipeSlugId = $id;

            $this->onOpen();
        }
    }
}


<?php
/**
 * Phossa Project
 *
 * PHP version 5.4
 *
 * @category  Library
 * @package   Phossa2\Shared
 * @copyright Copyright (c) 2016 phossa.com
 * @license   http://mit-license.org/ MIT License
 * @link      http://www.phossa.com/
 */
/*# declare(strict_types=1); */

namespace Phossa2\Shared\Queue;

/**
 * PriorityQueueTrait
 *
 * @package Phossa2\Shared
 * @author  Hong Zhang <phossa@126.com>
 * @see     PriorityQueueInterface
 * @version 2.0.20
 * @since   2.0.20 added
 * @since   2.0.21 updated to store extra data
 */
trait PriorityQueueTrait
{
    /**
     * inner data storage
     *
     * @var    array
     * @access protected
     */
    protected $queue = [];

    /**
     * marker for sorted queue
     *
     * @var    bool
     * @access protected
     */
    protected $sorted = false;

    /**
     * priority counter, descreasing
     *
     * @var    int
     * @access protected
     */
    protected $counter = 10000000;

    /**
     * {@inheritDoc}
     *
     * @since  2.0.21 added extra data
     */
    public function insert($data, /*# int */ $priority = 0, $extra = null)
    {
        // fix priority
        $pri = $this->fixPriority((int) $priority);

        // generate key to be used (int)
        $key = $this->generateKey($pri);

        // make sure not duplicated
        $this->remove($data);

        // added to the queue
        $this->queue[$key] = [
            'data' => $data, 'priority' => $pri, 'extra' => $extra
        ];

        // mark as not sorted
        $this->sorted = false;

        return $this;
    }

    /**
     * {@inheritDoc}
     */
    public function remove($data)
    {
        foreach ($this->queue as $key => $val) {
            if ($val['data'] === $data) {
                unset($this->queue[$key]);
                break;
            }
        }
        return $this;
    }

    /**
     * {@inheritdic}
     */
    public function flush()
    {
        $this->queue = [];
        return $this;
    }

    /**
     * {@inheritDoc}
     */
    public function combine(
        PriorityQueueInterface $queue
    )/*# : PriorityQueueInterface */ {
        // clone a new queue
        $nqueue = clone $this;

        // insert into new queue
        foreach ($queue as $data) {
            $nqueue->insert($data['data'], $data['priority'], $data['extra']);
        }

        return $nqueue;
    }

    /**
     * {@inheritDoc}
     */
    public function count()
    {
        return count($this->queue);
    }

    /**
     * {@inheritDoc}
     */
    public function getIterator()
    {
        // sort queue if not yet
        $this->sortQueue();

        // return iterator
        return new \ArrayIterator($this->queue);
    }

    /**
     * Make sure priority in the range of -100 - +100
     *
     * @param  int $priority
     * @return int
     * @access protected
     */
    protected function fixPriority(/*# int */ $priority)/*# : int */
    {
        return (int) ($priority > 100 ? 100 : ($priority < -100 ? -100 : $priority));
    }

    /**
     * Generate one int base on the priority
     *
     * @param  int $priority
     * @return int
     * @access protected
     */
    protected function generateKey(/*# int */ $priority)/*# : int */
    {
        return ($priority + 100) * 10000000 + --$this->counter;
    }

    /**
     * Sort the queue from higher to lower int $key
     *
     * @return $this
     * @access protected
     */
    protected function sortQueue()
    {
        if (!$this->sorted) {
            krsort($this->queue);
            $this->sorted = true;
        }
        return $this;
    }
}