Browse Source

restore original file name on download

Daniel Sheffield 1 year ago
parent
commit
96c5e695cd
4 changed files with 23 additions and 11 deletions
  1. 8 1
      app/rest/pyapi.py
  2. 7 5
      app/rest/save.py
  3. 1 1
      app/rest/templates/file-form.tpl
  4. 7 4
      app/rest/validate.py

+ 8 - 1
app/rest/pyapi.py

@@ -4,6 +4,7 @@
 #
 # THIS SOFTWARE IS PROVIDED AS IS WITHOUT WARRANTY
 
+from io import BytesIO
 from threading import Thread
 from typing import Union
 from bottle import (
@@ -22,6 +23,7 @@ from .query_to_xml import get_categories, get_groups, get_products, get_tags
 from .CachedLoadingPage import CachedLoadingPage
 from .Cache import Cache
 from . import trend as worker
+from .save import save, save_upload
 
 host = f"host={os.getenv('HOST')}"
 db = f"dbname={os.getenv('DB', 'grocery')}"
@@ -177,7 +179,12 @@ def upload():
         if 'paste' not in request.files:
             return abort(400, "Parameter 'paste' must be specified")
         
-        _b32 = save_upload(request.files['paste'].file)
+        upload = request.files['paste']
+        if isinstance(upload.file, BytesIO):
+            if len(upload.file.read()) == 0:
+                return abort(400, "File is empty")
+
+        _b32 = save_upload(upload.raw_filename , upload.file, root='app/rest/static')
         return redirect(f'/upload?hash={_b32}')
 
 

+ 7 - 5
app/rest/save.py

@@ -24,12 +24,13 @@ def save(content: bytes, root='app/rest/static') -> str:
         f.write(content)
     return _b32
 
-def save_upload(content: BufferedRandom, root='app/rest/static') -> str:
+def save_upload(name: str, content: BufferedRandom, root='app/rest/static') -> str:
     tmpdir = '/tmp/upload'
     try:
         os.mkdir(tmpdir, mode=0o700, dir_fd=None)
     except FileExistsError:
         pass
+    
     unique = uuid4()
     fd = os.open(f'{tmpdir}/{unique.hex}', os.O_WRONLY | os.O_TRUNC | os.O_CREAT, 0o600)
     with open(fd, "wb") as f:
@@ -37,9 +38,7 @@ def save_upload(content: BufferedRandom, root='app/rest/static') -> str:
             seg = content.read(1024)
             f.write(seg)
     
-    fd = os.open(f'{tmpdir}/{unique.hex}', os.O_RDONLY, 0o600)
-    with open(fd, "rb") as f:
-        f.seek(0)
+    with open(f'{tmpdir}/{unique.hex}', "rb") as f:
         _blake = blake2b(usedforsecurity=False, digest_size=DIGEST_SIZE_BYTES, person='upload'.encode('utf-8'))
         while f.peek(1):
             _blake.update(f.read(1024))
@@ -54,6 +53,9 @@ def save_upload(content: BufferedRandom, root='app/rest/static') -> str:
         pass
 
     os.replace(f'{tmpdir}/{unique.hex}', f'{directory}/{_b32}.file')
-    
+    fd = os.open(f'{directory}/{_b32}.name', os.O_WRONLY | os.O_TRUNC | os.O_CREAT, 0o600)
+    with open(fd, "w") as f:
+        f.write(name)
+
     return _b32
 

+ 1 - 1
app/rest/templates/file-form.tpl

@@ -2,5 +2,5 @@
 % content = setdefault("content", "") or ""
 % disabled = (setdefault("disabled", False) and 'readonly="true"') or ""
 <form id="upload" method="{{ method }}" action="{{ action }}" enctype="multipart/form-data">
-  <input type="file" name="paste" />
+  <input type="file" name="paste" required="true" />
 </form>

+ 7 - 4
app/rest/validate.py

@@ -57,13 +57,16 @@ def validate(filename: str) -> bytes:
         return abort(410, f"Paste content differs")
     return content
 
-def validate_file(filename: str) -> HTTPResponse:
-    # TODO: restore original filename
-    ret = static_file('/'.join([filename,]*2) + '.file', root='app/rest/static', download=filename)
+def validate_file(filename: str, root: str = 'app/rest/static') -> HTTPResponse:
+    path = '/'.join([filename,]*2)
+    with open(f'{root}/{path}.name', "r") as f:
+        name = f.read()
+    
+    ret = static_file(f'{path}.file', root=root, download=name)
     if isinstance(ret, HTTPError):
         return abort(404, f"No such upload: {filename}")
 
-    _bytes = blake_file('/'.join([filename,]*2) + '.file', person='upload'.encode('utf-8'), root='app/rest/static')
+    _bytes = blake_file(f'{path}.file', person='upload'.encode('utf-8'), root=root)
     _b32 = bytes_to_base32(_bytes)
     if _b32 != filename:
         return abort(410, f"Uploaded content differs")