1+ import argparse
2+ import base64
3+ import os
4+ from flask import Flask , request , make_response
5+
6+ app = Flask (__name__ )
7+
8+ parser = argparse .ArgumentParser ()
9+ parser .add_argument ("--ssl" , action = "store_true" )
10+ parser .add_argument ("--auth-token" )
11+ parser .add_argument ("--port" , default = "4902" )
12+ parser .add_argument ("--upload-dir" , default = (os .path .join (os .getenv ("HOME" ), "Uploads" )))
13+ args , _ = parser .parse_known_args ()
14+
15+ @app .route ("/upload" , methods = ["POST" ])
16+ def upload ():
17+ if args .auth_token != "" :
18+ if "Authorization" in request .headers and request .headers ["Authorization" ].startswith ("Basic " ):
19+ try :
20+ user_pass_raw = base64 .b64decode (request .headers ["Authorization" ].replace ("Basic " , "" ))
21+ except :
22+ return make_response (('Failed to decode auth 1' , 403 ))
23+ else :
24+ try :
25+ user_pass_as_text = user_pass_raw .decode ("ISO-8859-1" )
26+ except :
27+ return make_response (('Failed to decode auth 2' , 403 ))
28+ else :
29+ if user_pass_as_text != args .auth_token :
30+ return make_response (('Access Denied!' , 403 ))
31+ else :
32+ return make_response (('Authorization Header missing or invalid' , 403 ))
33+
34+ file = request .files ["file" ]
35+ current_chunk = int (request .form ["dzchunkindex" ])
36+ if args .upload_dir :
37+ save_path = os .path .join (args .upload_dir , escapeFilename (file .filename ))
38+ if os .path .exists (save_path ):
39+ if current_chunk == 0 :
40+ return make_response (('File already exists' , 400 ))
41+ save_path = os .path .join (args .upload_dir , "." + escapeFilename (file .filename ) + ".uploading" )
42+ if os .path .exists (save_path ) and current_chunk == 0 :
43+ os .remove (save_path )
44+ else :
45+ return make_response (("Couldn't find upload path" , 500 ))
46+
47+ if current_chunk == 0 :
48+ syssize = os .statvfs (args .upload_dir )
49+ space = syssize .f_bsize * syssize .f_bavail
50+ if space - int (request .form ["dztotalfilesize" ]) < 0 :
51+ return make_response (('No Space available' , 400 ))
52+ try :
53+ with open (save_path , "ab" ) as f :
54+ f .seek (int (request .form ["dzchunkbyteoffset" ]))
55+ f .write (file .stream .read ())
56+ except OSError :
57+ return make_response (("Couldn't write the file to disk" , 500 ))
58+ else :
59+ total_chunks = int (request .form ["dztotalchunkcount" ])
60+ if current_chunk + 1 == total_chunks :
61+ if os .path .getsize (save_path ) != int (request .form ["dztotalfilesize" ]):
62+ os .remove (save_path )
63+ return make_response (('Size mismatch' , 500 ))
64+ os .rename (save_path , os .path .join (args .upload_dir , escapeFilename (file .filename )))
65+ return make_response (('uploaded Chunk' , 200 ))
66+
67+ def escapeFilename (filename ):
68+ keepcharacters = (' ' , '.' , '_' , '-' )
69+ return "" .join ((c for c in filename if c .isalnum () or c in keepcharacters )).rstrip ()
70+
71+ if __name__ == "__main__" :
72+ app .run (host = "0.0.0.0" , port = args .port , ssl_context = "adhoc" if args .ssl else None )
0 commit comments