diff --git a/includes/ajaxHandler.class.php b/includes/ajaxHandler.class.php index a55c6e8a..f40ed712 100644 --- a/includes/ajaxHandler.class.php +++ b/includes/ajaxHandler.class.php @@ -6,26 +6,21 @@ if (!defined('AOWOW_REVISION')) class AjaxHandler { + use TrRequestData; + protected $validParams = []; protected $params = []; protected $handler; protected $contentType = MIME_TYPE_JSON; - protected $_post = []; - protected $_get = []; - public $doRedirect = false; public function __construct(array $params) { $this->params = $params; - foreach ($this->_post as $k => &$v) - $v = isset($_POST[$k]) ? filter_input(INPUT_POST, $k, $v[0], $v[1]) : null; - - foreach ($this->_get as $k => &$v) - $v = isset($_GET[$k]) ? filter_input(INPUT_GET, $k, $v[0], $v[1]) : null; + $this->initRequestData(); } public function handle(string &$out) : bool @@ -72,48 +67,5 @@ class AjaxHandler return true; } - - protected static function checkEmptySet(string $val) : bool - { - return $val === ''; // parameter is expected to be empty - } - - protected static function checkLocale(string $val) : int - { - if (preg_match('/^'.implode('|', array_keys(array_filter(Util::$localeStrings))).'$/', $val)) - return intVal($val); - - return -1; - } - - protected static function checkInt(string $val) : int - { - if (preg_match('/^-?\d+$/', $val)) - return intVal($val); - - return 0; - } - - protected static function checkIdList(string $val) : array - { - if (preg_match('/^-?\d+(,-?\d+)*$/', $val)) - return array_map('intVal', explode(',', $val)); - - return []; - } - - protected static function checkIdListUnsigned(string $val) : array - { - if (preg_match('/\d+(,\d+)*/', $val)) - return array_map('intVal', explode(',', $val)); - - return []; - } - - protected static function checkFulltext(string $val) : string - { - // trim non-printable chars - return preg_replace('/[\p{Cf}\p{Co}\p{Cs}\p{Cn}]/ui', '', $val); - } } ?> diff --git a/includes/ajaxHandler/account.class.php b/includes/ajaxHandler/account.class.php index 3b5f85a6..222c1565 100644 --- a/includes/ajaxHandler/account.class.php +++ b/includes/ajaxHandler/account.class.php @@ -7,21 +7,21 @@ class AjaxAccount extends AjaxHandler { protected $validParams = ['exclude', 'weightscales', 'favorites']; protected $_post = array( - 'groups' => [FILTER_SANITIZE_NUMBER_INT, null ], - 'save' => [FILTER_SANITIZE_NUMBER_INT, null ], - 'delete' => [FILTER_SANITIZE_NUMBER_INT, null ], - 'id' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkIdList']], - 'name' => [FILTER_CALLBACK, ['options' => 'AjaxAccount::checkName'] ], - 'scale' => [FILTER_CALLBACK, ['options' => 'AjaxAccount::checkScale'] ], - 'reset' => [FILTER_SANITIZE_NUMBER_INT, null ], - 'mode' => [FILTER_SANITIZE_NUMBER_INT, null ], - 'type' => [FILTER_SANITIZE_NUMBER_INT, null ], - 'add' => [FILTER_SANITIZE_NUMBER_INT, null ], - 'remove' => [FILTER_SANITIZE_NUMBER_INT, null ], - // 'sessionKey' => [FILTER_SANITIZE_NUMBER_INT, null ] + 'groups' => ['filter' => FILTER_SANITIZE_NUMBER_INT], + 'save' => ['filter' => FILTER_SANITIZE_NUMBER_INT], + 'delete' => ['filter' => FILTER_SANITIZE_NUMBER_INT], + 'id' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkIdList'], + 'name' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxAccount::checkName' ], + 'scale' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxAccount::checkScale' ], + 'reset' => ['filter' => FILTER_SANITIZE_NUMBER_INT], + 'mode' => ['filter' => FILTER_SANITIZE_NUMBER_INT], + 'type' => ['filter' => FILTER_SANITIZE_NUMBER_INT], + 'add' => ['filter' => FILTER_SANITIZE_NUMBER_INT], + 'remove' => ['filter' => FILTER_SANITIZE_NUMBER_INT], + // 'sessionKey' => ['filter' => FILTER_SANITIZE_NUMBER_INT] ); protected $_get = array( - 'locale' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkLocale']] + 'locale' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkLocale'] ); public function __construct(array $params) @@ -177,7 +177,7 @@ class AjaxAccount extends AjaxHandler { $var = trim(urldecode($val)); - return filter_var($var, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW); + return filter_var($var, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_AOWOW); } } diff --git a/includes/ajaxHandler/admin.class.php b/includes/ajaxHandler/admin.class.php index f8996c21..54ebbedd 100644 --- a/includes/ajaxHandler/admin.class.php +++ b/includes/ajaxHandler/admin.class.php @@ -7,23 +7,23 @@ class AjaxAdmin extends AjaxHandler { protected $validParams = ['screenshots', 'siteconfig', 'weight-presets', 'spawn-override']; protected $_get = array( - 'action' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH ], - 'id' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkIdListUnsigned']], - 'key' => [FILTER_CALLBACK, ['options' => 'AjaxAdmin::checkKey'] ], - 'all' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkFulltext'] ], - 'type' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt'] ], - 'typeid' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt'] ], - 'user' => [FILTER_CALLBACK, ['options' => 'AjaxAdmin::checkUser'] ], - 'val' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkFulltext'] ], - 'guid' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt'] ], - 'area' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt'] ], - 'floor' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt'] ] + 'action' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW ], + 'id' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkIdListUnsigned'], + 'key' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxAdmin::checkKey' ], + 'all' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkFulltext' ], + 'type' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt' ], + 'typeid' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt' ], + 'user' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxAdmin::checkUser' ], + 'val' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkFulltext' ], + 'guid' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt' ], + 'area' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt' ], + 'floor' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt' ] ); protected $_post = array( - 'alt' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW ], - 'id' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']], - 'scale' => [FILTER_CALLBACK, ['options' => 'AjaxAdmin::checkScale']], - '__icon' => [FILTER_CALLBACK, ['options' => 'AjaxAdmin::checkKey'] ] + 'alt' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW ], + 'id' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt'], + 'scale' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxAdmin::checkScale'], + '__icon' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxAdmin::checkKey' ] ); public function __construct(array $params) diff --git a/includes/ajaxHandler/arenateam.class.php b/includes/ajaxHandler/arenateam.class.php index 6e822318..1b7b9eca 100644 --- a/includes/ajaxHandler/arenateam.class.php +++ b/includes/ajaxHandler/arenateam.class.php @@ -7,8 +7,8 @@ class AjaxArenaTeam extends AjaxHandler { protected $validParams = ['resync', 'status']; protected $_get = array( - 'id' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkIdList'] ], - 'profile' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkEmptySet']], + 'id' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkIdList' ], + 'profile' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkEmptySet'], ); public function __construct(array $params) diff --git a/includes/ajaxHandler/comment.class.php b/includes/ajaxHandler/comment.class.php index ea046e08..0ce1670d 100644 --- a/includes/ajaxHandler/comment.class.php +++ b/includes/ajaxHandler/comment.class.php @@ -11,23 +11,23 @@ class AjaxComment extends AjaxHandler const REPLY_LENGTH_MAX = 600; protected $_post = array( - 'id' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkIdListUnsigned']], - 'body' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkFulltext'] ], - 'commentbody' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkFulltext'] ], - 'response' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW ], - 'reason' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW ], - 'remove' => [FILTER_SANITIZE_NUMBER_INT, null ], - 'commentId' => [FILTER_SANITIZE_NUMBER_INT, null ], - 'replyId' => [FILTER_SANITIZE_NUMBER_INT, null ], - 'sticky' => [FILTER_SANITIZE_NUMBER_INT, null ], - // 'username' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH ] + 'id' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkIdListUnsigned'], + 'body' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkFulltext' ], + 'commentbody' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkFulltext' ], + 'response' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW ], + 'reason' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW ], + 'remove' => ['filter' => FILTER_SANITIZE_NUMBER_INT], + 'commentId' => ['filter' => FILTER_SANITIZE_NUMBER_INT], + 'replyId' => ['filter' => FILTER_SANITIZE_NUMBER_INT], + 'sticky' => ['filter' => FILTER_SANITIZE_NUMBER_INT], + // 'username' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW ] ); protected $_get = array( - 'id' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']], - 'type' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']], - 'typeid' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']], - 'rating' => [FILTER_SANITIZE_NUMBER_INT, null] + 'id' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt'], + 'type' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt'], + 'typeid' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt'], + 'rating' => ['filter' => FILTER_SANITIZE_NUMBER_INT] ); public function __construct(array $params) diff --git a/includes/ajaxHandler/contactus.class.php b/includes/ajaxHandler/contactus.class.php index bbd3cb6d..d2a2517e 100644 --- a/includes/ajaxHandler/contactus.class.php +++ b/includes/ajaxHandler/contactus.class.php @@ -6,15 +6,15 @@ if (!defined('AOWOW_REVISION')) class AjaxContactus extends AjaxHandler { protected $_post = array( - 'mode' => [FILTER_SANITIZE_NUMBER_INT, null ], - 'reason' => [FILTER_SANITIZE_NUMBER_INT, null ], - 'ua' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW], - 'appname' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW], - 'page' => [FILTER_SANITIZE_URL, null ], - 'desc' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW], - 'id' => [FILTER_SANITIZE_NUMBER_INT, null ], - 'relatedurl' => [FILTER_SANITIZE_URL, null ], - 'email' => [FILTER_SANITIZE_EMAIL, null ] + 'mode' => ['filter' => FILTER_SANITIZE_NUMBER_INT], + 'reason' => ['filter' => FILTER_SANITIZE_NUMBER_INT], + 'ua' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], + 'appname' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], + 'page' => ['filter' => FILTER_SANITIZE_URL], + 'desc' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], + 'id' => ['filter' => FILTER_SANITIZE_NUMBER_INT], + 'relatedurl' => ['filter' => FILTER_SANITIZE_URL], + 'email' => ['filter' => FILTER_SANITIZE_EMAIL] ); public function __construct(array $params) diff --git a/includes/ajaxHandler/cookie.class.php b/includes/ajaxHandler/cookie.class.php index c1a7d9d7..ccc36166 100644 --- a/includes/ajaxHandler/cookie.class.php +++ b/includes/ajaxHandler/cookie.class.php @@ -12,7 +12,7 @@ class AjaxCookie extends AjaxHandler return; $this->_get = array( - $params[0] => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH], + $params[0] => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], ); // NOW we know, what to expect and sanitize diff --git a/includes/ajaxHandler/data.class.php b/includes/ajaxHandler/data.class.php index 2df14239..b114baa9 100644 --- a/includes/ajaxHandler/data.class.php +++ b/includes/ajaxHandler/data.class.php @@ -6,12 +6,12 @@ if (!defined('AOWOW_REVISION')) class AjaxData extends AjaxHandler { protected $_get = array( - 'locale' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkLocale'] ], - 't' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH], - 'catg' => [FILTER_SANITIZE_NUMBER_INT, null ], - 'skill' => [FILTER_CALLBACK, ['options' => 'AjaxData::checkSkill'] ], - 'class' => [FILTER_SANITIZE_NUMBER_INT, null ], - 'callback' => [FILTER_CALLBACK, ['options' => 'AjaxData::checkCallback'] ] + 'locale' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkLocale'], + 't' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW ], + 'catg' => ['filter' => FILTER_SANITIZE_NUMBER_INT ], + 'skill' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxData::checkSkill' ], + 'class' => ['filter' => FILTER_SANITIZE_NUMBER_INT ], + 'callback' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxData::checkCallback' ] ); public function __construct(array $params) diff --git a/includes/ajaxHandler/gotocomment.class.php b/includes/ajaxHandler/gotocomment.class.php index 42636a55..f4e612d7 100644 --- a/includes/ajaxHandler/gotocomment.class.php +++ b/includes/ajaxHandler/gotocomment.class.php @@ -6,7 +6,7 @@ if (!defined('AOWOW_REVISION')) class AjaxGotocomment extends AjaxHandler { protected $_get = array( - 'id' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']] + 'id' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt'] ); public function __construct(array $params) diff --git a/includes/ajaxHandler/guild.class.php b/includes/ajaxHandler/guild.class.php index c4d199d5..1c9e2aba 100644 --- a/includes/ajaxHandler/guild.class.php +++ b/includes/ajaxHandler/guild.class.php @@ -7,8 +7,8 @@ class AjaxGuild extends AjaxHandler { protected $validParams = ['resync', 'status']; protected $_get = array( - 'id' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkIdList'] ], - 'profile' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkEmptySet']], + 'id' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkIdList' ], + 'profile' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkEmptySet'], ); public function __construct(array $params) diff --git a/includes/ajaxHandler/locale.class.php b/includes/ajaxHandler/locale.class.php index 57083964..b6c64d22 100644 --- a/includes/ajaxHandler/locale.class.php +++ b/includes/ajaxHandler/locale.class.php @@ -6,7 +6,7 @@ if (!defined('AOWOW_REVISION')) class AjaxLocale extends AjaxHandler { protected $_get = array( - 'locale' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkLocale']] + 'locale' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkLocale'] ); public function __construct(array $params) diff --git a/includes/ajaxHandler/profile.class.php b/includes/ajaxHandler/profile.class.php index 1f77008c..91327ffe 100644 --- a/includes/ajaxHandler/profile.class.php +++ b/includes/ajaxHandler/profile.class.php @@ -9,36 +9,36 @@ class AjaxProfile extends AjaxHandler protected $validParams = ['link', 'unlink', 'pin', 'unpin', 'public', 'private', 'avatar', 'resync', 'status', 'save', 'delete', 'purge', 'summary', 'load']; protected $_get = array( - 'id' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkIdList'] ], - 'items' => [FILTER_CALLBACK, ['options' => 'AjaxProfile::checkItemList'] ], - 'size' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH], - 'guild' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkEmptySet'] ], - 'arena-team' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkEmptySet'] ], - 'user' => [FILTER_CALLBACK, ['options' => 'AjaxProfile::checkUser'] ] + 'id' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkIdList' ], + 'items' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxProfile::checkItemList'], + 'size' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW ], + 'guild' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkEmptySet'], + 'arena-team' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkEmptySet'], + 'user' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxProfile::checkUser' ] ); protected $_post = array( - 'name' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkFulltext'] ], - 'level' => [FILTER_SANITIZE_NUMBER_INT, null ], - 'class' => [FILTER_SANITIZE_NUMBER_INT, null ], - 'race' => [FILTER_SANITIZE_NUMBER_INT, null ], - 'gender' => [FILTER_SANITIZE_NUMBER_INT, null ], - 'nomodel' => [FILTER_SANITIZE_NUMBER_INT, null ], - 'talenttree1' => [FILTER_SANITIZE_NUMBER_INT, null ], - 'talenttree2' => [FILTER_SANITIZE_NUMBER_INT, null ], - 'talenttree3' => [FILTER_SANITIZE_NUMBER_INT, null ], - 'activespec' => [FILTER_SANITIZE_NUMBER_INT, null ], - 'talentbuild1' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH ], - 'glyphs1' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH ], - 'talentbuild2' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH ], - 'glyphs2' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH ], - 'icon' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH ], - 'description' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkFulltext'] ], - 'source' => [FILTER_SANITIZE_NUMBER_INT, null ], - 'copy' => [FILTER_SANITIZE_NUMBER_INT, null ], - 'public' => [FILTER_SANITIZE_NUMBER_INT, null ], - 'gearscore' => [FILTER_SANITIZE_NUMBER_INT, null ], - 'inv' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkIdListUnsigned', 'flags' => FILTER_REQUIRE_ARRAY]], + 'name' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkFulltext'], + 'level' => ['filter' => FILTER_SANITIZE_NUMBER_INT], + 'class' => ['filter' => FILTER_SANITIZE_NUMBER_INT], + 'race' => ['filter' => FILTER_SANITIZE_NUMBER_INT], + 'gender' => ['filter' => FILTER_SANITIZE_NUMBER_INT], + 'nomodel' => ['filter' => FILTER_SANITIZE_NUMBER_INT], + 'talenttree1' => ['filter' => FILTER_SANITIZE_NUMBER_INT], + 'talenttree2' => ['filter' => FILTER_SANITIZE_NUMBER_INT], + 'talenttree3' => ['filter' => FILTER_SANITIZE_NUMBER_INT], + 'activespec' => ['filter' => FILTER_SANITIZE_NUMBER_INT], + 'talentbuild1' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], + 'glyphs1' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], + 'talentbuild2' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], + 'glyphs2' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], + 'icon' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], + 'description' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkFulltext'], + 'source' => ['filter' => FILTER_SANITIZE_NUMBER_INT], + 'copy' => ['filter' => FILTER_SANITIZE_NUMBER_INT], + 'public' => ['filter' => FILTER_SANITIZE_NUMBER_INT], + 'gearscore' => ['filter' => FILTER_SANITIZE_NUMBER_INT], + 'inv' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkIdListUnsigned', 'flags' => FILTER_REQUIRE_ARRAY], ); public function __construct(array $params) diff --git a/includes/community.class.php b/includes/community.class.php index 61334031..90dcf6fd 100644 --- a/includes/community.class.php +++ b/includes/community.class.php @@ -511,7 +511,7 @@ class CommunityContent { $result = array( 'vi' => self::getVideos($type, $typeId), - 'sc' => self::getScreenshots($type, $typeId), + 'ss' => self::getScreenshots($type, $typeId), 'co' => self::getComments($type, $typeId) ); diff --git a/includes/defines.php b/includes/defines.php index fda8c801..d3545a48 100644 --- a/includes/defines.php +++ b/includes/defines.php @@ -7,8 +7,9 @@ if (!defined('AOWOW_REVISION')) * Page */ -define('E_AOWOW', E_ALL & ~(E_DEPRECATED | E_USER_DEPRECATED | E_STRICT)); -define('JSON_AOWOW_POWER', JSON_PRETTY_PRINT | JSON_NUMERIC_CHECK | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); +define('E_AOWOW', E_ALL & ~(E_DEPRECATED | E_USER_DEPRECATED | E_STRICT)); +define('JSON_AOWOW_POWER', JSON_PRETTY_PRINT | JSON_NUMERIC_CHECK | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); +define('FILTER_FLAG_STRIP_AOWOW', FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH | FILTER_STRIP_BACKTICK); define('MIME_TYPE_TEXT', 'Content-Type: text/plain; charset=utf-8'); define('MIME_TYPE_XML', 'Content-Type: text/xml; charset=utf-8'); diff --git a/includes/utilities.php b/includes/utilities.php index 739b091a..610b999e 100644 --- a/includes/utilities.php +++ b/includes/utilities.php @@ -16,6 +16,86 @@ class SimpleXML extends SimpleXMLElement } } +trait TrRequestData +{ + private $filtered = false; + + private function initRequestData() : void + { + if ($this->filtered) + return; + + if (isset($this->_post) && gettype($this->_post) == 'array') + $this->_post = filter_input_array(INPUT_POST, $this->_post); + + if (isset($this->_get) && gettype($this->_get) == 'array') + $this->_get = filter_input_array(INPUT_GET, $this->_get); + + if (isset($this->_cookie) && gettype($this->_cookie) == 'array') + $this->_cookie = filter_input_array(INPUT_COOKIE, $this->_cookie); + + $this->filtered = true; + } + + protected static function checkEmptySet(string $val) : bool + { + return $val === ''; // parameter is expected to be empty + } + + protected static function checkInt(string $val) : int + { + if (preg_match('/^-?\d+$/', $val)) + return intVal($val); + + return 0; + } + + protected static function checkLocale(string $val) : int + { + if (preg_match('/^'.implode('|', array_keys(array_filter(Util::$localeStrings))).'$/', $val)) + return intVal($val); + + return -1; + } + + protected static function checkDomain(string $val) : string + { + if (preg_match('/^'.implode('|', array_filter(Util::$subDomains)).'$/i', $val)) + return strtolower($val); + + return ''; + } + + protected static function checkIdList(string $val) : array + { + if (preg_match('/^-?\d+(,-?\d+)*$/', $val)) + return array_map('intVal', explode(',', $val)); + + return []; + } + + protected static function checkIntArray(string $val) : array + { + if (preg_match('/^-?\d+(:-?\d+)*$/', $val)) + return array_map('intVal', explode(':', $val)); + + return []; + } + + protected static function checkIdListUnsigned(string $val) : array + { + if (preg_match('/\d+(,\d+)*/', $val)) + return array_map('intVal', explode(',', $val)); + + return []; + } + + protected static function checkFulltext(string $val) : string + { + // trim non-printable chars + return preg_replace('/[\p{Cf}\p{Co}\p{Cs}\p{Cn}]/ui', '', $val); + } +} class CLI { diff --git a/pages/account.php b/pages/account.php index a95ef3e0..d38d2685 100644 --- a/pages/account.php +++ b/pages/account.php @@ -27,13 +27,18 @@ class AccountPage extends GenericPage protected $lvTabs = []; protected $banned = []; - private $_post = array( - 'username' => [FILTER_SANITIZE_SPECIAL_CHARS, 0xC], // FILTER_FLAG_STRIP_LOW | *_HIGH - 'password' => [FILTER_UNSAFE_RAW, null], - 'c_password' => [FILTER_UNSAFE_RAW, null], - 'token' => [FILTER_UNSAFE_RAW, null], - 'remember_me' => [FILTER_CALLBACK, ['options' => 'AccountPage::rememberCallback']], - 'email' => [FILTER_SANITIZE_EMAIL, null] + protected $_get = array( + 'token' => ['filter' => FILTER_SANITIZE_SPECIAL_CHARS, 'flags' => FILTER_FLAG_STRIP_AOWOW], + 'next' => ['filter' => FILTER_SANITIZE_SPECIAL_CHARS, 'flags' => FILTER_FLAG_STRIP_AOWOW], + ); + + protected $_post = array( + 'username' => ['filter' => FILTER_SANITIZE_SPECIAL_CHARS, 'flags' => FILTER_FLAG_STRIP_AOWOW], + 'password' => ['filter' => FILTER_UNSAFE_RAW], + 'c_password' => ['filter' => FILTER_UNSAFE_RAW], + 'token' => ['filter' => FILTER_UNSAFE_RAW], + 'remember_me' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::rememberCallback'], + 'email' => ['filter' => FILTER_SANITIZE_EMAIL] ); public function __construct($pageCall, $pageParam) @@ -43,9 +48,6 @@ class AccountPage extends GenericPage parent::__construct($pageCall, $pageParam); - foreach ($this->_post as $k => &$v) - $v = !empty($_POST[$k]) ? filter_input(INPUT_POST, $k, $v[0], $v[1]) : null; - if ($pageParam) { // requires auth && not authed @@ -57,7 +59,7 @@ class AccountPage extends GenericPage } } - private function rememberCallback($val) + protected function rememberCallback($val) { return $val == 'yes' ? $val : null; } @@ -128,7 +130,7 @@ class AccountPage extends GenericPage header('Location: '.$this->getNext(true), true, 302); } } - else if (!empty($_GET['token']) && ($_ = DB::Aowow()->selectCell('SELECT user FROM ?_account WHERE status IN (?a) AND token = ? AND statusTimer > UNIX_TIMESTAMP()', [ACC_STATUS_RECOVER_USER, ACC_STATUS_OK], $_GET['token']))) + else if ($this->_get['token'] && ($_ = DB::Aowow()->selectCell('SELECT user FROM ?_account WHERE status IN (?a) AND token = ? AND statusTimer > UNIX_TIMESTAMP()', [ACC_STATUS_RECOVER_USER, ACC_STATUS_OK], $this->_get['token']))) $this->user = $_; break; @@ -156,13 +158,13 @@ class AccountPage extends GenericPage $this->text = sprintf(Lang::account('createAccSent'), $this->_post['email']); } } - else if (!empty($_GET['token']) && ($newId = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE status = ?d AND token = ?', ACC_STATUS_NEW, $_GET['token']))) + else if ($this->_get['token'] && ($newId = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE status = ?d AND token = ?', ACC_STATUS_NEW, $this->_get['token']))) { $nStep = 2; - DB::Aowow()->query('UPDATE ?_account SET status = ?d, statusTimer = 0, token = 0, userGroups = ?d WHERE token = ?', ACC_STATUS_OK, U_GROUP_NONE, $_GET['token']); + DB::Aowow()->query('UPDATE ?_account SET status = ?d, statusTimer = 0, token = 0, userGroups = ?d WHERE token = ?', ACC_STATUS_OK, U_GROUP_NONE, $this->_get['token']); DB::Aowow()->query('REPLACE INTO ?_account_bannedips (ip, type, count, unbanDate) VALUES (?, 1, ?d + 1, UNIX_TIMESTAMP() + ?d)', User::$ip, CFG_ACC_FAILED_AUTH_COUNT, CFG_ACC_FAILED_AUTH_BLOCK); - $this->text = sprintf(Lang::account('accActivated'), $_GET['token']); + $this->text = sprintf(Lang::account('accActivated'), $this->_get['token']); } else $this->next = $this->getNext(); @@ -313,17 +315,17 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup $this->text = sprintf(Lang::account('recovPassSent'), $this->_post['email']); } } - else if (isset($_GET['token'])) // step 2 + else if ($this->_get['token']) // step 2 { $step = 2; $this->resetPass = true; - $this->token = $_GET['token']; + $this->token = $this->_get['token']; } else if ($this->_post['token'] && $this->_post['email'] && $this->_post['password'] && $this->_post['c_password']) { $step = 2; $this->resetPass = true; - $this->token = $_GET['token']; // insecure source .. that sucks; but whats the worst that could happen .. this account cannot be recovered for some minutes + $this->token = $this->_post['token']; // insecure source .. that sucks; but whats the worst that could happen .. this account cannot be recovered for some minutes if ($err = $this->doResetPass()) $this->error = $err; @@ -413,7 +415,7 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup } // username taken - if ($_ = DB::Aowow()->SelectCell('SELECT user FROM ?_account WHERE (user = ? OR email = ?) AND (status <> ?d OR (status = ?d AND statusTimer > UNIX_TIMESTAMP()))', $this->_post['username'], $email, ACC_STATUS_NEW, ACC_STATUS_NEW)) + if ($_ = DB::Aowow()->SelectCell('SELECT user FROM ?_account WHERE (user = ? OR email = ?) AND (status <> ?d OR (status = ?d AND statusTimer > UNIX_TIMESTAMP()))', $this->_post['username'], $this->_post['email'], ACC_STATUS_NEW, ACC_STATUS_NEW)) return $_ == $this->_post['username'] ? Lang::account('nameInUse') : Lang::account('mailInUse'); // create.. @@ -473,10 +475,10 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup if (!$uId) return Lang::account('emailNotFound'); // assume they didn't meddle with the token - if (!User::verifyCrypt($newPass)) + if (!User::verifyCrypt($this->_post['c_password'])) return Lang::account('newPassDiff'); - if (!DB::Aowow()->query('UPDATE ?_account SET passHash = ?, status = ?d WHERE id = ?d', User::hashcrypt($newPass), ACC_STATUS_OK, $uId)) + if (!DB::Aowow()->query('UPDATE ?_account SET passHash = ?, status = ?d WHERE id = ?d', User::hashCrypt($this->_post['c_password']), ACC_STATUS_OK, $uId)) return Lang::main('intError'); } @@ -520,8 +522,8 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup private function getNext($forHeader = false) { $next = $forHeader ? '.' : ''; - if (isset($_GET['next'])) - $next = $_GET['next']; + if ($this->_get['next']) + $next = $this->_get['next']; else if (isset($_SERVER['HTTP_REFERER']) && strstr($_SERVER['HTTP_REFERER'], '?')) $next = explode('?', $_SERVER['HTTP_REFERER'])[1]; diff --git a/pages/achievement.php b/pages/achievement.php index b0907ef1..80e5339d 100644 --- a/pages/achievement.php +++ b/pages/achievement.php @@ -32,6 +32,8 @@ class AchievementPage extends GenericPage protected $tabId = 0; protected $mode = CACHE_TYPE_PAGE; + protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain']]; + private $powerTpl = '$WowheadPower.registerAchievement(%d, %d, %s);'; public function __construct($pageCall, $id) @@ -39,8 +41,8 @@ class AchievementPage extends GenericPage parent::__construct($pageCall, $id); // temp locale - if ($this->mode == CACHE_TYPE_TOOLTIP && isset($_GET['domain'])) - Util::powerUseLocale($_GET['domain']); + if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain']) + Util::powerUseLocale($this->_get['domain']); $this->typeId = intVal($id); diff --git a/pages/achievements.php b/pages/achievements.php index 57c0fa77..6b28239d 100644 --- a/pages/achievements.php +++ b/pages/achievements.php @@ -16,6 +16,9 @@ class AchievementsPage extends GenericPage protected $tabId = 0; protected $mode = CACHE_TYPE_PAGE; protected $js = ['filters.js']; + + protected $_get = ['filter' => ['filter' => FILTER_UNSAFE_RAW]]; + protected $validCats = array( 92 => true, 96 => [14861, 14862, 14863], @@ -64,7 +67,7 @@ class AchievementsPage extends GenericPage // recreate form selection $this->filter = $this->filterObj->getForm(); - $this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : null; + $this->filter['query'] = $this->_get['filter']; $this->filter['initData'] = ['init' => 'achievements']; if ($x = $this->filterObj->getSetCriteria()) diff --git a/pages/admin.php b/pages/admin.php index 5cfc5d38..09a450f9 100644 --- a/pages/admin.php +++ b/pages/admin.php @@ -6,13 +6,19 @@ if (!defined('AOWOW_REVISION')) class AdminPage extends GenericPage { - protected $tpl = null; // depends on the subject protected $reqUGroup = U_GROUP_NONE; // actual group dependant on the subPage protected $reqAuth = true; protected $path = [4]; protected $tabId = 4; + protected $_get = array( + 'all' => ['filter' => FILTER_UNSAFE_RAW], + 'type' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkInt'], + 'typeid' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkInt'], + 'user' => ['filter' => FILTER_CALLBACK, 'options' => 'urldecode'], + ); + private $generator = ''; public function __construct($pageCall, $pageParam) @@ -187,22 +193,21 @@ class AdminPage extends GenericPage ['string' => '#highlightedRow { background-color: #322C1C; }'] )); - $ssGetAll = isset($_GET['all']) && empty($_GET['all']); + $ssGetAll = $this->_get['all']; $ssPages = []; $ssData = []; $nMatches = 0; - if (!empty($_GET['type']) && !empty($_GET['typeid'])) + if ($this->_get['type'] && $this->_get['typeId']) { - $ssData = CommunityContent::getScreenshotsForManager(intVal($_GET['type']), intVal($_GET['typeid'])); + $ssData = CommunityContent::getScreenshotsForManager($this->_get['type'], $this->_get['typeid']); $nMatches = count($ssData); } - else if (!empty($_GET['user'])) + else if ($this->_get['user']) { - $name = urldecode($_GET['user']); - if (mb_strlen($name) >= 3) + if (mb_strlen($this->_get['user']) >= 3) { - if ($uId = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE displayName = ?', ucFirst($name))) + if ($uId = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE displayName = ?', ucFirst($this->_get['user']))) { $ssData = CommunityContent::getScreenshotsForManager(0, 0, $uId); $nMatches = count($ssData); diff --git a/pages/areatriggers.php b/pages/areatriggers.php index d4f78248..0f95841b 100644 --- a/pages/areatriggers.php +++ b/pages/areatriggers.php @@ -19,6 +19,8 @@ class AreaTriggersPage extends GenericPage protected $js = ['filters.js']; protected $reqUGroup = U_GROUP_STAFF; + protected $_get = ['filter' => ['filter' => FILTER_UNSAFE_RAW]]; + public function __construct($pageCall, $pageParam) { $this->getCategoryFromUrl($pageParam);; @@ -36,7 +38,7 @@ class AreaTriggersPage extends GenericPage { // recreate form selection $this->filter = $this->filterObj->getForm(); - $this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : null; + $this->filter['query'] = $this->_get['filter']; $this->filter['initData'] = ['init' => 'areatrigger']; if ($x = $this->filterObj->getSetCriteria()) diff --git a/pages/arenateams.php b/pages/arenateams.php index 5bde8627..d5a81c52 100644 --- a/pages/arenateams.php +++ b/pages/arenateams.php @@ -17,6 +17,8 @@ class ArenaTeamsPage extends GenericPage protected $tpl = 'arena-teams'; protected $js = ['filters.js', 'profile_all.js', 'profile.js']; + protected $_get = ['filter' => ['filter' => FILTER_UNSAFE_RAW]]; + public function __construct($pageCall, $pageParam) { if (!CFG_PROFILER_ENABLE) @@ -66,7 +68,7 @@ class ArenaTeamsPage extends GenericPage // recreate form selection $this->filter = $this->filterObj->getForm(); - $this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : null; + $this->filter['query'] = $this->_get['filter']; $this->filter['initData'] = ['type' => 'arenateams']; $tabData = array( diff --git a/pages/compare.php b/pages/compare.php index e628b3d5..a53f6c3f 100644 --- a/pages/compare.php +++ b/pages/compare.php @@ -23,17 +23,20 @@ class ComparePage extends GenericPage protected $summary = []; protected $cmpItems = []; + protected $_get = ['compare' => ['filter' => FILTER_CALLBACK, 'options' => 'ComparePage::checkCompareString']]; + protected $_cookie = ['compare_groups' => ['filter' => FILTER_CALLBACK, 'options' => 'ComparePage::checkCompareString']]; + private $compareString = ''; public function __construct($pageCall, $__) { parent::__construct($pageCall, $__); - // prefer $_GET over $_COOKIE - if (!empty($_GET['compare'])) - $this->compareString = $_GET['compare']; - else if (!empty($_COOKIE['compare_groups'])) - $this->compareString = urldecode($_COOKIE['compare_groups']); + // prefer GET over COOKIE + if ($this->_get['compare']) + $this->compareString = $this->_get['compare']; + else if ($this->_cookie['compare_groups']) + $this->compareString = $this->_cookie['compare_groups']; $this->name = Lang::main('compareTool'); } @@ -56,14 +59,12 @@ class ComparePage extends GenericPage $items = $outSet = []; foreach ($sets as $set) { - $itemSting = explode(':', $set); - $outString = []; - foreach ($itemSting as $substring) + $itemString = explode(':', $set); + $outString = []; + foreach ($itemString as $is) { - $params = explode('.', $substring); + $params = array_pad(explode('.', $is), 7, 0); $items[] = (int)$params[0]; - while (sizeof($params) < 7) - $params[] = 0; $outString[] = $params; } @@ -100,6 +101,15 @@ class ComparePage extends GenericPage } protected function generatePath() {} + + private function checkCompareString(string $val) : string + { + $val = urldecode($val); + if (preg_match('/[^\d\.:;]/', $val)) + return ''; + + return $val; + } } ?> diff --git a/pages/currency.php b/pages/currency.php index 8a64bd2a..c2dd3945 100644 --- a/pages/currency.php +++ b/pages/currency.php @@ -17,6 +17,8 @@ class CurrencyPage extends GenericPage protected $tabId = 0; protected $mode = CACHE_TYPE_PAGE; + protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain']]; + private $powerTpl = '$WowheadPower.registerCurrency(%d, %d, %s);'; public function __construct($pageCall, $id) @@ -24,8 +26,8 @@ class CurrencyPage extends GenericPage parent::__construct($pageCall, $id); // temp locale - if ($this->mode == CACHE_TYPE_TOOLTIP && isset($_GET['domain'])) - Util::powerUseLocale($_GET['domain']); + if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain']) + Util::powerUseLocale($this->_get['domain']); $this->typeId = intVal($id); diff --git a/pages/enchantments.php b/pages/enchantments.php index 6d70a6b8..bd56a168 100644 --- a/pages/enchantments.php +++ b/pages/enchantments.php @@ -17,6 +17,8 @@ class EnchantmentsPage extends GenericPage protected $mode = CACHE_TYPE_PAGE; protected $js = ['filters.js']; + protected $_get = ['filter' => ['filter' => FILTER_UNSAFE_RAW]]; + public function __construct($pageCall, $pageParam) { $this->getCategoryFromUrl($pageParam);; @@ -50,7 +52,7 @@ class EnchantmentsPage extends GenericPage // recreate form selection $this->filter = $this->filterObj->getForm(); - $this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : NULL; + $this->filter['query'] = $this->_get['filter']; $this->filter['initData'] = ['init' => 'enchantments']; if ($x = $this->filterObj->getSetCriteria()) diff --git a/pages/event.php b/pages/event.php index a0ca3181..256e8752 100644 --- a/pages/event.php +++ b/pages/event.php @@ -17,6 +17,8 @@ class EventPage extends GenericPage protected $tabId = 0; protected $mode = CACHE_TYPE_PAGE; + protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain']]; + private $powerTpl = '$WowheadPower.registerHoliday(%d, %d, %s);'; private $hId = 0; private $eId = 0; @@ -26,8 +28,8 @@ class EventPage extends GenericPage parent::__construct($pageCall, $id); // temp locale - if ($this->mode == CACHE_TYPE_TOOLTIP && isset($_GET['domain'])) - Util::powerUseLocale($_GET['domain']); + if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain']) + Util::powerUseLocale($this->_get['domain']); $this->typeId = intVal($id); diff --git a/pages/genericPage.class.php b/pages/genericPage.class.php index a35b81e6..a6d29fb4 100644 --- a/pages/genericPage.class.php +++ b/pages/genericPage.class.php @@ -167,6 +167,8 @@ trait TrProfiler class GenericPage { + use TrRequestData; + protected $tpl = ''; protected $reqUGroup = U_GROUP_NONE; protected $reqAuth = false; @@ -238,6 +240,8 @@ class GenericPage { $this->time = microtime(true); + $this->initRequestData(); + if (!isset($this->contribute)) $this->contribute = CONTRIBUTE_NONE; diff --git a/pages/guilds.php b/pages/guilds.php index 7e3175f8..2e09cd1d 100644 --- a/pages/guilds.php +++ b/pages/guilds.php @@ -17,6 +17,8 @@ class GuildsPage extends GenericPage protected $tpl = 'guilds'; protected $js = ['filters.js', 'profile_all.js', 'profile.js']; + protected $_get = ['filter' => ['filter' => FILTER_UNSAFE_RAW]]; + public function __construct($pageCall, $pageParam) { if (!CFG_PROFILER_ENABLE) @@ -67,7 +69,7 @@ class GuildsPage extends GenericPage // recreate form selection $this->filter = $this->filterObj->getForm(); - $this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : null; + $this->filter['query'] = $this->_get['filter']; $this->filter['initData'] = ['type' => 'guilds']; $tabData = array( diff --git a/pages/icons.php b/pages/icons.php index d702f6d4..5f029672 100644 --- a/pages/icons.php +++ b/pages/icons.php @@ -17,6 +17,8 @@ class IconsPage extends GenericPage protected $mode = CACHE_TYPE_PAGE; protected $js = ['filters.js']; + protected $_get = ['filter' => ['filter' => FILTER_UNSAFE_RAW]]; + public function __construct($pageCall) { $this->filterObj = new IconListFilter(); @@ -49,7 +51,7 @@ class IconsPage extends GenericPage // recreate form selection $this->filter = $this->filterObj->getForm(); - $this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : null; + $this->filter['query'] = $this->_get['filter']; $this->filter['initData'] = ['init' => 'icons']; if ($x = $this->filterObj->getSetCriteria()) diff --git a/pages/item.php b/pages/item.php index f84f243b..7a1f22a9 100644 --- a/pages/item.php +++ b/pages/item.php @@ -23,6 +23,14 @@ class ItemPage extends genericPage 'filters.js' // lolwut? ); + protected $_get = array( + 'domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain'], + 'rand' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkInt'], + 'ench' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkInt'], + 'gems' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkIntArray'], + 'sock' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkEmptySet'] + ); + private $powerTpl = '$WowheadPower.registerItem(%s, %d, %s);'; public function __construct($pageCall, $param) @@ -36,23 +44,23 @@ class ItemPage extends genericPage if ($this->mode == CACHE_TYPE_TOOLTIP) { // temp locale - if (isset($_GET['domain'])) - Util::powerUseLocale($_GET['domain']); + if ($this->_get['domain']) + Util::powerUseLocale($this->_get['domain']); - if (isset($_GET['rand'])) - $this->enhancedTT['r'] = $_GET['rand']; - if (isset($_GET['ench'])) - $this->enhancedTT['e'] = $_GET['ench']; - if (isset($_GET['gems'])) - $this->enhancedTT['g'] = explode(':', $_GET['gems']); - if (isset($_GET['sock'])) + if ($this->_get['rand']) + $this->enhancedTT['r'] = $this->_get['rand']; + if ($this->_get['ench']) + $this->enhancedTT['e'] = $this->_get['ench']; + if ($this->_get['gems']) + $this->enhancedTT['g'] = $this->_get['gems']; + if ($this->_get['sock']) $this->enhancedTT['s'] = ''; } else if ($this->mode == CACHE_TYPE_XML) { // temp locale - if (isset($_GET['domain'])) - Util::powerUseLocale($_GET['domain']); + if ($this->_get['domain']) + Util::powerUseLocale($this->_get['domain']); // allow lookup by name for xml if (!is_numeric($param)) diff --git a/pages/items.php b/pages/items.php index f4cfaa20..9200081b 100644 --- a/pages/items.php +++ b/pages/items.php @@ -16,6 +16,9 @@ class ItemsPage extends GenericPage protected $tabId = 0; protected $mode = CACHE_TYPE_PAGE; protected $js = ['filters.js', 'swfobject.js']; + + protected $_get = ['filter' => ['filter' => FILTER_UNSAFE_RAW]]; + protected $validCats = array( // if > 0 class => subclass 2 => [15, 13, 0, 4, 7, 6, 10, 1, 5, 8, 2, 18, 3, 16, 19, 20, 14], 4 => array( @@ -109,7 +112,7 @@ class ItemsPage extends GenericPage $conditions[] = $_; $this->filter = $this->filterObj->getForm(); - $this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : null; + $this->filter['query'] = $this->_get['filter']; $this->filter['initData'] = ['init' => 'items']; if ($x = $this->filterObj->getSetCriteria()) diff --git a/pages/itemset.php b/pages/itemset.php index 3667d369..9d9c9b15 100644 --- a/pages/itemset.php +++ b/pages/itemset.php @@ -21,6 +21,8 @@ class ItemsetPage extends GenericPage 'Summary.js' ); + protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain']]; + private $powerTpl = '$WowheadPower.registerItemSet(%d, %d, %s);'; public function __construct($pageCall, $id) @@ -28,8 +30,8 @@ class ItemsetPage extends GenericPage parent::__construct($pageCall, $id); // temp locale - if ($this->mode == CACHE_TYPE_TOOLTIP && isset($_GET['domain'])) - Util::powerUseLocale($_GET['domain']); + if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain']) + Util::powerUseLocale($this->_get['domain']); $this->typeId = intVal($id); diff --git a/pages/itemsets.php b/pages/itemsets.php index 1bbf059f..db7494ee 100644 --- a/pages/itemsets.php +++ b/pages/itemsets.php @@ -17,6 +17,8 @@ class ItemsetsPage extends GenericPage protected $mode = CACHE_TYPE_PAGE; protected $js = ['filters.js']; + protected $_get = ['filter' => ['filter' => FILTER_UNSAFE_RAW]]; + public function __construct($pageCall, $pageParam) { $this->getCategoryFromUrl($pageParam); @@ -44,7 +46,7 @@ class ItemsetsPage extends GenericPage // recreate form selection $this->filter = $this->filterObj->getForm(); - $this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : NULL; + $this->filter['query'] = $this->_get['filter']; $this->filter['initData'] = ['init' => 'itemsets']; if ($x = $this->filterObj->getSetCriteria()) diff --git a/pages/npc.php b/pages/npc.php index 43d10e14..8e88ed63 100644 --- a/pages/npc.php +++ b/pages/npc.php @@ -19,6 +19,8 @@ class NpcPage extends GenericPage protected $js = ['swfobject.js']; protected $css = [['path' => 'Profiler.css']]; + protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain']]; + private $soundIds = []; private $powerTpl = '$WowheadPower.registerNpc(%d, %d, %s);'; @@ -27,8 +29,8 @@ class NpcPage extends GenericPage parent::__construct($pageCall, $id); // temp locale - if ($this->mode == CACHE_TYPE_TOOLTIP && isset($_GET['domain'])) - Util::powerUseLocale($_GET['domain']); + if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain']) + Util::powerUseLocale($this->_get['domain']); $this->typeId = intVal($id); diff --git a/pages/npcs.php b/pages/npcs.php index a90ffd30..db2410e8 100644 --- a/pages/npcs.php +++ b/pages/npcs.php @@ -18,6 +18,8 @@ class NpcsPage extends GenericPage protected $validCats = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]; protected $js = ['filters.js']; + protected $_get = ['filter' => ['filter' => FILTER_UNSAFE_RAW]]; + public function __construct($pageCall, $pageParam) { $this->getCategoryFromUrl($pageParam);; @@ -54,7 +56,7 @@ class NpcsPage extends GenericPage // recreate form selection $this->filter = $this->filterObj->getForm(); - $this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : null; + $this->filter['query'] = $this->_get['filter']; $this->filter['initData'] = ['init' => 'npcs']; $rCols = $this->filterObj->getReputationCols(); diff --git a/pages/object.php b/pages/object.php index 05a19661..87b2bd09 100644 --- a/pages/object.php +++ b/pages/object.php @@ -18,6 +18,8 @@ class ObjectPage extends GenericPage protected $mode = CACHE_TYPE_PAGE; protected $js = ['swfobject.js']; + protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain']]; + private $powerTpl = '$WowheadPower.registerObject(%d, %d, %s);'; public function __construct($pageCall, $id) @@ -25,8 +27,8 @@ class ObjectPage extends GenericPage parent::__construct($pageCall, $id); // temp locale - if ($this->mode == CACHE_TYPE_TOOLTIP && isset($_GET['domain'])) - Util::powerUseLocale($_GET['domain']); + if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain']) + Util::powerUseLocale($this->_get['domain']); $this->typeId = intVal($id); diff --git a/pages/objects.php b/pages/objects.php index 5f6fd68b..1932d977 100644 --- a/pages/objects.php +++ b/pages/objects.php @@ -18,6 +18,8 @@ class ObjectsPage extends GenericPage protected $validCats = [-2, -3, -4, -5, -6, 0, 3, 9, 25]; protected $js = ['filters.js']; + protected $_get = ['filter' => ['filter' => FILTER_UNSAFE_RAW]]; + public function __construct($pageCall, $pageParam) { $this->getCategoryFromUrl($pageParam);; @@ -43,7 +45,7 @@ class ObjectsPage extends GenericPage // recreate form selection $this->filter = $this->filterObj->getForm(); - $this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : null; + $this->filter['query'] = $this->_get['filter']; $this->filter['initData'] = ['init' => 'objects']; if ($x = $this->filterObj->getSetCriteria()) diff --git a/pages/profile.php b/pages/profile.php index 79b2f861..d71fe4ae 100644 --- a/pages/profile.php +++ b/pages/profile.php @@ -24,10 +24,15 @@ class ProfilePage extends GenericPage ['path' => 'Profiler.css'] ); - private $isCustom = false; - private $profile = null; - private $rnItr = 0; - private $powerTpl = '$WowheadPower.registerProfile(%s, %d, %s);'; + protected $_get = array( + 'domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain'], + 'new' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkEmptySet'] + ); + + private $isCustom = false; + private $profile = null; + private $rnItr = 0; + private $powerTpl = '$WowheadPower.registerProfile(%s, %d, %s);'; public function __construct($pageCall, $pageParam) { @@ -43,8 +48,8 @@ class ProfilePage extends GenericPage parent::__construct($pageCall, $pageParam); // temp locale - if ($this->mode == CACHE_TYPE_TOOLTIP && isset($_GET['domain'])) - Util::powerUseLocale($_GET['domain']); + if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain']) + Util::powerUseLocale($this->_get['domain']); if (count($params) == 1 && intval($params[0])) { @@ -125,9 +130,9 @@ class ProfilePage extends GenericPage else $this->notFound(); } - else if (($params && $params[0]) || !isset($_GET['new'])) + else if (($params && $params[0]) || !$this->_get['new']) $this->notFound(); - else if (isset($_GET['new'])) + else if ($this->_get['new']) $this->mode = CACHE_TYPE_NONE; } diff --git a/pages/profiles.php b/pages/profiles.php index da76266a..cb82c6f5 100644 --- a/pages/profiles.php +++ b/pages/profiles.php @@ -20,6 +20,8 @@ class ProfilesPage extends GenericPage protected $js = ['filters.js', 'profile_all.js', 'profile.js']; protected $css = [['path' => 'Profiler.css']]; + protected $_get = ['filter' => ['filter' => FILTER_UNSAFE_RAW]]; + public function __construct($pageCall, $pageParam) { if (!CFG_PROFILER_ENABLE) @@ -76,7 +78,7 @@ class ProfilesPage extends GenericPage // recreate form selection $this->filter = $this->filterObj->getForm(); - $this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : null; + $this->filter['query'] = $this->_get['filter']; $this->filter['initData'] = ['init' => 'profiles']; if ($x = $this->filterObj->getSetCriteria()) diff --git a/pages/quest.php b/pages/quest.php index 96cc30e9..00dab396 100644 --- a/pages/quest.php +++ b/pages/quest.php @@ -19,6 +19,8 @@ class QuestPage extends GenericPage protected $css = [['path' => 'Book.css']]; protected $js = ['ShowOnMap.js']; + protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain']]; + private $catExtra = array( 3526 => 3524, 363 => 14, @@ -39,8 +41,8 @@ class QuestPage extends GenericPage parent::__construct($pageCall, $id); // temp locale - if ($this->mode == CACHE_TYPE_TOOLTIP && isset($_GET['domain'])) - Util::powerUseLocale($_GET['domain']); + if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain']) + Util::powerUseLocale($this->_get['domain']); $this->typeId = intVal($id); diff --git a/pages/quests.php b/pages/quests.php index 580506da..3e6bc517 100644 --- a/pages/quests.php +++ b/pages/quests.php @@ -17,6 +17,8 @@ class QuestsPage extends GenericPage protected $validCats = []; protected $js = ['filters.js']; + protected $_get = ['filter' => ['filter' => FILTER_UNSAFE_RAW]]; + public function __construct($pageCall, $pageParam) { $this->validCats = Game::$questClasses; // not allowed to set this as default @@ -51,7 +53,7 @@ class QuestsPage extends GenericPage // recreate form selection $this->filter = $this->filterObj->getForm(); - $this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : null; + $this->filter['query'] = $this->_get['filter']; $this->filter['initData'] = ['init' => 'quests']; $rCols = $this->filterObj->getReputationCols(); diff --git a/pages/screenshot.php b/pages/screenshot.php index 6be7f109..ab667cbe 100644 --- a/pages/screenshot.php +++ b/pages/screenshot.php @@ -27,6 +27,11 @@ class ScreenshotPage extends GenericPage protected $destTypeId = 0; protected $imgHash = ''; + protected $_post = array( + 'coords' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkIdListUnsigned'], + 'screenshotalt' => ['filter' => FILTER_UNSAFE_RAW] + ); + public function __construct($pageCall, $pageParam) { parent::__construct($pageCall, $pageParam); @@ -191,10 +196,10 @@ class ScreenshotPage extends GenericPage return 1; // check post data - if (empty($_POST) || empty($_POST['coords'])) + if (!$this->_post['coords']) return 2; - $dims = explode(',', $_POST['coords']); + $dims = $this->_post['coords']; if (count($dims) != 4) return 3; @@ -220,7 +225,7 @@ class ScreenshotPage extends GenericPage $this->destType, $this->destTypeId, User::$id, $w, $h, - $_POST['screenshotalt'] ?? '' + $this->_post['screenshotalt'] ?? '' ); // write to file diff --git a/pages/search.php b/pages/search.php index f7936267..58b6f452 100644 --- a/pages/search.php +++ b/pages/search.php @@ -36,6 +36,15 @@ class SearchPage extends GenericPage protected $search = ''; // output protected $invalid = []; + protected $_get = array( + 'wt' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkIntArray'], + 'wtv' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkIntArray'], + 'slots' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkIntArray'], + 'type' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkInt'], + 'json' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkEmptySet'], + 'opensearch' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkEmptySet'] + ); + private $maxResults = CFG_SQL_LIMIT_SEARCH; private $searchMask = 0x0; private $query = ''; // lookup @@ -53,18 +62,20 @@ class SearchPage extends GenericPage public function __construct($pageCall, $pageParam) { - $this->search = - $this->query = trim(urlDecode($pageParam)); - // restricted access if ($this->reqUGroup && !User::isInGroup($this->reqUGroup)) $this->error(); + parent::__construct($pageCall, $pageParam); // just to set g_user and g_locale + + $this->search = + $this->query = trim(urlDecode($pageParam)); + // sanitize stat weights - if (!empty($_GET['wt']) && !empty($_GET['wtv'])) + if ($this->_get['wt'] && $this->_get['wtv']) { - $wt = explode(':', $_GET['wt']); - $wtv = explode(':', $_GET['wtv']); + $wt = $this->_get['wt']; + $wtv = $this->_get['wtv']; $nwt = count($wt); $nwtv = count($wtv); @@ -74,25 +85,23 @@ class SearchPage extends GenericPage array_splice($wtv, $nwt); if ($wt && $wtv) - $this->statWeights = [array_map('intVal', $wt), array_map('intVal', $wtv)]; + $this->statWeights = [$wt, $wtv]; } // select search mode - if (isset($_GET['json'])) + if ($this->_get['json']) { if ($_ = intVal($this->search)) // allow for search by Id $this->query = $_; - $type = isset($_GET['type']) ? intVal($_GET['type']) : 0; - - if (!empty($_GET['slots'])) + if ($this->_get['slots']) $this->searchMask |= SEARCH_TYPE_JSON | 0x40; - else if ($type == TYPE_ITEMSET) + else if ($this->_get['type'] == TYPE_ITEMSET) $this->searchMask |= SEARCH_TYPE_JSON | 0x60; - else if ($type == TYPE_ITEM) + else if ($this->_get['type'] == TYPE_ITEM) $this->searchMask |= SEARCH_TYPE_JSON | 0x40; } - else if (isset($_GET['opensearch'])) + else if ($this->_get['opensearch']) { $this->maxResults = CFG_SQL_LIMIT_QUICKSEARCH; $this->searchMask |= SEARCH_TYPE_OPEN | SEARCH_MASK_OPEN; @@ -104,8 +113,6 @@ class SearchPage extends GenericPage if (CFG_MAINTENANCE && !User::isInGroup(U_GROUP_EMPLOYEE) && !($this->searchMask & SEARCH_TYPE_REGULAR)) $this->notFound(); - parent::__construct($pageCall, $pageParam); // just to set g_user and g_locale - // fill include, exclude and ignore $this->tokenizeQuery(); @@ -555,8 +562,7 @@ class SearchPage extends GenericPage $cnd[] = ['i.class', [ITEM_CLASS_WEAPON, ITEM_CLASS_GEM, ITEM_CLASS_ARMOR]]; $cnd[] = $cndAdd; - $slots = isset($_GET['slots']) ? explode(':', $_GET['slots']) : []; - if ($_ = array_filter(array_map('intVal', $slots))) + if ($_ = array_filter($this->_get['slots'])) $cnd[] = ['slot', $_]; // trick ItemListFilter into evaluating weights diff --git a/pages/sound.php b/pages/sound.php index 91516296..d64d0079 100644 --- a/pages/sound.php +++ b/pages/sound.php @@ -16,15 +16,17 @@ class SoundPage extends GenericPage protected $tabId = 0; protected $mode = CACHE_TYPE_PAGE; - private $cat = 0; protected $special = false; + protected $_get = ['playlist' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkEmptySet']]; + + private $cat = 0; public function __construct($pageCall, $id) { parent::__construct($pageCall, $id); // special case - if (!$id && isset($_GET['playlist'])) + if (!$id && $this->_get['playlist']) { $this->special = true; $this->name = Lang::sound('cat', 1000); diff --git a/pages/sounds.php b/pages/sounds.php index 643a3b2f..b3c59b69 100644 --- a/pages/sounds.php +++ b/pages/sounds.php @@ -18,6 +18,8 @@ class SoundsPage extends GenericPage protected $validCats = [1, 2, 3, 4, 6, 9, 10, 12, 13, 14, 16, 17, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 50, 52, 53]; protected $js = ['filters.js']; + protected $_get = ['filter' => ['filter' => FILTER_UNSAFE_RAW]]; + public function __construct($pageCall, $pageParam) { $this->getCategoryFromUrl($pageParam);; @@ -43,7 +45,7 @@ class SoundsPage extends GenericPage $conditions[] = $_; $this->filter = $this->filterObj->getForm(); - $this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : null; + $this->filter['query'] = $this->_get['filter']; $tabData = []; $sounds = new SoundList($conditions); diff --git a/pages/spell.php b/pages/spell.php index 425fede9..d30c7032 100644 --- a/pages/spell.php +++ b/pages/spell.php @@ -18,6 +18,8 @@ class SpellPage extends GenericPage protected $mode = CACHE_TYPE_PAGE; protected $js = ['swfobject.js']; + protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain']]; + private $difficulties = []; private $firstRank = 0; private $powerTpl = '$WowheadPower.registerSpell(%d, %d, %s);'; @@ -27,8 +29,8 @@ class SpellPage extends GenericPage parent::__construct($pageCall, $id); // temp locale - if ($this->mode == CACHE_TYPE_TOOLTIP && isset($_GET['domain'])) - Util::powerUseLocale($_GET['domain']); + if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain']) + Util::powerUseLocale($this->_get['domain']); $this->typeId = intVal($id); diff --git a/pages/spells.php b/pages/spells.php index e20bdba8..ab4e86ec 100644 --- a/pages/spells.php +++ b/pages/spells.php @@ -16,6 +16,9 @@ class SpellsPage extends GenericPage protected $tabId = 0; protected $mode = CACHE_TYPE_PAGE; protected $js = ['filters.js']; + + protected $_get = ['filter' => ['filter' => FILTER_UNSAFE_RAW]]; + protected $validCats = array( -2 => array( // Talents: Class => Skill 1 => [ 26, 256, 257], @@ -412,7 +415,7 @@ class SpellsPage extends GenericPage // recreate form selection $this->filter = $this->filterObj->getForm(); - $this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : NULL; + $this->filter['query'] = $this->_get['filter']; $this->filter['initData'] = ['init' => 'spells']; if ($ec = $this->filterObj->getExtraCols()) diff --git a/pages/utility.php b/pages/utility.php index 68719b93..93e107ed 100644 --- a/pages/utility.php +++ b/pages/utility.php @@ -17,6 +17,8 @@ class UtilityPage extends GenericPage 'unrated-comments', 11 => 'latest-videos', 12 => 'most-comments', 13 => 'missing-screenshots' ); + protected $_get = ['rss' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkEmptySet']]; + private $page = ''; private $rss = false; private $feedData = []; @@ -28,7 +30,7 @@ class UtilityPage extends GenericPage parent::__construct($pageCall, $pageParam); $this->page = $pageCall; - $this->rss = isset($_GET['rss']); + $this->rss = $this->_get['rss']; if ($this->page != 'random') $this->name = Lang::main('utilities', array_search($pageCall, $this->validPages)); diff --git a/template/bricks/pageTemplate.tpl.php b/template/bricks/pageTemplate.tpl.php index ab722116..45fee1b2 100644 --- a/template/bricks/pageTemplate.tpl.php +++ b/template/bricks/pageTemplate.tpl.php @@ -5,7 +5,7 @@ if ($this->contribute & CONTRIBUTE_CO): endif; if ($this->contribute & CONTRIBUTE_SS): - echo " var lv_screenshots = ".Util::toJSON($this->community['sc']).";\n"; + echo " var lv_screenshots = ".Util::toJSON($this->community['ss']).";\n"; endif; if ($this->contribute & CONTRIBUTE_VI): echo " var lv_videos = ".Util::toJSON($this->community['vi']).";\n";