summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--db.py4
-rwxr-xr-xfbin.py65
-rw-r--r--static/style.css3
-rw-r--r--templates/help.tmpl18
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 ['<a href="/f/{0}/{1}">{1}</a>'.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
<p>Usage: POST to <a href="$scheme://$host/u">$scheme://$host/u</a> 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)).</p>
+ Login is sent by cookies with either:
+ <ul>
+ <li>user id in "uid" and an identifier which is sha1(uid+sha1(password))</li>
+ </ul>
+ or
+ <ul>
+ <li>username in "username" and an identifier which is sha1(username+sha1(password))</li>
+ </ul>
+ </p>
<p>cURL example:
- <code>curl -b 'uid=42; identifier=360b411581c3d516c8d55c290f039b144cea79ad' -F 'file=@image.png' -F 'filename=image.png' http://myhost/u</code>
+ <blockquote><code>curl -b 'uid=42; identifier=360b411581c3d516c8d55c290f039b144cea79ad' -F 'file=@image.png' -F 'filename=image.png' -F 'api=1' http://myhost/u</code></blockquote>
Here user id is 42 and the password is "foobar".
- If you get HTTP 417 responses, try adding:<code>-H 'Expect:'</code></p>
+ If you get HTTP 417 responses, try adding:<code>-H 'Expect:'</code>.</p>
+ <p>By adding the key-value pair "api=1" you will get machine-readable responses in the form: <code>response result</code> where <code>response</code> is either <code>ERROR</code> or <code>OK</code>,
+ and <code>result</code> is the file hash in the case of <code>OK</code>, or an error message in the case of <code>ERROR</code>.
+ The hash can be used to construct URLs in which the paths begin with <code>/f/hash</code> where <code>hash</code> is the hash received.</p>
+ <p>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.</p>
#end def