Compare commits
36 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
c65d5c4d09 | ||
|
3b3cae831a | ||
|
3e0c4da193 | ||
|
ab10db69b4 | ||
|
ff6fc227eb | ||
|
dff881ee90 | ||
|
8ce3793ff6 | ||
|
b873215dd8 | ||
|
788cf0118d | ||
|
5dcb0d407e | ||
|
4ab4bffc0f | ||
|
75d272d430 | ||
|
2725cd10b4 | ||
|
b83f284b98 | ||
|
90672f7b39 | ||
|
536fa12975 | ||
|
b86bc2c0ce | ||
|
73ce7c4e14 | ||
|
a29a7cb961 | ||
|
a9b2f53e65 | ||
|
6c64f28643 | ||
|
5b515f4c35 | ||
|
9558751f5a | ||
|
aa064a5724 | ||
|
ed12243d67 | ||
|
7364cd2020 | ||
|
183150a6b0 | ||
|
0b1fad5a2b | ||
|
fab8f31064 | ||
|
eb5ecdb04e | ||
|
cf3a05ab53 | ||
|
2bba894d67 | ||
|
ea3ee454b6 | ||
|
b54574d5ca | ||
|
ff00c972b1 | ||
|
d753f92207 |
31
.gitignore
vendored
|
@ -7,34 +7,41 @@
|
|||
*_index
|
||||
*.orig
|
||||
*.swp
|
||||
.* # all hidden files...
|
||||
!.gitignore # ...except gitignore
|
||||
*.old
|
||||
|
||||
|
||||
# binaries
|
||||
|
||||
*.pyc
|
||||
*.pyo
|
||||
*.pyz
|
||||
*.zip
|
||||
__pycache__
|
||||
.mypy*
|
||||
*.db
|
||||
|
||||
/tools/zerobinpaste.js
|
||||
/tools/zerobinpaste.min
|
||||
/tools/zerobinpaste
|
||||
|
||||
# files generated by setuptools
|
||||
# build and env
|
||||
|
||||
build
|
||||
0bin
|
||||
env
|
||||
venv
|
||||
*.egg-info
|
||||
dist
|
||||
*.tar.gz
|
||||
*.egg
|
||||
*.in
|
||||
|
||||
# others
|
||||
|
||||
content
|
||||
# IDE
|
||||
|
||||
*.sublime-project
|
||||
*.sublime-workspace
|
||||
settings_local.py
|
||||
build
|
||||
*-workspace
|
||||
*_old*
|
||||
.vscode
|
||||
var
|
||||
|
||||
# JS
|
||||
|
||||
package-lock.json
|
||||
node_modules
|
||||
|
|
18
README.rst
|
@ -1,7 +1,7 @@
|
|||
0bin: a client side encrypted pastebin
|
||||
===========================================
|
||||
|
||||
0bin is a pastebin that encrypts the user content in the browsder and can run without a database.
|
||||
0bin is a pastebin that encrypts the user content in the browser and can run without a database.
|
||||
|
||||
* Try it: `0bin.net <http://0bin.net>`_
|
||||
* `Report a bug <https://github.com/sametmax/0bin/issues>`_
|
||||
|
@ -12,15 +12,18 @@ to `moderate the pastebin content`_ as they have no way to decrypt it.
|
|||
|
||||
It's an Python implementation of the `zerobin project`_, created by sebsauvage, under the `WTFPL licence`_.
|
||||
|
||||
For now tested with IE9, and the last opera, safari, chrome and FF.
|
||||
To run zerobin, download zerobin.pyz from the latest release_ then:
|
||||
|
||||
There is a `good doc <http://readthedocs.org/docs/0bin/en/latest/>`_,
|
||||
but in short::
|
||||
::
|
||||
|
||||
pip install zerobin
|
||||
zerobin
|
||||
python zerobin.pyz
|
||||
|
||||
0bin requires Python 3.7 or higher.
|
||||
|
||||
You may need to type :code:`py -3.7 zerobin.pyz` on Windows, or :code:`python3.7 zerobin.pyz` on Mac/Linux, depending on your configuration.
|
||||
|
||||
If you are familiar with the Python ecosystem, you can also :code:`python -m pip install zerobin --user` and run :code:`python -m zerobin` for the same effect.
|
||||
|
||||
0bin runs on Python 3.7+.
|
||||
|
||||
How it works
|
||||
=============
|
||||
|
@ -70,6 +73,7 @@ Known issues
|
|||
.. _node.js: http://nodejs.org/
|
||||
.. _is not worth it: http://stackoverflow.com/questions/201705/how-many-random-elements-before-md5-produces-collisions
|
||||
.. _WTFPL licence: http://en.wikipedia.org/wiki/WTFPL
|
||||
.. _release: https://github.com/Tygs/0bin/releases
|
||||
|
||||
Contributing
|
||||
=============
|
||||
|
|
22
compress.sh
|
@ -1,22 +1,22 @@
|
|||
#! /bin/bash
|
||||
|
||||
command -v "yui-compressor" >/dev/null 2>&1 || {
|
||||
echo >&2 "Error: this script requires the command 'yui-compressor' to be available"
|
||||
export PYTHONWARNINGS=ignore::FutureWarning # scss prints future warnings
|
||||
|
||||
python -c "import scss" || {
|
||||
echo >&2 "Error: this script requires the scss python module. pip install -r dev-requirements.txt"
|
||||
exit 1
|
||||
}
|
||||
|
||||
command -v "uglifyjs" >/dev/null 2>&1 || {
|
||||
echo >&2 "Error: this script requires the command 'uglifyjs' to be available"
|
||||
echo >&2 "Error: this script requires the command 'uglifyjs' to be available."
|
||||
exit 1
|
||||
}
|
||||
|
||||
CURDIR=$(dirname $(readlink -f $0))
|
||||
STATICDIR=$CURDIR'/zerobin/static/'
|
||||
CSSDIR=$STATICDIR'css/'
|
||||
JSDIR=$STATICDIR'js/'
|
||||
CSSDIR=$CURDIR'/zerobin/static/css/'
|
||||
JSDIR=$CURDIR'/zerobin/static/js/'
|
||||
|
||||
MAIN_JS_OUTPUT=$JSDIR"main.min.js"
|
||||
ADDITIONAL_JS_OUTPUT=$JSDIR"additional.min.js"
|
||||
CSS_OUTPUT=$CSSDIR"style.min.css"
|
||||
|
||||
cat /dev/null >$CSS_OUTPUT
|
||||
|
@ -24,16 +24,16 @@ cat /dev/null >$CSS_OUTPUT
|
|||
echo "Compressing CSS..."
|
||||
|
||||
echo $'\n''/* Prettify */' >>$CSS_OUTPUT
|
||||
cat $CSSDIR'prettify.css' >>$CSS_OUTPUT
|
||||
python -m scss $CSSDIR'prettify.css' >>$CSS_OUTPUT
|
||||
|
||||
echo $'\n''/* Desert prettify theme */' >>$CSS_OUTPUT
|
||||
cat $CSSDIR'desert.css' >>$CSS_OUTPUT
|
||||
python -m scss $CSSDIR'desert.css' >>$CSS_OUTPUT
|
||||
|
||||
echo $'\n''/* Bootswatch bootstrap theme */' >>$CSS_OUTPUT
|
||||
yui-compressor $CSSDIR'bootswatch.4.5.css' >>$CSS_OUTPUT
|
||||
python -m scss $CSSDIR'bootswatch.4.5.css' >>$CSS_OUTPUT
|
||||
|
||||
echo $'\n''/* Our own CSS */' >>$CSS_OUTPUT
|
||||
yui-compressor $CSSDIR'style.css' >>$CSS_OUTPUT
|
||||
python -m scss $CSSDIR'style.css' >>$CSS_OUTPUT
|
||||
|
||||
echo "Compressing JS..."
|
||||
|
||||
|
|
3
dev-requirements.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
doit==0.32.0
|
||||
pyScss==1.3.7
|
||||
twine==3.2.0
|
|
@ -44,10 +44,15 @@ GROUP = None
|
|||
|
||||
# Names/links to insert in the menu bar.
|
||||
# Any link with "mailto:" will be escaped to prevent spam
|
||||
|
||||
MENU = (
|
||||
('Home', '/'), # internal link. First link will be highlited
|
||||
('Download 0bin', 'https://github.com/sametmax/0bin'), # external link
|
||||
('Contact', 'mailto:your@email.com') # email
|
||||
("Github", "https://github.com/Tygs/0bin"),
|
||||
("Faq", "/faq/"), # You probably want to keep this
|
||||
# Any link with "mailto:" will be escaped to limit spam, but displayed
|
||||
# correctly to the user using JS.
|
||||
("Contact", "mailto:your@email.com"),
|
||||
("Zerobin Pastebin", "https://www.0bin.net/"), # Thanks the authors :)
|
||||
("How to buy Bitcoin?", "/buy_bitcoin"), # Thanks the authors :)
|
||||
)
|
||||
|
||||
# limit size of pasted text in bytes. Be careful allowing too much size can slow down user's
|
||||
|
|
146
dodo.py
Normal file
|
@ -0,0 +1,146 @@
|
|||
import sys
|
||||
import subprocess
|
||||
|
||||
from pathlib import Path
|
||||
from fnmatch import fnmatch
|
||||
|
||||
from doit.tools import PythonInteractiveAction
|
||||
|
||||
try:
|
||||
from local_dodo import *
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
ROOT = Path(__file__).absolute().parent
|
||||
SOURCE_DIR = ROOT / "zerobin/"
|
||||
DIST_DIR = ROOT / "dist"
|
||||
|
||||
ZEROBIN_VERSION = (SOURCE_DIR / "VERSION").read_text().strip()
|
||||
|
||||
DOIT_CONFIG = {
|
||||
"default_tasks": ["task_compress"],
|
||||
"action_string_formatting": "new",
|
||||
}
|
||||
|
||||
|
||||
def git(*args, **kwargs):
|
||||
return subprocess.check_output(
|
||||
["git", *args], stderr=subprocess.STDOUT, universal_newlines=True,
|
||||
).rstrip("\n")
|
||||
|
||||
|
||||
def source_files(extensions=None, exclude=()):
|
||||
exclude_filter = ["*.pyc", ".*"]
|
||||
exclude_filter.extend(exclude)
|
||||
extensions = extensions or [".*"]
|
||||
for ext in extensions:
|
||||
for file in SOURCE_DIR.rglob(f"*{ext}"):
|
||||
if not (
|
||||
file.is_dir()
|
||||
or any(fnmatch(file, pattern) for pattern in exclude_filter)
|
||||
):
|
||||
yield file
|
||||
|
||||
|
||||
def task_generate_manifest():
|
||||
def generate():
|
||||
globs = " ".join(set(f"*{f.suffix}" for f in source_files()))
|
||||
globs += " VERSION"
|
||||
(ROOT / "MANIFEST.in").write_text(f"recursive-include zerobin {globs}")
|
||||
|
||||
return {
|
||||
"targets": [ROOT / "MANIFEST.in"],
|
||||
"actions": [generate],
|
||||
}
|
||||
|
||||
|
||||
def task_compress():
|
||||
main_js = str(SOURCE_DIR / "static/js/main.min.js")
|
||||
main_css = str(SOURCE_DIR / "static/css/style.min.css")
|
||||
return {
|
||||
"targets": [main_js, main_css],
|
||||
"file_dep": list(
|
||||
str(f) for f in source_files([".css", ".js"], exclude=[main_css, main_js])
|
||||
),
|
||||
"actions": [str(ROOT / "compress.sh")],
|
||||
}
|
||||
|
||||
|
||||
def task_build():
|
||||
|
||||
return {
|
||||
"targets": [DIST_DIR / f"zerobin-{ZEROBIN_VERSION}-py3-none-any.whl"],
|
||||
"file_dep": list(str(f) for f in source_files() if ".min." not in str(f)),
|
||||
"task_dep": ["compress", "generate_manifest"],
|
||||
"actions": ["python setup.py bdist_wheel"],
|
||||
}
|
||||
|
||||
|
||||
def task_publish_to_pypi():
|
||||
|
||||
return {
|
||||
"task_dep": ["build"],
|
||||
"actions": ["twine upload ./dist/*.whl"],
|
||||
}
|
||||
|
||||
|
||||
def task_build_pyz():
|
||||
return {
|
||||
"actions": ["shiv zerobin -o dist/zerobin.pyz -c zerobin"],
|
||||
}
|
||||
|
||||
|
||||
def task_bump_version():
|
||||
def bump():
|
||||
|
||||
if git("branch", "--show-current") != "master":
|
||||
sys.exit("You must be on the branch master to do that")
|
||||
|
||||
git("fetch", "origin", "master")
|
||||
if git("rev-parse", "@{u}") != git("merge-base", "@", "@{u}"):
|
||||
sys.exit("Cannot push a new version, you need to pull first")
|
||||
|
||||
git_status = git("status", "--porcelain=1").split("\n")
|
||||
if not all(
|
||||
line.startswith(" ") for line in git_status if not line.startswith("?")
|
||||
):
|
||||
sys.exit("Cannot commit the new version: you have changes to be commited.")
|
||||
|
||||
print("Current version is:", ZEROBIN_VERSION)
|
||||
action = "0"
|
||||
while action not in "123":
|
||||
|
||||
print("What kind of version is it?\n")
|
||||
print("1) Major")
|
||||
print("2) Minor")
|
||||
print("3) Fix")
|
||||
action = input("Enter 1, 2 or 3 (Ctrl + C to quit): ")
|
||||
|
||||
new_version = list(map(int, ZEROBIN_VERSION.split(".")))
|
||||
action = int(action) - 1
|
||||
new_version[action] += 1
|
||||
new_version = ".".join(map(str, new_version))
|
||||
|
||||
print("The new version will be:", new_version)
|
||||
if input("Ok? [y/N] ").strip().lower() != "y":
|
||||
sys.exit("The version has NOT been bumped")
|
||||
|
||||
print("- Updating VERSION file")
|
||||
(SOURCE_DIR / "VERSION").write_text(new_version)
|
||||
print("- Commiting VERSION file")
|
||||
git("add", "zerobin/VERSION")
|
||||
git(
|
||||
"commit", "-m", f"Bumping to version {new_version}",
|
||||
)
|
||||
print(f"- Adding v{new_version} tag")
|
||||
git("tag", f"v{new_version}")
|
||||
print("- Pushing tag")
|
||||
git("push", "origin", "master", "--tag")
|
||||
|
||||
return {
|
||||
"actions": [PythonInteractiveAction(bump),],
|
||||
}
|
||||
|
||||
|
||||
def task_release_to_pypi():
|
||||
return {"task_dep": ["bump_version", "publish_to_pypi"], "actions": []}
|
6
pyproject.toml
Normal file
|
@ -0,0 +1,6 @@
|
|||
[build-system]
|
||||
requires = [
|
||||
"setuptools >= 40.9.0",
|
||||
"wheel",
|
||||
]
|
||||
build-backend = "setuptools.build_meta"
|
|
@ -1,8 +0,0 @@
|
|||
clize==4.1.1
|
||||
lockfile==0.12.2
|
||||
sigtools==2.0.2
|
||||
bottle==0.12.18
|
||||
Beaker==1.11.0
|
||||
Paste==3.4.3
|
||||
appdirs==1.4.4
|
||||
bleach==3.1.5
|
BIN
screenshot.png
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 41 KiB |
|
@ -15,7 +15,6 @@ packages = find:
|
|||
install_requires =
|
||||
clize==4.1.1
|
||||
lockfile==0.12.2
|
||||
sigtools==2.0.2
|
||||
bottle==0.12.18
|
||||
Beaker==1.11.0
|
||||
Paste==3.4.3
|
||||
|
@ -26,3 +25,6 @@ install_requires =
|
|||
* = static/img/*, static/css/*, static/js/*, view/*
|
||||
hello = *.msg
|
||||
|
||||
[options.entry_points]
|
||||
console_scripts =
|
||||
zerobin = zerobin.cli:main
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
|
||||
zerobinpaste: zerobinpaste.js commander.js ../zerobin/static/js/sjcl.js ../zerobin/static/js/lzw.js
|
||||
echo '#!/usr/bin/env node' > zerobinpaste
|
||||
cat commander.js ../zerobin/static/js/sjcl.js ../zerobin/static/js/lzw.js >> zerobinpaste
|
||||
cat zerobinpaste.js >> zerobinpaste
|
||||
chmod +x zerobinpaste
|
||||
|
||||
ugly: zerobinpaste
|
||||
uglifyjs=$$(PATH="$$(npm bin):$$PATH" which uglifyjs 2>/dev/null) \
|
||||
|| { npm install uglify-js; uglifyjs=$$(PATH="$$(npm bin):$$PATH" which uglifyjs); } \
|
||||
&& sed -i 1d zerobinpaste \
|
||||
&& $${uglifyjs} -o zerobinpaste.min zerobinpaste \
|
||||
&& echo '#!/usr/bin/env node' > zerobinpaste \
|
||||
&& cat zerobinpaste.min >> zerobinpaste \
|
||||
&& chmod +x zerobinpaste
|
||||
|
||||
clean:
|
||||
rm -f zerobinpaste{,.js,.min}
|
||||
|
||||
zerobinpaste.js: zerobinpaste.coffee
|
||||
coffee=$$(PATH="$$(npm bin):$$PATH" which coffee 2>/dev/null) \
|
||||
|| { npm install coffee-script; coffee=$$(PATH="$$(npm bin):$$PATH" which coffee); } \
|
||||
&& $$coffee -c zerobinpaste.coffee
|
||||
|
||||
.PHONY: uglify
|
1118
tools/commander.js
|
@ -1,145 +0,0 @@
|
|||
|
||||
program
|
||||
.version('0.0.1')
|
||||
.usage('[options] [ file ... ]\n\n' + ' Paste contents of file(s) or stdin to 0bin site.')
|
||||
.option('-u, --url [url]', 'URL of a 0bin site.')
|
||||
.option('-e, --expire [period]',
|
||||
'Expiration period - one of: 1_view, 1_day (default), 1_month, never.', '1_day')
|
||||
.option('-k, --entropy [bytes]',
|
||||
'Encryption key entropy (and hence length) to use,'\
|
||||
+ ' in bytes (default: 32).\n'\
|
||||
+ ' That key will be processed by 1000 pbkdf2-sha256 iterations, not used as-is.', 32)
|
||||
.option('-c, --config [path]',
|
||||
'Path to zerobin configuration file (default: ~/.zerobinpasterc).\n'\
|
||||
+ ' Should be json-file with the same keys as can be specified on the command line.\n'\
|
||||
+ ' Example contents: {"url": "http://some-0bin.com"}', '~/.zerobinpasterc')
|
||||
.option('-n, --nocheck', 'do not check SSL certs.')
|
||||
.parse(process.argv);
|
||||
|
||||
|
||||
[http, https, url, qs, fs, path] = ['http', 'https', 'url', 'querystring', 'fs', 'path'].map(require)
|
||||
|
||||
|
||||
# Parse config file, if any
|
||||
config = program.config.replace(/^~\/+/, '')
|
||||
config = path.resolve(process.env.HOME, config)
|
||||
|
||||
try
|
||||
if fs.statSync(config).isFile()
|
||||
config = JSON.parse(fs.readFileSync(config))
|
||||
(program[k] = v) for own k, v of config
|
||||
|
||||
|
||||
# Sanity checks and option processing
|
||||
if not program.url
|
||||
console.error('ERROR: URL option must be specified.')
|
||||
process.exit(1)
|
||||
|
||||
if program.expire == '1_view'
|
||||
# "burn_after_reading" is too damn long for cli
|
||||
program.expire = 'burn_after_reading'
|
||||
|
||||
expire_opts = ['burn_after_reading', '1_day', '1_month', 'never']
|
||||
if program.expire not in expire_opts
|
||||
console.error(
|
||||
"ERROR: --expire value (provided: '#{program.expire}')"\
|
||||
+ ' must be one of: ' + expire_opts.join(', ') + "." )
|
||||
process.exit(1)
|
||||
|
||||
program.entropy = parseInt(program.entropy)
|
||||
|
||||
|
||||
# Generated key will use base64 (6b per char) charset
|
||||
# Key is not decoded for pbkdf2, so it's generated via base64 here just for convenience
|
||||
generate_key = (entropy) ->
|
||||
entropy = Math.ceil(entropy / 8.0) * 8
|
||||
key = sjcl.bitArray.clamp(
|
||||
sjcl.random.randomWords(Math.ceil(entropy / 32), 0), entropy )
|
||||
return sjcl.codec.base64.fromBits(key, 0).replace(/\=+$/, '').replace(/\//, '-')
|
||||
|
||||
|
||||
# Paste one dump and print URL, optionally prefixed with name
|
||||
paste_file = (content, name) ->
|
||||
|
||||
content = sjcl.codec.utf8String.toBits(content)
|
||||
content = sjcl.codec.base64.fromBits(content)
|
||||
# content = lzw.compress(content)
|
||||
|
||||
key = generate_key(program.entropy)
|
||||
content = sjcl.encrypt(key, content)
|
||||
content = qs.stringify
|
||||
content: content
|
||||
expiration: program.expire
|
||||
|
||||
# host.com -> http://host.com
|
||||
if not program.url.match(/^https?:\/\//)
|
||||
program.url = 'http://' + program.url.replace(/^\/+/, '')
|
||||
|
||||
proto = http
|
||||
|
||||
if program.url.match(/^https:\/\//)
|
||||
proto = https
|
||||
|
||||
req_opts = url.parse(program.url)
|
||||
req_opts.method = 'POST'
|
||||
|
||||
req_opts.headers =
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
'Content-Length': content.length
|
||||
|
||||
req_url_base = req_opts.path
|
||||
.replace(/\/paste\/create\/?$/, '').replace(/\/+$/, '')
|
||||
req_opts.path = req_url_base + '/paste/create'
|
||||
|
||||
if program.nocheck
|
||||
req_opts.rejectUnauthorized = false
|
||||
|
||||
req = proto.request req_opts, (res) ->
|
||||
req_reply = ''
|
||||
res.setEncoding('utf8')
|
||||
res.on 'data', (chunk) -> req_reply += chunk
|
||||
res.on 'end', ->
|
||||
req_reply = JSON.parse(req_reply)
|
||||
if req_reply.status != 'ok'
|
||||
console.error("ERROR: failure posting #{name} - " + req_reply.message)
|
||||
return
|
||||
|
||||
req_opts.pathname = req_url_base + '/paste/' + req_reply.paste
|
||||
req_opts.hash = key
|
||||
paste = url.format(req_opts)
|
||||
|
||||
console.log(if name then "#{name} #{paste}" else paste)
|
||||
|
||||
req.write(content)
|
||||
req.end()
|
||||
req.on 'error', (e) -> console.error(e)
|
||||
|
||||
# Seed sjcl prng from /dev/(u)random
|
||||
do (bytes=64) ->
|
||||
for src in ['/dev/urandom', '/dev/random', null]
|
||||
break if not src or fs.existsSync(src)
|
||||
if not src
|
||||
console.error( 'ERROR: Failed to seed PRNG -'\
|
||||
+ ' /dev/(u)random is unavailable, relying only on sjcl entropy sources' )
|
||||
return
|
||||
fd = fs.openSync(src, 'r')
|
||||
buff = new Buffer(bytes)
|
||||
fs.readSync(fd, buff, 0, bytes)
|
||||
fs.closeSync(fd)
|
||||
sjcl.random.addEntropy(
|
||||
(buff.readUInt32BE(n) for n in [0..bytes/4]), bytes * 8, src )
|
||||
|
||||
|
||||
# Loop over file args or read stdin
|
||||
if not program.args or not program.args.length
|
||||
process.stdin.resume()
|
||||
process.stdin.setEncoding('utf8')
|
||||
|
||||
stdin_data = ''
|
||||
process.stdin.on 'data', (chunk) -> stdin_data += chunk
|
||||
process.stdin.on 'end', -> paste_file(stdin_data)
|
||||
|
||||
else
|
||||
for file in program.args
|
||||
paste_file( fs.readFileSync(file, 'utf8'),
|
||||
if program.args.length > 1 then path.basename(file) else null )
|
1
zerobin/VERSION
Normal file
|
@ -0,0 +1 @@
|
|||
1.0.5
|
|
@ -1,5 +1,5 @@
|
|||
from pathlib import Path
|
||||
|
||||
__version__ = "1.0.0"
|
||||
__version__ = (Path(__file__).parent / "VERSION").read_text().strip()
|
||||
|
||||
ROOT_DIR = Path(__file__).absolute().parent
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Get error messages and auto reload.
|
||||
# Don't set this to True in production
|
||||
DEBUG = True
|
||||
DEBUG = False
|
||||
|
||||
# Port and host for the embedded python server
|
||||
HOST = "127.0.0.1"
|
||||
|
@ -9,18 +9,18 @@ PORT = "3255"
|
|||
# Names/links to insert in the footer.
|
||||
#
|
||||
MENU = (
|
||||
("Create paste", "/"),
|
||||
("Github", "https://github.com/Tygs/0bin"),
|
||||
("Faq", "/faq/"), # You probably want to keep this
|
||||
# Any link with "mailto:" will be escaped to limit spam, but displayed
|
||||
# correctly to the user using JS.
|
||||
("Contact", "mailto:your@email.com"),
|
||||
("Zerobin Pastebin", "https://www.0bin.net/"), # Thanks the authors :)
|
||||
("How to buy Bitcoin?", "/buy_bitcoin"), # Thanks the authors :)
|
||||
)
|
||||
|
||||
# Size limit of the paste content in bytes. Be careful, allowing a size too big can
|
||||
# slow down the user's browser
|
||||
MAX_SIZE = 1024 * 600
|
||||
MAX_SIZE = 1024 * 1000
|
||||
|
||||
# Display a tiny counter for pastes created.
|
||||
DISPLAY_COUNTER = True
|
||||
|
|
|
@ -59,6 +59,11 @@ def index():
|
|||
def faq():
|
||||
return GLOBAL_CONTEXT
|
||||
|
||||
@app.route("/buy_bitcoin")
|
||||
@view("buy_bitcoin")
|
||||
def index():
|
||||
return GLOBAL_CONTEXT
|
||||
|
||||
|
||||
@app.get(settings.ADMIN_URL)
|
||||
@app.post(settings.ADMIN_URL)
|
||||
|
|
|
@ -8,6 +8,10 @@
|
|||
border: 25px solid red;
|
||||
}
|
||||
|
||||
body {
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
/* logo */
|
||||
|
||||
.brand {
|
||||
|
@ -336,6 +340,22 @@ pre {
|
|||
/* Common css */
|
||||
|
||||
|
||||
#faq {
|
||||
max-width: 80%;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
#buy_bitcoin {
|
||||
max-width: 80%;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
#buy_bitcoin img{
|
||||
width: 85%;
|
||||
display: block;
|
||||
margin: 20px auto;
|
||||
}
|
||||
|
||||
.caret {
|
||||
border-left: 6px solid transparent;
|
||||
border-right: 6px solid transparent;
|
||||
|
@ -626,6 +646,7 @@ nav ul li a:hover {
|
|||
max-width: 120px;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
51
zerobin/static/css/style.min.css
vendored
BIN
zerobin/static/img/binance1.png
Normal file
After Width: | Height: | Size: 261 KiB |
BIN
zerobin/static/img/binance2.png
Normal file
After Width: | Height: | Size: 580 KiB |
BIN
zerobin/static/img/binance3.png
Normal file
After Width: | Height: | Size: 73 KiB |
BIN
zerobin/static/img/binance4.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
zerobin/static/img/binance5.png
Normal file
After Width: | Height: | Size: 147 KiB |
BIN
zerobin/static/img/binance6.png
Normal file
After Width: | Height: | Size: 73 KiB |
|
@ -64,7 +64,7 @@ class SettingsContainer(object):
|
|||
Update settings with values from the given module file.
|
||||
Uses update_with_dict() behind the scenes.
|
||||
"""
|
||||
params = run_path(filepath)
|
||||
params = run_path(str(filepath))
|
||||
return self.update_with_dict(params)
|
||||
|
||||
|
||||
|
|
|
@ -5,9 +5,7 @@
|
|||
<meta charset="utf-8">
|
||||
<title>0bin - encrypted pastebin</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1">
|
||||
<meta name="description" content="0bin is a client-side-encrypted
|
||||
pastebin featuring burn after reading, history, and
|
||||
a clipboard">
|
||||
<meta name="description" content="0bin is a client-side-encrypted alternative pastebin. You can store code/text/images online for a set period of time and share with the world. Featuring burn after reading, history, clipboard.">
|
||||
|
||||
<link rel="icon" href="/static/img/favicon.ico" />
|
||||
<link rel="apple-touch-icon" href="/static/img/apple-touch-icon.png" />
|
||||
|
|
151
zerobin/views/buy_bitcoin.tpl
Normal file
|
@ -0,0 +1,151 @@
|
|||
<div class="well" id="buy_bitcoin">
|
||||
<h1>How To Buy Bitcoin?</h1>
|
||||
|
||||
|
||||
<p></p>
|
||||
|
||||
|
||||
<h4>What is Bitcoin?</h4>
|
||||
|
||||
|
||||
<p>Bitcoin was created by Satoshi Nakamoto, a pseudonymous person or team who outlined the technology in a 2008 white
|
||||
paper. It’s an appealingly simple concept: <strong>bitcoin is digital money</strong> that allows for secure
|
||||
peer-to-peer transactions on the internet.
|
||||
</p>
|
||||
<p>Unlike services like Venmo and PayPal, which rely on the traditional financial system for permission to transfer
|
||||
money and on existing debit/credit accounts, bitcoin is decentralized: any two people, anywhere in the world, can
|
||||
send bitcoin to each other without the involvement of a bank, the government, or other institution.
|
||||
<p>
|
||||
Every transaction involving Bitcoin is tracked on the blockchain, which is similar to a bank ledger, or log of
|
||||
customers’ funds going in and out of the bank. In simple terms, it’s a record of every transaction ever made
|
||||
using bitcoin.
|
||||
</p>
|
||||
<p>
|
||||
There will only ever be 21 million bitcoin. This is digital money that cannot be inflated or manipulated in any
|
||||
way.
|
||||
</p>
|
||||
<p>
|
||||
It isn’t necessary to buy an entire bitcoin: you can buy just a fraction of one if that’s all you want or need.
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
<h4>Why would I buy Bitcoin?</h4>
|
||||
|
||||
|
||||
<p>Bitcoin is in the news today more than ever. Thanks to skyrocketing prices and rollercoaster dips, everyone and
|
||||
their dogs are interested in learning how to buy and sell Bitcoin. As the most popular form of cryptocurrency,
|
||||
Bitcoin is now widely accepted around the world and has a growing number of applications. If you want to take
|
||||
advantage of that though, you first need to know how to buy Bitcoin and what to do with it when you have.
|
||||
</p>
|
||||
|
||||
|
||||
<h4>How to buy Bitcoin ?</h4>
|
||||
|
||||
|
||||
<p>The best place to make your first Bitcoin purchase is on an exchange. There are a whole lot of exchanges out
|
||||
there, with varying performance. Some are less trustworthy than others, and some can be quite limited, so it’s
|
||||
crucial to pick the right exchange in the first place. We recommend using <a
|
||||
href="https://www.binance.com/en/register?ref=CAWS9NNE" title="Buy Bitcoin">Binance</a>, follow the simple
|
||||
guide below to buy your first Bitcoins.
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
<h6>1. Buy Bitcoin on Binance</h6>
|
||||
|
||||
|
||||
<p>We recommend buying Bitcoins on <a href="https://www.binance.com/en/register?ref=CAWS9NNE"
|
||||
title="Buy Bitcoin">Binance</a> because in terms of volume, it is considered to be the world's leading
|
||||
platform.
|
||||
In 2019, Binance reports an average trading volume of <strong>$2.8 billion per day</strong>. This platform,
|
||||
launched on July 14, 2017, in Hong Kong, has the advantage of operating with technical assistance 24 hours a
|
||||
day, 7 days a week. Its <strong>CEO Zhao Changpeng</strong>, who has become a billionaire, was featured on the
|
||||
cover of the prestigious Forbes magazine in February 2018.
|
||||
</p>
|
||||
|
||||
|
||||
<h6>2. How do I register with <a href="https://www.binance.com/en/register?ref=CAWS9NNE"
|
||||
title="Buy Bitcoin">Binance</a> to buy Bitcoin?</h6>
|
||||
|
||||
|
||||
<p>The first step before buying Bitcoin on <a href="https://www.binance.com/en/register?ref=CAWS9NNE"
|
||||
title="Buy Bitcoin">Binance</a> is to register. The user must first select the language in which they want
|
||||
to access the site, then enter a valid email address and finally choose a password.
|
||||
</p>
|
||||
|
||||
|
||||
<h3 class="text-center"><a href="https://www.binance.com/en/register?ref=CAWS9NNE" title="Buy Bitcoin">Click here
|
||||
to register an account with Binance now!<a></h3>
|
||||
|
||||
|
||||
<img src="/static/img/binance1.png" alt="Register Binance">
|
||||
|
||||
|
||||
<p>For your security, the platform offers you to proceed to the 2FA, also called "Two Step Verification", which
|
||||
consists in logging in with your password and your phone using <a
|
||||
href="https://support.google.com/accounts/answer/1066447?co=GENIE.Platform%3DAndroid">Google
|
||||
Authenticator</a>. Both we and the platform recommend that you delay the purchase of your Bitcoins by opting
|
||||
for this extra layer of security. Binance Academy 2FA available <a
|
||||
href="https://academy.binance.com/tutorials/binance-2fa-guide">here</a>.
|
||||
</p>
|
||||
|
||||
|
||||
<img src="/static/img/binance2.png" alt="2FA Binance">
|
||||
|
||||
|
||||
<p>The second step is to verify your identity. Indeed, <a href="https://www.binance.com/en/register?ref=CAWS9NNE"
|
||||
title="Buy Bitcoin">Binance</a> is subject to KYC regulations as part of the fight against money laundering
|
||||
and terrorist financing. The platform will ask you whether or not you reside in China, before moving on to
|
||||
other personal information (surname, first name, gender, country of residence).
|
||||
</p>
|
||||
|
||||
|
||||
<img src="/static/img/binance3.png" alt="Verify identity Binance">
|
||||
|
||||
|
||||
<p>Authentication is done by sending the number and a photocopy of both sides of your ID and a photo of you. On
|
||||
this photo, you must show the same ID and a newspaper (or other document) with the current date.
|
||||
</p>
|
||||
|
||||
|
||||
<img src="/static/img/binance4.png" alt="Verify identity Binance">
|
||||
|
||||
|
||||
<p>The easiest way to get Bitcoin at Binance is to buy it by credit card. To do so, head over to the “Buy Crypto”
|
||||
section on the <a href="https://www.binance.com/en/register?ref=CAWS9NNE" title="Buy Bitcoin">Binance</a>
|
||||
toolbar, and choose the “Buy with Credit Card” option.
|
||||
</p>
|
||||
|
||||
|
||||
<img src="/static/img/binance6.png" alt="Verify identity Binance">
|
||||
|
||||
|
||||
<p>Select your currency and BTC coin you wish to purchase and enter the amount before clicking "Buy BTC". All you
|
||||
will need to do is enter your bank details and the purchase will be completed.</p>
|
||||
|
||||
|
||||
<img src="/static/img/binance5.png" alt="Verify identity Binance">
|
||||
|
||||
|
||||
<p>Although it is mainly focused on the exchange of cryptomoney, <a
|
||||
href="https://www.binance.com/en/register?ref=CAWS9NNE" title="Buy Bitcoin">Binance</a> is now establishing
|
||||
itself as a very competitive platform for the purchase of cryptomoney by credit card. It is also reassuring
|
||||
because of its reputation, its activity and its ecosystem.</p>
|
||||
|
||||
|
||||
<h4>You're now a part of the future! Congrats!</h4>
|
||||
|
||||
|
||||
<p></p>
|
||||
<p>Read more about Bitcoins
|
||||
<br><a href="https://bitcoin.org/en/">Bitcoin.org</a>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
% rebase("base", settings=settings, pastes_count=pastes_count)
|
|
@ -2,9 +2,10 @@
|
|||
|
||||
<h1>FAQ</h1>
|
||||
|
||||
<table>
|
||||
<tr>How does 0bin work?</tr>
|
||||
<td>
|
||||
<p></p>
|
||||
|
||||
<h4>How does 0bin work?</h4>
|
||||
|
||||
<p>A random key is generated and used to encrypt the paste, thanks to
|
||||
the <a href="http://crypto.stanford.edu/sjcl/">sjcl</a>
|
||||
JavaScript library.</p>
|
||||
|
@ -17,10 +18,10 @@
|
|||
JavaScript will use it to decrypt the content sent by the server.</p>
|
||||
<p>The browser never sends the hash to the server, so the latter does not
|
||||
receives the key at any time.</p>
|
||||
</td>
|
||||
|
||||
<tr>But JavaScript encryption is not secure!</tr>
|
||||
<td>
|
||||
|
||||
<h4>But JavaScript encryption is not secure!</h4>
|
||||
|
||||
<p>No, it isn't.</p>
|
||||
<p>The goal of 0bin is <strong>not</strong> to protect the user and their data
|
||||
(including, obviously, their secrets).</p>
|
||||
|
@ -32,12 +33,12 @@
|
|||
<p>Remember that as an user, you should use 0bin in the same way as unencrypted and
|
||||
insecure pastebins - that is, with caution. The only difference with those is that if
|
||||
you decide to host a 0bin server, the encryption feature hopefully be used as a defense.
|
||||
This is not proven, though! :-)
|
||||
This is not proven, though! :-)</p>
|
||||
|
||||
|
||||
<h4>What if the server changes the JavaScript code? And what happens in the case of a <a
|
||||
href="https://en.wikipedia.org/wiki/Man-in-the-middle_attack">MITM attack</a>?</h4>
|
||||
|
||||
</td>
|
||||
<tr>What if the server changes the JavaScript code? And what happens in the case of a <a
|
||||
href="https://en.wikipedia.org/wiki/Man-in-the-middle_attack">MITM attack</a>?</tr>
|
||||
<td>
|
||||
<p>Read above.</p>
|
||||
<p>0bin is not built, and does not aim, to protect user data - but rather the host.
|
||||
If any user data is compromised, 0bin still provides the host with
|
||||
|
@ -53,22 +54,20 @@
|
|||
<p>It would be unlikely for those softwares to fail you. Errors will nearly always come from your side - you
|
||||
ought to have a perfect <a href="https://en.wikipedia.org/wiki/Operations_security">operations security</a>
|
||||
if you do not want your data to be leaked. Remember to use your common sense.</p>
|
||||
</td>
|
||||
<tr>How did the idea of 0bin emerge?</tr>
|
||||
<td>
|
||||
|
||||
<h4>How did the idea of 0bin emerge?</h4>
|
||||
|
||||
<p>0bin is based on <a href="http://sebsauvage.net/wiki/doku.php?id=php:zerobin">sebsauvage's work</a>.
|
||||
The project sprang as a reaction to <a
|
||||
href="https://www.zdnet.com/blog/security/pastebin-to-hunt-for-hacker-pastes-anonymous-cries-censorship/11336">the
|
||||
implementation of a moderation system on Pastebin</a>,
|
||||
due to the significant amount of illegal content pasted on it, or that it linked to.</p>
|
||||
</td>
|
||||
<tr>How can I get 0bin?</tr>
|
||||
<td>
|
||||
|
||||
<h4>How can I get 0bin?</h4>
|
||||
|
||||
<p>0bin is an open-source project, and the code is hosted on <a
|
||||
href="https://github.com/sametmax/0bin">GitHub</a>.
|
||||
You can either download a tarball or clone the repository.</p>
|
||||
</td>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@
|
|||
|
||||
<div class="paste-options-res">
|
||||
<div class="btn-group">
|
||||
<span class="input-group-text">Tip it with<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18"
|
||||
<span class="input-group-text">Tip it<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18"
|
||||
viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M12 2c5.514 0 10 4.486 10 10s-4.486 10-10 10-10-4.486-10-10 4.486-10 10-10zm0-2c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm0 18v-1.511h-.5v1.511h-1v-1.511h-2.484l.25-1.489h.539c.442 0 .695-.425.695-.854v-4.444c0-.416-.242-.702-.683-.702h-.817v-1.5h2.5v-1.5h1v1.5h.5v-1.5h1v1.526c2.158.073 3.012.891 3.257 1.812.29 1.09-.429 2.005-1.046 2.228.75.192 1.789.746 1.789 2.026 0 1.742-1.344 2.908-4 2.908v1.5h-1zm-.5-5.503v2.503c1.984 0 3.344-.188 3.344-1.258 0-1.148-1.469-1.245-3.344-1.245zm0-.997c1.105 0 2.789-.078 2.789-1.25 0-1-1.039-1.25-2.789-1.25v2.5z"
|
||||
|
@ -111,8 +111,10 @@
|
|||
|
||||
|
||||
<div class="d-flex justify-content-between down">
|
||||
<div v-if="currentPaste.ownerKey">
|
||||
<button class="btn btn-secondary" @click.prevent="handleDeletePaste()">Delete Paste</button>
|
||||
<div>
|
||||
<div v-if="currentPaste.ownerKey">
|
||||
<button class="btn btn-secondary" @click.prevent="handleDeletePaste()">Delete Paste</button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<span class="paste-option btn-group responsive-icons">
|
||||
|
@ -211,7 +213,6 @@
|
|||
<div class="d-flex justify-content-between" v-if="displayBottomToolBar">>
|
||||
|
||||
<div>
|
||||
<label class="col-form-label"> </label>
|
||||
<div class="file-upload">
|
||||
<button type="button" class="btn btn-info" @click.prevent="handleCancelClone()">Cancel clone</button>
|
||||
</div>
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
from zerobin.routes import get_app
|
||||
|
||||
# Remember you can set the following environment variables to configure
|
||||
# how get_app() setup the 0bin:
|
||||
#
|
||||
# - ZEROBIN_DEBUG =
|
||||
# - ZEROBIN_DATA_DIR
|
||||
# - ZEROBIN_CONFIG_DIR
|
||||
|
||||
settings, app = get_app()
|
||||
|
|