-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy path__init__.py
153 lines (92 loc) · 3.3 KB
/
__init__.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# Jaziel Lopez <juan.jaziel@gmail.com>
# Software Developer
# http://jlopez.mx
import argparse
import os
import glob
import subprocess
FROM_EXTENSION = "pyc"
TO_EXTENSION = "py"
parser = argparse.ArgumentParser(
description='Decompile .pyc files recursively. '
'It takes a directory in --path argument to scan for .pyc files to uncompile')
parser.add_argument('-p', '--path', dest='path',
default=os.path.abspath("."),
help="Specify root directory to scan pyc files from")
class uncompyle6:
def __init__(self):
pass
@staticmethod
def check_uncompyle():
try:
subprocess.call(["uncompyle6", "--version"])
except OSError as e:
print("[ERROR] - uncompyle6 or any of its dependencies are not installed")
print("[ERROR] - refer to https://pypi.org/project/uncompyle6/ to install uncompyle6 and try again")
exit(e.errno)
@staticmethod
def swap_extension(compiled):
"""
Swap file extension from .pyc to .py
:param compiled:
:return:
"""
metadata = os.path.splitext(compiled)
return "{0}.{1}".format(metadata[0], TO_EXTENSION)
def normalize_path(self, paths):
"""
Normalize paths
:param paths:
:return:
"""
clean = [] # hold clean list of normalized matching paths
prefix = os.path.commonprefix(paths)
for i in paths:
source = i
base = self.swap_extension(i.replace(prefix, ""))
clean.append({"source": source, "dirname": os.path.dirname(base), "name": os.path.basename(base)})
return clean
@staticmethod
def search_pyc(use_directory):
"""
Search .pyc files
:param use_directory:
:return:
"""
return glob.glob("/".join([use_directory, "*." + FROM_EXTENSION]))
@staticmethod
def setup_directories(directories, parent):
"""
Mimic file organization
:param directories:
:param parent:
:return:
"""
for i in directories:
if i["dirname"]:
directory_name = os.path.join(parent, i["dirname"])
if os.path.exists(directory_name):
continue
os.mkdir(directory_name)
print("[INFO] - Done creating %s directory" % directory_name)
@staticmethod
def uncompyle(locations, parent):
for i in locations:
uncompyle_source = i["source"]
uncompyle_to = os.path.join(parent, i["dirname"], i["name"])
subprocess.call(["uncompyle6", "-o", uncompyle_to, uncompyle_source])
print("[INFO] - {0} decompiled at {1}".format(uncompyle_source, uncompyle_to))
if __name__ == "__main__":
matches = []
args = parser.parse_args()
path = args.path
cwd = os.path.abspath(".")
uncompyler = uncompyle6()
uncompyler.check_uncompyle()
for root, dirs, files in os.walk(path):
for result in uncompyler.search_pyc(root):
matches.append(result)
normalized = uncompyler.normalize_path(matches)
uncompyler.setup_directories(normalized, cwd)
uncompyler.uncompyle(normalized, cwd)
exit(0)