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
|
||||
to `moderate the pastebin content`_ as they have no way to decrypt it.
|
||||
|
||||
It's an Python implementation of the
|
||||
`zerobin project`_ under the `WTF licence`_. It's easy to
|
||||
install even if you know nothing about Python.
|
||||
It's an Python implementation of the `zerobin project`_, created by sebsauvage, under the `WTF licence`_.
|
||||
|
||||
For now tested with IE9, and the last opera, safari, chrome and FF.
|
||||
|
||||
@ -22,7 +20,7 @@ but in short::
|
||||
pip install zerobin
|
||||
zerobin
|
||||
|
||||
0bin runs on Python 2.7 and Python 3.4.
|
||||
0bin runs on Python 3.7.
|
||||
|
||||
How it works
|
||||
=============
|
||||
@ -74,7 +72,6 @@ Technologies used
|
||||
- Cherrypy_ (server only)
|
||||
- `node.js`_ (for optional command-line tool only)
|
||||
|
||||
|
||||
Known issues
|
||||
============
|
||||
|
||||
|
@ -31,6 +31,7 @@ def runserver(
|
||||
server="cherrypy",
|
||||
):
|
||||
|
||||
debug = True
|
||||
if version:
|
||||
print("0bin V%s" % settings.VERSION)
|
||||
sys.exit(0)
|
||||
|
@ -2,6 +2,7 @@
|
||||
# coding: utf-8
|
||||
|
||||
from __future__ import unicode_literals, absolute_import, print_function
|
||||
import pdb
|
||||
|
||||
"""
|
||||
Script including controller, rooting, and dependency management.
|
||||
@ -24,84 +25,90 @@ from datetime import datetime, timedelta
|
||||
|
||||
# add project dir and libs dir to the PYTHON PATH to ensure they are
|
||||
# importable
|
||||
from zerobin.utils import (settings, SettingsValidationError,
|
||||
drop_privileges, dmerge)
|
||||
from zerobin.utils import settings, SettingsValidationError, drop_privileges, dmerge
|
||||
|
||||
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
|
||||
|
||||
|
||||
app = Bottle()
|
||||
GLOBAL_CONTEXT = {
|
||||
'settings': settings,
|
||||
'pastes_count': Paste.get_pastes_count(),
|
||||
'refresh_counter': datetime.now()
|
||||
"settings": settings,
|
||||
"pastes_count": Paste.get_pastes_count(),
|
||||
"refresh_counter": datetime.now(),
|
||||
}
|
||||
|
||||
|
||||
@app.route('/')
|
||||
@view('home')
|
||||
@app.route("/")
|
||||
@view("home")
|
||||
def index():
|
||||
return GLOBAL_CONTEXT
|
||||
|
||||
|
||||
@app.route('/faq/')
|
||||
@view('faq')
|
||||
@app.route("/faq/")
|
||||
@view("faq")
|
||||
def faq():
|
||||
return GLOBAL_CONTEXT
|
||||
|
||||
|
||||
@app.route('/paste/create', method='POST')
|
||||
@app.route("/paste/create", method="POST")
|
||||
def create_paste():
|
||||
|
||||
try:
|
||||
body = urlparse.parse_qs(request.body.read(int(settings.MAX_SIZE * 1.1)))
|
||||
except ValueError:
|
||||
return {'status': 'error', 'message': "Wrong data payload."}
|
||||
return {"status": "error", "message": "Wrong data payload."}
|
||||
|
||||
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):
|
||||
return {'status': 'error',
|
||||
'message': "Encoding error: the paste couldn't be saved."}
|
||||
return {
|
||||
"status": "error",
|
||||
"message": "Encoding error: the paste couldn't be saved.",
|
||||
}
|
||||
|
||||
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
|
||||
# without saving paste. prevent from unusual use of the
|
||||
# system. need to be improved
|
||||
if 0 < len(content) < settings.MAX_SIZE:
|
||||
expiration = body.get(b'expiration', ['burn_after_reading'])[0]
|
||||
paste = Paste(expiration=expiration.decode('utf8'), content=content,
|
||||
uuid_length=settings.PASTE_ID_LENGTH)
|
||||
expiration = body.get(b"expiration", [b"burn_after_reading"])[0]
|
||||
paste = Paste(
|
||||
expiration=expiration.decode("utf8"),
|
||||
content=content,
|
||||
uuid_length=settings.PASTE_ID_LENGTH,
|
||||
)
|
||||
paste.save()
|
||||
|
||||
# display counter
|
||||
if settings.DISPLAY_COUNTER:
|
||||
|
||||
#increment paste counter
|
||||
# increment paste counter
|
||||
paste.increment_counter()
|
||||
|
||||
# if refresh time elapsed pick up new counter value
|
||||
now = datetime.now()
|
||||
timeout = (GLOBAL_CONTEXT['refresh_counter']
|
||||
+ timedelta(seconds=settings.REFRESH_COUNTER))
|
||||
timeout = GLOBAL_CONTEXT["refresh_counter"] + timedelta(
|
||||
seconds=settings.REFRESH_COUNTER
|
||||
)
|
||||
if timeout < now:
|
||||
GLOBAL_CONTEXT['pastes_count'] = Paste.get_pastes_count()
|
||||
GLOBAL_CONTEXT['refresh_counter'] = now
|
||||
GLOBAL_CONTEXT["pastes_count"] = Paste.get_pastes_count()
|
||||
GLOBAL_CONTEXT["refresh_counter"] = now
|
||||
|
||||
return {'status': 'ok', 'paste': paste.uuid}
|
||||
return {"status": "ok", "paste": paste.uuid}
|
||||
|
||||
return {'status': 'error',
|
||||
'message': "Serveur error: the paste couldn't be saved. "
|
||||
"Please try later."}
|
||||
return {
|
||||
"status": "error",
|
||||
"message": "Serveur error: the paste couldn't be saved. " "Please try later.",
|
||||
}
|
||||
|
||||
|
||||
@app.route('/paste/:paste_id')
|
||||
@view('paste')
|
||||
@app.route("/paste/:paste_id")
|
||||
@view("paste")
|
||||
def display_paste(paste_id):
|
||||
|
||||
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
|
||||
# to the paste that happens during the paste creation
|
||||
try:
|
||||
keep_alive = paste.expiration.split('#')[1]
|
||||
keep_alive = datetime.strptime(keep_alive,
|
||||
'%Y-%m-%d %H:%M:%S.%f')
|
||||
keep_alive = paste.expiration.split("#")[1]
|
||||
keep_alive = datetime.strptime(keep_alive, "%Y-%m-%d %H:%M:%S.%f")
|
||||
keep_alive = now < keep_alive + timedelta(seconds=10)
|
||||
except IndexError:
|
||||
keep_alive = False
|
||||
@ -131,35 +137,34 @@ def display_paste(paste_id):
|
||||
except (TypeError, ValueError):
|
||||
return error404(ValueError)
|
||||
|
||||
context = {'paste': paste, 'keep_alive': keep_alive}
|
||||
context = {"paste": paste, "keep_alive": keep_alive}
|
||||
return dmerge(context, GLOBAL_CONTEXT)
|
||||
|
||||
|
||||
@app.error(404)
|
||||
@view('404')
|
||||
@view("404")
|
||||
def error404(code):
|
||||
return GLOBAL_CONTEXT
|
||||
|
||||
|
||||
@app.route('/static/<filename:path>')
|
||||
@app.route("/static/<filename:path>")
|
||||
def server_static(filename):
|
||||
return static_file(filename, root=settings.STATIC_FILES_ROOT)
|
||||
|
||||
|
||||
def get_app(debug=None, settings_file='',
|
||||
compressed_static=None, settings=settings):
|
||||
def get_app(debug=None, settings_file="", compressed_static=None, settings=settings):
|
||||
"""
|
||||
Return a tuple (settings, app) configured using passed
|
||||
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:
|
||||
settings.update_with_file(os.path.realpath(settings_file))
|
||||
|
||||
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:
|
||||
settings.COMPRESSED_STATIC_FILES = compressed_static
|
||||
|
@ -1,223 +1,239 @@
|
||||
[v-cloak] {
|
||||
display: none
|
||||
}
|
||||
|
||||
.noscript {
|
||||
position: relative;
|
||||
top: 25%;
|
||||
border: 25px solid red;
|
||||
}
|
||||
|
||||
/* logo */
|
||||
|
||||
|
||||
.brand {
|
||||
font-size: 38px !important;
|
||||
padding: 0 55px 3px !important;
|
||||
font-size: 38px !important;
|
||||
padding: 0 55px 3px !important;
|
||||
|
||||
text-shadow: 0 1px 0 rgba(255, 255, 255, .1), 0 0 30px rgba(255, 255, 255, .125);
|
||||
-webkit-transition: all .2s linear;
|
||||
-moz-transition: all .2s linear;
|
||||
-o-transition: all .2s linear;
|
||||
-ms-transition: all .2s linear;
|
||||
transition: all .2s linear;
|
||||
text-shadow: 0 1px 0 rgba(255, 255, 255, .1), 0 0 30px rgba(255, 255, 255, .125);
|
||||
-webkit-transition: all .2s linear;
|
||||
-moz-transition: all .2s linear;
|
||||
-o-transition: all .2s linear;
|
||||
-ms-transition: all .2s linear;
|
||||
transition: all .2s linear;
|
||||
}
|
||||
|
||||
.brand span {
|
||||
font-size: 48px;
|
||||
line-height: 0;
|
||||
font-size: 48px;
|
||||
line-height: 0;
|
||||
}
|
||||
|
||||
.brand em {
|
||||
display: inline;
|
||||
color: #D40202;
|
||||
font-size: 27px;
|
||||
display: inline;
|
||||
color: #D40202;
|
||||
font-size: 27px;
|
||||
}
|
||||
|
||||
.about {
|
||||
line-height: 13px;
|
||||
font-style: italic;
|
||||
text-align: right;
|
||||
padding-top: 9px;
|
||||
margin-bottom: 0 !important;
|
||||
line-height: 13px;
|
||||
font-style: italic;
|
||||
text-align: right;
|
||||
padding-top: 9px;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.about span{
|
||||
font-size: 10px;
|
||||
.about span {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
/* body & other stuff */
|
||||
|
||||
body {
|
||||
padding-top: 60px;
|
||||
padding-bottom: 40px;
|
||||
padding-top: 60px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
|
||||
.sidebar-nav {
|
||||
padding: 9px 0;
|
||||
padding: 9px 0;
|
||||
}
|
||||
|
||||
select {
|
||||
width: 135px;
|
||||
width: 135px;
|
||||
}
|
||||
|
||||
label {
|
||||
display: inline;
|
||||
margin-left: 18px;
|
||||
font-style: italic;
|
||||
font-size: 11px;
|
||||
color: #888;
|
||||
display: inline;
|
||||
margin-left: 18px;
|
||||
font-style: italic;
|
||||
font-size: 11px;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
ul, ol {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
ul,
|
||||
ol {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-left: -9px;
|
||||
margin-left: -9px;
|
||||
}
|
||||
|
||||
|
||||
p {
|
||||
margin: 0 0 20px;
|
||||
margin: 0 0 20px;
|
||||
}
|
||||
|
||||
.grey {
|
||||
color: #999;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.nav-list {
|
||||
padding-right: 0px !important;
|
||||
font-size: 12px;
|
||||
padding-right: 0px !important;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
width: 630px;
|
||||
float: left;
|
||||
width: 630px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
h4 p {
|
||||
float: left;
|
||||
font-size: 80px;
|
||||
text-shadow: 1px 3px 1px #DDD, 0 0 4px #333;
|
||||
-webkit-transition: all 0.2s linear;
|
||||
-o-transition: all .2s linear;
|
||||
-ms-transition: all .2s linear;
|
||||
-moz-transition: all .2s linear;
|
||||
transition: all .2s linear;
|
||||
margin-right: 7px;
|
||||
margin-top: 3px;
|
||||
float: left;
|
||||
font-size: 80px;
|
||||
text-shadow: 1px 3px 1px #DDD, 0 0 4px #333;
|
||||
-webkit-transition: all 0.2s linear;
|
||||
-o-transition: all .2s linear;
|
||||
-ms-transition: all .2s linear;
|
||||
-moz-transition: all .2s linear;
|
||||
transition: all .2s linear;
|
||||
margin-right: 7px;
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
h4#pixels-total {
|
||||
position: relative;
|
||||
width: 166px;
|
||||
float: right;
|
||||
margin: 8px 0 0 0;
|
||||
padding: 0 0 0 54px;
|
||||
font-size: 1.1em;
|
||||
line-height: 1.4;
|
||||
font-weight: normal;
|
||||
color: #777;
|
||||
-webkit-border-top-right-radius: 6px;
|
||||
-webkit-border-top-left-radius: 20px;
|
||||
-moz-border-top-right-radius: 6px;
|
||||
-moz-border-top-left-radius: 20px;
|
||||
border-top-right-radius: 6px;
|
||||
border-top-left-radius: 20px;
|
||||
position: relative;
|
||||
width: 166px;
|
||||
float: right;
|
||||
margin: 8px 0 0 0;
|
||||
padding: 0 0 0 54px;
|
||||
font-size: 1.1em;
|
||||
line-height: 1.4;
|
||||
font-weight: normal;
|
||||
color: #777;
|
||||
-webkit-border-top-right-radius: 6px;
|
||||
-webkit-border-top-left-radius: 20px;
|
||||
-moz-border-top-right-radius: 6px;
|
||||
-moz-border-top-left-radius: 20px;
|
||||
border-top-right-radius: 6px;
|
||||
border-top-left-radius: 20px;
|
||||
}
|
||||
|
||||
.greetings {
|
||||
clear: both;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
margin-top: 40px;
|
||||
clear: both;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.alert .title {
|
||||
display:block;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Home */
|
||||
|
||||
.btn-group {
|
||||
float:left;
|
||||
float: left;
|
||||
}
|
||||
|
||||
html.file-upload p.file-upload {
|
||||
float: left;
|
||||
margin: 22px 0px 0px 21px;
|
||||
display: none;
|
||||
float: left;
|
||||
margin: 22px 0px 0px 21px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
html.file-upload p.file-upload {
|
||||
display:inherit;
|
||||
display: inherit;
|
||||
}
|
||||
|
||||
html.no-file-upload p.file-upload {
|
||||
display:none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
input.btn-upload {
|
||||
position: relative;
|
||||
left: -6px;
|
||||
width: 100px;
|
||||
z-index: 1;
|
||||
margin-top: -13px;
|
||||
position: relative;
|
||||
left: -6px;
|
||||
width: 100px;
|
||||
z-index: 1;
|
||||
margin-top: -13px;
|
||||
}
|
||||
|
||||
input.hide-upload {
|
||||
position: relative;
|
||||
left: -110px;
|
||||
-moz-opacity: 0;
|
||||
filter: alpha(opacity=0);
|
||||
opacity: 0 ;
|
||||
z-index: 2;
|
||||
width: 100px;
|
||||
margin-top: -20px;
|
||||
cursor: pointer;
|
||||
cursor: hand;
|
||||
height: 49px;
|
||||
position: relative;
|
||||
left: -110px;
|
||||
-moz-opacity: 0;
|
||||
filter: alpha(opacity=0);
|
||||
opacity: 0;
|
||||
z-index: 2;
|
||||
width: 100px;
|
||||
margin-top: -20px;
|
||||
cursor: pointer;
|
||||
cursor: hand;
|
||||
height: 49px;
|
||||
}
|
||||
|
||||
|
||||
/* Paste Page */
|
||||
|
||||
#paste-content {
|
||||
background-color: white;
|
||||
padding:1em;
|
||||
background-color: white;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
|
||||
#paste-content.linenums {
|
||||
padding-left:0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.submit-form {
|
||||
display:none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.paste-option {
|
||||
float:right;
|
||||
float: right;
|
||||
}
|
||||
|
||||
a#clip-button.hover{
|
||||
cursor:pointer;
|
||||
text-decoration:underline;
|
||||
a#clip-button.hover {
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
li.L0, li.L1, li.L2, li.L3, li.L4,
|
||||
li.L5, li.L6, li.L7, li.L8, li.L9
|
||||
{
|
||||
list-style-type: decimal;
|
||||
background: inherit;
|
||||
li.L0,
|
||||
li.L1,
|
||||
li.L2,
|
||||
li.L3,
|
||||
li.L4,
|
||||
li.L5,
|
||||
li.L6,
|
||||
li.L7,
|
||||
li.L8,
|
||||
li.L9 {
|
||||
list-style-type: decimal;
|
||||
background: inherit;
|
||||
}
|
||||
|
||||
.prettyprint.linenums {
|
||||
-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;
|
||||
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;
|
||||
}
|
||||
|
||||
/* Specify class=linenums on a pre to get line numbering */
|
||||
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 {
|
||||
color: #bebec5;
|
||||
line-height: 18px;
|
||||
@ -231,160 +247,154 @@ ol.linenums li {
|
||||
}
|
||||
|
||||
pre {
|
||||
font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, monospace, serif;
|
||||
line-height: 21px;
|
||||
font-size: 12px;
|
||||
font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, monospace, serif;
|
||||
line-height: 21px;
|
||||
font-size: 12px;
|
||||
|
||||
}
|
||||
|
||||
.kwd {
|
||||
color: #66F;
|
||||
color: #66F;
|
||||
}
|
||||
|
||||
.pun, .opn, .clo {
|
||||
color: #0A0;
|
||||
.pun,
|
||||
.opn,
|
||||
.clo {
|
||||
color: #0A0;
|
||||
}
|
||||
|
||||
.lit {
|
||||
color: #933;
|
||||
color: #933;
|
||||
}
|
||||
|
||||
.com {
|
||||
color: #C0C;
|
||||
color: #C0C;
|
||||
}
|
||||
|
||||
|
||||
/* Common css */
|
||||
|
||||
form {
|
||||
padding-bottom:3em !important;
|
||||
padding-right: 17px;
|
||||
padding-bottom: 3em !important;
|
||||
padding-right: 17px;
|
||||
}
|
||||
|
||||
form textarea {
|
||||
overflow-y:auto;
|
||||
min-height:250px;
|
||||
overflow-y: auto;
|
||||
min-height: 250px;
|
||||
}
|
||||
|
||||
button.btn, input[type="submit"].btn {
|
||||
margin-left: 5px;
|
||||
button.btn,
|
||||
input[type="submit"].btn {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.well {
|
||||
padding-bottom: 40px;
|
||||
padding-right: 17px;
|
||||
padding-bottom: 40px;
|
||||
padding-right: 17px;
|
||||
}
|
||||
|
||||
.legal {
|
||||
margin: 0 auto;
|
||||
width: 300px;
|
||||
text-align: center;
|
||||
margin-top: 30px;
|
||||
margin: 0 auto;
|
||||
width: 300px;
|
||||
text-align: center;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
margin-left: 5px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.btn-primary, .btn-danger {
|
||||
position:relative;
|
||||
top:-4px;
|
||||
}
|
||||
|
||||
#alert-template {
|
||||
display: none;
|
||||
.btn-primary,
|
||||
.btn-danger {
|
||||
position: relative;
|
||||
top: -4px;
|
||||
}
|
||||
|
||||
/** Progress bar */
|
||||
|
||||
.progress {
|
||||
display:none;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.progress .bar {
|
||||
width: 25%;
|
||||
text-indent: 10px;
|
||||
text-align:left;
|
||||
width: 25%;
|
||||
text-indent: 10px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.lnk-option canvas {
|
||||
vertical-align:middle;
|
||||
margin-right:10px;
|
||||
vertical-align: middle;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
|
||||
/* Previous paste list */
|
||||
|
||||
.previous-pastes .item {
|
||||
margin-top:5px;
|
||||
vertical-align:middle;
|
||||
line-height:24px;
|
||||
padding-left:1em;
|
||||
margin-top: 5px;
|
||||
vertical-align: middle;
|
||||
line-height: 24px;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
li.item {
|
||||
margin-left: -13px;
|
||||
margin-right: -5px;
|
||||
margin-left: -13px;
|
||||
margin-right: -5px;
|
||||
}
|
||||
|
||||
.previous-pastes canvas {
|
||||
display:block;
|
||||
float:left;
|
||||
margin-right:5px;
|
||||
display: block;
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
html.local-storage .no-local-storage {
|
||||
display:none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
html.no-local-storage .local-storage {
|
||||
display:none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
canvas {
|
||||
border: 1px solid white;
|
||||
}
|
||||
|
||||
#wrap-content {
|
||||
display: none;
|
||||
border: 1px solid white;
|
||||
}
|
||||
|
||||
.noscript {
|
||||
text-align: center;
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#faq dt {
|
||||
margin:2em 0 1em 0;
|
||||
margin: 2em 0 1em 0;
|
||||
}
|
||||
|
||||
#faq p {
|
||||
margin:1em;
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
#force-coloration {
|
||||
text-decoration:underline;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#expiration-tag {
|
||||
float:right;
|
||||
margin:1em;
|
||||
background:grey;
|
||||
color:white;
|
||||
font-size:0.8em;
|
||||
padding:0 1ex;
|
||||
opacity: 0.5;
|
||||
filter: alpha(opacity=50);
|
||||
font-weight:bold;
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
-moz-background-clip: padding;
|
||||
-webkit-background-clip: padding-box;
|
||||
background-clip: padding-box;
|
||||
float: right;
|
||||
margin: 1em;
|
||||
background: grey;
|
||||
color: white;
|
||||
font-size: 0.8em;
|
||||
padding: 0 1ex;
|
||||
opacity: 0.5;
|
||||
filter: alpha(opacity=50);
|
||||
font-weight: bold;
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
-moz-background-clip: padding;
|
||||
-webkit-background-clip: padding-box;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
#content.hover {
|
||||
background-color: #eee;
|
||||
}
|
||||
background-color: #eee;
|
||||
}
|
||||
|
@ -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>
|
||||
|
||||
<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>
|
||||
<span class="message">
|
||||
Either this paste has expired or this page never existed.
|
||||
@ -11,30 +11,40 @@
|
||||
</p>
|
||||
|
||||
<p class="file-upload">
|
||||
<input type="button" class="btn btn-upload" value="Upload File">
|
||||
<input type="file" class="hide-upload" id="file-upload" >
|
||||
<input type="button" class="btn btn-upload" :value="isUploading ? 'Uploading...': 'Upload file'"
|
||||
:disabled="isUploading">
|
||||
<input type="file" class="hide-upload" id="file-upload" @change="handleUpload($event.target.files)">
|
||||
</p>
|
||||
|
||||
<form class="well" method="post" action="/paste/create">
|
||||
<p class="paste-option">
|
||||
<label for="expiration" >Expiration:</label>
|
||||
<select id="expiration" name="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">Submit</button>
|
||||
</p>
|
||||
<p>
|
||||
<div class="progress progress-striped active">
|
||||
<p class="paste-option">
|
||||
<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>
|
||||
<div class="progress progress-striped active" v-show="isLoading">
|
||||
<div class="bar"></div>
|
||||
</div>
|
||||
<textarea rows="10" style="width:100%;"
|
||||
class="input-xlarge"
|
||||
id="content" name="content"></textarea>
|
||||
</p>
|
||||
<textarea rows="10" style="width:100%;" class="input-xlarge" id="content" name="content" autofocus
|
||||
v-on:keydown.ctrl.enter="encryptAndSendPaste($event)"></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>
|
||||
</form>
|
||||
|
||||
|
||||
% rebase('base', settings=settings, pastes_count=pastes_count)
|
||||
% rebase('base', settings=settings, pastes_count=pastes_count)
|
||||
|
@ -1,165 +1,180 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>0bin - encrypted pastebin</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description"
|
||||
content="0bin is a client-side-encrypted
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>0bin - encrypted pastebin</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="0bin is a client-side-encrypted
|
||||
pastebin featuring burn after reading, history, and
|
||||
a clipboard">
|
||||
|
||||
<link rel="shortcut icon" href="/favicon.ico">
|
||||
<link rel="shortcut icon" href="/favicon.ico">
|
||||
|
||||
%if settings.COMPRESSED_STATIC_FILES:
|
||||
<link href="/static/css/style.min.css?{{ settings.VERSION }}"
|
||||
rel="stylesheet" />
|
||||
%else:
|
||||
<link href="/static/css/prettify.css" rel="stylesheet" />
|
||||
<link href="/static/css/bootstrap.css" rel="stylesheet">
|
||||
<link href="/static/css/style.css?{{ settings.VERSION }}"
|
||||
rel="stylesheet">
|
||||
%end
|
||||
%if settings.COMPRESSED_STATIC_FILES:
|
||||
<link href="/static/css/style.min.css?{{ settings.VERSION }}" rel="stylesheet" />
|
||||
%else:
|
||||
<link href="/static/css/prettify.css" rel="stylesheet" />
|
||||
<link href="/static/css/bootstrap.css" rel="stylesheet">
|
||||
<link href="/static/css/style.css?{{ settings.VERSION }}" rel="stylesheet">
|
||||
%end
|
||||
|
||||
<!-- Le HTML5 shim, for IE7-8 support of HTML5 elements -->
|
||||
<!--[if lt IE 9]>
|
||||
<!-- Le HTML5 shim, for IE7-8 support of HTML5 elements -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![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
|
||||
</head>
|
||||
|
||||
<script type="text/javascript">
|
||||
zerobin.max_size = {{ settings.MAX_SIZE }};
|
||||
</script>
|
||||
<body>
|
||||
|
||||
</head>
|
||||
<div class="navbar navbar-fixed-top" id="menu-top">
|
||||
<div class="navbar-inner">
|
||||
<div class="container">
|
||||
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</a>
|
||||
<a class="brand" href="/"><span>ø</span>bin<em>.net</em></a>
|
||||
<div class="nav-collapse">
|
||||
<ul class="nav">
|
||||
|
||||
<body>
|
||||
|
||||
<div class="navbar navbar-fixed-top">
|
||||
<div class="navbar-inner">
|
||||
<div class="container">
|
||||
<a class="btn btn-navbar" data-toggle="collapse"
|
||||
data-target=".nav-collapse">
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</a>
|
||||
<a class="brand" href="/"><span>ø</span>bin<em>.net</em></a>
|
||||
<div class="nav-collapse">
|
||||
<ul class="nav">
|
||||
|
||||
%for i, entry in enumerate(settings.MENU):
|
||||
<li
|
||||
%if not i:
|
||||
class="active"
|
||||
%end
|
||||
>
|
||||
%if "mailto:" in entry[1]:
|
||||
<span title="{{ entry[1].replace('mailto:', '').replace('@', '__AT__') }}"
|
||||
class="email-link" >
|
||||
{{ entry[0] }}
|
||||
</span>
|
||||
%else:
|
||||
<a href="{{ entry[1] }}">{{ entry[0] }}</a>
|
||||
%end
|
||||
|
||||
</li>
|
||||
%for i, entry in enumerate(settings.MENU):
|
||||
<li>
|
||||
%if "mailto:" in entry[1]:
|
||||
<a :href="formatEmail('{{ entry[1].replace('mailto:', '').replace('@', '__AT__') }}')" class="email-link">
|
||||
{{ entry[0] }}
|
||||
</a>
|
||||
%else:
|
||||
<a href="{{ entry[1] }}">{{ entry[0] }}</a>
|
||||
%end
|
||||
|
||||
</ul>
|
||||
<p class="about pull-right">
|
||||
"A client side encrypted PasteBin"<br>
|
||||
<span>All pastes are AES256 encrypted, we cannot know what you paste...</span>
|
||||
</p>
|
||||
</div><!--/.nav-collapse -->
|
||||
</li>
|
||||
%end
|
||||
|
||||
</ul>
|
||||
<p class="about pull-right">
|
||||
"A client side encrypted PasteBin"<br>
|
||||
<span>All pastes are AES256 encrypted, we cannot know what you paste...</span>
|
||||
</p>
|
||||
</div>
|
||||
<!--/.nav-collapse -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<noscript class="container 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>
|
||||
<p>Please enable JavaScript for this website or use a JavaScript-capable web browser.</p>
|
||||
</noscript>
|
||||
<noscript class="noscript">
|
||||
|
||||
<div class="container" id="wrap-content">
|
||||
<div class="row">
|
||||
<div class="span2">
|
||||
<div class="well sidebar-nav">
|
||||
<ul class="nav nav-list previous-pastes">
|
||||
<li class="nav-header">Previous pastes</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>
|
||||
</div><!--/.well -->
|
||||
</div><!--/span-->
|
||||
<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>
|
||||
</div>
|
||||
|
||||
<div id='main' class="span10">
|
||||
{{!base}}
|
||||
</noscript>
|
||||
|
||||
</div><!--/span-->
|
||||
<div class="container app" id="wrap-content" v-cloak>
|
||||
<div class="row">
|
||||
<div class="span2">
|
||||
<div class="well sidebar-nav">
|
||||
<ul class="nav nav-list previous-pastes">
|
||||
<li class="nav-header">Previous pastes</li>
|
||||
<li class="item local-storage" v-if="previousPastes.length === 0">
|
||||
<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>
|
||||
<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>
|
||||
</div>
|
||||
<!--/.well -->
|
||||
</div>
|
||||
<!--/span-->
|
||||
|
||||
</div><!--/row-->
|
||||
<div id='main' class="span10">
|
||||
|
||||
<hr>
|
||||
|
||||
<footer>
|
||||
<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 :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}}
|
||||
|
||||
</div>
|
||||
<!--/span-->
|
||||
|
||||
</div>
|
||||
<!--/row-->
|
||||
|
||||
<hr>
|
||||
|
||||
<footer>
|
||||
<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>
|
||||
<small>Edgar Allan Poe</small>
|
||||
</blockquote>
|
||||
|
||||
|
||||
%if settings.DISPLAY_COUNTER:
|
||||
<h4 id="pixels-total" >
|
||||
<p>ø</p>
|
||||
<strong>{{ pastes_count }}</strong> <br/>pastes øbinned
|
||||
</h4>
|
||||
<h4 id="pixels-total">
|
||||
<p>ø</p>
|
||||
<strong>{{ pastes_count }}</strong> <br />pastes øbinned
|
||||
</h4>
|
||||
%end
|
||||
|
||||
|
||||
</br>
|
||||
<p class="greetings span12">
|
||||
Based on an original idea from
|
||||
<a href="http://sebsauvage.net/paste/">sebsauvage.net</a><br>
|
||||
<a href="http://sametmax.com">Sam & Max</a>
|
||||
</p>
|
||||
</footer>
|
||||
<br>
|
||||
<p class="greetings span12">
|
||||
Based on an original idea from
|
||||
<a href="http://sebsauvage.net/paste/">sebsauvage.net</a><br>
|
||||
<a href="http://sametmax.com">Sam & Max</a>
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
%if settings.COMPRESSED_STATIC_FILES:
|
||||
<script src="/static/js/additional.min.js?{{ settings.VERSION }}"></script>
|
||||
%else:
|
||||
<script src="/static/js/jquery.elastic.source.js"></script>
|
||||
<script src="/static/js/lzw.js"></script>
|
||||
<script src="/static/js/prettify.min.js"></script>
|
||||
<script src="/static/js/ZeroClipboard.js"></script>
|
||||
%end
|
||||
</div>
|
||||
<!--/wrap-content-->
|
||||
|
||||
<p id="alert-template">
|
||||
<a class="close" data-dismiss="alert" href="#">×</a>
|
||||
<strong class="title"></strong>
|
||||
<span class="message"></span>
|
||||
</p>
|
||||
</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
|
||||
|
||||
</body>
|
||||
<script type="text/javascript">
|
||||
zerobin.max_size = {{ settings.MAX_SIZE }};
|
||||
|
||||
</script>
|
||||
|
||||
%if settings.COMPRESSED_STATIC_FILES:
|
||||
<script src="/static/js/additional.min.js?{{ settings.VERSION }}"></script>
|
||||
%else:
|
||||
|
||||
<script src="/static/js/lzw.js"></script>
|
||||
<script src="/static/js/prettify.min.js"></script>
|
||||
%end
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
@ -1,26 +1,37 @@
|
||||
<p class="file-upload">
|
||||
<input type="button" class="btn btn-upload" value="Upload File">
|
||||
<input type="file" class="hide-upload" id="file-upload" >
|
||||
<p class="file-upload" v-if="support.fileUpload">
|
||||
<input type="button" class="btn btn-upload" value="Upload File" :value="isUploading ? 'Uploading...': 'Upload file'"
|
||||
:disabled="isUploading">
|
||||
<input type="file" class="hide-upload" id="file-upload" @change="handleUpload($event.target.files)">
|
||||
</p>
|
||||
|
||||
<form class="well" method="post" action="/paste/create">
|
||||
<p class="paste-option">
|
||||
<label for="expiration" >Expiration:</label>
|
||||
<select id="expiration" name="expiration">
|
||||
<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">Submit</button>
|
||||
<button type="submit" class="btn btn-primary" @click="encryptAndSendPaste($event)">Submit</button>
|
||||
</p>
|
||||
<p>
|
||||
<div class="progress progress-striped active">
|
||||
<div class="bar"></div>
|
||||
</div>
|
||||
<textarea rows="10" style="width:100%;"
|
||||
class="input-xlarge"
|
||||
id="content" name="content"></textarea>
|
||||
<div class="progress progress-striped active" v-show="isLoading">
|
||||
<div class="bar"></div>
|
||||
</div>
|
||||
<textarea rows="10" style="width:100%" class="input-xlarge" id="content" name="content" autofocus
|
||||
v-on:keydown.ctrl.enter="encryptAndSendPaste($event)"></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>
|
||||
</form>
|
||||
|
||||
|
@ -1,87 +1,108 @@
|
||||
%if "burn_after_reading" in str(paste.expiration):
|
||||
%if keep_alive:
|
||||
<p class="alert alert-info">
|
||||
<a class="close" data-dismiss="alert" href="#">×</a>
|
||||
<strong class="title">Ok!</strong>
|
||||
<span class="message">
|
||||
This paste will be deleted the next time it is read.
|
||||
</span>
|
||||
</p>
|
||||
%else:
|
||||
<p class="alert">
|
||||
<a class="close" data-dismiss="alert" href="#">×</a>
|
||||
<strong class="title">Warning!</strong>
|
||||
<span class="message">
|
||||
This paste has self-destructed. If you close this window,
|
||||
there is no way to recover it.
|
||||
</span>
|
||||
</p>
|
||||
%end
|
||||
%if keep_alive:
|
||||
<p class="alert alert-info">
|
||||
<a class="close" data-dismiss="alert" href="#" @click="$event.target.parentNode.remove()">×</a>
|
||||
<strong class="title">Ok!</strong>
|
||||
<span class="message">
|
||||
This paste will be deleted the next time it is read.
|
||||
</span>
|
||||
</p>
|
||||
%else:
|
||||
<p class="alert">
|
||||
<a class="close" data-dismiss="alert" href="#" @click="$event.target.parentNode.remove()">×</a>
|
||||
<strong class="title">Warning!</strong>
|
||||
<span class="message">
|
||||
This paste has self-destructed. If you close this window,
|
||||
there is no way to recover it.
|
||||
</span>
|
||||
</p>
|
||||
%end
|
||||
%end
|
||||
|
||||
<div class="well paste-form">
|
||||
<form action="/" method="get" accept-charset="utf-8">
|
||||
<p class="lnk-option">
|
||||
<a id="clip-button" href="#">Copy To Clipboard</a> |
|
||||
<a id="short-url" href="#">Get short url</a> |
|
||||
<a id="email-link" href="#">Email this</a>
|
||||
<form action="/" method="get" accept-charset="utf-8">
|
||||
<p class="lnk-option">
|
||||
<a id="clip-button" v-if="support.clipboard" href="#" @click.prevent="copyToClipboard()">Copy To Clipboard</a> |
|
||||
|
||||
<span class="paste-option btn-group top">
|
||||
<button class="btn btn-clone"><i class="icon-camera"></i> Clone</button>
|
||||
<button class="btn">New Paste</button>
|
||||
</span>
|
||||
</p>
|
||||
<a id="email-link" href="#" @click="handleSendByEmail($event)">Email this</a>
|
||||
|
||||
<div class="progress progress-striped active">
|
||||
<div class="bar"></div>
|
||||
</div>
|
||||
<span class="paste-option btn-group top">
|
||||
<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>
|
||||
|
||||
%expiration = paste.humanized_expiration
|
||||
%if expiration:
|
||||
<p id="expiration-tag">Expire {{ expiration }}</p>
|
||||
%end
|
||||
|
||||
<p>
|
||||
<pre id="paste-content" class="prettyprint">
|
||||
<button class="btn">New Paste</button>
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<div class="progress progress-striped active" v-show="isLoading">
|
||||
<div class="bar"></div>
|
||||
</div>
|
||||
|
||||
%expiration = paste.humanized_expiration
|
||||
%if expiration:
|
||||
<p id="expiration-tag">Expire {{ expiration }}</p>
|
||||
%end
|
||||
|
||||
<p>
|
||||
<pre id="paste-content" class="prettyprint">
|
||||
<code>
|
||||
{{ paste.content }}
|
||||
</code>
|
||||
</pre>
|
||||
</p>
|
||||
</p>
|
||||
|
||||
<p class="paste-option btn-group bottom">
|
||||
<button class="btn btn-clone"><i class="icon-camera"></i> Clone</button>
|
||||
<button class="btn">New Paste</button>
|
||||
</p>
|
||||
<p class="paste-option btn-group bottom">
|
||||
<button class="btn btn-clone" @click.prevent="handleClone()"><i class="icon-camera"></i> Clone</button>
|
||||
|
||||
</form>
|
||||
<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>
|
||||
</p>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- For cloning -->
|
||||
<div class="submit-form clone">
|
||||
<form class="well" method="post" action="/paste/create">
|
||||
<p class="paste-option">
|
||||
<label for="expiration" >Expiration:</label>
|
||||
<select id="expiration" name="expiration">
|
||||
<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">Submit</button>
|
||||
<button class="btn btn-danger">Cancel clone</button>
|
||||
<button type="submit" class="btn btn-primary" @click="encryptAndSendPaste($event)">Submit</button>
|
||||
<button class="btn btn-danger" @click.prevent="handleCancelClone()">Cancel clone</button>
|
||||
</p>
|
||||
|
||||
<div>
|
||||
<div class="progress progress-striped active">
|
||||
<div class="bar"></div>
|
||||
</div>
|
||||
<textarea rows="10" style="width:100%;"
|
||||
class="input-xlarge"
|
||||
id="content" name="content"></textarea>
|
||||
<div class="progress progress-striped active" v-show="isLoading">
|
||||
<div class="bar"></div>
|
||||
</div>
|
||||
<textarea rows="10" style="width:100%;" class="input-xlarge" id="content" name="content" autofocus
|
||||
v-on:keydown.ctrl.enter="encryptAndSendPaste($event)"></textarea>
|
||||
</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>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
% rebase("base", settings=settings, pastes_count=pastes_count)
|
||||
|
Loading…
Reference in New Issue
Block a user