Browse Source

fix handling of plain text and large files

Daniel Sheffield 1 year ago
parent
commit
cf1f3f9741
3 changed files with 30 additions and 13 deletions
  1. 7 2
      app/rest/pyapi.py
  2. 16 8
      app/rest/templates/upload.tpl
  3. 7 3
      app/rest/validate.py

+ 7 - 2
app/rest/pyapi.py

@@ -18,7 +18,7 @@ from psycopg.rows import TupleRow
 from linkpreview import link_preview
 
 from .qr import get_qr_code
-from .validate import get_file_mimetype, get_filename, validate, validate_file, validate_parameter, validate_url
+from .validate import get_file_mimetype, get_file_size, get_filename, validate, validate_file, validate_parameter, validate_url
 from .hash_util import normalize_base32
 from .route_decorators import normalize, poison, cursor
 from .query_to_xml import get_categories, get_groups, get_products, get_tags
@@ -179,8 +179,11 @@ def upload():
         mimetype = None
         if _hash:
             _hash = normalize_base32(_hash)
+            size = get_file_size(_hash)
             name = get_filename(_hash)
             mimetype = get_file_mimetype(name)
+            if mimetype is not True and mimetype.startswith('text'):
+                mimetype = None if size > CLIP_SIZE_LIMIT else mimetype
         
         link = f'{LOCATION}/upload/{_hash}' if _hash else f'{LOCATION}/upload'
         response.content_type = 'text/html; charset=utf-8'
@@ -206,10 +209,12 @@ def upload():
 def get_upload(filename):
     filename = filename and normalize_base32(filename)
     download = True
+    mimetype = True
     if request.params.download == "false":
         download = False
+    mimetype = request.params.mimetype or None
 
-    return validate_file(filename, download=download)
+    return validate_file(filename, download=download, mimetype=mimetype)
 
 
 @route('/goto', method=['GET', 'POST'])

+ 16 - 8
app/rest/templates/upload.tpl

@@ -19,10 +19,18 @@ svg {
   max-height: min(100vh, calc(100vw * 9 / 16));
   max-width: calc(100vw - 2em);
 }
-iframe {
-  color: floralwhite;
-  background: darkgray;
+object {
+  width: 80%;
+  margin: 1em 0 0;
+}
+object.other {
+  height: 60vh;
+}
+object.text {
   height: 60vh;
+  border: floralwhite;
+  border-style: solid;
+  border-width: thin;
 }
     </style>
     <title>Upload</title>
@@ -47,13 +55,13 @@ iframe {
       <div class="pure-u-1">
         <p><details><summary> Show QR code ...</summary>{{!svg}}</details></p>
 {{!form}}
-        <p>
-        % if mimetype and not mimetype.startswith('text'):
-        <embed type="{{mimetype}}" src="{{link}}" width="80%"></embed>
+        % if mimetype and mimetype.startswith('text'):
+        <object class="text" data="{{link}}?download=false&mimetype=text/plain" type={{mimetype}}><p>Unable to display {{mimetype}}</p></object>
+        % elif mimetype and mimetype.startswith('image'):
+        <object data="{{link}}?download=false" type="{{mimetype}}"><p>Unable to display {{mimetype}}</p></object>
         % elif mimetype:
-        <iframe src="{{link}}?download=false" width="80%" height="50%"></iframe>
+        <object class="other" data="{{link}}?download=false" type={{mimetype}}><p>Unable to display {{mimetype}}</p></object>
         % end
-        </p>
       </div>
     </div>
   </body>

+ 7 - 3
app/rest/validate.py

@@ -23,6 +23,7 @@
 from io import BufferedReader
 import mimetypes
 from itertools import chain
+import os
 from bottle import static_file, response, HTTPError, abort, LocalRequest, HTTPResponse
 from urllib.parse import urlparse, quote, quote_plus
 from .hash_util import blake_file, bytes_to_base32, blake
@@ -68,16 +69,19 @@ def get_filename(filename: str, root: str = 'app/rest/static'):
     except:
         pass
 
+def get_file_size(filename: str, root: str = 'app/rest/static'):
+    path = '/'.join([filename,]*2)
+    return os.stat(f'{root}/{path}.file').st_size
+
 def get_file_mimetype(name):
     mimetype = mimetypes.guess_type(name, strict=False)[0] if name else True
     return mimetype
 
-
-def validate_file(filename: str, root: str = 'app/rest/static', download=True) -> HTTPResponse:
+def validate_file(filename: str, root: str = 'app/rest/static', download=True, mimetype=True) -> HTTPResponse:
     path = '/'.join([filename,]*2)
 
     name = get_filename(filename)
-    mimetype = get_file_mimetype(name)
+    mimetype = mimetype if mimetype and mimetype is not True else get_file_mimetype(name)
     
     ret = static_file(f'{path}.file', root=root, download=name if name and download else download, mimetype=mimetype)
     if isinstance(ret, HTTPError):