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: + + or + +

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