deadline a.php?g=l~k => zip a.php?s=mel@domain.org => send status e-mail */ use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\SMTP; use PHPMailer\PHPMailer\Exception; require 'vendor/autoload.php'; define ('JIRAFEAU_ROOT', dirname (__FILE__) . '/'); require (JIRAFEAU_ROOT . 'lib/settings.php'); require (JIRAFEAU_ROOT . 'lib/functions.php'); require (JIRAFEAU_ROOT . 'lib/lang.php'); define ('VAR_TOKENS', $cfg['var_root'] . 'tokens/'); define ('VAR_TRACKS', $cfg['var_root'] . 'tracks/'); define ('TOKEN_USE_LIMIT', "-2 hours"); define ('TOKEN_LOGIN_LIMIT', "-15 minutes"); define ('TOKEN_LOGOUT_LIMIT', "-8 hours"); define ('E_BAD_ARCHIVE_NAME', 'Bad archive name format'); define ('E_CREATE_ZIP', "Impossible de créer l'archive."); define ('E_OPEN_ZIP', "Impossible d'ouvrir l'archive."); define ('M_BAD_KEY', "Mauvaise clef pour "); define ('M_BAD_SENDER_NAME', 'Votre mèl est incorrect'); define ('M_BAD_TOKEN', "Vous n'utilisez pas le bon jeton (consultez votre messagerie)."); define ('M_TOO_LONG_BEFORE_LOGGED', "Jeton de connexion trop ancien."); define ('M_TOO_LONG_LOGGED', "Temps de connexion dépassé."); define ('M_EMAIL_CONTENT', "Bonjour,

Ceci est un message automatique, car vous venez de cliquer sur une demande de consultation de vos pièces jointes.

!!! Si vous n'êtes pas à l'origine de cette demande, ne cliquez sur aucun lien de ce message. !!!

Le lien de connexion suivant est valable 15 minutes.
___LINK___

Vous pouvez signaler des abus auprès de Kaz en faisant suivre ce message qui contient les traces de son émetteur (___IP___, ___DATE___).

Bonne navigation.
."); define ('M_DOWNLOAD', "Télécharger"); define ('M_UPDATE', "Prolonger"); define ('M_EMAIL_SUBJECT', "Lien de consultation des envoies de pièces jointes."); define ('M_FILE', " fichier."); define ('M_FILES', " fichiers."); define ('M_FILES_NOT_FOUND', " fichiers sont expirés."); define ('M_FILES_RENAMED', " fichiers renommés."); define ('M_FILE_NOT_FOUND', " fichier est expiré."); define ('M_FILE_RENAMED', " fichier renommé."); define ('M_INTRO_FORM', "Quelles sont les informations me concernant ?"); define ('M_MEL', "votre mèl"); 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_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'); define ('A_GET', 'g'); define ('A_HASH', 'h'); define ('A_OPEN_TOKEN', 'o'); // ask send token define ('A_SENDER', 's'); define ('A_TOKEN', 't'); define ('A_UPDATE', 'u'); define ('A_RECORD', 'r'); define ('T_BAD_PASW', 'bad_psw'); define ('T_CREATE', "create"); define ('T_CRYPTED', 'crypted'); define ('T_CRYPT_KEY', 'crypt_key'); define ('T_ENTRIES', 'entries'); define ('T_FILENAME', 'file_name'); define ('T_HASH', 'hash'); define ('T_LOGGED', "logged"); define ('T_NEW', 'new'); define ('T_NOT_FOUND', 'not_found'); define ('T_OLD', 'old'); define ('T_RENAME', 'rename'); define ('T_SEND', 'send'); define ('T_LOGOUT', 'lougout'); define ('T_SENDER', 'sender'); define ('T_TIMESTAMP', 'timestamp'); define ('T_TOKEN', "token"); define ('T_WARNING_FILENAME', "-Avertissement.txt"); define ('T_ZIP_EXT', ".zip"); /* Operations may take a long time. * Be sure PHP's safe mode is off. */ @set_time_limit (0); /* Remove errors. */ @error_reporting (0); $do_update = false; if (isset ($_REQUEST[A_UPDATE]) && !empty ($_REQUEST[A_UPDATE])) { $do_update = true; } $do_download = false; if (isset ($_REQUEST[A_GET]) && !empty ($_REQUEST[A_GET])) { $do_download = true; } // ======================================== function return_error ($msg) { require (JIRAFEAU_ROOT.'lib/template/header.php'); echo '

' . $msg . '

'; require (JIRAFEAU_ROOT.'lib/template/footer.php'); exit; } // ======================================== /** Update link * @param $link the link's name (hash) * @param $update_period the periode (i.e in : "month") */ function update_link ($link_name, $link, $update_period) { $time_max = $link ['time']; $time_up = time () + $update_period; $time_more = $time_up + JIRAFEAU_HOUR; if ($time_max < 0 || $time_up < $time_max) return $time_max; $link ['time'] = $time_more; $link_tmp_name = VAR_LINKS . $link ['hash'] . rand (0, 10000) . '.tmp'; $handle = fopen ($link_tmp_name, 'w'); fwrite ($handle, $link ['file_name'] .NL. $link ['mime_type'] .NL. $link ['file_size'] .NL. $link ['key'] .NL. $link ['time'] .NL. $link ['hash'] .NL. $link ['onetime'] .' '.JIRAFEAU_MONTH . ' '. JIRAFEAU_DAY .NL. $link ['upload_date'] .NL. $link ['ip'] .NL. $link ['link_code'] .NL. $link ['crypted']); fclose ($handle); $link_file = VAR_LINKS . s2p ("$link_name") . $link_name; rename ($link_tmp_name, $link_file); return $time_more; } // ======================================== function read_archive_info ($link) { $p = s2p ($link ['hash']); // read archive info $result=[]; 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): $result[T_SENDER] = $matches[1]; break; case preg_match ("/^\s*time:\s*(\d{4}([:-]\d{2}){5})\s*$/i", $line, $matches): $result[T_TIMESTAMP] = $matches[1]; break; case preg_match ("/^\s*old:\s*([0-9a-zA-Z_-]+)\s+([0-9a-zA-Z_-]+)\s*$/", $line, $matches): $result[T_OLD][] = [$matches[1], $matches[2]]; break; case preg_match ("/^\s*new:\s*([0-9a-zA-Z_-]+)\s+([0-9a-zA-Z_-]+)\s*$/", $line, $matches): $result[T_NEW][] = [$matches[1], $matches[2]]; break; default: break; } } return $result; } // ======================================== function send_email($receiver, $receiver_name, $subject, $body_string){ // SERVER SETTINGS $mail = new PHPMailer (true); $mail->isSMTP (); $mail->Host = 'smtp'; $mail->SMTPAuth = false; $mail->SMTPAutoTLS = false; $mail->SMTPSecure = "none"; $mail->Port = 25; $mail->charSet = "UTF-8"; $mail->ContentType = 'text/html'; //Recipients (change this for every project) $mail->setFrom ('no-reply@kaz.local', ''); $mail->addAddress ($receiver, $receiver_name); //Content $mail->isHTML (true); $mail->Subject = $subject; $mail->Body = $body_string; //send the message, check for errors if (!$mail->send ()) { //echo 'Mailer Error: ' . $mail->ErrorInfo; return 0; } else { //echo 'Message sent!'; return 1; } } // ======================================== 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)) mkdir (VAR_TOKENS, 0755); $d = dir (VAR_TOKENS); $oldest = strtotime (TOKEN_USE_LIMIT); foreach (glob (VAR_TOKENS."*") as $file) { if (filemtime ($file) <= $oldest) unlink ($file); } } function rmToken ($sender) { if (!$sender) return; if (file_exists (VAR_TOKENS.$sender)) unlink (VAR_TOKENS.$sender); } function setToken ($sender) { if (!$sender) return; $token = md5 (rand ()); if (file_put_contents (VAR_TOKENS.$sender, T_CREATE.": ".time ().NL.T_TOKEN.": ".$token.NL)) return $token; return false; } function setLoggedToken ($sender, $token) { if (!$sender || !$token) return; file_put_contents (VAR_TOKENS.$sender, T_CREATE.": ".time ().NL.T_TOKEN.": ".$token.NL.T_LOGGED.": ok".NL); } function getTokenVar ($sender, $varName) { if (!$sender) return; if (!file_exists (VAR_TOKENS.$sender)) return false; $content = file_get_contents (VAR_TOKENS.$sender); if (preg_match ("/\b".$varName.":\s*([^\s]+)\n/", $content, $matches)) return $matches[1]; return false; } function getToken ($sender) { return getTokenVar ($sender, T_TOKEN,); } function getCreateToken ($sender) { return getTokenVar ($sender, T_CREATE); } function getLoggedToken ($sender) { return getTokenVar ($sender, T_LOGGED); } function getTimeToken ($sender) { if (!$sender || !file_exists (VAR_TOKENS.$sender)) return false; return filemtime (VAR_TOKENS.$sender); } // ======================================== if ($do_update) { $update_period = JIRAFEAU_MONTH; switch ($_REQUEST[A_UPDATE]) { case 'minute': $update_period = JIRAFEAU_MINUTE; break; case 'hour': $update_period = JIRAFEAU_HOUR; break; case 'day': $update_period = JIRAFEAU_DAY; break; case 'week': $update_period = JIRAFEAU_WEEK; break; case 'month': $update_period = JIRAFEAU_MONTH; break; case 'quarter': $update_period = JIRAFEAU_QUARTER; break; case 'year': $update_period = JIRAFEAU_YEAR; break; default: return_error (t ('ERR_OCC') . ' (update_period)'); } $link_name = $_REQUEST[A_HASH]; if (!preg_match ('/[0-9a-zA-Z_-]+$/', $link_name)) return_error (t ('FILE_404')); $link = jirafeau_get_link ($link_name); if (count ($link) == 0) return_error (t ('FILE_404')); $time = update_link ($link_name, $link, $update_period); $content = '' . $time . NL; if (@preg_match ("/archive_content/", jirafeau_escape ($link ['file_name'])) && jirafeau_escape ($link ['mime_type']) != "text/plain") { $archive_info = read_archive_info ($l); if (count ($archive_info)) { foreach ([T_OLD, T_NEW] as $cat) if (isset ($archive_info[$cat])) foreach ($archive_info[$cat] as [$link_name, $crypt_key]) update_link ($link_name, jirafeau_get_link ($link_name), $update_period); } } header ('HTTP/1.0 200 OK'); header ('Content-Length: ' . strlen ($content)); header ('Content-Type: text/plain'); echo $content; exit; } $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])) { $senderError=true; return; } cleanToken (); $sender = $_REQUEST [A_SENDER]; } // ======================================== if ($do_download) { // check archive exist $couple = explode ("~", $_REQUEST[A_GET], 2); if (count ($couple) == 0) return_error (E_BAD_ARCHIVE_NAME); $link_name = $couple [0]; if (!$link_name || !preg_match ('/[0-9a-zA-Z_-]+$/', $link_name)) return_error (E_BAD_ARCHIVE_NAME); $crypt_key = count ($couple) == 2 ? $couple [1] : ""; $link = jirafeau_get_link ($link_name); if (count ($link) == 0) return_error (t ('FILE_404')); $key = $link ['key']; if ($key && (empty ($crypt_key) || $key != $crypt_key)) return_error (t ('BAD_PSW')); $archive_info = read_archive_info ($link); // check entries $archive_content = []; $modif = false; $single_name = []; foreach ([T_OLD, T_NEW] as $cat) if (isset ($archive_info[$cat])) foreach ($archive_info[$cat] as [$link_name, $crypt_key]) { $link = jirafeau_get_link ($link_name); if (count ($link) == 0) { if (isset ($archive_content[T_NOT_FOUND])) ++$archive_content[T_NOT_FOUND]; else $archive_content[T_NOT_FOUND] = 1; $modif = true; continue; } $key = $link ['key']; if ($key && (empty ($crypt_key) || $key != $crypt_key)) { if (isset ($archive_content[T_BAD_PASW])) ++$archive_content[T_BAD_PASW]; else $archive_content[T_BAD_PASW] = 1; $modif = true; continue; } $src_name = $dst_name = ($link ['file_name'] ? $link ['file_name'] : M_NO_FILENAME); if (in_array ($src_name, $single_name)) for ($i = 0; $i < 10000; ++$i) { $dst_name = sprintf ("%s-%2d", $src_name, $i); if (!in_array ($dst_name, $single_name)) { if (isset ($archive_content[T_RENAME])) ++$archive_content[T_RENAME]; else $archive_content[T_RENAME] = 1; $modif = true; break; } } $single_name [] = $dst_name; $archive_content[$cat][T_ENTRIES][] = [T_HASH => $link ['hash'], T_FILENAME => $dst_name, T_CRYPT_KEY => $crypt_key, T_CRYPTED => $link['crypted']]; } // build zip $dirname = (isset ($archive_info[T_SENDER]) && !empty ($archive_info[T_SENDER])) ? $archive_info[T_SENDER] : ($sender ? $sender : M_NO_SENDER); $dirname .= "-" . (isset ($archive_info[T_TIMESTAMP]) && !empty ($archive_info[T_TIMESTAMP])) ? $archive_info[T_TIMESTAMP] : date ("Ymd-His"); $tmpFileName = tempnam (sys_get_temp_dir (), $dirname."-"); $zip = new ZipArchive; if (!$zip) return_error (E_CREATE_ZIP); if ($zip->open ($tmpFileName.T_ZIP_EXT, ZipArchive::CREATE) !== TRUE) return_error (E_OPEN_ZIP); // create info XXX 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; $zip->addFromString ($dirname.T_WARNING_FILENAME, $info); } foreach ([T_OLD, T_NEW] as $cat) if (isset ($archive_info [$cat])) { $subdir = $dirname . ($cat == T_NEW ? "" : "/".M_OLD_ATTACHEMENT_DIRNAME); foreach ($archive_content [$cat][T_ENTRIES] as $entry) { $p = s2p ($entry [T_HASH]); if ($entry [T_CRYPTED]) { $m = mcrypt_module_open ('rijndael-256', '', 'ofb', ''); $md5_key = md5 ($entry [T_CRYPT_KEY]); $iv = jirafeau_crypt_create_iv ($md5_key, mcrypt_enc_get_iv_size ($m)); mcrypt_generic_init ($m, $md5_key, $iv); $r = fopen (VAR_FILES . $p . $entry [T_HASH], 'r'); $content = ""; while (!feof ($r)) { $dec = mdecrypt_generic ($m, fread ($r, 1024)); $content .= $dec; ob_flush (); } fclose ($r); $zip->addFromString ($subdir."/".$entry [T_FILENAME], $content); mcrypt_generic_deinit ($m); mcrypt_module_close ($m); continue; } $zip->addFile (VAR_FILES.$p.$entry [T_HASH], $subdir."/".$entry [T_FILENAME]); } } $zip->close (); if (!is_file ($tmpFileName.T_ZIP_EXT,)) return_error (E_OPEN_ZIP); if (false) { // log $content = print_r ($archive_info, 1); $content .= print_r ($archive_content, 1); header ('HTTP/1.0 200 OK'); header ('Content-Length: ' . strlen ($content)); header ('Content-Type: text/plain'); echo $content; exit; } header ("Content-Type: application/zip"); header ('Content-Disposition: filename="'.$dirname.'.zip"'); $r = fopen ($tmpFileName.".zip", 'r'); while (!feof ($r)) { print fread ($r, 1024); ob_flush (); } fclose ($r); unlink ($tmpFileName.".zip"); unlink ($tmpFileName); exit; } // ======================================== if (isset ($_REQUEST [A_RECORD]) && !empty ($_REQUEST [A_RECORD])) { if (!preg_match ("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/i", $_REQUEST [A_RECORD])) return_error (M_BAD_SENDER_NAME); $content = getTrack ($_REQUEST [A_RECORD]).NL; header ('HTTP/1.0 200 OK'); header ('Content-Length: ' . strlen ($content)); header ('Content-Type: text/plain'); echo $content; exit; } // ======================================== // form $token = ''; if (isset ($_REQUEST [A_TOKEN]) && !empty ($_REQUEST [A_TOKEN])) { if (!preg_match ("/^([0-9a-zA-Z_-]+)$/", $_REQUEST [A_TOKEN])) return false; $token = $_REQUEST [A_TOKEN]; } $refToken = getToken ($sender); $url_base = $_SERVER['HTTP_X_FORWARDED_PROTO']."://".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME']."?"; if (isset ($_REQUEST [A_ACTION]) && $_REQUEST [A_ACTION] == T_SEND && $sender) { $token = setToken ($sender); // XXX test token $url = $url_base.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; require (JIRAFEAU_ROOT.'lib/template/footer.php'); exit; } if (!($sender && $token && $token == $refToken && (getLoggedToken ($sender) || (getTimeToken ($sender) >= strtotime (TOKEN_LOGIN_LIMIT))) && (getCreateToken ($sender) >= strtotime (TOKEN_LOGOUT_LIMIT)))) { // XXX temps de connexion require (JIRAFEAU_ROOT . 'lib/template/header.php'); echo M_INTRO_FORM; if ($senderError) echo "

".M_BAD_SENDER_NAME."

"; else if (($token && !$refToken) || !getLoggedToken ($sender)) echo "

".M_TOO_LONG_BEFORE_LOGGED."

"; else if ($token && $token != $refToken) echo "

".M_BAD_TOKEN."

"; else if (getCreateToken ($sender) < strtotime (TOKEN_LOGOUT_LIMIT)) echo "

".M_TOO_LONG_LOGGED."

"; ?>
'. ''. ''. 'oui'. 'non'. ''. ''. '
'. ''. ''. ''. ''. '
'; if ($archives) { echo // '
archives'. ''; foreach ($archives as $archive_info) { echo ''; } echo '
'.t('ACTION').'
'.$archive_info [T_TIMESTAMP].''; echo '
=> '. ($archive_info ['time'] == -1 ? '∞' : jirafeau_get_datetimefield ($archive_info ['time'])).'
    '; foreach ([T_NEW, T_OLD] as $cat) { $li_style = $cat == T_NEW ? "font-weight: bold;" : "font-style: italic;"; if (isset ($archive_info [$cat])) foreach ($archive_info [$cat] as [$link_name, $crypt_key]) { $link = jirafeau_get_link ($link_name); if (count ($link) == 0) continue; echo '
  • '.jirafeau_escape ($link ['file_name']). ' ('.jirafeau_escape ($link ['mime_type']). ' '.jirafeau_human_size($l['file_size']). ')
  • '; } } $dl_val = $archive_info ['link']."~".$archive_info ['key']; echo '
'. '
'. '' . '' . '
' . '
' . '' . '
'. '
';//
'; } else echo "Il n'y a aucune information vous concernant."; require (JIRAFEAU_ROOT.'lib/template/footer.php'); exit; ?>