2019-10-29 14:57:13 +01:00
< ? php
namespace controllers\internals ;
2019-10-29 18:36:25 +01:00
class Console extends \descartes\InternalController
2019-10-29 14:57:13 +01:00
{
/**
* Cette fonction retourne l ' aide de la console
*/
public function help ()
{
//On définit les commandes disponibles
$commands = array (
'sendScheduled' => array (
'description' => 'Cette commande permet d\'envoyer les SMS programmés qui doivent l\'êtres.' ,
'requireds' => array (),
'optionals' => array (),
),
'parseReceivedSMS' => array (
'description' => 'Cette commande permet d\'enregistrer un SMS, et de l\'analyser pour voir s\'il contient une commande. Pour cela, il analyse le dossier PWD_RECEIVEDS' ,
'requireds' => array (
),
'optionals' => array (),
),
'sendTransfers' => array (
'description' => 'Cette commande permet d\'envoyer par mails les sms à transférés.' ,
'requireds' => [],
'optionals' => [],
),
);
$message = " Vous êtes ici dans l'aide de la console. \n " ;
$message .= " Voici la liste des commandes disponibles : \n " ;
//On écrit les texte pour la liste des commandes dispos
2019-10-29 18:36:25 +01:00
foreach ( $commands as $name => $value ) {
2019-10-29 14:57:13 +01:00
$requireds = isset ( $value [ 'requireds' ]) ? $value [ 'requireds' ] : array ();
$optionals = isset ( $value [ 'optionals' ]) ? $value [ 'optionals' ] : array ();
$message .= ' ' . $name . ' : ' . $value [ 'description' ] . " \n " ;
$message .= " Arguments obligatoires : \n " ;
2019-10-29 18:36:25 +01:00
if ( ! count ( $requireds )) {
2019-10-29 14:57:13 +01:00
$message .= " Pas d'argument \n " ;
2019-10-29 18:36:25 +01:00
} else {
foreach ( $requireds as $argument => $desc ) {
2019-10-29 14:57:13 +01:00
$message .= ' - ' . $argument . ' : ' . $desc . " \n " ;
}
}
$message .= " Arguments optionnels : \n " ;
2019-10-29 18:36:25 +01:00
if ( ! count ( $optionals )) {
2019-10-29 14:57:13 +01:00
$message .= " Pas d'argument \n " ;
2019-10-29 18:36:25 +01:00
} else {
foreach ( $optionals as $argument => $desc ) {
2019-10-29 14:57:13 +01:00
$message .= ' - ' . $argument . ' : ' . $desc . " \n " ;
}
}
}
echo $message ;
}
/**
* Cette fonction envoie tous les SMS programmés qui doivent l ' être
*/
public function sendScheduled ()
{
//On créé l'objet de base de données
global $db ;
2019-10-29 18:36:25 +01:00
for ( $i = 0 ; $i < 30 ; $i ++ ) {
2019-10-29 14:57:13 +01:00
$now = new \DateTime ();
$now = $now -> format ( 'Y-m-d H:i:s' );
echo " Début de l'envoi des SMS programmés \n " ;
$scheduleds = $db -> getScheduledNotInProgressBefore ( $now );
$ids_scheduleds = array ();
//On passe en cours de progression tous les SMS
2019-10-29 18:36:25 +01:00
foreach ( $scheduleds as $scheduled ) {
2019-10-29 14:57:13 +01:00
$ids_scheduleds [] = $scheduled [ 'id' ];
}
echo count ( $ids_scheduleds ) . " SMS à envoyer ont été trouvés et ajoutés à la liste des SMS en cours d'envoi. \n " ;
$db -> updateProgressScheduledIn ( $ids_scheduleds , true );
//Pour chaque SMS à envoyer
2019-10-29 18:36:25 +01:00
foreach ( $scheduleds as $scheduled ) {
2019-10-29 14:57:13 +01:00
$id_scheduled = $scheduled [ 'id' ];
$text_sms = escapeshellarg ( $scheduled [ 'content' ]);
$flash = $scheduled [ 'flash' ];
//On initialise les numéros auxquelles envoyer le SMS
$numbers = array ();
//On récupère les numéros pour le SMS et on les ajoute
$target_numbers = $db -> getNumbersForScheduled ( $id_scheduled );
2019-10-29 18:36:25 +01:00
foreach ( $target_numbers as $target_number ) {
2019-10-29 14:57:13 +01:00
$numbers [] = $target_number [ 'number' ];
}
//On récupère les contacts, et on ajoute les numéros
$contacts = $db -> getContactForScheduled ( $id_scheduled );
2019-10-29 18:36:25 +01:00
foreach ( $contacts as $contact ) {
2019-10-29 14:57:13 +01:00
$numbers [] = $contact [ 'number' ];
}
//On récupère les groupes
$groupes = $db -> getGroupeForScheduled ( $id_scheduled );
2019-10-29 18:36:25 +01:00
foreach ( $groupes as $groupe ) {
2019-10-29 14:57:13 +01:00
//On récupère les contacts du groupe et on les ajoute aux numéros
$contacts = $db -> getContactForGroupe ( $groupe [ 'id' ]);
2019-10-29 18:36:25 +01:00
foreach ( $contacts as $contact ) {
2019-10-29 14:57:13 +01:00
$numbers [] = $contact [ 'number' ];
}
}
$smsStops = $db -> getFromTableWhere ( 'smsstop' );
2019-10-29 18:36:25 +01:00
foreach ( $numbers as $number ) {
2019-10-29 14:57:13 +01:00
//Si les SMS STOP sont activés, on passe au numéro suivant si le numéro actuelle fait parti des SMS STOP
2019-10-29 18:36:25 +01:00
if ( RASPISMS_SETTINGS_SMSSTOPS ) {
foreach ( $smsStops as $smsStop ) {
if ( ! ( $number == $smsStop [ 'number' ])) {
2019-10-29 14:57:13 +01:00
continue ;
}
echo " Un SMS destiné au " . $number . " a été bloqué par SMS STOP \n " ;
continue ( 2 ); //On passe au numéro suivant !
}
}
echo " Envoi d'un SMS au " . $number . " \n " ;
//On ajoute le SMS aux SMS envoyés
//Pour plus de précision, on remet la date à jour en réinstanciant l'objet \DateTime (et on reformatte la date, bien entendu)
$now = new \DateTime ();
$now = $now -> format ( 'Y-m-d H:i:s' );
//On peut maintenant ajouter le SMS
2019-10-29 18:36:25 +01:00
if ( ! $db -> insertIntoTable ( 'sendeds' , [ 'at' => $now , 'target' => $number , 'content' => $scheduled [ 'content' ], 'before_delivered' => ceil ( mb_strlen ( $scheduled [ 'content' ]) / 160 )])) {
2019-10-29 14:57:13 +01:00
echo 'Impossible d\'inserer le sms pour le numero ' . $number . " \n " ;
}
$id_sended = $db -> lastId ();
//Commande qui envoie le SMS
$commande_send_sms = 'gammu-smsd-inject TEXT ' . escapeshellarg ( $number ) . ' -report -len ' . mb_strlen ( $text_sms ) . ' -text ' . $text_sms ;
2019-10-29 18:36:25 +01:00
if ( RASPISMS_SETTINGS_SMS_FLASH && $flash ) {
2019-10-29 14:57:13 +01:00
$commande_send_sms .= ' -flash' ;
}
//Commande qui s'assure de passer le SMS dans ceux envoyés, et de lui donner le bon statut
//On va liée les deux commandes pour envoyer le SMS puis le passer en echec
$commande = '(' . $commande_send_sms . ') >/dev/null 2>/dev/null &' ;
exec ( $commande ); //On execute la commande d'envoie d'un SMS
}
}
echo " Tous les SMS sont en cours d'envoi. \n " ;
2019-10-29 18:36:25 +01:00
//Tous les SMS ont été envoyés.
2019-10-29 14:57:13 +01:00
$db -> deleteScheduledIn ( $ids_scheduleds );
//On dors 2 secondes
sleep ( 2 );
}
}
/**
* Cette fonction reçoit un SMS , et l ' enregistre , en essayant dde trouver une commande au passage .
*/
public function parseReceivedSMS ()
{
//On créer l'objet de base de données
global $db ;
2019-10-29 18:36:25 +01:00
for ( $i = 0 ; $i < 30 ; $i ++ ) {
foreach ( scandir ( PWD_RECEIVEDS ) as $dir ) {
2019-10-29 14:57:13 +01:00
//Si le fichier est un fichier système, on passe à l'itération suivante
2019-10-29 18:36:25 +01:00
if ( $dir == '.' || $dir == '..' || $dir == '.tokeep' ) {
2019-10-29 14:57:13 +01:00
continue ;
2019-10-29 18:36:25 +01:00
}
2019-10-29 14:57:13 +01:00
echo " Analyse du SMS " . $dir . " \n " ;
//On récupère la date du SMS à la seconde près grâce au nom du fichier (Cf. parseSMS.sh)
//Il faut mettre la date au format Y-m-d H:i:s
$date = substr ( $dir , 0 , 4 ) . '-' . substr ( $dir , 4 , 2 ) . '-' . substr ( $dir , 6 , 2 ) . ' ' . substr ( $dir , 8 , 2 ) . ':' . substr ( $dir , 10 , 2 ) . ':' . substr ( $dir , 12 , 2 );
//On récupère le fichier, et on récupère la chaine jusqu'au premier ':' pour le numéro de téléphone source, et la fin pour le message
$content_file = file_get_contents ( PWD_RECEIVEDS . $dir );
//Si on peux pas ouvrir le fichier, on quitte en logant une erreur
2019-10-29 18:36:25 +01:00
if ( $content_file == false ) {
2019-10-29 14:57:13 +01:00
$this -> wlog ( 'Unable to read file "' . $dir );
die ( 4 );
}
//On supprime le fichier. Si on n'y arrive pas, alors on log
2019-10-29 18:36:25 +01:00
if ( ! unlink ( PWD_RECEIVEDS . $dir )) {
2019-10-29 14:57:13 +01:00
$this -> wlog ( 'Unable to delete file "' . $dir );
die ( 8 );
}
$content_file = explode ( ':' , $content_file , 2 );
//Si on a pas passé de numéro ou de message, alors on lève une erreur
2019-10-29 18:36:25 +01:00
if ( ! isset ( $content_file [ 0 ], $content_file [ 1 ])) {
2019-10-29 14:57:13 +01:00
$this -> wlog ( 'Missing params in file "' . $dir );
die ( 5 );
}
$number = $content_file [ 0 ];
$number = internalTool :: parse_phone ( $number );
$text = $content_file [ 1 ];
//On gère les SMS STOP
2019-10-29 18:36:25 +01:00
if ( trim ( $text ) == 'STOP' ) {
2019-10-29 14:57:13 +01:00
echo 'STOP SMS detected ' . $number . " \n " ;
$this -> wlog ( 'STOP SMS detected ' . $number );
$db -> insertIntoTable ( 'smsstop' , [ 'number' => $number ]);
continue ;
}
//On gère les accusés de reception
2019-10-29 18:36:25 +01:00
if ( trim ( $text ) == 'Delivered' || trim ( $text ) == 'Failed' ) {
2019-10-29 14:57:13 +01:00
echo 'Delivered or Failed SMS for ' . $number . " \n " ;
$this -> wlog ( 'Delivered or Failed SMS for ' . $number );
//On récupère les SMS pas encore validé, uniquement sur les dernières 12h
$now = new \DateTime ();
$interval = new \DateInterval ( 'PT12H' );
$sinceDate = $now -> sub ( $interval ) -> format ( 'Y-m-d H:i:s' );
2019-10-29 18:36:25 +01:00
if ( ! $sendeds = $db -> getFromTableWhere ( 'sendeds' , [ 'target' => $number , 'delivered' => false , 'failed' => false , '>at' => $sinceDate ], 'at' , false , 1 )) {
2019-10-29 14:57:13 +01:00
continue ;
}
$sended = $sendeds [ 0 ];
//On gère les echecs
2019-10-29 18:36:25 +01:00
if ( trim ( $text ) == 'Failed' ) {
2019-10-29 14:57:13 +01:00
$db -> updateTableWhere ( 'sendeds' , [ 'before_delivered' => 0 , 'failed' => true ], [ 'id' => $sended [ 'id' ]]);
echo " Sended SMS id " . $sended [ 'id' ] . " pass to failed status \n " ;
continue ;
}
//On gère le cas des messages de plus de 160 caractères, lesquels impliquent plusieurs accusés
2019-10-29 18:36:25 +01:00
if ( $sended [ 'before_delivered' ] > 1 ) {
2019-10-29 14:57:13 +01:00
$db -> updateTableWhere ( 'sendeds' , [ 'before_delivered' => $sended [ 'before_delivered' ] - 1 ], [ 'id' => $sended [ 'id' ]]);
echo " Sended SMS id " . $sended [ 'id' ] . " before_delivered decrement \n " ;
continue ;
}
//Si tout est bon, que nous avons assez d'accusés, nous validons !
$db -> updateTableWhere ( 'sendeds' , [ 'before_delivered' => 0 , 'delivered' => true ], [ 'id' => $sended [ 'id' ]]);
echo " Sended SMS id " . $sended [ 'id' ] . " to delivered status \n " ;
continue ;
}
2019-10-29 18:36:25 +01:00
if ( ! $number ) {
2019-10-29 14:57:13 +01:00
$this -> wlog ( 'Invalid phone number in file "' . $dir );
die ( 6 );
}
//On va vérifier si on a reçu une commande, et des identifiants
$flags = internalTool :: parse_for_flag ( $text );
//On créer le tableau qui permettra de stocker les commandes trouvées
$found_commands = array ();
//Si on reçu des identifiants
2019-10-29 18:36:25 +01:00
if ( array_key_exists ( 'LOGIN' , $flags ) && array_key_exists ( 'PASSWORD' , $flags )) {
2019-10-29 14:57:13 +01:00
//Si on a bien un utilisateur avec les identifiants reçus
$user = $db -> getUserFromEmail ( $flags [ 'LOGIN' ]);
$this -> wlog ( 'We found ' . count ( $user ) . ' users' );
2019-10-29 18:36:25 +01:00
if ( $user && $user [ 'password' ] == sha1 ( $flags [ 'PASSWORD' ])) {
2019-10-29 14:57:13 +01:00
$this -> wlog ( 'Password is valid' );
//On va passer en revue toutes les commandes, pour voir si on en trouve dans ce message
$commands = $db -> getFromTableWhere ( 'commands' );
$this -> wlog ( 'We found ' . count ( $commands ) . ' commands' );
2019-10-29 18:36:25 +01:00
foreach ( $commands as $command ) {
2019-10-29 14:57:13 +01:00
$command_name = mb_strtoupper ( $command [ 'name' ]);
2019-10-29 18:36:25 +01:00
if ( array_key_exists ( $command_name , $flags )) {
2019-10-29 14:57:13 +01:00
$this -> wlog ( 'We found command ' . $command_name );
//Si la commande ne nécessite pas d'être admin, ou si on est admin
2019-10-29 18:36:25 +01:00
if ( ! $command [ 'admin' ] || $user [ 'admin' ]) {
2019-10-29 14:57:13 +01:00
$this -> wlog ( 'And the count is ok' );
$found_commands [ $command_name ] = PWD_SCRIPTS . $command [ 'script' ] . escapeshellcmd ( $flags [ $command_name ]);
}
}
}
}
}
//On va supprimer le mot de passe du SMS pour pouvoir l'enregistrer sans danger
2019-10-29 18:36:25 +01:00
if ( isset ( $flags [ 'PASSWORD' ])) {
2019-10-29 14:57:13 +01:00
$text = str_replace ( $flags [ 'PASSWORD' ], '*****' , $text );
}
//On map les données et on créer le SMS reçu
$send_by = $number ;
$content = $text ;
$is_command = count ( $found_commands );
2019-10-29 18:36:25 +01:00
if ( ! $db -> insertIntoTable ( 'receiveds' , [ 'at' => $date , 'send_by' => $send_by , 'content' => $content , 'is_command' => $is_command ])) {
2019-10-29 14:57:13 +01:00
echo " Erreur lors de l'enregistrement du SMS \n " ;
$this -> wlog ( 'Unable to process the SMS in file "' . $dir );
die ( 7 );
}
//On insert le SMS dans le tableau des sms à envoyer par mail
$db -> insertIntoTable ( 'transfers' , [ 'id_received' => $db -> lastId (), 'progress' => false ]);
//Chaque commande sera executée.
2019-10-29 18:36:25 +01:00
foreach ( $found_commands as $command_name => $command ) {
2019-10-29 14:57:13 +01:00
echo 'Execution de la commande : ' . $command_name . ' :: ' . $command . " \n " ;
exec ( $command );
}
}
//On attend 2 secondes
sleep ( 2 );
}
}
/**
* Cette fonction permet d ' envoyer par mail les sms à transférer
*/
2019-10-29 18:36:25 +01:00
public function sendTransfers ()
2019-10-29 14:57:13 +01:00
{
2019-10-29 18:36:25 +01:00
if ( ! RASPISMS_SETTINGS_TRANSFER ) {
2019-10-29 14:57:13 +01:00
echo " Le transfer de SMS est désactivé ! \n " ;
return false ;
}
global $db ;
$transfers = $db -> getFromTableWhere ( 'transfers' , [ 'progress' => false ]);
$ids_transfers = [];
$ids_receiveds = [];
2019-10-29 18:36:25 +01:00
foreach ( $transfers as $transfer ) {
2019-10-29 14:57:13 +01:00
$ids_transfers [] = $transfer [ 'id' ];
$ids_receiveds [] = $transfer [ 'id_received' ];
}
$db -> updateProgressTransfersIn ( $ids_transfers , true );
$receiveds = $db -> getReceivedIn ( $ids_receiveds );
$users = $db -> getFromTableWhere ( 'users' , [ 'transfer' => true ]);
2019-10-29 18:36:25 +01:00
foreach ( $users as $user ) {
foreach ( $receiveds as $received ) {
2019-10-29 14:57:13 +01:00
echo " Transfer d'un SMS du " . $received [ 'send_by' ] . " à l'email " . $user [ 'email' ];
$to = $user [ 'email' ];
$subject = '[RaspiSMS] - Transfert d\'un SMS du ' . $received [ 'send_by' ];
$message = " Le numéro " . $received [ 'send_by' ] . " vous a envoyé un SMS : \n " . $received [ 'content' ];
$ok = mail ( $to , $subject , $message );
echo " ... " . ( $ok ? 'OK' : 'KO' ) . " \n " ;
}
}
$db -> deleteTransfersIn ( $ids_transfers );
}
}