1371 lines
34 KiB
PHP
1371 lines
34 KiB
PHP
<?php
|
|
/**
|
|
* Copyright since 2024 Webshop System
|
|
*
|
|
* Hilfsfunktionen für das Webshop-System
|
|
*
|
|
* @author Webshop System
|
|
* @license GPL v3
|
|
*/
|
|
|
|
class Tools
|
|
{
|
|
// Security-Konstanten
|
|
public const PASSWORDGEN_FLAG_NUMERIC = 1;
|
|
public const PASSWORDGEN_FLAG_NO_NUMERIC = 2;
|
|
public const PASSWORDGEN_FLAG_RANDOM = 4;
|
|
public const PASSWORDGEN_FLAG_ALPHANUMERIC = 8;
|
|
|
|
// Cache-Konstanten
|
|
public const CACHE_LIFETIME_SECONDS = 604800;
|
|
public const CACERT_LOCATION = 'https://curl.haxx.se/ca/cacert.pem';
|
|
|
|
// Statische Variablen
|
|
protected static $file_exists_cache = [];
|
|
protected static $_forceCompile;
|
|
protected static $_caching;
|
|
protected static $_string_modifier;
|
|
protected static $_user_plateform;
|
|
protected static $_user_browser;
|
|
protected static $request;
|
|
protected static $cldr_cache = [];
|
|
protected static $colorBrightnessCalculator;
|
|
protected static $fallbackParameters = [];
|
|
|
|
public static $round_mode = null;
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
public function __construct()
|
|
{
|
|
// Initialisierung
|
|
}
|
|
|
|
/**
|
|
* Redirect to install
|
|
*/
|
|
public static function redirectToInstall()
|
|
{
|
|
header('Location: /install');
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Convert bytes to integer
|
|
*/
|
|
public static function convertBytes($value)
|
|
{
|
|
if (is_numeric($value)) {
|
|
return (int)$value;
|
|
}
|
|
$value_length = strlen($value);
|
|
$qty = (int)substr($value, 0, $value_length - 1);
|
|
$unit = strtolower(substr($value, $value_length - 1));
|
|
switch ($unit) {
|
|
case 'k':
|
|
$qty *= 1024;
|
|
break;
|
|
case 'm':
|
|
$qty *= 1048576;
|
|
break;
|
|
case 'g':
|
|
$qty *= 1073741824;
|
|
break;
|
|
}
|
|
return $qty;
|
|
}
|
|
|
|
/**
|
|
* Check if running in CLI
|
|
*/
|
|
public static function isPHPCLI()
|
|
{
|
|
return (php_sapi_name() === 'cli' || defined('STDIN'));
|
|
}
|
|
|
|
/**
|
|
* Convert argv to GET parameters
|
|
*/
|
|
public static function argvToGET($argc, $argv)
|
|
{
|
|
for ($i = 1; $i < $argc; $i++) {
|
|
if (strpos($argv[$i], '=') !== false) {
|
|
list($key, $value) = explode('=', $argv[$i], 2);
|
|
$_GET[$key] = $value;
|
|
}
|
|
}
|
|
}
|
|
|
|
// ===== SECURITY FUNCTIONS =====
|
|
|
|
/**
|
|
* Hash password
|
|
*/
|
|
public static function hash($passwd)
|
|
{
|
|
return hash('sha256', $passwd . (defined('_COOKIE_KEY_') ? _COOKIE_KEY_ : 'webshop_key'));
|
|
}
|
|
|
|
/**
|
|
* Hash data with IV
|
|
*/
|
|
public static function hashIV($data)
|
|
{
|
|
return hash('sha256', $data . (defined('_COOKIE_IV_') ? _COOKIE_IV_ : 'webshop_iv'));
|
|
}
|
|
|
|
/**
|
|
* Generate random password
|
|
*/
|
|
public static function passwdGen($length = 8, $flag = self::PASSWORDGEN_FLAG_ALPHANUMERIC)
|
|
{
|
|
$chars = '';
|
|
if ($flag & self::PASSWORDGEN_FLAG_NUMERIC) {
|
|
$chars .= '0123456789';
|
|
}
|
|
if ($flag & self::PASSWORDGEN_FLAG_NO_NUMERIC) {
|
|
$chars .= 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
}
|
|
if ($flag & self::PASSWORDGEN_FLAG_ALPHANUMERIC) {
|
|
$chars .= 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
|
}
|
|
if ($flag & self::PASSWORDGEN_FLAG_RANDOM) {
|
|
$chars .= 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()';
|
|
}
|
|
|
|
$password = '';
|
|
for ($i = 0; $i < $length; $i++) {
|
|
$password .= $chars[rand(0, strlen($chars) - 1)];
|
|
}
|
|
|
|
return $password;
|
|
}
|
|
|
|
/**
|
|
* Get CSRF token
|
|
*/
|
|
public static function getToken($page = true, $context = null)
|
|
{
|
|
if (!$context) {
|
|
$context = Context::getContext();
|
|
}
|
|
|
|
if ($page === true) {
|
|
$customer_id = isset($context->customer) ? $context->customer->id : 0;
|
|
$customer_passwd = isset($context->customer) ? $context->customer->passwd : '';
|
|
$script_name = isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : '';
|
|
return self::hash($customer_id . $customer_passwd . $script_name);
|
|
} else {
|
|
$customer_id = isset($context->customer) ? $context->customer->id : 0;
|
|
$customer_passwd = isset($context->customer) ? $context->customer->passwd : '';
|
|
return self::hash($customer_id . $customer_passwd . $page);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get admin token
|
|
*/
|
|
public static function getAdminToken($string)
|
|
{
|
|
return !empty($string) ? self::hash($string) : false;
|
|
}
|
|
|
|
/**
|
|
* Get admin token lite
|
|
*/
|
|
public static function getAdminTokenLite($tab, $context = null)
|
|
{
|
|
if (!$context) {
|
|
$context = Context::getContext();
|
|
}
|
|
|
|
$employee_id = isset($context->employee) ? $context->employee->id : 0;
|
|
return self::getAdminToken($tab . $employee_id);
|
|
}
|
|
|
|
/**
|
|
* Get admin token for Smarty
|
|
*/
|
|
public static function getAdminTokenLiteSmarty($params)
|
|
{
|
|
$context = Context::getContext();
|
|
$employee_id = isset($context->employee) ? $context->employee->id : 0;
|
|
return self::getAdminToken($params['tab'] . $employee_id);
|
|
}
|
|
|
|
/**
|
|
* Get admin URL
|
|
*/
|
|
public static function getAdminUrl($url = null, $entities = false)
|
|
{
|
|
$admin_url = defined('_WEBSHOP_ADMIN_DIR_') ? _WEBSHOP_ADMIN_DIR_ : '/admin/';
|
|
|
|
if ($url) {
|
|
$admin_url .= $url;
|
|
}
|
|
|
|
if ($entities) {
|
|
$admin_url = htmlentities($admin_url);
|
|
}
|
|
|
|
return $admin_url;
|
|
}
|
|
|
|
/**
|
|
* Get admin image URL
|
|
*/
|
|
public static function getAdminImageUrl($image = null, $entities = false)
|
|
{
|
|
$admin_img_url = defined('_WEBSHOP_ADMIN_IMG_') ? _WEBSHOP_ADMIN_IMG_ : '/admin/img/';
|
|
|
|
if ($image) {
|
|
$admin_img_url .= $image;
|
|
}
|
|
|
|
if ($entities) {
|
|
$admin_img_url = htmlentities($admin_img_url);
|
|
}
|
|
|
|
return $admin_img_url;
|
|
}
|
|
|
|
/**
|
|
* Convert string to URL-friendly format
|
|
*/
|
|
public static function str2url($str)
|
|
{
|
|
$str = self::replaceAccentedChars($str);
|
|
$str = preg_replace('/[^a-zA-Z0-9\s\-\_]/', '', $str);
|
|
$str = preg_replace('/[\s\-\_]+/', '-', $str);
|
|
$str = strtolower(trim($str, '-'));
|
|
|
|
return $str;
|
|
}
|
|
|
|
/**
|
|
* Replace accented characters
|
|
*/
|
|
public static function replaceAccentedChars($str)
|
|
{
|
|
$unwanted_array = [
|
|
'Š'=>'S', 'š'=>'s', 'Ž'=>'Z', 'ž'=>'z', 'À'=>'A', 'Á'=>'A', 'Â'=>'A', 'Ã'=>'A', 'Ä'=>'A', 'Å'=>'A', 'Æ'=>'A', 'Ç'=>'C', 'È'=>'E', 'É'=>'E',
|
|
'Ê'=>'E', 'Ë'=>'E', 'Ì'=>'I', 'Í'=>'I', 'Î'=>'I', 'Ï'=>'I', 'Ñ'=>'N', 'Ò'=>'O', 'Ó'=>'O', 'Ô'=>'O', 'Õ'=>'O', 'Ö'=>'O', 'Ø'=>'O', 'Ù'=>'U',
|
|
'Ú'=>'U', 'Û'=>'U', 'Ü'=>'U', 'Ý'=>'Y', 'Þ'=>'B', 'ß'=>'Ss', 'à'=>'a', 'á'=>'a', 'â'=>'a', 'ã'=>'a', 'ä'=>'a', 'å'=>'a', 'æ'=>'a', 'ç'=>'c',
|
|
'è'=>'e', 'é'=>'e', 'ê'=>'e', 'ë'=>'e', 'ì'=>'i', 'í'=>'i', 'î'=>'i', 'ï'=>'i', 'ð'=>'o', 'ñ'=>'n', 'ò'=>'o', 'ó'=>'o', 'ô'=>'o', 'õ'=>'o',
|
|
'ö'=>'o', 'ø'=>'o', 'ù'=>'u', 'ú'=>'u', 'û'=>'u', 'ý'=>'y', 'ý'=>'y', 'þ'=>'b', 'ÿ'=>'y'
|
|
];
|
|
|
|
return strtr($str, $unwanted_array);
|
|
}
|
|
|
|
/**
|
|
* Truncate string
|
|
*/
|
|
public static function truncate($str, $max_length, $suffix = '...')
|
|
{
|
|
if (self::strlen($str) <= $max_length) {
|
|
return $str;
|
|
}
|
|
|
|
return self::substr($str, 0, $max_length - self::strlen($suffix)) . $suffix;
|
|
}
|
|
|
|
/**
|
|
* Get string length
|
|
*/
|
|
public static function strlen($str, $encoding = 'UTF-8')
|
|
{
|
|
return mb_strlen($str, $encoding);
|
|
}
|
|
|
|
/**
|
|
* Convert to lowercase
|
|
*/
|
|
public static function strtolower($str)
|
|
{
|
|
return mb_strtolower($str, 'UTF-8');
|
|
}
|
|
|
|
/**
|
|
* Convert to uppercase
|
|
*/
|
|
public static function strtoupper($str)
|
|
{
|
|
return mb_strtoupper($str, 'UTF-8');
|
|
}
|
|
|
|
/**
|
|
* Get substring
|
|
*/
|
|
public static function substr($str, $start, $length = false, $encoding = 'UTF-8')
|
|
{
|
|
if ($length === false) {
|
|
return mb_substr($str, $start, mb_strlen($str, $encoding), $encoding);
|
|
}
|
|
|
|
return mb_substr($str, $start, $length, $encoding);
|
|
}
|
|
|
|
/**
|
|
* Find position of substring
|
|
*/
|
|
public static function strpos($str, $find, $offset = 0, $encoding = 'UTF-8')
|
|
{
|
|
return mb_strpos($str, $find, $offset, $encoding);
|
|
}
|
|
|
|
/**
|
|
* Find last position of substring
|
|
*/
|
|
public static function strrpos($str, $find, $offset = 0, $encoding = 'UTF-8')
|
|
{
|
|
return mb_strrpos($str, $find, $offset, $encoding);
|
|
}
|
|
|
|
/**
|
|
* Convert first character to uppercase
|
|
*/
|
|
public static function ucfirst($str)
|
|
{
|
|
return self::strtoupper(self::substr($str, 0, 1)) . self::substr($str, 1);
|
|
}
|
|
|
|
/**
|
|
* Convert first character of each word to uppercase
|
|
*/
|
|
public static function ucwords($str)
|
|
{
|
|
return mb_convert_case($str, MB_CASE_TITLE, 'UTF-8');
|
|
}
|
|
|
|
/**
|
|
* Delete directory recursively
|
|
*/
|
|
public static function deleteDirectory($dirname, $delete_self = true)
|
|
{
|
|
if (!is_dir($dirname)) {
|
|
return false;
|
|
}
|
|
|
|
$files = array_diff(scandir($dirname), ['.', '..']);
|
|
|
|
foreach ($files as $file) {
|
|
$path = $dirname . DIRECTORY_SEPARATOR . $file;
|
|
|
|
if (is_dir($path)) {
|
|
self::deleteDirectory($path, true);
|
|
} else {
|
|
unlink($path);
|
|
}
|
|
}
|
|
|
|
if ($delete_self) {
|
|
return rmdir($dirname);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Delete file
|
|
*/
|
|
public static function deleteFile($file, $exclude_files = [])
|
|
{
|
|
if (in_array(basename($file), $exclude_files)) {
|
|
return true;
|
|
}
|
|
|
|
if (is_file($file)) {
|
|
return unlink($file);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Clear XML cache
|
|
*/
|
|
public static function clearXMLCache()
|
|
{
|
|
$files = glob(_PS_CACHE_DIR_ . '*.xml');
|
|
|
|
foreach ($files as $file) {
|
|
if (is_file($file)) {
|
|
unlink($file);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Check if file exists (with cache)
|
|
*/
|
|
public static function file_exists_cache($filename)
|
|
{
|
|
if (!isset(self::$file_exists_cache[$filename])) {
|
|
self::$file_exists_cache[$filename] = file_exists($filename);
|
|
}
|
|
|
|
return self::$file_exists_cache[$filename];
|
|
}
|
|
|
|
/**
|
|
* Check if file exists (without cache)
|
|
*/
|
|
public static function file_exists_no_cache($filename)
|
|
{
|
|
return file_exists($filename);
|
|
}
|
|
|
|
/**
|
|
* Refresh CA certificate file
|
|
*/
|
|
public static function refreshCACertFile()
|
|
{
|
|
$cacert_file = _PS_CACHE_DIR_ . 'cacert.pem';
|
|
|
|
if (!file_exists($cacert_file) || (time() - filemtime($cacert_file)) > self::CACHE_LIFETIME_SECONDS) {
|
|
$cacert_content = self::file_get_contents(self::CACERT_LOCATION);
|
|
|
|
if ($cacert_content) {
|
|
file_put_contents($cacert_file, $cacert_content);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Get file contents with cURL
|
|
*/
|
|
private static function file_get_contents_curl($url, $curl_timeout, $opts)
|
|
{
|
|
$ch = curl_init();
|
|
curl_setopt($ch, CURLOPT_URL, $url);
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, $curl_timeout);
|
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
|
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
|
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
|
curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
|
|
|
|
if (is_array($opts)) {
|
|
curl_setopt_array($ch, $opts);
|
|
}
|
|
|
|
$content = curl_exec($ch);
|
|
curl_close($ch);
|
|
|
|
return $content;
|
|
}
|
|
|
|
/**
|
|
* Get file contents with fopen
|
|
*/
|
|
private static function file_get_contents_fopen($url, $use_include_path, $stream_context)
|
|
{
|
|
$opts = [
|
|
'http' => [
|
|
'method' => 'GET',
|
|
'timeout' => 5,
|
|
'user_agent' => 'Webshop System'
|
|
]
|
|
];
|
|
|
|
if ($stream_context) {
|
|
$context = stream_context_create($opts);
|
|
} else {
|
|
$context = null;
|
|
}
|
|
|
|
return file_get_contents($url, $use_include_path, $context);
|
|
}
|
|
|
|
/**
|
|
* Get file contents
|
|
*/
|
|
public static function file_get_contents($url, $use_include_path = false, $stream_context = null, $curl_timeout = 5, $fallback = false)
|
|
{
|
|
$content = self::file_get_contents_curl($url, $curl_timeout, []);
|
|
|
|
if ($content === false && $fallback) {
|
|
$content = self::file_get_contents_fopen($url, $use_include_path, $stream_context);
|
|
}
|
|
|
|
return $content;
|
|
}
|
|
|
|
/**
|
|
* Create file from URL
|
|
*/
|
|
public static function createFileFromUrl($url)
|
|
{
|
|
$content = self::file_get_contents($url);
|
|
|
|
if ($content === false) {
|
|
return false;
|
|
}
|
|
|
|
$filename = tempnam(_PS_CACHE_DIR_, 'webshop_');
|
|
|
|
if (file_put_contents($filename, $content)) {
|
|
return $filename;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Load simple XML from file
|
|
*/
|
|
public static function simplexml_load_file($url, $class_name = null)
|
|
{
|
|
$content = self::file_get_contents($url);
|
|
|
|
if ($content === false) {
|
|
return false;
|
|
}
|
|
|
|
return simplexml_load_string($content, $class_name);
|
|
}
|
|
|
|
/**
|
|
* Copy file
|
|
*/
|
|
public static function copy($source, $destination, $stream_context = null)
|
|
{
|
|
if (!$stream_context) {
|
|
return copy($source, $destination);
|
|
}
|
|
|
|
return copy($source, $destination, $stream_context);
|
|
}
|
|
|
|
/**
|
|
* Recursively copy directory
|
|
*/
|
|
public static function recurseCopy($src, $dst, $del = false)
|
|
{
|
|
if (!is_dir($src)) {
|
|
return false;
|
|
}
|
|
|
|
if (!is_dir($dst)) {
|
|
mkdir($dst, 0755, true);
|
|
}
|
|
|
|
$files = array_diff(scandir($src), ['.', '..']);
|
|
|
|
foreach ($files as $file) {
|
|
$src_file = $src . DIRECTORY_SEPARATOR . $file;
|
|
$dst_file = $dst . DIRECTORY_SEPARATOR . $file;
|
|
|
|
if (is_dir($src_file)) {
|
|
self::recurseCopy($src_file, $dst_file, $del);
|
|
if ($del) {
|
|
rmdir($src_file);
|
|
}
|
|
} else {
|
|
copy($src_file, $dst_file);
|
|
if ($del) {
|
|
unlink($src_file);
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Scan directory
|
|
*/
|
|
public static function scandir($path, $ext = 'php', $dir = '', $recursive = false)
|
|
{
|
|
$files = [];
|
|
|
|
if (!is_dir($path)) {
|
|
return $files;
|
|
}
|
|
|
|
$items = scandir($path);
|
|
|
|
foreach ($items as $item) {
|
|
if ($item == '.' || $item == '..') {
|
|
continue;
|
|
}
|
|
|
|
$item_path = $path . DIRECTORY_SEPARATOR . $item;
|
|
|
|
if (is_dir($item_path) && $recursive) {
|
|
$files = array_merge($files, self::scandir($item_path, $ext, $dir . $item . DIRECTORY_SEPARATOR, $recursive));
|
|
} elseif (is_file($item_path) && pathinfo($item_path, PATHINFO_EXTENSION) == $ext) {
|
|
$files[] = $dir . $item;
|
|
}
|
|
}
|
|
|
|
return $files;
|
|
}
|
|
|
|
/**
|
|
* Change file modification time
|
|
*/
|
|
public static function changeFileMTime($file_name)
|
|
{
|
|
return touch($file_name);
|
|
}
|
|
|
|
/**
|
|
* Wait until file is modified
|
|
*/
|
|
public static function waitUntilFileIsModified($file_name, $timeout = 180)
|
|
{
|
|
$time = time();
|
|
$filemtime = filemtime($file_name);
|
|
|
|
while ($timeout > 0 && ($time - $filemtime) < 0) {
|
|
sleep(1);
|
|
$timeout--;
|
|
clearstatcache();
|
|
$filemtime = filemtime($file_name);
|
|
}
|
|
|
|
return ($time - $filemtime) >= 0;
|
|
}
|
|
|
|
/**
|
|
* File attachment
|
|
*/
|
|
public static function fileAttachment($input = 'fileUpload', $return_content = true)
|
|
{
|
|
if (!isset($_FILES[$input])) {
|
|
return false;
|
|
}
|
|
|
|
$file = $_FILES[$input];
|
|
|
|
if ($file['error'] !== UPLOAD_ERR_OK) {
|
|
return false;
|
|
}
|
|
|
|
if ($return_content) {
|
|
return file_get_contents($file['tmp_name']);
|
|
}
|
|
|
|
return $file;
|
|
}
|
|
|
|
/**
|
|
* Normalize directory
|
|
*/
|
|
public static function normalizeDirectory($directory)
|
|
{
|
|
return rtrim($directory, '/\\') . DIRECTORY_SEPARATOR;
|
|
}
|
|
|
|
/**
|
|
* Get directories
|
|
*/
|
|
public static function getDirectories($path)
|
|
{
|
|
$directories = [];
|
|
|
|
if (!is_dir($path)) {
|
|
return $directories;
|
|
}
|
|
|
|
$items = scandir($path);
|
|
|
|
foreach ($items as $item) {
|
|
if ($item == '.' || $item == '..') {
|
|
continue;
|
|
}
|
|
|
|
$item_path = $path . DIRECTORY_SEPARATOR . $item;
|
|
|
|
if (is_dir($item_path)) {
|
|
$directories[] = $item;
|
|
}
|
|
}
|
|
|
|
return $directories;
|
|
}
|
|
|
|
/**
|
|
* Get directories with glob
|
|
*/
|
|
public static function getDirectoriesWithGlob($path)
|
|
{
|
|
$directories = glob($path . '/*', GLOB_ONLYDIR);
|
|
|
|
if ($directories === false) {
|
|
return [];
|
|
}
|
|
|
|
return array_map('basename', $directories);
|
|
}
|
|
|
|
/**
|
|
* Get directories with readdir
|
|
*/
|
|
public static function getDirectoriesWithReaddir($path)
|
|
{
|
|
$directories = [];
|
|
|
|
if (!is_dir($path)) {
|
|
return $directories;
|
|
}
|
|
|
|
$handle = opendir($path);
|
|
|
|
while (($item = readdir($handle)) !== false) {
|
|
if ($item == '.' || $item == '..') {
|
|
continue;
|
|
}
|
|
|
|
$item_path = $path . DIRECTORY_SEPARATOR . $item;
|
|
|
|
if (is_dir($item_path)) {
|
|
$directories[] = $item;
|
|
}
|
|
}
|
|
|
|
closedir($handle);
|
|
|
|
return $directories;
|
|
}
|
|
|
|
/**
|
|
* Check if form is submitted
|
|
*/
|
|
public static function isSubmit($submit)
|
|
{
|
|
return isset($_POST[$submit]) || isset($_GET[$submit]);
|
|
}
|
|
|
|
/**
|
|
* Get value from POST or GET
|
|
*/
|
|
public static function getValue($key, $default_value = false)
|
|
{
|
|
if (!isset($key) || empty($key) || !is_string($key)) {
|
|
return false;
|
|
}
|
|
|
|
$ret = (isset($_POST[$key]) ? $_POST[$key] : (isset($_GET[$key]) ? $_GET[$key] : $default_value));
|
|
|
|
if (is_string($ret)) {
|
|
return stripslashes(urldecode(preg_replace('/((\%5C0+)|(\%00+))/i', '', urlencode($ret))));
|
|
}
|
|
|
|
return $ret;
|
|
}
|
|
|
|
/**
|
|
* Get all values
|
|
*/
|
|
public static function getAllValues()
|
|
{
|
|
return $_POST + $_GET;
|
|
}
|
|
|
|
/**
|
|
* Check if value is set
|
|
*/
|
|
public static function getIsset($key)
|
|
{
|
|
return isset($_POST[$key]) || isset($_GET[$key]);
|
|
}
|
|
|
|
/**
|
|
* Safe output
|
|
*/
|
|
public static function safeOutput($string, $html = false)
|
|
{
|
|
if (!$html) {
|
|
$string = strip_tags($string);
|
|
}
|
|
|
|
return $string;
|
|
}
|
|
|
|
/**
|
|
* HTML entities UTF8
|
|
*/
|
|
public static function htmlentitiesUTF8($string, $type = ENT_QUOTES)
|
|
{
|
|
return htmlentities($string, $type, 'UTF-8');
|
|
}
|
|
|
|
/**
|
|
* HTML entities decode UTF8
|
|
*/
|
|
public static function htmlentitiesDecodeUTF8($string)
|
|
{
|
|
return html_entity_decode($string, ENT_QUOTES, 'UTF-8');
|
|
}
|
|
|
|
/**
|
|
* Get HTTP host
|
|
*/
|
|
public static function getHttpHost($http = false, $entities = false, $ignore_port = false)
|
|
{
|
|
$host = (isset($_SERVER['HTTP_X_FORWARDED_HOST']) ? $_SERVER['HTTP_X_FORWARDED_HOST'] : $_SERVER['HTTP_HOST']);
|
|
|
|
if ($ignore_port && $pos = strpos($host, ':')) {
|
|
$host = substr($host, 0, $pos);
|
|
}
|
|
|
|
if ($entities) {
|
|
$host = htmlspecialchars($host, ENT_QUOTES, 'UTF-8');
|
|
}
|
|
|
|
if ($http) {
|
|
$host = (self::usingSecureMode() ? 'https://' : 'http://') . $host;
|
|
}
|
|
|
|
return $host;
|
|
}
|
|
|
|
/**
|
|
* Get current URL protocol prefix
|
|
*/
|
|
public static function getCurrentUrlProtocolPrefix()
|
|
{
|
|
if (self::usingSecureMode()) {
|
|
return 'https://';
|
|
}
|
|
|
|
return 'http://';
|
|
}
|
|
|
|
/**
|
|
* Check if using secure mode
|
|
*/
|
|
public static function usingSecureMode()
|
|
{
|
|
return (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ||
|
|
(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https');
|
|
}
|
|
|
|
/**
|
|
* Get remote address
|
|
*/
|
|
public static function getRemoteAddr()
|
|
{
|
|
if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR'] && (!isset($_SERVER['REMOTE_ADDR']) || preg_match('/^127\.|^10\.|^172\.16|^192\.168\./', $_SERVER['REMOTE_ADDR']))) {
|
|
$ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
|
|
return trim($ips[0]);
|
|
}
|
|
|
|
return $_SERVER['REMOTE_ADDR'];
|
|
}
|
|
|
|
/**
|
|
* Redirect
|
|
*/
|
|
public static function redirect($url, $base_uri = '/', $link = null, $headers = null)
|
|
{
|
|
if (!$link) {
|
|
$link = Context::getContext()->link;
|
|
}
|
|
|
|
if (strpos($url, 'http') !== 0) {
|
|
if (strpos($url, $base_uri) === 0) {
|
|
$url = substr($url, strlen($base_uri));
|
|
}
|
|
$url = $link->getBaseLink() . ltrim($url, '/');
|
|
}
|
|
|
|
if (is_array($headers)) {
|
|
foreach ($headers as $header) {
|
|
header($header);
|
|
}
|
|
}
|
|
|
|
header('Location: ' . $url);
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Redirect admin
|
|
*/
|
|
public static function redirectAdmin($url)
|
|
{
|
|
header('Location: ' . $url);
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Display error
|
|
*/
|
|
public static function displayError($errorMessage = null, $htmlentities = null, $context = null)
|
|
{
|
|
if (!$context) {
|
|
$context = Context::getContext();
|
|
}
|
|
|
|
if (!$htmlentities) {
|
|
$htmlentities = (bool)Configuration::get('PS_HTML_ERRORS');
|
|
}
|
|
|
|
if ($errorMessage) {
|
|
$errorMessage = $htmlentities ? htmlentities($errorMessage, ENT_QUOTES, 'UTF-8') : $errorMessage;
|
|
}
|
|
|
|
$context->smarty->assign('error', $errorMessage);
|
|
}
|
|
|
|
/**
|
|
* Die object
|
|
*/
|
|
public static function dieObject($object, $kill = true)
|
|
{
|
|
echo '<pre style="text-align: left;">';
|
|
print_r($object);
|
|
echo '</pre><br />';
|
|
|
|
if ($kill) {
|
|
die('END');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Debug backtrace
|
|
*/
|
|
public static function debug_backtrace($start = 0, $limit = null)
|
|
{
|
|
$backtrace = debug_backtrace();
|
|
|
|
if ($limit) {
|
|
$backtrace = array_slice($backtrace, $start, $limit);
|
|
} else {
|
|
$backtrace = array_slice($backtrace, $start);
|
|
}
|
|
|
|
return $backtrace;
|
|
}
|
|
|
|
/**
|
|
* Error log
|
|
*/
|
|
public static function error_log($object, $message_type = null, $destination = null, $extra_headers = null)
|
|
{
|
|
return error_log($object, $message_type, $destination, $extra_headers);
|
|
}
|
|
|
|
/**
|
|
* Reset static cache
|
|
*/
|
|
public static function resetStaticCache()
|
|
{
|
|
self::$file_exists_cache = [];
|
|
self::$_forceCompile = null;
|
|
self::$_caching = null;
|
|
}
|
|
|
|
/**
|
|
* Reset request
|
|
*/
|
|
public static function resetRequest()
|
|
{
|
|
self::$request = null;
|
|
}
|
|
|
|
/**
|
|
* String replace first
|
|
*/
|
|
public static function strReplaceFirst($search, $replace, $subject, $cur = 0)
|
|
{
|
|
return (strpos($subject, $search, $cur) !== false) ? substr_replace($subject, $replace, (int)strpos($subject, $search, $cur), strlen($search)) : $subject;
|
|
}
|
|
|
|
/**
|
|
* String replace once
|
|
*/
|
|
public static function str_replace_once($needle, $replace, $haystack)
|
|
{
|
|
$pos = strpos($haystack, $needle);
|
|
|
|
if ($pos === false) {
|
|
return $haystack;
|
|
}
|
|
|
|
return substr_replace($haystack, $replace, $pos, strlen($needle));
|
|
}
|
|
|
|
/**
|
|
* Check if field is empty
|
|
*/
|
|
public static function isEmpty($field)
|
|
{
|
|
return ($field === '' || $field === null);
|
|
}
|
|
|
|
/**
|
|
* Format bytes
|
|
*/
|
|
public static function formatBytes($size, $precision = 2)
|
|
{
|
|
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
|
|
for ($i = 0; $size > 1024 && $i < count($units) - 1; $i++) {
|
|
$size /= 1024;
|
|
}
|
|
|
|
return round($size, $precision) . ' ' . $units[$i];
|
|
}
|
|
|
|
/**
|
|
* Boolean value
|
|
*/
|
|
public static function boolVal($value)
|
|
{
|
|
if (is_string($value)) {
|
|
$value = strtolower($value);
|
|
}
|
|
|
|
return in_array($value, [true, 1, '1', 'on', 'yes', 'true'], true);
|
|
}
|
|
|
|
/**
|
|
* Get user platform
|
|
*/
|
|
public static function getUserPlatform()
|
|
{
|
|
if (isset(self::$_user_plateform)) {
|
|
return self::$_user_plateform;
|
|
}
|
|
|
|
$user_agent = $_SERVER['HTTP_USER_AGENT'];
|
|
|
|
if (strpos($user_agent, 'Win')) {
|
|
self::$_user_plateform = 'Windows';
|
|
} elseif (strpos($user_agent, 'Mac')) {
|
|
self::$_user_plateform = 'Mac';
|
|
} elseif (strpos($user_agent, 'Linux')) {
|
|
self::$_user_plateform = 'Linux';
|
|
} elseif (strpos($user_agent, 'Android')) {
|
|
self::$_user_plateform = 'Android';
|
|
} elseif (strpos($user_agent, 'iPhone') || strpos($user_agent, 'iPad')) {
|
|
self::$_user_plateform = 'iOS';
|
|
} else {
|
|
self::$_user_plateform = 'Unknown';
|
|
}
|
|
|
|
return self::$_user_plateform;
|
|
}
|
|
|
|
/**
|
|
* Get user browser
|
|
*/
|
|
public static function getUserBrowser()
|
|
{
|
|
if (isset(self::$_user_browser)) {
|
|
return self::$_user_browser;
|
|
}
|
|
|
|
$user_agent = $_SERVER['HTTP_USER_AGENT'];
|
|
|
|
if (strpos($user_agent, 'Chrome')) {
|
|
self::$_user_browser = 'Chrome';
|
|
} elseif (strpos($user_agent, 'Firefox')) {
|
|
self::$_user_browser = 'Firefox';
|
|
} elseif (strpos($user_agent, 'Safari')) {
|
|
self::$_user_browser = 'Safari';
|
|
} elseif (strpos($user_agent, 'Edge')) {
|
|
self::$_user_browser = 'Edge';
|
|
} elseif (strpos($user_agent, 'MSIE') || strpos($user_agent, 'Trident')) {
|
|
self::$_user_browser = 'Internet Explorer';
|
|
} else {
|
|
self::$_user_browser = 'Unknown';
|
|
}
|
|
|
|
return self::$_user_browser;
|
|
}
|
|
|
|
/**
|
|
* Round value
|
|
*/
|
|
public static function ps_round($value, $precision = 0, $round_mode = null)
|
|
{
|
|
if ($round_mode === null) {
|
|
$round_mode = self::$round_mode;
|
|
}
|
|
|
|
if ($round_mode === null) {
|
|
$round_mode = PS_ROUND_HALF_UP;
|
|
}
|
|
|
|
return self::math_round($value, $precision, $round_mode);
|
|
}
|
|
|
|
/**
|
|
* Math round
|
|
*/
|
|
public static function math_round($value, $places, $mode = PS_ROUND_HALF_UP)
|
|
{
|
|
return self::round_helper($value, $mode);
|
|
}
|
|
|
|
/**
|
|
* Round helper
|
|
*/
|
|
public static function round_helper($value, $mode)
|
|
{
|
|
if (is_string($value)) {
|
|
return $value;
|
|
}
|
|
|
|
switch ($mode) {
|
|
case PS_ROUND_UP:
|
|
return ceil($value);
|
|
case PS_ROUND_DOWN:
|
|
return floor($value);
|
|
case PS_ROUND_HALF_DOWN:
|
|
return round($value, 0, PHP_ROUND_HALF_DOWN);
|
|
case PS_ROUND_HALF_EVEN:
|
|
return round($value, 0, PHP_ROUND_HALF_EVEN);
|
|
case PS_ROUND_HALF_ODD:
|
|
return round($value, 0, PHP_ROUND_HALF_ODD);
|
|
case PS_ROUND_HALF_UP:
|
|
default:
|
|
return round($value, 0, PHP_ROUND_HALF_UP);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Ceil with precision
|
|
*/
|
|
public static function ceilf($value, $precision = 0)
|
|
{
|
|
$precision_factor = $precision == 0 ? 1 : pow(10, $precision);
|
|
$tmp = $value * $precision_factor;
|
|
$tmp2 = (string)$tmp;
|
|
|
|
if (strpos($tmp2, '.') === false) {
|
|
return $value;
|
|
}
|
|
|
|
$tmp = ceil($tmp);
|
|
$tmp /= $precision_factor;
|
|
|
|
return $tmp;
|
|
}
|
|
|
|
/**
|
|
* Floor with precision
|
|
*/
|
|
public static function floorf($value, $precision = 0)
|
|
{
|
|
$precision_factor = $precision == 0 ? 1 : pow(10, $precision);
|
|
$tmp = $value * $precision_factor;
|
|
$tmp2 = (string)$tmp;
|
|
|
|
if (strpos($tmp2, '.') === false) {
|
|
return $value;
|
|
}
|
|
|
|
$tmp = floor($tmp);
|
|
$tmp /= $precision_factor;
|
|
|
|
return $tmp;
|
|
}
|
|
|
|
/**
|
|
* Spread amount
|
|
*/
|
|
public static function spreadAmount($amount, $precision, &$rows, $column)
|
|
{
|
|
$sum = 0;
|
|
$precision_factor = pow(10, $precision);
|
|
|
|
foreach ($rows as $row) {
|
|
$sum += $row[$column] * $precision_factor;
|
|
}
|
|
|
|
$diff = ($amount * $precision_factor) - $sum;
|
|
|
|
if ($diff != 0) {
|
|
$rows[0][$column] += $diff / $precision_factor;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Enable cache
|
|
*/
|
|
public static function enableCache($level = 1, ?Context $context = null)
|
|
{
|
|
if (!$context) {
|
|
$context = Context::getContext();
|
|
}
|
|
|
|
if (!isset(self::$_caching)) {
|
|
self::$_caching = [];
|
|
}
|
|
|
|
self::$_caching[$level] = true;
|
|
|
|
if (isset($context->smarty)) {
|
|
$context->smarty->caching = $level;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Restore cache settings
|
|
*/
|
|
public static function restoreCacheSettings(?Context $context = null)
|
|
{
|
|
if (!$context) {
|
|
$context = Context::getContext();
|
|
}
|
|
|
|
if (isset(self::$_caching)) {
|
|
foreach (self::$_caching as $level => $enabled) {
|
|
if ($enabled) {
|
|
self::enableCache($level, $context);
|
|
} else {
|
|
self::disableCache($context);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clear cache
|
|
*/
|
|
public static function clearCache($smarty = null, $tpl = false, $cache_id = null, $compile_id = null)
|
|
{
|
|
if (!$smarty) {
|
|
$smarty = Context::getContext()->smarty;
|
|
}
|
|
|
|
if ($tpl) {
|
|
$smarty->clearCache($tpl, $cache_id, $compile_id);
|
|
} else {
|
|
$smarty->clearAllCache();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clear compile
|
|
*/
|
|
public static function clearCompile($smarty = null)
|
|
{
|
|
if (!$smarty) {
|
|
$smarty = Context::getContext()->smarty;
|
|
}
|
|
|
|
$smarty->clearCompiledTemplate();
|
|
}
|
|
|
|
/**
|
|
* Clear Smarty cache
|
|
*/
|
|
public static function clearSmartyCache()
|
|
{
|
|
$smarty = Context::getContext()->smarty;
|
|
$smarty->clearAllCache();
|
|
$smarty->clearCompiledTemplate();
|
|
}
|
|
|
|
/**
|
|
* Clear Symfony cache
|
|
*/
|
|
public static function clearSf2Cache($env = null)
|
|
{
|
|
if (!$env) {
|
|
$env = _PS_MODE_DEV_ ? 'dev' : 'prod';
|
|
}
|
|
|
|
$cache_dir = _PS_CACHE_DIR_ . 'sf2/' . $env . '/';
|
|
|
|
if (is_dir($cache_dir)) {
|
|
self::deleteDirectory($cache_dir, false);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clear all cache
|
|
*/
|
|
public static function clearAllCache()
|
|
{
|
|
self::clearSmartyCache();
|
|
self::clearSf2Cache();
|
|
self::clearXMLCache();
|
|
}
|
|
|
|
/**
|
|
* Get memory limit
|
|
*/
|
|
public static function getMemoryLimit()
|
|
{
|
|
$memory_limit = @ini_get('memory_limit');
|
|
|
|
if (preg_match('/^(\d+)(.)$/', $memory_limit, $matches)) {
|
|
switch ($matches[2]) {
|
|
case 'G':
|
|
$memory_limit = $matches[1] * 1024 * 1024 * 1024;
|
|
break;
|
|
case 'M':
|
|
$memory_limit = $matches[1] * 1024 * 1024;
|
|
break;
|
|
case 'K':
|
|
$memory_limit = $matches[1] * 1024;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return $memory_limit;
|
|
}
|
|
|
|
/**
|
|
* Get octets
|
|
*/
|
|
public static function getOctets($option)
|
|
{
|
|
if (preg_match('/[0-9]+k/i', $option)) {
|
|
return 1024 * (int)$option;
|
|
}
|
|
|
|
if (preg_match('/[0-9]+m/i', $option)) {
|
|
return 1024 * 1024 * (int)$option;
|
|
}
|
|
|
|
if (preg_match('/[0-9]+g/i', $option)) {
|
|
return 1024 * 1024 * 1024 * (int)$option;
|
|
}
|
|
|
|
return (int)$option;
|
|
}
|
|
|
|
/**
|
|
* Check if x86_64 architecture
|
|
*/
|
|
public static function isX86_64arch()
|
|
{
|
|
return (PHP_INT_SIZE == 8);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Get max upload size
|
|
*/
|
|
public static function getMaxUploadSize($max_size = 0)
|
|
{
|
|
$post_max_size = self::getOctets(ini_get('post_max_size'));
|
|
$upload_max_filesize = self::getOctets(ini_get('upload_max_filesize'));
|
|
$memory_limit = self::getOctets(ini_get('memory_limit'));
|
|
|
|
$max_upload = min($post_max_size, $upload_max_filesize, $memory_limit);
|
|
|
|
if ($max_size > 0) {
|
|
$max_upload = min($max_upload, $max_size);
|
|
}
|
|
|
|
return $max_upload;
|
|
}
|
|
}
|