raspisms/controllers/internals/Tool.php

375 lines
12 KiB
PHP
Raw Normal View History

2019-10-29 14:57:13 +01:00
<?php
/*
2019-11-10 17:48:54 +01:00
* This file is part of RaspiSMS.
*
2019-11-10 17:48:54 +01:00
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
2019-11-10 17:48:54 +01:00
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\internals;
2019-10-29 14:57:13 +01:00
/**
* Some tools frequently used.
2020-01-17 18:19:25 +01:00
* Not a standard controller as it's not linked to a model in any way.
*/
2019-10-29 18:36:25 +01:00
class Tool extends \descartes\InternalController
{
/**
* Cette fonction parse un numéro pour le retourner sans espaces, etc.
*
2019-10-29 18:36:25 +01:00
* @param string $number : Le numéro de téléphone à parser
*
2019-10-29 18:36:25 +01:00
* @return mixed : Si le numéro est bien un numéro de téléphone, on retourne le numéro parsé. Sinon, on retourne faux
*/
public static function parse_phone($number)
{
2019-11-30 05:31:20 +01:00
try
{
2019-11-30 05:31:20 +01:00
$phone_number_util = \libphonenumber\PhoneNumberUtil::getInstance();
$phone_number_o = $phone_number_util->parse($number, null);
$valid = $phone_number_util->isValidNumber($phone_number_o);
if (!$valid)
{
return false;
}
2019-11-30 05:31:20 +01:00
return $phone_number_util->format($phone_number_o, \libphonenumber\PhoneNumberFormat::E164);
}
2020-01-17 18:19:25 +01:00
catch (\Exception $e)
2019-11-30 05:31:20 +01:00
{
return false;
}
2019-10-29 18:36:25 +01:00
}
2019-10-29 14:57:13 +01:00
2019-10-29 18:36:25 +01:00
/**
* Cette fonction parse un numéro pour le retourner avec des espaces, etc.
*
2019-10-29 18:36:25 +01:00
* @param string $number : Le numéro de téléphone à parser
*
2019-10-29 18:36:25 +01:00
* @return mixed : Si le numéro est bien un numéro de téléphone, on retourne le numéro parsé. Sinon, on retourne faux
*/
2019-11-10 01:17:28 +01:00
public static function phone_format($number)
2019-10-29 18:36:25 +01:00
{
2019-11-30 05:31:20 +01:00
try
{
$phone_number_util = \libphonenumber\PhoneNumberUtil::getInstance();
$phone_number_o = $phone_number_util->parse($number, null);
2019-11-10 17:36:42 +01:00
2019-11-30 05:31:20 +01:00
return $phone_number_util->format($phone_number_o, \libphonenumber\PhoneNumberFormat::INTERNATIONAL);
}
2020-01-17 18:19:25 +01:00
catch (\Exception $e)
2019-11-30 05:31:20 +01:00
{
return false;
2019-11-30 05:31:20 +01:00
}
2019-10-29 18:36:25 +01:00
}
2019-10-29 14:57:13 +01:00
/**
2020-01-17 18:19:25 +01:00
* Format a number and make a link to a discussion with this number.
*
* @param string $number : Number to format and make a link for
2020-01-17 18:19:25 +01:00
*
* @return string : Link to the number
*/
2020-01-17 18:19:25 +01:00
public static function phone_link($number)
{
2020-01-17 18:19:25 +01:00
$number_format = self::phone_format($number);
$url = \descartes\Router::url('Discussion', 'show', ['number' => $number]);
2020-01-17 18:19:25 +01:00
return '<a href="' . self::s($url, false, true, false) . '">' . self::s($number_format, false, true, false) . '</a>';
}
2019-10-29 18:36:25 +01:00
/**
* Cette fonction fait la correspondance entre un type d'evenement et une icone font awesome.
*
2019-10-29 18:36:25 +01:00
* @param string $type : Le type de l'évenement à analyser
*
2019-10-29 18:36:25 +01:00
* @return string : Le nom de l'icone à afficher (ex : fa-user)
*/
public static function event_type_to_icon($type)
{
switch ($type) {
case 'USER_ADD':
$logo = 'fa-user';
2019-10-29 18:36:25 +01:00
break;
2021-01-14 03:32:17 +01:00
2019-10-29 18:36:25 +01:00
case 'CONTACT_ADD':
$logo = 'fa-user';
2019-10-29 18:36:25 +01:00
break;
2021-01-14 03:32:17 +01:00
2019-10-29 18:36:25 +01:00
case 'GROUP_ADD':
$logo = 'fa-group';
2020-09-27 02:01:29 +02:00
break;
2021-01-14 03:32:17 +01:00
2020-09-27 02:01:29 +02:00
case 'CONDITIONAL_GROUP_ADD':
$logo = 'fa-bullseye';
2019-10-29 18:36:25 +01:00
break;
2021-01-14 03:32:17 +01:00
2019-10-29 18:36:25 +01:00
case 'SCHEDULED_ADD':
$logo = 'fa-calendar';
2019-10-29 18:36:25 +01:00
break;
2021-01-14 03:32:17 +01:00
2019-10-29 18:36:25 +01:00
case 'COMMAND_ADD':
$logo = 'fa-terminal';
2019-10-29 18:36:25 +01:00
break;
2021-01-14 03:32:17 +01:00
2021-06-14 20:21:06 +02:00
case 'QUOTA_LIMIT_CLOSE':
$logo = 'fa-exclamation';
break;
case 'QUOTA_LIMIT_REACHED':
$logo = 'fa-exclamation-triangle';
break;
case 'QUOTA_RENEWAL':
$logo = 'fa-retweet';
break;
case 'QUOTA_CONSUME':
$logo = 'fa-euro';
break;
2019-10-29 18:36:25 +01:00
default:
$logo = 'fa-question';
}
2019-10-29 14:57:13 +01:00
2019-10-29 18:36:25 +01:00
return $logo;
}
2019-10-29 14:57:13 +01:00
2019-10-29 18:36:25 +01:00
/**
* Cette fonction vérifie une date.
*
* @param string $date : La date a valider
2019-10-29 18:36:25 +01:00
* @param string $format : Le format de la date
*
* @return bool : Vrai si la date et valide, faux sinon
2019-10-29 18:36:25 +01:00
*/
public static function validate_date($date, $format)
{
$objectDate = \DateTime::createFromFormat($format, $date);
return $objectDate && $objectDate->format($format) === $date;
2019-10-29 18:36:25 +01:00
}
2021-06-12 23:23:15 +02:00
/**
* Check if a sting represent a valid PHP period for creating an interval.
*
* @param string $period : Period string to check
*
* @return bool : True if valid period, false else
*/
public static function validate_period($period)
{
try
{
$interval = new \DateInterval($period);
}
catch (\Throwable $e)
{
return false;
}
return true;
}
2019-10-29 14:57:13 +01:00
2019-10-29 18:36:25 +01:00
/**
* Cette fonction retourne un mot de passe généré aléatoirement.
*
2019-10-29 18:36:25 +01:00
* @param int $length : Taille du mot de passe à générer
*
2019-10-29 18:36:25 +01:00
* @return string : Le mot de passe aléatoire
*/
public static function generate_password($length)
{
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-@()?.:!%*$&/';
$password = '';
$chars_length = mb_strlen($chars) - 1;
$i = 0;
while ($i < $length)
{
++$i;
2019-10-29 18:36:25 +01:00
$password .= $chars[rand(0, $chars_length)];
}
2019-10-29 18:36:25 +01:00
return $password;
}
/**
* Cette fonction vérifie si un utilisateur et connecté, et si il ne l'est pas, redirige sur la page de connexion.
2019-10-29 18:36:25 +01:00
*/
public static function verifyconnect()
2019-10-29 18:36:25 +01:00
{
if (!isset($_SESSION['connect']) || !$_SESSION['connect'])
{
2019-10-29 18:36:25 +01:00
header('Location: /');
2021-01-14 03:32:17 +01:00
exit();
2019-10-29 18:36:25 +01:00
}
2019-10-29 14:57:13 +01:00
}
2019-11-11 00:22:40 +01:00
/**
* Check if the user connected.
*
* @return bool : True if connected, False else
*/
public static function is_connected()
{
return (bool) ($_SESSION['connect'] ?? false);
}
2019-10-29 14:57:13 +01:00
/**
* Check if the user is admin.
*
* @return bool : True if admin, False else
2019-10-29 18:36:25 +01:00
*/
public static function is_admin()
{
return (bool) ($_SESSION['user']['admin'] ?? false);
2019-10-29 14:57:13 +01:00
}
2019-11-30 05:31:20 +01:00
/**
2020-01-17 18:19:25 +01:00
* Allow to read an uploaded file.
*
2019-11-30 05:31:20 +01:00
* @param array $file : The array extracted from $_FILES['file']
2020-01-17 18:19:25 +01:00
*
* @return array : ['success' => bool, 'content' => file handler | error message, 'error_code' => $file['error'], 'mime_type' => server side calculated mimetype, 'extension' => original extension, 'tmp_name' => name of the tmp_file]
2019-11-30 05:31:20 +01:00
*/
public static function read_uploaded_file(array $file)
{
$result = [
'success' => false,
'content' => 'Une erreur inconnue est survenue.',
'error_code' => $file['error'] ?? 99,
'mime_type' => null,
'extension' => null,
'tmp_name' => null,
2019-11-30 05:31:20 +01:00
];
2020-01-17 18:19:25 +01:00
if (UPLOAD_ERR_OK !== $file['error'])
2019-11-30 05:31:20 +01:00
{
switch ($file['error'])
{
2020-01-17 18:19:25 +01:00
case UPLOAD_ERR_INI_SIZE:
$result['content'] = 'Impossible de télécharger le fichier car il dépasse les ' . ini_get('upload_max_filesize') / (1000 * 1000) . ' Mégaoctets.';
2020-01-17 18:19:25 +01:00
2019-11-30 05:31:20 +01:00
break;
2021-01-14 03:32:17 +01:00
2020-01-17 18:19:25 +01:00
case UPLOAD_ERR_FORM_SIZE:
2019-11-30 05:31:20 +01:00
$result['content'] = 'Le fichier dépasse la limite de taille.';
2020-01-17 18:19:25 +01:00
2019-11-30 05:31:20 +01:00
break;
2021-01-14 03:32:17 +01:00
2020-01-17 18:19:25 +01:00
case UPLOAD_ERR_PARTIAL:
2019-11-30 05:31:20 +01:00
$result['content'] = 'L\'envoi du fichier a été interrompu.';
2020-01-17 18:19:25 +01:00
break;
2021-01-14 03:32:17 +01:00
2020-01-17 18:19:25 +01:00
case UPLOAD_ERR_NO_FILE:
2019-11-30 05:31:20 +01:00
$result['content'] = 'Aucun fichier n\'a été envoyé.';
2020-01-17 18:19:25 +01:00
2019-11-30 05:31:20 +01:00
break;
2021-01-14 03:32:17 +01:00
2020-01-17 18:19:25 +01:00
case UPLOAD_ERR_NO_TMP_DIR:
2019-11-30 05:31:20 +01:00
$result['content'] = 'Le serveur ne dispose pas de fichier temporaire permettant l\'envoi de fichiers.';
break;
2021-01-14 03:32:17 +01:00
2020-01-17 18:19:25 +01:00
case UPLOAD_ERR_CANT_WRITE:
$result['content'] = 'Impossible d\'envoyer le fichier car il n\'y a plus de place sur le serveur.';
2019-11-30 05:31:20 +01:00
2020-01-17 18:19:25 +01:00
break;
2021-01-14 03:32:17 +01:00
2020-01-17 18:19:25 +01:00
case UPLOAD_ERR_EXTENSION:
2019-11-30 05:31:20 +01:00
$result['content'] = 'Le serveur a interrompu l\'envoi du fichier.';
2020-01-17 18:19:25 +01:00
2019-11-30 05:31:20 +01:00
break;
}
2020-01-17 18:19:25 +01:00
return $result;
2019-11-30 05:31:20 +01:00
}
$tmp_filename = $file['tmp_name'] ?? false;
if (!$tmp_filename || !is_readable($tmp_filename))
{
return $result;
}
$result['tmp_name'] = $tmp_filename;
$result['extension'] = pathinfo($file['name'], PATHINFO_EXTENSION);
$result['mime_type'] = mime_content_type($tmp_filename);
2019-11-30 05:31:20 +01:00
$file_handler = fopen($tmp_filename, 'r');
$result['success'] = true;
$result['content'] = $file_handler;
return $result;
}
2020-01-17 18:19:25 +01:00
2019-12-04 03:04:45 +01:00
/**
* Generate a highly random uuid based on timestamp and strong cryptographic random
2020-01-17 18:19:25 +01:00
*
* @return string
2019-12-04 03:04:45 +01:00
*/
public static function random_uuid()
2019-12-04 03:04:45 +01:00
{
$bytes = random_bytes(16);
return time() . '-' . bin2hex($bytes);
}
2019-12-04 03:04:45 +01:00
/**
* Create a user data public path
* @param int $id_user : The user id
*
* @return string : The created path
* @exception Raise exception on error
*/
public static function create_user_public_path (int $id_user)
{
$new_dir = PWD_DATA_PUBLIC . '/' . $id_user;
if (file_exists($new_dir))
2019-12-04 03:04:45 +01:00
{
return $new_dir;
2019-12-04 03:04:45 +01:00
}
clearstatcache();
if (!mkdir($new_dir))
2019-12-04 03:04:45 +01:00
{
throw new \Exception('Cannot create dir ' . $new_dir);
2019-12-04 03:04:45 +01:00
}
//We do chmod in two times because else umask fuck mkdir permissions
if (!chmod($new_dir, fileperms(PWD_DATA_PUBLIC) & 0777)) //Fileperms return garbage in addition to perms. Perms are only in weak bytes. We must use an octet notation with 0
2019-12-04 03:04:45 +01:00
{
throw new \Exception('Cannot give dir ' . $new_dir . ' rights : ' . decoct(fileperms(PWD_DATA_PUBLIC) & 0777)); //Show error in dec
}
if (posix_getuid() === 0 && !chown($new_dir, fileowner(PWD_DATA_PUBLIC))) //If we are root, try to give the file to a proper user
{
throw new \Exception('Cannot give dir ' . $new_dir . ' to user : ' . fileowner(PWD_DATA_PUBLIC));
2019-12-04 03:04:45 +01:00
}
if (posix_getuid() === 0 && !chgrp($new_dir, filegroup(PWD_DATA_PUBLIC))) //If we are root, try to give the file to a proper group
2019-12-04 03:04:45 +01:00
{
throw new \Exception('Cannot give dir ' . $new_dir . ' to group : ' . filegroup(PWD_DATA_PUBLIC));
2019-12-04 03:04:45 +01:00
}
return $new_dir;
}
2019-10-29 18:36:25 +01:00
}