<?php
/*-------------------------------------------------------+
| PHPFusion Content Management System
| Copyright (C) PHP Fusion Inc
| https://phpfusion.com/
+--------------------------------------------------------+
| Filename: core_functions_include.php
| Author: Core Development Team
+--------------------------------------------------------+
| This program is released as free software under the
| Affero GPL license. You can redistribute it and/or
| modify it under the terms of this license which you
| can read by viewing the included agpl.txt or online
| at www.gnu.org/licenses/agpl.html. Removal of this
| copyright header is strictly prohibited without
| written permission from the original author(s).
+--------------------------------------------------------*/
defined('IN_FUSION') || exit;
use Defender\Token;
use PHPFusion\Authenticate;
use PHPFusion\ImageRepo;
use PHPFusion\Minify\JS;
use PHPFusion\PrivateMessages;
use PHPFusion\QuantumFields;
/**
* Get currency symbol by using a 3-letter ISO 4217 currency code
* Note that if INTL pecl package is not installed, signs will degrade to ISO4217 code itself
*
* @param string $iso 3-letter ISO 4217
* @param bool $description Set to false for just symbol
*
* @return array|string Array of currencies or string with one currency.
*/
function fusion_get_currency($iso = NULL, $description = TRUE) {
$locale = fusion_get_locale('', LOCALE.LOCALESET."currency.php");
static $__currency = [];
if (empty($__currency)) {
// Euro Exceptions list
$currency_exceptions = [
"ADF" => "EUR",
"ATS" => "EUR",
"BEF" => "EUR",
"CYP" => "EUR",
"DEM" => "EUR",
"EEK" => "EUR",
"ESP" => "EUR",
"FIM" => "EUR",
"FRF" => "EUR",
"GRD" => "EUR",
"IEP" => "EUR",
"ITL" => "EUR",
"KZT" => "EUR",
"LTL" => "EUR",
"LUF" => "EUR",
"LVL" => "EUR",
"MCF" => "EUR",
"MTL" => "EUR",
"NLG" => "EUR",
"PTE" => "EUR",
"RUB" => "EUR",
"SIT" => "EUR",
"SKK" => "EUR",
"SML" => "EUR",
"VAL" => "EUR",
"DDM" => "EUR",
"ESA" => "EUR",
"ESB" => "EUR",
];
foreach (array_keys($locale['currency']) as $country_iso) {
$c_iso = !empty($currency_exceptions[$country_iso]) ? $currency_exceptions[$country_iso] : $country_iso;
$c_symbol = (!empty($locale['currency_symbol'][$c_iso]) ? html_entity_decode($locale['currency_symbol'][$c_iso], ENT_QUOTES, $locale['charset']) : $c_iso);
$c_text = $locale['currency'][$c_iso];
$__currency[$country_iso] = $description ? $c_text." ($c_symbol)" : $c_symbol;
}
}
return $iso === NULL ? $__currency : (isset($__currency[$iso]) ? $__currency[$iso] : NULL);
}
/**
* Check if a given theme exists and is valid.
*
* @param string $theme The theme folder you want to check.
*
* @return bool False if the theme does not exist and true if it does.
*/
function theme_exists($theme) {
if ($theme == "Default") {
$theme = fusion_get_settings('theme');
}
return is_string($theme) and
preg_match("/^([a-z0-9_-]){2,50}$/i", $theme) and
file_exists(THEMES.$theme."/theme.php") and
file_exists(THEMES.$theme."/styles.css");
}
/**
* Set a valid theme.
*
* @param string $theme The theme folder you want to set.
*/
function set_theme($theme) {
$locale = fusion_get_locale();
if (defined("THEME")) {
return;
}
if (theme_exists($theme)) {
define("THEME", THEMES.($theme == "Default" ? fusion_get_settings('theme') : $theme)."/");
return;
}
foreach (new GlobIterator(THEMES.'*') as $dir) {
if ($dir->isDir() and theme_exists($dir->getBasename())) {
define("THEME", $dir->getPathname()."/");
return;
}
}
// Don't stop if we are in admin panel since we use different themes now
$no_theme_message = str_replace("[SITE_EMAIL]", fusion_get_settings("siteemail"), $locale['global_301']);
if (preg_match("/\/administration\//i", $_SERVER['PHP_SELF'])) {
addnotice('danger', "<strong>".$theme." - ".$locale['global_300'].".</strong><br /><br />\n".$no_theme_message);
} else {
echo "<strong>".$theme." - ".$locale['global_300'].".</strong><br /><br />\n";
echo $no_theme_message;
die();
}
}
/**
* Set password of the currently logged in an administrator.
*
* @param string $password Any password.
*
* @return bool True if a password is set.
*/
function set_admin_pass($password) {
return Authenticate::setAdminCookie($password);
}
/**
* Check if admin password matches userdata.
*
* @param string $password Password.
*
* @return bool True if the password matches the user's admin password or if the admin's cookie or session is set and is valid.
*/
function check_admin_pass($password) {
return Authenticate::validateAuthAdmin($password);
}
/**
* Redirect to internal or external URL.
*
* @param string $location Desintation URL.
* @param bool $delay meta refresh delay.
* @param bool $script True if you want to redirect via javascript.
* @param int $code HTTP status code to send.
*/
function redirect($location, $delay = FALSE, $script = FALSE, $code = 200) {
//define('STOP_REDIRECT', TRUE);
//debug_print_backtrace();
if (!defined('STOP_REDIRECT')) {
if (isnum($delay)) {
$ref = "<meta http-equiv='refresh' content='$delay; url=".$location."' />";
add_to_head($ref);
} else {
if ($script == FALSE && !headers_sent()) {
set_status_header($code);
header("Location: ".str_replace("&", "&", $location));
} else {
echo "<script type='text/javascript'>document.location.href='".str_replace("&", "&", $location)."'</script>\n";
}
exit;
}
}
}
/**
* Set HTTP status header.
*
* @param int $code Status header code.
*
* @return bool Whether header was sent.
*/
function set_status_header($code = 200) {
if (headers_sent()) {
return FALSE;
}
$protocol = $_SERVER['SERVER_PROTOCOL'];
if ('HTTP/1.1' != $protocol && 'HTTP/1.0' != $protocol) {
$protocol = 'HTTP/1.0';
}
$desc = [
100 => 'Continue',
101 => 'Switching Protocols',
102 => 'Processing',
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authoritative Information',
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
207 => 'Multi-Status',
226 => 'IM Used',
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Found',
303 => 'See Other',
304 => 'Not Modified',
305 => 'Use Proxy',
306 => 'Reserved',
307 => 'Temporary Redirect',
400 => 'Bad Request',
401 => 'Unauthorized',
402 => 'Payment Required',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
406 => 'Not Acceptable',
407 => 'Proxy Authentication Required',
408 => 'Request Timeout',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition Failed',
413 => 'Request Entity Too Large',
414 => 'Request-URI Too Long',
415 => 'Unsupported Media Type',
416 => 'Requested Range Not Satisfiable',
417 => 'Expectation Failed',
422 => 'Unprocessable Entity',
423 => 'Locked',
424 => 'Failed Dependency',
426 => 'Upgrade Required',
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Timeout',
505 => 'HTTP Version Not Supported',
506 => 'Variant Also Negotiates',
507 => 'Insufficient Storage',
510 => 'Not Extended'
];
$desc = !empty($desc[$code]) ? $desc[$code] : '';
header("$protocol $code $desc");
return TRUE;
}
/**
* Get HTTP response code.
*
* @param string $url URL.
*
* @return false|string
*/
function get_http_response_code($url) {
if (function_exists('curl_init')) {
$handle = curl_init($url);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, TRUE);
curl_exec($handle);
$http_code = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);
return $http_code;
} else {
stream_context_set_default([
'ssl' => [
'verify_peer' => FALSE,
'verify_peer_name' => FALSE
],
]);
$headers = @get_headers($url);
return substr($headers[0], 9, 3);
}
}
/**
* Clean the URL and prevents entities in server globals.
*
* @param string $url URL.
*
* @return string $url clean and ready for use XHTML strict and without any dangerous code.
*/
function cleanurl($url) {
$bad_entities = ["&", "\"", "'", '\"', "\'", "<", ">", "", "", "*"];
$safe_entities = ["&", "", "", "", "", "", "", "", "", ""];
return str_replace($bad_entities, $safe_entities, $url);
}
/**
* Prevents HTML in unwanted places
*
* @param string|array $text String or array to be stripped.
*
* @return array|string The given string decoded as non HTML text.
*/
function stripinput($text) {
if (!is_array($text) && !is_null($text)) {
return str_replace('\\', '\', htmlspecialchars(stripslashes(trim($text)), ENT_QUOTES));
}
if (is_array($text) && !is_null($text)) {
foreach ($text as $i => $item) {
$text[$i] = stripinput($item);
}
}
return $text;
}
/**
* Prevent any possible XSS attacks via $_GET.
*
* @param array|string $check_url String or array to be stripped.
*
* @return bool True if the URL is not secure.
*/
function stripget($check_url) {
if (is_array($check_url)) {
foreach ($check_url as $value) {
if (stripget($value) == TRUE) {
return TRUE;
}
}
} else {
$check_url = str_replace(["\"", "\'"], ["", ""], urldecode($check_url));
if (preg_match("/<[^<>]+>/i", $check_url)) {
return TRUE;
}
}
return FALSE;
}
/**
* Strips a given filename from any unwanted characters and symbols.
*
* @param string $filename Filename you want to strip. Remember to remove the file extension before parsing it through this function.
*
* @return string The filename stripped and ready for use.
*/
function stripfilename($filename) {
$patterns = [
'/\s+/' => '_',
'/[^a-z0-9_-]|^\W/i' => '',
'/([_-])\1+/' => '$1'
];
return preg_replace(array_keys($patterns), $patterns, strtolower($filename)) ?: (string)time();
}
/**
* Converts all applicable characters to HTML entities.
* htmlentities is too agressive so we use this function.
*
* @param string $text The input string.
*
* @return string Encoded string.
*/
function phpentities($text) {
return str_replace('\\', '\', htmlspecialchars($text, ENT_QUOTES));
}
/**
* Prevent strings from growing to long and breaking the layout.
*
* @param string $text String to trim.
* @param int $length Max length of the string.
*
* @return string String trimmed to the given length.
*/
function trimlink($text, $length) {
if (strlen($text) > $length) {
if (function_exists('mb_substr')) {
$text = mb_substr($text, 0, ($length - 3), 'UTF-8')."...";
} else {
$text = substr($text, 0, ($length - 3))."...";
}
}
return $text;
}
/**
* Trim a text to a number of words.
*
* @param string $text String to trim.
* @param int $limit The number of words.
* @param string $suffix If $text is longer than $limit, $suffix will be appended.
*
* @return string String trimmed to the given length.
*/
function fusion_first_words($text, $limit, $suffix = '…') {
$text = preg_replace('/[\r\n]+/', '', $text);
return preg_replace('~^(\s*\w+'.str_repeat('\W+\w+', $limit - 1).'(?(?=[?!:;.])[[:punct:]]\s*))\b(.+)$~isxu', '$1'.$suffix, strip_tags($text));
}
/**
* Pure trim function.
*
* @param string $str String to trim.
* @param int $length The number of characters.
*
* @return string Trimmed text.
*/
function trim_text($str, $length = 300) {
for ($i = $length; $i <= strlen($str); $i++) {
$spacetest = substr("$str", $i, 1);
if ($spacetest == " ") {
$spaceok = substr("$str", 0, $i);
return ($spaceok."...");
}
}
return ($str);
}
/**
* Replaces special characters in a string with their "non-special" counterpart.
*
* @param string $value String to normalize.
*
* @return string
*/
function normalize($value) {
$table = [
'&' => 'and', '@' => 'at', '©' => 'c', '®' => 'r', 'À' => 'a', '(' => '', ')' => '', '.' => '',
'Á' => 'a', 'Â' => 'a', 'Ä' => 'a', 'Å' => 'a', 'Æ' => 'ae', 'Ç' => 'c',
'È' => 'e', 'É' => 'e', 'Ë' => 'e', 'Ì' => 'i', 'Í' => 'i', 'Î' => 'i',
'Ï' => 'i', 'Ò' => 'o', 'Ó' => 'o', 'Ô' => 'o', 'Õ' => 'o', 'Ö' => 'o',
'Ø' => 'o', 'Ù' => 'u', 'Ú' => 'u', 'Û' => 'u', 'Ü' => 'u', 'Ý' => 'y',
'ß' => 'ss', 'à' => 'a', 'á' => 'a', 'â' => 'a', 'ä' => 'a', 'å' => 'a',
'æ' => 'ae', 'ç' => 'c', 'è' => 'e', 'é' => 'e', 'ê' => 'e', 'ë' => 'e',
'ì' => 'i', 'í' => 'i', 'î' => 'i', 'ï' => 'i', 'ò' => 'o', 'ó' => 'o',
'ô' => 'o', 'õ' => 'o', 'ö' => 'o', 'ø' => 'o', 'ù' => 'u', 'ú' => 'u',
'û' => 'u', 'ü' => 'u', 'ý' => 'y', 'þ' => 'p', 'ÿ' => 'y', 'Ā' => 'a',
'ā' => 'a', 'Ă' => 'a', 'ă' => 'a', 'Ą' => 'a', 'ą' => 'a', 'Ć' => 'c',
'ć' => 'c', 'Ĉ' => 'c', 'ĉ' => 'c', 'Ċ' => 'c', 'ċ' => 'c', 'Č' => 'c',
'č' => 'c', 'Ď' => 'd', 'ď' => 'd', 'Đ' => 'd', 'đ' => 'd', 'Ē' => 'e',
'ē' => 'e', 'Ĕ' => 'e', 'ĕ' => 'e', 'Ė' => 'e', 'ė' => 'e', 'Ę' => 'e',
'ę' => 'e', 'Ě' => 'e', 'ě' => 'e', 'Ĝ' => 'g', 'ĝ' => 'g', 'Ğ' => 'g',
'ğ' => 'g', 'Ġ' => 'g', 'ġ' => 'g', 'Ģ' => 'g', 'ģ' => 'g', 'Ĥ' => 'h',
'ĥ' => 'h', 'Ħ' => 'h', 'ħ' => 'h', 'Ĩ' => 'i', 'ĩ' => 'i', 'Ī' => 'i',
'ī' => 'i', 'Ĭ' => 'i', 'ĭ' => 'i', 'Į' => 'i', 'į' => 'i', 'İ' => 'i',
'ı' => 'i', 'IJ' => 'ij', 'ij' => 'ij', 'Ĵ' => 'j', 'ĵ' => 'j', 'Ķ' => 'k',
'ķ' => 'k', 'ĸ' => 'k', 'Ĺ' => 'l', 'ĺ' => 'l', 'Ļ' => 'l', 'ļ' => 'l',
'Ľ' => 'l', 'ľ' => 'l', 'Ŀ' => 'l', 'ŀ' => 'l', 'Ł' => 'l', 'ł' => 'l',
'Ń' => 'n', 'ń' => 'n', 'Ņ' => 'n', 'ņ' => 'n', 'Ň' => 'n', 'ň' => 'n',
'ʼn' => 'n', 'Ŋ' => 'n', 'ŋ' => 'n', 'Ō' => 'o', 'ō' => 'o', 'Ŏ' => 'o',
'ŏ' => 'o', 'Ő' => 'o', 'ő' => 'o', 'Œ' => 'oe', 'œ' => 'oe', 'Ŕ' => 'r',
'ŕ' => 'r', 'Ŗ' => 'r', 'ŗ' => 'r', 'Ř' => 'r', 'ř' => 'r', 'Ś' => 's',
'ś' => 's', 'Ŝ' => 's', 'ŝ' => 's', 'Ş' => 's', 'ş' => 's', 'Š' => 's',
'š' => 's', 'Ţ' => 't', 'ţ' => 't', 'Ť' => 't', 'ť' => 't', 'Ŧ' => 't',
'ŧ' => 't', 'Ũ' => 'u', 'ũ' => 'u', 'Ū' => 'u', 'ū' => 'u', 'Ŭ' => 'u',
'ŭ' => 'u', 'Ů' => 'u', 'ů' => 'u', 'Ű' => 'u', 'ű' => 'u', 'Ų' => 'u',
'ų' => 'u', 'Ŵ' => 'w', 'ŵ' => 'w', 'Ŷ' => 'y', 'ŷ' => 'y', 'Ÿ' => 'y',
'Ź' => 'z', 'ź' => 'z', 'Ż' => 'z', 'ż' => 'z', 'Ž' => 'z', 'ž' => 'z',
'ſ' => 'z', 'Ə' => 'e', 'ƒ' => 'f', 'Ơ' => 'o', 'ơ' => 'o', 'Ư' => 'u',
'ư' => 'u', 'Ǎ' => 'a', 'ǎ' => 'a', 'Ǐ' => 'i', 'ǐ' => 'i', 'Ǒ' => 'o',
'ǒ' => 'o', 'Ǔ' => 'u', 'ǔ' => 'u', 'Ǖ' => 'u', 'ǖ' => 'u', 'Ǘ' => 'u',
'ǘ' => 'u', 'Ǚ' => 'u', 'ǚ' => 'u', 'Ǜ' => 'u', 'ǜ' => 'u', 'Ǻ' => 'a',
'ǻ' => 'a', 'Ǽ' => 'ae', 'ǽ' => 'ae', 'Ǿ' => 'o', 'ǿ' => 'o', 'ə' => 'e',
'Ё' => 'jo', 'Є' => 'e', 'І' => 'i', 'Ї' => 'i', 'А' => 'a', 'Б' => 'b',
'В' => 'v', 'Г' => 'g', 'Д' => 'd', 'Е' => 'e', 'Ж' => 'zh', 'З' => 'z',
'И' => 'i', 'Й' => 'j', 'К' => 'k', 'Л' => 'l', 'М' => 'm', 'Н' => 'n',
'О' => 'o', 'П' => 'p', 'Р' => 'r', 'С' => 's', 'Т' => 't', 'У' => 'u',
'Ф' => 'f', 'Х' => 'h', 'Ц' => 'c', 'Ч' => 'ch', 'Ш' => 'sh', 'Щ' => 'sch',
'Ъ' => '-', 'Ы' => 'y', 'Ь' => '-', 'Э' => 'je', 'Ю' => 'ju', 'Я' => 'ja',
'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'д' => 'd', 'е' => 'e',
'ж' => 'zh', 'з' => 'z', 'и' => 'i', 'й' => 'j', 'к' => 'k', 'л' => 'l',
'м' => 'm', 'н' => 'n', 'о' => 'o', 'п' => 'p', 'р' => 'r', 'с' => 's',
'т' => 't', 'у' => 'u', 'ф' => 'f', 'х' => 'h', 'ц' => 'c', 'ч' => 'ch',
'ш' => 'sh', 'щ' => 'sch', 'ъ' => '-', 'ы' => 'y', 'ь' => '-', 'э' => 'je',
'ю' => 'ju', 'я' => 'ja', 'ё' => 'jo', 'є' => 'e', 'і' => 'i', 'ї' => 'i',
'Ґ' => 'g', 'ґ' => 'g', 'א' => 'a', 'ב' => 'b', 'ג' => 'g', 'ד' => 'd',
'ה' => 'h', 'ו' => 'v', 'ז' => 'z', 'ח' => 'h', 'ט' => 't', 'י' => 'i',
'ך' => 'k', 'כ' => 'k', 'ל' => 'l', 'ם' => 'm', 'מ' => 'm', 'ן' => 'n',
'נ' => 'n', 'ס' => 's', 'ע' => 'e', 'ף' => 'p', 'פ' => 'p', 'ץ' => 'C',
'צ' => 'c', 'ק' => 'q', 'ר' => 'r', 'ש' => 'w', 'ת' => 't', '™' => 'tm',
'ء' => 'a', 'ا' => 'a', 'آ' => 'a', 'ب' => 'b', 'پ' => 'p', 'ت' => 't',
'ث' => 's', 'ج' => 'j', 'چ' => 'ch', 'ح' => 'h', 'خ' => 'kh', 'د' => 'd',
'ر' => 'r', 'ز' => 'z', 'ژ' => 'zh', 'س' => 's', 'ص' => 's', 'ض' => 'z',
'ط' => 't', 'ظ' => 'z', 'غ' => 'gh', 'ف' => 'f', 'ق' => 'q', 'ک' => 'k',
'گ' => 'g', 'ل' => 'l', 'م' => 'm', 'ن' => 'n', 'و' => 'w', 'ه' => 'h', 'ی' => 'y ',
];
return strtr($value, $table);
}
/**
* Generate random string.
*
* @param int $length The length of the string.
* @param bool $letters_only Only letters.
*
* @return string
*/
function random_string($length = 6, $letters_only = FALSE) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
if ($letters_only) {
$characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
}
$characters_length = strlen($characters);
$random_string = '';
for ($i = 0; $i < $length; $i++) {
$random_string .= $characters[rand(0, $characters_length - 1)];
}
return $random_string;
}
/**
* Validate numeric input.
*
* @param mixed $value The value to be checked.
* @param bool $decimal Decimals.
* @param bool $negative Negative numbers.
*
* @return bool True if the value is a number.
*/
function isnum($value, $decimal = FALSE, $negative = FALSE) {
if ($negative == TRUE) {
return is_numeric($value);
} else {
$float = $decimal ? '(.{0,1})[0-9]*' : '';
return !is_array($value) and preg_match("/^[0-9]+".$float."$/", $value);
}
}
/**
* Custom preg_match function.
*
* @param string $expression The expression to search for.
* @param mixed $value The input string.
*
* @return bool FALSE when $value is an array
*/
function preg_check($expression, $value) {
return !is_array($value) and preg_match($expression, $value);
}
/**
* Generate a clean Request URI.
*
* @param mixed $request_addition 'page=1&ref=2' or array('page' => 1, 'ref' => 2)
* @param array $filter_array array('aid','page', ref')
* @param bool $keep_filtered True to keep filter, false to remove filter from FUSION_REQUEST.
* If remove is true, to remove everything and keep $requests_array and $request
* addition. If remove is false, to keep everything else except $requests_array
*
* @return string
*/
function clean_request($request_addition = '', $filter_array = [], $keep_filtered = TRUE) {
$fusion_query = [];
if (fusion_get_settings("site_seo") && defined('IN_PERMALINK') && !isset($_GET['aid'])) {
global $filepath;
$url['path'] = $filepath;
if (!empty($_GET)) {
$fusion_query = $_GET;
}
} else {
$url = ((array)parse_url(htmlspecialchars_decode($_SERVER['REQUEST_URI']))) + [
'path' => '',
'query' => ''
];
if ($url['query']) {
parse_str($url['query'], $fusion_query); // this is original.
}
}
if ($keep_filtered) {
$fusion_query = array_intersect_key($fusion_query, array_flip($filter_array));
} else {
$fusion_query = array_diff_key($fusion_query, array_flip($filter_array));
}
if ($request_addition) {
$request_addition_array = [];
if (is_array($request_addition)) {
$fusion_query = $fusion_query + $request_addition;
} else {
parse_str($request_addition, $request_addition_array);
$fusion_query = $fusion_query + $request_addition_array;
}
}
$prefix = $fusion_query ? '?' : '';
return $url['path'].$prefix.http_build_query($fusion_query, 'flags_', '&');
}
/**
* Cache of all smileys from the database.
*
* @return array Array of all smileys.
*/
function cache_smileys() {
return ImageRepo::cacheSmileys();
}
/**
* Parse the smileys in string and display smiley codes as smiley images.
*
* @param string $message A string that should have parsed smileys.
*
* @return string String with parsed smiley codes as smiley images ready for display.
*/
function parsesmileys($message) {
if (!preg_match("#(\[code\](.*?)\[/code\]|\[geshi=(.*?)\](.*?)\[/geshi\]|\[php\](.*?)\[/php\])#si", $message)) {
foreach (cache_smileys() as $smiley) {
$smiley_code = preg_quote($smiley['smiley_code'], '#');
$smiley_image = get_image("smiley_".$smiley['smiley_text']);
$smiley_image = "<img class='smiley' style='width:20px;height:20px;' src='$smiley_image' alt='".$smiley['smiley_text']."'>";
$message = preg_replace("#$smiley_code#s", $smiley_image, $message);
}
}
return $message;
}
/**
* Show smiley's button which will insert the smileys to the given textarea and form.
*
* @param string $textarea The id of the textarea
* @param string $form The form id in which the textarea is located.
*
* @return string Option for users to insert smileys in a post by displaying the smiley's button.
*/
function displaysmileys($textarea, $form = "inputform") {
$smileys = "";
$i = 0;
foreach (cache_smileys() as $smiley) {
if ($i != 0 && ($i % 10 == 0)) {
$smileys .= "<br />\n";
}
$i++;
$img = get_image("smiley_".$smiley['smiley_text']);
$smileys .= "<img class='smiley m-2' style='width:20px;height:20px;' src='".$img."' alt='".$smiley['smiley_text']."' title='".$smiley['smiley_text']."' onclick=\"insertText('".$textarea."', '".$smiley['smiley_code']."', '".$form."');\">\n";
}
return $smileys;
}
/**
* Tag a user by simply just posting his name like @Nick and if found, returns a tooltip.
*
* @param string $user_name @Nick
* @param string $tooltip Additional info e.g. ($userdata['user_lastvisit'] - 120 < time() ? 'Online' : 'Offline').
*
* @return string Tooltip with info.
*/
function fusion_parse_user($user_name, $tooltip = '') {
return preg_replace_callback("/\@([A-Za-z0-9\-_!\.]+)/", function ($user_name) use ($tooltip) {
$user = $user_name[1];
$result = dbquery("SELECT *
FROM ".DB_USERS."
WHERE (user_name=:user_00 OR user_name=:user_01 OR user_name=:user_02 OR user_name=:user_03) AND user_status='0'
LIMIT 1
", [
':user_00' => $user,
':user_01' => ucwords($user),
':user_02' => strtoupper($user),
':user_03' => strtolower($user)
]);
if (dbrows($result) > 0) {
$data = dbarray($result);
return render_user_tags($data, $tooltip);
}
return $user_name[0];
}, $user_name);
}
/**
* Cache of all installed BBCodes from the database.
*
* @return array Array of all BBCodes.
*/
function cache_bbcode() {
static $bbcode_cache = [];
if (empty($bbcode_cache)) {
$bbcode_cache = [];
$result = cdquery('bbcodes_cache', "SELECT bbcode_name FROM ".DB_BBCODES." ORDER BY bbcode_order");
while ($data = cdarray($result)) {
$bbcode_cache[] = $data['bbcode_name'];
}
}
return $bbcode_cache;
}
/**
* Parse and force image/ to own directory.
* Neutralize all image dir levels and convert image to pf image folder
*
* @param string $data String to parse.
* @param string $prefix_ Image folder.
*
* @return string Parsed string.
*/
function parse_image_dir($data, $prefix_ = "") {
$str = str_replace("../", "", $data);
return (string)$prefix_ ? str_replace("images/", $prefix_, $str) : str_replace("images/", IMAGES, $str);
}
/**
* Parse BBCodes, smileys and any special characters to HTML string.
*
* @param string $value String with unparsed text.
* @param array $options Array of options.
*
* @return string
*/
function parse_text($value, $options = []) {
$default_options = [
'parse_smileys' => TRUE, // Smiley parsing.
'parse_bbcode' => TRUE, // BBCode parsing.
'decode' => TRUE, // Decode HTML entities.
'default_image_folder' => IMAGES, // Image folder for parse_image_dir().
'add_line_breaks' => FALSE, // Allows nl2br().
'descript' => TRUE, // Sanitize text.
'parse_usres' => TRUE // Create user @tags.
];
$options += $default_options;
$charset = fusion_get_locale('charset');
$value = stripslashes($value);
if ($options['descript']) {
$value = descript($value);
$value = htmlspecialchars_decode($value);
}
if ($options['default_image_folder']) {
$value = parse_image_dir($value, $options['default_image_folder']);
}
if ($options['parse_bbcode']) {
$value = parseubb($value);
}
if ($options['parse_smileys']) {
$value = parsesmileys($value);
}
if ($options['add_line_breaks']) {
$value = nl2br($value);
}
if ($options['parse_usres']) {
$value = fusion_parse_user($value);
}
if ($options['decode']) {
$value = html_entity_decode(html_entity_decode($value, ENT_QUOTES, $charset));
$value = encode_code($value);
}
return (string)$value;
}
/**
* Parse BBCodes in the given string.
*
* @param string $text A string that contains the text to be parsed.
* @param string $selected The names of the required bbcodes to parse, separated by |.
* @param bool $descript Sanitize text.
*
* @return string Parsed string.
*/
function parseubb($text, $selected = "", $descript = TRUE) {
if ($descript) {
$text = descript($text, FALSE);
}
$bbcode_cache = cache_bbcode();
$bbcodes = [];
foreach ($bbcode_cache as $bbcode) {
$bbcodes[$bbcode] = $bbcode;
}
if (!empty($bbcodes['code'])) {
$move_to_top = $bbcodes['code'];
unset($bbcodes['code']);
array_unshift($bbcodes, $move_to_top);
}
$sel_bbcodes = [];
if ($selected) {
$sel_bbcodes = explode("|", $selected);
}
foreach ($bbcodes as $bbcode) {
$locale_file = '';
if (file_exists(LOCALE.LOCALESET."bbcodes/".$bbcode.".php")) {
$locale_file = LOCALE.LOCALESET."bbcodes/".$bbcode.".php";
} else if (file_exists(LOCALE."English/bbcodes/".$bbcode.".php")) {
$locale_file = LOCALE."English/bbcodes/".$bbcode.".php";
}
if ($locale_file) {
\PHPFusion\Locale::setLocale($locale_file);
}
}
$locale = fusion_get_locale();
foreach ($bbcodes as $bbcode) {
if ($selected && in_array($bbcode, $sel_bbcodes)) {
if (file_exists(INCLUDES."bbcodes/".$bbcode."_bbcode_include.php")) {
include(INCLUDES."bbcodes/".$bbcode."_bbcode_include.php");
}
} else if (!$selected) {
if (file_exists(INCLUDES."bbcodes/".$bbcode."_bbcode_include.php")) {
include(INCLUDES."bbcodes/".$bbcode."_bbcode_include.php");
}
}
}
// Added to fix code sniffer reported error
unset($locale);
return $text;
}
/**
* Hide email from robots that have JavaScript disabled, as it requires JavaScript to view email.
* Create a "mailto" link for the email address
*
* @param string $email The email you want to hide from robots.
* @param string $title The text of the link.
* @param string $subject A subject for a mail message if someone opens a link, and it opens in the mail client.
*
* @return string If browser has JavaScript enabled, email will be displayed correctly,
* otherwise, it will be hidden and difficult for a robot to decrypt.
*/
function hide_email($email, $title = "", $subject = "") {
if (preg_match("/^[-0-9A-Z_\.]{1,50}@([-0-9A-Z_\.]+\.){1,50}([0-9A-Z]){2,4}$/i", $email)) {
$enc_email = '';
$parts = explode("@", $email);
$email = $parts[0].'@'.$parts[1];
for ($i = 0; $i < strlen($email); $i++) {
$enc_email .= '&#'.ord($email[$i]).';';
}
$MailLink = "<a href='mailto:".$enc_email;
if ($subject != "") {
$MailLink .= "?subject=".urlencode($subject);
}
$MailLink .= "'>".(!empty($title) ? $title : $enc_email)."</a>";
$MailLetters = "";
for ($i = 0; $i < strlen($MailLink); $i++) {
$l = substr($MailLink, $i, 1);
if (strpos($MailLetters, $l) === FALSE) {
$p = rand(0, strlen($MailLetters));
$MailLetters = substr($MailLetters, 0, $p).$l.substr($MailLetters, $p, strlen($MailLetters));
}
}
$MailLettersEnc = str_replace("\\", "\\\\", $MailLetters);
$MailLettersEnc = str_replace("\"", "\\\"", $MailLettersEnc);
$MailIndexes = "";
for ($i = 0; $i < strlen($MailLink); $i++) {
$index = strpos($MailLetters, substr($MailLink, $i, 1));
$index += 48;
$MailIndexes .= chr($index);
}
$id = 'e'.rand(1, 99999999);
$MailIndexes = str_replace("\\", "\\\\", $MailIndexes);
$MailIndexes = str_replace("\"", "\\\"", $MailIndexes);
$res = "<span id='".$id."'></span>";
$res .= "<script type='text/javascript'>";
$res .= "ML=\"".str_replace("<", "xxxx", $MailLettersEnc)."\";";
$res .= "MI=\"".str_replace("<", "xxxx", $MailIndexes)."\";";
$res .= "ML=ML.replace(/xxxx/g, '<');";
$res .= "MI=MI.replace(/xxxx/g, '<');";
$res .= "OT=\"\";";
$res .= "for(j=0;j < MI.length;j++){";
$res .= "OT+=ML.charAt(MI.charCodeAt(j)-48);";
$res .= "}var e=document.getElementById('".$id."');e.innerHTML += OT;";
$res .= "</script>";
return $res;
} else {
return $email;
}
}
/**
* Encode and format code inside <code> tag.
*
* @param string $text String with code.
*
* @return string Encoded and formatted code.
*/
function encode_code($text) {
preg_match_all("#<code>(.*?)</code>#is", $text, $codes);
$replace = [];
foreach ($codes[1] as $key => $codeblock) {
$replace[$key] = htmlentities($codeblock, ENT_QUOTES, 'UTF-8', FALSE);
}
unset($key, $codeblock);
if (!empty($codes[0])) {
if (!defined('PRISMJS')) {
define('PRISMJS', TRUE);
add_to_head('<link rel="stylesheet" href="'.INCLUDES.'bbcodes/code/prism.css">');
add_to_footer('<script src="'.INCLUDES.'bbcodes/code/prism.js"></script>');
}
}
foreach ($codes[0] as $key => $replacer) {
$code = str_replace('<br />', '', $replace[$key]);
$code = format_code($code);
$text = str_replace($replacer, '<pre><code class="language-php">'.$code.'</code></pre>', $text);
}
unset($key, $replacer, $replace);
return $text;
}
/**
* Add correct amount of spaces and tabs inside code.
*
* @param string $code The code you want to format.
*
* @return string Formatted code.
*/
function format_code($code) {
$code = htmlentities($code, ENT_QUOTES, 'UTF-8', FALSE);
$code = str_replace(
[" ", " ", "\t", "[", "]"],
[" ", " ", " ", "[", "]"],
$code
);
return preg_replace("/^ {1}/m", " ", $code);
}
/**
* Formats a number in a numeric acronym, and rounding.
*
* @param int $value Number to format.
* @param int $decimals The number of decimals.
* @param string $dec_point Decimal point.
* @param string $thousand_sep Thousands separator.
* @param bool $round Round number.
* @param bool $acryonym Acronym.
*
* @return string
*/
function format_num($value, $decimals = 0, $dec_point = ".", $thousand_sep = ",", $round = TRUE, $acryonym = TRUE) {
$array = [
13 => $acryonym ? "t" : "trillion",
10 => $acryonym ? "b" : "billion",
7 => $acryonym ? "m" : "million",
4 => $acryonym ? "k" : "thousand"
];
if (is_numeric($value)) {
if ($round === TRUE) {
foreach ($array as $length => $rounding) {
if (strlen($value) >= $length) {
$power = pow(10, $length - 1);
if ($value > $power && $length > 4 && $decimals === NULL) {
$decimals = 2;
}
return number_format(($value / $power), $decimals, $dec_point, $thousand_sep).$rounding;
}
}
}
return number_format($value, $decimals, $dec_point, $thousand_sep);
}
return $value;
}
/**
* Converts any formatted number back to float numbers in PHP
*
* @param string|int $value Formatted number.
*
* @return float
*/
function format_float($value) {
return floatval(preg_replace('/[^\d.]/', '', $value));
}
/**
* Highlights given words in string.
*
* @param array $words The words to highlight.
* @param string $subject Text that contains a word (s) that should be highlighted.
*
* @return string Words highlighted in the string.
*/
function highlight_words($words, $subject) {
for ($i = 0, $l = count($words); $i < $l; $i++) {
$word[$i] = str_replace([
"\\",
"+",
"*",
"?",
"[",
"^",
"]",
"$",
"(",
")",
"{",
"}",
"=",
"!",
"<",
">",
"|",
":",
"#",
"-",
"_"
], "", $words[$i]);
if (!empty($words[$i])) {
$subject = preg_replace("#($words[$i])(?![^<]*>)#i",
"<span style='background-color:yellow;color:#333;font-weight:bold;padding-left:2px;padding-right:2px;'>\${1}</span>",
$subject);
}
}
return $subject;
}
/**
* Sanitize text and remove a potentially dangerous HTML and JavaScript.
*
* @param string $text String to be sanitized.
* @param bool $strip_tags Removes potentially dangerous HTML tags.
* @param bool $strip_scripts Removes <script> tags.
*
* @return string|array Sanitized and safe string.
*/
function descript($text, $strip_tags = TRUE, $strip_scripts = TRUE) {
if (is_array($text) || is_null($text)) {
return $text;
}
$text = html_entity_decode($text, ENT_QUOTES, fusion_get_locale('charset'));
$text = preg_replace('/&([a-z0-9]+|#[0-9]{1,6}|#x[0-9a-f]{1,6});/i', '', $text);
// Convert problematic ascii characters to their true values
$patterns = [
'#(&\#x)([0-9A-F]+);*#si' => '',
'#(/\bon\w+=\S+(?=.*>))#is' => '',
'#([a-z]*)=([\`\'\"]*)script:#iU' => '$1=$2nojscript...',
'#([a-z]*)=([\`\'\"]*)javascript:#iU' => '$1=$2nojavascript...',
'#([a-z]*)=([\'\"]*)vbscript:#iU' => '$1=$2novbscript...',
'#(<[^>]+)style=([\`\'\"]*).*expression\([^>]*>#iU' => "$1>",
'#(<[^>]+)style=([\`\'\"]*).*behaviour\([^>]*>#iU' => "$1>"
];
foreach (array_merge(['(', ')', ':'], range('A', 'Z'), range('a', 'z')) as $chr) {
$patterns["#(&\#)(0*".ord($chr)."+);*#si"] = $chr;
}
if ($strip_tags) {
do {
$count = 0;
$text = preg_replace('#</*(applet|meta|xml|blink|link|style|script|object|frame|frameset|ilayer|layer|bgsound|title|base)[^>]*>#i', "", $text, -1, $count);
} while ($count);
}
$text = preg_replace(array_keys($patterns), $patterns, $text);
$preg_patterns = [
// Fix &entity\n
'!(�+[0-9]+)!' => '$1;',
'/(&#*\w+)[\x00-\x20]+;/u' => '$1;>',
'/(&#x*[0-9A-F]+);*/iu' => '$1;',
// Remove any attribute starting with "on" or xml name space
//'#(<[^>]+?[\x00-\x20"\'])(?:on|xmlns)[^>]*+>#iu' => '$1>',
'#(<[^>]+?[\x00-\x20"\'])((?:on|xmlns)+[=\w\d()]*+)#iu' => '$1>',
// javascript: and VB script: protocols
'#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([`\'"]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu' => '$1=$2nojavascript...',
'#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu' => '$1=$2novbscript...',
'#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u' => '$1=$2nomozbinding...',
// Only works in IE: <span style="width: expression(alert('Ping!'));"></span>
'#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?expression[\x00-\x20]*\([^>]*+>#i' => '$1>',
'#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*+>#iu' => '$1>',
// namespace elements
'#</*\w+:\w[^>]*+>#i' => ''
];
if ($strip_scripts) {
$preg_patterns += [
'#<script(.*?)>(.*?)</script>#is' => ''
];
}
foreach ($preg_patterns as $pattern => $replacement) {
$text = preg_replace($pattern, $replacement, $text);
}
return htmlspecialchars($text, ENT_QUOTES, 'UTF-8', FALSE);
}
/**
* Scan image files for malicious code.
*
* @param string $file Path to image.
*
* @return bool True or false, depending on whether the image is safe or not.
*/
function verify_image($file) {
$txt = file_get_contents($file);
$patterns = [
'#\<\?php#i',
'#&(quot|lt|gt|nbsp);#i',
'#&\#x([0-9a-f]+);#i',
'#&\#([0-9]+);#i',
"#([a-z]*)=([\`\'\"]*)script:#iU",
"#([a-z]*)=([\`\'\"]*)javascript:#iU",
"#([a-z]*)=([\'\"]*)vbscript:#iU",
"#(<[^>]+)style=([\`\'\"]*).*expression\([^>]*>#iU",
"#(<[^>]+)style=([\`\'\"]*).*behaviour\([^>]*>#iU",
"#</*(applet|link|style|script|iframe|frame|frameset)[^>]*>#i"
];
foreach ($patterns as $pattern) {
if (preg_match($pattern, $txt)) {
return FALSE;
}
}
return TRUE;
}
/**
* Replace offensive words with the defined replacement word.
* The list of offensive words and the replacement word are both defined in the Security Settings.
*
* @param string $text Text that should be censored.
*
* @return string Censored text.
*/
function censorwords($text) {
$settings = fusion_get_settings();
if ($settings['bad_words_enabled'] && !empty($settings['bad_words'])) {
$words = preg_quote(trim($settings['bad_words']), "/");
$words = preg_replace("/\\s+/", "|", $words);
$text = preg_replace("/".$words."/si", $settings['bad_word_replace'], $text);
}
return $text;
}
/**
* Get a user level's name by the numeric code of level.
*
* @param int $userlevel Level code.
*
* @return string The name of the given user level, null if it does not exist.
*/
function getuserlevel($userlevel) {
$locale = fusion_get_locale();
$userlevels = [
USER_LEVEL_MEMBER => $locale['user1'],
USER_LEVEL_ADMIN => $locale['user2'],
USER_LEVEL_SUPER_ADMIN => $locale['user3']
];
return isset($userlevels[$userlevel]) ? $userlevels[$userlevel] : NULL;
}
/**
* Get a user status by the numeric code of status.
*
* @param int $userstatus Status code 0 - 8.
*
* @return string|null The name of the given user status, null if it does not exist.
*/
function getuserstatus($userstatus) {
$locale = fusion_get_locale();
return ($userstatus >= 0 and $userstatus <= 8) ? $locale['status'.$userstatus] : NULL;
}
/**
* Check if an Administrator has the correct rights assigned.
*
* @param string $rights Rights you want to check for the administrator.
*
* @return bool True if the user is an Administrator with rights defined in $rights.
*/
function checkrights($rights) {
if (iADMIN && in_array($rights, explode(".", iUSER_RIGHTS))) {
return TRUE;
} else {
return FALSE;
}
}
/**
* Check the user has rights and redirect if the user does not have rights for the page.
*
* @param string $rights Rights you want to check for the administrator.
* @param bool $debug For debugging purposes.
*/
function pageaccess($rights, $debug = FALSE) {
$error = [];
if ($debug) {
print_p('Admin Panel mode');
}
if (!defined('iAUTH')) {
$error[] = 'iAuth error';
}
if (!isset($_GET['aid'])) {
$error[] = 'Aid link error';
}
if (iADMIN && !empty($_GET['aid'])) {
if ($_GET['aid'] != iAUTH) {
$error[] = 'Aidlink mismatch. '.iAUTH.' != '.$_GET['aid']."<br/>";
$error[] .= USER_IP;
}
} else {
$error[] = "You are logged out while accessing admin panel";
}
if (!checkrights($rights)) {
$error[] = 'Checkrights Error';
}
if (!empty($error)) {
if ($debug) {
print_p($error);
} else {
redirect(BASEDIR);
}
}
}
/**
* Check if user is assigned to the specified user group(s).
*
* @param int $group The group number you want to check for the user.
* @param string $delim Delimiter.
*
* @return bool True if the user is in the group.
*/
function checkgroup($group, $delim = ',') {
if (strpos($group, $delim) !== FALSE) {
foreach (explode($delim, $group) as $group_) {
if (iSUPERADMIN) {
return TRUE;
} else if (iADMIN && ($group_ == 0 || $group_ == USER_LEVEL_MEMBER || $group_ == USER_LEVEL_ADMIN)) {
return TRUE;
} else if (iMEMBER && ($group_ == 0 || $group_ == USER_LEVEL_MEMBER)) {
return TRUE;
} else if (iGUEST && $group_ == 0) {
return TRUE;
} else if (iMEMBER && $group_ && in_array($group_, explode(".", iUSER_GROUPS))) {
return TRUE;
}
}
} else {
if (iSUPERADMIN) {
return TRUE;
} else if (iADMIN && ($group == 0 || $group == USER_LEVEL_MEMBER || $group == USER_LEVEL_ADMIN)) {
return TRUE;
} else if (iMEMBER && ($group == 0 || $group == USER_LEVEL_MEMBER)) {
return TRUE;
} else if (iGUEST && $group == 0) {
return TRUE;
} else if (iMEMBER && $group && in_array($group, explode('.', iUSER_GROUPS))) {
return TRUE;
}
}
return NULL;
}
/**
* Check if user is assigned to the specified user group(s) and has the required user level.
*
* @param int $group The group number(s) you want to check for the user.
* @param int $user_level User level.
* @param string $user_groups Assigned groups to the user.
* @param string $delim Delimiter.
*
* @return bool True if the user has access.
*/
function checkusergroup($group, $user_level, $user_groups, $delim = ',') {
if (strpos($group, $delim) !== FALSE) {
foreach (explode($delim, $group) as $group_) {
if ($user_level == USER_LEVEL_SUPER_ADMIN) {
return TRUE;
} else if ($user_level == USER_LEVEL_ADMIN && ($group_ == 0 || $group_ == USER_LEVEL_MEMBER || $group_ == USER_LEVEL_ADMIN)) {
return TRUE;
} else if ($user_level == USER_LEVEL_MEMBER && ($group_ == 0 || $group_ == USER_LEVEL_MEMBER)) {
return TRUE;
} else if ($user_level == USER_LEVEL_PUBLIC && $group_ == 0) {
return TRUE;
} else if ($user_level == USER_LEVEL_MEMBER && $group_ && in_array($group_, explode('.', $user_groups))) {
return TRUE;
}
}
} else {
if ($user_level == USER_LEVEL_SUPER_ADMIN) {
return TRUE;
} else if ($user_level == USER_LEVEL_ADMIN && ($group == 0 || $group == USER_LEVEL_MEMBER || $group == USER_LEVEL_ADMIN)) {
return TRUE;
} else if ($user_level == USER_LEVEL_MEMBER && ($group == 0 || $group == USER_LEVEL_MEMBER)) {
return TRUE;
} else if ($user_level == USER_LEVEL_PUBLIC && $group == 0) {
return TRUE;
} else if ($user_level == USER_LEVEL_MEMBER && $group && in_array($group, explode('.', $user_groups))) {
return TRUE;
}
}
return NULL;
}
/**
* Cache of all user groups from the database.
*
* @return array Array of all user groups.
*/
function cache_groups() {
static $groups_cache = NULL;
if ($groups_cache === NULL) {
$groups_cache = [];
$result = dbquery("SELECT * FROM ".DB_USER_GROUPS." ORDER BY group_id");
while ($data = dbarray($result)) {
$groups_cache[] = $data;
}
}
return $groups_cache;
}
/**
* Gets all access levels and user groups and make one array out of them for easy access and usage.
*
* @return array Array of all access levels and user groups.
*/
function getusergroups() {
$locale = fusion_get_locale();
$groups_array = [
[USER_LEVEL_PUBLIC, $locale['user0'], $locale['user0'], 'fa fa-user'],
[USER_LEVEL_MEMBER, $locale['user1'], $locale['user1'], 'fa fa-user'],
[USER_LEVEL_ADMIN, $locale['user2'], $locale['user2'], 'fa fa-user'],
[USER_LEVEL_SUPER_ADMIN, $locale['user3'], $locale['user3'], 'fa fa-user']
];
$groups_cache = cache_groups();
foreach ($groups_cache as $group) {
$group_icon = !empty($group['group_icon']) ? $group['group_icon'] : '';
array_push($groups_array, [$group['group_id'], $group['group_name'], $group['group_description'], $group_icon]);
}
return $groups_array;
}
/**
* Get the name of the access level or user group.
*
* @param int $group_id The ID of the group or access level to which you want to get a name.
* @param bool $return_desc If true, description will be returned instead of name.
* @param bool $return_icon If true, icon will be returned next to name.
*
* @return string The name or icon or description of the given group, null if it does not exist.
*/
function getgroupname($group_id, $return_desc = FALSE, $return_icon = FALSE) {
foreach (getusergroups() as $group) {
if ($group_id == $group[0]) {
return ($return_desc ? ($group[2] ?: '-') : (!empty($group[3]) && $return_icon ? "<i class='".$group[3]."'></i> " : "").$group[1]);
}
}
return NULL;
}
/**
* Gets array of all access levels and user groups.
*
* @param array $remove Array of groups you want to exclude from output.
*
* @return array Array of all access levels and user groups.
*/
function fusion_get_groups($remove = []) {
$visibility_opts = [];
$groups = array_diff_key(getusergroups(), array_flip($remove));
foreach ($groups as $group) {
$visibility_opts[$group[0]] = $group[1];
}
return $visibility_opts;
}
/**
* Check if user has access to the group.
*
* @param int $group_id The ID of the group.
*
* @return bool True if the user has access.
*/
function users_groupaccess($group_id) {
if (preg_match("(^\.$group_id$|\.$group_id\.|\.$group_id$)", fusion_get_userdata('user_groups'))) {
return TRUE;
}
return FALSE;
}
/**
* Getting the access levels used when asking the database for data.
*
* @param string $field MySQL's field from which you want to check access.
* @param string $delim Delimiter.
*
* @return string The part of WHERE clause, always returns a condition.
*/
function groupaccess($field, $delim = ',') {
$res = '';
if (iGUEST) {
$res = $field." in (".USER_LEVEL_PUBLIC.")";
} else if (iSUPERADMIN) {
$res = "1 = 1";
} else if (iADMIN) {
$res = $field." in (".USER_LEVEL_PUBLIC.", ".USER_LEVEL_MEMBER.", ".USER_LEVEL_ADMIN.")";
} else if (iMEMBER) {
$res = $field." in (".USER_LEVEL_PUBLIC.", ".USER_LEVEL_MEMBER.")";
}
if (iUSER_GROUPS != "" && !iSUPERADMIN) {
$groups = explode('.', iUSER_GROUPS);
$groups_ = [];
foreach ($groups as $group) {
$groups_[] = in_group($field, $group, $delim);
}
$group_sql = implode(' OR ', $groups_);
$res = "(".$res." OR ".$group_sql.")";
}
return $res;
}
/**
* Get the data of the access level or user group.
*
* @param int $group_id The ID of the group.
*
* @return array
*/
function getgroupdata($group_id) {
foreach (getusergroups() as $group) {
if ($group_id == $group[0]) {
return $group;
}
}
return NULL;
}
/**
* UF blacklist for SQL - same as groupaccess() but $field is the user_id column.
*
* @param string $field The name of the field
*
* @return string SQL condition. It can return an empty condition if the user_blacklist field is not installed!
*/
function blacklist($field) {
if (column_exists('users', 'user_blacklist')) {
$user_id = fusion_get_userdata('user_id');
if (!empty($user_id)) {
$result = dbquery("SELECT user_id, user_level FROM ".DB_USERS." WHERE ".in_group('user_blacklist', $user_id));
if (dbrows($result) > 0) {
$i = 0;
$sql = '';
while ($data = dbarray($result)) {
$sql .= ($i > 0) ? "AND $field !='".$data['user_id']."'" : "($field !='".$data['user_id']."'";
$i++;
}
$sql .= $sql ? ")" : '1=1';
return $sql;
}
}
}
return '';
}
/**
* Check if user was blacklisted by a member.
*
* @param int $user_id User ID.
* @param bool $me Set true to hide blocked user's content on your account.
*
* @return bool True if the user is blacklisted.
*/
function user_blacklisted($user_id, $me = FALSE) {
if (column_exists('users', 'user_blacklist')) {
$my_id = fusion_get_userdata('user_id');
if ($me && !empty(fusion_get_userdata('user_blacklist'))) {
$blacklist = explode(',', fusion_get_userdata('user_blacklist'));
if (!empty($blacklist)) {
foreach ($blacklist as $id) {
if ($id == $user_id) {
return TRUE;
}
}
}
} else {
$result = dbquery("SELECT user_id, user_level FROM ".DB_USERS." WHERE ".in_group('user_blacklist', $my_id));
if (dbrows($result) > 0) {
while ($data = dbarray($result)) {
if ($user_id == $data['user_id']) {
return TRUE;
}
}
}
}
}
return FALSE;
}
/**
* Create a list of files or folders and store them in an array.
*
* @param string $folder Path to folder.
* @param string $filter The names of the filtered folders and files separated by |, false to use default filter.
* @param bool $sort False if you don't want to sort the result.
* @param string $type Possible value: files, folders.
* @param string $ext_filter File extensions separated by |, only when $type is 'files'.
*
* @return array Array of all items.
*/
function makefilelist($folder, $filter = "", $sort = TRUE, $type = "files", $ext_filter = "") {
$res = [];
$default_filters = '.|..|.htaccess|index.php|._DS_STORE|.tmp';
if ($filter === FALSE) {
$filter = $default_filters;
}
$filter = explode("|", $filter);
if ($type == "files" && !empty($ext_filter)) {
$ext_filter = explode("|", strtolower($ext_filter));
}
if (file_exists($folder)) {
$temp = opendir($folder);
while ($file = readdir($temp)) {
if ($type == "files" && !in_array($file, $filter)) {
if (!empty($ext_filter)) {
if (!in_array(substr(strtolower(stristr($file, '.')), +1), $ext_filter) && !is_dir($folder.$file)) {
$res[] = $file;
}
} else {
if (is_file($folder.$file)) {
$res[] = $file;
}
}
} else if
($type == "folders" && !in_array($file, $filter)) {
if (is_dir($folder.$file)) {
$res[] = $file;
}
}
}
closedir($temp);
if ($sort) {
natsort($res);
}
} else {
$error_log = debug_backtrace()[1];
$function = (isset($error_log['class']) ? $error_log['class'] : '').(isset($error_log['type']) ? $error_log['type'] : '').(isset($error_log['function']) ? $error_log['function'] : '');
$error_log = strtr(fusion_get_locale('err_103', LOCALE.LOCALESET.'errors.php'), [
'{%folder%}' => $folder,
'{%function%}' => (!empty($function) ? '<code class=\'m-r-10\'>'.$function.'</code>' : '')
]);
set_error(2, $error_log, debug_backtrace()[1]['file'], debug_backtrace()[1]['line']);
}
return $res;
}
/**
* Creates page navigation.
*
* @param int $rowstart The number of the first listed item.
* @param int $count The number of entries displayed on one page.
* @param int $total The total entries which should be displayed.
* @param int $range The number of page buttons displayed and the range of them.
* @param string $link The base url before the appended part.
* @param string $getname The name of the $_GET parameter that contains the start number.
* @param bool $button Displays as button.
*
* @return string|bool HTML navigation. False if $count is invalid.
*/
function makepagenav($rowstart, $count, $total, $range = 3, $link = "", $getname = "rowstart", $button = FALSE) {
$locale = fusion_get_locale();
/* Bootstrap may be disabled in theme (see Gillette for example) without settings change in DB.
In such case this function will not work properly.
With this fix (used $settings instead fusion_get_settings) function will work.*/
if (defined('BOOTSTRAP') && BOOTSTRAP == TRUE) {
$tpl_global = "<nav>%s<div class='btn-group'>\n%s</div></nav>\n";
$tpl_currpage = "<a class='btn btn-sm btn-default active' href='%s=%d'><strong>%d</strong></a>\n";
$tpl_page = "<a class='btn btn-sm btn-default' data-value='%d' href='%s=%d'>%s</a>\n";
$tpl_divider = "</div>\n<div class='btn-group'>";
$tpl_firstpage = "<a class='btn btn-sm btn-default' data-value='0' href='%s=0'>1</a>\n";
$tpl_lastpage = "<a class='btn btn-sm btn-default' data-value='%d' href='%s=%d'>%s</a>\n";
$tpl_button = "<a class='btn btn-primary btn-block btn-md' data-value='%d' href='%s=%d'>%s</a>\n";
} else {
$tpl_global = "<div class='pagenav'>%s\n%s</div>\n";
$tpl_currpage = "<a class='pagenavlink active' href='%s=%d'>%d</a>";
$tpl_page = "<a class='pagenavlink' data-value='%d' href='%s=%d'>%s</a>";
$tpl_divider = "<span class='pagenavdivider'>...</span>";
$tpl_firstpage = "<a class='pagenavlink' data-value='0' href='%s=0'>1</a>";
$tpl_lastpage = "<a class='pagenavlink' data-value='%d' href='%s=%d'>%s</a>\n";
$tpl_button = "<a class='pagenavlink' data-value='%d' href='%s=%d'>%s</a>\n";
}
if ($link == '') {
$link = FUSION_SELF."?";
if (fusion_get_settings("site_seo") && defined('IN_PERMALINK')) {
global $filepath;
$link = $filepath."?";
}
}
if (!preg_match("#[0-9]+#", $count) || $count == 0) {
return FALSE;
}
$pg_cnt = ceil($total / $count);
if ($pg_cnt <= 1) {
return "";
}
$idx_back = $rowstart - $count;
$idx_next = $rowstart + $count;
if ($button == TRUE) {
if ($idx_next >= $total) {
return sprintf($tpl_button, 0, $link.$getname, 0, $locale['load_end']);
} else {
return sprintf($tpl_button, $idx_next, $link.$getname, $idx_next, $locale['load_more']);
}
}
$cur_page = ceil(($rowstart + 1) / $count);
$res = "";
if ($idx_back >= 0) {
if ($cur_page > ($range + 1)) {
$res .= sprintf($tpl_firstpage, $link.$getname);
if ($cur_page != ($range + 2)) {
$res .= $tpl_divider;
}
}
}
$idx_fst = max($cur_page - $range, 1);
$idx_lst = min($cur_page + $range, $pg_cnt);
if ($range == 0) {
$idx_fst = 1;
$idx_lst = $pg_cnt;
}
for ($i = $idx_fst; $i <= $idx_lst; $i++) {
$offset_page = ($i - 1) * $count;
if ($i == $cur_page) {
$res .= sprintf($tpl_currpage, $link.$getname, $offset_page, $i);
} else {
$res .= sprintf($tpl_page, $offset_page, $link.$getname, $offset_page, $i);
}
}
if ($idx_next < $total) {
if ($cur_page < ($pg_cnt - $range)) {
if ($cur_page != ($pg_cnt - $range - 1)) {
$res .= $tpl_divider;
}
$res .= sprintf($tpl_lastpage, ($pg_cnt - 1) * $count, $link.$getname, ($pg_cnt - 1) * $count, $pg_cnt);
}
}
return sprintf($tpl_global, "<small class='m-r-10'><span>".$locale['global_092']."</span> ".$cur_page.$locale['global_093'].$pg_cnt."</small> ", $res);
}
/**
* Rowstart count.
*
* @param int $count The number of entries displayed on one page.
* @param int $total The total entries which should be displayed.
* @param int $range The number of page buttons displayed and the range of them.
*
* @return float
*/
function rowstart_count($total, $count, $range = 3) {
if ($total > $count) {
$cur_page = ceil(($total + 1) / $count);
$pg_cnt = ceil($total / $count);
if ($pg_cnt <= 1) {
return 0;
}
$row = min($cur_page + $range, $pg_cnt);
return ($row - 1) * $count;
}
return 0;
}
/**
* Infinite scroll pagination.
*
* @param string $scroll_url The ajax script that loads the content.
* @param int $rowstart The number of the first listed item.
* @param int $count The number of entries displayed on one page.
* @param string $getname The name of the $_GET parameter that contains the start number.
* @param string $http_query Additional http query.
*
* @return string
*/
function infinite_scroll($scroll_url, $rowstart, $count, $getname = 'rowstart', $http_query = '') {
$locale = fusion_get_locale();
add_to_jquery("
var count = $rowstart+1;
$(window).scroll(function(){
if ($(window).scrollTop() == ($(document).height() - $(window).height())) {
if (count <= '$count') {
loadInfinityContent(count);
count++;
}
}
});
function loadInfinityContent(pageNumber){
$('.infiniteLoader').show('fast');
$.ajax({
url: '$scroll_url',
type:'GET',
data: 'action=infinite_scroll&$getname='+ pageNumber +'".($http_query ? "&".$http_query : '')."',
success: function(html){
$('.infiniteLoader').hide();
$('#scroll_target').append(html); // This will be the div where our content will be loaded
}
});
return false;
}
");
return "
<div id='scroll_target'></div>
<div class='infiniteLoader panel panel-default' style='display:none;'><div class='panel-body text-center'>".$locale['loading']."</div></div>
";
}
/**
* Hierarchy Page Breadcrumbs, generates breadcrumbs on all your category needs.
*
* @param array $tree_index dbquery_tree() or tree_index().
* @param array $tree_full dbquery_tree_full().
* @param string $id_col The name of the category id column.
* @param string $title_col The name of the category nmae column.
* @param string $getname The name of the $_GET parameter.
*/
function make_page_breadcrumbs($tree_index, $tree_full, $id_col, $title_col, $getname = "rownav") {
$_GET[$getname] = !empty($_GET[$getname]) && isnum($_GET[$getname]) ? $_GET[$getname] : 0;
// Recursive fatal protection
if (!function_exists('breadcrumb_page_arrays')) {
function breadcrumb_page_arrays($tree_index, $tree_full, $id_col, $title_col, $getname, $id) {
$crumb = [];
if (isset($tree_index[get_parent($tree_index, $id)])) {
$_name = get_parent_array($tree_full, $id);
$crumb = [
'link' => isset($_name[$id_col]) ? clean_request($getname."=".$_name[$id_col], ["aid"]) : "",
'title' => isset($_name[$title_col]) ? QuantumFields::parseLabel($_name[$title_col]) : "",
];
if (get_parent($tree_index, $id) == 0) {
return $crumb;
}
$crumb_1 = breadcrumb_page_arrays($tree_index, $tree_full, $id_col, $title_col, $getname, get_parent($tree_index, $id));
if (!empty($crumb_1)) {
$crumb = array_merge_recursive($crumb, $crumb_1);
}
}
return $crumb;
}
}
// then we make an infinity recursive function to loop/break it out.
$crumb = breadcrumb_page_arrays($tree_index, $tree_full, $id_col, $title_col, $getname, $_GET[$getname]);
// then we sort in reverse.
$title_count = !empty($crumb['title']) && is_array($crumb['title']) ? count($crumb['title']) > 1 : 0;
if ($title_count) {
krsort($crumb['title']);
krsort($crumb['link']);
}
if ($title_count) {
foreach ($crumb['title'] as $i => $value) {
add_breadcrumb(['link' => $crumb['link'][$i], 'title' => $value]);
if ($i == count($crumb['title']) - 1) {
add_to_title($value);
add_to_meta($value);
}
}
} else if (isset($crumb['title'])) {
add_to_title($crumb['title']);
add_to_meta($crumb['title']);
add_breadcrumb(['link' => $crumb['link'], 'title' => $crumb['title']]);
}
}
/**
* Format the date and time according to the site and user offset.
*
* @param string $format Possible value: shortdate, longdate, forumdate, newsdate or date pattern for the strftime.
* @param int $val Unix timestamp.
* @param array $options Possible options tz_override.
*
* @return string String formatted according to the given format string.
* Month and weekday names and other language dependent strings respect the current locale set.
*/
function showdate($format, $val, $options = []) {
$userdata = fusion_get_userdata();
if (isset($options['tz_override'])) {
$tz_client = $options['tz_override'];
} else {
if (!empty($userdata['user_timezone'])) {
$tz_client = $userdata['user_timezone'];
} else {
$tz_client = fusion_get_settings('timeoffset');
}
}
if (empty($tz_client)) {
$tz_client = 'Europe/London';
}
$offset = 0;
try {
$client_dtz = new DateTimeZone($tz_client);
$client_dt = new DateTime('now', $client_dtz);
$offset = (int)$client_dtz->getOffset($client_dt);
} catch (Exception $e) {
set_error(E_CORE_ERROR, $e->getMessage(), $e->getFile(), $e->getLine());
}
if (!empty($val)) {
$offset = (int)$val + $offset;
if (in_array($format, ['shortdate', 'longdate', 'forumdate', 'newsdate'])) {
$format = fusion_get_settings($format);
return format_date($format, $offset);
}
return format_date($format, $offset);
}
$format = fusion_get_settings($format);
$offset = time() + $offset;
return format_date($format, $offset);
}
/**
* Format date - replacement for strftime()
*
* @param string $format Dateformat
* @param int $time Timestamp
*
* @return string
*/
function format_date($format, $time) {
$format = str_replace(
['%a', '%A', '%d', '%e', '%u', '%w', '%W', '%b', '%h', '%B', '%m', '%y', '%Y', '%D', '%F', '%x', '%n', '%t', '%H', '%k', '%I', '%l', '%M', '%p', '%P', '%r', '%R', '%S', '%T', '%X', '%z', '%Z', '%c', '%s', '%%'],
['D', 'l', 'd', 'j', 'N', 'w', 'W', 'M', 'M', 'F', 'm', 'y', 'Y', 'm/d/y', 'Y-m-d', 'm/d/y', "\n", "\t", 'H', 'G', 'h', 'g', 'i', 'A', 'a', 'h:i:s A', 'H:i', 's', 'H:i:s', 'H:i:s', 'O', 'T', 'D M j H:i:s Y', 'U', '%'],
$format
);
$date = DateTimeImmutable::createFromFormat('U', $time);
return $date->format($format);
}
/**
* Translate bytes into kB, MB, GB or TB.
*
* @param int $size The number of bytes.
* @param int $decimals The number of decimals.
* @param bool $dir True if it is the size of a directory.
*
* @return string
*/
function parsebytesize($size, $decimals = 2, $dir = FALSE) {
$locale = fusion_get_locale();
$kb = 1024;
$mb = 1024 * $kb;
$gb = 1024 * $mb;
$tb = 1024 * $gb;
$size = (empty($size)) ? "0" : $size;
if (($size == 0) && ($dir)) {
return "0 ".$locale['global_460'];
} else if ($size < $kb) {
return $size.$locale['global_461'];
} else if ($size < $mb) {
return round($size / $kb, $decimals).'kB';
} else if ($size < $gb) {
return round($size / $mb, $decimals).'MB';
} else if ($size < $tb) {
return round($size / $gb, $decimals).'GB';
} else {
return round($size / $tb, $decimals).'TB';
}
}
/**
* Prints human-readable information about a variable.
*
* @param mixed $data The expression to be printed.
* @param bool $modal Dump info in the modal.
* @param bool $print Dump info in <pre> tag.
*
* @return string The value of the variable.
*/
function print_p($data, $modal = FALSE, $print = TRUE) {
ob_start();
echo htmlspecialchars(print_r($data, TRUE), ENT_QUOTES, 'utf-8');
$debug = ob_get_clean();
if ($modal == TRUE) {
$modal = openmodal('Debug', 'Debug');
$modal .= "<pre class='printp' style='white-space:pre-wrap !important;'>";
$modal .= $debug;
$modal .= "</pre>\n";
$modal .= closemodal();
PHPFusion\OutputHandler::addToFooter($modal);
return FALSE;
}
if ($print == TRUE) {
echo "<pre class='printp' style='white-space:pre-wrap !important;'>";
echo $debug;
echo "</pre>\n";
}
return $debug;
}
/**
* Fetch the settings from the database.
*
* @param string $key The key of one setting
*
* @return string[]|string Associative array of settings or one setting by key.
*/
function fusion_get_settings($key = NULL) {
// It is initialized only once because of 'static'
static $settings = [];
if (empty($settings) and defined('DB_SETTINGS') and dbconnection() && db_exists('settings')) {
$result = dbquery("SELECT * FROM ".DB_SETTINGS);
while ($data = dbarray($result)) {
$settings[$data['settings_name']] = $data['settings_value'];
}
}
return $key === NULL ? $settings : (isset($settings[$key]) ? $settings[$key] : NULL);
}
/**
* Fetch username by ID.
*
* @param int $user_id User ID.
*
* @return string Username.
*/
function fusion_get_username($user_id) {
$result = (dbresult(dbquery("SELECT user_name FROM ".DB_USERS." WHERE user_id='".intval($user_id)."'"), 0));
return ($result !== NULL) ? $result : fusion_get_locale("na");
}
/**
* Fetch user data of the currently logged-in user from database.
*
* @param string $key The key of one column.
*
* @return string|array Associative array of all data or one column by key.
*/
function fusion_get_userdata($key = NULL) {
global $userdata;
if (empty($userdata)) {
$userdata = ["user_level" => 0, "user_rights" => "", "user_groups" => "", "user_theme" => 'Default', "user_ip" => USER_IP];
}
$userdata = $userdata + [
"user_id" => 0,
"user_name" => fusion_get_locale("user_guest"),
"user_status" => 1,
"user_level" => 0,
"user_rights" => "",
"user_groups" => "",
"user_theme" => fusion_get_settings("theme"),
];
return $key === NULL ? $userdata : (isset($userdata[$key]) ? $userdata[$key] : NULL);
}
/**
* Get the data of any user by ID.
*
* @param int $user_id The user ID.
* @param string $key The key of column.
*
* @return string|array Associative array of all data or one column by key.
*/
function fusion_get_user($user_id, $key = NULL) {
static $user = [];
if (!isset($user[$user_id]) && isnum($user_id)) {
$user[$user_id] = dbarray(dbquery("SELECT * FROM ".DB_USERS." WHERE user_id='".intval($user_id)."'"));
}
if (!isset($user[$user_id])) {
return NULL;
}
return $key === NULL ? $user[$user_id] : (isset($user[$user_id][$key]) ? $user[$user_id][$key] : NULL);
}
/**
* Get Aidlink.
*
* @return string
*/
function fusion_get_aidlink() {
$aidlink = '';
if (defined('iADMIN') && iADMIN && defined('iAUTH')) {
$aidlink = '?aid='.iAUTH;
}
return $aidlink;
}
/**
* Get form tokens.
*
* @param string $form_id Form ID.
* @param int $max_tokens Max tokens.
*
* @return string
*/
function fusion_get_token($form_id, $max_tokens = 5) {
return Token::generate_token($form_id, $max_tokens);
}
/**
* Fetch user PM settings.
*
* @param int $user_id User ID.
* @param string $key user_inbox, user_outbox, user_archive, user_pm_email_notify, user_pm_save_sent
*
* @return array|string Associative array of all data or one column by key.
*/
function user_pm_settings($user_id, $key = NULL) {
return PrivateMessages::getPmSettings($user_id, $key);
}
/**
* Define constants for site language.
*
* @param string $lang The name of the language.
*/
function define_site_language($lang) {
if (valid_language($lang)) {
define('LANGUAGE', $lang);
define('LOCALESET', $lang.'/');
}
}
/**
* Set the requested language.
*
* @param string $lang The name of the language.
*/
function set_language($lang) {
$userdata = fusion_get_userdata();
if (valid_language($lang)) {
if (iMEMBER) {
dbquery("UPDATE ".DB_USERS." SET user_language='".$lang."' WHERE user_id='".$userdata['user_id']."'");
} else {
$rows = dbrows(dbquery("SELECT user_language FROM ".DB_LANGUAGE_SESSIONS." WHERE user_ip='".USER_IP."'"));
if ($rows != 0) {
dbquery("UPDATE ".DB_LANGUAGE_SESSIONS." SET user_language='".$lang."', user_datestamp='".time()."' WHERE user_ip='".USER_IP."'");
} else {
dbquery("INSERT INTO ".DB_LANGUAGE_SESSIONS." (user_ip, user_language, user_datestamp) VALUES ('".USER_IP."', '".$lang."', '".time()."');");
}
// Sanitize guest sessions occasionally
dbquery("DELETE FROM ".DB_LANGUAGE_SESSIONS." WHERE user_datestamp<'".(time() - (86400 * 60))."'");
}
}
}
/**
* Check if a given language is valid or if exists.
* Checks whether a language can be found in enabled languages array.
* Can also be used to check whether a language actually exists.
*
* @param string $lang The name of the language.
* @param bool $file_check Intended to be used when enabling languages in Admin Panel.
*
* @return bool
*/
function valid_language($lang, $file_check = FALSE) {
$enabled_languages = fusion_get_enabled_languages();
if (preg_match("/^([a-z0-9_-]){2,50}$/i", $lang) &&
($file_check ? file_exists(LOCALE.$lang."/global.php") : isset($enabled_languages[$lang]))
) {
return TRUE;
} else {
return FALSE;
}
}
/**
* Get language switch arrays.
*
* @return array
*/
function fusion_get_language_switch() {
static $language_switch = [];
if (empty($language_link)) {
$enabled_languages = fusion_get_enabled_languages();
foreach ($enabled_languages as $language => $language_name) {
$link = clean_request('lang='.$language, ['lang'], FALSE);
$language_switch[$language] = [
"language_name" => $language_name,
"language_icon_s" => BASEDIR."locale/$language/$language-s.png",
"language_icon" => BASEDIR."locale/$language/$language.png",
"language_link" => $link,
];
}
}
return $language_switch;
}
/**
* Get the array of enabled languages.
*
* @return array
*/
function fusion_get_enabled_languages() {
$settings = fusion_get_settings();
static $enabled_languages = NULL;
if ($enabled_languages === NULL) {
if (isset($settings['enabled_languages'])) {
$values = explode('.', $settings['enabled_languages']);
foreach ($values as $language_name) {
$enabled_languages[$language_name] = translate_lang_names($language_name);
}
}
}
return $enabled_languages;
}
/**
* Get the array of detected languages.
*
* @return array
*/
function fusion_get_detected_languages() {
static $detected_languages = NULL;
if ($detected_languages === NULL) {
$all_languages = makefilelist(LOCALE, ".svn|.|..", TRUE, "folders");
foreach ($all_languages as $language_name) {
$detected_languages[$language_name] = translate_lang_names($language_name);
}
}
return $detected_languages;
}
/**
* Run the installer or halt the script
*/
function fusion_run_installer() {
if (file_exists("install.php")) {
redirect("install.php");
} else {
die("No config.php or install.php files were found");
}
}
/**
* Detect whether the system is installed and return the config file path.
*
* @return string
*/
function fusion_detect_installation() {
$config_path = dirname(__DIR__).'/config.php';
if (!is_file($config_path) or !filesize($config_path)) {
fusion_run_installer();
}
return $config_path;
}
/**
* Log user actions.
*
* @param int $user_id User ID.
* @param string $column_name Affected column.
* @param string $new_value New value.
* @param string $old_value Old value.
*/
function save_user_log($user_id, $column_name, $new_value, $old_value) {
$data = [
"userlog_id" => 0,
"userlog_user_id" => $user_id,
"userlog_field" => $column_name,
"userlog_value_new" => $new_value,
"userlog_value_old" => $old_value,
"userlog_timestamp" => time(),
];
dbquery_insert(DB_USER_LOG, $data, "save", ["keep_session" => TRUE]);
}
/**
* Minify JS code.
*
* @param string $code Unminified code.
*
* @return string Minified code.
*/
function jsminify($code) {
$minifier = new JS($code);
return $minifier->minify();
}
/**
* A wrapper function for file_put_contents with cache invalidation.
* If opcache is enabled on the server, this function will write the file.
* as the original file_put_contents and invalidate the cache of the file.
* It is needed when you create a file dynamically and want to include it
* before the cache is invalidated. Redirection does not matter.
*
* @param string $file File path.
* @param string|array $data The data to write.
* @param int $flags
*
* @return int Number of written bytes
*/
function write_file($file, $data, $flags = NULL) {
if ($flags === NULL) {
$bytes = file_put_contents($file, $data);
} else {
$bytes = file_put_contents($file, $data, $flags);
}
if (function_exists('opcache_invalidate')) {
opcache_invalidate($file, TRUE);
}
return $bytes;
}
/**
* Returns nearest data unit.
*
* @param int $total_bit Number of bytes.
*
* @return int
*/
function calculate_byte($total_bit) {
$calc_opts = fusion_get_locale('1020', LOCALE.LOCALESET."admin/settings.php");
foreach ($calc_opts as $byte => $val) {
if ($total_bit / $byte <= 999) {
return (int)$byte;
}
}
return 1048576;
}
/**
* Recursively remove folder and all files/subdirectories.
*
* @param string $dir Path to the folder.
*/
function rrmdir($dir) {
if (is_dir($dir)) {
$objects = scandir($dir);
foreach ($objects as $object) {
if ($object != '.' && $object != '..') {
if (filetype($dir.'/'.$object) == 'dir') {
rrmdir($dir.'/'.$object);
} else {
unlink($dir.'/'.$object);
}
}
}
reset($objects);
rmdir($dir);
}
}
/**
* Alternative to rename() that works on Windows.
*
* @param string $origin The old name.
* @param string $target The new name.
*/
function fusion_rename($origin, $target) {
if ($origin != "." && $origin != ".." && !is_dir($origin)) {
if (TRUE !== @rename($origin, $target)) {
copy($origin, $target);
unlink($origin);
}
}
}
/**
* cURL method to get any contents for Apache that does not support SSL for remote paths.
*
* @param string $url
*
* @return bool|string
*/
function fusion_get_contents($url) {
if (function_exists('curl_init')) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
//curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); // PHP 7.1
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$data = curl_exec($ch);
curl_close($ch);
} else {
$data = @file_get_contents($url);
}
return $data;
}
/**
* Checks whether a string is JSON or not.
*
* @param string $string The string to be checked.
*
* @return bool
*/
function is_json($string) {
json_decode($string);
return (json_last_error() == JSON_ERROR_NONE);
}
/**
* Cached script loader.
* This function will cache the path that has been added and avoid duplicates.
*
* @param string $file_path The source file.
* @param string $file_type Possible value: script, css.
* @param bool $html Return as html tags instead add to output handler.
* @param bool $cached False to invalidate browser's cache.
*
* @return string
*/
function fusion_load_script($file_path, $file_type = "script", $html = FALSE, $cached = TRUE) {
static $paths = [];
$file_info = pathinfo($file_path);
if (isset($file_info['dirname']) && isset($file_info['basename']) && isset($file_info['extension']) && isset($file_info['filename'])) {
$mtime = 0;
$file = $file_info['dirname'].'/'.$file_info['basename'];
$min_file = $file_info['dirname'].'/'.$file_info['filename'].(!stristr($file_info['filename'], '.min') ? '.min.' : '.').$file_info['extension'];
// do not inspect this file
$return_file = $file;
// inspect only on min file
$m_min_file = str_replace((!empty(fusion_get_settings('siteurl')) ? fusion_get_settings('siteurl') : get_current_url()), BASEDIR, $min_file);
if (is_file($m_min_file)) { // fixes https:// on local server
$return_file = $m_min_file;
} else if (is_file($min_file)) { // checks local server
$return_file = $min_file;
} else if (filter_var($min_file, FILTER_VALIDATE_DOMAIN)) { // checks remote server
if (fusion_get_contents($min_file)) {
$return_file = $min_file;
}
}
if (is_file($return_file)) {
$mtime = filemtime($return_file);
}
$file_path = $return_file."?v=".$mtime;
if (!$cached) {
$file_path = $return_file;
}
}
if ($file_path && empty($paths[$file_path])) {
$paths[$file_path] = $file_path;
if ($file_type == "script") {
$html_tag = "<script src='$file_path'></script>";
if ($html === TRUE) {
return $html_tag;
}
add_to_footer($html_tag);
} else if ($file_type == "css") {
$html_tag = "<link rel='stylesheet' href='$file_path' media='all'>";
if ($html === TRUE) {
return $html_tag;
}
add_to_head($html_tag);
}
}
return '';
}
/**
* Get max server upload limit.
*
* @return mixed
*/
function max_server_upload() {
// select maximum upload size
$max_upload = convert_to_bytes(ini_get('upload_max_filesize'));
// select post limit
$max_post = convert_to_bytes(ini_get('post_max_size'));
// select memory limit
$memory_limit = convert_to_bytes(ini_get('memory_limit'));
// return the smallest of them, this defines the real limit
return min($max_upload, $max_post, $memory_limit);
}
/**
* Convert to bytes.
*
* @param int|string $val
*
* @return int
*/
function convert_to_bytes($val) {
$val = trim($val);
$last = strtolower($val[strlen($val) - 1]);
$kb = 1024;
$mb = 1024 * $kb;
$gb = 1024 * $mb;
switch ($last) {
case 'g':
$val = (int)$val * $gb;
break;
case 'm':
$val = (int)$val * $mb;
break;
case 'k':
$val = (int)$val * $kb;
break;
}
return (int)$val;
}
/**
* Get current URL.
*
* @return string
*/
function get_current_url() {
$s = (empty($_SERVER["HTTPS"]) ? "" : ($_SERVER["HTTPS"] == "on")) ? "s" : "";
$protocol = strleft(strtolower($_SERVER["SERVER_PROTOCOL"]), "/").$s;
$port = ($_SERVER["SERVER_PORT"] == "80" || ($_SERVER['SERVER_PORT'] == "443" && $s == "s")) ? "" : (":".$_SERVER["SERVER_PORT"]);
return $protocol."://".$_SERVER['SERVER_NAME'].$port.
(str_replace(basename(cleanurl($_SERVER['PHP_SELF'])), "", $_SERVER['REQUEST_URI']));
}
/**
* @param $s1
* @param $s2
*
* @return false|string
*/
function strleft($s1, $s2) {
return substr($s1, 0, strpos($s1, $s2));
}
/**
* Adds a whitespace if value is present.
*
* @param string $value
*
* @return string
*/
function whitespace($value) {
if (!empty($value)) {
return " ".$value;
}
return "";
}
/**
* Send a cookie.
*
* @param string $name The name of the cookie.
* @param string $value The value of the cookie.
* @param int $expires The time the cookie expires.
* @param string $path The path on the server in which the cookie will be available on.
* @param string $domain The (sub)domain that the cookie is available to.
* @param bool $secure Whether the client should send back the cookie only over HTTPS or null to auto-enable this when the request is already using HTTPS.
* @param bool $httponly Whether the cookie will be made accessible only through the HTTP protocol.
* @param string|null $samesite Whether the cookie will be available for cross-site requests. Possible value: none | lax | strict
*/
function fusion_set_cookie($name, $value, $expires, $path, $domain, $secure = FALSE, $httponly = FALSE, $samesite = NULL) {
$samesite = in_array($samesite, ['lax', 'none', 'strict', NULL]) ? $samesite : NULL;
if (PHP_VERSION_ID < 70300) {
if (!headers_sent()) {
if ($value !== '') {
$expires = $expires !== 0 ? ' expires='.$expires.';' : '';
$domain = $domain ? 'domain='.$domain.';' : '';
$secure = $secure ? 'secure;' : '';
$httponly = $httponly ? 'httponly;' : '';
$samesite = $samesite !== NULL ? 'samesite='.$samesite : '';
header("Set-Cookie: $name=$value; $expires path=$path; $domain $secure $httponly $samesite");
} else {
setcookie($name, $value, $expires, $path, $domain, $secure, $httponly);
}
} else {
setcookie($name, $value, $expires, $path, $domain, $secure, $httponly);
}
} else {
setcookie($name, $value, [
'expires' => $expires,
'path' => $path,
'domain' => $domain,
'secure' => $secure,
'httponly' => $httponly,
'samesite' => $samesite
]);
}
}
/**
* Turn on/off maintenance mode.
*
* @param bool $maintenance Turn On/Off.
*
* @return bool
*/
function maintenance_mode($maintenance = TRUE) {
$file = BASEDIR.'.maintenance';
if ($maintenance) {
if (!($fp = @fopen($file, 'w'))) {
return FALSE;
}
@fwrite($fp, '<?php $mt_mode_start = '.time().'; ?>');
@fclose($fp);
@chmod($file, 0644);
return is_readable($file);
} else {
if (file_exists($file)) {
return @unlink($file);
}
return NULL;
}
}
/**
* Recursive in_array
*
* @param mixed $needle The searched value.
* @param array $haystack The array.
* @param bool $strict If the third parameter strict is set to true then the in_array() function will also check the types of the needle in the haystack.
*
* @return bool
*/
function in_array_r($needle, $haystack, $strict = FALSE) {
foreach ($haystack as $item) {
if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && in_array_r($needle, $item, $strict))) {
return TRUE;
}
}
return FALSE;
}
/**
* Check if current page is set as homepage.
*
* @return bool
*/
function is_homepage() {
$settings = fusion_get_settings();
if ($settings['site_seo']) {
$params = http_build_query(\PHPFusion\Rewrite\Router::getRouterInstance()->getFileParams());
$path = \PHPFusion\Rewrite\Router::getRouterInstance()->getFilePath();
$file_path = '/'.(!empty($path) ? $path : PERMALINK_CURRENT_PATH).($params ? "?" : '').$params;
} else {
$file_path = '/'.PERMALINK_CURRENT_PATH;
}
return $settings['opening_page'] == 'index.php' && $file_path == '/' || $file_path == '/'.$settings['opening_page'];
}