from threading import current_thread

from jsbeautifier.javascript.beautifier import remove_redundant_indentation
from pyparser.oleparser import OleParser
from pyparser.hwp_parser import HwpParser
from scan.init_scan import init_hwp5_scan
from scan.bindata_scanner import BinData_Scanner
from scan.jscript_scanner import JS_Scanner
from scan.paratext_scanner import ParaText_Scanner
import zipfile
import os
import sys
import platform
from common.errors import *
from utils.dumphex import print_hexdump

js_scanner = None
bindata_scanner = None
paratext_scanner = None
_platform = None
binary_info = {
    "type": "",
    "p": None
}

def cmd_handler(cmdline):
    global binary_info
    global js_scanner
    global bindata_scanner
    global paratext_scanner
    global _platform

    ty = binary_info["type"]
    parser = binary_info["p"]
    
    s_cmd = cmdline.split(" ")
    cmd = s_cmd[0]
    arg = s_cmd[1:]

    if "windows" in _platform:
        os.system('cls')
    else:
        os.system('clear')

    print(">> "+cmdline)
    if cmd == "help":
        
        print("> tree")
        print("  Print the structure of target Binary")

        print("> dump [binary_name] [directory]")
        print("  Dump OLE or Zipped Binary at specific direcotry (default is current direcotry)")
        
        print("> show-hex [binary_name]")
        print("  Print hexcidecimal view of specific OLE or Zipped Binary")
        
        print("> scan")
        print("  re-scanning the target file")

        print("> exit")
        print("  quit command liner")
        return 1

    elif cmd == "clear":
        if "windows" in _platform:
            os.system('cls')
        else:
            os.system('clear')
        return 0

    elif cmd == "tree":
        if ty == "hwp":
            parser.ole_container.print_dir_entry_all()
        else:
            for file in parser.filelist:
                print(file.filename)
        return 0

    elif cmd == "dump":
        if len(arg) > 1:
            binary_name, target_dir = arg[0], arg[1]
        else:
            binary_name, target_dir = arg[0], None
        
        if not target_dir:
            target_dir = os.getcwd()
        
        if ty == "hwp":
            stream = parser.ole_container.get_dir_entry_by_name(binary_name).get_decompressed_stream()
        else:
            targ = ""
            for file in parser.filelist:
                fname = file.filename.split("/")[-1]
                if fname == binary_name:
                    targ = file.filename
                    break
            if not targ:
                print("no file exist")
                return 0
            stream = parser.read(targ)
        with open(target_dir+"/"+binary_name, "wb") as f:
            f.write(stream)

        print("dump succeed..")
        return 1

    elif cmd == "show-hex":
        binary_name = arg[0]
        if ty == "hwp":
            stream = parser.ole_container.get_dir_entry_by_name(binary_name).get_decompressed_stream()
        else:
            stream = parser.read(binary_name)
        print_hexdump(stream)
        return 1

    elif cmd == "scan":
        if ty == "hwp":
            bindata_scanner.scan()
            js_scanner.scan()
        else:
            paratext_scanner.scan()
        return 1
    
    elif cmd == "exit":
        return -1
    else:
        print("unknown command..")
        return 0
    print()

class HWPScanner:
    def __init__(self) -> None:
        self.__platform__ = platform.platform()
        self.hwpx_flag = False
        self.ole_parser = OleParser()
        self.hwp_parser = None
        pass

    def parse_hwpdoc(self, file_name):
        self.file_name = file_name
        self.ole_parser.read_ole_binary(file_name)
        try:
            self.ole_parser.parse()
            self.hwp_parser = HwpParser(self.ole_parser)
            self.hwp_parser.parse()
            if not init_hwp5_scan(self.hwp_parser.hwp_header):
                exit(-1)
        except:
            self.hwpx_docs = zipfile.ZipFile(self.file_name, "r")
            self.hwpx_flag = True 
        pass
    '''
    def parse_hwpdoc(self):
        try:
            self.hwp_parser = HwpParser(self.ole_parser)
            self.hwp_parser.parse()
            if not init_hwp5_scan(self.hwp_parser.hwp_header):
                exit(-1)
            
        except:
            self.hwpx_docs = zipfile.ZipFile(self.file_name, "r")
            self.hwpx_flag = True            
        pass
    '''
    def setup_scanner(self):
        if not self.hwpx_flag:
            self.js_scanner = JS_Scanner(self.hwp_parser)
            self.bindata_scanner = BinData_Scanner(self.hwp_parser)
        else:
            self.paratext_scanner = ParaText_Scanner(self.hwpx_docs)

    def get_file_structure(self):
        strt = {}
        if not self.hwpx_flag:
            self.ole_parser.get_dir_entry_all(strt, entry_id=0, depth=0)
        else:

            for _file in self.hwpx_docs.filelist:
                _path = os.path.split( _file.filename)
                if _path[0] not in strt:
                    # root
                    if _path[0]:
                        strt[_path[0]] = {}
                    else:
                        strt[_path[1]] = _file.file_size
                        continue
                cur_strt = strt[_path[0]]
                for path in _path:
                    if path not in strt:
                        if path == _path[-1]:
                            cur_strt[path] = _file.file_size
                        else:
                            cur_strt[path] = {}
                            cur_strt = cur_strt[path]
                    else:
                        cur_strt = strt[path]
                    
        return strt

    def scan(self):
        scan_result = ""
        if not self.hwpx_flag:
            scan_result += self.js_scanner.scan()
            scan_result += self.bindata_scanner.scan()
        else:
            scan_result += self.paratext_scanner.scan()
        return scan_result
[((41, 8, 41, 24), 'os.system', 'os.system', ({(41, 18, 41, 23): '"""cls"""'}, {}), "('cls')", False, 'import os\n'), ((43, 8, 43, 26), 'os.system', 'os.system', ({(43, 18, 43, 25): '"""clear"""'}, {}), "('clear')", False, 'import os\n'), ((133, 28, 133, 47), 'platform.platform', 'platform.platform', ({}, {}), '()', False, 'import platform\n'), ((135, 26, 135, 37), 'pyparser.oleparser.OleParser', 'OleParser', ({}, {}), '()', False, 'from pyparser.oleparser import OleParser\n'), ((144, 30, 144, 56), 'pyparser.hwp_parser.HwpParser', 'HwpParser', ({(144, 40, 144, 55): 'self.ole_parser'}, {}), '(self.ole_parser)', False, 'from pyparser.hwp_parser import HwpParser\n'), ((167, 30, 167, 57), 'scan.jscript_scanner.JS_Scanner', 'JS_Scanner', ({(167, 41, 167, 56): 'self.hwp_parser'}, {}), '(self.hwp_parser)', False, 'from scan.jscript_scanner import JS_Scanner\n'), ((168, 35, 168, 67), 'scan.bindata_scanner.BinData_Scanner', 'BinData_Scanner', ({(168, 51, 168, 66): 'self.hwp_parser'}, {}), '(self.hwp_parser)', False, 'from scan.bindata_scanner import BinData_Scanner\n'), ((170, 36, 170, 68), 'scan.paratext_scanner.ParaText_Scanner', 'ParaText_Scanner', ({(170, 53, 170, 67): 'self.hwpx_docs'}, {}), '(self.hwpx_docs)', False, 'from scan.paratext_scanner import ParaText_Scanner\n'), ((66, 12, 66, 28), 'os.system', 'os.system', ({(66, 22, 66, 27): '"""cls"""'}, {}), "('cls')", False, 'import os\n'), ((68, 12, 68, 30), 'os.system', 'os.system', ({(68, 22, 68, 29): '"""clear"""'}, {}), "('clear')", False, 'import os\n'), ((146, 19, 146, 61), 'scan.init_scan.init_hwp5_scan', 'init_hwp5_scan', ({(146, 34, 146, 60): 'self.hwp_parser.hwp_header'}, {}), '(self.hwp_parser.hwp_header)', False, 'from scan.init_scan import init_hwp5_scan\n'), ((149, 29, 149, 65), 'zipfile.ZipFile', 'zipfile.ZipFile', ({(149, 45, 149, 59): 'self.file_name', (149, 61, 149, 64): '"""r"""'}, {}), "(self.file_name, 'r')", False, 'import zipfile\n'), ((179, 24, 179, 54), 'os.path.split', 'os.path.split', ({(179, 39, 179, 53): '_file.filename'}, {}), '(_file.filename)', False, 'import os\n'), ((86, 25, 86, 36), 'os.getcwd', 'os.getcwd', ({}, {}), '()', False, 'import os\n'), ((113, 8, 113, 29), 'utils.dumphex.print_hexdump', 'print_hexdump', ({(113, 22, 113, 28): 'stream'}, {}), '(stream)', False, 'from utils.dumphex import print_hexdump\n')]