/** * Cette fonction met à jour une liste de contacts * @param $csrf : Le jeton CSRF * @param array $_POST['contacts'] : Un tableau des contacts avec leur nouvelle valeurs * @return boolean; */ public function update($csrf) { //On vérifie que le jeton csrf est bon if (!internalTools::verifyCSRF($csrf)) { $_SESSION['errormessage'] = 'Jeton CSRF invalide !'; header('Location: ' . $this->generateUrl('contacts')); } global $db; $errors = array(); //On initialise le tableau qui contiendra les erreurs rencontrés //Pour chaque contact reçu, on boucle en récupérant son id (la clef), et le contact lui-même (la value) foreach ($_POST['contacts'] as $id => $contact) { if (!isset($contact['name']) || !isset($contact['phone']) || RASPISMS_SETTINGS_EXTENDED_CONTACTS_INFOS && !isset($contact['civility'])) { $errors[] = $id; continue; } $nom = $contact['name']; $phone = $contact['phone']; // on enregistre les infos si elles ont été saisies par l'utilisateur $civility = isset($contact['civility']) ? $contact['civility'] : null; $prenom = isset($contact['first_name']) ? $contact['first_name'] : null; $birthday = isset($contact['birthday']) ? $contact['birthday'] : null; $loveSituation = isset($contact['love_situation']) ? $contact['love_situation'] : null; $nomComplet = $prenom ? $prenom . ' ' . $nom : $nom; if (!($number = internalTools::parsePhone($contact['phone']))) { $errors[] = $id; continue; } $db->updateTableWhere('contacts', ['name' => $nomComplet, 'number' => $number], ['id' => $id]); // si l'option des infos contacts n'est pas activée, on sort de la boucle if (!RASPISMS_SETTINGS_EXTENDED_CONTACTS_INFOS) { continue; } if (empty($contact['contacts_infos_id'])) { if (!$db->insertIntoTable('contacts_infos', ['id_contact' => $id, 'civility' => $civility, 'first_name' => $prenom, 'last_name' => $nom, 'birthday' => $birthday, 'love_situation' => $loveSituation])) { $errors[] = $id; continue; } } elseif (!$db->updateTableWhere('contacts_infos', ['id_contact' => $id, 'civility' => $civility, 'first_name' => $prenom, 'last_name' => $nom, 'birthday' => $birthday, 'love_situation' => $loveSituation], ['id' => $contact['contacts_infos_id']])) { $errors[] = $id; continue; } } //Si on a eu des erreurs if (count($errors)) { $_SESSION['errormessage'] = 'Certains contacts n\'ont pas pu êtres mis à jour. Voici leurs identifiants : ' . implode(', ', $errors); return header('Location: ' . $this->generateUrl('contacts')); } $_SESSION['successmessage'] = 'Tous les contacts ont été modifiés avec succès.'; return header('Location: ' . $this->generateUrl('contacts')); }
/** * Cette fonction met à jour une liste de sms * @param $csrf : Le jeton CSRF * @param array $_POST['scheduleds'] : Un tableau contenant les sms avec leurs nouvelles valeurs */ public function update($csrf) { //On vérifie que le jeton csrf est bon if (!internalTools::verifyCSRF($csrf)) { $_SESSION['successmessage'] = 'Jeton CSRF invalide !'; header('Location: ' . $this->generateUrl('scheduleds')); return false; } global $db; $errors = false; //Pour chaque SMS programmé reçu, on boucle en récupérant son id (la clef), et sont contenu foreach ($_POST['scheduleds'] as $id_scheduled => $scheduled) { $date = $scheduled['date']; if (!internalTools::validateDate($date, 'Y-m-d H:i:s') && !internalTools::validateDate($date, 'Y-m-d H:i')) { $_SESSION['errormessage'] = 'La date renseignée pour le SMS numéro ' . $scheduled['id'] . ' est invalide.'; header('Location: ' . $this->generateUrl('scheduleds')); return false; } //Si la date fournie est passée, on la change pour dans 2 minutes $objectDate = DateTime::createFromFormat('Y-m-d H:i', $date); $db->updateTableWhere('scheduleds', ['content' => $scheduled['content'], 'at' => $date], ['id' => $id_scheduled]); $db->deleteScheduleds_numbersForScheduled($id_scheduled); //On supprime tous les numéros pour ce SMS $db->deleteScheduleds_contactsForScheduled($id_scheduled); //On supprime tous les contacts pour ce SMS $db->deleteScheduleds_GroupsForScheduled($id_scheduled); //On supprime tous les groupes pour ce SMS if (array_key_exists('numbers', $scheduled)) { foreach ($scheduled['numbers'] as $number) { if (!($number = internalTools::parsePhone($number))) { $errors = true; continue; } if (!$db->insertIntoTable('scheduleds_numbers', ['id_scheduled' => $id_scheduled, 'number' => $number])) { $errors = true; } } } if (array_key_exists('contacts', $scheduled)) { foreach ($scheduled['contacts'] as $id_contact) { if (!$db->insertIntoTable('scheduleds_contacts', ['id_scheduled' => $id_scheduled, 'id_contact' => $id_contact])) { $errors = true; } } } if (array_key_exists('groups', $scheduled)) { foreach ($scheduled['groups'] as $id_group) { if (!$db->insertIntoTable('scheduleds_groups', ['id_scheduled' => $id_scheduled, 'id_group' => $id_group])) { $errors = true; } } } } if ($errors) { $_SESSION['errormessage'] = 'Tous les SMS ont été modifiés mais certaines données incorrects ont été ignorées.'; header('Location: ' . $this->generateUrl('scheduleds')); return false; } else { $_SESSION['successmessage'] = 'Tous les SMS ont été modifiés avec succès.'; header('Location: ' . $this->generateUrl('scheduleds')); return true; } }
/** * Cette fonction reçoit un SMS, et l'enregistre, en essayant de trouver une commande au passage. */ public function parseReceivedSMS() { //On créer l'objet de base de données global $db; for ($i = 0; $i < 30; $i++) { foreach (scandir(PWD_RECEIVEDS) as $dir) { //Si le fichier est un fichier système, on passe à l'itération suivante if ($dir == '.' || $dir == '..') { continue; } 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 ne peux pas ouvrir le fichier, on quitte en logant une erreur if ($content_file == false) { $this->wlog('Unable to read file "' . $dir); die(4); } //On supprime le fichier. Si on n'y arrive pas, alors on log if (!unlink(PWD_RECEIVEDS . $dir)) { $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 if (!isset($content_file[0], $content_file[1])) { $this->wlog('Missing params in file "' . $dir); die(5); } $number = $content_file[0]; $number = internalTools::parsePhone($number); $text = $content_file[1]; //On gère les SMS STOP if (trim($text) == 'STOP') { echo 'STOP SMS detected ' . $number . "\n"; $this->wlog('STOP SMS detected ' . $number); $db->insertIntoTable('sms_stop', ['number' => $number]); continue; } //On gère les accusés de reception if (trim($text) == 'Delivered' || trim($text) == 'Failed') { 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'); if (!($sendeds = $db->getFromTableWhere('sendeds', ['target' => $number, 'delivered' => false, 'failed' => false, '>at' => $sinceDate], 'at', false, 1))) { continue; } $sended = $sendeds[0]; //On gère les echecs if (trim($text) == 'Failed') { $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 if ($sended['before_delivered'] > 1) { $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; } if (!$number) { $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 = internalTools::parseForFlag($text); //On créer le tableau qui permettra de stocker les commandes trouvées $found_commands = array(); //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'); foreach ($commands as $command) { $command_name = mb_strtoupper($command['name']); if (array_key_exists($command_name, $flags)) { $this->wlog('We found command ' . $command_name); if (!$command['anonymous']) { //Si on reçu des identifiants if (array_key_exists('LOGIN', $flags) && array_key_exists('PASSWORD', $flags)) { //Si on a bien un utilisateur avec les identifiants reçus $user = $db->getUserFromEmail($flags['LOGIN']); $this->wlog('We found ' . count($user) . ' users'); if ($user && $user['password'] == sha1($flags['PASSWORD'])) { $this->wlog('Password is valid'); //Si la commande ne nécessite pas d'être admin, ou si on est admin if (!$command['admin'] || $user['admin']) { $this->wlog('And the count is ok'); $found_commands[$command_name] = PWD_SCRIPTS . $command['script'] . escapeshellcmd($flags[$command_name]); } } } } else { $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 if (isset($flags['PASSWORD'])) { $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); if (!$db->insertIntoTable('receiveds', ['at' => $date, 'send_by' => $send_by, 'content' => $content, 'is_command' => $is_command])) { 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. foreach ($found_commands as $command_name => $command) { echo 'Execution de la commande : ' . $command_name . ' :: ' . $command . "\n"; exec($command); } } //On attend 2 secondes sleep(2); } }
/** * Cette fonction met à jour une liste de contacts * @param $csrf : Le jeton CSRF * @param array $_POST['contacts'] : Un tableau des contacts avec leur nouvelle valeurs * @return boolean; */ public function update($csrf) { //On vérifie que le jeton csrf est bon if (!internalTools::verifyCSRF($csrf)) { $_SESSION['errormessage'] = 'Jeton CSRF invalide !'; header('Location: ' . $this->generateUrl('contacts')); } global $db; $errors = array(); //On initialise le tableau qui contiendra les erreurs rencontrés //Pour chaque contact reçu, on boucle en récupérant son id (la clef), et le contact lui-même (la value) foreach ($_POST['contacts'] as $id => $contact) { if (!($number = internalTools::parsePhone($contact['phone']))) { $errors[] = $contact['id']; continue; } $db->updateTableWhere('contacts', ['name' => $contact['name'], 'number' => $number], ['id' => $id]); } //Si on a eu des erreurs if (count($errors)) { $_SESSION['errormessage'] = 'Certains contacts n\'ont pas pu êtres mis à jour. Voici leurs identifiants : ' . implode(', ', $errors); return header('Location: ' . $this->generateUrl('contacts')); } $_SESSION['successmessage'] = 'Tous les contacts ont été modifiés avec succès.'; return header('Location: ' . $this->generateUrl('contacts')); }