PickyPaste For Picky People: Robust (uses Zerobin) AND easy-to-use


(Pour qu'on puisse vous répondre)

(Le message est détruit après lecture)
Votre message




N'oubliez pas d'utiliser notre snippet pour encore plus de facilité et de gain de temps !!

» Glissez-déposez ce lien (PickyPaste) dans vos favoris et vous n'aurez plus qu'à cliquer dessus pour automatiquement ouvrir cette fenêtre avec le champ message pré-remplis avec l'adresse de la page où vous vous trouviez lorsque vous avez cliqué sur le snippet.

( Ne modifiez les valeurs ci-dessous que si vous savez ce que vous faites )




Voir le code source

<?php error_reporting(-1);

# PickyPaste 0.12beta
# > For Picky People (aka I want it robust AND easy-to-use)

# @author: JeromeJ (webmaster of http://www.olissea.com/ )
# @licence: DoWhatTheFuckYouWantAsLongAsYouGiveMeSomeCredits

# Based on Zerobin's encryption code

# NOTE: Best used with the snippet

# 2013-06-07: Added the expiration date to the mail's title.
#            - Also removed the anglicism crypter from French (chiffrer is the right word)
# 2013-06-04: Added auto-focus on the receiver field.
#             - Centralized the config into $PP_config which is set to global (in case PP would be embarked into a scope)
#            - Added the dynamic lang attribute into PP_error.

# TODO:
# - Create a local version of the HTML client, configurable through an optionnal external config file (an .ini file ?)
# - Create two versions: A standalone PHP and a client/server version.
#     -> The client/server version could simple have a client sending data to the standalone PHP version.
#    -> Additionnaly, for the people who DONT want people being able to use the standalone PHP version, there could be a light PHP version (no form, only the 'mailServer')
# - What if they don't want to send it by email? Wouldn't it be easier for them if they had only one tool to use? -> Make it modulable!

#################### CONFIG ####################################

global $PP_config# Just in case PP would be embarked in a scope.

$PP_config = array();

# Note: Langs aren't used yet

$PP_config['langs'] = array('fr''en'); # Available langs

# Set those as you prefer
define('PP_DEFAULT_LANG''fr');
define('PP_DEFAULT_EXPI''1month'); # Can be never, 5min, 10min, 1hour, 1day, 1week, 1month or 1year

################# ACTUAL CODE ##################################

# 5.2: filter_var, DateTime class 
if(version_compare(PHP_VERSION'5.2.0') < 0) exit('PickyPaste nécessite au moins PHP 5.2.0');

# 5.3: namespaces
# if(version_compare(PHP_VERSION, '5.3.0') < 0) exit('PickyPaste nécessite au moins PHP 5.3.0');

session_start();

if(isset(
$_GET['set_lang']) && in_array($_GET['set_lang'], $PP_config['langs']))
{
    
$_SESSION['PP']['lang'] = $_GET['set_lang'];
    
$PP_config['lang'] = $_GET['set_lang'];
}
else if(isset(
$_SESSION['PP']['lang']) && in_array($_SESSION['PP']['lang'], $PP_config['langs'])) $PP_config['lang'] = $_SESSION['PP']['lang'];
else 
$PP_config['lang'] = PP_DEFAULT_LANG;

if(!
in_array($PP_config['lang'], $PP_config['langs'])) $PP_config['lang'] = PP_DEFAULT_LANG;

function 
PP_error($error$extra=null)
{
    global 
$PP_config;
    
    echo 
'<!DOCTYPE html>',
        
'<html lang="',htmlspecialchars($PP_config['lang']),'">',
            
'<head>',
                
'<title>PickyPaste - Erreur !!</title>',
                
'<link type="text/css" rel="stylesheet" href="css/pickypaste.css" />',
                
'<meta charset="UTF-8">',
                
'<meta http-equiv="content-type" content="text/html; charset=utf-8" />',
            
'</head>',
            
'<body>',
                
'<span class="error">',$error,'</span>',
                (
$extra !== null '<br /><br />'.$extra:''),
            
'</body',
        
'</html>';
    
    exit;
}

if(!empty(
$_POST))
{
    if(!isset(
$_POST['randomkey'])) PP_error('La clé de décryptage n\'a pas été reçue !!');
    
    if(!isset(
$_POST['to'])) PP_error('Vous devez spécifiez un destinataire !!');
    else 
    {    
        if(
in_array(strtolower($_POST['to']), array('jeromej')))
        {
            require 
$_SERVER['DOCUMENT_ROOT'].'/inc/init.php';
            
            
$_POST $_POST_HTML# Removing auto-protection from Olissea
            
            # TODO: Add a hash verification to allow private access to username->email (Actually, this is to add Piiu to the list but not making it public)  (a "password" would be required)
            
            
list($_POST['to']) = $pdo->query('SELECT email FROM mb WHERE f_username=? LIMIT 1', array($_POST['to']), 'row');
        }
    }
    
    if(isset(
$_POST['from']) && $_POST['from']) $from htmlspecialchars($_POST['from']);
    else 
$from 'Anonyme';
    
    
$zerobinServer = (isset($_POST['zerobinServer']) ? $_POST['zerobinServer']:$_SERVER['SCRIPT_URI']);
    
    
$data = array('data''expire''burnafterreading''opendiscussion''syntaxcoloring');
    
    
$postdata = array();
    foreach(
$data AS $k) if(isset($_POST[$k])) $postdata[$k] = $_POST[$k];
    
    if(isset(
$postdata['data'])) $postdata['data'] = str_replace('\\'''$postdata['data']);
    
    
$opts = array('http' =>
        array(
            
'method'  => 'POST',
            
'header'  => 'Content-type: application/x-www-form-urlencoded',
            
'content' => http_build_query($postdata)
        )
    );
    
    
$context stream_context_create($opts);
    
    
set_error_handler(function($errno$errstr){throw new Exception($errno);});
    
    try
    {
        if(!
filter_var($zerobinServerFILTER_VALIDATE_URL)) throw new Exception('BAD URL');
        
        
$result file_get_contents($zerobinServerfalse$context);
    }
    catch(
Exception $e)
    {
        if(
$e->getMessage() == 'BAD URL'PP_error('Adresse du serveur Zerobin invalide !!');
        else 
PP_error('Serveur Zerobin injoignable !!''Veuillez réessayer plus tard ou en choisir un autre le cas échéant.');
        
        
restore_error_handler();
        
        exit();
    }
    
    
restore_error_handler();
    
    
$result json_decode($resulttrue);
    
    if(
$result === null || !isset($result['status']) || ($result['status'] == && !isset($result['message'])) || $result['status'] != || !isset($result['id']) || !is_string($result['id'])) PP_error('Impossible de créer votre past !! (Erreur de protocole avec le serveur Zerobin)');
    
    if(
$result['status'] == 1PP_error('Impossible de créer votre past : '.htmlspecialchars($result['message']));
    
    
$months = array(
        
'en' => cal_info(0), # Retrieve the list of English's months (1/2)
        
'fr' => array(=> 'janvier''février''mars''avril''mai''juin''juillet''août''septembre''octobre''novembre''décembre'),
    );
    
    
$months['en'] = $months['en']['abbrevmonths']; # Retrieve the list of English's months (2/2)
    
    
$dateHandler = array(
        
'fr' => function($date) use($months) {
            return array(
'Ce message expirera le '.str_replace($months['en'], $months['fr'], $date->format('d M Y à H\hi')),
                
'Expire le '.$date->format('d/m/Y à H\hi')
            );
        },
        
'en' => function($date){
            return array(
'This paste will expire on '.date_format($date'M d \'Y \a\t H:i'),
                
'Expires on '.date_format($date'm-d-Y \a\t H:i')
            );
        },
    );
    
    
$expirationTable = array(
        
'5min'    => '+5 min',
        
'10min'    => '+10 min',
        
'1hour'    => '+1 hour',
        
'1day'    => '+1 day',
        
'1week'    => '+7 day'# To match how Zerobin works
        
'1month'=> '+30 day'# To match how Zerobin works
        
'1year'    => '+365 day'# To match how Zerobin works
    
);
    
    
$expiration = new DateTime();
    
    
$expire = (isset($_POST['expire']) ? $_POST['expire']:'1month');
    
    if(
$expire == 'never'$expiration '';
    else
    {
        if(isset(
$expirationTable[$expire])) $expiration->modify($expirationTable[$expire]);
        else 
$expiration->modify($expirationTable['1month']);
        
        list(
$expiration$expiration_abbr) = $dateHandler[$PP_config['lang']]($expiration);
        
$expiration .= '.<br />';
    }
    
    if(isset(
$_POST['burnafterreading']) && $_POST['burnafterreading'] == '1')
    {
        
$burnafterreading = <<<EOF
Ce message est à <strong>lecture unique</strong>. Ce qui signifie que vous ne pourrez l'ouvrir qu'une seule fois.<br />
Par conséquent, si vous voulez pouvoir revoir son contenu, n'oubliez pas de le sauvegarder manuellement d'une façon ou d'une autre.<br /><br />

<strong>Attention,</strong> si vous ne parvenez pas à ouvrir ce message alors qu'il n'est pas censé être déjà expiré (voir date d'expiration ci dessus, s'il en avait une), veuillez considérez ce qui suit :
<ol>
    <li>Se peut-il que vous ayez déjà ouvert ce message (ou quelqu'un d'autre ayant accès à votre messagerie) ? Dans ce cas, vous n'êtes pas censé pouvoir le réouvrir.</li>
    <li>Le cas échéant, et si le message n'était pas censé être expiré, cela peut vouloir dire que le réseau que vous utilisez actuellement est <strong>corrompu</strong> !!<br />
    Merci de nous prévenir si cela vous arrive en nous précisant quel service mail vous utilisez et si cela s'est déjà produit auparavant. <a href="http://www.olissea.com/contact.php">Me contacter</a> (N'oubliez pas de préciser le motif !!) (Tout abus est punissable)</li>
</ol><br />
EOF;
    }
    else 
$burnafterreading '';
    
    
$link htmlspecialchars($zerobinServer).'?'.htmlspecialchars($result['id']).'#'.htmlspecialchars($_POST['randomkey']);
    
    
$mailContent = <<<EOF
Bonjour/soir,<br /><br />

Vous avez reçu un message de la part de <strong>
$from</strong>.<br /><br />

Afin de protéger votre vie privée, le message en question a été chiffré à l'aide de <a href="http://sebsauvage.net/paste/">Zerobin</a> via <a href="http://www.olissea.com/PickyPaste/">PickyPaste</a> (service facilitant l'envoie de mail sécurisé via Zerobin).<br /><br />

Pour visionner le message, merci de cliquer sur ce lien : <a href="
$link">$link</a><br />
$expiration<br />

$burnafterreading

<strong>Note :</strong> Toutes les applications et intermédiaires utilisés pour chiffrer et transmettre ce message sont des applications open-sources : Rien ne vous oblige à avoir confiance en nos applications naïvement, vous pouvez vérifier leur fonctionnement en détail ou même implémenter vos propres instances.
EOF;
    
    
/*if($from == 'debug')
    {
        echo '<pre>',var_dump($mailContent),'</pre>';
        exit('<br /><br />Petite maintenance ;) Réessayer dans quelques minutes svp ! Désolé pour le dérangement !');
    }*/
    
    # Used this technic to get the title to be displayed in UTF-8 as well: http://bitprison.net/php_mail_utf-8_subject_and_message
    
if(!mail('<'.$_POST['to'].'>',
        
'=?UTF-8?B?'.base64_encode('Lien Zerobin (via PickyPaste) #'.substr(htmlspecialchars($result['id']), 05).($expiration ' ('.$expiration_abbr.')':'')).'?=',
        
$mailContent,
        
"From: PickyPaste<no-reply@".(preg_replace('#^www\.#'''$_SERVER['SERVER_NAME'])).">\r\n".
        
"Content-type: text/html; charset=utf-8".
        (
filter_var($fromFILTER_VALIDATE_EMAIL) ? "\r\nReply-To: ".$from:'')))
    {
        
PP_error('L\'envoie du mail a échoué !!''Voici le lien vers votre paste <a href="'.$link.'">'.$link.'</a> (Procédure manuelle : clic droit sur le lien, copier l\'adresse du lien puis coller là dans votre email)');
    }
    
    echo 
'<html>',
            
'<head>',
                
'<title>PickyPaste</title>',
                
'<link type="text/css" rel="stylesheet" href="css/pickypaste.css" />',
                
'<meta charset="UTF-8">',
                
'<meta http-equiv="content-type" content="text/html; charset=utf-8" />',
                
# Note: Ne fonctionne pas sous Firefox.
                # Note 2: À réfléchir, idéalement peut-être ne pas fermer afin de pouvoir donner le lien de suppression du paste (ou l'envoyer à l'email de l'envoyeur ?)
                # '<script type="text/javascript">window.close();</script>', # TODO: Mettre un timer de 5sec
            
'</head>',
            
'<body>',
                
'Mail envoyé avec succès !<br /><br />',
                
'Vous pouvez dès à présent fermer cette page.',
                (isset(
$result['deletetoken']) ? '<br /><br />(<a href="'.htmlspecialchars($zerobinServer).'?pasteid='.$result['id'].'&deletetoken='.$result['deletetoken'].'">Lien pour détruire votre message manuellement</a>)':''),
            
'</body>',
        
'</html>';
    
    exit;
}

?>
<!DOCTYPE html>
<html lang="fr">
    <head>
        <title>PickyPaste</title>
        <link type="text/css" rel="stylesheet" href="css/pickypaste.css" />
        <meta charset="UTF-8">
        <meta http-equiv="content-type" content="text/html; charset=utf-8" />
        <script src="js/sjcl.js"></script>
        <script src="js/base64.js"></script>
        <script src="js/rawdeflate.js"></script>
        <script src="js/pickypaste.js"></script>
    </head>
    <body>
        <h1 id="title">
            <span class="title_P">P</span>icky<span class="title_P">P</span>aste 
            <span id="subtitle">For Picky People: Robust (uses <a href="http://sebsauvage.net/paste/">Zerobin</a>) AND easy-to-use</span>
        </h1>
        
        <noscript>
            <strong style="color: red">
                /!\ Your JavaScript seems disabled, DON'T USE THIS APPLICATION. It's not secured without JavaScript /!\<br />
                /!\ Votre JavaScript semble désactivé, N'UTILISEZ PAS CETTE APPLICATION. Ce n'est pas sécurisé sans JavaScript /!\
            </strong>
            <div> </div>
        </noscript>
        
        <form action="javascript:;" id="ppForm" method="post" onSubmit="return prepareForm()">
            <label for="f_to">Destinataire</label> <input autofocus id="f_to" name="to"  placeholder="Adresse email" required type="text" /><br /><!--  Changed type="email" to type="text" to allow Olissea plugin. -->
            <label for="f_from">Votre email</label> <input id="f_from" name="from" placeholder="Facultatif" type="text" /> (Pour qu'on puisse vous répondre)<br />
            <label for="pasteExpiration">Expiration</label> <select id="pasteExpiration" name="expire" required>
                <option value="5min">5 minutes</option>
                <option value="10min">10 minutes</option>
                <option value="1hour">1 heure</option>
                <option value="1day">1 jour</option>
                <option value="1week">1 semaine</option>
                <option value="1month" selected="selected">1 mois</option>
                <option value="1year">1 an</option>
                <option value="never">Jamais</option>
            </select><br />
            <label for="burnafterreading" title="Burn After Reading">Lecture unique</label> <input checked="checked" id="burnafterreading" name="burnafterreading" type="checkbox" value="1" /> (Le message est détruit après lecture)<br />
            
            <div id="status"></div>
            
            <span class="label">Votre message</span><br />
            <textarea id="message" cols="70" rows="20" required></textarea><br /><br />

            <input type="submit" /><br /><br />
            
            <strong>N'oubliez pas</strong> d'utiliser notre <strong>snippet</strong> pour encore plus de facilité et de gain de temps !!<br /><br />
            
            » Glissez-déposez ce lien (<a href="javascript:void(window.open('http://www.olissea.com/PickyPaste/#'+window.location.href, '_blank'))">PickyPaste</a>) dans vos favoris et vous n'aurez plus qu'à cliquer dessus pour automatiquement ouvrir cette fenêtre avec le champ message pré-remplis avec l'adresse de la page où vous vous trouviez lorsque vous avez cliqué sur le snippet.<br /><br />
            
            <em>( Ne modifiez les valeurs ci-dessous que si vous savez ce que vous faites )</em><br /><br />
            <label for="zerobinServer">Serveur Zerobin</label> <input id="zerobinServer" name="zerobinServer" type="text" value="http://sebsauvage.net/paste/" size="50" /><br />
            <label for="mailServer">Serveur Mail</label> <input id="mailServer" type="text" size="50" /> <br />
            <label for="opendiscussion">Discussion ouverte</label> <input id="opendiscussion" name="opendiscussion" type="checkbox" value="1" /> <br />
            <label for="syntaxcoloring" style="clear: both">Colorisation syntaxique</label> <input id="syntaxcoloring" name="syntaxcoloring" type="checkbox" value="1" />
            
            <input id="data" name="data" type="hidden" />
            <input id="randomkey" name="randomkey" type="hidden" />
        </form>
        
        <div id="source"><a href="?showSource#source">Voir le code source</a></div>
        
        <script type="text/javascript">
            document.getElementById('message').value = window.location.hash.substring(1) // Get it then…
            if(window.location.hash) window.location.hash = '' // Clean it (to avoid that someone share his private URL accidently when sharing the PickyPaste address)
        </script>
<?php

if(isset($_GET['showSource']))
{
    echo 
'<br />';
    
highlight_file(__FILE__);
}

?>
    </body>
</html>