From 360ca1941c0df71a2472fa9b1a3f3df1c12c42b3 Mon Sep 17 00:00:00 2001 From: Taka Date: Wed, 19 Dec 2018 15:51:26 +0000 Subject: [PATCH] Allow user files to be included in snippets. --- vasl_templates/webapp/files.py | 54 +++-- vasl_templates/webapp/static/snippets.js | 3 + .../fixtures/user-files/amp=& ; plus=+.txt | 1 + .../tests/fixtures/user-files/hello.txt | 1 + .../user-files/subdir/placeholder.png | Bin 0 -> 1339 bytes vasl_templates/webapp/tests/remote.py | 13 ++ vasl_templates/webapp/tests/test_files.py | 198 ++++++++++++++++-- vasl_templates/webapp/tests/utils.py | 3 +- vasl_templates/webapp/vo_notes.py | 25 +-- 9 files changed, 260 insertions(+), 38 deletions(-) create mode 100644 vasl_templates/webapp/tests/fixtures/user-files/amp=& ; plus=+.txt create mode 100644 vasl_templates/webapp/tests/fixtures/user-files/hello.txt create mode 100644 vasl_templates/webapp/tests/fixtures/user-files/subdir/placeholder.png diff --git a/vasl_templates/webapp/files.py b/vasl_templates/webapp/files.py index e285e5a..7b606de 100644 --- a/vasl_templates/webapp/files.py +++ b/vasl_templates/webapp/files.py @@ -2,8 +2,11 @@ import os import io +import urllib.request +import urllib.parse +import mimetypes -from flask import send_file, jsonify, redirect, url_for, abort +from flask import send_file, send_from_directory, jsonify, redirect, url_for, abort from vasl_templates.webapp import app from vasl_templates.webapp.file_server.vasl_mod import VaslMod @@ -19,20 +22,45 @@ class FileServer: """Serve static files.""" def __init__( self, base_dir ): - self.base_dir = os.path.abspath( base_dir ) + if FileServer.is_remote_path( base_dir ): + self.base_dir = base_dir + else: + self.base_dir = os.path.abspath( base_dir ) - def get_file( self, fname ): + def serve_file( self, path ): """Serve a file.""" - if not fname: - return None - fname = os.path.join( self.base_dir, fname ) - fname = os.path.abspath( fname ) - if not os.path.isfile( fname ): - return None - prefix = os.path.commonpath( [ self.base_dir, fname ] ) - if prefix != self.base_dir: - return None # nb: files must be sub-ordinate to the configured directory - return fname + if FileServer.is_remote_path( self.base_dir ): + url = "{}/{}".format( self.base_dir, path ) + # NOTE: We download the target file and serve it ourself (instead of just redirecting) + # since VASSAL can't handle SSL :-/ + resp = urllib.request.urlopen( url ) + buf = io.BytesIO() + buf.write( resp.read() ) + buf.seek( 0 ) + mime_type = mimetypes.guess_type( url )[0] + if not mime_type: + # FUDGE! send_file() requires a MIME type, so we take a guess and hope the browser + # can figure it out if we're wrong :-/ + mime_type = "image/png" + return send_file( buf, mimetype=mime_type ) + else: + path = path.replace( "\\", "/" ) # nb: for Windows :-/ + return send_from_directory( self.base_dir, path ) + + @staticmethod + def is_remote_path( path ): + """Check if a path is referring to a remote server.""" + return path.startswith( ("http://","https://") ) + +# --------------------------------------------------------------------- + +@app.route( "/user/" ) +def get_user_file( path ): + """Get a static file.""" + dname = app.config.get( "USER_FILES_DIR" ) + if not dname: + abort( 404 ) + return FileServer( dname ).serve_file( path ) # --------------------------------------------------------------------- diff --git a/vasl_templates/webapp/static/snippets.js b/vasl_templates/webapp/static/snippets.js index 23d2edb..c12f656 100644 --- a/vasl_templates/webapp/static/snippets.js +++ b/vasl_templates/webapp/static/snippets.js @@ -283,6 +283,9 @@ function make_snippet( $btn, params, extra_params, show_date_warnings ) return "[error: can't process template'" ; } + // fixup any user file URL's + snippet = snippet.replace( "{{USER_FILES}}", APP_URL_BASE + "/user" ) ; + return snippet ; } diff --git a/vasl_templates/webapp/tests/fixtures/user-files/amp=& ; plus=+.txt b/vasl_templates/webapp/tests/fixtures/user-files/amp=& ; plus=+.txt new file mode 100644 index 0000000..15ce1ca --- /dev/null +++ b/vasl_templates/webapp/tests/fixtures/user-files/amp=& ; plus=+.txt @@ -0,0 +1 @@ +special chars diff --git a/vasl_templates/webapp/tests/fixtures/user-files/hello.txt b/vasl_templates/webapp/tests/fixtures/user-files/hello.txt new file mode 100644 index 0000000..2bd9a94 --- /dev/null +++ b/vasl_templates/webapp/tests/fixtures/user-files/hello.txt @@ -0,0 +1 @@ +Yo, wassup! diff --git a/vasl_templates/webapp/tests/fixtures/user-files/subdir/placeholder.png b/vasl_templates/webapp/tests/fixtures/user-files/subdir/placeholder.png new file mode 100644 index 0000000000000000000000000000000000000000..62b26786bb3c169f871ad6e5fa6f6712e0ee5a5f GIT binary patch literal 1339 zcmXxkeN>WH90%}6NRUTB)TfC;_T)=Fvm$V~sWiuHVlIR7nC#J_fLAldhyTX}>WmD9N(a2|-D5`$=ZYmNb=wrc(I;0I z0KhCwWKE24-9rO(4m)_f-w6iPc}M3NPeF_&SaP)_k~9^~#P zUqlgI=%mtwQVnxH$}?17BVyi2TmqZNy*g>)E7BZUmiwn+=9R>!ut@NHmmaeUf`~+R zS=)gWnZ+#t}>q1QNq3Pmo0F zL3o`MVRiGGYbEjqV9e0rW+Zt;fPTazI1#B~4(juljTK(-34y>^Vk10=tYak`Q))FA zQ@qA$1)M?;%0|S8>B#%q9ON#5x|@-5rbAzB4k8Icx*HH5mc!6i7&KeJ?#@KYS%C)O zj<7xvj3}$GH#Ihrud+`rS-g0sEve34T2c~I(Q~h-y}f;^r>AGZwTO~(#7qbBk|}wd z3Y)U}oI9|0-@fUycDp@{gdGiZNc_U%CMPFz7cW}$j-GS5uP^4!9_lIBn7z8ItLy3V zL#wvr=Ei)<;cT6h-L7h0@%|X8M!*^DI?NzX9Qw0j6SN!dq-Pwmny~)&ex2tng1RHC zVw6ZKcYcdLp6~58em6=8f$N zz|^KOz7@!@{Gt1I^E)v4f?JiIV3Y@*n1CFFYnaWJGQGwzn#ad<_!|R4BTci2%PTB! zIrFH*pcgwVTmmM@KbQ?hivyW_D|&^5UZyOo-S1RD_?r2Dgrqq0%KPY5% z)V6_Es!Y0JmbCa8a@m03NSA(s&Ag%)b4{uJ)}iaoim0+^#K|F}|tc)zF9oojHca