$getValue) { if ($count > 0) $string .= '&'; header('Location: ' . $location . '?' . http_build_query($getArray)); exit; } header("Location: {$location}?{$string}"); exit(); } // Sweet error reporting function data_dump($print = false, $var = false, $title = false) { if ($title !== false) echo "
$title
"; else echo ''; if ($print !== false) { echo 'Print: - '; print_r($print); echo "
"; } if ($var !== false) { echo 'Var_dump: - '; var_dump($var); } echo '
'; } function accountAccess($accountId, $TFS) { $accountId = (int)$accountId; $access = 0; // TFS 0.3/4 $yourChars = db()->fetchAll("SELECT `name`, `group_id`, `account_id` FROM `players` WHERE `account_id` = ?;", [$accountId]); if ($yourChars !== false) { foreach ($yourChars as $char) { if ($TFS === 'TFS_03' || $TFS === 'OTHIRE') { if ($char['group_id'] > $access) $access = $char['group_id']; } else { if ($char['group_id'] > 1) { if ($access == 0) { $acc = db()->fetchOne("SELECT `type` FROM `accounts` WHERE `id` = ? LIMIT 1;", [$char['account_id']]); $access = $acc['type']; } } } } if ($access == 0) $access++; return $access; } else return false; // } // Generate recovery key function generate_recovery_key($length) { return substr(bin2hex(random_bytes(32)), 0, (int)$length); } // Calculate discount function calculate_discount($orig, $new) { $orig = (int)$orig; $new = (int)$new; $tmp = ''; if ($new >= $orig) { if ($new != $orig) { $calc = ($new/$orig) - 1; $calc *= 100; $tmp = '+'. floor($calc) .'%'; } else $tmp = '0%'; } else { $calc = 1 - ($new/$orig); $calc *= 100; $tmp = '-'. floor($calc) .'%'; } return $tmp; } // Proper URLs function url($path = false) { $folder = dirname($_SERVER['SCRIPT_NAME']); return config('site_url') . '/' . $path; } function getCache() { $results = db()->fetchOne("SELECT `cached` FROM `znote`;"); return ($results !== false) ? $results['cached'] : false; } function setCache($time) { db()->execute("UPDATE `znote` set `cached` = ?", [(int)$time]); } // Get visitor basic data function znote_visitors_get_data() { return db()->fetchAll("SELECT `ip`, `value` FROM `znote_visitors` ORDER BY `id` DESC LIMIT 1000;"); } // Set visitor basic data function znote_visitor_set_data($visitor_data) { $exist = false; $ip = getIPLong(); foreach ((array)$visitor_data as $row) { if ($ip == $row['ip']) { $exist = true; $value = $row['value']; } } if ($exist && isset($value)) { // Update the value $value++; db()->execute("UPDATE `znote_visitors` SET `value` = ? WHERE `ip` = ?", [$value, $ip]); } else { // Insert new row db()->execute("INSERT INTO `znote_visitors` (`ip`, `value`) VALUES (?, 1)", [$ip]); } } // Get visitor basic data function znote_visitors_get_detailed_data($cache_time) { $period = (int)time() - (int)$cache_time; return db()->fetchAll("SELECT `ip`, `time`, `type`, `account_id` FROM `znote_visitors_details` WHERE `time` >= ? LIMIT 0, 50", [$period]); } function znote_visitor_insert_detailed_data($type) { $type = (int)$type; /* type 0 = normal visits type 1 = register form type 2 = character creation type 3 = fetch highscores type 4 = search character */ $time = time(); $ip = getIPLong(); $acc = user_logged_in() ? (int)getSession('user_id') : 0; db()->execute("INSERT INTO `znote_visitors_details` (`ip`, `time`, `type`, `account_id`) VALUES (?, ?, ?, ?)", [$ip, $time, $type, $acc]); } function something () { // Make acc data compatible: $ip = getIPLong(); } // Secret token function create_token() { if (empty($_SESSION['token'])) { $_SESSION['token'] = bin2hex(random_bytes(32)); } echo ''; } function reset_token() { echo 'Reseting token
'; unset($_SESSION['token']); } // Time based functions // 60 seconds to 1 minute function second_to_minute($seconds) { return ($seconds / 60); } // 1 minute to 60 seconds function minute_to_seconds($minutes) { return ($minutes * 60); } // 60 minutes to 1 hour function minute_to_hour($minutes) { return ($minutes / 60); } // 1 hour to 60 minutes function hour_to_minute($hours) { return $hours * 60; } // seconds / 60 / 60 = hours. function seconds_to_hours($seconds) { $minutes = second_to_minute($seconds); $hours = minute_to_hour($minutes); return $hours; } function remaining_seconds_to_clock($seconds) { return date("(H:i)",time() + $seconds); } /** * Check if name contains more than configured max words * * @param string $string * @return string|boolean */ function validate_name($string) { $max = config('maxW') ?? 3; return (str_word_count(trim($string)) > $max) ? false : trim($string); } // Checks if an IPv4(or localhost IPv6) address is valid function validate_ip($ip) { $ipL = safeIp2Long($ip); $ipR = long2ip((int)$ipL); if ($ip === $ipR) { return true; } elseif ($ip=='::1') { return true; } else { return false; } } // Fetch a config value. Etc config('vocations') will return vocation array from config.php. function config($value) { global $config; return $config[$value] ?? null; } function serverEngineReal() { global $config; return $config['ServerEngineReal'] ?? ($config['ServerEngine'] ?? 'TFS_10'); } function engineIsCanary() { return serverEngineReal() === 'CANARY'; } function engineIsTFS16() { return serverEngineReal() === 'TFS_16'; } function accountField($field) { if ($field === 'premium_ends_at') { if (function_exists('znote_column_exists') && znote_column_exists('accounts', 'premium_ends_at')) { return '`premium_ends_at`'; } if (function_exists('znote_column_exists') && znote_column_exists('accounts', 'lastday') && znote_column_exists('accounts', 'premdays')) { return '(`lastday` + (`premdays` * 86400)) AS `premium_ends_at`'; } if (function_exists('znote_column_exists') && znote_column_exists('accounts', 'premdays')) { return '(CASE WHEN `premdays` > 0 THEN UNIX_TIMESTAMP() + (`premdays` * 86400) ELSE 0 END) AS `premium_ends_at`'; } } if (engineIsCanary()) { if ($field === 'secret') return 'NULL AS `secret`'; } return '`' . $field . '`'; } function accountFieldList(array $fields) { return implode(', ', array_map('accountField', $fields)); } function houseCol($name) { if (!engineIsCanary()) return $name; $map = array( 'bid' => 'internal_bid', 'bid_end' => 'bid_end_date', 'last_bid' => 'highest_bid', 'highest_bidder' => 'bidder', ); return $map[$name] ?? $name; } function houseSelect(array $fields, $prefix = '') { $p = ($prefix !== '') ? '`' . $prefix . '`.' : ''; $out = array(); foreach ($fields as $f) { $phys = houseCol($f); $out[] = ($phys === $f) ? $p . '`' . $f . '`' : $p . '`' . $phys . '` AS `' . $f . '`'; } return implode(', ', $out); } function sqlIpWrite($ipLong) { if (engineIsTFS16()) { return "INET6_ATON('" . mysql_znote_escape_string(long2ip((int)$ipLong)) . "')"; } return "'" . (int)$ipLong . "'"; } function sqlIpSelect($column, $alias, $prefix = '') { $p = ($prefix !== '') ? '`' . $prefix . '`.' : ''; if (engineIsTFS16()) { return 'INET_ATON(INET6_NTOA(' . $p . '`' . $column . '`)) AS `' . $alias . '`'; } return $p . '`' . $column . '` AS `' . $alias . '`'; } // Some functions uses several configurations from config.php, so it sounds // smarter to give them the whole array instead of calling the function all the time. function fullConfig() { global $config; return $config; } // Capitalize Every Word In String. function format_character_name($name) { return ucwords(strtolower($name)); } // Gets you the actual IP address even from users behind ISP proxies and so on. function getIP() { /* $IP = ''; if (getenv('HTTP_CLIENT_IP')) { $IP =getenv('HTTP_CLIENT_IP'); } elseif (getenv('HTTP_X_FORWARDED_FOR')) { $IP =getenv('HTTP_X_FORWARDED_FOR'); } elseif (getenv('HTTP_X_FORWARDED')) { $IP =getenv('HTTP_X_FORWARDED'); } elseif (getenv('HTTP_FORWARDED_FOR')) { $IP =getenv('HTTP_FORWARDED_FOR'); } elseif (getenv('HTTP_FORWARDED')) { $IP = getenv('HTTP_FORWARDED'); } else { $IP = $_SERVER['REMOTE_ADDR']; } */ return $_SERVER['REMOTE_ADDR']; } function safeIp2Long($ip) { return sprintf('%u', ip2long($ip)); } // Gets you the actual IP address even from users in long type function getIPLong() { return safeIp2Long(getIP()); } // Deprecated, just use count($array) instead. function array_length($ar) { return count($ar); } // Parameter: level, returns experience for that level from an experience table. function level_to_experience($level) { return 50/3*(pow($level, 3) - 6*pow($level, 2) + 17*$level - 12); } // Parameter: players.hide_char returns: Status word inside a font with class identifier so it can be designed later on by CSS. function hide_char_to_name($id) { $id = (int)$id; if ($id == 1) { return 'hidden'; } else { return 'visible'; } } // Parameter: players.online returns: Status word inside a font with class identifier so it can be designed later on by CSS. function online_id_to_name($id) { $id = (int)$id; if ($id == 1) { return 'ONLINE'; } else { return 'offline'; } } // Parameter: players.vocation_id. Returns: Configured vocation name. function vocation_id_to_name($id) { $vocations = config('vocations'); return (isset($vocations[$id]['name'])) ? $vocations[$id]['name'] : "{$id} - Unknown"; } // Parameter: players.name. Returns: Configured vocation id. function vocation_name_to_id($name) { $vocations = config('vocations'); foreach ($vocations as $id => $vocation) if ($vocation['name'] == $name) return $id; return false; } // Parameter: players.group_id. Returns: Configured group name. function group_id_to_name($id) { $positions = config('ingame_positions'); return $positions[$id] ?? false; } function gender_exist($gender) { // Range of allowed gender ids, fromid toid if ($gender >= 0 && $gender <= 1) { return true; } else { return false; } } function skillid_to_name($skillid) { $skillname = [ 0 => 'fist fighting', 1 => 'club fighting', 2 => 'sword fighting', 3 => 'axe fighting', 4 => 'distance fighting', 5 => 'shielding', 6 => 'fishing', 7 => 'experience', 8 => 'magic level' ]; return $skillname[$skillid] ?? false; } // Parameter: players.town_id. Returns: Configured town name. function town_id_to_name($id) { $towns = config('towns'); return (array_key_exists($id, $towns)) ? $towns[$id] : 'Missing Town'; } // On this version we included From, because without that nowdays the email is classed directly as spam, using a From prevents that. function email($to, $subject, $body) { $headers = "From: noreply@znoteaac.com\r\nContent-Type: text/plain; charset=UTF-8"; mail($to, $subject, $body, $headers); } function logged_in_redirect() { if (user_logged_in() === true) { header('Location: myaccount.php'); exit; } } function protect_page() { if (user_logged_in() === false) { header('Location: protected.php'); exit; } } // When function is called, you will be redirected to protect_page and deny access to rest of page, as long as you are not admin. function admin_only($user_data) { // Chris way $gotAccess = is_admin($user_data); if ($gotAccess == false) { logged_in_redirect(); exit(); } } function admin_roles($user_data): array { if (!is_array($user_data)) return array(); $identity = config('ServerEngine') === 'OTHIRE' ? ($user_data['id'] ?? null) : ($user_data['name'] ?? null); $owners = (array)config('page_admin_access'); if (in_array($identity, $owners)) { return array('owner'); } $assignments = (array)config('page_admin_roles'); foreach ($assignments as $account => $assigned) { if ((string)$account === (string)$identity) { $modules = is_array($assigned) ? $assigned : array($assigned); return array_values(array_unique(array_filter(array_map( static fn($module) => strtolower(trim((string)$module)), $modules ), static fn($module) => $module !== ''))); } } return array(); } function has_admin_panel_access($user_data): bool { return admin_roles($user_data) !== array(); } // Legacy full-admin checks deliberately remain owner-only. This prevents a // scoped ACP role from inheriting unrestricted forum or maintenance powers. function is_admin($user_data) { return in_array('owner', admin_roles($user_data), true); } function array_sanitize(&$item) { $item = htmlentities(strip_tags(mysql_znote_escape_string($item))); } function sanitize($data) { return htmlspecialchars(strip_tags((string)($data ?? '')), ENT_QUOTES, 'UTF-8'); } function output_errors($errors) { return '