@ -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 to o , 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 ( '<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
*
@ -2088,10 +2329,16 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) {
me . init = function ( )
{
$attachment = $ ( '#attachment' ) ;
$attachmentLink = $ ( '#attachment a' ) ;
$attachmentPreview = $ ( '#attachmentPreview' ) ;
attachmentHasPreview = false ;
} ;
if ( $attachment . length ) {
$attachmentLink = $ ( '#attachment a' ) ;
$attachmentPreview = $ ( '#attachmentPreview' ) ;
$dragAndDropFileName = $ ( '#dragAndDropFileName' ) ;
$fileInput = $ ( '#file' ) ;
me . addDragDropHandler ( ) ;
me . addClipboardEventHandler ( ) ;
}
}
return me ;
} ) ( ) ;
@ -3328,31 +3575,19 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) {
* @ name PasteEncrypter . encryptAttachments
* @ private
* @ function
* @ param { File | null | undefined } file - optional , falls back to cloned attachment
* @ param { function } callback - excuted when action is successful
* /
function encryptAttachments ( file , callback ) {
if ( typeof file !== 'undefined' && file !== null ) {
// 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 ;
}
function encryptAttachments ( callback ) {
var file = AttachmentViewer . getAttachmentData ( ) ;
var reader = new FileReader ( ) ;
// closure to capture the file information
reader . onload = function ( event ) {
Uploader . setData ( 'attachment' , event . target . result ) ;
Uploader . setData ( 'attachmentname' , file . name ) ;
if ( typeof file !== 'undefined' && file !== null ) {
var fileName = AttachmentViewer . getFile ( ) . name ;
// run callback
return callback ( ) ;
} ;
Uploader . setData ( 'attachment' , file ) ;
Uploader . setData ( 'attachmentname' , fileName ) ;
// actually read first file
reader . readAsDataURL ( file ) ;
// run callback
return callback ( ) ;
} else if ( AttachmentViewer . hasAttachment ( ) ) {
// fall back to cloned part
var attachment = AttachmentViewer . getAttachment ( ) ;
@ -3461,7 +3696,7 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) {
// get data
var plainText = Editor . getText ( ) ,
format = PasteViewer . getFormat ( ) ,
files = TopNav . getFileList ( ) ;
files = TopNav . getFileList ( ) || AttachmentViewer . getFile ( ) || AttachmentViewer . hasAttachment ( ) ;
// do not send if there is no data
if ( plainText . length === 0 && files === null ) {
@ -3512,7 +3747,6 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) {
// encrypt attachments
encryptAttachments (
files === null ? null : files [ 0 ] ,
function ( ) {
// send data
Uploader . run ( ) ;
@ -3727,10 +3961,12 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) {
try {
// decrypt attachments
if ( paste . attachment ) {
// try to decrypt paste and if it fails (because the password is
// missing) return to let JS continue and wait for user
if ( ! decryptAttachment ( paste , key , password ) ) {
return ;
if ( AttachmentViewer . hasAttachmentData ( ) ) {
// try to decrypt paste and if it fails (because the password is
// missing) return to let JS continue and wait for user
if ( ! decryptAttachment ( paste , key , password ) ) {
return ;
}
}
// ignore empty paste, as this is allowed when pasting attachments
decryptPaste ( paste , key , password , true ) ;
@ -3813,6 +4049,7 @@ jQuery.PrivateBin = (function($, sjcl, Base64, RawDeflate) {
Editor . resetInput ( ) ;
Editor . show ( ) ;
Editor . focusInput ( ) ;
AttachmentViewer . removeAttachment ( ) ;
TopNav . showCreateButtons ( ) ;
Alert . hideLoading ( ) ;