10
10
from cgi import parse_qs
11
11
import copy
12
12
from distutils .version import StrictVersion
13
+ import http .client
13
14
from http .server import BaseHTTPRequestHandler
14
15
from http .server import HTTPServer
15
16
import hashlib
54
55
UPDATE_LOC = os .path .join (CWD , 'updates' )
55
56
THEME_LOC = os .path .join (CWD , 'themes' )
56
57
DEBUG_LOC = os .path .join (CWD , 'debug' )
58
+ PKG_LOC = os .path .join (CWD , 'pkgs' )
57
59
SETTINGS = None
58
60
MENU_OPEN = False
59
61
DEBUG_VAR = {}
@@ -209,6 +211,25 @@ def api_edit_settings(self, data):
209
211
# TODO
210
212
pass
211
213
214
+ def api_pkg_list (self ):
215
+ try :
216
+ pkgs = os .listdir (PKG_LOC )
217
+ for entry in pkgs :
218
+ print (entry )
219
+ if not os .path .isfile (os .path .join (PKG_LOC , entry )) or entry == 'PUT PKGS HERE' :
220
+ pkgs .remove (entry )
221
+ pkgs .sort ()
222
+ if len (pkgs ) == 0 :
223
+ data = b'["No PKGs Found"]'
224
+ else :
225
+ data = bytes (json .dumps (pkgs ), 'utf-8' )
226
+ except (IOError , PermissionError ):
227
+ data = b'["I/O Error on Host"]'
228
+
229
+ # TODO: Combine partial pkgs based on names
230
+
231
+ self .my_sender ('application/json' , data )
232
+
212
233
def menu (self ):
213
234
with open (os .path .join (THEME_LOC , SETTINGS ['Theme' ], 'index.html' ), 'rb' ) as buf :
214
235
data = buf .read ()
@@ -385,6 +406,8 @@ def check_ua(self):
385
406
return False
386
407
387
408
def do_GET (self ):
409
+ global DEBUG_VAR
410
+
388
411
self .path = self .path .split ('?' )[0 ]
389
412
try :
390
413
if re .match (r'^\/update\/(ps4|psp2)\/list\/[a-z]{2}\/(ps4|psp2)\-updatelist\.xml' , self .path ):
@@ -414,9 +437,15 @@ def do_GET(self):
414
437
else :
415
438
self .send_error (404 )
416
439
return
440
+ elif re .match (r'^\/api\/serverip$' , self .path ) and not SETTINGS ['Public' ]:
441
+ self .my_sender ('text/plain' , bytes (SETTINGS ['HTTP_Interface_IP' ] + ':' + str (SETTINGS ['HTTP_Port' ]) , 'utf-8' ))
442
+ return
417
443
elif re .match (r'^\/api\/settings\/view$' , self .path ) and not SETTINGS ['Public' ]:
418
444
self .api_view_settings ()
419
445
return
446
+ elif re .match (r'^\/api\/pkglist$' , self .path ):
447
+ self .api_pkg_list ()
448
+ return
420
449
else :
421
450
self .send_error (404 )
422
451
return
@@ -464,19 +493,23 @@ def do_GET(self):
464
493
elif re .match (r'^\/themes\/' , self .path ):
465
494
self .static_request ()
466
495
return
467
- elif re .match (r'\/news$' , self .path ):
496
+ elif re .match (r'^ \/news$' , self .path ):
468
497
self .news ()
469
498
return
470
- elif re .match (r'\/blank.html$' , self .path ):
499
+ elif re .match (r'^ \/blank.html$' , self .path ):
471
500
self .my_sender ('text/html' , b'<html><head><meta charset="utf-8"><title>Deus Machina</title></head><body>ZmzJCgLnJ43j2FK4NUR/EmFc7hJRN7Ub4adlqCRLfsXoswDsjyvn5vGwLj2FZdOlVLNmi/l0mjiuHgCYSZqPSndVhg6U8ODSl1+/aDxQLZE=</body></html>' )
472
501
return
473
- elif re .match (r'^\/debug\/var\/[a-zA-Z0-9\-\_\.]*$' , self .path ):
502
+ elif re .match (r'^\/debug\/var\/[a-zA-Z0-9\-\_\.]*$' , self .path ) and not SETTINGS [ 'Public' ] :
474
503
try :
475
504
result = re .search (r'^\/debug\/var\/([a-zA-Z0-9\-\_\.]*)$' , self .path )
476
505
self .my_sender ('text/plain' , DEBUG_VAR [result .group (1 )])
477
506
except KeyError :
478
507
self .send_error (404 )
479
508
return
509
+ elif re .match (r'\/debug\/varclear$' , self .path ) and not SETTINGS ['Public' ]:
510
+ DEBUG_VAR = {}
511
+ self .my_sender ('text/plain' , b'' )
512
+ return
480
513
else :
481
514
self .send_error (404 )
482
515
return
@@ -491,6 +524,9 @@ def parse_POST(self):
491
524
elif ctype == 'application/x-www-form-urlencoded' :
492
525
length = int (self .headers ['content-length' ])
493
526
postvars = parse_qs (self .rfile .read (length ), keep_blank_values = 1 )
527
+ elif ctype == 'application/json' :
528
+ length = int (self .headers ['content-length' ])
529
+ postvars = self .rfile .read (length )
494
530
else :
495
531
postvars = {}
496
532
return postvars
@@ -506,6 +542,26 @@ def do_POST(self):
506
542
self .api_edit_settings (post_data )
507
543
self .my_sender ('text/plain' , b'' )
508
544
return
545
+ elif re .match (r'^\/api\/remote\_pkg$' , self .path ) and not SETTINGS ['Public' ]:
546
+ try :
547
+ json_request = json .loads (str (post_data , 'utf-8' ).replace ('\\ "' , '"' ))
548
+ ps4_IP = json_request ['PS4_IP' ]
549
+ endpoint = json_request ['Endpoint' ]
550
+ command = bytes (json .dumps (json_request ['Command' ]), 'utf-8' )
551
+ with urllib .request .urlopen ('http://{}:12800/api/{}' .format (ps4_IP , endpoint ), data = command ) as buf :
552
+ response = buf .read ()
553
+ response = response .strip ()
554
+ self .my_sender ('application/json' , response )
555
+ return
556
+ except http .client .RemoteDisconnected :
557
+ self .my_sender ('application/json' , b'{ "status": "fail", "error": "Remote disconnect" }' )
558
+ return
559
+ except (KeyError , urllib .error .HTTPError , json .JSONDecodeError ):
560
+ self .my_sender ('application/json' , b'{ "status": "fail", "error": "Bad input" }' )
561
+ return
562
+ except IOError :
563
+ self .my_sender ('application/json' , b'{ "status": "fail", "error": "IO error" }' )
564
+ return
509
565
elif re .match (r'^\/debug\/jserrorlog$' , self .path ):
510
566
message = '--------------------------------------------------------------------------------\n '
511
567
message += ' Message: ' + post_data [b'message' ][0 ].decode ('utf-8' ) + '\n '
@@ -514,7 +570,7 @@ def do_POST(self):
514
570
message += ' URL: ' + post_data [b'url' ][0 ].decode ('utf-8' ) + '\n '
515
571
message += ' User-Agent: ' + post_data [b'useragent' ][0 ].decode ('utf-8' ) + '\n '
516
572
message += ' Stack: ' + post_data [b'stack' ][0 ].decode ('utf-8' ) + '\n '
517
- with open (os .path .join (DEBUG_LOC , 'js-error.log' ), 'a+ ' ) as buf :
573
+ with open (os .path .join (DEBUG_LOC , 'js-error.log' ), 'a' ) as buf :
518
574
buf .write (message )
519
575
self .my_sender ('text/plain' , b'' )
520
576
return
@@ -539,6 +595,20 @@ def do_POST(self):
539
595
else :
540
596
self .send_error (404 )
541
597
return
598
+ elif re .match (r'\/debug\/clearlogs$' , self .path ) and not SETTINGS ['Public' ]:
599
+ with open (os .path .join (DEBUG_LOC , 'js-error.log' ), 'w' ) as buf :
600
+ pass
601
+ with open (os .path .join (DEBUG_LOC , 'httpd.log' ), 'w' ) as buf :
602
+ pass
603
+ self .my_sender ('text/plain' , b'' )
604
+ return
605
+ elif re .match (r'\/debug\/vardump$' , self .path ) and not SETTINGS ['Public' ]:
606
+ if post_data [b'filename' ][0 ].decode ('utf-8' ) != 'js-error.log' and \
607
+ post_data [b'filename' ][0 ].decode ('utf-8' ) != 'httpd.log' :
608
+ with open (os .path .join (DEBUG_LOC , post_data [b'filename' ][0 ].decode ('utf-8' )), 'w' ) as buf :
609
+ buf .write (json .dumps (DEBUG_VAR , indent = 2 , sort_keys = True ))
610
+ self .my_sender ('text/plain' , b'' )
611
+ return
542
612
elif re .match (r'^\/debug\/var\/[a-zA-Z0-9\-\_\.]*$' , self .path ) and not SETTINGS ['Public' ]:
543
613
result = re .search (r'^\/debug\/var\/([a-zA-Z0-9\-\_\.]*)$' , self .path )
544
614
DEBUG_VAR [result .group (1 )] = self .rfile .read (int (self .headers ['Content-Length' ]))
@@ -553,7 +623,7 @@ def do_POST(self):
553
623
554
624
def log_message (self , format , * args ):
555
625
try :
556
- with open (os .path .join (DEBUG_LOC , 'httpd.log' ), 'a+ ' ) as buf :
626
+ with open (os .path .join (DEBUG_LOC , 'httpd.log' ), 'a' ) as buf :
557
627
buf .write ("%s - - [%s] %s\n " % (self .address_string (), self .log_date_time_string (), format % args ))
558
628
except (IOError , PermissionError ):
559
629
pass
0 commit comments