diff --git a/cfg/conf.ini.sample b/cfg/conf.ini.sample index 0d251c18..22e7eaa7 100644 --- a/cfg/conf.ini.sample +++ b/cfg/conf.ini.sample @@ -64,7 +64,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 *; 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 'self' data:; object-src 'self' data:; Referrer-Policy: 'no-referrer'" ; 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 381f72d7..ca447d5d 100644 --- a/css/bootstrap/privatebin.css +++ b/css/bootstrap/privatebin.css @@ -64,12 +64,25 @@ body.navbar-spacing { 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; } diff --git a/css/privatebin.css b/css/privatebin.css index d3c79b41..485dd0a0 100644 --- a/css/privatebin.css +++ b/css/privatebin.css @@ -72,13 +72,13 @@ h3.title { bottom: 8px; } -#aboutbox { - color: #94a3b4; +#aboutbox { + color: #94a3b4; padding: 4px 8px 4px 16px; - position: relative; + position: relative; top: 10px; border-left: 2px solid #94a3b4; - float: right; + float: right; width: 60%; } @@ -104,17 +104,29 @@ h3.title { font-family: Consolas, "Lucida Console", "DejaVu Sans Mono", Monaco, monospace; } -#image img { +#attachmentPreview img { max-width: 100%; height: auto; } -#status { +#attachmentPreview .pdfPreview { + width: 100%; + height: 100vh; + margin-bottom: 20px; +} + +.dragAndDropFile{ + color:#777; + font-size:1em; + display:inline; +} + +#status { clear: both; padding: 5px 10px; } -#pasteresult { +#pasteresult { background-color: #1F2833; color: #fff; padding: 4px 12px; @@ -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 87f55ccb..5f976daa 100644 --- a/i18n/de.json +++ b/i18n/de.json @@ -131,6 +131,8 @@ "Download attachment": "Anhang herunterladen", "Cloned file attached.": "Kopierte Datei angehängt.", "Attach a file": "Datei anhängen", + "or drag & drop file": "oder per Drag & Drop einfügen", + "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/js/privatebin.js b/js/privatebin.js index 4fd0e99b..b6623cd9 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -339,6 +339,180 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) { } }; + /** + * static attachment helper methods + * + * @name helper + * @class + */ + var attachmentHelpers = { + attachmentData: undefined, + file: undefined, + + /* + * Read file data as dataURL using the FileReader API + * https://developer.mozilla.org/en-US/docs/Web/API/FileReader#readAsDataURL() + */ + readFileData: function (file) { + if (typeof FileReader === undefined) { + // revert loading status… + this.stateNewPaste(); + this.showError(i18n._('Your browser does not support uploading encrypted files. Please use a newer browser.')); + return; + } + + var fr = new FileReader(); + if (file === undefined) { + file = controller.fileInput[0].files[0]; + $('#dragAndDropFileName').text(''); + } else { + $('#dragAndDropFileName').text(file.name); + } + + attachmentHelpers.file = file; + + fr.onload = function (e) { + var dataURL = e.target.result; + attachmentHelpers.attachmentData = dataURL; + + if (controller.messagePreview.parent().hasClass('active')) { + attachmentHelpers.handleFilePreviews(controller.attachmentPreview, dataURL); + } + }; + fr.readAsDataURL(file); + }, + + /** + * Handle the preview of files. + * @argument {DOM Element} element where the preview should be appended. + * @argument {File Data} data of the file to be displayed. + */ + handleFilePreviews: function (element, data) { + if (data) { + var mimeType = this.getMimeTypeFromDataURL(data); + + if (mimeType.match(/image\//i)) { + this.showImagePreview(element, data); + } else if (mimeType.match(/video\//i)) { + this.showVideoPreview(element, data, mimeType); + } else if (mimeType.match(/audio\//i)) { + this.showAudioPreview(element, data, mimeType); + } else if (mimeType.match(/\/pdf/i)) { + this.showPDFPreview(element, data); + } + //else { + //console.log("file but no image/video/audio/pdf"); + //} + } + }, + + /** + * Get Mime Type from a DataURL + * + * @param {type} dataURL + * @returns Mime Type from a dataURL as obtained for a file using the FileReader API https://developer.mozilla.org/en-US/docs/Web/API/FileReader#readAsDataURL() + */ + getMimeTypeFromDataURL: function (dataURL) { + return dataURL.slice(dataURL.indexOf('data:') + 5, dataURL.indexOf(';base64,')); + }, + + showImagePreview: function (element, image) { + element.html( + $(document.createElement('img')) + .attr('src', image) + .attr('class', 'img-thumbnail') + ); + element.removeClass('hidden'); + }, + + showVideoPreview: function (element, video, mimeType) { + var videoPlayer = $(document.createElement('video')) + .attr('controls', 'true') + .attr('autoplay', 'true') + .attr('loop', 'true') + .attr('class', 'img-thumbnail'); + + videoPlayer.append($(document.createElement('source')) + .attr('type', mimeType) + .attr('src', video)); + element.html(videoPlayer); + element.removeClass('hidden'); + }, + + showAudioPreview: function (element, audio, mimeType) { + var audioPlayer = $(document.createElement('audio')) + .attr('controls', 'true') + .attr('autoplay', 'true'); + + audioPlayer.append($(document.createElement('source')) + .attr('type', mimeType) + .attr('src', audio)); + element.html(audioPlayer); + element.removeClass('hidden'); + }, + + showPDFPreview: function (element, pdf) { + //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 bareable + if (pdf.length < 1398488) { + + //Fallback for browsers, that don't support the vh unit + var clientHeight = $(window).height(); + + element.html( + $(document.createElement('embed')) + .attr('src', pdf) + .attr('type', 'application/pdf') + .attr('class', 'pdfPreview') + .css('height', clientHeight) + ); + element.removeClass('hidden'); + } else { + controller.showError(i18n._('File too large, to display a preview. Please download the attachment.')); + } + }, + + addDragDropHandler: function () { + var fileInput = controller.fileInput; + + if (fileInput.length === 0) { + return; + } + + function ignoreDragDrop(e) { + e.stopPropagation(); + e.preventDefault(); + } + + function drop(e) { + e.stopPropagation(); + e.preventDefault(); + + if (fileInput) { + var file = e.dataTransfer.files[0]; + //Clear the file input: + fileInput.wrap('