From 4989a8e572ea666d3e392a503ee6831b8a9386f9 Mon Sep 17 00:00:00 2001 From: Jon Bergli Heier Date: Tue, 15 Feb 2011 23:04:18 +0100 Subject: Initial commit. --- fbin.py | 267 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 267 insertions(+) create mode 100755 fbin.py (limited to 'fbin.py') 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 ['

Not Found

The file you requested does not exist.

'] + + 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 ['{1}'.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() -- cgit v1.2.3