mirror of
https://github.com/Tygs/0bin.git
synced 2023-08-10 21:13:00 +03:00
901 lines
27 KiB
JavaScript
901 lines
27 KiB
JavaScript
/*global sjcl:true, jQuery:true, $:true, lzw:true, zerobin:true, ZeroClipboard:true, vizhash:true, prettyPrint:true, confirm:true */
|
|
;
|
|
(function () {
|
|
"use strict";
|
|
|
|
/* Start random number generator seeding ASAP */
|
|
sjcl.random.startCollectors();
|
|
/* Ensure jquery use cache for ajax requests */
|
|
$.ajaxSetup({
|
|
cache: true
|
|
});
|
|
|
|
/** Create a function that create inline callbacks.
|
|
We use it to create callbacks for onliners with static arguments
|
|
E.G:
|
|
$('stuff').hide(function()(console.log(1, 2, 3)))
|
|
|
|
Becomes:
|
|
|
|
$('stuff').hide(mkcb(console.log, 1, 2, 3))
|
|
*/
|
|
function mkcb(func) {
|
|
var args = arguments;
|
|
return function () {
|
|
return func.apply(func, Array.prototype.slice.call(args, 1));
|
|
};
|
|
}
|
|
|
|
|
|
|
|
/***************************
|
|
**** 0bin utilities ***
|
|
***************************/
|
|
|
|
|
|
window.zerobin = {
|
|
/** Base64 + compress + encrypt, with callbacks before each operation,
|
|
and all of them are executed in a timed continuation to give
|
|
a change to the UI to respond.
|
|
*/
|
|
version: '0.1.1',
|
|
encrypt: function (key, content, toBase64Callback,
|
|
compressCallback, encryptCallback, doneCallback) {
|
|
|
|
setTimeout(function () {
|
|
|
|
content = sjcl.codec.utf8String.toBits(content);
|
|
if (toBase64Callback) {
|
|
toBase64Callback();
|
|
}
|
|
|
|
setTimeout(function () {
|
|
|
|
content = sjcl.codec.base64.fromBits(content);
|
|
if (compressCallback) {
|
|
compressCallback();
|
|
}
|
|
|
|
setTimeout(function () {
|
|
|
|
// content = lzw.compress(content); // Create a bug with JPG
|
|
if (encryptCallback) {
|
|
encryptCallback();
|
|
}
|
|
|
|
setTimeout(function () {
|
|
try {
|
|
content = sjcl.encrypt(key, content);
|
|
} catch (e) {
|
|
$('input, textarea, select, button').prop('disabled', false);
|
|
zerobin.progressBar('form.well .progress').container.hide();
|
|
|
|
zerobin.message('error', 'Paste could not be encrypted. Aborting.',
|
|
'Error');
|
|
}
|
|
if (doneCallback) {
|
|
doneCallback(content);
|
|
}
|
|
}, 250);
|
|
|
|
}, 250);
|
|
|
|
}, 250);
|
|
|
|
}, 250);
|
|
},
|
|
|
|
/** Base64 decoding + uncompress + decrypt, with callbacks before each operation,
|
|
and all of them are executed in a timed continuation to give
|
|
a change to the UI to respond.
|
|
|
|
This is where using a library to fake synchronicity could start to be
|
|
useful, this code is starting be difficult to read. If anyone read this
|
|
and got a suggestion, by all means, speak your mind.
|
|
*/
|
|
decrypt: function (key, content, errorCallback, uncompressCallback,
|
|
fromBase64Callback, toStringCallback, doneCallback) {
|
|
|
|
/* Decrypt */
|
|
setTimeout(function () {
|
|
try {
|
|
content = sjcl.decrypt(key, content);
|
|
if (uncompressCallback) {
|
|
uncompressCallback();
|
|
}
|
|
|
|
/* Decompress */
|
|
setTimeout(function () {
|
|
try {
|
|
content = lzw.decompress(content);
|
|
if (fromBase64Callback) {
|
|
fromBase64Callback();
|
|
}
|
|
|
|
/* From base 64 to bits */
|
|
setTimeout(function () {
|
|
try {
|
|
content = sjcl.codec.base64.toBits(content);
|
|
if (toStringCallback) {
|
|
toStringCallback();
|
|
}
|
|
|
|
/* From bits to string */
|
|
setTimeout(function () {
|
|
try {
|
|
content = sjcl.codec.utf8String.fromBits(content);
|
|
if (doneCallback) {
|
|
doneCallback(content);
|
|
}
|
|
} catch (err) {
|
|
errorCallback(err);
|
|
}
|
|
|
|
}, 250); /* "End of from bits to string" */
|
|
|
|
} catch (err) {
|
|
errorCallback(err);
|
|
}
|
|
|
|
}, 250); /* End of "from base 64 to bits" */
|
|
|
|
} catch (err) {
|
|
errorCallback(err);
|
|
}
|
|
|
|
}, 250); /* End of "decompress" */
|
|
|
|
} catch (err) {
|
|
errorCallback(err);
|
|
}
|
|
|
|
}, 250); /* End of "decrypt" */
|
|
},
|
|
|
|
/** Create a random base64-like string long enought to be suitable as
|
|
an encryption key */
|
|
makeKey: function (entropy) {
|
|
entropy = Math.ceil(entropy / 6) * 6; /* non-6-multiple produces same-length base64 */
|
|
var key = sjcl.bitArray.clamp(
|
|
sjcl.random.randomWords(Math.ceil(entropy / 32), 0), entropy );
|
|
return sjcl.codec.base64.fromBits(key, 0).replace(/\=+$/, '').replace(/\//, '-');
|
|
},
|
|
|
|
getFormatedDate: function (date) {
|
|
date = date || new Date();
|
|
return ((date.getMonth() + 1) + '-' + date.getDate() + '-' + date.getFullYear());
|
|
},
|
|
|
|
getFormatedTime: function (date) {
|
|
date = date || new Date();
|
|
var h = date.getHours(),
|
|
m = date.getMinutes(),
|
|
s = date.getSeconds();
|
|
if (h < 10) {
|
|
h = "0" + h;
|
|
}
|
|
if (m < 10) {
|
|
m = "0" + m;
|
|
}
|
|
if (s < 10) {
|
|
s = "0" + s;
|
|
}
|
|
return h + ":" + m + ":" + s;
|
|
},
|
|
|
|
numOrdA: function (a, b) {
|
|
return (a - b);
|
|
},
|
|
|
|
/** Return a reverse sorted list of all the keys in local storage that
|
|
are prefixed with with the passed version (default being this lib
|
|
version) */
|
|
getLocalStorageKeys: function () {
|
|
var version = 'zerobinV0.1';
|
|
var keys = [];
|
|
for (var key in localStorage) {
|
|
if (key.indexOf(version) !== -1) {
|
|
keys.push(key);
|
|
}
|
|
}
|
|
keys.sort();
|
|
keys.reverse();
|
|
return keys;
|
|
},
|
|
|
|
/** Get a tinyurl using JSONP */
|
|
getTinyURL: function(longURL, success) {
|
|
$.ajax({
|
|
url: 'https://www.googleapis.com/urlshortener/v1/url',
|
|
type: 'POST',
|
|
contentType: 'application/json',
|
|
data: JSON.stringify({
|
|
"longUrl": longURL
|
|
}),
|
|
processData: false,
|
|
dataType: 'json'
|
|
}).done(function(data){
|
|
success(data.id);
|
|
});
|
|
},
|
|
|
|
/** Check for browser support of the named featured. Store the result
|
|
and add a class to the html tag with the result */
|
|
support: {
|
|
localStorage: (function () {
|
|
var val = !! (localStorage);
|
|
$('html').addClass((val ? '' : 'no-') + 'local-storage');
|
|
return val;
|
|
})(),
|
|
|
|
history: (function () {
|
|
var val = !! (window.history && history.pushState);
|
|
$('html').addClass((val ? '' : 'no-') + 'history');
|
|
return val;
|
|
})(),
|
|
|
|
fileUpload: (function () {
|
|
var w = window;
|
|
var val = !! (w.File && w.FileReader && w.FileList && w.Blob);
|
|
$('html').addClass((val ? '' : 'no-') + 'file-upload');
|
|
return val;
|
|
})()
|
|
},
|
|
|
|
/** Store the paste of a URL in local storate, with a storage format
|
|
version prefix and the paste date as the key */
|
|
storePaste: function (url, date) {
|
|
|
|
date = date || new Date();
|
|
date = (date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate() + ' ' + zerobin.getFormatedTime(date));
|
|
|
|
var keys = zerobin.getLocalStorageKeys();
|
|
|
|
if (localStorage.length > 19) {
|
|
void localStorage.removeItem(keys[19]);
|
|
}
|
|
|
|
localStorage.setItem('zerobinV' + zerobin.version + "#" + date, url);
|
|
},
|
|
|
|
/** Return a list of the previous paste url with the creation date
|
|
If the paste is from today, date format should be "at hh:ss",
|
|
else it should be "the mm-dd-yyy"
|
|
*/
|
|
getPreviousPastes: function () {
|
|
var pastes = [],
|
|
keys = zerobin.getLocalStorageKeys(),
|
|
today = zerobin.getFormatedDate();
|
|
|
|
$.each(keys, function (i, key) {
|
|
var pasteDateTime = key.replace(/^[^#]+#/, '');
|
|
var displayDate = pasteDateTime.match(/^(\d+)-(\d+)-(\d+)\s/);
|
|
displayDate = displayDate[2] + '-' + displayDate[3] + '-' + displayDate[1];
|
|
var prefix = 'the ';
|
|
if (displayDate === today) {
|
|
displayDate = pasteDateTime.split(' ')[1];
|
|
prefix = 'at ';
|
|
}
|
|
pastes.push({
|
|
displayDate: displayDate,
|
|
prefix: prefix,
|
|
link: localStorage.getItem(key)
|
|
});
|
|
});
|
|
|
|
return pastes;
|
|
},
|
|
|
|
/** Return an link object with the URL as href so you can extract host,
|
|
protocol, hash, etc.
|
|
|
|
This function use a closure to store a <div> parent for the <a>
|
|
because IE requires the link be processed by it's HTML parser
|
|
for the URL to be parsed. */
|
|
parseUrl: (function () {
|
|
|
|
var div = document.createElement('div');
|
|
div.innerHTML = "<a></a>";
|
|
|
|
return function (url) {
|
|
div.firstChild.href = url;
|
|
div.innerHTML = div.innerHTML;
|
|
return div.firstChild;
|
|
};
|
|
|
|
})(),
|
|
|
|
getPasteId: function (url) {
|
|
var loc = url ? zerobin.parseUrl(url) : window.location;
|
|
return loc.pathname.replace(/\/|paste/g, '');
|
|
},
|
|
|
|
getPasteKey: function (url) {
|
|
var loc = url ? zerobin.parseUrl(url) : window.location;
|
|
return loc.hash.replace('#', '').replace(/(\?|&).*$/, '');
|
|
},
|
|
|
|
/** Return the paste content stripted from any code coloration */
|
|
getPasteContent: function () {
|
|
var copy = '';
|
|
$("#paste-content li").each(function (index) {
|
|
copy = copy + $(this).text().replace(/[\u00a0]+/g, ' ') + '\n';
|
|
});
|
|
if (copy == '') {
|
|
copy = $("#paste-content").text();
|
|
}
|
|
return copy;
|
|
},
|
|
|
|
/** Return an approximate estimate the number of bytes in a text */
|
|
count: function (text, options) {
|
|
// Set option defaults
|
|
var crlf = /(\r?\n|\r)/g;
|
|
var whitespace = /(\r?\n|\r|\s+)/g;
|
|
options = options || {};
|
|
options.lineBreaks = options.lineBreaks || 1;
|
|
|
|
var length = text.length,
|
|
nonAscii = length - text.replace(/[\u0100-\uFFFF]/g, '').length,
|
|
lineBreaks = length - text.replace(crlf, '').length;
|
|
|
|
return length + nonAscii + Math.max(0, options.lineBreaks * (lineBreaks - 1));
|
|
},
|
|
/** Create a message, style it and insert it in the alert box */
|
|
message: function (type, message, title, flush, callback) {
|
|
$(window).scrollTop(0);
|
|
|
|
if (flush) {
|
|
$('.alert-' + type).remove();
|
|
}
|
|
|
|
var $message = $('#alert-template').clone().attr('id', null)
|
|
.addClass('alert alert-' + type);
|
|
$('.message', $message).html(message);
|
|
|
|
if (title) {
|
|
$('.title', $message).html(title);
|
|
} else {
|
|
$('.title', $message).remove();
|
|
}
|
|
|
|
$message.prependTo($('#main')).show('fadeUp', callback);
|
|
},
|
|
|
|
/** Return a progress bar object */
|
|
progressBar: function (selector) {
|
|
var $container = $(selector);
|
|
var bar = {
|
|
container: $container,
|
|
elem: $container.find('.bar')
|
|
};
|
|
bar.set = function (text, rate) {
|
|
bar.elem.text(text).css('width', rate);
|
|
};
|
|
return bar;
|
|
},
|
|
|
|
/** Return an integer ranking the probability this text is any kind of
|
|
source code. */
|
|
isCode: function (text) {
|
|
|
|
var code_chars = /[A-Z]{3}[A-Z]+|\.[a-z]|[=:<>{}\[\]$_'"&]| {2}|\t/g;
|
|
var comments = /(:?\/\*|<!--)(:?.|\n)*?(:?\*\/|-->)|(\/\/|#)(.*?)\n/g;
|
|
var formating = /[-*=_+]{4,}/;
|
|
|
|
var total = 0;
|
|
var size = 0;
|
|
var m = text.match(comments);
|
|
if (m) {
|
|
total += text.match(comments).length;
|
|
}
|
|
text = text.replace(comments, '');
|
|
text.replace(formating, '');
|
|
text = text.split('\n');
|
|
for (var i = 0; i < text.length; i++) {
|
|
var line = text[i];
|
|
size += line.length;
|
|
var match = line.replace(formating, '').match(code_chars);
|
|
if (match) {
|
|
total += match.length;
|
|
}
|
|
}
|
|
|
|
return total * 1000 / size;
|
|
},
|
|
|
|
// prevent defaults
|
|
ignoreDrag: function (e) {
|
|
e.originalEvent.stopPropagation();
|
|
e.originalEvent.preventDefault();
|
|
},
|
|
|
|
// Handle Drop
|
|
handleDrop: function (e) {
|
|
e.originalEvent.preventDefault();
|
|
zerobin.upload(e.originalEvent.dataTransfer.files);
|
|
$("#content").removeClass('hover');
|
|
},
|
|
|
|
handleDragOver: function (e) {
|
|
zerobin.ignoreDrag(e);
|
|
$(this).addClass('hover');
|
|
},
|
|
|
|
handleDragLeave: function (e) {
|
|
$(this).removeClass('hover');
|
|
},
|
|
|
|
upload: function (files) {
|
|
var current_file = files[0];
|
|
var reader = new FileReader();
|
|
if (current_file.type.indexOf('image') == 0) {
|
|
reader.onload = function (event) {
|
|
var image = new Image();
|
|
image.src = event.target.result;
|
|
|
|
image.onload = function() {
|
|
var maxWidth = 1024,
|
|
maxHeight = 1024,
|
|
imageWidth = image.width,
|
|
imageHeight = image.height;
|
|
|
|
|
|
if (imageWidth > imageHeight) {
|
|
if (imageWidth > maxWidth) {
|
|
imageHeight *= maxWidth / imageWidth;
|
|
imageWidth = maxWidth;
|
|
}
|
|
}
|
|
else {
|
|
if (imageHeight > maxHeight) {
|
|
imageWidth *= maxHeight / imageHeight;
|
|
imageHeight = maxHeight;
|
|
}
|
|
}
|
|
|
|
var canvas = document.createElement('canvas');
|
|
canvas.width = imageWidth;
|
|
canvas.height = imageHeight;
|
|
image.width = imageWidth;
|
|
image.height = imageHeight;
|
|
var ctx = canvas.getContext("2d");
|
|
ctx.drawImage(this, 0, 0, imageWidth, imageHeight);
|
|
|
|
var paste = canvas.toDataURL(current_file.type);
|
|
$('#content').val(paste).trigger('change');
|
|
$('#content').hide();
|
|
$(image).css('max-width', '742px');
|
|
$('#content').after(image);
|
|
}
|
|
}
|
|
reader.readAsDataURL(current_file);
|
|
} else {
|
|
reader.onload = function (event) {
|
|
$('#content').val(event.target.result).trigger('change');
|
|
};
|
|
reader.readAsText(current_file);
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
/***************************
|
|
**** On document ready ***
|
|
****************************/
|
|
|
|
|
|
$(function () {
|
|
|
|
/**
|
|
On the create paste page:
|
|
On click on the send button, compress and encrypt data before
|
|
posting it using ajax. Then redirect to the address of the
|
|
newly created paste, adding the key in the hash.
|
|
*/
|
|
$('.btn-primary').live("click", function (e) {
|
|
|
|
e.preventDefault();
|
|
var paste = $('textarea').val();
|
|
|
|
if (paste.trim()) {
|
|
|
|
var $form = $('input, textarea, select, button').prop('disabled', true);
|
|
|
|
// set up progress bar
|
|
var bar = zerobin.progressBar('form.well .progress');
|
|
bar.container.show();
|
|
bar.set('Converting paste to bits...', '25%');
|
|
|
|
/* Encode, compress, encrypt and send the paste then redirect the user
|
|
to the new paste. We ensure a loading animation is updated
|
|
during the process by passing callbacks.
|
|
*/
|
|
try {
|
|
|
|
var expiration = $('#expiration').val();
|
|
var key = zerobin.makeKey(256);
|
|
|
|
zerobin.encrypt(key, paste,
|
|
|
|
mkcb(bar.set, 'Encoding to base64...', '45%'),
|
|
mkcb(bar.set, 'Compressing...', '65%'),
|
|
mkcb(bar.set, 'Encrypting...', '85%'),
|
|
|
|
/* This block deal with sending the data, redirection or error handling */
|
|
function (content) {
|
|
|
|
bar.set('Sending...', '95%');
|
|
var data = {
|
|
content: content,
|
|
expiration: expiration
|
|
};
|
|
var sizebytes = zerobin.count(JSON.stringify(data));
|
|
var oversized = sizebytes > zerobin.max_size; // 100kb - the others header information
|
|
var readableFsize = Math.round(sizebytes / 1024);
|
|
var readableMaxsize = Math.round(zerobin.max_size / 1024);
|
|
|
|
if (oversized) {
|
|
bar.container.hide();
|
|
$form.prop('disabled', false);
|
|
zerobin.message('error', ('The encrypted file was <strong class="file-size">' + readableFsize +
|
|
'</strong>KB. You have reached the maximum size limit of ' + readableMaxsize + 'KB.'),
|
|
'Warning!', true);
|
|
return;
|
|
}
|
|
|
|
$.post('/paste/create', data)
|
|
.error(function (error) {
|
|
$form.prop('disabled', false);
|
|
bar.container.hide();
|
|
zerobin.message(
|
|
'error',
|
|
'Paste could not be saved. Please try again later.',
|
|
'Error');
|
|
|
|
})
|
|
.success(function (data) {
|
|
bar.set('Redirecting to new paste...', '100%');
|
|
|
|
if (data.status === 'error') {
|
|
zerobin.message('error', data.message, 'Error');
|
|
$form.prop('disabled', false);
|
|
bar.container.hide();
|
|
} else {
|
|
var paste_url = '/paste/' + data.paste + '#' + key;
|
|
if (zerobin.support.localStorage) {
|
|
zerobin.storePaste(paste_url);
|
|
}
|
|
window.location = (paste_url);
|
|
}
|
|
});
|
|
});
|
|
} catch (err) {
|
|
$form.prop('disabled', false);
|
|
bar.container.hide();
|
|
zerobin.message('error', 'Paste could not be encrypted. Aborting.',
|
|
'Error');
|
|
}
|
|
}
|
|
});
|
|
|
|
/**
|
|
DECRYPTION:
|
|
On the display paste page, decrypt and decompress the paste content,
|
|
add syntax coloration then setup the copy to clipboard button.
|
|
Also calculate and set the paste visual hash.
|
|
*/
|
|
var content = $('#paste-content').text().trim();
|
|
var key = zerobin.getPasteKey();
|
|
var error = false;
|
|
|
|
if (content && key) {
|
|
|
|
/* Load the lib for visual canvas, create one from the paste id and
|
|
insert it */
|
|
$.getScript("/static/js/vizhash.min.js").done(function (script, textStatus) {
|
|
if (vizhash.supportCanvas) {
|
|
var vhash = vizhash.canvasHash(zerobin.getPasteId(), 24, 24);
|
|
$('<a class="vhash" href="#"></a>').click(function (e) {
|
|
e.preventDefault();
|
|
if (confirm("This picture is unique to your paste so you can identify" +
|
|
" it quickly. \n\n Do you want to know more about this?")) {
|
|
window.open("https://github.com/sametmax/VizHash.js", "_blank");
|
|
}
|
|
}).prependTo('.lnk-option').append(vhash.canvas);
|
|
}
|
|
});
|
|
|
|
var $form = $('input, textarea, select, button').prop('disabled', true);
|
|
|
|
var bar = zerobin.progressBar('.well form .progress');
|
|
bar.container.show();
|
|
bar.set('Decrypting paste...', '25%');
|
|
|
|
zerobin.decrypt(key, content,
|
|
|
|
/* On error*/
|
|
function () {
|
|
bar.container.hide();
|
|
zerobin.message('error', 'Could not decrypt data (Wrong key ?)', 'Error');
|
|
},
|
|
|
|
/* Update progress bar */
|
|
mkcb(bar.set, 'Decompressing...', '45%'),
|
|
mkcb(bar.set, 'Base64 decoding...', '65%'),
|
|
mkcb(bar.set, 'From bits to string...', '85%'),
|
|
|
|
/* When done */
|
|
function (content) {
|
|
|
|
/* Decrypted content goes back to initial container*/
|
|
$('#paste-content').text(content);
|
|
|
|
if (content.indexOf('data:image') == 0) {
|
|
// Display Image
|
|
$('#paste-content').hide();
|
|
var img = $('<img/>');
|
|
$(img).attr('src', content);
|
|
$(img).css('max-width', '742px');
|
|
$('#paste-content').after(img);
|
|
|
|
// Display Download button
|
|
$('.btn-clone').hide();
|
|
|
|
var button = $('<a/>').attr('href', content);
|
|
$(button).attr('download', '0bin_' + document.location.pathname.split('/').pop());
|
|
$(button).addClass('btn');
|
|
$(button).html('<i class="icon-download"></i> Download');
|
|
$('.btn-clone').after(button);
|
|
|
|
}
|
|
bar.set('Code coloration...', '95%');
|
|
|
|
/* Add a continuation to let the UI redraw */
|
|
setTimeout(function () {
|
|
|
|
/* Setup flash clipboard button */
|
|
ZeroClipboard.setMoviePath('/static/js/ZeroClipboard.swf');
|
|
|
|
var clip = new ZeroClipboard.Client();
|
|
|
|
// Callback to reposition the clibpboad flash animation overlay
|
|
var reposition = function () {
|
|
clip.reposition();
|
|
};
|
|
|
|
clip.addEventListener('mouseup', function () {
|
|
$('#clip-button').text('Copying paste...');
|
|
clip.setText(zerobin.getPasteContent());
|
|
});
|
|
clip.addEventListener('complete', function () {
|
|
$('#clip-button').text('Copy to clipboard');
|
|
zerobin.message('info', 'The paste is now in your clipboard', '',
|
|
true, reposition);
|
|
});
|
|
clip.glue('clip-button');
|
|
|
|
window.onresize = reposition;
|
|
|
|
|
|
/* Setup link to get the paste short url*/
|
|
$('#short-url').click(function (e) {
|
|
e.preventDefault();
|
|
$('#short-url').text('Loading short url...');
|
|
zerobin.getTinyURL(window.location.toString(), function (tinyurl) {
|
|
clip.setText(tinyurl);
|
|
$('#copy-success').hide();
|
|
zerobin.message('success',
|
|
'<a href="' + tinyurl + '">' + tinyurl + '</a>',
|
|
'Short url', true, reposition);
|
|
$('#short-url').text('Get short url');
|
|
});
|
|
});
|
|
|
|
/* Remap the message close handler to include the clipboard
|
|
flash reposition */
|
|
$(".close").die().live('click', function (e) {
|
|
e.preventDefault();
|
|
$(this).parent().fadeOut(reposition);
|
|
});
|
|
|
|
/** Syntaxic coloration */
|
|
|
|
if (zerobin.isCode(content) > 100) {
|
|
$('#paste-content').addClass('linenums');
|
|
prettyPrint();
|
|
} else {
|
|
if (content.indexOf('data:image') != 0) {
|
|
zerobin.message('info',
|
|
"The paste did not seem to be code, so it " +
|
|
"was not colorized. " +
|
|
"<a id='force-coloration' href='#'>Force coloration</a>",
|
|
'', false, reposition);
|
|
}
|
|
}
|
|
|
|
/* Class to switch to paste content style with coloration done */
|
|
$('#paste-content').addClass('done');
|
|
|
|
/* Display result */
|
|
bar.set('Done', '100%');
|
|
bar.container.hide();
|
|
|
|
$form.prop('disabled', false);
|
|
content = '';
|
|
|
|
}, 250);
|
|
|
|
});
|
|
|
|
} /* End of "DECRYPTION" */
|
|
|
|
/* Synchronize expiration select boxes value */
|
|
$('.paste-option select').live('change', function () {
|
|
$('.paste-option select').val($(this).val());
|
|
});
|
|
|
|
|
|
/* Resize Textarea according to content */
|
|
$('#content').elastic();
|
|
|
|
|
|
/* Display bottom paste option buttons when needed */
|
|
$('#content').live('keyup change', function () {
|
|
if ($('#content').height() < 400) {
|
|
$('.paste-option.down').remove();
|
|
} else {
|
|
|
|
if ($('.paste-option').length === 1) {
|
|
$('.paste-option').clone().addClass('down').appendTo('form.well');
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
|
|
/* Display previous pastes */
|
|
if (zerobin.support.localStorage) {
|
|
|
|
var $container = $('.previous-pastes'),
|
|
pastes = zerobin.getPreviousPastes();
|
|
|
|
if (pastes.length) {
|
|
|
|
$.getScript("/static/js/vizhash.min.js").done(function (script, textStatus) {
|
|
|
|
$container.find('.item').remove();
|
|
$.each(zerobin.getPreviousPastes(), function (i, paste) {
|
|
|
|
var $li = $('<li class="item"></li>').appendTo($container);
|
|
var $link = $('<a></a>').attr('href', paste.link)
|
|
.text(paste.prefix + paste.displayDate)
|
|
.appendTo($li);
|
|
|
|
if (vizhash.supportCanvas) {
|
|
var pasteId = zerobin.getPasteId(paste.link);
|
|
var vhash = vizhash.canvasHash(pasteId, 24, 24).canvas;
|
|
$link.prepend($(vhash).addClass('vhash'));
|
|
}
|
|
|
|
// hightlite the current link and make sure clicking the link
|
|
// does redirect to the page
|
|
if (paste.link.replace(/#[^#]+/, '') === window.location.pathname) {
|
|
$li.addClass('active');
|
|
$link.click(function () {
|
|
window.location = $link.attr('href');
|
|
window.location.reload();
|
|
});
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/* Event handler for "clone paste" button */
|
|
$('.btn-clone').click(function (e) {
|
|
e.preventDefault();
|
|
$('.submit-form').show();
|
|
$('.paste-form').hide();
|
|
$('#content').val(zerobin.getPasteContent()).trigger('change');
|
|
});
|
|
|
|
$('.clone .btn-danger').click(function (e) {
|
|
e.preventDefault();
|
|
$('.submit-form').hide();
|
|
$('.paste-form').show();
|
|
});
|
|
|
|
|
|
|
|
/* Upload file using HTML5 File API */
|
|
if (zerobin.support.fileUpload) {
|
|
|
|
var $buttonOverlay = $('#file-upload');
|
|
var $button = $('.btn-upload');
|
|
|
|
try {
|
|
$button.val('Uploading...');
|
|
$button.prop('disabled', true);
|
|
$buttonOverlay.change(function () {
|
|
zerobin.upload(this.files);
|
|
});
|
|
} catch (e) {
|
|
zerobin.message('error', 'Could no upload the file', 'Error');
|
|
$button.val('Upload File');
|
|
$button.prop('disabled', false);
|
|
}
|
|
|
|
$button.prop('disabled', false);
|
|
$button.val('Upload File');
|
|
$buttonOverlay.mouseover(mkcb($(this).css, 'cursor', 'pointer'));
|
|
|
|
// Implements drag & drop upload
|
|
$('#content').bind('drop', zerobin.handleDrop);
|
|
$('#content').bind('dragover', zerobin.handleDragOver);
|
|
$('#content').bind('dragleave', zerobin.handleDragLeave);
|
|
|
|
|
|
}
|
|
|
|
/* Alerts */
|
|
|
|
$(".close").live('click', function (e) {
|
|
e.preventDefault();
|
|
$(this).parent().fadeOut();
|
|
});
|
|
|
|
|
|
/* Parse obfuscaded emails and make them usable */
|
|
$('.email-link').each(function (i, elem) {
|
|
var $obfuscatedEmail = $(this);
|
|
var address = $obfuscatedEmail.attr('title').replace('__AT__', '@');
|
|
var text = $obfuscatedEmail.text().replace('__AT__', '@');
|
|
var $plainTextEmail = $('<a href="mailto:' + address + '">' + text + '</a>');
|
|
$obfuscatedEmail.replaceWith($plainTextEmail);
|
|
|
|
});
|
|
|
|
/* Show the page using javascript. Non js enabled browser will see an
|
|
error message */
|
|
$('#wrap-content').each(function (i, elem) {
|
|
$(elem).show();
|
|
});
|
|
|
|
/* Remove expired pasted from history */
|
|
if (zerobin.support.history && zerobin.paste_not_found) {
|
|
var paste_id = zerobin.getPasteId();
|
|
var keys = zerobin.getLocalStorageKeys();
|
|
$.each(keys, function (i, key) {
|
|
if (localStorage[key].indexOf(paste_id) !== -1) {
|
|
localStorage.removeItem(key);
|
|
return false;
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
/* Force text coloration when clickin on link */
|
|
$("#force-coloration").live("click", function (e) {
|
|
e.preventDefault();
|
|
$('#paste-content').addClass('linenums');
|
|
$(this).die(e).text('Applying coloration');
|
|
prettyPrint();
|
|
$(this).remove();
|
|
});
|
|
|
|
/* Send the paste by email */
|
|
$('#email-link').click(function(e) {
|
|
e.target.href = 'mailto:friend@example.com?body=' + window.location.toString();
|
|
});
|
|
|
|
|
|
}); /* End of "document ready" jquery callback */
|
|
|
|
})(); /* End of self executing function */
|