From 779edcd6dd2e4b898ebb3a56f80a556b918a9353 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Tue, 15 Feb 2022 13:30:19 +0100 Subject: [PATCH] update jirafeau --- src/Jirafeau/a.php | 414 ++++++++++++++++++++++++++++----------------- 1 file changed, 257 insertions(+), 157 deletions(-) diff --git a/src/Jirafeau/a.php b/src/Jirafeau/a.php index 83a47b1..aae06d3 100644 --- a/src/Jirafeau/a.php +++ b/src/Jirafeau/a.php @@ -20,10 +20,13 @@ require (JIRAFEAU_ROOT . 'lib/lang.php'); define ('VAR_TOKENS', $cfg ['var_root'].'tokens/'); define ('VAR_TRACKS', $cfg ['var_root'].'tracks/'); +define ('VAR_PERIOD', $cfg ['var_root'].'period/'); +define ('VAR_FAKE', $cfg ['var_root'].'fake/'); define ('TOKEN_USE_LIMIT', "-2 hours"); define ('TOKEN_LOGIN_LIMIT', "-15 minutes"); define ('TOKEN_LOGOUT_LIMIT', "-8 hours"); +define ('DEFAULT_PERIOD', "month"); define ('E_BAD_ARCHIVE_NAME', 'Bad archive name format'); define ('E_CREATE_ZIP', "Impossible de créer l'archive."); @@ -49,11 +52,12 @@ define ('M_NO_FILENAME', 'SansNom'); define ('M_NO_SENDER', 'kaz-'); define ('M_OLD_ATTACHEMENT_DIRNAME', "RappelHistorique"); define ('M_SEND', "Connexion"); -define ('M_LOGOUT', 'Déconnexion'); +define ('M_LOGOUT', 'Deconnecter'); +define ('M_REFRESH', 'Actualiser'); define ('M_LOGOUT_TOKEN', "Vous n'êtes plus connecté."); define ('M_SEND_TOKEN', "Vous allez recevoir un lien d'accès temporaire à vos données."); -define ('A_ACTION', 'a'); // action : T_SEND, T_LOGOUT, A_RECORD+(on|off) +define ('A_ACTION', 'a'); // action : T_SEND, T_LOGOUT, A_RECORD+(on|off), A_PERIOD(minute|hour|day|week|month|quarter) define ('A_GET', 'g'); // get archive define ('A_HASH', 'h'); // file to update or delete define ('A_OPEN_TOKEN', 'o'); // ask token @@ -61,6 +65,7 @@ define ('A_SENDER', 's'); // session sender define ('A_TOKEN', 't'); // session token define ('A_UPDATE', 'u'); // update perriod for file or archive define ('A_RECORD', 'r'); // get track status +define ('A_PERIOD', 'p'); // get period status define ('A_DELETE', 'd'); // delete file ou archive + (sender+token) define ('T_BAD_PASW', 'bad_psw'); define ('T_CREATE', "create"); @@ -84,6 +89,16 @@ define ('T_ZIP_EXT', ".zip"); define ('T_ARCHIVE_TITLE', "archive_content"); define ('T_ARCHIVE_MIME', "text/kaz_email_archive"); + +$periodText = ['minute' => "minute", 'hour' => "heure", 'day' => "jour", 'week' => "semaine", 'month' => "mois", 'quarter' => "trimestre"]; +$periodButton = ['day' => ["🕜", ">1 jour"], + 'week' => ["🕝", "> 1 semaine"], + 'month' => ["🕞", "> 1 mois"], + 'quarter' => ["🕟", "> 1 trimestre"]]; +$trackText = ['on' => "oui", 'off' => "non"]; +$doLogout = ''; +$message = ''; + /* Operations may take a long time. * Be sure PHP's safe mode is off. */ @@ -109,6 +124,66 @@ function return_error ($msg) { exit; } +// ======================================== +function setTrack ($sender) { + if (!$sender) + return; + if (!file_exists (VAR_TRACKS)) + mkdir (VAR_TRACKS, 0755); + touch (VAR_TRACKS.$sender); +} +function rmTrack ($sender) { + if (!$sender) + return; + if (file_exists (VAR_TRACKS.$sender)) + unlink (VAR_TRACKS.$sender); +} +function getTrack ($sender) { + if (!$sender) + return; + return file_exists (VAR_TRACKS.$sender); +} + +// ======================================== +function setPeriod ($sender, $period) { + if (!$sender) + return; + if (!file_exists (VAR_PERIOD)) + mkdir (VAR_PERIOD, 0755); + if (empty ($period) || DEFAULT_PERIOD == $period) { + if (file_exists (VAR_PERIOD.$sender)) + unlink (VAR_PERIOD.$sender); + } else + file_put_contents (VAR_PERIOD.$sender, $period.NL); +} +function rmPeriod ($sender) { + if (!$sender) + return; + if (file_exists (VAR_PERIOD.$sender)) + unlink (VAR_PERIOD.$sender); +} +function getPeriod ($sender) { + if (!$sender || !file_exists (VAR_PERIOD.$sender)) + return DEFAULT_PERIOD; + return trim (file (VAR_PERIOD.$sender)[0]); +} + +// ======================================== +function setFake ($sender, $dir_link, $dirTime) { + if (!$sender) + return; + if (!file_exists (VAR_FAKE)) + mkdir (VAR_FAKE, 0755); + file_put_contents (VAR_FAKE.$sender, "time: ".$dirTime.NL."sender: ".$sender.NL); + rmToken ($sender); +} + +function getFake ($sender) { + if (!$sender) + return; + return file_exists (VAR_FAKE.$sender); +} + // ======================================== function isKazArchive ($link) { return @@ -116,16 +191,10 @@ function isKazArchive ($link) { jirafeau_escape ($link ['mime_type']) == T_ARCHIVE_MIME; } // ======================================== -function getTimeFile ($link) { - $p = s2p ($link ['hash']); - return filemtime (VAR_FILES . $p . $link ['hash']); -} - -function timeStamp2time ($timeStamp) { - if (preg_match ("/^(\d{4})-(\d{2})-(\d{2})[ :-](\d{2}):(\d{2}):(\d{2})/i", $timeStamp, $matches)) - // XXX bug GMT+1 - return mktime ($matches [4]-1, $matches [5], $matches [6], $matches [2], $matches [3], $matches [1]-2000); - return false; +function getTimeFile ($hash) { + $p = s2p ("$hash"); + $f = VAR_FILES . $p . $hash; + return file_exists ($f) ? filemtime ($f) : 0; } function valideTime ($t1, $t2) { @@ -157,10 +226,11 @@ function update_link ($link_name, $link, $update_period) { } // ======================================== +// read archive info function read_archive_info ($link) { $p = s2p ($link ['hash']); - // read archive info $result = []; + $error=false; foreach (file (VAR_FILES . $p . $link ['hash']) as $line) { switch (true) { case preg_match ("/^\s*src:\s*(([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6})\s*$/i", $line, $matches): @@ -176,10 +246,11 @@ function read_archive_info ($link) { $result [T_NEW][] = [$matches [1], $matches [2]]; break; default: + $error = true; break; } } - return $result; + return $error ? [] : $result; } // ======================================== @@ -214,26 +285,6 @@ function send_email ($receiver, $receiver_name, $subject, $body_string){ } } -// ======================================== -function setTrack ($sender) { - if (!$sender) - return; - if (!file_exists (VAR_TRACKS)) - mkdir (VAR_TRACKS, 0755); - touch (VAR_TRACKS.$sender); -} -function rmTrack ($sender) { - if (!$sender) - return; - if (file_exists (VAR_TRACKS.$sender)) - unlink (VAR_TRACKS.$sender); -} -function getTrack ($sender) { - if (!$sender) - return; - return file_exists (VAR_TRACKS.$sender); -} - // ======================================== function cleanToken () { if (!file_exists (VAR_TOKENS)) @@ -353,12 +404,12 @@ if ($do_update) { $sender = ''; $senderError = false; if (isset ($_REQUEST [A_SENDER]) && !empty ($_REQUEST [A_SENDER])) { - if (!preg_match ("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/i", $_REQUEST [A_SENDER])) { + if (!preg_match ("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/i", $_REQUEST [A_SENDER])) $senderError=true; - return; + else { + cleanToken (); + $sender = $_REQUEST [A_SENDER]; } - cleanToken (); - $sender = $_REQUEST [A_SENDER]; } // ======================================== @@ -433,15 +484,15 @@ if ($do_download) { if ($zip->open ($tmpFileName.T_ZIP_EXT, ZipArchive::CREATE) !== TRUE) return_error (E_OPEN_ZIP); - // create info XXX + // create info if ($modif) { $info = ''; if (isset ($archive_info [T_NOT_FOUND])) $info .= $archive_info [T_NOT_FOUND]. ($archive_info [T_NOT_FOUND] ? M_FILE_NOT_FOUND : M_FILES_NOT_FOUND).NL; if (isset ($archive_info [T_BAD_PASW])) $info .= M_BAD_KEY. $archive_info [T_BAD_PASW]. ($archive_info [T_BAD_PASW] ? M_FILE : M_FILES).NL; - if (isset ($archive_info [$cat][T_RENAME])) - $info .= $archive_info [$cat][T_RENAME]. ($archive_info [$cat][T_RENAME] ? M_FILE_RENAMED : M_FILES_RENAMED).NL; + if (isset ($archive_info[T_RENAME])) + $info .= $archive_info[T_RENAME]. ($archive_info[T_RENAME] ? M_FILE_RENAMED : M_FILES_RENAMED).NL; $zip->addFromString ($dirname.T_WARNING_FILENAME, $info); } foreach ([T_OLD, T_NEW] as $cat) @@ -514,6 +565,18 @@ if (isset ($_REQUEST [A_RECORD]) && !empty ($_REQUEST [A_RECORD])) { exit; } +// ======================================== +if (isset ($_REQUEST [A_PERIOD]) && !empty ($_REQUEST [A_PERIOD])) { + if (!preg_match ("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/i", $_REQUEST [A_PERIOD])) + return_error (M_BAD_SENDER_NAME); + $content = getPeriod ($_REQUEST [A_PERIOD]).NL; + header ('HTTP/1.0 200 OK'); + header ('Content-Length: ' . strlen ($content)); + header ('Content-Type: text/plain'); + echo $content; + exit; +} + // ======================================== // form $token = ''; @@ -526,15 +589,18 @@ if (isset ($_REQUEST [A_TOKEN]) && !empty ($_REQUEST [A_TOKEN])) { $refToken = getToken ($sender); $url_base = $_SERVER ['HTTP_X_FORWARDED_PROTO']."://".$_SERVER ['HTTP_HOST']; if (isset ($_REQUEST [A_ACTION]) && $_REQUEST [A_ACTION] == T_SEND && $sender) { - $token = setToken ($sender); - // XXX test token - $url = $url_base.$_SERVER ['SCRIPT_NAME']."?".A_SENDER."=".$sender."&".A_TOKEN."=".$token; - $result = send_email ($sender, "", M_EMAIL_SUBJECT, - str_replace (["___LINK___", "___IP___", "___DATE___"], - [$url, $_SERVER ['HTTP_X_REAL_IP'] , date ("Y-m-d H:i:s")], M_EMAIL_CONTENT)); - require (JIRAFEAU_ROOT . 'lib/template/header.php'); - echo M_SEND_TOKEN; + if (getFake ($sender)) + echo "Ce compte ne peut plus se connecter. Veuillez contacter les administrateurs."; + else { + $token = setToken ($sender); + // XXX test token + $url = $url_base.$_SERVER ['SCRIPT_NAME']."?".A_SENDER."=".$sender."&".A_TOKEN."=".$token; + $result = send_email ($sender, "", M_EMAIL_SUBJECT, + str_replace (["___LINK___", "___IP___", "___DATE___"], + [$url, $_SERVER ['HTTP_X_REAL_IP'] , date ("Y-m-d H:i:s")], M_EMAIL_CONTENT)); + echo M_SEND_TOKEN; + } require (JIRAFEAU_ROOT.'lib/template/footer.php'); exit; } @@ -585,106 +651,114 @@ if (!getLoggedToken ($sender)) else touch (VAR_TOKENS.$sender); -function setFake ($sender, $link_name) { - // XXX -} - function deleteAction ($link_name) { global $sender, $token, $message, $doLogout; $link = jirafeau_get_link ($link_name); - //$message .= "
".print_r ($link, 1)."
"; if (!count ($link)) return; if (isKazArchive ($link)) { $dir_name = $link_name; $dir_link = $link; - $dirTime = getTimeFile ($link); + $dirTime = getTimeFile ($dir_name); $archive_info = read_archive_info ($dir_link); - if (count ($archive_info) && isset ($archive_info [T_TIMESTAMP]) && !empty ($archive_info [T_TIMESTAMP])) { - $timeStamp = timeStamp2time ($archive_info [T_TIMESTAMP]); - if (!valideTime ($timeStamp, $dirTime)) { - setFake ($sender, $dir_name); - $message .= "PB1 : ".$archive_info [T_TIMESTAMP]." ".$timeStamp." / ".$dirTime."
"; - // XXX $doLogout = true; - return; - } + if (! count ($archive_info)) + return; + if ($sender != $archive_info [T_SENDER]) { + setFake ($sender, $dir_link, $dirTime); + $message .= "Tentative de supprimer un envoi dont vous n'êtes pas le propriétaire"; + $doLogout = true; + return; + } + if ($archive_info [T_NEW]) foreach ($archive_info [T_NEW] as [$file_name, $crypt_key]) { $file_link = jirafeau_get_link ($file_name); - if (count ($file_link) == 0) + if (! count ($file_link)) continue; - $fileTime = getTimeFile ($file_link); - if (!valideTime ($dirTime, $fileTime)) { - setFake ($sender, $dir_name); - $message .= "PB2 : ".$archive_info [T_TIMESTAMP]." ".$timeStamp." / ".$dirTime." / ".$fileTime."
"; - // XXX $doLogout = true; + $fileTime = getTimeFile ($file_name); + if (! valideTime ($dirTime, $fileTime)) { + setFake ($sender, $dir_link, $dirTime); + $message .= "Cet envoie a été forgée (dates incohéantes)."; + $doLogout = true; return; } } + if ($archive_info [T_NEW]) foreach ($archive_info [T_NEW] as [$file_name, $crypt_key]) { $file_link = jirafeau_get_link ($file_name); - if (count ($file_link) == 0) + if (! count ($file_link)) continue; - jirafeau_delete_link ($file_link); + jirafeau_delete_link ($file_name); } - jirafeau_delete_link ($dir_link); - } else { - setFake ($sender, $dir_name); - $message .= "PB3 : ".$archive_info [T_TIMESTAMP]."
"; - // XXX $doLogout = true; - } - } else { - $file_name = $link_name; - $file_link = $link; - $fileTime = getTimeFile ($file_link); - $stack = array (VAR_LINKS); - while (($d = array_shift ($stack)) && $d != null) { - $dir = scandir ($d); - foreach ($dir as $dir_name) { - if (strcmp ($dir_name, '.') == 0 || strcmp ($dir_name, '..') == 0 || - preg_match ('/\.tmp/i', "$dir_name")) { - continue; - } - if (is_dir ($d . $dir_name)) { - /* Push new found directory. */ - $stack [] = $d . $dir_name . '/'; - continue; - } - /* Read link informations. */ - $dir_link = jirafeau_get_link ($dir_name); - $dirTime = getTimeFile ($dir_link); - if (!count ($dir_link)) - continue; - if (!isKazArchive ($dir_link)) - continue; - $archive_info = read_archive_info ($dir_link); + jirafeau_delete_link ($dir_name); + return; + } + $file_name = $link_name; + $file_link = $link; + $fileTime = getTimeFile ($file_name); + $stack = array (VAR_LINKS); + while (($d = array_shift ($stack)) && $d != null) { + if (!file_exists ($d)) + continue; + $dir = scandir ($d); + foreach ($dir as $dir_name) { + if (strcmp ($dir_name, '.') == 0 || strcmp ($dir_name, '..') == 0 || + preg_match ('/\.tmp/i', "$dir_name")) { + continue; + } + if (is_dir ($d . $dir_name)) { + /* Push new found directory. */ + $stack [] = $d . $dir_name . '/'; + continue; + } + /* Read link informations. */ + $dir_link = jirafeau_get_link ($dir_name); + $dirTime = getTimeFile ($dir_name); + if (!count ($dir_link)) + continue; + if (!isKazArchive ($dir_link)) + continue; + $archive_info = read_archive_info ($dir_link); + if (! count ($archive_info)) + return; + if ($archive_info [T_NEW]) foreach ($archive_info [T_NEW] as [$new_name, $crypt_key]) { - if ($file_name == $new_name) { - if ($sender == $archive_info [T_SENDER]) { - if (valideTime ($dirTime, $fileTime)) - jirafeau_delete_link ($file_link); - else { - setFake ($sender, $dir_name); - $message .= "
".print_r ($archive_info, 1)."
"; - $message .= "PB4 : ".$archive_info [T_TIMESTAMP]." ".$timeStamp." / ".$dirTime." / ".$fileTime."
"; - // XXX $dologout = true; + if ($file_name != $new_name) + continue; + if ($sender == $archive_info [T_SENDER]) { + if (valideTime ($dirTime, $fileTime)) { + jirafeau_delete_link ($file_name); + $message .= jirafeau_escape ($file_link ['file_name'])." est supprim&eacte;."; + // check empty dir + $empty = true; + foreach ([T_OLD, T_NEW] as $cat) + if ($empty && isset ($archive_info [$cat])) + foreach ($archive_info [$cat] as [$l, $c]) + if (count (jirafeau_get_link ($l))) { + $empty = false; + break; + } + if ($empty) { + $message .= jirafeau_escape ($file_link ['dir_name'])." vide est &eacte;galement supprim&eacte;."; + jirafeau_delete_link ($dir_name); } break; } - if (valideTime ($dirTime, $fileTime)) { - setFake ($sender, $dir_name); - $message .= "
".print_r ($archive_info, 1)."
"; - $message .= "PB5 : ".$archive_info [T_TIMESTAMP]." ".$timeStamp." / ".$dirTime." / ".$fileTime."
"; - // XXX $doLogout = true; - } else { - setFake ($archive_info [T_SENDER], $dir_name); - $message .= "
".print_r ($archive_info, 1)."
"; - $message .= "PB6 : ".$archive_info [T_TIMESTAMP]." ".$timeStamp." / ".$dirTime." / ".$fileTime."
"; - } + setFake ($sender, $dir_link, $dirTime); + $message .= "Cet envoie a été forgée (dates incohéantes ".$dirTime. " ".$fileTime.")."; + $dologout = true; break; } + if (valideTime ($dirTime, $fileTime)) { + setFake ($sender, $dir_link, $dirTime); + $message .= "Tentative de supprimer un envoi dont vous n'êtes pas le propriétaire"; + $doLogout = true; + break; + } + setFake ($archive_info [T_SENDER], $dir_link, $dirTime); + $message .= "Quelqu'un avétait revandiqué cet envoi"; + break; } - } } } } @@ -694,8 +768,6 @@ function deleteAction ($link_name) { // ======================================== // delete -$doLogout = ''; -$message = ''; if (isset ($_REQUEST [A_DELETE])) { if (!preg_match ('/[0-9a-zA-Z_-]+$/', $_REQUEST [A_DELETE])) return_error (t ('FILE_404')); @@ -706,20 +778,31 @@ if (isset ($_REQUEST [A_DELETE])) { if ($doLogout || (isset ($_REQUEST [A_ACTION]) && $_REQUEST [A_ACTION] == T_LOGOUT)) { rmToken ($sender); require (JIRAFEAU_ROOT . 'lib/template/header.php'); + echo + "

Informations concernant le compte : ".$sender."". + " (page actualisée à ".date ("H:i:s")." le ".date ("d/m/Y").").

"; if ($message) - echo $message; + echo "

Info : ".$message."

"; echo M_LOGOUT; require (JIRAFEAU_ROOT.'lib/template/footer.php'); exit; } -// change track if (isset ($_REQUEST [A_ACTION])) { - if ($_REQUEST [A_ACTION] == A_RECORD."on") - setTrack ($sender); - else if ($_REQUEST [A_ACTION] == A_RECORD."off") - rmTrack ($sender); - $message = "

Votre suivi à été changé.

"; + // change track + switch (true) { + case preg_match ("/^".A_RECORD."(on|off)$/i", $_REQUEST [A_ACTION], $matches): + if ($matches [1] == "on") + setTrack ($sender); + else + rmTrack ($sender); + $message .= "Votre suivi à été mise à jour."; + break; + case preg_match ("/^".A_PERIOD."(".implode ("|", array_keys ($periodText)).")$/i", $_REQUEST [A_ACTION], $matches): + setPeriod ($sender, $matches [1]); + $message .= "Votre période à été mise à jour."; + break; + } } // list @@ -753,9 +836,11 @@ while ( ($d = array_shift ($stack)) && $d != null) { } } require (JIRAFEAU_ROOT . 'lib/template/header.php'); -echo "

Page actualisée à ".date ("H:i:s d/m/Y")."

"; +echo + "

Informations concernant le compte : ".$sender."". + " (page actualisée à ".date ("H:i:s")." le ".date ("d/m/Y").").

"; if ($message) - echo $message; + echo "

Info : ".$message."

"; echo ' '. - "je veux que Kaz suive tous mes futurs envoie : ". + 'Je veux que Kaz suive tous mes futurs envoies: '. ''. - ''. - 'oui '. - 'non '. + ''; +foreach ($trackText as $item => $text) + echo ''.$text.' '; +echo ''. ''. '
'. + 'Je veux que mes futurs envois soient accessibles pendant au moins un·e '. + ' '. + ''. + '
'. + '
'. + 'Je veux '. + ''. + ''. + ''. + ' la page.
'. + '
'. + 'Je veux me '. ''. ''. ''. ''. - '
'; + '.'; if ($archives) { foreach ($archives as $archive_info) { @@ -838,12 +938,12 @@ if ($archives) { $ka = $archive_info ['key']; echo ' 👁 '. - ' 🔗 '. - ' 🕝 '. - ' 🕞 '. - ' 🕟 '. + ' 🔗 '; + foreach ($periodButton as $item => $bt) + echo ' '.$bt[0].' '; + echo ''.$archive_info [T_TIMESTAMP].''. - ''; + ''; echo '
=> '. ($archive_info ['time'] == -1 ? '∞' : jirafeau_get_datetimefield ($archive_info ['time'])).'