Allow multiple files
This commit is contained in:
parent
6ff08b6884
commit
095a5be0b6
@ -8,6 +8,12 @@
|
||||
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
*/
|
||||
|
||||
#attachmentPreview {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#attachmentPreview img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
|
353
js/privatebin.js
353
js/privatebin.js
@ -2536,11 +2536,18 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
// show preview
|
||||
PasteViewer.setText($message.val());
|
||||
if (AttachmentViewer.hasAttachmentData()) {
|
||||
const attachment = AttachmentViewer.getAttachment();
|
||||
AttachmentViewer.handleBlobAttachmentPreview(
|
||||
AttachmentViewer.getAttachmentPreview(),
|
||||
attachment[0], attachment[1]
|
||||
);
|
||||
const attachmentsData = AttachmentViewer.getAttachmentsData();
|
||||
|
||||
attachmentsData.forEach(attachmentData => {
|
||||
const mimeType = AttachmentViewer.getAttachmentMimeType(attachmentData);
|
||||
|
||||
AttachmentViewer.handleBlobAttachmentPreview(
|
||||
AttachmentViewer.getAttachmentPreview(),
|
||||
attachmentData, mimeType
|
||||
);
|
||||
});
|
||||
|
||||
AttachmentViewer.showAttachment();
|
||||
}
|
||||
PasteViewer.run();
|
||||
|
||||
@ -2925,14 +2932,12 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
const AttachmentViewer = (function () {
|
||||
const me = {};
|
||||
|
||||
let $attachmentLink,
|
||||
$attachmentPreview,
|
||||
let $attachmentPreview,
|
||||
$attachment,
|
||||
attachmentData,
|
||||
file,
|
||||
attachmentsData = [],
|
||||
files,
|
||||
$fileInput,
|
||||
$dragAndDropFileName,
|
||||
attachmentHasPreview = false,
|
||||
$dragAndDropFileNames,
|
||||
$dropzone;
|
||||
|
||||
/**
|
||||
@ -2974,26 +2979,28 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
me.setAttachment = function(attachmentData, fileName)
|
||||
{
|
||||
// skip, if attachments got disabled
|
||||
if (!$attachmentLink || !$attachmentPreview) return;
|
||||
if (!$attachment || !$attachmentPreview) return;
|
||||
|
||||
// data URI format: data:[<mimeType>][;base64],<data>
|
||||
|
||||
const template = Model.getTemplate('attachment');
|
||||
const attachmentLink = template.find('a');
|
||||
|
||||
// position in data URI string of where data begins
|
||||
const base64Start = attachmentData.indexOf(',') + 1;
|
||||
// position in data URI string of where mimeType ends
|
||||
const mimeTypeEnd = attachmentData.indexOf(';');
|
||||
|
||||
// extract mimeType
|
||||
const mimeType = attachmentData.substring(5, mimeTypeEnd);
|
||||
const mimeType = me.getAttachmentMimeType(attachmentData);
|
||||
|
||||
// extract data and convert to binary
|
||||
const rawData = attachmentData.substring(base64Start);
|
||||
const decodedData = rawData.length > 0 ? atob(rawData) : '';
|
||||
|
||||
let blobUrl = getBlobUrl(decodedData, mimeType);
|
||||
$attachmentLink.attr('href', blobUrl);
|
||||
attachmentLink.attr('href', blobUrl);
|
||||
|
||||
if (typeof fileName !== 'undefined') {
|
||||
$attachmentLink.attr('download', fileName);
|
||||
attachmentLink.attr('download', fileName);
|
||||
template.append(fileName);
|
||||
}
|
||||
|
||||
// sanitize SVG preview
|
||||
@ -3008,6 +3015,9 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
blobUrl = getBlobUrl(sanitizedData, mimeType);
|
||||
}
|
||||
|
||||
template.removeClass('hidden');
|
||||
$attachment.append(template);
|
||||
|
||||
me.handleBlobAttachmentPreview($attachmentPreview, blobUrl, mimeType);
|
||||
};
|
||||
|
||||
@ -3024,7 +3034,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
|
||||
$attachment.removeClass('hidden');
|
||||
|
||||
if (attachmentHasPreview) {
|
||||
if (me.hasAttachmentPreview()) {
|
||||
$attachmentPreview.removeClass('hidden');
|
||||
}
|
||||
};
|
||||
@ -3045,11 +3055,9 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
}
|
||||
me.hideAttachment();
|
||||
me.hideAttachmentPreview();
|
||||
$attachmentLink.removeAttr('href');
|
||||
$attachmentLink.removeAttr('download');
|
||||
$attachmentLink.off('click');
|
||||
$attachment.html('');
|
||||
$attachmentPreview.html('');
|
||||
$dragAndDropFileName.text('');
|
||||
$dragAndDropFileNames.html('');
|
||||
|
||||
AttachmentViewer.removeAttachmentData();
|
||||
};
|
||||
@ -3064,8 +3072,8 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
*/
|
||||
me.removeAttachmentData = function()
|
||||
{
|
||||
file = undefined;
|
||||
attachmentData = undefined;
|
||||
files = undefined;
|
||||
attachmentsData = [];
|
||||
};
|
||||
|
||||
/**
|
||||
@ -3076,9 +3084,21 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
*/
|
||||
me.clearDragAndDrop = function()
|
||||
{
|
||||
$dragAndDropFileName.text('');
|
||||
$dragAndDropFileNames.html('');
|
||||
};
|
||||
|
||||
/**
|
||||
* Print file names added via drag & drop
|
||||
*
|
||||
* @name AttachmentViewer.printDragAndDropFileNames
|
||||
* @private
|
||||
* @function
|
||||
* @param {array} fileNames
|
||||
*/
|
||||
function printDragAndDropFileNames(fileNames) {
|
||||
$dragAndDropFileNames.html(fileNames.join("<br>"));
|
||||
}
|
||||
|
||||
/**
|
||||
* hides the attachment
|
||||
*
|
||||
@ -3107,6 +3127,18 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* checks if has any attachment preview
|
||||
*
|
||||
* @name AttachmentViewer.hasAttachmentPreview
|
||||
* @function
|
||||
* @return {JQuery}
|
||||
*/
|
||||
me.hasAttachmentPreview = function()
|
||||
{
|
||||
return $attachmentPreview.children().length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* checks if there is an attachment displayed
|
||||
*
|
||||
@ -3118,8 +3150,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
if (!$attachment.length) {
|
||||
return false;
|
||||
}
|
||||
const link = $attachmentLink.prop('href');
|
||||
return (typeof link !== 'undefined' && link !== '');
|
||||
return [...$attachment.children()].length > 0;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -3139,20 +3170,38 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
};
|
||||
|
||||
/**
|
||||
* return the attachment
|
||||
* return the attachments
|
||||
*
|
||||
* @name AttachmentViewer.getAttachment
|
||||
* @name AttachmentViewer.getAttachments
|
||||
* @function
|
||||
* @returns {array}
|
||||
*/
|
||||
me.getAttachment = function()
|
||||
me.getAttachments = function()
|
||||
{
|
||||
return [
|
||||
$attachmentLink.prop('href'),
|
||||
$attachmentLink.prop('download')
|
||||
];
|
||||
return [...$attachment.find('a')].map(link => (
|
||||
[
|
||||
$(link).prop('href'),
|
||||
$(link).prop('download')
|
||||
]
|
||||
));
|
||||
};
|
||||
|
||||
/**
|
||||
* Get attachment mime type
|
||||
*
|
||||
* @name AttachmentViewer.getAttachmentMimeType
|
||||
* @function
|
||||
* @param {string} attachmentData - Base64 string
|
||||
*/
|
||||
me.getAttachmentMimeType = function(attachmentData)
|
||||
{
|
||||
// position in data URI string of where mimeType ends
|
||||
const mimeTypeEnd = attachmentData.indexOf(';');
|
||||
|
||||
// extract mimeType
|
||||
return attachmentData.substring(5, mimeTypeEnd);
|
||||
}
|
||||
|
||||
/**
|
||||
* moves the attachment link to another element
|
||||
*
|
||||
@ -3161,27 +3210,33 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
* @name AttachmentViewer.moveAttachmentTo
|
||||
* @function
|
||||
* @param {jQuery} $element - the wrapper/container element where this should be moved to
|
||||
* @param {array} attachment - attachment data
|
||||
* @param {string} label - the text to show (%s will be replaced with the file name), will automatically be translated
|
||||
*/
|
||||
me.moveAttachmentTo = function($element, label)
|
||||
me.moveAttachmentTo = function($element, attachment, label)
|
||||
{
|
||||
const attachmentLink = $(document.createElement('a'))
|
||||
.addClass('alert-link')
|
||||
.prop('href', attachment[0])
|
||||
.prop('download', attachment[1]);
|
||||
|
||||
// move elemement to new place
|
||||
$attachmentLink.appendTo($element);
|
||||
attachmentLink.appendTo($element);
|
||||
|
||||
// update text - ensuring no HTML is inserted into the text node
|
||||
I18n._($attachmentLink, label, $attachmentLink.attr('download'));
|
||||
I18n._(attachmentLink, label, attachment[1]);
|
||||
};
|
||||
|
||||
/**
|
||||
* read file data as data URL using the FileReader API
|
||||
* read files data as data URL using the FileReader API
|
||||
*
|
||||
* @name AttachmentViewer.readFileData
|
||||
* @private
|
||||
* @function
|
||||
* @param {object} loadedFile (optional) loaded file object
|
||||
* @param {FileList[]} loadedFiles (optional) loaded files array
|
||||
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/FileReader#readAsDataURL()}
|
||||
*/
|
||||
function readFileData(loadedFile) {
|
||||
function readFileData(loadedFiles) {
|
||||
if (typeof FileReader === 'undefined') {
|
||||
// revert loading status…
|
||||
me.hideAttachment();
|
||||
@ -3190,28 +3245,35 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
return;
|
||||
}
|
||||
|
||||
const fileReader = new FileReader();
|
||||
if (loadedFile === undefined) {
|
||||
loadedFile = $fileInput[0].files[0];
|
||||
$dragAndDropFileName.text('');
|
||||
if (loadedFiles === undefined) {
|
||||
loadedFiles = [...$fileInput[0].files];
|
||||
me.clearDragAndDrop();
|
||||
} else {
|
||||
$dragAndDropFileName.text(loadedFile.name);
|
||||
const fileNames = loadedFiles.map((loadedFile => loadedFile.name));
|
||||
printDragAndDropFileNames(fileNames);
|
||||
}
|
||||
|
||||
if (typeof loadedFile !== 'undefined') {
|
||||
file = loadedFile;
|
||||
fileReader.onload = function (event) {
|
||||
const dataURL = event.target.result;
|
||||
attachmentData = dataURL;
|
||||
if (typeof loadedFiles !== 'undefined') {
|
||||
files = loadedFiles;
|
||||
loadedFiles.forEach(loadedFile => {
|
||||
const fileReader = new FileReader();
|
||||
|
||||
if (Editor.isPreview()) {
|
||||
me.handleAttachmentPreview($attachmentPreview, dataURL);
|
||||
$attachmentPreview.removeClass('hidden');
|
||||
}
|
||||
fileReader.onload = function (event) {
|
||||
const dataURL = event.target.result;
|
||||
if (dataURL) {
|
||||
attachmentsData.push(dataURL);
|
||||
}
|
||||
|
||||
TopNav.highlightFileupload();
|
||||
};
|
||||
fileReader.readAsDataURL(loadedFile);
|
||||
if (Editor.isPreview()) {
|
||||
me.handleAttachmentPreview($attachmentPreview, dataURL);
|
||||
$attachmentPreview.removeClass('hidden');
|
||||
}
|
||||
|
||||
TopNav.highlightFileupload();
|
||||
};
|
||||
|
||||
fileReader.readAsDataURL(loadedFile);
|
||||
});
|
||||
} else {
|
||||
me.removeAttachmentData();
|
||||
}
|
||||
@ -3227,16 +3289,17 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
* @argument {string} mime type
|
||||
*/
|
||||
me.handleBlobAttachmentPreview = function ($targetElement, blobUrl, mimeType) {
|
||||
if (blobUrl) {
|
||||
attachmentHasPreview = true;
|
||||
const alreadyIncludesCurrentAttachment = $targetElement.find(`[src='${blobUrl}']`).length > 0;
|
||||
|
||||
if (blobUrl && !alreadyIncludesCurrentAttachment) {
|
||||
if (mimeType.match(/^image\//i)) {
|
||||
$targetElement.html(
|
||||
$targetElement.append(
|
||||
$(document.createElement('img'))
|
||||
.attr('src', blobUrl)
|
||||
.attr('class', 'img-thumbnail')
|
||||
);
|
||||
} else if (mimeType.match(/^video\//i)) {
|
||||
$targetElement.html(
|
||||
$targetElement.append(
|
||||
$(document.createElement('video'))
|
||||
.attr('controls', 'true')
|
||||
.attr('autoplay', 'true')
|
||||
@ -3247,7 +3310,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
.attr('src', blobUrl))
|
||||
);
|
||||
} else if (mimeType.match(/^audio\//i)) {
|
||||
$targetElement.html(
|
||||
$targetElement.append(
|
||||
$(document.createElement('audio'))
|
||||
.attr('controls', 'true')
|
||||
.attr('autoplay', 'true')
|
||||
@ -3260,15 +3323,13 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
// Fallback for browsers, that don't support the vh unit
|
||||
const clientHeight = $(window).height();
|
||||
|
||||
$targetElement.html(
|
||||
$targetElement.append(
|
||||
$(document.createElement('embed'))
|
||||
.attr('src', blobUrl)
|
||||
.attr('type', 'application/pdf')
|
||||
.attr('class', 'pdfPreview')
|
||||
.css('height', clientHeight)
|
||||
);
|
||||
} else {
|
||||
attachmentHasPreview = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -3301,14 +3362,14 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
}
|
||||
|
||||
if ($fileInput) {
|
||||
const file = evt.dataTransfer.files[0];
|
||||
const files = [...evt.dataTransfer.files];
|
||||
//Clear the file input:
|
||||
$fileInput.wrap('<form>').closest('form').get(0).reset();
|
||||
$fileInput.unwrap();
|
||||
//Only works in Chrome:
|
||||
//fileInput[0].files = e.dataTransfer.files;
|
||||
|
||||
readFileData(file);
|
||||
readFileData(files);
|
||||
}
|
||||
};
|
||||
|
||||
@ -3362,23 +3423,12 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
/**
|
||||
* getter for attachment data
|
||||
*
|
||||
* @name AttachmentViewer.getAttachmentData
|
||||
* @name AttachmentViewer.getAttachmentsData
|
||||
* @function
|
||||
* @return {jQuery}
|
||||
* @return {string[]}
|
||||
*/
|
||||
me.getAttachmentData = function () {
|
||||
return attachmentData;
|
||||
};
|
||||
|
||||
/**
|
||||
* getter for attachment link
|
||||
*
|
||||
* @name AttachmentViewer.getAttachmentLink
|
||||
* @function
|
||||
* @return {jQuery}
|
||||
*/
|
||||
me.getAttachmentLink = function () {
|
||||
return $attachmentLink;
|
||||
me.getAttachmentsData = function () {
|
||||
return attachmentsData;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -3393,14 +3443,14 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
};
|
||||
|
||||
/**
|
||||
* getter for file data, returns the file contents
|
||||
* getter for files data, returns the file list
|
||||
*
|
||||
* @name AttachmentViewer.getFile
|
||||
* @name AttachmentViewer.getFiles
|
||||
* @function
|
||||
* @return {string}
|
||||
* @return {FileList[]}
|
||||
*/
|
||||
me.getFile = function () {
|
||||
return file;
|
||||
me.getFiles = function () {
|
||||
return files;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -3414,9 +3464,8 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
me.init = function()
|
||||
{
|
||||
$attachment = $('#attachment');
|
||||
$dragAndDropFileName = $('#dragAndDropFileName');
|
||||
$dragAndDropFileNames = $('#dragAndDropFileName');
|
||||
$dropzone = $('#dropzone');
|
||||
$attachmentLink = $('#attachment a') || $('<a>');
|
||||
if($attachment.length) {
|
||||
$attachmentPreview = $('#attachmentPreview');
|
||||
|
||||
@ -5135,7 +5184,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
const plainText = Editor.getText(),
|
||||
format = PasteViewer.getFormat(),
|
||||
// the methods may return different values if no files are attached (null, undefined or false)
|
||||
files = TopNav.getFileList() || AttachmentViewer.getFile() || AttachmentViewer.hasAttachment();
|
||||
files = TopNav.getFileList() || AttachmentViewer.getFiles() || AttachmentViewer.hasAttachment();
|
||||
|
||||
// do not send if there is no data
|
||||
if (plainText.length === 0 && !files) {
|
||||
@ -5175,62 +5224,64 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
PasteViewer.setFormat(format);
|
||||
|
||||
// prepare cypher message
|
||||
let file = AttachmentViewer.getAttachmentData(),
|
||||
let attachmentsData = AttachmentViewer.getAttachmentsData(),
|
||||
cipherMessage = {
|
||||
'paste': plainText
|
||||
};
|
||||
if (typeof file !== 'undefined' && file !== null) {
|
||||
cipherMessage['attachment'] = file;
|
||||
cipherMessage['attachment_name'] = AttachmentViewer.getFile().name;
|
||||
if (attachmentsData.length) {
|
||||
cipherMessage['attachment'] = attachmentsData;
|
||||
cipherMessage['attachment_name'] = AttachmentViewer.getFiles().map((fileInfo => fileInfo.name));
|
||||
} else if (AttachmentViewer.hasAttachment()) {
|
||||
// fall back to cloned part
|
||||
let attachment = AttachmentViewer.getAttachment();
|
||||
cipherMessage['attachment'] = attachment[0];
|
||||
cipherMessage['attachment_name'] = attachment[1];
|
||||
let attachments = AttachmentViewer.getAttachments();
|
||||
cipherMessage['attachment'] = attachments.map(attachment => attachment[0]);
|
||||
cipherMessage['attachment_name'] = attachments.map(attachment => attachment[1]);
|
||||
|
||||
// we need to retrieve data from blob if browser already parsed it in memory
|
||||
if (typeof attachment[0] === 'string' && attachment[0].startsWith('blob:')) {
|
||||
Alert.showStatus(
|
||||
[
|
||||
'Retrieving cloned file \'%s\' from memory...',
|
||||
attachment[1]
|
||||
],
|
||||
'copy'
|
||||
);
|
||||
try {
|
||||
const blobData = await $.ajax({
|
||||
type: 'GET',
|
||||
url: `${attachment[0]}`,
|
||||
processData: false,
|
||||
timeout: 10000,
|
||||
xhrFields: {
|
||||
withCredentials: false,
|
||||
responseType: 'blob'
|
||||
}
|
||||
});
|
||||
if (blobData instanceof window.Blob) {
|
||||
const fileReading = new Promise(function(resolve, reject) {
|
||||
const fileReader = new FileReader();
|
||||
fileReader.onload = function (event) {
|
||||
resolve(event.target.result);
|
||||
};
|
||||
fileReader.onerror = function (error) {
|
||||
reject(error);
|
||||
cipherMessage['attachment'] = await Promise.all(cipherMessage['attachment'].map(async (attachment) => {
|
||||
// we need to retrieve data from blob if browser already parsed it in memory
|
||||
if (typeof attachment === 'string' && attachment.startsWith('blob:')) {
|
||||
Alert.showStatus(
|
||||
[
|
||||
'Retrieving cloned file \'%s\' from memory...',
|
||||
attachment[1]
|
||||
],
|
||||
'copy'
|
||||
);
|
||||
try {
|
||||
const blobData = await $.ajax({
|
||||
type: 'GET',
|
||||
url: `${attachment}`,
|
||||
processData: false,
|
||||
timeout: 10000,
|
||||
xhrFields: {
|
||||
withCredentials: false,
|
||||
responseType: 'blob'
|
||||
}
|
||||
fileReader.readAsDataURL(blobData);
|
||||
});
|
||||
cipherMessage['attachment'] = await fileReading;
|
||||
} else {
|
||||
const error = 'Cannot process attachment data.';
|
||||
Alert.showError(error);
|
||||
throw new TypeError(error);
|
||||
if (blobData instanceof window.Blob) {
|
||||
const fileReading = new Promise(function(resolve, reject) {
|
||||
const fileReader = new FileReader();
|
||||
fileReader.onload = function (event) {
|
||||
resolve(event.target.result);
|
||||
};
|
||||
fileReader.onerror = function (error) {
|
||||
reject(error);
|
||||
}
|
||||
fileReader.readAsDataURL(blobData);
|
||||
});
|
||||
|
||||
return await fileReading;
|
||||
} else {
|
||||
const error = 'Cannot process attachment data.';
|
||||
Alert.showError(error);
|
||||
throw new TypeError(error);
|
||||
}
|
||||
} catch (error) {
|
||||
Alert.showError('Cannot retrieve attachment.');
|
||||
throw error;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
Alert.showError('Cannot retrieve attachment.');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
// encrypt message
|
||||
@ -5325,7 +5376,15 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
// version 2 paste
|
||||
const pasteMessage = JSON.parse(pastePlain);
|
||||
if (pasteMessage.hasOwnProperty('attachment') && pasteMessage.hasOwnProperty('attachment_name')) {
|
||||
AttachmentViewer.setAttachment(pasteMessage.attachment, pasteMessage.attachment_name);
|
||||
if (Array.isArray(pasteMessage.attachment) && Array.isArray(pasteMessage.attachment_name)) {
|
||||
pasteMessage.attachment.forEach((attachment, key) => {
|
||||
const attachment_name = pasteMessage.attachment_name[key];
|
||||
AttachmentViewer.setAttachment(attachment, attachment_name);
|
||||
});
|
||||
} else {
|
||||
// Continue to process attachment parameters as strings to ensure backward compatibility
|
||||
AttachmentViewer.setAttachment(pasteMessage.attachment, pasteMessage.attachment_name);
|
||||
}
|
||||
AttachmentViewer.showAttachment();
|
||||
}
|
||||
pastePlain = pasteMessage.paste;
|
||||
@ -5808,10 +5867,14 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
history.pushState({type: 'clone'}, document.title, Helper.baseUri());
|
||||
|
||||
if (AttachmentViewer.hasAttachment()) {
|
||||
AttachmentViewer.moveAttachmentTo(
|
||||
TopNav.getCustomAttachment(),
|
||||
'Cloned: \'%s\''
|
||||
);
|
||||
const attachments = AttachmentViewer.getAttachments();
|
||||
attachments.forEach(attachment => {
|
||||
AttachmentViewer.moveAttachmentTo(
|
||||
TopNav.getCustomAttachment(),
|
||||
attachment,
|
||||
'Cloned: \'%s\''
|
||||
);
|
||||
});
|
||||
TopNav.hideFileSelector();
|
||||
AttachmentViewer.hideAttachment();
|
||||
// NOTE: it also looks nice without removing the attachment
|
||||
@ -5819,12 +5882,12 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
AttachmentViewer.hideAttachmentPreview();
|
||||
TopNav.showCustomAttachment();
|
||||
|
||||
// show another status message to make the user aware that the
|
||||
// file was cloned too!
|
||||
// show another status messages to make the user aware that the
|
||||
// files were cloned too!
|
||||
Alert.showStatus(
|
||||
[
|
||||
'The cloned file \'%s\' was attached to this paste.',
|
||||
AttachmentViewer.getAttachment()[1]
|
||||
attachments.map(attachment => attachment[1]).join(', '),
|
||||
],
|
||||
'copy'
|
||||
);
|
||||
|
@ -27,11 +27,14 @@ describe('AttachmentViewer', function () {
|
||||
prefix = prefix.replace(/%(s|d)/g, '%%');
|
||||
postfix = postfix.replace(/%(s|d)/g, '%%');
|
||||
$('body').html(
|
||||
'<div id="attachment" role="alert" class="hidden alert ' +
|
||||
'alert-info"><span class="glyphicon glyphicon-download-' +
|
||||
'alt" aria-hidden="true"></span> <a class="alert-link">' +
|
||||
'Download attachment</a></div><div id="attachmentPrevie' +
|
||||
'w" class="hidden"></div>'
|
||||
'<div id="attachmentPreview" class="col-md-12 text-center hidden"></div>' +
|
||||
'<div id="attachment" class="hidden"></div>' +
|
||||
'<div id="templates">' +
|
||||
'<div id="attachmenttemplate" role="alert" class="attachment hidden alert alert-info">' +
|
||||
'<span class="glyphicon glyphicon-download-alt" aria-hidden="true"></span>' +
|
||||
'<a class="alert-link">Download attachment</a>' +
|
||||
'</div>' +
|
||||
'</div>'
|
||||
);
|
||||
// mock createObjectURL for jsDOM
|
||||
if (typeof window.URL.createObjectURL === 'undefined') {
|
||||
@ -44,9 +47,12 @@ describe('AttachmentViewer', function () {
|
||||
)
|
||||
}
|
||||
$.PrivateBin.AttachmentViewer.init();
|
||||
$.PrivateBin.Model.init();
|
||||
results.push(
|
||||
!$.PrivateBin.AttachmentViewer.hasAttachment() &&
|
||||
$('#attachment').hasClass('hidden') &&
|
||||
$('#attachment').children().length === 0 &&
|
||||
$('#attachmenttemplate').hasClass('hidden') &&
|
||||
$('#attachmentPreview').hasClass('hidden')
|
||||
);
|
||||
global.atob = common.atob;
|
||||
@ -55,19 +61,21 @@ describe('AttachmentViewer', function () {
|
||||
} else {
|
||||
$.PrivateBin.AttachmentViewer.setAttachment(data);
|
||||
}
|
||||
// beyond this point we will get the blob URL instead of the data
|
||||
// // beyond this point we will get the blob URL instead of the data
|
||||
data = window.URL.createObjectURL(data);
|
||||
const attachment = $.PrivateBin.AttachmentViewer.getAttachment();
|
||||
const attachment = $.PrivateBin.AttachmentViewer.getAttachments();
|
||||
results.push(
|
||||
$.PrivateBin.AttachmentViewer.hasAttachment() &&
|
||||
$('#attachment').hasClass('hidden') &&
|
||||
$('#attachment').children().length > 0 &&
|
||||
$('#attachmentPreview').hasClass('hidden') &&
|
||||
attachment[0] === data &&
|
||||
attachment[1] === filename
|
||||
attachment[0][0] === data &&
|
||||
attachment[0][1] === filename
|
||||
);
|
||||
$.PrivateBin.AttachmentViewer.showAttachment();
|
||||
results.push(
|
||||
!$('#attachment').hasClass('hidden') &&
|
||||
$('#attachment').children().length > 0 &&
|
||||
(previewSupported ? !$('#attachmentPreview').hasClass('hidden') : $('#attachmentPreview').hasClass('hidden'))
|
||||
);
|
||||
$.PrivateBin.AttachmentViewer.hideAttachment();
|
||||
@ -85,7 +93,7 @@ describe('AttachmentViewer', function () {
|
||||
(previewSupported ? !$('#attachmentPreview').hasClass('hidden') : $('#attachmentPreview').hasClass('hidden'))
|
||||
);
|
||||
let element = $('<div>');
|
||||
$.PrivateBin.AttachmentViewer.moveAttachmentTo(element, prefix + '%s' + postfix);
|
||||
$.PrivateBin.AttachmentViewer.moveAttachmentTo(element, attachment[0], prefix + '%s' + postfix);
|
||||
// messageIDs with links get a relaxed treatment
|
||||
if (prefix.indexOf('<a') === -1 && postfix.indexOf('<a') === -1) {
|
||||
result = $('<textarea>').text((prefix + filename + postfix)).text();
|
||||
@ -99,16 +107,17 @@ describe('AttachmentViewer', function () {
|
||||
}
|
||||
if (filename.length) {
|
||||
results.push(
|
||||
element.children()[0].href === data &&
|
||||
element.children()[0].getAttribute('download') === filename &&
|
||||
element.children()[0].text === result
|
||||
element.find('a')[0].href === data &&
|
||||
element.find('a')[0].getAttribute('download') === filename &&
|
||||
element.find('a')[0].text === result
|
||||
);
|
||||
} else {
|
||||
results.push(element.children()[0].href === data);
|
||||
results.push(element.find('a')[0].href === data);
|
||||
}
|
||||
$.PrivateBin.AttachmentViewer.removeAttachment();
|
||||
results.push(
|
||||
$('#attachment').hasClass('hidden') &&
|
||||
$('#attachment').children().length === 0 &&
|
||||
$('#attachmentPreview').hasClass('hidden')
|
||||
);
|
||||
clean();
|
||||
|
@ -119,7 +119,7 @@ class Configuration
|
||||
'js/kjua-0.9.0.js' => 'sha512-CVn7af+vTMBd9RjoS4QM5fpLFEOtBCoB0zPtaqIDC7sF4F8qgUSRFQQpIyEDGsr6yrjbuOLzdf20tkHHmpaqwQ==',
|
||||
'js/legacy.js' => 'sha512-UxW/TOZKon83n6dk/09GsYKIyeO5LeBHokxyIq+r7KFS5KMBeIB/EM7NrkVYIezwZBaovnyNtY2d9tKFicRlXg==',
|
||||
'js/prettify.js' => 'sha512-puO0Ogy++IoA2Pb9IjSxV1n4+kQkKXYAEUtVzfZpQepyDPyXk8hokiYDS7ybMogYlyyEIwMLpZqVhCkARQWLMg==',
|
||||
'js/privatebin.js' => 'sha512-QkOUM8rg4MI60YRwHqWmayBzCdf/e3XnbHtrX17h2nn0EcyOQNhtSq8a0dXR1hoQFHFfF+9PiT73nZ6qoogjQA==',
|
||||
'js/privatebin.js' => 'm6RrsOsz4RgIWXDzgRghQDx6aegFCpkpqURwhfXwE/rNWhe/1rPJaLR+FXII82iTWo0n9JCzSbqrDqkYVPI50w==',
|
||||
'js/purify-3.2.5.js' => 'sha512-eLlLLL/zYuf5JuG0x4WQm687MToqOGP9cDQHIdmOy1ZpjiY4J48BBcOM7DtZheKk1UogW920+9RslWYB4KGuuA==',
|
||||
'js/rawinflate-0.3.js' => 'sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==',
|
||||
'js/showdown-2.1.0.js' => 'sha512-WYXZgkTR0u/Y9SVIA4nTTOih0kXMEd8RRV6MLFdL6YU8ymhR528NLlYQt1nlJQbYz4EW+ZsS0fx1awhiQJme1Q==',
|
||||
|
@ -386,7 +386,7 @@ if ($FILEUPLOAD) :
|
||||
<ul class="dropdown-menu">
|
||||
<li id="filewrap">
|
||||
<div>
|
||||
<input type="file" id="file" name="file" />
|
||||
<input type="file" id="file" name="file" multiple />
|
||||
</div>
|
||||
<div id="dragAndDropFileName" class="dragAndDropFile"><?php echo I18n::_('alternatively drag & drop a file or paste an image from the clipboard'); ?></div>
|
||||
</li>
|
||||
@ -505,10 +505,7 @@ endif;
|
||||
<?php
|
||||
if ($FILEUPLOAD) :
|
||||
?>
|
||||
<div id="attachment" role="alert" class="hidden alert alert-info">
|
||||
<span class="glyphicon glyphicon-download-alt" aria-hidden="true"></span>
|
||||
<a class="alert-link"><?php echo I18n::_('Download attachment'); ?></a>
|
||||
</div>
|
||||
<div id="attachment" class="hidden"></div>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
@ -656,9 +653,6 @@ endif;
|
||||
</div>
|
||||
</footer>
|
||||
</main>
|
||||
<?php
|
||||
if ($DISCUSSION) :
|
||||
?>
|
||||
<div id="serverdata" class="hidden" aria-hidden="true">
|
||||
<div id="templates">
|
||||
<article id="commenttemplate" class="comment">
|
||||
@ -680,12 +674,13 @@ if ($DISCUSSION) :
|
||||
</div>
|
||||
<button id="replybutton" class="btn btn-default btn-sm"><?php echo I18n::_('Post comment'); ?></button>
|
||||
</div>
|
||||
<div id="attachmenttemplate" role="alert" class="attachment hidden alert alert-info">
|
||||
<span class="glyphicon glyphicon-download-alt" aria-hidden="true"></span>
|
||||
<a class="alert-link"><?php echo I18n::_('Download attachment'); ?></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
<?php
|
||||
if ($FILEUPLOAD) :
|
||||
?>
|
||||
<div id="dropzone" class="hidden" tabindex="-1" aria-hidden="true"></div>
|
||||
|
@ -261,11 +261,11 @@ if ($FILEUPLOAD) :
|
||||
<ul class="dropdown-menu px-2">
|
||||
<li id="filewrap">
|
||||
<div>
|
||||
<input type="file" id="file" name="file" class="form-control" />
|
||||
<input type="file" id="file" name="file" class="form-control" multiple />
|
||||
</div>
|
||||
<div id="dragAndDropFileName" class="dragAndDropFile"><?php echo I18n::_('alternatively drag & drop a file or paste an image from the clipboard'); ?></div>
|
||||
</li>
|
||||
<li id="customattachment" class="hidden"></li>
|
||||
<li id="customattachment" class="hidden d-flex flex-column px-3"></li>
|
||||
<li>
|
||||
<a id="fileremovebutton" href="#" class="dropdown-item">
|
||||
<?php echo I18n::_('Remove attachment'), PHP_EOL; ?>
|
||||
@ -370,10 +370,7 @@ endif;
|
||||
<?php
|
||||
if ($FILEUPLOAD) :
|
||||
?>
|
||||
<div id="attachment" role="alert" class="hidden alert alert-info">
|
||||
<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#download" /></svg>
|
||||
<a class="alert-link"><?php echo I18n::_('Download attachment'); ?></a>
|
||||
</div>
|
||||
<div id="attachment" class="hidden"></div>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
@ -514,9 +511,6 @@ endif;
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
<?php
|
||||
if ($DISCUSSION) :
|
||||
?>
|
||||
<div id="serverdata" class="hidden" aria-hidden="true">
|
||||
<div id="templates">
|
||||
<article id="commenttemplate" class="comment px-2 pb-3">
|
||||
@ -538,12 +532,13 @@ if ($DISCUSSION) :
|
||||
</div>
|
||||
<button id="replybutton" class="btn btn-secondary btn-sm"><?php echo I18n::_('Post comment'); ?></button>
|
||||
</div>
|
||||
<div id="attachmenttemplate" role="alert" class="hidden alert alert-info">
|
||||
<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#download" /></svg>
|
||||
<a class="alert-link"><?php echo I18n::_('Download attachment'); ?></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
<?php
|
||||
if ($FILEUPLOAD) :
|
||||
?>
|
||||
<div id="dropzone" class="hidden" tabindex="-1" aria-hidden="true"></div>
|
||||
|
13
tpl/page.php
13
tpl/page.php
@ -265,10 +265,10 @@ endif;
|
||||
<?php
|
||||
if ($FILEUPLOAD):
|
||||
?>
|
||||
<div id="attachment" class="hidden"><a><?php echo I18n::_('Download attachment'); ?></a></div>
|
||||
<div id="attachment" class="hidden"></div>
|
||||
<div id="attach" class="hidden">
|
||||
<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" multiple /></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>
|
||||
</div>
|
||||
@ -297,9 +297,6 @@ endif;
|
||||
<div id="commentcontainer"></div>
|
||||
</div>
|
||||
</section>
|
||||
<?php
|
||||
if ($DISCUSSION):
|
||||
?>
|
||||
<div id="serverdata" class="hidden" aria-hidden="true">
|
||||
<div id="templates">
|
||||
<article id="commenttemplate" class="comment">
|
||||
@ -321,12 +318,12 @@ if ($DISCUSSION):
|
||||
</div>
|
||||
<button id="replybutton" class="btn btn-default btn-sm"><?php echo I18n::_('Post comment'); ?></button>
|
||||
</div>
|
||||
<div id="attachmenttemplate" class="attachment">
|
||||
<a><?php echo I18n::_('Download attachment'); ?></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
<?php
|
||||
if ($FILEUPLOAD):
|
||||
?>
|
||||
<div id="dropzone" class="hidden" tabindex="-1" aria-hidden="true"></div>
|
||||
|
Loading…
x
Reference in New Issue
Block a user