2013-11-12 06:01:44 +08:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace RainLoop;
|
|
|
|
|
|
|
|
class Utils
|
|
|
|
{
|
2015-07-24 01:57:46 +08:00
|
|
|
/**
|
|
|
|
* @var string
|
|
|
|
*/
|
2015-08-15 03:20:47 +08:00
|
|
|
static $CookieDefaultPath = '';
|
2015-07-24 01:57:46 +08:00
|
|
|
|
2015-11-17 02:51:12 +08:00
|
|
|
/**
|
|
|
|
* @var bool|null
|
|
|
|
*/
|
|
|
|
static $CookieDefaultSecure = null;
|
|
|
|
|
2013-11-12 06:01:44 +08:00
|
|
|
static $Cookies = null;
|
2014-05-22 03:49:27 +08:00
|
|
|
|
2015-05-18 04:38:20 +08:00
|
|
|
static $RsaKey = null;
|
|
|
|
|
2013-11-12 06:01:44 +08:00
|
|
|
private function __construct()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-03-10 00:04:17 +08:00
|
|
|
static public function PgpVerifyFile(string $sFileName, string $sSignature) : bool
|
2015-05-13 00:33:02 +08:00
|
|
|
{
|
|
|
|
$sKeyFile = APP_VERSION_ROOT_PATH.'app/resources/RainLoop.asc';
|
|
|
|
if (\file_exists($sKeyFile) && \file_exists($sFileName) && !empty($sSignature))
|
|
|
|
{
|
|
|
|
$sKeyFile = @\file_get_contents($sKeyFile);
|
|
|
|
return !empty($sKeyFile); // TODO
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2015-05-18 04:38:20 +08:00
|
|
|
|
2020-03-10 00:04:17 +08:00
|
|
|
static public function RsaPrivateKey() : string
|
2015-05-18 04:38:20 +08:00
|
|
|
{
|
|
|
|
if (!empty(\RainLoop\Utils::$RsaKey))
|
|
|
|
{
|
|
|
|
return \RainLoop\Utils::$RsaKey;
|
|
|
|
}
|
|
|
|
|
|
|
|
\RainLoop\Utils::$RsaKey = \file_exists(APP_PRIVATE_DATA.'rsa/private') ?
|
|
|
|
\file_get_contents(APP_PRIVATE_DATA.'rsa/private') : '';
|
|
|
|
|
|
|
|
\RainLoop\Utils::$RsaKey = \is_string(\RainLoop\Utils::$RsaKey) ? \RainLoop\Utils::$RsaKey : '';
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return string|false
|
|
|
|
*/
|
2020-03-10 00:04:17 +08:00
|
|
|
static public function EncryptStringRSA(string $sString, string $sKey = '')
|
2015-05-18 04:38:20 +08:00
|
|
|
{
|
|
|
|
$sResult = '';
|
|
|
|
$sKey = \md5($sKey);
|
|
|
|
|
|
|
|
$sPrivateKey = \RainLoop\Utils::RsaPrivateKey();
|
|
|
|
if (!empty($sPrivateKey))
|
|
|
|
{
|
|
|
|
$oPrivKey = \openssl_pkey_get_private($sPrivateKey);
|
|
|
|
$oKeyDetails = \openssl_pkey_get_details($oPrivKey);
|
|
|
|
|
|
|
|
if (!empty($oKeyDetails['key']) && !empty($oKeyDetails['bits']))
|
|
|
|
{
|
|
|
|
$oPubKey = \openssl_pkey_get_public($oKeyDetails['key']);
|
|
|
|
|
|
|
|
$iC = (($oKeyDetails['bits'] / 8) - 15);
|
|
|
|
$aString = \str_split($sString, $iC);
|
|
|
|
|
|
|
|
foreach ($aString as $iIndex => $sLine)
|
|
|
|
{
|
|
|
|
$sEncrypted = '';
|
|
|
|
\openssl_public_encrypt($sLine, $sEncrypted, $oPubKey);
|
|
|
|
$aString[$iIndex] = $sEncrypted;
|
|
|
|
}
|
|
|
|
|
|
|
|
$aString[] = $sKey;
|
|
|
|
$sResult = @\serialize($aString);
|
|
|
|
|
|
|
|
\openssl_free_key($oPubKey);
|
|
|
|
}
|
|
|
|
|
|
|
|
\openssl_free_key($oPrivKey);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $sResult;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return string|false
|
|
|
|
*/
|
2020-03-10 00:04:17 +08:00
|
|
|
static public function DecryptStringRSA(string $sString, string $sKey = '')
|
2015-05-18 04:38:20 +08:00
|
|
|
{
|
|
|
|
$sResult = '';
|
|
|
|
$sKey = \md5($sKey);
|
|
|
|
|
|
|
|
$sPrivateKey = \RainLoop\Utils::RsaPrivateKey();
|
|
|
|
if (!empty($sPrivateKey) && !empty($sString))
|
|
|
|
{
|
|
|
|
$oPrivKey = \openssl_pkey_get_private($sPrivateKey);
|
|
|
|
|
|
|
|
$aString = @\unserialize($sString);
|
|
|
|
if (\is_array($aString))
|
|
|
|
{
|
|
|
|
if ($sKey === \array_pop($aString))
|
|
|
|
{
|
|
|
|
foreach ($aString as $iIndex => $sLine)
|
|
|
|
{
|
|
|
|
$sDecrypted = '';
|
|
|
|
\openssl_private_decrypt($sLine, $sDecrypted, $oPrivKey);
|
|
|
|
$aString[$iIndex] = $sDecrypted;
|
|
|
|
}
|
|
|
|
|
|
|
|
$sResult = \implode('', $aString);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
\openssl_free_key($oPrivKey);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $sResult;
|
|
|
|
}
|
2015-05-13 00:33:02 +08:00
|
|
|
|
2020-03-10 00:04:17 +08:00
|
|
|
static public function EncryptString(string $sString, string $sKey) : string
|
2013-11-12 06:01:44 +08:00
|
|
|
{
|
|
|
|
return \MailSo\Base\Crypt::XxteaEncrypt($sString, $sKey);
|
|
|
|
}
|
|
|
|
|
2020-03-10 00:04:17 +08:00
|
|
|
static public function DecryptString(string $sEncriptedString, string $sKey) : string
|
2013-11-12 06:01:44 +08:00
|
|
|
{
|
|
|
|
return \MailSo\Base\Crypt::XxteaDecrypt($sEncriptedString, $sKey);
|
|
|
|
}
|
2014-05-22 03:49:27 +08:00
|
|
|
|
2020-03-10 00:04:17 +08:00
|
|
|
static public function EncryptStringQ(string $sString, string $sKey) : string
|
2015-05-18 04:38:20 +08:00
|
|
|
{
|
|
|
|
// if (\MailSo\Base\Utils::FunctionExistsAndEnabled('openssl_pkey_get_private'))
|
|
|
|
// {
|
|
|
|
// return \RainLoop\Utils::EncryptStringRSA($sString,
|
|
|
|
// $sKey.'Q'.\RainLoop\Utils::GetShortToken());
|
|
|
|
// }
|
|
|
|
|
|
|
|
return \MailSo\Base\Crypt::XxteaEncrypt($sString,
|
|
|
|
$sKey.'Q'.\RainLoop\Utils::GetShortToken());
|
|
|
|
}
|
|
|
|
|
2020-03-10 00:04:17 +08:00
|
|
|
static public function DecryptStringQ(string $sEncriptedString, string $sKey) : string
|
2015-05-18 04:38:20 +08:00
|
|
|
{
|
|
|
|
// if (\MailSo\Base\Utils::FunctionExistsAndEnabled('openssl_pkey_get_private'))
|
|
|
|
// {
|
|
|
|
// return \RainLoop\Utils::DecryptStringRSA($sEncriptedString,
|
|
|
|
// $sKey.'Q'.\RainLoop\Utils::GetShortToken());
|
|
|
|
// }
|
|
|
|
|
|
|
|
return \MailSo\Base\Crypt::XxteaDecrypt($sEncriptedString,
|
|
|
|
$sKey.'Q'.\RainLoop\Utils::GetShortToken());
|
|
|
|
}
|
|
|
|
|
2020-03-10 00:04:17 +08:00
|
|
|
static public function EncodeKeyValues(array $aValues, string $sCustomKey = '') : string
|
2013-11-12 06:01:44 +08:00
|
|
|
{
|
|
|
|
return \MailSo\Base\Utils::UrlSafeBase64Encode(
|
2015-05-18 04:38:20 +08:00
|
|
|
\RainLoop\Utils::EncryptString(@\serialize($aValues), \md5(APP_SALT.$sCustomKey)));
|
2013-11-12 06:01:44 +08:00
|
|
|
}
|
|
|
|
|
2020-03-10 00:04:17 +08:00
|
|
|
static public function DecodeKeyValues(string $sEncodedValues, string $sCustomKey = '') : array
|
2013-11-12 06:01:44 +08:00
|
|
|
{
|
2015-05-18 04:38:20 +08:00
|
|
|
$aResult = @\unserialize(
|
2013-11-12 06:01:44 +08:00
|
|
|
\RainLoop\Utils::DecryptString(
|
|
|
|
\MailSo\Base\Utils::UrlSafeBase64Decode($sEncodedValues), \md5(APP_SALT.$sCustomKey)));
|
|
|
|
|
|
|
|
return \is_array($aResult) ? $aResult : array();
|
|
|
|
}
|
|
|
|
|
2020-03-10 00:04:17 +08:00
|
|
|
static public function EncodeKeyValuesQ(array $aValues, string $sCustomKey = '') : string
|
2015-05-18 04:38:20 +08:00
|
|
|
{
|
|
|
|
return \MailSo\Base\Utils::UrlSafeBase64Encode(
|
|
|
|
\RainLoop\Utils::EncryptStringQ(
|
|
|
|
@\serialize($aValues), \md5(APP_SALT.$sCustomKey)));
|
|
|
|
}
|
|
|
|
|
2020-03-10 00:04:17 +08:00
|
|
|
static public function DecodeKeyValuesQ(string $sEncodedValues, string $sCustomKey = '') : array
|
2015-05-18 04:38:20 +08:00
|
|
|
{
|
|
|
|
$aResult = @\unserialize(
|
|
|
|
\RainLoop\Utils::DecryptStringQ(
|
|
|
|
\MailSo\Base\Utils::UrlSafeBase64Decode($sEncodedValues), \md5(APP_SALT.$sCustomKey)));
|
|
|
|
|
|
|
|
return \is_array($aResult) ? $aResult : array();
|
|
|
|
}
|
|
|
|
|
2020-03-10 00:04:17 +08:00
|
|
|
static public function GetConnectionToken() : string
|
2013-11-12 06:01:44 +08:00
|
|
|
{
|
|
|
|
$sKey = 'rltoken';
|
|
|
|
|
|
|
|
$sToken = \RainLoop\Utils::GetCookie($sKey, null);
|
|
|
|
if (null === $sToken)
|
|
|
|
{
|
2015-02-12 05:39:27 +08:00
|
|
|
$sToken = \MailSo\Base\Utils::Md5Rand(APP_SALT);
|
2015-07-24 01:57:46 +08:00
|
|
|
\RainLoop\Utils::SetCookie($sKey, $sToken, \time() + 60 * 60 * 24 * 30);
|
2013-11-12 06:01:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return \md5('Connection'.APP_SALT.$sToken.'Token'.APP_SALT);
|
|
|
|
}
|
|
|
|
|
2020-03-10 00:04:17 +08:00
|
|
|
static public function Fingerprint() : string
|
2014-04-17 04:33:12 +08:00
|
|
|
{
|
|
|
|
return \md5(empty($_SERVER['HTTP_USER_AGENT']) ? 'RainLoopFingerprint' : $_SERVER['HTTP_USER_AGENT']);
|
|
|
|
}
|
|
|
|
|
2020-03-10 00:04:17 +08:00
|
|
|
static public function GetShortToken() : string
|
2013-11-12 06:01:44 +08:00
|
|
|
{
|
|
|
|
$sKey = 'rlsession';
|
|
|
|
|
|
|
|
$sToken = \RainLoop\Utils::GetCookie($sKey, null);
|
|
|
|
if (null === $sToken)
|
|
|
|
{
|
2015-02-12 05:39:27 +08:00
|
|
|
$sToken = \MailSo\Base\Utils::Md5Rand(APP_SALT);
|
2015-07-24 01:57:46 +08:00
|
|
|
\RainLoop\Utils::SetCookie($sKey, $sToken, 0);
|
2013-11-12 06:01:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return \md5('Session'.APP_SALT.$sToken.'Token'.APP_SALT);
|
|
|
|
}
|
|
|
|
|
2020-03-11 01:45:00 +08:00
|
|
|
static public function UpdateConnectionToken() : void
|
2013-11-12 06:01:44 +08:00
|
|
|
{
|
|
|
|
$sKey = 'rltoken';
|
|
|
|
|
|
|
|
$sToken = \RainLoop\Utils::GetCookie($sKey, '');
|
|
|
|
if (!empty($sToken))
|
|
|
|
{
|
2015-07-24 01:57:46 +08:00
|
|
|
\RainLoop\Utils::SetCookie($sKey, $sToken, \time() + 60 * 60 * 24 * 30);
|
2013-11-12 06:01:44 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-10 00:04:17 +08:00
|
|
|
static public function GetCsrfToken() : string
|
2013-11-12 06:01:44 +08:00
|
|
|
{
|
|
|
|
return \md5('Csrf'.APP_SALT.self::GetConnectionToken().'Token'.APP_SALT);
|
|
|
|
}
|
|
|
|
|
2020-03-10 00:04:17 +08:00
|
|
|
public static function PathMD5(string $sPath) : string
|
2013-11-12 06:01:44 +08:00
|
|
|
{
|
|
|
|
$sResult = '';
|
|
|
|
if (@\is_dir($sPath))
|
|
|
|
{
|
|
|
|
$oDirIterator = new \RecursiveDirectoryIterator($sPath);
|
|
|
|
$oIterator = new \RecursiveIteratorIterator($oDirIterator, \RecursiveIteratorIterator::SELF_FIRST);
|
|
|
|
|
|
|
|
foreach ($oIterator as $oFile)
|
|
|
|
{
|
|
|
|
$sResult = \md5($sResult.($oFile->isFile() ? \md5_file($oFile) : $oFile));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $sResult;
|
|
|
|
}
|
|
|
|
|
2020-03-11 01:45:00 +08:00
|
|
|
public static function ReadAndAddLang(string $sFileName, array &$aResultLang) : void
|
2013-11-12 06:01:44 +08:00
|
|
|
{
|
2015-01-05 03:30:07 +08:00
|
|
|
if (\file_exists($sFileName))
|
2013-11-12 06:01:44 +08:00
|
|
|
{
|
2015-11-13 01:11:52 +08:00
|
|
|
$isYml = '.yml' === substr($sFileName, -4);
|
|
|
|
if ($isYml)
|
|
|
|
{
|
2016-05-11 03:52:40 +08:00
|
|
|
$aLang = \spyc_load(\str_replace(array(': >-', ': |-', ': |+'), array(': >', ': |', ': |'), \file_get_contents($sFileName)));
|
2015-11-13 01:11:52 +08:00
|
|
|
if (\is_array($aLang))
|
|
|
|
{
|
|
|
|
\reset($aLang);
|
|
|
|
$sLangKey = key($aLang);
|
|
|
|
if (isset($aLang[$sLangKey]) && is_array($aLang[$sLangKey]))
|
|
|
|
{
|
|
|
|
$aLang = $aLang[$sLangKey];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$aLang = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$aLang = \RainLoop\Utils::CustomParseIniFile($sFileName, true);
|
|
|
|
}
|
|
|
|
|
2013-11-12 06:01:44 +08:00
|
|
|
if (\is_array($aLang))
|
|
|
|
{
|
|
|
|
foreach ($aLang as $sKey => $mValue)
|
|
|
|
{
|
|
|
|
if (\is_array($mValue))
|
|
|
|
{
|
|
|
|
foreach ($mValue as $sSecKey => $mSecValue)
|
|
|
|
{
|
|
|
|
$aResultLang[$sKey.'/'.$sSecKey] = $mSecValue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$aResultLang[$sKey] = $mValue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-10 00:04:17 +08:00
|
|
|
public static function FolderFiles(string $sDir, string $sType = '') : array
|
2013-11-12 06:01:44 +08:00
|
|
|
{
|
|
|
|
$aResult = array();
|
|
|
|
if (@\is_dir($sDir))
|
|
|
|
{
|
|
|
|
if (false !== ($rDirHandle = @\opendir($sDir)))
|
|
|
|
{
|
|
|
|
while (false !== ($sFile = @\readdir($rDirHandle)))
|
|
|
|
{
|
|
|
|
if (empty($sType) || $sType === \substr($sFile, -\strlen($sType)))
|
|
|
|
{
|
|
|
|
if (\is_file($sDir.'/'.$sFile))
|
|
|
|
{
|
|
|
|
$aResult[] = $sFile;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@\closedir($rDirHandle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $aResult;
|
|
|
|
}
|
|
|
|
|
2020-03-10 00:04:17 +08:00
|
|
|
public static function ClearHtmlOutput(string $sHtml) : string
|
2013-11-12 06:01:44 +08:00
|
|
|
{
|
|
|
|
// return $sHtml;
|
2016-05-20 08:04:15 +08:00
|
|
|
return \trim(\str_replace('> <', '><',
|
|
|
|
\str_replace('" />', '"/>',
|
2013-11-12 06:01:44 +08:00
|
|
|
\preg_replace('/[\s]+ /i', ' ',
|
|
|
|
\preg_replace('/ [\s]+/i', ' ',
|
|
|
|
\preg_replace('/[\r\n\t]+/', ' ',
|
|
|
|
$sHtml
|
2016-05-20 08:04:15 +08:00
|
|
|
))))));
|
2013-11-12 06:01:44 +08:00
|
|
|
}
|
|
|
|
|
2020-03-10 00:04:17 +08:00
|
|
|
public static function FastCheck(string $sKey) : bool
|
2013-11-12 06:01:44 +08:00
|
|
|
{
|
|
|
|
$bResult = false;
|
|
|
|
|
|
|
|
$aMatches = array();
|
|
|
|
if (!empty($sKey) && 0 < \strlen($sKey) && \preg_match('/^(RL[\d]+)\-(.+)\-([^\-]+)$/', $sKey, $aMatches) && 3 === \count($aMatches))
|
|
|
|
{
|
|
|
|
$bResult = $aMatches[3] === \strtoupper(\base_convert(\crc32(\md5(
|
|
|
|
$aMatches[1].'-'.$aMatches[2].'-')), 10, 32));
|
|
|
|
}
|
|
|
|
|
|
|
|
return $bResult;
|
|
|
|
}
|
|
|
|
|
2020-03-10 00:04:17 +08:00
|
|
|
public static function CompileTemplates(array &$aList, string $sDirName, string $sNameSuffix = '')
|
2013-11-12 06:01:44 +08:00
|
|
|
{
|
|
|
|
if (\file_exists($sDirName))
|
|
|
|
{
|
2015-06-01 01:40:54 +08:00
|
|
|
$aFileList = \RainLoop\Utils::FolderFiles($sDirName, '.html');
|
2013-11-12 06:01:44 +08:00
|
|
|
|
2015-06-01 01:40:54 +08:00
|
|
|
foreach ($aFileList as $sName)
|
2013-11-12 06:01:44 +08:00
|
|
|
{
|
2014-10-29 06:05:50 +08:00
|
|
|
$sTemplateName = \substr($sName, 0, -5).$sNameSuffix;
|
2015-06-01 01:40:54 +08:00
|
|
|
$aList[$sTemplateName] = $sDirName.'/'.$sName;
|
2013-11-12 06:01:44 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param mixed $mDefault = null
|
|
|
|
* @return mixed
|
|
|
|
*/
|
2020-03-10 00:04:17 +08:00
|
|
|
public static function GetCookie(string $sName, $mDefault = null)
|
2013-11-12 06:01:44 +08:00
|
|
|
{
|
2015-05-18 04:38:20 +08:00
|
|
|
if (null === \RainLoop\Utils::$Cookies)
|
2013-11-12 06:01:44 +08:00
|
|
|
{
|
2015-05-18 04:38:20 +08:00
|
|
|
\RainLoop\Utils::$Cookies = is_array($_COOKIE) ? $_COOKIE : array();
|
2013-11-12 06:01:44 +08:00
|
|
|
}
|
|
|
|
|
2015-05-18 04:38:20 +08:00
|
|
|
return isset(\RainLoop\Utils::$Cookies[$sName]) ? \RainLoop\Utils::$Cookies[$sName] : $mDefault;
|
2013-11-12 06:01:44 +08:00
|
|
|
}
|
|
|
|
|
2020-03-10 00:04:17 +08:00
|
|
|
public static function SetCookie(string $sName, string $sValue = '', int $iExpire = 0, ?string $sPath = null, ?string $sDomain = null, ?bool $bSecure = null, bool $bHttpOnly = true)
|
2013-11-12 06:01:44 +08:00
|
|
|
{
|
2015-05-18 04:38:20 +08:00
|
|
|
if (null === \RainLoop\Utils::$Cookies)
|
2013-11-12 06:01:44 +08:00
|
|
|
{
|
2015-05-18 04:38:20 +08:00
|
|
|
\RainLoop\Utils::$Cookies = is_array($_COOKIE) ? $_COOKIE : array();
|
2013-11-12 06:01:44 +08:00
|
|
|
}
|
|
|
|
|
2015-07-24 01:57:46 +08:00
|
|
|
if (null === $sPath)
|
|
|
|
{
|
|
|
|
$sPath = \RainLoop\Utils::$CookieDefaultPath;
|
2015-08-15 03:20:47 +08:00
|
|
|
$sPath = $sPath && 0 < \strlen($sPath) ? $sPath : null;
|
2015-07-24 01:57:46 +08:00
|
|
|
}
|
|
|
|
|
2015-11-17 02:51:12 +08:00
|
|
|
if (null === $bSecure)
|
|
|
|
{
|
|
|
|
$bSecure = \RainLoop\Utils::$CookieDefaultSecure;
|
|
|
|
}
|
|
|
|
|
2015-05-18 04:38:20 +08:00
|
|
|
\RainLoop\Utils::$Cookies[$sName] = $sValue;
|
2015-11-17 02:51:12 +08:00
|
|
|
@\setcookie($sName, $sValue, $iExpire, $sPath, $sDomain, $bSecure, $bHttpOnly);
|
2013-11-12 06:01:44 +08:00
|
|
|
}
|
|
|
|
|
2020-03-10 00:04:17 +08:00
|
|
|
public static function ClearCookie(string $sName)
|
2013-11-12 06:01:44 +08:00
|
|
|
{
|
2015-05-18 04:38:20 +08:00
|
|
|
if (null === \RainLoop\Utils::$Cookies)
|
2013-11-12 06:01:44 +08:00
|
|
|
{
|
2015-05-18 04:38:20 +08:00
|
|
|
\RainLoop\Utils::$Cookies = is_array($_COOKIE) ? $_COOKIE : array();
|
2013-11-12 06:01:44 +08:00
|
|
|
}
|
|
|
|
|
2015-08-15 03:20:47 +08:00
|
|
|
$sPath = \RainLoop\Utils::$CookieDefaultPath;
|
|
|
|
$sPath = $sPath && 0 < \strlen($sPath) ? $sPath : null;
|
|
|
|
|
2015-05-18 04:38:20 +08:00
|
|
|
unset(\RainLoop\Utils::$Cookies[$sName]);
|
2015-08-15 03:20:47 +08:00
|
|
|
@\setcookie($sName, '', \time() - 3600 * 24 * 30, $sPath);
|
2013-11-12 06:01:44 +08:00
|
|
|
}
|
|
|
|
|
2020-03-10 00:04:17 +08:00
|
|
|
public static function UrlEncode(string $sV, bool $bEncode = false) : string
|
2015-06-01 01:40:54 +08:00
|
|
|
{
|
|
|
|
return $bEncode ? \urlencode($sV) : $sV;
|
2015-04-25 06:15:11 +08:00
|
|
|
}
|
2015-02-12 08:48:11 +08:00
|
|
|
|
2020-03-10 00:04:17 +08:00
|
|
|
public static function WebPath() : string
|
2015-02-12 08:48:11 +08:00
|
|
|
{
|
|
|
|
$sAppPath = '';
|
|
|
|
return $sAppPath;
|
|
|
|
}
|
2020-03-10 00:04:17 +08:00
|
|
|
public static function WebVersionPath() : string
|
2015-02-12 08:48:11 +08:00
|
|
|
{
|
|
|
|
return self::WebPath().'rainloop/v/'.APP_VERSION.'/';
|
|
|
|
}
|
|
|
|
|
2020-03-10 00:04:17 +08:00
|
|
|
public static function WebStaticPath() : string
|
2015-02-12 08:48:11 +08:00
|
|
|
{
|
|
|
|
return self::WebVersionPath().'static/';
|
|
|
|
}
|
|
|
|
|
2020-03-10 00:04:17 +08:00
|
|
|
public static function RemoveSuggestionDuplicates(array $aSuggestions) : array
|
2015-08-20 02:58:34 +08:00
|
|
|
{
|
|
|
|
$aResult = array();
|
|
|
|
|
|
|
|
if (is_array($aSuggestions))
|
|
|
|
{
|
|
|
|
$aCache = array();
|
|
|
|
foreach ($aSuggestions as $aItem)
|
|
|
|
{
|
|
|
|
$sLine = \implode('~~', $aItem);
|
|
|
|
if (!isset($aCache[$sLine]))
|
|
|
|
{
|
|
|
|
$aCache[$sLine] = true;
|
|
|
|
$aResult[] = $aItem;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $aResult;
|
|
|
|
}
|
|
|
|
|
2020-03-10 00:04:17 +08:00
|
|
|
public static function CustomParseIniFile(string $sFileName, bool $bProcessSections = false) : array
|
2015-01-05 03:30:07 +08:00
|
|
|
{
|
2015-03-16 21:54:56 +08:00
|
|
|
// if (\MailSo\Base\Utils::FunctionExistsAndEnabled('parse_ini_file'))
|
|
|
|
// {
|
|
|
|
// return @\parse_ini_file($sFileName, !!$bProcessSections);
|
|
|
|
// }
|
2015-01-05 03:30:07 +08:00
|
|
|
|
|
|
|
$sData = @\file_get_contents($sFileName);
|
|
|
|
return \is_string($sData) ? @\parse_ini_string($sData, !!$bProcessSections) : null;
|
|
|
|
}
|
|
|
|
|
2020-03-10 00:04:17 +08:00
|
|
|
public static function CustomBaseConvert(string $sNumberInput, string $sFromBaseInput = '0123456789', string $sToBaseInput = '0123456789')
|
2014-05-22 03:49:27 +08:00
|
|
|
{
|
2013-11-12 06:01:44 +08:00
|
|
|
if ($sFromBaseInput === $sToBaseInput)
|
|
|
|
{
|
|
|
|
return $sNumberInput;
|
|
|
|
}
|
2014-05-22 03:49:27 +08:00
|
|
|
|
2013-11-12 06:01:44 +08:00
|
|
|
$mFromBase = \str_split($sFromBaseInput, 1);
|
|
|
|
$mToBase = \str_split($sToBaseInput, 1);
|
|
|
|
$aNumber = \str_split($sNumberInput, 1);
|
|
|
|
$iFromLen = \strlen($sFromBaseInput);
|
|
|
|
$iToLen = \strlen($sToBaseInput);
|
|
|
|
$numberLen = \strlen($sNumberInput);
|
|
|
|
$mRetVal = '';
|
|
|
|
|
|
|
|
if ($sToBaseInput === '0123456789')
|
|
|
|
{
|
|
|
|
$mRetVal = 0;
|
|
|
|
for ($iIndex = 1; $iIndex <= $numberLen; $iIndex++)
|
|
|
|
{
|
|
|
|
$mRetVal = \bcadd($mRetVal, \bcmul(\array_search($aNumber[$iIndex - 1], $mFromBase), \bcpow($iFromLen, $numberLen - $iIndex)));
|
|
|
|
}
|
2014-05-22 03:49:27 +08:00
|
|
|
|
2013-11-12 06:01:44 +08:00
|
|
|
return $mRetVal;
|
|
|
|
}
|
2014-05-22 03:49:27 +08:00
|
|
|
|
2013-11-12 06:01:44 +08:00
|
|
|
if ($sFromBaseInput != '0123456789')
|
|
|
|
{
|
|
|
|
$sBase10 = \RainLoop\Utils::CustomBaseConvert($sNumberInput, $sFromBaseInput, '0123456789');
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$sBase10 = $sNumberInput;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($sBase10 < \strlen($sToBaseInput))
|
|
|
|
{
|
|
|
|
return $mToBase[$sBase10];
|
|
|
|
}
|
|
|
|
|
|
|
|
while ($sBase10 !== '0')
|
|
|
|
{
|
|
|
|
$mRetVal = $mToBase[\bcmod($sBase10, $iToLen)].$mRetVal;
|
|
|
|
$sBase10 = \bcdiv($sBase10, $iToLen, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $mRetVal;
|
|
|
|
}
|
2020-03-10 00:04:17 +08:00
|
|
|
}
|