2017-12-16 08:19:56 +00:00
|
|
|
<?php
|
2018-01-02 00:14:55 +00:00
|
|
|
// both of these are provided by illuminate/database already
|
|
|
|
// but i feel like it makes sense to add these definitions regardless
|
2017-12-16 08:19:56 +00:00
|
|
|
|
|
|
|
if (!function_exists('starts_with')) {
|
2017-12-16 22:51:36 +00:00
|
|
|
function starts_with(string $string, string $text): bool
|
|
|
|
{
|
2017-12-16 08:19:56 +00:00
|
|
|
return substr($string, 0, strlen($text)) === $text;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!function_exists('ends_with')) {
|
2017-12-16 22:51:36 +00:00
|
|
|
function ends_with(string $string, string $text): bool
|
|
|
|
{
|
2017-12-16 08:19:56 +00:00
|
|
|
return substr($string, 0 - strlen($text)) === $text;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-14 01:39:02 +00:00
|
|
|
function json_encode_m($obj): string
|
|
|
|
{
|
|
|
|
if (!headers_sent()) {
|
|
|
|
header('Content-Type: application/json; charset=utf-8');
|
|
|
|
}
|
|
|
|
|
|
|
|
return json_encode($obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
function set_cookie_m(string $name, string $value, int $expires): void
|
|
|
|
{
|
|
|
|
setcookie(
|
|
|
|
"msz_{$name}",
|
|
|
|
$value,
|
|
|
|
time() + $expires,
|
|
|
|
'/',
|
|
|
|
'',
|
|
|
|
!empty($_SERVER['HTTPS']),
|
|
|
|
true
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2018-01-16 07:26:29 +00:00
|
|
|
function password_entropy(string $password): int
|
|
|
|
{
|
|
|
|
return count(count_chars(utf8_decode($password), 1)) * log(256, 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
function check_mx_record(string $email): bool
|
|
|
|
{
|
|
|
|
$domain = substr(strstr($email, '@'), 1);
|
|
|
|
return checkdnsrr($domain, 'MX') || checkdnsrr($domain, 'A');
|
|
|
|
}
|
|
|
|
|
2017-12-16 22:51:36 +00:00
|
|
|
function dechex_pad(int $value, int $padding = 2): string
|
|
|
|
{
|
2017-12-16 08:19:56 +00:00
|
|
|
return str_pad(dechex($value), $padding, '0', STR_PAD_LEFT);
|
|
|
|
}
|
2017-12-16 19:17:29 +00:00
|
|
|
|
2017-12-16 22:51:36 +00:00
|
|
|
function array_rand_value(array $array, $fallback = null)
|
|
|
|
{
|
|
|
|
if (!$array) {
|
2017-12-16 19:17:29 +00:00
|
|
|
return $fallback;
|
2017-12-16 22:51:36 +00:00
|
|
|
}
|
2017-12-16 19:17:29 +00:00
|
|
|
|
|
|
|
return $array[array_rand($array)];
|
|
|
|
}
|
|
|
|
|
2017-12-16 22:51:36 +00:00
|
|
|
function has_flag(int $flags, int $flag): bool
|
|
|
|
{
|
2017-12-16 19:17:29 +00:00
|
|
|
return ($flags & $flag) > 0;
|
|
|
|
}
|
2017-12-16 21:44:45 +00:00
|
|
|
|
2018-01-03 01:12:28 +00:00
|
|
|
function byte_symbol($bytes, $decimal = false)
|
|
|
|
{
|
|
|
|
if ($bytes < 1) {
|
|
|
|
return "0 B";
|
|
|
|
}
|
|
|
|
|
|
|
|
$divider = $decimal ? 1000 : 1024;
|
|
|
|
$symbols = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'];
|
|
|
|
|
|
|
|
$exp = floor(log($bytes) / log($divider));
|
|
|
|
$bytes = $bytes / pow($divider, floor($exp));
|
|
|
|
$symbol = $symbols[$exp];
|
|
|
|
|
|
|
|
return sprintf("%.2f %s%sB", $bytes, $symbol, $symbol !== '' && !$decimal ? 'i' : '');
|
|
|
|
}
|
|
|
|
|
2018-03-12 20:48:09 +00:00
|
|
|
// this should be rewritten to only load the database once per Application instance.
|
|
|
|
// for now this will do since the only time this function is called is once during registration.
|
|
|
|
// also make sure an instance of Application with config exists before calling this!
|
2018-01-16 07:26:29 +00:00
|
|
|
function get_country_code(string $ipAddr, string $fallback = 'XX'): string
|
|
|
|
{
|
2018-03-12 20:48:09 +00:00
|
|
|
try {
|
|
|
|
$app = \Misuzu\Application::getInstance();
|
|
|
|
|
|
|
|
if (!$app->hasModule('config')) {
|
|
|
|
return $fallback;
|
|
|
|
}
|
|
|
|
|
|
|
|
$database_path = $app->config->get('GeoIP', 'database_path');
|
|
|
|
|
|
|
|
if ($database_path === null) {
|
|
|
|
return $fallback;
|
2018-01-16 07:26:29 +00:00
|
|
|
}
|
2018-03-12 20:48:09 +00:00
|
|
|
|
|
|
|
$geoip = new \GeoIp2\Database\Reader($database_path);
|
|
|
|
$record = $geoip->country($ipAddr);
|
|
|
|
|
|
|
|
return $record->country->isoCode;
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
// report error?
|
2018-01-16 07:26:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return $fallback;
|
|
|
|
}
|
|
|
|
|
2018-03-22 02:56:41 +00:00
|
|
|
function get_country_name(string $code): string
|
|
|
|
{
|
|
|
|
switch (strtolower($code)) {
|
|
|
|
case 'xx':
|
|
|
|
return 'Unknown';
|
|
|
|
|
|
|
|
case 'a1':
|
|
|
|
return 'Anonymous Proxy';
|
|
|
|
|
|
|
|
case 'a2':
|
|
|
|
return 'Satellite Provider';
|
|
|
|
|
|
|
|
default:
|
|
|
|
return locale_get_display_region("-{$code}", 'en');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-22 18:07:02 +00:00
|
|
|
// this is temporary, don't scream at me for using md5
|
|
|
|
// BIG TODO: make these functions not dependent on sessions so they can be used outside of those.
|
|
|
|
function tmp_csrf_verify(string $token, ?\Misuzu\Users\Session $session = null): bool
|
|
|
|
{
|
|
|
|
if ($session === null) {
|
|
|
|
$session = \Misuzu\Application::getInstance()->getSession();
|
|
|
|
}
|
|
|
|
|
|
|
|
return hash_equals(tmp_csrf_token($session), $token);
|
|
|
|
}
|
|
|
|
|
|
|
|
function tmp_csrf_token(?\Misuzu\Users\Session $session = null): string
|
|
|
|
{
|
|
|
|
if ($session === null) {
|
|
|
|
$session = \Misuzu\Application::getInstance()->getSession();
|
|
|
|
}
|
|
|
|
|
|
|
|
return md5($session->session_key);
|
|
|
|
}
|
|
|
|
|
2018-03-24 04:31:42 +00:00
|
|
|
function crop_image_centred_path(string $filename, int $target_width, int $target_height): \Imagick
|
|
|
|
{
|
|
|
|
return crop_image_centred(new \Imagick($filename), $target_width, $target_height);
|
|
|
|
}
|
|
|
|
|
|
|
|
function crop_image_centred(Imagick $image, int $target_width, int $target_height): Imagick
|
|
|
|
{
|
|
|
|
$image->setImageFormat($image->getNumberImages() > 1 ? 'gif' : 'png');
|
|
|
|
$image = $image->coalesceImages();
|
|
|
|
|
|
|
|
$width = $image->getImageWidth();
|
|
|
|
$height = $image->getImageHeight();
|
|
|
|
|
|
|
|
if ($width > $height) {
|
|
|
|
$resize_width = $width * $target_height / $height;
|
|
|
|
$resize_height = $target_height;
|
|
|
|
} else {
|
|
|
|
$resize_width = $target_width;
|
|
|
|
$resize_height = $height * $target_width / $width;
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
|
|
|
$image->resizeImage(
|
|
|
|
$resize_width,
|
|
|
|
$resize_height,
|
|
|
|
Imagick::FILTER_LANCZOS,
|
|
|
|
0.9
|
|
|
|
);
|
|
|
|
|
|
|
|
$image->cropImage(
|
|
|
|
$target_width,
|
|
|
|
$target_height,
|
|
|
|
($resize_width - $target_width) / 2,
|
|
|
|
($resize_height - $target_height) / 2
|
|
|
|
);
|
|
|
|
|
|
|
|
$image->setImagePage(
|
|
|
|
$target_width,
|
|
|
|
$target_height,
|
|
|
|
0,
|
|
|
|
0
|
|
|
|
);
|
|
|
|
} while ($image->nextImage());
|
|
|
|
|
|
|
|
return $image->deconstructImages();
|
|
|
|
}
|
|
|
|
|
2018-03-27 03:15:03 +00:00
|
|
|
function create_pagination($paginator)
|
|
|
|
{
|
2018-03-28 00:35:37 +00:00
|
|
|
return \Illuminate\Pagination\UrlWindow::make($paginator);
|
2018-03-27 03:15:03 +00:00
|
|
|
}
|
|
|
|
|
2018-03-31 22:28:32 +00:00
|
|
|
function running_on_windows(): bool
|
2017-12-16 22:51:36 +00:00
|
|
|
{
|
2018-03-31 22:28:32 +00:00
|
|
|
return starts_with(strtolower(PHP_OS), 'win');
|
2017-12-16 21:44:45 +00:00
|
|
|
}
|
2018-04-14 02:58:53 +00:00
|
|
|
|
|
|
|
function first_paragraph(string $text, string $delimiter = "\n"): string
|
|
|
|
{
|
|
|
|
$index = mb_strpos($text, $delimiter);
|
|
|
|
return $index === false ? $text : mb_substr($text, 0, $index);
|
|
|
|
}
|