parent
61903665df
commit
106141efa4
|
@ -17,6 +17,9 @@ opendiscussion = false
|
||||||
; enable or disable the password feature, defaults to true
|
; enable or disable the password feature, defaults to true
|
||||||
password = true
|
password = true
|
||||||
|
|
||||||
|
; enable or disable the file upload feature, defaults to false
|
||||||
|
fileupload = false
|
||||||
|
|
||||||
; preselect the burn-after-reading feature, defaults to false
|
; preselect the burn-after-reading feature, defaults to false
|
||||||
burnafterreadingselected = false
|
burnafterreadingselected = false
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ body {
|
||||||
padding-right: 60px;
|
padding-right: 60px;
|
||||||
}
|
}
|
||||||
|
|
||||||
a { color: #0f388f; }
|
a { color: #0f388f; cursor:pointer; }
|
||||||
|
|
||||||
h1.title {
|
h1.title {
|
||||||
font-size: 3.5em;
|
font-size: 3.5em;
|
||||||
|
@ -76,7 +76,7 @@ h3.title {
|
||||||
|
|
||||||
#aboutbox a { color: #94a3b4; }
|
#aboutbox a { color: #94a3b4; }
|
||||||
|
|
||||||
#message, #cleartext, #prettymessage, .replymessage {
|
#message, #cleartext, #prettymessage, #attachment, .replymessage {
|
||||||
clear: both;
|
clear: both;
|
||||||
color: #000;
|
color: #000;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
|
|
|
@ -127,5 +127,12 @@
|
||||||
"Format": "Format",
|
"Format": "Format",
|
||||||
"Plain Text": "Nur Text",
|
"Plain Text": "Nur Text",
|
||||||
"Source Code": "Quellcode",
|
"Source Code": "Quellcode",
|
||||||
"Markdown": "Markdown"
|
"Markdown": "Markdown",
|
||||||
|
"Download attachment": "Anhang herunterladen",
|
||||||
|
"Cloned file attached.": "Kopierte Datei angehängt.",
|
||||||
|
"Attach a file:": "Datei anhängen:",
|
||||||
|
"Remove attachment": "Anhang entfernen",
|
||||||
|
"Your browser does not support uploading encrypted files. Please use a newer browser.":
|
||||||
|
"Dein Browser unterstützt das hochladen von verschlüsselten Dateien nicht. Bitte verwende einen neueren Browser.",
|
||||||
|
"Invalid attachment.": "Ungültiger Datei-Anhang."
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,5 +136,12 @@
|
||||||
"Format": "Format",
|
"Format": "Format",
|
||||||
"Plain Text": "texte",
|
"Plain Text": "texte",
|
||||||
"Source Code": "code source",
|
"Source Code": "code source",
|
||||||
"Markdown": "Markdown"
|
"Markdown": "Markdown",
|
||||||
|
"Download attachment": "Download attachment",
|
||||||
|
"Cloned file attached.": "Cloned file attached.",
|
||||||
|
"Attach a file:": "Attach a file:",
|
||||||
|
"Remove attachment": "Remove attachment",
|
||||||
|
"Your browser does not support uploading encrypted files. Please use a newer browser.":
|
||||||
|
"Your browser does not support uploading encrypted files. Please use a newer browser.",
|
||||||
|
"Invalid attachment.": "Invalid attachment."
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,5 +127,12 @@
|
||||||
"Format": "Format",
|
"Format": "Format",
|
||||||
"Plain Text": "Plain Text",
|
"Plain Text": "Plain Text",
|
||||||
"Source Code": "Source Code",
|
"Source Code": "Source Code",
|
||||||
"Markdown": "Markdown"
|
"Markdown": "Markdown",
|
||||||
|
"Download attachment": "Download attachment",
|
||||||
|
"Cloned file attached.": "Cloned file attached.",
|
||||||
|
"Attach a file:": "Attach a file:",
|
||||||
|
"Remove attachment": "Remove attachment",
|
||||||
|
"Your browser does not support uploading encrypted files. Please use a newer browser.":
|
||||||
|
"Your browser does not support uploading encrypted files. Please use a newer browser.",
|
||||||
|
"Invalid attachment.": "Invalid attachment."
|
||||||
}
|
}
|
||||||
|
|
|
@ -585,6 +585,15 @@ $(function() {
|
||||||
}
|
}
|
||||||
if (cleartext.length == 0) throw 'failed to decipher message';
|
if (cleartext.length == 0) throw 'failed to decipher message';
|
||||||
this.passwordInput.val(password);
|
this.passwordInput.val(password);
|
||||||
|
if (comments[0].attachment)
|
||||||
|
{
|
||||||
|
var attachment = filter.decipher(key, password, comments[0].attachment);
|
||||||
|
if (attachment)
|
||||||
|
{
|
||||||
|
this.attachmentLink.attr('href', attachment);
|
||||||
|
this.attachment.removeClass('hidden');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
helper.setElementText(this.clearText, cleartext);
|
helper.setElementText(this.clearText, cleartext);
|
||||||
helper.setElementText(this.prettyPrint, cleartext);
|
helper.setElementText(this.prettyPrint, cleartext);
|
||||||
|
@ -799,9 +808,10 @@ $(function() {
|
||||||
sendData: function(event)
|
sendData: function(event)
|
||||||
{
|
{
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
var files = document.getElementById('file').files; // FileList object
|
||||||
|
|
||||||
// Do not send if no data.
|
// Do not send if no data.
|
||||||
if (this.message.val().length == 0) return;
|
if (this.message.val().length == 0 && !(files && files[0])) return;
|
||||||
|
|
||||||
// If sjcl has not collected enough entropy yet, display a message.
|
// If sjcl has not collected enough entropy yet, display a message.
|
||||||
if (!sjcl.random.isReady())
|
if (!sjcl.random.isReady())
|
||||||
|
@ -818,6 +828,48 @@ $(function() {
|
||||||
this.showStatus(i18n._('Sending paste...'), true);
|
this.showStatus(i18n._('Sending paste...'), true);
|
||||||
|
|
||||||
var randomkey = sjcl.codec.base64.fromBits(sjcl.random.randomWords(8, 0), 0);
|
var randomkey = sjcl.codec.base64.fromBits(sjcl.random.randomWords(8, 0), 0);
|
||||||
|
var cipherdata_attachment;
|
||||||
|
var password = this.passwordInput.val();
|
||||||
|
if(files && files[0])
|
||||||
|
{
|
||||||
|
if(typeof FileReader === undefined)
|
||||||
|
{
|
||||||
|
this.showError(i18n._('Your browser does not support uploading encrypted files. Please use a newer browser.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var reader = new FileReader();
|
||||||
|
// Closure to capture the file information.
|
||||||
|
reader.onload = (function(theFile)
|
||||||
|
{
|
||||||
|
return function(e) {
|
||||||
|
zerobin.sendDataContinue(
|
||||||
|
randomkey,
|
||||||
|
filter.cipher(randomkey, password, e.target.result)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})(files[0]);
|
||||||
|
reader.readAsDataURL(files[0]);
|
||||||
|
}
|
||||||
|
else if(this.attachmentLink.attr('href'))
|
||||||
|
{
|
||||||
|
this.sendDataContinue(
|
||||||
|
randomkey,
|
||||||
|
filter.cipher(randomkey, password, this.attachmentLink.attr('href'))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.sendDataContinue(randomkey, '');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a new paste to server, step 2
|
||||||
|
*
|
||||||
|
* @param Event event
|
||||||
|
*/
|
||||||
|
sendDataContinue: function(randomkey, cipherdata_attachment)
|
||||||
|
{
|
||||||
var cipherdata = filter.cipher(randomkey, this.passwordInput.val(), this.message.val());
|
var cipherdata = filter.cipher(randomkey, this.passwordInput.val(), this.message.val());
|
||||||
var data_to_send = {
|
var data_to_send = {
|
||||||
data: cipherdata,
|
data: cipherdata,
|
||||||
|
@ -826,6 +878,10 @@ $(function() {
|
||||||
burnafterreading: this.burnAfterReading.is(':checked') ? 1 : 0,
|
burnafterreading: this.burnAfterReading.is(':checked') ? 1 : 0,
|
||||||
opendiscussion: this.openDiscussion.is(':checked') ? 1 : 0
|
opendiscussion: this.openDiscussion.is(':checked') ? 1 : 0
|
||||||
};
|
};
|
||||||
|
if (cipherdata_attachment.length > 0)
|
||||||
|
{
|
||||||
|
data_to_send.attachment = cipherdata_attachment;
|
||||||
|
}
|
||||||
$.post(this.scriptLocation(), data_to_send, function(data)
|
$.post(this.scriptLocation(), data_to_send, function(data)
|
||||||
{
|
{
|
||||||
if (data.status == 0) {
|
if (data.status == 0) {
|
||||||
|
@ -880,6 +936,8 @@ $(function() {
|
||||||
this.openDisc.removeClass('hidden');
|
this.openDisc.removeClass('hidden');
|
||||||
this.newButton.removeClass('hidden');
|
this.newButton.removeClass('hidden');
|
||||||
this.password.removeClass('hidden');
|
this.password.removeClass('hidden');
|
||||||
|
this.attach.removeClass('hidden');
|
||||||
|
this.attachment.removeClass('hidden');
|
||||||
this.message.removeClass('hidden');
|
this.message.removeClass('hidden');
|
||||||
this.message.focus();
|
this.message.focus();
|
||||||
},
|
},
|
||||||
|
@ -902,6 +960,8 @@ $(function() {
|
||||||
}
|
}
|
||||||
this.rawTextButton.removeClass('hidden');
|
this.rawTextButton.removeClass('hidden');
|
||||||
|
|
||||||
|
this.attach.addClass('hidden');
|
||||||
|
this.attachment.addClass('hidden');
|
||||||
this.expiration.addClass('hidden');
|
this.expiration.addClass('hidden');
|
||||||
this.formatter.addClass('hidden');
|
this.formatter.addClass('hidden');
|
||||||
this.burnAfterReadingOption.addClass('hidden');
|
this.burnAfterReadingOption.addClass('hidden');
|
||||||
|
@ -969,6 +1029,11 @@ $(function() {
|
||||||
history.replaceState(document.title, document.title, this.scriptLocation());
|
history.replaceState(document.title, document.title, this.scriptLocation());
|
||||||
|
|
||||||
this.showStatus('', false);
|
this.showStatus('', false);
|
||||||
|
if (this.attachmentLink.attr('href'))
|
||||||
|
{
|
||||||
|
this.clonedFile.removeClass('hidden');
|
||||||
|
this.fileWrap.addClass('hidden');
|
||||||
|
}
|
||||||
this.message.text(this.clearText.text());
|
this.message.text(this.clearText.text());
|
||||||
$('.navbar-toggle').click();
|
$('.navbar-toggle').click();
|
||||||
},
|
},
|
||||||
|
@ -984,6 +1049,19 @@ $(function() {
|
||||||
$('.navbar-toggle').click();
|
$('.navbar-toggle').click();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes an attachment.
|
||||||
|
*/
|
||||||
|
removeAttachment: function()
|
||||||
|
{
|
||||||
|
this.clonedFile.addClass('hidden');
|
||||||
|
// removes the saved decrypted file data
|
||||||
|
$('#attachment a').attr('href', '');
|
||||||
|
// the only way to deselect the file is to recreate the input
|
||||||
|
this.fileWrap.html(this.fileWrap.html());
|
||||||
|
this.fileWrap.removeClass('hidden');
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display an error message
|
* Display an error message
|
||||||
* (We use the same function for paste and reply to comments)
|
* (We use the same function for paste and reply to comments)
|
||||||
|
@ -1042,6 +1120,7 @@ $(function() {
|
||||||
this.sendButton.click($.proxy(this.sendData, this));
|
this.sendButton.click($.proxy(this.sendData, this));
|
||||||
this.cloneButton.click($.proxy(this.clonePaste, this));
|
this.cloneButton.click($.proxy(this.clonePaste, this));
|
||||||
this.rawTextButton.click($.proxy(this.rawText, this));
|
this.rawTextButton.click($.proxy(this.rawText, this));
|
||||||
|
this.fileRemoveButton.click($.proxy(this.removeAttachment, this));
|
||||||
$('.reloadlink').click($.proxy(this.reloadPage, this));
|
$('.reloadlink').click($.proxy(this.reloadPage, this));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1054,15 +1133,21 @@ $(function() {
|
||||||
$('#noscript').hide();
|
$('#noscript').hide();
|
||||||
|
|
||||||
// preload jQuery wrapped DOM elements and bind events
|
// preload jQuery wrapped DOM elements and bind events
|
||||||
|
this.attach = $('#attach');
|
||||||
|
this.attachment = $('#attachment');
|
||||||
|
this.attachmentLink = $('#attachment a');
|
||||||
this.burnAfterReading = $('#burnafterreading');
|
this.burnAfterReading = $('#burnafterreading');
|
||||||
this.burnAfterReadingOption = $('#burnafterreadingoption');
|
this.burnAfterReadingOption = $('#burnafterreadingoption');
|
||||||
this.cipherData = $('#cipherdata');
|
this.cipherData = $('#cipherdata');
|
||||||
this.clearText = $('#cleartext');
|
this.clearText = $('#cleartext');
|
||||||
this.cloneButton = $('#clonebutton');
|
this.cloneButton = $('#clonebutton');
|
||||||
|
this.clonedFile = $('#clonedfile');
|
||||||
this.comments = $('#comments');
|
this.comments = $('#comments');
|
||||||
this.discussion = $('#discussion');
|
this.discussion = $('#discussion');
|
||||||
this.errorMessage = $('#errormessage');
|
this.errorMessage = $('#errormessage');
|
||||||
this.expiration = $('#expiration');
|
this.expiration = $('#expiration');
|
||||||
|
this.fileRemoveButton = $('#fileremovebutton');
|
||||||
|
this.fileWrap = $('#filewrap');
|
||||||
this.formatter = $('#formatter');
|
this.formatter = $('#formatter');
|
||||||
this.message = $('#message');
|
this.message = $('#message');
|
||||||
this.newButton = $('#newbutton');
|
this.newButton = $('#newbutton');
|
||||||
|
|
|
@ -116,9 +116,12 @@ class zerobin
|
||||||
$this->_init();
|
$this->_init();
|
||||||
|
|
||||||
// create new paste or comment
|
// create new paste or comment
|
||||||
if (!empty($_POST['data']))
|
if (
|
||||||
|
(array_key_exists('data', $_POST) && !empty($_POST['data'])) ||
|
||||||
|
(array_key_exists('attachment', $_POST) && !empty($_POST['attachment']))
|
||||||
|
)
|
||||||
{
|
{
|
||||||
$this->_create($_POST['data']);
|
$this->_create();
|
||||||
}
|
}
|
||||||
// delete an existing paste
|
// delete an existing paste
|
||||||
elseif (!empty($_GET['deletetoken']) && !empty($_GET['pasteid']))
|
elseif (!empty($_GET['deletetoken']) && !empty($_GET['pasteid']))
|
||||||
|
@ -191,24 +194,30 @@ class zerobin
|
||||||
/**
|
/**
|
||||||
* Store new paste or comment
|
* Store new paste or comment
|
||||||
*
|
*
|
||||||
* POST contains:
|
* POST contains one or both:
|
||||||
* data (mandatory) = json encoded SJCL encrypted text (containing keys: iv,v,iter,ks,ts,mode,adata,cipher,salt,ct)
|
* data = json encoded SJCL encrypted text (containing keys: iv,v,iter,ks,ts,mode,adata,cipher,salt,ct)
|
||||||
|
* attachment = json encoded SJCL encrypted text (containing keys: iv,v,iter,ks,ts,mode,adata,cipher,salt,ct)
|
||||||
*
|
*
|
||||||
* All optional data will go to meta information:
|
* All optional data will go to meta information:
|
||||||
* expire (optional) = expiration delay (never,5min,10min,1hour,1day,1week,1month,1year,burn) (default:never)
|
* expire (optional) = expiration delay (never,5min,10min,1hour,1day,1week,1month,1year,burn) (default:never)
|
||||||
|
* formatter (optional) = format to display the paste as (plaintext,syntaxhighlighting,markdown) (default:syntaxhighlighting)
|
||||||
|
* burnafterreading (optional) = if this paste may only viewed once ? (0/1) (default:0)
|
||||||
* opendiscusssion (optional) = is the discussion allowed on this paste ? (0/1) (default:0)
|
* opendiscusssion (optional) = is the discussion allowed on this paste ? (0/1) (default:0)
|
||||||
* nickname (optional) = in discussion, encoded SJCL encrypted text nickname of author of comment (containing keys: iv,v,iter,ks,ts,mode,adata,cipher,salt,ct)
|
* nickname (optional) = in discussion, encoded SJCL encrypted text nickname of author of comment (containing keys: iv,v,iter,ks,ts,mode,adata,cipher,salt,ct)
|
||||||
* parentid (optional) = in discussion, which comment this comment replies to.
|
* parentid (optional) = in discussion, which comment this comment replies to.
|
||||||
* 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 string
|
* @return string
|
||||||
*/
|
*/
|
||||||
private function _create($data)
|
private function _create()
|
||||||
{
|
{
|
||||||
$error = false;
|
$error = false;
|
||||||
|
|
||||||
|
$has_attachment = array_key_exists('attachment', $_POST);
|
||||||
|
$data = array_key_exists('data', $_POST) ? $_POST['data'] : '';
|
||||||
|
$attachment = $has_attachment ? $_POST['attachment'] : '';
|
||||||
|
|
||||||
// Make sure last paste from the IP address was more than X seconds ago.
|
// Make sure last paste from the IP address was more than X seconds ago.
|
||||||
trafficlimiter::setLimit($this->_conf['traffic']['limit']);
|
trafficlimiter::setLimit($this->_conf['traffic']['limit']);
|
||||||
trafficlimiter::setPath($this->_conf['traffic']['dir']);
|
trafficlimiter::setPath($this->_conf['traffic']['dir']);
|
||||||
|
@ -226,7 +235,7 @@ class zerobin
|
||||||
|
|
||||||
// Make sure content is not too big.
|
// Make sure content is not too big.
|
||||||
$sizelimit = (int) $this->_getMainConfig('sizelimit', 2097152);
|
$sizelimit = (int) $this->_getMainConfig('sizelimit', 2097152);
|
||||||
if (strlen($data) > $sizelimit)
|
if (strlen($data) + strlen($attachment) > $sizelimit)
|
||||||
{
|
{
|
||||||
$this->_return_message(
|
$this->_return_message(
|
||||||
1,
|
1,
|
||||||
|
@ -241,6 +250,15 @@ class zerobin
|
||||||
// Make sure format is correct.
|
// Make sure format is correct.
|
||||||
if (!sjcl::isValid($data)) return $this->_return_message(1, 'Invalid data.');
|
if (!sjcl::isValid($data)) return $this->_return_message(1, 'Invalid data.');
|
||||||
|
|
||||||
|
// Make sure attachments are enabled and format is correct.
|
||||||
|
if($has_attachment)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
!$this->_getMainConfig('fileupload', false) ||
|
||||||
|
!sjcl::isValid($attachment)
|
||||||
|
) $this->_return_message(1, 'Invalid attachment.');
|
||||||
|
}
|
||||||
|
|
||||||
// Read additional meta-information.
|
// Read additional meta-information.
|
||||||
$meta = array();
|
$meta = array();
|
||||||
|
|
||||||
|
@ -416,6 +434,9 @@ class zerobin
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add attachment if one was sent
|
||||||
|
if($has_attachment) $storage['attachment'] = $attachment;
|
||||||
|
|
||||||
// New paste
|
// New paste
|
||||||
if (
|
if (
|
||||||
$this->_model()->create($dataid, $storage) === false
|
$this->_model()->create($dataid, $storage) === false
|
||||||
|
@ -634,6 +655,7 @@ class zerobin
|
||||||
$page->assign('NOTICE', i18n::_($this->_getMainConfig('notice', '')));
|
$page->assign('NOTICE', i18n::_($this->_getMainConfig('notice', '')));
|
||||||
$page->assign('BURNAFTERREADINGSELECTED', $this->_getMainConfig('burnafterreadingselected', false));
|
$page->assign('BURNAFTERREADINGSELECTED', $this->_getMainConfig('burnafterreadingselected', false));
|
||||||
$page->assign('PASSWORD', $this->_getMainConfig('password', true));
|
$page->assign('PASSWORD', $this->_getMainConfig('password', true));
|
||||||
|
$page->assign('FILEUPLOAD', $this->_getMainConfig('fileupload', false));
|
||||||
$page->assign('BASE64JSVERSION', $this->_getMainConfig('base64version', '2.1.9'));
|
$page->assign('BASE64JSVERSION', $this->_getMainConfig('base64version', '2.1.9'));
|
||||||
$page->assign('EXPIRE', $expire);
|
$page->assign('EXPIRE', $expire);
|
||||||
$page->assign('EXPIREDEFAULT', $this->_conf['expire']['default']);
|
$page->assign('EXPIREDEFAULT', $this->_conf['expire']['default']);
|
||||||
|
|
|
@ -74,7 +74,13 @@
|
||||||
<div id="pasteresult" class="hidden">
|
<div id="pasteresult" class="hidden">
|
||||||
<div id="deletelink"></div>
|
<div id="deletelink"></div>
|
||||||
<div id="pastelink"></div>
|
<div id="pastelink"></div>
|
||||||
</div>
|
</div>{if="$FILEUPLOAD"}
|
||||||
|
<div id="attachment" class="hidden"><a>{function="t('Download attachment')"}</a></div>
|
||||||
|
<div id="attach" class="hidden">
|
||||||
|
<span id="clonedfile" class="hidden">{function="t('Cloned file attached.')"}</span>
|
||||||
|
<span id="filewrap">{function="t('Attach a file:')"} <input type="file" id="file" name="file" /></span>
|
||||||
|
<button id="fileremovebutton">{function="t('Remove attachment')"}</button>
|
||||||
|
</div>{/if}
|
||||||
<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>
|
||||||
|
|
|
@ -38,6 +38,7 @@ class RainTPLTest extends PHPUnit_Framework_TestCase
|
||||||
$page->assign('SYNTAXHIGHLIGHTINGTHEME', 'sons-of-obsidian');
|
$page->assign('SYNTAXHIGHLIGHTINGTHEME', 'sons-of-obsidian');
|
||||||
$page->assign('BURNAFTERREADINGSELECTED', false);
|
$page->assign('BURNAFTERREADINGSELECTED', false);
|
||||||
$page->assign('PASSWORD', true);
|
$page->assign('PASSWORD', true);
|
||||||
|
$page->assign('FILEUPLOAD', false);
|
||||||
$page->assign('BASE64JSVERSION', '2.1.9');
|
$page->assign('BASE64JSVERSION', '2.1.9');
|
||||||
$page->assign('NOTICE', 'example');
|
$page->assign('NOTICE', 'example');
|
||||||
$page->assign('EXPIRE', self::$expire);
|
$page->assign('EXPIRE', self::$expire);
|
||||||
|
|
Loading…
Reference in New Issue