Merge branch 'attachment-handling' of https://github.com/thororm/PrivateBin into thororm-attachment-handling

apart from resolving conflicts:
- added missing docs
- inlined functions that were used in only one location
- updated unit test to support all previews
- fixed a regression that displayed the preview even when there was no preview and too early
pull/308/head
El RIDO 6 years ago
commit 2c82279292
No known key found for this signature in database
GPG Key ID: 0F5C940A6BD81F92

@ -73,7 +73,7 @@ languageselection = false
; scripts or run your site behind certain DDoS-protection services. ; scripts or run your site behind certain DDoS-protection services.
; Check the documentation at https://content-security-policy.com/ ; Check the documentation at https://content-security-policy.com/
; Note: If you use a bootstrap theme, you can remove the allow-popups from the sandbox restrictions. ; Note: If you use a bootstrap theme, you can remove the allow-popups from the sandbox restrictions.
; cspheader = "default-src 'none'; manifest-src 'self'; connect-src *; form-action 'none'; script-src 'self'; style-src 'self'; font-src 'self'; img-src 'self' data:; referrer no-referrer; sandbox allow-same-origin allow-scripts allow-forms allow-popups" ; cspheader = "default-src 'none'; manifest-src 'self'; connect-src *; script-src 'self'; style-src 'self'; font-src 'self'; img-src 'self' data:; media-src data:; object-src data:; Referrer-Policy: 'no-referrer'; sandbox allow-same-origin allow-scripts allow-forms allow-popups"
; stay compatible with PrivateBin Alpha 0.19, less secure ; stay compatible with PrivateBin Alpha 0.19, less secure
; if enabled will use base64.js version 1.7 instead of 2.1.9 and sha1 instead of ; if enabled will use base64.js version 1.7 instead of 2.1.9 and sha1 instead of

@ -68,12 +68,25 @@ body.loading {
margin-right: 8px; margin-right: 8px;
} }
#image img { #attachmentPreview img {
max-width: 100%; max-width: 100%;
height: auto; height: auto;
margin-bottom: 20px; margin-bottom: 20px;
} }
#attachmentPreview .pdfPreview {
width: 100%;
height: 100vh;
margin-bottom: 20px;
}
.dragAndDropFile{
color:#777;
font-size:1em;
display:inline;
}
#deletelink { #deletelink {
float: right; float: right;
margin-left: 5px; margin-left: 5px;

@ -104,11 +104,23 @@ h3.title {
font-family: Consolas, "Lucida Console", "DejaVu Sans Mono", Monaco, monospace; font-family: Consolas, "Lucida Console", "DejaVu Sans Mono", Monaco, monospace;
} }
#image img { #attachmentPreview img {
max-width: 100%; max-width: 100%;
height: auto; height: auto;
} }
#attachmentPreview .pdfPreview {
width: 100%;
height: 100vh;
margin-bottom: 20px;
}
.dragAndDropFile{
color:#777;
font-size:1em;
display:inline;
}
#status { #status {
clear: both; clear: both;
padding: 5px 10px; padding: 5px 10px;
@ -249,7 +261,7 @@ input {
font-weight: bold !important; font-weight: bold !important;
} }
#image, .nonworking { #attachmentPreview, .nonworking {
background-color: #fff; background-color: #fff;
color: #000; color: #000;
width: 100%; width: 100%;

@ -132,6 +132,8 @@
"Cloned: '%s'": "Geklont: '%s'", "Cloned: '%s'": "Geklont: '%s'",
"The cloned file '%s' was attached to this paste.": "Die geklonte Datei '%s' wurde angehängt.", "The cloned file '%s' was attached to this paste.": "Die geklonte Datei '%s' wurde angehängt.",
"Attach a file": "Datei anhängen", "Attach a file": "Datei anhängen",
"alternatively drag & drop a file or paste an image from the clipboard": "Alternativ Drag & Drop einer Datei oder einfügen eines Bildes aus der Zwischenablage",
"File too large, to display a preview. Please download the attachment.": "Datei zu groß, um als Vorschau angezeigt zu werden. Bitte Anhang herunterladen.",
"Remove attachment": "Anhang entfernen", "Remove attachment": "Anhang entfernen",
"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.":
"Dein Browser unterstützt das hochladen von verschlüsselten Dateien nicht. Bitte verwende einen neueren Browser.", "Dein Browser unterstützt das hochladen von verschlüsselten Dateien nicht. Bitte verwende einen neueren Browser.",

@ -132,6 +132,8 @@
"Cloned: '%s'": "Clonado: '%s'.", "Cloned: '%s'": "Clonado: '%s'.",
"The cloned file '%s' was attached to this paste.": "El archivo clonado '%s' ha sido adjuntado a este texto.", "The cloned file '%s' was attached to this paste.": "El archivo clonado '%s' ha sido adjuntado a este texto.",
"Attach a file": "Adjuntar archivo", "Attach a file": "Adjuntar archivo",
"alternatively drag & drop a file or paste an image from the clipboard": "alternatively drag & drop a file or paste an image from the clipboard",
"File too large, to display a preview. Please download the attachment.": "File too large, to display a preview. Please download the attachment.",
"Remove attachment": "Remover adjunto", "Remove attachment": "Remover adjunto",
"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.":
"Tu navegador no admite la carga de archivos cifrados. Utilice un navegador más reciente.", "Tu navegador no admite la carga de archivos cifrados. Utilice un navegador más reciente.",

@ -141,6 +141,8 @@
"Cloned: '%s'": "Cloner '%s'", "Cloned: '%s'": "Cloner '%s'",
"The cloned file '%s' was attached to this paste.": "Le fichier cloné '%s' a été attaché à ce paste.", "The cloned file '%s' was attached to this paste.": "Le fichier cloné '%s' a été attaché à ce paste.",
"Attach a file": "Attacher un fichier ", "Attach a file": "Attacher un fichier ",
"alternatively drag & drop a file or paste an image from the clipboard": "alternatively drag & drop a file or paste an image from the clipboard",
"File too large, to display a preview. Please download the attachment.": "File too large, to display a preview. Please download the attachment.",
"Remove attachment": "Enlever l'attachement", "Remove attachment": "Enlever l'attachement",
"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.":
"Votre navigateur ne supporte pas l'envoi de fichiers chiffrés. Merci d'utiliser un navigateur plus récent.", "Votre navigateur ne supporte pas l'envoi de fichiers chiffrés. Merci d'utiliser un navigateur plus récent.",

@ -132,6 +132,8 @@
"Cloned: '%s'": "Clonato: '%s'", "Cloned: '%s'": "Clonato: '%s'",
"The cloned file '%s' was attached to this paste.": "Il file clonato '%s' era allegato a questo messaggio.", "The cloned file '%s' was attached to this paste.": "Il file clonato '%s' era allegato a questo messaggio.",
"Attach a file": "Allega un file", "Attach a file": "Allega un file",
"alternatively drag & drop a file or paste an image from the clipboard": "alternatively drag & drop a file or paste an image from the clipboard",
"File too large, to display a preview. Please download the attachment.": "File too large, to display a preview. Please download the attachment.",
"Remove attachment": "Rimuovi allegato", "Remove attachment": "Rimuovi allegato",
"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.":
"Il tuo browser non supporta l'invio di file cifrati. Utilizza un browser più recente.", "Il tuo browser non supporta l'invio di file cifrati. Utilizza un browser più recente.",

@ -132,6 +132,8 @@
"Cloned: '%s'": "Kopiert: '%s'", "Cloned: '%s'": "Kopiert: '%s'",
"The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.", "The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.",
"Attach a file": "Legg til fil", "Attach a file": "Legg til fil",
"alternatively drag & drop a file or paste an image from the clipboard": "alternatively drag & drop a file or paste an image from the clipboard",
"File too large, to display a preview. Please download the attachment.": "File too large, to display a preview. Please download the attachment.",
"Remove attachment": "Slett vedlegg", "Remove attachment": "Slett vedlegg",
"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.":
"Nettleseren din støtter ikke å laste opp krypterte filer. Vennligst bruk en nyere nettleser.", "Nettleseren din støtter ikke å laste opp krypterte filer. Vennligst bruk en nyere nettleser.",

@ -141,6 +141,8 @@
"Cloned: '%s'": "Clonar: '%s'", "Cloned: '%s'": "Clonar: '%s'",
"The cloned file '%s' was attached to this paste.": "Aqueste fichièr clonat '%s' es estat ajustat a aqueste tèxte.", "The cloned file '%s' was attached to this paste.": "Aqueste fichièr clonat '%s' es estat ajustat a aqueste tèxte.",
"Attach a file": "Juntar un fichièr ", "Attach a file": "Juntar un fichièr ",
"alternatively drag & drop a file or paste an image from the clipboard": "alternatively drag & drop a file or paste an image from the clipboard",
"File too large, to display a preview. Please download the attachment.": "File too large, to display a preview. Please download the attachment.",
"Remove attachment": "Levar la pèca junta", "Remove attachment": "Levar la pèca junta",
"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.":
"Vòstre navigator es pas compatible amb lo mandadís de fichièrs chifrats. Mercés demplegar un navigator mai recent.", "Vòstre navigator es pas compatible amb lo mandadís de fichièrs chifrats. Mercés demplegar un navigator mai recent.",

@ -132,6 +132,8 @@
"Cloned: '%s'": "Sklonowano: '%s'", "Cloned: '%s'": "Sklonowano: '%s'",
"The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.", "The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.",
"Attach a file": "Załącz plik", "Attach a file": "Załącz plik",
"alternatively drag & drop a file or paste an image from the clipboard": "alternatively drag & drop a file or paste an image from the clipboard",
"File too large, to display a preview. Please download the attachment.": "File too large, to display a preview. Please download the attachment.",
"Remove attachment": "Usuń załącznik", "Remove attachment": "Usuń załącznik",
"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.":
"Twoja przeglądarka nie wspiera wysyłania zaszyfrowanych plików. Użyj nowszej przeglądarki.", "Twoja przeglądarka nie wspiera wysyłania zaszyfrowanych plików. Użyj nowszej przeglądarki.",

@ -132,6 +132,8 @@
"Cloned: '%s'": "Clonado: '%s'", "Cloned: '%s'": "Clonado: '%s'",
"The cloned file '%s' was attached to this paste.": "O arquivo clonado '%s' foi anexado a essa cópia.", "The cloned file '%s' was attached to this paste.": "O arquivo clonado '%s' foi anexado a essa cópia.",
"Attach a file": "Anexar um arquivo", "Attach a file": "Anexar um arquivo",
"alternatively drag & drop a file or paste an image from the clipboard": "alternatively drag & drop a file or paste an image from the clipboard",
"File too large, to display a preview. Please download the attachment.": "File too large, to display a preview. Please download the attachment.",
"Remove attachment": "Remover anexo", "Remove attachment": "Remover anexo",
"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.":
"Seu navegador não permite subir arquivos cifrados. Por favor, utilize um navegador mais recente.", "Seu navegador não permite subir arquivos cifrados. Por favor, utilize um navegador mais recente.",

@ -142,6 +142,8 @@
"The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.":
"Дубликат файла '%s' был прикреплен к этой записи.", "Дубликат файла '%s' был прикреплен к этой записи.",
"Attach a file": "Прикрепить файл", "Attach a file": "Прикрепить файл",
"alternatively drag & drop a file or paste an image from the clipboard": "alternatively drag & drop a file or paste an image from the clipboard",
"File too large, to display a preview. Please download the attachment.": "File too large, to display a preview. Please download the attachment.",
"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.":
"Ваш браузер не поддерживает отправку зашифрованных файлов. Используйте более новый браузер.", "Ваш браузер не поддерживает отправку зашифрованных файлов. Используйте более новый браузер.",

@ -141,6 +141,8 @@
"Cloned: '%s'": "'%s' klonirana", "Cloned: '%s'": "'%s' klonirana",
"The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.", "The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.",
"Attach a file": "Pripni datoteko", "Attach a file": "Pripni datoteko",
"alternatively drag & drop a file or paste an image from the clipboard": "alternatively drag & drop a file or paste an image from the clipboard",
"File too large, to display a preview. Please download the attachment.": "File too large, to display a preview. Please download the attachment.",
"Remove attachment": "Odstrani priponko", "Remove attachment": "Odstrani priponko",
"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.":
"Tvoj brskalnik ne omogoča nalaganje zakodiranih datotek. Prosim uporabi novejši brskalnik.", "Tvoj brskalnik ne omogoča nalaganje zakodiranih datotek. Prosim uporabi novejši brskalnik.",

@ -132,6 +132,8 @@
"Cloned: '%s'": "克隆: '%s'", "Cloned: '%s'": "克隆: '%s'",
"The cloned file '%s' was attached to this paste.": "克隆文件 '%s' 已附加到此粘贴。", "The cloned file '%s' was attached to this paste.": "克隆文件 '%s' 已附加到此粘贴。",
"Attach a file": "添加一个附件", "Attach a file": "添加一个附件",
"alternatively drag & drop a file or paste an image from the clipboard": "alternatively drag & drop a file or paste an image from the clipboard",
"File too large, to display a preview. Please download the attachment.": "File too large, to display a preview. Please download the attachment.",
"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.":
"您的浏览器不支持上传加密的文件,请使用更新的浏览器。", "您的浏览器不支持上传加密的文件,请使用更新的浏览器。",

@ -1520,6 +1520,10 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) {
// show preview // show preview
PasteViewer.setText($message.val()); PasteViewer.setText($message.val());
if (AttachmentViewer.hasAttachmentData()) {
var attachmentData = AttachmentViewer.getAttachmentData() || AttachmentViewer.getAttachmentLink().attr('href');
AttachmentViewer.handleAttachmentPreview(AttachmentViewer.getAttachmentPreview(), attachmentData);
}
PasteViewer.run(); PasteViewer.run();
// finish // finish
@ -1855,6 +1859,7 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) {
$plainText.addClass('hidden'); $plainText.addClass('hidden');
$prettyMessage.addClass('hidden'); $prettyMessage.addClass('hidden');
$placeholder.addClass('hidden'); $placeholder.addClass('hidden');
AttachmentViewer.hideAttachmentPreview();
isDisplayed = false; isDisplayed = false;
}; };
@ -1907,10 +1912,13 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) {
var AttachmentViewer = (function () { var AttachmentViewer = (function () {
var me = {}; var me = {};
var $attachmentLink, var $attachmentLink;
$attachmentPreview, var $attachmentPreview;
$attachment; var $attachment;
var attachmentData;
var file;
var $fileInput;
var $dragAndDropFileName;
var attachmentHasPreview = false; var attachmentHasPreview = false;
/** /**
@ -1923,8 +1931,6 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) {
*/ */
me.setAttachment = function(attachmentData, fileName) me.setAttachment = function(attachmentData, fileName)
{ {
var imagePrefix = 'data:image/';
// IE does not support setting a data URI on an a element // IE does not support setting a data URI on an a element
// Convert dataURI to a Blob and use msSaveBlob to download // Convert dataURI to a Blob and use msSaveBlob to download
if (window.Blob && navigator.msSaveBlob) { if (window.Blob && navigator.msSaveBlob) {
@ -1960,15 +1966,7 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) {
$attachmentLink.attr('download', fileName); $attachmentLink.attr('download', fileName);
} }
// if the attachment is an image, display it me.handleAttachmentPreview($attachmentPreview, attachmentData);
if (attachmentData.substring(0, imagePrefix.length) === imagePrefix) {
$attachmentPreview.html(
$(document.createElement('img'))
.attr('src', attachmentData)
.attr('class', 'img-thumbnail')
);
attachmentHasPreview = true;
}
}; };
/** /**
@ -1989,7 +1987,7 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) {
/** /**
* removes the attachment * removes the attachment
* *
* This automatically hides the attachment containers to, to * This automatically hides the attachment containers too, to
* prevent an inconsistent display. * prevent an inconsistent display.
* *
* @name AttachmentViewer.removeAttachment * @name AttachmentViewer.removeAttachment
@ -1997,12 +1995,18 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) {
*/ */
me.removeAttachment = function() me.removeAttachment = function()
{ {
if (!$attachment.length) {
return;
}
me.hideAttachment(); me.hideAttachment();
me.hideAttachmentPreview(); me.hideAttachmentPreview();
$attachmentLink.prop('href', ''); $attachmentLink.removeAttr('href');
$attachmentLink.prop('download', ''); $attachmentLink.removeAttr('download');
$attachmentLink.off('click'); $attachmentLink.off('click');
$attachmentPreview.html(''); $attachmentPreview.html('');
file = undefined;
attachmentData = undefined;
}; };
/** /**
@ -2028,7 +2032,9 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) {
*/ */
me.hideAttachmentPreview = function() me.hideAttachmentPreview = function()
{ {
$attachmentPreview.addClass('hidden'); if ($attachmentPreview) {
$attachmentPreview.addClass('hidden');
}
}; };
/** /**
@ -2039,8 +2045,25 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) {
*/ */
me.hasAttachment = function() me.hasAttachment = function()
{ {
if (!$attachment.length) {
return false;
}
var link = $attachmentLink.prop('href'); var link = $attachmentLink.prop('href');
return typeof link !== 'undefined' && link !== ''; return (typeof link !== 'undefined' && link !== '');
};
/**
* checks if there is attachment data available
*
* @name AttachmentViewer.hasAttachmentData
* @function
*/
me.hasAttachmentData = function()
{
if ($attachment.length) {
return true;
}
return false;
}; };
/** /**
@ -2077,6 +2100,224 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) {
I18n._($attachmentLink, label, $attachmentLink.attr('download')); I18n._($attachmentLink, label, $attachmentLink.attr('download'));
}; };
/**
* read file data as dataURL using the FileReader API
*
* @name AttachmentViewer.readFileData
* @function
* @param {object} loadedFile The loaded file.
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/FileReader#readAsDataURL()}
*/
me.readFileData = function (loadedFile) {
if (typeof FileReader === 'undefined') {
// revert loading status…
me.hideAttachment();
me.hideAttachmentPreview();
Alert.showError('Your browser does not support uploading encrypted files. Please use a newer browser.');
return;
}
var fileReader = new FileReader();
if (loadedFile === undefined) {
loadedFile = $fileInput[0].files[0];
$dragAndDropFileName.text('');
} else {
$dragAndDropFileName.text(loadedFile.name);
}
file = loadedFile;
fileReader.onload = function (event) {
var dataURL = event.target.result;
attachmentData = dataURL;
if (Editor.isPreview()) {
me.handleAttachmentPreview($attachmentPreview, dataURL);
$attachmentPreview.removeClass('hidden');
}
};
fileReader.readAsDataURL(loadedFile);
};
/**
* handle the preview of files that can either be an image, video, audio or pdf element
*
* @name AttachmentViewer.handleAttachmentPreview
* @function
* @argument {jQuery} $targetElement where the preview should be appended.
* @argument {File Data} data of the file to be displayed.
*/
me.handleAttachmentPreview = function ($targetElement, data) {
if (data) {
// source: https://developer.mozilla.org/en-US/docs/Web/API/FileReader#readAsDataURL()
var mimeType = data.slice(
data.indexOf('data:') + 5,
data.indexOf(';base64,')
);
attachmentHasPreview = true;
if (mimeType.match(/image\//i)) {
$targetElement.html(
$(document.createElement('img'))
.attr('src', data)
.attr('class', 'img-thumbnail')
);
} else if (mimeType.match(/video\//i)) {
$targetElement.html(
$(document.createElement('video'))
.attr('controls', 'true')
.attr('autoplay', 'true')
.attr('class', 'img-thumbnail')
.append($(document.createElement('source'))
.attr('type', mimeType)
.attr('src', data))
);
} else if (mimeType.match(/audio\//i)) {
$targetElement.html(
$(document.createElement('audio'))
.attr('controls', 'true')
.attr('autoplay', 'true')
.append($(document.createElement('source'))
.attr('type', mimeType)
.attr('src', data))
);
} else if (mimeType.match(/\/pdf/i)) {
// PDFs are only displayed if the filesize is smaller than about 1MB (after base64 encoding).
// Bigger filesizes currently cause crashes in various browsers.
// See also: https://code.google.com/p/chromium/issues/detail?id=69227
// Firefox crashes with files that are about 1.5MB
// The performance with 1MB files is bearable
if (data.length > 1398488) {
Alert.showError('File too large, to display a preview. Please download the attachment.');
return;
}
// Fallback for browsers, that don't support the vh unit
var clientHeight = $(window).height();
$targetElement.html(
$(document.createElement('embed'))
.attr('src', data)
.attr('type', 'application/pdf')
.attr('class', 'pdfPreview')
.css('height', clientHeight)
);
} else {
attachmentHasPreview = false;
}
}
};
/**
* attaches the file attachment drag & drop handler to the page
*
* @name AttachmentViewer.addDragDropHandler
* @function
*/
me.addDragDropHandler = function () {
if (typeof $fileInput === 'undefined' || $fileInput.length === 0) {
return;
}
var ignoreDragDrop = function(event) {
event.stopPropagation();
event.preventDefault();
};
var drop = function(event) {
var evt = event.originalEvent;
evt.stopPropagation();
evt.preventDefault();
if ($fileInput) {
var file = evt.dataTransfer.files[0];
//Clear the file input:
$fileInput.wrap('<form>').closest('form').get(0).reset();
$fileInput.unwrap();
//Only works in Chrome:
//fileInput[0].files = e.dataTransfer.files;
me.readFileData(file);
}
};
$(document).on('drop', drop);
$(document).on('dragenter', ignoreDragDrop);
$(document).on('dragover', ignoreDragDrop);
$fileInput.on("change", function () {
me.readFileData();
});
};
/**
* attaches the clipboard attachment handler to the page
*
* @name AttachmentViewer.addClipboardEventHandler
* @function
*/
me.addClipboardEventHandler = function () {
$(document).on('paste',
function (event) {
var items = (event.clipboardData || event.originalEvent.clipboardData).items;
for (var i in items) {
if (items.hasOwnProperty(i)) {
var item = items[i];
if (item.kind === 'file') {
me.readFileData(item.getAsFile());
}
}
}
});
};
/**
* getter for attachment data
*
* @name AttachmentViewer.getAttachmentData
* @function
* @return {jQuery}
*/
me.getAttachmentData = function () {
return attachmentData;
};
/**
* getter for attachment link
*
* @name AttachmentViewer.getAttachmentLink
* @function
* @return {jQuery}
*/
me.getAttachmentLink = function () {
return $attachmentLink;
};
/**
* getter for attachment preview
*
* @name AttachmentViewer.getAttachmentPreview
* @function
* @return {jQuery}
*/
me.getAttachmentPreview = function () {
return $attachmentPreview;
};
/**
* getter for file data, returns the file contents
*
* @name AttachmentViewer.getFile
* @function
* @return {string}
*/
me.getFile = function () {
return file;
};
/** /**
* initiate * initiate
* *
@ -2088,10 +2329,16 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) {
me.init = function() me.init = function()
{ {
$attachment = $('#attachment'); $attachment = $('#attachment');
$attachmentLink = $('#attachment a'); if($attachment.length){
$attachmentPreview = $('#attachmentPreview'); $attachmentLink = $('#attachment a');
attachmentHasPreview = false; $attachmentPreview = $('#attachmentPreview');
}; $dragAndDropFileName = $('#dragAndDropFileName');
$fileInput = $('#file');
me.addDragDropHandler();
me.addClipboardEventHandler();
}
}
return me; return me;
})(); })();
@ -3328,31 +3575,19 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) {
* @name PasteEncrypter.encryptAttachments * @name PasteEncrypter.encryptAttachments
* @private * @private
* @function * @function
* @param {File|null|undefined} file - optional, falls back to cloned attachment
* @param {function} callback - excuted when action is successful * @param {function} callback - excuted when action is successful
*/ */
function encryptAttachments(file, callback) { function encryptAttachments(callback) {
if (typeof file !== 'undefined' && file !== null) { var file = AttachmentViewer.getAttachmentData();
// check file reader requirements for upload
if (typeof FileReader === 'undefined') {
Alert.showError('Your browser does not support uploading encrypted files. Please use a newer browser.');
// cancels process as it does not execute callback
return;
}
var reader = new FileReader(); if (typeof file !== 'undefined' && file !== null) {
var fileName = AttachmentViewer.getFile().name;
// closure to capture the file information
reader.onload = function(event) {
Uploader.setData('attachment', event.target.result);
Uploader.setData('attachmentname', file.name);
// run callback Uploader.setData('attachment', file);
return callback(); Uploader.setData('attachmentname', fileName);
};
// actually read first file // run callback
reader.readAsDataURL(file); return callback();
} else if (AttachmentViewer.hasAttachment()) { } else if (AttachmentViewer.hasAttachment()) {
// fall back to cloned part // fall back to cloned part
var attachment = AttachmentViewer.getAttachment(); var attachment = AttachmentViewer.getAttachment();
@ -3461,7 +3696,7 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) {
// get data // get data
var plainText = Editor.getText(), var plainText = Editor.getText(),
format = PasteViewer.getFormat(), format = PasteViewer.getFormat(),
files = TopNav.getFileList(); files = TopNav.getFileList() || AttachmentViewer.getFile() || AttachmentViewer.hasAttachment();
// do not send if there is no data // do not send if there is no data
if (plainText.length === 0 && files === null) { if (plainText.length === 0 && files === null) {
@ -3512,7 +3747,6 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) {
// encrypt attachments // encrypt attachments
encryptAttachments( encryptAttachments(
files === null ? null : files[0],
function () { function () {
// send data // send data
Uploader.run(); Uploader.run();
@ -3727,10 +3961,12 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) {
try { try {
// decrypt attachments // decrypt attachments
if (paste.attachment) { if (paste.attachment) {
// try to decrypt paste and if it fails (because the password is if (AttachmentViewer.hasAttachmentData()) {
// missing) return to let JS continue and wait for user // try to decrypt paste and if it fails (because the password is
if (!decryptAttachment(paste, key, password)) { // missing) return to let JS continue and wait for user
return; if (!decryptAttachment(paste, key, password)) {
return;
}
} }
// ignore empty paste, as this is allowed when pasting attachments // ignore empty paste, as this is allowed when pasting attachments
decryptPaste(paste, key, password, true); decryptPaste(paste, key, password, true);
@ -3813,6 +4049,7 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) {
Editor.resetInput(); Editor.resetInput();
Editor.show(); Editor.show();
Editor.focusInput(); Editor.focusInput();
AttachmentViewer.removeAttachment();
TopNav.showCreateButtons(); TopNav.showCreateButtons();
Alert.hideLoading(); Alert.hideLoading();

@ -18,7 +18,12 @@ describe('AttachmentViewer', function () {
function (mimeType, base64, filename, prefix, postfix) { function (mimeType, base64, filename, prefix, postfix) {
var clean = jsdom(), var clean = jsdom(),
data = 'data:' + mimeType + ';base64,' + base64.join(''), data = 'data:' + mimeType + ';base64,' + base64.join(''),
isImage = mimeType.substring(0, 6) === 'image/', previewSupported = (
mimeType.substring(0, 6) === 'image/' ||
mimeType.substring(0, 6) === 'audio/' ||
mimeType.substring(0, 6) === 'video/' ||
mimeType.match(/\/pdf/i)
),
results = []; results = [];
prefix = prefix.replace(/%(s|d)/g, '%%'); prefix = prefix.replace(/%(s|d)/g, '%%');
postfix = postfix.replace(/%(s|d)/g, '%%'); postfix = postfix.replace(/%(s|d)/g, '%%');
@ -40,32 +45,32 @@ describe('AttachmentViewer', function () {
} else { } else {
$.PrivateBin.AttachmentViewer.setAttachment(data); $.PrivateBin.AttachmentViewer.setAttachment(data);
} }
var attachement = $.PrivateBin.AttachmentViewer.getAttachment(); var attachment = $.PrivateBin.AttachmentViewer.getAttachment();
results.push( results.push(
$.PrivateBin.AttachmentViewer.hasAttachment() && $.PrivateBin.AttachmentViewer.hasAttachment() &&
$('#attachment').hasClass('hidden') && $('#attachment').hasClass('hidden') &&
$('#attachmentPreview').hasClass('hidden') && $('#attachmentPreview').hasClass('hidden') &&
attachement[0] === data && attachment[0] === data &&
attachement[1] === filename attachment[1] === filename
); );
$.PrivateBin.AttachmentViewer.showAttachment(); $.PrivateBin.AttachmentViewer.showAttachment();
results.push( results.push(
!$('#attachment').hasClass('hidden') && !$('#attachment').hasClass('hidden') &&
(isImage ? !$('#attachmentPreview').hasClass('hidden') : $('#attachmentPreview').hasClass('hidden')) (previewSupported ? !$('#attachmentPreview').hasClass('hidden') : $('#attachmentPreview').hasClass('hidden'))
); );
$.PrivateBin.AttachmentViewer.hideAttachment(); $.PrivateBin.AttachmentViewer.hideAttachment();
results.push( results.push(
$('#attachment').hasClass('hidden') && $('#attachment').hasClass('hidden') &&
(isImage ? !$('#attachmentPreview').hasClass('hidden') : $('#attachmentPreview').hasClass('hidden')) (previewSupported ? !$('#attachmentPreview').hasClass('hidden') : $('#attachmentPreview').hasClass('hidden'))
); );
if (isImage) { if (previewSupported) {
$.PrivateBin.AttachmentViewer.hideAttachmentPreview(); $.PrivateBin.AttachmentViewer.hideAttachmentPreview();
results.push($('#attachmentPreview').hasClass('hidden')); results.push($('#attachmentPreview').hasClass('hidden'));
} }
$.PrivateBin.AttachmentViewer.showAttachment(); $.PrivateBin.AttachmentViewer.showAttachment();
results.push( results.push(
!$('#attachment').hasClass('hidden') && !$('#attachment').hasClass('hidden') &&
(isImage ? !$('#attachmentPreview').hasClass('hidden') : $('#attachmentPreview').hasClass('hidden')) (previewSupported ? !$('#attachmentPreview').hasClass('hidden') : $('#attachmentPreview').hasClass('hidden'))
); );
var element = $('<div></div>'); var element = $('<div></div>');
$.PrivateBin.AttachmentViewer.moveAttachmentTo(element, prefix + '%s' + postfix); $.PrivateBin.AttachmentViewer.moveAttachmentTo(element, prefix + '%s' + postfix);

@ -54,7 +54,7 @@ class Configuration
'urlshortener' => '', 'urlshortener' => '',
'qrcode' => true, 'qrcode' => true,
'icon' => 'identicon', 'icon' => 'identicon',
'cspheader' => 'default-src \'none\'; manifest-src \'self\'; connect-src *; form-action \'none\'; script-src \'self\'; style-src \'self\'; font-src \'self\'; img-src \'self\' data:; referrer no-referrer; sandbox allow-same-origin allow-scripts allow-forms allow-popups', 'cspheader' => 'default-src \'none\'; manifest-src \'self\'; connect-src *; script-src \'self\'; style-src \'self\'; font-src \'self\'; img-src \'self\' data:; media-src data:; object-src data:; Referrer-Policy: \'no-referrer\'; sandbox allow-same-origin allow-scripts allow-forms allow-popups',
'zerobincompatibility' => false, 'zerobincompatibility' => false,
), ),
'expire' => array( 'expire' => array(

@ -75,7 +75,7 @@ if ($MARKDOWN):
<?php <?php
endif; endif;
?> ?>
<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-fJAdh2DQpns2TMhDmiohfNCQXpjX+f/KpRCiRnWI6hq0lOT/RRFc11+qJzGK5zNFjDvDhCMbMADKn4D03p9Uag==" crossorigin="anonymous"></script> <script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-5MEpLVeCKou7sL5U7X8uo5O0CG+1+aLGpN2O5Xvo9e31Ql7/7N8X03OCcwqBNEKv61IcSlxkCP9eLXZl8eMeBA==" crossorigin="anonymous"></script>
<!--[if lt IE 10]> <!--[if lt IE 10]>
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style> <style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
<![endif]--> <![endif]-->
@ -323,8 +323,9 @@ if ($FILEUPLOAD):
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li id="filewrap"> <li id="filewrap">
<div> <div>
<input type="file" id="file" name="file" /> <input type="file" id="file" name="file"/>
</div> </div>
<div id="dragAndDropFileName" class="dragAndDropFile"><?php echo I18n::_('alternatively drag & drop a file or paste an image from the clipboard'); ?></div>
</li> </li>
<li id="customattachment" class="hidden"></li> <li id="customattachment" class="hidden"></li>
<li> <li>
@ -420,30 +421,30 @@ endif;
<?php <?php
if (strlen($NOTICE)): if (strlen($NOTICE)):
?> ?>
<div role="alert" class="alert alert-info"> <div role="alert" class="alert alert-info">
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
<?php echo htmlspecialchars($NOTICE), PHP_EOL; ?> <?php echo htmlspecialchars($NOTICE), PHP_EOL; ?>
</div> </div>
<?php <?php
endif; endif;
?> ?>
<div id="remainingtime" role="alert" class="hidden alert alert-info"> <div id="remainingtime" role="alert" class="hidden alert alert-info">
<span class="glyphicon glyphicon-fire" aria-hidden="true"></span> <span class="glyphicon glyphicon-fire" aria-hidden="true"></span>
</div> </div>
<?php <?php
if ($FILEUPLOAD): if ($FILEUPLOAD):
?> ?>
<div id="attachment" role="alert" class="hidden alert alert-info"> <div id="attachment" role="alert" class="hidden alert alert-info">
<span class="glyphicon glyphicon-download-alt" aria-hidden="true"></span> <span class="glyphicon glyphicon-download-alt" aria-hidden="true"></span>
<a class="alert-link"><?php echo I18n::_('Download attachment'), PHP_EOL; ?></a> <a class="alert-link"><?php echo I18n::_('Download attachment'), PHP_EOL; ?></a>
</div> </div>
<?php <?php
endif; endif;
?> ?>
<div id="status" role="alert" class="statusmessage alert alert-info<?php echo empty($STATUS) ? ' hidden' : '' ?>"> <div id="status" role="alert" class="statusmessage alert alert-info<?php echo empty($STATUS) ? ' hidden' : '' ?>">
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
<?php echo htmlspecialchars($STATUS), PHP_EOL; ?> <?php echo htmlspecialchars($STATUS), PHP_EOL; ?>
</div> </div>
<div id="errormessage" role="alert" class="statusmessage<?php echo empty($ERROR) ? ' hidden' : '' ?> alert alert-danger"> <div id="errormessage" role="alert" class="statusmessage<?php echo empty($ERROR) ? ' hidden' : '' ?> alert alert-danger">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<?php echo htmlspecialchars($ERROR), PHP_EOL; ?> <?php echo htmlspecialchars($ERROR), PHP_EOL; ?>
@ -461,14 +462,22 @@ endif;
<div id="ienotice" role="alert" class="hidden alert alert-<?php echo $isDark ? 'error' : 'warning'; ?>"> <div id="ienotice" role="alert" class="hidden alert alert-<?php echo $isDark ? 'error' : 'warning'; ?>">
<span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span> <span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span>
<?php echo I18n::_('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:'), PHP_EOL; ?> <?php echo I18n::_('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:'), PHP_EOL; ?>
<a href="https://www.mozilla.org/firefox/">Firefox</a>, <a href="https://www.mozilla.org/firefox/">Firefox</a>,
<a href="https://www.opera.com/">Opera</a>, <a href="https://www.opera.com/">Opera</a>,
<a href="https://www.google.com/chrome">Chrome</a> <a href="https://www.google.com/chrome">Chrome</a>
<<<<<<< HEAD
</div> </div>
<div id="pastesuccess" role="alert" class="hidden alert alert-success"> <div id="pastesuccess" role="alert" class="hidden alert alert-success">
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span> <span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
<div id="deletelink"></div> <div id="deletelink"></div>
<div id="pastelink"></div> <div id="pastelink"></div>
=======
</div>
<div id="pasteSuccess" role="alert" class="hidden alert alert-success">
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
<div id="deletelink"></div>
<div id="pastelink">
>>>>>>> 08972e4da33c72a2fad7d04ce065147f5fa5f0c1
<?php <?php
if (strlen($URLSHORTENER)): if (strlen($URLSHORTENER)):
?> ?>
@ -479,44 +488,45 @@ if (strlen($URLSHORTENER)):
endif; endif;
?> ?>
</div> </div>
</div>
<ul id="editorTabs" class="nav nav-tabs hidden"> <ul id="editorTabs" class="nav nav-tabs hidden">
<li role="presentation" class="active"><a id="messageedit" href="#"><?php echo I18n::_('Editor'); ?></a></li> <li role="presentation" class="active"><a id="messageedit" href="#"><?php echo I18n::_('Editor'); ?></a></li>
<li role="presentation"><a id="messagepreview" href="#"><?php echo I18n::_('Preview'); ?></a></li> <li role="presentation"><a id="messagepreview" href="#"><?php echo I18n::_('Preview'); ?></a></li>
</ul> </ul>
</section> </section>
<section class="container"> <section class="container">
<article class="row"> <article class="row">
<div id="placeholder" class="col-md-12 hidden"><?php echo I18n::_('+++ no paste text +++'); ?></div> <div id="placeholder" class="col-md-12 hidden"><?php echo I18n::_('+++ no paste text +++'); ?></div>
<div id="attachmentPreview" class="col-md-12 text-center hidden"></div> <div id="attachmentPreview" class="col-md-12 text-center hidden"></div>
<div id="prettymessage" class="col-md-12 hidden"> <div id="prettymessage" class="col-md-12 hidden">
<pre id="prettyprint" class="col-md-12 prettyprint linenums:1"></pre> <pre id="prettyprint" class="col-md-12 prettyprint linenums:1"></pre>
</div> </div>
<div id="plaintext" class="col-md-12 hidden"></div> <div id="plaintext" class="col-md-12 hidden"></div>
<p class="col-md-12"><textarea id="message" name="message" cols="80" rows="25" class="form-control hidden"></textarea></p> <p class="col-md-12"><textarea id="message" name="message" cols="80" rows="25" class="form-control hidden"></textarea></p>
</article> </article>
</section> </section>
<section class="container"> <section class="container">
<div id="discussion" class="hidden"> <div id="discussion" class="hidden">
<h4><?php echo I18n::_('Discussion'); ?></h4> <h4><?php echo I18n::_('Discussion'); ?></h4>
<div id="commentcontainer"></div> <div id="commentcontainer"></div>
</div> </div>
</section> </section>
<section class="container"> <section class="container">
<div id="noscript" role="alert" class="nonworking alert alert-info noscript-hide"> <div id="noscript" role="alert" class="nonworking alert alert-info noscript-hide">
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
<?php echo I18n::_('Loading…'); ?><br /> <?php echo I18n::_('Loading…'); ?><br />
<span class="small"><?php echo I18n::_('In case this message never disappears please have a look at <a href="https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away">this FAQ for information to troubleshoot</a>.'); ?></span> <span class="small"><?php echo I18n::_('In case this message never disappears please have a look at <a href="https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away">this FAQ for information to troubleshoot</a>.'); ?></span>
</div> </div>
</section> </section>
<footer class="container"> <footer class="container">
<div class="row"> <div class="row">
<h4 class="col-md-5 col-xs-8"><?php echo I18n::_($NAME); ?> <small>- <?php echo I18n::_('Because ignorance is bliss'); ?></small></h4> <h4 class="col-md-5 col-xs-8"><?php echo I18n::_($NAME); ?> <small>- <?php echo I18n::_('Because ignorance is bliss'); ?></small></h4>
<p class="col-md-1 col-xs-4 text-center"><?php echo $VERSION; ?></p> <p class="col-md-1 col-xs-4 text-center"><?php echo $VERSION; ?></p>
<p id="aboutbox" class="col-md-6 col-xs-12"> <p id="aboutbox" class="col-md-6 col-xs-12">
<?php echo I18n::_('%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href="https://privatebin.info/">project page</a>.', I18n::_($NAME)), PHP_EOL; ?> <?php echo I18n::_('%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href="https://privatebin.info/">project page</a>.', I18n::_($NAME)), PHP_EOL; ?>
</p> </p>
</div> </div>
</footer> </footer>
</main> </main>
<div id="serverdata" class="hidden" aria-hidden="true"> <div id="serverdata" class="hidden" aria-hidden="true">
<div id="cipherdata"><?php echo htmlspecialchars($CIPHERDATA, ENT_NOQUOTES); ?></div> <div id="cipherdata"><?php echo htmlspecialchars($CIPHERDATA, ENT_NOQUOTES); ?></div>

@ -54,7 +54,7 @@ if ($QRCODE):
<?php <?php
endif; endif;
?> ?>
<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-fJAdh2DQpns2TMhDmiohfNCQXpjX+f/KpRCiRnWI6hq0lOT/RRFc11+qJzGK5zNFjDvDhCMbMADKn4D03p9Uag==" crossorigin="anonymous"></script> <script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-5MEpLVeCKou7sL5U7X8uo5O0CG+1+aLGpN2O5Xvo9e31Ql7/7N8X03OCcwqBNEKv61IcSlxkCP9eLXZl8eMeBA==" crossorigin="anonymous"></script>
<!--[if lt IE 10]> <!--[if lt IE 10]>
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style> <style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
<![endif]--> <![endif]-->
@ -222,6 +222,7 @@ if ($FILEUPLOAD):
<div id="attach" class="hidden"> <div id="attach" class="hidden">
<span id="clonedfile" class="hidden"><?php echo I18n::_('Cloned file attached.'); ?></span> <span id="clonedfile" class="hidden"><?php echo I18n::_('Cloned file attached.'); ?></span>
<span id="filewrap"><?php echo I18n::_('Attach a file'); ?>: <input type="file" id="file" name="file" /></span> <span id="filewrap"><?php echo I18n::_('Attach a file'); ?>: <input type="file" id="file" name="file" /></span>
<span id="dragAndDropFileName" class="dragAndDropFile"><?php echo I18n::_('alternatively drag & drop a file or paste an image from the clipboard'); ?></span>
<button id="fileremovebutton"><?php echo I18n::_('Remove attachment'); ?></button> <button id="fileremovebutton"><?php echo I18n::_('Remove attachment'); ?></button>
</div> </div>
<?php <?php
@ -231,7 +232,7 @@ endif;
<button id="messageedit"><?php echo I18n::_('Editor'); ?></button> <button id="messageedit"><?php echo I18n::_('Editor'); ?></button>
<button id="messagepreview"><?php echo I18n::_('Preview'); ?></button> <button id="messagepreview"><?php echo I18n::_('Preview'); ?></button>
</div> </div>
<div id="image" class="hidden"></div> <div id="attachmentPreview" class="hidden"></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>
@ -246,7 +247,7 @@ endif;
</div> </div>
</section> </section>
<div id="serverdata" class="hidden" aria-hidden="true"> <div id="serverdata" class="hidden" aria-hidden="true">
<div id="cipherdata" class="hidden"><?php echo htmlspecialchars($CIPHERDATA, ENT_NOQUOTES); ?></div> <div id="cipherdata" class="hidden"><?php echo htmlspecialchars($CIPHERDATA, ENT_NOQUOTES); ?></div>
<?php <?php
if ($DISCUSSION): if ($DISCUSSION):
?> ?>

Loading…
Cancel
Save