mirror of
https://github.com/Tygs/0bin.git
synced 2023-08-10 21:13:00 +03:00
Merge branch 'v2' of github.com:Tygs/0bin into v2
This commit is contained in:
commit
ed12243d67
26
.gitignore
vendored
26
.gitignore
vendored
@ -7,8 +7,7 @@
|
|||||||
*_index
|
*_index
|
||||||
*.orig
|
*.orig
|
||||||
*.swp
|
*.swp
|
||||||
.* # all hidden files...
|
|
||||||
!.gitignore # ...except gitignore
|
|
||||||
|
|
||||||
# binaries
|
# binaries
|
||||||
|
|
||||||
@ -16,27 +15,30 @@
|
|||||||
*.pyo
|
*.pyo
|
||||||
__pycache__
|
__pycache__
|
||||||
.mypy*
|
.mypy*
|
||||||
|
*.db
|
||||||
|
|
||||||
/tools/zerobinpaste.js
|
|
||||||
/tools/zerobinpaste.min
|
|
||||||
/tools/zerobinpaste
|
|
||||||
|
|
||||||
# files generated by setuptools
|
# build and env
|
||||||
|
|
||||||
|
build
|
||||||
|
0bin
|
||||||
|
env
|
||||||
|
venv
|
||||||
*.egg-info
|
*.egg-info
|
||||||
dist
|
dist
|
||||||
*.tar.gz
|
*.tar.gz
|
||||||
*.egg
|
*.egg
|
||||||
*.in
|
*.in
|
||||||
|
|
||||||
# others
|
|
||||||
|
|
||||||
content
|
# IDE
|
||||||
|
|
||||||
*.sublime-project
|
*.sublime-project
|
||||||
*-workspace
|
*-workspace
|
||||||
*_old*
|
*_old*
|
||||||
settings_local.py
|
|
||||||
build
|
|
||||||
.vscode
|
.vscode
|
||||||
var
|
|
||||||
0bin
|
# JS
|
||||||
|
|
||||||
|
package-lock.json
|
||||||
|
node_modules
|
||||||
|
23
compress.sh
23
compress.sh
@ -1,22 +1,20 @@
|
|||||||
#! /bin/bash
|
#! /bin/bash
|
||||||
|
|
||||||
command -v "yui-compressor" >/dev/null 2>&1 || {
|
python -c "import scss" || {
|
||||||
echo >&2 "Error: this script requires the command 'yui-compressor' to be available"
|
echo >&2 "Error: this script requires the scss python module. pip install -r dev-requirements.txt"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
command -v "uglifyjs" >/dev/null 2>&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
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
CURDIR=$(dirname $(readlink -f $0))
|
CURDIR=$(dirname $(readlink -f $0))
|
||||||
STATICDIR=$CURDIR'/zerobin/static/'
|
CSSDIR=$CURDIR'/zerobin/static/css/'
|
||||||
CSSDIR=$STATICDIR'css/'
|
JSDIR=$CURDIR'/zerobin/static/js/'
|
||||||
JSDIR=$STATICDIR'js/'
|
|
||||||
|
|
||||||
MAIN_JS_OUTPUT=$JSDIR"main.min.js"
|
MAIN_JS_OUTPUT=$JSDIR"main.min.js"
|
||||||
ADDITIONAL_JS_OUTPUT=$JSDIR"additional.min.js"
|
|
||||||
CSS_OUTPUT=$CSSDIR"style.min.css"
|
CSS_OUTPUT=$CSSDIR"style.min.css"
|
||||||
|
|
||||||
cat /dev/null >$CSS_OUTPUT
|
cat /dev/null >$CSS_OUTPUT
|
||||||
@ -24,16 +22,19 @@ cat /dev/null >$CSS_OUTPUT
|
|||||||
echo "Compressing CSS..."
|
echo "Compressing CSS..."
|
||||||
|
|
||||||
echo $'\n''/* Prettify */' >>$CSS_OUTPUT
|
echo $'\n''/* Prettify */' >>$CSS_OUTPUT
|
||||||
cat $CSSDIR'prettify.css' >>$CSS_OUTPUT
|
python -m scss $CSSDIR'prettify.css' >>$CSS_OUTPUT
|
||||||
|
rm $CSSDIR'prettify.min.css'
|
||||||
|
|
||||||
echo $'\n''/* Desert prettify theme */' >>$CSS_OUTPUT
|
echo $'\n''/* Desert prettify theme */' >>$CSS_OUTPUT
|
||||||
cat $CSSDIR'desert.css' >>$CSS_OUTPUT
|
python -m scss $CSSDIR'desert.css' >>$CSS_OUTPUT
|
||||||
|
rm $CSSDIR'desert.min.css'
|
||||||
|
|
||||||
echo $'\n''/* Bootswatch bootstrap theme */' >>$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
|
||||||
|
rm $CSSDIR'bootswatch.4.5.min.css'
|
||||||
|
|
||||||
echo $'\n''/* Our own 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..."
|
echo "Compressing JS..."
|
||||||
|
|
||||||
|
2
dev-requirements.txt
Normal file
2
dev-requirements.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
doit==0.32.0
|
||||||
|
pyScss==1.3.7
|
46
dodo.py
Normal file
46
dodo.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import zerobin
|
||||||
|
|
||||||
|
|
||||||
|
ROOT = Path(__file__).absolute().parent
|
||||||
|
SOURCE_DIR = ROOT / "zerobin/"
|
||||||
|
DIST_DIR = ROOT / "dist"
|
||||||
|
|
||||||
|
|
||||||
|
def source_files(extensions=None):
|
||||||
|
extensions = extensions or [".*"]
|
||||||
|
for ext in extensions:
|
||||||
|
for file in SOURCE_DIR.rglob(f"*{ext}"):
|
||||||
|
if (
|
||||||
|
not file.suffix.endswith("pyc")
|
||||||
|
and not file.is_dir()
|
||||||
|
and not "/." in str(file)
|
||||||
|
):
|
||||||
|
yield file
|
||||||
|
|
||||||
|
|
||||||
|
def generate_manifest():
|
||||||
|
extensions = " ".join(set(f"*{f.suffix}" for f in source_files()))
|
||||||
|
(ROOT / "MANIFEST.in").write_text(f"recursive-include zerobin {extensions}")
|
||||||
|
|
||||||
|
|
||||||
|
def task_compress():
|
||||||
|
return {
|
||||||
|
"targets": [
|
||||||
|
str(SOURCE_DIR / "static/js/main.min.js"),
|
||||||
|
str(SOURCE_DIR / "static/css/style.min.css"),
|
||||||
|
],
|
||||||
|
"file_dep": list(str(f) for f in source_files([".css", ".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)),
|
||||||
|
"actions": [task_compress, generate_manifest, "python setup.py bdist_wheel",],
|
||||||
|
}
|
||||||
|
|
@ -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
BIN
screenshot.png
Binary file not shown.
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 41 KiB |
@ -15,7 +15,6 @@ packages = find:
|
|||||||
install_requires =
|
install_requires =
|
||||||
clize==4.1.1
|
clize==4.1.1
|
||||||
lockfile==0.12.2
|
lockfile==0.12.2
|
||||||
sigtools==2.0.2
|
|
||||||
bottle==0.12.18
|
bottle==0.12.18
|
||||||
Beaker==1.11.0
|
Beaker==1.11.0
|
||||||
Paste==3.4.3
|
Paste==3.4.3
|
||||||
|
@ -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
1118
tools/commander.js
File diff suppressed because it is too large
Load Diff
@ -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 )
|
|
51
zerobin/static/css/style.min.css
vendored
51
zerobin/static/css/style.min.css
vendored
File diff suppressed because one or more lines are too long
@ -1,3 +1,10 @@
|
|||||||
from zerobin.routes import get_app
|
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()
|
settings, app = get_app()
|
||||||
|
Loading…
Reference in New Issue
Block a user