summaryrefslogtreecommitdiff
path: root/fbin.py
diff options
context:
space:
mode:
authorJon Bergli Heier <snakebite@jvnv.net>2011-02-15 23:04:18 +0100
committerJon Bergli Heier <snakebite@jvnv.net>2011-02-15 23:04:18 +0100
commit4989a8e572ea666d3e392a503ee6831b8a9386f9 (patch)
treef1cf0bf4e6744acb45ad3cbd15023916762ecf37 /fbin.py
Initial commit.
Diffstat (limited to 'fbin.py')
-rwxr-xr-xfbin.py267
1 files changed, 267 insertions, 0 deletions
diff --git a/fbin.py b/fbin.py
new file mode 100755
index 0000000..9a1a4df
--- /dev/null
+++ b/fbin.py
@@ -0,0 +1,267 @@
+#!/usr/bin/env python2
+
+import templates
+import settings, db, os, random, datetime, shutil, mimetypes, cgi, tempfile, hashlib, Cookie
+
+base62_alphabet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
+
+if not os.path.isdir(settings.file_directory):
+ os.mkdir(settings.file_directory)
+
+class Application(object):
+ def get_user(self, username, password):
+ session = db.Session()
+ try:
+ user = session.query(db.User).filter(db.and_(db.User.username == username, db.User.password == password)).one()
+ except db.NoResultFound:
+ return None
+ finally:
+ session.close()
+
+ return user
+
+ def add_user(self, username, password):
+ session = db.Session()
+ try:
+ user = db.User(username, password)
+ session.add(user)
+ session.commit()
+ except db.IntegrityError:
+ return None
+ finally:
+ session.close()
+
+ return user
+
+ def get_file_path(self, hash):
+ session = db.Session()
+ try:
+ file = session.query(db.File).filter(db.File.hash == hash).one()
+ except db.NoResultFound:
+ return None
+ finally:
+ session.close()
+
+ return os.path.join(settings.file_directory, hash + os.path.splitext(file.filename)[1])
+
+ def add_file(self, path, filename, user = None):
+ hash = ''.join(random.choice(base62_alphabet) for x in xrange(5))
+ new_path = os.path.join(settings.file_directory, hash + os.path.splitext(filename)[1])
+ shutil.copyfile(path, new_path)
+
+ session = db.Session()
+ try:
+ file = db.File(hash, filename, datetime.datetime.utcnow(), user.id if user else None)
+ session.add(file)
+ session.commit()
+ finally:
+ session.close()
+
+ return hash
+
+ def get_files(self, user):
+ session = db.Session()
+ try:
+ session.add(user)
+ files = user.files
+ except db.NoResultFound:
+ return []
+ finally:
+ session.close()
+
+ return files
+
+ def validate_cookie(self, cookie):
+ if not cookie:
+ return None
+ uid = int(cookie['uid'].value)
+ identifier = cookie['identifier'].value
+
+ session = db.Session()
+ try:
+ user = session.query(db.User).filter(db.User.id == uid).one()
+ except db.NoResultFound:
+ return None
+ finally:
+ session.close()
+
+ digest = hashlib.md5(str(uid) + user.password).hexdigest()
+ return user if (digest == identifier) else None
+
+ def file(self, environ, start_response, path):
+ hash = path[1]
+ filename = self.get_file_path(hash)
+ if filename == None:
+ start_response('404 Not Found', [('Content-Type', 'text/html')])
+ return ['<h1>Not Found</h1><p>The file you requested does not exist.</p>']
+
+ mime = mimetypes.guess_type(filename, strict = False)[0] or 'application/octet-stream'
+
+ start_response('200 OK', [('Content-Type', mime), ('Content-Length', str(os.path.getsize(filename)))])
+ return open(filename, 'rb')
+
+ def upload(self, environ, start_response, path):
+ c = Cookie.SimpleCookie(environ['HTTP_COOKIE'] if 'HTTP_COOKIE' in environ else None)
+ user = self.validate_cookie(c)
+ form = cgi.FieldStorage(fp = environ['wsgi.input'], environ = environ)
+ if environ['REQUEST_METHOD'] != 'POST' or not 'file' in form or not 'filename' in form:
+ start_response('200 OK', [('Content-Type', 'text/html')])
+ return str(templates.upload(searchList = {'user': user}))
+
+ filename = form.getvalue('filename')
+
+ temp = tempfile.NamedTemporaryFile(mode = 'wb', prefix = 'fbin', delete = True)
+ temp.write(form.getvalue('file'))
+ temp.flush()
+
+ hash = self.add_file(temp.name, filename, user)
+
+ temp.close()
+
+ if 'redir' in form:
+ start_response('302 Found', [('Content-Type', 'text/html'), ('Location', '/f/{0}/{1}'.format(hash, filename))])
+ return ['<a href="/f/{0}/{1}">{1}</a>'.format(hash, filename)]
+ else:
+ start_response('200 OK', [('Content-Type', 'text/html')])
+ return str(templates.uploaded(searchList = {
+ 'user': user,
+ 'hash': hash,
+ 'filename': filename,
+ 'scheme': environ['wsgi.url_scheme'],
+ 'host': environ['HTTP_HOST'],
+ }))
+
+ def login(self, environ, start_response, path):
+ c = Cookie.SimpleCookie(environ['HTTP_COOKIE'] if 'HTTP_COOKIE' in environ else None)
+ user = self.validate_cookie(c)
+ form = cgi.FieldStorage(fp = environ['wsgi.input'], environ = environ)
+ if environ['REQUEST_METHOD'] != 'POST' or not 'username' in form or not 'password' in form:
+ start_response('200 OK', [('Content-Type', 'text/html')])
+ return str(templates.login(searchList = {
+ 'user': user,
+ 'error': None,
+ }))
+
+ username = form.getvalue('username')
+ password = hashlib.md5(form.getvalue('password')).hexdigest()
+
+ user = self.get_user(username, password)
+
+ if user == None:
+ start_response('200 OK', [('Content-Type', 'text/html')])
+ return str(templates.login(searchList = {
+ 'user': user,
+ 'error': 'Login failed',
+ }))
+
+ c = Cookie.SimpleCookie()
+ c['uid'] = user.id
+ c['identifier'] = hashlib.md5(str(user.id) + password).hexdigest()
+
+ dt = datetime.datetime.utcnow() + datetime.timedelta(days = 30)
+ expires = dt.strftime('%a, %d-%b-%y %H:%M:%S GMT')
+ c['uid']['expires'] = expires
+ c['identifier']['expires'] = expires
+
+ start_response('302 Found', [('Location', '/u'), ('Set-Cookie', c['uid'].OutputString()), ('Set-Cookie', c['identifier'].OutputString())])
+ return []
+
+ def register(self, environ, start_response, path):
+ c = Cookie.SimpleCookie(environ['HTTP_COOKIE'] if 'HTTP_COOKIE' in environ else None)
+ user = self.validate_cookie(c)
+ form = cgi.FieldStorage(fp = environ['wsgi.input'], environ = environ)
+ if environ['REQUEST_METHOD'] != 'POST' or not 'username' in form or not 'password' in form or not 'password2' in form:
+ start_response('200 OK', [('Content-Type', 'text/html')])
+ return str(templates.register(searchList = {
+ 'user': user,
+ 'error': None,
+ }))
+
+ username = form.getvalue('username')
+ password = form.getvalue('password')
+ password2 = form.getvalue('password2')
+ if password != password2:
+ start_response('200 OK', [('Content-Type', 'text/html')])
+ return str(templates.register(searchList = {
+ 'user': user,
+ 'error': 'Passwords doesn\'t match',
+ }))
+
+ user = self.add_user(username, hashlib.md5(password).hexdigest())
+ if not user:
+ start_response('200 OK', [('Content-Type', 'text/html')])
+ return str(templates.register(searchList = {
+ 'user': None,
+ 'error': 'Username already taken.',
+ }))
+
+ start_response('302 Found', [('Location', '/l')])
+ return []
+
+ def logout(self, environ, start_response, path):
+ c = Cookie.SimpleCookie()
+ expires = datetime.datetime.utcfromtimestamp(0).strftime('%a, %d-%b-%y %H:%M:%S GMT')
+ c['uid'] = 0
+ c['uid']['expires'] = expires
+ c['identifier'] = ''
+ c['identifier']['expires'] = expires
+ start_response('302 Found', [('Set-Cookie', c['uid'].OutputString()), ('Set-Cookie', c['identifier'].OutputString()), ('Location', '/')])
+ return []
+
+ def static(self, environ, start_response, path):
+ filename = path[1]
+ if not filename in ('style.css',):
+ start_response('404 Not Found', [])
+ return []
+
+ mime = mimetypes.guess_type(filename, strict = False)[0] or 'application/octet-stream'
+ start_response('200 OK', [('Content-Type', mime)])
+ return open('static/' + filename, 'rb')
+
+ def help(self, environ, start_response, path):
+ c = Cookie.SimpleCookie(environ['HTTP_COOKIE'] if 'HTTP_COOKIE' in environ else None)
+ user = self.validate_cookie(c)
+ start_response('200 OK', [('Content-Type', 'text/html')])
+ return str(templates.help(searchList = {
+ 'user': user,
+ 'scheme': environ['wsgi.url_scheme'],
+ 'host': environ['HTTP_HOST'],
+ }))
+
+ def my_files(self, environ, start_response, path):
+ c = Cookie.SimpleCookie(environ['HTTP_COOKIE'] if 'HTTP_COOKIE' in environ else None)
+ user = self.validate_cookie(c)
+ if user == None:
+ start_response('200 OK', [('Content-Type', 'text/html')])
+ return ['Not logged in.']
+ files = self.get_files(user)
+ start_response('200 OK', [('Content-Type', 'text/html')])
+ return str(templates.my(searchList = {
+ 'user': user,
+ 'files': files,
+ }))
+
+ f = file
+ u = upload
+ l = login
+ s = static
+ h = help
+ m = my_files
+ o = logout
+ r = register
+
+ def __call__(self, environ, start_response):
+ path = environ['PATH_INFO'].split('/')[1:]
+ module = path[0]
+ if len(module) and module in 'fulshmor':
+ return getattr(self, module)(environ, start_response, path)
+ else:
+ start_response('302 Found', [('Location', '/u')])
+ return []
+
+if __name__ == '__main__':
+ from wsgiref.simple_server import make_server, WSGIServer
+ # enable IPv6
+ WSGIServer.address_family |= 10
+ http = make_server('', 8000, Application())
+ http.serve_forever()