1
0
mirror of https://github.com/Tygs/0bin.git synced 2023-08-10 21:13:00 +03:00

Visual hash on paste history, paste history refactoring, callback refactoring, reversible clone

This commit is contained in:
sam 2012-05-07 00:24:46 +07:00
parent 2bf36b4b4b
commit c7b815c471
10 changed files with 395 additions and 203 deletions

View File

@ -1,13 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import os # import default settings value from src/default_settings.py
import math # you can refer to this file if you forgot what
ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) # settings is for and what it is set to by default
STATIC_FILES_ROOT = os.path.join(ROOT_DIR, 'static') # DO NOT ALTER THIS LINE
from src.default_settings import *
#####################################################
# You can start editing settings after this comment #
#####################################################
# debug will get you error message and auto reload # debug will get you error message and auto reload
# don't set this to True in production # don't set this to True in production
@ -19,16 +16,18 @@ DEBUG = False
PASTE_FILES_ROOT = os.path.join(STATIC_FILES_ROOT, 'content') PASTE_FILES_ROOT = os.path.join(STATIC_FILES_ROOT, 'content')
# Port and host the embeded python server should be using # Port and host the embeded python server should be using
# You can also specify them using the --host and --port script options
# which have priority on these settings
HOST = "127.0.0.1" HOST = "127.0.0.1"
PORT= "8000" PORT= "8000"
# User and group the server should run as. Set to None if it should be the # User and group the server should run as. Set to None if it should be the
# current user # current user. Some OS don't support it and if so, it will be ignored.
USER = None USER = None
GROUP = None GROUP = None
# limit size of pasted text in bytes. Be carefull allowing too much size can slow down user's # limit size of pasted text in bytes. Be carefull allowing too much
# browser # size can slow down user's browser
MAX_SIZE = 1024 * 500 MAX_SIZE = 1024 * 500
MAX_SIZE_KB = int(math.ceil(MAX_SIZE / 1024.0)) MAX_SIZE_KB = int(math.ceil(MAX_SIZE / 1024.0))

View File

@ -1,13 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""
General configuration and imports gathering.
"""
import os
import sys
import settings
from paste import Paste
from utils import drop_privileges

33
src/default_settings.py Normal file
View File

@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
import os
import math
ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATIC_FILES_ROOT = os.path.join(ROOT_DIR, 'static')
# debug will get you error message and auto reload
# don't set this to True in production
DEBUG = False
# absolute path where the paste files should be store
# default in projectdirectory/static/content/
# use "/" even under Windows
PASTE_FILES_ROOT = os.path.join(STATIC_FILES_ROOT, 'content')
# Port and host the embeded python server should be using
# You can also specify them using the --host and --port script options
# which have priority on these settings
HOST = "127.0.0.1"
PORT= "8000"
# User and group the server should run as. Set to None if it should be the
# current user. Some OS don't support it and if so, it will be ignored.
USER = None
GROUP = None
# limit size of pasted text in bytes. Be carefull allowing too much size can slow down user's
# browser
MAX_SIZE = 1024 * 500
MAX_SIZE_KB = int(math.ceil(MAX_SIZE / 1024.0))

View File

@ -13,6 +13,8 @@ import math
from datetime import datetime, timedelta from datetime import datetime, timedelta
# add project dir and libs dir to the PYTHON PATH to ensure they are
# importable
import settings import settings
sys.path.insert(0, os.path.dirname(settings.ROOT_DIR)) sys.path.insert(0, os.path.dirname(settings.ROOT_DIR))
sys.path.append(os.path.join(settings.ROOT_DIR, 'libs')) sys.path.append(os.path.join(settings.ROOT_DIR, 'libs'))
@ -23,7 +25,8 @@ from bottle import (Bottle, route, run, abort, error,
import clize import clize
from src import settings, Paste, drop_privileges from src.paste import Paste
from src.utils import drop_privileges
app = Bottle() app = Bottle()

View File

@ -119,12 +119,21 @@ h4#pixels-total {
float:left; float:left;
} }
.file-upload { html.file-upload p.file-upload {
float: left; float: left;
margin: 22px 0px 0px 21px; margin: 22px 0px 0px 21px;
display: none; display: none;
} }
html.file-upload p.file-upload {
display:inherit;
}
html.no-file-upload p.file-upload {
display:none;
}
input.btn-upload { input.btn-upload {
position: relative; position: relative;
left: -6px; left: -6px;
@ -147,14 +156,19 @@ input.hide-upload {
height: 49px; height: 49px;
} }
/* Paste Page */
.items { /* Paste Page */
text-align: center;
}
#paste-content { #paste-content {
background-color: white; background-color: white;
padding:1em;
}
#paste-content.done {
background-color: white;
padding-top:1em;
padding-left:0;
} }
.submit-form { .submit-form {
@ -177,7 +191,7 @@ li.L5, li.L6, li.L7, li.L8, li.L9
background: inherit; background: inherit;
} }
.prettyprint.linenums { .prettyprint.linenums.done {
-webkit-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0; -webkit-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0;
-moz-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0; -moz-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0;
box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0; box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0;
@ -254,7 +268,7 @@ button.btn, input[type="submit"].btn {
margin-left: 5px; margin-left: 5px;
} }
.btn-primary { .btn-primary, .btn-danger {
position:relative; position:relative;
top:-4px; top:-4px;
} }
@ -275,8 +289,35 @@ button.btn, input[type="submit"].btn {
text-align:left; text-align:left;
} }
-webkit-transition: width 0.1s ease; .lnk-option canvas {
-moz-transition: width 0.1s ease; vertical-align:middle;
-ms-transition: width 0.1s ease; margin-right:10px;
-o-transition: width 0.1s ease; }
transition: width 0.1s ease;
/* Previous paste list */
.previous-pastes .item {
margin-top:5px;
vertical-align:middle;
line-height:24px;
padding-left:1em;
}
.previous-pastes canvas {
display:block;
float:left;
margin-right:5px;
}
html.local-storage .no-local-storage {
display:none;
}
html.no-local-storage .local-storage {
display:none;
}
canvas {
border: 1px solid white;
}

View File

@ -5,6 +5,29 @@ sjcl.random.startCollectors();
/* Ensure jquery use cache for ajax requests */ /* Ensure jquery use cache for ajax requests */
$.ajaxSetup({ cache: true }); $.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 ***
****************************/
zerobin = { zerobin = {
/** Base64 + compress + encrypt, with callbacks before each operation, /** Base64 + compress + encrypt, with callbacks before each operation,
and all of them are executed in a timed continuation to give and all of them are executed in a timed continuation to give
@ -148,64 +171,88 @@ zerobin = {
}); });
}, },
/** Check for browser support of the named featured. Store the result
and add a class to the html tag with the result */
support: { support: {
localstorage: function(){ localStorage: (function(){
return !!(localStorage); var val = !!(localStorage);
}, $('html').addClass((val ? '' : 'no-') + 'local-storage');
history: function(){ return val;
return !!(window.history && history.pushState); })(),
}
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;
})(),
}, },
storatePaste: function(url){ storatePaste: function(url){
if (zerobin.support.localstorage){ if (zerobin.support.localStorage){
var date = new Date();
var paste = zerobin.getDate()+" "+zerobin.getTime()+";"+url; var paste = zerobin.getDate()+" "+zerobin.getTime()+";"+url;
var keys = zerobin.getKeys(); var keys = zerobin.getKeys();
if(keys.length < 1) if(keys.length < 1){keys[0] = 0}
keys[0] = 0;
if (localStorage.length > 19) if (localStorage.length > 19) {
void localStorage.removeItem(keys[0]); void localStorage.removeItem(keys[0]);
}
localStorage.setItem(keys.reverse()[0]+1, paste); localStorage.setItem(keys.reverse()[0]+1, paste);
} }
}, },
getPastes: function(){ /** Return a list of the previous paste url with creation date */
if (zerobin.support.localstorage){ getPreviousPastes: function(){
var pastes = ''; var pastes = [],
var keys = zerobin.getKeys(); keys = zerobin.getKeys(),
keys.reverse(); date = zerobin.getDate(),
prefix = 'on ';
keys.reverse();
for (i=0; i<=keys.length-1; i++) for (i=0; i <= keys.length-1; i++) {
{ var paste = localStorage.getItem(keys[i]).split(';');
var paste = localStorage.getItem(keys[i]); var displayDate = paste[0].split(' ')[0];
if (paste.split(';')[0].split(' ')[0] == zerobin.getDate()){ if (displayDate == date){
var display_date = paste.split(';')[0].split(' ')[1]; displayDate = paste[0].split(' ')[1];
var on_at = 'at '; prefix = 'at ';
}else{
var display_date = zerobin.getDate();
var on_at = 'on ';
}
pastes = pastes + '<li><a class="items" href="' + paste.split(';')[1] + '">' + on_at + display_date + '</a></li>';
} }
if (!pastes){ pastes.push({displayDate: displayDate, prefix: prefix, link: paste[1]});
return '<i class="grey">Your previous pastes will be saved in your browser using <a href="http://www.w3.org/TR/webstorage/">localStorage</a>.</i>';
}
return pastes;
}else{
return 'Sorry your browser does not support LocalStorage, We cannot display your previous pastes.';
} }
return pastes
}, },
getPasteContent: function(){ /** Return an link object with the URL as href so you can extract host,
var content_clone = '' ; protocol, hash, etc*/
$("#paste-content li").each(function(index) { parseUrl: function(url){
content_clone = content_clone + $(this).text() + '\n'; var a = document.createElement('a');
}); a.href = url
return content_clone; return a
}, },
getPasteId: function(url){
loc = url ? zerobin.parseUrl(url) : window.location
return loc.pathname.replace(/[/]|paste/g, '');
},
/** Return the paste content stripted from any code coloration */
getPasteContent: function(){
var copy = '' ;
$("#paste-content li").each(function(index) {
copy = copy + $(this).text() + '\n';
});
return copy;
},
/** Return an approximate estimate the number of bytes in a text */
count: function(text, options) { count: function(text, options) {
// Set option defaults // Set option defaults
var crlf = /(\r?\n|\r)/g; var crlf = /(\r?\n|\r)/g;
@ -219,6 +266,7 @@ zerobin = {
return length + nonAscii + Math.max(0, options.lineBreaks * (lineBreaks - 1)); 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) { message: function(type, message, title, flush, callback) {
$(window).scrollTop(0); $(window).scrollTop(0);
@ -233,10 +281,23 @@ zerobin = {
else {$('.title', $message).remove()} else {$('.title', $message).remove()}
$message.prependTo($('#main')).show('fadeUp', callback); $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;
} }
}; };
/***************************
**** On document ready ***
****************************/
$(function(){ $(function(){
/** /**
@ -245,31 +306,32 @@ $(function(){
posting it using ajax. Then redirect to the address of the posting it using ajax. Then redirect to the address of the
newly created paste, adding the key in the hash. newly created paste, adding the key in the hash.
*/ */
$('button[type=submit]').live("click", function(e){ $('.btn-primary').live("click", function(e){
e.preventDefault(); e.preventDefault();
var paste = $('textarea').val(); var paste = $('textarea').val();
var sizebytes = zerobin.count($('#content').val(), { }); var sizebytes = zerobin.count($('#content').val());
var oversized = sizebytes > zerobin.max_size; var oversized = sizebytes > zerobin.max_size;
var readable_fsize = Math.round(sizebytes/1024); var readableFsize = Math.round(sizebytes / 1024);
var readable_maxsize = Math.round(zerobin.max_size/1024) var readableMaxsize = Math.round(zerobin.max_size / 1024);
if (oversized){ if (oversized){
zerobin.message('error', zerobin.message('error',
('Your file is <strong class="file-size">' + readable_fsize + ('Your file is <strong class="file-size">' + readablFfsize +
'</strong>KB. You have reached the maximum size limit of ' + '</strong>KB. You have reached the maximum size limit of ' +
readable_maxsize + 'KB.'), readableMaxsize + 'KB.'),
'Warning!', true) 'Warning!', true)
} }
if (!oversized && paste.trim()) { if (!oversized && paste.trim()) {
$form = $('input, textarea, select, button').prop('disabled', true); $form = $('input, textarea, select, button').prop('disabled', true);
$form.prop('disabled', true);
$bar = $('form.well .progress').show(); // set up progress bar
var $loading = $('form.well .progress .bar') var bar = zerobin.progressBar('form.well .progress');
.css('width', '25%') bar.container.show();
.text('Converting paste to bits...'); bar.set('Converting paste to bits...', '25%');
/* Encode, compress, encrypt and send the paste then redirect the user /* Encode, compress, encrypt and send the paste then redirect the user
to the new paste. We ensure a loading animation is updated to the new paste. We ensure a loading animation is updated
@ -282,20 +344,20 @@ $('button[type=submit]').live("click", function(e){
zerobin.encrypt(key, paste, zerobin.encrypt(key, paste,
function(){$loading.text('Encoding to base64...').css('width', '45%')}, mkcb(bar.set, 'Encoding to base64...', '45%'),
function(){$loading.text('Compressing...').css('width', '65%')}, mkcb(bar.set, 'Compressing...', '65%'),
function(){$loading.text('Encrypting...').css('width', '85%')}, mkcb(bar.set, 'Encrypting...', '85%'),
/* This block deal with sending the data, redirection or error handling */ /* This block deal with sending the data, redirection or error handling */
function(content){ function(content){
$loading.text('Sending...').css('width', '95%'); bar.set('Sending...', '95%');
var data = {content: content, expiration: expiration}; var data = {content: content, expiration: expiration};
$.post('/paste/create', data) $.post('/paste/create', data)
.error(function(error) { .error(function(error) {
$form.prop('disabled', false); $form.prop('disabled', false);
$loading.hide(); bar.container.hide();
zerobin.message( zerobin.message(
'error', 'error',
'Paste could not be saved. Please try again later.', 'Paste could not be saved. Please try again later.',
@ -304,12 +366,12 @@ $('button[type=submit]').live("click", function(e){
}) })
.success(function(data) { .success(function(data) {
$loading.text('Redirecting to new paste...').css('width', '100%'); bar.set('Redirecting to new paste...', '100%');
if (data['status'] == 'error') { if (data['status'] == 'error') {
zerobin.message('error', data['message'], 'Error'); zerobin.message('error', data['message'], 'Error');
$form.prop('disabled', false); $form.prop('disabled', false);
$bar.hide(); bar.container.hide();
} else { } else {
var paste_url = '/paste/' + data['paste'] + '#' + key; var paste_url = '/paste/' + data['paste'] + '#' + key;
zerobin.storatePaste(paste_url); zerobin.storatePaste(paste_url);
@ -320,7 +382,7 @@ $('button[type=submit]').live("click", function(e){
); );
} catch (err) { } catch (err) {
$form.prop('disabled', false); $form.prop('disabled', false);
$bar.hide(); bar.container.hide();
zerobin.message('error', 'Paste could not be encrypted. Aborting.', zerobin.message('error', 'Paste could not be encrypted. Aborting.',
'Error'); 'Error');
} }
@ -332,29 +394,46 @@ $('button[type=submit]').live("click", function(e){
DECRYPTION: DECRYPTION:
On the display paste page, decrypt and decompress the paste content, On the display paste page, decrypt and decompress the paste content,
add syntax coloration then setup the copy to clipboard button. 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 content = $('#paste-content').text().trim();
var key = window.location.hash.substring(1); var key = window.location.hash.substring(1);
var error = false; var error = false;
if (content && key) { if (content && key) {
var $bar = $('.well form .progress').show(); /* Load the lib for visual canvas, create one from the paste id and
var $loading = $('.well form .progress .bar').css('width', '25%') insert it */
.text('Decrypting paste...'); $.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("http://is.gd/IJaMRG", "_blank");
}
}).prependTo('.lnk-option').append(vhash.canvas);
}
});
$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, zerobin.decrypt(key, content,
/* On error*/ /* On error*/
function(){ function(){
$bar.hide(); bar.container.hide();
zerobin.message('error', 'Could not decrypt data (Wrong key ?)', zerobin.message('error', 'Could not decrypt data (Wrong key ?)', 'Error');
'Error');
}, },
/* Update progress bar */ /* Update progress bar */
function(){$loading.text('Decompressing...').css('width', '45%')}, mkcb(bar.set, 'Decompressing...', '45%'),
function(){$loading.text('Base64 decoding...').css('width', '65%')}, mkcb(bar.set, 'Base64 decoding...', '65%'),
function(){$loading.text('From bits to string...').css('width', '85%')}, mkcb(bar.set, 'From bits to string...', '85%'),
/* When done */ /* When done */
function(content){ function(content){
@ -363,7 +442,7 @@ if (content && key) {
$('#paste-content').text(content); $('#paste-content').text(content);
content = ''; content = '';
$loading.text('Code coloration...').css('width', '95%'); bar.set('Code coloration...', '95%');
/* Add a continuation to let the UI redraw */ /* Add a continuation to let the UI redraw */
setTimeout(function(){ setTimeout(function(){
@ -372,16 +451,21 @@ if (content && key) {
ZeroClipboard.setMoviePath('/static/js/ZeroClipboard.swf'); ZeroClipboard.setMoviePath('/static/js/ZeroClipboard.swf');
var clip = new ZeroClipboard.Client(); var clip = new ZeroClipboard.Client();
// Callback to reposition the clibpboad flash animation overlay
var reposition = function(){clip.reposition()};
clip.addEventListener('mouseup', function(){ clip.addEventListener('mouseup', function(){
clip.setText(zerobin.getPasteContent()); clip.setText(zerobin.getPasteContent());
}); });
clip.addEventListener('complete', function(){ clip.addEventListener('complete',
zerobin.message('info', 'The paste is now in your clipboard', mkcb(zerobin.message, 'info',
'', false, function(){clip.reposition()}); 'The paste is now in your clipboard',
}); '', true, reposition)
);
clip.glue('clip-button'); clip.glue('clip-button');
window.onresize = clip.reposition; window.onresize = reposition;
/* Setup link to get the paste short url*/ /* Setup link to get the paste short url*/
@ -393,7 +477,7 @@ if (content && key) {
$('#copy-success').hide(); $('#copy-success').hide();
zerobin.message('success', zerobin.message('success',
'<a href="' + tinyurl + '">' + tinyurl + '</a>', '<a href="' + tinyurl + '">' + tinyurl + '</a>',
'Short url', true, function(){clip.reposition()} 'Short url', true, reposition
) )
$('#short-url').text('Get short url'); $('#short-url').text('Get short url');
}); });
@ -403,15 +487,21 @@ if (content && key) {
flash reposition */ flash reposition */
$(".close").die().live('click', function(e){ $(".close").die().live('click', function(e){
e.preventDefault(); e.preventDefault();
$(this).parent().fadeOut(function(){clip.reposition()}); $(this).parent().fadeOut(reposition);
}); });
/** Syntaxic coloration */ /** Syntaxic coloration */
prettyPrint(); prettyPrint();
/* Class to switch to paste content style with coloration done */
$('#paste-content').addClass('done');
/* Display result */ /* Display result */
$loading.text('Done').css('width', '100%'); bar.set('Done', '100%');
$bar.hide(); bar.container.hide();
$form.prop('disabled', false);
}, 250); }, 250);
} }
@ -421,8 +511,8 @@ if (content && key) {
/* Synchronize expiration select boxes value */ /* Synchronize expiration select boxes value */
$('.paste-option select').live('change', function(){ $('.paste-option select').live('change', function(){
var value = $(this).val(); var $this = $(this);
$('.paste-option select').val(value); $this.val($this.val());
}); });
@ -431,11 +521,12 @@ $('#content').elastic();
/* Display bottom paste option buttons when needed */ /* Display bottom paste option buttons when needed */
$('#content').live('keyup change', function(){ $('#content').on('keyup change', function(){
if($('#content').height() < 400 ){ if($('#content').height() < 400 ){
$('.paste-option.down').remove(); $('.paste-option.down').remove();
} }
else { else {
if ($('.paste-option').length == 1) { if ($('.paste-option').length == 1) {
$('.paste-option').clone().addClass('down').appendTo('form.well'); $('.paste-option').clone().addClass('down').appendTo('form.well');
} }
@ -443,52 +534,84 @@ $('#content').live('keyup change', function(){
}); });
/* Display previous pastes */
$('.previous-pastes .items').html(zerobin.getPastes());
/* clone a paste */ /* 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.reload()});
}
});
});
}
}
/* Event handler for "clone paste" button */
$('.btn-clone').click(function(e){ $('.btn-clone').click(function(e){
e.preventDefault(); e.preventDefault();
var content_clone = zerobin.getPasteContent();
$('.submit-form').show(); $('.submit-form').show();
$('.paste-form').remove(); $('.paste-form').hide();
$('#content').val(content_clone); $('#content').val(zerobin.getPasteContent()).trigger('change');
$('#content').trigger('change'); });
$('.clone .btn-danger').click(function(e){
e.preventDefault();
$('.submit-form').hide();
$('.paste-form').show();
}); });
/* Upload file using HTML5 File API */ /* Upload file using HTML5 File API */
if (zerobin.support.fileUpload) {
if (window.File && window.FileReader && window.FileList && window.Blob) { var upload = function(files) {
$('.file-upload').show(); var reader = new FileReader();
reader.onload = function(event) {
$('#content').val(event.target.result).trigger('change');
};
reader.readAsText(files[0]);
}
var $button = $('#file-upload');
try {
$button.change(function(){upload(this.files)});
}
catch (e) {
zerobin.message('error', 'Could no upload the file', 'Error');
}
$button.mouseover(mkcb($(this).css, 'cursor', 'pointer'));
} }
var file_upload = function(file) {
var reader = new FileReader();
reader.onload = function(event) {
var content = event.target.result;
$('#content').val(content);
$('#content').trigger('change');
};
reader.readAsText(file[0]);
}
try {
$('#file-upload').change(function() {
file_upload(this.files);
});
}
catch (e) {
zerobin.message('error', 'Could no upload the file', 'Error');
}
$('#file-upload').mouseover(function(){
$(this).css( 'cursor', 'pointer' );
});
/* Alerts */ /* Alerts */
$(".close").live('click', function(e){ $(".close").live('click', function(e){
@ -496,6 +619,7 @@ $(".close").live('click', function(e){
$(this).parent().fadeOut(); $(this).parent().fadeOut();
}); });
}); /* End of "document ready" jquery callback */ }); /* End of "document ready" jquery callback */

2
static/js/vizhash.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -19,9 +19,10 @@
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script> <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]--> <![endif]-->
<script src="/static/js/sjcl.js"></script>
<script src="/static/js/jquery-1.7.2.min.js"></script> <script src="/static/js/jquery-1.7.2.min.js"></script>
<script src="/static/js/sjcl.js"></script>
<script src="/static/js/behavior.js"></script> <script src="/static/js/behavior.js"></script>
<script type="text/javascript"> <script type="text/javascript">
zerobin.max_size = {{ get('max_size', -1)}}; zerobin.max_size = {{ get('max_size', -1)}};
</script> </script>
@ -58,7 +59,19 @@
<div class="well sidebar-nav"> <div class="well sidebar-nav">
<ul class="nav nav-list previous-pastes"> <ul class="nav nav-list previous-pastes">
<li class="nav-header">Previous pastes</li> <li class="nav-header">Previous pastes</li>
<li class="items"></li> <li class="item local-storage">
<em class="grey">
Your previous pastes will be saved in your browser using
<a href="http://www.w3.org/TR/webstorage/">localStorage</a>.
</em>
</li>
<li class="item no-local-storage">
<em class="grey">
Sorry your browser does not support
<a href="http://www.w3.org/TR/webstorage/">LocalStorage</a>,
We cannot display your previous pastes.
</em>
</li>
</ul> </ul>
</div><!--/.well --> </div><!--/.well -->
</div><!--/span--> </div><!--/span-->
@ -94,27 +107,10 @@
</p> </p>
</footer> </footer>
<script src="/static/js/jquery.elastic.source.js"></script> <script src="/static/js/jquery.elastic.source.js"></script>
<script src="/static/js/lzw.js"></script> <script src="/static/js/lzw.js"></script>
<script src="/static/js/prettify.min.js"></script> <script src="/static/js/prettify.min.js"></script>
<script src="/static/js/ZeroClipboard.js"></script> <script src="/static/js/ZeroClipboard.js"></script>
<!--
<script src="/static/js/jquery.js"></script>
<script src="/static/js/bootstrap-transition.js"></script>
<script src="/static/js/bootstrap-alert.js"></script>
<script src="/static/js/bootstrap-modal.js"></script>
<script src="/static/js/bootstrap-dropdown.js"></script>
<script src="/static/js/bootstrap-scrollspy.js"></script>
<script src="/static/js/bootstrap-tab.js"></script>
<script src="/static/js/bootstrap-tooltip.js"></script>
<script src="/static/js/bootstrap-popover.js"></script>
<script src="/static/js/bootstrap-button.js"></script>
<script src="/static/js/bootstrap-collapse.js"></script>
<script src="/static/js/bootstrap-carousel.js"></script>
<script src="/static/js/bootstrap-typeahead.js"></script>
-->
<p id="alert-template"> <p id="alert-template">
<a class="close" data-dismiss="alert" href="#">×</a> <a class="close" data-dismiss="alert" href="#">×</a>

View File

@ -4,24 +4,24 @@
</p> </p>
<form class="well" method="post" action="/paste/create"> <form class="well" method="post" action="/paste/create">
<p class="paste-option"> <p class="paste-option">
<label for="expiration" >Expiration:</label> <label for="expiration" >Expiration:</label>
<select id="expiration" name="expiration"> <select id="expiration" name="expiration">
<option value="burn_after_reading">Burn after reading</option> <option value="burn_after_reading">Burn after reading</option>
<option selected value="1_day">1 day</option> <option selected value="1_day">1 day</option>
<option value="1_month">1 month</option> <option value="1_month">1 month</option>
<option value="never">Never</option> <option value="never">Never</option>
</select> </select>
<button type="submit" class="btn btn-primary">Submit</button> <button type="submit" class="btn btn-primary">Submit</button>
</p> </p>
<p> <p>
<div class="progress progress-striped active"> <div class="progress progress-striped active">
<div class="bar"></div> <div class="bar"></div>
</div> </div>
<textarea rows="10" style="width:100%;" <textarea rows="10" style="width:100%;"
class="input-xlarge" class="input-xlarge"
id="content" name="content"></textarea> id="content" name="content"></textarea>
</p> </p>
</form> </form>

View File

@ -53,25 +53,28 @@
</div> </div>
<!-- For cloning --> <!-- For cloning -->
<span class="submit-form"> <div class="submit-form clone">
<form class="well" method="post" action="/paste/create"> <form class="well" method="post" action="/paste/create">
<p class="paste-option"> <p class="paste-option">
<label for="expiration" >Expiration:</label> <label for="expiration" >Expiration:</label>
<select id="expiration" name="expiration"> <select id="expiration" name="expiration">
<option value="burn_after_reading">Burn after reading</option> <option value="burn_after_reading">Burn after reading</option>
<option selected value="1_day">1 day</option> <option selected value="1_day">1 day</option>
<option value="1_month">1 month</option> <option value="1_month">1 month</option>
<option value="never">Never</option> <option value="never">Never</option>
</select> </select>
<button type="submit" class="btn btn-primary">Submit</button> <button type="submit" class="btn btn-primary">Submit</button>
<p> </p>
<p> <p>
<textarea rows="10" style="width:100%;" <div class="progress progress-striped active">
class="input-xlarge" <div class="bar"></div>
id="content" name="content"></textarea> </div>
</p> <textarea rows="10" style="width:100%;"
</form> class="input-xlarge"
</span> id="content" name="content"></textarea>
</p>
</form>
</div>
%rebase base max_size=max_size %rebase base max_size=max_size