diff --git a/src/Jirafeau/a.php b/src/Jirafeau/a.php index ea6a0f8..06836d4 100644 --- a/src/Jirafeau/a.php +++ b/src/Jirafeau/a.php @@ -18,43 +18,69 @@ require (JIRAFEAU_ROOT . 'lib/settings.php'); require (JIRAFEAU_ROOT . 'lib/functions.php'); require (JIRAFEAU_ROOT . 'lib/lang.php'); -define ('A_GET', 'g'); -define ('A_HASH', 'h'); -define ('A_SENDER', 's'); -define ('A_UPDATE', 'u'); -define ('A_OPEN_TOKEN', 'o'); -define ('E_BAD_SENDER_NAME', 'mèl incorrect : '); -define ('E_BAD_ARCHIVE_NAME', 'bad archive name format : '); +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_INTRO_FORM', "Où sont les dernières pièces jointe que j'ai envoyé ?"); +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. */ @@ -85,7 +111,7 @@ function return_error ($msg) { * @param $link the link's name (hash) * @param $update_period the periode (i.e in : "month") */ -function jirafeau_update_link ($link_name, $link, $update_period) { +function update_link ($link_name, $link, $update_period) { $time_max = $link ['time']; $time_up = time () + $update_period; $time_more = $time_up + JIRAFEAU_HOUR; @@ -135,18 +161,20 @@ function send_email($receiver, $receiver_name, $subject, $body_string){ // SERVER SETTINGS $mail = new PHPMailer (true); $mail->isSMTP (); - $mail->Host = 'smtp'; - $mail->SMTPAuth = false; + $mail->Host = 'smtp'; + $mail->SMTPAuth = false; $mail->SMTPAutoTLS = false; - $mail->SMTPSecure = "none"; - $mail->Port = 25; + $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 (false); + $mail->isHTML (true); $mail->Subject = $subject; $mail->Body = $body_string; @@ -160,6 +188,89 @@ 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)) + 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; @@ -194,8 +305,19 @@ if ($do_update) { $link = jirafeau_get_link ($link_name); if (count ($link) == 0) return_error (t ('FILE_404')); - $time = jirafeau_update_link ($link_name, $link, $update_period); + $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'); @@ -203,15 +325,26 @@ if ($do_update) { 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.$_REQUEST [A_GET]); + 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.$_REQUEST [A_GET]); + return_error (E_BAD_ARCHIVE_NAME); $crypt_key = count ($couple) == 2 ? $couple [1] : ""; $link = jirafeau_get_link ($link_name); if (count ($link) == 0) @@ -266,7 +399,7 @@ if ($do_download) { // build zip $dirname = (isset ($archive_info[T_SENDER]) && !empty ($archive_info[T_SENDER])) - ? $archive_info[T_SENDER] : M_NO_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."-"); @@ -346,35 +479,73 @@ if ($do_download) { } // ======================================== -// XXX form send -$content = "TODO send form".NL; - -$sender = ''; -if (isset ($_REQUEST [A_SENDER]) && !empty ($_REQUEST [A_SENDER])) { - $sender=$_REQUEST [A_SENDER]; - if (!preg_match ("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix", $sender)) - return_error (E_BAD_SENDER_NAME.$sender); - $content = "${sender}".NL; +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; } -if (!$sender) { +// ======================================== +// 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."

"; + ?>
-
+
- - - - +
+
+
@@ -385,31 +556,29 @@ if (!$sender) { exit; } -$open_service = ''; -if (!isset ($_REQUEST [A_OPEN_TOKEN]) || empty ($_REQUEST [A_OPEN_TOKEN])) - $open_service=$_REQUEST [A_OPEN_TOKEN]; - -if (!isset ($open_service)) { - // send e-mail - //preg_match ("%^http.*//depot.([^/]+)/?$%i", $cfg ['web_root'], $matches); - // $domain = $matches[1]; - // $to = $sender; - // $subject = 'Lien de consultation des envoies de pièces jointes'; - // $message = 'Bonjour !'; - // $headers = - // 'From: no-reply@'.$domain.'' . "\r\n" . - // 'X-Mailer: PHP/' . phpversion(); - // mail ($to, $subject, $message, $headers); - - $result = send_email ($sender, "", "Lien de consultation des envoies de pièces jointes", "Bonjour!"); +if (!getLoggedToken ($sender)) + setLoggedToken ($sender, $token); +else + touch (VAR_TOKENS.$sender); +// ======================================== +if (isset ($_REQUEST [A_ACTION]) && $_REQUEST [A_ACTION] == T_LOGOUT) { + rmToken ($sender); require (JIRAFEAU_ROOT . 'lib/template/header.php'); - echo M_SEND_TOKEN; + echo M_LOGOUT; require (JIRAFEAU_ROOT.'lib/template/footer.php'); exit; } -$found = []; +if (isset ($_REQUEST [A_ACTION])) { + if ($_REQUEST [A_ACTION] == A_RECORD."on") + setTrack ($sender); + else if ($_REQUEST [A_ACTION] == A_RECORD."off") + rmTrack ($sender); +} + +// list +$archives = []; $stack = array (VAR_LINKS); while ( ($d = array_shift ($stack)) && $d != null) { $dir = scandir ($d); @@ -433,28 +602,85 @@ while ( ($d = array_shift ($stack)) && $d != null) { $archive_info = read_archive_info ($l); if ($sender != $archive_info [T_SENDER]) continue; - if (isset ($archive_info [T_NEW])) - foreach ($archive_info [T_NEW] as [$link_name, $crypt_key]) - $found [$link_name] = $crypt_key; + $archive_info ['link'] = $node; + $archive_info ['time'] = $l ['time']; + $archive_info ['key'] = $l ['key']; + $archives [] = $archive_info; } } } -foreach ($found as $link_name => $crypt_key) - $content .= $link_name . " - " . $crypt_key . NL; - -// XXX find -// add link : name / time / download / delete -// sort by name ? - -// $tmpFileName = tempnam (sys_get_temp_dir (), $dirname."-"); -// $fd = fopen ($tmpFileName, "w"); -// if (!$fd) -// return_error ("Unable to open tmp file!"); -// fwrite ($fd, $content); -// fclose ($fd); - -header ('HTTP/1.0 200 OK'); -header ('Content-Length: ' . strlen ($content)); -header ('Content-Type: text/plain'); -echo $content; +require (JIRAFEAU_ROOT . 'lib/template/header.php'); +?> + +'. + ''. + ''. + '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; ?> diff --git a/src/bash/filter.sh b/src/bash/filter.sh index 7e72952..9e31281 100644 --- a/src/bash/filter.sh +++ b/src/bash/filter.sh @@ -75,7 +75,8 @@ LOG_FIC "--------------- debut de programme -------------------" mkdir -p "${MAILS}" || { LOG_FIC "impossible de creer ce dossier"; exit "${EX_UNAVAILABLE}"; } MAIL_SOURCE=$(echo $@ | awk 'BEGIN{FS=" "} {print $2}') DATE_TEMPS=$(date "+%Y-%m-%d-%H:%M:%S") -REP_PIECE_JOINTE=$(echo "${MAILS}/${DATE_TEMPS}_${MAIL_SOURCE}_$$") +REP_PIECE_JOINTE="${MAILS}/${DATE_TEMPS}_${MAIL_SOURCE}_$$" +TRACK=$(curl "${JIRAFEAU_URL}/a.php?r=${MAIL_SOURCE}" 2>/dev/null) cd "${INSPECT_DIR}" || { echo "${INSPECT_DIR} does not exist"; exit "${EX_TEMPFAIL}"; } # lien renvoyé par le téléverssement @@ -97,10 +98,9 @@ mkdir -p "${REP_PIECE_JOINTE}/" >"${ARCHIVE_CONTENT}" # Etape de rafraichissement des anciens fichiers inclus -cat > "${ARCHIVE_CONTENT}" < "${ARCHIVE_CONTENT}" +[ -n "${TRACK}" ] && echo "src: ${MAIL_SOURCE}" >> "${ARCHIVE_CONTENT}" + LOG_FIC "${SHRINK_CMD} -u \"${INSPECT_DIR}/in.$$\" 2>> \"${FIC_LOG}\" > \"${OLD_LINKS}\"" "${SHRINK_CMD}" -u "${INSPECT_DIR}/in.$$" 2>> "${FIC_LOG}" > "${OLD_LINKS}" @@ -155,29 +155,31 @@ LOG_FIC "${SHRINK_CMD} -s ${MAX_KEEP_IN_MAIL} -d ${REP_PIECE_JOINTE} ${INSPECT_D rm -f "${ATTACH_TMP_FILE}" done # Création de l'archive - if [ "$(wc -l < "${ARCHIVE_CONTENT}")" -ge 4 ]; then + NB_ATTCH=$(grep -e "^old: " -e "^new1: " "${ARCHIVE_CONTENT}" | wc -l) + if [ -n "${TRACK}" ] || [ "${nb}" -gt 1 ]; then PASSWORD=$(apg -n 1 -m 12) PASSWORD_MD5=$(echo -n ${PASSWORD} | ${MD5_CMD} | cut -d \ -f 1) LOG_FIC " - \"${JIRAFEAU_CMD}\" -f \"${JIRAFEAU_LOCAL}\" -s \"${MAX_UPLOAD_SIZE}\" -c \"text/plain\" -n \"archive_content\" send \"${ARCHIVE_CONTENT}\" \"${PASSWORD}\" 2>> \"${FIC_LOG}\" > \"${ONE_LINK}\"" "${JIRAFEAU_CMD}" -f "${JIRAFEAU_LOCAL}" -s "${MAX_UPLOAD_SIZE}" -c "text/plain" -n "archive_content" send "${ARCHIVE_CONTENT}" "${PASSWORD}" 2>> "${FIC_LOG}" > "${ONE_LINK}" - cat "${ONE_LINK}" | { - read JIR_TOKEN - read JIR_CODE - LOG_FIC " - Jirafeau retourne ${JIR_TOKEN} et ${JIR_CODE}" - case "${JIR_TOKEN}" in - "" | no | *Error* | \<* ) - LOG_FIC " - impossible de televerser l'archive (${JIR_TOKEN}), il ne sera pas remplace dans le message" - echo "arch: bad" - ;; - * ) - LOG_FIC " - ajoute de l'archive ${JIRAFEAU_URL}/a.php?g=${JIR_TOKEN}~${PASSWORD_MD5}" - echo "arch: ${JIRAFEAU_URL}/a.php?g=${JIR_TOKEN}~${PASSWORD_MD5}" - ;; - esac - } - else - LOG_FIC " - pas d'archive (moins de 2 PJ)" - echo "arch: none" + if [ "${nb}" -gt 1 ]; then + cat "${ONE_LINK}" | { + read JIR_TOKEN + read JIR_CODE + LOG_FIC " - Jirafeau retourne ${JIR_TOKEN} et ${JIR_CODE}" + case "${JIR_TOKEN}" in + "" | no | *Error* | \<* ) + LOG_FIC " - impossible de televerser l'archive (${JIR_TOKEN}), il ne sera pas remplace dans le message" + echo "arch: bad" + ;; + * ) + LOG_FIC " - ajoute de l'archive ${JIRAFEAU_URL}/a.php?g=${JIR_TOKEN}~${PASSWORD_MD5}&s=${MAIL_SOURCE}" + echo "arch: ${JIRAFEAU_URL}/a.php?g=${JIR_TOKEN}~${PASSWORD_MD5}&s=${MAIL_SOURCE}" + ;; + esac + } else + LOG_FIC " - pas d'archive (moins de 2 PJ)" + echo "arch: none" + fi fi # Etape de substitution LOG_FIC "${SHRINK_CMD} -s \"${MAX_KEEP_IN_MAIL}\" \"${INSPECT_DIR}/in.$$\" \"${INSPECT_DIR}/in.$$.altered\" 2>> \"${FIC_LOG}\""