summaryrefslogtreecommitdiff
path: root/fbin.py
diff options
context:
space:
mode:
Diffstat (limited to 'fbin.py')
-rwxr-xr-xfbin.py122
1 files changed, 85 insertions, 37 deletions
diff --git a/fbin.py b/fbin.py
index 51d3203..1d70712 100755
--- a/fbin.py
+++ b/fbin.py
@@ -22,6 +22,10 @@ except OSError:
else:
has_mogrify = True
+class BinError(Exception): pass
+class InvalidCookieError(BinError): pass
+class InactiveLoginError(BinError): pass
+
class FileUploadFieldStorage(cgi.FieldStorage):
def make_file(self, binary = None):
# Make a temporary file in the destination directory, which will be renamed on completion.
@@ -57,10 +61,10 @@ class Application(object):
finally:
session.close()
- def add_user(self, username, password):
+ def add_user(self, username, password, active):
session = db.Session()
try:
- user = db.User(username, password)
+ user = db.User(username, password, active)
session.add(user)
session.commit()
except db.IntegrityError:
@@ -81,6 +85,18 @@ class Application(object):
finally:
session.close()
+ def update_user_login(self, user, login_time = None):
+ if login_time is None:
+ login_time = datetime.datetime.utcnow()
+ session = db.Session()
+ try:
+ user.last_login = login_time
+ session.add(user)
+ session.commit()
+ session.refresh(user)
+ finally:
+ session.close()
+
def get_file(self, hash, update_accessed = False):
session = db.Session()
try:
@@ -137,14 +153,17 @@ class Application(object):
if not user:
return None
digest = hashlib.sha1(user.username + user.password).hexdigest()
- return user if (digest == identifier) else None
-
- user = self.get_user_by_id(cookie['uid'].value)
- if not user:
- return None
+ else:
+ user = self.get_user_by_id(cookie['uid'].value)
+ if not user:
+ return None
+ digest = hashlib.sha1(str(user.id) + user.password).hexdigest()
- digest = hashlib.sha1(str(user.id) + user.password).hexdigest()
- return user if (digest == identifier) else None
+ if digest != identifier:
+ raise InvalidCookieError(user.username)
+ if not user.active:
+ raise InactiveLoginError(user.username)
+ return user
def get_file_by_file_hash(self, file_hash):
session = db.Session()
@@ -166,6 +185,10 @@ class Application(object):
finally:
session.close()
+ def redirect(self, environ, start_response, dest):
+ start_response('302 Found', [('Location', settings.virtual_root + dest)])
+ return []
+
def not_modified(self, environ, date):
if not 'HTTP_IF_MODIFIED_SINCE' in environ:
return False
@@ -246,8 +269,16 @@ class Application(object):
if environ['REQUEST_METHOD'] != 'POST' or not 'file' in form or not 'filename' in form:
if 'file' in form:
form['file'].file.delete = True
- start_response('200 OK', [('Content-Type', 'text/html')])
- return str(templates.upload(searchList = {'root': settings.virtual_root, 'user': user}))
+ if settings.allow_anonymous_uploads:
+ start_response('200 OK', [('Content-Type', 'text/html')])
+ return str(templates.upload(searchList = {'settings': settings, 'user': user}))
+ else:
+ return self.redirect(environ, start_response, 'l')
+
+ if not user and not settings.allow_anonymous_uploads:
+ form['file'].file.delete = True
+ start_response('403 Forbidden', [('Content-Type', 'text/plain')])
+ return ['Anonymous uploads are disabled by the administrator.']
filename = form.getvalue('filename')
temp = form['file'].file
@@ -295,7 +326,7 @@ class Application(object):
else:
start_response('200 OK', [('Content-Type', 'text/html')])
return str(templates.uploaded(searchList = {
- 'root': settings.virtual_root,
+ 'settings': settings,
'user': user,
'hash': hash,
'filename': filename,
@@ -312,7 +343,7 @@ class Application(object):
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 = {
- 'root': settings.virtual_root,
+ 'settings': settings,
'user': user,
'error': None,
'next': next,
@@ -323,15 +354,24 @@ class Application(object):
user = self.get_user(username, password)
+ error = None
if user == None:
+ error = 'Login failed'
+ elif not user.active:
+ user = None
+ error = 'User account is not active'
+
+ if error:
start_response('200 OK', [('Content-Type', 'text/html')])
return str(templates.login(searchList = {
- 'root': settings.virtual_root,
+ 'settings': settings,
'user': user,
- 'error': 'Login failed',
+ 'error': error,
'next': next,
}))
+ self.update_user_login(user)
+
c = Cookie.SimpleCookie()
c['uid'] = user.id
c['identifier'] = hashlib.sha1(str(user.id) + password).hexdigest()
@@ -348,13 +388,17 @@ class Application(object):
return []
def register(self, environ, start_response, path):
+ if not settings.allow_registration:
+ start_response('403 Forbidden', [('Content-Type', 'text/plain')])
+ return ['Registrations are disabled by the administrator.']
+
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 = {
- 'root': settings.virtual_root,
+ 'settings': settings,
'user': user,
'error': None,
}))
@@ -365,22 +409,21 @@ class Application(object):
if password != password2:
start_response('200 OK', [('Content-Type', 'text/html')])
return str(templates.register(searchList = {
- 'root': settings.virtual_root,
+ 'settings': settings,
'user': user,
'error': 'Passwords doesn\'t match',
}))
- user = self.add_user(username, hashlib.sha1(password).hexdigest())
+ user = self.add_user(username, hashlib.sha1(password).hexdigest(), settings.create_active_users)
if not user:
start_response('200 OK', [('Content-Type', 'text/html')])
return str(templates.register(searchList = {
- 'root': settings.virtual_root,
+ 'settings': settings,
'user': None,
'error': 'Username already taken.',
}))
- start_response('302 Found', [('Location', settings.virtual_root + 'l')])
- return []
+ return self.redirect(environ, start_response, 'l')
def logout(self, environ, start_response, path):
c = Cookie.SimpleCookie()
@@ -398,11 +441,13 @@ class Application(object):
def changepass(self, environ, start_response, path):
c = Cookie.SimpleCookie(environ['HTTP_COOKIE'] if 'HTTP_COOKIE' in environ else None)
user = self.validate_cookie(c)
+ if not user:
+ return self.redirect(environ, start_response, 'l?' + urllib.urlencode({'next': settings.virtual_root + 'c'}))
form = cgi.FieldStorage(fp = environ['wsgi.input'], environ = environ)
if environ['REQUEST_METHOD'] != 'POST' or not 'oldpass' in form or not 'password' in form or not 'password2' in form:
start_response('200 OK', [('Content-Type', 'text/html')])
return str(templates.changepass(searchList = {
- 'root': settings.virtual_root,
+ 'settings': settings,
'user': user,
'error': None,
}))
@@ -414,7 +459,7 @@ class Application(object):
if oldpass != user.password:
start_response('200 OK', [('Content-Type', 'text/html')])
return str(templates.changepass(searchList = {
- 'root': settings.virtual_root,
+ 'settings': settings,
'user': user,
'error': 'Invalid password.',
}))
@@ -422,7 +467,7 @@ class Application(object):
if password != password2:
start_response('200 OK', [('Content-Type', 'text/html')])
return str(templates.changepass(searchList = {
- 'root': settings.virtual_root,
+ 'settings': settings,
'user': user,
'error': 'Passwords doesn\'t match.',
}))
@@ -460,7 +505,7 @@ class Application(object):
user = self.validate_cookie(c)
start_response('200 OK', [('Content-Type', 'text/html')])
return str(templates.help(searchList = {
- 'root': settings.virtual_root,
+ 'settings': settings,
'user': user,
'scheme': environ['wsgi.url_scheme'],
'host': environ['HTTP_HOST'],
@@ -475,7 +520,7 @@ class Application(object):
files = self.get_files(user)
start_response('200 OK', [('Content-Type', 'text/html')])
return str(templates.my(searchList = {
- 'root': settings.virtual_root,
+ 'settings': settings,
'user': user,
'files': files,
'total_size': db.File.pretty_size(sum([f.get_size() for f in files])),
@@ -490,7 +535,7 @@ class Application(object):
files = [f for f in self.get_files(user) if f.is_image()]
start_response('200 OK', [('Content-Type', 'text/html')])
return str(templates.images(searchList = {
- 'root': settings.virtual_root,
+ 'settings': settings,
'user': user,
'files': files,
'total_size': db.File.pretty_size(sum([f.get_size() for f in files])),
@@ -539,7 +584,7 @@ class Application(object):
else:
start_response('200 OK', [('Content-Type', 'text/html')])
return str(templates.delete(searchList = {
- 'root': settings.virtual_root,
+ 'settings': settings,
'user': user,
'hash': hash,
'filename': file.filename,
@@ -586,15 +631,18 @@ class Application(object):
a = api
def __call__(self, environ, start_response):
- path = environ['PATH_INFO'].split('/')[1:]
- module = path[0] if len(path) else ''
- if len(module) and module in 'fulshmitorcda':
- return getattr(self, module)(environ, start_response, path)
- elif path == ['favicon.ico']:
- return self.static(environ, start_response, ['s'] + path)
- else:
- start_response('302 Found', [('Location', settings.virtual_root + 'u')])
- return []
+ try:
+ path = environ['PATH_INFO'].split('/')[1:]
+ module = path[0] if len(path) else ''
+ if len(module) and module in 'fulshmitorcda':
+ return getattr(self, module)(environ, start_response, path)
+ elif path == ['favicon.ico']:
+ return self.static(environ, start_response, ['s'] + path)
+ else:
+ start_response('302 Found', [('Location', settings.virtual_root + 'u')])
+ return []
+ except (InactiveLoginError, InvalidCookieError):
+ return self.logout(environ, start_response, path)
if __name__ == '__main__':
import sys