mirror of
https://github.com/Tygs/0bin.git
synced 2023-08-10 21:13:00 +03:00
jQuery fully removed, clipboard fixed
This commit is contained in:
parent
722fb45b51
commit
e13cead89b
@ -10,9 +10,7 @@
|
|||||||
be pasted in it. The idea is that one can (probably...) not be legally entitled
|
be pasted in it. The idea is that one can (probably...) not be legally entitled
|
||||||
to `moderate the pastebin content`_ as they have no way to decrypt it.
|
to `moderate the pastebin content`_ as they have no way to decrypt it.
|
||||||
|
|
||||||
It's an Python implementation of the
|
It's an Python implementation of the `zerobin project`_, created by sebsauvage, under the `WTF licence`_.
|
||||||
`zerobin project`_ under the `WTF licence`_. It's easy to
|
|
||||||
install even if you know nothing about Python.
|
|
||||||
|
|
||||||
For now tested with IE9, and the last opera, safari, chrome and FF.
|
For now tested with IE9, and the last opera, safari, chrome and FF.
|
||||||
|
|
||||||
@ -22,7 +20,7 @@ but in short::
|
|||||||
pip install zerobin
|
pip install zerobin
|
||||||
zerobin
|
zerobin
|
||||||
|
|
||||||
0bin runs on Python 2.7 and Python 3.4.
|
0bin runs on Python 3.7.
|
||||||
|
|
||||||
How it works
|
How it works
|
||||||
=============
|
=============
|
||||||
@ -74,7 +72,6 @@ Technologies used
|
|||||||
- Cherrypy_ (server only)
|
- Cherrypy_ (server only)
|
||||||
- `node.js`_ (for optional command-line tool only)
|
- `node.js`_ (for optional command-line tool only)
|
||||||
|
|
||||||
|
|
||||||
Known issues
|
Known issues
|
||||||
============
|
============
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ def runserver(
|
|||||||
server="cherrypy",
|
server="cherrypy",
|
||||||
):
|
):
|
||||||
|
|
||||||
|
debug = True
|
||||||
if version:
|
if version:
|
||||||
print("0bin V%s" % settings.VERSION)
|
print("0bin V%s" % settings.VERSION)
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import, print_function
|
from __future__ import unicode_literals, absolute_import, print_function
|
||||||
|
import pdb
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Script including controller, rooting, and dependency management.
|
Script including controller, rooting, and dependency management.
|
||||||
@ -24,59 +25,63 @@ from datetime import datetime, timedelta
|
|||||||
|
|
||||||
# add project dir and libs dir to the PYTHON PATH to ensure they are
|
# add project dir and libs dir to the PYTHON PATH to ensure they are
|
||||||
# importable
|
# importable
|
||||||
from zerobin.utils import (settings, SettingsValidationError,
|
from zerobin.utils import settings, SettingsValidationError, drop_privileges, dmerge
|
||||||
drop_privileges, dmerge)
|
|
||||||
|
|
||||||
import bottle
|
import bottle
|
||||||
from bottle import (Bottle, run, static_file, view, request)
|
from bottle import Bottle, run, static_file, view, request
|
||||||
|
|
||||||
from zerobin.paste import Paste
|
from zerobin.paste import Paste
|
||||||
|
|
||||||
|
|
||||||
app = Bottle()
|
app = Bottle()
|
||||||
GLOBAL_CONTEXT = {
|
GLOBAL_CONTEXT = {
|
||||||
'settings': settings,
|
"settings": settings,
|
||||||
'pastes_count': Paste.get_pastes_count(),
|
"pastes_count": Paste.get_pastes_count(),
|
||||||
'refresh_counter': datetime.now()
|
"refresh_counter": datetime.now(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@app.route('/')
|
@app.route("/")
|
||||||
@view('home')
|
@view("home")
|
||||||
def index():
|
def index():
|
||||||
return GLOBAL_CONTEXT
|
return GLOBAL_CONTEXT
|
||||||
|
|
||||||
|
|
||||||
@app.route('/faq/')
|
@app.route("/faq/")
|
||||||
@view('faq')
|
@view("faq")
|
||||||
def faq():
|
def faq():
|
||||||
return GLOBAL_CONTEXT
|
return GLOBAL_CONTEXT
|
||||||
|
|
||||||
|
|
||||||
@app.route('/paste/create', method='POST')
|
@app.route("/paste/create", method="POST")
|
||||||
def create_paste():
|
def create_paste():
|
||||||
|
|
||||||
try:
|
try:
|
||||||
body = urlparse.parse_qs(request.body.read(int(settings.MAX_SIZE * 1.1)))
|
body = urlparse.parse_qs(request.body.read(int(settings.MAX_SIZE * 1.1)))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return {'status': 'error', 'message': "Wrong data payload."}
|
return {"status": "error", "message": "Wrong data payload."}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
content = "".join(x.decode("utf8") for x in body[b"content"])
|
||||||
content = "".join(x.decode('utf8') for x in body[b'content'])
|
|
||||||
except (UnicodeDecodeError, KeyError):
|
except (UnicodeDecodeError, KeyError):
|
||||||
return {'status': 'error',
|
return {
|
||||||
'message': "Encoding error: the paste couldn't be saved."}
|
"status": "error",
|
||||||
|
"message": "Encoding error: the paste couldn't be saved.",
|
||||||
|
}
|
||||||
|
|
||||||
if '{"iv":' not in content: # reject silently non encrypted content
|
if '{"iv":' not in content: # reject silently non encrypted content
|
||||||
return {'status': 'error', 'message': "Wrong data payload."}
|
return {"status": "error", "message": "Wrong data payload."}
|
||||||
|
|
||||||
# check size of the paste. if more than settings return error
|
# check size of the paste. if more than settings return error
|
||||||
# without saving paste. prevent from unusual use of the
|
# without saving paste. prevent from unusual use of the
|
||||||
# system. need to be improved
|
# system. need to be improved
|
||||||
if 0 < len(content) < settings.MAX_SIZE:
|
if 0 < len(content) < settings.MAX_SIZE:
|
||||||
expiration = body.get(b'expiration', ['burn_after_reading'])[0]
|
expiration = body.get(b"expiration", [b"burn_after_reading"])[0]
|
||||||
paste = Paste(expiration=expiration.decode('utf8'), content=content,
|
paste = Paste(
|
||||||
uuid_length=settings.PASTE_ID_LENGTH)
|
expiration=expiration.decode("utf8"),
|
||||||
|
content=content,
|
||||||
|
uuid_length=settings.PASTE_ID_LENGTH,
|
||||||
|
)
|
||||||
paste.save()
|
paste.save()
|
||||||
|
|
||||||
# display counter
|
# display counter
|
||||||
@ -87,21 +92,23 @@ def create_paste():
|
|||||||
|
|
||||||
# if refresh time elapsed pick up new counter value
|
# if refresh time elapsed pick up new counter value
|
||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
timeout = (GLOBAL_CONTEXT['refresh_counter']
|
timeout = GLOBAL_CONTEXT["refresh_counter"] + timedelta(
|
||||||
+ timedelta(seconds=settings.REFRESH_COUNTER))
|
seconds=settings.REFRESH_COUNTER
|
||||||
|
)
|
||||||
if timeout < now:
|
if timeout < now:
|
||||||
GLOBAL_CONTEXT['pastes_count'] = Paste.get_pastes_count()
|
GLOBAL_CONTEXT["pastes_count"] = Paste.get_pastes_count()
|
||||||
GLOBAL_CONTEXT['refresh_counter'] = now
|
GLOBAL_CONTEXT["refresh_counter"] = now
|
||||||
|
|
||||||
return {'status': 'ok', 'paste': paste.uuid}
|
return {"status": "ok", "paste": paste.uuid}
|
||||||
|
|
||||||
return {'status': 'error',
|
return {
|
||||||
'message': "Serveur error: the paste couldn't be saved. "
|
"status": "error",
|
||||||
"Please try later."}
|
"message": "Serveur error: the paste couldn't be saved. " "Please try later.",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@app.route('/paste/:paste_id')
|
@app.route("/paste/:paste_id")
|
||||||
@view('paste')
|
@view("paste")
|
||||||
def display_paste(paste_id):
|
def display_paste(paste_id):
|
||||||
|
|
||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
@ -115,9 +122,8 @@ def display_paste(paste_id):
|
|||||||
# we don't delete the paste because it means it's the redirection
|
# we don't delete the paste because it means it's the redirection
|
||||||
# to the paste that happens during the paste creation
|
# to the paste that happens during the paste creation
|
||||||
try:
|
try:
|
||||||
keep_alive = paste.expiration.split('#')[1]
|
keep_alive = paste.expiration.split("#")[1]
|
||||||
keep_alive = datetime.strptime(keep_alive,
|
keep_alive = datetime.strptime(keep_alive, "%Y-%m-%d %H:%M:%S.%f")
|
||||||
'%Y-%m-%d %H:%M:%S.%f')
|
|
||||||
keep_alive = now < keep_alive + timedelta(seconds=10)
|
keep_alive = now < keep_alive + timedelta(seconds=10)
|
||||||
except IndexError:
|
except IndexError:
|
||||||
keep_alive = False
|
keep_alive = False
|
||||||
@ -131,35 +137,34 @@ def display_paste(paste_id):
|
|||||||
except (TypeError, ValueError):
|
except (TypeError, ValueError):
|
||||||
return error404(ValueError)
|
return error404(ValueError)
|
||||||
|
|
||||||
context = {'paste': paste, 'keep_alive': keep_alive}
|
context = {"paste": paste, "keep_alive": keep_alive}
|
||||||
return dmerge(context, GLOBAL_CONTEXT)
|
return dmerge(context, GLOBAL_CONTEXT)
|
||||||
|
|
||||||
|
|
||||||
@app.error(404)
|
@app.error(404)
|
||||||
@view('404')
|
@view("404")
|
||||||
def error404(code):
|
def error404(code):
|
||||||
return GLOBAL_CONTEXT
|
return GLOBAL_CONTEXT
|
||||||
|
|
||||||
|
|
||||||
@app.route('/static/<filename:path>')
|
@app.route("/static/<filename:path>")
|
||||||
def server_static(filename):
|
def server_static(filename):
|
||||||
return static_file(filename, root=settings.STATIC_FILES_ROOT)
|
return static_file(filename, root=settings.STATIC_FILES_ROOT)
|
||||||
|
|
||||||
|
|
||||||
def get_app(debug=None, settings_file='',
|
def get_app(debug=None, settings_file="", compressed_static=None, settings=settings):
|
||||||
compressed_static=None, settings=settings):
|
|
||||||
"""
|
"""
|
||||||
Return a tuple (settings, app) configured using passed
|
Return a tuple (settings, app) configured using passed
|
||||||
parameters and/or a setting file.
|
parameters and/or a setting file.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
settings_file = settings_file or os.environ.get('ZEROBIN_SETTINGS_FILE')
|
settings_file = settings_file or os.environ.get("ZEROBIN_SETTINGS_FILE")
|
||||||
|
|
||||||
if settings_file:
|
if settings_file:
|
||||||
settings.update_with_file(os.path.realpath(settings_file))
|
settings.update_with_file(os.path.realpath(settings_file))
|
||||||
|
|
||||||
if settings.PASTE_ID_LENGTH < 4:
|
if settings.PASTE_ID_LENGTH < 4:
|
||||||
raise SettingsValidationError('PASTE_ID_LENGTH cannot be lower than 4')
|
raise SettingsValidationError("PASTE_ID_LENGTH cannot be lower than 4")
|
||||||
|
|
||||||
if compressed_static is not None:
|
if compressed_static is not None:
|
||||||
settings.COMPRESSED_STATIC_FILES = compressed_static
|
settings.COMPRESSED_STATIC_FILES = compressed_static
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
/* logo */
|
[v-cloak] {
|
||||||
|
display: none
|
||||||
|
}
|
||||||
|
|
||||||
|
.noscript {
|
||||||
|
position: relative;
|
||||||
|
top: 25%;
|
||||||
|
border: 25px solid red;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* logo */
|
||||||
|
|
||||||
.brand {
|
.brand {
|
||||||
font-size: 38px !important;
|
font-size: 38px !important;
|
||||||
@ -46,6 +55,7 @@ body {
|
|||||||
padding-top: 60px;
|
padding-top: 60px;
|
||||||
padding-bottom: 40px;
|
padding-bottom: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-nav {
|
.sidebar-nav {
|
||||||
padding: 9px 0;
|
padding: 9px 0;
|
||||||
}
|
}
|
||||||
@ -62,7 +72,8 @@ label {
|
|||||||
color: #888;
|
color: #888;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul, ol {
|
ul,
|
||||||
|
ol {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
@ -71,7 +82,6 @@ li {
|
|||||||
margin-left: -9px;
|
margin-left: -9px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin: 0 0 20px;
|
margin: 0 0 20px;
|
||||||
}
|
}
|
||||||
@ -152,7 +162,6 @@ html.no-file-upload p.file-upload {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
input.btn-upload {
|
input.btn-upload {
|
||||||
position: relative;
|
position: relative;
|
||||||
left: -6px;
|
left: -6px;
|
||||||
@ -175,7 +184,6 @@ input.hide-upload {
|
|||||||
height: 49px;
|
height: 49px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Paste Page */
|
/* Paste Page */
|
||||||
|
|
||||||
#paste-content {
|
#paste-content {
|
||||||
@ -183,7 +191,6 @@ input.hide-upload {
|
|||||||
padding: 1em;
|
padding: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#paste-content.linenums {
|
#paste-content.linenums {
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
}
|
}
|
||||||
@ -201,9 +208,16 @@ a#clip-button.hover{
|
|||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
li.L0, li.L1, li.L2, li.L3, li.L4,
|
li.L0,
|
||||||
li.L5, li.L6, li.L7, li.L8, li.L9
|
li.L1,
|
||||||
{
|
li.L2,
|
||||||
|
li.L3,
|
||||||
|
li.L4,
|
||||||
|
li.L5,
|
||||||
|
li.L6,
|
||||||
|
li.L7,
|
||||||
|
li.L8,
|
||||||
|
li.L9 {
|
||||||
list-style-type: decimal;
|
list-style-type: decimal;
|
||||||
background: inherit;
|
background: inherit;
|
||||||
}
|
}
|
||||||
@ -216,8 +230,10 @@ li.L5, li.L6, li.L7, li.L8, li.L9
|
|||||||
|
|
||||||
/* Specify class=linenums on a pre to get line numbering */
|
/* Specify class=linenums on a pre to get line numbering */
|
||||||
ol.linenums {
|
ol.linenums {
|
||||||
margin: 0 0 0 55px; /* IE indents via margin-left */
|
margin: 0 0 0 55px;
|
||||||
|
/* IE indents via margin-left */
|
||||||
}
|
}
|
||||||
|
|
||||||
ol.linenums li {
|
ol.linenums li {
|
||||||
color: #bebec5;
|
color: #bebec5;
|
||||||
line-height: 18px;
|
line-height: 18px;
|
||||||
@ -241,7 +257,9 @@ pre {
|
|||||||
color: #66F;
|
color: #66F;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pun, .opn, .clo {
|
.pun,
|
||||||
|
.opn,
|
||||||
|
.clo {
|
||||||
color: #0A0;
|
color: #0A0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,7 +271,6 @@ color: #933;
|
|||||||
color: #C0C;
|
color: #C0C;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Common css */
|
/* Common css */
|
||||||
|
|
||||||
form {
|
form {
|
||||||
@ -266,7 +283,8 @@ form textarea {
|
|||||||
min-height: 250px;
|
min-height: 250px;
|
||||||
}
|
}
|
||||||
|
|
||||||
button.btn, input[type="submit"].btn {
|
button.btn,
|
||||||
|
input[type="submit"].btn {
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,19 +304,16 @@ button.btn, input[type="submit"].btn {
|
|||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-primary, .btn-danger {
|
.btn-primary,
|
||||||
|
.btn-danger {
|
||||||
position: relative;
|
position: relative;
|
||||||
top: -4px;
|
top: -4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#alert-template {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Progress bar */
|
/** Progress bar */
|
||||||
|
|
||||||
.progress {
|
.progress {
|
||||||
display:none;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress .bar {
|
.progress .bar {
|
||||||
@ -312,7 +327,6 @@ button.btn, input[type="submit"].btn {
|
|||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Previous paste list */
|
/* Previous paste list */
|
||||||
|
|
||||||
.previous-pastes .item {
|
.previous-pastes .item {
|
||||||
@ -345,10 +359,6 @@ canvas {
|
|||||||
border: 1px solid white;
|
border: 1px solid white;
|
||||||
}
|
}
|
||||||
|
|
||||||
#wrap-content {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.noscript {
|
.noscript {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: red;
|
color: red;
|
||||||
|
@ -1,311 +0,0 @@
|
|||||||
// Simple Set Clipboard System
|
|
||||||
// Author: Joseph Huckaby
|
|
||||||
|
|
||||||
var ZeroClipboard = {
|
|
||||||
|
|
||||||
version: "1.0.7",
|
|
||||||
clients: {}, // registered upload clients on page, indexed by id
|
|
||||||
moviePath: 'ZeroClipboard.swf', // URL to movie
|
|
||||||
nextId: 1, // ID of next movie
|
|
||||||
|
|
||||||
$: function(thingy) {
|
|
||||||
// simple DOM lookup utility function
|
|
||||||
if (typeof(thingy) == 'string') thingy = document.getElementById(thingy);
|
|
||||||
if (!thingy.addClass) {
|
|
||||||
// extend element with a few useful methods
|
|
||||||
thingy.hide = function() { this.style.display = 'none'; };
|
|
||||||
thingy.show = function() { this.style.display = ''; };
|
|
||||||
thingy.addClass = function(name) { this.removeClass(name); this.className += ' ' + name; };
|
|
||||||
thingy.removeClass = function(name) {
|
|
||||||
var classes = this.className.split(/\s+/);
|
|
||||||
var idx = -1;
|
|
||||||
for (var k = 0; k < classes.length; k++) {
|
|
||||||
if (classes[k] == name) { idx = k; k = classes.length; }
|
|
||||||
}
|
|
||||||
if (idx > -1) {
|
|
||||||
classes.splice( idx, 1 );
|
|
||||||
this.className = classes.join(' ');
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
thingy.hasClass = function(name) {
|
|
||||||
return !!this.className.match( new RegExp("\\s*" + name + "\\s*") );
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return thingy;
|
|
||||||
},
|
|
||||||
|
|
||||||
setMoviePath: function(path) {
|
|
||||||
// set path to ZeroClipboard.swf
|
|
||||||
this.moviePath = path;
|
|
||||||
},
|
|
||||||
|
|
||||||
dispatch: function(id, eventName, args) {
|
|
||||||
// receive event from flash movie, send to client
|
|
||||||
var client = this.clients[id];
|
|
||||||
if (client) {
|
|
||||||
client.receiveEvent(eventName, args);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
register: function(id, client) {
|
|
||||||
// register new client to receive events
|
|
||||||
this.clients[id] = client;
|
|
||||||
},
|
|
||||||
|
|
||||||
getDOMObjectPosition: function(obj, stopObj) {
|
|
||||||
// get absolute coordinates for dom element
|
|
||||||
var info = {
|
|
||||||
left: 0,
|
|
||||||
top: 0,
|
|
||||||
width: obj.width ? obj.width : obj.offsetWidth,
|
|
||||||
height: obj.height ? obj.height : obj.offsetHeight
|
|
||||||
};
|
|
||||||
|
|
||||||
while (obj && (obj != stopObj)) {
|
|
||||||
info.left += obj.offsetLeft;
|
|
||||||
info.top += obj.offsetTop;
|
|
||||||
obj = obj.offsetParent;
|
|
||||||
}
|
|
||||||
|
|
||||||
return info;
|
|
||||||
},
|
|
||||||
|
|
||||||
Client: function(elem) {
|
|
||||||
// constructor for new simple upload client
|
|
||||||
this.handlers = {};
|
|
||||||
|
|
||||||
// unique ID
|
|
||||||
this.id = ZeroClipboard.nextId++;
|
|
||||||
this.movieId = 'ZeroClipboardMovie_' + this.id;
|
|
||||||
|
|
||||||
// register client with singleton to receive flash events
|
|
||||||
ZeroClipboard.register(this.id, this);
|
|
||||||
|
|
||||||
// create movie
|
|
||||||
if (elem) this.glue(elem);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ZeroClipboard.Client.prototype = {
|
|
||||||
|
|
||||||
id: 0, // unique ID for us
|
|
||||||
ready: false, // whether movie is ready to receive events or not
|
|
||||||
movie: null, // reference to movie object
|
|
||||||
clipText: '', // text to copy to clipboard
|
|
||||||
handCursorEnabled: true, // whether to show hand cursor, or default pointer cursor
|
|
||||||
cssEffects: true, // enable CSS mouse effects on dom container
|
|
||||||
handlers: null, // user event handlers
|
|
||||||
|
|
||||||
glue: function(elem, appendElem, stylesToAdd) {
|
|
||||||
// glue to DOM element
|
|
||||||
// elem can be ID or actual DOM element object
|
|
||||||
this.domElement = ZeroClipboard.$(elem);
|
|
||||||
|
|
||||||
// float just above object, or zIndex 99 if dom element isn't set
|
|
||||||
var zIndex = 99;
|
|
||||||
if (this.domElement.style.zIndex) {
|
|
||||||
zIndex = parseInt(this.domElement.style.zIndex, 10) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof(appendElem) == 'string') {
|
|
||||||
appendElem = ZeroClipboard.$(appendElem);
|
|
||||||
}
|
|
||||||
else if (typeof(appendElem) == 'undefined') {
|
|
||||||
appendElem = document.getElementsByTagName('body')[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
// find X/Y position of domElement
|
|
||||||
var box = ZeroClipboard.getDOMObjectPosition(this.domElement, appendElem);
|
|
||||||
|
|
||||||
// create floating DIV above element
|
|
||||||
this.div = document.createElement('div');
|
|
||||||
var style = this.div.style;
|
|
||||||
style.position = 'absolute';
|
|
||||||
style.left = '' + box.left + 'px';
|
|
||||||
style.top = '' + box.top + 'px';
|
|
||||||
style.width = '' + box.width + 'px';
|
|
||||||
style.height = '' + box.height + 'px';
|
|
||||||
style.zIndex = zIndex;
|
|
||||||
|
|
||||||
if (typeof(stylesToAdd) == 'object') {
|
|
||||||
for (addedStyle in stylesToAdd) {
|
|
||||||
style[addedStyle] = stylesToAdd[addedStyle];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//style.backgroundColor = '#f00'; // debug
|
|
||||||
|
|
||||||
appendElem.appendChild(this.div);
|
|
||||||
|
|
||||||
this.div.innerHTML = this.getHTML( box.width, box.height );
|
|
||||||
},
|
|
||||||
|
|
||||||
getHTML: function(width, height) {
|
|
||||||
// return HTML for movie
|
|
||||||
var html = '';
|
|
||||||
var flashvars = 'id=' + this.id +
|
|
||||||
'&width=' + width +
|
|
||||||
'&height=' + height;
|
|
||||||
|
|
||||||
if (navigator.userAgent.match(/MSIE/)) {
|
|
||||||
// IE gets an OBJECT tag
|
|
||||||
var protocol = location.href.match(/^https/i) ? 'https://' : 'http://';
|
|
||||||
html += '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="'+protocol+'download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="'+width+'" height="'+height+'" id="'+this.movieId+'" align="middle"><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="false" /><param name="movie" value="'+ZeroClipboard.moviePath+'" /><param name="loop" value="false" /><param name="menu" value="false" /><param name="quality" value="best" /><param name="bgcolor" value="#ffffff" /><param name="flashvars" value="'+flashvars+'"/><param name="wmode" value="transparent"/></object>';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// all other browsers get an EMBED tag
|
|
||||||
html += '<embed id="'+this.movieId+'" src="'+ZeroClipboard.moviePath+'" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="'+width+'" height="'+height+'" name="'+this.movieId+'" align="middle" allowScriptAccess="always" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="'+flashvars+'" wmode="transparent" />';
|
|
||||||
}
|
|
||||||
return html;
|
|
||||||
},
|
|
||||||
|
|
||||||
hide: function() {
|
|
||||||
// temporarily hide floater offscreen
|
|
||||||
if (this.div) {
|
|
||||||
this.div.style.left = '-2000px';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
show: function() {
|
|
||||||
// show ourselves after a call to hide()
|
|
||||||
this.reposition();
|
|
||||||
},
|
|
||||||
|
|
||||||
destroy: function() {
|
|
||||||
// destroy control and floater
|
|
||||||
if (this.domElement && this.div) {
|
|
||||||
this.hide();
|
|
||||||
this.div.innerHTML = '';
|
|
||||||
|
|
||||||
var body = document.getElementsByTagName('body')[0];
|
|
||||||
try { body.removeChild( this.div ); } catch(e) {;}
|
|
||||||
|
|
||||||
this.domElement = null;
|
|
||||||
this.div = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
reposition: function(elem) {
|
|
||||||
// reposition our floating div, optionally to new container
|
|
||||||
// warning: container CANNOT change size, only position
|
|
||||||
if (elem) {
|
|
||||||
this.domElement = ZeroClipboard.$(elem);
|
|
||||||
if (!this.domElement) this.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.domElement && this.div) {
|
|
||||||
var box = ZeroClipboard.getDOMObjectPosition(this.domElement);
|
|
||||||
var style = this.div.style;
|
|
||||||
style.left = '' + box.left + 'px';
|
|
||||||
style.top = '' + box.top + 'px';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
setText: function(newText) {
|
|
||||||
// set text to be copied to clipboard
|
|
||||||
this.clipText = newText;
|
|
||||||
if (this.ready) this.movie.setText(newText);
|
|
||||||
},
|
|
||||||
|
|
||||||
addEventListener: function(eventName, func) {
|
|
||||||
// add user event listener for event
|
|
||||||
// event types: load, queueStart, fileStart, fileComplete, queueComplete, progress, error, cancel
|
|
||||||
eventName = eventName.toString().toLowerCase().replace(/^on/, '');
|
|
||||||
if (!this.handlers[eventName]) this.handlers[eventName] = [];
|
|
||||||
this.handlers[eventName].push(func);
|
|
||||||
},
|
|
||||||
|
|
||||||
setHandCursor: function(enabled) {
|
|
||||||
// enable hand cursor (true), or default arrow cursor (false)
|
|
||||||
this.handCursorEnabled = enabled;
|
|
||||||
if (this.ready) this.movie.setHandCursor(enabled);
|
|
||||||
},
|
|
||||||
|
|
||||||
setCSSEffects: function(enabled) {
|
|
||||||
// enable or disable CSS effects on DOM container
|
|
||||||
this.cssEffects = !!enabled;
|
|
||||||
},
|
|
||||||
|
|
||||||
receiveEvent: function(eventName, args) {
|
|
||||||
// receive event from flash
|
|
||||||
eventName = eventName.toString().toLowerCase().replace(/^on/, '');
|
|
||||||
|
|
||||||
// special behavior for certain events
|
|
||||||
switch (eventName) {
|
|
||||||
case 'load':
|
|
||||||
// movie claims it is ready, but in IE this isn't always the case...
|
|
||||||
// bug fix: Cannot extend EMBED DOM elements in Firefox, must use traditional function
|
|
||||||
this.movie = document.getElementById(this.movieId);
|
|
||||||
if (!this.movie) {
|
|
||||||
var self = this;
|
|
||||||
setTimeout( function() { self.receiveEvent('load', null); }, 1 );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// firefox on pc needs a "kick" in order to set these in certain cases
|
|
||||||
if (!this.ready && navigator.userAgent.match(/Firefox/) && navigator.userAgent.match(/Windows/)) {
|
|
||||||
var self = this;
|
|
||||||
setTimeout( function() { self.receiveEvent('load', null); }, 100 );
|
|
||||||
this.ready = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.ready = true;
|
|
||||||
this.movie.setText( this.clipText );
|
|
||||||
this.movie.setHandCursor( this.handCursorEnabled );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'mouseover':
|
|
||||||
if (this.domElement && this.cssEffects) {
|
|
||||||
this.domElement.addClass('hover');
|
|
||||||
if (this.recoverActive) this.domElement.addClass('active');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'mouseout':
|
|
||||||
if (this.domElement && this.cssEffects) {
|
|
||||||
this.recoverActive = false;
|
|
||||||
if (this.domElement.hasClass('active')) {
|
|
||||||
this.domElement.removeClass('active');
|
|
||||||
this.recoverActive = true;
|
|
||||||
}
|
|
||||||
this.domElement.removeClass('hover');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'mousedown':
|
|
||||||
if (this.domElement && this.cssEffects) {
|
|
||||||
this.domElement.addClass('active');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'mouseup':
|
|
||||||
if (this.domElement && this.cssEffects) {
|
|
||||||
this.domElement.removeClass('active');
|
|
||||||
this.recoverActive = false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
} // switch eventName
|
|
||||||
|
|
||||||
if (this.handlers[eventName]) {
|
|
||||||
for (var idx = 0, len = this.handlers[eventName].length; idx < len; idx++) {
|
|
||||||
var func = this.handlers[eventName][idx];
|
|
||||||
|
|
||||||
if (typeof(func) == 'function') {
|
|
||||||
// actual function reference
|
|
||||||
func(this, args);
|
|
||||||
}
|
|
||||||
else if ((typeof(func) == 'object') && (func.length == 2)) {
|
|
||||||
// PHP style object + method, i.e. [myObject, 'myMethod']
|
|
||||||
func[0][ func[1] ](this, args);
|
|
||||||
}
|
|
||||||
else if (typeof(func) == 'string') {
|
|
||||||
// name of function
|
|
||||||
window[func](this, args);
|
|
||||||
}
|
|
||||||
} // foreach event handler defined
|
|
||||||
} // user defined handler for event
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
4
zerobin/static/js/jquery-1.7.2.min.js
vendored
4
zerobin/static/js/jquery-1.7.2.min.js
vendored
File diff suppressed because one or more lines are too long
@ -1,162 +0,0 @@
|
|||||||
/**
|
|
||||||
* @name Elastic
|
|
||||||
* @descripton Elastic is jQuery plugin that grow and shrink your textareas automatically
|
|
||||||
* @version 1.6.11
|
|
||||||
* @requires jQuery 1.2.6+
|
|
||||||
*
|
|
||||||
* @author Jan Jarfalk
|
|
||||||
* @author-email jan.jarfalk@unwrongest.com
|
|
||||||
* @author-website http://www.unwrongest.com
|
|
||||||
*
|
|
||||||
* @licence MIT License - http://www.opensource.org/licenses/mit-license.php
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function($){
|
|
||||||
jQuery.fn.extend({
|
|
||||||
elastic: function() {
|
|
||||||
|
|
||||||
// We will create a div clone of the textarea
|
|
||||||
// by copying these attributes from the textarea to the div.
|
|
||||||
var mimics = [
|
|
||||||
'paddingTop',
|
|
||||||
'paddingRight',
|
|
||||||
'paddingBottom',
|
|
||||||
'paddingLeft',
|
|
||||||
'fontSize',
|
|
||||||
'lineHeight',
|
|
||||||
'fontFamily',
|
|
||||||
'width',
|
|
||||||
'fontWeight',
|
|
||||||
'border-top-width',
|
|
||||||
'border-right-width',
|
|
||||||
'border-bottom-width',
|
|
||||||
'border-left-width',
|
|
||||||
'borderTopStyle',
|
|
||||||
'borderTopColor',
|
|
||||||
'borderRightStyle',
|
|
||||||
'borderRightColor',
|
|
||||||
'borderBottomStyle',
|
|
||||||
'borderBottomColor',
|
|
||||||
'borderLeftStyle',
|
|
||||||
'borderLeftColor'
|
|
||||||
];
|
|
||||||
|
|
||||||
return this.each( function() {
|
|
||||||
|
|
||||||
// Elastic only works on textareas
|
|
||||||
if ( this.type !== 'textarea' ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var $textarea = jQuery(this),
|
|
||||||
$twin = jQuery('<div />').css({
|
|
||||||
'position' : 'absolute',
|
|
||||||
'display' : 'none',
|
|
||||||
'word-wrap' : 'break-word',
|
|
||||||
'white-space' :'pre-wrap'
|
|
||||||
}),
|
|
||||||
lineHeight = parseInt($textarea.css('line-height'),10) || parseInt($textarea.css('font-size'),'10'),
|
|
||||||
minheight = parseInt($textarea.css('height'),10) || lineHeight*3,
|
|
||||||
maxheight = parseInt($textarea.css('max-height'),10) || Number.MAX_VALUE,
|
|
||||||
goalheight = 0;
|
|
||||||
|
|
||||||
// Opera returns max-height of -1 if not set
|
|
||||||
if (maxheight < 0) { maxheight = Number.MAX_VALUE; }
|
|
||||||
|
|
||||||
// Append the twin to the DOM
|
|
||||||
// We are going to meassure the height of this, not the textarea.
|
|
||||||
$twin.appendTo($textarea.parent());
|
|
||||||
|
|
||||||
// Copy the essential styles (mimics) from the textarea to the twin
|
|
||||||
var i = mimics.length;
|
|
||||||
while(i--){
|
|
||||||
$twin.css(mimics[i].toString(),$textarea.css(mimics[i].toString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Updates the width of the twin. (solution for textareas with widths in percent)
|
|
||||||
function setTwinWidth(){
|
|
||||||
var curatedWidth = Math.floor(parseInt($textarea.width(),10));
|
|
||||||
if($twin.width() !== curatedWidth){
|
|
||||||
$twin.css({'width': curatedWidth + 'px'});
|
|
||||||
|
|
||||||
// Update height of textarea
|
|
||||||
update(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets a given height and overflow state on the textarea
|
|
||||||
function setHeightAndOverflow(height, overflow){
|
|
||||||
|
|
||||||
var curratedHeight = Math.floor(parseInt(height,10));
|
|
||||||
if($textarea.height() !== curratedHeight){
|
|
||||||
$textarea.css({'height': curratedHeight + 'px','overflow':overflow});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function will update the height of the textarea if necessary
|
|
||||||
function update(forced) {
|
|
||||||
|
|
||||||
// Get curated content from the textarea.
|
|
||||||
var textareaContent = $textarea.val().replace(/&/g,'&').replace(/ {2}/g, ' ').replace(/<|>/g, '>').replace(/\n/g, '<br />');
|
|
||||||
|
|
||||||
// Compare curated content with curated twin.
|
|
||||||
var twinContent = $twin.html().replace(/<br>/ig,'<br />');
|
|
||||||
|
|
||||||
if(forced || textareaContent+' ' !== twinContent){
|
|
||||||
|
|
||||||
// Add an extra white space so new rows are added when you are at the end of a row.
|
|
||||||
$twin.html(textareaContent+' ');
|
|
||||||
|
|
||||||
// Change textarea height if twin plus the height of one line differs more than 3 pixel from textarea height
|
|
||||||
if(Math.abs($twin.height() + lineHeight - $textarea.height()) > 3){
|
|
||||||
|
|
||||||
var goalheight = $twin.height()+lineHeight;
|
|
||||||
if(goalheight >= maxheight) {
|
|
||||||
setHeightAndOverflow(maxheight,'auto');
|
|
||||||
} else if(goalheight <= minheight) {
|
|
||||||
setHeightAndOverflow(minheight,'hidden');
|
|
||||||
} else {
|
|
||||||
setHeightAndOverflow(goalheight,'hidden');
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hide scrollbars
|
|
||||||
$textarea.css({'overflow':'hidden'});
|
|
||||||
|
|
||||||
// Update textarea size on keyup, change, cut and paste
|
|
||||||
$textarea.bind('keyup change cut paste', function(){
|
|
||||||
update();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update width of twin if browser or textarea is resized (solution for textareas with widths in percent)
|
|
||||||
$(window).bind('resize', setTwinWidth);
|
|
||||||
$textarea.bind('resize', setTwinWidth);
|
|
||||||
$textarea.bind('update', update);
|
|
||||||
|
|
||||||
// Compact textarea on blur
|
|
||||||
$textarea.bind('blur',function(){
|
|
||||||
if($twin.height() < maxheight){
|
|
||||||
if($twin.height() > minheight) {
|
|
||||||
$textarea.height($twin.height());
|
|
||||||
} else {
|
|
||||||
$textarea.height(minheight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// And this line is to catch the browser paste event
|
|
||||||
$textarea.bind('input paste',function(e){ setTimeout( update, 250); });
|
|
||||||
|
|
||||||
// Run update once when elastic is initialized
|
|
||||||
update();
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})(jQuery);
|
|
2
zerobin/static/js/vizhash.min.js
vendored
2
zerobin/static/js/vizhash.min.js
vendored
File diff suppressed because one or more lines are too long
11965
zerobin/static/js/vue.js
Normal file
11965
zerobin/static/js/vue.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<p class="alert alert-error">
|
<p class="alert alert-error">
|
||||||
<a class="close" data-dismiss="alert" href="#">×</a>
|
<a class="close" data-dismiss="alert" href="#" @click.prevent="$event.target.parentNode.remove()">×</a>
|
||||||
<strong class="title">404 Error!</strong>
|
<strong class="title">404 Error!</strong>
|
||||||
<span class="message">
|
<span class="message">
|
||||||
Either this paste has expired or this page never existed.
|
Either this paste has expired or this page never existed.
|
||||||
@ -11,28 +11,38 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p class="file-upload">
|
<p class="file-upload">
|
||||||
<input type="button" class="btn btn-upload" value="Upload File">
|
<input type="button" class="btn btn-upload" :value="isUploading ? 'Uploading...': 'Upload file'"
|
||||||
<input type="file" class="hide-upload" id="file-upload" >
|
:disabled="isUploading">
|
||||||
|
<input type="file" class="hide-upload" id="file-upload" @change="handleUpload($event.target.files)">
|
||||||
</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" v-model="newPaste.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" @click="encryptAndSendPaste($event)">Submit</button>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<div class="progress progress-striped active">
|
<div class="progress progress-striped active" v-show="isLoading">
|
||||||
<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" id="content" name="content" autofocus
|
||||||
class="input-xlarge"
|
v-on:keydown.ctrl.enter="encryptAndSendPaste($event)"></textarea>
|
||||||
id="content" name="content"></textarea>
|
</p>
|
||||||
|
<p class="paste-option down" v-if="displayBottomToolBar">
|
||||||
|
<label for="expiration">Expiration:</label>
|
||||||
|
<select id="expiration" name="expiration" v-model="newPaste.expiration">
|
||||||
|
<option value="burn_after_reading">Burn after reading</option>
|
||||||
|
<option selected value="1_day">1 day</option>
|
||||||
|
<option value="1_month">1 month</option>
|
||||||
|
<option value="never">Never</option>
|
||||||
|
</select>
|
||||||
|
<button type="submit" class="btn btn-primary" @click="encryptAndSendPaste($event)">Submit</button>
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
@ -1,24 +1,22 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>0bin - encrypted pastebin</title>
|
<title>0bin - encrypted pastebin</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="description"
|
<meta name="description" content="0bin is a client-side-encrypted
|
||||||
content="0bin is a client-side-encrypted
|
|
||||||
pastebin featuring burn after reading, history, and
|
pastebin featuring burn after reading, history, and
|
||||||
a clipboard">
|
a clipboard">
|
||||||
|
|
||||||
<link rel="shortcut icon" href="/favicon.ico">
|
<link rel="shortcut icon" href="/favicon.ico">
|
||||||
|
|
||||||
%if settings.COMPRESSED_STATIC_FILES:
|
%if settings.COMPRESSED_STATIC_FILES:
|
||||||
<link href="/static/css/style.min.css?{{ settings.VERSION }}"
|
<link href="/static/css/style.min.css?{{ settings.VERSION }}" rel="stylesheet" />
|
||||||
rel="stylesheet" />
|
|
||||||
%else:
|
%else:
|
||||||
<link href="/static/css/prettify.css" rel="stylesheet" />
|
<link href="/static/css/prettify.css" rel="stylesheet" />
|
||||||
<link href="/static/css/bootstrap.css" rel="stylesheet">
|
<link href="/static/css/bootstrap.css" rel="stylesheet">
|
||||||
<link href="/static/css/style.css?{{ settings.VERSION }}"
|
<link href="/static/css/style.css?{{ settings.VERSION }}" rel="stylesheet">
|
||||||
rel="stylesheet">
|
|
||||||
%end
|
%end
|
||||||
|
|
||||||
<!-- Le HTML5 shim, for IE7-8 support of HTML5 elements -->
|
<!-- Le HTML5 shim, for IE7-8 support of HTML5 elements -->
|
||||||
@ -26,27 +24,14 @@
|
|||||||
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
|
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
|
||||||
<![endif]-->
|
<![endif]-->
|
||||||
|
|
||||||
%if settings.COMPRESSED_STATIC_FILES:
|
|
||||||
<script src="/static/js/main.min.js?{{ settings.VERSION }}"></script>
|
|
||||||
%else:
|
|
||||||
<script src="/static/js/jquery-1.7.2.min.js"></script>
|
|
||||||
<script src="/static/js/sjcl.js"></script>
|
|
||||||
<script src="/static/js/behavior.js?{{ settings.VERSION }}"></script>
|
|
||||||
%end
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
zerobin.max_size = {{ settings.MAX_SIZE }};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div class="navbar navbar-fixed-top">
|
<div class="navbar navbar-fixed-top" id="menu-top">
|
||||||
<div class="navbar-inner">
|
<div class="navbar-inner">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<a class="btn btn-navbar" data-toggle="collapse"
|
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||||
data-target=".nav-collapse">
|
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
@ -56,16 +41,11 @@
|
|||||||
<ul class="nav">
|
<ul class="nav">
|
||||||
|
|
||||||
%for i, entry in enumerate(settings.MENU):
|
%for i, entry in enumerate(settings.MENU):
|
||||||
<li
|
<li>
|
||||||
%if not i:
|
|
||||||
class="active"
|
|
||||||
%end
|
|
||||||
>
|
|
||||||
%if "mailto:" in entry[1]:
|
%if "mailto:" in entry[1]:
|
||||||
<span title="{{ entry[1].replace('mailto:', '').replace('@', '__AT__') }}"
|
<a :href="formatEmail('{{ entry[1].replace('mailto:', '').replace('@', '__AT__') }}')" class="email-link">
|
||||||
class="email-link" >
|
|
||||||
{{ entry[0] }}
|
{{ entry[0] }}
|
||||||
</span>
|
</a>
|
||||||
%else:
|
%else:
|
||||||
<a href="{{ entry[1] }}">{{ entry[0] }}</a>
|
<a href="{{ entry[1] }}">{{ entry[0] }}</a>
|
||||||
%end
|
%end
|
||||||
@ -78,24 +58,30 @@
|
|||||||
"A client side encrypted PasteBin"<br>
|
"A client side encrypted PasteBin"<br>
|
||||||
<span>All pastes are AES256 encrypted, we cannot know what you paste...</span>
|
<span>All pastes are AES256 encrypted, we cannot know what you paste...</span>
|
||||||
</p>
|
</p>
|
||||||
</div><!--/.nav-collapse -->
|
</div>
|
||||||
|
<!--/.nav-collapse -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<noscript class="container noscript">
|
<noscript class="noscript">
|
||||||
<p>This pastebin uses client-side encryption. Therefore, it needs JavaScript enabled.</p>
|
|
||||||
<p>It seems like your browser doesn't have JavaScript enable.</p>
|
<div class="container jumbotron">
|
||||||
|
<h1 class="display-4">This site requires Javascript</h1>
|
||||||
|
<p class="lead">This pastebin uses client-side encryption, and therefore, it needs JavaScript to work.</p>
|
||||||
|
<p>It seems like your browser doesn't have JavaScript enabled.</p>
|
||||||
<p>Please enable JavaScript for this website or use a JavaScript-capable web browser.</p>
|
<p>Please enable JavaScript for this website or use a JavaScript-capable web browser.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
</noscript>
|
</noscript>
|
||||||
|
|
||||||
<div class="container" id="wrap-content">
|
<div class="container app" id="wrap-content" v-cloak>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="span2">
|
<div class="span2">
|
||||||
<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="item local-storage">
|
<li class="item local-storage" v-if="previousPastes.length === 0">
|
||||||
<em class="grey">
|
<em class="grey">
|
||||||
Your previous pastes will be saved in your browser using
|
Your previous pastes will be saved in your browser using
|
||||||
<a href="http://www.w3.org/TR/webstorage/">localStorage</a>.
|
<a href="http://www.w3.org/TR/webstorage/">localStorage</a>.
|
||||||
@ -108,22 +94,43 @@
|
|||||||
We cannot display your previous pastes.
|
We cannot display your previous pastes.
|
||||||
</em>
|
</em>
|
||||||
</li>
|
</li>
|
||||||
|
<li :class="{item: true, active: paste.isCurrent}" v-for="paste in previousPastes">
|
||||||
|
<a :href="paste.link" @click="forceLoadPaste(paste.link)">
|
||||||
|
{% paste.prefix %}{% paste.displayDate %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div><!--/.well -->
|
</div>
|
||||||
</div><!--/span-->
|
<!--/.well -->
|
||||||
|
</div>
|
||||||
|
<!--/span-->
|
||||||
|
|
||||||
<div id='main' class="span10">
|
<div id='main' class="span10">
|
||||||
|
|
||||||
|
|
||||||
|
<p :class="'alert alert-' + msg.type" v-for="msg in messages">
|
||||||
|
<a class="close" data-dismiss="alert" href="#" @click="$event.target.parentNode.remove()">×</a>
|
||||||
|
<strong class="title" v-if="msg.title" v-html="msg.title"></strong>
|
||||||
|
<span class="message" v-html="msg.content"></span>
|
||||||
|
<a v-if="msg.action.message" href="#"
|
||||||
|
@click.once.prevent="msg.action.callback($event)">{% msg.action.message %}</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
{{!base}}
|
{{!base}}
|
||||||
|
|
||||||
</div><!--/span-->
|
</div>
|
||||||
|
<!--/span-->
|
||||||
|
|
||||||
</div><!--/row-->
|
</div>
|
||||||
|
<!--/row-->
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<p>“Few persons can be made to believe that it is not quite an easy thing to invent a method of secret writing which shall baffle investigation. Yet it may be roundly asserted that human ingenuity cannot concoct a cipher which human ingenuity cannot resolve...”</p>
|
<p>“Few persons can be made to believe that it is not quite an easy thing to invent a method of secret writing
|
||||||
|
which shall baffle investigation. Yet it may be roundly asserted that human ingenuity cannot concoct a cipher
|
||||||
|
which human ingenuity cannot resolve...”</p>
|
||||||
<small>Edgar Allan Poe</small>
|
<small>Edgar Allan Poe</small>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
@ -136,7 +143,7 @@
|
|||||||
%end
|
%end
|
||||||
|
|
||||||
|
|
||||||
</br>
|
<br>
|
||||||
<p class="greetings span12">
|
<p class="greetings span12">
|
||||||
Based on an original idea from
|
Based on an original idea from
|
||||||
<a href="http://sebsauvage.net/paste/">sebsauvage.net</a><br>
|
<a href="http://sebsauvage.net/paste/">sebsauvage.net</a><br>
|
||||||
@ -144,22 +151,30 @@
|
|||||||
</p>
|
</p>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!--/wrap-content-->
|
||||||
|
|
||||||
|
<script src="/static/js/vue.js"></script>
|
||||||
|
%if settings.COMPRESSED_STATIC_FILES:
|
||||||
|
<script src="/static/js/main.min.js?{{ settings.VERSION }}"></script>
|
||||||
|
%else:
|
||||||
|
<script src="/static/js/sjcl.js"></script>
|
||||||
|
<script src="/static/js/behavior.js?{{ settings.VERSION }}"></script>
|
||||||
|
%end
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
zerobin.max_size = {{ settings.MAX_SIZE }};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
%if settings.COMPRESSED_STATIC_FILES:
|
%if settings.COMPRESSED_STATIC_FILES:
|
||||||
<script src="/static/js/additional.min.js?{{ settings.VERSION }}"></script>
|
<script src="/static/js/additional.min.js?{{ settings.VERSION }}"></script>
|
||||||
%else:
|
%else:
|
||||||
<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>
|
|
||||||
%end
|
%end
|
||||||
|
|
||||||
<p id="alert-template">
|
|
||||||
<a class="close" data-dismiss="alert" href="#">×</a>
|
|
||||||
<strong class="title"></strong>
|
|
||||||
<span class="message"></span>
|
|
||||||
</p>
|
|
||||||
</div><!--/wrap-content-->
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
@ -1,26 +1,37 @@
|
|||||||
<p class="file-upload">
|
<p class="file-upload" v-if="support.fileUpload">
|
||||||
<input type="button" class="btn btn-upload" value="Upload File">
|
<input type="button" class="btn btn-upload" value="Upload File" :value="isUploading ? 'Uploading...': 'Upload file'"
|
||||||
<input type="file" class="hide-upload" id="file-upload" >
|
:disabled="isUploading">
|
||||||
|
<input type="file" class="hide-upload" id="file-upload" @change="handleUpload($event.target.files)">
|
||||||
</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" v-model="newPaste.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" @click="encryptAndSendPaste($event)">Submit</button>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<div class="progress progress-striped active">
|
<div class="progress progress-striped active" v-show="isLoading">
|
||||||
<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" id="content" name="content" autofocus
|
||||||
class="input-xlarge"
|
v-on:keydown.ctrl.enter="encryptAndSendPaste($event)"></textarea>
|
||||||
id="content" name="content"></textarea>
|
</p>
|
||||||
|
|
||||||
|
<p class="paste-option down" v-if="displayBottomToolBar">
|
||||||
|
<label for="expiration">Expiration:</label>
|
||||||
|
<select id="expiration" name="expiration" v-model="newPaste.expiration">
|
||||||
|
<option value="burn_after_reading">Burn after reading</option>
|
||||||
|
<option selected value="1_day">1 day</option>
|
||||||
|
<option value="1_month">1 month</option>
|
||||||
|
<option value="never">Never</option>
|
||||||
|
</select>
|
||||||
|
<button type="submit" class="btn btn-primary" @click="encryptAndSendPaste($event)">Submit</button>
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
%if "burn_after_reading" in str(paste.expiration):
|
%if "burn_after_reading" in str(paste.expiration):
|
||||||
%if keep_alive:
|
%if keep_alive:
|
||||||
<p class="alert alert-info">
|
<p class="alert alert-info">
|
||||||
<a class="close" data-dismiss="alert" href="#">×</a>
|
<a class="close" data-dismiss="alert" href="#" @click="$event.target.parentNode.remove()">×</a>
|
||||||
<strong class="title">Ok!</strong>
|
<strong class="title">Ok!</strong>
|
||||||
<span class="message">
|
<span class="message">
|
||||||
This paste will be deleted the next time it is read.
|
This paste will be deleted the next time it is read.
|
||||||
@ -9,7 +9,7 @@
|
|||||||
</p>
|
</p>
|
||||||
%else:
|
%else:
|
||||||
<p class="alert">
|
<p class="alert">
|
||||||
<a class="close" data-dismiss="alert" href="#">×</a>
|
<a class="close" data-dismiss="alert" href="#" @click="$event.target.parentNode.remove()">×</a>
|
||||||
<strong class="title">Warning!</strong>
|
<strong class="title">Warning!</strong>
|
||||||
<span class="message">
|
<span class="message">
|
||||||
This paste has self-destructed. If you close this window,
|
This paste has self-destructed. If you close this window,
|
||||||
@ -22,17 +22,22 @@
|
|||||||
<div class="well paste-form">
|
<div class="well paste-form">
|
||||||
<form action="/" method="get" accept-charset="utf-8">
|
<form action="/" method="get" accept-charset="utf-8">
|
||||||
<p class="lnk-option">
|
<p class="lnk-option">
|
||||||
<a id="clip-button" href="#">Copy To Clipboard</a> |
|
<a id="clip-button" v-if="support.clipboard" href="#" @click.prevent="copyToClipboard()">Copy To Clipboard</a> |
|
||||||
<a id="short-url" href="#">Get short url</a> |
|
|
||||||
<a id="email-link" href="#">Email this</a>
|
<a id="email-link" href="#" @click="handleSendByEmail($event)">Email this</a>
|
||||||
|
|
||||||
<span class="paste-option btn-group top">
|
<span class="paste-option btn-group top">
|
||||||
<button class="btn btn-clone"><i class="icon-camera"></i> Clone</button>
|
<button class="btn btn-clone" @click.prevent="handleClone()"><i class="icon-camera"></i> Clone</button>
|
||||||
|
<button class="btn" v-if="downloadLink.url">
|
||||||
|
<a :href="downloadLink.url" :download="downloadLink.name"><i class="icon-download"></i> Download</a>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
|
||||||
<button class="btn">New Paste</button>
|
<button class="btn">New Paste</button>
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="progress progress-striped active">
|
<div class="progress progress-striped active" v-show="isLoading">
|
||||||
<div class="bar"></div>
|
<div class="bar"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -50,7 +55,12 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p class="paste-option btn-group bottom">
|
<p class="paste-option btn-group bottom">
|
||||||
<button class="btn btn-clone"><i class="icon-camera"></i> Clone</button>
|
<button class="btn btn-clone" @click.prevent="handleClone()"><i class="icon-camera"></i> Clone</button>
|
||||||
|
|
||||||
|
<button class="btn" v-if="downloadLink.url">
|
||||||
|
<a :href="downloadLink.url" :download="downloadLink.name"><i class="icon-download"></i> Download</a>
|
||||||
|
</button>
|
||||||
|
|
||||||
<button class="btn">New Paste</button>
|
<button class="btn">New Paste</button>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@ -62,26 +72,37 @@
|
|||||||
<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" v-model="newPaste.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" @click="encryptAndSendPaste($event)">Submit</button>
|
||||||
<button class="btn btn-danger">Cancel clone</button>
|
<button class="btn btn-danger" @click.prevent="handleCancelClone()">Cancel clone</button>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div class="progress progress-striped active">
|
<div class="progress progress-striped active" v-show="isLoading">
|
||||||
<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" id="content" name="content" autofocus
|
||||||
class="input-xlarge"
|
v-on:keydown.ctrl.enter="encryptAndSendPaste($event)"></textarea>
|
||||||
id="content" name="content"></textarea>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<p class="paste-option down" v-if="displayBottomToolBar">
|
||||||
|
<label for="expiration">Expiration:</label>
|
||||||
|
<select id="expiration" name="expiration" v-model="newPaste.expiration">
|
||||||
|
<option value="burn_after_reading">Burn after reading</option>
|
||||||
|
<option selected value="1_day">1 day</option>
|
||||||
|
<option value="1_month">1 month</option>
|
||||||
|
<option value="never">Never</option>
|
||||||
|
</select>
|
||||||
|
<button type="submit" class="btn btn-primary" @click="encryptAndSendPaste($event)">Submit</button>
|
||||||
|
</p>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
% rebase("base", settings=settings, pastes_count=pastes_count)
|
% rebase("base", settings=settings, pastes_count=pastes_count)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user