ZeroBin 0.17
* added deletion link. * small refactoring. * improved regex checks. * larger server alt on installation.
This commit is contained in:
parent
6c7de8aca8
commit
5b253cf77c
|
@ -5,7 +5,7 @@
|
||||||
; @link http://sebsauvage.net/wiki/doku.php?id=php:zerobin
|
; @link http://sebsauvage.net/wiki/doku.php?id=php:zerobin
|
||||||
; @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
; @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||||
; @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
; @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||||
; @version 0.15
|
; @version 0.17
|
||||||
|
|
||||||
[main]
|
[main]
|
||||||
; enable or disable discussions
|
; enable or disable discussions
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ZeroBin 0.15 - http://sebsauvage.net/wiki/doku.php?id=php:zerobin */
|
/* ZeroBin 0.17 - http://sebsauvage.net/wiki/doku.php?id=php:zerobin */
|
||||||
|
|
||||||
/* Hé, t'as vu Idleman, j'ai fait un effort sur les CSS ! ;-) */
|
|
||||||
|
|
||||||
/* CSS Reset from YUI 3.4.1 (build 4118) - Copyright 2011 Yahoo! Inc. All rights reserved.
|
/* CSS Reset from YUI 3.4.1 (build 4118) - Copyright 2011 Yahoo! Inc. All rights reserved.
|
||||||
Licensed under the BSD License. - http://yuilibrary.com/license/ */
|
Licensed under the BSD License. - http://yuilibrary.com/license/ */
|
||||||
|
@ -100,8 +99,7 @@ h3 {
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pasteresult {
|
||||||
#pastelink {
|
|
||||||
background-color: #1F2833;
|
background-color: #1F2833;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
padding: 4px 12px;
|
padding: 4px 12px;
|
||||||
|
@ -111,9 +109,11 @@ h3 {
|
||||||
box-shadow: inset 0 2px 2px #000;
|
box-shadow: inset 0 2px 2px #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pastelink a { color: #fff; }
|
#pasteresult a { color: #fff; }
|
||||||
|
|
||||||
#pastelink button { margin-left: 11px }
|
#pasteresult button { margin-left: 11px }
|
||||||
|
|
||||||
|
#deletelink { float: right; }
|
||||||
|
|
||||||
#toolbar, #status { margin-bottom: 5px; }
|
#toolbar, #status { margin-bottom: 5px; }
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* @link http://sebsauvage.net/wiki/doku.php?id=php:zerobin
|
* @link http://sebsauvage.net/wiki/doku.php?id=php:zerobin
|
||||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||||
* @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
* @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||||
* @version 0.15
|
* @version 0.17
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// change this, if your php files and data is outside of your webservers document root
|
// change this, if your php files and data is outside of your webservers document root
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* @link http://sebsauvage.net/wiki/doku.php?id=php:zerobin
|
* @link http://sebsauvage.net/wiki/doku.php?id=php:zerobin
|
||||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||||
* @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
* @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||||
* @version 0.15
|
* @version 0.17
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Immediately start random number generator collector.
|
// Immediately start random number generator collector.
|
||||||
|
@ -328,8 +328,13 @@ function send_data() {
|
||||||
if (data.status == 0) {
|
if (data.status == 0) {
|
||||||
stateExistingPaste();
|
stateExistingPaste();
|
||||||
var url = scriptLocation() + "?" + data.id + '#' + randomkey;
|
var url = scriptLocation() + "?" + data.id + '#' + randomkey;
|
||||||
|
var deleteUrl = scriptLocation() + "?pasteid=" + data.id + '&deletetoken=' + data.deletetoken;
|
||||||
showStatus('');
|
showStatus('');
|
||||||
$('div#pastelink').html('Your paste is <a href="' + url + '">' + url + '</a>').removeClass('hidden');
|
|
||||||
|
$('div#pastelink').html('Your paste is <a href="' + url + '">' + url + '</a>');
|
||||||
|
$('div#deletelink').html('<a href="' + deleteUrl + '">Delete link</a>');
|
||||||
|
$('div#pasteresult').show();
|
||||||
|
|
||||||
setElementText($('div#cleartext'), $('textarea#message').val());
|
setElementText($('div#cleartext'), $('textarea#message').val());
|
||||||
setElementText($('pre#prettyprint'), $('textarea#message').val());
|
setElementText($('pre#prettyprint'), $('textarea#message').val());
|
||||||
urls2links($('div#cleartext'));
|
urls2links($('div#cleartext'));
|
||||||
|
@ -357,7 +362,7 @@ function stateNewPaste() {
|
||||||
$('input#password').addClass('hidden'); //$('#password').removeClass('hidden');
|
$('input#password').addClass('hidden'); //$('#password').removeClass('hidden');
|
||||||
$('div#opendisc').removeClass('hidden');
|
$('div#opendisc').removeClass('hidden');
|
||||||
$('button#newbutton').removeClass('hidden');
|
$('button#newbutton').removeClass('hidden');
|
||||||
$('div#pastelink').addClass('hidden');
|
$('div#pasteresult').addClass('hidden');
|
||||||
$('textarea#message').text('');
|
$('textarea#message').text('');
|
||||||
$('textarea#message').removeClass('hidden');
|
$('textarea#message').removeClass('hidden');
|
||||||
$('div#cleartext').addClass('hidden');
|
$('div#cleartext').addClass('hidden');
|
||||||
|
@ -385,7 +390,7 @@ function stateExistingPaste() {
|
||||||
$('input#password').addClass('hidden');
|
$('input#password').addClass('hidden');
|
||||||
$('div#opendisc').addClass('hidden');
|
$('div#opendisc').addClass('hidden');
|
||||||
$('button#newbutton').removeClass('hidden');
|
$('button#newbutton').removeClass('hidden');
|
||||||
$('div#pastelink').addClass('hidden');
|
$('div#pasteresult').addClass('hidden');
|
||||||
$('textarea#message').addClass('hidden');
|
$('textarea#message').addClass('hidden');
|
||||||
$('div#cleartext').addClass('hidden');
|
$('div#cleartext').addClass('hidden');
|
||||||
$('div#prettymessage').removeClass('hidden');
|
$('div#prettymessage').removeClass('hidden');
|
||||||
|
@ -505,6 +510,14 @@ $(function() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Display status returned by php code if any (eg. Paste was properly deleted.)
|
||||||
|
if ($('div#status').text().length > 0) {
|
||||||
|
showStatus($('div#status').text(),false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$('div#status').html(' '); // Keep line height even if content empty.
|
||||||
|
|
||||||
// Display an existing paste
|
// Display an existing paste
|
||||||
if ($('div#cipherdata').text().length > 1) {
|
if ($('div#cipherdata').text().length > 1) {
|
||||||
// Missing decryption key in URL ?
|
// Missing decryption key in URL ?
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* ZeroBin
|
||||||
|
*
|
||||||
|
* a zero-knowledge paste bin
|
||||||
|
*
|
||||||
|
* @link http://sebsauvage.net/wiki/doku.php?id=php:zerobin
|
||||||
|
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||||
|
* @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||||
|
* @version 0.17
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* serversalt
|
||||||
|
*
|
||||||
|
* This is a random string which is unique to each ZeroBin installation.
|
||||||
|
* It is automatically created if not present.
|
||||||
|
*
|
||||||
|
* Salt is used:
|
||||||
|
* - to generate unique VizHash in discussions (which are not reproductible across ZeroBin servers)
|
||||||
|
* - to generate unique deletion token (which are not re-usable across ZeroBin servers)
|
||||||
|
*/
|
||||||
|
class serversalt extends persistence
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @access private
|
||||||
|
* @static
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private static $_salt = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* generate a large random hexadecimal salt
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @static
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function generate()
|
||||||
|
{
|
||||||
|
$randomSalt = '';
|
||||||
|
for($i=0; $i<16; ++$i) {
|
||||||
|
$randomSalt .= base_convert(mt_rand(), 10, 16);
|
||||||
|
}
|
||||||
|
self::$_salt = $randomSalt;
|
||||||
|
return self::$_salt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get server salt
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @static
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function get()
|
||||||
|
{
|
||||||
|
if (strlen(self::$_salt)) return self::$_salt;
|
||||||
|
|
||||||
|
$file = 'salt.php';
|
||||||
|
if (!self::_exists($file)) {
|
||||||
|
self::_store(
|
||||||
|
$file,
|
||||||
|
'<?php /* |'. self::generate() . '| */ ?>'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$items = explode('|', file_get_contents(self::getPath($file)));
|
||||||
|
self::$_salt = $items[1];
|
||||||
|
return $items[1];
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,15 +7,15 @@
|
||||||
* @link http://sebsauvage.net/wiki/doku.php?id=php:zerobin
|
* @link http://sebsauvage.net/wiki/doku.php?id=php:zerobin
|
||||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||||
* @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
* @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||||
* @version 0.15
|
* @version 0.17
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* traffic_limiter
|
* trafficlimiter
|
||||||
*
|
*
|
||||||
* Handles traffic limiting, so no user does more than one call per 10 seconds.
|
* Handles traffic limiting, so no user does more than one call per 10 seconds.
|
||||||
*/
|
*/
|
||||||
class trafficlimiter
|
class trafficlimiter extends persistence
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @access private
|
* @access private
|
||||||
|
@ -24,13 +24,6 @@ class trafficlimiter
|
||||||
*/
|
*/
|
||||||
private static $_limit = 10;
|
private static $_limit = 10;
|
||||||
|
|
||||||
/**
|
|
||||||
* @access private
|
|
||||||
* @static
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private static $_path = 'data';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set the time limit in seconds
|
* set the time limit in seconds
|
||||||
*
|
*
|
||||||
|
@ -44,19 +37,6 @@ class trafficlimiter
|
||||||
self::$_limit = $limit;
|
self::$_limit = $limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* set the path
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @static
|
|
||||||
* @param string $path
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public static function setPath($path)
|
|
||||||
{
|
|
||||||
self::$_path = $path;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* traffic limiter
|
* traffic limiter
|
||||||
*
|
*
|
||||||
|
@ -72,29 +52,18 @@ class trafficlimiter
|
||||||
// disable limits if set to less then 1
|
// disable limits if set to less then 1
|
||||||
if (self::$_limit < 1) return true;
|
if (self::$_limit < 1) return true;
|
||||||
|
|
||||||
// Create storage directory if it does not exist.
|
$file = 'traffic_limiter.php';
|
||||||
if (!is_dir(self::$_path)) mkdir(self::$_path, 0705);
|
if (!self::_exists($file))
|
||||||
// Create .htaccess file if it does not exist.
|
|
||||||
if (!is_file(self::$_path . '/.htaccess'))
|
|
||||||
{
|
{
|
||||||
file_put_contents(
|
self::_store(
|
||||||
self::$_path . '/.htaccess',
|
|
||||||
'Allow from none' . PHP_EOL .
|
|
||||||
'Deny from all'. PHP_EOL
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$file = self::$_path . '/traffic_limiter.php';
|
|
||||||
if (!is_file($file))
|
|
||||||
{
|
|
||||||
file_put_contents(
|
|
||||||
$file,
|
$file,
|
||||||
'<?php' . PHP_EOL .
|
'<?php' . PHP_EOL .
|
||||||
'$GLOBALS[\'traffic_limiter\'] = array();' . PHP_EOL
|
'$GLOBALS[\'traffic_limiter\'] = array();' . PHP_EOL
|
||||||
);
|
);
|
||||||
chmod($file, 0705);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
require $file;
|
$path = self::getPath($file);
|
||||||
|
require $path;
|
||||||
$now = time();
|
$now = time();
|
||||||
$tl = $GLOBALS['traffic_limiter'];
|
$tl = $GLOBALS['traffic_limiter'];
|
||||||
|
|
||||||
|
@ -114,7 +83,7 @@ class trafficlimiter
|
||||||
$tl[$ip] = time();
|
$tl[$ip] = time();
|
||||||
$result = true;
|
$result = true;
|
||||||
}
|
}
|
||||||
file_put_contents(
|
self::_store(
|
||||||
$file,
|
$file,
|
||||||
'<?php' . PHP_EOL .
|
'<?php' . PHP_EOL .
|
||||||
'$GLOBALS[\'traffic_limiter\'] = ' .
|
'$GLOBALS[\'traffic_limiter\'] = ' .
|
||||||
|
|
|
@ -1,16 +1,27 @@
|
||||||
<?php
|
<?php
|
||||||
// VizHash_GD 0.0.4 beta ZeroBin 0.15
|
/**
|
||||||
// Visual Hash implementation in php4+GD, stripped down and modified version for ZeroBin
|
* VizHash_GD
|
||||||
// See: http://sebsauvage.net/wiki/doku.php?id=php:vizhash_gd
|
*
|
||||||
// This is free software under the zlib/libpng licence
|
* Visual Hash implementation in php4+GD,
|
||||||
// http://www.opensource.org/licenses/zlib-license.php
|
* stripped down and modified version for ZeroBin
|
||||||
/* Example:
|
*
|
||||||
$vz = new vizhash16x16();
|
* @link http://sebsauvage.net/wiki/doku.php?id=php:vizhash_gd
|
||||||
$data = $vz->generate('hello');
|
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||||
header('Content-type: image/png');
|
* @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||||
echo $data;
|
* @version 0.0.4 beta ZeroBin 0.17
|
||||||
exit;
|
*/
|
||||||
*/
|
|
||||||
|
/**
|
||||||
|
* vizhash16x16
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* $vz = new vizhash16x16();
|
||||||
|
* $data = $vz->generate('hello');
|
||||||
|
* header('Content-type: image/png');
|
||||||
|
* echo $data;
|
||||||
|
* exit;
|
||||||
|
*/
|
||||||
|
|
||||||
class vizhash16x16
|
class vizhash16x16
|
||||||
{
|
{
|
||||||
private $VALUES;
|
private $VALUES;
|
||||||
|
@ -22,15 +33,7 @@ class vizhash16x16
|
||||||
{
|
{
|
||||||
$this->width=16;
|
$this->width=16;
|
||||||
$this->height=16;
|
$this->height=16;
|
||||||
|
$this->salt = serversalt::get();
|
||||||
// Read salt from file (and create it if does not exist).
|
|
||||||
// The salt will make vizhash avatar unique on each ZeroBin installation
|
|
||||||
// to prevent IP checking.
|
|
||||||
$saltfile = PATH . 'data/salt.php';
|
|
||||||
if (!is_file($saltfile))
|
|
||||||
file_put_contents($saltfile,'<?php /* |'.$this->randomSalt().'| */ ?>');
|
|
||||||
$items=explode('|',file_get_contents($saltfile));
|
|
||||||
$this->salt = $items[1];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate a 16x16 png corresponding to $text.
|
// Generate a 16x16 png corresponding to $text.
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* @link http://sebsauvage.net/wiki/doku.php?id=php:zerobin
|
* @link http://sebsauvage.net/wiki/doku.php?id=php:zerobin
|
||||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||||
* @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
* @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||||
* @version 0.15
|
* @version 0.17
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -20,7 +20,7 @@ class zerobin
|
||||||
/*
|
/*
|
||||||
* @const string version
|
* @const string version
|
||||||
*/
|
*/
|
||||||
const VERSION = 'Alpha 0.15';
|
const VERSION = 'Alpha 0.17';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @access private
|
* @access private
|
||||||
|
@ -42,6 +42,12 @@ class zerobin
|
||||||
*/
|
*/
|
||||||
private $_error = '';
|
private $_error = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @access private
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_status = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @access private
|
* @access private
|
||||||
* @var zerobin_data
|
* @var zerobin_data
|
||||||
|
@ -60,7 +66,7 @@ class zerobin
|
||||||
if (version_compare(PHP_VERSION, '5.2.6') < 0)
|
if (version_compare(PHP_VERSION, '5.2.6') < 0)
|
||||||
die('ZeroBin requires php 5.2.6 or above to work. Sorry.');
|
die('ZeroBin requires php 5.2.6 or above to work. Sorry.');
|
||||||
|
|
||||||
// In case stupid admin has left magic_quotes enabled in php.ini.
|
// in case stupid admin has left magic_quotes enabled in php.ini
|
||||||
if (get_magic_quotes_gpc())
|
if (get_magic_quotes_gpc())
|
||||||
{
|
{
|
||||||
$_POST = array_map('filter::stripslashes_deep', $_POST);
|
$_POST = array_map('filter::stripslashes_deep', $_POST);
|
||||||
|
@ -68,21 +74,26 @@ class zerobin
|
||||||
$_COOKIE = array_map('filter::stripslashes_deep', $_COOKIE);
|
$_COOKIE = array_map('filter::stripslashes_deep', $_COOKIE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load config from ini file.
|
// load config from ini file
|
||||||
$this->_init();
|
$this->_init();
|
||||||
|
|
||||||
// Create new paste or comment.
|
// create new paste or comment
|
||||||
if (!empty($_POST['data']))
|
if (!empty($_POST['data']))
|
||||||
{
|
{
|
||||||
$this->_create();
|
$this->_create($_POST['data']);
|
||||||
}
|
}
|
||||||
// Display an existing paste.
|
// delete an existing paste
|
||||||
|
elseif (!empty($_GET['deletetoken']) && !empty($_GET['pasteid']))
|
||||||
|
{
|
||||||
|
$this->_delete($_GET['pasteid'], $_GET['deletetoken']);
|
||||||
|
}
|
||||||
|
// display an existing paste
|
||||||
elseif (!empty($_SERVER['QUERY_STRING']))
|
elseif (!empty($_SERVER['QUERY_STRING']))
|
||||||
{
|
{
|
||||||
$this->_read();
|
$this->_read($_SERVER['QUERY_STRING']);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display ZeroBin frontend
|
// display ZeroBin frontend
|
||||||
$this->_view();
|
$this->_view();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +137,7 @@ class zerobin
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store new paste or comment.
|
* Store new paste or comment
|
||||||
*
|
*
|
||||||
* POST contains:
|
* POST contains:
|
||||||
* data (mandatory) = json encoded SJCL encrypted text (containing keys: iv,salt,ct)
|
* data (mandatory) = json encoded SJCL encrypted text (containing keys: iv,salt,ct)
|
||||||
|
@ -139,9 +150,10 @@ class zerobin
|
||||||
* pasteid (optional) = in discussion, which paste this comment belongs to.
|
* pasteid (optional) = in discussion, which paste this comment belongs to.
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
|
* @param string $data
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private function _create()
|
private function _create($data)
|
||||||
{
|
{
|
||||||
header('Content-type: application/json');
|
header('Content-type: application/json');
|
||||||
$error = false;
|
$error = false;
|
||||||
|
@ -159,7 +171,6 @@ class zerobin
|
||||||
);
|
);
|
||||||
|
|
||||||
// Make sure content is not too big.
|
// Make sure content is not too big.
|
||||||
$data = $_POST['data'];
|
|
||||||
if (
|
if (
|
||||||
strlen($data) > $this->_conf['main']['sizelimit']
|
strlen($data) > $this->_conf['main']['sizelimit']
|
||||||
) $this->_return_message(
|
) $this->_return_message(
|
||||||
|
@ -252,8 +263,8 @@ class zerobin
|
||||||
$pasteid = $_POST['pasteid'];
|
$pasteid = $_POST['pasteid'];
|
||||||
$parentid = $_POST['parentid'];
|
$parentid = $_POST['parentid'];
|
||||||
if (
|
if (
|
||||||
!preg_match('/[a-f\d]{16}/', $pasteid) ||
|
!preg_match('/\A[a-f\d]{16}\z/', $pasteid) ||
|
||||||
!preg_match('/[a-f\d]{16}/', $parentid)
|
!preg_match('/\A[a-f\d]{16}\z/', $parentid)
|
||||||
) $this->_return_message(1, 'Invalid data.');
|
) $this->_return_message(1, 'Invalid data.');
|
||||||
|
|
||||||
// Comments do not expire (it's the paste that expires)
|
// Comments do not expire (it's the paste that expires)
|
||||||
|
@ -297,23 +308,60 @@ class zerobin
|
||||||
$this->_model()->create($dataid, $storage) === false
|
$this->_model()->create($dataid, $storage) === false
|
||||||
) $this->_return_message(1, 'Error saving paste. Sorry.');
|
) $this->_return_message(1, 'Error saving paste. Sorry.');
|
||||||
|
|
||||||
|
// Generate the "delete" token.
|
||||||
|
// The token is the hmac of the pasteid signed with the server salt.
|
||||||
|
// The paste can be delete by calling http://myserver.com/zerobin/?pasteid=<pasteid>&deletetoken=<deletetoken>
|
||||||
|
$deletetoken = hash_hmac('sha1', $dataid , serversalt::get());
|
||||||
|
|
||||||
// 0 = no error
|
// 0 = no error
|
||||||
$this->_return_message(0, $dataid);
|
$this->_return_message(0, $dataid, array('deletetoken' => $deletetoken));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->_return_message(1, 'Server error.');
|
$this->_return_message(1, 'Server error.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete an existing paste
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param string $dataid
|
||||||
|
* @param string $deletetoken
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function _delete($dataid, $deletetoken)
|
||||||
|
{
|
||||||
|
// Is this a valid paste identifier?
|
||||||
|
if (preg_match('\A[a-f\d]{16}\z', $dataid))
|
||||||
|
{
|
||||||
|
// Check that paste exists.
|
||||||
|
if (!$this->_model()->exists($dataid))
|
||||||
|
{
|
||||||
|
$this->_error = 'Paste does not exist, has expired or has been deleted.';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure token is valid.
|
||||||
|
if ($deletetoken != hash_hmac('sha1', $dataid , serversalt::get()))
|
||||||
|
{
|
||||||
|
$this->_error = 'Wrong deletion token. Paste was not deleted.';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Paste exists and deletion token is valid: Delete the paste.
|
||||||
|
$this->_model()->delete($dataid);
|
||||||
|
$this->_status = 'Paste was properly deleted.';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read an existing paste or comment.
|
* Read an existing paste or comment
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
|
* @param string $dataid
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private function _read()
|
private function _read($dataid)
|
||||||
{
|
{
|
||||||
$dataid = $_SERVER['QUERY_STRING'];
|
|
||||||
|
|
||||||
// Is this a valid paste identifier?
|
// Is this a valid paste identifier?
|
||||||
if (preg_match('\A[a-f\d]{16}\z', $dataid))
|
if (preg_match('\A[a-f\d]{16}\z', $dataid))
|
||||||
{
|
{
|
||||||
|
@ -331,7 +379,7 @@ class zerobin
|
||||||
{
|
{
|
||||||
// Delete the paste
|
// Delete the paste
|
||||||
$this->_model()->delete($dataid);
|
$this->_model()->delete($dataid);
|
||||||
$this->_error = 'Paste does not exist or has expired.';
|
$this->_error = 'Paste does not exist, has expired or has been deleted.';
|
||||||
}
|
}
|
||||||
// If no error, return the paste.
|
// If no error, return the paste.
|
||||||
else
|
else
|
||||||
|
@ -398,7 +446,8 @@ class zerobin
|
||||||
$page = new RainTPL;
|
$page = new RainTPL;
|
||||||
// we escape it here because ENT_NOQUOTES can't be used in RainTPL templates
|
// we escape it here because ENT_NOQUOTES can't be used in RainTPL templates
|
||||||
$page->assign('CIPHERDATA', htmlspecialchars($this->_data, ENT_NOQUOTES));
|
$page->assign('CIPHERDATA', htmlspecialchars($this->_data, ENT_NOQUOTES));
|
||||||
$page->assign('ERRORMESSAGE', $this->_error);
|
$page->assign('ERROR', $this->_error);
|
||||||
|
$page->assign('STATUS', $this->_status);
|
||||||
$page->assign('VERSION', self::VERSION);
|
$page->assign('VERSION', self::VERSION);
|
||||||
$page->assign('BURNAFTERREADINGSELECTED', $this->_conf['main']['burnafterreadingselected']);
|
$page->assign('BURNAFTERREADINGSELECTED', $this->_conf['main']['burnafterreadingselected']);
|
||||||
$page->assign('OPENDISCUSSION', $this->_conf['main']['opendiscussion']);
|
$page->assign('OPENDISCUSSION', $this->_conf['main']['opendiscussion']);
|
||||||
|
@ -414,9 +463,10 @@ class zerobin
|
||||||
* @access private
|
* @access private
|
||||||
* @param bool $status
|
* @param bool $status
|
||||||
* @param string $message
|
* @param string $message
|
||||||
|
* @param array $other
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private function _return_message($status, $message)
|
private function _return_message($status, $message, $other = array())
|
||||||
{
|
{
|
||||||
$result = array('status' => $status);
|
$result = array('status' => $status);
|
||||||
if ($status)
|
if ($status)
|
||||||
|
@ -427,6 +477,7 @@ class zerobin
|
||||||
{
|
{
|
||||||
$result['id'] = $message;
|
$result['id'] = $message;
|
||||||
}
|
}
|
||||||
|
$result += $other;
|
||||||
exit(json_encode($result));
|
exit(json_encode($result));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,14 +43,14 @@
|
||||||
</header>
|
</header>
|
||||||
<section>
|
<section>
|
||||||
<article>
|
<article>
|
||||||
<div id="status"> </div>
|
<div id="status">{$STATUS|htmlspecialchars}</div>
|
||||||
<div id="errormessage" class="hidden">{$ERRORMESSAGE|htmlspecialchars}</div>
|
<div id="errormessage" class="hidden">{$ERROR|htmlspecialchars}</div>
|
||||||
<div id="toolbar">
|
<div id="toolbar">
|
||||||
<button id="newbutton" onclick="window.location.href=scriptLocation();return false;" class="hidden"><img src="img/icon_new.png#" width="11" height="15" alt="" />New</button>
|
<button id="newbutton" onclick="window.location.href=scriptLocation();return false;" class="hidden"><img src="img/icon_new.png#" width="11" height="15" alt="" />New</button>
|
||||||
<button id="sendbutton" onclick="send_data();return false;" class="hidden"><img src="img/icon_send.png#" width="18" height="15" alt="" />Send</button>
|
<button id="sendbutton" onclick="send_data();return false;" class="hidden"><img src="img/icon_send.png#" width="18" height="15" alt="" />Send</button>
|
||||||
<button id="clonebutton" onclick="clonePaste();return false;" class="hidden"><img src="img/icon_clone.png#" width="15" height="17" alt="" />Clone</button>
|
<button id="clonebutton" onclick="clonePaste();return false;" class="hidden"><img src="img/icon_clone.png#" width="15" height="17" alt="" />Clone</button>
|
||||||
<div id="expiration" class="hidden">Expire:
|
<div id="expiration" class="hidden">Expire:
|
||||||
<select id="pasteExpiration" name="pasteExpiration">
|
<select id="pasteExpiration" name="pasteExpiration">
|
||||||
<option value="burn"{if="$BURNAFTERREADINGSELECTED"} selected="selected"{/if}>Burn after reading</option>{loop="EXPIRE"}
|
<option value="burn"{if="$BURNAFTERREADINGSELECTED"} selected="selected"{/if}>Burn after reading</option>{loop="EXPIRE"}
|
||||||
<option value="{$key}"{if="!$BURNAFTERREADINGSELECTED && $key == $EXPIREDEFAULT"} selected="selected"{/if}>{$value}</option>{/loop}
|
<option value="{$key}"{if="!$BURNAFTERREADINGSELECTED && $key == $EXPIREDEFAULT"} selected="selected"{/if}>{$value}</option>{/loop}
|
||||||
</select>
|
</select>
|
||||||
|
@ -70,7 +70,10 @@
|
||||||
<label for="opendiscussion">Open discussion</label>
|
<label for="opendiscussion">Open discussion</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="pastelink" class="hidden"></div>
|
<div id="pasteresult" style="display:none;">
|
||||||
|
<div id="deletelink"></div>
|
||||||
|
<div id="pastelink"></div>
|
||||||
|
</div>
|
||||||
<div id="prettymessage" class="hidden">
|
<div id="prettymessage" class="hidden">
|
||||||
<pre id="prettyprint" class="prettyprint linenums:1"></pre>
|
<pre id="prettyprint" class="prettyprint linenums:1"></pre>
|
||||||
</div>
|
</div>
|
||||||
|
@ -85,5 +88,5 @@
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<div id="cipherdata" class="hidden">{$CIPHERDATA}</div>
|
<div id="cipherdata" class="hidden">{$CIPHERDATA}</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -5,6 +5,8 @@ class RainTPLTest extends PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
private static $error = 'foo bar';
|
private static $error = 'foo bar';
|
||||||
|
|
||||||
|
private static $status = '!*#@?$+';
|
||||||
|
|
||||||
private static $expire = array(
|
private static $expire = array(
|
||||||
'5min' => '5 minutes',
|
'5min' => '5 minutes',
|
||||||
'1hour' => '1 hour',
|
'1hour' => '1 hour',
|
||||||
|
@ -26,7 +28,8 @@ class RainTPLTest extends PHPUnit_Framework_TestCase
|
||||||
$page = new RainTPL;
|
$page = new RainTPL;
|
||||||
// We escape it here because ENT_NOQUOTES can't be used in RainTPL templates.
|
// We escape it here because ENT_NOQUOTES can't be used in RainTPL templates.
|
||||||
$page->assign('CIPHERDATA', htmlspecialchars(self::$data, ENT_NOQUOTES));
|
$page->assign('CIPHERDATA', htmlspecialchars(self::$data, ENT_NOQUOTES));
|
||||||
$page->assign('ERRORMESSAGE', self::$error);
|
$page->assign('ERROR', self::$error);
|
||||||
|
$page->assign('STATUS', self::$status);
|
||||||
$page->assign('VERSION', self::$version);
|
$page->assign('VERSION', self::$version);
|
||||||
$page->assign('BURNAFTERREADINGSELECTED', false);
|
$page->assign('BURNAFTERREADINGSELECTED', false);
|
||||||
$page->assign('OPENDISCUSSION', false);
|
$page->assign('OPENDISCUSSION', false);
|
||||||
|
|
|
@ -6,14 +6,14 @@ class trafficlimiterTest extends PHPUnit_Framework_TestCase
|
||||||
public function setUp()
|
public function setUp()
|
||||||
{
|
{
|
||||||
/* Setup Routine */
|
/* Setup Routine */
|
||||||
$this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'trafficlimit' . DIRECTORY_SEPARATOR;
|
$this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'trafficlimit';
|
||||||
trafficlimiter::setPath($this->_path);
|
trafficlimiter::setPath($this->_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function tearDown()
|
public function tearDown()
|
||||||
{
|
{
|
||||||
/* Tear Down Routine */
|
/* Tear Down Routine */
|
||||||
helper::rmdir($this->_path);
|
helper::rmdir($this->_path . DIRECTORY_SEPARATOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testTrafficGetsLimited()
|
public function testTrafficGetsLimited()
|
||||||
|
|
Loading…
Reference in New Issue