diff --git a/cfg/conf.sample.php b/cfg/conf.sample.php index db600d5..ed494b7 100644 --- a/cfg/conf.sample.php +++ b/cfg/conf.sample.php @@ -73,7 +73,7 @@ languageselection = false ; scripts or run your site behind certain DDoS-protection services. ; 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. -; 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 ; if enabled will use base64.js version 1.7 instead of 2.1.9 and sha1 instead of diff --git a/css/bootstrap/privatebin.css b/css/bootstrap/privatebin.css index e0dd81f..3aed386 100644 --- a/css/bootstrap/privatebin.css +++ b/css/bootstrap/privatebin.css @@ -68,12 +68,25 @@ body.loading { margin-right: 8px; } -#image img { +#attachmentPreview img { max-width: 100%; height: auto; margin-bottom: 20px; } +#attachmentPreview .pdfPreview { + width: 100%; + height: 100vh; + margin-bottom: 20px; +} + +.dragAndDropFile{ + color:#777; + font-size:1em; + display:inline; +} + + #deletelink { float: right; margin-left: 5px; diff --git a/css/privatebin.css b/css/privatebin.css index a1d3b23..68e951a 100644 --- a/css/privatebin.css +++ b/css/privatebin.css @@ -104,11 +104,23 @@ h3.title { font-family: Consolas, "Lucida Console", "DejaVu Sans Mono", Monaco, monospace; } -#image img { +#attachmentPreview img { max-width: 100%; height: auto; } +#attachmentPreview .pdfPreview { + width: 100%; + height: 100vh; + margin-bottom: 20px; +} + +.dragAndDropFile{ + color:#777; + font-size:1em; + display:inline; +} + #status { clear: both; padding: 5px 10px; @@ -249,7 +261,7 @@ input { font-weight: bold !important; } -#image, .nonworking { +#attachmentPreview, .nonworking { background-color: #fff; color: #000; width: 100%; diff --git a/i18n/de.json b/i18n/de.json index 332c61c..6c0ad33 100644 --- a/i18n/de.json +++ b/i18n/de.json @@ -132,6 +132,8 @@ "Cloned: '%s'": "Geklont: '%s'", "The cloned file '%s' was attached to this paste.": "Die geklonte Datei '%s' wurde angehängt.", "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", "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.", diff --git a/i18n/es.json b/i18n/es.json index 7d8de7a..9fb6ed8 100644 --- a/i18n/es.json +++ b/i18n/es.json @@ -132,6 +132,8 @@ "Cloned: '%s'": "Clonado: '%s'.", "The cloned file '%s' was attached to this paste.": "El archivo clonado '%s' ha sido adjuntado a este texto.", "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", "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.", diff --git a/i18n/fr.json b/i18n/fr.json index da9d373..bcfc43c 100644 --- a/i18n/fr.json +++ b/i18n/fr.json @@ -141,6 +141,8 @@ "Cloned: '%s'": "Cloner '%s'", "The cloned file '%s' was attached to this paste.": "Le fichier cloné '%s' a été attaché à ce paste.", "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", "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.", diff --git a/i18n/it.json b/i18n/it.json index d7885d7..bf15fc1 100644 --- a/i18n/it.json +++ b/i18n/it.json @@ -132,6 +132,8 @@ "Cloned: '%s'": "Clonato: '%s'", "The cloned file '%s' was attached to this paste.": "Il file clonato '%s' era allegato a questo messaggio.", "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", "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.", diff --git a/i18n/no.json b/i18n/no.json index 8292e10..912cfc0 100644 --- a/i18n/no.json +++ b/i18n/no.json @@ -132,6 +132,8 @@ "Cloned: '%s'": "Kopiert: '%s'", "The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.", "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", "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.", diff --git a/i18n/oc.json b/i18n/oc.json index c934916..d5dd041 100644 --- a/i18n/oc.json +++ b/i18n/oc.json @@ -141,6 +141,8 @@ "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.", "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", "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 d’emplegar un navigator mai recent.", diff --git a/i18n/pl.json b/i18n/pl.json index 82d9b57..9842246 100644 --- a/i18n/pl.json +++ b/i18n/pl.json @@ -132,6 +132,8 @@ "Cloned: '%s'": "Sklonowano: '%s'", "The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.", "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", "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.", diff --git a/i18n/pt.json b/i18n/pt.json index 05ce23d..5eb5b4a 100644 --- a/i18n/pt.json +++ b/i18n/pt.json @@ -132,6 +132,8 @@ "Cloned: '%s'": "Clonado: '%s'", "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", + "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", "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.", diff --git a/i18n/ru.json b/i18n/ru.json index da462c3..8324723 100644 --- a/i18n/ru.json +++ b/i18n/ru.json @@ -142,6 +142,8 @@ "The cloned file '%s' was attached to this paste.": "Дубликат файла '%s' был прикреплен к этой записи.", "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": "Удалить вложение", "Your browser does not support uploading encrypted files. Please use a newer browser.": "Ваш браузер не поддерживает отправку зашифрованных файлов. Используйте более новый браузер.", diff --git a/i18n/sl.json b/i18n/sl.json index 21db8c1..fc67eac 100644 --- a/i18n/sl.json +++ b/i18n/sl.json @@ -141,6 +141,8 @@ "Cloned: '%s'": "'%s' klonirana", "The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.", "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", "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.", diff --git a/i18n/zh.json b/i18n/zh.json index 5fcaf3d..a41b6de 100644 --- a/i18n/zh.json +++ b/i18n/zh.json @@ -132,6 +132,8 @@ "Cloned: '%s'": "克隆: '%s'", "The cloned file '%s' was attached to this paste.": "克隆文件 '%s' 已附加到此粘贴。", "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": "移除附件", "Your browser does not support uploading encrypted files. Please use a newer browser.": "您的浏览器不支持上传加密的文件,请使用更新的浏览器。", diff --git a/js/privatebin.js b/js/privatebin.js index 9a8e7a3..48dc7a0 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -1520,6 +1520,10 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) { // show preview PasteViewer.setText($message.val()); + if (AttachmentViewer.hasAttachmentData()) { + var attachmentData = AttachmentViewer.getAttachmentData() || AttachmentViewer.getAttachmentLink().attr('href'); + AttachmentViewer.handleAttachmentPreview(AttachmentViewer.getAttachmentPreview(), attachmentData); + } PasteViewer.run(); // finish @@ -1855,6 +1859,7 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) { $plainText.addClass('hidden'); $prettyMessage.addClass('hidden'); $placeholder.addClass('hidden'); + AttachmentViewer.hideAttachmentPreview(); isDisplayed = false; }; @@ -1907,10 +1912,13 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) { var AttachmentViewer = (function () { var me = {}; - var $attachmentLink, - $attachmentPreview, - $attachment; - + var $attachmentLink; + var $attachmentPreview; + var $attachment; + var attachmentData; + var file; + var $fileInput; + var $dragAndDropFileName; var attachmentHasPreview = false; /** @@ -1923,8 +1931,6 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) { */ me.setAttachment = function(attachmentData, fileName) { - var imagePrefix = 'data:image/'; - // IE does not support setting a data URI on an a element // Convert dataURI to a Blob and use msSaveBlob to download if (window.Blob && navigator.msSaveBlob) { @@ -1960,15 +1966,7 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) { $attachmentLink.attr('download', fileName); } - // if the attachment is an image, display it - if (attachmentData.substring(0, imagePrefix.length) === imagePrefix) { - $attachmentPreview.html( - $(document.createElement('img')) - .attr('src', attachmentData) - .attr('class', 'img-thumbnail') - ); - attachmentHasPreview = true; - } + me.handleAttachmentPreview($attachmentPreview, attachmentData); }; /** @@ -1989,7 +1987,7 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) { /** * removes the attachment * - * This automatically hides the attachment containers to, to + * This automatically hides the attachment containers too, to * prevent an inconsistent display. * * @name AttachmentViewer.removeAttachment @@ -1997,12 +1995,18 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) { */ me.removeAttachment = function() { + if (!$attachment.length) { + return; + } me.hideAttachment(); me.hideAttachmentPreview(); - $attachmentLink.prop('href', ''); - $attachmentLink.prop('download', ''); + $attachmentLink.removeAttr('href'); + $attachmentLink.removeAttr('download'); $attachmentLink.off('click'); $attachmentPreview.html(''); + + file = undefined; + attachmentData = undefined; }; /** @@ -2028,7 +2032,9 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) { */ me.hideAttachmentPreview = function() { - $attachmentPreview.addClass('hidden'); + if ($attachmentPreview) { + $attachmentPreview.addClass('hidden'); + } }; /** @@ -2039,8 +2045,25 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) { */ me.hasAttachment = function() { + if (!$attachment.length) { + return false; + } 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')); }; + /** + * 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('