From 7a5d729859a2f667658532303c2616a38f781dd2 Mon Sep 17 00:00:00 2001
From: Jon Bergli Heier
Date: Sat, 26 Feb 2011 22:39:22 +0100
Subject: Added some requests, more details in long description.
- Files are now hashed, when you upload a file with an existing hash
you will get the existing file in return (will fix adding files to
your account at a later time).
- Username can be used instead of uid for cookies, hashing for the
identifier works the same way as before, but with username instead of
uid if username is used.
- Add api=1 to get machine-readable responses, details in are found on
the help page.
---
.gitignore | 2 +-
db.py | 4 +++-
fbin.py | 65 ++++++++++++++++++++++++++++++++++++++++++++---------
static/style.css | 3 ++-
templates/help.tmpl | 18 ++++++++++++---
5 files changed, 75 insertions(+), 17 deletions(-)
diff --git a/.gitignore b/.gitignore
index 418bb19..11f02b8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,4 @@
*.swp
*.pyc
settings.py
-/images
+/files
diff --git a/db.py b/db.py
index 762fc07..1deb196 100644
--- a/db.py
+++ b/db.py
@@ -27,12 +27,14 @@ class File(Base):
id = Column(Integer, primary_key = True)
hash = Column(String, unique = True, index = True)
+ file_hash = Column(String, unique = True, index = True)
filename = Column(String)
date = Column(DateTime)
user_id = Column(Integer, ForeignKey('users.id'), nullable = True)
- def __init__(self, hash, filename, date, user_id = None):
+ def __init__(self, hash, file_hash, filename, date, user_id = None):
self.hash = hash
+ self.file_hash = file_hash
self.filename = filename
self.date = date
self.user_id = user_id
diff --git a/fbin.py b/fbin.py
index 39ae6d8..3d1c2e5 100755
--- a/fbin.py
+++ b/fbin.py
@@ -20,6 +20,24 @@ class Application(object):
return user
+ def get_user_by_name(self, username):
+ session = db.Session()
+ try:
+ return session.query(db.User).filter(db.User.username == username).one()
+ except db.NoResultFound:
+ return None
+ finally:
+ session.close()
+
+ def get_user_by_id(self, uid):
+ session = db.Session()
+ try:
+ return session.query(db.User).filter(db.User.id == uid).one()
+ except db.NoResultFound:
+ return None
+ finally:
+ session.close()
+
def add_user(self, username, password):
session = db.Session()
try:
@@ -44,14 +62,14 @@ class Application(object):
return os.path.join(settings.file_directory, hash + os.path.splitext(file.filename)[1])
- def add_file(self, path, filename, user = None):
+ def add_file(self, path, filename, file_hash, 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)
+ file = db.File(hash, file_hash, filename, datetime.datetime.utcnow(), user.id if user else None)
session.add(file)
session.commit()
finally:
@@ -74,20 +92,32 @@ class Application(object):
def validate_cookie(self, cookie):
if not cookie:
return None
- uid = int(cookie['uid'].value)
+
identifier = cookie['identifier'].value
+ if 'username' in cookie:
+ user = self.get_user_by_name(cookie['username'].value)
+ 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
+
+ digest = hashlib.sha1(str(user.id) + user.password).hexdigest()
+ return user if (digest == identifier) else None
+
+ def get_file_by_file_hash(self, file_hash):
session = db.Session()
try:
- user = session.query(db.User).filter(db.User.id == uid).one()
+ return session.query(db.File).filter(db.File.file_hash == file_hash).one()
except db.NoResultFound:
return None
finally:
session.close()
- digest = hashlib.sha1(str(uid) + user.password).hexdigest()
- return user if (digest == identifier) else None
-
def file(self, environ, start_response, path):
hash = path[1]
if '.' in hash:
@@ -116,13 +146,26 @@ class Application(object):
temp.write(form.getvalue('file'))
temp.flush()
- hash = self.add_file(temp.name, filename, user)
+ m = hashlib.md5()
+ with open(temp.name) as f:
+ s = f.read(128)
+ while len(s):
+ m.update(s)
+ s = f.read(128)
+ file_hash = m.hexdigest()
+
+ f = self.get_file_by_file_hash(file_hash)
+ # TODO: Currently users uploading existing files won't get their files added to their account.
+ if f:
+ hash = f.hash
+ else:
+ hash = self.add_file(temp.name, filename, file_hash, 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)]
+ if 'api' in form:
+ start_response('200 OK', [('Content-Type', 'text/plain')])
+ return ['OK {hash}'.format(hash = hash)]
else:
start_response('200 OK', [('Content-Type', 'text/html')])
return str(templates.uploaded(searchList = {
diff --git a/static/style.css b/static/style.css
index f281482..e16b5b7 100644
--- a/static/style.css
+++ b/static/style.css
@@ -9,7 +9,8 @@ div#page-footer { background-color: #333; color: #666; height: 1em; padding: .5e
ul { list-style-type: none; }
li { margin-left: 1em; }
p { margin-bottom: 1em; }
-code { font-family: monospace; margin: 1em; display: block; }
+code { font-family: monospace; }
+blockquote { margin: 1em; display: block; }
.error { color: red; }
diff --git a/templates/help.tmpl b/templates/help.tmpl
index 5dc096f..bdf95d4 100644
--- a/templates/help.tmpl
+++ b/templates/help.tmpl
@@ -3,9 +3,21 @@
#extends templates.base
#def content
Usage: POST to $scheme://$host/u with filedata given to "file" and original filename to "filename".
- Login is sent by cookies with user id in "uid" and an identifier which is sha1(uid+sha1(password)).
+ Login is sent by cookies with either:
+
+ - user id in "uid" and an identifier which is sha1(uid+sha1(password))
+
+ or
+
+ - username in "username" and an identifier which is sha1(username+sha1(password))
+
+
cURL example:
- curl -b 'uid=42; identifier=360b411581c3d516c8d55c290f039b144cea79ad' -F 'file=@image.png' -F 'filename=image.png' http://myhost/u
+
curl -b 'uid=42; identifier=360b411581c3d516c8d55c290f039b144cea79ad' -F 'file=@image.png' -F 'filename=image.png' -F 'api=1' http://myhost/u
Here user id is 42 and the password is "foobar".
- If you get HTTP 417 responses, try adding:-H 'Expect:'
+ If you get HTTP 417 responses, try adding:-H 'Expect:'
.
+ By adding the key-value pair "api=1" you will get machine-readable responses in the form: response result
where response
is either ERROR
or OK
,
+ and result
is the file hash in the case of OK
, or an error message in the case of ERROR
.
+ The hash can be used to construct URLs in which the paths begin with /f/hash
where hash
is the hash received.
+ Any file extension an be appended to the hash, and for convenience the original filename (or whatever filename you prefer) can be appended after an additional slash after the hash.
#end def
--
cgit v1.2.3