@@ -85,23 +85,60 @@ def list_directory(self, path):
8585 f .write (b'<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">' )
8686 f .write (("<html>\n <title>Directory listing for %s</title>\n " % displaypath ).encode ())
8787 f .write (("<body>\n <h2>Directory listing for %s</h2>\n " % displaypath ).encode ())
88+
89+ if self .B64_ENCODE_PAYLOAD :
90+ # Insert JavaScript for decoding
91+ f .write ("<script type='text/javascript'>\n {}</script>\n " .format (
92+ CorsHandler .B64_JS_TEMPLATE ).encode ('utf8' )
93+ )
94+
8895 f .write (b"<hr>\n " )
89- f .write (b"<form ENCTYPE=\" multipart/form-data\" method=\" post\" >" )
96+ if self .B64_ENCODE_PAYLOAD :
97+ f .write (b"<form ENCTYPE=\" multipart/form-data\" onsubmit=\" return encoder(2);\" >" )
98+ else :
99+ f .write (b"<form ENCTYPE=\" multipart/form-data\" method=\" post\" >" )
90100 f .write (b"<input name=\" file\" type=\" file\" />" )
91101 f .write (b"<input type=\" submit\" value=\" upload\" /></form>\n " )
92102 f .write (b"<hr>\n <ul>\n " )
103+
104+ # Generate download links
93105 for name in list :
106+
94107 fullname = os .path .join (path , name )
95108 displayname = linkname = name
109+
96110 # Append / for directories or @ for symbolic links
97111 if os .path .isdir (fullname ):
98112 displayname = name + "/"
99113 linkname = name + "/"
100114 if os .path .islink (fullname ):
101115 displayname = name + "@"
102116 # Note: a link to a directory displays with @ and links with /
103- f .write (('<li><a href="%s">%s</a>\n '
104- % (urllib .parse .quote (linkname ), html .escape (displayname ))).encode ())
117+
118+ linkname = urllib .parse .quote (linkname )
119+ displayname = html .escape (displayname )
120+
121+ # TODO: Handle insertion of JS links
122+ if self .B64_ENCODE_PAYLOAD :
123+ # implenet call to JS via onClick
124+
125+ f .write (
126+ '<li><a href="javascript:decoder(\' {}\' )">{}</a>\n ' .format (
127+ linkname ,
128+ linkname ,
129+ displayname ).encode ('utf8' )
130+ )
131+
132+ else :
133+
134+ # Non-JS links
135+ f .write (
136+ '<li><a href="{}">{}</a>\n ' .format (
137+ linkname ,
138+ displayname
139+ ).encode ('utf8' )
140+ )
141+
105142 f .write (b"</ul>\n <hr>\n </body>\n </html>\n " )
106143 length = f .tell ()
107144 f .seek (0 )
@@ -113,6 +150,9 @@ def list_directory(self, path):
113150
114151class CorsHandler (http .server .SimpleHTTPRequestHandler ):
115152
153+ B64_ENCODE_PAYLOAD = False
154+ B64_JS_TEMPLATE = None
155+
116156 @property
117157 def client_ip (self ):
118158 return self .client_address [0 ]
@@ -206,6 +246,14 @@ def send_head(self):
206246 # Adding Access-Control-Allow-Origin header
207247 self .send_header ('Access-Control-Allow-Origin' ,'*' )
208248 self .end_headers ()
249+
250+ if CorsHandler .B64_ENCODE_PAYLOAD :
251+ encoded = f .read ()
252+ # TODO: Make iterations configurable
253+ for i in range (0 ,2 ):
254+ encoded = b64encode (encoded )
255+ return BytesIO (encoded )
256+
209257 return f
210258 except :
211259 f .close ()
@@ -298,12 +346,15 @@ def deal_post_data(self):
298346 remainbytes -= len (line )
299347 line = self .rfile .readline ()
300348 remainbytes -= len (line )
349+
350+ # Prepare the output file
301351 try :
302352 out = open (fn , 'wb' )
303353 except IOError :
304354 self .log_error ("Cannot write to target directory. (Permissions Problem)" )
305355 return (False , "Can't create file to write, do you have permission to write?" )
306-
356+
357+ # Read file content
307358 preline = self .rfile .readline ()
308359 remainbytes -= len (preline )
309360 while remainbytes > 0 :
@@ -315,6 +366,20 @@ def deal_post_data(self):
315366 preline = preline [0 :- 1 ]
316367 out .write (preline )
317368 out .close ()
369+
370+ # TODO: Handle decoding of uploads
371+ if CorsHandler .B64_ENCODE_PAYLOAD :
372+
373+ # Read in the file content
374+ with open (fn ,'rb' ) as f : data = f .read ()
375+
376+ # Decode the data
377+ for i in range (0 ,2 ):
378+ data = b64decode (data )
379+
380+ # Open and write the decoded content
381+ with open (fn ,'wb' ) as f : f .write (data )
382+
318383 self .log_message ("File '%s' uploaded by '%s:%d'" ,fn , self .client_ip , self .client_port )
319384 return (True , "File '%s' upload success!" % fn )
320385 else :
@@ -333,7 +398,7 @@ def do_HEAD(self):
333398
334399 def do_AUTHHEAD (self ):
335400 self .send_response (401 )
336- self .send_header ('WWW-Authenticate' , 'Basic realm="simple_https_server ", charset="UTF-8"' )
401+ self .send_header ('WWW-Authenticate' , 'Basic realm="internal ", charset="UTF-8"' )
337402 self .send_header ('Content-Type' , 'text/html' )
338403 self .end_headers ()
339404
@@ -362,7 +427,21 @@ def do_basic_POST(self):
362427 self .wfile .write (bytes ('Not authenticated' ,'utf-8' ))
363428
364429def run_server (interface , port , keyfile , certfile ,
365- webroot = None , enable_uploads = False , * args , ** kwargs ):
430+ webroot = None , enable_uploads = False , enable_b64 = False ,
431+ * args , ** kwargs ):
432+
433+ # ============================
434+ # CONFIGURE BASE64 OBFUSCATION
435+ # ============================
436+
437+ CorsHandler .B64_ENCODE_PAYLOAD = enable_b64
438+
439+ if enable_b64 :
440+
441+ # Get the JavaScript template
442+ with open (str (Path (__file__ ).resolve ().parent .absolute ()) + \
443+ '/templates/b64_obfuscation.js' ,'r' ) as infile :
444+ CorsHandler .B64_JS_TEMPLATE = infile .read ()
366445
367446 webroot = webroot or '.'
368447
@@ -500,6 +579,16 @@ def generate_certificate(certfile, keyfile):
500579 auth_arg_group .add_argument ('--basic-password' ,'-bp' ,
501580 help = 'Password for basic authentication' )
502581
582+ # obfuscation
583+ obf_group = parser .add_argument_group ('Obfuscation' ,
584+ '''Configure the server to implement file obfuscation.
585+ JavaScript is injected into the browser to handle
586+ obfuscation at the client.
587+ ''' )
588+ obf_group .add_argument ('--enable-b64' ,
589+ help = 'Enable double base 64 obfuscation of files.' ,
590+ action = 'store_true' )
591+
503592 args = parser .parse_args ()
504593
505594 # handle basic auth credentials
0 commit comments