Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add config file -- includes a lot of config options! #63

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
8a268f3
Add config.inc.php to dynamically generate expire times
ulikoehler Oct 8, 2013
937aa35
Fix syntax error
ulikoehler Oct 8, 2013
a69f2b2
Fix tpl variables
ulikoehler Oct 8, 2013
b30488b
Fix tpl errors
ulikoehler Oct 8, 2013
9f95b84
Fix never-expiration
ulikoehler Oct 8, 2013
d9ff124
Fix multiline comment style
ulikoehler Oct 8, 2013
aa59963
Added config option to enable or disable burn-after-reading checkbox …
ulikoehler Oct 8, 2013
5cf28cd
Fix burn-after-reading checkbox default selection
ulikoehler Oct 8, 2013
c19e5d2
Fix disabling of open discussion checkbox if burn-after-reading is di…
ulikoehler Oct 8, 2013
04f96b0
Added time between posts option
ulikoehler Oct 9, 2013
2cc138a
Fix variable scope
ulikoehler Oct 9, 2013
47ab138
Fix time between posts error message
ulikoehler Oct 9, 2013
8f72136
Fix time between posts error message
ulikoehler Oct 9, 2013
333eaed
Fix bracket indentation
ulikoehler Oct 9, 2013
6d9cb8e
Allow rate-limiting disable
ulikoehler Oct 9, 2013
5513eee
Implemented configurable maximum post size
ulikoehler Oct 9, 2013
38d0f83
Fix error message if maximum size is exceeded
ulikoehler Oct 9, 2013
6371488
Implemented configurable vizhash
ulikoehler Oct 10, 2013
77d188e
Fix vizhash in JS
ulikoehler Oct 10, 2013
f02d062
Added config option to disable discussion
ulikoehler Oct 10, 2013
439f80f
Made syntax highlighting optional
ulikoehler Oct 10, 2013
ed9991f
Disable syntax highlighting btn if disabled in cfg
ulikoehler Oct 10, 2013
d182ef3
Remove merge leftover
ulikoehler Oct 10, 2013
1b52926
Don't load highlighting CSS/JS if disabled
ulikoehler Oct 10, 2013
3e5c8b9
Fix not declared global, thanks @nitmir
ulikoehler Oct 28, 2013
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions config.inc.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php
/*
ZeroBin - a zero-knowledge paste bin
Please see project page: http://sebsauvage.net/wiki/doku.php?id=php:zerobin
*/

// Set each one of these to the number
// of seconds in the expiration period,
// or -1 if it shall never expire
$cfg["expire"]["5min"] = 5*60;
$cfg["expire"]["10min"] = 10*60;
$cfg["expire"]["1hour"] = 60*60;
$cfg["expire"]["1day"] = 24*60*60;
$cfg["expire"]["1week"] = 7*24*60*60;
$cfg["expire"]["1month"] = 30*24*60*60; // Well this is not *exactly* one month, it's 30 days.
$cfg["expire"]["1year"] = 365*24*60*60;
$cfg["expire"]["never"] = -1;

//Labels for the expiration times. Must match those in $cfg["expire"]
$cfg["expireLabels"]["5min"] = "5 minutes";
$cfg["expireLabels"]["10min"] = "10 minutes";
$cfg["expireLabels"]["1hour"] = "1 hour";
$cfg["expireLabels"]["1day"] = "1 day";
$cfg["expireLabels"]["1week"] = "1 week";
$cfg["expireLabels"]["1month"] = "1 month";
$cfg["expireLabels"]["1year"] = "1 year";
$cfg["expireLabels"]["never"] = "Never";

/*
* The expire value that is selected per default
* Make sure the value exists in $cfg["expire"]
*/
$cfg["expireSelected"] = "1month";

/* Default expiration time, if nothing or sth invalid is selected
* This is NOT the per-default selected option
* Make sure the value exists in $cfg["expire"]
*/
$cfg["expireDefault"] = "never";

/*
* Set this to true to default-select
* the burn-after-reading feature
*/
$cfg["burnAfterReadingSelected"] = false;

/*
* The time between two posts, in seconds
* from a single IP address.
* Set this to -1 to disable rate limiting.
*/
$cfg["timeBetweenPosts"] = 10;

/*
* The maximum post size in bytes.
* Default: 2 Mibibytes
*/
$cfg["maxPostSize"] = 2097152;

/*
* Whether to show the hash on-screen.
* Users selecting the text could copy
* the paste URL without hash if
* this is disabled, but it provides
* slightly higher security.
*/
$cfg["showHash"] = true;


/*
* Set this to false to disable the discussion system
*/
$cfg["enableDiscussionSystem"] = true;

/*
* Set this to false to disable syntax highlighting
*/
$cfg["enableSyntaxHighlighting"] = true;

?>
57 changes: 37 additions & 20 deletions index.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/
$VERSION='Alpha 0.19';
if (version_compare(PHP_VERSION, '5.2.6') < 0) die('ZeroBin requires php 5.2.6 or above to work. Sorry.');
require_once "config.inc.php";
require_once "lib/serversalt.php";
require_once "lib/vizhash_gd_zero.php";

Expand All @@ -21,6 +22,12 @@ function stripslashes_deep($value) { $value = is_array($value) ? array_map('stri
// Will return false if IP address made a call less than 10 seconds ago.
function trafic_limiter_canPass($ip)
{
global $cfg;
$timeBetweenPosts = $cfg["timeBetweenPosts"];
// -1: no rate limiting
if($timeBetweenPosts == -1) {
return true;
}
$tfilename='./data/trafic_limiter.php';
if (!is_file($tfilename))
{
Expand All @@ -29,7 +36,7 @@ function trafic_limiter_canPass($ip)
}
require $tfilename;
$tl=$GLOBALS['trafic_limiter'];
if (!empty($tl[$ip]) && ($tl[$ip]+10>=time()))
if (!empty($tl[$ip]) && ($tl[$ip] + $timeBetweenPosts >=time()))
{
return false;
// FIXME: purge file of expired IPs to keep it small
Expand Down Expand Up @@ -144,13 +151,17 @@ function deletePaste($pasteid)
}

// Make sure last paste from the IP address was more than 10 seconds ago.
if (!trafic_limiter_canPass($_SERVER['REMOTE_ADDR']))
{ echo json_encode(array('status'=>1,'message'=>'Please wait 10 seconds between each post.')); exit; }
if (!trafic_limiter_canPass($_SERVER['REMOTE_ADDR'])) {
$timeBetweenPosts = $cfg['timeBetweenPosts'];
echo json_encode(array('status'=>1,'message'=>"Please wait $timeBetweenPosts seconds between each post."));
exit;
}

// Make sure content is not too big.
$data = $_POST['data'];
if (strlen($data)>2000000)
{ echo json_encode(array('status'=>1,'message'=>'Paste is limited to 2 Mb of encrypted data.')); exit; }
$maxPostSize = $cfg["maxPostSize"];
if (strlen($data) > $maxPostSize)
{ echo json_encode(array('status'=>1,'message'=>"Paste is limited to $maxPostSize bytes of encrypted data.")); exit; }

// Make sure format is correct.
if (!validSJCL($data))
Expand All @@ -160,16 +171,20 @@ function deletePaste($pasteid)
$meta=array();

// Read expiration date
if (!empty($_POST['expire']))
{
$expire=$_POST['expire'];
if ($expire=='5min') $meta['expire_date']=time()+5*60;
elseif ($expire=='10min') $meta['expire_date']=time()+10*60;
elseif ($expire=='1hour') $meta['expire_date']=time()+60*60;
elseif ($expire=='1day') $meta['expire_date']=time()+24*60*60;
elseif ($expire=='1week') $meta['expire_date']=time()+7*24*60*60;
elseif ($expire=='1month') $meta['expire_date']=time()+30*24*60*60; // Well this is not *exactly* one month, it's 30 days.
elseif ($expire=='1year') $meta['expire_date']=time()+365*24*60*60;
$expire=$_POST['expire'];
if(array_key_exists($expire, $cfg["expire"])) {
// Valid expiration info
$expireDelay = $cfg["expire"][$expire];
if($expireDelay != -1) { // -1 means never
$meta['expire_date'] = time() + $expireDelay;
}
} else {
// Use default for an invalid POST expire name.
// Will also be executed for empty keys
$expireDelay = $cfg["expire"][$cfg["expireDefault"]];
if($expireDelay != -1) { // -1 means never
$meta['expire_date'] = time() + $expireDelay;
}
}

// Destroy the paste when it is read.
Expand All @@ -181,15 +196,15 @@ function deletePaste($pasteid)
}

// Read open discussion flag
if (!empty($_POST['opendiscussion']))
if (!empty($_POST['opendiscussion']) && $cfg["enableDiscussionSystem"])
{
$opendiscussion = $_POST['opendiscussion'];
if ($opendiscussion!='0' && $opendiscussion!='1') { $error=true; }
if ($opendiscussion!='0') { $meta['opendiscussion']=true; }
}

// Should we use syntax coloring when displaying ?
if (!empty($_POST['syntaxcoloring']))
if (!empty($_POST['syntaxcoloring']) && $cfg["enableSyntaxHighlighting"])
{
$syntaxcoloring = $_POST['syntaxcoloring'];
if ($syntaxcoloring!='0' && $syntaxcoloring!='1') { $error=true; }
Expand Down Expand Up @@ -287,7 +302,7 @@ function deletePaste($pasteid)
// The paste can be delete by calling http://myserver.com/zerobin/?pasteid=<pasteid>&deletetoken=<deletetoken>
$deletetoken = hash_hmac('sha1', $dataid , getServerSalt());

echo json_encode(array('status'=>0,'id'=>$dataid,'deletetoken'=>$deletetoken)); // 0 = no error
echo json_encode(array('status'=>0,'id'=>$dataid,'deletetoken'=>$deletetoken,'showHash'=>$cfg['showHash'])); // 0 = no error
exit;
}

Expand Down Expand Up @@ -324,6 +339,7 @@ function processPasteDelete($pasteid,$deletetoken)
*/
function processPasteFetch($pasteid)
{
global $cfg;
if (preg_match('/\A[a-f\d]{16}\z/',$pasteid)) // Is this a valid paste identifier ?
{
$filename = dataid2path($pasteid).$pasteid;
Expand Down Expand Up @@ -352,8 +368,8 @@ function processPasteFetch($pasteid)
if (property_exists($paste->meta, 'expire_date')) $paste->meta->remaining_time = $paste->meta->expire_date - time();

$messages = array($paste); // The paste itself is the first in the list of encrypted messages.
// If it's a discussion, get all comments.
if (property_exists($paste->meta, 'opendiscussion') && $paste->meta->opendiscussion)
// If it's a discussion, get all comments, unless discussions are disabled
if (property_exists($paste->meta, 'opendiscussion') && $paste->meta->opendiscussion && $cfg["enableDiscussionSystem"])
{
$comments=array();
$datadir = dataid2discussionpath($pasteid);
Expand Down Expand Up @@ -404,6 +420,7 @@ function processPasteFetch($pasteid)
require_once "lib/rain.tpl.class.php";
header('Content-Type: text/html; charset=utf-8');
$page = new RainTPL;
$page->assign('cfg',$cfg);
$page->assign('CIPHERDATA',htmlspecialchars($CIPHERDATA,ENT_NOQUOTES)); // We escape it here because ENT_NOQUOTES can't be used in RainTPL templates.
$page->assign('VERSION',$VERSION);
$page->assign('ERRORMESSAGE',$ERRORMESSAGE);
Expand Down
19 changes: 13 additions & 6 deletions js/zerobin.js
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,9 @@ function send_data() {
var deleteUrl = scriptLocation() + "?pasteid=" + data.id + '&deletetoken=' + data.deletetoken;
showStatus('');

$('div#pastelink').html('Your paste is <a id="pasteurl" href="' + url + '">' + url + '</a> <span id="copyhint">(Hit CTRL+C to copy)</span>');
//Only show the hash if enabled in config
var visibleURL = data.showHash ? url : scriptLocation() + "?" + data.id;
$('div#pastelink').html('Your paste is <a id="pasteurl" href="' + url + '">' + visibleURL + '</a> <span id="copyhint">(Hit CTRL+C to copy)</span>');
$('div#deletelink').html('<a href="' + deleteUrl + '">Delete link</a>');
$('div#pasteresult').show();
selectText('pasteurl'); // We pre-select the link so that the user only has to CTRL+C the link.
Expand Down Expand Up @@ -560,10 +562,9 @@ function pageKey() {
}

$(function() {

// If "burn after reading" is checked, disable discussion.
$('input#burnafterreading').change(function() {
if ($(this).is(':checked') ) {

function onBurnAfterReadingCheckboxChange() {
if ($("input#burnafterreading").is(':checked') ) {
$('div#opendisc').addClass('buttondisabled');
$('input#opendiscussion').attr({checked: false});
$('input#opendiscussion').attr('disabled',true);
Expand All @@ -572,7 +573,13 @@ $(function() {
$('div#opendisc').removeClass('buttondisabled');
$('input#opendiscussion').removeAttr('disabled');
}
});
}

// If "burn after reading" is checked, disable discussion.
$('input#burnafterreading').change(onBurnAfterReadingCheckboxChange);

// ...it might be enabled or disabled by default
onBurnAfterReadingCheckboxChange();

// Display status returned by php code if any (eg. Paste was properly deleted.)
if ($('div#status').text().length > 0) {
Expand Down
57 changes: 34 additions & 23 deletions tpl/page.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
<script src="js/rawdeflate.js?{$VERSION|rawurlencode}#"></script>
<script src="js/rawinflate.js?{$VERSION|rawurlencode}#"></script>
<script src="js/zerobin.js?{$VERSION|rawurlencode}#"></script>
<link type="text/css" rel="stylesheet" href="js/highlight.styles/monokai.css?{$VERSION|rawurlencode}#">
<script src="js/highlight.pack.js?{$VERSION|rawurlencode}#"></script>
{if condition="$cfg['enableSyntaxHighlighting']"}
<link type="text/css" rel="stylesheet" href="js/highlight.styles/monokai.css?{$VERSION|rawurlencode}#">
<script src="js/highlight.pack.js?{$VERSION|rawurlencode}#"></script>
{/if}

<!--[if lt IE 10]>
<style> body {padding-left:60px;padding-right:60px;} div#ienotice {display:block;} </style>
Expand Down Expand Up @@ -49,40 +51,49 @@ <h3>{$VERSION}</h3>
<button id="rawtextbutton" onclick="rawText();return false;" style="display:none; "><img src="img/icon_raw.png#" width="15" height="15" style="padding:1px 0px 1px 0px;"/>Raw text</button>
<div id="expiration" style="display:none;">Expires:
<select id="pasteExpiration" name="pasteExpiration">
<option value="5min">5 minutes</option>
<option value="10min">10 minutes</option>
<option value="1hour">1 hour</option>
<option value="1day">1 day</option>
<option value="1week">1 week</option>
<option value="1month" selected="selected">1 month</option>
<option value="1year">1 year</option>
<option value="never">Never</option>
{loop="$cfg['expireLabels']"}
{if condition="$cfg['expireSelected'] == $key"}
<option value="{$key}" selected="selected">{$value}</option>
{else}
<option value="{$key}">{$value}</option>
{/if}
{/loop}
</select>
</div>
<div id="remainingtime" style="display:none;"></div>
<div id="burnafterreadingoption" class="button" style="display:none;">
<input type="checkbox" id="burnafterreading" name="burnafterreading" />
{if condition="$cfg['burnAfterReadingSelected']"}
<input type="checkbox" id="burnafterreading" name="burnafterreading" checked="checked" />
{else}
<input type="checkbox" id="burnafterreading" name="burnafterreading" />
{/if}
<label for="burnafterreading">Burn after reading</label>
</div>
<div id="opendisc" class="button" style="display:none;">
<input type="checkbox" id="opendiscussion" name="opendiscussion" />
<label for="opendiscussion">Open discussion</label>
</div>
<div id="syntaxcoloringoption" class="button" style="display:none;">
<input type="checkbox" id="syntaxcoloring" name="syntaxcoloring" />
<label for="syntaxcoloring">Syntax coloring</label>
</div>
{if condition="$cfg['enableDiscussionSystem']"}
<div id="opendisc" class="button" style="display:none;">
<input type="checkbox" id="opendiscussion" name="opendiscussion" />
<label for="opendiscussion">Open discussion</label>
</div>
{/if}
{if condition="$cfg['enableSyntaxHighlighting']"}
<div id="syntaxcoloringoption" class="button" style="display:none;">
<input type="checkbox" id="syntaxcoloring" name="syntaxcoloring" />
<label for="syntaxcoloring">Syntax coloring</label>
</div>
{/if}
</div>
<div id="pasteresult" style="display:none;">
<div id="deletelink"></div>
<div id="pastelink"></div>
</div>
<div id="cleartext" style="display:none;"></div>
<textarea id="message" name="message" cols="80" rows="25" style="display:none;"></textarea>
<div id="discussion" style="display:none;">
<h4>Discussion</h4>
<div id="comments"></div>
</div>
{if condition="$cfg['enableDiscussionSystem']"}
<div id="discussion" style="display:none;">
<h4>Discussion</h4>
<div id="comments"></div>
</div>
{/if}
<div id="cipherdata" style="display:none;">{$CIPHERDATA}</div>
</body>
</html>