Browse Source

initial commit

master
dave 1 year ago
commit
6cc6650e15
7 changed files with 177 additions and 0 deletions
  1. +2
    -0
      .dockerignore
  2. +2
    -0
      .gitignore
  3. +15
    -0
      Dockerfile
  4. +10
    -0
      requirements.txt
  5. +25
    -0
      setup.py
  6. +0
    -0
      wastebin/__init__.py
  7. +123
    -0
      wastebin/daemon.py

+ 2
- 0
.dockerignore View File

@@ -0,0 +1,2 @@
/testenv
__pycache__

+ 2
- 0
.gitignore View File

@@ -0,0 +1,2 @@
/testenv
__pycache__

+ 15
- 0
Dockerfile View File

@@ -0,0 +1,15 @@
FROM ubuntu:bionic

ADD . /tmp/code/

RUN apt-get update && \
apt-get install -y python3-pip

RUN pip3 install -U pip && \
cd /tmp/code && \
python3 setup.py install && \
useradd --uid 1000 app

VOLUME /data/

ENTRYPOINT ["wastebind", "-d", "/data/"]

+ 10
- 0
requirements.txt View File

@@ -0,0 +1,10 @@
backports.functools-lru-cache==1.5
cheroot==6.5.4
CherryPy==18.1.0
jaraco.functools==2.0
more-itertools==5.0.0
portend==2.3
pytz==2018.9
six==1.12.0
tempora==1.14
zc.lockfile==1.4

+ 25
- 0
setup.py View File

@@ -0,0 +1,25 @@
#!/usr/bin/env python3

from setuptools import setup
import os


__version__ = "0.0.0"
with open(os.path.join(os.path.dirname(__file__), "requirements.txt")) as f:
__requirements__ = [line.strip() for line in f.readlines()]


setup(name='wastebin',
version=__version__,
description='lazy pastebin',
url='',
author='dpedu',
author_email='dave@davepedu.com',
packages=['wastebin'],
install_requires=__requirements__,
entry_points={
"console_scripts": [
"wastebind = wastebin.daemon:main"
]
},
zip_safe=False)

+ 0
- 0
wastebin/__init__.py View File


+ 123
- 0
wastebin/daemon.py View File

@@ -0,0 +1,123 @@
import os
import cherrypy
import logging
import hashlib
import re


PAGE = """<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Wastebin</title>
</head>
<body>
<form action="/make" method="post">
<textarea name="contents" rows="30" cols="120">{data}</textarea><br />
<input type="text" name="name" placeholder="url name" value="{load}" /><br />
<input type="submit" value="Go">
</form>
</body>
</html>
"""


RE_NAME = re.compile(r'^[a-z0-9_\-/]+$')


def sha256(data):
h = hashlib.sha256()
h.update(data.encode("utf-8"))
return h.hexdigest()


class WasteWeb(object):
def __init__(self, datadir):
self.datadir = datadir

@cherrypy.expose
def index(self, load=None):
data = ""
if load:
assert RE_NAME.match(load)
data = self.loadpaste(load)
yield PAGE.format(data=data.replace("<", "&lt;"), load=load or "")

@cherrypy.expose
def make(self, name, contents):
assert RE_NAME.match(name)
pname = name or sha256(contents)
self.writepaste(pname, contents)
raise cherrypy.HTTPRedirect("/" + pname)

@cherrypy.expose
def default(self, *args):
data = self.loadpaste(args[0])
yield data

def loadpaste(self, name):
path = self.pastepath(sha256(name))
with open(path) as f:
f.readline() # the name
return f.read()

def writepaste(self, name, contents):
hname = sha256(name)
path = self.pastepath(hname)
os.makedirs(os.path.dirname(path), exist_ok=True)
with open(path, "w") as f:
f.write(name)
f.write("\n")
f.write(contents)

def pastepath(self, hashedname):
return os.path.join(self.datadir, hashedname[0], hashedname[1], hashedname + ".txt")


def main():
import argparse
import signal

parser = argparse.ArgumentParser(description="")

parser.add_argument('-p', '--port', default=8080, type=int, help="http port")
parser.add_argument('-d', '--data', default="./", help="data dir")
parser.add_argument('--debug', action="store_true", help="enable development options")

args = parser.parse_args()

logging.basicConfig(level=logging.INFO if args.debug else logging.WARNING,
format="%(asctime)-15s %(levelname)-8s %(filename)s:%(lineno)d %(message)s")

web = WasteWeb(args.data)

cherrypy.tree.mount(web, '/', {'/': {'tools.trailing_slash.on': False}})

cherrypy.config.update({
'tools.sessions.on': False,
'request.show_tracebacks': True,
'server.socket_port': args.port,
'server.thread_pool': 5,
'server.socket_host': '0.0.0.0',
'server.show_tracebacks': args.debug,
'log.screen': False,
'engine.autoreload.on': args.debug
})

def signal_handler(signum, stack):
logging.critical('Got sig {}, exiting...'.format(signum))
cherrypy.engine.exit()

signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)

try:
cherrypy.engine.start()
cherrypy.engine.block()
finally:
logging.info("API has shut down")
cherrypy.engine.exit()


if __name__ == '__main__':
main()

Loading…
Cancel
Save